Bitflow SDK

An overview of the Bitflow SDK, including installation, configuration, and usage in your project.

Bitflow SDK is a powerful and easy-to-use library for interacting with the Bitflow Protocol. It provides a set of tools to seamlessly integrate Bitflow functionality into your applications. Currently, the SDK is available by request only. If you are interested in integrating with the BitFlow SDK please reach out to the team on Discord.

Table of Contents

  • Bitflow SDK

  • Table of Contents

  • Installation

  • Configuration

  • Usage

  • Available Functions

    • Get Available Tokens

    • Get Possible Swaps

    • Get All Possible Token Y

    • Get All Possible Token Y Routes

    • Getting Quote for Route

    • Getting Swap Parameters

    • Executing Swap (uses @stacks/connect)

  • Bitflow SDK - Keeper Functions

    • Get or Create Keeper Contract

    • Create Order

    • Get Order

    • Get User

    • Get Quote

    • Create Group Order

    • Get Group Order

    • Cancel Order

    • Cancel Group Order

    • Get Keeper Tokens

    • Get Keeper Possible Swaps

    • Get All Keeper Possible Token Y

    • Get All Keeper Possible Token Y Routes

    • Get Keeper Quote For Route

    • Example of BTC to sBTC

  • Types

  • Outline of Optional Parameters

  • Troubleshooting

  • License

Installation

Install the Bitflow SDK using npm:

npm install @bitflowlabs/core-sdk

Latest Stable Version is 1.6.1

Configuration

Before using the Bitflow SDK, you need to set up your environment variables. Create a .env file in your project root with the following variables:

# will be provided by Bitflow
BITFLOW_API_HOST=https://example-api-host.com
# will be provided by Bitflow
BITFLOW_API_KEY=<your_api_key_here>
# will be provided by Bitflow
READONLY_CALL_API_HOST=https://example-readonly-api.com
# will be provided by Bitflow
KEEPER_API_KEY=<your_api_key_here>
# will be provided by Bitflow
KEEPER_API_HOST=https://your-keeper-api-host.com

Usage

Here's a step-by-step guide to implement the Bitflow SDK in your project:

  1. Import the SDK:

import { BitflowSDK } from '@bitflowlabs/core-sdk';
  1. Initialize the SDK:

// if no parameters are provided, the SDK will try to use the environment variables
const bitflow = new BitflowSDK({
  BITFLOW_API_HOST: string,
  BITFLOW_API_KEY: string,
  READONLY_CALL_API_HOST: string,
  KEEPER_API_KEY: string,
  KEEPER_API_HOST: string
});
  1. Use the SDK methods to interact with the Bitflow Protocol. Here are some common operations:

Available Functions

Get Available Tokens

Retrieve a list of all available tokens:

const tokens = await bitflow.getAvailableTokens();
console.log(tokens);

Get Possible Swaps

Get all possible swap options for a given token:

const tokenXId = 'token-stx'; // the `tokenId` prop from `Token` interface
const swapOptions = await bitflow.getPossibleSwaps(tokenXId);
console.log(swapOptions);

Get All Possible Token Y

Retrieve all possible tokens that can be swapped for a given token:

const tokenXId = 'token-stx';
const possibleTokens = await bitflow.getAllPossibleTokenY(tokenXId);
console.log(possibleTokens);

Get All Possible Token Y Routes

Get all possible routes for swapping between two tokens:

const tokenXId = 'token-usda';
const tokenYId = 'token-stx';
const routes = await bitflow.getAllPossibleTokenYRoutes(tokenXId, tokenYId);
console.log(routes);

Getting Quote for Route

Get the quotes for a swap between two tokens:

const tokenXId = 'token-usda';
const tokenYId = 'token-stx';
const amount = 100; // Amount of tokenX to swap
const quoteResult = await bitflow.getQuoteForRoute(tokenXId, tokenYId, amount);
console.log(quoteResult);

Getting Swap Parameters

Get the necessary parameters for signing a swap transaction:

const swapExecutionData = {
  route: selectedRoute,
  amount: 100,
  tokenXDecimals: selectedRoute.tokenXDecimals,
  tokenYDecimals: selectedRoute.tokenYDecimals,
};
const senderAddress = 'your_stacks_address';
const slippageTolerance = 0.01; // 1%

