@omnisea/sdk
v0.1.3
Published
Small, typed viem SDK for creating and transferring Omnisea assets through the standard OFT interface.
Readme
@omnisea/sdk
Create and transfer Omnisea assets with your existing viem clients. The SDK calls the source-chain contracts directly through the standard OFT interface. It needs no Omnisea API key, React provider or hosted relayer.
Status: 0.1.3 contains the October 8 ten-chain deployment addresses, including Abstract and Arc, and is packaged locally. It has not been published to npm by this change.
Install
From this directory:
npm ci
npm run check
npm packIn your application, install the resulting tarball and viem:
npm install /path/to/omnisea-sdk-0.1.2.tgz viem@^2.56.9After the public release:
npm install @omnisea/sdk viem@^2.56.9ESM package, MIT license. Node.js 20.19+ for tooling; browser use through your bundler. viem is the only runtime peer dependency. ABI and deployment subpath exports are separate from the main API.
Configure once
import { createPublicClient, createWalletClient, custom, http } from "viem";
import { mainnet } from "viem/chains";
import { createOmnisea } from "@omnisea/sdk";
// provider is your connected EIP-1193 wallet provider; no connection popup is opened here.
const publicClient = createPublicClient({ chain: mainnet, transport: http(rpcUrl) });
const walletClient = createWalletClient({ chain: mainnet, transport: custom(provider) });
const omnisea = createOmnisea({ publicClient, walletClient });Connect the wallet before preparing a transaction. Both clients must refer to the source chain. The first selected wallet account is used by default; an explicit account may be passed, but must match the wallet's selected account when signing. Local viem accounts are also supported. Recreate the clients and prepare again after switching networks or accounts. The SDK does not connect wallets or switch chains.
For reads, omit walletClient. For read-only transfer preparation, also pass the intended sender as account; that sender must own enough tokens. approve(), send() and createAsset() require a wallet.
Transfer
const transfer = await omnisea.prepareTransfer({
oft: sourceOftAddress,
toChain: 8453,
amount: "100",
});
console.log(transfer.formattedReceived, transfer.nativeFee);
if (transfer.approvalRequired) await transfer.approve();
const hash = await transfer.send();
const receipt = await omnisea.waitForReceipt(hash);oftis this issuer's deployed source OFT or OFTAdapter, not the original ERC-20. A predicted destination address is not evidence of deployment.toChainis an EVM chain ID. Endpoint IDs are resolved internally.- A string amount is in token units; a bigint is in raw source-chain local units. Excess decimal precision is rejected, not rounded.
recipientdefaults to the sender. EVM recipients are supported in this release.- Preparation reads source state and returns a quote; it never signs.
approvalRequiredis a snapshot, refreshed after approval. Allowance is checked again before sending. - Approval is for the exact requested amount and the source adapter only. An insufficient existing allowance is first reset to zero, requiring two wallet confirmations. Successful receipts and the resulting allowance are checked. Approvals cost source gas.
minReceiveddefaults to the quoted raw receipt, after fees and shared-decimal dust removal.maxNativeFeedefaults to the quoted native fee. Set either explicitly to accept another bound. A zero minimum is not accepted.send()requotes and simulates. It rejects a receipt below your minimum or a native fee above your cap, and sends only the current quoted native fee. Source transaction gas is additional, not included innativeFee.- No signing flow is atomic across RPC calls. The contract minimum and transaction value remain the final on-chain protections. Balance, compliance or routing changes can still cause a revert.
- After submission starts, a prepared send cannot be reused, including after an ambiguous RPC failure. Check the wallet/explorer before preparing again. The SDK never automatically retries a transfer.
The source receipt is not destination completion. Decode OFTSent for the GUID, then track LayerZero delivery and Omnisea destination processing. See the tracking guide. A destination failure can require retry or recovery.
Optional extraOptions and composeMsg are forwarded unchanged. The SDK does not invent compose gas or authenticate destination composers for you; follow the compose guide.
Resolve an asset
const asset = await omnisea.getAsset({ token: originalToken, issuer });
// Or: { assetId }, or { oft: sourceOftAddress }
console.log(asset.assetId, asset.token, asset.destinations);The token/issuer lookup is for the original token on its origin chain. On remote chains, use the asset ID or deployed OFT. Each issuer has an independent asset; the SDK never chooses an issuer for a token. destinations[].enabled reflects the source router's peer and enablement state, not destination delivery readiness. creator and originToken retain their protocol bytes32 representation.
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 });The signing account becomes the permanent issuer. Use the intended issuer wallet on the original chain. To attach a policy, pass compliance: policyAddress at creation. Simulation checks the current contract rules. Omitting compliance is a permanent choice, not a promise that the original ERC-20 has no restrictions. Fee-on-transfer and rebasing assets are unsupported.
Enable a destination
const action = await omnisea.prepareEnableChain({ assetId, toChain: 8453 });
console.log(action.nativeFee);
const hash = await action.send();
await omnisea.waitForReceipt(hash);Use the issuer wallet on the origin chain for a not-yet-enabled destination. An asset with issuer compliance requires remoteCompliance for the destination. The quote comes from OmniseaLens. A source receipt confirms submission, not successful remote configuration: wait for destination processing before advertising the route. Existing remote representations may also need the origin's updated enabled-chain list propagated with syncAsset; this SDK version does not automate that fan-out. Remote policy bytecode and destination readiness must be checked by the integrator.
Errors
import { OmniseaError } from "@omnisea/sdk";
try {
await transfer.send();
} catch (error) {
if (error instanceof OmniseaError && error.code === "QUOTE_CHANGED") {
// Prepare and display a fresh quote; let the user confirm the new terms.
} else {
throw error;
}
}SDK validation errors have a stable code. Wallet rejection, RPC errors and contract reverts remain the original viem errors (including their causes); do not treat every error as an insufficient balance.
Deployment snapshot
Protocol v1: Ethereum (1), Optimism (10), BNB Chain (56), Polygon (137), Abstract (2741), Robinhood Chain (4663), Arc (5042), Base (8453), Arbitrum (42161), Ink (57073). Addresses are committed in src/deployments.ts, with no environment variables. The SDK rejects other chains. Adding a chain requires a reviewed package release, not an untrusted runtime address override.
import { deployments } from "@omnisea/sdk/deployments";
import { routerAbi, oftAbi, lensAbi } from "@omnisea/sdk/abi";These are selected ABIs for SDK actions, not every protocol admin/recovery function. The SDK uses native fee payment only, and makes no destination RPC calls. It does not include React hooks, an indexer, key storage, automatic fee administration, recovery transactions or deployment tooling.
Maintaining and publishing
- Review the registry against the release addresses and regenerate selected ABI entries when contracts change. Repository parity tests run when sibling protocol/web folders are available.
- Run
npm ci && npm run checkandnpm pack --dry-run. The allowlist publishes only built ESM/declarations, this README and the MIT license. No private configuration or repository-relative runtime imports are included. - Run
npm run test:packageto install the tarball into an isolated temporary consumer and verify exports and client types. Then test it with your application's wallet provider. - With npm access to the
@omniseaorganization, runnpm publish --access public. Follow npm's authentication requirements. Bump the package version for each subsequent release.
prepublishOnly reruns validation. Nothing in the normal test/build/pack commands publishes a package or sends a blockchain transaction. Unit tests use simulated clients and ABI encoding, not a live-wallet or mainnet smoke test.
