Skip to content

Commit

Permalink
feat: code cleanup and tests
Browse files Browse the repository at this point in the history
  • Loading branch information
r-marques committed Oct 18, 2023
1 parent be0d681 commit cda807a
Show file tree
Hide file tree
Showing 6 changed files with 176 additions and 127 deletions.
256 changes: 170 additions & 86 deletions integration/external/Zerodev.test.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
import { ethers } from 'ethers'
import { ZeroDevEthersProvider } from '@zerodev/sdk'
import { verifyMessage } from '@ambire/signature-validator'
import * as fs from 'fs'
import {
Account,
AssetAttributes,
AssetPrice,
DDO,
MetaData,
Nevermined,
convertEthersV6SignerToAccountSigner,
} from '../../src'
Expand All @@ -14,118 +17,199 @@ import { config } from '../config'
import { getMetadata } from '../utils'

describe('Nevermined sdk with zerodev', () => {
let zerodevProvider: ZeroDevEthersProvider<'ECDSA'>
let nevermined: Nevermined
let clientAssertion: string
let userId: string

before(async () => {
const projectId = process.env.PROJECT_ID!
const owner = ethers.Wallet.createRandom()

zerodevProvider = await ZeroDevEthersProvider.init('ECDSA', {
projectId,
owner: convertEthersV6SignerToAccountSigner(owner),
})
nevermined = await Nevermined.getInstance(config)
})

it('should produce a valid EIP-6492 signature', async () => {
const signer = zerodevProvider.getAccountSigner()
describe('Test zerodev signatures and login', () => {
let zerodevProvider: ZeroDevEthersProvider<'ECDSA'>
let clientAssertion: string

const signature = await signer.signMessageWith6492('nevermined')
const isValidSignature = await verifyMessage({
signer: await signer.getAddress(),
message: 'nevermined',
signature: signature,
provider: zerodevProvider,
before(async () => {
const projectId = process.env.PROJECT_ID!
const owner = ethers.Wallet.createRandom()

zerodevProvider = await ZeroDevEthersProvider.init('ECDSA', {
projectId,
owner: convertEthersV6SignerToAccountSigner(owner),
})
})

assert.isTrue(isValidSignature)
})
it('should produce a valid EIP-6492 signature', async () => {
const signer = zerodevProvider.getAccountSigner()

const signature = await signer.signMessageWith6492('nevermined')
const isValidSignature = await verifyMessage({
signer: await signer.getAddress(),
message: 'nevermined',
signature: signature,
provider: zerodevProvider,
})

it('should provide a valid EIP-6492 typed signature', async () => {
const domain = {
name: 'Nevermined',
version: '1',
chainId: 80001,
}
const types = {
Nevermined: [{ name: 'message', type: 'string' }],
}
const message = {
message: 'nevermined',
}

const signer = zerodevProvider.getAccountSigner()
const signature = await signer.signTypedDataWith6492({
domain,
types,
message,
primaryType: '',
assert.isTrue(isValidSignature)
})

const isValidSignature = await verifyMessage({
signer: await signer.getAddress(),
signature: signature,
typedData: {
types,
it('should provide a valid EIP-6492 typed signature', async () => {
const domain = {
name: 'Nevermined',
version: '1',
chainId: 80001,
}
const types = {
Nevermined: [{ name: 'message', type: 'string' }],
}
const message = {
message: 'nevermined',
}

const signer = zerodevProvider.getAccountSigner()
const signature = await signer.signTypedDataWith6492({
domain,
types,
message,
},
provider: zerodevProvider,
primaryType: '',
})

const isValidSignature = await verifyMessage({
signer: await signer.getAddress(),
signature: signature,
typedData: {
types,
domain,
message,
},
provider: zerodevProvider,
})

assert.isTrue(isValidSignature)
})

assert.isTrue(isValidSignature)
})
it('should generate a client assertion with a zerodev signer', async () => {
const signer = zerodevProvider.getAccountSigner()
const account = await Account.fromZeroDevSigner(signer)

it('should initialize nevermined with zerodev provider', async () => {
nevermined = await Nevermined.getInstance(config)
assert.isDefined(nevermined)
})
clientAssertion = await nevermined.utils.jwt.generateClientAssertion(account, 'hello world')
assert.isDefined(clientAssertion)

it('should generate a client assertion with a zerodev signer', async () => {
const signer = zerodevProvider.getAccountSigner()
const account = await Account.fromZeroDevSigner(signer)
const jwtPayload = decodeJwt(clientAssertion)
assert.equal(jwtPayload.iss, await signer.getAddress())
})

clientAssertion = await nevermined.utils.jwt.generateClientAssertion(account, 'hello world')
assert.isDefined(clientAssertion)
it('should login to the marketplace api', async () => {
const accessToken = await nevermined.services.marketplace.login(clientAssertion)
assert.isDefined(accessToken)

const jwtPayload = decodeJwt(clientAssertion)
assert.equal(jwtPayload.iss, await signer.getAddress())
const jwtPayload = decodeJwt(accessToken)
const signer = zerodevProvider.getAccountSigner()
assert.equal(jwtPayload.iss, await signer.getAddress())
assert.isDefined(jwtPayload.sub)
})
})

it('should login to the marketplace api', async () => {
const accessToken = await nevermined.services.marketplace.login(clientAssertion)
assert.isDefined(accessToken)
describe('E2E Asset flow with zerodev', () => {
let zerodevProviderPublisher: ZeroDevEthersProvider<'ECDSA'>
let zerodevProviderConsumer: ZeroDevEthersProvider<'ECDSA'>
let metadata: MetaData
let ddo: DDO
let agreementId: string

before(async () => {
const projectId = process.env.PROJECT_ID!
const publisher = ethers.Wallet.createRandom()
const consumer = ethers.Wallet.createRandom()

zerodevProviderPublisher = await ZeroDevEthersProvider.init('ECDSA', {
projectId,
owner: convertEthersV6SignerToAccountSigner(publisher),
})

zerodevProviderConsumer = await ZeroDevEthersProvider.init('ECDSA', {
projectId,
owner: convertEthersV6SignerToAccountSigner(consumer),
})

const signerPublisher = zerodevProviderPublisher.getAccountSigner()
const accountPublisher = await Account.fromZeroDevSigner(signerPublisher)
const clientAssertion = await nevermined.utils.jwt.generateClientAssertion(accountPublisher)

const accessToken = await nevermined.services.marketplace.login(clientAssertion)
const payload = decodeJwt(accessToken)

metadata = getMetadata()
metadata.userId = payload.sub
})

const jwtPayload = decodeJwt(accessToken)
const signer = zerodevProvider.getAccountSigner()
assert.equal(jwtPayload.iss, await signer.getAddress())
assert.isDefined(jwtPayload.sub)
it('should register an asset with a zerodev account', async () => {
const assetAttributes = AssetAttributes.getInstance({
metadata,
services: [
{
serviceType: 'access',
price: new AssetPrice(),
},
],
providers: [config.neverminedNodeAddress],
})

const signerPublisher = zerodevProviderPublisher.getAccountSigner()
const publisher = await Account.fromZeroDevSigner(signerPublisher)
ddo = await nevermined.assets.create(assetAttributes, publisher, undefined, {
zeroDevSigner: signerPublisher,
})

assert.isDefined(ddo)
assert.equal(ddo.publicKey[0].owner, await signerPublisher.getAddress())
assert.equal(ddo.proof.creator, await signerPublisher.getAddress())
})

userId = jwtPayload.sub
})
it('owner should be able to download the asset', async () => {
const signerPublisher = zerodevProviderPublisher.getAccountSigner()
const publisher = await Account.fromZeroDevSigner(signerPublisher)
const folder = '/tmp/nevermined/sdk-js'

it('should register an asset with a zerodev account', async () => {
const metadata = getMetadata()
metadata.userId = userId
const assetAttributes = AssetAttributes.getInstance({
metadata,
services: [
{
serviceType: 'access',
price: new AssetPrice(),
},
],
providers: [config.neverminedNodeAddress],
const path = (await nevermined.assets.download(ddo.id, publisher, folder, -1)) as string
const files = await new Promise<string[]>((resolve) => {
fs.readdir(path, (e, fileList) => {
resolve(fileList)
})
})

assert.deepEqual(files, ['README.md', 'ddo-example.json'])
})

it('consumer should be able to order the asset with a zerodev account', async () => {
const signerConsumer = zerodevProviderConsumer.getAccountSigner()
const consumer = await Account.fromZeroDevSigner(signerConsumer)
agreementId = await nevermined.assets.order(ddo.id, 'access', consumer, {
zeroDevSigner: signerConsumer,
})

assert.isDefined(agreementId)
})

const signer = zerodevProvider.getAccountSigner()
const account = await nevermined.accounts.fromZeroDevSigner(signer)
const ddo = await nevermined.assets.create(assetAttributes, account, undefined, {
zeroDevSigner: signer,
it('consumer should be able to access ordered assets with zerodev account', async () => {
const signerConsumer = zerodevProviderConsumer.getAccountSigner()
const consumer = await Account.fromZeroDevSigner(signerConsumer)
const folder = '/tmp/nevermined/sdk-js'

const path = (await nevermined.assets.access(
agreementId,
ddo.id,
'access',
consumer,
folder,
-1,
)) as string

const files = await new Promise<string[]>((resolve) => {
fs.readdir(path, (e, fileList) => {
resolve(fileList)
})
})

assert.deepEqual(files, ['README.md', 'ddo-example.json'])
})
assert.isDefined(ddo)
console.log(ddo)
})
})
4 changes: 2 additions & 2 deletions src/keeper/ContractHandler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ export class ContractHandler extends Instantiable {
this.logger.debug(`Deploying abi using account: ${from.getId()}`)

const signer = await this.nevermined.accounts.findSigner(from.getId())
const contract = new ethers.ContractFactory(artifact.abi, artifact.bytecode, signer as any)
const contract = new ethers.ContractFactory(artifact.abi, artifact.bytecode, signer)
const isZos = contract.interface.hasFunction('initialize')

const argument = isZos ? [] : args
Expand All @@ -144,7 +144,7 @@ export class ContractHandler extends Instantiable {
if (isZos) {
const methodSignature = ContractHandler.getSignatureOfMethod(baseContract, 'initialize', args)

const contract = baseContract.connect(signer as any)
const contract = baseContract.connect(signer)

// estimate gas
const gasLimit = await contract[methodSignature].estimateGas(...args, {
Expand Down
13 changes: 3 additions & 10 deletions src/keeper/contracts/ContractBase.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ import { ContractEvent, EventHandler, SubgraphEvent } from '../../events'
import { Instantiable, InstantiableConfig } from '../../Instantiable.abstract'
import { KeeperError } from '../../errors'
import {
Contract,
ContractTransactionReceipt,
ContractTransactionResponse,
FunctionFragment,
Expand Down Expand Up @@ -163,7 +162,7 @@ export abstract class ContractBase extends Instantiable {
})
}

return transactionResponse as any
return transactionReceipt
}

private async internalSendZeroDev(
Expand Down Expand Up @@ -230,7 +229,7 @@ export abstract class ContractBase extends Instantiable {
})
}

return transactionResponse as any
return transactionReceipt as ContractTransactionReceipt
}

public async send(
Expand All @@ -252,12 +251,6 @@ export abstract class ContractBase extends Instantiable {
)
}

if (this.config.zerodevProvider) {
const signer = this.config.zerodevProvider.getAccountSigner()
const contract = new Contract(this.address, this.contract.interface, signer as any)
return await this.internalSend(name, from, args, params, contract, params.progress)
}

if (params.signer) {
const paramsFixed = { ...params, signer: undefined }
const contract = this.contract.connect(params.signer)
Expand All @@ -268,7 +261,7 @@ export abstract class ContractBase extends Instantiable {

// get signer
const signer = await this.nevermined.accounts.findSigner(from)
const contract = this.contract.connect(signer as any)
const contract = this.contract.connect(signer)

// calculate gas cost
let { gasLimit } = params
Expand Down
5 changes: 0 additions & 5 deletions src/models/NeverminedOptions.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import { ethers } from 'ethers'
import { LogLevel } from '../utils'
import { AaveConfig } from './'
import { ZeroDevAccountSigner, ZeroDevEthersProvider } from '@zerodev/sdk'

export class NeverminedOptions {
/**
Expand Down Expand Up @@ -69,8 +68,6 @@ export class NeverminedOptions {

public accounts?: ethers.Signer[]

public zeroDevAccounts?: ZeroDevAccountSigner<'ECDSA'>[]

/**
* IPFS variables enable the resolution of DDOs (via `assets.resolve`) from CID urls
* INFO: For performance purposes, it is recommended to setup a IPFS Infura endpoint to accelerate
Expand All @@ -86,6 +83,4 @@ export class NeverminedOptions {
* Use a gas station to calculate transaction fees
*/
public gasStationUri?: string

public zerodevProvider?: ZeroDevEthersProvider<'ECDSA'>
}
Loading

0 comments on commit cda807a

Please sign in to comment.