@ibearua/bitmask-core-dev 1.0.0-beta.10 → 1.0.0-beta.12

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/bitcoin.d.ts ADDED
@@ -0,0 +1,140 @@
1
+ export declare const hashPassword: (password: string) => string;
2
+ export declare const decryptWallet: (hash: string, encryptedDescriptors: string, seedPassword?: string) => Promise<Vault>;
3
+ export declare const upgradeWallet: (hash: string, encryptedDescriptors: string, seedPassword?: string) => Promise<string>;
4
+ export declare const syncWallets: () => Promise<void>;
5
+ export declare const newWallet: (hash: string, seedPassword: string) => Promise<string>;
6
+ export declare const encryptWallet: (mnemonic: string, hash: string, seedPassword: string) => Promise<string>;
7
+ export declare const getWalletData: (descriptor: string, changeDescriptor?: string) => Promise<WalletData>;
8
+ export declare const getNewAddress: (descriptor: string, changeDescriptor?: string) => Promise<string>;
9
+ export declare const sendSats: (descriptor: string, changeDescriptor: string, address: string, amount: bigint, broadcast: boolean, feeRate: number) => Promise<TransactionData>;
10
+ export declare const fundVault: (descriptor: string, changeDescriptor: string, rgbAddress: string, broadcast: boolean, feeRate?: number) => Promise<FundVaultDetails>;
11
+ export declare const getAssetsVault: (rgbDescriptorXpub: string) => Promise<FundVaultDetails>;
12
+ export declare const drainWallet: (destination: string, descriptor: string, changeDescriptor?: string, feeRate?: number) => Promise<TransactionData>;
13
+ export declare const bumpFee: (txid: string, feeRate: number, broadcast: boolean, descriptor: string, changeDescriptor?: string) => Promise<TransactionData>;
14
+ export interface PrivateWalletData {
15
+ xprvkh: string;
16
+ btcDescriptorXprv: string;
17
+ btcChangeDescriptorXprv: string;
18
+ rgbDescriptorXprv: string;
19
+ nostrPrv: string;
20
+ nostrNsec: string;
21
+ }
22
+ export interface PublicWalletData {
23
+ xpubkh: string;
24
+ btcDescriptorXpub: string;
25
+ btcChangeDescriptorXpub: string;
26
+ rgbDescriptorXpub: string;
27
+ nostrPub: string;
28
+ nostrNpub: string;
29
+ }
30
+ export interface Vault {
31
+ mnemonic: string;
32
+ private: PrivateWalletData;
33
+ public: PublicWalletData;
34
+ }
35
+ export interface Transaction extends WalletTransaction {
36
+ amount: number;
37
+ asset?: string;
38
+ assetType: string;
39
+ fee: number;
40
+ message?: string;
41
+ note?: string;
42
+ }
43
+ export interface Activity extends Transaction {
44
+ id: string;
45
+ date: number;
46
+ action: string;
47
+ status: string;
48
+ lightning?: boolean;
49
+ sender?: {
50
+ name: string;
51
+ address: string;
52
+ };
53
+ recipient?: {
54
+ name: string;
55
+ address: string;
56
+ invoice: string;
57
+ };
58
+ }
59
+ export interface TransactionDetails extends Transaction {
60
+ sender: {
61
+ name: string;
62
+ address: string;
63
+ };
64
+ recipient: {
65
+ name: string;
66
+ address: string;
67
+ invoice: string;
68
+ };
69
+ }
70
+ export interface TransactionData {
71
+ details: TransactionDataDetails;
72
+ vsize: number;
73
+ feeRate: number;
74
+ }
75
+ export interface TransactionDataDetails {
76
+ transaction?: Transaction;
77
+ txid: string;
78
+ received: number;
79
+ sent: number;
80
+ fee: number;
81
+ confirmationTime?: ConfirmationTime;
82
+ confirmed?: boolean;
83
+ }
84
+ export interface ConfirmationTime {
85
+ height: number;
86
+ timestamp: number;
87
+ }
88
+ export interface WalletTransaction {
89
+ txid: string;
90
+ received: number;
91
+ sent: number;
92
+ fee: number;
93
+ confirmed: boolean;
94
+ confirmationTime: ConfirmationTime;
95
+ vsize: number;
96
+ feeRate: number;
97
+ }
98
+ export interface WalletBalance {
99
+ immature: number;
100
+ trustedPending: number;
101
+ untrustedPending: number;
102
+ confirmed: number;
103
+ }
104
+ export interface WalletData {
105
+ wallet?: string;
106
+ name: string;
107
+ address: string;
108
+ balance: WalletBalance;
109
+ transactions: WalletTransaction[];
110
+ utxos: string[];
111
+ }
112
+ export interface FundVaultDetails {
113
+ rgbOutput?: string;
114
+ isFunded: boolean;
115
+ fundTxid?: string;
116
+ fundFee?: number;
117
+ }
118
+ export type FeeEstimates = Record<string, number>;
119
+ export declare function fetchFeeEstimates(): Promise<FeeEstimates>;
120
+ export declare function feeFromRate(vbytes: number, satPerVb: number): number;
121
+ /**
122
+ * Rough vbytes guesser for swap/bid PSBTs when you don't yet know exact inputs/outputs.
123
+ * Prefer passing a conservative bound to avoid underpaying relays:
124
+ * - Default assumes ~2 inputs, ~3 outputs, taproot heavy mix, returns ~400 vB.
125
+ * - Scale linearly for more inputs/outputs.
126
+ *
127
+ * If you know inputs/outputs counts beforehand, pass them to tighten the estimate.
128
+ */
129
+ export declare function guessSwapVbytes(inputs?: number, outputs?: number, taprootHeavy?: boolean): number;
130
+ /**
131
+ * Convenience: get a safe absolute fee quote for a swap given a target confirmation bucket.
132
+ * - bucket can be "1","2","3","6","144", etc., matching Esplora keys.
133
+ * - vbytesEstimate can be computed via guessSwapVbytes() or a tighter UI estimate.
134
+ * - Adds a small 10% safety margin on the feerate to reduce min-relay rejections.
135
+ */
136
+ export declare function quoteSwapFeeSats(bucket: string, vbytesEstimate: number): Promise<{
137
+ rate: number;
138
+ fee: number;
139
+ }>;
140
+ //# sourceMappingURL=bitcoin.d.ts.map
package/bitcoin.js ADDED
@@ -0,0 +1,154 @@
1
+ "use strict";
2
+ // Methods meant to work with BDK defined within the web::bitcoin module from bitmask-core:
3
+ // https://github.com/diba-io/bitmask-core/blob/development/src/web.rs
4
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
5
+ if (k2 === undefined) k2 = k;
6
+ var desc = Object.getOwnPropertyDescriptor(m, k);
7
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
8
+ desc = { enumerable: true, get: function() { return m[k]; } };
9
+ }
10
+ Object.defineProperty(o, k2, desc);
11
+ }) : (function(o, m, k, k2) {
12
+ if (k2 === undefined) k2 = k;
13
+ o[k2] = m[k];
14
+ }));
15
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
16
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
17
+ }) : function(o, v) {
18
+ o["default"] = v;
19
+ });
20
+ var __importStar = (this && this.__importStar) || function (mod) {
21
+ if (mod && mod.__esModule) return mod;
22
+ var result = {};
23
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
24
+ __setModuleDefault(result, mod);
25
+ return result;
26
+ };
27
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
28
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
29
+ return new (P || (P = Promise))(function (resolve, reject) {
30
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
31
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
32
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
33
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
34
+ });
35
+ };
36
+ Object.defineProperty(exports, "__esModule", { value: true });
37
+ 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;
38
+ const BMC = __importStar(require("./bitmask_core"));
39
+ const constants_1 = require("./constants");
40
+ const hashPassword = (password) => BMC.hash_password(password);
41
+ exports.hashPassword = hashPassword;
42
+ const decryptWallet = (hash, encryptedDescriptors, seedPassword = "") => __awaiter(void 0, void 0, void 0, function* () {
43
+ return JSON.parse(yield BMC.decrypt_wallet(hash, encryptedDescriptors, seedPassword));
44
+ });
45
+ exports.decryptWallet = decryptWallet;
46
+ const upgradeWallet = (hash, encryptedDescriptors, seedPassword = "") => __awaiter(void 0, void 0, void 0, function* () {
47
+ return JSON.parse(yield BMC.upgrade_wallet(hash, encryptedDescriptors, seedPassword));
48
+ });
49
+ exports.upgradeWallet = upgradeWallet;
50
+ const syncWallets = () => __awaiter(void 0, void 0, void 0, function* () { return BMC.sync_wallets(); });
51
+ exports.syncWallets = syncWallets;
52
+ const newWallet = (hash, seedPassword) => __awaiter(void 0, void 0, void 0, function* () { return JSON.parse(yield BMC.new_wallet(hash, seedPassword)); });
53
+ exports.newWallet = newWallet;
54
+ const encryptWallet = (mnemonic, hash, seedPassword) => __awaiter(void 0, void 0, void 0, function* () { return JSON.parse(yield BMC.encrypt_wallet(mnemonic, hash, seedPassword)); });
55
+ exports.encryptWallet = encryptWallet;
56
+ const getWalletData = (descriptor, changeDescriptor) => __awaiter(void 0, void 0, void 0, function* () { return JSON.parse(yield BMC.get_wallet_data(descriptor, changeDescriptor)); });
57
+ exports.getWalletData = getWalletData;
58
+ const getNewAddress = (descriptor, changeDescriptor) => __awaiter(void 0, void 0, void 0, function* () { return JSON.parse(yield BMC.get_new_address(descriptor, changeDescriptor)); });
59
+ exports.getNewAddress = getNewAddress;
60
+ const sendSats = (descriptor, changeDescriptor, address, amount, broadcast, feeRate) => __awaiter(void 0, void 0, void 0, function* () {
61
+ return JSON.parse(yield BMC.send_sats(descriptor, changeDescriptor, address, amount, broadcast, feeRate));
62
+ });
63
+ exports.sendSats = sendSats;
64
+ const fundVault = (descriptor, changeDescriptor, rgbAddress, broadcast, feeRate) => __awaiter(void 0, void 0, void 0, function* () {
65
+ return JSON.parse(yield BMC.fund_vault(descriptor, changeDescriptor, rgbAddress, broadcast, feeRate));
66
+ });
67
+ exports.fundVault = fundVault;
68
+ const getAssetsVault = (rgbDescriptorXpub) => __awaiter(void 0, void 0, void 0, function* () { return JSON.parse(yield BMC.get_assets_vault(rgbDescriptorXpub)); });
69
+ exports.getAssetsVault = getAssetsVault;
70
+ const drainWallet = (destination, descriptor, changeDescriptor, feeRate) => __awaiter(void 0, void 0, void 0, function* () {
71
+ return JSON.parse(yield BMC.drain_wallet(destination, descriptor, changeDescriptor, feeRate));
72
+ });
73
+ exports.drainWallet = drainWallet;
74
+ const bumpFee = (txid, feeRate, broadcast, descriptor, changeDescriptor) => __awaiter(void 0, void 0, void 0, function* () {
75
+ return JSON.parse(yield BMC.bump_fee(txid, feeRate, descriptor, changeDescriptor, broadcast));
76
+ });
77
+ exports.bumpFee = bumpFee;
78
+ function fetchFeeEstimates() {
79
+ return __awaiter(this, void 0, void 0, function* () {
80
+ const net = yield (0, constants_1.getNetwork)();
81
+ let envKey;
82
+ switch (net) {
83
+ case "bitcoin":
84
+ envKey = "BITCOIN_EXPLORER_API_MAINNET";
85
+ break;
86
+ case "testnet":
87
+ envKey = "BITCOIN_EXPLORER_API_TESTNET";
88
+ break;
89
+ case "signet":
90
+ envKey = "BITCOIN_EXPLORER_API_SIGNET";
91
+ break;
92
+ case "regtest":
93
+ envKey = "BITCOIN_EXPLORER_API_REGTEST";
94
+ break;
95
+ default:
96
+ // Fallback to signet if unknown string is returned
97
+ envKey = "BITCOIN_EXPLORER_API_SIGNET";
98
+ break;
99
+ }
100
+ const base = yield (0, constants_1.getEnv)(envKey);
101
+ if (!base) {
102
+ throw new Error(`fee-estimates: missing env ${envKey} for network ${net}`);
103
+ }
104
+ const baseUrl = (base || "").replace(/\/$/, "");
105
+ const url = `${baseUrl}/fee-estimates`;
106
+ const resp = yield fetch(url, { method: "GET" });
107
+ if (!resp.ok) {
108
+ const text = yield resp.text().catch(() => "");
109
+ throw new Error(`fee-estimates fetch failed ${resp.status}: ${text}`);
110
+ }
111
+ return (yield resp.json());
112
+ });
113
+ }
114
+ exports.fetchFeeEstimates = fetchFeeEstimates;
115
+ function feeFromRate(vbytes, satPerVb) {
116
+ return Math.ceil(vbytes * satPerVb);
117
+ }
118
+ exports.feeFromRate = feeFromRate;
119
+ /**
120
+ * Rough vbytes guesser for swap/bid PSBTs when you don't yet know exact inputs/outputs.
121
+ * Prefer passing a conservative bound to avoid underpaying relays:
122
+ * - Default assumes ~2 inputs, ~3 outputs, taproot heavy mix, returns ~400 vB.
123
+ * - Scale linearly for more inputs/outputs.
124
+ *
125
+ * If you know inputs/outputs counts beforehand, pass them to tighten the estimate.
126
+ */
127
+ function guessSwapVbytes(inputs = 2, outputs = 3, taprootHeavy = true) {
128
+ // Heuristic base (conservative): taproot-heavy ~180 vB per input, ~34 vB per output, +10 overhead
129
+ // Non-taproot may be slightly bigger; this errs on the safe side.
130
+ const perIn = taprootHeavy ? 180 : 200;
131
+ const perOut = 34;
132
+ const overhead = 10;
133
+ // Ensure a floor to avoid extremely small estimates in edge cases
134
+ const est = inputs * perIn + outputs * perOut + overhead;
135
+ return Math.max(est, 300);
136
+ }
137
+ exports.guessSwapVbytes = guessSwapVbytes;
138
+ /**
139
+ * Convenience: get a safe absolute fee quote for a swap given a target confirmation bucket.
140
+ * - bucket can be "1","2","3","6","144", etc., matching Esplora keys.
141
+ * - vbytesEstimate can be computed via guessSwapVbytes() or a tighter UI estimate.
142
+ * - Adds a small 10% safety margin on the feerate to reduce min-relay rejections.
143
+ */
144
+ function quoteSwapFeeSats(bucket, vbytesEstimate) {
145
+ var _a, _b;
146
+ return __awaiter(this, void 0, void 0, function* () {
147
+ const estimates = yield fetchFeeEstimates();
148
+ const satPerVb = (_b = (_a = estimates[bucket]) !== null && _a !== void 0 ? _a : estimates["6"]) !== null && _b !== void 0 ? _b : 1.0;
149
+ const paddedRate = Math.max(1.0, satPerVb * 1.1); // 10% headroom
150
+ const fee = feeFromRate(vbytesEstimate, paddedRate);
151
+ return { rate: paddedRate, fee };
152
+ });
153
+ }
154
+ exports.quoteSwapFeeSats = quoteSwapFeeSats;
package/bitcoin.ts ADDED
@@ -0,0 +1,317 @@
1
+ // Methods meant to work with BDK defined within the web::bitcoin module from bitmask-core:
2
+ // https://github.com/diba-io/bitmask-core/blob/development/src/web.rs
3
+
4
+ import * as BMC from "./bitmask_core";
5
+ import { getEnv, getNetwork, Network } from "./constants";
6
+
7
+ export const hashPassword = (password: string) => BMC.hash_password(password);
8
+
9
+ export const decryptWallet = async (
10
+ hash: string,
11
+ encryptedDescriptors: string,
12
+ seedPassword = ""
13
+ ): Promise<Vault> =>
14
+ JSON.parse(
15
+ await BMC.decrypt_wallet(hash, encryptedDescriptors, seedPassword)
16
+ );
17
+
18
+ export const upgradeWallet = async (
19
+ hash: string,
20
+ encryptedDescriptors: string,
21
+ seedPassword = ""
22
+ ): Promise<string> =>
23
+ JSON.parse(
24
+ await BMC.upgrade_wallet(hash, encryptedDescriptors, seedPassword)
25
+ );
26
+
27
+ export const syncWallets = async (): Promise<void> => BMC.sync_wallets();
28
+
29
+ export const newWallet = async (
30
+ hash: string,
31
+ seedPassword: string
32
+ ): Promise<string> => JSON.parse(await BMC.new_wallet(hash, seedPassword));
33
+
34
+ export const encryptWallet = async (
35
+ mnemonic: string,
36
+ hash: string,
37
+ seedPassword: string
38
+ ): Promise<string> =>
39
+ JSON.parse(await BMC.encrypt_wallet(mnemonic, hash, seedPassword));
40
+
41
+ export const getWalletData = async (
42
+ descriptor: string,
43
+ changeDescriptor?: string
44
+ ): Promise<WalletData> =>
45
+ JSON.parse(await BMC.get_wallet_data(descriptor, changeDescriptor));
46
+
47
+ export const getNewAddress = async (
48
+ descriptor: string,
49
+ changeDescriptor?: string
50
+ ): Promise<string> =>
51
+ JSON.parse(await BMC.get_new_address(descriptor, changeDescriptor));
52
+
53
+ export const sendSats = async (
54
+ descriptor: string,
55
+ changeDescriptor: string,
56
+ address: string,
57
+ amount: bigint,
58
+ broadcast: boolean,
59
+ feeRate: number
60
+ ): Promise<TransactionData> =>
61
+ JSON.parse(
62
+ await BMC.send_sats(
63
+ descriptor,
64
+ changeDescriptor,
65
+ address,
66
+ amount,
67
+ broadcast,
68
+ feeRate
69
+ )
70
+ );
71
+
72
+ export const fundVault = async (
73
+ descriptor: string,
74
+ changeDescriptor: string,
75
+ rgbAddress: string,
76
+ broadcast: boolean,
77
+ feeRate?: number
78
+ ): Promise<FundVaultDetails> =>
79
+ JSON.parse(
80
+ await BMC.fund_vault(
81
+ descriptor,
82
+ changeDescriptor,
83
+ rgbAddress,
84
+ broadcast,
85
+ feeRate
86
+ )
87
+ );
88
+
89
+ export const getAssetsVault = async (
90
+ rgbDescriptorXpub: string
91
+ ): Promise<FundVaultDetails> =>
92
+ JSON.parse(await BMC.get_assets_vault(rgbDescriptorXpub));
93
+
94
+ export const drainWallet = async (
95
+ destination: string,
96
+ descriptor: string,
97
+ changeDescriptor?: string,
98
+ feeRate?: number
99
+ ): Promise<TransactionData> =>
100
+ JSON.parse(
101
+ await BMC.drain_wallet(destination, descriptor, changeDescriptor, feeRate)
102
+ );
103
+
104
+ export const bumpFee = async (
105
+ txid: string,
106
+ feeRate: number,
107
+ broadcast: boolean,
108
+ descriptor: string,
109
+ changeDescriptor?: string
110
+ ): Promise<TransactionData> =>
111
+ JSON.parse(
112
+ await BMC.bump_fee(txid, feeRate, descriptor, changeDescriptor, broadcast)
113
+ );
114
+
115
+ // Core type interfaces based on structs defined within the bitmask-core Rust crate:
116
+ // https://github.com/diba-io/bitmask-core/blob/development/src/structs.rs
117
+
118
+ export interface PrivateWalletData {
119
+ xprvkh: string;
120
+ btcDescriptorXprv: string;
121
+ btcChangeDescriptorXprv: string;
122
+ rgbDescriptorXprv: string;
123
+ nostrPrv: string;
124
+ nostrNsec: string;
125
+ }
126
+
127
+ export interface PublicWalletData {
128
+ xpubkh: string;
129
+ btcDescriptorXpub: string;
130
+ btcChangeDescriptorXpub: string;
131
+ rgbDescriptorXpub: string;
132
+ nostrPub: string;
133
+ nostrNpub: string;
134
+ }
135
+
136
+ export interface Vault {
137
+ mnemonic: string;
138
+ private: PrivateWalletData;
139
+ public: PublicWalletData;
140
+ }
141
+
142
+ export interface Transaction extends WalletTransaction {
143
+ amount: number;
144
+ asset?: string;
145
+ assetType: string;
146
+ fee: number;
147
+ message?: string;
148
+ note?: string;
149
+ }
150
+
151
+ export interface Activity extends Transaction {
152
+ id: string;
153
+ date: number;
154
+ action: string;
155
+ status: string;
156
+ lightning?: boolean;
157
+ sender?: {
158
+ name: string;
159
+ address: string;
160
+ };
161
+ recipient?: {
162
+ name: string;
163
+ address: string;
164
+ invoice: string;
165
+ };
166
+ }
167
+
168
+ export interface TransactionDetails extends Transaction {
169
+ sender: {
170
+ name: string;
171
+ address: string;
172
+ };
173
+ recipient: {
174
+ name: string;
175
+ address: string;
176
+ invoice: string;
177
+ };
178
+ }
179
+
180
+ export interface TransactionData {
181
+ details: TransactionDataDetails;
182
+ vsize: number;
183
+ feeRate: number;
184
+ }
185
+
186
+ export interface TransactionDataDetails {
187
+ transaction?: Transaction;
188
+ txid: string;
189
+ received: number;
190
+ sent: number;
191
+ fee: number;
192
+ confirmationTime?: ConfirmationTime;
193
+ confirmed?: boolean;
194
+ }
195
+
196
+ export interface ConfirmationTime {
197
+ height: number;
198
+ timestamp: number;
199
+ }
200
+
201
+ export interface WalletTransaction {
202
+ txid: string;
203
+ received: number;
204
+ sent: number;
205
+ fee: number;
206
+ confirmed: boolean;
207
+ confirmationTime: ConfirmationTime;
208
+ vsize: number;
209
+ feeRate: number;
210
+ }
211
+
212
+ export interface WalletBalance {
213
+ immature: number;
214
+ trustedPending: number;
215
+ untrustedPending: number;
216
+ confirmed: number;
217
+ }
218
+
219
+ export interface WalletData {
220
+ wallet?: string;
221
+ name: string;
222
+ address: string;
223
+ balance: WalletBalance;
224
+ transactions: WalletTransaction[];
225
+ utxos: string[];
226
+ }
227
+
228
+ export interface FundVaultDetails {
229
+ rgbOutput?: string;
230
+ isFunded: boolean;
231
+ fundTxid?: string;
232
+ fundFee?: number;
233
+ }
234
+
235
+ export type FeeEstimates = Record<string, number>;
236
+
237
+ export async function fetchFeeEstimates(): Promise<FeeEstimates> {
238
+ const net = await getNetwork();
239
+
240
+ let envKey: string;
241
+ switch (net) {
242
+ case "bitcoin":
243
+ envKey = "BITCOIN_EXPLORER_API_MAINNET";
244
+ break;
245
+ case "testnet":
246
+ envKey = "BITCOIN_EXPLORER_API_TESTNET";
247
+ break;
248
+ case "signet":
249
+ envKey = "BITCOIN_EXPLORER_API_SIGNET";
250
+ break;
251
+ case "regtest":
252
+ envKey = "BITCOIN_EXPLORER_API_REGTEST";
253
+ break;
254
+ default:
255
+ // Fallback to signet if unknown string is returned
256
+ envKey = "BITCOIN_EXPLORER_API_SIGNET";
257
+ break;
258
+ }
259
+
260
+ const base = await getEnv(envKey);
261
+ if (!base) {
262
+ throw new Error(`fee-estimates: missing env ${envKey} for network ${net}`);
263
+ }
264
+
265
+ const baseUrl = (base || "").replace(/\/$/, "");
266
+ const url = `${baseUrl}/fee-estimates`;
267
+ const resp = await fetch(url, { method: "GET" });
268
+ if (!resp.ok) {
269
+ const text = await resp.text().catch(() => "");
270
+ throw new Error(`fee-estimates fetch failed ${resp.status}: ${text}`);
271
+ }
272
+ return (await resp.json()) as FeeEstimates;
273
+ }
274
+
275
+ export function feeFromRate(vbytes: number, satPerVb: number): number {
276
+ return Math.ceil(vbytes * satPerVb);
277
+ }
278
+
279
+ /**
280
+ * Rough vbytes guesser for swap/bid PSBTs when you don't yet know exact inputs/outputs.
281
+ * Prefer passing a conservative bound to avoid underpaying relays:
282
+ * - Default assumes ~2 inputs, ~3 outputs, taproot heavy mix, returns ~400 vB.
283
+ * - Scale linearly for more inputs/outputs.
284
+ *
285
+ * If you know inputs/outputs counts beforehand, pass them to tighten the estimate.
286
+ */
287
+ export function guessSwapVbytes(
288
+ inputs = 2,
289
+ outputs = 3,
290
+ taprootHeavy = true
291
+ ): number {
292
+ // Heuristic base (conservative): taproot-heavy ~180 vB per input, ~34 vB per output, +10 overhead
293
+ // Non-taproot may be slightly bigger; this errs on the safe side.
294
+ const perIn = taprootHeavy ? 180 : 200;
295
+ const perOut = 34;
296
+ const overhead = 10;
297
+ // Ensure a floor to avoid extremely small estimates in edge cases
298
+ const est = inputs * perIn + outputs * perOut + overhead;
299
+ return Math.max(est, 300);
300
+ }
301
+
302
+ /**
303
+ * Convenience: get a safe absolute fee quote for a swap given a target confirmation bucket.
304
+ * - bucket can be "1","2","3","6","144", etc., matching Esplora keys.
305
+ * - vbytesEstimate can be computed via guessSwapVbytes() or a tighter UI estimate.
306
+ * - Adds a small 10% safety margin on the feerate to reduce min-relay rejections.
307
+ */
308
+ export async function quoteSwapFeeSats(
309
+ bucket: string,
310
+ vbytesEstimate: number
311
+ ): Promise<{ rate: number; fee: number }> {
312
+ const estimates = await fetchFeeEstimates();
313
+ const satPerVb = estimates[bucket] ?? estimates["6"] ?? 1.0;
314
+ const paddedRate = Math.max(1.0, satPerVb * 1.1); // 10% headroom
315
+ const fee = feeFromRate(vbytesEstimate, paddedRate);
316
+ return { rate: paddedRate, fee };
317
+ }
package/bitmask_core.js CHANGED
@@ -2256,19 +2256,19 @@ function __wbg_get_imports() {
2256
2256
  const ret = false;
2257
2257
  return ret;
2258
2258
  };
