diff --git a/.changeset/purple-apes-yell.md b/.changeset/purple-apes-yell.md new file mode 100644 index 0000000000..fb02533462 --- /dev/null +++ b/.changeset/purple-apes-yell.md @@ -0,0 +1,21 @@ +--- +"@layerzerolabs/oft-adapter-aptos-move-example": patch +"@layerzerolabs/mint-burn-oft-adapter-example": patch +"@layerzerolabs/native-oft-adapter-example": patch +"@layerzerolabs/oft-adapter-initia-example": patch +"@layerzerolabs/oapp-aptos-example": patch +"@layerzerolabs/oft-hyperliquid-example": patch +"@layerzerolabs/oft-upgradeable-example": patch +"@layerzerolabs/oft-aptos-move-example": patch +"@layerzerolabs/onft721-zksync-example": patch +"@layerzerolabs/oft-adapter-example": patch +"@layerzerolabs/oft-initia-example": patch +"@layerzerolabs/oft-solana-example": patch +"@layerzerolabs/omni-call-example": patch +"@layerzerolabs/oft-alt-example": patch +"@layerzerolabs/onft721-example": patch +"@layerzerolabs/oapp-example": patch +"@layerzerolabs/oft-example": patch +--- + +Updating license from UNLICENSED to MIT. diff --git a/.changeset/weak-crabs-chew.md b/.changeset/weak-crabs-chew.md new file mode 100644 index 0000000000..e6fe866469 --- /dev/null +++ b/.changeset/weak-crabs-chew.md @@ -0,0 +1,5 @@ +--- +"@layerzerolabs/oapp-aptos-example": patch +--- + +Adding param encoding and decoding to Move OApp example. diff --git a/examples/mint-burn-oft-adapter/contracts/MyMintBurnOFTAdapter.sol b/examples/mint-burn-oft-adapter/contracts/MyMintBurnOFTAdapter.sol index b03d501dd4..e7ad46b686 100644 --- a/examples/mint-burn-oft-adapter/contracts/MyMintBurnOFTAdapter.sol +++ b/examples/mint-burn-oft-adapter/contracts/MyMintBurnOFTAdapter.sol @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: UNLICENSED +// SPDX-License-Identifier: MIT pragma solidity ^0.8.22; import { Ownable } from "@openzeppelin/contracts/access/Ownable.sol"; diff --git a/examples/mint-burn-oft-adapter/contracts/MyOFT.sol b/examples/mint-burn-oft-adapter/contracts/MyOFT.sol index f8bc7b47f6..fc0694fc77 100644 --- a/examples/mint-burn-oft-adapter/contracts/MyOFT.sol +++ b/examples/mint-burn-oft-adapter/contracts/MyOFT.sol @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: UNLICENSED +// SPDX-License-Identifier: MIT pragma solidity ^0.8.22; import { Ownable } from "@openzeppelin/contracts/access/Ownable.sol"; diff --git a/examples/native-oft-adapter/contracts/MyNativeOFTAdapter.sol b/examples/native-oft-adapter/contracts/MyNativeOFTAdapter.sol index 03a1b7cca4..1cd21fdb49 100644 --- a/examples/native-oft-adapter/contracts/MyNativeOFTAdapter.sol +++ b/examples/native-oft-adapter/contracts/MyNativeOFTAdapter.sol @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: UNLICENSED +// SPDX-License-Identifier: MIT pragma solidity ^0.8.22; import { Ownable } from "@openzeppelin/contracts/access/Ownable.sol"; diff --git a/examples/native-oft-adapter/contracts/MyOFT.sol b/examples/native-oft-adapter/contracts/MyOFT.sol index f8bc7b47f6..fc0694fc77 100644 --- a/examples/native-oft-adapter/contracts/MyOFT.sol +++ b/examples/native-oft-adapter/contracts/MyOFT.sol @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: UNLICENSED +// SPDX-License-Identifier: MIT pragma solidity ^0.8.22; import { Ownable } from "@openzeppelin/contracts/access/Ownable.sol"; diff --git a/examples/oapp-aptos-move/README.md b/examples/oapp-aptos-move/README.md index 6e67decd52..61571a65f0 100644 --- a/examples/oapp-aptos-move/README.md +++ b/examples/oapp-aptos-move/README.md @@ -96,15 +96,19 @@ APTOS_PRIVATE_KEY= Then run `source .env` in order for your values to be mapped. -> **Important:** If using Aptos CLI version >= 6.1.0 (required for Aptos chain), you need to uncomment the following lines in Move.toml and remove the existing AptosFramework dependency: +> **Important:** If using Aptos CLI version 3.5.0 (required for Movement chain), you need to uncomment the following lines in Move.toml and remove the existing AptosFramework dependency: > > ``` > # [dependencies.AptosFramework] -> # git = "https://github.com/aptos-labs/aptos-framework.git" -> # rev = "mainnet" -> # subdir = "aptos-framework" +> # git = "https://github.com/movementlabsxyz/aptos-core.git" +> # rev = "movement-cli-v3.5.0" +> # subdir = "aptos-move/framework/aptos-framework" > ``` +## Contracts + +The starter OApp contracts are located in `./sources/oapp.move` and `./contracts/MyOApp.sol`. Feel free to adjust these based on the needs of you application. There are also some test scripts in `./scripts/` that allow you to test sending messages between your OApps. + ## OApp Config Setup Before running the deploy and wire commands, first inside of `move.layerzero.config.ts`, set the delegate and owner address to your deployer account address. These can be changed in the future with commands shown later in this README, but for now they should be set to the address you will be running the commands from (deployer account address). @@ -207,6 +211,48 @@ If `--only-calldata ` is specified, only the calldata is generated and not pnpm run lz:sdk:move:wire --oapp-config move.layerzero.config.ts ``` +### Testing Send + +This OApp example includes several test scripts in `./scripts`. **Before running any script, you must manually update the values inside each file with your deployed contract addresses and configuration.** + +For EVM scripts (`evm-send.ts`, `evm-get-message.ts`), update the following values inside the files: + +- `contractAddress` with your deployed EVM contract address +- RPC URL in the `JsonRpcProvider` with your EVM chain's RPC endpoint +- Set `EVM_PRIVATE_KEY` environment variable for sending transactions + +For Aptos/Movement scripts (`aptos-move-send.ts`, `aptos-get-receive-values.ts`), update the following values inside the files: + +- `OAPP_ADDRESS` or `oappAddress` with your deployed Aptos/Movement contract address +- Set `APTOS_PRIVATE_KEY` and `ACCOUNT_ADDRESS` environment variables for sending transactions +- Adjust the `Network` configuration if needed (TESTNET/MAINNET) + +To test sending from your EVM deployment to your deployed OApp on Aptos or Movement, run: + +```bash +ts-node scripts/evm-send.ts +``` + +For demonstration purposes, we have added encoding and decoding of some useful parameters in `oapp.move` and `evm-send.ts`. These are for demonstration purposes only and should be adjusted based on the needs of your application. + +To confirm your values have been sent to your Aptos or Movement OApp, run: + +```bash +ts-node scripts/aptos-get-received-values.ts +``` + +To send a test value from your Aptos/Movement OApp to your EVM OApp, run: + +```bash +ts-node scripts/aptos-move-send.ts +``` + +To check that your message has been registered in your EVM OApp, run: + +```bash +ts-node scripts/evm-get-received-message.ts +``` + ### Transferring Ownership of your Move OApp There are three steps to transferring ownership of your Move OApp: diff --git a/examples/oapp-aptos-move/contracts/MyOApp.sol b/examples/oapp-aptos-move/contracts/MyOApp.sol index 316a91aa33..8feca07bf7 100644 --- a/examples/oapp-aptos-move/contracts/MyOApp.sol +++ b/examples/oapp-aptos-move/contracts/MyOApp.sol @@ -1,34 +1,31 @@ // SPDX-License-Identifier: MIT - pragma solidity ^0.8.22; -import { Ownable } from "@openzeppelin/contracts/access/Ownable.sol"; -import { OApp, MessagingFee, Origin } from "@layerzerolabs/oapp-evm/contracts/oapp/OApp.sol"; -import { MessagingReceipt } from "@layerzerolabs/oapp-evm/contracts/oapp/OAppSender.sol"; +import { OApp, Origin, MessagingFee } from "@layerzerolabs/oapp-evm/contracts/oapp/OApp.sol"; import { OAppOptionsType3 } from "@layerzerolabs/oapp-evm/contracts/oapp/libs/OAppOptionsType3.sol"; +import { Ownable } from "@openzeppelin/contracts/access/Ownable.sol"; contract MyOApp is OApp, OAppOptionsType3 { - constructor(address _endpoint, address _delegate) OApp(_endpoint, _delegate) Ownable(_delegate) {} + /// @notice Last string received from any remote chain + address public address1; + address public address2; + uint256 public num; - string public data = "Nothing received yet."; - uint256 public counter = 0; + /// @notice The only Message Type in use for this OApp: sending an arbitrary string. + /// Different message types can be assigned different enforced options per destination endpoint ID. + uint16 public constant SEND = 1; - /** - * @notice Sends a message from the source chain to a destination chain. - * @param _dstEid The endpoint ID of the destination chain. - * @param _message The message string to be sent. - * @param _options Additional options for message execution. - * @dev Encodes the message as bytes and sends it using the `_lzSend` internal function. - * @return receipt A `MessagingReceipt` struct containing details of the message sent. - */ - function send( - uint32 _dstEid, - string memory _message, - bytes calldata _options - ) external payable returns (MessagingReceipt memory receipt) { - bytes memory _payload = abi.encode(_message); - receipt = _lzSend(_dstEid, _payload, _options, MessagingFee(msg.value, 0), payable(msg.sender)); - } + /// @notice Initialize with Endpoint V2 and owner address + /// @param _endpoint The local chain's LayerZero Endpoint V2 address + /// @param _owner The address permitted to configure this OApp + constructor(address _endpoint, address _owner) OApp(_endpoint, _owner) Ownable(_owner) {} + + // ────────────────────────────────────────────────────────────────────────────── + // 0. (Optional) Quote business logic + // + // Example: Get a quote from the Endpoint for a cost estimate of sending a message. + // Replace this to mirror your own send business logic. + // ────────────────────────────────────────────────────────────────────────────── /** * @notice Quotes the gas needed to pay for the full omnichain transaction in native gas or ZRO token. @@ -38,35 +35,87 @@ contract MyOApp is OApp, OAppOptionsType3 { * @param _payInLzToken Whether to return fee in ZRO token. * @return fee A `MessagingFee` struct containing the calculated gas fee in either the native token or ZRO token. */ - function quote( + function quoteSend( uint32 _dstEid, - string memory _message, - bytes memory _options, + string calldata _message, + bytes calldata _options, bool _payInLzToken ) public view returns (MessagingFee memory fee) { - bytes memory payload = abi.encode(_message); - fee = _quote(_dstEid, payload, _options, _payInLzToken); + bytes memory _message = abi.encode(_message); + // combineOptions (from OAppOptionsType3) merges enforced options set by the contract owner + // with any additional execution options provided by the caller + fee = _quote(_dstEid, _message, combineOptions(_dstEid, SEND, _options), _payInLzToken); } - /** - * @dev Internal function override to handle incoming messages from another chain. - * @dev _origin A struct containing information about the message sender. - * @dev _guid A unique global packet identifier for the message. - * @dev payload The encoded message payload being received. - * - * @dev The following params are unused in the current implementation of the OApp. - * @dev _executor The address of the Executor responsible for processing the message. - * @dev _extraData Arbitrary data appended by the Executor to the message. - * - * Increments the counter. - */ + // ────────────────────────────────────────────────────────────────────────────── + // 1. Send business logic + // + // Example: send a simple string to a remote chain. Replace this with your + // own state-update logic, then encode whatever data your application needs. + // ────────────────────────────────────────────────────────────────────────────── + + /// @notice Send a string to a remote OApp on another chain + /// @param _dstEid Destination Endpoint ID (uint32) + /// @param _message The string to send + /// @param _options Execution options for gas on the destination (bytes) + function send(uint32 _dstEid, string calldata _message, bytes calldata _options) external payable { + // 1. (Optional) Update any local state here. + // e.g., record that a message was "sent": + // sentCount += 1; + + // 2. Encode any data structures you wish to send into bytes + // You can use abi.encode, abi.encodePacked, or directly splice bytes + // if you know the format of your data structures + bytes memory _message = abi.encode(_message); + + // 3. Call OAppSender._lzSend to package and dispatch the cross-chain message + // - _dstEid: remote chain's Endpoint ID + // - _message: ABI-encoded string + // - _options: combined execution options (enforced + caller-provided) + // - MessagingFee(msg.value, 0): pay all gas as native token; no ZRO + // - payable(msg.sender): refund excess gas to caller + // + // combineOptions (from OAppOptionsType3) merges enforced options set by the contract owner + // with any additional execution options provided by the caller + _lzSend( + _dstEid, + _message, + combineOptions(_dstEid, SEND, _options), + MessagingFee(msg.value, 0), + payable(msg.sender) + ); + } + + // ────────────────────────────────────────────────────────────────────────────── + // 2. Receive business logic + // + // Override _lzReceive to decode the incoming bytes and apply your logic. + // The base OAppReceiver.lzReceive ensures: + // • Only the LayerZero Endpoint can call this method + // • The sender is a registered peer (peers[srcEid] == origin.sender) + // ────────────────────────────────────────────────────────────────────────────── + + /// @notice Invoked by OAppReceiver when EndpointV2.lzReceive is called + /// @dev _origin Metadata (source chain, sender address, nonce) + /// @dev _guid Global unique ID for tracking this message + /// @param _message ABI-encoded bytes (the string we sent earlier) + /// @dev _executor Executor address that delivered the message + /// @dev _extraData Additional data from the Executor (unused by the LayerZero executor) function _lzReceive( Origin calldata /*_origin*/, bytes32 /*_guid*/, - bytes calldata /*payload*/, + bytes calldata _message, address /*_executor*/, bytes calldata /*_extraData*/ ) internal override { - counter += 1; + // 1. Decode the incoming bytes into a string + // You can use abi.decode, abi.decodePacked, or directly splice bytes + // if you know the format of your data structures + (address1, address2, num) = abi.decode(_message, (address, address, uint256)); + + // 2. Apply your custom logic. In this example, store it in `lastMessage`. + // 3. (Optional) Trigger further on-chain actions. + // e.g., emit an event, mint tokens, call another contract, etc. + // emit MessageReceived(_origin.srcEid, _message); } } diff --git a/examples/oapp-aptos-move/move.layerzero.config.ts b/examples/oapp-aptos-move/move.layerzero.config.ts index 61bd999ad3..01667ab44a 100644 --- a/examples/oapp-aptos-move/move.layerzero.config.ts +++ b/examples/oapp-aptos-move/move.layerzero.config.ts @@ -74,7 +74,7 @@ const config: OAppOmniGraphHardhat = { }, ulnConfig: { // The number of block confirmations to wait on Aptos before emitting the message from the source chain. - confirmations: BigInt(260), + confirmations: BigInt(10), // The address of the DVNs you will pay to verify a sent message on the source chain. // The destination tx will wait until ALL `requiredDVNs` verify the message. requiredDVNs: ['0x756f8ab056688d22687740f4a9aeec3b361170b28d08b719e28c4d38eed1043e'], @@ -143,7 +143,7 @@ const config: OAppOmniGraphHardhat = { }, receiveConfig: { ulnConfig: { - confirmations: BigInt(260), + confirmations: BigInt(10), requiredDVNs: ['0x0eE552262f7B562eFcED6DD4A7e2878AB897d405'], optionalDVNThreshold: 0, }, diff --git a/examples/oapp-aptos-move/scripts/aptos-get-received-values.ts b/examples/oapp-aptos-move/scripts/aptos-get-received-values.ts new file mode 100644 index 0000000000..940dd11b99 --- /dev/null +++ b/examples/oapp-aptos-move/scripts/aptos-get-received-values.ts @@ -0,0 +1,57 @@ +import { Aptos, AptosConfig, Network } from '@aptos-labs/ts-sdk' + +/** + * A utility script to verify cross-chain message delivery by checking the last received values. + * The values are updated each time a message is successfully received by the OApp, + * providing a simple way to confirm that cross-chain communication is working as expected. + */ +async function main() { + const config = new AptosConfig({ network: Network.TESTNET }) + const aptos = new Aptos(config) + const oappAddress = '' + + console.log('Fetching receive values...') + console.log('---') + + const [counterResult, address1Result, address2Result, numberResult, rawMessageResult] = await Promise.all([ + aptos.view({ + payload: { + function: `${oappAddress}::oapp::get_counter_value`, + typeArguments: [], + }, + }), + aptos.view({ + payload: { + function: `${oappAddress}::oapp::get_decoded_address1`, + typeArguments: [], + }, + }), + aptos.view({ + payload: { + function: `${oappAddress}::oapp::get_decoded_address2`, + typeArguments: [], + }, + }), + aptos.view({ + payload: { + function: `${oappAddress}::oapp::get_decoded_number`, + typeArguments: [], + }, + }), + aptos.view({ + payload: { + function: `${oappAddress}::oapp::get_raw_message`, + typeArguments: [], + }, + }), + ]) + + console.log('- Counter:', counterResult[0]) + console.log('- Address 1:', address1Result[0]) + console.log('- Address 2:', address2Result[0]) + console.log('- Number:', numberResult[0]) + console.log('- Raw Message:', rawMessageResult[0]) + console.log('---') +} + +main().catch(console.error) diff --git a/examples/oapp-aptos-move/scripts/aptos-move-get-count.ts b/examples/oapp-aptos-move/scripts/aptos-move-get-count.ts deleted file mode 100644 index 0c662a0d9a..0000000000 --- a/examples/oapp-aptos-move/scripts/aptos-move-get-count.ts +++ /dev/null @@ -1,47 +0,0 @@ -/** - * @file aptos-move-get-count.ts - * @description A script to get the current counter value from the OApp on Aptos. - * This counter increments each time a message is successfully received by the OApp, - * providing a simple way to confirm that cross-chain communication is working. - */ - -import { Aptos, AptosConfig, Network } from '@aptos-labs/ts-sdk' -import * as dotenv from 'dotenv' - -// Load environment variables from .env file -dotenv.config() - -// OApp configuration -const OAPP_ADDRESS = '' // Set your OApp's address on Aptos -const NETWORK = Network.TESTNET // Aptos network configuration - -// Initialize Aptos client -const aptos = new Aptos(new AptosConfig({ network: NETWORK })) - -/** - * Gets the current counter value from the OApp contract on Aptos. - * This function demonstrates how to call a view function on an Aptos contract. - */ -async function getCount() { - try { - // Call the view function to get the counter value - const counter = await aptos.view({ - payload: { - function: `${OAPP_ADDRESS}::oapp::get_counter`, - functionArguments: [], - }, - }) - - console.log('Current counter value:', counter) - return counter - } catch (error) { - console.error('Error getting counter value:', error) - throw error - } -} - -// Execute the getCount function and handle any errors -getCount().catch((error) => { - console.error(error) - process.exit(1) -}) diff --git a/examples/oapp-aptos-move/scripts/aptos-move-send.ts b/examples/oapp-aptos-move/scripts/aptos-move-send.ts index feb14c6372..e7218e69c6 100644 --- a/examples/oapp-aptos-move/scripts/aptos-move-send.ts +++ b/examples/oapp-aptos-move/scripts/aptos-move-send.ts @@ -21,6 +21,7 @@ import { SimpleTransaction, } from '@aptos-labs/ts-sdk' import * as dotenv from 'dotenv' +import { ethers } from 'ethers' import { EndpointId } from '@layerzerolabs/lz-definitions' import { Options } from '@layerzerolabs/lz-v2-utilities' @@ -28,25 +29,26 @@ import { Options } from '@layerzerolabs/lz-v2-utilities' // Load environment variables from .env file dotenv.config() +// Configuration constants +const APTOS_PRIVATE_KEY = process.env.APTOS_PRIVATE_KEY || '' +const APTOS_ACCOUNT_ADDRESS = process.env.APTOS_ACCOUNT_ADDRESS || '' + // Validate required environment variables -if (!process.env.APTOS_PRIVATE_KEY || !process.env.ACCOUNT_ADDRESS) { - throw new Error('Please set APTOS_PRIVATE_KEY and ACCOUNT_ADDRESS in your .env file') +if (!APTOS_PRIVATE_KEY || !APTOS_ACCOUNT_ADDRESS) { + throw new Error('Please set APTOS_PRIVATE_KEY and APTOS_ACCOUNT_ADDRESS in your .env file') } -// Configuration constants -const APTOS_PRIVATE_KEY = process.env.APTOS_PRIVATE_KEY -const ACCOUNT_ADDRESS = process.env.ACCOUNT_ADDRESS - // OApp configuration -const OAPP_ADDRESS = '' // Set your OApp's address on Aptos -const REMOTE_EID = EndpointId.BSC_V2_TESTNET // Destination chain endpoint ID +const OAPP_ADDRESS = '' const NETWORK = Network.TESTNET // Aptos network configuration +const REMOTE_EID = EndpointId.BSC_V2_TESTNET // Destination chain endpoint ID + // Initialize Aptos account and client const privateKey = PrivateKey.formatPrivateKey(APTOS_PRIVATE_KEY, PrivateKeyVariants.Ed25519) const signerAccount = Account.fromPrivateKey({ privateKey: new Ed25519PrivateKey(privateKey), - address: ACCOUNT_ADDRESS, + address: APTOS_ACCOUNT_ADDRESS, }) const aptos = new Aptos(new AptosConfig({ network: NETWORK })) @@ -59,9 +61,21 @@ async function send() { const options = Options.newOptions().addExecutorLzReceiveOption(BigInt(30000)) const extraOptions = options.toBytes() - // Prepare the message - const message = 'Hello, EVM!' - const messageBytes = new TextEncoder().encode(message) + // Prepare the message - ABI encode it to match Solidity contract expectations + const address1 = '0x' // EVM 20 byte address + const address2 = '0x' // EVM 20 byte address + const num = ethers.BigNumber.from('0') + console.log('Sending message:', address1, address2, num) + + // ABI encode the string to match what the Solidity contract expects + const abiEncodedMessage = ethers.utils.defaultAbiCoder.encode( + ['address', 'address', 'uint256'], + [address1, address2, num] + ) + console.log('ABI encoded message:', abiEncodedMessage) + + // Convert to bytes array for Aptos + const messageBytes = ethers.utils.arrayify(abiEncodedMessage) const messageArray = new Uint8Array(messageBytes) // Get fee quote for the cross-chain message @@ -75,11 +89,11 @@ async function send() { // Log fee details console.log('Quote details:') console.log('Native fee (octas):', quote[0]) - console.log('Native fee (APT):', Number(quote[0]) / 100000000) + console.log('Native fee:', Number(quote[0]) / 100000000) console.log('ZRO fee:', quote[1]) // Verify account has sufficient balance - const balance = await aptos.account.getAccountAPTAmount({ accountAddress: ACCOUNT_ADDRESS }) + const balance = await aptos.account.getAccountAPTAmount({ accountAddress: APTOS_ACCOUNT_ADDRESS }) console.log('Account balance:', Number(balance) / 100000000, 'APT') if (Number(balance) < Number(quote[0])) { @@ -96,7 +110,7 @@ async function send() { // Create the transaction const transaction: SimpleTransaction = await aptos.transaction.build.simple({ - sender: ACCOUNT_ADDRESS, + sender: APTOS_ACCOUNT_ADDRESS, data: payload, options: { maxGasAmount: 100000, @@ -114,7 +128,7 @@ async function send() { transactionHash: signedTransaction.hash, }) - console.log(`Transaction hash: ${executedTransaction.hash}`) + console.log(`Transaction link: https://layerzeroscan.com/tx/${executedTransaction.hash}`) console.log('Message sent!') } diff --git a/examples/oapp-aptos-move/scripts/evm-get-received-message.ts b/examples/oapp-aptos-move/scripts/evm-get-received-message.ts new file mode 100644 index 0000000000..2988a6aec5 --- /dev/null +++ b/examples/oapp-aptos-move/scripts/evm-get-received-message.ts @@ -0,0 +1,36 @@ +import { ethers } from 'ethers' + +/** + * A utility script to verify cross-chain message delivery by checking the last received data. + * The address1, address2, and num fields are updated each time a message is successfully received by the OApp, + * providing a simple way to confirm that cross-chain communication is working as expected. + */ +async function main() { + const abi = [ + 'function address1() view returns (address)', + 'function address2() view returns (address)', + 'function num() view returns (uint256)', + ] + + const contractAddress = 'your-EVM-OApp-contract-address' + + const provider = new ethers.providers.JsonRpcProvider('your-EVM-chain-rpc-url') + + const contract = new ethers.Contract(contractAddress, abi, provider) + + const address1 = await contract.address1() + const address2 = await contract.address2() + const num = await contract.num() + + console.log('Last received data:') + console.log(' Address 1:', address1) + console.log(' Address 2:', address2) + console.log(' Number:', num.toString()) +} + +main() + .then(() => process.exit(0)) + .catch((error) => { + console.error(error) + process.exit(1) + }) diff --git a/examples/oapp-aptos-move/scripts/evm-send.ts b/examples/oapp-aptos-move/scripts/evm-send.ts index 5cb9ff9e01..22a52df73f 100644 --- a/examples/oapp-aptos-move/scripts/evm-send.ts +++ b/examples/oapp-aptos-move/scripts/evm-send.ts @@ -1,12 +1,12 @@ import { ethers } from 'ethers' -import { EndpointId } from '@layerzerolabs/lz-definitions' +import { EndpointId, getNetworkForChainId } from '@layerzerolabs/lz-definitions' import { Options } from '@layerzerolabs/lz-v2-utilities' import 'dotenv/config' -// ABI for the functions we need +// ABI for the functions we need - updated to match the Solidity contract const ABI = [ - 'function quote(uint32 _dstEid, string memory _message, bytes memory _options, bool _payInLzToken) public view returns (tuple(uint256 nativeFee, uint256 lzTokenFee))', + 'function quoteSend(uint32 _dstEid, string memory _message, bytes memory _options, bool _payInLzToken) public view returns (tuple(uint256 nativeFee, uint256 lzTokenFee))', 'function send(uint32 _dstEid, string memory _message, bytes calldata _options) external payable returns (tuple(bytes32 guid, uint256 nonce, bytes32 messageId))', ] @@ -21,37 +21,48 @@ async function main() { const provider = new ethers.providers.JsonRpcProvider('https://data-seed-prebsc-1-s1.binance.org:8545') const wallet = new ethers.Wallet(privateKey, provider) - // Contract address - const contractAddress = '' + // Contract address - update this to your deployed contract address + const contractAddress = '' // Create contract instance const myOApp = new ethers.Contract(contractAddress, ABI, wallet) - // Destination endpoint ID for Aptos - const aptosEid = EndpointId.APTOS_V2_TESTNET + // Destination endpoint ID for Aptos/Movement + const aptosMoveEid = EndpointId.APTOS_V2_TESTNET - // Message to send - const message = 'Hello Aptos!' + // Fill in the addresses and number to send to Aptos/Movement + const address1 = '0x' // Aptos 32 byte address + const address2 = '0x' // Aptos 32 byte address + const num = ethers.BigNumber.from('0') + + const encodedMessage = ethers.utils.solidityPack(['bytes32', 'bytes32', 'uint256'], [address1, address2, num]) + + const hexString = ethers.utils.hexlify(encodedMessage) + + console.log('Encoded message:', hexString) + console.log('Address1:', address1) + console.log('Address2:', address2) + console.log('Number:', num) // Build options with gas for execution - const options = Options.newOptions() - .addExecutorLzReceiveOption(200000, 0) // Similar to test file - .toHex() - .toString() + const options = Options.newOptions().addExecutorLzReceiveOption(200000, 0).toHex().toString() try { // Get quote - const [nativeFee] = await myOApp.quote(aptosEid, message, options, false) - console.log(`Quote for message: ${nativeFee} ETH`) + const [nativeFee] = await myOApp.quoteSend(aptosMoveEid, hexString, options, false) + console.log(`Quote for message: ${ethers.utils.formatEther(nativeFee)} native.`) // Send message - const tx = await myOApp.send(aptosEid, message, options, { + const tx = await myOApp.send(aptosMoveEid, hexString, options, { value: nativeFee.toString(), }) - console.log('Sending message to Aptos...') + const network = getNetworkForChainId(EndpointId.APTOS_V2_TESTNET) + const networkString = network.chainName + '-' + network.env + console.log(`Sending encoded message to ${networkString}...`) + const receipt = await tx.wait() - console.log(`Transaction hash: ${receipt?.transactionHash}`) + console.log(`Transaction hash: https://layerzeroscan.com/tx/${receipt?.transactionHash}`) console.log('Message sent!') } catch (error) { console.error('Error sending message:', error) diff --git a/examples/oapp-aptos-move/scripts/get-count.ts b/examples/oapp-aptos-move/scripts/get-count.ts deleted file mode 100644 index 9e836f03c2..0000000000 --- a/examples/oapp-aptos-move/scripts/get-count.ts +++ /dev/null @@ -1,26 +0,0 @@ -import { ethers } from 'ethers' - -/** - * A utility script to verify cross-chain message delivery by checking the counter value. - * The counter increments each time a message is successfully received by the OApp, - * providing a simple way to confirm that cross-chain communication is working as expected. - */ -async function main() { - const abi = ['function counter() view returns (uint256)'] - - const contractAddress = 'your-contract-address' - - const provider = new ethers.providers.JsonRpcProvider('your-rpc-url') - - const contract = new ethers.Contract(contractAddress, abi, provider) - - const counter = await contract.counter() - console.log('Counter value:', counter.toString()) -} - -main() - .then(() => process.exit(0)) - .catch((error) => { - console.error(error) - process.exit(1) - }) diff --git a/examples/oapp-aptos-move/sources/oapp.move b/examples/oapp-aptos-move/sources/oapp.move index 85c589f75e..78e4aad87e 100644 --- a/examples/oapp-aptos-move/sources/oapp.move +++ b/examples/oapp-aptos-move/sources/oapp.move @@ -9,11 +9,15 @@ module oapp::oapp { use std::option::Option; use std::primary_fungible_store; use std::signer::address_of; + use std::string; + use std::vector; use endpoint_v2_common::bytes32::Bytes32; use endpoint_v2_common::native_token; + use endpoint_v2_common::serde::{extract_address, extract_u256}; use oapp::oapp_core::{combine_options, lz_quote, lz_send, refund_fees}; use oapp::oapp_store::OAPP_ADDRESS; + use oapp::utils::hex_string_to_bytes; friend oapp::oapp_receive; friend oapp::oapp_compose; @@ -24,13 +28,46 @@ module oapp::oapp { value: u64 } + struct ReceiveData has key { + address1: address, + address2: address, + number: u256, + counter: u64, + raw_message: vector + } + fun init_module(account: &signer) { move_to(account, Counter { value: 0 }); + move_to(account, ReceiveData { + address1: @0x0, + address2: @0x0, + number: 0, + counter: 0, + raw_message: vector::empty() + }); } - #[view] - public fun get_counter(): u64 acquires Counter { - borrow_global(@oapp).value + /// Parses a cross-chain message to extract two addresses and a u256 number + /// The message format contains hex-encoded data representing: + /// - First 32 bytes: address1 + /// - Next 32 bytes: address2 + /// - Remaining bytes: u256 number + public fun parse_message(message: vector): (address, address, u256) { + let string_len_offset = 0; + let offset = extract_u256(&message, &mut string_len_offset); + string_len_offset = (offset as u64); + let string_length = extract_u256(&message, &mut string_len_offset); + let string_bytes = vector::slice(&message, string_len_offset, string_len_offset + (string_length as u64)); + + let hex_bytes = vector::slice(&string_bytes, 2, vector::length(&string_bytes)); + let hex_content = hex_string_to_bytes(string::utf8(hex_bytes)); + + let pos = 0; + let decoded_addr1 = extract_address(&hex_content, &mut pos); + let decoded_addr2 = extract_address(&hex_content, &mut pos); + let number_u256 = extract_u256(&hex_content, &mut pos); + + (decoded_addr1, decoded_addr2, number_u256) } public(friend) fun lz_receive_impl( @@ -41,17 +78,23 @@ module oapp::oapp { _message: vector, _extra_data: vector, receive_value: Option, - ) acquires Counter { - // Deposit any received value + ) acquires Counter, ReceiveData { option::destroy(receive_value, |value| primary_fungible_store::deposit(OAPP_ADDRESS(), value)); - // Increment counter - let counter = borrow_global_mut(@oapp); + let counter = borrow_global_mut(OAPP_ADDRESS()); counter.value = counter.value + 1; - // todo: Perform any actions with received message here - } + let (decoded_addr1, decoded_addr2, number_u256) = parse_message(_message); + + let receive_data = borrow_global_mut(OAPP_ADDRESS()); + receive_data.address1 = decoded_addr1; + receive_data.address2 = decoded_addr2; + receive_data.number = number_u256; + receive_data.counter = counter.value; + receive_data.raw_message = _message; + // Optionally, you can add any additional logic here to handle the received message. + } // todo: replicate the logic in here where sending a message must happen public entry fun example_message_sender( @@ -126,8 +169,39 @@ module oapp::oapp { 0 } + // ================================================== View Functions =========================================== + + #[view] + public fun get_decoded_address1(): address acquires ReceiveData { + borrow_global(OAPP_ADDRESS()).address1 + } + + #[view] + public fun get_decoded_address2(): address acquires ReceiveData { + borrow_global(OAPP_ADDRESS()).address2 + } + + #[view] + public fun get_decoded_number(): u256 acquires ReceiveData { + borrow_global(OAPP_ADDRESS()).number + } + + #[view] + public fun get_counter_value(): u64 acquires Counter { + borrow_global(OAPP_ADDRESS()).value + } + + #[view] + public fun get_raw_message(): vector acquires ReceiveData { + borrow_global(OAPP_ADDRESS()).raw_message + } + // ================================================== Error Codes ================================================= const ECOMPOSE_NOT_IMPLEMENTED: u64 = 1; const EINSUFFICIENT_BALANCE: u64 = 2; -} + const EINVALID_HEX_CHAR: u64 = 3; + const EINVALID_LENGTH: u64 = 4; + + +} \ No newline at end of file diff --git a/examples/oapp-aptos-move/sources/utils.move b/examples/oapp-aptos-move/sources/utils.move new file mode 100644 index 0000000000..0bbef65b5c --- /dev/null +++ b/examples/oapp-aptos-move/sources/utils.move @@ -0,0 +1,71 @@ +module oapp::utils { + use std::string::{Self, String}; + use std::vector; + + const ASCII_ZERO: u8 = 48; + const ASCII_NINE: u8 = 57; + const ASCII_UPPERCASE_A: u8 = 65; + const ASCII_UPPERCASE_F: u8 = 70; + const ASCII_LOWERCASE_A: u8 = 97; + const ASCII_LOWERCASE_F: u8 = 102; + + /// Converts a hex string (without 0x prefix) to a vector of bytes + /// Example: "48656c6c6f" -> b"Hello" + /// Aborts if the hex string has odd length (not properly formatted) + public fun hex_string_to_bytes(hex_str: String): vector { + let hex_bytes = string::bytes(&hex_str); + let len = vector::length(hex_bytes); + + // Assert that hex string has even length + assert!(len % 2 == 0, EINVALID_HEX_LENGTH); + + let result = vector[]; + let i = 0; + while (i < len) { + let high_nibble = hex_char_to_u8(*vector::borrow(hex_bytes, i)); + let low_nibble = hex_char_to_u8(*vector::borrow(hex_bytes, i + 1)); + let byte_val = (high_nibble << 4) | low_nibble; + vector::push_back(&mut result, byte_val); + i = i + 2; + }; + result + } + + /// Converts bytes to a hex string (lowercase) + public fun bytes_to_hex_string(bytes: vector): String { + let hex_chars = b"0123456789abcdef"; + let result = vector[]; + + let i = 0; + let len = vector::length(&bytes); + while (i < len) { + let byte = *vector::borrow(&bytes, i); + let high = (byte >> 4) & 0x0f; + let low = byte & 0x0f; + vector::push_back(&mut result, *vector::borrow(&hex_chars, (high as u64))); + vector::push_back(&mut result, *vector::borrow(&hex_chars, (low as u64))); + i = i + 1; + }; + + string::utf8(result) + } + + /// Helper function to convert a hex character to u8 + fun hex_char_to_u8(char: u8): u8 { + if (char >= ASCII_ZERO && char <= ASCII_NINE) { + char - ASCII_ZERO + } else if (char >= ASCII_UPPERCASE_A && char <= ASCII_UPPERCASE_F) { + char - ASCII_UPPERCASE_A + 10 + } else if (char >= ASCII_LOWERCASE_A && char <= ASCII_LOWERCASE_F) { + char - ASCII_LOWERCASE_A + 10 + } else { + abort EINVALID_HEX_CHARACTER + } + } + + // ================================================== Error Codes ================================================= + + const EINVALID_HEX_CHARACTER: u64 = 1; + const EINVALID_ADDRESS_LENGTH: u64 = 2; + const EINVALID_HEX_LENGTH: u64 = 3; +} \ No newline at end of file diff --git a/examples/oapp-aptos-move/test/hardhat/MyOApp.test.ts b/examples/oapp-aptos-move/test/hardhat/MyOApp.test.ts index e4550147ce..014254c782 100644 --- a/examples/oapp-aptos-move/test/hardhat/MyOApp.test.ts +++ b/examples/oapp-aptos-move/test/hardhat/MyOApp.test.ts @@ -1,10 +1,7 @@ import { SignerWithAddress } from '@nomiclabs/hardhat-ethers/signers' -import { expect } from 'chai' import { Contract, ContractFactory } from 'ethers' import { deployments, ethers } from 'hardhat' -import { Options } from '@layerzerolabs/lz-v2-utilities' - describe('MyOApp Test', function () { // Constant representing a mock Endpoint ID for testing purposes const eidA = 1 @@ -61,24 +58,4 @@ describe('MyOApp Test', function () { await myOAppA.connect(ownerA).setPeer(eidB, ethers.utils.zeroPad(myOAppB.address, 32)) await myOAppB.connect(ownerB).setPeer(eidA, ethers.utils.zeroPad(myOAppA.address, 32)) }) - - // A test case to verify message sending functionality - it('should increment counter when receiving a message', async function () { - // Assert initial counter state in both MyOApp instances - expect((await myOAppA.counter()).toNumber()).to.equal(0) - expect((await myOAppB.counter()).toNumber()).to.equal(0) - - const options = Options.newOptions().addExecutorLzReceiveOption(200000, 0).toHex().toString() - - // Define native fee and quote for the message send operation - let nativeFee = 0 - ;[nativeFee] = await myOAppA.quote(eidB, 'Test message.', options, false) - - // Execute send operation from myOAppA - await myOAppA.send(eidB, 'Test message.', options, { value: nativeFee.toString() }) - - // Assert the counter was incremented in the receiving app - expect((await myOAppA.counter()).toNumber()).to.equal(0) - expect((await myOAppB.counter()).toNumber()).to.equal(1) - }) }) diff --git a/examples/oapp-aptos-move/tests/oapp_tests.move b/examples/oapp-aptos-move/tests/oapp_tests.move new file mode 100644 index 0000000000..821fc15a1f --- /dev/null +++ b/examples/oapp-aptos-move/tests/oapp_tests.move @@ -0,0 +1,39 @@ +#[test_only] +module oapp::oapp_tests { + + use oapp::oapp::parse_message; + + #[test] + fun test_parse_message() { + let expected_addr1 = @0x1234567890123456789012345678901234567890; + let expected_addr2 = @0x9876543210987654321098765432109876543210; + let expected_number: u256 = 123456789012345678901234567890; + + let encoded_data = x"000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000c23078303030303030303030303030303030303030303030303030313233343536373839303132333435363738393031323334353637383930313233343536373839303030303030303030303030303030303030303030303030303938373635343332313039383736353433323130393837363534333231303938373635343332313030303030303030303030303030303030303030303030303030303030303030303030303030303031386565393066663663333733653065653465336630616432000000000000000000000000000000000000000000000000000000000000"; + + let (actual_addr1, actual_addr2, actual_number) = parse_message(encoded_data); + + assert!(actual_addr1 == expected_addr1, 1); + assert!(actual_addr2 == expected_addr2, 2); + assert!(actual_number == expected_number, 3); + } + + #[test] + fun test_parse_message_with_prefix() { + let expected_addr1 = @0x58b730d07e98a22f2b357bee721115c986e4dc873c1884763708ee3d4006f74e; + let expected_addr2 = @0x58b730d07e98a22f2b357bee721115c986e4dc873c1884763708ee3d4006f74e; + let expected_number: u256 = 123456789012345678901234567890; + + let encoded_data = x"000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000c23078353862373330643037653938613232663262333537626565373231313135633938366534646338373363313838343736333730386565336434303036663734653538623733306430376539386132326632623335376265653732313131356339383665346463383733633138383437363337303865653364343030366637346530303030303030303030303030303030303030303030303030303030303030303030303030303031386565393066663663333733653065653465336630616432000000000000000000000000000000000000000000000000000000000000"; + + let (actual_addr1, actual_addr2, actual_number) = parse_message(encoded_data); + + std::debug::print(&actual_addr1); + std::debug::print(&actual_addr2); + std::debug::print(&actual_number); + + assert!(actual_addr1 == expected_addr1, 1); + assert!(actual_addr2 == expected_addr2, 2); + assert!(actual_number == expected_number, 3); + } +} \ No newline at end of file diff --git a/examples/oapp/contracts/MyOApp.sol b/examples/oapp/contracts/MyOApp.sol index dc4f0beb38..29618723fa 100644 --- a/examples/oapp/contracts/MyOApp.sol +++ b/examples/oapp/contracts/MyOApp.sol @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: UNLICENSED +// SPDX-License-Identifier: MIT pragma solidity ^0.8.22; import { OApp, Origin, MessagingFee } from "@layerzerolabs/oapp-evm/contracts/oapp/OApp.sol"; @@ -9,7 +9,8 @@ contract MyOApp is OApp, OAppOptionsType3 { /// @notice Last string received from any remote chain string public lastMessage; - /// @notice Msg type for sending a string, for use in OAppOptionsType3 as an enforced option + /// @notice The only Message Type in use for this OApp: sending an arbitrary string. + /// Different message types can be assigned different enforced options per destination endpoint ID. uint16 public constant SEND = 1; /// @notice Initialize with Endpoint V2 and owner address @@ -97,7 +98,7 @@ contract MyOApp is OApp, OAppOptionsType3 { /// @dev _guid Global unique ID for tracking this message /// @param _message ABI-encoded bytes (the string we sent earlier) /// @dev _executor Executor address that delivered the message - /// @dev _extraData Additional data from the Executor (unused here) + /// @dev _extraData Additional data from the Executor (unused by the LayerZero executor) function _lzReceive( Origin calldata /*_origin*/, bytes32 /*_guid*/, diff --git a/examples/oft-adapter-aptos-move/contracts/MyOFT.sol b/examples/oft-adapter-aptos-move/contracts/MyOFT.sol index f8bc7b47f6..fc0694fc77 100644 --- a/examples/oft-adapter-aptos-move/contracts/MyOFT.sol +++ b/examples/oft-adapter-aptos-move/contracts/MyOFT.sol @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: UNLICENSED +// SPDX-License-Identifier: MIT pragma solidity ^0.8.22; import { Ownable } from "@openzeppelin/contracts/access/Ownable.sol"; diff --git a/examples/oft-adapter-initia/contracts/MyOFT.sol b/examples/oft-adapter-initia/contracts/MyOFT.sol index f8bc7b47f6..fc0694fc77 100644 --- a/examples/oft-adapter-initia/contracts/MyOFT.sol +++ b/examples/oft-adapter-initia/contracts/MyOFT.sol @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: UNLICENSED +// SPDX-License-Identifier: MIT pragma solidity ^0.8.22; import { Ownable } from "@openzeppelin/contracts/access/Ownable.sol"; diff --git a/examples/oft-adapter/contracts/MyOFT.sol b/examples/oft-adapter/contracts/MyOFT.sol index f8bc7b47f6..fc0694fc77 100644 --- a/examples/oft-adapter/contracts/MyOFT.sol +++ b/examples/oft-adapter/contracts/MyOFT.sol @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: UNLICENSED +// SPDX-License-Identifier: MIT pragma solidity ^0.8.22; import { Ownable } from "@openzeppelin/contracts/access/Ownable.sol"; diff --git a/examples/oft-adapter/contracts/MyOFTAdapter.sol b/examples/oft-adapter/contracts/MyOFTAdapter.sol index f87f5e5119..365e740015 100644 --- a/examples/oft-adapter/contracts/MyOFTAdapter.sol +++ b/examples/oft-adapter/contracts/MyOFTAdapter.sol @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: UNLICENSED +// SPDX-License-Identifier: MIT pragma solidity ^0.8.22; import { Ownable } from "@openzeppelin/contracts/access/Ownable.sol"; diff --git a/examples/oft-alt/contracts/MyOFTAdapterAlt.sol b/examples/oft-alt/contracts/MyOFTAdapterAlt.sol index 5444b0ef11..f4b3eac059 100644 --- a/examples/oft-alt/contracts/MyOFTAdapterAlt.sol +++ b/examples/oft-alt/contracts/MyOFTAdapterAlt.sol @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: UNLICENSED +// SPDX-License-Identifier: MIT pragma solidity ^0.8.22; import { Ownable } from "@openzeppelin/contracts/access/Ownable.sol"; diff --git a/examples/oft-alt/contracts/MyOFTAlt.sol b/examples/oft-alt/contracts/MyOFTAlt.sol index 8e6b6b2f99..ca924f85fa 100644 --- a/examples/oft-alt/contracts/MyOFTAlt.sol +++ b/examples/oft-alt/contracts/MyOFTAlt.sol @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: UNLICENSED +// SPDX-License-Identifier: MIT pragma solidity ^0.8.22; import { Ownable } from "@openzeppelin/contracts/access/Ownable.sol"; diff --git a/examples/oft-aptos-move/contracts/MyOFT.sol b/examples/oft-aptos-move/contracts/MyOFT.sol index f8bc7b47f6..fc0694fc77 100644 --- a/examples/oft-aptos-move/contracts/MyOFT.sol +++ b/examples/oft-aptos-move/contracts/MyOFT.sol @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: UNLICENSED +// SPDX-License-Identifier: MIT pragma solidity ^0.8.22; import { Ownable } from "@openzeppelin/contracts/access/Ownable.sol"; diff --git a/examples/oft-hyperliquid/contracts/MyHyperLiquidComposer.sol b/examples/oft-hyperliquid/contracts/MyHyperLiquidComposer.sol index c2b3fee16a..1b2c221c58 100644 --- a/examples/oft-hyperliquid/contracts/MyHyperLiquidComposer.sol +++ b/examples/oft-hyperliquid/contracts/MyHyperLiquidComposer.sol @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: UNLICENSED +// SPDX-License-Identifier: MIT pragma solidity ^0.8.22; import { HyperLiquidComposer } from "@layerzerolabs/hyperliquid-composer/contracts/HyperLiquidComposer.sol"; diff --git a/examples/oft-hyperliquid/contracts/MyOFT.sol b/examples/oft-hyperliquid/contracts/MyOFT.sol index f0c28c8c5f..f6e1adc8c5 100644 --- a/examples/oft-hyperliquid/contracts/MyOFT.sol +++ b/examples/oft-hyperliquid/contracts/MyOFT.sol @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: UNLICENSED +// SPDX-License-Identifier: MIT pragma solidity ^0.8.20; import { Ownable } from "@openzeppelin/contracts/access/Ownable.sol"; diff --git a/examples/oft-initia/contracts/MyOFT.sol b/examples/oft-initia/contracts/MyOFT.sol index f8bc7b47f6..fc0694fc77 100644 --- a/examples/oft-initia/contracts/MyOFT.sol +++ b/examples/oft-initia/contracts/MyOFT.sol @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: UNLICENSED +// SPDX-License-Identifier: MIT pragma solidity ^0.8.22; import { Ownable } from "@openzeppelin/contracts/access/Ownable.sol"; diff --git a/examples/oft-solana/contracts/MyOFT.sol b/examples/oft-solana/contracts/MyOFT.sol index f8bc7b47f6..fc0694fc77 100644 --- a/examples/oft-solana/contracts/MyOFT.sol +++ b/examples/oft-solana/contracts/MyOFT.sol @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: UNLICENSED +// SPDX-License-Identifier: MIT pragma solidity ^0.8.22; import { Ownable } from "@openzeppelin/contracts/access/Ownable.sol"; diff --git a/examples/oft-upgradeable/contracts/MyOFTAdapterFeeUpgradeable.sol b/examples/oft-upgradeable/contracts/MyOFTAdapterFeeUpgradeable.sol index 155d360aaf..202a44c1c3 100644 --- a/examples/oft-upgradeable/contracts/MyOFTAdapterFeeUpgradeable.sol +++ b/examples/oft-upgradeable/contracts/MyOFTAdapterFeeUpgradeable.sol @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: UNLICENSED +// SPDX-License-Identifier: MIT pragma solidity ^0.8.22; import { OFTAdapterFeeUpgradeable } from "@layerzerolabs/oft-evm-upgradeable/contracts/oft/OFTAdapterFeeUpgradeable.sol"; diff --git a/examples/oft-upgradeable/contracts/MyOFTAdapterUpgradeable.sol b/examples/oft-upgradeable/contracts/MyOFTAdapterUpgradeable.sol index c4d3646145..9c34be2145 100644 --- a/examples/oft-upgradeable/contracts/MyOFTAdapterUpgradeable.sol +++ b/examples/oft-upgradeable/contracts/MyOFTAdapterUpgradeable.sol @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: UNLICENSED +// SPDX-License-Identifier: MIT pragma solidity ^0.8.22; import { OFTAdapterUpgradeable } from "@layerzerolabs/oft-evm-upgradeable/contracts/oft/OFTAdapterUpgradeable.sol"; diff --git a/examples/oft-upgradeable/contracts/MyOFTFeeUpgradeable.sol b/examples/oft-upgradeable/contracts/MyOFTFeeUpgradeable.sol index f40720fb89..88acb96341 100644 --- a/examples/oft-upgradeable/contracts/MyOFTFeeUpgradeable.sol +++ b/examples/oft-upgradeable/contracts/MyOFTFeeUpgradeable.sol @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: UNLICENSED +// SPDX-License-Identifier: MIT pragma solidity ^0.8.22; import { OFTFeeUpgradeable } from "@layerzerolabs/oft-evm-upgradeable/contracts/oft/OFTFeeUpgradeable.sol"; diff --git a/examples/oft-upgradeable/contracts/MyOFTUpgradeable.sol b/examples/oft-upgradeable/contracts/MyOFTUpgradeable.sol index 1eeaf8a1ec..6e7883cde5 100644 --- a/examples/oft-upgradeable/contracts/MyOFTUpgradeable.sol +++ b/examples/oft-upgradeable/contracts/MyOFTUpgradeable.sol @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: UNLICENSED +// SPDX-License-Identifier: MIT pragma solidity ^0.8.22; import { OFTUpgradeable } from "@layerzerolabs/oft-evm-upgradeable/contracts/oft/OFTUpgradeable.sol"; diff --git a/examples/oft/contracts/MyOFT.sol b/examples/oft/contracts/MyOFT.sol index f8bc7b47f6..fc0694fc77 100644 --- a/examples/oft/contracts/MyOFT.sol +++ b/examples/oft/contracts/MyOFT.sol @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: UNLICENSED +// SPDX-License-Identifier: MIT pragma solidity ^0.8.22; import { Ownable } from "@openzeppelin/contracts/access/Ownable.sol"; diff --git a/examples/omni-call/contracts/OmniCall.sol b/examples/omni-call/contracts/OmniCall.sol index faf0a4813b..5ea5c6f36b 100644 --- a/examples/omni-call/contracts/OmniCall.sol +++ b/examples/omni-call/contracts/OmniCall.sol @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: UNLICENSED +// SPDX-License-Identifier: MIT pragma solidity 0.8.22; /// ----------------------------------------------------------------------- diff --git a/examples/omni-call/contracts/OmniCallMsgCodecLib.sol b/examples/omni-call/contracts/OmniCallMsgCodecLib.sol index 2295bdabcb..2f34f0e24b 100644 --- a/examples/omni-call/contracts/OmniCallMsgCodecLib.sol +++ b/examples/omni-call/contracts/OmniCallMsgCodecLib.sol @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: UNLICENSED +// SPDX-License-Identifier: MIT pragma solidity 0.8.22; /// ----------------------------------------------------------------------- diff --git a/examples/omni-call/contracts/interfaces/IOmniCall.sol b/examples/omni-call/contracts/interfaces/IOmniCall.sol index 3bfc56d097..ff3a53e4bc 100644 --- a/examples/omni-call/contracts/interfaces/IOmniCall.sol +++ b/examples/omni-call/contracts/interfaces/IOmniCall.sol @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: UNLICENSED +// SPDX-License-Identifier: MIT pragma solidity 0.8.22; /// ----------------------------------------------------------------------- diff --git a/examples/onft721-zksync/contracts/MyONFT721.sol b/examples/onft721-zksync/contracts/MyONFT721.sol index 64350c3c69..a668960733 100644 --- a/examples/onft721-zksync/contracts/MyONFT721.sol +++ b/examples/onft721-zksync/contracts/MyONFT721.sol @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: UNLICENSED +// SPDX-License-Identifier: MIT pragma solidity ^0.8.22; import { ONFT721 } from "@layerzerolabs/onft-evm/contracts/onft721/ONFT721.sol"; diff --git a/examples/onft721/contracts/MyONFT721.sol b/examples/onft721/contracts/MyONFT721.sol index 64350c3c69..a668960733 100644 --- a/examples/onft721/contracts/MyONFT721.sol +++ b/examples/onft721/contracts/MyONFT721.sol @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: UNLICENSED +// SPDX-License-Identifier: MIT pragma solidity ^0.8.22; import { ONFT721 } from "@layerzerolabs/onft-evm/contracts/onft721/ONFT721.sol"; diff --git a/examples/onft721/contracts/MyONFT721Adapter.sol b/examples/onft721/contracts/MyONFT721Adapter.sol index 5a14f57761..1a31ce20d9 100644 --- a/examples/onft721/contracts/MyONFT721Adapter.sol +++ b/examples/onft721/contracts/MyONFT721Adapter.sol @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: UNLICENSED +// SPDX-License-Identifier: MIT pragma solidity ^0.8.22; import { ONFT721Adapter } from "@layerzerolabs/onft-evm/contracts/onft721/ONFT721Adapter.sol"; diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 62f4c41801..384443c4bb 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -42,7 +42,7 @@ importers: version: 17.1.0(eslint-plugin-import@2.29.1)(eslint-plugin-n@16.6.2)(eslint-plugin-promise@6.1.1)(eslint@8.57.1) eslint-plugin-import: specifier: ^2.29.1 - version: 2.29.1(@typescript-eslint/parser@7.7.1)(eslint-import-resolver-typescript@3.6.1)(eslint@8.57.1) + version: 2.29.1(@typescript-eslint/parser@7.7.1)(eslint@8.57.1) eslint-plugin-jest: specifier: ^27.6.3 version: 27.6.3(@typescript-eslint/eslint-plugin@7.7.1)(eslint@8.57.1)(typescript@5.5.3) @@ -4010,7 +4010,7 @@ importers: version: 2.16.2 jest: specifier: ^29.6.2 - version: 29.7.0(@types/node@18.18.14)(ts-node@10.9.2) + version: 29.7.0(@types/node@18.18.14) tsup: specifier: ~8.0.1 version: 8.0.1(@swc/core@1.4.0)(typescript@5.5.3) @@ -4195,7 +4195,7 @@ importers: version: 29.5.12 jest: specifier: ^29.7.0 - version: 29.7.0(@types/node@18.18.14)(ts-node@10.9.2) + version: 29.7.0(@types/node@18.18.14) tslib: specifier: ~2.6.2 version: 2.6.3 @@ -4723,13 +4723,13 @@ importers: version: 3.0.75 '@layerzerolabs/lz-solana-sdk-v2': specifier: ^3.0.0 - version: 3.0.0(typescript@5.5.3) + version: 3.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.5.3) '@layerzerolabs/lz-v2-utilities': specifier: ^3.0.75 version: 3.0.75 '@layerzerolabs/oft-v2-solana-sdk': specifier: ^3.0.38 - version: 3.0.38(@swc/core@1.4.0)(@types/node@18.18.14)(typescript@5.5.3) + version: 3.0.38(@swc/core@1.4.0)(@types/node@18.18.14)(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.5.3) '@layerzerolabs/protocol-devtools': specifier: ~2.0.0 version: link:../protocol-devtools @@ -5350,13 +5350,13 @@ importers: version: 3.0.75 '@layerzerolabs/lz-solana-sdk-v2': specifier: ^3.0.59 - version: 3.0.66(@swc/core@1.4.0)(@types/node@18.18.14)(typescript@5.5.3) + version: 3.0.66(@swc/core@1.4.0)(@types/node@18.18.14)(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.5.3) '@layerzerolabs/lz-v2-utilities': specifier: ^3.0.75 version: 3.0.75 '@layerzerolabs/oft-v2-solana-sdk': specifier: ^3.0.59 - version: 3.0.66(@swc/core@1.4.0)(@types/node@18.18.14)(typescript@5.5.3) + version: 3.0.66(@swc/core@1.4.0)(@types/node@18.18.14)(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.5.3) '@layerzerolabs/protocol-devtools': specifier: ~2.0.0 version: link:../protocol-devtools @@ -5461,7 +5461,7 @@ importers: version: 12.6.1 jest: specifier: ^29.7.0 - version: 29.7.0(@types/node@18.18.14)(ts-node@10.9.2) + version: 29.7.0(@types/node@18.18.14) tsup: specifier: ^8.0.1 version: 8.0.1(@swc/core@1.4.0)(typescript@5.5.3) @@ -9060,13 +9060,13 @@ packages: resolution: {integrity: sha512-WlBSy47LGPILdrNgzPiRtQf/hAY62IN37ncUsQwcr8T7cyX1HZREx2qljuXpvduLDAKn5otsm0XIqHuCRUHEFg==} dependencies: '@typescript-eslint/eslint-plugin': 7.7.1(@typescript-eslint/parser@7.7.1)(eslint@8.57.1)(typescript@5.5.3) - '@typescript-eslint/parser': 7.7.1(eslint@8.57.1)(typescript@5.5.3) + '@typescript-eslint/parser': 7.7.1(eslint@8.57.0)(typescript@5.5.3) eslint: 8.57.1 eslint-config-prettier: 9.1.0(eslint@8.57.1) eslint-import-resolver-typescript: 3.6.1(@typescript-eslint/parser@7.7.1)(eslint-plugin-import@2.29.1)(eslint@8.57.1) eslint-plugin-autofix: 2.2.0(eslint@8.57.1) eslint-plugin-compat: 4.2.0(eslint@8.57.1) - eslint-plugin-import: 2.29.1(@typescript-eslint/parser@7.7.1)(eslint-import-resolver-typescript@3.6.1)(eslint@8.57.1) + eslint-plugin-import: 2.29.1(@typescript-eslint/parser@7.7.1)(eslint@8.57.0) eslint-plugin-prettier: 5.1.3(eslint-config-prettier@9.1.0)(eslint@8.57.1)(prettier@3.2.5) eslint-plugin-unused-imports: 3.2.0(@typescript-eslint/eslint-plugin@7.7.1)(eslint@8.57.1) prettier: 3.2.5 @@ -10291,7 +10291,7 @@ packages: - typescript - utf-8-validate - /@layerzerolabs/lz-solana-sdk-v2@3.0.0(typescript@5.5.3): + /@layerzerolabs/lz-solana-sdk-v2@3.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.5.3): resolution: {integrity: sha512-sPvLXeQUO9QLpjOuWE7V+V8yfoI4E/NBYsH9lO2aPx0LYkQa+88ACgPq43B/zFROUD8238WuSb+doGrn3PKtJQ==} dependencies: '@ethersproject/abi': 5.7.0 @@ -10322,7 +10322,7 @@ packages: - utf-8-validate dev: true - /@layerzerolabs/lz-solana-sdk-v2@3.0.66(@swc/core@1.4.0)(@types/node@18.18.14)(typescript@5.5.3): + /@layerzerolabs/lz-solana-sdk-v2@3.0.66(@swc/core@1.4.0)(@types/node@18.18.14)(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.5.3): resolution: {integrity: sha512-zyuqBYxaVtSa+STdcbO/uzzQV2kyxmBX3flNbvOq7kS2QHBivuaYd/XDbNLE54/egQ63yMtFcilqwy3VzNpclw==} dependencies: '@layerzerolabs/lz-corekit-solana': 3.0.66(@swc/core@1.4.0)(@types/node@18.18.14)(typescript@5.5.3) @@ -10430,7 +10430,7 @@ packages: - utf-8-validate dev: true - /@layerzerolabs/lz-solana-sdk-v2@3.0.86(@swc/core@1.4.0)(@types/node@18.18.14)(typescript@5.5.3): + /@layerzerolabs/lz-solana-sdk-v2@3.0.86(@swc/core@1.4.0)(@types/node@18.18.14)(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.5.3): resolution: {integrity: sha512-FfZLkFHIOPIFLkevQD0QSrfVR2UgREG6YF6oSR92XPViuVpAq0LAyCTXQi915bdiSdQ/Mwd+9eU/9ZPlk9f6sA==} dependencies: '@layerzerolabs/lz-corekit-solana': 3.0.86(@swc/core@1.4.0)(@types/node@18.18.14)(typescript@5.5.3) @@ -10757,12 +10757,12 @@ packages: '@layerzerolabs/lz-definitions': 3.0.75 dev: true - /@layerzerolabs/oft-v2-solana-sdk@3.0.38(@swc/core@1.4.0)(@types/node@18.18.14)(typescript@5.5.3): + /@layerzerolabs/oft-v2-solana-sdk@3.0.38(@swc/core@1.4.0)(@types/node@18.18.14)(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.5.3): resolution: {integrity: sha512-P06/a5+ixph0u1AQkDZ0P0oFaIAdfGPl/UezMfWXUpiWLth428RT0rrMR6qI7z6X1uxqlUFNIotz2ET1fyFcpQ==} dependencies: '@ethersproject/bytes': 5.7.0 '@layerzerolabs/lz-foundation': 3.0.38(@swc/core@1.4.0)(@types/node@18.18.14)(typescript@5.5.3) - '@layerzerolabs/lz-solana-sdk-v2': 3.0.86(@swc/core@1.4.0)(@types/node@18.18.14)(typescript@5.5.3) + '@layerzerolabs/lz-solana-sdk-v2': 3.0.86(@swc/core@1.4.0)(@types/node@18.18.14)(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.5.3) '@layerzerolabs/lz-v2-utilities': 3.0.86 '@metaplex-foundation/beet': 0.7.2 '@metaplex-foundation/beet-solana': 0.4.1 @@ -10788,12 +10788,12 @@ packages: - utf-8-validate dev: true - /@layerzerolabs/oft-v2-solana-sdk@3.0.66(@swc/core@1.4.0)(@types/node@18.18.14)(typescript@5.5.3): + /@layerzerolabs/oft-v2-solana-sdk@3.0.66(@swc/core@1.4.0)(@types/node@18.18.14)(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.5.3): resolution: {integrity: sha512-ijbvj6/Gc4O4WLHfqnrBuKUtIhpaYws/ORj2apZFT1RKSgAX8CCJ9aZmn0ClamEG98i+PpXoroPPU46LMOMZyA==} dependencies: '@ethersproject/bytes': 5.7.0 '@layerzerolabs/lz-foundation': 3.0.66(@swc/core@1.4.0)(@types/node@18.18.14)(typescript@5.5.3) - '@layerzerolabs/lz-solana-sdk-v2': 3.0.86(@swc/core@1.4.0)(@types/node@18.18.14)(typescript@5.5.3) + '@layerzerolabs/lz-solana-sdk-v2': 3.0.86(@swc/core@1.4.0)(@types/node@18.18.14)(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.5.3) '@layerzerolabs/lz-v2-utilities': 3.0.86 '@metaplex-foundation/beet': 0.7.2 '@metaplex-foundation/beet-solana': 0.4.1 @@ -13969,6 +13969,27 @@ packages: - supports-color dev: true + /@typescript-eslint/parser@7.7.1(eslint@8.57.0)(typescript@5.5.3): + resolution: {integrity: sha512-vmPzBOOtz48F6JAGVS/kZYk4EkXao6iGrD838sp1w3NQQC0W8ry/q641KU4PrG7AKNAf56NOcR8GOpH8l9FPCw==} + engines: {node: ^18.18.0 || >=20.0.0} + peerDependencies: + eslint: ^8.56.0 + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + dependencies: + '@typescript-eslint/scope-manager': 7.7.1 + '@typescript-eslint/types': 7.7.1 + '@typescript-eslint/typescript-estree': 7.7.1(typescript@5.5.3) + '@typescript-eslint/visitor-keys': 7.7.1 + debug: 4.3.7 + eslint: 8.57.0 + typescript: 5.5.3 + transitivePeerDependencies: + - supports-color + dev: true + /@typescript-eslint/parser@7.7.1(eslint@8.57.1)(typescript@5.5.3): resolution: {integrity: sha512-vmPzBOOtz48F6JAGVS/kZYk4EkXao6iGrD838sp1w3NQQC0W8ry/q641KU4PrG7AKNAf56NOcR8GOpH8l9FPCw==} engines: {node: ^18.18.0 || >=20.0.0} @@ -16761,7 +16782,7 @@ packages: eslint-plugin-promise: ^6.0.0 dependencies: eslint: 8.57.1 - eslint-plugin-import: 2.29.1(@typescript-eslint/parser@7.7.1)(eslint-import-resolver-typescript@3.6.1)(eslint@8.57.1) + eslint-plugin-import: 2.29.1(@typescript-eslint/parser@7.7.1)(eslint@8.57.1) eslint-plugin-n: 16.6.2(eslint@8.57.1) eslint-plugin-promise: 6.1.1(eslint@8.57.1) dev: true @@ -16787,7 +16808,7 @@ packages: enhanced-resolve: 5.16.0 eslint: 8.57.1 eslint-module-utils: 2.8.1(@typescript-eslint/parser@7.7.1)(eslint-import-resolver-typescript@3.6.1)(eslint@8.57.1) - eslint-plugin-import: 2.29.1(@typescript-eslint/parser@7.7.1)(eslint-import-resolver-typescript@3.6.1)(eslint@8.57.1) + eslint-plugin-import: 2.29.1(@typescript-eslint/parser@7.7.1)(eslint@8.57.0) fast-glob: 3.3.2 get-tsconfig: 4.7.3 is-core-module: 2.13.1 @@ -16799,7 +16820,36 @@ packages: - supports-color dev: true - /eslint-module-utils@2.8.0(@typescript-eslint/parser@7.7.1)(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1)(eslint@8.57.1): + /eslint-module-utils@2.8.0(@typescript-eslint/parser@7.7.1)(eslint-import-resolver-node@0.3.9)(eslint@8.57.0): + resolution: {integrity: sha512-aWajIYfsqCKRDgUfjEXNN/JlrzauMuSEy5sbd7WXbtW3EH6A6MpwEh42c7qD+MqQo9QMJ6fWLAeIJynx0g6OAw==} + engines: {node: '>=4'} + peerDependencies: + '@typescript-eslint/parser': '*' + eslint: '*' + eslint-import-resolver-node: '*' + eslint-import-resolver-typescript: '*' + eslint-import-resolver-webpack: '*' + peerDependenciesMeta: + '@typescript-eslint/parser': + optional: true + eslint: + optional: true + eslint-import-resolver-node: + optional: true + eslint-import-resolver-typescript: + optional: true + eslint-import-resolver-webpack: + optional: true + dependencies: + '@typescript-eslint/parser': 7.7.1(eslint@8.57.0)(typescript@5.5.3) + debug: 3.2.7 + eslint: 8.57.0 + eslint-import-resolver-node: 0.3.9 + transitivePeerDependencies: + - supports-color + dev: true + + /eslint-module-utils@2.8.0(@typescript-eslint/parser@7.7.1)(eslint-import-resolver-node@0.3.9)(eslint@8.57.1): resolution: {integrity: sha512-aWajIYfsqCKRDgUfjEXNN/JlrzauMuSEy5sbd7WXbtW3EH6A6MpwEh42c7qD+MqQo9QMJ6fWLAeIJynx0g6OAw==} engines: {node: '>=4'} peerDependencies: @@ -16824,7 +16874,6 @@ packages: debug: 3.2.7 eslint: 8.57.1 eslint-import-resolver-node: 0.3.9 - eslint-import-resolver-typescript: 3.6.1(@typescript-eslint/parser@7.7.1)(eslint-plugin-import@2.29.1)(eslint@8.57.1) transitivePeerDependencies: - supports-color dev: true @@ -16850,7 +16899,7 @@ packages: eslint-import-resolver-webpack: optional: true dependencies: - '@typescript-eslint/parser': 7.7.1(eslint@8.57.1)(typescript@5.5.3) + '@typescript-eslint/parser': 7.7.1(eslint@8.57.0)(typescript@5.5.3) debug: 3.2.7 eslint: 8.57.1 eslint-import-resolver-typescript: 3.6.1(@typescript-eslint/parser@7.7.1)(eslint-plugin-import@2.29.1)(eslint@8.57.1) @@ -16910,7 +16959,42 @@ packages: regexpp: 3.2.0 dev: true - /eslint-plugin-import@2.29.1(@typescript-eslint/parser@7.7.1)(eslint-import-resolver-typescript@3.6.1)(eslint@8.57.1): + /eslint-plugin-import@2.29.1(@typescript-eslint/parser@7.7.1)(eslint@8.57.0): + resolution: {integrity: sha512-BbPC0cuExzhiMo4Ff1BTVwHpjjv28C5R+btTOGaCRC7UEz801up0JadwkeSk5Ued6TG34uaczuVuH6qyy5YUxw==} + engines: {node: '>=4'} + peerDependencies: + '@typescript-eslint/parser': '*' + eslint: ^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8 + peerDependenciesMeta: + '@typescript-eslint/parser': + optional: true + dependencies: + '@typescript-eslint/parser': 7.7.1(eslint@8.57.0)(typescript@5.5.3) + array-includes: 3.1.7 + array.prototype.findlastindex: 1.2.3 + array.prototype.flat: 1.3.2 + array.prototype.flatmap: 1.3.2 + debug: 3.2.7 + doctrine: 2.1.0 + eslint: 8.57.0 + eslint-import-resolver-node: 0.3.9 + eslint-module-utils: 2.8.0(@typescript-eslint/parser@7.7.1)(eslint-import-resolver-node@0.3.9)(eslint@8.57.0) + hasown: 2.0.0 + is-core-module: 2.13.1 + is-glob: 4.0.3 + minimatch: 3.1.2 + object.fromentries: 2.0.7 + object.groupby: 1.0.1 + object.values: 1.1.7 + semver: 6.3.1 + tsconfig-paths: 3.15.0 + transitivePeerDependencies: + - eslint-import-resolver-typescript + - eslint-import-resolver-webpack + - supports-color + dev: true + + /eslint-plugin-import@2.29.1(@typescript-eslint/parser@7.7.1)(eslint@8.57.1): resolution: {integrity: sha512-BbPC0cuExzhiMo4Ff1BTVwHpjjv28C5R+btTOGaCRC7UEz801up0JadwkeSk5Ued6TG34uaczuVuH6qyy5YUxw==} engines: {node: '>=4'} peerDependencies: @@ -16929,7 +17013,7 @@ packages: doctrine: 2.1.0 eslint: 8.57.1 eslint-import-resolver-node: 0.3.9 - eslint-module-utils: 2.8.0(@typescript-eslint/parser@7.7.1)(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1)(eslint@8.57.1) + eslint-module-utils: 2.8.0(@typescript-eslint/parser@7.7.1)(eslint-import-resolver-node@0.3.9)(eslint@8.57.1) hasown: 2.0.0 is-core-module: 2.13.1 is-glob: 4.0.3 @@ -19720,6 +19804,34 @@ packages: - babel-plugin-macros - supports-color + /jest-cli@29.7.0(@types/node@18.18.14): + resolution: {integrity: sha512-OVVobw2IubN/GSYsxETi+gOe7Ka59EFMR/twOU3Jb2GnKKeMGJB5SGUUrEz3SFVmJASUdZUzy83sLNNQ2gZslg==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + hasBin: true + peerDependencies: + node-notifier: ^8.0.1 || ^9.0.0 || ^10.0.0 + peerDependenciesMeta: + node-notifier: + optional: true + dependencies: + '@jest/core': 29.7.0(ts-node@10.9.2) + '@jest/test-result': 29.7.0 + '@jest/types': 29.6.3 + chalk: 4.1.2 + create-jest: 29.7.0(@types/node@18.18.14)(ts-node@10.9.2) + exit: 0.1.2 + import-local: 3.1.0 + jest-config: 29.7.0(@types/node@18.18.14)(ts-node@10.9.2) + jest-util: 29.7.0 + jest-validate: 29.7.0 + yargs: 17.7.2 + transitivePeerDependencies: + - '@types/node' + - babel-plugin-macros + - supports-color + - ts-node + dev: true + /jest-cli@29.7.0(@types/node@18.18.14)(ts-node@10.9.2): resolution: {integrity: sha512-OVVobw2IubN/GSYsxETi+gOe7Ka59EFMR/twOU3Jb2GnKKeMGJB5SGUUrEz3SFVmJASUdZUzy83sLNNQ2gZslg==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} @@ -20132,6 +20244,27 @@ packages: merge-stream: 2.0.0 supports-color: 8.1.1 + /jest@29.7.0(@types/node@18.18.14): + resolution: {integrity: sha512-NIy3oAFp9shda19hy4HK0HRTWKtPJmGdnvywu01nOqNC2vZg+Z+fvJDxpMQA88eb2I9EcafcdjYgsDthnYTvGw==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + hasBin: true + peerDependencies: + node-notifier: ^8.0.1 || ^9.0.0 || ^10.0.0 + peerDependenciesMeta: + node-notifier: + optional: true + dependencies: + '@jest/core': 29.7.0(ts-node@10.9.2) + '@jest/types': 29.6.3 + import-local: 3.1.0 + jest-cli: 29.7.0(@types/node@18.18.14) + transitivePeerDependencies: + - '@types/node' + - babel-plugin-macros + - supports-color + - ts-node + dev: true + /jest@29.7.0(@types/node@18.18.14)(ts-node@10.9.2): resolution: {integrity: sha512-NIy3oAFp9shda19hy4HK0HRTWKtPJmGdnvywu01nOqNC2vZg+Z+fvJDxpMQA88eb2I9EcafcdjYgsDthnYTvGw==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}