Skip to main content

Earn Deposit with API

1

Import Dependencies

Import the required packages for Solana RPC communication, transaction handling, and Kamino SDK utilities.
import {
  createSolanaRpc,
  createSolanaRpcSubscriptions,
  pipe,
  getTransactionDecoder,
  getCompiledTransactionMessageDecoder,
  decompileTransactionMessageFetchingLookupTables,
  setTransactionMessageFeePayerSigner,
  setTransactionMessageLifetimeUsingBlockhash,
  addSignersToTransactionMessage,
  signTransactionMessageWithSigners,
  sendAndConfirmTransactionFactory,
  getSignatureFromTransaction,
} from '@solana/kit';
import { parseKeypairFile } from '@kamino-finance/klend-sdk/dist/utils/signer.js';
2

Configure and Initialize

Set up the configuration and initialize RPC connections.
const KEYPAIR_FILE = '/path/to/your/keypair.json';
const API_BASE_URL = 'https://api.kamino.finance';

const signer = await parseKeypairFile(KEYPAIR_FILE);
const rpc = createSolanaRpc('https://api.mainnet-beta.solana.com');
const rpcSubscriptions = createSolanaRpcSubscriptions('wss://api.mainnet-beta.solana.com');
3

Call Kamino API

Make a POST request to the Kamino API to build the deposit transaction.
const response = await fetch(`${API_BASE_URL}/ktx/kvault/deposit`, {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({
    wallet: signer.address,
    kvault: 'HDsayqAsDWy3QvANGqh2yNraqcD8Fnjgh73Mhb3WRS5E',
    amount: '1.0',
  }),
});

if (!response.ok) {
  const error = await response.json();
  throw new Error(`API error: ${error.message}`);
}

const { transaction: encodedTransaction } = await response.json();
The API returns a pre-built transaction encoded in base64 format. This transaction includes Address Lookup Tables (ALTs) for efficiency.
4

Decode Transaction

Decode the base64-encoded transaction and extract the message bytes.
const txBuffer = Buffer.from(encodedTransaction, 'base64');
const txMessageBytes = getTransactionDecoder().decode(txBuffer).messageBytes;

const compiledMessage = getCompiledTransactionMessageDecoder().decode(txMessageBytes);
5

Resolve Address Lookup Tables

Fetch and resolve the Address Lookup Tables from the blockchain.
const { value: latestBlockhash } = await rpc.getLatestBlockhash({ commitment: 'finalized' }).send();

const signedTransaction = await pipe(
  await decompileTransactionMessageFetchingLookupTables(compiledMessage, rpc),
  (tx) => setTransactionMessageLifetimeUsingBlockhash(latestBlockhash, tx),
  (tx) => setTransactionMessageFeePayerSigner(signer, tx),
  (tx) => addSignersToTransactionMessage([signer], tx),
  (tx) => signTransactionMessageWithSigners(tx)
);
decompileTransactionMessageFetchingLookupTables fetches the lookup table data from the blockchain and resolves all address references. This is required for transactions that use ALTs.
A fresh blockhash is fetched and set to ensure the transaction remains valid.
6

Send and Confirm Transaction

Submit the signed transaction to the Solana network.
const signature = getSignatureFromTransaction(signedTransaction);

console.log(`Sending transaction with signature: ${signature}`);

await sendAndConfirmTransactionFactory({ rpc, rpcSubscriptions })(signedTransaction, {
  commitment: 'confirmed',
  skipPreflight: true,
});

console.log('Deposit successful! Signature:', signature);
Your deposit is complete! The API built the transaction, you signed it locally (keeping your keys secure), and it was successfully submitted to the network.