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
For additional support, use the Intercom chat widget in the bottom right corner, join our Discord , or reach out via support .