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
|
@@ -1,11 +1,12 @@
|
|
|
1
|
-
import { APP_STATE_DEFAULT_COLLECTIONS, APP_STATE_EMPTY_LT_HASH } from './constants.js';
|
|
2
|
-
import { keyIdToHex } from './utils.js';
|
|
1
|
+
import { APP_STATE_DEFAULT_COLLECTIONS, APP_STATE_DEFAULT_COLLECTION_VERSION, APP_STATE_EMPTY_LT_HASH } from './constants.js';
|
|
3
2
|
import { WaAppStateCrypto } from './WaAppStateCrypto.js';
|
|
4
3
|
import { parseSyncResponse } from './WaAppStateSyncResponseParser.js';
|
|
5
4
|
import { proto } from '../proto.js';
|
|
6
5
|
import { WA_APP_STATE_COLLECTION_STATES, WA_DEFAULTS, WA_IQ_TYPES, WA_NODE_TAGS, WA_XMLNS } from '../protocol/constants.js';
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
6
|
+
import { parseSignalAddressFromJid } from '../protocol/jid.js';
|
|
7
|
+
import { assertIqResult } from '../transport/node/query.js';
|
|
8
|
+
import { decodeProtoBytes } from '../util/bytes.js';
|
|
9
|
+
import { bytesToHex, uint8Equal } from '../util/bytes.js';
|
|
9
10
|
import { longToNumber } from '../util/primitives.js';
|
|
10
11
|
export class WaAppStateMissingKeyError extends Error {
|
|
11
12
|
constructor(message, keyId, collection) {
|
|
@@ -20,6 +21,7 @@ export class WaAppStateSyncClient {
|
|
|
20
21
|
this.logger = options.logger;
|
|
21
22
|
this.query = options.query;
|
|
22
23
|
this.store = options.store;
|
|
24
|
+
this.getCurrentMeJid = options.getCurrentMeJid;
|
|
23
25
|
this.hostDomain = options.hostDomain ?? WA_DEFAULTS.HOST_DOMAIN;
|
|
24
26
|
this.defaultTimeoutMs = options.defaultTimeoutMs ?? WA_DEFAULTS.APP_STATE_SYNC_TIMEOUT_MS;
|
|
25
27
|
this.onMissingKeys = options.onMissingKeys;
|
|
@@ -46,7 +48,7 @@ export class WaAppStateSyncClient {
|
|
|
46
48
|
const keyId = decodeProtoBytes(item.keyId?.keyId, 'appStateSyncKeyShare.keys[].keyId.keyId');
|
|
47
49
|
if (!item.keyData?.keyData) {
|
|
48
50
|
this.logger.debug('app-state sync key share entry missing key data', {
|
|
49
|
-
keyId:
|
|
51
|
+
keyId: bytesToHex(keyId)
|
|
50
52
|
});
|
|
51
53
|
continue;
|
|
52
54
|
}
|
|
@@ -89,6 +91,10 @@ export class WaAppStateSyncClient {
|
|
|
89
91
|
...new Set(options.collections ?? APP_STATE_DEFAULT_COLLECTIONS)
|
|
90
92
|
];
|
|
91
93
|
try {
|
|
94
|
+
const initialCollectionStates = await this.store.getCollectionStates(collections);
|
|
95
|
+
for (let index = 0; index < collections.length; index += 1) {
|
|
96
|
+
context.collections.set(collections[index], initialCollectionStates[index]);
|
|
97
|
+
}
|
|
92
98
|
this.logger.info('app-state sync start', {
|
|
93
99
|
collections: collections.length,
|
|
94
100
|
pendingMutations: options.pendingMutations?.length ?? 0
|
|
@@ -158,36 +164,13 @@ export class WaAppStateSyncClient {
|
|
|
158
164
|
}
|
|
159
165
|
}
|
|
160
166
|
async syncCollectionsRound(collections, pendingByCollection, options) {
|
|
161
|
-
const prepared = await this.prepareSyncRoundRequest(collections, pendingByCollection);
|
|
162
|
-
const iqNode = this.buildSyncIqNode(prepared.collectionNodes);
|
|
163
|
-
const payloadByCollection = await this.fetchSyncPayloadByCollection(iqNode, options.timeoutMs ?? this.defaultTimeoutMs);
|
|
164
|
-
const collectionOutcomes = await Promise.all(collections.map((collection) => this.processCollectionRound({
|
|
165
|
-
collection,
|
|
166
|
-
payloadByCollection,
|
|
167
|
-
pendingByCollection,
|
|
168
|
-
options,
|
|
169
|
-
outgoingContexts: prepared.outgoingContexts,
|
|
170
|
-
skippedUploadCollections: prepared.skippedUploadCollections
|
|
171
|
-
})));
|
|
172
|
-
return {
|
|
173
|
-
results: collectionOutcomes.map((entry) => entry.result),
|
|
174
|
-
collectionsToRefetch: collectionOutcomes
|
|
175
|
-
.filter((entry) => entry.shouldRefetch)
|
|
176
|
-
.map((entry) => entry.collection),
|
|
177
|
-
stateChanged: collectionOutcomes.some((entry) => entry.stateChanged),
|
|
178
|
-
missingKeyIds: this.collectDistinctMissingKeyIds(collectionOutcomes
|
|
179
|
-
.map((entry) => entry.missingKeyId)
|
|
180
|
-
.filter((value) => value !== null)),
|
|
181
|
-
blockedCollections: collectionOutcomes
|
|
182
|
-
.filter((entry) => entry.result.state === WA_APP_STATE_COLLECTION_STATES.BLOCKED)
|
|
183
|
-
.map((entry) => entry.collection)
|
|
184
|
-
};
|
|
185
|
-
}
|
|
186
|
-
async prepareSyncRoundRequest(collections, pendingByCollection) {
|
|
187
167
|
const requests = await Promise.all(collections.map((collection) => this.buildCollectionSyncRequest(collection, pendingByCollection)));
|
|
168
|
+
const collectionNodes = new Array(requests.length);
|
|
188
169
|
const outgoingContexts = new Map();
|
|
189
170
|
const skippedUploadCollections = new Set();
|
|
190
|
-
for (
|
|
171
|
+
for (let index = 0; index < requests.length; index += 1) {
|
|
172
|
+
const request = requests[index];
|
|
173
|
+
collectionNodes[index] = request.node;
|
|
191
174
|
if (request.outgoingContext) {
|
|
192
175
|
outgoingContexts.set(request.collection, request.outgoingContext);
|
|
193
176
|
}
|
|
@@ -195,26 +178,57 @@ export class WaAppStateSyncClient {
|
|
|
195
178
|
skippedUploadCollections.add(request.collection);
|
|
196
179
|
}
|
|
197
180
|
}
|
|
198
|
-
|
|
199
|
-
|
|
181
|
+
const iqNode = this.buildSyncIqNode(collectionNodes);
|
|
182
|
+
const payloadByCollection = await this.fetchSyncPayloadByCollection(iqNode, options.timeoutMs ?? this.defaultTimeoutMs);
|
|
183
|
+
const collectionOutcomes = await Promise.all(collections.map((collection) => this.processCollectionRound({
|
|
184
|
+
collection,
|
|
185
|
+
payloadByCollection,
|
|
186
|
+
pendingByCollection,
|
|
187
|
+
options,
|
|
200
188
|
outgoingContexts,
|
|
201
189
|
skippedUploadCollections
|
|
190
|
+
})));
|
|
191
|
+
const results = [];
|
|
192
|
+
const collectionsToRefetch = [];
|
|
193
|
+
const blockedCollections = [];
|
|
194
|
+
const missingKeyIds = [];
|
|
195
|
+
const missingKeyIdHexes = new Set();
|
|
196
|
+
let stateChanged = false;
|
|
197
|
+
for (const entry of collectionOutcomes) {
|
|
198
|
+
results.push(entry.result);
|
|
199
|
+
if (entry.shouldRefetch) {
|
|
200
|
+
collectionsToRefetch.push(entry.collection);
|
|
201
|
+
}
|
|
202
|
+
if (entry.stateChanged) {
|
|
203
|
+
stateChanged = true;
|
|
204
|
+
}
|
|
205
|
+
if (entry.result.state === WA_APP_STATE_COLLECTION_STATES.BLOCKED) {
|
|
206
|
+
blockedCollections.push(entry.collection);
|
|
207
|
+
}
|
|
208
|
+
if (entry.missingKeyId) {
|
|
209
|
+
const keyHex = bytesToHex(entry.missingKeyId);
|
|
210
|
+
if (!missingKeyIdHexes.has(keyHex)) {
|
|
211
|
+
missingKeyIdHexes.add(keyHex);
|
|
212
|
+
missingKeyIds.push(entry.missingKeyId);
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
return {
|
|
217
|
+
results,
|
|
218
|
+
collectionsToRefetch,
|
|
219
|
+
stateChanged,
|
|
220
|
+
missingKeyIds,
|
|
221
|
+
blockedCollections
|
|
202
222
|
};
|
|
203
223
|
}
|
|
204
224
|
async buildCollectionSyncRequest(collection, pendingByCollection) {
|
|
205
225
|
const collectionState = await this.getCollectionState(collection);
|
|
206
|
-
const hasPersistedState = collectionState.
|
|
207
|
-
collectionState.indexValueMap.size > 0 ||
|
|
208
|
-
!uint8Equal(collectionState.hash, APP_STATE_EMPTY_LT_HASH);
|
|
226
|
+
const hasPersistedState = collectionState.initialized;
|
|
209
227
|
const attrs = {
|
|
210
|
-
name: collection
|
|
228
|
+
name: collection,
|
|
229
|
+
version: String(hasPersistedState ? collectionState.version : APP_STATE_DEFAULT_COLLECTION_VERSION),
|
|
230
|
+
return_snapshot: hasPersistedState ? 'false' : 'true'
|
|
211
231
|
};
|
|
212
|
-
if (hasPersistedState) {
|
|
213
|
-
attrs.version = String(collectionState.version);
|
|
214
|
-
}
|
|
215
|
-
else {
|
|
216
|
-
attrs.return_snapshot = 'true';
|
|
217
|
-
}
|
|
218
232
|
const children = [];
|
|
219
233
|
const pendingMutations = pendingByCollection.get(collection) ?? [];
|
|
220
234
|
let outgoingContext;
|
|
@@ -271,6 +285,7 @@ export class WaAppStateSyncClient {
|
|
|
271
285
|
tag: responseNode.tag,
|
|
272
286
|
type: responseNode.attrs.type
|
|
273
287
|
});
|
|
288
|
+
assertIqResult(responseNode, 'app-state sync');
|
|
274
289
|
const payloads = parseSyncResponse(responseNode);
|
|
275
290
|
this.logger.debug('app-state sync payloads parsed', { count: payloads.length });
|
|
276
291
|
const payloadByCollection = new Map();
|
|
@@ -292,20 +307,16 @@ export class WaAppStateSyncClient {
|
|
|
292
307
|
return this.createCollectionOutcome(collection, payload.state, payload.version);
|
|
293
308
|
}
|
|
294
309
|
const pendingMutationsCount = pendingByCollection.get(collection)?.length ?? 0;
|
|
295
|
-
if (payload.state === WA_APP_STATE_COLLECTION_STATES.
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
: WA_APP_STATE_COLLECTION_STATES.SUCCESS, payload.version, shouldRefetch);
|
|
306
|
-
}
|
|
307
|
-
if (payload.state === WA_APP_STATE_COLLECTION_STATES.CONFLICT_HAS_MORE) {
|
|
308
|
-
return this.createCollectionOutcome(collection, payload.state, payload.version, shouldRefetch);
|
|
310
|
+
if (payload.state === WA_APP_STATE_COLLECTION_STATES.CONFLICT ||
|
|
311
|
+
payload.state === WA_APP_STATE_COLLECTION_STATES.CONFLICT_HAS_MORE) {
|
|
312
|
+
shouldRefetch =
|
|
313
|
+
payload.state === WA_APP_STATE_COLLECTION_STATES.CONFLICT_HAS_MORE ||
|
|
314
|
+
pendingMutationsCount > 0;
|
|
315
|
+
return this.createCollectionOutcome(collection, payload.state === WA_APP_STATE_COLLECTION_STATES.CONFLICT
|
|
316
|
+
? pendingMutationsCount > 0
|
|
317
|
+
? WA_APP_STATE_COLLECTION_STATES.CONFLICT
|
|
318
|
+
: WA_APP_STATE_COLLECTION_STATES.SUCCESS
|
|
319
|
+
: payload.state, payload.version, shouldRefetch);
|
|
309
320
|
}
|
|
310
321
|
try {
|
|
311
322
|
let appliedMutations = [];
|
|
@@ -337,13 +348,17 @@ export class WaAppStateSyncClient {
|
|
|
337
348
|
collectionStateChanged = true;
|
|
338
349
|
}
|
|
339
350
|
}
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
shouldRefetch = true;
|
|
351
|
+
const currentCollectionState = await this.getCollectionState(collection);
|
|
352
|
+
if (!currentCollectionState.initialized &&
|
|
353
|
+
payload.state === WA_APP_STATE_COLLECTION_STATES.SUCCESS) {
|
|
354
|
+
this.setCollectionState(collection, payload.version ?? currentCollectionState.version, currentCollectionState.hash, currentCollectionState.indexValueMap);
|
|
355
|
+
collectionStateChanged = true;
|
|
346
356
|
}
|
|
357
|
+
shouldRefetch =
|
|
358
|
+
shouldRefetch ||
|
|
359
|
+
payload.state === WA_APP_STATE_COLLECTION_STATES.SUCCESS_HAS_MORE ||
|
|
360
|
+
(payload.state === WA_APP_STATE_COLLECTION_STATES.SUCCESS &&
|
|
361
|
+
skippedUploadCollections.has(collection));
|
|
347
362
|
this.logger.debug('app-state collection processed', {
|
|
348
363
|
collection: payload.collection,
|
|
349
364
|
state: payload.state,
|
|
@@ -382,24 +397,13 @@ export class WaAppStateSyncClient {
|
|
|
382
397
|
}
|
|
383
398
|
};
|
|
384
399
|
}
|
|
385
|
-
collectDistinctMissingKeyIds(keyIds) {
|
|
386
|
-
const byHex = new Map();
|
|
387
|
-
for (const keyId of keyIds) {
|
|
388
|
-
const keyHex = keyIdToHex(keyId);
|
|
389
|
-
if (byHex.has(keyHex)) {
|
|
390
|
-
continue;
|
|
391
|
-
}
|
|
392
|
-
byHex.set(keyHex, keyId);
|
|
393
|
-
}
|
|
394
|
-
return [...byHex.values()];
|
|
395
|
-
}
|
|
396
400
|
async notifyMissingKeys(input) {
|
|
397
|
-
const keyIds =
|
|
398
|
-
const collections =
|
|
401
|
+
const keyIds = input.keyIds;
|
|
402
|
+
const collections = input.collections;
|
|
399
403
|
if (keyIds.length === 0 || collections.length === 0) {
|
|
400
404
|
return;
|
|
401
405
|
}
|
|
402
|
-
const keyIdsHex = keyIds.map((keyId) =>
|
|
406
|
+
const keyIdsHex = keyIds.map((keyId) => bytesToHex(keyId));
|
|
403
407
|
this.logger.info('app-state requesting missing sync keys', {
|
|
404
408
|
keys: keyIdsHex.length,
|
|
405
409
|
keyIds: keyIdsHex.join(','),
|
|
@@ -492,13 +496,13 @@ export class WaAppStateSyncClient {
|
|
|
492
496
|
const keyId = decodeProtoBytes(snapshot.keyId?.id, `snapshot.keyId.id (${collection})`);
|
|
493
497
|
const keyData = await this.getKeyData(keyId);
|
|
494
498
|
if (!keyData) {
|
|
495
|
-
throw new WaAppStateMissingKeyError(`missing snapshot key ${
|
|
499
|
+
throw new WaAppStateMissingKeyError(`missing snapshot key ${bytesToHex(keyId)} for ${collection}`, keyId, collection);
|
|
496
500
|
}
|
|
497
501
|
const indexValueMap = new Map();
|
|
498
502
|
const mutations = [];
|
|
499
503
|
const decryptedRecords = await this.decryptSnapshotRecords(collection, snapshot);
|
|
500
504
|
for (const { decrypted, recordKeyId } of decryptedRecords) {
|
|
501
|
-
const indexMacHex =
|
|
505
|
+
const indexMacHex = bytesToHex(decrypted.indexMac);
|
|
502
506
|
indexValueMap.set(indexMacHex, decrypted.valueMac);
|
|
503
507
|
mutations.push({
|
|
504
508
|
collection,
|
|
@@ -530,29 +534,36 @@ export class WaAppStateSyncClient {
|
|
|
530
534
|
const patchKeyId = decodeProtoBytes(patch.keyId?.id, `patch.keyId.id (${collection})`);
|
|
531
535
|
const patchKeyData = await this.getKeyData(patchKeyId);
|
|
532
536
|
if (!patchKeyData) {
|
|
533
|
-
throw new WaAppStateMissingKeyError(`missing patch key ${
|
|
537
|
+
throw new WaAppStateMissingKeyError(`missing patch key ${bytesToHex(patchKeyId)} for ${collection}`, patchKeyId, collection);
|
|
534
538
|
}
|
|
535
539
|
const decryptedMutations = await this.decryptPatchMutations(collection, patch);
|
|
536
|
-
const
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
540
|
+
const macMutations = new Array(decryptedMutations.length);
|
|
541
|
+
const valueMacs = new Array(decryptedMutations.length);
|
|
542
|
+
for (let index = 0; index < decryptedMutations.length; index += 1) {
|
|
543
|
+
const mutation = decryptedMutations[index];
|
|
544
|
+
valueMacs[index] = mutation.valueMac;
|
|
545
|
+
macMutations[index] = {
|
|
546
|
+
operation: mutation.operationCode,
|
|
547
|
+
indexMac: mutation.indexMac,
|
|
548
|
+
valueMac: mutation.valueMac
|
|
549
|
+
};
|
|
550
|
+
}
|
|
551
|
+
const nextState = await this.computeNextCollectionState(current.hash, current.indexValueMap, macMutations, collection);
|
|
552
|
+
await this.assertPatchMacsMatch(patch, collection, patchKeyData, patchVersion, nextState.hash, valueMacs);
|
|
542
553
|
this.setCollectionState(collection, patchVersion, nextState.hash, nextState.indexValueMap);
|
|
543
|
-
return decryptedMutations.
|
|
544
|
-
void operationCode;
|
|
545
|
-
return mutation;
|
|
546
|
-
});
|
|
554
|
+
return decryptedMutations.slice();
|
|
547
555
|
}
|
|
548
556
|
async decryptSnapshotRecords(collection, snapshot) {
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
557
|
+
const records = (snapshot.records ?? []).map((record) => ({
|
|
558
|
+
indexMac: decodeProtoBytes(record.index?.blob, `snapshot.record.index.blob (${collection})`),
|
|
559
|
+
valueBlob: decodeProtoBytes(record.value?.blob, `snapshot.record.value.blob (${collection})`),
|
|
560
|
+
recordKeyId: decodeProtoBytes(record.keyId?.id, `snapshot.record.keyId.id (${collection})`)
|
|
561
|
+
}));
|
|
562
|
+
await this.preloadKeyData(records.map((record) => record.recordKeyId));
|
|
563
|
+
return Promise.all(records.map(async ({ indexMac, valueBlob, recordKeyId }) => {
|
|
553
564
|
const recordKeyData = await this.getKeyData(recordKeyId);
|
|
554
565
|
if (!recordKeyData) {
|
|
555
|
-
throw new WaAppStateMissingKeyError(`missing snapshot mutation key ${
|
|
566
|
+
throw new WaAppStateMissingKeyError(`missing snapshot mutation key ${bytesToHex(recordKeyId)} for ${collection}`, recordKeyId, collection);
|
|
556
567
|
}
|
|
557
568
|
const decrypted = await this.crypto.decryptMutation({
|
|
558
569
|
operation: proto.SyncdMutation.SyncdOperation.SET,
|
|
@@ -568,7 +579,7 @@ export class WaAppStateSyncClient {
|
|
|
568
579
|
}));
|
|
569
580
|
}
|
|
570
581
|
async decryptPatchMutations(collection, patch) {
|
|
571
|
-
|
|
582
|
+
const parsedMutations = (patch.mutations ?? []).map((mutation) => {
|
|
572
583
|
const operationCode = mutation.operation;
|
|
573
584
|
if (operationCode === null || operationCode === undefined) {
|
|
574
585
|
throw new Error(`patch mutation is missing operation (${collection})`);
|
|
@@ -577,12 +588,18 @@ export class WaAppStateSyncClient {
|
|
|
577
588
|
if (!record) {
|
|
578
589
|
throw new Error(`patch mutation is missing record (${collection})`);
|
|
579
590
|
}
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
591
|
+
return {
|
|
592
|
+
operationCode,
|
|
593
|
+
indexMac: decodeProtoBytes(record.index?.blob, `patch.record.index.blob (${collection})`),
|
|
594
|
+
valueBlob: decodeProtoBytes(record.value?.blob, `patch.record.value.blob (${collection})`),
|
|
595
|
+
recordKeyId: decodeProtoBytes(record.keyId?.id, `patch.record.keyId.id (${collection})`)
|
|
596
|
+
};
|
|
597
|
+
});
|
|
598
|
+
await this.preloadKeyData(parsedMutations.map((mutation) => mutation.recordKeyId));
|
|
599
|
+
return Promise.all(parsedMutations.map(async ({ operationCode, indexMac, valueBlob, recordKeyId }) => {
|
|
583
600
|
const recordKeyData = await this.getKeyData(recordKeyId);
|
|
584
601
|
if (!recordKeyData) {
|
|
585
|
-
throw new WaAppStateMissingKeyError(`missing mutation key ${
|
|
602
|
+
throw new WaAppStateMissingKeyError(`missing mutation key ${bytesToHex(recordKeyId)} for ${collection}`, recordKeyId, collection);
|
|
586
603
|
}
|
|
587
604
|
const decrypted = await this.crypto.decryptMutation({
|
|
588
605
|
operation: operationCode,
|
|
@@ -608,14 +625,14 @@ export class WaAppStateSyncClient {
|
|
|
608
625
|
};
|
|
609
626
|
}));
|
|
610
627
|
}
|
|
611
|
-
async assertPatchMacsMatch(patch, collection, patchKeyData, patchVersion, nextHash,
|
|
628
|
+
async assertPatchMacsMatch(patch, collection, patchKeyData, patchVersion, nextHash, valueMacs) {
|
|
612
629
|
const snapshotMac = decodeProtoBytes(patch.snapshotMac, `patch.snapshotMac (${collection})`);
|
|
613
630
|
const expectedSnapshotMac = await this.crypto.generateSnapshotMac(patchKeyData, nextHash, patchVersion, collection);
|
|
614
631
|
if (!uint8Equal(expectedSnapshotMac, snapshotMac)) {
|
|
615
632
|
throw new Error(`patch snapshot MAC mismatch for ${collection}`);
|
|
616
633
|
}
|
|
617
634
|
const patchMac = decodeProtoBytes(patch.patchMac, `patch.patchMac (${collection})`);
|
|
618
|
-
const expectedPatchMac = await this.crypto.generatePatchMac(patchKeyData, snapshotMac,
|
|
635
|
+
const expectedPatchMac = await this.crypto.generatePatchMac(patchKeyData, snapshotMac, valueMacs, patchVersion, collection);
|
|
619
636
|
if (!uint8Equal(expectedPatchMac, patchMac)) {
|
|
620
637
|
throw new Error(`patch MAC mismatch for ${collection}`);
|
|
621
638
|
}
|
|
@@ -657,12 +674,15 @@ export class WaAppStateSyncClient {
|
|
|
657
674
|
const patchVersion = snapshot.version + 1;
|
|
658
675
|
const snapshotMac = await this.crypto.generateSnapshotMac(activeKey.keyData, nextState.hash, patchVersion, collection);
|
|
659
676
|
const patchMac = await this.crypto.generatePatchMac(activeKey.keyData, snapshotMac, macMutations.map((item) => item.valueMac), patchVersion, collection);
|
|
677
|
+
const deviceIndex = this.resolveDeviceIndex();
|
|
678
|
+
const clientDebugData = this.buildPatchClientDebugData();
|
|
660
679
|
const encodedPatch = proto.SyncdPatch.encode({
|
|
661
|
-
version: { version: patchVersion },
|
|
662
680
|
mutations: encryptedMutations,
|
|
663
681
|
snapshotMac,
|
|
664
682
|
patchMac,
|
|
665
|
-
keyId: { id: activeKey.keyId }
|
|
683
|
+
keyId: { id: activeKey.keyId },
|
|
684
|
+
...(deviceIndex === undefined ? {} : { deviceIndex }),
|
|
685
|
+
clientDebugData
|
|
666
686
|
}).finish();
|
|
667
687
|
return {
|
|
668
688
|
encodedPatch,
|
|
@@ -674,13 +694,35 @@ export class WaAppStateSyncClient {
|
|
|
674
694
|
}
|
|
675
695
|
};
|
|
676
696
|
}
|
|
697
|
+
resolveDeviceIndex() {
|
|
698
|
+
const meJid = this.getCurrentMeJid?.();
|
|
699
|
+
if (!meJid) {
|
|
700
|
+
return undefined;
|
|
701
|
+
}
|
|
702
|
+
try {
|
|
703
|
+
return parseSignalAddressFromJid(meJid).device;
|
|
704
|
+
}
|
|
705
|
+
catch (error) {
|
|
706
|
+
this.logger.debug('app-state could not parse device index from me jid', {
|
|
707
|
+
meJid
|
|
708
|
+
});
|
|
709
|
+
void error;
|
|
710
|
+
return undefined;
|
|
711
|
+
}
|
|
712
|
+
}
|
|
713
|
+
buildPatchClientDebugData() {
|
|
714
|
+
return proto.PatchDebugData.encode({
|
|
715
|
+
isSenderPrimary: false,
|
|
716
|
+
senderPlatform: proto.PatchDebugData.Platform.WEB
|
|
717
|
+
}).finish();
|
|
718
|
+
}
|
|
677
719
|
async computeNextCollectionState(baseHash, baseMap, mutations, collection) {
|
|
678
720
|
const indexValueMap = new Map(baseMap);
|
|
679
721
|
const addValues = [];
|
|
680
722
|
const removeValues = [];
|
|
681
723
|
let missingRemoveCount = 0;
|
|
682
724
|
for (const mutation of mutations) {
|
|
683
|
-
const indexMacHex =
|
|
725
|
+
const indexMacHex = bytesToHex(mutation.indexMac);
|
|
684
726
|
const existing = indexValueMap.get(indexMacHex);
|
|
685
727
|
if (mutation.operation === proto.SyncdMutation.SyncdOperation.REMOVE) {
|
|
686
728
|
if (!existing) {
|
|
@@ -745,9 +787,33 @@ export class WaAppStateSyncClient {
|
|
|
745
787
|
}
|
|
746
788
|
return compacted;
|
|
747
789
|
}
|
|
790
|
+
async preloadKeyData(keyIds) {
|
|
791
|
+
if (keyIds.length === 0) {
|
|
792
|
+
return;
|
|
793
|
+
}
|
|
794
|
+
const context = this.requireSyncContext();
|
|
795
|
+
const missingKeyIds = [];
|
|
796
|
+
const missingKeyHexes = new Set();
|
|
797
|
+
for (let index = 0; index < keyIds.length; index += 1) {
|
|
798
|
+
const keyId = keyIds[index];
|
|
799
|
+
const keyHex = bytesToHex(keyId);
|
|
800
|
+
if (context.keys.has(keyHex) || missingKeyHexes.has(keyHex)) {
|
|
801
|
+
continue;
|
|
802
|
+
}
|
|
803
|
+
missingKeyHexes.add(keyHex);
|
|
804
|
+
missingKeyIds.push(keyId);
|
|
805
|
+
}
|
|
806
|
+
if (missingKeyIds.length === 0) {
|
|
807
|
+
return;
|
|
808
|
+
}
|
|
809
|
+
const loadedKeyData = await this.store.getSyncKeyDataBatch(missingKeyIds);
|
|
810
|
+
for (let index = 0; index < missingKeyIds.length; index += 1) {
|
|
811
|
+
context.keys.set(bytesToHex(missingKeyIds[index]), loadedKeyData[index] ?? null);
|
|
812
|
+
}
|
|
813
|
+
}
|
|
748
814
|
async getKeyData(keyId) {
|
|
749
815
|
const context = this.requireSyncContext();
|
|
750
|
-
const keyHex =
|
|
816
|
+
const keyHex = bytesToHex(keyId);
|
|
751
817
|
if (context.keys.has(keyHex)) {
|
|
752
818
|
return context.keys.get(keyHex) ?? null;
|
|
753
819
|
}
|
|
@@ -768,6 +834,7 @@ export class WaAppStateSyncClient {
|
|
|
768
834
|
setCollectionState(collection, version, hash, indexValueMap) {
|
|
769
835
|
const context = this.requireSyncContext();
|
|
770
836
|
context.collections.set(collection, {
|
|
837
|
+
initialized: true,
|
|
771
838
|
version,
|
|
772
839
|
hash,
|
|
773
840
|
indexValueMap
|
|
@@ -1,13 +1,19 @@
|
|
|
1
1
|
import { parseCollectionName } from './utils.js';
|
|
2
2
|
import { proto } from '../proto.js';
|
|
3
3
|
import { WA_APP_STATE_COLLECTION_STATES, WA_APP_STATE_ERROR_CODES, WA_IQ_TYPES, WA_NODE_TAGS } from '../protocol/constants.js';
|
|
4
|
-
import { decodeNodeContentBase64OrBytes, findNodeChild, getNodeChildrenByTag } from '../transport/node/helpers.js';
|
|
4
|
+
import { decodeNodeContentBase64OrBytes, findNodeChildrenByTags, findNodeChild, getNodeChildrenByTag } from '../transport/node/helpers.js';
|
|
5
5
|
export function parseSyncResponse(iqNode) {
|
|
6
6
|
if (iqNode.tag !== WA_NODE_TAGS.IQ) {
|
|
7
7
|
throw new Error(`invalid sync response tag ${iqNode.tag}`);
|
|
8
8
|
}
|
|
9
9
|
const syncNode = findNodeChild(iqNode, WA_NODE_TAGS.SYNC);
|
|
10
10
|
if (!syncNode) {
|
|
11
|
+
if (iqNode.attrs.type === WA_IQ_TYPES.ERROR) {
|
|
12
|
+
const errorNode = findNodeChild(iqNode, WA_NODE_TAGS.ERROR);
|
|
13
|
+
const code = errorNode?.attrs.code ?? 'unknown';
|
|
14
|
+
const text = errorNode?.attrs.text ?? 'unknown';
|
|
15
|
+
throw new Error(`sync iq failed (${code}: ${text})`);
|
|
16
|
+
}
|
|
11
17
|
throw new Error('sync response is missing <sync> node');
|
|
12
18
|
}
|
|
13
19
|
const payloads = [];
|
|
@@ -26,11 +32,16 @@ export function parseSyncResponse(iqNode) {
|
|
|
26
32
|
}
|
|
27
33
|
version = parsedVersion;
|
|
28
34
|
}
|
|
29
|
-
const patchesNode =
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
const
|
|
35
|
+
const [patchesNode, snapshotNode] = findNodeChildrenByTags(collectionNode, [
|
|
36
|
+
WA_NODE_TAGS.PATCHES,
|
|
37
|
+
WA_NODE_TAGS.SNAPSHOT
|
|
38
|
+
]);
|
|
39
|
+
const patches = [];
|
|
40
|
+
if (patchesNode) {
|
|
41
|
+
for (const patchNode of getNodeChildrenByTag(patchesNode, WA_NODE_TAGS.PATCH)) {
|
|
42
|
+
patches.push(proto.SyncdPatch.decode(decodeNodeContentBase64OrBytes(patchNode.content, 'collection.patches.patch')));
|
|
43
|
+
}
|
|
44
|
+
}
|
|
34
45
|
const snapshotReference = snapshotNode
|
|
35
46
|
? proto.ExternalBlobReference.decode(decodeNodeContentBase64OrBytes(snapshotNode.content, 'collection.snapshot'))
|
|
36
47
|
: undefined;
|
|
@@ -11,10 +11,11 @@ export const APP_STATE_IV_LENGTH = 16;
|
|
|
11
11
|
export const APP_STATE_LT_HASH_SIZE = 128;
|
|
12
12
|
export const APP_STATE_POINT_SIZE = 2;
|
|
13
13
|
export const APP_STATE_EMPTY_LT_HASH = new Uint8Array(APP_STATE_LT_HASH_SIZE);
|
|
14
|
-
export const
|
|
14
|
+
export const APP_STATE_DEFAULT_COLLECTION_VERSION = 0;
|
|
15
|
+
export const APP_STATE_DEFAULT_COLLECTIONS = Object.freeze([
|
|
15
16
|
WA_APP_STATE_COLLECTIONS.CRITICAL_UNBLOCK_LOW,
|
|
16
17
|
WA_APP_STATE_COLLECTIONS.CRITICAL_BLOCK,
|
|
17
18
|
WA_APP_STATE_COLLECTIONS.REGULAR_LOW,
|
|
18
19
|
WA_APP_STATE_COLLECTIONS.REGULAR,
|
|
19
20
|
WA_APP_STATE_COLLECTIONS.REGULAR_HIGH
|
|
20
|
-
];
|
|
21
|
+
]);
|
|
@@ -1,31 +1,16 @@
|
|
|
1
1
|
import { WA_APP_STATE_COLLECTIONS, WA_APP_STATE_KEY_TYPES } from '../protocol/constants.js';
|
|
2
|
-
import { decodeProtoBytes } from '../util/
|
|
3
|
-
|
|
4
|
-
export function keyIdToHex(keyId) {
|
|
5
|
-
return bytesToHex(keyId);
|
|
6
|
-
}
|
|
2
|
+
import { decodeProtoBytes, intToBytes } from '../util/bytes.js';
|
|
3
|
+
const APP_STATE_COLLECTION_NAMES = new Set(Object.values(WA_APP_STATE_COLLECTIONS));
|
|
7
4
|
export function parseCollectionName(value) {
|
|
8
|
-
|
|
9
|
-
return null;
|
|
10
|
-
}
|
|
11
|
-
for (const collection of Object.values(WA_APP_STATE_COLLECTIONS)) {
|
|
12
|
-
if (collection === value) {
|
|
13
|
-
return collection;
|
|
14
|
-
}
|
|
15
|
-
}
|
|
16
|
-
return null;
|
|
5
|
+
return value && APP_STATE_COLLECTION_NAMES.has(value) ? value : null;
|
|
17
6
|
}
|
|
18
7
|
export function keyDeviceId(keyId) {
|
|
19
|
-
|
|
20
|
-
return null;
|
|
21
|
-
}
|
|
22
|
-
return (keyId[0] << 8) | keyId[1];
|
|
8
|
+
return keyId.byteLength < 6 ? null : (keyId[0] << 8) | keyId[1];
|
|
23
9
|
}
|
|
24
10
|
export function keyEpoch(keyId) {
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
return new DataView(keyId.buffer, keyId.byteOffset, keyId.byteLength).getUint32(2, false);
|
|
11
|
+
return keyId.byteLength < 6
|
|
12
|
+
? -1
|
|
13
|
+
: keyId[2] * 16777216 + keyId[3] * 65536 + keyId[4] * 256 + keyId[5];
|
|
29
14
|
}
|
|
30
15
|
export function pickActiveSyncKey(keys) {
|
|
31
16
|
let active = null;
|
|
@@ -52,11 +37,7 @@ export function pickActiveSyncKey(keys) {
|
|
|
52
37
|
return active;
|
|
53
38
|
}
|
|
54
39
|
export function toNetworkOrder64(value) {
|
|
55
|
-
|
|
56
|
-
const view = new DataView(out.buffer);
|
|
57
|
-
view.setUint32(0, Math.floor(value / 4294967296), false);
|
|
58
|
-
view.setUint32(4, value >>> 0, false);
|
|
59
|
-
return out;
|
|
40
|
+
return intToBytes(8, value);
|
|
60
41
|
}
|
|
61
42
|
export async function downloadExternalBlobReference(mediaTransfer, reference) {
|
|
62
43
|
if (!reference.directPath) {
|