On this page
TypeScript SDK
@omnisea/sdk handles OFT quotes, exact-amount approvals and transaction simulation. You supply the source-chain RPC and wallet; the SDK reads the contracts directly. No Omnisea API key or React provider is required.
Release status: version 0.1.0 is available in the repository's sdk directory, ahead of public npm publication. The homepage SDK examples use this package. Use the local package instructions below until it is published.
Install
In the repository's sdk directory:
npm ci
npm run check
npm packInstall the generated tarball in your application:
npm install /path/to/omnisea-sdk-0.1.0.tgz viem@^2.56.9After public release, use npm install @omnisea/sdk viem@^2.56.9. The package is ESM, MIT-licensed and has viem as its only runtime peer dependency. Tooling requires Node.js 20.19 or later.
Set up your clients
import { createPublicClient, createWalletClient, custom, http } from "viem";
import { mainnet } from "viem/chains";
import { createOmnisea } from "@omnisea/sdk";
// rpcUrl is your source RPC; provider is your connected EIP-1193 wallet provider.
const publicClient = createPublicClient({ chain: mainnet, transport: http(rpcUrl) });
const walletClient = createWalletClient({ chain: mainnet, transport: custom(provider) });
const omnisea = createOmnisea({ publicClient, walletClient });The wallet and RPC must be on the same source chain. The SDK uses the selected wallet account and does not open a connection popup or switch networks. Recreate the clients and prepare a fresh quote after a wallet or chain change.
Read-only integrations may omit walletClient. To prepare a transfer without a wallet, supply account: senderAddress; signing still requires a wallet client, and the sender must have sufficient token balance to prepare.
Send an OFT
const transfer = await omnisea.prepareTransfer({
oft: sourceOftAddress,
toChain: 8453,
amount: "100",
});
// Display the receipt and native fee before asking for a signature.
console.log(transfer.formattedReceived, transfer.nativeFee);
if (transfer.approvalRequired) await transfer.approve();
const hash = await transfer.send();
await omnisea.waitForReceipt(hash);sourceOftAddress must be this issuer's deployed OFT or OFTAdapter on the source chain, not the original ERC-20. toChain is an EVM chain ID, not a LayerZero endpoint ID. The recipient defaults to the sender; add recipient to choose another EVM address.
String amounts are token units. Bigints are raw source-chain local units. Extra decimal precision is rejected rather than rounded. The SDK handles shared-decimal conversion through quoteOFT and rejects a zero receipt.
Preparation never signs. If approval is required, approve() grants the exact amount to the adapter and waits for a successful receipt. An existing insufficient allowance is reset to zero first, which requires two confirmations. Approval and send gas are additional source-chain costs.
send() calls the standard OFT send interface. It does not introduce a different bridging contract. You can keep using the direct viem integration or Solidity interface alongside the SDK.
Quote bounds
By default, the quoted amount received is the minimum and the quoted native fee is the maximum. send() requotes before simulation and rejects a worse quote. To accept a different bound explicitly:
const transfer = await omnisea.prepareTransfer({
oft: sourceOftAddress,
toChain: 8453,
amount: "100",
minReceived: minimumRawAmount,
maxNativeFee: maximumNativeWei,
});minReceived must be positive. nativeFee is the contract's native quote, excluding source transaction gas. The SDK pays the fresh quote, not your whole maximum. It checks current balances and allowances before sending; the transaction can still revert if contract state changes after simulation.
A prepared send is single-use once submission starts. If the wallet or RPC reports an ambiguous failure, inspect the wallet/explorer before preparing again. Never automatically retry a transfer that might already have been submitted.
Track delivery
waitForReceipt() checks a successful source receipt. It does not wait for destination delivery. Decode OFTSent with oftAbi from @omnisea/sdk/abi for the GUID, then follow the tracking guide. Destination execution may still require retry or recovery.
Optional extraOptions and composeMsg are forwarded unchanged. Choose and test the destination gas budget yourself; the SDK does not automatically configure a composer. See Transfer and deposit.
Choose the issuer's asset
const asset = await omnisea.getAsset({ token: originalToken, issuer });
console.log(asset.assetId, asset.token, asset.destinations);Use this lookup on the original token's chain. On another chain, look up { assetId } or { oft: sourceOftAddress }. A token can have multiple independent issuers: the SDK never picks one for you. See asset identity.
destinations[].enabled reports source-router enablement and peer state. It is not proof that the destination is ready or that a transfer will arrive successfully. creator and originToken are returned in the protocol's bytes32 format.
Create an asset
// No issuer compliance contract; cannot be added later.
const hash = await omnisea.createAsset({ token: originalToken });
await omnisea.waitForReceipt(hash);
const asset = await omnisea.getAsset({ token: originalToken, issuer });Use the intended issuer wallet on the origin chain. The signing account becomes the permanent issuer. Pass compliance: policyAddress at creation if the asset needs an issuer compliance contract; you cannot add one later if you omit it. The original token may still have its own restrictions. Fee-on-transfer and rebasing tokens are unsupported. Read Create your Omniasset before signing.
Enable a destination
const action = await omnisea.prepareEnableChain({ assetId, toChain: 8453 });
console.log(action.nativeFee);
const hash = await action.send();
await omnisea.waitForReceipt(hash);Only the issuer can do this, from the origin chain, for a destination not already enabled. An asset with issuer compliance requires remoteCompliance: destinationPolicyAddress. The SDK quotes with OmniseaLens and checks the fee again before submission.
Wait for destination processing before treating enablement as complete. Existing remote representations may need an additional syncAsset call from the origin to receive the new enabled-chain list. This version does not automate that fan-out or inspect destination compliance bytecode. See Enable chains and manage fees.
Handle errors
import { OmniseaError } from "@omnisea/sdk";
try {
await transfer.send();
} catch (error) {
if (error instanceof OmniseaError && error.code === "QUOTE_CHANGED") {
// Show a fresh quote and ask the user to confirm its new terms.
} else {
throw error;
}
}SDK checks expose stable codes such as CHAIN_MISMATCH, WALLET_CHANGED, APPROVAL_REQUIRED, ROUTE_UNAVAILABLE and QUOTE_CHANGED. RPC failures, wallet rejections and contract reverts retain their original viem errors and causes. See Handle errors for protocol-specific recovery.
Scope and deployments
The package contains a protocol-v1 registry for Ethereum, Optimism, BNB Chain, Polygon, Robinhood Chain, Base and Arbitrum. Unsupported chains are rejected. Adding a deployment requires a reviewed package release; no environment variables are used for addresses.
Import the snapshot from @omnisea/sdk/deployments and selected routerAbi, oftAbi, lensAbi from @omnisea/sdk/abi. The SDK supports EVM clients and native fee payment. It does not store keys, run an indexer, configure React, send recovery transactions or administer fees. Those actions remain available through the documented contracts.