@glyphteck/veyl 0.66.0 → 0.66.2

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
@@ -5995,9 +5995,6 @@ var BAN_REFRESH_GRACE_MS = 50;
5995
5995
  var REQUEST_MONEY_MAX_SATS = SATS_PER_BITCOIN * 100000n;
5996
5996
  var WALLET_TRANSFER_POLL_MS = 3 * MS_PER_SECOND;
5997
5997
  var WALLET_ACTIVE_TRANSFER_REFRESH_MS = MS_PER_SECOND;
5998
- var WALLET_IDLE_ACTIVE_TRANSFER_REFRESH_MS = 5 * MS_PER_SECOND;
5999
- var WALLET_VISIBLE_TRANSFER_DISCOVERY_WINDOW_MS = 12 * MS_PER_SECOND;
6000
- var WALLET_ACTIVE_TRANSFER_EMPTY_SCAN_LIMIT = 8;
6001
5998
  var WALLET_CACHE_HYDRATE_DELAY_MS = 0;
6002
5999
  var WALLET_BOOT_REFRESH_DELAY_MS = 500;
6003
6000
  var WALLET_BOOT_CACHED_REFRESH_DELAY_MS = 2500;
@@ -11679,12 +11676,16 @@ function projectRequestPayment(requestValue, paymentValue) {
11679
11676
  if (!requester || !payer || requester === payer || requestNetwork(requestValue) !== requestNetwork(paymentValue)) {
11680
11677
  return requestValue;
11681
11678
  }
11682
- const payments = normalizedPayments(requestValue);
11679
+ const progress = getRequestProgress(requestValue);
11680
+ const amount = positiveSats(paymentValue.a);
11681
+ if (progress.paid !== 0n || amount !== progress.requested) {
11682
+ return requestValue;
11683
+ }
11684
+ const payments = progress.payments;
11683
11685
  const tx = cleanText(paymentValue.tx);
11684
11686
  if (payments.some((payment) => payment.tx === tx)) {
11685
11687
  return requestValue;
11686
11688
  }
11687
- const amount = positiveSats(paymentValue.a);
11688
11689
  return {
11689
11690
  ...requestValue,
11690
11691
  payments: [...payments, {
@@ -11695,6 +11696,20 @@ function projectRequestPayment(requestValue, paymentValue) {
11695
11696
  }]
11696
11697
  };
11697
11698
  }
11699
+ function getRequestProgress(message) {
11700
+ const requested = positiveSats(message?.a) ?? 0n;
11701
+ const payments = normalizedPayments(message);
11702
+ const paid = payments.reduce((sum, payment) => sum + BigInt(payment.a), 0n);
11703
+ const remaining = paid >= requested ? 0n : requested - paid;
11704
+ return {
11705
+ requested,
11706
+ paid,
11707
+ remaining,
11708
+ fulfilled: requested > 0n && remaining === 0n,
11709
+ payments,
11710
+ lastPayment: payments[payments.length - 1] || null
11711
+ };
11712
+ }
11698
11713
 
11699
11714
  // ../../core/chat/messages/control.js
11700
11715
  var sourceGoneVisibleMessageCache = new WeakMap;
@@ -12058,7 +12073,7 @@ function applyMessageActions(messages) {
12058
12073
  const index2 = target ? indexByKey.get(target) : null;
12059
12074
  const base = index2 != null ? out[index2] : null;
12060
12075
  const actionMembers = [...new Set((Array.isArray(msg?.epochMemberChatPKs) ? msg.epochMemberChatPKs : []).map(cleanText).filter(Boolean))];
12061
- const authorized = base?.t === "req" && isRequestPayment(msg) && actionMembers.includes(cleanText(base.s)) && actionMembers.includes(cleanText(msg.s));
12076
+ const authorized = base?.t === "req" && isRequestPayment(msg) && msg?.failed !== true && actionMembers.includes(cleanText(base.s)) && actionMembers.includes(cleanText(msg.s));
12062
12077
  if (authorized) {
12063
12078
  const next = projectRequestPayment(base, msg);
12064
12079
  const projected = isHeldSourceGoneMsg(base) ? holdSourceGoneVisibleMsg(next) : next;
@@ -18073,7 +18088,19 @@ ${cid}` : "";
18073
18088
  if (!chat || !options?.epochState || !options?.ownEntry)
18074
18089
  throw makeChatUnavailableError();
18075
18090
  const chatId = chat.chatId;
18076
- const { cid, local } = makeLocalMessage(chatId, chatPK, peerChatPK, message);
18091
+ const epochManifest = options.epochState?.manifest;
18092
+ const actionOp = cleanText(options.actionOp);
18093
+ const actionTarget3 = cleanText(options.actionTarget);
18094
+ const localMessage = {
18095
+ ...message,
18096
+ ...actionOp ? { actionOp } : {},
18097
+ ...actionTarget3 ? { actionTarget: actionTarget3 } : {},
18098
+ ...epochManifest?.epochId ? { epochId: epochManifest.epochId } : {},
18099
+ ...Array.isArray(epochManifest?.members) ? {
18100
+ epochMemberChatPKs: epochManifest.members.map((member) => cleanText(member?.chatPK)).filter(Boolean)
18101
+ } : {}
18102
+ };
18103
+ const { cid, local } = makeLocalMessage(chatId, chatPK, peerChatPK, localMessage);
18077
18104
  selectLocalChat?.(peerChatPK, chatId);
18078
18105
  if (hasSentLocalCid(chatId, cid)) {
18079
18106
  local.pending = false;
@@ -28474,6 +28501,8 @@ function createChatSave({ cloud, media = {}, chatBanned, localCache, getOwnerCha
28474
28501
  try {
28475
28502
  const targetEpochId = list[0]?.epochId || mutationOptions(chatId).epochState.manifest.epochId;
28476
28503
  const updated = await makeMsgPermanent(cloud, targetEpochId, list, mutationOptions(chatId));
28504
+ if (updated !== list.length)
28505
+ throw makeMessageSaveUnavailableError();
28477
28506
  return { updated, ttl: null };
28478
28507
  } catch (error) {
28479
28508
  throw normalizeMessageSaveError(error);
@@ -29796,7 +29825,20 @@ function createChatSession({
29796
29825
  const target = typeof request === "string" ? request.trim() : messageRef(request);
29797
29826
  if (!target)
29798
29827
  throw new Error("payment request target required");
29799
- return pendingOwner.sendChatMessage(chatId, makeRequestPayment(payment.amountSats, payment.tx, payment.network), {
29828
+ const batch = messageBatchOwner.getMessageBatch(chatId);
29829
+ const requestMessage = request && typeof request === "object" ? request : [...batch?.messages || [], ...batch?.sourceMessages || []].find((message) => message?.t === "req" && messageRef(message) === target);
29830
+ if (!requestMessage || requestMessage.t !== "req")
29831
+ throw new Error("payment request not found");
29832
+ if (cleanText(requestMessage.s || requestMessage.from) === chatPK)
29833
+ throw new Error("cannot pay your own request");
29834
+ const requestProgress = getRequestProgress(requestMessage);
29835
+ if (requestProgress.fulfilled || requestProgress.paid !== 0n)
29836
+ throw new Error("payment request already paid");
29837
+ const confirmation = makeRequestPayment(payment.amountSats, payment.tx, payment.network);
29838
+ if (requestNetwork(requestMessage) !== requestNetwork(confirmation) || BigInt(confirmation.a) !== requestProgress.requested) {
29839
+ throw new Error("payment must fulfill the request");
29840
+ }
29841
+ return pendingOwner.sendChatMessage(chatId, confirmation, {
29800
29842
  actionOp: CHAT_ACTION_OPS.PAY_CONFIRM,
29801
29843
  actionTarget: target,
29802
29844
  updatePreview: true
@@ -33472,9 +33514,18 @@ function createPeerList({ peerApi, diag, onMissingPeers }) {
33472
33514
  return subscriberCount > 0;
33473
33515
  }
33474
33516
  function beginSubscription() {
33475
- if (!subscriberCount)
33517
+ const firstSubscriber = !subscriberCount;
33518
+ if (firstSubscriber)
33476
33519
  lifecycle += 1;
33477
33520
  subscriberCount += 1;
33521
+ if (!firstSubscriber)
33522
+ return;
33523
+ const becameReady = startProfileLoad();
33524
+ if (becameReady) {
33525
+ rebuild({ base: true });
33526
+ } else {
33527
+ scheduleRefresh();
33528
+ }
33478
33529
  }
33479
33530
  function endSubscription() {
33480
33531
  subscriberCount = Math.max(0, subscriberCount - 1);
@@ -36150,8 +36201,6 @@ function createLightning({ wallet }) {
36150
36201
  // ../../core/wallet/lifecycle.js
36151
36202
  var POLL_TXS_RATE = WALLET_TRANSFER_POLL_MS;
36152
36203
  var ACTIVE_TRANSFER_REFRESH_RATE = WALLET_ACTIVE_TRANSFER_REFRESH_MS;
36153
- var IDLE_ACTIVE_TRANSFER_REFRESH_RATE = WALLET_IDLE_ACTIVE_TRANSFER_REFRESH_MS;
36154
- var ACTIVE_TRANSFER_EMPTY_SCAN_LIMIT = WALLET_ACTIVE_TRANSFER_EMPTY_SCAN_LIMIT;
36155
36204
  var BOOT_REFRESH_DELAY_MS = WALLET_BOOT_REFRESH_DELAY_MS;
36156
36205
  var BOOT_CACHED_REFRESH_DELAY_MS = WALLET_BOOT_CACHED_REFRESH_DELAY_MS;
36157
36206
  var BOOT_CACHE_DECISION_DELAY_MS = BOOT_REFRESH_DELAY_MS + Math.max(0, WALLET_CACHE_HYDRATE_DELAY_MS) + 250;
@@ -36376,23 +36425,18 @@ function createWalletPolling({ wallet, network, appState, getTransferState, getB
36376
36425
  let activeRefreshPromise = null;
36377
36426
  let pendingPollPromise = null;
36378
36427
  let activeRefreshLastAt = 0;
36379
- let activeRefreshEmptyScanCount = 0;
36380
- let activeTransferHotUntilMs = 0;
36428
+ let transferDiscoveryVisible = false;
36381
36429
  let closed = false;
36382
36430
  const depositClaimRate = getDepositClaimPollMs(network);
36383
36431
  const activeRefreshPollMs = Math.max(500, Number(activeTransferRefreshMs) || ACTIVE_TRANSFER_REFRESH_RATE);
36384
- const activeRefreshIdlePollMs = Math.max(activeRefreshPollMs, Number(IDLE_ACTIVE_TRANSFER_REFRESH_RATE) || activeRefreshPollMs);
36385
- const activeRefreshEmptyScanLimit = Math.max(1, Number(ACTIVE_TRANSFER_EMPTY_SCAN_LIMIT) || 1);
36386
36432
  const isActive = () => !appState?.currentState || appState.currentState === "active";
36387
36433
  const isTxReady = () => getTransferState().txReady === true && getBalanceState().balanceReady === true;
36388
36434
  const hasActivePendingClaim = () => getTransferState().hasActivePendingClaim?.() === true;
36389
- const hasFastActiveRefreshWork = () => activeTransferHotUntilMs > Date.now() || hasActivePendingClaim();
36435
+ const hasFastActiveRefreshWork = () => transferDiscoveryVisible || hasActivePendingClaim();
36390
36436
  const activeRefreshDue = () => {
36391
- if (hasActivePendingClaim()) {
36392
- return true;
36393
- }
36394
- const delayMs = hasFastActiveRefreshWork() || activeRefreshEmptyScanCount < activeRefreshEmptyScanLimit ? activeRefreshPollMs : activeRefreshIdlePollMs;
36395
- return !activeRefreshLastAt || Date.now() - activeRefreshLastAt >= delayMs;
36437
+ if (!hasFastActiveRefreshWork())
36438
+ return false;
36439
+ return hasActivePendingClaim() || !activeRefreshLastAt || Date.now() - activeRefreshLastAt >= activeRefreshPollMs;
36396
36440
  };
36397
36441
  const runActiveRefresh = (reason = "active-poll") => {
36398
36442
  if (closed || !wallet || !isActive()) {
@@ -36405,16 +36449,8 @@ function createWalletPolling({ wallet, network, appState, getTransferState, getB
36405
36449
  activeRefreshLastAt = Date.now();
36406
36450
  const transferState = getTransferState();
36407
36451
  const transfers = typeof transferState.claimPendingIncomingTransfers === "function" ? await transferState.claimPendingIncomingTransfers(reason) : [];
36408
- if (Array.isArray(transfers) && transfers.length) {
36409
- activeRefreshEmptyScanCount = 0;
36410
- } else if (hasActivePendingClaim()) {
36411
- activeRefreshEmptyScanCount = 0;
36412
- } else {
36413
- activeRefreshEmptyScanCount += 1;
36414
- }
36415
- const visibleHot = activeTransferHotUntilMs > Date.now();
36416
36452
  const claimActive = hasActivePendingClaim();
36417
- if (isTxReady() && typeof transferState.refreshPendingTransfers === "function" && !visibleHot && !claimActive) {
36453
+ if (isTxReady() && typeof transferState.refreshPendingTransfers === "function" && !transferDiscoveryVisible && !claimActive) {
36418
36454
  transferState.refreshPendingTransfers(null, { cold: true, reason });
36419
36455
  }
36420
36456
  return transfers;
@@ -36433,12 +36469,16 @@ function createWalletPolling({ wallet, network, appState, getTransferState, getB
36433
36469
  activeRefreshInterval = null;
36434
36470
  };
36435
36471
  const runObservedActiveRefresh = () => {
36472
+ if (!hasFastActiveRefreshWork()) {
36473
+ stopActiveRefreshPoll();
36474
+ return;
36475
+ }
36436
36476
  if (activeRefreshDue()) {
36437
36477
  runActiveRefresh();
36438
36478
  }
36439
36479
  };
36440
36480
  const startActiveRefreshPoll = () => {
36441
- if (closed || !appState || activeRefreshInterval || !wallet || !isActive() || typeof getTransferState().claimPendingIncomingTransfers !== "function") {
36481
+ if (closed || !appState || activeRefreshInterval || !wallet || !isActive() || !hasFastActiveRefreshWork() || typeof getTransferState().claimPendingIncomingTransfers !== "function") {
36442
36482
  return;
36443
36483
  }
36444
36484
  markDiag(diag, "wallet.pendingTxs.active.start", {});
@@ -36448,6 +36488,7 @@ function createWalletPolling({ wallet, network, appState, getTransferState, getB
36448
36488
  }
36449
36489
  runObservedActiveRefresh();
36450
36490
  }, activeRefreshPollMs);
36491
+ runObservedActiveRefresh();
36451
36492
  };
36452
36493
  const runPendingPoll = () => {
36453
36494
  if (pendingPollPromise) {
@@ -36485,7 +36526,7 @@ function createWalletPolling({ wallet, network, appState, getTransferState, getB
36485
36526
  stopActiveRefreshPoll();
36486
36527
  return;
36487
36528
  }
36488
- if (isActive()) {
36529
+ if (isActive() && hasFastActiveRefreshWork()) {
36489
36530
  startActiveRefreshPoll();
36490
36531
  } else {
36491
36532
  stopActiveRefreshPoll();
@@ -36496,17 +36537,19 @@ function createWalletPolling({ wallet, network, appState, getTransferState, getB
36496
36537
  stopPoll();
36497
36538
  }
36498
36539
  };
36499
- const requestTransferDiscoveryHotWindow = ({ durationMs = WALLET_VISIBLE_TRANSFER_DISCOVERY_WINDOW_MS } = {}) => {
36500
- const windowMs = Math.max(0, Number(durationMs) || WALLET_VISIBLE_TRANSFER_DISCOVERY_WINDOW_MS);
36501
- activeTransferHotUntilMs = Math.max(activeTransferHotUntilMs, Date.now() + windowMs);
36502
- if (isActive()) {
36503
- startActiveRefreshPoll();
36504
- }
36540
+ const setTransferDiscoveryVisible = (visible) => {
36541
+ const next = visible === true;
36542
+ if (transferDiscoveryVisible === next)
36543
+ return;
36544
+ transferDiscoveryVisible = next;
36545
+ if (next)
36546
+ activeRefreshLastAt = 0;
36547
+ sync();
36505
36548
  };
36506
36549
  const appStateSubscription = appState?.addEventListener?.("change", (nextState2) => {
36507
36550
  if (nextState2 === "active") {
36508
- startActiveRefreshPoll();
36509
36551
  runActiveRefresh("focus");
36552
+ startActiveRefreshPoll();
36510
36553
  if (getTransferState().hasPendingTxs) {
36511
36554
  startPoll();
36512
36555
  runPendingPoll();
@@ -36524,7 +36567,7 @@ function createWalletPolling({ wallet, network, appState, getTransferState, getB
36524
36567
  }, depositClaimRate);
36525
36568
  sync();
36526
36569
  return {
36527
- requestTransferDiscoveryHotWindow,
36570
+ setTransferDiscoveryVisible,
36528
36571
  stopPoll,
36529
36572
  sync,
36530
36573
  close() {
@@ -39071,7 +39114,7 @@ function createEmptyWalletSessionSnapshot(network, transferSnapshot = null, cach
39071
39114
  isWalletDataReady: false,
39072
39115
  isWalletDataLoaded: cachedDataReady,
39073
39116
  refresh: ASYNC_NOOP,
39074
- requestTransferDiscoveryHotWindow: NOOP5,
39117
+ setTransferDiscoveryVisible: NOOP5,
39075
39118
  claimDeposits: ASYNC_FALSE,
39076
39119
  getFundingAddress: ASYNC_NOOP,
39077
39120
  preparePayment: WALLET_NOT_READY,
@@ -39247,7 +39290,7 @@ function createWalletSession({
39247
39290
  isWalletDataReady: true,
39248
39291
  isWalletDataLoaded: balanceState.balanceReady || currentTransferState.txReady,
39249
39292
  refresh: claims.refresh,
39250
- requestTransferDiscoveryHotWindow: polling.requestTransferDiscoveryHotWindow,
39293
+ setTransferDiscoveryVisible: polling.setTransferDiscoveryVisible,
39251
39294
  claimDeposits: claims.claimDeposits,
39252
39295
  getFundingAddress: funding.getFundingAddress,
39253
39296
  preparePayment: mutationActions.preparePayment,
@@ -127,9 +127,6 @@ var BAN_REFRESH_GRACE_MS = 50;
127
127
  var REQUEST_MONEY_MAX_SATS = SATS_PER_BITCOIN * 100000n;
128
128
  var WALLET_TRANSFER_POLL_MS = 3 * MS_PER_SECOND;
129
129
  var WALLET_ACTIVE_TRANSFER_REFRESH_MS = MS_PER_SECOND;
130
- var WALLET_IDLE_ACTIVE_TRANSFER_REFRESH_MS = 5 * MS_PER_SECOND;
131
- var WALLET_VISIBLE_TRANSFER_DISCOVERY_WINDOW_MS = 12 * MS_PER_SECOND;
132
- var WALLET_ACTIVE_TRANSFER_EMPTY_SCAN_LIMIT = 8;
133
130
  var WALLET_CACHE_HYDRATE_DELAY_MS = 0;
134
131
  var WALLET_BOOT_REFRESH_DELAY_MS = 500;
135
132
  var WALLET_BOOT_CACHED_REFRESH_DELAY_MS = 2500;
package/dist/cli.js CHANGED
@@ -6126,7 +6126,7 @@ var init_emoji = __esm(() => {
6126
6126
  });
6127
6127
 
6128
6128
  // ../../core/config.js
6129
- var MS_PER_SECOND = 1000, MINUTE_MS, HOUR_MS, DAY_MS, KIB_BYTES = 1024, MIB_BYTES, SATS_PER_BITCOIN = 100000000n, USERNAME_MAX_CHARS = 12, PASSWORD_MIN_CHARS = 15, PASSWORD_MAX_CHARS = 64, PASSWORD_MAX_BYTES, AUTOLOCK_MIN_MINUTES = 1, AUTOLOCK_MAX_MINUTES = 60, LOCAL_CACHE_WRITE_DELAY_MS = 350, LOCAL_MEDIA_CACHE_MAX_BYTES, LOCAL_MEDIA_CACHE_MAX_ITEMS = 1000, LOCAL_MEDIA_ACCESS_TOUCH_MIN_MS, LOCAL_PROFILE_CACHE_MAX_ITEMS = 500, LOCAL_PROFILE_CACHE_MAX_AGE_MS, LOCAL_CHAT_CACHE_MAX_ITEMS = 1000, LOCAL_CHAT_MESSAGE_CACHE_MAX_VISIBLE = 1000, LOCAL_CHAT_MESSAGE_CACHE_WRITE_DELAY_MS = 2500, LOCAL_AVATAR_CACHE_MAX_BYTES, LOCAL_AVATAR_CACHE_MAX_AGE_MS, AVATAR_IMAGE_MAX_BYTES, AVATAR_IMAGE_QUALITY_ATTEMPTS, CHAT_AVATAR_IMAGE_MAX_BYTES, CHAT_AVATAR_REF_MAX_CHARS = 256, CHAT_MESSAGE_FILE_CACHE_MAX_BYTES, IDLE_CALLBACK_MIN_TIMEOUT_MS = 50, ATTACHMENT_CACHE_IDLE_TIMEOUT_MS = 2500, ATTACHMENT_CACHE_FALLBACK_DELAY_MS = 250, CHAT_UNSAVED_TTL_DAYS = 21, CHAT_UNSAVED_TTL_MS, CHAT_AFTER_SEEN_MS, CHAT_MEDIA_TTL_DAYS, CHAT_MEDIA_TTL_MS, CHAT_UPLOAD_MAX_BYTES, CHAT_AUDIO_TRANSCODE_BITRATE_BPS = 128000, CHAT_VIDEO_TRANSCODE_VIDEO_BITRATE_BPS = 3000000, CHAT_VIDEO_TRANSCODE_AUDIO_BITRATE_BPS, CHAT_MESSAGE_BATCH_SIZE = 40, CHAT_MESSAGE_QUERY_MAX_DOCS = 120, CHAT_MESSAGE_MUTATION_MAX_ITEMS = 256, CHAT_TTL_CLIENT_DELETE_GRACE_MS, CHAT_BATCH_CLEANUP_IDLE_TIMEOUT_MS = 1500, CHAT_BATCH_CLEANUP_IDLE_DELAY_MS = 250, CHAT_LIST_PAGE_SIZE = 20, CHAT_LIST_LIVE_COUNT, CHAT_INBOX_PING_PAGE_SIZE = 25, CHAT_INBOX_DISCOVERY_PARALLEL_CHATS, CHAT_INBOX_SETTLEMENT_PARALLEL_CHATS = 4, CHAT_INBOX_CURSOR_OVERLAP_MS, CHAT_LIST_CACHE_WRITE_DELAY_MS = 1500, CHAT_LIST_SNAPSHOT_COALESCE_MS = 80, CHAT_LIST_COMPLETE_SYNC_DELAY_MS = 250, CHAT_LIST_LISTENER_RETRY_MS = 1000, CHAT_TOP_WARM_COUNT = 0, CHAT_EAGER_WARM_COUNT = 0, CHAT_WARM_DELAY_MS = 3000, CHAT_WARM_BATCH_SIZE, CHAT_MESSAGE_VIEW_CACHE_SIZE = 30, CHAT_MEDIA_WARM_MESSAGES_PER_CHAT, CHAT_MEDIA_WARM_START_DELAY_MS = 600, CHAT_MEDIA_WARM_STEP_DELAY_MS = 120, CHAT_MEDIA_WARM_TYPES, CHAT_MEDIA_WARM_MAX_BYTES = 0, CHAT_READ_WRITE_INTERVAL_MS, CHAT_READ_WRITE_MAX_WAIT_MS, CHAT_LIVE_PING_INTERVAL_MS, CHAT_LIVE_SWEEP_INTERVAL_MS, CHAT_LIVE_STALE_AFTER_MS, CHAT_LIVE_RECONNECT_MAX_MS, CHAT_LIVE_TYPING_IDLE_MS, CHAT_LIVE_TYPING_RENEW_MS, CHAT_LIVE_COMPOSITION_HANDOFF_MS, CHAT_LIVE_READ_SEND_INTERVAL_MS = 120, CHAT_LIVE_READ_SEND_MAX_WAIT_MS = 500, CHAT_LIVE_READ_WRITE_INTERVAL_MS, CHAT_LIVE_READ_WRITE_MAX_WAIT_MS, CHAT_SEND_QUEUE_RATE_LIMIT_COUNT = 12, CHAT_SEND_QUEUE_RATE_LIMIT_WINDOW_MS, CHAT_SETTINGS_BODY_MAX_BYTES, CHAT_TITLE_STATE_MAX_CHARS = 128, CHAT_MANIFEST_MAX_BYTES, CHAT_RECEIPT_MAX_MEMBERS = 32, CHAT_ORDINARY_DELIVERY_MAX_MEMBERS = 128, CHAT_MAX_MEMBERS = 256, CHAT_MAX_TEXT_CHARS = 2048, CHAT_TITLE_INPUT_MAX_CHARS = 16, CHAT_MAX_REACTIONS, SEARCH_DEBOUNCE_MS = 300, SEARCH_USERNAME_LIMIT = 15, SEARCH_ROLE_LIMIT = 15, RECENT_PEER_REFRESH_LIMIT = 50, RECENT_PEER_REFRESH_DELAY_MS = 250, RECENT_PEER_REFRESH_INTERVAL_MS, RECENT_PEER_REFRESH_THROTTLE_MS = 120, BAN_REFRESH_GRACE_MS = 50, REQUEST_MONEY_MAX_SATS, WALLET_TRANSFER_POLL_MS, WALLET_ACTIVE_TRANSFER_REFRESH_MS, WALLET_IDLE_ACTIVE_TRANSFER_REFRESH_MS, WALLET_VISIBLE_TRANSFER_DISCOVERY_WINDOW_MS, WALLET_ACTIVE_TRANSFER_EMPTY_SCAN_LIMIT = 8, WALLET_CACHE_HYDRATE_DELAY_MS = 0, WALLET_BOOT_REFRESH_DELAY_MS = 500, WALLET_BOOT_CACHED_REFRESH_DELAY_MS = 2500, WALLET_REGTEST_DEPOSIT_CLAIM_POLL_MS, WALLET_MAINNET_DEPOSIT_CLAIM_POLL_MS, WALLET_BALANCE_EVENT_COALESCE_MS, WALLET_INCOMING_UPDATE_COALESCE_MS = 250, WALLET_AUTO_CLAIM_MAX_FEE_SATS = 5000, WALLET_CLAIM_PAGE_SIZE = 100, WALLET_PENDING_TRANSFER_CLAIM_BATCH_SIZE = 50, WALLET_PENDING_TRANSFER_STATUS_BATCH_SIZE = 2, WALLET_PENDING_TRANSFER_COLD_REFRESH_BATCH_SIZE = 50, WALLET_PENDING_TRANSFER_COLD_REFRESH_INTERVAL_MS, WALLET_PENDING_TRANSFER_ADAPTIVE_BATCH_SMALL_QUEUE = 3, WALLET_PENDING_TRANSFER_ADAPTIVE_BATCH_LARGE_QUEUE = 10, WALLET_PENDING_TRANSFER_ADAPTIVE_BATCH_SMALL_SIZE = 2, WALLET_PENDING_TRANSFER_ADAPTIVE_BATCH_LARGE_SIZE = 3, WALLET_PENDING_TRANSFER_SLOW_CLAIM_MS, WALLET_PENDING_TRANSFER_CLAIM_COOLDOWN_MS, WALLET_SDK_BACKGROUND_QUIET_MS, WALLET_RECENT_TRANSFER_LIMIT = 100, WALLET_TRANSFER_PAGE_LIMIT = 100, WALLET_TRANSFER_FETCH_THROTTLE_MS = 150, WALLET_PENDING_TRANSFER_CLAIM_RETRY_MS, WALLET_SENT_TRANSFER_REFRESH_DELAY_MS, WALLET_PENDING_TRANSFER_BOOT_GRACE_MS, WALLET_PENDING_TRANSFER_HOT_AGE_MS, WALLET_PENDING_TRANSFER_WARM_AGE_MS, WALLET_PENDING_TRANSFER_WARM_RETRY_MS, WALLET_PENDING_TRANSFER_STALE_RETRY_MS, WALLET_PENDING_TRANSFER_STUCK_RETRY_MS, WALLET_PENDING_TRANSFER_DORMANT_RETRY_MS, WALLET_TRANSFER_CACHE_WRITE_DELAY_MS;
6129
+ var MS_PER_SECOND = 1000, MINUTE_MS, HOUR_MS, DAY_MS, KIB_BYTES = 1024, MIB_BYTES, SATS_PER_BITCOIN = 100000000n, USERNAME_MAX_CHARS = 12, PASSWORD_MIN_CHARS = 15, PASSWORD_MAX_CHARS = 64, PASSWORD_MAX_BYTES, AUTOLOCK_MIN_MINUTES = 1, AUTOLOCK_MAX_MINUTES = 60, LOCAL_CACHE_WRITE_DELAY_MS = 350, LOCAL_MEDIA_CACHE_MAX_BYTES, LOCAL_MEDIA_CACHE_MAX_ITEMS = 1000, LOCAL_MEDIA_ACCESS_TOUCH_MIN_MS, LOCAL_PROFILE_CACHE_MAX_ITEMS = 500, LOCAL_PROFILE_CACHE_MAX_AGE_MS, LOCAL_CHAT_CACHE_MAX_ITEMS = 1000, LOCAL_CHAT_MESSAGE_CACHE_MAX_VISIBLE = 1000, LOCAL_CHAT_MESSAGE_CACHE_WRITE_DELAY_MS = 2500, LOCAL_AVATAR_CACHE_MAX_BYTES, LOCAL_AVATAR_CACHE_MAX_AGE_MS, AVATAR_IMAGE_MAX_BYTES, AVATAR_IMAGE_QUALITY_ATTEMPTS, CHAT_AVATAR_IMAGE_MAX_BYTES, CHAT_AVATAR_REF_MAX_CHARS = 256, CHAT_MESSAGE_FILE_CACHE_MAX_BYTES, IDLE_CALLBACK_MIN_TIMEOUT_MS = 50, ATTACHMENT_CACHE_IDLE_TIMEOUT_MS = 2500, ATTACHMENT_CACHE_FALLBACK_DELAY_MS = 250, CHAT_UNSAVED_TTL_DAYS = 21, CHAT_UNSAVED_TTL_MS, CHAT_AFTER_SEEN_MS, CHAT_MEDIA_TTL_DAYS, CHAT_MEDIA_TTL_MS, CHAT_UPLOAD_MAX_BYTES, CHAT_AUDIO_TRANSCODE_BITRATE_BPS = 128000, CHAT_VIDEO_TRANSCODE_VIDEO_BITRATE_BPS = 3000000, CHAT_VIDEO_TRANSCODE_AUDIO_BITRATE_BPS, CHAT_MESSAGE_BATCH_SIZE = 40, CHAT_MESSAGE_QUERY_MAX_DOCS = 120, CHAT_MESSAGE_MUTATION_MAX_ITEMS = 256, CHAT_TTL_CLIENT_DELETE_GRACE_MS, CHAT_BATCH_CLEANUP_IDLE_TIMEOUT_MS = 1500, CHAT_BATCH_CLEANUP_IDLE_DELAY_MS = 250, CHAT_LIST_PAGE_SIZE = 20, CHAT_LIST_LIVE_COUNT, CHAT_INBOX_PING_PAGE_SIZE = 25, CHAT_INBOX_DISCOVERY_PARALLEL_CHATS, CHAT_INBOX_SETTLEMENT_PARALLEL_CHATS = 4, CHAT_INBOX_CURSOR_OVERLAP_MS, CHAT_LIST_CACHE_WRITE_DELAY_MS = 1500, CHAT_LIST_SNAPSHOT_COALESCE_MS = 80, CHAT_LIST_COMPLETE_SYNC_DELAY_MS = 250, CHAT_LIST_LISTENER_RETRY_MS = 1000, CHAT_TOP_WARM_COUNT = 0, CHAT_EAGER_WARM_COUNT = 0, CHAT_WARM_DELAY_MS = 3000, CHAT_WARM_BATCH_SIZE, CHAT_MESSAGE_VIEW_CACHE_SIZE = 30, CHAT_MEDIA_WARM_MESSAGES_PER_CHAT, CHAT_MEDIA_WARM_START_DELAY_MS = 600, CHAT_MEDIA_WARM_STEP_DELAY_MS = 120, CHAT_MEDIA_WARM_TYPES, CHAT_MEDIA_WARM_MAX_BYTES = 0, CHAT_READ_WRITE_INTERVAL_MS, CHAT_READ_WRITE_MAX_WAIT_MS, CHAT_LIVE_PING_INTERVAL_MS, CHAT_LIVE_SWEEP_INTERVAL_MS, CHAT_LIVE_STALE_AFTER_MS, CHAT_LIVE_RECONNECT_MAX_MS, CHAT_LIVE_TYPING_IDLE_MS, CHAT_LIVE_TYPING_RENEW_MS, CHAT_LIVE_COMPOSITION_HANDOFF_MS, CHAT_LIVE_READ_SEND_INTERVAL_MS = 120, CHAT_LIVE_READ_SEND_MAX_WAIT_MS = 500, CHAT_LIVE_READ_WRITE_INTERVAL_MS, CHAT_LIVE_READ_WRITE_MAX_WAIT_MS, CHAT_SEND_QUEUE_RATE_LIMIT_COUNT = 12, CHAT_SEND_QUEUE_RATE_LIMIT_WINDOW_MS, CHAT_SETTINGS_BODY_MAX_BYTES, CHAT_TITLE_STATE_MAX_CHARS = 128, CHAT_MANIFEST_MAX_BYTES, CHAT_RECEIPT_MAX_MEMBERS = 32, CHAT_ORDINARY_DELIVERY_MAX_MEMBERS = 128, CHAT_MAX_MEMBERS = 256, CHAT_MAX_TEXT_CHARS = 2048, CHAT_TITLE_INPUT_MAX_CHARS = 16, CHAT_MAX_REACTIONS, SEARCH_DEBOUNCE_MS = 300, SEARCH_USERNAME_LIMIT = 15, SEARCH_ROLE_LIMIT = 15, RECENT_PEER_REFRESH_LIMIT = 50, RECENT_PEER_REFRESH_DELAY_MS = 250, RECENT_PEER_REFRESH_INTERVAL_MS, RECENT_PEER_REFRESH_THROTTLE_MS = 120, BAN_REFRESH_GRACE_MS = 50, REQUEST_MONEY_MAX_SATS, WALLET_TRANSFER_POLL_MS, WALLET_ACTIVE_TRANSFER_REFRESH_MS, WALLET_CACHE_HYDRATE_DELAY_MS = 0, WALLET_BOOT_REFRESH_DELAY_MS = 500, WALLET_BOOT_CACHED_REFRESH_DELAY_MS = 2500, WALLET_REGTEST_DEPOSIT_CLAIM_POLL_MS, WALLET_MAINNET_DEPOSIT_CLAIM_POLL_MS, WALLET_BALANCE_EVENT_COALESCE_MS, WALLET_INCOMING_UPDATE_COALESCE_MS = 250, WALLET_AUTO_CLAIM_MAX_FEE_SATS = 5000, WALLET_CLAIM_PAGE_SIZE = 100, WALLET_PENDING_TRANSFER_CLAIM_BATCH_SIZE = 50, WALLET_PENDING_TRANSFER_STATUS_BATCH_SIZE = 2, WALLET_PENDING_TRANSFER_COLD_REFRESH_BATCH_SIZE = 50, WALLET_PENDING_TRANSFER_COLD_REFRESH_INTERVAL_MS, WALLET_PENDING_TRANSFER_ADAPTIVE_BATCH_SMALL_QUEUE = 3, WALLET_PENDING_TRANSFER_ADAPTIVE_BATCH_LARGE_QUEUE = 10, WALLET_PENDING_TRANSFER_ADAPTIVE_BATCH_SMALL_SIZE = 2, WALLET_PENDING_TRANSFER_ADAPTIVE_BATCH_LARGE_SIZE = 3, WALLET_PENDING_TRANSFER_SLOW_CLAIM_MS, WALLET_PENDING_TRANSFER_CLAIM_COOLDOWN_MS, WALLET_SDK_BACKGROUND_QUIET_MS, WALLET_RECENT_TRANSFER_LIMIT = 100, WALLET_TRANSFER_PAGE_LIMIT = 100, WALLET_TRANSFER_FETCH_THROTTLE_MS = 150, WALLET_PENDING_TRANSFER_CLAIM_RETRY_MS, WALLET_SENT_TRANSFER_REFRESH_DELAY_MS, WALLET_PENDING_TRANSFER_BOOT_GRACE_MS, WALLET_PENDING_TRANSFER_HOT_AGE_MS, WALLET_PENDING_TRANSFER_WARM_AGE_MS, WALLET_PENDING_TRANSFER_WARM_RETRY_MS, WALLET_PENDING_TRANSFER_STALE_RETRY_MS, WALLET_PENDING_TRANSFER_STUCK_RETRY_MS, WALLET_PENDING_TRANSFER_DORMANT_RETRY_MS, WALLET_TRANSFER_CACHE_WRITE_DELAY_MS;
6130
6130
  var init_config = __esm(() => {
6131
6131
  MINUTE_MS = 60 * MS_PER_SECOND;
6132
6132
  HOUR_MS = 60 * MINUTE_MS;
@@ -6174,8 +6174,6 @@ var init_config = __esm(() => {
6174
6174
  REQUEST_MONEY_MAX_SATS = SATS_PER_BITCOIN * 100000n;
6175
6175
  WALLET_TRANSFER_POLL_MS = 3 * MS_PER_SECOND;
6176
6176
  WALLET_ACTIVE_TRANSFER_REFRESH_MS = MS_PER_SECOND;
6177
- WALLET_IDLE_ACTIVE_TRANSFER_REFRESH_MS = 5 * MS_PER_SECOND;
6178
- WALLET_VISIBLE_TRANSFER_DISCOVERY_WINDOW_MS = 12 * MS_PER_SECOND;
6179
6177
  WALLET_REGTEST_DEPOSIT_CLAIM_POLL_MS = 20 * MS_PER_SECOND;
6180
6178
  WALLET_MAINNET_DEPOSIT_CLAIM_POLL_MS = MINUTE_MS;
6181
6179
  WALLET_BALANCE_EVENT_COALESCE_MS = 2 * MS_PER_SECOND;
@@ -12541,12 +12539,16 @@ function projectRequestPayment(requestValue, paymentValue) {
12541
12539
  if (!requester || !payer || requester === payer || requestNetwork(requestValue) !== requestNetwork(paymentValue)) {
12542
12540
  return requestValue;
12543
12541
  }
12544
- const payments = normalizedPayments(requestValue);
12542
+ const progress = getRequestProgress(requestValue);
12543
+ const amount = positiveSats(paymentValue.a);
12544
+ if (progress.paid !== 0n || amount !== progress.requested) {
12545
+ return requestValue;
12546
+ }
12547
+ const payments = progress.payments;
12545
12548
  const tx = cleanText(paymentValue.tx);
12546
12549
  if (payments.some((payment) => payment.tx === tx)) {
12547
12550
  return requestValue;
12548
12551
  }
12549
- const amount = positiveSats(paymentValue.a);
12550
12552
  return {
12551
12553
  ...requestValue,
12552
12554
  payments: [...payments, {
@@ -13031,7 +13033,7 @@ function applyMessageActions(messages) {
13031
13033
  const index2 = target ? indexByKey.get(target) : null;
13032
13034
  const base = index2 != null ? out[index2] : null;
13033
13035
  const actionMembers = [...new Set((Array.isArray(msg?.epochMemberChatPKs) ? msg.epochMemberChatPKs : []).map(cleanText).filter(Boolean))];
13034
- const authorized = base?.t === "req" && isRequestPayment(msg) && actionMembers.includes(cleanText(base.s)) && actionMembers.includes(cleanText(msg.s));
13036
+ const authorized = base?.t === "req" && isRequestPayment(msg) && msg?.failed !== true && actionMembers.includes(cleanText(base.s)) && actionMembers.includes(cleanText(msg.s));
13035
13037
  if (authorized) {
13036
13038
  const next = projectRequestPayment(base, msg);
13037
13039
  const projected = isHeldSourceGoneMsg(base) ? holdSourceGoneVisibleMsg(next) : next;
@@ -20238,7 +20240,19 @@ ${cid}` : "";
20238
20240
  if (!chat || !options?.epochState || !options?.ownEntry)
20239
20241
  throw makeChatUnavailableError();
20240
20242
  const chatId = chat.chatId;
20241
- const { cid, local } = makeLocalMessage(chatId, chatPK, peerChatPK, message);
20243
+ const epochManifest = options.epochState?.manifest;
20244
+ const actionOp = cleanText(options.actionOp);
20245
+ const actionTarget3 = cleanText(options.actionTarget);
20246
+ const localMessage = {
20247
+ ...message,
20248
+ ...actionOp ? { actionOp } : {},
20249
+ ...actionTarget3 ? { actionTarget: actionTarget3 } : {},
20250
+ ...epochManifest?.epochId ? { epochId: epochManifest.epochId } : {},
20251
+ ...Array.isArray(epochManifest?.members) ? {
20252
+ epochMemberChatPKs: epochManifest.members.map((member) => cleanText(member?.chatPK)).filter(Boolean)
20253
+ } : {}
20254
+ };
20255
+ const { cid, local } = makeLocalMessage(chatId, chatPK, peerChatPK, localMessage);
20242
20256
  selectLocalChat?.(peerChatPK, chatId);
20243
20257
  if (hasSentLocalCid(chatId, cid)) {
20244
20258
  local.pending = false;
@@ -31893,6 +31907,8 @@ function createChatSave({ cloud, media = {}, chatBanned, localCache, getOwnerCha
31893
31907
  try {
31894
31908
  const targetEpochId = list[0]?.epochId || mutationOptions(chatId).epochState.manifest.epochId;
31895
31909
  const updated = await makeMsgPermanent(cloud, targetEpochId, list, mutationOptions(chatId));
31910
+ if (updated !== list.length)
31911
+ throw makeMessageSaveUnavailableError();
31896
31912
  return { updated, ttl: null };
31897
31913
  } catch (error) {
31898
31914
  throw normalizeMessageSaveError(error);
@@ -33257,7 +33273,20 @@ function createChatSession({
33257
33273
  const target = typeof request2 === "string" ? request2.trim() : messageRef(request2);
33258
33274
  if (!target)
33259
33275
  throw new Error("payment request target required");
33260
- return pendingOwner.sendChatMessage(chatId, makeRequestPayment(payment.amountSats, payment.tx, payment.network), {
33276
+ const batch = messageBatchOwner.getMessageBatch(chatId);
33277
+ const requestMessage = request2 && typeof request2 === "object" ? request2 : [...batch?.messages || [], ...batch?.sourceMessages || []].find((message) => message?.t === "req" && messageRef(message) === target);
33278
+ if (!requestMessage || requestMessage.t !== "req")
33279
+ throw new Error("payment request not found");
33280
+ if (cleanText(requestMessage.s || requestMessage.from) === chatPK)
33281
+ throw new Error("cannot pay your own request");
33282
+ const requestProgress = getRequestProgress(requestMessage);
33283
+ if (requestProgress.fulfilled || requestProgress.paid !== 0n)
33284
+ throw new Error("payment request already paid");
33285
+ const confirmation = makeRequestPayment(payment.amountSats, payment.tx, payment.network);
33286
+ if (requestNetwork(requestMessage) !== requestNetwork(confirmation) || BigInt(confirmation.a) !== requestProgress.requested) {
33287
+ throw new Error("payment must fulfill the request");
33288
+ }
33289
+ return pendingOwner.sendChatMessage(chatId, confirmation, {
33261
33290
  actionOp: CHAT_ACTION_OPS.PAY_CONFIRM,
33262
33291
  actionTarget: target,
33263
33292
  updatePreview: true
@@ -37341,9 +37370,18 @@ function createPeerList({ peerApi, diag, onMissingPeers }) {
37341
37370
  return subscriberCount > 0;
37342
37371
  }
37343
37372
  function beginSubscription() {
37344
- if (!subscriberCount)
37373
+ const firstSubscriber = !subscriberCount;
37374
+ if (firstSubscriber)
37345
37375
  lifecycle += 1;
37346
37376
  subscriberCount += 1;
37377
+ if (!firstSubscriber)
37378
+ return;
37379
+ const becameReady = startProfileLoad();
37380
+ if (becameReady) {
37381
+ rebuild({ base: true });
37382
+ } else {
37383
+ scheduleRefresh();
37384
+ }
37347
37385
  }
37348
37386
  function endSubscription() {
37349
37387
  subscriberCount = Math.max(0, subscriberCount - 1);
@@ -40347,23 +40385,18 @@ function createWalletPolling({ wallet, network, appState, getTransferState, getB
40347
40385
  let activeRefreshPromise = null;
40348
40386
  let pendingPollPromise = null;
40349
40387
  let activeRefreshLastAt = 0;
40350
- let activeRefreshEmptyScanCount = 0;
40351
- let activeTransferHotUntilMs = 0;
40388
+ let transferDiscoveryVisible = false;
40352
40389
  let closed = false;
40353
40390
  const depositClaimRate = getDepositClaimPollMs(network);
40354
40391
  const activeRefreshPollMs = Math.max(500, Number(activeTransferRefreshMs) || ACTIVE_TRANSFER_REFRESH_RATE);
40355
- const activeRefreshIdlePollMs = Math.max(activeRefreshPollMs, Number(IDLE_ACTIVE_TRANSFER_REFRESH_RATE) || activeRefreshPollMs);
40356
- const activeRefreshEmptyScanLimit = Math.max(1, Number(ACTIVE_TRANSFER_EMPTY_SCAN_LIMIT) || 1);
40357
40392
  const isActive = () => !appState?.currentState || appState.currentState === "active";
40358
40393
  const isTxReady = () => getTransferState().txReady === true && getBalanceState().balanceReady === true;
40359
40394
  const hasActivePendingClaim = () => getTransferState().hasActivePendingClaim?.() === true;
40360
- const hasFastActiveRefreshWork = () => activeTransferHotUntilMs > Date.now() || hasActivePendingClaim();
40395
+ const hasFastActiveRefreshWork = () => transferDiscoveryVisible || hasActivePendingClaim();
40361
40396
  const activeRefreshDue = () => {
40362
- if (hasActivePendingClaim()) {
40363
- return true;
40364
- }
40365
- const delayMs = hasFastActiveRefreshWork() || activeRefreshEmptyScanCount < activeRefreshEmptyScanLimit ? activeRefreshPollMs : activeRefreshIdlePollMs;
40366
- return !activeRefreshLastAt || Date.now() - activeRefreshLastAt >= delayMs;
40397
+ if (!hasFastActiveRefreshWork())
40398
+ return false;
40399
+ return hasActivePendingClaim() || !activeRefreshLastAt || Date.now() - activeRefreshLastAt >= activeRefreshPollMs;
40367
40400
  };
40368
40401
  const runActiveRefresh = (reason = "active-poll") => {
40369
40402
  if (closed || !wallet || !isActive()) {
@@ -40376,16 +40409,8 @@ function createWalletPolling({ wallet, network, appState, getTransferState, getB
40376
40409
  activeRefreshLastAt = Date.now();
40377
40410
  const transferState = getTransferState();
40378
40411
  const transfers = typeof transferState.claimPendingIncomingTransfers === "function" ? await transferState.claimPendingIncomingTransfers(reason) : [];
40379
- if (Array.isArray(transfers) && transfers.length) {
40380
- activeRefreshEmptyScanCount = 0;
40381
- } else if (hasActivePendingClaim()) {
40382
- activeRefreshEmptyScanCount = 0;
40383
- } else {
40384
- activeRefreshEmptyScanCount += 1;
40385
- }
40386
- const visibleHot = activeTransferHotUntilMs > Date.now();
40387
40412
  const claimActive = hasActivePendingClaim();
40388
- if (isTxReady() && typeof transferState.refreshPendingTransfers === "function" && !visibleHot && !claimActive) {
40413
+ if (isTxReady() && typeof transferState.refreshPendingTransfers === "function" && !transferDiscoveryVisible && !claimActive) {
40389
40414
  transferState.refreshPendingTransfers(null, { cold: true, reason });
40390
40415
  }
40391
40416
  return transfers;
@@ -40404,12 +40429,16 @@ function createWalletPolling({ wallet, network, appState, getTransferState, getB
40404
40429
  activeRefreshInterval = null;
40405
40430
  };
40406
40431
  const runObservedActiveRefresh = () => {
40432
+ if (!hasFastActiveRefreshWork()) {
40433
+ stopActiveRefreshPoll();
40434
+ return;
40435
+ }
40407
40436
  if (activeRefreshDue()) {
40408
40437
  runActiveRefresh();
40409
40438
  }
40410
40439
  };
40411
40440
  const startActiveRefreshPoll = () => {
40412
- if (closed || !appState || activeRefreshInterval || !wallet || !isActive() || typeof getTransferState().claimPendingIncomingTransfers !== "function") {
40441
+ if (closed || !appState || activeRefreshInterval || !wallet || !isActive() || !hasFastActiveRefreshWork() || typeof getTransferState().claimPendingIncomingTransfers !== "function") {
40413
40442
  return;
40414
40443
  }
40415
40444
  markDiag(diag, "wallet.pendingTxs.active.start", {});
@@ -40419,6 +40448,7 @@ function createWalletPolling({ wallet, network, appState, getTransferState, getB
40419
40448
  }
40420
40449
  runObservedActiveRefresh();
40421
40450
  }, activeRefreshPollMs);
40451
+ runObservedActiveRefresh();
40422
40452
  };
40423
40453
  const runPendingPoll = () => {
40424
40454
  if (pendingPollPromise) {
@@ -40456,7 +40486,7 @@ function createWalletPolling({ wallet, network, appState, getTransferState, getB
40456
40486
  stopActiveRefreshPoll();
40457
40487
  return;
40458
40488
  }
40459
- if (isActive()) {
40489
+ if (isActive() && hasFastActiveRefreshWork()) {
40460
40490
  startActiveRefreshPoll();
40461
40491
  } else {
40462
40492
  stopActiveRefreshPoll();
@@ -40467,17 +40497,19 @@ function createWalletPolling({ wallet, network, appState, getTransferState, getB
40467
40497
  stopPoll();
40468
40498
  }
40469
40499
  };
40470
- const requestTransferDiscoveryHotWindow = ({ durationMs = WALLET_VISIBLE_TRANSFER_DISCOVERY_WINDOW_MS } = {}) => {
40471
- const windowMs = Math.max(0, Number(durationMs) || WALLET_VISIBLE_TRANSFER_DISCOVERY_WINDOW_MS);
40472
- activeTransferHotUntilMs = Math.max(activeTransferHotUntilMs, Date.now() + windowMs);
40473
- if (isActive()) {
40474
- startActiveRefreshPoll();
40475
- }
40500
+ const setTransferDiscoveryVisible = (visible) => {
40501
+ const next = visible === true;
40502
+ if (transferDiscoveryVisible === next)
40503
+ return;
40504
+ transferDiscoveryVisible = next;
40505
+ if (next)
40506
+ activeRefreshLastAt = 0;
40507
+ sync();
40476
40508
  };
40477
40509
  const appStateSubscription = appState?.addEventListener?.("change", (nextState2) => {
40478
40510
  if (nextState2 === "active") {
40479
- startActiveRefreshPoll();
40480
40511
  runActiveRefresh("focus");
40512
+ startActiveRefreshPoll();
40481
40513
  if (getTransferState().hasPendingTxs) {
40482
40514
  startPoll();
40483
40515
  runPendingPoll();
@@ -40495,7 +40527,7 @@ function createWalletPolling({ wallet, network, appState, getTransferState, getB
40495
40527
  }, depositClaimRate);
40496
40528
  sync();
40497
40529
  return {
40498
- requestTransferDiscoveryHotWindow,
40530
+ setTransferDiscoveryVisible,
40499
40531
  stopPoll,
40500
40532
  sync,
40501
40533
  close() {
@@ -40609,15 +40641,13 @@ function createWalletReadyDiag({ wallet, getBalanceState, getTransferState, diag
40609
40641
  }
40610
40642
  };
40611
40643
  }
40612
- var POLL_TXS_RATE, ACTIVE_TRANSFER_REFRESH_RATE, IDLE_ACTIVE_TRANSFER_REFRESH_RATE, ACTIVE_TRANSFER_EMPTY_SCAN_LIMIT, BOOT_REFRESH_DELAY_MS, BOOT_CACHED_REFRESH_DELAY_MS, BOOT_CACHE_DECISION_DELAY_MS, BALANCE_EVENT_COALESCE_MS, INCOMING_UPDATE_COALESCE_MS, WALLET_EVENTS;
40644
+ var POLL_TXS_RATE, ACTIVE_TRANSFER_REFRESH_RATE, BOOT_REFRESH_DELAY_MS, BOOT_CACHED_REFRESH_DELAY_MS, BOOT_CACHE_DECISION_DELAY_MS, BALANCE_EVENT_COALESCE_MS, INCOMING_UPDATE_COALESCE_MS, WALLET_EVENTS;
40613
40645
  var init_lifecycle = __esm(() => {
40614
40646
  init_config();
40615
40647
  init_network();
40616
40648
  init_async();
40617
40649
  POLL_TXS_RATE = WALLET_TRANSFER_POLL_MS;
40618
40650
  ACTIVE_TRANSFER_REFRESH_RATE = WALLET_ACTIVE_TRANSFER_REFRESH_MS;
40619
- IDLE_ACTIVE_TRANSFER_REFRESH_RATE = WALLET_IDLE_ACTIVE_TRANSFER_REFRESH_MS;
40620
- ACTIVE_TRANSFER_EMPTY_SCAN_LIMIT = WALLET_ACTIVE_TRANSFER_EMPTY_SCAN_LIMIT;
40621
40651
  BOOT_REFRESH_DELAY_MS = WALLET_BOOT_REFRESH_DELAY_MS;
40622
40652
  BOOT_CACHED_REFRESH_DELAY_MS = WALLET_BOOT_CACHED_REFRESH_DELAY_MS;
40623
40653
  BOOT_CACHE_DECISION_DELAY_MS = BOOT_REFRESH_DELAY_MS + Math.max(0, WALLET_CACHE_HYDRATE_DELAY_MS) + 250;
@@ -43083,7 +43113,7 @@ function createEmptyWalletSessionSnapshot(network, transferSnapshot = null, cach
43083
43113
  isWalletDataReady: false,
43084
43114
  isWalletDataLoaded: cachedDataReady,
43085
43115
  refresh: ASYNC_NOOP,
43086
- requestTransferDiscoveryHotWindow: NOOP5,
43116
+ setTransferDiscoveryVisible: NOOP5,
43087
43117
  claimDeposits: ASYNC_FALSE,
43088
43118
  getFundingAddress: ASYNC_NOOP,
43089
43119
  preparePayment: WALLET_NOT_READY,
@@ -43259,7 +43289,7 @@ function createWalletSession({
43259
43289
  isWalletDataReady: true,
43260
43290
  isWalletDataLoaded: balanceState.balanceReady || currentTransferState.txReady,
43261
43291
  refresh: claims.refresh,
43262
- requestTransferDiscoveryHotWindow: polling.requestTransferDiscoveryHotWindow,
43292
+ setTransferDiscoveryVisible: polling.setTransferDiscoveryVisible,
43263
43293
  claimDeposits: claims.claimDeposits,
43264
43294
  getFundingAddress: funding.getFundingAddress,
43265
43295
  preparePayment: mutationActions.preparePayment,
@@ -56267,9 +56297,12 @@ function createRuntimeMoneyActions({ getRuntime, getSession, resolvePeer, chat }
56267
56297
  const progress = getRequestProgress(message);
56268
56298
  if (progress.fulfilled)
56269
56299
  throw new Error("payment request already fulfilled");
56270
- const amountSats = cleanPositiveSats(options.amountSats ?? progress.remaining);
56271
- if (BigInt(amountSats) > progress.remaining)
56272
- throw new Error("payment exceeds request remainder");
56300
+ if (progress.paid !== 0n)
56301
+ throw new Error("payment request already paid");
56302
+ const amountSats = cleanPositiveSats(progress.requested);
56303
+ if (options.amountSats != null && BigInt(cleanPositiveSats(options.amountSats)) !== progress.requested) {
56304
+ throw new Error("payment must fulfill the request");
56305
+ }
56273
56306
  const requesterChatPK = cleanText(message.s || message.from);
56274
56307
  let profile = runtime.peers.getSnapshot().peerByChatPK.get(requesterChatPK) || null;
56275
56308
  if (!profile)
@@ -56391,7 +56424,7 @@ var package_default;
56391
56424
  var init_package2 = __esm(() => {
56392
56425
  package_default = {
56393
56426
  name: "veyl",
56394
- version: "0.66.0",
56427
+ version: "0.66.2",
56395
56428
  packageManager: "bun@1.4.0",
56396
56429
  private: true,
56397
56430
  license: "UNLICENSED",
package/dist/index.js CHANGED
@@ -6125,7 +6125,7 @@ var init_emoji = __esm(() => {
6125
6125
  });
6126
6126
 
6127
6127
  // ../../core/config.js
6128
- var MS_PER_SECOND = 1000, MINUTE_MS, HOUR_MS, DAY_MS, KIB_BYTES = 1024, MIB_BYTES, SATS_PER_BITCOIN = 100000000n, USERNAME_MAX_CHARS = 12, PASSWORD_MIN_CHARS = 15, PASSWORD_MAX_CHARS = 64, PASSWORD_MAX_BYTES, AUTOLOCK_MIN_MINUTES = 1, AUTOLOCK_MAX_MINUTES = 60, LOCAL_CACHE_WRITE_DELAY_MS = 350, LOCAL_MEDIA_CACHE_MAX_BYTES, LOCAL_MEDIA_CACHE_MAX_ITEMS = 1000, LOCAL_MEDIA_ACCESS_TOUCH_MIN_MS, LOCAL_PROFILE_CACHE_MAX_ITEMS = 500, LOCAL_PROFILE_CACHE_MAX_AGE_MS, LOCAL_CHAT_CACHE_MAX_ITEMS = 1000, LOCAL_CHAT_MESSAGE_CACHE_MAX_VISIBLE = 1000, LOCAL_CHAT_MESSAGE_CACHE_WRITE_DELAY_MS = 2500, LOCAL_AVATAR_CACHE_MAX_BYTES, LOCAL_AVATAR_CACHE_MAX_AGE_MS, AVATAR_IMAGE_MAX_BYTES, AVATAR_IMAGE_QUALITY_ATTEMPTS, CHAT_AVATAR_IMAGE_MAX_BYTES, CHAT_AVATAR_REF_MAX_CHARS = 256, CHAT_MESSAGE_FILE_CACHE_MAX_BYTES, IDLE_CALLBACK_MIN_TIMEOUT_MS = 50, ATTACHMENT_CACHE_IDLE_TIMEOUT_MS = 2500, ATTACHMENT_CACHE_FALLBACK_DELAY_MS = 250, CHAT_UNSAVED_TTL_DAYS = 21, CHAT_UNSAVED_TTL_MS, CHAT_AFTER_SEEN_MS, CHAT_MEDIA_TTL_DAYS, CHAT_MEDIA_TTL_MS, CHAT_UPLOAD_MAX_BYTES, CHAT_AUDIO_TRANSCODE_BITRATE_BPS = 128000, CHAT_VIDEO_TRANSCODE_VIDEO_BITRATE_BPS = 3000000, CHAT_VIDEO_TRANSCODE_AUDIO_BITRATE_BPS, CHAT_MESSAGE_BATCH_SIZE = 40, CHAT_MESSAGE_QUERY_MAX_DOCS = 120, CHAT_MESSAGE_MUTATION_MAX_ITEMS = 256, CHAT_TTL_CLIENT_DELETE_GRACE_MS, CHAT_BATCH_CLEANUP_IDLE_TIMEOUT_MS = 1500, CHAT_BATCH_CLEANUP_IDLE_DELAY_MS = 250, CHAT_LIST_PAGE_SIZE = 20, CHAT_LIST_LIVE_COUNT, CHAT_INBOX_PING_PAGE_SIZE = 25, CHAT_INBOX_DISCOVERY_PARALLEL_CHATS, CHAT_INBOX_SETTLEMENT_PARALLEL_CHATS = 4, CHAT_INBOX_CURSOR_OVERLAP_MS, CHAT_LIST_CACHE_WRITE_DELAY_MS = 1500, CHAT_LIST_SNAPSHOT_COALESCE_MS = 80, CHAT_LIST_COMPLETE_SYNC_DELAY_MS = 250, CHAT_LIST_LISTENER_RETRY_MS = 1000, CHAT_TOP_WARM_COUNT = 0, CHAT_EAGER_WARM_COUNT = 0, CHAT_WARM_DELAY_MS = 3000, CHAT_WARM_BATCH_SIZE, CHAT_MESSAGE_VIEW_CACHE_SIZE = 30, CHAT_MEDIA_WARM_MESSAGES_PER_CHAT, CHAT_MEDIA_WARM_START_DELAY_MS = 600, CHAT_MEDIA_WARM_STEP_DELAY_MS = 120, CHAT_MEDIA_WARM_TYPES, CHAT_MEDIA_WARM_MAX_BYTES = 0, CHAT_READ_WRITE_INTERVAL_MS, CHAT_READ_WRITE_MAX_WAIT_MS, CHAT_LIVE_PING_INTERVAL_MS, CHAT_LIVE_SWEEP_INTERVAL_MS, CHAT_LIVE_STALE_AFTER_MS, CHAT_LIVE_RECONNECT_MAX_MS, CHAT_LIVE_TYPING_IDLE_MS, CHAT_LIVE_TYPING_RENEW_MS, CHAT_LIVE_COMPOSITION_HANDOFF_MS, CHAT_LIVE_READ_SEND_INTERVAL_MS = 120, CHAT_LIVE_READ_SEND_MAX_WAIT_MS = 500, CHAT_LIVE_READ_WRITE_INTERVAL_MS, CHAT_LIVE_READ_WRITE_MAX_WAIT_MS, CHAT_SEND_QUEUE_RATE_LIMIT_COUNT = 12, CHAT_SEND_QUEUE_RATE_LIMIT_WINDOW_MS, CHAT_SETTINGS_BODY_MAX_BYTES, CHAT_TITLE_STATE_MAX_CHARS = 128, CHAT_MANIFEST_MAX_BYTES, CHAT_RECEIPT_MAX_MEMBERS = 32, CHAT_ORDINARY_DELIVERY_MAX_MEMBERS = 128, CHAT_MAX_MEMBERS = 256, CHAT_MAX_TEXT_CHARS = 2048, CHAT_TITLE_INPUT_MAX_CHARS = 16, CHAT_MAX_REACTIONS, SEARCH_DEBOUNCE_MS = 300, SEARCH_USERNAME_LIMIT = 15, SEARCH_ROLE_LIMIT = 15, RECENT_PEER_REFRESH_LIMIT = 50, RECENT_PEER_REFRESH_DELAY_MS = 250, RECENT_PEER_REFRESH_INTERVAL_MS, RECENT_PEER_REFRESH_THROTTLE_MS = 120, BAN_REFRESH_GRACE_MS = 50, REQUEST_MONEY_MAX_SATS, WALLET_TRANSFER_POLL_MS, WALLET_ACTIVE_TRANSFER_REFRESH_MS, WALLET_IDLE_ACTIVE_TRANSFER_REFRESH_MS, WALLET_VISIBLE_TRANSFER_DISCOVERY_WINDOW_MS, WALLET_ACTIVE_TRANSFER_EMPTY_SCAN_LIMIT = 8, WALLET_CACHE_HYDRATE_DELAY_MS = 0, WALLET_BOOT_REFRESH_DELAY_MS = 500, WALLET_BOOT_CACHED_REFRESH_DELAY_MS = 2500, WALLET_REGTEST_DEPOSIT_CLAIM_POLL_MS, WALLET_MAINNET_DEPOSIT_CLAIM_POLL_MS, WALLET_BALANCE_EVENT_COALESCE_MS, WALLET_INCOMING_UPDATE_COALESCE_MS = 250, WALLET_AUTO_CLAIM_MAX_FEE_SATS = 5000, WALLET_CLAIM_PAGE_SIZE = 100, WALLET_PENDING_TRANSFER_CLAIM_BATCH_SIZE = 50, WALLET_PENDING_TRANSFER_STATUS_BATCH_SIZE = 2, WALLET_PENDING_TRANSFER_COLD_REFRESH_BATCH_SIZE = 50, WALLET_PENDING_TRANSFER_COLD_REFRESH_INTERVAL_MS, WALLET_PENDING_TRANSFER_ADAPTIVE_BATCH_SMALL_QUEUE = 3, WALLET_PENDING_TRANSFER_ADAPTIVE_BATCH_LARGE_QUEUE = 10, WALLET_PENDING_TRANSFER_ADAPTIVE_BATCH_SMALL_SIZE = 2, WALLET_PENDING_TRANSFER_ADAPTIVE_BATCH_LARGE_SIZE = 3, WALLET_PENDING_TRANSFER_SLOW_CLAIM_MS, WALLET_PENDING_TRANSFER_CLAIM_COOLDOWN_MS, WALLET_SDK_BACKGROUND_QUIET_MS, WALLET_RECENT_TRANSFER_LIMIT = 100, WALLET_TRANSFER_PAGE_LIMIT = 100, WALLET_TRANSFER_FETCH_THROTTLE_MS = 150, WALLET_PENDING_TRANSFER_CLAIM_RETRY_MS, WALLET_SENT_TRANSFER_REFRESH_DELAY_MS, WALLET_PENDING_TRANSFER_BOOT_GRACE_MS, WALLET_PENDING_TRANSFER_HOT_AGE_MS, WALLET_PENDING_TRANSFER_WARM_AGE_MS, WALLET_PENDING_TRANSFER_WARM_RETRY_MS, WALLET_PENDING_TRANSFER_STALE_RETRY_MS, WALLET_PENDING_TRANSFER_STUCK_RETRY_MS, WALLET_PENDING_TRANSFER_DORMANT_RETRY_MS, WALLET_TRANSFER_CACHE_WRITE_DELAY_MS;
6128
+ var MS_PER_SECOND = 1000, MINUTE_MS, HOUR_MS, DAY_MS, KIB_BYTES = 1024, MIB_BYTES, SATS_PER_BITCOIN = 100000000n, USERNAME_MAX_CHARS = 12, PASSWORD_MIN_CHARS = 15, PASSWORD_MAX_CHARS = 64, PASSWORD_MAX_BYTES, AUTOLOCK_MIN_MINUTES = 1, AUTOLOCK_MAX_MINUTES = 60, LOCAL_CACHE_WRITE_DELAY_MS = 350, LOCAL_MEDIA_CACHE_MAX_BYTES, LOCAL_MEDIA_CACHE_MAX_ITEMS = 1000, LOCAL_MEDIA_ACCESS_TOUCH_MIN_MS, LOCAL_PROFILE_CACHE_MAX_ITEMS = 500, LOCAL_PROFILE_CACHE_MAX_AGE_MS, LOCAL_CHAT_CACHE_MAX_ITEMS = 1000, LOCAL_CHAT_MESSAGE_CACHE_MAX_VISIBLE = 1000, LOCAL_CHAT_MESSAGE_CACHE_WRITE_DELAY_MS = 2500, LOCAL_AVATAR_CACHE_MAX_BYTES, LOCAL_AVATAR_CACHE_MAX_AGE_MS, AVATAR_IMAGE_MAX_BYTES, AVATAR_IMAGE_QUALITY_ATTEMPTS, CHAT_AVATAR_IMAGE_MAX_BYTES, CHAT_AVATAR_REF_MAX_CHARS = 256, CHAT_MESSAGE_FILE_CACHE_MAX_BYTES, IDLE_CALLBACK_MIN_TIMEOUT_MS = 50, ATTACHMENT_CACHE_IDLE_TIMEOUT_MS = 2500, ATTACHMENT_CACHE_FALLBACK_DELAY_MS = 250, CHAT_UNSAVED_TTL_DAYS = 21, CHAT_UNSAVED_TTL_MS, CHAT_AFTER_SEEN_MS, CHAT_MEDIA_TTL_DAYS, CHAT_MEDIA_TTL_MS, CHAT_UPLOAD_MAX_BYTES, CHAT_AUDIO_TRANSCODE_BITRATE_BPS = 128000, CHAT_VIDEO_TRANSCODE_VIDEO_BITRATE_BPS = 3000000, CHAT_VIDEO_TRANSCODE_AUDIO_BITRATE_BPS, CHAT_MESSAGE_BATCH_SIZE = 40, CHAT_MESSAGE_QUERY_MAX_DOCS = 120, CHAT_MESSAGE_MUTATION_MAX_ITEMS = 256, CHAT_TTL_CLIENT_DELETE_GRACE_MS, CHAT_BATCH_CLEANUP_IDLE_TIMEOUT_MS = 1500, CHAT_BATCH_CLEANUP_IDLE_DELAY_MS = 250, CHAT_LIST_PAGE_SIZE = 20, CHAT_LIST_LIVE_COUNT, CHAT_INBOX_PING_PAGE_SIZE = 25, CHAT_INBOX_DISCOVERY_PARALLEL_CHATS, CHAT_INBOX_SETTLEMENT_PARALLEL_CHATS = 4, CHAT_INBOX_CURSOR_OVERLAP_MS, CHAT_LIST_CACHE_WRITE_DELAY_MS = 1500, CHAT_LIST_SNAPSHOT_COALESCE_MS = 80, CHAT_LIST_COMPLETE_SYNC_DELAY_MS = 250, CHAT_LIST_LISTENER_RETRY_MS = 1000, CHAT_TOP_WARM_COUNT = 0, CHAT_EAGER_WARM_COUNT = 0, CHAT_WARM_DELAY_MS = 3000, CHAT_WARM_BATCH_SIZE, CHAT_MESSAGE_VIEW_CACHE_SIZE = 30, CHAT_MEDIA_WARM_MESSAGES_PER_CHAT, CHAT_MEDIA_WARM_START_DELAY_MS = 600, CHAT_MEDIA_WARM_STEP_DELAY_MS = 120, CHAT_MEDIA_WARM_TYPES, CHAT_MEDIA_WARM_MAX_BYTES = 0, CHAT_READ_WRITE_INTERVAL_MS, CHAT_READ_WRITE_MAX_WAIT_MS, CHAT_LIVE_PING_INTERVAL_MS, CHAT_LIVE_SWEEP_INTERVAL_MS, CHAT_LIVE_STALE_AFTER_MS, CHAT_LIVE_RECONNECT_MAX_MS, CHAT_LIVE_TYPING_IDLE_MS, CHAT_LIVE_TYPING_RENEW_MS, CHAT_LIVE_COMPOSITION_HANDOFF_MS, CHAT_LIVE_READ_SEND_INTERVAL_MS = 120, CHAT_LIVE_READ_SEND_MAX_WAIT_MS = 500, CHAT_LIVE_READ_WRITE_INTERVAL_MS, CHAT_LIVE_READ_WRITE_MAX_WAIT_MS, CHAT_SEND_QUEUE_RATE_LIMIT_COUNT = 12, CHAT_SEND_QUEUE_RATE_LIMIT_WINDOW_MS, CHAT_SETTINGS_BODY_MAX_BYTES, CHAT_TITLE_STATE_MAX_CHARS = 128, CHAT_MANIFEST_MAX_BYTES, CHAT_RECEIPT_MAX_MEMBERS = 32, CHAT_ORDINARY_DELIVERY_MAX_MEMBERS = 128, CHAT_MAX_MEMBERS = 256, CHAT_MAX_TEXT_CHARS = 2048, CHAT_TITLE_INPUT_MAX_CHARS = 16, CHAT_MAX_REACTIONS, SEARCH_DEBOUNCE_MS = 300, SEARCH_USERNAME_LIMIT = 15, SEARCH_ROLE_LIMIT = 15, RECENT_PEER_REFRESH_LIMIT = 50, RECENT_PEER_REFRESH_DELAY_MS = 250, RECENT_PEER_REFRESH_INTERVAL_MS, RECENT_PEER_REFRESH_THROTTLE_MS = 120, BAN_REFRESH_GRACE_MS = 50, REQUEST_MONEY_MAX_SATS, WALLET_TRANSFER_POLL_MS, WALLET_ACTIVE_TRANSFER_REFRESH_MS, WALLET_CACHE_HYDRATE_DELAY_MS = 0, WALLET_BOOT_REFRESH_DELAY_MS = 500, WALLET_BOOT_CACHED_REFRESH_DELAY_MS = 2500, WALLET_REGTEST_DEPOSIT_CLAIM_POLL_MS, WALLET_MAINNET_DEPOSIT_CLAIM_POLL_MS, WALLET_BALANCE_EVENT_COALESCE_MS, WALLET_INCOMING_UPDATE_COALESCE_MS = 250, WALLET_AUTO_CLAIM_MAX_FEE_SATS = 5000, WALLET_CLAIM_PAGE_SIZE = 100, WALLET_PENDING_TRANSFER_CLAIM_BATCH_SIZE = 50, WALLET_PENDING_TRANSFER_STATUS_BATCH_SIZE = 2, WALLET_PENDING_TRANSFER_COLD_REFRESH_BATCH_SIZE = 50, WALLET_PENDING_TRANSFER_COLD_REFRESH_INTERVAL_MS, WALLET_PENDING_TRANSFER_ADAPTIVE_BATCH_SMALL_QUEUE = 3, WALLET_PENDING_TRANSFER_ADAPTIVE_BATCH_LARGE_QUEUE = 10, WALLET_PENDING_TRANSFER_ADAPTIVE_BATCH_SMALL_SIZE = 2, WALLET_PENDING_TRANSFER_ADAPTIVE_BATCH_LARGE_SIZE = 3, WALLET_PENDING_TRANSFER_SLOW_CLAIM_MS, WALLET_PENDING_TRANSFER_CLAIM_COOLDOWN_MS, WALLET_SDK_BACKGROUND_QUIET_MS, WALLET_RECENT_TRANSFER_LIMIT = 100, WALLET_TRANSFER_PAGE_LIMIT = 100, WALLET_TRANSFER_FETCH_THROTTLE_MS = 150, WALLET_PENDING_TRANSFER_CLAIM_RETRY_MS, WALLET_SENT_TRANSFER_REFRESH_DELAY_MS, WALLET_PENDING_TRANSFER_BOOT_GRACE_MS, WALLET_PENDING_TRANSFER_HOT_AGE_MS, WALLET_PENDING_TRANSFER_WARM_AGE_MS, WALLET_PENDING_TRANSFER_WARM_RETRY_MS, WALLET_PENDING_TRANSFER_STALE_RETRY_MS, WALLET_PENDING_TRANSFER_STUCK_RETRY_MS, WALLET_PENDING_TRANSFER_DORMANT_RETRY_MS, WALLET_TRANSFER_CACHE_WRITE_DELAY_MS;
6129
6129
  var init_config = __esm(() => {
6130
6130
  MINUTE_MS = 60 * MS_PER_SECOND;
6131
6131
  HOUR_MS = 60 * MINUTE_MS;
@@ -6173,8 +6173,6 @@ var init_config = __esm(() => {
6173
6173
  REQUEST_MONEY_MAX_SATS = SATS_PER_BITCOIN * 100000n;
6174
6174
  WALLET_TRANSFER_POLL_MS = 3 * MS_PER_SECOND;
6175
6175
  WALLET_ACTIVE_TRANSFER_REFRESH_MS = MS_PER_SECOND;
6176
- WALLET_IDLE_ACTIVE_TRANSFER_REFRESH_MS = 5 * MS_PER_SECOND;
6177
- WALLET_VISIBLE_TRANSFER_DISCOVERY_WINDOW_MS = 12 * MS_PER_SECOND;
6178
6176
  WALLET_REGTEST_DEPOSIT_CLAIM_POLL_MS = 20 * MS_PER_SECOND;
6179
6177
  WALLET_MAINNET_DEPOSIT_CLAIM_POLL_MS = MINUTE_MS;
6180
6178
  WALLET_BALANCE_EVENT_COALESCE_MS = 2 * MS_PER_SECOND;
@@ -12540,12 +12538,16 @@ function projectRequestPayment(requestValue, paymentValue) {
12540
12538
  if (!requester || !payer || requester === payer || requestNetwork(requestValue) !== requestNetwork(paymentValue)) {
12541
12539
  return requestValue;
12542
12540
  }
12543
- const payments = normalizedPayments(requestValue);
12541
+ const progress = getRequestProgress(requestValue);
12542
+ const amount = positiveSats(paymentValue.a);
12543
+ if (progress.paid !== 0n || amount !== progress.requested) {
12544
+ return requestValue;
12545
+ }
12546
+ const payments = progress.payments;
12544
12547
  const tx = cleanText(paymentValue.tx);
12545
12548
  if (payments.some((payment) => payment.tx === tx)) {
12546
12549
  return requestValue;
12547
12550
  }
12548
- const amount = positiveSats(paymentValue.a);
12549
12551
  return {
12550
12552
  ...requestValue,
12551
12553
  payments: [...payments, {
@@ -13030,7 +13032,7 @@ function applyMessageActions(messages) {
13030
13032
  const index2 = target ? indexByKey.get(target) : null;
13031
13033
  const base = index2 != null ? out[index2] : null;
13032
13034
  const actionMembers = [...new Set((Array.isArray(msg?.epochMemberChatPKs) ? msg.epochMemberChatPKs : []).map(cleanText).filter(Boolean))];
13033
- const authorized = base?.t === "req" && isRequestPayment(msg) && actionMembers.includes(cleanText(base.s)) && actionMembers.includes(cleanText(msg.s));
13035
+ const authorized = base?.t === "req" && isRequestPayment(msg) && msg?.failed !== true && actionMembers.includes(cleanText(base.s)) && actionMembers.includes(cleanText(msg.s));
13034
13036
  if (authorized) {
13035
13037
  const next = projectRequestPayment(base, msg);
13036
13038
  const projected = isHeldSourceGoneMsg(base) ? holdSourceGoneVisibleMsg(next) : next;
@@ -20237,7 +20239,19 @@ ${cid}` : "";
20237
20239
  if (!chat || !options?.epochState || !options?.ownEntry)
20238
20240
  throw makeChatUnavailableError();
20239
20241
  const chatId = chat.chatId;
20240
- const { cid, local } = makeLocalMessage(chatId, chatPK, peerChatPK, message);
20242
+ const epochManifest = options.epochState?.manifest;
20243
+ const actionOp = cleanText(options.actionOp);
20244
+ const actionTarget3 = cleanText(options.actionTarget);
20245
+ const localMessage = {
20246
+ ...message,
20247
+ ...actionOp ? { actionOp } : {},
20248
+ ...actionTarget3 ? { actionTarget: actionTarget3 } : {},
20249
+ ...epochManifest?.epochId ? { epochId: epochManifest.epochId } : {},
20250
+ ...Array.isArray(epochManifest?.members) ? {
20251
+ epochMemberChatPKs: epochManifest.members.map((member) => cleanText(member?.chatPK)).filter(Boolean)
20252
+ } : {}
20253
+ };
20254
+ const { cid, local } = makeLocalMessage(chatId, chatPK, peerChatPK, localMessage);
20241
20255
  selectLocalChat?.(peerChatPK, chatId);
20242
20256
  if (hasSentLocalCid(chatId, cid)) {
20243
20257
  local.pending = false;
@@ -31892,6 +31906,8 @@ function createChatSave({ cloud, media = {}, chatBanned, localCache, getOwnerCha
31892
31906
  try {
31893
31907
  const targetEpochId = list[0]?.epochId || mutationOptions(chatId).epochState.manifest.epochId;
31894
31908
  const updated = await makeMsgPermanent(cloud, targetEpochId, list, mutationOptions(chatId));
31909
+ if (updated !== list.length)
31910
+ throw makeMessageSaveUnavailableError();
31895
31911
  return { updated, ttl: null };
31896
31912
  } catch (error) {
31897
31913
  throw normalizeMessageSaveError(error);
@@ -33256,7 +33272,20 @@ function createChatSession({
33256
33272
  const target = typeof request2 === "string" ? request2.trim() : messageRef(request2);
33257
33273
  if (!target)
33258
33274
  throw new Error("payment request target required");
33259
- return pendingOwner.sendChatMessage(chatId, makeRequestPayment(payment.amountSats, payment.tx, payment.network), {
33275
+ const batch = messageBatchOwner.getMessageBatch(chatId);
33276
+ const requestMessage = request2 && typeof request2 === "object" ? request2 : [...batch?.messages || [], ...batch?.sourceMessages || []].find((message) => message?.t === "req" && messageRef(message) === target);
33277
+ if (!requestMessage || requestMessage.t !== "req")
33278
+ throw new Error("payment request not found");
33279
+ if (cleanText(requestMessage.s || requestMessage.from) === chatPK)
33280
+ throw new Error("cannot pay your own request");
33281
+ const requestProgress = getRequestProgress(requestMessage);
33282
+ if (requestProgress.fulfilled || requestProgress.paid !== 0n)
33283
+ throw new Error("payment request already paid");
33284
+ const confirmation = makeRequestPayment(payment.amountSats, payment.tx, payment.network);
33285
+ if (requestNetwork(requestMessage) !== requestNetwork(confirmation) || BigInt(confirmation.a) !== requestProgress.requested) {
33286
+ throw new Error("payment must fulfill the request");
33287
+ }
33288
+ return pendingOwner.sendChatMessage(chatId, confirmation, {
33260
33289
  actionOp: CHAT_ACTION_OPS.PAY_CONFIRM,
33261
33290
  actionTarget: target,
33262
33291
  updatePreview: true
@@ -37340,9 +37369,18 @@ function createPeerList({ peerApi, diag, onMissingPeers }) {
37340
37369
  return subscriberCount > 0;
37341
37370
  }
37342
37371
  function beginSubscription() {
37343
- if (!subscriberCount)
37372
+ const firstSubscriber = !subscriberCount;
37373
+ if (firstSubscriber)
37344
37374
  lifecycle += 1;
37345
37375
  subscriberCount += 1;
37376
+ if (!firstSubscriber)
37377
+ return;
37378
+ const becameReady = startProfileLoad();
37379
+ if (becameReady) {
37380
+ rebuild({ base: true });
37381
+ } else {
37382
+ scheduleRefresh();
37383
+ }
37346
37384
  }
37347
37385
  function endSubscription() {
37348
37386
  subscriberCount = Math.max(0, subscriberCount - 1);
@@ -40346,23 +40384,18 @@ function createWalletPolling({ wallet, network, appState, getTransferState, getB
40346
40384
  let activeRefreshPromise = null;
40347
40385
  let pendingPollPromise = null;
40348
40386
  let activeRefreshLastAt = 0;
40349
- let activeRefreshEmptyScanCount = 0;
40350
- let activeTransferHotUntilMs = 0;
40387
+ let transferDiscoveryVisible = false;
40351
40388
  let closed = false;
40352
40389
  const depositClaimRate = getDepositClaimPollMs(network);
40353
40390
  const activeRefreshPollMs = Math.max(500, Number(activeTransferRefreshMs) || ACTIVE_TRANSFER_REFRESH_RATE);
40354
- const activeRefreshIdlePollMs = Math.max(activeRefreshPollMs, Number(IDLE_ACTIVE_TRANSFER_REFRESH_RATE) || activeRefreshPollMs);
40355
- const activeRefreshEmptyScanLimit = Math.max(1, Number(ACTIVE_TRANSFER_EMPTY_SCAN_LIMIT) || 1);
40356
40391
  const isActive = () => !appState?.currentState || appState.currentState === "active";
40357
40392
  const isTxReady = () => getTransferState().txReady === true && getBalanceState().balanceReady === true;
40358
40393
  const hasActivePendingClaim = () => getTransferState().hasActivePendingClaim?.() === true;
40359
- const hasFastActiveRefreshWork = () => activeTransferHotUntilMs > Date.now() || hasActivePendingClaim();
40394
+ const hasFastActiveRefreshWork = () => transferDiscoveryVisible || hasActivePendingClaim();
40360
40395
  const activeRefreshDue = () => {
40361
- if (hasActivePendingClaim()) {
40362
- return true;
40363
- }
40364
- const delayMs = hasFastActiveRefreshWork() || activeRefreshEmptyScanCount < activeRefreshEmptyScanLimit ? activeRefreshPollMs : activeRefreshIdlePollMs;
40365
- return !activeRefreshLastAt || Date.now() - activeRefreshLastAt >= delayMs;
40396
+ if (!hasFastActiveRefreshWork())
40397
+ return false;
40398
+ return hasActivePendingClaim() || !activeRefreshLastAt || Date.now() - activeRefreshLastAt >= activeRefreshPollMs;
40366
40399
  };
40367
40400
  const runActiveRefresh = (reason = "active-poll") => {
40368
40401
  if (closed || !wallet || !isActive()) {
@@ -40375,16 +40408,8 @@ function createWalletPolling({ wallet, network, appState, getTransferState, getB
40375
40408
  activeRefreshLastAt = Date.now();
40376
40409
  const transferState = getTransferState();
40377
40410
  const transfers = typeof transferState.claimPendingIncomingTransfers === "function" ? await transferState.claimPendingIncomingTransfers(reason) : [];
40378
- if (Array.isArray(transfers) && transfers.length) {
40379
- activeRefreshEmptyScanCount = 0;
40380
- } else if (hasActivePendingClaim()) {
40381
- activeRefreshEmptyScanCount = 0;
40382
- } else {
40383
- activeRefreshEmptyScanCount += 1;
40384
- }
40385
- const visibleHot = activeTransferHotUntilMs > Date.now();
40386
40411
  const claimActive = hasActivePendingClaim();
40387
- if (isTxReady() && typeof transferState.refreshPendingTransfers === "function" && !visibleHot && !claimActive) {
40412
+ if (isTxReady() && typeof transferState.refreshPendingTransfers === "function" && !transferDiscoveryVisible && !claimActive) {
40388
40413
  transferState.refreshPendingTransfers(null, { cold: true, reason });
40389
40414
  }
40390
40415
  return transfers;
@@ -40403,12 +40428,16 @@ function createWalletPolling({ wallet, network, appState, getTransferState, getB
40403
40428
  activeRefreshInterval = null;
40404
40429
  };
40405
40430
  const runObservedActiveRefresh = () => {
40431
+ if (!hasFastActiveRefreshWork()) {
40432
+ stopActiveRefreshPoll();
40433
+ return;
40434
+ }
40406
40435
  if (activeRefreshDue()) {
40407
40436
  runActiveRefresh();
40408
40437
  }
40409
40438
  };
40410
40439
  const startActiveRefreshPoll = () => {
40411
- if (closed || !appState || activeRefreshInterval || !wallet || !isActive() || typeof getTransferState().claimPendingIncomingTransfers !== "function") {
40440
+ if (closed || !appState || activeRefreshInterval || !wallet || !isActive() || !hasFastActiveRefreshWork() || typeof getTransferState().claimPendingIncomingTransfers !== "function") {
40412
40441
  return;
40413
40442
  }
40414
40443
  markDiag(diag, "wallet.pendingTxs.active.start", {});
@@ -40418,6 +40447,7 @@ function createWalletPolling({ wallet, network, appState, getTransferState, getB
40418
40447
  }
40419
40448
  runObservedActiveRefresh();
40420
40449
  }, activeRefreshPollMs);
40450
+ runObservedActiveRefresh();
40421
40451
  };
40422
40452
  const runPendingPoll = () => {
40423
40453
  if (pendingPollPromise) {
@@ -40455,7 +40485,7 @@ function createWalletPolling({ wallet, network, appState, getTransferState, getB
40455
40485
  stopActiveRefreshPoll();
40456
40486
  return;
40457
40487
  }
40458
- if (isActive()) {
40488
+ if (isActive() && hasFastActiveRefreshWork()) {
40459
40489
  startActiveRefreshPoll();
40460
40490
  } else {
40461
40491
  stopActiveRefreshPoll();
@@ -40466,17 +40496,19 @@ function createWalletPolling({ wallet, network, appState, getTransferState, getB
40466
40496
  stopPoll();
40467
40497
  }
40468
40498
  };
40469
- const requestTransferDiscoveryHotWindow = ({ durationMs = WALLET_VISIBLE_TRANSFER_DISCOVERY_WINDOW_MS } = {}) => {
40470
- const windowMs = Math.max(0, Number(durationMs) || WALLET_VISIBLE_TRANSFER_DISCOVERY_WINDOW_MS);
40471
- activeTransferHotUntilMs = Math.max(activeTransferHotUntilMs, Date.now() + windowMs);
40472
- if (isActive()) {
40473
- startActiveRefreshPoll();
40474
- }
40499
+ const setTransferDiscoveryVisible = (visible) => {
40500
+ const next = visible === true;
40501
+ if (transferDiscoveryVisible === next)
40502
+ return;
40503
+ transferDiscoveryVisible = next;
40504
+ if (next)
40505
+ activeRefreshLastAt = 0;
40506
+ sync();
40475
40507
  };
40476
40508
  const appStateSubscription = appState?.addEventListener?.("change", (nextState2) => {
40477
40509
  if (nextState2 === "active") {
40478
- startActiveRefreshPoll();
40479
40510
  runActiveRefresh("focus");
40511
+ startActiveRefreshPoll();
40480
40512
  if (getTransferState().hasPendingTxs) {
40481
40513
  startPoll();
40482
40514
  runPendingPoll();
@@ -40494,7 +40526,7 @@ function createWalletPolling({ wallet, network, appState, getTransferState, getB
40494
40526
  }, depositClaimRate);
40495
40527
  sync();
40496
40528
  return {
40497
- requestTransferDiscoveryHotWindow,
40529
+ setTransferDiscoveryVisible,
40498
40530
  stopPoll,
40499
40531
  sync,
40500
40532
  close() {
@@ -40608,15 +40640,13 @@ function createWalletReadyDiag({ wallet, getBalanceState, getTransferState, diag
40608
40640
  }
40609
40641
  };
40610
40642
  }
40611
- var POLL_TXS_RATE, ACTIVE_TRANSFER_REFRESH_RATE, IDLE_ACTIVE_TRANSFER_REFRESH_RATE, ACTIVE_TRANSFER_EMPTY_SCAN_LIMIT, BOOT_REFRESH_DELAY_MS, BOOT_CACHED_REFRESH_DELAY_MS, BOOT_CACHE_DECISION_DELAY_MS, BALANCE_EVENT_COALESCE_MS, INCOMING_UPDATE_COALESCE_MS, WALLET_EVENTS;
40643
+ var POLL_TXS_RATE, ACTIVE_TRANSFER_REFRESH_RATE, BOOT_REFRESH_DELAY_MS, BOOT_CACHED_REFRESH_DELAY_MS, BOOT_CACHE_DECISION_DELAY_MS, BALANCE_EVENT_COALESCE_MS, INCOMING_UPDATE_COALESCE_MS, WALLET_EVENTS;
40612
40644
  var init_lifecycle = __esm(() => {
40613
40645
  init_config();
40614
40646
  init_network();
40615
40647
  init_async();
40616
40648
  POLL_TXS_RATE = WALLET_TRANSFER_POLL_MS;
40617
40649
  ACTIVE_TRANSFER_REFRESH_RATE = WALLET_ACTIVE_TRANSFER_REFRESH_MS;
40618
- IDLE_ACTIVE_TRANSFER_REFRESH_RATE = WALLET_IDLE_ACTIVE_TRANSFER_REFRESH_MS;
40619
- ACTIVE_TRANSFER_EMPTY_SCAN_LIMIT = WALLET_ACTIVE_TRANSFER_EMPTY_SCAN_LIMIT;
40620
40650
  BOOT_REFRESH_DELAY_MS = WALLET_BOOT_REFRESH_DELAY_MS;
40621
40651
  BOOT_CACHED_REFRESH_DELAY_MS = WALLET_BOOT_CACHED_REFRESH_DELAY_MS;
40622
40652
  BOOT_CACHE_DECISION_DELAY_MS = BOOT_REFRESH_DELAY_MS + Math.max(0, WALLET_CACHE_HYDRATE_DELAY_MS) + 250;
@@ -43082,7 +43112,7 @@ function createEmptyWalletSessionSnapshot(network, transferSnapshot = null, cach
43082
43112
  isWalletDataReady: false,
43083
43113
  isWalletDataLoaded: cachedDataReady,
43084
43114
  refresh: ASYNC_NOOP,
43085
- requestTransferDiscoveryHotWindow: NOOP5,
43115
+ setTransferDiscoveryVisible: NOOP5,
43086
43116
  claimDeposits: ASYNC_FALSE,
43087
43117
  getFundingAddress: ASYNC_NOOP,
43088
43118
  preparePayment: WALLET_NOT_READY,
@@ -43258,7 +43288,7 @@ function createWalletSession({
43258
43288
  isWalletDataReady: true,
43259
43289
  isWalletDataLoaded: balanceState.balanceReady || currentTransferState.txReady,
43260
43290
  refresh: claims.refresh,
43261
- requestTransferDiscoveryHotWindow: polling.requestTransferDiscoveryHotWindow,
43291
+ setTransferDiscoveryVisible: polling.setTransferDiscoveryVisible,
43262
43292
  claimDeposits: claims.claimDeposits,
43263
43293
  getFundingAddress: funding.getFundingAddress,
43264
43294
  preparePayment: mutationActions.preparePayment,
@@ -56266,9 +56296,12 @@ function createRuntimeMoneyActions({ getRuntime, getSession, resolvePeer, chat }
56266
56296
  const progress = getRequestProgress(message);
56267
56297
  if (progress.fulfilled)
56268
56298
  throw new Error("payment request already fulfilled");
56269
- const amountSats = cleanPositiveSats(options.amountSats ?? progress.remaining);
56270
- if (BigInt(amountSats) > progress.remaining)
56271
- throw new Error("payment exceeds request remainder");
56299
+ if (progress.paid !== 0n)
56300
+ throw new Error("payment request already paid");
56301
+ const amountSats = cleanPositiveSats(progress.requested);
56302
+ if (options.amountSats != null && BigInt(cleanPositiveSats(options.amountSats)) !== progress.requested) {
56303
+ throw new Error("payment must fulfill the request");
56304
+ }
56272
56305
  const requesterChatPK = cleanText(message.s || message.from);
56273
56306
  let profile = runtime.peers.getSnapshot().peerByChatPK.get(requesterChatPK) || null;
56274
56307
  if (!profile)
@@ -56390,7 +56423,7 @@ var package_default;
56390
56423
  var init_package2 = __esm(() => {
56391
56424
  package_default = {
56392
56425
  name: "veyl",
56393
- version: "0.66.0",
56426
+ version: "0.66.2",
56394
56427
  packageManager: "bun@1.4.0",
56395
56428
  private: true,
56396
56429
  license: "UNLICENSED",
package/package.json CHANGED
@@ -42,5 +42,5 @@
42
42
  "start": "node src/cli.js",
43
43
  "lint": "eslint src --quiet"
44
44
  },
45
- "version": "0.66.0"
45
+ "version": "0.66.2"
46
46
  }