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