0.0.4 • Published 7 months ago

@saturnbtcio/pools-api-sdk v0.0.4

Weekly downloads
-
License
MIT
Repository
github
Last release
7 months ago

Pools SDK Documentation

Welcome to the Pools SDK documentation!


Table of Contents


Introduction

The Pools SDK provides a convenient way to interact with the Pools API, which includes endpoints for managing liquidity pools, performing token swaps, and more. The SDK abstracts away the complexities of HTTP requests and data serialization, allowing you to focus on building your application logic.

Installation

To install the SDK, run the following command:

npm install @saturnbtcio/pools-api-sdk

Configuration

Before using the SDK, you need to configure it with the base URL of your Saturn API server. Most endpoints require authentication using an API key, so ensure that you include the x-api-key header in the configuration.

import { IConnection } from "@saturnbtcio/pools-api-sdk";

const connection: IConnection = {
  host: "https://api-dev.saturnbtc.io", // Replace with your API base URL
  headers: {
    "x-api-key": "your-api-key", // Replace with your actual API key
  },
};

You can pass this connection object to the SDK functions when making API calls.

Usage

Below are examples of how to use the SDK to interact with various endpoints.

Initialize Pool

Step 1: Generate PSBT

import sdk from "@saturnbtcio/pools-api-sdk";

const psbtResponse = await sdk.functional.v0.pool.initialize_pool.psbt.initializePoolPsbt(
  {
    pubkey: "your-public-key",
    feeRate: 10, // Fee rate in satoshis per byte
    accountsLength: 11, // Number of accounts to create
  },
  connection
);

if (!psbtResponse.success) {
  if (
    psbtResponse.status === 401 ||
    psbtResponse.status === 403 ||
    psbtResponse.status === 500
  ) {
    // Handle common errors
    // 401: Unauthorized
    // 403: User not found
    // 500: Internal server error
  }

  // Handle PoolErrorException
  console.error("Error:", psbtResponse.data);
  throw new Error("Failed to generate PSBT");
}

// Access PSBT data
const { psbt, fee, utxosToSign, accounts } = psbtResponse.data;
  • Parameters:
    • runePubkey: Your wallet's Taproot pubkey.
    • paymentPubkey: (Optional) Your wallet's payment pubkey (for xverse and others).
    • feeRate: Desired fee rate for the transaction.
    • accountsLength: Number of accounts to create for the pool.
    • connection: The connection object configured with your API host and headers.

Step 2: Sign PSBT and Generate Message

Sign the PSBT using your wallet, then generate the message hash.

// Implement signPsbt according to your wallet
const signedPsbt = signPsbt(psbtResponse.data.psbt, psbtResponse.data.utxosToSign);

const messageHashResponse = await sdk.functional.v0.pool.initialize_pool.message.initializePoolMessage(
  {
    runePubkey: "your-public-key",
    paymentPubkey: "your-payment-key",
    accounts: psbtResponse.data.accounts,
    feeRate: 10,
    signedPsbt,
    token0: "token0-id",
    token1: "token1-id",
    feeTier: 3000, // Example fee tier in basis points (e.g., 0.3% fee tier is 3000)
  },
  connection
);

if (!messageHashResponse.success) {
  // Handle error
  console.error("Error:", messageHashResponse.data);
  throw new Error("Failed to generate message hash");
}

const messageHash = messageHashResponse.data;
  • Parameters:
    • accounts: Accounts from the PSBT response.
    • signedPsbt: Your signed PSBT in base64 format.
    • token0, token1: Identifiers of the tokens in the pool.
    • feeTier: The fee tier for the pool in basis points.
    • connection: The connection object.

Step 3: Submit Signed Message

Sign the message hash using BIP322 with your Taproot address, then submit the final request.

// Implement signMessage according to your wallet
const signature = signMessage(messageHash);

const initializePoolResponse = await sdk.functional.v0.pool.initialize_pool.initializePool(
  {
    pubkey: "your-public-key",
    accounts: psbtResponse.data.accounts,
    feeRate: 10,
    signedPsbt,
    token0: "token0-id",
    token1: "token1-id",
    feeTier: 3000,
    signature,
  },
  connection
);

