@glyphteck/veyl 0.1.1 → 0.2.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.
Files changed (4) hide show
  1. package/README.md +46 -4
  2. package/dist/cli.js +3013 -406
  3. package/dist/index.js +2800 -383
  4. package/package.json +1 -1
package/dist/cli.js CHANGED
@@ -92156,6 +92156,9 @@ var WALLET_IDLE_ACTIVE_TRANSFER_REFRESH_MS = 5 * MS_PER_SECOND;
92156
92156
  var WALLET_VISIBLE_TRANSFER_DISCOVERY_WINDOW_MS = 12 * MS_PER_SECOND;
92157
92157
  var WALLET_REGTEST_DEPOSIT_CLAIM_POLL_MS = 20 * MS_PER_SECOND;
92158
92158
  var WALLET_BALANCE_EVENT_COALESCE_MS = 2 * MS_PER_SECOND;
92159
+ var WALLET_AUTO_CLAIM_MAX_FEE_SATS = 5000;
92160
+ var WALLET_CLAIM_PAGE_SIZE = 100;
92161
+ var WALLET_PENDING_TRANSFER_CLAIM_BATCH_SIZE = 50;
92159
92162
  var WALLET_PENDING_TRANSFER_COLD_REFRESH_INTERVAL_MS = 15 * MS_PER_SECOND;
92160
92163
  var WALLET_PENDING_TRANSFER_SLOW_CLAIM_MS = 4 * MS_PER_SECOND;
92161
92164
  var WALLET_PENDING_TRANSFER_CLAIM_COOLDOWN_MS = 15 * MS_PER_SECOND;
@@ -92214,6 +92217,7 @@ var HIDDEN_CHECKPOINT_MSG_TYPE = "hid";
92214
92217
  var DELETE_MSG_TYPE = "del";
92215
92218
  var SYSTEM_MSG_TYPE = "sys";
92216
92219
  var SYSTEM_RETENTION_KIND = "retention";
92220
+ var DEFAULT_REACTION_EMOJI = "\u2764\uFE0F";
92217
92221
  var HOLD_VISIBLE_KEY = "__holdVisible";
92218
92222
 
92219
92223
  // ../../shared/chat/messages/actions.js
@@ -92460,6 +92464,17 @@ function hasStoredFileRef(msg) {
92460
92464
  return false;
92461
92465
  }
92462
92466
  }
92467
+ function hasChatMediaFileRef(msg) {
92468
+ if (!hasText(msg?.p) || !hasText(msg?.k) || hasLocalFileRef(msg)) {
92469
+ return false;
92470
+ }
92471
+ try {
92472
+ getChatMediaFileRef(msg.p);
92473
+ return true;
92474
+ } catch {
92475
+ return false;
92476
+ }
92477
+ }
92463
92478
  function hasFileRef(msg) {
92464
92479
  return hasLocalFileRef(msg) || hasStoredFileRef(msg);
92465
92480
  }
@@ -92496,6 +92511,12 @@ function getMessageOrderMs(message) {
92496
92511
  }
92497
92512
 
92498
92513
  // ../../shared/chat/messagekeys.js
