Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.rebelfi.io/docs/llms.txt

Use this file to discover all available pages before exploring further.

EVM Integration (Ethereum, Polygon, Base)

On EVM chains, the signing and submission flow differs from Solana. This guide covers the key differences.

Multi-Transaction Operations

On EVM chains, supply operations return two transactions that must be signed and submitted in order:
  1. Approve transaction — Authorizes the protocol to spend your USDC
  2. Supply transaction — Deposits USDC into the yield strategy

Unsigned Transaction Format

EVM unsigned transactions are returned as JSON objects with these fields:
FieldTypeDescription
tostringContract/recipient address
datastringEncoded call data (hex string)
valuestringNative token value in wei (usually '0')
gasLimitstringGas limit
maxFeePerGasstringEIP-1559 max fee per gas
maxPriorityFeePerGasstringEIP-1559 priority fee per gas
noncenumberTransaction nonce
chainIdnumberChain ID for replay protection

Signing with ethers.js

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

const client = new RebelfiClient({ apiKey: process.env.REBELFI_API_KEY });

// 1. Plan the supply
const operation = await client.operations.supply({
  walletAddress: '0xYourWalletAddress',
  strategyId: strategy.strategyId,
  amount: '1000000', // 1 USDC
  tokenAddress: strategy.tokenAddress
});

// 2. Sign and submit each transaction in order
for (const tx of operation.transactions) {
  const wallet = new ethers.Wallet(privateKey, provider);
  const signedTx = await wallet.signTransaction({
    to: tx.to,
    data: tx.data,
    value: tx.value || '0x0',
    gasLimit: tx.gasLimit,
    maxFeePerGas: tx.maxFeePerGas,
    maxPriorityFeePerGas: tx.maxPriorityFeePerGas,
    nonce: tx.nonce,
    chainId: tx.chainId
  });

  // Submit to RebelFi
  await client.transactions.submitSigned({
    operationId: operation.operationId,
    transactionId: tx.id, // Required for multi-tx operations
    signedTransaction: signedTx // Hex-encoded
  });
}

Key Differences from Solana

SolanaEVM
Transactions per supply12 (approve + supply)
Transaction formatBase64-encodedHex-encoded
transactionId on submitOptionalRequired
Gas tokenSOLETH / POL / ETH (Base)
The transactionId parameter is required when submitting EVM transactions because operations contain multiple transactions. It tells RebelFi which transaction you are submitting. For Solana single-transaction operations, it is optional.

Complete EVM Example

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

const client = new RebelfiClient({ apiKey: process.env.REBELFI_API_KEY });
const provider = new ethers.JsonRpcProvider('https://polygon-mainnet.infura.io/v3/YOUR_KEY');
const signer = new ethers.Wallet(process.env.PRIVATE_KEY, provider);

async function supplyOnEVM(walletAddress: string, strategyId: number, amount: string, tokenAddress: string) {
  // Plan the supply
  const operation = await client.operations.supply({
    walletAddress,
    strategyId,
    amount,
    tokenAddress
  });

  console.log(`Operation ${operation.operationId}: ${operation.transactions.length} transactions`);

  // Sign and submit each transaction sequentially
  for (const tx of operation.transactions) {
    console.log(`Signing: ${tx.description}`);

    const signedTx = await signer.signTransaction({
      to: tx.to,
      data: tx.data,
      value: tx.value || '0x0',
      gasLimit: tx.gasLimit,
      maxFeePerGas: tx.maxFeePerGas,
      maxPriorityFeePerGas: tx.maxPriorityFeePerGas,
      nonce: tx.nonce,
      chainId: tx.chainId
    });

    await client.transactions.submitSigned({
      operationId: operation.operationId,
      transactionId: tx.id,
      signedTransaction: signedTx
    });

    console.log(`Submitted: ${tx.description}`);
  }

  // Wait for confirmation
  const start = Date.now();
  while (Date.now() - start < 120_000) {
    const op = await client.operations.get(operation.operationId);
    if (op.status === 'CONFIRMED') {
      console.log('Supply confirmed!');
      return op;
    }
    if (op.status === 'FAILED') {
      throw new Error(op.transactions[0]?.error || 'Operation failed');
    }
    await new Promise(r => setTimeout(r, 3000));
  }
  throw new Error('Timeout waiting for confirmation');
}

Next Steps

Wallet Profiles

Configure EVM chains in your wallet profile

Fireblocks Integration

Sign EVM transactions with Fireblocks custody

Integration Tutorial

Complete E2E walkthrough