Affiliate Fee Integration Guide

Overview

The Affiliate Fee feature allows partners to earn a commission on swap transactions. When a user performs a swap through your platform, a percentage of the input amount is distributed to a designated affiliate recipient address.

This guide explains how to integrate the Affiliate Fee feature into your frontend application, including the calculation formulas and API integration steps.


Table of Contents


Understanding Affiliate Fee

Key Concepts

  • Affiliate Fee: A commission paid to a partner (affiliate) for facilitating a swap transaction

  • Basis Points (bps): Fee rate expressed in basis points (1% = 10,000 bps, 0.1% = 1,000 bps)

  • Fee Recipient: The Bitcoin address that receives the affiliate fee

  • Input Token: The token being swapped FROM (e.g., RUNE or BTC)

  • Output Token: The token being swapped TO (e.g., BTC or RUNE)

How It Works

  1. RUNE → BTC Swap: Affiliate receives RUNE tokens

    • Fee is deducted from the input RUNE amount

    • Affiliate receives RUNE via Runestone edict

    • Pool receives the remaining RUNE amount

  2. BTC → RUNE Swap: Affiliate receives BTC

    • Fee is deducted from the input BTC amount

    • Affiliate receives BTC directly

    • Pool receives the remaining BTC amount

Important Rules

  • Affiliate fee is always calculated on the input token amount

  • Affiliate fee is deducted before the swap calculation

  • The pool receives amountIn - affiliateFee for the swap

  • amountOut is calculated based on the pool's received amount (not the original amountIn)


Fee Calculation Formula

Basic Formula

Where:

  • amountIn: Original input amount (in smallest unit: sats for BTC, base units for RUNE)

  • partnerFeeBps: Affiliate fee rate in basis points (0-1,000,000)

  • affiliateFeeAmount: Calculated fee amount (rounded down)

  • poolAmountIn: Amount that the pool actually receives for the swap

Examples

Example 1: RUNE → BTC Swap

  • amountIn: 1,000,000 RUNE

  • partnerFeeBps: 10,000 (1%)

  • Calculation:

  • Result: Affiliate receives 10,000 RUNE, pool receives 990,000 RUNE for swap

Example 2: BTC → RUNE Swap

  • amountIn: 1,000,000 sats (0.01 BTC)

  • partnerFeeBps: 5,000 (0.5%)

  • Calculation:

  • Result: Affiliate receives 5,000 sats, pool receives 995,000 sats for swap

Minimum Fee Requirements

  • RUNE → BTC: Minimum 1 RUNE (if calculated fee < 1, transaction will fail)

  • BTC → RUNE: Minimum 546 sats (if calculated fee < 546, it will be set to 546 sats automatically)


Amount Calculation with Affiliate Fee

Important: Affiliate Fee is Deducted from Input

Key Point: The affiliate fee is deducted from amountIn before the swap calculation. The pool receives the remaining amount after the fee deduction.

Calculation Flow

  1. Calculate affiliate fee from amountIn:

  2. Calculate pool input (amount that actually goes into the pool):

  3. Calculate amountOut based on poolAmountIn (not the original amountIn):

Example

Scenario: User swaps 100 sats BTC with 1% affiliate fee (10,000 bps)

Result:

  • Affiliate receives: 1 sat

  • Pool receives: 99 sats for swap

  • User receives: amountOut calculated from 99 sats


Transaction Flow

The complete transaction flow consists of two steps:

  1. Create Transaction (POST /transactions): Get the unsigned PSBT

  2. Sign and Broadcast (POST /transactions/sign): Sign the PSBT and broadcast to network

Step 1: Create Transaction

The first step creates an unsigned Partially Signed Bitcoin Transaction (PSBT) that the user needs to sign.

Step 2: Sign and Broadcast

After receiving the PSBT, the frontend must:

  1. Sign the PSBT using the user's private key for inputs specified in userInputIndexes

  2. Send the signed transaction back to the backend via /transactions/sign endpoint

  3. Backend validates and broadcasts the transaction to the Bitcoin network


API Integration

Endpoint 1: Create Transaction

Authentication

All requests require JWT authentication via Authorization: Bearer <token> header.

Request Body

Parameters

Parameter
Type
Required
Description

tokens

string[]

Yes

Array of 2 token IDs: [tokenInId, tokenOutId]

amountIn

string

Yes

Input amount in smallest unit (sats for BTC, base units for RUNE)

amountOut

string

Yes

Expected output amount in smallest unit

feeRates

number[]

Yes

Pool fee rates (e.g., [3000] for 0.3%)

isExactIn

boolean

Optional

true for exact input, false for exact output (default: true)

partnerFeeBps

number

Optional

Affiliate fee in basis points (0-1,000,000). Required if partnerFeeRecipient is provided

