bitmask-core
Version:
Core functionality for the BitMask wallet
164 lines (163 loc) • 9.09 kB
JavaScript
// Methods meant to work with BDK defined within the web::bitcoin module from bitmask-core:
// https://github.com/diba-io/bitmask-core/blob/development/src/web.rs
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;
};
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.quoteSwapFeeSats = exports.guessSwapVbytes = exports.feeFromRate = exports.fetchFeeEstimates = exports.bumpFee = exports.drainWallet = exports.getAssetsVault = exports.fundVault = exports.sendSats = exports.getNewAddress = exports.getWalletData = exports.encryptWallet = exports.newWallet = exports.syncWallets = exports.upgradeWallet = exports.decryptWallet = exports.hashPassword = void 0;
const BMC = __importStar(require("./bitmask_core"));
const constants_1 = require("./constants");
const hashPassword = (password) => BMC.hash_password(password);
exports.hashPassword = hashPassword;
const decryptWallet = (hash, encryptedDescriptors, seedPassword = "") => __awaiter(void 0, void 0, void 0, function* () {
return JSON.parse(yield BMC.decrypt_wallet(hash, encryptedDescriptors, seedPassword));
});
exports.decryptWallet = decryptWallet;
const upgradeWallet = (hash, encryptedDescriptors, seedPassword = "") => __awaiter(void 0, void 0, void 0, function* () {
return JSON.parse(yield BMC.upgrade_wallet(hash, encryptedDescriptors, seedPassword));
});
exports.upgradeWallet = upgradeWallet;
const syncWallets = () => __awaiter(void 0, void 0, void 0, function* () { return BMC.sync_wallets(); });
exports.syncWallets = syncWallets;
const newWallet = (hash, seedPassword) => __awaiter(void 0, void 0, void 0, function* () { return JSON.parse(yield BMC.new_wallet(hash, seedPassword)); });
exports.newWallet = newWallet;
const encryptWallet = (mnemonic, hash, seedPassword) => __awaiter(void 0, void 0, void 0, function* () { return JSON.parse(yield BMC.encrypt_wallet(mnemonic, hash, seedPassword)); });
exports.encryptWallet = encryptWallet;
const getWalletData = (descriptor, changeDescriptor) => __awaiter(void 0, void 0, void 0, function* () { return JSON.parse(yield BMC.get_wallet_data(descriptor, changeDescriptor)); });
exports.getWalletData = getWalletData;
const getNewAddress = (descriptor, changeDescriptor) => __awaiter(void 0, void 0, void 0, function* () { return JSON.parse(yield BMC.get_new_address(descriptor, changeDescriptor)); });
exports.getNewAddress = getNewAddress;
const sendSats = (descriptor, changeDescriptor, address, amount, broadcast, feeRate) => __awaiter(void 0, void 0, void 0, function* () {
return JSON.parse(yield BMC.send_sats(descriptor, changeDescriptor, address, amount, broadcast, feeRate));
});
exports.sendSats = sendSats;
const fundVault = (descriptor, changeDescriptor, rgbAddress, broadcast, feeRate) => __awaiter(void 0, void 0, void 0, function* () {
return JSON.parse(yield BMC.fund_vault(descriptor, changeDescriptor, rgbAddress, broadcast, feeRate));
});
exports.fundVault = fundVault;
const getAssetsVault = (rgbDescriptorXpub) => __awaiter(void 0, void 0, void 0, function* () { return JSON.parse(yield BMC.get_assets_vault(rgbDescriptorXpub)); });
exports.getAssetsVault = getAssetsVault;
const drainWallet = (destination, descriptor, changeDescriptor, feeRate) => __awaiter(void 0, void 0, void 0, function* () {
return JSON.parse(yield BMC.drain_wallet(destination, descriptor, changeDescriptor, feeRate));
});
exports.drainWallet = drainWallet;
const bumpFee = (txid, feeRate, broadcast, descriptor, changeDescriptor) => __awaiter(void 0, void 0, void 0, function* () {
return JSON.parse(yield BMC.bump_fee(txid, feeRate, descriptor, changeDescriptor, broadcast));
});
exports.bumpFee = bumpFee;
function fetchFeeEstimates() {
return __awaiter(this, void 0, void 0, function* () {
const net = yield (0, constants_1.getNetwork)();
// Map exact network to explicit env key as requested
// bitcoin -> BITCOIN_EXPLORER_API_MAINNET
// testnet -> BITCOIN_EXPLORER_API_TESTNET
// signet -> BITCOIN_EXPLORER_API_SIGNET
// regtest -> BITCOIN_EXPLORER_API_REGTEST
let envKey;
switch (net) {
case "bitcoin":
envKey = "BITCOIN_EXPLORER_API_MAINNET";
break;
case "testnet":
envKey = "BITCOIN_EXPLORER_API_TESTNET";
break;
case "signet":
envKey = "BITCOIN_EXPLORER_API_SIGNET";
break;
case "regtest":
envKey = "BITCOIN_EXPLORER_API_REGTEST";
break;
default:
// Fallback to testnet if unknown string is returned
envKey = "BITCOIN_EXPLORER_API_TESTNET";
break;
}
const base = yield (0, constants_1.getEnv)(envKey);
if (!base) {
throw new Error(`fee-estimates: missing env ${envKey} for network ${net}`);
}
const baseUrl = (base || "").replace(/\/$/, "");
const url = `${baseUrl}/fee-estimates`;
const resp = yield fetch(url, { method: "GET" });
if (!resp.ok) {
const text = yield resp.text().catch(() => "");
throw new Error(`fee-estimates fetch failed ${resp.status}: ${text}`);
}
return (yield resp.json());
});
}
exports.fetchFeeEstimates = fetchFeeEstimates;
/**
* Compute absolute fee in sats from a sat/vB rate and an estimated vsize.
* Always ceil so we don't underpay policy minimums.
*/
function feeFromRate(vbytes, satPerVb) {
return Math.ceil(vbytes * satPerVb);
}
exports.feeFromRate = feeFromRate;
/**
* Rough vbytes guesser for swap/bid PSBTs when you don't yet know exact inputs/outputs.
* Prefer passing a conservative bound to avoid underpaying relays:
* - Default assumes ~2 inputs, ~3 outputs, taproot heavy mix, returns ~400 vB.
* - Scale linearly for more inputs/outputs.
*
* If you know inputs/outputs counts beforehand, pass them to tighten the estimate.
*/
function guessSwapVbytes(inputs = 2, outputs = 3, taprootHeavy = true) {
// Heuristic base (conservative): taproot-heavy ~180 vB per input, ~34 vB per output, +10 overhead
// Non-taproot may be slightly bigger; this errs on the safe side.
const perIn = taprootHeavy ? 180 : 200;
const perOut = 34;
const overhead = 10;
// Ensure a floor to avoid extremely small estimates in edge cases
const est = inputs * perIn + outputs * perOut + overhead;
return Math.max(est, 300);
}
exports.guessSwapVbytes = guessSwapVbytes;
/**
* Convenience: get a safe absolute fee quote for a swap given a target confirmation bucket.
* - bucket can be "1","2","3","6","144", etc., matching Esplora keys.
* - vbytesEstimate can be computed via guessSwapVbytes() or a tighter UI estimate.
* - Adds a small 10% safety margin on the feerate to reduce min-relay rejections.
*/
function quoteSwapFeeSats(bucket, vbytesEstimate) {
var _a, _b;
return __awaiter(this, void 0, void 0, function* () {
const estimates = yield fetchFeeEstimates();
const satPerVb = (_b = (_a = estimates[bucket]) !== null && _a !== void 0 ? _a : estimates["6"]) !== null && _b !== void 0 ? _b : 1.0;
const paddedRate = Math.max(1.0, satPerVb * 1.1); // 10% headroom
const fee = feeFromRate(vbytesEstimate, paddedRate);
return { rate: paddedRate, fee };
});
}
exports.quoteSwapFeeSats = quoteSwapFeeSats;
;