diff --git a/.changeset/selfish-deers-destroy.md b/.changeset/selfish-deers-destroy.md new file mode 100644 index 00000000000..84905ddb343 --- /dev/null +++ b/.changeset/selfish-deers-destroy.md @@ -0,0 +1,30 @@ +--- +"thirdweb": minor +--- + +Adds LoyaltyCard extensions and support for ERC721 deployment. + +```ts +import { deployERC721Contract } from "thirdweb/deploys"; + +const loyaltyCardContractAddress = await deployERC721Contract({ + chain: "your-chain-id", // replace with your chain ID + client: yourThirdwebClient, // replace with your Thirdweb client instance + account: yourAccount, // replace with your account details + type: "LoyaltyCard", + params: { + name: "MyLoyaltyCard", + symbol: "LOYAL", + description: "A loyalty card NFT contract", + image: "path/to/image.png", // replace with your image path + defaultAdmin: "0xYourAdminAddress", // replace with your admin address + royaltyRecipient: "0xYourRoyaltyRecipient", // replace with your royalty recipient address + royaltyBps: 500n, // 5% royalty + trustedForwarders: ["0xTrustedForwarderAddress"], // replace with your trusted forwarder addresses + saleRecipient: "0xYourSaleRecipient", // replace with your sale recipient address + platformFeeBps: 200n, // 2% platform fee + platformFeeRecipient: "0xYourPlatformFeeRecipient", // replace with your platform fee recipient address + }, +}); + +``` diff --git a/.github/workflows/issue.yml b/.github/workflows/issue.yml index 91280f7119d..4997ce6e099 100644 --- a/.github/workflows/issue.yml +++ b/.github/workflows/issue.yml @@ -21,16 +21,18 @@ jobs: repo: context.repo.repo, pull_number: context.issue.number }); - + const body = pr.data.body || ''; + const branchName = pr.data.head.ref; const issueRegex = new RegExp(`(${process.env.VALID_ISSUE_PREFIXES})-\\d+`, 'i'); - - if (!issueRegex.test(body)) { + const branchIssueRegex = new RegExp(`(${process.env.VALID_ISSUE_PREFIXES.toLowerCase()})-\\d+`, 'i'); + + if (!issueRegex.test(body) && !branchIssueRegex.test(branchName)) { core.setFailed( - `No valid issue reference found. PR body must contain an issue ID with one of these prefixes: ${process.env.VALID_ISSUE_PREFIXES}` + `No valid issue reference found. PR body or branch name must contain an issue ID with one of these prefixes: ${process.env.VALID_ISSUE_PREFIXES}` ); return; } - - const matches = body.match(issueRegex); + + const matches = body.match(issueRegex) || branchName.match(branchIssueRegex); console.log(`Found issue reference: ${matches[0]}`); diff --git a/codecov.yml b/codecov.yml index 906334b1939..a43ccdbc0c9 100644 --- a/codecov.yml +++ b/codecov.yml @@ -8,6 +8,8 @@ coverage: target: 80% flags: - packages + ignore: + - "**/__generated__/**" github_checks: diff --git a/packages/thirdweb/scripts/generate/abis/erc721/LoyaltyCard.json b/packages/thirdweb/scripts/generate/abis/erc721/LoyaltyCard.json new file mode 100644 index 00000000000..94c5484a161 --- /dev/null +++ b/packages/thirdweb/scripts/generate/abis/erc721/LoyaltyCard.json @@ -0,0 +1,14 @@ +[ + "constructor()", + "function cancel(uint256 tokenId)", + "function initialize(address _defaultAdmin, string _name, string _symbol, string _contractURI, address[] _trustedForwarders, address _saleRecipient, address _royaltyRecipient, uint128 _royaltyBps, uint128 _platformFeeBps, address _platformFeeRecipient)", + "function mintTo(address _to, string _uri) returns (uint256 tokenIdMinted)", + "function mintWithSignature((address to, address royaltyRecipient, uint256 royaltyBps, address primarySaleRecipient, uint256 quantity, uint256 pricePerToken, address currency, uint128 validityStartTimestamp, uint128 validityEndTimestamp, string uri) _req, bytes _signature) payable returns (address signer)", + "function nextTokenIdToMint() view returns (uint256)", + "function revoke(uint256 tokenId)", + "function supportsInterface(bytes4 interfaceId) view returns (bool)", + "function tokenURI(uint256 _tokenId) view returns (string)", + "function totalMinted() view returns (uint256)", + "event TokensMinted(address indexed mintedTo, uint256 indexed tokenIdMinted, string uri)", + "event TokensMintedWithSignature(address indexed signer, address indexed mintedTo, uint256 indexed tokenIdMinted, (address to, address royaltyRecipient, uint256 royaltyBps, address primarySaleRecipient, uint256 quantity, uint256 pricePerToken, address currency, uint128 validityStartTimestamp, uint128 validityEndTimestamp, string uri) mintRequest)" +] \ No newline at end of file diff --git a/packages/thirdweb/scripts/generate/abis/erc721/Multiwrap.json b/packages/thirdweb/scripts/generate/abis/erc721/Multiwrap.json new file mode 100644 index 00000000000..92d63ef06b8 --- /dev/null +++ b/packages/thirdweb/scripts/generate/abis/erc721/Multiwrap.json @@ -0,0 +1,15 @@ +[ + "constructor(address _nativeTokenWrapper)", + "event TokensWrapped(address indexed wrapper, address indexed recipientOfWrappedToken, uint256 indexed tokenIdOfWrappedToken, (address assetContract, uint8 tokenType, uint256 tokenId, uint256 amount)[] wrappedContents)", + "event TokensUnwrapped(address indexed unwrapper, address indexed recipientOfWrappedContents, uint256 indexed tokenIdOfWrappedToken)", + "function contractType() pure returns (bytes32)", + "function contractVersion() pure returns (uint8)", + "function getWrappedContents(uint256 _tokenId) view returns ((address assetContract, uint8 tokenType, uint256 tokenId, uint256 amount)[] contents)", + "function initialize(address _defaultAdmin, string _name, string _symbol, string _contractURI, address[] _trustedForwarders, address _royaltyRecipient, uint256 _royaltyBps)", + "function nextTokenIdToMint() view returns (uint256)", + "function supportsInterface(bytes4 interfaceId) view returns (bool)", + "function tokenURI(uint256 _tokenId) view returns (string)", + "function unwrap(uint256 _tokenId, address _recipient)", + "function wrap((address assetContract, uint8 tokenType, uint256 tokenId, uint256 amount)[] _tokensToWrap, string _uriForWrappedToken, address _recipient) payable returns (uint256 tokenId)", + "receive() external payable" +] \ No newline at end of file diff --git a/packages/thirdweb/src/extensions/erc721/__generated__/LoyaltyCard/events/TokensMinted.ts b/packages/thirdweb/src/extensions/erc721/__generated__/LoyaltyCard/events/TokensMinted.ts new file mode 100644 index 00000000000..667cd89e059 --- /dev/null +++ b/packages/thirdweb/src/extensions/erc721/__generated__/LoyaltyCard/events/TokensMinted.ts @@ -0,0 +1,47 @@ +import { prepareEvent } from "../../../../../event/prepare-event.js"; +import type { AbiParameterToPrimitiveType } from "abitype"; + +/** + * Represents the filters for the "TokensMinted" event. + */ +export type TokensMintedEventFilters = Partial<{ + mintedTo: AbiParameterToPrimitiveType<{ + type: "address"; + name: "mintedTo"; + indexed: true; + }>; + tokenIdMinted: AbiParameterToPrimitiveType<{ + type: "uint256"; + name: "tokenIdMinted"; + indexed: true; + }>; +}>; + +/** + * Creates an event object for the TokensMinted event. + * @param filters - Optional filters to apply to the event. + * @returns The prepared event object. + * @extension ERC721 + * @example + * ```ts + * import { getContractEvents } from "thirdweb"; + * import { tokensMintedEvent } from "thirdweb/extensions/erc721"; + * + * const events = await getContractEvents({ + * contract, + * events: [ + * tokensMintedEvent({ + * mintedTo: ..., + * tokenIdMinted: ..., + * }) + * ], + * }); + * ``` + */ +export function tokensMintedEvent(filters: TokensMintedEventFilters = {}) { + return prepareEvent({ + signature: + "event TokensMinted(address indexed mintedTo, uint256 indexed tokenIdMinted, string uri)", + filters, + }); +} diff --git a/packages/thirdweb/src/extensions/erc721/__generated__/LoyaltyCard/events/TokensMintedWithSignature.ts b/packages/thirdweb/src/extensions/erc721/__generated__/LoyaltyCard/events/TokensMintedWithSignature.ts new file mode 100644 index 00000000000..9b1685e557a --- /dev/null +++ b/packages/thirdweb/src/extensions/erc721/__generated__/LoyaltyCard/events/TokensMintedWithSignature.ts @@ -0,0 +1,55 @@ +import { prepareEvent } from "../../../../../event/prepare-event.js"; +import type { AbiParameterToPrimitiveType } from "abitype"; + +/** + * Represents the filters for the "TokensMintedWithSignature" event. + */ +export type TokensMintedWithSignatureEventFilters = Partial<{ + signer: AbiParameterToPrimitiveType<{ + type: "address"; + name: "signer"; + indexed: true; + }>; + mintedTo: AbiParameterToPrimitiveType<{ + type: "address"; + name: "mintedTo"; + indexed: true; + }>; + tokenIdMinted: AbiParameterToPrimitiveType<{ + type: "uint256"; + name: "tokenIdMinted"; + indexed: true; + }>; +}>; + +/** + * Creates an event object for the TokensMintedWithSignature event. + * @param filters - Optional filters to apply to the event. + * @returns The prepared event object. + * @extension ERC721 + * @example + * ```ts + * import { getContractEvents } from "thirdweb"; + * import { tokensMintedWithSignatureEvent } from "thirdweb/extensions/erc721"; + * + * const events = await getContractEvents({ + * contract, + * events: [ + * tokensMintedWithSignatureEvent({ + * signer: ..., + * mintedTo: ..., + * tokenIdMinted: ..., + * }) + * ], + * }); + * ``` + */ +export function tokensMintedWithSignatureEvent( + filters: TokensMintedWithSignatureEventFilters = {}, +) { + return prepareEvent({ + signature: + "event TokensMintedWithSignature(address indexed signer, address indexed mintedTo, uint256 indexed tokenIdMinted, (address to, address royaltyRecipient, uint256 royaltyBps, address primarySaleRecipient, uint256 quantity, uint256 pricePerToken, address currency, uint128 validityStartTimestamp, uint128 validityEndTimestamp, string uri) mintRequest)", + filters, + }); +} diff --git a/packages/thirdweb/src/extensions/erc721/__generated__/LoyaltyCard/read/nextTokenIdToMint.ts b/packages/thirdweb/src/extensions/erc721/__generated__/LoyaltyCard/read/nextTokenIdToMint.ts new file mode 100644 index 00000000000..abab41a1765 --- /dev/null +++ b/packages/thirdweb/src/extensions/erc721/__generated__/LoyaltyCard/read/nextTokenIdToMint.ts @@ -0,0 +1,70 @@ +import { readContract } from "../../../../../transaction/read-contract.js"; +import type { BaseTransactionOptions } from "../../../../../transaction/types.js"; + +import { decodeAbiParameters } from "viem"; +import type { Hex } from "../../../../../utils/encoding/hex.js"; +import { detectMethod } from "../../../../../utils/bytecode/detectExtension.js"; + +export const FN_SELECTOR = "0x3b1475a7" as const; +const FN_INPUTS = [] as const; +const FN_OUTPUTS = [ + { + type: "uint256", + }, +] as const; + +/** + * Checks if the `nextTokenIdToMint` method is supported by the given contract. + * @param availableSelectors An array of 4byte function selectors of the contract. You can get this in various ways, such as using "whatsabi" or if you have the ABI of the contract available you can use it to generate the selectors. + * @returns A boolean indicating if the `nextTokenIdToMint` method is supported. + * @extension ERC721 + * @example + * ```ts + * import { isNextTokenIdToMintSupported } from "thirdweb/extensions/erc721"; + * const supported = isNextTokenIdToMintSupported(["0x..."]); + * ``` + */ +export function isNextTokenIdToMintSupported(availableSelectors: string[]) { + return detectMethod({ + availableSelectors, + method: [FN_SELECTOR, FN_INPUTS, FN_OUTPUTS] as const, + }); +} + +/** + * Decodes the result of the nextTokenIdToMint function call. + * @param result - The hexadecimal result to decode. + * @returns The decoded result as per the FN_OUTPUTS definition. + * @extension ERC721 + * @example + * ```ts + * import { decodeNextTokenIdToMintResult } from "thirdweb/extensions/erc721"; + * const result = decodeNextTokenIdToMintResultResult("..."); + * ``` + */ +export function decodeNextTokenIdToMintResult(result: Hex) { + return decodeAbiParameters(FN_OUTPUTS, result)[0]; +} + +/** + * Calls the "nextTokenIdToMint" function on the contract. + * @param options - The options for the nextTokenIdToMint function. + * @returns The parsed result of the function call. + * @extension ERC721 + * @example + * ```ts + * import { nextTokenIdToMint } from "thirdweb/extensions/erc721"; + * + * const result = await nextTokenIdToMint({ + * contract, + * }); + * + * ``` + */ +export async function nextTokenIdToMint(options: BaseTransactionOptions) { + return readContract({ + contract: options.contract, + method: [FN_SELECTOR, FN_INPUTS, FN_OUTPUTS] as const, + params: [], + }); +} diff --git a/packages/thirdweb/src/extensions/erc721/__generated__/LoyaltyCard/read/supportsInterface.ts b/packages/thirdweb/src/extensions/erc721/__generated__/LoyaltyCard/read/supportsInterface.ts new file mode 100644 index 00000000000..0f6b2f9089d --- /dev/null +++ b/packages/thirdweb/src/extensions/erc721/__generated__/LoyaltyCard/read/supportsInterface.ts @@ -0,0 +1,130 @@ +import type { AbiParameterToPrimitiveType } from "abitype"; +import { readContract } from "../../../../../transaction/read-contract.js"; +import type { BaseTransactionOptions } from "../../../../../transaction/types.js"; +import { encodeAbiParameters } from "../../../../../utils/abi/encodeAbiParameters.js"; +import { decodeAbiParameters } from "viem"; +import type { Hex } from "../../../../../utils/encoding/hex.js"; +import { detectMethod } from "../../../../../utils/bytecode/detectExtension.js"; + +/** + * Represents the parameters for the "supportsInterface" function. + */ +export type SupportsInterfaceParams = { + interfaceId: AbiParameterToPrimitiveType<{ + type: "bytes4"; + name: "interfaceId"; + }>; +}; + +export const FN_SELECTOR = "0x01ffc9a7" as const; +const FN_INPUTS = [ + { + type: "bytes4", + name: "interfaceId", + }, +] as const; +const FN_OUTPUTS = [ + { + type: "bool", + }, +] as const; + +/** + * Checks if the `supportsInterface` method is supported by the given contract. + * @param availableSelectors An array of 4byte function selectors of the contract. You can get this in various ways, such as using "whatsabi" or if you have the ABI of the contract available you can use it to generate the selectors. + * @returns A boolean indicating if the `supportsInterface` method is supported. + * @extension ERC721 + * @example + * ```ts + * import { isSupportsInterfaceSupported } from "thirdweb/extensions/erc721"; + * const supported = isSupportsInterfaceSupported(["0x..."]); + * ``` + */ +export function isSupportsInterfaceSupported(availableSelectors: string[]) { + return detectMethod({ + availableSelectors, + method: [FN_SELECTOR, FN_INPUTS, FN_OUTPUTS] as const, + }); +} + +/** + * Encodes the parameters for the "supportsInterface" function. + * @param options - The options for the supportsInterface function. + * @returns The encoded ABI parameters. + * @extension ERC721 + * @example + * ```ts + * import { encodeSupportsInterfaceParams } from "thirdweb/extensions/erc721"; + * const result = encodeSupportsInterfaceParams({ + * interfaceId: ..., + * }); + * ``` + */ +export function encodeSupportsInterfaceParams( + options: SupportsInterfaceParams, +) { + return encodeAbiParameters(FN_INPUTS, [options.interfaceId]); +} + +/** + * Encodes the "supportsInterface" function into a Hex string with its parameters. + * @param options - The options for the supportsInterface function. + * @returns The encoded hexadecimal string. + * @extension ERC721 + * @example + * ```ts + * import { encodeSupportsInterface } from "thirdweb/extensions/erc721"; + * const result = encodeSupportsInterface({ + * interfaceId: ..., + * }); + * ``` + */ +export function encodeSupportsInterface(options: SupportsInterfaceParams) { + // we do a "manual" concat here to avoid the overhead of the "concatHex" function + // we can do this because we know the specific formats of the values + return (FN_SELECTOR + + encodeSupportsInterfaceParams(options).slice( + 2, + )) as `${typeof FN_SELECTOR}${string}`; +} + +/** + * Decodes the result of the supportsInterface function call. + * @param result - The hexadecimal result to decode. + * @returns The decoded result as per the FN_OUTPUTS definition. + * @extension ERC721 + * @example + * ```ts + * import { decodeSupportsInterfaceResult } from "thirdweb/extensions/erc721"; + * const result = decodeSupportsInterfaceResultResult("..."); + * ``` + */ +export function decodeSupportsInterfaceResult(result: Hex) { + return decodeAbiParameters(FN_OUTPUTS, result)[0]; +} + +/** + * Calls the "supportsInterface" function on the contract. + * @param options - The options for the supportsInterface function. + * @returns The parsed result of the function call. + * @extension ERC721 + * @example + * ```ts + * import { supportsInterface } from "thirdweb/extensions/erc721"; + * + * const result = await supportsInterface({ + * contract, + * interfaceId: ..., + * }); + * + * ``` + */ +export async function supportsInterface( + options: BaseTransactionOptions, +) { + return readContract({ + contract: options.contract, + method: [FN_SELECTOR, FN_INPUTS, FN_OUTPUTS] as const, + params: [options.interfaceId], + }); +} diff --git a/packages/thirdweb/src/extensions/erc721/__generated__/LoyaltyCard/read/tokenURI.ts b/packages/thirdweb/src/extensions/erc721/__generated__/LoyaltyCard/read/tokenURI.ts new file mode 100644 index 00000000000..cdd424d3861 --- /dev/null +++ b/packages/thirdweb/src/extensions/erc721/__generated__/LoyaltyCard/read/tokenURI.ts @@ -0,0 +1,123 @@ +import type { AbiParameterToPrimitiveType } from "abitype"; +import { readContract } from "../../../../../transaction/read-contract.js"; +import type { BaseTransactionOptions } from "../../../../../transaction/types.js"; +import { encodeAbiParameters } from "../../../../../utils/abi/encodeAbiParameters.js"; +import { decodeAbiParameters } from "viem"; +import type { Hex } from "../../../../../utils/encoding/hex.js"; +import { detectMethod } from "../../../../../utils/bytecode/detectExtension.js"; + +/** + * Represents the parameters for the "tokenURI" function. + */ +export type TokenURIParams = { + tokenId: AbiParameterToPrimitiveType<{ type: "uint256"; name: "_tokenId" }>; +}; + +export const FN_SELECTOR = "0xc87b56dd" as const; +const FN_INPUTS = [ + { + type: "uint256", + name: "_tokenId", + }, +] as const; +const FN_OUTPUTS = [ + { + type: "string", + }, +] as const; + +/** + * Checks if the `tokenURI` method is supported by the given contract. + * @param availableSelectors An array of 4byte function selectors of the contract. You can get this in various ways, such as using "whatsabi" or if you have the ABI of the contract available you can use it to generate the selectors. + * @returns A boolean indicating if the `tokenURI` method is supported. + * @extension ERC721 + * @example + * ```ts + * import { isTokenURISupported } from "thirdweb/extensions/erc721"; + * const supported = isTokenURISupported(["0x..."]); + * ``` + */ +export function isTokenURISupported(availableSelectors: string[]) { + return detectMethod({ + availableSelectors, + method: [FN_SELECTOR, FN_INPUTS, FN_OUTPUTS] as const, + }); +} + +/** + * Encodes the parameters for the "tokenURI" function. + * @param options - The options for the tokenURI function. + * @returns The encoded ABI parameters. + * @extension ERC721 + * @example + * ```ts + * import { encodeTokenURIParams } from "thirdweb/extensions/erc721"; + * const result = encodeTokenURIParams({ + * tokenId: ..., + * }); + * ``` + */ +export function encodeTokenURIParams(options: TokenURIParams) { + return encodeAbiParameters(FN_INPUTS, [options.tokenId]); +} + +/** + * Encodes the "tokenURI" function into a Hex string with its parameters. + * @param options - The options for the tokenURI function. + * @returns The encoded hexadecimal string. + * @extension ERC721 + * @example + * ```ts + * import { encodeTokenURI } from "thirdweb/extensions/erc721"; + * const result = encodeTokenURI({ + * tokenId: ..., + * }); + * ``` + */ +export function encodeTokenURI(options: TokenURIParams) { + // we do a "manual" concat here to avoid the overhead of the "concatHex" function + // we can do this because we know the specific formats of the values + return (FN_SELECTOR + + encodeTokenURIParams(options).slice(2)) as `${typeof FN_SELECTOR}${string}`; +} + +/** + * Decodes the result of the tokenURI function call. + * @param result - The hexadecimal result to decode. + * @returns The decoded result as per the FN_OUTPUTS definition. + * @extension ERC721 + * @example + * ```ts + * import { decodeTokenURIResult } from "thirdweb/extensions/erc721"; + * const result = decodeTokenURIResultResult("..."); + * ``` + */ +export function decodeTokenURIResult(result: Hex) { + return decodeAbiParameters(FN_OUTPUTS, result)[0]; +} + +/** + * Calls the "tokenURI" function on the contract. + * @param options - The options for the tokenURI function. + * @returns The parsed result of the function call. + * @extension ERC721 + * @example + * ```ts + * import { tokenURI } from "thirdweb/extensions/erc721"; + * + * const result = await tokenURI({ + * contract, + * tokenId: ..., + * }); + * + * ``` + */ +export async function tokenURI( + options: BaseTransactionOptions, +) { + return readContract({ + contract: options.contract, + method: [FN_SELECTOR, FN_INPUTS, FN_OUTPUTS] as const, + params: [options.tokenId], + }); +} diff --git a/packages/thirdweb/src/extensions/erc721/__generated__/LoyaltyCard/read/totalMinted.ts b/packages/thirdweb/src/extensions/erc721/__generated__/LoyaltyCard/read/totalMinted.ts new file mode 100644 index 00000000000..121dc3577cd --- /dev/null +++ b/packages/thirdweb/src/extensions/erc721/__generated__/LoyaltyCard/read/totalMinted.ts @@ -0,0 +1,70 @@ +import { readContract } from "../../../../../transaction/read-contract.js"; +import type { BaseTransactionOptions } from "../../../../../transaction/types.js"; + +import { decodeAbiParameters } from "viem"; +import type { Hex } from "../../../../../utils/encoding/hex.js"; +import { detectMethod } from "../../../../../utils/bytecode/detectExtension.js"; + +export const FN_SELECTOR = "0xa2309ff8" as const; +const FN_INPUTS = [] as const; +const FN_OUTPUTS = [ + { + type: "uint256", + }, +] as const; + +/** + * Checks if the `totalMinted` method is supported by the given contract. + * @param availableSelectors An array of 4byte function selectors of the contract. You can get this in various ways, such as using "whatsabi" or if you have the ABI of the contract available you can use it to generate the selectors. + * @returns A boolean indicating if the `totalMinted` method is supported. + * @extension ERC721 + * @example + * ```ts + * import { isTotalMintedSupported } from "thirdweb/extensions/erc721"; + * const supported = isTotalMintedSupported(["0x..."]); + * ``` + */ +export function isTotalMintedSupported(availableSelectors: string[]) { + return detectMethod({ + availableSelectors, + method: [FN_SELECTOR, FN_INPUTS, FN_OUTPUTS] as const, + }); +} + +/** + * Decodes the result of the totalMinted function call. + * @param result - The hexadecimal result to decode. + * @returns The decoded result as per the FN_OUTPUTS definition. + * @extension ERC721 + * @example + * ```ts + * import { decodeTotalMintedResult } from "thirdweb/extensions/erc721"; + * const result = decodeTotalMintedResultResult("..."); + * ``` + */ +export function decodeTotalMintedResult(result: Hex) { + return decodeAbiParameters(FN_OUTPUTS, result)[0]; +} + +/** + * Calls the "totalMinted" function on the contract. + * @param options - The options for the totalMinted function. + * @returns The parsed result of the function call. + * @extension ERC721 + * @example + * ```ts + * import { totalMinted } from "thirdweb/extensions/erc721"; + * + * const result = await totalMinted({ + * contract, + * }); + * + * ``` + */ +export async function totalMinted(options: BaseTransactionOptions) { + return readContract({ + contract: options.contract, + method: [FN_SELECTOR, FN_INPUTS, FN_OUTPUTS] as const, + params: [], + }); +} diff --git a/packages/thirdweb/src/extensions/erc721/__generated__/LoyaltyCard/write/cancel.ts b/packages/thirdweb/src/extensions/erc721/__generated__/LoyaltyCard/write/cancel.ts new file mode 100644 index 00000000000..f140b90318c --- /dev/null +++ b/packages/thirdweb/src/extensions/erc721/__generated__/LoyaltyCard/write/cancel.ts @@ -0,0 +1,135 @@ +import type { AbiParameterToPrimitiveType } from "abitype"; +import type { + BaseTransactionOptions, + WithOverrides, +} from "../../../../../transaction/types.js"; +import { prepareContractCall } from "../../../../../transaction/prepare-contract-call.js"; +import { encodeAbiParameters } from "../../../../../utils/abi/encodeAbiParameters.js"; +import { once } from "../../../../../utils/promise/once.js"; +import { detectMethod } from "../../../../../utils/bytecode/detectExtension.js"; + +/** + * Represents the parameters for the "cancel" function. + */ +export type CancelParams = WithOverrides<{ + tokenId: AbiParameterToPrimitiveType<{ type: "uint256"; name: "tokenId" }>; +}>; + +export const FN_SELECTOR = "0x40e58ee5" as const; +const FN_INPUTS = [ + { + type: "uint256", + name: "tokenId", + }, +] as const; +const FN_OUTPUTS = [] as const; + +/** + * Checks if the `cancel` method is supported by the given contract. + * @param availableSelectors An array of 4byte function selectors of the contract. You can get this in various ways, such as using "whatsabi" or if you have the ABI of the contract available you can use it to generate the selectors. + * @returns A boolean indicating if the `cancel` method is supported. + * @extension ERC721 + * @example + * ```ts + * import { isCancelSupported } from "thirdweb/extensions/erc721"; + * + * const supported = isCancelSupported(["0x..."]); + * ``` + */ +export function isCancelSupported(availableSelectors: string[]) { + return detectMethod({ + availableSelectors, + method: [FN_SELECTOR, FN_INPUTS, FN_OUTPUTS] as const, + }); +} + +/** + * Encodes the parameters for the "cancel" function. + * @param options - The options for the cancel function. + * @returns The encoded ABI parameters. + * @extension ERC721 + * @example + * ```ts + * import { encodeCancelParams } from "thirdweb/extensions/erc721"; + * const result = encodeCancelParams({ + * tokenId: ..., + * }); + * ``` + */ +export function encodeCancelParams(options: CancelParams) { + return encodeAbiParameters(FN_INPUTS, [options.tokenId]); +} + +/** + * Encodes the "cancel" function into a Hex string with its parameters. + * @param options - The options for the cancel function. + * @returns The encoded hexadecimal string. + * @extension ERC721 + * @example + * ```ts + * import { encodeCancel } from "thirdweb/extensions/erc721"; + * const result = encodeCancel({ + * tokenId: ..., + * }); + * ``` + */ +export function encodeCancel(options: CancelParams) { + // we do a "manual" concat here to avoid the overhead of the "concatHex" function + // we can do this because we know the specific formats of the values + return (FN_SELECTOR + + encodeCancelParams(options).slice(2)) as `${typeof FN_SELECTOR}${string}`; +} + +/** + * Prepares a transaction to call the "cancel" function on the contract. + * @param options - The options for the "cancel" function. + * @returns A prepared transaction object. + * @extension ERC721 + * @example + * ```ts + * import { sendTransaction } from "thirdweb"; + * import { cancel } from "thirdweb/extensions/erc721"; + * + * const transaction = cancel({ + * contract, + * tokenId: ..., + * overrides: { + * ... + * } + * }); + * + * // Send the transaction + * await sendTransaction({ transaction, account }); + * ``` + */ +export function cancel( + options: BaseTransactionOptions< + | CancelParams + | { + asyncParams: () => Promise; + } + >, +) { + const asyncOptions = once(async () => { + return "asyncParams" in options ? await options.asyncParams() : options; + }); + + return prepareContractCall({ + contract: options.contract, + method: [FN_SELECTOR, FN_INPUTS, FN_OUTPUTS] as const, + params: async () => { + const resolvedOptions = await asyncOptions(); + return [resolvedOptions.tokenId] as const; + }, + value: async () => (await asyncOptions()).overrides?.value, + accessList: async () => (await asyncOptions()).overrides?.accessList, + gas: async () => (await asyncOptions()).overrides?.gas, + gasPrice: async () => (await asyncOptions()).overrides?.gasPrice, + maxFeePerGas: async () => (await asyncOptions()).overrides?.maxFeePerGas, + maxPriorityFeePerGas: async () => + (await asyncOptions()).overrides?.maxPriorityFeePerGas, + nonce: async () => (await asyncOptions()).overrides?.nonce, + extraGas: async () => (await asyncOptions()).overrides?.extraGas, + erc20Value: async () => (await asyncOptions()).overrides?.erc20Value, + }); +} diff --git a/packages/thirdweb/src/extensions/erc721/__generated__/LoyaltyCard/write/initialize.ts b/packages/thirdweb/src/extensions/erc721/__generated__/LoyaltyCard/write/initialize.ts new file mode 100644 index 00000000000..53f68aafa0c --- /dev/null +++ b/packages/thirdweb/src/extensions/erc721/__generated__/LoyaltyCard/write/initialize.ts @@ -0,0 +1,255 @@ +import type { AbiParameterToPrimitiveType } from "abitype"; +import type { + BaseTransactionOptions, + WithOverrides, +} from "../../../../../transaction/types.js"; +import { prepareContractCall } from "../../../../../transaction/prepare-contract-call.js"; +import { encodeAbiParameters } from "../../../../../utils/abi/encodeAbiParameters.js"; +import { once } from "../../../../../utils/promise/once.js"; +import { detectMethod } from "../../../../../utils/bytecode/detectExtension.js"; + +/** + * Represents the parameters for the "initialize" function. + */ +export type InitializeParams = WithOverrides<{ + defaultAdmin: AbiParameterToPrimitiveType<{ + type: "address"; + name: "_defaultAdmin"; + }>; + name: AbiParameterToPrimitiveType<{ type: "string"; name: "_name" }>; + symbol: AbiParameterToPrimitiveType<{ type: "string"; name: "_symbol" }>; + contractURI: AbiParameterToPrimitiveType<{ + type: "string"; + name: "_contractURI"; + }>; + trustedForwarders: AbiParameterToPrimitiveType<{ + type: "address[]"; + name: "_trustedForwarders"; + }>; + saleRecipient: AbiParameterToPrimitiveType<{ + type: "address"; + name: "_saleRecipient"; + }>; + royaltyRecipient: AbiParameterToPrimitiveType<{ + type: "address"; + name: "_royaltyRecipient"; + }>; + royaltyBps: AbiParameterToPrimitiveType<{ + type: "uint128"; + name: "_royaltyBps"; + }>; + platformFeeBps: AbiParameterToPrimitiveType<{ + type: "uint128"; + name: "_platformFeeBps"; + }>; + platformFeeRecipient: AbiParameterToPrimitiveType<{ + type: "address"; + name: "_platformFeeRecipient"; + }>; +}>; + +export const FN_SELECTOR = "0xe1591634" as const; +const FN_INPUTS = [ + { + type: "address", + name: "_defaultAdmin", + }, + { + type: "string", + name: "_name", + }, + { + type: "string", + name: "_symbol", + }, + { + type: "string", + name: "_contractURI", + }, + { + type: "address[]", + name: "_trustedForwarders", + }, + { + type: "address", + name: "_saleRecipient", + }, + { + type: "address", + name: "_royaltyRecipient", + }, + { + type: "uint128", + name: "_royaltyBps", + }, + { + type: "uint128", + name: "_platformFeeBps", + }, + { + type: "address", + name: "_platformFeeRecipient", + }, +] as const; +const FN_OUTPUTS = [] as const; + +/** + * Checks if the `initialize` method is supported by the given contract. + * @param availableSelectors An array of 4byte function selectors of the contract. You can get this in various ways, such as using "whatsabi" or if you have the ABI of the contract available you can use it to generate the selectors. + * @returns A boolean indicating if the `initialize` method is supported. + * @extension ERC721 + * @example + * ```ts + * import { isInitializeSupported } from "thirdweb/extensions/erc721"; + * + * const supported = isInitializeSupported(["0x..."]); + * ``` + */ +export function isInitializeSupported(availableSelectors: string[]) { + return detectMethod({ + availableSelectors, + method: [FN_SELECTOR, FN_INPUTS, FN_OUTPUTS] as const, + }); +} + +/** + * Encodes the parameters for the "initialize" function. + * @param options - The options for the initialize function. + * @returns The encoded ABI parameters. + * @extension ERC721 + * @example + * ```ts + * import { encodeInitializeParams } from "thirdweb/extensions/erc721"; + * const result = encodeInitializeParams({ + * defaultAdmin: ..., + * name: ..., + * symbol: ..., + * contractURI: ..., + * trustedForwarders: ..., + * saleRecipient: ..., + * royaltyRecipient: ..., + * royaltyBps: ..., + * platformFeeBps: ..., + * platformFeeRecipient: ..., + * }); + * ``` + */ +export function encodeInitializeParams(options: InitializeParams) { + return encodeAbiParameters(FN_INPUTS, [ + options.defaultAdmin, + options.name, + options.symbol, + options.contractURI, + options.trustedForwarders, + options.saleRecipient, + options.royaltyRecipient, + options.royaltyBps, + options.platformFeeBps, + options.platformFeeRecipient, + ]); +} + +/** + * Encodes the "initialize" function into a Hex string with its parameters. + * @param options - The options for the initialize function. + * @returns The encoded hexadecimal string. + * @extension ERC721 + * @example + * ```ts + * import { encodeInitialize } from "thirdweb/extensions/erc721"; + * const result = encodeInitialize({ + * defaultAdmin: ..., + * name: ..., + * symbol: ..., + * contractURI: ..., + * trustedForwarders: ..., + * saleRecipient: ..., + * royaltyRecipient: ..., + * royaltyBps: ..., + * platformFeeBps: ..., + * platformFeeRecipient: ..., + * }); + * ``` + */ +export function encodeInitialize(options: InitializeParams) { + // we do a "manual" concat here to avoid the overhead of the "concatHex" function + // we can do this because we know the specific formats of the values + return (FN_SELECTOR + + encodeInitializeParams(options).slice( + 2, + )) as `${typeof FN_SELECTOR}${string}`; +} + +/** + * Prepares a transaction to call the "initialize" function on the contract. + * @param options - The options for the "initialize" function. + * @returns A prepared transaction object. + * @extension ERC721 + * @example + * ```ts + * import { sendTransaction } from "thirdweb"; + * import { initialize } from "thirdweb/extensions/erc721"; + * + * const transaction = initialize({ + * contract, + * defaultAdmin: ..., + * name: ..., + * symbol: ..., + * contractURI: ..., + * trustedForwarders: ..., + * saleRecipient: ..., + * royaltyRecipient: ..., + * royaltyBps: ..., + * platformFeeBps: ..., + * platformFeeRecipient: ..., + * overrides: { + * ... + * } + * }); + * + * // Send the transaction + * await sendTransaction({ transaction, account }); + * ``` + */ +export function initialize( + options: BaseTransactionOptions< + | InitializeParams + | { + asyncParams: () => Promise; + } + >, +) { + const asyncOptions = once(async () => { + return "asyncParams" in options ? await options.asyncParams() : options; + }); + + return prepareContractCall({ + contract: options.contract, + method: [FN_SELECTOR, FN_INPUTS, FN_OUTPUTS] as const, + params: async () => { + const resolvedOptions = await asyncOptions(); + return [ + resolvedOptions.defaultAdmin, + resolvedOptions.name, + resolvedOptions.symbol, + resolvedOptions.contractURI, + resolvedOptions.trustedForwarders, + resolvedOptions.saleRecipient, + resolvedOptions.royaltyRecipient, + resolvedOptions.royaltyBps, + resolvedOptions.platformFeeBps, + resolvedOptions.platformFeeRecipient, + ] as const; + }, + value: async () => (await asyncOptions()).overrides?.value, + accessList: async () => (await asyncOptions()).overrides?.accessList, + gas: async () => (await asyncOptions()).overrides?.gas, + gasPrice: async () => (await asyncOptions()).overrides?.gasPrice, + maxFeePerGas: async () => (await asyncOptions()).overrides?.maxFeePerGas, + maxPriorityFeePerGas: async () => + (await asyncOptions()).overrides?.maxPriorityFeePerGas, + nonce: async () => (await asyncOptions()).overrides?.nonce, + extraGas: async () => (await asyncOptions()).overrides?.extraGas, + erc20Value: async () => (await asyncOptions()).overrides?.erc20Value, + }); +} diff --git a/packages/thirdweb/src/extensions/erc721/__generated__/LoyaltyCard/write/mintTo.ts b/packages/thirdweb/src/extensions/erc721/__generated__/LoyaltyCard/write/mintTo.ts new file mode 100644 index 00000000000..3613cdb97e0 --- /dev/null +++ b/packages/thirdweb/src/extensions/erc721/__generated__/LoyaltyCard/write/mintTo.ts @@ -0,0 +1,148 @@ +import type { AbiParameterToPrimitiveType } from "abitype"; +import type { + BaseTransactionOptions, + WithOverrides, +} from "../../../../../transaction/types.js"; +import { prepareContractCall } from "../../../../../transaction/prepare-contract-call.js"; +import { encodeAbiParameters } from "../../../../../utils/abi/encodeAbiParameters.js"; +import { once } from "../../../../../utils/promise/once.js"; +import { detectMethod } from "../../../../../utils/bytecode/detectExtension.js"; + +/** + * Represents the parameters for the "mintTo" function. + */ +export type MintToParams = WithOverrides<{ + to: AbiParameterToPrimitiveType<{ type: "address"; name: "_to" }>; + uri: AbiParameterToPrimitiveType<{ type: "string"; name: "_uri" }>; +}>; + +export const FN_SELECTOR = "0x0075a317" as const; +const FN_INPUTS = [ + { + type: "address", + name: "_to", + }, + { + type: "string", + name: "_uri", + }, +] as const; +const FN_OUTPUTS = [ + { + type: "uint256", + name: "tokenIdMinted", + }, +] as const; + +/** + * Checks if the `mintTo` method is supported by the given contract. + * @param availableSelectors An array of 4byte function selectors of the contract. You can get this in various ways, such as using "whatsabi" or if you have the ABI of the contract available you can use it to generate the selectors. + * @returns A boolean indicating if the `mintTo` method is supported. + * @extension ERC721 + * @example + * ```ts + * import { isMintToSupported } from "thirdweb/extensions/erc721"; + * + * const supported = isMintToSupported(["0x..."]); + * ``` + */ +export function isMintToSupported(availableSelectors: string[]) { + return detectMethod({ + availableSelectors, + method: [FN_SELECTOR, FN_INPUTS, FN_OUTPUTS] as const, + }); +} + +/** + * Encodes the parameters for the "mintTo" function. + * @param options - The options for the mintTo function. + * @returns The encoded ABI parameters. + * @extension ERC721 + * @example + * ```ts + * import { encodeMintToParams } from "thirdweb/extensions/erc721"; + * const result = encodeMintToParams({ + * to: ..., + * uri: ..., + * }); + * ``` + */ +export function encodeMintToParams(options: MintToParams) { + return encodeAbiParameters(FN_INPUTS, [options.to, options.uri]); +} + +/** + * Encodes the "mintTo" function into a Hex string with its parameters. + * @param options - The options for the mintTo function. + * @returns The encoded hexadecimal string. + * @extension ERC721 + * @example + * ```ts + * import { encodeMintTo } from "thirdweb/extensions/erc721"; + * const result = encodeMintTo({ + * to: ..., + * uri: ..., + * }); + * ``` + */ +export function encodeMintTo(options: MintToParams) { + // we do a "manual" concat here to avoid the overhead of the "concatHex" function + // we can do this because we know the specific formats of the values + return (FN_SELECTOR + + encodeMintToParams(options).slice(2)) as `${typeof FN_SELECTOR}${string}`; +} + +/** + * Prepares a transaction to call the "mintTo" function on the contract. + * @param options - The options for the "mintTo" function. + * @returns A prepared transaction object. + * @extension ERC721 + * @example + * ```ts + * import { sendTransaction } from "thirdweb"; + * import { mintTo } from "thirdweb/extensions/erc721"; + * + * const transaction = mintTo({ + * contract, + * to: ..., + * uri: ..., + * overrides: { + * ... + * } + * }); + * + * // Send the transaction + * await sendTransaction({ transaction, account }); + * ``` + */ +export function mintTo( + options: BaseTransactionOptions< + | MintToParams + | { + asyncParams: () => Promise; + } + >, +) { + const asyncOptions = once(async () => { + return "asyncParams" in options ? await options.asyncParams() : options; + }); + + return prepareContractCall({ + contract: options.contract, + method: [FN_SELECTOR, FN_INPUTS, FN_OUTPUTS] as const, + params: async () => { + const resolvedOptions = await asyncOptions(); + return [resolvedOptions.to, resolvedOptions.uri] as const; + }, + value: async () => (await asyncOptions()).overrides?.value, + accessList: async () => (await asyncOptions()).overrides?.accessList, + gas: async () => (await asyncOptions()).overrides?.gas, + gasPrice: async () => (await asyncOptions()).overrides?.gasPrice, + maxFeePerGas: async () => (await asyncOptions()).overrides?.maxFeePerGas, + maxPriorityFeePerGas: async () => + (await asyncOptions()).overrides?.maxPriorityFeePerGas, + nonce: async () => (await asyncOptions()).overrides?.nonce, + extraGas: async () => (await asyncOptions()).overrides?.extraGas, + erc20Value: async () => (await asyncOptions()).overrides?.erc20Value, + }); +} diff --git a/packages/thirdweb/src/extensions/erc721/__generated__/LoyaltyCard/write/mintWithSignature.ts b/packages/thirdweb/src/extensions/erc721/__generated__/LoyaltyCard/write/mintWithSignature.ts new file mode 100644 index 00000000000..e051a864201 --- /dev/null +++ b/packages/thirdweb/src/extensions/erc721/__generated__/LoyaltyCard/write/mintWithSignature.ts @@ -0,0 +1,209 @@ +import type { AbiParameterToPrimitiveType } from "abitype"; +import type { + BaseTransactionOptions, + WithOverrides, +} from "../../../../../transaction/types.js"; +import { prepareContractCall } from "../../../../../transaction/prepare-contract-call.js"; +import { encodeAbiParameters } from "../../../../../utils/abi/encodeAbiParameters.js"; +import { once } from "../../../../../utils/promise/once.js"; +import { detectMethod } from "../../../../../utils/bytecode/detectExtension.js"; + +/** + * Represents the parameters for the "mintWithSignature" function. + */ +export type MintWithSignatureParams = WithOverrides<{ + req: AbiParameterToPrimitiveType<{ + type: "tuple"; + name: "_req"; + components: [ + { type: "address"; name: "to" }, + { type: "address"; name: "royaltyRecipient" }, + { type: "uint256"; name: "royaltyBps" }, + { type: "address"; name: "primarySaleRecipient" }, + { type: "uint256"; name: "quantity" }, + { type: "uint256"; name: "pricePerToken" }, + { type: "address"; name: "currency" }, + { type: "uint128"; name: "validityStartTimestamp" }, + { type: "uint128"; name: "validityEndTimestamp" }, + { type: "string"; name: "uri" }, + ]; + }>; + signature: AbiParameterToPrimitiveType<{ type: "bytes"; name: "_signature" }>; +}>; + +export const FN_SELECTOR = "0x91c5ee92" as const; +const FN_INPUTS = [ + { + type: "tuple", + name: "_req", + components: [ + { + type: "address", + name: "to", + }, + { + type: "address", + name: "royaltyRecipient", + }, + { + type: "uint256", + name: "royaltyBps", + }, + { + type: "address", + name: "primarySaleRecipient", + }, + { + type: "uint256", + name: "quantity", + }, + { + type: "uint256", + name: "pricePerToken", + }, + { + type: "address", + name: "currency", + }, + { + type: "uint128", + name: "validityStartTimestamp", + }, + { + type: "uint128", + name: "validityEndTimestamp", + }, + { + type: "string", + name: "uri", + }, + ], + }, + { + type: "bytes", + name: "_signature", + }, +] as const; +const FN_OUTPUTS = [ + { + type: "address", + name: "signer", + }, +] as const; + +/** + * Checks if the `mintWithSignature` method is supported by the given contract. + * @param availableSelectors An array of 4byte function selectors of the contract. You can get this in various ways, such as using "whatsabi" or if you have the ABI of the contract available you can use it to generate the selectors. + * @returns A boolean indicating if the `mintWithSignature` method is supported. + * @extension ERC721 + * @example + * ```ts + * import { isMintWithSignatureSupported } from "thirdweb/extensions/erc721"; + * + * const supported = isMintWithSignatureSupported(["0x..."]); + * ``` + */ +export function isMintWithSignatureSupported(availableSelectors: string[]) { + return detectMethod({ + availableSelectors, + method: [FN_SELECTOR, FN_INPUTS, FN_OUTPUTS] as const, + }); +} + +/** + * Encodes the parameters for the "mintWithSignature" function. + * @param options - The options for the mintWithSignature function. + * @returns The encoded ABI parameters. + * @extension ERC721 + * @example + * ```ts + * import { encodeMintWithSignatureParams } from "thirdweb/extensions/erc721"; + * const result = encodeMintWithSignatureParams({ + * req: ..., + * signature: ..., + * }); + * ``` + */ +export function encodeMintWithSignatureParams( + options: MintWithSignatureParams, +) { + return encodeAbiParameters(FN_INPUTS, [options.req, options.signature]); +} + +/** + * Encodes the "mintWithSignature" function into a Hex string with its parameters. + * @param options - The options for the mintWithSignature function. + * @returns The encoded hexadecimal string. + * @extension ERC721 + * @example + * ```ts + * import { encodeMintWithSignature } from "thirdweb/extensions/erc721"; + * const result = encodeMintWithSignature({ + * req: ..., + * signature: ..., + * }); + * ``` + */ +export function encodeMintWithSignature(options: MintWithSignatureParams) { + // we do a "manual" concat here to avoid the overhead of the "concatHex" function + // we can do this because we know the specific formats of the values + return (FN_SELECTOR + + encodeMintWithSignatureParams(options).slice( + 2, + )) as `${typeof FN_SELECTOR}${string}`; +} + +/** + * Prepares a transaction to call the "mintWithSignature" function on the contract. + * @param options - The options for the "mintWithSignature" function. + * @returns A prepared transaction object. + * @extension ERC721 + * @example + * ```ts + * import { sendTransaction } from "thirdweb"; + * import { mintWithSignature } from "thirdweb/extensions/erc721"; + * + * const transaction = mintWithSignature({ + * contract, + * req: ..., + * signature: ..., + * overrides: { + * ... + * } + * }); + * + * // Send the transaction + * await sendTransaction({ transaction, account }); + * ``` + */ +export function mintWithSignature( + options: BaseTransactionOptions< + | MintWithSignatureParams + | { + asyncParams: () => Promise; + } + >, +) { + const asyncOptions = once(async () => { + return "asyncParams" in options ? await options.asyncParams() : options; + }); + + return prepareContractCall({ + contract: options.contract, + method: [FN_SELECTOR, FN_INPUTS, FN_OUTPUTS] as const, + params: async () => { + const resolvedOptions = await asyncOptions(); + return [resolvedOptions.req, resolvedOptions.signature] as const; + }, + value: async () => (await asyncOptions()).overrides?.value, + accessList: async () => (await asyncOptions()).overrides?.accessList, + gas: async () => (await asyncOptions()).overrides?.gas, + gasPrice: async () => (await asyncOptions()).overrides?.gasPrice, + maxFeePerGas: async () => (await asyncOptions()).overrides?.maxFeePerGas, + maxPriorityFeePerGas: async () => + (await asyncOptions()).overrides?.maxPriorityFeePerGas, + nonce: async () => (await asyncOptions()).overrides?.nonce, + extraGas: async () => (await asyncOptions()).overrides?.extraGas, + erc20Value: async () => (await asyncOptions()).overrides?.erc20Value, + }); +} diff --git a/packages/thirdweb/src/extensions/erc721/__generated__/LoyaltyCard/write/revoke.ts b/packages/thirdweb/src/extensions/erc721/__generated__/LoyaltyCard/write/revoke.ts new file mode 100644 index 00000000000..dc6543b474b --- /dev/null +++ b/packages/thirdweb/src/extensions/erc721/__generated__/LoyaltyCard/write/revoke.ts @@ -0,0 +1,135 @@ +import type { AbiParameterToPrimitiveType } from "abitype"; +import type { + BaseTransactionOptions, + WithOverrides, +} from "../../../../../transaction/types.js"; +import { prepareContractCall } from "../../../../../transaction/prepare-contract-call.js"; +import { encodeAbiParameters } from "../../../../../utils/abi/encodeAbiParameters.js"; +import { once } from "../../../../../utils/promise/once.js"; +import { detectMethod } from "../../../../../utils/bytecode/detectExtension.js"; + +/** + * Represents the parameters for the "revoke" function. + */ +export type RevokeParams = WithOverrides<{ + tokenId: AbiParameterToPrimitiveType<{ type: "uint256"; name: "tokenId" }>; +}>; + +export const FN_SELECTOR = "0x20c5429b" as const; +const FN_INPUTS = [ + { + type: "uint256", + name: "tokenId", + }, +] as const; +const FN_OUTPUTS = [] as const; + +/** + * Checks if the `revoke` method is supported by the given contract. + * @param availableSelectors An array of 4byte function selectors of the contract. You can get this in various ways, such as using "whatsabi" or if you have the ABI of the contract available you can use it to generate the selectors. + * @returns A boolean indicating if the `revoke` method is supported. + * @extension ERC721 + * @example + * ```ts + * import { isRevokeSupported } from "thirdweb/extensions/erc721"; + * + * const supported = isRevokeSupported(["0x..."]); + * ``` + */ +export function isRevokeSupported(availableSelectors: string[]) { + return detectMethod({ + availableSelectors, + method: [FN_SELECTOR, FN_INPUTS, FN_OUTPUTS] as const, + }); +} + +/** + * Encodes the parameters for the "revoke" function. + * @param options - The options for the revoke function. + * @returns The encoded ABI parameters. + * @extension ERC721 + * @example + * ```ts + * import { encodeRevokeParams } from "thirdweb/extensions/erc721"; + * const result = encodeRevokeParams({ + * tokenId: ..., + * }); + * ``` + */ +export function encodeRevokeParams(options: RevokeParams) { + return encodeAbiParameters(FN_INPUTS, [options.tokenId]); +} + +/** + * Encodes the "revoke" function into a Hex string with its parameters. + * @param options - The options for the revoke function. + * @returns The encoded hexadecimal string. + * @extension ERC721 + * @example + * ```ts + * import { encodeRevoke } from "thirdweb/extensions/erc721"; + * const result = encodeRevoke({ + * tokenId: ..., + * }); + * ``` + */ +export function encodeRevoke(options: RevokeParams) { + // we do a "manual" concat here to avoid the overhead of the "concatHex" function + // we can do this because we know the specific formats of the values + return (FN_SELECTOR + + encodeRevokeParams(options).slice(2)) as `${typeof FN_SELECTOR}${string}`; +} + +/** + * Prepares a transaction to call the "revoke" function on the contract. + * @param options - The options for the "revoke" function. + * @returns A prepared transaction object. + * @extension ERC721 + * @example + * ```ts + * import { sendTransaction } from "thirdweb"; + * import { revoke } from "thirdweb/extensions/erc721"; + * + * const transaction = revoke({ + * contract, + * tokenId: ..., + * overrides: { + * ... + * } + * }); + * + * // Send the transaction + * await sendTransaction({ transaction, account }); + * ``` + */ +export function revoke( + options: BaseTransactionOptions< + | RevokeParams + | { + asyncParams: () => Promise; + } + >, +) { + const asyncOptions = once(async () => { + return "asyncParams" in options ? await options.asyncParams() : options; + }); + + return prepareContractCall({ + contract: options.contract, + method: [FN_SELECTOR, FN_INPUTS, FN_OUTPUTS] as const, + params: async () => { + const resolvedOptions = await asyncOptions(); + return [resolvedOptions.tokenId] as const; + }, + value: async () => (await asyncOptions()).overrides?.value, + accessList: async () => (await asyncOptions()).overrides?.accessList, + gas: async () => (await asyncOptions()).overrides?.gas, + gasPrice: async () => (await asyncOptions()).overrides?.gasPrice, + maxFeePerGas: async () => (await asyncOptions()).overrides?.maxFeePerGas, + maxPriorityFeePerGas: async () => + (await asyncOptions()).overrides?.maxPriorityFeePerGas, + nonce: async () => (await asyncOptions()).overrides?.nonce, + extraGas: async () => (await asyncOptions()).overrides?.extraGas, + erc20Value: async () => (await asyncOptions()).overrides?.erc20Value, + }); +} diff --git a/packages/thirdweb/src/extensions/erc721/__generated__/Multiwrap/events/TokensUnwrapped.ts b/packages/thirdweb/src/extensions/erc721/__generated__/Multiwrap/events/TokensUnwrapped.ts new file mode 100644 index 00000000000..1c2e257586d --- /dev/null +++ b/packages/thirdweb/src/extensions/erc721/__generated__/Multiwrap/events/TokensUnwrapped.ts @@ -0,0 +1,55 @@ +import { prepareEvent } from "../../../../../event/prepare-event.js"; +import type { AbiParameterToPrimitiveType } from "abitype"; + +/** + * Represents the filters for the "TokensUnwrapped" event. + */ +export type TokensUnwrappedEventFilters = Partial<{ + unwrapper: AbiParameterToPrimitiveType<{ + type: "address"; + name: "unwrapper"; + indexed: true; + }>; + recipientOfWrappedContents: AbiParameterToPrimitiveType<{ + type: "address"; + name: "recipientOfWrappedContents"; + indexed: true; + }>; + tokenIdOfWrappedToken: AbiParameterToPrimitiveType<{ + type: "uint256"; + name: "tokenIdOfWrappedToken"; + indexed: true; + }>; +}>; + +/** + * Creates an event object for the TokensUnwrapped event. + * @param filters - Optional filters to apply to the event. + * @returns The prepared event object. + * @extension ERC721 + * @example + * ```ts + * import { getContractEvents } from "thirdweb"; + * import { tokensUnwrappedEvent } from "thirdweb/extensions/erc721"; + * + * const events = await getContractEvents({ + * contract, + * events: [ + * tokensUnwrappedEvent({ + * unwrapper: ..., + * recipientOfWrappedContents: ..., + * tokenIdOfWrappedToken: ..., + * }) + * ], + * }); + * ``` + */ +export function tokensUnwrappedEvent( + filters: TokensUnwrappedEventFilters = {}, +) { + return prepareEvent({ + signature: + "event TokensUnwrapped(address indexed unwrapper, address indexed recipientOfWrappedContents, uint256 indexed tokenIdOfWrappedToken)", + filters, + }); +} diff --git a/packages/thirdweb/src/extensions/erc721/__generated__/Multiwrap/events/TokensWrapped.ts b/packages/thirdweb/src/extensions/erc721/__generated__/Multiwrap/events/TokensWrapped.ts new file mode 100644 index 00000000000..476e907ad6d --- /dev/null +++ b/packages/thirdweb/src/extensions/erc721/__generated__/Multiwrap/events/TokensWrapped.ts @@ -0,0 +1,53 @@ +import { prepareEvent } from "../../../../../event/prepare-event.js"; +import type { AbiParameterToPrimitiveType } from "abitype"; + +/** + * Represents the filters for the "TokensWrapped" event. + */ +export type TokensWrappedEventFilters = Partial<{ + wrapper: AbiParameterToPrimitiveType<{ + type: "address"; + name: "wrapper"; + indexed: true; + }>; + recipientOfWrappedToken: AbiParameterToPrimitiveType<{ + type: "address"; + name: "recipientOfWrappedToken"; + indexed: true; + }>; + tokenIdOfWrappedToken: AbiParameterToPrimitiveType<{ + type: "uint256"; + name: "tokenIdOfWrappedToken"; + indexed: true; + }>; +}>; + +/** + * Creates an event object for the TokensWrapped event. + * @param filters - Optional filters to apply to the event. + * @returns The prepared event object. + * @extension ERC721 + * @example + * ```ts + * import { getContractEvents } from "thirdweb"; + * import { tokensWrappedEvent } from "thirdweb/extensions/erc721"; + * + * const events = await getContractEvents({ + * contract, + * events: [ + * tokensWrappedEvent({ + * wrapper: ..., + * recipientOfWrappedToken: ..., + * tokenIdOfWrappedToken: ..., + * }) + * ], + * }); + * ``` + */ +export function tokensWrappedEvent(filters: TokensWrappedEventFilters = {}) { + return prepareEvent({ + signature: + "event TokensWrapped(address indexed wrapper, address indexed recipientOfWrappedToken, uint256 indexed tokenIdOfWrappedToken, (address assetContract, uint8 tokenType, uint256 tokenId, uint256 amount)[] wrappedContents)", + filters, + }); +} diff --git a/packages/thirdweb/src/extensions/erc721/__generated__/Multiwrap/read/contractType.ts b/packages/thirdweb/src/extensions/erc721/__generated__/Multiwrap/read/contractType.ts new file mode 100644 index 00000000000..1ea0195f972 --- /dev/null +++ b/packages/thirdweb/src/extensions/erc721/__generated__/Multiwrap/read/contractType.ts @@ -0,0 +1,70 @@ +import { readContract } from "../../../../../transaction/read-contract.js"; +import type { BaseTransactionOptions } from "../../../../../transaction/types.js"; + +import { decodeAbiParameters } from "viem"; +import type { Hex } from "../../../../../utils/encoding/hex.js"; +import { detectMethod } from "../../../../../utils/bytecode/detectExtension.js"; + +export const FN_SELECTOR = "0xcb2ef6f7" as const; +const FN_INPUTS = [] as const; +const FN_OUTPUTS = [ + { + type: "bytes32", + }, +] as const; + +/** + * Checks if the `contractType` method is supported by the given contract. + * @param availableSelectors An array of 4byte function selectors of the contract. You can get this in various ways, such as using "whatsabi" or if you have the ABI of the contract available you can use it to generate the selectors. + * @returns A boolean indicating if the `contractType` method is supported. + * @extension ERC721 + * @example + * ```ts + * import { isContractTypeSupported } from "thirdweb/extensions/erc721"; + * const supported = isContractTypeSupported(["0x..."]); + * ``` + */ +export function isContractTypeSupported(availableSelectors: string[]) { + return detectMethod({ + availableSelectors, + method: [FN_SELECTOR, FN_INPUTS, FN_OUTPUTS] as const, + }); +} + +/** + * Decodes the result of the contractType function call. + * @param result - The hexadecimal result to decode. + * @returns The decoded result as per the FN_OUTPUTS definition. + * @extension ERC721 + * @example + * ```ts + * import { decodeContractTypeResult } from "thirdweb/extensions/erc721"; + * const result = decodeContractTypeResultResult("..."); + * ``` + */ +export function decodeContractTypeResult(result: Hex) { + return decodeAbiParameters(FN_OUTPUTS, result)[0]; +} + +/** + * Calls the "contractType" function on the contract. + * @param options - The options for the contractType function. + * @returns The parsed result of the function call. + * @extension ERC721 + * @example + * ```ts + * import { contractType } from "thirdweb/extensions/erc721"; + * + * const result = await contractType({ + * contract, + * }); + * + * ``` + */ +export async function contractType(options: BaseTransactionOptions) { + return readContract({ + contract: options.contract, + method: [FN_SELECTOR, FN_INPUTS, FN_OUTPUTS] as const, + params: [], + }); +} diff --git a/packages/thirdweb/src/extensions/erc721/__generated__/Multiwrap/read/contractVersion.ts b/packages/thirdweb/src/extensions/erc721/__generated__/Multiwrap/read/contractVersion.ts new file mode 100644 index 00000000000..c8d50c84091 --- /dev/null +++ b/packages/thirdweb/src/extensions/erc721/__generated__/Multiwrap/read/contractVersion.ts @@ -0,0 +1,70 @@ +import { readContract } from "../../../../../transaction/read-contract.js"; +import type { BaseTransactionOptions } from "../../../../../transaction/types.js"; + +import { decodeAbiParameters } from "viem"; +import type { Hex } from "../../../../../utils/encoding/hex.js"; +import { detectMethod } from "../../../../../utils/bytecode/detectExtension.js"; + +export const FN_SELECTOR = "0xa0a8e460" as const; +const FN_INPUTS = [] as const; +const FN_OUTPUTS = [ + { + type: "uint8", + }, +] as const; + +/** + * Checks if the `contractVersion` method is supported by the given contract. + * @param availableSelectors An array of 4byte function selectors of the contract. You can get this in various ways, such as using "whatsabi" or if you have the ABI of the contract available you can use it to generate the selectors. + * @returns A boolean indicating if the `contractVersion` method is supported. + * @extension ERC721 + * @example + * ```ts + * import { isContractVersionSupported } from "thirdweb/extensions/erc721"; + * const supported = isContractVersionSupported(["0x..."]); + * ``` + */ +export function isContractVersionSupported(availableSelectors: string[]) { + return detectMethod({ + availableSelectors, + method: [FN_SELECTOR, FN_INPUTS, FN_OUTPUTS] as const, + }); +} + +/** + * Decodes the result of the contractVersion function call. + * @param result - The hexadecimal result to decode. + * @returns The decoded result as per the FN_OUTPUTS definition. + * @extension ERC721 + * @example + * ```ts + * import { decodeContractVersionResult } from "thirdweb/extensions/erc721"; + * const result = decodeContractVersionResultResult("..."); + * ``` + */ +export function decodeContractVersionResult(result: Hex) { + return decodeAbiParameters(FN_OUTPUTS, result)[0]; +} + +/** + * Calls the "contractVersion" function on the contract. + * @param options - The options for the contractVersion function. + * @returns The parsed result of the function call. + * @extension ERC721 + * @example + * ```ts + * import { contractVersion } from "thirdweb/extensions/erc721"; + * + * const result = await contractVersion({ + * contract, + * }); + * + * ``` + */ +export async function contractVersion(options: BaseTransactionOptions) { + return readContract({ + contract: options.contract, + method: [FN_SELECTOR, FN_INPUTS, FN_OUTPUTS] as const, + params: [], + }); +} diff --git a/packages/thirdweb/src/extensions/erc721/__generated__/Multiwrap/read/getWrappedContents.ts b/packages/thirdweb/src/extensions/erc721/__generated__/Multiwrap/read/getWrappedContents.ts new file mode 100644 index 00000000000..4b768cdca11 --- /dev/null +++ b/packages/thirdweb/src/extensions/erc721/__generated__/Multiwrap/read/getWrappedContents.ts @@ -0,0 +1,146 @@ +import type { AbiParameterToPrimitiveType } from "abitype"; +import { readContract } from "../../../../../transaction/read-contract.js"; +import type { BaseTransactionOptions } from "../../../../../transaction/types.js"; +import { encodeAbiParameters } from "../../../../../utils/abi/encodeAbiParameters.js"; +import { decodeAbiParameters } from "viem"; +import type { Hex } from "../../../../../utils/encoding/hex.js"; +import { detectMethod } from "../../../../../utils/bytecode/detectExtension.js"; + +/** + * Represents the parameters for the "getWrappedContents" function. + */ +export type GetWrappedContentsParams = { + tokenId: AbiParameterToPrimitiveType<{ type: "uint256"; name: "_tokenId" }>; +}; + +export const FN_SELECTOR = "0xd5576d26" as const; +const FN_INPUTS = [ + { + type: "uint256", + name: "_tokenId", + }, +] as const; +const FN_OUTPUTS = [ + { + type: "tuple[]", + name: "contents", + components: [ + { + type: "address", + name: "assetContract", + }, + { + type: "uint8", + name: "tokenType", + }, + { + type: "uint256", + name: "tokenId", + }, + { + type: "uint256", + name: "amount", + }, + ], + }, +] as const; + +/** + * Checks if the `getWrappedContents` method is supported by the given contract. + * @param availableSelectors An array of 4byte function selectors of the contract. You can get this in various ways, such as using "whatsabi" or if you have the ABI of the contract available you can use it to generate the selectors. + * @returns A boolean indicating if the `getWrappedContents` method is supported. + * @extension ERC721 + * @example + * ```ts + * import { isGetWrappedContentsSupported } from "thirdweb/extensions/erc721"; + * const supported = isGetWrappedContentsSupported(["0x..."]); + * ``` + */ +export function isGetWrappedContentsSupported(availableSelectors: string[]) { + return detectMethod({ + availableSelectors, + method: [FN_SELECTOR, FN_INPUTS, FN_OUTPUTS] as const, + }); +} + +/** + * Encodes the parameters for the "getWrappedContents" function. + * @param options - The options for the getWrappedContents function. + * @returns The encoded ABI parameters. + * @extension ERC721 + * @example + * ```ts + * import { encodeGetWrappedContentsParams } from "thirdweb/extensions/erc721"; + * const result = encodeGetWrappedContentsParams({ + * tokenId: ..., + * }); + * ``` + */ +export function encodeGetWrappedContentsParams( + options: GetWrappedContentsParams, +) { + return encodeAbiParameters(FN_INPUTS, [options.tokenId]); +} + +/** + * Encodes the "getWrappedContents" function into a Hex string with its parameters. + * @param options - The options for the getWrappedContents function. + * @returns The encoded hexadecimal string. + * @extension ERC721 + * @example + * ```ts + * import { encodeGetWrappedContents } from "thirdweb/extensions/erc721"; + * const result = encodeGetWrappedContents({ + * tokenId: ..., + * }); + * ``` + */ +export function encodeGetWrappedContents(options: GetWrappedContentsParams) { + // we do a "manual" concat here to avoid the overhead of the "concatHex" function + // we can do this because we know the specific formats of the values + return (FN_SELECTOR + + encodeGetWrappedContentsParams(options).slice( + 2, + )) as `${typeof FN_SELECTOR}${string}`; +} + +/** + * Decodes the result of the getWrappedContents function call. + * @param result - The hexadecimal result to decode. + * @returns The decoded result as per the FN_OUTPUTS definition. + * @extension ERC721 + * @example + * ```ts + * import { decodeGetWrappedContentsResult } from "thirdweb/extensions/erc721"; + * const result = decodeGetWrappedContentsResultResult("..."); + * ``` + */ +export function decodeGetWrappedContentsResult(result: Hex) { + return decodeAbiParameters(FN_OUTPUTS, result)[0]; +} + +/** + * Calls the "getWrappedContents" function on the contract. + * @param options - The options for the getWrappedContents function. + * @returns The parsed result of the function call. + * @extension ERC721 + * @example + * ```ts + * import { getWrappedContents } from "thirdweb/extensions/erc721"; + * + * const result = await getWrappedContents({ + * contract, + * tokenId: ..., + * }); + * + * ``` + */ +export async function getWrappedContents( + options: BaseTransactionOptions, +) { + return readContract({ + contract: options.contract, + method: [FN_SELECTOR, FN_INPUTS, FN_OUTPUTS] as const, + params: [options.tokenId], + }); +} diff --git a/packages/thirdweb/src/extensions/erc721/__generated__/Multiwrap/read/nextTokenIdToMint.ts b/packages/thirdweb/src/extensions/erc721/__generated__/Multiwrap/read/nextTokenIdToMint.ts new file mode 100644 index 00000000000..abab41a1765 --- /dev/null +++ b/packages/thirdweb/src/extensions/erc721/__generated__/Multiwrap/read/nextTokenIdToMint.ts @@ -0,0 +1,70 @@ +import { readContract } from "../../../../../transaction/read-contract.js"; +import type { BaseTransactionOptions } from "../../../../../transaction/types.js"; + +import { decodeAbiParameters } from "viem"; +import type { Hex } from "../../../../../utils/encoding/hex.js"; +import { detectMethod } from "../../../../../utils/bytecode/detectExtension.js"; + +export const FN_SELECTOR = "0x3b1475a7" as const; +const FN_INPUTS = [] as const; +const FN_OUTPUTS = [ + { + type: "uint256", + }, +] as const; + +/** + * Checks if the `nextTokenIdToMint` method is supported by the given contract. + * @param availableSelectors An array of 4byte function selectors of the contract. You can get this in various ways, such as using "whatsabi" or if you have the ABI of the contract available you can use it to generate the selectors. + * @returns A boolean indicating if the `nextTokenIdToMint` method is supported. + * @extension ERC721 + * @example + * ```ts + * import { isNextTokenIdToMintSupported } from "thirdweb/extensions/erc721"; + * const supported = isNextTokenIdToMintSupported(["0x..."]); + * ``` + */ +export function isNextTokenIdToMintSupported(availableSelectors: string[]) { + return detectMethod({ + availableSelectors, + method: [FN_SELECTOR, FN_INPUTS, FN_OUTPUTS] as const, + }); +} + +/** + * Decodes the result of the nextTokenIdToMint function call. + * @param result - The hexadecimal result to decode. + * @returns The decoded result as per the FN_OUTPUTS definition. + * @extension ERC721 + * @example + * ```ts + * import { decodeNextTokenIdToMintResult } from "thirdweb/extensions/erc721"; + * const result = decodeNextTokenIdToMintResultResult("..."); + * ``` + */ +export function decodeNextTokenIdToMintResult(result: Hex) { + return decodeAbiParameters(FN_OUTPUTS, result)[0]; +} + +/** + * Calls the "nextTokenIdToMint" function on the contract. + * @param options - The options for the nextTokenIdToMint function. + * @returns The parsed result of the function call. + * @extension ERC721 + * @example + * ```ts + * import { nextTokenIdToMint } from "thirdweb/extensions/erc721"; + * + * const result = await nextTokenIdToMint({ + * contract, + * }); + * + * ``` + */ +export async function nextTokenIdToMint(options: BaseTransactionOptions) { + return readContract({ + contract: options.contract, + method: [FN_SELECTOR, FN_INPUTS, FN_OUTPUTS] as const, + params: [], + }); +} diff --git a/packages/thirdweb/src/extensions/erc721/__generated__/Multiwrap/read/supportsInterface.ts b/packages/thirdweb/src/extensions/erc721/__generated__/Multiwrap/read/supportsInterface.ts new file mode 100644 index 00000000000..0f6b2f9089d --- /dev/null +++ b/packages/thirdweb/src/extensions/erc721/__generated__/Multiwrap/read/supportsInterface.ts @@ -0,0 +1,130 @@ +import type { AbiParameterToPrimitiveType } from "abitype"; +import { readContract } from "../../../../../transaction/read-contract.js"; +import type { BaseTransactionOptions } from "../../../../../transaction/types.js"; +import { encodeAbiParameters } from "../../../../../utils/abi/encodeAbiParameters.js"; +import { decodeAbiParameters } from "viem"; +import type { Hex } from "../../../../../utils/encoding/hex.js"; +import { detectMethod } from "../../../../../utils/bytecode/detectExtension.js"; + +/** + * Represents the parameters for the "supportsInterface" function. + */ +export type SupportsInterfaceParams = { + interfaceId: AbiParameterToPrimitiveType<{ + type: "bytes4"; + name: "interfaceId"; + }>; +}; + +export const FN_SELECTOR = "0x01ffc9a7" as const; +const FN_INPUTS = [ + { + type: "bytes4", + name: "interfaceId", + }, +] as const; +const FN_OUTPUTS = [ + { + type: "bool", + }, +] as const; + +/** + * Checks if the `supportsInterface` method is supported by the given contract. + * @param availableSelectors An array of 4byte function selectors of the contract. You can get this in various ways, such as using "whatsabi" or if you have the ABI of the contract available you can use it to generate the selectors. + * @returns A boolean indicating if the `supportsInterface` method is supported. + * @extension ERC721 + * @example + * ```ts + * import { isSupportsInterfaceSupported } from "thirdweb/extensions/erc721"; + * const supported = isSupportsInterfaceSupported(["0x..."]); + * ``` + */ +export function isSupportsInterfaceSupported(availableSelectors: string[]) { + return detectMethod({ + availableSelectors, + method: [FN_SELECTOR, FN_INPUTS, FN_OUTPUTS] as const, + }); +} + +/** + * Encodes the parameters for the "supportsInterface" function. + * @param options - The options for the supportsInterface function. + * @returns The encoded ABI parameters. + * @extension ERC721 + * @example + * ```ts + * import { encodeSupportsInterfaceParams } from "thirdweb/extensions/erc721"; + * const result = encodeSupportsInterfaceParams({ + * interfaceId: ..., + * }); + * ``` + */ +export function encodeSupportsInterfaceParams( + options: SupportsInterfaceParams, +) { + return encodeAbiParameters(FN_INPUTS, [options.interfaceId]); +} + +/** + * Encodes the "supportsInterface" function into a Hex string with its parameters. + * @param options - The options for the supportsInterface function. + * @returns The encoded hexadecimal string. + * @extension ERC721 + * @example + * ```ts + * import { encodeSupportsInterface } from "thirdweb/extensions/erc721"; + * const result = encodeSupportsInterface({ + * interfaceId: ..., + * }); + * ``` + */ +export function encodeSupportsInterface(options: SupportsInterfaceParams) { + // we do a "manual" concat here to avoid the overhead of the "concatHex" function + // we can do this because we know the specific formats of the values + return (FN_SELECTOR + + encodeSupportsInterfaceParams(options).slice( + 2, + )) as `${typeof FN_SELECTOR}${string}`; +} + +/** + * Decodes the result of the supportsInterface function call. + * @param result - The hexadecimal result to decode. + * @returns The decoded result as per the FN_OUTPUTS definition. + * @extension ERC721 + * @example + * ```ts + * import { decodeSupportsInterfaceResult } from "thirdweb/extensions/erc721"; + * const result = decodeSupportsInterfaceResultResult("..."); + * ``` + */ +export function decodeSupportsInterfaceResult(result: Hex) { + return decodeAbiParameters(FN_OUTPUTS, result)[0]; +} + +/** + * Calls the "supportsInterface" function on the contract. + * @param options - The options for the supportsInterface function. + * @returns The parsed result of the function call. + * @extension ERC721 + * @example + * ```ts + * import { supportsInterface } from "thirdweb/extensions/erc721"; + * + * const result = await supportsInterface({ + * contract, + * interfaceId: ..., + * }); + * + * ``` + */ +export async function supportsInterface( + options: BaseTransactionOptions, +) { + return readContract({ + contract: options.contract, + method: [FN_SELECTOR, FN_INPUTS, FN_OUTPUTS] as const, + params: [options.interfaceId], + }); +} diff --git a/packages/thirdweb/src/extensions/erc721/__generated__/Multiwrap/read/tokenURI.ts b/packages/thirdweb/src/extensions/erc721/__generated__/Multiwrap/read/tokenURI.ts new file mode 100644 index 00000000000..cdd424d3861 --- /dev/null +++ b/packages/thirdweb/src/extensions/erc721/__generated__/Multiwrap/read/tokenURI.ts @@ -0,0 +1,123 @@ +import type { AbiParameterToPrimitiveType } from "abitype"; +import { readContract } from "../../../../../transaction/read-contract.js"; +import type { BaseTransactionOptions } from "../../../../../transaction/types.js"; +import { encodeAbiParameters } from "../../../../../utils/abi/encodeAbiParameters.js"; +import { decodeAbiParameters } from "viem"; +import type { Hex } from "../../../../../utils/encoding/hex.js"; +import { detectMethod } from "../../../../../utils/bytecode/detectExtension.js"; + +/** + * Represents the parameters for the "tokenURI" function. + */ +export type TokenURIParams = { + tokenId: AbiParameterToPrimitiveType<{ type: "uint256"; name: "_tokenId" }>; +}; + +export const FN_SELECTOR = "0xc87b56dd" as const; +const FN_INPUTS = [ + { + type: "uint256", + name: "_tokenId", + }, +] as const; +const FN_OUTPUTS = [ + { + type: "string", + }, +] as const; + +/** + * Checks if the `tokenURI` method is supported by the given contract. + * @param availableSelectors An array of 4byte function selectors of the contract. You can get this in various ways, such as using "whatsabi" or if you have the ABI of the contract available you can use it to generate the selectors. + * @returns A boolean indicating if the `tokenURI` method is supported. + * @extension ERC721 + * @example + * ```ts + * import { isTokenURISupported } from "thirdweb/extensions/erc721"; + * const supported = isTokenURISupported(["0x..."]); + * ``` + */ +export function isTokenURISupported(availableSelectors: string[]) { + return detectMethod({ + availableSelectors, + method: [FN_SELECTOR, FN_INPUTS, FN_OUTPUTS] as const, + }); +} + +/** + * Encodes the parameters for the "tokenURI" function. + * @param options - The options for the tokenURI function. + * @returns The encoded ABI parameters. + * @extension ERC721 + * @example + * ```ts + * import { encodeTokenURIParams } from "thirdweb/extensions/erc721"; + * const result = encodeTokenURIParams({ + * tokenId: ..., + * }); + * ``` + */ +export function encodeTokenURIParams(options: TokenURIParams) { + return encodeAbiParameters(FN_INPUTS, [options.tokenId]); +} + +/** + * Encodes the "tokenURI" function into a Hex string with its parameters. + * @param options - The options for the tokenURI function. + * @returns The encoded hexadecimal string. + * @extension ERC721 + * @example + * ```ts + * import { encodeTokenURI } from "thirdweb/extensions/erc721"; + * const result = encodeTokenURI({ + * tokenId: ..., + * }); + * ``` + */ +export function encodeTokenURI(options: TokenURIParams) { + // we do a "manual" concat here to avoid the overhead of the "concatHex" function + // we can do this because we know the specific formats of the values + return (FN_SELECTOR + + encodeTokenURIParams(options).slice(2)) as `${typeof FN_SELECTOR}${string}`; +} + +/** + * Decodes the result of the tokenURI function call. + * @param result - The hexadecimal result to decode. + * @returns The decoded result as per the FN_OUTPUTS definition. + * @extension ERC721 + * @example + * ```ts + * import { decodeTokenURIResult } from "thirdweb/extensions/erc721"; + * const result = decodeTokenURIResultResult("..."); + * ``` + */ +export function decodeTokenURIResult(result: Hex) { + return decodeAbiParameters(FN_OUTPUTS, result)[0]; +} + +/** + * Calls the "tokenURI" function on the contract. + * @param options - The options for the tokenURI function. + * @returns The parsed result of the function call. + * @extension ERC721 + * @example + * ```ts + * import { tokenURI } from "thirdweb/extensions/erc721"; + * + * const result = await tokenURI({ + * contract, + * tokenId: ..., + * }); + * + * ``` + */ +export async function tokenURI( + options: BaseTransactionOptions, +) { + return readContract({ + contract: options.contract, + method: [FN_SELECTOR, FN_INPUTS, FN_OUTPUTS] as const, + params: [options.tokenId], + }); +} diff --git a/packages/thirdweb/src/extensions/erc721/__generated__/Multiwrap/write/initialize.ts b/packages/thirdweb/src/extensions/erc721/__generated__/Multiwrap/write/initialize.ts new file mode 100644 index 00000000000..30b0ad0e6f7 --- /dev/null +++ b/packages/thirdweb/src/extensions/erc721/__generated__/Multiwrap/write/initialize.ts @@ -0,0 +1,216 @@ +import type { AbiParameterToPrimitiveType } from "abitype"; +import type { + BaseTransactionOptions, + WithOverrides, +} from "../../../../../transaction/types.js"; +import { prepareContractCall } from "../../../../../transaction/prepare-contract-call.js"; +import { encodeAbiParameters } from "../../../../../utils/abi/encodeAbiParameters.js"; +import { once } from "../../../../../utils/promise/once.js"; +import { detectMethod } from "../../../../../utils/bytecode/detectExtension.js"; + +/** + * Represents the parameters for the "initialize" function. + */ +export type InitializeParams = WithOverrides<{ + defaultAdmin: AbiParameterToPrimitiveType<{ + type: "address"; + name: "_defaultAdmin"; + }>; + name: AbiParameterToPrimitiveType<{ type: "string"; name: "_name" }>; + symbol: AbiParameterToPrimitiveType<{ type: "string"; name: "_symbol" }>; + contractURI: AbiParameterToPrimitiveType<{ + type: "string"; + name: "_contractURI"; + }>; + trustedForwarders: AbiParameterToPrimitiveType<{ + type: "address[]"; + name: "_trustedForwarders"; + }>; + royaltyRecipient: AbiParameterToPrimitiveType<{ + type: "address"; + name: "_royaltyRecipient"; + }>; + royaltyBps: AbiParameterToPrimitiveType<{ + type: "uint256"; + name: "_royaltyBps"; + }>; +}>; + +export const FN_SELECTOR = "0x754b8fe7" as const; +const FN_INPUTS = [ + { + type: "address", + name: "_defaultAdmin", + }, + { + type: "string", + name: "_name", + }, + { + type: "string", + name: "_symbol", + }, + { + type: "string", + name: "_contractURI", + }, + { + type: "address[]", + name: "_trustedForwarders", + }, + { + type: "address", + name: "_royaltyRecipient", + }, + { + type: "uint256", + name: "_royaltyBps", + }, +] as const; +const FN_OUTPUTS = [] as const; + +/** + * Checks if the `initialize` method is supported by the given contract. + * @param availableSelectors An array of 4byte function selectors of the contract. You can get this in various ways, such as using "whatsabi" or if you have the ABI of the contract available you can use it to generate the selectors. + * @returns A boolean indicating if the `initialize` method is supported. + * @extension ERC721 + * @example + * ```ts + * import { isInitializeSupported } from "thirdweb/extensions/erc721"; + * + * const supported = isInitializeSupported(["0x..."]); + * ``` + */ +export function isInitializeSupported(availableSelectors: string[]) { + return detectMethod({ + availableSelectors, + method: [FN_SELECTOR, FN_INPUTS, FN_OUTPUTS] as const, + }); +} + +/** + * Encodes the parameters for the "initialize" function. + * @param options - The options for the initialize function. + * @returns The encoded ABI parameters. + * @extension ERC721 + * @example + * ```ts + * import { encodeInitializeParams } from "thirdweb/extensions/erc721"; + * const result = encodeInitializeParams({ + * defaultAdmin: ..., + * name: ..., + * symbol: ..., + * contractURI: ..., + * trustedForwarders: ..., + * royaltyRecipient: ..., + * royaltyBps: ..., + * }); + * ``` + */ +export function encodeInitializeParams(options: InitializeParams) { + return encodeAbiParameters(FN_INPUTS, [ + options.defaultAdmin, + options.name, + options.symbol, + options.contractURI, + options.trustedForwarders, + options.royaltyRecipient, + options.royaltyBps, + ]); +} + +/** + * Encodes the "initialize" function into a Hex string with its parameters. + * @param options - The options for the initialize function. + * @returns The encoded hexadecimal string. + * @extension ERC721 + * @example + * ```ts + * import { encodeInitialize } from "thirdweb/extensions/erc721"; + * const result = encodeInitialize({ + * defaultAdmin: ..., + * name: ..., + * symbol: ..., + * contractURI: ..., + * trustedForwarders: ..., + * royaltyRecipient: ..., + * royaltyBps: ..., + * }); + * ``` + */ +export function encodeInitialize(options: InitializeParams) { + // we do a "manual" concat here to avoid the overhead of the "concatHex" function + // we can do this because we know the specific formats of the values + return (FN_SELECTOR + + encodeInitializeParams(options).slice( + 2, + )) as `${typeof FN_SELECTOR}${string}`; +} + +/** + * Prepares a transaction to call the "initialize" function on the contract. + * @param options - The options for the "initialize" function. + * @returns A prepared transaction object. + * @extension ERC721 + * @example + * ```ts + * import { sendTransaction } from "thirdweb"; + * import { initialize } from "thirdweb/extensions/erc721"; + * + * const transaction = initialize({ + * contract, + * defaultAdmin: ..., + * name: ..., + * symbol: ..., + * contractURI: ..., + * trustedForwarders: ..., + * royaltyRecipient: ..., + * royaltyBps: ..., + * overrides: { + * ... + * } + * }); + * + * // Send the transaction + * await sendTransaction({ transaction, account }); + * ``` + */ +export function initialize( + options: BaseTransactionOptions< + | InitializeParams + | { + asyncParams: () => Promise; + } + >, +) { + const asyncOptions = once(async () => { + return "asyncParams" in options ? await options.asyncParams() : options; + }); + + return prepareContractCall({ + contract: options.contract, + method: [FN_SELECTOR, FN_INPUTS, FN_OUTPUTS] as const, + params: async () => { + const resolvedOptions = await asyncOptions(); + return [ + resolvedOptions.defaultAdmin, + resolvedOptions.name, + resolvedOptions.symbol, + resolvedOptions.contractURI, + resolvedOptions.trustedForwarders, + resolvedOptions.royaltyRecipient, + resolvedOptions.royaltyBps, + ] as const; + }, + value: async () => (await asyncOptions()).overrides?.value, + accessList: async () => (await asyncOptions()).overrides?.accessList, + gas: async () => (await asyncOptions()).overrides?.gas, + gasPrice: async () => (await asyncOptions()).overrides?.gasPrice, + maxFeePerGas: async () => (await asyncOptions()).overrides?.maxFeePerGas, + maxPriorityFeePerGas: async () => + (await asyncOptions()).overrides?.maxPriorityFeePerGas, + nonce: async () => (await asyncOptions()).overrides?.nonce, + extraGas: async () => (await asyncOptions()).overrides?.extraGas, + erc20Value: async () => (await asyncOptions()).overrides?.erc20Value, + }); +} diff --git a/packages/thirdweb/src/extensions/erc721/__generated__/Multiwrap/write/unwrap.ts b/packages/thirdweb/src/extensions/erc721/__generated__/Multiwrap/write/unwrap.ts new file mode 100644 index 00000000000..d46680b4329 --- /dev/null +++ b/packages/thirdweb/src/extensions/erc721/__generated__/Multiwrap/write/unwrap.ts @@ -0,0 +1,146 @@ +import type { AbiParameterToPrimitiveType } from "abitype"; +import type { + BaseTransactionOptions, + WithOverrides, +} from "../../../../../transaction/types.js"; +import { prepareContractCall } from "../../../../../transaction/prepare-contract-call.js"; +import { encodeAbiParameters } from "../../../../../utils/abi/encodeAbiParameters.js"; +import { once } from "../../../../../utils/promise/once.js"; +import { detectMethod } from "../../../../../utils/bytecode/detectExtension.js"; + +/** + * Represents the parameters for the "unwrap" function. + */ +export type UnwrapParams = WithOverrides<{ + tokenId: AbiParameterToPrimitiveType<{ type: "uint256"; name: "_tokenId" }>; + recipient: AbiParameterToPrimitiveType<{ + type: "address"; + name: "_recipient"; + }>; +}>; + +export const FN_SELECTOR = "0x7647691d" as const; +const FN_INPUTS = [ + { + type: "uint256", + name: "_tokenId", + }, + { + type: "address", + name: "_recipient", + }, +] as const; +const FN_OUTPUTS = [] as const; + +/** + * Checks if the `unwrap` method is supported by the given contract. + * @param availableSelectors An array of 4byte function selectors of the contract. You can get this in various ways, such as using "whatsabi" or if you have the ABI of the contract available you can use it to generate the selectors. + * @returns A boolean indicating if the `unwrap` method is supported. + * @extension ERC721 + * @example + * ```ts + * import { isUnwrapSupported } from "thirdweb/extensions/erc721"; + * + * const supported = isUnwrapSupported(["0x..."]); + * ``` + */ +export function isUnwrapSupported(availableSelectors: string[]) { + return detectMethod({ + availableSelectors, + method: [FN_SELECTOR, FN_INPUTS, FN_OUTPUTS] as const, + }); +} + +/** + * Encodes the parameters for the "unwrap" function. + * @param options - The options for the unwrap function. + * @returns The encoded ABI parameters. + * @extension ERC721 + * @example + * ```ts + * import { encodeUnwrapParams } from "thirdweb/extensions/erc721"; + * const result = encodeUnwrapParams({ + * tokenId: ..., + * recipient: ..., + * }); + * ``` + */ +export function encodeUnwrapParams(options: UnwrapParams) { + return encodeAbiParameters(FN_INPUTS, [options.tokenId, options.recipient]); +} + +/** + * Encodes the "unwrap" function into a Hex string with its parameters. + * @param options - The options for the unwrap function. + * @returns The encoded hexadecimal string. + * @extension ERC721 + * @example + * ```ts + * import { encodeUnwrap } from "thirdweb/extensions/erc721"; + * const result = encodeUnwrap({ + * tokenId: ..., + * recipient: ..., + * }); + * ``` + */ +export function encodeUnwrap(options: UnwrapParams) { + // we do a "manual" concat here to avoid the overhead of the "concatHex" function + // we can do this because we know the specific formats of the values + return (FN_SELECTOR + + encodeUnwrapParams(options).slice(2)) as `${typeof FN_SELECTOR}${string}`; +} + +/** + * Prepares a transaction to call the "unwrap" function on the contract. + * @param options - The options for the "unwrap" function. + * @returns A prepared transaction object. + * @extension ERC721 + * @example + * ```ts + * import { sendTransaction } from "thirdweb"; + * import { unwrap } from "thirdweb/extensions/erc721"; + * + * const transaction = unwrap({ + * contract, + * tokenId: ..., + * recipient: ..., + * overrides: { + * ... + * } + * }); + * + * // Send the transaction + * await sendTransaction({ transaction, account }); + * ``` + */ +export function unwrap( + options: BaseTransactionOptions< + | UnwrapParams + | { + asyncParams: () => Promise; + } + >, +) { + const asyncOptions = once(async () => { + return "asyncParams" in options ? await options.asyncParams() : options; + }); + + return prepareContractCall({ + contract: options.contract, + method: [FN_SELECTOR, FN_INPUTS, FN_OUTPUTS] as const, + params: async () => { + const resolvedOptions = await asyncOptions(); + return [resolvedOptions.tokenId, resolvedOptions.recipient] as const; + }, + value: async () => (await asyncOptions()).overrides?.value, + accessList: async () => (await asyncOptions()).overrides?.accessList, + gas: async () => (await asyncOptions()).overrides?.gas, + gasPrice: async () => (await asyncOptions()).overrides?.gasPrice, + maxFeePerGas: async () => (await asyncOptions()).overrides?.maxFeePerGas, + maxPriorityFeePerGas: async () => + (await asyncOptions()).overrides?.maxPriorityFeePerGas, + nonce: async () => (await asyncOptions()).overrides?.nonce, + extraGas: async () => (await asyncOptions()).overrides?.extraGas, + erc20Value: async () => (await asyncOptions()).overrides?.erc20Value, + }); +} diff --git a/packages/thirdweb/src/extensions/erc721/__generated__/Multiwrap/write/wrap.ts b/packages/thirdweb/src/extensions/erc721/__generated__/Multiwrap/write/wrap.ts new file mode 100644 index 00000000000..0bde3d448ad --- /dev/null +++ b/packages/thirdweb/src/extensions/erc721/__generated__/Multiwrap/write/wrap.ts @@ -0,0 +1,197 @@ +import type { AbiParameterToPrimitiveType } from "abitype"; +import type { + BaseTransactionOptions, + WithOverrides, +} from "../../../../../transaction/types.js"; +import { prepareContractCall } from "../../../../../transaction/prepare-contract-call.js"; +import { encodeAbiParameters } from "../../../../../utils/abi/encodeAbiParameters.js"; +import { once } from "../../../../../utils/promise/once.js"; +import { detectMethod } from "../../../../../utils/bytecode/detectExtension.js"; + +/** + * Represents the parameters for the "wrap" function. + */ +export type WrapParams = WithOverrides<{ + tokensToWrap: AbiParameterToPrimitiveType<{ + type: "tuple[]"; + name: "_tokensToWrap"; + components: [ + { type: "address"; name: "assetContract" }, + { type: "uint8"; name: "tokenType" }, + { type: "uint256"; name: "tokenId" }, + { type: "uint256"; name: "amount" }, + ]; + }>; + uriForWrappedToken: AbiParameterToPrimitiveType<{ + type: "string"; + name: "_uriForWrappedToken"; + }>; + recipient: AbiParameterToPrimitiveType<{ + type: "address"; + name: "_recipient"; + }>; +}>; + +export const FN_SELECTOR = "0x29e471dd" as const; +const FN_INPUTS = [ + { + type: "tuple[]", + name: "_tokensToWrap", + components: [ + { + type: "address", + name: "assetContract", + }, + { + type: "uint8", + name: "tokenType", + }, + { + type: "uint256", + name: "tokenId", + }, + { + type: "uint256", + name: "amount", + }, + ], + }, + { + type: "string", + name: "_uriForWrappedToken", + }, + { + type: "address", + name: "_recipient", + }, +] as const; +const FN_OUTPUTS = [ + { + type: "uint256", + name: "tokenId", + }, +] as const; + +/** + * Checks if the `wrap` method is supported by the given contract. + * @param availableSelectors An array of 4byte function selectors of the contract. You can get this in various ways, such as using "whatsabi" or if you have the ABI of the contract available you can use it to generate the selectors. + * @returns A boolean indicating if the `wrap` method is supported. + * @extension ERC721 + * @example + * ```ts + * import { isWrapSupported } from "thirdweb/extensions/erc721"; + * + * const supported = isWrapSupported(["0x..."]); + * ``` + */ +export function isWrapSupported(availableSelectors: string[]) { + return detectMethod({ + availableSelectors, + method: [FN_SELECTOR, FN_INPUTS, FN_OUTPUTS] as const, + }); +} + +/** + * Encodes the parameters for the "wrap" function. + * @param options - The options for the wrap function. + * @returns The encoded ABI parameters. + * @extension ERC721 + * @example + * ```ts + * import { encodeWrapParams } from "thirdweb/extensions/erc721"; + * const result = encodeWrapParams({ + * tokensToWrap: ..., + * uriForWrappedToken: ..., + * recipient: ..., + * }); + * ``` + */ +export function encodeWrapParams(options: WrapParams) { + return encodeAbiParameters(FN_INPUTS, [ + options.tokensToWrap, + options.uriForWrappedToken, + options.recipient, + ]); +} + +/** + * Encodes the "wrap" function into a Hex string with its parameters. + * @param options - The options for the wrap function. + * @returns The encoded hexadecimal string. + * @extension ERC721 + * @example + * ```ts + * import { encodeWrap } from "thirdweb/extensions/erc721"; + * const result = encodeWrap({ + * tokensToWrap: ..., + * uriForWrappedToken: ..., + * recipient: ..., + * }); + * ``` + */ +export function encodeWrap(options: WrapParams) { + // we do a "manual" concat here to avoid the overhead of the "concatHex" function + // we can do this because we know the specific formats of the values + return (FN_SELECTOR + + encodeWrapParams(options).slice(2)) as `${typeof FN_SELECTOR}${string}`; +} + +/** + * Prepares a transaction to call the "wrap" function on the contract. + * @param options - The options for the "wrap" function. + * @returns A prepared transaction object. + * @extension ERC721 + * @example + * ```ts + * import { sendTransaction } from "thirdweb"; + * import { wrap } from "thirdweb/extensions/erc721"; + * + * const transaction = wrap({ + * contract, + * tokensToWrap: ..., + * uriForWrappedToken: ..., + * recipient: ..., + * overrides: { + * ... + * } + * }); + * + * // Send the transaction + * await sendTransaction({ transaction, account }); + * ``` + */ +export function wrap( + options: BaseTransactionOptions< + | WrapParams + | { + asyncParams: () => Promise; + } + >, +) { + const asyncOptions = once(async () => { + return "asyncParams" in options ? await options.asyncParams() : options; + }); + + return prepareContractCall({ + contract: options.contract, + method: [FN_SELECTOR, FN_INPUTS, FN_OUTPUTS] as const, + params: async () => { + const resolvedOptions = await asyncOptions(); + return [ + resolvedOptions.tokensToWrap, + resolvedOptions.uriForWrappedToken, + resolvedOptions.recipient, + ] as const; + }, + value: async () => (await asyncOptions()).overrides?.value, + accessList: async () => (await asyncOptions()).overrides?.accessList, + gas: async () => (await asyncOptions()).overrides?.gas, + gasPrice: async () => (await asyncOptions()).overrides?.gasPrice, + maxFeePerGas: async () => (await asyncOptions()).overrides?.maxFeePerGas, + maxPriorityFeePerGas: async () => + (await asyncOptions()).overrides?.maxPriorityFeePerGas, + nonce: async () => (await asyncOptions()).overrides?.nonce, + extraGas: async () => (await asyncOptions()).overrides?.extraGas, + erc20Value: async () => (await asyncOptions()).overrides?.erc20Value, + }); +} diff --git a/packages/thirdweb/src/extensions/prebuilts/deploy-erc721.test.ts b/packages/thirdweb/src/extensions/prebuilts/deploy-erc721.test.ts index eefb338f913..0d5681c843c 100644 --- a/packages/thirdweb/src/extensions/prebuilts/deploy-erc721.test.ts +++ b/packages/thirdweb/src/extensions/prebuilts/deploy-erc721.test.ts @@ -8,8 +8,6 @@ import { deployERC721Contract } from "./deploy-erc721.js"; const account = TEST_ACCOUNT_B; -// skip this test suite if there is no secret key available to test with -// TODO: remove reliance on secret key during unit tests entirely describe.runIf(process.env.TW_SECRET_KEY)("deployERC721", () => { it("should deploy ERC721 open edition", async () => { const address = await deployERC721Contract({ @@ -21,6 +19,7 @@ describe.runIf(process.env.TW_SECRET_KEY)("deployERC721", () => { name: "OE", }, }); + expect(address).toBeDefined(); const deployedName = await name({ contract: getContract({ @@ -31,4 +30,73 @@ describe.runIf(process.env.TW_SECRET_KEY)("deployERC721", () => { }); expect(deployedName).toBe("OE"); }); + + it("should deploy ERC721 drop", async () => { + const address = await deployERC721Contract({ + client: TEST_CLIENT, + chain: ANVIL_CHAIN, + account, + type: "DropERC721", + params: { + name: "Drop", + symbol: "DRP", + }, + }); + + expect(address).toBeDefined(); + const deployedName = await name({ + contract: getContract({ + client: TEST_CLIENT, + chain: ANVIL_CHAIN, + address, + }), + }); + expect(deployedName).toBe("Drop"); + }); + + it("should deploy ERC721 token", async () => { + const address = await deployERC721Contract({ + client: TEST_CLIENT, + chain: ANVIL_CHAIN, + account, + type: "TokenERC721", + params: { + name: "Token", + symbol: "TKN", + }, + }); + + expect(address).toBeDefined(); + const deployedName = await name({ + contract: getContract({ + client: TEST_CLIENT, + chain: ANVIL_CHAIN, + address, + }), + }); + expect(deployedName).toBe("Token"); + }); + + it("should deploy ERC721 loyalty card", async () => { + const address = await deployERC721Contract({ + client: TEST_CLIENT, + chain: ANVIL_CHAIN, + account, + type: "LoyaltyCard", + params: { + name: "Loyalty", + symbol: "LOY", + }, + }); + + expect(address).toBeDefined(); + const deployedName = await name({ + contract: getContract({ + client: TEST_CLIENT, + chain: ANVIL_CHAIN, + address, + }), + }); + expect(deployedName).toBe("Loyalty"); + }); }); diff --git a/packages/thirdweb/src/extensions/prebuilts/deploy-erc721.ts b/packages/thirdweb/src/extensions/prebuilts/deploy-erc721.ts index 6c0d9f6d567..448770101f4 100644 --- a/packages/thirdweb/src/extensions/prebuilts/deploy-erc721.ts +++ b/packages/thirdweb/src/extensions/prebuilts/deploy-erc721.ts @@ -6,6 +6,7 @@ import { upload } from "../../storage/upload.js"; import type { FileOrBufferOrString } from "../../storage/upload/types.js"; import type { Prettify } from "../../utils/type-utils.js"; import type { ClientAndChainAndAccount } from "../../utils/types.js"; +import { initialize as initLoyaltyCard } from "../erc721/__generated__/LoyaltyCard/write/initialize.js"; import { initialize as initDropERC721 } from "./__generated__/DropERC721/write/initialize.js"; import { initialize as initOpenEditionERC721 } from "./__generated__/OpenEditionERC721/write/initialize.js"; import { initialize as initTokenERC721 } from "./__generated__/TokenERC721/write/initialize.js"; @@ -16,7 +17,8 @@ import { initialize as initTokenERC721 } from "./__generated__/TokenERC721/write export type ERC721ContractType = | "DropERC721" | "TokenERC721" - | "OpenEditionERC721"; + | "OpenEditionERC721" + | "LoyaltyCard"; /** * @extension DEPLOY @@ -167,5 +169,19 @@ async function getInitializeTransaction(options: { royaltyBps: params.royaltyBps || 0n, trustedForwarders: params.trustedForwarders || [], }); + case "LoyaltyCard": + return initLoyaltyCard({ + contract: implementationContract, + defaultAdmin: params.defaultAdmin || accountAddress, + name: params.name || "", + symbol: params.symbol || "", + contractURI, + royaltyRecipient: params.royaltyRecipient || accountAddress, + royaltyBps: params.royaltyBps || 0n, + trustedForwarders: params.trustedForwarders || [], + saleRecipient: params.saleRecipient || accountAddress, + platformFeeBps: params.platformFeeBps || 0n, + platformFeeRecipient: params.platformFeeRecipient || accountAddress, + }); } }