zapo-js 0.1.2 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +12 -4
- package/dist/appstate/WaAppStateCrypto.js +1 -1
- package/dist/appstate/WaAppStateSyncClient.js +138 -93
- package/dist/appstate/{store/sqlite.js → encoding.js} +13 -8
- package/dist/appstate/index.js +8 -6
- package/dist/appstate/utils.js +0 -5
- package/dist/auth/WaAuthClient.js +36 -47
- package/dist/auth/flow/WaAuthCredentialsFlow.js +7 -7
- package/dist/auth/index.js +1 -6
- package/dist/auth/pairing/WaPairingCodeCrypto.js +6 -4
- package/dist/auth/pairing/WaPairingFlow.js +13 -3
- package/dist/client/WaClient.js +225 -101
- package/dist/client/WaClientFactory.js +294 -44
- package/dist/client/connection/WaConnectionManager.js +19 -10
- package/dist/client/coordinators/WaBusinessCoordinator.js +241 -0
- package/dist/client/coordinators/WaGroupCoordinator.js +11 -7
- package/dist/client/coordinators/WaIncomingNodeCoordinator.js +1 -0
- package/dist/client/coordinators/WaMessageDispatchCoordinator.js +292 -99
- package/dist/client/coordinators/WaPassiveTasksCoordinator.js +74 -31
- package/dist/client/coordinators/WaPrivacyCoordinator.js +134 -0
- package/dist/client/coordinators/WaProfileCoordinator.js +212 -0
- package/dist/client/coordinators/WaRetryCoordinator.js +179 -27
- package/dist/client/coordinators/WaStreamControlCoordinator.js +18 -11
- package/dist/client/coordinators/WaTrustedContactTokenCoordinator.js +166 -0
- package/dist/client/dirty.js +40 -20
- package/dist/client/events/devices.js +72 -0
- package/dist/client/events/group.js +3 -11
- package/dist/client/events/identity.js +22 -0
- package/dist/client/events/privacy-token.js +39 -0
- package/dist/client/history-sync.js +50 -9
- package/dist/client/incoming.js +37 -7
- package/dist/client/mailbox.js +24 -23
- package/dist/client/messages.js +107 -31
- package/dist/client/messaging/fanout.js +21 -11
- package/dist/client/messaging/participants.js +6 -4
- package/dist/client/persistence/WriteBehindPersistence.js +129 -0
- package/dist/client/tokens/cs-token.js +50 -0
- package/dist/client/tokens/tc-token.js +25 -0
- package/dist/crypto/core/index.js +2 -2
- package/dist/crypto/core/keys.js +4 -4
- package/dist/crypto/core/nonce.js +2 -0
- package/dist/crypto/core/primitives.js +0 -8
- package/dist/crypto/core/random.js +22 -0
- package/dist/crypto/curves/X25519.js +25 -6
- package/dist/crypto/index.js +3 -0
- package/dist/crypto/math/constants.js +13 -36
- package/dist/crypto/math/edwards.js +171 -44
- package/dist/crypto/math/fe.js +706 -0
- package/dist/crypto/math/mod.js +10 -3
- package/dist/esm/appstate/WaAppStateCrypto.js +1 -1
- package/dist/esm/appstate/WaAppStateSyncClient.js +138 -93
- package/dist/esm/appstate/{store/sqlite.js → encoding.js} +13 -8
- package/dist/esm/appstate/index.js +2 -2
- package/dist/esm/appstate/utils.js +2 -5
- package/dist/esm/auth/WaAuthClient.js +36 -47
- package/dist/esm/auth/flow/WaAuthCredentialsFlow.js +7 -7
- package/dist/esm/auth/index.js +0 -2
- package/dist/esm/auth/pairing/WaPairingCodeCrypto.js +6 -4
- package/dist/esm/auth/pairing/WaPairingFlow.js +14 -4
- package/dist/esm/client/WaClient.js +225 -101
- package/dist/esm/client/WaClientFactory.js +295 -45
- package/dist/esm/client/connection/WaConnectionManager.js +19 -10
- package/dist/esm/client/coordinators/WaBusinessCoordinator.js +238 -0
- package/dist/esm/client/coordinators/WaGroupCoordinator.js +11 -7
- package/dist/esm/client/coordinators/WaIncomingNodeCoordinator.js +1 -0
- package/dist/esm/client/coordinators/WaMessageDispatchCoordinator.js +295 -102
- package/dist/esm/client/coordinators/WaPassiveTasksCoordinator.js +74 -31
- package/dist/esm/client/coordinators/WaPrivacyCoordinator.js +131 -0
- package/dist/esm/client/coordinators/WaProfileCoordinator.js +209 -0
- package/dist/esm/client/coordinators/WaRetryCoordinator.js +181 -29
- package/dist/esm/client/coordinators/WaStreamControlCoordinator.js +19 -12
- package/dist/esm/client/coordinators/WaTrustedContactTokenCoordinator.js +162 -0
- package/dist/esm/client/dirty.js +40 -20
- package/dist/esm/client/events/devices.js +68 -0
- package/dist/esm/client/events/group.js +3 -11
- package/dist/esm/client/events/identity.js +19 -0
- package/dist/esm/client/events/privacy-token.js +36 -0
- package/dist/esm/client/history-sync.js +50 -9
- package/dist/esm/client/incoming.js +38 -8
- package/dist/esm/client/mailbox.js +24 -23
- package/dist/esm/client/messages.js +108 -32
- package/dist/esm/client/messaging/fanout.js +22 -12
- package/dist/esm/client/messaging/participants.js +6 -4
- package/dist/esm/client/persistence/WriteBehindPersistence.js +125 -0
- package/dist/esm/client/tokens/cs-token.js +46 -0
- package/dist/esm/client/tokens/tc-token.js +18 -0
- package/dist/esm/crypto/core/index.js +2 -2
- package/dist/esm/crypto/core/keys.js +1 -1
- package/dist/esm/crypto/core/nonce.js +2 -0
- package/dist/esm/crypto/core/primitives.js +0 -7
- package/dist/esm/crypto/core/random.js +22 -1
- package/dist/esm/crypto/curves/X25519.js +25 -6
- package/dist/esm/crypto/index.js +1 -0
- package/dist/esm/crypto/math/constants.js +12 -35
- package/dist/esm/crypto/math/edwards.js +174 -47
- package/dist/esm/crypto/math/fe.js +691 -0
- package/dist/esm/crypto/math/mod.js +10 -1
- package/dist/esm/index.js +1 -1
- package/dist/esm/infra/perf/BackgroundQueue.js +478 -0
- package/dist/esm/infra/perf/BoundedTaskQueue.js +3 -1
- package/dist/esm/infra/perf/PromiseDedup.js +20 -0
- package/dist/esm/infra/perf/SharedExclusiveGate.js +109 -0
- package/dist/esm/infra/perf/StoreLock.js +77 -0
- package/dist/esm/media/WaMediaCrypto.js +95 -13
- package/dist/esm/media/WaMediaTransferClient.js +39 -47
- package/dist/esm/media/constants.js +2 -1
- package/dist/esm/message/WaMessageClient.js +26 -19
- package/dist/esm/message/content.js +195 -9
- package/dist/esm/message/icdc.js +76 -0
- package/dist/esm/message/incoming.js +24 -12
- package/dist/esm/message/phash.js +3 -1
- package/dist/esm/message/reporting-token.js +14 -27
- package/dist/esm/protocol/appstate.js +9 -40
- package/dist/esm/protocol/browser.js +10 -18
- package/dist/esm/protocol/constants.js +5 -3
- package/dist/esm/protocol/defaults.js +6 -0
- package/dist/esm/protocol/index.js +1 -2
- package/dist/esm/protocol/jid.js +105 -36
- package/dist/esm/protocol/message.js +61 -1
- package/dist/esm/protocol/nodes.js +2 -0
- package/dist/esm/protocol/notification.js +3 -1
- package/dist/esm/protocol/privacy-token.js +17 -0
- package/dist/esm/protocol/privacy.js +55 -0
- package/dist/esm/protocol/stream.js +26 -1
- package/dist/esm/retry/codec.js +216 -0
- package/dist/esm/retry/constants.js +1 -1
- package/dist/esm/retry/index.js +2 -2
- package/dist/esm/retry/parse.js +50 -30
- package/dist/esm/retry/replay.js +11 -7
- package/dist/esm/retry/tracker.js +50 -12
- package/dist/esm/signal/api/SignalDeviceSyncApi.js +49 -32
- package/dist/esm/signal/api/SignalDigestSyncApi.js +13 -9
- package/dist/esm/signal/api/SignalIdentitySyncApi.js +26 -11
- package/dist/esm/signal/api/SignalMissingPreKeysSyncApi.js +18 -7
- package/dist/esm/signal/api/SignalRotateKeyApi.js +4 -2
- package/dist/esm/signal/api/SignalSessionSyncApi.js +16 -7
- package/dist/esm/signal/api/result-map.js +10 -0
- package/dist/esm/signal/constants.js +0 -4
- package/dist/esm/signal/crypto/WaAdvSignature.js +12 -6
- package/dist/esm/signal/{store/sqlite.js → encoding.js} +78 -24
- package/dist/esm/signal/group/SenderKeyCodec.js +3 -2
- package/dist/esm/signal/group/SenderKeyManager.js +125 -106
- package/dist/esm/signal/index.js +1 -0
- package/dist/esm/signal/registration/keygen.js +6 -2
- package/dist/esm/signal/registration/utils.js +1 -0
- package/dist/esm/signal/session/SignalProtocol.js +150 -74
- package/dist/esm/signal/session/resolver.js +137 -102
- package/dist/esm/store/contracts/privacy-token.store.js +1 -0
- package/dist/esm/store/createStore.js +101 -187
- package/dist/esm/store/index.js +1 -10
- package/dist/esm/store/locks/appstate.lock.js +26 -0
- package/dist/esm/store/locks/auth.lock.js +15 -0
- package/dist/esm/store/locks/contact.lock.js +20 -0
- package/dist/esm/store/locks/device-list.lock.js +20 -0
- package/dist/esm/store/locks/message.lock.js +21 -0
- package/dist/esm/store/locks/participants.lock.js +20 -0
- package/dist/esm/store/locks/privacy-token.lock.js +18 -0
- package/dist/esm/store/locks/retry.lock.js +29 -0
- package/dist/esm/store/locks/sender-key.lock.js +52 -0
- package/dist/esm/store/locks/signal.lock.js +63 -0
- package/dist/esm/store/locks/thread.lock.js +21 -0
- package/dist/esm/store/noop.store.js +1 -1
- package/dist/esm/store/providers/memory/appstate.store.js +22 -24
- package/dist/esm/store/providers/memory/device-list.store.js +10 -5
- package/dist/esm/store/providers/memory/privacy-token.store.js +43 -0
- package/dist/esm/store/providers/memory/retry.store.js +77 -2
- package/dist/esm/store/providers/memory/sender-key.store.js +6 -1
- package/dist/esm/store/providers/memory/signal.store.js +36 -19
- package/dist/esm/transport/WaComms.js +3 -1
- package/dist/esm/transport/WaWebSocket.js +0 -6
- package/dist/esm/transport/binary/constants.js +0 -30
- package/dist/esm/transport/binary/decoder.js +4 -4
- package/dist/esm/transport/binary/encoder.js +8 -15
- package/dist/esm/transport/binary/index.js +0 -1
- package/dist/esm/transport/node/WaNodeOrchestrator.js +25 -19
- package/dist/esm/transport/node/builders/business.js +129 -0
- package/dist/esm/transport/node/builders/global.js +370 -0
- package/dist/esm/transport/node/builders/index.js +5 -2
- package/dist/esm/transport/node/builders/message.js +63 -239
- package/dist/esm/transport/node/builders/pairing.js +0 -24
- package/dist/esm/transport/node/builders/privacy-token.js +41 -0
- package/dist/esm/transport/node/builders/privacy.js +48 -0
- package/dist/esm/transport/node/builders/profile.js +70 -0
- package/dist/esm/transport/node/builders/retry.js +10 -22
- package/dist/esm/transport/node/builders/usync.js +6 -2
- package/dist/esm/transport/node/helpers.js +19 -1
- package/dist/esm/transport/node/usync.js +3 -33
- package/dist/esm/transport/node/xml.js +35 -14
- package/dist/esm/transport/noise/WaClientPayload.js +10 -10
- package/dist/esm/transport/noise/WaNoiseCert.js +3 -3
- package/dist/esm/transport/noise/WaNoiseSession.js +64 -23
- package/dist/esm/transport/noise/WaNoiseSocket.js +8 -4
- package/dist/esm/transport/stream/parse.js +8 -4
- package/dist/esm/util/bytes.js +22 -18
- package/dist/esm/util/index.js +5 -0
- package/dist/esm/util/primitives.js +3 -2
- package/dist/index.js +7 -1
- package/dist/infra/perf/BackgroundQueue.js +482 -0
- package/dist/infra/perf/BoundedTaskQueue.js +3 -1
- package/dist/infra/perf/PromiseDedup.js +24 -0
- package/dist/infra/perf/SharedExclusiveGate.js +113 -0
- package/dist/infra/perf/StoreLock.js +81 -0
- package/dist/media/WaMediaCrypto.js +94 -12
- package/dist/media/WaMediaTransferClient.js +39 -47
- package/dist/media/constants.js +2 -1
- package/dist/message/WaMessageClient.js +26 -19
- package/dist/message/content.js +198 -9
- package/dist/message/icdc.js +81 -0
- package/dist/message/incoming.js +24 -12
- package/dist/message/phash.js +3 -1
- package/dist/message/reporting-token.js +14 -28
- package/dist/protocol/appstate.js +10 -41
- package/dist/protocol/browser.js +10 -18
- package/dist/protocol/constants.js +21 -2
- package/dist/protocol/defaults.js +6 -0
- package/dist/protocol/index.js +8 -5
- package/dist/protocol/jid.js +111 -36
- package/dist/protocol/message.js +62 -2
- package/dist/protocol/nodes.js +2 -0
- package/dist/protocol/notification.js +3 -1
- package/dist/protocol/privacy-token.js +20 -0
- package/dist/protocol/privacy.js +58 -0
- package/dist/protocol/stream.js +27 -2
- package/dist/retry/codec.js +220 -0
- package/dist/retry/constants.js +1 -1
- package/dist/retry/index.js +5 -5
- package/dist/retry/parse.js +51 -30
- package/dist/retry/replay.js +10 -6
- package/dist/retry/tracker.js +50 -12
- package/dist/signal/api/SignalDeviceSyncApi.js +48 -31
- package/dist/signal/api/SignalDigestSyncApi.js +13 -9
- package/dist/signal/api/SignalIdentitySyncApi.js +25 -10
- package/dist/signal/api/SignalMissingPreKeysSyncApi.js +17 -6
- package/dist/signal/api/SignalRotateKeyApi.js +4 -2
- package/dist/signal/api/SignalSessionSyncApi.js +16 -7
- package/dist/signal/api/result-map.js +13 -0
- package/dist/signal/constants.js +1 -5
- package/dist/signal/crypto/WaAdvSignature.js +11 -5
- package/dist/signal/{store/sqlite.js → encoding.js} +79 -25
- package/dist/signal/group/SenderKeyCodec.js +4 -3
- package/dist/signal/group/SenderKeyManager.js +125 -106
- package/dist/signal/index.js +13 -1
- package/dist/signal/registration/keygen.js +6 -2
- package/dist/signal/registration/utils.js +1 -0
- package/dist/signal/session/SignalProtocol.js +150 -74
- package/dist/signal/session/resolver.js +135 -100
- package/dist/store/contracts/privacy-token.store.js +2 -0
- package/dist/store/createStore.js +101 -187
- package/dist/store/index.js +15 -33
- package/dist/store/locks/appstate.lock.js +29 -0
- package/dist/store/locks/auth.lock.js +18 -0
- package/dist/store/locks/contact.lock.js +23 -0
- package/dist/store/locks/device-list.lock.js +23 -0
- package/dist/store/locks/message.lock.js +24 -0
- package/dist/store/locks/participants.lock.js +23 -0
- package/dist/store/locks/privacy-token.lock.js +21 -0
- package/dist/store/locks/retry.lock.js +32 -0
- package/dist/store/locks/sender-key.lock.js +55 -0
- package/dist/store/locks/signal.lock.js +66 -0
- package/dist/store/locks/thread.lock.js +24 -0
- package/dist/store/noop.store.js +1 -1
- package/dist/store/providers/memory/appstate.store.js +22 -24
- package/dist/store/providers/memory/device-list.store.js +10 -5
- package/dist/store/providers/memory/privacy-token.store.js +47 -0
- package/dist/store/providers/memory/retry.store.js +77 -2
- package/dist/store/providers/memory/sender-key.store.js +6 -1
- package/dist/store/providers/memory/signal.store.js +36 -19
- package/dist/transport/WaComms.js +3 -1
- package/dist/transport/WaWebSocket.js +0 -6
- package/dist/transport/binary/constants.js +1 -31
- package/dist/transport/binary/decoder.js +4 -4
- package/dist/transport/binary/encoder.js +8 -15
- package/dist/transport/binary/index.js +0 -4
- package/dist/transport/node/WaNodeOrchestrator.js +24 -18
- package/dist/transport/node/builders/business.js +137 -0
- package/dist/transport/node/builders/global.js +375 -0
- package/dist/transport/node/builders/index.js +18 -9
- package/dist/transport/node/builders/message.js +64 -245
- package/dist/transport/node/builders/pairing.js +0 -26
- package/dist/transport/node/builders/privacy-token.js +46 -0
- package/dist/transport/node/builders/privacy.js +55 -0
- package/dist/transport/node/builders/profile.js +78 -0
- package/dist/transport/node/builders/retry.js +9 -21
- package/dist/transport/node/builders/usync.js +6 -2
- package/dist/transport/node/helpers.js +20 -1
- package/dist/transport/node/usync.js +2 -32
- package/dist/transport/node/xml.js +35 -14
- package/dist/transport/noise/WaClientPayload.js +13 -13
- package/dist/transport/noise/WaNoiseCert.js +2 -2
- package/dist/transport/noise/WaNoiseSession.js +64 -23
- package/dist/transport/noise/WaNoiseSocket.js +8 -4
- package/dist/transport/stream/parse.js +7 -3
- package/dist/types/appstate/encoding.d.ts +7 -0
- package/dist/types/appstate/index.d.ts +3 -3
- package/dist/types/appstate/utils.d.ts +0 -2
- package/dist/types/auth/flow/WaAuthCredentialsFlow.d.ts +1 -1
- package/dist/types/auth/index.d.ts +0 -2
- package/dist/types/auth/types.d.ts +1 -0
- package/dist/types/client/WaClient.d.ts +27 -12
- package/dist/types/client/WaClientFactory.d.ts +12 -4
- package/dist/types/client/connection/WaConnectionManager.d.ts +2 -0
- package/dist/types/client/coordinators/WaBusinessCoordinator.d.ts +57 -0
- package/dist/types/client/coordinators/WaIncomingNodeCoordinator.d.ts +3 -1
- package/dist/types/client/coordinators/WaMessageDispatchCoordinator.d.ts +14 -0
- package/dist/types/client/coordinators/WaPassiveTasksCoordinator.d.ts +4 -0
- package/dist/types/client/coordinators/WaPrivacyCoordinator.d.ts +26 -0
- package/dist/types/client/coordinators/WaProfileCoordinator.d.ts +36 -0
- package/dist/types/client/coordinators/WaRetryCoordinator.d.ts +6 -0
- package/dist/types/client/coordinators/WaStreamControlCoordinator.d.ts +3 -2
- package/dist/types/client/coordinators/WaTrustedContactTokenCoordinator.d.ts +45 -0
- package/dist/types/client/events/devices.d.ts +20 -0
- package/dist/types/client/events/identity.d.ts +9 -0
- package/dist/types/client/events/privacy-token.d.ts +7 -0
- package/dist/types/client/history-sync.d.ts +9 -6
- package/dist/types/client/incoming.d.ts +3 -1
- package/dist/types/client/index.d.ts +1 -1
- package/dist/types/client/mailbox.d.ts +3 -5
- package/dist/types/client/messages.d.ts +1 -2
- package/dist/types/client/persistence/WriteBehindPersistence.d.ts +34 -0
- package/dist/types/client/tokens/cs-token.d.ts +10 -0
- package/dist/types/client/tokens/tc-token.d.ts +5 -0
- package/dist/types/client/types.d.ts +51 -3
- package/dist/types/crypto/core/index.d.ts +2 -2
- package/dist/types/crypto/core/nonce.d.ts +2 -0
- package/dist/types/crypto/core/primitives.d.ts +0 -1
- package/dist/types/crypto/core/random.d.ts +1 -0
- package/dist/types/crypto/index.d.ts +1 -0
- package/dist/types/crypto/math/constants.d.ts +4 -2
- package/dist/types/crypto/math/fe.d.ts +30 -0
- package/dist/types/crypto/math/mod.d.ts +0 -2
- package/dist/types/crypto/math/types.d.ts +11 -4
- package/dist/types/index.d.ts +5 -3
- package/dist/types/infra/perf/BackgroundQueue.d.ts +58 -0
- package/dist/types/infra/perf/PromiseDedup.d.ts +4 -0
- package/dist/types/infra/perf/SharedExclusiveGate.d.ts +17 -0
- package/dist/types/infra/perf/StoreLock.d.ts +10 -0
- package/dist/types/media/WaMediaCrypto.d.ts +3 -2
- package/dist/types/media/WaMediaTransferClient.d.ts +3 -12
- package/dist/types/media/constants.d.ts +1 -1
- package/dist/types/media/index.d.ts +1 -1
- package/dist/types/media/types.d.ts +10 -2
- package/dist/types/message/content.d.ts +8 -0
- package/dist/types/message/icdc.d.ts +13 -0
- package/dist/types/message/reporting-token.d.ts +0 -1
- package/dist/types/message/types.d.ts +45 -6
- package/dist/types/protocol/appstate.d.ts +0 -11
- package/dist/types/protocol/constants.d.ts +7 -3
- package/dist/types/protocol/defaults.d.ts +6 -0
- package/dist/types/protocol/index.d.ts +1 -2
- package/dist/types/protocol/jid.d.ts +19 -2
- package/dist/types/protocol/message.d.ts +60 -0
- package/dist/types/protocol/nodes.d.ts +2 -0
- package/dist/types/protocol/notification.d.ts +2 -0
- package/dist/types/protocol/privacy-token.d.ts +17 -0
- package/dist/types/protocol/privacy.d.ts +75 -0
- package/dist/types/protocol/stream.d.ts +30 -0
- package/dist/types/retry/codec.d.ts +3 -0
- package/dist/types/retry/index.d.ts +3 -3
- package/dist/types/retry/parse.d.ts +5 -2
- package/dist/types/retry/tracker.d.ts +1 -0
- package/dist/types/retry/types.d.ts +6 -1
- package/dist/types/signal/api/SignalDeviceSyncApi.d.ts +2 -1
- package/dist/types/signal/api/SignalDigestSyncApi.d.ts +6 -0
- package/dist/types/signal/api/SignalIdentitySyncApi.d.ts +2 -0
- package/dist/types/signal/api/SignalRotateKeyApi.d.ts +4 -5
- package/dist/types/signal/api/SignalSessionSyncApi.d.ts +8 -6
- package/dist/types/signal/api/result-map.d.ts +1 -0
- package/dist/types/signal/constants.d.ts +0 -3
- package/dist/types/signal/{store/sqlite.d.ts → encoding.d.ts} +3 -3
- package/dist/types/signal/group/SenderKeyManager.d.ts +10 -5
- package/dist/types/signal/index.d.ts +2 -0
- package/dist/types/signal/session/SignalProtocol.d.ts +10 -4
- package/dist/types/signal/session/resolver.d.ts +7 -2
- package/dist/types/store/contracts/appstate.store.d.ts +1 -1
- package/dist/types/store/contracts/privacy-token.store.d.ts +16 -0
- package/dist/types/store/contracts/retry.store.d.ts +7 -0
- package/dist/types/store/contracts/signal.store.d.ts +7 -0
- package/dist/types/store/createStore.d.ts +1 -1
- package/dist/types/store/index.d.ts +5 -13
- package/dist/types/store/locks/appstate.lock.d.ts +3 -0
- package/dist/types/store/locks/auth.lock.d.ts +3 -0
- package/dist/types/store/locks/contact.lock.d.ts +3 -0
- package/dist/types/store/locks/device-list.lock.d.ts +2 -0
- package/dist/types/store/locks/message.lock.d.ts +3 -0
- package/dist/types/store/locks/participants.lock.d.ts +2 -0
- package/dist/types/store/locks/privacy-token.lock.d.ts +2 -0
- package/dist/types/store/locks/retry.lock.d.ts +2 -0
- package/dist/types/store/locks/sender-key.lock.d.ts +3 -0
- package/dist/types/store/locks/signal.lock.d.ts +3 -0
- package/dist/types/store/locks/thread.lock.d.ts +3 -0
- package/dist/types/store/providers/memory/appstate.store.d.ts +1 -1
- package/dist/types/store/providers/memory/privacy-token.store.d.ts +13 -0
- package/dist/types/store/providers/memory/retry.store.d.ts +8 -0
- package/dist/types/store/providers/memory/signal.store.d.ts +2 -1
- package/dist/types/store/types.d.ts +49 -61
- package/dist/types/transport/WaWebSocket.d.ts +0 -1
- package/dist/types/transport/binary/constants.d.ts +0 -30
- package/dist/types/transport/binary/index.d.ts +0 -1
- package/dist/types/transport/node/WaNodeOrchestrator.d.ts +3 -4
- package/dist/types/transport/node/builders/business.d.ts +29 -0
- package/dist/types/transport/node/builders/global.d.ts +102 -0
- package/dist/types/transport/node/builders/index.d.ts +5 -2
- package/dist/types/transport/node/builders/message.d.ts +8 -7
- package/dist/types/transport/node/builders/pairing.d.ts +0 -2
- package/dist/types/transport/node/builders/privacy-token.d.ts +9 -0
- package/dist/types/transport/node/builders/privacy.d.ts +7 -0
- package/dist/types/transport/node/builders/profile.d.ts +8 -0
- package/dist/types/transport/node/builders/retry.d.ts +0 -1
- package/dist/types/transport/node/helpers.d.ts +5 -0
- package/dist/types/transport/noise/WaNoiseSession.d.ts +3 -2
- package/dist/types/transport/noise/WaNoiseSocket.d.ts +4 -2
- package/dist/types/util/bytes.d.ts +1 -1
- package/dist/types/util/index.d.ts +5 -0
- package/dist/types/util/primitives.d.ts +0 -1
- package/dist/util/bytes.js +22 -18
- package/dist/util/index.js +23 -0
- package/dist/util/primitives.js +2 -2
- package/package.json +29 -7
- package/proto/index.js +1 -1
- package/dist/crypto/core/constants.js +0 -4
- package/dist/esm/crypto/core/constants.js +0 -1
- package/dist/esm/retry/outbound.js +0 -82
- package/dist/esm/store/providers/sqlite/BaseSqliteStore.js +0 -37
- package/dist/esm/store/providers/sqlite/appstate.store.js +0 -250
- package/dist/esm/store/providers/sqlite/auth.store.js +0 -176
- package/dist/esm/store/providers/sqlite/connection.js +0 -245
- package/dist/esm/store/providers/sqlite/contact.store.js +0 -74
- package/dist/esm/store/providers/sqlite/device-list.store.js +0 -127
- package/dist/esm/store/providers/sqlite/message.store.js +0 -132
- package/dist/esm/store/providers/sqlite/migrations.js +0 -347
- package/dist/esm/store/providers/sqlite/participants.store.js +0 -77
- package/dist/esm/store/providers/sqlite/retry.store.js +0 -141
- package/dist/esm/store/providers/sqlite/sender-key.store.js +0 -198
- package/dist/esm/store/providers/sqlite/signal.store.js +0 -435
- package/dist/esm/store/providers/sqlite/table-names.js +0 -107
- package/dist/esm/store/providers/sqlite/thread.store.js +0 -85
- package/dist/retry/outbound.js +0 -87
- package/dist/store/providers/sqlite/BaseSqliteStore.js +0 -41
- package/dist/store/providers/sqlite/appstate.store.js +0 -254
- package/dist/store/providers/sqlite/auth.store.js +0 -180
- package/dist/store/providers/sqlite/connection.js +0 -281
- package/dist/store/providers/sqlite/contact.store.js +0 -78
- package/dist/store/providers/sqlite/device-list.store.js +0 -131
- package/dist/store/providers/sqlite/message.store.js +0 -136
- package/dist/store/providers/sqlite/migrations.js +0 -350
- package/dist/store/providers/sqlite/participants.store.js +0 -81
- package/dist/store/providers/sqlite/retry.store.js +0 -145
- package/dist/store/providers/sqlite/sender-key.store.js +0 -202
- package/dist/store/providers/sqlite/signal.store.js +0 -439
- package/dist/store/providers/sqlite/table-names.js +0 -113
- package/dist/store/providers/sqlite/thread.store.js +0 -89
- package/dist/types/appstate/store/sqlite.d.ts +0 -7
- package/dist/types/crypto/core/constants.d.ts +0 -1
- package/dist/types/retry/outbound.d.ts +0 -4
- package/dist/types/store/providers/sqlite/BaseSqliteStore.d.ts +0 -12
- package/dist/types/store/providers/sqlite/appstate.store.d.ts +0 -17
- package/dist/types/store/providers/sqlite/auth.store.d.ts +0 -10
- package/dist/types/store/providers/sqlite/connection.d.ts +0 -10
- package/dist/types/store/providers/sqlite/contact.store.d.ts +0 -12
- package/dist/types/store/providers/sqlite/device-list.store.d.ts +0 -15
- package/dist/types/store/providers/sqlite/message.store.d.ts +0 -13
- package/dist/types/store/providers/sqlite/migrations.d.ts +0 -3
- package/dist/types/store/providers/sqlite/participants.store.d.ts +0 -12
- package/dist/types/store/providers/sqlite/retry.store.d.ts +0 -15
- package/dist/types/store/providers/sqlite/sender-key.store.d.ts +0 -24
- package/dist/types/store/providers/sqlite/signal.store.d.ts +0 -53
- package/dist/types/store/providers/sqlite/table-names.d.ts +0 -5
- package/dist/types/store/providers/sqlite/thread.store.d.ts +0 -13
|
@@ -1,9 +1,33 @@
|
|
|
1
|
+
import { isGroupOrBroadcastJid, normalizeDeviceJid } from '../protocol/jid.js';
|
|
2
|
+
import { encodeRetryReplayPayload } from './codec.js';
|
|
1
3
|
import { RETRY_OUTBOUND_TTL_MS } from './constants.js';
|
|
2
|
-
import { encodeRetryReplayPayload } from './outbound.js';
|
|
3
4
|
import { toError } from '../util/primitives.js';
|
|
4
5
|
export function createOutboundRetryTracker(options) {
|
|
5
6
|
const { retryStore, logger } = options;
|
|
6
7
|
const retryTtlMs = retryStore.getTtlMs?.() ?? RETRY_OUTBOUND_TTL_MS;
|
|
8
|
+
const supportsRawReplayPayload = retryStore.supportsRawReplayPayload?.() ?? false;
|
|
9
|
+
const normalizeEligibleRequesterDeviceJids = (values) => {
|
|
10
|
+
if (!values || values.length === 0) {
|
|
11
|
+
return undefined;
|
|
12
|
+
}
|
|
13
|
+
const deduped = new Set();
|
|
14
|
+
for (let index = 0; index < values.length; index += 1) {
|
|
15
|
+
const raw = values[index]?.trim();
|
|
16
|
+
if (!raw) {
|
|
17
|
+
continue;
|
|
18
|
+
}
|
|
19
|
+
try {
|
|
20
|
+
deduped.add(normalizeDeviceJid(raw));
|
|
21
|
+
}
|
|
22
|
+
catch {
|
|
23
|
+
continue;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
if (deduped.size === 0) {
|
|
27
|
+
return undefined;
|
|
28
|
+
}
|
|
29
|
+
return Array.from(deduped);
|
|
30
|
+
};
|
|
7
31
|
const safeUpsertRetryOutboundRecord = async (record) => {
|
|
8
32
|
try {
|
|
9
33
|
await retryStore.upsertOutboundMessage(record);
|
|
@@ -22,34 +46,48 @@ export function createOutboundRetryTracker(options) {
|
|
|
22
46
|
return {
|
|
23
47
|
track: async (hint, publish) => {
|
|
24
48
|
const nowMs = Date.now();
|
|
25
|
-
const expiresAtMs = nowMs + retryTtlMs;
|
|
26
|
-
const hintedMessageId = hint.messageIdHint?.trim();
|
|
27
49
|
const replayMode = hint.replayPayload.mode;
|
|
28
50
|
const resolvedToJid = hint.toJid ?? (replayMode === 'opaque_node' ? '' : hint.replayPayload.to);
|
|
29
|
-
const replayPayload =
|
|
30
|
-
|
|
31
|
-
|
|
51
|
+
const replayPayload = supportsRawReplayPayload
|
|
52
|
+
? hint.replayPayload
|
|
53
|
+
: encodeRetryReplayPayload(hint.replayPayload);
|
|
54
|
+
let eligibleRequesterDeviceJids = normalizeEligibleRequesterDeviceJids(hint.eligibleRequesterDeviceJids);
|
|
55
|
+
if (!eligibleRequesterDeviceJids &&
|
|
56
|
+
resolvedToJid &&
|
|
57
|
+
!isGroupOrBroadcastJid(resolvedToJid)) {
|
|
58
|
+
try {
|
|
59
|
+
eligibleRequesterDeviceJids = [normalizeDeviceJid(resolvedToJid)];
|
|
60
|
+
}
|
|
61
|
+
catch {
|
|
62
|
+
eligibleRequesterDeviceJids = undefined;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
const createRetryOutboundRecord = (messageId, updatedAtMs, expiresAtMs) => ({
|
|
32
66
|
messageId,
|
|
33
67
|
toJid: resolvedToJid,
|
|
34
68
|
participantJid: hint.participantJid,
|
|
35
69
|
recipientJid: hint.recipientJid,
|
|
70
|
+
eligibleRequesterDeviceJids,
|
|
71
|
+
deliveredRequesterDeviceJids: [],
|
|
36
72
|
messageType: hint.type,
|
|
37
73
|
replayMode,
|
|
38
74
|
replayPayload,
|
|
39
75
|
state: 'pending',
|
|
40
|
-
createdAtMs,
|
|
76
|
+
createdAtMs: nowMs,
|
|
41
77
|
updatedAtMs,
|
|
42
78
|
expiresAtMs
|
|
43
79
|
});
|
|
44
|
-
if (hintedMessageId) {
|
|
45
|
-
hintedPersisted = await safeUpsertRetryOutboundRecord(createRetryOutboundRecord(hintedMessageId, nowMs, nowMs, expiresAtMs));
|
|
46
|
-
}
|
|
47
80
|
const result = await publish();
|
|
48
|
-
|
|
81
|
+
const persistedMessageId = result.id.trim();
|
|
82
|
+
if (!persistedMessageId) {
|
|
83
|
+
logger.warn('retry outbound record skipped: publish returned empty message id', {
|
|
84
|
+
to: resolvedToJid,
|
|
85
|
+
mode: replayMode
|
|
86
|
+
});
|
|
49
87
|
return result;
|
|
50
88
|
}
|
|
51
89
|
const persistedNowMs = Date.now();
|
|
52
|
-
await safeUpsertRetryOutboundRecord(createRetryOutboundRecord(
|
|
90
|
+
await safeUpsertRetryOutboundRecord(createRetryOutboundRecord(persistedMessageId, persistedNowMs, persistedNowMs + retryTtlMs));
|
|
53
91
|
return result;
|
|
54
92
|
}
|
|
55
93
|
};
|
|
@@ -1,11 +1,13 @@
|
|
|
1
|
+
import { PromiseDedup } from '../../infra/perf/PromiseDedup.js';
|
|
1
2
|
import { WA_DEFAULTS, WA_NODE_TAGS, WA_USYNC_CONTEXTS } from '../../protocol/constants.js';
|
|
2
|
-
import {
|
|
3
|
+
import { buildDeviceJid, isHostedDeviceId, splitJid, toUserJid } from '../../protocol/jid.js';
|
|
3
4
|
import { buildUsyncIq } from '../../transport/node/builders/usync.js';
|
|
4
5
|
import { findNodeChild, getNodeChildrenByTag } from '../../transport/node/helpers.js';
|
|
5
6
|
import { assertIqResult } from '../../transport/node/query.js';
|
|
6
7
|
import { createUsyncSidGenerator } from '../../transport/node/usync.js';
|
|
7
8
|
export class SignalDeviceSyncApi {
|
|
8
9
|
constructor(options) {
|
|
10
|
+
this.syncDedup = new PromiseDedup();
|
|
9
11
|
this.logger = options.logger;
|
|
10
12
|
this.query = options.query;
|
|
11
13
|
this.deviceListStore = options.deviceListStore;
|
|
@@ -14,11 +16,15 @@ export class SignalDeviceSyncApi {
|
|
|
14
16
|
this.hostDomain = options.hostDomain ?? WA_DEFAULTS.HOST_DOMAIN;
|
|
15
17
|
this.generateSid = options.generateSid ?? createUsyncSidGenerator();
|
|
16
18
|
}
|
|
17
|
-
|
|
19
|
+
syncDeviceList(userJids, timeoutMs = this.defaultTimeoutMs) {
|
|
18
20
|
const normalizedUsers = this.normalizeUsers(userJids);
|
|
19
21
|
if (normalizedUsers.length === 0) {
|
|
20
|
-
return [];
|
|
22
|
+
return Promise.resolve([]);
|
|
21
23
|
}
|
|
24
|
+
const dedupKey = normalizedUsers.join(',');
|
|
25
|
+
return this.syncDedup.run(dedupKey, () => this.syncDeviceListInternal(normalizedUsers, timeoutMs));
|
|
26
|
+
}
|
|
27
|
+
async syncDeviceListInternal(normalizedUsers, timeoutMs) {
|
|
22
28
|
const nowMs = Date.now();
|
|
23
29
|
const cachedByUser = new Map();
|
|
24
30
|
const usersToQuery = this.deviceListStore
|
|
@@ -123,16 +129,19 @@ export class SignalDeviceSyncApi {
|
|
|
123
129
|
}
|
|
124
130
|
async collectUsersToQuery(normalizedUsers, nowMs, cachedByUser, store) {
|
|
125
131
|
const records = await store.getUserDevicesBatch(normalizedUsers, nowMs);
|
|
126
|
-
const usersToQuery =
|
|
132
|
+
const usersToQuery = new Array(normalizedUsers.length);
|
|
133
|
+
let usersToQueryCount = 0;
|
|
127
134
|
for (let index = 0; index < normalizedUsers.length; index += 1) {
|
|
128
135
|
const userJid = normalizedUsers[index];
|
|
129
136
|
const record = records[index];
|
|
130
137
|
if (!record) {
|
|
131
|
-
usersToQuery
|
|
138
|
+
usersToQuery[usersToQueryCount] = userJid;
|
|
139
|
+
usersToQueryCount += 1;
|
|
132
140
|
continue;
|
|
133
141
|
}
|
|
134
142
|
cachedByUser.set(userJid, record.deviceJids);
|
|
135
143
|
}
|
|
144
|
+
usersToQuery.length = usersToQueryCount;
|
|
136
145
|
return usersToQuery;
|
|
137
146
|
}
|
|
138
147
|
makeDeviceSyncRequest(userJids, sid) {
|
|
@@ -201,7 +210,8 @@ export class SignalDeviceSyncApi {
|
|
|
201
210
|
}
|
|
202
211
|
const requestedSet = new Set(requestedUsers);
|
|
203
212
|
const userNodes = getNodeChildrenByTag(listNode, WA_NODE_TAGS.USER);
|
|
204
|
-
const parsed =
|
|
213
|
+
const parsed = new Array(userNodes.length);
|
|
214
|
+
let parsedCount = 0;
|
|
205
215
|
for (let index = 0; index < userNodes.length; index += 1) {
|
|
206
216
|
const userNode = userNodes[index];
|
|
207
217
|
const userJid = userNode.attrs.jid;
|
|
@@ -212,11 +222,13 @@ export class SignalDeviceSyncApi {
|
|
|
212
222
|
if (!requestedSet.has(normalizedUserJid)) {
|
|
213
223
|
continue;
|
|
214
224
|
}
|
|
215
|
-
parsed
|
|
225
|
+
parsed[parsedCount] = {
|
|
216
226
|
jid: normalizedUserJid,
|
|
217
|
-
deviceJids: this.parseUserDeviceJids(userNode, normalizedUserJid)
|
|
218
|
-
}
|
|
227
|
+
deviceJids: this.parseUserDeviceJids(userNode, userJid, normalizedUserJid)
|
|
228
|
+
};
|
|
229
|
+
parsedCount += 1;
|
|
219
230
|
}
|
|
231
|
+
parsed.length = parsedCount;
|
|
220
232
|
return parsed;
|
|
221
233
|
}
|
|
222
234
|
parseLidSyncResponse(node, requestedUsers) {
|
|
@@ -231,7 +243,8 @@ export class SignalDeviceSyncApi {
|
|
|
231
243
|
}
|
|
232
244
|
const requestedSet = new Set(requestedUsers);
|
|
233
245
|
const userNodes = getNodeChildrenByTag(listNode, WA_NODE_TAGS.USER);
|
|
234
|
-
const parsed =
|
|
246
|
+
const parsed = new Array(userNodes.length);
|
|
247
|
+
let parsedCount = 0;
|
|
235
248
|
for (let index = 0; index < userNodes.length; index += 1) {
|
|
236
249
|
const userNode = userNodes[index];
|
|
237
250
|
const userJid = userNode.attrs.jid;
|
|
@@ -250,7 +263,8 @@ export class SignalDeviceSyncApi {
|
|
|
250
263
|
const lidNode = findNodeChild(userNode, WA_NODE_TAGS.LID);
|
|
251
264
|
const contactNode = findNodeChild(userNode, WA_NODE_TAGS.CONTACT);
|
|
252
265
|
if (!lidNode) {
|
|
253
|
-
parsed
|
|
266
|
+
parsed[parsedCount] = this.buildLidSyncResult(normalizedUserJid, normalizedPhoneJid, contactNode, null);
|
|
267
|
+
parsedCount += 1;
|
|
254
268
|
continue;
|
|
255
269
|
}
|
|
256
270
|
const errorNode = findNodeChild(lidNode, WA_NODE_TAGS.ERROR);
|
|
@@ -260,12 +274,15 @@ export class SignalDeviceSyncApi {
|
|
|
260
274
|
code: errorNode.attrs.code,
|
|
261
275
|
text: errorNode.attrs.text
|
|
262
276
|
});
|
|
263
|
-
parsed
|
|
277
|
+
parsed[parsedCount] = this.buildLidSyncResult(normalizedUserJid, normalizedPhoneJid, contactNode, null);
|
|
278
|
+
parsedCount += 1;
|
|
264
279
|
continue;
|
|
265
280
|
}
|
|
266
281
|
const lidJid = lidNode.attrs.val ? this.normalizeUserJid(lidNode.attrs.val) : null;
|
|
267
|
-
parsed
|
|
282
|
+
parsed[parsedCount] = this.buildLidSyncResult(normalizedUserJid, normalizedPhoneJid, contactNode, lidJid);
|
|
283
|
+
parsedCount += 1;
|
|
268
284
|
}
|
|
285
|
+
parsed.length = parsedCount;
|
|
269
286
|
return parsed;
|
|
270
287
|
}
|
|
271
288
|
buildLidSyncResult(jid, phoneJid, contactNode, lidJid) {
|
|
@@ -291,7 +308,7 @@ export class SignalDeviceSyncApi {
|
|
|
291
308
|
}
|
|
292
309
|
return contactNode.attrs.type === 'in';
|
|
293
310
|
}
|
|
294
|
-
parseUserDeviceJids(userNode,
|
|
311
|
+
parseUserDeviceJids(userNode, rawUserJid, normalizedUserJid) {
|
|
295
312
|
const devicesNode = findNodeChild(userNode, WA_NODE_TAGS.DEVICES);
|
|
296
313
|
if (!devicesNode) {
|
|
297
314
|
return [];
|
|
@@ -299,7 +316,7 @@ export class SignalDeviceSyncApi {
|
|
|
299
316
|
const errorNode = findNodeChild(devicesNode, WA_NODE_TAGS.ERROR);
|
|
300
317
|
if (errorNode) {
|
|
301
318
|
this.logger.warn('signal device sync user error', {
|
|
302
|
-
jid:
|
|
319
|
+
jid: normalizedUserJid,
|
|
303
320
|
code: errorNode.attrs.code,
|
|
304
321
|
text: errorNode.attrs.text
|
|
305
322
|
});
|
|
@@ -309,7 +326,8 @@ export class SignalDeviceSyncApi {
|
|
|
309
326
|
if (!deviceListNode) {
|
|
310
327
|
return [];
|
|
311
328
|
}
|
|
312
|
-
const
|
|
329
|
+
const parsedNormalizedUser = splitJid(normalizedUserJid);
|
|
330
|
+
const parsedRawUser = splitJid(rawUserJid);
|
|
313
331
|
const dedup = new Set();
|
|
314
332
|
for (const deviceNode of getNodeChildrenByTag(deviceListNode, 'device')) {
|
|
315
333
|
const parsedId = deviceNode.attrs.id
|
|
@@ -318,16 +336,17 @@ export class SignalDeviceSyncApi {
|
|
|
318
336
|
if (!Number.isSafeInteger(parsedId) || parsedId < 0) {
|
|
319
337
|
continue;
|
|
320
338
|
}
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
339
|
+
const isHostedDevice = isHostedDeviceId(parsedId) || deviceNode.attrs.is_hosted === 'true';
|
|
340
|
+
dedup.add(buildDeviceJid(parsedNormalizedUser.user, parsedNormalizedUser.server, parsedId, {
|
|
341
|
+
rawServer: parsedRawUser.server,
|
|
342
|
+
isHosted: isHostedDevice
|
|
343
|
+
}));
|
|
326
344
|
}
|
|
327
|
-
return
|
|
345
|
+
return Array.from(dedup);
|
|
328
346
|
}
|
|
329
347
|
normalizeUsers(userJids) {
|
|
330
|
-
const normalized =
|
|
348
|
+
const normalized = new Array(userJids.length);
|
|
349
|
+
let normalizedCount = 0;
|
|
331
350
|
const dedup = new Set();
|
|
332
351
|
for (let index = 0; index < userJids.length; index += 1) {
|
|
333
352
|
const normalizedJid = this.normalizeUserJid(userJids[index]);
|
|
@@ -335,18 +354,16 @@ export class SignalDeviceSyncApi {
|
|
|
335
354
|
continue;
|
|
336
355
|
}
|
|
337
356
|
dedup.add(normalizedJid);
|
|
338
|
-
normalized
|
|
357
|
+
normalized[normalizedCount] = normalizedJid;
|
|
358
|
+
normalizedCount += 1;
|
|
339
359
|
}
|
|
360
|
+
normalized.length = normalizedCount;
|
|
340
361
|
return normalized;
|
|
341
362
|
}
|
|
342
363
|
normalizeUserJid(jid) {
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
if (deviceId === 0) {
|
|
348
|
-
return `${user}@${server}`;
|
|
349
|
-
}
|
|
350
|
-
return `${user}:${deviceId}@${server}`;
|
|
364
|
+
return toUserJid(jid, {
|
|
365
|
+
canonicalizeSignalServer: true,
|
|
366
|
+
hostDomain: this.hostDomain
|
|
367
|
+
});
|
|
351
368
|
}
|
|
352
369
|
}
|
|
@@ -14,8 +14,10 @@ export class SignalDigestSyncApi {
|
|
|
14
14
|
options.defaultTimeoutMs ?? WA_DEFAULTS.SIGNAL_FETCH_KEY_BUNDLES_TIMEOUT_MS;
|
|
15
15
|
this.hostDomain = options.hostDomain ?? WA_DEFAULTS.HOST_DOMAIN;
|
|
16
16
|
}
|
|
17
|
-
async validateLocalKeyBundle(timeoutMs = this.defaultTimeoutMs) {
|
|
18
|
-
|
|
17
|
+
async validateLocalKeyBundle(prefetchedOrTimeout, timeoutMs = this.defaultTimeoutMs) {
|
|
18
|
+
const prefetched = typeof prefetchedOrTimeout === 'number' ? undefined : prefetchedOrTimeout;
|
|
19
|
+
const effectiveTimeoutMs = typeof prefetchedOrTimeout === 'number' ? prefetchedOrTimeout : timeoutMs;
|
|
20
|
+
this.logger.debug('signal digest query request', { timeoutMs: effectiveTimeoutMs });
|
|
19
21
|
const response = await this.query({
|
|
20
22
|
tag: WA_NODE_TAGS.IQ,
|
|
21
23
|
attrs: {
|
|
@@ -29,7 +31,7 @@ export class SignalDigestSyncApi {
|
|
|
29
31
|
attrs: {}
|
|
30
32
|
}
|
|
31
33
|
]
|
|
32
|
-
},
|
|
34
|
+
}, effectiveTimeoutMs);
|
|
33
35
|
if (response.tag !== WA_NODE_TAGS.IQ) {
|
|
34
36
|
throw new Error(`invalid signal digest response tag: ${response.tag}`);
|
|
35
37
|
}
|
|
@@ -58,10 +60,12 @@ export class SignalDigestSyncApi {
|
|
|
58
60
|
preKeyCount: digest.preKeyIds.length
|
|
59
61
|
};
|
|
60
62
|
}
|
|
61
|
-
const [registrationInfo, signedPreKey] =
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
63
|
+
const [registrationInfo, signedPreKey] = prefetched
|
|
64
|
+
? [prefetched.registrationInfo, prefetched.signedPreKey]
|
|
65
|
+
: await Promise.all([
|
|
66
|
+
this.signalStore.getRegistrationInfo(),
|
|
67
|
+
this.signalStore.getSignedPreKey()
|
|
68
|
+
]);
|
|
65
69
|
if (!registrationInfo || !signedPreKey) {
|
|
66
70
|
return {
|
|
67
71
|
valid: false,
|
|
@@ -161,11 +165,11 @@ export class SignalDigestSyncApi {
|
|
|
161
165
|
const signedKeyId = parseUint(decodeExactLength(signedKeyIdNode.content, 'signal digest skey.id', SIGNAL_KEY_ID_LENGTH), 'signal digest skey.id');
|
|
162
166
|
const signedKeyPublicKey = decodeExactLength(signedKeyValueNode.content, 'signal digest skey.value', SIGNAL_KEY_DATA_LENGTH);
|
|
163
167
|
const signedKeySignature = decodeExactLength(signedKeySignatureNode.content, 'signal digest skey.signature', SIGNAL_SIGNATURE_LENGTH);
|
|
164
|
-
const preKeyIds = [];
|
|
165
168
|
const listChildren = getNodeChildren(listNode);
|
|
169
|
+
const preKeyIds = new Array(listChildren.length);
|
|
166
170
|
for (let index = 0; index < listChildren.length; index += 1) {
|
|
167
171
|
const child = listChildren[index];
|
|
168
|
-
preKeyIds
|
|
172
|
+
preKeyIds[index] = parseUint(decodeExactLength(child.content, `signal digest list[${index}]`, SIGNAL_KEY_ID_LENGTH), `signal digest list[${index}]`);
|
|
169
173
|
}
|
|
170
174
|
const hash = decodeNodeContentBase64OrBytes(hashNode.content, 'signal digest hash');
|
|
171
175
|
return {
|
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
import { toSerializedPubKey } from '../../crypto/core/keys.js';
|
|
2
|
+
import { PromiseDedup } from '../../infra/perf/PromiseDedup.js';
|
|
2
3
|
import { WA_DEFAULTS, WA_IQ_TYPES, WA_NODE_TAGS, WA_XMLNS } from '../../protocol/constants.js';
|
|
3
|
-
import {
|
|
4
|
+
import { canonicalizeSignalJid, parseSignalAddressFromJid } from '../../protocol/jid.js';
|
|
4
5
|
import { decodeExactLength, parseUint } from '../api/codec.js';
|
|
5
6
|
import { SIGNAL_KEY_BUNDLE_TYPE_LENGTH, SIGNAL_KEY_DATA_LENGTH } from '../api/constants.js';
|
|
6
7
|
import { findNodeChild, getNodeChildrenByTag } from '../../transport/node/helpers.js';
|
|
7
8
|
import { assertIqResult } from '../../transport/node/query.js';
|
|
8
9
|
export class SignalIdentitySyncApi {
|
|
9
10
|
constructor(options) {
|
|
11
|
+
this.syncDedup = new PromiseDedup();
|
|
10
12
|
this.logger = options.logger;
|
|
11
13
|
this.query = options.query;
|
|
12
14
|
this.signalStore = options.signalStore;
|
|
@@ -14,17 +16,24 @@ export class SignalIdentitySyncApi {
|
|
|
14
16
|
options.defaultTimeoutMs ?? WA_DEFAULTS.SIGNAL_FETCH_KEY_BUNDLES_TIMEOUT_MS;
|
|
15
17
|
this.hostDomain = options.hostDomain ?? WA_DEFAULTS.HOST_DOMAIN;
|
|
16
18
|
}
|
|
17
|
-
|
|
18
|
-
const
|
|
19
|
+
syncIdentityKeys(targetJids, timeoutMs = this.defaultTimeoutMs) {
|
|
20
|
+
const dedupKey = `${timeoutMs}:${targetJids.join(',')}`;
|
|
21
|
+
return this.syncDedup.run(dedupKey, () => this.syncIdentityKeysInternal(targetJids, timeoutMs));
|
|
22
|
+
}
|
|
23
|
+
async syncIdentityKeysInternal(targetJids, timeoutMs) {
|
|
24
|
+
const normalizedTargets = new Array(targetJids.length);
|
|
25
|
+
let normalizedTargetsCount = 0;
|
|
19
26
|
const dedup = new Set();
|
|
20
27
|
for (let index = 0; index < targetJids.length; index += 1) {
|
|
21
|
-
const normalized =
|
|
28
|
+
const normalized = canonicalizeSignalJid(targetJids[index], this.hostDomain);
|
|
22
29
|
if (dedup.has(normalized)) {
|
|
23
30
|
continue;
|
|
24
31
|
}
|
|
25
32
|
dedup.add(normalized);
|
|
26
|
-
normalizedTargets
|
|
33
|
+
normalizedTargets[normalizedTargetsCount] = normalized;
|
|
34
|
+
normalizedTargetsCount += 1;
|
|
27
35
|
}
|
|
36
|
+
normalizedTargets.length = normalizedTargetsCount;
|
|
28
37
|
if (normalizedTargets.length === 0) {
|
|
29
38
|
return [];
|
|
30
39
|
}
|
|
@@ -83,10 +92,13 @@ export class SignalIdentitySyncApi {
|
|
|
83
92
|
}
|
|
84
93
|
const requested = new Set(requestedJids);
|
|
85
94
|
const userNodes = getNodeChildrenByTag(listNode, WA_NODE_TAGS.USER);
|
|
86
|
-
const parsed =
|
|
95
|
+
const parsed = new Array(userNodes.length);
|
|
96
|
+
let parsedCount = 0;
|
|
87
97
|
for (let index = 0; index < userNodes.length; index += 1) {
|
|
88
98
|
const userNode = userNodes[index];
|
|
89
|
-
const jid = userNode.attrs.jid
|
|
99
|
+
const jid = userNode.attrs.jid
|
|
100
|
+
? canonicalizeSignalJid(userNode.attrs.jid, this.hostDomain)
|
|
101
|
+
: '';
|
|
90
102
|
if (!jid || !requested.has(jid)) {
|
|
91
103
|
continue;
|
|
92
104
|
}
|
|
@@ -109,18 +121,21 @@ export class SignalIdentitySyncApi {
|
|
|
109
121
|
? parseUint(decodeExactLength(typeNode.content, 'identity sync type', SIGNAL_KEY_BUNDLE_TYPE_LENGTH), 'identity sync type')
|
|
110
122
|
: undefined;
|
|
111
123
|
if (parsedType === undefined) {
|
|
112
|
-
parsed
|
|
124
|
+
parsed[parsedCount] = {
|
|
113
125
|
jid,
|
|
114
126
|
identity
|
|
115
|
-
}
|
|
127
|
+
};
|
|
128
|
+
parsedCount += 1;
|
|
116
129
|
continue;
|
|
117
130
|
}
|
|
118
|
-
parsed
|
|
131
|
+
parsed[parsedCount] = {
|
|
119
132
|
jid,
|
|
120
133
|
identity,
|
|
121
134
|
type: parsedType
|
|
122
|
-
}
|
|
135
|
+
};
|
|
136
|
+
parsedCount += 1;
|
|
123
137
|
}
|
|
138
|
+
parsed.length = parsedCount;
|
|
124
139
|
return parsed;
|
|
125
140
|
}
|
|
126
141
|
}
|
|
@@ -1,10 +1,14 @@
|
|
|
1
1
|
import { WA_DEFAULTS, WA_NODE_TAGS } from '../../protocol/constants.js';
|
|
2
|
-
import { splitJid } from '../../protocol/jid.js';
|
|
2
|
+
import { splitJid, toUserJid } from '../../protocol/jid.js';
|
|
3
3
|
import { decodeExactLength, parseUint } from '../api/codec.js';
|
|
4
4
|
import { SIGNAL_KEY_DATA_LENGTH, SIGNAL_KEY_ID_LENGTH, SIGNAL_REGISTRATION_ID_LENGTH, SIGNAL_SIGNATURE_LENGTH } from '../api/constants.js';
|
|
5
5
|
import { buildMissingPreKeysFetchIq } from '../api/prekeys.js';
|
|
6
|
+
import { registerParsedResultByRawAndCanonicalKey } from '../api/result-map.js';
|
|
6
7
|
import { decodeNodeContentBase64OrBytes, findNodeChildrenByTags, findNodeChild, getNodeChildrenByTag } from '../../transport/node/helpers.js';
|
|
7
8
|
import { assertIqResult } from '../../transport/node/query.js';
|
|
9
|
+
function isMissingPreKeysUserResultPreferred(result) {
|
|
10
|
+
return 'devices' in result;
|
|
11
|
+
}
|
|
8
12
|
export class SignalMissingPreKeysSyncApi {
|
|
9
13
|
constructor(options) {
|
|
10
14
|
this.logger = options.logger;
|
|
@@ -35,31 +39,38 @@ export class SignalMissingPreKeysSyncApi {
|
|
|
35
39
|
}
|
|
36
40
|
const users = getNodeChildrenByTag(listNode, WA_NODE_TAGS.USER);
|
|
37
41
|
const parsedByJid = new Map();
|
|
42
|
+
const parsedByCanonicalJid = new Map();
|
|
38
43
|
for (let index = 0; index < users.length; index += 1) {
|
|
39
44
|
const userNode = users[index];
|
|
40
45
|
const userJid = userNode.attrs.jid;
|
|
41
46
|
if (!userJid) {
|
|
42
47
|
continue;
|
|
43
48
|
}
|
|
49
|
+
const canonicalUserJid = toUserJid(userJid, {
|
|
50
|
+
canonicalizeSignalServer: true
|
|
51
|
+
});
|
|
44
52
|
const userErrorNode = findNodeChild(userNode, WA_NODE_TAGS.ERROR);
|
|
45
53
|
if (userErrorNode) {
|
|
46
54
|
const parsedCode = Number.parseInt(userErrorNode.attrs.code ?? '', 10);
|
|
47
|
-
parsedByJid
|
|
55
|
+
registerParsedResultByRawAndCanonicalKey(parsedByJid, parsedByCanonicalJid, userJid, canonicalUserJid, {
|
|
48
56
|
userJid,
|
|
49
57
|
errorCode: Number.isSafeInteger(parsedCode) ? parsedCode : undefined,
|
|
50
58
|
errorText: userErrorNode.attrs.text ?? userErrorNode.attrs.type ?? 'unknown'
|
|
51
|
-
});
|
|
59
|
+
}, isMissingPreKeysUserResultPreferred);
|
|
52
60
|
continue;
|
|
53
61
|
}
|
|
54
|
-
parsedByJid
|
|
62
|
+
registerParsedResultByRawAndCanonicalKey(parsedByJid, parsedByCanonicalJid, userJid, canonicalUserJid, {
|
|
55
63
|
userJid,
|
|
56
|
-
devices: this.parseUserDevices(userNode,
|
|
57
|
-
});
|
|
64
|
+
devices: this.parseUserDevices(userNode, canonicalUserJid)
|
|
65
|
+
}, isMissingPreKeysUserResultPreferred);
|
|
58
66
|
}
|
|
59
67
|
const results = new Array(requestedTargets.length);
|
|
60
68
|
for (let index = 0; index < requestedTargets.length; index += 1) {
|
|
61
69
|
const target = requestedTargets[index];
|
|
62
|
-
results[index] = parsedByJid.get(target.userJid) ??
|
|
70
|
+
results[index] = parsedByJid.get(target.userJid) ??
|
|
71
|
+
parsedByCanonicalJid.get(toUserJid(target.userJid, {
|
|
72
|
+
canonicalizeSignalServer: true
|
|
73
|
+
})) ?? {
|
|
63
74
|
userJid: target.userJid,
|
|
64
75
|
errorText: 'missing user in key_fetch response'
|
|
65
76
|
};
|
|
@@ -10,11 +10,13 @@ export class SignalRotateKeyApi {
|
|
|
10
10
|
this.defaultTimeoutMs = options.defaultTimeoutMs ?? WA_DEFAULTS.IQ_TIMEOUT_MS;
|
|
11
11
|
}
|
|
12
12
|
async rotateSignedPreKey(timeoutMs = this.defaultTimeoutMs) {
|
|
13
|
-
const registrationInfo = await
|
|
13
|
+
const [registrationInfo, currentSignedPreKey] = await Promise.all([
|
|
14
|
+
this.signalStore.getRegistrationInfo(),
|
|
15
|
+
this.signalStore.getSignedPreKey()
|
|
16
|
+
]);
|
|
14
17
|
if (!registrationInfo) {
|
|
15
18
|
throw new Error('signal rotate key requires registration info');
|
|
16
19
|
}
|
|
17
|
-
const currentSignedPreKey = await this.signalStore.getSignedPreKey();
|
|
18
20
|
const nextSignedPreKey = await generateSignedPreKey(currentSignedPreKey ? currentSignedPreKey.keyId + 1 : 1, registrationInfo.identityKeyPair.privKey);
|
|
19
21
|
await this.signalStore.setSignedPreKey(nextSignedPreKey);
|
|
20
22
|
this.logger.info('signal signed prekey uploading', {
|
|
@@ -1,8 +1,13 @@
|
|
|
1
1
|
import { WA_DEFAULTS, WA_IQ_TYPES, WA_NODE_TAGS, WA_XMLNS } from '../../protocol/constants.js';
|
|
2
|
+
import { canonicalizeSignalJid } from '../../protocol/jid.js';
|
|
2
3
|
import { decodeExactLength, parseUint } from '../api/codec.js';
|
|
3
4
|
import { SIGNAL_KEY_DATA_LENGTH, SIGNAL_KEY_ID_LENGTH, SIGNAL_REGISTRATION_ID_LENGTH, SIGNAL_SIGNATURE_LENGTH } from '../api/constants.js';
|
|
5
|
+
import { registerParsedResultByRawAndCanonicalKey } from '../api/result-map.js';
|
|
4
6
|
import { findNodeChild, getNodeChildrenByTag, decodeNodeContentBase64OrBytes } from '../../transport/node/helpers.js';
|
|
5
7
|
import { assertIqResult } from '../../transport/node/query.js';
|
|
8
|
+
function isKeyBundleResultPreferred(result) {
|
|
9
|
+
return 'bundle' in result;
|
|
10
|
+
}
|
|
6
11
|
export class SignalSessionSyncApi {
|
|
7
12
|
constructor(options) {
|
|
8
13
|
this.logger = options.logger;
|
|
@@ -41,9 +46,11 @@ export class SignalSessionSyncApi {
|
|
|
41
46
|
reasonIdentity: (previous?.reasonIdentity ?? false) || target.reasonIdentity === true
|
|
42
47
|
});
|
|
43
48
|
}
|
|
44
|
-
const mergedTargets =
|
|
49
|
+
const mergedTargets = new Array(targetByJid.size);
|
|
50
|
+
let mergedTargetsCount = 0;
|
|
45
51
|
for (const target of targetByJid.values()) {
|
|
46
|
-
mergedTargets
|
|
52
|
+
mergedTargets[mergedTargetsCount] = target;
|
|
53
|
+
mergedTargetsCount += 1;
|
|
47
54
|
}
|
|
48
55
|
const userNodes = new Array(mergedTargets.length);
|
|
49
56
|
for (let index = 0; index < mergedTargets.length; index += 1) {
|
|
@@ -87,6 +94,7 @@ export class SignalSessionSyncApi {
|
|
|
87
94
|
throw new Error('key bundle response list is empty');
|
|
88
95
|
}
|
|
89
96
|
const parsedByJid = new Map();
|
|
97
|
+
const parsedByCanonicalJid = new Map();
|
|
90
98
|
for (let index = 0; index < userNodes.length; index += 1) {
|
|
91
99
|
const userNode = userNodes[index];
|
|
92
100
|
const jid = userNode.attrs.jid;
|
|
@@ -95,24 +103,25 @@ export class SignalSessionSyncApi {
|
|
|
95
103
|
}
|
|
96
104
|
const userErrorNode = findNodeChild(userNode, WA_NODE_TAGS.ERROR);
|
|
97
105
|
if (userErrorNode) {
|
|
98
|
-
parsedByJid
|
|
106
|
+
registerParsedResultByRawAndCanonicalKey(parsedByJid, parsedByCanonicalJid, jid, canonicalizeSignalJid(jid, this.hostDomain), {
|
|
99
107
|
jid,
|
|
100
108
|
errorCode: userErrorNode.attrs.code,
|
|
101
109
|
errorText: userErrorNode.attrs.text ?? 'unknown'
|
|
102
|
-
});
|
|
110
|
+
}, isKeyBundleResultPreferred);
|
|
103
111
|
continue;
|
|
104
112
|
}
|
|
105
113
|
const parsed = this.parseUserKeyBundle(userNode);
|
|
106
|
-
parsedByJid
|
|
114
|
+
registerParsedResultByRawAndCanonicalKey(parsedByJid, parsedByCanonicalJid, jid, canonicalizeSignalJid(jid, this.hostDomain), {
|
|
107
115
|
jid,
|
|
108
116
|
bundle: parsed.bundle,
|
|
109
117
|
...(parsed.deviceIdentity ? { deviceIdentity: parsed.deviceIdentity } : {})
|
|
110
|
-
});
|
|
118
|
+
}, isKeyBundleResultPreferred);
|
|
111
119
|
}
|
|
112
120
|
const output = new Array(requestedTargets.length);
|
|
113
121
|
for (let index = 0; index < requestedTargets.length; index += 1) {
|
|
114
122
|
const target = requestedTargets[index];
|
|
115
|
-
output[index] = parsedByJid.get(target.jid) ??
|
|
123
|
+
output[index] = parsedByJid.get(target.jid) ??
|
|
124
|
+
parsedByCanonicalJid.get(canonicalizeSignalJid(target.jid, this.hostDomain)) ?? {
|
|
116
125
|
jid: target.jid,
|
|
117
126
|
errorText: 'missing key bundle user in response'
|
|
118
127
|
};
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
function mergePreferredParsedResult(target, key, next, isPreferred) {
|
|
2
|
+
const current = target.get(key);
|
|
3
|
+
if (!current || !isPreferred(current)) {
|
|
4
|
+
target.set(key, next);
|
|
5
|
+
}
|
|
6
|
+
}
|
|
7
|
+
export function registerParsedResultByRawAndCanonicalKey(parsedByRawKey, parsedByCanonicalKey, rawKey, canonicalKey, result, isPreferred) {
|
|
8
|
+
mergePreferredParsedResult(parsedByRawKey, rawKey, result, isPreferred);
|
|
9
|
+
mergePreferredParsedResult(parsedByCanonicalKey, canonicalKey, result, isPreferred);
|
|
10
|
+
}
|
|
@@ -1,11 +1,7 @@
|
|
|
1
|
-
import { SERIALIZED_PUB_KEY_PREFIX as CORE_SERIALIZED_PUB_KEY_PREFIX } from '../crypto/core/constants.js';
|
|
2
1
|
import { TEXT_ENCODER } from '../util/bytes.js';
|
|
3
2
|
export const SIGNAL_VERSION = 3;
|
|
4
3
|
export const SIGNAL_GROUP_VERSION = 3;
|
|
5
|
-
export const SERIALIZED_PUB_KEY_PREFIX = CORE_SERIALIZED_PUB_KEY_PREFIX;
|
|
6
|
-
export const KEY_TYPE_CURVE25519 = 5;
|
|
7
4
|
export const SIGNAL_MAC_SIZE = 8;
|
|
8
|
-
export const SIGNATURE_SIZE = 64;
|
|
9
5
|
export const MAX_PREV_SESSIONS = 40;
|
|
10
6
|
export const MAX_UNUSED_KEYS = 2000;
|
|
11
7
|
export const FUTURE_MESSAGES_MAX = 2000;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Ed25519, importHmacKey, hmacSign, randomBytesAsync, sha512, toRawPubKey } from '../../crypto/index.js';
|
|
2
2
|
import { clampCurvePrivateKeyInPlace, montgomeryToEdwardsPublic } from '../../crypto/curves/X25519.js';
|
|
3
3
|
import { encodeExtendedPoint, scalarMultBase } from '../../crypto/math/edwards.js';
|
|
4
4
|
import { bytesToBigIntLE, bigIntToBytesLE } from '../../crypto/math/le.js';
|
|
@@ -7,18 +7,24 @@ import { ADV_PREFIX_ACCOUNT_SIGNATURE, ADV_PREFIX_DEVICE_SIGNATURE, ADV_PREFIX_H
|
|
|
7
7
|
import { assertByteLength, concatBytes } from '../../util/bytes.js';
|
|
8
8
|
export { ADV_PREFIX_ACCOUNT_SIGNATURE, ADV_PREFIX_DEVICE_SIGNATURE, ADV_PREFIX_HOSTED_ACCOUNT_SIGNATURE, ADV_PREFIX_HOSTED_DEVICE_SIGNATURE } from '../crypto/constants.js';
|
|
9
9
|
export async function verifySignalSignature(publicKey, message, signature) {
|
|
10
|
-
if (
|
|
10
|
+
if (signature.length !== 64) {
|
|
11
11
|
return false;
|
|
12
12
|
}
|
|
13
13
|
if ((signature[63] & 0x60) !== 0) {
|
|
14
14
|
return false;
|
|
15
15
|
}
|
|
16
|
-
const
|
|
17
|
-
const
|
|
18
|
-
|
|
16
|
+
const signatureLastByteIndex = 63;
|
|
17
|
+
const originalSignatureLastByte = signature[signatureLastByteIndex];
|
|
18
|
+
const signBit = originalSignatureLastByte & 0x80;
|
|
19
|
+
signature[signatureLastByteIndex] = originalSignatureLastByte & 0x7f;
|
|
19
20
|
const curvePublic = toRawPubKey(publicKey);
|
|
20
21
|
const edPublic = montgomeryToEdwardsPublic(curvePublic, signBit);
|
|
21
|
-
|
|
22
|
+
try {
|
|
23
|
+
return await Ed25519.verify(message, signature, edPublic);
|
|
24
|
+
}
|
|
25
|
+
finally {
|
|
26
|
+
signature[signatureLastByteIndex] = originalSignatureLastByte;
|
|
27
|
+
}
|
|
22
28
|
}
|
|
23
29
|
export async function signSignalMessage(privateKey, message) {
|
|
24
30
|
assertByteLength(privateKey, 32, `invalid curve25519 private key length ${privateKey.length}`);
|