@glyphteck/veyl 0.51.0 → 0.55.0

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/dist/account.js CHANGED
@@ -6346,10 +6346,10 @@ var domains = Object.freeze({
6346
6346
  var origins = Object.freeze({
6347
6347
  root: `https://${domains.root}`,
6348
6348
  rootDev: `https://${domains.rootDev}`,
6349
- rootDevWeb: `https://${domains.rootDev}:3001`,
6350
6349
  veyl: `https://${domains.veyl}`,
6351
6350
  veylDev: `https://${domains.veylDev}`,
6352
- veylDevWeb: `https://${domains.veylDev}:3000`
6351
+ veylDevWeb: `https://${domains.veylDev}:3000`,
6352
+ veylDevFeatureWeb: `https://${domains.veylDev}:3001`
6353
6353
  });
6354
6354
  var appDomains = Object.freeze([
6355
6355
  domains.veyl
@@ -7143,6 +7143,84 @@ function clearSettingsKey(key) {
7143
7143
  cleanBytes(key);
7144
7144
  }
7145
7145
 
7146
+ // ../../core/utils/number.js
7147
+ function nonNegativeNumber(value, fallback) {
7148
+ const next = Number(value);
7149
+ return Number.isFinite(next) && next >= 0 ? next : fallback;
7150
+ }
7151
+ function positiveNumber(value, fallback) {
7152
+ const next = Number(value);
7153
+ return Number.isFinite(next) && next > 0 ? next : fallback;
7154
+ }
7155
+ function positiveInt(value, fallback) {
7156
+ const next = Math.trunc(Number(value));
7157
+ return Number.isFinite(next) && next > 0 ? next : fallback;
7158
+ }
7159
+ function nonNegativeInt(value, fallback) {
7160
+ const next = Math.trunc(Number(value));
7161
+ return Number.isFinite(next) && next >= 0 ? next : fallback;
7162
+ }
7163
+
7164
+ // ../../core/utils/async.js
7165
+ function sleep(ms) {
7166
+ return new Promise((resolve) => setTimeout(resolve, nonNegativeNumber(ms, 0)));
7167
+ }
7168
+ function createOwnedWaits() {
7169
+ const waits = new Set;
7170
+ let closed = false;
7171
+ const wait = (schedule, cancel) => new Promise((resolve) => {
7172
+ if (closed) {
7173
+ resolve();
7174
+ return;
7175
+ }
7176
+ const pending = { cancel, id: null, resolve };
7177
+ pending.id = schedule(() => {
7178
+ waits.delete(pending);
7179
+ resolve();
7180
+ });
7181
+ waits.add(pending);
7182
+ });
7183
+ return {
7184
+ delay(ms) {
7185
+ return wait((done) => globalThis.setTimeout(done, nonNegativeNumber(ms, 0)), (id) => globalThis.clearTimeout(id));
7186
+ },
7187
+ idle({ timeout = 0, delay = 0 } = {}) {
7188
+ const requestIdle = globalThis.requestIdleCallback?.bind(globalThis);
7189
+ const cancelIdle = globalThis.cancelIdleCallback?.bind(globalThis);
7190
+ if (typeof requestIdle === "function" && typeof cancelIdle === "function") {
7191
+ return wait((done) => requestIdle(done, { timeout: nonNegativeNumber(timeout, 0) }), cancelIdle);
7192
+ }
7193
+ return wait((done) => globalThis.setTimeout(done, nonNegativeNumber(delay, 0)), (id) => globalThis.clearTimeout(id));
7194
+ },
7195
+ close() {
7196
+ if (closed)
7197
+ return;
7198
+ closed = true;
7199
+ for (const pending of waits) {
7200
+ pending.cancel(pending.id);
7201
+ pending.resolve();
7202
+ }
7203
+ waits.clear();
7204
+ }
7205
+ };
7206
+ }
7207
+ async function yieldToUi() {
7208
+ if (typeof requestAnimationFrame === "function") {
7209
+ await new Promise((resolve) => requestAnimationFrame(resolve));
7210
+ }
7211
+ await sleep(0);
7212
+ }
7213
+ function waitForIdle({ timeout = 0, delay = 0 } = {}) {
7214
+ return new Promise((resolve) => {
7215
+ const idle = globalThis.requestIdleCallback?.bind(globalThis);
7216
+ if (typeof idle === "function") {
7217
+ idle(() => resolve(), { timeout: nonNegativeNumber(timeout, 0) });
7218
+ return;
7219
+ }
7220
+ globalThis.setTimeout(resolve, nonNegativeNumber(delay, 0));
7221
+ });
7222
+ }
7223
+
7146
7224
  // ../../core/crypto/sign.js
7147
7225
  "use client";
7148
7226
  var CHAT_SIGNING_SCOPE = "chat-actor-sign-v2";
@@ -8067,6 +8145,8 @@ async function openVaultAccountSession(vault, password, options = {}) {
8067
8145
  mark(diag, "vault.unlock.decrypt.done", { elapsedMs: Date.now() - decryptStartedAt, source });
8068
8146
  onStage?.("seed-decrypted");
8069
8147
  notifySeedDecrypted(onSeedDecrypted, diag, source);
8148
+ await yieldToUi();
8149
+ requireCurrent(isCurrent);
8070
8150
  onStage?.("deriving");
8071
8151
  const deriveStartedAt = Date.now();
8072
8152
  const registry = await openSecretRegistry(masterSeed, registryEnvelope);
@@ -8334,12 +8414,9 @@ function nextBanRefreshMs(banned, keys = ["full", "chat"], now = Date.now()) {
8334
8414
  }
8335
8415
 
8336
8416
  // ../../core/profile.js
8337
- var BOT_PROFILE_MARKER = "bot";
8417
+ var BOT_PROFILE_MARKER = "glyphteck";
8338
8418
  function readBotMarker(profile) {
8339
- const bot = profile?.bot;
8340
- if (!bot)
8341
- return null;
8342
- return typeof bot === "string" ? bot : BOT_PROFILE_MARKER;
8419
+ return profile?.bot === BOT_PROFILE_MARKER ? BOT_PROFILE_MARKER : null;
8343
8420
  }
8344
8421
  function hasPeerKeys(profile) {
8345
8422
  return !!(profile?.walletPK || profile?.chatPK);
@@ -9385,24 +9462,6 @@ async function makeSharedFileUploadPayload(data, { contentType = "application/oc
9385
9462
  }
9386
9463
  }
9387
9464
 
9388
- // ../../core/utils/number.js
9389
- function nonNegativeNumber(value, fallback) {
9390
- const next = Number(value);
9391
- return Number.isFinite(next) && next >= 0 ? next : fallback;
9392
- }
9393
- function positiveNumber(value, fallback) {
9394
- const next = Number(value);
9395
- return Number.isFinite(next) && next > 0 ? next : fallback;
9396
- }
9397
- function positiveInt(value, fallback) {
9398
- const next = Math.trunc(Number(value));
9399
- return Number.isFinite(next) && next > 0 ? next : fallback;
9400
- }
9401
- function nonNegativeInt(value, fallback) {
9402
- const next = Math.trunc(Number(value));
9403
- return Number.isFinite(next) && next >= 0 ? next : fallback;
9404
- }
9405
-
9406
9465
  // ../../core/chat/messages/files.js
9407
9466
  function hasLocalFileRef(msg) {
9408
9467
  if (!hasText(msg?.p) || !hasText(msg?.k)) {
@@ -12412,8 +12471,8 @@ var HIDDEN_TRANSFER_STATUSES = new Set(["TRANSFER_STATUS_EXPIRED", "TRANSFER_STA
12412
12471
  var LIGHTNING_RECEIVE_DONE_STATUSES = new Set(["transfer_completed", "lightning_payment_received", "payment_preimage_recovered", "completed"]);
12413
12472
  var WALLET_TRANSFER_TYPE_CODES = new Set([TRANSFER_TYPE_TRANSFER_CODE]);
12414
12473
  var WALLET_TRANSFER_TYPES = new Set([TRANSFER_TYPE_TRANSFER]);
12415
- var WITHDRAWAL_TRANSFER_TYPE_CODES = new Set([TRANSFER_TYPE_COOPERATIVE_EXIT_CODE]);
12416
- var WITHDRAWAL_TRANSFER_TYPES = new Set([TRANSFER_TYPE_COOPERATIVE_EXIT]);
12474
+ var BITCOIN_PAYMENT_TRANSFER_TYPE_CODES = new Set([TRANSFER_TYPE_COOPERATIVE_EXIT_CODE]);
12475
+ var BITCOIN_PAYMENT_TRANSFER_TYPES = new Set([TRANSFER_TYPE_COOPERATIVE_EXIT]);
12417
12476
  var BITCOIN_DEPOSIT_TYPE_CODES = new Set;
12418
12477
  var BITCOIN_DEPOSIT_TYPES = new Set([TRANSFER_TYPE_BITCOIN_DEPOSIT]);
12419
12478
  var FUNDING_TRANSFER_TYPE_CODES = new Set([TRANSFER_TYPE_UTXO_SWAP_CODE]);
@@ -12447,8 +12506,8 @@ function isPendingTransfer(tx) {
12447
12506
  function isWalletTransfer(tx) {
12448
12507
  return hasTransferType(tx, WALLET_TRANSFER_TYPES, WALLET_TRANSFER_TYPE_CODES);
12449
12508
  }
12450
- function isWithdrawalTransfer(tx) {
12451
- return hasTransferType(tx, WITHDRAWAL_TRANSFER_TYPES, WITHDRAWAL_TRANSFER_TYPE_CODES);
12509
+ function isBitcoinPaymentTransfer(tx) {
12510
+ return hasTransferType(tx, BITCOIN_PAYMENT_TRANSFER_TYPES, BITCOIN_PAYMENT_TRANSFER_TYPE_CODES);
12452
12511
  }
12453
12512
  function isFundingTransfer(tx) {
12454
12513
  if (hasTransferType(tx, BITCOIN_DEPOSIT_TYPES, BITCOIN_DEPOSIT_TYPE_CODES)) {
@@ -12464,7 +12523,7 @@ function isVisibleTransferStatus(tx) {
12464
12523
  return !status || !HIDDEN_TRANSFER_STATUSES.has(status);
12465
12524
  }
12466
12525
  function isVisibleTransfer(tx) {
12467
- return isVisibleTransferStatus(tx) && (isWalletTransfer(tx) || isFundingTransfer(tx) || isWithdrawalTransfer(tx));
12526
+ return isVisibleTransferStatus(tx) && (isWalletTransfer(tx) || isFundingTransfer(tx) || isBitcoinPaymentTransfer(tx));
12468
12527
  }
12469
12528
  function isClaimablePendingTransfer(tx, types = null) {
12470
12529
  if (Array.isArray(types) && types.length && !types.includes(tx?.type)) {
@@ -15939,66 +15998,6 @@ function sameHead(a, b) {
15939
15998
  return a?.from === b?.from && a?.cid === b?.cid;
15940
15999
  }
15941
16000
 
15942
- // ../../core/utils/async.js
15943
- function sleep(ms) {
15944
- return new Promise((resolve) => setTimeout(resolve, nonNegativeNumber(ms, 0)));
15945
- }
15946
- function createOwnedWaits() {
15947
- const waits = new Set;
15948
- let closed = false;
15949
- const wait = (schedule, cancel) => new Promise((resolve) => {
15950
- if (closed) {
15951
- resolve();
15952
- return;
15953
- }
15954
- const pending = { cancel, id: null, resolve };
15955
- pending.id = schedule(() => {
15956
- waits.delete(pending);
15957
- resolve();
15958
- });
15959
- waits.add(pending);
15960
- });
15961
- return {
15962
- delay(ms) {
15963
- return wait((done) => globalThis.setTimeout(done, nonNegativeNumber(ms, 0)), (id) => globalThis.clearTimeout(id));
15964
- },
15965
- idle({ timeout = 0, delay = 0 } = {}) {
15966
- const requestIdle = globalThis.requestIdleCallback?.bind(globalThis);
15967
- const cancelIdle = globalThis.cancelIdleCallback?.bind(globalThis);
15968
- if (typeof requestIdle === "function" && typeof cancelIdle === "function") {
15969
- return wait((done) => requestIdle(done, { timeout: nonNegativeNumber(timeout, 0) }), cancelIdle);
15970
- }
15971
- return wait((done) => globalThis.setTimeout(done, nonNegativeNumber(delay, 0)), (id) => globalThis.clearTimeout(id));
15972
- },
15973
- close() {
15974
- if (closed)
15975
- return;
15976
- closed = true;
15977
- for (const pending of waits) {
15978
- pending.cancel(pending.id);
15979
- pending.resolve();
15980
- }
15981
- waits.clear();
15982
- }
15983
- };
15984
- }
15985
- async function yieldToUi() {
15986
- if (typeof requestAnimationFrame === "function") {
15987
- await new Promise((resolve) => requestAnimationFrame(resolve));
15988
- }
15989
- await sleep(0);
15990
- }
15991
- function waitForIdle({ timeout = 0, delay = 0 } = {}) {
15992
- return new Promise((resolve) => {
15993
- const idle = globalThis.requestIdleCallback?.bind(globalThis);
15994
- if (typeof idle === "function") {
15995
- idle(() => resolve(), { timeout: nonNegativeNumber(timeout, 0) });
15996
- return;
15997
- }
15998
- globalThis.setTimeout(resolve, nonNegativeNumber(delay, 0));
15999
- });
16000
- }
16001
-
16002
16001
  // ../../core/chat/messages/payloadlog.js
16003
16002
  var CHAT_PAYLOAD_DIAG_ENV = globalThis.process?.env || {};
16004
16003
  var CHAT_PAYLOAD_DIAG_DEV = typeof globalThis !== "undefined" && globalThis.__DEV__ === true || CHAT_PAYLOAD_DIAG_ENV?.NODE_ENV === "development";
@@ -21194,7 +21193,7 @@ var FEE_RATE_FALLBACKS = Object.freeze({
21194
21193
  noPriority: Object.freeze(["low", "medium", "high"]),
21195
21194
  average: Object.freeze(["medium", "low", "high"])
21196
21195
  });
21197
- var WITHDRAWAL_FEE_FIELDS = Object.freeze({
21196
+ var BITCOIN_PAYMENT_FEE_FIELDS = Object.freeze({
21198
21197
  FAST: Object.freeze({ user: "userFeeFast", l1: "l1BroadcastFeeFast" }),
21199
21198
  MEDIUM: Object.freeze({ user: "userFeeMedium", l1: "l1BroadcastFeeMedium" }),
21200
21199
  SLOW: Object.freeze({ user: "userFeeSlow", l1: "l1BroadcastFeeSlow" })
@@ -21240,12 +21239,12 @@ function getCurrencyAmountSats(amount) {
21240
21239
  }
21241
21240
  return value;
21242
21241
  }
21243
- function getWithdrawalFeeBreakdown(feeQuote, exitSpeed = DEFAULT_EXIT_SPEED) {
21242
+ function getBitcoinPaymentFeeBreakdown(feeQuote, exitSpeed = DEFAULT_EXIT_SPEED) {
21244
21243
  if (!feeQuote) {
21245
21244
  return null;
21246
21245
  }
21247
21246
  const speed = getExitSpeed(exitSpeed);
21248
- const fields = WITHDRAWAL_FEE_FIELDS[speed];
21247
+ const fields = BITCOIN_PAYMENT_FEE_FIELDS[speed];
21249
21248
  const userFeeSats = getCurrencyAmountSats(feeQuote[fields.user]);
21250
21249
  const l1BroadcastFeeSats = getCurrencyAmountSats(feeQuote[fields.l1]);
21251
21250
  return {
@@ -21257,16 +21256,16 @@ function getWithdrawalFeeBreakdown(feeQuote, exitSpeed = DEFAULT_EXIT_SPEED) {
21257
21256
  expiresAt: feeQuote.expiresAt ?? null
21258
21257
  };
21259
21258
  }
21260
- function getWithdrawalFeeAmountSats(feeQuote, exitSpeed = DEFAULT_EXIT_SPEED) {
21261
- return getWithdrawalFeeBreakdown(feeQuote, exitSpeed)?.feeAmountSats ?? null;
21259
+ function getBitcoinPaymentFeeAmountSats(feeQuote, exitSpeed = DEFAULT_EXIT_SPEED) {
21260
+ return getBitcoinPaymentFeeBreakdown(feeQuote, exitSpeed)?.feeAmountSats ?? null;
21262
21261
  }
21263
- function normalizeWithdrawalFeeQuote(feeQuote) {
21262
+ function normalizeBitcoinPaymentFeeQuote(feeQuote) {
21264
21263
  if (!feeQuote) {
21265
21264
  return null;
21266
21265
  }
21267
21266
  const speeds = {};
21268
21267
  for (const speed of EXIT_SPEEDS) {
21269
- speeds[speed] = getWithdrawalFeeBreakdown(feeQuote, speed);
21268
+ speeds[speed] = getBitcoinPaymentFeeBreakdown(feeQuote, speed);
21270
21269
  }
21271
21270
  return {
21272
21271
  id: feeQuote.id ?? null,
@@ -23855,59 +23854,6 @@ async function createLightningInvoice(wallet, { amountSats = 0, memo, expirySeco
23855
23854
  return { success: false, error };
23856
23855
  }
23857
23856
  }
23858
- async function quoteLightningFees(wallet, { invoice, amountSats } = {}) {
23859
- if (!wallet) {
23860
- return { success: false, error: new Error("wallet not ready") };
23861
- }
23862
- const encodedInvoice = cleanText(invoice);
23863
- if (!encodedInvoice) {
23864
- return { success: false, error: new Error("lightning invoice required") };
23865
- }
23866
- try {
23867
- const params = { encodedInvoice };
23868
- if (amountSats != null) {
23869
- params.amountSats = toSafeSats(amountSats);
23870
- }
23871
- const feeAmountSats = await wallet.getLightningSendFeeEstimate(params);
23872
- return {
23873
- success: true,
23874
- feeAmountSats,
23875
- fees: normalizeLightningFeeEstimate(feeAmountSats)
23876
- };
23877
- } catch (error) {
23878
- return { success: false, error };
23879
- }
23880
- }
23881
- async function sendLightningPayment(wallet, { invoice, maxFeeSats, preferSpark = false, amountSatsToSend, idempotencyKey } = {}) {
23882
- if (!wallet) {
23883
- return { success: false, error: new Error("wallet not ready") };
23884
- }
23885
- const encodedInvoice = cleanText(invoice);
23886
- if (!encodedInvoice) {
23887
- return { success: false, error: new Error("lightning invoice required") };
23888
- }
23889
- try {
23890
- const params = {
23891
- invoice: encodedInvoice,
23892
- maxFeeSats: toSafeNonNegativeSats(maxFeeSats, "maxFeeSats"),
23893
- preferSpark: !!preferSpark
23894
- };
23895
- if (amountSatsToSend != null) {
23896
- params.amountSatsToSend = toSafeSats(amountSatsToSend, "amountSatsToSend");
23897
- }
23898
- if (idempotencyKey) {
23899
- params.idempotencyKey = idempotencyKey;
23900
- }
23901
- const payment = await wallet.payLightningInvoice(params);
23902
- return {
23903
- success: true,
23904
- payment,
23905
- result: normalizeLightningPaymentResult(payment)
23906
- };
23907
- } catch (error) {
23908
- return { success: false, error };
23909
- }
23910
- }
23911
23857
  async function getLightningReceiveRequest(wallet, id) {
23912
23858
  if (!wallet) {
23913
23859
  return { success: false, error: new Error("wallet not ready") };
@@ -23948,17 +23894,9 @@ async function getLightningSendRequest(wallet, id) {
23948
23894
  }
23949
23895
 
23950
23896
  // ../../core/wallet/lightning.js
23951
- function createLightning({ wallet, updateWalletData }) {
23897
+ function createLightning({ wallet }) {
23952
23898
  return {
23953
23899
  createLightningInvoice: (params) => createLightningInvoice(wallet, params),
23954
- quoteLightningFees: (params) => quoteLightningFees(wallet, params),
23955
- async sendLightningPayment(params) {
23956
- const result = await sendLightningPayment(wallet, params);
23957
- if (result.success) {
23958
- await updateWalletData({ reason: "lightning-send" });
23959
- }
23960
- return result;
23961
- },
23962
23900
  getLightningReceiveRequest: (id) => getLightningReceiveRequest(wallet, id),
23963
23901
  getLightningSendRequest: (id) => getLightningSendRequest(wallet, id)
23964
23902
  };
@@ -24456,56 +24394,6 @@ function createWalletReadyDiag({ wallet, getBalanceState, getTransferState, diag
24456
24394
  };
24457
24395
  }
24458
24396
 
24459
- // ../../core/wallet/privacy.js
24460
- var PRIVACY_SYNC_DELAY_MS = WALLET_BOOT_CACHED_REFRESH_DELAY_MS * 2;
24461
- function createWalletPrivacy({ wallet, ghostWallet, diag }) {
24462
- let desiredPrivacy = ghostWallet === true;
24463
- let revision = 0;
24464
- let closed = false;
24465
- let privacySync = Promise.resolve();
24466
- const waits = createOwnedWaits();
24467
- const setGhostWallet = (nextGhostWallet) => {
24468
- const nextDesiredPrivacy = nextGhostWallet === true;
24469
- if (revision > 0 && desiredPrivacy === nextDesiredPrivacy) {
24470
- return privacySync;
24471
- }
24472
- desiredPrivacy = nextDesiredPrivacy;
24473
- const requestRevision = ++revision;
24474
- if (!wallet || typeof wallet.setPrivacyEnabled !== "function" || closed) {
24475
- return privacySync;
24476
- }
24477
- privacySync = privacySync.catch(() => {}).then(async () => {
24478
- await waits.delay(PRIVACY_SYNC_DELAY_MS);
24479
- if (closed || requestRevision !== revision) {
24480
- return;
24481
- }
24482
- await waits.idle({ timeout: PRIVACY_SYNC_DELAY_MS, delay: PRIVACY_SYNC_DELAY_MS });
24483
- if (closed || requestRevision !== revision) {
24484
- return;
24485
- }
24486
- const startedAt = Date.now();
24487
- const desired = desiredPrivacy;
24488
- markDiag(diag, "wallet.privacy.start", { ghostWallet: desired });
24489
- await wallet.setPrivacyEnabled(desired);
24490
- markDone(diag, "wallet.privacy", startedAt, { changed: true });
24491
- }).catch((error) => {
24492
- markDiag(diag, "wallet.privacy.error", { code: error?.code || "", message: error?.message || String(error) });
24493
- });
24494
- return privacySync;
24495
- };
24496
- setGhostWallet(ghostWallet);
24497
- return {
24498
- setGhostWallet,
24499
- close() {
24500
- if (closed)
24501
- return;
24502
- closed = true;
24503
- revision += 1;
24504
- waits.close();
24505
- }
24506
- };
24507
- }
24508
-
24509
24397
  // ../../core/wallet/spark.js
24510
24398
  var import_bech32 = __toESM(require_dist(), 1);
24511
24399
  var SPARK_ADDRESS_PREFIX = Object.freeze({
@@ -24550,7 +24438,58 @@ function walletPKtoSparkAddress(walletPK, network) {
24550
24438
  return import_bech32.bech32m.encode(getSparkAddressPrefix(network), import_bech32.bech32m.toWords(payload), 1500);
24551
24439
  }
24552
24440
 
24553
- // ../../core/wallet/send.js
24441
+ // ../../core/wallet/payment.js
24442
+ var PAYMENT_KIND_BITCOIN = "bitcoin";
24443
+ var PAYMENT_KIND_LIGHTNING = "lightning";
24444
+ var PAYMENT_KIND_SPARK = "spark";
24445
+ var PAYMENT_KIND_SPARK_INVOICE = "spark_invoice";
24446
+ var PAYMENT_STATE_PREPARED = "prepared";
24447
+ var PAYMENT_KINDS = new Set([
24448
+ PAYMENT_KIND_BITCOIN,
24449
+ PAYMENT_KIND_LIGHTNING,
24450
+ PAYMENT_KIND_SPARK,
24451
+ PAYMENT_KIND_SPARK_INVOICE
24452
+ ]);
24453
+ var P2PKH_DUST_SATS = 546;
24454
+ var P2SH_DUST_SATS = 540;
24455
+ var P2WPKH_DUST_SATS = 294;
24456
+ var SEGWIT_SCRIPT_DUST_SATS = 330;
24457
+ function paymentKind(value) {
24458
+ const kind = cleanText(value).toLowerCase();
24459
+ if (!PAYMENT_KINDS.has(kind)) {
24460
+ throw new Error("unsupported payment kind");
24461
+ }
24462
+ return kind;
24463
+ }
24464
+ function paymentDestination(value) {
24465
+ const destination = cleanText(value);
24466
+ if (!destination) {
24467
+ throw new Error("payment destination required");
24468
+ }
24469
+ return destination;
24470
+ }
24471
+ function optionalPaymentAmount(value) {
24472
+ return value == null ? null : toSafeSats(value);
24473
+ }
24474
+ function normalizeIntent(intent = {}) {
24475
+ const kind = paymentKind(intent.kind);
24476
+ const destination = paymentDestination(intent.destination);
24477
+ const amountSats = optionalPaymentAmount(intent.amountSats);
24478
+ if ((kind === PAYMENT_KIND_BITCOIN || kind === PAYMENT_KIND_SPARK) && amountSats == null) {
24479
+ throw new Error("payment amount required");
24480
+ }
24481
+ return {
24482
+ kind,
24483
+ destination,
24484
+ amountSats,
24485
+ variableAmount: intent.variableAmount === true,
24486
+ preferSpark: intent.preferSpark === true,
24487
+ idempotencyKey: cleanText(intent.idempotencyKey) || null,
24488
+ maxFeeSats: intent.maxFeeSats == null ? null : toSafeNonNegativeSats(intent.maxFeeSats, "maxFeeSats"),
24489
+ exitSpeed: getExitSpeed(intent.exitSpeed),
24490
+ deductFeeFromAmount: intent.deductFeeFromAmount !== false
24491
+ };
24492
+ }
24554
24493
  function firstSparkInvoiceError(result) {
24555
24494
  return result?.invalidInvoices?.[0]?.error || result?.satsTransactionErrors?.[0]?.error || result?.tokenTransactionErrors?.[0]?.error || null;
24556
24495
  }
@@ -24566,137 +24505,345 @@ function publicSparkInvoiceResult(transfer) {
24566
24505
  amountSats: Number.isSafeInteger(transfer?.totalValue) ? transfer.totalValue : null
24567
24506
  };
24568
24507
  }
24569
- function createWalletSend({ wallet, network, updateWalletData, refreshBalance = null, rememberTransfer, refreshPendingTransfers = null, sentTransferRefreshDelayMs = null, beginSdkActivity = null, diag }) {
24570
- const refreshTimers = new Set;
24571
- let closed = false;
24572
- const sendMoneyWithSpark = async (receiverWalletPK, amountSats) => {
24573
- if (!wallet || closed) {
24574
- throw new Error("wallet not ready");
24508
+ function getBitcoinPaymentMinimumReceiveSats(addressInput) {
24509
+ const address = cleanText(addressInput).toLowerCase();
24510
+ if (address.startsWith("1"))
24511
+ return P2PKH_DUST_SATS;
24512
+ if (address.startsWith("3"))
24513
+ return P2SH_DUST_SATS;
24514
+ const p2wpkhLength = address.startsWith("bcrt1q") ? 44 : 42;
24515
+ if ((address.startsWith("bc1q") || address.startsWith("bcrt1q")) && address.length === p2wpkhLength) {
24516
+ return P2WPKH_DUST_SATS;
24517
+ }
24518
+ return SEGWIT_SCRIPT_DUST_SATS;
24519
+ }
24520
+ function getBitcoinPaymentAmounts(payment) {
24521
+ const amountSats = toSafeSats(payment?.amountSats);
24522
+ const feeAmountSats = toSafeNonNegativeSats(payment?.feeAmountSats ?? 0, "feeAmountSats");
24523
+ const deductFeeFromAmount = payment?.deductFeeFromAmount !== false;
24524
+ const receiveAmountSats = deductFeeFromAmount ? Math.max(0, amountSats - feeAmountSats) : amountSats;
24525
+ const sendAmountSats = deductFeeFromAmount ? amountSats : amountSats + feeAmountSats;
24526
+ return {
24527
+ sendAmountSats,
24528
+ receiveAmountSats,
24529
+ feeAmountSats
24530
+ };
24531
+ }
24532
+ function assertBitcoinPaymentReceivesFunds(payment) {
24533
+ const { receiveAmountSats } = getBitcoinPaymentAmounts(payment);
24534
+ const minimumReceiveAmountSats = getBitcoinPaymentMinimumReceiveSats(payment?.destination);
24535
+ if (receiveAmountSats < minimumReceiveAmountSats) {
24536
+ throw new Error(`bitcoin payment would create a dust output below ${minimumReceiveAmountSats} sats`);
24537
+ }
24538
+ }
24539
+ function bitcoinPaymentReview(intent, feeQuote) {
24540
+ const feeQuoteId = feeQuote?.id ?? null;
24541
+ const feeAmountSats = getBitcoinPaymentFeeAmountSats(feeQuote, intent.exitSpeed);
24542
+ if (!feeQuoteId || feeAmountSats == null) {
24543
+ throw new Error("bitcoin payment fee quote unavailable");
24544
+ }
24545
+ const sparkFees = normalizeBitcoinPaymentFeeQuote(feeQuote);
24546
+ const payment = {
24547
+ ...intent,
24548
+ state: PAYMENT_STATE_PREPARED,
24549
+ feeQuote,
24550
+ feeQuoteId,
24551
+ feeAmountSats,
24552
+ fees: { spark: sparkFees },
24553
+ expiresAt: sparkFees?.expiresAt ?? feeQuote.expiresAt ?? null
24554
+ };
24555
+ assertBitcoinPaymentReceivesFunds(payment);
24556
+ return Object.freeze(payment);
24557
+ }
24558
+ function preparedPayment(intent, extra = {}) {
24559
+ return Object.freeze({
24560
+ ...intent,
24561
+ state: PAYMENT_STATE_PREPARED,
24562
+ fees: null,
24563
+ expiresAt: null,
24564
+ ...extra
24565
+ });
24566
+ }
24567
+ async function prepare(wallet, network, paymentInput) {
24568
+ if (!wallet) {
24569
+ throw new Error("wallet not ready");
24570
+ }
24571
+ const intent = normalizeIntent(paymentInput);
24572
+ if (intent.kind === PAYMENT_KIND_BITCOIN) {
24573
+ if (!isAddressOnNetwork(intent.destination, network)) {
24574
+ throw new Error(`refusing to pay - address is not a ${network} address`);
24575
24575
  }
24576
- const startedAt = Date.now();
24577
- markDiag(diag, "wallet.send.start", {});
24578
- const endSdkActivity = typeof beginSdkActivity === "function" ? beginSdkActivity("send") : null;
24579
- try {
24580
- const receiverSparkAddress = walletPKtoSparkAddress(receiverWalletPK, network);
24581
- const tx = await wallet.transfer({
24582
- receiverSparkAddress,
24583
- amountSats: toSafeSats(amountSats)
24584
- });
24585
- endSdkActivity?.();
24586
- markDone(diag, "wallet.send.sdk", startedAt, { hasTransfer: !!tx?.id });
24587
- const rememberStartedAt = Date.now();
24588
- await rememberTransfer?.(tx, { pending: true });
24589
- markDone(diag, "wallet.send.remember", rememberStartedAt, { hasTransfer: !!tx?.id });
24590
- await refreshBalance?.();
24591
- const refreshDelayMs = Number(sentTransferRefreshDelayMs);
24592
- if (!closed && tx?.id && typeof refreshPendingTransfers === "function" && Number.isFinite(refreshDelayMs) && refreshDelayMs >= 0) {
24593
- markDiag(diag, "wallet.send.refresh.schedule", { delayMs: refreshDelayMs });
24594
- const timer = setTimeout(() => {
24595
- refreshTimers.delete(timer);
24596
- if (closed)
24597
- return;
24598
- markDiag(diag, "wallet.send.refresh.start", {});
24599
- refreshPendingTransfers([tx.id]);
24600
- }, refreshDelayMs);
24601
- refreshTimers.add(timer);
24576
+ const feeQuote = await wallet.getWithdrawalFeeQuote({
24577
+ amountSats: intent.amountSats,
24578
+ withdrawalAddress: intent.destination
24579
+ });
24580
+ return bitcoinPaymentReview(intent, feeQuote);
24581
+ }
24582
+ if (intent.kind === PAYMENT_KIND_LIGHTNING) {
24583
+ let maxFeeSats = intent.maxFeeSats;
24584
+ let fees = maxFeeSats == null ? null : normalizeLightningFeeEstimate(maxFeeSats);
24585
+ if (maxFeeSats == null) {
24586
+ const estimateParams = { encodedInvoice: intent.destination };
24587
+ if (intent.variableAmount && intent.amountSats != null) {
24588
+ estimateParams.amountSats = intent.amountSats;
24602
24589
  }
24603
- markDone(diag, "wallet.send", startedAt, { hasTransfer: !!tx?.id });
24604
- return tx?.id;
24605
- } catch (error) {
24606
- endSdkActivity?.();
24607
- markError(diag, "wallet.send", startedAt, error);
24608
- const message = error instanceof Error ? error.message : String(error);
24609
- throw new Error(`failed to send money: ${message}`, { cause: error });
24590
+ maxFeeSats = await wallet.getLightningSendFeeEstimate(estimateParams);
24591
+ fees = normalizeLightningFeeEstimate(maxFeeSats);
24610
24592
  }
24593
+ return preparedPayment(intent, { maxFeeSats, fees });
24594
+ }
24595
+ return preparedPayment(intent);
24596
+ }
24597
+ function normalizePreparedPayment(paymentInput, network) {
24598
+ const intent = normalizeIntent(paymentInput);
24599
+ if (paymentInput?.state !== PAYMENT_STATE_PREPARED) {
24600
+ throw new Error("prepared payment required");
24601
+ }
24602
+ if (intent.kind !== PAYMENT_KIND_BITCOIN) {
24603
+ return preparedPayment(intent, {
24604
+ fees: paymentInput.fees || null,
24605
+ expiresAt: paymentInput.expiresAt ?? null
24606
+ });
24607
+ }
24608
+ if (!isAddressOnNetwork(intent.destination, network)) {
24609
+ throw new Error(`refusing to pay - address is not a ${network} address`);
24610
+ }
24611
+ const feeQuoteId = cleanText(paymentInput.feeQuoteId);
24612
+ if (!feeQuoteId) {
24613
+ throw new Error("bitcoin payment fee quote missing");
24614
+ }
24615
+ const payment = {
24616
+ ...intent,
24617
+ state: PAYMENT_STATE_PREPARED,
24618
+ feeQuote: paymentInput.feeQuote || null,
24619
+ feeQuoteId,
24620
+ feeAmountSats: toSafeNonNegativeSats(paymentInput.feeAmountSats, "feeAmountSats"),
24621
+ fees: paymentInput.fees || null,
24622
+ expiresAt: paymentInput.expiresAt ?? null
24623
+ };
24624
+ assertBitcoinPaymentReceivesFunds(payment);
24625
+ return Object.freeze(payment);
24626
+ }
24627
+ async function sendBitcoin(wallet, walletPK, network, payment, rememberTransfer) {
24628
+ if (!isAddressOnNetwork(payment.destination, network)) {
24629
+ throw new Error(`refusing to pay - address is not a ${network} address`);
24630
+ }
24631
+ if (!payment.feeQuoteId || payment.feeAmountSats == null) {
24632
+ throw new Error("bitcoin payment review missing");
24633
+ }
24634
+ assertBitcoinPaymentReceivesFunds(payment);
24635
+ const tx = await wallet.withdraw({
24636
+ onchainAddress: payment.destination,
24637
+ amountSats: payment.amountSats,
24638
+ exitSpeed: payment.exitSpeed,
24639
+ feeQuoteId: payment.feeQuoteId,
24640
+ feeAmountSats: payment.feeAmountSats,
24641
+ deductFeeFromWithdrawalAmount: payment.deductFeeFromAmount
24642
+ });
24643
+ const transferId = tx?.transfer?.sparkId || tx?.transfer?.id || null;
24644
+ if (transferId) {
24645
+ const createdTime = tx?.createdAt || new Date().toISOString();
24646
+ await rememberTransfer?.({
24647
+ id: transferId,
24648
+ senderIdentityPublicKey: walletPK,
24649
+ receiverIdentityPublicKey: "",
24650
+ status: "TRANSFER_STATUS_SENDER_INITIATED",
24651
+ totalValue: payment.amountSats,
24652
+ createdTime,
24653
+ updatedTime: tx?.updatedAt || createdTime,
24654
+ type: "COOPERATIVE_EXIT",
24655
+ transferDirection: "OUTGOING"
24656
+ }, {
24657
+ pending: true,
24658
+ bitcoinAddress: payment.destination,
24659
+ bitcoinTxid: tx?.coopExitTxid || null
24660
+ });
24661
+ }
24662
+ return {
24663
+ id: transferId || tx?.id || tx?.coopExitTxid || null,
24664
+ result: tx
24611
24665
  };
24612
- const payExternalInvoice = async ({ type, invoice, amountSats, variableAmount = false } = {}) => {
24666
+ }
24667
+ function createPayment({
24668
+ wallet,
24669
+ walletPK,
24670
+ network,
24671
+ updateWalletData,
24672
+ refreshBalance = null,
24673
+ rememberTransfer,
24674
+ refreshPendingTransfers = null,
24675
+ sentTransferRefreshDelayMs = null,
24676
+ beginSdkActivity = null,
24677
+ diag = null
24678
+ }) {
24679
+ const refreshTimers = new Set;
24680
+ let closed = false;
24681
+ const assertReady = () => {
24613
24682
  if (!wallet || closed) {
24614
24683
  throw new Error("wallet not ready");
24615
24684
  }
24616
- const value = cleanText(invoice);
24617
- if (!value) {
24618
- throw new Error("invoice required");
24685
+ };
24686
+ const preparePayment = async (intent) => {
24687
+ assertReady();
24688
+ return prepare(wallet, network, intent);
24689
+ };
24690
+ const scheduleTransferRefresh = (id) => {
24691
+ const refreshDelayMs = Number(sentTransferRefreshDelayMs);
24692
+ if (closed || !id || typeof refreshPendingTransfers !== "function" || !Number.isFinite(refreshDelayMs) || refreshDelayMs < 0) {
24693
+ return;
24694
+ }
24695
+ markDiag(diag, "wallet.send.refresh.schedule", { delayMs: refreshDelayMs });
24696
+ const timer = setTimeout(() => {
24697
+ refreshTimers.delete(timer);
24698
+ if (closed)
24699
+ return;
24700
+ markDiag(diag, "wallet.send.refresh.start", {});
24701
+ refreshPendingTransfers([id]);
24702
+ }, refreshDelayMs);
24703
+ refreshTimers.add(timer);
24704
+ };
24705
+ const sendPayment = async (paymentInput) => {
24706
+ assertReady();
24707
+ if (paymentInput?.kind === PAYMENT_KIND_BITCOIN && paymentInput?.state !== PAYMENT_STATE_PREPARED) {
24708
+ throw new Error("bitcoin payment must be reviewed before sending");
24619
24709
  }
24710
+ const payment = paymentInput?.state === PAYMENT_STATE_PREPARED ? normalizePreparedPayment(paymentInput, network) : await preparePayment(paymentInput);
24620
24711
  const startedAt = Date.now();
24621
- markDiag(diag, "wallet.externalPay.start", { type });
24622
- if (type === "lightning") {
24623
- try {
24624
- const sendAmountSats = variableAmount ? toSafeSats(amountSats, "amountSatsToSend") : null;
24625
- const estimateParams = {
24626
- encodedInvoice: value,
24627
- ...sendAmountSats != null ? { amountSats: sendAmountSats } : {}
24628
- };
24629
- const feeAmountSats = await wallet.getLightningSendFeeEstimate(estimateParams);
24630
- const fees = normalizeLightningFeeEstimate(feeAmountSats);
24631
- const payment = await wallet.payLightningInvoice({
24632
- invoice: value,
24633
- maxFeeSats: fees.feeAmountSats,
24634
- preferSpark: true,
24635
- ...sendAmountSats != null ? { amountSatsToSend: sendAmountSats } : {}
24712
+ const diagKind = payment.kind;
24713
+ markDiag(diag, "wallet.payment.start", { kind: diagKind });
24714
+ const endSdkActivity = typeof beginSdkActivity === "function" ? beginSdkActivity("payment") : null;
24715
+ try {
24716
+ let outcome;
24717
+ if (payment.kind === PAYMENT_KIND_SPARK) {
24718
+ if (sameText(payment.destination, walletPK)) {
24719
+ throw new Error("cannot send money to the same wallet");
24720
+ }
24721
+ const tx = await wallet.transfer({
24722
+ receiverSparkAddress: walletPKtoSparkAddress(payment.destination, network),
24723
+ amountSats: payment.amountSats
24724
+ });
24725
+ await rememberTransfer?.(tx, { pending: true });
24726
+ await refreshBalance?.();
24727
+ scheduleTransferRefresh(tx?.id);
24728
+ outcome = { id: tx?.id || null, result: tx };
24729
+ } else if (payment.kind === PAYMENT_KIND_LIGHTNING) {
24730
+ const sent = await wallet.payLightningInvoice({
24731
+ invoice: payment.destination,
24732
+ maxFeeSats: payment.maxFeeSats,
24733
+ preferSpark: payment.preferSpark,
24734
+ ...payment.variableAmount && payment.amountSats != null ? { amountSatsToSend: payment.amountSats } : {},
24735
+ ...payment.idempotencyKey ? { idempotencyKey: payment.idempotencyKey } : {}
24636
24736
  });
24637
- const result = normalizeLightningPaymentResult(payment);
24737
+ const result = normalizeLightningPaymentResult(sent);
24638
24738
  if (result?.kind === "spark" && result?.transfer) {
24639
24739
  await rememberTransfer?.(result.transfer, { pending: true });
24640
24740
  } else {
24641
- await rememberTransfer?.(result?.id || payment?.id);
24741
+ await rememberTransfer?.(result?.id || sent?.id);
24642
24742
  await updateWalletData({ reason: "external-lightning-send" });
24643
24743
  }
24644
- markDone(diag, "wallet.externalPay", startedAt, { type, hasTransfer: !!result?.transfer });
24645
- return {
24646
- id: result?.id || payment?.id || null,
24647
- payment,
24648
- result,
24649
- fees
24650
- };
24651
- } catch (error) {
24652
- markError(diag, "wallet.externalPay", startedAt, error, { type });
24653
- throw error;
24654
- }
24655
- }
24656
- if (type === "spark") {
24657
- try {
24658
- const safeAmountSats = amountSats != null ? toSafeSats(amountSats, "amountSats") : null;
24744
+ outcome = { id: result?.id || sent?.id || null, result, raw: sent };
24745
+ } else if (payment.kind === PAYMENT_KIND_SPARK_INVOICE) {
24659
24746
  const result = await wallet.fulfillSparkInvoice([
24660
24747
  {
24661
- invoice: value,
24662
- ...safeAmountSats != null ? { amount: BigInt(safeAmountSats) } : {}
24748
+ invoice: payment.destination,
24749
+ ...payment.amountSats != null ? { amount: BigInt(payment.amountSats) } : {}
24663
24750
  }
24664
24751
  ]);
24665
24752
  const error = firstSparkInvoiceError(result);
24666
- if (error) {
24753
+ if (error)
24667
24754
  throw error;
24668
- }
24669
24755
  const success = firstSparkInvoiceSuccess(result);
24670
- if (!success) {
24756
+ if (!success)
24671
24757
  throw new Error("failed to pay spark invoice");
24672
- }
24673
24758
  const id = success.id || success.txid || null;
24674
24759
  await rememberTransfer?.(success.id ? success : id, { pending: true });
24675
- markDone(diag, "wallet.externalPay", startedAt, { type, hasTransfer: !!id });
24676
- return {
24677
- id,
24678
- result: publicSparkInvoiceResult(success)
24679
- };
24680
- } catch (error) {
24681
- markError(diag, "wallet.externalPay", startedAt, error, { type });
24682
- throw error;
24760
+ outcome = { id, result: publicSparkInvoiceResult(success), raw: result };
24761
+ } else if (payment.kind === PAYMENT_KIND_BITCOIN) {
24762
+ outcome = await sendBitcoin(wallet, walletPK, network, payment, rememberTransfer);
24763
+ await updateWalletData({ reason: "bitcoin-payment" });
24764
+ } else {
24765
+ throw new Error("unsupported payment kind");
24683
24766
  }
24767
+ endSdkActivity?.();
24768
+ markDone(diag, "wallet.payment", startedAt, { kind: diagKind, hasTransfer: !!outcome?.id });
24769
+ return Object.freeze({
24770
+ kind: payment.kind,
24771
+ destination: payment.destination,
24772
+ amountSats: payment.amountSats,
24773
+ id: outcome?.id || null,
24774
+ fees: payment.fees || null,
24775
+ result: outcome?.result || null,
24776
+ raw: outcome?.raw || null
24777
+ });
24778
+ } catch (error) {
24779
+ endSdkActivity?.();
24780
+ markError(diag, "wallet.payment", startedAt, error, { kind: diagKind });
24781
+ const message = error instanceof Error ? error.message : String(error);
24782
+ throw new Error(`failed to send payment: ${message}`, { cause: error });
24684
24783
  }
24685
- throw new Error("unsupported invoice type");
24686
24784
  };
24687
24785
  return {
24688
- sendMoneyWithSpark,
24689
- payExternalInvoice,
24786
+ preparePayment,
24787
+ sendPayment,
24690
24788
  close() {
24691
24789
  closed = true;
24692
- for (const timer of refreshTimers) {
24790
+ for (const timer of refreshTimers)
24693
24791
  clearTimeout(timer);
24694
- }
24695
24792
  refreshTimers.clear();
24696
24793
  }
24697
24794
  };
24698
24795
  }
24699
24796
 
24797
+ // ../../core/wallet/privacy.js
24798
+ var PRIVACY_SYNC_DELAY_MS = WALLET_BOOT_CACHED_REFRESH_DELAY_MS * 2;
24799
+ function createWalletPrivacy({ wallet, ghostWallet, diag }) {
24800
+ let desiredPrivacy = ghostWallet === true;
24801
+ let revision = 0;
24802
+ let closed = false;
24803
+ let privacySync = Promise.resolve();
24804
+ const waits = createOwnedWaits();
24805
+ const setGhostWallet = (nextGhostWallet) => {
24806
+ const nextDesiredPrivacy = nextGhostWallet === true;
24807
+ if (revision > 0 && desiredPrivacy === nextDesiredPrivacy) {
24808
+ return privacySync;
24809
+ }
24810
+ desiredPrivacy = nextDesiredPrivacy;
24811
+ const requestRevision = ++revision;
24812
+ if (!wallet || typeof wallet.setPrivacyEnabled !== "function" || closed) {
24813
+ return privacySync;
24814
+ }
24815
+ privacySync = privacySync.catch(() => {}).then(async () => {
24816
+ await waits.delay(PRIVACY_SYNC_DELAY_MS);
24817
+ if (closed || requestRevision !== revision) {
24818
+ return;
24819
+ }
24820
+ await waits.idle({ timeout: PRIVACY_SYNC_DELAY_MS, delay: PRIVACY_SYNC_DELAY_MS });
24821
+ if (closed || requestRevision !== revision) {
24822
+ return;
24823
+ }
24824
+ const startedAt = Date.now();
24825
+ const desired = desiredPrivacy;
24826
+ markDiag(diag, "wallet.privacy.start", { ghostWallet: desired });
24827
+ await wallet.setPrivacyEnabled(desired);
24828
+ markDone(diag, "wallet.privacy", startedAt, { changed: true });
24829
+ }).catch((error) => {
24830
+ markDiag(diag, "wallet.privacy.error", { code: error?.code || "", message: error?.message || String(error) });
24831
+ });
24832
+ return privacySync;
24833
+ };
24834
+ setGhostWallet(ghostWallet);
24835
+ return {
24836
+ setGhostWallet,
24837
+ close() {
24838
+ if (closed)
24839
+ return;
24840
+ closed = true;
24841
+ revision += 1;
24842
+ waits.close();
24843
+ }
24844
+ };
24845
+ }
24846
+
24700
24847
  // ../../core/wallet/history.js
24701
24848
  function transferPage(page, currentOffset, limit) {
24702
24849
  const transfers = Array.isArray(page?.transfers) ? page.transfers : [];
@@ -24775,7 +24922,7 @@ function compareRecentTransfer(a, b) {
24775
24922
  return String(b?.id || "").localeCompare(String(a?.id || ""));
24776
24923
  }
24777
24924
  function sameTransfer(left, right) {
24778
- return left?.id === right?.id && left?.status === right?.status && txCreatedMs(left) === txCreatedMs(right) && txUpdatedMs(left) === txUpdatedMs(right) && left?.totalValue === right?.totalValue && left?.type === right?.type && left?.transferDirection === right?.transferDirection && left?.senderIdentityPublicKey === right?.senderIdentityPublicKey && left?.receiverIdentityPublicKey === right?.receiverIdentityPublicKey;
24925
+ return left?.id === right?.id && left?.status === right?.status && txCreatedMs(left) === txCreatedMs(right) && txUpdatedMs(left) === txUpdatedMs(right) && left?.totalValue === right?.totalValue && left?.type === right?.type && left?.transferDirection === right?.transferDirection && left?.senderIdentityPublicKey === right?.senderIdentityPublicKey && left?.receiverIdentityPublicKey === right?.receiverIdentityPublicKey && left?.bitcoinAddress === right?.bitcoinAddress && left?.bitcoinTxid === right?.bitcoinTxid;
24779
24926
  }
24780
24927
  function sameTransfers(a = [], b = []) {
24781
24928
  if (a === b) {
@@ -24817,10 +24964,13 @@ function satValue(value) {
24817
24964
  const amount = Number(value);
24818
24965
  return Number.isFinite(amount) ? amount : 0;
24819
24966
  }
24820
- function compactTransfer(tx, { incoming = false } = {}) {
24967
+ function compactTransfer(tx, { incoming = false, bitcoinAddress = null, bitcoinTxid = null } = {}) {
24821
24968
  if (!tx?.id) {
24822
24969
  return null;
24823
24970
  }
24971
+ const isBitcoinPayment = enumName(tx.type, TRANSFER_TYPE_BY_CODE) === "COOPERATIVE_EXIT";
24972
+ const storedBitcoinAddress = String(bitcoinAddress || tx.bitcoinAddress || "").trim() || null;
24973
+ const storedBitcoinTxid = String(bitcoinTxid || tx.bitcoinTxid || (isBitcoinPayment ? tx.userRequest?.coopExitTxid : "") || "").trim() || null;
24824
24974
  return {
24825
24975
  id: tx.id,
24826
24976
  senderIdentityPublicKey: hexKey(tx.senderIdentityPublicKey),
@@ -24830,11 +24980,13 @@ function compactTransfer(tx, { incoming = false } = {}) {
24830
24980
  createdTime: tx.createdTime,
24831
24981
  updatedTime: tx.updatedTime,
24832
24982
  type: enumName(tx.type, TRANSFER_TYPE_BY_CODE),
24833
- transferDirection: tx.transferDirection || (incoming ? "INCOMING" : undefined)
24983
+ transferDirection: tx.transferDirection || (incoming ? "INCOMING" : undefined),
24984
+ ...isBitcoinPayment && storedBitcoinAddress ? { bitcoinAddress: storedBitcoinAddress } : {},
24985
+ ...isBitcoinPayment && storedBitcoinTxid ? { bitcoinTxid: storedBitcoinTxid } : {}
24834
24986
  };
24835
24987
  }
24836
24988
  function compactRememberedTransfer(tx, options = {}) {
24837
- const compact = compactTransfer(tx, { incoming: options?.incoming === true });
24989
+ const compact = compactTransfer(tx, options);
24838
24990
  if (!compact) {
24839
24991
  return null;
24840
24992
  }
@@ -24908,12 +25060,30 @@ function getOldestAnyTransferMs(transfers = []) {
24908
25060
  function shouldReplaceTransfer(current, next) {
24909
25061
  return isPendingTransfer(current) && (!isPendingTransfer(next) || current?.status !== next?.status || txUpdatedMs(next) > txUpdatedMs(current));
24910
25062
  }
25063
+ function mergeTransferDetails(current, next) {
25064
+ if (!current)
25065
+ return next;
25066
+ const base = shouldReplaceTransfer(current, next) ? next : current;
25067
+ const bitcoinAddress = next?.bitcoinAddress || current.bitcoinAddress || null;
25068
+ const bitcoinTxid = next?.bitcoinTxid || current.bitcoinTxid || null;
25069
+ if (base === current && bitcoinAddress === current?.bitcoinAddress && bitcoinTxid === current?.bitcoinTxid) {
25070
+ return current;
25071
+ }
25072
+ if (base === next && bitcoinAddress === next?.bitcoinAddress && bitcoinTxid === next?.bitcoinTxid) {
25073
+ return next;
25074
+ }
25075
+ return {
25076
+ ...base,
25077
+ ...bitcoinAddress ? { bitcoinAddress } : {},
25078
+ ...bitcoinTxid ? { bitcoinTxid } : {}
25079
+ };
25080
+ }
24911
25081
  function indexTransfersById(transfers = []) {
24912
25082
  const byId = new Map;
24913
25083
  for (const tx of Array.isArray(transfers) ? transfers : []) {
24914
25084
  const id = String(tx?.id || "");
24915
25085
  if (id) {
24916
- byId.set(id, tx);
25086
+ byId.set(id, mergeTransferDetails(byId.get(id), tx));
24917
25087
  }
24918
25088
  }
24919
25089
  return byId;
@@ -24925,7 +25095,7 @@ function hasMergeableTransferChanges(transfers = [], transferById = new Map) {
24925
25095
  continue;
24926
25096
  }
24927
25097
  const current = transferById.get(id);
24928
- if (!current || shouldReplaceTransfer(current, tx)) {
25098
+ if (!current || mergeTransferDetails(current, tx) !== current) {
24929
25099
  return true;
24930
25100
  }
24931
25101
  }
@@ -24942,8 +25112,9 @@ function dedupeSortedTransfers(transfers = []) {
24942
25112
  continue;
24943
25113
  }
24944
25114
  const current = byId.get(id);
24945
- if (!current || shouldReplaceTransfer(current, tx)) {
24946
- byId.set(id, tx);
25115
+ const merged = mergeTransferDetails(current, tx);
25116
+ if (!current || merged !== current) {
25117
+ byId.set(id, merged);
24947
25118
  }
24948
25119
  }
24949
25120
  return sortRecentTransfers([...byId.values()]);
@@ -25011,11 +25182,14 @@ function mergeCompactedTransferPage(current = [], pageTransfers = [], position =
25011
25182
  const updatedCurrent = replacements.size ? current.map((tx) => {
25012
25183
  const id = String(tx?.id || "");
25013
25184
  const replacement = id ? replacements.get(id) : null;
25014
- if (!replacement || !shouldReplaceTransfer(tx, replacement)) {
25185
+ if (!replacement) {
25015
25186
  return tx;
25016
25187
  }
25188
+ const merged = mergeTransferDetails(tx, replacement);
25189
+ if (merged === tx)
25190
+ return tx;
25017
25191
  changed = true;
25018
- return replacement;
25192
+ return merged;
25019
25193
  }) : current;
25020
25194
  if (!newItems.length) {
25021
25195
  return changed ? updatedCurrent : current;
@@ -25038,7 +25212,8 @@ function mergeTransferPageForWallet(currentTransfers = [], pageTransfers = [], w
25038
25212
  return mergeCompactedTransferPage(current, page, position);
25039
25213
  }
25040
25214
  function mergeRecentSnapshotForWallet(currentTransfers = [], latestTransfers = [], walletPK) {
25041
- const latest = mergeTransferPageForWallet([], latestTransfers, walletPK, "append");
25215
+ const currentById = new Map(currentTransfers.map((tx) => [String(tx?.id || ""), tx]));
25216
+ const latest = mergeTransferPageForWallet([], latestTransfers, walletPK, "append").map((tx) => mergeTransferDetails(currentById.get(String(tx?.id || "")), tx));
25042
25217
  if (!latest.length) {
25043
25218
  return filterTransfersForWallet(currentTransfers, walletPK);
25044
25219
  }
@@ -25167,7 +25342,7 @@ function pendingReconcileAgeMs(tx, now = Date.now(), firstSeenAt = null) {
25167
25342
  return baseMs ? Math.max(0, now - baseMs) : null;
25168
25343
  }
25169
25344
  function getPendingTransferRetryMs(tx, ageMs, unresolvedCount = 0) {
25170
- if (isWithdrawalTransfer(tx)) {
25345
+ if (isBitcoinPaymentTransfer(tx)) {
25171
25346
  if (!Number.isFinite(ageMs) || ageMs <= PENDING_TRANSFER_WARM_AGE_MS) {
25172
25347
  return PENDING_TRANSFER_WARM_RETRY_MS;
25173
25348
  }
@@ -27138,206 +27313,6 @@ function createWalletTransferSession({ wallet, walletPK, localCache, claimIncomi
27138
27313
  };
27139
27314
  }
27140
27315
 
27141
- // ../../core/wallet/withdrawops.js
27142
- var P2PKH_DUST_SATS = 546;
27143
- var P2SH_DUST_SATS = 540;
27144
- var P2WPKH_DUST_SATS = 294;
27145
- var SEGWIT_SCRIPT_DUST_SATS = 330;
27146
- function getWithdrawalMinimumReceiveSats(onchainAddress) {
27147
- const address = cleanText(onchainAddress).toLowerCase();
27148
- if (address.startsWith("1"))
27149
- return P2PKH_DUST_SATS;
27150
- if (address.startsWith("3"))
27151
- return P2SH_DUST_SATS;
27152
- const p2wpkhLength = address.startsWith("bcrt1q") ? 44 : 42;
27153
- if ((address.startsWith("bc1q") || address.startsWith("bcrt1q")) && address.length === p2wpkhLength) {
27154
- return P2WPKH_DUST_SATS;
27155
- }
27156
- return SEGWIT_SCRIPT_DUST_SATS;
27157
- }
27158
- function getWithdrawalReviewAmounts(withdrawal) {
27159
- const amountSats = toSafeSats(withdrawal?.amountSats);
27160
- const feeAmountSats = toSafeNonNegativeSats(withdrawal?.feeAmountSats ?? 0, "feeAmountSats");
27161
- const deductFeeFromWithdrawalAmount = withdrawal?.deductFeeFromWithdrawalAmount !== false;
27162
- const receiveAmountSats = deductFeeFromWithdrawalAmount ? Math.max(0, amountSats - feeAmountSats) : amountSats;
27163
- const sendAmountSats = deductFeeFromWithdrawalAmount ? amountSats : amountSats + feeAmountSats;
27164
- return {
27165
- sendAmountSats,
27166
- receiveAmountSats,
27167
- feeAmountSats
27168
- };
27169
- }
27170
- function assertWithdrawalReceivesFunds(withdrawal) {
27171
- const { receiveAmountSats } = getWithdrawalReviewAmounts(withdrawal);
27172
- const minimumReceiveAmountSats = getWithdrawalMinimumReceiveSats(withdrawal?.onchainAddress);
27173
- if (receiveAmountSats < minimumReceiveAmountSats) {
27174
- throw new Error(`withdrawal would create a dust output below ${minimumReceiveAmountSats} sats`);
27175
- }
27176
- }
27177
- function getWithdrawalReview({ feeQuote, exitSpeed, amountSats, onchainAddress, deductFeeFromWithdrawalAmount = true }) {
27178
- const safeExitSpeed = getExitSpeed(exitSpeed);
27179
- const feeQuoteId = feeQuote?.id ?? null;
27180
- const feeAmountSats = getWithdrawalFeeAmountSats(feeQuote, safeExitSpeed);
27181
- if (!feeQuoteId || feeAmountSats == null) {
27182
- throw new Error("withdrawal fee quote unavailable");
27183
- }
27184
- const sparkFees = normalizeWithdrawalFeeQuote(feeQuote);
27185
- const withdrawal = {
27186
- kind: "cooperative_exit",
27187
- onchainAddress,
27188
- amountSats,
27189
- exitSpeed: safeExitSpeed,
27190
- deductFeeFromWithdrawalAmount,
27191
- feeQuote,
27192
- feeQuoteId,
27193
- feeAmountSats,
27194
- fees: {
27195
- spark: sparkFees
27196
- },
27197
- sparkFees,
27198
- expiresAt: sparkFees?.expiresAt ?? feeQuote.expiresAt ?? null
27199
- };
27200
- assertWithdrawalReceivesFunds(withdrawal);
27201
- return withdrawal;
27202
- }
27203
- async function quoteWithdrawalFees(wallet, network, { onchainAddress, amountSats } = {}) {
27204
- if (!wallet) {
27205
- return { success: false, error: new Error("wallet not ready") };
27206
- }
27207
- const address = cleanText(onchainAddress);
27208
- if (!isAddressOnNetwork(address, network)) {
27209
- return { success: false, error: new Error(`refusing to withdraw - address is not a ${network} address`) };
27210
- }
27211
- try {
27212
- const safeAmountSats = toSafeSats(amountSats);
27213
- const feeQuote = await wallet.getWithdrawalFeeQuote({
27214
- amountSats: safeAmountSats,
27215
- withdrawalAddress: address
27216
- });
27217
- if (!feeQuote?.id) {
27218
- throw new Error("withdrawal fee quote unavailable");
27219
- }
27220
- const sparkFees = normalizeWithdrawalFeeQuote(feeQuote);
27221
- return {
27222
- success: true,
27223
- feeQuote,
27224
- fees: {
27225
- spark: sparkFees
27226
- },
27227
- sparkFees,
27228
- amountSats: safeAmountSats,
27229
- onchainAddress: address
27230
- };
27231
- } catch (error) {
27232
- return { success: false, error };
27233
- }
27234
- }
27235
- async function prepareWithdrawal(wallet, network, { onchainAddress, amountSats, exitSpeed = DEFAULT_EXIT_SPEED, deductFeeFromWithdrawalAmount = true } = {}) {
27236
- const quoted = await quoteWithdrawalFees(wallet, network, { onchainAddress, amountSats });
27237
- if (!quoted.success) {
27238
- return quoted;
27239
- }
27240
- try {
27241
- const withdrawal = getWithdrawalReview({
27242
- feeQuote: quoted.feeQuote,
27243
- exitSpeed,
27244
- amountSats: quoted.amountSats,
27245
- onchainAddress: quoted.onchainAddress,
27246
- deductFeeFromWithdrawalAmount
27247
- });
27248
- return {
27249
- success: true,
27250
- withdrawal,
27251
- ...withdrawal
27252
- };
27253
- } catch (error) {
27254
- return { success: false, error };
27255
- }
27256
- }
27257
- async function withdrawFunds(wallet, network, { onchainAddress, amountSats, exitSpeed = DEFAULT_EXIT_SPEED, feeQuote = null, feeQuoteId = null, feeAmountSats = null, deductFeeFromWithdrawalAmount = true } = {}) {
27258
- if (!wallet) {
27259
- return { success: false, error: new Error("wallet not ready") };
27260
- }
27261
- const address = cleanText(onchainAddress);
27262
- if (!isAddressOnNetwork(address, network)) {
27263
- return { success: false, error: new Error(`refusing to withdraw - address is not a ${network} address`) };
27264
- }
27265
- try {
27266
- const safeAmountSats = toSafeSats(amountSats);
27267
- const safeExitSpeed = getExitSpeed(exitSpeed);
27268
- let readyFeeQuote = feeQuote;
27269
- if (!readyFeeQuote && (!feeQuoteId || feeAmountSats == null)) {
27270
- const quoted = await quoteWithdrawalFees(wallet, network, {
27271
- onchainAddress: address,
27272
- amountSats: safeAmountSats
27273
- });
27274
- if (!quoted.success) {
27275
- return quoted;
27276
- }
27277
- readyFeeQuote = quoted.feeQuote;
27278
- }
27279
- const readyFeeQuoteId = feeQuoteId || readyFeeQuote?.id;
27280
- const readyFeeAmountSats = feeAmountSats == null ? getWithdrawalFeeAmountSats(readyFeeQuote, safeExitSpeed) : toSafeNonNegativeSats(feeAmountSats, "feeAmountSats");
27281
- if (!readyFeeQuoteId || readyFeeAmountSats == null) {
27282
- throw new Error("withdrawal fee quote unavailable");
27283
- }
27284
- assertWithdrawalReceivesFunds({
27285
- onchainAddress: address,
27286
- amountSats: safeAmountSats,
27287
- feeAmountSats: readyFeeAmountSats,
27288
- deductFeeFromWithdrawalAmount
27289
- });
27290
- const tx = await wallet.withdraw({
27291
- onchainAddress: address,
27292
- amountSats: safeAmountSats,
27293
- exitSpeed: safeExitSpeed,
27294
- feeQuoteId: readyFeeQuoteId,
27295
- feeAmountSats: readyFeeAmountSats,
27296
- deductFeeFromWithdrawalAmount
27297
- });
27298
- return {
27299
- success: true,
27300
- tx,
27301
- feeQuote: readyFeeQuote,
27302
- fees: readyFeeQuote ? {
27303
- spark: normalizeWithdrawalFeeQuote(readyFeeQuote)
27304
- } : null,
27305
- feeAmountSats: readyFeeAmountSats
27306
- };
27307
- } catch (error) {
27308
- return { success: false, error };
27309
- }
27310
- }
27311
- async function confirmWithdrawal(wallet, network, withdrawal) {
27312
- if (!withdrawal) {
27313
- return { success: false, error: new Error("withdrawal review missing") };
27314
- }
27315
- return withdrawFunds(wallet, network, {
27316
- onchainAddress: withdrawal.onchainAddress,
27317
- amountSats: withdrawal.amountSats,
27318
- exitSpeed: withdrawal.exitSpeed,
27319
- feeQuoteId: withdrawal.feeQuoteId,
27320
- feeAmountSats: withdrawal.feeAmountSats,
27321
- deductFeeFromWithdrawalAmount: withdrawal.deductFeeFromWithdrawalAmount
27322
- });
27323
- }
27324
-
27325
- // ../../core/wallet/withdraw.js
27326
- function createWithdrawal({ wallet, network, updateWalletData }) {
27327
- const refreshOnSuccess = async (result) => {
27328
- if (result.success) {
27329
- await updateWalletData({ reason: "withdraw" });
27330
- }
27331
- return result;
27332
- };
27333
- return {
27334
- quoteWithdrawalFees: (params) => quoteWithdrawalFees(wallet, network, params),
27335
- prepareWithdrawal: (params) => prepareWithdrawal(wallet, network, params),
27336
- confirmWithdrawal: async (withdrawal) => refreshOnSuccess(await confirmWithdrawal(wallet, network, withdrawal)),
27337
- withdrawFunds: async (params) => refreshOnSuccess(await withdrawFunds(wallet, network, params))
27338
- };
27339
- }
27340
-
27341
27316
  // ../../core/wallet/session.js
27342
27317
  var NOOP5 = () => {};
27343
27318
  var ASYNC_NOOP = async () => null;
@@ -27396,18 +27371,12 @@ function createEmptyWalletSessionSnapshot(network, transferSnapshot = null, cach
27396
27371
  requestTransferDiscoveryHotWindow: NOOP5,
27397
27372
  claimDeposits: ASYNC_FALSE,
27398
27373
  getFundingAddress: ASYNC_NOOP,
27399
- sendMoneyWithSpark: WALLET_NOT_READY,
27400
- payExternalInvoice: WALLET_NOT_READY,
27374
+ preparePayment: WALLET_NOT_READY,
27375
+ sendPayment: WALLET_NOT_READY,
27401
27376
  createLightningInvoice: WALLET_NOT_READY,
27402
- quoteLightningFees: WALLET_NOT_READY,
27403
- sendLightningPayment: WALLET_NOT_READY,
27404
27377
  getLightningReceiveRequest: WALLET_NOT_READY,
27405
27378
  getLightningSendRequest: WALLET_NOT_READY,
27406
- quoteWithdrawalFees: WALLET_NOT_READY,
27407
- prepareWithdrawal: WALLET_NOT_READY,
27408
- confirmWithdrawal: WALLET_NOT_READY,
27409
- withdrawFunds: WALLET_NOT_READY,
27410
- runWalletMutation: WALLET_NOT_READY
27379
+ runPayment: WALLET_NOT_READY
27411
27380
  },
27412
27381
  txValue: {
27413
27382
  oldestTxMs: null,
@@ -27538,8 +27507,9 @@ function createWalletSession({
27538
27507
  diag
27539
27508
  });
27540
27509
  const transferState = getTransferState();
27541
- const send = createWalletSend({
27510
+ const payment = createPayment({
27542
27511
  wallet,
27512
+ walletPK,
27543
27513
  network,
27544
27514
  updateWalletData,
27545
27515
  refreshBalance: balance.getBalance,
@@ -27549,28 +27519,15 @@ function createWalletSession({
27549
27519
  beginSdkActivity: transferState.beginSdkActivity,
27550
27520
  diag
27551
27521
  });
27552
- const lightning = createLightning({ wallet, updateWalletData });
27553
- const withdrawal = createWithdrawal({ wallet, network, updateWalletData });
27522
+ const lightning = createLightning({ wallet });
27554
27523
  const privacy = createWalletPrivacy({ wallet, ghostWallet, diag });
27555
27524
  const mutations = createWalletMutationQueue();
27556
- const sendMoneyWithSpark = (receiverWalletPK, ...args) => {
27557
- if (sameText(receiverWalletPK, walletPK)) {
27558
- throw new Error("cannot send money to the same wallet");
27559
- }
27560
- return send.sendMoneyWithSpark(receiverWalletPK, ...args);
27561
- };
27562
27525
  const mutationActions = {
27563
- sendMoneyWithSpark: (...args) => mutations.run(() => sendMoneyWithSpark(...args)),
27564
- payExternalInvoice: (...args) => mutations.run(() => send.payExternalInvoice(...args)),
27565
- sendLightningPayment: (...args) => mutations.run(() => lightning.sendLightningPayment(...args)),
27566
- confirmWithdrawal: (...args) => mutations.run(() => withdrawal.confirmWithdrawal(...args)),
27567
- withdrawFunds: (...args) => mutations.run(() => withdrawal.withdrawFunds(...args)),
27568
- runWalletMutation: (task) => mutations.run(() => task({
27569
- sendMoneyWithSpark,
27570
- payExternalInvoice: send.payExternalInvoice,
27571
- sendLightningPayment: lightning.sendLightningPayment,
27572
- confirmWithdrawal: withdrawal.confirmWithdrawal,
27573
- withdrawFunds: withdrawal.withdrawFunds
27526
+ preparePayment: (...args) => mutations.run(() => payment.preparePayment(...args)),
27527
+ sendPayment: (...args) => mutations.run(() => payment.sendPayment(...args)),
27528
+ runPayment: (task) => mutations.run(() => task({
27529
+ preparePayment: payment.preparePayment,
27530
+ sendPayment: payment.sendPayment
27574
27531
  }))
27575
27532
  };
27576
27533
  function buildSnapshot() {
@@ -27592,18 +27549,12 @@ function createWalletSession({
27592
27549
  requestTransferDiscoveryHotWindow: polling.requestTransferDiscoveryHotWindow,
27593
27550
  claimDeposits: claims.claimDeposits,
27594
27551
  getFundingAddress: funding.getFundingAddress,
27595
- sendMoneyWithSpark: mutationActions.sendMoneyWithSpark,
27596
- payExternalInvoice: mutationActions.payExternalInvoice,
27552
+ preparePayment: mutationActions.preparePayment,
27553
+ sendPayment: mutationActions.sendPayment,
27597
27554
  createLightningInvoice: lightning.createLightningInvoice,
27598
- quoteLightningFees: lightning.quoteLightningFees,
27599
- sendLightningPayment: mutationActions.sendLightningPayment,
27600
27555
  getLightningReceiveRequest: lightning.getLightningReceiveRequest,
27601
27556
  getLightningSendRequest: lightning.getLightningSendRequest,
27602
- quoteWithdrawalFees: withdrawal.quoteWithdrawalFees,
27603
- prepareWithdrawal: withdrawal.prepareWithdrawal,
27604
- confirmWithdrawal: mutationActions.confirmWithdrawal,
27605
- withdrawFunds: mutationActions.withdrawFunds,
27606
- runWalletMutation: mutationActions.runWalletMutation
27557
+ runPayment: mutationActions.runPayment
27607
27558
  };
27608
27559
  const txValue = {
27609
27560
  oldestTxMs: currentTransferState.oldestLoadedMs,
@@ -27666,7 +27617,7 @@ function createWalletSession({
27666
27617
  polling.close();
27667
27618
  privacy.close();
27668
27619
  mutations.close();
27669
- send.close();
27620
+ payment.close();
27670
27621
  claims.close();
27671
27622
  funding.close();
27672
27623
  updateWalletData.close();
@@ -28009,7 +27960,7 @@ function coveredUnitsSince(oldestLoadedMs, unitMs, nowMs2 = Date.now()) {
28009
27960
  }
28010
27961
  var enrichTx = (tx) => {
28011
27962
  const incoming = tx.transferDirection === "INCOMING";
28012
- const isWithdrawal = isWithdrawalTransfer(tx);
27963
+ const isBitcoinPayment = isBitcoinPaymentTransfer(tx);
28013
27964
  const isFunding = isFundingTransfer(tx);
28014
27965
  const pending = !isCompletedTransfer(tx);
28015
27966
  const peerPK = incoming ? tx.senderIdentityPublicKey : tx.receiverIdentityPublicKey;
@@ -28021,10 +27972,10 @@ var enrichTx = (tx) => {
28021
27972
  totalValue: tx.totalValue,
28022
27973
  amount: incoming ? tx.totalValue : -tx.totalValue,
28023
27974
  funding: isFunding,
28024
- withdrawal: isWithdrawal,
27975
+ bitcoin: isBitcoinPayment,
28025
27976
  pending,
28026
27977
  pendingCredit: pending && (incoming || isFunding),
28027
- summaryPending: pending && (incoming || isFunding || isWithdrawal)
27978
+ summaryPending: pending && (incoming || isFunding || isBitcoinPayment)
28028
27979
  };
28029
27980
  };
28030
27981
  var aggregateTxs = (transfers, userPK) => {
@@ -28057,7 +28008,7 @@ var aggregateTxs = (transfers, userPK) => {
28057
28008
  }
28058
28009
  if (!firstDate || txDate < firstDate)
28059
28010
  firstDate = txDate;
28060
- if (tx.peerPK && tx.peerPK !== userPK && !tx.funding && !tx.withdrawal) {
28011
+ if (tx.peerPK && tx.peerPK !== userPK && !tx.funding && !tx.bitcoin) {
28061
28012
  const txMs = txDate.getTime();
28062
28013
  if (!peerMap.has(tx.peerPK)) {
28063
28014
  peerMap.set(tx.peerPK, {
@@ -28164,7 +28115,9 @@ function txSearchFields(tx) {
28164
28115
  tx?.amount == null ? "" : String(tx.amount),
28165
28116
  tx?.incoming ? "incoming received inflow" : "outgoing sent outflow",
28166
28117
  tx?.funding ? "funded fund deposit" : "",
28167
- tx?.withdrawal ? "withdrawn withdraw" : "",
28118
+ tx?.bitcoin ? "bitcoin payment onchain on-chain l1" : "",
28119
+ tx?.bitcoinAddress,
28120
+ tx?.bitcoinTxid,
28168
28121
  tx?.pending ? "pending" : "completed"
28169
28122
  ];
28170
28123
  }
@@ -28380,7 +28333,7 @@ function getRecentWalletPeers(transfers, walletPK) {
28380
28333
  continue;
28381
28334
  }
28382
28335
  const tx = enrichTx(raw);
28383
- if (!isVisibleTransfer(tx) || tx.funding || tx.withdrawal || !tx.peerPK || tx.peerPK === walletPK) {
28336
+ if (!isVisibleTransfer(tx) || tx.funding || tx.bitcoin || !tx.peerPK || tx.peerPK === walletPK) {
28384
28337
  continue;
28385
28338
  }
28386
28339
  const txMs = tx.createdMs || 0;
@@ -28419,7 +28372,7 @@ function getPeerDataFromTransfers(transfers, walletPK, peerPK) {
28419
28372
  if (rawPeerPK !== peerPK)
28420
28373
  continue;
28421
28374
  const tx = enrichTx(raw);
28422
- if (tx.funding || tx.withdrawal) {
28375
+ if (tx.funding || tx.bitcoin) {
28423
28376
  continue;
28424
28377
  }
28425
28378
  txs.push(tx);