UNPKG

chaingate

Version:

Multi-chain cryptocurrency SDK for TypeScript — unified API for Bitcoin, Ethereum, Litecoin, Dogecoin, Bitcoin Cash, Polygon, Arbitrum, and any EVM-compatible chain. Create wallets, query balances, send transactions, and manage tokens and NFTs across UTXO

86 lines (85 loc) 3.38 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.UtxoLocalCache = void 0; /** * Local cache that tracks spent and unspent UTXOs between broadcast and API indexing. * * When a transaction is broadcast, the API may still return the spent inputs * (stale) and may not yet know about the new change outputs. This cache bridges * that gap so that successive transactions can be built immediately. * * - **Spent**: UTXOs consumed by a local broadcast. Filtered out even if the * API still returns them. * - **Unspent**: Change outputs created by a local broadcast. Included even if * the API does not know about them yet. * * When a broadcasted transaction is confirmed, {@link confirmTransaction} should * be called to clean up the cache entries (the API has caught up). */ class UtxoLocalCache { constructor() { /** "txid:n" → broadcastTxId that consumed the UTXO. */ this.spent = new Map(); /** address → locally created unspent UTXOs. */ this.unspent = new Map(); } /** * Marks a UTXO as spent by a broadcast transaction. * * If the UTXO was a locally cached unspent (e.g. a change output from a * previous broadcast), it is also removed from the unspent set. */ markSpent(txid, n, broadcastTxId) { this.spent.set(`${txid}:${n}`, broadcastTxId); // Remove from unspent if present (tx2 spending tx1's change). for (const [address, utxos] of this.unspent) { const idx = utxos.findIndex((u) => u.txid === txid && u.n === n); if (idx !== -1) { utxos.splice(idx, 1); if (utxos.length === 0) this.unspent.delete(address); break; } } } /** Returns `true` if the UTXO has been marked as spent by a local broadcast. */ isSpent(txid, n) { return this.spent.has(`${txid}:${n}`); } /** Adds a new unspent UTXO (typically a change output from a local broadcast). */ addUnspent(address, utxo) { const list = this.unspent.get(address) ?? []; list.push(utxo); this.unspent.set(address, list); } /** Returns a copy of locally cached unspent UTXOs for the given address. */ getUnspent(address) { return [...(this.unspent.get(address) ?? [])]; } /** * Cleans up cache entries for a confirmed broadcast transaction. * * Once the API has indexed the transaction, the local overrides are no longer * needed: * - Spent entries consumed by this broadcast are removed. * - Unspent entries created by this broadcast are removed. */ confirmTransaction(broadcastTxId) { // Remove spent entries that were consumed by this broadcast. for (const [key, txId] of this.spent) { if (txId === broadcastTxId) this.spent.delete(key); } // Remove unspent entries created by this broadcast. for (const [address, utxos] of this.unspent) { const filtered = utxos.filter((u) => u.txid !== broadcastTxId); if (filtered.length === 0) { this.unspent.delete(address); } else { this.unspent.set(address, filtered); } } } } exports.UtxoLocalCache = UtxoLocalCache;