@solayer-labs/bridge-sdk
v0.2.7
Published
TypeScript SDK for the Bridge Program
Readme
Bridge SDK
A TypeScript SDK for interacting with the Solayer Bridge Program, enabling cross-chain asset transfers between Solana and Solayer networks.
Features
- 🔗 Cross-chain bridging between Solana and Solayer
- 🪙 SPL Token support for bridging any SPL tokens
- 💰 Native SOL bridging support
- 🔍 Bridge proof tracking and verification
- 🛡️ Guardian signature verification for security
- 📊 Token binding mapping between chains with automatic tokenInfo inclusion
- 🚀 Easy-to-use client interface
- 🛠️ Robust error handling and validation
- 📋 Transaction creation helpers for custom workflows
Installation
npm install @solayer-labs/bridge-sdk
# or
yarn add @solayer-labs/bridge-sdkQuick Start
Basic Setup
import { BridgeClient, Chain } from "@solayer-labs/bridge-sdk";
import { Connection, Keypair } from "@solana/web3.js";
import * as anchor from "@coral-xyz/anchor";
// Initialize connections
const solanaConnection = new Connection("https://api.devnet.solana.com");
const solayerConnection = new Connection("https://rpc.devnet.solayer.com");
// Create user keypair
const userKeypair = Keypair.generate();
const bridgeClient = new BridgeClient({
connection: solanaConnection,
userPublicKey: userKeypair.publicKey,
chain: Chain.Solana,
commitment: "confirmed",
});Bridge SPL Tokens
import { BridgeAssetSourceChainParams } from "@solayer-labs/bridge-sdk";
import { PublicKey } from "@solana/web3.js";
import * as anchor from "@coral-xyz/anchor";
// Bridge parameters
const params: BridgeAssetSourceChainParams = {
bridgeProofNonce: new anchor.BN(Date.now()),
amount: new anchor.BN(1000000000), // 1 token with 9 decimals
recipient: new PublicKey("recipient_public_key_here"),
additionalSolGas: new anchor.BN(0),
};
// Account information
const accounts = {
mint: new PublicKey("token_mint_address"),
signerVault: new PublicKey("your_token_account"),
};
// Create and send bridge transaction
const transaction = await bridgeClient.createBridgeAssetSourceChainTransaction(
params,
accounts
);
// You need to sign and send the transaction yourself
// const signature = await sendAndConfirmTransaction(connection, transaction, [userKeypair]);
console.log("Bridge transaction created:", transaction);
// The transaction now includes the tokenInfo field for cross-chain token mappingBridge Native SOL
import { BridgeAssetSourceChainSolParams } from "@solayer-labs/bridge-sdk";
import { PublicKey } from "@solana/web3.js";
import * as anchor from "@coral-xyz/anchor";
// Bridge SOL parameters
const params: BridgeAssetSourceChainSolParams = {
bridgeProofNonce: new anchor.BN(Date.now()),
amount: new anchor.BN(5000000), // 0.005 SOL
recipient: new PublicKey("recipient_public_key_here"),
};
// Create SOL bridge transaction
const transaction =
await bridgeClient.createBridgeAssetSourceChainSolTransaction(params);
// You need to sign and send the transaction yourself
// const signature = await sendAndConfirmTransaction(connection, transaction, [userKeypair]);
console.log("SOL bridge transaction created:", transaction);API Reference
BridgeClient
The main client class for interacting with the bridge program.
Constructor
new BridgeClient(config: BridgeClientConfig)Config Options:
connection: Solana connection instanceuserPublicKey: User's public key for transactionschain: Target chain (Solana or Solayer)programId?: Optional custom program IDcommitment?: RPC commitment level
Methods
Note: The BridgeClient only creates transactions - you need to sign and send them yourself using sendAndConfirmTransaction or similar methods.
getBridgeHandler(chain)
Fetches bridge handler account information.
Parameters:
chain: Chain enum (Solana or Solayer)
Returns: Bridge handler account data
getSourceChainBridgeProof(bridgeHandler, signer, bridgeProofNonce)
Fetches source chain bridge proof account.
Parameters:
bridgeHandler: Bridge handler PublicKeysigner: Signer PublicKeybridgeProofNonce: Bridge proof nonce
Returns: Source chain bridge proof account data
getSourceChainBridgeProofByAccount(account)
Fetches source chain bridge proof by account address.
Parameters:
account: Bridge proof account PublicKey
Returns: Source chain bridge proof account data
getDestinationChainBridgeProof(bridgeHandler, sourceTxId)
Fetches destination chain bridge proof account.
Parameters:
bridgeHandler: Bridge handler PublicKeysourceTxId: Source transaction ID
Returns: Destination chain bridge proof account data
getDestinationChainBridgeProofByAccount(account)
Fetches destination chain bridge proof by account address.
Parameters:
account: Bridge proof account PublicKey
Returns: Destination chain bridge proof account data
getBridgeHandlerVaultPDA(bridgeHandler, mint)
Gets the bridge handler vault PDA for a mint.
Parameters:
bridgeHandler: Bridge handler PublicKeymint: Token mint PublicKey
Returns: Bridge handler vault PDA
createBridgeAssetSourceChainTransaction(params, accounts)
Creates a bridge transaction without sending it, allowing for custom signing and sending. The method automatically determines the target chain mint address using the get_target_mint utility function and includes the tokenInfo field for token mapping between chains.
Parameters:
params: BridgeAssetSourceChainParamsaccounts: Object containing mint and signerVault PublicKeys
Returns: Promise
createBridgeAssetSourceChainSolTransaction(params)
Creates a SOL bridge transaction without sending it, allowing for custom signing and sending.
Parameters:
params: BridgeAssetSourceChainSolParams
Returns: Promise
Utility Functions
getBridgeHandlerPDA(chain)
Gets the Program Derived Address (PDA) for bridge handler.
Parameters:
chain: Chain enum
Returns: [PublicKey, number] tuple
getSourceChainBridgeProofPDA(bridgeHandler, signer, bridgeProofNonce)
Gets the PDA for source chain bridge proof.
Parameters:
bridgeHandler: Bridge handler PublicKeysigner: Signer PublicKeybridgeProofNonce: Bridge proof nonce
Returns: [PublicKey, number] tuple
getDestinationChainBridgeProofPDA(bridgeHandler, sourceTxId)
Gets the PDA for destination chain bridge proof.
Parameters:
bridgeHandler: Bridge handler PublicKeysourceTxId: Source transaction ID
Returns: [PublicKey, number] tuple
calculateTargetChainBridgedMintAddress(sourceMint, bridgeHandler)
Calculates the target chain bridged mint address for a source mint.
Parameters:
sourceMint: Source chain mint PublicKeybridgeHandler: Bridge handler PublicKey
Returns: Target chain bridged mint PublicKey
calculateTokenInfoAddress(mint, bridgeHandler)
Calculates the token info PDA address for a given mint.
Parameters:
mint: Token mint PublicKeybridgeHandler: Bridge handler PublicKey
Returns: Token info PDA PublicKey
is_mint_bridged_token(connection, bridgeHandler, mint)
Checks if a mint is a bridged token by verifying its owner.
Parameters:
connection: Solana connection instancebridgeHandler: Bridge handler PublicKeymint: Token mint PublicKey to check
Returns: Promise - true if the mint is a bridged token
get_target_mint(sourceChain, sourceChainConnection, bridgeHandler, sourceMint)
Gets the target chain mint address for a given source mint, handling both bridged and native tokens.
Parameters:
sourceChain: Source chain enum (Solana or Solayer)sourceChainConnection: Source chain RPC connectionbridgeHandler: Bridge handler PublicKeysourceMint: Source chain mint PublicKey
Returns: Promise - Target chain mint address
getTargetChainBridgeTxIdFromSourceTxId(sourceTxId, sourceChain, targetChainConnection)
Gets target chain bridge transaction ID from source transaction ID.
Parameters:
sourceTxId: Source transaction IDsourceChain: Source chain enumtargetChainConnection: Target chain RPC connection
Returns: Promise<string | null>
getSourceChainBridgeTxIdFromTargetChainBridgeProof(bridgeProofKey, targetChainConnection)
Gets source chain bridge transaction ID from target chain bridge proof.
Parameters:
bridgeProofKey: Target chain bridge proof PublicKeytargetChainConnection: Target chain RPC connection
Returns: Promise<string | null>
getUserBridgeTx(connection, user, bridgeHandler)
Gets all bridge transactions for a specific user.
Parameters:
connection: RPC connectionuser: User PublicKeybridgeHandler: Bridge handler PublicKey
Returns: Promise
Types
BridgeAssetSourceChainParams
interface BridgeAssetSourceChainParams {
bridgeProofNonce: anchor.BN;
amount: anchor.BN;
recipient: PublicKey;
additionalSolGas: anchor.BN;
}BridgeAssetSourceChainSolParams
interface BridgeAssetSourceChainSolParams {
bridgeProofNonce: anchor.BN;
amount: anchor.BN;
recipient: PublicKey;
}BridgeClientConfig
interface BridgeClientConfig {
connection: Connection;
userPublicKey: PublicKey;
chain: Chain;
programId?: PublicKey;
commitment?: anchor.web3.Commitment;
}UserBridgeTx
interface UserBridgeTx {
sourceChainBridgeTx: string[];
targetChainBridgeTx: string[];
}Chain Enum
enum Chain {
Solana = 1,
Solayer = 2,
}Exported Types
These types are exported from the SDK and represent the program account structures:
export type BridgeHandler = BridgeProgram["accounts"][0];
export type BridgeProof = BridgeProgram["accounts"][1];
export type BridgeProofSourceChain = BridgeProgram["accounts"][2];
export type TokenInfo = BridgeProgram["types"][0];BridgeHandler: Bridge handler account structureBridgeProof: Bridge proof account structure for destination chainBridgeProofSourceChain: Bridge proof account structure for source chainTokenInfo: Token information structure containing mint addresses and status (automatically included in bridge transactions)
Examples
Complete Bridge Workflow
import {
BridgeClient,
Chain,
BridgeAssetSourceChainParams,
getBridgeHandlerPDA,
} from "@solayer-labs/bridge-sdk";
import {
Connection,
Keypair,
PublicKey,
sendAndConfirmTransaction,
} from "@solana/web3.js";
import * as anchor from "@coral-xyz/anchor";
async function bridgeTokens() {
// Setup connections
const solanaConnection = new Connection("https://api.devnet.solana.com");
// Initialize client
const userKeypair = Keypair.generate();
const bridgeClient = new BridgeClient({
connection: solanaConnection,
userPublicKey: userKeypair.publicKey,
chain: Chain.Solana,
commitment: "confirmed",
});
// Bridge parameters
const params: BridgeAssetSourceChainParams = {
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
);
// The transaction now includes tokenInfo for cross-chain token mapping
// Sign and send transaction (you need to implement this)
const signature = await sendAndConfirmTransaction(
solanaConnection,
transaction,
[userKeypair]
);
console.log("Bridge successful:", signature);
// Get bridge proof
const [bridgeHandler] = getBridgeHandlerPDA(Chain.Solana);
const bridgeProof = await bridgeClient.getSourceChainBridgeProof(
bridgeHandler,
userKeypair.publicKey,
params.bridgeProofNonce
);
console.log("Bridge proof:", bridgeProof);
} catch (error) {
console.error("Bridge failed:", error);
}
}SOL Bridge Workflow
import {
BridgeClient,
Chain,
BridgeAssetSourceChainSolParams,
} from "@solayer-labs/bridge-sdk";
import {
Connection,
Keypair,
PublicKey,
sendAndConfirmTransaction,
} from "@solana/web3.js";
import * as anchor from "@coral-xyz/anchor";
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: BridgeAssetSourceChainSolParams = {
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);
// Sign and send transaction (you need to implement this)
const signature = await sendAndConfirmTransaction(
new Connection("https://api.devnet.solana.com"),
transaction,
[userKeypair]
);
console.log("SOL bridge initiated:", signature);
} catch (error) {
console.error("SOL bridge failed:", error);
}
}Track Bridge Status
import {
getTargetChainBridgeTxIdFromSourceTxId,
Chain,
} from "@solayer-labs/bridge-sdk";
import { Connection } from "@solana/web3.js";
async function trackBridgeStatus(sourceTxId: string) {
const solayerConnection = new Connection("https://rpc.devnet.solayer.com");
// Get target chain transaction ID
const targetTxId = await getTargetChainBridgeTxIdFromSourceTxId(
sourceTxId,
Chain.Solana,
solayerConnection
);
if (targetTxId) {
console.log("Bridge completed on target chain:", targetTxId);
} else {
console.log("Bridge still pending on target chain");
}
}Get User Bridge Transactions
import {
getUserBridgeTx,
getBridgeHandlerPDA,
Chain,
} from "@solayer-labs/bridge-sdk";
import { Connection, PublicKey } from "@solana/web3.js";
async function getUserTransactions() {
const connection = new Connection("https://api.devnet.solana.com");
const user = new PublicKey("user_public_key");
const [bridgeHandler] = getBridgeHandlerPDA(Chain.Solana);
const userTxs = await getUserBridgeTx(connection, user, bridgeHandler);
console.log("Source chain transactions:", userTxs.sourceChainBridgeTx);
console.log("Target chain transactions:", userTxs.targetChainBridgeTx);
}Create Custom Bridge Transaction
import {
BridgeClient,
Chain,
BridgeAssetSourceChainParams,
} from "@solayer-labs/bridge-sdk";
import {
Connection,
Keypair,
PublicKey,
sendAndConfirmTransaction,
} from "@solana/web3.js";
import * as anchor from "@coral-xyz/anchor";
async function createCustomBridgeTransaction() {
const connection = new Connection("https://api.devnet.solana.com");
const userKeypair = Keypair.generate();
const bridgeClient = new BridgeClient({
connection,
userPublicKey: userKeypair.publicKey,
chain: Chain.Solana,
});
const params: BridgeAssetSourceChainParams = {
bridgeProofNonce: new anchor.BN(Date.now()),
amount: new anchor.BN(1000000000),
recipient: new PublicKey("recipient_address"),
additionalSolGas: new anchor.BN(0),
};
const accounts = {
mint: new PublicKey("token_mint"),
signerVault: new PublicKey("your_token_account"),
};
// Create transaction without sending
const transaction =
await bridgeClient.createBridgeAssetSourceChainTransaction(
params,
accounts
);
// The transaction now includes tokenInfo for cross-chain token mapping
// Add custom instructions if needed
// transaction.add(customInstruction);
// Sign and send manually
const signature = await sendAndConfirmTransaction(connection, transaction, [
userKeypair,
]);
console.log("Custom bridge transaction:", signature);
}Development
Building
# Install dependencies
yarn install
# Build the SDK
yarn build
# Development mode with watch
yarn devTesting
# Run tests
yarn test
# Run tests with coverage
yarn test:coverageContributing
- Fork the repository
- Create a feature branch
- Make your changes
- Add tests if applicable
- Submit a pull request
License
MIT License - see LICENSE file for details
Support
- 📖 Documentation
- 💬 Discord
- 🐛 Issues
