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