@saturnbtcio/pool-sdk
v0.0.45
Published
A TypeScript client library for interacting with Bitcoin Rune liquidity pools on Saturn. This SDK provides a simple, high-level interface to:
Downloads
158
Readme
@saturnbtcio/pool-sdk
A TypeScript client library for interacting with Bitcoin Rune liquidity pools on Saturn.
This SDK provides a simple, high-level interface to:
- Initialize a new liquidity pool
- Add shards (on-chain dust-limit UTXOs backing pool shares)
- Open and increase positions (deposit Rune + BTC into a pool)
- Decrease liquidity and withdraw tokens from an existing position
- Swap BTC ↔ Rune trades via on-chain instructions
Installation
npm install @saturnbtcio/pool-sdk
yarn add @saturnbtcio/pool-sdk
pnpm install @saturnbtcio/pool-sdkSaturnSdk
The SaturnSdk class is your main entry point to driving all pool-related instructions on Saturn. You instantiate it once with your program/account IDs and three “provider” implementations, then call into its methods to build & send transactions.
The configuration you need to pass to the SaturnSdk is the following:
| Field | Type | Description |
| -------------------------- | ---------------------- | ---------------------------------------------------------------- |
| programAddress | string | On-chain program ID (PDA) to which all instructions are sent |
| programAccount | string | 32-byte hex pubkey for your pool program account |
| network | Network | Bitcoin network enum (Mainnet/Testnet/Regtest) |
| mempoolInfoOracleAccount | string | PDA that holds live mempool fee & vsize data |
| feeRateOracleAccount | string | PDA that holds on-chain fee-rate oracle |
| maxTxSize | number | Maximum allowed PSBT vsize (enforced client-side) |
| archProvider | IArchProvider | RPC adapter for Arch (Solana-style) transactions |
| bitcoinProvider | IBitcoinProvider | RPC adapter for Bitcoin wallet, mempool, blockheight lookups |
| indexerProvider | IPoolIndexerProvider | Adapter for fetching pool & position state from your indexer API |
const sdk = new SaturnSdk({
programAddress: '… your on-chain program address …',
programAccount: '… your program’s account pubkey …',
network: Network.Regtest, // or Mainnet/Testnet
mempoolInfoOracleAccount: '… oracle PDAs …',
feeRateOracleAccount: '… oracle PDAs …',
maxTxSize: 10_000, // enforce PSBT size limits
archProvider: new ArchRpc(...),
bitcoinProvider: new BtcRpc(...),
indexerProvider: new IndexerApi(...),
})Providers
The SDK delegates external concerns to three pluggable “provider” interfaces. You must supply concrete implementations when constructing SaturnSdk.
Bitcoin provider
| Method | Return Type | Description |
| ------------------------ | -------------------------- | ---------------------------------------------------------------------------------- |
| getRecommendedFees() | Promise<FeesRecommended> | Fetches fee estimates for constructing transactions. |
| getLatestBlockHeight() | Promise<number> | Returns the current chain height. |
| getMempoolInfo(txIds) | Promise<MempoolInfoMap> | Looks up mempool entries by TXID; returns a map of `TxId → MempoolEntry |
| getWallet(address) | Promise<Wallet> | Returns a Wallet object containing UTXOs, balances, etc., for the given address. |
Arch provider
| Method | Return Type | Description |
| --------------------- | ----------------- | -------------------------------------------- |
| getAccountAddress() | Promise<string> | Fetches the address for the provided pubkey. |
Indexer provider
| Method | Return Type | Description |
| -------------------------------------------------- | -------------------------------------- | -------------------------------------------------------------- |
| getPoolById(poolId) | Promise<IdentifiableLiquidityPool> | Fetches a single pool by its on-chain identifier. |
| getPoolsByTokenIds(token0Id, token1Id, feeTier?) | Promise<IdentifiableLiquidityPool[]> | Fetches all pools matching a token pair and optional fee tier. |
| getCollection(token) | Promise<Collection> | Loads an on-chain collection entry. |
Instructions
Initialize Pool
Bootstraps a fresh liquidity pool for a Rune <> BTC pair. After this completes, your pool program owns N “shard” PDAs plus one pool-config PDA, each pre-funded with a dust UTXO and ready to accept swaps, adds, and withdrawals.
PSBT Method: initPoolCreateAccountPsbt
What it does:
- Computes the addresses of 1 + shardsLength PDAs (the “pool-config” PDA + each shard PDA).
- Adds a dust output to each PDA.
- Adds an output back to your Arch account to cover the “state-change” fee.
- Collects your wallet UTXOs and builds a PSBT to fund all of the above + miner fees.
Request object InitPoolCreateAccountPsbtRequest:
| Field | Type | Description |
| -------------- | ----------------------------- | ---------------------------------------------------------------- |
| address | string | Your Bitcoin address (receives change & state-fee refund) |
| publicKey | string | X-only pubkey hex of your Arch account (32 bytes → 64 hex chars) |
| feeRate | bigint | sats per vbyte |
| shardsLength | number | Number of pool shards (N) |
| feeTier | number | Numerical fee tier (used in swap math, e.g. 20 000) |
| token0 | {block: bigint, tx: number} | Your Rune collection ID |
| token1 | {block: bigint, tx: number} | Always {0n, 0} for BTC |
Example of usage:
const psbtResponse = await sdk.createAccounts.initPoolCreateAccountPsbt({
address: myBtcAddr,
publicKey: xOnlyHex,
feeRate: 20_000n,
shardsLength: 10,
feeTier: 20_000,
token0: { block: 123n, tx: 456 },
token1: { block: 0n, tx: 0 },
});Message Method: initializePoolMessage
What it does:
- Verifies no existing pool exists for your (token0, token1, feeTier).
- Confirms your Rune UTXO is deeply confirmed (via the indexer + Bitcoin).
- Parses your signed PSBT to collect the exact UTXOs you funded.
- Constructs an InitializePool Arch message ready to send on-chain.
Request object: InitializePoolMessageRequest:
| Field | Type | Description |
| ------------------ | -------- | --------------------------------------------------- |
| address | string | Same Bitcoin address you used above |
| publicKey | string | X-only pubkey hex (must match the PSBT funding) |
| randomNumber | number | 1 byte randomness to prevent replay |
| feeRate | bigint | Same sats/vbyte you used to build the PSBT |
| signedPsbt | string | Base64 encoding of the fully signed PSBT |
| token0 | string | "block:tx" of your Rune collection |
| token1 | string | "0:0" (must be BTC) |
| feeTier | number | Same fee tier |
| minConfirmations | number | Minimum confirmations for the Rune etch (usually 6) |
| shardsLength | number | Number of pool shards |
Example of usage:
const initMsg = await sdk.initializePool.initializePoolMessage({
address: myBtcAddr,
publicKey: xOnlyHex,
randomNumber: Math.floor(Math.random() * 256),
feeRate: 20_000n,
signedPsbt: signedPsbtBase64,
token0: '123:456',
token1: '0:0',
feeTier: 20_000,
minConfirmations: 6,
shardsLength: 10,
});Add Pool Shards
Injects N new “shard” PDAs into an already‐initialized pool. Each new shard PDA gets a dust UTXO, and the pool program can use them for swaps, adds, and withdrawals.
PSBT Method: addPoolShardsCreateAccountPsbt
What it does:
- Fetches your pool state from the indexer (must exist).
- Generates N new shard PDAs via the same PDA derivation used in initialization.
- Adds a dust‐sats output for each new shard.
- Adds a state‐change refund output back to your Arch account.
- Selects your wallet UTXOs to fund the total dust + miner fees.
- Builds a PSBT ready for you to sign & broadcast.
Request object: AddPoolShardsCreateAccountPsbtRequest:
| Field | Type | Description |
| -------------- | -------- | -------------------------------------- |
| address | string | Your Bitcoin change address |
| publicKey | string | X-only pubkey hex of your Arch account |
| feeRate | bigint | sats per vbyte |
| shardsLength | number | Number of shards to add |
| poolId | string | Identifier of the existing pool |
Example of usage:
const { psbt } = await sdk.createAccounts.addPoolShardsCreateAccountPsbt({
address: myBtcAddr,
publicKey: xOnlyHex,
feeRate: 20_000n,
shardsLength: 5,
poolId: "abc123…",
});Message Method: addPoolShardsMessage
What it does:
- Validates the same pool still exists and your fee tier/collection is unchanged.
- Parses your signed PSBT to identify the exact UTXOs you funded.
- Constructs an AddPoolShards Arch message with all new shard pubkeys + UTXO proofs.
Request object: AddPoolShardsMessageRequest:
| Field | Type | Description |
| -------------- | -------- | ----------------------------------------- |
| address | string | Same Bitcoin address used for PSBT change |
| publicKey | string | X-only pubkey hex |
| randomNumber | number | 1 byte randomness |
| feeRate | bigint | sats per vbyte |
| signedPsbt | string | Base64 of your fully signed PSBT |
| poolId | string | Pool identifier |
| shardsLength | number | Number of shards you added |
Example of usage:
const msg = await sdk.addPoolShards.addPoolShardsMessage({
address: myBtcAddr,
publicKey: xOnlyHex,
randomNumber: Math.floor(Math.random()*256),
feeRate: 20_000n,
signedPsbt: signedPsbtBase64,
poolId: "abc123…",
shardsLength: 5,
});Increase Liquidity
Deposit Rune & BTC into an existing pool—either opening a new position or topping up an existing one.
- Open Position: Lock fresh Rune + BTC into the pool and mint you a new position PDA.
- Add Liquidity: Send additional Rune + BTC into your existing position PDA.
PSBT Method: buildPsbtToSendFundsToProgram
Used for both open position and increase liquidity instructions.
What it does:
- Validates your pool & collection state via the indexer.
- Selects your Rune UTXOs (and optional payment address UTXOs) to meet:
collectionAmountof RunebtcAmount+ program‐side state‐change fee
- Construct a PSBT with:
- Inputs for Rune UTXOs
- Change & refund outputs back to you
- A dust‐sats output to the pool program for each asset
- (If includeAccountUtxo=true) a dust UTXO for a new Position PDA
- Estimates final vsize & flags if it’s under your maxTxSize limit.
Request object: IncreaseLiquidityRequest
| Field | Type | Description |
| -------------------- | -------------- | -------------------------------------------------------------------- |
| runeAddress | string | Your Bitcoin address holding Rune UTXOs |
| runePublicKey | string | X-only hex pubkey for your Arch account |
| paymentAddress? | string\|null | Optional separate address to pay BTC part of the fee |
| paymentPublicKey? | string | X-only hex pubkey for your payment address, if any |
| feeRate | bigint | sats per vbyte |
| collectionAmount | bigint | amount of Rune to deposit |
| btcAmount | bigint | amount of BTC (sats) to deposit |
| includeAccountUtxo | boolean | true to open a new position PDA; false to top up an existing one |
| poolId | string | Identifier of the target pool |
Example of usage:
const { tx, account, txSizeIsSmallerThanMaxTxSize } =
await sdk.increaseLiquidity.buildPsbtToSendFundsToProgram({
runeAddress: wallet.addr,
runePublicKey: xOnlyHex,
paymentAddress: null,
paymentPublicKey: undefined,
feeRate: 20_000n,
collectionAmount: 10_000n,
btcAmount: 10_000n,
includeAccountUtxo: true, // open new position
poolId: 'pool123…',
});Message Creation - Opening a New Position: createOpenPositionMessage
Use this after you’ve funded the pool-controlled address with your signed PSBT.
Request object: OpenPositionMessageRequest
| Field | Type | Description |
| -------------- | -------- | ------------------------------------------------- |
| signedPsbt | string | Base64 of your fully‐signed PSBT |
| amount0 | number | Rune quantity |
| amount1 | number | BTC (sats) quantity |
| randomNumber | number | 1-byte randomness |
| … | … | (See common PoolSdkMessageRequest fields above) |
Example of usage:
const { message, utxosInfo } =
await sdk.increaseLiquidity.createOpenPositionMessage({
runeAddress: wallet.addr,
runePublicKey: xOnlyHex,
paymentAddress: null,
randomNumber: 42,
feeRate: 20_000n,
signedPsbt: signedPsbtBase64,
poolId: 'pool123…',
amount0: 10_000, // Rune (integer)
amount1: 10_000, // BTC sats (integer)
mergeUtxoPsbt: undefined,
});Message Creation - Increasing Liquidity: createIncreaseLiquidityMessage
Request object: IncreaseLiquidityMessageRequest
| Field | Type | Description |
| ------------------ | -------- | ------------------------------------------------- |
| positionPubKey | string | X-only hex pubkey of your position PDA |
| collectionAmount | bigint | Rune being added |
| btcAmount | bigint | BTC (sats) being added |
| … | … | (See common PoolSdkMessageRequest fields above) |
Example of usage:
const { message, utxosInfo } =
await sdk.increaseLiquidity.createIncreaseLiquidityMessage({
runeAddress: wallet.addr,
runePublicKey: xOnlyHex,
paymentAddress: null,
randomNumber: 7,
feeRate: 20_000n,
signedPsbt: signedPsbtBase64,
poolId: 'pool123…',
positionPubKey: positionPdaHex,
collectionAmount: 5_000n,
btcAmount: 5_000n,
mergeUtxoPsbt: undefined,
});Decrease Liquidity
The Decrease Liquidity instruction withdraws a specified amount of liquidity from a position in a Saturn pool, returning the underlying tokens (token0 and token1) to the user’s addresses. It also handles payment of any required transaction fees, either from the pool’s own reserves or by sourcing funds from the user via UTXO or a signed PSBT.
Message Creation: createDecreaseLiquidityMessage
Builds the serialized Arch transaction message for decreasing liquidity, handling fee payment via one of three methods (none, fee_utxo, signed_psbt).
What it does:
- Validates pool & position state via the indexer and your request parameters.
- Calculates the fee based on shard count, output types, and provided
feeRate. - Selects shards to remove liquidity from and (if needed) locates or verifies UTXOs/PSBT for fee payment.
- Constructs the
DecreaseLiquidityInstructionand returns the raw Arch message.
Request object: DecreaseLiquidityMessageRequest
| Field | Type | Description |
| ----------------------- | -------------------------------- | ------------------------------------------------------------- | --------------------------------------------- | --------------------------------------------- |
| runeAddress | string | Your Arch‐controlled Bitcoin address holding Rune UTXOs |
| runePublicKey | string | X-only hex pubkey for your Arch account |
| paymentAddress? | string \| null | Optional address to pay BTC fees (if not using pool reserves) |
| paymentPublicKey? | string \| undefined | X-only hex pubkey corresponding to paymentAddress |
| randomNumber | number | 1-byte randomness nonce |
| feeRate | bigint | Fee rate in sats per byte |
| poolId | string | Identifier of the pool (pubkey) |
| positionPubKey | string | X-only hex pubkey of your position PDA |
| liquidityAmount | bigint | Amount of liquidity to withdraw |
| minToken0 | bigint | Minimum amount of Rune (token0) to receive |
| minToken1 | bigint | Minimum amount of BTC (token1) to receive |
| withdrawAddressToken0 | string | Bitcoin address to receive Rune |
| withdrawAddressToken1 | string | Bitcoin address to receive BTC |
| paymentMethod | DecreaseLiquidityPaymentMethod | { type: 'none' } | { type: 'fee_utxo'; feeUtxo: UtxoMetaData } | { type: 'signed_psbt'; signedPsbt: string } |
Example Usage
1) Pool covers fees (none)
const msgNone = await sdk.decreaseLiquidity.createDecreaseLiquidityMessage({
runeAddress, // your Arch address
runePublicKey, // x-only hex pubkey
paymentAddress: null,
paymentPublicKey: undefined,
randomNumber: 0,
feeRate: 20_000n,
poolId: 'pool123…',
positionPubKey: positionPdaHex,
liquidityAmount: 5_000n,
minToken0: 10n,
minToken1: 200n,
withdrawAddressToken0: wallet.addr,
withdrawAddressToken1: wallet.addr,
paymentMethod: { type: 'none' },
});PSBT Funding with ArchWalletSdk
Before calling createDecreaseLiquidityMessage with fee_utxo or signed_psbt, you must deposit sats into the pool’s Arch-controlled address and obtain a PSBT.
In order to do that use the @saturnbtcio/arch-wallet-sdk and the method:
Usage:
import { ArchWalletSdk } from '@saturnbtcio/arch-wallet-sdk';
import { Signer } from '@scure/btc-signer';
const archWalletSdk = new ArchWalletSdk({
/* your config */
});
const signer = new Signer(secretKey, 'regtest');
const wallet = await signerWallet.toSdkWallet();
const xOnlyHex = Buffer.from(signer.getPublicKey()).toString('hex');
const { psbt } =
await archWalletSdk.archWalletManager.depositFundsToArchControlledAddress({
runeAddress: wallet.address,
runePublicKey: xOnlyHex,
paymentAddress: null,
paymentPublicKey: null,
amount: BigInt(10_000), // sats to cover fees
feeRate, // sats per byte
});2) UTXO‐based fee payment (fee_utxo)
const msgFeeUtxo = await sdk.decreaseLiquidity.createDecreaseLiquidityMessage({
runeAddress,
runePublicKey,
paymentAddress: null,
paymentPublicKey: undefined,
randomNumber: 42,
feeRate: 20_000n,
poolId: 'pool123…',
positionPubKey: positionPdaHex,
liquidityAmount: 5_000n,
minToken0: 10n,
minToken1: 200n,
withdrawAddressToken0: wallet.addr,
withdrawAddressToken1: wallet.addr,
paymentMethod: {
type: 'fee_utxo',
feeUtxo: { txid: 'abcd1234…', vout: 0 },
},
});3) Signed‐PSBT fee payment (signed_psbt)
const msgSignedPsbt =
await sdk.decreaseLiquidity.createDecreaseLiquidityMessage({
runeAddress,
runePublicKey,
paymentAddress: null,
paymentPublicKey: undefined,
randomNumber: 99,
feeRate: 20_000n,
poolId: 'pool123…',
positionPubKey: positionPdaHex,
liquidityAmount: 5_000n,
minToken0: 10n,
minToken1: 200n,
withdrawAddressToken0: wallet.addr,
withdrawAddressToken1: wallet.addr,
paymentMethod: {
type: 'signed_psbt',
signedPsbt: '<base64-encoded PSBT>',
},
});Swap BTC → Rune
Swap BTC for Rune tokens in a Saturn pool-exact‐in swap (you specify BTC in, receive ≥ Rune out).
- Exact‐In Swap: Trade
amountInBTC (sats) for at leastamountOutRune tokens. - Fee Handling: All fees are paid via the BTC inputs in the PSBT; no separate fee parameter.
PSBT Method: buildBtcToRunePsbt
Constructs a PSBT funding the swap and selecting the best shards to source Rune.
What it does:
- Validates your pool & wallet state and requested amounts.
- Fetches pool info & sharding metadata from the indexer.
- Selects shards to remove Rune from (
amountOut). - Splits & adjusts Rune amounts per‐shard to avoid on‐chain limits.
- Builds a PSBT with:
- Outputs to each shard PDA for state update
- Pointer output for program‐side Rune accounting
- Rune output to your address (
amountOut) - BTC funding input(s) to cover
amountIn+ dust + fees
- Returns the raw PSBT, its input UTXOs, and the list of shard pubkeys.
Request object: BtcToRunePsbtRequest
| Field | Type | Description |
| ------------------ | --------------------- | --------------------------------------- |
| runeAddress | string | Your Bitcoin address holding BTC UTXOs |
| runePublicKey | string | X-only hex pubkey for your Arch account |
| paymentAddress | string \| null | (unused for BTC→Rune; pass null) |
| paymentPublicKey | string \| undefined | (unused; pass undefined) |
| poolId | string | Pubkey of the target pool |
| amountIn | bigint | BTC to swap in (sats) |
| amountOut | bigint | Minimum Rune to receive |
| feeRate | bigint | Fee rate (sats per vbyte) |
Example of usage:
const { tx, shardPubkeys } = await sdk.oneToZeroSwap.buildBtcToRunePsbt({
runeAddress: wallet.address,
runePublicKey: xOnlyHex,
paymentAddress: null,
paymentPublicKey: undefined,
poolId: 'pool123…',
amountIn: BigInt(1_000_000), // 0.01 BTC
amountOut: BigInt(500), // 500 Rune
feeRate: BigInt(10), // 10 sats/vbyte
});Message Creation: swapMessage
Serializes the swap instruction, embedding your signed PSBT.
| Field | Type | Description |
| ---------------- | ---------------- | ---------------------------------------------- |
| runeAddress | string | Your Bitcoin address (same as PSBT inputs) |
| runePublicKey | string | X-only hex pubkey |
| paymentAddress | string \| null | (unused; pass null) |
| randomNumber | number | 1-byte nonce |
| feeRate | bigint | Fee rate (sats per vbyte) |
| poolId | string | Pool pubkey |
| amountIn | bigint | BTC in (sats) |
| amountOut | bigint | Rune out |
| exactIn | boolean | true = exact‐in swap |
| signedPsbt | string | Base64‐encoded signed PSBT |
| shardPubkeys | string[] | Shard pubkeys returned by buildBtcToRunePsbt |
Example of usage:
const { message, utxosInfo, splitRuneInputs } =
await sdk.oneToZeroSwap.swapMessage({
runeAddress: wallet.address,
runePublicKey: xOnlyHex,
paymentAddress: null,
randomNumber: 0,
feeRate: BigInt(10),
poolId: 'pool123…',
amountIn: BigInt(1_000_000),
amountOut: BigInt(500),
exactIn: true,
signedPsbt: signedPsbtBase64,
shardPubkeys, // from PSBT step
});Swap Rune → BTC
Swap Rune tokens for BTC in a Saturn pool—exact‐in or exact‐out swap (you specify Rune in, receive ≥ BTC out).
- Exact‐In Swap: Trade
amountInRune for at leastamountOutBTC (sats). - Fee Handling: Fees paid via BTC inputs in the final PSBT; split Rune PSBT may be needed to consolidate inputs.
PSBT Method: buildRuneToBtcPsbt
Builds the main swap PSBT, consuming a single Rune UTXO (possibly from split) and funding the BTC output.
| Field | Type | Description |
| ------------------ | --------------------- | ----------------------------------------------------------- |
| runeAddress | string | Your Bitcoin address holding Rune UTXOs |
| runePublicKey | string | X-only hex public key |
| paymentAddress | string \| null | (unused; pass null) |
| paymentPublicKey | string \| undefined | (unused; pass undefined) |
| amountIn | bigint | Rune to swap in |
| amountOut | bigint | Minimum BTC to receive (sats) |
| exactIn | boolean | true = exact‐in swap |
| feeRate | bigint | Fee rate (sats per vbyte) |
| poolId | string | Pubkey of the target pool |
| splitRunePsbt | string \| undefined | Base64 split‐PSBT from buildSplitRunePsbt, or undefined |
Example of usage - may return splitUtxoTx:
let { tx: psbt, splitUtxoTx } = await sdk.zeroToOneSwap.buildRuneToBtcPsbt({
runeAddress,
runePublicKey,
paymentAddress: null,
paymentPublicKey: undefined,
amountIn: BigInt(1_000), // 1,000 Rune
amountOut: BigInt(50_000), // 50,000 sats
exactIn: true,
feeRate: BigInt(5),
poolId: 'pool123…',
splitRunePsbt: undefined,
});PSBT Split Method: buildSplitRunePsbt
Splits Rune UTXOs to prepare a single‐UTXO input for the swap PSBT.
| Field | Type | Description |
| ------------------ | --------------------- | ----------------------------------------- |
| runeAddress | string | Your Bitcoin address holding Rune UTXOs |
| runePublicKey | string | X-only hex public key for signing |
| paymentWallet | Wallet \| undefined | (unused here; always undefined) |
| paymentPublicKey | string \| undefined | (unused; pass same as runePublicKey) |
| collectionUtxos | CollectionUtxo[] | Rune UTXOs from your wallet |
| collection | Collection | Collection metadata for Rune |
| amountIn | bigint | Rune amount to swap |
| feeRate | bigint | Fee rate (sats per vbyte) |
| runeToBtcTxVsize | number | Estimated vsize of final swap transaction |
Example of usage - if splitUtxoTx present, sign & re-build:
if (splitUtxoTx) {
const signedSplit = signer.signTransaction(
wallet.address,
splitUtxoTx.tx.psbt,
splitUtxoTx.tx.inputs,
);
const splitBase64 = Buffer.from(signedSplit.toPSBT()).toString('base64');
const result = await sdk.zeroToOneSwap.buildRuneToBtcPsbt({
runeAddress,
runePublicKey,
paymentAddress: null,
paymentPublicKey: undefined,
amountIn: BigInt(1_000),
amountOut: BigInt(50_000),
exactIn: true,
feeRate: BigInt(5),
poolId: 'pool123…',
splitRunePsbt: splitBase64,
});
psbt = result.tx;
splitUtxoTx = result.splitUtxoTx;
}Message Creation: swapMessage
Serializes the swap instruction, embedding your signed PSBT(s).
| Field | Type | Description |
| ---------------- | ---------------- | ----------------------------------------- |
| runeAddress | string | Your Bitcoin address (PSBT input owner) |
| runePublicKey | string | X-only hex pubkey |
| paymentAddress | string \| null | (unused; pass null) |
| randomNumber | number | 1-byte nonce |
| feeRate | bigint | Fee rate (sats per vbyte) |
| poolId | string | Pool pubkey |
| amountIn | bigint | Rune in |
| amountOut | bigint | BTC out (sats) |
| exactIn | boolean | true = exact‐in swap |
| signedPsbt | string | Base64‐encoded signed main PSBT |
| splitRunePsbt? | string | Base64‐encoded signed split PSBT (if any) |
Example of usage:
const message = await saturnSdk.zeroToOneSwap.swapMessage({
runeAddress: wallet.address,
runePublicKey: publicKeyHex,
paymentAddress: null,
amountIn: runeAmount,
amountOut: btcAmount,
exactIn: true,
poolId,
randomNumber: 0,
feeRate,
signedPsbt: Buffer.from(signedPsbt.toPSBT()).toString('base64'),
splitRunePsbt: signedSplitRunePsbt
? Buffer.from(signedSplitRunePsbt.toPSBT()).toString('base64')
: undefined,
});