if (!initializePoolResponse.success) {
  // Handle error
  console.error("Error:", initializePoolResponse.data);
  throw new Error("Failed to initialize pool");
}

const transactionId = initializePoolResponse.data;
console.log("Pool initialized with transaction ID:", transactionId);
  • Parameters:
    • signature: Your signature of the message hash.
    • connection: The connection object.

Add Pool Shards

Follow similar steps as Initialize Pool, but use the addPoolShards methods.

Step 1: Generate PSBT

const psbtResponse = await sdk.functional.v0.pool.add_pool_shards.psbt.addPoolShardsPsbt(
  {
    runePubkey: "your-public-key",
    paymentPubkey: "your-payment-key",
    feeRate: 10,
    accountsLength: 2,
  },
  connection
);

// Handle errors as shown previously

Step 2: Sign PSBT and Generate Message

const signedPsbt = signPsbt(psbtResponse.data.psbt, psbtResponse.data.utxosToSign);

const messageHashResponse = await sdk.functional.v0.pool.add_pool_shards.message.addPoolShardsMessage(
  {
    runePubkey: "your-public-key",
    paymentPubkey: "your-payment-key",
    poolId: "pool-id",
    accounts: psbtResponse.data.accounts,
    feeRate: 10,
    signedPsbt,
  },
  connection
);

// Handle errors as shown previously

Step 3: Submit Signed Message

const signature = signMessage(messageHashResponse.data);

const addShardsResponse = await sdk.functional.v0.pool.add_pool_shards.addPoolShards(
  {
    runePubkey: "your-public-key",
    paymentPubkey: "your-payment-key",
    poolId: "pool-id",
    accounts: psbtResponse.data.accounts,
    feeRate: 10,
    signedPsbt,
    signature,
  },
  connection
);

// Handle errors as shown previously

console.log("Added pool shards with transaction ID:", addShardsResponse.data);

Open Position

Step 1: Generate PSBT

const psbtResponse = await sdk.functional.v0.pool.open_position.psbt.openPositionPsbt(
  {
    runePubkey: "your-public-key",
    paymentPubkey: "your-payment-key",
    token0: "token0-id",
    token1: "token1-id",
    amount0: "100000000", // Amount in smallest units (e.g., satoshis)
    amount1: "50000000",
    initializeAccountUtxo: true,
    feeRate: 10,
  },
  connection
);

// Handle errors as shown previously

Step 2: Sign PSBT and Generate Message

const signedPsbt = signPsbt(psbtResponse.data.psbt, psbtResponse.data.utxosToSign);

const messageHashResponse = await sdk.functional.v0.pool.open_position.message.openPositionMessage(
  {
    runePubkey: "your-public-key",
    paymentPubkey: "your-payment-key",
    poolId: "pool-id",
    amount0: "100000000",
    amount1: "50000000",
    feeRate: 10,
    signedPsbt,
    account: psbtResponse.data.account, // From PSBT response
  },
  connection
);

// Handle errors as shown previously

Step 3: Submit Signed Message

const signature = signMessage(messageHashResponse.data);

const openPositionResponse = await sdk.functional.v0.pool.open_position.openPosition(
  {
    runePubkey: "your-public-key",
    paymentPubkey: "your-payment-key",
    poolId: "pool-id",
    amount0: "100000000",
    amount1: "50000000",
    feeRate: 10,
    signedPsbt,
    account: psbtResponse.data.account,
    signature,
  },
  connection
);

// Handle errors as shown previously

console.log("Position opened with transaction ID:", openPositionResponse.data);

Increase Liquidity

Step 1: Generate PSBT

const psbtResponse = await sdk.functional.v0.pool.increase_liquidity.psbt.increaseLiquidityPsbt(
  {
    runePubkey: "your-public-key",
    paymentPubkey: "your-payment-key",
    token0: "token0-id",
    token1: "token1-id",
    amount0: "50000000",
    amount1: "25000000",
    initializeAccountUtxo: false,
    feeRate: 10,
  },
  connection
);

// Handle errors as shown previously

Step 2: Sign PSBT and Generate Message

const signedPsbt = signPsbt(psbtResponse.data.psbt, psbtResponse.data.utxosToSign);

