Skip to content

Commit

Permalink
use v1.8.0 in cluster creation
Browse files Browse the repository at this point in the history
  • Loading branch information
HananINouman committed Mar 14, 2024
1 parent 0a31856 commit 08658e0
Show file tree
Hide file tree
Showing 7 changed files with 117 additions and 50 deletions.
23 changes: 23 additions & 0 deletions src/ajv.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,33 @@
import Ajv, { type ErrorObject } from 'ajv'

import { ETHER_TO_GWEI } from './constants'

function validDpositAmounts (data: boolean, deposits: string[]): boolean {
let sum = 0
for (let i = 0; i < deposits.length; i++) {
const amount = parseInt(deposits[i])
if (amount % ETHER_TO_GWEI !== 0 || amount > 32 * ETHER_TO_GWEI) {
return false
}
sum += amount
}
if (sum !== 32 * ETHER_TO_GWEI) {
return false
} else {
return true
}
}

export function validatePayload (
data: any,
schema: any,
): ErrorObject[] | undefined | null | boolean {
const ajv = new Ajv()
ajv.addKeyword({
keyword: 'validDpositAmounts',
validate: validDpositAmounts,
errors: true,
})
const validate = ajv.compile(schema)
const isValid = validate(data)
if (!isValid) {
Expand Down
2 changes: 1 addition & 1 deletion src/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ export const signEnrPayload = (

export const DKG_ALGORITHM = 'default'

export const CONFIG_VERSION = 'v1.7.0'
export const CONFIG_VERSION = 'v1.8.0'

export const SDK_VERSION = pjson.version

Expand Down
12 changes: 6 additions & 6 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ export class Client extends Base {
* An example of how to instantiate obol-sdk Client:
* [obolClient](https://github.com/ObolNetwork/obol-sdk-examples/blob/main/TS-Example/index.ts#L29)
*/
constructor (
constructor(
config: { baseUrl?: string, chainId?: number },
signer?: Signer,
) {
Expand All @@ -56,7 +56,7 @@ export class Client extends Base {
* An example of how to use createClusterDefinition:
* [createObolCluster](https://github.com/ObolNetwork/obol-sdk-examples/blob/main/TS-Example/index.ts)
*/
async createClusterDefinition (newCluster: ClusterPayload): Promise<string> {
async createClusterDefinition(newCluster: ClusterPayload): Promise<string> {
if (!this.signer) { throw new Error('Signer is required in createClusterDefinition') }

validatePayload(newCluster, definitionSchema)
Expand All @@ -70,8 +70,8 @@ export class Client extends Base {
timestamp: new Date().toISOString(),
threshold: Math.ceil((2 * newCluster.operators.length) / 3),
num_validators: newCluster.validators.length,
deposit_amounts: newCluster.deposit_amounts ? newCluster.deposit_amounts : ['32000000000']
}

try {
const address = await this.signer.getAddress()

Expand Down Expand Up @@ -114,7 +114,7 @@ export class Client extends Base {
* An example of how to use acceptClusterDefinition:
* [acceptClusterDefinition](https://github.com/ObolNetwork/obol-sdk-examples/blob/main/TS-Example/index.ts)
*/
async acceptClusterDefinition (
async acceptClusterDefinition(
operatorPayload: OperatorPayload,
configHash: string,
): Promise<ClusterDefintion> {
Expand Down Expand Up @@ -166,7 +166,7 @@ export class Client extends Base {
* An example of how to use getClusterDefinition:
* [getObolClusterDefinition](https://github.com/ObolNetwork/obol-sdk-examples/blob/main/TS-Example/index.ts)
*/
async getClusterDefinition (configHash: string): Promise<ClusterDefintion> {
async getClusterDefinition(configHash: string): Promise<ClusterDefintion> {
const clusterDefinition: ClusterDefintion = await this.request(
`/dv/${configHash}`,
{
Expand All @@ -185,7 +185,7 @@ export class Client extends Base {
* An example of how to use getClusterLock:
* [getObolClusterLock](https://github.com/ObolNetwork/obol-sdk-examples/blob/main/TS-Example/index.ts)
*/
async getClusterLock (configHash: string): Promise<ClusterLock> {
async getClusterLock(configHash: string): Promise<ClusterLock> {
const lock: ClusterLock = await this.request(
`/lock/configHash/${configHash}`,
{
Expand Down
8 changes: 8 additions & 0 deletions src/schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,14 @@ export const definitionSchema = {
required: ['fee_recipient_address', 'withdrawal_address'],
},
},
deposit_amounts: {
type: 'array',
items: {
type: 'string',
pattern: '^[0-9]+$',
},
validDpositAmounts: true
},
},
required: ['name', 'operators', 'validators'],
}
81 changes: 57 additions & 24 deletions test/methods.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,23 +35,23 @@ describe('Cluster Client', () => {
.mockReturnValue(Promise.resolve({ config_hash: mockConfigHash }))

const configHash =
await clientInstance.createClusterDefinition(clusterConfigV1X7)
await clientInstance.createClusterDefinition(clusterConfigV1X8)
expect(configHash).toEqual(mockConfigHash)
})

test('acceptClusterDefinition should return cluster definition', async () => {
clientInstance['request'] = jest
.fn()
.mockReturnValue(Promise.resolve(clusterLockV1X7.cluster_definition))
.mockReturnValue(Promise.resolve(clusterLockV1X8.cluster_definition))

const clusterDefinition = await clientInstance.acceptClusterDefinition(
{
enr: clusterLockV1X7.cluster_definition.operators[0].enr,
version: clusterLockV1X7.cluster_definition.version,
enr: clusterLockV1X8.cluster_definition.operators[0].enr,
version: clusterLockV1X8.cluster_definition.version,
},
clusterLockV1X7.cluster_definition.config_hash,
clusterLockV1X8.cluster_definition.config_hash,
)
expect(clusterDefinition).toEqual(clusterLockV1X7.cluster_definition)
expect(clusterDefinition).toEqual(clusterLockV1X8.cluster_definition)
})

test('createClusterDefinition should throw an error on invalid operators', async () => {
Expand All @@ -60,7 +60,7 @@ describe('Cluster Client', () => {
.mockReturnValue(Promise.resolve({ config_hash: mockConfigHash }))
try {
await clientInstance.createClusterDefinition({
...clusterConfigV1X7,
...clusterConfigV1X8,
operators: [],
})
} catch (error: any) {
Expand All @@ -70,9 +70,38 @@ describe('Cluster Client', () => {
}
})

//cause we default to 32000000000
test('createClusterDefinition should accept a configuration without deposit_amounts', async () => {
clientInstance['request'] = jest
.fn()
.mockReturnValue(Promise.resolve({ config_hash: mockConfigHash }))

const configHash = await clientInstance.createClusterDefinition({
...clusterConfigV1X7,
})

expect(configHash).toEqual(mockConfigHash)
})

test('createClusterDefinition should throw on not valid deposit_amounts ', async () => {
clientInstance['request'] = jest
.fn()
.mockReturnValue(Promise.resolve({ config_hash: mockConfigHash }))
try {
await clientInstance.createClusterDefinition({
...clusterConfigV1X7,
deposit_amounts: ['34000000']
})
} catch (error: any) {
expect(error.message).toEqual(
"Schema compilation errors', must pass \"validDpositAmounts\" keyword validation",
)
}
})

test('validatePayload should throw an error on empty schema', async () => {
try {
validatePayload({ ...clusterConfigV1X7, operators: [] }, '')
validatePayload({ ...clusterConfigV1X8, operators: [] }, '')
} catch (error: any) {
expect(error.message).toEqual('schema must be object or boolean')
}
Expand All @@ -81,26 +110,30 @@ describe('Cluster Client', () => {
test('getClusterdefinition should return cluster definition if config hash exist', async () => {
clientInstance['request'] = jest
.fn()
.mockReturnValue(Promise.resolve(clusterLockV1X7.cluster_definition))
.mockReturnValue(Promise.resolve(clusterLockV1X8.cluster_definition))

const clusterDefinition = await clientInstance.getClusterDefinition(
clusterLockV1X7.cluster_definition.config_hash,
clusterLockV1X8.cluster_definition.config_hash,
)

expect(clusterDefinition.deposit_amounts?.length).toEqual(
clusterLockV1X8.cluster_definition.deposit_amounts.length,
)

expect(clusterDefinition.config_hash).toEqual(
clusterLockV1X7.cluster_definition.config_hash,
clusterLockV1X8.cluster_definition.config_hash,
)
})

test('getClusterLock should return lockFile if exist', async () => {
clientInstance['request'] = jest
.fn()
.mockReturnValue(Promise.resolve(clusterLockV1X7))
.mockReturnValue(Promise.resolve(clusterLockV1X8))

const clusterLock = await clientInstance.getClusterLock(
clusterLockV1X7.cluster_definition.config_hash,
clusterLockV1X8.cluster_definition.config_hash,
)
expect(clusterLock.lock_hash).toEqual(clusterLockV1X7.lock_hash)
expect(clusterLock.lock_hash).toEqual(clusterLockV1X8.lock_hash)
})

test('request method should set user agent header', async () => {
Expand Down Expand Up @@ -140,7 +173,7 @@ describe('Cluster Client without a signer', () => {

test('createClusterDefinition should throw an error without signer', async () => {
try {
await clientInstance.createClusterDefinition(clusterConfigV1X7)
await clientInstance.createClusterDefinition(clusterConfigV1X8)
} catch (err: any) {
expect(err.message).toEqual('Signer is required in createClusterDefinition')
}
Expand All @@ -150,10 +183,10 @@ describe('Cluster Client without a signer', () => {
try {
await clientInstance.acceptClusterDefinition(
{
enr: clusterLockV1X7.cluster_definition.operators[0].enr,
version: clusterLockV1X7.cluster_definition.version,
enr: clusterLockV1X8.cluster_definition.operators[0].enr,
version: clusterLockV1X8.cluster_definition.version,
},
clusterLockV1X7.cluster_definition.config_hash,
clusterLockV1X8.cluster_definition.config_hash,
)
} catch (err: any) {
expect(err.message).toEqual('Signer is required in acceptClusterDefinition')
Expand All @@ -163,25 +196,25 @@ describe('Cluster Client without a signer', () => {
test('getClusterdefinition should return cluster definition if config hash exist', async () => {
clientInstance['request'] = jest
.fn()
.mockReturnValue(Promise.resolve(clusterLockV1X7.cluster_definition))
.mockReturnValue(Promise.resolve(clusterLockV1X8.cluster_definition))

const clusterDefinition = await clientInstance.getClusterDefinition(
clusterLockV1X7.cluster_definition.config_hash,
clusterLockV1X8.cluster_definition.config_hash,
)
expect(clusterDefinition.config_hash).toEqual(
clusterLockV1X7.cluster_definition.config_hash,
clusterLockV1X8.cluster_definition.config_hash,
)
})

test('getClusterLock should return lockFile if exist', async () => {
clientInstance['request'] = jest
.fn()
.mockReturnValue(Promise.resolve(clusterLockV1X7))
.mockReturnValue(Promise.resolve(clusterLockV1X8))

const clusterLock = await clientInstance.getClusterLock(
clusterLockV1X7.cluster_definition.config_hash,
clusterLockV1X8.cluster_definition.config_hash,
)
expect(clusterLock.lock_hash).toEqual(clusterLockV1X7.lock_hash)
expect(clusterLock.lock_hash).toEqual(clusterLockV1X8.lock_hash)
})

test.each([{ version: 'v1.7.0', clusterLock: clusterLockV1X7 }, { version: 'v1.8.0', clusterLock: clusterLockV1X8 }])(
Expand Down
Loading

0 comments on commit 08658e0

Please sign in to comment.