From 0e49232fa8f14a7d70681093de8cee1a925f0477 Mon Sep 17 00:00:00 2001 From: Leslie-57blocks Date: Thu, 29 Feb 2024 19:59:05 +0800 Subject: [PATCH] update code & add readme --- .nvmrc | 1 + README | 32 ++++++++++++++ config/mintAbi.json => abi/mintNFT.json | 0 package.json | 3 +- test/e2e/e2e.ts | 12 +++--- test/e2e/flows/flow1.ts | 19 +++++---- test/e2e/flows/flow2.ts | 19 +++++---- test/e2e/flows/flow3.ts | 8 ++-- test/e2e/flows/flow4.ts | 3 +- test/e2e/flows/flow5.ts | 24 +++++------ test/e2e/flows/flow6.ts | 43 +++++++------------ test/e2e/flows/flow7.ts | 16 +++++++ utils/utils.ts | 55 ++++++++++++++++++------- 13 files changed, 153 insertions(+), 82 deletions(-) create mode 100644 .nvmrc create mode 100644 README rename config/mintAbi.json => abi/mintNFT.json (100%) create mode 100644 test/e2e/flows/flow7.ts diff --git a/.nvmrc b/.nvmrc new file mode 100644 index 0000000..2a59cf4 --- /dev/null +++ b/.nvmrc @@ -0,0 +1 @@ +v20.0.0 diff --git a/README b/README new file mode 100644 index 0000000..9ddbdd6 --- /dev/null +++ b/README @@ -0,0 +1,32 @@ +# SDK-E2E-Tests + +This project dedicates to perform e2e test for the story protocol typescript sdk. + +## Prerequisites to run the e2e test + +- install nvm if don't have it by running: + + `curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.7/install.sh | bash`. + +- run `nvm use` to switch node version to v20.0.0 +- if you don't have v20.0.0 node installed, please install it by running: `nvm install v20.0.0` + +- run `npm i` to install dependencies. +- once all dependencies are installed, you should config your `.env` file with a reference to the `.env.example` file + +## How to run the test + +- Run specific test (recommend): + + run `npm run test:flow1` + +- Run all test together: + + run `npm run test` + +## How can I extend test flows to this project + +- wrap your test flow into a function and default export this function. +- put the new test file into `/test/e2e/flows` +- import the function from `/test/e2e/e2e.ts`, and register it into `flowsTestMap` +- extend the `scripts` field of the `/package.json` file with a reference to the existing other scrip command, and finally add the flow name to `TEST_FLOWS` in 'test' of the 'scripts' diff --git a/config/mintAbi.json b/abi/mintNFT.json similarity index 100% rename from config/mintAbi.json rename to abi/mintNFT.json diff --git a/package.json b/package.json index 3d69abd..2ce80d6 100644 --- a/package.json +++ b/package.json @@ -11,7 +11,8 @@ "test:flow4": "TEST_FLOWS=flow4 tsx test/e2e/e2e.ts", "test:flow5": "TEST_FLOWS=flow5 tsx test/e2e/e2e.ts", "test:flow6": "TEST_FLOWS=flow6 tsx test/e2e/e2e.ts", - "test:all": "TEST_FLOWS=flow1,flow2,flow3,flow4,flow5,flow6 tsx test/e2e/e2e.ts" + "test:flow7": "TEST_FLOWS=flow7 tsx test/e2e/e2e.ts", + "test": "TEST_FLOWS=flow1,flow2,flow3,flow4,flow5,flow6,flow7 tsx test/e2e/e2e.ts" }, "engines": { "node": "20.0.0" diff --git a/test/e2e/e2e.ts b/test/e2e/e2e.ts index e2ac155..861034a 100644 --- a/test/e2e/e2e.ts +++ b/test/e2e/e2e.ts @@ -4,10 +4,11 @@ import testFlow3 from './flows/flow3'; import testFlow4 from './flows/flow4'; import testFlow5 from './flows/flow5'; import testFlow6 from './flows/flow6'; +import testFlow7 from './flows/flow7'; type flowsTestMapType = { - [key: string]: Function -} + [key: string]: Function; +}; const flowsTestMap: flowsTestMapType = { flow1: testFlow1, flow2: testFlow2, @@ -15,9 +16,10 @@ const flowsTestMap: flowsTestMapType = { flow4: testFlow4, flow5: testFlow5, flow6: testFlow6, -} + flow7: testFlow7, +}; process.env.TEST_FLOWS?.split(',').forEach(async (flow: keyof flowsTestMapType) => { - if(flowsTestMap[flow]) { + if (flowsTestMap[flow]) { try { console.log(`testing ${flow}...`); await flowsTestMap[flow](); @@ -27,4 +29,4 @@ process.env.TEST_FLOWS?.split(',').forEach(async (flow: keyof flowsTestMapType) throw new Error(`${flow} failed with error: ${(err as Error).message}`); } } -}) \ No newline at end of file +}); diff --git a/test/e2e/flows/flow1.ts b/test/e2e/flows/flow1.ts index dfc626b..bc47319 100644 --- a/test/e2e/flows/flow1.ts +++ b/test/e2e/flows/flow1.ts @@ -1,18 +1,23 @@ import { Hex } from 'viem'; -import { mintNFT, registerRootIp, registerSocialRemixPolicy, registerDerivativeIP, mintLicense, sleep } from '../../../utils/utils'; +import { + mintNFT, + registerRootIp, + registerSocialRemixPolicy, + registerDerivativeIP, + mintLicense, + sleep, +} from '../../../utils/utils'; export default async function testFlow1() { - // const NFTIdOfA = await mintNFT('A'); - // const NFTIdOfB = await mintNFT('B'); + const NFTIdOfA = await mintNFT('A'); + const NFTIdOfB = await mintNFT('B'); const policyId = await registerSocialRemixPolicy(); - const NFTIdOfA = '200'; - const NFTIdOfB = '207'; await sleep(5); const ipId = (await registerRootIp(NFTIdOfA)) as Hex; await sleep(5); if (!ipId || !policyId) return; const licenseId = await mintLicense(ipId, policyId, 'B', 'A'); - await sleep(5); + await sleep(30); if (!licenseId) return; - registerDerivativeIP(NFTIdOfB, [licenseId], 'B'); + await registerDerivativeIP(NFTIdOfB, [licenseId], 'B'); } diff --git a/test/e2e/flows/flow2.ts b/test/e2e/flows/flow2.ts index becc86b..3c156f6 100644 --- a/test/e2e/flows/flow2.ts +++ b/test/e2e/flows/flow2.ts @@ -1,12 +1,17 @@ import { Hex } from 'viem'; -import { mintNFT, sleep, registerSocialRemixPolicy, registerRootIp, linkIpToParent, mintLicense } from '../../../utils/utils'; +import { + mintNFT, + sleep, + registerSocialRemixPolicy, + registerRootIp, + linkIpToParent, + mintLicense, +} from '../../../utils/utils'; export default async function testFlow2() { - // const NFTIdOfA = await mintNFT('A'); - // const NFTIdOfB = await mintNFT('B'); + const NFTIdOfA = await mintNFT('A'); + const NFTIdOfB = await mintNFT('B'); const policyId = await registerSocialRemixPolicy(); - const NFTIdOfA = '201'; - const NFTIdOfB = '208'; await sleep(5); const ipId = (await registerRootIp(NFTIdOfA)) as Hex; await sleep(5); @@ -15,6 +20,6 @@ export default async function testFlow2() { await sleep(5); if (!licenseId) return; const ipOfB = (await registerRootIp(NFTIdOfB, 'B')) as Hex; - await sleep(5); - linkIpToParent(ipOfB, [licenseId], 'B'); + await sleep(30); + await linkIpToParent(ipOfB, [licenseId], 'B'); } diff --git a/test/e2e/flows/flow3.ts b/test/e2e/flows/flow3.ts index e5aa91f..817f159 100644 --- a/test/e2e/flows/flow3.ts +++ b/test/e2e/flows/flow3.ts @@ -10,10 +10,8 @@ import { export default async function testFlow3() { const policyId = await registerSocialRemixPolicy(); - // const NFTIdOfA = await mintNFT('A'); - // const NFTIdOfB = await mintNFT('B'); - const NFTIdOfA = '202'; - const NFTIdOfB = '209'; + const NFTIdOfA = await mintNFT('A'); + const NFTIdOfB = await mintNFT('B'); await sleep(5); if (!policyId) return; const ipId = (await registerIpWithExistingPolicy(NFTIdOfA, policyId)) as Hex; @@ -21,5 +19,5 @@ export default async function testFlow3() { const licenseId = await mintLicense(ipId, policyId, 'B', 'A'); if (!licenseId) return; await sleep(5); - registerDerivativeIP(NFTIdOfB, [licenseId], 'B'); + await registerDerivativeIP(NFTIdOfB, [licenseId], 'B'); } diff --git a/test/e2e/flows/flow4.ts b/test/e2e/flows/flow4.ts index 647f10f..bb7f060 100644 --- a/test/e2e/flows/flow4.ts +++ b/test/e2e/flows/flow4.ts @@ -3,8 +3,7 @@ import { mintNFT, sleep, grantIp, registerSocialRemixPolicy, mintLicense, regist export default async function testFlow4() { const policyId = await registerSocialRemixPolicy(); - // const NFTIdOfA = await mintNFT('A'); - const NFTIdOfA = '204'; + const NFTIdOfA = await mintNFT('A'); await sleep(5); const ipId = (await registerRootIp(NFTIdOfA)) as Hex; await sleep(5); diff --git a/test/e2e/flows/flow5.ts b/test/e2e/flows/flow5.ts index 7338567..24169cb 100644 --- a/test/e2e/flows/flow5.ts +++ b/test/e2e/flows/flow5.ts @@ -8,28 +8,26 @@ import { mintLicense, } from '../../../utils/utils'; +// test royalty. +// You need to approve an amount of funds to the royalty policy contract in advance. export default async function testFlow5() { const policyId = await registerCommercialUsePolicy(); - // const NFTIdOfA = await mintNFT('A'); - // const NFTIdOfB = await mintNFT('B'); - // const NFTIdOfC = await mintNFT('C'); - const NFTIdOfA = '277'; - const NFTIdOfB = '272'; - const NFTIdOfC = '268'; + const NFTIdOfA = await mintNFT('A'); + const NFTIdOfB = await mintNFT('B'); + const NFTIdOfC = await mintNFT('C'); await sleep(5); - if (!policyId) return 1; - const ipIdOfA = (await registerIpWithExistingPolicy(NFTIdOfA, policyId, 'A')) as Hex; + const ipIdOfA = (await registerIpWithExistingPolicy(NFTIdOfA, policyId!, 'A')) as Hex; await sleep(5); - if (!ipIdOfA || !policyId) return 2; + if (!ipIdOfA || !policyId) return 'register root ip failed'; const licenseId = await mintLicense(ipIdOfA, policyId, 'B', 'B'); - await sleep(100); - if (!licenseId) return 3; + await sleep(60); + if (!licenseId) return 'wallet B mint license failed'; const ipIdOfB = (await registerDerivativeIP(NFTIdOfB, [licenseId], 'B')) as Hex; await sleep(5); const licenseIdFromA = await mintLicense(ipIdOfA, policyId, 'C', 'C'); const licenseIdFromB = await mintLicense(ipIdOfB, policyId, 'C', 'C'); - if (!licenseIdFromA || !licenseIdFromB) return 4; - await sleep(100); + if (!licenseIdFromA || !licenseIdFromB) return 'wallet C mint license failed'; + await sleep(60); await registerDerivativeIP(NFTIdOfC, [licenseIdFromA, licenseIdFromB], 'C'); } diff --git a/test/e2e/flows/flow6.ts b/test/e2e/flows/flow6.ts index 9bcbba1..b214eb9 100644 --- a/test/e2e/flows/flow6.ts +++ b/test/e2e/flows/flow6.ts @@ -12,19 +12,17 @@ import { registerDerivativeIP, } from '../../../utils/utils'; +// multiple policy export default async function testFlow6() { - // const NFTIdOfA = await mintNFT('A'); - // const NFTIdOfB = await mintNFT('B'); + const NFTIdOfA = await mintNFT('A'); + const NFTIdOfB1 = await mintNFT('B'); + const NFTIdOfB2 = await mintNFT('B'); + const NFTIdOfB3 = await mintNFT('B'); + const NFTIdOfB4 = await mintNFT('B'); const remixPolicyId1 = await registerSocialRemixPolicy(); const remixPolicyId2 = await registerSocialRemixPolicy2(); const remixPolicyId3 = await registerSocialRemixPolicy3(); const commercialPolicyId1 = await registerCommercialUsePolicy(); - const NFTIdOfA = '237'; - const NFTIdOfB1 = '234'; - const NFTIdOfB2 = '235'; - const NFTIdOfB3 = '228'; - const NFTIdOfB4 = '236'; - const NFTIdOfB5 = '230'; await sleep(5); const ipIdOfA = (await registerRootIp(NFTIdOfA)) as Hex; await sleep(5); @@ -36,24 +34,15 @@ export default async function testFlow6() { await sleep(5); const licenseId1 = await mintLicense(ipIdOfA, remixPolicyId1, 'B', 'A'); - await sleep(5); - if (!licenseId1) return; - registerDerivativeIP(NFTIdOfB1, [licenseId1], 'B'); - const licenseId2 = await mintLicense(ipIdOfA, remixPolicyId2, 'B', 'A'); - await sleep(5); - if (!licenseId2) return; - registerDerivativeIP(NFTIdOfB2, [licenseId2], 'B'); - - const licenseId3 = await mintLicense(ipIdOfA, remixPolicyId1, 'B', 'A'); - await sleep(5); - if (!licenseId3) return; - registerDerivativeIP(NFTIdOfB3, [licenseId1], 'B'); - - const licenseId4 = await mintLicense(ipIdOfA, commercialPolicyId1, 'B', 'A'); - await sleep(5); - if (!licenseId4) return; - registerDerivativeIP(NFTIdOfB4, [licenseId1], 'B'); - - registerDerivativeIP(NFTIdOfB5, [licenseId1, licenseId2], 'B'); + const licenseId3 = await mintLicense(ipIdOfA, remixPolicyId3, 'B', 'A'); + const licenseId4 = await mintLicense(ipIdOfA, commercialPolicyId1, 'B', 'B'); + await sleep(30); + if (!licenseId1 || !licenseId2 || !licenseId3 || !licenseId4) return; + await Promise.allSettled([ + registerDerivativeIP(NFTIdOfB1, [licenseId1], 'B'), + registerDerivativeIP(NFTIdOfB2, [licenseId2], 'B'), + registerDerivativeIP(NFTIdOfB3, [licenseId3], 'B'), + registerDerivativeIP(NFTIdOfB4, [licenseId4], 'B'), + ]); } diff --git a/test/e2e/flows/flow7.ts b/test/e2e/flows/flow7.ts new file mode 100644 index 0000000..a4c891f --- /dev/null +++ b/test/e2e/flows/flow7.ts @@ -0,0 +1,16 @@ +import { Hex } from 'viem'; +import { mintNFT, registerRootIp, registerDerivativeIP, mintLicense, sleep } from '../../../utils/utils'; + +// No policy should impossible to mint license +export default async function testFlow7() { + try { + const NFTIdOfA = await mintNFT('A'); + await sleep(5); + const ipId = (await registerRootIp(NFTIdOfA)) as Hex; + await sleep(5); + if (!ipId) return; + const licenseId = await mintLicense(ipId, '0', 'B', 'A'); + } catch (error) { + console.log('cannot mint license without policy, it is expected behavior'); + } +} diff --git a/utils/utils.ts b/utils/utils.ts index 104e836..7c398e5 100644 --- a/utils/utils.ts +++ b/utils/utils.ts @@ -1,4 +1,4 @@ -import { http, Hex } from "viem"; +import { http, Hex, createPublicClient } from 'viem'; import { PrivateKeyAccount } from 'viem/accounts'; import type { StoryConfig } from '@story-protocol/core-sdk'; import { sepolia } from 'viem/chains'; @@ -21,10 +21,31 @@ import { LICENSE_MODULE, RPC_URL, } from '../config/config'; +import mintNFTAbi from '../abi/mintNFT.json'; export type Who = 'A' | 'B' | 'C'; -export async function mintNFT(who: Who) { +const publicClient = createPublicClient({ + chain: sepolia, + transport: http(), +}); +export async function getNFTId(txHash: Hex) { + const { logs } = await publicClient.waitForTransactionReceipt({ + hash: txHash, + }); + if (logs[0].topics[3]) { + const tokenId = parseInt(logs[0].topics[3], 16); + return tokenId; + } + return 0; +} +function getWalletAddress(who: Who = 'A') { + let walletAddress = TEST_WALLET_A_ADDRESS; + if (who === 'B') walletAddress = TEST_WALLET_B_ADDRESS; + if (who === 'C') walletAddress = TEST_WALLET_C_ADDRESS; + return walletAddress; +} +export async function mintNFT(who: Who): Promise { let client = walletClientA; let account = accountA; if (who === 'B') { @@ -35,17 +56,20 @@ export async function mintNFT(who: Who) { client = walletClientC; account = accountC; } - const hash = await client.writeContract({ + const walletAddress = getWalletAddress(who); + const txHash = await client.writeContract({ account, - address: (NFT_CONTRACT_ADDRESS || '0x') as `0x${string}`, + address: NFT_CONTRACT_ADDRESS, chain: sepolia, - abi: [], - functionName: 'mint' as never, - args: [], + abi: mintNFTAbi, + functionName: 'mint', + args: [walletAddress], }); - - console.log('mintNFT', hash); - return '123'; + console.log('mintNFTHash:', txHash); + await sleep(5); + const tokenId = await getNFTId(txHash); + console.log(`tokenId of ${who}`, tokenId); + return String(tokenId); } function getStoryClient(who?: Who) { @@ -163,15 +187,16 @@ export const registerCommercialUsePolicy = async () => { return response.policyId; }; -export const addOnePolicyToIp = async (ipId: Hex, policyId: string) => { - const response = await storyClientA.policy.addPolicyToIp({ +export const addOnePolicyToIp = async (ipId: Hex, policyId: string, who: Who = 'A') => { + const storyClient = getStoryClient(who); + const response = await storyClient.policy.addPolicyToIp({ policyId, ipId, txOptions: { waitForTransaction: true, }, }); - console.log(`added policy ${policyId} to IP ${ipId}: `, response); + console.log(`added policy ${policyId} to IP ${ipId}, which belong to wallet ${who}: `, response); }; export const grantIp = async (ipId: Hex, receiver: Who = 'B', promoter: Who = 'A') => { @@ -203,7 +228,7 @@ export const mintLicense = async (ipId: Hex, policyId: string, receiver: Who = ' waitForTransaction: true, }, }); - console.log(`${promoter} mint license to ${receiver} derived from IP ${ipId}: `, response); + console.log(`${promoter} mint license with policy ${policyId} to ${receiver} derived from IP ${ipId}: `, response); return response.licenseId; }; @@ -231,4 +256,4 @@ export const registerDerivativeIP = async (tokenId: string, licenseIds: string[] }); console.log(`${who} RegisterDerivativeIP with licenses ${licenseIds}: `, response); return response.ipId; -}; \ No newline at end of file +};