const messageHashResponse = await sdk.functional.v0.pool.increase_liquidity.message.increaseLiquidityMessage(
  {
    runePubkey: "your-public-key",
    paymentPubkey: "your-payment-key",
    poolId: "pool-id",
    amount0: "50000000",
    amount1: "25000000",
    feeRate: 10,
    signedPsbt,
    positionPubKey: "position-public-key",
  },
  connection
);

// Handle errors as shown previously

Step 3: Submit Signed Message

const signature = signMessage(messageHashResponse.data);

const increaseLiquidityResponse = await sdk.functional.v0.pool.increase_liquidity.increaseLiquidity(
  {
    runePubkey: "your-public-key",
    paymentPubkey: "your-payment-key",
    poolId: "pool-id",
    amount0: "50000000",
    amount1: "25000000",
    feeRate: 10,
    signedPsbt,
    positionPubKey: "position-public-key",
    signature,
  },
  connection
);

// Handle errors as shown previously

console.log("Liquidity increased with transaction ID:", increaseLiquidityResponse.data);

Decrease Liquidity

Optional Step: Generate PSBT

Creating a PSBT is optional for decreasing liquidity. If you need to cover network fees, generate a PSBT.

const psbtResponse = await sdk.functional.v0.pool.decrease_liquidity.psbt.decreaseLiquidityPsbt(
  {
    runePubkey: "your-public-key",
    paymentPubkey: "your-payment-key",
    feeRate: 10,
  },
  connection
);

// Handle errors as shown previously

const signedPsbt = psbtResponse.success
  ? signPsbt(psbtResponse.data.psbt, psbtResponse.data.utxosToSign)
  : undefined;

Step 1: Generate Message

const messageHashResponse = await sdk.functional.v0.pool.decrease_liquidity.message.decreaseLiquidityMessage(
  {
    runePubkey: "your-public-key",
    paymentPubkey: "your-payment-key",
    poolId: "pool-id",
    positionPubKey: "position-public-key",
    liquidityAmount: "50000000",
    feeRate: 10,
    minToken0: "49000000", // Minimum expected amounts
    minToken1: "24000000",
    withdrawAddressToken0: "btc-address",
    withdrawAddressToken1: "token-address",
    signedPsbt, // Include if generated
  },
  connection
);

// Handle errors as shown previously

Step 2: Submit Signed Message

const signature = signMessage(messageHashResponse.data);

const decreaseLiquidityResponse = await sdk.functional.v0.pool.decrease_liquidity.decreaseLiquidity(
  {
    runePubkey: "your-public-key",
    paymentPubkey: "your-payment-key",
    poolId: "pool-id",
    positionPubKey: "position-public-key",
    liquidityAmount: "50000000",
    feeRate: 10,
    minToken0: "49000000",
    minToken1: "24000000",
    withdrawAddressToken0: "btc-address",
    withdrawAddressToken1: "token-address",
    signedPsbt, // Include if generated
    signature,
  },
  connection
);

// Handle errors as shown previously

console.log("Liquidity decreased with transaction ID:", decreaseLiquidityResponse.data);

Swap Tokens

Step 1: Generate PSBT

const psbtResponse = await sdk.functional.v0.pool.swap.psbt.swapPsbt(
  {
    runePubkey: "your-public-key",
    paymentPubkey: "your-payment-key",
    poolId: "pool-id",
    amountIn: "100000000",
    amountOut: "95000000",
    feeRate: 10,
    zeroToOne: true,
    exactIn: true,
  },
  connection
);

// Handle errors as shown previously

const signedPsbt = signPsbt(psbtResponse.data.psbt, psbtResponse.data.utxosToSign);

const signedSplitRunePsbt = psbtResponse.data.splitRunePsbt
  ? signPsbt(psbtResponse.data.splitRunePsbt.psbt, psbtResponse.data.splitRunePsbt.utxosToSign)
  : undefined;

Step 2: Generate Message

const messageHashResponse = await sdk.functional.v0.pool.swap.message.swapMessage(
  {
    runePubkey: "your-public-key",
    paymentPubkey: "your-payment-key",
    poolId: "pool-id",
    amountIn: "100000000",
    amountOut: "95000000",
    feeRate: 10,
    zeroToOne: true,
    exactIn: true,
    signedPsbt,
    splitRunePsbt: signedSplitRunePsbt,
    shardPubkeys: psbtResponse.data.shardPubkeys,
  },
  connection
);

