Skip to content

Commit

Permalink
update code & add readme
Browse files Browse the repository at this point in the history
  • Loading branch information
leslie555 committed Feb 29, 2024
1 parent fb17497 commit 0e49232
Show file tree
Hide file tree
Showing 13 changed files with 153 additions and 82 deletions.
1 change: 1 addition & 0 deletions .nvmrc
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
v20.0.0
32 changes: 32 additions & 0 deletions README
Original file line number Diff line number Diff line change
@@ -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'
File renamed without changes.
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
12 changes: 7 additions & 5 deletions test/e2e/e2e.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,20 +4,22 @@ 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,
flow3: testFlow3,
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]();
Expand All @@ -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}`);
}
}
})
});
19 changes: 12 additions & 7 deletions test/e2e/flows/flow1.ts
Original file line number Diff line number Diff line change
@@ -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');
}
19 changes: 12 additions & 7 deletions test/e2e/flows/flow2.ts
Original file line number Diff line number Diff line change
@@ -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);
Expand All @@ -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');
}
8 changes: 3 additions & 5 deletions test/e2e/flows/flow3.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,16 +10,14 @@ 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;
await sleep(5);
const licenseId = await mintLicense(ipId, policyId, 'B', 'A');
if (!licenseId) return;
await sleep(5);
registerDerivativeIP(NFTIdOfB, [licenseId], 'B');
await registerDerivativeIP(NFTIdOfB, [licenseId], 'B');
}
3 changes: 1 addition & 2 deletions test/e2e/flows/flow4.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
24 changes: 11 additions & 13 deletions test/e2e/flows/flow5.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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');
}
43 changes: 16 additions & 27 deletions test/e2e/flows/flow6.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -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'),
]);
}
16 changes: 16 additions & 0 deletions test/e2e/flows/flow7.ts
Original file line number Diff line number Diff line change
@@ -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');
}
}
55 changes: 40 additions & 15 deletions utils/utils.ts
Original file line number Diff line number Diff line change
@@ -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';
Expand All @@ -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<string> {
let client = walletClientA;
let account = accountA;
if (who === 'B') {
Expand All @@ -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) {
Expand Down Expand Up @@ -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') => {
Expand Down Expand Up @@ -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;
};

Expand Down Expand Up @@ -231,4 +256,4 @@ export const registerDerivativeIP = async (tokenId: string, licenseIds: string[]
});
console.log(`${who} RegisterDerivativeIP with licenses ${licenseIds}: `, response);
return response.ipId;
};
};

0 comments on commit 0e49232

Please sign in to comment.