Skip to content

Commit 402252b

Browse files
authored
feat: auto-approve erc20 token (#658)
* test: enhance Erc20 Token Fee Utilities tests with new scenarios and assertions * feat: enhance contract fee handling with separate ERC20 and WIP payment methods * refactor: replace Erc20Spender with TokenSpender and integrate WIP token handling across multiple resources * feat: implement spender merging logic and enhance ERC20 payment handling in contract calls * refactor: streamline ERC20 payment handling and introduce token spender grouping logic * feat: enhance fee handle comments * Feat: Modify logic to auto approve in ipAsset module * refactor: update IPAssetClient to use unified options structure for WIP and ERC20 handling * feat: update RegisterIpAssetRequest and RegisterDerivativeIpAssetRequest to use unified ERC20 and WIP options; enhance fee handling tests for ERC20 integration * test: add integration tests for registering IP assets with WIP token, including derivative IP handling and license terms validation * feat: update IPAssetClient and tests to support mixed ERC20 and WIP token fees, enhancing fee calculation and registration workflows * fix: update documentation and types to replace `wipOptions` with `options` for consistency in IP asset handling * refactor: replace all instances of `wip` with `token` in imports and options for consistency across SDK resources * fix: update IPAssetClient to include erc20Options in transaction handling, ensuring proper fee management for public and private minting * refactor: streamline token handling in IPAssetClient and update documentation for clarity on erc20 and wrapped IP token usage * refactor: unify options handling in IPAssetClient and update response structures for royalty token distribution requests * refactor: enhance documentation and update variable names in IPAssetClient tests for clarity on ERC20 and WIP token usage * refactor: clean up imports and improve type formatting in license and registerHelper files for consistency * refactor: add comments for clarity on WIP token usage in dispute handling and improve type documentation for token spending * test * refactor: update options handling in IPAssetClient to disable multicall for WIP token registration and clean up test case for clarity
1 parent d8ee21e commit 402252b

File tree

17 files changed

+1629
-752
lines changed

17 files changed

+1629
-752
lines changed

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

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,6 @@ export class DisputeClient {
100100
} else {
101101
const contractCall = (): Promise<Hash> => this.disputeModuleClient.raiseDispute(req);
102102
const { txHash, receipt } = await contractCallWithFees({
103-
totalFees: bonds,
104103
options: {
105104
wipOptions: {
106105
...request.wipOptions,
@@ -114,6 +113,8 @@ export class DisputeClient {
114113
{
115114
address: this.arbitrationPolicyUmaClient.address,
116115
amount: bonds,
116+
// Currently, only WIP is supported as the whitelisted dispute bond token.
117+
token: WIP_TOKEN_ADDRESS,
117118
},
118119
],
119120
contractCall,
@@ -319,7 +320,6 @@ export class DisputeClient {
319320
};
320321

321322
const { txHash, receipt } = await contractCallWithFees({
322-
totalFees: bond,
323323
options: {
324324
wipOptions: {
325325
...request.wipOptions,
@@ -336,6 +336,8 @@ export class DisputeClient {
336336
{
337337
address: this.arbitrationPolicyUmaClient.address,
338338
amount: bond,
339+
// Currently, only WIP is supported as the whitelisted dispute bond token.
340+
token: WIP_TOKEN_ADDRESS,
339341
},
340342
],
341343
encodedTxs: [encodedData],

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

Lines changed: 103 additions & 105 deletions
Large diffs are not rendered by default.

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

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -47,8 +47,8 @@ import {
4747
SetMaxLicenseTokensRequest,
4848
} from "../types/resources/license";
4949
import { SignatureMethodType } from "../types/utils/registerHelper";
50-
import { Erc20Spender } from "../types/utils/wip";
51-
import { calculateLicenseWipMintFee, predictMintingLicenseFee } from "../utils/calculateMintFee";
50+
import { TokenSpender } from "../types/utils/token";
51+
import { calculateLicenseMintFee, predictMintingLicenseFee } from "../utils/calculateMintFee";
5252
import { handleError } from "../utils/errors";
5353
import { contractCallWithFees } from "../utils/feeUtils";
5454
import { generateOperationSignature } from "../utils/generateOperationSignature";
@@ -232,23 +232,22 @@ export class LicenseClient {
232232
}
233233

234234
// get license token minting fee
235-
const licenseMintingFee = await calculateLicenseWipMintFee({
235+
const licenseMintingFee = await calculateLicenseMintFee({
236236
predictMintingFeeRequest: req,
237237
rpcClient: this.rpcClient,
238238
chainId: this.chainId,
239239
walletAddress: this.walletAddress,
240240
});
241241

242-
const wipSpenders: Erc20Spender[] = [];
243-
if (licenseMintingFee > 0n) {
242+
const wipSpenders: TokenSpender[] = [];
243+
if (licenseMintingFee.amount > 0n) {
244244
wipSpenders.push({
245245
address: royaltyModuleAddress[this.chainId],
246-
amount: licenseMintingFee,
246+
...licenseMintingFee,
247247
});
248248
}
249249
const { txHash, receipt } = await contractCallWithFees({
250-
totalFees: licenseMintingFee,
251-
options: { wipOptions: request.options?.wipOptions },
250+
options: request.options,
252251
multicall3Address: this.multicall3Client.address,
253252
rpcClient: this.rpcClient,
254253
tokenSpenders: wipSpenders,

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

Lines changed: 5 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ import {
3838
TransferClaimedTokensFromIpToWalletParams,
3939
TransferToVaultRequest,
4040
} from "../types/resources/royalty";
41-
import { Erc20Spender } from "../types/utils/wip";
41+
import { TokenSpender } from "../types/utils/token";
4242
import { handleError } from "../utils/errors";
4343
import { contractCallWithFees } from "../utils/feeUtils";
4444
import { royaltyPolicyInputToAddress } from "../utils/royalty";
@@ -266,14 +266,7 @@ export class RoyaltyClient {
266266
request: PayRoyaltyOnBehalfRequest,
267267
): Promise<PayRoyaltyOnBehalfResponse> {
268268
try {
269-
const {
270-
receiverIpId,
271-
payerIpId,
272-
token,
273-
amount,
274-
options: { erc20Options, wipOptions } = {},
275-
txOptions,
276-
} = request;
269+
const { receiverIpId, payerIpId, token, amount, options, txOptions } = request;
277270
const sender = this.wallet.account!.address;
278271
const payAmount = BigInt(amount);
279272
if (payAmount <= 0n) {
@@ -309,21 +302,20 @@ export class RoyaltyClient {
309302
const contractCall = (): Promise<Hash> => {
310303
return this.royaltyModuleClient.payRoyaltyOnBehalf(req);
311304
};
312-
const tokenSpenders: Erc20Spender[] = [
305+
const tokenSpenders: TokenSpender[] = [
313306
{
314307
address: this.royaltyModuleClient.address,
315308
amount: payAmount,
309+
token,
316310
},
317311
];
318312
return await contractCallWithFees({
319-
totalFees: payAmount,
320-
options: { erc20Options, wipOptions },
313+
options,
321314
multicall3Address: this.multicall3Client.address,
322315
rpcClient: this.rpcClient,
323316
tokenSpenders: tokenSpenders,
324317
contractCall,
325318
sender,
326-
token,
327319
wallet: this.wallet,
328320
txOptions,
329321
encodedTxs: [encodedTxData],

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

Lines changed: 60 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,9 @@ import {
2525
RevShareInput,
2626
TokenIdInput,
2727
} from "../common";
28-
import { TxOptions, WipOptions, WithWipOptions } from "../options";
28+
import { ERC20Options, TxOptions, WipOptions, WithErc20AndWipOptions } from "../options";
2929
import { LicenseTerms, LicenseTermsDataInput } from "./license";
30-
import { Erc20Spender } from "../utils/wip";
30+
import { TokenSpender } from "../utils/token";
3131

3232
export type MaxRtsInput = number;
3333
export type DerivativeDataInput = {
@@ -93,7 +93,7 @@ export type RegisterDerivativeWithLicenseTokensRequest = {
9393
txOptions?: TxOptions;
9494
};
9595

96-
export type RegisterDerivativeRequest = WithWipOptions &
96+
export type RegisterDerivativeRequest = WithErc20AndWipOptions &
9797
DerivativeDataInput & {
9898
txOptions?: TxOptions;
9999
childIpId: Address;
@@ -118,7 +118,7 @@ export type MintAndRegisterIpAssetWithPilTermsRequest = {
118118
/** The address to receive the minted NFT. If not provided, the client's own wallet address will be used. */
119119
recipient?: Address;
120120
} & IpMetadataAndTxOptions &
121-
WithWipOptions;
121+
WithErc20AndWipOptions;
122122

123123
export type MintAndRegisterIpAssetWithPilTermsResponse = {
124124
txHash?: Hash;
@@ -141,7 +141,7 @@ export type RegisterIpAndMakeDerivativeRequest = {
141141
/** The derivative data to be used for register derivative. */
142142
derivData: DerivativeDataInput;
143143
} & IpMetadataAndTxOptions &
144-
WithWipOptions;
144+
WithErc20AndWipOptions;
145145

146146
export type RegisterIpAndMakeDerivativeResponse = {
147147
txHash?: Hash;
@@ -183,8 +183,7 @@ export type MintAndRegisterIpAndMakeDerivativeRequest = {
183183
*/
184184
allowDuplicates?: boolean;
185185
} & IpMetadataAndTxOptions &
186-
WithWipOptions;
187-
186+
WithErc20AndWipOptions;
188187
export type MintAndRegisterIpAndMakeDerivativeResponse = RegistrationResponse & {
189188
encodedTxData?: EncodedTxData;
190189
};
@@ -199,7 +198,7 @@ export type WithIpMetadata = {
199198
};
200199

201200
export type MintAndRegisterIpRequest = IpMetadataAndTxOptions &
202-
WithWipOptions & {
201+
WithErc20AndWipOptions & {
203202
spgNftContract: Address;
204203
/** The address of the recipient of the minted NFT. If not provided, the client's own wallet address will be used. */
205204
recipient?: Address;
@@ -227,7 +226,7 @@ export type MintAndRegisterIpAndMakeDerivativeWithLicenseTokensRequest = {
227226
*/
228227
allowDuplicates?: boolean;
229228
} & IpMetadataAndTxOptions &
230-
WithWipOptions;
229+
WithErc20AndWipOptions;
231230

232231
export type RegisterIpAndMakeDerivativeWithLicenseTokensRequest = {
233232
nftContract: Address;
@@ -245,10 +244,10 @@ export type RegisterIpAndMakeDerivativeWithLicenseTokensRequest = {
245244
*/
246245
deadline?: DeadlineInput;
247246
} & IpMetadataAndTxOptions &
248-
WithWipOptions;
247+
WithErc20AndWipOptions;
249248

250249
export type BatchMintAndRegisterIpAssetWithPilTermsRequest = {
251-
args: Omit<MintAndRegisterIpAssetWithPilTermsRequest, "txOptions">[];
250+
args: Omit<MintAndRegisterIpAssetWithPilTermsRequest, "options" | "txOptions">[];
252251
txOptions?: Omit<TxOptions, "EncodedTxData">;
253252
};
254253
export type BatchMintAndRegisterIpAssetWithPilTermsResult = {
@@ -264,7 +263,7 @@ export type BatchMintAndRegisterIpAssetWithPilTermsResponse = {
264263
};
265264

266265
export type BatchRegisterDerivativeRequest = {
267-
args: RegisterDerivativeRequest[];
266+
args: Omit<RegisterDerivativeRequest, "options" | "txOptions">[];
268267
/**
269268
* The deadline for the signature in seconds.
270269
* @default 1000
@@ -277,7 +276,7 @@ export type BatchRegisterDerivativeResponse = {
277276
txHash: Hash;
278277
};
279278
export type BatchMintAndRegisterIpAndMakeDerivativeRequest = {
280-
args: Omit<MintAndRegisterIpAndMakeDerivativeRequest, "txOptions">[];
279+
args: Omit<MintAndRegisterIpAndMakeDerivativeRequest, "txOptions" | "options">[];
281280
txOptions?: Omit<TxOptions, "encodedTxDataOnly">;
282281
};
283282
export type BatchMintAndRegisterIpAndMakeDerivativeResponse = {
@@ -351,7 +350,7 @@ export type RegisterDerivativeAndAttachLicenseTermsAndDistributeRoyaltyTokensReq
351350
/** Authors of the IP and their shares of the royalty tokens. */
352351
royaltyShares: RoyaltyShare[];
353352
txOptions?: Omit<TxOptions, "encodedTxDataOnly">;
354-
} & WithWipOptions &
353+
} & WithErc20AndWipOptions &
355354
WithIpMetadata;
356355

357356
export type RegisterDerivativeAndAttachLicenseTermsAndDistributeRoyaltyTokensResponse = {
@@ -377,7 +376,7 @@ export type MintAndRegisterIpAndAttachPILTermsAndDistributeRoyaltyTokensRequest
377376
recipient?: Address;
378377
txOptions?: Omit<TxOptions, "encodedTxDataOnly">;
379378
} & WithIpMetadata &
380-
WithWipOptions;
379+
WithErc20AndWipOptions;
381380

382381
export type MintAndRegisterIpAndAttachPILTermsAndDistributeRoyaltyTokensResponse = {
383382
txHash: Hash;
@@ -403,15 +402,15 @@ export type MintAndRegisterIpAndMakeDerivativeAndDistributeRoyaltyTokensRequest
403402
recipient?: Address;
404403
txOptions?: Omit<TxOptions, "encodedTxDataOnly">;
405404
} & WithIpMetadata &
406-
WithWipOptions;
405+
WithErc20AndWipOptions;
407406

408407
export type MintAndRegisterIpAndMakeDerivativeAndDistributeRoyaltyTokensResponse = {
409408
txHash: Hash;
410409
ipId?: Address;
411410
tokenId?: bigint;
412411
};
413412

414-
export type CommonRegistrationParams = {
413+
export type CommonRegistrationParams = WithErc20AndWipOptions & {
415414
contractCall: () => Promise<Hash>;
416415
encodedTxs: EncodedTxData[];
417416
spgNftContract?: Address;
@@ -420,7 +419,6 @@ export type CommonRegistrationParams = {
420419
derivData?: DerivativeData;
421420
sender: Address;
422421
txOptions?: TxOptions;
423-
wipOptions?: WipOptions;
424422
};
425423

426424
export type RegistrationResponse = {
@@ -456,17 +454,21 @@ export type TransformedIpRegistrationWorkflowRequest<
456454
| DerivativeWorkflowsClient
457455
| LicenseAttachmentWorkflowsClient
458456
| RoyaltyTokenDistributionWorkflowsClient;
459-
spenders?: Erc20Spender[];
460-
totalFees?: bigint;
457+
spenders?: TokenSpender[];
461458
extraData?: ExtraData;
462459
};
463460

461+
export type PrepareRoyaltyTokensDistributionRequestsResponse = {
462+
requests: TransformedIpRegistrationWorkflowRequest[];
463+
ipRoyaltyVaults: RoyaltyModuleIpRoyaltyVaultDeployedEvent[];
464+
};
465+
464466
/**
465467
* Utility type that removes option-related fields (txOptions and wipOptions) from a type.
466468
* This preserves discriminated unions unlike using Omit directly.
467469
*/
468470
type RemoveOptionsFields<Type> = {
469-
[Property in keyof Type as Exclude<Property, "txOptions" | "wipOptions">]: Type[Property];
471+
[Property in keyof Type as Exclude<Property, "txOptions" | "options">]: Type[Property];
470472
};
471473

472474
export type MintSpgNftRegistrationRequest = RemoveOptionsFields<
@@ -516,7 +518,7 @@ export type BatchRegistrationResult = {
516518
}[];
517519
};
518520

519-
export type BatchRegisterIpAssetsWithOptimizedWorkflowsRequest = WithWipOptions & {
521+
export type BatchRegisterIpAssetsWithOptimizedWorkflowsRequest = WithErc20AndWipOptions & {
520522
requests: IpRegistrationWorkflowRequest[];
521523
txOptions?: Omit<WaitForTransactionReceiptParameters, "hash">;
522524
};
@@ -534,8 +536,10 @@ export type ExtraData = {
534536
};
535537

536538
export type BatchMintAndRegisterIpRequest = {
537-
requests: Omit<MintAndRegisterIpRequest, "txOptions" | "wipOptions">[];
539+
requests: Omit<MintAndRegisterIpRequest, "txOptions" | "options">[];
540+
//TODO: merge wipOptions and erc20Options into options in main version upgrade
538541
wipOptions?: WipOptions;
542+
erc20Options?: ERC20Options;
539543
txOptions?: Omit<TxOptions, "encodedTxDataOnly">;
540544
};
541545

@@ -637,7 +641,7 @@ export type MintedNFT = {
637641
* };
638642
* ```
639643
*/
640-
export type RegisterIpAssetRequest<T extends MintNFT | MintedNFT> = WithWipOptions &
644+
export type RegisterIpAssetRequest<T extends MintNFT | MintedNFT> = WithErc20AndWipOptions &
641645
WithIpMetadata & {
642646
/** The NFT to be registered as an IP asset. */
643647
nft: T;
@@ -764,37 +768,38 @@ export type RegisterIpAssetResponse<T extends RegisterIpAssetRequest<MintedNFT |
764768
* };
765769
* ```
766770
*/
767-
export type RegisterDerivativeIpAssetRequest<T extends MintedNFT | MintNFT> = WithWipOptions &
768-
WithIpMetadata & {
769-
nft: T;
770-
/**
771-
* Authors of the IP and their shares of the royalty tokens.
772-
*
773-
* @remarks
774-
* Royalty shares can only be specified if `derivData` is also provided.
775-
* This ensures that royalty distribution is always associated with derivative IP registration.
776-
* The shares define how royalty tokens will be distributed among IP authors.
777-
*/
778-
royaltyShares?: RoyaltyShare[];
779-
/**
780-
* The derivative data containing parent IP information and licensing terms.
781-
* Can be used independently or together with `royaltyShares` for royalty distribution.
782-
*/
783-
derivData?: DerivativeDataInput;
784-
/**
785-
* The maximum number of royalty tokens that can be distributed to the external royalty policies (max: 100,000,000).
786-
* @default 100_000_000
787-
*/
788-
maxRts?: MaxRtsInput;
789-
/** The IDs of the license tokens to be burned for linking the IP to parent IPs. */
790-
licenseTokenIds?: LicenseTermsIdInput[];
791-
/**
792-
* The deadline for the signature in seconds.
793-
* @default 1000
794-
*/
795-
deadline?: DeadlineInput;
796-
txOptions?: Omit<TxOptions, "encodedTxDataOnly">;
797-
};
771+
export type RegisterDerivativeIpAssetRequest<T extends MintedNFT | MintNFT> =
772+
WithErc20AndWipOptions &
773+
WithIpMetadata & {
774+
nft: T;
775+
/**
776+
* Authors of the IP and their shares of the royalty tokens.
777+
*
778+
* @remarks
779+
* Royalty shares can only be specified if `derivData` is also provided.
780+
* This ensures that royalty distribution is always associated with derivative IP registration.
781+
* The shares define how royalty tokens will be distributed among IP authors.
782+
*/
783+
royaltyShares?: RoyaltyShare[];
784+
/**
785+
* The derivative data containing parent IP information and licensing terms.
786+
* Can be used independently or together with `royaltyShares` for royalty distribution.
787+
*/
788+
derivData?: DerivativeDataInput;
789+
/**
790+
* The maximum number of royalty tokens that can be distributed to the external royalty policies (max: 100,000,000).
791+
* @default 100_000_000
792+
*/
793+
maxRts?: MaxRtsInput;
794+
/** The IDs of the license tokens to be burned for linking the IP to parent IPs. */
795+
licenseTokenIds?: LicenseTermsIdInput[];
796+
/**
797+
* The deadline for the signature in seconds.
798+
* @default 1000
799+
*/
800+
deadline?: DeadlineInput;
801+
txOptions?: Omit<TxOptions, "encodedTxDataOnly">;
802+
};
798803

799804
/**
800805
* Response type for derivative IP asset registration with conditional return types.

0 commit comments

Comments
 (0)