feat(theseus/aegis): DGB adapter on @dgb-wallet/{core,psbt} vendored packages

Aegis now shares its DGB code with the standalone DigiByte web-wallet at
D:\Dev\SilentCode\Digibyte. Address derivation and PSBT construction come
from that project's @dgb-wallet/core and @dgb-wallet/psbt packages instead
of Aegis-local reimplementations. Any bugfix upstream flows in via a
re-vendor of dist/*.

- lib/dgb/{core,psbt}/ — vendored dist/ output of the two packages plus
  a tiny package.json shim marking them as ESM. @dgb-wallet/core's own
  import specifier "@dgb-wallet/core" inside psbt/*.js is rewritten to
  "../core/index.js" so the sibling module resolves without a workspace.
- New Theseus deps: bitcoinjs-lib, bip32, bip39, @bitcoinerlab/secp256k1,
  ecpair — the peer deps the vendored packages need. Loaded via
  api.require in index.js's loadDeps().
- chain-dgb.js is a thin adapter now: BIP32 tree via bip32 + DGB
  Network object, addresses via core.p2wpkhAddress, tx via
  psbt.buildPsbt + PSBT.signInput (per-input, since each UTXO's key
  differs) + psbt.finalizeAndExtract. Runtime backend stays the same —
  Theseus's lib/electrum.js against the DGB ElectrumX pool.
- Verified end-to-end in scratchpad: abandon×11 mnemonic derives
  dgb1q9gmf0pv8jdymcly6lz6fl7lf6mhslsd72e2jq8 (matches iancoleman.io/bip39
  and the previous inline implementation, so no on-chain address change
  for anyone who was already using Aegis's DGB slot). PSBT build+sign+
  finalize on a mock UTXO produces a valid 223-byte witness tx.

BIP44 (D…) and BIP49 (S…) address families are implemented in the
vendored core but not yet exposed in Aegis's picker — the panel needs
an "address family" selector inside the DGB settings block first. Left
for a follow-up; today's DGB pick uses BIP84 native SegWit only.
This commit is contained in:
Local Dev 2026-09-07 02:19:44 +02:00
parent 118de0ef5c
commit 4c63ae1bc7
28 changed files with 1183 additions and 214 deletions

View file

@ -32,7 +32,6 @@ async function loadDeps(api) {
const { keccak_256 } = await api.import("@noble/hashes/sha3.js");
const { blake2b } = await api.import("@noble/hashes/blake2.js");
const { HDKey } = await api.import("@scure/bip32");
const { bech32 } = await api.import("@scure/base");
const WebSocket = api.require("ws");
const cashaddr = require("./lib/cashaddr.js");
const keysLib = require("./lib/keys.js")({ HDKey, secp256k1, sha256, ripemd160, cashaddr });
@ -46,12 +45,26 @@ async function loadDeps(api) {
HDKey, secp256k1, sha256, keccak_256, base58check,
});
const siaAdapter = require("./lib/chain-sia.js")({ ed25519, blake2b });
// DGB delegates address derivation + PSBT to the vendored @dgb-wallet/*
// packages under lib/dgb/. Those are ESM; the peer deps (bitcoinjs-lib,
// bip32, ecpair, @bitcoinerlab/secp256k1) are CommonJS and reachable via
// api.require from the Theseus dependency tree.
const { pathToFileURL } = require("node:url");
const dgbCore = await import(pathToFileURL(path.join(api.folder, "lib/dgb/core/index.js")).href);
const dgbPsbt = await import(pathToFileURL(path.join(api.folder, "lib/dgb/psbt/index.js")).href);
const bitcoinjs = api.require("bitcoinjs-lib");
const { BIP32Factory } = api.require("bip32");
const { ECPairFactory } = api.require("ecpair");
const ecc = api.require("@bitcoinerlab/secp256k1");
const dgbAdapter = require("./lib/chain-dgb.js")({
HDKey, secp256k1, sha256, ripemd160, bech32, electrum,
dgbCore, dgbPsbt, bitcoinjs,
bip32Factory: BIP32Factory, ecpairFactory: ECPairFactory, ecc,
sha256, electrum,
});
return { HDKey, secp256k1, ed25519, sha256, ripemd160, keccak_256, blake2b, bech32,
return { HDKey, secp256k1, ed25519, sha256, ripemd160, keccak_256, blake2b,
cashaddr, keysLib, tx, electrum, base58check,
bchAdapter, tronAdapter, siaAdapter, dgbAdapter };
bchAdapter, tronAdapter, siaAdapter, dgbAdapter,
dgbCore, dgbPsbt, bitcoinjs, ecc };
}
// ---- servers ---------------------------------------------------------------

View file

@ -1,23 +1,25 @@
// DigiByte (DGB) chain adapter — BIP84 native SegWit v0 (dgb1q…) over
// ElectrumX-DGB. Ported from the DigiByte-mobile design at
// SilentCode/Digibyte/packages/core, trimmed to what a browser-side wallet
// needs: HD derivation, address/balance/history + BIP143 P2WPKH send.
// DigiByte (DGB) chain adapter — thin bridge over the @dgb-wallet/* packages
// vendored under lib/dgb/ from D:\Dev\SilentCode\Digibyte\packages\{core,psbt}.
// Address derivation, network params and PSBT construction come from the
// upstream design; Aegis provides the runtime shell (ElectrumX transport,
// gap-limit scanning, wallet-manager plumbing).
//
// Chain params from DGB Core src/kernel/chainparams.cpp CMainParams:
// pubKeyHash 0x1e, scriptHash 0x3f, bech32 HRP "dgb", SLIP-44 coin type 20.
// Backend: DGB ElectrumX pool via Theseus's existing lib/electrum.js — same
// TCP-over-wss stack the BCH wallet uses, no separate protocol adapter.
// Optional Blockbook mode is on the roadmap; ElectrumX is the default
// because it matches Aegis's transport shape and needs no per-server keys.
//
// Only BIP84 is implemented here (m/84'/20'/0'/0/x → dgb1q…). Legacy P2PKH
// import (D…) and P2SH-wrapped SegWit (S…) are on the roadmap; they need
// address-family selection in the panel and a scriptPubKey-selecting
// tx.select variant. For now dgb1q covers the modern DGB user's default.
// Only BIP84 (m/84'/20'/0'/0/x → dgb1q…) is exposed in this rev; the
// vendored core also supports BIP44 (D…) and BIP49 (S…) — plumb them by
// switching the purpose passed to accountNode(). Address recovery from any
// BIP39 tool at coin type 20 is guaranteed by bitcoinjs-lib's Network
// object, so a seed exported here can be restored on iancoleman.io/bip39
// or the SilentCode Digibyte web-wallet with matching addresses.
const NETWORK = "mainnet";
const DGB_COIN_TYPE = 20;
const DEFAULT_ACCOUNT_PATH = "m/84'/20'/0'";
const HRP = "dgb";
const DEFAULT_PURPOSE = 84;
const EXPLORER_TX = "https://digiexplorer.info/tx/";
const EXPLORER_ADDR = "https://digiexplorer.info/address/";
// A small pool of DGB ElectrumX endpoints; the client rotates on failure.
const DEFAULT_SERVERS = [
"wss://electrum1.cyberbits.eu:50022",
"wss://electrum3.cyberbits.eu:50022",
@ -25,154 +27,96 @@ const DEFAULT_SERVERS = [
];
module.exports = function makeDgbAdapter({
HDKey, secp256k1, sha256, ripemd160, bech32, electrum,
dgbCore, // ESM namespace of @dgb-wallet/core (vendored)
dgbPsbt, // ESM namespace of @dgb-wallet/psbt (vendored)
bitcoinjs, // require("bitcoinjs-lib")
bip32Factory, // require("bip32").BIP32Factory
ecpairFactory, // require("ecpair").ECPairFactory
ecc, // require("@bitcoinerlab/secp256k1")
sha256, // @noble/hashes/sha2 (only used for scripthash reversal)
electrum,
}) {
if (!HDKey || !secp256k1 || !sha256 || !ripemd160 || !bech32 || !electrum) {
if (!dgbCore || !dgbPsbt || !bitcoinjs || !bip32Factory || !ecpairFactory || !ecc || !electrum) {
throw new Error("chain-dgb: missing dep");
}
const hash160 = (b) => ripemd160(sha256(b));
const dsha = (b) => sha256(sha256(b));
const toHex = (b) => Array.from(b, (x) => x.toString(16).padStart(2, "0")).join("");
const fromHex = (h) => Uint8Array.from((h.match(/../g) || []), (x) => parseInt(x, 16));
const concat = (...ps) => { const n = ps.reduce((a, p) => a + p.length, 0); const o = new Uint8Array(n); let k = 0; for (const p of ps) { o.set(p, k); k += p.length; } return o; };
const u32le = (n) => Uint8Array.from([n & 0xff, (n >>> 8) & 0xff, (n >>> 16) & 0xff, (n >>> 24) & 0xff]);
const u64le = (n) => { let v = BigInt(n); const o = new Uint8Array(8); for (let i = 0; i < 8; i++) { o[i] = Number(v & 0xffn); v >>= 8n; } return o; };
const varint = (n) => {
if (n < 0xfd) return Uint8Array.from([n]);
if (n <= 0xffff) return Uint8Array.from([0xfd, n & 0xff, (n >> 8) & 0xff]);
return concat(Uint8Array.from([0xfe]), u32le(n));
};
const varbytes = (b) => concat(varint(b.length), b);
const { rootFromSeed, accountNode, addressNode, p2wpkhAddress, digibyte, DGB_COIN_TYPE } = dgbCore;
const { buildPsbt, signAllInputs, finalizeAndExtract, feeSats } = dgbPsbt;
const { payments, Psbt } = bitcoinjs;
const bip32 = bip32Factory(ecc);
const ECPair = ecpairFactory(ecc);
// ---- addresses --------------------------------------------------------
// dgb1q…: bech32 (BIP173), witness version 0, program = h160(pubkey).
function encodeSegwitV0(h160) {
// @scure/base bech32.encode takes hrp and 5-bit words; the version byte
// is prepended verbatim (no toWords for it).
const words = [0, ...bech32.toWords(h160)];
return bech32.encode(HRP, words);
const toHex = (b) => Buffer.from(b).toString("hex");
// Electrum scripthash: sha256(scriptPubKey), byte-reversed, hex.
function scripthashOf(scriptBuf) {
const h = sha256(scriptBuf);
const rev = Buffer.from(h).reverse();
return rev.toString("hex");
}
function decodeAddress(str) {
const s = String(str || "").trim().toLowerCase();
if (!s.startsWith(HRP + "1")) throw new Error(`not a DGB bech32 address (want ${HRP}1…)`);
const dec = bech32.decode(s);
if (dec.prefix !== HRP) throw new Error(`bad HRP: ${dec.prefix}`);
const version = dec.words[0];
const program = bech32.fromWords(dec.words.slice(1));
if (version !== 0 || program.length !== 20) {
throw new Error("only P2WPKH (dgb1q…, 20-byte program) is supported in this build");
}
return { version, program: Uint8Array.from(program) };
function scriptPubKeyBuf(pubkeyBuf) {
return payments.p2wpkh({ pubkey: pubkeyBuf, network: digibyte }).output;
}
function scriptPubKeyOf(address) {
const { program } = decodeAddress(address);
return concat(Uint8Array.from([0x00, 0x14]), program); // OP_0 <20>
}
// electrum scripthash: sha256(script), byte-reversed, hex.
const scripthash = (script) => toHex(sha256(script).slice().reverse());
// ---- keys -------------------------------------------------------------
// ---- keys --------------------------------------------------------------
// The HD node is the sole owner of the private key material; every derived
// entry keeps a reference so PSBT.signInput(index, node) can sign each
// input under its own key.
class WalletKeys {
constructor(root32, accountPath = DEFAULT_ACCOUNT_PATH) {
this._accountPath = /^m(\/\d+'?)+$/.test(accountPath) ? accountPath : DEFAULT_ACCOUNT_PATH;
this._account = HDKey.fromMasterSeed(root32).derive(this._accountPath);
this._branch = [this._account.deriveChild(0), this._account.deriveChild(1)];
constructor(root32, accountPath) {
const purpose = parsePurposeFromPath(accountPath) || DEFAULT_PURPOSE;
this._purpose = purpose;
// bip32.fromSeed uses bitcoinjs-lib's Network object — pass DGB's so
// extended keys serialize with the right BIP32 magic (0x0488B21E).
this._root = bip32.fromSeed(Buffer.from(root32), digibyte);
this._account = this._root.derivePath(`m/${purpose}'/${DGB_COIN_TYPE}'/0'`);
this._accountPath = `m/${purpose}'/${DGB_COIN_TYPE}'/0'`;
this._branch = [this._account.derive(0), this._account.derive(1)];
this._cache = new Map();
}
get xpub() { return this._account.publicExtendedKey; }
get xprv() { return this._account.privateExtendedKey; }
get xpub() { return this._account.neutered().toBase58(); }
get xprv() { return this._account.toBase58(); }
get accountPath() { return this._accountPath; }
entry(branch, index) {
const k = branch + "/" + index;
let e = this._cache.get(k);
if (!e) {
const node = this._branch[branch].deriveChild(index);
const compressed = secp256k1.getPublicKey(node.privateKey, true);
const h160 = hash160(compressed);
const script = concat(Uint8Array.from([0x00, 0x14]), h160);
const address = encodeSegwitV0(h160);
const node = this._branch[branch].derive(index);
const pubkey = Buffer.from(node.publicKey);
const address = p2wpkhAddress(node, digibyte);
const script = Buffer.from(scriptPubKeyBuf(pubkey));
e = {
branch, index, path: this._accountPath + "/" + branch + "/" + index,
publicKey: compressed, h160, script, scriptHex: toHex(script),
scripthash: scripthash(script),
address, _node: node,
publicKey: pubkey, script, scriptHex: script.toString("hex"),
scripthash: scripthashOf(script),
address,
_node: node,
};
this._cache.set(k, e);
}
return e;
}
signDigest(entry, digest32) {
// BIP143 sighash uses ECDSA over the preimage double-sha; signature is
// low-S DER with sighash byte appended by the caller.
const sig = secp256k1.sign(digest32, entry._node.privateKey, { prehash: false, lowS: true, format: "der" });
return sig;
signerFor(entry) {
// bitcoinjs-lib's PSBT accepts anything with .publicKey + .sign(hash).
// BIP32Interface fits, but ECPair.fromPrivateKey gives a plain signer
// that matches what the DGB web-wallet uses — pick that for parity.
return ECPair.fromPrivateKey(Buffer.from(entry._node.privateKey), { network: digibyte });
}
wipe() {
for (const e of this._cache.values()) { try { e._node.wipePrivateData(); } catch {} }
// BIP32Interface holds Buffers; drop references so GC picks them up.
for (const e of this._cache.values()) e._node = null;
this._cache.clear();
for (const b of this._branch) try { b.wipePrivateData(); } catch {}
try { this._account.wipePrivateData(); } catch {}
this._branch = null;
this._account = null;
this._root = null;
}
}
// ---- BIP143 P2WPKH sighash + tx serialize -----------------------------
// Legacy scriptSigs are empty for pure-SegWit tx; witnesses carry the sig.
const SIGHASH_ALL = 0x01;
function scriptCodeFor(h160) {
// 0x1976a914{h160}88ac wrapped as varlen bytes for the sighash preimage.
return varbytes(concat(Uint8Array.from([0x76, 0xa9, 0x14]), h160, Uint8Array.from([0x88, 0xac])));
}
function sighashP2WPKH(txDraft, inputIndex) {
const version = u32le(2);
const locktime = u32le(0);
const sequence = u32le(0xffffffff);
const hashPrevouts = dsha(concat(...txDraft.inputs.map((i) => concat(fromHex(i.txid).reverse(), u32le(i.vout)))));
const hashSequence = dsha(concat(...txDraft.inputs.map(() => sequence)));
const hashOutputs = dsha(concat(...txDraft.outputs.map((o) => concat(u64le(o.value), varbytes(o.script)))));
const inp = txDraft.inputs[inputIndex];
const outpoint = concat(fromHex(inp.txid).reverse(), u32le(inp.vout));
const preimage = concat(
version, hashPrevouts, hashSequence, outpoint,
scriptCodeFor(inp.entry.h160), u64le(inp.value), sequence,
hashOutputs, locktime, u32le(SIGHASH_ALL),
);
return dsha(preimage);
}
function serializeWithWitnesses(txDraft, witnesses) {
const version = u32le(2);
const locktime = u32le(0);
const sequence = u32le(0xffffffff);
// marker/flag come between input-count and inputs.
return concat(
version,
Uint8Array.from([0x00, 0x01]),
varint(txDraft.inputs.length),
...txDraft.inputs.map((i) => concat(fromHex(i.txid).reverse(), u32le(i.vout), varbytes(new Uint8Array(0)), sequence)),
varint(txDraft.outputs.length),
...txDraft.outputs.map((o) => concat(u64le(o.value), varbytes(o.script))),
...witnesses.map((stack) => concat(varint(stack.length), ...stack.map(varbytes))),
locktime,
);
}
function txidOf(txDraft) {
const version = u32le(2);
const locktime = u32le(0);
const sequence = u32le(0xffffffff);
const noWitness = concat(
version,
varint(txDraft.inputs.length),
...txDraft.inputs.map((i) => concat(fromHex(i.txid).reverse(), u32le(i.vout), varbytes(new Uint8Array(0)), sequence)),
varint(txDraft.outputs.length),
...txDraft.outputs.map((o) => concat(u64le(o.value), varbytes(o.script))),
locktime,
);
return toHex(dsha(noWitness).slice().reverse());
function parsePurposeFromPath(p) {
const m = /^m\/(\d+)'\/\d+'\/\d+'$/.exec(String(p || ""));
return m ? Number(m[1]) : null;
}
// Rough vsize model for fee selection: base tx + 1 P2WPKH out per output +
// per-input contribution (BIP141 discounts witness data by 4×).
// ---- vsize model (fee estimation ahead of PSBT.getFee) -----------------
const OVERHEAD_VB = 10.5;
const P2WPKH_INPUT_VB = 68; // ~ (41 base + 108 witness/4)
const P2WPKH_INPUT_VB = 68;
const P2WPKH_OUTPUT_VB = 31;
const feeVb = (nIn, nOut, feePerVb) => Math.ceil((OVERHEAD_VB + nIn * P2WPKH_INPUT_VB + nOut * P2WPKH_OUTPUT_VB) * feePerVb);
@ -188,7 +132,7 @@ module.exports = function makeDgbAdapter({
class DgbWallet {
constructor(root32, {
walletId, storage, log = () => {}, onChange = () => {}, servers,
accountPath = DEFAULT_ACCOUNT_PATH,
accountPath,
} = {}) {
if (!walletId) throw new Error("chain-dgb: walletId required");
this.walletId = walletId;
@ -204,7 +148,7 @@ module.exports = function makeDgbAdapter({
this._client.onServer = () => this._emit();
this._state = {
used: new Set(),
watched: new Map(), // scripthash -> entry
watched: new Map(),
height: 0,
balance: { confirmed: 0, unconfirmed: 0 },
utxos: [],
@ -215,8 +159,6 @@ module.exports = function makeDgbAdapter({
};
this._refreshTimer = null;
this._subscribedHeaders = false;
// DGB's electrum notifications behave the same as BCH's — hook the
// client's onNotify to a debounced re-refresh.
this._client.onNotify = (method, params) => {
if (method === "blockchain.headers.subscribe") {
const h = params && params[0] && params[0].height;
@ -229,7 +171,7 @@ module.exports = function makeDgbAdapter({
_emit() { try { this.onChange(); } catch {} }
// ---- discovery + refresh (gap-limit) --------------------------------
// ---- discovery (gap-limit) -----------------------------------------
async _historyOf(entry) {
const h = await this._client.call("blockchain.scripthash.get_history", [entry.scripthash]);
return Array.isArray(h) ? h : [];
@ -278,11 +220,9 @@ module.exports = function makeDgbAdapter({
this._state.balance = { confirmed, unconfirmed };
}
async _loadHistory() {
// Minimal shape — enough for the panel to show tx rows. Deep decoding
// (per-input attribution, "sent to" heuristic) is skipped for the
// first DGB rev; delta comes from listunspent-derived UTXOs plus the
// scripthash history height. Real per-tx delta requires get_transaction
// (verbose) which DGB electrum supports; wired here as best effort.
// Best-effort tx-history summary: pull the transactions listed against
// any used scripthash, sum ours-vs-not to get a delta per tx. Fine on
// the DGB electrum pool (get_transaction verbose is supported).
const entries = [...this._state.watched.values()].filter((e) => this._state.used.has(e.branch + "/" + e.index));
const merged = new Map();
const lists = await Promise.all(entries.map((e) => this._historyOf(e)));
@ -320,7 +260,7 @@ module.exports = function makeDgbAdapter({
status: (t.confirmations || 0) > 0 ? "confirmed" : "pending",
kind: "transfer",
});
} catch (e) {
} catch {
out.push({ txid: h.txid, height: h.height, confirmations: 0, time: 0, delta: 0, fee: null, to: null, status: "pending", kind: "transfer" });
}
}
@ -357,7 +297,6 @@ module.exports = function makeDgbAdapter({
this._refreshTimer = setTimeout(() => this.refresh(false), ms);
}
// ---- addresses -------------------------------------------------------
current() { return this._keys.entry(0, this._state.receiveIndex); }
nextAddress() {
let r = this._state.receiveIndex + 1;
@ -381,12 +320,19 @@ module.exports = function makeDgbAdapter({
this._client.setServers(this._servers);
}
// ---- plan + sign -----------------------------------------------------
// ---- plan + sign (via @dgb-wallet/psbt) -----------------------------
plan({ to, amount, feeRate = 20, sendMax = false }) {
const rate = Math.min(500, Math.max(1, Number(feeRate) || 20)); // sat/vB
const script = scriptPubKeyOf(String(to || ""));
const targets = [{ value: sendMax ? 0 : Math.round(Number(amount) || 0), script, to: String(to) }];
// Spend confirmed first; unconfirmed if needed.
const rate = Math.min(500, Math.max(1, Number(feeRate) || 20));
const dest = String(to || "");
// The `payments` decoder will reject anything that isn't a valid
// DGB address; catch and re-raise as a sane error.
try { payments.address({ address: dest, network: digibyte }); }
catch {
// bitcoinjs-lib's address decoder is `address.toOutputScript`, not
// payments.address; use it for validation.
try { bitcoinjs.address.toOutputScript(dest, digibyte); }
catch (e) { throw new Error(`bad DGB address: ${e?.message || dest}`); }
}
const spendable = this._state.utxos.slice().sort((a, b) => (b.height > 0) - (a.height > 0));
const change = this._changeEntry();
if (sendMax) {
@ -394,29 +340,29 @@ module.exports = function makeDgbAdapter({
const sum = chosen.reduce((a, u) => a + u.value, 0);
const fee = feeVb(chosen.length, 1, rate);
if (sum <= fee) throw new Error("balance does not cover the fee");
targets[0].value = sum - fee;
return {
inputs: chosen, outputs: [{ value: sum - fee, script, to }],
_chosen: chosen, _rate: rate, _to: dest, _sendMax: true, _change: change,
recipients: [{ to: dest, value: sum - fee }],
fee, feeRate: rate, change: 0,
recipients: [{ to, value: sum - fee }], total: sum,
total: sum,
};
}
if (!(targets[0].value > 0)) throw new Error("amount must be > 0");
const value = Math.round(Number(amount) || 0);
if (!(value > 0)) throw new Error("amount must be > 0");
let sum = 0; const chosen = [];
for (const u of spendable) {
chosen.push(u); sum += u.value;
const withChange = feeVb(chosen.length, 2, rate);
if (sum >= targets[0].value + withChange) {
const changeVal = sum - targets[0].value - withChange;
const outs = changeVal > 546
? [targets[0], { value: changeVal, script: change.script, to: change.address }]
: [targets[0]];
const fee = changeVal > 546 ? withChange : sum - targets[0].value;
if (sum >= value + withChange) {
const changeVal = sum - value - withChange;
const fee = changeVal > 546 ? withChange : sum - value;
return {
inputs: chosen, outputs: outs, fee, feeRate: rate,
_chosen: chosen, _rate: rate, _to: dest, _value: value,
_change: change, _changeVal: changeVal > 546 ? changeVal : 0,
recipients: [{ to: dest, value }],
fee, feeRate: rate,
change: changeVal > 546 ? changeVal : 0,
recipients: [{ to, value: targets[0].value }],
total: targets[0].value + fee,
total: value + fee,
};
}
}
@ -424,23 +370,34 @@ module.exports = function makeDgbAdapter({
}
async signAndBroadcast(plan) {
const witnesses = plan.inputs.map((_, i) => {
const digest = sighashP2WPKH(plan, i);
const sigDer = this._keys.signDigest(plan.inputs[i].entry, digest);
const sigWithHash = concat(sigDer, Uint8Array.from([SIGHASH_ALL]));
return [sigWithHash, plan.inputs[i].entry.publicKey];
});
const rawTx = serializeWithWitnesses(plan, witnesses);
const rawHex = toHex(rawTx);
const txid = await this._client.call("blockchain.transaction.broadcast", [rawHex]);
if (typeof txid !== "string" || txid.length !== 64) throw new Error("broadcast rejected: " + JSON.stringify(txid));
const psbtInputs = plan._chosen.map((u) => ({
txid: u.txid,
vout: u.vout,
witness: { scriptHex: u.entry.scriptHex, value: u.value },
}));
const psbtOutputs = [{ address: plan._to, value: plan._sendMax ? plan.recipients[0].value : plan._value }];
if (!plan._sendMax && plan._changeVal > 0) {
psbtOutputs.push({ address: plan._change.address, value: plan._changeVal });
}
const psbt = buildPsbt({ inputs: psbtInputs, outputs: psbtOutputs }, digibyte);
// Sign per-input with the exact key that funded that UTXO. signAllInputs
// would work when all inputs share a key, but each derived address
// has its own key, so we go per-input.
for (let i = 0; i < plan._chosen.length; i++) {
const signer = this._keys.signerFor(plan._chosen[i].entry);
psbt.signInput(i, signer);
}
const { hex, txid } = finalizeAndExtract(psbt);
const broadcast = await this._client.call("blockchain.transaction.broadcast", [hex]);
if (typeof broadcast !== "string" || broadcast.length !== 64) {
throw new Error("broadcast rejected: " + JSON.stringify(broadcast));
}
this.log("broadcast", txid);
this._scheduleRefresh(1200);
return { txid, hex: rawHex, fee: plan.fee };
return { txid, hex, fee: plan.fee };
}
// Minimal BIP-137-style signature over sha256d of the message with a
// "DigiByte Signed Message:\n" magic — parallels the BCH build.
// BIP-137-style: 65-byte recoverable signature over sha256d(magic || msg).
signMessage(message) {
const enc = new TextEncoder();
const varstr = (s) => { const b = enc.encode(s); if (b.length >= 0xfd) throw new Error("too long"); return Uint8Array.from([b.length, ...b]); };
@ -448,11 +405,15 @@ module.exports = function makeDgbAdapter({
const payload = Uint8Array.from([...varstr(MAGIC), ...varstr(String(message))]);
const digest = sha256(sha256(payload));
const entry = this.current();
const sig = secp256k1.sign(digest, entry._node.privateKey, { prehash: false, lowS: true, format: "recovered" });
const out = new Uint8Array(65);
out[0] = 27 + sig[0] + 4; // 4 = compressed
out.set(sig.subarray(1), 1);
return { address: entry.address, signature: Buffer.from(out).toString("base64") };
const signer = this._keys.signerFor(entry);
// ECPair's `signSchnorr` and `sign` don't emit recoverable sigs; fall
// back to node's ecc.signRecoverable through @bitcoinerlab/secp256k1
// (which the vendored @dgb-wallet/core already loaded).
const sig = ecc.signRecoverable(Buffer.from(digest), signer.privateKey);
const out = Buffer.alloc(65);
out[0] = 27 + sig.recoveryId + 4; // +4 = compressed pubkey
Buffer.from(sig.signature).copy(out, 1);
return { address: entry.address, signature: out.toString("base64") };
}
recovery() {
@ -486,5 +447,5 @@ module.exports = function makeDgbAdapter({
}
}
return { DgbWallet, DEFAULT_ACCOUNT_PATH, HRP, EXPLORER_TX, EXPLORER_ADDR, encodeSegwitV0, decodeAddress };
return { DgbWallet, EXPLORER_TX, EXPLORER_ADDR };
};

View file

@ -0,0 +1,10 @@
import type { BIP32Interface } from 'bip32';
import { type Network } from './network.js';
export declare function p2pkhAddress(node: BIP32Interface, network?: Network): string;
export declare function p2shP2wpkhAddress(node: BIP32Interface, network?: Network): string;
export declare function p2shP2wpkhAddressesBoth(node: BIP32Interface): {
modern: string;
legacy: string;
};
export declare function p2wpkhAddress(node: BIP32Interface, network?: Network): string;
export declare function p2trAddress(node: BIP32Interface, network?: Network): string;

View file

@ -0,0 +1,53 @@
import { payments, initEccLib } from 'bitcoinjs-lib';
import * as ecc from '@bitcoinerlab/secp256k1';
import { digibyte, digibyteLegacyP2SH } from './network.js';
// Required for Taproot address derivation (P2TR).
initEccLib(ecc);
export function p2pkhAddress(node, network = digibyte) {
const { address } = payments.p2pkh({
pubkey: Buffer.from(node.publicKey),
network,
});
if (!address)
throw new Error('p2pkh derivation returned no address');
return address;
}
export function p2shP2wpkhAddress(node, network = digibyte) {
const redeem = payments.p2wpkh({
pubkey: Buffer.from(node.publicKey),
network,
});
const { address } = payments.p2sh({ redeem, network });
if (!address)
throw new Error('p2sh-p2wpkh derivation returned no address');
return address;
}
// Derive the "S..." (current DGB, scriptHash 0x3f) AND "3..." (legacy
// Bitcoin-compatible, scriptHash 0x05) BIP49 addresses for the same
// key. Ian Coleman's BIP39 tool and several older wallets generate the
// legacy "3..." variant, so any seed-recovery scan must check both.
export function p2shP2wpkhAddressesBoth(node) {
return {
modern: p2shP2wpkhAddress(node, digibyte),
legacy: p2shP2wpkhAddress(node, digibyteLegacyP2SH),
};
}
export function p2wpkhAddress(node, network = digibyte) {
const { address } = payments.p2wpkh({
pubkey: Buffer.from(node.publicKey),
network,
});
if (!address)
throw new Error('p2wpkh derivation returned no address');
return address;
}
// BIP86 Taproot address using the x-only pubkey with no script tree,
// which applies the standard BIP86 tweak internally in bitcoinjs-lib.
export function p2trAddress(node, network = digibyte) {
const internalPubkey = Buffer.from(node.publicKey.subarray(1, 33));
const { address } = payments.p2tr({ internalPubkey, network });
if (!address)
throw new Error('p2tr derivation returned no address');
return address;
}
//# sourceMappingURL=address.js.map

View file

@ -0,0 +1,5 @@
import type { BIP32Interface } from 'bip32';
import type { Purpose } from './hd.js';
export declare function derivationPath(purpose: Purpose, account: number, change: 0 | 1, index: number): string;
export declare function accountXpub(accountNode: BIP32Interface): string;
export declare function accountXprv(accountNode: BIP32Interface): string;

View file

@ -0,0 +1,18 @@
import { DGB_COIN_TYPE } from './network.js';
// Convenience helper: full derivation-path string for a specific
// address, e.g. m/84'/20'/0'/0/5.
export function derivationPath(purpose, account, change, index) {
return `m/${purpose}'/${DGB_COIN_TYPE}'/${account}'/${change}/${index}`;
}
// xpub for an account, ready to be shared with a watch-only or
// external indexer. Never share the corresponding xprv.
export function accountXpub(accountNode) {
return accountNode.neutered().toBase58();
}
export function accountXprv(accountNode) {
if (!accountNode.privateKey) {
throw new Error('Node has no private key; cannot export xprv');
}
return accountNode.toBase58();
}
//# sourceMappingURL=descriptor.js.map

View file

@ -0,0 +1,8 @@
import { type BIP32Interface } from 'bip32';
import { type Network } from './network.js';
export type Purpose = 44 | 49 | 84 | 86;
export declare const PURPOSE_LABEL: Record<Purpose, string>;
export declare function rootFromSeed(seed: Buffer, network?: Network): BIP32Interface;
export declare function accountNode(root: BIP32Interface, purpose: Purpose, account?: number): BIP32Interface;
export declare function addressNode(account: BIP32Interface, change: 0 | 1, index: number): BIP32Interface;
export type { BIP32Interface };

View file

@ -0,0 +1,24 @@
import { BIP32Factory } from 'bip32';
import * as ecc from '@bitcoinerlab/secp256k1';
import { digibyte, DGB_COIN_TYPE } from './network.js';
const bip32 = BIP32Factory(ecc);
export const PURPOSE_LABEL = {
44: 'BIP44 legacy P2PKH',
49: 'BIP49 P2SH-wrapped SegWit',
84: 'BIP84 native SegWit v0',
86: 'BIP86 Taproot (SegWit v1)',
};
export function rootFromSeed(seed, network = digibyte) {
return bip32.fromSeed(seed, network);
}
// Standard account-level derivation: m/purpose'/coin'/account'.
// account defaults to 0 (the first account).
export function accountNode(root, purpose, account = 0) {
return root.derivePath(`m/${purpose}'/${DGB_COIN_TYPE}'/${account}'`);
}
// Address-level derivation from an account node.
// change = 0 for external (receive) addresses, 1 for internal (change).
export function addressNode(account, change, index) {
return account.derive(change).derive(index);
}
//# sourceMappingURL=hd.js.map

View file

@ -0,0 +1,6 @@
export * from './network.js';
export * from './seed.js';
export * from './hd.js';
export * from './address.js';
export * from './wif.js';
export * from './descriptor.js';

View file

@ -0,0 +1,7 @@
export * from './network.js';
export * from './seed.js';
export * from './hd.js';
export * from './address.js';
export * from './wif.js';
export * from './descriptor.js';
//# sourceMappingURL=index.js.map

View file

@ -0,0 +1,13 @@
import type { networks } from 'bitcoinjs-lib';
export type Network = (typeof networks)['bitcoin'];
export declare const digibyte: Network;
export declare const digibyteLegacyP2SH: Network;
export declare const digibyteLegacyWIF: Network;
export declare const digibyteTestnet: Network;
export declare const DGB_COIN_TYPE = 20;
export declare const DGB_P2P: {
readonly magic: 3669410810;
readonly defaultPort: 12024;
readonly rpcPort: 14022;
readonly dnsSeeds: readonly ["seed.digibyte.io", "seed.diginode.tools", "seed.digibyte.link", "seed.aroundtheblock.app", "seed.tuyul.cc"];
};

View file

@ -0,0 +1,74 @@
// DigiByte mainnet parameters. Sourced from
// github.com/DigiByte-Core/digibyte src/kernel/chainparams.cpp CMainParams.
//
// Note on scriptHash: DGB Core defines BOTH SCRIPT_ADDRESS = 0x3f ("S..."
// addresses, the current default) and SCRIPT_ADDRESS2 = 0x05 ("3..."
// addresses, kept for Bitcoin compatibility). Older BIP39 tools and
// wallets that forked bitcoinjs-lib params generate 3-addresses; current
// DGB Core generates S-addresses. `digibyte` below uses the current
// default; use `digibyteLegacyP2SH` when recovering from Ian Coleman's
// BIP39 tool, older Atomic/Exodus vintages, or anything else that
// inherited Bitcoin's 0x05 P2SH byte. Both are valid on-chain.
export const digibyte = {
messagePrefix: '\x19DigiByte Signed Message:\n',
bech32: 'dgb',
bip32: {
public: 0x0488b21e,
private: 0x0488ade4,
},
pubKeyHash: 0x1e,
scriptHash: 0x3f,
wif: 0x80,
};
// Same as `digibyte`, but with the legacy Bitcoin-compatible P2SH
// version byte. Use for producing/scanning "3..."-style P2SH addresses
// during seed recovery from tools that predate the 0x3f switch.
// DGB Core keeps SCRIPT_ADDRESS_OLD = 5 for backward compatibility.
export const digibyteLegacyP2SH = {
...digibyte,
scriptHash: 0x05,
};
// Same as `digibyte`, but with the legacy WIF version byte.
// DGB Core keeps SECRET_KEY_OLD = 158 (0x9e) for backward compatibility.
// Older DGB tools may have exported private keys with this prefix.
// The wallet's WIF-import path should try both `digibyte` and this
// variant before rejecting a key.
export const digibyteLegacyWIF = {
...digibyte,
wif: 0x9e,
};
// DigiByte testnet parameters. From CTestNetParams in chainparams.cpp.
export const digibyteTestnet = {
messagePrefix: '\x19DigiByte Signed Message:\n',
bech32: 'dgbt',
bip32: {
public: 0x043587cf,
private: 0x04358394,
},
pubKeyHash: 0x7e,
scriptHash: 0x8c,
wif: 0xef,
};
// SLIP-0044 registered coin type.
export const DGB_COIN_TYPE = 20;
// P2P network constants (unused by @dgb-wallet/core itself, exposed for
// the P2P client package that will consume them).
export const DGB_P2P = {
// pchMessageStart in DGB Core chainparams.cpp is the byte sequence
// 0xFA 0xC3 0xB6 0xDA on the wire. `writeUInt32LE(magic)` writes
// least-significant-byte first, so the integer value stored here must
// be the LE-reading: 0xDAB6C3FA (byte 0 = 0xFA, byte 3 = 0xDA).
// Getting this wrong means peers see wrong-network frames and close
// immediately at handshake.
magic: 0xdab6c3fa,
defaultPort: 12024,
rpcPort: 14022,
dnsSeeds: [
'seed.digibyte.io',
'seed.diginode.tools',
'seed.digibyte.link',
'seed.aroundtheblock.app',
'seed.tuyul.cc',
],
};
//# sourceMappingURL=network.js.map

View file

@ -0,0 +1 @@
{"type":"module","main":"./index.js"}

View file

@ -0,0 +1,4 @@
export type SeedStrength = 128 | 160 | 192 | 224 | 256;
export declare function generateSeedPhrase(strength?: SeedStrength): string;
export declare function validateSeedPhrase(phrase: string, wordlist?: string[]): boolean;
export declare function seedFromPhrase(phrase: string, passphrase?: string): Promise<Buffer>;

View file

@ -0,0 +1,17 @@
import { generateMnemonic, validateMnemonic, mnemonicToSeed, wordlists, } from 'bip39';
// Word count → entropy strength for BIP39.
// 12 → 128, 15 → 160, 18 → 192, 21 → 224, 24 → 256.
export function generateSeedPhrase(strength = 128) {
return generateMnemonic(strength);
}
// BIP39 checksum + wordlist validation. Returns false for typos, bad
// word counts, and out-of-wordlist words.
export function validateSeedPhrase(phrase, wordlist = wordlists.english) {
return validateMnemonic(phrase.trim(), wordlist);
}
// BIP39 seed derivation. Passphrase is the optional "25th word";
// changing it produces a different wallet from the same mnemonic.
export async function seedFromPhrase(phrase, passphrase = '') {
return mnemonicToSeed(phrase.trim(), passphrase);
}
//# sourceMappingURL=seed.js.map

View file

@ -0,0 +1,27 @@
import { type ECPairInterface } from 'ecpair';
import { type Network } from './network.js';
export type WifImportResult = {
keyPair: ECPairInterface;
variant: 'modern' | 'legacy';
};
export declare function importWif(wif: string): WifImportResult;
export declare function importWifStrict(wif: string, network?: Network): ECPairInterface;
export declare function exportWif(keyPair: ECPairInterface): string;
export interface PubkeyAddresses {
p2pkh: string;
p2shP2wpkhModern: string;
p2shP2wpkhLegacy: string;
p2wpkh: string;
p2tr: string;
scripts: {
p2pkh: string;
p2shP2wpkh: string;
p2wpkh: string;
p2tr: string;
};
}
export declare function addressesForPubkey(pubkey: Buffer, network?: Network): PubkeyAddresses;
export interface WifImportWithAddresses extends WifImportResult, PubkeyAddresses {
}
export declare function importWifWithAddresses(wif: string): WifImportWithAddresses;
export type { ECPairInterface };

View file

@ -0,0 +1,72 @@
import { ECPairFactory } from 'ecpair';
import * as ecc from '@bitcoinerlab/secp256k1';
import { payments, initEccLib } from 'bitcoinjs-lib';
import { digibyte, digibyteLegacyP2SH, digibyteLegacyWIF } from './network.js';
const ECPair = ECPairFactory(ecc);
initEccLib(ecc);
// Import a DigiByte private key in WIF (Wallet Import Format).
// Tries the modern 0x80 prefix first, falls back to the legacy 0x9e
// prefix that older DGB tools produced. Rejects anything else with a
// clear message that identifies the network mismatch.
export function importWif(wif) {
const trimmed = wif.trim();
try {
return { keyPair: ECPair.fromWIF(trimmed, digibyte), variant: 'modern' };
}
catch {
// fall through to legacy attempt
}
try {
return { keyPair: ECPair.fromWIF(trimmed, digibyteLegacyWIF), variant: 'legacy' };
}
catch (e) {
throw new Error(`Not a valid DigiByte WIF (tried both current 0x80 and legacy 0x9e prefixes). ` +
`Underlying error: ${e.message}. Check the key is for DGB mainnet, not testnet or another chain.`);
}
}
// Import against a specific network only (advanced / testing).
export function importWifStrict(wif, network = digibyte) {
return ECPair.fromWIF(wif.trim(), network);
}
export function exportWif(keyPair) {
return keyPair.toWIF();
}
export function addressesForPubkey(pubkey, network = digibyte) {
const p2pkh = payments.p2pkh({ pubkey, network });
const wpkhRedeem = payments.p2wpkh({ pubkey, network });
// bitcoinjs-lib enforces `redeem.network === outerNetwork` (identity
// comparison, not shape). To render the legacy 3-prefix P2SH address
// we need a fresh redeem whose .network property is the legacy variant
// — same bytes on the wire, different object identity.
const wpkhRedeemLegacy = payments.p2wpkh({ pubkey, network: digibyteLegacyP2SH });
const p2shModern = payments.p2sh({ redeem: wpkhRedeem, network });
const p2shLegacy = payments.p2sh({ redeem: wpkhRedeemLegacy, network: digibyteLegacyP2SH });
const p2wpkh = payments.p2wpkh({ pubkey, network });
const p2tr = payments.p2tr({ internalPubkey: pubkey.subarray(1, 33), network });
if (!p2pkh.address || !p2shModern.address || !p2shLegacy.address || !p2wpkh.address || !p2tr.address) {
throw new Error('bitcoinjs-lib returned an empty address for one of the payment types');
}
if (!p2pkh.output || !p2shModern.output || !p2wpkh.output || !p2tr.output) {
throw new Error('bitcoinjs-lib returned an empty scriptPubKey for one of the payment types');
}
return {
p2pkh: p2pkh.address,
p2shP2wpkhModern: p2shModern.address,
p2shP2wpkhLegacy: p2shLegacy.address,
p2wpkh: p2wpkh.address,
p2tr: p2tr.address,
scripts: {
p2pkh: Buffer.from(p2pkh.output).toString('hex'),
p2shP2wpkh: Buffer.from(p2shModern.output).toString('hex'),
p2wpkh: Buffer.from(p2wpkh.output).toString('hex'),
p2tr: Buffer.from(p2tr.output).toString('hex'),
},
};
}
export function importWifWithAddresses(wif) {
const imported = importWif(wif);
const pubkey = Buffer.from(imported.keyPair.publicKey);
const addrs = addressesForPubkey(pubkey);
return { ...imported, ...addrs };
}
//# sourceMappingURL=wif.js.map

View file

@ -0,0 +1,4 @@
import { Psbt } from 'bitcoinjs-lib';
import { type Network } from '@dgb-wallet/core';
import type { BuildParams } from './types.js';
export declare function buildPsbt(params: BuildParams, network?: Network): Psbt;

View file

@ -0,0 +1,56 @@
import { Psbt } from 'bitcoinjs-lib';
import { digibyte } from '../core/index.js';
// Construct an unsigned PSBT from a set of UTXOs and destination outputs.
// Does not add a change output — the caller decides change amount and
// address. Does not compute fees — the caller must have already subtracted
// fee from outputs.
export function buildPsbt(params, network = digibyte) {
const psbt = new Psbt({ network });
const inputs = params.sortBip69 === false ? params.inputs : sortInputs(params.inputs);
const outputs = params.sortBip69 === false ? params.outputs : sortOutputs(params.outputs);
for (const u of inputs) {
psbt.addInput(inputToPsbtInput(u));
}
for (const o of outputs) {
psbt.addOutput({ address: o.address, value: o.value });
}
return psbt;
}
function inputToPsbtInput(u) {
const input = {
hash: u.txid,
index: u.vout,
};
if (u.witness) {
input.witnessUtxo = {
script: Buffer.from(u.witness.scriptHex, 'hex'),
value: u.witness.value,
};
}
if (u.nonWitnessTxHex) {
input.nonWitnessUtxo = Buffer.from(u.nonWitnessTxHex, 'hex');
}
if (u.redeemScriptHex) {
input.redeemScript = Buffer.from(u.redeemScriptHex, 'hex');
}
if (u.tapInternalKeyHex) {
input.tapInternalKey = Buffer.from(u.tapInternalKeyHex, 'hex');
}
return input;
}
// BIP69 lexicographic ordering. Improves privacy by not revealing input
// selection order (which can hint at wallet coin-selection strategy).
function sortInputs(inputs) {
return [...inputs].sort((a, b) => {
const cmp = a.txid.localeCompare(b.txid);
return cmp !== 0 ? cmp : a.vout - b.vout;
});
}
function sortOutputs(outputs) {
return [...outputs].sort((a, b) => {
if (a.value !== b.value)
return a.value - b.value;
return a.address.localeCompare(b.address);
});
}
//# sourceMappingURL=build.js.map

View file

@ -0,0 +1,3 @@
export * from './types.js';
export * from './build.js';
export * from './sign.js';

View file

@ -0,0 +1,4 @@
export * from './types.js';
export * from './build.js';
export * from './sign.js';
//# sourceMappingURL=index.js.map

View file

@ -0,0 +1 @@
{"type":"module","main":"./index.js"}

View file

@ -0,0 +1,9 @@
import type { Psbt } from 'bitcoinjs-lib';
import type { ECPairInterface } from 'ecpair';
export declare function signAllInputs(psbt: Psbt, keyPair: ECPairInterface): Psbt;
export declare function finalizeAndExtract(psbt: Psbt): {
hex: string;
txid: string;
};
export declare function feeSats(psbt: Psbt): number;
export declare function feeRateSatsPerByte(psbt: Psbt): number;

View file

@ -0,0 +1,25 @@
// Sign every input of a PSBT with the given key. Fails loudly if any
// input can't be signed by this key (rather than silently leaving it
// unsigned), so callers notice before broadcasting a half-signed tx.
export function signAllInputs(psbt, keyPair) {
psbt.signAllInputs(keyPair);
return psbt;
}
// After all inputs are signed by all necessary parties, finalize and
// extract the network-ready hex-encoded transaction.
export function finalizeAndExtract(psbt) {
psbt.finalizeAllInputs();
const tx = psbt.extractTransaction();
return { hex: tx.toHex(), txid: tx.getId() };
}
// Fee computed from the difference between total input value and total
// output value. Requires all inputs to have witnessUtxo or
// nonWitnessUtxo populated (which `buildPsbt` in this package
// guarantees when the caller populates Utxo.value fields).
export function feeSats(psbt) {
return psbt.getFee();
}
export function feeRateSatsPerByte(psbt) {
return psbt.getFeeRate();
}
//# sourceMappingURL=sign.js.map

View file

@ -0,0 +1,23 @@
export interface Utxo {
txid: string;
vout: number;
value: number;
address: string;
scriptPubKey: string;
witness?: {
scriptHex: string;
value: number;
};
nonWitnessTxHex?: string;
redeemScriptHex?: string;
tapInternalKeyHex?: string;
}
export interface Output {
address: string;
value: number;
}
export interface BuildParams {
inputs: Utxo[];
outputs: Output[];
sortBip69?: boolean;
}

View file

@ -0,0 +1,2 @@
export {};
//# sourceMappingURL=types.js.map

582
package-lock.json generated
View file

@ -1,16 +1,21 @@
{
"name": "theseus-navigator",
"version": "0.3.6",
"version": "0.3.16",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "theseus-navigator",
"version": "0.3.6",
"version": "0.3.16",
"dependencies": {
"@bitcoinerlab/secp256k1": "^1.2.0",
"@noble/curves": "^2.0.1",
"@noble/hashes": "^2.0.1",
"@scure/bip32": "^2.0.1",
"bip32": "^4.0.0",
"bip39": "^3.1.0",
"bitcoinjs-lib": "^6.1.7",
"ecpair": "^2.1.0",
"fetch-socks": "^1.3.3",
"nostr-tools": "^2.10.4",
"psl": "^1.15.0",
@ -22,6 +27,42 @@
"electron-builder": "^25.1.8"
}
},
"node_modules/@bitcoinerlab/secp256k1": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/@bitcoinerlab/secp256k1/-/secp256k1-1.2.0.tgz",
"integrity": "sha512-jeujZSzb3JOZfmJYI0ph1PVpCRV5oaexCgy+RvCXV8XlY+XFB/2n3WOcvBsKLsOw78KYgnQrQWb2HrKE4be88Q==",
"license": "MIT",
"dependencies": {
"@noble/curves": "^1.7.0"
}
},
"node_modules/@bitcoinerlab/secp256k1/node_modules/@noble/curves": {
"version": "1.9.7",
"resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.9.7.tgz",
"integrity": "sha512-gbKGcRUYIjA3/zCCNaWDciTMFI0dCkvou3TL8Zmy5Nc7sJ47a0jtOeZoTaMxkuqRo9cRhjOdZJXegxYE5FN/xw==",
"license": "MIT",
"dependencies": {
"@noble/hashes": "1.8.0"
},
"engines": {
"node": "^14.21.3 || >=16"
},
"funding": {
"url": "https://paulmillr.com/funding/"
}
},
"node_modules/@bitcoinerlab/secp256k1/node_modules/@noble/hashes": {
"version": "1.8.0",
"resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.8.0.tgz",
"integrity": "sha512-jCs9ldd7NwzpgXDIf6P3+NrHh9/sD6CQdxHyjQI+h/6rDNo88ypBxxz45UDuZHz9r3tNz7N/VInSVoVdtXEI4A==",
"license": "MIT",
"engines": {
"node": "^14.21.3 || >=16"
},
"funding": {
"url": "https://paulmillr.com/funding/"
}
},
"node_modules/@develar/schema-utils": {
"version": "2.6.5",
"resolved": "https://registry.npmjs.org/@develar/schema-utils/-/schema-utils-2.6.5.tgz",
@ -1251,6 +1292,21 @@
"node": ">= 4.0.0"
}
},
"node_modules/available-typed-arrays": {
"version": "1.0.7",
"resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz",
"integrity": "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==",
"license": "MIT",
"dependencies": {
"possible-typed-array-names": "^1.0.0"
},
"engines": {
"node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/balanced-match": {
"version": "4.0.4",
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.4.tgz",
@ -1261,6 +1317,12 @@
"node": "18 || 20 || >=22"
}
},
"node_modules/base-x": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/base-x/-/base-x-4.0.1.tgz",
"integrity": "sha512-uAZ8x6r6S3aUM9rbHGVOIsR15U/ZSc82b3ymnCPsT45Gk1DDvhDPdIgB5MrhirZWt+5K0EEPQH985kNqZgNPFw==",
"license": "MIT"
},
"node_modules/base64-js": {
"version": "1.5.1",
"resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz",
@ -1282,6 +1344,107 @@
],
"license": "MIT"
},
"node_modules/bech32": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/bech32/-/bech32-2.0.0.tgz",
"integrity": "sha512-LcknSilhIGatDAsY1ak2I8VtGaHNhgMSYVxFrGLXv+xLHytaKZKcaUJJUE7qmBr7h33o5YQwP55pMI0xmkpJwg==",
"license": "MIT"
},
"node_modules/bip174": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/bip174/-/bip174-2.1.1.tgz",
"integrity": "sha512-mdFV5+/v0XyNYXjBS6CQPLo9ekCx4gtKZFnJm5PMto7Fs9hTTDpkkzOB7/FtluRI6JbUUAu+snTYfJRgHLZbZQ==",
"license": "MIT",
"engines": {
"node": ">=8.0.0"
}
},
"node_modules/bip32": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/bip32/-/bip32-4.0.0.tgz",
"integrity": "sha512-aOGy88DDlVUhspIXJN+dVEtclhIsfAUppD43V0j40cPTld3pv/0X/MlrZSZ6jowIaQQzFwP8M6rFU2z2mVYjDQ==",
"license": "MIT",
"dependencies": {
"@noble/hashes": "^1.2.0",
"@scure/base": "^1.1.1",
"typeforce": "^1.11.5",
"wif": "^2.0.6"
},
"engines": {
"node": ">=6.0.0"
}
},
"node_modules/bip32/node_modules/@noble/hashes": {
"version": "1.8.0",
"resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.8.0.tgz",
"integrity": "sha512-jCs9ldd7NwzpgXDIf6P3+NrHh9/sD6CQdxHyjQI+h/6rDNo88ypBxxz45UDuZHz9r3tNz7N/VInSVoVdtXEI4A==",
"license": "MIT",
"engines": {
"node": "^14.21.3 || >=16"
},
"funding": {
"url": "https://paulmillr.com/funding/"
}
},
"node_modules/bip32/node_modules/@scure/base": {
"version": "1.2.6",
"resolved": "https://registry.npmjs.org/@scure/base/-/base-1.2.6.tgz",
"integrity": "sha512-g/nm5FgUa//MCj1gV09zTJTaM6KBAHqLN907YVQqf7zC49+DcO4B1so4ZX07Ef10Twr6nuqYEH9GEggFXA4Fmg==",
"license": "MIT",
"funding": {
"url": "https://paulmillr.com/funding/"
}
},
"node_modules/bip39": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/bip39/-/bip39-3.1.0.tgz",
"integrity": "sha512-c9kiwdk45Do5GL0vJMe7tS95VjCii65mYAH7DfWl3uW8AVzXKQVUm64i3hzVybBDMp9r7j9iNxR85+ul8MdN/A==",
"license": "ISC",
"dependencies": {
"@noble/hashes": "^1.2.0"
}
},
"node_modules/bip39/node_modules/@noble/hashes": {
"version": "1.8.0",
"resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.8.0.tgz",
"integrity": "sha512-jCs9ldd7NwzpgXDIf6P3+NrHh9/sD6CQdxHyjQI+h/6rDNo88ypBxxz45UDuZHz9r3tNz7N/VInSVoVdtXEI4A==",
"license": "MIT",
"engines": {
"node": "^14.21.3 || >=16"
},
"funding": {
"url": "https://paulmillr.com/funding/"
}
},
"node_modules/bitcoinjs-lib": {
"version": "6.1.7",
"resolved": "https://registry.npmjs.org/bitcoinjs-lib/-/bitcoinjs-lib-6.1.7.tgz",
"integrity": "sha512-tlf/r2DGMbF7ky1MgUqXHzypYHakkEnm0SZP23CJKIqNY/5uNAnMbFhMJdhjrL/7anfb/U8+AlpdjPWjPnAalg==",
"license": "MIT",
"dependencies": {
"@noble/hashes": "^1.2.0",
"bech32": "^2.0.0",
"bip174": "^2.1.1",
"bs58check": "^3.0.1",
"typeforce": "^1.11.3",
"varuint-bitcoin": "^1.1.2"
},
"engines": {
"node": ">=8.0.0"
}
},
"node_modules/bitcoinjs-lib/node_modules/@noble/hashes": {
"version": "1.8.0",
"resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.8.0.tgz",
"integrity": "sha512-jCs9ldd7NwzpgXDIf6P3+NrHh9/sD6CQdxHyjQI+h/6rDNo88ypBxxz45UDuZHz9r3tNz7N/VInSVoVdtXEI4A==",
"license": "MIT",
"engines": {
"node": "^14.21.3 || >=16"
},
"funding": {
"url": "https://paulmillr.com/funding/"
}
},
"node_modules/bl": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz",
@ -1333,6 +1496,37 @@
"node": "20 || >=22"
}
},
"node_modules/bs58": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/bs58/-/bs58-5.0.0.tgz",
"integrity": "sha512-r+ihvQJvahgYT50JD05dyJNKlmmSlMoOGwn1lCcEzanPglg7TxYjioQUYehQ9mAR/+hOSd2jRc/Z2y5UxBymvQ==",
"license": "MIT",
"dependencies": {
"base-x": "^4.0.0"
}
},
"node_modules/bs58check": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/bs58check/-/bs58check-3.0.1.tgz",
"integrity": "sha512-hjuuJvoWEybo7Hn/0xOrczQKKEKD63WguEjlhLExYs2wUBcebDC1jDNK17eEAD2lYfw82d5ASC1d7K3SWszjaQ==",
"license": "MIT",
"dependencies": {
"@noble/hashes": "^1.2.0",
"bs58": "^5.0.0"
}
},
"node_modules/bs58check/node_modules/@noble/hashes": {
"version": "1.8.0",
"resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.8.0.tgz",
"integrity": "sha512-jCs9ldd7NwzpgXDIf6P3+NrHh9/sD6CQdxHyjQI+h/6rDNo88ypBxxz45UDuZHz9r3tNz7N/VInSVoVdtXEI4A==",
"license": "MIT",
"engines": {
"node": "^14.21.3 || >=16"
},
"funding": {
"url": "https://paulmillr.com/funding/"
}
},
"node_modules/buffer": {
"version": "5.7.1",
"resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz",
@ -1572,11 +1766,28 @@
"node": ">=8"
}
},
"node_modules/call-bind": {
"version": "1.0.9",
"resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.9.tgz",
"integrity": "sha512-a/hy+pNsFUTR+Iz8TCJvXudKVLAnz/DyeSUo10I5yvFDQJBFU2s9uqQpoSrJlroHUKoKqzg+epxyP9lqFdzfBQ==",
"license": "MIT",
"dependencies": {
"call-bind-apply-helpers": "^1.0.2",
"es-define-property": "^1.0.1",
"get-intrinsic": "^1.3.0",
"set-function-length": "^1.2.2"
},
"engines": {
"node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/call-bind-apply-helpers": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz",
"integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==",
"dev": true,
"license": "MIT",
"dependencies": {
"es-errors": "^1.3.0",
@ -1586,6 +1797,22 @@
"node": ">= 0.4"
}
},
"node_modules/call-bound": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz",
"integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==",
"license": "MIT",
"dependencies": {
"call-bind-apply-helpers": "^1.0.2",
"get-intrinsic": "^1.3.0"
},
"engines": {
"node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/chalk": {
"version": "4.1.2",
"resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
@ -1636,6 +1863,20 @@
"node": ">=8"
}
},
"node_modules/cipher-base": {
"version": "1.0.7",
"resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.7.tgz",
"integrity": "sha512-Mz9QMT5fJe7bKI7MH31UilT5cEK5EHHRCccw/YRFsRY47AuNgaV6HY3rscp0/I4Q+tTW/5zoqpSeRRI54TkDWA==",
"license": "MIT",
"dependencies": {
"inherits": "^2.0.4",
"safe-buffer": "^5.2.1",
"to-buffer": "^1.2.2"
},
"engines": {
"node": ">= 0.10"
}
},
"node_modules/clean-stack": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz",
@ -1902,7 +2143,6 @@
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz",
"integrity": "sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ==",
"dev": true,
"license": "MIT"
},
"node_modules/crc": {
@ -1945,6 +2185,19 @@
"node": ">= 10"
}
},
"node_modules/create-hash": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz",
"integrity": "sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==",
"license": "MIT",
"dependencies": {
"cipher-base": "^1.0.1",
"inherits": "^2.0.1",
"md5.js": "^1.3.4",
"ripemd160": "^2.0.1",
"sha.js": "^2.4.0"
}
},
"node_modules/cross-spawn": {
"version": "7.0.6",
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz",
@ -2033,9 +2286,7 @@
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz",
"integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==",
"dev": true,
"license": "MIT",
"optional": true,
"dependencies": {
"es-define-property": "^1.0.0",
"es-errors": "^1.3.0",
@ -2260,7 +2511,6 @@
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz",
"integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==",
"dev": true,
"license": "MIT",
"dependencies": {
"call-bind-apply-helpers": "^1.0.1",
@ -2278,6 +2528,20 @@
"dev": true,
"license": "MIT"
},
"node_modules/ecpair": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/ecpair/-/ecpair-2.1.0.tgz",
"integrity": "sha512-cL/mh3MtJutFOvFc27GPZE2pWL3a3k4YvzUWEOvilnfZVlH3Jwgx/7d6tlD7/75tNk8TG2m+7Kgtz0SI1tWcqw==",
"license": "MIT",
"dependencies": {
"randombytes": "^2.1.0",
"typeforce": "^1.18.0",
"wif": "^2.0.6"
},
"engines": {
"node": ">=8.0.0"
}
},
"node_modules/ejs": {
"version": "3.1.10",
"resolved": "https://registry.npmjs.org/ejs/-/ejs-3.1.10.tgz",
@ -2535,7 +2799,6 @@
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz",
"integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">= 0.4"
@ -2545,7 +2808,6 @@
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz",
"integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">= 0.4"
@ -2555,7 +2817,6 @@
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.2.tgz",
"integrity": "sha512-HWcBoN6NileqtSydK2FqHbS/LoDd2pqrnQHLyJzBj4kOp/ky2MWMN694xOfkK8/SnUsW2DH7EfyVlydKCsm1Zw==",
"dev": true,
"license": "MIT",
"dependencies": {
"es-errors": "^1.3.0"
@ -2725,6 +2986,21 @@
"node": ">=10"
}
},
"node_modules/for-each": {
"version": "0.3.5",
"resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.5.tgz",
"integrity": "sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg==",
"license": "MIT",
"dependencies": {
"is-callable": "^1.2.7"
},
"engines": {
"node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/foreground-child": {
"version": "3.3.1",
"resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.1.tgz",
@ -2819,7 +3095,6 @@
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz",
"integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==",
"dev": true,
"license": "MIT",
"funding": {
"url": "https://github.com/sponsors/ljharb"
@ -2860,7 +3135,6 @@
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz",
"integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==",
"dev": true,
"license": "MIT",
"dependencies": {
"call-bind-apply-helpers": "^1.0.2",
@ -2885,7 +3159,6 @@
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz",
"integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==",
"dev": true,
"license": "MIT",
"dependencies": {
"dunder-proto": "^1.0.1",
@ -3019,7 +3292,6 @@
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz",
"integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">= 0.4"
@ -3075,9 +3347,7 @@
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz",
"integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==",
"dev": true,
"license": "MIT",
"optional": true,
"dependencies": {
"es-define-property": "^1.0.0"
},
@ -3089,7 +3359,6 @@
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz",
"integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">= 0.4"
@ -3102,7 +3371,6 @@
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz",
"integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==",
"dev": true,
"license": "MIT",
"dependencies": {
"has-symbols": "^1.0.3"
@ -3121,11 +3389,61 @@
"dev": true,
"license": "ISC"
},
"node_modules/hash-base": {
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.1.2.tgz",
"integrity": "sha512-Bb33KbowVTIj5s7Ked1OsqHUeCpz//tPwR+E2zJgJKo9Z5XolZ9b6bdUgjmYlwnWhoOQKoTd1TYToZGn5mAYOg==",
"license": "MIT",
"dependencies": {
"inherits": "^2.0.4",
"readable-stream": "^2.3.8",
"safe-buffer": "^5.2.1",
"to-buffer": "^1.2.1"
},
"engines": {
"node": ">= 0.8"
}
},
"node_modules/hash-base/node_modules/readable-stream": {
"version": "2.3.8",
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz",
"integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==",
"license": "MIT",
"dependencies": {
"core-util-is": "~1.0.0",
"inherits": "~2.0.3",
"isarray": "~1.0.0",
"process-nextick-args": "~2.0.0",
"safe-buffer": "~5.1.1",
"string_decoder": "~1.1.1",
"util-deprecate": "~1.0.1"
}
},
"node_modules/hash-base/node_modules/readable-stream/node_modules/safe-buffer": {
"version": "5.1.2",
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
"integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==",
"license": "MIT"
},
"node_modules/hash-base/node_modules/string_decoder": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
"integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
"license": "MIT",
"dependencies": {
"safe-buffer": "~5.1.0"
}
},
"node_modules/hash-base/node_modules/string_decoder/node_modules/safe-buffer": {
"version": "5.1.2",
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
"integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==",
"license": "MIT"
},
"node_modules/hasown": {
"version": "2.0.4",
"resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.4.tgz",
"integrity": "sha512-T2UbfbBEF32wiepXIsMlTW9+dDYC6wMh/t/vYA4tuOMKqWz/n3vr1NFSxQiyP+zk2mXsoMA/i/7qV6LKut1t1A==",
"dev": true,
"license": "MIT",
"dependencies": {
"function-bind": "^1.1.2"
@ -3321,7 +3639,6 @@
"version": "2.0.4",
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
"dev": true,
"license": "ISC"
},
"node_modules/ip-address": {
@ -3333,6 +3650,18 @@
"node": ">= 12"
}
},
"node_modules/is-callable": {
"version": "1.2.7",
"resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz",
"integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==",
"license": "MIT",
"engines": {
"node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/is-ci": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/is-ci/-/is-ci-3.0.1.tgz",
@ -3373,6 +3702,21 @@
"dev": true,
"license": "MIT"
},
"node_modules/is-typed-array": {
"version": "1.1.15",
"resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.15.tgz",
"integrity": "sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ==",
"license": "MIT",
"dependencies": {
"which-typed-array": "^1.1.16"
},
"engines": {
"node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/is-unicode-supported": {
"version": "0.1.0",
"resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz",
@ -3390,9 +3734,7 @@
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
"integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==",
"dev": true,
"license": "MIT",
"peer": true
"license": "MIT"
},
"node_modules/isbinaryfile": {
"version": "5.0.7",
@ -3783,12 +4125,22 @@
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz",
"integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">= 0.4"
}
},
"node_modules/md5.js": {
"version": "1.3.5",
"resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz",
"integrity": "sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg==",
"license": "MIT",
"dependencies": {
"hash-base": "^3.0.0",
"inherits": "^2.0.1",
"safe-buffer": "^5.1.2"
}
},
"node_modules/mime": {
"version": "2.6.0",
"resolved": "https://registry.npmjs.org/mime/-/mime-2.6.0.tgz",
@ -4387,13 +4739,20 @@
"node": ">=10.4.0"
}
},
"node_modules/possible-typed-array-names": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.1.0.tgz",
"integrity": "sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg==",
"license": "MIT",
"engines": {
"node": ">= 0.4"
}
},
"node_modules/process-nextick-args": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz",
"integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==",
"dev": true,
"license": "MIT",
"peer": true
"license": "MIT"
},
"node_modules/progress": {
"version": "2.0.3",
@ -4471,6 +4830,15 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/randombytes": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz",
"integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==",
"license": "MIT",
"dependencies": {
"safe-buffer": "^5.1.0"
}
},
"node_modules/read-binary-file-arch": {
"version": "1.0.6",
"resolved": "https://registry.npmjs.org/read-binary-file-arch/-/read-binary-file-arch-1.0.6.tgz",
@ -4632,6 +5000,19 @@
"url": "https://github.com/sponsors/isaacs"
}
},
"node_modules/ripemd160": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.3.tgz",
"integrity": "sha512-5Di9UC0+8h1L6ZD2d7awM7E/T4uA1fJRlx6zk/NvdCCVEoAnFqvHmCuNeIKoCeIixBX/q8uM+6ycDvF8woqosA==",
"license": "MIT",
"dependencies": {
"hash-base": "^3.1.2",
"inherits": "^2.0.4"
},
"engines": {
"node": ">= 0.8"
}
},
"node_modules/roarr": {
"version": "2.15.4",
"resolved": "https://registry.npmjs.org/roarr/-/roarr-2.15.4.tgz",
@ -4655,7 +5036,6 @@
"version": "5.2.1",
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
"integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==",
"dev": true,
"funding": [
{
"type": "github",
@ -4741,6 +5121,43 @@
"dev": true,
"license": "ISC"
},
"node_modules/set-function-length": {
"version": "1.2.2",
"resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz",
"integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==",
"license": "MIT",
"dependencies": {
"define-data-property": "^1.1.4",
"es-errors": "^1.3.0",
"function-bind": "^1.1.2",
"get-intrinsic": "^1.2.4",
"gopd": "^1.0.1",
"has-property-descriptors": "^1.0.2"
},
"engines": {
"node": ">= 0.4"
}
},
"node_modules/sha.js": {
"version": "2.4.12",
"resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.12.tgz",
"integrity": "sha512-8LzC5+bvI45BjpfXU8V5fdU2mfeKiQe1D1gIMn7XUlF3OTUrpdJpPPH4EMAnF0DsHHdSZqCdSss5qCmJKuiO3w==",
"license": "(MIT AND BSD-3-Clause)",
"dependencies": {
"inherits": "^2.0.4",
"safe-buffer": "^5.2.1",
"to-buffer": "^1.2.0"
},
"bin": {
"sha.js": "bin.js"
},
"engines": {
"node": ">= 0.10"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/shebang-command": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
@ -5113,6 +5530,26 @@
"tmp": "^0.2.0"
}
},
"node_modules/to-buffer": {
"version": "1.2.2",
"resolved": "https://registry.npmjs.org/to-buffer/-/to-buffer-1.2.2.tgz",
"integrity": "sha512-db0E3UJjcFhpDhAF4tLo03oli3pwl3dbnzXOUIlRKrp+ldk/VUxzpWYZENsw2SZiuBjHAk7DfB0VU7NKdpb6sw==",
"license": "MIT",
"dependencies": {
"isarray": "^2.0.5",
"safe-buffer": "^5.2.1",
"typed-array-buffer": "^1.0.3"
},
"engines": {
"node": ">= 0.4"
}
},
"node_modules/to-buffer/node_modules/isarray": {
"version": "2.0.5",
"resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz",
"integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==",
"license": "MIT"
},
"node_modules/truncate-utf8-bytes": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/truncate-utf8-bytes/-/truncate-utf8-bytes-1.0.2.tgz",
@ -5137,6 +5574,26 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/typed-array-buffer": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.3.tgz",
"integrity": "sha512-nAYYwfY3qnzX30IkA6AQZjVbtK6duGontcQm1WSG1MD94YLqK0515GNApXkoxKOWMusVssAHWLh9SeaoefYFGw==",
"license": "MIT",
"dependencies": {
"call-bound": "^1.0.3",
"es-errors": "^1.3.0",
"is-typed-array": "^1.1.14"
},
"engines": {
"node": ">= 0.4"
}
},
"node_modules/typeforce": {
"version": "1.18.0",
"resolved": "https://registry.npmjs.org/typeforce/-/typeforce-1.18.0.tgz",
"integrity": "sha512-7uc1O8h1M1g0rArakJdf0uLRSSgFcYexrVoKo+bzJd32gd4gDy2L/Z+8/FjPnU9ydY3pEnVPtr9FyscYY60K1g==",
"license": "MIT"
},
"node_modules/typescript": {
"version": "5.9.3",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz",
@ -5224,9 +5681,17 @@
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
"integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==",
"dev": true,
"license": "MIT"
},
"node_modules/varuint-bitcoin": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/varuint-bitcoin/-/varuint-bitcoin-1.1.2.tgz",
"integrity": "sha512-4EVb+w4rx+YfVM32HQX42AbbT7/1f5zwAYhIujKXKk8NQK+JfRVl3pqT3hjNn/L+RstigmGGKVwHA/P0wgITZw==",
"license": "MIT",
"dependencies": {
"safe-buffer": "^5.1.1"
}
},
"node_modules/verror": {
"version": "1.10.1",
"resolved": "https://registry.npmjs.org/verror/-/verror-1.10.1.tgz",
@ -5269,6 +5734,27 @@
"node": ">= 8"
}
},
"node_modules/which-typed-array": {
"version": "1.1.22",
"resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.22.tgz",
"integrity": "sha512-fvO4ExWMFsqyhG3AiPAObMuY1lxaqgYcxbc49CNdWDDECOJNgQyvsOWVwbZc+qf3rzRtxojBK+CMEv0Ld5CYpw==",
"license": "MIT",
"dependencies": {
"available-typed-arrays": "^1.0.7",
"call-bind": "^1.0.9",
"call-bound": "^1.0.4",
"for-each": "^0.3.5",
"get-proto": "^1.0.1",
"gopd": "^1.2.0",
"has-tostringtag": "^1.0.2"
},
"engines": {
"node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/wide-align": {
"version": "1.1.5",
"resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz",
@ -5279,6 +5765,44 @@
"string-width": "^1.0.2 || 2 || 3 || 4"
}
},
"node_modules/wif": {
"version": "2.0.6",
"resolved": "https://registry.npmjs.org/wif/-/wif-2.0.6.tgz",
"integrity": "sha512-HIanZn1zmduSF+BQhkE+YXIbEiH0xPr1012QbFEGB0xsKqJii0/SqJjyn8dFv6y36kOznMgMB+LGcbZTJ1xACQ==",
"license": "MIT",
"dependencies": {
"bs58check": "<3.0.0"
}
},
"node_modules/wif/node_modules/base-x": {
"version": "3.0.11",
"resolved": "https://registry.npmjs.org/base-x/-/base-x-3.0.11.tgz",
"integrity": "sha512-xz7wQ8xDhdyP7tQxwdteLYeFfS68tSMNCZ/Y37WJ4bhGfKPpqEIlmIyueQHqOyoPhE6xNUqjzRr8ra0eF9VRvA==",
"license": "MIT",
"dependencies": {
"safe-buffer": "^5.0.1"
}
},
"node_modules/wif/node_modules/bs58": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/bs58/-/bs58-4.0.1.tgz",
"integrity": "sha512-Ok3Wdf5vOIlBrgCvTq96gBkJw+JUEzdBgyaza5HLtPm7yTHkjRy8+JzNyHF7BHa0bNWOQIp3m5YF0nnFcOIKLw==",
"license": "MIT",
"dependencies": {
"base-x": "^3.0.2"
}
},
"node_modules/wif/node_modules/bs58check": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/bs58check/-/bs58check-2.1.2.tgz",
"integrity": "sha512-0TS1jicxdU09dwJMNZtVAfzPi6Q6QeN0pM1Fkzrjn+XYHvzMKPU3pHVpva+769iNVSfIYWf7LJ6WR+BuuMf8cA==",
"license": "MIT",
"dependencies": {
"bs58": "^4.0.0",
"create-hash": "^1.1.0",
"safe-buffer": "^5.1.2"
}
},
"node_modules/wrap-ansi": {
"version": "7.0.0",
"resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",

View file

@ -11,9 +11,14 @@
"dist": "electron-builder --win nsis portable"
},
"dependencies": {
"@bitcoinerlab/secp256k1": "^1.1.1",
"@noble/curves": "^2.0.1",
"@noble/hashes": "^2.0.1",
"@scure/bip32": "^2.0.1",
"bip32": "^4.0.0",
"bip39": "^3.1.0",
"bitcoinjs-lib": "^6.1.7",
"ecpair": "^2.1.0",
"fetch-socks": "^1.3.3",
"nostr-tools": "^2.10.4",
"psl": "^1.15.0",