diff --git a/examples/onft721/hardhat.config.ts b/examples/onft721/hardhat.config.ts index cf20c1f2f..5acb49ec1 100644 --- a/examples/onft721/hardhat.config.ts +++ b/examples/onft721/hardhat.config.ts @@ -9,6 +9,7 @@ import 'hardhat-deploy' import 'hardhat-contract-sizer' import '@nomiclabs/hardhat-ethers' import '@layerzerolabs/toolbox-hardhat' +import './tasks' import { HardhatUserConfig, HttpNetworkAccountsUserConfig } from 'hardhat/types' import { EndpointId } from '@layerzerolabs/lz-definitions' diff --git a/examples/onft721/package.json b/examples/onft721/package.json index 3ce642635..73b274dc3 100644 --- a/examples/onft721/package.json +++ b/examples/onft721/package.json @@ -19,6 +19,9 @@ "ethers": "^5.7.2", "hardhat-deploy": "^0.12.1" }, + "dependencies": { + "@layerzerolabs/devtools": "0.3.17" + }, "devDependencies": { "@babel/core": "^7.23.9", "@layerzerolabs/eslint-config-next": "~2.3.34", diff --git a/examples/onft721/tasks/index.ts b/examples/onft721/tasks/index.ts new file mode 100644 index 000000000..4fbe2d05c --- /dev/null +++ b/examples/onft721/tasks/index.ts @@ -0,0 +1,2 @@ +import './mint' +import './send' diff --git a/examples/onft721/tasks/mint.ts b/examples/onft721/tasks/mint.ts new file mode 100644 index 000000000..1d27abe27 --- /dev/null +++ b/examples/onft721/tasks/mint.ts @@ -0,0 +1,28 @@ +import { task } from 'hardhat/config' +import { ActionType, HardhatRuntimeEnvironment } from 'hardhat/types' + +const ABI = ['function mint(address _to, uint256 _tokenId) public'] + +const createMyONFT721MockContract = async (hre: HardhatRuntimeEnvironment, onft721Address: string) => { + return await hre.ethers.getContractAt(ABI, onft721Address) +} + +interface TaskArgs { + onft721Address: string + tokenId: number +} + +const action: ActionType = async (taskArgs: TaskArgs, hre) => { + const signer = (await hre.getNamedAccounts()).deployer + const user = await hre.ethers.getSigner(signer) + + const myONFT721Mock = await createMyONFT721MockContract(hre, taskArgs.onft721Address) + + const tx = await myONFT721Mock.mint(user.address, taskArgs.tokenId) + const txReceipt = await tx.wait() + console.log(`Transaction hash: ${txReceipt.transactionHash}`) +} + +task('mint', 'Mint ONFT721 Mock', action) + .addParam('onft721Address', 'ONFT721 contract address') + .addParam('tokenId', 'Token ID') diff --git a/examples/onft721/tasks/send.ts b/examples/onft721/tasks/send.ts new file mode 100644 index 000000000..d78d4b9c3 --- /dev/null +++ b/examples/onft721/tasks/send.ts @@ -0,0 +1,56 @@ +import { SignerWithAddress } from '@nomiclabs/hardhat-ethers/signers' +import { task } from 'hardhat/config' +import { ActionType, HardhatRuntimeEnvironment } from 'hardhat/types' + +import { makeBytes32 } from '@layerzerolabs/devtools' + +const DEFAULT_EXTRA_OPTIONS = '0x' +const DEFAULT_COMPOSE_MSG = '0x' +const DEFAULT_OFT_CMD = '0x' + +const ONFT721_ABI = [ + 'function send((uint32 dstEid,bytes32 to,uint256 tokenId,bytes extraOptions,bytes composeMsg,bytes oftCmd),(uint256 nativeFee,uint256 lzFee),address refundAddress) external payable returns (MessagingReceipt msgReceipt)', + 'function quoteSend((uint32 dstEid,bytes32 to,uint256 tokenId,bytes extraOptions,bytes composeMsg,bytes oftCmd),bool payInLzToken) external view returns ((uint256, uint256))', +] + +const getONFT721Contract = async (hre: HardhatRuntimeEnvironment, onft721Address: string, signer: SignerWithAddress) => + hre.ethers.getContractAt(ONFT721_ABI, onft721Address, signer) + +const createSendParam = (user: SignerWithAddress, taskArgs: TaskArgs) => { + return { + dstEid: taskArgs.dstEid, + to: makeBytes32(user.address), + tokenId: taskArgs.tokenId, + extraOptions: DEFAULT_EXTRA_OPTIONS, + composeMsg: DEFAULT_COMPOSE_MSG, + oftCmd: DEFAULT_OFT_CMD, + } +} + +interface TaskArgs { + onft721Address: string + dstEid: number + to: string + tokenId: number +} + +const action: ActionType = async (taskArgs: TaskArgs, hre) => { + const signer = (await hre.getNamedAccounts()).deployer + const user = await hre.ethers.getSigner(signer) + + const sendParam = createSendParam(user, taskArgs) + const onft721 = await getONFT721Contract(hre, taskArgs.onft721Address, user) + const messagingFee = await onft721.quoteSend(sendParam, false) + + const tx = await onft721.send(sendParam, messagingFee, user.address, { + value: messagingFee[0], + gasLimit: 1_000_000, + }) + const txReceipt = await tx.wait() + console.log(`Transaction hash: ${txReceipt.transactionHash}`) +} + +task('send', 'Send ONFT721 from one chain to another', action) + .addParam('onft721Address', 'ONFT721 contract address') + .addParam('dstEid', 'Destination LayerZero EndpointV2 ID') + .addParam('tokenId', 'Token ID') diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index c2af726ca..698ee7f8b 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -604,6 +604,10 @@ importers: version: 5.5.4 examples/onft721: + dependencies: + '@layerzerolabs/devtools': + specifier: 0.3.17 + version: 0.3.17(@ethersproject/bytes@5.7.0)(@layerzerolabs/io-devtools@packages+io-devtools)(@layerzerolabs/lz-definitions@2.3.34)(zod@3.22.4) devDependencies: '@babel/core': specifier: ^7.23.9 @@ -4919,6 +4923,22 @@ packages: '@jridgewell/resolve-uri': 3.1.1 '@jridgewell/sourcemap-codec': 1.4.15 + /@layerzerolabs/devtools@0.3.17(@ethersproject/bytes@5.7.0)(@layerzerolabs/io-devtools@packages+io-devtools)(@layerzerolabs/lz-definitions@2.3.34)(zod@3.22.4): + resolution: {integrity: sha512-G/NUnmInAJna5/gsqjVNdumH68eJGe3FGFHxMDQKKOUlffznZcOqwdObkYdjXDx7XdUiDdCSWTXmmpV9xVW6mQ==} + peerDependencies: + '@ethersproject/bytes': ~5.7.0 + '@layerzerolabs/io-devtools': ~0.1.11 + '@layerzerolabs/lz-definitions': ^2.3.3 + zod: ^3.22.4 + dependencies: + '@ethersproject/bytes': 5.7.0 + '@layerzerolabs/io-devtools': link:packages/io-devtools + '@layerzerolabs/lz-definitions': 2.3.34 + exponential-backoff: 3.1.1 + js-yaml: 4.1.0 + zod: 3.22.4 + dev: false + /@layerzerolabs/eslint-config-next@2.3.34(typescript@5.5.4): resolution: {integrity: sha512-2/vfOjQIwxw1rXzUv2i9Qio5/s/G8PC4K3oq/IPaaGmgouw+3Qeu+4oVfEeHu829Q31QzlivZ6wAfAAJ7zODzA==} dependencies: