LayerZero Solana SDK
Package
Use the @layerzerolabs/lz-solana-sdk-v2
package to interact with the LayerZero Endpoint program on Solana from TypeScript/JavaScript.
Interacting with the Endpoint
Note that the SDK makes use of Umi
in place of @solana/web3.js
Create an endpoint
instance:
import {TransactionBuilder, publicKey as umiPublicKey} from '@metaplex-foundation/umi';
import {EndpointProgram} from '@layerzerolabs/lz-solana-sdk-v2/umi';
const endpoint = new EndpointProgram.Endpoint(EndpointProgram.ENDPOINT_PROGRAM_ID);
Note: If the payload account is missing in some flows, call endpoint.initVerify(umiWalletSigner, { srcEid, sender, receiver, nonce })
before skip
or clear
.
Skip a message
endpoint.skip(umiWalletSigner, { sender, receiver, srcEid, nonce })
- When to use: Bypass a stuck inbound message at a future nonce to unblock subsequent processing.
- Preconditions:
nonce > inboundNonce
nonce <= inboundNonce + 256
(sliding window)- If the payload account is missing, call
initVerify
first - Caller is the authorized delegate
const skipIxn = endpoint.skip(umiWalletSigner, {
sender: senderBytes32, // bytes32 normalized sender
receiver: umiPublicKey('<RECEIVER_OAPP>'),
srcEid: <SRC_EID>,
nonce: BigInt(<NONCE>),
})
await new TransactionBuilder([skipIxn]).sendAndConfirm(umi)
Example usage: https://github.com/LayerZero-Labs/devtools/blob/main/examples/oft-solana/tasks/solana/endpoint/skip.ts
Nilify a nonce
endpoint.oAppNilify(umiWalletSigner, { nonce, receiver, sender, srcEid, payloadHash })
- When to use: Invalidate a verified payload by setting its payload hash to NIL without deleting the account.
- Preconditions:
- Provide the exact
payloadHash
(must match on-chain) - Typically after verification; does not create the payload account
- Caller is the authorized delegate
- Provide the exact
const nilifyIxn = endpoint.oAppNilify(umiWalletSigner, {
nonce: BigInt(<NONCE>),
receiver: umiPublicKey('<RECEIVER_OAPP>'),
sender: senderBytes32,
srcEid: <SRC_EID>,
payloadHash: payloadHashBytes32,
})
await new TransactionBuilder([nilifyIxn]).sendAndConfirm(umi)
Example usage: https://github.com/LayerZero-Labs/devtools/blob/main/examples/oft-solana/tasks/solana/endpoint/nilify.ts
Burn a nonce
endpoint.oAppBurnNonce(umiWalletSigner, { nonce, receiver, sender, srcEid, payloadHash })
- When to use: Delete the payload hash account for an older nonce after inbound processing has advanced beyond it (state cleanup).
- Preconditions:
nonce < inboundNonce
- Provide the exact
payloadHash
(must match on-chain) - Caller is the authorized delegate
const burnIxn = endpoint.oAppBurnNonce(umiWalletSigner, {
nonce: BigInt(<NONCE>),
receiver: umiPublicKey('<RECEIVER_OAPP>'),
sender: senderBytes32,
srcEid: <SRC_EID>,
payloadHash: payloadHashBytes32,
})
await new TransactionBuilder([burnIxn]).sendAndConfirm(umi)
Example usage: https://github.com/LayerZero-Labs/devtools/blob/main/examples/oft-solana/tasks/solana/endpoint/burn.ts
Clear a payload
Note that clear
does not make use of the endpoint
class, but instead requires usage of EndpointProgram.instruction
.
EndpointProgram.instructions.clear({ programs }, { accounts }, { args })
- When to use: Finalize/ack a payload for a nonce that has already been verified; clean up state for a known payload.
- Preconditions:
nonce <= inboundNonce
- Provide
payloadHash
ORguid + message
(to derive the hash) - If payload account is missing, call
initVerify
first - Caller is the authorized delegate
// Derive PDAs
const [endpointPda] = endpoint.pda.setting()
const [noncePda] = endpoint.pda.nonce(umiPublicKey('<RECEIVER_OAPP>'), <SRC_EID>, senderBytes32)
const [oappRegistryPda] = endpoint.pda.oappRegistry(umiPublicKey('<RECEIVER_OAPP>'))
const [payloadHashPda] = endpoint.pda.payloadHash(umiPublicKey('<RECEIVER_OAPP>'), <SRC_EID>, senderBytes32, Number(<NONCE>))
const clearIxn = EndpointProgram.instructions.clear(
{ programs: endpoint.programRepo },
{
signer: umiWalletSigner,
oappRegistry: oappRegistryPda,
nonce: noncePda,
payloadHash: payloadHashPda,
endpoint: endpointPda,
eventAuthority: endpoint.eventAuthority,
program: endpoint.programId,
},
{
receiver: umiPublicKey('<RECEIVER_OAPP>'),
srcEid: <SRC_EID>,
sender: senderBytes32,
nonce: BigInt(<NONCE>),
guid: guidBytes32,
message: messageBytes,
}
).items[0]
await new TransactionBuilder([clearIxn]).sendAndConfirm(umi)
Example usage: https://github.com/LayerZero-Labs/devtools/blob/main/examples/oft-solana/tasks/solana/endpoint/clear.ts