omni-transfer-sdk
v0.1.2
Published
TypeScript SDK for the omni-transfer cross-chain swap and bridge API
Readme
omni-transfer TypeScript SDK
Typed TypeScript client for the omni-transfer API — cross-chain swap and bridge infrastructure. Generated from the OpenAPI spec, so it always matches the live API surface.
npm install omni-transfer-sdkWorks in Node.js 20+ and modern browsers (fetch-based, ESM + CJS builds, full type declarations).
Client setup
import { createOmniTransferClient } from 'omni-transfer-sdk';
const client = createOmniTransferClient({
baseUrl: 'https://api.example.com',
apiKey: 'prefix.secret', // for swap / explorer endpoints
});Prefer a global default? Call configureOmniTransfer({ baseUrl, apiKey }) once at startup and omit client from every call.
Swap: route → sign → execute → track
1. Get quotes
import { createRoute } from 'omni-transfer-sdk';
const route = await createRoute({
client,
body: {
srcChainId: 'eip155:1', // Ethereum mainnet (CAIP-2)
dstChainId: 'eip155:8453', // Base
srcToken: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48', // USDC
dstToken: '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913', // USDC on Base
amountIn: '1000000', // 1 USDC (6 decimals)
sender: '0xYourAddress',
recipient: '0xRecipient',
},
throwOnError: true,
});
const quote = route.data.quotes!.items![0]!;quote.execution?.type tells you what to do next:
| type | What to do |
|---|---|
| evm_gasless | Sign the EIP-712 digest, call executeQuote with signature |
| evm_deposit | Broadcast the send tx, call lockDepositQuote — API auto-detects the deposit |
| solana_sponsored | Sign the base64 message, call executeQuote with signature |
| btc_psbt | Sign your inputs, call executeQuote with the signed tx as signature |
| deposit address | Lock the quote, send BTC, call executeQuote with triggerTxHash |
2. Sign & execute
EVM gasless
The relayer pays gas; you only sign a digest.
import { executeQuote, signEvmDigest } from 'omni-transfer-sdk';
const digest = quote.execution!.sign!.fields!['digest'] as string;
const signature = await signEvmDigest(digest, '0x<private-key>');
const exec = await executeQuote({
client,
body: { quoteId: quote.quoteId!, signature },
throwOnError: true,
});EVM deposit
Broadcast the transaction from your own wallet, then let auto-detection handle it or supply the hash yourself.
import { lockDepositQuote, executeQuote } from 'omni-transfer-sdk';
// 1. Lock the quote (activates the on-chain listener for 5 minutes)
await lockDepositQuote({
client,
path: { quoteId: quote.quoteId! },
throwOnError: true,
});
// 2. Broadcast from your wallet using:
// quote.execution!.send!.chainId — chain
// quote.execution!.send!.to — destination
// quote.execution!.send!.data — calldata
// quote.execution!.send!.value — value in wei
// Option A — auto-detection (recommended): the API watches for the deposit
// and starts execution automatically. No executeQuote call needed.
// Option B — supply the tx hash immediately after broadcasting:
const exec = await executeQuote({
client,
body: { quoteId: quote.quoteId!, triggerTxHash: '0x<your-tx-hash>' },
throwOnError: true,
});Solana sponsored
Fees are covered; you sign the serialized transaction message.
import { executeQuote, signSolanaMessage, solanaPrivateKeyFromBase58 } from 'omni-transfer-sdk';
const privKey = solanaPrivateKeyFromBase58('<base58-private-key>');
const message = quote.execution!.sign!.fields!['message'] as string; // base64
const signature = await signSolanaMessage(message, privKey);
const exec = await executeQuote({
client,
body: { quoteId: quote.quoteId!, signature },
throwOnError: true,
});Bitcoin PSBT
Sign your inputs with SIGHASH_SINGLE|ANYONECANPAY; the API appends the treasury leg and broadcasts.
import { executeQuote, signBtcUnsignedTx } from 'omni-transfer-sdk';
const fields = quote.execution!.sign!.fields as {
unsignedTxHex: string;
inputAmounts: number[];
inputPkScripts: string[];
};
const signature = signBtcUnsignedTx(fields, '<WIF-key>');
const exec = await executeQuote({
client,
body: { quoteId: quote.quoteId!, signature },
throwOnError: true,
});Bitcoin deposit address
Send BTC to the deposit address returned in the route response, then report the tx hash.
import { lockDepositQuote, executeQuote } from 'omni-transfer-sdk';
// 1. Lock the quote
await lockDepositQuote({
client,
path: { quoteId: quote.quoteId! },
throwOnError: true,
});
// 2. Send BTC to: route.data.depositAddress (from your wallet)
// 3. Execute with the broadcast tx hash
const exec = await executeQuote({
client,
body: { quoteId: quote.quoteId!, triggerTxHash: '<your-txid>' },
throwOnError: true,
});3. Track execution
import { getExecution } from 'omni-transfer-sdk';
// Poll until status is "completed" or "failed"
let status = await getExecution({
client,
path: { id: exec.data.executionId! },
throwOnError: true,
});
while (status.data.status !== 'completed' && status.data.status !== 'failed') {
await new Promise(r => setTimeout(r, 3000));
status = await getExecution({ client, path: { id: exec.data.executionId! }, throwOnError: true });
}
console.log('final status:', status.data.status);Get granular per-step progress (with live EVM confirmation counts):
import { getExecutionSteps } from 'omni-transfer-sdk';
const steps = await getExecutionSteps({
client,
path: { id: exec.data.executionId! },
throwOnError: true,
});
for (const step of steps.data) {
console.log(`[${step.status}] ${step.label} — tx: ${step.txHash}`);
}Authentication (wallet login)
loginWithEvm runs the full challenge → EIP-191 sign → verify flow and sets the bearer token on the client automatically, so /v1/me calls authenticate without any extra wiring.
Accepts a raw private key or any viem account (privateKeyToAccount, mnemonicToAccount, hardware wallets, wallet adapters):
import { createOmniTransferClient, loginWithEvm, listApiKeys } from 'omni-transfer-sdk';
import { privateKeyToAccount } from 'viem/accounts';
const client = createOmniTransferClient({ baseUrl: 'https://api.example.com' });
// viem account:
const account = privateKeyToAccount('0x<private-key>');
await loginWithEvm(account, client);
// or raw private key string:
await loginWithEvm('0x<private-key>', client);
// All /v1/me calls are now authenticated:
const keys = await listApiKeys({ client, throwOnError: true });You can also wire a pre-existing session token at construction time:
const client = createOmniTransferClient({
baseUrl: 'https://api.example.com',
sessionToken: 'existing-token',
});Account management (/v1/me)
All endpoints require a session (see above).
List API keys
import { listApiKeys } from 'omni-transfer-sdk';
const { data: keys } = await listApiKeys({ client, throwOnError: true });
for (const k of keys) {
console.log(k.keyPrefix, k.name, k.revokedAt ? '(revoked)' : '');
}Create an API key
import { createApiKey } from 'omni-transfer-sdk';
const { data } = await createApiKey({
client,
body: {
name: 'My integration',
annotation: 'Used by my backend',
partnerBps: 50, // 0.5% partner fee, up to root key's system fee
},
throwOnError: true,
});
// The full key is returned ONCE — store it immediately.
console.log('API key:', data.apiKey);Store an encrypted blob on a key
import { updateApiKeyBlob } from 'omni-transfer-sdk';
await updateApiKeyBlob({
client,
path: { id: '<key-uuid>' },
body: { encryptedBlob: '<client-encrypted payload>' },
throwOnError: true,
});Usage & revenue summaries (30d)
import { getUsageSummary, getRevenueSummary } from 'omni-transfer-sdk';
const { data: usage } = await getUsageSummary({ client, throwOnError: true });
console.log('tx count:', usage.txCount);
const { data: rev } = await getRevenueSummary({ client, throwOnError: true });
console.log('revenue:', rev.revenueUsd, 'USD');Analytics
import { getCreatorAnalytics } from 'omni-transfer-sdk';
const { data } = await getCreatorAnalytics({
client,
query: { window: '30d' }, // '7d' (default) or '30d'
throwOnError: true,
});
console.log(`success rate: ${data.txStats?.pctSuccess?.toFixed(1)}%`);Explorer
No API key required.
Search by execution ID, tx hash, or wallet address
import { searchExplorerExecutions } from 'omni-transfer-sdk';
const { data } = await searchExplorerExecutions({
client,
query: { q: '0x<tx-hash-or-wallet>' },
throwOnError: true,
});
if (data.execution) {
console.log('found:', data.execution.executionId);
}Execution details
import { getExplorerExecution } from 'omni-transfer-sdk';
const { data: ex } = await getExplorerExecution({
client,
path: { id: '<execution-id>' },
throwOnError: true,
});
console.log(ex.status, ex.source?.token?.symbol, '→', ex.destination?.token?.symbol);Error handling
Without throwOnError, calls return { data, error, response }:
const result = await createRoute({ client, body });
if (result.error) {
// result.error is the typed error body, result.response.status is the HTTP code
console.error(result.response.status, result.error.message);
} else {
// result.data is the typed 200 response
}With throwOnError: true, only the success type is returned — TypeScript narrows data accordingly.
Signing helpers reference
| Helper | Chain | Purpose |
|---|---|---|
| signEvmDigest(digestHex, privKeyHex) | EVM | Sign a 32-byte execution digest (v = 27/28) — viem |
| personalSign(message, privKeyHex) | EVM | EIP-191 personal_sign (used internally by loginWithEvm) |
| signSolanaMessage(messageB64, privKey) | Solana | Sign raw transaction message bytes — @solana/kit |
| solanaPrivateKeyFromBase58(b58) | Solana | Decode a base58 64-byte keypair to Uint8Array |
| signBtcUnsignedTx(fields, wif) | Bitcoin | P2WPKH / P2SH-P2WPKH / legacy SIGHASH_SINGLE\|ANYONECANPAY — @scure/btc-signer |
| loginWithEvm(signer, client?) | EVM | Full challenge → sign → verify auth flow with automatic session population |
All signing helpers are pure functions — no key material is transmitted. Outputs are verified byte-for-byte against the Go SDK with shared test vectors.
Changelog
See CHANGELOG.md.
Contributing
Source lives at github.com/omnes-tech/omni-transfer-sdk-ts. The client is generated from the API's OpenAPI spec — see the repo for development instructions.
