Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add two methods and return tokenId from mintAndRegisterIpAndMakeDerivative #307

Merged
merged 3 commits into from
Oct 31, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
68 changes: 68 additions & 0 deletions packages/core-sdk/src/abi/generated.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18484,6 +18484,26 @@ export type LicensingModuleRegisterDerivativeWithLicenseTokensRequest = {
royaltyContext: Hex;
};

/**
* LicensingModuleSetLicensingConfigRequest
*
* @param ipId address
* @param licenseTemplate address
* @param licenseTermsId uint256
* @param licensingConfig tuple
*/
export type LicensingModuleSetLicensingConfigRequest = {
ipId: Address;
licenseTemplate: Address;
licenseTermsId: bigint;
licensingConfig: {
isSet: boolean;
mintingFee: bigint;
licensingHook: Address;
hookData: Hex;
};
};

/**
* contract LicensingModule event
*/
Expand Down Expand Up @@ -18802,6 +18822,54 @@ export class LicensingModuleClient extends LicensingModuleReadOnlyClient {
}),
};
}

/**
* method setLicensingConfig for contract LicensingModule
*
* @param request LicensingModuleSetLicensingConfigRequest
* @return Promise<WriteContractReturnType>
*/
public async setLicensingConfig(
request: LicensingModuleSetLicensingConfigRequest,
): Promise<WriteContractReturnType> {
const { request: call } = await this.rpcClient.simulateContract({
abi: licensingModuleAbi,
address: this.address,
functionName: "setLicensingConfig",
account: this.wallet.account,
args: [
request.ipId,
request.licenseTemplate,
request.licenseTermsId,
request.licensingConfig,
],
});
return await this.wallet.writeContract(call as WriteContractParameters);
}

/**
* method setLicensingConfig for contract LicensingModule with only encode
*
* @param request LicensingModuleSetLicensingConfigRequest
* @return EncodedTxData
*/
public setLicensingConfigEncode(
request: LicensingModuleSetLicensingConfigRequest,
): EncodedTxData {
return {
to: this.address,
data: encodeFunctionData({
abi: licensingModuleAbi,
functionName: "setLicensingConfig",
args: [
request.ipId,
request.licenseTemplate,
request.licenseTermsId,
request.licensingConfig,
],
}),
};
}
}

// Contract MockERC20 =============================================================
Expand Down
4 changes: 4 additions & 0 deletions packages/core-sdk/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,9 @@ export type {
MintLicenseTokensResponse,
LicenseTermsId,
LicenseTerms,
PredictMintingLicenseFeeRequest,
SetLicensingConfigRequest,
SetLicensingConfigResponse,
} from "./types/resources/license";
export { PIL_TYPE } from "./types/resources/license";

Expand Down Expand Up @@ -124,6 +127,7 @@ export type {
PiLicenseTemplateGetLicenseTermsResponse,
IpAccountImplStateResponse,
EncodedTxData,
LicensingModulePredictMintingLicenseFeeResponse,
} from "./abi/generated";

