@ledgerhq/live-common 25.0.0-next.2 → 25.0.0-next.5
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/__tests__/accounts/importAccounts.js +1 -1
- package/lib/__tests__/test-helpers/setup.js +1 -1
- package/lib/account/helpers.d.ts +5 -1
- package/lib/account/helpers.d.ts.map +1 -1
- package/lib/account/helpers.js +28 -1
- package/lib/account/helpers.js.map +1 -1
- package/lib/apps/filtering.test.js +1 -1
- package/lib/apps/support.d.ts.map +1 -1
- package/lib/apps/support.js +2 -1
- package/lib/apps/support.js.map +1 -1
- package/lib/currencies/helpers.d.ts +9 -0
- package/lib/currencies/helpers.d.ts.map +1 -0
- package/lib/currencies/helpers.js +78 -0
- package/lib/currencies/helpers.js.map +1 -0
- package/lib/currencies/helpers.test.d.ts +2 -0
- package/lib/currencies/helpers.test.d.ts.map +1 -0
- package/lib/currencies/helpers.test.js +20 -0
- package/lib/currencies/helpers.test.js.map +1 -0
- package/lib/currencies/index.d.ts +1 -0
- package/lib/currencies/index.d.ts.map +1 -1
- package/lib/currencies/index.js +1 -0
- package/lib/currencies/index.js.map +1 -1
- package/lib/currencies/react.d.ts +4 -0
- package/lib/currencies/react.d.ts.map +1 -0
- package/lib/currencies/react.js +16 -0
- package/lib/currencies/react.js.map +1 -0
- package/lib/families/cardano/bridge.integration.test.d.ts.map +1 -1
- package/lib/families/cardano/bridge.integration.test.js +36 -2
- package/lib/families/cardano/bridge.integration.test.js.map +1 -1
- package/lib/families/cardano/buildSubAccounts.d.ts.map +1 -1
- package/lib/families/cardano/buildSubAccounts.js +5 -3
- package/lib/families/cardano/buildSubAccounts.js.map +1 -1
- package/lib/families/cardano/deviceTransactionConfig.d.ts +11 -0
- package/lib/families/cardano/deviceTransactionConfig.d.ts.map +1 -0
- package/lib/families/cardano/deviceTransactionConfig.js +91 -0
- package/lib/families/cardano/deviceTransactionConfig.js.map +1 -0
- package/lib/families/cardano/errors.d.ts +4 -0
- package/lib/families/cardano/errors.d.ts.map +1 -1
- package/lib/families/cardano/errors.js +5 -1
- package/lib/families/cardano/errors.js.map +1 -1
- package/lib/families/cardano/js-estimateMaxSpendable.d.ts.map +1 -1
- package/lib/families/cardano/js-estimateMaxSpendable.js +3 -2
- package/lib/families/cardano/js-estimateMaxSpendable.js.map +1 -1
- package/lib/families/cardano/js-getTransactionStatus.d.ts.map +1 -1
- package/lib/families/cardano/js-getTransactionStatus.js +6 -5
- package/lib/families/cardano/js-getTransactionStatus.js.map +1 -1
- package/lib/families/cardano/js-signOperation.d.ts.map +1 -1
- package/lib/families/cardano/js-signOperation.js +10 -5
- package/lib/families/cardano/js-signOperation.js.map +1 -1
- package/lib/families/cardano/js-synchronisation.d.ts.map +1 -1
- package/lib/families/cardano/js-synchronisation.js +126 -98
- package/lib/families/cardano/js-synchronisation.js.map +1 -1
- package/lib/families/cardano/js-transaction.js +1 -1
- package/lib/families/cardano/js-transaction.js.map +1 -1
- package/lib/families/cardano/logic.d.ts +1 -0
- package/lib/families/cardano/logic.d.ts.map +1 -1
- package/lib/families/cardano/logic.js +11 -1
- package/lib/families/cardano/logic.js.map +1 -1
- package/lib/families/cardano/specs.d.ts.map +1 -1
- package/lib/families/cardano/specs.js +39 -1
- package/lib/families/cardano/specs.js.map +1 -1
- package/lib/families/cardano/speculos-deviceActions.d.ts.map +1 -1
- package/lib/families/cardano/speculos-deviceActions.js +15 -0
- package/lib/families/cardano/speculos-deviceActions.js.map +1 -1
- package/lib/families/hedera/api/mirror.js +1 -1
- package/lib/families/hedera/api/mirror.js.map +1 -1
- package/lib/families/hedera/api/network.d.ts.map +1 -1
- package/lib/families/hedera/api/network.js +3 -1
- package/lib/families/hedera/api/network.js.map +1 -1
- package/lib/families/hedera/deviceTransactionConfig.d.ts.map +1 -1
- package/lib/families/hedera/deviceTransactionConfig.js +7 -0
- package/lib/families/hedera/deviceTransactionConfig.js.map +1 -1
- package/lib/families/hedera/js-synchronisation.d.ts.map +1 -1
- package/lib/families/hedera/js-synchronisation.js +10 -7
- package/lib/families/hedera/js-synchronisation.js.map +1 -1
- package/lib/families/hedera/specs.d.ts.map +1 -1
- package/lib/families/hedera/specs.js +23 -0
- package/lib/families/hedera/specs.js.map +1 -1
- package/lib/families/hedera/speculos-deviceActions.d.ts.map +1 -1
- package/lib/families/hedera/speculos-deviceActions.js +5 -1
- package/lib/families/hedera/speculos-deviceActions.js.map +1 -1
- package/lib/families/hedera/transaction.d.ts.map +1 -1
- package/lib/families/hedera/transaction.js +2 -2
- package/lib/families/hedera/transaction.js.map +1 -1
- package/lib/families/hedera/types.d.ts +2 -5
- package/lib/families/hedera/types.d.ts.map +1 -1
- package/lib/families/hedera/types.js +0 -4
- package/lib/families/hedera/types.js.map +1 -1
- package/lib/families/hedera/utils.d.ts.map +1 -1
- package/lib/featureFlags/types.d.ts +1 -1
- package/lib/featureFlags/types.d.ts.map +1 -1
- package/lib/generated/deviceTransactionConfig.d.ts +2 -0
- package/lib/generated/deviceTransactionConfig.d.ts.map +1 -1
- package/lib/generated/deviceTransactionConfig.js +28 -26
- package/lib/generated/deviceTransactionConfig.js.map +1 -1
- package/lib/platform/PlatformAppProvider/api/api.mock.js +11 -11
- package/lib/platform/PlatformAppProvider/api/api.mock.js.map +1 -1
- package/lib/platform/PlatformAppProvider/helpers.d.ts +0 -7
- package/lib/platform/PlatformAppProvider/helpers.d.ts.map +1 -1
- package/lib/platform/PlatformAppProvider/helpers.js +1 -29
- package/lib/platform/PlatformAppProvider/helpers.js.map +1 -1
- package/lib/platform/converters.d.ts +4 -4
- package/lib/platform/converters.d.ts.map +1 -1
- package/lib/platform/converters.js +40 -2
- package/lib/platform/converters.js.map +1 -1
- package/lib/platform/filters.d.ts +18 -0
- package/lib/platform/filters.d.ts.map +1 -0
- package/lib/platform/filters.js +63 -0
- package/lib/platform/filters.js.map +1 -0
- package/lib/platform/helpers.d.ts +7 -0
- package/lib/platform/helpers.d.ts.map +1 -0
- package/lib/platform/helpers.js +22 -0
- package/lib/platform/helpers.js.map +1 -0
- package/lib/platform/logic.d.ts +1 -5
- package/lib/platform/logic.d.ts.map +1 -1
- package/lib/platform/logic.js +1 -18
- package/lib/platform/logic.js.map +1 -1
- package/lib/platform/providers/RemoteLiveAppProvider/api/mock.json +87 -246
- package/lib/platform/react.d.ts +11 -0
- package/lib/platform/react.d.ts.map +1 -0
- package/lib/platform/react.js +61 -0
- package/lib/platform/react.js.map +1 -0
- package/lib/platform/types.d.ts +8 -2
- package/lib/platform/types.d.ts.map +1 -1
- package/lib/platform/types.js +15 -0
- package/lib/platform/types.js.map +1 -1
- package/lib/platform/version.test.js +1 -1
- package/lib/walletconnect/walletconnect.test.js +0 -2
- package/lib/walletconnect/walletconnect.test.js.map +1 -1
- package/package.json +5 -4
- package/src/__tests__/accounts/importAccounts.ts +1 -1
- package/src/__tests__/test-helpers/setup.ts +1 -1
- package/src/account/helpers.ts +51 -0
- package/src/apps/filtering.test.ts +1 -1
- package/src/apps/support.ts +1 -0
- package/src/currencies/__snapshots__/sortByMarketcap.test.ts.snap +101 -0
- package/src/currencies/helpers.test.ts +21 -0
- package/src/currencies/helpers.ts +69 -0
- package/src/currencies/index.ts +1 -0
- package/src/currencies/react.ts +16 -0
- package/src/families/cardano/__snapshots__/bridge.integration.test.ts.snap +41 -1
- package/src/families/cardano/bridge.integration.test.ts +38 -0
- package/src/families/cardano/buildSubAccounts.ts +5 -3
- package/src/families/cardano/deviceTransactionConfig.ts +109 -0
- package/src/families/cardano/errors.ts +7 -0
- package/src/families/cardano/js-estimateMaxSpendable.ts +4 -1
- package/src/families/cardano/js-getTransactionStatus.ts +7 -7
- package/src/families/cardano/js-signOperation.ts +10 -5
- package/src/families/cardano/js-synchronisation.ts +52 -21
- package/src/families/cardano/js-transaction.ts +1 -1
- package/src/families/cardano/logic.ts +10 -0
- package/src/families/cardano/specs.ts +53 -1
- package/src/families/cardano/speculos-deviceActions.ts +15 -0
- package/src/families/hedera/api/mirror.ts +1 -1
- package/src/families/hedera/api/network.ts +1 -0
- package/src/families/hedera/deviceTransactionConfig.ts +8 -0
- package/src/families/hedera/js-synchronisation.ts +5 -3
- package/src/families/hedera/specs.ts +56 -5
- package/src/families/hedera/speculos-deviceActions.ts +1 -0
- package/src/families/hedera/transaction.ts +2 -0
- package/src/families/hedera/types.ts +2 -8
- package/src/families/hedera/utils.ts +1 -1
- package/src/featureFlags/types.ts +1 -0
- package/src/generated/deviceTransactionConfig.ts +3 -0
- package/src/platform/PlatformAppProvider/api/api.mock.ts +11 -11
- package/src/platform/PlatformAppProvider/helpers.ts +0 -48
- package/src/platform/converters.ts +60 -6
- package/src/platform/filters.ts +102 -0
- package/src/platform/helpers.ts +33 -0
- package/src/platform/logic.ts +1 -20
- package/src/platform/providers/RemoteLiveAppProvider/api/mock.json +87 -246
- package/src/platform/react.ts +93 -0
- package/src/platform/types.ts +23 -1
- package/src/platform/version.test.ts +1 -1
- package/src/walletconnect/walletconnect.test.ts +0 -3
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { useMemo } from "react";
|
|
2
|
+
import { listAndFilterCurrencies } from "./helpers";
|
|
3
|
+
import { Currency } from "../types";
|
|
4
|
+
import { CurrencyFilters } from "../platform/filters";
|
|
5
|
+
|
|
6
|
+
export function useFilteredCurrencies({
|
|
7
|
+
includeTokens,
|
|
8
|
+
currencies,
|
|
9
|
+
}: CurrencyFilters): Currency[] {
|
|
10
|
+
return useMemo(() => {
|
|
11
|
+
return listAndFilterCurrencies({
|
|
12
|
+
includeTokens,
|
|
13
|
+
currencies,
|
|
14
|
+
});
|
|
15
|
+
}, [currencies, includeTokens]);
|
|
16
|
+
}
|
|
@@ -820,7 +820,7 @@ Array [
|
|
|
820
820
|
"operationsCount": 4,
|
|
821
821
|
"pendingOperations": Array [],
|
|
822
822
|
"seedIdentifier": "21a6a622d47969ef0b2b89ef7c2e8428f955bae3e52f211e651ccffd",
|
|
823
|
-
"spendableBalance": "
|
|
823
|
+
"spendableBalance": "1019831859",
|
|
824
824
|
"starred": false,
|
|
825
825
|
"subAccounts": Array [],
|
|
826
826
|
"swapHistory": Array [],
|
|
@@ -829,6 +829,20 @@ Array [
|
|
|
829
829
|
"used": true,
|
|
830
830
|
"xpub": "a902bc61a79256e1d5858d2ba49cab7011a26ad49580daace7412e255e818b1c1eba2defa321ff2937deba397f639f5bbabb0f0064516301fa4d08663c83f5b2",
|
|
831
831
|
},
|
|
832
|
+
Object {
|
|
833
|
+
"approvals": undefined,
|
|
834
|
+
"balance": "5000000000",
|
|
835
|
+
"compoundBalance": undefined,
|
|
836
|
+
"id": "js:2:cardano_testnet:a902bc61a79256e1d5858d2ba49cab7011a26ad49580daace7412e255e818b1c1eba2defa321ff2937deba397f639f5bbabb0f0064516301fa4d08663c83f5b2:cardano+cardano_testnet%2Fnative%2F581684861359b6d4d00594073a9aa4223c6fc24d24da05e1b34fb865544553545f544f4b454e",
|
|
837
|
+
"operationsCount": 1,
|
|
838
|
+
"parentId": "js:2:cardano_testnet:a902bc61a79256e1d5858d2ba49cab7011a26ad49580daace7412e255e818b1c1eba2defa321ff2937deba397f639f5bbabb0f0064516301fa4d08663c83f5b2:cardano",
|
|
839
|
+
"pendingOperations": Array [],
|
|
840
|
+
"spendableBalance": "5000000000",
|
|
841
|
+
"starred": false,
|
|
842
|
+
"swapHistory": Array [],
|
|
843
|
+
"tokenId": "cardano_testnet/native/581684861359b6d4d00594073a9aa4223c6fc24d24da05e1b34fb865544553545f544f4b454e",
|
|
844
|
+
"type": "TokenAccountRaw",
|
|
845
|
+
},
|
|
832
846
|
Object {
|
|
833
847
|
"balance": "0",
|
|
834
848
|
"cardanoResources": Object {
|
|
@@ -1662,6 +1676,32 @@ Array [
|
|
|
1662
1676
|
"value": "1000000000",
|
|
1663
1677
|
},
|
|
1664
1678
|
],
|
|
1679
|
+
Array [
|
|
1680
|
+
Object {
|
|
1681
|
+
"accountId": "js:2:cardano_testnet:a902bc61a79256e1d5858d2ba49cab7011a26ad49580daace7412e255e818b1c1eba2defa321ff2937deba397f639f5bbabb0f0064516301fa4d08663c83f5b2:cardano+cardano_testnet%2Fnative%2F581684861359b6d4d00594073a9aa4223c6fc24d24da05e1b34fb865544553545f544f4b454e",
|
|
1682
|
+
"blockHash": undefined,
|
|
1683
|
+
"blockHeight": 3568569,
|
|
1684
|
+
"contract": undefined,
|
|
1685
|
+
"extra": Object {
|
|
1686
|
+
"memo": undefined,
|
|
1687
|
+
},
|
|
1688
|
+
"fee": "215441",
|
|
1689
|
+
"hash": "2c8106d296fe10a8e8bf37a0202df048265dc17f2aa6c184bd132960fbb18bae",
|
|
1690
|
+
"id": "js:2:cardano_testnet:a902bc61a79256e1d5858d2ba49cab7011a26ad49580daace7412e255e818b1c1eba2defa321ff2937deba397f639f5bbabb0f0064516301fa4d08663c83f5b2:cardano+cardano_testnet%2Fnative%2F581684861359b6d4d00594073a9aa4223c6fc24d24da05e1b34fb865544553545f544f4b454e-2c8106d296fe10a8e8bf37a0202df048265dc17f2aa6c184bd132960fbb18bae-IN",
|
|
1691
|
+
"operator": undefined,
|
|
1692
|
+
"recipients": Array [
|
|
1693
|
+
"addr_test1qqs6df3z63uknmct9wy77lpwss50j4d6u0jj7gg7v5wvll23krjmh2m86v92yu0my7rqydx3h5erqwty82kwgjuc4elsr6hdhy",
|
|
1694
|
+
"addr_test1qzpdaf0vr0gdsjncllv7cejmpwmwu6m86c3epd8uadv99ktra2x9gp8eakdwsrv4k42ys4ajqy0r7f4k8hwrhcdt6sks7k7alz",
|
|
1695
|
+
],
|
|
1696
|
+
"senders": Array [
|
|
1697
|
+
"addr_test1qr4qq9s7cf28zse9t4c46l3utj6ajphx654l8ddcv6rhketra2x9gp8eakdwsrv4k42ys4ajqy0r7f4k8hwrhcdt6sksjh37nz",
|
|
1698
|
+
],
|
|
1699
|
+
"standard": undefined,
|
|
1700
|
+
"tokenId": undefined,
|
|
1701
|
+
"type": "IN",
|
|
1702
|
+
"value": "5000000000",
|
|
1703
|
+
},
|
|
1704
|
+
],
|
|
1665
1705
|
Array [],
|
|
1666
1706
|
]
|
|
1667
1707
|
`;
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { NotEnoughBalance } from "@ledgerhq/errors";
|
|
1
2
|
import "../../__tests__/test-helpers/setup";
|
|
2
3
|
import { testBridge } from "../../__tests__/test-helpers/bridge";
|
|
3
4
|
import BigNumber from "bignumber.js";
|
|
@@ -33,6 +34,43 @@ const dataset: DatasetTest<Transaction> = {
|
|
|
33
34
|
},
|
|
34
35
|
},
|
|
35
36
|
},
|
|
37
|
+
{
|
|
38
|
+
name: "token amount more than balance",
|
|
39
|
+
transaction: fromTransactionRaw({
|
|
40
|
+
family: "cardano",
|
|
41
|
+
recipient:
|
|
42
|
+
"addr_test1qpl90kc2jl5kr9tev0s7vays9yhwcdnq8nlylyk4dqsdq3g466elxnxwrzwq72pvp5akenj30t5s9et7frfvrxxx8xcsxrzs87",
|
|
43
|
+
amount: "5000000001",
|
|
44
|
+
subAccountId:
|
|
45
|
+
"js:2:cardano_testnet:a902bc61a79256e1d5858d2ba49cab7011a26ad49580daace7412e255e818b1c1eba2defa321ff2937deba397f639f5bbabb0f0064516301fa4d08663c83f5b2:+cardano_testnet%2Fnative%2F581684861359b6d4d00594073a9aa4223c6fc24d24da05e1b34fb865544553545f544f4b454e",
|
|
46
|
+
mode: "send",
|
|
47
|
+
}),
|
|
48
|
+
expectedStatus: {
|
|
49
|
+
amount: new BigNumber("5000000001"),
|
|
50
|
+
errors: {
|
|
51
|
+
amount: new NotEnoughBalance(),
|
|
52
|
+
},
|
|
53
|
+
},
|
|
54
|
+
},
|
|
55
|
+
{
|
|
56
|
+
name: "send max token",
|
|
57
|
+
transaction: fromTransactionRaw({
|
|
58
|
+
family: "cardano",
|
|
59
|
+
recipient:
|
|
60
|
+
"addr_test1qpl90kc2jl5kr9tev0s7vays9yhwcdnq8nlylyk4dqsdq3g466elxnxwrzwq72pvp5akenj30t5s9et7frfvrxxx8xcsxrzs87",
|
|
61
|
+
amount: "0",
|
|
62
|
+
subAccountId:
|
|
63
|
+
"js:2:cardano_testnet:a902bc61a79256e1d5858d2ba49cab7011a26ad49580daace7412e255e818b1c1eba2defa321ff2937deba397f639f5bbabb0f0064516301fa4d08663c83f5b2:+cardano_testnet%2Fnative%2F581684861359b6d4d00594073a9aa4223c6fc24d24da05e1b34fb865544553545f544f4b454e",
|
|
64
|
+
mode: "send",
|
|
65
|
+
useAllAmount: true,
|
|
66
|
+
}),
|
|
67
|
+
expectedStatus: {
|
|
68
|
+
amount: new BigNumber("5000000000"),
|
|
69
|
+
totalSpent: new BigNumber("5000000000"),
|
|
70
|
+
errors: {},
|
|
71
|
+
warnings: {},
|
|
72
|
+
},
|
|
73
|
+
},
|
|
36
74
|
],
|
|
37
75
|
},
|
|
38
76
|
],
|
|
@@ -83,6 +83,10 @@ const mapTxToTokenAccountOperation = ({
|
|
|
83
83
|
|
|
84
84
|
const tokenOperationType = token.amount.lt(0) ? "OUT" : "IN";
|
|
85
85
|
const memo = getMemoFromTx(tx);
|
|
86
|
+
const extra = {};
|
|
87
|
+
if (memo) {
|
|
88
|
+
extra["memo"] = memo;
|
|
89
|
+
}
|
|
86
90
|
const operation: Operation = {
|
|
87
91
|
accountId: tokenAccountId,
|
|
88
92
|
id: encodeOperationId(tokenAccountId, tx.hash, tokenOperationType),
|
|
@@ -102,9 +106,7 @@ const mapTxToTokenAccountOperation = ({
|
|
|
102
106
|
),
|
|
103
107
|
blockHeight: tx.blockHeight,
|
|
104
108
|
date: new Date(tx.timestamp),
|
|
105
|
-
extra:
|
|
106
|
-
memo,
|
|
107
|
-
},
|
|
109
|
+
extra: extra,
|
|
108
110
|
blockHash: undefined,
|
|
109
111
|
};
|
|
110
112
|
operations.push(operation);
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
import BigNumber from "bignumber.js";
|
|
2
|
+
import { getAccountUnit, getMainAccount } from "../../account";
|
|
3
|
+
import { formatCurrencyUnit } from "../../currencies";
|
|
4
|
+
import { DeviceTransactionField } from "../../transaction";
|
|
5
|
+
import { Account, AccountLike, TransactionStatus } from "../../types";
|
|
6
|
+
import { decodeTokenAssetId, decodeTokenCurrencyId } from "./buildSubAccounts";
|
|
7
|
+
import { CardanoResources, Transaction } from "./types";
|
|
8
|
+
import { utils as TyphonUtils } from "@stricahq/typhonjs";
|
|
9
|
+
import { decodeTokenName } from "./logic";
|
|
10
|
+
|
|
11
|
+
function getDeviceTransactionConfig({
|
|
12
|
+
account,
|
|
13
|
+
transaction,
|
|
14
|
+
parentAccount,
|
|
15
|
+
}: {
|
|
16
|
+
account: AccountLike;
|
|
17
|
+
parentAccount: Account | null | undefined;
|
|
18
|
+
transaction: Transaction;
|
|
19
|
+
status: TransactionStatus;
|
|
20
|
+
}): Array<DeviceTransactionField> {
|
|
21
|
+
const { mode } = transaction;
|
|
22
|
+
const fields: DeviceTransactionField[] = [];
|
|
23
|
+
const mainAccount = getMainAccount(account, parentAccount);
|
|
24
|
+
|
|
25
|
+
if (mode === "send") {
|
|
26
|
+
if (account.type === "TokenAccount") {
|
|
27
|
+
const cardanoResources = mainAccount.cardanoResources as CardanoResources;
|
|
28
|
+
|
|
29
|
+
const { assetId } = decodeTokenCurrencyId(account.token.id);
|
|
30
|
+
const { policyId, assetName } = decodeTokenAssetId(assetId);
|
|
31
|
+
const transactionAmount = transaction.useAllAmount
|
|
32
|
+
? account.balance
|
|
33
|
+
: transaction.amount;
|
|
34
|
+
const { fees } = transaction;
|
|
35
|
+
|
|
36
|
+
const tokensToSend = [
|
|
37
|
+
{
|
|
38
|
+
policyId,
|
|
39
|
+
assetName,
|
|
40
|
+
amount: transactionAmount,
|
|
41
|
+
},
|
|
42
|
+
];
|
|
43
|
+
|
|
44
|
+
const requiredMinAdaForTokens = TyphonUtils.calculateMinUtxoAmount(
|
|
45
|
+
tokensToSend,
|
|
46
|
+
new BigNumber(cardanoResources.protocolParams.lovelacePerUtxoWord)
|
|
47
|
+
);
|
|
48
|
+
fields.push({
|
|
49
|
+
type: "text",
|
|
50
|
+
label: "ADA",
|
|
51
|
+
value: formatCurrencyUnit(
|
|
52
|
+
getAccountUnit(mainAccount),
|
|
53
|
+
requiredMinAdaForTokens,
|
|
54
|
+
{ showCode: true, disableRounding: true }
|
|
55
|
+
),
|
|
56
|
+
});
|
|
57
|
+
fields.push({
|
|
58
|
+
type: "text",
|
|
59
|
+
label: "Token Name",
|
|
60
|
+
value: decodeTokenName(assetName),
|
|
61
|
+
});
|
|
62
|
+
fields.push({
|
|
63
|
+
type: "text",
|
|
64
|
+
label: "Amount",
|
|
65
|
+
value: formatCurrencyUnit(getAccountUnit(account), transactionAmount, {
|
|
66
|
+
showCode: true,
|
|
67
|
+
disableRounding: true,
|
|
68
|
+
}),
|
|
69
|
+
});
|
|
70
|
+
if (fees) {
|
|
71
|
+
fields.push({
|
|
72
|
+
type: "text",
|
|
73
|
+
label: "Fees",
|
|
74
|
+
value: formatCurrencyUnit(getAccountUnit(mainAccount), fees, {
|
|
75
|
+
showCode: true,
|
|
76
|
+
disableRounding: true,
|
|
77
|
+
}),
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
} else if (account.type === "Account") {
|
|
81
|
+
const { fees } = transaction;
|
|
82
|
+
const transactionAmount = transaction.useAllAmount
|
|
83
|
+
? account.balance
|
|
84
|
+
: transaction.amount;
|
|
85
|
+
fields.push({
|
|
86
|
+
type: "text",
|
|
87
|
+
label: "Amount",
|
|
88
|
+
value: formatCurrencyUnit(getAccountUnit(account), transactionAmount, {
|
|
89
|
+
showCode: true,
|
|
90
|
+
disableRounding: true,
|
|
91
|
+
}),
|
|
92
|
+
});
|
|
93
|
+
if (fees) {
|
|
94
|
+
fields.push({
|
|
95
|
+
type: "text",
|
|
96
|
+
label: "Fees",
|
|
97
|
+
value: formatCurrencyUnit(getAccountUnit(account), fees, {
|
|
98
|
+
showCode: true,
|
|
99
|
+
disableRounding: true,
|
|
100
|
+
}),
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
return fields;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
export default getDeviceTransactionConfig;
|
|
@@ -6,3 +6,10 @@ import { createCustomErrorClass } from "@ledgerhq/errors";
|
|
|
6
6
|
export const CardanoMinAmountError = createCustomErrorClass(
|
|
7
7
|
"CardanoMinAmountError"
|
|
8
8
|
);
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Cardano error thrown when not enough funds to perform transaction
|
|
12
|
+
*/
|
|
13
|
+
export const CardanoNotEnoughFunds = createCustomErrorClass(
|
|
14
|
+
"CardanoNotEnoughFunds"
|
|
15
|
+
);
|
|
@@ -30,10 +30,13 @@ const estimateMaxSpendable = async ({
|
|
|
30
30
|
return account.balance;
|
|
31
31
|
}
|
|
32
32
|
|
|
33
|
+
const dummyRecipient =
|
|
34
|
+
"addr_test1qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq0uk53y";
|
|
33
35
|
const a = getMainAccount(account, parentAccount);
|
|
34
|
-
const t = {
|
|
36
|
+
const t: Transaction = {
|
|
35
37
|
...createTransaction(),
|
|
36
38
|
...transaction,
|
|
39
|
+
recipient: dummyRecipient,
|
|
37
40
|
// amount field will not be used to build a transaction when useAllAmount is true
|
|
38
41
|
amount: new BigNumber(0),
|
|
39
42
|
useAllAmount: true,
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { BigNumber } from "bignumber.js";
|
|
2
2
|
import {
|
|
3
|
-
NotEnoughBalance,
|
|
4
3
|
RecipientRequired,
|
|
5
4
|
FeeNotLoaded,
|
|
6
5
|
InvalidAddress,
|
|
@@ -10,7 +9,7 @@ import type { Account, TransactionStatus } from "../../types";
|
|
|
10
9
|
import type { CardanoResources, Token, Transaction } from "./types";
|
|
11
10
|
import { isValidAddress } from "./logic";
|
|
12
11
|
import { utils as TyphonUtils } from "@stricahq/typhonjs";
|
|
13
|
-
import { CardanoMinAmountError } from "./errors";
|
|
12
|
+
import { CardanoMinAmountError, CardanoNotEnoughFunds } from "./errors";
|
|
14
13
|
import { AccountAwaitingSendPendingOperations } from "../../errors";
|
|
15
14
|
import { getNetworkParameters } from "./networks";
|
|
16
15
|
import { decodeTokenAssetId, decodeTokenCurrencyId } from "./buildSubAccounts";
|
|
@@ -86,17 +85,18 @@ const getTransactionStatus = async (
|
|
|
86
85
|
|
|
87
86
|
if (!amount.gt(0)) {
|
|
88
87
|
errors.amount = useAllAmount
|
|
89
|
-
? new
|
|
88
|
+
? new CardanoNotEnoughFunds()
|
|
90
89
|
: new AmountRequired();
|
|
91
90
|
} else if (!t.subAccountId && amount.lt(minTransactionAmount)) {
|
|
92
91
|
errors.amount = new CardanoMinAmountError("", {
|
|
93
92
|
amount: minTransactionAmount.div(1e6).toString(),
|
|
94
93
|
});
|
|
95
94
|
} else if (
|
|
96
|
-
|
|
97
|
-
|
|
95
|
+
tokenAccount
|
|
96
|
+
? totalSpent.gt(tokenAccount.balance)
|
|
97
|
+
: totalSpent.gt(a.balance)
|
|
98
98
|
) {
|
|
99
|
-
errors.amount = new
|
|
99
|
+
errors.amount = new CardanoNotEnoughFunds();
|
|
100
100
|
} else {
|
|
101
101
|
try {
|
|
102
102
|
await buildTransaction(a, t);
|
|
@@ -105,7 +105,7 @@ const getTransactionStatus = async (
|
|
|
105
105
|
e.message.toLowerCase() === "not enough ada" ||
|
|
106
106
|
e.message.toLowerCase() === "not enough tokens"
|
|
107
107
|
) {
|
|
108
|
-
errors.amount = new
|
|
108
|
+
errors.amount = new CardanoNotEnoughFunds();
|
|
109
109
|
}
|
|
110
110
|
throw e;
|
|
111
111
|
}
|
|
@@ -83,11 +83,18 @@ const buildOptimisticOperation = (
|
|
|
83
83
|
const memoMetadata = auxiliaryData.metadata.find(
|
|
84
84
|
(m) => m.label === MEMO_LABEL
|
|
85
85
|
);
|
|
86
|
-
if (memoMetadata &&
|
|
87
|
-
|
|
86
|
+
if (memoMetadata && memoMetadata.data instanceof Map) {
|
|
87
|
+
const msg = memoMetadata.data.get("msg");
|
|
88
|
+
if (Array.isArray(msg) && msg.length) {
|
|
89
|
+
memo = msg.join(", ");
|
|
90
|
+
}
|
|
88
91
|
}
|
|
89
92
|
}
|
|
90
93
|
|
|
94
|
+
const extra = {};
|
|
95
|
+
if (memo) {
|
|
96
|
+
extra["memo"] = memo;
|
|
97
|
+
}
|
|
91
98
|
const op: Operation = {
|
|
92
99
|
id: encodeOperationId(account.id, transactionHash, opType),
|
|
93
100
|
hash: transactionHash,
|
|
@@ -100,9 +107,7 @@ const buildOptimisticOperation = (
|
|
|
100
107
|
recipients: transaction.getOutputs().map((o) => o.address.getBech32()),
|
|
101
108
|
accountId: account.id,
|
|
102
109
|
date: new Date(),
|
|
103
|
-
extra:
|
|
104
|
-
memo,
|
|
105
|
-
},
|
|
110
|
+
extra: extra,
|
|
106
111
|
};
|
|
107
112
|
|
|
108
113
|
const tokenAccount = t.subAccountId
|
|
@@ -21,6 +21,7 @@ import {
|
|
|
21
21
|
getMemoFromTx,
|
|
22
22
|
getOperationType,
|
|
23
23
|
isHexString,
|
|
24
|
+
mergeTokens,
|
|
24
25
|
} from "./logic";
|
|
25
26
|
import { encodeOperationId } from "../../operation";
|
|
26
27
|
import { getNetworkParameters } from "./networks";
|
|
@@ -28,6 +29,9 @@ import { getNetworkInfo } from "./api/getNetworkInfo";
|
|
|
28
29
|
import uniqBy from "lodash/uniqBy";
|
|
29
30
|
import postSyncPatch from "./postSyncPatch";
|
|
30
31
|
import { getTransactions } from "./api/getTransactions";
|
|
32
|
+
import { buildSubAccounts } from "./buildSubAccounts";
|
|
33
|
+
import { calculateMinUtxoAmount } from "@stricahq/typhonjs/dist/utils/utils";
|
|
34
|
+
import { listTokensForCryptoCurrency } from "../../currencies";
|
|
31
35
|
|
|
32
36
|
function mapTxToAccountOperation(
|
|
33
37
|
tx: APITransaction,
|
|
@@ -43,6 +47,10 @@ function mapTxToAccountOperation(
|
|
|
43
47
|
|
|
44
48
|
const subOperations = inferSubOperations(tx.hash, subAccounts);
|
|
45
49
|
const memo = getMemoFromTx(tx);
|
|
50
|
+
const extra = {};
|
|
51
|
+
if (memo) {
|
|
52
|
+
extra["memo"] = memo;
|
|
53
|
+
}
|
|
46
54
|
|
|
47
55
|
return {
|
|
48
56
|
accountId,
|
|
@@ -64,14 +72,12 @@ function mapTxToAccountOperation(
|
|
|
64
72
|
subOperations,
|
|
65
73
|
blockHeight: tx.blockHeight,
|
|
66
74
|
date: new Date(tx.timestamp),
|
|
67
|
-
extra:
|
|
68
|
-
memo,
|
|
69
|
-
},
|
|
75
|
+
extra: extra,
|
|
70
76
|
blockHash: undefined,
|
|
71
77
|
};
|
|
72
78
|
}
|
|
73
79
|
|
|
74
|
-
function
|
|
80
|
+
function prepareUtxos(
|
|
75
81
|
newTransactions: Array<APITransaction>,
|
|
76
82
|
stableUtxos: Array<CardanoOutput>,
|
|
77
83
|
accountCredentialsMap: Record<string, PaymentCredential>
|
|
@@ -116,7 +122,10 @@ function syncUtxos(
|
|
|
116
122
|
return utxos;
|
|
117
123
|
}
|
|
118
124
|
|
|
119
|
-
export const getAccountShape: GetAccountShape = async (
|
|
125
|
+
export const getAccountShape: GetAccountShape = async (
|
|
126
|
+
info,
|
|
127
|
+
{ blacklistedTokenIds }
|
|
128
|
+
) => {
|
|
120
129
|
const {
|
|
121
130
|
transport,
|
|
122
131
|
currency,
|
|
@@ -152,16 +161,27 @@ export const getAccountShape: GetAccountShape = async (info) => {
|
|
|
152
161
|
derivationMode,
|
|
153
162
|
});
|
|
154
163
|
|
|
164
|
+
// when new tokens are added / blacklist changes, we need to sync again because we need to go through all operations again
|
|
165
|
+
const syncHash =
|
|
166
|
+
JSON.stringify(blacklistedTokenIds || []) +
|
|
167
|
+
"_" +
|
|
168
|
+
listTokensForCryptoCurrency(currency, {
|
|
169
|
+
withDelisted: true,
|
|
170
|
+
}).length;
|
|
171
|
+
const outdatedSyncHash = initialAccount?.syncHash !== syncHash;
|
|
172
|
+
|
|
155
173
|
const requiredConfirmations = 90;
|
|
156
174
|
|
|
157
175
|
const oldOperations = initialAccount?.operations || [];
|
|
158
176
|
const lastBlockHeight = oldOperations.length
|
|
159
177
|
? (oldOperations[0].blockHeight || 0) + 1
|
|
160
178
|
: 0;
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
179
|
+
|
|
180
|
+
const syncFromBlockHeight = outdatedSyncHash
|
|
181
|
+
? 0
|
|
182
|
+
: lastBlockHeight > requiredConfirmations
|
|
183
|
+
? lastBlockHeight - requiredConfirmations
|
|
184
|
+
: 0;
|
|
165
185
|
|
|
166
186
|
const {
|
|
167
187
|
transactions: newTransactions,
|
|
@@ -195,21 +215,24 @@ export const getAccountShape: GetAccountShape = async (info) => {
|
|
|
195
215
|
(u) => stableOperationsByIds[u.hash]
|
|
196
216
|
);
|
|
197
217
|
|
|
198
|
-
const utxos =
|
|
218
|
+
const utxos = prepareUtxos(
|
|
219
|
+
newTransactions,
|
|
220
|
+
stableUtxos,
|
|
221
|
+
accountCredentialsMap
|
|
222
|
+
);
|
|
199
223
|
const accountBalance = utxos.reduce(
|
|
200
224
|
(total, u) => total.plus(u.amount),
|
|
201
225
|
new BigNumber(0)
|
|
202
226
|
);
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
const subAccounts = [];
|
|
227
|
+
const tokenBalance = mergeTokens(utxos.map((u) => u.tokens).flat());
|
|
228
|
+
const subAccounts = buildSubAccounts({
|
|
229
|
+
initialAccount,
|
|
230
|
+
parentAccountId: accountId,
|
|
231
|
+
parentCurrency: currency,
|
|
232
|
+
newTransactions,
|
|
233
|
+
tokens: tokenBalance,
|
|
234
|
+
accountCredentialsMap,
|
|
235
|
+
});
|
|
213
236
|
|
|
214
237
|
const newOperations = newTransactions.map((t) =>
|
|
215
238
|
mapTxToAccountOperation(t, accountId, accountCredentialsMap, subAccounts)
|
|
@@ -233,13 +256,21 @@ export const getAccountShape: GetAccountShape = async (info) => {
|
|
|
233
256
|
}).getBech32(),
|
|
234
257
|
}));
|
|
235
258
|
const cardanoNetworkInfo = await getNetworkInfo(initialAccount, currency);
|
|
259
|
+
const minAdaBalanceForTokens = tokenBalance.length
|
|
260
|
+
? calculateMinUtxoAmount(
|
|
261
|
+
tokenBalance,
|
|
262
|
+
new BigNumber(cardanoNetworkInfo.protocolParams.lovelacePerUtxoWord),
|
|
263
|
+
false
|
|
264
|
+
)
|
|
265
|
+
: new BigNumber(0);
|
|
236
266
|
|
|
237
267
|
return {
|
|
238
268
|
id: accountId,
|
|
239
269
|
xpub,
|
|
240
270
|
balance: accountBalance,
|
|
241
|
-
spendableBalance: accountBalance,
|
|
271
|
+
spendableBalance: accountBalance.minus(minAdaBalanceForTokens),
|
|
242
272
|
operations: operations,
|
|
273
|
+
syncHash,
|
|
243
274
|
subAccounts,
|
|
244
275
|
freshAddresses,
|
|
245
276
|
freshAddress: freshAddresses[0].address,
|
|
@@ -47,7 +47,7 @@ export const prepareTransaction = async (
|
|
|
47
47
|
try {
|
|
48
48
|
transaction = await buildTransaction(a, t);
|
|
49
49
|
} catch (error) {
|
|
50
|
-
return { ...t, fees: new BigNumber(0), amount:
|
|
50
|
+
return { ...t, fees: new BigNumber(0), amount: t.amount };
|
|
51
51
|
}
|
|
52
52
|
|
|
53
53
|
const transactionFees = transaction.getFee();
|
|
@@ -448,3 +448,13 @@ export function isHexString(value: string): boolean {
|
|
|
448
448
|
const regExp = /^[0-9a-fA-F]+$/;
|
|
449
449
|
return regExp.test(value);
|
|
450
450
|
}
|
|
451
|
+
|
|
452
|
+
export function decodeTokenName(assetName: string): string {
|
|
453
|
+
if (assetName.length > 0) {
|
|
454
|
+
const bytes = [...Buffer.from(assetName, "hex")];
|
|
455
|
+
if (bytes.filter((byte) => byte <= 32 || byte >= 127).length === 0) {
|
|
456
|
+
return String.fromCharCode(...bytes);
|
|
457
|
+
}
|
|
458
|
+
}
|
|
459
|
+
return assetName;
|
|
460
|
+
}
|
|
@@ -9,10 +9,15 @@ import invariant from "invariant";
|
|
|
9
9
|
import { utils as TyphonUtils } from "@stricahq/typhonjs";
|
|
10
10
|
import { mergeTokens } from "./logic";
|
|
11
11
|
import { parseCurrencyUnit } from "../../currencies";
|
|
12
|
+
import { SubAccount } from "../../types";
|
|
12
13
|
|
|
13
14
|
const currency = getCryptoCurrencyById("cardano");
|
|
14
15
|
const minBalanceRequired = parseCurrencyUnit(currency.units[0], "2.2");
|
|
15
16
|
const minBalanceRequiredForMaxSend = parseCurrencyUnit(currency.units[0], "1");
|
|
17
|
+
const minSpendableRequiredForTokenTx = parseCurrencyUnit(
|
|
18
|
+
currency.units[0],
|
|
19
|
+
"3"
|
|
20
|
+
);
|
|
16
21
|
|
|
17
22
|
const cardano: AppSpec<Transaction> = {
|
|
18
23
|
name: "cardano",
|
|
@@ -34,7 +39,12 @@ const cardano: AppSpec<Transaction> = {
|
|
|
34
39
|
|
|
35
40
|
const updates = [
|
|
36
41
|
{ recipient },
|
|
37
|
-
{
|
|
42
|
+
{
|
|
43
|
+
amount: new BigNumber(account.balance.dividedBy(2)).dp(
|
|
44
|
+
0,
|
|
45
|
+
BigNumber.ROUND_CEIL
|
|
46
|
+
),
|
|
47
|
+
},
|
|
38
48
|
{ memo: "LedgerLiveBot" },
|
|
39
49
|
];
|
|
40
50
|
|
|
@@ -90,6 +100,48 @@ const cardano: AppSpec<Transaction> = {
|
|
|
90
100
|
);
|
|
91
101
|
},
|
|
92
102
|
},
|
|
103
|
+
{
|
|
104
|
+
name: "move ~10% token",
|
|
105
|
+
maxRun: 1,
|
|
106
|
+
transaction: ({ account, siblings, bridge, maxSpendable }) => {
|
|
107
|
+
invariant(
|
|
108
|
+
maxSpendable.gte(minSpendableRequiredForTokenTx),
|
|
109
|
+
"balance is too low"
|
|
110
|
+
);
|
|
111
|
+
const sibling = pickSiblings(siblings, 3);
|
|
112
|
+
const recipient = sibling.freshAddress;
|
|
113
|
+
const transaction = bridge.createTransaction(account);
|
|
114
|
+
|
|
115
|
+
const subAccount = account.subAccounts?.find((subAccount) =>
|
|
116
|
+
subAccount.balance.gt(1)
|
|
117
|
+
) as SubAccount;
|
|
118
|
+
invariant(subAccount, "No token account with balance");
|
|
119
|
+
|
|
120
|
+
const updates = [
|
|
121
|
+
{ subAccountId: subAccount.id },
|
|
122
|
+
{ recipient },
|
|
123
|
+
{
|
|
124
|
+
amount: new BigNumber(subAccount.balance.dividedBy(10)).dp(
|
|
125
|
+
0,
|
|
126
|
+
BigNumber.ROUND_CEIL
|
|
127
|
+
),
|
|
128
|
+
},
|
|
129
|
+
];
|
|
130
|
+
|
|
131
|
+
return {
|
|
132
|
+
transaction,
|
|
133
|
+
updates,
|
|
134
|
+
};
|
|
135
|
+
},
|
|
136
|
+
test: ({ operation, transaction }): void => {
|
|
137
|
+
expect(operation.subOperations).toBeTruthy();
|
|
138
|
+
expect(operation.subOperations?.length).toEqual(1);
|
|
139
|
+
|
|
140
|
+
const subOperation =
|
|
141
|
+
operation.subOperations && operation.subOperations[0];
|
|
142
|
+
expect(subOperation?.value).toEqual(transaction.amount);
|
|
143
|
+
},
|
|
144
|
+
},
|
|
93
145
|
],
|
|
94
146
|
};
|
|
95
147
|
|
|
@@ -39,6 +39,21 @@ const acceptTransaction: DeviceAction<Transaction, any> = deviceActionFlow({
|
|
|
39
39
|
expectedValue: ({ account, status }) =>
|
|
40
40
|
expectedValue(account.unit, status.amount),
|
|
41
41
|
},
|
|
42
|
+
{
|
|
43
|
+
title: "Asset fingerprint",
|
|
44
|
+
button: "LRlr",
|
|
45
|
+
},
|
|
46
|
+
{
|
|
47
|
+
title: "Token amount",
|
|
48
|
+
button: "LRlr",
|
|
49
|
+
},
|
|
50
|
+
{
|
|
51
|
+
title: "Confirm",
|
|
52
|
+
},
|
|
53
|
+
{
|
|
54
|
+
title: "output?",
|
|
55
|
+
button: "Rr",
|
|
56
|
+
},
|
|
42
57
|
{
|
|
43
58
|
title: "Transaction fee",
|
|
44
59
|
button: "LRlr",
|
|
@@ -136,7 +136,7 @@ export async function getOperationsForAccount(
|
|
|
136
136
|
// Set a value just so that it's considered confirmed according to isConfirmedOperation
|
|
137
137
|
blockHeight: 5,
|
|
138
138
|
blockHash: null,
|
|
139
|
-
extra: {
|
|
139
|
+
extra: {},
|
|
140
140
|
fee,
|
|
141
141
|
hash,
|
|
142
142
|
recipients,
|
|
@@ -23,6 +23,7 @@ export async function buildUnsignedTransaction({
|
|
|
23
23
|
return new hedera.TransferTransaction()
|
|
24
24
|
.setNodeAccountIds([new AccountId(3)])
|
|
25
25
|
.setTransactionId(hedera.TransactionId.generate(accountId))
|
|
26
|
+
.setTransactionMemo(transaction.memo ?? "")
|
|
26
27
|
.addHbarTransfer(accountId, hbarAmount.negated())
|
|
27
28
|
.addHbarTransfer(transaction.recipient, hbarAmount)
|
|
28
29
|
.freeze();
|