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
178 lines (177 loc) • 7.64 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.BchConnector = void 0;
const Connector_1 = require("../../Connector");
const HDWallet_1 = require("../../../Wallet/SigningWallet/HDWallet/HDWallet");
const PrivateKeyWallet_1 = require("../../../Wallet/SigningWallet/PrivateKeyWallet/PrivateKeyWallet");
const XpubWallet_1 = require("../../../Wallet/ViewOnlyWallet/XpubWallet/XpubWallet");
const PublicKeyWallet_1 = require("../../../Wallet/ViewOnlyWallet/PublicKeyWallet/PublicKeyWallet");
const errors_1 = require("../../../errors");
const utils_1 = require("../../../utils");
const BchTransaction_1 = require("./BchTransaction");
const CustomUtxoTransaction_1 = require("../CustomUtxoTransaction");
const bch_1 = require("./bch");
const cashaddr_1 = require("./cashaddr");
const utxoConnectorUtils_1 = require("../utxoConnectorUtils");
/**
* Connector for Bitcoin Cash (BCH).
*
* @example
* ```ts
* const cg = new ChainGate();
* const bch = cg.connect(cg.networks.bitcoincash, wallet);
*
* // Default address (cashaddr)
* const addr = await bch.address();
*
* // Legacy address
* const legacyAddr = await bch.address({ addressType: 'legacy' });
*
* const balance = await bch.addressBalance();
*
* const amount = cg.networks.bitcoincash.amount('0.01');
* const tx = await bch.transfer(amount, 'bitcoincash:qq...');
* ```
*/
class BchConnector 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 the Bitcoin Cash 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 (cashaddr or legacy) 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 BCH transfer transaction with recommended fees.
*
* @param amount - Amount to send.
* @param toAddress - Recipient address (cashaddr or legacy).
*
* @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 BchTransaction_1.BchTransaction.create({
explorer: this.explorer,
fromAddress,
toAddress,
valueSat,
networkParams: this.network.networkParams,
getPrivateKey,
});
}
/**
* Creates a custom BCH transaction with caller-defined inputs and outputs.
*
* Addresses may be provided in CashAddr or legacy format.
*
* @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);
// Convert output addresses to legacy for signing compatibility.
const legacyOutputs = params.outputs.map((o) => ({
address: (0, cashaddr_1.toLegacyAddress)(o.address),
amount: o.amount,
}));
return new CustomUtxoTransaction_1.CustomUtxoTransaction({
explorer: this.explorer,
networkParams: this.network.networkParams,
inputs: params.inputs,
outputs: legacyOutputs,
getPrivateKey,
signTransaction: signCustomBchTransaction,
});
}
}
exports.BchConnector = BchConnector;
// ---------------------------------------------------------------------------
// BCH-specific custom signing adapter
// ---------------------------------------------------------------------------
/** @internal */
function signCustomBchTransaction(inputs, outputs, privateKey, networkParams) {
return (0, bch_1.signBchTransaction)(inputs.map((i) => ({
txid: i.txid,
n: i.index,
script: (0, utils_1.hexToBytes)(i.script),
amount: i.amount.min(),
})), outputs.map((o) => ({
address: o.address,
amount: o.amount.min(),
})), privateKey, networkParams);
}