Skip to content
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
111 changes: 11 additions & 100 deletions packages/core-sdk/src/resources/group.ts

Large diffs are not rendered by default.

351 changes: 36 additions & 315 deletions packages/core-sdk/src/resources/ipAsset.ts

Large diffs are not rendered by default.

58 changes: 11 additions & 47 deletions packages/core-sdk/src/resources/license.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,10 +43,11 @@ import {
getRevenueShare,
validateLicenseTerms,
} from "../utils/licenseTermsHelper";
import { chain, getAddress } from "../utils/utils";
import { chain, getAddress, validateAddress } from "../utils/utils";
import { ChainIds } from "../types/config";
import { calculateLicenseWipMintFee, contractCallWithFees } from "../utils/feeUtils";
import { Erc20Spender } from "../types/utils/wip";
import { validateLicenseConfig } from "../utils/validateLicenseConfig";

export class LicenseClient {
public licenseRegistryClient: LicenseRegistryEventClient;
Expand Down Expand Up @@ -538,80 +539,43 @@ export class LicenseClient {

/**
* 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.licensingConfig.commercialRevShare The commercial revenue share percentage.
* @param request.licensingConfig.disabled Whether the license is disabled or not.
* @param request.licensingConfig.expectMinimumGroupRewardShare The minimum percentage of the group’s reward share (from 0 to 100%, represented as 100 * 10 ** 6) that can be allocated to the IP when it is added to the group.
* If the remaining reward share in the group is less than the minimumGroupRewardShare, the IP cannot be added to the group.
* @param request.licensingConfig.expectGroupRewardPool The address of the expected group reward pool. The IP can only be added to a group with this specified reward pool address,
* or address(0) if the IP does not want to be added to any group.
* @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 req: LicensingModuleSetLicensingConfigRequest = {
ipId: request.ipId,
licenseTemplate: getAddress(request.licenseTemplate, "request.licenseTemplate"),
licenseTemplate: validateAddress(request.licenseTemplate),
licenseTermsId: BigInt(request.licenseTermsId),
licensingConfig: {
isSet: request.licensingConfig.isSet,
mintingFee: BigInt(request.licensingConfig.mintingFee),
hookData: request.licensingConfig.hookData,
licensingHook: request.licensingConfig.licensingHook,
disabled: request.licensingConfig.disabled,
commercialRevShare: getRevenueShare(request.licensingConfig.commercialRevShare),
expectGroupRewardPool: getAddress(
request.licensingConfig.expectGroupRewardPool,
"request.licensingConfig.expectGroupRewardPool",
),
expectMinimumGroupRewardShare: Number(
request.licensingConfig.expectMinimumGroupRewardShare,
),
},
licensingConfig: validateLicenseConfig(request.licensingConfig),
};
if (req.licensingConfig.mintingFee < 0) {
throw new Error("The minting fee must be greater than 0.");
}
if (
request.licenseTemplate === zeroAddress &&
request.licensingConfig.commercialRevShare !== 0
) {
if (req.licenseTemplate === zeroAddress && req.licensingConfig.commercialRevShare !== 0) {
throw new Error(
"The license template cannot be zero address if commercial revenue share is not zero.",
);
}
const isLicenseIpIdRegistered = await this.ipAssetRegistryClient.isRegistered({
id: getAddress(request.ipId, "request.ipId"),
id: validateAddress(req.ipId),
});
if (!isLicenseIpIdRegistered) {
throw new Error(`The licensor IP with id ${request.ipId} is not registered.`);
throw new Error(`The licensor IP with id ${req.ipId} is not registered.`);
}
const isExisted = await this.piLicenseTemplateReadOnlyClient.exists({
licenseTermsId: req.licenseTermsId,
});
if (!isExisted) {
throw new Error(`License terms id ${request.licenseTermsId} do not exist.`);
throw new Error(`License terms id ${req.licenseTermsId} do not exist.`);
}
if (request.licensingConfig.licensingHook !== zeroAddress) {
if (req.licensingConfig.licensingHook !== zeroAddress) {
const isRegistered = await this.moduleRegistryReadOnlyClient.isRegistered({
moduleAddress: request.licensingConfig.licensingHook,
moduleAddress: req.licensingConfig.licensingHook,
});
if (!isRegistered) {
throw new Error("The licensing hook is not registered.");
}
}
if (request.licenseTemplate === zeroAddress && request.licenseTermsId !== 0n) {
if (req.licenseTemplate === zeroAddress && req.licenseTermsId !== 0n) {
throw new Error("The license template is zero address but license terms id is not zero.");
}

Expand Down
14 changes: 11 additions & 3 deletions packages/core-sdk/src/types/common.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,25 +9,33 @@ export type TypedData = {
};

export type IpMetadataAndTxOptions = WithTxOptions & {
/** The desired metadata for the newly minted NFT and newly registered IP. */
ipMetadata?: Partial<IpMetadataForWorkflow>;
};

export type LicensingConfig = {
/** Whether the configuration is set or not */
isSet: boolean;
/** The minting fee to be paid when minting license tokens. */
mintingFee: bigint | string | number;
/** The hook contract address for the licensing module, or zero address if none. */
licensingHook: Address;
/** The data to be used by the licensing hook. */
hookData: Hex;
/** The commercial revenue share percentage (from 0 to 100%, represented as 100_000_000). */
commercialRevShare: number | string;
/** Whether the licensing is disabled or not. */
disabled: boolean;
/** The minimum percentage of the group’s reward share (from 0 to 100%, represented as 100_000_000) that can be allocated to the IP when it is added to the group. */
expectMinimumGroupRewardShare: number | string;
/** The address of the expected group reward pool. The IP can only be added to a group with this specified reward pool address, or zero address if the IP does not want to be added to any group. */
expectGroupRewardPool: Address;
};

export type InnerLicensingConfig = {
export type ValidatedLicensingConfig = LicensingConfig & {
mintingFee: bigint;
commercialRevShare: number;
expectMinimumGroupRewardShare: number;
} & LicensingConfig;
};

/**
* Input for token amount, can be bigint or number.
Expand Down
33 changes: 26 additions & 7 deletions packages/core-sdk/src/types/resources/group.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,27 +2,35 @@ import { Address } from "viem";

import { TxOptions } from "../options";
import { EncodedTxData } from "../../abi/generated";
import { InnerLicensingConfig, IpMetadataAndTxOptions, LicensingConfig } from "../common";
import { IpMetadataAndTxOptions, LicensingConfig, ValidatedLicensingConfig } from "../common";

export type LicenseData = {
licenseTermsId: string | bigint | number;
licensingConfig: LicensingConfig;
licensingConfig?: LicensingConfig;
licenseTemplate?: Address;
};

export type InnerLicenseData = {
export type ValidatedLicenseData = {
licenseTermsId: bigint;
licensingConfig: InnerLicensingConfig;
licensingConfig: ValidatedLicensingConfig;
licenseTemplate: Address;
};

export type MintAndRegisterIpAndAttachLicenseAndAddToGroupRequest = {
spgNftContract: Address;
/** The ID of the group IP to add the newly registered IP. */
groupId: Address;
/** Set to true to allow minting an NFT with a duplicate metadata hash. */
allowDuplicates: boolean;
/** The maximum reward share percentage that can be allocated to each member IP. */
maxAllowedRewardShare: number | string;
/** The data of the license and its configuration to be attached to the new group IP. */
licenseData: LicenseData[];
/** The address of the recipient of the minted NFT. If not provided, the function will use the user's own wallet address. */
recipient?: Address;
/**
* The deadline for the signature in seconds.
* @default 1000
*/
deadline?: string | number | bigint;
} & IpMetadataAndTxOptions;

