Skip to content

Commit 46a90d1

Browse files
authored
Merge pull request #437 from storyprotocol/feat/updating-ip-metadata-url
Update ip metadata url
2 parents cf8f7a6 + c82b54d commit 46a90d1

File tree

7 files changed

+92
-17
lines changed

7 files changed

+92
-17
lines changed

packages/core-sdk/src/client.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -170,7 +170,7 @@ export class StoryClient {
170170
*/
171171
public get ipAccount(): IPAccountClient {
172172
if (this._ipAccount === null) {
173-
this._ipAccount = new IPAccountClient(this.rpcClient, this.wallet);
173+
this._ipAccount = new IPAccountClient(this.rpcClient, this.wallet, this.chainId);
174174
}
175175

176176
return this._ipAccount;

packages/core-sdk/src/resources/ipAccount.ts

Lines changed: 43 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,32 @@
1-
import { Address, PublicClient } from "viem";
1+
import { Address, Hex, encodeFunctionData, PublicClient } from "viem";
22

33
import {
44
IPAccountExecuteRequest,
55
IPAccountExecuteResponse,
66
IPAccountExecuteWithSigRequest,
77
IPAccountExecuteWithSigResponse,
88
IpAccountStateResponse,
9+
SetIpMetadataRequest,
910
TokenResponse,
1011
} from "../types/resources/ipAccount";
1112
import { handleError } from "../utils/errors";
12-
import { IpAccountImplClient, SimpleWalletClient } from "../abi/generated";
13-
import { getAddress } from "../utils/utils";
13+
import {
14+
coreMetadataModuleAbi,
15+
coreMetadataModuleAddress,
16+
IpAccountImplClient,
17+
SimpleWalletClient,
18+
} from "../abi/generated";
19+
import { getAddress, validateAddress } from "../utils/utils";
20+
import { ChainIds } from "../types/config";
1421

1522
export class IPAccountClient {
1623
private readonly wallet: SimpleWalletClient;
1724
private readonly rpcClient: PublicClient;
18-
19-
constructor(rpcClient: PublicClient, wallet: SimpleWalletClient) {
25+
private readonly chainId: ChainIds;
26+
constructor(rpcClient: PublicClient, wallet: SimpleWalletClient, chainId: ChainIds) {
2027
this.wallet = wallet;
2128
this.rpcClient = rpcClient;
29+
this.chainId = chainId;
2230
}
2331

2432
/** Executes a transaction from the IP Account.
@@ -150,4 +158,34 @@ export class IPAccountClient {
150158
handleError(error, "Failed to get the token");
151159
}
152160
}
161+
/**
162+
* Sets the metadataURI for an IP asset.
163+
*/
164+
public async setIpMetadata({
165+
ipId,
166+
metadataURI,
167+
metadataHash,
168+
txOptions,
169+
}: SetIpMetadataRequest): Promise<Hex> {
170+
try {
171+
const data = encodeFunctionData({
172+
abi: coreMetadataModuleAbi,
173+
functionName: "setMetadataURI",
174+
args: [validateAddress(ipId), metadataURI, metadataHash],
175+
});
176+
const { txHash } = await this.execute({
177+
ipId: ipId,
178+
to: coreMetadataModuleAddress[this.chainId],
179+
data: data,
180+
value: 0,
181+
txOptions: {
182+
...txOptions,
183+
encodedTxDataOnly: false,
184+
},
185+
});
186+
return txHash!;
187+
} catch (error) {
188+
handleError(error, "Failed to set the IP metadata");
189+
}
190+
}
153191
}

packages/core-sdk/src/resources/royalty.ts

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,6 @@ import {
3333
SimpleWalletClient,
3434
WrappedIpClient,
3535
} from "../abi/generated";
36-
import { IPAccountClient } from "./ipAccount";
3736
import { getAddress, validateAddress, validateAddresses } from "../utils/utils";
3837
import { WIP_TOKEN_ADDRESS } from "../constants/common";
3938
import { contractCallWithFees } from "../utils/feeUtils";
@@ -43,7 +42,6 @@ import { simulateAndWriteContract } from "../utils/contract";
4342
export class RoyaltyClient {
4443
public royaltyModuleClient: RoyaltyModuleClient;
4544
public ipAssetRegistryClient: IpAssetRegistryClient;
46-
public ipAccountClient: IPAccountClient;
4745
public ipRoyaltyVaultImplReadOnlyClient: IpRoyaltyVaultImplReadOnlyClient;
4846
public ipRoyaltyVaultImplEventClient: IpRoyaltyVaultImplEventClient;
4947
public multicall3Client: Multicall3Client;
@@ -57,7 +55,6 @@ export class RoyaltyClient {
5755
this.ipAssetRegistryClient = new IpAssetRegistryClient(rpcClient, wallet);
5856
this.ipRoyaltyVaultImplReadOnlyClient = new IpRoyaltyVaultImplReadOnlyClient(rpcClient);
5957
this.ipRoyaltyVaultImplEventClient = new IpRoyaltyVaultImplEventClient(rpcClient);
60-
this.ipAccountClient = new IPAccountClient(rpcClient, wallet);
6158
this.multicall3Client = new Multicall3Client(rpcClient, wallet);
6259
this.wrappedIpClient = new WrappedIpClient(rpcClient, wallet);
6360
this.rpcClient = rpcClient;

packages/core-sdk/src/types/resources/ipAccount.ts

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ export type IPAccountExecuteRequest = {
1212
};
1313

1414
export type IPAccountExecuteResponse = {
15-
txHash?: string;
15+
txHash?: Hex;
1616
encodedTxData?: EncodedTxData;
1717
};
1818

@@ -28,7 +28,7 @@ export type IPAccountExecuteWithSigRequest = {
2828
};
2929

3030
export type IPAccountExecuteWithSigResponse = {
31-
txHash?: string;
31+
txHash?: Hex;
3232
encodedTxData?: EncodedTxData;
3333
};
3434

@@ -39,3 +39,12 @@ export type TokenResponse = {
3939
tokenContract: Address;
4040
tokenId: bigint;
4141
};
42+
43+
export type SetIpMetadataRequest = {
44+
ipId: Address;
45+
/** The metadataURI to set for the IP asset. */
46+
metadataURI: string;
47+
/** The hash of metadata at metadataURI. */
48+
metadataHash: Hex;
49+
txOptions?: Omit<TxOptions, "encodedTxDataOnly">;
50+
};

packages/core-sdk/test/integration/ipAccount.test.ts

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import chai from "chai";
22
import chaiAsPromised from "chai-as-promised";
33
import { AccessPermission, StoryClient } from "../../src";
44
import { mockERC721, getStoryClient, getTokenId, aeneid } from "./utils/util";
5-
import { Hex, encodeFunctionData, getAddress, toFunctionSelector } from "viem";
5+
import { Hex, encodeFunctionData, getAddress, toFunctionSelector, toHex } from "viem";
66
import {
77
accessControllerAbi,
88
accessControllerAddress,
@@ -150,4 +150,13 @@ describe("IPAccount Functions", () => {
150150
.rejected;
151151
});
152152
});
153+
154+
it("should successfully set ip metadata", async () => {
155+
const txHash = await client.ipAccount.setIpMetadata({
156+
ipId: ipId,
157+
metadataURI: "https://example.com",
158+
metadataHash: toHex("test", { size: 32 }),
159+
});
160+
expect(txHash).to.be.a("string").and.not.empty;
161+
});
153162
});
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
export const txHash = "0x063834efe214f4199b1ad7181ce8c5ced3e15d271c8e866da7c89e86ee629cfb";
22
export const ipId = "0x73fcb515cee99e4991465ef586cfe2b072ebb512";
3-
export const aeneid = 13_15;
3+
export const aeneid = "1315";
44
export const mockERC20 = "0x73fcb515cee99e4991465ef586cfe2b072ebb512";
55
export const walletAddress = "0x73fcb515cee99e4991465ef586cfe2b072ebb512";

packages/core-sdk/test/unit/resources/ipAccount.test.ts

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,20 +4,20 @@ import * as sinon from "sinon";
44
import { IPAccountClient } from "../../../src/resources/ipAccount";
55
import { IPAccountExecuteRequest, IPAccountExecuteWithSigRequest } from "../../../src";
66
import * as utils from "../../../src/utils/utils";
7-
import { Account, PublicClient, WalletClient, zeroAddress } from "viem";
8-
const { IpAccountImplClient } = require("../../../src/abi/generated");
7+
import { Account, PublicClient, toHex, WalletClient, zeroAddress } from "viem";
8+
import { aeneid, ipId, txHash } from "../mockData";
9+
import { IpAccountImplClient } from "../../../src/abi/generated";
910

1011
describe("Test IPAccountClient", () => {
1112
let ipAccountClient: IPAccountClient;
1213
let rpcMock: PublicClient;
1314
let walletMock: WalletClient;
14-
const txHash = "0x129f7dd802200f096221dd89d5b086e4bd3ad6eafb378a0c75e3b04fc375f997";
1515
beforeEach(() => {
1616
rpcMock = createMock<PublicClient>();
1717
walletMock = createMock<WalletClient>();
1818
const accountMock = createMock<Account>();
1919
walletMock.account = accountMock;
20-
ipAccountClient = new IPAccountClient(rpcMock, walletMock);
20+
ipAccountClient = new IPAccountClient(rpcMock, walletMock, aeneid);
2121
sinon.stub(IpAccountImplClient.prototype, "execute").resolves(txHash);
2222
sinon.stub(IpAccountImplClient.prototype, "executeEncode").returns({ data: "0x", to: "0x" });
2323
sinon.stub(IpAccountImplClient.prototype, "executeWithSig").resolves(txHash);
@@ -195,4 +195,26 @@ describe("Test IPAccountClient", () => {
195195
expect(token).to.deep.equal({ chainId: 1513n, tokenContract: zeroAddress, tokenId: 1n });
196196
});
197197
});
198+
199+
describe("Test setIpMetadata", () => {
200+
it("should throw error when call setIpMetadata given wrong ipId", async () => {
201+
try {
202+
await ipAccountClient.setIpMetadata({
203+
ipId: "0x",
204+
metadataURI: "https://example.com",
205+
metadataHash: toHex("test", { size: 32 }),
206+
});
207+
} catch (err) {
208+
expect((err as Error).message).equal("Failed to set the IP metadata: Invalid address: 0x.");
209+
}
210+
});
211+
it("should return txHash when call setIpMetadata successfully", async () => {
212+
const result = await ipAccountClient.setIpMetadata({
213+
ipId: ipId,
214+
metadataURI: "https://example.com",
215+
metadataHash: toHex("test", { size: 32 }),
216+
});
217+
expect(result).to.equal(txHash);
218+
});
219+
});
198220
});

0 commit comments

Comments
 (0)