@ledgerhq/coin-hedera 1.10.1 → 1.11.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/.eslintrc.js +1 -0
- package/.turbo/turbo-build.log +1 -1
- package/CHANGELOG.md +37 -12
- package/lib/api/mirror.d.ts +3 -20
- package/lib/api/mirror.d.ts.map +1 -1
- package/lib/api/mirror.js +32 -90
- package/lib/api/mirror.js.map +1 -1
- package/lib/api/mirror.test.js +59 -4
- package/lib/api/mirror.test.js.map +1 -1
- package/lib/api/network.d.ts +3 -3
- package/lib/api/network.d.ts.map +1 -1
- package/lib/api/network.js +46 -3
- package/lib/api/network.js.map +1 -1
- package/lib/api/types.d.ts +44 -0
- package/lib/api/types.d.ts.map +1 -0
- package/lib/api/types.js +3 -0
- package/lib/api/types.js.map +1 -0
- package/lib/api/utils.d.ts +8 -0
- package/lib/api/utils.d.ts.map +1 -0
- package/lib/api/utils.js +132 -0
- package/lib/api/utils.js.map +1 -0
- package/lib/bridge/broadcast.d.ts.map +1 -1
- package/lib/bridge/broadcast.js +2 -0
- package/lib/bridge/broadcast.js.map +1 -1
- package/lib/bridge/buildOptimisticOperation.d.ts +2 -2
- package/lib/bridge/buildOptimisticOperation.d.ts.map +1 -1
- package/lib/bridge/buildOptimisticOperation.integration.test.d.ts +2 -0
- package/lib/bridge/buildOptimisticOperation.integration.test.d.ts.map +1 -0
- package/lib/bridge/buildOptimisticOperation.integration.test.js +82 -0
- package/lib/bridge/buildOptimisticOperation.integration.test.js.map +1 -0
- package/lib/bridge/buildOptimisticOperation.js +87 -5
- package/lib/bridge/buildOptimisticOperation.js.map +1 -1
- package/lib/bridge/estimateMaxSpendable.d.ts.map +1 -1
- package/lib/bridge/estimateMaxSpendable.js +8 -2
- package/lib/bridge/estimateMaxSpendable.js.map +1 -1
- package/lib/bridge/getTransactionStatus.d.ts +3 -3
- package/lib/bridge/getTransactionStatus.d.ts.map +1 -1
- package/lib/bridge/getTransactionStatus.js +116 -23
- package/lib/bridge/getTransactionStatus.js.map +1 -1
- package/lib/bridge/getTransactionStatus.test.d.ts +2 -0
- package/lib/bridge/getTransactionStatus.test.d.ts.map +1 -0
- package/lib/bridge/getTransactionStatus.test.js +176 -0
- package/lib/bridge/getTransactionStatus.test.js.map +1 -0
- package/lib/bridge/index.d.ts +4 -4
- package/lib/bridge/index.d.ts.map +1 -1
- package/lib/bridge/index.js +9 -6
- package/lib/bridge/index.js.map +1 -1
- package/lib/bridge/js-estimateMaxSpendable.integration.test.js +28 -44
- package/lib/bridge/js-estimateMaxSpendable.integration.test.js.map +1 -1
- package/lib/bridge/js-transaction.test.js +10 -49
- package/lib/bridge/js-transaction.test.js.map +1 -1
- package/lib/bridge/prepareTransaction.d.ts +0 -1
- package/lib/bridge/prepareTransaction.d.ts.map +1 -1
- package/lib/bridge/prepareTransaction.js +0 -1
- package/lib/bridge/prepareTransaction.js.map +1 -1
- package/lib/bridge/serialization.d.ts +7 -0
- package/lib/bridge/serialization.d.ts.map +1 -0
- package/lib/bridge/serialization.js +36 -0
- package/lib/bridge/serialization.js.map +1 -0
- package/lib/bridge/serialization.test.d.ts +2 -0
- package/lib/bridge/serialization.test.d.ts.map +1 -0
- package/lib/bridge/serialization.test.js +27 -0
- package/lib/bridge/serialization.test.js.map +1 -0
- package/lib/bridge/synchronisation.d.ts +3 -3
- package/lib/bridge/synchronisation.d.ts.map +1 -1
- package/lib/bridge/synchronisation.js +37 -15
- package/lib/bridge/synchronisation.js.map +1 -1
- package/lib/bridge/transaction.test.js +18 -59
- package/lib/bridge/transaction.test.js.map +1 -1
- package/lib/bridge/utils.d.ts +22 -8
- package/lib/bridge/utils.d.ts.map +1 -1
- package/lib/bridge/utils.integration.test.js +415 -73
- package/lib/bridge/utils.integration.test.js.map +1 -1
- package/lib/bridge/utils.js +300 -15
- package/lib/bridge/utils.js.map +1 -1
- package/lib/constants.d.ts +32 -0
- package/lib/constants.d.ts.map +1 -0
- package/lib/constants.js +37 -0
- package/lib/constants.js.map +1 -0
- package/lib/deviceTransactionConfig.d.ts.map +1 -1
- package/lib/deviceTransactionConfig.js +17 -15
- package/lib/deviceTransactionConfig.js.map +1 -1
- package/lib/logic.d.ts +9 -3
- package/lib/logic.d.ts.map +1 -1
- package/lib/logic.js +31 -3
- package/lib/logic.js.map +1 -1
- package/lib/logic.test.js +103 -50
- package/lib/logic.test.js.map +1 -1
- package/lib/test/fixtures/account.fixture.d.ts +19 -0
- package/lib/test/fixtures/account.fixture.d.ts.map +1 -0
- package/lib/test/fixtures/account.fixture.js +116 -0
- package/lib/test/fixtures/account.fixture.js.map +1 -0
- package/lib/test/fixtures/currency.fixture.d.ts +5 -0
- package/lib/test/fixtures/currency.fixture.d.ts.map +1 -0
- package/lib/test/fixtures/currency.fixture.js +67 -0
- package/lib/test/fixtures/currency.fixture.js.map +1 -0
- package/lib/test/fixtures/mirror.fixture.d.ts +3 -0
- package/lib/test/fixtures/mirror.fixture.d.ts.map +1 -0
- package/lib/test/fixtures/mirror.fixture.js +17 -0
- package/lib/test/fixtures/mirror.fixture.js.map +1 -0
- package/lib/test/fixtures/operation.fixture.d.ts +3 -0
- package/lib/test/fixtures/operation.fixture.d.ts.map +1 -0
- package/lib/test/fixtures/operation.fixture.js +26 -0
- package/lib/test/fixtures/operation.fixture.js.map +1 -0
- package/lib/test/fixtures/transaction.fixture.d.ts +4 -0
- package/lib/test/fixtures/transaction.fixture.d.ts.map +1 -0
- package/lib/test/fixtures/transaction.fixture.js +28 -0
- package/lib/test/fixtures/transaction.fixture.js.map +1 -0
- package/lib/types/bridge.d.ts +25 -1
- package/lib/types/bridge.d.ts.map +1 -1
- package/lib-es/api/mirror.d.ts +3 -20
- package/lib-es/api/mirror.d.ts.map +1 -1
- package/lib-es/api/mirror.js +29 -88
- package/lib-es/api/mirror.js.map +1 -1
- package/lib-es/api/mirror.test.js +60 -5
- package/lib-es/api/mirror.test.js.map +1 -1
- package/lib-es/api/network.d.ts +3 -3
- package/lib-es/api/network.d.ts.map +1 -1
- package/lib-es/api/network.js +44 -4
- package/lib-es/api/network.js.map +1 -1
- package/lib-es/api/types.d.ts +44 -0
- package/lib-es/api/types.d.ts.map +1 -0
- package/lib-es/api/types.js +2 -0
- package/lib-es/api/types.js.map +1 -0
- package/lib-es/api/utils.d.ts +8 -0
- package/lib-es/api/utils.d.ts.map +1 -0
- package/lib-es/api/utils.js +124 -0
- package/lib-es/api/utils.js.map +1 -0
- package/lib-es/bridge/broadcast.d.ts.map +1 -1
- package/lib-es/bridge/broadcast.js +2 -0
- package/lib-es/bridge/broadcast.js.map +1 -1
- package/lib-es/bridge/buildOptimisticOperation.d.ts +2 -2
- package/lib-es/bridge/buildOptimisticOperation.d.ts.map +1 -1
- package/lib-es/bridge/buildOptimisticOperation.integration.test.d.ts +2 -0
- package/lib-es/bridge/buildOptimisticOperation.integration.test.d.ts.map +1 -0
- package/lib-es/bridge/buildOptimisticOperation.integration.test.js +77 -0
- package/lib-es/bridge/buildOptimisticOperation.integration.test.js.map +1 -0
- package/lib-es/bridge/buildOptimisticOperation.js +84 -5
- package/lib-es/bridge/buildOptimisticOperation.js.map +1 -1
- package/lib-es/bridge/estimateMaxSpendable.d.ts.map +1 -1
- package/lib-es/bridge/estimateMaxSpendable.js +8 -2
- package/lib-es/bridge/estimateMaxSpendable.js.map +1 -1
- package/lib-es/bridge/getTransactionStatus.d.ts +3 -3
- package/lib-es/bridge/getTransactionStatus.d.ts.map +1 -1
- package/lib-es/bridge/getTransactionStatus.js +114 -24
- package/lib-es/bridge/getTransactionStatus.js.map +1 -1
- package/lib-es/bridge/getTransactionStatus.test.d.ts +2 -0
- package/lib-es/bridge/getTransactionStatus.test.d.ts.map +1 -0
- package/lib-es/bridge/getTransactionStatus.test.js +148 -0
- package/lib-es/bridge/getTransactionStatus.test.js.map +1 -0
- package/lib-es/bridge/index.d.ts +4 -4
- package/lib-es/bridge/index.d.ts.map +1 -1
- package/lib-es/bridge/index.js +9 -6
- package/lib-es/bridge/index.js.map +1 -1
- package/lib-es/bridge/js-estimateMaxSpendable.integration.test.js +28 -44
- package/lib-es/bridge/js-estimateMaxSpendable.integration.test.js.map +1 -1
- package/lib-es/bridge/js-transaction.test.js +10 -49
- package/lib-es/bridge/js-transaction.test.js.map +1 -1
- package/lib-es/bridge/prepareTransaction.d.ts +0 -1
- package/lib-es/bridge/prepareTransaction.d.ts.map +1 -1
- package/lib-es/bridge/prepareTransaction.js +0 -1
- package/lib-es/bridge/prepareTransaction.js.map +1 -1
- package/lib-es/bridge/serialization.d.ts +7 -0
- package/lib-es/bridge/serialization.d.ts.map +1 -0
- package/lib-es/bridge/serialization.js +29 -0
- package/lib-es/bridge/serialization.js.map +1 -0
- package/lib-es/bridge/serialization.test.d.ts +2 -0
- package/lib-es/bridge/serialization.test.d.ts.map +1 -0
- package/lib-es/bridge/serialization.test.js +25 -0
- package/lib-es/bridge/serialization.test.js.map +1 -0
- package/lib-es/bridge/synchronisation.d.ts +3 -3
- package/lib-es/bridge/synchronisation.d.ts.map +1 -1
- package/lib-es/bridge/synchronisation.js +39 -17
- package/lib-es/bridge/synchronisation.js.map +1 -1
- package/lib-es/bridge/transaction.test.js +18 -59
- package/lib-es/bridge/transaction.test.js.map +1 -1
- package/lib-es/bridge/utils.d.ts +22 -8
- package/lib-es/bridge/utils.d.ts.map +1 -1
- package/lib-es/bridge/utils.integration.test.js +416 -74
- package/lib-es/bridge/utils.integration.test.js.map +1 -1
- package/lib-es/bridge/utils.js +295 -15
- package/lib-es/bridge/utils.js.map +1 -1
- package/lib-es/constants.d.ts +32 -0
- package/lib-es/constants.d.ts.map +1 -0
- package/lib-es/constants.js +34 -0
- package/lib-es/constants.js.map +1 -0
- package/lib-es/deviceTransactionConfig.d.ts.map +1 -1
- package/lib-es/deviceTransactionConfig.js +17 -15
- package/lib-es/deviceTransactionConfig.js.map +1 -1
- package/lib-es/logic.d.ts +9 -3
- package/lib-es/logic.d.ts.map +1 -1
- package/lib-es/logic.js +26 -3
- package/lib-es/logic.js.map +1 -1
- package/lib-es/logic.test.js +104 -51
- package/lib-es/logic.test.js.map +1 -1
- package/lib-es/test/fixtures/account.fixture.d.ts +19 -0
- package/lib-es/test/fixtures/account.fixture.d.ts.map +1 -0
- package/lib-es/test/fixtures/account.fixture.js +107 -0
- package/lib-es/test/fixtures/account.fixture.js.map +1 -0
- package/lib-es/test/fixtures/currency.fixture.d.ts +5 -0
- package/lib-es/test/fixtures/currency.fixture.d.ts.map +1 -0
- package/lib-es/test/fixtures/currency.fixture.js +58 -0
- package/lib-es/test/fixtures/currency.fixture.js.map +1 -0
- package/lib-es/test/fixtures/mirror.fixture.d.ts +3 -0
- package/lib-es/test/fixtures/mirror.fixture.d.ts.map +1 -0
- package/lib-es/test/fixtures/mirror.fixture.js +13 -0
- package/lib-es/test/fixtures/mirror.fixture.js.map +1 -0
- package/lib-es/test/fixtures/operation.fixture.d.ts +3 -0
- package/lib-es/test/fixtures/operation.fixture.d.ts.map +1 -0
- package/lib-es/test/fixtures/operation.fixture.js +19 -0
- package/lib-es/test/fixtures/operation.fixture.js.map +1 -0
- package/lib-es/test/fixtures/transaction.fixture.d.ts +4 -0
- package/lib-es/test/fixtures/transaction.fixture.d.ts.map +1 -0
- package/lib-es/test/fixtures/transaction.fixture.js +20 -0
- package/lib-es/test/fixtures/transaction.fixture.js.map +1 -0
- package/lib-es/types/bridge.d.ts +25 -1
- package/lib-es/types/bridge.d.ts.map +1 -1
- package/package.json +12 -10
- package/src/api/mirror.test.ts +79 -5
- package/src/api/mirror.ts +30 -111
- package/src/api/network.ts +71 -4
- package/src/api/types.ts +48 -0
- package/src/api/utils.ts +150 -0
- package/src/bridge/broadcast.ts +2 -0
- package/src/bridge/buildOptimisticOperation.integration.test.ts +88 -0
- package/src/bridge/buildOptimisticOperation.ts +118 -7
- package/src/bridge/estimateMaxSpendable.ts +8 -2
- package/src/bridge/getTransactionStatus.test.ts +200 -0
- package/src/bridge/getTransactionStatus.ts +166 -32
- package/src/bridge/index.ts +13 -10
- package/src/bridge/js-estimateMaxSpendable.integration.test.ts +37 -46
- package/src/bridge/js-transaction.test.ts +13 -54
- package/src/bridge/prepareTransaction.ts +1 -2
- package/src/bridge/serialization.test.ts +39 -0
- package/src/bridge/serialization.ts +43 -0
- package/src/bridge/synchronisation.ts +65 -27
- package/src/bridge/transaction.test.ts +22 -64
- package/src/bridge/utils.integration.test.ts +525 -76
- package/src/bridge/utils.ts +423 -24
- package/src/constants.ts +35 -0
- package/src/deviceTransactionConfig.ts +16 -15
- package/src/logic.test.ts +147 -57
- package/src/logic.ts +58 -7
- package/src/test/fixtures/account.fixture.ts +123 -0
- package/src/test/fixtures/currency.fixture.ts +66 -0
- package/src/test/fixtures/mirror.fixture.ts +14 -0
- package/src/test/fixtures/operation.fixture.ts +20 -0
- package/src/test/fixtures/transaction.fixture.ts +22 -0
- package/src/types/bridge.ts +33 -0
package/src/logic.test.ts
CHANGED
|
@@ -1,62 +1,152 @@
|
|
|
1
|
-
import { BigNumber } from "bignumber.js";
|
|
2
|
-
import { Operation } from "@ledgerhq/types-live";
|
|
3
1
|
import { getCryptoCurrencyById } from "@ledgerhq/cryptoassets";
|
|
4
|
-
import {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
2
|
+
import {
|
|
3
|
+
getTransactionExplorer,
|
|
4
|
+
isAutoTokenAssociationEnabled,
|
|
5
|
+
isTokenAssociateTransaction,
|
|
6
|
+
isTokenAssociationRequired,
|
|
7
|
+
isValidExtra,
|
|
8
|
+
sendRecipientCanNext,
|
|
9
|
+
} from "./logic";
|
|
10
|
+
import { getMockedAccount, getMockedTokenAccount } from "./test/fixtures/account.fixture";
|
|
11
|
+
import { getMockedOperation } from "./test/fixtures/operation.fixture";
|
|
12
|
+
import { getMockedTokenCurrency } from "./test/fixtures/currency.fixture";
|
|
13
|
+
import { HEDERA_TRANSACTION_KINDS } from "./constants";
|
|
14
|
+
|
|
15
|
+
describe("logic", () => {
|
|
16
|
+
describe("getTransactionExplorer", () => {
|
|
17
|
+
test("Tx explorer URL is converted from hash to consensus timestamp", async () => {
|
|
18
|
+
const explorerView = getCryptoCurrencyById("hedera").explorerViews[0];
|
|
19
|
+
expect(explorerView).toEqual({
|
|
20
|
+
tx: expect.any(String),
|
|
21
|
+
address: expect.any(String),
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
const mockedOperation = getMockedOperation({
|
|
25
|
+
extra: { consensusTimestamp: "1.2.3.4" },
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
const newUrl = getTransactionExplorer(explorerView, mockedOperation);
|
|
29
|
+
expect(newUrl).toBe("https://hashscan.io/mainnet/transaction/1.2.3.4");
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
test("Tx explorer URL is based on transaction id if consensus timestamp is not available", async () => {
|
|
33
|
+
const explorerView = getCryptoCurrencyById("hedera").explorerViews[0];
|
|
34
|
+
expect(explorerView).toEqual({
|
|
35
|
+
tx: expect.any(String),
|
|
36
|
+
address: expect.any(String),
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
const mockedOperation = getMockedOperation({
|
|
40
|
+
extra: { transactionId: "0.0.1234567-123-123" },
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
const newUrl = getTransactionExplorer(explorerView, mockedOperation);
|
|
44
|
+
expect(newUrl).toBe("https://hashscan.io/mainnet/transaction/0.0.1234567-123-123");
|
|
45
|
+
});
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
describe("isTokenAssociateTransaction", () => {
|
|
49
|
+
test("returns correct value based on tx.properties", () => {
|
|
50
|
+
expect(
|
|
51
|
+
isTokenAssociateTransaction({
|
|
52
|
+
properties: { name: HEDERA_TRANSACTION_KINDS.TokenAssociate.name },
|
|
53
|
+
} as any),
|
|
54
|
+
).toBe(true);
|
|
55
|
+
|
|
56
|
+
expect(
|
|
57
|
+
isTokenAssociateTransaction({
|
|
58
|
+
properties: { name: "transfer" },
|
|
59
|
+
} as any),
|
|
60
|
+
).toBe(false);
|
|
61
|
+
|
|
62
|
+
expect(isTokenAssociateTransaction({} as any)).toBe(false);
|
|
63
|
+
});
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
describe("isAutoTokenAssociationEnabled", () => {
|
|
67
|
+
test("returns value based on isAutoTokenAssociationEnabled flag", () => {
|
|
68
|
+
expect(
|
|
69
|
+
isAutoTokenAssociationEnabled({
|
|
70
|
+
hederaResources: { isAutoTokenAssociationEnabled: true },
|
|
71
|
+
} as any),
|
|
72
|
+
).toBe(true);
|
|
73
|
+
|
|
74
|
+
expect(
|
|
75
|
+
isAutoTokenAssociationEnabled({
|
|
76
|
+
hederaResources: { isAutoTokenAssociationEnabled: false },
|
|
77
|
+
} as any),
|
|
78
|
+
).toBe(false);
|
|
79
|
+
|
|
80
|
+
expect(isAutoTokenAssociationEnabled({} as any)).toBe(false);
|
|
81
|
+
});
|
|
33
82
|
});
|
|
34
83
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
84
|
+
describe("isTokenAssociationRequired", () => {
|
|
85
|
+
test("should return false if token is already associated (token account exists)", () => {
|
|
86
|
+
const mockedTokenCurrency = getMockedTokenCurrency();
|
|
87
|
+
const mockedTokenAccount = getMockedTokenAccount(mockedTokenCurrency);
|
|
88
|
+
const mockedAccount = getMockedAccount({ subAccounts: [mockedTokenAccount] });
|
|
89
|
+
|
|
90
|
+
expect(isTokenAssociationRequired(mockedAccount, mockedTokenCurrency)).toBe(false);
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
test("should return false if auto token associations are enabled", () => {
|
|
94
|
+
const mockedTokenCurrency = getMockedTokenCurrency();
|
|
95
|
+
const mockedAccount = getMockedAccount({
|
|
96
|
+
subAccounts: [],
|
|
97
|
+
hederaResources: {
|
|
98
|
+
maxAutomaticTokenAssociations: -1,
|
|
99
|
+
isAutoTokenAssociationEnabled: true,
|
|
100
|
+
},
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
expect(isTokenAssociationRequired(mockedAccount, mockedTokenCurrency)).toBe(false);
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
test("should return true if token is not associated and auto associations are disabled", () => {
|
|
107
|
+
const mockedTokenCurrency = getMockedTokenCurrency();
|
|
108
|
+
const mockedAccount = getMockedAccount({ subAccounts: [] });
|
|
109
|
+
|
|
110
|
+
expect(isTokenAssociationRequired(mockedAccount, mockedTokenCurrency)).toBe(true);
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
test("should return false if token is undefined", () => {
|
|
114
|
+
const mockedAccount = getMockedAccount({ subAccounts: [] });
|
|
115
|
+
|
|
116
|
+
expect(isTokenAssociationRequired(mockedAccount, undefined)).toBe(false);
|
|
117
|
+
});
|
|
118
|
+
|
|
119
|
+
test("should return false for legacy accounts without subAccounts or hederaResources", () => {
|
|
120
|
+
const mockedTokenCurrency = getMockedTokenCurrency();
|
|
121
|
+
const mockedAccount = getMockedAccount();
|
|
122
|
+
|
|
123
|
+
delete mockedAccount.subAccounts;
|
|
124
|
+
delete mockedAccount.hederaResources;
|
|
125
|
+
|
|
126
|
+
expect(isTokenAssociationRequired(mockedAccount, mockedTokenCurrency)).toBe(true);
|
|
127
|
+
});
|
|
128
|
+
});
|
|
129
|
+
|
|
130
|
+
describe("isValidExtra", () => {
|
|
131
|
+
test("returns true for object and false for invalid types", () => {
|
|
132
|
+
expect(isValidExtra({ some: "value" })).toBe(true);
|
|
133
|
+
expect(isValidExtra(null)).toBe(false);
|
|
134
|
+
expect(isValidExtra(undefined)).toBe(false);
|
|
135
|
+
expect(isValidExtra("string")).toBe(false);
|
|
136
|
+
expect(isValidExtra(123)).toBe(false);
|
|
137
|
+
expect(isValidExtra([])).toBe(false);
|
|
138
|
+
});
|
|
139
|
+
});
|
|
140
|
+
|
|
141
|
+
describe("sendRecipientCanNext", () => {
|
|
142
|
+
test("handles association warnings", () => {
|
|
143
|
+
expect(sendRecipientCanNext({ warnings: {} } as any)).toBe(true);
|
|
144
|
+
expect(sendRecipientCanNext({ warnings: { missingAssociation: new Error() } } as any)).toBe(
|
|
145
|
+
false,
|
|
146
|
+
);
|
|
147
|
+
expect(
|
|
148
|
+
sendRecipientCanNext({ warnings: { unverifiedAssociation: new Error() } } as any),
|
|
149
|
+
).toBe(false);
|
|
150
|
+
});
|
|
61
151
|
});
|
|
62
152
|
});
|
package/src/logic.ts
CHANGED
|
@@ -1,15 +1,66 @@
|
|
|
1
|
-
import { ExplorerView } from "@ledgerhq/types-cryptoassets";
|
|
2
|
-
import { Operation } from "@ledgerhq/types-live";
|
|
3
|
-
|
|
4
|
-
import {
|
|
1
|
+
import type { ExplorerView, TokenCurrency } from "@ledgerhq/types-cryptoassets";
|
|
2
|
+
import type { AccountLike, Operation } from "@ledgerhq/types-live";
|
|
3
|
+
import { HEDERA_TRANSACTION_KINDS } from "./constants";
|
|
4
|
+
import type {
|
|
5
|
+
HederaAccount,
|
|
6
|
+
HederaOperationExtra,
|
|
7
|
+
TokenAssociateProperties,
|
|
8
|
+
Transaction,
|
|
9
|
+
TransactionStatus,
|
|
10
|
+
} from "./types";
|
|
5
11
|
|
|
6
12
|
const getTransactionExplorer = (
|
|
7
13
|
explorerView: ExplorerView | null | undefined,
|
|
8
14
|
operation: Operation,
|
|
9
15
|
): string | undefined => {
|
|
10
|
-
const extra = operation.extra
|
|
16
|
+
const extra = isValidExtra(operation.extra) ? operation.extra : null;
|
|
17
|
+
|
|
18
|
+
return explorerView?.tx?.replace(
|
|
19
|
+
"$hash",
|
|
20
|
+
extra?.consensusTimestamp ?? extra?.transactionId ?? "0",
|
|
21
|
+
);
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
const isTokenAssociateTransaction = (
|
|
25
|
+
tx: Transaction,
|
|
26
|
+
): tx is Extract<Required<Transaction>, { properties: TokenAssociateProperties }> => {
|
|
27
|
+
return tx.properties?.name === HEDERA_TRANSACTION_KINDS.TokenAssociate.name;
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
const isAutoTokenAssociationEnabled = (account: AccountLike) => {
|
|
31
|
+
const hederaAccount = "hederaResources" in account ? (account as HederaAccount) : null;
|
|
11
32
|
|
|
12
|
-
return
|
|
33
|
+
return hederaAccount?.hederaResources?.isAutoTokenAssociationEnabled ?? false;
|
|
13
34
|
};
|
|
14
35
|
|
|
15
|
-
|
|
36
|
+
const isTokenAssociationRequired = (
|
|
37
|
+
account: AccountLike,
|
|
38
|
+
token: TokenCurrency | null | undefined,
|
|
39
|
+
) => {
|
|
40
|
+
const subAccounts = !!account && "subAccounts" in account ? account.subAccounts ?? [] : [];
|
|
41
|
+
const isTokenAssociated = subAccounts.some(item => item.token.id === token?.id);
|
|
42
|
+
|
|
43
|
+
return !!token && !isTokenAssociated && !isAutoTokenAssociationEnabled(account);
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
const isValidExtra = (extra: unknown): extra is HederaOperationExtra => {
|
|
47
|
+
return !!extra && typeof extra === "object" && !Array.isArray(extra);
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
// disables the "Continue" button in the Send modal's Recipient step during token transfers if:
|
|
51
|
+
// - the recipient is not associated with the token
|
|
52
|
+
// - the association status can't be verified
|
|
53
|
+
const sendRecipientCanNext = (status: TransactionStatus) => {
|
|
54
|
+
const { missingAssociation, unverifiedAssociation } = status.warnings;
|
|
55
|
+
|
|
56
|
+
return !missingAssociation && !unverifiedAssociation;
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
export {
|
|
60
|
+
sendRecipientCanNext,
|
|
61
|
+
getTransactionExplorer,
|
|
62
|
+
isValidExtra,
|
|
63
|
+
isTokenAssociateTransaction,
|
|
64
|
+
isTokenAssociationRequired,
|
|
65
|
+
isAutoTokenAssociationEnabled,
|
|
66
|
+
};
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
import BigNumber from "bignumber.js";
|
|
2
|
+
import type {
|
|
3
|
+
HederaAccount,
|
|
4
|
+
HederaAccountRaw,
|
|
5
|
+
HederaResources,
|
|
6
|
+
HederaResourcesRaw,
|
|
7
|
+
} from "../../types";
|
|
8
|
+
import type { TokenAccount } from "@ledgerhq/types-live";
|
|
9
|
+
import { getMockedCurrency, getMockedTokenCurrency } from "./currency.fixture";
|
|
10
|
+
import { TokenCurrency } from "@ledgerhq/types-cryptoassets";
|
|
11
|
+
|
|
12
|
+
const defaultMockedCurrency = getMockedCurrency();
|
|
13
|
+
const defaultMockedTokenCurrency = getMockedTokenCurrency();
|
|
14
|
+
const defaultMockAccountId = "js:2:hedera:0.0.1234567:hederaBip44";
|
|
15
|
+
const defaultMockTokenAccountId = `${defaultMockAccountId}+${defaultMockedTokenCurrency.id}`;
|
|
16
|
+
const defaultBalance = new BigNumber(100000000);
|
|
17
|
+
const defaultTokenBalance = new BigNumber(10);
|
|
18
|
+
|
|
19
|
+
export const mockHederaResources: HederaResources = {
|
|
20
|
+
maxAutomaticTokenAssociations: 0,
|
|
21
|
+
isAutoTokenAssociationEnabled: false,
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
export const mockHederaResourcesRaw: HederaResourcesRaw = {
|
|
25
|
+
maxAutomaticTokenAssociations: 0,
|
|
26
|
+
isAutoTokenAssociationEnabled: false,
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* default settings:
|
|
31
|
+
* - account balance is 1 HBAR
|
|
32
|
+
* - auto token association is disabled
|
|
33
|
+
* - subAccounts array is empty (no tokens account are used)
|
|
34
|
+
*/
|
|
35
|
+
export const getMockedAccount = (overrides?: Partial<HederaAccount>): HederaAccount => {
|
|
36
|
+
return {
|
|
37
|
+
type: "Account",
|
|
38
|
+
id: defaultMockAccountId,
|
|
39
|
+
seedIdentifier: "",
|
|
40
|
+
derivationMode: "",
|
|
41
|
+
index: 0,
|
|
42
|
+
freshAddress: "0.0.12345",
|
|
43
|
+
freshAddressPath: "44/3030",
|
|
44
|
+
used: false,
|
|
45
|
+
balance: defaultBalance,
|
|
46
|
+
spendableBalance: defaultBalance,
|
|
47
|
+
creationDate: new Date(),
|
|
48
|
+
blockHeight: 0,
|
|
49
|
+
currency: defaultMockedCurrency,
|
|
50
|
+
operationsCount: 0,
|
|
51
|
+
operations: [],
|
|
52
|
+
pendingOperations: [],
|
|
53
|
+
lastSyncDate: new Date(),
|
|
54
|
+
balanceHistoryCache: {
|
|
55
|
+
HOUR: { latestDate: null, balances: [] },
|
|
56
|
+
DAY: { latestDate: null, balances: [] },
|
|
57
|
+
WEEK: { latestDate: null, balances: [] },
|
|
58
|
+
},
|
|
59
|
+
swapHistory: [],
|
|
60
|
+
subAccounts: [],
|
|
61
|
+
hederaResources: mockHederaResources,
|
|
62
|
+
...overrides,
|
|
63
|
+
};
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
export const getMockedAccountRaw = (overrides?: Partial<HederaAccountRaw>): HederaAccountRaw => {
|
|
67
|
+
return {
|
|
68
|
+
id: defaultMockAccountId,
|
|
69
|
+
seedIdentifier: "",
|
|
70
|
+
derivationMode: "",
|
|
71
|
+
index: 0,
|
|
72
|
+
freshAddress: "0.0.12345",
|
|
73
|
+
freshAddressPath: "44/3030",
|
|
74
|
+
used: false,
|
|
75
|
+
balance: defaultBalance.toString(),
|
|
76
|
+
spendableBalance: defaultBalance.toString(),
|
|
77
|
+
creationDate: new Date().toISOString(),
|
|
78
|
+
blockHeight: 0,
|
|
79
|
+
currencyId: defaultMockedCurrency.id,
|
|
80
|
+
operationsCount: 0,
|
|
81
|
+
operations: [],
|
|
82
|
+
pendingOperations: [],
|
|
83
|
+
lastSyncDate: new Date().toISOString(),
|
|
84
|
+
balanceHistoryCache: {
|
|
85
|
+
HOUR: { latestDate: null, balances: [] },
|
|
86
|
+
DAY: { latestDate: null, balances: [] },
|
|
87
|
+
WEEK: { latestDate: null, balances: [] },
|
|
88
|
+
},
|
|
89
|
+
swapHistory: [],
|
|
90
|
+
subAccounts: [],
|
|
91
|
+
hederaResources: mockHederaResourcesRaw,
|
|
92
|
+
...overrides,
|
|
93
|
+
};
|
|
94
|
+
};
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* default settings:
|
|
98
|
+
* - balance is 10
|
|
99
|
+
*/
|
|
100
|
+
export const getMockedTokenAccount = (
|
|
101
|
+
token: TokenCurrency,
|
|
102
|
+
overrides?: Partial<TokenAccount>,
|
|
103
|
+
): TokenAccount => {
|
|
104
|
+
return {
|
|
105
|
+
type: "TokenAccount",
|
|
106
|
+
id: defaultMockTokenAccountId,
|
|
107
|
+
parentId: defaultMockAccountId,
|
|
108
|
+
token,
|
|
109
|
+
balance: defaultTokenBalance,
|
|
110
|
+
spendableBalance: defaultTokenBalance,
|
|
111
|
+
creationDate: new Date(),
|
|
112
|
+
operations: [],
|
|
113
|
+
operationsCount: 0,
|
|
114
|
+
pendingOperations: [],
|
|
115
|
+
swapHistory: [],
|
|
116
|
+
balanceHistoryCache: {
|
|
117
|
+
HOUR: { latestDate: null, balances: [] },
|
|
118
|
+
DAY: { latestDate: null, balances: [] },
|
|
119
|
+
WEEK: { latestDate: null, balances: [] },
|
|
120
|
+
},
|
|
121
|
+
...overrides,
|
|
122
|
+
};
|
|
123
|
+
};
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { getCryptoCurrencyById, listTokensForCryptoCurrency } from "@ledgerhq/cryptoassets";
|
|
2
|
+
import type { CryptoCurrency, TokenCurrency } from "@ledgerhq/types-cryptoassets";
|
|
3
|
+
import invariant from "invariant";
|
|
4
|
+
|
|
5
|
+
export const getMockedCurrency = (overrides?: Partial<CryptoCurrency>): CryptoCurrency => {
|
|
6
|
+
return {
|
|
7
|
+
type: "CryptoCurrency",
|
|
8
|
+
id: "hedera",
|
|
9
|
+
managerAppName: "Hedera",
|
|
10
|
+
coinType: 3030,
|
|
11
|
+
scheme: "hedera",
|
|
12
|
+
color: "#000",
|
|
13
|
+
family: "hedera",
|
|
14
|
+
explorerViews: [
|
|
15
|
+
{
|
|
16
|
+
tx: "https://hashscan.io/mainnet/transaction/$hash",
|
|
17
|
+
address: "https://hashscan.io/mainnet/account/$address",
|
|
18
|
+
},
|
|
19
|
+
],
|
|
20
|
+
name: "Hedera",
|
|
21
|
+
ticker: "HBAR",
|
|
22
|
+
units: [
|
|
23
|
+
{
|
|
24
|
+
name: "HBAR",
|
|
25
|
+
code: "HBAR",
|
|
26
|
+
magnitude: 8,
|
|
27
|
+
},
|
|
28
|
+
],
|
|
29
|
+
...overrides,
|
|
30
|
+
};
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
export const getTokenCurrencyFromCAL = (
|
|
34
|
+
index: number,
|
|
35
|
+
overrides?: Partial<TokenCurrency>,
|
|
36
|
+
): TokenCurrency => {
|
|
37
|
+
const hedera = getCryptoCurrencyById("hedera");
|
|
38
|
+
const token = listTokensForCryptoCurrency(hedera)[index];
|
|
39
|
+
|
|
40
|
+
invariant(token, `token not found in CAL list on ${index} position`);
|
|
41
|
+
|
|
42
|
+
return {
|
|
43
|
+
...token,
|
|
44
|
+
...overrides,
|
|
45
|
+
};
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
export const getMockedTokenCurrency = (overrides?: Partial<TokenCurrency>): TokenCurrency => {
|
|
49
|
+
return {
|
|
50
|
+
id: "hedera/hts/test_0.0.1234567",
|
|
51
|
+
contractAddress: "0.0.1001",
|
|
52
|
+
parentCurrency: getMockedCurrency(),
|
|
53
|
+
tokenType: "hts",
|
|
54
|
+
name: "Test token",
|
|
55
|
+
ticker: "TEST",
|
|
56
|
+
type: "TokenCurrency",
|
|
57
|
+
units: [
|
|
58
|
+
{
|
|
59
|
+
name: "Test",
|
|
60
|
+
code: "TEST",
|
|
61
|
+
magnitude: 8,
|
|
62
|
+
},
|
|
63
|
+
],
|
|
64
|
+
...overrides,
|
|
65
|
+
};
|
|
66
|
+
};
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { HederaMirrorToken } from "../../api/types";
|
|
2
|
+
|
|
3
|
+
export const getMockedMirrorToken = (overrides?: Partial<HederaMirrorToken>): HederaMirrorToken => {
|
|
4
|
+
return {
|
|
5
|
+
token_id: "",
|
|
6
|
+
created_timestamp: "123",
|
|
7
|
+
automatic_association: false,
|
|
8
|
+
balance: 0,
|
|
9
|
+
decimals: 0,
|
|
10
|
+
freeze_status: "NOT_APPLICABLE",
|
|
11
|
+
kyc_status: "NOT_APPLICABLE",
|
|
12
|
+
...overrides,
|
|
13
|
+
};
|
|
14
|
+
};
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import BigNumber from "bignumber.js";
|
|
2
|
+
import type { HederaOperation } from "../../types";
|
|
3
|
+
|
|
4
|
+
export const getMockedOperation = (overrides?: Partial<HederaOperation>): HederaOperation => {
|
|
5
|
+
return {
|
|
6
|
+
id: "",
|
|
7
|
+
hash: "",
|
|
8
|
+
type: "IN",
|
|
9
|
+
value: new BigNumber(0),
|
|
10
|
+
fee: new BigNumber(0),
|
|
11
|
+
senders: [],
|
|
12
|
+
recipients: [],
|
|
13
|
+
blockHeight: undefined,
|
|
14
|
+
blockHash: undefined,
|
|
15
|
+
accountId: "",
|
|
16
|
+
date: new Date(),
|
|
17
|
+
extra: {},
|
|
18
|
+
...overrides,
|
|
19
|
+
};
|
|
20
|
+
};
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import BigNumber from "bignumber.js";
|
|
2
|
+
import type { Transaction, TransactionRaw } from "../../types";
|
|
3
|
+
|
|
4
|
+
export const getMockedTransaction = (overrides?: Partial<Transaction>): Transaction => {
|
|
5
|
+
return {
|
|
6
|
+
family: "hedera",
|
|
7
|
+
amount: new BigNumber(0),
|
|
8
|
+
recipient: "",
|
|
9
|
+
useAllAmount: false,
|
|
10
|
+
...overrides,
|
|
11
|
+
};
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
export const getMockedTransactionRaw = (overrides?: Partial<TransactionRaw>): TransactionRaw => {
|
|
15
|
+
return {
|
|
16
|
+
family: "hedera",
|
|
17
|
+
amount: "0",
|
|
18
|
+
recipient: "",
|
|
19
|
+
useAllAmount: false,
|
|
20
|
+
...overrides,
|
|
21
|
+
};
|
|
22
|
+
};
|
package/src/types/bridge.ts
CHANGED
|
@@ -1,9 +1,14 @@
|
|
|
1
|
+
import { TokenCurrency } from "@ledgerhq/types-cryptoassets";
|
|
1
2
|
import type {
|
|
3
|
+
Account,
|
|
4
|
+
AccountRaw,
|
|
5
|
+
Operation,
|
|
2
6
|
TransactionCommon,
|
|
3
7
|
TransactionCommonRaw,
|
|
4
8
|
TransactionStatusCommon,
|
|
5
9
|
TransactionStatusCommonRaw,
|
|
6
10
|
} from "@ledgerhq/types-live";
|
|
11
|
+
import { HEDERA_TRANSACTION_KINDS } from "../constants";
|
|
7
12
|
|
|
8
13
|
export type NetworkInfo = {
|
|
9
14
|
family: "hedera";
|
|
@@ -13,21 +18,49 @@ export type NetworkInfoRaw = {
|
|
|
13
18
|
family: "hedera";
|
|
14
19
|
};
|
|
15
20
|
|
|
21
|
+
export type TokenAssociateProperties = {
|
|
22
|
+
name: typeof HEDERA_TRANSACTION_KINDS.TokenAssociate.name;
|
|
23
|
+
token: TokenCurrency;
|
|
24
|
+
};
|
|
25
|
+
|
|
16
26
|
export type Transaction = TransactionCommon & {
|
|
17
27
|
family: "hedera";
|
|
18
28
|
memo?: string | undefined;
|
|
29
|
+
properties?: TokenAssociateProperties;
|
|
19
30
|
};
|
|
20
31
|
|
|
21
32
|
export type TransactionRaw = TransactionCommonRaw & {
|
|
22
33
|
family: "hedera";
|
|
23
34
|
memo?: string | undefined;
|
|
35
|
+
properties?: TokenAssociateProperties;
|
|
24
36
|
};
|
|
25
37
|
|
|
26
38
|
export type TransactionStatus = TransactionStatusCommon;
|
|
27
39
|
|
|
28
40
|
export type TransactionStatusRaw = TransactionStatusCommonRaw;
|
|
29
41
|
|
|
42
|
+
export interface HederaResources {
|
|
43
|
+
maxAutomaticTokenAssociations: number;
|
|
44
|
+
isAutoTokenAssociationEnabled: boolean;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export interface HederaResourcesRaw {
|
|
48
|
+
maxAutomaticTokenAssociations: number;
|
|
49
|
+
isAutoTokenAssociationEnabled: boolean;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export type HederaAccount = Account & {
|
|
53
|
+
hederaResources?: HederaResources;
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
export type HederaAccountRaw = AccountRaw & {
|
|
57
|
+
hederaResources?: HederaResourcesRaw;
|
|
58
|
+
};
|
|
59
|
+
|
|
30
60
|
export type HederaOperationExtra = {
|
|
31
61
|
consensusTimestamp?: string;
|
|
32
62
|
transactionId?: string;
|
|
63
|
+
associatedTokenId?: string;
|
|
33
64
|
};
|
|
65
|
+
|
|
66
|
+
export type HederaOperation = Operation<HederaOperationExtra>;
|