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:
Approve transaction — Authorizes the protocol to spend your USDC
Supply transaction — Deposits USDC into the yield strategy
EVM unsigned transactions are returned as JSON objects with these fields:
Field Type Description 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
Solana EVM Transactions per supply 1 2 (approve + supply) Transaction format Base64-encoded Hex-encoded transactionId on submitOptional Required Gas token SOL ETH / 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