2259
- imports.wbg.__wbindgen_closure_wrapper11530 = function(arg0, arg1, arg2) {
2259
+ imports.wbg.__wbindgen_closure_wrapper11536 = function(arg0, arg1, arg2) {
2260
2260
  const ret = makeMutClosure(arg0, arg1, 2666, __wbg_adapter_60);
2261
2261
  return ret;
2262
2262
  };
2263
- imports.wbg.__wbindgen_closure_wrapper15959 = function(arg0, arg1, arg2) {
2263
+ imports.wbg.__wbindgen_closure_wrapper15965 = function(arg0, arg1, arg2) {
2264
2264
  const ret = makeMutClosure(arg0, arg1, 3826, __wbg_adapter_63);
2265
2265
  return ret;
2266
2266
  };
2267
- imports.wbg.__wbindgen_closure_wrapper7697 = function(arg0, arg1, arg2) {
2267
+ imports.wbg.__wbindgen_closure_wrapper7702 = function(arg0, arg1, arg2) {
2268
2268
  const ret = makeMutClosure(arg0, arg1, 1856, __wbg_adapter_54);
2269
2269
  return ret;
2270
2270
  };
2271
- imports.wbg.__wbindgen_closure_wrapper8145 = function(arg0, arg1, arg2) {
2271
+ imports.wbg.__wbindgen_closure_wrapper8151 = function(arg0, arg1, arg2) {
2272
2272
  const ret = makeMutClosure(arg0, arg1, 1998, __wbg_adapter_57);
2273
2273
  return ret;
2274
2274
  };
Binary file
package/bp.d.ts ADDED
@@ -0,0 +1,28 @@
1
+ import { FundVaultDetails, TransactionDataDetails, WalletTransaction } from "./bitcoin";
2
+ export declare const transferBtc: (nostrHexSk: string, address: string, sats: bigint, feeRate: number, secrets: string[]) => Promise<TransactionData>;
3
+ export declare const fundRgbVault: (nostrHexSk: string, feeRate: number, secrets: string[], broadcast: boolean, fundValue?: bigint | null, coordinatorFee?: boolean | null) => Promise<FundVaultDetails>;
4
+ export declare const backupBtcWallet: (nostrHexSk: string) => Promise<boolean>;
5
+ export declare const restoreBtcWallet: (nostrHexSk: string) => Promise<boolean>;
6
+ export declare const recoverFundsFromBadWallets: (seed: string, passPhrase: string, recoverAddress: string) => Promise<RecoverVaultDetails>;
7
+ export declare const getBtcWallet: (nostrHexSk: string) => Promise<WalletData>;
8
+ export interface TransactionData {
9
+ details: TransactionDataDetails;
10
+ vsize: number;
11
+ feeRate: number;
12
+ }
13
+ export interface WalletBalance {
14
+ confirmed: number;
15
+ }
16
+ export interface WalletData {
17
+ wallet?: string;
18
+ name: string;
19
+ address: string;
20
+ balance: WalletBalance;
21
+ transactions: WalletTransaction[];
22
+ utxos: string[];
23
+ }
24
+ export interface RecoverVaultDetails {
25
+ txid: string;
26
+ fee: number;
27
+ }
28
+ //# sourceMappingURL=bp.d.ts.map