@wuwei-labs/srsly
Version:
TypeScript SDK for SRSLY
116 lines • 4.33 kB
JavaScript
/**
* @purpose Borrower account utilities for SRSLY
*
* Fetches borrower state data from the SRSLY program.
*/
import { getBase64Encoder } from '@solana/kit';
import { fetchBorrowerState, BORROWER_STATE_DISCRIMINATOR, getBorrowerStateDecoder, } from '../generated/codama/accounts';
import { SRSLY_PROGRAM_ADDRESS } from '../generated/codama/programs/srsly';
import { getRpcUrl } from '../utils/config';
import { createRpc } from '../utils/rpc';
import { deriveBorrowerState } from '../pda';
/**
* Fetch borrower state from the SRSLY program
*
* Accepts either a borrower state PDA address OR a wallet address.
* If direct fetch fails, automatically derives the borrower state PDA
* from the address (treating it as a wallet) and retries.
*
* @param address - Borrower state address OR wallet address
* @param rpcUrl - Optional RPC endpoint URL. If not provided, uses RPC from global config
* @returns Borrower state with discounts, payment info, etc.
* @throws Error if borrower account not found or fetch fails
*
* @example
* ```typescript
* // Fetch by borrower state PDA address
* const borrower = await fetchBorrower('BorrowerStatePDA...');
*
* // Fetch by wallet address (auto-derives PDA)
* const borrower2 = await fetchBorrower('WalletAddress...');
*
* // With custom RPC
* const borrower3 = await fetchBorrower(
* 'WalletOrStateAddress...',
* 'https://api.devnet.solana.com'
* );
* ```
*/
export async function fetchBorrower(address, rpcUrl) {
// Get RPC URL from config or use provided
const resolvedRpcUrl = rpcUrl || getRpcUrl();
const rpc = createRpc(resolvedRpcUrl);
// Try direct fetch first (assumes address is borrower state PDA)
try {
const account = await fetchBorrowerState(rpc, address);
return account;
}
catch (directError) {
// Direct fetch failed - try deriving PDA from address as wallet
try {
const derivedAddress = await deriveBorrowerState(address);
const account = await fetchBorrowerState(rpc, derivedAddress);
return account;
}
catch (derivedError) {
// Both attempts failed - throw with helpful message
throw new Error(`Failed to fetch borrower state. Tried direct fetch at ${address} and derived PDA. ` +
`Error: ${derivedError.message}`);
}
}
}
/**
* Fetch all borrower state accounts from the SRSLY program
*
* Uses getProgramAccounts with a discriminator filter to find all BorrowerState accounts.
*
* @param rpcUrl - Optional RPC endpoint URL. If not provided, uses RPC from global config
* @returns Array of borrower states with their addresses
*
* @example
* ```typescript
* const borrowers = await fetchAllBorrowers();
* console.log(`Found ${borrowers.length} borrowers`);
* borrowers.forEach(b => console.log(b.address, b.data.borrower));
* ```
*/
export async function fetchAllBorrowers(rpcUrl) {
try {
const resolvedRpcUrl = rpcUrl || getRpcUrl();
const rpc = createRpc(resolvedRpcUrl);
const discriminatorBase64 = btoa(String.fromCharCode(...BORROWER_STATE_DISCRIMINATOR));
const response = await rpc
.getProgramAccounts(SRSLY_PROGRAM_ADDRESS, {
encoding: 'base64',
filters: [
{
memcmp: {
offset: 0n,
bytes: discriminatorBase64,
encoding: 'base64',
},
},
],
})
.send();
const base64Encoder = getBase64Encoder();
const decoder = getBorrowerStateDecoder();
const accounts = Array.isArray(response) ? response : response.value;
const results = [];
for (const account of accounts) {
try {
const bytes = base64Encoder.encode(account.account.data[0]);
const decoded = decoder.decode(bytes);
results.push({ data: decoded, address: account.pubkey });
}
catch {
// Skip accounts that fail to decode
}
}
return results;
}
catch (error) {
throw new Error(`Failed to fetch all borrower states: ${error.message}`);
}
}
//# sourceMappingURL=borrower.js.map