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
|
@@ -2,13 +2,14 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.WaAppStateSyncClient = exports.WaAppStateMissingKeyError = void 0;
|
|
4
4
|
const constants_1 = require("./constants");
|
|
5
|
-
const utils_1 = require("./utils");
|
|
6
5
|
const WaAppStateCrypto_1 = require("./WaAppStateCrypto");
|
|
7
6
|
const WaAppStateSyncResponseParser_1 = require("./WaAppStateSyncResponseParser");
|
|
8
7
|
const _proto_1 = require("../proto.js");
|
|
9
8
|
const constants_2 = require("../protocol/constants");
|
|
10
|
-
const
|
|
9
|
+
const jid_1 = require("../protocol/jid");
|
|
10
|
+
const query_1 = require("../transport/node/query");
|
|
11
11
|
const bytes_1 = require("../util/bytes");
|
|
12
|
+
const bytes_2 = require("../util/bytes");
|
|
12
13
|
const primitives_1 = require("../util/primitives");
|
|
13
14
|
class WaAppStateMissingKeyError extends Error {
|
|
14
15
|
constructor(message, keyId, collection) {
|
|
@@ -24,6 +25,7 @@ class WaAppStateSyncClient {
|
|
|
24
25
|
this.logger = options.logger;
|
|
25
26
|
this.query = options.query;
|
|
26
27
|
this.store = options.store;
|
|
28
|
+
this.getCurrentMeJid = options.getCurrentMeJid;
|
|
27
29
|
this.hostDomain = options.hostDomain ?? constants_2.WA_DEFAULTS.HOST_DOMAIN;
|
|
28
30
|
this.defaultTimeoutMs = options.defaultTimeoutMs ?? constants_2.WA_DEFAULTS.APP_STATE_SYNC_TIMEOUT_MS;
|
|
29
31
|
this.onMissingKeys = options.onMissingKeys;
|
|
@@ -47,14 +49,14 @@ class WaAppStateSyncClient {
|
|
|
47
49
|
async importSyncKeyShare(share) {
|
|
48
50
|
const keys = [];
|
|
49
51
|
for (const item of share.keys ?? []) {
|
|
50
|
-
const keyId = (0,
|
|
52
|
+
const keyId = (0, bytes_1.decodeProtoBytes)(item.keyId?.keyId, 'appStateSyncKeyShare.keys[].keyId.keyId');
|
|
51
53
|
if (!item.keyData?.keyData) {
|
|
52
54
|
this.logger.debug('app-state sync key share entry missing key data', {
|
|
53
|
-
keyId: (0,
|
|
55
|
+
keyId: (0, bytes_2.bytesToHex)(keyId)
|
|
54
56
|
});
|
|
55
57
|
continue;
|
|
56
58
|
}
|
|
57
|
-
const keyData = (0,
|
|
59
|
+
const keyData = (0, bytes_1.decodeProtoBytes)(item.keyData?.keyData, 'appStateSyncKeyShare.keys[].keyData.keyData');
|
|
58
60
|
keys.push({
|
|
59
61
|
keyId,
|
|
60
62
|
keyData,
|
|
@@ -93,6 +95,10 @@ class WaAppStateSyncClient {
|
|
|
93
95
|
...new Set(options.collections ?? constants_1.APP_STATE_DEFAULT_COLLECTIONS)
|
|
94
96
|
];
|
|
95
97
|
try {
|
|
98
|
+
const initialCollectionStates = await this.store.getCollectionStates(collections);
|
|
99
|
+
for (let index = 0; index < collections.length; index += 1) {
|
|
100
|
+
context.collections.set(collections[index], initialCollectionStates[index]);
|
|
101
|
+
}
|
|
96
102
|
this.logger.info('app-state sync start', {
|
|
97
103
|
collections: collections.length,
|
|
98
104
|
pendingMutations: options.pendingMutations?.length ?? 0
|
|
@@ -162,36 +168,13 @@ class WaAppStateSyncClient {
|
|
|
162
168
|
}
|
|
163
169
|
}
|
|
164
170
|
async syncCollectionsRound(collections, pendingByCollection, options) {
|
|
165
|
-
const prepared = await this.prepareSyncRoundRequest(collections, pendingByCollection);
|
|
166
|
-
const iqNode = this.buildSyncIqNode(prepared.collectionNodes);
|
|
167
|
-
const payloadByCollection = await this.fetchSyncPayloadByCollection(iqNode, options.timeoutMs ?? this.defaultTimeoutMs);
|
|
168
|
-
const collectionOutcomes = await Promise.all(collections.map((collection) => this.processCollectionRound({
|
|
169
|
-
collection,
|
|
170
|
-
payloadByCollection,
|
|
171
|
-
pendingByCollection,
|
|
172
|
-
options,
|
|
173
|
-
outgoingContexts: prepared.outgoingContexts,
|
|
174
|
-
skippedUploadCollections: prepared.skippedUploadCollections
|
|
175
|
-
})));
|
|
176
|
-
return {
|
|
177
|
-
results: collectionOutcomes.map((entry) => entry.result),
|
|
178
|
-
collectionsToRefetch: collectionOutcomes
|
|
179
|
-
.filter((entry) => entry.shouldRefetch)
|
|
180
|
-
.map((entry) => entry.collection),
|
|
181
|
-
stateChanged: collectionOutcomes.some((entry) => entry.stateChanged),
|
|
182
|
-
missingKeyIds: this.collectDistinctMissingKeyIds(collectionOutcomes
|
|
183
|
-
.map((entry) => entry.missingKeyId)
|
|
184
|
-
.filter((value) => value !== null)),
|
|
185
|
-
blockedCollections: collectionOutcomes
|
|
186
|
-
.filter((entry) => entry.result.state === constants_2.WA_APP_STATE_COLLECTION_STATES.BLOCKED)
|
|
187
|
-
.map((entry) => entry.collection)
|
|
188
|
-
};
|
|
189
|
-
}
|
|
190
|
-
async prepareSyncRoundRequest(collections, pendingByCollection) {
|
|
191
171
|
const requests = await Promise.all(collections.map((collection) => this.buildCollectionSyncRequest(collection, pendingByCollection)));
|
|
172
|
+
const collectionNodes = new Array(requests.length);
|
|
192
173
|
const outgoingContexts = new Map();
|
|
193
174
|
const skippedUploadCollections = new Set();
|
|
194
|
-
for (
|
|
175
|
+
for (let index = 0; index < requests.length; index += 1) {
|
|
176
|
+
const request = requests[index];
|
|
177
|
+
collectionNodes[index] = request.node;
|
|
195
178
|
if (request.outgoingContext) {
|
|
196
179
|
outgoingContexts.set(request.collection, request.outgoingContext);
|
|
197
180
|
}
|
|
@@ -199,26 +182,57 @@ class WaAppStateSyncClient {
|
|
|
199
182
|
skippedUploadCollections.add(request.collection);
|
|
200
183
|
}
|
|
201
184
|
}
|
|
202
|
-
|
|
203
|
-
|
|
185
|
+
const iqNode = this.buildSyncIqNode(collectionNodes);
|
|
186
|
+
const payloadByCollection = await this.fetchSyncPayloadByCollection(iqNode, options.timeoutMs ?? this.defaultTimeoutMs);
|
|
187
|
+
const collectionOutcomes = await Promise.all(collections.map((collection) => this.processCollectionRound({
|
|
188
|
+
collection,
|
|
189
|
+
payloadByCollection,
|
|
190
|
+
pendingByCollection,
|
|
191
|
+
options,
|
|
204
192
|
outgoingContexts,
|
|
205
193
|
skippedUploadCollections
|
|
194
|
+
})));
|
|
195
|
+
const results = [];
|
|
196
|
+
const collectionsToRefetch = [];
|
|
197
|
+
const blockedCollections = [];
|
|
198
|
+
const missingKeyIds = [];
|
|
199
|
+
const missingKeyIdHexes = new Set();
|
|
200
|
+
let stateChanged = false;
|
|
201
|
+
for (const entry of collectionOutcomes) {
|
|
202
|
+
results.push(entry.result);
|
|
203
|
+
if (entry.shouldRefetch) {
|
|
204
|
+
collectionsToRefetch.push(entry.collection);
|
|
205
|
+
}
|
|
206
|
+
if (entry.stateChanged) {
|
|
207
|
+
stateChanged = true;
|
|
208
|
+
}
|
|
209
|
+
if (entry.result.state === constants_2.WA_APP_STATE_COLLECTION_STATES.BLOCKED) {
|
|
210
|
+
blockedCollections.push(entry.collection);
|
|
211
|
+
}
|
|
212
|
+
if (entry.missingKeyId) {
|
|
213
|
+
const keyHex = (0, bytes_2.bytesToHex)(entry.missingKeyId);
|
|
214
|
+
if (!missingKeyIdHexes.has(keyHex)) {
|
|
215
|
+
missingKeyIdHexes.add(keyHex);
|
|
216
|
+
missingKeyIds.push(entry.missingKeyId);
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
return {
|
|
221
|
+
results,
|
|
222
|
+
collectionsToRefetch,
|
|
223
|
+
stateChanged,
|
|
224
|
+
missingKeyIds,
|
|
225
|
+
blockedCollections
|
|
206
226
|
};
|
|
207
227
|
}
|
|
208
228
|
async buildCollectionSyncRequest(collection, pendingByCollection) {
|
|
209
229
|
const collectionState = await this.getCollectionState(collection);
|
|
210
|
-
const hasPersistedState = collectionState.
|
|
211
|
-
collectionState.indexValueMap.size > 0 ||
|
|
212
|
-
!(0, bytes_1.uint8Equal)(collectionState.hash, constants_1.APP_STATE_EMPTY_LT_HASH);
|
|
230
|
+
const hasPersistedState = collectionState.initialized;
|
|
213
231
|
const attrs = {
|
|
214
|
-
name: collection
|
|
232
|
+
name: collection,
|
|
233
|
+
version: String(hasPersistedState ? collectionState.version : constants_1.APP_STATE_DEFAULT_COLLECTION_VERSION),
|
|
234
|
+
return_snapshot: hasPersistedState ? 'false' : 'true'
|
|
215
235
|
};
|
|
216
|
-
if (hasPersistedState) {
|
|
217
|
-
attrs.version = String(collectionState.version);
|
|
218
|
-
}
|
|
219
|
-
else {
|
|
220
|
-
attrs.return_snapshot = 'true';
|
|
221
|
-
}
|
|
222
236
|
const children = [];
|
|
223
237
|
const pendingMutations = pendingByCollection.get(collection) ?? [];
|
|
224
238
|
let outgoingContext;
|
|
@@ -275,6 +289,7 @@ class WaAppStateSyncClient {
|
|
|
275
289
|
tag: responseNode.tag,
|
|
276
290
|
type: responseNode.attrs.type
|
|
277
291
|
});
|
|
292
|
+
(0, query_1.assertIqResult)(responseNode, 'app-state sync');
|
|
278
293
|
const payloads = (0, WaAppStateSyncResponseParser_1.parseSyncResponse)(responseNode);
|
|
279
294
|
this.logger.debug('app-state sync payloads parsed', { count: payloads.length });
|
|
280
295
|
const payloadByCollection = new Map();
|
|
@@ -296,20 +311,16 @@ class WaAppStateSyncClient {
|
|
|
296
311
|
return this.createCollectionOutcome(collection, payload.state, payload.version);
|
|
297
312
|
}
|
|
298
313
|
const pendingMutationsCount = pendingByCollection.get(collection)?.length ?? 0;
|
|
299
|
-
if (payload.state === constants_2.WA_APP_STATE_COLLECTION_STATES.
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
: constants_2.WA_APP_STATE_COLLECTION_STATES.SUCCESS, payload.version, shouldRefetch);
|
|
310
|
-
}
|
|
311
|
-
if (payload.state === constants_2.WA_APP_STATE_COLLECTION_STATES.CONFLICT_HAS_MORE) {
|
|
312
|
-
return this.createCollectionOutcome(collection, payload.state, payload.version, shouldRefetch);
|
|
314
|
+
if (payload.state === constants_2.WA_APP_STATE_COLLECTION_STATES.CONFLICT ||
|
|
315
|
+
payload.state === constants_2.WA_APP_STATE_COLLECTION_STATES.CONFLICT_HAS_MORE) {
|
|
316
|
+
shouldRefetch =
|
|
317
|
+
payload.state === constants_2.WA_APP_STATE_COLLECTION_STATES.CONFLICT_HAS_MORE ||
|
|
318
|
+
pendingMutationsCount > 0;
|
|
319
|
+
return this.createCollectionOutcome(collection, payload.state === constants_2.WA_APP_STATE_COLLECTION_STATES.CONFLICT
|
|
320
|
+
? pendingMutationsCount > 0
|
|
321
|
+
? constants_2.WA_APP_STATE_COLLECTION_STATES.CONFLICT
|
|
322
|
+
: constants_2.WA_APP_STATE_COLLECTION_STATES.SUCCESS
|
|
323
|
+
: payload.state, payload.version, shouldRefetch);
|
|
313
324
|
}
|
|
314
325
|
try {
|
|
315
326
|
let appliedMutations = [];
|
|
@@ -341,13 +352,17 @@ class WaAppStateSyncClient {
|
|
|
341
352
|
collectionStateChanged = true;
|
|
342
353
|
}
|
|
343
354
|
}
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
shouldRefetch = true;
|
|
355
|
+
const currentCollectionState = await this.getCollectionState(collection);
|
|
356
|
+
if (!currentCollectionState.initialized &&
|
|
357
|
+
payload.state === constants_2.WA_APP_STATE_COLLECTION_STATES.SUCCESS) {
|
|
358
|
+
this.setCollectionState(collection, payload.version ?? currentCollectionState.version, currentCollectionState.hash, currentCollectionState.indexValueMap);
|
|
359
|
+
collectionStateChanged = true;
|
|
350
360
|
}
|
|
361
|
+
shouldRefetch =
|
|
362
|
+
shouldRefetch ||
|
|
363
|
+
payload.state === constants_2.WA_APP_STATE_COLLECTION_STATES.SUCCESS_HAS_MORE ||
|
|
364
|
+
(payload.state === constants_2.WA_APP_STATE_COLLECTION_STATES.SUCCESS &&
|
|
365
|
+
skippedUploadCollections.has(collection));
|
|
351
366
|
this.logger.debug('app-state collection processed', {
|
|
352
367
|
collection: payload.collection,
|
|
353
368
|
state: payload.state,
|
|
@@ -386,24 +401,13 @@ class WaAppStateSyncClient {
|
|
|
386
401
|
}
|
|
387
402
|
};
|
|
388
403
|
}
|
|
389
|
-
collectDistinctMissingKeyIds(keyIds) {
|
|
390
|
-
const byHex = new Map();
|
|
391
|
-
for (const keyId of keyIds) {
|
|
392
|
-
const keyHex = (0, utils_1.keyIdToHex)(keyId);
|
|
393
|
-
if (byHex.has(keyHex)) {
|
|
394
|
-
continue;
|
|
395
|
-
}
|
|
396
|
-
byHex.set(keyHex, keyId);
|
|
397
|
-
}
|
|
398
|
-
return [...byHex.values()];
|
|
399
|
-
}
|
|
400
404
|
async notifyMissingKeys(input) {
|
|
401
|
-
const keyIds =
|
|
402
|
-
const collections =
|
|
405
|
+
const keyIds = input.keyIds;
|
|
406
|
+
const collections = input.collections;
|
|
403
407
|
if (keyIds.length === 0 || collections.length === 0) {
|
|
404
408
|
return;
|
|
405
409
|
}
|
|
406
|
-
const keyIdsHex = keyIds.map((keyId) => (0,
|
|
410
|
+
const keyIdsHex = keyIds.map((keyId) => (0, bytes_2.bytesToHex)(keyId));
|
|
407
411
|
this.logger.info('app-state requesting missing sync keys', {
|
|
408
412
|
keys: keyIdsHex.length,
|
|
409
413
|
keyIds: keyIdsHex.join(','),
|
|
@@ -493,16 +497,16 @@ class WaAppStateSyncClient {
|
|
|
493
497
|
}
|
|
494
498
|
async applySnapshot(collection, snapshot) {
|
|
495
499
|
const version = this.normalizeProtoLong(snapshot.version?.version, `snapshot.version.version (${collection})`);
|
|
496
|
-
const keyId = (0,
|
|
500
|
+
const keyId = (0, bytes_1.decodeProtoBytes)(snapshot.keyId?.id, `snapshot.keyId.id (${collection})`);
|
|
497
501
|
const keyData = await this.getKeyData(keyId);
|
|
498
502
|
if (!keyData) {
|
|
499
|
-
throw new WaAppStateMissingKeyError(`missing snapshot key ${(0,
|
|
503
|
+
throw new WaAppStateMissingKeyError(`missing snapshot key ${(0, bytes_2.bytesToHex)(keyId)} for ${collection}`, keyId, collection);
|
|
500
504
|
}
|
|
501
505
|
const indexValueMap = new Map();
|
|
502
506
|
const mutations = [];
|
|
503
507
|
const decryptedRecords = await this.decryptSnapshotRecords(collection, snapshot);
|
|
504
508
|
for (const { decrypted, recordKeyId } of decryptedRecords) {
|
|
505
|
-
const indexMacHex = (0,
|
|
509
|
+
const indexMacHex = (0, bytes_2.bytesToHex)(decrypted.indexMac);
|
|
506
510
|
indexValueMap.set(indexMacHex, decrypted.valueMac);
|
|
507
511
|
mutations.push({
|
|
508
512
|
collection,
|
|
@@ -519,7 +523,7 @@ class WaAppStateSyncClient {
|
|
|
519
523
|
}
|
|
520
524
|
const ltHash = await this.crypto.ltHashAdd(constants_1.APP_STATE_EMPTY_LT_HASH, Array.from(indexValueMap.values()));
|
|
521
525
|
const expectedSnapshotMac = await this.crypto.generateSnapshotMac(keyData, ltHash, version, collection);
|
|
522
|
-
if (!(0,
|
|
526
|
+
if (!(0, bytes_2.uint8Equal)(expectedSnapshotMac, snapshot.mac)) {
|
|
523
527
|
throw new Error(`snapshot MAC mismatch for ${collection}`);
|
|
524
528
|
}
|
|
525
529
|
this.setCollectionState(collection, version, ltHash, indexValueMap);
|
|
@@ -531,32 +535,39 @@ class WaAppStateSyncClient {
|
|
|
531
535
|
if (current.version !== patchVersion - 1) {
|
|
532
536
|
throw new Error(`patch version mismatch for ${collection}: local=${current.version}, incoming=${patchVersion}`);
|
|
533
537
|
}
|
|
534
|
-
const patchKeyId = (0,
|
|
538
|
+
const patchKeyId = (0, bytes_1.decodeProtoBytes)(patch.keyId?.id, `patch.keyId.id (${collection})`);
|
|
535
539
|
const patchKeyData = await this.getKeyData(patchKeyId);
|
|
536
540
|
if (!patchKeyData) {
|
|
537
|
-
throw new WaAppStateMissingKeyError(`missing patch key ${(0,
|
|
541
|
+
throw new WaAppStateMissingKeyError(`missing patch key ${(0, bytes_2.bytesToHex)(patchKeyId)} for ${collection}`, patchKeyId, collection);
|
|
538
542
|
}
|
|
539
543
|
const decryptedMutations = await this.decryptPatchMutations(collection, patch);
|
|
540
|
-
const
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
544
|
+
const macMutations = new Array(decryptedMutations.length);
|
|
545
|
+
const valueMacs = new Array(decryptedMutations.length);
|
|
546
|
+
for (let index = 0; index < decryptedMutations.length; index += 1) {
|
|
547
|
+
const mutation = decryptedMutations[index];
|
|
548
|
+
valueMacs[index] = mutation.valueMac;
|
|
549
|
+
macMutations[index] = {
|
|
550
|
+
operation: mutation.operationCode,
|
|
551
|
+
indexMac: mutation.indexMac,
|
|
552
|
+
valueMac: mutation.valueMac
|
|
553
|
+
};
|
|
554
|
+
}
|
|
555
|
+
const nextState = await this.computeNextCollectionState(current.hash, current.indexValueMap, macMutations, collection);
|
|
556
|
+
await this.assertPatchMacsMatch(patch, collection, patchKeyData, patchVersion, nextState.hash, valueMacs);
|
|
546
557
|
this.setCollectionState(collection, patchVersion, nextState.hash, nextState.indexValueMap);
|
|
547
|
-
return decryptedMutations.
|
|
548
|
-
void operationCode;
|
|
549
|
-
return mutation;
|
|
550
|
-
});
|
|
558
|
+
return decryptedMutations.slice();
|
|
551
559
|
}
|
|
552
560
|
async decryptSnapshotRecords(collection, snapshot) {
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
561
|
+
const records = (snapshot.records ?? []).map((record) => ({
|
|
562
|
+
indexMac: (0, bytes_1.decodeProtoBytes)(record.index?.blob, `snapshot.record.index.blob (${collection})`),
|
|
563
|
+
valueBlob: (0, bytes_1.decodeProtoBytes)(record.value?.blob, `snapshot.record.value.blob (${collection})`),
|
|
564
|
+
recordKeyId: (0, bytes_1.decodeProtoBytes)(record.keyId?.id, `snapshot.record.keyId.id (${collection})`)
|
|
565
|
+
}));
|
|
566
|
+
await this.preloadKeyData(records.map((record) => record.recordKeyId));
|
|
567
|
+
return Promise.all(records.map(async ({ indexMac, valueBlob, recordKeyId }) => {
|
|
557
568
|
const recordKeyData = await this.getKeyData(recordKeyId);
|
|
558
569
|
if (!recordKeyData) {
|
|
559
|
-
throw new WaAppStateMissingKeyError(`missing snapshot mutation key ${(0,
|
|
570
|
+
throw new WaAppStateMissingKeyError(`missing snapshot mutation key ${(0, bytes_2.bytesToHex)(recordKeyId)} for ${collection}`, recordKeyId, collection);
|
|
560
571
|
}
|
|
561
572
|
const decrypted = await this.crypto.decryptMutation({
|
|
562
573
|
operation: _proto_1.proto.SyncdMutation.SyncdOperation.SET,
|
|
@@ -572,7 +583,7 @@ class WaAppStateSyncClient {
|
|
|
572
583
|
}));
|
|
573
584
|
}
|
|
574
585
|
async decryptPatchMutations(collection, patch) {
|
|
575
|
-
|
|
586
|
+
const parsedMutations = (patch.mutations ?? []).map((mutation) => {
|
|
576
587
|
const operationCode = mutation.operation;
|
|
577
588
|
if (operationCode === null || operationCode === undefined) {
|
|
578
589
|
throw new Error(`patch mutation is missing operation (${collection})`);
|
|
@@ -581,12 +592,18 @@ class WaAppStateSyncClient {
|
|
|
581
592
|
if (!record) {
|
|
582
593
|
throw new Error(`patch mutation is missing record (${collection})`);
|
|
583
594
|
}
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
595
|
+
return {
|
|
596
|
+
operationCode,
|
|
597
|
+
indexMac: (0, bytes_1.decodeProtoBytes)(record.index?.blob, `patch.record.index.blob (${collection})`),
|
|
598
|
+
valueBlob: (0, bytes_1.decodeProtoBytes)(record.value?.blob, `patch.record.value.blob (${collection})`),
|
|
599
|
+
recordKeyId: (0, bytes_1.decodeProtoBytes)(record.keyId?.id, `patch.record.keyId.id (${collection})`)
|
|
600
|
+
};
|
|
601
|
+
});
|
|
602
|
+
await this.preloadKeyData(parsedMutations.map((mutation) => mutation.recordKeyId));
|
|
603
|
+
return Promise.all(parsedMutations.map(async ({ operationCode, indexMac, valueBlob, recordKeyId }) => {
|
|
587
604
|
const recordKeyData = await this.getKeyData(recordKeyId);
|
|
588
605
|
if (!recordKeyData) {
|
|
589
|
-
throw new WaAppStateMissingKeyError(`missing mutation key ${(0,
|
|
606
|
+
throw new WaAppStateMissingKeyError(`missing mutation key ${(0, bytes_2.bytesToHex)(recordKeyId)} for ${collection}`, recordKeyId, collection);
|
|
590
607
|
}
|
|
591
608
|
const decrypted = await this.crypto.decryptMutation({
|
|
592
609
|
operation: operationCode,
|
|
@@ -612,15 +629,15 @@ class WaAppStateSyncClient {
|
|
|
612
629
|
};
|
|
613
630
|
}));
|
|
614
631
|
}
|
|
615
|
-
async assertPatchMacsMatch(patch, collection, patchKeyData, patchVersion, nextHash,
|
|
616
|
-
const snapshotMac = (0,
|
|
632
|
+
async assertPatchMacsMatch(patch, collection, patchKeyData, patchVersion, nextHash, valueMacs) {
|
|
633
|
+
const snapshotMac = (0, bytes_1.decodeProtoBytes)(patch.snapshotMac, `patch.snapshotMac (${collection})`);
|
|
617
634
|
const expectedSnapshotMac = await this.crypto.generateSnapshotMac(patchKeyData, nextHash, patchVersion, collection);
|
|
618
|
-
if (!(0,
|
|
635
|
+
if (!(0, bytes_2.uint8Equal)(expectedSnapshotMac, snapshotMac)) {
|
|
619
636
|
throw new Error(`patch snapshot MAC mismatch for ${collection}`);
|
|
620
637
|
}
|
|
621
|
-
const patchMac = (0,
|
|
622
|
-
const expectedPatchMac = await this.crypto.generatePatchMac(patchKeyData, snapshotMac,
|
|
623
|
-
if (!(0,
|
|
638
|
+
const patchMac = (0, bytes_1.decodeProtoBytes)(patch.patchMac, `patch.patchMac (${collection})`);
|
|
639
|
+
const expectedPatchMac = await this.crypto.generatePatchMac(patchKeyData, snapshotMac, valueMacs, patchVersion, collection);
|
|
640
|
+
if (!(0, bytes_2.uint8Equal)(expectedPatchMac, patchMac)) {
|
|
624
641
|
throw new Error(`patch MAC mismatch for ${collection}`);
|
|
625
642
|
}
|
|
626
643
|
}
|
|
@@ -661,12 +678,15 @@ class WaAppStateSyncClient {
|
|
|
661
678
|
const patchVersion = snapshot.version + 1;
|
|
662
679
|
const snapshotMac = await this.crypto.generateSnapshotMac(activeKey.keyData, nextState.hash, patchVersion, collection);
|
|
663
680
|
const patchMac = await this.crypto.generatePatchMac(activeKey.keyData, snapshotMac, macMutations.map((item) => item.valueMac), patchVersion, collection);
|
|
681
|
+
const deviceIndex = this.resolveDeviceIndex();
|
|
682
|
+
const clientDebugData = this.buildPatchClientDebugData();
|
|
664
683
|
const encodedPatch = _proto_1.proto.SyncdPatch.encode({
|
|
665
|
-
version: { version: patchVersion },
|
|
666
684
|
mutations: encryptedMutations,
|
|
667
685
|
snapshotMac,
|
|
668
686
|
patchMac,
|
|
669
|
-
keyId: { id: activeKey.keyId }
|
|
687
|
+
keyId: { id: activeKey.keyId },
|
|
688
|
+
...(deviceIndex === undefined ? {} : { deviceIndex }),
|
|
689
|
+
clientDebugData
|
|
670
690
|
}).finish();
|
|
671
691
|
return {
|
|
672
692
|
encodedPatch,
|
|
@@ -678,13 +698,35 @@ class WaAppStateSyncClient {
|
|
|
678
698
|
}
|
|
679
699
|
};
|
|
680
700
|
}
|
|
701
|
+
resolveDeviceIndex() {
|
|
702
|
+
const meJid = this.getCurrentMeJid?.();
|
|
703
|
+
if (!meJid) {
|
|
704
|
+
return undefined;
|
|
705
|
+
}
|
|
706
|
+
try {
|
|
707
|
+
return (0, jid_1.parseSignalAddressFromJid)(meJid).device;
|
|
708
|
+
}
|
|
709
|
+
catch (error) {
|
|
710
|
+
this.logger.debug('app-state could not parse device index from me jid', {
|
|
711
|
+
meJid
|
|
712
|
+
});
|
|
713
|
+
void error;
|
|
714
|
+
return undefined;
|
|
715
|
+
}
|
|
716
|
+
}
|
|
717
|
+
buildPatchClientDebugData() {
|
|
718
|
+
return _proto_1.proto.PatchDebugData.encode({
|
|
719
|
+
isSenderPrimary: false,
|
|
720
|
+
senderPlatform: _proto_1.proto.PatchDebugData.Platform.WEB
|
|
721
|
+
}).finish();
|
|
722
|
+
}
|
|
681
723
|
async computeNextCollectionState(baseHash, baseMap, mutations, collection) {
|
|
682
724
|
const indexValueMap = new Map(baseMap);
|
|
683
725
|
const addValues = [];
|
|
684
726
|
const removeValues = [];
|
|
685
727
|
let missingRemoveCount = 0;
|
|
686
728
|
for (const mutation of mutations) {
|
|
687
|
-
const indexMacHex = (0,
|
|
729
|
+
const indexMacHex = (0, bytes_2.bytesToHex)(mutation.indexMac);
|
|
688
730
|
const existing = indexValueMap.get(indexMacHex);
|
|
689
731
|
if (mutation.operation === _proto_1.proto.SyncdMutation.SyncdOperation.REMOVE) {
|
|
690
732
|
if (!existing) {
|
|
@@ -749,9 +791,33 @@ class WaAppStateSyncClient {
|
|
|
749
791
|
}
|
|
750
792
|
return compacted;
|
|
751
793
|
}
|
|
794
|
+
async preloadKeyData(keyIds) {
|
|
795
|
+
if (keyIds.length === 0) {
|
|
796
|
+
return;
|
|
797
|
+
}
|
|
798
|
+
const context = this.requireSyncContext();
|
|
799
|
+
const missingKeyIds = [];
|
|
800
|
+
const missingKeyHexes = new Set();
|
|
801
|
+
for (let index = 0; index < keyIds.length; index += 1) {
|
|
802
|
+
const keyId = keyIds[index];
|
|
803
|
+
const keyHex = (0, bytes_2.bytesToHex)(keyId);
|
|
804
|
+
if (context.keys.has(keyHex) || missingKeyHexes.has(keyHex)) {
|
|
805
|
+
continue;
|
|
806
|
+
}
|
|
807
|
+
missingKeyHexes.add(keyHex);
|
|
808
|
+
missingKeyIds.push(keyId);
|
|
809
|
+
}
|
|
810
|
+
if (missingKeyIds.length === 0) {
|
|
811
|
+
return;
|
|
812
|
+
}
|
|
813
|
+
const loadedKeyData = await this.store.getSyncKeyDataBatch(missingKeyIds);
|
|
814
|
+
for (let index = 0; index < missingKeyIds.length; index += 1) {
|
|
815
|
+
context.keys.set((0, bytes_2.bytesToHex)(missingKeyIds[index]), loadedKeyData[index] ?? null);
|
|
816
|
+
}
|
|
817
|
+
}
|
|
752
818
|
async getKeyData(keyId) {
|
|
753
819
|
const context = this.requireSyncContext();
|
|
754
|
-
const keyHex = (0,
|
|
820
|
+
const keyHex = (0, bytes_2.bytesToHex)(keyId);
|
|
755
821
|
if (context.keys.has(keyHex)) {
|
|
756
822
|
return context.keys.get(keyHex) ?? null;
|
|
757
823
|
}
|
|
@@ -772,6 +838,7 @@ class WaAppStateSyncClient {
|
|
|
772
838
|
setCollectionState(collection, version, hash, indexValueMap) {
|
|
773
839
|
const context = this.requireSyncContext();
|
|
774
840
|
context.collections.set(collection, {
|
|
841
|
+
initialized: true,
|
|
775
842
|
version,
|
|
776
843
|
hash,
|
|
777
844
|
indexValueMap
|
|
@@ -12,6 +12,12 @@ function parseSyncResponse(iqNode) {
|
|
|
12
12
|
}
|
|
13
13
|
const syncNode = (0, helpers_1.findNodeChild)(iqNode, constants_1.WA_NODE_TAGS.SYNC);
|
|
14
14
|
if (!syncNode) {
|
|
15
|
+
if (iqNode.attrs.type === constants_1.WA_IQ_TYPES.ERROR) {
|
|
16
|
+
const errorNode = (0, helpers_1.findNodeChild)(iqNode, constants_1.WA_NODE_TAGS.ERROR);
|
|
17
|
+
const code = errorNode?.attrs.code ?? 'unknown';
|
|
18
|
+
const text = errorNode?.attrs.text ?? 'unknown';
|
|
19
|
+
throw new Error(`sync iq failed (${code}: ${text})`);
|
|
20
|
+
}
|
|
15
21
|
throw new Error('sync response is missing <sync> node');
|
|
16
22
|
}
|
|
17
23
|
const payloads = [];
|
|
@@ -30,11 +36,16 @@ function parseSyncResponse(iqNode) {
|
|
|
30
36
|
}
|
|
31
37
|
version = parsedVersion;
|
|
32
38
|
}
|
|
33
|
-
const patchesNode = (0, helpers_1.
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
const
|
|
39
|
+
const [patchesNode, snapshotNode] = (0, helpers_1.findNodeChildrenByTags)(collectionNode, [
|
|
40
|
+
constants_1.WA_NODE_TAGS.PATCHES,
|
|
41
|
+
constants_1.WA_NODE_TAGS.SNAPSHOT
|
|
42
|
+
]);
|
|
43
|
+
const patches = [];
|
|
44
|
+
if (patchesNode) {
|
|
45
|
+
for (const patchNode of (0, helpers_1.getNodeChildrenByTag)(patchesNode, constants_1.WA_NODE_TAGS.PATCH)) {
|
|
46
|
+
patches.push(_proto_1.proto.SyncdPatch.decode((0, helpers_1.decodeNodeContentBase64OrBytes)(patchNode.content, 'collection.patches.patch')));
|
|
47
|
+
}
|
|
48
|
+
}
|
|
38
49
|
const snapshotReference = snapshotNode
|
|
39
50
|
? _proto_1.proto.ExternalBlobReference.decode((0, helpers_1.decodeNodeContentBase64OrBytes)(snapshotNode.content, 'collection.snapshot'))
|
|
40
51
|
: undefined;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.APP_STATE_DEFAULT_COLLECTIONS = exports.APP_STATE_EMPTY_LT_HASH = exports.APP_STATE_POINT_SIZE = exports.APP_STATE_LT_HASH_SIZE = exports.APP_STATE_IV_LENGTH = exports.APP_STATE_MAC_OCTET_LENGTH = exports.APP_STATE_VALUE_MAC_LENGTH = exports.APP_STATE_DERIVED_PATCH_MAC_KEY_END = exports.APP_STATE_DERIVED_SNAPSHOT_MAC_KEY_END = exports.APP_STATE_DERIVED_VALUE_MAC_KEY_END = exports.APP_STATE_DERIVED_VALUE_ENCRYPTION_KEY_END = exports.APP_STATE_DERIVED_INDEX_KEY_END = exports.APP_STATE_DERIVED_KEY_LENGTH = void 0;
|
|
3
|
+
exports.APP_STATE_DEFAULT_COLLECTIONS = exports.APP_STATE_DEFAULT_COLLECTION_VERSION = exports.APP_STATE_EMPTY_LT_HASH = exports.APP_STATE_POINT_SIZE = exports.APP_STATE_LT_HASH_SIZE = exports.APP_STATE_IV_LENGTH = exports.APP_STATE_MAC_OCTET_LENGTH = exports.APP_STATE_VALUE_MAC_LENGTH = exports.APP_STATE_DERIVED_PATCH_MAC_KEY_END = exports.APP_STATE_DERIVED_SNAPSHOT_MAC_KEY_END = exports.APP_STATE_DERIVED_VALUE_MAC_KEY_END = exports.APP_STATE_DERIVED_VALUE_ENCRYPTION_KEY_END = exports.APP_STATE_DERIVED_INDEX_KEY_END = exports.APP_STATE_DERIVED_KEY_LENGTH = void 0;
|
|
4
4
|
const constants_1 = require("../protocol/constants");
|
|
5
5
|
exports.APP_STATE_DERIVED_KEY_LENGTH = 160;
|
|
6
6
|
exports.APP_STATE_DERIVED_INDEX_KEY_END = 32;
|
|
@@ -14,10 +14,11 @@ exports.APP_STATE_IV_LENGTH = 16;
|
|
|
14
14
|
exports.APP_STATE_LT_HASH_SIZE = 128;
|
|
15
15
|
exports.APP_STATE_POINT_SIZE = 2;
|
|
16
16
|
exports.APP_STATE_EMPTY_LT_HASH = new Uint8Array(exports.APP_STATE_LT_HASH_SIZE);
|
|
17
|
-
exports.
|
|
17
|
+
exports.APP_STATE_DEFAULT_COLLECTION_VERSION = 0;
|
|
18
|
+
exports.APP_STATE_DEFAULT_COLLECTIONS = Object.freeze([
|
|
18
19
|
constants_1.WA_APP_STATE_COLLECTIONS.CRITICAL_UNBLOCK_LOW,
|
|
19
20
|
constants_1.WA_APP_STATE_COLLECTIONS.CRITICAL_BLOCK,
|
|
20
21
|
constants_1.WA_APP_STATE_COLLECTIONS.REGULAR_LOW,
|
|
21
22
|
constants_1.WA_APP_STATE_COLLECTIONS.REGULAR,
|
|
22
23
|
constants_1.WA_APP_STATE_COLLECTIONS.REGULAR_HIGH
|
|
23
|
-
];
|
|
24
|
+
]);
|
package/dist/appstate/utils.js
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.keyIdToHex = keyIdToHex;
|
|
4
3
|
exports.parseCollectionName = parseCollectionName;
|
|
5
4
|
exports.keyDeviceId = keyDeviceId;
|
|
6
5
|
exports.keyEpoch = keyEpoch;
|
|
@@ -8,33 +7,18 @@ exports.pickActiveSyncKey = pickActiveSyncKey;
|
|
|
8
7
|
exports.toNetworkOrder64 = toNetworkOrder64;
|
|
9
8
|
exports.downloadExternalBlobReference = downloadExternalBlobReference;
|
|
10
9
|
const constants_1 = require("../protocol/constants");
|
|
11
|
-
const base64_1 = require("../util/base64");
|
|
12
10
|
const bytes_1 = require("../util/bytes");
|
|
13
|
-
|
|
14
|
-
return (0, bytes_1.bytesToHex)(keyId);
|
|
15
|
-
}
|
|
11
|
+
const APP_STATE_COLLECTION_NAMES = new Set(Object.values(constants_1.WA_APP_STATE_COLLECTIONS));
|
|
16
12
|
function parseCollectionName(value) {
|
|
17
|
-
|
|
18
|
-
return null;
|
|
19
|
-
}
|
|
20
|
-
for (const collection of Object.values(constants_1.WA_APP_STATE_COLLECTIONS)) {
|
|
21
|
-
if (collection === value) {
|
|
22
|
-
return collection;
|
|
23
|
-
}
|
|
24
|
-
}
|
|
25
|
-
return null;
|
|
13
|
+
return value && APP_STATE_COLLECTION_NAMES.has(value) ? value : null;
|
|
26
14
|
}
|
|
27
15
|
function keyDeviceId(keyId) {
|
|
28
|
-
|
|
29
|
-
return null;
|
|
30
|
-
}
|
|
31
|
-
return (keyId[0] << 8) | keyId[1];
|
|
16
|
+
return keyId.byteLength < 6 ? null : (keyId[0] << 8) | keyId[1];
|
|
32
17
|
}
|
|
33
18
|
function keyEpoch(keyId) {
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
return new DataView(keyId.buffer, keyId.byteOffset, keyId.byteLength).getUint32(2, false);
|
|
19
|
+
return keyId.byteLength < 6
|
|
20
|
+
? -1
|
|
21
|
+
: keyId[2] * 16777216 + keyId[3] * 65536 + keyId[4] * 256 + keyId[5];
|
|
38
22
|
}
|
|
39
23
|
function pickActiveSyncKey(keys) {
|
|
40
24
|
let active = null;
|
|
@@ -61,19 +45,15 @@ function pickActiveSyncKey(keys) {
|
|
|
61
45
|
return active;
|
|
62
46
|
}
|
|
63
47
|
function toNetworkOrder64(value) {
|
|
64
|
-
|
|
65
|
-
const view = new DataView(out.buffer);
|
|
66
|
-
view.setUint32(0, Math.floor(value / 4294967296), false);
|
|
67
|
-
view.setUint32(4, value >>> 0, false);
|
|
68
|
-
return out;
|
|
48
|
+
return (0, bytes_1.intToBytes)(8, value);
|
|
69
49
|
}
|
|
70
50
|
async function downloadExternalBlobReference(mediaTransfer, reference) {
|
|
71
51
|
if (!reference.directPath) {
|
|
72
52
|
throw new Error('external blob reference is missing directPath');
|
|
73
53
|
}
|
|
74
|
-
const mediaKey = (0,
|
|
75
|
-
const fileSha256 = (0,
|
|
76
|
-
const fileEncSha256 = (0,
|
|
54
|
+
const mediaKey = (0, bytes_1.decodeProtoBytes)(reference.mediaKey, 'external blob mediaKey');
|
|
55
|
+
const fileSha256 = (0, bytes_1.decodeProtoBytes)(reference.fileSha256, 'external blob fileSha256');
|
|
56
|
+
const fileEncSha256 = (0, bytes_1.decodeProtoBytes)(reference.fileEncSha256, 'external blob fileEncSha256');
|
|
77
57
|
return mediaTransfer.downloadAndDecrypt({
|
|
78
58
|
directPath: reference.directPath,
|
|
79
59
|
mediaType: constants_1.WA_APP_STATE_KEY_TYPES.MD_APP_STATE,
|