UNPKG

@ledgerhq/coin-stacks

Version:
236 lines 8.84 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.fetchFungibleTokenMetadataCached = exports.fetchFungibleTokenMetadata = exports.fetchNonce = exports.fetchFullMempoolTxs = exports.fetchMempoolTransactionsPage = exports.broadcastTx = exports.fetchFullTxs = exports.fetchAllTransactions = exports.fetchTransactionsPage = exports.fetchBlockHeight = exports.fetchEstimatedFees = exports.fetchAllTokenBalances = exports.fetchTokenBalancesPage = exports.fetchBalances = exports.StacksNetwork = void 0; const live_env_1 = require("@ledgerhq/live-env"); const network_1 = __importDefault(require("@ledgerhq/live-network/network")); const transformers_1 = require("./transformers"); const cache_1 = require("@ledgerhq/live-network/cache"); const network_2 = require("@stacks/network"); exports.StacksNetwork = { mainnet: new network_2.StacksMainnet({ url: (0, live_env_1.getEnv)("API_STACKS_ENDPOINT") }), testnet: new network_2.StacksTestnet(), }; /** * Builds the Stacks API URL with an optional path */ const getStacksURL = (path) => { const baseUrl = (0, live_env_1.getEnv)("API_STACKS_ENDPOINT"); if (!baseUrl) throw new Error("API base URL not available"); return `${baseUrl}${path ? path : ""}`; }; /** * Basic GET request to the Stacks API */ const fetch = async (path) => { const url = getStacksURL(path); // We force data to this way as network func is not using the correct param type. Changing that func will generate errors in other implementations const opts = { method: "GET", url, }; const rawResponse = await (0, network_1.default)(opts); // We force data to this way as network func is not using the correct param type. Changing that func will generate errors in other implementations const { data } = rawResponse; return data; }; /** * Basic POST request with JSON data to the Stacks API */ const send = async (path, data) => { const url = getStacksURL(path); const opts = { method: "POST", url, data: JSON.stringify(data), headers: { "Content-Type": "application/json" }, }; const rawResponse = await (0, network_1.default)(opts); // We force data to this way as network func is not using generics. Changing that func will generate errors in other implementations const { data: responseData } = rawResponse; return responseData; }; /** * Basic POST request with raw binary data to the Stacks API */ const sendRaw = async (path, data) => { const url = getStacksURL(path); const opts = { method: "POST", url, data, headers: { "Content-Type": "application/octet-stream" }, }; const rawResponse = await (0, network_1.default)(opts); // We force data to this way as network func is not using generics. Changing that func will generate errors in other implementations const { data: responseData } = rawResponse; return responseData; }; /** * Fetches STX balance for an address */ const fetchBalances = async (addr) => { const data = await fetch(`/extended/v1/address/${addr}/stx`); return data; }; exports.fetchBalances = fetchBalances; /** * Fetches a page of token balances for an address */ const fetchTokenBalancesPage = async (addr, offset = 0, limit = 50) => { try { const response = await fetch(`/extended/v2/addresses/${addr}/balances/ft?offset=${offset}&limit=${limit}`); return response; } catch { return { limit, offset, total: 0, results: [] }; } }; exports.fetchTokenBalancesPage = fetchTokenBalancesPage; /** * Fetches all token balances for an address by paginating through results */ const fetchAllTokenBalances = async (addr) => { const limit = 50; let offset = 0; let total = 0; const tokenBalanceMap = {}; do { const response = await (0, exports.fetchTokenBalancesPage)(addr, offset, limit); // Map token balances to a more convenient format for (const item of response.results) { tokenBalanceMap[item.token.toLowerCase()] = item.balance; } offset += limit; total = response.total; } while (offset < total); return tokenBalanceMap; }; exports.fetchAllTokenBalances = fetchAllTokenBalances; /** * Fetches estimated fees for a transfer */ const fetchEstimatedFees = async (request) => { // Cast to Record<string, unknown> to satisfy type constraints const feeRate = await send(`/v2/fees/transfer`, request); return feeRate; }; exports.fetchEstimatedFees = fetchEstimatedFees; /** * Fetches current blockchain status, including block height */ const fetchBlockHeight = async () => { const data = await fetch("/extended"); return data; }; exports.fetchBlockHeight = fetchBlockHeight; /** * Fetches a page of transactions for an address */ const fetchTransactionsPage = async (addr, offset = 0, limit = 50) => { try { const response = await fetch(`/extended/v2/addresses/${addr}/transactions?offset=${offset}&limit=${limit}`); return response; } catch { return { limit, offset, total: 0, results: [] }; } }; exports.fetchTransactionsPage = fetchTransactionsPage; /** * Fetches all transactions for an address */ const fetchAllTransactions = async (addr) => { let qty; let offset = 0; const limit = 50; const allTransactions = []; // Fetch all transactions in pages do { const { results, total } = await (0, exports.fetchTransactionsPage)(addr, offset, limit); allTransactions.push(...results); offset += limit; qty = total; } while (offset < qty); return allTransactions; }; exports.fetchAllTransactions = fetchAllTransactions; /** * Fetches all transactions for an address and organizes them by type */ const fetchFullTxs = async (addr) => { // 1. Fetch all transactions const allTransactions = await (0, exports.fetchAllTransactions)(addr); // 2. Extract regular token transfers const tokenTransfers = (0, transformers_1.extractTokenTransferTransactions)(allTransactions); // 3. Extract and group contract calls const contractTransactions = await (0, transformers_1.extractContractTransactions)(allTransactions); // 4. Add send-many transactions to token transfers const sendManyTransactions = (0, transformers_1.extractSendManyTransactions)(allTransactions); tokenTransfers.push(...sendManyTransactions); return [tokenTransfers, contractTransactions]; }; exports.fetchFullTxs = fetchFullTxs; /** * Broadcasts a signed transaction to the Stacks network */ const broadcastTx = async (message) => { let response = await sendRaw(`/v2/transactions`, message); if (response !== "") response = `0x${response}`; return response; }; exports.broadcastTx = broadcastTx; /** * Fetches a page of mempool transactions for an address */ const fetchMempoolTransactionsPage = async (addr, offset = 0, limit = 50) => { const response = await fetch(`/extended/v1/tx/mempool?sender_address=${addr}&offset=${offset}&limit=${limit}`); return response; }; exports.fetchMempoolTransactionsPage = fetchMempoolTransactionsPage; /** * Fetches all mempool transactions for an address */ const fetchFullMempoolTxs = async (addr) => { let qty; let offset = 0; const limit = 50; let txs = []; do { const { results, total } = await (0, exports.fetchMempoolTransactionsPage)(addr, offset, limit); txs = txs.concat(results); offset += limit; qty = total; } while (offset < qty); return txs; }; exports.fetchFullMempoolTxs = fetchFullMempoolTxs; /** * Fetches the nonce for an address */ const fetchNonce = async (addr) => { const response = await fetch(`/extended/v1/address/${addr}/nonces`); return response; }; exports.fetchNonce = fetchNonce; /** * Fetches metadata for a fungible token by contract address * This can be used to extract the asset_identifier from a contract_id * @param contractAddress - The contract address in format: ADDRESS.CONTRACT_NAME * @returns The fungible token metadata including asset_identifier */ const fetchFungibleTokenMetadata = async (contractAddress) => { const url = `/metadata/v1/ft?address=${contractAddress}`; const response = await fetch(url); return response; }; exports.fetchFungibleTokenMetadata = fetchFungibleTokenMetadata; /** * Fetches metadata for a fungible token by contract address with caching */ exports.fetchFungibleTokenMetadataCached = (0, cache_1.makeLRUCache)(exports.fetchFungibleTokenMetadata, args => args, (0, cache_1.minutes)(60)); //# sourceMappingURL=api.js.map