UNPKG

@arklabs/wallet-sdk

Version:

Bitcoin wallet SDK with Taproot and Ark integration

47 lines (46 loc) 1.74 kB
import { Address, p2tr, TAP_LEAF_VERSION, taprootListToTree, } from "@scure/btc-signer/payment"; import { TAPROOT_UNSPENDABLE_KEY, } from "@scure/btc-signer/utils"; import { ArkAddress } from './address.js'; import { Script } from "@scure/btc-signer"; import { hex } from "@scure/base"; export function scriptFromTapLeafScript(leaf) { return leaf[1].subarray(0, leaf[1].length - 1); // remove the version byte } export class VtxoScript { static decode(scripts) { return new VtxoScript(scripts.map(hex.decode)); } constructor(scripts) { this.scripts = scripts; const tapTree = taprootListToTree(scripts.map((script) => ({ script, leafVersion: TAP_LEAF_VERSION }))); const payment = p2tr(TAPROOT_UNSPENDABLE_KEY, tapTree, undefined, true); if (!payment.tapLeafScript || payment.tapLeafScript.length !== scripts.length) { throw new Error("invalid scripts"); } this.leaves = payment.tapLeafScript; this.tweakedPublicKey = payment.tweakedPubkey; } encode() { return this.scripts.map(hex.encode); } address(prefix, serverPubKey) { return new ArkAddress(serverPubKey, this.tweakedPublicKey, prefix); } get pkScript() { return Script.encode(["OP_1", this.tweakedPublicKey]); } onchainAddress(network) { return Address(network).encode({ type: "tr", pubkey: this.tweakedPublicKey, }); } findLeaf(scriptHex) { const leaf = this.leaves.find((leaf) => hex.encode(scriptFromTapLeafScript(leaf)) === scriptHex); if (!leaf) { throw new Error(`leaf '${scriptHex}' not found`); } return leaf; } }