zapo-js 0.1.0 → 0.1.2
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 -7
- package/dist/appstate/WaAppStateCrypto.js +18 -25
- package/dist/appstate/WaAppStateSyncClient.js +181 -114
- package/dist/appstate/WaAppStateSyncResponseParser.js +16 -5
- package/dist/appstate/constants.js +4 -3
- package/dist/appstate/utils.js +10 -30
- package/dist/auth/WaAuthClient.js +48 -55
- package/dist/auth/flow/WaAuthCredentialsFlow.js +21 -14
- package/dist/auth/index.js +1 -3
- package/dist/auth/pairing/WaPairingFlow.js +21 -23
- package/dist/auth/pairing/WaQrFlow.js +37 -24
- package/dist/client/WaClient.js +103 -276
- package/dist/client/WaClientFactory.js +227 -110
- package/dist/client/connection/WaConnectionManager.js +292 -0
- package/dist/client/connection/WaKeyShareCoordinator.js +63 -0
- package/dist/client/connection/WaReceiptQueue.js +51 -0
- package/dist/client/coordinators/WaAppStateMutationCoordinator.js +471 -0
- package/dist/client/coordinators/WaGroupCoordinator.js +27 -17
- package/dist/client/coordinators/WaIncomingNodeCoordinator.js +20 -27
- package/dist/client/coordinators/WaMessageDispatchCoordinator.js +231 -686
- package/dist/client/coordinators/WaRetryCoordinator.js +70 -37
- package/dist/client/dirty.js +35 -29
- package/dist/client/events/chat.js +4 -3
- package/dist/client/events/group.js +59 -36
- package/dist/client/history-sync.js +53 -63
- package/dist/client/incoming.js +23 -20
- package/dist/client/mailbox.js +8 -8
- package/dist/client/messages.js +4 -4
- package/dist/client/messaging/fanout.js +189 -0
- package/dist/client/messaging/key-protocol.js +130 -0
- package/dist/client/messaging/participants.js +191 -0
- package/dist/crypto/core/hkdf.js +3 -8
- package/dist/crypto/core/index.js +1 -4
- package/dist/crypto/core/keys.js +2 -3
- package/dist/crypto/core/primitives.js +12 -15
- package/dist/crypto/core/random.js +7 -26
- package/dist/crypto/curves/Ed25519.js +7 -8
- package/dist/crypto/curves/X25519.js +13 -16
- package/dist/crypto/index.js +0 -5
- package/dist/esm/appstate/WaAppStateCrypto.js +6 -13
- package/dist/esm/appstate/WaAppStateSyncClient.js +174 -107
- package/dist/esm/appstate/WaAppStateSyncResponseParser.js +17 -6
- package/dist/esm/appstate/constants.js +3 -2
- package/dist/esm/appstate/utils.js +8 -27
- package/dist/esm/auth/WaAuthClient.js +48 -55
- package/dist/esm/auth/flow/WaAuthCredentialsFlow.js +21 -14
- package/dist/esm/auth/index.js +0 -1
- package/dist/esm/auth/pairing/WaPairingFlow.js +14 -16
- package/dist/esm/auth/pairing/WaQrFlow.js +37 -24
- package/dist/esm/client/WaClient.js +103 -276
- package/dist/esm/client/WaClientFactory.js +227 -110
- package/dist/esm/client/connection/WaConnectionManager.js +288 -0
- package/dist/esm/client/connection/WaKeyShareCoordinator.js +59 -0
- package/dist/esm/client/connection/WaReceiptQueue.js +47 -0
- package/dist/esm/client/coordinators/WaAppStateMutationCoordinator.js +467 -0
- package/dist/esm/client/coordinators/WaGroupCoordinator.js +20 -10
- package/dist/esm/client/coordinators/WaIncomingNodeCoordinator.js +20 -27
- package/dist/esm/client/coordinators/WaMessageDispatchCoordinator.js +232 -687
- package/dist/esm/client/coordinators/WaRetryCoordinator.js +71 -38
- package/dist/esm/client/dirty.js +30 -24
- package/dist/esm/client/events/chat.js +4 -3
- package/dist/esm/client/events/group.js +50 -28
- package/dist/esm/client/history-sync.js +50 -60
- package/dist/esm/client/incoming.js +23 -20
- package/dist/esm/client/mailbox.js +8 -8
- package/dist/esm/client/messages.js +1 -1
- package/dist/esm/client/messaging/fanout.js +186 -0
- package/dist/esm/client/messaging/key-protocol.js +127 -0
- package/dist/esm/client/messaging/participants.js +188 -0
- package/dist/esm/crypto/core/hkdf.js +3 -8
- package/dist/esm/crypto/core/index.js +0 -1
- package/dist/esm/crypto/core/keys.js +2 -3
- package/dist/esm/crypto/core/primitives.js +12 -15
- package/dist/esm/crypto/core/random.js +6 -25
- package/dist/esm/crypto/curves/Ed25519.js +4 -5
- package/dist/esm/crypto/curves/X25519.js +10 -13
- package/dist/esm/crypto/index.js +0 -2
- package/dist/esm/infra/log/ConsoleLogger.js +18 -17
- package/dist/esm/infra/log/PinoLogger.js +15 -9
- package/dist/esm/infra/log/types.js +11 -1
- package/dist/esm/infra/perf/BoundedTaskQueue.js +13 -17
- package/dist/esm/media/WaMediaCrypto.js +2 -4
- package/dist/esm/media/WaMediaTransferClient.js +226 -58
- package/dist/esm/media/conn.js +10 -6
- package/dist/esm/media/constants.js +4 -1
- package/dist/esm/message/WaMessageClient.js +4 -13
- package/dist/esm/message/ack.js +6 -6
- package/dist/esm/message/addon-crypto.js +59 -0
- package/dist/esm/message/incoming.js +106 -111
- package/dist/esm/message/index.js +2 -0
- package/dist/esm/message/reporting-token.js +438 -0
- package/dist/esm/message/use-case-secret.js +49 -0
- package/dist/esm/protocol/appstate.js +58 -0
- package/dist/esm/protocol/constants.js +2 -1
- package/dist/esm/protocol/index.js +2 -10
- package/dist/esm/protocol/jid.js +63 -51
- package/dist/esm/protocol/media.js +3 -3
- package/dist/esm/protocol/nodes.js +2 -0
- package/dist/esm/protocol/usync.js +11 -0
- package/dist/esm/retry/index.js +1 -0
- package/dist/esm/retry/outbound.js +4 -5
- package/dist/esm/retry/parse.js +58 -76
- package/dist/esm/retry/replay.js +48 -49
- package/dist/esm/retry/tracker.js +56 -0
- package/dist/esm/signal/api/SignalDeviceSyncApi.js +249 -82
- package/dist/esm/signal/api/SignalDigestSyncApi.js +6 -1
- package/dist/esm/signal/api/SignalIdentitySyncApi.js +49 -34
- package/dist/esm/signal/api/SignalMissingPreKeysSyncApi.js +70 -62
- package/dist/esm/signal/api/SignalSessionSyncApi.js +23 -30
- package/dist/esm/signal/crypto/WaAdvSignature.js +3 -5
- package/dist/esm/signal/group/SenderKeyChain.js +28 -23
- package/dist/esm/signal/group/SenderKeyCodec.js +2 -4
- package/dist/esm/signal/group/SenderKeyManager.js +26 -16
- package/dist/esm/signal/index.js +1 -0
- package/dist/esm/signal/session/SignalProtocol.js +49 -14
- package/dist/esm/signal/session/SignalRatchet.js +24 -15
- package/dist/esm/signal/session/SignalSession.js +14 -9
- package/dist/esm/signal/session/resolver.js +186 -0
- package/dist/esm/signal/store/sqlite.js +16 -37
- package/dist/esm/store/createStore.js +16 -18
- package/dist/esm/store/noop.store.js +3 -6
- package/dist/esm/store/providers/memory/appstate.store.js +30 -6
- package/dist/esm/store/providers/memory/contact.store.js +5 -0
- package/dist/esm/store/providers/memory/device-list.store.js +3 -30
- package/dist/esm/store/providers/memory/message.store.js +11 -5
- package/dist/esm/store/providers/memory/participants.store.js +1 -8
- package/dist/esm/store/providers/memory/sender-key.store.js +5 -7
- package/dist/esm/store/providers/memory/signal.store.js +13 -1
- package/dist/esm/store/providers/memory/thread.store.js +5 -0
- package/dist/esm/store/providers/sqlite/appstate.store.js +82 -1
- package/dist/esm/store/providers/sqlite/connection.js +18 -13
- package/dist/esm/store/providers/sqlite/contact.store.js +31 -18
- package/dist/esm/store/providers/sqlite/device-list.store.js +7 -35
- package/dist/esm/store/providers/sqlite/message.store.js +45 -32
- package/dist/esm/store/providers/sqlite/migrations.js +1 -1
- package/dist/esm/store/providers/sqlite/participants.store.js +1 -9
- package/dist/esm/store/providers/sqlite/retry.store.js +8 -11
- package/dist/esm/store/providers/sqlite/sender-key.store.js +25 -30
- package/dist/esm/store/providers/sqlite/signal.store.js +104 -22
- package/dist/esm/store/providers/sqlite/table-names.js +107 -0
- package/dist/esm/store/providers/sqlite/thread.store.js +35 -22
- package/dist/esm/transport/WaComms.js +25 -23
- package/dist/esm/transport/WaWebSocket.js +115 -12
- package/dist/esm/transport/binary/decoder.js +4 -4
- package/dist/esm/transport/binary/encoder.js +12 -4
- package/dist/esm/transport/index.js +1 -0
- package/dist/esm/transport/keepalive/WaKeepAlive.js +2 -8
- package/dist/esm/transport/node/WaNodeOrchestrator.js +2 -4
- package/dist/esm/transport/node/WaNodeTransport.js +0 -3
- package/dist/esm/transport/node/builders/{accountSync.js → account-sync.js} +16 -36
- package/dist/esm/transport/node/builders/index.js +2 -1
- package/dist/esm/transport/node/builders/message.js +9 -0
- package/dist/esm/transport/node/builders/pairing.js +4 -5
- package/dist/esm/transport/node/builders/usync.js +41 -0
- package/dist/esm/transport/node/helpers.js +107 -5
- package/dist/esm/transport/node/usync.js +35 -0
- package/dist/esm/transport/noise/WaFrameCodec.js +48 -33
- package/dist/esm/transport/noise/WaNoiseCert.js +3 -6
- package/dist/esm/transport/noise/WaNoiseSession.js +17 -10
- package/dist/esm/transport/proxy.js +27 -0
- package/dist/esm/transport/stream/parse.js +13 -48
- package/dist/esm/util/bytes.js +50 -32
- package/dist/esm/util/coercion.js +6 -14
- package/dist/esm/util/primitives.js +39 -14
- package/dist/infra/log/ConsoleLogger.js +18 -17
- package/dist/infra/log/PinoLogger.js +15 -9
- package/dist/infra/log/types.js +12 -0
- package/dist/infra/perf/BoundedTaskQueue.js +13 -17
- package/dist/media/WaMediaCrypto.js +1 -3
- package/dist/media/WaMediaTransferClient.js +259 -58
- package/dist/media/conn.js +10 -6
- package/dist/media/constants.js +4 -1
- package/dist/message/WaMessageClient.js +5 -14
- package/dist/message/ack.js +6 -6
- package/dist/message/addon-crypto.js +65 -0
- package/dist/message/incoming.js +104 -109
- package/dist/message/index.js +2 -0
- package/dist/message/reporting-token.js +443 -0
- package/dist/message/use-case-secret.js +55 -0
- package/dist/protocol/appstate.js +59 -1
- package/dist/protocol/constants.js +7 -1
- package/dist/protocol/index.js +20 -42
- package/dist/protocol/jid.js +64 -51
- package/dist/protocol/media.js +3 -3
- package/dist/protocol/nodes.js +2 -0
- package/dist/protocol/usync.js +14 -0
- package/dist/retry/index.js +3 -1
- package/dist/retry/outbound.js +6 -7
- package/dist/retry/parse.js +57 -75
- package/dist/retry/replay.js +46 -47
- package/dist/retry/tracker.js +59 -0
- package/dist/signal/api/SignalDeviceSyncApi.js +247 -80
- package/dist/signal/api/SignalDigestSyncApi.js +6 -1
- package/dist/signal/api/SignalIdentitySyncApi.js +49 -34
- package/dist/signal/api/SignalMissingPreKeysSyncApi.js +67 -59
- package/dist/signal/api/SignalSessionSyncApi.js +23 -30
- package/dist/signal/crypto/WaAdvSignature.js +2 -4
- package/dist/signal/group/SenderKeyChain.js +27 -22
- package/dist/signal/group/SenderKeyCodec.js +1 -3
- package/dist/signal/group/SenderKeyManager.js +26 -16
- package/dist/signal/index.js +3 -1
- package/dist/signal/session/SignalProtocol.js +49 -14
- package/dist/signal/session/SignalRatchet.js +24 -15
- package/dist/signal/session/SignalSession.js +14 -9
- package/dist/signal/session/resolver.js +189 -0
- package/dist/signal/store/sqlite.js +16 -37
- package/dist/store/createStore.js +16 -18
- package/dist/store/noop.store.js +3 -6
- package/dist/store/providers/memory/appstate.store.js +28 -4
- package/dist/store/providers/memory/contact.store.js +5 -0
- package/dist/store/providers/memory/device-list.store.js +3 -30
- package/dist/store/providers/memory/message.store.js +11 -5
- package/dist/store/providers/memory/participants.store.js +1 -8
- package/dist/store/providers/memory/sender-key.store.js +8 -10
- package/dist/store/providers/memory/signal.store.js +21 -9
- package/dist/store/providers/memory/thread.store.js +5 -0
- package/dist/store/providers/sqlite/appstate.store.js +81 -0
- package/dist/store/providers/sqlite/connection.js +18 -13
- package/dist/store/providers/sqlite/contact.store.js +31 -18
- package/dist/store/providers/sqlite/device-list.store.js +7 -35
- package/dist/store/providers/sqlite/message.store.js +45 -32
- package/dist/store/providers/sqlite/migrations.js +1 -1
- package/dist/store/providers/sqlite/participants.store.js +1 -9
- package/dist/store/providers/sqlite/retry.store.js +8 -11
- package/dist/store/providers/sqlite/sender-key.store.js +24 -29
- package/dist/store/providers/sqlite/signal.store.js +105 -23
- package/dist/store/providers/sqlite/table-names.js +113 -0
- package/dist/store/providers/sqlite/thread.store.js +35 -22
- package/dist/transport/WaComms.js +27 -25
- package/dist/transport/WaWebSocket.js +148 -12
- package/dist/transport/binary/decoder.js +4 -4
- package/dist/transport/binary/encoder.js +12 -4
- package/dist/transport/index.js +7 -1
- package/dist/transport/keepalive/WaKeepAlive.js +1 -7
- package/dist/transport/node/WaNodeOrchestrator.js +2 -4
- package/dist/transport/node/WaNodeTransport.js +0 -3
- package/dist/transport/node/builders/{accountSync.js → account-sync.js} +15 -35
- package/dist/transport/node/builders/index.js +12 -9
- package/dist/transport/node/builders/message.js +9 -0
- package/dist/transport/node/builders/pairing.js +4 -5
- package/dist/transport/node/builders/usync.js +45 -0
- package/dist/transport/node/helpers.js +112 -4
- package/dist/transport/node/usync.js +38 -0
- package/dist/transport/noise/WaFrameCodec.js +47 -32
- package/dist/transport/noise/WaNoiseCert.js +5 -8
- package/dist/transport/noise/WaNoiseSession.js +17 -10
- package/dist/transport/proxy.js +34 -0
- package/dist/transport/stream/parse.js +17 -53
- package/dist/types/appstate/WaAppStateCrypto.d.ts +0 -1
- package/dist/types/appstate/WaAppStateSyncClient.d.ts +5 -2
- package/dist/types/appstate/constants.d.ts +1 -0
- package/dist/types/appstate/store/sqlite.d.ts +4 -18
- package/dist/types/appstate/utils.d.ts +0 -1
- package/dist/types/auth/WaAuthClient.d.ts +10 -12
- package/dist/types/auth/index.d.ts +0 -2
- package/dist/types/auth/pairing/WaQrFlow.d.ts +1 -1
- package/dist/types/auth/types.d.ts +6 -9
- package/dist/types/client/WaClient.d.ts +27 -25
- package/dist/types/client/WaClientFactory.d.ts +22 -23
- package/dist/types/client/connection/WaConnectionManager.d.ts +64 -0
- package/dist/types/client/connection/WaKeyShareCoordinator.d.ts +14 -0
- package/dist/types/client/connection/WaReceiptQueue.d.ts +13 -0
- package/dist/types/client/coordinators/WaAppStateMutationCoordinator.d.ts +46 -0
- package/dist/types/client/coordinators/WaIncomingNodeCoordinator.d.ts +0 -1
- package/dist/types/client/coordinators/WaMessageDispatchCoordinator.d.ts +18 -41
- package/dist/types/client/coordinators/WaRetryCoordinator.d.ts +2 -0
- package/dist/types/client/dirty.d.ts +1 -0
- package/dist/types/client/events/group.d.ts +2 -1
- package/dist/types/client/index.d.ts +1 -1
- package/dist/types/client/messaging/fanout.d.ts +14 -0
- package/dist/types/client/messaging/key-protocol.d.ts +18 -0
- package/dist/types/client/messaging/participants.d.ts +13 -0
- package/dist/types/client/types.d.ts +24 -1
- package/dist/types/crypto/core/hkdf.d.ts +0 -6
- package/dist/types/crypto/core/index.d.ts +0 -1
- package/dist/types/crypto/core/random.d.ts +1 -7
- package/dist/types/crypto/index.d.ts +0 -2
- package/dist/types/index.d.ts +1 -1
- package/dist/types/infra/log/ConsoleLogger.d.ts +2 -1
- package/dist/types/infra/log/PinoLogger.d.ts +1 -1
- package/dist/types/infra/log/types.d.ts +1 -0
- package/dist/types/infra/perf/BoundedTaskQueue.d.ts +1 -1
- package/dist/types/media/WaMediaTransferClient.d.ts +13 -3
- package/dist/types/media/types.d.ts +5 -0
- package/dist/types/message/addon-crypto.d.ts +25 -0
- package/dist/types/message/index.d.ts +2 -0
- package/dist/types/message/reporting-token.d.ts +19 -0
- package/dist/types/message/use-case-secret.d.ts +20 -0
- package/dist/types/protocol/appstate.d.ts +58 -0
- package/dist/types/protocol/constants.d.ts +2 -1
- package/dist/types/protocol/index.d.ts +2 -10
- package/dist/types/protocol/jid.d.ts +3 -3
- package/dist/types/protocol/nodes.d.ts +2 -0
- package/dist/types/protocol/usync.d.ts +11 -0
- package/dist/types/retry/index.d.ts +1 -0
- package/dist/types/retry/replay.d.ts +0 -4
- package/dist/types/retry/tracker.d.ts +19 -0
- package/dist/types/retry/types.d.ts +4 -3
- package/dist/types/signal/api/SignalDeviceSyncApi.d.ts +13 -1
- package/dist/types/signal/group/SenderKeyCodec.d.ts +4 -6
- package/dist/types/signal/index.d.ts +1 -0
- package/dist/types/signal/session/SignalProtocol.d.ts +9 -0
- package/dist/types/signal/session/resolver.d.ts +17 -0
- package/dist/types/store/contracts/appstate.store.d.ts +3 -0
- package/dist/types/store/contracts/contact.store.d.ts +1 -0
- package/dist/types/store/contracts/device-list.store.d.ts +0 -3
- package/dist/types/store/contracts/message.store.d.ts +1 -0
- package/dist/types/store/contracts/participants.store.d.ts +0 -1
- package/dist/types/store/contracts/sender-key.store.d.ts +0 -1
- package/dist/types/store/contracts/signal.store.d.ts +6 -0
- package/dist/types/store/contracts/thread.store.d.ts +1 -0
- package/dist/types/store/index.d.ts +1 -1
- package/dist/types/store/providers/memory/appstate.store.d.ts +2 -0
- package/dist/types/store/providers/memory/contact.store.d.ts +1 -0
- package/dist/types/store/providers/memory/device-list.store.d.ts +0 -3
- package/dist/types/store/providers/memory/message.store.d.ts +1 -0
- package/dist/types/store/providers/memory/participants.store.d.ts +0 -1
- package/dist/types/store/providers/memory/sender-key.store.d.ts +0 -1
- package/dist/types/store/providers/memory/signal.store.d.ts +6 -0
- package/dist/types/store/providers/memory/thread.store.d.ts +1 -0
- package/dist/types/store/providers/sqlite/appstate.store.d.ts +2 -0
- package/dist/types/store/providers/sqlite/contact.store.d.ts +2 -0
- package/dist/types/store/providers/sqlite/device-list.store.d.ts +0 -3
- package/dist/types/store/providers/sqlite/message.store.d.ts +2 -0
- package/dist/types/store/providers/sqlite/participants.store.d.ts +0 -1
- package/dist/types/store/providers/sqlite/retry.store.d.ts +0 -1
- package/dist/types/store/providers/sqlite/sender-key.store.d.ts +0 -1
- package/dist/types/store/providers/sqlite/signal.store.d.ts +7 -0
- package/dist/types/store/providers/sqlite/table-names.d.ts +5 -0
- package/dist/types/store/providers/sqlite/thread.store.d.ts +2 -0
- package/dist/types/store/types.d.ts +3 -0
- package/dist/types/transport/WaWebSocket.d.ts +3 -0
- package/dist/types/transport/index.d.ts +2 -1
- package/dist/types/transport/keepalive/WaKeepAlive.d.ts +0 -1
- package/dist/types/transport/node/WaNodeTransport.d.ts +0 -9
- package/dist/types/transport/node/builders/group.d.ts +4 -6
- package/dist/types/transport/node/builders/index.d.ts +2 -1
- package/dist/types/transport/node/builders/message.d.ts +14 -25
- package/dist/types/transport/node/builders/retry.d.ts +2 -4
- package/dist/types/transport/node/builders/usync.d.ts +21 -0
- package/dist/types/transport/node/helpers.d.ts +8 -0
- package/dist/types/transport/node/usync.d.ts +2 -0
- package/dist/types/transport/noise/WaFrameCodec.d.ts +3 -0
- package/dist/types/transport/noise/WaNoiseSession.d.ts +1 -0
- package/dist/types/transport/proxy.d.ts +6 -0
- package/dist/types/transport/stream/parse.d.ts +0 -1
- package/dist/types/transport/types.d.ts +18 -1
- package/dist/types/util/bytes.d.ts +5 -0
- package/dist/types/util/primitives.d.ts +3 -0
- package/dist/util/bytes.js +55 -33
- package/dist/util/coercion.js +6 -14
- package/dist/util/primitives.js +42 -14
- package/package.json +27 -9
- package/proto/index.d.ts +1090 -1048
- package/proto/index.js +1 -1
- package/scripts/check-node-version.cjs +0 -1
- package/dist/crypto/core/encoding.js +0 -29
- package/dist/esm/crypto/core/encoding.js +0 -25
- package/dist/esm/util/base64.js +0 -18
- package/dist/esm/util/signal-address.js +0 -5
- package/dist/types/crypto/core/encoding.d.ts +0 -11
- package/dist/types/util/base64.d.ts +0 -4
- package/dist/types/util/signal-address.d.ts +0 -2
- package/dist/util/base64.js +0 -24
- package/dist/util/signal-address.js +0 -8
- /package/dist/types/transport/node/builders/{accountSync.d.ts → account-sync.d.ts} +0 -0
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
import { toSerializedPubKey } from '../../crypto/core/keys.js';
|
|
2
|
+
import { normalizeDeviceJid, parseSignalAddressFromJid } from '../../protocol/jid.js';
|
|
3
|
+
import { uint8Equal } from '../../util/bytes.js';
|
|
4
|
+
import { toError } from '../../util/primitives.js';
|
|
5
|
+
export function createSignalSessionResolver(options) {
|
|
6
|
+
const { signalProtocol, signalStore, signalIdentitySync, signalSessionSync, logger } = options;
|
|
7
|
+
const ensureSession = async (address, jid, expectedIdentity, reasonIdentity = false) => {
|
|
8
|
+
const expectedSerializedIdentity = expectedIdentity
|
|
9
|
+
? toSerializedPubKey(expectedIdentity)
|
|
10
|
+
: null;
|
|
11
|
+
if (reasonIdentity) {
|
|
12
|
+
await signalIdentitySync.syncIdentityKeys([jid]);
|
|
13
|
+
}
|
|
14
|
+
if (await signalProtocol.hasSession(address)) {
|
|
15
|
+
if (expectedSerializedIdentity) {
|
|
16
|
+
const storedIdentity = await signalStore.getRemoteIdentity(address);
|
|
17
|
+
if (!storedIdentity || !uint8Equal(storedIdentity, expectedSerializedIdentity)) {
|
|
18
|
+
throw new Error('identity mismatch');
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
return;
|
|
22
|
+
}
|
|
23
|
+
logger.info('signal session missing, fetching remote key bundle', { jid });
|
|
24
|
+
const fetched = await signalSessionSync.fetchKeyBundle({
|
|
25
|
+
jid,
|
|
26
|
+
reasonIdentity
|
|
27
|
+
});
|
|
28
|
+
const remoteIdentity = toSerializedPubKey(fetched.bundle.identity);
|
|
29
|
+
if (reasonIdentity) {
|
|
30
|
+
const storedIdentity = await signalStore.getRemoteIdentity(address);
|
|
31
|
+
if (storedIdentity && !uint8Equal(remoteIdentity, storedIdentity)) {
|
|
32
|
+
throw new Error('identity mismatch');
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
if (expectedSerializedIdentity && !uint8Equal(remoteIdentity, expectedSerializedIdentity)) {
|
|
36
|
+
throw new Error('identity mismatch');
|
|
37
|
+
}
|
|
38
|
+
await signalProtocol.establishOutgoingSession(address, fetched.bundle);
|
|
39
|
+
logger.info('signal session synchronized', {
|
|
40
|
+
jid,
|
|
41
|
+
regId: fetched.bundle.regId,
|
|
42
|
+
hasOneTimeKey: fetched.bundle.oneTimeKey !== undefined
|
|
43
|
+
});
|
|
44
|
+
};
|
|
45
|
+
const ensureSessionsBatch = async (targetJids, expectedIdentityByJid) => {
|
|
46
|
+
const seenTargetJids = new Set();
|
|
47
|
+
const normalizedTargetJids = [];
|
|
48
|
+
const normalizedTargetAddresses = [];
|
|
49
|
+
for (let index = 0; index < targetJids.length; index += 1) {
|
|
50
|
+
const jid = normalizeDeviceJid(targetJids[index]);
|
|
51
|
+
if (seenTargetJids.has(jid)) {
|
|
52
|
+
continue;
|
|
53
|
+
}
|
|
54
|
+
seenTargetJids.add(jid);
|
|
55
|
+
normalizedTargetJids.push(jid);
|
|
56
|
+
normalizedTargetAddresses.push(parseSignalAddressFromJid(jid));
|
|
57
|
+
}
|
|
58
|
+
if (normalizedTargetJids.length === 0) {
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
const normalizedExpectedIdentityByJid = expectedIdentityByJid && expectedIdentityByJid.size > 0
|
|
62
|
+
? new Map()
|
|
63
|
+
: undefined;
|
|
64
|
+
if (normalizedExpectedIdentityByJid && expectedIdentityByJid) {
|
|
65
|
+
for (const [jid, identity] of expectedIdentityByJid.entries()) {
|
|
66
|
+
try {
|
|
67
|
+
normalizedExpectedIdentityByJid.set(normalizeDeviceJid(jid), identity);
|
|
68
|
+
}
|
|
69
|
+
catch (error) {
|
|
70
|
+
logger.trace('ignoring malformed expected identity jid during batch normalization', { jid, message: toError(error).message });
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
const hasSessions = await signalProtocol.hasSessions(normalizedTargetAddresses);
|
|
75
|
+
if (normalizedExpectedIdentityByJid) {
|
|
76
|
+
const identityAddresses = [];
|
|
77
|
+
const expectedSerializedIdentities = [];
|
|
78
|
+
for (let index = 0; index < normalizedTargetJids.length; index += 1) {
|
|
79
|
+
if (!hasSessions[index]) {
|
|
80
|
+
continue;
|
|
81
|
+
}
|
|
82
|
+
const expectedIdentity = normalizedExpectedIdentityByJid.get(normalizedTargetJids[index]);
|
|
83
|
+
if (!expectedIdentity) {
|
|
84
|
+
continue;
|
|
85
|
+
}
|
|
86
|
+
identityAddresses.push(normalizedTargetAddresses[index]);
|
|
87
|
+
expectedSerializedIdentities.push(toSerializedPubKey(expectedIdentity));
|
|
88
|
+
}
|
|
89
|
+
const storedIdentities = await signalStore.getRemoteIdentities(identityAddresses);
|
|
90
|
+
for (let index = 0; index < storedIdentities.length; index += 1) {
|
|
91
|
+
const storedIdentity = storedIdentities[index];
|
|
92
|
+
if (!storedIdentity ||
|
|
93
|
+
!uint8Equal(storedIdentity, expectedSerializedIdentities[index])) {
|
|
94
|
+
throw new Error('identity mismatch');
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
const missingIndices = [];
|
|
99
|
+
for (let index = 0; index < normalizedTargetJids.length; index += 1) {
|
|
100
|
+
if (!hasSessions[index]) {
|
|
101
|
+
missingIndices.push(index);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
if (missingIndices.length === 0) {
|
|
105
|
+
return;
|
|
106
|
+
}
|
|
107
|
+
try {
|
|
108
|
+
const batchRequest = [];
|
|
109
|
+
for (let index = 0; index < missingIndices.length; index += 1) {
|
|
110
|
+
batchRequest.push({ jid: normalizedTargetJids[missingIndices[index]] });
|
|
111
|
+
}
|
|
112
|
+
const batchResults = await signalSessionSync.fetchKeyBundles(batchRequest);
|
|
113
|
+
const fallbackIndices = [];
|
|
114
|
+
const establishedIndices = [];
|
|
115
|
+
const establishPromises = [];
|
|
116
|
+
for (let index = 0; index < missingIndices.length; index += 1) {
|
|
117
|
+
const targetIndex = missingIndices[index];
|
|
118
|
+
const result = batchResults[index];
|
|
119
|
+
if (!result || !('bundle' in result)) {
|
|
120
|
+
fallbackIndices.push(targetIndex);
|
|
121
|
+
continue;
|
|
122
|
+
}
|
|
123
|
+
const targetJid = normalizedTargetJids[targetIndex];
|
|
124
|
+
const expectedIdentity = normalizedExpectedIdentityByJid?.get(targetJid);
|
|
125
|
+
const remoteIdentity = toSerializedPubKey(result.bundle.identity);
|
|
126
|
+
if (expectedIdentity &&
|
|
127
|
+
!uint8Equal(remoteIdentity, toSerializedPubKey(expectedIdentity))) {
|
|
128
|
+
throw new Error('identity mismatch');
|
|
129
|
+
}
|
|
130
|
+
establishedIndices.push(targetIndex);
|
|
131
|
+
establishPromises.push(signalProtocol
|
|
132
|
+
.establishOutgoingSession(normalizedTargetAddresses[targetIndex], result.bundle)
|
|
133
|
+
.then(() => {
|
|
134
|
+
logger.debug('signal session synchronized from batch key fetch', {
|
|
135
|
+
jid: targetJid,
|
|
136
|
+
regId: result.bundle.regId,
|
|
137
|
+
hasOneTimeKey: result.bundle.oneTimeKey !== undefined
|
|
138
|
+
});
|
|
139
|
+
}));
|
|
140
|
+
}
|
|
141
|
+
const establishmentResults = await Promise.allSettled(establishPromises);
|
|
142
|
+
for (let index = 0; index < establishmentResults.length; index += 1) {
|
|
143
|
+
const result = establishmentResults[index];
|
|
144
|
+
if (result.status === 'fulfilled') {
|
|
145
|
+
continue;
|
|
146
|
+
}
|
|
147
|
+
const error = toError(result.reason);
|
|
148
|
+
if (error.message === 'identity mismatch') {
|
|
149
|
+
throw error;
|
|
150
|
+
}
|
|
151
|
+
fallbackIndices.push(establishedIndices[index]);
|
|
152
|
+
}
|
|
153
|
+
if (fallbackIndices.length === 0) {
|
|
154
|
+
return;
|
|
155
|
+
}
|
|
156
|
+
logger.warn('signal batch key fetch returned partial errors, falling back to single requests', {
|
|
157
|
+
requested: missingIndices.length,
|
|
158
|
+
fallbackTargets: fallbackIndices.length
|
|
159
|
+
});
|
|
160
|
+
for (let index = 0; index < fallbackIndices.length; index += 1) {
|
|
161
|
+
const targetIndex = fallbackIndices[index];
|
|
162
|
+
const jid = normalizedTargetJids[targetIndex];
|
|
163
|
+
await ensureSession(normalizedTargetAddresses[targetIndex], jid, normalizedExpectedIdentityByJid?.get(jid));
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
catch (error) {
|
|
167
|
+
const normalized = toError(error);
|
|
168
|
+
if (normalized.message === 'identity mismatch') {
|
|
169
|
+
throw normalized;
|
|
170
|
+
}
|
|
171
|
+
logger.warn('signal batch key fetch failed, falling back to single requests', {
|
|
172
|
+
requested: missingIndices.length,
|
|
173
|
+
message: normalized.message
|
|
174
|
+
});
|
|
175
|
+
for (let index = 0; index < missingIndices.length; index += 1) {
|
|
176
|
+
const targetIndex = missingIndices[index];
|
|
177
|
+
const jid = normalizedTargetJids[targetIndex];
|
|
178
|
+
await ensureSession(normalizedTargetAddresses[targetIndex], jid, normalizedExpectedIdentityByJid?.get(jid));
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
};
|
|
182
|
+
return {
|
|
183
|
+
ensureSession,
|
|
184
|
+
ensureSessionsBatch
|
|
185
|
+
};
|
|
186
|
+
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { proto } from '../../proto.js';
|
|
2
2
|
import { WA_DEFAULTS } from '../../protocol/constants.js';
|
|
3
|
+
import { assertByteLength } from '../../util/bytes.js';
|
|
3
4
|
import { asBytes, asNumber, asOptionalBytes, asOptionalNumber, asString, toBoolOrUndef } from '../../util/coercion.js';
|
|
4
5
|
export function toSignalAddressParts(address) {
|
|
5
6
|
return {
|
|
@@ -94,17 +95,11 @@ function encodeSignalRecvChain(chain) {
|
|
|
94
95
|
}
|
|
95
96
|
function decodeSignalMessageKey(messageKey, field) {
|
|
96
97
|
const cipherKey = asBytes(messageKey.cipherKey, `${field}.cipherKey`);
|
|
97
|
-
|
|
98
|
-
throw new Error(`invalid ${field}.cipherKey length ${cipherKey.byteLength}`);
|
|
99
|
-
}
|
|
98
|
+
assertByteLength(cipherKey, 32, `invalid ${field}.cipherKey length ${cipherKey.byteLength}`);
|
|
100
99
|
const macKey = asBytes(messageKey.macKey, `${field}.macKey`);
|
|
101
|
-
|
|
102
|
-
throw new Error(`invalid ${field}.macKey length ${macKey.byteLength}`);
|
|
103
|
-
}
|
|
100
|
+
assertByteLength(macKey, 32, `invalid ${field}.macKey length ${macKey.byteLength}`);
|
|
104
101
|
const iv = asBytes(messageKey.iv, `${field}.iv`);
|
|
105
|
-
|
|
106
|
-
throw new Error(`invalid ${field}.iv length ${iv.byteLength}`);
|
|
107
|
-
}
|
|
102
|
+
assertByteLength(iv, 16, `invalid ${field}.iv length ${iv.byteLength}`);
|
|
108
103
|
return {
|
|
109
104
|
index: asNumber(messageKey.index, `${field}.index`),
|
|
110
105
|
cipherKey,
|
|
@@ -118,13 +113,9 @@ function decodeSignalRecvChain(chain, field) {
|
|
|
118
113
|
throw new Error(`missing ${field}.chainKey`);
|
|
119
114
|
}
|
|
120
115
|
const ratchetPubKey = asBytes(chain.senderRatchetKey, `${field}.senderRatchetKey`);
|
|
121
|
-
|
|
122
|
-
throw new Error(`invalid ${field}.senderRatchetKey length ${ratchetPubKey.byteLength}`);
|
|
123
|
-
}
|
|
116
|
+
assertByteLength(ratchetPubKey, 33, `invalid ${field}.senderRatchetKey length ${ratchetPubKey.byteLength}`);
|
|
124
117
|
const chainKeyBytes = asBytes(chainKey.key, `${field}.chainKey.key`);
|
|
125
|
-
|
|
126
|
-
throw new Error(`invalid ${field}.chainKey.key length ${chainKeyBytes.byteLength}`);
|
|
127
|
-
}
|
|
118
|
+
assertByteLength(chainKeyBytes, 32, `invalid ${field}.chainKey.key length ${chainKeyBytes.byteLength}`);
|
|
128
119
|
return {
|
|
129
120
|
ratchetPubKey,
|
|
130
121
|
nextMsgIndex: asNumber(chainKey.index, `${field}.chainKey.index`),
|
|
@@ -141,17 +132,11 @@ function decodeSignalSendChain(chain, field) {
|
|
|
141
132
|
if (!privateKey) {
|
|
142
133
|
throw new Error(`missing ${field}.senderRatchetKeyPrivate`);
|
|
143
134
|
}
|
|
144
|
-
|
|
145
|
-
throw new Error(`invalid ${field}.senderRatchetKeyPrivate length ${privateKey.byteLength}`);
|
|
146
|
-
}
|
|
135
|
+
assertByteLength(privateKey, 32, `invalid ${field}.senderRatchetKeyPrivate length ${privateKey.byteLength}`);
|
|
147
136
|
const ratchetPubKey = asBytes(chain.senderRatchetKey, `${field}.senderRatchetKey`);
|
|
148
|
-
|
|
149
|
-
throw new Error(`invalid ${field}.senderRatchetKey length ${ratchetPubKey.byteLength}`);
|
|
150
|
-
}
|
|
137
|
+
assertByteLength(ratchetPubKey, 33, `invalid ${field}.senderRatchetKey length ${ratchetPubKey.byteLength}`);
|
|
151
138
|
const chainKeyBytes = asBytes(chainKey.key, `${field}.chainKey.key`);
|
|
152
|
-
|
|
153
|
-
throw new Error(`invalid ${field}.chainKey.key length ${chainKeyBytes.byteLength}`);
|
|
154
|
-
}
|
|
139
|
+
assertByteLength(chainKeyBytes, 32, `invalid ${field}.chainKey.key length ${chainKeyBytes.byteLength}`);
|
|
155
140
|
return {
|
|
156
141
|
ratchetKey: {
|
|
157
142
|
pubKey: ratchetPubKey,
|
|
@@ -168,26 +153,20 @@ function decodeSignalSessionSnapshot(session, field) {
|
|
|
168
153
|
}
|
|
169
154
|
const pendingPreKey = session.pendingPreKey;
|
|
170
155
|
const localPubKey = asBytes(session.localIdentityPublic, `${field}.localIdentityPublic`);
|
|
171
|
-
|
|
172
|
-
throw new Error(`invalid ${field}.localIdentityPublic length ${localPubKey.byteLength}`);
|
|
173
|
-
}
|
|
156
|
+
assertByteLength(localPubKey, 33, `invalid ${field}.localIdentityPublic length ${localPubKey.byteLength}`);
|
|
174
157
|
const remotePubKey = asBytes(session.remoteIdentityPublic, `${field}.remoteIdentityPublic`);
|
|
175
|
-
|
|
176
|
-
throw new Error(`invalid ${field}.remoteIdentityPublic length ${remotePubKey.byteLength}`);
|
|
177
|
-
}
|
|
158
|
+
assertByteLength(remotePubKey, 33, `invalid ${field}.remoteIdentityPublic length ${remotePubKey.byteLength}`);
|
|
178
159
|
const rootKey = asBytes(session.rootKey, `${field}.rootKey`);
|
|
179
|
-
|
|
180
|
-
throw new Error(`invalid ${field}.rootKey length ${rootKey.byteLength}`);
|
|
181
|
-
}
|
|
160
|
+
assertByteLength(rootKey, 32, `invalid ${field}.rootKey length ${rootKey.byteLength}`);
|
|
182
161
|
const localOneTimePubKey = pendingPreKey
|
|
183
162
|
? asBytes(pendingPreKey.baseKey, `${field}.pendingPreKey.baseKey`)
|
|
184
163
|
: null;
|
|
185
|
-
if (localOneTimePubKey
|
|
186
|
-
|
|
164
|
+
if (localOneTimePubKey) {
|
|
165
|
+
assertByteLength(localOneTimePubKey, 33, `invalid ${field}.pendingPreKey.baseKey length ${localOneTimePubKey.byteLength}`);
|
|
187
166
|
}
|
|
188
167
|
const aliceBaseKey = asOptionalBytes(session.aliceBaseKey, `${field}.aliceBaseKey`) ?? null;
|
|
189
|
-
if (aliceBaseKey
|
|
190
|
-
|
|
168
|
+
if (aliceBaseKey) {
|
|
169
|
+
assertByteLength(aliceBaseKey, 33, `invalid ${field}.aliceBaseKey length ${aliceBaseKey.byteLength}`);
|
|
191
170
|
}
|
|
192
171
|
return {
|
|
193
172
|
local: {
|
|
@@ -101,18 +101,17 @@ export function createStore(options) {
|
|
|
101
101
|
if (cached) {
|
|
102
102
|
return cached;
|
|
103
103
|
}
|
|
104
|
-
const
|
|
105
|
-
const
|
|
106
|
-
const
|
|
107
|
-
const
|
|
108
|
-
const
|
|
109
|
-
const
|
|
110
|
-
const
|
|
111
|
-
const
|
|
112
|
-
const
|
|
113
|
-
const
|
|
114
|
-
const
|
|
115
|
-
const customContacts = resolveStoreValue(normalizedSessionId, custom?.contacts, 'custom.contacts');
|
|
104
|
+
const resolveCustom = (value, domainPath) => resolveStoreValue(normalizedSessionId, value, domainPath);
|
|
105
|
+
const customAuth = resolveCustom(options.custom?.auth, 'custom.auth');
|
|
106
|
+
const customSignal = resolveCustom(options.custom?.signal, 'custom.signal');
|
|
107
|
+
const customSenderKey = resolveCustom(options.custom?.senderKey, 'custom.senderKey');
|
|
108
|
+
const customAppState = resolveCustom(options.custom?.appState, 'custom.appState');
|
|
109
|
+
const customRetry = resolveCustom(options.customCache?.retry, 'customCache.retry');
|
|
110
|
+
const customParticipants = resolveCustom(options.customCache?.participants, 'customCache.participants');
|
|
111
|
+
const customDeviceList = resolveCustom(options.customCache?.deviceList, 'customCache.deviceList');
|
|
112
|
+
const customMessages = resolveCustom(options.custom?.messages, 'custom.messages');
|
|
113
|
+
const customThreads = resolveCustom(options.custom?.threads, 'custom.threads');
|
|
114
|
+
const customContacts = resolveCustom(options.custom?.contacts, 'custom.contacts');
|
|
116
115
|
const memoryLimits = options.memory?.limits ?? {};
|
|
117
116
|
const requiresSqlite = !customAuth ||
|
|
118
117
|
(!customSignal && providers.signal === 'sqlite') ||
|
|
@@ -133,7 +132,8 @@ export function createStore(options) {
|
|
|
133
132
|
path: sqlite.path,
|
|
134
133
|
sessionId: normalizedSessionId,
|
|
135
134
|
driver: sqlite.driver ?? 'auto',
|
|
136
|
-
pragmas: sqlite.pragmas
|
|
135
|
+
pragmas: sqlite.pragmas,
|
|
136
|
+
tableNames: sqlite.tableNames
|
|
137
137
|
}
|
|
138
138
|
: null;
|
|
139
139
|
const authStore = customAuth ?? new WaAuthSqliteStore(sqliteOptions);
|
|
@@ -258,8 +258,7 @@ export function createStore(options) {
|
|
|
258
258
|
return session;
|
|
259
259
|
},
|
|
260
260
|
async destroyCaches() {
|
|
261
|
-
const
|
|
262
|
-
for (const session of activeSessions) {
|
|
261
|
+
for (const session of sessions.values()) {
|
|
263
262
|
await session.destroyCaches();
|
|
264
263
|
}
|
|
265
264
|
},
|
|
@@ -268,9 +267,8 @@ export function createStore(options) {
|
|
|
268
267
|
return;
|
|
269
268
|
}
|
|
270
269
|
storeDestroyed = true;
|
|
271
|
-
const
|
|
272
|
-
|
|
273
|
-
for (const session of activeSessions) {
|
|
270
|
+
for (const [sessionId, session] of sessions) {
|
|
271
|
+
sessions.delete(sessionId);
|
|
274
272
|
await session.destroy();
|
|
275
273
|
}
|
|
276
274
|
}
|
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
const EMPTY_STORE_LIST = Object.freeze([]);
|
|
2
|
-
const DEFAULT_PARTICIPANTS_CACHE_TTL_MS = 5 * 60 * 1000;
|
|
3
|
-
const DEFAULT_DEVICE_LIST_CACHE_TTL_MS = 5 * 60 * 1000;
|
|
4
2
|
export const NOOP_MESSAGE_STORE = Object.freeze({
|
|
5
3
|
upsert: async (_record) => { },
|
|
4
|
+
upsertBatch: async (_records) => { },
|
|
6
5
|
getById: async (_id) => null,
|
|
7
6
|
listByThread: async (_threadJid, _limit, _beforeTimestampMs) => EMPTY_STORE_LIST,
|
|
8
7
|
deleteById: async (_id) => 0,
|
|
@@ -10,6 +9,7 @@ export const NOOP_MESSAGE_STORE = Object.freeze({
|
|
|
10
9
|
});
|
|
11
10
|
export const NOOP_THREAD_STORE = Object.freeze({
|
|
12
11
|
upsert: async (_record) => { },
|
|
12
|
+
upsertBatch: async (_records) => { },
|
|
13
13
|
getByJid: async (_jid) => null,
|
|
14
14
|
list: async (_limit) => EMPTY_STORE_LIST,
|
|
15
15
|
deleteByJid: async (_jid) => 0,
|
|
@@ -17,12 +17,12 @@ export const NOOP_THREAD_STORE = Object.freeze({
|
|
|
17
17
|
});
|
|
18
18
|
export const NOOP_CONTACT_STORE = Object.freeze({
|
|
19
19
|
upsert: async (_record) => { },
|
|
20
|
+
upsertBatch: async (_records) => { },
|
|
20
21
|
getByJid: async (_jid) => null,
|
|
21
22
|
deleteByJid: async (_jid) => 0,
|
|
22
23
|
clear: async () => { }
|
|
23
24
|
});
|
|
24
25
|
export const NOOP_PARTICIPANTS_STORE = Object.freeze({
|
|
25
|
-
getTtlMs: () => DEFAULT_PARTICIPANTS_CACHE_TTL_MS,
|
|
26
26
|
upsertGroupParticipants: async (_snapshot) => { },
|
|
27
27
|
getGroupParticipants: async (_groupJid, _nowMs) => null,
|
|
28
28
|
deleteGroupParticipants: async (_groupJid) => 0,
|
|
@@ -31,10 +31,7 @@ export const NOOP_PARTICIPANTS_STORE = Object.freeze({
|
|
|
31
31
|
destroy: async () => { }
|
|
32
32
|
});
|
|
33
33
|
export const NOOP_DEVICE_LIST_STORE = Object.freeze({
|
|
34
|
-
getTtlMs: () => DEFAULT_DEVICE_LIST_CACHE_TTL_MS,
|
|
35
|
-
upsertUserDevices: async (_snapshot) => { },
|
|
36
34
|
upsertUserDevicesBatch: async (_snapshots) => { },
|
|
37
|
-
getUserDevices: async (_userJid, _nowMs) => null,
|
|
38
35
|
getUserDevicesBatch: async (userJids, _nowMs) => userJids.map(() => null),
|
|
39
36
|
deleteUserDevices: async (_userJid) => 0,
|
|
40
37
|
cleanupExpired: async (_nowMs) => 0,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { APP_STATE_EMPTY_LT_HASH } from '../../../appstate/constants.js';
|
|
2
|
-
import {
|
|
3
|
-
import { uint8Equal } from '../../../util/bytes.js';
|
|
2
|
+
import { pickActiveSyncKey } from '../../../appstate/utils.js';
|
|
3
|
+
import { bytesToHex, uint8Equal } from '../../../util/bytes.js';
|
|
4
4
|
import { resolvePositive } from '../../../util/coercion.js';
|
|
5
5
|
import { setBoundedMapEntry } from '../../../util/collections.js';
|
|
6
6
|
const DEFAULT_APPSTATE_MEMORY_STORE_LIMITS = Object.freeze({
|
|
@@ -22,13 +22,14 @@ export class WaAppStateMemoryStore {
|
|
|
22
22
|
this.maxCollectionEntries = resolvePositive(options.maxCollectionEntries, DEFAULT_APPSTATE_MEMORY_STORE_LIMITS.collectionEntries, 'WaAppStateMemoryStoreOptions.maxCollectionEntries');
|
|
23
23
|
if (initial) {
|
|
24
24
|
for (const key of initial.keys) {
|
|
25
|
-
setBoundedMapEntry(this.keys,
|
|
25
|
+
setBoundedMapEntry(this.keys, bytesToHex(key.keyId), key, this.maxSyncKeys);
|
|
26
26
|
}
|
|
27
27
|
for (const [collectionName, collection] of Object.entries(initial.collections)) {
|
|
28
28
|
if (!collection) {
|
|
29
29
|
continue;
|
|
30
30
|
}
|
|
31
31
|
this.collections.set(collectionName, {
|
|
32
|
+
initialized: true,
|
|
32
33
|
version: collection.version,
|
|
33
34
|
hash: collection.hash,
|
|
34
35
|
indexValueMap: toBoundedMap(Object.entries(collection.indexValueMap), this.maxCollectionEntries)
|
|
@@ -54,7 +55,7 @@ export class WaAppStateMemoryStore {
|
|
|
54
55
|
async upsertSyncKeys(keys) {
|
|
55
56
|
let inserted = 0;
|
|
56
57
|
for (const key of keys) {
|
|
57
|
-
const keyHex =
|
|
58
|
+
const keyHex = bytesToHex(key.keyId);
|
|
58
59
|
const existing = this.keys.get(keyHex);
|
|
59
60
|
if (existing && uint8Equal(existing.keyData, key.keyData)) {
|
|
60
61
|
continue;
|
|
@@ -65,10 +66,13 @@ export class WaAppStateMemoryStore {
|
|
|
65
66
|
return inserted;
|
|
66
67
|
}
|
|
67
68
|
async getSyncKey(keyId) {
|
|
68
|
-
return this.keys.get(
|
|
69
|
+
return this.keys.get(bytesToHex(keyId)) ?? null;
|
|
69
70
|
}
|
|
70
71
|
async getSyncKeyData(keyId) {
|
|
71
|
-
return this.keys.get(
|
|
72
|
+
return this.keys.get(bytesToHex(keyId))?.keyData ?? null;
|
|
73
|
+
}
|
|
74
|
+
async getSyncKeyDataBatch(keyIds) {
|
|
75
|
+
return keyIds.map((keyId) => this.keys.get(bytesToHex(keyId))?.keyData ?? null);
|
|
72
76
|
}
|
|
73
77
|
async getActiveSyncKey() {
|
|
74
78
|
return pickActiveSyncKey(this.keys.values());
|
|
@@ -77,6 +81,7 @@ export class WaAppStateMemoryStore {
|
|
|
77
81
|
let state = this.collections.get(collection);
|
|
78
82
|
if (!state) {
|
|
79
83
|
state = {
|
|
84
|
+
initialized: false,
|
|
80
85
|
version: 0,
|
|
81
86
|
hash: APP_STATE_EMPTY_LT_HASH,
|
|
82
87
|
indexValueMap: new Map()
|
|
@@ -85,9 +90,28 @@ export class WaAppStateMemoryStore {
|
|
|
85
90
|
}
|
|
86
91
|
return state;
|
|
87
92
|
}
|
|
93
|
+
async getCollectionStates(collections) {
|
|
94
|
+
const result = new Array(collections.length);
|
|
95
|
+
for (let index = 0; index < collections.length; index += 1) {
|
|
96
|
+
const collection = collections[index];
|
|
97
|
+
let state = this.collections.get(collection);
|
|
98
|
+
if (!state) {
|
|
99
|
+
state = {
|
|
100
|
+
initialized: false,
|
|
101
|
+
version: 0,
|
|
102
|
+
hash: APP_STATE_EMPTY_LT_HASH,
|
|
103
|
+
indexValueMap: new Map()
|
|
104
|
+
};
|
|
105
|
+
this.collections.set(collection, state);
|
|
106
|
+
}
|
|
107
|
+
result[index] = state;
|
|
108
|
+
}
|
|
109
|
+
return result;
|
|
110
|
+
}
|
|
88
111
|
async setCollectionStates(updates) {
|
|
89
112
|
for (const update of updates) {
|
|
90
113
|
this.collections.set(update.collection, {
|
|
114
|
+
initialized: true,
|
|
91
115
|
version: update.version,
|
|
92
116
|
hash: update.hash,
|
|
93
117
|
indexValueMap: toBoundedMap(update.indexValueMap.entries(), this.maxCollectionEntries)
|
|
@@ -11,6 +11,11 @@ export class WaContactMemoryStore {
|
|
|
11
11
|
async upsert(record) {
|
|
12
12
|
setBoundedMapEntry(this.contacts, record.jid, record, this.maxContacts);
|
|
13
13
|
}
|
|
14
|
+
async upsertBatch(records) {
|
|
15
|
+
for (const record of records) {
|
|
16
|
+
setBoundedMapEntry(this.contacts, record.jid, record, this.maxContacts);
|
|
17
|
+
}
|
|
18
|
+
}
|
|
14
19
|
async getByJid(jid) {
|
|
15
20
|
return this.contacts.get(jid) ?? null;
|
|
16
21
|
}
|
|
@@ -14,38 +14,15 @@ export class WaDeviceListMemoryStore {
|
|
|
14
14
|
}, resolveCleanupIntervalMs(ttlMs));
|
|
15
15
|
this.cleanupTimer.unref();
|
|
16
16
|
}
|
|
17
|
-
getTtlMs() {
|
|
18
|
-
return this.ttlMs;
|
|
19
|
-
}
|
|
20
|
-
async upsertUserDevices(snapshot) {
|
|
21
|
-
setBoundedMapEntry(this.records, snapshot.userJid, {
|
|
22
|
-
...snapshot,
|
|
23
|
-
expiresAtMs: snapshot.updatedAtMs + this.ttlMs
|
|
24
|
-
}, this.maxUsers);
|
|
25
|
-
}
|
|
26
17
|
async upsertUserDevicesBatch(snapshots) {
|
|
27
|
-
for (
|
|
18
|
+
for (let index = 0; index < snapshots.length; index += 1) {
|
|
19
|
+
const snapshot = snapshots[index];
|
|
28
20
|
setBoundedMapEntry(this.records, snapshot.userJid, {
|
|
29
21
|
...snapshot,
|
|
30
22
|
expiresAtMs: snapshot.updatedAtMs + this.ttlMs
|
|
31
23
|
}, this.maxUsers);
|
|
32
24
|
}
|
|
33
25
|
}
|
|
34
|
-
async getUserDevices(userJid, nowMs = Date.now()) {
|
|
35
|
-
const record = this.records.get(userJid);
|
|
36
|
-
if (!record) {
|
|
37
|
-
return null;
|
|
38
|
-
}
|
|
39
|
-
if (record.expiresAtMs <= nowMs) {
|
|
40
|
-
this.records.delete(userJid);
|
|
41
|
-
return null;
|
|
42
|
-
}
|
|
43
|
-
return {
|
|
44
|
-
userJid: record.userJid,
|
|
45
|
-
deviceJids: record.deviceJids,
|
|
46
|
-
updatedAtMs: record.updatedAtMs
|
|
47
|
-
};
|
|
48
|
-
}
|
|
49
26
|
async getUserDevicesBatch(userJids, nowMs = Date.now()) {
|
|
50
27
|
return userJids.map((userJid) => {
|
|
51
28
|
const record = this.records.get(userJid);
|
|
@@ -56,11 +33,7 @@ export class WaDeviceListMemoryStore {
|
|
|
56
33
|
this.records.delete(userJid);
|
|
57
34
|
return null;
|
|
58
35
|
}
|
|
59
|
-
return
|
|
60
|
-
userJid: record.userJid,
|
|
61
|
-
deviceJids: record.deviceJids,
|
|
62
|
-
updatedAtMs: record.updatedAtMs
|
|
63
|
-
};
|
|
36
|
+
return record;
|
|
64
37
|
});
|
|
65
38
|
}
|
|
66
39
|
async deleteUserDevices(userJid) {
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { resolvePositive } from '../../../util/coercion.js';
|
|
2
|
-
import { normalizeQueryLimit } from '../../../util/collections.js';
|
|
3
|
-
import { setBoundedMapEntry } from '../../../util/collections.js';
|
|
2
|
+
import { normalizeQueryLimit, setBoundedMapEntry } from '../../../util/collections.js';
|
|
4
3
|
const DEFAULT_MESSAGE_MEMORY_STORE_LIMITS = Object.freeze({
|
|
5
4
|
messages: 50000
|
|
6
5
|
});
|
|
@@ -12,6 +11,11 @@ export class WaMessageMemoryStore {
|
|
|
12
11
|
async upsert(record) {
|
|
13
12
|
setBoundedMapEntry(this.messages, record.id, record, this.maxMessages);
|
|
14
13
|
}
|
|
14
|
+
async upsertBatch(records) {
|
|
15
|
+
for (const record of records) {
|
|
16
|
+
setBoundedMapEntry(this.messages, record.id, record, this.maxMessages);
|
|
17
|
+
}
|
|
18
|
+
}
|
|
15
19
|
async getById(id) {
|
|
16
20
|
return this.messages.get(id) ?? null;
|
|
17
21
|
}
|
|
@@ -19,9 +23,8 @@ export class WaMessageMemoryStore {
|
|
|
19
23
|
const normalizedLimit = normalizeQueryLimit(limit, 50);
|
|
20
24
|
const records = [];
|
|
21
25
|
for (const record of this.messages.values()) {
|
|
22
|
-
if (record.threadJid !== threadJid)
|
|
26
|
+
if (record.threadJid !== threadJid)
|
|
23
27
|
continue;
|
|
24
|
-
}
|
|
25
28
|
if (beforeTimestampMs !== undefined &&
|
|
26
29
|
(record.timestampMs === undefined || record.timestampMs >= beforeTimestampMs)) {
|
|
27
30
|
continue;
|
|
@@ -29,7 +32,10 @@ export class WaMessageMemoryStore {
|
|
|
29
32
|
records.push(record);
|
|
30
33
|
}
|
|
31
34
|
records.sort((left, right) => (right.timestampMs ?? 0) - (left.timestampMs ?? 0));
|
|
32
|
-
|
|
35
|
+
if (records.length > normalizedLimit) {
|
|
36
|
+
records.length = normalizedLimit;
|
|
37
|
+
}
|
|
38
|
+
return records;
|
|
33
39
|
}
|
|
34
40
|
async deleteById(id) {
|
|
35
41
|
return this.messages.delete(id) ? 1 : 0;
|
|
@@ -14,9 +14,6 @@ export class WaParticipantsMemoryStore {
|
|
|
14
14
|
}, resolveCleanupIntervalMs(ttlMs));
|
|
15
15
|
this.cleanupTimer.unref();
|
|
16
16
|
}
|
|
17
|
-
getTtlMs() {
|
|
18
|
-
return this.ttlMs;
|
|
19
|
-
}
|
|
20
17
|
async upsertGroupParticipants(snapshot) {
|
|
21
18
|
setBoundedMapEntry(this.records, snapshot.groupJid, {
|
|
22
19
|
...snapshot,
|
|
@@ -32,11 +29,7 @@ export class WaParticipantsMemoryStore {
|
|
|
32
29
|
this.records.delete(groupJid);
|
|
33
30
|
return null;
|
|
34
31
|
}
|
|
35
|
-
return
|
|
36
|
-
groupJid: record.groupJid,
|
|
37
|
-
participants: record.participants,
|
|
38
|
-
updatedAtMs: record.updatedAtMs
|
|
39
|
-
};
|
|
32
|
+
return record;
|
|
40
33
|
}
|
|
41
34
|
async deleteGroupParticipants(groupJid) {
|
|
42
35
|
return this.records.delete(groupJid) ? 1 : 0;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
+
import { signalAddressKey } from '../../../protocol/jid.js';
|
|
1
2
|
import { resolvePositive } from '../../../util/coercion.js';
|
|
2
3
|
import { setBoundedMapEntry } from '../../../util/collections.js';
|
|
3
|
-
import { signalAddressKey } from '../../../util/signal-address.js';
|
|
4
4
|
const DEFAULT_SENDER_KEY_STORE_LIMITS = Object.freeze({
|
|
5
5
|
senderKeys: 8192,
|
|
6
6
|
senderDistributions: 8192
|
|
@@ -45,10 +45,6 @@ export class SenderKeyMemoryStore {
|
|
|
45
45
|
const record = this.senderKeys.get(this.makeKey(groupId, sender));
|
|
46
46
|
return record ?? null;
|
|
47
47
|
}
|
|
48
|
-
async getDeviceSenderKeyDistribution(groupId, sender) {
|
|
49
|
-
const record = this.senderDistributions.get(this.makeKey(groupId, sender));
|
|
50
|
-
return record ?? null;
|
|
51
|
-
}
|
|
52
48
|
async getDeviceSenderKeyDistributions(groupId, senders) {
|
|
53
49
|
return senders.map((sender) => this.senderDistributions.get(this.makeKey(groupId, sender)) ?? null);
|
|
54
50
|
}
|
|
@@ -60,8 +56,10 @@ export class SenderKeyMemoryStore {
|
|
|
60
56
|
}
|
|
61
57
|
async markForgetSenderKey(groupId, participants) {
|
|
62
58
|
let deleted = 0;
|
|
63
|
-
for (
|
|
64
|
-
|
|
59
|
+
for (let index = 0; index < participants.length; index += 1) {
|
|
60
|
+
const participant = participants[index];
|
|
61
|
+
deleted += this.deleteMatching(this.senderKeys, participant, groupId);
|
|
62
|
+
deleted += this.deleteMatching(this.senderDistributions, participant, groupId);
|
|
65
63
|
}
|
|
66
64
|
return deleted;
|
|
67
65
|
}
|