const swapParams = await bitflow.getSwapParams(
  swapExecutionData,
  senderAddress,
  slippageTolerance
);
console.log(swapParams);

Executing Swap (uses @stacks/connect)

This function uses the @stacks/connect library to execute a swap transaction:

const swapExecutionData = {
  route: selectedRoute,
  amount: 100,
  tokenXDecimals: selectedRoute.tokenXDecimals,
  tokenYDecimals: selectedRoute.tokenYDecimals,
};
const senderAddress = 'your_stacks_address';
const slippageTolerance = 0.01; // 1%

await bitflow.executeSwap(
  swapExecutionData,
  senderAddress,
  slippageTolerance,
  stacksProvider, // a valid object of type `StacksProvider` from `@stacks/connect`
  (data) => console.log('Swap executed:', data),
  () => console.log('Swap cancelled')
);

Types

The SDK exports several TypeScript types that you can use in your application:

  • BitflowSDKConfig: Represents the configuration object for the Bitflow SDK.

  • Token: Represents a token with its properties.

  • SwapOptions: Represents possible swap options for a token.

  • PostConditionType: Represents the type of a post-condition used in transactions.

  • SelectedSwapRoute: Represents a selected swap route with its details.

  • RouteQuote: Represents the quote for a swap route.

  • QuoteResult: Represents the result of a quote request, including the best RouteQuote and all possible routes.

  • SwapExecutionData: Represents the data needed to execute a swap.

  • SwapDataParamsAndPostConditions: Represents the parameters and post-conditions needed to execute/sign a swap transaction.

import {
  Token,
  SwapOptions,
  SelectedSwapRoute,
  QuoteResult,
  SwapExecutionData,
  SwapDataParamsAndPostConditions,
} from '@bitflowlabs/core-sdk';

Bitflow SDK - Keeper Functions

The Bitflow SDK also provides a set of Keeper functions that enable automated token swaps and order management on the Stacks blockchain. These functions allow your application to interact with the Keeper service for executing various types of token operations.

Available Keeper Functions

Get or Create Keeper Contract

Get an existing keeper contract or create a new one for a Stacks address:

const params = {
  stacksAddress: 'SP3D03X5BHMNSAAW71NN7BQRMV4DW2G4JB3MZAGJ8',
  keeperType: 'MULTI_ACTION_V1',
  bitcoinAddress: 'bc1q9h0wnrj3u5qysj5kr9lnlgxcmyt2nljvlknujq',
  deployContract: true,
  allActionsApproved: true
};

const response = await bitflow.getOrCreateKeeperContract(params);
console.log(response.keeperContract);

Create Order

Create a new swap or action order:

const params = {
  contractIdentifier: 'SP3R9DNHRSBPT42JX98J92ZJHASWSBXT5ZW8X4XCK.keeper-4-bpuokbrj9-v-1-1', // keeper address
  stacksAddress: 'SP3D03X5BHMNSAAW71NN7BQRMV4DW2G4JB3MZAGJ8', // user stacks address
  keeperType: 'MULTI_ACTION_V1',
  actionType: 'SWAP_XYK_SWAP_HELPER',
  fundingTokens: {
    'SP14NS8MVBRHXMM96BQY0727AJ59SWPV7RMHC0NCG.pontis-bridge-pBTC::bridge-token': '10000'
  }, // if stx then STX:
  actionAggregatorTokens: {
    tokenXId: 'token-pbtc',
    tokenYId: 'token-sbtc'
  },
  minReceived: {
    amount: '0',
    autoAdjust: false
  },
  feeRecipient: 'SPQC38PW542EQJ5M11CR25P7BS1CA6QT4TBXGB3M',
  actionAmount: '10000',
  bitcoinTxId: '7115ece25072562f662bc72e2ad11d39b9a2abce8592930c9177ee320ac64b45'// when bridging BTC to stacks
};

const response = await bitflow.createOrder(params);
console.log(response.keeperOrder);

Get Order

Retrieve details of a specific order by its ID:

const orderId = 'your-order-id';
const order = await bitflow.getOrder(orderId);
console.log(order);

Get User

Get user information including their associated Keeper contracts and orders:

const stacksAddress = 'SP3D03X5BHMNSAAW71NN7BQRMV4DW2G4JB3MZAGJ8';
const user = await bitflow.getUser(stacksAddress);
console.log(user);

Get Quote

