Skip to main content

SDK Reference

The OdinTrade SDK provides a simple and efficient way to interact with the OdinTrade Atomic Swap protocol. This guide will help you integrate the SDK into your application. The current version of the SDK supports only Testnet environment, with multiple initialization options including private key injection and browser wallet providers. For browser wallet providers, the SDK supports only Xverse for Bitcoin and MetaMask, or Rabby Wallet, for Ethereum. The testnets are Testnet3 for Bitcoin and Sepolia for Ethereum. For Bitcoin, only Native SegWit (Bech32) addresses are supported, which in Testnet should start with tb1.

Accessing the SDK

Since the SDK is private on npm, only the authorized users can access it. This requires setting up an .npmrc file with an access token. This file will be provided by the team (contact us at [email protected]).
//registry.npmjs.org/:_authToken=<npm_access_token>

Installation

bun add @odinxorg/sdk
# or
npm install @odinxorg/sdk
# or
yarn add @odinxorg/sdk

Initialization

The SDK can be initialized in two ways depending on your use case:

Backend Initialization (Private Key)

For backend applications, you can initialize the SDK using private keys:
import { OdinTradeSdk, PrivkeyBitcoinSigner, PrivkeyEvmSigner } from '@odinxorg/sdk';

// Initialize signers with private keys

const bitcoinSigner = new PrivkeyBitcoinSigner(
  'your-btc-private-key', // private key hex (64 characters)
  'testnet', // it refers to Bitcoin Testnet3
);

const ethereumSigner = new PrivkeyEvmSigner(
  'https://sepolia.infura.io/v3/<your-infura-token>', // or any other Ethereum-Sepolia RPC URL
  'your-eth-private-key', // 32 characters (bytes)
);

// Initialize SDK
const sdk = new OdinTradeSdk({
  ethereumSigner,
  bitcoinSigner,
  url: 'https://api.odinx.org/testnet',
  walletPartnerId: 'your-wallet-partner-id', // Optional, will be communicated by OdinTrade support
});
An example test is available in the SDK at tests/sdk.spec.ts.

Frontend Initialization (Browser Wallet)

For frontend applications, you can use browser wallet providers like MetaMask:
import { OdinTradeSdk, WindowProviderEvmSigner, XverseBitcoinSigner } from '@odinxorg/sdk';

// Initialize signers with browser providers
const ethereumSigner = new WindowProviderEvmSigner();
const bitcoinSigner = new XverseBitcoinSigner();

// Connect to the providers
await ethereumSigner.connect();
await bitcoinSigner.connect();

// Initialize SDK
const sdk = new OdinTradeSdk({
  ethereumSigner,
  bitcoinSigner,
  url: 'https://api.odinx.org/testnet',
  walletPartnerId: 'your-wallet-partner-id', // Optional, will be communicated by OdinTrade support
});

User Requirements for Swapping with Browse Wallets

  1. The user must have the appropriate wallet installed:
    • MetaMask or Rabby Wallet for Ethereum
    • Xverse for Bitcoin
  2. The user must approve the connection request when connect() is called.

Browser Wallet Interactions per Function

createSwap

  • The user must sign a message containing the timestamp with addressIn.

confirmSwap (only for User Claim on Bitcoin )

  • The user must sign the user HTLC claim transaction with addressOut, in order to claim the HTLC. The transaction will be broadcasted by the LiquidityNode.

confirmUserHTLC (Ethereum)

  • If swapping an ERC20 token for the first time, the user must approve the ERC20 transfer (this transaction is broadcasted directly by the user).
  • If swapping ETH, the user must sign the userDeposit transaction each time they perform an ETH swap.
  • The user must sign the meta-transaction for HTLC creation.
The last two interactions (userDeposit for ETH & HTLC creation metaTX) are necessary because they are broadcasted by the LiquidityNode—the user’s only action is signing.

confirmUserHTLC (Bitcoin)

  • The user must sign the User HTLC creation transaction, which is broadcasted by the LiquidityNode.

Available Methods

Get Token Swap Details

Calculate estimated exchange rates and amountOut, for token pairs.
const details = await sdk.getTokenSwapDetails({
  amountIn: 1.0,
  tokenInSymbol: 'BTC',
  tokenOutSymbol: 'ETH',
  chainIn: 'bitcoin',
  chainOut: 'ethereum',
  addressIn: 'your-btc-address', // (tb1...) only Native SegWit (Bech32) addresses are supported in Testnet3
  addressOut: 'your-eth-address',
});

console.log(details);
// {
//   amountOut: 0.1,
//   rate: "8.546"
// }

Get Maximum Amount Out

Calculate the maximum amount of tokens you can receive based on your available balance.
const maxAmount = await sdk.getMaxAmountOut({
  tokenInSymbol: 'BTC',
  tokenOutSymbol: 'ETH',
  chainIn: 'bitcoin',
  chainOut: 'ethereum',
  addressIn: 'your-btc-address', // (tb1...) only Native SegWit (Bech32) addresses are supported in Testnet3
  addressOut: 'your-eth-address',
});

