@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/index.js
CHANGED
|
@@ -6216,7 +6216,7 @@ var init_seed = __esm(() => {
|
|
|
6216
6216
|
});
|
|
6217
6217
|
|
|
6218
6218
|
// ../../shared/config.js
|
|
6219
|
-
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 =
|
|
6219
|
+
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;
|
|
6220
6220
|
var init_config = __esm(() => {
|
|
6221
6221
|
MINUTE_MS = 60 * MS_PER_SECOND;
|
|
6222
6222
|
HOUR_MS = 60 * MINUTE_MS;
|
|
@@ -6227,7 +6227,7 @@ var init_config = __esm(() => {
|
|
|
6227
6227
|
LOCAL_PROFILE_CACHE_MAX_AGE_MS = 30 * DAY_MS;
|
|
6228
6228
|
LOCAL_AVATAR_CACHE_MAX_BYTES = 128 * MIB_BYTES;
|
|
6229
6229
|
LOCAL_AVATAR_CACHE_MAX_AGE_MS = 30 * DAY_MS;
|
|
6230
|
-
AVATAR_IMAGE_MAX_BYTES =
|
|
6230
|
+
AVATAR_IMAGE_MAX_BYTES = 256 * KIB_BYTES;
|
|
6231
6231
|
CHAT_READY_DOWNLOAD_MAX_BYTES = 8 * MIB_BYTES;
|
|
6232
6232
|
CHAT_MESSAGE_FILE_CACHE_MAX_BYTES = 64 * MIB_BYTES;
|
|
6233
6233
|
CHAT_UNSAVED_TTL_MS = CHAT_UNSAVED_TTL_DAYS * DAY_MS;
|
|
@@ -7743,20 +7743,17 @@ function expectedSigningKeys(pair, signingKeysByChatKey) {
|
|
|
7743
7743
|
}
|
|
7744
7744
|
return values;
|
|
7745
7745
|
}
|
|
7746
|
-
async function
|
|
7746
|
+
async function preverifyExpectedSigner(pair, sig, bytes, options = {}) {
|
|
7747
7747
|
if (!options?.crypto?.preverifyBeforeOpen) {
|
|
7748
|
-
return
|
|
7749
|
-
}
|
|
7750
|
-
const signingKeysByChatKey = expectedSigningKeys(pair, options?.signingKeysByChatKey);
|
|
7751
|
-
if (signingKeysByChatKey.length < 2) {
|
|
7752
|
-
return true;
|
|
7748
|
+
return "";
|
|
7753
7749
|
}
|
|
7754
|
-
|
|
7750
|
+
const signingPublicKeys = expectedSigningKeys(pair, options?.signingKeysByChatKey);
|
|
7751
|
+
for (const signingPublicKey of signingPublicKeys) {
|
|
7755
7752
|
if (await verifyMsgSignature(signingPublicKey, sig, bytes, options)) {
|
|
7756
|
-
return
|
|
7753
|
+
return signingPublicKey;
|
|
7757
7754
|
}
|
|
7758
7755
|
}
|
|
7759
|
-
return
|
|
7756
|
+
return null;
|
|
7760
7757
|
}
|
|
7761
7758
|
async function sealMsg(pair, message, options = {}) {
|
|
7762
7759
|
const head = getHead(pair, message);
|
|
@@ -7777,14 +7774,16 @@ async function openMsg(pair, data, options = {}) {
|
|
|
7777
7774
|
const { suite, flags, nonce, sig, ct } = unpackMsgBody(data.body);
|
|
7778
7775
|
const aad = getMsgAad(pair, head, suite, flags);
|
|
7779
7776
|
const signatureInput = getSignatureInput(aad, nonce, ct);
|
|
7780
|
-
|
|
7777
|
+
const preverifiedSigner = await preverifyExpectedSigner(pair, sig, signatureInput, options);
|
|
7778
|
+
if (preverifiedSigner == null) {
|
|
7781
7779
|
throw new Error("invalid chat action signature");
|
|
7782
7780
|
}
|
|
7783
7781
|
const plaintext = await openMsgPlaintext(pair, nonce, ct, aad, options);
|
|
7784
7782
|
try {
|
|
7785
7783
|
const action = JSON.parse(decoder.decode(plaintext));
|
|
7786
7784
|
const normalized = normalizeOpenedAction(pair, head, action, options);
|
|
7787
|
-
|
|
7785
|
+
const validSignature = preverifiedSigner ? normalized.signingPublicKey === preverifiedSigner : await verifyMsgSignature(normalized.signingPublicKey, sig, signatureInput, options);
|
|
7786
|
+
if (!validSignature) {
|
|
7788
7787
|
throw new Error("invalid chat action signature");
|
|
7789
7788
|
}
|
|
7790
7789
|
return {
|
|
@@ -7858,40 +7857,120 @@ var init_protocol = __esm(() => {
|
|
|
7858
7857
|
});
|
|
7859
7858
|
|
|
7860
7859
|
// ../../shared/chat/pairs.js
|
|
7860
|
+
function accountGeneration(chatPK) {
|
|
7861
|
+
return accountGenerations.get(cleanText(chatPK)) || 0;
|
|
7862
|
+
}
|
|
7861
7863
|
function getChatPairKey(chatPK, peerChatPK, chatId = "") {
|
|
7862
7864
|
if (!chatPK || !peerChatPK)
|
|
7863
7865
|
return null;
|
|
7864
7866
|
return `${cleanText(chatPK)}|${cleanText(peerChatPK)}|${cleanText(chatId)}`;
|
|
7865
7867
|
}
|
|
7866
|
-
function
|
|
7867
|
-
|
|
7868
|
-
|
|
7868
|
+
function closeEntry(entry) {
|
|
7869
|
+
if (!entry || entry.closed || entry.leases > 0) {
|
|
7870
|
+
return;
|
|
7869
7871
|
}
|
|
7870
|
-
|
|
7872
|
+
entry.closed = true;
|
|
7873
|
+
closeChatPair(entry.pair);
|
|
7871
7874
|
}
|
|
7872
|
-
|
|
7875
|
+
function retireEntry(entry) {
|
|
7876
|
+
if (!entry || entry.retired) {
|
|
7877
|
+
return;
|
|
7878
|
+
}
|
|
7879
|
+
entry.retired = true;
|
|
7880
|
+
closeEntry(entry);
|
|
7881
|
+
}
|
|
7882
|
+
function releaseEntry(entry) {
|
|
7883
|
+
if (!entry || entry.leases <= 0) {
|
|
7884
|
+
return;
|
|
7885
|
+
}
|
|
7886
|
+
entry.leases -= 1;
|
|
7887
|
+
if (entry.retired) {
|
|
7888
|
+
closeEntry(entry);
|
|
7889
|
+
}
|
|
7890
|
+
}
|
|
7891
|
+
function evictOverflow() {
|
|
7892
|
+
while (pairCache.size > MAX_PAIR_CACHE) {
|
|
7893
|
+
const firstKey = pairCache.keys().next().value;
|
|
7894
|
+
if (!firstKey) {
|
|
7895
|
+
return;
|
|
7896
|
+
}
|
|
7897
|
+
const entry = pairCache.get(firstKey);
|
|
7898
|
+
pairCache.delete(firstKey);
|
|
7899
|
+
retireEntry(entry);
|
|
7900
|
+
}
|
|
7901
|
+
}
|
|
7902
|
+
function clearChatPairCache(chatPK = "") {
|
|
7903
|
+
const account = cleanText(chatPK);
|
|
7904
|
+
if (!account) {
|
|
7905
|
+
cacheGeneration += 1;
|
|
7906
|
+
accountGenerations.clear();
|
|
7907
|
+
for (const entry of pairCache.values()) {
|
|
7908
|
+
retireEntry(entry);
|
|
7909
|
+
}
|
|
7910
|
+
pairCache.clear();
|
|
7911
|
+
return;
|
|
7912
|
+
}
|
|
7913
|
+
accountGenerations.set(account, accountGeneration(account) + 1);
|
|
7914
|
+
for (const [key, entry] of pairCache) {
|
|
7915
|
+
if (entry.account !== account) {
|
|
7916
|
+
continue;
|
|
7917
|
+
}
|
|
7918
|
+
pairCache.delete(key);
|
|
7919
|
+
retireEntry(entry);
|
|
7920
|
+
}
|
|
7921
|
+
}
|
|
7922
|
+
async function acquireCachedPair(chatPK, chatPrivKey, peerChatPK, options = {}) {
|
|
7923
|
+
const account = cleanText(chatPK);
|
|
7873
7924
|
const chatId = cleanText(options?.chatId);
|
|
7874
7925
|
const key = getChatPairKey(chatPK, peerChatPK, chatId);
|
|
7926
|
+
const generation = cacheGeneration;
|
|
7927
|
+
const accountVersion = accountGeneration(account);
|
|
7875
7928
|
if (!key) {
|
|
7876
|
-
|
|
7929
|
+
const pair = await openChatPair(chatPK, chatPrivKey, peerChatPK, { chatId });
|
|
7930
|
+
const entry2 = { pair, leases: 1, retired: true, closed: false };
|
|
7931
|
+
return {
|
|
7932
|
+
pair,
|
|
7933
|
+
release: () => releaseEntry(entry2)
|
|
7934
|
+
};
|
|
7877
7935
|
}
|
|
7878
|
-
|
|
7879
|
-
if (
|
|
7880
|
-
|
|
7881
|
-
|
|
7882
|
-
|
|
7883
|
-
|
|
7884
|
-
|
|
7885
|
-
|
|
7886
|
-
|
|
7887
|
-
|
|
7936
|
+
let entry = pairCache.get(key);
|
|
7937
|
+
if (!entry) {
|
|
7938
|
+
const pair = await openChatPair(chatPK, chatPrivKey, peerChatPK, { chatId });
|
|
7939
|
+
if (generation !== cacheGeneration || accountVersion !== accountGeneration(account)) {
|
|
7940
|
+
const staleEntry = { pair, leases: 1, retired: true, closed: false };
|
|
7941
|
+
return {
|
|
7942
|
+
pair,
|
|
7943
|
+
release: () => releaseEntry(staleEntry)
|
|
7944
|
+
};
|
|
7945
|
+
}
|
|
7946
|
+
entry = pairCache.get(key);
|
|
7947
|
+
if (entry) {
|
|
7948
|
+
closeChatPair(pair);
|
|
7949
|
+
} else {
|
|
7950
|
+
entry = { account, pair, leases: 0, retired: false, closed: false };
|
|
7951
|
+
pairCache.set(key, entry);
|
|
7952
|
+
evictOverflow();
|
|
7888
7953
|
}
|
|
7954
|
+
} else {
|
|
7955
|
+
pairCache.delete(key);
|
|
7956
|
+
pairCache.set(key, entry);
|
|
7957
|
+
}
|
|
7958
|
+
entry.leases += 1;
|
|
7959
|
+
return {
|
|
7960
|
+
pair: entry.pair,
|
|
7961
|
+
release: () => releaseEntry(entry)
|
|
7962
|
+
};
|
|
7963
|
+
}
|
|
7964
|
+
async function withCachedPair(chatPK, chatPrivKey, peerChatPK, options, runWithPair) {
|
|
7965
|
+
const { pair, release } = await acquireCachedPair(chatPK, chatPrivKey, peerChatPK, options);
|
|
7966
|
+
try {
|
|
7967
|
+
return await runWithPair(pair);
|
|
7968
|
+
} finally {
|
|
7969
|
+
release();
|
|
7889
7970
|
}
|
|
7890
|
-
return pair;
|
|
7891
7971
|
}
|
|
7892
7972
|
async function resolveLinkId(chatPK, chatPrivKey, peerChatPK) {
|
|
7893
|
-
|
|
7894
|
-
return pair?.linkId || null;
|
|
7973
|
+
return withCachedPair(chatPK, chatPrivKey, peerChatPK, {}, (pair) => pair?.linkId || null);
|
|
7895
7974
|
}
|
|
7896
7975
|
async function resolvePeerChat(cloud, chatPK, chatPrivateKey, peerChatPK, options = {}) {
|
|
7897
7976
|
const existingChatId = cleanText(options?.chatId);
|
|
@@ -7922,13 +8001,14 @@ async function resolvePeerChat(cloud, chatPK, chatPrivateKey, peerChatPK, option
|
|
|
7922
8001
|
exists: linkChat?.exists === true
|
|
7923
8002
|
};
|
|
7924
8003
|
}
|
|
7925
|
-
var pairCache, MAX_PAIR_CACHE;
|
|
8004
|
+
var pairCache, MAX_PAIR_CACHE, cacheGeneration = 0, accountGenerations;
|
|
7926
8005
|
var init_pairs = __esm(() => {
|
|
7927
8006
|
init_config();
|
|
7928
8007
|
init_chat();
|
|
7929
8008
|
init_protocol();
|
|
7930
8009
|
pairCache = new Map;
|
|
7931
8010
|
MAX_PAIR_CACHE = CHAT_PAIR_CACHE_LIMIT;
|
|
8011
|
+
accountGenerations = new Map;
|
|
7932
8012
|
});
|
|
7933
8013
|
|
|
7934
8014
|
// ../../shared/utils/diagnostics.js
|
|
@@ -8081,14 +8161,16 @@ function lockWallet(wallet) {
|
|
|
8081
8161
|
cleanup?.catch?.(() => {});
|
|
8082
8162
|
} catch {}
|
|
8083
8163
|
}
|
|
8084
|
-
function lockChat(chatPrivateKey) {
|
|
8164
|
+
function lockChat(chatPrivateKey, chatPK = "") {
|
|
8085
8165
|
try {
|
|
8086
8166
|
if (chatPrivateKey) {
|
|
8087
8167
|
chatPrivateKey.fill(0);
|
|
8088
8168
|
}
|
|
8089
8169
|
} catch {}
|
|
8090
8170
|
try {
|
|
8091
|
-
|
|
8171
|
+
if (chatPK) {
|
|
8172
|
+
clearChatPairCache(chatPK);
|
|
8173
|
+
}
|
|
8092
8174
|
} catch {}
|
|
8093
8175
|
}
|
|
8094
8176
|
var init_vault = __esm(() => {
|
|
@@ -8108,7 +8190,7 @@ function walletPubkey(value) {
|
|
|
8108
8190
|
}
|
|
8109
8191
|
return key;
|
|
8110
8192
|
}
|
|
8111
|
-
function closeSessionResources({ wallet, chatPrivateKey, localCache, vaultAccess, vaultSigner } = {}) {
|
|
8193
|
+
function closeSessionResources({ wallet, chatPK, chatPrivateKey, localCache, vaultAccess, vaultSigner } = {}) {
|
|
8112
8194
|
try {
|
|
8113
8195
|
vaultAccess?.close?.();
|
|
8114
8196
|
} catch {}
|
|
@@ -8119,7 +8201,7 @@ function closeSessionResources({ wallet, chatPrivateKey, localCache, vaultAccess
|
|
|
8119
8201
|
localCache?.close?.();
|
|
8120
8202
|
} catch {}
|
|
8121
8203
|
lockWallet(wallet);
|
|
8122
|
-
lockChat(chatPrivateKey);
|
|
8204
|
+
lockChat(chatPrivateKey, chatPK);
|
|
8123
8205
|
}
|
|
8124
8206
|
function createAccountSession(resources = {}) {
|
|
8125
8207
|
let closed = false;
|
|
@@ -8210,6 +8292,32 @@ function notifySeedDecrypted(callback, markDiag2, source) {
|
|
|
8210
8292
|
failed(error);
|
|
8211
8293
|
}
|
|
8212
8294
|
}
|
|
8295
|
+
function startWalletBoot(bootWallet2, walletMnemonic, user, options) {
|
|
8296
|
+
let closed = false;
|
|
8297
|
+
let handedOff = false;
|
|
8298
|
+
let wallet = null;
|
|
8299
|
+
const result = Promise.resolve().then(() => bootWallet2(walletMnemonic, user, options)).then((identity) => {
|
|
8300
|
+
wallet = identity?.wallet || null;
|
|
8301
|
+
if (closed && wallet) {
|
|
8302
|
+
lockWallet(wallet);
|
|
8303
|
+
}
|
|
8304
|
+
return identity;
|
|
8305
|
+
});
|
|
8306
|
+
return {
|
|
8307
|
+
result,
|
|
8308
|
+
handoff() {
|
|
8309
|
+
handedOff = true;
|
|
8310
|
+
},
|
|
8311
|
+
close() {
|
|
8312
|
+
if (closed)
|
|
8313
|
+
return;
|
|
8314
|
+
closed = true;
|
|
8315
|
+
if (wallet && !handedOff) {
|
|
8316
|
+
lockWallet(wallet);
|
|
8317
|
+
}
|
|
8318
|
+
}
|
|
8319
|
+
};
|
|
8320
|
+
}
|
|
8213
8321
|
async function openVaultAccountSession(vault, password, options = {}) {
|
|
8214
8322
|
const {
|
|
8215
8323
|
uid,
|
|
@@ -8251,6 +8359,7 @@ async function openVaultAccountSession(vault, password, options = {}) {
|
|
|
8251
8359
|
throw new Error("unlockSettings missing");
|
|
8252
8360
|
const { decryptSeed: decryptSeed2, unpackVaultSeedData } = vaultCrypto;
|
|
8253
8361
|
let wallet = null;
|
|
8362
|
+
let chatPK = "";
|
|
8254
8363
|
let chatPrivateKey = null;
|
|
8255
8364
|
let localCache = null;
|
|
8256
8365
|
let masterSeed = null;
|
|
@@ -8261,6 +8370,7 @@ async function openVaultAccountSession(vault, password, options = {}) {
|
|
|
8261
8370
|
let vaultSigner = null;
|
|
8262
8371
|
let vaultAccess = null;
|
|
8263
8372
|
let vaultAccessResult = null;
|
|
8373
|
+
let walletBoot = null;
|
|
8264
8374
|
let network;
|
|
8265
8375
|
try {
|
|
8266
8376
|
onStage?.("unlocking");
|
|
@@ -8329,46 +8439,18 @@ async function openVaultAccountSession(vault, password, options = {}) {
|
|
|
8329
8439
|
onStage?.("wallet");
|
|
8330
8440
|
const walletStartedAt = Date.now();
|
|
8331
8441
|
mark(diag, "vault.unlock.wallet.start", { source });
|
|
8332
|
-
|
|
8333
|
-
wallet = walletIdentity?.wallet;
|
|
8334
|
-
const walletPK = walletPubkey(walletIdentity?.walletPK);
|
|
8335
|
-
mark(diag, "vault.unlock.wallet.done", { elapsedMs: Date.now() - walletStartedAt, source });
|
|
8336
|
-
requireCurrent(isCurrent);
|
|
8442
|
+
walletBoot = startWalletBoot(bootWallet2, walletMnemonic, user, { network, diag });
|
|
8337
8443
|
onStage?.("chat");
|
|
8338
8444
|
const chatStartedAt = Date.now();
|
|
8339
8445
|
mark(diag, "vault.unlock.chat.start", { source });
|
|
8340
8446
|
const chatIdentity = await bootChat2(chatSeed, user, { diag });
|
|
8341
8447
|
chatPrivateKey = chatIdentity?.chatPrivateKey;
|
|
8342
|
-
|
|
8448
|
+
chatPK = cleanText(chatIdentity?.chatPK);
|
|
8343
8449
|
if (!chatPrivateKey || !chatPK)
|
|
8344
8450
|
throw new Error("chat identity missing");
|
|
8345
8451
|
chatSeed = null;
|
|
8346
8452
|
mark(diag, "vault.unlock.chat.done", { elapsedMs: Date.now() - chatStartedAt, source });
|
|
8347
8453
|
requireCurrent(isCurrent);
|
|
8348
|
-
const identityPayload = {};
|
|
8349
|
-
if (walletIdentity?.walletPKNeedsWrite) {
|
|
8350
|
-
identityPayload.walletPK = walletPK;
|
|
8351
|
-
identityPayload.network = network;
|
|
8352
|
-
}
|
|
8353
|
-
if (chatIdentity?.chatPKNeedsWrite) {
|
|
8354
|
-
identityPayload.chatPK = chatPK;
|
|
8355
|
-
}
|
|
8356
|
-
const identityFields = Object.keys(identityPayload);
|
|
8357
|
-
let identityResult = null;
|
|
8358
|
-
if (identityFields.length) {
|
|
8359
|
-
const identitiesStartedAt = Date.now();
|
|
8360
|
-
mark(diag, "vault.unlock.identities.start", { source, fields: identityFields });
|
|
8361
|
-
identityResult = cloud.user.profile.identity.write(identityPayload).then(() => {
|
|
8362
|
-
mark(diag, "vault.unlock.identities.done", {
|
|
8363
|
-
elapsedMs: Date.now() - identitiesStartedAt,
|
|
8364
|
-
source,
|
|
8365
|
-
fields: identityFields
|
|
8366
|
-
});
|
|
8367
|
-
return { error: null };
|
|
8368
|
-
}, (error) => ({ error }));
|
|
8369
|
-
} else {
|
|
8370
|
-
mark(diag, "vault.unlock.identities.skip", { source });
|
|
8371
|
-
}
|
|
8372
8454
|
const cacheStartedAt = Date.now();
|
|
8373
8455
|
mark(diag, "vault.unlock.localCache.start", { source });
|
|
8374
8456
|
localCache = await openLocalCache(cacheKey, { uid, network });
|
|
@@ -8376,20 +8458,16 @@ async function openVaultAccountSession(vault, password, options = {}) {
|
|
|
8376
8458
|
cleanBytes(cacheKey);
|
|
8377
8459
|
cacheKey = null;
|
|
8378
8460
|
requireCurrent(isCurrent);
|
|
8379
|
-
const identityWrite = await identityResult;
|
|
8380
|
-
if (identityWrite?.error)
|
|
8381
|
-
throw identityWrite.error;
|
|
8382
|
-
requireCurrent(isCurrent);
|
|
8383
8461
|
const signatureResult = await vaultAccessResult;
|
|
8384
8462
|
if (signatureResult.error)
|
|
8385
8463
|
throw signatureResult.error;
|
|
8386
8464
|
vaultAccess = signatureResult.access;
|
|
8387
8465
|
requireCurrent(isCurrent);
|
|
8388
|
-
|
|
8466
|
+
const session = createAccountSession({
|
|
8389
8467
|
uid,
|
|
8390
8468
|
network,
|
|
8391
|
-
wallet,
|
|
8392
|
-
walletPK,
|
|
8469
|
+
wallet: null,
|
|
8470
|
+
walletPK: null,
|
|
8393
8471
|
chatPK,
|
|
8394
8472
|
chatPrivateKey,
|
|
8395
8473
|
localCache,
|
|
@@ -8397,12 +8475,56 @@ async function openVaultAccountSession(vault, password, options = {}) {
|
|
|
8397
8475
|
vaultAccess,
|
|
8398
8476
|
vaultPK: vaultSigner.publicKey
|
|
8399
8477
|
});
|
|
8478
|
+
session.own(walletBoot);
|
|
8479
|
+
const walletReady = walletBoot.result.then(async (walletIdentity) => {
|
|
8480
|
+
if (session.closed)
|
|
8481
|
+
throw new Error("account session closed");
|
|
8482
|
+
const readyWallet = walletIdentity?.wallet;
|
|
8483
|
+
const walletPK = walletPubkey(walletIdentity?.walletPK);
|
|
8484
|
+
if (!readyWallet)
|
|
8485
|
+
throw new Error("wallet missing");
|
|
8486
|
+
mark(diag, "vault.unlock.wallet.done", { elapsedMs: Date.now() - walletStartedAt, source });
|
|
8487
|
+
const identityPayload = {};
|
|
8488
|
+
if (walletIdentity?.walletPKNeedsWrite) {
|
|
8489
|
+
identityPayload.walletPK = walletPK;
|
|
8490
|
+
identityPayload.network = network;
|
|
8491
|
+
}
|
|
8492
|
+
if (chatIdentity?.chatPKNeedsWrite) {
|
|
8493
|
+
identityPayload.chatPK = chatPK;
|
|
8494
|
+
}
|
|
8495
|
+
const identityFields = Object.keys(identityPayload);
|
|
8496
|
+
if (identityFields.length) {
|
|
8497
|
+
const identitiesStartedAt = Date.now();
|
|
8498
|
+
mark(diag, "vault.unlock.identities.start", { source, fields: identityFields });
|
|
8499
|
+
await cloud.user.profile.identity.write(identityPayload);
|
|
8500
|
+
mark(diag, "vault.unlock.identities.done", {
|
|
8501
|
+
elapsedMs: Date.now() - identitiesStartedAt,
|
|
8502
|
+
source,
|
|
8503
|
+
fields: identityFields
|
|
8504
|
+
});
|
|
8505
|
+
} else {
|
|
8506
|
+
mark(diag, "vault.unlock.identities.skip", { source });
|
|
8507
|
+
}
|
|
8508
|
+
if (session.closed)
|
|
8509
|
+
throw new Error("account session closed");
|
|
8510
|
+
walletBoot.handoff();
|
|
8511
|
+
session.wallet = readyWallet;
|
|
8512
|
+
session.walletPK = walletPK;
|
|
8513
|
+
return { wallet: readyWallet, walletPK };
|
|
8514
|
+
}).catch((error) => {
|
|
8515
|
+
walletBoot.close();
|
|
8516
|
+
throw error;
|
|
8517
|
+
});
|
|
8518
|
+
walletReady.catch(() => {});
|
|
8519
|
+
session.walletReady = walletReady;
|
|
8520
|
+
return session;
|
|
8400
8521
|
} catch (error) {
|
|
8522
|
+
walletBoot?.close();
|
|
8401
8523
|
if (vaultAccessResult && !vaultAccess) {
|
|
8402
8524
|
const signatureResult = await vaultAccessResult;
|
|
8403
8525
|
vaultAccess = signatureResult.access;
|
|
8404
8526
|
}
|
|
8405
|
-
closeSessionResources({ wallet, chatPrivateKey, localCache, vaultAccess, vaultSigner });
|
|
8527
|
+
closeSessionResources({ wallet, chatPK, chatPrivateKey, localCache, vaultAccess, vaultSigner });
|
|
8406
8528
|
throw error;
|
|
8407
8529
|
} finally {
|
|
8408
8530
|
cleanBytes(masterSeed, walletEntropy, chatSeed, cacheKey, settingsKey);
|
|
@@ -8417,6 +8539,7 @@ async function openAccountSessionFromSecrets(walletEntropy, chatSeed, masterSeed
|
|
|
8417
8539
|
}
|
|
8418
8540
|
const walletMnemonic = mnemonicFromWalletEntropy(walletEntropy);
|
|
8419
8541
|
let wallet = null;
|
|
8542
|
+
let chatPK = "";
|
|
8420
8543
|
let chatPrivateKey = null;
|
|
8421
8544
|
let chatPubKey = null;
|
|
8422
8545
|
let vaultSigner = null;
|
|
@@ -8445,10 +8568,11 @@ async function openAccountSessionFromSecrets(walletEntropy, chatSeed, masterSeed
|
|
|
8445
8568
|
throw new Error("vault signature uid missing");
|
|
8446
8569
|
vaultAccess = await cloud.auth.vaultSignature.open(vaultSigner);
|
|
8447
8570
|
}
|
|
8571
|
+
chatPK = toHex(chatPubKey);
|
|
8448
8572
|
return createAccountSession({
|
|
8449
8573
|
wallet,
|
|
8450
8574
|
walletPK,
|
|
8451
|
-
chatPK
|
|
8575
|
+
chatPK,
|
|
8452
8576
|
chatPrivateKey,
|
|
8453
8577
|
localCache,
|
|
8454
8578
|
network,
|
|
@@ -8457,7 +8581,7 @@ async function openAccountSessionFromSecrets(walletEntropy, chatSeed, masterSeed
|
|
|
8457
8581
|
vaultPK: vaultSigner.publicKey
|
|
8458
8582
|
});
|
|
8459
8583
|
} catch (error) {
|
|
8460
|
-
closeSessionResources({ wallet, chatPrivateKey, localCache, vaultAccess, vaultSigner });
|
|
8584
|
+
closeSessionResources({ wallet, chatPK, chatPrivateKey, localCache, vaultAccess, vaultSigner });
|
|
8461
8585
|
throw error;
|
|
8462
8586
|
} finally {
|
|
8463
8587
|
cleanBytes(chatSeed, chatPubKey);
|
|
@@ -8484,9 +8608,10 @@ var init_session = __esm(() => {
|
|
|
8484
8608
|
});
|
|
8485
8609
|
|
|
8486
8610
|
// ../../shared/community.js
|
|
8487
|
-
var COMMUNITY_RULES_VERSION = "2026-05-11.1", COMMUNITY_SECTIONS;
|
|
8611
|
+
var COMMUNITY_RULES_VERSION = "2026-05-11.1", COMMUNITY_SUPPORT_EMAIL, COMMUNITY_SECTIONS;
|
|
8488
8612
|
var init_community = __esm(() => {
|
|
8489
8613
|
init_links();
|
|
8614
|
+
COMMUNITY_SUPPORT_EMAIL = links.contact.replace("mailto:", "");
|
|
8490
8615
|
COMMUNITY_SECTIONS = [
|
|
8491
8616
|
{
|
|
8492
8617
|
title: "Use veyl directly and lawfully",
|
|
@@ -8526,7 +8651,7 @@ var init_community = __esm(() => {
|
|
|
8526
8651
|
{
|
|
8527
8652
|
title: "Reporting and support",
|
|
8528
8653
|
body: [
|
|
8529
|
-
`If someone is abusing veyl, contact us at ${
|
|
8654
|
+
`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.`,
|
|
8530
8655
|
"Because veyl uses end-to-end encryption, we may rely on reports, account-level signals, and evidence you submit when reviewing abuse."
|
|
8531
8656
|
]
|
|
8532
8657
|
}
|
|
@@ -106243,18 +106368,13 @@ var init_values = __esm(() => {
|
|
|
106243
106368
|
|
|
106244
106369
|
// ../../shared/avatar.js
|
|
106245
106370
|
function readAvatarVersion(value) {
|
|
106246
|
-
|
|
106247
|
-
|
|
106248
|
-
}
|
|
106249
|
-
const version = Number(value);
|
|
106250
|
-
return Number.isSafeInteger(version) && version >= 0 ? version : null;
|
|
106251
|
-
}
|
|
106252
|
-
function avatarUrlWithVersion(url, version) {
|
|
106253
|
-
if (!url)
|
|
106254
|
-
return null;
|
|
106255
|
-
return version == null ? url : `${url}${url.includes("?") ? "&" : "?"}v=${encodeURIComponent(String(version))}`;
|
|
106371
|
+
const version = typeof value === "string" ? value.trim().toLowerCase() : "";
|
|
106372
|
+
return AVATAR_VERSION_RE.test(version) ? version : null;
|
|
106256
106373
|
}
|
|
106257
|
-
var
|
|
106374
|
+
var AVATAR_VERSION_RE;
|
|
106375
|
+
var init_avatar = __esm(() => {
|
|
106376
|
+
AVATAR_VERSION_RE = /^[0-9a-f]{64}$/;
|
|
106377
|
+
});
|
|
106258
106378
|
|
|
106259
106379
|
// ../../shared/moderation.js
|
|
106260
106380
|
function banUntilMs(ban) {
|
|
@@ -106532,11 +106652,16 @@ function createUser({ cloud, network, avatarCache = null, diag = null, onSession
|
|
|
106532
106652
|
markDiag(diag, "user.avatar.fetch.start", { force: !!force, persist: !!persist, hasVersion: avatarVersion != null });
|
|
106533
106653
|
try {
|
|
106534
106654
|
const promise = (async () => {
|
|
106535
|
-
|
|
106536
|
-
|
|
106537
|
-
|
|
106655
|
+
if (persist && avatarVersion != null && avatarCache && typeof cloud.peer.avatar.read === "function") {
|
|
106656
|
+
try {
|
|
106657
|
+
const bytes = await cloud.peer.avatar.read(uid, { version: avatarVersion });
|
|
106658
|
+
const cachedAvatar = await writeCachedAvatar(uid, { version: avatarVersion, bytes });
|
|
106659
|
+
if (cachedAvatar) {
|
|
106660
|
+
return cachedAvatar;
|
|
106661
|
+
}
|
|
106662
|
+
} catch {}
|
|
106538
106663
|
}
|
|
106539
|
-
return
|
|
106664
|
+
return cloud.peer.avatar.url(uid, { version: avatarVersion });
|
|
106540
106665
|
})().then((nextAvatar) => {
|
|
106541
106666
|
markDone(diag, "user.avatar.fetch", startedAt, { found: !!nextAvatar, hasVersion: avatarVersion != null });
|
|
106542
106667
|
if (!nextAvatar || avatarFetch.uid !== uid || avatarFetch.key !== key) {
|
|
@@ -106876,10 +107001,12 @@ function createUser({ cloud, network, avatarCache = null, diag = null, onSession
|
|
|
106876
107001
|
}
|
|
106877
107002
|
function refetchAvatar(options = {}) {
|
|
106878
107003
|
const requestedVersion = readAvatarVersion(options?.version);
|
|
106879
|
-
const
|
|
106880
|
-
|
|
106881
|
-
|
|
106882
|
-
|
|
107004
|
+
const nextVersion = requestedVersion ?? state.avatarVersion;
|
|
107005
|
+
return fetchAvatar(state.uid, {
|
|
107006
|
+
force: options?.force === true || state.avatarVersion !== nextVersion || !state.avatar,
|
|
107007
|
+
persist: options?.persist !== false,
|
|
107008
|
+
version: nextVersion
|
|
107009
|
+
});
|
|
106883
107010
|
}
|
|
106884
107011
|
function setNetwork(nextNetwork) {
|
|
106885
107012
|
if (activeNetwork === nextNetwork)
|
|
@@ -107147,7 +107274,7 @@ function getSubtleCrypto() {
|
|
|
107147
107274
|
async function importAesKey(key, usages) {
|
|
107148
107275
|
return getSubtleCrypto().importKey("raw", toBytes32(key, "file key"), { name: "AES-GCM" }, false, usages);
|
|
107149
107276
|
}
|
|
107150
|
-
async function sealFile(
|
|
107277
|
+
async function sealFile(key, bytes, scope) {
|
|
107151
107278
|
const fileKey = new Uint8Array(toBytes32(key, "file key"));
|
|
107152
107279
|
try {
|
|
107153
107280
|
const cryptoKey = await importAesKey(fileKey, ["encrypt"]);
|
|
@@ -107310,20 +107437,22 @@ async function toUploadBytes(data) {
|
|
|
107310
107437
|
}
|
|
107311
107438
|
return toBytes(data, "upload bytes");
|
|
107312
107439
|
}
|
|
107313
|
-
async function makeChatFileUploadPayload(
|
|
107314
|
-
const
|
|
107440
|
+
async function makeChatFileUploadPayload(chatId, cid, data, { cacheControl = "private, max-age=0, no-transform" } = {}) {
|
|
107441
|
+
const nextChatId = cleanMediaChatId(chatId);
|
|
107315
107442
|
const mediaId = makeChatMediaId();
|
|
107316
|
-
const path = mediaFilePath(
|
|
107443
|
+
const path = mediaFilePath(nextChatId, mediaId);
|
|
107317
107444
|
const expiresAt = Date.now() + CHAT_MEDIA_TTL_MS2;
|
|
107318
107445
|
const key = createFileKey();
|
|
107319
107446
|
try {
|
|
107320
107447
|
const uploadBytes = await toUploadBytes(data);
|
|
107321
107448
|
assertChatUploadByteSize(uploadBytes);
|
|
107449
|
+
const body = await sealFile(key, uploadBytes, path);
|
|
107450
|
+
assertChatUploadByteSize(body);
|
|
107322
107451
|
return {
|
|
107323
|
-
chatId,
|
|
107452
|
+
chatId: nextChatId,
|
|
107324
107453
|
mediaId,
|
|
107325
107454
|
path,
|
|
107326
|
-
body
|
|
107455
|
+
body,
|
|
107327
107456
|
metadata: {
|
|
107328
107457
|
contentType: "application/octet-stream",
|
|
107329
107458
|
cacheControl
|
|
@@ -107352,10 +107481,12 @@ async function makeSharedFileUploadPayload(data, { contentType = "application/oc
|
|
|
107352
107481
|
try {
|
|
107353
107482
|
const uploadBytes = await toUploadBytes(data);
|
|
107354
107483
|
assertChatUploadByteSize(uploadBytes);
|
|
107484
|
+
const body = await sealFile(key, uploadBytes, path);
|
|
107485
|
+
assertChatUploadByteSize(body);
|
|
107355
107486
|
return {
|
|
107356
107487
|
sharedId,
|
|
107357
107488
|
path,
|
|
107358
|
-
body
|
|
107489
|
+
body,
|
|
107359
107490
|
metadata: {
|
|
107360
107491
|
contentType,
|
|
107361
107492
|
cacheControl
|
|
@@ -109281,10 +109412,19 @@ function sortedUniqueValues(items) {
|
|
|
109281
109412
|
}
|
|
109282
109413
|
|
|
109283
109414
|
// ../../shared/chat/chats.js
|
|
109415
|
+
function sameSigningKeys(left, right) {
|
|
109416
|
+
if (left === right)
|
|
109417
|
+
return true;
|
|
109418
|
+
const leftKeys = Object.keys(left || {});
|
|
109419
|
+
const rightKeys = Object.keys(right || {});
|
|
109420
|
+
if (leftKeys.length !== rightKeys.length)
|
|
109421
|
+
return false;
|
|
109422
|
+
return leftKeys.every((key) => left[key] === right[key]);
|
|
109423
|
+
}
|
|
109284
109424
|
function sameChatShape(a, b) {
|
|
109285
109425
|
if (!a || !b)
|
|
109286
109426
|
return a === b;
|
|
109287
|
-
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);
|
|
109427
|
+
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);
|
|
109288
109428
|
}
|
|
109289
109429
|
function sameChats(prev, next) {
|
|
109290
109430
|
if (prev.length !== next.length)
|
|
@@ -109643,8 +109783,10 @@ function emptyPayload() {
|
|
|
109643
109783
|
chatsById: {},
|
|
109644
109784
|
profilesByUid: {},
|
|
109645
109785
|
mediaByKey: {},
|
|
109786
|
+
walletBalance: null,
|
|
109646
109787
|
resumeRoute: null,
|
|
109647
|
-
lastCameraFacing: null
|
|
109788
|
+
lastCameraFacing: null,
|
|
109789
|
+
cloaked: false
|
|
109648
109790
|
};
|
|
109649
109791
|
}
|
|
109650
109792
|
function isObject3(value) {
|
|
@@ -109705,8 +109847,26 @@ function normalizePayload(value) {
|
|
|
109705
109847
|
chatsById: isObject3(input.chatsById) ? input.chatsById : {},
|
|
109706
109848
|
profilesByUid: isObject3(input.profilesByUid) ? input.profilesByUid : {},
|
|
109707
109849
|
mediaByKey: isObject3(input.mediaByKey) ? input.mediaByKey : {},
|
|
109850
|
+
walletBalance: cleanWalletBalance(input.walletBalance),
|
|
109708
109851
|
resumeRoute: cleanResumeRoute(input.resumeRoute),
|
|
109709
|
-
lastCameraFacing: cleanCameraFacing(input.lastCameraFacing)
|
|
109852
|
+
lastCameraFacing: cleanCameraFacing(input.lastCameraFacing),
|
|
109853
|
+
cloaked: input.cloaked === true
|
|
109854
|
+
};
|
|
109855
|
+
}
|
|
109856
|
+
function cleanWalletBalance(value) {
|
|
109857
|
+
if (!isObject3(value))
|
|
109858
|
+
return null;
|
|
109859
|
+
const walletPK = cleanText(value.walletPK).toLowerCase();
|
|
109860
|
+
const network = cleanText(value.network).toLowerCase();
|
|
109861
|
+
const balance = Number(value.balance);
|
|
109862
|
+
if (!walletPK || !network || !Number.isSafeInteger(balance) || balance < 0) {
|
|
109863
|
+
return null;
|
|
109864
|
+
}
|
|
109865
|
+
return {
|
|
109866
|
+
walletPK,
|
|
109867
|
+
network,
|
|
109868
|
+
balance,
|
|
109869
|
+
savedAt: Number.isFinite(value.savedAt) ? value.savedAt : 0
|
|
109710
109870
|
};
|
|
109711
109871
|
}
|
|
109712
109872
|
function cleanResumeRoute(route) {
|
|
@@ -110152,8 +110312,8 @@ function stateFromPayload(payload, { chatId, selfChatPublicKey, peerChatPublicKe
|
|
|
110152
110312
|
if (!cleanOlder.length && !cleanLive.length) {
|
|
110153
110313
|
return { rejectReason: "empty-message-cache" };
|
|
110154
110314
|
}
|
|
110155
|
-
const historyStartReached = payload.historyStartReached === true
|
|
110156
|
-
const payloadHasOlder =
|
|
110315
|
+
const historyStartReached = payload.historyStartReached === true;
|
|
110316
|
+
const payloadHasOlder = payload.hasOlder === true || payload.truncated === true;
|
|
110157
110317
|
const partialOlderThan = partial ? markerFromMessage(cleanOlder[0]) : null;
|
|
110158
110318
|
return {
|
|
110159
110319
|
historyMessages: cleanOlder,
|
|
@@ -110298,7 +110458,7 @@ function writeCachedMessageState(cache, { stateVersion = null, chatId, selfChatP
|
|
|
110298
110458
|
signingKeysVersion: cleanText(signingKeysVersion),
|
|
110299
110459
|
savedAt: Date.now(),
|
|
110300
110460
|
hasOlder: nextHasOlder === true || compacted.truncated,
|
|
110301
|
-
historyStartReached: nextHistoryStartReached === true
|
|
110461
|
+
historyStartReached: nextHistoryStartReached === true,
|
|
110302
110462
|
olderThan: serializeMarker(storedOlderThan),
|
|
110303
110463
|
olderLoaded: nextOlderLoaded === true || compacted.historyMessages.length > 0,
|
|
110304
110464
|
latestServerPage: batchFromLive(compacted.latestMessages, expiredKeys, deletedKeys, nextServerBatch),
|
|
@@ -110557,6 +110717,36 @@ var init_chats2 = __esm(() => {
|
|
|
110557
110717
|
"use client";
|
|
110558
110718
|
});
|
|
110559
110719
|
|
|
110720
|
+
// ../../shared/cache/localdata/balance.js
|
|
110721
|
+
function normalizedBalance(value) {
|
|
110722
|
+
const balance = Number(value);
|
|
110723
|
+
return Number.isSafeInteger(balance) && balance >= 0 ? balance : null;
|
|
110724
|
+
}
|
|
110725
|
+
function writeCachedWalletBalance(cache, { walletPK = null, network = null, balance = null } = {}) {
|
|
110726
|
+
const nextWalletPK = lowerText(walletPK);
|
|
110727
|
+
const nextNetwork = lowerText(network);
|
|
110728
|
+
const nextBalance = normalizedBalance(balance);
|
|
110729
|
+
if (!cache || !nextWalletPK || !nextNetwork || nextBalance == null) {
|
|
110730
|
+
return Promise.resolve(false);
|
|
110731
|
+
}
|
|
110732
|
+
const current = cache.read?.()?.walletBalance;
|
|
110733
|
+
if (sameText(current?.walletPK, nextWalletPK) && sameText(current?.network, nextNetwork) && normalizedBalance(current?.balance) === nextBalance) {
|
|
110734
|
+
return Promise.resolve(false);
|
|
110735
|
+
}
|
|
110736
|
+
return cache.patch((draft) => {
|
|
110737
|
+
draft.walletBalance = {
|
|
110738
|
+
walletPK: nextWalletPK,
|
|
110739
|
+
network: nextNetwork,
|
|
110740
|
+
balance: nextBalance,
|
|
110741
|
+
savedAt: Date.now()
|
|
110742
|
+
};
|
|
110743
|
+
return draft;
|
|
110744
|
+
}).then(() => true);
|
|
110745
|
+
}
|
|
110746
|
+
var init_balance = __esm(() => {
|
|
110747
|
+
"use client";
|
|
110748
|
+
});
|
|
110749
|
+
|
|
110560
110750
|
// ../../shared/cache/localdata/profiles.js
|
|
110561
110751
|
function isUsableProfile(profile, now = Date.now()) {
|
|
110562
110752
|
if (!profile?.uid || !profile.walletPK && !profile.chatPK) {
|
|
@@ -110797,24 +110987,26 @@ async function readCachedTransferHeadState(cache, { walletPK = null } = {}) {
|
|
|
110797
110987
|
const stored = cache ? await cache.readPart(TX_HEAD_PART).catch(() => null) : null;
|
|
110798
110988
|
return stateFromPayload2(stored, { walletPK, source: "head" });
|
|
110799
110989
|
}
|
|
110800
|
-
function
|
|
110801
|
-
if (!
|
|
110802
|
-
return
|
|
110990
|
+
function cachedTransferPayloads({ transfers, walletPK = null, serverEndReached = false, historyCount = null, nextOffset = null, oldestTxMs = null } = {}) {
|
|
110991
|
+
if (!Array.isArray(transfers)) {
|
|
110992
|
+
return null;
|
|
110803
110993
|
}
|
|
110804
110994
|
const nextWalletPK = lowerText(walletPK);
|
|
110805
110995
|
if (!nextWalletPK) {
|
|
110806
|
-
return
|
|
110996
|
+
return null;
|
|
110807
110997
|
}
|
|
110808
110998
|
const visible = [...transfers].filter((tx) => tx?.id && isVisibleTransfer(tx) && transferBelongsToWallet(tx, nextWalletPK)).sort((a, b) => txCreatedMs(b) - txCreatedMs(a));
|
|
110809
110999
|
const sorted2 = visible.slice(0, Math.max(1, WALLET_TRANSFER_CACHE_LIMIT)).map(jsonClean);
|
|
110810
111000
|
const capped = sorted2.length < visible.length;
|
|
111001
|
+
const knownHistoryCount = Math.max(sorted2.length, Math.floor(Number(historyCount) || 0));
|
|
111002
|
+
const complete = serverEndReached === true && !capped && sorted2.length >= knownHistoryCount;
|
|
110811
111003
|
const fullPayload = {
|
|
110812
111004
|
version: CACHE_VERSION,
|
|
110813
111005
|
walletPK: nextWalletPK,
|
|
110814
|
-
serverEndReached:
|
|
110815
|
-
historyCount:
|
|
111006
|
+
serverEndReached: complete,
|
|
111007
|
+
historyCount: knownHistoryCount,
|
|
110816
111008
|
nextOffset: Number.isFinite(nextOffset) ? nextOffset : sorted2.length,
|
|
110817
|
-
oldestTxMs:
|
|
111009
|
+
oldestTxMs: complete && Number.isFinite(oldestTxMs) ? oldestTxMs : null,
|
|
110818
111010
|
savedAt: Date.now(),
|
|
110819
111011
|
transfers: sorted2
|
|
110820
111012
|
};
|
|
@@ -110823,7 +111015,24 @@ function writeCachedTransferState(cache, { transfers, walletPK = null, serverEnd
|
|
|
110823
111015
|
...fullPayload,
|
|
110824
111016
|
transfers: headTransfers
|
|
110825
111017
|
};
|
|
110826
|
-
return
|
|
111018
|
+
return { fullPayload, headPayload };
|
|
111019
|
+
}
|
|
111020
|
+
function writeCachedTransferHeadState(cache, state = {}) {
|
|
111021
|
+
if (!cache) {
|
|
111022
|
+
return Promise.resolve(false);
|
|
111023
|
+
}
|
|
111024
|
+
const payloads = cachedTransferPayloads(state);
|
|
111025
|
+
return payloads ? cache.writePart(TX_HEAD_PART, payloads.headPayload) : Promise.resolve(false);
|
|
111026
|
+
}
|
|
111027
|
+
function writeCachedTransferState(cache, state = {}) {
|
|
111028
|
+
if (!cache) {
|
|
111029
|
+
return Promise.resolve(false);
|
|
111030
|
+
}
|
|
111031
|
+
const payloads = cachedTransferPayloads(state);
|
|
111032
|
+
if (!payloads) {
|
|
111033
|
+
return Promise.resolve(false);
|
|
111034
|
+
}
|
|
111035
|
+
return Promise.all([cache.writePart(TX_HEAD_PART, payloads.headPayload), cache.writePart(TX_PART, payloads.fullPayload)]).then((results) => results.some(Boolean));
|
|
110827
111036
|
}
|
|
110828
111037
|
var TX_PART = "wallet-transfers", TX_HEAD_PART = "wallet-transfers-head", CACHE_VERSION = 2, CACHE_HEAD_LIMIT;
|
|
110829
111038
|
var init_transfers = __esm(() => {
|
|
@@ -110847,8 +111056,14 @@ function mediaAad(uid, network, id) {
|
|
|
110847
111056
|
function partAad(uid, network, part) {
|
|
110848
111057
|
return encoder.encode(JSON.stringify(["veyl-local-cache-part", CACHE_PART_ENVELOPE_VERSION, String(uid || ""), String(network || ""), String(part || "")]));
|
|
110849
111058
|
}
|
|
111059
|
+
function encodePayloadData(payload) {
|
|
111060
|
+
return encoder.encode(JSON.stringify({ ...normalizePayload(payload), savedAt: Date.now() }));
|
|
111061
|
+
}
|
|
111062
|
+
function decodePayloadData(raw) {
|
|
111063
|
+
return JSON.parse(decoder.decode(toBytes(raw, "cache payload")));
|
|
111064
|
+
}
|
|
110850
111065
|
async function sealPayload(key, payload, uid, network) {
|
|
110851
|
-
const body =
|
|
111066
|
+
const body = encodePayloadData(payload);
|
|
110852
111067
|
try {
|
|
110853
111068
|
const { iv, ct } = await sealAes(key, body, cacheAad(uid, network));
|
|
110854
111069
|
return JSON.stringify({
|
|
@@ -110870,7 +111085,7 @@ async function openPayloadData(key, raw, uid, network) {
|
|
|
110870
111085
|
}
|
|
110871
111086
|
const plain = await openAes(key, fromHexBytes(envelope.iv, "cache iv"), fromHexBytes(envelope.ct, "cache ciphertext"), cacheAad(uid, network));
|
|
110872
111087
|
try {
|
|
110873
|
-
return
|
|
111088
|
+
return decodePayloadData(plain);
|
|
110874
111089
|
} finally {
|
|
110875
111090
|
cleanBytes(plain);
|
|
110876
111091
|
}
|
|
@@ -110931,6 +111146,14 @@ function mediaCrypto(uid, network, id, keyBytes) {
|
|
|
110931
111146
|
ivBytes: AES_IV_BYTES
|
|
110932
111147
|
};
|
|
110933
111148
|
}
|
|
111149
|
+
function payloadCrypto(uid, network, keyBytes) {
|
|
111150
|
+
return {
|
|
111151
|
+
key: keyBytes,
|
|
111152
|
+
aad: cacheAad(uid, network),
|
|
111153
|
+
version: LOCAL_DATA_CACHE_VERSION,
|
|
111154
|
+
ivBytes: AES_IV_BYTES
|
|
111155
|
+
};
|
|
111156
|
+
}
|
|
110934
111157
|
var MEDIA_ENVELOPE_VERSION = 1, CACHE_PART_ENVELOPE_VERSION = 1;
|
|
110935
111158
|
var init_crypto = __esm(() => {
|
|
110936
111159
|
init_aes2();
|
|
@@ -110966,11 +111189,32 @@ async function openVaultCache({ key, storage, uid, network }) {
|
|
|
110966
111189
|
let writeTimer = null;
|
|
110967
111190
|
let writeTask = Promise.resolve();
|
|
110968
111191
|
const partWriteTasks = new Map;
|
|
111192
|
+
let storedPayload = null;
|
|
110969
111193
|
try {
|
|
110970
|
-
|
|
110971
|
-
|
|
111194
|
+
storedPayload = await storage.read();
|
|
111195
|
+
if (!storedPayload) {
|
|
111196
|
+
payload = emptyPayload();
|
|
111197
|
+
} else if (typeof storage.openPayload === "function") {
|
|
111198
|
+
const readKey = new Uint8Array(cacheKey);
|
|
111199
|
+
let plain;
|
|
111200
|
+
try {
|
|
111201
|
+
plain = await storage.openPayload(storedPayload, payloadCrypto(uid, network, readKey));
|
|
111202
|
+
payload = normalizePayload(decodePayloadData(plain));
|
|
111203
|
+
} finally {
|
|
111204
|
+
cleanBytes(plain, readKey);
|
|
111205
|
+
}
|
|
111206
|
+
} else {
|
|
111207
|
+
payload = normalizePayload(await openPayloadData(cacheKey, storedPayload, uid, network));
|
|
111208
|
+
}
|
|
110972
111209
|
} catch {
|
|
110973
111210
|
payload = emptyPayload();
|
|
111211
|
+
if (storedPayload) {
|
|
111212
|
+
await Promise.all([
|
|
111213
|
+
storage.remove().catch(() => {}),
|
|
111214
|
+
storage.removeAllMedia().catch(() => {}),
|
|
111215
|
+
storage.removeAllParts().catch(() => {})
|
|
111216
|
+
]);
|
|
111217
|
+
}
|
|
110974
111218
|
}
|
|
110975
111219
|
const writeNow = () => {
|
|
110976
111220
|
if (closed) {
|
|
@@ -110988,10 +111232,12 @@ async function openVaultCache({ key, storage, uid, network }) {
|
|
|
110988
111232
|
return;
|
|
110989
111233
|
}
|
|
110990
111234
|
const writeKey = new Uint8Array(cacheKey);
|
|
111235
|
+
let body;
|
|
110991
111236
|
try {
|
|
110992
|
-
await storage.
|
|
111237
|
+
const raw = typeof storage.sealPayload === "function" ? await storage.sealPayload(body = encodePayloadData(payload), payloadCrypto(uid, network, writeKey)) : await sealPayload(writeKey, payload, uid, network);
|
|
111238
|
+
await storage.write(raw);
|
|
110993
111239
|
} finally {
|
|
110994
|
-
cleanBytes(writeKey);
|
|
111240
|
+
cleanBytes(body, writeKey);
|
|
110995
111241
|
}
|
|
110996
111242
|
}).catch(() => {});
|
|
110997
111243
|
return writeTask;
|
|
@@ -111262,6 +111508,7 @@ var init_vault2 = __esm(() => {
|
|
|
111262
111508
|
// ../../shared/cache/localdata.js
|
|
111263
111509
|
var init_localdata = __esm(() => {
|
|
111264
111510
|
init_chats2();
|
|
111511
|
+
init_balance();
|
|
111265
111512
|
init_media();
|
|
111266
111513
|
init_messages2();
|
|
111267
111514
|
init_profiles();
|
|
@@ -111339,7 +111586,8 @@ function makeOwnChatEntry(pair, fields = {}) {
|
|
|
111339
111586
|
preview: fields.preview || null,
|
|
111340
111587
|
saved: fields.saved || null,
|
|
111341
111588
|
readMs: Number.isFinite(fields.readMs) ? fields.readMs : null,
|
|
111342
|
-
startMs: Number.isFinite(fields.startMs) ? fields.startMs : null
|
|
111589
|
+
startMs: Number.isFinite(fields.startMs) ? fields.startMs : null,
|
|
111590
|
+
signerShared: fields.signerShared === true
|
|
111343
111591
|
};
|
|
111344
111592
|
}
|
|
111345
111593
|
var CHAT_ENTRY_VERSION = 1;
|
|
@@ -111794,9 +112042,9 @@ function setErrorStage(error, stage, extra = {}) {
|
|
|
111794
112042
|
Object.assign(error, extra);
|
|
111795
112043
|
return error;
|
|
111796
112044
|
}
|
|
111797
|
-
async function makeChatFileUpload(
|
|
112045
|
+
async function makeChatFileUpload(chatId, cid, data, { cacheControl = "private, max-age=0, no-transform" } = {}) {
|
|
111798
112046
|
try {
|
|
111799
|
-
return await makeChatFileUploadPayload(
|
|
112047
|
+
return await makeChatFileUploadPayload(chatId, cid, data, {
|
|
111800
112048
|
cacheControl
|
|
111801
112049
|
});
|
|
111802
112050
|
} catch (error) {
|
|
@@ -111806,8 +112054,8 @@ async function makeChatFileUpload(pair, cid, data, { cacheControl = "private, ma
|
|
|
111806
112054
|
});
|
|
111807
112055
|
}
|
|
111808
112056
|
}
|
|
111809
|
-
async function putChatFile(
|
|
111810
|
-
const upload = await makeChatFileUpload(
|
|
112057
|
+
async function putChatFile(chatId, cid, data, options) {
|
|
112058
|
+
const upload = await makeChatFileUpload(chatId, cid, data, options);
|
|
111811
112059
|
try {
|
|
111812
112060
|
if (typeof options?.uploadChatMedia !== "function") {
|
|
111813
112061
|
throw new Error("chat media upload required");
|
|
@@ -111842,7 +112090,7 @@ async function putSharedFile(data, options = {}) {
|
|
|
111842
112090
|
throw setErrorStage(error, "upload", { path: upload.path });
|
|
111843
112091
|
}
|
|
111844
112092
|
}
|
|
111845
|
-
async function readChatFile(readChatMedia,
|
|
112093
|
+
async function readChatFile(readChatMedia, file) {
|
|
111846
112094
|
let body;
|
|
111847
112095
|
try {
|
|
111848
112096
|
if (typeof readChatMedia !== "function") {
|
|
@@ -111900,8 +112148,8 @@ function buildAttachmentMsg(type, file) {
|
|
|
111900
112148
|
return makeAttachment(type, file);
|
|
111901
112149
|
}
|
|
111902
112150
|
}
|
|
111903
|
-
async function putAttachment(
|
|
111904
|
-
const file = await putChatFile(
|
|
112151
|
+
async function putAttachment(chatId, cid, type, data, meta = {}) {
|
|
112152
|
+
const file = await putChatFile(chatId, cid, data, meta);
|
|
111905
112153
|
return buildAttachmentMsg(type, {
|
|
111906
112154
|
...file,
|
|
111907
112155
|
...pickAttachmentMeta(meta)
|
|
@@ -111914,26 +112162,26 @@ async function putSharedAttachment(type, data, meta = {}) {
|
|
|
111914
112162
|
...pickAttachmentMeta(meta)
|
|
111915
112163
|
});
|
|
111916
112164
|
}
|
|
111917
|
-
async function putImg(
|
|
111918
|
-
return putAttachment(
|
|
112165
|
+
async function putImg(chatId, cid, data, meta = {}) {
|
|
112166
|
+
return putAttachment(chatId, cid, "img", data, meta);
|
|
111919
112167
|
}
|
|
111920
|
-
async function putGif(
|
|
111921
|
-
return putAttachment(
|
|
112168
|
+
async function putGif(chatId, cid, data, meta = {}) {
|
|
112169
|
+
return putAttachment(chatId, cid, "gif", data, meta);
|
|
111922
112170
|
}
|
|
111923
|
-
async function putM4a(
|
|
111924
|
-
return putAttachment(
|
|
112171
|
+
async function putM4a(chatId, cid, data, meta = {}) {
|
|
112172
|
+
return putAttachment(chatId, cid, "m4a", data, meta);
|
|
111925
112173
|
}
|
|
111926
|
-
async function putMp4(
|
|
111927
|
-
return putAttachment(
|
|
112174
|
+
async function putMp4(chatId, cid, data, meta = {}) {
|
|
112175
|
+
return putAttachment(chatId, cid, "mp4", data, meta);
|
|
111928
112176
|
}
|
|
111929
|
-
async function putFile(
|
|
111930
|
-
return putAttachment(
|
|
112177
|
+
async function putFile(chatId, cid, data, meta = {}) {
|
|
112178
|
+
return putAttachment(chatId, cid, "file", data, meta);
|
|
111931
112179
|
}
|
|
111932
|
-
function readMsgAttachment(readChatMedia,
|
|
111933
|
-
return readChatFile(readChatMedia,
|
|
112180
|
+
function readMsgAttachment(readChatMedia, msg) {
|
|
112181
|
+
return readChatFile(readChatMedia, msg);
|
|
111934
112182
|
}
|
|
111935
|
-
function readMsgFile(readChatMedia,
|
|
111936
|
-
return readMsgAttachment(readChatMedia,
|
|
112183
|
+
function readMsgFile(readChatMedia, msg) {
|
|
112184
|
+
return readMsgAttachment(readChatMedia, msg);
|
|
111937
112185
|
}
|
|
111938
112186
|
var init_media2 = __esm(() => {
|
|
111939
112187
|
init_files2();
|
|
@@ -112104,7 +112352,25 @@ async function setChatRead(cloud, uid, chatPrivKey, chatId, readMs, options = {}
|
|
|
112104
112352
|
body: await sealOwnChatEntry(chatPrivKey, entryId, {
|
|
112105
112353
|
...entry,
|
|
112106
112354
|
readMs: Math.max(currentReadMs, nextReadMs),
|
|
112107
|
-
...hasPreviewPatch ? { preview: preview2 || null } : {}
|
|
112355
|
+
...hasPreviewPatch ? { preview: preview2 || null } : {},
|
|
112356
|
+
...options.signerShared === true ? { signerShared: true } : {}
|
|
112357
|
+
})
|
|
112358
|
+
});
|
|
112359
|
+
return true;
|
|
112360
|
+
}
|
|
112361
|
+
async function setChatSignerShared(cloud, uid, chatPrivKey, chatId) {
|
|
112362
|
+
if (!cloud || !uid || !chatPrivKey || !chatId) {
|
|
112363
|
+
return false;
|
|
112364
|
+
}
|
|
112365
|
+
const entryId = ownChatEntryId(chatPrivKey, chatId);
|
|
112366
|
+
const entry = await readOwnEntry(cloud, uid, chatPrivKey, entryId);
|
|
112367
|
+
if (!entry?.chatId || entry.signerShared === true) {
|
|
112368
|
+
return entry?.signerShared === true;
|
|
112369
|
+
}
|
|
112370
|
+
await cloud.user.chats.write(uid, entryId, {
|
|
112371
|
+
body: await sealOwnChatEntry(chatPrivKey, entryId, {
|
|
112372
|
+
...entry,
|
|
112373
|
+
signerShared: true
|
|
112108
112374
|
})
|
|
112109
112375
|
});
|
|
112110
112376
|
return true;
|
|
@@ -112147,7 +112413,8 @@ async function ownEntryWrite(cloud, uid, chatPrivKey, pair, fields = {}) {
|
|
|
112147
112413
|
preview: fields.preview || existing?.preview,
|
|
112148
112414
|
saved: existing?.saved || null,
|
|
112149
112415
|
readMs: existing?.readMs,
|
|
112150
|
-
startMs: existing?.startMs
|
|
112416
|
+
startMs: existing?.startMs,
|
|
112417
|
+
signerShared: fields.signerShared === true || existing?.signerShared === true
|
|
112151
112418
|
});
|
|
112152
112419
|
const tsMs = timestampMs(fields.ts, null);
|
|
112153
112420
|
return {
|
|
@@ -112182,14 +112449,6 @@ function ownerEditedPreview(senderPubkey, message) {
|
|
|
112182
112449
|
failed: false
|
|
112183
112450
|
};
|
|
112184
112451
|
}
|
|
112185
|
-
function messageFileChatId(message) {
|
|
112186
|
-
try {
|
|
112187
|
-
const ref = getMediaFileRef(message?.p);
|
|
112188
|
-
return ref?.type === "chat" ? ref.chatId : "";
|
|
112189
|
-
} catch {
|
|
112190
|
-
return "";
|
|
112191
|
-
}
|
|
112192
|
-
}
|
|
112193
112452
|
async function recipientForSend(cloud, receiverChatPK, options, needed) {
|
|
112194
112453
|
if (!needed) {
|
|
112195
112454
|
return null;
|
|
@@ -112210,50 +112469,63 @@ async function sendMsg(cloud, senderPubkey, senderPrivkey, receiverChatPK, messa
|
|
|
112210
112469
|
if (!chatId) {
|
|
112211
112470
|
throw new Error("chat id required");
|
|
112212
112471
|
}
|
|
112213
|
-
|
|
112214
|
-
|
|
112215
|
-
|
|
112216
|
-
|
|
112217
|
-
|
|
112218
|
-
|
|
112219
|
-
|
|
112220
|
-
|
|
112221
|
-
|
|
112222
|
-
|
|
112223
|
-
|
|
112224
|
-
|
|
112225
|
-
|
|
112226
|
-
|
|
112227
|
-
|
|
112228
|
-
|
|
112229
|
-
|
|
112230
|
-
|
|
112231
|
-
|
|
112232
|
-
|
|
112233
|
-
|
|
112234
|
-
|
|
112235
|
-
|
|
112236
|
-
|
|
112237
|
-
|
|
112238
|
-
|
|
112239
|
-
|
|
112240
|
-
|
|
112241
|
-
|
|
112242
|
-
|
|
112243
|
-
|
|
112244
|
-
|
|
112245
|
-
|
|
112246
|
-
|
|
112247
|
-
|
|
112248
|
-
|
|
112249
|
-
|
|
112250
|
-
|
|
112251
|
-
|
|
112252
|
-
|
|
112253
|
-
|
|
112254
|
-
|
|
112472
|
+
return withCachedPair(senderPubkey, senderPrivkey, receiverChatPK, { chatId }, async (pair) => {
|
|
112473
|
+
if (options?.linkId && cleanText(options.linkId) !== pair.linkId) {
|
|
112474
|
+
throw new Error("link mismatch");
|
|
112475
|
+
}
|
|
112476
|
+
const retention = cleanChatRetention(options?.retention ?? options?.ttlMode);
|
|
112477
|
+
const tsMs = Date.now();
|
|
112478
|
+
const messagePayload = withMessageRetention(message, retention);
|
|
112479
|
+
const actionOp = actionOpForPayload(messagePayload);
|
|
112480
|
+
const { head, body } = await sealMsg(pair, messagePayload, { op: actionOp, ts: tsMs });
|
|
112481
|
+
const ttlMs = actionOp === CHAT_ACTION_OPS.CREATE ? newStorageTtlMs() : null;
|
|
112482
|
+
const messageId = head.cid;
|
|
112483
|
+
const msgData = {
|
|
112484
|
+
head,
|
|
112485
|
+
body,
|
|
112486
|
+
ttlMs
|
|
112487
|
+
};
|
|
112488
|
+
const recipientProfile = await recipientForSend(cloud, receiverChatPK, options, updatePreview || options?.ping === true);
|
|
112489
|
+
const sentMessage = ownerPreview(senderPubkey, messagePayload, messageId, head, tsMs, ttlMs);
|
|
112490
|
+
const preview2 = updatePreview ? sentMessage : null;
|
|
112491
|
+
const ownerEntry = updatePreview ? await ownEntryWrite(cloud, cleanText(options?.senderUid), senderPrivkey, pair, {
|
|
112492
|
+
peerUid: recipientProfile?.uid || cleanText(options?.receiverUid),
|
|
112493
|
+
peerSigningPublicKey: recipientProfile?.signingPublicKey,
|
|
112494
|
+
entry: options?.ownEntry,
|
|
112495
|
+
settings: options?.chatSettings,
|
|
112496
|
+
preview: preview2,
|
|
112497
|
+
ts: tsMs
|
|
112498
|
+
}) : null;
|
|
112499
|
+
const pingKind = updatePreview ? "message" : cleanText(options?.pingKind) || "ping";
|
|
112500
|
+
const ping = recipientProfile?.uid && (updatePreview || options?.ping === true) ? await sealPing(senderPubkey, senderPrivkey, receiverChatPK, {
|
|
112501
|
+
kind: pingKind,
|
|
112502
|
+
chatId,
|
|
112503
|
+
senderUid: cleanText(options?.senderUid),
|
|
112504
|
+
messageId,
|
|
112505
|
+
ts: tsMs
|
|
112506
|
+
}) : null;
|
|
112507
|
+
const write = await cloud.chat.messages.send({
|
|
112508
|
+
chatId,
|
|
112509
|
+
messageId,
|
|
112510
|
+
message: msgData,
|
|
112511
|
+
ownerEntry,
|
|
112512
|
+
inbox: ping ? { recipientUid: recipientProfile?.uid, ping, notify: options?.notify !== false } : null,
|
|
112513
|
+
onCommitted: typeof options?.onCommitted === "function" ? (committed) => options.onCommitted({ ...committed, message: sentMessage, preview: preview2 }) : undefined
|
|
112514
|
+
});
|
|
112515
|
+
const delivered = options?.ping === true ? !!ping && write?.delivered !== false : write?.delivered !== false;
|
|
112516
|
+
if (ping && delivered && ownerEntry && options?.ownEntry?.signerShared !== true) {
|
|
112517
|
+
await setChatSignerShared(cloud, cleanText(options?.senderUid), senderPrivkey, chatId).catch(() => false);
|
|
112518
|
+
}
|
|
112519
|
+
return {
|
|
112520
|
+
chatId,
|
|
112521
|
+
msgId: messageId,
|
|
112522
|
+
cid: head.cid,
|
|
112523
|
+
message: sentMessage,
|
|
112524
|
+
preview: preview2,
|
|
112525
|
+
delivered,
|
|
112526
|
+
...write?.skipped ? { skipped: true } : {}
|
|
112527
|
+
};
|
|
112255
112528
|
});
|
|
112256
|
-
return { chatId, msgId: messageId, cid: head.cid, message: sentMessage, preview: preview2, ...write?.skipped ? { skipped: true } : {} };
|
|
112257
112529
|
}
|
|
112258
112530
|
async function sendReadReceipt(cloud, senderPubkey, senderPrivkey, receiverChatPK, target, options = {}) {
|
|
112259
112531
|
const receipt = {
|
|
@@ -112261,7 +112533,13 @@ async function sendReadReceipt(cloud, senderPubkey, senderPrivkey, receiverChatP
|
|
|
112261
112533
|
cid: makeCid(),
|
|
112262
112534
|
s: senderPubkey
|
|
112263
112535
|
};
|
|
112264
|
-
return sendMsg(cloud, senderPubkey, senderPrivkey, receiverChatPK, receipt, {
|
|
112536
|
+
return sendMsg(cloud, senderPubkey, senderPrivkey, receiverChatPK, receipt, {
|
|
112537
|
+
...options,
|
|
112538
|
+
updatePreview: false,
|
|
112539
|
+
ping: options?.ping === true,
|
|
112540
|
+
pingKind: "read",
|
|
112541
|
+
notify: false
|
|
112542
|
+
});
|
|
112265
112543
|
}
|
|
112266
112544
|
async function sendReaction(cloud, senderPubkey, senderPrivkey, receiverChatPK, target, emoji, options = {}) {
|
|
112267
112545
|
const reaction = {
|
|
@@ -112363,27 +112641,28 @@ async function setChatRetention(cloud, chatId, senderPubkey, senderPrivkey, peer
|
|
|
112363
112641
|
throw new Error("vault locked");
|
|
112364
112642
|
}
|
|
112365
112643
|
const nextRetention = cleanChatRetention(retention);
|
|
112366
|
-
|
|
112367
|
-
|
|
112368
|
-
|
|
112369
|
-
|
|
112370
|
-
|
|
112371
|
-
|
|
112372
|
-
|
|
112373
|
-
|
|
112374
|
-
|
|
112375
|
-
|
|
112376
|
-
|
|
112377
|
-
|
|
112378
|
-
|
|
112379
|
-
|
|
112380
|
-
|
|
112381
|
-
|
|
112382
|
-
|
|
112383
|
-
|
|
112384
|
-
|
|
112644
|
+
return withCachedPair(senderPubkey, senderPrivkey, peerChatPK, { chatId }, async (pair) => {
|
|
112645
|
+
if (chatId && pair.chatId !== chatId) {
|
|
112646
|
+
throw new Error("chat mismatch");
|
|
112647
|
+
}
|
|
112648
|
+
const systemMessage = {
|
|
112649
|
+
...makeRetentionSystemMsg(nextRetention),
|
|
112650
|
+
cid: cleanText(options?.cid) || makeCid(),
|
|
112651
|
+
s: senderPubkey
|
|
112652
|
+
};
|
|
112653
|
+
await sendMsg(cloud, senderPubkey, senderPrivkey, peerChatPK, systemMessage, {
|
|
112654
|
+
chatId,
|
|
112655
|
+
linkId: pair.linkId,
|
|
112656
|
+
updatePreview: true,
|
|
112657
|
+
retention: nextRetention,
|
|
112658
|
+
chatExists: true,
|
|
112659
|
+
senderUid: options?.senderUid,
|
|
112660
|
+
ownEntry: options?.ownEntry,
|
|
112661
|
+
chatSettings: { retention: nextRetention },
|
|
112662
|
+
onCommitted: options?.onCommitted
|
|
112663
|
+
});
|
|
112664
|
+
return nextRetention;
|
|
112385
112665
|
});
|
|
112386
|
-
return nextRetention;
|
|
112387
112666
|
}
|
|
112388
112667
|
async function uploadAttachmentMsg(_cloud, senderPubkey, senderPrivkey, receiverChatPK, attachment = {}) {
|
|
112389
112668
|
if (!senderPrivkey || !senderPubkey) {
|
|
@@ -112397,95 +112676,96 @@ async function uploadAttachmentMsg(_cloud, senderPubkey, senderPrivkey, receiver
|
|
|
112397
112676
|
if (!chatId) {
|
|
112398
112677
|
throw new Error("chat id required");
|
|
112399
112678
|
}
|
|
112400
|
-
const pair = await getCachedPair(senderPubkey, senderPrivkey, receiverChatPK, { chatId });
|
|
112401
112679
|
const type = cleanText(attachment?.type) || "file";
|
|
112402
112680
|
const data = attachment?.data;
|
|
112403
112681
|
const meta = attachment?.meta || {};
|
|
112404
112682
|
switch (type) {
|
|
112405
112683
|
case "img":
|
|
112406
|
-
return putImg(
|
|
112684
|
+
return putImg(chatId, nextCid, data, meta);
|
|
112407
112685
|
case "gif":
|
|
112408
|
-
return putGif(
|
|
112686
|
+
return putGif(chatId, nextCid, data, meta);
|
|
112409
112687
|
case "m4a":
|
|
112410
|
-
return putM4a(
|
|
112688
|
+
return putM4a(chatId, nextCid, data, meta);
|
|
112411
112689
|
case "mp4":
|
|
112412
|
-
return putMp4(
|
|
112690
|
+
return putMp4(chatId, nextCid, data, meta);
|
|
112413
112691
|
case "file":
|
|
112414
|
-
return putFile(
|
|
112692
|
+
return putFile(chatId, nextCid, data, meta);
|
|
112415
112693
|
default:
|
|
112416
|
-
return putAttachment(
|
|
112694
|
+
return putAttachment(chatId, nextCid, type, data, meta);
|
|
112417
112695
|
}
|
|
112418
112696
|
}
|
|
112419
112697
|
async function updateMsg(cloud, chatId, msgId, senderPubkey, senderPrivkey, receiverChatPK, newMessage, options = {}) {
|
|
112420
112698
|
if (!senderPubkey || !senderPrivkey)
|
|
112421
112699
|
throw new Error("vault locked");
|
|
112422
|
-
|
|
112423
|
-
|
|
112424
|
-
|
|
112425
|
-
|
|
112426
|
-
|
|
112427
|
-
|
|
112428
|
-
|
|
112429
|
-
|
|
112430
|
-
|
|
112431
|
-
|
|
112432
|
-
|
|
112433
|
-
|
|
112434
|
-
|
|
112435
|
-
|
|
112436
|
-
|
|
112437
|
-
|
|
112438
|
-
|
|
112439
|
-
|
|
112440
|
-
|
|
112441
|
-
|
|
112442
|
-
|
|
112443
|
-
|
|
112444
|
-
|
|
112445
|
-
|
|
112446
|
-
|
|
112447
|
-
|
|
112448
|
-
|
|
112449
|
-
|
|
112450
|
-
|
|
112451
|
-
|
|
112452
|
-
|
|
112453
|
-
|
|
112454
|
-
|
|
112455
|
-
|
|
112456
|
-
|
|
112457
|
-
|
|
112700
|
+
return withCachedPair(senderPubkey, senderPrivkey, receiverChatPK, { chatId }, async (pair) => {
|
|
112701
|
+
if (pair.chatId !== chatId) {
|
|
112702
|
+
throw new Error("chat mismatch");
|
|
112703
|
+
}
|
|
112704
|
+
const target = cleanText(newMessage?.cid) || cleanText(msgId);
|
|
112705
|
+
if (!target) {
|
|
112706
|
+
throw new Error("message target required");
|
|
112707
|
+
}
|
|
112708
|
+
const op = newMessage?.t === "req" && cleanText(newMessage?.tx) ? CHAT_ACTION_OPS.PAY_CONFIRM : CHAT_ACTION_OPS.EDIT;
|
|
112709
|
+
const tsMs = Date.now();
|
|
112710
|
+
const action = {
|
|
112711
|
+
...newMessage || {},
|
|
112712
|
+
cid: makeCid(),
|
|
112713
|
+
s: senderPubkey
|
|
112714
|
+
};
|
|
112715
|
+
const { head, body } = await sealMsg(pair, action, { op, target, ts: tsMs });
|
|
112716
|
+
const messageId = head.cid;
|
|
112717
|
+
const updatePreview = options?.updatePreview === true;
|
|
112718
|
+
const preview2 = updatePreview ? ownerEditedPreview(senderPubkey, newMessage) : null;
|
|
112719
|
+
const ownerEntry = updatePreview ? await ownEntryWrite(cloud, cleanText(options?.senderUid), senderPrivkey, pair, {
|
|
112720
|
+
peerUid: cleanText(options?.receiverUid),
|
|
112721
|
+
peerSigningPublicKey: cleanText(options?.peerSigningPublicKey),
|
|
112722
|
+
entry: options?.ownEntry,
|
|
112723
|
+
preview: preview2,
|
|
112724
|
+
ts: preview2?.ts ?? tsMs
|
|
112725
|
+
}) : null;
|
|
112726
|
+
await cloud.chat.messages.send({
|
|
112727
|
+
chatId,
|
|
112728
|
+
messageId,
|
|
112729
|
+
message: {
|
|
112730
|
+
head,
|
|
112731
|
+
body,
|
|
112732
|
+
ttlMs: null
|
|
112733
|
+
},
|
|
112734
|
+
ownerEntry,
|
|
112735
|
+
inbox: null
|
|
112736
|
+
});
|
|
112737
|
+
return {
|
|
112738
|
+
chatId,
|
|
112739
|
+
msgId: messageId,
|
|
112740
|
+
cid: head.cid,
|
|
112741
|
+
preview: preview2
|
|
112742
|
+
};
|
|
112458
112743
|
});
|
|
112459
|
-
return {
|
|
112460
|
-
chatId,
|
|
112461
|
-
msgId: messageId,
|
|
112462
|
-
cid: head.cid,
|
|
112463
|
-
preview: preview2
|
|
112464
|
-
};
|
|
112465
112744
|
}
|
|
112466
112745
|
async function deleteMsg(cloud, chatId, messageOrId, senderPubkey, senderPrivkey, peerChatPK, options = {}) {
|
|
112467
112746
|
if (!cloud || !chatId || !messageOrId || !senderPubkey || !senderPrivkey || !peerChatPK) {
|
|
112468
112747
|
return false;
|
|
112469
112748
|
}
|
|
112470
|
-
|
|
112471
|
-
|
|
112472
|
-
|
|
112473
|
-
|
|
112474
|
-
|
|
112475
|
-
|
|
112476
|
-
|
|
112477
|
-
|
|
112478
|
-
|
|
112479
|
-
|
|
112480
|
-
|
|
112481
|
-
|
|
112482
|
-
|
|
112483
|
-
|
|
112484
|
-
|
|
112485
|
-
|
|
112486
|
-
|
|
112749
|
+
return withCachedPair(senderPubkey, senderPrivkey, peerChatPK, { chatId }, async (pair) => {
|
|
112750
|
+
if (pair.chatId !== chatId) {
|
|
112751
|
+
return false;
|
|
112752
|
+
}
|
|
112753
|
+
const item = messageDeleteItems([messageOrId])[0];
|
|
112754
|
+
const target = cleanText(options?.docId) || cleanText(item?.id);
|
|
112755
|
+
if (!target || target.startsWith("local:")) {
|
|
112756
|
+
return false;
|
|
112757
|
+
}
|
|
112758
|
+
const deleteTarget = cleanText(options?.target) || cleanText(getMessageKey(messageOrId)) || target;
|
|
112759
|
+
await sendDeleteAction(cloud, senderPubkey, senderPrivkey, peerChatPK, deleteTarget, {
|
|
112760
|
+
chatId,
|
|
112761
|
+
linkId: options?.linkId,
|
|
112762
|
+
senderUid: options?.senderUid
|
|
112763
|
+
});
|
|
112764
|
+
await cloud.chat.messages.delete(chatId, target, {
|
|
112765
|
+
mediaPaths: item?.mediaPath ? [item.mediaPath] : []
|
|
112766
|
+
});
|
|
112767
|
+
return true;
|
|
112487
112768
|
});
|
|
112488
|
-
return true;
|
|
112489
112769
|
}
|
|
112490
112770
|
async function deleteMsgs(cloud, chatId, messages, senderPubkey, senderPrivkey, peerChatPK) {
|
|
112491
112771
|
if (!cloud || !chatId || !senderPubkey || !senderPrivkey || !peerChatPK) {
|
|
@@ -112495,31 +112775,31 @@ async function deleteMsgs(cloud, chatId, messages, senderPubkey, senderPrivkey,
|
|
|
112495
112775
|
if (!items.length) {
|
|
112496
112776
|
return 0;
|
|
112497
112777
|
}
|
|
112498
|
-
|
|
112499
|
-
|
|
112500
|
-
|
|
112501
|
-
|
|
112502
|
-
|
|
112503
|
-
|
|
112504
|
-
|
|
112505
|
-
|
|
112506
|
-
|
|
112507
|
-
|
|
112508
|
-
|
|
112509
|
-
|
|
112778
|
+
return withCachedPair(senderPubkey, senderPrivkey, peerChatPK, { chatId }, async (pair) => {
|
|
112779
|
+
if (pair.chatId !== chatId) {
|
|
112780
|
+
return 0;
|
|
112781
|
+
}
|
|
112782
|
+
let deleted = 0;
|
|
112783
|
+
for (let index = 0;index < items.length; index += DELETE_WRITE_BATCH_SIZE) {
|
|
112784
|
+
const chunk = items.slice(index, index + DELETE_WRITE_BATCH_SIZE);
|
|
112785
|
+
const targets = chunk.map((item) => cleanText(item.id)).filter((target) => target && !target.startsWith("local:"));
|
|
112786
|
+
const mediaPaths = chunk.map((item) => cleanText(item.mediaPath)).filter(Boolean);
|
|
112787
|
+
deleted += await cloud.chat.messages.deleteMany(chatId, targets, { mediaPaths });
|
|
112788
|
+
}
|
|
112789
|
+
return deleted;
|
|
112790
|
+
});
|
|
112510
112791
|
}
|
|
112511
|
-
async function readMsgMedia(readChatMedia,
|
|
112512
|
-
return readMsgAttachment2(readChatMedia,
|
|
112792
|
+
async function readMsgMedia(readChatMedia, msg) {
|
|
112793
|
+
return readMsgAttachment2(readChatMedia, msg);
|
|
112513
112794
|
}
|
|
112514
|
-
async function readMsgAttachment2(readChatMedia,
|
|
112795
|
+
async function readMsgAttachment2(readChatMedia, msg) {
|
|
112515
112796
|
if (typeof readChatMedia !== "function") {
|
|
112516
112797
|
throw new Error("chat media read required");
|
|
112517
112798
|
}
|
|
112518
|
-
if (!
|
|
112799
|
+
if (!msg) {
|
|
112519
112800
|
return null;
|
|
112520
112801
|
}
|
|
112521
|
-
|
|
112522
|
-
return readMsgFile(readChatMedia, pair, msg);
|
|
112802
|
+
return readMsgFile(readChatMedia, msg);
|
|
112523
112803
|
}
|
|
112524
112804
|
var DELETE_WRITE_BATCH_SIZE;
|
|
112525
112805
|
var init_write = __esm(() => {
|
|
@@ -112762,14 +113042,14 @@ function hasInvalidStoredMediaRef(message) {
|
|
|
112762
113042
|
return true;
|
|
112763
113043
|
}
|
|
112764
113044
|
}
|
|
112765
|
-
function readMessageMedia(cloud, media,
|
|
113045
|
+
function readMessageMedia(cloud, media, message) {
|
|
112766
113046
|
const readChatMedia = cloud?.chat?.media?.read;
|
|
112767
113047
|
if (typeof media?.readMessageFile === "function") {
|
|
112768
|
-
return media.readMessageFile(readChatMedia,
|
|
113048
|
+
return media.readMessageFile(readChatMedia, message);
|
|
112769
113049
|
}
|
|
112770
|
-
return readMsgMedia(readChatMedia,
|
|
113050
|
+
return readMsgMedia(readChatMedia, message);
|
|
112771
113051
|
}
|
|
112772
|
-
function createChatSave({ cloud, media = {}, chatBanned,
|
|
113052
|
+
function createChatSave({ cloud, media = {}, chatBanned, localCache }) {
|
|
112773
113053
|
const makeMessagePermanent = async (chatId, message) => {
|
|
112774
113054
|
if (chatBanned) {
|
|
112775
113055
|
throw makeChatUnavailableError();
|
|
@@ -112787,7 +113067,7 @@ function createChatSave({ cloud, media = {}, chatBanned, chatPK, chatPrivateKey,
|
|
|
112787
113067
|
const updated = await makeMsgTemporary(cloud, chatId, list, ttl);
|
|
112788
113068
|
return { updated, ttl };
|
|
112789
113069
|
};
|
|
112790
|
-
const readMessageFile = async (
|
|
113070
|
+
const readMessageFile = async (_peerChatPK, message) => {
|
|
112791
113071
|
if (chatBanned) {
|
|
112792
113072
|
throw makeChatUnavailableError();
|
|
112793
113073
|
}
|
|
@@ -112809,7 +113089,7 @@ function createChatSave({ cloud, media = {}, chatBanned, chatPK, chatPrivateKey,
|
|
|
112809
113089
|
throw makeFileGoneError();
|
|
112810
113090
|
}
|
|
112811
113091
|
try {
|
|
112812
|
-
const bytes = await readMessageMedia(cloud, media,
|
|
113092
|
+
const bytes = await readMessageMedia(cloud, media, message);
|
|
112813
113093
|
saveMedia(localCache, message, bytes, message);
|
|
112814
113094
|
return bytes;
|
|
112815
113095
|
} catch (error) {
|
|
@@ -112876,7 +113156,7 @@ function messageExpiryGroups(messages, selfChatPublicKey, seenAt) {
|
|
|
112876
113156
|
{ messages: day, expiresAt: seenAt + AFTER_SEEN_MS }
|
|
112877
113157
|
].filter((group) => group.messages.length);
|
|
112878
113158
|
}
|
|
112879
|
-
function createChatSeen({ cloud, uid, chatBanned, chatPK, chatPrivateKey, localCache, pendingReadRef, readCacheRef, readWriteInterval, getChatRetention, setChats, diag }) {
|
|
113159
|
+
function createChatSeen({ cloud, uid, chatBanned, chatPK, chatPrivateKey, localCache, pendingReadRef, readCacheRef, readWriteInterval, getChatRetention, sendOptionsForPeer, setChats, diag }) {
|
|
112880
113160
|
const scheduleRead = (chatId, message, previewMs, sendReceipt, expiryMessages = []) => {
|
|
112881
113161
|
scheduleReadWrite({
|
|
112882
113162
|
pendingRead: pendingReadRef.current,
|
|
@@ -112887,24 +113167,37 @@ function createChatSeen({ cloud, uid, chatBanned, chatPK, chatPrivateKey, localC
|
|
|
112887
113167
|
expiryMessages: sendReceipt ? expiryMessages : [],
|
|
112888
113168
|
interval: readWriteInterval,
|
|
112889
113169
|
write: async (pending) => {
|
|
113170
|
+
let receiptError = null;
|
|
113171
|
+
let receiptResult = null;
|
|
113172
|
+
let introduceSigner = false;
|
|
113173
|
+
if (pending.receipt) {
|
|
113174
|
+
const sendOptions = sendOptionsForPeer(pending.receipt.peerChatPK);
|
|
113175
|
+
introduceSigner = sendOptions?.signerShared !== true;
|
|
113176
|
+
try {
|
|
113177
|
+
receiptResult = await sendReadReceipt(cloud, chatPK, chatPrivateKey, pending.receipt.peerChatPK, pending.receipt.target, {
|
|
113178
|
+
chatId,
|
|
113179
|
+
retention: getChatRetention(chatId),
|
|
113180
|
+
senderUid: uid,
|
|
113181
|
+
receiverUid: sendOptions?.receiverUid,
|
|
113182
|
+
ping: introduceSigner
|
|
113183
|
+
});
|
|
113184
|
+
} catch (error) {
|
|
113185
|
+
receiptError = error;
|
|
113186
|
+
}
|
|
113187
|
+
}
|
|
112890
113188
|
const writes = [
|
|
112891
113189
|
setChatRead(cloud, uid, chatPrivateKey, chatId, pending.previewMs, {
|
|
112892
|
-
preview: (currentPreview) => withChatPreviewOpened(currentPreview, pending.message, pending.previewMs, chatPK) || currentPreview
|
|
113190
|
+
preview: (currentPreview) => withChatPreviewOpened(currentPreview, pending.message, pending.previewMs, chatPK) || currentPreview,
|
|
113191
|
+
signerShared: introduceSigner && receiptResult?.delivered === true
|
|
112893
113192
|
})
|
|
112894
113193
|
];
|
|
112895
113194
|
if (pending.receipt) {
|
|
112896
|
-
writes.push(sendReadReceipt(cloud, chatPK, chatPrivateKey, pending.receipt.peerChatPK, pending.receipt.target, {
|
|
112897
|
-
chatId,
|
|
112898
|
-
retention: getChatRetention(chatId),
|
|
112899
|
-
senderUid: uid
|
|
112900
|
-
}));
|
|
112901
113195
|
for (const group of messageExpiryGroups(pending.expiryMessages, chatPK, pending.expirySeenAt)) {
|
|
112902
113196
|
writes.push(setMessageExpiry(cloud, chatId, group.messages, group.expiresAt));
|
|
112903
113197
|
}
|
|
112904
113198
|
}
|
|
112905
113199
|
const results = await Promise.allSettled(writes);
|
|
112906
113200
|
const ownerError = results[0]?.status === "rejected" ? results[0].reason : null;
|
|
112907
|
-
const receiptError = pending.receipt && results[1]?.status === "rejected" ? results[1].reason : null;
|
|
112908
113201
|
if (ownerError) {
|
|
112909
113202
|
markError(diag, "chat.read.state.write", Date.now(), ownerError);
|
|
112910
113203
|
}
|
|
@@ -112912,7 +113205,7 @@ function createChatSeen({ cloud, uid, chatBanned, chatPK, chatPrivateKey, localC
|
|
|
112912
113205
|
readCacheRef.current.delete(chatId);
|
|
112913
113206
|
markError(diag, "chat.read.receipt.write", Date.now(), receiptError);
|
|
112914
113207
|
}
|
|
112915
|
-
for (const result of results.slice(
|
|
113208
|
+
for (const result of results.slice(1)) {
|
|
112916
113209
|
if (result?.status === "rejected") {
|
|
112917
113210
|
markError(diag, "chat.message.expiry.write", Date.now(), result.reason);
|
|
112918
113211
|
}
|
|
@@ -113455,8 +113748,11 @@ function withSharedMediaUpload(cloud, media, meta = {}) {
|
|
|
113455
113748
|
};
|
|
113456
113749
|
}
|
|
113457
113750
|
function uploadMessageAttachment(cloud, media, senderPubkey, senderPrivkey, receiverChatPK, attachment = {}) {
|
|
113751
|
+
if (!senderPubkey || !senderPrivkey) {
|
|
113752
|
+
throw new Error("vault locked");
|
|
113753
|
+
}
|
|
113458
113754
|
if (typeof media?.uploadAttachment === "function") {
|
|
113459
|
-
return media.uploadAttachment(
|
|
113755
|
+
return media.uploadAttachment(attachment);
|
|
113460
113756
|
}
|
|
113461
113757
|
return uploadAttachmentMsg(cloud, senderPubkey, senderPrivkey, receiverChatPK, withMediaUpload(cloud, media, attachment));
|
|
113462
113758
|
}
|
|
@@ -113754,17 +114050,21 @@ ${cid}` : "";
|
|
|
113754
114050
|
const requiredPreview = previewRequired || sendOptions.chatExists !== true;
|
|
113755
114051
|
let local = await showLocalMessage(peerChatPK, message, sendOptions);
|
|
113756
114052
|
let committed = false;
|
|
114053
|
+
let sent = false;
|
|
114054
|
+
const markSent = () => {
|
|
114055
|
+
if (sent)
|
|
114056
|
+
return;
|
|
114057
|
+
sent = true;
|
|
114058
|
+
sentChatIdsRef.current.add(local.chatId);
|
|
114059
|
+
markLocalStatus(local.chatId, local.cid, LOCAL_SENT);
|
|
114060
|
+
};
|
|
113757
114061
|
const markCommitted = () => {
|
|
113758
114062
|
if (committed)
|
|
113759
114063
|
return;
|
|
113760
114064
|
committed = true;
|
|
113761
|
-
|
|
114065
|
+
markSent();
|
|
113762
114066
|
markDone(diag, "chat.send.commit", startedAt, { type: local?.t || "txt", previewRequired: !!requiredPreview });
|
|
113763
114067
|
};
|
|
113764
|
-
const markSent = () => {
|
|
113765
|
-
sentChatIdsRef.current.add(local.chatId);
|
|
113766
|
-
markLocalStatus(local.chatId, local.cid, LOCAL_SENT);
|
|
113767
|
-
};
|
|
113768
114068
|
return await new Promise((resolve, reject) => {
|
|
113769
114069
|
const job = {
|
|
113770
114070
|
previewKey: local.chatId,
|
|
@@ -113982,7 +114282,8 @@ ${cid}` : "";
|
|
|
113982
114282
|
linkId: local.linkId,
|
|
113983
114283
|
version: local.version,
|
|
113984
114284
|
sendOptions,
|
|
113985
|
-
nextAttachment: prepared.nextAttachment
|
|
114285
|
+
nextAttachment: prepared.nextAttachment,
|
|
114286
|
+
committed: false
|
|
113986
114287
|
};
|
|
113987
114288
|
}));
|
|
113988
114289
|
return await new Promise((resolve, reject) => {
|
|
@@ -113991,7 +114292,9 @@ ${cid}` : "";
|
|
|
113991
114292
|
reject,
|
|
113992
114293
|
onError: () => {
|
|
113993
114294
|
for (const item of locals) {
|
|
113994
|
-
|
|
114295
|
+
if (!item.committed) {
|
|
114296
|
+
markLocalStatus(item.chatId, item.cid, LOCAL_FAILED);
|
|
114297
|
+
}
|
|
113995
114298
|
}
|
|
113996
114299
|
},
|
|
113997
114300
|
run: async () => {
|
|
@@ -114006,6 +114309,7 @@ ${cid}` : "";
|
|
|
114006
114309
|
results.push({ peerChatPK: item.peerChatPK, ok: false, error: uploadError });
|
|
114007
114310
|
continue;
|
|
114008
114311
|
}
|
|
114312
|
+
let sentMessage;
|
|
114009
114313
|
try {
|
|
114010
114314
|
let uploaded = uploads.get(uploadKey);
|
|
114011
114315
|
if (!uploaded) {
|
|
@@ -114018,17 +114322,32 @@ ${cid}` : "";
|
|
|
114018
114322
|
cid: item.cid,
|
|
114019
114323
|
s: chatPK
|
|
114020
114324
|
};
|
|
114021
|
-
|
|
114325
|
+
sentMessage = withMessageRetention(sent, item.sendOptions.retention);
|
|
114022
114326
|
rememberCachedLocalMedia(item.chatId, item.cid, sentMessage);
|
|
114023
|
-
await sendMsg(cloud, chatPK, chatPrivateKey, item.peerChatPK, sentMessage, {
|
|
114024
|
-
|
|
114327
|
+
await sendMsg(cloud, chatPK, chatPrivateKey, item.peerChatPK, sentMessage, {
|
|
114328
|
+
...item.sendOptions,
|
|
114329
|
+
chatId: item.chatId,
|
|
114330
|
+
linkId: item.linkId,
|
|
114331
|
+
senderUid: uid,
|
|
114332
|
+
onCommitted: () => {
|
|
114333
|
+
if (item.committed)
|
|
114334
|
+
return;
|
|
114335
|
+
item.committed = true;
|
|
114336
|
+
sentChatIdsRef.current.add(item.chatId);
|
|
114337
|
+
markLocalStatus(item.chatId, item.cid, LOCAL_SENT);
|
|
114338
|
+
}
|
|
114339
|
+
});
|
|
114025
114340
|
results.push({ peerChatPK: item.peerChatPK, ok: true, message: sentMessage });
|
|
114026
114341
|
} catch (error) {
|
|
114027
114342
|
if (!uploads.has(uploadKey)) {
|
|
114028
114343
|
uploadErrors.set(uploadKey, error);
|
|
114029
114344
|
}
|
|
114030
|
-
|
|
114031
|
-
|
|
114345
|
+
if (item.committed) {
|
|
114346
|
+
results.push({ peerChatPK: item.peerChatPK, ok: true, message: sentMessage });
|
|
114347
|
+
} else {
|
|
114348
|
+
markLocalStatus(item.chatId, item.cid, LOCAL_FAILED);
|
|
114349
|
+
results.push({ peerChatPK: item.peerChatPK, ok: false, error });
|
|
114350
|
+
}
|
|
114032
114351
|
}
|
|
114033
114352
|
}
|
|
114034
114353
|
return results;
|
|
@@ -114835,7 +115154,6 @@ async function decryptRecordEntries(records, userChatPK, userPrivKey, peerChatPK
|
|
|
114835
115154
|
return [];
|
|
114836
115155
|
}
|
|
114837
115156
|
const signingKeysVersion = signingKeysFingerprint(options?.signingKeysByChatKey);
|
|
114838
|
-
const pair = await getCachedPair(userChatPK, userPrivKey, peerChatPK, { chatId: options?.chatId });
|
|
114839
115157
|
const entryOptions = { ...options, signingKeysVersion };
|
|
114840
115158
|
const shouldYield = positiveInt(options?.yieldEvery, 0) > 0;
|
|
114841
115159
|
const entries = new Array(source.length).fill(null);
|
|
@@ -114852,38 +115170,40 @@ async function decryptRecordEntries(records, userChatPK, userPrivKey, peerChatPK
|
|
|
114852
115170
|
}
|
|
114853
115171
|
pending.push({ record, index });
|
|
114854
115172
|
};
|
|
114855
|
-
|
|
114856
|
-
|
|
114857
|
-
|
|
114858
|
-
|
|
114859
|
-
|
|
114860
|
-
|
|
114861
|
-
|
|
114862
|
-
|
|
114863
|
-
|
|
115173
|
+
return withCachedPair(userChatPK, userPrivKey, peerChatPK, { chatId: options?.chatId }, async (pair) => {
|
|
115174
|
+
const openPending = async (pending) => {
|
|
115175
|
+
if (!pending.length) {
|
|
115176
|
+
return;
|
|
115177
|
+
}
|
|
115178
|
+
const opened = await decryptRecordBatchWithPair(pending.map((item) => item.record), pair, cache, entryOptions);
|
|
115179
|
+
for (let index = 0;index < opened.length; index += 1) {
|
|
115180
|
+
const entry = opened[index];
|
|
115181
|
+
if (entry) {
|
|
115182
|
+
entries[pending[index].index] = entry;
|
|
115183
|
+
}
|
|
114864
115184
|
}
|
|
115185
|
+
};
|
|
115186
|
+
if (!options?.signal && !shouldYield) {
|
|
115187
|
+
const pending = [];
|
|
115188
|
+
for (let index = 0;index < source.length; index += 1) {
|
|
115189
|
+
collectRecord(source[index], index, pending);
|
|
115190
|
+
}
|
|
115191
|
+
await openPending(pending);
|
|
115192
|
+
return entries.filter(Boolean);
|
|
114865
115193
|
}
|
|
114866
|
-
|
|
114867
|
-
|
|
114868
|
-
|
|
114869
|
-
|
|
114870
|
-
|
|
115194
|
+
const chunkSize = positiveInt(options?.yieldEvery, source.length || 1);
|
|
115195
|
+
for (let index = 0;index < source.length; index += chunkSize) {
|
|
115196
|
+
throwIfAborted(options?.signal);
|
|
115197
|
+
const chunk = source.slice(index, index + chunkSize);
|
|
115198
|
+
const pending = [];
|
|
115199
|
+
for (let offset = 0;offset < chunk.length; offset += 1) {
|
|
115200
|
+
collectRecord(chunk[offset], index + offset, pending);
|
|
115201
|
+
}
|
|
115202
|
+
await openPending(pending);
|
|
115203
|
+
await maybeYield(index + chunk.length, options);
|
|
114871
115204
|
}
|
|
114872
|
-
await openPending(pending);
|
|
114873
115205
|
return entries.filter(Boolean);
|
|
114874
|
-
}
|
|
114875
|
-
const chunkSize = positiveInt(options?.yieldEvery, source.length || 1);
|
|
114876
|
-
for (let index = 0;index < source.length; index += chunkSize) {
|
|
114877
|
-
throwIfAborted(options?.signal);
|
|
114878
|
-
const chunk = source.slice(index, index + chunkSize);
|
|
114879
|
-
const pending = [];
|
|
114880
|
-
for (let offset = 0;offset < chunk.length; offset += 1) {
|
|
114881
|
-
collectRecord(chunk[offset], index + offset, pending);
|
|
114882
|
-
}
|
|
114883
|
-
await openPending(pending);
|
|
114884
|
-
await maybeYield(index + chunk.length, options);
|
|
114885
|
-
}
|
|
114886
|
-
return entries.filter(Boolean);
|
|
115206
|
+
});
|
|
114887
115207
|
}
|
|
114888
115208
|
function messageQueryLimit(pageSize) {
|
|
114889
115209
|
return positiveInt(pageSize, MSG_BATCH_SIZE);
|
|
@@ -114936,7 +115256,11 @@ function readableEntryWindow(entries, pageSize, chatPK, peerChatPK, options = {}
|
|
|
114936
115256
|
const limitCount = positiveInt(pageSize, MSG_BATCH_SIZE);
|
|
114937
115257
|
const projectedEntries = readableProjectedEntries(source, chatPK, peerChatPK, options);
|
|
114938
115258
|
if (!projectedEntries.length) {
|
|
114939
|
-
return {
|
|
115259
|
+
return {
|
|
115260
|
+
count: 0,
|
|
115261
|
+
entries: source.filter((entry) => isProjectionSupportMsg(entry?.message)),
|
|
115262
|
+
start: 0
|
|
115263
|
+
};
|
|
114940
115264
|
}
|
|
114941
115265
|
const indexes = projectedEntries.map((entry) => entry.index);
|
|
114942
115266
|
const projectedByIndex = new Map(projectedEntries.map((entry) => [entry.index, entry.message]));
|
|
@@ -115229,9 +115553,10 @@ async function decryptMsg(msgData, userChatPK, userPrivKey, peerChatPK, options
|
|
|
115229
115553
|
return null;
|
|
115230
115554
|
}
|
|
115231
115555
|
try {
|
|
115232
|
-
|
|
115233
|
-
|
|
115234
|
-
|
|
115556
|
+
return await withCachedPair(userChatPK, userPrivKey, peerChatPK, { chatId: options?.chatId }, async (pair) => {
|
|
115557
|
+
const message = await openMsg(pair, msgData, { signingKeysByChatKey: options?.signingKeysByChatKey, crypto: options?.crypto });
|
|
115558
|
+
return normalizeDecryptedMsg(msgData, message);
|
|
115559
|
+
});
|
|
115235
115560
|
} catch {
|
|
115236
115561
|
return null;
|
|
115237
115562
|
}
|
|
@@ -116301,12 +116626,12 @@ function warmKeyStore(ref) {
|
|
|
116301
116626
|
}
|
|
116302
116627
|
return ref.current;
|
|
116303
116628
|
}
|
|
116304
|
-
function readMessageMedia2(cloud, media,
|
|
116629
|
+
function readMessageMedia2(cloud, media, message) {
|
|
116305
116630
|
const readChatMedia = cloud?.chat?.media?.read;
|
|
116306
116631
|
if (typeof media?.readMessageFile === "function") {
|
|
116307
|
-
return media.readMessageFile(readChatMedia,
|
|
116632
|
+
return media.readMessageFile(readChatMedia, message);
|
|
116308
116633
|
}
|
|
116309
|
-
return readMsgMedia(readChatMedia,
|
|
116634
|
+
return readMsgMedia(readChatMedia, message);
|
|
116310
116635
|
}
|
|
116311
116636
|
function isDenied3(error) {
|
|
116312
116637
|
return error?.code === "permission-denied";
|
|
@@ -116513,12 +116838,12 @@ function createChatMessageBatches({ cloud, media = {}, chatPK, chatPrivateKey, c
|
|
|
116513
116838
|
return;
|
|
116514
116839
|
}
|
|
116515
116840
|
const tasks = buildMediaTasks();
|
|
116516
|
-
const readFile = async (
|
|
116841
|
+
const readFile = async (_peerChatPK, message) => {
|
|
116517
116842
|
const cached = await readCachedMedia(localCache, message);
|
|
116518
116843
|
if (cached?.byteLength) {
|
|
116519
116844
|
return cached;
|
|
116520
116845
|
}
|
|
116521
|
-
const bytes = await readMessageMedia2(cloud, media,
|
|
116846
|
+
const bytes = await readMessageMedia2(cloud, media, message);
|
|
116522
116847
|
if (bytes?.byteLength) {
|
|
116523
116848
|
saveMedia(localCache, message, bytes, message);
|
|
116524
116849
|
}
|
|
@@ -117265,6 +117590,16 @@ function pingSigningKeys(ping, existing) {
|
|
|
117265
117590
|
[ping.payload.senderChatPK]: ping.payload.signingPublicKey
|
|
117266
117591
|
};
|
|
117267
117592
|
}
|
|
117593
|
+
function chatSettingsFromPreview(settings, preview2) {
|
|
117594
|
+
const current = normalizeChatSettings(settings);
|
|
117595
|
+
if (!isSystemMsg(preview2)) {
|
|
117596
|
+
return current;
|
|
117597
|
+
}
|
|
117598
|
+
return {
|
|
117599
|
+
...current,
|
|
117600
|
+
retention: cleanChatRetention(preview2.retention)
|
|
117601
|
+
};
|
|
117602
|
+
}
|
|
117268
117603
|
function chatFromPing(ping, entryId, existing, preview2, userChatPK, ms, options = {}) {
|
|
117269
117604
|
const ts = timestampMs(ms, null) ?? timestampMs(existing?.ts, null) ?? timestampMs(preview2?.ts, null) ?? 0;
|
|
117270
117605
|
if (!ts) {
|
|
@@ -117281,10 +117616,11 @@ function chatFromPing(ping, entryId, existing, preview2, userChatPK, ms, options
|
|
|
117281
117616
|
peerChatPK: ping.payload.senderChatPK,
|
|
117282
117617
|
peerUid: existing?.peerUid || cleanText(ping.payload.senderUid) || null,
|
|
117283
117618
|
signingKeysByChatKey: pingSigningKeys(ping, existing),
|
|
117284
|
-
settings: existing?.settings,
|
|
117619
|
+
settings: chatSettingsFromPreview(existing?.settings, preview2),
|
|
117285
117620
|
saved: existing?.saved || null,
|
|
117286
117621
|
readMs,
|
|
117287
117622
|
startMs,
|
|
117623
|
+
signerShared: existing?.signerShared === true,
|
|
117288
117624
|
preview: visiblePreview,
|
|
117289
117625
|
ts,
|
|
117290
117626
|
unseen: visiblePreview ? isChatUnseenForUser({ preview: visiblePreview, readMs }, userChatPK) : false
|
|
@@ -117340,10 +117676,11 @@ async function savePing(cloud, uid, userChatPK, userPrivKey, ping, options = {})
|
|
|
117340
117676
|
peerUid: peerUid2 || existing?.peerUid,
|
|
117341
117677
|
peerSigningPublicKey: ping.payload.signingPublicKey || existing?.signingKeysByChatKey?.[ping.payload.senderChatPK],
|
|
117342
117678
|
signingKeysByChatKey,
|
|
117343
|
-
settings: existing?.settings,
|
|
117679
|
+
settings: chatSettingsFromPreview(existing?.settings, preview2),
|
|
117344
117680
|
preview: preview2 || existing?.preview,
|
|
117345
117681
|
readMs: existing?.readMs,
|
|
117346
|
-
startMs: existing ? existing.startMs : timestampMs(options.startPreview?.ts ?? preview2?.ts, null, { positive: true })
|
|
117682
|
+
startMs: existing ? existing.startMs : timestampMs(options.startPreview?.ts ?? preview2?.ts, null, { positive: true }),
|
|
117683
|
+
signerShared: existing?.signerShared === true
|
|
117347
117684
|
});
|
|
117348
117685
|
const body = await sealOwnChatEntry(userPrivKey, entryId, entry);
|
|
117349
117686
|
const record = { body };
|
|
@@ -117353,14 +117690,16 @@ async function savePing(cloud, uid, userChatPK, userPrivKey, ping, options = {})
|
|
|
117353
117690
|
await cloud.user.chats.write(uid, entryId, record);
|
|
117354
117691
|
return true;
|
|
117355
117692
|
}
|
|
117356
|
-
function chatWithReadPreview(existing, preview2, userChatPK) {
|
|
117357
|
-
if (!existing?.id
|
|
117693
|
+
function chatWithReadPreview(existing, preview2, userChatPK, fields = {}) {
|
|
117694
|
+
if (!existing?.id) {
|
|
117358
117695
|
return null;
|
|
117359
117696
|
}
|
|
117360
117697
|
return {
|
|
117361
117698
|
...existing,
|
|
117362
|
-
|
|
117363
|
-
|
|
117699
|
+
signingKeysByChatKey: fields.signingKeysByChatKey || existing.signingKeysByChatKey,
|
|
117700
|
+
peerUid: fields.peerUid || existing.peerUid,
|
|
117701
|
+
preview: preview2 || existing.preview,
|
|
117702
|
+
unseen: preview2 ? isChatUnseenForUser({ preview: preview2, readMs: existing.readMs }, userChatPK) : existing.unseen
|
|
117364
117703
|
};
|
|
117365
117704
|
}
|
|
117366
117705
|
function patchReadPingPreview(existing, receiptPreview, userChatPK) {
|
|
@@ -117441,6 +117780,8 @@ async function processInbox(cloud, uid, userChatPK, userPrivKey, options = {}) {
|
|
|
117441
117780
|
let current = chatsById.get(group.chatId) || null;
|
|
117442
117781
|
let wrote = false;
|
|
117443
117782
|
let handled = false;
|
|
117783
|
+
const identityPing = group.message?.ping || group.read?.ping || group.delete?.ping;
|
|
117784
|
+
const peerUid2 = await resolvePingUid(cloud, identityPing?.payload);
|
|
117444
117785
|
if (group.message) {
|
|
117445
117786
|
const item = group.message;
|
|
117446
117787
|
const entryId = ownChatEntryId(userPrivKey, item.chatId);
|
|
@@ -117461,7 +117802,8 @@ async function processInbox(cloud, uid, userChatPK, userPrivKey, options = {}) {
|
|
|
117461
117802
|
signingKeysByChatKey,
|
|
117462
117803
|
preview: preview2,
|
|
117463
117804
|
startPreview,
|
|
117464
|
-
tsMs: item.ms
|
|
117805
|
+
tsMs: item.ms,
|
|
117806
|
+
peerUid: peerUid2
|
|
117465
117807
|
});
|
|
117466
117808
|
}
|
|
117467
117809
|
if (group.read) {
|
|
@@ -117471,22 +117813,24 @@ async function processInbox(cloud, uid, userChatPK, userPrivKey, options = {}) {
|
|
|
117471
117813
|
const signingKeysByChatKey = pingSigningKeys(item.ping, existing);
|
|
117472
117814
|
const receiptPreview = await readPingMsg(cloud, userChatPK, userPrivKey, item.ping, signingKeysByChatKey);
|
|
117473
117815
|
const openedPreview = patchReadPingPreview(existing, receiptPreview, userChatPK);
|
|
117474
|
-
const chat = chatWithReadPreview(current, openedPreview, userChatPK
|
|
117816
|
+
const chat = chatWithReadPreview(current || existing, openedPreview, userChatPK, {
|
|
117817
|
+
signingKeysByChatKey,
|
|
117818
|
+
peerUid: peerUid2
|
|
117819
|
+
});
|
|
117475
117820
|
handled = true;
|
|
117476
|
-
if (
|
|
117477
|
-
|
|
117478
|
-
|
|
117479
|
-
|
|
117480
|
-
options.onPingChat?.(chat);
|
|
117481
|
-
}
|
|
117482
|
-
const writeExisting = chat || existing;
|
|
117483
|
-
wrote = await savePing(cloud, uid, userChatPK, userPrivKey, item.ping, {
|
|
117484
|
-
existing: writeExisting,
|
|
117485
|
-
signingKeysByChatKey,
|
|
117486
|
-
preview: openedPreview,
|
|
117487
|
-
writeTs: false
|
|
117488
|
-
}) || wrote;
|
|
117821
|
+
if (chat) {
|
|
117822
|
+
current = chat;
|
|
117823
|
+
chatsById.set(chat.id, chat);
|
|
117824
|
+
options.onPingChat?.(chat);
|
|
117489
117825
|
}
|
|
117826
|
+
const writeExisting = chat || existing;
|
|
117827
|
+
wrote = await savePing(cloud, uid, userChatPK, userPrivKey, item.ping, {
|
|
117828
|
+
existing: writeExisting,
|
|
117829
|
+
signingKeysByChatKey,
|
|
117830
|
+
preview: openedPreview || existing?.preview || null,
|
|
117831
|
+
writeTs: false,
|
|
117832
|
+
peerUid: peerUid2
|
|
117833
|
+
}) || wrote;
|
|
117490
117834
|
}
|
|
117491
117835
|
if (group.delete) {
|
|
117492
117836
|
const item = group.delete;
|
|
@@ -117507,7 +117851,8 @@ async function processInbox(cloud, uid, userChatPK, userPrivKey, options = {}) {
|
|
|
117507
117851
|
wrote = await savePing(cloud, uid, userChatPK, userPrivKey, item.ping, {
|
|
117508
117852
|
existing: writeExisting,
|
|
117509
117853
|
signingKeysByChatKey,
|
|
117510
|
-
preview: deletedPreview
|
|
117854
|
+
preview: deletedPreview,
|
|
117855
|
+
peerUid: peerUid2
|
|
117511
117856
|
}) || wrote;
|
|
117512
117857
|
}
|
|
117513
117858
|
}
|
|
@@ -117529,6 +117874,7 @@ var init_inbox = __esm(() => {
|
|
|
117529
117874
|
init_ping();
|
|
117530
117875
|
init_query();
|
|
117531
117876
|
init_chats();
|
|
117877
|
+
init_ttl();
|
|
117532
117878
|
init_time();
|
|
117533
117879
|
init_protocol();
|
|
117534
117880
|
});
|
|
@@ -117912,6 +118258,7 @@ async function decryptChatEntry(entryRecord, userChatPK, userPrivKey) {
|
|
|
117912
118258
|
saved: entry.saved || null,
|
|
117913
118259
|
readMs,
|
|
117914
118260
|
startMs,
|
|
118261
|
+
signerShared: entry.signerShared === true,
|
|
117915
118262
|
preview: visiblePreview,
|
|
117916
118263
|
ts,
|
|
117917
118264
|
unseen: visiblePreview ? isChatUnseenForUser({ preview: visiblePreview, readMs }, userChatPK) : false
|
|
@@ -118024,6 +118371,7 @@ function createChatList({
|
|
|
118024
118371
|
let chats = [];
|
|
118025
118372
|
let peers = [];
|
|
118026
118373
|
let isChatDataReady = false;
|
|
118374
|
+
let isChatListLive = false;
|
|
118027
118375
|
let chatSourceReady = false;
|
|
118028
118376
|
let lastChat = null;
|
|
118029
118377
|
let serverChatIds = [];
|
|
@@ -118060,6 +118408,7 @@ function createChatList({
|
|
|
118060
118408
|
chats,
|
|
118061
118409
|
peers,
|
|
118062
118410
|
isChatDataReady,
|
|
118411
|
+
isChatListLive,
|
|
118063
118412
|
hasChats: chats.length > 0,
|
|
118064
118413
|
previewNow,
|
|
118065
118414
|
lastChat,
|
|
@@ -118093,6 +118442,13 @@ function createChatList({
|
|
|
118093
118442
|
isChatDataReady = value;
|
|
118094
118443
|
publish();
|
|
118095
118444
|
};
|
|
118445
|
+
const setIsChatListLive = (next) => {
|
|
118446
|
+
const value = nextValue(isChatListLive, next);
|
|
118447
|
+
if (Object.is(isChatListLive, value))
|
|
118448
|
+
return;
|
|
118449
|
+
isChatListLive = value;
|
|
118450
|
+
publish();
|
|
118451
|
+
};
|
|
118096
118452
|
const setLastChat = (next) => {
|
|
118097
118453
|
const value = nextValue(lastChat, next);
|
|
118098
118454
|
if (Object.is(lastChat, value))
|
|
@@ -118302,6 +118658,7 @@ function createChatList({
|
|
|
118302
118658
|
const resetChatList = (ready = false) => {
|
|
118303
118659
|
chatSourceReady = ready;
|
|
118304
118660
|
syncChatDataReady();
|
|
118661
|
+
setIsChatListLive(false);
|
|
118305
118662
|
setChats((prev) => prev.length ? [] : prev);
|
|
118306
118663
|
setPeers((prev) => prev.length ? [] : prev);
|
|
118307
118664
|
setLastChat((prev) => prev ? null : prev);
|
|
@@ -118391,6 +118748,7 @@ function createChatList({
|
|
|
118391
118748
|
resetAllChatState();
|
|
118392
118749
|
return;
|
|
118393
118750
|
}
|
|
118751
|
+
setIsChatListLive(false);
|
|
118394
118752
|
let cancelled = false;
|
|
118395
118753
|
const hydrateKey = localCache?.id ? `${localCache.id}:${chatPK}` : "";
|
|
118396
118754
|
if (hydrateKey && lastHydratedCacheKeyRef.current !== hydrateKey) {
|
|
@@ -118490,6 +118848,7 @@ function createChatList({
|
|
|
118490
118848
|
writeCache: true,
|
|
118491
118849
|
serverEndReached: cachedHistoryEndRef.current
|
|
118492
118850
|
});
|
|
118851
|
+
setIsChatListLive(true);
|
|
118493
118852
|
listenUpdateSeqRef.current += 1;
|
|
118494
118853
|
markDiag(diag, "chat.provider.listen.update", {
|
|
118495
118854
|
seq: listenUpdateSeqRef.current,
|
|
@@ -118532,6 +118891,7 @@ function createChatList({
|
|
|
118532
118891
|
markChatSourceReady();
|
|
118533
118892
|
fillVisibleChatPage();
|
|
118534
118893
|
}, (error) => {
|
|
118894
|
+
setIsChatListLive(false);
|
|
118535
118895
|
markError(diag, "chat.provider.listen", listenStartedAt, error);
|
|
118536
118896
|
if (shouldResetChatListAfterListenError(error)) {
|
|
118537
118897
|
resetAllChatState();
|
|
@@ -118685,6 +119045,7 @@ function createChatList({
|
|
|
118685
119045
|
chatExists: !!peerChat?.id || hasServerChatForPeer(peerChatPK),
|
|
118686
119046
|
receiverUid: peerChat?.peerUid || "",
|
|
118687
119047
|
peerSigningPublicKey: peerChat?.signingKeysByChatKey?.[peerChatPK] || "",
|
|
119048
|
+
signerShared: peerChat?.signerShared === true,
|
|
118688
119049
|
ownEntry: peerChat?.entryId ? peerChat : null
|
|
118689
119050
|
};
|
|
118690
119051
|
};
|
|
@@ -119382,6 +119743,7 @@ function createChatSession({
|
|
|
119382
119743
|
readCacheRef,
|
|
119383
119744
|
readWriteInterval,
|
|
119384
119745
|
getChatRetention,
|
|
119746
|
+
sendOptionsForPeer,
|
|
119385
119747
|
setChats,
|
|
119386
119748
|
diag
|
|
119387
119749
|
});
|
|
@@ -120526,7 +120888,7 @@ function createPeersApi({ cloud, network, avatarCache = null }) {
|
|
|
120526
120888
|
}
|
|
120527
120889
|
if (avatarVersion != null && typeof cloud.peer.avatar.read === "function") {
|
|
120528
120890
|
try {
|
|
120529
|
-
const bytes = await cloud.peer.avatar.read(uid);
|
|
120891
|
+
const bytes = await cloud.peer.avatar.read(uid, { version: avatarVersion });
|
|
120530
120892
|
const cachedSource = await writeCachedAvatar(uid, avatarVersion, bytes);
|
|
120531
120893
|
if (cachedSource) {
|
|
120532
120894
|
return cachedSource;
|
|
@@ -121063,6 +121425,10 @@ function getSatsBalance(result) {
|
|
|
121063
121425
|
}
|
|
121064
121426
|
return satsBalance;
|
|
121065
121427
|
}
|
|
121428
|
+
function displayBalanceValue(value) {
|
|
121429
|
+
const balance = Number(value);
|
|
121430
|
+
return Number.isSafeInteger(balance) && balance >= 0 ? balance : null;
|
|
121431
|
+
}
|
|
121066
121432
|
function samePlainObject(a, b) {
|
|
121067
121433
|
if (a === b) {
|
|
121068
121434
|
return true;
|
|
@@ -121091,9 +121457,10 @@ function sameTokenBalances(a, b) {
|
|
|
121091
121457
|
}
|
|
121092
121458
|
return true;
|
|
121093
121459
|
}
|
|
121094
|
-
function createWalletBalance({ wallet, diag, onChange = null }) {
|
|
121460
|
+
function createWalletBalance({ wallet, diag, initialDisplayBalance = null, onBalance = null, onChange = null }) {
|
|
121095
121461
|
let snapshot = {
|
|
121096
121462
|
balance: null,
|
|
121463
|
+
displayBalance: displayBalanceValue(initialDisplayBalance),
|
|
121097
121464
|
satsBalance: null,
|
|
121098
121465
|
tokenBalances: new Map,
|
|
121099
121466
|
balanceReady: false,
|
|
@@ -121103,10 +121470,28 @@ function createWalletBalance({ wallet, diag, onChange = null }) {
|
|
|
121103
121470
|
snapshot = { ...snapshot, ...changes };
|
|
121104
121471
|
onChange?.();
|
|
121105
121472
|
};
|
|
121473
|
+
const publishDisplayBalance = (changes, value, trusted = false) => {
|
|
121474
|
+
const displayBalance = displayBalanceValue(value);
|
|
121475
|
+
if (displayBalance == null || !trusted && !snapshot.balanceReady) {
|
|
121476
|
+
return null;
|
|
121477
|
+
}
|
|
121478
|
+
if (!Object.is(snapshot.displayBalance, displayBalance)) {
|
|
121479
|
+
changes.displayBalance = displayBalance;
|
|
121480
|
+
}
|
|
121481
|
+
return displayBalance;
|
|
121482
|
+
};
|
|
121106
121483
|
const setBalance = (nextBalance) => {
|
|
121107
121484
|
const value = typeof nextBalance === "function" ? nextBalance(snapshot.balance) : nextBalance;
|
|
121485
|
+
const changes = {};
|
|
121108
121486
|
if (!Object.is(snapshot.balance, value)) {
|
|
121109
|
-
|
|
121487
|
+
changes.balance = value;
|
|
121488
|
+
}
|
|
121489
|
+
const displayBalance = publishDisplayBalance(changes, value);
|
|
121490
|
+
if (Object.keys(changes).length) {
|
|
121491
|
+
publish(changes);
|
|
121492
|
+
}
|
|
121493
|
+
if (displayBalance != null) {
|
|
121494
|
+
onBalance?.(displayBalance);
|
|
121110
121495
|
}
|
|
121111
121496
|
};
|
|
121112
121497
|
const setTokenBalances = (nextTokenBalances) => {
|
|
@@ -121115,12 +121500,13 @@ function createWalletBalance({ wallet, diag, onChange = null }) {
|
|
|
121115
121500
|
publish({ tokenBalances: new Map(source) });
|
|
121116
121501
|
}
|
|
121117
121502
|
};
|
|
121118
|
-
const setBalanceResult = (result) => {
|
|
121503
|
+
const setBalanceResult = (result, { ready = false } = {}) => {
|
|
121119
121504
|
const changes = {};
|
|
121120
121505
|
const nextBalance = getBalanceValue(result);
|
|
121121
121506
|
if (nextBalance != null && !Object.is(snapshot.balance, nextBalance)) {
|
|
121122
121507
|
changes.balance = nextBalance;
|
|
121123
121508
|
}
|
|
121509
|
+
const nextDisplayBalance = publishDisplayBalance(changes, nextBalance, true);
|
|
121124
121510
|
const nextSatsBalance = getSatsBalance(result);
|
|
121125
121511
|
if (nextSatsBalance && !samePlainObject(snapshot.satsBalance, nextSatsBalance)) {
|
|
121126
121512
|
changes.satsBalance = nextSatsBalance;
|
|
@@ -121129,9 +121515,15 @@ function createWalletBalance({ wallet, diag, onChange = null }) {
|
|
|
121129
121515
|
if (nextTokenBalances && !sameTokenBalances(snapshot.tokenBalances, nextTokenBalances)) {
|
|
121130
121516
|
changes.tokenBalances = new Map(nextTokenBalances);
|
|
121131
121517
|
}
|
|
121518
|
+
if (ready && !snapshot.balanceReady) {
|
|
121519
|
+
changes.balanceReady = true;
|
|
121520
|
+
}
|
|
121132
121521
|
if (Object.keys(changes).length) {
|
|
121133
121522
|
publish(changes);
|
|
121134
121523
|
}
|
|
121524
|
+
if (nextDisplayBalance != null) {
|
|
121525
|
+
onBalance?.(nextDisplayBalance);
|
|
121526
|
+
}
|
|
121135
121527
|
};
|
|
121136
121528
|
const setSatsBalanceResult = (nextSatsBalance) => {
|
|
121137
121529
|
if (!nextSatsBalance || typeof nextSatsBalance !== "object") {
|
|
@@ -121144,9 +121536,13 @@ function createWalletBalance({ wallet, diag, onChange = null }) {
|
|
|
121144
121536
|
if (nextSatsBalance.available != null && !Object.is(snapshot.balance, nextSatsBalance.available)) {
|
|
121145
121537
|
changes.balance = nextSatsBalance.available;
|
|
121146
121538
|
}
|
|
121539
|
+
const nextDisplayBalance = publishDisplayBalance(changes, nextSatsBalance.available);
|
|
121147
121540
|
if (Object.keys(changes).length) {
|
|
121148
121541
|
publish(changes);
|
|
121149
121542
|
}
|
|
121543
|
+
if (nextDisplayBalance != null) {
|
|
121544
|
+
onBalance?.(nextDisplayBalance);
|
|
121545
|
+
}
|
|
121150
121546
|
};
|
|
121151
121547
|
const getBalance = async () => {
|
|
121152
121548
|
if (!wallet) {
|
|
@@ -121160,7 +121556,7 @@ function createWalletBalance({ wallet, diag, onChange = null }) {
|
|
|
121160
121556
|
}
|
|
121161
121557
|
try {
|
|
121162
121558
|
const result = await wallet.getBalance();
|
|
121163
|
-
setBalanceResult(result);
|
|
121559
|
+
setBalanceResult(result, { ready: true });
|
|
121164
121560
|
markDone(diag, "wallet.balance", startedAt, { hasBalance: getBalanceValue(result) != null, hasSatsBalance: !!getSatsBalance(result), hasTokenBalances: !!getTokenBalances(result) });
|
|
121165
121561
|
} catch (error) {
|
|
121166
121562
|
markError(diag, "wallet.balance", startedAt, error);
|
|
@@ -121180,6 +121576,7 @@ function createWalletBalance({ wallet, diag, onChange = null }) {
|
|
|
121180
121576
|
const reset = () => {
|
|
121181
121577
|
snapshot = {
|
|
121182
121578
|
balance: null,
|
|
121579
|
+
displayBalance: null,
|
|
121183
121580
|
satsBalance: null,
|
|
121184
121581
|
tokenBalances: new Map,
|
|
121185
121582
|
balanceReady: false,
|
|
@@ -121196,7 +121593,7 @@ function createWalletBalance({ wallet, diag, onChange = null }) {
|
|
|
121196
121593
|
setSatsBalanceResult
|
|
121197
121594
|
};
|
|
121198
121595
|
}
|
|
121199
|
-
var
|
|
121596
|
+
var init_balance2 = () => {};
|
|
121200
121597
|
|
|
121201
121598
|
// ../../shared/wallet/deposits.js
|
|
121202
121599
|
async function getClaimableDepositUtxos(wallet, options = {}) {
|
|
@@ -122221,11 +122618,6 @@ function createWalletPrivacy({ wallet, ghostWallet, diag }) {
|
|
|
122221
122618
|
const startedAt = Date.now();
|
|
122222
122619
|
const desired = desiredPrivacy;
|
|
122223
122620
|
markDiag(diag, "wallet.privacy.start", { ghostWallet: desired });
|
|
122224
|
-
const current = typeof wallet.getWalletSettings === "function" ? await wallet.getWalletSettings() : null;
|
|
122225
|
-
if (closed || requestRevision !== revision || current?.privateEnabled === true === desired) {
|
|
122226
|
-
markDone(diag, "wallet.privacy", startedAt, { changed: false, cancelled: closed || requestRevision !== revision });
|
|
122227
|
-
return;
|
|
122228
|
-
}
|
|
122229
122621
|
await wallet.setPrivacyEnabled(desired);
|
|
122230
122622
|
markDone(diag, "wallet.privacy", startedAt, { changed: true });
|
|
122231
122623
|
}).catch((error) => {
|
|
@@ -122979,8 +123371,8 @@ function pendingTransfers(transfers = []) {
|
|
|
122979
123371
|
function pendingTransferIds(transfers = []) {
|
|
122980
123372
|
return pendingTransfers(transfers).map((tx) => String(tx.id));
|
|
122981
123373
|
}
|
|
122982
|
-
function
|
|
122983
|
-
return pendingTransfers(transfers).filter(
|
|
123374
|
+
function pendingIncomingTransfers(transfers = []) {
|
|
123375
|
+
return pendingTransfers(transfers).filter(isIncomingTransfer);
|
|
122984
123376
|
}
|
|
122985
123377
|
function uniqueIds(ids = []) {
|
|
122986
123378
|
return [...new Set((Array.isArray(ids) ? ids : [ids]).map((id) => String(id || "")).filter(Boolean))];
|
|
@@ -123075,7 +123467,7 @@ function adaptiveClaimBatchSize(maxBatchSize, queueDepth) {
|
|
|
123075
123467
|
}
|
|
123076
123468
|
return 1;
|
|
123077
123469
|
}
|
|
123078
|
-
function createWalletTransferSession({ wallet, walletPK, localCache, claimIncomingTransfers, pendingClaimBatchSize = null, eagerOutgoingStatusRefresh = false, transferStore, appState = null, deferBackgroundWork = null, backgroundSignal = null, diag }) {
|
|
123470
|
+
function createWalletTransferSession({ wallet, walletPK, localCache, claimIncomingTransfers, pendingClaimBatchSize = null, eagerOutgoingStatusRefresh = false, eagerCacheHistory = true, transferStore, appState = null, deferBackgroundWork = null, backgroundSignal = null, refreshBalance = null, diag }) {
|
|
123079
123471
|
if (!transferStore || typeof transferStore.subscribe !== "function" || typeof transferStore.getSnapshot !== "function" || typeof transferStore.getCacheState !== "function" || typeof transferStore.setHistory !== "function") {
|
|
123080
123472
|
throw new Error("createWalletTransferSession requires transferStore");
|
|
123081
123473
|
}
|
|
@@ -123089,6 +123481,7 @@ function createWalletTransferSession({ wallet, walletPK, localCache, claimIncomi
|
|
|
123089
123481
|
const initialTransfers = canUseInitialStore ? transferStore.getTransfers() : [];
|
|
123090
123482
|
const initialHistoryTransfers = canUseInitialStore ? transferStore.getHistoryTransfers() : [];
|
|
123091
123483
|
const initialTxReady = canUseInitialStore && (initialStoreSnapshot.ready || initialTransfers.length > 0 || initialHistoryTransfers.length > 0);
|
|
123484
|
+
const initialCacheReady = initialTxReady && (eagerCacheHistory === false || initialStoreSnapshot.serverEndReached === true && initialHistoryTransfers.length >= initialStoreSnapshot.historyCount);
|
|
123092
123485
|
const listeners = new Set;
|
|
123093
123486
|
let isTxLoading = false;
|
|
123094
123487
|
let publishedSnapshot = null;
|
|
@@ -123139,7 +123532,7 @@ function createWalletTransferSession({ wallet, walletPK, localCache, claimIncomi
|
|
|
123139
123532
|
const cacheHydrateKeyRef = { current: "" };
|
|
123140
123533
|
const cacheHydratePromiseRef = { current: null };
|
|
123141
123534
|
const fullCacheHydratePromiseRef = { current: null };
|
|
123142
|
-
const cacheWriteRef = { current: { timer: null, cache: null, state: null } };
|
|
123535
|
+
const cacheWriteRef = { current: { timer: null, cache: null, state: null, fullHistory: false } };
|
|
123143
123536
|
const cacheDirtyRef = { current: false };
|
|
123144
123537
|
const lastFetchAtRef = { current: 0 };
|
|
123145
123538
|
const claimBatchSize = Math.max(1, Number(pendingClaimBatchSize) || PENDING_TRANSFER_CLAIM_BATCH_SIZE);
|
|
@@ -123467,9 +123860,9 @@ function createWalletTransferSession({ wallet, walletPK, localCache, claimIncomi
|
|
|
123467
123860
|
return false;
|
|
123468
123861
|
}
|
|
123469
123862
|
const cachedTransfers = filterTransfersForWallet(cached.transfers, walletPKRef.current);
|
|
123470
|
-
const
|
|
123471
|
-
const
|
|
123472
|
-
const
|
|
123863
|
+
const cachedPublishTransfers = !publish && historyTransfersRef.current.length ? mergeTransferPageForWallet(historyTransfersRef.current, cachedTransfers, walletPKRef.current, "append") : cachedTransfers;
|
|
123864
|
+
const cachedPendingIncoming = pendingIncomingTransfers(cachedPublishTransfers);
|
|
123865
|
+
const cachedPending = pendingTransfers(cachedPublishTransfers);
|
|
123473
123866
|
rememberPendingTransferIds(cachedPending.map((tx) => tx.id));
|
|
123474
123867
|
markDiag(diag, label, {
|
|
123475
123868
|
elapsedMs: Date.now() - startedAt,
|
|
@@ -123608,9 +124001,11 @@ function createWalletTransferSession({ wallet, walletPK, localCache, claimIncomi
|
|
|
123608
124001
|
pending.timer = null;
|
|
123609
124002
|
const cache = pending.cache;
|
|
123610
124003
|
const state = pending.state;
|
|
124004
|
+
const fullHistory = pending.fullHistory;
|
|
123611
124005
|
pending.state = null;
|
|
123612
124006
|
if (cache && state) {
|
|
123613
|
-
writeCachedTransferState
|
|
124007
|
+
const write = fullHistory ? writeCachedTransferState : writeCachedTransferHeadState;
|
|
124008
|
+
write(cache, state);
|
|
123614
124009
|
}
|
|
123615
124010
|
};
|
|
123616
124011
|
const queueWalletFetch = (read) => {
|
|
@@ -123715,7 +124110,7 @@ function createWalletTransferSession({ wallet, walletPK, localCache, claimIncomi
|
|
|
123715
124110
|
return pendingQueryPromiseRef.current;
|
|
123716
124111
|
};
|
|
123717
124112
|
const pendingIncomingClaimCandidates = (sourceTransfers = []) => {
|
|
123718
|
-
return
|
|
124113
|
+
return pendingIncomingTransfers(sourceTransfers).filter((tx) => {
|
|
123719
124114
|
const id = String(tx?.id || "");
|
|
123720
124115
|
return id && !claimedTransferIdsRef.current.has(id);
|
|
123721
124116
|
});
|
|
@@ -123931,6 +124326,9 @@ function createWalletTransferSession({ wallet, walletPK, localCache, claimIncomi
|
|
|
123931
124326
|
batchClaimedIds.push(...staged);
|
|
123932
124327
|
flushClaimed();
|
|
123933
124328
|
const uniqueBatchClaimedIds = uniqueIds(batchClaimedIds);
|
|
124329
|
+
if (uniqueBatchClaimedIds.length && typeof refreshBalance === "function") {
|
|
124330
|
+
await refreshBalance();
|
|
124331
|
+
}
|
|
123934
124332
|
const unclaimedIds = candidateIds.filter((id) => !uniqueBatchClaimedIds.includes(id) && !claimedTransferIdsRef.current.has(id));
|
|
123935
124333
|
if (unclaimedIds.length) {
|
|
123936
124334
|
const elapsedMs = Date.now() - startedAt;
|
|
@@ -124453,7 +124851,7 @@ function createWalletTransferSession({ wallet, walletPK, localCache, claimIncomi
|
|
|
124453
124851
|
try {
|
|
124454
124852
|
await yieldToUi();
|
|
124455
124853
|
const pendingTransfers2 = await getPendingTransfersSnapshot();
|
|
124456
|
-
const incomingTransfers =
|
|
124854
|
+
const incomingTransfers = pendingIncomingTransfers(pendingTransfers2);
|
|
124457
124855
|
const claimCandidates = pendingIncomingClaimCandidates(incomingTransfers);
|
|
124458
124856
|
if (!incomingTransfers.length) {
|
|
124459
124857
|
markDone(diag, "wallet.pendingTxs.active", startedAt, { pending: 0, claimed: 0, reason });
|
|
@@ -124798,13 +125196,16 @@ function createWalletTransferSession({ wallet, walletPK, localCache, claimIncomi
|
|
|
124798
125196
|
if (cacheWriteRef.current.timer) {
|
|
124799
125197
|
clearTimeout(cacheWriteRef.current.timer);
|
|
124800
125198
|
}
|
|
124801
|
-
cacheWriteRef.current = { timer: null, cache: null, state: null };
|
|
125199
|
+
cacheWriteRef.current = { timer: null, cache: null, state: null, fullHistory: false };
|
|
124802
125200
|
cacheDirtyRef.current = false;
|
|
124803
125201
|
};
|
|
124804
125202
|
const startCacheHydration = () => {
|
|
124805
125203
|
if (!wallet || !localCache || !walletPKRef.current) {
|
|
124806
125204
|
return;
|
|
124807
125205
|
}
|
|
125206
|
+
if (initialCacheReady) {
|
|
125207
|
+
return;
|
|
125208
|
+
}
|
|
124808
125209
|
const hydrateKey = `${localCache.id || "cache"}:${walletPKRef.current}`;
|
|
124809
125210
|
if (cacheHydrateKeyRef.current === hydrateKey) {
|
|
124810
125211
|
return;
|
|
@@ -124829,7 +125230,7 @@ function createWalletTransferSession({ wallet, walletPK, localCache, claimIncomi
|
|
|
124829
125230
|
return;
|
|
124830
125231
|
}
|
|
124831
125232
|
const hydratedHead = applyCachedTransferState(cachedHead, { label: "wallet.provider.cache.hydrate", publish: true, startedAt: hydrateStartedAt });
|
|
124832
|
-
if (cancelled)
|
|
125233
|
+
if (cancelled || !eagerCacheHistory)
|
|
124833
125234
|
return;
|
|
124834
125235
|
await loadFullTransferCache({ label: "wallet.provider.cache.fullHydrate", publish: !hydratedHead });
|
|
124835
125236
|
}).catch((error) => {
|
|
@@ -124853,12 +125254,10 @@ function createWalletTransferSession({ wallet, walletPK, localCache, claimIncomi
|
|
|
124853
125254
|
if (!cacheDirtyRef.current && !cacheWriteRef.current.timer) {
|
|
124854
125255
|
return;
|
|
124855
125256
|
}
|
|
124856
|
-
if (historyTransfersRef.current.length < knownHistoryCountRef.current) {
|
|
124857
|
-
return;
|
|
124858
|
-
}
|
|
124859
125257
|
cacheDirtyRef.current = false;
|
|
124860
125258
|
cacheWriteRef.current.cache = localCache;
|
|
124861
125259
|
cacheWriteRef.current.state = transferStore.getCacheState();
|
|
125260
|
+
cacheWriteRef.current.fullHistory = historyTransfersRef.current.length >= knownHistoryCountRef.current;
|
|
124862
125261
|
if (cacheWriteRef.current.timer) {
|
|
124863
125262
|
clearTimeout(cacheWriteRef.current.timer);
|
|
124864
125263
|
}
|
|
@@ -124887,7 +125286,7 @@ function createWalletTransferSession({ wallet, walletPK, localCache, claimIncomi
|
|
|
124887
125286
|
serverHistoryComplete: serverHistoryCompleteRef.current,
|
|
124888
125287
|
hasMoreTxs: !historyComplete,
|
|
124889
125288
|
hasPendingTxs,
|
|
124890
|
-
hasPendingIncomingTxs:
|
|
125289
|
+
hasPendingIncomingTxs: pendingIncomingTransfers(transfersRef.current).length > 0,
|
|
124891
125290
|
beginSdkActivity,
|
|
124892
125291
|
getRecentTxs,
|
|
124893
125292
|
claimPendingIncomingTransfers: claimPendingIncomingTransfers2,
|
|
@@ -125238,10 +125637,12 @@ function createWalletSession({
|
|
|
125238
125637
|
pendingClaimBatchSize = null,
|
|
125239
125638
|
activeTransferRefreshMs = null,
|
|
125240
125639
|
eagerOutgoingStatusRefresh = false,
|
|
125640
|
+
eagerCacheHistory = true,
|
|
125241
125641
|
sentTransferRefreshDelayMs = null,
|
|
125242
125642
|
deferBackgroundWork = null,
|
|
125243
125643
|
appState = null,
|
|
125244
125644
|
transferStore,
|
|
125645
|
+
cachedBalance = null,
|
|
125245
125646
|
ghostWallet = true,
|
|
125246
125647
|
diag = null
|
|
125247
125648
|
}) {
|
|
@@ -125259,6 +125660,7 @@ function createWalletSession({
|
|
|
125259
125660
|
const txSubscriptions = createFieldSubscriptions(() => publishedSnapshot?.txValue);
|
|
125260
125661
|
let polling = null;
|
|
125261
125662
|
let readyDiag = null;
|
|
125663
|
+
let refreshWalletBalance = null;
|
|
125262
125664
|
const transferSession = createWalletTransferSession({
|
|
125263
125665
|
wallet,
|
|
125264
125666
|
walletPK,
|
|
@@ -125266,10 +125668,12 @@ function createWalletSession({
|
|
|
125266
125668
|
claimIncomingTransfers,
|
|
125267
125669
|
pendingClaimBatchSize,
|
|
125268
125670
|
eagerOutgoingStatusRefresh,
|
|
125671
|
+
eagerCacheHistory,
|
|
125269
125672
|
transferStore,
|
|
125270
125673
|
appState,
|
|
125271
125674
|
deferBackgroundWork,
|
|
125272
125675
|
backgroundSignal: backgroundAbort.signal,
|
|
125676
|
+
refreshBalance: () => refreshWalletBalance?.(),
|
|
125273
125677
|
diag
|
|
125274
125678
|
});
|
|
125275
125679
|
const getTransferState = () => transferSession.getSnapshot();
|
|
@@ -125289,7 +125693,16 @@ function createWalletSession({
|
|
|
125289
125693
|
listener();
|
|
125290
125694
|
}
|
|
125291
125695
|
};
|
|
125292
|
-
const balance = createWalletBalance({
|
|
125696
|
+
const balance = createWalletBalance({
|
|
125697
|
+
wallet,
|
|
125698
|
+
diag,
|
|
125699
|
+
initialDisplayBalance: cachedBalance,
|
|
125700
|
+
onBalance: (value) => {
|
|
125701
|
+
writeCachedWalletBalance(localCache, { walletPK, network, balance: value }).catch(() => {});
|
|
125702
|
+
},
|
|
125703
|
+
onChange: publish
|
|
125704
|
+
});
|
|
125705
|
+
refreshWalletBalance = balance.getBalance;
|
|
125293
125706
|
const funding = createFundingAddress({ wallet, network, diag, onChange: publish });
|
|
125294
125707
|
const updateWalletData = createWalletData({
|
|
125295
125708
|
wallet,
|
|
@@ -125370,13 +125783,14 @@ function createWalletSession({
|
|
|
125370
125783
|
wallet,
|
|
125371
125784
|
network,
|
|
125372
125785
|
balance: balanceState.balance,
|
|
125786
|
+
displayBalance: balanceState.displayBalance,
|
|
125373
125787
|
satsBalance: balanceState.satsBalance,
|
|
125374
125788
|
tokenBalances: balanceState.tokenBalances,
|
|
125375
125789
|
fundingAddress: funding.getSnapshot(),
|
|
125376
125790
|
balanceReady: balanceState.balanceReady,
|
|
125377
125791
|
isBalanceLoading: balanceState.isBalanceLoading,
|
|
125378
125792
|
isWalletDataReady: true,
|
|
125379
|
-
isWalletDataLoaded: balanceState.balanceReady
|
|
125793
|
+
isWalletDataLoaded: balanceState.balanceReady || currentTransferState.txReady,
|
|
125380
125794
|
refresh: claims.refresh,
|
|
125381
125795
|
requestTransferDiscoveryHotWindow: polling.requestTransferDiscoveryHotWindow,
|
|
125382
125796
|
claimDeposits: claims.claimDeposits,
|
|
@@ -125468,7 +125882,7 @@ function createWalletSession({
|
|
|
125468
125882
|
};
|
|
125469
125883
|
}
|
|
125470
125884
|
var init_session4 = __esm(() => {
|
|
125471
|
-
|
|
125885
|
+
init_balance2();
|
|
125472
125886
|
init_claims();
|
|
125473
125887
|
init_funding();
|
|
125474
125888
|
init_lightning();
|
|
@@ -125477,6 +125891,7 @@ var init_session4 = __esm(() => {
|
|
|
125477
125891
|
init_send2();
|
|
125478
125892
|
init_transfers2();
|
|
125479
125893
|
init_withdraw();
|
|
125894
|
+
init_localdata();
|
|
125480
125895
|
});
|
|
125481
125896
|
|
|
125482
125897
|
// ../../shared/wallet/transferstore.js
|
|
@@ -125685,6 +126100,7 @@ function createTransferStore() {
|
|
|
125685
126100
|
transfers: state.historyTransfers,
|
|
125686
126101
|
walletPK: state.walletPK,
|
|
125687
126102
|
serverEndReached: state.serverEndReached,
|
|
126103
|
+
historyCount: state.historyCount,
|
|
125688
126104
|
nextOffset: state.nextOffset,
|
|
125689
126105
|
oldestTxMs: state.serverEndReached ? state.oldestVerifiedTxMs : null
|
|
125690
126106
|
};
|
|
@@ -169168,9 +169584,13 @@ function peerRecordFromDoc(snap) {
|
|
|
169168
169584
|
function peerRecordsFromSnapshot(snapshot) {
|
|
169169
169585
|
return snapshot.docs.map(peerRecordFromDoc).filter(Boolean);
|
|
169170
169586
|
}
|
|
169171
|
-
function avatarPath(uid) {
|
|
169587
|
+
function avatarPath(uid, version8) {
|
|
169172
169588
|
requireUid(uid);
|
|
169173
|
-
|
|
169589
|
+
const avatarVersion = readAvatarVersion(version8);
|
|
169590
|
+
if (!avatarVersion) {
|
|
169591
|
+
throw new Error("avatar version required");
|
|
169592
|
+
}
|
|
169593
|
+
return `${uid}/avatars/${avatarVersion}.webp`;
|
|
169174
169594
|
}
|
|
169175
169595
|
function reportEvidencePath(reporter, targetUid, evidenceId) {
|
|
169176
169596
|
if (!reporter || !targetUid || !evidenceId) {
|
|
@@ -169236,6 +169656,7 @@ function createFirebaseCloud({ db, auth: auth2, getAuth: getAuth2, functions: fu
|
|
|
169236
169656
|
}
|
|
169237
169657
|
let activeVaultSigner = null;
|
|
169238
169658
|
const localSessionTerminations = new Set;
|
|
169659
|
+
const pendingAvatars = new Map;
|
|
169239
169660
|
function pageTs(value) {
|
|
169240
169661
|
if (value instanceof Timestamp2) {
|
|
169241
169662
|
return value;
|
|
@@ -169318,7 +169739,12 @@ function createFirebaseCloud({ db, auth: auth2, getAuth: getAuth2, functions: fu
|
|
|
169318
169739
|
"Content-Type": upload?.metadata?.contentType || "application/octet-stream"
|
|
169319
169740
|
};
|
|
169320
169741
|
if (typeof uploadSignedStorageBytes === "function") {
|
|
169321
|
-
await uploadSignedStorageBytes(url, upload?.body, { ...signed, method, headers, metadata: upload?.metadata || {}, path: upload?.path || "" })
|
|
169742
|
+
await uploadSignedStorageBytes(url, upload?.body, { ...signed, method, headers, metadata: upload?.metadata || {}, path: upload?.path || "" }).catch((error) => {
|
|
169743
|
+
if (error?.status === 412 && (headers["X-Goog-If-Generation-Match"] === "0" || headers["x-goog-if-generation-match"] === "0")) {
|
|
169744
|
+
return true;
|
|
169745
|
+
}
|
|
169746
|
+
throw error;
|
|
169747
|
+
});
|
|
169322
169748
|
return true;
|
|
169323
169749
|
}
|
|
169324
169750
|
const payload = typeof Blob !== "undefined" && upload?.body instanceof Blob ? upload.body : toBytes(upload?.body, "upload bytes");
|
|
@@ -169327,6 +169753,9 @@ function createFirebaseCloud({ db, auth: auth2, getAuth: getAuth2, functions: fu
|
|
|
169327
169753
|
headers,
|
|
169328
169754
|
body: payload
|
|
169329
169755
|
});
|
|
169756
|
+
if (response.status === 412 && (headers["X-Goog-If-Generation-Match"] === "0" || headers["x-goog-if-generation-match"] === "0")) {
|
|
169757
|
+
return true;
|
|
169758
|
+
}
|
|
169330
169759
|
if (!response.ok) {
|
|
169331
169760
|
const error = new Error(`signed upload failed (${response.status || 0})`);
|
|
169332
169761
|
error.status = response.status || 0;
|
|
@@ -169496,6 +169925,7 @@ function createFirebaseCloud({ db, auth: auth2, getAuth: getAuth2, functions: fu
|
|
|
169496
169925
|
}, onError);
|
|
169497
169926
|
}
|
|
169498
169927
|
async function logout() {
|
|
169928
|
+
pendingAvatars.clear();
|
|
169499
169929
|
await signOut(requireAuth());
|
|
169500
169930
|
return true;
|
|
169501
169931
|
}
|
|
@@ -169629,25 +170059,45 @@ function createFirebaseCloud({ db, auth: auth2, getAuth: getAuth2, functions: fu
|
|
|
169629
170059
|
await callFunction("acceptAgreement");
|
|
169630
170060
|
return true;
|
|
169631
170061
|
}
|
|
169632
|
-
async function
|
|
170062
|
+
async function setProfileAvatar(uid, data) {
|
|
169633
170063
|
requireUid(uid);
|
|
169634
|
-
|
|
169635
|
-
|
|
169636
|
-
|
|
169637
|
-
|
|
169638
|
-
|
|
169639
|
-
|
|
169640
|
-
|
|
169641
|
-
|
|
169642
|
-
|
|
169643
|
-
|
|
169644
|
-
|
|
169645
|
-
|
|
169646
|
-
|
|
169647
|
-
|
|
169648
|
-
|
|
169649
|
-
|
|
169650
|
-
|
|
170064
|
+
if (requireAuth().currentUser?.uid !== uid) {
|
|
170065
|
+
throw new Error("avatar account mismatch");
|
|
170066
|
+
}
|
|
170067
|
+
if (data == null) {
|
|
170068
|
+
pendingAvatars.delete(uid);
|
|
170069
|
+
const result = await callFunction("setAvatar", { body: null });
|
|
170070
|
+
if (result?.avatar != null) {
|
|
170071
|
+
throw new Error("avatar clear returned invalid state");
|
|
170072
|
+
}
|
|
170073
|
+
return { version: null };
|
|
170074
|
+
}
|
|
170075
|
+
const bytes = new Uint8Array(encryptedBytes(data, "avatar bytes"));
|
|
170076
|
+
const pending = { bytes, version: null, promise: null };
|
|
170077
|
+
const entries = pendingAvatars.get(uid) || [];
|
|
170078
|
+
pendingAvatars.set(uid, [...entries, pending]);
|
|
170079
|
+
pending.promise = callFunction("setAvatar", {
|
|
170080
|
+
body: cloudBytesBase64(bytes, "avatar bytes")
|
|
170081
|
+
}).then((result) => {
|
|
170082
|
+
const version8 = readAvatarVersion(result?.avatar);
|
|
170083
|
+
if (!version8) {
|
|
170084
|
+
throw new Error("avatar publish returned invalid version");
|
|
170085
|
+
}
|
|
170086
|
+
pending.version = version8;
|
|
170087
|
+
return version8;
|
|
170088
|
+
});
|
|
170089
|
+
try {
|
|
170090
|
+
return { version: await pending.promise };
|
|
170091
|
+
} catch (error) {
|
|
170092
|
+
const active = pendingAvatars.get(uid) || [];
|
|
170093
|
+
const remaining = active.filter((entry) => entry !== pending);
|
|
170094
|
+
if (remaining.length) {
|
|
170095
|
+
pendingAvatars.set(uid, remaining);
|
|
170096
|
+
} else {
|
|
170097
|
+
pendingAvatars.delete(uid);
|
|
170098
|
+
}
|
|
170099
|
+
throw error;
|
|
170100
|
+
}
|
|
169651
170101
|
}
|
|
169652
170102
|
async function writeProfileIdentity(identity) {
|
|
169653
170103
|
if (!identity || typeof identity !== "object" || Array.isArray(identity)) {
|
|
@@ -169784,13 +170234,28 @@ function createFirebaseCloud({ db, auth: auth2, getAuth: getAuth2, functions: fu
|
|
|
169784
170234
|
onUpdate?.(snap.exists() ? snap.data()?.active === true : false, { exists: snap.exists() });
|
|
169785
170235
|
}, onError);
|
|
169786
170236
|
}
|
|
169787
|
-
async function readPeerAvatar(uid) {
|
|
169788
|
-
|
|
170237
|
+
async function readPeerAvatar(uid, { version: version8 = null } = {}) {
|
|
170238
|
+
const avatarVersion = readAvatarVersion(version8);
|
|
170239
|
+
const entries = pendingAvatars.get(uid) || [];
|
|
170240
|
+
if (entries.length) {
|
|
170241
|
+
await Promise.allSettled(entries.map((entry) => entry.promise));
|
|
170242
|
+
const pending = entries.find((entry) => entry.version === avatarVersion);
|
|
170243
|
+
if (pending) {
|
|
170244
|
+
const active = pendingAvatars.get(uid) || [];
|
|
170245
|
+
const remaining = active.filter((entry) => entry !== pending);
|
|
170246
|
+
if (remaining.length) {
|
|
170247
|
+
pendingAvatars.set(uid, remaining);
|
|
170248
|
+
} else {
|
|
170249
|
+
pendingAvatars.delete(uid);
|
|
170250
|
+
}
|
|
170251
|
+
return new Uint8Array(pending.bytes);
|
|
170252
|
+
}
|
|
170253
|
+
}
|
|
170254
|
+
return readStorageFile(avatarPath(uid, avatarVersion));
|
|
169789
170255
|
}
|
|
169790
170256
|
async function peerAvatarUrl(uid, { version: version8 = null } = {}) {
|
|
169791
170257
|
const targetStorage = requireStorage2();
|
|
169792
|
-
|
|
169793
|
-
return avatarUrlWithVersion(url, version8);
|
|
170258
|
+
return getDownloadURL(ref(targetStorage, avatarPath(uid, version8)));
|
|
169794
170259
|
}
|
|
169795
170260
|
function profileQueryField(field2, { network } = {}) {
|
|
169796
170261
|
if (field2 === "walletPK") {
|
|
@@ -169841,20 +170306,12 @@ function createFirebaseCloud({ db, auth: auth2, getAuth: getAuth2, functions: fu
|
|
|
169841
170306
|
const snapshot = await getDocs(roleQuery);
|
|
169842
170307
|
return peerRecordsFromSnapshot(snapshot);
|
|
169843
170308
|
}
|
|
169844
|
-
async function
|
|
170309
|
+
async function uploadMedia(upload) {
|
|
169845
170310
|
const path = upload?.path;
|
|
169846
170311
|
if (!path)
|
|
169847
170312
|
throw new Error("media path required");
|
|
169848
|
-
|
|
169849
|
-
await
|
|
169850
|
-
return true;
|
|
169851
|
-
}
|
|
169852
|
-
async function uploadSharedMedia(upload) {
|
|
169853
|
-
const path = upload?.path;
|
|
169854
|
-
if (!path)
|
|
169855
|
-
throw new Error("shared media path required");
|
|
169856
|
-
const signed = await callFunction("reserveSharedMediaUpload", {
|
|
169857
|
-
sharedId: upload?.sharedId,
|
|
170313
|
+
getMediaFileRef(path);
|
|
170314
|
+
const signed = await callFunction("reserveMediaUpload", {
|
|
169858
170315
|
path,
|
|
169859
170316
|
size: uploadByteSize(upload?.body),
|
|
169860
170317
|
contentType: upload?.metadata?.contentType || "application/octet-stream"
|
|
@@ -169862,6 +170319,14 @@ function createFirebaseCloud({ db, auth: auth2, getAuth: getAuth2, functions: fu
|
|
|
169862
170319
|
await uploadSignedStorageFile(upload, signed?.upload);
|
|
169863
170320
|
return true;
|
|
169864
170321
|
}
|
|
170322
|
+
async function uploadChatMedia(upload) {
|
|
170323
|
+
getChatMediaFileRef(upload?.path);
|
|
170324
|
+
return uploadMedia(upload);
|
|
170325
|
+
}
|
|
170326
|
+
async function uploadSharedMedia(upload) {
|
|
170327
|
+
getSharedMediaFileRef(upload?.path);
|
|
170328
|
+
return uploadMedia(upload);
|
|
170329
|
+
}
|
|
169865
170330
|
async function readChatMedia(path) {
|
|
169866
170331
|
if (!path)
|
|
169867
170332
|
throw new Error("media path required");
|
|
@@ -170249,12 +170714,13 @@ function createFirebaseCloud({ db, auth: auth2, getAuth: getAuth2, functions: fu
|
|
|
170249
170714
|
}
|
|
170250
170715
|
};
|
|
170251
170716
|
}
|
|
170252
|
-
async function pushInbox(recipientUid, ping) {
|
|
170717
|
+
async function pushInbox(recipientUid, ping, options2 = {}) {
|
|
170253
170718
|
requireUid(recipientUid);
|
|
170254
170719
|
if (!ping)
|
|
170255
170720
|
throw new Error("inbox ping required");
|
|
170256
170721
|
await callFunction("push", {
|
|
170257
170722
|
recipientUid,
|
|
170723
|
+
notify: options2?.notify !== false,
|
|
170258
170724
|
ping: {
|
|
170259
170725
|
v: ping.v,
|
|
170260
170726
|
epk: ping.epk,
|
|
@@ -170293,7 +170759,9 @@ function createFirebaseCloud({ db, auth: auth2, getAuth: getAuth2, functions: fu
|
|
|
170293
170759
|
payload.onCommitted?.({ chatId, messageId });
|
|
170294
170760
|
let delivered = true;
|
|
170295
170761
|
if (payload.inbox?.recipientUid && payload.inbox?.ping) {
|
|
170296
|
-
delivered = await pushInbox(payload.inbox.recipientUid, payload.inbox.ping
|
|
170762
|
+
delivered = await pushInbox(payload.inbox.recipientUid, payload.inbox.ping, {
|
|
170763
|
+
notify: payload.inbox.notify !== false
|
|
170764
|
+
}).then(() => true, () => false);
|
|
170297
170765
|
}
|
|
170298
170766
|
return { chatId, messageId, delivered };
|
|
170299
170767
|
}
|
|
@@ -170546,18 +171014,19 @@ function createFirebaseCloud({ db, auth: auth2, getAuth: getAuth2, functions: fu
|
|
|
170546
171014
|
}
|
|
170547
171015
|
async function banAdminUser(uid, feature = "chat") {
|
|
170548
171016
|
requireUid(uid);
|
|
170549
|
-
await setDoc(doc(db, "moderation", uid), { banned: { [feature]: { until: null } } }, { merge: true });
|
|
170550
171017
|
if (feature === "avatar") {
|
|
170551
|
-
await
|
|
170552
|
-
|
|
170553
|
-
throw error;
|
|
170554
|
-
}
|
|
170555
|
-
});
|
|
171018
|
+
await callFunction("setAvatarModeration", { uid, banned: true });
|
|
171019
|
+
return true;
|
|
170556
171020
|
}
|
|
171021
|
+
await setDoc(doc(db, "moderation", uid), { banned: { [feature]: { until: null } } }, { merge: true });
|
|
170557
171022
|
return true;
|
|
170558
171023
|
}
|
|
170559
171024
|
async function unbanAdminUser(uid, feature = "chat") {
|
|
170560
171025
|
requireUid(uid);
|
|
171026
|
+
if (feature === "avatar") {
|
|
171027
|
+
await callFunction("setAvatarModeration", { uid, banned: false });
|
|
171028
|
+
return true;
|
|
171029
|
+
}
|
|
170561
171030
|
await setDoc(doc(db, "moderation", uid), { banned: { [feature]: deleteField() } }, { merge: true });
|
|
170562
171031
|
return true;
|
|
170563
171032
|
}
|
|
@@ -170595,9 +171064,7 @@ function createFirebaseCloud({ db, auth: auth2, getAuth: getAuth2, functions: fu
|
|
|
170595
171064
|
write: writeProfileIdentity
|
|
170596
171065
|
},
|
|
170597
171066
|
avatar: {
|
|
170598
|
-
|
|
170599
|
-
upload: uploadProfileAvatar,
|
|
170600
|
-
delete: deleteProfileAvatar
|
|
171067
|
+
set: setProfileAvatar
|
|
170601
171068
|
}
|
|
170602
171069
|
},
|
|
170603
171070
|
private: {
|
|
@@ -173187,13 +173654,6 @@ function cleanMessage(value, limit2, label = "message") {
|
|
|
173187
173654
|
throw new Error(`${label} must be ${limit2} characters or fewer`);
|
|
173188
173655
|
return message;
|
|
173189
173656
|
}
|
|
173190
|
-
function readAvatarGeneration(value) {
|
|
173191
|
-
const version8 = Number(value);
|
|
173192
|
-
if (!Number.isSafeInteger(version8) || version8 <= 0) {
|
|
173193
|
-
throw new Error("avatar upload did not return a valid generation");
|
|
173194
|
-
}
|
|
173195
|
-
return version8;
|
|
173196
|
-
}
|
|
173197
173657
|
function passkeyRows(linksList, passkeys, currentPasskeyId) {
|
|
173198
173658
|
return [...linksList, ...passkeys].sort((left, right) => (right.createdAt || 0) - (left.createdAt || 0)).map((row) => ({
|
|
173199
173659
|
...row,
|
|
@@ -173281,23 +173741,17 @@ function createRuntimeProductActions({
|
|
|
173281
173741
|
const user = await getUser();
|
|
173282
173742
|
if (!data)
|
|
173283
173743
|
throw new Error("avatar data required");
|
|
173284
|
-
|
|
173285
|
-
|
|
173286
|
-
}
|
|
173287
|
-
const
|
|
173288
|
-
await
|
|
173289
|
-
|
|
173290
|
-
return { avatar:
|
|
173744
|
+
if (options2.contentType && options2.contentType !== "image/webp") {
|
|
173745
|
+
throw new Error("avatar content type must be image/webp");
|
|
173746
|
+
}
|
|
173747
|
+
const result = await cloud.user.profile.avatar.set(user.uid, data);
|
|
173748
|
+
await user.refetchAvatar?.({ version: result.version });
|
|
173749
|
+
const updated = await getUser();
|
|
173750
|
+
return { avatar: updated.avatar || null, avatarVersion: result.version };
|
|
173291
173751
|
},
|
|
173292
173752
|
async deleteAvatar() {
|
|
173293
173753
|
const user = await getUser();
|
|
173294
|
-
|
|
173295
|
-
await cloud.user.profile.avatar.delete(user.uid);
|
|
173296
|
-
} catch (error) {
|
|
173297
|
-
if (error?.code !== "storage/object-not-found")
|
|
173298
|
-
throw error;
|
|
173299
|
-
}
|
|
173300
|
-
await cloud.user.profile.avatar.write(user.uid, null);
|
|
173754
|
+
await cloud.user.profile.avatar.set(user.uid, null);
|
|
173301
173755
|
user.clearAvatar?.();
|
|
173302
173756
|
return { deleted: true };
|
|
173303
173757
|
}
|
|
@@ -174473,6 +174927,34 @@ class ProfileStore {
|
|
|
174473
174927
|
var FILE_MODE2 = 384, DIR_MODE2 = 448;
|
|
174474
174928
|
var init_storage = () => {};
|
|
174475
174929
|
|
|
174930
|
+
// ../../shared/actioncopy.js
|
|
174931
|
+
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.";
|
|
174932
|
+
var init_actioncopy = __esm(() => {
|
|
174933
|
+
ACCOUNT_DELETE_COPY = Object.freeze({
|
|
174934
|
+
prepare: ACCOUNT_DELETE_PREPARE,
|
|
174935
|
+
condition: ACCOUNT_DELETE_CONDITION,
|
|
174936
|
+
consequence: ACCOUNT_DELETE_CONSEQUENCE,
|
|
174937
|
+
body: `${ACCOUNT_DELETE_PREPARE} ${ACCOUNT_DELETE_CONDITION} ${ACCOUNT_DELETE_CONSEQUENCE}`
|
|
174938
|
+
});
|
|
174939
|
+
PASSKEY_DELETE_COPY = Object.freeze({
|
|
174940
|
+
pendingBody: PASSKEY_DELETE_PENDING,
|
|
174941
|
+
body: PASSKEY_DELETE_VERIFIED,
|
|
174942
|
+
description: `${PASSKEY_DELETE_PENDING} ${PASSKEY_DELETE_VERIFIED}`,
|
|
174943
|
+
infoBody: `${PASSKEY_DELETE_PENDING} ${PASSKEY_DELETE_LIMITS} ${PASSKEY_DELETE_VERIFIED}`
|
|
174944
|
+
});
|
|
174945
|
+
WALLET_EXPORT_COPY = Object.freeze({
|
|
174946
|
+
networkLead: "this is not a bitcoin wallet.",
|
|
174947
|
+
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.",
|
|
174948
|
+
withdrawBody: "if you do not want to use this account anymore, withdraw your funds back to a bitcoin wallet instead.",
|
|
174949
|
+
secretBody: "the mnemonic gives full control of this Spark wallet. reveal it only somewhere private."
|
|
174950
|
+
});
|
|
174951
|
+
WITHDRAWAL_COPY = Object.freeze({
|
|
174952
|
+
feeBody: "you can withdraw your funds back to any bitcoin address. bitcoin transactions are not free. validators need to get paid.",
|
|
174953
|
+
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.",
|
|
174954
|
+
irreversibleBody: "once confirmed, bitcoin withdrawals are irreversible."
|
|
174955
|
+
});
|
|
174956
|
+
});
|
|
174957
|
+
|
|
174476
174958
|
// src/commands.js
|
|
174477
174959
|
import { Buffer as Buffer4 } from "node:buffer";
|
|
174478
174960
|
import { chmod as chmod3, readFile as readFile3, writeFile as writeFile3 } from "node:fs/promises";
|
|
@@ -174640,6 +175122,7 @@ function cliHelpLines() {
|
|
|
174640
175122
|
}
|
|
174641
175123
|
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;
|
|
174642
175124
|
var init_commands = __esm(() => {
|
|
175125
|
+
init_actioncopy();
|
|
174643
175126
|
stringProp = Object.freeze({ type: "string" });
|
|
174644
175127
|
numberProp = Object.freeze({ type: "number" });
|
|
174645
175128
|
booleanProp = Object.freeze({ type: "boolean" });
|
|
@@ -174716,12 +175199,12 @@ var init_commands = __esm(() => {
|
|
|
174716
175199
|
invokeCli: async (client2, input, context) => client2.account.acceptTerms({ ...input, termsVersion: await context.acceptTerms(input.termsVersion) })
|
|
174717
175200
|
}),
|
|
174718
175201
|
command({ name: "account_logout", group: "account", apiName: "logout", description: "Lock and sign out this runtime.", usage: "account logout", cliInput: optionsOnly, access: "write", invoke: (client2) => client2.account.logout() }),
|
|
174719
|
-
command({ name: "account_logout_all", group: "account", apiName: "logoutAll", description:
|
|
174720
|
-
command({ name: "account_delete", group: "account", apiName: "delete", description:
|
|
175202
|
+
command({ name: "account_logout_all", group: "account", apiName: "logoutAll", description: LOGOUT_ALL_DEVICES_BODY, usage: "account logout-all", cliInput: optionsOnly, access: "destructive", invoke: (client2) => client2.account.logoutAll() }),
|
|
175203
|
+
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: (client2, input) => client2.account.delete(input) }),
|
|
174721
175204
|
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: (client2, input) => client2.vault.create(input) }),
|
|
174722
175205
|
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: (client2, input) => client2.vault.unlock(input) }),
|
|
174723
175206
|
command({ name: "vault_lock", group: "vault", apiName: "lock", description: "Lock wallet and chat state.", usage: "vault lock", cliInput: optionsOnly, access: "write", invoke: (client2) => client2.vault.lock() }),
|
|
174724
|
-
command({ name: "vault_export", group: "vault", apiName: "export", description:
|
|
175207
|
+
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: (client2, input) => client2.vault.export(input) }),
|
|
174725
175208
|
command({ name: "profile_show", group: "profile", apiName: "show", description: "Show the public account profile.", usage: "profile show", cliInput: optionsOnly, invoke: (client2) => client2.profile.show() }),
|
|
174726
175209
|
command({
|
|
174727
175210
|
name: "profile_avatar_set",
|
|
@@ -174747,8 +175230,8 @@ var init_commands = __esm(() => {
|
|
|
174747
175230
|
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: (client2, input) => client2.peers.search(input.query, input) }),
|
|
174748
175231
|
command({ name: "peers_list", group: "peers", apiName: "list", description: "List recent peers.", properties: { count: numberProp, recent: booleanProp }, usage: "peers list", cliInput: optionsOnly, invoke: (client2, input) => client2.peers.list(input) }),
|
|
174749
175232
|
command({ name: "peers_blocked", group: "peers", apiName: "blocked", description: "List blocked peers.", usage: "peers blocked", cliInput: optionsOnly, invoke: (client2) => client2.peers.blocked() }),
|
|
174750
|
-
command({ name: "peers_block", group: "peers", apiName: "block", description:
|
|
174751
|
-
command({ name: "peers_unblock", group: "peers", apiName: "unblock", description:
|
|
175233
|
+
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: (client2, input) => client2.peers.block(input.peer) }),
|
|
175234
|
+
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: (client2, input) => client2.peers.unblock(input.peer) }),
|
|
174752
175235
|
command({ name: "chat_list", group: "chat", apiName: "list", description: "List chats.", properties: { count: numberProp }, usage: "chat list", cliInput: optionsOnly, invoke: (client2, input) => client2.chat.list(input) }),
|
|
174753
175236
|
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: (client2, input) => client2.chat.read(input.peer, input) }),
|
|
174754
175237
|
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: (client2, input) => client2.chat.markRead(input.peer, input) }),
|
|
@@ -174761,7 +175244,7 @@ var init_commands = __esm(() => {
|
|
|
174761
175244
|
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: (client2, { peer, messageId, ...options2 }) => client2.chat.unsave(peer, messageId, options2) }),
|
|
174762
175245
|
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: (client2, { peer, messageId, message, ...options2 }) => client2.chat.update(peer, messageId, message, options2) }),
|
|
174763
175246
|
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: (client2, { peer, messageId, ...options2 }) => client2.chat.delete(peer, messageId, options2) }),
|
|
174764
|
-
command({ name: "chat_delete", group: "chat", apiName: "deleteChat", description:
|
|
175247
|
+
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: (client2, input) => client2.chat.deleteChat(input.peer, input) }),
|
|
174765
175248
|
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: (client2, input) => client2.chat.retention(input.peer, input.retention, input) }),
|
|
174766
175249
|
command({
|
|
174767
175250
|
name: "chat_send_file",
|
|
@@ -174846,12 +175329,12 @@ var init_commands = __esm(() => {
|
|
|
174846
175329
|
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: (client2, input) => client2.lightning.send(input.id, input) }),
|
|
174847
175330
|
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: (client2, input) => client2.withdrawal.quote(input.address, input.sats, input) }),
|
|
174848
175331
|
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: (client2, input) => client2.withdrawal.prepare(input.address, input.sats, input) }),
|
|
174849
|
-
command({ name: "withdrawal_confirm", group: "withdrawal", apiName: "confirm", description:
|
|
175332
|
+
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: (client2, input) => client2.withdrawal.confirm(input.address, input.sats, input) }),
|
|
174850
175333
|
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: (client2, input) => client2.invite.link(input) }),
|
|
174851
175334
|
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: (client2, input) => client2.invite.read(input.value) }),
|
|
174852
175335
|
command({ name: "passkeys_list", group: "passkeys", apiName: "list", description: "List passkeys and pending links.", usage: "passkeys list", cliInput: optionsOnly, invoke: (client2, input) => client2.passkeys.list(input) }),
|
|
174853
175336
|
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: (client2, input) => client2.passkeys.createLink(input) }),
|
|
174854
|
-
command({ name: "passkeys_delete", group: "passkeys", apiName: "delete", description:
|
|
175337
|
+
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: (client2, input) => client2.passkeys.delete(input.id, input) }),
|
|
174855
175338
|
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: (client2, input) => client2.support.feedback(input.message, input) }),
|
|
174856
175339
|
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: (client2, input) => client2.support.bug(input.message, input) }),
|
|
174857
175340
|
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: (client2, input) => client2.support.report(input.peer, input) }),
|
|
@@ -174890,7 +175373,7 @@ var package_default;
|
|
|
174890
175373
|
var init_package = __esm(() => {
|
|
174891
175374
|
package_default = {
|
|
174892
175375
|
name: "veyl",
|
|
174893
|
-
version: "0.
|
|
175376
|
+
version: "1.0.0",
|
|
174894
175377
|
private: true,
|
|
174895
175378
|
license: "Apache-2.0",
|
|
174896
175379
|
workspaces: {
|
|
@@ -174906,16 +175389,16 @@ var init_package = __esm(() => {
|
|
|
174906
175389
|
"@noble/curves": "^2.2.0",
|
|
174907
175390
|
"@noble/hashes": "^2.2.0",
|
|
174908
175391
|
"@scure/bip39": "^2.2.0",
|
|
174909
|
-
"@tailwindcss/postcss": "^4.3.
|
|
175392
|
+
"@tailwindcss/postcss": "^4.3.3",
|
|
174910
175393
|
bech32: "^2.0.0",
|
|
174911
175394
|
firebase: "^12.16.0",
|
|
174912
175395
|
"lucide-react": "^1.24.0",
|
|
174913
175396
|
next: "16.3.0-preview.6",
|
|
174914
175397
|
"next-themes": "^0.4.6",
|
|
174915
|
-
postcss: "^8.5.
|
|
174916
|
-
react: "19.2.
|
|
174917
|
-
"react-dom": "19.2.
|
|
174918
|
-
tailwindcss: "^4.3.
|
|
175398
|
+
postcss: "^8.5.22",
|
|
175399
|
+
react: "19.2.8",
|
|
175400
|
+
"react-dom": "19.2.8",
|
|
175401
|
+
tailwindcss: "^4.3.3",
|
|
174919
175402
|
"tw-animate-css": "^1.4.0"
|
|
174920
175403
|
}
|
|
174921
175404
|
},
|
|
@@ -175687,6 +176170,7 @@ class VeylHeadlessClient {
|
|
|
175687
176170
|
this.userOwner.setNetwork(network);
|
|
175688
176171
|
}
|
|
175689
176172
|
});
|
|
176173
|
+
await opened.walletReady;
|
|
175690
176174
|
this.userSnapshot = this.userOwner.getSnapshot();
|
|
175691
176175
|
} catch (error) {
|
|
175692
176176
|
if (opened)
|