Get a price quote for a Keeper action:

const params = {
  stacksAddress: 'SP3D03X5BHMNSAAW71NN7BQRMV4DW2G4JB3MZAGJ8',
  actionAmount: '10000',
  keeperType: 'MULTI_ACTION_V1',
  actionType: 'SWAP_XYK_SWAP_HELPER',
  tokenXId: 'token-pbtc',
  tokenYId: 'token-sbtc',
  minReceived: {
    amount: '0',
    autoAdjust: true
  },
  feeRecipient: 'SPQC38PW542EQJ5M11CR25P7BS1CA6QT4TBXGB3M',
  bitcoinAddress: 'bc1q9h0wnrj3u5qysj5kr9lnlgxcmyt2nljvlknujq'
};

const quote = await bitflow.getQuote(params);
console.log(quote);

Create Group Order

Create a group of orders to be executed according to a schedule:

const params = {
  stacksAddress: 'SP3D03X5BHMNSAAW71NN7BQRMV4DW2G4JB3MZAGJ8',
  amountPerOrder: 1000,
  numberOfOrders: 5,
  executionFrequency: 86400, // in seconds (daily)
  feeRecipient: 'SPQC38PW542EQJ5M11CR25P7BS1CA6QT4TBXGB3M',
  fundingTokens: {
    'SP14NS8MVBRHXMM96BQY0727AJ59SWPV7RMHC0NCG.pontis-bridge-pBTC::bridge-token': '5000'
  },
  bitcoinTxId: '7115ece25072562f662bc72e2ad11d39b9a2abce8592930c9177ee320ac64b45',
  keeperType: 'MULTI_ACTION_V1',
  actionType: 'SWAP_XYK_SWAP_HELPER',
  actionAggregatorTokens: {
    tokenXId: 'token-pbtc',
    tokenYId: 'token-sbtc'
  },
  bitcoinAddress: 'bc1q9h0wnrj3u5qysj5kr9lnlgxcmyt2nljvlknujq',
  minReceived: {
    amount: '0',
    autoAdjust: true
  }
};

const response = await bitflow.createGroupOrder(params);
console.log(response.keeperGroupOrder);

Get Group Order

Retrieve details of a specific group order:

const groupId = 'your-group-id';
const includeOrders = true; // set to true to include detailed order information
const groupOrder = await bitflow.getGroupOrder(groupId, includeOrders);
console.log(groupOrder);

Cancel Order

Cancel a specific order:

const orderId = 'your-order-id';
const response = await bitflow.cancelOrder(orderId);
console.log(response.success);

Cancel Group Order

Cancel a group order:

const groupId = 'your-group-id';
const response = await bitflow.cancelGroupOrder(groupId);
console.log(response.success);

Get Keeper Tokens

Get tokens that are compatible with the Keeper service:

const tokens = await bitflow.getKeeperTokens();
console.log(tokens);

Get Keeper Possible Swaps

Get all possible swap options for a given token using the Keeper service:

const tokenXId = 'token-pbtc';
const swapOptions = await bitflow.getKeeperPossibleSwaps(tokenXId);
console.log(swapOptions);

Get All Keeper Possible Token Y

Retrieve all possible tokens that can be swapped for a given token using the Keeper service:

const tokenXId = 'token-pbtc';
const possibleTokens = await bitflow.getAllKeeperPossibleTokenY(tokenXId);
console.log(possibleTokens);

Get All Keeper Possible Token Y Routes

Get all possible Keeper routes for swapping between two tokens:

const tokenXId = 'token-pbtc';
const tokenYId = 'token-sbtc';
const routes = await bitflow.getAllKeeperPossibleTokenYRoutes(tokenXId, tokenYId);
console.log(routes);

Get Keeper Quote For Route

Get the quotes for a swap between two tokens using the Keeper service:

const tokenXId = 'token-pbtc';
const tokenYId = 'token-sbtc';
const amount = 10000;
const quoteResult = await bitflow.getKeeperQuoteForRoute(tokenXId, tokenYId, amount);
console.log(quoteResult);

Example of BTC to sBTC

Call the Pontis SDK’s createSendBTC function as follows. This function takes the scaled BTC amount, fee information, and the keeper’s (recipient) address, and it uses a callback (that internally calls doSignAndBroadcastPsbt) to sign and broadcast the transaction. Once broadcast, it returns a claim (the transaction id):

