Skip to content

Putting It Together

Deposit on Avalanche, spend on Optimism in one binary.

use alloy_primitives::{address, U256};
use alloy_provider::network::{AnyNetwork, EthereumWallet};
use alloy_provider::{DynProvider, ProviderBuilder};
use alloy_signer_local::PrivateKeySigner;
use tonic::transport::Endpoint;
use trident_sdk::{SpendRequestBuilder, TridentClientBuilder};
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let signer = PrivateKeySigner::from_bytes(&your_private_key)?;
let avax_provider: DynProvider<AnyNetwork> = ProviderBuilder::default()
.with_recommended_fillers()
.wallet(EthereumWallet::new(signer.clone()))
.connect_http("https://api.avax.network/ext/bc/C/rpc".parse()?)
.erased();
let op_provider: DynProvider<AnyNetwork> = ProviderBuilder::default()
.with_recommended_fillers()
.wallet(EthereumWallet::new(signer.clone()))
.connect_http("https://mainnet.optimism.io".parse()?)
.erased();
let mut client = TridentClientBuilder::new(
Endpoint::from_static("http://your-attester:9000"),
)
.with_evm_chain(1, avax_provider, signer.clone()) // Avalanche
.with_evm_chain(2, op_provider, signer.clone()) // Optimism
.connect()
.await?;
// 1. Deposit on Avalanche
let avax_token = address!("..."); // Token on Avalanche
let amount = U256::from(1_000_000_000_000_000u64); // 0.001 in 18-decimal
let deposit_receipt = client.deposit(1, avax_token, amount).await?;
println!("Deposited: {:?}", deposit_receipt.transaction_hash);
// 2. Wait for attester finalization (poll balances or wait for block finality)
// 3. Spend on Optimism
let op_token = address!("..."); // Same asset on Optimism
let recipient = address!("...");
let request = SpendRequestBuilder::new(
1, avax_token, // source: Avalanche
2, op_token, // destination: Optimism
recipient, amount,
);
let attestation = client.spend(request).await?;
let spend_receipt = attestation.execute().await?;
println!("Spent: {:?}", spend_receipt.transaction_hash);
Ok(())
}

Build an Alloy provider for each chain you plan to interact with, each bound to your signer.

TridentClientBuilder takes the attester endpoint and registers each chain’s provider and signer by domain ID. On connect(), deployment metadata (contract addresses per domain) is fetched automatically.

Call client.deposit(domain, token, amount) on the source chain. The SDK handles ERC-20 approval if needed.

After the deposit transaction confirms, the attester must observe and finalize the block before the balance is spendable. Finalization time depends on the source chain.

Build a SpendRequestBuilder with source/destination domains, tokens, recipient, and amount. The SDK submits it to the attester, gets a signed attestation, and execute() submits it on the destination chain.