diff --git a/.eslintignore b/.eslintignore index a8db49124..43b492eeb 100644 --- a/.eslintignore +++ b/.eslintignore @@ -3,4 +3,5 @@ dist webpack* plugins scripts -test/mocks \ No newline at end of file +test/mocks +coverage* diff --git a/.eslintrc b/.eslintrc index 68f06fd67..4b7504d3d 100644 --- a/.eslintrc +++ b/.eslintrc @@ -1,10 +1,26 @@ { + // "extends": [ + // "nevermined" + // ], "extends": [ - "nevermined" + "plugin:@typescript-eslint/recommended" + ], + "parser": "@typescript-eslint/parser", + "overrides": [ + { + "files": ["*.ts", "*.tsx"], + "parserOptions": { + "project": "./tsconfig.eslint.json" + } + } ], - "rules": { + "rules": { "@next/next/no-html-link-for-pages": "off", "@typescript-eslint/no-explicit-any": "off", + "@typescript-eslint/no-unnecessary-type-constraint": "off", + "@typescript-eslint/ban-types": "off", + "@typescript-eslint/ban-ts-comment": "off", + "@typescript-eslint/triple-slash-reference": "off", "@typescript-eslint/no-unused-vars": [ "error", { "argsIgnorePattern": "^_", @@ -12,5 +28,5 @@ "caughtErrorsIgnorePattern": "^_" }] }, - "ignorePatterns": ["test/resources/proxy-poc/*.js"] + "ignorePatterns": ["test/*.ts", "test/resources/proxy-poc/*", "test/**/*.d.ts", "test/**/*js"] } diff --git a/integration/external/Assistants.e2e.test.ts b/integration/external/Assistants.e2e.test.ts index 8e6ea02d1..32bacf3b6 100644 --- a/integration/external/Assistants.e2e.test.ts +++ b/integration/external/Assistants.e2e.test.ts @@ -1,309 +1,310 @@ -import chai, { assert } from 'chai' -import chaiAsPromised from 'chai-as-promised' -import { - AssetPrice, - ResourceAuthentication, - SubscriptionToken, - convertEthersV6SignerToAccountSigner, - makeRandomWallet, -} from '../../src' -import TestContractHandler from '../../test/keeper/TestContractHandler' -import { NVMAppEnvironments, NvmApp } from '../../src/nevermined/NvmApp' -import { NvmAppMetadata } from '../../src/ddo/NvmAppMetadata' -import { AppDeploymentStaging } from '../../src/nevermined/resources/AppNetworks' -import { ZeroDevAccountSigner, ZeroDevEthersProvider } from '@zerodev/sdk' -import { sleep } from '@opengsn/provider' - -chai.use(chaiAsPromised) - -describe('E2E flow for interacting with OpenAI proxified assistants', () => { - let nvmAppPublisher: NvmApp - let nvmAppSubscriber: NvmApp - let publisherAddress: string - let subscriberAddress: string - let subscriptionNFTAddress: string - let subscriptionDid: string - let agentDid: string - let _agreementId - let subscriptionPrice: AssetPrice - let subscriptionPriceWithFees: AssetPrice - let publisherAccountSigner: ZeroDevAccountSigner<'ECDSA'> - let subscriberAccountSigner: ZeroDevAccountSigner<'ECDSA'> - - const projectId = process.env.PROJECT_ID! - let zerodevProviderPublisher: ZeroDevEthersProvider<'ECDSA'> - let zerodevProviderSubscriber: ZeroDevEthersProvider<'ECDSA'> - - const PROXY_URL = process.env.PROXY_URL || 'https://127.0.0.1:443' - // Required because we are dealing with self signed certificates locally - process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0' - - // OpenAI assistant configuration - const ASSISTANT_ID = process.env.ASSISTANT_ID || 'asst_m3hDiBSEScF4vTyeGGJ8JI8T' - const BACKEND_URL = process.env.BACKEND_URL || 'http://localhost:3001' - const ASSISTANT_QUERY_URL = `${BACKEND_URL}/api/v1/workflows/assistant/${ASSISTANT_ID}/query` - const ASSISTANT_RUN_URL = `${BACKEND_URL}/api/v1/workflows/assistant/${ASSISTANT_ID}/run/` - const ASSISTANT_STATUS_URL = `${BACKEND_URL}/api/v1/workflows/assistant/${ASSISTANT_ID}/status` - // const SERVICE_ENDPOINT = - // process.env.SERVICE_ENDPOINT || - // `http://localhost:3001/api/v1/workflows/assistant/${ASSISTANT_ID}/query` - const OPEN_API_ENDPOINT = - process.env.OPEN_ENDPOINT || `http://localhost:3001/api/v1/rest/docs-json` - const AUTHORIZATION_TYPE = 'bearer' as ResourceAuthentication['type'] - const AUTHORIZATION_TOKEN = process.env.AUTHORIZATION_TOKEN || 'openai_authorization_token' - const AUTHORIZATION_USER = undefined - const AUTHORIZATION_PASSWORD = undefined - - const QUERY_REQUEST_DATA = - process.env.QUERY_REQUEST_DATA || - `{"did": "__DID__", "assistantId": "${ASSISTANT_ID}", "query": "Why Elvis was so important?", "threadId": "", file_ids: []}` - // const RUN_REQUEST_DATA = process.env.RUN_REQUEST_DATA || `{"did": "__DID__", "assistantId": "${ASSISTANT_ID}", "query": "Why Elvis was so important?", "threadId": "", file_ids: []}` - - let subscriptionToken: SubscriptionToken - - before(async () => { - const owner = makeRandomWallet() - const subscriber = makeRandomWallet() - - zerodevProviderPublisher = await ZeroDevEthersProvider.init('ECDSA', { - projectId, - owner: convertEthersV6SignerToAccountSigner(owner), - }) - - zerodevProviderSubscriber = await ZeroDevEthersProvider.init('ECDSA', { - projectId, - owner: convertEthersV6SignerToAccountSigner(subscriber), - }) - - const contractABI = await TestContractHandler.getABIArtifact( - `NFT1155SubscriptionUpgradeable.arbitrum-sepolia`, - './artifacts/', - ) - - subscriptionNFTAddress = contractABI.address - console.debug(`Using ERC-1155 Subscription NFT on address: ${subscriptionNFTAddress}`) - - publisherAccountSigner = zerodevProviderPublisher.getAccountSigner() - publisherAddress = await publisherAccountSigner.getAddress() - - subscriberAccountSigner = zerodevProviderSubscriber.getAccountSigner() - subscriberAddress = await subscriberAccountSigner.getAddress() - - // Using USDC token address - // WARN: Make sure the subscriber account has balance to pay the gas and the subscription - subscriptionPrice = new AssetPrice(publisherAddress, 0n).setTokenAddress( - new AppDeploymentStaging().tokenAddress, - ) - }) - - describe('PUBLISHER: As a OpenAI developer I want to monetize my assistant', () => { - it('As Publisher I want to connect my account', async () => { - nvmAppPublisher = await NvmApp.getInstance(NVMAppEnvironments.Staging, { - artifactsFolder: './artifacts', - }) - - assert.isFalse(nvmAppPublisher.isWeb3Connected()) - - console.log(`Publisher address: ${publisherAddress}`) - await nvmAppPublisher.connect(publisherAccountSigner) - - assert.isTrue(nvmAppPublisher.isWeb3Connected()) - }) - - it('I can calculate and include network fees', async () => { - subscriptionPriceWithFees = nvmAppPublisher.addNetworkFee(subscriptionPrice) - console.log(`Asset Price with fees: ${subscriptionPriceWithFees.toString()}`) - - assert.isTrue(nvmAppPublisher.isNetworkFeeIncluded(subscriptionPriceWithFees)) - }) - - it('I want to create a credits subscription', async () => { - const creditsSubscriptionMetadata = NvmAppMetadata.getCreditsSubscriptionMetadataTemplate( - 'Assistants Credits Subscription test', - 'Nevermined', - ) - - const ddo = await nvmAppPublisher.createCreditsSubscription( - creditsSubscriptionMetadata, - subscriptionPrice, - 5000n, // number of credits - ) - - assert.isDefined(ddo) - const ddoFound = await nvmAppPublisher.search.byDID(ddo.id) - assert.equal(ddo.id, ddoFound.id) - subscriptionDid = ddo.id - }) - - it('Before publishing it, I can check the assistant is okay', async function () { - console.log(`Query assistant status endpoint: ${ASSISTANT_STATUS_URL}`) - const opts: RequestInit = {} - opts.headers = { - authorization: `Bearer ${AUTHORIZATION_TOKEN}`, // Using OpenAI API Key here - } - console.log(`Options: ${JSON.stringify(opts)}`) - const result = await fetch(ASSISTANT_STATUS_URL, opts) - - assert.isTrue(result.ok) - assert.isTrue(result.status === 200) - }) - - it('I want to register an Assistant', async () => { - const agentMetadata = NvmAppMetadata.getServiceMetadataTemplate( - 'Nevermined Assistant', - 'Nevermined Corp', - [{ POST: `${ASSISTANT_QUERY_URL}` }, { POST: `${ASSISTANT_RUN_URL}(.*)` }], - [ASSISTANT_STATUS_URL], - OPEN_API_ENDPOINT, - 'RESTful', - AUTHORIZATION_TYPE, - AUTHORIZATION_TOKEN, - AUTHORIZATION_USER, - AUTHORIZATION_PASSWORD, - false, - ) - agentMetadata.additionalInformation.customData = { - ...agentMetadata.additionalInformation.customData, - agentType: 'assistant', - provider: 'openai', - assistantId: ASSISTANT_ID, - } - - const ddo = await nvmAppPublisher.registerServiceAsset( - agentMetadata, - subscriptionDid, - // We are gonna configure the agent usage costs in a dynamic manner: - // The cost in credits for every succesful query to the agent will be between 1 and 5 credits being 2 credits the default cost - 2n, // default cost in credits for every succesful query to the agent - 1n, // min amount of credits to be consumed - 5n, // max amount of credits to be consumed - ) - - assert.isDefined(ddo) - const ddoFound = await nvmAppPublisher.search.byDID(ddo.id) - assert.equal(ddo.id, ddoFound.id) - agentDid = ddo.id - - console.log(`Assistant registered with DID: ${agentDid}`) - }) - - it('I can disconnect', async () => { - await nvmAppPublisher.disconnect() - const results = await nvmAppPublisher.search.query({}) - assert.isTrue(results.totalResults.value > 0) - }) - }) - - describe('SUBSCRIBER: As a subscriber I want to order and use an Assistant', () => { - let queryResponse - let runResponse - - it('As Subscriber I want to connect too', async () => { - nvmAppSubscriber = await NvmApp.getInstance(NVMAppEnvironments.Staging, { - artifactsFolder: './artifacts', - }) - - console.log(`Subscriber address: ${subscriberAddress}`) - await nvmAppSubscriber.connect(subscriberAccountSigner) - - assert.isTrue(nvmAppSubscriber.isWeb3Connected()) - }) - - it('I want to order a subscription', async () => { - if (process.env.AGENT_DID && process.env.SUBSCRIPTION_DID) { - agentDid = process.env.AGENT_DID - subscriptionDid = process.env.SUBSCRIPTION_DID - console.log(`Using Subscription DID from ENV variable: ${subscriptionDid}`) - console.log(`Using Agent DID from ENV variable: ${agentDid}`) - } - - const orderResult = await nvmAppSubscriber.orderSubscription(subscriptionDid) - assert.isDefined(orderResult) - assert.isTrue(orderResult.success) - assert.isTrue(orderResult.agreementId.length > 0) - _agreementId = orderResult.agreementId - }) - - it('I want to get the token giving access to a remote agent', async () => { - subscriptionToken = await nvmAppSubscriber.getServiceAccessToken(agentDid) - assert.isDefined(subscriptionToken) - assert.isTrue(subscriptionToken.accessToken.length > 0) - assert.isTrue(subscriptionToken.neverminedProxyUri.length > 0) - - console.log(`Proxy Url: ${subscriptionToken.neverminedProxyUri}`) - console.log(`Token: ${subscriptionToken.accessToken}`) - }) - - it('I want make an Assistant query through the proxy', async () => { - const url = new URL(ASSISTANT_QUERY_URL) - const proxyEndpoint = `${PROXY_URL}${url.pathname}` - - const opts: RequestInit = {} - opts.method = 'POST' - const query = QUERY_REQUEST_DATA.replace('__DID__', agentDid) - opts.body = JSON.stringify(JSON.parse(query)) - opts.headers = { - // The proxy expects the `HTTP Authorization` header with the JWT - authorization: `Bearer ${subscriptionToken.accessToken}`, - 'content-type': 'application/json', - } - - console.debug(JSON.stringify(opts)) - console.log(`Proxy Endpoint: ${proxyEndpoint}`) - console.debug(JSON.stringify(opts)) - - const result = await fetch(proxyEndpoint, opts) - queryResponse = await result.text() - console.debug(` ${result.status} - ${queryResponse}`) - - assert.isTrue(result.ok) - assert.isTrue(result.status === 200 || result.status === 201) - }) - - it('I want make an Assistant query through the proxy', async () => { - if (!queryResponse) { - assert.fail('Query response is empty') - } - - console.log(`Waiting for Job to be executed. Sleeping for 10 seconds...\n\n`) - await sleep(10_000) - - const queryObj = JSON.parse(queryResponse) - const url = new URL(`${ASSISTANT_RUN_URL}${queryObj.runId}`) - const proxyEndpoint = `${PROXY_URL}${url.pathname}` - - const runBody = { - runId: queryObj.runId, - did: agentDid, - threadId: queryObj.threadId, - messageId: queryObj.messageId, - } - - const opts: RequestInit = {} - opts.method = 'POST' - opts.body = JSON.stringify(runBody) - opts.headers = { - // The proxy expects the `HTTP Authorization` header with the JWT - authorization: `Bearer ${subscriptionToken.accessToken}`, - 'content-type': 'application/json', - } - - console.debug(JSON.stringify(opts)) - console.log(`Proxy Endpoint: ${proxyEndpoint}`) - console.debug(JSON.stringify(opts)) - - const result = await fetch(proxyEndpoint, opts) - runResponse = await result.text() - console.debug(` ${result.status} - ${runResponse}`) - - assert.isTrue(result.ok) - assert.isTrue(result.status === 200 || result.status === 201) - }) - - it('I can disconnect', async () => { - await nvmAppSubscriber.disconnect() - const results = await nvmAppSubscriber.search.query({}) - assert.isTrue(results.totalResults.value > 0) - }) - }) -}) +// TODO: Enable when ZeroDev is back +// import chai, { assert } from 'chai' +// import chaiAsPromised from 'chai-as-promised' +// import { +// AssetPrice, +// ResourceAuthentication, +// SubscriptionToken, +// // convertEthersV6SignerToAccountSigner, +// makeRandomWallet, +// } from '../../src' +// import TestContractHandler from '../../test/keeper/TestContractHandler' +// import { NVMAppEnvironments, NvmApp } from '../../src/nevermined/NvmApp' +// import { NvmAppMetadata } from '../../src/ddo/NvmAppMetadata' +// import { AppDeploymentStaging } from '../../src/nevermined/resources/AppNetworks' +// import { ZeroDevAccountSigner, ZeroDevEthersProvider } from '@zerodev/sdk' +// import { sleep } from '@opengsn/provider' + +// chai.use(chaiAsPromised) + +// describe('E2E flow for interacting with OpenAI proxified assistants', () => { +// let nvmAppPublisher: NvmApp +// let nvmAppSubscriber: NvmApp +// let publisherAddress: string +// let subscriberAddress: string +// let subscriptionNFTAddress: string +// let subscriptionDid: string +// let agentDid: string +// let _agreementId +// let subscriptionPrice: AssetPrice +// let subscriptionPriceWithFees: AssetPrice +// let publisherAccountSigner: ZeroDevAccountSigner<'ECDSA'> +// let subscriberAccountSigner: ZeroDevAccountSigner<'ECDSA'> + +// const projectId = process.env.PROJECT_ID! +// let zerodevProviderPublisher: ZeroDevEthersProvider<'ECDSA'> +// let zerodevProviderSubscriber: ZeroDevEthersProvider<'ECDSA'> + +// const PROXY_URL = process.env.PROXY_URL || 'https://127.0.0.1:443' +// // Required because we are dealing with self signed certificates locally +// process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0' + +// // OpenAI assistant configuration +// const ASSISTANT_ID = process.env.ASSISTANT_ID || 'asst_m3hDiBSEScF4vTyeGGJ8JI8T' +// const BACKEND_URL = process.env.BACKEND_URL || 'http://localhost:3001' +// const ASSISTANT_QUERY_URL = `${BACKEND_URL}/api/v1/workflows/assistant/${ASSISTANT_ID}/query` +// const ASSISTANT_RUN_URL = `${BACKEND_URL}/api/v1/workflows/assistant/${ASSISTANT_ID}/run/` +// const ASSISTANT_STATUS_URL = `${BACKEND_URL}/api/v1/workflows/assistant/${ASSISTANT_ID}/status` +// // const SERVICE_ENDPOINT = +// // process.env.SERVICE_ENDPOINT || +// // `http://localhost:3001/api/v1/workflows/assistant/${ASSISTANT_ID}/query` +// const OPEN_API_ENDPOINT = +// process.env.OPEN_ENDPOINT || `http://localhost:3001/api/v1/rest/docs-json` +// const AUTHORIZATION_TYPE = 'bearer' as ResourceAuthentication['type'] +// const AUTHORIZATION_TOKEN = process.env.AUTHORIZATION_TOKEN || 'openai_authorization_token' +// const AUTHORIZATION_USER = undefined +// const AUTHORIZATION_PASSWORD = undefined + +// const QUERY_REQUEST_DATA = +// process.env.QUERY_REQUEST_DATA || +// `{"did": "__DID__", "assistantId": "${ASSISTANT_ID}", "query": "Why Elvis was so important?", "threadId": "", file_ids: []}` +// // const RUN_REQUEST_DATA = process.env.RUN_REQUEST_DATA || `{"did": "__DID__", "assistantId": "${ASSISTANT_ID}", "query": "Why Elvis was so important?", "threadId": "", file_ids: []}` + +// let subscriptionToken: SubscriptionToken + +// before(async () => { +// const owner = makeRandomWallet() +// const subscriber = makeRandomWallet() + +// zerodevProviderPublisher = await ZeroDevEthersProvider.init('ECDSA', { +// projectId, +// owner: convertEthersV6SignerToAccountSigner(owner), +// }) + +// zerodevProviderSubscriber = await ZeroDevEthersProvider.init('ECDSA', { +// projectId, +// owner: convertEthersV6SignerToAccountSigner(subscriber), +// }) + +// const contractABI = await TestContractHandler.getABIArtifact( +// `NFT1155SubscriptionUpgradeable.arbitrum-sepolia`, +// './artifacts/', +// ) + +// subscriptionNFTAddress = contractABI.address +// console.debug(`Using ERC-1155 Subscription NFT on address: ${subscriptionNFTAddress}`) + +// publisherAccountSigner = zerodevProviderPublisher.getAccountSigner() +// publisherAddress = await publisherAccountSigner.getAddress() + +// subscriberAccountSigner = zerodevProviderSubscriber.getAccountSigner() +// subscriberAddress = await subscriberAccountSigner.getAddress() + +// // Using USDC token address +// // WARN: Make sure the subscriber account has balance to pay the gas and the subscription +// subscriptionPrice = new AssetPrice(publisherAddress, 0n).setTokenAddress( +// new AppDeploymentStaging().tokenAddress, +// ) +// }) + +// describe('PUBLISHER: As a OpenAI developer I want to monetize my assistant', () => { +// it('As Publisher I want to connect my account', async () => { +// nvmAppPublisher = await NvmApp.getInstance(NVMAppEnvironments.Staging, { +// artifactsFolder: './artifacts', +// }) + +// assert.isFalse(nvmAppPublisher.isWeb3Connected()) + +// console.log(`Publisher address: ${publisherAddress}`) +// await nvmAppPublisher.connect(publisherAccountSigner) + +// assert.isTrue(nvmAppPublisher.isWeb3Connected()) +// }) + +// it('I can calculate and include network fees', async () => { +// subscriptionPriceWithFees = nvmAppPublisher.addNetworkFee(subscriptionPrice) +// console.log(`Asset Price with fees: ${subscriptionPriceWithFees.toString()}`) + +// assert.isTrue(nvmAppPublisher.isNetworkFeeIncluded(subscriptionPriceWithFees)) +// }) + +// it('I want to create a credits subscription', async () => { +// const creditsSubscriptionMetadata = NvmAppMetadata.getCreditsSubscriptionMetadataTemplate( +// 'Assistants Credits Subscription test', +// 'Nevermined', +// ) + +// const ddo = await nvmAppPublisher.createCreditsSubscription( +// creditsSubscriptionMetadata, +// subscriptionPrice, +// 5000n, // number of credits +// ) + +// assert.isDefined(ddo) +// const ddoFound = await nvmAppPublisher.search.byDID(ddo.id) +// assert.equal(ddo.id, ddoFound.id) +// subscriptionDid = ddo.id +// }) + +// it('Before publishing it, I can check the assistant is okay', async function () { +// console.log(`Query assistant status endpoint: ${ASSISTANT_STATUS_URL}`) +// const opts: RequestInit = {} +// opts.headers = { +// authorization: `Bearer ${AUTHORIZATION_TOKEN}`, // Using OpenAI API Key here +// } +// console.log(`Options: ${JSON.stringify(opts)}`) +// const result = await fetch(ASSISTANT_STATUS_URL, opts) + +// assert.isTrue(result.ok) +// assert.isTrue(result.status === 200) +// }) + +// it('I want to register an Assistant', async () => { +// const agentMetadata = NvmAppMetadata.getServiceMetadataTemplate( +// 'Nevermined Assistant', +// 'Nevermined Corp', +// [{ POST: `${ASSISTANT_QUERY_URL}` }, { POST: `${ASSISTANT_RUN_URL}(.*)` }], +// [ASSISTANT_STATUS_URL], +// OPEN_API_ENDPOINT, +// 'RESTful', +// AUTHORIZATION_TYPE, +// AUTHORIZATION_TOKEN, +// AUTHORIZATION_USER, +// AUTHORIZATION_PASSWORD, +// false, +// ) +// agentMetadata.additionalInformation.customData = { +// ...agentMetadata.additionalInformation.customData, +// agentType: 'assistant', +// provider: 'openai', +// assistantId: ASSISTANT_ID, +// } + +// const ddo = await nvmAppPublisher.registerServiceAsset( +// agentMetadata, +// subscriptionDid, +// // We are gonna configure the agent usage costs in a dynamic manner: +// // The cost in credits for every succesful query to the agent will be between 1 and 5 credits being 2 credits the default cost +// 2n, // default cost in credits for every succesful query to the agent +// 1n, // min amount of credits to be consumed +// 5n, // max amount of credits to be consumed +// ) + +// assert.isDefined(ddo) +// const ddoFound = await nvmAppPublisher.search.byDID(ddo.id) +// assert.equal(ddo.id, ddoFound.id) +// agentDid = ddo.id + +// console.log(`Assistant registered with DID: ${agentDid}`) +// }) + +// it('I can disconnect', async () => { +// await nvmAppPublisher.disconnect() +// const results = await nvmAppPublisher.search.query({}) +// assert.isTrue(results.totalResults.value > 0) +// }) +// }) + +// describe('SUBSCRIBER: As a subscriber I want to order and use an Assistant', () => { +// let queryResponse +// let runResponse + +// it('As Subscriber I want to connect too', async () => { +// nvmAppSubscriber = await NvmApp.getInstance(NVMAppEnvironments.Staging, { +// artifactsFolder: './artifacts', +// }) + +// console.log(`Subscriber address: ${subscriberAddress}`) +// await nvmAppSubscriber.connect(subscriberAccountSigner) + +// assert.isTrue(nvmAppSubscriber.isWeb3Connected()) +// }) + +// it('I want to order a subscription', async () => { +// if (process.env.AGENT_DID && process.env.SUBSCRIPTION_DID) { +// agentDid = process.env.AGENT_DID +// subscriptionDid = process.env.SUBSCRIPTION_DID +// console.log(`Using Subscription DID from ENV variable: ${subscriptionDid}`) +// console.log(`Using Agent DID from ENV variable: ${agentDid}`) +// } + +// const orderResult = await nvmAppSubscriber.orderSubscription(subscriptionDid) +// assert.isDefined(orderResult) +// assert.isTrue(orderResult.success) +// assert.isTrue(orderResult.agreementId.length > 0) +// _agreementId = orderResult.agreementId +// }) + +// it('I want to get the token giving access to a remote agent', async () => { +// subscriptionToken = await nvmAppSubscriber.getServiceAccessToken(agentDid) +// assert.isDefined(subscriptionToken) +// assert.isTrue(subscriptionToken.accessToken.length > 0) +// assert.isTrue(subscriptionToken.neverminedProxyUri.length > 0) + +// console.log(`Proxy Url: ${subscriptionToken.neverminedProxyUri}`) +// console.log(`Token: ${subscriptionToken.accessToken}`) +// }) + +// it('I want make an Assistant query through the proxy', async () => { +// const url = new URL(ASSISTANT_QUERY_URL) +// const proxyEndpoint = `${PROXY_URL}${url.pathname}` + +// const opts: RequestInit = {} +// opts.method = 'POST' +// const query = QUERY_REQUEST_DATA.replace('__DID__', agentDid) +// opts.body = JSON.stringify(JSON.parse(query)) +// opts.headers = { +// // The proxy expects the `HTTP Authorization` header with the JWT +// authorization: `Bearer ${subscriptionToken.accessToken}`, +// 'content-type': 'application/json', +// } + +// console.debug(JSON.stringify(opts)) +// console.log(`Proxy Endpoint: ${proxyEndpoint}`) +// console.debug(JSON.stringify(opts)) + +// const result = await fetch(proxyEndpoint, opts) +// queryResponse = await result.text() +// console.debug(` ${result.status} - ${queryResponse}`) + +// assert.isTrue(result.ok) +// assert.isTrue(result.status === 200 || result.status === 201) +// }) + +// it('I want make an Assistant query through the proxy', async () => { +// if (!queryResponse) { +// assert.fail('Query response is empty') +// } + +// console.log(`Waiting for Job to be executed. Sleeping for 10 seconds...\n\n`) +// await sleep(10_000) + +// const queryObj = JSON.parse(queryResponse) +// const url = new URL(`${ASSISTANT_RUN_URL}${queryObj.runId}`) +// const proxyEndpoint = `${PROXY_URL}${url.pathname}` + +// const runBody = { +// runId: queryObj.runId, +// did: agentDid, +// threadId: queryObj.threadId, +// messageId: queryObj.messageId, +// } + +// const opts: RequestInit = {} +// opts.method = 'POST' +// opts.body = JSON.stringify(runBody) +// opts.headers = { +// // The proxy expects the `HTTP Authorization` header with the JWT +// authorization: `Bearer ${subscriptionToken.accessToken}`, +// 'content-type': 'application/json', +// } + +// console.debug(JSON.stringify(opts)) +// console.log(`Proxy Endpoint: ${proxyEndpoint}`) +// console.debug(JSON.stringify(opts)) + +// const result = await fetch(proxyEndpoint, opts) +// runResponse = await result.text() +// console.debug(` ${result.status} - ${runResponse}`) + +// assert.isTrue(result.ok) +// assert.isTrue(result.status === 200 || result.status === 201) +// }) + +// it('I can disconnect', async () => { +// await nvmAppSubscriber.disconnect() +// const results = await nvmAppSubscriber.search.query({}) +// assert.isTrue(results.totalResults.value > 0) +// }) +// }) +// }) diff --git a/integration/external/Datasets.e2e.test.ts b/integration/external/Datasets.e2e.test.ts index 2f5627d51..843047884 100644 --- a/integration/external/Datasets.e2e.test.ts +++ b/integration/external/Datasets.e2e.test.ts @@ -21,7 +21,7 @@ import { RoyaltyKind, NFT721Api, SubscriptionNFTApi, - getAddress, + getChecksumAddress, } from '../../src/nevermined' describe('Gate-keeping of Dataset using NFT ERC-721 End-to-End', () => { @@ -235,7 +235,7 @@ describe('Gate-keeping of Dataset using NFT ERC-721 End-to-End', () => { }) it('I am ordering the subscription NFT', async () => { - await subscriber.requestTokens(subscriptionPrice / scale) + await nevermined.accounts.requestTokens(subscriber, subscriptionPrice / scale) const subscriberBalanceBefore = await token.balanceOf(subscriber.getId()) assert.isTrue(subscriberBalanceBefore == initialBalances.subscriber + subscriptionPrice) @@ -307,7 +307,7 @@ describe('Gate-keeping of Dataset using NFT ERC-721 End-to-End', () => { assert.equal(eventValues._did, didZeroX(subscriptionDDO.id)) // thegraph stores the addresses in lower case - assert.equal(getAddress(eventValues._receiver), subscriber.getId()) + assert.equal(getChecksumAddress(eventValues._receiver), subscriber.getId()) }) it('The Subscriber should have an NFT balance', async () => { diff --git a/integration/external/NVMAppAPI.staging.test.ts b/integration/external/NVMAppAPI.staging.test.ts index ede375f9f..e2b2dc7cf 100644 --- a/integration/external/NVMAppAPI.staging.test.ts +++ b/integration/external/NVMAppAPI.staging.test.ts @@ -1,285 +1,286 @@ -import chai, { assert } from 'chai' -import chaiAsPromised from 'chai-as-promised' - -import { - AssetPrice, - ResourceAuthentication, - SubscriptionType, - convertEthersV6SignerToAccountSigner, - isAddress, - makeWallets, - makeRandomWallet, -} from '../../src' -import TestContractHandler from '../../test/keeper/TestContractHandler' -import { NVMAppEnvironments, NvmApp } from '../../src/nevermined/NvmApp' -import { NvmAppMetadata } from '../../src/ddo/NvmAppMetadata' -import { ZeroDevAccountSigner, ZeroDevEthersProvider } from '@zerodev/sdk' -import { AppDeploymentStaging } from '../../src/nevermined/resources/AppNetworks' - -chai.use(chaiAsPromised) - -// Execute first: -// ./scripts/download-artifacts.sh v3.5.6 arbitrum-sepolia public -// export PROJECT_ID=your_project_id -describe('NVM App API', () => { - let nvmAppPublisher: NvmApp - let nvmAppSubscriber: NvmApp - - let subscriptionNFTAddress: string - let subscriptionDid: string - let agentDid: string - let datasetDid: string - let agreementId - - const projectId = process.env.PROJECT_ID! - let zerodevProvider: ZeroDevEthersProvider<'ECDSA'> - let accountSigner: ZeroDevAccountSigner<'ECDSA'> - let publisherAddress: string - let subscriptionPrice: AssetPrice - let subscriptionPriceWithFees: AssetPrice - - // Agent/Service test configuration - const SERVICE_ENDPOINT = process.env.SERVICE_ENDPOINT || 'http://127.0.0.1:3000' - const OPEN_PATH = process.env.OPEN_PATH || '/openapi.json' - const OPEN_ENDPOINT = process.env.OPEN_ENDPOINT || `${SERVICE_ENDPOINT}${OPEN_PATH}` - const AUTHORIZATION_TYPE = (process.env.AUTHORIZATION_TYPE || - 'bearer') as ResourceAuthentication['type'] - const AUTHORIZATION_TOKEN = process.env.AUTHORIZATION_TOKEN || 'new_authorization_token' - const AUTHORIZATION_USER = process.env.AUTHORIZATION_USER || 'user' - const AUTHORIZATION_PASSWORD = process.env.AUTHORIZATION_PASSWORD || 'password' - - before(async () => { - const owner = makeRandomWallet() - zerodevProvider = await ZeroDevEthersProvider.init('ECDSA', { - projectId, - owner: convertEthersV6SignerToAccountSigner(owner), - }) - - const contractABI = await TestContractHandler.getABIArtifact( - `NFT1155SubscriptionUpgradeable.arbitrum-sepolia`, - './artifacts/', - ) - - subscriptionNFTAddress = contractABI.address - console.debug(`Using ERC-1155 Subscription NFT on address: ${subscriptionNFTAddress}`) - - accountSigner = zerodevProvider.getAccountSigner() - publisherAddress = await accountSigner.getAddress() - - // Using USDC token address - // WARN: Make sure the subscriber account has balance to pay the gas and the subscription - subscriptionPrice = new AssetPrice(publisherAddress, 1000n).setTokenAddress( - new AppDeploymentStaging().tokenAddress, - ) - }) - - describe('As a PUBLISHER', () => { - it('I want to search content from the app', async () => { - nvmAppPublisher = await NvmApp.getInstance(NVMAppEnvironments.Staging) - const results = await nvmAppPublisher.search.query({}) - console.log(JSON.stringify(results.totalResults)) - - assert.isDefined(results) - }) - - it('Get the default configuration used', async () => { - const appConfig = nvmAppPublisher.config - assert.isDefined(appConfig) - assert.equal(appConfig.marketplaceUri, 'https://marketplace-api.staging.nevermined.app') - }) - - it('Overwrite the default config with some parameters', async () => { - assert.notEqual(nvmAppPublisher.config.artifactsFolder, './artifacts') - nvmAppPublisher = await NvmApp.getInstance(NVMAppEnvironments.Staging, { - artifactsFolder: './artifacts', - }) - assert.equal(nvmAppPublisher.config.artifactsFolder, './artifacts') - }) - - it('I want to connect my account', async () => { - assert.isFalse(nvmAppPublisher.isWeb3Connected()) - - await nvmAppPublisher.connect(accountSigner) - - assert.isTrue(nvmAppPublisher.isWeb3Connected()) - assert.isTrue(nvmAppPublisher.getLoginCredentials().length > 0) - }) - - it('I can get the network fees', async () => { - const networkFees = nvmAppPublisher.networkFees - assert.isDefined(networkFees) - console.log(`Network Fees: ${JSON.stringify(networkFees)}`) - assert.isTrue(isAddress(networkFees.receiver)) - assert.isTrue(networkFees.fee > 0) - }) - - it('I can calculate and include network fees', async () => { - // console.log(`AssetPrice object: ${subscriptionPrice.toString()}`) - - // assert.isFalse(nvmApp.isNetworkFeeIncluded(subscriptionPrice)) - - subscriptionPriceWithFees = nvmAppPublisher.addNetworkFee(subscriptionPrice) - console.log(`Asset Price with fees: ${subscriptionPriceWithFees.toString()}`) - - assert.isTrue(nvmAppPublisher.isNetworkFeeIncluded(subscriptionPriceWithFees)) - }) - - it('I want to create a time subscription', async () => { - const timeSubscriptionMetadata = NvmAppMetadata.getTimeSubscriptionMetadataTemplate( - 'NVM App Time only Subscription test', - 'Nevermined', - 'hours', - ) - timeSubscriptionMetadata.additionalInformation.customData = { - subscriptionLimitType: SubscriptionType.Time, - dateMeasure: 'hours', - } - - const ddo = await nvmAppPublisher.createTimeSubscription( - timeSubscriptionMetadata, - subscriptionPriceWithFees, - 100, // 100 blocks duration - ) - - assert.isDefined(ddo) - const ddoFound = await nvmAppPublisher.search.byDID(ddo.id) - assert.equal(ddo.id, ddoFound.id) - }) - - it('I want to create a credits subscription', async () => { - const creditsSubscriptionMetadata = NvmAppMetadata.getCreditsSubscriptionMetadataTemplate( - 'NVM App Credits Subscription test', - 'Nevermined', - ) - creditsSubscriptionMetadata.additionalInformation.customData = { - subscriptionLimitType: SubscriptionType.Credits, - } - - const ddo = await nvmAppPublisher.createCreditsSubscription( - creditsSubscriptionMetadata, - subscriptionPriceWithFees, - 50n, // number of credits given to the subscribers - ) - - assert.isDefined(ddo) - const ddoFound = await nvmAppPublisher.search.byDID(ddo.id) - assert.equal(ddo.id, ddoFound.id) - subscriptionDid = ddo.id - }) - - it('I want to register an Agent', async () => { - const agentMetadata = NvmAppMetadata.getServiceMetadataTemplate( - 'Nevermined Ageeeent', - 'Nevermined', - [ - { - GET: `${SERVICE_ENDPOINT}/(.*)`, - }, - ], - [OPEN_ENDPOINT], - OPEN_ENDPOINT, - 'RESTful', - AUTHORIZATION_TYPE, - AUTHORIZATION_TOKEN, - AUTHORIZATION_USER, - AUTHORIZATION_PASSWORD, - true, - ) - - const ddo = await nvmAppPublisher.registerServiceAsset( - agentMetadata, - subscriptionDid, - // We are gonna configure the agent usage costs in a dynamic manner: - // The cost in credits for every succesful query to the agent will be between 1 and 5 credits being 2 credits the default cost - 2n, // default cost in credits for every succesful query to the agent - 1n, // min amount of credits to be consumed - 5n, // max amount of credits to be consumed - ) - - assert.isDefined(ddo) - const ddoFound = await nvmAppPublisher.search.byDID(ddo.id) - assert.equal(ddo.id, ddoFound.id) - agentDid = ddo.id - }) - - it('I want to register a Dataset', async () => { - const datasetMetadata = NvmAppMetadata.getFileMetadataTemplate( - 'NVM App Dataset test', - 'Nevermined', - ) - datasetMetadata.main.files = [ - { - index: 0, - contentType: 'application/json', - name: 'ddo-example.json', - url: 'https://storage.googleapis.com/nvm-static-assets/files/ci/ddo-example.json', - }, - { - index: 1, - contentType: 'text/plain', - name: 'README.md', - url: 'https://storage.googleapis.com/nvm-static-assets/files/ci/README.md', - }, - ] - - const ddo = await nvmAppPublisher.registerFileAsset( - datasetMetadata, - subscriptionDid, - 1n, // every file download costs 1 credit to the subscriber - ) - - assert.isDefined(ddo) - const ddoFound = await nvmAppPublisher.search.byDID(ddo.id) - assert.equal(ddo.id, ddoFound.id) - datasetDid = ddo.id - }) - }) - - describe('As a SUBSCRIBER', () => { - it('I want to connect as subscriber', async () => { - nvmAppSubscriber = await NvmApp.getInstance(NVMAppEnvironments.Staging, { - artifactsFolder: './artifacts', - }) - const appConfig = nvmAppSubscriber.config - appConfig.accounts = makeWallets(process.env.SEED_WORDS) - - const subscriberAddress = await appConfig.accounts[0].getAddress() - await nvmAppSubscriber.connect(subscriberAddress, appConfig) - - assert.isTrue(nvmAppSubscriber.isWeb3Connected()) - }) - - it('I want to order a subscription', async () => { - const orderResult = await nvmAppSubscriber.orderSubscription(subscriptionDid) - assert.isDefined(orderResult) - assert.isTrue(orderResult.success) - assert.isTrue(orderResult.agreementId.length > 0) - agreementId = orderResult.agreementId - }) - - it('I want to get the token giving access to a remote agent', async () => { - const token = await nvmAppSubscriber.getServiceAccessToken(agentDid) - console.log(`Token: ${JSON.stringify(token)}`) - assert.isDefined(token) - assert.isTrue(token.accessToken.length > 0) - assert.isTrue(token.neverminedProxyUri.length > 0) - }) - - it('I want to download a file asset', async () => { - const results = await nvmAppSubscriber.downloadFiles( - datasetDid, - agreementId, - `/tmp/.nevermined/downloads/${datasetDid}/`, - ) - - assert.isDefined(results) - assert.isTrue(results.success) - }) - - it('I can disconnect and still search', async () => { - await nvmAppSubscriber.disconnect() - const results = await nvmAppSubscriber.search.query({}) - assert.isTrue(results.totalResults.value > 0) - }) - }) -}) +// TODO: Enable when ZeroDev is back +// import chai, { assert } from 'chai' +// import chaiAsPromised from 'chai-as-promised' + +// import { +// AssetPrice, +// ResourceAuthentication, +// SubscriptionType, +// convertEthersV6SignerToAccountSigner, +// isAddress, +// makeWallets, +// makeRandomWallet, +// } from '../../src' +// import TestContractHandler from '../../test/keeper/TestContractHandler' +// import { NVMAppEnvironments, NvmApp } from '../../src/nevermined/NvmApp' +// import { NvmAppMetadata } from '../../src/ddo/NvmAppMetadata' +// import { ZeroDevAccountSigner, ZeroDevEthersProvider } from '@zerodev/sdk' +// import { AppDeploymentStaging } from '../../src/nevermined/resources/AppNetworks' + +// chai.use(chaiAsPromised) + +// // Execute first: +// // ./scripts/download-artifacts.sh v3.5.6 arbitrum-sepolia public +// // export PROJECT_ID=your_project_id +// describe('NVM App API', () => { +// let nvmAppPublisher: NvmApp +// let nvmAppSubscriber: NvmApp + +// let subscriptionNFTAddress: string +// let subscriptionDid: string +// let agentDid: string +// let datasetDid: string +// let agreementId + +// const projectId = process.env.PROJECT_ID! +// let zerodevProvider: ZeroDevEthersProvider<'ECDSA'> +// let accountSigner: ZeroDevAccountSigner<'ECDSA'> +// let publisherAddress: string +// let subscriptionPrice: AssetPrice +// let subscriptionPriceWithFees: AssetPrice + +// // Agent/Service test configuration +// const SERVICE_ENDPOINT = process.env.SERVICE_ENDPOINT || 'http://127.0.0.1:3000' +// const OPEN_PATH = process.env.OPEN_PATH || '/openapi.json' +// const OPEN_ENDPOINT = process.env.OPEN_ENDPOINT || `${SERVICE_ENDPOINT}${OPEN_PATH}` +// const AUTHORIZATION_TYPE = (process.env.AUTHORIZATION_TYPE || +// 'bearer') as ResourceAuthentication['type'] +// const AUTHORIZATION_TOKEN = process.env.AUTHORIZATION_TOKEN || 'new_authorization_token' +// const AUTHORIZATION_USER = process.env.AUTHORIZATION_USER || 'user' +// const AUTHORIZATION_PASSWORD = process.env.AUTHORIZATION_PASSWORD || 'password' + +// before(async () => { +// const owner = makeRandomWallet() +// zerodevProvider = await ZeroDevEthersProvider.init('ECDSA', { +// projectId, +// owner: convertEthersV6SignerToAccountSigner(owner), +// }) + +// const contractABI = await TestContractHandler.getABIArtifact( +// `NFT1155SubscriptionUpgradeable.arbitrum-sepolia`, +// './artifacts/', +// ) + +// subscriptionNFTAddress = contractABI.address +// console.debug(`Using ERC-1155 Subscription NFT on address: ${subscriptionNFTAddress}`) + +// accountSigner = zerodevProvider.getAccountSigner() +// publisherAddress = await accountSigner.getAddress() + +// // Using USDC token address +// // WARN: Make sure the subscriber account has balance to pay the gas and the subscription +// subscriptionPrice = new AssetPrice(publisherAddress, 1000n).setTokenAddress( +// new AppDeploymentStaging().tokenAddress, +// ) +// }) + +// describe('As a PUBLISHER', () => { +// it('I want to search content from the app', async () => { +// nvmAppPublisher = await NvmApp.getInstance(NVMAppEnvironments.Staging) +// const results = await nvmAppPublisher.search.query({}) +// console.log(JSON.stringify(results.totalResults)) + +// assert.isDefined(results) +// }) + +// it('Get the default configuration used', async () => { +// const appConfig = nvmAppPublisher.config +// assert.isDefined(appConfig) +// assert.equal(appConfig.marketplaceUri, 'https://marketplace-api.staging.nevermined.app') +// }) + +// it('Overwrite the default config with some parameters', async () => { +// assert.notEqual(nvmAppPublisher.config.artifactsFolder, './artifacts') +// nvmAppPublisher = await NvmApp.getInstance(NVMAppEnvironments.Staging, { +// artifactsFolder: './artifacts', +// }) +// assert.equal(nvmAppPublisher.config.artifactsFolder, './artifacts') +// }) + +// it('I want to connect my account', async () => { +// assert.isFalse(nvmAppPublisher.isWeb3Connected()) + +// await nvmAppPublisher.connect(accountSigner) + +// assert.isTrue(nvmAppPublisher.isWeb3Connected()) +// assert.isTrue(nvmAppPublisher.getLoginCredentials().length > 0) +// }) + +// it('I can get the network fees', async () => { +// const networkFees = nvmAppPublisher.networkFees +// assert.isDefined(networkFees) +// console.log(`Network Fees: ${JSON.stringify(networkFees)}`) +// assert.isTrue(isAddress(networkFees.receiver)) +// assert.isTrue(networkFees.fee > 0) +// }) + +// it('I can calculate and include network fees', async () => { +// // console.log(`AssetPrice object: ${subscriptionPrice.toString()}`) + +// // assert.isFalse(nvmApp.isNetworkFeeIncluded(subscriptionPrice)) + +// subscriptionPriceWithFees = nvmAppPublisher.addNetworkFee(subscriptionPrice) +// console.log(`Asset Price with fees: ${subscriptionPriceWithFees.toString()}`) + +// assert.isTrue(nvmAppPublisher.isNetworkFeeIncluded(subscriptionPriceWithFees)) +// }) + +// it('I want to create a time subscription', async () => { +// const timeSubscriptionMetadata = NvmAppMetadata.getTimeSubscriptionMetadataTemplate( +// 'NVM App Time only Subscription test', +// 'Nevermined', +// 'hours', +// ) +// timeSubscriptionMetadata.additionalInformation.customData = { +// subscriptionLimitType: SubscriptionType.Time, +// dateMeasure: 'hours', +// } + +// const ddo = await nvmAppPublisher.createTimeSubscription( +// timeSubscriptionMetadata, +// subscriptionPriceWithFees, +// 100, // 100 blocks duration +// ) + +// assert.isDefined(ddo) +// const ddoFound = await nvmAppPublisher.search.byDID(ddo.id) +// assert.equal(ddo.id, ddoFound.id) +// }) + +// it('I want to create a credits subscription', async () => { +// const creditsSubscriptionMetadata = NvmAppMetadata.getCreditsSubscriptionMetadataTemplate( +// 'NVM App Credits Subscription test', +// 'Nevermined', +// ) +// creditsSubscriptionMetadata.additionalInformation.customData = { +// subscriptionLimitType: SubscriptionType.Credits, +// } + +// const ddo = await nvmAppPublisher.createCreditsSubscription( +// creditsSubscriptionMetadata, +// subscriptionPriceWithFees, +// 50n, // number of credits given to the subscribers +// ) + +// assert.isDefined(ddo) +// const ddoFound = await nvmAppPublisher.search.byDID(ddo.id) +// assert.equal(ddo.id, ddoFound.id) +// subscriptionDid = ddo.id +// }) + +// it('I want to register an Agent', async () => { +// const agentMetadata = NvmAppMetadata.getServiceMetadataTemplate( +// 'Nevermined Ageeeent', +// 'Nevermined', +// [ +// { +// GET: `${SERVICE_ENDPOINT}/(.*)`, +// }, +// ], +// [OPEN_ENDPOINT], +// OPEN_ENDPOINT, +// 'RESTful', +// AUTHORIZATION_TYPE, +// AUTHORIZATION_TOKEN, +// AUTHORIZATION_USER, +// AUTHORIZATION_PASSWORD, +// true, +// ) + +// const ddo = await nvmAppPublisher.registerServiceAsset( +// agentMetadata, +// subscriptionDid, +// // We are gonna configure the agent usage costs in a dynamic manner: +// // The cost in credits for every succesful query to the agent will be between 1 and 5 credits being 2 credits the default cost +// 2n, // default cost in credits for every succesful query to the agent +// 1n, // min amount of credits to be consumed +// 5n, // max amount of credits to be consumed +// ) + +// assert.isDefined(ddo) +// const ddoFound = await nvmAppPublisher.search.byDID(ddo.id) +// assert.equal(ddo.id, ddoFound.id) +// agentDid = ddo.id +// }) + +// it('I want to register a Dataset', async () => { +// const datasetMetadata = NvmAppMetadata.getFileMetadataTemplate( +// 'NVM App Dataset test', +// 'Nevermined', +// ) +// datasetMetadata.main.files = [ +// { +// index: 0, +// contentType: 'application/json', +// name: 'ddo-example.json', +// url: 'https://storage.googleapis.com/nvm-static-assets/files/ci/ddo-example.json', +// }, +// { +// index: 1, +// contentType: 'text/plain', +// name: 'README.md', +// url: 'https://storage.googleapis.com/nvm-static-assets/files/ci/README.md', +// }, +// ] + +// const ddo = await nvmAppPublisher.registerFileAsset( +// datasetMetadata, +// subscriptionDid, +// 1n, // every file download costs 1 credit to the subscriber +// ) + +// assert.isDefined(ddo) +// const ddoFound = await nvmAppPublisher.search.byDID(ddo.id) +// assert.equal(ddo.id, ddoFound.id) +// datasetDid = ddo.id +// }) +// }) + +// describe('As a SUBSCRIBER', () => { +// it('I want to connect as subscriber', async () => { +// nvmAppSubscriber = await NvmApp.getInstance(NVMAppEnvironments.Staging, { +// artifactsFolder: './artifacts', +// }) +// const appConfig = nvmAppSubscriber.config +// appConfig.accounts = makeWallets(process.env.SEED_WORDS) + +// const subscriberAddress = await appConfig.accounts[0].getAddress() +// await nvmAppSubscriber.connect(subscriberAddress, appConfig) + +// assert.isTrue(nvmAppSubscriber.isWeb3Connected()) +// }) + +// it('I want to order a subscription', async () => { +// const orderResult = await nvmAppSubscriber.orderSubscription(subscriptionDid) +// assert.isDefined(orderResult) +// assert.isTrue(orderResult.success) +// assert.isTrue(orderResult.agreementId.length > 0) +// agreementId = orderResult.agreementId +// }) + +// it('I want to get the token giving access to a remote agent', async () => { +// const token = await nvmAppSubscriber.getServiceAccessToken(agentDid) +// console.log(`Token: ${JSON.stringify(token)}`) +// assert.isDefined(token) +// assert.isTrue(token.accessToken.length > 0) +// assert.isTrue(token.neverminedProxyUri.length > 0) +// }) + +// it('I want to download a file asset', async () => { +// const results = await nvmAppSubscriber.downloadFiles( +// datasetDid, +// agreementId, +// `/tmp/.nevermined/downloads/${datasetDid}/`, +// ) + +// assert.isDefined(results) +// assert.isTrue(results.success) +// }) + +// it('I can disconnect and still search', async () => { +// await nvmAppSubscriber.disconnect() +// const results = await nvmAppSubscriber.search.query({}) +// assert.isTrue(results.totalResults.value > 0) +// }) +// }) +// }) diff --git a/integration/external/Services_NFT1155.e2e.test.ts b/integration/external/Services_NFT1155.e2e.test.ts index 3aaa3ae1d..6ffaaf002 100644 --- a/integration/external/Services_NFT1155.e2e.test.ts +++ b/integration/external/Services_NFT1155.e2e.test.ts @@ -29,7 +29,7 @@ import { SubscriptionCreditsNFTApi, PublishMetadataOptions, PublishOnChainOptions, - getAddress, + getChecksumAddress, } from '../../src/nevermined' import { RequestInit } from 'node-fetch' import fetch from 'node-fetch' @@ -336,7 +336,7 @@ describe('Gate-keeping of Web Services using NFT ERC-1155 End-to-End', () => { }) it('I am ordering the subscription NFT', async () => { - await subscriber.requestTokens(subscriptionPrice / scale) + await nevermined.accounts.requestTokens(subscriber, subscriptionPrice / scale) const subscriberBalanceBefore = await token.balanceOf(subscriber.getId()) assert.equal(subscriberBalanceBefore, initialBalances.subscriber + subscriptionPrice) @@ -410,7 +410,7 @@ describe('Gate-keeping of Web Services using NFT ERC-1155 End-to-End', () => { assert.equal(eventValues._did, didZeroX(subscriptionDDO.id)) // thegraph stores the addresses in lower case - assert.equal(getAddress(eventValues._receiver), subscriber.getId()) + assert.equal(getChecksumAddress(eventValues._receiver), subscriber.getId()) }) it('The publisher can access the service endpoints available', async () => { diff --git a/integration/external/Services_NFT721.e2e.test.ts b/integration/external/Services_NFT721.e2e.test.ts index efd02d045..e00d82bc3 100644 --- a/integration/external/Services_NFT721.e2e.test.ts +++ b/integration/external/Services_NFT721.e2e.test.ts @@ -28,7 +28,7 @@ import { NFT721Api, SubscriptionNFTApi, DID, - getAddress, + getChecksumAddress, } from '../../src/nevermined' import { RequestInit } from 'node-fetch' import fetch from 'node-fetch' @@ -349,7 +349,7 @@ describe('Gate-keeping of Web Services using NFT ERC-721 End-to-End', () => { }) it('I am ordering the subscription NFT', async () => { - await subscriber.requestTokens(subscriptionPrice / scale) + await nevermined.accounts.requestTokens(subscriber, subscriptionPrice / scale) const subscriberBalanceBefore = await token.balanceOf(subscriber.getId()) assert.equal(subscriberBalanceBefore, initialBalances.subscriber + subscriptionPrice) @@ -424,7 +424,7 @@ describe('Gate-keeping of Web Services using NFT ERC-721 End-to-End', () => { assert.equal(eventValues._did, didZeroX(subscriptionDDO.id)) // thegraph stores the addresses in lower case - assert.equal(getAddress(eventValues._receiver), subscriber.getId()) + assert.equal(getChecksumAddress(eventValues._receiver), subscriber.getId()) }) }) diff --git a/integration/external/Zerodev.test.ts b/integration/external/Zerodev.test.ts index 39bbfd031..9df80e150 100644 --- a/integration/external/Zerodev.test.ts +++ b/integration/external/Zerodev.test.ts @@ -1,215 +1,216 @@ -import { ZeroDevEthersProvider } from '@zerodev/sdk' -import { verifyMessage } from '@ambire/signature-validator' -import * as fs from 'fs' -import { - AssetAttributes, - AssetPrice, - DDO, - MetaData, - Nevermined, - NvmAccount, - convertEthersV6SignerToAccountSigner, - makeRandomWallet, -} from '../../src' -import { assert } from 'chai' -import { decodeJwt } from 'jose' -import { config } from '../config' -import { getMetadata } from '../utils' - -describe('Nevermined sdk with zerodev', () => { - let nevermined: Nevermined - - before(async () => { - nevermined = await Nevermined.getInstance(config) - }) - - describe('Test zerodev signatures and login', () => { - let zerodevProvider: ZeroDevEthersProvider<'ECDSA'> - let clientAssertion: string - - before(async () => { - const projectId = process.env.PROJECT_ID! - const owner = makeRandomWallet() - - zerodevProvider = await ZeroDevEthersProvider.init('ECDSA', { - projectId, - owner: convertEthersV6SignerToAccountSigner(owner), - }) - }) - - 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, - }) - - assert.isTrue(isValidSignature) - }) - - 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: '', - }) - - const isValidSignature = await verifyMessage({ - signer: await signer.getAddress(), - signature: signature, - typedData: { - types, - domain, - message, - }, - provider: zerodevProvider, - }) - - assert.isTrue(isValidSignature) - }) - - it('should generate a client assertion with a zerodev signer', async () => { - const signer = zerodevProvider.getAccountSigner() - const account = await Account.fromZeroDevSigner(signer) - - clientAssertion = await nevermined.utils.jwt.generateClientAssertion(account, 'hello world') - assert.isDefined(clientAssertion) - - const jwtPayload = decodeJwt(clientAssertion) - assert.equal(jwtPayload.iss, await signer.getAddress()) - }) - - it('should login to the marketplace api', async () => { - const accessToken = await nevermined.services.marketplace.login(clientAssertion) - assert.isDefined(accessToken) - - const jwtPayload = decodeJwt(accessToken) - const signer = zerodevProvider.getAccountSigner() - assert.equal(jwtPayload.iss, await signer.getAddress()) - assert.isDefined(jwtPayload.sub) - }) - }) - - 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 = makeRandomWallet() - const consumer = makeRandomWallet() - - 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 NvmAccount.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 - }) - - 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()) - }) - - 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' - - const path = (await nevermined.assets.download(ddo.id, publisher, folder, -1)) as string - const files = await new Promise((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) - }) - - 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((resolve) => { - fs.readdir(path, (e, fileList) => { - resolve(fileList) - }) - }) - - assert.deepEqual(files, ['README.md', 'ddo-example.json']) - }) - }) -}) +// TODO: Enable when ZeroDev is ready +// import { ZeroDevEthersProvider } from '@zerodev/sdk' +// import { verifyMessage } from '@ambire/signature-validator' +// import * as fs from 'fs' +// import { +// AssetAttributes, +// AssetPrice, +// DDO, +// MetaData, +// Nevermined, +// NvmAccount, +// convertEthersV6SignerToAccountSigner, +// makeRandomWallet, +// } from '../../src' +// import { assert } from 'chai' +// import { decodeJwt } from 'jose' +// import { config } from '../config' +// import { getMetadata } from '../utils' + +// describe('Nevermined sdk with zerodev', () => { +// let nevermined: Nevermined + +// before(async () => { +// nevermined = await Nevermined.getInstance(config) +// }) + +// describe('Test zerodev signatures and login', () => { +// let zerodevProvider: ZeroDevEthersProvider<'ECDSA'> +// let clientAssertion: string + +// before(async () => { +// const projectId = process.env.PROJECT_ID! +// const owner = makeRandomWallet() + +// zerodevProvider = await ZeroDevEthersProvider.init('ECDSA', { +// projectId, +// owner: convertEthersV6SignerToAccountSigner(owner), +// }) +// }) + +// 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, +// }) + +// assert.isTrue(isValidSignature) +// }) + +// 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: '', +// }) + +// const isValidSignature = await verifyMessage({ +// signer: await signer.getAddress(), +// signature: signature, +// typedData: { +// types, +// domain, +// message, +// }, +// provider: zerodevProvider, +// }) + +// assert.isTrue(isValidSignature) +// }) + +// it('should generate a client assertion with a zerodev signer', async () => { +// const signer = zerodevProvider.getAccountSigner() +// const account = await Account.fromZeroDevSigner(signer) + +// clientAssertion = await nevermined.utils.jwt.generateClientAssertion(account, 'hello world') +// assert.isDefined(clientAssertion) + +// const jwtPayload = decodeJwt(clientAssertion) +// assert.equal(jwtPayload.iss, await signer.getAddress()) +// }) + +// it('should login to the marketplace api', async () => { +// const accessToken = await nevermined.services.marketplace.login(clientAssertion) +// assert.isDefined(accessToken) + +// const jwtPayload = decodeJwt(accessToken) +// const signer = zerodevProvider.getAccountSigner() +// assert.equal(jwtPayload.iss, await signer.getAddress()) +// assert.isDefined(jwtPayload.sub) +// }) +// }) + +// 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 = makeRandomWallet() +// const consumer = makeRandomWallet() + +// 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 NvmAccount.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 +// }) + +// 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()) +// }) + +// 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' + +// const path = (await nevermined.assets.download(ddo.id, publisher, folder, -1)) as string +// const files = await new Promise((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) +// }) + +// 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((resolve) => { +// fs.readdir(path, (e, fileList) => { +// resolve(fileList) +// }) +// }) + +// assert.deepEqual(files, ['README.md', 'ddo-example.json']) +// }) +// }) +// }) diff --git a/integration/tsconfig.json b/integration/tsconfig.json index 4dcca442c..de4e823d5 100644 --- a/integration/tsconfig.json +++ b/integration/tsconfig.json @@ -2,8 +2,12 @@ "compilerOptions": { "moduleResolution": "Node", "resolveJsonModule": true, - "lib": ["es6", "es7", "dom", "ES2020"], - "target": "ES2020", + "lib": [ + "ES2022", // By using ES2022 we get access to the `.cause` property on `Error` instances. + "DOM" // We are adding `DOM` here to get the `fetch`, etc. types. This should be removed once these types are available via DefinitelyTyped. + ], + //"lib": ["es6", "es7", "dom", "ES2020"], + "target": "ES2021", "noUnusedLocals": true, "esModuleInterop": true, "allowSyntheticDefaultImports": true diff --git a/package.json b/package.json index 052dd912e..653090cf5 100644 --- a/package.json +++ b/package.json @@ -11,7 +11,7 @@ "build:metadata": "./scripts/get-metadata.js > src/metadata.json", "build:dist": "cross-env NODE_ENV=production webpack", "build:watch": "tsc -w", - "test": "mocha --full-trace --max_old_space_size=8192 --config test/.mocharc.json ", + "test": "mocha --full-trace --check-leaks --allow-uncaught --max_old_space_size=8192 --config test/.mocharc.json ", "test:all": "mocha --config test/.mocharc.json ./test/**/*.test.ts", "integration": "mocha --config integration/.mocharc.json ", "integration:all": "mocha --config integration/.mocharc.json ./integration/nevermined/*.test.ts", @@ -21,8 +21,8 @@ "integration:compute": "mocha --config integration/.mocharc.json ./integration/compute/Compute*.test.ts", "integration:external": "mocha --config integration/.mocharc.json ./integration/external/*.test.ts", "clean": "rm -rf ./dist/ ./doc/ ./.nyc_output", - "lint": "eslint ./", - "lint:fix": "eslint ./ --fix", + "lint": "NODE_OPTIONS=--trace-deprecation eslint ./", + "lint:fix": "NODE_OPTIONS=--trace-deprecation eslint ./ --fix --quiet", "format": "prettier --parser typescript --ignore-path .gitignore --write '**/*.{js,jsx,ts,tsx}'", "docs": "typedoc", "run": "ts-node", @@ -89,7 +89,7 @@ "@types/chai-as-promised": "^7.1.3", "@types/chai-spies": "^1.0.1", "@types/lodash": "^4.14.195", - "@types/mocha": "^10.0.1", + "@types/mocha": "^10.0.6", "@types/node": "^20.1.0", "@types/node-fetch": "^2.5.7", "@types/pluralize": "^0.0.29", @@ -97,20 +97,22 @@ "@types/temp": "^0.9.1", "@typescript-eslint/eslint-plugin": "^7.3.1", "@typescript-eslint/parser": "^7.3.1", + "@typescript-eslint/typescript-estree": "^7.3.1", "auto-changelog": "^2.4.0", "chai": "^4.3.7", "chai-as-promised": "^7.1.1", "chai-exclude": "^2.1.0", "chai-spies": "^1.0.0", "cross-env": "^7.0.3", - "eslint": "^8.19.0", + "eslint": "^8.57.0", "eslint-config-nevermined": "^0.2.0", - "eslint-config-next": "^12.3.1", - "eslint-config-prettier": "^8.5.0", - "eslint-plugin-import": "^2.26.0", - "eslint-plugin-mdx": "^2.0.2", - "eslint-plugin-prettier": "^4.2.1", - "eslint-plugin-tsdoc": "^0.2.16", + "eslint-config-next": "^14.1.4", + "eslint-config-prettier": "^9.1.0", + "eslint-plugin-import": "^2.29.1", + "eslint-plugin-mdx": "^3.1.5", + "eslint-plugin-prettier": "^5.1.3", + "eslint-plugin-tsdoc": "^0.2.17", + "eslint-plugin-react": "7.34.1", "express": "^4.18.2", "ganache": "^7.9.1", "http-proxy": "^1.18.1", @@ -128,8 +130,8 @@ "tar": "^6.1.11", "terser-webpack-plugin": "^5.3.1", "ts-node": "^10.9.2", - "typedoc": "^0.25.2", - "typedoc-plugin-markdown": "^3.16.0", + "typedoc": "^0.25.12", + "typedoc-plugin-markdown": "^3.17.1", "typescript": "^5.4.2", "url": "^0.11.0", "webpack": "^5.90.3", diff --git a/src/keeper/contracts/ContractBase.ts b/src/keeper/contracts/ContractBase.ts index c26116861..4e33f5bbe 100644 --- a/src/keeper/contracts/ContractBase.ts +++ b/src/keeper/contracts/ContractBase.ts @@ -65,7 +65,7 @@ export abstract class ContractBase extends Instantiable { protected async getFromAddress(from?: string): Promise { if (!from) { - // eslint-disable-next-line @typescript-eslint/no-extra-semi + // eslint-disable-next-line ;[from] = await this.nevermined.accounts.addresses() } return from @@ -80,6 +80,13 @@ export abstract class ContractBase extends Instantiable { }) } + public someLog(logs: any[]) { + logs.some((e: any) => { + return e.args + }) + return undefined + } + public async sendFrom( functionName: string, args: any[], diff --git a/src/keeper/contracts/conditions/Condition.abstract.ts b/src/keeper/contracts/conditions/Condition.abstract.ts index c3edc307a..4cafb84a8 100644 --- a/src/keeper/contracts/conditions/Condition.abstract.ts +++ b/src/keeper/contracts/conditions/Condition.abstract.ts @@ -41,7 +41,6 @@ export interface ConditionInstance extends ConditionInstanceSmall { export const conditionStateNames = ['Uninitialized', 'Unfulfilled', 'Fulfilled', 'Aborted'] export abstract class ConditionSmall extends ContractBase { - // eslint-disable-next-line @typescript-eslint/no-unused-vars // public static async getInstance( public static async getInstance( config: InstantiableConfig, @@ -74,7 +73,7 @@ export abstract class ConditionSmall extends ContractBase { return this.generateId(agreementId, await this.hashValues(...values)) } - public generateId(agreementId: string, valueHash: string) { + public generateId(agreementId: string, valueHash: string): Promise<`0x${string}`> { return this.call('generateId', [zeroX(agreementId), valueHash]) } diff --git a/src/nevermined/Token.ts b/src/nevermined/Token.ts index 451d6e468..2b896249d 100644 --- a/src/nevermined/Token.ts +++ b/src/nevermined/Token.ts @@ -70,7 +70,7 @@ export class TokenUtils extends Instantiable { * @param txParams - Transaction parameters * @returns {@link true} if the call succeeded, {@link false} otherwise */ - public async request(account: NvmAccount, amount: number, params?: txParams): Promise { + public async request(account: NvmAccount, amount: bigint, params?: txParams): Promise { try { await this.nevermined.accounts.requestTokens(account, amount, params) return true diff --git a/src/nevermined/api/RegistryBaseApi.ts b/src/nevermined/api/RegistryBaseApi.ts index 44a5d93fd..fc1323680 100644 --- a/src/nevermined/api/RegistryBaseApi.ts +++ b/src/nevermined/api/RegistryBaseApi.ts @@ -200,7 +200,7 @@ export abstract class RegistryBaseApi extends Instantiable { if (publicationOptions.metadata != PublishMetadataOptions.OnlyMetadataAPI) { observer.next(CreateProgressStep.DdoStoredImmutable) try { - // eslint-disable-next-line @typescript-eslint/no-extra-semi + // eslint-disable-next-line ;({ url: ddoVersion.immutableUrl, backend: ddoVersion.immutableBackend } = await this.nevermined.services.node.publishImmutableContent( ddo, @@ -417,7 +417,7 @@ export abstract class RegistryBaseApi extends Instantiable { if (publishMetadataOptions != PublishMetadataOptions.OnlyMetadataAPI) { observer.next(UpdateProgressStep.StoringImmutableDDO) try { - // eslint-disable-next-line @typescript-eslint/no-extra-semi + // eslint-disable-next-line ;({ url: ddoVersion.immutableUrl, backend: ddoVersion.immutableBackend } = await this.nevermined.services.node.publishImmutableContent( ddo, diff --git a/src/nevermined/utils/BlockchainViemUtils.ts b/src/nevermined/utils/BlockchainViemUtils.ts index a08cf9758..a4a1f2c79 100644 --- a/src/nevermined/utils/BlockchainViemUtils.ts +++ b/src/nevermined/utils/BlockchainViemUtils.ts @@ -32,17 +32,6 @@ export class BlockchainViemUtils extends Instantiable { args: string[] = [], ) { this.logger.debug(`Deploying abi using account: ${from.getId()}`) - let isZos - try { - const initializeFunc = searchAbiFunction(artifact.abi, 'initialize') - isZos = initializeFunc ? true : false - this.logger.debug(`Initialize function: ${JSON.stringify(initializeFunc)}`) - this.logger.debug(JSON.stringify(args)) - } catch (error) { - isZos = false - } - - this.logger.debug(`Is ZOS: ${isZos}`) const addresses = await this.walletClient.getAddresses() addresses.map((address) => this.logger.debug(`Address: ${address}`)) @@ -69,6 +58,23 @@ export class BlockchainViemUtils extends Instantiable { // @ts-expect-error "viem, wtf?" client: { wallet: this.client.wallet, public: this.client.public }, }) + + let isZos + try { + const initializeFunc = searchAbiFunction(artifact.abi, 'initialize') + isZos = initializeFunc ? true : false + this.logger.debug(`Initialize function: ${JSON.stringify(initializeFunc)}`) + this.logger.debug(JSON.stringify(args)) + + this.logger.debug(`Is ZOS: ${isZos}`) + if (isZos) { + // @ts-expect-error "viem, wtf?" + await contract.write.initialize(...args) + } + } catch (error) { + isZos = false + } + return contract // const initArgs = isZos ? [] : args diff --git a/src/nevermined/utils/JwtUtils.ts b/src/nevermined/utils/JwtUtils.ts index d3354eadc..3ba38083e 100644 --- a/src/nevermined/utils/JwtUtils.ts +++ b/src/nevermined/utils/JwtUtils.ts @@ -155,10 +155,10 @@ export class JwtUtils extends Instantiable { const address = account.getId().toLowerCase() // Currently only works with HDWalletProvider - // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // eslint-disable-next-line // @ts-ignore const publicKey = this.web3.currentProvider.wallets[address].getPublicKey() - // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // eslint-disable-next-line // @ts-ignore const privateKey = this.web3.currentProvider.wallets[address].getPrivateKey() diff --git a/test/keeper/ContractBase.test.ts b/test/keeper/ContractBase.test.ts index 0a887fc45..4ba160c12 100644 --- a/test/keeper/ContractBase.test.ts +++ b/test/keeper/ContractBase.test.ts @@ -1,7 +1,7 @@ import { assert } from 'chai' import { NvmAccount } from '../../src/nevermined' import { Nevermined } from '../../src/nevermined' -import { getSignatureOfFunction } from '../../src/nevermined/utils/BlockchainEthersUtils' +import { getSignatureOfFunction } from '../../src/nevermined/utils/BlockchainViemUtils' import config from '../config' import ContractBaseMock from '../mocks/ContractBase.Mock' import TestContractHandler from './TestContractHandler' diff --git a/test/keeper/ContractEvent.test.ts b/test/keeper/ContractEvent.test.ts index 93ae6c071..b29d5a1d8 100644 --- a/test/keeper/ContractEvent.test.ts +++ b/test/keeper/ContractEvent.test.ts @@ -3,8 +3,7 @@ import { Nevermined } from '../../src/nevermined' import config from '../config' import TestContractHandler from './TestContractHandler' import { ContractEventSubscription } from '../../src/events/NeverminedEvent' -import { NvmAccount, getWeb3EthersProvider } from '../../src' -import { ethers } from 'ethers' +import { NvmAccount } from '../../src' describe('ContractEvent', () => { let nevermined: Nevermined @@ -12,19 +11,17 @@ describe('ContractEvent', () => { let account2: NvmAccount let account3: NvmAccount let account4: NvmAccount - let web3: ethers.JsonRpcProvider | ethers.BrowserProvider before(async () => { await TestContractHandler.prepareContracts() nevermined = await Nevermined.getInstance(config) - web3 = await getWeb3EthersProvider(config) ;[account1, account2, account3, account4] = await nevermined.accounts.list() }) describe('#subscribe()', () => { it('should be able to listen to events', async () => { let subscription: ContractEventSubscription - const fromBlock = await web3.getBlockNumber() + const fromBlock = await nevermined.client.public.getBlockNumber() const waitForEvents = new Promise((resolve) => { subscription = nevermined.keeper.token.events.subscribe( @@ -58,7 +55,7 @@ describe('ContractEvent', () => { describe('#once()', () => { it('should listen to event only once', async () => { - const fromBlock = await web3.getBlockNumber() + const fromBlock = await nevermined.client.public.getBlockNumber() const eventsPromise = nevermined.keeper.token.events.once((e) => e, { eventName: 'Transfer', diff --git a/test/keeper/DIDRegistry.test.ts b/test/keeper/DIDRegistry.test.ts index 2a79d6b60..b7a09d688 100644 --- a/test/keeper/DIDRegistry.test.ts +++ b/test/keeper/DIDRegistry.test.ts @@ -7,7 +7,6 @@ import TestContractHandler from './TestContractHandler' import { Logger, LogLevel } from '../../src/utils' import { ContractTransactionReceipt, ethers, EventLog } from 'ethers' import { TxParameters } from '../../src/keeper' -import { getWeb3EthersProvider } from '../../src' let nevermined: Nevermined let didRegistry: DIDRegistry @@ -26,7 +25,7 @@ describe('DIDRegistry', () => { const [ownerAccount] = await nevermined.accounts.list() const did = generateId() const data = 'my nice provider, is nice' - const contractReceipt: ContractTransactionReceipt = await didRegistry.registerAttribute( + const contractReceipt = await didRegistry.registerAttribute( did, checksum, [], diff --git a/test/keeper/TestContractHandler.ts b/test/keeper/TestContractHandler.ts index f34a41184..abc90b019 100644 --- a/test/keeper/TestContractHandler.ts +++ b/test/keeper/TestContractHandler.ts @@ -3,40 +3,36 @@ import * as KeeperUtils from '../../src/keeper/utils' import Logger from '../../src/utils/Logger' import config from '../config' import { ZeroAddress } from '../../src/utils' -import { ContractTransactionReceipt, ContractTransactionResponse, ethers } from 'ethers' import fs from 'fs' -import { - NeverminedOptions, - Web3Clients, - getWeb3EthersProvider, - getWeb3ViemClients, -} from '../../src' -import { getSignatureOfFunction } from '../../src/nevermined/utils/BlockchainEthersUtils' +import { keccak256, NeverminedOptions, Web3Clients, NvmAccount, Nevermined } from '../../src' export default abstract class TestContractHandler extends ContractHandler { + private static networkId: number + private static minter: string + private static config = config + // private static web3: ethers.JsonRpcProvider | ethers.BrowserProvider + private static client: Web3Clients + private static nevermined: Nevermined + public static async prepareContracts(): Promise { - await TestContractHandler.setConfig(config) + // await TestContractHandler.setConfig(config) + TestContractHandler.config = config + TestContractHandler.nevermined = await Nevermined.getInstance(config) const [deployerAddress] = await TestContractHandler.addresses(TestContractHandler.config) TestContractHandler.networkId = await TestContractHandler.client.public.getChainId() //TestContractHandler.web3 //Number((await TestContractHandler.web3.getNetwork()).chainId) - TestContractHandler.minter = ethers.encodeBytes32String('minter') + TestContractHandler.minter = keccak256('minter') // deploy contracts await TestContractHandler.deployContracts(deployerAddress) return deployerAddress } - private static networkId: number - private static minter: string - private static config = config - private static web3: ethers.JsonRpcProvider | ethers.BrowserProvider - private static client: Web3Clients - - public static async setConfig(config) { - TestContractHandler.config = config - TestContractHandler.web3 = await getWeb3EthersProvider(TestContractHandler.config) - TestContractHandler.client = getWeb3ViemClients(TestContractHandler.config) - } + // public static async setConfig(config) { + // TestContractHandler.config = config + // // TestContractHandler.web3 = await getWeb3EthersProvider(TestContractHandler.config) + // // TestContractHandler.client = await getWeb3ViemClients(TestContractHandler.config) + // } private static async deployContracts(deployerAddress: string) { Logger.log('Trying to deploy contracts') @@ -66,17 +62,22 @@ export default abstract class TestContractHandler extends ContractHandler { // Add dispenser as Token minter - const signer = await TestContractHandler.findSignerStatic( - TestContractHandler.config, - TestContractHandler.web3, - deployerAddress, - ) - const contract = token.connect(signer) + // const nvmAccount = await TestContractHandler.findNvmAccount( + // TestContractHandler.config, + // TestContractHandler.client, + // deployerAddress, + // ) + //const contract = token.connect(signer) const args = [TestContractHandler.minter, await dispenser.getAddress()] - const methodSignature = getSignatureOfFunction(contract.interface, 'grantRole', args) - let transactionResponse: ContractTransactionResponse = await contract[methodSignature](...args) - let contractReceipt: ContractTransactionReceipt = await transactionResponse.wait() - if (contractReceipt.status !== 1) { + // const methodSignature = getSignatureOfFunction(token.interface, 'grantRole', args) + // let transactionResponse: ContractTransactionResponse = await contract[methodSignature](...args) + // let contractReceipt: ContractTransactionReceipt = await transactionResponse.wait() + // if (contractReceipt.status !== 1) { + // throw new Error('Error calling "grantRole" on "token"') + // } + let txHash = await token.write.grantRole(args) + let tx = await this.client.public.waitForTransactionReceipt({ hash: txHash }) + if (tx.status !== 'success') { throw new Error('Error calling "grantRole" on "token"') } @@ -111,13 +112,18 @@ export default abstract class TestContractHandler extends ContractHandler { await nvmConfig.getAddress(), ]) - transactionResponse = await didRegistry.connect(signer).getFunction('setNFT1155')( - await erc1155.getAddress(), - ) - contractReceipt = await transactionResponse.wait() - if (contractReceipt.status !== 1) { + txHash = didRegistry.write.setNFT1155(await erc1155.getAddress()) + tx = await this.client.public.waitForTransactionReceipt({ hash: txHash }) + if (tx.status !== 'success') { throw new Error('Error calling "setNFT1155" on "didRegistry"') } + // transactionResponse = await didRegistry.connect(nvmAccount).getFunction('setNFT1155')( + // await erc1155.getAddress(), + // ) + // contractReceipt = await transactionResponse.wait() + // if (contractReceipt.status !== 1) { + // throw new Error('Error calling "setNFT1155" on "didRegistry"') + // } // Managers const templateStoreManager = await TestContractHandler.deployContract( @@ -175,14 +181,20 @@ export default abstract class TestContractHandler extends ContractHandler { deployerAddress, [deployerAddress, await conditionStoreManager.getAddress(), await erc1155.getAddress()], ) - transactionResponse = await erc1155.connect(signer).getFunction('grantOperatorRole')( - await nftLockCondition.getAddress(), - ) - contractReceipt = await transactionResponse.wait() - if (contractReceipt.status !== 1) { - throw new Error('Error calling "grantOperatorRole" on "erc1155"') + txHash = erc1155.write.grantOperatorRole(await nftLockCondition.getAddress()) + tx = await this.client.public.waitForTransactionReceipt({ hash: txHash }) + if (tx.status !== 'success') { + throw new Error('Error calling "grantOperatorRole" on "erc1155" - nftLockCondition') } + // transactionResponse = await erc1155.connect(nvmAccount).getFunction('grantOperatorRole')( + // await nftLockCondition.getAddress(), + // ) + // contractReceipt = await transactionResponse.wait() + // if (contractReceipt.status !== 1) { + // throw new Error('Error calling "grantOperatorRole" on "erc1155"') + // } + const nftAcessCondition = await TestContractHandler.deployContract( 'NFTAccessCondition', deployerAddress, @@ -213,20 +225,30 @@ export default abstract class TestContractHandler extends ContractHandler { ], ) - transactionResponse = await erc1155.connect(signer).getFunction('grantOperatorRole')( - await transferNftCondition.getAddress(), - ) - contractReceipt = await transactionResponse.wait() - if (contractReceipt.status !== 1) { - throw new Error('Error calling "grantOperatorRole" on "erc721"') + txHash = erc1155.write.grantOperatorRole(await transferNftCondition.getAddress()) + tx = await this.client.public.waitForTransactionReceipt({ hash: txHash }) + if (tx.status !== 'success') { + throw new Error('Error calling "grantOperatorRole" on "erc1155" - transferNftCondition') } - - transactionResponse = await erc1155.connect(signer).getFunction('grantOperatorRole')( - await didRegistry.getAddress(), - ) - contractReceipt = await transactionResponse.wait() - if (contractReceipt.status !== 1) { - throw new Error('Error calling "grantOperatorRole" on "erc721"') + // transactionResponse = await erc1155.connect(nvmAccount).getFunction('grantOperatorRole')( + // await transferNftCondition.getAddress(), + // ) + // contractReceipt = await transactionResponse.wait() + // if (contractReceipt.status !== 1) { + // throw new Error('Error calling "grantOperatorRole" on "erc721"') + // } + + // transactionResponse = await erc1155.connect(nvmAccount).getFunction('grantOperatorRole')( + // await didRegistry.getAddress(), + // ) + // contractReceipt = await transactionResponse.wait() + // if (contractReceipt.status !== 1) { + // throw new Error('Error calling "grantOperatorRole" on "erc721"') + // } + txHash = erc1155.write.grantOperatorRole(await didRegistry.getAddress()) + tx = await this.client.public.waitForTransactionReceipt({ hash: txHash }) + if (tx.status !== 'success') { + throw new Error('Error calling "grantOperatorRole" on "erc1155" - didRegistry') } const transferDidOwnershipCondition = await TestContractHandler.deployContract( @@ -291,15 +313,15 @@ export default abstract class TestContractHandler extends ContractHandler { ]) } - public static async findSignerStatic( + public static async findNvmAccount( config: NeverminedOptions, - web3: ethers.JsonRpcProvider | ethers.BrowserProvider, + client: Web3Clients, from: string, - ): Promise { + ): Promise { for (const acc of config.accounts || []) { const addr = await acc.getAddress() if (addr.toLowerCase() === from.toLowerCase()) { - return acc.connect(web3) + return acc } } } @@ -314,10 +336,10 @@ export default abstract class TestContractHandler extends ContractHandler { args: any[] = [], tokens: { [name: string]: string } = {}, init = true, - ): Promise { + ) { const where = TestContractHandler.networkId - let contractInstance: ethers.BaseContract + let contractInstance try { const networkName = ( await KeeperUtils.getNetworkName(TestContractHandler.networkId) @@ -326,6 +348,7 @@ export default abstract class TestContractHandler extends ContractHandler { const artifact = JSON.parse( fs.readFileSync(`./artifacts/${name}.${networkName}.json`).toString(), ) + contractInstance = await TestContractHandler.deployArtifact( artifact, from, @@ -353,59 +376,77 @@ export default abstract class TestContractHandler extends ContractHandler { from?: string, args = [], tokens = {}, - init = true, - ): Promise { + _init = true, + ) { if (!from) { // eslint-disable-next-line @typescript-eslint/no-extra-semi ;[from] = await TestContractHandler.addresses(TestContractHandler.config) } - const sendConfig = { - gasLimit: 6721975, - gasPrice: '0x87500000', - } + // const sendConfig = { + // gasLimit: 6721975, + // gasPrice: '0x87500000', + // } - const signer = await TestContractHandler.findSignerStatic( + const nvmAccount = await TestContractHandler.findNvmAccount( TestContractHandler.config, - TestContractHandler.web3, + TestContractHandler.client, from, ) - const tempContract = new ethers.ContractFactory( - artifact.abi, - TestContractHandler.replaceTokens(artifact.bytecode, tokens), - signer, - ) - const initializeExists = tempContract.interface.hasFunction('initialize') - const isZos = initializeExists && init - - Logger.debug({ - name: artifact.name, - from, - isZos, - args, - libraries: artifact.bytecode - .replace(/(0x)?[a-f0-9]{8}/gi, '') - .replace(/__([^_]+)_*[0-9a-f]{2}/g, '|$1') - .split('|') - .splice(1), - }) - - const argument = isZos ? [] : args - const contractInstance: ethers.BaseContract = await tempContract.deploy(...argument, sendConfig) - await contractInstance.waitForDeployment() - - if (isZos) { - const methodSignature = getSignatureOfFunction(contractInstance.interface, 'initialize', args) - const contract = contractInstance.connect(signer) - const transactionResponse: ContractTransactionResponse = await contract[methodSignature]( - ...args, - sendConfig, - ) - const contractReceipt: ContractTransactionReceipt = await transactionResponse.wait() - if (contractReceipt.status !== 1) { - throw new Error(`Error deploying contract ${artifact.name}`) - } + const contractArtifact = { + ...artifact, + bytecode: TestContractHandler.replaceTokens(artifact.bytecode, tokens), } + const contractInstance = TestContractHandler.nevermined.utils.blockchain.deployAbi( + contractArtifact, + nvmAccount, + args, + ) + // const tempContract = getContract({ + // abi: artifact.abi, + // bytecode: TestContractHandler.replaceTokens(artifact.bytecode, tokens), + // // address: contractAddress, + // // @ts-expect-error "viem, wtf?" + // client: { wallet: this.client.wallet, public: this.client.public }, + // }) + + // const tempContract = new ethers.ContractFactory( + // artifact.abi, + // TestContractHandler.replaceTokens(artifact.bytecode, tokens), + // nvmAccount, + // ) + // const initializeFunc = searchAbiFunction(artifact.abi, 'initialize') + // // const initializeExists = tempContract.interface.hasFunction('initialize') + // const isZos = initializeFunc ? true : false + + // Logger.debug({ + // name: artifact.name, + // from, + // isZos, + // args, + // libraries: artifact.bytecode + // .replace(/(0x)?[a-f0-9]{8}/gi, '') + // .replace(/__([^_]+)_*[0-9a-f]{2}/g, '|$1') + // .split('|') + // .splice(1), + // }) + + // const argument = isZos ? [] : args + // const contractInstance: ethers.BaseContract = await tempContract.deploy(...argument, sendConfig) + // await contractInstance.waitForDeployment() + + // if (isZos) { + // const methodSignature = getSignatureOfFunction(contractInstance.interface, 'initialize', args) + // const contract = contractInstance.connect(nvmAccount) + // const transactionResponse: ContractTransactionResponse = await contract[methodSignature]( + // ...args, + // sendConfig, + // ) + // const contractReceipt: ContractTransactionReceipt = await transactionResponse.wait() + // if (contractReceipt.status !== 1) { + // throw new Error(`Error deploying contract ${artifact.name}`) + // } + // } return contractInstance } diff --git a/test/keeper/conditions/LockPaymentCondition.test.ts b/test/keeper/conditions/LockPaymentCondition.test.ts index a61222a29..390f19364 100644 --- a/test/keeper/conditions/LockPaymentCondition.test.ts +++ b/test/keeper/conditions/LockPaymentCondition.test.ts @@ -25,6 +25,7 @@ describe('LockPaymentCondition', () => { const amount = 15n let agreementId let did + let nevermined beforeEach(() => { agreementId = generateId(64) @@ -34,7 +35,7 @@ describe('LockPaymentCondition', () => { before(async () => { await TestContractHandler.prepareContracts() - const nevermined = await Nevermined.getInstance(config) + nevermined = await Nevermined.getInstance(config) await nevermined.keeper.nvmConfig.setNetworkFees(0, ZeroAddress) ;({ conditionStoreManager } = nevermined.keeper) ;({ lockPaymentCondition, escrowPaymentCondition } = nevermined.keeper.conditions) @@ -85,7 +86,7 @@ describe('LockPaymentCondition', () => { await conditionStoreManager.createCondition(conditionId, lockPaymentCondition.address, owner) - await buyer.requestTokens(assetPrice.getTotalPrice()) + await nevermined.accounts.requestTokens(buyer, assetPrice.getTotalPrice()) await token.approve(lockPaymentCondition.address, assetPrice.getTotalPrice(), buyer) diff --git a/test/keeper/conditions/NFT721LockCondition.test.ts b/test/keeper/conditions/NFT721LockCondition.test.ts index 81f652826..a1abd5c66 100644 --- a/test/keeper/conditions/NFT721LockCondition.test.ts +++ b/test/keeper/conditions/NFT721LockCondition.test.ts @@ -8,7 +8,7 @@ import config from '../../config' import TestContractHandler from '../TestContractHandler' import { NFT721Api } from '../../../src' import { DIDRegistry } from '../../../src/keeper' -import { ContractTransactionReceipt, EventLog, BaseContract } from 'ethers' +import { EventLog, BaseContract } from 'ethers' chai.use(chaiAsPromised) @@ -90,7 +90,7 @@ describe('NFT721LockCondition', () => { ) const conditionId = await nft721LockCondition.generateId(agreementId, hashValues) await conditionStoreManager.createCondition(conditionId, nft721LockCondition.address, owner) - const contractReceipt: ContractTransactionReceipt = await nft721LockCondition.fulfill( + const contractReceipt = await nft721LockCondition.fulfill( agreementId, did, lockAddress.getId(), diff --git a/test/keeper/conditions/NFTAccessCondition.test.ts b/test/keeper/conditions/NFTAccessCondition.test.ts index adfe15412..1ac4c4a0d 100644 --- a/test/keeper/conditions/NFTAccessCondition.test.ts +++ b/test/keeper/conditions/NFTAccessCondition.test.ts @@ -13,7 +13,7 @@ import { DIDRegistry } from '../../../src/keeper' import { didZeroX, zeroX } from '../../../src/utils' import config from '../../config' import TestContractHandler from '../TestContractHandler' -import { ContractTransactionReceipt, EventLog } from 'ethers' +import { EventLog } from 'ethers' chai.use(chaiAsPromised) @@ -105,11 +105,7 @@ describe('NFTAccessCondition', () => { templateId, ) - const contractReceipt: ContractTransactionReceipt = await nftAccessCondition.fulfill( - agreementId, - did, - grantee.getId(), - ) + const contractReceipt = await nftAccessCondition.fulfill(agreementId, did, grantee.getId()) const { state } = await conditionStoreManager.getCondition(conditionId) assert.equal(state, ConditionState.Fulfilled) diff --git a/test/keeper/conditions/NFTHolderCondition.test.ts b/test/keeper/conditions/NFTHolderCondition.test.ts index 91057dc2f..da3eef552 100644 --- a/test/keeper/conditions/NFTHolderCondition.test.ts +++ b/test/keeper/conditions/NFTHolderCondition.test.ts @@ -16,7 +16,7 @@ import { import { didZeroX, zeroX, generateId } from '../../../src/utils' import config from '../../config' import TestContractHandler from '../TestContractHandler' -import { ContractTransactionReceipt, EventLog } from 'ethers' +import { EventLog } from 'ethers' chai.use(chaiAsPromised) @@ -101,7 +101,7 @@ describe('NFTHolderCondition', () => { await nftUpgradeable.mint(holder.getId(), did, 10n, owner.getId()) - const contractReceipt: ContractTransactionReceipt = await nftHolderCondition.fulfill( + const contractReceipt = await nftHolderCondition.fulfill( agreementId, did, holder.getId(), diff --git a/test/keeper/conditions/TransferDIDOwnershipCondition.test.ts b/test/keeper/conditions/TransferDIDOwnershipCondition.test.ts index 88490aa47..19f83eb53 100644 --- a/test/keeper/conditions/TransferDIDOwnershipCondition.test.ts +++ b/test/keeper/conditions/TransferDIDOwnershipCondition.test.ts @@ -12,7 +12,7 @@ import { import { didZeroX, zeroX, generateId } from '../../../src/utils' import config from '../../config' import TestContractHandler from '../TestContractHandler' -import { ContractTransactionReceipt, EventLog } from 'ethers' +import { EventLog } from 'ethers' chai.use(chaiAsPromised) @@ -117,8 +117,12 @@ describe('TransferDIDOwnershipCondition', () => { const storedDIDRegister: any = await didRegistry.getDIDRegister(did) assert.equal(storedDIDRegister.owner, owner.getId()) - const contractReceipt: ContractTransactionReceipt = - await transferDidOwnershipCondition.fulfill(agreementId, did, receiver.getId(), owner) + const contractReceipt = await transferDidOwnershipCondition.fulfill( + agreementId, + did, + receiver.getId(), + owner, + ) const { state } = await conditionStoreManager.getCondition(conditionId) assert.equal(state, ConditionState.Fulfilled) diff --git a/test/keeper/conditions/TransferNFTCondition.test.ts b/test/keeper/conditions/TransferNFTCondition.test.ts index becb3f84e..3462a3364 100644 --- a/test/keeper/conditions/TransferNFTCondition.test.ts +++ b/test/keeper/conditions/TransferNFTCondition.test.ts @@ -19,7 +19,7 @@ import { import { didZeroX, ZeroAddress, zeroX, generateId } from '../../../src/utils' import config from '../../config' import TestContractHandler from '../TestContractHandler' -import { ContractTransactionReceipt, EventLog } from 'ethers' +import { EventLog } from 'ethers' chai.use(chaiAsPromised) @@ -152,7 +152,7 @@ describe('TransferNFTCondition', () => { ) await nevermined.nfts1155.mint(did, nftAmount, owner.getId(), owner) - await nftReceiver.requestTokens(10) + await nevermined.accounts.requestTokens(nftReceiver, 10n) await nevermined.keeper.token.approve(lockPaymentCondition.address, 10n, nftReceiver) await lockPaymentCondition.fulfill( @@ -179,7 +179,7 @@ describe('TransferNFTCondition', () => { await conditionStoreManager.createCondition(conditionId, transferNftCondition.address, owner) - const contractReceipt: ContractTransactionReceipt = await transferNftCondition.fulfill( + const contractReceipt = await transferNftCondition.fulfill( agreementId, did, nftReceiver.getId(), @@ -282,7 +282,7 @@ describe('TransferNFTCondition', () => { await conditionStoreManager.createCondition(conditionId, transferNftCondition.address, owner) - const contractReceipt: ContractTransactionReceipt = await transferNftCondition.fulfill( + const contractReceipt = await transferNftCondition.fulfill( agreementId, did, nftReceiver.getId(), @@ -359,7 +359,7 @@ describe('TransferNFTCondition', () => { ) await nevermined.nfts1155.mint(did, nftAmount, owner.getId(), owner) - await nftReceiver.requestTokens(10) + await nevermined.accounts.requestTokens(nftReceiver, 10n) await nevermined.keeper.token.approve(lockPaymentCondition.address, 10n, nftReceiver) await lockPaymentCondition.fulfill( @@ -395,6 +395,7 @@ describe('TransferNFTCondition', () => { nftUpgradeable.address, conditionIdPayment, true, + 0, other, ), ) diff --git a/test/keeper/templates/NFTSalesTemplate.test.ts b/test/keeper/templates/NFTSalesTemplate.test.ts index 9a0120ba5..220a76f54 100644 --- a/test/keeper/templates/NFTSalesTemplate.test.ts +++ b/test/keeper/templates/NFTSalesTemplate.test.ts @@ -11,7 +11,6 @@ import { import { didZeroX, zeroX, generateId } from '../../../src/utils' import config from '../../config' import TestContractHandler from '../TestContractHandler' -import { ContractTransactionReceipt, EventLog } from 'ethers' chai.use(chaiAsPromised) @@ -110,7 +109,7 @@ describe('NFTSalesTemplate', () => { await didRegistry.registerAttribute(didSeed, checksum, [], url, sender.getId()) const did = await didRegistry.hashDID(didSeed, sender.getId()) - const contractReceipt: ContractTransactionReceipt = await nftSalesTemplate.createAgreement( + const txHash = await nftSalesTemplate.createAgreement( agreementIdSeed, didZeroX(did), conditionIdSeeds, @@ -119,13 +118,32 @@ describe('NFTSalesTemplate', () => { [receiver.getId()], sender, ) - assert.equal(contractReceipt.status, 1) - assert.isTrue(contractReceipt.logs.some((e: EventLog) => e.eventName === 'AgreementCreated')) + const tx = await nevermined.client.public.waitForTransactionReceipt({ + hash: txHash.transactionHash, + }) + assert.equal(tx.status, 'success') - const event: EventLog = contractReceipt.logs.find( - (e: EventLog) => e.eventName === 'AgreementCreated', - ) as EventLog - const { _agreementId, _did } = event.args + const logs = nftSalesTemplate.getTransactionLogs(tx, 'AgreementCreated') + assert.isTrue(logs.length > 0) + const e = nftSalesTemplate.someLog(logs) + const _agreementId = e.args['_agreementId'] + const _did = e.args['_did'] + // logs.some((log) => { + // // @ts-expect-error "viem, wtf?" + // assert.equal(log.args['_agreementId'], zeroX(agreementId)) + // // @ts-expect-error "viem, wtf?" + // assert.equal(log.args['_did'], didZeroX(did)) + // }) + // nftSalesTemplate.decodeLog(tx.logs) + // const event = tx.logs[0] + // event. + // const _agreementId = event.args['_agreementId'] + //assert.isTrue(contractReceipt.logs.some((e: EventLog) => e.eventName === 'AgreementCreated')) + + // const event: EventLog = contractReceipt.logs.find( + // (e: EventLog) => e.eventName === 'AgreementCreated', + // ) as EventLog + // const { _agreementId, _did } = event.args assert.equal(_agreementId, zeroX(agreementId)) assert.equal(_did, didZeroX(did)) diff --git a/test/mocks/ContractBase.Mock.ts b/test/mocks/ContractBase.Mock.ts index 7c093dea7..e62123f62 100644 --- a/test/mocks/ContractBase.Mock.ts +++ b/test/mocks/ContractBase.Mock.ts @@ -1,9 +1,9 @@ -import { ethers } from 'ethers' import { ContractEvent, EventHandler } from '../../src/events' import { TxParameters, ContractBase } from '../../src/keeper' +import { parseAbi } from 'viem' export default class ContractBaseMock extends ContractBase { - public interface: ethers.Interface + public interface public async initMock(config: any) { await this.init(config) const eventEmitter = new EventHandler() @@ -11,9 +11,9 @@ export default class ContractBaseMock extends ContractBase { this, eventEmitter, this.nevermined, - + this.nevermined.client ) - this.interface = new ethers.Interface(['function name() view returns (string)']) + this.interface = parseAbi(['function name() view returns (string)']) } public async callMock(name: string, args: any[], from?: string) { diff --git a/test/nevermined/NvmAccount.test.ts b/test/nevermined/NvmAccount.test.ts index b52a27ad7..be2103448 100644 --- a/test/nevermined/NvmAccount.test.ts +++ b/test/nevermined/NvmAccount.test.ts @@ -7,6 +7,7 @@ import { NvmAccount, makeRandomWallet } from '../../src' // let nevermined: Nevermined describe('NvmAccount', () => { + console.log(`TEST!!!!`) before(async () => { // await TestContractHandler.prepareContracts() // nevermined = await Nevermined.getInstance(config) diff --git a/test/resources/proxy-poc/proxy.js b/test/resources/proxy-poc/proxy.js deleted file mode 100644 index 2a1694a8b..000000000 --- a/test/resources/proxy-poc/proxy.js +++ /dev/null @@ -1,75 +0,0 @@ -const http = require('http') -const httpProxy = require('http-proxy') -const jose = require('jose') - -const PROXY_PORT = 3128 - -const JWT_SECRET_PHRASE = process.env.JWT_SECRET_PHRASE || '12345678901234567890123456789012' -const JWT_SECRET = Uint8Array.from(JWT_SECRET_PHRASE.split('').map((x) => parseInt(x))) - -const validateAuthorization = async (authorizationHeader) => { - const token = authorizationHeader.split(' ')[1] - const { _header, payload } = await jose.jwtDecrypt(token, JWT_SECRET) - - return payload -} - -const main = async () => { - // Issue access token - // This should be done by nevermined one after it validated that a user has a valid subscription - - const token = await new jose.EncryptJWT({ - endpoints: ['http://127.0.0.1:3000'], - headers: [{ authorization: 'Bearer xxxxx' }], - }) - .setProtectedHeader({ alg: 'dir', enc: 'A128CBC-HS256' }) - .setIssuedAt() - .setExpirationTime('1d') - .encrypt(JWT_SECRET) - - console.log('Access token:\n\n', token) - - const proxy = httpProxy.createProxyServer() - const server = http.createServer(async function (req, res) { - console.log('proxying request', req.headers) - - // validate authorization header - let payload - try { - console.log(JSON.stringify(req.headers)) - payload = await validateAuthorization(req.headers['nvm-authorization']) - } catch (err) { - console.error(err) - res.writeHead(401) - res.end() - return - } - - // validate origin url is valid - const url = new URL(req.url) - - if (!payload.endpoints.includes(url.origin)) { - console.log(`${url.origin} not in ${payload.endpoints}`) - res.writeHead(401) - res.end() - return - } - - proxy.on('proxyReq', function (proxyReq, req, res, options) { - proxyReq.removeHeader('nvm-authorization') - payload.headers.forEach((header) => { - const key = Object.keys(header)[0] - proxyReq.setHeader(key, header[key]) - }) - }) - - proxy.web(req, res, { target: url.origin }) - }) - - console.log(`Proxy listening on port ${PROXY_PORT}`) - server.listen(PROXY_PORT) -} - -;(async () => { - await main() -})() diff --git a/test/resources/proxy-poc/web-service.js b/test/resources/proxy-poc/web-service.js deleted file mode 100644 index 3b1c66477..000000000 --- a/test/resources/proxy-poc/web-service.js +++ /dev/null @@ -1,19 +0,0 @@ -const express = require('express') -const app = express() -const port = 3000 - -app.get('/', (req, res) => { - console.log(req.headers) - res.send('Hello World!') -}) - -app.get('/sum', (req, res) => { - let a = Number(req.query.a) - let b = Number(req.query.b) - let result = `${a + b}` - res.send(result) -}) - -app.listen(port, () => { - console.log(`Example app listening on port ${port}`) -}) diff --git a/tsconfig.eslint.json b/tsconfig.eslint.json new file mode 100644 index 000000000..03f9752cc --- /dev/null +++ b/tsconfig.eslint.json @@ -0,0 +1,50 @@ +{ + "compilerOptions": { + "strict": true, + + "useDefineForClassFields": true, + // "noImplicitReturns": true, // Not enabled by default in `strict` mode. + // "useUnknownInCatchVariables": true, // TODO: This would normally be enabled in `strict` mode but would require some adjustments to the codebase. + // "noImplicitOverride": true, // Not enabled by default in `strict` mode. + "noUnusedLocals": true, // Not enabled by default in `strict` mode. + "noUnusedParameters": true, // Not enabled by default in `strict` mode. + // // "exactOptionalPropertyTypes": true, + + // "verbatimModuleSyntax": true, + + // JavaScript support + "allowJs": false, + "checkJs": false, + + "strictPropertyInitialization": false, + "strictNullChecks": false, + "useUnknownInCatchVariables": false, + "resolveJsonModule": true, + + "esModuleInterop": true, + "skipLibCheck": true, + "allowSyntheticDefaultImports": true, + "lib": [ + //["es2019", "ES2020", "ES2021.String", "ES2017", "ES6", "ES7", "DOM"], + "ES2022", // By using ES2022 we get access to the `.cause` property on `Error` instances. + "DOM" // We are adding `DOM` here to get the `fetch`, etc. types. This should be removed once these types are available via DefinitelyTyped. + ], + "declaration": true, + + // Language and environment + "moduleResolution": "Node", + "module": "CommonJS", + + "target": "ES2021", + "noImplicitAny": false, + "removeComments": true, + "experimentalDecorators": true, + "preserveConstEnums": true, + "outDir": "./dist/node/", + "rootDir": "./src/", + "sourceMap": true, + "typeRoots": ["node_modules/@types"] + }, + "include": ["src/**/*", "test/**/*.test.ts", "integration/**/*.test.ts"], + "exclude": ["node_modules"] +} diff --git a/tsconfig.json b/tsconfig.json index 151a36a34..88b5ecd7c 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -22,8 +22,6 @@ "resolveJsonModule": true, "esModuleInterop": true, - //"noEmit": true, // new - "skipLibCheck": true, "allowSyntheticDefaultImports": true, "lib": [ @@ -35,10 +33,9 @@ // Language and environment "moduleResolution": "Node", - "module": "CommonJS", - "target": "ES2021", + "target": "ES2021", "noImplicitAny": false, "removeComments": true, "experimentalDecorators": true, @@ -49,5 +46,5 @@ "typeRoots": ["node_modules/@types"] }, "include": ["src/**/*"], - "exclude": ["node_modules", "**/*.test.ts"] + "exclude": ["node_modules", "test/**/*"] }