@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.
207 lines • 7.88 kB
JavaScript
;
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.RuneTestWallet = exports.RuneWallet = void 0;
const coin_base_1 = require("@okxweb3/coin-base");
const BtcWallet_1 = require("./BtcWallet");
const bitcoin = __importStar(require("../index"));
const index_1 = require("../index");
const rune_1 = require("../rune");
const coin_base_2 = require("@okxweb3/coin-base");
class RuneWallet extends BtcWallet_1.BtcWallet {
convert2RuneTx(paramData) {
const clonedParamData = (0, coin_base_1.cloneObject)(paramData);
for (let input of clonedParamData.inputs) {
let dataArray = input.data;
if (dataArray != null && dataArray instanceof Array) {
for (let data of dataArray) {
if (typeof data['amount'] === 'string') {
data['amount'] = BigInt(data['amount']);
}
}
}
}
for (let output of clonedParamData.outputs) {
let dataArray = output.data;
if (dataArray != null && dataArray instanceof Array) {
for (let data of dataArray) {
if (typeof data['amount'] === 'string') {
data['amount'] = BigInt(data['amount']);
}
}
}
}
let inputs = clonedParamData.inputs;
const runeInputMap = new Map();
for (const input of inputs) {
let dataArray = input.data;
if (dataArray != null && dataArray instanceof Array) {
for (const data of dataArray) {
let runeId = data['id'];
let runeAmount = BigInt(data['amount']);
if (runeId == null || runeAmount == null) {
continue;
}
let beforeAmount = runeInputMap.get(runeId);
if (beforeAmount == null) {
runeInputMap.set(runeId, runeAmount);
}
else {
runeInputMap.set(runeId, BigInt(beforeAmount) + BigInt(runeAmount));
}
}
}
}
let outputs = clonedParamData.outputs;
const runeSendMap = new Map();
for (const output of outputs) {
let data = output.data;
if (data != null) {
let runeId = data['id'];
let runeAmount = BigInt(data['amount']);
if (runeId == null || runeAmount == null) {
continue;
}
let beforeAmount = runeSendMap.get(runeId);
if (beforeAmount == null) {
runeSendMap.set(runeId, runeAmount);
}
else {
runeSendMap.set(runeId, BigInt(beforeAmount) + BigInt(runeAmount));
}
}
}
let isRuneChange = false;
for (const id of runeInputMap.keys()) {
let inputAmount = runeInputMap.get(id);
let sendAmount = runeSendMap.get(id);
if ((inputAmount != null &&
sendAmount != null &&
inputAmount > sendAmount) ||
(inputAmount != null && sendAmount == null)) {
isRuneChange = true;
}
isRuneChange = true;
}
let outputIndex = 0;
let updateOutputs = [];
if (isRuneChange) {
let runeChange = {
address: clonedParamData.address,
amount: 546,
};
updateOutputs.push(runeChange);
outputIndex++;
}
const typedEdicts = [];
for (const output of outputs) {
let data = output.data;
if (data != null) {
let runeId = data['id'];
let runeAmount = BigInt(data['amount']);
if (runeId == null || runeAmount == null) {
continue;
}
const typedEdict = {
id: parseInt('0x' + runeId),
amount: BigInt(runeAmount),
output: outputIndex,
};
typedEdicts.push(typedEdict);
}
output.data = null;
updateOutputs.push(output);
outputIndex++;
}
return {
inputs: clonedParamData.inputs,
outputs: updateOutputs,
address: clonedParamData.address,
feePerB: clonedParamData.feePerB,
runeData: {
edicts: typedEdicts,
etching: clonedParamData.runeData.etching,
burn: clonedParamData.runeData.burn,
},
};
}
async signTransaction(param) {
const network = this.network();
let txHex = null;
try {
const privateKey = param.privateKey;
if (!param.data.runeData) {
return Promise.reject('missing runeData');
}
const runeTx = this.convert2RuneTx(param.data);
const opReturnOutput = this.getOpReturnOutput(network, runeTx.runeData);
runeTx.outputs.push(opReturnOutput);
txHex = (0, index_1.signBtc)(runeTx, privateKey, network);
return Promise.resolve(txHex);
}
catch (e) {
return Promise.reject(coin_base_1.SignTxError);
}
}
getOpReturnOutput(network, runeData) {
let isMainnet = false;
if (index_1.networks.bitcoin === network) {
isMainnet = true;
}
if (runeData.edicts == undefined) {
runeData.edicts = [];
}
const opReturnScript = (0, rune_1.buildRuneData)(isMainnet, runeData.edicts);
const opReturnOutput = {
address: '',
amount: 0,
omniScript: coin_base_2.base.toHex(opReturnScript),
};
return opReturnOutput;
}
async estimateFee(param) {
try {
if (!param.data.runeData) {
return Promise.reject('missing runeData');
}
const runeTx = this.convert2RuneTx(param.data);
const opReturnOutput = this.getOpReturnOutput(this.network(), runeTx.runeData);
runeTx.outputs.push(opReturnOutput);
const fee = bitcoin.estimateBtcFee(runeTx, this.network());
return Promise.resolve(fee);
}
catch (e) {
return Promise.reject(coin_base_1.EstimateFeeError);
}
}
}
exports.RuneWallet = RuneWallet;
class RuneTestWallet extends RuneWallet {
network() {
return bitcoin.networks.testnet;
}
}
exports.RuneTestWallet = RuneTestWallet;
//# sourceMappingURL=RuneWallet.js.map