UNPKG

@wuwei-labs/srsly

Version:
141 lines 4.89 kB
"use strict"; /** * @purpose Address Lookup Table utilities for SRSLY * * Provides helpers for fetching and using the SRSLY Address Lookup Table * to reduce transaction size for rental operations. */ Object.defineProperty(exports, "__esModule", { value: true }); exports.fetchLookupTable = fetchLookupTable; exports.getLookupTableAddress = getLookupTableAddress; const config_1 = require("../accounts/config"); const rpc_1 = require("./rpc"); const config_2 = require("./config"); /** * System program address used as default when ALT not configured */ const SYSTEM_PROGRAM_ID = '11111111111111111111111111111111'; /** * Fetch the SRSLY Address Lookup Table from chain * * The ALT contains static addresses used across all rental operations, * reducing transaction size by ~310 bytes when used with versioned transactions. * * @param rpcUrl - Optional RPC endpoint URL. If not provided, uses RPC from global config * @returns ALT data with addresses, or null if ALT not configured * @throws Error if fetch fails * * @example * ```typescript * // Fetch ALT using global config RPC * const alt = await fetchLookupTable(); * if (alt) { * console.log('ALT address:', alt.address); * console.log('Contains', alt.addresses.length, 'addresses'); * } * ``` */ async function fetchLookupTable(rpcUrl) { try { // Fetch config to get ALT address const config = await (0, config_1.fetchConfig)(rpcUrl); const altAddress = config.data.lookupTable; // Return null if ALT not configured (default pubkey) if (altAddress === SYSTEM_PROGRAM_ID) { return null; } // Fetch ALT account data const resolvedRpcUrl = rpcUrl || (0, config_2.getRpcUrl)(); const rpc = (0, rpc_1.createRpc)(resolvedRpcUrl); const accountInfo = await rpc.getAccountInfo(altAddress, { encoding: 'base64' }).send(); if (!accountInfo.value) { return null; } // Decode ALT data // ALT format: https://docs.solanalabs.com/implemented-proposals/address-lookup-table // Header: 56 bytes (discriminator, deactivation_slot, last_extended_slot, etc.) // Addresses: remaining bytes, 32 bytes each const data = base64ToUint8Array(accountInfo.value.data[0]); // Skip 56-byte header to get to addresses const HEADER_SIZE = 56; const ADDRESS_SIZE = 32; const addresses = []; for (let i = HEADER_SIZE; i < data.length; i += ADDRESS_SIZE) { const addressBytes = data.subarray(i, i + ADDRESS_SIZE); // Convert to base58 address string addresses.push(bs58Encode(addressBytes)); } return { address: altAddress, addresses, isActive: addresses.length > 0, }; } catch (error) { throw new Error(`Failed to fetch lookup table: ${error.message}`); } } /** * Get the ALT address from config without fetching full ALT data * * @param rpcUrl - Optional RPC endpoint URL * @returns ALT address, or null if not configured */ async function getLookupTableAddress(rpcUrl) { const config = await (0, config_1.fetchConfig)(rpcUrl); const altAddress = config.data.lookupTable; if (altAddress === SYSTEM_PROGRAM_ID) { return null; } return altAddress; } /** * Browser-compatible base64 to Uint8Array decoder * Uses atob which is available in browsers and Node.js 16+ */ function base64ToUint8Array(base64) { const binaryString = atob(base64); const bytes = new Uint8Array(binaryString.length); for (let i = 0; i < binaryString.length; i++) { bytes[i] = binaryString.charCodeAt(i); } return bytes; } /** * Simple base58 encoder for address bytes * Using a minimal implementation to avoid additional dependencies */ function bs58Encode(bytes) { const ALPHABET = '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz'; const BASE = 58; if (bytes.length === 0) return ''; // Count leading zeros let zeros = 0; while (zeros < bytes.length && bytes[zeros] === 0) { zeros++; } // Convert to base58 const input = Array.from(bytes); const encoded = []; for (const byte of input) { let carry = byte; for (let i = 0; i < encoded.length; i++) { carry += encoded[i] << 8; encoded[i] = carry % BASE; carry = Math.floor(carry / BASE); } while (carry > 0) { encoded.push(carry % BASE); carry = Math.floor(carry / BASE); } } // Add leading zeros let result = ALPHABET[0].repeat(zeros); // Convert to string (encoded is in reverse order) for (let i = encoded.length - 1; i >= 0; i--) { result += ALPHABET[encoded[i]]; } return result; } //# sourceMappingURL=lookupTable.js.map