Documentation Index
Fetch the complete documentation index at: https://docs.solayer.org/llms.txt
Use this file to discover all available pages before exploring further.
The Bridge SDK provides a full TypeScript interface for interacting with the Solayer Bridge Program. It enables cross-chain asset transfers between Solana and Solayer networks with built-in security features and proof verification.
Installation
npm install @solayer-labs/bridge-sdk
Bridge Flow
Cross-chain transfers follow a secure five-step process:
- Source Chain: User initiates bridge transaction on source chain (Solana/Solayer)
- Proof Generation: Bridge proof is created with transaction details
- Guardian Verification: Guardians verify and sign the bridge proof
- Target Chain: Operator executes bridge on target chain using verified proof
- Asset Transfer: Assets are transferred to recipient on target chain
Key Components
- BridgeHandler: Manages bridge state and configuration
- BridgeProof: Contains bridge transaction details and verification data
- GuardianInfo: Stores guardian public keys and threshold information
- TokenInfo: Maps tokens between chains
BridgeClient
The main client class for bridge operations.
import { BridgeClient, Chain } from "@solayer-labs/bridge-sdk";
import { Connection, PublicKey } from "@solana/web3.js";
const bridgeClient = new BridgeClient({
connection: new Connection("https://api.devnet.solana.com"),
userPublicKey: new PublicKey("your_public_key_here"),
chain: Chain.Solana,
commitment: "confirmed",
});
Important Note: The BridgeClient class only provides transaction creation methods. You need to sign and send transactions yourself using sendAndConfirmTransaction or similar methods.
Query Methods
const bridgeHandler = await bridgeClient.getBridgeHandler(Chain.Solana);
Bridge Proof Queries
import * as anchor from "@coral-xyz/anchor";
import { getBridgeHandlerPDA } from "@solayer-labs/bridge-sdk";
// Get source chain bridge proof
const [bridgeHandler] = getBridgeHandlerPDA(Chain.Solana);
const bridgeProof = await bridgeClient.getSourceChainBridgeProof(
bridgeHandler,
userPublicKey,
new anchor.BN(12345)
);
// Get destination chain bridge proof
const destProof = await bridgeClient.getDestinationChainBridgeProof(
bridgeHandler,
"source_transaction_signature"
);
// Get bridge proof by account address
const proofByAccount = await bridgeClient.getSourceChainBridgeProofByAccount(
new PublicKey("bridge_proof_account_address")
);
Bridge Handler Vault PDA
const [bridgeHandler] = getBridgeHandlerPDA(Chain.Solana);
const vaultPDA = bridgeClient.getBridgeHandlerVaultPDA(
bridgeHandler,
new PublicKey("token_mint_address")
);
Transaction Builders
createBridgeAssetSourceChainTransaction
Creates bridge transaction without sending it. The method automatically determines the target chain mint address using the get_target_mint utility function.
const tx = await bridgeClient.createBridgeAssetSourceChainTransaction(
params,
accounts
);
// Customize transaction if needed
const signature = await sendAndConfirmTransaction(connection, tx, [
userKeypair,
]);
createBridgeAssetSourceChainSolTransaction
Creates SOL bridge transaction without sending it.
const tx = await bridgeClient.createBridgeAssetSourceChainSolTransaction(
params
);
// Customize transaction if needed
const signature = await sendAndConfirmTransaction(connection, tx, [
userKeypair,
]);
Utility Functions
PDA Helpers
import * as anchor from "@coral-xyz/anchor";
import {
getBridgeHandlerPDA,
getSourceChainBridgeProofPDA,
getDestinationChainBridgeProofPDA,
} from "@solayer-labs/bridge-sdk";
// Get bridge handler PDA
const [bridgeHandler, bump] = getBridgeHandlerPDA(Chain.Solana);
// Get source chain bridge proof PDA
const [bridgeProof, bump] = getSourceChainBridgeProofPDA(
bridgeHandler,
userKeypair.publicKey,
new anchor.BN(12345)
);
// Get destination chain bridge proof PDA
const [destProof, bump] = getDestinationChainBridgeProofPDA(
bridgeHandler,
"source_transaction_signature"
);
Token Utilities
import {
calculateTargetChainBridgedMintAddress,
calculateTokenInfoAddress,
is_mint_bridged_token,
get_target_mint,
Chain,
} from "@solayer-labs/bridge-sdk";
import { PublicKey } from "@solana/web3.js";
// Calculate target chain bridged mint address
const targetMint = calculateTargetChainBridgedMintAddress(
new PublicKey("source_mint_address"),
bridgeHandler
);
// Calculate token info PDA address
const tokenInfoAddress = calculateTokenInfoAddress(
new PublicKey("token_mint_address"),
bridgeHandler
);
// Check if mint is a bridged token
const isBridged = await is_mint_bridged_token(
connection,
bridgeHandler,
new PublicKey("token_mint_address")
);
// Get target chain mint address
const targetMint = await get_target_mint(
Chain.Solana,
connection,
bridgeHandler,
new PublicKey("source_mint_address")
);
Bridge Status Tracking
import {
getTargetChainBridgeTxIdFromSourceTxId,
getSourceChainBridgeTxIdFromTargetChainBridgeProof,
getUserBridgeTx,
Chain,
} from "@solayer-labs/bridge-sdk";
import { PublicKey } from "@solana/web3.js";
// Check if bridge is completed on target chain
const targetTxId = await getTargetChainBridgeTxIdFromSourceTxId(
"source_tx_signature",
Chain.Solana,
solayerConnection
);
// Get source transaction from target chain bridge proof
const sourceTxId = await getSourceChainBridgeTxIdFromTargetChainBridgeProof(
new PublicKey("bridge_proof_key"),
solayerConnection
);
// Get user's bridge transaction history
const userTxs = await getUserBridgeTx(
connection,
user.publicKey,
bridgeHandler
);
Types and Interfaces
Core Configuration Types
interface BridgeClientConfig {
connection: Connection;
userPublicKey: PublicKey;
chain: Chain;
programId?: PublicKey;
commitment?: anchor.web3.Commitment;
}
enum Chain {
Solana = 1,
Solayer = 2,
}
Bridge Parameter Types
interface BridgeAssetSourceChainParams {
bridgeProofNonce: anchor.BN;
amount: anchor.BN;
recipient: PublicKey;
additionalSolGas: anchor.BN;
}
interface BridgeAssetSourceChainSolParams {
bridgeProofNonce: anchor.BN;
amount: anchor.BN;
recipient: PublicKey;
}
interface UserBridgeTx {
sourceChainBridgeTx: string[];
targetChainBridgeTx: string[];
}
Program Account Types
export type BridgeHandler = BridgeProgram["accounts"][0];
export type BridgeProof = BridgeProgram["accounts"][1];
export type BridgeProofSourceChain = BridgeProgram["accounts"][2];
export type TokenInfo = BridgeProgram["types"][0];
Usage Examples
Complete Bridge Workflow
import {
BridgeClient,
Chain,
getBridgeHandlerPDA,
getTargetChainBridgeTxIdFromSourceTxId,
} from "@solayer-labs/bridge-sdk";
import {
Connection,
Keypair,
PublicKey,
sendAndConfirmTransaction,
} from "@solana/web3.js";
import * as anchor from "@coral-xyz/anchor";
async function completeBridgeWorkflow() {
const connection = new Connection("https://api.devnet.solana.com");
const userKeypair = Keypair.generate();
const bridgeClient = new BridgeClient({
connection,
userPublicKey: userKeypair.publicKey,
chain: Chain.Solana,
commitment: "confirmed",
});
// Bridge parameters
const params = {
bridgeProofNonce: new anchor.BN(Date.now()),
amount: new anchor.BN(1000000000), // 1 token
recipient: new PublicKey("recipient_address"),
additionalSolGas: new anchor.BN(0),
};
const accounts = {
mint: new PublicKey("token_mint"),
signerVault: new PublicKey("your_token_account"),
};
try {
// Create bridge transaction
const transaction =
await bridgeClient.createBridgeAssetSourceChainTransaction(
params,
accounts
);
// Sign and send transaction
const signature = await sendAndConfirmTransaction(connection, transaction, [
userKeypair,
]);
console.log("Bridge initiated:", signature);
// Track bridge completion
const targetTxId = await getTargetChainBridgeTxIdFromSourceTxId(
signature,
Chain.Solana,
new Connection("https://rpc.devnet.solayer.com")
);
if (targetTxId) {
console.log("Bridge completed on target chain:", targetTxId);
}
} catch (error) {
console.error("Bridge failed:", error);
}
}
SOL Bridge Workflow
async function bridgeSOL() {
const userKeypair = Keypair.generate();
const bridgeClient = new BridgeClient({
connection: new Connection("https://api.devnet.solana.com"),
userPublicKey: userKeypair.publicKey,
chain: Chain.Solana,
});
const params = {
bridgeProofNonce: new anchor.BN(Date.now()),
amount: new anchor.BN(5000000), // 0.005 SOL
recipient: new PublicKey("recipient_address"),
};
try {
const transaction =
await bridgeClient.createBridgeAssetSourceChainSolTransaction(params);
const signature = await sendAndConfirmTransaction(connection, transaction, [
userKeypair,
]);
console.log("SOL bridge initiated:", signature);
} catch (error) {
console.error("SOL bridge failed:", error);
}
}
Working with Bridged Tokens
import {
getBridgeHandlerPDA,
is_mint_bridged_token,
get_target_mint,
calculateTokenInfoAddress,
Chain,
} from "@solayer-labs/bridge-sdk";
import { Connection, PublicKey } from "@solana/web3.js";
async function workWithBridgedTokens() {
const connection = new Connection("https://api.devnet.solana.com");
const [bridgeHandler] = getBridgeHandlerPDA(Chain.Solana);
const sourceMint = new PublicKey("token_mint_address");
// Check if a mint is a bridged token
const isBridged = await is_mint_bridged_token(
connection,
bridgeHandler,
sourceMint
);
console.log("Is bridged token:", isBridged);
// Get the target chain mint address
const targetMint = await get_target_mint(
Chain.Solana,
connection,
bridgeHandler,
sourceMint
);
console.log("Target mint:", targetMint.toString());
// Get token info PDA address
const tokenInfoAddress = calculateTokenInfoAddress(sourceMint, bridgeHandler);
console.log("Token info PDA:", tokenInfoAddress.toString());
}
Error Handling
Common bridge errors and their meanings:
- InsufficientAmount: User doesn’t have enough tokens
- BridgePaused: Bridge is currently paused by admin
- TokenPaused: Specific token is paused for bridging
- TooMuchAdditionalSolGas: Additional SOL gas exceeds limit
- TooLittleAdditionalSolGas: Additional SOL gas below minimum
- InvalidChain: Invalid chain specified
- InvalidOperator: Invalid operator for the operation
try {
const tx = await bridgeClient.createBridgeAssetSourceChainTransaction(
params,
accounts
);
const signature = await sendAndConfirmTransaction(connection, tx, [
userKeypair,
]);
} catch (error) {
if (error.message.includes("BridgePaused")) {
console.error("Bridge is currently paused");
} else if (error.message.includes("InsufficientAmount")) {
console.error("Insufficient token balance");
} else if (error.message.includes("TokenPaused")) {
console.error("This token is paused for bridging");
}
}
Best Practices
Pre-flight Checks
// Check bridge status before initiating
const bridgeHandler = await bridgeClient.getBridgeHandler(Chain.Solana);
if (bridgeHandler.pause) {
throw new Error("Bridge is currently paused");
}
Transaction Management
// Use unique nonces
const bridgeProofNonce = new anchor.BN(Date.now() + Math.random());
// Create and confirm transactions
const tx = await bridgeClient.createBridgeAssetSourceChainTransaction(
params,
accounts
);
const signature = await sendAndConfirmTransaction(connection, tx, [
userKeypair,
]);
Progress Monitoring
import {
getTargetChainBridgeTxIdFromSourceTxId,
Chain,
} from "@solayer-labs/bridge-sdk";
// Poll for bridge completion with timeout
async function waitForBridgeCompletion(sourceTxId: string, maxAttempts = 30) {
for (let i = 0; i < maxAttempts; i++) {
const targetTxId = await getTargetChainBridgeTxIdFromSourceTxId(
sourceTxId,
Chain.Solana,
solayerConnection
);
if (targetTxId) return targetTxId;
await new Promise((resolve) => setTimeout(resolve, 2000));
}
throw new Error("Bridge timeout");
}
Parameter Validation
import { BridgeAssetSourceChainParams } from "@solayer-labs/bridge-sdk";
import * as anchor from "@coral-xyz/anchor";
// Validate bridge parameters
function validateBridgeParams(params: BridgeAssetSourceChainParams) {
if (params.amount.lte(new anchor.BN(0))) {
throw new Error("Amount must be greater than 0");
}
if (params.additionalSolGas.gt(new anchor.BN(10000000))) {
// 0.01 SOL
throw new Error("Additional SOL gas too high");
}
}