export { getPermissionSignature } from "./utils/sign";
Expand Down
4 changes: 2 additions & 2 deletions packages/core-sdk/src/resources/ipAsset.ts
Original file line number Diff line number Diff line change
Expand Up @@ -811,7 +811,7 @@ export class IPAssetClient {
* @param request.ipMetadata.nftMetadataHash [Optional] The hash of the metadata for the IP NFT.
* @param request.recipient [Optional] The address of the recipient of the minted NFT,default value is your wallet address.
* @param request.txOptions - [Optional] transaction. This extends `WaitForTransactionReceiptParameters` from the Viem library, excluding the `hash` property.
* @returns A Promise that resolves to an object containing the transaction hash and optional IP ID if waitForTxn is set to true.
* @returns A Promise that resolves to a transaction hash, and if encodedTxDataOnly is true, includes encoded transaction data, and if waitForTransaction is true, includes child ip id and token id.
* @emits IPRegistered (ipId, chainId, tokenContract, tokenId, name, uri, registrationDate)
*/
public async mintAndRegisterIpAndMakeDerivative(
Expand Down Expand Up @@ -873,7 +873,7 @@ export class IPAssetClient {
hash: txHash,
});
const log = this.ipAssetRegistryClient.parseTxIpRegisteredEvent(receipt)[0];
return { txHash, childIpId: log.ipId };
return { txHash, childIpId: log.ipId, tokenId: log.tokenId };
}
return { txHash };
}
Expand Down
140 changes: 134 additions & 6 deletions packages/core-sdk/src/resources/license.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,10 @@ import {
LicenseRegistryEventClient,
LicenseRegistryReadOnlyClient,
LicensingModuleClient,
LicensingModulePredictMintingLicenseFeeRequest,
LicensingModulePredictMintingLicenseFeeResponse,
LicensingModuleSetLicensingConfigRequest,
ModuleRegistryReadOnlyClient,
PiLicenseTemplateClient,
PiLicenseTemplateGetLicenseTermsResponse,
PiLicenseTemplateReadOnlyClient,
Expand All @@ -25,6 +29,9 @@ import {
AttachLicenseTermsResponse,
LicenseTermsId,
RegisterPILTermsRequest,
PredictMintingLicenseFeeRequest,
SetLicensingConfigRequest,
SetLicensingConfigResponse,
} from "../types/resources/license";
import { handleError } from "../utils/errors";
import { getLicenseTermByType, validateLicenseTerms } from "../utils/licenseTermsHelper";
Expand All @@ -38,6 +45,7 @@ export class LicenseClient {
public piLicenseTemplateReadOnlyClient: PiLicenseTemplateReadOnlyClient;
public licenseTemplateClient: PiLicenseTemplateClient;
public licenseRegistryReadOnlyClient: LicenseRegistryReadOnlyClient;
public moduleRegistryReadOnlyClient: ModuleRegistryReadOnlyClient;
private readonly rpcClient: PublicClient;
private readonly wallet: SimpleWalletClient;
private readonly chainId: SupportedChainIds;
Expand All @@ -49,6 +57,7 @@ export class LicenseClient {
this.licenseTemplateClient = new PiLicenseTemplateClient(rpcClient, wallet);
this.licenseRegistryReadOnlyClient = new LicenseRegistryReadOnlyClient(rpcClient);
this.ipAssetRegistryClient = new IpAssetRegistryClient(rpcClient, wallet);
this.moduleRegistryReadOnlyClient = new ModuleRegistryReadOnlyClient(rpcClient);
this.rpcClient = rpcClient;
this.wallet = wallet;
this.chainId = chainId;
Expand All @@ -74,7 +83,7 @@ export class LicenseClient {
* @param request.currency The ERC20 token to be used to pay the minting fee. the token must be registered in story protocol.
* @param request.uri The URI of the license terms, which can be used to fetch the offchain license terms.
* @param request.txOptions - [Optional] transaction. This extends `WaitForTransactionReceiptParameters` from the Viem library, excluding the `hash` property.
* @returns A Promise that resolves to an object containing the optional transaction hash, optional transaction encodedTxData and optional license terms Id.
* @returns A Promise that resolves to a transaction hash, and if encodedTxDataOnly is true, includes encoded transaction data, and if waitForTransaction is true, includes license terms Id.
* @emits LicenseTermsRegistered (licenseTermsId, licenseTemplate, licenseTerms);
*/
public async registerPILTerms(request: RegisterPILTermsRequest): Promise<RegisterPILResponse> {
Expand Down Expand Up @@ -114,7 +123,7 @@ export class LicenseClient {
* Convenient function to register a PIL non commercial social remix license to the registry
* @param request - [Optional] The request object that contains all data needed to register a PIL non commercial social remix license.
* @param request.txOptions - [Optional] transaction. This extends `WaitForTransactionReceiptParameters` from the Viem library, excluding the `hash` property.
* @returns A Promise that resolves to an object containing the optional transaction hash and optional license terms Id.
* @returns A Promise that resolves to a transaction hash, and if encodedTxDataOnly is true, includes encoded transaction data, and if waitForTransaction is true, includes license terms Id.
* @emits LicenseTermsRegistered (licenseTermsId, licenseTemplate, licenseTerms);
*/
public async registerNonComSocialRemixingPIL(
Expand Down Expand Up @@ -159,7 +168,7 @@ export class LicenseClient {
* @param request.currency The ERC20 token to be used to pay the minting fee and the token must be registered in story protocol.
* @param request.royaltyPolicyAddress [Optional] The address of the royalty policy contract, default value is LAP.
* @param request.txOptions - [Optional] transaction. This extends `WaitForTransactionReceiptParameters` from the Viem library, excluding the `hash` property.
* @returns A Promise that resolves to an object containing the optional transaction hash and optional license terms Id.
* @returns A Promise that resolves to a transaction hash, and if encodedTxDataOnly is true, includes encoded transaction data, and if waitForTransaction is true, includes license terms Id.
* @emits LicenseTermsRegistered (licenseTermsId, licenseTemplate, licenseTerms);
*/
public async registerCommercialUsePIL(
Expand Down Expand Up @@ -212,7 +221,7 @@ export class LicenseClient {
* @param request.currency The ERC20 token to be used to pay the minting fee. the token must be registered in story protocol.
* @param request.royaltyPolicyAddress [Optional] The address of the royalty policy contract, default value is LAP.
* @param request.txOptions - [Optional] transaction. This extends `WaitForTransactionReceiptParameters` from the Viem library, excluding the `hash` property.
* @returns A Promise that resolves to an object containing the optional transaction hash and optional license terms Id.
* @returns A Promise that resolves to a transaction hash, and if encodedTxDataOnly is true, includes encoded transaction data, and if waitForTransaction is true, includes license terms Id.
* @emits LicenseTermsRegistered (licenseTermsId, licenseTemplate, licenseTerms);
*/
public async registerCommercialRemixPIL(
Expand Down Expand Up @@ -266,7 +275,8 @@ export class LicenseClient {
* @param request.licenseTemplate The address of the license template.
* @param request.licenseTermsId The ID of the license terms.
* @param request.txOptions - [Optional] transaction. This extends `WaitForTransactionReceiptParameters` from the Viem library, excluding the `hash` property.
* @returns A Promise that resolves to an object containing the transaction hash.
* @returns A Promise that resolves to a transaction hash, and if encodedTxDataOnly is true, includes encoded transaction data, and if waitForTransaction is true, includes success.
* If Ip have attached license terms, success will return false and txhash is empty.
*/
public async attachLicenseTerms(
request: AttachLicenseTermsRequest,
Expand Down Expand Up @@ -340,7 +350,7 @@ export class LicenseClient {
* @param request.amount The amount of license tokens to mint.
* @param request.receiver The address of the receiver.
* @param request.txOptions - [Optional] transaction. This extends `WaitForTransactionReceiptParameters` from the Viem library, excluding the `hash` property.
* @returns A Promise that resolves to an object containing the transaction hash and optional license token IDs if waitForTxn is set to true.
* @returns A Promise that resolves to a transaction hash, and if encodedTxDataOnly is true, includes encoded transaction data, and if waitForTransaction is true, includes license token IDs.
* @emits LicenseTokensMinted (msg.sender, licensorIpId, licenseTemplate, licenseTermsId, amount, receiver, startLicenseTokenId);
*/
public async mintLicenseTokens(
Expand Down Expand Up @@ -427,6 +437,124 @@ export class LicenseClient {
}
}

/**
* Pre-compute the minting license fee for the given IP and license terms. The function can be used to calculate the minting license fee before minting license tokens.
* @param request - The request object that contains all data needed to predict minting licenses fee.
* @param request.licensorIpId The IP ID of the licensor.
* @param request.licenseTermsId The ID of the license terms.
* @param request.amount The amount of license tokens to mint.
* @param request.licenseTemplate [Optional] The address of the license template,default value is Programmable IP License.
* @param request.receiver [Optional] The address of the receiver,default value is your wallet address.
* @param request.txOptions [Optional] This extends `WaitForTransactionReceiptParameters` from the Viem library, excluding the `hash` property.
* @returns A Promise that resolves to an object containing the currency token and token amount.
*/
public async predictMintingLicenseFee(
request: PredictMintingLicenseFeeRequest,
): Promise<LicensingModulePredictMintingLicenseFeeResponse> {
try {
const isLicenseIpIdRegistered = await this.ipAssetRegistryClient.isRegistered({
id: getAddress(request.licensorIpId, "request.licensorIpId"),
});
if (!isLicenseIpIdRegistered) {
throw new Error(`The licensor IP with id ${request.licensorIpId} is not registered.`);
}
const licenseTermsId = BigInt(request.licenseTermsId);
const isExisted = await this.piLicenseTemplateReadOnlyClient.exists({
licenseTermsId,
});
if (!isExisted) {
throw new Error(`License terms id ${request.licenseTermsId} do not exist.`);
}
const object: LicensingModulePredictMintingLicenseFeeRequest = {
...request,
receiver:
(request.receiver && getAddress(request.receiver, "request.receiver")) ||
this.wallet.account!.address,
amount: BigInt(request.amount),
royaltyContext: zeroAddress,
licenseTemplate:
(request.licenseTemplate &&
getAddress(request.licenseTemplate, "request.licenseTemplate")) ||
this.licenseTemplateClient.address,
licenseTermsId,
};
return await this.licensingModuleClient.predictMintingLicenseFee(object);
} catch (error) {
handleError(error, "Failed to predict minting license fee");
}
}

/**
* Sets the licensing configuration for a specific license terms of an IP. If both licenseTemplate and licenseTermsId are not specified then the licensing config apply to all licenses of given IP.
* @param request - The request object that contains all data needed to set licensing config.
* @param request.ipId The address of the IP for which the configuration is being set.
* @param request.licenseTermsId The ID of the license terms within the license template.
* @param request.licenseTemplate The address of the license template used, If not specified, the configuration applies to all licenses.
* @param request.licensingConfig The licensing configuration for the license.
* @param request.licensingConfig.isSet Whether the configuration is set or not.
* @param request.licensingConfig.mintingFee The minting fee to be paid when minting license tokens.
* @param request.licensingConfig.hookData The data to be used by the licensing hook.
* @param request.licensingConfig.licensingHook The hook contract address for the licensing module, or address(0) if none.
* @param request.txOptions [Optional] This extends `WaitForTransactionReceiptParameters` from the Viem library, excluding the `hash` property.
* @returns A Promise that resolves to a transaction hash, and if encodedTxDataOnly is true, includes encoded transaction data, and if waitForTransaction is true, includes success.
*/
public async setLicensingConfig(
request: SetLicensingConfigRequest,
): Promise<SetLicensingConfigResponse> {
try {
const isLicenseIpIdRegistered = await this.ipAssetRegistryClient.isRegistered({
id: getAddress(request.ipId, "request.ipId"),
});
if (!isLicenseIpIdRegistered) {
throw new Error(`The licensor IP with id ${request.ipId} is not registered.`);
}
const licenseTermsId = BigInt(request.licenseTermsId);
const isExisted = await this.piLicenseTemplateReadOnlyClient.exists({
licenseTermsId,
});
if (!isExisted) {
throw new Error(`License terms id ${request.licenseTermsId} do not exist.`);
}
if (request.licensingConfig.licensingHook !== zeroAddress) {
const isRegistered = await this.moduleRegistryReadOnlyClient.isRegistered({
moduleAddress: request.licensingConfig.licensingHook,
});
if (!isRegistered) {
throw new Error("The licensing hook is not registered.");
}
}

if (request.licenseTemplate === zeroAddress && request.licenseTermsId !== 0n) {
throw new Error("licenseTemplate is zero address but licenseTermsId is zero.");
}
const object: LicensingModuleSetLicensingConfigRequest = {
ipId: request.ipId,
licenseTemplate: getAddress(request.licenseTemplate, "request.licenseTemplate"),
licenseTermsId,
licensingConfig: {
isSet: request.licensingConfig.isSet,
mintingFee: BigInt(request.licensingConfig.mintingFee),
hookData: request.licensingConfig.hookData,
licensingHook: request.licensingConfig.licensingHook,
},
};
if (request.txOptions?.encodedTxDataOnly) {
return { encodedTxData: this.licensingModuleClient.setLicensingConfigEncode(object) };
} else {
const txHash = await this.licensingModuleClient.setLicensingConfig(object);
if (request.txOptions?.waitForTransaction) {
await this.rpcClient.waitForTransactionReceipt({
...request.txOptions,
hash: txHash,
});
return { txHash: txHash, success: true };
}
return { txHash: txHash };
}
} catch (error) {
handleError(error, "Failed to set licensing config");
}
}
private async getLicenseTermsId(request: LicenseTerms): Promise<LicenseTermsIdResponse> {
const licenseRes = await this.licenseTemplateClient.getLicenseTermsId({ terms: request });
return licenseRes.selectedLicenseTermsId;
Expand Down
1 change: 1 addition & 0 deletions packages/core-sdk/src/types/resources/ipAsset.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ export type RegisterDerivativeResponse = {
txHash?: string;
encodedTxData?: EncodedTxData;
childIpId?: Address;
tokenId?: bigint;
};

export type CreateIpAssetWithPilTermsRequest = {
Expand Down
30 changes: 29 additions & 1 deletion packages/core-sdk/src/types/resources/license.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Address } from "viem";
import { Address, Hex } from "viem";

import { TxOptions } from "../options";
import { EncodedTxData } from "../../abi/generated";
Expand Down Expand Up @@ -125,3 +125,31 @@ export enum PIL_TYPE {
}

export type LicenseTermsId = string | number | bigint;

export type PredictMintingLicenseFeeRequest = {
licensorIpId: Address;
licenseTermsId: LicenseTermsId;
amount: string | number | bigint;
licenseTemplate?: Address;
receiver?: Address;
txOptions?: TxOptions;
};

export type SetLicensingConfigRequest = {
ipId: Address;
licenseTermsId: string | number | bigint;
licensingConfig: {
isSet: boolean;
mintingFee: bigint | string | number;
licensingHook: Address;
hookData: Hex;
};
licenseTemplate: Address;
txOptions?: TxOptions;
};

export type SetLicensingConfigResponse = {
txHash?: string;
encodedTxData?: EncodedTxData;
success?: boolean;
};
1 change: 1 addition & 0 deletions packages/core-sdk/test/integration/ipAsset.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -282,6 +282,7 @@ describe("IP Asset Functions ", () => {
});
expect(result.txHash).to.be.a("string").and.not.empty;
expect(result.childIpId).to.be.a("string").and.not.empty;
expect(result.tokenId).to.be.a("bigint");
});

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