Skip to main content

Prerequisites

  • Node.js 18+ or Bun
  • A RebelFi API key (get one here)
  • A Solana wallet for testing

Installation

npm install @rebelfi/sdk

Initialize the Client

import { RebelfiClient } from '@rebelfi/sdk';

const client = new RebelfiClient({
  apiKey: process.env.REBELFI_API_KEY
});
Store your API key securely. Never commit it to version control or expose it in client-side code.

Register a Wallet

Before supplying, register the user’s wallet:
const wallet = await client.wallets.register({
  walletAddress: 'YourSolanaWalletAddress',
  blockchain: 'solana',
  userId: 'your-internal-user-id' // optional
});

console.log('Wallet ID:', wallet.walletId);
Registration is idempotent — calling it again returns the existing wallet.

List Available Venues

Query available yield venues and their strategies:
const { venues } = await client.venues.list({
  blockchain: 'solana',
  token: 'USDC'
});

console.log(`Found ${venues.length} venues`);

for (const venue of venues) {
  console.log(`\n${venue.name} (${venue.protocol})`);
  for (const strategy of venue.strategies) {
    console.log(`  ${strategy.name}: ${(strategy.apy * 100).toFixed(2)}% APY`);
  }
}
Example output:
Found 2 venues

Kamino (kamino)
  USDC Vault: 8.50% APY

Drift (drift)
  USDC Lending: 7.20% APY

Plan a Supply Operation

Select a strategy and plan a supply operation:
// Pick a strategy
const venue = venues[0];
const strategy = venue.strategies[0];

// Plan the supply operation (use walletId from registration)
const operation = await client.operations.supply({
  walletId: wallet.walletId,
  strategyId: strategy.strategyId,
  amount: '1000000',  // 1 USDC (6 decimals)
  tokenAddress: strategy.tokenAddress
});

console.log('Operation ID:', operation.operationId);
console.log('Status:', operation.status);
console.log('Expires at:', operation.expiresAt);

// Get the unsigned transaction
const tx = operation.transactions[0];
console.log('Transaction to sign:', tx.unsignedTransaction);
Operations expire after a short time (typically 5 minutes). Make sure to sign and submit promptly.

Sign and Submit

After the user signs the transaction:
// Option 1: You broadcast the transaction and submit the hash
const txHash = await broadcastTransaction(signedTx);

await client.transactions.submitHash({
  operationId: operation.operationId,
  txHash
});

// Option 2: Let RebelFi broadcast for you
await client.transactions.submitSigned({
  operationId: operation.operationId,
  signedTransaction: signedTxBase64
});

Check Operation Status

Poll for confirmation:
const checkStatus = async (operationId: number) => {
  const op = await client.operations.get(operationId);
  console.log(`Status: ${op.status}`);

  if (op.status === 'confirmed') {
    console.log('Supply confirmed!');
    return true;
  }

  if (op.status === 'failed') {
    const tx = op.transactions[0];
    console.error('Failed:', tx.error);
    return false;
  }

  if (op.status === 'cancelled') {
    console.log('Operation was cancelled');
    return false;
  }

  return null; // Still pending
};

// Poll every 2 seconds
const pollInterval = setInterval(async () => {
  const result = await checkStatus(operation.operationId);
  if (result !== null) {
    clearInterval(pollInterval);
  }
}, 2000);

View Allocations

After supply is confirmed, check the allocation:
const { allocations, totalValue, totalYieldEarned } = await client.allocations.list({
  walletId: wallet.walletId
});

console.log(`Total value: ${totalValue}`);
console.log(`Total yield earned: ${totalYieldEarned}`);

for (const allocation of allocations) {
  console.log(`\n${allocation.venueName} - ${allocation.strategyName}`);
  console.log(`  Principal: ${allocation.principal}`);
  console.log(`  Current value: ${allocation.currentValue}`);
  console.log(`  Yield earned: ${allocation.yieldEarned}`);
}

Complete Example

import { RebelfiClient, RebelfiError, ErrorCode } from '@rebelfi/sdk';

async function supplyToYield(walletAddress: string, amount: string) {
  const client = new RebelfiClient({
    apiKey: process.env.REBELFI_API_KEY
  });

  try {
    // 1. Find a strategy
    const { venues } = await client.venues.list({
      blockchain: 'solana',
      token: 'USDC'
    });

    if (venues.length === 0) {
      throw new Error('No venues available');
    }

    const strategy = venues[0].strategies[0];
    console.log(`Using ${venues[0].name} - ${strategy.name}`);

    // 2. Register wallet & plan supply
    const wallet = await client.wallets.register({
      walletAddress,
      blockchain: 'solana'
    });

    const operation = await client.operations.supply({
      walletId: wallet.walletId,
      strategyId: strategy.strategyId,
      amount,
      tokenAddress: strategy.tokenAddress
    });

    console.log(`Operation ${operation.operationId} created`);

    // 3. Return unsigned transaction for signing
    return {
      operationId: operation.operationId,
      unsignedTransaction: operation.transactions[0].unsignedTransaction,
      expiresAt: operation.expiresAt
    };
  } catch (error) {
    if (error instanceof RebelfiError) {
      if (error.is(ErrorCode.INSUFFICIENT_BALANCE)) {
        console.error('Wallet has insufficient balance');
      } else if (error.is(ErrorCode.STRATEGY_NOT_ACTIVE)) {
        console.error('Strategy is currently paused');
      } else {
        console.error(`API error: ${error.message} (${error.code})`);
      }
    }
    throw error;
  }
}

Next Steps