import { Transaction as RawTransaction, ECPairInterface as ECPair, Network } from 'bitcoinjs-lib'; import { ILogger, IBTCTransactionAddress, IUTXOTransaction, IBTCUnspent, IBTCInput, IBTCOutput, IKeypair, binStr } from '@onechain/core'; import { IApiProvider } from './api-providers'; /** * Transaction * * 为什么要在交易对象之上再包一层交易对象? * * 首先明确三个特点: * * 1. 对于 BTC 具体交易的构造还不完全理解,不过能够明确的是,交易构造完成后不能修改 output 的 value 。 * 2. BTC 交易的 fee 是根据交易总体积有多少字节来计算的,但是复杂的情况下比较难在交易构造完成前就算出整个交易的体积,而 * fee 又是通过定义找零 output 的 value 来实现的,所以构造交易和设置交易的 fee 变成了一个先有鸡还有是先有蛋的问题。 * 3. 交易 output 中 value 占用的体积是固定的 8 bytes ,所以即使修改 output 的 value ,构造的交易体积不会发生变化。 * 4. 每个 input 和 output 的体积实际是根据 script 来变化的,并非网上常说的固定体积。 * * 在此特点的基础上,需要实现可多次计算调整交易费率的功能,那么最简单的办法就是:先构造交易,计算 fee,然后重新根据实际 * fee 再次构造交易。 * * 所以实现了这个类来解决这其中的参数过多、需要保存状态等问题。 * * @export * @class Transaction * @implements {IUTXOTransaction} */ export declare class Transaction implements IUTXOTransaction { protected _apiProvider: IApiProvider; protected _logger: ILogger; protected _network: Network; protected _wallets: { [address: string]: ECPair; }; protected _transaction: RawTransaction; protected _unspents: IBTCUnspent[]; protected _inputs: IBTCInput[]; protected _outputs: IBTCOutput[]; protected _changes: IBTCOutput[]; protected _value: number; protected _fee: number; protected _froms: IBTCTransactionAddress[]; protected _tos: IBTCTransactionAddress[]; protected _memos: binStr[]; /** * 自动修正是因为用户想要全部转出时,很难精确的计算出 `总余额 - 矿工费` 的 `可转金额` ,这种模式下会自动将 `可转金额` * 限制在 `总余额 - 矿工费` 的范围之内。 */ protected _autoFix: boolean; readonly value: number; readonly change: number; readonly fee: number; readonly size: number; readonly unspents: IBTCUnspent[]; readonly inputs: IBTCUnspent[]; constructor(froms: IBTCTransactionAddress[], tos: IBTCTransactionAddress[], changeAddress: string, memos?: binStr[], autoFix?: boolean); init(apiProvider: IApiProvider, logger: ILogger, network: Network, wallets?: { [address: string]: ECPair; }): Promise; /** * 编辑交易内容 * * 使用这个接口可以避免重复查询 unspents ,froms 不能修改,是因为 froms 一旦修改就要重新查询 unspents 。 * * @param {number} [fee=-1] * @param {IBTCTransactionAddress[]} [tos=[]] * @param {string[]} [memos=[]] * @param {IKeypair[]} [keypairs=[]] * @param {string} [changeAddress=''] * @memberof Transaction */ edit(fee?: number, tos?: IBTCTransactionAddress[], memos?: string[], keypairs?: IKeypair[], changeAddress?: string): void; /** * 试算交易的矿工费 * * @param {number} feeRate * @returns * @memberof Transaction */ calcFee(feeRate: number): any; /** * 生成 hex 编码交易数据 * * @returns * @memberof Transaction */ toHex(): string; /** * 生成 JSON 格式的交易数据 * * @returns * @memberof Transaction */ toJSON(): { txid: string; iscoinbase: boolean; fee: string; block_height: number; blockhash: string; blocktime: string; confirmations: number; inputs: { from_address: string; from_txid: string; vin_index: number; value: string; sequence: number; }[]; outputs: { to_address: string; vout_index: number; value: string; type: any; asm: string; hex: any; }[]; }; /** * 载入 unspents * * @protected * @param {IBTCTransactionAddress[]} froms * @memberof Transaction */ protected _loadUnspents(froms: IBTCTransactionAddress[]): Promise; /** * 计算交易输入输出 * * WARNING 支付地址必须和 keypairs 中的地址一致,因为只有地址无法倒退回 publicKey ,那么假设 keypair 中用的是 p2pkh , * 但是支付地址是 p2wpkh ,那么想要根据支付地址找到对应的 privateKey 就必须把每个 keypair 用来尝试生成 p2wpkh * * @param froms * @param tos * @param changeAddress */ protected _calcInputOutput(unspents: IBTCUnspent[], tos: IBTCTransactionAddress[], fee: number, autoFix: boolean): void; /** * 从最后一个 output 开始尝试扣除 fee 的部分 * * @protected * @param {*} outputs * @param {*} fee * @returns * @memberof Transaction */ protected _removeFeeFromOutputs(outputs: any, fee: any): any; /** * 构造 bitcoinjs 交易对象 * * @protected * @param {IBTCInput[]} inputs * @param {IBTCOutput[]} outputs * @param {IBTCOutput[]} changes * @param {binStr[]} [memos=[]] * @returns * @memberof Transaction */ protected _buildTransaction(inputs: IBTCInput[], outputs: IBTCOutput[], changes: IBTCOutput[], memos?: binStr[]): RawTransaction; } export default Transaction;