SDKs & tools
Rust SDK
The layerhop crate — an async reqwest (rustls) client with serde models, a typed error enum, a watch Stream and webhook verification.
The layerhop crate is an async client for the REST API that mirrors the TypeScript SDK. It is built on reqwest (rustls, no OpenSSL), tokio and serde.
Source: github.com/layerhop/layerhop-rust — source repository (opens at launch).
The SDK never holds keys. It returns unsigned transactions; your wallet library (alloy, solana-sdk, a KMS…) signs and broadcasts them.
Install#
cargo add layerhop
cargo add tokio --features macros,rt-multi-thread
cargo add futures-util # StreamExt for watch()Quickstart#
Amounts are integer strings in base units ("100000000" = 100 USDC).
use futures_util::StreamExt;
use layerhop::{BuiltTx, LayerHop, QuoteParams, WatchOptions};
let lh = LayerHop::builder().build(); // .api_key(..).base_url("http://localhost:8787")
// 1. Quote
let q = lh.quote(&QuoteParams {
src_chain: "base".into(), src_token: "USDC".into(), amount: "100000000".into(),
dst_chain: "solana".into(), dst_token: "SOL".into(),
sender: "0xYourEvmAddress".into(), recipient: "YourSolanaAddress".into(),
slippage_bps: None,
}).await?;
// 2. Build the unsigned transaction
let tx = lh.build_tx(&q.best.quote_id).await?;
// 3. Sign + send with YOUR wallet library
let tx_hash = match tx {
BuiltTx::Evm(evm) => sign_evm(evm).await?, // send evm.approval first when Some
BuiltTx::Svm(svm) => sign_svm(svm).await?, // submit_via_api == Some(true) → lh.submit(..)
};
// 4. Report the broadcast
lh.report_submitted(&q.best.quote_id, &tx_hash).await?;
// 5. Watch until filled / refunded / failed
let mut updates = Box::pin(lh.watch(&q.best.provider, &tx_hash, WatchOptions::default()));
while let Some(status) = updates.next().await {
println!("{}", status?.state);
}Methods#
| Method | Endpoint |
|---|---|
health() · chains() · tokens(chain) |
GET /v1/health · /v1/chains · /v1/tokens |
quote(&QuoteParams) |
GET /v1/quote |
build_tx(quote_id) |
POST /v1/orders → BuiltTx::Evm / BuiltTx::Svm |
simulate(quote_id) |
POST /v1/simulate |
submit(quote_id, signed_base64) |
POST /v1/orders/submit (Solana submit_via_api only) |
report_submitted(quote_id, tx_hash) |
POST /v1/orders/{quoteId}/submitted |
status(provider, id) |
GET /v1/orders/{provider}/{id} |
watch(provider, id, WatchOptions) |
A Stream of state changes; ends when final, yields Error::Timeout after 30 min by default |
list_orders(&ListOrdersParams) |
GET /v1/orders |
Builder options: base_url, api_key, channel, integrator, integrator_fee_bps, http_client.
Errors#
layerhop::Error::Api { code, message, status, request_id } for non-2xx responses, where code is one of the stable error codes; err.code() returns it. The other variants are Error::Http (transport), Error::Decode (unexpected body) and Error::Timeout (watch).
Webhooks#
layerhop::webhook::verify(&secret, &raw_body, signature_header)?; // 300 s toleranceThe header is t=<unix>,v1=<hex HMAC-SHA256(secret, "<t>.<raw body>")>. webhook::verify_signature takes an explicit tolerance and clock.