console.log(maxAmount);
// {
//   maxAmountOut: 10.0,
//   maxAmountIn: 1.0
// }

Create Swap

Initialize a new atomic swap. The SDK will automatically handle signing and address management. If it is not clear why amountOut is required, instead of amountIn, please refer to the Protocol Flow section.
const swap = await sdk.createSwap({
  amountOut: 1.0,
  tokenInSymbol: 'BTC',
  tokenOutSymbol: 'ETH',
  chainIn: 'bitcoin',
  chainOut: 'ethereum',
});

console.log(swap);
// {
//   swapId: "swap-123", // The swapId is the id of the swap and is required in the next steps
//   userClaimToSign: "..." // Only if ChainOut is Bitcoin, userClaimToSign is a string of the psbt to sign for the user to claim the htlc
// }

Confirm Swap

Confirm and execute the swap. The SDK will handle the appropriate signing based on the chain. swap is the swap object returned by the createSwap method.
const confirmation = await sdk.confirmSwap(swap.swapId, swap.userClaimToSign);

console.log(confirmation);
// {
//   transactionHash: "0x...",
//   estimatedAmountIn: 0.1,
//   estimatedRate: 0.1,
//   }
// }

Create User HTLC

Generate HTLC for the user’s part of the swap. swap is the swap object returned by the createSwap method.
const htlc = await sdk.createUserHtlc(swap.swapId);

console.log(htlc);
// {
//   amountIn: 0.1,
//   rate: 0.1,
//   userHtlcToSign: ["..."]
// }

Confirm User HTLC

Submit the signed HTLC transaction. swap is the swap object returned by the createSwap method and htlc is the htlc object returned by the createUserHtlc method.
const confirmation = await sdk.confirmUserHtlc(swap.swapId, htlc.userHtlcToSign);

console.log(confirmation);
// {
//   transactionHash: "0x..."
// }

Get Swap Status

Get detailed information about a specific swap.
const status = await sdk.getSwap(swapId);

console.log(status);
// {
//   id: "swap-123",
//   status: "PENDING",
//   htlc1TransactionHash: "0x...",
//   htlc2TransactionHash: "0x...",
//   brokerClaimedTransactionHash: "0x...",
//   userClaimedTransactionHash: "0x...",
//   createdAt: "2024-03-14T12:00:00Z",
//   tokenInSymbol: "BTC",
//   tokenOutSymbol: "ETH",
//   tokenInAddress: "0x...",
//   tokenOutAddress: "0x...",
//   chainIn: "bitcoin",
//   chainOut: "ethereum",
//   amountIn: 0.1,
//   amountOut: 1.0,
//   rate: 0.1
// }

Get Swaps History

Get all swaps history. If addressIn or addressOut is provided, it will return only the swaps for that address, and if both are provided, it will return the swaps for both addresses. At least one address (addressIn or addressOut) is required.
const history = await sdk.getSwapHistory(addressIn, addressOut);

console.log(history);
// [
//   {
//     id: "swap-123",
//     status: "PENDING",
//     tokenInSymbol: "BTC",
//     tokenOutSymbol: "ETH",
//     chainIn: "bitcoin",
//     chainOut: "ethereum",
//     amountIn: 0.1,
//     amountOut: 1.0,
//     rate: 0.1,
//     addressIn: "your-btc-address",
//     addressOut: "your-eth-address",
//     htlc1TransactionHash: "0x...",
//     htlc2TransactionHash: "0x...",
//     htlc1Output: "0x...",
//     htlc2Output: "0x...",
//     timestampBrokerClaimConfirmation: "2024-03-14T12:00:00Z",
//     timestampUserClaimConfirmation: "2024-03-14T12:00:00Z",
//     brokerClaimedTransactionHash: "0x...",
//     userClaimedTransactionHash: "0x...",
//     createdAt: "2024-03-14T12:00:00Z",
//     updatedAt: "2024-03-14T12:00:00Z",
//   }
// ]

Error Handling

The SDK throws errors in the following cases:
  1. Missing required signers for specific chains
  2. Invalid parameters
  3. Network errors
  4. API errors
Example error handling:
try {
  const swap = await sdk.createSwap({
    amountOut: 1.0,
    tokenInSymbol: 'BTC',
    tokenOutSymbol: 'ETH',
    chainIn: 'bitcoin',
    chainOut: 'ethereum',
  });
} catch (error) {
  console.error('Failed to create swap:', error.message);
  // Handle error appropriately
}

Best Practices

  1. Always initialize the SDK with the appropriate signers for the chains you plan to use
  2. Handle errors appropriately in your application
  3. Keep your private keys secure and never expose them
  4. Use environment variables for sensitive information like API URLs and private keys
  5. Test thoroughly on testnet before moving to mainnet