partnerFeeRecipient

string

Optional

Bitcoin address to receive affiliate fee. Required if partnerFeeBps is provided

userAddress

string

Optional

User's Bitcoin address (from JWT if omitted)

Validation Rules

  1. If partnerFeeBps is provided, partnerFeeRecipient is required

  2. If partnerFeeRecipient is provided, partnerFeeBps is required

  3. partnerFeeRecipient cannot be the same as:

    • Pool address

    • User's trading address

  4. For RUNE → BTC: Minimum affiliate fee is 1 RUNE

  5. For BTC → RUNE: Minimum affiliate fee is 546 sats (auto-adjusted if lower)

Response

Note: The response does not include affiliate fee information. The affiliate fee is automatically deducted and distributed during transaction execution. You can verify the affiliate fee by checking the transaction outputs after the transaction is confirmed.

Endpoint 2: Sign and Broadcast Transaction

After receiving the base64Psbt from the create transaction endpoint, you need to:

  1. Sign the PSBT on the frontend using the user's private key

    • Sign only the inputs specified in userInputIndexes array

    • Use Bitcoin signing libraries (e.g., @scure/btc-signer, bitcoinjs-lib)

  2. Send signed transaction to this endpoint

Request Body

Parameters

Parameter
Type
Required
Description

type

string

Yes

Transaction type (e.g., "SWAP")

params.signedBase64Tx

string

Yes

Base64 encoded signed transaction (PSBT after user signing)

params.userAddress

string

Optional

User's Bitcoin address (from JWT if omitted)

Response

Example Request

Example Response

Note: After successful signing and broadcast, the transaction is submitted to the Bitcoin network. The txId in the response is the final transaction ID that can be used to track the transaction on blockchain explorers.


Request/Response Examples

Note: All addresses, transaction IDs, and PSBT data in the examples below are placeholder values for demonstration purposes only. Replace them with actual values when making real API calls.

Example 1: RUNE → BTC Swap with 1% Affiliate Fee

Request:

Calculation:

  • amountIn: 1,000,000 RUNE

  • affiliateFeeAmount: floor((1,000,000 × 10,000) / 1,000,000) = 10,000 RUNE

  • poolAmountIn: 1,000,000 - 10,000 = 990,000 RUNE

  • Pool performs swap with 990,000 RUNE → calculates amountOut

Response:

Note: The txId is available immediately after the transaction is created. The base64Psbt contains the partially signed transaction that needs to be signed by the user using the indices in userInputIndexes.

Example 2: BTC → RUNE Swap with 0.5% Affiliate Fee

Request:

Calculation:

  • amountIn: 1,000,000 sats (0.01 BTC)

  • affiliateFeeAmount: floor((1,000,000 × 5,000) / 1,000,000) = 5,000 sats

  • poolAmountIn: 1,000,000 - 5,000 = 995,000 sats

  • Pool performs swap with 995,000 sats → calculates amountOut

Response:

Example 3: Swap without Affiliate Fee

Request:

Note: Simply omit partnerFeeBps and partnerFeeRecipient fields.


Error Handling

Common Errors

1. Missing Recipient

Solution: Always provide both partnerFeeBps and partnerFeeRecipient together.

2. Invalid Recipient Address

Solution: Ensure affiliate recipient is different from pool and user addresses.

3. Fee Too Small (RUNE → BTC)

Solution: Increase partnerFeeBps or amountIn to ensure minimum 1 RUNE fee.

4. Fee Too Large

Solution: Reduce partnerFeeBps or increase amountIn.

5. Insufficient Balance

Solution: Check user's balance before initiating swap.

Error Response Format

All error responses follow this structure:

  • code: Error code (string, e.g., "1006"). Success is "1", any other value indicates an error

  • message: Error message key (e.g., "common.invalidRequest")

  • name: Exception type (e.g., "BadRequestException", "HttpException")

  • error: Object containing detailed error information

    • message: Error message key

    • details: Human-readable error description

    • method: HTTP method used

    • path: API endpoint path

    • timestamp: Error timestamp


Summary

Key Takeaways

  1. Affiliate fee is deducted from input amount before swap calculation

  2. Formula: affiliateFeeAmount = floor((amountIn × partnerFeeBps) / 1,000,000)

  3. Pool receives: amountIn - affiliateFeeAmount

  4. Always provide both partnerFeeBps and partnerFeeRecipient together

  5. Minimum fees: 1 RUNE for RUNE swaps, 546 sats for BTC swaps

  6. Use backend quote API for accurate amount calculations when possible

Quick Reference

Formula:

API Request Structure:


Support

For questions or issues with affiliate fee integration, please contact the development team or refer to the main API documentation.

Last updated