@ledgerhq/live-common 34.51.0-nightly.0 → 34.51.0-nightly.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/lib/bridge/generic-alpaca/accountBridge.d.ts.map +1 -1
- package/lib/bridge/generic-alpaca/accountBridge.js +2 -0
- package/lib/bridge/generic-alpaca/accountBridge.js.map +1 -1
- package/lib/bridge/generic-alpaca/alpaca/network/network-alpaca.d.ts +1 -0
- package/lib/bridge/generic-alpaca/alpaca/network/network-alpaca.d.ts.map +1 -1
- package/lib/bridge/generic-alpaca/alpaca/network/network-alpaca.js +3 -0
- package/lib/bridge/generic-alpaca/alpaca/network/network-alpaca.js.map +1 -1
- package/lib/bridge/generic-alpaca/prepareTransaction.d.ts.map +1 -1
- package/lib/bridge/generic-alpaca/prepareTransaction.js +37 -45
- package/lib/bridge/generic-alpaca/prepareTransaction.js.map +1 -1
- package/lib/bridge/generic-alpaca/signOperation.d.ts.map +1 -1
- package/lib/bridge/generic-alpaca/signOperation.js +0 -20
- package/lib/bridge/generic-alpaca/signOperation.js.map +1 -1
- package/lib/bridge/generic-alpaca/signRawOperation.d.ts +8 -0
- package/lib/bridge/generic-alpaca/signRawOperation.d.ts.map +1 -0
- package/lib/bridge/generic-alpaca/signRawOperation.js +55 -0
- package/lib/bridge/generic-alpaca/signRawOperation.js.map +1 -0
- package/lib/bridge/generic-alpaca/tests/getAccountShape.test.js +1 -0
- package/lib/bridge/generic-alpaca/tests/getAccountShape.test.js.map +1 -1
- package/lib/bridge/generic-alpaca/tests/prepareTransaction.test.js +186 -88
- package/lib/bridge/generic-alpaca/tests/prepareTransaction.test.js.map +1 -1
- package/lib/bridge/generic-alpaca/utils.d.ts.map +1 -1
- package/lib/bridge/generic-alpaca/utils.js +1 -0
- package/lib/bridge/generic-alpaca/utils.js.map +1 -1
- package/lib/bridge/mockHelpers.d.ts +1 -0
- package/lib/bridge/mockHelpers.d.ts.map +1 -1
- package/lib/bridge/mockHelpers.js +53 -1
- package/lib/bridge/mockHelpers.js.map +1 -1
- package/lib/bridge/react/BridgeSync.d.ts +1 -0
- package/lib/bridge/react/BridgeSync.d.ts.map +1 -1
- package/lib/bridge/react/BridgeSync.js +19 -16
- package/lib/bridge/react/BridgeSync.js.map +1 -1
- package/lib/bridge/react/BridgeSync.test.js +403 -66
- package/lib/bridge/react/BridgeSync.test.js.map +1 -1
- package/lib/dada-client/entities/index.d.ts +1 -1
- package/lib/dada-client/entities/index.d.ts.map +1 -1
- package/lib/e2e/index.d.ts +8 -0
- package/lib/e2e/index.d.ts.map +1 -1
- package/lib/families/algorand/bridge/mock.d.ts.map +1 -1
- package/lib/families/algorand/bridge/mock.js +1 -0
- package/lib/families/algorand/bridge/mock.js.map +1 -1
- package/lib/families/bitcoin/bridge/mock.d.ts.map +1 -1
- package/lib/families/bitcoin/bridge/mock.js +1 -0
- package/lib/families/bitcoin/bridge/mock.js.map +1 -1
- package/lib/families/canton/bridge/mock.d.ts.map +1 -1
- package/lib/families/canton/bridge/mock.js +3 -0
- package/lib/families/canton/bridge/mock.js.map +1 -1
- package/lib/families/cardano/bridge/mock.d.ts.map +1 -1
- package/lib/families/cardano/bridge/mock.js +1 -0
- package/lib/families/cardano/bridge/mock.js.map +1 -1
- package/lib/families/casper/bridge/mock.d.ts.map +1 -1
- package/lib/families/casper/bridge/mock.js +1 -0
- package/lib/families/casper/bridge/mock.js.map +1 -1
- package/lib/families/cosmos/bridge/mock.d.ts.map +1 -1
- package/lib/families/cosmos/bridge/mock.js +1 -0
- package/lib/families/cosmos/bridge/mock.js.map +1 -1
- package/lib/families/evm/bridge/mock.d.ts.map +1 -1
- package/lib/families/evm/bridge/mock.js +1 -0
- package/lib/families/evm/bridge/mock.js.map +1 -1
- package/lib/families/icon/bridge/mock.d.ts.map +1 -1
- package/lib/families/icon/bridge/mock.js +1 -0
- package/lib/families/icon/bridge/mock.js.map +1 -1
- package/lib/families/multiversx/bridge/mock.d.ts.map +1 -1
- package/lib/families/multiversx/bridge/mock.js +1 -0
- package/lib/families/multiversx/bridge/mock.js.map +1 -1
- package/lib/families/polkadot/bridge/mock.d.ts.map +1 -1
- package/lib/families/polkadot/bridge/mock.js +1 -0
- package/lib/families/polkadot/bridge/mock.js.map +1 -1
- package/lib/families/polkadot/config.d.ts.map +1 -1
- package/lib/families/polkadot/config.js +84 -0
- package/lib/families/polkadot/config.js.map +1 -1
- package/lib/families/polkadot/setup.d.ts.map +1 -1
- package/lib/families/polkadot/setup.js +5 -4
- package/lib/families/polkadot/setup.js.map +1 -1
- package/lib/families/solana/bridge/mock.d.ts +1 -0
- package/lib/families/solana/bridge/mock.d.ts.map +1 -1
- package/lib/families/stellar/bridge/mock.d.ts.map +1 -1
- package/lib/families/stellar/bridge/mock.js +1 -0
- package/lib/families/stellar/bridge/mock.js.map +1 -1
- package/lib/families/tezos/bridge/mock.d.ts.map +1 -1
- package/lib/families/tezos/bridge/mock.js +1 -0
- package/lib/families/tezos/bridge/mock.js.map +1 -1
- package/lib/families/tron/bridge/mock.d.ts.map +1 -1
- package/lib/families/tron/bridge/mock.js +1 -0
- package/lib/families/tron/bridge/mock.js.map +1 -1
- package/lib/families/xrp/bridge/mock.d.ts.map +1 -1
- package/lib/families/xrp/bridge/mock.js +1 -0
- package/lib/families/xrp/bridge/mock.js.map +1 -1
- package/lib/featureFlags/defaultFeatures.d.ts +3 -0
- package/lib/featureFlags/defaultFeatures.d.ts.map +1 -1
- package/lib/featureFlags/defaultFeatures.js +10 -1
- package/lib/featureFlags/defaultFeatures.js.map +1 -1
- package/lib/featureFlags/useFeature.d.ts +1 -1
- package/lib/featureFlags/useFeature.d.ts.map +1 -1
- package/lib/generated/bridge/mock.d.ts +1 -0
- package/lib/generated/bridge/mock.d.ts.map +1 -1
- package/lib/hw/actions/rawTransaction.d.ts +37 -0
- package/lib/hw/actions/rawTransaction.d.ts.map +1 -0
- package/lib/hw/actions/rawTransaction.js +107 -0
- package/lib/hw/actions/rawTransaction.js.map +1 -0
- package/lib/modularDrawer/hooks/useCurrenciesUnderFeatureFlag.d.ts.map +1 -1
- package/lib/modularDrawer/hooks/useCurrenciesUnderFeatureFlag.js +9 -0
- package/lib/modularDrawer/hooks/useCurrenciesUnderFeatureFlag.js.map +1 -1
- package/lib/wallet-api/logic.d.ts +1 -0
- package/lib/wallet-api/logic.d.ts.map +1 -1
- package/lib/wallet-api/logic.js +21 -1
- package/lib/wallet-api/logic.js.map +1 -1
- package/lib/wallet-api/react.d.ts +9 -1
- package/lib/wallet-api/react.d.ts.map +1 -1
- package/lib/wallet-api/react.js +60 -2
- package/lib/wallet-api/react.js.map +1 -1
- package/lib/wallet-api/tracking.d.ts +3 -0
- package/lib/wallet-api/tracking.d.ts.map +1 -1
- package/lib/wallet-api/tracking.js +12 -0
- package/lib/wallet-api/tracking.js.map +1 -1
- package/lib-es/bridge/generic-alpaca/accountBridge.d.ts.map +1 -1
- package/lib-es/bridge/generic-alpaca/accountBridge.js +2 -0
- package/lib-es/bridge/generic-alpaca/accountBridge.js.map +1 -1
- package/lib-es/bridge/generic-alpaca/alpaca/network/network-alpaca.d.ts +1 -0
- package/lib-es/bridge/generic-alpaca/alpaca/network/network-alpaca.d.ts.map +1 -1
- package/lib-es/bridge/generic-alpaca/alpaca/network/network-alpaca.js +3 -0
- package/lib-es/bridge/generic-alpaca/alpaca/network/network-alpaca.js.map +1 -1
- package/lib-es/bridge/generic-alpaca/prepareTransaction.d.ts.map +1 -1
- package/lib-es/bridge/generic-alpaca/prepareTransaction.js +37 -45
- package/lib-es/bridge/generic-alpaca/prepareTransaction.js.map +1 -1
- package/lib-es/bridge/generic-alpaca/signOperation.d.ts.map +1 -1
- package/lib-es/bridge/generic-alpaca/signOperation.js +0 -17
- package/lib-es/bridge/generic-alpaca/signOperation.js.map +1 -1
- package/lib-es/bridge/generic-alpaca/signRawOperation.d.ts +8 -0
- package/lib-es/bridge/generic-alpaca/signRawOperation.d.ts.map +1 -0
- package/lib-es/bridge/generic-alpaca/signRawOperation.js +48 -0
- package/lib-es/bridge/generic-alpaca/signRawOperation.js.map +1 -0
- package/lib-es/bridge/generic-alpaca/tests/getAccountShape.test.js +1 -0
- package/lib-es/bridge/generic-alpaca/tests/getAccountShape.test.js.map +1 -1
- package/lib-es/bridge/generic-alpaca/tests/prepareTransaction.test.js +163 -88
- package/lib-es/bridge/generic-alpaca/tests/prepareTransaction.test.js.map +1 -1
- package/lib-es/bridge/generic-alpaca/utils.d.ts.map +1 -1
- package/lib-es/bridge/generic-alpaca/utils.js +1 -0
- package/lib-es/bridge/generic-alpaca/utils.js.map +1 -1
- package/lib-es/bridge/mockHelpers.d.ts +1 -0
- package/lib-es/bridge/mockHelpers.d.ts.map +1 -1
- package/lib-es/bridge/mockHelpers.js +51 -0
- package/lib-es/bridge/mockHelpers.js.map +1 -1
- package/lib-es/bridge/react/BridgeSync.d.ts +1 -0
- package/lib-es/bridge/react/BridgeSync.d.ts.map +1 -1
- package/lib-es/bridge/react/BridgeSync.js +17 -15
- package/lib-es/bridge/react/BridgeSync.js.map +1 -1
- package/lib-es/bridge/react/BridgeSync.test.js +382 -65
- package/lib-es/bridge/react/BridgeSync.test.js.map +1 -1
- package/lib-es/dada-client/entities/index.d.ts +1 -1
- package/lib-es/dada-client/entities/index.d.ts.map +1 -1
- package/lib-es/e2e/index.d.ts +8 -0
- package/lib-es/e2e/index.d.ts.map +1 -1
- package/lib-es/families/algorand/bridge/mock.d.ts.map +1 -1
- package/lib-es/families/algorand/bridge/mock.js +2 -1
- package/lib-es/families/algorand/bridge/mock.js.map +1 -1
- package/lib-es/families/bitcoin/bridge/mock.d.ts.map +1 -1
- package/lib-es/families/bitcoin/bridge/mock.js +2 -1
- package/lib-es/families/bitcoin/bridge/mock.js.map +1 -1
- package/lib-es/families/canton/bridge/mock.d.ts.map +1 -1
- package/lib-es/families/canton/bridge/mock.js +3 -0
- package/lib-es/families/canton/bridge/mock.js.map +1 -1
- package/lib-es/families/cardano/bridge/mock.d.ts.map +1 -1
- package/lib-es/families/cardano/bridge/mock.js +2 -1
- package/lib-es/families/cardano/bridge/mock.js.map +1 -1
- package/lib-es/families/casper/bridge/mock.d.ts.map +1 -1
- package/lib-es/families/casper/bridge/mock.js +2 -1
- package/lib-es/families/casper/bridge/mock.js.map +1 -1
- package/lib-es/families/cosmos/bridge/mock.d.ts.map +1 -1
- package/lib-es/families/cosmos/bridge/mock.js +2 -1
- package/lib-es/families/cosmos/bridge/mock.js.map +1 -1
- package/lib-es/families/evm/bridge/mock.d.ts.map +1 -1
- package/lib-es/families/evm/bridge/mock.js +2 -1
- package/lib-es/families/evm/bridge/mock.js.map +1 -1
- package/lib-es/families/icon/bridge/mock.d.ts.map +1 -1
- package/lib-es/families/icon/bridge/mock.js +2 -1
- package/lib-es/families/icon/bridge/mock.js.map +1 -1
- package/lib-es/families/multiversx/bridge/mock.d.ts.map +1 -1
- package/lib-es/families/multiversx/bridge/mock.js +2 -1
- package/lib-es/families/multiversx/bridge/mock.js.map +1 -1
- package/lib-es/families/polkadot/bridge/mock.d.ts.map +1 -1
- package/lib-es/families/polkadot/bridge/mock.js +2 -1
- package/lib-es/families/polkadot/bridge/mock.js.map +1 -1
- package/lib-es/families/polkadot/config.d.ts.map +1 -1
- package/lib-es/families/polkadot/config.js +84 -0
- package/lib-es/families/polkadot/config.js.map +1 -1
- package/lib-es/families/polkadot/setup.d.ts.map +1 -1
- package/lib-es/families/polkadot/setup.js +5 -4
- package/lib-es/families/polkadot/setup.js.map +1 -1
- package/lib-es/families/solana/bridge/mock.d.ts +1 -0
- package/lib-es/families/solana/bridge/mock.d.ts.map +1 -1
- package/lib-es/families/stellar/bridge/mock.d.ts.map +1 -1
- package/lib-es/families/stellar/bridge/mock.js +2 -1
- package/lib-es/families/stellar/bridge/mock.js.map +1 -1
- package/lib-es/families/tezos/bridge/mock.d.ts.map +1 -1
- package/lib-es/families/tezos/bridge/mock.js +2 -1
- package/lib-es/families/tezos/bridge/mock.js.map +1 -1
- package/lib-es/families/tron/bridge/mock.d.ts.map +1 -1
- package/lib-es/families/tron/bridge/mock.js +2 -1
- package/lib-es/families/tron/bridge/mock.js.map +1 -1
- package/lib-es/families/xrp/bridge/mock.d.ts.map +1 -1
- package/lib-es/families/xrp/bridge/mock.js +2 -1
- package/lib-es/families/xrp/bridge/mock.js.map +1 -1
- package/lib-es/featureFlags/defaultFeatures.d.ts +3 -0
- package/lib-es/featureFlags/defaultFeatures.d.ts.map +1 -1
- package/lib-es/featureFlags/defaultFeatures.js +10 -1
- package/lib-es/featureFlags/defaultFeatures.js.map +1 -1
- package/lib-es/featureFlags/useFeature.d.ts +1 -1
- package/lib-es/featureFlags/useFeature.d.ts.map +1 -1
- package/lib-es/generated/bridge/mock.d.ts +1 -0
- package/lib-es/generated/bridge/mock.d.ts.map +1 -1
- package/lib-es/hw/actions/rawTransaction.d.ts +37 -0
- package/lib-es/hw/actions/rawTransaction.d.ts.map +1 -0
- package/lib-es/hw/actions/rawTransaction.js +103 -0
- package/lib-es/hw/actions/rawTransaction.js.map +1 -0
- package/lib-es/modularDrawer/hooks/useCurrenciesUnderFeatureFlag.d.ts.map +1 -1
- package/lib-es/modularDrawer/hooks/useCurrenciesUnderFeatureFlag.js +9 -0
- package/lib-es/modularDrawer/hooks/useCurrenciesUnderFeatureFlag.js.map +1 -1
- package/lib-es/wallet-api/logic.d.ts +1 -0
- package/lib-es/wallet-api/logic.d.ts.map +1 -1
- package/lib-es/wallet-api/logic.js +19 -0
- package/lib-es/wallet-api/logic.js.map +1 -1
- package/lib-es/wallet-api/react.d.ts +9 -1
- package/lib-es/wallet-api/react.d.ts.map +1 -1
- package/lib-es/wallet-api/react.js +61 -3
- package/lib-es/wallet-api/react.js.map +1 -1
- package/lib-es/wallet-api/tracking.d.ts +3 -0
- package/lib-es/wallet-api/tracking.d.ts.map +1 -1
- package/lib-es/wallet-api/tracking.js +12 -0
- package/lib-es/wallet-api/tracking.js.map +1 -1
- package/package.json +54 -54
- package/src/bridge/generic-alpaca/accountBridge.ts +2 -0
- package/src/bridge/generic-alpaca/alpaca/network/network-alpaca.ts +8 -0
- package/src/bridge/generic-alpaca/prepareTransaction.ts +46 -69
- package/src/bridge/generic-alpaca/signOperation.ts +0 -20
- package/src/bridge/generic-alpaca/signRawOperation.ts +86 -0
- package/src/bridge/generic-alpaca/tests/getAccountShape.test.ts +1 -0
- package/src/bridge/generic-alpaca/tests/prepareTransaction.test.ts +191 -109
- package/src/bridge/generic-alpaca/utils.ts +1 -0
- package/src/bridge/mockHelpers.ts +57 -0
- package/src/bridge/react/BridgeSync.test.tsx +513 -82
- package/src/bridge/react/BridgeSync.tsx +18 -17
- package/src/dada-client/MIGRATION_GUIDE.md +215 -0
- package/src/dada-client/entities/index.ts +1 -1
- package/src/families/algorand/bridge/mock.ts +2 -0
- package/src/families/bitcoin/bridge/mock.ts +2 -0
- package/src/families/canton/bridge/mock.ts +3 -0
- package/src/families/cardano/bridge/mock.ts +2 -0
- package/src/families/casper/bridge/mock.ts +2 -0
- package/src/families/cosmos/bridge/mock.ts +2 -0
- package/src/families/evm/bridge/mock.ts +2 -0
- package/src/families/icon/bridge/mock.ts +2 -0
- package/src/families/multiversx/bridge/mock.ts +2 -0
- package/src/families/polkadot/bridge/mock.ts +2 -0
- package/src/families/polkadot/config.ts +84 -0
- package/src/families/polkadot/setup.ts +6 -4
- package/src/families/stellar/bridge/mock.ts +2 -0
- package/src/families/tezos/bridge/mock.ts +2 -0
- package/src/families/tron/bridge/mock.ts +2 -0
- package/src/families/xrp/bridge/mock.ts +2 -0
- package/src/featureFlags/defaultFeatures.ts +10 -1
- package/src/hw/actions/rawTransaction.ts +190 -0
- package/src/modularDrawer/hooks/useCurrenciesUnderFeatureFlag.ts +9 -0
- package/src/wallet-api/logic.ts +35 -0
- package/src/wallet-api/react.ts +87 -1
- package/src/wallet-api/tracking.ts +15 -0
|
@@ -134,6 +134,7 @@ export function transactionToIntent(
|
|
|
134
134
|
const res: TransactionIntent & { memo?: { type: string; value?: string } } & {
|
|
135
135
|
data?: { type: string; value?: unknown };
|
|
136
136
|
} = {
|
|
137
|
+
intentType: isStaking ? "staking" : "transaction",
|
|
137
138
|
type: intentType,
|
|
138
139
|
sender: account.freshAddress,
|
|
139
140
|
recipient: transaction.recipient,
|
|
@@ -183,3 +183,60 @@ export const makeAccountBridgeReceive: () => (
|
|
|
183
183
|
path: account.freshAddressPath,
|
|
184
184
|
publicKey: "mockPublickKey", // We could probably keep the publicKey in `account.freshPublicKey`
|
|
185
185
|
});
|
|
186
|
+
|
|
187
|
+
export const signRawOperation: AccountBridge<any>["signRawOperation"] = ({ account }) =>
|
|
188
|
+
new Observable(o => {
|
|
189
|
+
let cancelled = false;
|
|
190
|
+
|
|
191
|
+
async function main() {
|
|
192
|
+
await delay(1000);
|
|
193
|
+
if (cancelled) return;
|
|
194
|
+
|
|
195
|
+
for (let i = 0; i <= 1; i += 0.1) {
|
|
196
|
+
o.next({
|
|
197
|
+
type: "device-streaming",
|
|
198
|
+
progress: i,
|
|
199
|
+
index: i,
|
|
200
|
+
total: 10,
|
|
201
|
+
});
|
|
202
|
+
await delay(300);
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
o.next({
|
|
206
|
+
type: "device-signature-requested",
|
|
207
|
+
});
|
|
208
|
+
await delay(2000);
|
|
209
|
+
if (cancelled) return;
|
|
210
|
+
o.next({
|
|
211
|
+
type: "device-signature-granted",
|
|
212
|
+
});
|
|
213
|
+
const rng = new Prando("");
|
|
214
|
+
const op = genOperation(account, account, account.operations, rng);
|
|
215
|
+
op.type = "OUT";
|
|
216
|
+
op.value = new BigNumber(0);
|
|
217
|
+
op.blockHash = null;
|
|
218
|
+
op.blockHeight = null;
|
|
219
|
+
op.senders = [account.freshAddress];
|
|
220
|
+
op.recipients = [];
|
|
221
|
+
op.blockHeight = account.blockHeight;
|
|
222
|
+
op.date = new Date();
|
|
223
|
+
await delay(1000);
|
|
224
|
+
if (cancelled) return;
|
|
225
|
+
broadcasted[account.id] = (broadcasted[account.id] || []).concat(op);
|
|
226
|
+
o.next({
|
|
227
|
+
type: "signed",
|
|
228
|
+
signedOperation: {
|
|
229
|
+
operation: { ...op },
|
|
230
|
+
signature: "",
|
|
231
|
+
},
|
|
232
|
+
});
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
main().then(
|
|
236
|
+
() => o.complete(),
|
|
237
|
+
e => o.error(e),
|
|
238
|
+
);
|
|
239
|
+
return () => {
|
|
240
|
+
cancelled = true;
|
|
241
|
+
};
|
|
242
|
+
});
|
|
@@ -2,13 +2,19 @@
|
|
|
2
2
|
* @jest-environment jsdom
|
|
3
3
|
*/
|
|
4
4
|
import "../../__tests__/test-helpers/dom-polyfill";
|
|
5
|
-
import React from "react";
|
|
5
|
+
import React, { useEffect } from "react";
|
|
6
6
|
import { render, screen } from "@testing-library/react";
|
|
7
|
+
import type { Account } from "@ledgerhq/types-live";
|
|
8
|
+
import type { CryptoCurrency } from "@ledgerhq/types-cryptoassets";
|
|
9
|
+
import { Observable } from "rxjs";
|
|
10
|
+
import type { Observer } from "rxjs";
|
|
7
11
|
import { getCryptoCurrencyById } from "@ledgerhq/cryptoassets";
|
|
8
12
|
import { genAccount } from "../../mock/account";
|
|
9
|
-
import { BridgeSync } from "./BridgeSync";
|
|
13
|
+
import { BridgeSync, resetStates } from "./BridgeSync";
|
|
10
14
|
import { setSupportedCurrencies } from "../../currencies";
|
|
11
|
-
import
|
|
15
|
+
import * as Bridge from "..";
|
|
16
|
+
import { useBridgeSync, useBridgeSyncState } from "./context";
|
|
17
|
+
import type { Sync, BridgeSyncState } from "./types";
|
|
12
18
|
|
|
13
19
|
jest.setTimeout(30000);
|
|
14
20
|
|
|
@@ -24,96 +30,521 @@ const defaultsBridgeSyncOpts = {
|
|
|
24
30
|
|
|
25
31
|
setSupportedCurrencies(["bitcoin", "ethereum"]);
|
|
26
32
|
|
|
33
|
+
const bitcoin = getCryptoCurrencyById("bitcoin");
|
|
34
|
+
const ethereum = getCryptoCurrencyById("ethereum");
|
|
35
|
+
|
|
36
|
+
const createAccount = (
|
|
37
|
+
id: string,
|
|
38
|
+
currency: CryptoCurrency,
|
|
39
|
+
options: Parameters<typeof genAccount>[1] = {},
|
|
40
|
+
) => genAccount(id, { ...options, currency });
|
|
41
|
+
|
|
42
|
+
type BridgeSyncRenderProps = Partial<Omit<React.ComponentProps<typeof BridgeSync>, "children">>;
|
|
43
|
+
|
|
44
|
+
const renderBridgeSync = (props: BridgeSyncRenderProps = {}, children: React.ReactNode = null) =>
|
|
45
|
+
render(
|
|
46
|
+
<BridgeSync {...defaultsBridgeSyncOpts} {...props}>
|
|
47
|
+
{children}
|
|
48
|
+
</BridgeSync>,
|
|
49
|
+
);
|
|
50
|
+
|
|
51
|
+
type AccountUpdater = (arg0: Account) => Account;
|
|
52
|
+
|
|
53
|
+
const baseGetAccountBridge = Bridge.getAccountBridge;
|
|
54
|
+
|
|
55
|
+
const withMockedAccountBridge = (
|
|
56
|
+
account: Account,
|
|
57
|
+
syncFactory: () => Observable<AccountUpdater>,
|
|
58
|
+
) => {
|
|
59
|
+
const originalBridge = baseGetAccountBridge(account);
|
|
60
|
+
const mockBridge = {
|
|
61
|
+
...originalBridge,
|
|
62
|
+
sync: syncFactory,
|
|
63
|
+
};
|
|
64
|
+
return jest.spyOn(Bridge, "getAccountBridge").mockImplementation(acc => {
|
|
65
|
+
if (acc.id === account.id) {
|
|
66
|
+
return mockBridge;
|
|
67
|
+
}
|
|
68
|
+
return baseGetAccountBridge(acc);
|
|
69
|
+
});
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
const mockBridgeSync = (
|
|
73
|
+
account: Account,
|
|
74
|
+
producer: (observer: Observer<AccountUpdater>) => void | (() => void),
|
|
75
|
+
) =>
|
|
76
|
+
withMockedAccountBridge(
|
|
77
|
+
account,
|
|
78
|
+
() =>
|
|
79
|
+
new Observable<AccountUpdater>(observer => {
|
|
80
|
+
const cleanup = producer(observer);
|
|
81
|
+
return typeof cleanup === "function" ? cleanup : undefined;
|
|
82
|
+
}),
|
|
83
|
+
);
|
|
84
|
+
|
|
27
85
|
describe("BridgeSync", () => {
|
|
86
|
+
afterEach(() => {
|
|
87
|
+
jest.restoreAllMocks();
|
|
88
|
+
resetStates();
|
|
89
|
+
});
|
|
90
|
+
|
|
28
91
|
test("initialize without an error", async () => {
|
|
29
|
-
|
|
92
|
+
renderBridgeSync({}, "LOADED");
|
|
30
93
|
expect(screen.getByText("LOADED")).not.toBeNull();
|
|
31
94
|
});
|
|
32
95
|
|
|
33
|
-
test("executes a sync at start tracked as reason=initial",
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
});
|
|
57
|
-
resolve(null);
|
|
58
|
-
}
|
|
96
|
+
test("executes a sync at start tracked as reason=initial", done => {
|
|
97
|
+
const account = createAccount("btc1", bitcoin);
|
|
98
|
+
const futureOpLength = account.operations.length;
|
|
99
|
+
// we remove the first operation to feed it back as a broadcasted one, the mock impl will make it go back to operations
|
|
100
|
+
const lastOp = account.operations.splice(0, 1)[0];
|
|
101
|
+
Bridge.getAccountBridge(account).broadcast({
|
|
102
|
+
account,
|
|
103
|
+
signedOperation: {
|
|
104
|
+
operation: lastOp,
|
|
105
|
+
signature: "",
|
|
106
|
+
},
|
|
107
|
+
});
|
|
108
|
+
const accounts = [account];
|
|
109
|
+
expect(accounts[0].operations.length).toBe(futureOpLength - 1);
|
|
110
|
+
|
|
111
|
+
function track(type, opts) {
|
|
112
|
+
if (type === "SyncSuccess") {
|
|
113
|
+
expect(opts).toMatchObject({
|
|
114
|
+
reason: "initial",
|
|
115
|
+
currencyName: "Bitcoin",
|
|
116
|
+
operationsLength: futureOpLength,
|
|
117
|
+
});
|
|
118
|
+
done();
|
|
59
119
|
}
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
120
|
+
}
|
|
121
|
+
renderBridgeSync({ accounts, trackAnalytics: track });
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
test("sync all accounts in parallel at start tracked as reason=initial", done => {
|
|
125
|
+
const accounts = [
|
|
126
|
+
createAccount("2btc1", bitcoin),
|
|
127
|
+
createAccount("2btc2", bitcoin),
|
|
128
|
+
createAccount("2eth1", ethereum),
|
|
129
|
+
];
|
|
130
|
+
const synced: Array<Record<string, unknown>> = [];
|
|
131
|
+
let resolveFirst;
|
|
132
|
+
function prepareCurrency() {
|
|
133
|
+
if (!resolveFirst) {
|
|
134
|
+
return new Promise((resolve, reject) => {
|
|
135
|
+
resolveFirst = resolve;
|
|
136
|
+
setTimeout(
|
|
137
|
+
reject,
|
|
138
|
+
5000,
|
|
139
|
+
new Error("prepareCurrency doesn't seem to be called in parallel"),
|
|
140
|
+
);
|
|
141
|
+
});
|
|
142
|
+
}
|
|
143
|
+
// if we reach here, it means, we managed to have
|
|
144
|
+
// a SECOND sync that need to prepare currency
|
|
145
|
+
// so it's a proof that sync correctly runs in parallel
|
|
146
|
+
// otherwise it would timeout
|
|
147
|
+
resolveFirst();
|
|
148
|
+
return Promise.resolve();
|
|
149
|
+
}
|
|
150
|
+
function track(type, opts) {
|
|
151
|
+
expect(type).not.toEqual("SyncError");
|
|
152
|
+
if (type === "SyncSuccess") {
|
|
153
|
+
synced.push(opts);
|
|
154
|
+
expect(opts).toMatchObject({
|
|
155
|
+
reason: "initial",
|
|
156
|
+
});
|
|
157
|
+
if (synced.length === accounts.length) done();
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
renderBridgeSync({
|
|
161
|
+
accounts,
|
|
162
|
+
prepareCurrency,
|
|
163
|
+
trackAnalytics: track,
|
|
65
164
|
});
|
|
66
165
|
});
|
|
67
166
|
|
|
68
|
-
test("
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
167
|
+
test("provides context values correctly", () => {
|
|
168
|
+
const account = createAccount("btc1", bitcoin);
|
|
169
|
+
const accounts = [account];
|
|
170
|
+
|
|
171
|
+
let syncFunction: Sync | undefined;
|
|
172
|
+
let syncState: BridgeSyncState | undefined;
|
|
173
|
+
|
|
174
|
+
function TestComponent() {
|
|
175
|
+
syncFunction = useBridgeSync();
|
|
176
|
+
syncState = useBridgeSyncState();
|
|
177
|
+
return <div data-testid="test-component">Test</div>;
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
renderBridgeSync({ accounts }, <TestComponent />);
|
|
181
|
+
|
|
182
|
+
expect(syncFunction).toBeDefined();
|
|
183
|
+
expect(typeof syncFunction).toBe("function");
|
|
184
|
+
expect(syncState).toBeDefined();
|
|
185
|
+
expect(typeof syncState).toBe("object");
|
|
186
|
+
});
|
|
187
|
+
|
|
188
|
+
test("handles sync errors with recoverError function", done => {
|
|
189
|
+
const account = createAccount("btc1", bitcoin);
|
|
190
|
+
const accounts = [account];
|
|
191
|
+
|
|
192
|
+
const mockError = new Error("Sync failed");
|
|
193
|
+
const recoverError = jest.fn((error: Error) => {
|
|
194
|
+
expect(error.message).toBe("Sync failed");
|
|
195
|
+
return error; // Return error to treat as actual error
|
|
196
|
+
});
|
|
197
|
+
|
|
198
|
+
// Mock the account bridge to return an Observable that emits an error
|
|
199
|
+
mockBridgeSync(account, observer => {
|
|
200
|
+
const timeout = setTimeout(() => observer.error(mockError), 100);
|
|
201
|
+
return () => clearTimeout(timeout);
|
|
202
|
+
});
|
|
203
|
+
|
|
204
|
+
let syncStateChecked = false;
|
|
205
|
+
let syncStateRef: BridgeSyncState;
|
|
206
|
+
function TestComponent() {
|
|
207
|
+
const syncState = useBridgeSyncState();
|
|
208
|
+
syncStateRef = syncState;
|
|
209
|
+
|
|
210
|
+
// After the error is silenced, the sync state should show no error
|
|
211
|
+
setTimeout(() => {
|
|
212
|
+
if (!syncStateChecked && syncStateRef[account.id]) {
|
|
213
|
+
syncStateChecked = true;
|
|
214
|
+
expect(syncStateRef[account.id].error).toBe(mockError);
|
|
215
|
+
expect(recoverError).toHaveBeenCalledWith(mockError);
|
|
216
|
+
done();
|
|
89
217
|
}
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
218
|
+
}, 200);
|
|
219
|
+
|
|
220
|
+
return <div>Test</div>;
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
renderBridgeSync({ accounts, recoverError }, <TestComponent />);
|
|
224
|
+
});
|
|
225
|
+
|
|
226
|
+
test("silences errors when recoverError returns null", done => {
|
|
227
|
+
const account = createAccount("btc1", bitcoin);
|
|
228
|
+
const accounts = [account];
|
|
229
|
+
|
|
230
|
+
const mockError = new Error("Sync failed but should be silenced");
|
|
231
|
+
const recoverError = jest.fn(() => null); // Return null to silence the error
|
|
232
|
+
|
|
233
|
+
// Mock the account bridge to return an Observable that emits an error
|
|
234
|
+
mockBridgeSync(account, observer => {
|
|
235
|
+
const timeout = setTimeout(() => observer.error(mockError), 100);
|
|
236
|
+
return () => clearTimeout(timeout);
|
|
237
|
+
});
|
|
238
|
+
|
|
239
|
+
let syncStateChecked = false;
|
|
240
|
+
let syncStateRef: BridgeSyncState;
|
|
241
|
+
function TestComponent() {
|
|
242
|
+
const syncState = useBridgeSyncState();
|
|
243
|
+
syncStateRef = syncState;
|
|
244
|
+
|
|
245
|
+
// After the error is silenced, the sync state should show no error
|
|
246
|
+
setTimeout(() => {
|
|
247
|
+
if (!syncStateChecked && syncStateRef[account.id]) {
|
|
248
|
+
syncStateChecked = true;
|
|
249
|
+
expect(syncStateRef[account.id].error).toBeNull();
|
|
250
|
+
expect(recoverError).toHaveBeenCalledWith(mockError);
|
|
251
|
+
done();
|
|
105
252
|
}
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
253
|
+
}, 200);
|
|
254
|
+
|
|
255
|
+
return <div>Test</div>;
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
renderBridgeSync({ accounts, recoverError }, <TestComponent />);
|
|
259
|
+
});
|
|
260
|
+
|
|
261
|
+
test("handles blacklisted token IDs in sync config", () => {
|
|
262
|
+
const account = createAccount("btc1", bitcoin);
|
|
263
|
+
const blacklistedTokenIds = ["token1", "token2"];
|
|
264
|
+
|
|
265
|
+
renderBridgeSync({ accounts: [account], blacklistedTokenIds });
|
|
266
|
+
|
|
267
|
+
// Test passes if component renders without errors with blacklisted tokens
|
|
268
|
+
expect(blacklistedTokenIds).toHaveLength(2);
|
|
269
|
+
});
|
|
270
|
+
|
|
271
|
+
test("handles sync actions correctly", () => {
|
|
272
|
+
const account1 = createAccount("btc1", bitcoin);
|
|
273
|
+
const account2 = createAccount("eth1", ethereum);
|
|
274
|
+
const accounts = [account1, account2];
|
|
275
|
+
|
|
276
|
+
let sync: Sync | undefined;
|
|
277
|
+
|
|
278
|
+
function TestComponent() {
|
|
279
|
+
sync = useBridgeSync();
|
|
280
|
+
return <div>Test</div>;
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
renderBridgeSync({ accounts }, <TestComponent />);
|
|
284
|
+
|
|
285
|
+
expect(sync).toBeDefined();
|
|
286
|
+
|
|
287
|
+
// Test different sync actions
|
|
288
|
+
expect(() => {
|
|
289
|
+
sync?.({ type: "SYNC_ALL_ACCOUNTS", priority: 1, reason: "manual" });
|
|
290
|
+
}).not.toThrow();
|
|
291
|
+
|
|
292
|
+
expect(() => {
|
|
293
|
+
sync?.({ type: "SYNC_ONE_ACCOUNT", accountId: account1.id, priority: 1, reason: "manual" });
|
|
294
|
+
}).not.toThrow();
|
|
295
|
+
|
|
296
|
+
expect(() => {
|
|
297
|
+
sync?.({
|
|
298
|
+
type: "SYNC_SOME_ACCOUNTS",
|
|
299
|
+
accountIds: [account1.id],
|
|
300
|
+
priority: 1,
|
|
301
|
+
reason: "manual",
|
|
302
|
+
});
|
|
303
|
+
}).not.toThrow();
|
|
304
|
+
|
|
305
|
+
expect(() => {
|
|
306
|
+
sync?.({ type: "SET_SKIP_UNDER_PRIORITY", priority: 5 });
|
|
307
|
+
}).not.toThrow();
|
|
308
|
+
|
|
309
|
+
expect(() => {
|
|
310
|
+
sync?.({ type: "BACKGROUND_TICK", reason: "background" });
|
|
311
|
+
}).not.toThrow();
|
|
312
|
+
});
|
|
313
|
+
|
|
314
|
+
test("handles pending operations sync", () => {
|
|
315
|
+
const account = createAccount("btc1", bitcoin);
|
|
316
|
+
|
|
317
|
+
// Create account with pending operations
|
|
318
|
+
const accountWithPending = {
|
|
319
|
+
...account,
|
|
320
|
+
pendingOperations: [
|
|
321
|
+
{
|
|
322
|
+
id: "pending1",
|
|
323
|
+
hash: "hash1",
|
|
324
|
+
type: "OUT" as const,
|
|
325
|
+
value: account.balance,
|
|
326
|
+
fee: account.balance.dividedBy(10),
|
|
327
|
+
blockHash: null,
|
|
328
|
+
blockHeight: null,
|
|
329
|
+
senders: [account.freshAddress],
|
|
330
|
+
recipients: ["recipient1"],
|
|
331
|
+
accountId: account.id,
|
|
332
|
+
date: new Date(),
|
|
333
|
+
extra: {},
|
|
334
|
+
},
|
|
335
|
+
],
|
|
336
|
+
};
|
|
337
|
+
|
|
338
|
+
const accounts = [accountWithPending];
|
|
339
|
+
|
|
340
|
+
let sync: Sync | undefined;
|
|
341
|
+
|
|
342
|
+
function TestComponent() {
|
|
343
|
+
sync = useBridgeSync();
|
|
344
|
+
return <div>Test</div>;
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
renderBridgeSync({ accounts }, <TestComponent />);
|
|
348
|
+
|
|
349
|
+
expect(sync).toBeDefined();
|
|
350
|
+
|
|
351
|
+
// The component should automatically sync accounts with pending operations
|
|
352
|
+
// This is tested by checking that the component renders without errors
|
|
353
|
+
// and that pending operations are handled properly
|
|
354
|
+
expect(accountWithPending.pendingOperations.length).toBeGreaterThan(0);
|
|
355
|
+
});
|
|
356
|
+
|
|
357
|
+
test("hydrates currencies only once", async () => {
|
|
358
|
+
const account1 = createAccount("btc1", bitcoin);
|
|
359
|
+
const account2 = createAccount("btc2", bitcoin); // Same currency
|
|
360
|
+
const account3 = createAccount("eth1", ethereum);
|
|
361
|
+
const accounts = [account1, account2, account3];
|
|
362
|
+
|
|
363
|
+
const hydrateCurrency = jest.fn(() => Promise.resolve());
|
|
364
|
+
|
|
365
|
+
renderBridgeSync({ accounts, hydrateCurrency });
|
|
366
|
+
|
|
367
|
+
// Wait for hydration to complete
|
|
368
|
+
await new Promise(resolve => setTimeout(resolve, 50));
|
|
369
|
+
|
|
370
|
+
// Should only hydrate each currency once, not once per account
|
|
371
|
+
expect(hydrateCurrency).toHaveBeenCalledTimes(2); // BTC and ETH
|
|
372
|
+
expect(hydrateCurrency).toHaveBeenCalledWith(bitcoin);
|
|
373
|
+
expect(hydrateCurrency).toHaveBeenCalledWith(ethereum);
|
|
374
|
+
});
|
|
375
|
+
|
|
376
|
+
test("handles different sync actions", () => {
|
|
377
|
+
const account = createAccount("btc1", bitcoin);
|
|
378
|
+
const accounts = [account];
|
|
379
|
+
|
|
380
|
+
let sync: Sync | undefined;
|
|
381
|
+
|
|
382
|
+
function TestComponent() {
|
|
383
|
+
sync = useBridgeSync();
|
|
384
|
+
return <div>Test</div>;
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
renderBridgeSync({ accounts }, <TestComponent />);
|
|
388
|
+
|
|
389
|
+
expect(sync).toBeDefined();
|
|
390
|
+
|
|
391
|
+
// Test that sync actions can be called without throwing
|
|
392
|
+
expect(sync).toBeDefined();
|
|
393
|
+
const syncFn = sync!; // Assert non-null since we just checked
|
|
394
|
+
|
|
395
|
+
expect(() =>
|
|
396
|
+
syncFn({ type: "SYNC_ALL_ACCOUNTS", priority: 1, reason: "manual" }),
|
|
397
|
+
).not.toThrow();
|
|
398
|
+
expect(() =>
|
|
399
|
+
syncFn({ type: "SYNC_ONE_ACCOUNT", accountId: account.id, priority: 1, reason: "manual" }),
|
|
400
|
+
).not.toThrow();
|
|
401
|
+
expect(() => syncFn({ type: "SET_SKIP_UNDER_PRIORITY", priority: 5 })).not.toThrow();
|
|
402
|
+
expect(() => syncFn({ type: "BACKGROUND_TICK", reason: "background" })).not.toThrow();
|
|
403
|
+
});
|
|
404
|
+
|
|
405
|
+
test("tracks session analytics when all accounts complete", async () => {
|
|
406
|
+
const account1 = createAccount("btc1", bitcoin, { operationsSize: 3 });
|
|
407
|
+
const account2 = createAccount("eth1", ethereum, { operationsSize: 5 });
|
|
408
|
+
const accounts = [account1, account2];
|
|
409
|
+
|
|
410
|
+
const trackAnalytics = jest.fn();
|
|
411
|
+
|
|
412
|
+
renderBridgeSync({ accounts, trackAnalytics });
|
|
413
|
+
|
|
414
|
+
// Wait for potential analytics calls
|
|
415
|
+
await new Promise(resolve => setTimeout(resolve, 100));
|
|
416
|
+
|
|
417
|
+
// The component should not throw when tracking analytics
|
|
418
|
+
expect(accounts).toHaveLength(2);
|
|
419
|
+
});
|
|
420
|
+
|
|
421
|
+
test("handles non-existent account sync gracefully", () => {
|
|
422
|
+
const account = createAccount("btc1", bitcoin);
|
|
423
|
+
const accounts = [account];
|
|
424
|
+
|
|
425
|
+
let sync: Sync | undefined;
|
|
426
|
+
|
|
427
|
+
function TestComponent() {
|
|
428
|
+
sync = useBridgeSync();
|
|
429
|
+
return <div>Test</div>;
|
|
430
|
+
}
|
|
431
|
+
|
|
432
|
+
renderBridgeSync({ accounts }, <TestComponent />);
|
|
433
|
+
|
|
434
|
+
// Try to sync an account that doesn't exist - should not throw
|
|
435
|
+
expect(sync).toBeDefined();
|
|
436
|
+
const syncFn = sync!;
|
|
437
|
+
|
|
438
|
+
expect(() => {
|
|
439
|
+
syncFn({
|
|
440
|
+
type: "SYNC_ONE_ACCOUNT",
|
|
441
|
+
accountId: "non-existent-account",
|
|
442
|
+
priority: 1,
|
|
443
|
+
reason: "manual",
|
|
444
|
+
});
|
|
445
|
+
}).not.toThrow();
|
|
446
|
+
});
|
|
447
|
+
|
|
448
|
+
test("does not send analytics for background sync reason", done => {
|
|
449
|
+
const account = createAccount("btc1", bitcoin);
|
|
450
|
+
const accounts = [account];
|
|
451
|
+
|
|
452
|
+
const trackAnalytics = jest.fn();
|
|
453
|
+
|
|
454
|
+
// Mock the account bridge to complete successfully
|
|
455
|
+
mockBridgeSync(account, observer => {
|
|
456
|
+
observer.next((acc: typeof account) => acc);
|
|
457
|
+
observer.complete();
|
|
458
|
+
});
|
|
459
|
+
|
|
460
|
+
function TestComponent() {
|
|
461
|
+
const sync = useBridgeSync();
|
|
462
|
+
|
|
463
|
+
useEffect(() => {
|
|
464
|
+
// Trigger a background sync
|
|
465
|
+
sync({
|
|
466
|
+
type: "SYNC_ONE_ACCOUNT",
|
|
467
|
+
accountId: account.id,
|
|
468
|
+
priority: 1,
|
|
469
|
+
reason: "background",
|
|
470
|
+
});
|
|
471
|
+
}, [sync]);
|
|
472
|
+
return <div>Test</div>;
|
|
473
|
+
}
|
|
474
|
+
|
|
475
|
+
renderBridgeSync({ accounts, trackAnalytics }, <TestComponent />);
|
|
476
|
+
|
|
477
|
+
// Wait for sync to complete and verify no analytics were sent
|
|
478
|
+
setTimeout(() => {
|
|
479
|
+
// Should not have called trackAnalytics with SyncSuccess for background syncs
|
|
480
|
+
const syncSuccessCalls = trackAnalytics.mock.calls.filter(call => call[0] === "SyncSuccess");
|
|
481
|
+
expect(syncSuccessCalls).toHaveLength(0);
|
|
482
|
+
|
|
483
|
+
// Verify trackAnalytics was not called at all with SyncSuccess
|
|
484
|
+
expect(trackAnalytics).not.toHaveBeenCalledWith("SyncSuccess", expect.anything());
|
|
485
|
+
|
|
486
|
+
done();
|
|
487
|
+
}, 200);
|
|
488
|
+
});
|
|
489
|
+
|
|
490
|
+
test("sends analytics for non-background sync reason", done => {
|
|
491
|
+
const account = createAccount("btc1", bitcoin);
|
|
492
|
+
const accounts = [account];
|
|
493
|
+
|
|
494
|
+
const trackAnalytics = jest.fn();
|
|
495
|
+
|
|
496
|
+
// Mock the account bridge to complete successfully
|
|
497
|
+
mockBridgeSync(account, observer => {
|
|
498
|
+
observer.next((acc: typeof account) => acc);
|
|
499
|
+
observer.complete();
|
|
117
500
|
});
|
|
501
|
+
|
|
502
|
+
function TestComponent() {
|
|
503
|
+
const sync = useBridgeSync();
|
|
504
|
+
|
|
505
|
+
useEffect(() => {
|
|
506
|
+
// Trigger a manual (non-background) sync
|
|
507
|
+
sync({
|
|
508
|
+
type: "SYNC_ONE_ACCOUNT",
|
|
509
|
+
accountId: account.id,
|
|
510
|
+
priority: 1,
|
|
511
|
+
reason: "manual",
|
|
512
|
+
});
|
|
513
|
+
}, [sync]);
|
|
514
|
+
return <div>Test</div>;
|
|
515
|
+
}
|
|
516
|
+
|
|
517
|
+
renderBridgeSync({ accounts, trackAnalytics }, <TestComponent />);
|
|
518
|
+
|
|
519
|
+
// Wait for sync to complete and verify analytics were sent
|
|
520
|
+
setTimeout(() => {
|
|
521
|
+
// Should have called trackAnalytics with SyncSuccess for manual syncs
|
|
522
|
+
expect(trackAnalytics).toHaveBeenCalledWith(
|
|
523
|
+
"SyncSuccess",
|
|
524
|
+
expect.objectContaining({
|
|
525
|
+
reason: "manual",
|
|
526
|
+
currencyName: account.currency.name,
|
|
527
|
+
}),
|
|
528
|
+
);
|
|
529
|
+
|
|
530
|
+
done();
|
|
531
|
+
}, 400);
|
|
532
|
+
});
|
|
533
|
+
|
|
534
|
+
test("provides sync state context", () => {
|
|
535
|
+
const account = createAccount("btc1", bitcoin);
|
|
536
|
+
const accounts = [account];
|
|
537
|
+
|
|
538
|
+
let syncState: BridgeSyncState | undefined;
|
|
539
|
+
|
|
540
|
+
function TestComponent() {
|
|
541
|
+
syncState = useBridgeSyncState();
|
|
542
|
+
return <div>Test</div>;
|
|
543
|
+
}
|
|
544
|
+
|
|
545
|
+
renderBridgeSync({ accounts }, <TestComponent />);
|
|
546
|
+
|
|
547
|
+
expect(syncState).toBeDefined();
|
|
548
|
+
expect(typeof syncState).toBe("object");
|
|
118
549
|
});
|
|
119
550
|
});
|