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
165 lines (164 loc) • 7.36 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.UtxoConnector = void 0;
const Connector_1 = require("../Connector");
const XpubWallet_1 = require("../../Wallet/ViewOnlyWallet/XpubWallet/XpubWallet");
const PublicKeyWallet_1 = require("../../Wallet/ViewOnlyWallet/PublicKeyWallet/PublicKeyWallet");
const HDWallet_1 = require("../../Wallet/SigningWallet/HDWallet/HDWallet");
const PrivateKeyWallet_1 = require("../../Wallet/SigningWallet/PrivateKeyWallet/PrivateKeyWallet");
const errors_1 = require("../../errors");
const utils_1 = require("../../utils");
const UtxoTransaction_1 = require("./UtxoTransaction");
const CustomUtxoTransaction_1 = require("./CustomUtxoTransaction");
const utxoConnectorUtils_1 = require("./utxoConnectorUtils");
/**
* Connector for UTXO-based networks (Bitcoin, Litecoin, Dogecoin, Bitcoin Testnet).
*
* Bridges a {@link Wallet} with a {@link UtxoExplorer} to provide
* address derivation, balance queries, and transaction broadcasting.
*
* @example
* ```ts
* const cg = new ChainGate();
* const btcConn = cg.connect(cg.networks.bitcoin, wallet);
*
* // Default address (segwit for Bitcoin)
* const addr = await btcConn.address();
*
* // Taproot address (auto-resolves derivation path)
* const taprootAddr = await btcConn.address({ addressType: 'taproot' });
*
* // Legacy address with custom derivation path
* const legacyAddr = await btcConn.address({ addressType: 'legacy', derivationPath: "m/44'/0'/0'/0" });
*
* const balance = await btcConn.addressBalance();
*
* const amount = cg.networks.bitcoin.amount('0.001');
* const tx = await btcConn.transfer(amount, 'bc1q...');
* ```
*/
class UtxoConnector extends Connector_1.Connector {
/** @internal */
constructor(wallet, explorer, network) {
super(wallet, explorer, network);
}
/**
* Resolves the effective address type and derivation path from the given options.
* @internal
*/
resolveAddressOptions(options) {
const { index = 0, addressType, derivationPath } = options ?? {};
const resolvedType = addressType ?? this.network.defaultAddressType;
const typeConfig = this.network.addressTypes[resolvedType];
if (!typeConfig) {
const supported = Object.keys(this.network.addressTypes).join(', ');
throw new errors_1.UnsupportedOperationError(`Address type '${resolvedType}' is not supported on network '${this.network.id}'. ` +
`Supported types: ${supported}.`);
}
const resolvedPath = derivationPath ?? typeConfig.derivationPath;
return { index, addressType: resolvedType, derivationPath: resolvedPath };
}
/**
* Returns the address for this wallet on this UTXO network.
*
* - **HD wallets**: derives at `{derivationPath}/{index}` using the derivation
* path for the selected address type (or the network default).
* - **Single-key wallets**: only index `0` is valid. The address type determines
* the encoding (segwit, legacy, taproot) of the same public key.
* - **XpubWallet**: derives at `m/0/{index}`.
*/
async address(options) {
const { index, addressType, derivationPath } = this.resolveAddressOptions(options);
const wallet = this.wallet;
if (wallet instanceof HDWallet_1.HDWallet) {
const fullPath = `${derivationPath}/${index}`;
const derived = await wallet.derivePublicKey(fullPath);
return this.network.publicKeyToAddress(derived.publicKey, addressType);
}
if (wallet instanceof XpubWallet_1.XpubWallet) {
const relativePath = `m/0/${index}`;
const derived = await wallet.derive(relativePath);
return this.network.publicKeyToAddress(derived.publicKey, addressType);
}
if (index !== 0) {
throw new errors_1.UnsupportedOperationError(`Wallet type '${wallet.walletType}' does not support indexed address derivation. ` +
`Only index 0 is valid for single-key wallets.`);
}
if (wallet instanceof PrivateKeyWallet_1.PrivateKeyWallet || wallet instanceof PublicKeyWallet_1.PublicKeyWallet) {
const pubKeyBytes = (0, utils_1.hexToBytes)(wallet.publicKey);
return this.network.publicKeyToAddress(pubKeyBytes, addressType);
}
throw new errors_1.UnsupportedOperationError(`Unsupported wallet type: ${wallet.walletType}`);
}
/**
* Returns the confirmed and unconfirmed balance for this wallet's address.
*/
async addressBalance(options) {
const addr = await this.address(options);
return this.explorer.getAddressBalance(addr);
}
/**
* Returns paginated transaction history for this wallet's address.
*
* @param page - Pagination cursor.
*/
async addressHistory(page, options) {
const addr = await this.address(options);
return this.explorer.getAddressHistory(addr, page);
}
/**
* Returns paginated UTXOs for this wallet's address.
*
* @param page - Pagination cursor.
*/
async addressUtxos(page, options) {
const addr = await this.address(options);
return this.explorer.getUtxosByAddress(addr, page);
}
/**
* Creates a UTXO transfer transaction with recommended fees.
*
* The returned {@link UtxoTransaction} can be inspected, have its fee adjusted,
* and then signed + broadcast.
*
* @param amount - Amount to send. Create via
* {@link NetworkDescriptor.amount | cg.networks.bitcoin.amount(0.001)} or
* {@link NetworkDescriptor.amountFromCurrency | cg.networks.bitcoin.amountFromCurrency('usd', 50)}.
* @param toAddress - Recipient address.
*
* @throws {@link UnsupportedOperationError} if the wallet is view-only.
*/
async transfer(amount, toAddress, options) {
const { index, derivationPath } = this.resolveAddressOptions(options);
const fromAddress = await this.address(options);
const valueSat = amount.min();
const getPrivateKey = (0, utxoConnectorUtils_1.createPrivateKeyGetter)(this.wallet, index, derivationPath);
return UtxoTransaction_1.UtxoTransaction.create({
explorer: this.explorer,
fromAddress,
toAddress,
valueSat,
networkParams: this.network.networkParams,
getPrivateKey,
});
}
/**
* Creates a custom UTXO transaction with caller-defined inputs and outputs.
*
* @param params - Inputs and outputs for the transaction.
* @throws {@link UnsupportedOperationError} if the wallet is view-only.
*/
createTransaction(params, options) {
const { index, derivationPath } = this.resolveAddressOptions(options);
const getPrivateKey = (0, utxoConnectorUtils_1.createPrivateKeyGetter)(this.wallet, index, derivationPath);
return new CustomUtxoTransaction_1.CustomUtxoTransaction({
explorer: this.explorer,
networkParams: this.network.networkParams,
inputs: params.inputs,
outputs: params.outputs,
getPrivateKey,
signTransaction: CustomUtxoTransaction_1.signCustomUtxoTransaction,
});
}
}
exports.UtxoConnector = UtxoConnector;