92514
+ function keySet(value) {
92515
+ if (value instanceof Set) {
92516
+ return value;
92517
+ }
92518
+ return new Set(Array.isArray(value) ? value.filter(Boolean) : []);
92519
+ }
92499
92520
  function messageKeys(message) {
92500
92521
  if (typeof message === "string") {
92501
92522
  const key = cleanText(message);
@@ -92548,10 +92569,20 @@ function targetMessageMs(target, byKey) {
92548
92569
 
92549
92570
  // ../../shared/chat/messages/control.js
92550
92571
  var retainedMessageCache = new WeakMap;
92572
+ function cleanReactionEmoji(value) {
92573
+ const emoji = cleanText(value);
92574
+ return emoji || DEFAULT_REACTION_EMOJI;
92575
+ }
92551
92576
  function cleanTarget(value) {
92552
92577
  const target = typeof value === "object" && value ? getMessageKey(value) : value;
92553
92578
  return cleanText(target);
92554
92579
  }
92580
+ function cleanTargetFrom(target, fallback) {
92581
+ if (typeof target === "object" && target) {
92582
+ return cleanText(target.from) || cleanText(target.s) || cleanText(fallback);
92583
+ }
92584
+ return cleanText(fallback);
92585
+ }
92555
92586
  function isPeerMsg(msg, chatPK) {
92556
92587
  const sender = cleanText(msg?.s);
92557
92588
  const user = cleanText(chatPK);
@@ -92577,6 +92608,20 @@ function makeReadReceipt(target) {
92577
92608
  function isReadReceiptMsg(msg) {
92578
92609
  return msg?.t === READ_RECEIPT_MSG_TYPE && hasText(msg.upto);
92579
92610
  }
92611
+ function makeReaction(target, emoji = DEFAULT_REACTION_EMOJI, options = {}) {
92612
+ const nextTarget = cleanTarget(target);
92613
+ if (!nextTarget) {
92614
+ throw new Error("reaction target required");
92615
+ }
92616
+ const nextEmoji = emoji == null ? "" : cleanReactionEmoji(emoji);
92617
+ const targetFrom = cleanTargetFrom(target, options?.targetFrom);
92618
+ return {
92619
+ t: REACTION_MSG_TYPE,
92620
+ target: nextTarget,
92621
+ ...targetFrom ? { targetFrom } : {},
92622
+ ...nextEmoji ? { emoji: nextEmoji } : {}
92623
+ };
92624
+ }
92580
92625
  function isReactionMsg(msg) {
92581
92626
  return msg?.t === REACTION_MSG_TYPE && hasText(msg.target) && (msg.emoji == null || hasText(msg.emoji));
92582
92627
  }
@@ -92586,9 +92631,23 @@ function isHiddenCheckpointMsg(msg) {
92586
92631
  function deleteActionTarget(msg) {
92587
92632
  return cleanText(msg?.actionTarget) || cleanText(msg?.target) || cleanText(msg?.id);
92588
92633
  }
92634
+ function makeDeleteMsg(target) {
92635
+ const nextTarget = cleanTarget(target);
92636
+ if (!nextTarget) {
92637
+ throw new Error("delete target required");
92638
+ }
92639
+ return { t: DELETE_MSG_TYPE, target: nextTarget };
92640
+ }
92589
92641
  function isDeleteMsg(msg) {
92590
92642
  return (msg?.t === DELETE_MSG_TYPE || cleanText(msg?.actionOp) === CHAT_ACTION_OPS.DELETE) && hasText(deleteActionTarget(msg));
92591
92643
  }
92644
+ function makeRetentionSystemMsg(retention) {
92645
+ return {
92646
+ t: SYSTEM_MSG_TYPE,
92647
+ sys: SYSTEM_RETENTION_KIND,
92648
+ retention: cleanChatRetention(retention)
92649
+ };
92650
+ }
92592
92651
  function isSystemMsg(msg) {
92593
92652
  return msg?.t === SYSTEM_MSG_TYPE && msg?.sys === SYSTEM_RETENTION_KIND && !!getSystemMsgText(msg);
92594
92653
  }
@@ -93023,6 +93082,16 @@ function withCachedMessageRetention(msg, retention) {
93023
93082
  }
93024
93083
 
93025
93084
  // ../../shared/chat/messages/compose.js
93085
+ function setReply(msg, replyId) {
93086
+ const nextReplyId = String(replyId ?? "").trim();
93087
+ if (!nextReplyId) {
93088
+ return { ...msg || {} };
93089
+ }
93090
+ return {
93091
+ ...msg || {},
93092
+ r: nextReplyId
93093
+ };
93094
+ }
93026
93095
  function makeReq(amount) {
93027
93096
  const a = String(amount ?? "").trim();
93028
93097
  if (!a) {
@@ -93096,6 +93165,12 @@ function canRenderReactionPreview(preview) {
93096
93165
  function canRenderChatPreview(preview) {
93097
93166
  return !!preview && (canRenderPreviewContent(preview) || hasChatPreviewActivity(preview) || isReadReceiptMsg(preview) || canRenderReactionPreview(preview));
93098
93167
  }
93168
+ function getChatPreviewSourceKey(preview) {
93169
+ return cleanText(preview?.sourceKey) || cleanText(getMessageKey(preview));
93170
+ }
93171
+ function getChatPreviewSourceTs(preview) {
93172
+ return timestampMs(preview?.sourceTs, null, { positive: true }) ?? timestampMs(preview?.ts, null, { positive: true }) ?? getMessageOrderMs(preview);
93173
+ }
93099
93174
  function getChatPreviewActivityAt(preview) {
93100
93175
  return timestampMs(preview?.activity?.at, null, { positive: true });
93101
93176
  }
@@ -93106,6 +93181,93 @@ function chatPreviewActivityKind(preview) {
93106
93181
  function hasChatPreviewActivity(preview) {
93107
93182
  return !!chatPreviewActivityKind(preview) && getChatPreviewActivityAt(preview) != null;
93108
93183
  }
93184
+ function chatPreviewActivityOnly(preview) {
93185
+ if (!hasChatPreviewActivity(preview)) {
93186
+ return null;
93187
+ }
93188
+ const kind = chatPreviewActivityKind(preview);
93189
+ const sourceKey = getChatPreviewSourceKey(preview);
93190
+ const sourceTs = getChatPreviewSourceTs(preview);
93191
+ const sender = cleanText(preview?.from || preview?.s);
93192
+ const activityAt = getChatPreviewActivityAt(preview);
93193
+ const activityBy = cleanText(preview?.activity?.by);
93194
+ return {
93195
+ ...sender ? { s: sender, from: sender } : {},
93196
+ ...sourceKey ? { sourceKey } : {},
93197
+ ...Number.isFinite(sourceTs) ? { sourceTs, ts: sourceTs } : {},
93198
+ activity: {
93199
+ kind,
93200
+ at: activityAt,
93201
+ ...activityBy ? { by: activityBy } : {}
93202
+ }
93203
+ };
93204
+ }
93205
+ function isChatPreviewActivityOnly(preview) {
93206
+ return hasChatPreviewActivity(preview) && !canRenderPreviewContent(preview) && !isReadReceiptMsg(preview) && !isReactionMsg(preview);
93207
+ }
93208
+ function withChatPreviewActivity(preview, activity = {}) {
93209
+ if (!preview || typeof preview !== "object" || Array.isArray(preview)) {
93210
+ return null;
93211
+ }
93212
+ const kind = cleanText(activity.kind);
93213
+ const at = timestampMs(activity.at, null, { positive: true });
93214
+ if (!CHAT_PREVIEW_ACTIVITY_KINDS.has(kind) || at == null) {
93215
+ return preview;
93216
+ }
93217
+ const by = cleanText(activity.by);
93218
+ const sourceKey = cleanText(activity.sourceKey) || getChatPreviewSourceKey(preview);
93219
+ const sourceTs = timestampMs(activity.sourceTs, null, { positive: true }) ?? getChatPreviewSourceTs(preview);
93220
+ const contentUntil = timestampMs(activity.contentUntil, null, { positive: true });
93221
+ const { activity: _oldActivity, contentUntil: _oldContentUntil, sourceKey: _oldSourceKey, sourceTs: _oldSourceTs, ...rest } = preview;
93222
+ return {
93223
+ ...rest,
93224
+ ...sourceKey ? { sourceKey } : {},
93225
+ ...Number.isFinite(sourceTs) ? { sourceTs } : {},
93226
+ ...contentUntil != null ? { contentUntil } : {},
93227
+ activity: {
93228
+ kind,
93229
+ at,
93230
+ ...by ? { by } : {}
93231
+ }
93232
+ };
93233
+ }
93234
+ function withChatPreviewOpened(preview, target, openedAt, by) {
93235
+ if (!preview || !target) {
93236
+ return null;
93237
+ }
93238
+ const keys = collectMessageKeys(target);
93239
+ if (!chatPreviewHasKey(preview, keys)) {
93240
+ return null;
93241
+ }
93242
+ const at = timestampMs(openedAt, null, { positive: true });
93243
+ if (at == null) {
93244
+ return null;
93245
+ }
93246
+ return chatPreviewActivityOnly(withChatPreviewActivity(preview, {
93247
+ kind: CHAT_PREVIEW_ACTIVITY_OPENED,
93248
+ at,
93249
+ by,
93250
+ sourceKey: getChatPreviewSourceKey(preview),
93251
+ sourceTs: getChatPreviewSourceTs(preview)
93252
+ }));
93253
+ }
93254
+ function withChatPreviewDeleted(preview, target, deletedAt, by) {
93255
+ if (!preview || !target || isChatPreviewActivityOnly(preview)) {
93256
+ return null;
93257
+ }
93258
+ const keys = collectMessageKeys(target);
93259
+ if (!chatPreviewHasKey(preview, keys)) {
93260
+ return null;
93261
+ }
93262
+ const at = timestampMs(deletedAt, Date.now(), { positive: true });
93263
+ return chatPreviewActivityOnly(withChatPreviewActivity(preview, {
93264
+ kind: CHAT_PREVIEW_ACTIVITY_DELETED,
93265
+ at,
93266
+ by,
93267
+ sourceKey: getChatPreviewSourceKey(preview),
93268
+ sourceTs: getChatPreviewSourceTs(preview)
93269
+ }));
93270
+ }
93109
93271
  function chatPreviewWantsAttention(preview, chatPK) {
93110
93272
  if (!preview || fromSelf(preview, chatPK)) {
93111
93273
  return false;
@@ -93119,6 +93281,32 @@ function chatPreviewWantsAttention(preview, chatPK) {
93119
93281
  }
93120
93282
  return canRenderPreviewContent(preview);
93121
93283
  }
93284
+ function previewActionTargetsKey(message, key) {
93285
+ const targetKey = cleanText(key);
93286
+ if (!targetKey || !isReadReceiptMsg(message) && !isReactionMsg(message)) {
93287
+ return false;
93288
+ }
93289
+ return [message?.target, message?.upto, message?.actionTarget].map(cleanText).some((target) => target === targetKey);
93290
+ }
93291
+ function chatPreviewHasKey(preview, keys) {
93292
+ const nextKeys = keySet(keys);
93293
+ if (!preview || !nextKeys.size) {
93294
+ return false;
93295
+ }
93296
+ if (messageHasKey(preview, nextKeys)) {
93297
+ return true;
93298
+ }
93299
+ const sourceKey = getChatPreviewSourceKey(preview);
93300
+ if (sourceKey && nextKeys.has(sourceKey)) {
93301
+ return true;
93302
+ }
93303
+ for (const key of nextKeys) {
93304
+ if (previewActionTargetsKey(preview, key)) {
93305
+ return true;
93306
+ }
93307
+ }
93308
+ return false;
93309
+ }
93122
93310
 
93123
93311
  // ../../shared/chat/attachments.js
93124
93312
  "use client";
@@ -93226,6 +93414,19 @@ function canonicalChatVersions(chats) {
93226
93414
  return sortChats([...byVersion.values(), ...unkeyed]);
93227
93415
  }
93228
93416
 
93417
+ // ../../shared/utils/diagnostics.js
93418
+ function markDiag(diag, label, data) {
93419
+ try {
93420
+ diag?.(label, data);
93421
+ } catch {}
93422
+ }
93423
+ function markDone(diag, label, startedAt, data = {}) {
93424
+ markDiag(diag, `${label}.done`, { ...data, elapsedMs: Date.now() - startedAt });
93425
+ }
93426
+ function markError(diag, label, startedAt, error, data = {}) {
93427
+ markDiag(diag, `${label}.error`, { ...data, elapsedMs: Date.now() - startedAt, code: error?.code || "", message: error?.message || String(error) });
93428
+ }
93429
+
93229
93430
  // ../../shared/crypto/sign.js
93230
93431
  "use client";
93231
93432
  var CHAT_ACTOR_SIGN_SCOPE = "chat-actor-sign-v2";
@@ -93598,7 +93799,7 @@ var MAX_PAIR_CACHE = CHAT_PAIR_CACHE_LIMIT;
93598
93799
  function getChatPairKey(chatPK, peerChatPK, chatId = "") {
93599
93800
  if (!chatPK || !peerChatPK)
93600
93801
  return null;
93601
- return `${orderChatKeys(chatPK, peerChatPK).join("|")}|${cleanText(chatId)}`;
93802
+ return `${cleanText(chatPK)}|${cleanText(peerChatPK)}|${cleanText(chatId)}`;
93602
93803
  }
93603
93804
  async function getCachedPair(chatPK, chatPrivKey, peerChatPK, options = {}) {
93604
93805
  const chatId = cleanText(options?.chatId);
@@ -93802,6 +94003,44 @@ async function sealPing(senderChatPK, senderPrivKey, recipientChatPK, fields = {
93802
94003
  cleanBytes(eph?.priv, shared, key);
93803
94004
  }
93804
94005
  }
94006
+ async function openPing(chatPK, chatPrivKey, ping) {
94007
+ if (ping?.v !== CHAT_PING_VERSION || !ping?.epk || !ping?.body) {
94008
+ throw new Error("invalid chat ping");
94009
+ }
94010
+ let linkPair = null;
94011
+ const priv = toBytes32(chatPrivKey, "chat private key");
94012
+ const epk = cleanText(ping.epk);
94013
+ const shared = x25519.getSharedSecret(priv, fromHex(epk, "chat ping public key"));
94014
+ const key = deriveKey2(shared.subarray(0, 32), "chat-inbox-ping-v1", [epk, chatPK]);
94015
+ try {
94016
+ const { nonce, ct } = unpackBodyData(ping.body);
94017
+ const payload = await openJson(key, nonce, ct, canonicalBytes({ v: CHAT_PING_VERSION, epk }, "chat ping aad"));
94018
+ const senderChatPK = cleanText(payload?.senderChatPK);
94019
+ if (!senderChatPK || payload?.v !== CHAT_PING_VERSION || payload?.protocol !== CHAT_PROTOCOL_VERSION) {
94020
+ throw new Error("invalid chat ping payload");
94021
+ }
94022
+ linkPair = await openChatPair(chatPK, chatPrivKey, senderChatPK);
94023
+ if (payload.linkId !== linkPair.linkId || payload.proof !== pingProof(linkPair.linkRoot, payload)) {
94024
+ throw new Error("invalid chat ping proof");
94025
+ }
94026
+ const pair = await openChatPair(chatPK, chatPrivKey, senderChatPK, { chatId: payload.chatId });
94027
+ if (!pair?.chatId || !pair?.actor?.publicKey) {
94028
+ closeChatPair(pair);
94029
+ throw new Error("invalid chat ping chat");
94030
+ }
94031
+ return {
94032
+ pair,
94033
+ payload: {
94034
+ ...payload,
94035
+ senderChatPK,
94036
+ actorPK: cleanText(payload.actorPK)
94037
+ }
94038
+ };
94039
+ } finally {
94040
+ closeChatPair(linkPair);
94041
+ cleanBytes(shared, key);
94042
+ }
94043
+ }
93805
94044
 
93806
94045
  // ../../shared/chat/messages/write.js
93807
94046
  function makeTtlMs(value) {
@@ -93987,6 +94226,106 @@ async function sendReadReceipt(cloud, senderPubkey, senderPrivkey, receiverChatP
93987
94226
  };
93988
94227
  return sendMsg(cloud, senderPubkey, senderPrivkey, receiverChatPK, receipt, { ...options, updatePreview: false, ping: options?.ping !== false, pingKind: "read" });
93989
94228
  }
94229
+ async function sendReaction(cloud, senderPubkey, senderPrivkey, receiverChatPK, target, emoji, options = {}) {
94230
+ const reaction = {
94231
+ ...makeReaction(target, emoji),
94232
+ cid: makeCid(),
94233
+ s: senderPubkey
94234
+ };
94235
+ const addedReaction = cleanText(reaction.emoji);
94236
+ return sendMsg(cloud, senderPubkey, senderPrivkey, receiverChatPK, reaction, addedReaction ? { ...options, updatePreview: true } : { ...options, updatePreview: false, ping: false });
94237
+ }
94238
+ async function sendDeleteAction(cloud, senderPubkey, senderPrivkey, receiverChatPK, target, options = {}) {
94239
+ const deleteTarget = cleanText(target);
94240
+ if (!deleteTarget) {
94241
+ throw new Error("delete target required");
94242
+ }
94243
+ const deletion = {
94244
+ ...makeDeleteMsg(deleteTarget),
94245
+ cid: makeCid(),
94246
+ s: senderPubkey
94247
+ };
94248
+ return sendMsg(cloud, senderPubkey, senderPrivkey, receiverChatPK, deletion, { ...options, updatePreview: false, ping: options?.ping !== false, pingKind: "delete" });
94249
+ }
94250
+ function messageMutationItems(messages, { allowString = false, include = () => true } = {}) {
94251
+ const seen = new Set;
94252
+ const list = Array.isArray(messages) ? messages : [messages];
94253
+ const items = [];
94254
+ for (const message of list || []) {
94255
+ const stringMessage = typeof message === "string";
94256
+ const id = stringMessage ? allowString ? cleanText(message) : "" : cleanText(message?.id);
94257
+ if (!id || id.startsWith("local:") || seen.has(id) || message?.pending || message?.failed || !include(message)) {
94258
+ continue;
94259
+ }
94260
+ seen.add(id);
94261
+ const mediaRef = !stringMessage && hasChatMediaFileRef(message) ? getChatMediaFileRef(message.p) : null;
94262
+ items.push({
94263
+ id,
94264
+ cid: cleanText(message?.cid),
94265
+ mediaKey: mediaRef?.mediaId || "",
94266
+ mediaPath: mediaRef ? cleanText(message.p) : ""
94267
+ });
94268
+ }
94269
+ return items;
94270
+ }
94271
+ function messageDeleteItems(messages) {
94272
+ return messageMutationItems(messages, { allowString: true });
94273
+ }
94274
+ function messagePermanentUpdateItems(messages) {
94275
+ return messageMutationItems(messages, { include: (message) => message?.ttl != null });
94276
+ }
94277
+ function messageTemporaryUpdateItems(messages) {
94278
+ return messageMutationItems(messages, { include: (message) => message?.ttl == null });
94279
+ }
94280
+ async function makeMsgTemporary(cloud, chatId, messages, ttlMs = newMessageTtlMs()) {
94281
+ const nextTtlMs = makeTtlMs(ttlMs);
94282
+ const items = messageTemporaryUpdateItems(messages);
94283
+ if (!cloud || !chatId || !nextTtlMs || !items.length) {
94284
+ return 0;
94285
+ }
94286
+ if (typeof cloud.chat?.messages?.ttl !== "function") {
94287
+ throw new Error("message ttl unavailable");
94288
+ }
94289
+ const result = await cloud.chat.messages.ttl(chatId, items, { permanent: false, ttlMs: nextTtlMs });
94290
+ return Number.isFinite(result?.updated) ? result.updated : items.length;
94291
+ }
94292
+ async function makeMsgPermanent(cloud, chatId, messages) {
94293
+ const items = messagePermanentUpdateItems(messages);
94294
+ if (!cloud || !chatId || !items.length) {
94295
+ return 0;
94296
+ }
94297
+ if (typeof cloud.chat?.messages?.ttl !== "function") {
94298
+ throw new Error("message ttl unavailable");
94299
+ }
94300
+ const result = await cloud.chat.messages.ttl(chatId, items, { permanent: true });
94301
+ return Number.isFinite(result?.updated) ? result.updated : items.length;
94302
+ }
94303
+ async function setChatRetention(cloud, chatId, senderPubkey, senderPrivkey, peerChatPK, retention, options = {}) {
94304
+ if (!senderPubkey || !senderPrivkey || !peerChatPK) {
94305
+ throw new Error("vault locked");
94306
+ }
94307
+ const nextRetention = cleanChatRetention(retention);
94308
+ const pair = await getCachedPair(senderPubkey, senderPrivkey, peerChatPK, { chatId });
94309
+ if (chatId && pair.chatId !== chatId) {
94310
+ throw new Error("chat mismatch");
94311
+ }
94312
+ const systemMessage = {
94313
+ ...makeRetentionSystemMsg(nextRetention),
94314
+ cid: makeCid(),
94315
+ s: senderPubkey
94316
+ };
94317
+ await sendMsg(cloud, senderPubkey, senderPrivkey, peerChatPK, systemMessage, {
94318
+ chatId,
94319
+ linkId: pair.linkId,
94320
+ updatePreview: true,
94321
+ retention: nextRetention,
94322
+ chatExists: true,
94323
+ senderUid: options?.senderUid,
94324
+ ownEntry: options?.ownEntry,
94325
+ chatSettings: { retention: nextRetention }
94326
+ });
94327
+ return nextRetention;
94328
+ }
93990
94329
  async function updateMsg(cloud, chatId, msgId, senderPubkey, senderPrivkey, receiverChatPK, newMessage, options = {}) {
93991
94330
  if (!senderPubkey || !senderPrivkey)
93992
94331
  throw new Error("vault locked");
@@ -94034,6 +94373,31 @@ async function updateMsg(cloud, chatId, msgId, senderPubkey, senderPrivkey, rece
94034
94373
  preview
94035
94374
  };
94036
94375
  }
94376
+ async function deleteMsg(cloud, chatId, messageOrId, senderPubkey, senderPrivkey, peerChatPK, options = {}) {
94377
+ if (!cloud || !chatId || !messageOrId || !senderPubkey || !senderPrivkey || !peerChatPK) {
94378
+ return false;
94379
+ }
94380
+ const pair = await getCachedPair(senderPubkey, senderPrivkey, peerChatPK, { chatId });
94381
+ if (pair.chatId !== chatId) {
94382
+ return false;
94383
+ }
94384
+ const item = messageDeleteItems([messageOrId])[0];
94385
+ const target = cleanText(options?.docId) || cleanText(item?.id);
94386
+ if (!target || target.startsWith("local:")) {
94387
+ return false;
94388
+ }
94389
+ const deleteTarget = cleanText(options?.target) || cleanText(getMessageKey(messageOrId)) || target;
94390
+ await sendDeleteAction(cloud, senderPubkey, senderPrivkey, peerChatPK, deleteTarget, {
94391
+ chatId,
94392
+ linkId: options?.linkId,
94393
+ messageId: cleanText(options?.deleteActionId),
94394
+ senderUid: options?.senderUid
94395
+ });
94396
+ await cloud.chat.messages.delete(chatId, target, {
94397
+ mediaPaths: item?.mediaPath ? [item.mediaPath] : []
94398
+ });
94399
+ return true;
94400
+ }
94037
94401
 
94038
94402
  // ../../shared/chat/actions/send.js
94039
94403
  "use client";
@@ -94113,6 +94477,7 @@ function normalizeDecryptedMsg(msgData, message) {
94113
94477
  }
94114
94478
  const normalized = {
94115
94479
  ...message,
94480
+ id: message.id || msgData?.id || null,
94116
94481
  ts: msgData?.ts ?? null,
94117
94482
  ttl: msgData?.ttl ?? null
94118
94483
  };
@@ -94134,6 +94499,299 @@ async function decryptMsg(msgData, userChatPK, userPrivKey, peerChatPK, options
94134
94499
  }
94135
94500
  }
94136
94501
 
94502
+ // ../../shared/chat/inbox.js
94503
+ var CHAT_PING_KIND_READ = "read";
94504
+ var CHAT_PING_KIND_DELETE = "delete";
94505
+ function normalizeChatPreview(msgData, message) {
94506
+ if (!message || typeof message !== "object") {
94507
+ return null;
94508
+ }
94509
+ const normalized = {
94510
+ ...message,
94511
+ ts: msgData?.ts ?? null,
94512
+ ttl: msgData?.ttl ?? null
94513
+ };
94514
+ return canRenderChatPreview(normalized) ? normalized : null;
94515
+ }
94516
+ async function readExistingEntry(cloud, uid, userPrivKey, entryId) {
94517
+ const entry = await cloud.user.chats.read(uid, entryId).catch(() => null);
94518
+ if (!entry) {
94519
+ return null;
94520
+ }
94521
+ return openOwnChatEntry(userPrivKey, entryId, entry.body).catch(() => null);
94522
+ }
94523
+ function pingTsMs(ping, preview, fallbackMs) {
94524
+ const ms = timestampMs(ping?.payload?.ts, null) ?? timestampMs(preview?.ts, null) ?? fallbackMs;
94525
+ return Number.isFinite(ms) ? ms : Date.now();
94526
+ }
94527
+ function pingSortMs(pingDoc, ping) {
94528
+ const payloadMs = Number(ping?.payload?.ts);
94529
+ if (Number.isFinite(payloadMs)) {
94530
+ return payloadMs;
94531
+ }
94532
+ return timestampMs(pingDoc?.ts, 0) ?? 0;
94533
+ }
94534
+ function pingKind(ping) {
94535
+ return cleanText(ping?.payload?.kind);
94536
+ }
94537
+ function isReadPing(ping) {
94538
+ return pingKind(ping) === CHAT_PING_KIND_READ;
94539
+ }
94540
+ function isDeletePing(ping) {
94541
+ return pingKind(ping) === CHAT_PING_KIND_DELETE;
94542
+ }
94543
+ function pingActors(ping, existing) {
94544
+ return {
94545
+ ...existing?.actors || {},
94546
+ [ping.pair.chatPK]: ping.pair.actor.publicKey,
94547
+ [ping.payload.senderChatPK]: ping.payload.actorPK
94548
+ };
94549
+ }
94550
+ function chatFromPing(ping, entryId, existing, preview, userChatPK, ms) {
94551
+ const ts = timestampMs(ms, null) ?? timestampMs(existing?.ts, null) ?? timestampMs(preview?.ts, null) ?? 0;
94552
+ if (!ts) {
94553
+ return null;
94554
+ }
94555
+ const visiblePreview = preview || existing?.preview || null;
94556
+ const readMs = timestampMs(existing?.readMs, null);
94557
+ return {
94558
+ protocol: CHAT_PROTOCOL_VERSION,
94559
+ id: ping.pair.chatId,
94560
+ linkId: ping.pair.linkId,
94561
+ entryId,
94562
+ peerChatPK: ping.payload.senderChatPK,
94563
+ peerUid: existing?.peerUid || cleanText(ping.payload.senderUid) || null,
94564
+ actors: pingActors(ping, existing),
94565
+ settings: existing?.settings,
94566
+ saved: existing?.saved || null,
94567
+ readMs,
94568
+ preview: visiblePreview,
94569
+ ts,
94570
+ unseen: visiblePreview ? isChatUnseenForUser({ preview: visiblePreview, readMs }, userChatPK) : false
94571
+ };
94572
+ }
94573
+ async function resolvePingUid(cloud, payload) {
94574
+ const senderChatPK = cleanText(payload?.senderChatPK);
94575
+ const claimedUid = cleanText(payload?.senderUid);
94576
+ if (!cloud || !senderChatPK) {
94577
+ return null;
94578
+ }
94579
+ if (claimedUid) {
94580
+ const peer2 = await cloud.peer.read(claimedUid).catch(() => null);
94581
+ if (cleanText(peer2?.chatPK) !== senderChatPK) {
94582
+ throw new Error("ping sender uid mismatch");
94583
+ }
94584
+ return claimedUid;
94585
+ }
94586
+ const peer = await cloud.search.peer.byChatPK(senderChatPK).catch(() => null);
94587
+ return peer?.uid || null;
94588
+ }
94589
+ async function readPingMsg(cloud, userChatPK, userPrivKey, ping, actors, options = {}) {
94590
+ const chatId = ping?.pair?.chatId;
94591
+ const messageId = cleanText(ping?.payload?.messageId);
94592
+ const peerChatPK = cleanText(ping?.payload?.senderChatPK);
94593
+ if (!cloud || !chatId || !messageId || !userChatPK || !userPrivKey || !peerChatPK) {
94594
+ return null;
94595
+ }
94596
+ const data = await cloud.chat.messages.read(chatId, messageId).catch(() => null);
94597
+ if (!data) {
94598
+ return null;
94599
+ }
94600
+ const message = await decryptMsg(data, userChatPK, userPrivKey, peerChatPK, { actors, chatId }).catch(() => null);
94601
+ const normalized = message ? { ...message, id: data.id, ts: data.ts ?? message.ts, ttl: data.ttl ?? message.ttl } : null;
94602
+ if (options.raw === true) {
94603
+ return normalized;
94604
+ }
94605
+ const preview = normalizeChatPreview(data, normalized);
94606
+ return preview && canRenderChatPreview(preview) ? preview : null;
94607
+ }
94608
+ async function savePing(cloud, uid, userChatPK, userPrivKey, ping, options = {}) {
94609
+ const chatId = ping?.pair?.chatId;
94610
+ if (!chatId || !cleanText(ping?.payload?.actorPK) || !cleanText(ping?.payload?.senderChatPK)) {
94611
+ return false;
94612
+ }
94613
+ const entryId = ownChatEntryId(userPrivKey, chatId);
94614
+ const existing = options.existing || await readExistingEntry(cloud, uid, userPrivKey, entryId);
94615
+ const peerUid = options.peerUid || await resolvePingUid(cloud, ping.payload);
94616
+ const actors = options.actors || pingActors(ping, existing);
94617
+ const hasPreview = Object.prototype.hasOwnProperty.call(options, "preview");
94618
+ const preview = hasPreview ? options.preview : await readPingMsg(cloud, userChatPK, userPrivKey, ping, actors);
94619
+ const entry = makeOwnChatEntry(ping.pair, {
94620
+ peerUid: peerUid || existing?.peerUid,
94621
+ peerActorPK: ping.payload.actorPK || existing?.actors?.[ping.payload.senderChatPK],
94622
+ actors,
94623
+ settings: existing?.settings,
94624
+ preview: preview || existing?.preview,
94625
+ readMs: existing?.readMs
94626
+ });
94627
+ const body = await sealOwnChatEntry(userPrivKey, entryId, entry);
94628
+ const record = { body };
94629
+ if (options.writeTs !== false) {
94630
+ record.tsMs = timestampMs(options.tsMs, null) ?? pingTsMs(ping, preview, Date.now());
94631
+ }
94632
+ await cloud.user.chats.write(uid, entryId, record);
94633
+ return true;
94634
+ }
94635
+ function chatWithReadPreview(existing, preview, userChatPK) {
94636
+ if (!existing?.id || !preview) {
94637
+ return null;
94638
+ }
94639
+ return {
94640
+ ...existing,
94641
+ preview,
94642
+ unseen: isChatUnseenForUser({ preview, readMs: existing.readMs }, userChatPK)
94643
+ };
94644
+ }
94645
+ function patchReadPingPreview(existing, receiptPreview, userChatPK) {
94646
+ if (!existing?.preview || !isReadReceiptMsg(receiptPreview)) {
94647
+ return null;
94648
+ }
94649
+ return withChatPreviewOpened(existing.preview, receiptPreview, receiptPreview?.ts, receiptPreview?.from || receiptPreview?.s, userChatPK);
94650
+ }
94651
+ function deletePingTarget(preview) {
94652
+ return cleanText(preview?.actionTarget) || cleanText(preview?.target) || cleanText(preview?.id);
94653
+ }
94654
+ function patchDeletePingPreview(existing, deletePreview) {
94655
+ if (!existing?.preview || !isDeleteMsg(deletePreview)) {
94656
+ return null;
94657
+ }
94658
+ const target = deletePingTarget(deletePreview);
94659
+ return withChatPreviewDeleted(existing.preview, target, deletePreview?.ts, deletePreview?.from || deletePreview?.s);
94660
+ }
94661
+ async function processInbox(cloud, uid, userChatPK, userPrivKey, options = {}) {
94662
+ if (!cloud || !uid || !userChatPK || !userPrivKey) {
94663
+ return false;
94664
+ }
94665
+ const inboxItems = await cloud.inbox.list(uid).catch(() => null);
94666
+ if (!inboxItems?.length) {
94667
+ return false;
94668
+ }
94669
+ const chatsById = new Map((options.currentChats || []).map((chat) => [chat.id, chat]));
94670
+ const opened = [];
94671
+ const invalidDocs = [];
94672
+ for (const pingDoc of inboxItems) {
94673
+ try {
94674
+ const ping = await openPing(userChatPK, userPrivKey, pingDoc);
94675
+ const chatId = ping?.pair?.chatId;
94676
+ if (!chatId) {
94677
+ invalidDocs.push(pingDoc);
94678
+ continue;
94679
+ }
94680
+ opened.push({ pingDoc, ping, chatId, ms: pingSortMs(pingDoc, ping) });
94681
+ } catch {
94682
+ invalidDocs.push(pingDoc);
94683
+ }
94684
+ }
94685
+ await Promise.all(invalidDocs.map((pingDoc) => cloud.inbox.delete(uid, pingDoc.id).catch(() => {})));
94686
+ const pingsByChat = new Map;
94687
+ for (const item of opened.sort((a, b) => a.ms - b.ms)) {
94688
+ let group = pingsByChat.get(item.chatId);
94689
+ if (!group) {
94690
+ group = {
94691
+ chatId: item.chatId,
94692
+ docs: [],
94693
+ message: null,
94694
+ read: null,
94695
+ delete: null
94696
+ };
94697
+ pingsByChat.set(item.chatId, group);
94698
+ }
94699
+ group.docs.push(item.pingDoc);
94700
+ if (isReadPing(item.ping)) {
94701
+ if (!group.read || item.ms > group.read.ms) {
94702
+ group.read = item;
94703
+ }
94704
+ } else if (isDeletePing(item.ping)) {
94705
+ if (!group.delete || item.ms > group.delete.ms) {
94706
+ group.delete = item;
94707
+ }
94708
+ } else if (!group.message || item.ms > group.message.ms) {
94709
+ group.message = item;
94710
+ }
94711
+ }
94712
+ const writes = await Promise.all([...pingsByChat.values()].map(async (group) => {
94713
+ try {
94714
+ let current = chatsById.get(group.chatId) || null;
94715
+ let wrote = false;
94716
+ let handled = false;
94717
+ if (group.message) {
94718
+ const item = group.message;
94719
+ const entryId = ownChatEntryId(userPrivKey, item.chatId);
94720
+ const actors = pingActors(item.ping, current);
94721
+ const existingMs = timestampMs(current?.preview?.ts, 0) ?? 0;
94722
+ const preview = existingMs >= item.ms ? current?.preview || null : await readPingMsg(cloud, userChatPK, userPrivKey, item.ping, actors);
94723
+ const chat = chatFromPing(item.ping, entryId, current, preview, userChatPK, item.ms);
94724
+ if (chat) {
94725
+ current = chat;
94726
+ chatsById.set(chat.id, chat);
94727
+ options.onPingChat?.(chat);
94728
+ await new Promise((resolve) => setTimeout(resolve, 0));
94729
+ }
94730
+ wrote = await savePing(cloud, uid, userChatPK, userPrivKey, item.ping, {
94731
+ existing: current,
94732
+ actors,
94733
+ preview
94734
+ });
94735
+ }
94736
+ if (group.read) {
94737
+ const item = group.read;
94738
+ const entryId = ownChatEntryId(userPrivKey, item.chatId);
94739
+ const existing = current || await readExistingEntry(cloud, uid, userPrivKey, entryId);
94740
+ const actors = pingActors(item.ping, existing);
94741
+ const receiptPreview = await readPingMsg(cloud, userChatPK, userPrivKey, item.ping, actors);
94742
+ const openedPreview = patchReadPingPreview(existing, receiptPreview, userChatPK);
94743
+ const chat = chatWithReadPreview(current, openedPreview, userChatPK);
94744
+ handled = true;
94745
+ if (openedPreview) {
94746
+ if (chat) {
94747
+ current = chat;
94748
+ chatsById.set(chat.id, chat);
94749
+ options.onPingChat?.(chat);
94750
+ }
94751
+ const writeExisting = chat || existing;
94752
+ wrote = await savePing(cloud, uid, userChatPK, userPrivKey, item.ping, {
94753
+ existing: writeExisting,
94754
+ actors,
94755
+ preview: openedPreview,
94756
+ writeTs: false
94757
+ }) || wrote;
94758
+ }
94759
+ }
94760
+ if (group.delete) {
94761
+ const item = group.delete;
94762
+ const entryId = ownChatEntryId(userPrivKey, item.chatId);
94763
+ const existing = current || await readExistingEntry(cloud, uid, userPrivKey, entryId);
94764
+ const actors = pingActors(item.ping, existing);
94765
+ const deletePreview = await readPingMsg(cloud, userChatPK, userPrivKey, item.ping, actors, { raw: true });
94766
+ const deletedPreview = patchDeletePingPreview(existing, deletePreview);
94767
+ const chat = deletedPreview ? chatFromPing(item.ping, entryId, current || existing, deletedPreview, userChatPK, item.ms) : null;
94768
+ handled = true;
94769
+ if (deletedPreview) {
94770
+ if (chat) {
94771
+ current = chat;
94772
+ chatsById.set(chat.id, chat);
94773
+ options.onPingChat?.(chat);
94774
+ }
94775
+ const writeExisting = chat || existing;
94776
+ wrote = await savePing(cloud, uid, userChatPK, userPrivKey, item.ping, {
94777
+ existing: writeExisting,
94778
+ actors,
94779
+ preview: deletedPreview
94780
+ }) || wrote;
94781
+ }
94782
+ }
94783
+ if (wrote || handled) {
94784
+ await Promise.all(group.docs.map((pingDoc) => cloud.inbox.delete(uid, pingDoc.id).catch(() => {})));
94785
+ }
94786
+ return wrote || handled;
94787
+ } catch (error) {
94788
+ options.onPingError?.(error, group);
94789
+ return false;
94790
+ }
94791
+ }));
94792
+ return writes.some(Boolean);
94793
+ }
94794
+
94137
94795
  // ../../shared/chat/list.js
94138
94796
  var CHAT_LIST_DECRYPT_YIELD_EVERY = 2;
94139
94797
  function chatDocDataEqual(a, b) {
@@ -94160,7 +94818,7 @@ function pruneChatStatusCache(statusCache, chats, now = Date.now()) {
94160
94818
  }
94161
94819
  }
94162
94820
  }
94163
- function normalizeChatPreview(msgData, message) {
94821
+ function normalizeChatPreview2(msgData, message) {
94164
94822
  if (!message || typeof message !== "object") {
94165
94823
  return null;
94166
94824
  }
@@ -94307,7 +94965,7 @@ async function decryptChatEntry(entryRecord, userChatPK, userPrivKey) {
94307
94965
  if (entry.protocol !== CHAT_PROTOCOL_VERSION) {
94308
94966
  return null;
94309
94967
  }
94310
- const preview = normalizeChatPreview({ ts: data?.ts ?? null, ttl: entry?.preview?.ttl ?? null }, entry?.preview);
94968
+ const preview = normalizeChatPreview2({ ts: data?.ts ?? null, ttl: entry?.preview?.ttl ?? null }, entry?.preview);
94311
94969
  const visiblePreview = preview && canRenderChatPreview(preview) ? preview : null;
94312
94970
  const ts = timestampMs(data?.ts, null) ?? 0;
94313
94971
  const readMs = timestampMs(entry.readMs, null);
@@ -94352,76 +95010,6 @@ async function readEntryResult(entryRecord, userChatPK, userPrivKey, cache) {
94352
95010
  }
94353
95011
  }
94354
95012
 
94355
- // ../../shared/wallet/keys.js
94356
- "use client";
94357
- var VALID_WALLET_NETWORKS = new Set(["MAINNET", "REGTEST", "TESTNET", "SIGNET", "LOCAL"]);
94358
- function normalizeWalletNetwork(network) {
94359
- const next = String(network ?? "").trim().toUpperCase();
94360
- if (!VALID_WALLET_NETWORKS.has(next)) {
94361
- throw new Error("invalid wallet network");
94362
- }
94363
- return next;
94364
- }
94365
- function walletPKField(network) {
94366
- return `walletPKs.${normalizeWalletNetwork(network)}`;
94367
- }
94368
- function resolveWalletPK(data, network) {
94369
- const key = normalizeWalletNetwork(network);
94370
- const walletPKs = data?.walletPKs;
94371
- const walletPK = walletPKs && typeof walletPKs === "object" && typeof walletPKs[key] === "string" ? walletPKs[key].trim() : "";
94372
- if (walletPK) {
94373
- return normalizeWalletPK(walletPK);
94374
- }
94375
- return null;
94376
- }
94377
- function normalizeWalletPK(walletPK) {
94378
- return typeof walletPK === "string" ? lowerText(walletPK) : walletPK;
94379
- }
94380
-
94381
- // ../../shared/wallet/spark.js
94382
- var import_bech32 = __toESM(require_dist(), 1);
94383
- var SPARK_ADDRESS_PREFIX = Object.freeze({
94384
- MAINNET: "spark",
94385
- TESTNET: "sparkt",
94386
- REGTEST: "sparkrt",
94387
- SIGNET: "sparks",
94388
- LOCAL: "sparkl"
94389
- });
94390
- function getSparkAddressPrefix(network) {
94391
- const prefix2 = SPARK_ADDRESS_PREFIX[String(network ?? "").toUpperCase()];
94392
- if (!prefix2) {
94393
- throw new Error("invalid wallet network");
94394
- }
94395
- return prefix2;
94396
- }
94397
- function hexToBytes5(hex3) {
94398
- const value = String(hex3 ?? "").trim();
94399
- if (value.length % 2 !== 0) {
94400
- throw new Error("invalid hex");
94401
- }
94402
- const bytes = new Uint8Array(value.length / 2);
94403
- for (let i = 0;i < bytes.length; i++) {
94404
- const start = i * 2;
94405
- const byte = Number.parseInt(value.slice(start, start + 2), 16);
94406
- if (Number.isNaN(byte)) {
94407
- throw new Error("invalid hex");
94408
- }
94409
- bytes[i] = byte;
94410
- }
94411
- return bytes;
94412
- }
94413
- function walletPKtoSparkAddress(walletPK, network) {
94414
- const key = hexToBytes5(walletPK);
94415
- if (key.length !== 33) {
94416
- throw new Error("need 33-byte compressed pubkey");
94417
- }
94418
- const payload = new Uint8Array(2 + key.length);
94419
- payload[0] = 10;
94420
- payload[1] = 33;
94421
- payload.set(key, 2);
94422
- return import_bech32.bech32m.encode(getSparkAddressPrefix(network), import_bech32.bech32m.toWords(payload), 1500);
94423
- }
94424
-
94425
95013
  // ../../shared/wallet/tx.js
94426
95014
  var TRANSFER_STATUS_COMPLETED = "TRANSFER_STATUS_COMPLETED";
94427
95015
  var TRANSFER_TYPE_BITCOIN_DEPOSIT = "BITCOIN_DEPOSIT";
@@ -94490,11 +95078,17 @@ function isVisibleTransferStatus(tx) {
94490
95078
  function isVisibleTransfer(tx) {
94491
95079
  return isVisibleTransferStatus(tx) && (isWalletTransfer(tx) || isFundingTransfer(tx) || isWithdrawalTransfer(tx));
94492
95080
  }
95081
+ function isClaimablePendingTransfer(tx, types = null) {
95082
+ if (Array.isArray(types) && types.length && !types.includes(tx?.type)) {
95083
+ return false;
95084
+ }
95085
+ return CLAIMABLE_TRANSFER_STATUSES.has(tx?.status) || CLAIMABLE_TRANSFER_STATUS_CODES.has(tx?.status);
95086
+ }
94493
95087
  function transferBelongsToWallet(tx, walletPK) {
94494
95088
  return !!walletPK && (sameText(tx?.senderIdentityPublicKey, walletPK) || sameText(tx?.receiverIdentityPublicKey, walletPK));
94495
95089
  }
94496
95090
 
94497
- // ../../shared/account/actions.js
95091
+ // ../../shared/account/actions/values.js
94498
95092
  var CHAT_PK_RE = /^[0-9a-f]{64}$/i;
94499
95093
  var WALLET_PK_RE = /^0[2-3][0-9a-f]{64}$/i;
94500
95094
  function cleanPeer(value) {
@@ -94551,9 +95145,6 @@ function timestampValue(value) {
94551
95145
  const parsed = Date.parse(value);
94552
95146
  return Number.isFinite(parsed) ? parsed : null;
94553
95147
  }
94554
- function messageDirection(message, chatPK) {
94555
- return isPeerMsg(message, chatPK) ? "peer" : "self";
94556
- }
94557
95148
  function requestRef(chatId, messageId) {
94558
95149
  return `${chatId}:${messageId}`;
94559
95150
  }
@@ -94570,6 +95161,23 @@ function parseRequestRef(value) {
94570
95161
  }
94571
95162
  return { chatId, messageId };
94572
95163
  }
95164
+ function requireCloud(value) {
95165
+ if (!value) {
95166
+ throw new Error("cloud required");
95167
+ }
95168
+ return value;
95169
+ }
95170
+ function requireSession(session) {
95171
+ if (!session?.uid || !session?.network || !session?.wallet || !session?.chatPK || !session?.chatPrivKey) {
95172
+ throw new Error("account session unlocked required");
95173
+ }
95174
+ return session;
95175
+ }
95176
+
95177
+ // ../../shared/account/actions/summary.js
95178
+ function messageDirection(message, chatPK) {
95179
+ return isPeerMsg(message, chatPK) ? "peer" : "self";
95180
+ }
94573
95181
  function simplifyAccountMessage(message, chat, chatPK, options = {}) {
94574
95182
  const type = message?.t || "unknown";
94575
95183
  const item = {
@@ -94583,11 +95191,13 @@ function simplifyAccountMessage(message, chat, chatPK, options = {}) {
94583
95191
  };
94584
95192
  if (type === "txt") {
94585
95193
  item.text = message.c || "";
95194
+ item.replyId = message.r || null;
94586
95195
  } else if (type === "req") {
94587
95196
  item.amountSats = Number(message.a || 0);
94588
95197
  item.paid = !!message.tx;
94589
95198
  item.txId = message.tx || null;
94590
95199
  item.requestId = message.id ? requestRef(chat?.id, message.id) : null;
95200
+ item.replyId = message.r || null;
94591
95201
  } else {
94592
95202
  item.payload = { ...message };
94593
95203
  }
@@ -94618,31 +95228,1672 @@ function simplifyAccountTransfer(tx) {
94618
95228
  receiverIdentityPublicKey: tx?.receiverIdentityPublicKey || null
94619
95229
  };
94620
95230
  }
94621
- function requireCloud(value) {
94622
- if (!value) {
94623
- throw new Error("cloud required");
95231
+
95232
+ // ../../shared/account/actions/chat.js
95233
+ function createChatActions({ readCloud, readSession, inbox, peers }) {
95234
+ function writeOptions(active, chat, options = {}) {
95235
+ return {
95236
+ ...options,
95237
+ chatId: chat.id,
95238
+ senderUid: active.uid,
95239
+ receiverUid: chat.peerUid,
95240
+ peerActorPK: chat.actors?.[chat.peerChatPK],
95241
+ ownEntry: chat.entryId ? chat : null,
95242
+ chatSettings: normalizeChatSettings(chat.settings)
95243
+ };
95244
+ }
95245
+ function requireRetention(value) {
95246
+ const retention2 = cleanText(value);
95247
+ if (!hasChatRetention(retention2)) {
95248
+ throw new Error(`retention must be ${CHAT_RETENTION_VALUES.join(" or ")}`);
95249
+ }
95250
+ return cleanChatRetention(retention2);
95251
+ }
95252
+ function withPeerProfile(chat, profile) {
95253
+ if (!chat || !profile) {
95254
+ return chat || null;
95255
+ }
95256
+ const peerChatPK = profile.chatPK || chat.peerChatPK;
95257
+ return {
95258
+ ...chat,
95259
+ peerChatPK,
95260
+ peerUid: profile.uid || chat.peerUid || null,
95261
+ actors: {
95262
+ ...chat.actors || {},
95263
+ ...peerChatPK && profile.actorPK ? { [peerChatPK]: profile.actorPK } : {}
95264
+ }
95265
+ };
95266
+ }
95267
+ async function list(options = {}) {
95268
+ const active = await readSession();
95269
+ const count = cleanLimit(options.count || options.limit, 30);
95270
+ const current = await inbox.load(active, count);
95271
+ const { chats } = await inbox.sync(active, current);
95272
+ const peerMap = await peers.mapForChats(chats);
95273
+ return chats.map((chat) => simplifyAccountChat(chat, peerMap.get(chat.peerChatPK)));
95274
+ }
95275
+ async function chatForPeer(peer, options = {}) {
95276
+ const active = await readSession();
95277
+ const current = await inbox.load(active, cleanLimit(options.count, 50));
95278
+ const { chats } = await inbox.sync(active, current);
95279
+ const value = String(peer ?? "").trim().toLowerCase();
95280
+ const chatByProfile = async (profile2) => {
95281
+ if (!profile2?.chatPK) {
95282
+ return null;
95283
+ }
95284
+ const chat = chats.find((chat2) => chat2.peerChatPK === profile2.chatPK);
95285
+ if (chat) {
95286
+ return withPeerProfile(chat, profile2);
95287
+ }
95288
+ const link = await resolvePeerChat(readCloud(), active.chatPK, active.chatPrivKey, profile2.chatPK, options).catch(() => null);
95289
+ if (!link?.chatId) {
95290
+ return null;
95291
+ }
95292
+ const linkedChat = await getChat(readCloud(), active.uid, link.chatId, active.chatPK, active.chatPrivKey).catch(() => null);
95293
+ return withPeerProfile(linkedChat, profile2);
95294
+ };
95295
+ if (CHAT_PK_RE.test(value)) {
95296
+ const chat = chats.find((item) => item.id === value || item.peerChatPK === value);
95297
+ if (chat) {
95298
+ return chat;
95299
+ }
95300
+ const profile2 = await peers.resolve(value).catch(() => null);
95301
+ const resolvedChat = await chatByProfile(profile2);
95302
+ if (resolvedChat) {
95303
+ return resolvedChat;
95304
+ }
95305
+ return getChat(readCloud(), active.uid, value, active.chatPK, active.chatPrivKey).catch(() => null);
95306
+ }
95307
+ const profile = await peers.resolve(peer);
95308
+ return chatByProfile(profile);
95309
+ }
95310
+ async function readDisplayMessages(active, chat, options = {}) {
95311
+ const page = await readCloud().chat.messages.list(chat.id, { count: cleanLimit(options.count || options.limit, 30) });
95312
+ const decrypted = [];
95313
+ for (const record of page.records || []) {
95314
+ const message = await decryptMsg(record, active.chatPK, active.chatPrivKey, chat.peerChatPK, {
95315
+ actors: chat.actors,
95316
+ chatId: chat.id
95317
+ });
95318
+ if (message) {
95319
+ decrypted.push(message);
95320
+ }
95321
+ }
95322
+ const display = getDisplayMessages(decrypted, active.chatPK, chat.peerChatPK).filter(canShowMsg);
95323
+ return { page, decrypted, display };
95324
+ }
95325
+ async function read(peer, options = {}) {
95326
+ const active = await readSession();
95327
+ const chat = await chatForPeer(peer, options);
95328
+ if (!chat) {
95329
+ return { chat: null, messages: [] };
95330
+ }
95331
+ const { page, display } = await readDisplayMessages(active, chat, options);
95332
+ const messages = display.map((message) => simplifyAccountMessage(message, chat, active.chatPK, options));
95333
+ if (options.markRead !== false) {
95334
+ const lastPeer = [...display].reverse().find((message) => isPeerMsg(message, active.chatPK));
95335
+ if (lastPeer?.id) {
95336
+ await setChatRead(readCloud(), active.uid, active.chatPrivKey, chat.id, lastPeer.ts).catch(() => {});
95337
+ const target = getMessageKey(lastPeer);
95338
+ if (target) {
95339
+ await sendReadReceipt(readCloud(), active.chatPK, active.chatPrivKey, chat.peerChatPK, target, {
95340
+ chatId: chat.id,
95341
+ senderUid: active.uid,
95342
+ receiverUid: chat.peerUid,
95343
+ linkId: chat.linkId,
95344
+ peerActorPK: chat.actors?.[chat.peerChatPK],
95345
+ ping: true
95346
+ }).catch(() => {});
95347
+ }
95348
+ }
95349
+ }
95350
+ return {
95351
+ chat: simplifyAccountChat(chat),
95352
+ messages,
95353
+ hasMore: page.hasMore === true,
95354
+ nextOlderThan: page.nextOlderThan || null
95355
+ };
95356
+ }
95357
+ async function messageForPeer(peer, messageId, options = {}) {
95358
+ const target = cleanText(messageId);
95359
+ if (!target) {
95360
+ throw new Error("message id required");
95361
+ }
95362
+ const active = await readSession();
95363
+ const chat = await chatForPeer(peer, options);
95364
+ if (!chat) {
95365
+ throw new Error("chat not found");
95366
+ }
95367
+ const { decrypted, display } = await readDisplayMessages(active, chat, { ...options, count: 100, limit: 100 });
95368
+ const messages = [...display, ...decrypted];
95369
+ const message = messages.find((item) => item?.id === target || item?.cid === target || getMessageKey(item) === target);
95370
+ if (message) {
95371
+ return { active, chat, message, target: getMessageKey(message) || target };
95372
+ }
95373
+ const record = await readCloud().chat.messages.read(chat.id, target).catch(() => null);
95374
+ const direct = record ? await decryptMsg(record, active.chatPK, active.chatPrivKey, chat.peerChatPK, {
95375
+ actors: chat.actors,
95376
+ chatId: chat.id
95377
+ }) : null;
95378
+ if (!direct) {
95379
+ throw new Error("message not found");
95380
+ }
95381
+ return { active, chat, message: direct, target: getMessageKey(direct) || target };
95382
+ }
95383
+ async function targetForPeer(peer, messageId, options = {}) {
95384
+ try {
95385
+ return await messageForPeer(peer, messageId, options);
95386
+ } catch (error) {
95387
+ if (error?.message !== "message not found") {
95388
+ throw error;
95389
+ }
95390
+ const target = cleanText(messageId);
95391
+ if (!target) {
95392
+ throw new Error("message id required", { cause: error });
95393
+ }
95394
+ const active = await readSession();
95395
+ const chat = await chatForPeer(peer, options);
95396
+ if (!chat) {
95397
+ throw new Error("chat not found", { cause: error });
95398
+ }
95399
+ return { active, chat, message: null, target };
95400
+ }
95401
+ }
95402
+ async function sendPayload(peer, payload, options = {}) {
95403
+ const active = await readSession();
95404
+ const profile = await peers.resolve(peer);
95405
+ if (!profile.chatPK) {
95406
+ throw new Error("peer chat key missing");
95407
+ }
95408
+ if (profile.chatPK === active.chatPK) {
95409
+ throw new Error("cannot message self");
95410
+ }
95411
+ const link = await resolvePeerChat(readCloud(), active.chatPK, active.chatPrivKey, profile.chatPK, options);
95412
+ const message = {
95413
+ ...payload,
95414
+ s: payload?.s || active.chatPK,
95415
+ cid: payload?.cid || makeCid()
95416
+ };
95417
+ const sent = await sendMsg(readCloud(), active.chatPK, active.chatPrivKey, profile.chatPK, message, {
95418
+ ...options,
95419
+ chatId: link.chatId,
95420
+ linkId: link.linkId,
95421
+ linkVersion: link.version,
95422
+ protocol: link.protocol,
95423
+ senderUid: active.uid,
95424
+ receiverUid: profile.uid,
95425
+ peerActorPK: profile.actorPK
95426
+ });
95427
+ return {
95428
+ chat: {
95429
+ id: sent.chatId,
95430
+ peerChatPK: profile.chatPK,
95431
+ username: profile.username
95432
+ },
95433
+ message: simplifyAccountMessage(sent.message, { id: sent.chatId, peerChatPK: profile.chatPK }, active.chatPK, options)
95434
+ };
95435
+ }
95436
+ async function send(peer, message, options = {}) {
95437
+ return sendPayload(peer, makeTxt(cleanMessage(message)), options);
95438
+ }
95439
+ async function reply(peer, messageId, message, options = {}) {
95440
+ const { target } = await targetForPeer(peer, messageId, options);
95441
+ return sendPayload(peer, setReply(makeTxt(cleanMessage(message)), target), options);
95442
+ }
95443
+ async function react(peer, messageId, emoji, options = {}) {
95444
+ const { active, chat, target } = await targetForPeer(peer, messageId, options);
95445
+ const sent = await sendReaction(readCloud(), active.chatPK, active.chatPrivKey, chat.peerChatPK, target, emoji, writeOptions(active, chat, options));
95446
+ return {
95447
+ chat: simplifyAccountChat(chat),
95448
+ message: simplifyAccountMessage(sent.message, chat, active.chatPK, options)
95449
+ };
95450
+ }
95451
+ async function unreact(peer, messageId, options = {}) {
95452
+ return react(peer, messageId, null, options);
95453
+ }
95454
+ async function save(peer, messageId, options = {}) {
95455
+ const { active, chat, message } = await messageForPeer(peer, messageId, options);
95456
+ const updated = await makeMsgPermanent(readCloud(), chat.id, [message]);
95457
+ return {
95458
+ chat: simplifyAccountChat(chat),
95459
+ message: simplifyAccountMessage(message, chat, active.chatPK, options),
95460
+ saved: true,
95461
+ updated
95462
+ };
95463
+ }
95464
+ async function unsave(peer, messageId, options = {}) {
95465
+ const { active, chat, message } = await messageForPeer(peer, messageId, options);
95466
+ const updated = await makeMsgTemporary(readCloud(), chat.id, [message]);
95467
+ return {
95468
+ chat: simplifyAccountChat(chat),
95469
+ message: simplifyAccountMessage(message, chat, active.chatPK, options),
95470
+ saved: false,
95471
+ updated
95472
+ };
95473
+ }
95474
+ async function deleteMessage(peer, messageId, options = {}) {
95475
+ const { active, chat, message, target } = await messageForPeer(peer, messageId, options);
95476
+ const deleted = await deleteMsg(readCloud(), chat.id, message, active.chatPK, active.chatPrivKey, chat.peerChatPK, {
95477
+ ...writeOptions(active, chat, options),
95478
+ target,
95479
+ docId: message.id
95480
+ });
95481
+ return {
95482
+ chat: simplifyAccountChat(chat),
95483
+ messageId: message.id,
95484
+ target,
95485
+ deleted: deleted === true
95486
+ };
95487
+ }
95488
+ async function deleteChat(peer, options = {}) {
95489
+ const active = await readSession();
95490
+ const chat = await chatForPeer(peer, options);
95491
+ if (!chat) {
95492
+ return { deleted: false, chat: null };
95493
+ }
95494
+ const entryId = chat.entryId || ownChatEntryId(active.chatPrivKey, chat.id);
95495
+ await readCloud().chat.delete([
95496
+ {
95497
+ chatId: chat.id,
95498
+ entryId,
95499
+ linkId: chat.linkId
95500
+ }
95501
+ ], { cleanup: options.cleanup !== false });
95502
+ return {
95503
+ chat: simplifyAccountChat(chat),
95504
+ deleted: true
95505
+ };
95506
+ }
95507
+ async function retention(peer, value, options = {}) {
95508
+ const active = await readSession();
95509
+ const chat = await chatForPeer(peer, options);
95510
+ if (!chat) {
95511
+ throw new Error("chat not found");
95512
+ }
95513
+ const saved = await setChatRetention(readCloud(), chat.id, active.chatPK, active.chatPrivKey, chat.peerChatPK, requireRetention(value), writeOptions(active, chat, options));
95514
+ return {
95515
+ chat: simplifyAccountChat({
95516
+ ...chat,
95517
+ settings: {
95518
+ ...normalizeChatSettings(chat.settings),
95519
+ retention: saved
95520
+ }
95521
+ }),
95522
+ retention: saved
95523
+ };
95524
+ }
95525
+ return {
95526
+ list,
95527
+ chatForPeer,
95528
+ read,
95529
+ send,
95530
+ reply,
95531
+ sendPayload,
95532
+ react,
95533
+ unreact,
95534
+ save,
95535
+ unsave,
95536
+ deleteMessage,
95537
+ deleteChat,
95538
+ retention
95539
+ };
95540
+ }
95541
+
95542
+ // ../../shared/account/actions/inbox.js
95543
+ function createInboxSync({ readCloud }) {
95544
+ async function load(active, count = 30) {
95545
+ return loadAllChats(readCloud(), active.uid, active.chatPK, active.chatPrivKey, cleanLimit(count, 30));
95546
+ }
95547
+ async function sync(active, chats = null) {
95548
+ let current = Array.isArray(chats) ? chats : await load(active, 50);
95549
+ let processed = false;
95550
+ for (let index = 0;index < 4; index += 1) {
95551
+ const changed = await processInbox(readCloud(), active.uid, active.chatPK, active.chatPrivKey, { currentChats: current }).catch(() => false);
95552
+ if (!changed) {
95553
+ break;
95554
+ }
95555
+ processed = true;
95556
+ current = await load(active, Math.max(current.length, 50));
95557
+ }
95558
+ return { chats: current, processed };
95559
+ }
95560
+ return { load, sync };
95561
+ }
95562
+
95563
+ // ../../shared/navigation/params.js
95564
+ function firstRouteParam(value) {
95565
+ return Array.isArray(value) ? value[0] : value;
95566
+ }
95567
+ function getRouteParam(params, key) {
95568
+ const raw = typeof params?.get === "function" ? params.get(key) : params?.[key];
95569
+ return firstRouteParam(raw) ?? null;
95570
+ }
95571
+
95572
+ // ../../shared/username.js
95573
+ var MAX_USERNAME = USERNAME_MAX_CHARS;
95574
+ var usernameRegex = new RegExp(`^[a-z0-9]{1,${MAX_USERNAME}}$`);
95575
+ function normalizeUsername(value = "") {
95576
+ return String(value).trim().toLowerCase();
95577
+ }
95578
+ function isUsername(value = "") {
95579
+ return usernameRegex.test(value);
95580
+ }
95581
+
95582
+ // ../../shared/qr.js
95583
+ function getQrOrigin() {
95584
+ return origins.veyl;
95585
+ }
95586
+ var tx = {
95587
+ request: "req",
95588
+ payment: "pay"
95589
+ };
95590
+ var qrHosts = new Set(appLinkDomains);
95591
+ var qr = Object.freeze({
95592
+ user: "user",
95593
+ request: "request",
95594
+ payment: "payment",
95595
+ bitcoin: "bitcoin",
95596
+ lightning: "lightning",
95597
+ spark: "spark"
95598
+ });
95599
+ function maybe(value) {
95600
+ const next = cleanText(value);
95601
+ return next || null;
95602
+ }
95603
+ function userHandle(value) {
95604
+ const next = maybe(value);
95605
+ if (!next)
95606
+ return null;
95607
+ const raw = next.startsWith("@") ? next.slice(1) : next;
95608
+ const username = normalizeUsername(raw);
95609
+ return isUsername(username) ? username : null;
95610
+ }
95611
+ function readUser(value) {
95612
+ const username = userHandle(typeof value === "string" ? value : value?.u ?? value?.username);
95613
+ if (!username)
95614
+ return null;
95615
+ return {
95616
+ kind: qr.user,
95617
+ username
95618
+ };
95619
+ }
95620
+ function readTx(value) {
95621
+ if (!value || typeof value !== "object")
95622
+ return null;
95623
+ const tag = maybe(value.t ?? value.type);
95624
+ const to = maybe(value.r ?? value.to ?? value.receiver);
95625
+ if (!tag || !to)
95626
+ return null;
95627
+ if (tag !== tx.request && tag !== tx.payment)
95628
+ return null;
95629
+ return {
95630
+ kind: tag === tx.request ? qr.request : qr.payment,
95631
+ to,
95632
+ from: maybe(value.s ?? value.from ?? value.sender),
95633
+ amount: maybe(value.a ?? value.amount),
95634
+ currency: maybe(value.c ?? value.currency),
95635
+ pay: maybe(value.p ?? value.pay ?? value.payment ?? value.paymentType),
95636
+ message: maybe(value.m ?? value.message)
95637
+ };
95638
+ }
95639
+ function readQrUrlParams(value) {
95640
+ try {
95641
+ const url = new URL(value, getQrOrigin());
95642
+ if (url.protocol !== "https:" || url.pathname !== "/qr" || !qrHosts.has(url.hostname)) {
95643
+ return null;
95644
+ }
95645
+ return url.searchParams;
95646
+ } catch {
95647
+ return null;
95648
+ }
95649
+ }
95650
+ function readParams(params) {
95651
+ const user = readUser({
95652
+ u: getRouteParam(params, "u"),
95653
+ username: getRouteParam(params, "username")
95654
+ });
95655
+ if (user)
95656
+ return user;
95657
+ const request = readTx({
95658
+ t: tx.request,
95659
+ r: getRouteParam(params, "r"),
95660
+ s: getRouteParam(params, "s"),
95661
+ a: getRouteParam(params, "a"),
95662
+ c: getRouteParam(params, "c"),
95663
+ p: getRouteParam(params, "p"),
95664
+ m: getRouteParam(params, "m")
95665
+ });
95666
+ if (request)
95667
+ return request;
95668
+ const lightning = readLightning({
95669
+ invoice: getRouteParam(params, "l") || getRouteParam(params, "lightning") || getRouteParam(params, "invoice"),
95670
+ username: getRouteParam(params, "lu") || getRouteParam(params, "lightningUser"),
95671
+ walletPK: getRouteParam(params, "lw") || getRouteParam(params, "lightningWalletPK")
95672
+ });
95673
+ if (lightning)
95674
+ return lightning;
95675
+ const spark = readSpark(getRouteParam(params, "s") || getRouteParam(params, "spark"));
95676
+ if (spark)
95677
+ return spark;
95678
+ const address = readBitcoin(getRouteParam(params, "b"));
95679
+ if (!address)
95680
+ return null;
95681
+ return {
95682
+ kind: qr.bitcoin,
95683
+ address
95684
+ };
95685
+ }
95686
+ function getLightningInvoice(value) {
95687
+ const raw = cleanText(typeof value === "string" ? value : value?.invoice ?? value?.encodedInvoice ?? value?.bolt11);
95688
+ const lower = lowerText(raw);
95689
+ if (!lower)
95690
+ return null;
95691
+ const invoice = lower.startsWith("lightning://") ? raw.slice(12).trim() : lower.startsWith("lightning:") ? raw.slice(10).trim() : raw;
95692
+ const normalized = lowerText(invoice);
95693
+ return /^ln[a-z0-9]+$/.test(normalized) ? invoice : null;
95694
+ }
95695
+ function ceilDiv(value, divisor) {
95696
+ return (value + divisor - 1n) / divisor;
95697
+ }
95698
+ function lightningAmountSats(invoice) {
95699
+ const value = lowerText(invoice);
95700
+ const match2 = value.match(/^ln(?:bcrt|bc|tb|sb|tbs)(\d+[munp]?)?1/);
95701
+ const amount = match2?.[1];
95702
+ if (!amount)
95703
+ return null;
95704
+ const unit = /[munp]$/.test(amount) ? amount.slice(-1) : "";
95705
+ const raw = unit ? amount.slice(0, -1) : amount;
95706
+ if (!/^\d+$/.test(raw))
95707
+ return null;
95708
+ const n = BigInt(raw);
95709
+ switch (unit) {
95710
+ case "m":
95711
+ return n * 100000n;
95712
+ case "u":
95713
+ return n * 100n;
95714
+ case "n":
95715
+ return ceilDiv(n, 10n);
95716
+ case "p":
95717
+ return ceilDiv(n, 10000n);
95718
+ default:
95719
+ return n * 100000000n;
95720
+ }
95721
+ }
95722
+ function readLightning(value) {
95723
+ const invoice = getLightningInvoice(value);
95724
+ if (!invoice)
95725
+ return null;
95726
+ const amountSats = lightningAmountSats(invoice);
95727
+ const username = userHandle(typeof value === "object" ? value?.username ?? value?.user ?? value?.lu : null);
95728
+ const walletPK = maybe(typeof value === "object" ? value?.walletPK ?? value?.receiver ?? value?.lw : null);
95729
+ return {
95730
+ kind: qr.lightning,
95731
+ invoice,
95732
+ ...username ? { username } : {},
95733
+ ...walletPK ? { walletPK } : {},
95734
+ ...amountSats != null && amountSats > 0n ? { amount: amountSats.toString() } : {}
95735
+ };
95736
+ }
95737
+ function getSparkInvoice(value) {
95738
+ const raw = cleanText(typeof value === "string" ? value : value?.invoice ?? value?.sparkInvoice ?? value?.address);
95739
+ const lower = lowerText(raw);
95740
+ if (!lower)
95741
+ return null;
95742
+ return /^(spark|sparkt|sparkrt|sparks|sparkl)1[023456789acdefghjklmnpqrstuvwxyz]+$/.test(lower) ? raw : null;
95743
+ }
95744
+ function readSpark(value) {
95745
+ const invoice = getSparkInvoice(value);
95746
+ return invoice ? {
95747
+ kind: qr.spark,
95748
+ invoice
95749
+ } : null;
95750
+ }
95751
+ function readApp(raw) {
95752
+ if (raw && typeof raw === "object") {
95753
+ return readParams(raw);
95754
+ }
95755
+ const value = cleanText(raw);
95756
+ if (!value)
95757
+ return null;
95758
+ const params = readQrUrlParams(value);
95759
+ if (params)
95760
+ return readParams(params);
95761
+ return value.startsWith("@") ? readUser(value) : null;
95762
+ }
95763
+ function readBitcoin(value) {
95764
+ const raw = cleanText(value);
95765
+ let clean4 = raw;
95766
+ if (lowerText(raw).startsWith("bitcoin:"))
95767
+ clean4 = raw.slice(8);
95768
+ const legacy = /^[13][a-km-zA-HJ-NP-Z1-9]{25,34}$/;
95769
+ const bech323 = /^(bc1|bcrt1)[ac-hj-np-z02-9]{39,87}$/i;
95770
+ return legacy.test(clean4) || bech323.test(clean4) ? clean4 : null;
95771
+ }
95772
+ function readQr(raw) {
95773
+ const veyl = readApp(raw);
95774
+ if (veyl)
95775
+ return veyl;
95776
+ const lightning = readLightning(raw);
95777
+ if (lightning)
95778
+ return lightning;
95779
+ const spark = readSpark(raw);
95780
+ if (spark)
95781
+ return spark;
95782
+ const address = readBitcoin(raw);
95783
+ if (!address)
95784
+ return null;
95785
+ return {
95786
+ kind: qr.bitcoin,
95787
+ address
95788
+ };
95789
+ }
95790
+
95791
+ // ../../shared/wallet/claiming.js
95792
+ var activeWalletClaims = new WeakMap;
95793
+ function transferIds(transfers = []) {
95794
+ return [...new Set((Array.isArray(transfers) ? transfers : []).map((tx2) => String(tx2?.id || "")).filter(Boolean))];
95795
+ }
95796
+ async function queryPendingTransferIds(wallet, ids = [], diag) {
95797
+ if (!ids.length || typeof wallet?.transferService?.queryPendingTransfers !== "function") {
95798
+ return new Set;
95799
+ }
95800
+ const startedAt = Date.now();
95801
+ markDiag(diag, "wallet.pendingTxs.claim.verify.start", { count: ids.length });
95802
+ const requestedIds = new Set(ids);
95803
+ try {
95804
+ const page = await wallet.transferService.queryPendingTransfers.call(wallet.transferService, ids);
95805
+ const pendingTransfers = (Array.isArray(page?.transfers) ? page.transfers : []).filter((transfer) => requestedIds.has(String(transfer?.id || "")));
95806
+ markDone(diag, "wallet.pendingTxs.claim.verify", startedAt, { count: ids.length, pending: pendingTransfers.length });
95807
+ return new Set(pendingTransfers.map((transfer) => String(transfer?.id || "")).filter(Boolean));
95808
+ } catch (error) {
95809
+ markError(diag, "wallet.pendingTxs.claim.verify", startedAt, error, { count: ids.length });
95810
+ throw error;
95811
+ }
95812
+ }
95813
+ async function claimIncomingTransfersById(wallet, transfers = [], { onClaimed, emitClaimEvents = false, drainAll = true, diag } = {}) {
95814
+ const ids = transferIds(transfers);
95815
+ if (!ids.length || typeof wallet?.transferService?.queryPendingTransfers !== "function" || typeof wallet?.claimTransfers !== "function" && typeof wallet?.claimTransfer !== "function") {
95816
+ return [];
95817
+ }
95818
+ const requestedIds = new Set(ids);
95819
+ const activeClaim = activeWalletClaims.get(wallet);
95820
+ if (activeClaim) {
95821
+ const claimedIds = transferIds(await activeClaim).filter((id) => requestedIds.has(id));
95822
+ if (claimedIds.length) {
95823
+ onClaimed?.(claimedIds);
95824
+ }
95825
+ return claimedIds;
95826
+ }
95827
+ const claimPromise = (async () => {
95828
+ if (drainAll !== false && typeof wallet?.claimTransfers === "function") {
95829
+ const claimedIds2 = [];
95830
+ const claimStartedAt = Date.now();
95831
+ markDiag(diag, "wallet.pendingTxs.claim.sdk.start", { count: ids.length, mode: "all" });
95832
+ try {
95833
+ claimedIds2.push(...transferIds(await wallet.claimTransfers(undefined, emitClaimEvents === true)));
95834
+ markDone(diag, "wallet.pendingTxs.claim.sdk", claimStartedAt, { count: ids.length, mode: "all", claimed: claimedIds2.length });
95835
+ } catch (error) {
95836
+ markError(diag, "wallet.pendingTxs.claim.sdk", claimStartedAt, error, { count: ids.length, mode: "all" });
95837
+ console.debug?.("could not claim pending transfers", error?.message ?? error);
95838
+ }
95839
+ try {
95840
+ const pendingIds2 = await queryPendingTransferIds(wallet, ids, diag);
95841
+ claimedIds2.push(...ids.filter((id) => !pendingIds2.has(id)));
95842
+ } catch (error) {
95843
+ console.debug?.("could not verify pending transfers", error?.message ?? error);
95844
+ }
95845
+ const uniqueClaimedIds = [...new Set(claimedIds2)];
95846
+ if (uniqueClaimedIds.length) {
95847
+ onClaimed?.(uniqueClaimedIds);
95848
+ }
95849
+ return uniqueClaimedIds;
95850
+ }
95851
+ const queryStartedAt = Date.now();
95852
+ markDiag(diag, "wallet.pendingTxs.claim.query.start", { count: ids.length });
95853
+ let page;
95854
+ try {
95855
+ page = await wallet.transferService.queryPendingTransfers.call(wallet.transferService, ids);
95856
+ } catch (error) {
95857
+ markError(diag, "wallet.pendingTxs.claim.query", queryStartedAt, error, { count: ids.length });
95858
+ throw error;
95859
+ }
95860
+ const pendingTransfers = (Array.isArray(page?.transfers) ? page.transfers : []).filter((transfer) => requestedIds.has(String(transfer?.id || "")));
95861
+ markDone(diag, "wallet.pendingTxs.claim.query", queryStartedAt, { count: ids.length, pending: pendingTransfers.length });
95862
+ const pendingIds = new Set(pendingTransfers.map((transfer) => String(transfer?.id || "")).filter(Boolean));
95863
+ const claimedIds = [];
95864
+ const alreadySettledIds = ids.filter((id) => !pendingIds.has(id));
95865
+ if (alreadySettledIds.length) {
95866
+ claimedIds.push(...alreadySettledIds);
95867
+ onClaimed?.(alreadySettledIds);
95868
+ }
95869
+ for (const transfer of pendingTransfers) {
95870
+ if (!isClaimablePendingTransfer(transfer)) {
95871
+ continue;
95872
+ }
95873
+ let claimStartedAt = Date.now();
95874
+ try {
95875
+ await yieldToUi();
95876
+ claimStartedAt = Date.now();
95877
+ markDiag(diag, "wallet.pendingTxs.claim.sdk.start", { count: 1, leaves: Array.isArray(transfer?.leaves) ? transfer.leaves.length : 0 });
95878
+ await wallet.claimTransfer({ transfer, emit: emitClaimEvents === true });
95879
+ markDone(diag, "wallet.pendingTxs.claim.sdk", claimStartedAt, { count: 1 });
95880
+ if (transfer?.id) {
95881
+ const id = String(transfer.id);
95882
+ claimedIds.push(id);
95883
+ onClaimed?.([id]);
95884
+ }
95885
+ } catch (error) {
95886
+ markError(diag, "wallet.pendingTxs.claim.sdk", claimStartedAt, error, { count: 1 });
95887
+ console.debug?.("could not claim pending transfer", error?.message ?? error);
95888
+ }
95889
+ await yieldToUi();
95890
+ }
95891
+ return claimedIds;
95892
+ })();
95893
+ activeWalletClaims.set(wallet, claimPromise);
95894
+ try {
95895
+ return await claimPromise;
95896
+ } finally {
95897
+ if (activeWalletClaims.get(wallet) === claimPromise) {
95898
+ activeWalletClaims.delete(wallet);
95899
+ }
95900
+ }
95901
+ }
95902
+ async function claimPendingIncomingTransfers(wallet, { limit = WALLET_PENDING_TRANSFER_CLAIM_BATCH_SIZE, onClaimed, emitClaimEvents = false, drainAll = true, diag } = {}) {
95903
+ if (typeof wallet?.transferService?.queryPendingTransfers !== "function") {
95904
+ return [];
95905
+ }
95906
+ const startedAt = Date.now();
95907
+ const pageLimit = Math.max(1, Number(limit) || WALLET_PENDING_TRANSFER_CLAIM_BATCH_SIZE);
95908
+ markDiag(diag, "wallet.pendingTxs.claim.scan.start", { limit: pageLimit });
95909
+ let pendingTransfers;
95910
+ try {
95911
+ const page = await wallet.transferService.queryPendingTransfers.call(wallet.transferService, {
95912
+ limit: pageLimit,
95913
+ offset: 0
95914
+ });
95915
+ pendingTransfers = Array.isArray(page?.transfers) ? page.transfers : [];
95916
+ markDone(diag, "wallet.pendingTxs.claim.scan", startedAt, { limit: pageLimit, pending: pendingTransfers.length });
95917
+ } catch (error) {
95918
+ markError(diag, "wallet.pendingTxs.claim.scan", startedAt, error, { limit: pageLimit });
95919
+ throw error;
95920
+ }
95921
+ if (!pendingTransfers.length) {
95922
+ return [];
95923
+ }
95924
+ return claimIncomingTransfersById(wallet, pendingTransfers, {
95925
+ onClaimed,
95926
+ emitClaimEvents,
95927
+ drainAll,
95928
+ diag
95929
+ });
95930
+ }
95931
+
95932
+ // ../../shared/network.js
95933
+ var DEFAULT_NETWORK = "REGTEST";
95934
+ var MAINNET_NETWORK = "MAINNET";
95935
+ var REGTEST_NETWORK = "REGTEST";
95936
+ var MAINNET_DOMAIN = domains.veyl;
95937
+ var REGTEST_DOMAIN = domains.veylTest;
95938
+ function resolveNetwork(env = {}) {
95939
+ const raw = env?.EXPO_PUBLIC_NETWORK ?? env?.NEXT_PUBLIC_NETWORK ?? env?.VEYL_NETWORK ?? env?.NETWORK ?? DEFAULT_NETWORK;
95940
+ return String(raw).toUpperCase();
95941
+ }
95942
+ function getAddressNetwork(address) {
95943
+ const a = String(address ?? "").trim();
95944
+ if (!a)
95945
+ return null;
95946
+ if (/^bcrt1[ac-hj-np-z02-9]{39,87}$/i.test(a))
95947
+ return REGTEST_NETWORK;
95948
+ if (/^bc1[ac-hj-np-z02-9]{39,87}$/i.test(a))
95949
+ return MAINNET_NETWORK;
95950
+ if (/^[13][a-km-zA-HJ-NP-Z1-9]{25,34}$/.test(a))
95951
+ return MAINNET_NETWORK;
95952
+ return null;
95953
+ }
95954
+ function isAddressOnNetwork(address, network) {
95955
+ const detected = getAddressNetwork(address);
95956
+ return detected !== null && detected === String(network ?? "").toUpperCase();
95957
+ }
95958
+
95959
+ // ../../shared/wallet/deposits.js
95960
+ var AUTO_CLAIM_MAX_FEE_SATS = WALLET_AUTO_CLAIM_MAX_FEE_SATS;
95961
+ var CLAIM_PAGE_SIZE = WALLET_CLAIM_PAGE_SIZE;
95962
+ async function getStaticFundingAddress(wallet, network) {
95963
+ if (!wallet) {
95964
+ return null;
95965
+ }
95966
+ const address = await wallet.getStaticDepositAddress();
95967
+ const nextAddress = typeof address === "string" && address.trim() ? address.trim() : null;
95968
+ if (!nextAddress) {
95969
+ return null;
95970
+ }
95971
+ if (network && !isAddressOnNetwork(nextAddress, network)) {
95972
+ throw new Error(`funding address is not a ${network} address`);
95973
+ }
95974
+ return nextAddress;
95975
+ }
95976
+ async function getAddressDepositUtxos(wallet, getFundingAddress, { pageSize = CLAIM_PAGE_SIZE } = {}) {
95977
+ const address = await getFundingAddress();
95978
+ if (!address) {
95979
+ return [];
95980
+ }
95981
+ const utxos = [];
95982
+ let offset = 0;
95983
+ while (true) {
95984
+ const page = await wallet.getUtxosForDepositAddress(address, pageSize, offset, true);
95985
+ if (!Array.isArray(page) || !page.length) {
95986
+ break;
95987
+ }
95988
+ utxos.push(...page);
95989
+ if (page.length < pageSize) {
95990
+ break;
95991
+ }
95992
+ offset += page.length;
95993
+ }
95994
+ return utxos;
95995
+ }
95996
+ async function getClaimableDepositUtxos(wallet, getFundingAddress, options = {}) {
95997
+ if (typeof wallet?.getUtxosForIdentity !== "function") {
95998
+ return getAddressDepositUtxos(wallet, getFundingAddress, options);
95999
+ }
96000
+ try {
96001
+ const pageSize = options.pageSize || CLAIM_PAGE_SIZE;
96002
+ const utxos = [];
96003
+ let cursor = "";
96004
+ while (true) {
96005
+ const page = await wallet.getUtxosForIdentity({
96006
+ pageSize,
96007
+ cursor,
96008
+ excludeClaimed: true,
96009
+ includePending: false
96010
+ });
96011
+ const pageUtxos = Array.isArray(page?.utxos) ? page.utxos.filter((utxo) => utxo?.isConfirmed !== false) : [];
96012
+ utxos.push(...pageUtxos);
96013
+ const nextCursor = page?.pageResponse?.nextCursor || "";
96014
+ if (!page?.pageResponse?.hasNextPage || !nextCursor || nextCursor === cursor) {
96015
+ break;
96016
+ }
96017
+ cursor = nextCursor;
96018
+ }
96019
+ return utxos;
96020
+ } catch {
96021
+ return getAddressDepositUtxos(wallet, getFundingAddress, options);
96022
+ }
96023
+ }
96024
+ async function claimStaticDeposits(wallet, { getFundingAddress, maxFeeSats = AUTO_CLAIM_MAX_FEE_SATS, pageSize = CLAIM_PAGE_SIZE } = {}) {
96025
+ if (!wallet) {
96026
+ return false;
96027
+ }
96028
+ const readAddress = typeof getFundingAddress === "function" ? getFundingAddress : () => getStaticFundingAddress(wallet);
96029
+ const utxos = await getClaimableDepositUtxos(wallet, readAddress, { pageSize });
96030
+ if (!utxos.length) {
96031
+ return false;
96032
+ }
96033
+ let claimed = false;
96034
+ const seen = new Set;
96035
+ for (const utxo of utxos) {
96036
+ if (!utxo?.txid || !Number.isInteger(utxo.vout)) {
96037
+ continue;
96038
+ }
96039
+ const key = `${utxo.txid}:${utxo.vout}`;
96040
+ if (seen.has(key)) {
96041
+ continue;
96042
+ }
96043
+ seen.add(key);
96044
+ try {
96045
+ const claim = await wallet.claimStaticDepositWithMaxFee({
96046
+ transactionId: utxo.txid,
96047
+ outputIndex: utxo.vout,
96048
+ maxFee: maxFeeSats
96049
+ });
96050
+ if (claim) {
96051
+ claimed = true;
96052
+ }
96053
+ } catch (error) {
96054
+ console.debug?.("could not claim deposit", key, error?.message ?? error);
96055
+ }
96056
+ }
96057
+ return claimed;
96058
+ }
96059
+
96060
+ // ../../shared/wallet/fees.js
96061
+ var DEFAULT_EXIT_SPEED = "MEDIUM";
96062
+ var EXIT_SPEEDS = Object.freeze(["SLOW", "MEDIUM", "FAST"]);
96063
+ var UNILATERAL_EXIT_PARENT_TX_FALLBACK_VBYTES = 191;
96064
+ var UNILATERAL_EXIT_FEE_BUMP_TX_VBYTES = 151;
96065
+ var UNILATERAL_EXIT_PACKAGES_PER_LEAF = 2;
96066
+ var UNILATERAL_EXIT_PREVIEW_VBYTES = UNILATERAL_EXIT_PACKAGES_PER_LEAF * (UNILATERAL_EXIT_PARENT_TX_FALLBACK_VBYTES + UNILATERAL_EXIT_FEE_BUMP_TX_VBYTES);
96067
+ var FEE_RATE_FALLBACKS = Object.freeze({
96068
+ default: Object.freeze(["medium", "low", "high"]),
96069
+ high: Object.freeze(["high", "medium", "low"]),
96070
+ fastest: Object.freeze(["high", "medium", "low"]),
96071
+ medium: Object.freeze(["medium", "low", "high"]),
96072
+ halfHour: Object.freeze(["medium", "high", "low"]),
96073
+ hour: Object.freeze(["medium", "low", "high"]),
96074
+ low: Object.freeze(["low", "medium", "high"]),
96075
+ economy: Object.freeze(["low", "medium", "high"]),
96076
+ minimum: Object.freeze(["low", "medium", "high"]),
96077
+ noPriority: Object.freeze(["low", "medium", "high"]),
96078
+ average: Object.freeze(["medium", "low", "high"])
96079
+ });
96080
+ var WITHDRAWAL_FEE_FIELDS = Object.freeze({
96081
+ FAST: Object.freeze({ user: "userFeeFast", l1: "l1BroadcastFeeFast" }),
96082
+ MEDIUM: Object.freeze({ user: "userFeeMedium", l1: "l1BroadcastFeeMedium" }),
96083
+ SLOW: Object.freeze({ user: "userFeeSlow", l1: "l1BroadcastFeeSlow" })
96084
+ });
96085
+ function getOptionalSats(value) {
96086
+ if (value == null) {
96087
+ return null;
96088
+ }
96089
+ const n = typeof value === "bigint" ? Number(value) : Number(value);
96090
+ if (!Number.isSafeInteger(n) || n < 0) {
96091
+ return null;
96092
+ }
96093
+ return n;
96094
+ }
96095
+ function toSafeSats(value, label = "amountSats") {
96096
+ const n = getOptionalSats(value);
96097
+ if (n == null || n <= 0) {
96098
+ throw new Error(`${label} must be a positive safe integer`);
96099
+ }
96100
+ return n;
96101
+ }
96102
+ function toSafeNonNegativeSats(value, label = "amountSats") {
96103
+ const n = getOptionalSats(value);
96104
+ if (n == null) {
96105
+ throw new Error(`${label} must be a non-negative safe integer`);
96106
+ }
96107
+ return n;
96108
+ }
96109
+ function getExitSpeed(value = DEFAULT_EXIT_SPEED) {
96110
+ const speed = String(value || DEFAULT_EXIT_SPEED).toUpperCase();
96111
+ if (!EXIT_SPEEDS.includes(speed)) {
96112
+ throw new Error("invalid exit speed");
96113
+ }
96114
+ return speed;
96115
+ }
96116
+ function getCurrencyAmountSats(amount) {
96117
+ const value = getOptionalSats(amount?.originalValue);
96118
+ if (value == null) {
96119
+ return 0;
96120
+ }
96121
+ if (amount?.originalUnit === "MILLISATOSHI") {
96122
+ return Math.ceil(value / 1000);
94624
96123
  }
94625
96124
  return value;
94626
96125
  }
94627
- function requireSession(session) {
94628
- if (!session?.uid || !session?.network || !session?.wallet || !session?.chatPK || !session?.chatPrivKey) {
94629
- throw new Error("account session unlocked required");
96126
+ function getWithdrawalFeeBreakdown(feeQuote, exitSpeed = DEFAULT_EXIT_SPEED) {
96127
+ if (!feeQuote) {
96128
+ return null;
94630
96129
  }
94631
- return session;
96130
+ const speed = getExitSpeed(exitSpeed);
96131
+ const fields = WITHDRAWAL_FEE_FIELDS[speed];
96132
+ const userFeeSats = getCurrencyAmountSats(feeQuote[fields.user]);
96133
+ const l1BroadcastFeeSats = getCurrencyAmountSats(feeQuote[fields.l1]);
96134
+ return {
96135
+ speed,
96136
+ userFeeSats,
96137
+ l1BroadcastFeeSats,
96138
+ feeAmountSats: userFeeSats + l1BroadcastFeeSats,
96139
+ quoteId: feeQuote.id ?? null,
96140
+ expiresAt: feeQuote.expiresAt ?? null
96141
+ };
94632
96142
  }
94633
- function createAccountSessionActions({ cloud, getSession, session } = {}) {
94634
- const readCloud = () => requireCloud(typeof cloud === "function" ? cloud() : cloud);
94635
- const readSession = async () => requireSession(typeof getSession === "function" ? await getSession() : session);
94636
- async function resolvePeer(peer) {
96143
+ function getWithdrawalFeeAmountSats(feeQuote, exitSpeed = DEFAULT_EXIT_SPEED) {
96144
+ return getWithdrawalFeeBreakdown(feeQuote, exitSpeed)?.feeAmountSats ?? null;
96145
+ }
96146
+ function normalizeWithdrawalFeeQuote(feeQuote) {
96147
+ if (!feeQuote) {
96148
+ return null;
96149
+ }
96150
+ const speeds = {};
96151
+ for (const speed of EXIT_SPEEDS) {
96152
+ speeds[speed] = getWithdrawalFeeBreakdown(feeQuote, speed);
96153
+ }
96154
+ return {
96155
+ id: feeQuote.id ?? null,
96156
+ expiresAt: feeQuote.expiresAt ?? null,
96157
+ network: feeQuote.network ?? null,
96158
+ totalAmountSats: getCurrencyAmountSats(feeQuote.totalAmount),
96159
+ speeds,
96160
+ raw: feeQuote
96161
+ };
96162
+ }
96163
+ function normalizeLightningFeeEstimate(feeAmountSats) {
96164
+ return {
96165
+ feeAmountSats: toSafeNonNegativeSats(feeAmountSats, "feeAmountSats")
96166
+ };
96167
+ }
96168
+ function normalizeLightningReceiveRequest(request) {
96169
+ if (!request) {
96170
+ return null;
96171
+ }
96172
+ const invoice = request.invoice ?? null;
96173
+ return {
96174
+ id: request.id ?? null,
96175
+ status: request.status ?? null,
96176
+ network: request.network ?? invoice?.bitcoinNetwork ?? null,
96177
+ createdAt: request.createdAt ?? invoice?.createdAt ?? null,
96178
+ updatedAt: request.updatedAt ?? null,
96179
+ expiresAt: invoice?.expiresAt ?? null,
96180
+ amountSats: getCurrencyAmountSats(invoice?.amount),
96181
+ encodedInvoice: invoice?.encodedInvoice ?? null,
96182
+ paymentHash: invoice?.paymentHash ?? null,
96183
+ sparkInvoice: request.sparkInvoice ?? null,
96184
+ transfer: request.transfer ?? null,
96185
+ raw: request
96186
+ };
96187
+ }
96188
+ function normalizeLightningPaymentResult(result) {
96189
+ if (!result) {
96190
+ return null;
96191
+ }
96192
+ if (result.encodedInvoice || result.fee || String(result.typename || "").includes("LightningSendRequest")) {
96193
+ return {
96194
+ kind: "lightning",
96195
+ id: result.id ?? null,
96196
+ status: result.status ?? null,
96197
+ network: result.network ?? null,
96198
+ encodedInvoice: result.encodedInvoice ?? null,
96199
+ feeAmountSats: getCurrencyAmountSats(result.fee),
96200
+ idempotencyKey: result.idempotencyKey ?? null,
96201
+ transfer: result.transfer ?? null,
96202
+ raw: result
96203
+ };
96204
+ }
96205
+ return {
96206
+ kind: "spark",
96207
+ id: result.id ?? null,
96208
+ status: result.status ?? null,
96209
+ transfer: result,
96210
+ raw: result
96211
+ };
96212
+ }
96213
+
96214
+ // ../../shared/wallet/lightningops.js
96215
+ async function createLightningInvoice(wallet, { amountSats = 0, memo, expirySeconds, includeSparkAddress = false, includeSparkInvoice = false, receiverIdentityPubkey, descriptionHash } = {}) {
96216
+ if (!wallet) {
96217
+ return { success: false, error: new Error("wallet not ready") };
96218
+ }
96219
+ if (memo && descriptionHash) {
96220
+ return { success: false, error: new Error("lightning invoice memo and descriptionHash are mutually exclusive") };
96221
+ }
96222
+ if (includeSparkAddress && includeSparkInvoice) {
96223
+ return { success: false, error: new Error("includeSparkAddress and includeSparkInvoice are mutually exclusive") };
96224
+ }
96225
+ try {
96226
+ const request = await wallet.createLightningInvoice({
96227
+ amountSats: toSafeNonNegativeSats(amountSats),
96228
+ ...memo ? { memo } : {},
96229
+ ...expirySeconds != null ? { expirySeconds } : {},
96230
+ includeSparkAddress,
96231
+ includeSparkInvoice,
96232
+ ...receiverIdentityPubkey ? { receiverIdentityPubkey } : {},
96233
+ ...descriptionHash ? { descriptionHash } : {}
96234
+ });
96235
+ return {
96236
+ success: true,
96237
+ request,
96238
+ invoice: normalizeLightningReceiveRequest(request)
96239
+ };
96240
+ } catch (error) {
96241
+ return { success: false, error };
96242
+ }
96243
+ }
96244
+ async function quoteLightningFees(wallet, { invoice, amountSats } = {}) {
96245
+ if (!wallet) {
96246
+ return { success: false, error: new Error("wallet not ready") };
96247
+ }
96248
+ const encodedInvoice = cleanText(invoice);
96249
+ if (!encodedInvoice) {
96250
+ return { success: false, error: new Error("lightning invoice required") };
96251
+ }
96252
+ try {
96253
+ const params = { encodedInvoice };
96254
+ if (amountSats != null) {
96255
+ params.amountSats = toSafeSats(amountSats);
96256
+ }
96257
+ const feeAmountSats = await wallet.getLightningSendFeeEstimate(params);
96258
+ return {
96259
+ success: true,
96260
+ feeAmountSats,
96261
+ fees: normalizeLightningFeeEstimate(feeAmountSats)
96262
+ };
96263
+ } catch (error) {
96264
+ return { success: false, error };
96265
+ }
96266
+ }
96267
+ async function sendLightningPayment(wallet, { invoice, maxFeeSats, preferSpark = false, amountSatsToSend, idempotencyKey } = {}) {
96268
+ if (!wallet) {
96269
+ return { success: false, error: new Error("wallet not ready") };
96270
+ }
96271
+ const encodedInvoice = cleanText(invoice);
96272
+ if (!encodedInvoice) {
96273
+ return { success: false, error: new Error("lightning invoice required") };
96274
+ }
96275
+ try {
96276
+ const params = {
96277
+ invoice: encodedInvoice,
96278
+ maxFeeSats: toSafeNonNegativeSats(maxFeeSats, "maxFeeSats"),
96279
+ preferSpark: !!preferSpark
96280
+ };
96281
+ if (amountSatsToSend != null) {
96282
+ params.amountSatsToSend = toSafeSats(amountSatsToSend, "amountSatsToSend");
96283
+ }
96284
+ if (idempotencyKey) {
96285
+ params.idempotencyKey = idempotencyKey;
96286
+ }
96287
+ const payment = await wallet.payLightningInvoice(params);
96288
+ return {
96289
+ success: true,
96290
+ payment,
96291
+ result: normalizeLightningPaymentResult(payment)
96292
+ };
96293
+ } catch (error) {
96294
+ return { success: false, error };
96295
+ }
96296
+ }
96297
+ async function getLightningReceiveRequest(wallet, id) {
96298
+ if (!wallet) {
96299
+ return { success: false, error: new Error("wallet not ready") };
96300
+ }
96301
+ const requestId = cleanText(id);
96302
+ if (!requestId) {
96303
+ return { success: false, error: new Error("lightning receive request id required") };
96304
+ }
96305
+ try {
96306
+ const request = await wallet.getLightningReceiveRequest(requestId);
96307
+ return {
96308
+ success: true,
96309
+ request,
96310
+ invoice: normalizeLightningReceiveRequest(request)
96311
+ };
96312
+ } catch (error) {
96313
+ return { success: false, error };
96314
+ }
96315
+ }
96316
+ async function getLightningSendRequest(wallet, id) {
96317
+ if (!wallet) {
96318
+ return { success: false, error: new Error("wallet not ready") };
96319
+ }
96320
+ const requestId = cleanText(id);
96321
+ if (!requestId) {
96322
+ return { success: false, error: new Error("lightning send request id required") };
96323
+ }
96324
+ try {
96325
+ const request = await wallet.getLightningSendRequest(requestId);
96326
+ return {
96327
+ success: true,
96328
+ request,
96329
+ result: normalizeLightningPaymentResult(request)
96330
+ };
96331
+ } catch (error) {
96332
+ return { success: false, error };
96333
+ }
96334
+ }
96335
+
96336
+ // ../../shared/wallet/withdrawops.js
96337
+ function getWithdrawalReviewAmounts(withdrawal) {
96338
+ const amountSats = toSafeSats(withdrawal?.amountSats);
96339
+ const feeAmountSats = toSafeNonNegativeSats(withdrawal?.feeAmountSats ?? 0, "feeAmountSats");
96340
+ const deductFeeFromWithdrawalAmount = withdrawal?.deductFeeFromWithdrawalAmount !== false;
96341
+ const receiveAmountSats = deductFeeFromWithdrawalAmount ? Math.max(0, amountSats - feeAmountSats) : amountSats;
96342
+ const sendAmountSats = deductFeeFromWithdrawalAmount ? amountSats : amountSats + feeAmountSats;
96343
+ return {
96344
+ sendAmountSats,
96345
+ receiveAmountSats,
96346
+ feeAmountSats
96347
+ };
96348
+ }
96349
+ function assertWithdrawalReceivesFunds(withdrawal) {
96350
+ const { receiveAmountSats } = getWithdrawalReviewAmounts(withdrawal);
96351
+ if (receiveAmountSats <= 0) {
96352
+ throw new Error("withdrawal fee is greater than or equal to the amount");
96353
+ }
96354
+ }
96355
+ function getWithdrawalReview({ feeQuote, exitSpeed, amountSats, onchainAddress, deductFeeFromWithdrawalAmount = true }) {
96356
+ const safeExitSpeed = getExitSpeed(exitSpeed);
96357
+ const feeQuoteId = feeQuote?.id ?? null;
96358
+ const feeAmountSats = getWithdrawalFeeAmountSats(feeQuote, safeExitSpeed);
96359
+ if (!feeQuoteId || feeAmountSats == null) {
96360
+ throw new Error("withdrawal fee quote unavailable");
96361
+ }
96362
+ const sparkFees = normalizeWithdrawalFeeQuote(feeQuote);
96363
+ const withdrawal = {
96364
+ kind: "cooperative_exit",
96365
+ onchainAddress,
96366
+ amountSats,
96367
+ exitSpeed: safeExitSpeed,
96368
+ deductFeeFromWithdrawalAmount,
96369
+ feeQuote,
96370
+ feeQuoteId,
96371
+ feeAmountSats,
96372
+ fees: {
96373
+ spark: sparkFees
96374
+ },
96375
+ sparkFees,
96376
+ expiresAt: sparkFees?.expiresAt ?? feeQuote.expiresAt ?? null
96377
+ };
96378
+ assertWithdrawalReceivesFunds(withdrawal);
96379
+ return withdrawal;
96380
+ }
96381
+ async function quoteWithdrawalFees(wallet, network, { onchainAddress, amountSats } = {}) {
96382
+ if (!wallet) {
96383
+ return { success: false, error: new Error("wallet not ready") };
96384
+ }
96385
+ const address = cleanText(onchainAddress);
96386
+ if (!isAddressOnNetwork(address, network)) {
96387
+ return { success: false, error: new Error(`refusing to withdraw - address is not a ${network} address`) };
96388
+ }
96389
+ try {
96390
+ const safeAmountSats = toSafeSats(amountSats);
96391
+ const feeQuote = await wallet.getWithdrawalFeeQuote({
96392
+ amountSats: safeAmountSats,
96393
+ withdrawalAddress: address
96394
+ });
96395
+ if (!feeQuote?.id) {
96396
+ throw new Error("withdrawal fee quote unavailable");
96397
+ }
96398
+ const sparkFees = normalizeWithdrawalFeeQuote(feeQuote);
96399
+ return {
96400
+ success: true,
96401
+ feeQuote,
96402
+ fees: {
96403
+ spark: sparkFees
96404
+ },
96405
+ sparkFees,
96406
+ amountSats: safeAmountSats,
96407
+ onchainAddress: address
96408
+ };
96409
+ } catch (error) {
96410
+ return { success: false, error };
96411
+ }
96412
+ }
96413
+ async function prepareWithdrawal(wallet, network, { onchainAddress, amountSats, exitSpeed = DEFAULT_EXIT_SPEED, deductFeeFromWithdrawalAmount = true } = {}) {
96414
+ const quoted = await quoteWithdrawalFees(wallet, network, { onchainAddress, amountSats });
96415
+ if (!quoted.success) {
96416
+ return quoted;
96417
+ }
96418
+ try {
96419
+ const withdrawal = getWithdrawalReview({
96420
+ feeQuote: quoted.feeQuote,
96421
+ exitSpeed,
96422
+ amountSats: quoted.amountSats,
96423
+ onchainAddress: quoted.onchainAddress,
96424
+ deductFeeFromWithdrawalAmount
96425
+ });
96426
+ return {
96427
+ success: true,
96428
+ withdrawal,
96429
+ ...withdrawal
96430
+ };
96431
+ } catch (error) {
96432
+ return { success: false, error };
96433
+ }
96434
+ }
96435
+ async function withdrawFunds(wallet, network, { onchainAddress, amountSats, exitSpeed = DEFAULT_EXIT_SPEED, feeQuote = null, feeQuoteId = null, feeAmountSats = null, deductFeeFromWithdrawalAmount = true } = {}) {
96436
+ if (!wallet) {
96437
+ return { success: false, error: new Error("wallet not ready") };
96438
+ }
96439
+ const address = cleanText(onchainAddress);
96440
+ if (!isAddressOnNetwork(address, network)) {
96441
+ return { success: false, error: new Error(`refusing to withdraw - address is not a ${network} address`) };
96442
+ }
96443
+ try {
96444
+ const safeAmountSats = toSafeSats(amountSats);
96445
+ const safeExitSpeed = getExitSpeed(exitSpeed);
96446
+ let readyFeeQuote = feeQuote;
96447
+ if (!readyFeeQuote && (!feeQuoteId || feeAmountSats == null)) {
96448
+ const quoted = await quoteWithdrawalFees(wallet, network, {
96449
+ onchainAddress: address,
96450
+ amountSats: safeAmountSats
96451
+ });
96452
+ if (!quoted.success) {
96453
+ return quoted;
96454
+ }
96455
+ readyFeeQuote = quoted.feeQuote;
96456
+ }
96457
+ const readyFeeQuoteId = feeQuoteId || readyFeeQuote?.id;
96458
+ const readyFeeAmountSats = feeAmountSats == null ? getWithdrawalFeeAmountSats(readyFeeQuote, safeExitSpeed) : toSafeNonNegativeSats(feeAmountSats, "feeAmountSats");
96459
+ if (!readyFeeQuoteId || readyFeeAmountSats == null) {
96460
+ throw new Error("withdrawal fee quote unavailable");
96461
+ }
96462
+ assertWithdrawalReceivesFunds({
96463
+ amountSats: safeAmountSats,
96464
+ feeAmountSats: readyFeeAmountSats,
96465
+ deductFeeFromWithdrawalAmount
96466
+ });
96467
+ const tx2 = await wallet.withdraw({
96468
+ onchainAddress: address,
96469
+ amountSats: safeAmountSats,
96470
+ exitSpeed: safeExitSpeed,
96471
+ feeQuoteId: readyFeeQuoteId,
96472
+ feeAmountSats: readyFeeAmountSats,
96473
+ deductFeeFromWithdrawalAmount
96474
+ });
96475
+ return {
96476
+ success: true,
96477
+ tx: tx2,
96478
+ feeQuote: readyFeeQuote,
96479
+ fees: readyFeeQuote ? {
96480
+ spark: normalizeWithdrawalFeeQuote(readyFeeQuote)
96481
+ } : null,
96482
+ feeAmountSats: readyFeeAmountSats
96483
+ };
96484
+ } catch (error) {
96485
+ return { success: false, error };
96486
+ }
96487
+ }
96488
+
96489
+ // ../../shared/wallet/spark.js
96490
+ var import_bech32 = __toESM(require_dist(), 1);
96491
+ var SPARK_ADDRESS_PREFIX = Object.freeze({
96492
+ MAINNET: "spark",
96493
+ TESTNET: "sparkt",
96494
+ REGTEST: "sparkrt",
96495
+ SIGNET: "sparks",
96496
+ LOCAL: "sparkl"
96497
+ });
96498
+ function getSparkAddressPrefix(network) {
96499
+ const prefix2 = SPARK_ADDRESS_PREFIX[String(network ?? "").toUpperCase()];
96500
+ if (!prefix2) {
96501
+ throw new Error("invalid wallet network");
96502
+ }
96503
+ return prefix2;
96504
+ }
96505
+ function hexToBytes5(hex3) {
96506
+ const value = String(hex3 ?? "").trim();
96507
+ if (value.length % 2 !== 0) {
96508
+ throw new Error("invalid hex");
96509
+ }
96510
+ const bytes = new Uint8Array(value.length / 2);
96511
+ for (let i = 0;i < bytes.length; i++) {
96512
+ const start = i * 2;
96513
+ const byte = Number.parseInt(value.slice(start, start + 2), 16);
96514
+ if (Number.isNaN(byte)) {
96515
+ throw new Error("invalid hex");
96516
+ }
96517
+ bytes[i] = byte;
96518
+ }
96519
+ return bytes;
96520
+ }
96521
+ function walletPKtoSparkAddress(walletPK, network) {
96522
+ const key = hexToBytes5(walletPK);
96523
+ if (key.length !== 33) {
96524
+ throw new Error("need 33-byte compressed pubkey");
96525
+ }
96526
+ const payload = new Uint8Array(2 + key.length);
96527
+ payload[0] = 10;
96528
+ payload[1] = 33;
96529
+ payload.set(key, 2);
96530
+ return import_bech32.bech32m.encode(getSparkAddressPrefix(network), import_bech32.bech32m.toWords(payload), 1500);
96531
+ }
96532
+
96533
+ // ../../shared/account/actions/money.js
96534
+ function createMoneyActions({ readCloud, readSession, resolvePeer, sendPayload }) {
96535
+ function throwIfFailed(result, fallback = "wallet operation failed") {
96536
+ if (!result?.success) {
96537
+ throw result?.error || new Error(fallback);
96538
+ }
96539
+ return result;
96540
+ }
96541
+ function optionalPositiveSats(value, label = "amountSats") {
96542
+ if (value == null || value === "") {
96543
+ return null;
96544
+ }
96545
+ try {
96546
+ return cleanPositiveSats(value);
96547
+ } catch (error) {
96548
+ throw new Error(`${label} must be a positive safe integer`, { cause: error });
96549
+ }
96550
+ }
96551
+ function stripRaw(value, options = {}) {
96552
+ if (!value || typeof value !== "object") {
96553
+ return value;
96554
+ }
96555
+ const { raw, ...rest } = value;
96556
+ return options.raw ? { ...rest, raw: jsonSafe(raw) } : rest;
96557
+ }
96558
+ function stripFees(fees, options = {}) {
96559
+ if (!fees || typeof fees !== "object") {
96560
+ return fees || null;
96561
+ }
96562
+ return {
96563
+ ...fees,
96564
+ spark: stripRaw(fees.spark, options)
96565
+ };
96566
+ }
96567
+ function cleanWithdrawal(withdrawal, options = {}) {
96568
+ if (!withdrawal) {
96569
+ return null;
96570
+ }
96571
+ return {
96572
+ kind: withdrawal.kind,
96573
+ onchainAddress: withdrawal.onchainAddress,
96574
+ amountSats: withdrawal.amountSats,
96575
+ exitSpeed: withdrawal.exitSpeed,
96576
+ deductFeeFromWithdrawalAmount: withdrawal.deductFeeFromWithdrawalAmount,
96577
+ feeQuoteId: withdrawal.feeQuoteId,
96578
+ feeAmountSats: withdrawal.feeAmountSats,
96579
+ fees: stripFees(withdrawal.fees, options),
96580
+ amounts: getWithdrawalReviewAmounts(withdrawal),
96581
+ expiresAt: withdrawal.expiresAt,
96582
+ raw: options.raw ? jsonSafe(withdrawal.feeQuote) : undefined
96583
+ };
96584
+ }
96585
+ function firstSparkInvoiceError(result) {
96586
+ return result?.invalidInvoices?.[0]?.error || result?.satsTransactionErrors?.[0]?.error || result?.tokenTransactionErrors?.[0]?.error || null;
96587
+ }
96588
+ function firstSparkInvoiceSuccess(result) {
96589
+ return result?.satsTransactionSuccess?.[0]?.transferResponse || result?.tokenTransactionSuccess?.[0] || null;
96590
+ }
96591
+ function invoicePayload(value, options = {}) {
96592
+ const raw = cleanText(value);
96593
+ if (!raw) {
96594
+ throw new Error("invoice required");
96595
+ }
96596
+ const data = readQr(raw);
96597
+ const type = cleanText(options.type || data?.kind);
96598
+ const invoice2 = cleanText(data?.invoice || raw);
96599
+ if (type !== qr.lightning && type !== qr.spark) {
96600
+ throw new Error("invoice must be lightning or spark");
96601
+ }
96602
+ return { type, invoice: invoice2 };
96603
+ }
96604
+ async function balance(options = {}) {
96605
+ const active = await readSession();
96606
+ const raw = await active.wallet.getBalance();
96607
+ return {
96608
+ availableSats: balanceSats(raw),
96609
+ raw: options.raw ? jsonSafe(raw) : undefined
96610
+ };
96611
+ }
96612
+ async function address() {
96613
+ const active = await readSession();
96614
+ return {
96615
+ address: await getStaticFundingAddress(active.wallet, active.network),
96616
+ network: active.network
96617
+ };
96618
+ }
96619
+ async function claim(options = {}) {
96620
+ const active = await readSession();
96621
+ const depositsClaimed = await claimStaticDeposits(active.wallet, {
96622
+ getFundingAddress: () => getStaticFundingAddress(active.wallet, active.network)
96623
+ });
96624
+ const transferIds2 = await claimPendingIncomingTransfers(active.wallet, {
96625
+ limit: cleanLimit(options.count || options.limit, undefined)
96626
+ });
96627
+ return {
96628
+ claimed: depositsClaimed || transferIds2.length > 0,
96629
+ depositsClaimed,
96630
+ transferIds: transferIds2
96631
+ };
96632
+ }
96633
+ async function send(peer, sats, options = {}) {
96634
+ const active = await readSession();
96635
+ const amountSats = cleanPositiveSats(sats);
96636
+ const profile = await resolvePeer(peer);
96637
+ if (!profile.walletPK) {
96638
+ throw new Error("peer wallet key missing");
96639
+ }
96640
+ const receiverSparkAddress = walletPKtoSparkAddress(profile.walletPK, active.network);
96641
+ const tx2 = await active.wallet.transfer({ receiverSparkAddress, amountSats });
96642
+ return {
96643
+ txId: tx2?.id || null,
96644
+ amountSats,
96645
+ peer: profile.username ? `@${profile.username}` : profile.uid,
96646
+ raw: options.raw ? jsonSafe(tx2) : undefined
96647
+ };
96648
+ }
96649
+ async function invoice(sats = 0, options = {}) {
96650
+ const active = await readSession();
96651
+ const amountSats = toSafeNonNegativeSats(sats || 0);
96652
+ const result = throwIfFailed(await createLightningInvoice(active.wallet, {
96653
+ amountSats,
96654
+ memo: options.memo,
96655
+ expirySeconds: options.expirySeconds,
96656
+ includeSparkAddress: options.includeSparkAddress === true,
96657
+ includeSparkInvoice: options.includeSparkInvoice === true,
96658
+ receiverIdentityPubkey: options.receiverIdentityPubkey,
96659
+ descriptionHash: options.descriptionHash
96660
+ }), "could not create lightning invoice");
96661
+ return stripRaw(result.invoice, options);
96662
+ }
96663
+ async function lightningQuote(encodedInvoice, options = {}) {
96664
+ const active = await readSession();
96665
+ const result = throwIfFailed(await quoteLightningFees(active.wallet, {
96666
+ invoice: encodedInvoice,
96667
+ amountSats: options.amountSats
96668
+ }), "could not quote lightning fees");
96669
+ return {
96670
+ feeAmountSats: result.feeAmountSats,
96671
+ fees: result.fees
96672
+ };
96673
+ }
96674
+ async function lightningPay(encodedInvoice, options = {}) {
96675
+ const active = await readSession();
96676
+ const amountSatsToSend = options.amountSatsToSend ?? options.amountSats;
96677
+ let maxFeeSats = options.maxFeeSats;
96678
+ let fees = null;
96679
+ if (maxFeeSats == null) {
96680
+ const quote = throwIfFailed(await quoteLightningFees(active.wallet, {
96681
+ invoice: encodedInvoice,
96682
+ amountSats: amountSatsToSend
96683
+ }), "could not quote lightning fees");
96684
+ maxFeeSats = quote.feeAmountSats;
96685
+ fees = quote.fees;
96686
+ }
96687
+ const result = throwIfFailed(await sendLightningPayment(active.wallet, {
96688
+ invoice: encodedInvoice,
96689
+ maxFeeSats,
96690
+ preferSpark: options.preferSpark === true,
96691
+ amountSatsToSend,
96692
+ idempotencyKey: options.idempotencyKey
96693
+ }), "could not pay lightning invoice");
96694
+ return {
96695
+ id: result.result?.id || result.payment?.id || null,
96696
+ fees,
96697
+ result: stripRaw(result.result, options),
96698
+ raw: options.raw ? jsonSafe(result.payment) : undefined
96699
+ };
96700
+ }
96701
+ async function lightningReceive(id, options = {}) {
96702
+ const active = await readSession();
96703
+ const result = throwIfFailed(await getLightningReceiveRequest(active.wallet, id), "could not read lightning receive request");
96704
+ return stripRaw(result.invoice, options);
96705
+ }
96706
+ async function lightningSend(id, options = {}) {
96707
+ const active = await readSession();
96708
+ const result = throwIfFailed(await getLightningSendRequest(active.wallet, id), "could not read lightning send request");
96709
+ return stripRaw(result.result, options);
96710
+ }
96711
+ async function payInvoice(value, options = {}) {
96712
+ const active = await readSession();
96713
+ const { type, invoice: invoice2 } = invoicePayload(value, options);
96714
+ if (type === qr.lightning) {
96715
+ return {
96716
+ type,
96717
+ ...await lightningPay(invoice2, { ...options, preferSpark: options.preferSpark !== false })
96718
+ };
96719
+ }
96720
+ const amountSats = optionalPositiveSats(options.amountSats, "amountSats");
96721
+ const result = await active.wallet.fulfillSparkInvoice([
96722
+ {
96723
+ invoice: invoice2,
96724
+ ...amountSats != null ? { amount: BigInt(amountSats) } : {}
96725
+ }
96726
+ ]);
96727
+ const error = firstSparkInvoiceError(result);
96728
+ if (error) {
96729
+ throw error instanceof Error ? error : new Error(String(error));
96730
+ }
96731
+ const success = firstSparkInvoiceSuccess(result);
96732
+ if (!success) {
96733
+ throw new Error("failed to pay spark invoice");
96734
+ }
96735
+ return {
96736
+ type,
96737
+ id: success.id || success.txid || null,
96738
+ transfer: simplifyAccountTransfer(success),
96739
+ raw: options.raw ? jsonSafe(result) : undefined
96740
+ };
96741
+ }
96742
+ async function withdrawQuote(onchainAddress, sats, options = {}) {
96743
+ const active = await readSession();
96744
+ const result = throwIfFailed(await quoteWithdrawalFees(active.wallet, active.network, {
96745
+ onchainAddress,
96746
+ amountSats: sats
96747
+ }), "could not quote withdrawal");
96748
+ return {
96749
+ amountSats: result.amountSats,
96750
+ onchainAddress: result.onchainAddress,
96751
+ feeQuoteId: result.feeQuote?.id || null,
96752
+ fees: stripFees(result.fees, options),
96753
+ raw: options.raw ? jsonSafe(result.feeQuote) : undefined
96754
+ };
96755
+ }
96756
+ async function withdrawPrepare(onchainAddress, sats, options = {}) {
96757
+ const active = await readSession();
96758
+ const result = throwIfFailed(await prepareWithdrawal(active.wallet, active.network, {
96759
+ onchainAddress,
96760
+ amountSats: sats,
96761
+ exitSpeed: options.exitSpeed || options.speed,
96762
+ deductFeeFromWithdrawalAmount: options.deductFeeFromWithdrawalAmount !== false
96763
+ }), "could not prepare withdrawal");
96764
+ return cleanWithdrawal(result.withdrawal, options);
96765
+ }
96766
+ async function withdraw(onchainAddress, sats, options = {}) {
96767
+ const active = await readSession();
96768
+ const result = throwIfFailed(await withdrawFunds(active.wallet, active.network, {
96769
+ onchainAddress,
96770
+ amountSats: sats,
96771
+ exitSpeed: options.exitSpeed || options.speed,
96772
+ feeQuote: options.feeQuote,
96773
+ feeQuoteId: options.feeQuoteId,
96774
+ feeAmountSats: options.feeAmountSats,
96775
+ deductFeeFromWithdrawalAmount: options.deductFeeFromWithdrawalAmount !== false
96776
+ }), "could not withdraw funds");
96777
+ return {
96778
+ txId: result.tx?.id || result.tx?.txid || null,
96779
+ feeAmountSats: result.feeAmountSats,
96780
+ fees: stripFees(result.fees, options),
96781
+ tx: options.raw ? jsonSafe(result.tx) : undefined
96782
+ };
96783
+ }
96784
+ async function request(peer, sats, options = {}) {
96785
+ return sendPayload(peer, makeReq(String(cleanPositiveSats(sats))), options);
96786
+ }
96787
+ async function pay(requestId, options = {}) {
96788
+ const active = await readSession();
96789
+ const { chatId, messageId } = parseRequestRef(requestId);
96790
+ const chat = await getChat(readCloud(), active.uid, chatId, active.chatPK, active.chatPrivKey);
96791
+ if (!chat) {
96792
+ throw new Error("request chat not found");
96793
+ }
96794
+ const record = await readCloud().chat.messages.read(chat.id, messageId);
96795
+ const message = await decryptMsg(record, active.chatPK, active.chatPrivKey, chat.peerChatPK, {
96796
+ actors: chat.actors,
96797
+ chatId: chat.id
96798
+ });
96799
+ if (!message || message.t !== "req") {
96800
+ throw new Error("payment request not found");
96801
+ }
96802
+ if (message.tx) {
96803
+ throw new Error("payment request already paid");
96804
+ }
96805
+ if (!isPeerMsg(message, active.chatPK)) {
96806
+ throw new Error("cannot pay your own request");
96807
+ }
96808
+ const amountSats = cleanPositiveSats(message.a);
96809
+ const profile = await resolvePeer(message.from || message.s || chat.peerChatPK);
96810
+ if (!profile.walletPK) {
96811
+ throw new Error("requester wallet key missing");
96812
+ }
96813
+ const paid = await send(profile.walletPK, amountSats, { raw: options.raw === true });
96814
+ const newMessage = { ...setReqTx(message, paid.txId), cid: message.cid };
96815
+ await updateMsg(readCloud(), chat.id, message.id, active.chatPK, active.chatPrivKey, chat.peerChatPK, newMessage, {
96816
+ senderUid: active.uid,
96817
+ receiverUid: chat.peerUid,
96818
+ linkId: chat.linkId,
96819
+ peerActorPK: chat.actors?.[chat.peerChatPK]
96820
+ });
96821
+ return {
96822
+ ...paid,
96823
+ requestId: requestRef(chat.id, message.id)
96824
+ };
96825
+ }
96826
+ async function transactions(options = {}) {
96827
+ const active = await readSession();
96828
+ const limit = cleanLimit(options.count || options.limit, 50);
96829
+ const offset = Math.max(0, Math.floor(Number(options.offset || 0)) || 0);
96830
+ const page = await active.wallet.getTransfers(limit, offset);
96831
+ const transfers = (page?.transfers || []).filter((tx2) => isVisibleTransfer(tx2) && transferBelongsToWallet(tx2, active.walletPK)).map(simplifyAccountTransfer);
96832
+ return {
96833
+ transfers,
96834
+ raw: options.raw ? jsonSafe(page) : undefined
96835
+ };
96836
+ }
96837
+ return {
96838
+ address,
96839
+ balance,
96840
+ claim,
96841
+ invoice,
96842
+ lightningQuote,
96843
+ lightningPay,
96844
+ lightningReceive,
96845
+ lightningSend,
96846
+ payInvoice,
96847
+ receive: address,
96848
+ send,
96849
+ request,
96850
+ pay,
96851
+ transactions,
96852
+ withdrawQuote,
96853
+ withdrawPrepare,
96854
+ withdraw
96855
+ };
96856
+ }
96857
+
96858
+ // ../../shared/wallet/keys.js
96859
+ "use client";
96860
+ var VALID_WALLET_NETWORKS = new Set(["MAINNET", "REGTEST", "TESTNET", "SIGNET", "LOCAL"]);
96861
+ function normalizeWalletNetwork(network) {
96862
+ const next = String(network ?? "").trim().toUpperCase();
96863
+ if (!VALID_WALLET_NETWORKS.has(next)) {
96864
+ throw new Error("invalid wallet network");
96865
+ }
96866
+ return next;
96867
+ }
96868
+ function walletPKField(network) {
96869
+ return `walletPKs.${normalizeWalletNetwork(network)}`;
96870
+ }
96871
+ function resolveWalletPK(data, network) {
96872
+ const key = normalizeWalletNetwork(network);
96873
+ const walletPKs = data?.walletPKs;
96874
+ const walletPK = walletPKs && typeof walletPKs === "object" && typeof walletPKs[key] === "string" ? walletPKs[key].trim() : "";
96875
+ if (walletPK) {
96876
+ return normalizeWalletPK(walletPK);
96877
+ }
96878
+ return null;
96879
+ }
96880
+ function normalizeWalletPK(walletPK) {
96881
+ return typeof walletPK === "string" ? lowerText(walletPK) : walletPK;
96882
+ }
96883
+
96884
+ // ../../shared/account/actions/peers.js
96885
+ function createPeerResolver({ readCloud, readSession }) {
96886
+ async function resolve(peer) {
94637
96887
  const active = await readSession();
94638
96888
  const value = cleanPeer(peer);
96889
+ const cloud = readCloud();
94639
96890
  let profile;
94640
96891
  if (CHAT_PK_RE.test(value)) {
94641
- profile = await readCloud().search.peer.byChatPK(value);
96892
+ profile = await cloud.search.peer.byChatPK(value);
94642
96893
  } else if (WALLET_PK_RE.test(value)) {
94643
- profile = await readCloud().search.peer.byWalletPK(value, { network: active.network });
96894
+ profile = await cloud.search.peer.byWalletPK(value, { network: active.network });
94644
96895
  } else {
94645
- profile = await readCloud().search.peer.byUsername(value);
96896
+ profile = await cloud.search.peer.byUsername(value);
94646
96897
  }
94647
96898
  if (!profile) {
94648
96899
  throw new Error("peer not found");
@@ -94656,225 +96907,44 @@ function createAccountSessionActions({ cloud, getSession, session } = {}) {
94656
96907
  walletPK
94657
96908
  };
94658
96909
  }
94659
- async function peerMapForChats(chats) {
96910
+ async function mapForChats(chats) {
94660
96911
  const peerChatPKs = [...new Set((chats || []).map((chat) => chat.peerChatPK).filter(Boolean))];
94661
96912
  const peers = peerChatPKs.length ? await readCloud().search.peer.byChatPKs(peerChatPKs) : [];
94662
96913
  return new Map((peers || []).map((peer) => [peer.chatPK, peer]));
94663
96914
  }
94664
- async function listChats(options = {}) {
94665
- const active = await readSession();
94666
- const chats = await loadAllChats(readCloud(), active.uid, active.chatPK, active.chatPrivKey, cleanLimit(options.count || options.limit, 30));
94667
- const peers = await peerMapForChats(chats);
94668
- return chats.map((chat) => simplifyAccountChat(chat, peers.get(chat.peerChatPK)));
94669
- }
94670
- async function chatForPeer(peer, options = {}) {
94671
- const active = await readSession();
94672
- if (CHAT_PK_RE.test(String(peer ?? "").trim())) {
94673
- const chatId = String(peer).trim().toLowerCase();
94674
- const chat = await getChat(readCloud(), active.uid, chatId, active.chatPK, active.chatPrivKey);
94675
- if (chat) {
94676
- return chat;
94677
- }
94678
- }
94679
- const profile = await resolvePeer(peer);
94680
- const chats = await loadAllChats(readCloud(), active.uid, active.chatPK, active.chatPrivKey, cleanLimit(options.count, 50));
94681
- return chats.find((chat) => chat.peerChatPK === profile.chatPK) || null;
94682
- }
94683
- async function readChat(peer, options = {}) {
94684
- const active = await readSession();
94685
- const chat = await chatForPeer(peer, options);
94686
- if (!chat) {
94687
- return { chat: null, messages: [] };
94688
- }
94689
- const page = await readCloud().chat.messages.list(chat.id, { count: cleanLimit(options.count || options.limit, 30) });
94690
- const decrypted = [];
94691
- for (const record of page.records || []) {
94692
- const message = await decryptMsg(record, active.chatPK, active.chatPrivKey, chat.peerChatPK, {
94693
- actors: chat.actors,
94694
- chatId: chat.id
94695
- });
94696
- if (message) {
94697
- decrypted.push(message);
94698
- }
94699
- }
94700
- const display = getDisplayMessages(decrypted, active.chatPK, chat.peerChatPK).filter(canShowMsg);
94701
- const messages = display.map((message) => simplifyAccountMessage(message, chat, active.chatPK, options));
94702
- if (options.markRead !== false) {
94703
- const lastPeer = [...display].reverse().find((message) => isPeerMsg(message, active.chatPK));
94704
- if (lastPeer?.id) {
94705
- await setChatRead(readCloud(), active.uid, active.chatPrivKey, chat.id, lastPeer.ts).catch(() => {});
94706
- const target = getMessageKey(lastPeer);
94707
- if (target) {
94708
- await sendReadReceipt(readCloud(), active.chatPK, active.chatPrivKey, chat.peerChatPK, target, {
94709
- chatId: chat.id,
94710
- senderUid: active.uid,
94711
- receiverUid: chat.peerUid,
94712
- linkId: chat.linkId,
94713
- peerActorPK: chat.actors?.[chat.peerChatPK],
94714
- ping: true
94715
- }).catch(() => {});
94716
- }
94717
- }
94718
- }
94719
- return {
94720
- chat: simplifyAccountChat(chat),
94721
- messages,
94722
- hasMore: page.hasMore === true,
94723
- nextOlderThan: page.nextOlderThan || null
94724
- };
94725
- }
94726
- async function sendPayload(peer, payload, options = {}) {
94727
- const active = await readSession();
94728
- const profile = await resolvePeer(peer);
94729
- if (!profile.chatPK) {
94730
- throw new Error("peer chat key missing");
94731
- }
94732
- if (profile.chatPK === active.chatPK) {
94733
- throw new Error("cannot message self");
94734
- }
94735
- const link = await resolvePeerChat(readCloud(), active.chatPK, active.chatPrivKey, profile.chatPK, options);
94736
- const sent = await sendMsg(readCloud(), active.chatPK, active.chatPrivKey, profile.chatPK, payload, {
94737
- ...options,
94738
- chatId: link.chatId,
94739
- linkId: link.linkId,
94740
- linkVersion: link.version,
94741
- protocol: link.protocol,
94742
- senderUid: active.uid,
94743
- receiverUid: profile.uid,
94744
- peerActorPK: profile.actorPK
94745
- });
94746
- return {
94747
- chat: {
94748
- id: sent.chatId,
94749
- peerChatPK: profile.chatPK,
94750
- username: profile.username
94751
- },
94752
- message: simplifyAccountMessage(sent.message, { id: sent.chatId, peerChatPK: profile.chatPK }, active.chatPK, options)
94753
- };
94754
- }
94755
- async function sendChat(peer, message, options = {}) {
94756
- return sendPayload(peer, makeTxt(cleanMessage(message)), options);
94757
- }
94758
- async function balance(options = {}) {
94759
- const active = await readSession();
94760
- const raw = await active.wallet.getBalance();
94761
- return {
94762
- availableSats: balanceSats(raw),
94763
- raw: options.raw === false ? undefined : jsonSafe(raw)
94764
- };
94765
- }
94766
- async function sendMoney(peer, sats, options = {}) {
94767
- const active = await readSession();
94768
- const amountSats = cleanPositiveSats(sats);
94769
- const profile = await resolvePeer(peer);
94770
- if (!profile.walletPK) {
94771
- throw new Error("peer wallet key missing");
94772
- }
94773
- const receiverSparkAddress = walletPKtoSparkAddress(profile.walletPK, active.network);
94774
- const tx = await active.wallet.transfer({ receiverSparkAddress, amountSats });
94775
- return {
94776
- txId: tx?.id || null,
94777
- amountSats,
94778
- peer: profile.username ? `@${profile.username}` : profile.uid,
94779
- raw: options.raw ? jsonSafe(tx) : undefined
94780
- };
94781
- }
94782
- async function requestMoney(peer, sats, options = {}) {
94783
- return sendPayload(peer, makeReq(String(cleanPositiveSats(sats))), options);
94784
- }
94785
- async function payRequest(requestId, options = {}) {
94786
- const active = await readSession();
94787
- const { chatId, messageId } = parseRequestRef(requestId);
94788
- const chat = await getChat(readCloud(), active.uid, chatId, active.chatPK, active.chatPrivKey);
94789
- if (!chat) {
94790
- throw new Error("request chat not found");
94791
- }
94792
- const record = await readCloud().chat.messages.read(chat.id, messageId);
94793
- const message = await decryptMsg(record, active.chatPK, active.chatPrivKey, chat.peerChatPK, {
94794
- actors: chat.actors,
94795
- chatId: chat.id
94796
- });
94797
- if (!message || message.t !== "req") {
94798
- throw new Error("payment request not found");
94799
- }
94800
- if (message.tx) {
94801
- throw new Error("payment request already paid");
94802
- }
94803
- if (!isPeerMsg(message, active.chatPK)) {
94804
- throw new Error("cannot pay your own request");
94805
- }
94806
- const amountSats = cleanPositiveSats(message.a);
94807
- const profile = await resolvePeer(message.from || message.s || chat.peerChatPK);
94808
- if (!profile.walletPK) {
94809
- throw new Error("requester wallet key missing");
94810
- }
94811
- const paid = await sendMoney(profile.walletPK, amountSats, { raw: true });
94812
- const newMessage = { ...setReqTx(message, paid.txId), cid: message.cid };
94813
- await updateMsg(readCloud(), chat.id, message.id, active.chatPK, active.chatPrivKey, chat.peerChatPK, newMessage, {
94814
- senderUid: active.uid,
94815
- receiverUid: chat.peerUid,
94816
- linkId: chat.linkId,
94817
- peerActorPK: chat.actors?.[chat.peerChatPK]
94818
- });
94819
- return {
94820
- ...paid,
94821
- requestId: requestRef(chat.id, message.id)
94822
- };
94823
- }
94824
- async function transactions(options = {}) {
94825
- const active = await readSession();
94826
- const limit = cleanLimit(options.count || options.limit, 50);
94827
- const offset = Math.max(0, Math.floor(Number(options.offset || 0)) || 0);
94828
- const page = await active.wallet.getTransfers(limit, offset);
94829
- const transfers = (page?.transfers || []).filter((tx) => isVisibleTransfer(tx) && transferBelongsToWallet(tx, active.walletPK)).map(simplifyAccountTransfer);
94830
- return {
94831
- transfers,
94832
- raw: options.raw ? jsonSafe(page) : undefined
94833
- };
94834
- }
96915
+ return { resolve, mapForChats };
96916
+ }
96917
+
96918
+ // ../../shared/account/actions.js
96919
+ function createAccountSessionActions({ cloud, getSession, session } = {}) {
96920
+ const readCloud = () => requireCloud(typeof cloud === "function" ? cloud() : cloud);
96921
+ const readSession = async () => requireSession(typeof getSession === "function" ? await getSession() : session);
96922
+ const peers = createPeerResolver({ readCloud, readSession });
96923
+ const inbox = createInboxSync({ readCloud });
96924
+ const chat = createChatActions({
96925
+ readCloud,
96926
+ readSession,
96927
+ inbox,
96928
+ peers
96929
+ });
96930
+ const money = createMoneyActions({
96931
+ readCloud,
96932
+ readSession,
96933
+ resolvePeer: peers.resolve,
96934
+ sendPayload: chat.sendPayload
96935
+ });
94835
96936
  return {
94836
96937
  peer: {
94837
- resolve: resolvePeer
94838
- },
94839
- chat: {
94840
- list: listChats,
94841
- chatForPeer,
94842
- read: readChat,
94843
- send: sendChat,
94844
- sendPayload
94845
- },
94846
- money: {
94847
- balance,
94848
- send: sendMoney,
94849
- request: requestMoney,
94850
- pay: payRequest,
94851
- transactions
96938
+ resolve: peers.resolve
94852
96939
  },
96940
+ chat,
96941
+ money,
94853
96942
  transactions: {
94854
- list: transactions
96943
+ list: money.transactions
94855
96944
  }
94856
96945
  };
94857
96946
  }
94858
96947
 
94859
- // ../../shared/network.js
94860
- var DEFAULT_NETWORK = "REGTEST";
94861
- var MAINNET_DOMAIN = domains.veyl;
94862
- var REGTEST_DOMAIN = domains.veylTest;
94863
- function resolveNetwork(env = {}) {
94864
- const raw = env?.EXPO_PUBLIC_NETWORK ?? env?.NEXT_PUBLIC_NETWORK ?? env?.VEYL_NETWORK ?? env?.NETWORK ?? DEFAULT_NETWORK;
94865
- return String(raw).toUpperCase();
94866
- }
94867
-
94868
- // ../../shared/username.js
94869
- var MAX_USERNAME = USERNAME_MAX_CHARS;
94870
- var usernameRegex = new RegExp(`^[a-z0-9]{1,${MAX_USERNAME}}$`);
94871
- function normalizeUsername(value = "") {
94872
- return String(value).trim().toLowerCase();
94873
- }
94874
- function isUsername(value = "") {
94875
- return usernameRegex.test(value);
94876
- }
94877
-
94878
96948
  // ../../node_modules/.bun/@firebase+util@1.15.1/node_modules/@firebase/util/dist/postinstall.mjs
94879
96949
  var getDefaultsFromPostinstall = () => {
94880
96950
  return;
@@ -95899,28 +97969,28 @@ function promisifyRequest(request) {
95899
97969
  reverseTransformCache.set(promise, request);
95900
97970
  return promise;
95901
97971
  }
95902
- function cacheDonePromiseForTransaction(tx) {
95903
- if (transactionDoneMap.has(tx))
97972
+ function cacheDonePromiseForTransaction(tx2) {
97973
+ if (transactionDoneMap.has(tx2))
95904
97974
  return;
95905
97975
  const done = new Promise((resolve, reject) => {
95906
97976
  const unlisten = () => {
95907
- tx.removeEventListener("complete", complete);
95908
- tx.removeEventListener("error", error);
95909
- tx.removeEventListener("abort", error);
97977
+ tx2.removeEventListener("complete", complete);
97978
+ tx2.removeEventListener("error", error);
97979
+ tx2.removeEventListener("abort", error);
95910
97980
  };
95911
97981
  const complete = () => {
95912
97982
  resolve();
95913
97983
  unlisten();
95914
97984
  };
95915
97985
  const error = () => {
95916
- reject(tx.error || new DOMException("AbortError", "AbortError"));
97986
+ reject(tx2.error || new DOMException("AbortError", "AbortError"));
95917
97987
  unlisten();
95918
97988
  };
95919
- tx.addEventListener("complete", complete);
95920
- tx.addEventListener("error", error);
95921
- tx.addEventListener("abort", error);
97989
+ tx2.addEventListener("complete", complete);
97990
+ tx2.addEventListener("error", error);
97991
+ tx2.addEventListener("abort", error);
95922
97992
  });
95923
- transactionDoneMap.set(tx, done);
97993
+ transactionDoneMap.set(tx2, done);
95924
97994
  }
95925
97995
  var idbProxyTraps = {
95926
97996
  get(target, prop, receiver) {
@@ -95953,9 +98023,9 @@ function replaceTraps(callback) {
95953
98023
  function wrapFunction(func) {
95954
98024
  if (func === IDBDatabase.prototype.transaction && !("objectStoreNames" in IDBTransaction.prototype)) {
95955
98025
  return function(storeNames, ...args) {
95956
- const tx = func.call(unwrap(this), storeNames, ...args);
95957
- transactionStoreNamesMap.set(tx, storeNames.sort ? storeNames.sort() : [storeNames]);
95958
- return wrap3(tx);
98026
+ const tx2 = func.call(unwrap(this), storeNames, ...args);
98027
+ transactionStoreNamesMap.set(tx2, storeNames.sort ? storeNames.sort() : [storeNames]);
98028
+ return wrap3(tx2);
95959
98029
  };
95960
98030
  }
95961
98031
  if (getCursorAdvanceMethods().includes(func)) {
@@ -96028,13 +98098,13 @@ function getMethod2(target, prop) {
96028
98098
  return;
96029
98099
  }
96030
98100
  const method = async function(storeName, ...args) {
96031
- const tx = this.transaction(storeName, isWrite ? "readwrite" : "readonly");
96032
- let target2 = tx.store;
98101
+ const tx2 = this.transaction(storeName, isWrite ? "readwrite" : "readonly");
98102
+ let target2 = tx2.store;
96033
98103
  if (useIndex)
96034
98104
  target2 = target2.index(args.shift());
96035
98105
  return (await Promise.all([
96036
98106
  target2[targetFuncName](...args),
96037
- isWrite && tx.done
98107
+ isWrite && tx2.done
96038
98108
  ]))[0];
96039
98109
  };
96040
98110
  cachedMethods.set(prop, method);
@@ -96333,9 +98403,9 @@ function getDbPromise() {
96333
98403
  async function readHeartbeatsFromIndexedDB(app) {
96334
98404
  try {
96335
98405
  const db = await getDbPromise();
96336
- const tx = db.transaction(STORE_NAME);
96337
- const result = await tx.objectStore(STORE_NAME).get(computeKey(app));
96338
- await tx.done;
98406
+ const tx2 = db.transaction(STORE_NAME);
98407
+ const result = await tx2.objectStore(STORE_NAME).get(computeKey(app));
98408
+ await tx2.done;
96339
98409
  return result;
96340
98410
  } catch (e) {
96341
98411
  if (e instanceof FirebaseError) {
@@ -96351,10 +98421,10 @@ async function readHeartbeatsFromIndexedDB(app) {
96351
98421
  async function writeHeartbeatsToIndexedDB(app, heartbeatObject) {
96352
98422
  try {
96353
98423
  const db = await getDbPromise();
96354
- const tx = db.transaction(STORE_NAME, "readwrite");
96355
- const objectStore = tx.objectStore(STORE_NAME);
98424
+ const tx2 = db.transaction(STORE_NAME, "readwrite");
98425
+ const objectStore = tx2.objectStore(STORE_NAME);
96356
98426
  await objectStore.put(heartbeatObject, computeKey(app));
96357
- await tx.done;
98427
+ await tx2.done;
96358
98428
  } catch (e) {
96359
98429
  if (e instanceof FirebaseError) {
96360
98430
  logger2.warn(e.message);
@@ -123104,16 +125174,16 @@ function syncEngineGetRemoteKeysForTarget(syncEngine, targetId) {
123104
125174
  if (limboResolution && limboResolution.receivedDocument) {
123105
125175
  return documentKeySet().add(limboResolution.key);
123106
125176
  } else {
123107
- let keySet = documentKeySet();
125177
+ let keySet2 = documentKeySet();
123108
125178
  const queries = syncEngineImpl.queriesByTarget.get(targetId);
123109
125179
  if (!queries) {
123110
- return keySet;
125180
+ return keySet2;
123111
125181
  }
123112
125182
  for (const query of queries ?? []) {
123113
125183
  const queryView = syncEngineImpl.queryViewsByQuery.get(query);
123114
- keySet = keySet.unionWith(queryView.view.syncedDocuments);
125184
+ keySet2 = keySet2.unionWith(queryView.view.syncedDocuments);
123115
125185
  }
123116
- return keySet;
125186
+ return keySet2;
123117
125187
  }
123118
125188
  }
123119
125189
  function ensureWatchCallbacks(syncEngine) {
@@ -132196,6 +134266,9 @@ var DEFAULT_INTERVAL_MS = 3000;
132196
134266
  var DEFAULT_CHAT_COUNT = 20;
132197
134267
  var DEFAULT_MESSAGE_COUNT = 10;
132198
134268
  var DEFAULT_TX_COUNT = 50;
134269
+ function cleanString(value) {
134270
+ return String(value ?? "").trim();
134271
+ }
132199
134272
  function cleanCount(value, fallback) {
132200
134273
  const count = Math.floor(Number(value));
132201
134274
  return Number.isFinite(count) && count > 0 ? Math.min(count, 100) : fallback;
@@ -132214,13 +134287,13 @@ function messageKey(message) {
132214
134287
  message?.ts || ""
132215
134288
  ].join(":");
132216
134289
  }
132217
- function transferKey(tx) {
134290
+ function transferKey(tx2) {
132218
134291
  return [
132219
- tx?.id || "",
132220
- tx?.status || "",
132221
- tx?.direction || "",
132222
- tx?.amountSats || "",
132223
- tx?.updatedAt || ""
134292
+ tx2?.id || "",
134293
+ tx2?.status || "",
134294
+ tx2?.direction || "",
134295
+ tx2?.amountSats || "",
134296
+ tx2?.updatedAt || ""
132224
134297
  ].join(":");
132225
134298
  }
132226
134299
  function event(type, data = {}) {
@@ -132230,10 +134303,112 @@ function event(type, data = {}) {
132230
134303
  ...data
132231
134304
  };
132232
134305
  }
134306
+ function peerTarget(chat) {
134307
+ const username = cleanString(chat?.username).replace(/^@+/, "");
134308
+ return username ? `@${username}` : cleanString(chat?.peerChatPK || chat?.id);
134309
+ }
134310
+ function compactAccount(account) {
134311
+ return account ? {
134312
+ uid: account.uid || null,
134313
+ username: account.username || null,
134314
+ network: account.network || null,
134315
+ auth: account.auth || null,
134316
+ bot: account.bot || null,
134317
+ unlocked: account.unlocked === true
134318
+ } : null;
134319
+ }
134320
+ function compactChat(chat) {
134321
+ const peer = peerTarget(chat);
134322
+ return {
134323
+ id: chat?.id || null,
134324
+ peer,
134325
+ username: chat?.username || null,
134326
+ peerChatPK: chat?.peerChatPK || null,
134327
+ peerUid: chat?.peerUid || null,
134328
+ unseen: chat?.unseen === true,
134329
+ ts: chat?.ts || null
134330
+ };
134331
+ }
134332
+ function compactPayload(message) {
134333
+ const payload = message?.payload && typeof message.payload === "object" ? message.payload : {};
134334
+ if (message?.type === "rxn") {
134335
+ return {
134336
+ target: payload.target || null,
134337
+ emoji: payload.emoji || null
134338
+ };
134339
+ }
134340
+ if (message?.type === "img" || message?.type === "gif" || message?.type === "m4a" || message?.type === "mp4" || message?.type === "file") {
134341
+ return {
134342
+ name: payload.n || null,
134343
+ caption: payload.c || null,
134344
+ mime: payload.m || null,
134345
+ size: payload.z || null,
134346
+ width: payload.w || null,
134347
+ height: payload.h || null
134348
+ };
134349
+ }
134350
+ if (message?.type === "sys") {
134351
+ return {
134352
+ action: payload.action || payload.kind || null,
134353
+ value: payload.value || null
134354
+ };
134355
+ }
134356
+ return {};
134357
+ }
134358
+ function compactMessage(message) {
134359
+ const item = {
134360
+ id: message?.id || null,
134361
+ cid: message?.cid || null,
134362
+ chatId: message?.chatId || null,
134363
+ from: message?.from || null,
134364
+ type: message?.type || null,
134365
+ ts: message?.ts || null,
134366
+ peerChatPK: message?.peerChatPK || null
134367
+ };
134368
+ if (message?.replyId) {
134369
+ item.replyId = message.replyId;
134370
+ }
134371
+ if (message?.type === "txt") {
134372
+ item.text = message.text || "";
134373
+ } else if (message?.type === "req") {
134374
+ item.amountSats = message.amountSats || 0;
134375
+ item.paid = message.paid === true;
134376
+ item.txId = message.txId || null;
134377
+ item.requestId = message.requestId || null;
134378
+ } else {
134379
+ Object.assign(item, compactPayload(message));
134380
+ }
134381
+ return item;
134382
+ }
134383
+ function formatMessageEvent(chat, message, { compact = false } = {}) {
134384
+ const targetChat = compact ? compactChat(chat) : chat;
134385
+ const peer = peerTarget(chat);
134386
+ const messageId = message?.id || message?.cid || null;
134387
+ const target = messageId ? { peer, messageId } : null;
134388
+ return event("message", {
134389
+ peer,
134390
+ replyTo: target,
134391
+ reactTo: target,
134392
+ chat: targetChat,
134393
+ message: compact ? compactMessage(message) : message
134394
+ });
134395
+ }
132233
134396
  function stopped(signal) {
132234
134397
  return signal?.aborted === true;
132235
134398
  }
134399
+ function eventChat(source, pageChat) {
134400
+ return {
134401
+ ...source || {},
134402
+ ...pageChat || {},
134403
+ username: pageChat?.username || source?.username || null,
134404
+ peerUid: pageChat?.peerUid || source?.peerUid || null,
134405
+ peerChatPK: pageChat?.peerChatPK || source?.peerChatPK || null,
134406
+ id: pageChat?.id || source?.id || null
134407
+ };
134408
+ }
132236
134409
  async function listenAccount(client2, options2 = {}) {
134410
+ const compact = options2.compact === true || options2.agent === true;
134411
+ const incomingOnly = options2.incomingOnly === false ? false : options2.incomingOnly === true || options2.incoming === true || options2.agent === true;
132237
134412
  const intervalMs = cleanInterval(options2.intervalMs || options2.interval);
132238
134413
  const chatCount = cleanCount(options2.chatCount || options2.chats, DEFAULT_CHAT_COUNT);
132239
134414
  const messageCount = cleanCount(options2.messageCount || options2.messages, DEFAULT_MESSAGE_COUNT);
@@ -132244,58 +134419,90 @@ async function listenAccount(client2, options2 = {}) {
132244
134419
  const emit = typeof options2.onEvent === "function" ? options2.onEvent : () => {};
132245
134420
  const seenMessages = new Set;
132246
134421
  const seenTransfers = new Map;
132247
- let initialized = false;
132248
134422
  await client2.ensureUnlocked();
132249
- emit(event("ready", { account: client2.accountSummary() }));
132250
- while (!stopped(options2.signal)) {
132251
- try {
132252
- if (includeChats) {
132253
- const chats = await client2.chat.list({ count: chatCount });
132254
- for (const chat of chats) {
132255
- const peer = chat.peerChatPK || chat.username || chat.id;
132256
- if (!peer) {
132257
- continue;
132258
- }
132259
- const page = await client2.chat.read(peer, {
134423
+ const account = client2.accountSummary();
134424
+ async function poll(emitChanges) {
134425
+ if (includeChats) {
134426
+ const chats = await client2.chat.list({ count: chatCount });
134427
+ for (const chat of chats) {
134428
+ const peer = chat.peerChatPK || chat.username || chat.id;
134429
+ if (!peer) {
134430
+ continue;
134431
+ }
134432
+ let page;
134433
+ try {
134434
+ page = await client2.chat.read(peer, {
132260
134435
  count: messageCount,
132261
134436
  markRead: false
132262
134437
  });
132263
- for (const message of page.messages || []) {
132264
- const key = messageKey(message);
132265
- if (!key || seenMessages.has(key)) {
132266
- continue;
132267
- }
132268
- seenMessages.add(key);
132269
- if (initialized || replay) {
132270
- emit(event("message", {
132271
- chat: page.chat || chat,
132272
- message
132273
- }));
132274
- }
134438
+ } catch (error) {
134439
+ emit(event("error", {
134440
+ peer: peerTarget(chat),
134441
+ message: error?.message || String(error)
134442
+ }));
134443
+ continue;
134444
+ }
134445
+ for (const message of page.messages || []) {
134446
+ const key = messageKey(message);
134447
+ if (!key || seenMessages.has(key)) {
134448
+ continue;
134449
+ }
134450
+ seenMessages.add(key);
134451
+ if (incomingOnly && message.from !== "peer") {
134452
+ continue;
134453
+ }
134454
+ if (emitChanges) {
134455
+ emit(formatMessageEvent(eventChat(chat, page.chat), message, { compact }));
132275
134456
  }
132276
134457
  }
132277
134458
  }
132278
- if (includeTransactions) {
134459
+ }
134460
+ if (includeTransactions) {
134461
+ try {
132279
134462
  const page = await client2.money.transactions({ count: txCount });
132280
- for (const tx of page.transfers || []) {
132281
- const key = tx?.id || "";
132282
- const value = transferKey(tx);
134463
+ for (const tx2 of page.transfers || []) {
134464
+ const key = tx2?.id || "";
134465
+ const value = transferKey(tx2);
132283
134466
  if (!key || seenTransfers.get(key) === value) {
132284
134467
  continue;
132285
134468
  }
132286
134469
  seenTransfers.set(key, value);
132287
- if (initialized || replay) {
132288
- emit(event("transaction", { transaction: tx }));
134470
+ if (emitChanges) {
134471
+ emit(event("transaction", { transaction: tx2 }));
132289
134472
  }
132290
134473
  }
134474
+ } catch (error) {
134475
+ emit(event("error", {
134476
+ message: error?.message || String(error)
134477
+ }));
132291
134478
  }
132292
- initialized = true;
134479
+ }
134480
+ }
134481
+ if (replay) {
134482
+ emit(event("ready", { account: compact ? compactAccount(account) : account }));
134483
+ }
134484
+ try {
134485
+ await poll(replay);
134486
+ } catch (error) {
134487
+ emit(event("error", {
134488
+ message: error?.message || String(error)
134489
+ }));
134490
+ }
134491
+ if (!replay) {
134492
+ emit(event("ready", { account: compact ? compactAccount(account) : account }));
134493
+ }
134494
+ while (!stopped(options2.signal)) {
134495
+ await sleep2(intervalMs);
134496
+ if (stopped(options2.signal)) {
134497
+ break;
134498
+ }
134499
+ try {
134500
+ await poll(true);
132293
134501
  } catch (error) {
132294
134502
  emit(event("error", {
132295
134503
  message: error?.message || String(error)
132296
134504
  }));
132297
134505
  }
132298
- await sleep2(intervalMs);
132299
134506
  }
132300
134507
  }
132301
134508
 
@@ -132499,6 +134706,7 @@ async function runPasskeyBrowserFlow(options2 = {}) {
132499
134706
 
132500
134707
  // src/storage.js
132501
134708
  import { access, chmod, mkdir, readFile, rename, writeFile } from "fs/promises";
134709
+ import { randomUUID } from "crypto";
132502
134710
  import { homedir } from "os";
132503
134711
  import { dirname, join as join4 } from "path";
132504
134712
  import process3 from "process";
@@ -132530,7 +134738,7 @@ async function readJson(path, fallback = null) {
132530
134738
  }
132531
134739
  async function writeJson(path, value) {
132532
134740
  await mkdir(dirname(path), { recursive: true, mode: DIR_MODE });
132533
- const tmp = `${path}.${process3.pid}.${Date.now()}.tmp`;
134741
+ const tmp = `${path}.${process3.pid}.${Date.now()}.${randomUUID()}.tmp`;
132534
134742
  await writeFile(tmp, `${JSON.stringify(value, null, 2)}
132535
134743
  `, { mode: FILE_MODE });
132536
134744
  await chmod(tmp, FILE_MODE).catch(() => {});
@@ -132599,21 +134807,56 @@ class ProfileStore {
132599
134807
  // src/mcp.js
132600
134808
  import { createInterface } from "readline";
132601
134809
  import process4 from "process";
134810
+ function tool(name8, description, properties = {}, required = []) {
134811
+ return {
134812
+ name: name8,
134813
+ description,
134814
+ inputSchema: {
134815
+ type: "object",
134816
+ properties,
134817
+ ...required.length ? { required } : {}
134818
+ }
134819
+ };
134820
+ }
134821
+ var stringProp = { type: "string" };
134822
+ var numberProp = { type: "number" };
134823
+ var booleanProp = { type: "boolean" };
134824
+ var objectProp = { type: "object" };
132602
134825
  var TOOLS = [
132603
- { name: "account_create", description: "Create a Veyl account headlessly.", inputSchema: { type: "object", properties: { username: { type: "string" }, network: { type: "string" } }, required: ["username"] } },
132604
- { name: "account_login", description: "Log in with the local machine credential.", inputSchema: { type: "object", properties: { username: { type: "string" } } } },
132605
- { name: "account_me", description: "Show the current local account.", inputSchema: { type: "object", properties: {} } },
132606
- { name: "vault_create", description: "Create and upload the local encrypted vault.", inputSchema: { type: "object", properties: { secret: { type: "string" }, saveSecret: { type: "boolean" } } } },
132607
- { name: "vault_unlock", description: "Unlock the local encrypted vault.", inputSchema: { type: "object", properties: { secret: { type: "string" } } } },
132608
- { name: "vault_lock", description: "Lock the wallet and chat session.", inputSchema: { type: "object", properties: {} } },
132609
- { name: "chat_list", description: "List chats.", inputSchema: { type: "object", properties: { count: { type: "number" } } } },
132610
- { name: "chat_read", description: "Read display messages from a chat.", inputSchema: { type: "object", properties: { peer: { type: "string" }, count: { type: "number" } }, required: ["peer"] } },
132611
- { name: "chat_send", description: "Send a text message.", inputSchema: { type: "object", properties: { peer: { type: "string" }, message: { type: "string" } }, required: ["peer", "message"] } },
132612
- { name: "money_balance", description: "Read wallet balance.", inputSchema: { type: "object", properties: {} } },
132613
- { name: "money_send", description: "Send sats to a peer.", inputSchema: { type: "object", properties: { peer: { type: "string" }, sats: { type: "number" } }, required: ["peer", "sats"] } },
132614
- { name: "money_request", description: "Request sats from a peer.", inputSchema: { type: "object", properties: { peer: { type: "string" }, sats: { type: "number" } }, required: ["peer", "sats"] } },
132615
- { name: "money_pay", description: "Pay a chat payment request.", inputSchema: { type: "object", properties: { requestId: { type: "string" } }, required: ["requestId"] } },
132616
- { name: "transactions_list", description: "List wallet transactions.", inputSchema: { type: "object", properties: { count: { type: "number" }, offset: { type: "number" } } } }
134826
+ tool("account_create", "Create a Veyl account headlessly.", { username: stringProp, network: stringProp }, ["username"]),
134827
+ tool("account_login", "Log in with the local machine credential.", { username: stringProp }),
134828
+ tool("account_me", "Show the current local account."),
134829
+ tool("vault_create", "Create and upload the local encrypted vault.", { secret: stringProp, saveSecret: booleanProp }),
134830
+ tool("vault_unlock", "Unlock the local encrypted vault.", { secret: stringProp }),
134831
+ tool("vault_lock", "Lock the wallet and chat session."),
134832
+ tool("chat_list", "List chats.", { count: numberProp }),
134833
+ tool("chat_read", "Read display messages from a chat.", { peer: stringProp, count: numberProp }, ["peer"]),
134834
+ tool("chat_send", "Send a text message.", { peer: stringProp, message: stringProp }, ["peer", "message"]),
134835
+ tool("chat_reply", "Reply to one displayed message. Pass either a peer plus messageId or a message event from veyl listen.", { peer: stringProp, messageId: stringProp, event: objectProp, message: stringProp }, ["message"]),
134836
+ tool("chat_react", "React to one displayed message.", { peer: stringProp, messageId: stringProp, emoji: stringProp }, ["peer", "messageId", "emoji"]),
134837
+ tool("chat_react_to", "React to a displayed message or a message event from veyl listen.", { peer: stringProp, messageId: stringProp, event: objectProp, emoji: stringProp }, ["emoji"]),
134838
+ tool("chat_unreact", "Remove your reaction from one displayed message.", { peer: stringProp, messageId: stringProp }, ["peer", "messageId"]),
134839
+ tool("chat_save", "Keep one displayed message permanently.", { peer: stringProp, messageId: stringProp }, ["peer", "messageId"]),
134840
+ tool("chat_unsave", "Return one displayed message to normal temporary retention.", { peer: stringProp, messageId: stringProp }, ["peer", "messageId"]),
134841
+ tool("chat_delete_message", "Delete one displayed message.", { peer: stringProp, messageId: stringProp }, ["peer", "messageId"]),
134842
+ tool("chat_delete", "Delete one chat.", { peer: stringProp, cleanup: booleanProp }, ["peer"]),
134843
+ tool("chat_retention", "Set chat retention to seen or 24h.", { peer: stringProp, retention: stringProp }, ["peer", "retention"]),
134844
+ tool("money_receive", "Get the static funding address.", {}),
134845
+ tool("money_claim", "Claim static deposits and pending incoming transfers.", { count: numberProp }),
134846
+ tool("money_balance", "Read wallet balance.", {}),
134847
+ tool("money_send", "Send sats to a peer.", { peer: stringProp, sats: numberProp }, ["peer", "sats"]),
134848
+ tool("money_request", "Request sats from a peer.", { peer: stringProp, sats: numberProp }, ["peer", "sats"]),
134849
+ tool("money_pay", "Pay a chat payment request.", { requestId: stringProp }, ["requestId"]),
134850
+ tool("money_invoice", "Create a Lightning invoice.", { sats: numberProp, memo: stringProp, expirySeconds: numberProp, includeSparkAddress: booleanProp, includeSparkInvoice: booleanProp }),
134851
+ tool("money_pay_invoice", "Pay a Lightning or Spark invoice.", { invoice: stringProp, type: stringProp, amountSats: numberProp, maxFeeSats: numberProp, preferSpark: booleanProp }, ["invoice"]),
134852
+ tool("lightning_quote", "Quote Lightning send fees.", { invoice: stringProp, amountSats: numberProp }, ["invoice"]),
134853
+ tool("lightning_pay", "Pay a Lightning invoice.", { invoice: stringProp, amountSats: numberProp, amountSatsToSend: numberProp, maxFeeSats: numberProp, preferSpark: booleanProp }, ["invoice"]),
134854
+ tool("lightning_receive", "Read a Lightning receive request.", { id: stringProp }, ["id"]),
134855
+ tool("lightning_send", "Read a Lightning send request.", { id: stringProp }, ["id"]),
134856
+ tool("withdraw_quote", "Quote an on-chain withdrawal.", { address: stringProp, sats: numberProp }, ["address", "sats"]),
134857
+ tool("withdraw_prepare", "Prepare an on-chain withdrawal review.", { address: stringProp, sats: numberProp, speed: stringProp, deductFeeFromWithdrawalAmount: booleanProp }, ["address", "sats"]),
134858
+ tool("withdraw_send", "Send an on-chain withdrawal.", { address: stringProp, sats: numberProp, speed: stringProp, deductFeeFromWithdrawalAmount: booleanProp }, ["address", "sats"]),
134859
+ tool("transactions_list", "List wallet transactions.", { count: numberProp, offset: numberProp })
132617
134860
  ];
132618
134861
  function result(value) {
132619
134862
  return {
@@ -132637,13 +134880,35 @@ async function callTool(client2, name8, args = {}) {
132637
134880
  if (name8 === "vault_unlock")
132638
134881
  return client2.vault.unlock(args);
132639
134882
  if (name8 === "vault_lock")
132640
- return client2.vault.lock(args);
134883
+ return client2.vault.lock();
132641
134884
  if (name8 === "chat_list")
132642
134885
  return client2.chat.list(args);
132643
134886
  if (name8 === "chat_read")
132644
134887
  return client2.chat.read(args.peer, args);
132645
134888
  if (name8 === "chat_send")
132646
134889
  return client2.chat.send(args.peer, args.message, args);
134890
+ if (name8 === "chat_reply")
134891
+ return client2.chat.reply(args.event || { peer: args.peer, messageId: args.messageId }, args.message, args);
134892
+ if (name8 === "chat_react")
134893
+ return client2.chat.react(args.peer, args.messageId, args.emoji, args);
134894
+ if (name8 === "chat_react_to")
134895
+ return client2.chat.reactTo(args.event || { peer: args.peer, messageId: args.messageId }, args.emoji, args);
134896
+ if (name8 === "chat_unreact")
134897
+ return client2.chat.unreact(args.peer, args.messageId, args);
134898
+ if (name8 === "chat_save")
134899
+ return client2.chat.save(args.peer, args.messageId, args);
134900
+ if (name8 === "chat_unsave")
134901
+ return client2.chat.unsave(args.peer, args.messageId, args);
134902
+ if (name8 === "chat_delete_message")
134903
+ return client2.chat.delete(args.peer, args.messageId, args);
134904
+ if (name8 === "chat_delete")
134905
+ return client2.chat.deleteChat(args.peer, args);
134906
+ if (name8 === "chat_retention")
134907
+ return client2.chat.retention(args.peer, args.retention, args);
134908
+ if (name8 === "money_receive")
134909
+ return client2.money.receive(args);
134910
+ if (name8 === "money_claim")
134911
+ return client2.money.claim(args);
132647
134912
  if (name8 === "money_balance")
132648
134913
  return client2.money.balance(args);
132649
134914
  if (name8 === "money_send")
@@ -132652,6 +134917,24 @@ async function callTool(client2, name8, args = {}) {
132652
134917
  return client2.money.request(args.peer, args.sats, args);
132653
134918
  if (name8 === "money_pay")
132654
134919
  return client2.money.pay(args.requestId, args);
134920
+ if (name8 === "money_invoice")
134921
+ return client2.money.invoice(args.sats || 0, args);
134922
+ if (name8 === "money_pay_invoice")
134923
+ return client2.money.payInvoice(args.invoice, args);
134924
+ if (name8 === "lightning_quote")
134925
+ return client2.money.lightningQuote(args.invoice, args);
134926
+ if (name8 === "lightning_pay")
134927
+ return client2.money.lightningPay(args.invoice, args);
134928
+ if (name8 === "lightning_receive")
134929
+ return client2.money.lightningReceive(args.id, args);
134930
+ if (name8 === "lightning_send")
134931
+ return client2.money.lightningSend(args.id, args);
134932
+ if (name8 === "withdraw_quote")
134933
+ return client2.money.withdrawQuote(args.address, args.sats, args);
134934
+ if (name8 === "withdraw_prepare")
134935
+ return client2.money.withdrawPrepare(args.address, args.sats, args);
134936
+ if (name8 === "withdraw_send")
134937
+ return client2.money.withdraw(args.address, args.sats, args);
132655
134938
  if (name8 === "transactions_list")
132656
134939
  return client2.money.transactions(args);
132657
134940
  throw new Error(`unknown tool ${name8}`);
@@ -132708,8 +134991,8 @@ var API_VERSION = 1;
132708
134991
  var COMMANDS = Object.freeze({
132709
134992
  account: Object.freeze(["create", "login", "me"]),
132710
134993
  vault: Object.freeze(["create", "unlock", "lock"]),
132711
- chat: Object.freeze(["list", "read", "send"]),
132712
- money: Object.freeze(["balance", "send", "request", "pay"]),
134994
+ chat: Object.freeze(["list", "read", "send", "reply", "react", "react-to", "unreact", "save", "unsave", "delete", "delete-chat", "retention"]),
134995
+ money: Object.freeze(["address", "balance", "claim", "invoice", "lightning-quote", "lightning-pay", "lightning-receive", "lightning-send", "pay-invoice", "receive", "request", "send", "pay", "withdraw", "withdraw-prepare", "withdraw-quote"]),
132713
134996
  mcp: Object.freeze(["serve"]),
132714
134997
  transactions: Object.freeze(["list"]),
132715
134998
  listen: Object.freeze(["start"])
@@ -132738,6 +135021,43 @@ function randomSecret() {
132738
135021
  globalThis.crypto.getRandomValues(bytes);
132739
135022
  return Buffer4.from(bytes).toString("base64url");
132740
135023
  }
135024
+ function defaultAppName(profile) {
135025
+ const name8 = cleanProfileName(profile, "");
135026
+ return name8 ? `veyl-headless-${name8}` : "veyl-headless";
135027
+ }
135028
+ function cleanTargetValue(value) {
135029
+ return String(value ?? "").trim();
135030
+ }
135031
+ function peerFromTarget(target, options2 = {}) {
135032
+ if (typeof options2.peer === "string" && options2.peer.trim()) {
135033
+ return options2.peer.trim();
135034
+ }
135035
+ if (typeof target === "string") {
135036
+ return cleanTargetValue(target);
135037
+ }
135038
+ const chat = target?.chat || {};
135039
+ const message = target?.message || {};
135040
+ const username = cleanTargetValue(target?.username || chat.username).replace(/^@+/, "");
135041
+ const replyPeer = typeof target?.replyTo === "string" ? target.replyTo : target?.replyTo?.peer;
135042
+ const reactPeer = typeof target?.reactTo === "string" ? target.reactTo : target?.reactTo?.peer;
135043
+ const peer = cleanTargetValue(replyPeer || reactPeer || target?.peer || chat.peer || chat.peerChatPK || message.peerChatPK || target?.peerChatPK);
135044
+ if (peer) {
135045
+ return peer;
135046
+ }
135047
+ return username ? `@${username}` : "";
135048
+ }
135049
+ function messageIdFromTarget(target, options2 = {}) {
135050
+ if (typeof options2.replyId === "string" && options2.replyId.trim()) {
135051
+ return options2.replyId.trim();
135052
+ }
135053
+ if (typeof options2.messageId === "string" && options2.messageId.trim()) {
135054
+ return options2.messageId.trim();
135055
+ }
135056
+ if (typeof target === "string") {
135057
+ return "";
135058
+ }
135059
+ return cleanTargetValue(target?.replyTo?.messageId || target?.reactTo?.messageId || target?.messageId || target?.message?.id || target?.message?.cid || target?.id || target?.cid);
135060
+ }
132741
135061
 
132742
135062
  class VeylHeadlessClient {
132743
135063
  constructor(options2 = {}) {
@@ -132746,7 +135066,7 @@ class VeylHeadlessClient {
132746
135066
  this.store = options2.store || new ProfileStore({ dir: options2.homeDir, profile: options2.profile });
132747
135067
  this.profile = options2.profileData || null;
132748
135068
  this.session = options2.session || null;
132749
- const cloud = options2.cloudContext || createHeadlessCloud(options2);
135069
+ const cloud = options2.cloudContext || createHeadlessCloud({ ...options2, appName: options2.appName || defaultAppName(options2.profile || this.store.profile) });
132750
135070
  this.auth = cloud.auth;
132751
135071
  this.cloud = cloud.cloud;
132752
135072
  this.functionBaseUrl = options2.functionBaseUrl || cloud.functionBaseUrl;
@@ -132769,14 +135089,35 @@ class VeylHeadlessClient {
132769
135089
  this.chat = {
132770
135090
  list: (payload) => this.listChats(payload),
132771
135091
  read: (peer, payload) => this.readChat(peer, payload),
132772
- send: (peer, message, payload) => this.sendChat(peer, message, payload)
135092
+ send: (peer, message, payload) => this.sendChat(peer, message, payload),
135093
+ reply: (target, message, payload) => this.replyChat(target, message, payload),
135094
+ react: (peer, messageId, emoji, payload) => this.reactChat(peer, messageId, emoji, payload),
135095
+ reactTo: (target, emoji, payload) => this.reactToChat(target, emoji, payload),
135096
+ unreact: (peer, messageId, payload) => this.unreactChat(peer, messageId, payload),
135097
+ save: (peer, messageId, payload) => this.saveChatMessage(peer, messageId, payload),
135098
+ unsave: (peer, messageId, payload) => this.unsaveChatMessage(peer, messageId, payload),
135099
+ delete: (peer, messageId, payload) => this.deleteChatMessage(peer, messageId, payload),
135100
+ deleteChat: (peer, payload) => this.deleteChat(peer, payload),
135101
+ retention: (peer, value, payload) => this.setChatRetention(peer, value, payload)
132773
135102
  };
132774
135103
  this.money = {
135104
+ address: (payload) => this.receiveMoney(payload),
132775
135105
  balance: (payload) => this.balance(payload),
135106
+ claim: (payload) => this.claimMoney(payload),
135107
+ invoice: (sats, payload) => this.createInvoice(sats, payload),
135108
+ lightningQuote: (invoice, payload) => this.lightningQuote(invoice, payload),
135109
+ lightningPay: (invoice, payload) => this.lightningPay(invoice, payload),
135110
+ lightningReceive: (id, payload) => this.lightningReceive(id, payload),
135111
+ lightningSend: (id, payload) => this.lightningSend(id, payload),
135112
+ payInvoice: (invoice, payload) => this.payInvoice(invoice, payload),
135113
+ receive: (payload) => this.receiveMoney(payload),
132776
135114
  send: (peer, sats, payload) => this.sendMoney(peer, sats, payload),
132777
135115
  request: (peer, sats, payload) => this.requestMoney(peer, sats, payload),
132778
135116
  pay: (requestId, payload) => this.payRequest(requestId, payload),
132779
- transactions: (payload) => this.transactions(payload)
135117
+ transactions: (payload) => this.transactions(payload),
135118
+ withdrawQuote: (address, sats, payload) => this.withdrawQuote(address, sats, payload),
135119
+ withdrawPrepare: (address, sats, payload) => this.withdrawPrepare(address, sats, payload),
135120
+ withdraw: (address, sats, payload) => this.withdraw(address, sats, payload)
132780
135121
  };
132781
135122
  this.mcp = {
132782
135123
  serve: (payload) => serveMcp(this, payload)
@@ -132821,6 +135162,7 @@ class VeylHeadlessClient {
132821
135162
  walletPK: profile.walletPK || null,
132822
135163
  chatPK: profile.chatPK || null,
132823
135164
  auth: profile.auth || "machine",
135165
+ bot: profile.bot || null,
132824
135166
  signedIn: this.auth?.currentUser?.uid === profile.uid,
132825
135167
  unlocked: !!this.session
132826
135168
  };
@@ -132859,6 +135201,7 @@ class VeylHeadlessClient {
132859
135201
  publicKeyPem: machine.publicKeyPem,
132860
135202
  privateKeyPem: options2.saveCredential === false ? null : machine.privateKeyPem,
132861
135203
  auth: "machine",
135204
+ bot: finish.bot || "bot",
132862
135205
  createdAt: Date.now(),
132863
135206
  hasVault: false
132864
135207
  });
@@ -132887,6 +135230,7 @@ class VeylHeadlessClient {
132887
135230
  uid: finish.uid || profile.uid,
132888
135231
  username: finish.username || profile.username,
132889
135232
  credentialId,
135233
+ bot: finish.bot || profile.bot || null,
132890
135234
  lastLoginAt: Date.now()
132891
135235
  });
132892
135236
  return this.accountSummary(next);
@@ -133114,9 +135458,73 @@ class VeylHeadlessClient {
133114
135458
  async sendChat(peer, message, options2 = {}) {
133115
135459
  return this.actions.chat.send(peer, message, options2);
133116
135460
  }
135461
+ async replyChat(target, message, options2 = {}) {
135462
+ const peer = peerFromTarget(target, options2);
135463
+ if (!peer) {
135464
+ throw new Error("reply target required");
135465
+ }
135466
+ const messageId = messageIdFromTarget(target, options2);
135467
+ return messageId ? this.actions.chat.reply(peer, messageId, message, options2) : this.sendChat(peer, message, options2);
135468
+ }
135469
+ async reactChat(peer, messageId, emoji, options2 = {}) {
135470
+ return this.actions.chat.react(peer, messageId, emoji, options2);
135471
+ }
135472
+ async reactToChat(target, emoji, options2 = {}) {
135473
+ const peer = peerFromTarget(target, options2);
135474
+ const messageId = messageIdFromTarget(target, options2);
135475
+ if (!peer) {
135476
+ throw new Error("reaction peer required");
135477
+ }
135478
+ if (!messageId) {
135479
+ throw new Error("reaction message id required");
135480
+ }
135481
+ return this.reactChat(peer, messageId, emoji, options2);
135482
+ }
135483
+ async unreactChat(peer, messageId, options2 = {}) {
135484
+ return this.actions.chat.unreact(peer, messageId, options2);
135485
+ }
135486
+ async saveChatMessage(peer, messageId, options2 = {}) {
135487
+ return this.actions.chat.save(peer, messageId, options2);
135488
+ }
135489
+ async unsaveChatMessage(peer, messageId, options2 = {}) {
135490
+ return this.actions.chat.unsave(peer, messageId, options2);
135491
+ }
135492
+ async deleteChatMessage(peer, messageId, options2 = {}) {
135493
+ return this.actions.chat.deleteMessage(peer, messageId, options2);
135494
+ }
135495
+ async deleteChat(peer, options2 = {}) {
135496
+ return this.actions.chat.deleteChat(peer, options2);
135497
+ }
135498
+ async setChatRetention(peer, value, options2 = {}) {
135499
+ return this.actions.chat.retention(peer, value, options2);
135500
+ }
135501
+ async receiveMoney(options2 = {}) {
135502
+ return this.actions.money.receive(options2);
135503
+ }
133117
135504
  async balance(options2 = {}) {
133118
135505
  return this.actions.money.balance(options2);
133119
135506
  }
135507
+ async claimMoney(options2 = {}) {
135508
+ return this.actions.money.claim(options2);
135509
+ }
135510
+ async createInvoice(sats = 0, options2 = {}) {
135511
+ return this.actions.money.invoice(sats, options2);
135512
+ }
135513
+ async lightningQuote(invoice, options2 = {}) {
135514
+ return this.actions.money.lightningQuote(invoice, options2);
135515
+ }
135516
+ async lightningPay(invoice, options2 = {}) {
135517
+ return this.actions.money.lightningPay(invoice, options2);
135518
+ }
135519
+ async lightningReceive(id, options2 = {}) {
135520
+ return this.actions.money.lightningReceive(id, options2);
135521
+ }
135522
+ async lightningSend(id, options2 = {}) {
135523
+ return this.actions.money.lightningSend(id, options2);
135524
+ }
135525
+ async payInvoice(invoice, options2 = {}) {
135526
+ return this.actions.money.payInvoice(invoice, options2);
135527
+ }
133120
135528
  async sendMoney(peer, sats, options2 = {}) {
133121
135529
  return this.actions.money.send(peer, sats, options2);
133122
135530
  }
@@ -133129,6 +135537,15 @@ class VeylHeadlessClient {
133129
135537
  async transactions(options2 = {}) {
133130
135538
  return this.actions.money.transactions(options2);
133131
135539
  }
135540
+ async withdrawQuote(address, sats, options2 = {}) {
135541
+ return this.actions.money.withdrawQuote(address, sats, options2);
135542
+ }
135543
+ async withdrawPrepare(address, sats, options2 = {}) {
135544
+ return this.actions.money.withdrawPrepare(address, sats, options2);
135545
+ }
135546
+ async withdraw(address, sats, options2 = {}) {
135547
+ return this.actions.money.withdraw(address, sats, options2);
135548
+ }
133132
135549
  async listenEvents(options2 = {}) {
133133
135550
  return listenAccount(this, options2);
133134
135551
  }
@@ -133150,9 +135567,18 @@ var HELP = `Usage:
133150
135567
  veyl unlock
133151
135568
  veyl send @name 1000
133152
135569
  veyl request @name 1000
135570
+ veyl receive
135571
+ veyl claim
135572
+ veyl invoice 100 ["memo"]
135573
+ veyl pay-invoice <invoice>
135574
+ veyl withdraw <address> 1000
133153
135575
  veyl balance
133154
135576
  veyl read @name
133155
135577
  veyl say @name "message"
135578
+ veyl reply @name <message-id> "message"
135579
+ veyl react @name <message-id> <emoji>
135580
+ veyl save @name <message-id>
135581
+ veyl retention @name seen|24h
133156
135582
  veyl listen
133157
135583
 
133158
135584
  Structured:
@@ -133167,19 +135593,46 @@ Structured:
133167
135593
  veyl chats
133168
135594
  veyl chat read @name
133169
135595
  veyl chat send @name "message"
135596
+ veyl chat reply @name <message-id> "message"
135597
+ veyl chat react @name <message-id> <emoji>
135598
+ veyl chat unreact @name <message-id>
135599
+ veyl chat save @name <message-id>
135600
+ veyl chat unsave @name <message-id>
135601
+ veyl chat delete @name <message-id>
135602
+ veyl chat delete-chat @name
135603
+ veyl chat retention @name seen|24h
135604
+ veyl money receive
133170
135605
  veyl money balance
135606
+ veyl money claim
135607
+ veyl money invoice 100 ["memo"]
135608
+ veyl money pay-invoice <invoice>
133171
135609
  veyl money send @name 1000
133172
135610
  veyl money request @name 1000
133173
135611
  veyl money pay <request-id>
135612
+ veyl money withdraw-quote <address> 1000
135613
+ veyl money withdraw <address> 1000
133174
135614
  veyl transactions
133175
135615
  veyl mcp serve
133176
135616
 
133177
135617
  Listen:
133178
135618
  --interval ms poll interval, minimum 1000
133179
135619
  --replay emit current messages and transactions on startup
135620
+ --incoming emit only peer-authored messages
135621
+ --compact emit smaller event payloads
135622
+ --agent shorthand for --incoming --compact
133180
135623
  --no-chats skip chat message events
133181
135624
  --no-transactions skip transaction events
133182
135625
 
135626
+ Common options:
135627
+ --count n result count for list/read/claim/transactions
135628
+ --raw include raw SDK/backend data when supported
135629
+ --memo text lightning invoice memo
135630
+ --expiry seconds lightning invoice expiry
135631
+ --max-fee sats maximum lightning fee
135632
+ --amount sats variable invoice amount
135633
+ --speed value withdrawal speed, SLOW|MEDIUM|FAST
135634
+ --no-deduct-fee add withdrawal fee on top of the sent amount
135635
+
133183
135636
  Env:
133184
135637
  VEYL_HOME local profile directory
133185
135638
  VEYL_PROFILE default profile
@@ -133207,6 +135660,27 @@ ${HELP}`);
133207
135660
  error.code = "usage";
133208
135661
  return error;
133209
135662
  }
135663
+ function commandOptions(options2 = {}) {
135664
+ return {
135665
+ count: options2.count,
135666
+ limit: options2.limit,
135667
+ offset: options2.offset,
135668
+ raw: options2.raw,
135669
+ memo: options2.memo,
135670
+ expirySeconds: options2.expirySeconds,
135671
+ maxFeeSats: options2.maxFeeSats,
135672
+ amountSats: options2.amountSats,
135673
+ amountSatsToSend: options2.amountSatsToSend,
135674
+ speed: options2.speed,
135675
+ exitSpeed: options2.speed,
135676
+ type: options2.type,
135677
+ preferSpark: options2.preferSpark,
135678
+ includeSparkAddress: options2.includeSparkAddress,
135679
+ includeSparkInvoice: options2.includeSparkInvoice,
135680
+ deductFeeFromWithdrawalAmount: options2.deductFeeFromWithdrawalAmount,
135681
+ cleanup: options2.cleanup
135682
+ };
135683
+ }
133210
135684
  function parseArgs(argv) {
133211
135685
  const options2 = {};
133212
135686
  const args = [];
@@ -133234,8 +135708,50 @@ function parseArgs(argv) {
133234
135708
  options2.messageCount = argv[++index];
133235
135709
  } else if (item === "--tx-count") {
133236
135710
  options2.txCount = argv[++index];
135711
+ } else if (item === "--count") {
135712
+ options2.count = argv[++index];
135713
+ } else if (item === "--limit") {
135714
+ options2.limit = argv[++index];
135715
+ } else if (item === "--offset") {
135716
+ options2.offset = argv[++index];
135717
+ } else if (item === "--raw") {
135718
+ options2.raw = true;
135719
+ } else if (item === "--memo") {
135720
+ options2.memo = argv[++index];
135721
+ } else if (item === "--expiry" || item === "--expiry-seconds") {
135722
+ options2.expirySeconds = argv[++index];
135723
+ } else if (item === "--max-fee" || item === "--max-fee-sats") {
135724
+ options2.maxFeeSats = argv[++index];
135725
+ } else if (item === "--amount" || item === "--amount-sats") {
135726
+ options2.amountSats = argv[++index];
135727
+ } else if (item === "--amount-to-send" || item === "--amount-sats-to-send") {
135728
+ options2.amountSatsToSend = argv[++index];
135729
+ } else if (item === "--speed" || item === "--exit-speed") {
135730
+ options2.speed = argv[++index];
135731
+ } else if (item === "--no-deduct-fee") {
135732
+ options2.deductFeeFromWithdrawalAmount = false;
135733
+ } else if (item === "--type") {
135734
+ options2.type = argv[++index];
135735
+ } else if (item === "--prefer-spark") {
135736
+ options2.preferSpark = true;
135737
+ } else if (item === "--no-prefer-spark") {
135738
+ options2.preferSpark = false;
135739
+ } else if (item === "--include-spark-address") {
135740
+ options2.includeSparkAddress = true;
135741
+ } else if (item === "--include-spark-invoice") {
135742
+ options2.includeSparkInvoice = true;
135743
+ } else if (item === "--no-cleanup") {
135744
+ options2.cleanup = false;
133237
135745
  } else if (item === "--replay") {
133238
135746
  options2.replay = true;
135747
+ } else if (item === "--incoming" || item === "--incoming-only") {
135748
+ options2.incomingOnly = true;
135749
+ } else if (item === "--all") {
135750
+ options2.incomingOnly = false;
135751
+ } else if (item === "--compact") {
135752
+ options2.compact = true;
135753
+ } else if (item === "--agent") {
135754
+ options2.agent = true;
133239
135755
  } else if (item === "--no-chats") {
133240
135756
  options2.chats = false;
133241
135757
  } else if (item === "--no-transactions") {
@@ -133252,36 +135768,38 @@ async function runCommand(argv) {
133252
135768
  process.env.VEYL_VAULT_SECRET = parsed.options.secret;
133253
135769
  }
133254
135770
  const [area, command, ...args] = parsed.args;
135771
+ const shortArgs = command === undefined ? [] : [command, ...args];
133255
135772
  const veyl = createClient2({
133256
135773
  profile: parsed.options.profile,
133257
135774
  network: parsed.options.network
133258
135775
  });
135776
+ const opts = commandOptions(parsed.options);
133259
135777
  if (!area || area === "help" || area === "--help" || area === "-h") {
133260
135778
  return HELP;
133261
135779
  }
133262
135780
  if (area === "chats") {
133263
- return veyl.chat.list();
135781
+ return veyl.chat.list(opts);
133264
135782
  }
133265
135783
  if (area === "transactions") {
133266
- return veyl.money.transactions();
135784
+ return veyl.money.transactions(opts);
133267
135785
  }
133268
135786
  if (area === "create") {
133269
135787
  return parsed.options.passkey ? veyl.account.createPasskey({
133270
- username: args[0],
135788
+ username: shortArgs[0],
133271
135789
  network: parsed.options.network,
133272
135790
  webUrl: parsed.options.webUrl,
133273
135791
  saveCredential: parsed.options.saveCredential,
133274
135792
  onPasskeyUrl: (url) => console.error(`open ${url}`)
133275
- }) : veyl.account.create({ username: args[0], network: parsed.options.network, saveCredential: parsed.options.saveCredential });
135793
+ }) : veyl.account.create({ username: shortArgs[0], network: parsed.options.network, saveCredential: parsed.options.saveCredential });
133276
135794
  }
133277
135795
  if (area === "login") {
133278
135796
  return parsed.options.passkey ? veyl.account.loginPasskey({
133279
- username: args[0],
135797
+ username: shortArgs[0],
133280
135798
  network: parsed.options.network,
133281
135799
  webUrl: parsed.options.webUrl,
133282
135800
  saveCredential: parsed.options.saveCredential,
133283
135801
  onPasskeyUrl: (url) => console.error(`open ${url}`)
133284
- }) : veyl.account.login({ username: args[0] });
135802
+ }) : veyl.account.login({ username: shortArgs[0] });
133285
135803
  }
133286
135804
  if (area === "me") {
133287
135805
  return veyl.account.me();
@@ -133293,25 +135811,70 @@ async function runCommand(argv) {
133293
135811
  return veyl.vault.lock();
133294
135812
  }
133295
135813
  if (area === "balance") {
133296
- return veyl.money.balance();
135814
+ return veyl.money.balance(opts);
135815
+ }
135816
+ if (area === "receive" || area === "address") {
135817
+ return veyl.money.receive(opts);
135818
+ }
135819
+ if (area === "claim") {
135820
+ return veyl.money.claim(opts);
135821
+ }
135822
+ if (area === "invoice") {
135823
+ return veyl.money.invoice(shortArgs[0] || 0, { ...opts, memo: opts.memo || shortArgs.slice(1).join(" ") || undefined });
135824
+ }
135825
+ if (area === "pay-invoice" || area === "payinvoice") {
135826
+ return veyl.money.payInvoice(shortArgs[0], opts);
135827
+ }
135828
+ if (area === "withdraw-quote") {
135829
+ return veyl.money.withdrawQuote(shortArgs[0], shortArgs[1], opts);
135830
+ }
135831
+ if (area === "withdraw-prepare") {
135832
+ return veyl.money.withdrawPrepare(shortArgs[0], shortArgs[1], opts);
135833
+ }
135834
+ if (area === "withdraw") {
135835
+ return veyl.money.withdraw(shortArgs[0], shortArgs[1], opts);
133297
135836
  }
133298
135837
  if (area === "send") {
133299
- return veyl.money.send(args[0], args[1]);
135838
+ return veyl.money.send(shortArgs[0], shortArgs[1], opts);
133300
135839
  }
133301
135840
  if (area === "request") {
133302
- return veyl.money.request(args[0], args[1]);
135841
+ return veyl.money.request(shortArgs[0], shortArgs[1], opts);
133303
135842
  }
133304
135843
  if (area === "pay") {
133305
- return veyl.money.pay(args[0]);
135844
+ return veyl.money.pay(shortArgs[0], opts);
133306
135845
  }
133307
135846
  if (area === "txs") {
133308
- return veyl.money.transactions();
135847
+ return veyl.money.transactions(opts);
133309
135848
  }
133310
135849
  if (area === "read") {
133311
- return veyl.chat.read(args[0]);
135850
+ return veyl.chat.read(shortArgs[0], opts);
133312
135851
  }
133313
135852
  if (area === "say" || area === "msg") {
133314
- return veyl.chat.send(args[0], args.slice(1).join(" "));
135853
+ return veyl.chat.send(shortArgs[0], shortArgs.slice(1).join(" "), opts);
135854
+ }
135855
+ if (area === "reply") {
135856
+ return veyl.chat.reply({ peer: shortArgs[0], messageId: shortArgs[1] }, shortArgs.slice(2).join(" "), opts);
135857
+ }
135858
+ if (area === "react") {
135859
+ return veyl.chat.react(shortArgs[0], shortArgs[1], shortArgs.slice(2).join(" "), opts);
135860
+ }
135861
+ if (area === "unreact") {
135862
+ return veyl.chat.unreact(shortArgs[0], shortArgs[1], opts);
135863
+ }
135864
+ if (area === "save") {
135865
+ return veyl.chat.save(shortArgs[0], shortArgs[1], opts);
135866
+ }
135867
+ if (area === "unsave") {
135868
+ return veyl.chat.unsave(shortArgs[0], shortArgs[1], opts);
135869
+ }
135870
+ if (area === "delete-message") {
135871
+ return veyl.chat.delete(shortArgs[0], shortArgs[1], opts);
135872
+ }
135873
+ if (area === "delete-chat") {
135874
+ return veyl.chat.deleteChat(shortArgs[0], opts);
135875
+ }
135876
+ if (area === "retention") {
135877
+ return veyl.chat.retention(shortArgs[0], shortArgs[1], opts);
133315
135878
  }
133316
135879
  if (area === "listen") {
133317
135880
  const controller = new AbortController;
@@ -133323,6 +135886,9 @@ async function runCommand(argv) {
133323
135886
  messageCount: parsed.options.messageCount,
133324
135887
  txCount: parsed.options.txCount,
133325
135888
  replay: parsed.options.replay,
135889
+ incomingOnly: parsed.options.incomingOnly,
135890
+ compact: parsed.options.compact,
135891
+ agent: parsed.options.agent,
133326
135892
  chats: parsed.options.chats,
133327
135893
  transactions: parsed.options.transactions,
133328
135894
  signal: controller.signal,
@@ -133359,24 +135925,64 @@ async function runCommand(argv) {
133359
135925
  }
133360
135926
  if (area === "chat") {
133361
135927
  if (command === "list")
133362
- return veyl.chat.list();
135928
+ return veyl.chat.list(opts);
133363
135929
  if (command === "read")
133364
- return veyl.chat.read(args[0]);
135930
+ return veyl.chat.read(args[0], opts);
133365
135931
  if (command === "send")
133366
- return veyl.chat.send(args[0], args.slice(1).join(" "));
135932
+ return veyl.chat.send(args[0], args.slice(1).join(" "), opts);
135933
+ if (command === "reply")
135934
+ return veyl.chat.reply({ peer: args[0], messageId: args[1] }, args.slice(2).join(" "), opts);
135935
+ if (command === "react")
135936
+ return veyl.chat.react(args[0], args[1], args.slice(2).join(" "), opts);
135937
+ if (command === "react-to")
135938
+ return veyl.chat.reactTo({ peer: args[0], messageId: args[1] }, args.slice(2).join(" "), opts);
135939
+ if (command === "unreact")
135940
+ return veyl.chat.unreact(args[0], args[1], opts);
135941
+ if (command === "save")
135942
+ return veyl.chat.save(args[0], args[1], opts);
135943
+ if (command === "unsave")
135944
+ return veyl.chat.unsave(args[0], args[1], opts);
135945
+ if (command === "delete")
135946
+ return veyl.chat.delete(args[0], args[1], opts);
135947
+ if (command === "delete-chat")
135948
+ return veyl.chat.deleteChat(args[0], opts);
135949
+ if (command === "retention")
135950
+ return veyl.chat.retention(args[0], args[1], opts);
133367
135951
  throw usageError("unknown chat command");
133368
135952
  }
133369
135953
  if (area === "money") {
135954
+ if (command === "address" || command === "receive")
135955
+ return veyl.money.receive(opts);
133370
135956
  if (command === "balance")
133371
- return veyl.money.balance();
135957
+ return veyl.money.balance(opts);
135958
+ if (command === "claim")
135959
+ return veyl.money.claim(opts);
135960
+ if (command === "invoice")
135961
+ return veyl.money.invoice(args[0] || 0, { ...opts, memo: opts.memo || args.slice(1).join(" ") || undefined });
135962
+ if (command === "lightning-quote")
135963
+ return veyl.money.lightningQuote(args[0], opts);
135964
+ if (command === "lightning-pay")
135965
+ return veyl.money.lightningPay(args[0], opts);
135966
+ if (command === "lightning-receive")
135967
+ return veyl.money.lightningReceive(args[0], opts);
135968
+ if (command === "lightning-send")
135969
+ return veyl.money.lightningSend(args[0], opts);
135970
+ if (command === "pay-invoice")
135971
+ return veyl.money.payInvoice(args[0], opts);
133372
135972
  if (command === "send")
133373
- return veyl.money.send(args[0], args[1]);
135973
+ return veyl.money.send(args[0], args[1], opts);
133374
135974
  if (command === "request")
133375
- return veyl.money.request(args[0], args[1]);
135975
+ return veyl.money.request(args[0], args[1], opts);
133376
135976
  if (command === "pay")
133377
- return veyl.money.pay(args[0]);
135977
+ return veyl.money.pay(args[0], opts);
133378
135978
  if (command === "transactions")
133379
- return veyl.money.transactions();
135979
+ return veyl.money.transactions(opts);
135980
+ if (command === "withdraw-quote")
135981
+ return veyl.money.withdrawQuote(args[0], args[1], opts);
135982
+ if (command === "withdraw-prepare")
135983
+ return veyl.money.withdrawPrepare(args[0], args[1], opts);
135984
+ if (command === "withdraw")
135985
+ return veyl.money.withdraw(args[0], args[1], opts);
133380
135986
  throw usageError("unknown money command");
133381
135987
  }
133382
135988
  if (area === "mcp") {
@@ -133389,14 +135995,15 @@ async function runCommand(argv) {
133389
135995
  async function main() {
133390
135996
  try {
133391
135997
  print2(await runCommand(process.argv.slice(2)));
135998
+ process.exit(0);
133392
135999
  } catch (error) {
133393
136000
  if (error instanceof ClientNotReadyError) {
133394
136001
  console.error(error.message);
133395
- process.exitCode = 2;
136002
+ process.exit(2);
133396
136003
  return;
133397
136004
  }
133398
136005
  console.error(error?.message || String(error));
133399
- process.exitCode = error?.code === "usage" ? 1 : 2;
136006
+ process.exit(error?.code === "usage" ? 1 : 2);
133400
136007
  }
133401
136008
  }
133402
136009
  main();