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