From f8742fbb457394a3bf7bf85ae3ecbb0a1c1ab7bc Mon Sep 17 00:00:00 2001 From: alexanderliteplo Date: Wed, 2 Jul 2025 17:31:43 -0700 Subject: [PATCH 1/5] Enhance Solana to Move-VM integration with new Aptos support and configuration updates - Updated README.md to clarify Solana wiring instructions and added a note on deployment requirements. - Modified aptos-move-send.ts to correct environment variable names and update message content. - Introduced new Aptos configuration files and tasks for improved integration. - Added documentation for wiring Solana to Move-VM, including detailed deployment steps. - Implemented Aptos SDK factory and signer factory for better handling of Aptos transactions. --- examples/oapp-aptos-move/README.md | 13 +- .../scripts/aptos-move-send.ts | 11 +- examples/oapp-solana/docs/Aptos.md | 63 ++++ .../oapp-solana/docs/move.layerzero.config.ts | 119 +++++++ .../tasks/aptos/aptosEndpointV2.ts | 325 ++++++++++++++++++ .../tasks/aptos/aptosSdkFactory.ts | 66 ++++ .../tasks/aptos/aptosSignerFactory.ts | 54 +++ examples/oapp-solana/tasks/aptos/index.ts | 3 + examples/oapp-solana/tasks/common/utils.ts | 19 +- examples/oapp-solana/tasks/common/wire.ts | 15 +- examples/oft-solana/docs/Aptos.md | 70 +++- .../oft-solana/docs/move.layerzero.config.ts | 119 +++++++ 12 files changed, 846 insertions(+), 31 deletions(-) create mode 100644 examples/oapp-solana/docs/Aptos.md create mode 100644 examples/oapp-solana/docs/move.layerzero.config.ts create mode 100644 examples/oapp-solana/tasks/aptos/aptosEndpointV2.ts create mode 100644 examples/oapp-solana/tasks/aptos/aptosSdkFactory.ts create mode 100644 examples/oapp-solana/tasks/aptos/aptosSignerFactory.ts create mode 100644 examples/oapp-solana/tasks/aptos/index.ts create mode 100644 examples/oft-solana/docs/move.layerzero.config.ts diff --git a/examples/oapp-aptos-move/README.md b/examples/oapp-aptos-move/README.md index 6e67decd52..4e406d1901 100644 --- a/examples/oapp-aptos-move/README.md +++ b/examples/oapp-aptos-move/README.md @@ -179,14 +179,17 @@ Ensure that in move.layerzero.config.ts, all of your evm contracts have the owne ] ``` -If you are wiring solana to move-vm, create a file in `deployments/solana-mainnet/MyOFT.json` (or `deployments/solana-testnet/MyOFT.json` if you are using testnet) and add the following field: +If you are wiring solana to move-vm, in your config add: -```json -{ - "address": -} +```ts +const solanaContract: OmniPointHardhat = { + eid: EndpointId.SOLANA_V2_TESTNET as EndpointId, + address: "YOUR_DEPLOYED_SOLANA_OAPP_ADDRESS", +}; ``` +Note: Solana OApp must be deployed with the Solana example. + Commands: ### To wire from EVM to Move-VM: diff --git a/examples/oapp-aptos-move/scripts/aptos-move-send.ts b/examples/oapp-aptos-move/scripts/aptos-move-send.ts index feb14c6372..6b32d8480e 100644 --- a/examples/oapp-aptos-move/scripts/aptos-move-send.ts +++ b/examples/oapp-aptos-move/scripts/aptos-move-send.ts @@ -11,6 +11,7 @@ import { Account, + AccountAddressInput, Aptos, AptosConfig, Ed25519PrivateKey, @@ -29,13 +30,13 @@ import { Options } from '@layerzerolabs/lz-v2-utilities' dotenv.config() // 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 (!process.env.APTOS_PRIVATE_KEY || !process.env.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 +const ACCOUNT_ADDRESS = process.env.APTOS_ACCOUNT_ADDRESS // OApp configuration const OAPP_ADDRESS = '' // Set your OApp's address on Aptos @@ -79,7 +80,7 @@ async function send() { 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: ACCOUNT_ADDRESS as AccountAddressInput }) console.log('Account balance:', Number(balance) / 100000000, 'APT') if (Number(balance) < Number(quote[0])) { @@ -96,7 +97,7 @@ async function send() { // Create the transaction const transaction: SimpleTransaction = await aptos.transaction.build.simple({ - sender: ACCOUNT_ADDRESS, + sender: ACCOUNT_ADDRESS as AccountAddressInput, data: payload, options: { maxGasAmount: 100000, diff --git a/examples/oapp-solana/docs/Aptos.md b/examples/oapp-solana/docs/Aptos.md new file mode 100644 index 0000000000..5728de5ff3 --- /dev/null +++ b/examples/oapp-solana/docs/Aptos.md @@ -0,0 +1,63 @@ +### Wiring Solana to Move-VM (Aptos, Initia, Movement, etc.) + +:warning: **Important Limitations for Solana ↔ Move-VM Pathways** + +Currently, you can only perform **one-way wiring from Solana → Move-VM** using this example. For the reverse pathway (Move-VM → Solana), you must use the [OApp Aptos Move example](https://github.com/LayerZero-Labs/devtools/tree/main/examples/oapp-aptos-move). Please follow the deployment instructions in the README.md of the `oapp-aptos-move` example for deploying to Move-VM and configuring the Move-VM → Solana pathway. + +#### Configuration Steps for Solana → Aptos + +:information_source: **For bidirectional Solana ↔ Aptos communication, deploy both examples:** + +- **Solana → Aptos**: Use this example +- **Aptos → Solana**: Use the [OApp Aptos Move example](https://github.com/LayerZero-Labs/devtools/tree/main/examples/oapp-aptos-move) + +#### Deployment Process + +1. **Create and Deploy Solana Example** + + - Create the Solana example: `LZ_ENABLE_SOLANA_OAPP_EXAMPLE=1 npx create-lz-oapp@latest` + - Deploy to Solana following the deployment instructions in the Solana example README + +2. **Create and Deploy Aptos Move Example** + + - Create the Aptos Move example: `LZ_ENABLE_EXPERIMENTAL_MOVE_VM_EXAMPLES=1 npx create-lz-oapp@latest` + - Deploy to Aptos following the deployment and initialization instructions in the Aptos example README + + Your directory structure should look like this: + + ``` + your-folder/ + ├── your-aptos-example/ + └── your-solana-example/ + ``` + +3. **Configure Solana Example** + + - Navigate to the Solana example directory + - Use the example configuration at `./docs/move.layerzero.config.ts` + - Fill out the configuration with your desired values + - Replace `./layerzero.config.ts` with the completed `move.layerzero.config.ts` file + +4. **Wire Solana to Aptos** + + Execute the following commands in the Solana example directory: + + ```bash + npx hardhat lz:oapp:solana:init-config --oapp-config move.layerzero.config.ts + ``` + + ```bash + npx hardhat lz:oapp:wire --oapp-config move.layerzero.config.ts + ``` + + If these commands succeed, you have successfully wired the Solana contract to the Aptos Move contract. + +5. **Wire Aptos to Solana** + + - Transfer the `move.layerzero.config.ts` file from the Solana example to the Aptos Move example directory + - In the Aptos Move example directory, run: + ```bash + pnpm run lz:sdk:move:wire --oapp-config move.layerzero.config.ts + ``` + + If this command succeeds, you are ready to test the bidirectional pathway. diff --git a/examples/oapp-solana/docs/move.layerzero.config.ts b/examples/oapp-solana/docs/move.layerzero.config.ts new file mode 100644 index 0000000000..89a2960abc --- /dev/null +++ b/examples/oapp-solana/docs/move.layerzero.config.ts @@ -0,0 +1,119 @@ +import { EndpointId } from '@layerzerolabs/lz-definitions' +import { ExecutorOptionType } from '@layerzerolabs/lz-v2-utilities' +import { OAppOmniGraphHardhat, OmniPointHardhat } from '@layerzerolabs/toolbox-hardhat' + +enum MsgType { + SEND = 1, + SEND_AND_CALL = 2, +} +const aptosContract: OmniPointHardhat = { + eid: EndpointId.APTOS_V2_TESTNET as EndpointId, + address: 'YOUR_DEPLOYED_APTOS_CONTRACT_ADDRESS', +} +const solanaContract: OmniPointHardhat = { + eid: EndpointId.SOLANA_V2_TESTNET as EndpointId, + address: 'YOUR_DEPLOYED_SOLANA_OAPP_ADDRESS', +} + +const layerZeroDVNAptosAddress = '0x756f8ab056688d22687740f4a9aeec3b361170b28d08b719e28c4d38eed1043e' +const layerZeroDVNSolanaAddress = '4VDjp6XQaxoZf5RGwiPU9NR1EXSZn2TP4ATMmiSzLfhb' + +const config: OAppOmniGraphHardhat = { + contracts: [ + { + contract: solanaContract, + config: { + owner: 'YOUR_SOLANA_OWNER_ADDRESS', + delegate: 'YOUR_SOLANA_OWNER_ADDRESS', + }, + }, + { + contract: aptosContract, + config: { + owner: 'YOUR_APTOS_ACCOUNT_ADDRESS', + delegate: 'YOUR_APTOS_ACCOUNT_ADDRESS', + }, + }, + ], + connections: [ + { + from: aptosContract, + to: solanaContract, + config: { + enforcedOptions: [ + { + msgType: MsgType.SEND_AND_CALL, + optionType: ExecutorOptionType.LZ_RECEIVE, + gas: 5_000, + value: 0, + }, + ], + sendLibrary: '0xcc1c03aed42e2841211865758b5efe93c0dde2cb7a2a5dc6cf25a4e33ad23690', + receiveLibraryConfig: { + receiveLibrary: '0xcc1c03aed42e2841211865758b5efe93c0dde2cb7a2a5dc6cf25a4e33ad23690', + gracePeriod: BigInt(0), + }, + sendConfig: { + executorConfig: { + maxMessageSize: 10_000, + executor: '0x93353700091200ef9fdc536ce6a86182cc7e62da25f94356be9421c6310b9585', + }, + ulnConfig: { + confirmations: BigInt(10), + requiredDVNs: [layerZeroDVNAptosAddress], + optionalDVNs: [], + optionalDVNThreshold: 0, + }, + }, + receiveConfig: { + ulnConfig: { + confirmations: BigInt(15), + requiredDVNs: [layerZeroDVNAptosAddress], + optionalDVNs: [], + optionalDVNThreshold: 0, + }, + }, + }, + }, + { + from: solanaContract, + to: aptosContract, + config: { + enforcedOptions: [ + { + msgType: 1, + optionType: ExecutorOptionType.LZ_RECEIVE, + gas: 200_000, + value: 0, + }, + ], + sendLibrary: '7a4WjyR8VZ7yZz5XJAKm39BUGn5iT9CKcv2pmG9tdXVH', + receiveLibraryConfig: { + receiveLibrary: '7a4WjyR8VZ7yZz5XJAKm39BUGn5iT9CKcv2pmG9tdXVH', + gracePeriod: BigInt(0), + }, + sendConfig: { + executorConfig: { + maxMessageSize: 10_000, + executor: 'AwrbHeCyniXaQhiJZkLhgWdUCteeWSGaSN1sTfLiY7xK', + }, + ulnConfig: { + confirmations: BigInt(15), + requiredDVNs: [layerZeroDVNSolanaAddress], + optionalDVNs: [], + optionalDVNThreshold: 0, + }, + }, + receiveConfig: { + ulnConfig: { + confirmations: BigInt(10), + requiredDVNs: [layerZeroDVNSolanaAddress], + optionalDVNs: [], + optionalDVNThreshold: 0, + }, + }, + }, + }, + ], +} +export default config diff --git a/examples/oapp-solana/tasks/aptos/aptosEndpointV2.ts b/examples/oapp-solana/tasks/aptos/aptosEndpointV2.ts new file mode 100644 index 0000000000..4ff52e84d1 --- /dev/null +++ b/examples/oapp-solana/tasks/aptos/aptosEndpointV2.ts @@ -0,0 +1,325 @@ +import { OmniAddress, OmniPoint, OmniTransaction } from '@layerzerolabs/devtools' +import { EndpointId } from '@layerzerolabs/lz-definitions' +import { + IEndpointV2, + MessageParams, + MessagingFee, + SetConfigParam, + Timeout, + Uln302ConfigType, + Uln302ExecutorConfig, + Uln302SetExecutorConfig, + Uln302SetUlnConfig, + Uln302UlnConfig, + UlnReadSetUlnConfig, + UlnReadUlnConfig, + UlnReadUlnUserConfig, +} from '@layerzerolabs/protocol-devtools' + +/** + * Minimal "AptosEndpointV2" skeleton that implements IEndpointV2 for Aptos. + * All methods here return placeholder or dummy values for now. + */ +export class AptosEndpointV2 implements IEndpointV2 { + // The devtools often expect the "point" property from IOmniSDK + public point: OmniPoint + + constructor(point: OmniPoint) { + this.point = point + } + + // + // ---------------------------------------------------------- + // Required by IOmniSDK (the base) or the IEndpointV2 extension + // ---------------------------------------------------------- + + // The devtools might call this to fetch a "Uln302" object. + // For now, return a dummy object that implements IUln302 + async getUln302SDK(_address: OmniAddress) { + return { + point: this.point, + // placeholders to avoid compile errors: + async getUlnConfig(_eid: EndpointId, _address: OmniAddress, _type: Uln302ConfigType) { + return {} as Uln302UlnConfig + }, + async getAppUlnConfig(_eid: EndpointId, _address: OmniAddress, _type: Uln302ConfigType) { + return {} as Uln302UlnConfig + }, + async hasAppUlnConfig( + _eid: EndpointId, + _oapp: OmniAddress, + _config: Uln302UlnConfig, + _type: Uln302ConfigType + ) { + return false + }, + async setDefaultUlnConfig(_eid: EndpointId, _config: Uln302UlnConfig) { + return { + point: this.point, + data: '0x00', + } as OmniTransaction + }, + async getExecutorConfig(_eid: EndpointId, _address: OmniAddress) { + return { + maxMessageSize: 1024, + executor: '0x0', + } as Uln302ExecutorConfig + }, + async getAppExecutorConfig(_eid: EndpointId, _address: OmniAddress): Promise { + return { + maxMessageSize: 1024, + executor: '0x0', + } as Uln302ExecutorConfig + }, + async hasAppExecutorConfig(_eid: EndpointId, _oapp: OmniAddress, _config: Uln302ExecutorConfig) { + return false + }, + async setDefaultExecutorConfig(_eid: EndpointId, _config: Uln302ExecutorConfig) { + return { + point: this.point, + data: '0x00', + } as OmniTransaction + }, + } + } + + // The devtools might call this to fetch a "UlnRead" object. + // For now, return a dummy object that implements IUlnRead + async getUlnReadSDK(_address: OmniAddress) { + return { + point: this.point, + async getUlnConfig(_channelId: number, _address: OmniAddress) { + return { + executor: '0x0', + requiredDVNs: [], + optionalDVNs: [], + optionalDVNThreshold: 0, + } as UlnReadUlnConfig + }, + async getAppUlnConfig(_channelId: number, _address: OmniAddress) { + return { + executor: '0x0', + requiredDVNs: [], + optionalDVNs: [], + optionalDVNThreshold: 0, + } as UlnReadUlnConfig + }, + async hasAppUlnConfig(_channelId: number, _oapp: OmniAddress, _config: UlnReadUlnConfig) { + return false + }, + async setDefaultUlnConfig(_channelId: number, _config: UlnReadUlnConfig) { + return { + point: this.point, + data: '0x00', + } as OmniTransaction + }, + } + } + + // + // ---------------------------------------------------------- + // Required by IEndpointV2 specifically + // ---------------------------------------------------------- + + async getDelegate(_oapp: OmniAddress): Promise { + return undefined + } + + async isDelegate(_oapp: OmniAddress, _delegate: OmniAddress): Promise { + return false + } + + async getDefaultReceiveLibrary(_eid: EndpointId): Promise { + return undefined + } + + async setDefaultReceiveLibrary(_eid: EndpointId, _uln: OmniAddress, _gracePeriod?: bigint) { + return { + point: this.point, + data: '0x00', + } as OmniTransaction + } + + async getDefaultSendLibrary(_eid: EndpointId): Promise { + return undefined + } + + async setDefaultSendLibrary(_eid: EndpointId, _uln: OmniAddress) { + return { + point: this.point, + data: '0x00', + } as OmniTransaction + } + + async isRegisteredLibrary(_uln: OmniAddress): Promise { + return false + } + + async registerLibrary(_uln: OmniAddress) { + return { + point: this.point, + data: '0x00', + } as OmniTransaction + } + + async getSendLibrary(_sender: OmniAddress, _dstEid: EndpointId): Promise { + return '0x0' + } + + async getReceiveLibrary(_receiver: OmniAddress, _srcEid: EndpointId): Promise<[OmniAddress | undefined, boolean]> { + return ['0x0', false] + } + + async getDefaultReceiveLibraryTimeout(_eid: EndpointId): Promise { + return { lib: '0x0', expiry: BigInt(0) } + } + + async getReceiveLibraryTimeout(_receiver: OmniAddress, _srcEid: EndpointId): Promise { + return { lib: '0x0', expiry: BigInt(0) } + } + + async setSendLibrary(_oapp: OmniAddress, _eid: EndpointId, _uln: OmniAddress) { + return { + point: this.point, + data: '0x00', + } as OmniTransaction + } + + async isDefaultSendLibrary(_sender: OmniAddress, _dstEid: EndpointId): Promise { + return false + } + + async setReceiveLibrary(_oapp: OmniAddress, _eid: EndpointId, _uln: OmniAddress, _gracePeriod: bigint) { + return { + point: this.point, + data: '0x00', + } as OmniTransaction + } + + async setReceiveLibraryTimeout(_oapp: OmniAddress, _eid: EndpointId, _uln: OmniAddress, _expiry: bigint) { + return { + point: this.point, + data: '0x00', + } as OmniTransaction + } + + async getExecutorConfig(_oapp: OmniAddress, _uln: OmniAddress, _eid: EndpointId) { + return { + maxMessageSize: 1024, + executor: '0x0', + } as Uln302ExecutorConfig + } + + async getAppExecutorConfig(_oapp: OmniAddress, _uln: OmniAddress, _eid: EndpointId) { + return { + maxMessageSize: 1024, + executor: '0x0', + } as Uln302ExecutorConfig + } + + async hasAppExecutorConfig(_oapp: OmniAddress, _uln: OmniAddress, _eid: EndpointId, _config: Uln302ExecutorConfig) { + return false + } + + async setExecutorConfig(_oapp: OmniAddress, _uln: OmniAddress, _setExecutorConfig: Uln302SetExecutorConfig[]) { + // Possibly return multiple OmniTransactions if the devtools call expects them + return [ + { + point: this.point, + data: '0x00', + }, + ] as OmniTransaction[] + } + + async getUlnConfig(_oapp: OmniAddress, _uln: OmniAddress, _eid: EndpointId, _type: Uln302ConfigType) { + return { + confirmations: BigInt(0), + requiredDVNs: [], + optionalDVNs: [], + optionalDVNThreshold: 0, + } as Uln302UlnConfig + } + + async getAppUlnConfig(_oapp: OmniAddress, _uln: OmniAddress, _eid: EndpointId, _type: Uln302ConfigType) { + return { + confirmations: BigInt(0), + requiredDVNs: [], + optionalDVNs: [], + optionalDVNThreshold: 0, + } as Uln302UlnConfig + } + + async getAppUlnReadConfig(_oapp: OmniAddress, _uln: OmniAddress, _channelId: number) { + return { + executor: '0x0', + requiredDVNs: [], + optionalDVNs: [], + optionalDVNThreshold: 0, + } as UlnReadUlnConfig + } + + async hasAppUlnConfig( + _oapp: OmniAddress, + _uln: OmniAddress, + _eid: EndpointId, + _config: any, + _type: Uln302ConfigType + ) { + return false + } + + async hasAppUlnReadConfig( + _oapp: OmniAddress, + _uln: OmniAddress, + _channelId: number, + _config: UlnReadUlnUserConfig + ) { + return false + } + + async setUlnConfig(_oapp: OmniAddress, _uln: OmniAddress, _setUlnConfig: Uln302SetUlnConfig[]) { + return [ + { + point: this.point, + data: '0x00', + }, + ] as OmniTransaction[] + } + + async setUlnReadConfig(_oapp: OmniAddress, _uln: OmniAddress, _setUlnConfig: UlnReadSetUlnConfig[]) { + return [ + { + point: this.point, + data: '0x00', + }, + ] as OmniTransaction[] + } + + async getUlnConfigParams(_uln: OmniAddress, _setUlnConfig: Uln302SetUlnConfig[]) { + return [] as SetConfigParam[] + } + + async getUlnReadConfigParams(_uln: OmniAddress, _setUlnConfig: UlnReadSetUlnConfig[]) { + return [] as SetConfigParam[] + } + + async getExecutorConfigParams(_uln: OmniAddress, _setExecutorConfig: Uln302SetExecutorConfig[]) { + return [] as SetConfigParam[] + } + + async setConfig(_oapp: OmniAddress, _uln: OmniAddress, _setConfigParam: SetConfigParam[]) { + return [ + { + point: this.point, + data: '0x00', + }, + ] as OmniTransaction[] + } + + async quote(_params: MessageParams, _sender: OmniAddress): Promise { + return { + nativeFee: BigInt(0), + lzTokenFee: BigInt(0), + } + } +} diff --git a/examples/oapp-solana/tasks/aptos/aptosSdkFactory.ts b/examples/oapp-solana/tasks/aptos/aptosSdkFactory.ts new file mode 100644 index 0000000000..a6b6aec3a0 --- /dev/null +++ b/examples/oapp-solana/tasks/aptos/aptosSdkFactory.ts @@ -0,0 +1,66 @@ +import { OmniAddress, OmniPoint, OmniTransaction } from '@layerzerolabs/devtools' +import { ChainType, EndpointId, endpointIdToChainType } from '@layerzerolabs/lz-definitions' +import { IOApp, OAppEnforcedOptionParam } from '@layerzerolabs/ua-devtools' + +import { AptosEndpointV2 } from './aptosEndpointV2' + +export function createAptosOAppFactory() { + return async function (point: OmniPoint): Promise { + const supportedChaintypes = [ChainType.APTOS, ChainType.INITIA] + if (!supportedChaintypes.includes(endpointIdToChainType(point.eid))) { + throw new Error(`Aptos SDK factory can only create SDKs for Aptos networks. Received EID ${point.eid}.`) + } + + const createStubTransaction = (description: string): OmniTransaction => ({ + point, + data: `0x`, + description: `[APTOS STUB] ${description}`, + }) + + return { + point, + async getOwner(): Promise { + return undefined + }, + async hasOwner(owner: OmniAddress): Promise { + return false + }, + async setOwner(owner: OmniAddress): Promise { + return createStubTransaction(`setOwner(${owner})`) + }, + async getEndpointSDK() { + return new AptosEndpointV2(point) + }, + async getPeer(eid: EndpointId): Promise { + return undefined + }, + async hasPeer(eid: EndpointId, peer: OmniAddress): Promise { + return false + }, + async setPeer(eid: EndpointId, peer: OmniAddress | null | undefined): Promise { + return createStubTransaction(`setPeer(${eid}, ${peer})`) + }, + async getDelegate(): Promise { + return undefined + }, + async setDelegate(address: OmniAddress): Promise { + return createStubTransaction(`setDelegate(${address})`) + }, + async isDelegate(): Promise { + return false + }, + async getEnforcedOptions(): Promise { + return {} + }, + async setEnforcedOptions(enforcedOptions: OAppEnforcedOptionParam[]): Promise { + return createStubTransaction(`setEnforcedOptions(${enforcedOptions.length} options)`) + }, + async getCallerBpsCap(): Promise { + return BigInt(0) + }, + async setCallerBpsCap(callerBpsCap: bigint): Promise { + return createStubTransaction(`setCallerBpsCap(${callerBpsCap})`) + }, + } + } +} diff --git a/examples/oapp-solana/tasks/aptos/aptosSignerFactory.ts b/examples/oapp-solana/tasks/aptos/aptosSignerFactory.ts new file mode 100644 index 0000000000..11fc45bbbf --- /dev/null +++ b/examples/oapp-solana/tasks/aptos/aptosSignerFactory.ts @@ -0,0 +1,54 @@ +import { + OmniPoint, + OmniSigner, + OmniTransaction, + OmniTransactionReceipt, + OmniTransactionResponse, + formatEid, +} from '@layerzerolabs/devtools' +import { ChainType, EndpointId, endpointIdToChainType } from '@layerzerolabs/lz-definitions' + +export function createAptosSignerFactory(): ( + eid: EndpointId +) => Promise>> { + return async function (eid: EndpointId): Promise>> { + if (endpointIdToChainType(eid) !== ChainType.APTOS && endpointIdToChainType(eid) !== ChainType.INITIA) { + throw new Error(`createAptosSignerFactory() called with Move VM EID: ${formatEid(eid)}`) + } + + const aptosSigner: OmniSigner> = { + // The devtools signature requires these members: + eid, + getPoint: () => { + const point: OmniPoint = { + eid, + address: '0x0', + } + return point + }, + + /** + * sign(omniTx) => Promise + * Build & sign an Aptos entry function call, returning the BCS as a hex string. + */ + sign: async (omniTx: OmniTransaction): Promise => { + return '0x0' + }, + + /** + * signAndSend(omniTx) => Promise> + * Just calls sign(...) to get the BCS hex, then submit it. + */ + signAndSend: async (omniTx: OmniTransaction) => { + return { + transactionHash: '0x0', + wait: async (_confirmations?: number) => { + return { transactionHash: '0x0' } + }, + } + }, + } + + return aptosSigner + } +} diff --git a/examples/oapp-solana/tasks/aptos/index.ts b/examples/oapp-solana/tasks/aptos/index.ts new file mode 100644 index 0000000000..80f69f7420 --- /dev/null +++ b/examples/oapp-solana/tasks/aptos/index.ts @@ -0,0 +1,3 @@ +export { AptosEndpointV2 } from './aptosEndpointV2' +export { createAptosOAppFactory } from './aptosSdkFactory' +export { createAptosSignerFactory } from './aptosSignerFactory' diff --git a/examples/oapp-solana/tasks/common/utils.ts b/examples/oapp-solana/tasks/common/utils.ts index a994d2bfb6..e3d2c5fbed 100644 --- a/examples/oapp-solana/tasks/common/utils.ts +++ b/examples/oapp-solana/tasks/common/utils.ts @@ -8,7 +8,6 @@ import { OmniSigner, OmniTransactionReceipt, OmniTransactionResponse, - firstFactory, formatEid, } from '@layerzerolabs/devtools' import { createConnectedContractFactory } from '@layerzerolabs/devtools-evm-hardhat' @@ -31,6 +30,7 @@ import { } from '@layerzerolabs/ua-devtools-evm-hardhat' import { createSimpleOAppFactory } from '../../lib/factory' +import { createAptosOAppFactory } from '../aptos' export const createSolanaConnectionFactory = () => createConnectionFactory( @@ -50,6 +50,7 @@ export const createSdkFactory = ( // We do this by using the firstFactory helper function that is provided by the devtools package. // This function will try to execute the factories one by one and return the first one that succeeds. const evmSdkfactory = createOAppFactory(createConnectedContractFactory()) + const aptosSdkFactory = createAptosOAppFactory() const solanaSdkFactory = createSimpleOAppFactory( // The first parameter to createOFTFactory is a user account factory // @@ -76,7 +77,21 @@ export const createSdkFactory = ( // // We do this by using the firstFactory helper function that is provided by the devtools package. // This function will try to execute the factories one by one and return the first one that succeeds. - return firstFactory<[OmniPoint], IOApp>(evmSdkfactory, solanaSdkFactory) + return async (point: OmniPoint): Promise => { + if (endpointIdToChainType(point.eid) === ChainType.SOLANA) { + return solanaSdkFactory(point) + } else if (endpointIdToChainType(point.eid) === ChainType.EVM) { + return evmSdkfactory(point) + } else if ( + endpointIdToChainType(point.eid) === ChainType.APTOS || + endpointIdToChainType(point.eid) === ChainType.INITIA + ) { + return aptosSdkFactory(point) + } else { + console.error(`Unsupported chain type for EID ${point.eid}`) + throw new Error(`Unsupported chain type for EID ${point.eid}`) + } + } } export const createSolanaSignerFactory = ( diff --git a/examples/oapp-solana/tasks/common/wire.ts b/examples/oapp-solana/tasks/common/wire.ts index c76e27b3bd..31de828c66 100644 --- a/examples/oapp-solana/tasks/common/wire.ts +++ b/examples/oapp-solana/tasks/common/wire.ts @@ -14,6 +14,7 @@ import { TASK_LZ_OWNABLE_TRANSFER_OWNERSHIP, } from '@layerzerolabs/ua-devtools-evm-hardhat' +import { createAptosSignerFactory } from '../aptos' import { getSolanaDeployment, useWeb3Js } from '../solana' import { findSolanaEndpointIdInGraph } from '../solana/utils' @@ -104,6 +105,7 @@ task(TASK_LZ_OAPP_WIRE) // We'll also need a signer factory const solanaSignerFactory = createSolanaSignerFactory(keypair, connectionFactory, args.multisigKey) + const aptosSignerFactory = createAptosSignerFactory() // // @@ -169,6 +171,17 @@ task(TASK_LZ_OAPP_WIRE) ...subtaskArgs, configurator: configurator ?? subtaskArgs.configurator, sdkFactory, + graph: { + ...subtaskArgs.graph, + contracts: subtaskArgs.graph.contracts.filter((contract) => { + const chainType = endpointIdToChainType(contract.point.eid) + return chainType !== ChainType.APTOS && chainType !== ChainType.INITIA + }), + connections: subtaskArgs.graph.connections.filter((connection) => { + const fromChainType = endpointIdToChainType(connection.vector.from.eid) + return fromChainType !== ChainType.APTOS && fromChainType !== ChainType.INITIA + }), + }, }) } ) @@ -181,7 +194,7 @@ task(TASK_LZ_OAPP_WIRE) subtask(SUBTASK_LZ_SIGN_AND_SEND, 'Sign OFT transactions', (args: SignAndSendTaskArgs, _hre, runSuper) => runSuper({ ...args, - createSigner: firstFactory(solanaSignerFactory, args.createSigner), + createSigner: firstFactory(aptosSignerFactory, solanaSignerFactory, args.createSigner), }) ) diff --git a/examples/oft-solana/docs/Aptos.md b/examples/oft-solana/docs/Aptos.md index 19eb3e48c0..79a6ce17b4 100644 --- a/examples/oft-solana/docs/Aptos.md +++ b/examples/oft-solana/docs/Aptos.md @@ -1,29 +1,63 @@ ### Wiring Solana to Move-VM (Aptos, Initia, Movement, etc.) -:warning: **Important limitations for Solana ↔ Move-VM pathways:** +:warning: **Important Limitations for Solana ↔ Move-VM Pathways** -Currently, you can only do **one-way wiring from Solana → Move-VM** using this example. For the reverse pathway (Move-VM → Solana), you must use the [OFT Aptos Move example](https://github.com/LayerZero-Labs/devtools/tree/main/examples/oft-aptos-move). Please follow the instructions in the README.md of the `oft-aptos-move` example for deploying to Move-VM and wiring the Move-VM → Solana pathway. +Currently, you can only perform **one-way wiring from Solana → Move-VM** using this example. For the reverse pathway (Move-VM → Solana), you must use the [OFT Aptos Move example](https://github.com/LayerZero-Labs/devtools/tree/main/examples/oft-aptos-move). Please follow the deployment instructions in the README.md of the `oft-aptos-move` example for deploying to Move-VM and configuring the Move-VM → Solana pathway. -#### Configuration Requirements for Solana → Aptos +#### Configuration Steps for Solana → Aptos -When setting up Solana to Aptos wiring, ensure you: +:information_source: **For bidirectional Solana ↔ Aptos communication, deploy both examples:** -1. **Set the Aptos contract address**: In your `layerzero.config.ts`, manually specify the `address` field for your Aptos contract: +- **Solana → Aptos**: Use this example +- **Aptos → Solana**: Use the [OFT Aptos Move example](https://github.com/LayerZero-Labs/devtools/tree/main/examples/oft-aptos-move) -```typescript -const aptosContract: OmniPointHardhat = { - eid: EndpointId.APTOS_V2_TESTNET, - address: "0xYOUR_DEPLOYED_APTOS_CONTRACT_ADDRESS", // Replace with your actual Aptos contract address -}; -``` +#### Deployment Process -2. **Use manual configuration**: The simple config generator (`generateConnectionsConfig`) does not currently support Aptos pathways. You must use the regular configuration format. +1. **Create and Deploy Solana Example** -3. **Configuration resources**: - - [LayerZero Configuration Documentation](https://docs.layerzero.network/v2/developers/evm/create-lz-oapp/configuring-pathways) - - [Example Aptos Move config file](https://github.com/LayerZero-Labs/devtools/blob/main/examples/oft-aptos-move/move.layerzero.config.ts) + - Create the Solana example: `LZ_ENABLE_SOLANA_OAPP_EXAMPLE=1 npx create-lz-oapp@latest` + - Deploy to Solana following the deployment instructions in the Solana example README -:information_source: For bidirectional Solana ↔ Aptos communication, deploy both: +2. **Create and Deploy Aptos Move Example** -- Solana → Aptos: Use this example -- Aptos → Solana: Use the [OFT Aptos Move example](https://github.com/LayerZero-Labs/devtools/tree/main/examples/oft-aptos-move) + - Create the Aptos Move example: `LZ_ENABLE_EXPERIMENTAL_MOVE_VM_EXAMPLES=1 npx create-lz-oapp@latest` + - Deploy to Aptos following the deployment and initialization instructions in the Aptos example README + + Your directory structure should look like this: + + ``` + your-folder/ + ├── your-aptos-example/ + └── your-solana-example/ + ``` + +3. **Configure Solana Example** + + - Navigate to the Solana example directory + - Use the example configuration at `./docs/move.layerzero.config.ts` + - Fill out the configuration with your desired values + - Replace `./layerzero.config.ts` with the completed `move.layerzero.config.ts` file + +4. **Wire Solana to Aptos** + + Execute the following commands in the Solana example directory: + + ```bash + npx hardhat lz:oapp:solana:init-config --oapp-config move.layerzero.config.ts + ``` + + ```bash + npx hardhat lz:oapp:wire --oapp-config move.layerzero.config.ts + ``` + + If these commands succeed, you have successfully wired the Solana contract to the Aptos Move contract. + +5. **Wire Aptos to Solana** + + - Transfer the `move.layerzero.config.ts` file from the Solana example to the Aptos Move example directory + - In the Aptos Move example directory, run: + ```bash + pnpm run lz:sdk:move:wire --oapp-config move.layerzero.config.ts + ``` + + If this command succeeds, you are ready to test the bidirectional pathway. diff --git a/examples/oft-solana/docs/move.layerzero.config.ts b/examples/oft-solana/docs/move.layerzero.config.ts new file mode 100644 index 0000000000..fe8e165288 --- /dev/null +++ b/examples/oft-solana/docs/move.layerzero.config.ts @@ -0,0 +1,119 @@ +import { EndpointId } from '@layerzerolabs/lz-definitions' +import { ExecutorOptionType } from '@layerzerolabs/lz-v2-utilities' +import { OAppOmniGraphHardhat, OmniPointHardhat } from '@layerzerolabs/toolbox-hardhat' + +enum MsgType { + SEND = 1, + SEND_AND_CALL = 2, +} +const aptosContract: OmniPointHardhat = { + eid: EndpointId.APTOS_V2_TESTNET as EndpointId, + address: 'YOUR_DEPLOYED_APTOS_OFT_ADDRESS', +} +const solanaContract: OmniPointHardhat = { + eid: EndpointId.SOLANA_V2_TESTNET as EndpointId, + address: 'YOUR_DEPLOYED_SOLANA_OAPP_ADDRESS', +} + +const layerZeroDVNAptosAddress = '0x756f8ab056688d22687740f4a9aeec3b361170b28d08b719e28c4d38eed1043e' +const layerZeroDVNSolanaAddress = '4VDjp6XQaxoZf5RGwiPU9NR1EXSZn2TP4ATMmiSzLfhb' + +const config: OAppOmniGraphHardhat = { + contracts: [ + { + contract: solanaContract, + config: { + owner: 'YOUR_SOLANA_OWNER_ADDRESS', + delegate: 'YOUR_SOLANA_OWNER_ADDRESS', + }, + }, + { + contract: aptosContract, + config: { + owner: 'YOUR_APTOS_ACCOUNT_ADDRESS', + delegate: 'YOUR_APTOS_ACCOUNT_ADDRESS', + }, + }, + ], + connections: [ + { + from: aptosContract, + to: solanaContract, + config: { + enforcedOptions: [ + { + msgType: MsgType.SEND_AND_CALL, + optionType: ExecutorOptionType.LZ_RECEIVE, + gas: 5_000, + value: 0, + }, + ], + sendLibrary: '0xcc1c03aed42e2841211865758b5efe93c0dde2cb7a2a5dc6cf25a4e33ad23690', + receiveLibraryConfig: { + receiveLibrary: '0xcc1c03aed42e2841211865758b5efe93c0dde2cb7a2a5dc6cf25a4e33ad23690', + gracePeriod: BigInt(0), + }, + sendConfig: { + executorConfig: { + maxMessageSize: 10_000, + executor: '0x93353700091200ef9fdc536ce6a86182cc7e62da25f94356be9421c6310b9585', + }, + ulnConfig: { + confirmations: BigInt(10), + requiredDVNs: [layerZeroDVNAptosAddress], + optionalDVNs: [], + optionalDVNThreshold: 0, + }, + }, + receiveConfig: { + ulnConfig: { + confirmations: BigInt(15), + requiredDVNs: [layerZeroDVNAptosAddress], + optionalDVNs: [], + optionalDVNThreshold: 0, + }, + }, + }, + }, + { + from: solanaContract, + to: aptosContract, + config: { + enforcedOptions: [ + { + msgType: 1, + optionType: ExecutorOptionType.LZ_RECEIVE, + gas: 200_000, + value: 0, + }, + ], + sendLibrary: '7a4WjyR8VZ7yZz5XJAKm39BUGn5iT9CKcv2pmG9tdXVH', + receiveLibraryConfig: { + receiveLibrary: '7a4WjyR8VZ7yZz5XJAKm39BUGn5iT9CKcv2pmG9tdXVH', + gracePeriod: BigInt(0), + }, + sendConfig: { + executorConfig: { + maxMessageSize: 10_000, + executor: 'AwrbHeCyniXaQhiJZkLhgWdUCteeWSGaSN1sTfLiY7xK', + }, + ulnConfig: { + confirmations: BigInt(15), + requiredDVNs: [layerZeroDVNSolanaAddress], + optionalDVNs: [], + optionalDVNThreshold: 0, + }, + }, + receiveConfig: { + ulnConfig: { + confirmations: BigInt(10), + requiredDVNs: [layerZeroDVNSolanaAddress], + optionalDVNs: [], + optionalDVNThreshold: 0, + }, + }, + }, + }, + ], +} +export default config From 3385d4a3fb37019ce96694af810696e8be65d077 Mon Sep 17 00:00:00 2001 From: alexanderliteplo Date: Thu, 3 Jul 2025 10:20:32 -0700 Subject: [PATCH 2/5] Making insturctions more clear for wiring solana to aptos --- examples/oapp-solana/docs/move.layerzero.config.ts | 2 ++ examples/oapp-solana/docs/{Aptos.md => wiring-to-aptos.md} | 0 examples/oft-solana/docs/move.layerzero.config.ts | 2 ++ examples/oft-solana/docs/{Aptos.md => wiring-to-aptos.md} | 0 4 files changed, 4 insertions(+) rename examples/oapp-solana/docs/{Aptos.md => wiring-to-aptos.md} (100%) rename examples/oft-solana/docs/{Aptos.md => wiring-to-aptos.md} (100%) diff --git a/examples/oapp-solana/docs/move.layerzero.config.ts b/examples/oapp-solana/docs/move.layerzero.config.ts index 89a2960abc..11d6a0b953 100644 --- a/examples/oapp-solana/docs/move.layerzero.config.ts +++ b/examples/oapp-solana/docs/move.layerzero.config.ts @@ -1,3 +1,5 @@ +// NOTE: This config is an example for wiring Solana -> Aptos. +// See wiring-to-aptos.md for more information. import { EndpointId } from '@layerzerolabs/lz-definitions' import { ExecutorOptionType } from '@layerzerolabs/lz-v2-utilities' import { OAppOmniGraphHardhat, OmniPointHardhat } from '@layerzerolabs/toolbox-hardhat' diff --git a/examples/oapp-solana/docs/Aptos.md b/examples/oapp-solana/docs/wiring-to-aptos.md similarity index 100% rename from examples/oapp-solana/docs/Aptos.md rename to examples/oapp-solana/docs/wiring-to-aptos.md diff --git a/examples/oft-solana/docs/move.layerzero.config.ts b/examples/oft-solana/docs/move.layerzero.config.ts index fe8e165288..ac5091bb12 100644 --- a/examples/oft-solana/docs/move.layerzero.config.ts +++ b/examples/oft-solana/docs/move.layerzero.config.ts @@ -1,3 +1,5 @@ +// NOTE: This config is an example for wiring Solana -> Aptos. +// See wiring-to-aptos.md for more information. import { EndpointId } from '@layerzerolabs/lz-definitions' import { ExecutorOptionType } from '@layerzerolabs/lz-v2-utilities' import { OAppOmniGraphHardhat, OmniPointHardhat } from '@layerzerolabs/toolbox-hardhat' diff --git a/examples/oft-solana/docs/Aptos.md b/examples/oft-solana/docs/wiring-to-aptos.md similarity index 100% rename from examples/oft-solana/docs/Aptos.md rename to examples/oft-solana/docs/wiring-to-aptos.md From c60852b49858e466fc21446dc4accf3dc4a737ce Mon Sep 17 00:00:00 2001 From: alexanderliteplo Date: Thu, 3 Jul 2025 10:29:39 -0700 Subject: [PATCH 3/5] Update aptos-move-send.ts for improved message handling and configuration - Set OApp address for Aptos and updated destination chain endpoint ID to Solana. - Enhanced message preparation logic to handle different network types, specifically for Solana. - Added length encoding for messages sent to Solana to ensure proper formatting. --- .../scripts/aptos-move-send.ts | 27 +++++++++++++++---- 1 file changed, 22 insertions(+), 5 deletions(-) diff --git a/examples/oapp-aptos-move/scripts/aptos-move-send.ts b/examples/oapp-aptos-move/scripts/aptos-move-send.ts index 6b32d8480e..fd27a77739 100644 --- a/examples/oapp-aptos-move/scripts/aptos-move-send.ts +++ b/examples/oapp-aptos-move/scripts/aptos-move-send.ts @@ -23,7 +23,7 @@ import { } from '@aptos-labs/ts-sdk' import * as dotenv from 'dotenv' -import { EndpointId } from '@layerzerolabs/lz-definitions' +import { Chain, EndpointId, getNetworkForChainId } from '@layerzerolabs/lz-definitions' import { Options } from '@layerzerolabs/lz-v2-utilities' // Load environment variables from .env file @@ -60,10 +60,27 @@ 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) - const messageArray = new Uint8Array(messageBytes) + let messageArray: Uint8Array + if (getNetworkForChainId(REMOTE_EID).chainName === Chain.SOLANA) { + const message = 'Hello, Solana!' + const messageBytes = new TextEncoder().encode(message) + + // Create 32-byte length encoding (equivalent to abi.encode(uint256)) + const lengthBytes = new Uint8Array(32) + const lengthView = new DataView(lengthBytes.buffer) + lengthView.setBigUint64(24, BigInt(messageBytes.length), false) + + // Concatenate length and message bytes (equivalent to abi.encodePacked) + messageArray = new Uint8Array(lengthBytes.length + messageBytes.length) + messageArray.set(lengthBytes, 0) + messageArray.set(messageBytes, lengthBytes.length) + } else { + const message = 'Hello, EVM!' + const messageBytes = new TextEncoder().encode(message) + messageArray = new Uint8Array(messageBytes) + } + + // The Following is the code required for packaing a string message to be sent to Solana: // Get fee quote for the cross-chain message const quote = await aptos.view({ From 89bde3d5b690d24d7afb82289be65db9443f3e7b Mon Sep 17 00:00:00 2001 From: alexanderliteplo Date: Fri, 4 Jul 2025 10:21:40 -0700 Subject: [PATCH 4/5] Refactor aptos-move-send.ts and update README.md for clarity and configuration - Updated OApp address and changed destination chain endpoint ID to Solana in aptos-move-send.ts. - Simplified message preparation logic for Solana using ethers.js for better readability and efficiency. - Enhanced README.md to clarify instructions for wiring Move-VM OFT to Solana, including updated code snippets. --- .../oapp-aptos-move/scripts/aptos-move-send.ts | 16 ++++++---------- examples/oft-aptos-move/README.md | 13 ++++++++----- 2 files changed, 14 insertions(+), 15 deletions(-) diff --git a/examples/oapp-aptos-move/scripts/aptos-move-send.ts b/examples/oapp-aptos-move/scripts/aptos-move-send.ts index fd27a77739..8bcde20b95 100644 --- a/examples/oapp-aptos-move/scripts/aptos-move-send.ts +++ b/examples/oapp-aptos-move/scripts/aptos-move-send.ts @@ -63,17 +63,13 @@ async function send() { let messageArray: Uint8Array if (getNetworkForChainId(REMOTE_EID).chainName === Chain.SOLANA) { const message = 'Hello, Solana!' - const messageBytes = new TextEncoder().encode(message) - - // Create 32-byte length encoding (equivalent to abi.encode(uint256)) - const lengthBytes = new Uint8Array(32) - const lengthView = new DataView(lengthBytes.buffer) - lengthView.setBigUint64(24, BigInt(messageBytes.length), false) - // Concatenate length and message bytes (equivalent to abi.encodePacked) - messageArray = new Uint8Array(lengthBytes.length + messageBytes.length) - messageArray.set(lengthBytes, 0) - messageArray.set(messageBytes, lengthBytes.length) + const messageHex = ethers.utils.solidityPack( + ['uint256', 'bytes'], + [ethers.utils.toUtf8Bytes(message).length, ethers.utils.toUtf8Bytes(message)] + ) + // Convert hex string to Uint8Array + messageArray = ethers.utils.arrayify(messageHex) } else { const message = 'Hello, EVM!' const messageBytes = new TextEncoder().encode(message) diff --git a/examples/oft-aptos-move/README.md b/examples/oft-aptos-move/README.md index 6521104217..a6c9c0e320 100644 --- a/examples/oft-aptos-move/README.md +++ b/examples/oft-aptos-move/README.md @@ -206,14 +206,17 @@ Ensure that in move.layerzero.config.ts, all of your evm contracts have the owne ] ``` -If you are wiring solana to move-vm, create a file in `deployments/solana-mainnet/MyOFT.json` (solana-testnet if you are using testnet) and add the following field: +If you are wiring your Move-VM OFT to Solana, in your config add: -```json -{ - "address": -} +```ts +const solanaContract: OmniPointHardhat = { + eid: EndpointId.SOLANA_V2_TESTNET as EndpointId, + address: "YOUR_SOLANA_OFT_STORE_ADDRESS", +}; ``` +Note: Solana OFT can only be deployed from the Solana example. + ### To wire from EVM to Move-VM: ```bash From d03f7b0111c9628ca47132d33641f2abd42ae825 Mon Sep 17 00:00:00 2001 From: alexanderliteplo Date: Fri, 4 Jul 2025 10:33:13 -0700 Subject: [PATCH 5/5] small fix --- examples/oapp-aptos-move/scripts/aptos-move-send.ts | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/examples/oapp-aptos-move/scripts/aptos-move-send.ts b/examples/oapp-aptos-move/scripts/aptos-move-send.ts index 8bcde20b95..e4dbcc2bab 100644 --- a/examples/oapp-aptos-move/scripts/aptos-move-send.ts +++ b/examples/oapp-aptos-move/scripts/aptos-move-send.ts @@ -22,6 +22,7 @@ import { SimpleTransaction, } from '@aptos-labs/ts-sdk' import * as dotenv from 'dotenv' +import { ethers } from 'ethers' import { Chain, EndpointId, getNetworkForChainId } from '@layerzerolabs/lz-definitions' import { Options } from '@layerzerolabs/lz-v2-utilities' @@ -39,8 +40,8 @@ const APTOS_PRIVATE_KEY = process.env.APTOS_PRIVATE_KEY const ACCOUNT_ADDRESS = process.env.APTOS_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 = '0x' // Set your OApp's address on Aptos +const REMOTE_EID = EndpointId.SOLANA_V2_TESTNET // Destination chain endpoint ID const NETWORK = Network.TESTNET // Aptos network configuration // Initialize Aptos account and client @@ -76,7 +77,7 @@ async function send() { messageArray = new Uint8Array(messageBytes) } - // The Following is the code required for packaing a string message to be sent to Solana: + // The Following is the code required for packaging a string message to be sent to Solana: // Get fee quote for the cross-chain message const quote = await aptos.view({