const claim = await createSendBTC(
  bitcoinAmount * btcScaleFactor,          // Amount in satoshis
  bridgeFee,                               // Bridge fee (fee rate)
  recipientAddress,                        // Keeper address (recipient)
  ChainType.STX,                           // Destination chain: Stacks
  async (psbt, signTypes) => {               // Callback for signing and broadcasting
    return doSignAndBroadcastPsbt({
      psbt: psbt as any,
      signIndexes: signTypes,
      bitcoinAddress,                      
      ordinalsAddress,                     
      wallet,                              // Wallet instance for signing
      walletType,                          // Wallet type identifier
      onBroadcastBitcoinTransaction        
    });
  },
  {
    amount: (bitcoinAmount * btcScaleFactor).toString(),
    assetName: 'BTC',
    assetType: AssetType.BTC,
    address: recipientAddress,
    timestamp: new Date().toString()
  }
);

try {
  const claimData = txs.find(tx => tx.txId === claim);
  await signMessageForTx(
    bitcoinAddress,
    claim!,
    async (message: string) => {
      return await doSignMessage({ message, wallet, bitcoinAddress });
    },
    () => null,
    {
      amount: claimData?.amount,
      assetName: claimData?.assetName,
      assetType: claimData?.assetType,
      address: claimData?.recipientAddress,
      timestamp: new Date().toString()
    }
  );
} catch (error) {
  console.log('Error during BTC message signing:', error);
}

return { claim };

After you have the txId (claim) from createSendBTC, you create the on‑chain order to bridge BTC to sBTC. Use the claim as the bitcoinTxId in your order parameters. For example:

const params = {
  contractIdentifier: 'SP3R9DNHRSBPT42JX98J92ZJHASWSBXT5ZW8X4XCK.keeper-4-bpuokbrj9-v-1-1', // keeper address
  stacksAddress: 'SP3D03X5BHMNSAAW71NN7BQRMV4DW2G4JB3MZAGJ8', // user stacks address
  keeperType: 'MULTI_ACTION_V1',
  actionType: 'SWAP_XYK_SWAP_HELPER',
  fundingTokens: {
    'SP14NS8MVBRHXMM96BQY0727AJ59SWPV7RMHC0NCG.pontis-bridge-pBTC::bridge-token': '10000'
  },
  actionAggregatorTokens: {
    tokenXId: 'token-pbtc',
    tokenYId: 'token-sbtc'
  },
  minReceived: {
    amount: '0',
    autoAdjust: false
  },
  feeRecipient: 'SPQC38PW542EQJ5M11CR25P7BS1CA6QT4TBXGB3M',
  actionAmount: '10000',
  bitcoinTxId: '7115ece25072562f662bc72e2ad11d39b9a2abce8592930c9177ee320ac64b45'
};

const response = await bitflow.createOrder(params);
console.log(response.keeperOrder);

Outline of Optional Parameters

If a parameter is listed in this list, we consider it as an optional parameter needed to be passed along for the specified endpoint. createGroupOrder:

  • bitcoinTxId or stacksTxId optinal, can be provided for most actions -- depending on the actionType, no transaction needs to be provided (but providing one is still recommended)

  • fundingTokens: optional, should be used for most actions

  • minReceived: optional, should be used in most cases

  • bitcoinAddress: optional

  • actionFunctionArgs, actionPostConditions, and actionAggregatorTokens: optional -- actionAggregatorTokens is used for almost all swap-related actions. actionFunctionArgs and actionPostConditions are mostly used for actions such as adding liquidity

  • nextExecutionAfter: optional

  • priceRange: optional

  • feeRecipient: optional

createOrder:

  • Same as above, but includes cancelOrderAfter, which is optional

getGroupOrder:

  • includeOrders: optional

getOrCreateKeeperContract: Depending on the keeperType, bitcoinAddress is optional but providing it is still recommended

  • deployContract: optional

  • allActionsApproved: optional

Troubleshooting

If you encounter any issues while using the Bitflow SDK, please check the following:

  1. Ensure all environment variables are correctly set in your .env file.

  2. Make sure you have the latest version of the SDK installed.

  3. Check that you're using a valid Stacks address for the senderAddress parameter.

License

This project is licensed under the MIT License - see the LICENSE file for details.

Last updated