Expand All @@ -42,13 +50,19 @@ export type RegisterGroupResponse = {
encodedTxData?: EncodedTxData;
groupId?: Address;
};

export type RegisterIpAndAttachLicenseAndAddToGroupRequest = {
nftContract: Address;
tokenId: bigint | string | number;
/** The ID of the group IP to add the newly registered IP. */
groupId: Address;
/**
* The deadline for the signature in seconds.
* @default 1000
*/
deadline?: bigint;
/** The data of the license and its configuration to be attached to the new group IP. */
licenseData: LicenseData[];
/** The maximum reward share percentage that can be allocated to each member IP. */
maxAllowedRewardShare: number | string;
} & IpMetadataAndTxOptions;

Expand All @@ -59,7 +73,9 @@ export type RegisterIpAndAttachLicenseAndAddToGroupResponse = {
tokenId?: bigint;
};
export type RegisterGroupAndAttachLicenseRequest = {
/** The address specifying how royalty will be split amongst the pool of IPs in the group. */
groupPool: Address;
/** The data of the license and its configuration to be attached to the new group IP. */
licenseData: LicenseData;
txOptions?: TxOptions;
};
Expand All @@ -69,11 +85,14 @@ export type RegisterGroupAndAttachLicenseResponse = {
encodedTxData?: EncodedTxData;
groupId?: Address;
};

export type RegisterGroupAndAttachLicenseAndAddIpsRequest = {
/** The address specifying how royalty will be split amongst the pool of IPs in the group. */
groupPool: Address;
/** The IP IDs of the IPs to be added to the group. */
ipIds: Address[];
/** The data of the license and its configuration to be attached to the new group IP. */
licenseData: LicenseData;
/** The maximum reward share percentage that can be allocated to each member IP. */
maxAllowedRewardShare: number | string;
txOptions?: TxOptions;
};
Expand Down
Loading
Loading