Skip to content

Commit

Permalink
Export signature method (#208)
Browse files Browse the repository at this point in the history
* Export signature method

* Modify calling signTypedData by wallet client

* Upload pnpm-lock.yaml

* Export some types

* Refactor nftClient in order to better generate react sdk

* Fix test about nftClient

* Fix integration test

* Rename SignatureHelpParameter to PermissionSignatureRequest
  • Loading branch information
bonnie57 authored Jun 6, 2024
1 parent 9a94e68 commit 23c44a0
Show file tree
Hide file tree
Showing 19 changed files with 133 additions and 74 deletions.
2 changes: 1 addition & 1 deletion packages/core-sdk/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@story-protocol/core-sdk",
"version": "1.0.0-rc.13",
"version": "1.0.0-rc.14",
"description": "Story Protocol Core SDK",
"main": "dist/story-protocol-core-sdk.cjs.js",
"module": "dist/story-protocol-core-sdk.esm.js",
Expand Down
10 changes: 9 additions & 1 deletion packages/core-sdk/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ export { PermissionClient } from "./resources/permission";
export { LicenseClient } from "./resources/license";
export { DisputeClient } from "./resources/dispute";
export { NftClient } from "./resources/nftClient";
export { IPAccountClient } from "./resources/ipAccount";
export { RoyaltyClient } from "./resources/royalty";

export type { StoryConfig, SupportedChainIds } from "./types/config";
export type { TypedData } from "./types/common";
Expand All @@ -31,9 +33,11 @@ export type {
RegisterCommercialRemixPILRequest,
RegisterPILResponse,
AttachLicenseTermsRequest,
AttachLicenseTermsResponse,
LicenseTermsIdResponse,
MintLicenseTokensRequest,
MintLicenseTokensResponse,
LicenseTermsId,
} from "./types/resources/license";
export { PIL_TYPE } from "./types/resources/license";

Expand All @@ -46,7 +50,8 @@ export type {
SnapshotResponse,
ClaimableRevenueRequest,
ClaimableRevenueResponse,
RoyaltyVaultAddress,
ClaimRevenueRequest,
ClaimRevenueResponse,
} from "./types/resources/royalty";

export type {
Expand Down Expand Up @@ -86,3 +91,6 @@ export type {
PiLicenseTemplateGetLicenseTermsResponse,
IpAccountImplStateResponse,
} from "./abi/generated";

export { getPermissionSignature } from "./utils/sign";
export type { PermissionSignatureRequest } from "./types/common";
12 changes: 6 additions & 6 deletions packages/core-sdk/src/resources/ipAsset.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Hex, PublicClient, zeroAddress, Address, LocalAccount, zeroHash } from "viem";
import { Hex, PublicClient, zeroAddress, Address, zeroHash, WalletClient } from "viem";

import { chain, getAddress } from "../utils/utils";
import { SupportedChainIds } from "../types/config";
Expand Down Expand Up @@ -119,7 +119,7 @@ export class IPAssetClient {
ipId: ipIdAddress,
deadline: calculatedDeadline,
nonce: 1,
account: this.wallet.account as LocalAccount,
wallet: this.wallet as WalletClient,
chainId: chain[this.chainId],
permissions: [
{
Expand Down Expand Up @@ -385,7 +385,7 @@ export class IPAssetClient {
ipId: ipIdAddress,
deadline: calculatedDeadline,
nonce: 2,
account: this.wallet.account as LocalAccount,
wallet: this.wallet as WalletClient,
chainId: chain[this.chainId],
permissions: [
{
Expand Down Expand Up @@ -434,7 +434,7 @@ export class IPAssetClient {
ipId: ipIdAddress,
deadline: calculatedDeadline,
nonce: 1,
account: this.wallet.account as LocalAccount,
wallet: this.wallet as WalletClient,
chainId: chain[this.chainId],
permissions: [
{
Expand Down Expand Up @@ -518,7 +518,7 @@ export class IPAssetClient {
ipId: ipIdAddress,
deadline: calculatedDeadline,
nonce: 2,
account: this.wallet.account as LocalAccount,
wallet: this.wallet as WalletClient,
chainId: chain[this.chainId],
permissions: [
{
Expand Down Expand Up @@ -576,7 +576,7 @@ export class IPAssetClient {
ipId: ipIdAddress,
deadline: calculatedDeadline,
nonce: 1,
account: this.wallet.account as LocalAccount,
wallet: this.wallet as WalletClient,
chainId: chain[this.chainId],
permissions: [
{
Expand Down
10 changes: 7 additions & 3 deletions packages/core-sdk/src/resources/license.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ import {
MintLicenseTokensRequest,
MintLicenseTokensResponse,
PIL_TYPE,
AttachLicenseTermsResponse,
LicenseTermsId,
} from "../types/resources/license";
import { handleError } from "../utils/errors";
import { getLicenseTermByType } from "../utils/getLicenseTermsByType";
Expand Down Expand Up @@ -157,7 +159,9 @@ export class LicenseClient {
* @param request.txOptions [Optional] The transaction options.
* @returns A Promise that resolves to an object containing the transaction hash.
*/
public async attachLicenseTerms(request: AttachLicenseTermsRequest) {
public async attachLicenseTerms(
request: AttachLicenseTermsRequest,
): Promise<AttachLicenseTermsResponse> {
try {
request.licenseTermsId = BigInt(request.licenseTermsId);
const isRegistered = await this.ipAssetRegistryClient.isRegistered({
Expand Down Expand Up @@ -193,7 +197,7 @@ export class LicenseClient {
});
if (request.txOptions?.waitForTransaction) {
await this.rpcClient.waitForTransactionReceipt({ hash: txHash });
return { txHash: txHash };
return { txHash: txHash, success: true };
} else {
return { txHash: txHash };
}
Expand Down Expand Up @@ -289,7 +293,7 @@ export class LicenseClient {
* @returns A Promise that resolves to an object containing the PILTerms associate with the given ID.
*/
public async getLicenseTerms(
selectedLicenseTermsId: string | number | bigint,
selectedLicenseTermsId: LicenseTermsId,
): Promise<PiLicenseTemplateGetLicenseTermsResponse> {
try {
return await this.piLicenseTemplateReadOnlyClient.getLicenseTerms({
Expand Down
11 changes: 5 additions & 6 deletions packages/core-sdk/src/resources/nftClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,10 +32,9 @@ export class NftClient {
* @returns A Promise that resolves to a CreateNFTCollectionResponse containing the transaction hash and collection address.
* @emits CollectionCreated (nftContract);
*/
public async createNFTCollection<
TReq extends CreateNFTCollectionRequest,
TRes = CreateNFTCollectionResponse<TReq>,
>(request: TReq): Promise<TRes> {
public async createNFTCollection(
request: CreateNFTCollectionRequest,
): Promise<CreateNFTCollectionResponse> {
try {
if (
request.mintFee !== undefined &&
Expand All @@ -61,9 +60,9 @@ export class NftClient {
return {
txHash: txHash,
nftContract: targetLogs[0].nftContract,
} as TRes;
};
}
return { txHash: txHash } as TRes;
return { txHash: txHash };
} catch (error) {
handleError(error, "Failed to create a SPG NFT collection");
}
Expand Down
6 changes: 3 additions & 3 deletions packages/core-sdk/src/resources/permission.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { PublicClient, encodeFunctionData, Address, LocalAccount, toFunctionSelector } from "viem";
import { PublicClient, encodeFunctionData, Address, toFunctionSelector, WalletClient } from "viem";

import { handleError } from "../utils/errors";
import {
Expand Down Expand Up @@ -129,7 +129,7 @@ export class PermissionClient {
},
],
chainId: chain[this.chainId],
account: this.wallet.account as LocalAccount,
wallet: this.wallet as WalletClient,
});
const txHash = await ipAccountClient.executeWithSig({
to: getAddress(this.accessControllerClient.address, "accessControllerClientAddress"),
Expand Down Expand Up @@ -265,7 +265,7 @@ export class PermissionClient {
nonce,
permissions,
chainId: chain[this.chainId],
account: this.wallet.account as LocalAccount,
wallet: this.wallet as WalletClient,
permissionFunc: "setBatchPermissions",
});
const txHash = await ipAccountClient.executeWithSig({
Expand Down
5 changes: 2 additions & 3 deletions packages/core-sdk/src/resources/royalty.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Hex, PublicClient, encodeFunctionData } from "viem";
import { Address, Hex, PublicClient, encodeFunctionData } from "viem";

import { handleError } from "../utils/errors";
import {
Expand All @@ -8,7 +8,6 @@ import {
CollectRoyaltyTokensResponse,
PayRoyaltyOnBehalfRequest,
PayRoyaltyOnBehalfResponse,
RoyaltyVaultAddress,
SnapshotRequest,
SnapshotResponse,
ClaimRevenueRequest,
Expand Down Expand Up @@ -255,7 +254,7 @@ export class RoyaltyClient {
* @param royaltyVaultIpId the id of the royalty vault.
* @returns A Promise that resolves to an object containing the royalty vault address.
*/
public async getRoyaltyVaultAddress(royaltyVaultIpId: Hex): Promise<RoyaltyVaultAddress> {
public async getRoyaltyVaultAddress(royaltyVaultIpId: Hex): Promise<Address> {
const isRoyaltyVaultIpIdRegistered = await this.ipAssetRegistryClient.isRegistered({
id: getAddress(royaltyVaultIpId, "royaltyVaultIpId"),
});
Expand Down
14 changes: 14 additions & 0 deletions packages/core-sdk/src/types/common.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,18 @@
import { Address, WalletClient } from "viem";

import { SetPermissionsRequest } from "./resources/permission";

export type TypedData = {
interface: string; // i.e. "(address,uint256)"
data: unknown[];
};

export type PermissionSignatureRequest = {
ipId: Address;
nonce: number | bigint;
deadline: bigint;
wallet: WalletClient;
chainId: bigint;
permissions: Omit<SetPermissionsRequest, "txOptions">[];
permissionFunc?: "setPermission" | "setBatchPermissions";
};
9 changes: 8 additions & 1 deletion packages/core-sdk/src/types/resources/license.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ export type RegisterCommercialUsePILRequest = {
};

export type RegisterCommercialRemixPILRequest = {
mintingFee: string;
mintingFee: string | number | bigint;
commercialRevShare: number;
currency: Address;
txOptions?: TxOptions;
Expand All @@ -62,6 +62,11 @@ export type AttachLicenseTermsRequest = {
txOptions?: TxOptions;
};

export type AttachLicenseTermsResponse = {
txHash: string;
success?: boolean;
};

export type MintLicenseTokensRequest = {
licensorIpId: Address;
licenseTermsId: string | number | bigint;
Expand All @@ -81,3 +86,5 @@ export enum PIL_TYPE {
COMMERCIAL_USE,
COMMERCIAL_REMIX,
}

export type LicenseTermsId = string | number | bigint;
5 changes: 1 addition & 4 deletions packages/core-sdk/src/types/resources/nftClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,4 @@ export type CreateNFTCollectionRequest = {
txOptions?: TxOptions;
};

export type CreateNFTCollectionResponse<TReq extends CreateNFTCollectionRequest> =
TReq["txOptions"] extends { waitForTransaction: true }
? { txHash: string; nftContract: Hex }
: { txHash: string; nftContract?: Hex };
export type CreateNFTCollectionResponse = { txHash: string; nftContract?: Hex };
2 changes: 0 additions & 2 deletions packages/core-sdk/src/types/resources/royalty.ts
Original file line number Diff line number Diff line change
Expand Up @@ -83,5 +83,3 @@ export type SnapshotResponse = {
txHash: string;
snapshotId?: bigint;
};

export type RoyaltyVaultAddress = Address;
46 changes: 23 additions & 23 deletions packages/core-sdk/src/utils/sign.ts
Original file line number Diff line number Diff line change
@@ -1,30 +1,29 @@
import {
Address,
ContractFunctionName,
Hex,
LocalAccount,
PrivateKeyAccount,
encodeFunctionData,
toFunctionSelector,
} from "viem";
import { Hex, encodeFunctionData, toFunctionSelector } from "viem";

import { accessControllerAbi, accessControllerAddress } from "../abi/generated";
import { getAddress } from "./utils";
import { SetPermissionsRequest } from "../types/resources/permission";
import { defaultFunctionSelector } from "../constants/common";
import { PermissionSignatureRequest } from "../types/common";

export const getPermissionSignature = async (params: {
ipId: Address;
nonce: number | bigint;
deadline: bigint;
account: LocalAccount | PrivateKeyAccount;
chainId: bigint;
permissions: Omit<SetPermissionsRequest, "txOptions">[];
permissionFunc?: ContractFunctionName<typeof accessControllerAbi>;
}): Promise<Hex> => {
const { ipId, deadline, nonce, account, chainId, permissions, permissionFunc } = params;
if (!account.signTypedData) {
throw new Error("The account does not support signTypedData, Please use a local account.");
/**
* Get the signature for setting permissions.
* @param param - The parameter object containing necessary data to get the signature.
* @param param.ipId - The IP ID.
* @param param.deadline - The deadline.
* @param param.nonce - The nonce.
* @param param.wallet - The wallet client.
* @param param.chainId - The chain ID.
* @param param.permissions - The permissions.
* @param param.permissionFunc - The permission function,default function is setPermission.
* @returns A Promise that resolves to the signature.
*/
export const getPermissionSignature = async (param: PermissionSignatureRequest): Promise<Hex> => {
const { ipId, deadline, nonce, wallet, chainId, permissions, permissionFunc } = param;
if (!wallet.signTypedData) {
throw new Error("The wallet client does not support signTypedData, please try again.");
}
if (!wallet.account) {
throw new Error("The wallet client does not have an account, please try again.");
}
const permissionFunction = permissionFunc ? permissionFunc : "setPermission";
const data = encodeFunctionData({
Expand All @@ -49,7 +48,8 @@ export const getPermissionSignature = async (params: {
})),
],
});
return await account.signTypedData({
return await wallet.signTypedData({
account: wallet.account,
domain: {
name: "Story Protocol IP Account",
version: "1",
Expand Down
16 changes: 12 additions & 4 deletions packages/core-sdk/test/integration/ipAccount.test.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,22 @@
import chai from "chai";
import chaiAsPromised from "chai-as-promised";
import { AccessPermission, StoryClient } from "../../src";
import { MockERC721, getStoryClientInSepolia, getTokenId, sepoliaChainId } from "./utils/util";
import { AccessPermission, StoryClient, getPermissionSignature } from "../../src";
import {
MockERC721,
getStoryClientInSepolia,
getTokenId,
sepoliaChainId,
walletClient,
} from "./utils/util";
import { Hex, encodeFunctionData, getAddress, toFunctionSelector } from "viem";
import {
accessControllerAbi,
accessControllerAddress,
coreMetadataModuleAddress,
} from "../../src/abi/generated";
import { privateKeyToAccount } from "viem/accounts";
import { getDeadline, getPermissionSignature } from "../../src/utils/sign";
import { getDeadline } from "../../src/utils/sign";

chai.use(chaiAsPromised);
const expect = chai.expect;
const coreMetadataModule = coreMetadataModuleAddress[sepoliaChainId];
Expand Down Expand Up @@ -60,6 +67,7 @@ describe("Ip Account functions", () => {
const deadline = getDeadline(60000n);
const signature = await getPermissionSignature({
ipId,
wallet: walletClient,
permissions: [
{
ipId: ipId,
Expand All @@ -70,7 +78,7 @@ describe("Ip Account functions", () => {
},
],
nonce: expectedState,
account,

chainId: BigInt(sepoliaChainId),
deadline: deadline,
});
Expand Down
3 changes: 1 addition & 2 deletions packages/core-sdk/test/integration/ipAsset.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -133,13 +133,12 @@ describe("IP Asset Functions ", () => {
name: "test-collection",
symbol: "TEST",
maxSupply: 100,
mintCost: 0n,
txOptions: {
waitForTransaction: true,
},
});
expect(txData.nftContract).to.be.a("string").and.not.empty;
nftContract = txData.nftContract;
nftContract = txData.nftContract!;
});

describe("should not throw error when mint and register ip and attach pil terms", async () => {
Expand Down
Loading

0 comments on commit 23c44a0

Please sign in to comment.