Getting Started
Install the SDK, construct a client, and get your first quote.
This page gets a Quote back from a real testnet RPC endpoint, in the shortest sequence of real
API calls that actually works. It intentionally stops at quote() — building, signing, and
tracking a full transfer is the end-to-end walkthrough's job.
Install
pnpm add @ferryline/sdkThat's the only package you need. @ferryline/sdk re-exports everything from @ferryline/core
that a normal integration touches (FerrylineError, InMemoryTransferStore, every shared type) —
you don't need to separately install or import @ferryline/core unless you're doing something
low-level with it directly (its own decimal/address utilities, for instance).
Construct a client
Ferryline itself holds no rail-specific logic — it routes a request to whichever registered
adapter can handle it. Nothing is wired up by default, so you register the rail(s) you actually
need:
import { rpc } from "@stellar/stellar-sdk";
import { Ferryline, UsdcCctpAdapter } from "@ferryline/sdk";
const stellarRpc = new rpc.Server("https://soroban-testnet.stellar.org");
const ferryline = new Ferryline({
network: "testnet",
rpcUrl: "https://soroban-testnet.stellar.org",
});
ferryline.registerAdapter(
new UsdcCctpAdapter({
network: "testnet",
stellarRpc,
store: ferryline.store,
}),
);UsdcCctpAdapter is the USDC/CCTP rail, and it's the one to reach for on testnet — USDT0's
adapter (Usdt0LayerZeroAdapter) refuses to construct on anything but "mainnet", because USDT0
has no Stellar testnet deployment at all (see Core Concepts).
Passing ferryline.store as the adapter's store means both share the same record of
in-flight transfers; Ferryline's constructor defaults it to an InMemoryTransferStore unless you
pass your own.
Get a quote
Every rail's quote() takes the same shape of request regardless of which asset or direction it
is. Amounts are plain decimal strings, never floats:
const quote = await ferryline.quote({
asset: "USDC",
from: { chain: "stellar", address: "GBBA3HN2PNOAJGR6R5VY34SQFDFTZFQIGDPYATJB34UXXFUHVR4KZRAZ" },
to: { chain: "ethereum-sepolia", address: "0x78253429b7483FBcCEf90e943526BB990a4D5b50" },
amount: "0.5",
parameters: {
// Both required, no default ships for either — see Core Concepts for why.
maxFee: "0",
minFinalityThreshold: 2000,
},
});
console.log(quote.debit, quote.credit, quote.fees, quote.expiresAt);quote.checks lists every preflight check the rail ran (address format, trustline, balance,
route limits, whether the rail is paused) with a remedy on any that failed — worth inspecting
before calling build(), since build() itself throws PREFLIGHT_FAILED if any check is still
failing.
From here, Core Concepts explains the rest of the lifecycle
(build → sign → markSubmitted → track), and the SDK Reference documents
every method, option, and error code. The end-to-end walkthrough runs
the complete sequence against a real transaction.