@glyphteck/veyl 0.32.1 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.js +991 -507
- package/dist/index.js +991 -507
- package/docs/validation.md +1 -1
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -118,9 +118,10 @@ var init_links = __esm(() => {
|
|
|
118
118
|
});
|
|
119
119
|
|
|
120
120
|
// ../../shared/community.js
|
|
121
|
-
var COMMUNITY_RULES_VERSION = "2026-05-11.1", COMMUNITY_SECTIONS;
|
|
121
|
+
var COMMUNITY_RULES_VERSION = "2026-05-11.1", COMMUNITY_SUPPORT_EMAIL, COMMUNITY_SECTIONS;
|
|
122
122
|
var init_community = __esm(() => {
|
|
123
123
|
init_links();
|
|
124
|
+
COMMUNITY_SUPPORT_EMAIL = links.contact.replace("mailto:", "");
|
|
124
125
|
COMMUNITY_SECTIONS = [
|
|
125
126
|
{
|
|
126
127
|
title: "Use veyl directly and lawfully",
|
|
@@ -160,7 +161,7 @@ var init_community = __esm(() => {
|
|
|
160
161
|
{
|
|
161
162
|
title: "Reporting and support",
|
|
162
163
|
body: [
|
|
163
|
-
`If someone is abusing veyl, contact us at ${
|
|
164
|
+
`If someone is abusing veyl, contact us at ${COMMUNITY_SUPPORT_EMAIL} and include the username, profile details, screenshots, or any evidence you choose to provide from your own device.`,
|
|
164
165
|
"Because veyl uses end-to-end encryption, we may rely on reports, account-level signals, and evidence you submit when reviewing abuse."
|
|
165
166
|
]
|
|
166
167
|
}
|
|
@@ -446,6 +447,34 @@ var init_legal = __esm(() => {
|
|
|
446
447
|
};
|
|
447
448
|
});
|
|
448
449
|
|
|
450
|
+
// ../../shared/actioncopy.js
|
|
451
|
+
var ACCOUNT_DELETE_PREPARE = "you should export or empty your wallet first.", ACCOUNT_DELETE_CONDITION = "if you delete your account,", ACCOUNT_DELETE_CONSEQUENCE = "you will permanently lose access to your funds and chats.", PASSKEY_DELETE_PENDING = "deleting a pending link disables it.", PASSKEY_DELETE_VERIFIED = "deleting a verified passkey will log out any session currently using it.", PASSKEY_DELETE_LIMITS = "you can’t delete the passkey used by this session or the account’s last passkey.", ACCOUNT_DELETE_COPY, BLOCK_USER_BODY = "they will no longer be able to message you, and this chat will be permanently deleted.", UNBLOCK_USER_BODY = "they will be able to message you again.", CHAT_DELETE_BODY = "this chat will be permanently deleted.", PASSKEY_DELETE_COPY, WALLET_EXPORT_COPY, WITHDRAWAL_COPY, LOGOUT_ALL_DEVICES_BODY = "This will sign your account out on every connected device. If you suspect someone else has access, logging out may not be enough: they may already have copied your wallet recovery phrase or other sensitive information. Move your funds to a safe wallet only you control as soon as possible, then remove sensitive information from this account. Information already copied to another device cannot be erased remotely.";
|
|
452
|
+
var init_actioncopy = __esm(() => {
|
|
453
|
+
ACCOUNT_DELETE_COPY = Object.freeze({
|
|
454
|
+
prepare: ACCOUNT_DELETE_PREPARE,
|
|
455
|
+
condition: ACCOUNT_DELETE_CONDITION,
|
|
456
|
+
consequence: ACCOUNT_DELETE_CONSEQUENCE,
|
|
457
|
+
body: `${ACCOUNT_DELETE_PREPARE} ${ACCOUNT_DELETE_CONDITION} ${ACCOUNT_DELETE_CONSEQUENCE}`
|
|
458
|
+
});
|
|
459
|
+
PASSKEY_DELETE_COPY = Object.freeze({
|
|
460
|
+
pendingBody: PASSKEY_DELETE_PENDING,
|
|
461
|
+
body: PASSKEY_DELETE_VERIFIED,
|
|
462
|
+
description: `${PASSKEY_DELETE_PENDING} ${PASSKEY_DELETE_VERIFIED}`,
|
|
463
|
+
infoBody: `${PASSKEY_DELETE_PENDING} ${PASSKEY_DELETE_LIMITS} ${PASSKEY_DELETE_VERIFIED}`
|
|
464
|
+
});
|
|
465
|
+
WALLET_EXPORT_COPY = Object.freeze({
|
|
466
|
+
networkLead: "this is not a bitcoin wallet.",
|
|
467
|
+
networkBody: "you cannot use it like a normal bitcoin wallet. you can only use it with the spark network: with a new account on this platform, on a different platform that uses spark wallets, or directly through the spark sdk.",
|
|
468
|
+
withdrawBody: "if you do not want to use this account anymore, withdraw your funds back to a bitcoin wallet instead.",
|
|
469
|
+
secretBody: "the mnemonic gives full control of this Spark wallet. reveal it only somewhere private."
|
|
470
|
+
});
|
|
471
|
+
WITHDRAWAL_COPY = Object.freeze({
|
|
472
|
+
feeBody: "you can withdraw your funds back to any bitcoin address. bitcoin transactions are not free. validators need to get paid.",
|
|
473
|
+
reviewBody: "veyl gets a live Spark withdrawal quote after you press withdraw. review the destination address, the amount leaving your wallet, the quoted fee, and the amount that reaches the address before confirming.",
|
|
474
|
+
irreversibleBody: "once confirmed, bitcoin withdrawals are irreversible."
|
|
475
|
+
});
|
|
476
|
+
});
|
|
477
|
+
|
|
449
478
|
// src/commands.js
|
|
450
479
|
import { Buffer as Buffer2 } from "node:buffer";
|
|
451
480
|
import { chmod, readFile, writeFile } from "node:fs/promises";
|
|
@@ -613,6 +642,7 @@ function cliHelpLines() {
|
|
|
613
642
|
}
|
|
614
643
|
var stringProp, numberProp, booleanProp, objectProp, stringArrayProp, MIME_BY_EXTENSION, TYPE_BY_MIME, optionsOnly = (_args, context) => ({ ...context.commandOptions }), firstArg = (key) => (args, context) => ({ ...context.commandOptions, [key]: args[0] }), peerInput, peerMessageInput = (args, context) => ({ ...context.commandOptions, peer: args[0], message: args.slice(1).join(" ") }), peerMessageIdInput = (args, context) => ({ ...context.commandOptions, peer: args[0], messageId: args[1] }), peerCidInput = (args, context) => ({ ...context.commandOptions, peer: args[0], cid: args[1] }), peerMessageActionInput = (args, context) => ({ ...context.commandOptions, peer: args[0], messageId: args[1], message: args.slice(2).join(" ") }), peerEmojiInput = (args, context) => ({ ...context.commandOptions, peer: args[0], messageId: args[1], emoji: args.slice(2).join(" ") }), peerSatsInput = (args, context) => ({ ...context.commandOptions, peer: args[0], sats: args[1] }), invoiceInput, requestInput, idInput, withdrawalInput = (args, context) => ({ ...context.commandOptions, address: args[0], sats: args[1] }), inviteLinkInput = (args, context) => ({ ...context.commandOptions, kind: args[0], sats: args[1] }), HEADLESS_COMMANDS, commandByName, cliPaths, MCP_TOOLS, groups, COMMANDS;
|
|
615
644
|
var init_commands = __esm(() => {
|
|
645
|
+
init_actioncopy();
|
|
616
646
|
stringProp = Object.freeze({ type: "string" });
|
|
617
647
|
numberProp = Object.freeze({ type: "number" });
|
|
618
648
|
booleanProp = Object.freeze({ type: "boolean" });
|
|
@@ -689,12 +719,12 @@ var init_commands = __esm(() => {
|
|
|
689
719
|
invokeCli: async (client, input, context) => client.account.acceptTerms({ ...input, termsVersion: await context.acceptTerms(input.termsVersion) })
|
|
690
720
|
}),
|
|
691
721
|
command({ name: "account_logout", group: "account", apiName: "logout", description: "Lock and sign out this runtime.", usage: "account logout", cliInput: optionsOnly, access: "write", invoke: (client) => client.account.logout() }),
|
|
692
|
-
command({ name: "account_logout_all", group: "account", apiName: "logoutAll", description:
|
|
693
|
-
command({ name: "account_delete", group: "account", apiName: "delete", description:
|
|
722
|
+
command({ name: "account_logout_all", group: "account", apiName: "logoutAll", description: LOGOUT_ALL_DEVICES_BODY, usage: "account logout-all", cliInput: optionsOnly, access: "destructive", invoke: (client) => client.account.logoutAll() }),
|
|
723
|
+
command({ name: "account_delete", group: "account", apiName: "delete", description: ACCOUNT_DELETE_COPY.body, properties: { confirm: booleanProp }, required: ["confirm"], usage: "account delete", cliInput: optionsOnly, access: "destructive", invoke: (client, input) => client.account.delete(input) }),
|
|
694
724
|
command({ name: "vault_create", group: "vault", apiName: "create", description: "Create and upload a locally encrypted vault.", properties: { secret: stringProp, saveSecret: booleanProp }, usage: "vault create", cliInput: vaultInput, access: "write", secret: true, invoke: (client, input) => client.vault.create(input) }),
|
|
695
725
|
command({ name: "vault_unlock", group: "vault", apiName: "unlock", description: "Unlock the local vault.", properties: { secret: stringProp }, usage: "vault unlock", cliInput: vaultInput, access: "write", secret: true, invoke: (client, input) => client.vault.unlock(input) }),
|
|
696
726
|
command({ name: "vault_lock", group: "vault", apiName: "lock", description: "Lock wallet and chat state.", usage: "vault lock", cliInput: optionsOnly, access: "write", invoke: (client) => client.vault.lock() }),
|
|
697
|
-
command({ name: "vault_export", group: "vault", apiName: "export", description:
|
|
727
|
+
command({ name: "vault_export", group: "vault", apiName: "export", description: WALLET_EXPORT_COPY.secretBody, properties: { secret: stringProp }, usage: "vault export", cliInput: vaultInput, mcp: false, secret: true, invoke: (client, input) => client.vault.export(input) }),
|
|
698
728
|
command({ name: "profile_show", group: "profile", apiName: "show", description: "Show the public account profile.", usage: "profile show", cliInput: optionsOnly, invoke: (client) => client.profile.show() }),
|
|
699
729
|
command({
|
|
700
730
|
name: "profile_avatar_set",
|
|
@@ -720,8 +750,8 @@ var init_commands = __esm(() => {
|
|
|
720
750
|
command({ name: "peers_search", group: "peers", apiName: "search", description: "Search public Veyl profiles.", properties: { query: stringProp, count: numberProp }, required: ["query"], usage: "peers search <query>", cliInput: (args, context) => ({ ...context.commandOptions, query: args.join(" ") }), invoke: (client, input) => client.peers.search(input.query, input) }),
|
|
721
751
|
command({ name: "peers_list", group: "peers", apiName: "list", description: "List recent peers.", properties: { count: numberProp, recent: booleanProp }, usage: "peers list", cliInput: optionsOnly, invoke: (client, input) => client.peers.list(input) }),
|
|
722
752
|
command({ name: "peers_blocked", group: "peers", apiName: "blocked", description: "List blocked peers.", usage: "peers blocked", cliInput: optionsOnly, invoke: (client) => client.peers.blocked() }),
|
|
723
|
-
command({ name: "peers_block", group: "peers", apiName: "block", description:
|
|
724
|
-
command({ name: "peers_unblock", group: "peers", apiName: "unblock", description:
|
|
753
|
+
command({ name: "peers_block", group: "peers", apiName: "block", description: BLOCK_USER_BODY, properties: { peer: stringProp }, required: ["peer"], usage: "peers block @name", cliInput: peerInput, access: "destructive", invoke: (client, input) => client.peers.block(input.peer) }),
|
|
754
|
+
command({ name: "peers_unblock", group: "peers", apiName: "unblock", description: UNBLOCK_USER_BODY, properties: { peer: stringProp }, required: ["peer"], usage: "peers unblock @name", cliInput: peerInput, access: "write", invoke: (client, input) => client.peers.unblock(input.peer) }),
|
|
725
755
|
command({ name: "chat_list", group: "chat", apiName: "list", description: "List chats.", properties: { count: numberProp }, usage: "chat list", cliInput: optionsOnly, invoke: (client, input) => client.chat.list(input) }),
|
|
726
756
|
command({ name: "chat_messages", group: "chat", apiName: "messages", clientMethods: ["read"], description: "Read messages and mark the latest peer message as read.", properties: { peer: stringProp, count: numberProp }, required: ["peer"], usage: "chat messages @name", cliInput: peerInput, access: "write", invoke: (client, input) => client.chat.read(input.peer, input) }),
|
|
727
757
|
command({ name: "chat_mark_read", group: "chat", apiName: "markRead", description: "Mark the latest peer message as read.", properties: { peer: stringProp }, required: ["peer"], usage: "chat mark-read @name", cliInput: peerInput, access: "write", invoke: (client, input) => client.chat.markRead(input.peer, input) }),
|
|
@@ -734,7 +764,7 @@ var init_commands = __esm(() => {
|
|
|
734
764
|
command({ name: "chat_unsave", group: "chat", apiName: "unsave", description: "Return one message to temporary retention.", properties: { peer: stringProp, messageId: stringProp }, required: ["peer", "messageId"], usage: "chat unsave @name message-id", cliInput: peerMessageIdInput, access: "write", invoke: (client, { peer, messageId, ...options }) => client.chat.unsave(peer, messageId, options) }),
|
|
735
765
|
command({ name: "chat_edit", group: "chat", apiName: "edit", clientMethods: ["update"], description: "Edit a text message you sent.", properties: { peer: stringProp, messageId: stringProp, message: stringProp }, required: ["peer", "messageId", "message"], usage: "chat edit @name message-id message", cliInput: peerMessageActionInput, access: "write", invoke: (client, { peer, messageId, message, ...options }) => client.chat.update(peer, messageId, message, options) }),
|
|
736
766
|
command({ name: "chat_delete_message", group: "chat", apiName: "deleteMessage", clientMethods: ["delete"], description: "Delete one message immediately.", properties: { peer: stringProp, messageId: stringProp }, required: ["peer", "messageId"], usage: "chat delete-message @name message-id", cliInput: peerMessageIdInput, access: "destructive", invoke: (client, { peer, messageId, ...options }) => client.chat.delete(peer, messageId, options) }),
|
|
737
|
-
command({ name: "chat_delete", group: "chat", apiName: "deleteChat", description:
|
|
767
|
+
command({ name: "chat_delete", group: "chat", apiName: "deleteChat", description: CHAT_DELETE_BODY, properties: { peer: stringProp, cleanup: booleanProp }, required: ["peer"], usage: "chat delete @name", cliInput: peerInput, access: "destructive", invoke: (client, input) => client.chat.deleteChat(input.peer, input) }),
|
|
738
768
|
command({ name: "chat_retention", group: "chat", apiName: "retention", description: "Set chat retention to seen or 24h.", properties: { peer: stringProp, retention: stringProp }, required: ["peer", "retention"], usage: "chat retention @name seen|24h", cliInput: (args, context) => ({ ...context.commandOptions, peer: args[0], retention: args[1] }), access: "write", invoke: (client, input) => client.chat.retention(input.peer, input.retention, input) }),
|
|
739
769
|
command({
|
|
740
770
|
name: "chat_send_file",
|
|
@@ -819,12 +849,12 @@ var init_commands = __esm(() => {
|
|
|
819
849
|
command({ name: "lightning_send", group: "lightning", apiName: "send", description: "Read a Lightning send request.", properties: { id: stringProp }, required: ["id"], usage: "lightning send id", cliInput: idInput, money: true, invoke: (client, input) => client.lightning.send(input.id, input) }),
|
|
820
850
|
command({ name: "withdrawal_quote", group: "withdrawal", apiName: "quote", description: "Quote an on-chain withdrawal.", properties: { address: stringProp, sats: numberProp }, required: ["address", "sats"], usage: "withdrawal quote address sats", cliInput: withdrawalInput, access: "write", money: true, invoke: (client, input) => client.withdrawal.quote(input.address, input.sats, input) }),
|
|
821
851
|
command({ name: "withdrawal_prepare", group: "withdrawal", apiName: "prepare", description: "Prepare an on-chain withdrawal review.", properties: { address: stringProp, sats: numberProp, speed: stringProp, deductFeeFromWithdrawalAmount: booleanProp }, required: ["address", "sats"], usage: "withdrawal prepare address sats", cliInput: withdrawalInput, access: "write", money: true, invoke: (client, input) => client.withdrawal.prepare(input.address, input.sats, input) }),
|
|
822
|
-
command({ name: "withdrawal_confirm", group: "withdrawal", apiName: "confirm", description:
|
|
852
|
+
command({ name: "withdrawal_confirm", group: "withdrawal", apiName: "confirm", description: WITHDRAWAL_COPY.irreversibleBody, properties: { address: stringProp, sats: numberProp, speed: stringProp, feeQuoteId: stringProp, feeAmountSats: numberProp, deductFeeFromWithdrawalAmount: booleanProp }, required: ["address", "sats"], usage: "withdrawal confirm address sats", cliInput: withdrawalInput, access: "destructive", money: true, invoke: (client, input) => client.withdrawal.confirm(input.address, input.sats, input) }),
|
|
823
853
|
command({ name: "invite_link", group: "invite", apiName: "link", description: "Create a join, chat, send, or request invite link.", properties: { kind: stringProp, sats: numberProp }, usage: "invite link [join|chat|send|request] [sats]", cliInput: inviteLinkInput, invoke: (client, input) => client.invite.link(input) }),
|
|
824
854
|
command({ name: "invite_read", group: "invite", apiName: "read", description: "Parse a Veyl invite URL.", properties: { value: stringProp }, required: ["value"], usage: "invite read url", cliInput: firstArg("value"), invoke: (client, input) => client.invite.read(input.value) }),
|
|
825
855
|
command({ name: "passkeys_list", group: "passkeys", apiName: "list", description: "List passkeys and pending links.", usage: "passkeys list", cliInput: optionsOnly, invoke: (client, input) => client.passkeys.list(input) }),
|
|
826
856
|
command({ name: "passkeys_link", group: "passkeys", apiName: "link", clientMethods: ["createLink"], description: "Create a one-time passkey link.", properties: { webUrl: stringProp }, usage: "passkeys link", cliInput: optionsOnly, mcp: false, access: "write", secret: true, invoke: (client, input) => client.passkeys.createLink(input) }),
|
|
827
|
-
command({ name: "passkeys_delete", group: "passkeys", apiName: "delete", description:
|
|
857
|
+
command({ name: "passkeys_delete", group: "passkeys", apiName: "delete", description: PASSKEY_DELETE_COPY.description, properties: { id: stringProp, webUrl: stringProp }, required: ["id"], usage: "passkeys delete id", cliInput: (args, context) => ({ ...context.commandOptions, id: args[0], webUrl: context.options.webUrl, onUrl: context.onPasskeyUrl }), access: "destructive", invoke: (client, input) => client.passkeys.delete(input.id, input) }),
|
|
828
858
|
command({ name: "support_feedback", group: "support", apiName: "feedback", description: "Send product feedback.", properties: { message: stringProp, type: stringProp, context: stringProp }, required: ["message"], usage: "support feedback message", cliInput: (args, context) => ({ ...context.commandOptions, message: args.join(" ") }), access: "write", invoke: (client, input) => client.support.feedback(input.message, input) }),
|
|
829
859
|
command({ name: "support_bug", group: "support", apiName: "bug", description: "Submit a bug report.", properties: { message: stringProp }, required: ["message"], usage: "support bug message", cliInput: (args, context) => ({ ...context.commandOptions, message: args.join(" ") }), access: "write", invoke: (client, input) => client.support.bug(input.message, input) }),
|
|
830
860
|
command({ name: "support_report", group: "support", apiName: "report", description: "Report a peer or one harmful message.", properties: { peer: stringProp, messageId: stringProp, note: stringProp, includeAttachment: booleanProp }, required: ["peer"], usage: "support report @name [message-id]", cliInput: (args, context) => ({ ...context.commandOptions, peer: args[0], messageId: args[1] }), access: "write", invoke: (client, input) => client.support.report(input.peer, input) }),
|
|
@@ -979,7 +1009,7 @@ var package_default;
|
|
|
979
1009
|
var init_package = __esm(() => {
|
|
980
1010
|
package_default = {
|
|
981
1011
|
name: "veyl",
|
|
982
|
-
version: "0.
|
|
1012
|
+
version: "1.0.0",
|
|
983
1013
|
private: true,
|
|
984
1014
|
license: "Apache-2.0",
|
|
985
1015
|
workspaces: {
|
|
@@ -995,16 +1025,16 @@ var init_package = __esm(() => {
|
|
|
995
1025
|
"@noble/curves": "^2.2.0",
|
|
996
1026
|
"@noble/hashes": "^2.2.0",
|
|
997
1027
|
"@scure/bip39": "^2.2.0",
|
|
998
|
-
"@tailwindcss/postcss": "^4.3.
|
|
1028
|
+
"@tailwindcss/postcss": "^4.3.3",
|
|
999
1029
|
bech32: "^2.0.0",
|
|
1000
1030
|
firebase: "^12.16.0",
|
|
1001
1031
|
"lucide-react": "^1.24.0",
|
|
1002
1032
|
next: "16.3.0-preview.6",
|
|
1003
1033
|
"next-themes": "^0.4.6",
|
|
1004
|
-
postcss: "^8.5.
|
|
1005
|
-
react: "19.2.
|
|
1006
|
-
"react-dom": "19.2.
|
|
1007
|
-
tailwindcss: "^4.3.
|
|
1034
|
+
postcss: "^8.5.22",
|
|
1035
|
+
react: "19.2.8",
|
|
1036
|
+
"react-dom": "19.2.8",
|
|
1037
|
+
tailwindcss: "^4.3.3",
|
|
1008
1038
|
"tw-animate-css": "^1.4.0"
|
|
1009
1039
|
}
|
|
1010
1040
|
},
|
|
@@ -104534,7 +104564,7 @@ var init_seed = __esm(() => {
|
|
|
104534
104564
|
});
|
|
104535
104565
|
|
|
104536
104566
|
// ../../shared/config.js
|
|
104537
|
-
var MS_PER_SECOND = 1000, MINUTE_MS, HOUR_MS, DAY_MS, KIB_BYTES = 1024, MIB_BYTES, SATS_PER_BITCOIN = 100000000n, USERNAME_MAX_CHARS = 12, PASSWORD_MIN_CHARS = 12, PASSWORD_MAX_CHARS = 64, AUTOLOCK_MIN_MINUTES = 1, AUTOLOCK_MAX_MINUTES = 60, LOCAL_CACHE_WRITE_DELAY_MS = 350, LOCAL_MEDIA_CACHE_MAX_BYTES, LOCAL_MEDIA_CACHE_MAX_ITEMS = 1000, LOCAL_MEDIA_ACCESS_TOUCH_MIN_MS, LOCAL_PROFILE_CACHE_MAX_ITEMS = 500, LOCAL_PROFILE_CACHE_MAX_AGE_MS, LOCAL_CHAT_CACHE_MAX_ITEMS = 1000, LOCAL_CHAT_MESSAGE_CACHE_MAX_VISIBLE = 1000, LOCAL_AVATAR_CACHE_MAX_BYTES, LOCAL_AVATAR_CACHE_MAX_AGE_MS, AVATAR_IMAGE_MAX_BYTES, CHAT_READY_DOWNLOAD_MAX_BYTES, CHAT_MESSAGE_FILE_CACHE_MAX_BYTES, IDLE_CALLBACK_MIN_TIMEOUT_MS = 50, ATTACHMENT_CACHE_IDLE_TIMEOUT_MS = 2500, ATTACHMENT_CACHE_FALLBACK_DELAY_MS = 250, CHAT_UNSAVED_TTL_DAYS = 21, CHAT_UNSAVED_TTL_MS, CHAT_AFTER_SEEN_MS, CHAT_MEDIA_TTL_DAYS, CHAT_MEDIA_TTL_MS, CHAT_UPLOAD_MAX_BYTES, CHAT_AUDIO_TRANSCODE_BITRATE_BPS = 128000, CHAT_VIDEO_TRANSCODE_VIDEO_BITRATE_BPS =
|
|
104567
|
+
var MS_PER_SECOND = 1000, MINUTE_MS, HOUR_MS, DAY_MS, KIB_BYTES = 1024, MIB_BYTES, SATS_PER_BITCOIN = 100000000n, USERNAME_MAX_CHARS = 12, PASSWORD_MIN_CHARS = 12, PASSWORD_MAX_CHARS = 64, AUTOLOCK_MIN_MINUTES = 1, AUTOLOCK_MAX_MINUTES = 60, LOCAL_CACHE_WRITE_DELAY_MS = 350, LOCAL_MEDIA_CACHE_MAX_BYTES, LOCAL_MEDIA_CACHE_MAX_ITEMS = 1000, LOCAL_MEDIA_ACCESS_TOUCH_MIN_MS, LOCAL_PROFILE_CACHE_MAX_ITEMS = 500, LOCAL_PROFILE_CACHE_MAX_AGE_MS, LOCAL_CHAT_CACHE_MAX_ITEMS = 1000, LOCAL_CHAT_MESSAGE_CACHE_MAX_VISIBLE = 1000, LOCAL_AVATAR_CACHE_MAX_BYTES, LOCAL_AVATAR_CACHE_MAX_AGE_MS, AVATAR_IMAGE_MAX_BYTES, CHAT_READY_DOWNLOAD_MAX_BYTES, CHAT_MESSAGE_FILE_CACHE_MAX_BYTES, IDLE_CALLBACK_MIN_TIMEOUT_MS = 50, ATTACHMENT_CACHE_IDLE_TIMEOUT_MS = 2500, ATTACHMENT_CACHE_FALLBACK_DELAY_MS = 250, CHAT_UNSAVED_TTL_DAYS = 21, CHAT_UNSAVED_TTL_MS, CHAT_AFTER_SEEN_MS, CHAT_MEDIA_TTL_DAYS, CHAT_MEDIA_TTL_MS, CHAT_UPLOAD_MAX_BYTES, CHAT_AUDIO_TRANSCODE_BITRATE_BPS = 128000, CHAT_VIDEO_TRANSCODE_VIDEO_BITRATE_BPS = 3000000, CHAT_VIDEO_TRANSCODE_AUDIO_BITRATE_BPS, CHAT_MESSAGE_BATCH_SIZE = 40, CHAT_MESSAGE_QUERY_MAX_DOCS = 120, CHAT_TTL_CLIENT_DELETE_GRACE_MS, CHAT_TTL_DELETE_CHUNK_SIZE = 40, CHAT_DELETE_SCAN_BATCH_SIZE = 200, CHAT_TTL_WRITE_BATCH_SIZE = 400, CHAT_DELETE_WRITE_BATCH_SIZE = 400, CHAT_BATCH_CLEANUP_IDLE_TIMEOUT_MS = 1500, CHAT_BATCH_CLEANUP_IDLE_DELAY_MS = 250, CHAT_LIST_PAGE_SIZE = 20, CHAT_LIST_LIVE_COUNT, CHAT_INBOX_PING_PAGE_SIZE = 25, CHAT_LIST_CACHE_WRITE_DELAY_MS = 1500, CHAT_LIST_SNAPSHOT_COALESCE_MS = 80, CHAT_LIST_STATUS_CACHE_MS, CHAT_LIST_LISTENER_RETRY_MS = 1000, CHAT_TOP_WARM_COUNT = 0, CHAT_EAGER_WARM_COUNT = 0, CHAT_WARM_DELAY_MS = 3000, CHAT_WARM_BATCH_SIZE, CHAT_MESSAGE_VIEW_CACHE_SIZE = 30, CHAT_MEDIA_WARM_MESSAGES_PER_CHAT, CHAT_MEDIA_WARM_START_DELAY_MS = 600, CHAT_MEDIA_WARM_STEP_DELAY_MS = 120, CHAT_MEDIA_WARM_TYPES, CHAT_MEDIA_WARM_MAX_BYTES = 0, CHAT_READ_WRITE_INTERVAL_MS, CHAT_SEND_QUEUE_RATE_LIMIT_COUNT = 12, CHAT_SEND_QUEUE_RATE_LIMIT_WINDOW_MS, CHAT_MESSAGE_BODY_MAX_BYTES, CHAT_LAST_MESSAGE_BODY_MAX_BYTES, CHAT_SETTINGS_BODY_MAX_BYTES, BOT_WALLET_CLAIM_POLL_MS, BOT_WALLET_IDLE_CLAIM_POLL_MS, CHAT_MAX_TEXT_CHARS = 2048, CHAT_MAX_REACTIONS = 2, CHAT_PAIR_CACHE_LIMIT = 256, SEARCH_DEBOUNCE_MS = 300, SEARCH_USERNAME_LIMIT = 15, SEARCH_ROLE_LIMIT = 15, RECENT_PEER_REFRESH_LIMIT = 50, RECENT_PEER_REFRESH_DELAY_MS = 250, RECENT_PEER_REFRESH_INTERVAL_MS, RECENT_PEER_REFRESH_THROTTLE_MS = 120, BAN_REFRESH_GRACE_MS = 50, REQUEST_MONEY_MAX_SATS, WALLET_TRANSFER_POLL_MS, WALLET_ACTIVE_TRANSFER_REFRESH_MS, WALLET_IDLE_ACTIVE_TRANSFER_REFRESH_MS, WALLET_VISIBLE_TRANSFER_DISCOVERY_WINDOW_MS, WALLET_ACTIVE_TRANSFER_EMPTY_SCAN_LIMIT = 8, WALLET_CACHE_HYDRATE_DELAY_MS = 0, WALLET_BOOT_REFRESH_DELAY_MS = 500, WALLET_BOOT_CACHED_REFRESH_DELAY_MS = 2500, WALLET_REGTEST_DEPOSIT_CLAIM_POLL_MS, WALLET_MAINNET_DEPOSIT_CLAIM_POLL_MS, WALLET_BALANCE_EVENT_COALESCE_MS, WALLET_INCOMING_UPDATE_COALESCE_MS = 250, WALLET_AUTO_CLAIM_MAX_FEE_SATS = 5000, WALLET_CLAIM_PAGE_SIZE = 100, WALLET_PENDING_TRANSFER_CLAIM_BATCH_SIZE = 50, WALLET_PENDING_TRANSFER_STATUS_BATCH_SIZE = 2, WALLET_PENDING_TRANSFER_COLD_REFRESH_BATCH_SIZE = 50, WALLET_PENDING_TRANSFER_COLD_REFRESH_INTERVAL_MS, WALLET_PENDING_TRANSFER_ADAPTIVE_BATCH_SMALL_QUEUE = 3, WALLET_PENDING_TRANSFER_ADAPTIVE_BATCH_LARGE_QUEUE = 10, WALLET_PENDING_TRANSFER_ADAPTIVE_BATCH_SMALL_SIZE = 2, WALLET_PENDING_TRANSFER_ADAPTIVE_BATCH_LARGE_SIZE = 3, WALLET_PENDING_TRANSFER_SLOW_CLAIM_MS, WALLET_PENDING_TRANSFER_CLAIM_COOLDOWN_MS, WALLET_SDK_BACKGROUND_QUIET_MS, WALLET_RECENT_TRANSFER_LIMIT = 100, WALLET_TRANSFER_CACHE_LIMIT = 1e4, WALLET_TRANSFER_PAGE_LIMIT = 100, WALLET_TRANSFER_FETCH_THROTTLE_MS = 150, WALLET_PENDING_TRANSFER_CLAIM_RETRY_MS, WALLET_SENT_TRANSFER_REFRESH_DELAY_MS, WALLET_PENDING_TRANSFER_BOOT_GRACE_MS, WALLET_PENDING_TRANSFER_HOT_AGE_MS, WALLET_PENDING_TRANSFER_WARM_AGE_MS, WALLET_PENDING_TRANSFER_WARM_RETRY_MS, WALLET_PENDING_TRANSFER_STALE_RETRY_MS, WALLET_PENDING_TRANSFER_STUCK_RETRY_MS, WALLET_PENDING_TRANSFER_DORMANT_RETRY_MS, WALLET_TRANSFER_CACHE_WRITE_DELAY_MS;
|
|
104538
104568
|
var init_config = __esm(() => {
|
|
104539
104569
|
MINUTE_MS = 60 * MS_PER_SECOND;
|
|
104540
104570
|
HOUR_MS = 60 * MINUTE_MS;
|
|
@@ -104545,7 +104575,7 @@ var init_config = __esm(() => {
|
|
|
104545
104575
|
LOCAL_PROFILE_CACHE_MAX_AGE_MS = 30 * DAY_MS;
|
|
104546
104576
|
LOCAL_AVATAR_CACHE_MAX_BYTES = 128 * MIB_BYTES;
|
|
104547
104577
|
LOCAL_AVATAR_CACHE_MAX_AGE_MS = 30 * DAY_MS;
|
|
104548
|
-
AVATAR_IMAGE_MAX_BYTES =
|
|
104578
|
+
AVATAR_IMAGE_MAX_BYTES = 256 * KIB_BYTES;
|
|
104549
104579
|
CHAT_READY_DOWNLOAD_MAX_BYTES = 8 * MIB_BYTES;
|
|
104550
104580
|
CHAT_MESSAGE_FILE_CACHE_MAX_BYTES = 64 * MIB_BYTES;
|
|
104551
104581
|
CHAT_UNSAVED_TTL_MS = CHAT_UNSAVED_TTL_DAYS * DAY_MS;
|
|
@@ -105980,20 +106010,17 @@ function expectedSigningKeys(pair, signingKeysByChatKey) {
|
|
|
105980
106010
|
}
|
|
105981
106011
|
return values;
|
|
105982
106012
|
}
|
|
105983
|
-
async function
|
|
106013
|
+
async function preverifyExpectedSigner(pair, sig, bytes, options = {}) {
|
|
105984
106014
|
if (!options?.crypto?.preverifyBeforeOpen) {
|
|
105985
|
-
return
|
|
105986
|
-
}
|
|
105987
|
-
const signingKeysByChatKey = expectedSigningKeys(pair, options?.signingKeysByChatKey);
|
|
105988
|
-
if (signingKeysByChatKey.length < 2) {
|
|
105989
|
-
return true;
|
|
106015
|
+
return "";
|
|
105990
106016
|
}
|
|
105991
|
-
|
|
106017
|
+
const signingPublicKeys = expectedSigningKeys(pair, options?.signingKeysByChatKey);
|
|
106018
|
+
for (const signingPublicKey of signingPublicKeys) {
|
|
105992
106019
|
if (await verifyMsgSignature(signingPublicKey, sig, bytes, options)) {
|
|
105993
|
-
return
|
|
106020
|
+
return signingPublicKey;
|
|
105994
106021
|
}
|
|
105995
106022
|
}
|
|
105996
|
-
return
|
|
106023
|
+
return null;
|
|
105997
106024
|
}
|
|
105998
106025
|
async function sealMsg(pair, message, options = {}) {
|
|
105999
106026
|
const head = getHead(pair, message);
|
|
@@ -106014,14 +106041,16 @@ async function openMsg(pair, data, options = {}) {
|
|
|
106014
106041
|
const { suite, flags, nonce, sig, ct } = unpackMsgBody(data.body);
|
|
106015
106042
|
const aad = getMsgAad(pair, head, suite, flags);
|
|
106016
106043
|
const signatureInput = getSignatureInput(aad, nonce, ct);
|
|
106017
|
-
|
|
106044
|
+
const preverifiedSigner = await preverifyExpectedSigner(pair, sig, signatureInput, options);
|
|
106045
|
+
if (preverifiedSigner == null) {
|
|
106018
106046
|
throw new Error("invalid chat action signature");
|
|
106019
106047
|
}
|
|
106020
106048
|
const plaintext = await openMsgPlaintext(pair, nonce, ct, aad, options);
|
|
106021
106049
|
try {
|
|
106022
106050
|
const action = JSON.parse(decoder.decode(plaintext));
|
|
106023
106051
|
const normalized = normalizeOpenedAction(pair, head, action, options);
|
|
106024
|
-
|
|
106052
|
+
const validSignature = preverifiedSigner ? normalized.signingPublicKey === preverifiedSigner : await verifyMsgSignature(normalized.signingPublicKey, sig, signatureInput, options);
|
|
106053
|
+
if (!validSignature) {
|
|
106025
106054
|
throw new Error("invalid chat action signature");
|
|
106026
106055
|
}
|
|
106027
106056
|
return {
|
|
@@ -106095,40 +106124,120 @@ var init_protocol = __esm(() => {
|
|
|
106095
106124
|
});
|
|
106096
106125
|
|
|
106097
106126
|
// ../../shared/chat/pairs.js
|
|
106127
|
+
function accountGeneration(chatPK) {
|
|
106128
|
+
return accountGenerations.get(cleanText(chatPK)) || 0;
|
|
106129
|
+
}
|
|
106098
106130
|
function getChatPairKey(chatPK, peerChatPK, chatId = "") {
|
|
106099
106131
|
if (!chatPK || !peerChatPK)
|
|
106100
106132
|
return null;
|
|
106101
106133
|
return `${cleanText(chatPK)}|${cleanText(peerChatPK)}|${cleanText(chatId)}`;
|
|
106102
106134
|
}
|
|
106103
|
-
function
|
|
106104
|
-
|
|
106105
|
-
|
|
106135
|
+
function closeEntry(entry) {
|
|
106136
|
+
if (!entry || entry.closed || entry.leases > 0) {
|
|
106137
|
+
return;
|
|
106138
|
+
}
|
|
106139
|
+
entry.closed = true;
|
|
106140
|
+
closeChatPair(entry.pair);
|
|
106141
|
+
}
|
|
106142
|
+
function retireEntry(entry) {
|
|
106143
|
+
if (!entry || entry.retired) {
|
|
106144
|
+
return;
|
|
106145
|
+
}
|
|
106146
|
+
entry.retired = true;
|
|
106147
|
+
closeEntry(entry);
|
|
106148
|
+
}
|
|
106149
|
+
function releaseEntry(entry) {
|
|
106150
|
+
if (!entry || entry.leases <= 0) {
|
|
106151
|
+
return;
|
|
106152
|
+
}
|
|
106153
|
+
entry.leases -= 1;
|
|
106154
|
+
if (entry.retired) {
|
|
106155
|
+
closeEntry(entry);
|
|
106156
|
+
}
|
|
106157
|
+
}
|
|
106158
|
+
function evictOverflow() {
|
|
106159
|
+
while (pairCache.size > MAX_PAIR_CACHE) {
|
|
106160
|
+
const firstKey = pairCache.keys().next().value;
|
|
106161
|
+
if (!firstKey) {
|
|
106162
|
+
return;
|
|
106163
|
+
}
|
|
106164
|
+
const entry = pairCache.get(firstKey);
|
|
106165
|
+
pairCache.delete(firstKey);
|
|
106166
|
+
retireEntry(entry);
|
|
106167
|
+
}
|
|
106168
|
+
}
|
|
106169
|
+
function clearChatPairCache(chatPK = "") {
|
|
106170
|
+
const account = cleanText(chatPK);
|
|
106171
|
+
if (!account) {
|
|
106172
|
+
cacheGeneration += 1;
|
|
106173
|
+
accountGenerations.clear();
|
|
106174
|
+
for (const entry of pairCache.values()) {
|
|
106175
|
+
retireEntry(entry);
|
|
106176
|
+
}
|
|
106177
|
+
pairCache.clear();
|
|
106178
|
+
return;
|
|
106179
|
+
}
|
|
106180
|
+
accountGenerations.set(account, accountGeneration(account) + 1);
|
|
106181
|
+
for (const [key, entry] of pairCache) {
|
|
106182
|
+
if (entry.account !== account) {
|
|
106183
|
+
continue;
|
|
106184
|
+
}
|
|
106185
|
+
pairCache.delete(key);
|
|
106186
|
+
retireEntry(entry);
|
|
106106
106187
|
}
|
|
106107
|
-
pairCache.clear();
|
|
106108
106188
|
}
|
|
106109
|
-
async function
|
|
106189
|
+
async function acquireCachedPair(chatPK, chatPrivKey, peerChatPK, options = {}) {
|
|
106190
|
+
const account = cleanText(chatPK);
|
|
106110
106191
|
const chatId = cleanText(options?.chatId);
|
|
106111
106192
|
const key = getChatPairKey(chatPK, peerChatPK, chatId);
|
|
106193
|
+
const generation = cacheGeneration;
|
|
106194
|
+
const accountVersion = accountGeneration(account);
|
|
106112
106195
|
if (!key) {
|
|
106113
|
-
|
|
106196
|
+
const pair = await openChatPair(chatPK, chatPrivKey, peerChatPK, { chatId });
|
|
106197
|
+
const entry2 = { pair, leases: 1, retired: true, closed: false };
|
|
106198
|
+
return {
|
|
106199
|
+
pair,
|
|
106200
|
+
release: () => releaseEntry(entry2)
|
|
106201
|
+
};
|
|
106114
106202
|
}
|
|
106115
|
-
|
|
106116
|
-
if (
|
|
106117
|
-
|
|
106118
|
-
|
|
106119
|
-
|
|
106120
|
-
|
|
106121
|
-
|
|
106122
|
-
|
|
106123
|
-
|
|
106124
|
-
pairCache.delete(firstKey);
|
|
106203
|
+
let entry = pairCache.get(key);
|
|
106204
|
+
if (!entry) {
|
|
106205
|
+
const pair = await openChatPair(chatPK, chatPrivKey, peerChatPK, { chatId });
|
|
106206
|
+
if (generation !== cacheGeneration || accountVersion !== accountGeneration(account)) {
|
|
106207
|
+
const staleEntry = { pair, leases: 1, retired: true, closed: false };
|
|
106208
|
+
return {
|
|
106209
|
+
pair,
|
|
106210
|
+
release: () => releaseEntry(staleEntry)
|
|
106211
|
+
};
|
|
106125
106212
|
}
|
|
106213
|
+
entry = pairCache.get(key);
|
|
106214
|
+
if (entry) {
|
|
106215
|
+
closeChatPair(pair);
|
|
106216
|
+
} else {
|
|
106217
|
+
entry = { account, pair, leases: 0, retired: false, closed: false };
|
|
106218
|
+
pairCache.set(key, entry);
|
|
106219
|
+
evictOverflow();
|
|
106220
|
+
}
|
|
106221
|
+
} else {
|
|
106222
|
+
pairCache.delete(key);
|
|
106223
|
+
pairCache.set(key, entry);
|
|
106224
|
+
}
|
|
106225
|
+
entry.leases += 1;
|
|
106226
|
+
return {
|
|
106227
|
+
pair: entry.pair,
|
|
106228
|
+
release: () => releaseEntry(entry)
|
|
106229
|
+
};
|
|
106230
|
+
}
|
|
106231
|
+
async function withCachedPair(chatPK, chatPrivKey, peerChatPK, options, runWithPair) {
|
|
106232
|
+
const { pair, release } = await acquireCachedPair(chatPK, chatPrivKey, peerChatPK, options);
|
|
106233
|
+
try {
|
|
106234
|
+
return await runWithPair(pair);
|
|
106235
|
+
} finally {
|
|
106236
|
+
release();
|
|
106126
106237
|
}
|
|
106127
|
-
return pair;
|
|
106128
106238
|
}
|
|
106129
106239
|
async function resolveLinkId(chatPK, chatPrivKey, peerChatPK) {
|
|
106130
|
-
|
|
106131
|
-
return pair?.linkId || null;
|
|
106240
|
+
return withCachedPair(chatPK, chatPrivKey, peerChatPK, {}, (pair) => pair?.linkId || null);
|
|
106132
106241
|
}
|
|
106133
106242
|
async function resolvePeerChat(cloud, chatPK, chatPrivateKey, peerChatPK, options = {}) {
|
|
106134
106243
|
const existingChatId = cleanText(options?.chatId);
|
|
@@ -106159,13 +106268,14 @@ async function resolvePeerChat(cloud, chatPK, chatPrivateKey, peerChatPK, option
|
|
|
106159
106268
|
exists: linkChat?.exists === true
|
|
106160
106269
|
};
|
|
106161
106270
|
}
|
|
106162
|
-
var pairCache, MAX_PAIR_CACHE;
|
|
106271
|
+
var pairCache, MAX_PAIR_CACHE, cacheGeneration = 0, accountGenerations;
|
|
106163
106272
|
var init_pairs = __esm(() => {
|
|
106164
106273
|
init_config();
|
|
106165
106274
|
init_chat();
|
|
106166
106275
|
init_protocol();
|
|
106167
106276
|
pairCache = new Map;
|
|
106168
106277
|
MAX_PAIR_CACHE = CHAT_PAIR_CACHE_LIMIT;
|
|
106278
|
+
accountGenerations = new Map;
|
|
106169
106279
|
});
|
|
106170
106280
|
|
|
106171
106281
|
// ../../shared/utils/diagnostics.js
|
|
@@ -106318,14 +106428,16 @@ function lockWallet(wallet) {
|
|
|
106318
106428
|
cleanup?.catch?.(() => {});
|
|
106319
106429
|
} catch {}
|
|
106320
106430
|
}
|
|
106321
|
-
function lockChat(chatPrivateKey) {
|
|
106431
|
+
function lockChat(chatPrivateKey, chatPK = "") {
|
|
106322
106432
|
try {
|
|
106323
106433
|
if (chatPrivateKey) {
|
|
106324
106434
|
chatPrivateKey.fill(0);
|
|
106325
106435
|
}
|
|
106326
106436
|
} catch {}
|
|
106327
106437
|
try {
|
|
106328
|
-
|
|
106438
|
+
if (chatPK) {
|
|
106439
|
+
clearChatPairCache(chatPK);
|
|
106440
|
+
}
|
|
106329
106441
|
} catch {}
|
|
106330
106442
|
}
|
|
106331
106443
|
var init_vault = __esm(() => {
|
|
@@ -106345,7 +106457,7 @@ function walletPubkey(value) {
|
|
|
106345
106457
|
}
|
|
106346
106458
|
return key;
|
|
106347
106459
|
}
|
|
106348
|
-
function closeSessionResources({ wallet, chatPrivateKey, localCache, vaultAccess, vaultSigner } = {}) {
|
|
106460
|
+
function closeSessionResources({ wallet, chatPK, chatPrivateKey, localCache, vaultAccess, vaultSigner } = {}) {
|
|
106349
106461
|
try {
|
|
106350
106462
|
vaultAccess?.close?.();
|
|
106351
106463
|
} catch {}
|
|
@@ -106356,7 +106468,7 @@ function closeSessionResources({ wallet, chatPrivateKey, localCache, vaultAccess
|
|
|
106356
106468
|
localCache?.close?.();
|
|
106357
106469
|
} catch {}
|
|
106358
106470
|
lockWallet(wallet);
|
|
106359
|
-
lockChat(chatPrivateKey);
|
|
106471
|
+
lockChat(chatPrivateKey, chatPK);
|
|
106360
106472
|
}
|
|
106361
106473
|
function createAccountSession(resources = {}) {
|
|
106362
106474
|
let closed = false;
|
|
@@ -106447,6 +106559,32 @@ function notifySeedDecrypted(callback, markDiag2, source) {
|
|
|
106447
106559
|
failed(error);
|
|
106448
106560
|
}
|
|
106449
106561
|
}
|
|
106562
|
+
function startWalletBoot(bootWallet2, walletMnemonic, user, options) {
|
|
106563
|
+
let closed = false;
|
|
106564
|
+
let handedOff = false;
|
|
106565
|
+
let wallet = null;
|
|
106566
|
+
const result = Promise.resolve().then(() => bootWallet2(walletMnemonic, user, options)).then((identity) => {
|
|
106567
|
+
wallet = identity?.wallet || null;
|
|
106568
|
+
if (closed && wallet) {
|
|
106569
|
+
lockWallet(wallet);
|
|
106570
|
+
}
|
|
106571
|
+
return identity;
|
|
106572
|
+
});
|
|
106573
|
+
return {
|
|
106574
|
+
result,
|
|
106575
|
+
handoff() {
|
|
106576
|
+
handedOff = true;
|
|
106577
|
+
},
|
|
106578
|
+
close() {
|
|
106579
|
+
if (closed)
|
|
106580
|
+
return;
|
|
106581
|
+
closed = true;
|
|
106582
|
+
if (wallet && !handedOff) {
|
|
106583
|
+
lockWallet(wallet);
|
|
106584
|
+
}
|
|
106585
|
+
}
|
|
106586
|
+
};
|
|
106587
|
+
}
|
|
106450
106588
|
async function openVaultAccountSession(vault, password, options = {}) {
|
|
106451
106589
|
const {
|
|
106452
106590
|
uid,
|
|
@@ -106488,6 +106626,7 @@ async function openVaultAccountSession(vault, password, options = {}) {
|
|
|
106488
106626
|
throw new Error("unlockSettings missing");
|
|
106489
106627
|
const { decryptSeed: decryptSeed2, unpackVaultSeedData } = vaultCrypto;
|
|
106490
106628
|
let wallet = null;
|
|
106629
|
+
let chatPK = "";
|
|
106491
106630
|
let chatPrivateKey = null;
|
|
106492
106631
|
let localCache = null;
|
|
106493
106632
|
let masterSeed = null;
|
|
@@ -106498,6 +106637,7 @@ async function openVaultAccountSession(vault, password, options = {}) {
|
|
|
106498
106637
|
let vaultSigner = null;
|
|
106499
106638
|
let vaultAccess = null;
|
|
106500
106639
|
let vaultAccessResult = null;
|
|
106640
|
+
let walletBoot = null;
|
|
106501
106641
|
let network;
|
|
106502
106642
|
try {
|
|
106503
106643
|
onStage?.("unlocking");
|
|
@@ -106566,46 +106706,18 @@ async function openVaultAccountSession(vault, password, options = {}) {
|
|
|
106566
106706
|
onStage?.("wallet");
|
|
106567
106707
|
const walletStartedAt = Date.now();
|
|
106568
106708
|
mark(diag, "vault.unlock.wallet.start", { source });
|
|
106569
|
-
|
|
106570
|
-
wallet = walletIdentity?.wallet;
|
|
106571
|
-
const walletPK = walletPubkey(walletIdentity?.walletPK);
|
|
106572
|
-
mark(diag, "vault.unlock.wallet.done", { elapsedMs: Date.now() - walletStartedAt, source });
|
|
106573
|
-
requireCurrent(isCurrent);
|
|
106709
|
+
walletBoot = startWalletBoot(bootWallet2, walletMnemonic, user, { network, diag });
|
|
106574
106710
|
onStage?.("chat");
|
|
106575
106711
|
const chatStartedAt = Date.now();
|
|
106576
106712
|
mark(diag, "vault.unlock.chat.start", { source });
|
|
106577
106713
|
const chatIdentity = await bootChat2(chatSeed, user, { diag });
|
|
106578
106714
|
chatPrivateKey = chatIdentity?.chatPrivateKey;
|
|
106579
|
-
|
|
106715
|
+
chatPK = cleanText(chatIdentity?.chatPK);
|
|
106580
106716
|
if (!chatPrivateKey || !chatPK)
|
|
106581
106717
|
throw new Error("chat identity missing");
|
|
106582
106718
|
chatSeed = null;
|
|
106583
106719
|
mark(diag, "vault.unlock.chat.done", { elapsedMs: Date.now() - chatStartedAt, source });
|
|
106584
106720
|
requireCurrent(isCurrent);
|
|
106585
|
-
const identityPayload = {};
|
|
106586
|
-
if (walletIdentity?.walletPKNeedsWrite) {
|
|
106587
|
-
identityPayload.walletPK = walletPK;
|
|
106588
|
-
identityPayload.network = network;
|
|
106589
|
-
}
|
|
106590
|
-
if (chatIdentity?.chatPKNeedsWrite) {
|
|
106591
|
-
identityPayload.chatPK = chatPK;
|
|
106592
|
-
}
|
|
106593
|
-
const identityFields = Object.keys(identityPayload);
|
|
106594
|
-
let identityResult = null;
|
|
106595
|
-
if (identityFields.length) {
|
|
106596
|
-
const identitiesStartedAt = Date.now();
|
|
106597
|
-
mark(diag, "vault.unlock.identities.start", { source, fields: identityFields });
|
|
106598
|
-
identityResult = cloud.user.profile.identity.write(identityPayload).then(() => {
|
|
106599
|
-
mark(diag, "vault.unlock.identities.done", {
|
|
106600
|
-
elapsedMs: Date.now() - identitiesStartedAt,
|
|
106601
|
-
source,
|
|
106602
|
-
fields: identityFields
|
|
106603
|
-
});
|
|
106604
|
-
return { error: null };
|
|
106605
|
-
}, (error) => ({ error }));
|
|
106606
|
-
} else {
|
|
106607
|
-
mark(diag, "vault.unlock.identities.skip", { source });
|
|
106608
|
-
}
|
|
106609
106721
|
const cacheStartedAt = Date.now();
|
|
106610
106722
|
mark(diag, "vault.unlock.localCache.start", { source });
|
|
106611
106723
|
localCache = await openLocalCache(cacheKey, { uid, network });
|
|
@@ -106613,20 +106725,16 @@ async function openVaultAccountSession(vault, password, options = {}) {
|
|
|
106613
106725
|
cleanBytes(cacheKey);
|
|
106614
106726
|
cacheKey = null;
|
|
106615
106727
|
requireCurrent(isCurrent);
|
|
106616
|
-
const identityWrite = await identityResult;
|
|
106617
|
-
if (identityWrite?.error)
|
|
106618
|
-
throw identityWrite.error;
|
|
106619
|
-
requireCurrent(isCurrent);
|
|
106620
106728
|
const signatureResult = await vaultAccessResult;
|
|
106621
106729
|
if (signatureResult.error)
|
|
106622
106730
|
throw signatureResult.error;
|
|
106623
106731
|
vaultAccess = signatureResult.access;
|
|
106624
106732
|
requireCurrent(isCurrent);
|
|
106625
|
-
|
|
106733
|
+
const session = createAccountSession({
|
|
106626
106734
|
uid,
|
|
106627
106735
|
network,
|
|
106628
|
-
wallet,
|
|
106629
|
-
walletPK,
|
|
106736
|
+
wallet: null,
|
|
106737
|
+
walletPK: null,
|
|
106630
106738
|
chatPK,
|
|
106631
106739
|
chatPrivateKey,
|
|
106632
106740
|
localCache,
|
|
@@ -106634,12 +106742,56 @@ async function openVaultAccountSession(vault, password, options = {}) {
|
|
|
106634
106742
|
vaultAccess,
|
|
106635
106743
|
vaultPK: vaultSigner.publicKey
|
|
106636
106744
|
});
|
|
106745
|
+
session.own(walletBoot);
|
|
106746
|
+
const walletReady = walletBoot.result.then(async (walletIdentity) => {
|
|
106747
|
+
if (session.closed)
|
|
106748
|
+
throw new Error("account session closed");
|
|
106749
|
+
const readyWallet = walletIdentity?.wallet;
|
|
106750
|
+
const walletPK = walletPubkey(walletIdentity?.walletPK);
|
|
106751
|
+
if (!readyWallet)
|
|
106752
|
+
throw new Error("wallet missing");
|
|
106753
|
+
mark(diag, "vault.unlock.wallet.done", { elapsedMs: Date.now() - walletStartedAt, source });
|
|
106754
|
+
const identityPayload = {};
|
|
106755
|
+
if (walletIdentity?.walletPKNeedsWrite) {
|
|
106756
|
+
identityPayload.walletPK = walletPK;
|
|
106757
|
+
identityPayload.network = network;
|
|
106758
|
+
}
|
|
106759
|
+
if (chatIdentity?.chatPKNeedsWrite) {
|
|
106760
|
+
identityPayload.chatPK = chatPK;
|
|
106761
|
+
}
|
|
106762
|
+
const identityFields = Object.keys(identityPayload);
|
|
106763
|
+
if (identityFields.length) {
|
|
106764
|
+
const identitiesStartedAt = Date.now();
|
|
106765
|
+
mark(diag, "vault.unlock.identities.start", { source, fields: identityFields });
|
|
106766
|
+
await cloud.user.profile.identity.write(identityPayload);
|
|
106767
|
+
mark(diag, "vault.unlock.identities.done", {
|
|
106768
|
+
elapsedMs: Date.now() - identitiesStartedAt,
|
|
106769
|
+
source,
|
|
106770
|
+
fields: identityFields
|
|
106771
|
+
});
|
|
106772
|
+
} else {
|
|
106773
|
+
mark(diag, "vault.unlock.identities.skip", { source });
|
|
106774
|
+
}
|
|
106775
|
+
if (session.closed)
|
|
106776
|
+
throw new Error("account session closed");
|
|
106777
|
+
walletBoot.handoff();
|
|
106778
|
+
session.wallet = readyWallet;
|
|
106779
|
+
session.walletPK = walletPK;
|
|
106780
|
+
return { wallet: readyWallet, walletPK };
|
|
106781
|
+
}).catch((error) => {
|
|
106782
|
+
walletBoot.close();
|
|
106783
|
+
throw error;
|
|
106784
|
+
});
|
|
106785
|
+
walletReady.catch(() => {});
|
|
106786
|
+
session.walletReady = walletReady;
|
|
106787
|
+
return session;
|
|
106637
106788
|
} catch (error) {
|
|
106789
|
+
walletBoot?.close();
|
|
106638
106790
|
if (vaultAccessResult && !vaultAccess) {
|
|
106639
106791
|
const signatureResult = await vaultAccessResult;
|
|
106640
106792
|
vaultAccess = signatureResult.access;
|
|
106641
106793
|
}
|
|
106642
|
-
closeSessionResources({ wallet, chatPrivateKey, localCache, vaultAccess, vaultSigner });
|
|
106794
|
+
closeSessionResources({ wallet, chatPK, chatPrivateKey, localCache, vaultAccess, vaultSigner });
|
|
106643
106795
|
throw error;
|
|
106644
106796
|
} finally {
|
|
106645
106797
|
cleanBytes(masterSeed, walletEntropy, chatSeed, cacheKey, settingsKey);
|
|
@@ -106654,6 +106806,7 @@ async function openAccountSessionFromSecrets(walletEntropy, chatSeed, masterSeed
|
|
|
106654
106806
|
}
|
|
106655
106807
|
const walletMnemonic = mnemonicFromWalletEntropy(walletEntropy);
|
|
106656
106808
|
let wallet = null;
|
|
106809
|
+
let chatPK = "";
|
|
106657
106810
|
let chatPrivateKey = null;
|
|
106658
106811
|
let chatPubKey = null;
|
|
106659
106812
|
let vaultSigner = null;
|
|
@@ -106682,10 +106835,11 @@ async function openAccountSessionFromSecrets(walletEntropy, chatSeed, masterSeed
|
|
|
106682
106835
|
throw new Error("vault signature uid missing");
|
|
106683
106836
|
vaultAccess = await cloud.auth.vaultSignature.open(vaultSigner);
|
|
106684
106837
|
}
|
|
106838
|
+
chatPK = toHex(chatPubKey);
|
|
106685
106839
|
return createAccountSession({
|
|
106686
106840
|
wallet,
|
|
106687
106841
|
walletPK,
|
|
106688
|
-
chatPK
|
|
106842
|
+
chatPK,
|
|
106689
106843
|
chatPrivateKey,
|
|
106690
106844
|
localCache,
|
|
106691
106845
|
network,
|
|
@@ -106694,7 +106848,7 @@ async function openAccountSessionFromSecrets(walletEntropy, chatSeed, masterSeed
|
|
|
106694
106848
|
vaultPK: vaultSigner.publicKey
|
|
106695
106849
|
});
|
|
106696
106850
|
} catch (error) {
|
|
106697
|
-
closeSessionResources({ wallet, chatPrivateKey, localCache, vaultAccess, vaultSigner });
|
|
106851
|
+
closeSessionResources({ wallet, chatPK, chatPrivateKey, localCache, vaultAccess, vaultSigner });
|
|
106698
106852
|
throw error;
|
|
106699
106853
|
} finally {
|
|
106700
106854
|
cleanBytes(chatSeed, chatPubKey);
|
|
@@ -106866,18 +107020,13 @@ var init_values = __esm(() => {
|
|
|
106866
107020
|
|
|
106867
107021
|
// ../../shared/avatar.js
|
|
106868
107022
|
function readAvatarVersion(value) {
|
|
106869
|
-
|
|
106870
|
-
|
|
106871
|
-
}
|
|
106872
|
-
const version = Number(value);
|
|
106873
|
-
return Number.isSafeInteger(version) && version >= 0 ? version : null;
|
|
107023
|
+
const version = typeof value === "string" ? value.trim().toLowerCase() : "";
|
|
107024
|
+
return AVATAR_VERSION_RE.test(version) ? version : null;
|
|
106874
107025
|
}
|
|
106875
|
-
|
|
106876
|
-
|
|
106877
|
-
|
|
106878
|
-
|
|
106879
|
-
}
|
|
106880
|
-
var init_avatar = () => {};
|
|
107026
|
+
var AVATAR_VERSION_RE;
|
|
107027
|
+
var init_avatar = __esm(() => {
|
|
107028
|
+
AVATAR_VERSION_RE = /^[0-9a-f]{64}$/;
|
|
107029
|
+
});
|
|
106881
107030
|
|
|
106882
107031
|
// ../../shared/moderation.js
|
|
106883
107032
|
function banUntilMs(ban) {
|
|
@@ -107155,11 +107304,16 @@ function createUser({ cloud, network, avatarCache = null, diag = null, onSession
|
|
|
107155
107304
|
markDiag(diag, "user.avatar.fetch.start", { force: !!force, persist: !!persist, hasVersion: avatarVersion != null });
|
|
107156
107305
|
try {
|
|
107157
107306
|
const promise = (async () => {
|
|
107158
|
-
|
|
107159
|
-
|
|
107160
|
-
|
|
107307
|
+
if (persist && avatarVersion != null && avatarCache && typeof cloud.peer.avatar.read === "function") {
|
|
107308
|
+
try {
|
|
107309
|
+
const bytes = await cloud.peer.avatar.read(uid, { version: avatarVersion });
|
|
107310
|
+
const cachedAvatar = await writeCachedAvatar(uid, { version: avatarVersion, bytes });
|
|
107311
|
+
if (cachedAvatar) {
|
|
107312
|
+
return cachedAvatar;
|
|
107313
|
+
}
|
|
107314
|
+
} catch {}
|
|
107161
107315
|
}
|
|
107162
|
-
return
|
|
107316
|
+
return cloud.peer.avatar.url(uid, { version: avatarVersion });
|
|
107163
107317
|
})().then((nextAvatar) => {
|
|
107164
107318
|
markDone(diag, "user.avatar.fetch", startedAt, { found: !!nextAvatar, hasVersion: avatarVersion != null });
|
|
107165
107319
|
if (!nextAvatar || avatarFetch.uid !== uid || avatarFetch.key !== key) {
|
|
@@ -107499,10 +107653,12 @@ function createUser({ cloud, network, avatarCache = null, diag = null, onSession
|
|
|
107499
107653
|
}
|
|
107500
107654
|
function refetchAvatar(options = {}) {
|
|
107501
107655
|
const requestedVersion = readAvatarVersion(options?.version);
|
|
107502
|
-
const
|
|
107503
|
-
|
|
107504
|
-
|
|
107505
|
-
|
|
107656
|
+
const nextVersion = requestedVersion ?? state.avatarVersion;
|
|
107657
|
+
return fetchAvatar(state.uid, {
|
|
107658
|
+
force: options?.force === true || state.avatarVersion !== nextVersion || !state.avatar,
|
|
107659
|
+
persist: options?.persist !== false,
|
|
107660
|
+
version: nextVersion
|
|
107661
|
+
});
|
|
107506
107662
|
}
|
|
107507
107663
|
function setNetwork(nextNetwork) {
|
|
107508
107664
|
if (activeNetwork === nextNetwork)
|
|
@@ -107770,7 +107926,7 @@ function getSubtleCrypto() {
|
|
|
107770
107926
|
async function importAesKey(key, usages) {
|
|
107771
107927
|
return getSubtleCrypto().importKey("raw", toBytes32(key, "file key"), { name: "AES-GCM" }, false, usages);
|
|
107772
107928
|
}
|
|
107773
|
-
async function sealFile(
|
|
107929
|
+
async function sealFile(key, bytes, scope) {
|
|
107774
107930
|
const fileKey = new Uint8Array(toBytes32(key, "file key"));
|
|
107775
107931
|
try {
|
|
107776
107932
|
const cryptoKey = await importAesKey(fileKey, ["encrypt"]);
|
|
@@ -107933,20 +108089,22 @@ async function toUploadBytes(data) {
|
|
|
107933
108089
|
}
|
|
107934
108090
|
return toBytes2(data, "upload bytes");
|
|
107935
108091
|
}
|
|
107936
|
-
async function makeChatFileUploadPayload(
|
|
107937
|
-
const
|
|
108092
|
+
async function makeChatFileUploadPayload(chatId, cid, data, { cacheControl = "private, max-age=0, no-transform" } = {}) {
|
|
108093
|
+
const nextChatId = cleanMediaChatId(chatId);
|
|
107938
108094
|
const mediaId = makeChatMediaId();
|
|
107939
|
-
const path = mediaFilePath(
|
|
108095
|
+
const path = mediaFilePath(nextChatId, mediaId);
|
|
107940
108096
|
const expiresAt = Date.now() + CHAT_MEDIA_TTL_MS2;
|
|
107941
108097
|
const key = createFileKey();
|
|
107942
108098
|
try {
|
|
107943
108099
|
const uploadBytes = await toUploadBytes(data);
|
|
107944
108100
|
assertChatUploadByteSize(uploadBytes);
|
|
108101
|
+
const body = await sealFile(key, uploadBytes, path);
|
|
108102
|
+
assertChatUploadByteSize(body);
|
|
107945
108103
|
return {
|
|
107946
|
-
chatId,
|
|
108104
|
+
chatId: nextChatId,
|
|
107947
108105
|
mediaId,
|
|
107948
108106
|
path,
|
|
107949
|
-
body
|
|
108107
|
+
body,
|
|
107950
108108
|
metadata: {
|
|
107951
108109
|
contentType: "application/octet-stream",
|
|
107952
108110
|
cacheControl
|
|
@@ -107975,10 +108133,12 @@ async function makeSharedFileUploadPayload(data, { contentType = "application/oc
|
|
|
107975
108133
|
try {
|
|
107976
108134
|
const uploadBytes = await toUploadBytes(data);
|
|
107977
108135
|
assertChatUploadByteSize(uploadBytes);
|
|
108136
|
+
const body = await sealFile(key, uploadBytes, path);
|
|
108137
|
+
assertChatUploadByteSize(body);
|
|
107978
108138
|
return {
|
|
107979
108139
|
sharedId,
|
|
107980
108140
|
path,
|
|
107981
|
-
body
|
|
108141
|
+
body,
|
|
107982
108142
|
metadata: {
|
|
107983
108143
|
contentType,
|
|
107984
108144
|
cacheControl
|
|
@@ -109904,10 +110064,19 @@ function sortedUniqueValues(items) {
|
|
|
109904
110064
|
}
|
|
109905
110065
|
|
|
109906
110066
|
// ../../shared/chat/chats.js
|
|
110067
|
+
function sameSigningKeys(left, right) {
|
|
110068
|
+
if (left === right)
|
|
110069
|
+
return true;
|
|
110070
|
+
const leftKeys = Object.keys(left || {});
|
|
110071
|
+
const rightKeys = Object.keys(right || {});
|
|
110072
|
+
if (leftKeys.length !== rightKeys.length)
|
|
110073
|
+
return false;
|
|
110074
|
+
return leftKeys.every((key) => left[key] === right[key]);
|
|
110075
|
+
}
|
|
109907
110076
|
function sameChatShape(a, b) {
|
|
109908
110077
|
if (!a || !b)
|
|
109909
110078
|
return a === b;
|
|
109910
|
-
return a.id === b.id && a.protocol === b.protocol && a.linkId === b.linkId && a.ts === b.ts && a.startMs === b.startMs && a.unseen === b.unseen && a.settings?.retention === b.settings?.retention && sameChatPreview(a.preview, b.preview);
|
|
110079
|
+
return a.id === b.id && a.protocol === b.protocol && a.linkId === b.linkId && a.entryId === b.entryId && a.peerChatPK === b.peerChatPK && a.peerUid === b.peerUid && sameSigningKeys(a.signingKeysByChatKey, b.signingKeysByChatKey) && a.signerShared === b.signerShared && a.ts === b.ts && a.startMs === b.startMs && a.unseen === b.unseen && a.settings?.retention === b.settings?.retention && sameChatPreview(a.preview, b.preview);
|
|
109911
110080
|
}
|
|
109912
110081
|
function sameChats(prev, next) {
|
|
109913
110082
|
if (prev.length !== next.length)
|
|
@@ -110266,8 +110435,10 @@ function emptyPayload() {
|
|
|
110266
110435
|
chatsById: {},
|
|
110267
110436
|
profilesByUid: {},
|
|
110268
110437
|
mediaByKey: {},
|
|
110438
|
+
walletBalance: null,
|
|
110269
110439
|
resumeRoute: null,
|
|
110270
|
-
lastCameraFacing: null
|
|
110440
|
+
lastCameraFacing: null,
|
|
110441
|
+
cloaked: false
|
|
110271
110442
|
};
|
|
110272
110443
|
}
|
|
110273
110444
|
function isObject3(value) {
|
|
@@ -110328,8 +110499,26 @@ function normalizePayload(value) {
|
|
|
110328
110499
|
chatsById: isObject3(input.chatsById) ? input.chatsById : {},
|
|
110329
110500
|
profilesByUid: isObject3(input.profilesByUid) ? input.profilesByUid : {},
|
|
110330
110501
|
mediaByKey: isObject3(input.mediaByKey) ? input.mediaByKey : {},
|
|
110502
|
+
walletBalance: cleanWalletBalance(input.walletBalance),
|
|
110331
110503
|
resumeRoute: cleanResumeRoute(input.resumeRoute),
|
|
110332
|
-
lastCameraFacing: cleanCameraFacing(input.lastCameraFacing)
|
|
110504
|
+
lastCameraFacing: cleanCameraFacing(input.lastCameraFacing),
|
|
110505
|
+
cloaked: input.cloaked === true
|
|
110506
|
+
};
|
|
110507
|
+
}
|
|
110508
|
+
function cleanWalletBalance(value) {
|
|
110509
|
+
if (!isObject3(value))
|
|
110510
|
+
return null;
|
|
110511
|
+
const walletPK = cleanText(value.walletPK).toLowerCase();
|
|
110512
|
+
const network = cleanText(value.network).toLowerCase();
|
|
110513
|
+
const balance = Number(value.balance);
|
|
110514
|
+
if (!walletPK || !network || !Number.isSafeInteger(balance) || balance < 0) {
|
|
110515
|
+
return null;
|
|
110516
|
+
}
|
|
110517
|
+
return {
|
|
110518
|
+
walletPK,
|
|
110519
|
+
network,
|
|
110520
|
+
balance,
|
|
110521
|
+
savedAt: Number.isFinite(value.savedAt) ? value.savedAt : 0
|
|
110333
110522
|
};
|
|
110334
110523
|
}
|
|
110335
110524
|
function cleanResumeRoute(route) {
|
|
@@ -110775,8 +110964,8 @@ function stateFromPayload(payload, { chatId, selfChatPublicKey, peerChatPublicKe
|
|
|
110775
110964
|
if (!cleanOlder.length && !cleanLive.length) {
|
|
110776
110965
|
return { rejectReason: "empty-message-cache" };
|
|
110777
110966
|
}
|
|
110778
|
-
const historyStartReached = payload.historyStartReached === true
|
|
110779
|
-
const payloadHasOlder =
|
|
110967
|
+
const historyStartReached = payload.historyStartReached === true;
|
|
110968
|
+
const payloadHasOlder = payload.hasOlder === true || payload.truncated === true;
|
|
110780
110969
|
const partialOlderThan = partial ? markerFromMessage(cleanOlder[0]) : null;
|
|
110781
110970
|
return {
|
|
110782
110971
|
historyMessages: cleanOlder,
|
|
@@ -110921,7 +111110,7 @@ function writeCachedMessageState(cache, { stateVersion = null, chatId, selfChatP
|
|
|
110921
111110
|
signingKeysVersion: cleanText(signingKeysVersion),
|
|
110922
111111
|
savedAt: Date.now(),
|
|
110923
111112
|
hasOlder: nextHasOlder === true || compacted.truncated,
|
|
110924
|
-
historyStartReached: nextHistoryStartReached === true
|
|
111113
|
+
historyStartReached: nextHistoryStartReached === true,
|
|
110925
111114
|
olderThan: serializeMarker(storedOlderThan),
|
|
110926
111115
|
olderLoaded: nextOlderLoaded === true || compacted.historyMessages.length > 0,
|
|
110927
111116
|
latestServerPage: batchFromLive(compacted.latestMessages, expiredKeys, deletedKeys, nextServerBatch),
|
|
@@ -111180,6 +111369,36 @@ var init_chats2 = __esm(() => {
|
|
|
111180
111369
|
"use client";
|
|
111181
111370
|
});
|
|
111182
111371
|
|
|
111372
|
+
// ../../shared/cache/localdata/balance.js
|
|
111373
|
+
function normalizedBalance(value) {
|
|
111374
|
+
const balance = Number(value);
|
|
111375
|
+
return Number.isSafeInteger(balance) && balance >= 0 ? balance : null;
|
|
111376
|
+
}
|
|
111377
|
+
function writeCachedWalletBalance(cache, { walletPK = null, network = null, balance = null } = {}) {
|
|
111378
|
+
const nextWalletPK = lowerText(walletPK);
|
|
111379
|
+
const nextNetwork = lowerText(network);
|
|
111380
|
+
const nextBalance = normalizedBalance(balance);
|
|
111381
|
+
if (!cache || !nextWalletPK || !nextNetwork || nextBalance == null) {
|
|
111382
|
+
return Promise.resolve(false);
|
|
111383
|
+
}
|
|
111384
|
+
const current = cache.read?.()?.walletBalance;
|
|
111385
|
+
if (sameText(current?.walletPK, nextWalletPK) && sameText(current?.network, nextNetwork) && normalizedBalance(current?.balance) === nextBalance) {
|
|
111386
|
+
return Promise.resolve(false);
|
|
111387
|
+
}
|
|
111388
|
+
return cache.patch((draft) => {
|
|
111389
|
+
draft.walletBalance = {
|
|
111390
|
+
walletPK: nextWalletPK,
|
|
111391
|
+
network: nextNetwork,
|
|
111392
|
+
balance: nextBalance,
|
|
111393
|
+
savedAt: Date.now()
|
|
111394
|
+
};
|
|
111395
|
+
return draft;
|
|
111396
|
+
}).then(() => true);
|
|
111397
|
+
}
|
|
111398
|
+
var init_balance = __esm(() => {
|
|
111399
|
+
"use client";
|
|
111400
|
+
});
|
|
111401
|
+
|
|
111183
111402
|
// ../../shared/cache/localdata/profiles.js
|
|
111184
111403
|
function isUsableProfile(profile, now = Date.now()) {
|
|
111185
111404
|
if (!profile?.uid || !profile.walletPK && !profile.chatPK) {
|
|
@@ -111420,24 +111639,26 @@ async function readCachedTransferHeadState(cache, { walletPK = null } = {}) {
|
|
|
111420
111639
|
const stored = cache ? await cache.readPart(TX_HEAD_PART).catch(() => null) : null;
|
|
111421
111640
|
return stateFromPayload2(stored, { walletPK, source: "head" });
|
|
111422
111641
|
}
|
|
111423
|
-
function
|
|
111424
|
-
if (!
|
|
111425
|
-
return
|
|
111642
|
+
function cachedTransferPayloads({ transfers, walletPK = null, serverEndReached = false, historyCount = null, nextOffset = null, oldestTxMs = null } = {}) {
|
|
111643
|
+
if (!Array.isArray(transfers)) {
|
|
111644
|
+
return null;
|
|
111426
111645
|
}
|
|
111427
111646
|
const nextWalletPK = lowerText(walletPK);
|
|
111428
111647
|
if (!nextWalletPK) {
|
|
111429
|
-
return
|
|
111648
|
+
return null;
|
|
111430
111649
|
}
|
|
111431
111650
|
const visible = [...transfers].filter((tx) => tx?.id && isVisibleTransfer(tx) && transferBelongsToWallet(tx, nextWalletPK)).sort((a, b) => txCreatedMs(b) - txCreatedMs(a));
|
|
111432
111651
|
const sorted2 = visible.slice(0, Math.max(1, WALLET_TRANSFER_CACHE_LIMIT)).map(jsonClean);
|
|
111433
111652
|
const capped = sorted2.length < visible.length;
|
|
111653
|
+
const knownHistoryCount = Math.max(sorted2.length, Math.floor(Number(historyCount) || 0));
|
|
111654
|
+
const complete = serverEndReached === true && !capped && sorted2.length >= knownHistoryCount;
|
|
111434
111655
|
const fullPayload = {
|
|
111435
111656
|
version: CACHE_VERSION,
|
|
111436
111657
|
walletPK: nextWalletPK,
|
|
111437
|
-
serverEndReached:
|
|
111438
|
-
historyCount:
|
|
111658
|
+
serverEndReached: complete,
|
|
111659
|
+
historyCount: knownHistoryCount,
|
|
111439
111660
|
nextOffset: Number.isFinite(nextOffset) ? nextOffset : sorted2.length,
|
|
111440
|
-
oldestTxMs:
|
|
111661
|
+
oldestTxMs: complete && Number.isFinite(oldestTxMs) ? oldestTxMs : null,
|
|
111441
111662
|
savedAt: Date.now(),
|
|
111442
111663
|
transfers: sorted2
|
|
111443
111664
|
};
|
|
@@ -111446,7 +111667,24 @@ function writeCachedTransferState(cache, { transfers, walletPK = null, serverEnd
|
|
|
111446
111667
|
...fullPayload,
|
|
111447
111668
|
transfers: headTransfers
|
|
111448
111669
|
};
|
|
111449
|
-
return
|
|
111670
|
+
return { fullPayload, headPayload };
|
|
111671
|
+
}
|
|
111672
|
+
function writeCachedTransferHeadState(cache, state = {}) {
|
|
111673
|
+
if (!cache) {
|
|
111674
|
+
return Promise.resolve(false);
|
|
111675
|
+
}
|
|
111676
|
+
const payloads = cachedTransferPayloads(state);
|
|
111677
|
+
return payloads ? cache.writePart(TX_HEAD_PART, payloads.headPayload) : Promise.resolve(false);
|
|
111678
|
+
}
|
|
111679
|
+
function writeCachedTransferState(cache, state = {}) {
|
|
111680
|
+
if (!cache) {
|
|
111681
|
+
return Promise.resolve(false);
|
|
111682
|
+
}
|
|
111683
|
+
const payloads = cachedTransferPayloads(state);
|
|
111684
|
+
if (!payloads) {
|
|
111685
|
+
return Promise.resolve(false);
|
|
111686
|
+
}
|
|
111687
|
+
return Promise.all([cache.writePart(TX_HEAD_PART, payloads.headPayload), cache.writePart(TX_PART, payloads.fullPayload)]).then((results) => results.some(Boolean));
|
|
111450
111688
|
}
|
|
111451
111689
|
var TX_PART = "wallet-transfers", TX_HEAD_PART = "wallet-transfers-head", CACHE_VERSION = 2, CACHE_HEAD_LIMIT;
|
|
111452
111690
|
var init_transfers = __esm(() => {
|
|
@@ -111470,8 +111708,14 @@ function mediaAad(uid, network, id) {
|
|
|
111470
111708
|
function partAad(uid, network, part) {
|
|
111471
111709
|
return encoder.encode(JSON.stringify(["veyl-local-cache-part", CACHE_PART_ENVELOPE_VERSION, String(uid || ""), String(network || ""), String(part || "")]));
|
|
111472
111710
|
}
|
|
111711
|
+
function encodePayloadData(payload) {
|
|
111712
|
+
return encoder.encode(JSON.stringify({ ...normalizePayload(payload), savedAt: Date.now() }));
|
|
111713
|
+
}
|
|
111714
|
+
function decodePayloadData(raw) {
|
|
111715
|
+
return JSON.parse(decoder.decode(toBytes2(raw, "cache payload")));
|
|
111716
|
+
}
|
|
111473
111717
|
async function sealPayload(key, payload, uid, network) {
|
|
111474
|
-
const body =
|
|
111718
|
+
const body = encodePayloadData(payload);
|
|
111475
111719
|
try {
|
|
111476
111720
|
const { iv, ct } = await sealAes(key, body, cacheAad(uid, network));
|
|
111477
111721
|
return JSON.stringify({
|
|
@@ -111493,7 +111737,7 @@ async function openPayloadData(key, raw, uid, network) {
|
|
|
111493
111737
|
}
|
|
111494
111738
|
const plain = await openAes(key, fromHexBytes(envelope.iv, "cache iv"), fromHexBytes(envelope.ct, "cache ciphertext"), cacheAad(uid, network));
|
|
111495
111739
|
try {
|
|
111496
|
-
return
|
|
111740
|
+
return decodePayloadData(plain);
|
|
111497
111741
|
} finally {
|
|
111498
111742
|
cleanBytes(plain);
|
|
111499
111743
|
}
|
|
@@ -111554,6 +111798,14 @@ function mediaCrypto(uid, network, id, keyBytes) {
|
|
|
111554
111798
|
ivBytes: AES_IV_BYTES
|
|
111555
111799
|
};
|
|
111556
111800
|
}
|
|
111801
|
+
function payloadCrypto(uid, network, keyBytes) {
|
|
111802
|
+
return {
|
|
111803
|
+
key: keyBytes,
|
|
111804
|
+
aad: cacheAad(uid, network),
|
|
111805
|
+
version: LOCAL_DATA_CACHE_VERSION,
|
|
111806
|
+
ivBytes: AES_IV_BYTES
|
|
111807
|
+
};
|
|
111808
|
+
}
|
|
111557
111809
|
var MEDIA_ENVELOPE_VERSION = 1, CACHE_PART_ENVELOPE_VERSION = 1;
|
|
111558
111810
|
var init_crypto = __esm(() => {
|
|
111559
111811
|
init_aes2();
|
|
@@ -111589,11 +111841,32 @@ async function openVaultCache({ key, storage, uid, network }) {
|
|
|
111589
111841
|
let writeTimer = null;
|
|
111590
111842
|
let writeTask = Promise.resolve();
|
|
111591
111843
|
const partWriteTasks = new Map;
|
|
111844
|
+
let storedPayload = null;
|
|
111592
111845
|
try {
|
|
111593
|
-
|
|
111594
|
-
|
|
111846
|
+
storedPayload = await storage.read();
|
|
111847
|
+
if (!storedPayload) {
|
|
111848
|
+
payload = emptyPayload();
|
|
111849
|
+
} else if (typeof storage.openPayload === "function") {
|
|
111850
|
+
const readKey = new Uint8Array(cacheKey);
|
|
111851
|
+
let plain;
|
|
111852
|
+
try {
|
|
111853
|
+
plain = await storage.openPayload(storedPayload, payloadCrypto(uid, network, readKey));
|
|
111854
|
+
payload = normalizePayload(decodePayloadData(plain));
|
|
111855
|
+
} finally {
|
|
111856
|
+
cleanBytes(plain, readKey);
|
|
111857
|
+
}
|
|
111858
|
+
} else {
|
|
111859
|
+
payload = normalizePayload(await openPayloadData(cacheKey, storedPayload, uid, network));
|
|
111860
|
+
}
|
|
111595
111861
|
} catch {
|
|
111596
111862
|
payload = emptyPayload();
|
|
111863
|
+
if (storedPayload) {
|
|
111864
|
+
await Promise.all([
|
|
111865
|
+
storage.remove().catch(() => {}),
|
|
111866
|
+
storage.removeAllMedia().catch(() => {}),
|
|
111867
|
+
storage.removeAllParts().catch(() => {})
|
|
111868
|
+
]);
|
|
111869
|
+
}
|
|
111597
111870
|
}
|
|
111598
111871
|
const writeNow = () => {
|
|
111599
111872
|
if (closed) {
|
|
@@ -111611,10 +111884,12 @@ async function openVaultCache({ key, storage, uid, network }) {
|
|
|
111611
111884
|
return;
|
|
111612
111885
|
}
|
|
111613
111886
|
const writeKey = new Uint8Array(cacheKey);
|
|
111887
|
+
let body;
|
|
111614
111888
|
try {
|
|
111615
|
-
await storage.
|
|
111889
|
+
const raw = typeof storage.sealPayload === "function" ? await storage.sealPayload(body = encodePayloadData(payload), payloadCrypto(uid, network, writeKey)) : await sealPayload(writeKey, payload, uid, network);
|
|
111890
|
+
await storage.write(raw);
|
|
111616
111891
|
} finally {
|
|
111617
|
-
cleanBytes(writeKey);
|
|
111892
|
+
cleanBytes(body, writeKey);
|
|
111618
111893
|
}
|
|
111619
111894
|
}).catch(() => {});
|
|
111620
111895
|
return writeTask;
|
|
@@ -111885,6 +112160,7 @@ var init_vault2 = __esm(() => {
|
|
|
111885
112160
|
// ../../shared/cache/localdata.js
|
|
111886
112161
|
var init_localdata = __esm(() => {
|
|
111887
112162
|
init_chats2();
|
|
112163
|
+
init_balance();
|
|
111888
112164
|
init_media();
|
|
111889
112165
|
init_messages2();
|
|
111890
112166
|
init_profiles();
|
|
@@ -111962,7 +112238,8 @@ function makeOwnChatEntry(pair, fields = {}) {
|
|
|
111962
112238
|
preview: fields.preview || null,
|
|
111963
112239
|
saved: fields.saved || null,
|
|
111964
112240
|
readMs: Number.isFinite(fields.readMs) ? fields.readMs : null,
|
|
111965
|
-
startMs: Number.isFinite(fields.startMs) ? fields.startMs : null
|
|
112241
|
+
startMs: Number.isFinite(fields.startMs) ? fields.startMs : null,
|
|
112242
|
+
signerShared: fields.signerShared === true
|
|
111966
112243
|
};
|
|
111967
112244
|
}
|
|
111968
112245
|
var CHAT_ENTRY_VERSION = 1;
|
|
@@ -112417,9 +112694,9 @@ function setErrorStage(error, stage, extra = {}) {
|
|
|
112417
112694
|
Object.assign(error, extra);
|
|
112418
112695
|
return error;
|
|
112419
112696
|
}
|
|
112420
|
-
async function makeChatFileUpload(
|
|
112697
|
+
async function makeChatFileUpload(chatId, cid, data, { cacheControl = "private, max-age=0, no-transform" } = {}) {
|
|
112421
112698
|
try {
|
|
112422
|
-
return await makeChatFileUploadPayload(
|
|
112699
|
+
return await makeChatFileUploadPayload(chatId, cid, data, {
|
|
112423
112700
|
cacheControl
|
|
112424
112701
|
});
|
|
112425
112702
|
} catch (error) {
|
|
@@ -112429,8 +112706,8 @@ async function makeChatFileUpload(pair, cid, data, { cacheControl = "private, ma
|
|
|
112429
112706
|
});
|
|
112430
112707
|
}
|
|
112431
112708
|
}
|
|
112432
|
-
async function putChatFile(
|
|
112433
|
-
const upload = await makeChatFileUpload(
|
|
112709
|
+
async function putChatFile(chatId, cid, data, options) {
|
|
112710
|
+
const upload = await makeChatFileUpload(chatId, cid, data, options);
|
|
112434
112711
|
try {
|
|
112435
112712
|
if (typeof options?.uploadChatMedia !== "function") {
|
|
112436
112713
|
throw new Error("chat media upload required");
|
|
@@ -112465,7 +112742,7 @@ async function putSharedFile(data, options = {}) {
|
|
|
112465
112742
|
throw setErrorStage(error, "upload", { path: upload.path });
|
|
112466
112743
|
}
|
|
112467
112744
|
}
|
|
112468
|
-
async function readChatFile(readChatMedia,
|
|
112745
|
+
async function readChatFile(readChatMedia, file) {
|
|
112469
112746
|
let body;
|
|
112470
112747
|
try {
|
|
112471
112748
|
if (typeof readChatMedia !== "function") {
|
|
@@ -112523,8 +112800,8 @@ function buildAttachmentMsg(type, file) {
|
|
|
112523
112800
|
return makeAttachment(type, file);
|
|
112524
112801
|
}
|
|
112525
112802
|
}
|
|
112526
|
-
async function putAttachment(
|
|
112527
|
-
const file = await putChatFile(
|
|
112803
|
+
async function putAttachment(chatId, cid, type, data, meta = {}) {
|
|
112804
|
+
const file = await putChatFile(chatId, cid, data, meta);
|
|
112528
112805
|
return buildAttachmentMsg(type, {
|
|
112529
112806
|
...file,
|
|
112530
112807
|
...pickAttachmentMeta(meta)
|
|
@@ -112537,26 +112814,26 @@ async function putSharedAttachment(type, data, meta = {}) {
|
|
|
112537
112814
|
...pickAttachmentMeta(meta)
|
|
112538
112815
|
});
|
|
112539
112816
|
}
|
|
112540
|
-
async function putImg(
|
|
112541
|
-
return putAttachment(
|
|
112817
|
+
async function putImg(chatId, cid, data, meta = {}) {
|
|
112818
|
+
return putAttachment(chatId, cid, "img", data, meta);
|
|
112542
112819
|
}
|
|
112543
|
-
async function putGif(
|
|
112544
|
-
return putAttachment(
|
|
112820
|
+
async function putGif(chatId, cid, data, meta = {}) {
|
|
112821
|
+
return putAttachment(chatId, cid, "gif", data, meta);
|
|
112545
112822
|
}
|
|
112546
|
-
async function putM4a(
|
|
112547
|
-
return putAttachment(
|
|
112823
|
+
async function putM4a(chatId, cid, data, meta = {}) {
|
|
112824
|
+
return putAttachment(chatId, cid, "m4a", data, meta);
|
|
112548
112825
|
}
|
|
112549
|
-
async function putMp4(
|
|
112550
|
-
return putAttachment(
|
|
112826
|
+
async function putMp4(chatId, cid, data, meta = {}) {
|
|
112827
|
+
return putAttachment(chatId, cid, "mp4", data, meta);
|
|
112551
112828
|
}
|
|
112552
|
-
async function putFile(
|
|
112553
|
-
return putAttachment(
|
|
112829
|
+
async function putFile(chatId, cid, data, meta = {}) {
|
|
112830
|
+
return putAttachment(chatId, cid, "file", data, meta);
|
|
112554
112831
|
}
|
|
112555
|
-
function readMsgAttachment(readChatMedia,
|
|
112556
|
-
return readChatFile(readChatMedia,
|
|
112832
|
+
function readMsgAttachment(readChatMedia, msg) {
|
|
112833
|
+
return readChatFile(readChatMedia, msg);
|
|
112557
112834
|
}
|
|
112558
|
-
function readMsgFile(readChatMedia,
|
|
112559
|
-
return readMsgAttachment(readChatMedia,
|
|
112835
|
+
function readMsgFile(readChatMedia, msg) {
|
|
112836
|
+
return readMsgAttachment(readChatMedia, msg);
|
|
112560
112837
|
}
|
|
112561
112838
|
var init_media2 = __esm(() => {
|
|
112562
112839
|
init_files2();
|
|
@@ -112727,7 +113004,25 @@ async function setChatRead(cloud, uid, chatPrivKey, chatId, readMs, options = {}
|
|
|
112727
113004
|
body: await sealOwnChatEntry(chatPrivKey, entryId, {
|
|
112728
113005
|
...entry,
|
|
112729
113006
|
readMs: Math.max(currentReadMs, nextReadMs),
|
|
112730
|
-
...hasPreviewPatch ? { preview: preview2 || null } : {}
|
|
113007
|
+
...hasPreviewPatch ? { preview: preview2 || null } : {},
|
|
113008
|
+
...options.signerShared === true ? { signerShared: true } : {}
|
|
113009
|
+
})
|
|
113010
|
+
});
|
|
113011
|
+
return true;
|
|
113012
|
+
}
|
|
113013
|
+
async function setChatSignerShared(cloud, uid, chatPrivKey, chatId) {
|
|
113014
|
+
if (!cloud || !uid || !chatPrivKey || !chatId) {
|
|
113015
|
+
return false;
|
|
113016
|
+
}
|
|
113017
|
+
const entryId = ownChatEntryId(chatPrivKey, chatId);
|
|
113018
|
+
const entry = await readOwnEntry(cloud, uid, chatPrivKey, entryId);
|
|
113019
|
+
if (!entry?.chatId || entry.signerShared === true) {
|
|
113020
|
+
return entry?.signerShared === true;
|
|
113021
|
+
}
|
|
113022
|
+
await cloud.user.chats.write(uid, entryId, {
|
|
113023
|
+
body: await sealOwnChatEntry(chatPrivKey, entryId, {
|
|
113024
|
+
...entry,
|
|
113025
|
+
signerShared: true
|
|
112731
113026
|
})
|
|
112732
113027
|
});
|
|
112733
113028
|
return true;
|
|
@@ -112770,7 +113065,8 @@ async function ownEntryWrite(cloud, uid, chatPrivKey, pair, fields = {}) {
|
|
|
112770
113065
|
preview: fields.preview || existing?.preview,
|
|
112771
113066
|
saved: existing?.saved || null,
|
|
112772
113067
|
readMs: existing?.readMs,
|
|
112773
|
-
startMs: existing?.startMs
|
|
113068
|
+
startMs: existing?.startMs,
|
|
113069
|
+
signerShared: fields.signerShared === true || existing?.signerShared === true
|
|
112774
113070
|
});
|
|
112775
113071
|
const tsMs = timestampMs(fields.ts, null);
|
|
112776
113072
|
return {
|
|
@@ -112805,14 +113101,6 @@ function ownerEditedPreview(senderPubkey, message) {
|
|
|
112805
113101
|
failed: false
|
|
112806
113102
|
};
|
|
112807
113103
|
}
|
|
112808
|
-
function messageFileChatId(message) {
|
|
112809
|
-
try {
|
|
112810
|
-
const ref = getMediaFileRef(message?.p);
|
|
112811
|
-
return ref?.type === "chat" ? ref.chatId : "";
|
|
112812
|
-
} catch {
|
|
112813
|
-
return "";
|
|
112814
|
-
}
|
|
112815
|
-
}
|
|
112816
113104
|
async function recipientForSend(cloud, receiverChatPK, options, needed) {
|
|
112817
113105
|
if (!needed) {
|
|
112818
113106
|
return null;
|
|
@@ -112833,50 +113121,63 @@ async function sendMsg(cloud, senderPubkey, senderPrivkey, receiverChatPK, messa
|
|
|
112833
113121
|
if (!chatId) {
|
|
112834
113122
|
throw new Error("chat id required");
|
|
112835
113123
|
}
|
|
112836
|
-
|
|
112837
|
-
|
|
112838
|
-
|
|
112839
|
-
|
|
112840
|
-
|
|
112841
|
-
|
|
112842
|
-
|
|
112843
|
-
|
|
112844
|
-
|
|
112845
|
-
|
|
112846
|
-
|
|
112847
|
-
|
|
112848
|
-
|
|
112849
|
-
|
|
112850
|
-
|
|
112851
|
-
|
|
112852
|
-
|
|
112853
|
-
|
|
112854
|
-
|
|
112855
|
-
|
|
112856
|
-
|
|
112857
|
-
|
|
112858
|
-
|
|
112859
|
-
|
|
112860
|
-
|
|
112861
|
-
|
|
112862
|
-
|
|
112863
|
-
|
|
112864
|
-
|
|
112865
|
-
|
|
112866
|
-
|
|
112867
|
-
|
|
112868
|
-
|
|
112869
|
-
|
|
112870
|
-
|
|
112871
|
-
|
|
112872
|
-
|
|
112873
|
-
|
|
112874
|
-
|
|
112875
|
-
|
|
112876
|
-
|
|
112877
|
-
|
|
113124
|
+
return withCachedPair(senderPubkey, senderPrivkey, receiverChatPK, { chatId }, async (pair) => {
|
|
113125
|
+
if (options?.linkId && cleanText(options.linkId) !== pair.linkId) {
|
|
113126
|
+
throw new Error("link mismatch");
|
|
113127
|
+
}
|
|
113128
|
+
const retention = cleanChatRetention(options?.retention ?? options?.ttlMode);
|
|
113129
|
+
const tsMs = Date.now();
|
|
113130
|
+
const messagePayload = withMessageRetention(message, retention);
|
|
113131
|
+
const actionOp = actionOpForPayload(messagePayload);
|
|
113132
|
+
const { head, body } = await sealMsg(pair, messagePayload, { op: actionOp, ts: tsMs });
|
|
113133
|
+
const ttlMs = actionOp === CHAT_ACTION_OPS.CREATE ? newStorageTtlMs() : null;
|
|
113134
|
+
const messageId = head.cid;
|
|
113135
|
+
const msgData = {
|
|
113136
|
+
head,
|
|
113137
|
+
body,
|
|
113138
|
+
ttlMs
|
|
113139
|
+
};
|
|
113140
|
+
const recipientProfile = await recipientForSend(cloud, receiverChatPK, options, updatePreview || options?.ping === true);
|
|
113141
|
+
const sentMessage = ownerPreview(senderPubkey, messagePayload, messageId, head, tsMs, ttlMs);
|
|
113142
|
+
const preview2 = updatePreview ? sentMessage : null;
|
|
113143
|
+
const ownerEntry = updatePreview ? await ownEntryWrite(cloud, cleanText(options?.senderUid), senderPrivkey, pair, {
|
|
113144
|
+
peerUid: recipientProfile?.uid || cleanText(options?.receiverUid),
|
|
113145
|
+
peerSigningPublicKey: recipientProfile?.signingPublicKey,
|
|
113146
|
+
entry: options?.ownEntry,
|
|
113147
|
+
settings: options?.chatSettings,
|
|
113148
|
+
preview: preview2,
|
|
113149
|
+
ts: tsMs
|
|
113150
|
+
}) : null;
|
|
113151
|
+
const pingKind = updatePreview ? "message" : cleanText(options?.pingKind) || "ping";
|
|
113152
|
+
const ping = recipientProfile?.uid && (updatePreview || options?.ping === true) ? await sealPing(senderPubkey, senderPrivkey, receiverChatPK, {
|
|
113153
|
+
kind: pingKind,
|
|
113154
|
+
chatId,
|
|
113155
|
+
senderUid: cleanText(options?.senderUid),
|
|
113156
|
+
messageId,
|
|
113157
|
+
ts: tsMs
|
|
113158
|
+
}) : null;
|
|
113159
|
+
const write = await cloud.chat.messages.send({
|
|
113160
|
+
chatId,
|
|
113161
|
+
messageId,
|
|
113162
|
+
message: msgData,
|
|
113163
|
+
ownerEntry,
|
|
113164
|
+
inbox: ping ? { recipientUid: recipientProfile?.uid, ping, notify: options?.notify !== false } : null,
|
|
113165
|
+
onCommitted: typeof options?.onCommitted === "function" ? (committed) => options.onCommitted({ ...committed, message: sentMessage, preview: preview2 }) : undefined
|
|
113166
|
+
});
|
|
113167
|
+
const delivered = options?.ping === true ? !!ping && write?.delivered !== false : write?.delivered !== false;
|
|
113168
|
+
if (ping && delivered && ownerEntry && options?.ownEntry?.signerShared !== true) {
|
|
113169
|
+
await setChatSignerShared(cloud, cleanText(options?.senderUid), senderPrivkey, chatId).catch(() => false);
|
|
113170
|
+
}
|
|
113171
|
+
return {
|
|
113172
|
+
chatId,
|
|
113173
|
+
msgId: messageId,
|
|
113174
|
+
cid: head.cid,
|
|
113175
|
+
message: sentMessage,
|
|
113176
|
+
preview: preview2,
|
|
113177
|
+
delivered,
|
|
113178
|
+
...write?.skipped ? { skipped: true } : {}
|
|
113179
|
+
};
|
|
112878
113180
|
});
|
|
112879
|
-
return { chatId, msgId: messageId, cid: head.cid, message: sentMessage, preview: preview2, ...write?.skipped ? { skipped: true } : {} };
|
|
112880
113181
|
}
|
|
112881
113182
|
async function sendReadReceipt(cloud, senderPubkey, senderPrivkey, receiverChatPK, target, options = {}) {
|
|
112882
113183
|
const receipt = {
|
|
@@ -112884,7 +113185,13 @@ async function sendReadReceipt(cloud, senderPubkey, senderPrivkey, receiverChatP
|
|
|
112884
113185
|
cid: makeCid(),
|
|
112885
113186
|
s: senderPubkey
|
|
112886
113187
|
};
|
|
112887
|
-
return sendMsg(cloud, senderPubkey, senderPrivkey, receiverChatPK, receipt, {
|
|
113188
|
+
return sendMsg(cloud, senderPubkey, senderPrivkey, receiverChatPK, receipt, {
|
|
113189
|
+
...options,
|
|
113190
|
+
updatePreview: false,
|
|
113191
|
+
ping: options?.ping === true,
|
|
113192
|
+
pingKind: "read",
|
|
113193
|
+
notify: false
|
|
113194
|
+
});
|
|
112888
113195
|
}
|
|
112889
113196
|
async function sendReaction(cloud, senderPubkey, senderPrivkey, receiverChatPK, target, emoji, options = {}) {
|
|
112890
113197
|
const reaction = {
|
|
@@ -112986,27 +113293,28 @@ async function setChatRetention(cloud, chatId, senderPubkey, senderPrivkey, peer
|
|
|
112986
113293
|
throw new Error("vault locked");
|
|
112987
113294
|
}
|
|
112988
113295
|
const nextRetention = cleanChatRetention(retention);
|
|
112989
|
-
|
|
112990
|
-
|
|
112991
|
-
|
|
112992
|
-
|
|
112993
|
-
|
|
112994
|
-
|
|
112995
|
-
|
|
112996
|
-
|
|
112997
|
-
|
|
112998
|
-
|
|
112999
|
-
|
|
113000
|
-
|
|
113001
|
-
|
|
113002
|
-
|
|
113003
|
-
|
|
113004
|
-
|
|
113005
|
-
|
|
113006
|
-
|
|
113007
|
-
|
|
113296
|
+
return withCachedPair(senderPubkey, senderPrivkey, peerChatPK, { chatId }, async (pair) => {
|
|
113297
|
+
if (chatId && pair.chatId !== chatId) {
|
|
113298
|
+
throw new Error("chat mismatch");
|
|
113299
|
+
}
|
|
113300
|
+
const systemMessage = {
|
|
113301
|
+
...makeRetentionSystemMsg(nextRetention),
|
|
113302
|
+
cid: cleanText(options?.cid) || makeCid(),
|
|
113303
|
+
s: senderPubkey
|
|
113304
|
+
};
|
|
113305
|
+
await sendMsg(cloud, senderPubkey, senderPrivkey, peerChatPK, systemMessage, {
|
|
113306
|
+
chatId,
|
|
113307
|
+
linkId: pair.linkId,
|
|
113308
|
+
updatePreview: true,
|
|
113309
|
+
retention: nextRetention,
|
|
113310
|
+
chatExists: true,
|
|
113311
|
+
senderUid: options?.senderUid,
|
|
113312
|
+
ownEntry: options?.ownEntry,
|
|
113313
|
+
chatSettings: { retention: nextRetention },
|
|
113314
|
+
onCommitted: options?.onCommitted
|
|
113315
|
+
});
|
|
113316
|
+
return nextRetention;
|
|
113008
113317
|
});
|
|
113009
|
-
return nextRetention;
|
|
113010
113318
|
}
|
|
113011
113319
|
async function uploadAttachmentMsg(_cloud, senderPubkey, senderPrivkey, receiverChatPK, attachment = {}) {
|
|
113012
113320
|
if (!senderPrivkey || !senderPubkey) {
|
|
@@ -113020,95 +113328,96 @@ async function uploadAttachmentMsg(_cloud, senderPubkey, senderPrivkey, receiver
|
|
|
113020
113328
|
if (!chatId) {
|
|
113021
113329
|
throw new Error("chat id required");
|
|
113022
113330
|
}
|
|
113023
|
-
const pair = await getCachedPair(senderPubkey, senderPrivkey, receiverChatPK, { chatId });
|
|
113024
113331
|
const type = cleanText(attachment?.type) || "file";
|
|
113025
113332
|
const data = attachment?.data;
|
|
113026
113333
|
const meta = attachment?.meta || {};
|
|
113027
113334
|
switch (type) {
|
|
113028
113335
|
case "img":
|
|
113029
|
-
return putImg(
|
|
113336
|
+
return putImg(chatId, nextCid, data, meta);
|
|
113030
113337
|
case "gif":
|
|
113031
|
-
return putGif(
|
|
113338
|
+
return putGif(chatId, nextCid, data, meta);
|
|
113032
113339
|
case "m4a":
|
|
113033
|
-
return putM4a(
|
|
113340
|
+
return putM4a(chatId, nextCid, data, meta);
|
|
113034
113341
|
case "mp4":
|
|
113035
|
-
return putMp4(
|
|
113342
|
+
return putMp4(chatId, nextCid, data, meta);
|
|
113036
113343
|
case "file":
|
|
113037
|
-
return putFile(
|
|
113344
|
+
return putFile(chatId, nextCid, data, meta);
|
|
113038
113345
|
default:
|
|
113039
|
-
return putAttachment(
|
|
113346
|
+
return putAttachment(chatId, nextCid, type, data, meta);
|
|
113040
113347
|
}
|
|
113041
113348
|
}
|
|
113042
113349
|
async function updateMsg(cloud, chatId, msgId, senderPubkey, senderPrivkey, receiverChatPK, newMessage, options = {}) {
|
|
113043
113350
|
if (!senderPubkey || !senderPrivkey)
|
|
113044
113351
|
throw new Error("vault locked");
|
|
113045
|
-
|
|
113046
|
-
|
|
113047
|
-
|
|
113048
|
-
|
|
113049
|
-
|
|
113050
|
-
|
|
113051
|
-
|
|
113052
|
-
|
|
113053
|
-
|
|
113054
|
-
|
|
113055
|
-
|
|
113056
|
-
|
|
113057
|
-
|
|
113058
|
-
|
|
113059
|
-
|
|
113060
|
-
|
|
113061
|
-
|
|
113062
|
-
|
|
113063
|
-
|
|
113064
|
-
|
|
113065
|
-
|
|
113066
|
-
|
|
113067
|
-
|
|
113068
|
-
|
|
113069
|
-
|
|
113070
|
-
|
|
113071
|
-
|
|
113072
|
-
|
|
113073
|
-
|
|
113074
|
-
|
|
113075
|
-
|
|
113076
|
-
|
|
113077
|
-
|
|
113078
|
-
|
|
113079
|
-
|
|
113080
|
-
|
|
113352
|
+
return withCachedPair(senderPubkey, senderPrivkey, receiverChatPK, { chatId }, async (pair) => {
|
|
113353
|
+
if (pair.chatId !== chatId) {
|
|
113354
|
+
throw new Error("chat mismatch");
|
|
113355
|
+
}
|
|
113356
|
+
const target = cleanText(newMessage?.cid) || cleanText(msgId);
|
|
113357
|
+
if (!target) {
|
|
113358
|
+
throw new Error("message target required");
|
|
113359
|
+
}
|
|
113360
|
+
const op = newMessage?.t === "req" && cleanText(newMessage?.tx) ? CHAT_ACTION_OPS.PAY_CONFIRM : CHAT_ACTION_OPS.EDIT;
|
|
113361
|
+
const tsMs = Date.now();
|
|
113362
|
+
const action = {
|
|
113363
|
+
...newMessage || {},
|
|
113364
|
+
cid: makeCid(),
|
|
113365
|
+
s: senderPubkey
|
|
113366
|
+
};
|
|
113367
|
+
const { head, body } = await sealMsg(pair, action, { op, target, ts: tsMs });
|
|
113368
|
+
const messageId = head.cid;
|
|
113369
|
+
const updatePreview = options?.updatePreview === true;
|
|
113370
|
+
const preview2 = updatePreview ? ownerEditedPreview(senderPubkey, newMessage) : null;
|
|
113371
|
+
const ownerEntry = updatePreview ? await ownEntryWrite(cloud, cleanText(options?.senderUid), senderPrivkey, pair, {
|
|
113372
|
+
peerUid: cleanText(options?.receiverUid),
|
|
113373
|
+
peerSigningPublicKey: cleanText(options?.peerSigningPublicKey),
|
|
113374
|
+
entry: options?.ownEntry,
|
|
113375
|
+
preview: preview2,
|
|
113376
|
+
ts: preview2?.ts ?? tsMs
|
|
113377
|
+
}) : null;
|
|
113378
|
+
await cloud.chat.messages.send({
|
|
113379
|
+
chatId,
|
|
113380
|
+
messageId,
|
|
113381
|
+
message: {
|
|
113382
|
+
head,
|
|
113383
|
+
body,
|
|
113384
|
+
ttlMs: null
|
|
113385
|
+
},
|
|
113386
|
+
ownerEntry,
|
|
113387
|
+
inbox: null
|
|
113388
|
+
});
|
|
113389
|
+
return {
|
|
113390
|
+
chatId,
|
|
113391
|
+
msgId: messageId,
|
|
113392
|
+
cid: head.cid,
|
|
113393
|
+
preview: preview2
|
|
113394
|
+
};
|
|
113081
113395
|
});
|
|
113082
|
-
return {
|
|
113083
|
-
chatId,
|
|
113084
|
-
msgId: messageId,
|
|
113085
|
-
cid: head.cid,
|
|
113086
|
-
preview: preview2
|
|
113087
|
-
};
|
|
113088
113396
|
}
|
|
113089
113397
|
async function deleteMsg(cloud, chatId, messageOrId, senderPubkey, senderPrivkey, peerChatPK, options = {}) {
|
|
113090
113398
|
if (!cloud || !chatId || !messageOrId || !senderPubkey || !senderPrivkey || !peerChatPK) {
|
|
113091
113399
|
return false;
|
|
113092
113400
|
}
|
|
113093
|
-
|
|
113094
|
-
|
|
113095
|
-
|
|
113096
|
-
|
|
113097
|
-
|
|
113098
|
-
|
|
113099
|
-
|
|
113100
|
-
|
|
113101
|
-
|
|
113102
|
-
|
|
113103
|
-
|
|
113104
|
-
|
|
113105
|
-
|
|
113106
|
-
|
|
113107
|
-
|
|
113108
|
-
|
|
113109
|
-
|
|
113401
|
+
return withCachedPair(senderPubkey, senderPrivkey, peerChatPK, { chatId }, async (pair) => {
|
|
113402
|
+
if (pair.chatId !== chatId) {
|
|
113403
|
+
return false;
|
|
113404
|
+
}
|
|
113405
|
+
const item = messageDeleteItems([messageOrId])[0];
|
|
113406
|
+
const target = cleanText(options?.docId) || cleanText(item?.id);
|
|
113407
|
+
if (!target || target.startsWith("local:")) {
|
|
113408
|
+
return false;
|
|
113409
|
+
}
|
|
113410
|
+
const deleteTarget = cleanText(options?.target) || cleanText(getMessageKey(messageOrId)) || target;
|
|
113411
|
+
await sendDeleteAction(cloud, senderPubkey, senderPrivkey, peerChatPK, deleteTarget, {
|
|
113412
|
+
chatId,
|
|
113413
|
+
linkId: options?.linkId,
|
|
113414
|
+
senderUid: options?.senderUid
|
|
113415
|
+
});
|
|
113416
|
+
await cloud.chat.messages.delete(chatId, target, {
|
|
113417
|
+
mediaPaths: item?.mediaPath ? [item.mediaPath] : []
|
|
113418
|
+
});
|
|
113419
|
+
return true;
|
|
113110
113420
|
});
|
|
113111
|
-
return true;
|
|
113112
113421
|
}
|
|
113113
113422
|
async function deleteMsgs(cloud, chatId, messages, senderPubkey, senderPrivkey, peerChatPK) {
|
|
113114
113423
|
if (!cloud || !chatId || !senderPubkey || !senderPrivkey || !peerChatPK) {
|
|
@@ -113118,31 +113427,31 @@ async function deleteMsgs(cloud, chatId, messages, senderPubkey, senderPrivkey,
|
|
|
113118
113427
|
if (!items.length) {
|
|
113119
113428
|
return 0;
|
|
113120
113429
|
}
|
|
113121
|
-
|
|
113122
|
-
|
|
113123
|
-
|
|
113124
|
-
|
|
113125
|
-
|
|
113126
|
-
|
|
113127
|
-
|
|
113128
|
-
|
|
113129
|
-
|
|
113130
|
-
|
|
113131
|
-
|
|
113132
|
-
|
|
113430
|
+
return withCachedPair(senderPubkey, senderPrivkey, peerChatPK, { chatId }, async (pair) => {
|
|
113431
|
+
if (pair.chatId !== chatId) {
|
|
113432
|
+
return 0;
|
|
113433
|
+
}
|
|
113434
|
+
let deleted = 0;
|
|
113435
|
+
for (let index = 0;index < items.length; index += DELETE_WRITE_BATCH_SIZE) {
|
|
113436
|
+
const chunk = items.slice(index, index + DELETE_WRITE_BATCH_SIZE);
|
|
113437
|
+
const targets = chunk.map((item) => cleanText(item.id)).filter((target) => target && !target.startsWith("local:"));
|
|
113438
|
+
const mediaPaths = chunk.map((item) => cleanText(item.mediaPath)).filter(Boolean);
|
|
113439
|
+
deleted += await cloud.chat.messages.deleteMany(chatId, targets, { mediaPaths });
|
|
113440
|
+
}
|
|
113441
|
+
return deleted;
|
|
113442
|
+
});
|
|
113133
113443
|
}
|
|
113134
|
-
async function readMsgMedia(readChatMedia,
|
|
113135
|
-
return readMsgAttachment2(readChatMedia,
|
|
113444
|
+
async function readMsgMedia(readChatMedia, msg) {
|
|
113445
|
+
return readMsgAttachment2(readChatMedia, msg);
|
|
113136
113446
|
}
|
|
113137
|
-
async function readMsgAttachment2(readChatMedia,
|
|
113447
|
+
async function readMsgAttachment2(readChatMedia, msg) {
|
|
113138
113448
|
if (typeof readChatMedia !== "function") {
|
|
113139
113449
|
throw new Error("chat media read required");
|
|
113140
113450
|
}
|
|
113141
|
-
if (!
|
|
113451
|
+
if (!msg) {
|
|
113142
113452
|
return null;
|
|
113143
113453
|
}
|
|
113144
|
-
|
|
113145
|
-
return readMsgFile(readChatMedia, pair, msg);
|
|
113454
|
+
return readMsgFile(readChatMedia, msg);
|
|
113146
113455
|
}
|
|
113147
113456
|
var DELETE_WRITE_BATCH_SIZE;
|
|
113148
113457
|
var init_write = __esm(() => {
|
|
@@ -113385,14 +113694,14 @@ function hasInvalidStoredMediaRef(message) {
|
|
|
113385
113694
|
return true;
|
|
113386
113695
|
}
|
|
113387
113696
|
}
|
|
113388
|
-
function readMessageMedia(cloud, media,
|
|
113697
|
+
function readMessageMedia(cloud, media, message) {
|
|
113389
113698
|
const readChatMedia = cloud?.chat?.media?.read;
|
|
113390
113699
|
if (typeof media?.readMessageFile === "function") {
|
|
113391
|
-
return media.readMessageFile(readChatMedia,
|
|
113700
|
+
return media.readMessageFile(readChatMedia, message);
|
|
113392
113701
|
}
|
|
113393
|
-
return readMsgMedia(readChatMedia,
|
|
113702
|
+
return readMsgMedia(readChatMedia, message);
|
|
113394
113703
|
}
|
|
113395
|
-
function createChatSave({ cloud, media = {}, chatBanned,
|
|
113704
|
+
function createChatSave({ cloud, media = {}, chatBanned, localCache }) {
|
|
113396
113705
|
const makeMessagePermanent = async (chatId, message) => {
|
|
113397
113706
|
if (chatBanned) {
|
|
113398
113707
|
throw makeChatUnavailableError();
|
|
@@ -113410,7 +113719,7 @@ function createChatSave({ cloud, media = {}, chatBanned, chatPK, chatPrivateKey,
|
|
|
113410
113719
|
const updated = await makeMsgTemporary(cloud, chatId, list, ttl);
|
|
113411
113720
|
return { updated, ttl };
|
|
113412
113721
|
};
|
|
113413
|
-
const readMessageFile = async (
|
|
113722
|
+
const readMessageFile = async (_peerChatPK, message) => {
|
|
113414
113723
|
if (chatBanned) {
|
|
113415
113724
|
throw makeChatUnavailableError();
|
|
113416
113725
|
}
|
|
@@ -113432,7 +113741,7 @@ function createChatSave({ cloud, media = {}, chatBanned, chatPK, chatPrivateKey,
|
|
|
113432
113741
|
throw makeFileGoneError();
|
|
113433
113742
|
}
|
|
113434
113743
|
try {
|
|
113435
|
-
const bytes = await readMessageMedia(cloud, media,
|
|
113744
|
+
const bytes = await readMessageMedia(cloud, media, message);
|
|
113436
113745
|
saveMedia(localCache, message, bytes, message);
|
|
113437
113746
|
return bytes;
|
|
113438
113747
|
} catch (error) {
|
|
@@ -113499,7 +113808,7 @@ function messageExpiryGroups(messages, selfChatPublicKey, seenAt) {
|
|
|
113499
113808
|
{ messages: day, expiresAt: seenAt + AFTER_SEEN_MS }
|
|
113500
113809
|
].filter((group) => group.messages.length);
|
|
113501
113810
|
}
|
|
113502
|
-
function createChatSeen({ cloud, uid, chatBanned, chatPK, chatPrivateKey, localCache, pendingReadRef, readCacheRef, readWriteInterval, getChatRetention, setChats, diag }) {
|
|
113811
|
+
function createChatSeen({ cloud, uid, chatBanned, chatPK, chatPrivateKey, localCache, pendingReadRef, readCacheRef, readWriteInterval, getChatRetention, sendOptionsForPeer, setChats, diag }) {
|
|
113503
113812
|
const scheduleRead = (chatId, message, previewMs, sendReceipt, expiryMessages = []) => {
|
|
113504
113813
|
scheduleReadWrite({
|
|
113505
113814
|
pendingRead: pendingReadRef.current,
|
|
@@ -113510,24 +113819,37 @@ function createChatSeen({ cloud, uid, chatBanned, chatPK, chatPrivateKey, localC
|
|
|
113510
113819
|
expiryMessages: sendReceipt ? expiryMessages : [],
|
|
113511
113820
|
interval: readWriteInterval,
|
|
113512
113821
|
write: async (pending) => {
|
|
113822
|
+
let receiptError = null;
|
|
113823
|
+
let receiptResult = null;
|
|
113824
|
+
let introduceSigner = false;
|
|
113825
|
+
if (pending.receipt) {
|
|
113826
|
+
const sendOptions = sendOptionsForPeer(pending.receipt.peerChatPK);
|
|
113827
|
+
introduceSigner = sendOptions?.signerShared !== true;
|
|
113828
|
+
try {
|
|
113829
|
+
receiptResult = await sendReadReceipt(cloud, chatPK, chatPrivateKey, pending.receipt.peerChatPK, pending.receipt.target, {
|
|
113830
|
+
chatId,
|
|
113831
|
+
retention: getChatRetention(chatId),
|
|
113832
|
+
senderUid: uid,
|
|
113833
|
+
receiverUid: sendOptions?.receiverUid,
|
|
113834
|
+
ping: introduceSigner
|
|
113835
|
+
});
|
|
113836
|
+
} catch (error) {
|
|
113837
|
+
receiptError = error;
|
|
113838
|
+
}
|
|
113839
|
+
}
|
|
113513
113840
|
const writes = [
|
|
113514
113841
|
setChatRead(cloud, uid, chatPrivateKey, chatId, pending.previewMs, {
|
|
113515
|
-
preview: (currentPreview) => withChatPreviewOpened(currentPreview, pending.message, pending.previewMs, chatPK) || currentPreview
|
|
113842
|
+
preview: (currentPreview) => withChatPreviewOpened(currentPreview, pending.message, pending.previewMs, chatPK) || currentPreview,
|
|
113843
|
+
signerShared: introduceSigner && receiptResult?.delivered === true
|
|
113516
113844
|
})
|
|
113517
113845
|
];
|
|
113518
113846
|
if (pending.receipt) {
|
|
113519
|
-
writes.push(sendReadReceipt(cloud, chatPK, chatPrivateKey, pending.receipt.peerChatPK, pending.receipt.target, {
|
|
113520
|
-
chatId,
|
|
113521
|
-
retention: getChatRetention(chatId),
|
|
113522
|
-
senderUid: uid
|
|
113523
|
-
}));
|
|
113524
113847
|
for (const group of messageExpiryGroups(pending.expiryMessages, chatPK, pending.expirySeenAt)) {
|
|
113525
113848
|
writes.push(setMessageExpiry(cloud, chatId, group.messages, group.expiresAt));
|
|
113526
113849
|
}
|
|
113527
113850
|
}
|
|
113528
113851
|
const results = await Promise.allSettled(writes);
|
|
113529
113852
|
const ownerError = results[0]?.status === "rejected" ? results[0].reason : null;
|
|
113530
|
-
const receiptError = pending.receipt && results[1]?.status === "rejected" ? results[1].reason : null;
|
|
113531
113853
|
if (ownerError) {
|
|
113532
113854
|
markError(diag, "chat.read.state.write", Date.now(), ownerError);
|
|
113533
113855
|
}
|
|
@@ -113535,7 +113857,7 @@ function createChatSeen({ cloud, uid, chatBanned, chatPK, chatPrivateKey, localC
|
|
|
113535
113857
|
readCacheRef.current.delete(chatId);
|
|
113536
113858
|
markError(diag, "chat.read.receipt.write", Date.now(), receiptError);
|
|
113537
113859
|
}
|
|
113538
|
-
for (const result of results.slice(
|
|
113860
|
+
for (const result of results.slice(1)) {
|
|
113539
113861
|
if (result?.status === "rejected") {
|
|
113540
113862
|
markError(diag, "chat.message.expiry.write", Date.now(), result.reason);
|
|
113541
113863
|
}
|
|
@@ -114078,8 +114400,11 @@ function withSharedMediaUpload(cloud, media, meta = {}) {
|
|
|
114078
114400
|
};
|
|
114079
114401
|
}
|
|
114080
114402
|
function uploadMessageAttachment(cloud, media, senderPubkey, senderPrivkey, receiverChatPK, attachment = {}) {
|
|
114403
|
+
if (!senderPubkey || !senderPrivkey) {
|
|
114404
|
+
throw new Error("vault locked");
|
|
114405
|
+
}
|
|
114081
114406
|
if (typeof media?.uploadAttachment === "function") {
|
|
114082
|
-
return media.uploadAttachment(
|
|
114407
|
+
return media.uploadAttachment(attachment);
|
|
114083
114408
|
}
|
|
114084
114409
|
return uploadAttachmentMsg(cloud, senderPubkey, senderPrivkey, receiverChatPK, withMediaUpload(cloud, media, attachment));
|
|
114085
114410
|
}
|
|
@@ -114377,17 +114702,21 @@ ${cid}` : "";
|
|
|
114377
114702
|
const requiredPreview = previewRequired || sendOptions.chatExists !== true;
|
|
114378
114703
|
let local = await showLocalMessage(peerChatPK, message, sendOptions);
|
|
114379
114704
|
let committed = false;
|
|
114705
|
+
let sent = false;
|
|
114706
|
+
const markSent = () => {
|
|
114707
|
+
if (sent)
|
|
114708
|
+
return;
|
|
114709
|
+
sent = true;
|
|
114710
|
+
sentChatIdsRef.current.add(local.chatId);
|
|
114711
|
+
markLocalStatus(local.chatId, local.cid, LOCAL_SENT);
|
|
114712
|
+
};
|
|
114380
114713
|
const markCommitted = () => {
|
|
114381
114714
|
if (committed)
|
|
114382
114715
|
return;
|
|
114383
114716
|
committed = true;
|
|
114384
|
-
|
|
114717
|
+
markSent();
|
|
114385
114718
|
markDone(diag, "chat.send.commit", startedAt, { type: local?.t || "txt", previewRequired: !!requiredPreview });
|
|
114386
114719
|
};
|
|
114387
|
-
const markSent = () => {
|
|
114388
|
-
sentChatIdsRef.current.add(local.chatId);
|
|
114389
|
-
markLocalStatus(local.chatId, local.cid, LOCAL_SENT);
|
|
114390
|
-
};
|
|
114391
114720
|
return await new Promise((resolve2, reject) => {
|
|
114392
114721
|
const job = {
|
|
114393
114722
|
previewKey: local.chatId,
|
|
@@ -114605,7 +114934,8 @@ ${cid}` : "";
|
|
|
114605
114934
|
linkId: local.linkId,
|
|
114606
114935
|
version: local.version,
|
|
114607
114936
|
sendOptions,
|
|
114608
|
-
nextAttachment: prepared.nextAttachment
|
|
114937
|
+
nextAttachment: prepared.nextAttachment,
|
|
114938
|
+
committed: false
|
|
114609
114939
|
};
|
|
114610
114940
|
}));
|
|
114611
114941
|
return await new Promise((resolve2, reject) => {
|
|
@@ -114614,7 +114944,9 @@ ${cid}` : "";
|
|
|
114614
114944
|
reject,
|
|
114615
114945
|
onError: () => {
|
|
114616
114946
|
for (const item of locals) {
|
|
114617
|
-
|
|
114947
|
+
if (!item.committed) {
|
|
114948
|
+
markLocalStatus(item.chatId, item.cid, LOCAL_FAILED);
|
|
114949
|
+
}
|
|
114618
114950
|
}
|
|
114619
114951
|
},
|
|
114620
114952
|
run: async () => {
|
|
@@ -114629,6 +114961,7 @@ ${cid}` : "";
|
|
|
114629
114961
|
results.push({ peerChatPK: item.peerChatPK, ok: false, error: uploadError });
|
|
114630
114962
|
continue;
|
|
114631
114963
|
}
|
|
114964
|
+
let sentMessage;
|
|
114632
114965
|
try {
|
|
114633
114966
|
let uploaded = uploads.get(uploadKey);
|
|
114634
114967
|
if (!uploaded) {
|
|
@@ -114641,17 +114974,32 @@ ${cid}` : "";
|
|
|
114641
114974
|
cid: item.cid,
|
|
114642
114975
|
s: chatPK
|
|
114643
114976
|
};
|
|
114644
|
-
|
|
114977
|
+
sentMessage = withMessageRetention(sent, item.sendOptions.retention);
|
|
114645
114978
|
rememberCachedLocalMedia(item.chatId, item.cid, sentMessage);
|
|
114646
|
-
await sendMsg(cloud, chatPK, chatPrivateKey, item.peerChatPK, sentMessage, {
|
|
114647
|
-
|
|
114979
|
+
await sendMsg(cloud, chatPK, chatPrivateKey, item.peerChatPK, sentMessage, {
|
|
114980
|
+
...item.sendOptions,
|
|
114981
|
+
chatId: item.chatId,
|
|
114982
|
+
linkId: item.linkId,
|
|
114983
|
+
senderUid: uid,
|
|
114984
|
+
onCommitted: () => {
|
|
114985
|
+
if (item.committed)
|
|
114986
|
+
return;
|
|
114987
|
+
item.committed = true;
|
|
114988
|
+
sentChatIdsRef.current.add(item.chatId);
|
|
114989
|
+
markLocalStatus(item.chatId, item.cid, LOCAL_SENT);
|
|
114990
|
+
}
|
|
114991
|
+
});
|
|
114648
114992
|
results.push({ peerChatPK: item.peerChatPK, ok: true, message: sentMessage });
|
|
114649
114993
|
} catch (error) {
|
|
114650
114994
|
if (!uploads.has(uploadKey)) {
|
|
114651
114995
|
uploadErrors.set(uploadKey, error);
|
|
114652
114996
|
}
|
|
114653
|
-
|
|
114654
|
-
|
|
114997
|
+
if (item.committed) {
|
|
114998
|
+
results.push({ peerChatPK: item.peerChatPK, ok: true, message: sentMessage });
|
|
114999
|
+
} else {
|
|
115000
|
+
markLocalStatus(item.chatId, item.cid, LOCAL_FAILED);
|
|
115001
|
+
results.push({ peerChatPK: item.peerChatPK, ok: false, error });
|
|
115002
|
+
}
|
|
114655
115003
|
}
|
|
114656
115004
|
}
|
|
114657
115005
|
return results;
|
|
@@ -115458,7 +115806,6 @@ async function decryptRecordEntries(records, userChatPK, userPrivKey, peerChatPK
|
|
|
115458
115806
|
return [];
|
|
115459
115807
|
}
|
|
115460
115808
|
const signingKeysVersion = signingKeysFingerprint(options?.signingKeysByChatKey);
|
|
115461
|
-
const pair = await getCachedPair(userChatPK, userPrivKey, peerChatPK, { chatId: options?.chatId });
|
|
115462
115809
|
const entryOptions = { ...options, signingKeysVersion };
|
|
115463
115810
|
const shouldYield = positiveInt(options?.yieldEvery, 0) > 0;
|
|
115464
115811
|
const entries = new Array(source.length).fill(null);
|
|
@@ -115475,38 +115822,40 @@ async function decryptRecordEntries(records, userChatPK, userPrivKey, peerChatPK
|
|
|
115475
115822
|
}
|
|
115476
115823
|
pending.push({ record, index });
|
|
115477
115824
|
};
|
|
115478
|
-
|
|
115479
|
-
|
|
115480
|
-
|
|
115481
|
-
|
|
115482
|
-
|
|
115483
|
-
|
|
115484
|
-
|
|
115485
|
-
|
|
115486
|
-
|
|
115825
|
+
return withCachedPair(userChatPK, userPrivKey, peerChatPK, { chatId: options?.chatId }, async (pair) => {
|
|
115826
|
+
const openPending = async (pending) => {
|
|
115827
|
+
if (!pending.length) {
|
|
115828
|
+
return;
|
|
115829
|
+
}
|
|
115830
|
+
const opened = await decryptRecordBatchWithPair(pending.map((item) => item.record), pair, cache, entryOptions);
|
|
115831
|
+
for (let index = 0;index < opened.length; index += 1) {
|
|
115832
|
+
const entry = opened[index];
|
|
115833
|
+
if (entry) {
|
|
115834
|
+
entries[pending[index].index] = entry;
|
|
115835
|
+
}
|
|
115487
115836
|
}
|
|
115837
|
+
};
|
|
115838
|
+
if (!options?.signal && !shouldYield) {
|
|
115839
|
+
const pending = [];
|
|
115840
|
+
for (let index = 0;index < source.length; index += 1) {
|
|
115841
|
+
collectRecord(source[index], index, pending);
|
|
115842
|
+
}
|
|
115843
|
+
await openPending(pending);
|
|
115844
|
+
return entries.filter(Boolean);
|
|
115488
115845
|
}
|
|
115489
|
-
|
|
115490
|
-
|
|
115491
|
-
|
|
115492
|
-
|
|
115493
|
-
|
|
115846
|
+
const chunkSize = positiveInt(options?.yieldEvery, source.length || 1);
|
|
115847
|
+
for (let index = 0;index < source.length; index += chunkSize) {
|
|
115848
|
+
throwIfAborted(options?.signal);
|
|
115849
|
+
const chunk = source.slice(index, index + chunkSize);
|
|
115850
|
+
const pending = [];
|
|
115851
|
+
for (let offset = 0;offset < chunk.length; offset += 1) {
|
|
115852
|
+
collectRecord(chunk[offset], index + offset, pending);
|
|
115853
|
+
}
|
|
115854
|
+
await openPending(pending);
|
|
115855
|
+
await maybeYield(index + chunk.length, options);
|
|
115494
115856
|
}
|
|
115495
|
-
await openPending(pending);
|
|
115496
115857
|
return entries.filter(Boolean);
|
|
115497
|
-
}
|
|
115498
|
-
const chunkSize = positiveInt(options?.yieldEvery, source.length || 1);
|
|
115499
|
-
for (let index = 0;index < source.length; index += chunkSize) {
|
|
115500
|
-
throwIfAborted(options?.signal);
|
|
115501
|
-
const chunk = source.slice(index, index + chunkSize);
|
|
115502
|
-
const pending = [];
|
|
115503
|
-
for (let offset = 0;offset < chunk.length; offset += 1) {
|
|
115504
|
-
collectRecord(chunk[offset], index + offset, pending);
|
|
115505
|
-
}
|
|
115506
|
-
await openPending(pending);
|
|
115507
|
-
await maybeYield(index + chunk.length, options);
|
|
115508
|
-
}
|
|
115509
|
-
return entries.filter(Boolean);
|
|
115858
|
+
});
|
|
115510
115859
|
}
|
|
115511
115860
|
function messageQueryLimit(pageSize) {
|
|
115512
115861
|
return positiveInt(pageSize, MSG_BATCH_SIZE);
|
|
@@ -115559,7 +115908,11 @@ function readableEntryWindow(entries, pageSize, chatPK, peerChatPK, options = {}
|
|
|
115559
115908
|
const limitCount = positiveInt(pageSize, MSG_BATCH_SIZE);
|
|
115560
115909
|
const projectedEntries = readableProjectedEntries(source, chatPK, peerChatPK, options);
|
|
115561
115910
|
if (!projectedEntries.length) {
|
|
115562
|
-
return {
|
|
115911
|
+
return {
|
|
115912
|
+
count: 0,
|
|
115913
|
+
entries: source.filter((entry) => isProjectionSupportMsg(entry?.message)),
|
|
115914
|
+
start: 0
|
|
115915
|
+
};
|
|
115563
115916
|
}
|
|
115564
115917
|
const indexes = projectedEntries.map((entry) => entry.index);
|
|
115565
115918
|
const projectedByIndex = new Map(projectedEntries.map((entry) => [entry.index, entry.message]));
|
|
@@ -115852,9 +116205,10 @@ async function decryptMsg(msgData, userChatPK, userPrivKey, peerChatPK, options
|
|
|
115852
116205
|
return null;
|
|
115853
116206
|
}
|
|
115854
116207
|
try {
|
|
115855
|
-
|
|
115856
|
-
|
|
115857
|
-
|
|
116208
|
+
return await withCachedPair(userChatPK, userPrivKey, peerChatPK, { chatId: options?.chatId }, async (pair) => {
|
|
116209
|
+
const message = await openMsg(pair, msgData, { signingKeysByChatKey: options?.signingKeysByChatKey, crypto: options?.crypto });
|
|
116210
|
+
return normalizeDecryptedMsg(msgData, message);
|
|
116211
|
+
});
|
|
115858
116212
|
} catch {
|
|
115859
116213
|
return null;
|
|
115860
116214
|
}
|
|
@@ -116924,12 +117278,12 @@ function warmKeyStore(ref) {
|
|
|
116924
117278
|
}
|
|
116925
117279
|
return ref.current;
|
|
116926
117280
|
}
|
|
116927
|
-
function readMessageMedia2(cloud, media,
|
|
117281
|
+
function readMessageMedia2(cloud, media, message) {
|
|
116928
117282
|
const readChatMedia = cloud?.chat?.media?.read;
|
|
116929
117283
|
if (typeof media?.readMessageFile === "function") {
|
|
116930
|
-
return media.readMessageFile(readChatMedia,
|
|
117284
|
+
return media.readMessageFile(readChatMedia, message);
|
|
116931
117285
|
}
|
|
116932
|
-
return readMsgMedia(readChatMedia,
|
|
117286
|
+
return readMsgMedia(readChatMedia, message);
|
|
116933
117287
|
}
|
|
116934
117288
|
function isDenied3(error) {
|
|
116935
117289
|
return error?.code === "permission-denied";
|
|
@@ -117136,12 +117490,12 @@ function createChatMessageBatches({ cloud, media = {}, chatPK, chatPrivateKey, c
|
|
|
117136
117490
|
return;
|
|
117137
117491
|
}
|
|
117138
117492
|
const tasks = buildMediaTasks();
|
|
117139
|
-
const readFile4 = async (
|
|
117493
|
+
const readFile4 = async (_peerChatPK, message) => {
|
|
117140
117494
|
const cached = await readCachedMedia(localCache, message);
|
|
117141
117495
|
if (cached?.byteLength) {
|
|
117142
117496
|
return cached;
|
|
117143
117497
|
}
|
|
117144
|
-
const bytes = await readMessageMedia2(cloud, media,
|
|
117498
|
+
const bytes = await readMessageMedia2(cloud, media, message);
|
|
117145
117499
|
if (bytes?.byteLength) {
|
|
117146
117500
|
saveMedia(localCache, message, bytes, message);
|
|
117147
117501
|
}
|
|
@@ -117888,6 +118242,16 @@ function pingSigningKeys(ping, existing) {
|
|
|
117888
118242
|
[ping.payload.senderChatPK]: ping.payload.signingPublicKey
|
|
117889
118243
|
};
|
|
117890
118244
|
}
|
|
118245
|
+
function chatSettingsFromPreview(settings, preview2) {
|
|
118246
|
+
const current = normalizeChatSettings(settings);
|
|
118247
|
+
if (!isSystemMsg(preview2)) {
|
|
118248
|
+
return current;
|
|
118249
|
+
}
|
|
118250
|
+
return {
|
|
118251
|
+
...current,
|
|
118252
|
+
retention: cleanChatRetention(preview2.retention)
|
|
118253
|
+
};
|
|
118254
|
+
}
|
|
117891
118255
|
function chatFromPing(ping, entryId, existing, preview2, userChatPK, ms, options = {}) {
|
|
117892
118256
|
const ts = timestampMs(ms, null) ?? timestampMs(existing?.ts, null) ?? timestampMs(preview2?.ts, null) ?? 0;
|
|
117893
118257
|
if (!ts) {
|
|
@@ -117904,10 +118268,11 @@ function chatFromPing(ping, entryId, existing, preview2, userChatPK, ms, options
|
|
|
117904
118268
|
peerChatPK: ping.payload.senderChatPK,
|
|
117905
118269
|
peerUid: existing?.peerUid || cleanText(ping.payload.senderUid) || null,
|
|
117906
118270
|
signingKeysByChatKey: pingSigningKeys(ping, existing),
|
|
117907
|
-
settings: existing?.settings,
|
|
118271
|
+
settings: chatSettingsFromPreview(existing?.settings, preview2),
|
|
117908
118272
|
saved: existing?.saved || null,
|
|
117909
118273
|
readMs,
|
|
117910
118274
|
startMs,
|
|
118275
|
+
signerShared: existing?.signerShared === true,
|
|
117911
118276
|
preview: visiblePreview,
|
|
117912
118277
|
ts,
|
|
117913
118278
|
unseen: visiblePreview ? isChatUnseenForUser({ preview: visiblePreview, readMs }, userChatPK) : false
|
|
@@ -117963,10 +118328,11 @@ async function savePing(cloud, uid, userChatPK, userPrivKey, ping, options = {})
|
|
|
117963
118328
|
peerUid: peerUid2 || existing?.peerUid,
|
|
117964
118329
|
peerSigningPublicKey: ping.payload.signingPublicKey || existing?.signingKeysByChatKey?.[ping.payload.senderChatPK],
|
|
117965
118330
|
signingKeysByChatKey,
|
|
117966
|
-
settings: existing?.settings,
|
|
118331
|
+
settings: chatSettingsFromPreview(existing?.settings, preview2),
|
|
117967
118332
|
preview: preview2 || existing?.preview,
|
|
117968
118333
|
readMs: existing?.readMs,
|
|
117969
|
-
startMs: existing ? existing.startMs : timestampMs(options.startPreview?.ts ?? preview2?.ts, null, { positive: true })
|
|
118334
|
+
startMs: existing ? existing.startMs : timestampMs(options.startPreview?.ts ?? preview2?.ts, null, { positive: true }),
|
|
118335
|
+
signerShared: existing?.signerShared === true
|
|
117970
118336
|
});
|
|
117971
118337
|
const body = await sealOwnChatEntry(userPrivKey, entryId, entry);
|
|
117972
118338
|
const record = { body };
|
|
@@ -117976,14 +118342,16 @@ async function savePing(cloud, uid, userChatPK, userPrivKey, ping, options = {})
|
|
|
117976
118342
|
await cloud.user.chats.write(uid, entryId, record);
|
|
117977
118343
|
return true;
|
|
117978
118344
|
}
|
|
117979
|
-
function chatWithReadPreview(existing, preview2, userChatPK) {
|
|
117980
|
-
if (!existing?.id
|
|
118345
|
+
function chatWithReadPreview(existing, preview2, userChatPK, fields = {}) {
|
|
118346
|
+
if (!existing?.id) {
|
|
117981
118347
|
return null;
|
|
117982
118348
|
}
|
|
117983
118349
|
return {
|
|
117984
118350
|
...existing,
|
|
117985
|
-
|
|
117986
|
-
|
|
118351
|
+
signingKeysByChatKey: fields.signingKeysByChatKey || existing.signingKeysByChatKey,
|
|
118352
|
+
peerUid: fields.peerUid || existing.peerUid,
|
|
118353
|
+
preview: preview2 || existing.preview,
|
|
118354
|
+
unseen: preview2 ? isChatUnseenForUser({ preview: preview2, readMs: existing.readMs }, userChatPK) : existing.unseen
|
|
117987
118355
|
};
|
|
117988
118356
|
}
|
|
117989
118357
|
function patchReadPingPreview(existing, receiptPreview, userChatPK) {
|
|
@@ -118064,6 +118432,8 @@ async function processInbox(cloud, uid, userChatPK, userPrivKey, options = {}) {
|
|
|
118064
118432
|
let current = chatsById.get(group.chatId) || null;
|
|
118065
118433
|
let wrote = false;
|
|
118066
118434
|
let handled = false;
|
|
118435
|
+
const identityPing = group.message?.ping || group.read?.ping || group.delete?.ping;
|
|
118436
|
+
const peerUid2 = await resolvePingUid(cloud, identityPing?.payload);
|
|
118067
118437
|
if (group.message) {
|
|
118068
118438
|
const item = group.message;
|
|
118069
118439
|
const entryId = ownChatEntryId(userPrivKey, item.chatId);
|
|
@@ -118084,7 +118454,8 @@ async function processInbox(cloud, uid, userChatPK, userPrivKey, options = {}) {
|
|
|
118084
118454
|
signingKeysByChatKey,
|
|
118085
118455
|
preview: preview2,
|
|
118086
118456
|
startPreview,
|
|
118087
|
-
tsMs: item.ms
|
|
118457
|
+
tsMs: item.ms,
|
|
118458
|
+
peerUid: peerUid2
|
|
118088
118459
|
});
|
|
118089
118460
|
}
|
|
118090
118461
|
if (group.read) {
|
|
@@ -118094,22 +118465,24 @@ async function processInbox(cloud, uid, userChatPK, userPrivKey, options = {}) {
|
|
|
118094
118465
|
const signingKeysByChatKey = pingSigningKeys(item.ping, existing);
|
|
118095
118466
|
const receiptPreview = await readPingMsg(cloud, userChatPK, userPrivKey, item.ping, signingKeysByChatKey);
|
|
118096
118467
|
const openedPreview = patchReadPingPreview(existing, receiptPreview, userChatPK);
|
|
118097
|
-
const chat = chatWithReadPreview(current, openedPreview, userChatPK
|
|
118468
|
+
const chat = chatWithReadPreview(current || existing, openedPreview, userChatPK, {
|
|
118469
|
+
signingKeysByChatKey,
|
|
118470
|
+
peerUid: peerUid2
|
|
118471
|
+
});
|
|
118098
118472
|
handled = true;
|
|
118099
|
-
if (
|
|
118100
|
-
|
|
118101
|
-
|
|
118102
|
-
|
|
118103
|
-
options.onPingChat?.(chat);
|
|
118104
|
-
}
|
|
118105
|
-
const writeExisting = chat || existing;
|
|
118106
|
-
wrote = await savePing(cloud, uid, userChatPK, userPrivKey, item.ping, {
|
|
118107
|
-
existing: writeExisting,
|
|
118108
|
-
signingKeysByChatKey,
|
|
118109
|
-
preview: openedPreview,
|
|
118110
|
-
writeTs: false
|
|
118111
|
-
}) || wrote;
|
|
118473
|
+
if (chat) {
|
|
118474
|
+
current = chat;
|
|
118475
|
+
chatsById.set(chat.id, chat);
|
|
118476
|
+
options.onPingChat?.(chat);
|
|
118112
118477
|
}
|
|
118478
|
+
const writeExisting = chat || existing;
|
|
118479
|
+
wrote = await savePing(cloud, uid, userChatPK, userPrivKey, item.ping, {
|
|
118480
|
+
existing: writeExisting,
|
|
118481
|
+
signingKeysByChatKey,
|
|
118482
|
+
preview: openedPreview || existing?.preview || null,
|
|
118483
|
+
writeTs: false,
|
|
118484
|
+
peerUid: peerUid2
|
|
118485
|
+
}) || wrote;
|
|
118113
118486
|
}
|
|
118114
118487
|
if (group.delete) {
|
|
118115
118488
|
const item = group.delete;
|
|
@@ -118130,7 +118503,8 @@ async function processInbox(cloud, uid, userChatPK, userPrivKey, options = {}) {
|
|
|
118130
118503
|
wrote = await savePing(cloud, uid, userChatPK, userPrivKey, item.ping, {
|
|
118131
118504
|
existing: writeExisting,
|
|
118132
118505
|
signingKeysByChatKey,
|
|
118133
|
-
preview: deletedPreview
|
|
118506
|
+
preview: deletedPreview,
|
|
118507
|
+
peerUid: peerUid2
|
|
118134
118508
|
}) || wrote;
|
|
118135
118509
|
}
|
|
118136
118510
|
}
|
|
@@ -118152,6 +118526,7 @@ var init_inbox = __esm(() => {
|
|
|
118152
118526
|
init_ping();
|
|
118153
118527
|
init_query();
|
|
118154
118528
|
init_chats();
|
|
118529
|
+
init_ttl();
|
|
118155
118530
|
init_time();
|
|
118156
118531
|
init_protocol();
|
|
118157
118532
|
});
|
|
@@ -118535,6 +118910,7 @@ async function decryptChatEntry(entryRecord, userChatPK, userPrivKey) {
|
|
|
118535
118910
|
saved: entry.saved || null,
|
|
118536
118911
|
readMs,
|
|
118537
118912
|
startMs,
|
|
118913
|
+
signerShared: entry.signerShared === true,
|
|
118538
118914
|
preview: visiblePreview,
|
|
118539
118915
|
ts,
|
|
118540
118916
|
unseen: visiblePreview ? isChatUnseenForUser({ preview: visiblePreview, readMs }, userChatPK) : false
|
|
@@ -118647,6 +119023,7 @@ function createChatList({
|
|
|
118647
119023
|
let chats = [];
|
|
118648
119024
|
let peers = [];
|
|
118649
119025
|
let isChatDataReady = false;
|
|
119026
|
+
let isChatListLive = false;
|
|
118650
119027
|
let chatSourceReady = false;
|
|
118651
119028
|
let lastChat = null;
|
|
118652
119029
|
let serverChatIds = [];
|
|
@@ -118683,6 +119060,7 @@ function createChatList({
|
|
|
118683
119060
|
chats,
|
|
118684
119061
|
peers,
|
|
118685
119062
|
isChatDataReady,
|
|
119063
|
+
isChatListLive,
|
|
118686
119064
|
hasChats: chats.length > 0,
|
|
118687
119065
|
previewNow,
|
|
118688
119066
|
lastChat,
|
|
@@ -118716,6 +119094,13 @@ function createChatList({
|
|
|
118716
119094
|
isChatDataReady = value;
|
|
118717
119095
|
publish();
|
|
118718
119096
|
};
|
|
119097
|
+
const setIsChatListLive = (next) => {
|
|
119098
|
+
const value = nextValue(isChatListLive, next);
|
|
119099
|
+
if (Object.is(isChatListLive, value))
|
|
119100
|
+
return;
|
|
119101
|
+
isChatListLive = value;
|
|
119102
|
+
publish();
|
|
119103
|
+
};
|
|
118719
119104
|
const setLastChat = (next) => {
|
|
118720
119105
|
const value = nextValue(lastChat, next);
|
|
118721
119106
|
if (Object.is(lastChat, value))
|
|
@@ -118925,6 +119310,7 @@ function createChatList({
|
|
|
118925
119310
|
const resetChatList = (ready = false) => {
|
|
118926
119311
|
chatSourceReady = ready;
|
|
118927
119312
|
syncChatDataReady();
|
|
119313
|
+
setIsChatListLive(false);
|
|
118928
119314
|
setChats((prev) => prev.length ? [] : prev);
|
|
118929
119315
|
setPeers((prev) => prev.length ? [] : prev);
|
|
118930
119316
|
setLastChat((prev) => prev ? null : prev);
|
|
@@ -119014,6 +119400,7 @@ function createChatList({
|
|
|
119014
119400
|
resetAllChatState();
|
|
119015
119401
|
return;
|
|
119016
119402
|
}
|
|
119403
|
+
setIsChatListLive(false);
|
|
119017
119404
|
let cancelled = false;
|
|
119018
119405
|
const hydrateKey = localCache?.id ? `${localCache.id}:${chatPK}` : "";
|
|
119019
119406
|
if (hydrateKey && lastHydratedCacheKeyRef.current !== hydrateKey) {
|
|
@@ -119113,6 +119500,7 @@ function createChatList({
|
|
|
119113
119500
|
writeCache: true,
|
|
119114
119501
|
serverEndReached: cachedHistoryEndRef.current
|
|
119115
119502
|
});
|
|
119503
|
+
setIsChatListLive(true);
|
|
119116
119504
|
listenUpdateSeqRef.current += 1;
|
|
119117
119505
|
markDiag(diag, "chat.provider.listen.update", {
|
|
119118
119506
|
seq: listenUpdateSeqRef.current,
|
|
@@ -119155,6 +119543,7 @@ function createChatList({
|
|
|
119155
119543
|
markChatSourceReady();
|
|
119156
119544
|
fillVisibleChatPage();
|
|
119157
119545
|
}, (error) => {
|
|
119546
|
+
setIsChatListLive(false);
|
|
119158
119547
|
markError(diag, "chat.provider.listen", listenStartedAt, error);
|
|
119159
119548
|
if (shouldResetChatListAfterListenError(error)) {
|
|
119160
119549
|
resetAllChatState();
|
|
@@ -119308,6 +119697,7 @@ function createChatList({
|
|
|
119308
119697
|
chatExists: !!peerChat?.id || hasServerChatForPeer(peerChatPK),
|
|
119309
119698
|
receiverUid: peerChat?.peerUid || "",
|
|
119310
119699
|
peerSigningPublicKey: peerChat?.signingKeysByChatKey?.[peerChatPK] || "",
|
|
119700
|
+
signerShared: peerChat?.signerShared === true,
|
|
119311
119701
|
ownEntry: peerChat?.entryId ? peerChat : null
|
|
119312
119702
|
};
|
|
119313
119703
|
};
|
|
@@ -120005,6 +120395,7 @@ function createChatSession({
|
|
|
120005
120395
|
readCacheRef,
|
|
120006
120396
|
readWriteInterval,
|
|
120007
120397
|
getChatRetention,
|
|
120398
|
+
sendOptionsForPeer,
|
|
120008
120399
|
setChats,
|
|
120009
120400
|
diag
|
|
120010
120401
|
});
|
|
@@ -121149,7 +121540,7 @@ function createPeersApi({ cloud, network, avatarCache = null }) {
|
|
|
121149
121540
|
}
|
|
121150
121541
|
if (avatarVersion != null && typeof cloud.peer.avatar.read === "function") {
|
|
121151
121542
|
try {
|
|
121152
|
-
const bytes = await cloud.peer.avatar.read(uid);
|
|
121543
|
+
const bytes = await cloud.peer.avatar.read(uid, { version: avatarVersion });
|
|
121153
121544
|
const cachedSource = await writeCachedAvatar(uid, avatarVersion, bytes);
|
|
121154
121545
|
if (cachedSource) {
|
|
121155
121546
|
return cachedSource;
|
|
@@ -121686,6 +122077,10 @@ function getSatsBalance(result) {
|
|
|
121686
122077
|
}
|
|
121687
122078
|
return satsBalance;
|
|
121688
122079
|
}
|
|
122080
|
+
function displayBalanceValue(value) {
|
|
122081
|
+
const balance = Number(value);
|
|
122082
|
+
return Number.isSafeInteger(balance) && balance >= 0 ? balance : null;
|
|
122083
|
+
}
|
|
121689
122084
|
function samePlainObject(a, b) {
|
|
121690
122085
|
if (a === b) {
|
|
121691
122086
|
return true;
|
|
@@ -121714,9 +122109,10 @@ function sameTokenBalances(a, b) {
|
|
|
121714
122109
|
}
|
|
121715
122110
|
return true;
|
|
121716
122111
|
}
|
|
121717
|
-
function createWalletBalance({ wallet, diag, onChange = null }) {
|
|
122112
|
+
function createWalletBalance({ wallet, diag, initialDisplayBalance = null, onBalance = null, onChange = null }) {
|
|
121718
122113
|
let snapshot = {
|
|
121719
122114
|
balance: null,
|
|
122115
|
+
displayBalance: displayBalanceValue(initialDisplayBalance),
|
|
121720
122116
|
satsBalance: null,
|
|
121721
122117
|
tokenBalances: new Map,
|
|
121722
122118
|
balanceReady: false,
|
|
@@ -121726,10 +122122,28 @@ function createWalletBalance({ wallet, diag, onChange = null }) {
|
|
|
121726
122122
|
snapshot = { ...snapshot, ...changes };
|
|
121727
122123
|
onChange?.();
|
|
121728
122124
|
};
|
|
122125
|
+
const publishDisplayBalance = (changes, value, trusted = false) => {
|
|
122126
|
+
const displayBalance = displayBalanceValue(value);
|
|
122127
|
+
if (displayBalance == null || !trusted && !snapshot.balanceReady) {
|
|
122128
|
+
return null;
|
|
122129
|
+
}
|
|
122130
|
+
if (!Object.is(snapshot.displayBalance, displayBalance)) {
|
|
122131
|
+
changes.displayBalance = displayBalance;
|
|
122132
|
+
}
|
|
122133
|
+
return displayBalance;
|
|
122134
|
+
};
|
|
121729
122135
|
const setBalance = (nextBalance) => {
|
|
121730
122136
|
const value = typeof nextBalance === "function" ? nextBalance(snapshot.balance) : nextBalance;
|
|
122137
|
+
const changes = {};
|
|
121731
122138
|
if (!Object.is(snapshot.balance, value)) {
|
|
121732
|
-
|
|
122139
|
+
changes.balance = value;
|
|
122140
|
+
}
|
|
122141
|
+
const displayBalance = publishDisplayBalance(changes, value);
|
|
122142
|
+
if (Object.keys(changes).length) {
|
|
122143
|
+
publish(changes);
|
|
122144
|
+
}
|
|
122145
|
+
if (displayBalance != null) {
|
|
122146
|
+
onBalance?.(displayBalance);
|
|
121733
122147
|
}
|
|
121734
122148
|
};
|
|
121735
122149
|
const setTokenBalances = (nextTokenBalances) => {
|
|
@@ -121738,12 +122152,13 @@ function createWalletBalance({ wallet, diag, onChange = null }) {
|
|
|
121738
122152
|
publish({ tokenBalances: new Map(source) });
|
|
121739
122153
|
}
|
|
121740
122154
|
};
|
|
121741
|
-
const setBalanceResult = (result) => {
|
|
122155
|
+
const setBalanceResult = (result, { ready = false } = {}) => {
|
|
121742
122156
|
const changes = {};
|
|
121743
122157
|
const nextBalance = getBalanceValue(result);
|
|
121744
122158
|
if (nextBalance != null && !Object.is(snapshot.balance, nextBalance)) {
|
|
121745
122159
|
changes.balance = nextBalance;
|
|
121746
122160
|
}
|
|
122161
|
+
const nextDisplayBalance = publishDisplayBalance(changes, nextBalance, true);
|
|
121747
122162
|
const nextSatsBalance = getSatsBalance(result);
|
|
121748
122163
|
if (nextSatsBalance && !samePlainObject(snapshot.satsBalance, nextSatsBalance)) {
|
|
121749
122164
|
changes.satsBalance = nextSatsBalance;
|
|
@@ -121752,9 +122167,15 @@ function createWalletBalance({ wallet, diag, onChange = null }) {
|
|
|
121752
122167
|
if (nextTokenBalances && !sameTokenBalances(snapshot.tokenBalances, nextTokenBalances)) {
|
|
121753
122168
|
changes.tokenBalances = new Map(nextTokenBalances);
|
|
121754
122169
|
}
|
|
122170
|
+
if (ready && !snapshot.balanceReady) {
|
|
122171
|
+
changes.balanceReady = true;
|
|
122172
|
+
}
|
|
121755
122173
|
if (Object.keys(changes).length) {
|
|
121756
122174
|
publish(changes);
|
|
121757
122175
|
}
|
|
122176
|
+
if (nextDisplayBalance != null) {
|
|
122177
|
+
onBalance?.(nextDisplayBalance);
|
|
122178
|
+
}
|
|
121758
122179
|
};
|
|
121759
122180
|
const setSatsBalanceResult = (nextSatsBalance) => {
|
|
121760
122181
|
if (!nextSatsBalance || typeof nextSatsBalance !== "object") {
|
|
@@ -121767,9 +122188,13 @@ function createWalletBalance({ wallet, diag, onChange = null }) {
|
|
|
121767
122188
|
if (nextSatsBalance.available != null && !Object.is(snapshot.balance, nextSatsBalance.available)) {
|
|
121768
122189
|
changes.balance = nextSatsBalance.available;
|
|
121769
122190
|
}
|
|
122191
|
+
const nextDisplayBalance = publishDisplayBalance(changes, nextSatsBalance.available);
|
|
121770
122192
|
if (Object.keys(changes).length) {
|
|
121771
122193
|
publish(changes);
|
|
121772
122194
|
}
|
|
122195
|
+
if (nextDisplayBalance != null) {
|
|
122196
|
+
onBalance?.(nextDisplayBalance);
|
|
122197
|
+
}
|
|
121773
122198
|
};
|
|
121774
122199
|
const getBalance = async () => {
|
|
121775
122200
|
if (!wallet) {
|
|
@@ -121783,7 +122208,7 @@ function createWalletBalance({ wallet, diag, onChange = null }) {
|
|
|
121783
122208
|
}
|
|
121784
122209
|
try {
|
|
121785
122210
|
const result = await wallet.getBalance();
|
|
121786
|
-
setBalanceResult(result);
|
|
122211
|
+
setBalanceResult(result, { ready: true });
|
|
121787
122212
|
markDone(diag, "wallet.balance", startedAt, { hasBalance: getBalanceValue(result) != null, hasSatsBalance: !!getSatsBalance(result), hasTokenBalances: !!getTokenBalances(result) });
|
|
121788
122213
|
} catch (error) {
|
|
121789
122214
|
markError(diag, "wallet.balance", startedAt, error);
|
|
@@ -121803,6 +122228,7 @@ function createWalletBalance({ wallet, diag, onChange = null }) {
|
|
|
121803
122228
|
const reset = () => {
|
|
121804
122229
|
snapshot = {
|
|
121805
122230
|
balance: null,
|
|
122231
|
+
displayBalance: null,
|
|
121806
122232
|
satsBalance: null,
|
|
121807
122233
|
tokenBalances: new Map,
|
|
121808
122234
|
balanceReady: false,
|
|
@@ -121819,7 +122245,7 @@ function createWalletBalance({ wallet, diag, onChange = null }) {
|
|
|
121819
122245
|
setSatsBalanceResult
|
|
121820
122246
|
};
|
|
121821
122247
|
}
|
|
121822
|
-
var
|
|
122248
|
+
var init_balance2 = () => {};
|
|
121823
122249
|
|
|
121824
122250
|
// ../../shared/wallet/deposits.js
|
|
121825
122251
|
async function getClaimableDepositUtxos(wallet, options = {}) {
|
|
@@ -122844,11 +123270,6 @@ function createWalletPrivacy({ wallet, ghostWallet, diag }) {
|
|
|
122844
123270
|
const startedAt = Date.now();
|
|
122845
123271
|
const desired = desiredPrivacy;
|
|
122846
123272
|
markDiag(diag, "wallet.privacy.start", { ghostWallet: desired });
|
|
122847
|
-
const current = typeof wallet.getWalletSettings === "function" ? await wallet.getWalletSettings() : null;
|
|
122848
|
-
if (closed || requestRevision !== revision || current?.privateEnabled === true === desired) {
|
|
122849
|
-
markDone(diag, "wallet.privacy", startedAt, { changed: false, cancelled: closed || requestRevision !== revision });
|
|
122850
|
-
return;
|
|
122851
|
-
}
|
|
122852
123273
|
await wallet.setPrivacyEnabled(desired);
|
|
122853
123274
|
markDone(diag, "wallet.privacy", startedAt, { changed: true });
|
|
122854
123275
|
}).catch((error) => {
|
|
@@ -123602,8 +124023,8 @@ function pendingTransfers(transfers = []) {
|
|
|
123602
124023
|
function pendingTransferIds(transfers = []) {
|
|
123603
124024
|
return pendingTransfers(transfers).map((tx) => String(tx.id));
|
|
123604
124025
|
}
|
|
123605
|
-
function
|
|
123606
|
-
return pendingTransfers(transfers).filter(
|
|
124026
|
+
function pendingIncomingTransfers(transfers = []) {
|
|
124027
|
+
return pendingTransfers(transfers).filter(isIncomingTransfer);
|
|
123607
124028
|
}
|
|
123608
124029
|
function uniqueIds(ids = []) {
|
|
123609
124030
|
return [...new Set((Array.isArray(ids) ? ids : [ids]).map((id) => String(id || "")).filter(Boolean))];
|
|
@@ -123698,7 +124119,7 @@ function adaptiveClaimBatchSize(maxBatchSize, queueDepth) {
|
|
|
123698
124119
|
}
|
|
123699
124120
|
return 1;
|
|
123700
124121
|
}
|
|
123701
|
-
function createWalletTransferSession({ wallet, walletPK, localCache, claimIncomingTransfers, pendingClaimBatchSize = null, eagerOutgoingStatusRefresh = false, transferStore, appState = null, deferBackgroundWork = null, backgroundSignal = null, diag }) {
|
|
124122
|
+
function createWalletTransferSession({ wallet, walletPK, localCache, claimIncomingTransfers, pendingClaimBatchSize = null, eagerOutgoingStatusRefresh = false, eagerCacheHistory = true, transferStore, appState = null, deferBackgroundWork = null, backgroundSignal = null, refreshBalance = null, diag }) {
|
|
123702
124123
|
if (!transferStore || typeof transferStore.subscribe !== "function" || typeof transferStore.getSnapshot !== "function" || typeof transferStore.getCacheState !== "function" || typeof transferStore.setHistory !== "function") {
|
|
123703
124124
|
throw new Error("createWalletTransferSession requires transferStore");
|
|
123704
124125
|
}
|
|
@@ -123712,6 +124133,7 @@ function createWalletTransferSession({ wallet, walletPK, localCache, claimIncomi
|
|
|
123712
124133
|
const initialTransfers = canUseInitialStore ? transferStore.getTransfers() : [];
|
|
123713
124134
|
const initialHistoryTransfers = canUseInitialStore ? transferStore.getHistoryTransfers() : [];
|
|
123714
124135
|
const initialTxReady = canUseInitialStore && (initialStoreSnapshot.ready || initialTransfers.length > 0 || initialHistoryTransfers.length > 0);
|
|
124136
|
+
const initialCacheReady = initialTxReady && (eagerCacheHistory === false || initialStoreSnapshot.serverEndReached === true && initialHistoryTransfers.length >= initialStoreSnapshot.historyCount);
|
|
123715
124137
|
const listeners = new Set;
|
|
123716
124138
|
let isTxLoading = false;
|
|
123717
124139
|
let publishedSnapshot = null;
|
|
@@ -123762,7 +124184,7 @@ function createWalletTransferSession({ wallet, walletPK, localCache, claimIncomi
|
|
|
123762
124184
|
const cacheHydrateKeyRef = { current: "" };
|
|
123763
124185
|
const cacheHydratePromiseRef = { current: null };
|
|
123764
124186
|
const fullCacheHydratePromiseRef = { current: null };
|
|
123765
|
-
const cacheWriteRef = { current: { timer: null, cache: null, state: null } };
|
|
124187
|
+
const cacheWriteRef = { current: { timer: null, cache: null, state: null, fullHistory: false } };
|
|
123766
124188
|
const cacheDirtyRef = { current: false };
|
|
123767
124189
|
const lastFetchAtRef = { current: 0 };
|
|
123768
124190
|
const claimBatchSize = Math.max(1, Number(pendingClaimBatchSize) || PENDING_TRANSFER_CLAIM_BATCH_SIZE);
|
|
@@ -124090,9 +124512,9 @@ function createWalletTransferSession({ wallet, walletPK, localCache, claimIncomi
|
|
|
124090
124512
|
return false;
|
|
124091
124513
|
}
|
|
124092
124514
|
const cachedTransfers = filterTransfersForWallet(cached.transfers, walletPKRef.current);
|
|
124093
|
-
const
|
|
124094
|
-
const
|
|
124095
|
-
const
|
|
124515
|
+
const cachedPublishTransfers = !publish && historyTransfersRef.current.length ? mergeTransferPageForWallet(historyTransfersRef.current, cachedTransfers, walletPKRef.current, "append") : cachedTransfers;
|
|
124516
|
+
const cachedPendingIncoming = pendingIncomingTransfers(cachedPublishTransfers);
|
|
124517
|
+
const cachedPending = pendingTransfers(cachedPublishTransfers);
|
|
124096
124518
|
rememberPendingTransferIds(cachedPending.map((tx) => tx.id));
|
|
124097
124519
|
markDiag(diag, label, {
|
|
124098
124520
|
elapsedMs: Date.now() - startedAt,
|
|
@@ -124231,9 +124653,11 @@ function createWalletTransferSession({ wallet, walletPK, localCache, claimIncomi
|
|
|
124231
124653
|
pending.timer = null;
|
|
124232
124654
|
const cache = pending.cache;
|
|
124233
124655
|
const state = pending.state;
|
|
124656
|
+
const fullHistory = pending.fullHistory;
|
|
124234
124657
|
pending.state = null;
|
|
124235
124658
|
if (cache && state) {
|
|
124236
|
-
writeCachedTransferState
|
|
124659
|
+
const write = fullHistory ? writeCachedTransferState : writeCachedTransferHeadState;
|
|
124660
|
+
write(cache, state);
|
|
124237
124661
|
}
|
|
124238
124662
|
};
|
|
124239
124663
|
const queueWalletFetch = (read) => {
|
|
@@ -124338,7 +124762,7 @@ function createWalletTransferSession({ wallet, walletPK, localCache, claimIncomi
|
|
|
124338
124762
|
return pendingQueryPromiseRef.current;
|
|
124339
124763
|
};
|
|
124340
124764
|
const pendingIncomingClaimCandidates = (sourceTransfers = []) => {
|
|
124341
|
-
return
|
|
124765
|
+
return pendingIncomingTransfers(sourceTransfers).filter((tx) => {
|
|
124342
124766
|
const id = String(tx?.id || "");
|
|
124343
124767
|
return id && !claimedTransferIdsRef.current.has(id);
|
|
124344
124768
|
});
|
|
@@ -124554,6 +124978,9 @@ function createWalletTransferSession({ wallet, walletPK, localCache, claimIncomi
|
|
|
124554
124978
|
batchClaimedIds.push(...staged);
|
|
124555
124979
|
flushClaimed();
|
|
124556
124980
|
const uniqueBatchClaimedIds = uniqueIds(batchClaimedIds);
|
|
124981
|
+
if (uniqueBatchClaimedIds.length && typeof refreshBalance === "function") {
|
|
124982
|
+
await refreshBalance();
|
|
124983
|
+
}
|
|
124557
124984
|
const unclaimedIds = candidateIds.filter((id) => !uniqueBatchClaimedIds.includes(id) && !claimedTransferIdsRef.current.has(id));
|
|
124558
124985
|
if (unclaimedIds.length) {
|
|
124559
124986
|
const elapsedMs = Date.now() - startedAt;
|
|
@@ -125076,7 +125503,7 @@ function createWalletTransferSession({ wallet, walletPK, localCache, claimIncomi
|
|
|
125076
125503
|
try {
|
|
125077
125504
|
await yieldToUi();
|
|
125078
125505
|
const pendingTransfers2 = await getPendingTransfersSnapshot();
|
|
125079
|
-
const incomingTransfers =
|
|
125506
|
+
const incomingTransfers = pendingIncomingTransfers(pendingTransfers2);
|
|
125080
125507
|
const claimCandidates = pendingIncomingClaimCandidates(incomingTransfers);
|
|
125081
125508
|
if (!incomingTransfers.length) {
|
|
125082
125509
|
markDone(diag, "wallet.pendingTxs.active", startedAt, { pending: 0, claimed: 0, reason });
|
|
@@ -125421,13 +125848,16 @@ function createWalletTransferSession({ wallet, walletPK, localCache, claimIncomi
|
|
|
125421
125848
|
if (cacheWriteRef.current.timer) {
|
|
125422
125849
|
clearTimeout(cacheWriteRef.current.timer);
|
|
125423
125850
|
}
|
|
125424
|
-
cacheWriteRef.current = { timer: null, cache: null, state: null };
|
|
125851
|
+
cacheWriteRef.current = { timer: null, cache: null, state: null, fullHistory: false };
|
|
125425
125852
|
cacheDirtyRef.current = false;
|
|
125426
125853
|
};
|
|
125427
125854
|
const startCacheHydration = () => {
|
|
125428
125855
|
if (!wallet || !localCache || !walletPKRef.current) {
|
|
125429
125856
|
return;
|
|
125430
125857
|
}
|
|
125858
|
+
if (initialCacheReady) {
|
|
125859
|
+
return;
|
|
125860
|
+
}
|
|
125431
125861
|
const hydrateKey = `${localCache.id || "cache"}:${walletPKRef.current}`;
|
|
125432
125862
|
if (cacheHydrateKeyRef.current === hydrateKey) {
|
|
125433
125863
|
return;
|
|
@@ -125452,7 +125882,7 @@ function createWalletTransferSession({ wallet, walletPK, localCache, claimIncomi
|
|
|
125452
125882
|
return;
|
|
125453
125883
|
}
|
|
125454
125884
|
const hydratedHead = applyCachedTransferState(cachedHead, { label: "wallet.provider.cache.hydrate", publish: true, startedAt: hydrateStartedAt });
|
|
125455
|
-
if (cancelled)
|
|
125885
|
+
if (cancelled || !eagerCacheHistory)
|
|
125456
125886
|
return;
|
|
125457
125887
|
await loadFullTransferCache({ label: "wallet.provider.cache.fullHydrate", publish: !hydratedHead });
|
|
125458
125888
|
}).catch((error) => {
|
|
@@ -125476,12 +125906,10 @@ function createWalletTransferSession({ wallet, walletPK, localCache, claimIncomi
|
|
|
125476
125906
|
if (!cacheDirtyRef.current && !cacheWriteRef.current.timer) {
|
|
125477
125907
|
return;
|
|
125478
125908
|
}
|
|
125479
|
-
if (historyTransfersRef.current.length < knownHistoryCountRef.current) {
|
|
125480
|
-
return;
|
|
125481
|
-
}
|
|
125482
125909
|
cacheDirtyRef.current = false;
|
|
125483
125910
|
cacheWriteRef.current.cache = localCache;
|
|
125484
125911
|
cacheWriteRef.current.state = transferStore.getCacheState();
|
|
125912
|
+
cacheWriteRef.current.fullHistory = historyTransfersRef.current.length >= knownHistoryCountRef.current;
|
|
125485
125913
|
if (cacheWriteRef.current.timer) {
|
|
125486
125914
|
clearTimeout(cacheWriteRef.current.timer);
|
|
125487
125915
|
}
|
|
@@ -125510,7 +125938,7 @@ function createWalletTransferSession({ wallet, walletPK, localCache, claimIncomi
|
|
|
125510
125938
|
serverHistoryComplete: serverHistoryCompleteRef.current,
|
|
125511
125939
|
hasMoreTxs: !historyComplete,
|
|
125512
125940
|
hasPendingTxs,
|
|
125513
|
-
hasPendingIncomingTxs:
|
|
125941
|
+
hasPendingIncomingTxs: pendingIncomingTransfers(transfersRef.current).length > 0,
|
|
125514
125942
|
beginSdkActivity,
|
|
125515
125943
|
getRecentTxs,
|
|
125516
125944
|
claimPendingIncomingTransfers: claimPendingIncomingTransfers2,
|
|
@@ -125861,10 +126289,12 @@ function createWalletSession({
|
|
|
125861
126289
|
pendingClaimBatchSize = null,
|
|
125862
126290
|
activeTransferRefreshMs = null,
|
|
125863
126291
|
eagerOutgoingStatusRefresh = false,
|
|
126292
|
+
eagerCacheHistory = true,
|
|
125864
126293
|
sentTransferRefreshDelayMs = null,
|
|
125865
126294
|
deferBackgroundWork = null,
|
|
125866
126295
|
appState = null,
|
|
125867
126296
|
transferStore,
|
|
126297
|
+
cachedBalance = null,
|
|
125868
126298
|
ghostWallet = true,
|
|
125869
126299
|
diag = null
|
|
125870
126300
|
}) {
|
|
@@ -125882,6 +126312,7 @@ function createWalletSession({
|
|
|
125882
126312
|
const txSubscriptions = createFieldSubscriptions(() => publishedSnapshot?.txValue);
|
|
125883
126313
|
let polling = null;
|
|
125884
126314
|
let readyDiag = null;
|
|
126315
|
+
let refreshWalletBalance = null;
|
|
125885
126316
|
const transferSession = createWalletTransferSession({
|
|
125886
126317
|
wallet,
|
|
125887
126318
|
walletPK,
|
|
@@ -125889,10 +126320,12 @@ function createWalletSession({
|
|
|
125889
126320
|
claimIncomingTransfers,
|
|
125890
126321
|
pendingClaimBatchSize,
|
|
125891
126322
|
eagerOutgoingStatusRefresh,
|
|
126323
|
+
eagerCacheHistory,
|
|
125892
126324
|
transferStore,
|
|
125893
126325
|
appState,
|
|
125894
126326
|
deferBackgroundWork,
|
|
125895
126327
|
backgroundSignal: backgroundAbort.signal,
|
|
126328
|
+
refreshBalance: () => refreshWalletBalance?.(),
|
|
125896
126329
|
diag
|
|
125897
126330
|
});
|
|
125898
126331
|
const getTransferState = () => transferSession.getSnapshot();
|
|
@@ -125912,7 +126345,16 @@ function createWalletSession({
|
|
|
125912
126345
|
listener();
|
|
125913
126346
|
}
|
|
125914
126347
|
};
|
|
125915
|
-
const balance = createWalletBalance({
|
|
126348
|
+
const balance = createWalletBalance({
|
|
126349
|
+
wallet,
|
|
126350
|
+
diag,
|
|
126351
|
+
initialDisplayBalance: cachedBalance,
|
|
126352
|
+
onBalance: (value) => {
|
|
126353
|
+
writeCachedWalletBalance(localCache, { walletPK, network, balance: value }).catch(() => {});
|
|
126354
|
+
},
|
|
126355
|
+
onChange: publish
|
|
126356
|
+
});
|
|
126357
|
+
refreshWalletBalance = balance.getBalance;
|
|
125916
126358
|
const funding = createFundingAddress({ wallet, network, diag, onChange: publish });
|
|
125917
126359
|
const updateWalletData = createWalletData({
|
|
125918
126360
|
wallet,
|
|
@@ -125993,13 +126435,14 @@ function createWalletSession({
|
|
|
125993
126435
|
wallet,
|
|
125994
126436
|
network,
|
|
125995
126437
|
balance: balanceState.balance,
|
|
126438
|
+
displayBalance: balanceState.displayBalance,
|
|
125996
126439
|
satsBalance: balanceState.satsBalance,
|
|
125997
126440
|
tokenBalances: balanceState.tokenBalances,
|
|
125998
126441
|
fundingAddress: funding.getSnapshot(),
|
|
125999
126442
|
balanceReady: balanceState.balanceReady,
|
|
126000
126443
|
isBalanceLoading: balanceState.isBalanceLoading,
|
|
126001
126444
|
isWalletDataReady: true,
|
|
126002
|
-
isWalletDataLoaded: balanceState.balanceReady
|
|
126445
|
+
isWalletDataLoaded: balanceState.balanceReady || currentTransferState.txReady,
|
|
126003
126446
|
refresh: claims.refresh,
|
|
126004
126447
|
requestTransferDiscoveryHotWindow: polling.requestTransferDiscoveryHotWindow,
|
|
126005
126448
|
claimDeposits: claims.claimDeposits,
|
|
@@ -126091,7 +126534,7 @@ function createWalletSession({
|
|
|
126091
126534
|
};
|
|
126092
126535
|
}
|
|
126093
126536
|
var init_session4 = __esm(() => {
|
|
126094
|
-
|
|
126537
|
+
init_balance2();
|
|
126095
126538
|
init_claims();
|
|
126096
126539
|
init_funding();
|
|
126097
126540
|
init_lightning();
|
|
@@ -126100,6 +126543,7 @@ var init_session4 = __esm(() => {
|
|
|
126100
126543
|
init_send2();
|
|
126101
126544
|
init_transfers2();
|
|
126102
126545
|
init_withdraw();
|
|
126546
|
+
init_localdata();
|
|
126103
126547
|
});
|
|
126104
126548
|
|
|
126105
126549
|
// ../../shared/wallet/transferstore.js
|
|
@@ -126308,6 +126752,7 @@ function createTransferStore() {
|
|
|
126308
126752
|
transfers: state.historyTransfers,
|
|
126309
126753
|
walletPK: state.walletPK,
|
|
126310
126754
|
serverEndReached: state.serverEndReached,
|
|
126755
|
+
historyCount: state.historyCount,
|
|
126311
126756
|
nextOffset: state.nextOffset,
|
|
126312
126757
|
oldestTxMs: state.serverEndReached ? state.oldestVerifiedTxMs : null
|
|
126313
126758
|
};
|
|
@@ -169791,9 +170236,13 @@ function peerRecordFromDoc(snap) {
|
|
|
169791
170236
|
function peerRecordsFromSnapshot(snapshot) {
|
|
169792
170237
|
return snapshot.docs.map(peerRecordFromDoc).filter(Boolean);
|
|
169793
170238
|
}
|
|
169794
|
-
function avatarPath(uid) {
|
|
170239
|
+
function avatarPath(uid, version8) {
|
|
169795
170240
|
requireUid(uid);
|
|
169796
|
-
|
|
170241
|
+
const avatarVersion = readAvatarVersion(version8);
|
|
170242
|
+
if (!avatarVersion) {
|
|
170243
|
+
throw new Error("avatar version required");
|
|
170244
|
+
}
|
|
170245
|
+
return `${uid}/avatars/${avatarVersion}.webp`;
|
|
169797
170246
|
}
|
|
169798
170247
|
function reportEvidencePath(reporter, targetUid, evidenceId) {
|
|
169799
170248
|
if (!reporter || !targetUid || !evidenceId) {
|
|
@@ -169859,6 +170308,7 @@ function createFirebaseCloud({ db, auth: auth2, getAuth: getAuth2, functions: fu
|
|
|
169859
170308
|
}
|
|
169860
170309
|
let activeVaultSigner = null;
|
|
169861
170310
|
const localSessionTerminations = new Set;
|
|
170311
|
+
const pendingAvatars = new Map;
|
|
169862
170312
|
function pageTs(value) {
|
|
169863
170313
|
if (value instanceof Timestamp2) {
|
|
169864
170314
|
return value;
|
|
@@ -169941,7 +170391,12 @@ function createFirebaseCloud({ db, auth: auth2, getAuth: getAuth2, functions: fu
|
|
|
169941
170391
|
"Content-Type": upload?.metadata?.contentType || "application/octet-stream"
|
|
169942
170392
|
};
|
|
169943
170393
|
if (typeof uploadSignedStorageBytes === "function") {
|
|
169944
|
-
await uploadSignedStorageBytes(url, upload?.body, { ...signed, method, headers, metadata: upload?.metadata || {}, path: upload?.path || "" })
|
|
170394
|
+
await uploadSignedStorageBytes(url, upload?.body, { ...signed, method, headers, metadata: upload?.metadata || {}, path: upload?.path || "" }).catch((error) => {
|
|
170395
|
+
if (error?.status === 412 && (headers["X-Goog-If-Generation-Match"] === "0" || headers["x-goog-if-generation-match"] === "0")) {
|
|
170396
|
+
return true;
|
|
170397
|
+
}
|
|
170398
|
+
throw error;
|
|
170399
|
+
});
|
|
169945
170400
|
return true;
|
|
169946
170401
|
}
|
|
169947
170402
|
const payload = typeof Blob !== "undefined" && upload?.body instanceof Blob ? upload.body : toBytes2(upload?.body, "upload bytes");
|
|
@@ -169950,6 +170405,9 @@ function createFirebaseCloud({ db, auth: auth2, getAuth: getAuth2, functions: fu
|
|
|
169950
170405
|
headers,
|
|
169951
170406
|
body: payload
|
|
169952
170407
|
});
|
|
170408
|
+
if (response.status === 412 && (headers["X-Goog-If-Generation-Match"] === "0" || headers["x-goog-if-generation-match"] === "0")) {
|
|
170409
|
+
return true;
|
|
170410
|
+
}
|
|
169953
170411
|
if (!response.ok) {
|
|
169954
170412
|
const error = new Error(`signed upload failed (${response.status || 0})`);
|
|
169955
170413
|
error.status = response.status || 0;
|
|
@@ -170119,6 +170577,7 @@ function createFirebaseCloud({ db, auth: auth2, getAuth: getAuth2, functions: fu
|
|
|
170119
170577
|
}, onError);
|
|
170120
170578
|
}
|
|
170121
170579
|
async function logout() {
|
|
170580
|
+
pendingAvatars.clear();
|
|
170122
170581
|
await signOut(requireAuth());
|
|
170123
170582
|
return true;
|
|
170124
170583
|
}
|
|
@@ -170252,25 +170711,45 @@ function createFirebaseCloud({ db, auth: auth2, getAuth: getAuth2, functions: fu
|
|
|
170252
170711
|
await callFunction("acceptAgreement");
|
|
170253
170712
|
return true;
|
|
170254
170713
|
}
|
|
170255
|
-
async function
|
|
170714
|
+
async function setProfileAvatar(uid, data) {
|
|
170256
170715
|
requireUid(uid);
|
|
170257
|
-
|
|
170258
|
-
|
|
170259
|
-
|
|
170260
|
-
|
|
170261
|
-
|
|
170262
|
-
|
|
170263
|
-
|
|
170264
|
-
|
|
170265
|
-
|
|
170266
|
-
|
|
170267
|
-
|
|
170268
|
-
|
|
170269
|
-
|
|
170270
|
-
|
|
170271
|
-
|
|
170272
|
-
|
|
170273
|
-
|
|
170716
|
+
if (requireAuth().currentUser?.uid !== uid) {
|
|
170717
|
+
throw new Error("avatar account mismatch");
|
|
170718
|
+
}
|
|
170719
|
+
if (data == null) {
|
|
170720
|
+
pendingAvatars.delete(uid);
|
|
170721
|
+
const result = await callFunction("setAvatar", { body: null });
|
|
170722
|
+
if (result?.avatar != null) {
|
|
170723
|
+
throw new Error("avatar clear returned invalid state");
|
|
170724
|
+
}
|
|
170725
|
+
return { version: null };
|
|
170726
|
+
}
|
|
170727
|
+
const bytes = new Uint8Array(encryptedBytes(data, "avatar bytes"));
|
|
170728
|
+
const pending = { bytes, version: null, promise: null };
|
|
170729
|
+
const entries = pendingAvatars.get(uid) || [];
|
|
170730
|
+
pendingAvatars.set(uid, [...entries, pending]);
|
|
170731
|
+
pending.promise = callFunction("setAvatar", {
|
|
170732
|
+
body: cloudBytesBase64(bytes, "avatar bytes")
|
|
170733
|
+
}).then((result) => {
|
|
170734
|
+
const version8 = readAvatarVersion(result?.avatar);
|
|
170735
|
+
if (!version8) {
|
|
170736
|
+
throw new Error("avatar publish returned invalid version");
|
|
170737
|
+
}
|
|
170738
|
+
pending.version = version8;
|
|
170739
|
+
return version8;
|
|
170740
|
+
});
|
|
170741
|
+
try {
|
|
170742
|
+
return { version: await pending.promise };
|
|
170743
|
+
} catch (error) {
|
|
170744
|
+
const active = pendingAvatars.get(uid) || [];
|
|
170745
|
+
const remaining = active.filter((entry) => entry !== pending);
|
|
170746
|
+
if (remaining.length) {
|
|
170747
|
+
pendingAvatars.set(uid, remaining);
|
|
170748
|
+
} else {
|
|
170749
|
+
pendingAvatars.delete(uid);
|
|
170750
|
+
}
|
|
170751
|
+
throw error;
|
|
170752
|
+
}
|
|
170274
170753
|
}
|
|
170275
170754
|
async function writeProfileIdentity(identity) {
|
|
170276
170755
|
if (!identity || typeof identity !== "object" || Array.isArray(identity)) {
|
|
@@ -170407,13 +170886,28 @@ function createFirebaseCloud({ db, auth: auth2, getAuth: getAuth2, functions: fu
|
|
|
170407
170886
|
onUpdate?.(snap.exists() ? snap.data()?.active === true : false, { exists: snap.exists() });
|
|
170408
170887
|
}, onError);
|
|
170409
170888
|
}
|
|
170410
|
-
async function readPeerAvatar(uid) {
|
|
170411
|
-
|
|
170889
|
+
async function readPeerAvatar(uid, { version: version8 = null } = {}) {
|
|
170890
|
+
const avatarVersion = readAvatarVersion(version8);
|
|
170891
|
+
const entries = pendingAvatars.get(uid) || [];
|
|
170892
|
+
if (entries.length) {
|
|
170893
|
+
await Promise.allSettled(entries.map((entry) => entry.promise));
|
|
170894
|
+
const pending = entries.find((entry) => entry.version === avatarVersion);
|
|
170895
|
+
if (pending) {
|
|
170896
|
+
const active = pendingAvatars.get(uid) || [];
|
|
170897
|
+
const remaining = active.filter((entry) => entry !== pending);
|
|
170898
|
+
if (remaining.length) {
|
|
170899
|
+
pendingAvatars.set(uid, remaining);
|
|
170900
|
+
} else {
|
|
170901
|
+
pendingAvatars.delete(uid);
|
|
170902
|
+
}
|
|
170903
|
+
return new Uint8Array(pending.bytes);
|
|
170904
|
+
}
|
|
170905
|
+
}
|
|
170906
|
+
return readStorageFile(avatarPath(uid, avatarVersion));
|
|
170412
170907
|
}
|
|
170413
170908
|
async function peerAvatarUrl(uid, { version: version8 = null } = {}) {
|
|
170414
170909
|
const targetStorage = requireStorage2();
|
|
170415
|
-
|
|
170416
|
-
return avatarUrlWithVersion(url, version8);
|
|
170910
|
+
return getDownloadURL(ref(targetStorage, avatarPath(uid, version8)));
|
|
170417
170911
|
}
|
|
170418
170912
|
function profileQueryField(field2, { network } = {}) {
|
|
170419
170913
|
if (field2 === "walletPK") {
|
|
@@ -170464,20 +170958,12 @@ function createFirebaseCloud({ db, auth: auth2, getAuth: getAuth2, functions: fu
|
|
|
170464
170958
|
const snapshot = await getDocs(roleQuery);
|
|
170465
170959
|
return peerRecordsFromSnapshot(snapshot);
|
|
170466
170960
|
}
|
|
170467
|
-
async function
|
|
170961
|
+
async function uploadMedia(upload) {
|
|
170468
170962
|
const path = upload?.path;
|
|
170469
170963
|
if (!path)
|
|
170470
170964
|
throw new Error("media path required");
|
|
170471
|
-
|
|
170472
|
-
await
|
|
170473
|
-
return true;
|
|
170474
|
-
}
|
|
170475
|
-
async function uploadSharedMedia(upload) {
|
|
170476
|
-
const path = upload?.path;
|
|
170477
|
-
if (!path)
|
|
170478
|
-
throw new Error("shared media path required");
|
|
170479
|
-
const signed = await callFunction("reserveSharedMediaUpload", {
|
|
170480
|
-
sharedId: upload?.sharedId,
|
|
170965
|
+
getMediaFileRef(path);
|
|
170966
|
+
const signed = await callFunction("reserveMediaUpload", {
|
|
170481
170967
|
path,
|
|
170482
170968
|
size: uploadByteSize(upload?.body),
|
|
170483
170969
|
contentType: upload?.metadata?.contentType || "application/octet-stream"
|
|
@@ -170485,6 +170971,14 @@ function createFirebaseCloud({ db, auth: auth2, getAuth: getAuth2, functions: fu
|
|
|
170485
170971
|
await uploadSignedStorageFile(upload, signed?.upload);
|
|
170486
170972
|
return true;
|
|
170487
170973
|
}
|
|
170974
|
+
async function uploadChatMedia(upload) {
|
|
170975
|
+
getChatMediaFileRef(upload?.path);
|
|
170976
|
+
return uploadMedia(upload);
|
|
170977
|
+
}
|
|
170978
|
+
async function uploadSharedMedia(upload) {
|
|
170979
|
+
getSharedMediaFileRef(upload?.path);
|
|
170980
|
+
return uploadMedia(upload);
|
|
170981
|
+
}
|
|
170488
170982
|
async function readChatMedia(path) {
|
|
170489
170983
|
if (!path)
|
|
170490
170984
|
throw new Error("media path required");
|
|
@@ -170872,12 +171366,13 @@ function createFirebaseCloud({ db, auth: auth2, getAuth: getAuth2, functions: fu
|
|
|
170872
171366
|
}
|
|
170873
171367
|
};
|
|
170874
171368
|
}
|
|
170875
|
-
async function pushInbox(recipientUid, ping) {
|
|
171369
|
+
async function pushInbox(recipientUid, ping, options2 = {}) {
|
|
170876
171370
|
requireUid(recipientUid);
|
|
170877
171371
|
if (!ping)
|
|
170878
171372
|
throw new Error("inbox ping required");
|
|
170879
171373
|
await callFunction("push", {
|
|
170880
171374
|
recipientUid,
|
|
171375
|
+
notify: options2?.notify !== false,
|
|
170881
171376
|
ping: {
|
|
170882
171377
|
v: ping.v,
|
|
170883
171378
|
epk: ping.epk,
|
|
@@ -170916,7 +171411,9 @@ function createFirebaseCloud({ db, auth: auth2, getAuth: getAuth2, functions: fu
|
|
|
170916
171411
|
payload.onCommitted?.({ chatId, messageId });
|
|
170917
171412
|
let delivered = true;
|
|
170918
171413
|
if (payload.inbox?.recipientUid && payload.inbox?.ping) {
|
|
170919
|
-
delivered = await pushInbox(payload.inbox.recipientUid, payload.inbox.ping
|
|
171414
|
+
delivered = await pushInbox(payload.inbox.recipientUid, payload.inbox.ping, {
|
|
171415
|
+
notify: payload.inbox.notify !== false
|
|
171416
|
+
}).then(() => true, () => false);
|
|
170920
171417
|
}
|
|
170921
171418
|
return { chatId, messageId, delivered };
|
|
170922
171419
|
}
|
|
@@ -171169,18 +171666,19 @@ function createFirebaseCloud({ db, auth: auth2, getAuth: getAuth2, functions: fu
|
|
|
171169
171666
|
}
|
|
171170
171667
|
async function banAdminUser(uid, feature = "chat") {
|
|
171171
171668
|
requireUid(uid);
|
|
171172
|
-
await setDoc(doc(db, "moderation", uid), { banned: { [feature]: { until: null } } }, { merge: true });
|
|
171173
171669
|
if (feature === "avatar") {
|
|
171174
|
-
await
|
|
171175
|
-
|
|
171176
|
-
throw error;
|
|
171177
|
-
}
|
|
171178
|
-
});
|
|
171670
|
+
await callFunction("setAvatarModeration", { uid, banned: true });
|
|
171671
|
+
return true;
|
|
171179
171672
|
}
|
|
171673
|
+
await setDoc(doc(db, "moderation", uid), { banned: { [feature]: { until: null } } }, { merge: true });
|
|
171180
171674
|
return true;
|
|
171181
171675
|
}
|
|
171182
171676
|
async function unbanAdminUser(uid, feature = "chat") {
|
|
171183
171677
|
requireUid(uid);
|
|
171678
|
+
if (feature === "avatar") {
|
|
171679
|
+
await callFunction("setAvatarModeration", { uid, banned: false });
|
|
171680
|
+
return true;
|
|
171681
|
+
}
|
|
171184
171682
|
await setDoc(doc(db, "moderation", uid), { banned: { [feature]: deleteField() } }, { merge: true });
|
|
171185
171683
|
return true;
|
|
171186
171684
|
}
|
|
@@ -171218,9 +171716,7 @@ function createFirebaseCloud({ db, auth: auth2, getAuth: getAuth2, functions: fu
|
|
|
171218
171716
|
write: writeProfileIdentity
|
|
171219
171717
|
},
|
|
171220
171718
|
avatar: {
|
|
171221
|
-
|
|
171222
|
-
upload: uploadProfileAvatar,
|
|
171223
|
-
delete: deleteProfileAvatar
|
|
171719
|
+
set: setProfileAvatar
|
|
171224
171720
|
}
|
|
171225
171721
|
},
|
|
171226
171722
|
private: {
|
|
@@ -173810,13 +174306,6 @@ function cleanMessage(value, limit2, label = "message") {
|
|
|
173810
174306
|
throw new Error(`${label} must be ${limit2} characters or fewer`);
|
|
173811
174307
|
return message;
|
|
173812
174308
|
}
|
|
173813
|
-
function readAvatarGeneration(value) {
|
|
173814
|
-
const version8 = Number(value);
|
|
173815
|
-
if (!Number.isSafeInteger(version8) || version8 <= 0) {
|
|
173816
|
-
throw new Error("avatar upload did not return a valid generation");
|
|
173817
|
-
}
|
|
173818
|
-
return version8;
|
|
173819
|
-
}
|
|
173820
174309
|
function passkeyRows(linksList, passkeys, currentPasskeyId) {
|
|
173821
174310
|
return [...linksList, ...passkeys].sort((left, right) => (right.createdAt || 0) - (left.createdAt || 0)).map((row) => ({
|
|
173822
174311
|
...row,
|
|
@@ -173904,23 +174393,17 @@ function createRuntimeProductActions({
|
|
|
173904
174393
|
const user = await getUser();
|
|
173905
174394
|
if (!data)
|
|
173906
174395
|
throw new Error("avatar data required");
|
|
173907
|
-
|
|
173908
|
-
|
|
173909
|
-
}
|
|
173910
|
-
const
|
|
173911
|
-
await
|
|
173912
|
-
|
|
173913
|
-
return { avatar:
|
|
174396
|
+
if (options2.contentType && options2.contentType !== "image/webp") {
|
|
174397
|
+
throw new Error("avatar content type must be image/webp");
|
|
174398
|
+
}
|
|
174399
|
+
const result = await cloud.user.profile.avatar.set(user.uid, data);
|
|
174400
|
+
await user.refetchAvatar?.({ version: result.version });
|
|
174401
|
+
const updated = await getUser();
|
|
174402
|
+
return { avatar: updated.avatar || null, avatarVersion: result.version };
|
|
173914
174403
|
},
|
|
173915
174404
|
async deleteAvatar() {
|
|
173916
174405
|
const user = await getUser();
|
|
173917
|
-
|
|
173918
|
-
await cloud.user.profile.avatar.delete(user.uid);
|
|
173919
|
-
} catch (error) {
|
|
173920
|
-
if (error?.code !== "storage/object-not-found")
|
|
173921
|
-
throw error;
|
|
173922
|
-
}
|
|
173923
|
-
await cloud.user.profile.avatar.write(user.uid, null);
|
|
174406
|
+
await cloud.user.profile.avatar.set(user.uid, null);
|
|
173924
174407
|
user.clearAvatar?.();
|
|
173925
174408
|
return { deleted: true };
|
|
173926
174409
|
}
|
|
@@ -175688,6 +176171,7 @@ class VeylHeadlessClient {
|
|
|
175688
176171
|
this.userOwner.setNetwork(network);
|
|
175689
176172
|
}
|
|
175690
176173
|
});
|
|
176174
|
+
await opened.walletReady;
|
|
175691
176175
|
this.userSnapshot = this.userOwner.getSnapshot();
|
|
175692
176176
|
} catch (error) {
|
|
175693
176177
|
if (opened)
|