@glyphteck/veyl 0.70.0 → 0.71.1
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/account.js +642 -189
- package/dist/accountprofiles.js +1 -0
- package/dist/cli.js +707 -273
- package/dist/index.js +707 -273
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1008,6 +1008,16 @@ function numberToBytesBE(n, len) {
|
|
|
1008
1008
|
function numberToBytesLE(n, len) {
|
|
1009
1009
|
return numberToBytesBE(n, len).reverse();
|
|
1010
1010
|
}
|
|
1011
|
+
function equalBytes(a, b) {
|
|
1012
|
+
a = abytes2(a);
|
|
1013
|
+
b = abytes2(b);
|
|
1014
|
+
if (a.length !== b.length)
|
|
1015
|
+
return false;
|
|
1016
|
+
let diff = 0;
|
|
1017
|
+
for (let i = 0;i < a.length; i++)
|
|
1018
|
+
diff |= a[i] ^ b[i];
|
|
1019
|
+
return diff === 0;
|
|
1020
|
+
}
|
|
1011
1021
|
function copyBytes2(bytes) {
|
|
1012
1022
|
return Uint8Array.from(abytes2(bytes));
|
|
1013
1023
|
}
|
|
@@ -4725,7 +4735,7 @@ function checkOpts2(defaults, opts) {
|
|
|
4725
4735
|
const merged = Object.assign(defaults, opts);
|
|
4726
4736
|
return merged;
|
|
4727
4737
|
}
|
|
4728
|
-
function
|
|
4738
|
+
function equalBytes2(a, b) {
|
|
4729
4739
|
a = abytes3(a);
|
|
4730
4740
|
b = abytes3(b);
|
|
4731
4741
|
if (a.length !== b.length)
|
|
@@ -5169,7 +5179,7 @@ var init_aes = __esm(() => {
|
|
|
5169
5179
|
const passedTag = ciphertext.subarray(-tagLength);
|
|
5170
5180
|
const tag = _computeTag(authKey, tagMask, data);
|
|
5171
5181
|
toClean.push(tag);
|
|
5172
|
-
if (!
|
|
5182
|
+
if (!equalBytes2(tag, passedTag)) {
|
|
5173
5183
|
clean2(...toClean);
|
|
5174
5184
|
throw new Error("aes-gcm: invalid tag");
|
|
5175
5185
|
}
|
|
@@ -5856,7 +5866,7 @@ function sameText(left, right) {
|
|
|
5856
5866
|
}
|
|
5857
5867
|
|
|
5858
5868
|
// ../../core/config.js
|
|
5859
|
-
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 = 15, PASSWORD_MAX_CHARS = 64, PASSWORD_MAX_BYTES, ACCOUNT_CONNECTION_SLOW_MS, ACCOUNT_CONNECTION_UNAVAILABLE_MS, ACCOUNT_CONNECTION_RETRY_MIN_MS, ACCOUNT_CONNECTION_RETRY_MAX_MS, AUTOLOCK_MIN_MINUTES = 1, AUTOLOCK_MAX_MINUTES = 60, BTC_PRICE_FALLBACK = 80000, CHAT_MESSAGE_EDIT_WINDOW_MS, CHAT_SEND_CONNECTION_WAIT_MS, 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_CHAT_MESSAGE_CACHE_WRITE_DELAY_MS = 2500, LOCAL_AVATAR_CACHE_MAX_BYTES, LOCAL_AVATAR_CACHE_MAX_AGE_MS, AVATAR_IMAGE_MAX_BYTES, AVATAR_IMAGE_QUALITY_ATTEMPTS, CHAT_AVATAR_IMAGE_MAX_BYTES, CHAT_AVATAR_REF_MAX_CHARS = 256, 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_MESSAGE_MUTATION_MAX_ITEMS = 256, CHAT_TTL_CLIENT_DELETE_GRACE_MS, 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_INBOX_DISCOVERY_PARALLEL_CHATS, CHAT_INBOX_SETTLEMENT_PARALLEL_CHATS = 4, CHAT_INBOX_CURSOR_OVERLAP_MS, CHAT_LIST_CACHE_WRITE_DELAY_MS = 1500, CHAT_LIST_SNAPSHOT_COALESCE_MS = 80, CHAT_LIST_COMPLETE_SYNC_DELAY_MS = 250, 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_READ_WRITE_MAX_WAIT_MS, CHAT_LIVE_PING_INTERVAL_MS, CHAT_LIVE_SWEEP_INTERVAL_MS, CHAT_LIVE_STALE_AFTER_MS, CHAT_LIVE_RECONNECT_MIN_MS = 250, CHAT_LIVE_RECONNECT_MAX_MS, CHAT_LIVE_TYPING_IDLE_MS, CHAT_LIVE_TYPING_RENEW_MS, CHAT_LIVE_COMPOSITION_HANDOFF_MS, CHAT_LIVE_READ_SEND_INTERVAL_MS = 120, CHAT_LIVE_READ_SEND_MAX_WAIT_MS = 500, CHAT_LIVE_READ_WRITE_INTERVAL_MS, CHAT_LIVE_READ_WRITE_MAX_WAIT_MS, CHAT_SEND_QUEUE_RATE_LIMIT_COUNT = 12, CHAT_SEND_QUEUE_RATE_LIMIT_WINDOW_MS, CHAT_SETTINGS_BODY_MAX_BYTES, CHAT_TITLE_STATE_MAX_CHARS = 128, CHAT_MANIFEST_MAX_BYTES, CHAT_RECEIPT_MAX_MEMBERS = 32, CHAT_ORDINARY_DELIVERY_MAX_MEMBERS = 128, CHAT_MAX_MEMBERS = 256, CHAT_LARGE_GROUP_MENTION_MAX_TARGETS = 16, CHAT_MAX_TEXT_CHARS = 2048, CHAT_TITLE_INPUT_MAX_CHARS = 16, CHAT_MAX_REACTIONS, 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_THROTTLE_MS = 120, BAN_REFRESH_GRACE_MS = 50, REQUEST_MONEY_MAX_SATS, WALLET_TRANSFER_POLL_MS, WALLET_ACTIVE_TRANSFER_REFRESH_MS, 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_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;
|
|
5869
|
+
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 = 15, PASSWORD_MAX_CHARS = 64, PASSWORD_MAX_BYTES, ACCOUNT_CONNECTION_SLOW_MS, ACCOUNT_CONNECTION_UNAVAILABLE_MS, ACCOUNT_CONNECTION_RETRY_MIN_MS, ACCOUNT_CONNECTION_RETRY_MAX_MS, AUTOLOCK_MIN_MINUTES = 1, AUTOLOCK_MAX_MINUTES = 60, BTC_PRICE_FALLBACK = 80000, CHAT_MESSAGE_EDIT_WINDOW_MS, CHAT_SEND_CONNECTION_WAIT_MS, 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_CHAT_MESSAGE_CACHE_WRITE_DELAY_MS = 2500, LOCAL_AVATAR_CACHE_MAX_BYTES, LOCAL_AVATAR_CACHE_MAX_AGE_MS, AVATAR_IMAGE_MAX_BYTES, AVATAR_IMAGE_QUALITY_ATTEMPTS, CHAT_AVATAR_IMAGE_MAX_BYTES, CHAT_AVATAR_REF_MAX_CHARS = 256, 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_MESSAGE_MUTATION_MAX_ITEMS = 256, CHAT_TTL_CLIENT_DELETE_GRACE_MS, CHAT_BATCH_CLEANUP_IDLE_TIMEOUT_MS = 1500, CHAT_BATCH_CLEANUP_IDLE_DELAY_MS = 250, CHAT_LIST_PAGE_SIZE = 20, CHAT_ADMISSION_CACHE_PEERS = 1024, CHAT_LIST_LIVE_COUNT, CHAT_INBOX_PING_PAGE_SIZE = 25, CHAT_INBOX_DISCOVERY_PARALLEL_CHATS, CHAT_INBOX_SETTLEMENT_PARALLEL_CHATS = 4, CHAT_INBOX_CURSOR_OVERLAP_MS, CHAT_LIST_CACHE_WRITE_DELAY_MS = 1500, CHAT_LIST_SNAPSHOT_COALESCE_MS = 80, CHAT_LIST_COMPLETE_SYNC_DELAY_MS = 250, 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_READ_WRITE_MAX_WAIT_MS, CHAT_LIVE_PING_INTERVAL_MS, CHAT_LIVE_SWEEP_INTERVAL_MS, CHAT_LIVE_STALE_AFTER_MS, CHAT_LIVE_RECONNECT_MIN_MS = 250, CHAT_LIVE_RECONNECT_MAX_MS, CHAT_LIVE_TYPING_IDLE_MS, CHAT_LIVE_TYPING_RENEW_MS, CHAT_LIVE_COMPOSITION_HANDOFF_MS, CHAT_LIVE_READ_SEND_INTERVAL_MS = 120, CHAT_LIVE_READ_SEND_MAX_WAIT_MS = 500, CHAT_LIVE_READ_WRITE_INTERVAL_MS, CHAT_LIVE_READ_WRITE_MAX_WAIT_MS, CHAT_SEND_QUEUE_RATE_LIMIT_COUNT = 12, CHAT_SEND_QUEUE_RATE_LIMIT_WINDOW_MS, CHAT_SETTINGS_BODY_MAX_BYTES, CHAT_TITLE_STATE_MAX_CHARS = 128, CHAT_MANIFEST_MAX_BYTES, CHAT_RECEIPT_MAX_MEMBERS = 32, CHAT_ORDINARY_DELIVERY_MAX_MEMBERS = 128, CHAT_MAX_MEMBERS = 256, CHAT_LARGE_GROUP_MENTION_MAX_TARGETS = 16, CHAT_MAX_TEXT_CHARS = 2048, CHAT_TITLE_INPUT_MAX_CHARS = 16, CHAT_MAX_REACTIONS, 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_THROTTLE_MS = 120, BAN_REFRESH_GRACE_MS = 50, REQUEST_MONEY_MAX_SATS, WALLET_TRANSFER_POLL_MS, WALLET_ACTIVE_TRANSFER_REFRESH_MS, 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_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;
|
|
5860
5870
|
var init_config = __esm(() => {
|
|
5861
5871
|
MINUTE_MS = 60 * MS_PER_SECOND;
|
|
5862
5872
|
HOUR_MS = 60 * MINUTE_MS;
|
|
@@ -5997,9 +6007,12 @@ function normalizeChatNotificationMode(value, manifest) {
|
|
|
5997
6007
|
const mode = cleanText(value);
|
|
5998
6008
|
if (!NOTIFICATION_MODES.has(mode))
|
|
5999
6009
|
throw new Error("chat notification mode required");
|
|
6000
|
-
if (manifest?.lineage
|
|
6010
|
+
if (manifest?.lineage === "self")
|
|
6001
6011
|
return CHAT_NOTIFICATION_MODES.ALL;
|
|
6002
|
-
if (
|
|
6012
|
+
if (manifest?.lineage === "direct" && mode === CHAT_NOTIFICATION_MODES.MENTIONS) {
|
|
6013
|
+
throw new Error("mentions notifications require a group chat");
|
|
6014
|
+
}
|
|
6015
|
+
if (mode === CHAT_NOTIFICATION_MODES.ALL && manifest?.lineage === "group" && manifest.members?.length > CHAT_ORDINARY_DELIVERY_MAX_MEMBERS) {
|
|
6003
6016
|
return CHAT_NOTIFICATION_MODES.MENTIONS;
|
|
6004
6017
|
}
|
|
6005
6018
|
return mode;
|
|
@@ -7109,7 +7122,7 @@ var xchacha20, ZEROS162, updatePadded = (h, msg) => {
|
|
|
7109
7122
|
const data = ciphertext.subarray(0, -tagLength);
|
|
7110
7123
|
const passedTag = ciphertext.subarray(-tagLength);
|
|
7111
7124
|
const tag = computeTag2(xorStream, key, nonce, data, AAD);
|
|
7112
|
-
if (!
|
|
7125
|
+
if (!equalBytes2(passedTag, tag)) {
|
|
7113
7126
|
clean2(tag);
|
|
7114
7127
|
throw new Error("invalid tag");
|
|
7115
7128
|
}
|
|
@@ -8849,35 +8862,68 @@ function chatAdmissionCapabilityCommitment(value) {
|
|
|
8849
8862
|
cleanBytes(capability);
|
|
8850
8863
|
}
|
|
8851
8864
|
}
|
|
8852
|
-
function
|
|
8853
|
-
return deriveDirectAdmissionCapability(chatPrivateKey, chatPK,
|
|
8854
|
-
}
|
|
8855
|
-
function hasDirectAdmissionGrant(chatPrivateKey, chatPK, profile) {
|
|
8856
|
-
const policy = normalizeChatAdmission(profile?.chatAdmission);
|
|
8857
|
-
if (!policy.directGrants.length)
|
|
8858
|
-
return false;
|
|
8859
|
-
const capability = directAdmissionCapabilityForPeer(chatPrivateKey, chatPK, profile);
|
|
8860
|
-
try {
|
|
8861
|
-
return policy.directGrants.includes(chatAdmissionCapabilityCommitment(capability));
|
|
8862
|
-
} finally {
|
|
8863
|
-
cleanBytes(capability);
|
|
8864
|
-
}
|
|
8865
|
+
function deriveDirectAdmissionCommitment(chatPrivateKey, chatPK, peerChatPK, recipientChatPK) {
|
|
8866
|
+
return chatAdmissionCapabilityCommitment(deriveDirectAdmissionCapability(chatPrivateKey, chatPK, peerChatPK, recipientChatPK));
|
|
8865
8867
|
}
|
|
8866
|
-
function
|
|
8867
|
-
|
|
8868
|
+
function directAdmissionDecision(chatPK, profile, ownAdmission, commitmentFor) {
|
|
8869
|
+
const ownPolicy = normalizeChatAdmission(ownAdmission);
|
|
8870
|
+
if (ownAdmission != null && ownPolicy.direct === CHAT_DIRECT_ADMISSION_MODES.CLOSED && !ownPolicy.directGrants.includes(commitmentFor(profile?.chatPK, chatPK)))
|
|
8868
8871
|
return CHAT_ADMISSION_DECISIONS.REJECT;
|
|
8869
|
-
|
|
8872
|
+
const policy = normalizeChatAdmission(profile?.chatAdmission);
|
|
8873
|
+
if (policy.directGrants.length && policy.directGrants.includes(commitmentFor(profile?.chatPK, profile?.chatPK))) {
|
|
8870
8874
|
return CHAT_ADMISSION_DECISIONS.ACCEPT;
|
|
8871
8875
|
}
|
|
8872
|
-
const mode =
|
|
8876
|
+
const mode = policy.direct;
|
|
8873
8877
|
if (mode === CHAT_DIRECT_ADMISSION_MODES.OPEN)
|
|
8874
8878
|
return CHAT_ADMISSION_DECISIONS.ACCEPT;
|
|
8875
8879
|
if (mode === CHAT_DIRECT_ADMISSION_MODES.REQUESTS)
|
|
8876
8880
|
return CHAT_ADMISSION_DECISIONS.REQUEST;
|
|
8877
8881
|
return CHAT_ADMISSION_DECISIONS.REJECT;
|
|
8878
8882
|
}
|
|
8879
|
-
function
|
|
8880
|
-
return
|
|
8883
|
+
function directAdmissionForPeer(chatPrivateKey, chatPK, profile, ownAdmission = null) {
|
|
8884
|
+
return directAdmissionDecision(chatPK, profile, ownAdmission, (peerChatPK, recipientChatPK) => deriveDirectAdmissionCommitment(chatPrivateKey, chatPK, peerChatPK, recipientChatPK));
|
|
8885
|
+
}
|
|
8886
|
+
function createChatAdmission({ getIdentity, deriveCommitment = deriveDirectAdmissionCommitment }) {
|
|
8887
|
+
let chatPK = null;
|
|
8888
|
+
let privateKey = null;
|
|
8889
|
+
let privateKeyBytes = null;
|
|
8890
|
+
const peers = new Map;
|
|
8891
|
+
const reset = () => {
|
|
8892
|
+
peers.clear();
|
|
8893
|
+
cleanBytes(privateKeyBytes);
|
|
8894
|
+
chatPK = null;
|
|
8895
|
+
privateKey = null;
|
|
8896
|
+
privateKeyBytes = null;
|
|
8897
|
+
};
|
|
8898
|
+
const directAdmissionForPeer2 = (profile) => {
|
|
8899
|
+
const identity = getIdentity();
|
|
8900
|
+
if (chatPK !== identity.chatPK || privateKey !== identity.chatPrivateKey || privateKey instanceof Uint8Array && !equalBytes(privateKey, privateKeyBytes)) {
|
|
8901
|
+
reset();
|
|
8902
|
+
chatPK = identity.chatPK;
|
|
8903
|
+
privateKey = identity.chatPrivateKey;
|
|
8904
|
+
privateKeyBytes = privateKey instanceof Uint8Array ? new Uint8Array(privateKey) : null;
|
|
8905
|
+
}
|
|
8906
|
+
return directAdmissionDecision(chatPK, profile, identity.chatAdmission, (peerChatPK, recipientChatPK) => {
|
|
8907
|
+
let commitments = peers.get(peerChatPK);
|
|
8908
|
+
if (!commitments?.has(recipientChatPK)) {
|
|
8909
|
+
const commitment = deriveCommitment(privateKey, chatPK, peerChatPK, recipientChatPK);
|
|
8910
|
+
if (!commitments) {
|
|
8911
|
+
commitments = new Map;
|
|
8912
|
+
if (peers.size >= CHAT_ADMISSION_CACHE_PEERS)
|
|
8913
|
+
peers.delete(peers.keys().next().value);
|
|
8914
|
+
}
|
|
8915
|
+
commitments.set(recipientChatPK, commitment);
|
|
8916
|
+
}
|
|
8917
|
+
peers.delete(peerChatPK);
|
|
8918
|
+
peers.set(peerChatPK, commitments);
|
|
8919
|
+
return commitments.get(recipientChatPK);
|
|
8920
|
+
});
|
|
8921
|
+
};
|
|
8922
|
+
return {
|
|
8923
|
+
directAdmissionForPeer: directAdmissionForPeer2,
|
|
8924
|
+
canStartDirectChat: (profile) => directAdmissionForPeer2(profile) !== CHAT_ADMISSION_DECISIONS.REJECT,
|
|
8925
|
+
reset
|
|
8926
|
+
};
|
|
8881
8927
|
}
|
|
8882
8928
|
function canInviteToGroup(profile, ownAdmission = null) {
|
|
8883
8929
|
return (ownAdmission == null || normalizeChatAdmission(ownAdmission).groups === CHAT_GROUP_ADMISSION_MODES.OPEN) && normalizeChatAdmission(profile?.chatAdmission).groups === CHAT_GROUP_ADMISSION_MODES.OPEN;
|
|
@@ -8938,6 +8984,8 @@ var CHAT_ADMISSION_VERSION = 1, CHAT_ADMISSION_GRANT_COUNT = 8, CHAT_ADMISSION_D
|
|
|
8938
8984
|
var init_admission = __esm(() => {
|
|
8939
8985
|
init_ed25519();
|
|
8940
8986
|
init_sha2();
|
|
8987
|
+
init_utils2();
|
|
8988
|
+
init_config();
|
|
8941
8989
|
init_core();
|
|
8942
8990
|
init_kdf();
|
|
8943
8991
|
init_manifest();
|
|
@@ -11142,6 +11190,29 @@ var init_transition = __esm(() => {
|
|
|
11142
11190
|
TRANSITION_MEMBER_SCOPE = encoder.encode("veyl-chat-transition-member-v3");
|
|
11143
11191
|
});
|
|
11144
11192
|
|
|
11193
|
+
// ../../core/chat/capabilities.js
|
|
11194
|
+
function memberCount(value) {
|
|
11195
|
+
const count = Number(value);
|
|
11196
|
+
if (!Number.isSafeInteger(count) || count < 1 || count > CHAT_MAX_MEMBERS) {
|
|
11197
|
+
throw new Error("invalid chat member count");
|
|
11198
|
+
}
|
|
11199
|
+
return count;
|
|
11200
|
+
}
|
|
11201
|
+
function chatCapabilities(value) {
|
|
11202
|
+
const members = memberCount(value);
|
|
11203
|
+
return Object.freeze({
|
|
11204
|
+
members,
|
|
11205
|
+
sharedReceipts: members <= CHAT_RECEIPT_MAX_MEMBERS,
|
|
11206
|
+
ordinaryDelivery: members <= CHAT_ORDINARY_DELIVERY_MAX_MEMBERS
|
|
11207
|
+
});
|
|
11208
|
+
}
|
|
11209
|
+
function chatEpochCapabilities(epochState) {
|
|
11210
|
+
return chatCapabilities(epochState?.manifest?.members?.length);
|
|
11211
|
+
}
|
|
11212
|
+
var init_capabilities = __esm(() => {
|
|
11213
|
+
init_config();
|
|
11214
|
+
});
|
|
11215
|
+
|
|
11145
11216
|
// ../../core/chat/ttl.js
|
|
11146
11217
|
function hasChatRetention(value) {
|
|
11147
11218
|
const retention = cleanText(value);
|
|
@@ -11190,7 +11261,7 @@ function messageExpiryMs(retention, seenAt) {
|
|
|
11190
11261
|
}
|
|
11191
11262
|
return cleanChatRetention(retention) === CHAT_RETENTION_24H ? seenAt + AFTER_SEEN_MS : seenAt;
|
|
11192
11263
|
}
|
|
11193
|
-
var CHAT_RETENTION_SEEN = "seen", CHAT_RETENTION_24H = "24h", CHAT_RETENTION_FOREVER = "forever", DEFAULT_CHAT_RETENTION, CHAT_RETENTION_VALUES, CHAT_PROTOCOL_RETENTION_VALUES, CHAT_RETENTION_LABELS, MESSAGE_STORAGE_TTL_MS, AFTER_SEEN_MS;
|
|
11264
|
+
var CHAT_RETENTION_SEEN = "seen", CHAT_RETENTION_24H = "24h", CHAT_RETENTION_FOREVER = "forever", DEFAULT_CHAT_RETENTION, CHAT_RETENTION_VALUES, CHAT_PROTOCOL_RETENTION_VALUES, CHAT_RETENTION_LABELS, CHAT_RETENTION_DESCRIPTIONS, MESSAGE_STORAGE_TTL_MS, AFTER_SEEN_MS;
|
|
11194
11265
|
var init_ttl = __esm(() => {
|
|
11195
11266
|
init_config();
|
|
11196
11267
|
init_time();
|
|
@@ -11202,6 +11273,10 @@ var init_ttl = __esm(() => {
|
|
|
11202
11273
|
[CHAT_RETENTION_SEEN]: "delete after seen",
|
|
11203
11274
|
[CHAT_RETENTION_24H]: "keep for 24h"
|
|
11204
11275
|
});
|
|
11276
|
+
CHAT_RETENTION_DESCRIPTIONS = Object.freeze({
|
|
11277
|
+
[CHAT_RETENTION_SEEN]: "messages now delete after being seen",
|
|
11278
|
+
[CHAT_RETENTION_24H]: "messages now delete 24h after being seen"
|
|
11279
|
+
});
|
|
11205
11280
|
MESSAGE_STORAGE_TTL_MS = CHAT_UNSAVED_TTL_MS;
|
|
11206
11281
|
AFTER_SEEN_MS = CHAT_AFTER_SEEN_MS;
|
|
11207
11282
|
});
|
|
@@ -11843,6 +11918,8 @@ async function prepareOwnChatMutation(identity, entryId, current, update) {
|
|
|
11843
11918
|
open: (record) => openOwnChatMutationEntry(identity, entryId, record),
|
|
11844
11919
|
prepare: async (record) => {
|
|
11845
11920
|
if (!record) {
|
|
11921
|
+
if (current != null)
|
|
11922
|
+
throw makeChatUnavailableError();
|
|
11846
11923
|
return prepareMutation(identity, entryId, null, update);
|
|
11847
11924
|
}
|
|
11848
11925
|
if (!record?.body || !Number.isSafeInteger(record.revision) || record.revision < 1) {
|
|
@@ -12680,29 +12757,6 @@ var init_chatstate = __esm(() => {
|
|
|
12680
12757
|
STATE_SIGN_SCOPE = encoder.encode("veyl-chat-member-state-v3-sign");
|
|
12681
12758
|
});
|
|
12682
12759
|
|
|
12683
|
-
// ../../core/chat/capabilities.js
|
|
12684
|
-
function memberCount(value) {
|
|
12685
|
-
const count = Number(value);
|
|
12686
|
-
if (!Number.isSafeInteger(count) || count < 1 || count > CHAT_MAX_MEMBERS) {
|
|
12687
|
-
throw new Error("invalid chat member count");
|
|
12688
|
-
}
|
|
12689
|
-
return count;
|
|
12690
|
-
}
|
|
12691
|
-
function chatCapabilities(value) {
|
|
12692
|
-
const members = memberCount(value);
|
|
12693
|
-
return Object.freeze({
|
|
12694
|
-
members,
|
|
12695
|
-
sharedReceipts: members <= CHAT_RECEIPT_MAX_MEMBERS,
|
|
12696
|
-
ordinaryDelivery: members <= CHAT_ORDINARY_DELIVERY_MAX_MEMBERS
|
|
12697
|
-
});
|
|
12698
|
-
}
|
|
12699
|
-
function chatEpochCapabilities(epochState) {
|
|
12700
|
-
return chatCapabilities(epochState?.manifest?.members?.length);
|
|
12701
|
-
}
|
|
12702
|
-
var init_capabilities = __esm(() => {
|
|
12703
|
-
init_config();
|
|
12704
|
-
});
|
|
12705
|
-
|
|
12706
12760
|
// ../../core/chat/memberstate.js
|
|
12707
12761
|
function openStateEpoch(epochState, actor = null) {
|
|
12708
12762
|
if (!epochState?.manifest || !epochState?.epochSecret)
|
|
@@ -13893,7 +13947,8 @@ function getMsgReactions(msg) {
|
|
|
13893
13947
|
continue;
|
|
13894
13948
|
}
|
|
13895
13949
|
seen.add(user);
|
|
13896
|
-
|
|
13950
|
+
const ts = timestampMs(item.ts, null);
|
|
13951
|
+
reactions.push({ emoji, user, ...ts == null ? {} : { ts } });
|
|
13897
13952
|
if (reactions.length >= MAX_REACTIONS) {
|
|
13898
13953
|
break;
|
|
13899
13954
|
}
|
|
@@ -13906,7 +13961,7 @@ function sameReactions(a, b) {
|
|
|
13906
13961
|
if (left.length !== right.length) {
|
|
13907
13962
|
return false;
|
|
13908
13963
|
}
|
|
13909
|
-
return left.every((reaction, index) => reaction.user === right[index]?.user && reaction.emoji === right[index]?.emoji);
|
|
13964
|
+
return left.every((reaction, index) => reaction.user === right[index]?.user && reaction.emoji === right[index]?.emoji && reaction.ts === right[index]?.ts);
|
|
13910
13965
|
}
|
|
13911
13966
|
function hasReactionControl(messages) {
|
|
13912
13967
|
for (const msg of messages || []) {
|
|
@@ -13946,7 +14001,8 @@ function deriveMessageReactions(messages, chatPK, peerChatPK, memberChatPKs = nu
|
|
|
13946
14001
|
byTarget.set(target, reactions);
|
|
13947
14002
|
}
|
|
13948
14003
|
if (hasText(msg.emoji)) {
|
|
13949
|
-
|
|
14004
|
+
const ts = timestampMs(getMessageOrderMs(msg), null);
|
|
14005
|
+
reactions.set(user, { emoji: cleanReactionEmoji(msg.emoji), user, ...ts == null ? {} : { ts } });
|
|
13950
14006
|
} else {
|
|
13951
14007
|
reactions.delete(user);
|
|
13952
14008
|
}
|
|
@@ -15075,7 +15131,7 @@ function senderIdentity(senderChatPK, senderPrivateKey, options) {
|
|
|
15075
15131
|
notificationPrivateKey: options.notificationPrivateKey
|
|
15076
15132
|
};
|
|
15077
15133
|
}
|
|
15078
|
-
function ownerPreview(senderChatPK, message, messageId, head, tsMs, ttlMs) {
|
|
15134
|
+
function ownerPreview(epoch, senderChatPK, message, messageId, head, tsMs, ttlMs) {
|
|
15079
15135
|
return {
|
|
15080
15136
|
...message || {},
|
|
15081
15137
|
s: senderChatPK,
|
|
@@ -15084,6 +15140,8 @@ function ownerPreview(senderChatPK, message, messageId, head, tsMs, ttlMs) {
|
|
|
15084
15140
|
id: messageId,
|
|
15085
15141
|
ts: tsMs,
|
|
15086
15142
|
ttl: Number.isFinite(ttlMs) ? ttlMs : null,
|
|
15143
|
+
epochId: epoch.epochId,
|
|
15144
|
+
epochMemberChatPKs: epoch.manifest.members.map((member) => member.chatPK),
|
|
15087
15145
|
pending: false,
|
|
15088
15146
|
failed: false
|
|
15089
15147
|
};
|
|
@@ -15300,7 +15358,7 @@ async function prepareMsgRecord(identity, epochState, message, options = {}) {
|
|
|
15300
15358
|
msgId: messageId,
|
|
15301
15359
|
cid: head.cid,
|
|
15302
15360
|
record: { lane: epoch.messageLane, head, body, ttlMs },
|
|
15303
|
-
message: ownerPreview(identity.chatPK, messagePayload, messageId, head, tsMs, ttlMs),
|
|
15361
|
+
message: ownerPreview(epoch, identity.chatPK, messagePayload, messageId, head, tsMs, ttlMs),
|
|
15304
15362
|
mentionRecipientChatPKs: mentionTargets.recipientChatPKs,
|
|
15305
15363
|
tsMs
|
|
15306
15364
|
};
|
|
@@ -20020,12 +20078,6 @@ function dropCachedChats(cache, chatIds, currentPayload = null) {
|
|
|
20020
20078
|
...ids.map((chatId) => dropCachedMessageState(cache, chatId))
|
|
20021
20079
|
]));
|
|
20022
20080
|
}
|
|
20023
|
-
function dropCachedChat(cache, chatId) {
|
|
20024
|
-
if (!chatId) {
|
|
20025
|
-
return;
|
|
20026
|
-
}
|
|
20027
|
-
dropCachedChats(cache, [chatId]);
|
|
20028
|
-
}
|
|
20029
20081
|
var init_chats2 = __esm(() => {
|
|
20030
20082
|
init_config();
|
|
20031
20083
|
init_time();
|
|
@@ -24926,6 +24978,17 @@ function createRouteMemory(limit = CHAT_MESSAGE_VIEW_CACHE_SIZE) {
|
|
|
24926
24978
|
}
|
|
24927
24979
|
return {
|
|
24928
24980
|
clear,
|
|
24981
|
+
dropChat(chatId) {
|
|
24982
|
+
const id = String(chatId || "").trim();
|
|
24983
|
+
if (!id)
|
|
24984
|
+
return;
|
|
24985
|
+
const keys = chatRouteMemoryKeys(id, [...states.keys(), ...retained.keys()]);
|
|
24986
|
+
for (const key of keys) {
|
|
24987
|
+
states.delete(key);
|
|
24988
|
+
retained.delete(key);
|
|
24989
|
+
}
|
|
24990
|
+
activeChats.delete(id);
|
|
24991
|
+
},
|
|
24929
24992
|
resetAccount(nextAccountKey) {
|
|
24930
24993
|
const next = nextAccountKey || "";
|
|
24931
24994
|
if (accountKey === next) {
|
|
@@ -26530,6 +26593,9 @@ async function verifyOpenedPingEpoch(context) {
|
|
|
26530
26593
|
const decision = await decideIncomingChat(context, epochState);
|
|
26531
26594
|
if (decision === CHAT_ADMISSION_DECISIONS.REJECT)
|
|
26532
26595
|
return "rejected";
|
|
26596
|
+
const unavailable = await checkOpenedWelcomeAvailability(context);
|
|
26597
|
+
if (unavailable)
|
|
26598
|
+
return unavailable;
|
|
26533
26599
|
if (decision === CHAT_ADMISSION_DECISIONS.REQUEST)
|
|
26534
26600
|
return "request";
|
|
26535
26601
|
} else if (context.entry && (epochState.manifest.lineage === "direct" || epochState.manifest.lineage === "group")) {
|
|
@@ -26539,6 +26605,27 @@ async function verifyOpenedPingEpoch(context) {
|
|
|
26539
26605
|
}
|
|
26540
26606
|
return null;
|
|
26541
26607
|
}
|
|
26608
|
+
async function checkOpenedWelcomeAvailability(context) {
|
|
26609
|
+
const { cloud, identity, options, uid, epochState } = context;
|
|
26610
|
+
assertInboxLease(options);
|
|
26611
|
+
try {
|
|
26612
|
+
await cloud.chat.state.transition(epochState.manifest.chatId, epochState.manifest.epochId, epochState.stateCapability);
|
|
26613
|
+
assertInboxLease(options);
|
|
26614
|
+
return null;
|
|
26615
|
+
} catch (error) {
|
|
26616
|
+
const code = cleanText(error?.code).toLowerCase();
|
|
26617
|
+
if (code !== "permission-denied" && !code.endsWith("/permission-denied"))
|
|
26618
|
+
throw error;
|
|
26619
|
+
try {
|
|
26620
|
+
await retireConfirmedDeletedChat(cloud, uid, identity, context.committedEntry || context.entry || makeOwnChatEntry(epochState), options);
|
|
26621
|
+
return "deleted";
|
|
26622
|
+
} catch (confirmationError) {
|
|
26623
|
+
if (isRetryableInboxError(confirmationError))
|
|
26624
|
+
throw confirmationError;
|
|
26625
|
+
throw error;
|
|
26626
|
+
}
|
|
26627
|
+
}
|
|
26628
|
+
}
|
|
26542
26629
|
function startOpenedWelcomeHydration(context) {
|
|
26543
26630
|
const membershipWelcome = (!context.entry || context.restoringMembership) && context.payload.kind === "welcome";
|
|
26544
26631
|
if (!membershipWelcome)
|
|
@@ -26775,17 +26862,30 @@ async function settleOpenedPing(prepared, onAuthoritative) {
|
|
|
26775
26862
|
const createsMembership = !context.entry && context.payload.kind === "welcome";
|
|
26776
26863
|
const ownerPersistence = createsMembership ? captureAsync(persistOpenedPingOwner(context)) : null;
|
|
26777
26864
|
const messageStartedAt = Date.now();
|
|
26778
|
-
const
|
|
26865
|
+
const messageOutcome = await captureAsync(applyOpenedPingMessage(context));
|
|
26779
26866
|
markDiag(context.options.diag, "chat.inbox.settle.message.done", {
|
|
26780
26867
|
elapsedMs: Date.now() - messageStartedAt
|
|
26781
26868
|
});
|
|
26782
|
-
if (result)
|
|
26783
|
-
return result;
|
|
26784
|
-
prepareOpenedPingActivity(context);
|
|
26785
26869
|
if (ownerPersistence)
|
|
26786
26870
|
await unwrapAsync(ownerPersistence);
|
|
26787
|
-
else
|
|
26788
|
-
|
|
26871
|
+
else if (messageOutcome.error)
|
|
26872
|
+
throw messageOutcome.error;
|
|
26873
|
+
if (messageOutcome.value)
|
|
26874
|
+
return messageOutcome.value;
|
|
26875
|
+
if (!messageOutcome.error) {
|
|
26876
|
+
prepareOpenedPingActivity(context);
|
|
26877
|
+
if (!ownerPersistence)
|
|
26878
|
+
await persistOpenedPingOwner(context);
|
|
26879
|
+
}
|
|
26880
|
+
if (context.membershipWelcome) {
|
|
26881
|
+
const unavailable = await checkOpenedWelcomeAvailability(context);
|
|
26882
|
+
if (unavailable) {
|
|
26883
|
+
await cleanupOpenedPing(context);
|
|
26884
|
+
return unavailable;
|
|
26885
|
+
}
|
|
26886
|
+
}
|
|
26887
|
+
if (messageOutcome.error)
|
|
26888
|
+
throw messageOutcome.error;
|
|
26789
26889
|
publishOpenedPing(context);
|
|
26790
26890
|
onAuthoritative?.();
|
|
26791
26891
|
const phaseStartedAt = Date.now();
|
|
@@ -26912,6 +27012,7 @@ async function preparePreparedPing(cloud, uid, identity, prepared, options) {
|
|
|
26912
27012
|
ping,
|
|
26913
27013
|
uid
|
|
26914
27014
|
});
|
|
27015
|
+
assertInboxLease(options);
|
|
26915
27016
|
return { opened, releaseMutation };
|
|
26916
27017
|
} catch (error) {
|
|
26917
27018
|
releaseMutation();
|
|
@@ -27366,10 +27467,11 @@ async function prepareInboxWork(context, prepared, processingOptions = {}) {
|
|
|
27366
27467
|
const { blockedUids, cloud, identity, options, state, uid } = context;
|
|
27367
27468
|
const { document: document2, opened } = prepared;
|
|
27368
27469
|
let announcement = null;
|
|
27470
|
+
let ping = null;
|
|
27369
27471
|
try {
|
|
27370
27472
|
const authenticated = await authenticateInboxPing(cloud, identity, document2, opened, state.currentChats, context.profileCache);
|
|
27371
27473
|
assertInboxLease(options);
|
|
27372
|
-
|
|
27474
|
+
ping = await preparePreparedPing(cloud, uid, identity, authenticated, {
|
|
27373
27475
|
...options,
|
|
27374
27476
|
blockedUids,
|
|
27375
27477
|
currentChats: state.currentChats,
|
|
@@ -27386,9 +27488,11 @@ async function prepareInboxWork(context, prepared, processingOptions = {}) {
|
|
|
27386
27488
|
if (ping.opened?.result === "request") {
|
|
27387
27489
|
await hydrateOpenedChatRequest(ping.opened.context);
|
|
27388
27490
|
}
|
|
27491
|
+
assertInboxLease(options);
|
|
27389
27492
|
announcement = announcePreparedWelcome(context, authenticated, ping, document2, prepared.startedAt);
|
|
27390
27493
|
return { announcement, document: document2, ping, prepared, processingOptions, status: null };
|
|
27391
27494
|
} catch (error) {
|
|
27495
|
+
ping?.releaseMutation();
|
|
27392
27496
|
state.revokeAnnouncement(announcement);
|
|
27393
27497
|
if (processingOptions.deferUnknownWelcome === true && error?.message === "chat mls welcome required") {
|
|
27394
27498
|
markDiag(options.diag, "chat.inbox.document.deferred", { reason: "welcome_required" });
|
|
@@ -27516,6 +27620,8 @@ function createInboxSettlementController(options = {}) {
|
|
|
27516
27620
|
for (const job of lane.jobs) {
|
|
27517
27621
|
if (job.settled)
|
|
27518
27622
|
continue;
|
|
27623
|
+
if (job.state === "ready")
|
|
27624
|
+
job.discard?.(job.prepared);
|
|
27519
27625
|
job.settled = true;
|
|
27520
27626
|
job.state = "settled";
|
|
27521
27627
|
job.deferred.reject(error);
|
|
@@ -27560,9 +27666,12 @@ function createInboxSettlementController(options = {}) {
|
|
|
27560
27666
|
}
|
|
27561
27667
|
job.state = "preparing";
|
|
27562
27668
|
Promise.resolve().then(job.prepare).then((prepared) => {
|
|
27563
|
-
if (job.settled)
|
|
27669
|
+
if (job.settled) {
|
|
27670
|
+
job.discard?.(prepared);
|
|
27564
27671
|
return;
|
|
27672
|
+
}
|
|
27565
27673
|
if (!hasLease()) {
|
|
27674
|
+
job.discard?.(prepared);
|
|
27566
27675
|
finishJob(job, inboxLeaseError());
|
|
27567
27676
|
return;
|
|
27568
27677
|
}
|
|
@@ -27583,6 +27692,7 @@ function createInboxSettlementController(options = {}) {
|
|
|
27583
27692
|
if (!job || job.settled)
|
|
27584
27693
|
continue;
|
|
27585
27694
|
if (!hasLease()) {
|
|
27695
|
+
job.discard?.(job.prepared);
|
|
27586
27696
|
finishJob(job, inboxLeaseError());
|
|
27587
27697
|
continue;
|
|
27588
27698
|
}
|
|
@@ -27618,6 +27728,7 @@ function createInboxSettlementController(options = {}) {
|
|
|
27618
27728
|
const job = {
|
|
27619
27729
|
chatId,
|
|
27620
27730
|
deferred: inboxDeferred(),
|
|
27731
|
+
discard: task.discard,
|
|
27621
27732
|
lane,
|
|
27622
27733
|
prepare: task.prepare,
|
|
27623
27734
|
prepared: null,
|
|
@@ -27675,6 +27786,10 @@ async function processInboxDocuments(context, documents, processingOptions = {})
|
|
|
27675
27786
|
const deferred = [];
|
|
27676
27787
|
await Promise.all(groups.map((group) => context.settlementController.schedule(cleanText(group[0]?.opened?.payload?.chatId), {
|
|
27677
27788
|
prepare: () => context.discoveryPool.run(() => prepareInboxWork(context, group[0], processingOptions)),
|
|
27789
|
+
discard: (work) => {
|
|
27790
|
+
work?.ping?.releaseMutation();
|
|
27791
|
+
context.state.revokeAnnouncement(work?.announcement);
|
|
27792
|
+
},
|
|
27678
27793
|
settle: async (first, markAuthoritative) => {
|
|
27679
27794
|
if (await settleInboxWork(context, first, markAuthoritative) === "deferred")
|
|
27680
27795
|
deferred.push(first.document);
|
|
@@ -27986,6 +28101,7 @@ function listenToChats(cloud, uid, userChatPK, userPrivKey, onUpdate, onError, o
|
|
|
27986
28101
|
nextAfterChat: snapshot.nextAfterChat,
|
|
27987
28102
|
hasMore: snapshot.hasMore,
|
|
27988
28103
|
ownerListToken: snapshot.ownerListToken,
|
|
28104
|
+
sourceRevision: snapshot.sourceRevision,
|
|
27989
28105
|
source: "server"
|
|
27990
28106
|
});
|
|
27991
28107
|
deleteConfirmedUserChats(cloud, uid, page.deletedEntryIds);
|
|
@@ -28210,7 +28326,8 @@ function listenToChats(cloud, uid, userChatPK, userPrivKey, onUpdate, onError, o
|
|
|
28210
28326
|
latestOwnerSnapshot = {
|
|
28211
28327
|
docs: entries,
|
|
28212
28328
|
nextAfterChat: meta.nextAfterChat ?? null,
|
|
28213
|
-
hasMore: !!meta.hasMore
|
|
28329
|
+
hasMore: !!meta.hasMore,
|
|
28330
|
+
sourceRevision: options.getSourceRevision?.()
|
|
28214
28331
|
};
|
|
28215
28332
|
queueOwnerSnapshot();
|
|
28216
28333
|
}, onError, { limitCount: pageSize });
|
|
@@ -28721,15 +28838,15 @@ function createChatListIndex({ cache, filterHiddenChats, getSources, isHiddenCha
|
|
|
28721
28838
|
const ownerFor = (entry) => composeActivity(structuralOwnerFor(entry), entry);
|
|
28722
28839
|
const cacheFor = (entry) => composeActivity(entry?.cache, entry);
|
|
28723
28840
|
const sourceCanPublish = (chat, sourceRevision) => {
|
|
28841
|
+
const boundary = authorityBoundaries.get(chat?.id);
|
|
28842
|
+
if (boundary?.terminal)
|
|
28843
|
+
return false;
|
|
28724
28844
|
if (!chat?.id || !Number.isSafeInteger(sourceRevision))
|
|
28725
28845
|
return true;
|
|
28726
28846
|
if (sourceRevision < sourceRevisionFloor)
|
|
28727
28847
|
return false;
|
|
28728
|
-
const boundary = authorityBoundaries.get(chat.id);
|
|
28729
28848
|
if (!boundary)
|
|
28730
28849
|
return true;
|
|
28731
|
-
if (boundary.terminal)
|
|
28732
|
-
return false;
|
|
28733
28850
|
return sourceRevision >= boundary.revision || compareOwners(chat, boundary.owner) > 0;
|
|
28734
28851
|
};
|
|
28735
28852
|
const sourceCanRemove = (chatId, sourceRevision) => {
|
|
@@ -28869,21 +28986,33 @@ function createChatListIndex({ cache, filterHiddenChats, getSources, isHiddenCha
|
|
|
28869
28986
|
updatePeers(shown);
|
|
28870
28987
|
return shown;
|
|
28871
28988
|
};
|
|
28989
|
+
const clearRemovedOwners = (chatIds) => {
|
|
28990
|
+
if (!chatIds.length)
|
|
28991
|
+
return;
|
|
28992
|
+
const sources = getSources();
|
|
28993
|
+
for (const chatId of chatIds)
|
|
28994
|
+
sources.pendingDeleteIdsRef.current.delete(chatId);
|
|
28995
|
+
sources.onOwnerRemoved?.(chatIds);
|
|
28996
|
+
cache.removeMany(chatIds);
|
|
28997
|
+
const removedIds = new Set(chatIds);
|
|
28998
|
+
sources.setSelectedChat((current) => removedIds.has(current) ? null : current);
|
|
28999
|
+
};
|
|
28872
29000
|
const convergeCompleteOwnerSet = (incomingIds = null, sourceRevision = null) => {
|
|
28873
|
-
const
|
|
29001
|
+
const removedIds = [];
|
|
28874
29002
|
for (const [chatId, entry] of entries) {
|
|
28875
|
-
if (
|
|
28876
|
-
|
|
28877
|
-
|
|
28878
|
-
|
|
28879
|
-
|
|
28880
|
-
evictedCacheIds.push(chatId);
|
|
28881
|
-
entries.delete(chatId);
|
|
28882
|
-
} else if (!incomingIds || !incomingIds.has(chatId)) {
|
|
29003
|
+
if (incomingIds ? incomingIds.has(chatId) : entry.observedOwner)
|
|
29004
|
+
continue;
|
|
29005
|
+
if (!sourceCanRemove(chatId, sourceRevision))
|
|
29006
|
+
continue;
|
|
29007
|
+
if (entry.announcement && !authorityBoundaries.get(chatId)?.owner) {
|
|
28883
29008
|
entry.cache = null;
|
|
29009
|
+
continue;
|
|
28884
29010
|
}
|
|
29011
|
+
recordTerminal(chatId, ownerFor(entry) || cacheFor(entry));
|
|
29012
|
+
entries.delete(chatId);
|
|
29013
|
+
removedIds.push(chatId);
|
|
28885
29014
|
}
|
|
28886
|
-
|
|
29015
|
+
clearRemovedOwners(removedIds);
|
|
28887
29016
|
};
|
|
28888
29017
|
const observeOwnerChats = (rows, options = {}) => {
|
|
28889
29018
|
const incoming = (rows || []).filter((chat) => chat?.id && sourceCanPublish(chat, options.sourceRevision));
|
|
@@ -28959,6 +29088,8 @@ function createChatListIndex({ cache, filterHiddenChats, getSources, isHiddenCha
|
|
|
28959
29088
|
const announceWelcome = (announcement) => {
|
|
28960
29089
|
if (!announcement?.chatId || !announcement?.token)
|
|
28961
29090
|
return false;
|
|
29091
|
+
if (authorityBoundaries.get(announcement.chatId)?.terminal)
|
|
29092
|
+
return false;
|
|
28962
29093
|
const sources = getSources();
|
|
28963
29094
|
if (sources.pendingDeleteIdsRef.current.has(announcement.chatId))
|
|
28964
29095
|
return false;
|
|
@@ -28995,7 +29126,6 @@ function createChatListIndex({ cache, filterHiddenChats, getSources, isHiddenCha
|
|
|
28995
29126
|
return false;
|
|
28996
29127
|
if (!sourceCanRemove(chatId, options.sourceRevision))
|
|
28997
29128
|
return false;
|
|
28998
|
-
recordTerminal(chatId, cacheFor(entry));
|
|
28999
29129
|
entry.cache = null;
|
|
29000
29130
|
entry.presentation = null;
|
|
29001
29131
|
cache.remove(chatId);
|
|
@@ -29005,15 +29135,12 @@ function createChatListIndex({ cache, filterHiddenChats, getSources, isHiddenCha
|
|
|
29005
29135
|
return true;
|
|
29006
29136
|
};
|
|
29007
29137
|
const removeOwner = (chatId, options = {}) => {
|
|
29008
|
-
const sources = getSources();
|
|
29009
29138
|
if (!chatId)
|
|
29010
29139
|
return false;
|
|
29011
29140
|
recordTerminal(chatId, ownerFor(entries.get(chatId)) || cacheFor(entries.get(chatId)));
|
|
29012
|
-
sources.pendingDeleteIdsRef.current.delete(chatId);
|
|
29013
29141
|
const removed = entries.delete(chatId);
|
|
29014
|
-
|
|
29142
|
+
clearRemovedOwners([chatId]);
|
|
29015
29143
|
publishOwners({ ...options, warm: false });
|
|
29016
|
-
sources.setSelectedChat((current) => current === chatId ? null : current);
|
|
29017
29144
|
return removed;
|
|
29018
29145
|
};
|
|
29019
29146
|
const removeInboxOwner = (chatId, options = {}) => {
|
|
@@ -29370,7 +29497,7 @@ function createChatListListener({
|
|
|
29370
29497
|
sync();
|
|
29371
29498
|
}, CHAT_LIST_LISTENER_RETRY_MS);
|
|
29372
29499
|
};
|
|
29373
|
-
const subscription = subscribe(sources.cloud, sources.uid, sources.chatPK, sources.chatPrivateKey, (nextChats, _nextPeers, meta = {}) => handleUpdate(nextChats, meta, listenStartedAt,
|
|
29500
|
+
const subscription = subscribe(sources.cloud, sources.uid, sources.chatPK, sources.chatPrivateKey, (nextChats, _nextPeers, meta = {}) => handleUpdate(nextChats, meta, listenStartedAt, meta.sourceRevision), (error) => {
|
|
29374
29501
|
const current = getSources();
|
|
29375
29502
|
state.setIsChatListLive(false);
|
|
29376
29503
|
markError(current.diag, "chat.provider.listen", listenStartedAt, error);
|
|
@@ -29381,6 +29508,7 @@ function createChatListListener({
|
|
|
29381
29508
|
retry(error);
|
|
29382
29509
|
}, {
|
|
29383
29510
|
limitCount: CHAT_LIST_LIVE_COUNT,
|
|
29511
|
+
getSourceRevision: index.getAuthorityRevision,
|
|
29384
29512
|
onInboxAnnouncement: index.announceWelcome,
|
|
29385
29513
|
onInboxRevoke: index.revokeAnnouncement,
|
|
29386
29514
|
onInboxCommit: index.commitOwner,
|
|
@@ -31039,7 +31167,7 @@ function patchMessageFromCachedMessage(message, cached) {
|
|
|
31039
31167
|
const patch = {};
|
|
31040
31168
|
let changed = false;
|
|
31041
31169
|
const cachedReactions = getMsgReactions(cached);
|
|
31042
|
-
if (cachedReactions.length && !
|
|
31170
|
+
if (cachedReactions.length && !sameReactions(message.reactions, cached.reactions)) {
|
|
31043
31171
|
patch.reactions = cachedReactions;
|
|
31044
31172
|
changed = true;
|
|
31045
31173
|
}
|
|
@@ -31065,19 +31193,6 @@ function patchMessageFromCachedMessage(message, cached) {
|
|
|
31065
31193
|
}
|
|
31066
31194
|
return changed ? { ...message, ...patch } : message;
|
|
31067
31195
|
}
|
|
31068
|
-
function sameReactionProjection(a, b) {
|
|
31069
|
-
const left = getMsgReactions(a);
|
|
31070
|
-
const right = getMsgReactions(b);
|
|
31071
|
-
if (left.length !== right.length) {
|
|
31072
|
-
return false;
|
|
31073
|
-
}
|
|
31074
|
-
for (let index = 0;index < left.length; index += 1) {
|
|
31075
|
-
if (left[index].user !== right[index]?.user || left[index].emoji !== right[index]?.emoji) {
|
|
31076
|
-
return false;
|
|
31077
|
-
}
|
|
31078
|
-
}
|
|
31079
|
-
return true;
|
|
31080
|
-
}
|
|
31081
31196
|
function patchMessagesFromCachedWindow(messages, cachedMessages) {
|
|
31082
31197
|
if (!messages?.length || !cachedMessages?.length) {
|
|
31083
31198
|
return messages || [];
|
|
@@ -31734,6 +31849,7 @@ async function createGroupChat(cloud, identityValue, memberValues, settings = {}
|
|
|
31734
31849
|
if (!identity.chatSigningSecret)
|
|
31735
31850
|
throw new Error("unlocked chat signing identity required");
|
|
31736
31851
|
const mls = await lifecycle.mls?.open?.();
|
|
31852
|
+
lifecycle.assertCurrent?.();
|
|
31737
31853
|
if (!mls)
|
|
31738
31854
|
throw new Error("mls engine required");
|
|
31739
31855
|
const selfLeafId = lifecycle.selfLeafId || randomBytes3(32);
|
|
@@ -31754,7 +31870,7 @@ async function createGroupChat(cloud, identityValue, memberValues, settings = {}
|
|
|
31754
31870
|
if (additions.length)
|
|
31755
31871
|
mlsGroup = await mls.stageChange(mlsGroup.snapshot, { adds: additions });
|
|
31756
31872
|
const material = deriveChatMlsEpochMaterial(mlsGroup.epochKey, { chatId, epochVersion: 1 });
|
|
31757
|
-
const lineage = members.length === 1 ? CHAT_LINEAGES.SELF : members.length === 2 ? CHAT_LINEAGES.DIRECT : CHAT_LINEAGES.GROUP;
|
|
31873
|
+
const lineage = lifecycle.lineage || (members.length === 1 ? CHAT_LINEAGES.SELF : members.length === 2 ? CHAT_LINEAGES.DIRECT : CHAT_LINEAGES.GROUP);
|
|
31758
31874
|
const manifest = makeInitialEpochManifest({
|
|
31759
31875
|
chatId,
|
|
31760
31876
|
epochId: material.epochId,
|
|
@@ -31817,6 +31933,7 @@ async function createGroupChat(cloud, identityValue, memberValues, settings = {}
|
|
|
31817
31933
|
});
|
|
31818
31934
|
initial.backend.membershipOutbox = queuedWelcomes.map(({ outboxId: outboxId2, sealed }) => ({ outboxId: outboxId2, sealed }));
|
|
31819
31935
|
stage = "owner";
|
|
31936
|
+
lifecycle.assertCurrent?.();
|
|
31820
31937
|
const registration = registerInitialDelivery(cloud, identity, initialState);
|
|
31821
31938
|
const stateId = chatMlsStateId(identity.chatPrivateKey, chatId, initial.transitionCommitment);
|
|
31822
31939
|
const ownerMlsState = await sealChatMlsState(identity.chatPrivateKey, stateId, { v: 1, chatId, transitionCommitment: initial.transitionCommitment }, mlsGroup.snapshot);
|
|
@@ -31828,6 +31945,8 @@ async function createGroupChat(cloud, identityValue, memberValues, settings = {}
|
|
|
31828
31945
|
let stateError = null;
|
|
31829
31946
|
try {
|
|
31830
31947
|
stage = "state";
|
|
31948
|
+
lifecycle.assertCurrent?.();
|
|
31949
|
+
lifecycle.onCreateDispatched?.(initial.manifest.chatId);
|
|
31831
31950
|
await cloud.chat.state.create({
|
|
31832
31951
|
...initial.backend,
|
|
31833
31952
|
ownerEntry: owner.write,
|
|
@@ -32182,21 +32301,23 @@ function createChatSessionLaunches({
|
|
|
32182
32301
|
if (!opened?.chatId || !opened?.entry)
|
|
32183
32302
|
return "";
|
|
32184
32303
|
const chat = projectOwnChatEntry(opened.entry, opened.entryId || "", operation.identity.chatPK, opened.tsMs || Date.now());
|
|
32185
|
-
operation.listOwner.commitOwner(chat)
|
|
32304
|
+
if (!operation.listOwner.commitOwner(chat))
|
|
32305
|
+
throw makeChatUnavailableError();
|
|
32186
32306
|
return opened.chatId;
|
|
32187
32307
|
};
|
|
32188
32308
|
const presentOpenedChat = (opened, operation) => {
|
|
32189
32309
|
assertCurrent(operation);
|
|
32190
32310
|
if (!opened?.chatId || !opened?.entry)
|
|
32191
32311
|
return "";
|
|
32192
|
-
operation.pendingOwner.adoptOpenedChatId(opened.chatId);
|
|
32193
32312
|
const chatId = commitOpenedChat(opened, operation);
|
|
32313
|
+
operation.pendingOwner.adoptOpenedChatId(chatId);
|
|
32194
32314
|
pendingPeerSelect = null;
|
|
32195
32315
|
setSelectedChat(chatId);
|
|
32196
32316
|
return chatId;
|
|
32197
32317
|
};
|
|
32198
32318
|
const createChat = async (profiles, settings, lifecycle, adoptOpenedChat, operation, { profilesCurrent = false } = {}) => {
|
|
32199
32319
|
assertCurrent(operation);
|
|
32320
|
+
lifecycle.assertCurrent?.();
|
|
32200
32321
|
const { blocked, chatPK, chatPrivateKey } = operation.identity;
|
|
32201
32322
|
let profileList = Array.isArray(profiles) ? profiles : [profiles];
|
|
32202
32323
|
if (!profilesCurrent && profileList.length) {
|
|
@@ -32204,9 +32325,10 @@ function createChatSessionLaunches({
|
|
|
32204
32325
|
}
|
|
32205
32326
|
const blockedSet = new Set(blocked);
|
|
32206
32327
|
const requestedMembers = profileList.map(profileMember);
|
|
32207
|
-
|
|
32328
|
+
const expectedLineage = lifecycle.lineage || (requestedMembers.length === 0 ? "self" : requestedMembers.length === 1 ? "direct" : "group");
|
|
32329
|
+
if (expectedLineage === "direct") {
|
|
32208
32330
|
assertDirectAdmission(profileList[0], operation);
|
|
32209
|
-
} else if (
|
|
32331
|
+
} else if (expectedLineage === "group") {
|
|
32210
32332
|
if (normalizeChatAdmission(operation.identity.chatAdmission).groups === CHAT_GROUP_ADMISSION_MODES.CLOSED) {
|
|
32211
32333
|
throw new Error("group chats are closed");
|
|
32212
32334
|
}
|
|
@@ -32220,8 +32342,7 @@ function createChatSessionLaunches({
|
|
|
32220
32342
|
if (blockedSet.has(member.uid))
|
|
32221
32343
|
throw new Error("blocked peer cannot be added");
|
|
32222
32344
|
}
|
|
32223
|
-
const canonicalChatId = lifecycle.chatId || (
|
|
32224
|
-
const expectedLineage = requestedMembers.length === 0 ? "self" : requestedMembers.length === 1 ? "direct" : "group";
|
|
32345
|
+
const canonicalChatId = lifecycle.chatId || (expectedLineage === "self" ? deriveSelfChatId(chatPrivateKey, chatPK) : "");
|
|
32225
32346
|
const expectedMemberKeys = [chatPK, ...requestedMembers.map((member) => member.chatPK)].sort();
|
|
32226
32347
|
const matchingExistingChat = () => {
|
|
32227
32348
|
assertCurrent(operation);
|
|
@@ -32260,6 +32381,7 @@ function createChatSessionLaunches({
|
|
|
32260
32381
|
markDiag(diag, "chat.group.create.prekeys.start", { members: requestedMembers.length });
|
|
32261
32382
|
const additions = await prepareMlsAdditions(profileList);
|
|
32262
32383
|
assertCurrent(operation);
|
|
32384
|
+
lifecycle.assertCurrent?.();
|
|
32263
32385
|
markDiag(diag, "chat.group.create.prekeys.done", { members: requestedMembers.length, elapsedMs: Date.now() - prekeyStartedAt });
|
|
32264
32386
|
if (!additions.length && requestedMembers.length)
|
|
32265
32387
|
throw new Error("peer mls key package required");
|
|
@@ -32269,15 +32391,23 @@ function createChatSessionLaunches({
|
|
|
32269
32391
|
const created = await createGroupChat(cloud, operation.transitionIdentity, [...byKey.values()], settings, {
|
|
32270
32392
|
mls,
|
|
32271
32393
|
chatId: canonicalChatId || undefined,
|
|
32394
|
+
lineage: expectedLineage,
|
|
32272
32395
|
wakeMessageId: lifecycle.wakeMessageId,
|
|
32396
|
+
assertCurrent: () => {
|
|
32397
|
+
assertCurrent(operation);
|
|
32398
|
+
lifecycle.assertCurrent?.();
|
|
32399
|
+
},
|
|
32400
|
+
onCreateDispatched: lifecycle.onCreateDispatched,
|
|
32273
32401
|
onStateReady: (opened) => {
|
|
32274
32402
|
assertCurrent(operation);
|
|
32403
|
+
lifecycle.assertCurrent?.();
|
|
32275
32404
|
stateReady = true;
|
|
32276
32405
|
const chatId = adoptOpenedChat(opened);
|
|
32277
32406
|
lifecycle.onStateReady?.(chatId, opened, { created: true });
|
|
32278
32407
|
},
|
|
32279
32408
|
onOwnerReady: async (opened) => {
|
|
32280
32409
|
assertCurrent(operation);
|
|
32410
|
+
lifecycle.assertCurrent?.();
|
|
32281
32411
|
const chatId = adoptOpenedChat(opened);
|
|
32282
32412
|
const result = await lifecycle.onOwnerReady?.(chatId, opened, { created: true });
|
|
32283
32413
|
assertCurrent(operation);
|
|
@@ -32288,7 +32418,7 @@ function createChatSessionLaunches({
|
|
|
32288
32418
|
return adoptOpenedChat(created);
|
|
32289
32419
|
} catch (error) {
|
|
32290
32420
|
assertCurrent(operation);
|
|
32291
|
-
if (stateReady || !canonicalChatId
|
|
32421
|
+
if (stateReady || !canonicalChatId)
|
|
32292
32422
|
throw error;
|
|
32293
32423
|
await ensureChat(canonicalChatId);
|
|
32294
32424
|
assertCurrent(operation);
|
|
@@ -32302,6 +32432,10 @@ function createChatSessionLaunches({
|
|
|
32302
32432
|
const operation = operationContext();
|
|
32303
32433
|
return createChat(profiles, settings, lifecycle, (opened) => presentOpenedChat(opened, operation), operation);
|
|
32304
32434
|
};
|
|
32435
|
+
const materializeGroupChat = (profiles, settings = {}, lifecycle = {}) => {
|
|
32436
|
+
const operation = operationContext();
|
|
32437
|
+
return createChat(profiles, settings, lifecycle, (opened) => commitOpenedChat(opened, operation), operation);
|
|
32438
|
+
};
|
|
32305
32439
|
const runExistingDirectLifecycle = async (chatId, lifecycle, operation) => {
|
|
32306
32440
|
assertCurrent(operation);
|
|
32307
32441
|
const existing = getOwnerChat(chatId);
|
|
@@ -32373,6 +32507,7 @@ function createChatSessionLaunches({
|
|
|
32373
32507
|
getOpenOperation: (chatId) => directOpens.get(chatId)?.promise || null,
|
|
32374
32508
|
getPeerChatId,
|
|
32375
32509
|
materializeDirectChat,
|
|
32510
|
+
materializeGroupChat,
|
|
32376
32511
|
openDirectChat,
|
|
32377
32512
|
openNotesChat,
|
|
32378
32513
|
releaseOpenOperation: (chatId) => {
|
|
@@ -32500,16 +32635,21 @@ function createChatSessionPending({
|
|
|
32500
32635
|
getPeerProfile,
|
|
32501
32636
|
resolvePeerProfile,
|
|
32502
32637
|
setLocalByChat,
|
|
32503
|
-
getLocalByChat = () => new Map
|
|
32638
|
+
getLocalByChat = () => new Map,
|
|
32639
|
+
retireMaterializedChat = () => {}
|
|
32504
32640
|
}) {
|
|
32641
|
+
const admission = createChatAdmission({ getIdentity });
|
|
32505
32642
|
let pendingLaunch = null;
|
|
32506
32643
|
const pendingOperations = new Map;
|
|
32507
32644
|
let generation = 0;
|
|
32645
|
+
const operationForChat = (chatId) => pendingOperations.get(chatId) || [...pendingOperations.values()].find((state) => state.canonicalChatId === chatId) || null;
|
|
32646
|
+
const launchForChat = (chatId) => pendingLaunch && [pendingLaunch.id, pendingLaunch.canonicalChatId].includes(chatId) ? pendingLaunch : operationForChat(chatId)?.launch || storedLaunch(chatId);
|
|
32508
32647
|
const storedLaunch = (chatId) => getLocalByChat().get(chatId)?.find((message) => message.chatDraft)?.chatDraft || null;
|
|
32509
32648
|
const getPendingLaunch = () => {
|
|
32510
32649
|
if (!pendingLaunch)
|
|
32511
32650
|
return null;
|
|
32512
|
-
const
|
|
32651
|
+
const localByChat = getLocalByChat();
|
|
32652
|
+
const messages = localByChat.get(pendingLaunch.id) || localByChat.get(pendingLaunch.canonicalChatId) || [];
|
|
32513
32653
|
const message = messages[messages.length - 1] || null;
|
|
32514
32654
|
return { ...pendingLaunch, messages, message, chat: {
|
|
32515
32655
|
...pendingLaunch.chat,
|
|
@@ -32517,23 +32657,33 @@ function createChatSessionPending({
|
|
|
32517
32657
|
ts: message ? timestampMs(message.ts, null) : null
|
|
32518
32658
|
} };
|
|
32519
32659
|
};
|
|
32660
|
+
const resolvePendingChatId = (chatId) => {
|
|
32661
|
+
const canonicalId = operationForChat(chatId)?.canonicalChatId || launchForChat(chatId)?.canonicalChatId;
|
|
32662
|
+
return canonicalId && getOwnerChat(canonicalId) ? canonicalId : chatId;
|
|
32663
|
+
};
|
|
32520
32664
|
const finish = (launchId) => {
|
|
32521
32665
|
if (pendingLaunch?.id !== launchId)
|
|
32522
32666
|
return;
|
|
32667
|
+
if (pendingLaunch.canonicalChatId !== launchId) {
|
|
32668
|
+
publish();
|
|
32669
|
+
return;
|
|
32670
|
+
}
|
|
32523
32671
|
pendingLaunch = null;
|
|
32524
32672
|
pendingOperations.delete(launchId);
|
|
32525
32673
|
publish();
|
|
32526
32674
|
};
|
|
32527
32675
|
const track = (launchId, operation) => {
|
|
32528
32676
|
const tracked = Promise.resolve(operation);
|
|
32529
|
-
pendingOperations.
|
|
32677
|
+
const state = pendingOperations.get(launchId) || { active: true, promise: null };
|
|
32678
|
+
state.promise = tracked;
|
|
32679
|
+
pendingOperations.set(launchId, state);
|
|
32530
32680
|
tracked.then(() => {
|
|
32531
|
-
if (pendingOperations.get(launchId) !== tracked)
|
|
32681
|
+
if (pendingOperations.get(launchId) !== state || state.promise !== tracked)
|
|
32532
32682
|
return;
|
|
32533
32683
|
pendingOperations.delete(launchId);
|
|
32534
32684
|
finish(launchId);
|
|
32535
32685
|
}, () => {
|
|
32536
|
-
if (pendingOperations.get(launchId) !== tracked)
|
|
32686
|
+
if (pendingOperations.get(launchId) !== state || state.promise !== tracked)
|
|
32537
32687
|
return;
|
|
32538
32688
|
pendingOperations.delete(launchId);
|
|
32539
32689
|
if (pendingLaunch?.id !== launchId)
|
|
@@ -32545,6 +32695,12 @@ function createChatSessionPending({
|
|
|
32545
32695
|
});
|
|
32546
32696
|
return tracked;
|
|
32547
32697
|
};
|
|
32698
|
+
const cancelOperation = (launchId) => {
|
|
32699
|
+
const operation = pendingOperations.get(launchId);
|
|
32700
|
+
if (operation)
|
|
32701
|
+
operation.active = false;
|
|
32702
|
+
pendingOperations.delete(launchId);
|
|
32703
|
+
};
|
|
32548
32704
|
const show = (launch) => {
|
|
32549
32705
|
if (pendingLaunch?.id && pendingLaunch.id !== launch.id && !pendingOperations.has(pendingLaunch.id)) {
|
|
32550
32706
|
getRouteOwner().releaseOpenOperation?.(pendingLaunch.id);
|
|
@@ -32640,7 +32796,7 @@ function createChatSessionPending({
|
|
|
32640
32796
|
return cached;
|
|
32641
32797
|
return (fallbackProfiles || []).find((profile) => profileMatchesPeer(profile, peer)) || null;
|
|
32642
32798
|
};
|
|
32643
|
-
const profileAcceptsDirect = (identity, profile) => !!identity?.chatPK && !!identity?.chatPrivateKey && directAdmissionForPeer(
|
|
32799
|
+
const profileAcceptsDirect = (identity, profile) => !!identity?.chatPK && !!identity?.chatPrivateKey && admission.directAdmissionForPeer(profile) !== CHAT_ADMISSION_DECISIONS.REJECT;
|
|
32644
32800
|
const isChatAdmitted = (chat, fallbackProfiles = []) => {
|
|
32645
32801
|
const identity = getIdentity();
|
|
32646
32802
|
if (!chat)
|
|
@@ -32773,18 +32929,29 @@ function createChatSessionPending({
|
|
|
32773
32929
|
throw error;
|
|
32774
32930
|
}
|
|
32775
32931
|
};
|
|
32776
|
-
const
|
|
32777
|
-
const
|
|
32778
|
-
|
|
32779
|
-
|
|
32780
|
-
|
|
32932
|
+
const withReadyAttachmentTarget = async (chatId, options, send) => {
|
|
32933
|
+
const attemptGeneration = generation;
|
|
32934
|
+
await waitForSend(chatId, { expiresAt: options.expiresAt, signal: options.signal });
|
|
32935
|
+
if (attemptGeneration !== generation)
|
|
32936
|
+
throw makeChatUnavailableError();
|
|
32781
32937
|
const target = await admittedSendTarget(chatId, options);
|
|
32782
|
-
|
|
32938
|
+
if (attemptGeneration !== generation)
|
|
32939
|
+
throw makeChatUnavailableError();
|
|
32940
|
+
return send(target);
|
|
32783
32941
|
};
|
|
32942
|
+
const sendDurableAttachment = (chatId, attachment, options = {}) => withReadyAttachmentTarget(chatId, options, (target) => getSendActions().sendAttachment(target.routeAnchor, attachment, target.options));
|
|
32943
|
+
const sendDurableSharedAttachment = (chatId, attachment, options = {}) => withReadyAttachmentTarget(chatId, options, (target) => getSendActions().sendSharedAttachment(target.routeAnchor, attachment, target.options));
|
|
32784
32944
|
const stagePendingMessage = (launchId, local) => {
|
|
32785
|
-
|
|
32945
|
+
const launch = launchForChat(launchId);
|
|
32946
|
+
if (!launch || launch.id !== launchId)
|
|
32786
32947
|
throw makeChatUnavailableError();
|
|
32787
|
-
const { id, profiles: profiles2, settings, chat } =
|
|
32948
|
+
const { id, profiles: profiles2, settings, chat } = launch;
|
|
32949
|
+
const canonicalId = resolvePendingChatId(launchId);
|
|
32950
|
+
if (getOwnerChat(canonicalId)) {
|
|
32951
|
+
const { chatDraft: _draft, ...content } = local;
|
|
32952
|
+
setLocalByChat((current) => addLocalMessage(current, canonicalId, content));
|
|
32953
|
+
return;
|
|
32954
|
+
}
|
|
32788
32955
|
const chatDraft = { id, canonicalChatId: id, profiles: profiles2, settings, chat };
|
|
32789
32956
|
setLocalByChat((current) => addLocalMessage(current, launchId, { ...local, chatDraft }));
|
|
32790
32957
|
};
|
|
@@ -32796,6 +32963,8 @@ function createChatSessionPending({
|
|
|
32796
32963
|
const canonical = targetId !== launchId ? current.get(targetId) || [] : [];
|
|
32797
32964
|
const writerIds = new Set(canonical.map((message) => message.cid));
|
|
32798
32965
|
const staged = (current.get(launchId) || []).filter((message) => !writerIds.has(message.cid));
|
|
32966
|
+
if (!canonical.length && !staged.length)
|
|
32967
|
+
return current;
|
|
32799
32968
|
next.set(targetId, [...canonical, ...staged].map((message) => {
|
|
32800
32969
|
const { chatDraft, ...content } = message;
|
|
32801
32970
|
return {
|
|
@@ -32811,14 +32980,22 @@ function createChatSessionPending({
|
|
|
32811
32980
|
if (getOwnerChat(canonicalId) && pendingLaunch?.id === launchId)
|
|
32812
32981
|
setSelectedChat(canonicalId);
|
|
32813
32982
|
};
|
|
32814
|
-
const
|
|
32815
|
-
const launch =
|
|
32816
|
-
if (!launch
|
|
32983
|
+
const dropChat = (chatId) => {
|
|
32984
|
+
const launch = launchForChat(chatId);
|
|
32985
|
+
if (!launch || launch.id !== chatId && launch.canonicalChatId !== chatId)
|
|
32817
32986
|
return false;
|
|
32818
32987
|
beginSelection();
|
|
32819
32988
|
getRouteOwner().releaseOpenOperation?.(launch.id);
|
|
32820
|
-
pendingLaunch
|
|
32821
|
-
|
|
32989
|
+
if (pendingLaunch?.id === launch.id)
|
|
32990
|
+
pendingLaunch = null;
|
|
32991
|
+
cancelOperation(launch.id);
|
|
32992
|
+
setLocalByChat((current) => {
|
|
32993
|
+
if (!current.has(launch.id))
|
|
32994
|
+
return current;
|
|
32995
|
+
const next = new Map(current);
|
|
32996
|
+
next.delete(launch.id);
|
|
32997
|
+
return next;
|
|
32998
|
+
});
|
|
32822
32999
|
if (getSelectedChatId() === launch.id || getSelectedChatId() === launch.canonicalChatId) {
|
|
32823
33000
|
setSelectedChat(null);
|
|
32824
33001
|
} else {
|
|
@@ -32826,25 +33003,74 @@ function createChatSessionPending({
|
|
|
32826
33003
|
}
|
|
32827
33004
|
return true;
|
|
32828
33005
|
};
|
|
33006
|
+
const retirePeer = (peerChatPK) => pendingLaunch?.chat?.members?.some((member) => member?.chatPK === peerChatPK) ? dropChat(pendingLaunch.id) : false;
|
|
33007
|
+
const discardChat = async (chatId) => {
|
|
33008
|
+
const state = operationForChat(chatId);
|
|
33009
|
+
if (!state?.dispatched)
|
|
33010
|
+
return { discarded: dropChat(chatId), chat: null };
|
|
33011
|
+
state.discarding = true;
|
|
33012
|
+
if (pendingLaunch?.id === state.launch.id)
|
|
33013
|
+
pendingLaunch = null;
|
|
33014
|
+
if ([state.launch.id, state.canonicalChatId].includes(getSelectedChatId()))
|
|
33015
|
+
setSelectedChat(null);
|
|
33016
|
+
else
|
|
33017
|
+
publish();
|
|
33018
|
+
state.retirementTarget ||= getOwnerChat(state.canonicalChatId) || null;
|
|
33019
|
+
if (state.retirementTarget)
|
|
33020
|
+
retireMaterializedChat(state.canonicalChatId);
|
|
33021
|
+
const attemptGeneration = generation;
|
|
33022
|
+
await state.promise.catch(() => null);
|
|
33023
|
+
if (attemptGeneration !== generation)
|
|
33024
|
+
throw makeChatUnavailableError();
|
|
33025
|
+
if (!state.retirementTarget) {
|
|
33026
|
+
if (!getOwnerChat(state.canonicalChatId))
|
|
33027
|
+
await ensureChat(state.canonicalChatId);
|
|
33028
|
+
state.retirementTarget = getOwnerChat(state.canonicalChatId) || null;
|
|
33029
|
+
}
|
|
33030
|
+
if (attemptGeneration !== generation || !state.retirementTarget)
|
|
33031
|
+
throw makeChatUnavailableError();
|
|
33032
|
+
retireMaterializedChat(state.canonicalChatId);
|
|
33033
|
+
return { discarded: true, chat: state.retirementTarget };
|
|
33034
|
+
};
|
|
32829
33035
|
const materialize = (launchId, wakeMessageId, sendInitial) => {
|
|
32830
33036
|
const launch = pendingLaunch;
|
|
32831
33037
|
if (!launch || launch.id !== launchId || pendingOperations.has(launchId))
|
|
32832
33038
|
throw makeChatUnavailableError();
|
|
32833
33039
|
const attemptGeneration = generation;
|
|
33040
|
+
const state = { active: true, promise: null, launch, canonicalChatId: launchId };
|
|
33041
|
+
pendingOperations.set(launchId, state);
|
|
33042
|
+
const assertCurrent = () => {
|
|
33043
|
+
if (attemptGeneration !== generation || !state.active)
|
|
33044
|
+
throw makeChatUnavailableError();
|
|
33045
|
+
};
|
|
32834
33046
|
const expiresAt = Date.now() + CHAT_SEND_CONNECTION_WAIT_MS;
|
|
32835
33047
|
let canonicalId = launchId;
|
|
32836
33048
|
const operation = (async () => {
|
|
32837
33049
|
await waitForSend(launchId, { expiresAt });
|
|
32838
|
-
|
|
32839
|
-
throw makeChatUnavailableError();
|
|
33050
|
+
assertCurrent();
|
|
32840
33051
|
let initialResult = null;
|
|
32841
33052
|
const lifecycle = {
|
|
32842
33053
|
wakeMessageId,
|
|
33054
|
+
assertCurrent,
|
|
33055
|
+
onCreateDispatched: (chatId) => {
|
|
33056
|
+
assertCurrent();
|
|
33057
|
+
state.dispatched = true;
|
|
33058
|
+
state.canonicalChatId = chatId;
|
|
33059
|
+
state.launch = { ...state.launch, canonicalChatId: chatId };
|
|
33060
|
+
},
|
|
32843
33061
|
onStateReady: (chatId) => {
|
|
33062
|
+
assertCurrent();
|
|
32844
33063
|
canonicalId = chatId;
|
|
33064
|
+
state.canonicalChatId = chatId;
|
|
33065
|
+
state.launch = { ...state.launch, canonicalChatId: chatId };
|
|
32845
33066
|
adoptOpenedChatId(chatId, launchId);
|
|
33067
|
+
if (state.discarding) {
|
|
33068
|
+
state.retirementTarget = getOwnerChat(chatId);
|
|
33069
|
+
retireMaterializedChat(chatId);
|
|
33070
|
+
}
|
|
32846
33071
|
},
|
|
32847
33072
|
onOwnerReady: async (chatId, _opened, context) => {
|
|
33073
|
+
assertCurrent();
|
|
32848
33074
|
canonicalId = chatId;
|
|
32849
33075
|
initialResult = await sendInitial(chatId, { ...context, expiresAt });
|
|
32850
33076
|
return initialResult;
|
|
@@ -32859,18 +33085,20 @@ function createChatSessionPending({
|
|
|
32859
33085
|
canonicalId = resolvedChatId;
|
|
32860
33086
|
initialResult = await sendInitial(resolvedChatId, { created: false, expiresAt });
|
|
32861
33087
|
} else {
|
|
32862
|
-
canonicalId = await getRouteOwner().
|
|
33088
|
+
canonicalId = await getRouteOwner().materializeGroupChat(launch.profiles, launch.settings, {
|
|
32863
33089
|
...lifecycle,
|
|
32864
|
-
chatId:
|
|
33090
|
+
chatId: launch.canonicalChatId,
|
|
33091
|
+
lineage: launch.chat.lineage
|
|
32865
33092
|
});
|
|
32866
33093
|
}
|
|
32867
33094
|
}
|
|
32868
33095
|
if (attemptGeneration !== generation)
|
|
32869
33096
|
throw makeChatUnavailableError();
|
|
32870
|
-
|
|
33097
|
+
if (state.active)
|
|
33098
|
+
settleMaterialization(launchId, canonicalId);
|
|
32871
33099
|
return { ...initialResult || {}, chatId: canonicalId };
|
|
32872
33100
|
})().catch((error) => {
|
|
32873
|
-
if (attemptGeneration === generation)
|
|
33101
|
+
if (attemptGeneration === generation && state.active)
|
|
32874
33102
|
settleMaterialization(launchId, canonicalId, true);
|
|
32875
33103
|
throw error;
|
|
32876
33104
|
});
|
|
@@ -32881,10 +33109,74 @@ function createChatSessionPending({
|
|
|
32881
33109
|
...context?.expiresAt ? { expiresAt: context.expiresAt } : {},
|
|
32882
33110
|
...context?.created === true ? { deliverRecipients: false, ownerImmediate: true } : {}
|
|
32883
33111
|
});
|
|
33112
|
+
const runChatMutation = (chatId, mutate, { initialProfiles } = {}) => {
|
|
33113
|
+
const launch = launchForChat(chatId);
|
|
33114
|
+
const canonicalId = resolvePendingChatId(chatId);
|
|
33115
|
+
const active = launch && pendingOperations.get(launch.id);
|
|
33116
|
+
if (active?.discarding)
|
|
33117
|
+
throw makeChatUnavailableError();
|
|
33118
|
+
if (!active && getOwnerChat(canonicalId))
|
|
33119
|
+
return mutate(canonicalId, { created: false });
|
|
33120
|
+
if (!launch || getIdentity().chatBanned)
|
|
33121
|
+
throw makeChatUnavailableError();
|
|
33122
|
+
const attemptGeneration = generation;
|
|
33123
|
+
const perform = async (id, context) => {
|
|
33124
|
+
if (attemptGeneration !== generation)
|
|
33125
|
+
throw makeChatUnavailableError();
|
|
33126
|
+
const value = await mutate(id, context);
|
|
33127
|
+
if (attemptGeneration !== generation)
|
|
33128
|
+
throw makeChatUnavailableError();
|
|
33129
|
+
const ownerEntry = getOwnerChat(id)?.ownEntry;
|
|
33130
|
+
if (!ownerEntry)
|
|
33131
|
+
throw makeChatUnavailableError();
|
|
33132
|
+
return { value, ownerEntry };
|
|
33133
|
+
};
|
|
33134
|
+
if (active) {
|
|
33135
|
+
return track(launch.id, active.promise.then(async (result) => {
|
|
33136
|
+
if (!active.active)
|
|
33137
|
+
throw makeChatUnavailableError();
|
|
33138
|
+
const id = result?.chatId || launch.canonicalChatId;
|
|
33139
|
+
return { ...await perform(id, { created: false }), chatId: id };
|
|
33140
|
+
})).then((result) => result.value);
|
|
33141
|
+
}
|
|
33142
|
+
pendingLaunch = launch;
|
|
33143
|
+
if (initialProfiles) {
|
|
33144
|
+
if (launch.chat.lineage === "self")
|
|
33145
|
+
throw new Error("self chat membership is fixed");
|
|
33146
|
+
const profiles2 = initialProfiles(launch.profiles);
|
|
33147
|
+
if (profiles2 === launch.profiles)
|
|
33148
|
+
return Promise.resolve({ unchanged: true });
|
|
33149
|
+
const members = profiles2.map(profileMember);
|
|
33150
|
+
chatCapabilities(members.length + 1);
|
|
33151
|
+
const self2 = memberFromChatIdentity(transitionIdentity());
|
|
33152
|
+
if (members.some((member) => member.chatPK === self2.chatPK))
|
|
33153
|
+
throw new Error("current user is already a chat member");
|
|
33154
|
+
const lineage = launch.chat.lineage === "group" || members.length !== 1 ? "group" : launch.chat.lineage;
|
|
33155
|
+
pendingLaunch = {
|
|
33156
|
+
...launch,
|
|
33157
|
+
canonicalChatId: lineage === "group" && launch.chat.lineage !== "group" ? randomChatId() : launch.canonicalChatId,
|
|
33158
|
+
profiles: profiles2.map((profile, index) => pendingProfile(profile, members[index])),
|
|
33159
|
+
chat: {
|
|
33160
|
+
...launch.chat,
|
|
33161
|
+
lineage,
|
|
33162
|
+
peerChatPK: lineage === "direct" ? members[0]?.chatPK || null : null,
|
|
33163
|
+
members: [self2, ...members],
|
|
33164
|
+
memberCount: members.length + 1,
|
|
33165
|
+
memberChatPKs: [self2.chatPK, ...members.map((member) => member.chatPK)],
|
|
33166
|
+
memberUids: [self2.uid, ...members.map((member) => member.uid)]
|
|
33167
|
+
}
|
|
33168
|
+
};
|
|
33169
|
+
publish();
|
|
33170
|
+
}
|
|
33171
|
+
return materialize(launch.id, "", (id, context) => perform(id, {
|
|
33172
|
+
...context,
|
|
33173
|
+
...initialSendOptions({}, context)
|
|
33174
|
+
})).then((result) => result.value);
|
|
33175
|
+
};
|
|
32884
33176
|
const sendPendingMessage = (launchId, message, options = {}) => {
|
|
32885
33177
|
const { chatPK } = getIdentity();
|
|
32886
|
-
const launch =
|
|
32887
|
-
const previousOperation = pendingOperations.get(launchId);
|
|
33178
|
+
const launch = launchForChat(launchId);
|
|
33179
|
+
const previousOperation = pendingOperations.get(launchId)?.promise;
|
|
32888
33180
|
if (!launch || launch.id !== launchId)
|
|
32889
33181
|
throw makeChatUnavailableError();
|
|
32890
33182
|
const routeAnchor = launch.chat?.members?.find((member) => member.chatPK !== chatPK)?.chatPK || chatPK;
|
|
@@ -32903,8 +33195,8 @@ function createChatSessionPending({
|
|
|
32903
33195
|
};
|
|
32904
33196
|
const sendPendingAttachment = (launchId, attachment, options = {}) => {
|
|
32905
33197
|
const { chatPK } = getIdentity();
|
|
32906
|
-
const launch =
|
|
32907
|
-
const previousOperation = pendingOperations.get(launchId);
|
|
33198
|
+
const launch = launchForChat(launchId);
|
|
33199
|
+
const previousOperation = pendingOperations.get(launchId)?.promise;
|
|
32908
33200
|
if (!launch || launch.id !== launchId)
|
|
32909
33201
|
throw makeChatUnavailableError();
|
|
32910
33202
|
const routeAnchor = launch.chat?.members?.find((member) => member.chatPK !== chatPK)?.chatPK || chatPK;
|
|
@@ -32919,8 +33211,8 @@ function createChatSessionPending({
|
|
|
32919
33211
|
};
|
|
32920
33212
|
const sendPendingSharedAttachment = (launchId, attachment, options = {}) => {
|
|
32921
33213
|
const { chatPK } = getIdentity();
|
|
32922
|
-
const launch =
|
|
32923
|
-
const previousOperation = pendingOperations.get(launchId);
|
|
33214
|
+
const launch = launchForChat(launchId);
|
|
33215
|
+
const previousOperation = pendingOperations.get(launchId)?.promise;
|
|
32924
33216
|
if (!launch || launch.id !== launchId)
|
|
32925
33217
|
throw makeChatUnavailableError();
|
|
32926
33218
|
const routeAnchor = launch.chat?.members?.find((member) => member.chatPK !== chatPK)?.chatPK || chatPK;
|
|
@@ -32933,6 +33225,12 @@ function createChatSessionPending({
|
|
|
32933
33225
|
return track(launchId, previousOperation.then((result) => sendDurableSharedAttachment(result?.chatId || launchId, queuedAttachment, options)));
|
|
32934
33226
|
};
|
|
32935
33227
|
const sendChatMessage = (chatId, message, options = {}) => {
|
|
33228
|
+
const operation = operationForChat(chatId);
|
|
33229
|
+
if (operation?.discarding)
|
|
33230
|
+
throw makeChatUnavailableError();
|
|
33231
|
+
if (operation)
|
|
33232
|
+
return sendPendingMessage(operation.launch.id, message, options);
|
|
33233
|
+
chatId = resolvePendingChatId(chatId);
|
|
32936
33234
|
if (!getOwnerChat(chatId)) {
|
|
32937
33235
|
if (!pendingLaunch)
|
|
32938
33236
|
pendingLaunch = storedLaunch(chatId);
|
|
@@ -32943,9 +33241,10 @@ function createChatSessionPending({
|
|
|
32943
33241
|
return sendDurableMessage(chatId, message, options);
|
|
32944
33242
|
};
|
|
32945
33243
|
const retryMessage = (chatId, cid) => {
|
|
33244
|
+
chatId = resolvePendingChatId(chatId);
|
|
32946
33245
|
const attemptGeneration = generation;
|
|
32947
33246
|
const launch = pendingLaunch && (pendingLaunch.id === chatId || pendingLaunch.canonicalChatId === chatId) ? pendingLaunch : storedLaunch(chatId);
|
|
32948
|
-
const failed = getLocalByChat().get(
|
|
33247
|
+
const failed = getLocalByChat().get(chatId)?.find((message) => message.cid === cid && message.failed);
|
|
32949
33248
|
if (!failed)
|
|
32950
33249
|
return false;
|
|
32951
33250
|
if (launch && !getOwnerChat(chatId)) {
|
|
@@ -32982,8 +33281,24 @@ function createChatSessionPending({
|
|
|
32982
33281
|
getSendActions().discardLocalMessage(chatId, cid);
|
|
32983
33282
|
return true;
|
|
32984
33283
|
};
|
|
32985
|
-
const sendChatAttachment = (chatId, attachment, options = {}) =>
|
|
32986
|
-
|
|
33284
|
+
const sendChatAttachment = (chatId, attachment, options = {}) => {
|
|
33285
|
+
const operation = operationForChat(chatId);
|
|
33286
|
+
if (operation?.discarding)
|
|
33287
|
+
throw makeChatUnavailableError();
|
|
33288
|
+
if (operation)
|
|
33289
|
+
return sendPendingAttachment(operation.launch.id, attachment, options);
|
|
33290
|
+
chatId = resolvePendingChatId(chatId);
|
|
33291
|
+
return pendingLaunch?.id === chatId && !getOwnerChat(chatId) ? sendPendingAttachment(chatId, attachment, options) : sendDurableAttachment(chatId, attachment, options);
|
|
33292
|
+
};
|
|
33293
|
+
const sendChatSharedAttachment = (chatId, attachment, options = {}) => {
|
|
33294
|
+
const operation = operationForChat(chatId);
|
|
33295
|
+
if (operation?.discarding)
|
|
33296
|
+
throw makeChatUnavailableError();
|
|
33297
|
+
if (operation)
|
|
33298
|
+
return sendPendingSharedAttachment(operation.launch.id, attachment, options);
|
|
33299
|
+
chatId = resolvePendingChatId(chatId);
|
|
33300
|
+
return pendingLaunch?.id === chatId && !getOwnerChat(chatId) ? sendPendingSharedAttachment(chatId, attachment, options) : sendDurableSharedAttachment(chatId, attachment, options);
|
|
33301
|
+
};
|
|
32987
33302
|
const sendDirectAttachment = async (profile, attachment, options = {}) => sendChatAttachment(await getRouteOwner().openDirectChat(profile), attachment, options);
|
|
32988
33303
|
const sendMaterializedDirect = async (profile, payload, options, send) => {
|
|
32989
33304
|
const queuedPayload = { ...payload, cid: makeSendCid(payload) };
|
|
@@ -33030,6 +33345,10 @@ function createChatSessionPending({
|
|
|
33030
33345
|
return settleNormalizedTargets(normalizedTargets, (target) => sendPickerTarget(target, (chatId) => sendChatSharedAttachment(chatId, attachment), (profile) => sendPickerDirectSharedAttachment(profile, attachment)));
|
|
33031
33346
|
};
|
|
33032
33347
|
return {
|
|
33348
|
+
directAdmissionForPeer: admission.directAdmissionForPeer,
|
|
33349
|
+
dropChat,
|
|
33350
|
+
discardChat,
|
|
33351
|
+
canStartDirectChat: admission.canStartDirectChat,
|
|
33033
33352
|
adoptOpenedChatId,
|
|
33034
33353
|
adoptResolved,
|
|
33035
33354
|
beginPendingChat,
|
|
@@ -33037,8 +33356,11 @@ function createChatSessionPending({
|
|
|
33037
33356
|
canSendToChat,
|
|
33038
33357
|
isChatAdmitted,
|
|
33039
33358
|
isPendingLaunchAdmitted,
|
|
33040
|
-
isPendingChat: (chatId) =>
|
|
33359
|
+
isPendingChat: (chatId) => !!launchForChat(chatId),
|
|
33041
33360
|
getPendingLaunch,
|
|
33361
|
+
getActionChat: (chatId) => getOwnerChat(resolvePendingChatId(chatId)) || launchForChat(chatId)?.chat || null,
|
|
33362
|
+
hasPendingChatOperation: (chatId) => !!operationForChat(chatId),
|
|
33363
|
+
runChatMutation,
|
|
33042
33364
|
openNewChat,
|
|
33043
33365
|
retirePeer,
|
|
33044
33366
|
reconcileAdmission: () => {
|
|
@@ -33048,7 +33370,7 @@ function createChatSessionPending({
|
|
|
33048
33370
|
beginSelection();
|
|
33049
33371
|
getRouteOwner().clearOpenOperations?.();
|
|
33050
33372
|
pendingLaunch = null;
|
|
33051
|
-
|
|
33373
|
+
cancelOperation(launch.id);
|
|
33052
33374
|
if (getSelectedChatId() === launch.id || getSelectedChatId() === launch.canonicalChatId) {
|
|
33053
33375
|
setSelectedChat(null);
|
|
33054
33376
|
} else {
|
|
@@ -33058,10 +33380,13 @@ function createChatSessionPending({
|
|
|
33058
33380
|
},
|
|
33059
33381
|
reset: () => {
|
|
33060
33382
|
generation += 1;
|
|
33383
|
+
admission.reset();
|
|
33061
33384
|
beginSelection();
|
|
33062
33385
|
if (pendingLaunch?.id)
|
|
33063
33386
|
getRouteOwner().releaseOpenOperation?.(pendingLaunch.id);
|
|
33064
33387
|
pendingLaunch = null;
|
|
33388
|
+
for (const operation of pendingOperations.values())
|
|
33389
|
+
operation.active = false;
|
|
33065
33390
|
pendingOperations.clear();
|
|
33066
33391
|
},
|
|
33067
33392
|
selectChat: (chatId, { flushPrevious }) => {
|
|
@@ -33074,9 +33399,14 @@ function createChatSessionPending({
|
|
|
33074
33399
|
const selectResolved = () => {
|
|
33075
33400
|
if (!isSelectionCurrent(selection) || getIdentity().chatBanned)
|
|
33076
33401
|
return false;
|
|
33077
|
-
if (pendingLaunch && chatId !== pendingLaunch.id
|
|
33402
|
+
if (pendingLaunch && chatId !== pendingLaunch.id) {
|
|
33403
|
+
if (chatId === pendingLaunch.canonicalChatId) {
|
|
33404
|
+
settleMaterialization(pendingLaunch.id, chatId);
|
|
33405
|
+
}
|
|
33078
33406
|
getRouteOwner().releaseOpenOperation?.(pendingLaunch.id);
|
|
33079
33407
|
pendingLaunch = null;
|
|
33408
|
+
if (getSelectedChatId() === chatId)
|
|
33409
|
+
publish();
|
|
33080
33410
|
}
|
|
33081
33411
|
const previousChatId = getSelectedChatId();
|
|
33082
33412
|
if (previousChatId && previousChatId !== chatId)
|
|
@@ -33131,6 +33461,7 @@ var init_sessionpending = __esm(() => {
|
|
|
33131
33461
|
init_messages();
|
|
33132
33462
|
init_state();
|
|
33133
33463
|
init_targets();
|
|
33464
|
+
init_capabilities();
|
|
33134
33465
|
});
|
|
33135
33466
|
|
|
33136
33467
|
// ../../core/chat/sessionmembership.js
|
|
@@ -33625,7 +33956,6 @@ function createChatDelete({
|
|
|
33625
33956
|
for (const chatId of chatIds || []) {
|
|
33626
33957
|
if (!chatId)
|
|
33627
33958
|
continue;
|
|
33628
|
-
dropCachedChat(localCache, chatId);
|
|
33629
33959
|
closeMessageBatchRef.current?.(chatId);
|
|
33630
33960
|
if (localForRender.has(chatId)) {
|
|
33631
33961
|
if (!localChanged)
|
|
@@ -33657,6 +33987,7 @@ function createChatDelete({
|
|
|
33657
33987
|
keepSelectedDeletedChatIdsRef.current.delete(chatId);
|
|
33658
33988
|
}
|
|
33659
33989
|
}
|
|
33990
|
+
dropCachedChats(localCache, ids);
|
|
33660
33991
|
clearDeletedChatState(ids);
|
|
33661
33992
|
renderVisibleChats();
|
|
33662
33993
|
setSelectedChat((current) => current && ids.includes(current) && !options?.keepSelected ? null : current);
|
|
@@ -33714,9 +34045,7 @@ function createChatDelete({
|
|
|
33714
34045
|
const dropChat = (chatId) => {
|
|
33715
34046
|
if (!chatId)
|
|
33716
34047
|
return;
|
|
33717
|
-
clearDeletedChatState([chatId]);
|
|
33718
34048
|
listActionsRef.current?.removeOwner?.(chatId, { warm: false });
|
|
33719
|
-
setSelectedChat((current) => current === chatId ? null : current);
|
|
33720
34049
|
};
|
|
33721
34050
|
const dropLeftChat = (chatId) => {
|
|
33722
34051
|
if (!chatId)
|
|
@@ -35137,8 +35466,6 @@ async function setOwnChatNotificationMode(cloud, identity, entryId, entry, value
|
|
|
35137
35466
|
if (!current?.current || current.retirement)
|
|
35138
35467
|
throw makeChatUnavailableError();
|
|
35139
35468
|
const manifest = current.current.manifest;
|
|
35140
|
-
if (manifest.lineage !== "group")
|
|
35141
|
-
throw new Error("group chat required");
|
|
35142
35469
|
const requestedMode = cleanText(value);
|
|
35143
35470
|
const notificationMode = normalizeChatNotificationMode(requestedMode, manifest);
|
|
35144
35471
|
if (notificationMode !== requestedMode) {
|
|
@@ -35198,20 +35525,20 @@ function createChatSessionNotifications({
|
|
|
35198
35525
|
throw makeChatUnavailableError();
|
|
35199
35526
|
}
|
|
35200
35527
|
};
|
|
35201
|
-
const requireOwnerChat = (chatId, operation
|
|
35528
|
+
const requireOwnerChat = (chatId, operation) => {
|
|
35202
35529
|
assertCurrent(operation);
|
|
35203
35530
|
const chat = getOwnerChat(chatId);
|
|
35204
|
-
if (operation.identity.chatBanned || canWriteChat(chatId) !== true ||
|
|
35531
|
+
if (operation.identity.chatBanned || canWriteChat(chatId) !== true || !chat?.ownEntry || chat.ownEntry.retirement || !chat.entryId) {
|
|
35205
35532
|
throw makeChatUnavailableError();
|
|
35206
35533
|
}
|
|
35207
35534
|
return chat;
|
|
35208
35535
|
};
|
|
35209
35536
|
const setChatNotificationMode = async (chatId, mode) => {
|
|
35210
35537
|
const operation = operationContext();
|
|
35211
|
-
requireOwnerChat(chatId, operation
|
|
35538
|
+
requireOwnerChat(chatId, operation);
|
|
35212
35539
|
const releaseMutation = await operation.mutationGate.acquireExclusive(chatId);
|
|
35213
35540
|
try {
|
|
35214
|
-
const chat = requireOwnerChat(chatId, operation
|
|
35541
|
+
const chat = requireOwnerChat(chatId, operation);
|
|
35215
35542
|
const committed = await writeMode(cloud, operation.identity, chat.entryId, chat.ownEntry, mode);
|
|
35216
35543
|
assertCurrent(operation);
|
|
35217
35544
|
const projected = projectOwnChatEntry(committed, chat.entryId, operation.identity.chatPK, chat.ts);
|
|
@@ -35604,7 +35931,7 @@ function createChatSession({
|
|
|
35604
35931
|
const owner = getOwnerChat(chatId);
|
|
35605
35932
|
if (owner)
|
|
35606
35933
|
return !isChatMembershipRemoved(owner);
|
|
35607
|
-
return pendingOwner?.
|
|
35934
|
+
return pendingOwner?.isPendingChat(chatId) === true;
|
|
35608
35935
|
};
|
|
35609
35936
|
const requireOnline = () => {
|
|
35610
35937
|
if (!online)
|
|
@@ -35619,10 +35946,6 @@ function createChatSession({
|
|
|
35619
35946
|
if (chatId && !isMutableChat(chatId))
|
|
35620
35947
|
throw makeChatUnavailableError();
|
|
35621
35948
|
};
|
|
35622
|
-
const gateChatMutation = (fn) => (chatId, ...rest) => {
|
|
35623
|
-
requireMutableChat(chatId);
|
|
35624
|
-
return fn(chatId, ...rest);
|
|
35625
|
-
};
|
|
35626
35949
|
const gateAdmittedChatMutation = (fn) => (chatId, ...rest) => {
|
|
35627
35950
|
requireMutableChat(chatId);
|
|
35628
35951
|
return Promise.resolve(pendingOwner.assertChatAdmission(chatId)).then(() => fn(chatId, ...rest));
|
|
@@ -35824,7 +36147,8 @@ function createChatSession({
|
|
|
35824
36147
|
getPeerProfile,
|
|
35825
36148
|
resolvePeerProfile,
|
|
35826
36149
|
setLocalByChat,
|
|
35827
|
-
getLocalByChat: () => localByChatRef.current
|
|
36150
|
+
getLocalByChat: () => localByChatRef.current,
|
|
36151
|
+
retireMaterializedChat: (chatId) => actionOwner.deleteActions.beginRetirement(chatId)
|
|
35828
36152
|
});
|
|
35829
36153
|
launchOwner = createChatSessionLaunches({
|
|
35830
36154
|
cloud,
|
|
@@ -35864,29 +36188,79 @@ function createChatSession({
|
|
|
35864
36188
|
const openDirectChat = (...args) => launchOwner.openDirectChat(...args);
|
|
35865
36189
|
const openNotesChat = (...args) => launchOwner.openNotesChat(...args);
|
|
35866
36190
|
const openNewChat = (...args) => pendingOwner.openNewChat(...args);
|
|
35867
|
-
const
|
|
35868
|
-
const canStartDirectChat2 = (profile) => canStartDirectChat(chatPrivateKey, chatPK, profile, chatAdmission);
|
|
36191
|
+
const { directAdmissionForPeer: directAdmissionForPeer2, canStartDirectChat } = pendingOwner;
|
|
35869
36192
|
const canInviteToGroup2 = (profile) => canInviteToGroup(profile, chatAdmission);
|
|
35870
36193
|
const createGroupChat2 = (...args) => launchOwner.createGroupChat(...args);
|
|
35871
36194
|
const selectLocalChat = (...args) => launchOwner.selectLocalChat(...args);
|
|
35872
|
-
const
|
|
36195
|
+
const mutateMaterializedChat = (chatId, mutate, options) => {
|
|
35873
36196
|
requireMutableChat(chatId);
|
|
35874
|
-
|
|
35875
|
-
|
|
36197
|
+
return pendingOwner.runChatMutation(chatId, async (id, context) => {
|
|
36198
|
+
await pendingOwner.assertChatAdmission(id);
|
|
36199
|
+
return mutate(id, context);
|
|
36200
|
+
}, options);
|
|
35876
36201
|
};
|
|
35877
|
-
const
|
|
35878
|
-
|
|
35879
|
-
|
|
35880
|
-
return membershipOwner.
|
|
36202
|
+
const addChatMembers = (chatId, profiles2) => {
|
|
36203
|
+
const additions = Array.isArray(profiles2) ? profiles2 : [profiles2];
|
|
36204
|
+
additions.forEach(membershipOwner.profileMember);
|
|
36205
|
+
return mutateMaterializedChat(chatId, (id, context) => context.created ? { entry: getOwnerChat(id).ownEntry } : membershipOwner.addChatMembers(id, additions), {
|
|
36206
|
+
initialProfiles: (current) => {
|
|
36207
|
+
const next = new Map(current.map((profile) => [profile.chatPK, profile]));
|
|
36208
|
+
for (const profile of additions)
|
|
36209
|
+
next.set(profile.chatPK, profile);
|
|
36210
|
+
return next.size === current.length ? current : [...next.values()];
|
|
36211
|
+
}
|
|
36212
|
+
});
|
|
36213
|
+
};
|
|
36214
|
+
const kickChatMember = (chatId, memberChatPK) => {
|
|
36215
|
+
const target = cleanText(memberChatPK);
|
|
36216
|
+
if (!target)
|
|
36217
|
+
throw new Error("chat member required");
|
|
36218
|
+
if (target === chatPK && pendingOwner.isPendingChat(chatId)) {
|
|
36219
|
+
return deleteChat(chatId);
|
|
36220
|
+
}
|
|
36221
|
+
return mutateMaterializedChat(chatId, (id, context) => context.created ? { entry: getOwnerChat(id).ownEntry } : membershipOwner.kickChatMember(id, target), {
|
|
36222
|
+
initialProfiles: (current) => current.some((profile) => profile.chatPK === target) ? current.filter((profile) => profile.chatPK !== target) : current
|
|
36223
|
+
});
|
|
35881
36224
|
};
|
|
35882
36225
|
const leaveChat = (chatId) => {
|
|
36226
|
+
if (pendingOwner.isPendingChat(chatId)) {
|
|
36227
|
+
return deleteChat(chatId);
|
|
36228
|
+
}
|
|
35883
36229
|
requireMutableChat(chatId);
|
|
35884
36230
|
return membershipOwner.leaveChat(chatId);
|
|
35885
36231
|
};
|
|
35886
36232
|
const leaveOwnedChat = (...args) => membershipOwner.leaveOwnedChat(...args);
|
|
35887
|
-
const
|
|
35888
|
-
|
|
35889
|
-
|
|
36233
|
+
const sharedSettingsChat = (chatId) => {
|
|
36234
|
+
const chat = pendingOwner.getActionChat(chatId);
|
|
36235
|
+
if (chat?.lineage === "self")
|
|
36236
|
+
throw new Error("self chat identity follows your profile");
|
|
36237
|
+
return chat;
|
|
36238
|
+
};
|
|
36239
|
+
const updateChatSettings2 = async (chatId, settings) => {
|
|
36240
|
+
const chat = sharedSettingsChat(chatId);
|
|
36241
|
+
const requested = normalizeChatSettingsInput({ ...chat?.settings, ...settings });
|
|
36242
|
+
const changes = ["title", "avatarRef", "retention"].filter((key) => Object.prototype.hasOwnProperty.call(settings, key));
|
|
36243
|
+
const patch = Object.fromEntries(changes.map((key) => [key, requested[key]]));
|
|
36244
|
+
if (chat && !pendingOwner.hasPendingChatOperation(chatId) && changes.every((key) => chat.settings?.[key] === requested[key])) {
|
|
36245
|
+
return Promise.resolve({ unchanged: true });
|
|
36246
|
+
}
|
|
36247
|
+
return mutateMaterializedChat(chatId, (id) => settingsOwner.updateChatSettings(id, patch));
|
|
36248
|
+
};
|
|
36249
|
+
const updateChatAvatar = async (chatId, data) => {
|
|
36250
|
+
assertChatAvatarBytes(data);
|
|
36251
|
+
const chat = sharedSettingsChat(chatId);
|
|
36252
|
+
if (chat?.lineage !== "group")
|
|
36253
|
+
throw new Error("group chat required");
|
|
36254
|
+
return mutateMaterializedChat(chatId, (id) => settingsOwner.updateChatAvatar(id, data));
|
|
36255
|
+
};
|
|
36256
|
+
const setChatNotificationMode = async (chatId, mode) => {
|
|
36257
|
+
const chat = pendingOwner.getActionChat(chatId);
|
|
36258
|
+
if (chat && normalizeChatNotificationMode(mode, chat) !== mode)
|
|
36259
|
+
throw new Error("all notifications are unavailable in large groups");
|
|
36260
|
+
if (chat && !pendingOwner.hasPendingChatOperation(chatId) && (chat.notificationMode || defaultChatNotificationMode(chat)) === mode)
|
|
36261
|
+
return mode;
|
|
36262
|
+
return mutateMaterializedChat(chatId, (id) => notificationsOwner.setChatNotificationMode(id, mode));
|
|
36263
|
+
};
|
|
35890
36264
|
const updateMessage = async (chatId, original, changes) => {
|
|
35891
36265
|
if (chatBanned)
|
|
35892
36266
|
throw makeChatUnavailableError();
|
|
@@ -36040,7 +36414,27 @@ function createChatSession({
|
|
|
36040
36414
|
};
|
|
36041
36415
|
const dropChat = (...args) => actionOwner.deleteActions.dropChat(...args);
|
|
36042
36416
|
const dropUnavailableChat = (...args) => actionOwner.deleteActions.dropUnavailableChat(...args);
|
|
36043
|
-
const deleteChat =
|
|
36417
|
+
const deleteChat = async (value, options) => {
|
|
36418
|
+
const inputs = Array.isArray(value) ? value : [value];
|
|
36419
|
+
const durable = [];
|
|
36420
|
+
let discarded = 0;
|
|
36421
|
+
for (const input of inputs) {
|
|
36422
|
+
const id = cleanText(typeof input === "string" ? input : input?.chatId || input?.id);
|
|
36423
|
+
if (pendingOwner.hasPendingChatOperation(id) || !getOwnerChat(id) && pendingOwner.isPendingChat(id)) {
|
|
36424
|
+
const result = await pendingOwner.discardChat(id);
|
|
36425
|
+
if (result.chat)
|
|
36426
|
+
durable.push(result.chat);
|
|
36427
|
+
else if (result.discarded)
|
|
36428
|
+
discarded += 1;
|
|
36429
|
+
} else
|
|
36430
|
+
durable.push(input);
|
|
36431
|
+
}
|
|
36432
|
+
if (!durable.length)
|
|
36433
|
+
return Array.isArray(value) ? discarded : discarded > 0;
|
|
36434
|
+
requireOnline();
|
|
36435
|
+
const deleted = await actionOwner.deleteActions.deleteChat(Array.isArray(value) ? durable : durable[0], options);
|
|
36436
|
+
return Array.isArray(value) ? discarded + Number(deleted) : deleted;
|
|
36437
|
+
};
|
|
36044
36438
|
const purgePeerChats = async (affected, operation) => {
|
|
36045
36439
|
const identity = operation.identity;
|
|
36046
36440
|
for (const chat of affected) {
|
|
@@ -36055,6 +36449,8 @@ function createChatSession({
|
|
|
36055
36449
|
await leaveOwnedChat(chat, { optimistic: false });
|
|
36056
36450
|
assertBulkOperationCurrent(operation);
|
|
36057
36451
|
await cloud.user.chats.unlink(identity.uid, chat.entryId);
|
|
36452
|
+
assertBulkOperationCurrent(operation);
|
|
36453
|
+
operation.deleteActions.commitRetirement(chat.id);
|
|
36058
36454
|
} else {
|
|
36059
36455
|
await operation.deleteActions.deleteChat(chat, { cleanup: false });
|
|
36060
36456
|
}
|
|
@@ -36069,14 +36465,30 @@ function createChatSession({
|
|
|
36069
36465
|
const { uid: operationUid, chatPK: operationChatPK, chatPrivateKey: operationChatPrivateKey } = operation.identity;
|
|
36070
36466
|
if (!operationUid || !operationChatPK || !operationChatPrivateKey)
|
|
36071
36467
|
return retiredPending;
|
|
36072
|
-
const
|
|
36073
|
-
|
|
36074
|
-
|
|
36075
|
-
|
|
36076
|
-
|
|
36077
|
-
|
|
36078
|
-
|
|
36079
|
-
|
|
36468
|
+
const visible = chatsRef.current.filter((chat) => chat?.members?.some((member) => member.chatPK === peerChatPK) && !operation.deleteActions.isChatPendingDelete(chat.id));
|
|
36469
|
+
for (const chat of visible)
|
|
36470
|
+
operation.deleteActions.beginRetirement(chat.id);
|
|
36471
|
+
try {
|
|
36472
|
+
const allChats = await loadOwnerChats(cloud, operationUid, operationChatPK, operationChatPrivateKey);
|
|
36473
|
+
assertBulkOperationCurrent(operation);
|
|
36474
|
+
const affected = allChats.filter((chat) => chat?.members?.some((member) => member.chatPK === peerChatPK));
|
|
36475
|
+
await purgePeerChats(affected, operation);
|
|
36476
|
+
assertBulkOperationCurrent(operation);
|
|
36477
|
+
for (const chat of visible)
|
|
36478
|
+
operation.deleteActions.commitRetirement(chat.id);
|
|
36479
|
+
await options.onDeliveryRevoked?.();
|
|
36480
|
+
assertBulkOperationCurrent(operation);
|
|
36481
|
+
return retiredPending || affected.length > 0;
|
|
36482
|
+
} catch (error) {
|
|
36483
|
+
if (isBulkOperationCurrent(operation)) {
|
|
36484
|
+
for (const chat of visible) {
|
|
36485
|
+
if (operation.deleteActions.isChatPendingDelete(chat.id)) {
|
|
36486
|
+
operation.deleteActions.rollbackRetirement(chat.id);
|
|
36487
|
+
}
|
|
36488
|
+
}
|
|
36489
|
+
}
|
|
36490
|
+
throw error;
|
|
36491
|
+
}
|
|
36080
36492
|
};
|
|
36081
36493
|
const retireBlockedChats = async (blockedUids) => {
|
|
36082
36494
|
const operation = bulkOperation(blockedUids);
|
|
@@ -36145,14 +36557,14 @@ function createChatSession({
|
|
|
36145
36557
|
const sendPendingChatMessage = (...args) => pendingOwner.sendPendingChatMessage(...args);
|
|
36146
36558
|
const sendChatMessage = sendMessage;
|
|
36147
36559
|
const sendDirectAttachment = gateOnlineMutation((...args) => pendingOwner.sendDirectAttachment(...args));
|
|
36148
|
-
const sendChatAttachment =
|
|
36560
|
+
const sendChatAttachment = gateOnlineMutation((...args) => pendingOwner.sendChatAttachment(...args));
|
|
36149
36561
|
const retryMessage = async (...args) => {
|
|
36150
36562
|
const result = await pendingOwner.retryMessage(...args);
|
|
36151
36563
|
if (online)
|
|
36152
36564
|
drainMembershipOutbox();
|
|
36153
36565
|
return result;
|
|
36154
36566
|
};
|
|
36155
|
-
const sendAttachment =
|
|
36567
|
+
const sendAttachment = gateOnlineMutation((...args) => pendingOwner.sendChatAttachment(...args));
|
|
36156
36568
|
const sendChatImage = (chatId, image, options = {}) => sendChatAttachment(chatId, { ...image, type: image?.type || "img" }, options);
|
|
36157
36569
|
const sendAttachmentMany = gateOnlineMutation((...args) => pendingOwner.sendAttachmentMany(...args));
|
|
36158
36570
|
const sendImageMany = (targets, image, options = {}) => sendAttachmentMany(targets, { ...image, type: image?.type || "img" }, options);
|
|
@@ -36210,7 +36622,11 @@ function createChatSession({
|
|
|
36210
36622
|
});
|
|
36211
36623
|
return state;
|
|
36212
36624
|
};
|
|
36213
|
-
const setChatTtl =
|
|
36625
|
+
const setChatTtl = async (chatId, retention) => {
|
|
36626
|
+
const next = cleanChatRetention(retention);
|
|
36627
|
+
await updateChatSettings2(chatId, { retention: next });
|
|
36628
|
+
return next;
|
|
36629
|
+
};
|
|
36214
36630
|
const makeMessagePermanent = gateAdmittedChatMutation((...args) => actionOwner.saveActions.makeMessagePermanent(...args));
|
|
36215
36631
|
const makeMessageTemporary = gateAdmittedChatMutation((...args) => actionOwner.saveActions.makeMessageTemporary(...args));
|
|
36216
36632
|
const readMessageFile = (...args) => actionOwner.saveActions.readMessageFile(...args);
|
|
@@ -36313,6 +36729,17 @@ function createChatSession({
|
|
|
36313
36729
|
chatsRef,
|
|
36314
36730
|
reconcileMessageBatches: (...args) => messageBatchOwner.reconcileChats(...args),
|
|
36315
36731
|
warmChats: (...args) => messageBatchOwner.warm(...args),
|
|
36732
|
+
onOwnerRemoved: (chatIds) => {
|
|
36733
|
+
for (const chatId of chatIds)
|
|
36734
|
+
pendingOwner.dropChat(chatId);
|
|
36735
|
+
actionOwner.deleteActions.clearDeletedChatState(chatIds);
|
|
36736
|
+
for (const chatId of chatIds) {
|
|
36737
|
+
actionOwner.liveActions.closeChatActivity(chatId);
|
|
36738
|
+
historyOwner.clear(chatId);
|
|
36739
|
+
messageBatchOwner.routeMemory.dropChat(chatId);
|
|
36740
|
+
routeMemoryScopes.delete(chatId);
|
|
36741
|
+
}
|
|
36742
|
+
},
|
|
36316
36743
|
onTransition: stageCommittedMembershipMessage,
|
|
36317
36744
|
onRemoved: (removedChatId, _epochVersion, retiredEntry) => {
|
|
36318
36745
|
const applied = chatListOwner.applyMembershipRemoval(removedChatId, retiredEntry);
|
|
@@ -36369,7 +36796,7 @@ function createChatSession({
|
|
|
36369
36796
|
openNotesChat,
|
|
36370
36797
|
openNewChat,
|
|
36371
36798
|
directAdmissionForPeer: directAdmissionForPeer2,
|
|
36372
|
-
canStartDirectChat
|
|
36799
|
+
canStartDirectChat,
|
|
36373
36800
|
canInviteToGroup: canInviteToGroup2,
|
|
36374
36801
|
createGroupChat: createGroupChat2,
|
|
36375
36802
|
addChatMembers,
|
|
@@ -36663,6 +37090,10 @@ var init_session3 = __esm(() => {
|
|
|
36663
37090
|
init_sessionsources();
|
|
36664
37091
|
init_entry();
|
|
36665
37092
|
init_admission();
|
|
37093
|
+
init_avatar2();
|
|
37094
|
+
init_settings2();
|
|
37095
|
+
init_ttl();
|
|
37096
|
+
init_notifications();
|
|
36666
37097
|
init_write();
|
|
36667
37098
|
DEFAULT_READ_WRITE_INTERVAL_MS = CHAT_READ_WRITE_INTERVAL_MS;
|
|
36668
37099
|
EMPTY_LOCAL_MESSAGES = Object.freeze([]);
|
|
@@ -36845,7 +37276,7 @@ function createPresence({ cloud, diag = null, now = Date.now } = {}) {
|
|
|
36845
37276
|
let expiryTimer = null;
|
|
36846
37277
|
let command = null;
|
|
36847
37278
|
let authenticating = null;
|
|
36848
|
-
let snapshot = Object.freeze({ visibility: null, ready: false, pending: false, error: null, ...UNKNOWN_PRESENCE });
|
|
37279
|
+
let snapshot = Object.freeze({ visibility: null, ready: false, pending: false, pendingVisibility: null, error: null, ...UNKNOWN_PRESENCE });
|
|
36849
37280
|
function topic() {
|
|
36850
37281
|
return sources.uid ? derivePresenceTopic(realm2, sources.uid) : null;
|
|
36851
37282
|
}
|
|
@@ -36853,7 +37284,13 @@ function createPresence({ cloud, diag = null, now = Date.now } = {}) {
|
|
|
36853
37284
|
return Boolean(channel && challenge && policy && sources.enabled && !closed);
|
|
36854
37285
|
}
|
|
36855
37286
|
function publish(patch = {}) {
|
|
36856
|
-
const next = {
|
|
37287
|
+
const next = {
|
|
37288
|
+
...snapshot,
|
|
37289
|
+
...patch,
|
|
37290
|
+
ready: isReady(),
|
|
37291
|
+
pending: Boolean(command),
|
|
37292
|
+
pendingVisibility: command?.policy.visibility ?? null
|
|
37293
|
+
};
|
|
36857
37294
|
if (Object.keys(next).every((key) => Object.is(next[key], snapshot[key])))
|
|
36858
37295
|
return;
|
|
36859
37296
|
snapshot = Object.freeze(next);
|
|
@@ -36909,7 +37346,7 @@ function createPresence({ cloud, diag = null, now = Date.now } = {}) {
|
|
|
36909
37346
|
const pending = command;
|
|
36910
37347
|
command = null;
|
|
36911
37348
|
clearTimeout(pending.timer);
|
|
36912
|
-
publish({
|
|
37349
|
+
publish({ error });
|
|
36913
37350
|
if (error)
|
|
36914
37351
|
pending.reject(error);
|
|
36915
37352
|
else
|
|
@@ -37149,12 +37586,14 @@ function createPresence({ cloud, diag = null, now = Date.now } = {}) {
|
|
|
37149
37586
|
listener();
|
|
37150
37587
|
}
|
|
37151
37588
|
function update(next) {
|
|
37152
|
-
const
|
|
37589
|
+
const accountChanged = sources.uid !== next.uid;
|
|
37590
|
+
const identityChanged = accountChanged || sources.identity?.publicKey !== next.identity?.publicKey;
|
|
37153
37591
|
if (identityChanged) {
|
|
37154
37592
|
stop();
|
|
37155
37593
|
policy = null;
|
|
37156
37594
|
records.clear();
|
|
37157
|
-
|
|
37595
|
+
if (accountChanged)
|
|
37596
|
+
peers.clear();
|
|
37158
37597
|
publish({ visibility: null, error: null, ...UNKNOWN_PRESENCE });
|
|
37159
37598
|
}
|
|
37160
37599
|
sources = next;
|
|
@@ -37184,7 +37623,7 @@ function createPresence({ cloud, diag = null, now = Date.now } = {}) {
|
|
|
37184
37623
|
reject,
|
|
37185
37624
|
timer: setTimeout(() => finishCommand(new Error("could not confirm activity setting; reconnect to check")), COMMAND_TIMEOUT_MS)
|
|
37186
37625
|
};
|
|
37187
|
-
publish({
|
|
37626
|
+
publish({ error: null });
|
|
37188
37627
|
if (!channel.send(presenceShard(topic()), { type: "policy", expectedRevision: policy.revision, policy: nextPolicy })) {
|
|
37189
37628
|
finishCommand(new Error("could not update activity while offline"));
|
|
37190
37629
|
}
|
|
@@ -40970,6 +41409,7 @@ function createPeerList({ peerApi, presence, diag, onMissingPeers }) {
|
|
|
40970
41409
|
let profilesLoading = false;
|
|
40971
41410
|
let hydratedCacheKey = "";
|
|
40972
41411
|
let avatarHydrateKey = "";
|
|
41412
|
+
let avatarPublishSession = null;
|
|
40973
41413
|
let profilesReady = false;
|
|
40974
41414
|
let blockedPeersReady = false;
|
|
40975
41415
|
let discoveredPeerUids = new Set;
|
|
@@ -41380,12 +41820,21 @@ function createPeerList({ peerApi, presence, diag, onMissingPeers }) {
|
|
|
41380
41820
|
const session = lifecycle;
|
|
41381
41821
|
const startedAt = Date.now();
|
|
41382
41822
|
const requested = walletPKs.length + chatPeerPKs.length;
|
|
41383
|
-
hydrateCachedAvatars(walletPKs, chatPeerPKs
|
|
41823
|
+
hydrateCachedAvatars(walletPKs, chatPeerPKs, () => {
|
|
41824
|
+
if (!isCurrent(session) || avatarPublishSession === session)
|
|
41825
|
+
return;
|
|
41826
|
+
avatarPublishSession = session;
|
|
41827
|
+
queueMicrotask(() => {
|
|
41828
|
+
if (avatarPublishSession !== session)
|
|
41829
|
+
return;
|
|
41830
|
+
avatarPublishSession = null;
|
|
41831
|
+
if (isCurrent(session))
|
|
41832
|
+
rebuild({ base: true, persist: false });
|
|
41833
|
+
});
|
|
41834
|
+
}).then((changed) => {
|
|
41384
41835
|
if (!isCurrent(session))
|
|
41385
41836
|
return;
|
|
41386
41837
|
markDiag(diag, "peers.avatars.hydrate", { requested, changed, elapsedMs: Date.now() - startedAt });
|
|
41387
|
-
if (changed)
|
|
41388
|
-
rebuild({ base: true });
|
|
41389
41838
|
}).catch((error) => {
|
|
41390
41839
|
if (!isCurrent(session))
|
|
41391
41840
|
return;
|
|
@@ -41989,7 +42438,7 @@ function createPeersApi({ cloud, network, avatarCache = null }) {
|
|
|
41989
42438
|
function uniqueLookupKeys(keys) {
|
|
41990
42439
|
return uniqueValues(keys);
|
|
41991
42440
|
}
|
|
41992
|
-
async function hydrateCachedAvatars(walletPKs, chatPKs) {
|
|
42441
|
+
async function hydrateCachedAvatars(walletPKs, chatPKs, onHydrated) {
|
|
41993
42442
|
if (typeof avatarCache?.read !== "function")
|
|
41994
42443
|
return false;
|
|
41995
42444
|
const profiles2 = new Map;
|
|
@@ -42008,21 +42457,18 @@ function createPeersApi({ cloud, network, avatarCache = null }) {
|
|
|
42008
42457
|
queue(key, "chat");
|
|
42009
42458
|
if (!profiles2.size)
|
|
42010
42459
|
return false;
|
|
42011
|
-
const cached = await Promise.all(Array.from(profiles2.values()).map(async ({ uid, version }) => ({
|
|
42012
|
-
avatar: await readCachedAvatar(uid, version),
|
|
42013
|
-
uid,
|
|
42014
|
-
version
|
|
42015
|
-
})));
|
|
42016
42460
|
let changed = false;
|
|
42017
|
-
|
|
42018
|
-
|
|
42019
|
-
|
|
42020
|
-
|
|
42021
|
-
|
|
42022
|
-
|
|
42023
|
-
|
|
42461
|
+
await Promise.all(Array.from(profiles2.values()).map(async ({ uid, version }) => {
|
|
42462
|
+
const avatar = await readCachedAvatar(uid, version);
|
|
42463
|
+
if (!avatar)
|
|
42464
|
+
return;
|
|
42465
|
+
const current = profileCache.get(uid);
|
|
42466
|
+
if (!current || current.avatarVersion !== version || current.avatar === avatar)
|
|
42467
|
+
return;
|
|
42468
|
+
storeProfile({ ...current, avatar });
|
|
42024
42469
|
changed = true;
|
|
42025
|
-
|
|
42470
|
+
onHydrated?.();
|
|
42471
|
+
}));
|
|
42026
42472
|
return changed;
|
|
42027
42473
|
}
|
|
42028
42474
|
function needsAvatarResolve(profile) {
|
|
@@ -44692,6 +45138,7 @@ function createPayment({
|
|
|
44692
45138
|
throw new Error("bitcoin payment must be reviewed before sending");
|
|
44693
45139
|
}
|
|
44694
45140
|
const payment = paymentInput?.state === PAYMENT_STATE_PREPARED ? normalizePreparedPayment(paymentInput, wallet, network) : await preparePayment(paymentInput);
|
|
45141
|
+
assertReady();
|
|
44695
45142
|
const startedAt = Date.now();
|
|
44696
45143
|
const diagKind = payment.kind;
|
|
44697
45144
|
markDiag(diag, "wallet.payment.start", { kind: diagKind });
|
|
@@ -53576,20 +54023,7 @@ function sameMessageList(a, b) {
|
|
|
53576
54023
|
for (let i = 0;i < a.length; i += 1) {
|
|
53577
54024
|
const left = a[i];
|
|
53578
54025
|
const right = b[i];
|
|
53579
|
-
if (getMessageKey(left) !== getMessageKey(right) || getMessageOrderMs(left) !== getMessageOrderMs(right) || hasMessageTtl(left) !== hasMessageTtl(right) || timestampKey(left?.ttl ?? null) !== timestampKey(right?.ttl ?? null) || !
|
|
53580
|
-
return false;
|
|
53581
|
-
}
|
|
53582
|
-
}
|
|
53583
|
-
return true;
|
|
53584
|
-
}
|
|
53585
|
-
function sameMessageReactions(a, b) {
|
|
53586
|
-
const left = getMsgReactions(a);
|
|
53587
|
-
const right = getMsgReactions(b);
|
|
53588
|
-
if (left.length !== right.length) {
|
|
53589
|
-
return false;
|
|
53590
|
-
}
|
|
53591
|
-
for (let index2 = 0;index2 < left.length; index2 += 1) {
|
|
53592
|
-
if (left[index2].user !== right[index2]?.user || left[index2].emoji !== right[index2]?.emoji) {
|
|
54026
|
+
if (getMessageKey(left) !== getMessageKey(right) || getMessageOrderMs(left) !== getMessageOrderMs(right) || hasMessageTtl(left) !== hasMessageTtl(right) || timestampKey(left?.ttl ?? null) !== timestampKey(right?.ttl ?? null) || !sameReactions(left?.reactions, right?.reactions)) {
|
|
53593
54027
|
return false;
|
|
53594
54028
|
}
|
|
53595
54029
|
}
|
|
@@ -54008,7 +54442,7 @@ function cacheMessageSignature(message) {
|
|
|
54008
54442
|
if (!message)
|
|
54009
54443
|
return "";
|
|
54010
54444
|
const hasTtl = hasMessageTtl(message);
|
|
54011
|
-
const reactions = getMsgReactions(message).map((reaction) => `${reaction.user}:${reaction.emoji}`).join(",");
|
|
54445
|
+
const reactions = getMsgReactions(message).map((reaction) => `${reaction.user}:${reaction.emoji}:${reaction.ts ?? ""}`).join(",");
|
|
54012
54446
|
return [
|
|
54013
54447
|
cacheKeySignature(messageKeys(message)),
|
|
54014
54448
|
getMessageOrderMs(message) || 0,
|
|
@@ -60624,7 +61058,7 @@ var package_default;
|
|
|
60624
61058
|
var init_package2 = __esm(() => {
|
|
60625
61059
|
package_default = {
|
|
60626
61060
|
name: "veyl",
|
|
60627
|
-
version: "0.
|
|
61061
|
+
version: "0.71.1",
|
|
60628
61062
|
packageManager: "bun@1.4.0",
|
|
60629
61063
|
private: true,
|
|
60630
61064
|
license: "UNLICENSED",
|
|
@@ -79009,7 +79443,7 @@ function ensureBytes(title, hex3, expectedLength) {
|
|
|
79009
79443
|
throw new Error(title + " of length " + expectedLength + " expected, got " + len);
|
|
79010
79444
|
return res;
|
|
79011
79445
|
}
|
|
79012
|
-
function
|
|
79446
|
+
function equalBytes3(a, b) {
|
|
79013
79447
|
if (a.length !== b.length)
|
|
79014
79448
|
return false;
|
|
79015
79449
|
let diff = 0;
|
|
@@ -109820,7 +110254,7 @@ var init_legacy = __esm(() => {
|
|
|
109820
110254
|
});
|
|
109821
110255
|
|
|
109822
110256
|
// ../../node_modules/.bun/micro-packed@0.7.3/node_modules/micro-packed/lib/esm/index.js
|
|
109823
|
-
function
|
|
110257
|
+
function equalBytes4(a, b) {
|
|
109824
110258
|
if (a.length !== b.length)
|
|
109825
110259
|
return false;
|
|
109826
110260
|
for (let i = 0;i < a.length; i++)
|
|
@@ -109995,7 +110429,7 @@ class _Reader {
|
|
|
109995
110429
|
const leftBytes = this.data.length - idx;
|
|
109996
110430
|
if (leftBytes < needle.length)
|
|
109997
110431
|
return;
|
|
109998
|
-
if (
|
|
110432
|
+
if (equalBytes4(needle, this.data.subarray(idx, idx + needle.length)))
|
|
109999
110433
|
return idx;
|
|
110000
110434
|
}
|
|
110001
110435
|
return;
|
|
@@ -110347,7 +110781,7 @@ function magic(inner, constant, check = true) {
|
|
|
110347
110781
|
encodeStream: (w, _value) => inner.encodeStream(w, constant),
|
|
110348
110782
|
decodeStream: (r) => {
|
|
110349
110783
|
const value = inner.decodeStream(r);
|
|
110350
|
-
if (check && typeof value !== "object" && value !== constant || isBytes6(constant) && !
|
|
110784
|
+
if (check && typeof value !== "object" && value !== constant || isBytes6(constant) && !equalBytes4(constant, value)) {
|
|
110351
110785
|
throw r.err(`magic: invalid value: ${value} !== ${constant}`);
|
|
110352
110786
|
}
|
|
110353
110787
|
return;
|
|
@@ -110454,7 +110888,7 @@ function array(len, inner) {
|
|
|
110454
110888
|
if (len.length > _w.pos - startPos)
|
|
110455
110889
|
return;
|
|
110456
110890
|
const data = _w.finish(false).subarray(startPos, _w.pos);
|
|
110457
|
-
if (
|
|
110891
|
+
if (equalBytes4(data.subarray(0, len.length), len))
|
|
110458
110892
|
throw _w.err(`array: inner element encoding same as separator. elm=${elm} data=${data}`);
|
|
110459
110893
|
}
|
|
110460
110894
|
});
|
|
@@ -110474,7 +110908,7 @@ function array(len, inner) {
|
|
|
110474
110908
|
}
|
|
110475
110909
|
} else if (isBytes6(len)) {
|
|
110476
110910
|
for (let i = 0;; i++) {
|
|
110477
|
-
if (
|
|
110911
|
+
if (equalBytes4(r.bytes(len.length, true), len)) {
|
|
110478
110912
|
r.bytes(len.length);
|
|
110479
110913
|
break;
|
|
110480
110914
|
}
|
|
@@ -110687,7 +111121,7 @@ var EMPTY2, NULL, createView4 = (arr) => new DataView(arr.buffer, arr.byteOffset
|
|
|
110687
111121
|
decodeStream: (r) => {
|
|
110688
111122
|
let hasFlag = r.leftBytes >= flagValue.length;
|
|
110689
111123
|
if (hasFlag) {
|
|
110690
|
-
hasFlag =
|
|
111124
|
+
hasFlag = equalBytes4(r.bytes(flagValue.length, true), flagValue);
|
|
110691
111125
|
if (hasFlag)
|
|
110692
111126
|
r.bytes(flagValue.length);
|
|
110693
111127
|
}
|
|
@@ -110705,7 +111139,7 @@ var init_esm2 = __esm(() => {
|
|
|
110705
111139
|
EMPTY2 = /* @__PURE__ */ new Uint8Array;
|
|
110706
111140
|
NULL = /* @__PURE__ */ new Uint8Array([0]);
|
|
110707
111141
|
utils2 = {
|
|
110708
|
-
equalBytes:
|
|
111142
|
+
equalBytes: equalBytes4,
|
|
110709
111143
|
isBytes: isBytes6,
|
|
110710
111144
|
isCoder,
|
|
110711
111145
|
checkBounds,
|
|
@@ -110947,7 +111381,7 @@ function compareBytes(a, b) {
|
|
|
110947
111381
|
return Math.sign(a[i] - b[i]);
|
|
110948
111382
|
return Math.sign(a.length - b.length);
|
|
110949
111383
|
}
|
|
110950
|
-
var Point, CURVE_ORDER, isBytes7, concatBytes7,
|
|
111384
|
+
var Point, CURVE_ORDER, isBytes7, concatBytes7, equalBytes5, hash160 = (msg) => ripemd160(sha2562(msg)), sha256x2 = (...msgs) => sha2562(sha2562(concatBytes7(...msgs))), randomPrivateKeyBytes, pubSchnorr, pubECDSA, hasLowR = (sig) => sig.r < CURVE_ORDER / 2n, signSchnorr, tagSchnorr, PubT, TAPROOT_UNSPENDABLE_KEY, NETWORK, TEST_NETWORK;
|
|
110951
111385
|
var init_utils6 = __esm(() => {
|
|
110952
111386
|
init_secp256k1();
|
|
110953
111387
|
init_legacy();
|
|
@@ -110957,7 +111391,7 @@ var init_utils6 = __esm(() => {
|
|
|
110957
111391
|
CURVE_ORDER = secp256k1.CURVE.n;
|
|
110958
111392
|
isBytes7 = utils2.isBytes;
|
|
110959
111393
|
concatBytes7 = utils2.concatBytes;
|
|
110960
|
-
|
|
111394
|
+
equalBytes5 = utils2.equalBytes;
|
|
110961
111395
|
randomPrivateKeyBytes = schnorr.utils.randomPrivateKey;
|
|
110962
111396
|
pubSchnorr = schnorr.getPublicKey;
|
|
110963
111397
|
pubECDSA = secp256k1.getPublicKey;
|
|
@@ -111476,7 +111910,7 @@ function mergeKeyMap(psbtEnum, val, cur, allowedFields, allowUnknown) {
|
|
|
111476
111910
|
} else if (typeof res[k] === "string") {
|
|
111477
111911
|
res[k] = vC.decode(hex3.decode(res[k]));
|
|
111478
111912
|
} else if (cannotChange && k in val && cur && cur[k] !== undefined) {
|
|
111479
|
-
if (!
|
|
111913
|
+
if (!equalBytes5(vC.encode(val[k]), vC.encode(cur[k])))
|
|
111480
111914
|
throw new Error(`Cannot change signed field=${k}`);
|
|
111481
111915
|
}
|
|
111482
111916
|
}
|
|
@@ -111675,7 +112109,7 @@ function isValidPubkey(pub, type) {
|
|
|
111675
112109
|
}
|
|
111676
112110
|
}
|
|
111677
112111
|
function checkWSH(s, witnessScript) {
|
|
111678
|
-
if (!
|
|
112112
|
+
if (!equalBytes5(s.hash, sha2562(witnessScript)))
|
|
111679
112113
|
throw new Error("checkScript: wsh wrong witnessScript hash");
|
|
111680
112114
|
const w = OutScript.decode(witnessScript);
|
|
111681
112115
|
if (w.type === "tr" || w.type === "tr_ns" || w.type === "tr_ms")
|
|
@@ -111689,7 +112123,7 @@ function checkScript(script, redeemScript, witnessScript) {
|
|
|
111689
112123
|
if (s.type === "tr_ns" || s.type === "tr_ms" || s.type === "ms" || s.type == "pk")
|
|
111690
112124
|
throw new Error(`checkScript: non-wrapped ${s.type}`);
|
|
111691
112125
|
if (s.type === "sh" && redeemScript) {
|
|
111692
|
-
if (!
|
|
112126
|
+
if (!equalBytes5(s.hash, hash160(redeemScript)))
|
|
111693
112127
|
throw new Error("checkScript: sh wrong redeemScript hash");
|
|
111694
112128
|
const r = OutScript.decode(redeemScript);
|
|
111695
112129
|
if (r.type === "tr" || r.type === "tr_ns" || r.type === "tr_ms")
|
|
@@ -111726,9 +112160,9 @@ function checkTaprootScript(script, internalPubKey, allowUnknownOutputs = false,
|
|
|
111726
112160
|
const outms = out;
|
|
111727
112161
|
if (!allowUnknownOutputs && outms.pubkeys) {
|
|
111728
112162
|
for (const p of outms.pubkeys) {
|
|
111729
|
-
if (
|
|
112163
|
+
if (equalBytes5(p, TAPROOT_UNSPENDABLE_KEY))
|
|
111730
112164
|
throw new Error("Unspendable taproot key in leaf script");
|
|
111731
|
-
if (
|
|
112165
|
+
if (equalBytes5(p, internalPubKey)) {
|
|
111732
112166
|
throw new Error("Using P2TR with leaf script with same key as internal key is not supported");
|
|
111733
112167
|
}
|
|
111734
112168
|
}
|
|
@@ -111779,7 +112213,7 @@ function taprootHashTree(tree, internalPubKey, allowUnknownOutputs = false, cust
|
|
|
111779
112213
|
tree = tree[0];
|
|
111780
112214
|
if (!Array.isArray(tree)) {
|
|
111781
112215
|
const { leafVersion: version, script: leafScript } = tree;
|
|
111782
|
-
if (tree.tapLeafScript || tree.tapMerkleRoot && !
|
|
112216
|
+
if (tree.tapLeafScript || tree.tapMerkleRoot && !equalBytes5(tree.tapMerkleRoot, EMPTY2))
|
|
111783
112217
|
throw new Error("P2TR: tapRoot leafScript cannot have tree");
|
|
111784
112218
|
const script = typeof leafScript === "string" ? hex3.decode(leafScript) : leafScript;
|
|
111785
112219
|
if (!isBytes7(script))
|
|
@@ -112158,7 +112592,7 @@ function cloneDeep(obj) {
|
|
|
112158
112592
|
throw new Error(`cloneDeep: unknown type=${obj} (${typeof obj})`);
|
|
112159
112593
|
}
|
|
112160
112594
|
function getTaprootKeys(privKey, pubKey, internalKey, merkleRoot = EMPTY2) {
|
|
112161
|
-
if (
|
|
112595
|
+
if (equalBytes5(internalKey, pubKey)) {
|
|
112162
112596
|
privKey = taprootTweakPrivKey(privKey, merkleRoot);
|
|
112163
112597
|
pubKey = pubSchnorr(privKey);
|
|
112164
112598
|
}
|
|
@@ -112254,7 +112688,7 @@ function validateInput(i) {
|
|
|
112254
112688
|
if (i.index > last)
|
|
112255
112689
|
throw new Error(`validateInput: index(${i.index}) not in nonWitnessUtxo`);
|
|
112256
112690
|
const prevOut = i.nonWitnessUtxo.outputs[i.index];
|
|
112257
|
-
if (i.witnessUtxo && (!
|
|
112691
|
+
if (i.witnessUtxo && (!equalBytes5(i.witnessUtxo.script, prevOut.script) || i.witnessUtxo.amount !== prevOut.amount))
|
|
112258
112692
|
throw new Error("validateInput: witnessUtxo different from nonWitnessUtxo");
|
|
112259
112693
|
if (i.txid) {
|
|
112260
112694
|
const outputs = i.nonWitnessUtxo.outputs;
|
|
@@ -112810,7 +113244,7 @@ class Transaction {
|
|
|
112810
113244
|
let s = privateKey;
|
|
112811
113245
|
for (const i of path)
|
|
112812
113246
|
s = s.deriveChild(i);
|
|
112813
|
-
if (!
|
|
113247
|
+
if (!equalBytes5(s.publicKey, pubKey))
|
|
112814
113248
|
throw new Error("bip32Derivation: wrong pubKey");
|
|
112815
113249
|
if (!s.privateKey)
|
|
112816
113250
|
throw new Error("bip32Derivation: no privateKey");
|
|
@@ -112847,7 +113281,7 @@ class Transaction {
|
|
|
112847
113281
|
if (input.tapInternalKey) {
|
|
112848
113282
|
const { pubKey, privKey } = getTaprootKeys(privateKey, schnorrPub, input.tapInternalKey, merkleRoot);
|
|
112849
113283
|
const [taprootPubKey, _] = taprootTweakPubkey(input.tapInternalKey, merkleRoot);
|
|
112850
|
-
if (
|
|
113284
|
+
if (equalBytes5(taprootPubKey, pubKey)) {
|
|
112851
113285
|
const hash = this.preimageWitnessV1(idx, prevOutScript, sighash, amount);
|
|
112852
113286
|
const sig = concatBytes7(signSchnorr(hash, privKey, _auxRand), sighash !== SignatureHash.DEFAULT ? new Uint8Array([sighash]) : EMPTY2);
|
|
112853
113287
|
this.updateInput(idx, { tapKeySig: sig }, true);
|
|
@@ -112861,7 +113295,7 @@ class Transaction {
|
|
|
112861
113295
|
const scriptDecoded = Script.decode(script);
|
|
112862
113296
|
const ver = _script[_script.length - 1];
|
|
112863
113297
|
const hash = tapLeafHash(script, ver);
|
|
112864
|
-
const pos = scriptDecoded.findIndex((i) => isBytes7(i) &&
|
|
113298
|
+
const pos = scriptDecoded.findIndex((i) => isBytes7(i) && equalBytes5(i, schnorrPub));
|
|
112865
113299
|
if (pos === -1)
|
|
112866
113300
|
continue;
|
|
112867
113301
|
const msg = this.preimageWitnessV1(idx, prevOutScript, sighash, amount, undefined, script, ver);
|
|
@@ -112878,7 +113312,7 @@ class Transaction {
|
|
|
112878
113312
|
let hasPubkey = false;
|
|
112879
113313
|
const pubKeyHash = hash160(pubKey);
|
|
112880
113314
|
for (const i of Script.decode(inputType.lastScript)) {
|
|
112881
|
-
if (isBytes7(i) && (
|
|
113315
|
+
if (isBytes7(i) && (equalBytes5(i, pubKey) || equalBytes5(i, pubKeyHash)))
|
|
112882
113316
|
hasPubkey = true;
|
|
112883
113317
|
}
|
|
112884
113318
|
if (!hasPubkey)
|
|
@@ -112928,14 +113362,14 @@ class Transaction {
|
|
|
112928
113362
|
const ver = _script[_script.length - 1];
|
|
112929
113363
|
const outScript = OutScript.decode(script);
|
|
112930
113364
|
const hash = tapLeafHash(script, ver);
|
|
112931
|
-
const scriptSig = input.tapScriptSig.filter((i) =>
|
|
113365
|
+
const scriptSig = input.tapScriptSig.filter((i) => equalBytes5(i[0].leafHash, hash));
|
|
112932
113366
|
let signatures = [];
|
|
112933
113367
|
if (outScript.type === "tr_ms") {
|
|
112934
113368
|
const m = outScript.m;
|
|
112935
113369
|
const pubkeys = outScript.pubkeys;
|
|
112936
113370
|
let added = 0;
|
|
112937
113371
|
for (const pub of pubkeys) {
|
|
112938
|
-
const sigIdx = scriptSig.findIndex((i) =>
|
|
113372
|
+
const sigIdx = scriptSig.findIndex((i) => equalBytes5(i[0].pubKey, pub));
|
|
112939
113373
|
if (added === m || sigIdx === -1) {
|
|
112940
113374
|
signatures.push(EMPTY2);
|
|
112941
113375
|
continue;
|
|
@@ -112947,7 +113381,7 @@ class Transaction {
|
|
|
112947
113381
|
continue;
|
|
112948
113382
|
} else if (outScript.type === "tr_ns") {
|
|
112949
113383
|
for (const pub of outScript.pubkeys) {
|
|
112950
|
-
const sigIdx = scriptSig.findIndex((i) =>
|
|
113384
|
+
const sigIdx = scriptSig.findIndex((i) => equalBytes5(i[0].pubKey, pub));
|
|
112951
113385
|
if (sigIdx === -1)
|
|
112952
113386
|
continue;
|
|
112953
113387
|
signatures.push(scriptSig[sigIdx][1]);
|
|
@@ -112957,7 +113391,7 @@ class Transaction {
|
|
|
112957
113391
|
} else if (outScript.type === "unknown" && this.opts.allowUnknownInputs) {
|
|
112958
113392
|
const scriptDecoded = Script.decode(script);
|
|
112959
113393
|
signatures = scriptSig.map(([{ pubKey }, signature]) => {
|
|
112960
|
-
const pos = scriptDecoded.findIndex((i) => isBytes7(i) &&
|
|
113394
|
+
const pos = scriptDecoded.findIndex((i) => isBytes7(i) && equalBytes5(i, pubKey));
|
|
112961
113395
|
if (pos === -1)
|
|
112962
113396
|
throw new Error("finalize/taproot: cannot find position of pubkey in script");
|
|
112963
113397
|
return { signature, pos };
|
|
@@ -113005,7 +113439,7 @@ class Transaction {
|
|
|
113005
113439
|
const pubkeys = inputType.last.pubkeys;
|
|
113006
113440
|
let signatures = [];
|
|
113007
113441
|
for (const pub of pubkeys) {
|
|
113008
|
-
const sign3 = input.partialSig.find((s) =>
|
|
113442
|
+
const sign3 = input.partialSig.find((s) => equalBytes5(pub, s[0]));
|
|
113009
113443
|
if (!sign3)
|
|
113010
113444
|
continue;
|
|
113011
113445
|
signatures.push(sign3[1]);
|
|
@@ -113079,7 +113513,7 @@ class Transaction {
|
|
|
113079
113513
|
}
|
|
113080
113514
|
const thisUnsigned = this.global.unsignedTx ? RawOldTx.encode(this.global.unsignedTx) : EMPTY2;
|
|
113081
113515
|
const otherUnsigned = other.global.unsignedTx ? RawOldTx.encode(other.global.unsignedTx) : EMPTY2;
|
|
113082
|
-
if (!
|
|
113516
|
+
if (!equalBytes5(thisUnsigned, otherUnsigned))
|
|
113083
113517
|
throw new Error(`Transaction/combine: different unsigned tx`);
|
|
113084
113518
|
this.global = mergeKeyMap(PSBTGlobal, this.global, other.global, undefined, this.opts.allowUnknown);
|
|
113085
113519
|
for (let i = 0;i < this.inputs.length; i++)
|
|
@@ -117912,7 +118346,7 @@ function validateCoopExitPayoutTransaction({ rawCoopExitTransaction, expectedCoo
|
|
|
117912
118346
|
const output = tx.getOutput(i);
|
|
117913
118347
|
if (!output?.script || output.amount === undefined)
|
|
117914
118348
|
continue;
|
|
117915
|
-
if (!
|
|
118349
|
+
if (!equalBytes5(output.script, expectedScript))
|
|
117916
118350
|
continue;
|
|
117917
118351
|
if (output.amount >= BigInt(expectedPayoutAmountSats))
|
|
117918
118352
|
return;
|
|
@@ -118330,7 +118764,7 @@ function createSenderSpendTx({ htlcTx, network, hash, hashLockDestinationPubkey,
|
|
|
118330
118764
|
const entry = p2.tapLeafScript.find(([, scriptWithVer]) => Buffer.compare(scriptWithVer.slice(0, -1), sequenceLockScript) === 0);
|
|
118331
118765
|
const controlBlockBytes = TaprootControlBlock.encode(entry[0]);
|
|
118332
118766
|
const seqLeafEntry = p2.tapLeafScript.find(([_, leaf]) => {
|
|
118333
|
-
return
|
|
118767
|
+
return equalBytes3(leaf.subarray(0, leaf.length - 1), sequenceLockScript);
|
|
118334
118768
|
});
|
|
118335
118769
|
const sighash = senderSpendTx.preimageWitnessV1(0, [sequenceLockScript], SigHash.DEFAULT, [htlcAmount]);
|
|
118336
118770
|
senderSpendTx.updateInput(0, {
|
|
@@ -118380,7 +118814,7 @@ function createReceiverSpendTx({ htlcTx, network, hash, hashLockDestinationPubke
|
|
|
118380
118814
|
script: sequenceLockScript
|
|
118381
118815
|
}]), network, true);
|
|
118382
118816
|
const hashLeafEntry = p2.tapLeafScript.find(([_, leaf]) => {
|
|
118383
|
-
return
|
|
118817
|
+
return equalBytes3(leaf.subarray(0, leaf.length - 1), hashLockScript);
|
|
118384
118818
|
});
|
|
118385
118819
|
spendTx.updateInput(0, {
|
|
118386
118820
|
witnessUtxo: {
|
|
@@ -121130,7 +121564,7 @@ async function withRetry(operation, options = {}) {
|
|
|
121130
121564
|
function scopeTransferLeavesToReceiver(transfer, receiverIdentityPublicKey) {
|
|
121131
121565
|
if (transfer.receivers.length <= 1)
|
|
121132
121566
|
return transfer;
|
|
121133
|
-
const ownReceiver = transfer.receivers.find((receiver) =>
|
|
121567
|
+
const ownReceiver = transfer.receivers.find((receiver) => equalBytes3(receiver.identityPublicKey, receiverIdentityPublicKey));
|
|
121134
121568
|
if (!ownReceiver?.id)
|
|
121135
121569
|
throw new SparkValidationError("Cannot scope claim: wallet is not a receiver of this multi-receiver transfer");
|
|
121136
121570
|
const ownLeaves = transfer.leaves.filter((leaf) => leaf.transferReceiverId === ownReceiver.id);
|
|
@@ -121145,7 +121579,7 @@ function isReceiverLegComplete(transfer, receiverIdentityPublicKey) {
|
|
|
121145
121579
|
const wholeComplete = transfer.status === TransferStatus.TRANSFER_STATUS_COMPLETED;
|
|
121146
121580
|
if (transfer.receivers.length <= 1)
|
|
121147
121581
|
return wholeComplete;
|
|
121148
|
-
const ownReceiver = transfer.receivers.find((receiver) =>
|
|
121582
|
+
const ownReceiver = transfer.receivers.find((receiver) => equalBytes3(receiver.identityPublicKey, receiverIdentityPublicKey));
|
|
121149
121583
|
if (!ownReceiver)
|
|
121150
121584
|
return false;
|
|
121151
121585
|
return ownReceiver.status === TransferReceiverStatus.TRANSFER_RECEIVER_STATUS_COMPLETED || wholeComplete;
|
|
@@ -121891,7 +122325,7 @@ function isReceiverTransferStreamEvent(event2) {
|
|
|
121891
122325
|
function findOutputPayingScript(tx, script) {
|
|
121892
122326
|
for (let i = 0;i < tx.outputsLength; i++) {
|
|
121893
122327
|
const outputScript = tx.getOutput(i).script;
|
|
121894
|
-
if (outputScript &&
|
|
122328
|
+
if (outputScript && equalBytes3(outputScript, script))
|
|
121895
122329
|
return i;
|
|
121896
122330
|
}
|
|
121897
122331
|
}
|
|
@@ -121922,7 +122356,7 @@ function resolveRecoverableOutput(leaf, nodes, network, recoveryTxid, outputInde
|
|
|
121922
122356
|
const prevOut = tx.getOutput(outputIndex);
|
|
121923
122357
|
if (prevOut.amount === undefined)
|
|
121924
122358
|
continue;
|
|
121925
|
-
if (!prevOut.script || !
|
|
122359
|
+
if (!prevOut.script || !equalBytes3(prevOut.script, leafScript))
|
|
121926
122360
|
continue;
|
|
121927
122361
|
return {
|
|
121928
122362
|
txid,
|
|
@@ -123211,9 +123645,9 @@ var import_nice_grpc_common, import_light_bolt11_decoder, SparkFrostBase = class
|
|
|
123211
123645
|
}
|
|
123212
123646
|
signTransactionIndex(tx, index2, publicKey) {
|
|
123213
123647
|
let privateKey;
|
|
123214
|
-
if (
|
|
123648
|
+
if (equalBytes3(publicKey, this.identityKey?.publicKey ?? new Uint8Array))
|
|
123215
123649
|
privateKey = this.identityKey?.privateKey;
|
|
123216
|
-
else if (
|
|
123650
|
+
else if (equalBytes3(publicKey, this.depositKey?.publicKey ?? new Uint8Array))
|
|
123217
123651
|
privateKey = this.depositKey?.privateKey;
|
|
123218
123652
|
if (!privateKey)
|
|
123219
123653
|
throw new SparkValidationError("Private key not found for public key", {
|
|
@@ -124054,7 +124488,7 @@ var import_nice_grpc_common, import_light_bolt11_decoder, SparkFrostBase = class
|
|
|
124054
124488
|
return response.transfer;
|
|
124055
124489
|
}
|
|
124056
124490
|
compareTransfers(transfer1, transfer2) {
|
|
124057
|
-
return transfer1.id === transfer2.id &&
|
|
124491
|
+
return transfer1.id === transfer2.id && equalBytes3(transfer1.senderIdentityPublicKey, transfer2.senderIdentityPublicKey) && transfer1.status === transfer2.status && transfer1.totalValue === transfer2.totalValue && transfer1.expiryTime?.getTime() === transfer2.expiryTime?.getTime() && transfer1.leaves.length === transfer2.leaves.length;
|
|
124058
124492
|
}
|
|
124059
124493
|
}, TransferService, CoopExitService, DENOMINATIONS, Swap = class {
|
|
124060
124494
|
inLeaves;
|
|
@@ -124578,7 +125012,7 @@ var import_nice_grpc_common, import_light_bolt11_decoder, SparkFrostBase = class
|
|
|
124578
125012
|
}
|
|
124579
125013
|
}
|
|
124580
125014
|
async handleTransferEvent(transfer) {
|
|
124581
|
-
if (!this.identityPublicKey || !
|
|
125015
|
+
if (!this.identityPublicKey || !equalBytes3(transfer.senderIdentityPublicKey, this.identityPublicKey))
|
|
124582
125016
|
return;
|
|
124583
125017
|
const leafIds = transfer.leaves.flatMap((leaf) => leaf.leaf ? [leaf.leaf.id] : []);
|
|
124584
125018
|
this.log("handleTransferEvent", `transfer=${transfer.id} type=${transfer.type} status=${transfer.status} leaves=[${leafIds.join(",")}]`);
|
|
@@ -125208,12 +125642,12 @@ var import_nice_grpc_common, import_light_bolt11_decoder, SparkFrostBase = class
|
|
|
125208
125642
|
return pendingTransfer ? await this.transferService.claimTransfer(pendingTransfer) : [];
|
|
125209
125643
|
}
|
|
125210
125644
|
verifyKey(pubkey1, pubkey2, verifyingKey) {
|
|
125211
|
-
return
|
|
125645
|
+
return equalBytes3(addPublicKeys(pubkey1, pubkey2), verifyingKey);
|
|
125212
125646
|
}
|
|
125213
125647
|
isLeafConsistent(leaf, opLeaf) {
|
|
125214
125648
|
if (!opLeaf)
|
|
125215
125649
|
return false;
|
|
125216
|
-
return leaf.status === opLeaf.status && !!leaf.signingKeyshare && !!opLeaf.signingKeyshare &&
|
|
125650
|
+
return leaf.status === opLeaf.status && !!leaf.signingKeyshare && !!opLeaf.signingKeyshare && equalBytes3(leaf.signingKeyshare.publicKey, opLeaf.signingKeyshare.publicKey) && equalBytes3(leaf.nodeTx, opLeaf.nodeTx);
|
|
125217
125651
|
}
|
|
125218
125652
|
restoreLocalLockedToAvailable(leafIds) {
|
|
125219
125653
|
let changed = false;
|
|
@@ -134356,7 +134790,7 @@ var init_spark_wallet_CIYOesd9 = __esm(() => {
|
|
|
134356
134790
|
if (traceId)
|
|
134357
134791
|
this.logEvent(`handleStreamEvent: Receiver transfer ${transfer.id} traceId=${traceId}`);
|
|
134358
134792
|
const { senderIdentityPublicKey, receiverIdentityPublicKey } = transfer;
|
|
134359
|
-
const isSelf =
|
|
134793
|
+
const isSelf = equalBytes3(senderIdentityPublicKey, receiverIdentityPublicKey);
|
|
134360
134794
|
this.logEvent(`handleStreamEvent: Receiver transfer: id=${transfer.id} type=${transfer.type} status=${transfer.status} totalValue=${transfer.totalValue} leaves=${transfer.leaves.length} selfTransfer=${isSelf}`);
|
|
134361
134795
|
if (!isSelf) {
|
|
134362
134796
|
const incomingLeaves = transfer.leaves.map((l) => l.leaf).filter((l) => !!l);
|
|
@@ -135339,7 +135773,7 @@ var init_spark_wallet_CIYOesd9 = __esm(() => {
|
|
|
135339
135773
|
const network = this.config.getNetwork();
|
|
135340
135774
|
const identityPublicKey = await this.config.signer.getIdentityPublicKey();
|
|
135341
135775
|
const nodes = await this.leafManager.queryWatchtowerExitedNodes();
|
|
135342
|
-
return nodes.filter((node) => node.refundTx.length > 0 &&
|
|
135776
|
+
return nodes.filter((node) => node.refundTx.length > 0 && equalBytes3(node.ownerIdentityPublicKey, identityPublicKey)).map((leaf) => {
|
|
135343
135777
|
const recoverable = resolveRecoverableOutput(leaf, nodes, network);
|
|
135344
135778
|
return {
|
|
135345
135779
|
leafId: leaf.id,
|
|
@@ -135753,7 +136187,7 @@ var init_spark_wallet_CIYOesd9 = __esm(() => {
|
|
|
135753
136187
|
}
|
|
135754
136188
|
const transfer = await this.transferService.sendTransferV3(allLeafKeyTweaks);
|
|
135755
136189
|
const signerIdentityPublicKey = await this.config.signer.getIdentityPublicKey();
|
|
135756
|
-
if (decodedReceivers.some((r) =>
|
|
136190
|
+
if (decodedReceivers.some((r) => equalBytes3(r.identityPublicKey, signerIdentityPublicKey))) {
|
|
135757
136191
|
const pending = await this.transferService.queryTransfer(transfer.id);
|
|
135758
136192
|
if (pending)
|
|
135759
136193
|
await this.claimTransfer({ transfer: pending });
|
|
@@ -135797,7 +136231,7 @@ var init_spark_wallet_CIYOesd9 = __esm(() => {
|
|
|
135797
136231
|
return await Promise.all(jobs.map(async (job) => {
|
|
135798
136232
|
try {
|
|
135799
136233
|
const transfer = await this.transferService.sendTransferWithKeyTweaks(job.leafKeyTweaks, job.sparkInvoice, job.transferId);
|
|
135800
|
-
if (
|
|
136234
|
+
if (equalBytes3(signerIdentityPublicKey, job.receiverIdentityPubkey)) {
|
|
135801
136235
|
const pending = await this.transferService.queryTransfer(transfer.id);
|
|
135802
136236
|
if (pending)
|
|
135803
136237
|
await this.claimTransfer({ transfer: pending });
|
|
@@ -136472,7 +136906,7 @@ var init_spark_wallet_CIYOesd9 = __esm(() => {
|
|
|
136472
136906
|
if (!transfer)
|
|
136473
136907
|
throw new Error("Failed to provide preimage");
|
|
136474
136908
|
const receiverIdentityPublicKey = transfer.receiverIdentityPublicKey;
|
|
136475
|
-
if (
|
|
136909
|
+
if (equalBytes3(receiverIdentityPublicKey, await this.config.signer.getIdentityPublicKey()))
|
|
136476
136910
|
await this.claimTransfer({
|
|
136477
136911
|
transfer,
|
|
136478
136912
|
emit: true
|
|
@@ -136512,7 +136946,7 @@ var init_spark_wallet_CIYOesd9 = __esm(() => {
|
|
|
136512
136946
|
fee
|
|
136513
136947
|
});
|
|
136514
136948
|
this.config.signer.signTransactionIndex(spendTx, 0, await this.config.signer.getIdentityPublicKey());
|
|
136515
|
-
const sig = spendTx.getInput(0).tapScriptSig.find(([ref2]) =>
|
|
136949
|
+
const sig = spendTx.getInput(0).tapScriptSig.find(([ref2]) => equalBytes3(ref2.leafHash, leafHash))?.[1];
|
|
136516
136950
|
spendTx.updateInput(0, { finalScriptWitness: [
|
|
136517
136951
|
sig,
|
|
136518
136952
|
hexToBytes4(preimage),
|