Skip to content

Commit

Permalink
Merge pull request #241 from storyprotocol/dev
Browse files Browse the repository at this point in the history
add generateIpMetadata and generateCreatorMetadata (#238)
  • Loading branch information
edisonz0718 authored Aug 27, 2024
2 parents cedf6f4 + 53e8b7a commit 6c4e04f
Show file tree
Hide file tree
Showing 28 changed files with 8,173 additions and 6,136 deletions.
2 changes: 0 additions & 2 deletions packages/core-sdk/.env.example

This file was deleted.

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.19",
"version": "1.0.0-rc.20",
"description": "Story Protocol Core SDK",
"main": "dist/story-protocol-core-sdk.cjs.js",
"module": "dist/story-protocol-core-sdk.esm.js",
Expand Down
157 changes: 152 additions & 5 deletions packages/core-sdk/src/resources/ipAsset.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import {
encodeFunctionData,
keccak256,
toFunctionSelector,
TransactionReceipt,
} from "viem";

import { chain, getAddress } from "../utils/utils";
Expand All @@ -18,6 +19,13 @@ import { handleError } from "../utils/errors";
import {
CreateIpAssetWithPilTermsRequest,
CreateIpAssetWithPilTermsResponse,
IpAttribute,
IpCreator,
IpCreatorSocial,
IpMedia,
IpMetadata,
IpRelationship,
IPRobotTerms,
MintAndRegisterIpAndMakeDerivativeRequest,
RegisterDerivativeRequest,
RegisterDerivativeResponse,
Expand All @@ -29,6 +37,7 @@ import {
RegisterIpAndMakeDerivativeResponse,
RegisterIpResponse,
RegisterRequest,
StoryProtocolApp,
} from "../types/resources/ipAsset";
import {
AccessControllerClient,
Expand Down Expand Up @@ -82,6 +91,133 @@ export class IPAssetClient {
this.chainId = chainId;
}

/**
* Create a new `IpCreator` object with the specified details.
* @param params - The parameters required to create the `IpCreator` object.
* @param params.name The name of the creator.
* @param params.address The wallet address of the creator.
* @param params.description [Optional] A description of the creator.
* @param params.image [Optional] The URL or path to an image representing the creator.
* @param params.socialMedia [Optional] An array of social media profiles associated with the creator.
* @param params.socialMedia[].platform The name of the social media platform.
* @param params.socialMedia[].url The URL to the creator's profile on the platform.
* @param params.contributionPercent The percentage of contribution by the creator, must add up to 100.
* @param params.role [Optional] The role of the creator in relation to the IP.
* @returns An `IpCreator` object containing the provided details.
*/
public generateCreatorMetadata({
name,
address,
description = "",
image = "",
socialMedia = [],
contributionPercent,
role = "",
}: {
name: string;
address: Address;
contributionPercent: number;
description?: string;
image?: string;
socialMedia?: IpCreatorSocial[];
role?: string;
}): IpCreator {
return {
name,
address,
description,
image,
socialMedia,
contributionPercent,
role,
};
}

/**
* Create a new `IpMetadata` object with the specified details.
* @param params - The parameters required to create the `IpMetadata` object.
* @param params.title [Optional] The title of the IP.
* @param params.description [Optional] A description of the IP.
* @param params.ipType [Optional] The type of the IP asset (e.g., "character", "chapter").
* @param params.relationships [Optional] An array of relationships between this IP and its parent IPs.
* @param params.relationships[].ipId The ID of the parent IP.
* @param params.relationships[].type The type of relationship (e.g., "APPEARS_IN").
* @param params.createdAt [Optional] The creation date and time of the IP in ISO 8601 format.
* @param params.watermarkImg [Optional] The URL or path to an image used as a watermark for the IP.
* @param params.creators [Optional] An array of creators associated with the IP.
* @param params.creators[].name The name of the creator.
* @param params.creators[].address The address of the creator.
* @param params.creators[].description [Optional] A description of the creator.
* @param params.creators[].image [Optional] The URL or path to an image representing the creator.
* @param params.creators[].socialMedia [Optional] An array of social media profiles for the creator.
* @param params.creators[].socialMedia[].platform The social media platform name.
* @param params.creators[].socialMedia[].url The URL to the creator's profile.
* @param params.creators[].role [Optional] The role of the creator in relation to the IP.
* @param params.creators[].contributionPercent The percentage of contribution by the creator.
* @param params.media [Optional] An array of media related to the IP.
* @param params.media[].name The name of the media.
* @param params.media[].url The URL to the media.
* @param params.media[].mimeType The MIME type of the media.
* @param params.attributes [Optional] An array of key-value pairs providing additional metadata.
* @param params.attributes[].key The key for the attribute.
* @param params.attributes[].value The value for the attribute, can be a string or number.
* @param params.app [Optional] Information about the application associated with the IP.
* @param params.app.id The ID of the application.
* @param params.app.name The name of the application.
* @param params.app.website The website URL of the application.
* @param params.tags [Optional] An array of tags associated with the IP.
* @param params.robotTerms [Optional] Robot terms for the IP, specifying access rules.
* @param params.robotTerms.userAgent The user agent for which the rules apply.
* @param params.robotTerms.allow The rules allowing access.
* @param params.additionalProperties [Optional] Any additional key-value pairs to include in the metadata.
* @returns An `IpMetadata` object containing the provided details and any additional properties.
*/
public generateIpMetadata({
title = "",
description = "",
ipType = "",
relationships = [],
createdAt = "",
watermarkImg = "",
creators = [],
media = [],
attributes = [],
app,
tags = [],
robotTerms,
...additionalProperties
}: {
title?: string;
description?: string;
ipType?: string;
relationships?: IpRelationship[];
createdAt?: string;
watermarkImg?: string;
creators?: IpCreator[];
media?: IpMedia[];
attributes?: IpAttribute[];
app?: StoryProtocolApp;
tags?: string[];
robotTerms?: IPRobotTerms;
additionalProperties?: { [key: string]: unknown };
}): IpMetadata {
return {
title,
description,
ipType,
relationships,
createdAt,
watermarkImg,
creators,
media,
attributes,
app,
tags,
robotTerms,
...additionalProperties, // Include any additional properties
};
}

/**
* Registers an NFT as IP, creating a corresponding IP record.
* @param request - The request object that contains all data needed to register IP.
Expand Down Expand Up @@ -354,9 +490,7 @@ export class IPAssetClient {
if (request.txOptions?.waitForTransaction) {
const txReceipt = await this.rpcClient.waitForTransactionReceipt({ hash: txHash });
const iPRegisteredLog = this.ipAssetRegistryClient.parseTxIpRegisteredEvent(txReceipt)[0];
const licenseTermsId =
this.licensingModuleClient.parseTxLicenseTermsAttachedEvent(txReceipt)[0]
.licenseTermsId;
const licenseTermsId = await this.getLicenseTermsId(txReceipt);
return {
txHash: txHash,
ipId: iPRegisteredLog.ipId,
Expand Down Expand Up @@ -480,8 +614,9 @@ export class IPAssetClient {
const txHash = await this.spgClient.registerIpAndAttachPilTerms(object);
if (request.txOptions?.waitForTransaction) {
const txReceipt = await this.rpcClient.waitForTransactionReceipt({ hash: txHash });
const log = this.licensingModuleClient.parseTxLicenseTermsAttachedEvent(txReceipt)[0];
return { txHash, licenseTermsId: log.licenseTermsId, ipId: log.ipId };
const ipRegisterEvent = this.ipAssetRegistryClient.parseTxIpRegisteredEvent(txReceipt);
const licenseTermsId = await this.getLicenseTermsId(txReceipt);
return { txHash, licenseTermsId: licenseTermsId, ipId: ipRegisterEvent[0].ipId };
}
return { txHash };
}
Expand Down Expand Up @@ -754,4 +889,16 @@ export class IPAssetClient {
);
return sigAttachState;
}
private async getLicenseTermsId(txReceipt: TransactionReceipt): Promise<bigint> {
const licensingModuleLicenseTermsAttachedEvent =
this.licensingModuleClient.parseTxLicenseTermsAttachedEvent(txReceipt);
let licenseTermsId =
licensingModuleLicenseTermsAttachedEvent.length >= 1 &&
licensingModuleLicenseTermsAttachedEvent[0].licenseTermsId;
if (licenseTermsId === false) {
const defaultLicenseTerms = await this.licenseRegistryReadOnlyClient.getDefaultLicenseTerms();
licenseTermsId = defaultLicenseTerms.licenseTermsId;
}
return licenseTermsId;
}
}
59 changes: 59 additions & 0 deletions packages/core-sdk/src/types/resources/ipAsset.ts
Original file line number Diff line number Diff line change
Expand Up @@ -113,3 +113,62 @@ export type MintAndRegisterIpAndMakeDerivativeRequest = {
nftMetadata?: string;
recipient?: Address;
} & IpMetadataAndTxOption;

export type IpRelationship = {
parentIpId: Address;
type: string;
};

export type IpCreator = {
name: string;
address: Address;
description?: string;
image?: string;
socialMedia?: IpCreatorSocial[];
role?: string;
contributionPercent: number; // add up to 100
};

export type IpCreatorSocial = {
platform: string;
url: string;
};

export type IpMedia = {
name: string;
url: string;
mimeType: string;
};

export type IpAttribute = {
key: string;
value: string | number;
};

export type StoryProtocolApp = {
id: string;
name: string;
website: string;
action?: string;
};

export type IPRobotTerms = {
userAgent: string;
allow: string;
};

export type IpMetadata = {
title?: string;
description?: string;
ipType?: string;
relationships?: IpRelationship[];
createdAt?: string;
watermarkImg?: string;
creators?: IpCreator[];
media?: IpMedia[];
attributes?: IpAttribute[];
appInfo?: StoryProtocolApp[];
tags?: string[];
robotTerms?: IPRobotTerms;
[key: string]: unknown;
};
7 changes: 6 additions & 1 deletion packages/core-sdk/test/integration/ipAccount.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import chai from "chai";
import chaiAsPromised from "chai-as-promised";
import { AccessPermission, StoryClient } from "../../src";
import { mockERC721, getStoryClient, getTokenId, iliadChainId } from "./utils/util";
import { Hex, encodeFunctionData, getAddress, toFunctionSelector } from "viem";
import { Hex, encodeFunctionData, getAddress, toFunctionSelector, parseUnits } from "viem";
import {
accessControllerAbi,
accessControllerAddress,
Expand All @@ -26,6 +26,7 @@ describe("Ip Account functions", () => {
tokenId: tokenId!,
txOptions: {
waitForTransaction: true,
maxFeePerGas: parseUnits("100", 9),
},
});
ipId = registerResult.ipId!;
Expand All @@ -48,6 +49,10 @@ describe("Ip Account functions", () => {
value: 0,
data,
ipId: ipId,
txOptions: {
waitForTransaction: true,
maxFeePerGas: parseUnits("100", 9),
},
});
expect(response.txHash).to.be.a("string").and.not.empty;
});
Expand Down
Loading

0 comments on commit 6c4e04f

Please sign in to comment.