This page provides complete, working code examples for integrating Solana with OneBalance. All examples use real data from our testing environment and are copy-paste ready.
Prerequisites
Install the required dependencies:
npm install @solana/web3.js bs58
Signing Utilities
Here’s the signing function you’ll need for Solana operations:
Browser Wallet Signing
Private Key Signing
For browser wallets like Phantom or Solflare: import { MessageV0 , VersionedTransaction } from '@solana/web3.js' ;
import bs58 from 'bs58' ;
/**
* Signs a Solana operation using a browser wallet
* @param dataToSign - Base64 encoded data from quote response
* @param wallet - Connected Solana wallet (Phantom, Solflare, etc.)
* @returns Base58 encoded signature
*/
async function signSolanaOperation ( dataToSign : string , wallet : any ) : Promise < string > {
const msgBuffer = Buffer . from ( dataToSign , 'base64' );
const message = MessageV0 . deserialize ( msgBuffer );
const transaction = new VersionedTransaction ( message );
const signedTx = await wallet . signTransaction ( transaction );
return bs58 . encode ( Buffer . from ( signedTx . signatures [ signedTx . signatures . length - 1 ]));
}
For server-side operations or direct private key access: import { MessageV0 , VersionedTransaction , PublicKey } from '@solana/web3.js' ;
import bs58 from 'bs58' ;
/**
* Signs a Solana operation with a private key
* @param accountAddress - Your Solana account address
* @param privateKey - Your private key in base58 format
* @param chainOp - Chain operation from quote response
* @returns Signed chain operation
*/
function signSolanaChainOperation ( accountAddress : string , privateKey : string , chainOp : any ) {
const msgBuffer = Buffer . from ( chainOp . dataToSign , 'base64' );
const message = MessageV0 . deserialize ( msgBuffer );
const transaction = new VersionedTransaction ( message );
const decodedKey = bs58 . decode ( privateKey );
transaction . sign ([{
publicKey: new PublicKey ( accountAddress ),
secretKey: Buffer . from ( decodedKey ),
}]);
const signature = bs58 . encode ( Buffer . from ( transaction . signatures [ transaction . signatures . length - 1 ]));
return { ... chainOp , signature };
}
Example 1: SOL → USDC (Same Chain)
The simplest Solana operation - swap SOL to USDC within Solana:
Request Quote
Execute Quote
curl -X POST 'https://be.onebalance.io/api/v3/quote' \
-H 'Content-Type: application/json' \
-H 'x-api-key: 42bb629272001ee1163ca0dbbbc07bcbb0ef57a57baf16c4b1d4672db4562c11' \
-d '{
"from": {
"accounts": [{
"type": "solana",
"accountAddress": "J5CCzBULFax899tcirb6wMbenQUd8whbaetG7EfSick5"
}],
"asset": {
"assetId": "solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp/slip44:501"
},
"amount": "10000000"
},
"to": {
"asset": {
"assetId": "solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp/token:EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v"
}
}
}'
// Sign the Solana operation
const solanaOperation = quote . originChainsOperations . find ( op => op . type === 'solana' );
const signature = await signSolanaOperation ( solanaOperation . dataToSign , wallet );
// Add signature to the quote
const signedQuote = {
... quote ,
originChainsOperations: quote . originChainsOperations . map ( op =>
op . type === 'solana' ? { ... op , signature } : op
)
};
// Execute the quote
const executeResponse = await fetch ( 'https://be.onebalance.io/api/v3/quote/execute' , {
method: 'POST' ,
headers: {
'Content-Type' : 'application/json' ,
'x-api-key' : '42bb629272001ee1163ca0dbbbc07bcbb0ef57a57baf16c4b1d4672db4562c11'
},
body: JSON . stringify ( signedQuote )
});
const result = await executeResponse . json ();
console . log ( 'Swap completed:' , result );
Successfully swapped 0.01 SOL to ~1.63 USDC on Solana
Example 2: SOL → USDC (Cross-Chain)
Swap SOL on Solana to USDC on Arbitrum - the most common cross-chain pattern:
Request Quote
Quote Response
Execute Quote
curl -X POST 'https://be.onebalance.io/api/v3/quote' \
-H 'Content-Type: application/json' \
-H 'x-api-key: 42bb629272001ee1163ca0dbbbc07bcbb0ef57a57baf16c4b1d4672db4562c11' \
-d '{
"from": {
"accounts": [{
"type": "solana",
"accountAddress": "J5CCzBULFax899tcirb6wMbenQUd8whbaetG7EfSick5"
}],
"asset": {
"assetId": "solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp/slip44:501"
},
"amount": "10000000"
},
"to": {
"asset": {
"assetId": "eip155:42161/erc20:0xaf88d065e77c8cC2239327C5EDb3A432268e5831"
},
"account": "eip155:42161:0x895Cf62399bF1F8b88195E741b64278b41EB7F09"
}
}'
{
"id" : "0xcd3a5cfe80d1b84db755bfb8ebe0a617ff153cc48ab6d5ab28436386f06ce100" ,
"accounts" : [{
"type" : "solana" ,
"accountAddress" : "J5CCzBULFax899tcirb6wMbenQUd8whbaetG7EfSick5"
}],
"originToken" : {
"assetType" : [ "solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp/slip44:501" ],
"amount" : "10000000" ,
"fiatValue" : "1.67"
},
"destinationToken" : {
"assetType" : "eip155:42161/erc20:0xaf88d065e77c8cC2239327C5EDb3A432268e5831" ,
"amount" : "1570450" , // ~1.57 USDC on Arbitrum
"minimumAmount" : "1516171" ,
"fiatValue" : "1.57" ,
"recipientAccount" : "eip155:42161:0x895Cf62399bF1F8b88195E741b64278b41EB7F09"
},
"fees" : {
"cumulativeUSD" : "0.12"
}
}
// Sign and execute the cross-chain operation
const solanaOp = quote . originChainsOperations . find ( op => op . type === 'solana' );
const signedOp = await signSolanaOperation ( solanaOp . dataToSign , wallet );
const executeRequest = {
... quote ,
originChainsOperations: [{ ... solanaOp , signature: signedOp }]
};
const result = await fetch ( 'https://be.onebalance.io/api/v3/quote/execute' , {
method: 'POST' ,
headers: {
'Content-Type' : 'application/json' ,
'x-api-key' : '42bb629272001ee1163ca0dbbbc07bcbb0ef57a57baf16c4b1d4672db4562c11'
},
body: JSON . stringify ( executeRequest )
});
const execution = await result . json ();
console . log ( 'Cross-chain swap completed:' , execution );
Successfully swapped 0.01 SOL to 1.57 USDC and bridged to Arbitrum
Example 3: USDC (Solana) → USDC (Arbitrum)
Transfer USDC from Solana to Arbitrum:
curl -X POST 'https://be.onebalance.io/api/v3/quote' \
-H 'Content-Type: application/json' \
-H 'x-api-key: 42bb629272001ee1163ca0dbbbc07bcbb0ef57a57baf16c4b1d4672db4562c11' \
-d '{
"from": {
"accounts": [{
"type": "solana",
"accountAddress": "J5CCzBULFax899tcirb6wMbenQUd8whbaetG7EfSick5"
}],
"asset": {
"assetId": "solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp/token:EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v"
},
"amount": "1000000"
},
"to": {
"asset": {
"assetId": "eip155:42161/erc20:0xaf88d065e77c8cC2239327C5EDb3A432268e5831"
},
"account": "eip155:42161:0x895Cf62399bF1F8b88195E741b64278b41EB7F09"
}
}'
This operation only requires a Solana account since funds come entirely from Solana. The recipient is specified in to.account.
Example 4: Aggregated USDC → SOL (Multi-Account)
Use aggregated USDC balance from both EVM and Solana accounts to buy SOL:
Multi-Account Request
Multi-Account Signing
curl -X POST 'https://be.onebalance.io/api/v3/quote' \
-H 'Content-Type: application/json' \
-H 'x-api-key: 42bb629272001ee1163ca0dbbbc07bcbb0ef57a57baf16c4b1d4672db4562c11' \
-d '{
"from": {
"accounts": [
{
"type": "kernel-v3.1-ecdsa",
"accountAddress": "0xd4f5A60c9b500f875ADf757BC3027A4424079E05",
"deploymentType": "ERC4337",
"signerAddress": "0x9b747cC14A5672a7166b4eccdc92d7F4003f8081"
},
{
"type": "solana",
"accountAddress": "J5CCzBULFax899tcirb6wMbenQUd8whbaetG7EfSick5"
}
],
"asset": {
"assetId": "ob:usdc"
},
"amount": "10000000"
},
"to": {
"asset": {
"assetId": "solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp/slip44:501"
}
}
}'
This operation involves both EVM and Solana accounts: async function signMultiAccountQuote ( quote : any , solanaWallet : any , evmSigner : any ) {
const signedOperations = await Promise . all (
quote . originChainsOperations . map ( async ( operation : any ) => {
if ( operation . type === 'solana' ) {
const signature = await signSolanaOperation ( operation . dataToSign , solanaWallet );
return { ... operation , signature };
} else {
// Sign EVM operation with typed data
const signature = await evmSigner . signTypedData ( operation . typedDataToSign );
return {
... operation ,
userOp: { ... operation . userOp , signature }
};
}
})
);
return {
... quote ,
originChainsOperations: signedOperations
};
}
// Execute the multi-account operation
const signedQuote = await signMultiAccountQuote ( quote , solanaWallet , evmSigner );
const result = await fetch ( 'https://be.onebalance.io/api/v3/quote/execute' , {
method: 'POST' ,
headers: {
'Content-Type' : 'application/json' ,
'x-api-key' : '42bb629272001ee1163ca0dbbbc07bcbb0ef57a57baf16c4b1d4672db4562c11'
},
body: JSON . stringify ( signedQuote )
});
const execution = await result . json ();
console . log ( 'Aggregated swap completed:' , execution );
Used aggregated USDC from multiple chains to purchase SOL
This example shows OneBalance’s power - using funds from multiple blockchains in a single operation.
Check Balances
Always verify your balances before creating quotes:
cURL - Single Account
cURL - Multi-Account
TypeScript
curl -X GET 'https://be.onebalance.io/api/v3/balances/aggregated-balance?account=solana:J5CCzBULFax899tcirb6wMbenQUd8whbaetG7EfSick5' \
-H 'x-api-key: 42bb629272001ee1163ca0dbbbc07bcbb0ef57a57baf16c4b1d4672db4562c11'
Quick Error Handling
Validate Account
Check Quote Status
import { PublicKey } from '@solana/web3.js' ;
// Ensure Solana address is valid before making requests
try {
new PublicKey ( accountAddress );
} catch ( error ) {
throw new Error ( 'Invalid Solana address format' );
}
Next Steps
Contract Calls Use Solana assets to fund smart contract calls on EVM chains
Troubleshooting Common issues and solutions for Solana integration
API Reference Complete API documentation for v3 endpoints
Solana Overview Concepts and setup guide for Solana integration
For additional support, use the Intercom chat widget in the bottom right corner, join our Discord , or reach out via support .