// Handle errors as shown previously

Step 3: Submit Signed Message

const signature = signMessage(messageHashResponse.data);

const swapResponse = await sdk.functional.v0.pool.swap.swap(
  {
    runePubkey: "your-public-key",
    paymentPubkey: "your-payment-key",
    poolId: "pool-id",
    amountIn: "100000000",
    amountOut: "95000000",
    feeRate: 10,
    zeroToOne: true,
    exactIn: true,
    signedPsbt,
    splitRunePsbt: signedSplitRunePsbt,
    shardPubkeys: psbtResponse.data.shardPubkeys,
    signature,
  },
  connection
);

// Handle errors as shown previously

console.log("Swap executed with transaction ID:", swapResponse.data);

Get Swap Details

const swapDetailsResponse = await sdk.functional.v0.pool.swap.details.getSwapDetails(
  {
    token0: "token0-id",
    token1: "token1-id",
    amount: "100000000", // Amount in smallest units
    feeRate: 10,
    zeroToOne: true,
    exactIn: true,
  },
  connection
);

if (!swapDetailsResponse.success) {
  // Handle error
  console.error("Error:", swapDetailsResponse.data);
  throw new Error("Failed to get swap details");
}

const swapDetails = swapDetailsResponse.data;
console.log("Swap Details:", swapDetails);
  • Response Includes:
    • amountIn, amountOut
    • price
    • priceImpact
    • fees (network and liquidity provider fees)
    • poolId

Important Note on Swaps

When swapping from Rune to BTC:

  • The amountOut returned by getSwapDetails does not account for network fees.
  • You need to subtract network fees from amountOut before submitting your swap request.

Error Handling

The SDK methods return an object indicating whether the request was successful. You should handle these responses appropriately in your application.

const response = await sdk.functional.v0.pool.someMethod(params, connection);

if (!response.success) {
  // Handle error based on response status code and data
  if (response.status === 400) {
    console.error("Bad Request:", response.data);
  } else if (response.status === 401) {
    console.error("Unauthorized:", response.data);
  } else {
    console.error("Error:", response.data);
  }
  // Throw or handle the error as needed
  throw new Error("API request failed");
}

// Access the successful response data
const data = response.data;

Advanced Topics

Applying Slippage

To apply slippage to your swaps:

  • Decide on the slippage percentage (e.g., 3%).
  • Adjust the amountOut by subtracting the slippage percentage.
const slippagePercentage = 0.03; // 3%

const adjustedAmountOut = BigInt(swapDetails.amountOut) * BigInt(1 - slippagePercentage * 10000n) / 10000n;

const swapResponse = await sdk.functional.v0.pool.swap.swap(
  {
    // ... other parameters
    amountOut: adjustedAmountOut.toString(),
  },
  connection
);

Handling PSBTs

  • Use a Bitcoin library compatible with PSBTs to sign the PSBTs provided by the SDK.
  • Ensure you are using BIP322 for message signing.
  • Use Taproot addresses for signatures.
function signPsbt(psbtBase64: string, utxosToSign: UtxoToSign[]): string {
  // Decode the PSBT from base64
  const psbt = decodePsbt(psbtBase64);

  // Sign the PSBT using your wallet's functionality
  utxosToSign.forEach((utxo) => {
    // Use the signing indexes and sigHash from utxo to sign the inputs
    psbt.signInput(utxo.signingIndexes[0], yourKeyPair);
  });

  // Finalize the PSBT
  psbt.finalizeAllInputs();

  // Encode the signed PSBT back to base64
  return psbt.toBase64();
}

function signMessage(messageHash: string): string {
  // Sign the message hash using BIP322 with your Taproot address
  return wallet.signMessage(messageHash);
}

Conclusion

The Pools SDK simplifies the process of interacting with the Pools API by handling request construction, serialization, and authentication. By following the steps outlined in this documentation, you can efficiently manage liquidity pools, perform token swaps, and integrate these functionalities into your applications.

If you encounter any issues or need further assistance, please refer to the official API documentation or contact support.

0.0.4

7 months ago

0.0.3

9 months ago

0.0.2

12 months ago

0.0.1

12 months ago