UNPKG

@okxweb3/coin-bitcoin

Version:

@ok/coin-bitcoin is a Bitcoin SDK for building Web3 wallets and applications. It supports BTC, BSV, DOGE, LTC, and TBTC, enabling private key management, transaction signing, address generation, and inscriptions like BRC-20, Runes, CAT, and Atomicals.

239 lines 9.62 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.getFee = exports.getDummySignature = exports.getDummyEcKey = exports.verifyContract = exports.toTokenAddress = exports.resetTx = exports.scaleByDecimals = exports.toP2tr = exports.p2tr2Address = exports.toBitcoinNetwork = exports.toStateScript = exports.callToBufferList = exports.getDummyUTXO = exports.dummyUTXO = exports.getDummySigner = exports.outpoint2ByteString = exports.outpoint2TxOutpoint = exports.toTxOutpoint = exports.getTokenContractP2TR = exports.getTokenContract = exports.getGuardsP2TR = exports.GuardType = exports.script2P2TR = exports.contract2P2TR = exports.strToByteString = exports.byteStringToBuffer = exports.toXOnly = void 0; const cat_smartcontracts_1 = require("@cat-protocol/cat-smartcontracts"); const common_1 = require("../common"); const scrypt_ts_1 = require("scrypt-ts"); const tapscript_1 = require("@cmdcode/tapscript"); const crypto_1 = require("crypto"); const eckey_1 = require("./eckey"); const txBuild_1 = require("../../txBuild"); const ISSUE_PUBKEY = '0250929b74c1a04954b78b4b6035e97a5e078a5a0f28ec96d547bfee9ace803ac0'; function toXOnly(pubkey) { return pubkey.subarray(1, 33); } exports.toXOnly = toXOnly; const byteStringToBuffer = function (byteStringList) { const bufferList = []; for (const byteString of byteStringList) { bufferList.push(Buffer.from(byteString, 'hex')); } return bufferList; }; exports.byteStringToBuffer = byteStringToBuffer; function strToByteString(s) { return (0, scrypt_ts_1.toByteString)(Buffer.from(s, 'utf-8').toString('hex')); } exports.strToByteString = strToByteString; function contract2P2TR(contract) { const script = contract.lockingScript.toBuffer(); const p2tr = script2P2TR(script); return { ...p2tr, script: script.toString('hex'), contract, }; } exports.contract2P2TR = contract2P2TR; function script2P2TR(script) { const tapScript = tapscript_1.Tap.encodeScript(script); const [p2tr, cblock] = tapscript_1.Tap.getPubKey(ISSUE_PUBKEY, { target: tapScript, }); return { p2tr: new common_1.btc.Script(`OP_1 32 0x${p2tr}}`).toHex(), tapScript: tapScript, cblock, }; } exports.script2P2TR = script2P2TR; var GuardType; (function (GuardType) { GuardType[GuardType["Transfer"] = 0] = "Transfer"; GuardType[GuardType["Burn"] = 1] = "Burn"; })(GuardType = exports.GuardType || (exports.GuardType = {})); function getGuardsP2TR(guardType = GuardType.Transfer) { const burnGuard = new cat_smartcontracts_1.BurnGuard(); const transferGuard = new cat_smartcontracts_1.TransferGuard(); const tapleafKeyBurnGuard = tapscript_1.Tap.encodeScript(burnGuard.lockingScript.toBuffer()); const tapleafKeyTransferGuard = tapscript_1.Tap.encodeScript(transferGuard.lockingScript.toBuffer()); const tapTree = [tapleafKeyBurnGuard, tapleafKeyTransferGuard]; const [tpubkeyGuards] = tapscript_1.Tap.getPubKey(ISSUE_PUBKEY, { tree: tapTree, }); const [, cblockKeyBurnGuard] = tapscript_1.Tap.getPubKey(ISSUE_PUBKEY, { target: tapleafKeyBurnGuard, tree: tapTree, }); const [, cblockKeyTransferGuard] = tapscript_1.Tap.getPubKey(ISSUE_PUBKEY, { target: tapleafKeyTransferGuard, tree: tapTree, }); const p2tr = new common_1.btc.Script(`OP_1 32 0x${tpubkeyGuards}}`).toHex(); if (guardType === GuardType.Transfer) { return { p2tr, tapScript: tapleafKeyTransferGuard, cblock: cblockKeyTransferGuard, script: transferGuard.lockingScript.toBuffer().toString('hex'), contract: transferGuard, }; } return { p2tr, tapScript: tapleafKeyBurnGuard, cblock: cblockKeyBurnGuard, script: burnGuard.lockingScript.toBuffer().toString('hex'), contract: burnGuard, }; } exports.getGuardsP2TR = getGuardsP2TR; function getTokenContract(minterP2TR, guardsP2TR) { return new cat_smartcontracts_1.CAT20(minterP2TR, (0, scrypt_ts_1.toByteString)(guardsP2TR)); } exports.getTokenContract = getTokenContract; function getTokenContractP2TR(minterP2TR) { const { p2tr: guardsP2TR } = getGuardsP2TR(); return contract2P2TR(getTokenContract(minterP2TR, guardsP2TR)); } exports.getTokenContractP2TR = getTokenContractP2TR; function toTxOutpoint(txid, outputIndex) { const outputBuf = Buffer.alloc(4, 0); outputBuf.writeUInt32LE(outputIndex); return { txhash: Buffer.from(txid, 'hex').reverse().toString('hex'), outputIndex: outputBuf.toString('hex'), }; } exports.toTxOutpoint = toTxOutpoint; function outpoint2TxOutpoint(outpoint) { const [txid, vout] = outpoint.split('_'); return toTxOutpoint(txid, parseInt(vout)); } exports.outpoint2TxOutpoint = outpoint2TxOutpoint; const outpoint2ByteString = function (outpoint) { const txOutpoint = outpoint2TxOutpoint(outpoint); return txOutpoint.txhash + txOutpoint.outputIndex; }; exports.outpoint2ByteString = outpoint2ByteString; function getDummySigner(privateKey) { return scrypt_ts_1.TestWallet.random(new scrypt_ts_1.DummyProvider()); } exports.getDummySigner = getDummySigner; exports.dummyUTXO = { txId: (0, crypto_1.randomBytes)(32).toString('hex'), outputIndex: 0, script: '', satoshis: 10000, }; function getDummyUTXO(satoshis = 10000, unique = false) { if (unique) { return Object.assign({}, exports.dummyUTXO, { satoshis, txId: (0, crypto_1.randomBytes)(32).toString('hex'), }); } return Object.assign({}, exports.dummyUTXO, { satoshis }); } exports.getDummyUTXO = getDummyUTXO; const callToBufferList = function (ct) { const callArgs = ct.tx.inputs[ct.atInputIndex].script.chunks.map((value) => { if (!value.buf) { if (value.opcodenum >= 81 && value.opcodenum <= 96) { const hex = (0, scrypt_ts_1.int2ByteString)(BigInt(value.opcodenum - 80)); return Buffer.from(hex, 'hex'); } else { return Buffer.from((0, scrypt_ts_1.toByteString)('')); } } return value.buf; }); return callArgs; }; exports.callToBufferList = callToBufferList; const toStateScript = function (state) { return new common_1.btc.Script(`6a1863617401${state.hashRoot}`); }; exports.toStateScript = toStateScript; function toBitcoinNetwork(network) { if (network === 'btc-signet') { return common_1.btc.Networks.testnet; } else if (network === 'fractal-mainnet' || 'fractal-testnet') { return common_1.btc.Networks.mainnet; } else { throw new Error(`invalid network ${network}`); } } exports.toBitcoinNetwork = toBitcoinNetwork; function p2tr2Address(p2tr, network) { const script = typeof p2tr === 'string' ? common_1.btc.Script.fromHex(p2tr) : p2tr; return common_1.btc.Address.fromScript(script, toBitcoinNetwork(network)).toString(); } exports.p2tr2Address = p2tr2Address; function toP2tr(address) { const p2trAddress = typeof address === 'string' ? common_1.btc.Address.fromString(address) : address; if (p2trAddress.type !== 'taproot') { throw new Error(`address ${address} is not taproot`); } return common_1.btc.Script.fromAddress(address).toHex(); } exports.toP2tr = toP2tr; function scaleByDecimals(amount, decimals) { return amount * BigInt(Math.pow(10, decimals)); } exports.scaleByDecimals = scaleByDecimals; function resetTx(tx) { for (let i = 0; i < tx.inputs.length; i++) { const input = tx.inputs[i]; if (input.hasWitnesses()) { input.setWitnesses([]); } } tx.nLockTime = 0; } exports.resetTx = resetTx; function toTokenAddress(address) { if (typeof address === 'string') { address = common_1.btc.Address.fromString(address); } if (address.type === common_1.btc.Address.PayToTaproot) { return (0, scrypt_ts_1.hash160)(address.hashBuffer.toString('hex')); } else if (address.type === common_1.btc.Address.PayToWitnessPublicKeyHash) { return address.hashBuffer.toString('hex'); } else { throw new Error(`Unsupported address type: ${address.type}`); } } exports.toTokenAddress = toTokenAddress; function verifyContract(utxo, tx, inputIndex, witnesses) { const interpreter = new common_1.btc.Script.Interpreter(); const flags = common_1.btc.Script.Interpreter.SCRIPT_VERIFY_WITNESS | common_1.btc.Script.Interpreter.SCRIPT_VERIFY_TAPROOT; const res = interpreter.verify(new common_1.btc.Script(''), new common_1.btc.Script(utxo.script), tx, inputIndex, flags, witnesses, utxo.satoshis); if (!res) { return interpreter.errstr; } return true; } exports.verifyContract = verifyContract; function getDummyEcKey() { let privateKey = (0, crypto_1.randomBytes)(32); const wif = (0, txBuild_1.private2Wif)(privateKey); return new eckey_1.EcKeyService({ privateKey: wif }); } exports.getDummyEcKey = getDummyEcKey; function getDummySignature() { return common_1.btc.crypto.Signature.fromString('E907831F80848D1069A5371B402410364BDF1C5F8307B0084C55F1CE2DCA821525F66A4A85EA8B71E482A74F382D2CE5EBEEE8FDB2172F477DF4900D310536C0').toString('hex'); } exports.getDummySignature = getDummySignature; function getFee(tx) { return tx.inputs.reduce((acc, i) => acc + i.output.satoshis, 0) - tx.outputs.reduce((acc, o) => acc + o.satoshis, 0); } exports.getFee = getFee; //# sourceMappingURL=utils.js.map