@ledgerhq/live-common 21.17.2 → 21.19.1

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.
Files changed (119) hide show
  1. package/lib/__tests__/test-helpers/setup.js +1 -0
  2. package/lib/__tests__/test-helpers/setup.js.map +1 -1
  3. package/lib/account/addAccounts.d.ts.map +1 -1
  4. package/lib/account/addAccounts.js +3 -2
  5. package/lib/account/addAccounts.js.map +1 -1
  6. package/lib/account/helpers.d.ts.map +1 -1
  7. package/lib/account/helpers.js +1 -0
  8. package/lib/account/helpers.js.map +1 -1
  9. package/lib/api/Ethereum.d.ts.map +1 -1
  10. package/lib/api/Ethereum.js +2 -1
  11. package/lib/api/Ethereum.js.map +1 -1
  12. package/lib/api/explorerConfig/index.d.ts.map +1 -1
  13. package/lib/api/explorerConfig/index.js +0 -4
  14. package/lib/api/explorerConfig/index.js.map +1 -1
  15. package/lib/bridge/jsHelpers.d.ts.map +1 -1
  16. package/lib/bridge/jsHelpers.js +9 -8
  17. package/lib/bridge/jsHelpers.js.map +1 -1
  18. package/lib/env.d.ts +10 -5
  19. package/lib/env.d.ts.map +1 -1
  20. package/lib/env.js +5 -0
  21. package/lib/env.js.map +1 -1
  22. package/lib/env.react.d.ts +1 -1
  23. package/lib/env.react.d.ts.map +1 -1
  24. package/lib/families/bitcoin/getAccountNetworkInfo.d.ts.map +1 -1
  25. package/lib/families/bitcoin/getAccountNetworkInfo.js +12 -2
  26. package/lib/families/bitcoin/getAccountNetworkInfo.js.map +1 -1
  27. package/lib/families/bitcoin/test-dataset.js +2 -2
  28. package/lib/families/bitcoin/test-dataset.js.map +1 -1
  29. package/lib/families/bitcoin/types.d.ts +1 -0
  30. package/lib/families/bitcoin/types.d.ts.map +1 -1
  31. package/lib/families/bitcoin/types.js.map +1 -1
  32. package/lib/families/bitcoin/wallet-btc/explorer/index.d.ts +1 -0
  33. package/lib/families/bitcoin/wallet-btc/explorer/index.d.ts.map +1 -1
  34. package/lib/families/bitcoin/wallet-btc/explorer/index.js +19 -0
  35. package/lib/families/bitcoin/wallet-btc/explorer/index.js.map +1 -1
  36. package/lib/families/bitcoin/wallet-btc/explorer/types.d.ts +1 -0
  37. package/lib/families/bitcoin/wallet-btc/explorer/types.d.ts.map +1 -1
  38. package/lib/families/ethereum/bridge/js.d.ts.map +1 -1
  39. package/lib/families/ethereum/bridge/js.js +3 -0
  40. package/lib/families/ethereum/bridge/js.js.map +1 -1
  41. package/lib/families/ethereum/cli-transaction.d.ts.map +1 -1
  42. package/lib/families/ethereum/cli-transaction.js +10 -0
  43. package/lib/families/ethereum/cli-transaction.js.map +1 -1
  44. package/lib/families/ethereum/modules/erc1155.d.ts +4 -0
  45. package/lib/families/ethereum/modules/erc1155.d.ts.map +1 -0
  46. package/lib/families/ethereum/modules/erc1155.js +129 -0
  47. package/lib/families/ethereum/modules/erc1155.js.map +1 -0
  48. package/lib/families/ethereum/modules/erc721.d.ts +6 -0
  49. package/lib/families/ethereum/modules/erc721.d.ts.map +1 -0
  50. package/lib/families/ethereum/modules/erc721.js +189 -0
  51. package/lib/families/ethereum/modules/erc721.js.map +1 -0
  52. package/lib/families/ethereum/modules/index.d.ts +8 -1
  53. package/lib/families/ethereum/modules/index.d.ts.map +1 -1
  54. package/lib/families/ethereum/modules/index.js +14 -2
  55. package/lib/families/ethereum/modules/index.js.map +1 -1
  56. package/lib/families/ethereum/nft.test.d.ts +2 -0
  57. package/lib/families/ethereum/nft.test.d.ts.map +1 -0
  58. package/lib/families/ethereum/nft.test.js +353 -0
  59. package/lib/families/ethereum/nft.test.js.map +1 -0
  60. package/lib/families/ethereum/signOperation.d.ts.map +1 -1
  61. package/lib/families/ethereum/signOperation.js +3 -12
  62. package/lib/families/ethereum/signOperation.js.map +1 -1
  63. package/lib/families/ethereum/synchronisation.d.ts.map +1 -1
  64. package/lib/families/ethereum/synchronisation.js +21 -38
  65. package/lib/families/ethereum/synchronisation.js.map +1 -1
  66. package/lib/families/ethereum/synchronisation.test.js.map +1 -1
  67. package/lib/families/ethereum/transaction.d.ts.map +1 -1
  68. package/lib/families/ethereum/transaction.js +25 -8
  69. package/lib/families/ethereum/transaction.js.map +1 -1
  70. package/lib/families/ethereum/types.d.ts +8 -0
  71. package/lib/families/ethereum/types.d.ts.map +1 -1
  72. package/lib/families/ethereum/types.js.map +1 -1
  73. package/lib/hw/uninstallApp.d.ts.map +1 -1
  74. package/lib/hw/uninstallApp.js +1 -1
  75. package/lib/hw/uninstallApp.js.map +1 -1
  76. package/lib/nft/helpers.js +1 -2
  77. package/lib/nft/helpers.js.map +1 -1
  78. package/lib/nft/index.d.ts +1 -0
  79. package/lib/nft/index.d.ts.map +1 -1
  80. package/lib/nft/index.js +1 -0
  81. package/lib/nft/index.js.map +1 -1
  82. package/lib/nft/support.d.ts +4 -0
  83. package/lib/nft/support.d.ts.map +1 -0
  84. package/lib/nft/support.js +16 -0
  85. package/lib/nft/support.js.map +1 -0
  86. package/package.json +4 -4
  87. package/src/.DS_Store +0 -0
  88. package/src/__tests__/.DS_Store +0 -0
  89. package/src/__tests__/__snapshots__/all.libcore.ts.snap +10 -49
  90. package/src/__tests__/test-helpers/setup.ts +1 -0
  91. package/src/account/addAccounts.ts +3 -2
  92. package/src/account/helpers.ts +1 -0
  93. package/src/api/Ethereum.ts +4 -4
  94. package/src/api/explorerConfig/index.ts +0 -4
  95. package/src/bridge/jsHelpers.ts +9 -8
  96. package/src/currencies/{.DS_Store → __snapshots__/.DS_Store} +0 -0
  97. package/src/env.ts +5 -0
  98. package/src/families/bitcoin/getAccountNetworkInfo.ts +8 -1
  99. package/src/families/bitcoin/test-dataset.ts +2 -2
  100. package/src/families/bitcoin/types.ts +1 -0
  101. package/src/families/bitcoin/wallet-btc/explorer/index.ts +7 -0
  102. package/src/families/bitcoin/wallet-btc/explorer/types.ts +1 -0
  103. package/src/families/ethereum/bridge/js.ts +8 -1
  104. package/src/families/ethereum/cli-transaction.ts +10 -0
  105. package/src/families/ethereum/modules/erc1155.ts +157 -0
  106. package/src/families/ethereum/modules/erc721.ts +146 -0
  107. package/src/families/ethereum/modules/index.ts +32 -1
  108. package/src/families/ethereum/nft.test.ts +259 -0
  109. package/src/families/ethereum/signOperation.ts +3 -16
  110. package/src/families/ethereum/synchronisation.test.ts +1 -0
  111. package/src/families/ethereum/synchronisation.ts +104 -113
  112. package/src/families/ethereum/transaction.ts +42 -8
  113. package/src/families/ethereum/types.ts +8 -0
  114. package/src/hw/uninstallApp.ts +13 -8
  115. package/src/nft/helpers.ts +1 -1
  116. package/src/nft/index.ts +1 -0
  117. package/src/nft/support.ts +16 -0
  118. package/src/types/account.ts +1 -1
  119. package/src/currencies/__snapshots__/sortByMarketcap.test.ts.snap +0 -6150
@@ -0,0 +1,4 @@
1
+ import { Transaction, CryptoCurrency } from "../types";
2
+ export declare const isNftTransaction: (transaction: Transaction) => boolean;
3
+ export declare function isNFTActive(currency: CryptoCurrency): boolean;
4
+ //# sourceMappingURL=support.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"support.d.ts","sourceRoot":"","sources":["../../src/nft/support.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC;AAGvD,eAAO,MAAM,gBAAgB,gBAAiB,WAAW,KAAG,OAM3D,CAAC;AAEF,wBAAgB,WAAW,CAAC,QAAQ,EAAE,cAAc,GAAG,OAAO,CAI7D"}
@@ -0,0 +1,16 @@
1
+ "use strict";
2
+ exports.__esModule = true;
3
+ exports.isNFTActive = exports.isNftTransaction = void 0;
4
+ var env_1 = require("../env");
5
+ var isNftTransaction = function (transaction) {
6
+ if (transaction.family === "ethereum") {
7
+ return ["erc721.transfer", "erc1155.transfer"].includes(transaction.mode);
8
+ }
9
+ return false;
10
+ };
11
+ exports.isNftTransaction = isNftTransaction;
12
+ function isNFTActive(currency) {
13
+ return ((0, env_1.getEnv)("NFT") && (0, env_1.getEnv)("NFT_CURRENCIES").split(",").includes(currency.id));
14
+ }
15
+ exports.isNFTActive = isNFTActive;
16
+ //# sourceMappingURL=support.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"support.js","sourceRoot":"","sources":["../../src/nft/support.ts"],"names":[],"mappings":";;;AACA,8BAAgC;AAEzB,IAAM,gBAAgB,GAAG,UAAC,WAAwB;IACvD,IAAI,WAAW,CAAC,MAAM,KAAK,UAAU,EAAE;QACrC,OAAO,CAAC,iBAAiB,EAAE,kBAAkB,CAAC,CAAC,QAAQ,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC;KAC3E;IAED,OAAO,KAAK,CAAC;AACf,CAAC,CAAC;AANW,QAAA,gBAAgB,oBAM3B;AAEF,SAAgB,WAAW,CAAC,QAAwB;IAClD,OAAO,CACL,IAAA,YAAM,EAAC,KAAK,CAAC,IAAI,IAAA,YAAM,EAAC,gBAAgB,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC,CAC3E,CAAC;AACJ,CAAC;AAJD,kCAIC"}
package/package.json CHANGED
@@ -8,7 +8,7 @@
8
8
  "type": "git",
9
9
  "url": "https://github.com/LedgerHQ/ledger-live-common"
10
10
  },
11
- "version": "21.17.2",
11
+ "version": "21.19.1",
12
12
  "main": "lib/index.js",
13
13
  "types": "lib/index.d.ts",
14
14
  "license": "Apache-2.0",
@@ -44,13 +44,13 @@
44
44
  "dependencies": {
45
45
  "@crypto-com/chain-jslib": "0.0.19",
46
46
  "@ledgerhq/compressjs": "1.3.2",
47
- "@ledgerhq/cryptoassets": "6.16.0",
47
+ "@ledgerhq/cryptoassets": "6.18.0",
48
48
  "@ledgerhq/devices": "6.11.2",
49
49
  "@ledgerhq/errors": "6.10.0",
50
50
  "@ledgerhq/hw-app-algorand": "6.11.2",
51
- "@ledgerhq/hw-app-btc": "6.15.1",
51
+ "@ledgerhq/hw-app-btc": "6.17.1",
52
52
  "@ledgerhq/hw-app-cosmos": "6.11.2",
53
- "@ledgerhq/hw-app-eth": "6.16.2",
53
+ "@ledgerhq/hw-app-eth": "6.18.0",
54
54
  "@ledgerhq/hw-app-polkadot": "6.11.2",
55
55
  "@ledgerhq/hw-app-str": "6.11.2",
56
56
  "@ledgerhq/hw-app-tezos": "6.11.2",
package/src/.DS_Store CHANGED
Binary file
Binary file
@@ -11485,45 +11485,6 @@ Array [
11485
11485
  ]
11486
11486
  `;
11487
11487
 
11488
- exports[`bitcoin_cash currency bridge scanAccounts bitcoin_cash seed 1 1`] = `
11489
- Array [
11490
- Object {
11491
- "balance": "0",
11492
- "bitcoinResources": Object {},
11493
- "currencyId": "bitcoin_cash",
11494
- "derivationMode": "",
11495
- "freshAddress": "bitcoincash:qrt2zkjjchuxkmr3f70tc2yppl5pxwr36uuur9lzm9",
11496
- "freshAddressPath": "44'/145'/0'/0/0",
11497
- "freshAddresses": Array [
11498
- Object {
11499
- "address": "1LZru3UChDXkw4aYzn5dFdjvNDrKp3MtiA",
11500
- "derivationPath": "44'/145'/0'/0/0",
11501
- },
11502
- ],
11503
- "id": "js:2:bitcoin_cash:xpub6D7pqJa4V3SFSigcsRaFL2mpfG7469osrMkk4ieR2uk8y1v3nuQUD8W8v36PLWQtVRSggSQM7jLpGNKH7sqCaoPSJEp9wZCVkRnMWoiUUXa:",
11504
- "index": 0,
11505
- "name": "Bitcoin Cash 1",
11506
- "nfts": undefined,
11507
- "operationsCount": 0,
11508
- "pendingOperations": Array [],
11509
- "seedIdentifier": "04884ed3fe628a8487f782f97f38e7a9f014e624f1ea679951cf3a67445ea33fb334f4cc19e6c421b3ef9943d526cd4fbfebacebe8a62cc45db79a33d3ab04bd47",
11510
- "spendableBalance": "0",
11511
- "starred": false,
11512
- "swapHistory": Array [],
11513
- "syncHash": undefined,
11514
- "unitMagnitude": 8,
11515
- "used": false,
11516
- "xpub": "xpub6D7pqJa4V3SFSigcsRaFL2mpfG7469osrMkk4ieR2uk8y1v3nuQUD8W8v36PLWQtVRSggSQM7jLpGNKH7sqCaoPSJEp9wZCVkRnMWoiUUXa",
11517
- },
11518
- ]
11519
- `;
11520
-
11521
- exports[`bitcoin_cash currency bridge scanAccounts bitcoin_cash seed 1 2`] = `
11522
- Array [
11523
- Array [],
11524
- ]
11525
- `;
11526
-
11527
11488
  exports[`dash currency bridge scanAccounts dash seed 1 1`] = `
11528
11489
  Array [
11529
11490
  Object {
@@ -15216,7 +15177,7 @@ Array [
15216
15177
  "starred": false,
15217
15178
  "subAccounts": Array [],
15218
15179
  "swapHistory": Array [],
15219
- "syncHash": "[\\"ethereum/erc20/ampleforth\\",\\"ethereum/erc20/steth\\"]_6026",
15180
+ "syncHash": "[\\"ethereum/erc20/ampleforth\\",\\"ethereum/erc20/steth\\"]_false_6026",
15220
15181
  "unitMagnitude": 18,
15221
15182
  "used": true,
15222
15183
  },
@@ -15257,7 +15218,7 @@ Array [
15257
15218
  "starred": false,
15258
15219
  "subAccounts": Array [],
15259
15220
  "swapHistory": Array [],
15260
- "syncHash": "[\\"ethereum/erc20/ampleforth\\",\\"ethereum/erc20/steth\\"]_6026",
15221
+ "syncHash": "[\\"ethereum/erc20/ampleforth\\",\\"ethereum/erc20/steth\\"]_false_6026",
15261
15222
  "unitMagnitude": 18,
15262
15223
  "used": true,
15263
15224
  },
@@ -15737,7 +15698,7 @@ Array [
15737
15698
  "starred": false,
15738
15699
  "subAccounts": Array [],
15739
15700
  "swapHistory": Array [],
15740
- "syncHash": "[\\"ethereum/erc20/ampleforth\\",\\"ethereum/erc20/steth\\"]_6026",
15701
+ "syncHash": "[\\"ethereum/erc20/ampleforth\\",\\"ethereum/erc20/steth\\"]_false_6026",
15741
15702
  "unitMagnitude": 18,
15742
15703
  "used": true,
15743
15704
  },
@@ -16072,7 +16033,7 @@ Array [
16072
16033
  "starred": false,
16073
16034
  "subAccounts": Array [],
16074
16035
  "swapHistory": Array [],
16075
- "syncHash": "[\\"ethereum/erc20/ampleforth\\",\\"ethereum/erc20/steth\\"]_6026",
16036
+ "syncHash": "[\\"ethereum/erc20/ampleforth\\",\\"ethereum/erc20/steth\\"]_false_6026",
16076
16037
  "unitMagnitude": 18,
16077
16038
  "used": true,
16078
16039
  },
@@ -16169,7 +16130,7 @@ Array [
16169
16130
  "starred": false,
16170
16131
  "subAccounts": Array [],
16171
16132
  "swapHistory": Array [],
16172
- "syncHash": "[\\"ethereum/erc20/ampleforth\\",\\"ethereum/erc20/steth\\"]_6026",
16133
+ "syncHash": "[\\"ethereum/erc20/ampleforth\\",\\"ethereum/erc20/steth\\"]_false_6026",
16173
16134
  "unitMagnitude": 18,
16174
16135
  "used": true,
16175
16136
  },
@@ -16294,7 +16255,7 @@ Array [
16294
16255
  "starred": false,
16295
16256
  "subAccounts": Array [],
16296
16257
  "swapHistory": Array [],
16297
- "syncHash": "[\\"ethereum/erc20/ampleforth\\",\\"ethereum/erc20/steth\\"]_6026",
16258
+ "syncHash": "[\\"ethereum/erc20/ampleforth\\",\\"ethereum/erc20/steth\\"]_false_6026",
16298
16259
  "unitMagnitude": 18,
16299
16260
  "used": true,
16300
16261
  },
@@ -16391,7 +16352,7 @@ Array [
16391
16352
  "starred": false,
16392
16353
  "subAccounts": Array [],
16393
16354
  "swapHistory": Array [],
16394
- "syncHash": "[\\"ethereum/erc20/ampleforth\\",\\"ethereum/erc20/steth\\"]_6026",
16355
+ "syncHash": "[\\"ethereum/erc20/ampleforth\\",\\"ethereum/erc20/steth\\"]_false_6026",
16395
16356
  "unitMagnitude": 18,
16396
16357
  "used": true,
16397
16358
  },
@@ -48324,7 +48285,7 @@ Array [
48324
48285
  "starred": false,
48325
48286
  "subAccounts": Array [],
48326
48287
  "swapHistory": Array [],
48327
- "syncHash": "[\\"ethereum/erc20/ampleforth\\",\\"ethereum/erc20/steth\\"]_0",
48288
+ "syncHash": "[\\"ethereum/erc20/ampleforth\\",\\"ethereum/erc20/steth\\"]_false_0",
48328
48289
  "unitMagnitude": 18,
48329
48290
  "used": true,
48330
48291
  },
@@ -48351,7 +48312,7 @@ Array [
48351
48312
  "starred": false,
48352
48313
  "subAccounts": Array [],
48353
48314
  "swapHistory": Array [],
48354
- "syncHash": "[\\"ethereum/erc20/ampleforth\\",\\"ethereum/erc20/steth\\"]_0",
48315
+ "syncHash": "[\\"ethereum/erc20/ampleforth\\",\\"ethereum/erc20/steth\\"]_false_0",
48355
48316
  "unitMagnitude": 18,
48356
48317
  "used": true,
48357
48318
  },
@@ -48378,7 +48339,7 @@ Array [
48378
48339
  "starred": false,
48379
48340
  "subAccounts": Array [],
48380
48341
  "swapHistory": Array [],
48381
- "syncHash": "[\\"ethereum/erc20/ampleforth\\",\\"ethereum/erc20/steth\\"]_0",
48342
+ "syncHash": "[\\"ethereum/erc20/ampleforth\\",\\"ethereum/erc20/steth\\"]_false_0",
48382
48343
  "unitMagnitude": 18,
48383
48344
  "used": true,
48384
48345
  },
@@ -21,6 +21,7 @@ setSupportedCurrencies([
21
21
  "bitcoin",
22
22
  "ethereum",
23
23
  "bsc",
24
+ "polygon",
24
25
  "elrond",
25
26
  "ripple",
26
27
  "bitcoin_cash",
@@ -74,7 +74,7 @@ export function groupAddAccounts(
74
74
  );
75
75
 
76
76
  if (existingAccount) {
77
- if (!acc.used) {
77
+ if (!acc.used && !alreadyEmptyAccount) {
78
78
  alreadyEmptyAccount = existingAccount;
79
79
  }
80
80
 
@@ -122,7 +122,8 @@ export function groupAddAccounts(
122
122
  ? creatableAccounts.filter(
123
123
  (a) =>
124
124
  context.preferredNewAccountSchemes &&
125
- context.preferredNewAccountSchemes.includes(a.derivationMode)
125
+ // Note: we could use a simple preferredNewAccountScheme param
126
+ a.derivationMode === context.preferredNewAccountSchemes[0]
126
127
  )
127
128
  : creatableAccounts,
128
129
  });
@@ -150,6 +150,7 @@ export function clearAccount<T extends AccountLike>(account: T): T {
150
150
  copy.bitcoinResources = initialBitcoinResourcesValue;
151
151
  }
152
152
  delete copy.balanceHistory;
153
+ delete copy.nfts;
153
154
  return copy as T;
154
155
  }
155
156
  export function findSubAccountById(
@@ -10,6 +10,7 @@ import { blockchainBaseURL } from "./Ledger";
10
10
  import { FeeEstimationFailed } from "../errors";
11
11
  import { makeLRUCache } from "../cache";
12
12
  import { getEnv } from "../env";
13
+ import { isNFTActive } from "../nft/support";
13
14
 
14
15
  export type Block = {
15
16
  height: BigNumber;
@@ -132,10 +133,9 @@ export const apiForCurrency = (currency: CryptoCurrency): API => {
132
133
  let { data } = await network({
133
134
  method: "GET",
134
135
  url: URL.format({
135
- pathname:
136
- getEnv("NFT") && currency.ticker === "ETH"
137
- ? `https://explorers.api-01.live.ledger-stg.com/blockchain/v3/eth/addresses/${address}/transactions`
138
- : `${baseURL}/addresses/${address}/transactions`,
136
+ pathname: isNFTActive(currency)
137
+ ? `https://explorers.api-01.live.ledger-stg.com/blockchain/v3/eth/addresses/${address}/transactions`
138
+ : `${baseURL}/addresses/${address}/transactions`,
139
139
  query: {
140
140
  batch_size,
141
141
  noinput: true,
@@ -63,10 +63,6 @@ const initialExplorerConfig: FullConfig = {
63
63
  dogecoin: {
64
64
  id: "doge",
65
65
  stable: {
66
- base: "EXPLORER",
67
- version: "v2",
68
- },
69
- experimental: {
70
66
  base: "EXPLORER",
71
67
  version: "v3",
72
68
  },
@@ -134,21 +134,22 @@ export const mergeNfts = (
134
134
  const nfts = oldNfts?.slice() ?? [];
135
135
  for (let i = 0; i < nfts.length; i++) {
136
136
  const nft = nfts[i];
137
+
137
138
  // The NFTs are the same, do don't anything
138
- if (!newNftsPerId[nft.id] || isEqual(nft, newNftsPerId[nft.id])) {
139
- // NFT already in, deleting it from the newNfts to keep only the un-added ones at the end
140
- delete newNftsPerId[nft.id];
141
- continue;
139
+ if (!newNftsPerId[nft.id]) {
140
+ nfts.splice(i, 1);
141
+ i--;
142
+ } else if (!isEqual(nft, newNftsPerId[nft.id])) {
143
+ // Use the new NFT instead (as a copy cause we're deleting the reference just after)
144
+ nfts[i] = Object.assign({}, newNftsPerId[nft.id]);
142
145
  }
143
146
 
144
- // Use the new NFT instead (as a copy cause we're deleting the reference just after)
145
- nfts[i] = Object.assign({}, newNftsPerId[nft.id]);
146
147
  // Delete it from the newNfts to keep only the un-added ones at the end
147
148
  delete newNftsPerId[nft.id];
148
149
  }
149
150
 
150
- // Adding the rest of newNfts that was not already in oldNfts
151
- return nfts.concat(Object.values(newNftsPerId));
151
+ // Prepending newNfts to respect nfts's newest to oldest order
152
+ return Object.values(newNftsPerId).concat(nfts);
152
153
  };
153
154
 
154
155
  export const makeSync =
package/src/env.ts CHANGED
@@ -381,6 +381,11 @@ const envDefinitions = {
381
381
  parser: boolParser,
382
382
  desc: "synchronizing nfts",
383
383
  },
384
+ NFT_CURRENCIES: {
385
+ def: "ethereum",
386
+ parser: stringParser,
387
+ desc: "set the currencies where NFT is active",
388
+ },
384
389
  NFT_ETH_METADATA_SERVICE: {
385
390
  // FIXME LL-8001
386
391
  def: "https://nft.staging.aws.ledger.fr/v1/ethereum/1/contracts/tokens/infos",
@@ -20,6 +20,7 @@ export async function getAccountNetworkInfo(
20
20
  ): Promise<NetworkInfo> {
21
21
  const walletAccount = getWalletAccount(account);
22
22
  const rawFees = await walletAccount.xpub.explorer.getFees();
23
+ const relayFee = await walletAccount.xpub.explorer.getRelayFee();
23
24
  // Convoluted logic to convert from:
24
25
  // { "2": 2435, "3": 1241, "6": 1009, "last_updated": 1627973170 }
25
26
  // to:
@@ -44,7 +45,12 @@ export async function getAccountNetworkInfo(
44
45
  if (feesPerByte.length !== 3) {
45
46
  throw new Error("cardinality of feesPerByte should be exactly 3");
46
47
  }
47
-
48
+ // Fix fees if suggested fee is too low
49
+ if (feesPerByte[2].toNumber() < Math.ceil(relayFee * 100000)) {
50
+ feesPerByte[2] = new BigNumber(Math.ceil(relayFee * 100000)).plus(1);
51
+ feesPerByte[1] = feesPerByte[2].plus(1);
52
+ feesPerByte[0] = feesPerByte[1].plus(1);
53
+ }
48
54
  const feeItems = {
49
55
  items: feesPerByte.map((feePerByte, i) => ({
50
56
  key: String(i),
@@ -53,6 +59,7 @@ export async function getAccountNetworkInfo(
53
59
  })),
54
60
  defaultFeePerByte:
55
61
  feesPerByte[Math.floor(feesPerByte.length / 2)] || new BigNumber(0),
62
+ relayFee,
56
63
  };
57
64
  return {
58
65
  family: "bitcoin",
@@ -1,6 +1,6 @@
1
1
  import type { DatasetTest } from "../../types";
2
2
  import type { Transaction } from "./types";
3
- import bitcoin_cash from "./datasets/bitcoin_cash";
3
+ // import bitcoin_cash from "./datasets/bitcoin_cash";
4
4
  // import bitcoin_gold from "./datasets/bitcoin_gold";
5
5
  import bitcoin from "./datasets/bitcoin";
6
6
  import dash from "./datasets/dash";
@@ -21,7 +21,7 @@ const dataset: DatasetTest<Transaction> = {
21
21
  implementations: ["js", "libcore", "mock"],
22
22
  currencies: {
23
23
  bitcoin,
24
- bitcoin_cash,
24
+ // bitcoin_cash,
25
25
  // bitcoin_gold,
26
26
  dash,
27
27
  // decred, // BACK-2443
@@ -106,6 +106,7 @@ export type FeeItem = {
106
106
  export type FeeItems = {
107
107
  items: FeeItem[];
108
108
  defaultFeePerByte: BigNumber;
109
+ relayFee?: number;
109
110
  };
110
111
  export type FeeItemRaw = {
111
112
  key: string;
@@ -168,6 +168,13 @@ class BitcoinLikeExplorer extends EventEmitter implements IExplorer {
168
168
  return fees;
169
169
  }
170
170
 
171
+ async getRelayFee() {
172
+ const client = await this.client.acquire();
173
+ const fees = (await client.client.get(`/network`)).data;
174
+ await this.client.release(client);
175
+ return parseFloat(fees["relay_fee"]);
176
+ }
177
+
171
178
  async getPendings(address: Address, nbMax?: number) {
172
179
  const params: {
173
180
  no_token?: string;
@@ -9,6 +9,7 @@ export interface IExplorer {
9
9
  getTxHex(txId: string): Promise<string>;
10
10
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
11
11
  getFees(): Promise<any>;
12
+ getRelayFee(): Promise<number>;
12
13
  getCurrentBlock(): Promise<Block | null>;
13
14
  getBlockByHeight(height: number): Promise<Block | null>;
14
15
  getPendings(address: Address, nbMax?: number): Promise<TX[]>;
@@ -24,11 +24,16 @@ import {
24
24
  estimateGasLimit,
25
25
  } from "../transaction";
26
26
  import { getAccountShape } from "../synchronisation";
27
- import { preload, hydrate } from "../modules";
27
+ import {
28
+ preload,
29
+ hydrate,
30
+ prepareTransaction as prepareTransactionModules,
31
+ } from "../modules";
28
32
  import { signOperation } from "../signOperation";
29
33
  import { modes } from "../modules";
30
34
  import postSyncPatch from "../postSyncPatch";
31
35
  import { inferDynamicRange } from "../../../range";
36
+
32
37
  const receive = makeAccountBridgeReceive();
33
38
 
34
39
  const broadcast = async ({
@@ -173,6 +178,8 @@ const prepareTransaction = async (a, t: Transaction): Promise<Transaction> => {
173
178
  t.estimatedGasLimit = estimatedGasLimit;
174
179
  }
175
180
 
181
+ t = await prepareTransactionModules(a, t);
182
+
176
183
  return t;
177
184
  };
178
185
 
@@ -23,6 +23,16 @@ const options = [
23
23
  desc: "use an token account children of the account",
24
24
  multiple: true,
25
25
  },
26
+ {
27
+ name: "collection",
28
+ type: String,
29
+ desc: "determine the collection of an NFT (related to the --tokenId)",
30
+ },
31
+ {
32
+ name: "tokenId",
33
+ type: String,
34
+ desc: "determine the tokenId of an NFT (related to the --colection)",
35
+ },
26
36
  {
27
37
  name: "gasPrice",
28
38
  type: String,
@@ -0,0 +1,157 @@
1
+ import eip55 from "eip55";
2
+ import abi from "ethereumjs-abi";
3
+ import invariant from "invariant";
4
+ import BigNumber from "bignumber.js";
5
+ import {
6
+ createCustomErrorClass,
7
+ NotEnoughBalanceInParentAccount,
8
+ } from "@ledgerhq/errors";
9
+ import { validateRecipient } from "../transaction";
10
+ import type { ModeModule, Transaction } from "../types";
11
+ import type { Account } from "../../../types";
12
+ import { prepareTransaction } from "./erc721";
13
+
14
+ const notOwnedNft = createCustomErrorClass("NotOwnedNft");
15
+ const notEnoughNftOwned = createCustomErrorClass("NotEnoughNftOwned");
16
+ const notTokenIdsProvided = createCustomErrorClass("NotTokenIdsProvided");
17
+
18
+ export type Modes = "erc1155.transfer";
19
+
20
+ const erc1155Transfer: ModeModule = {
21
+ /**
22
+ * Tx data is filled during the buildEthereumTx
23
+ */
24
+ fillTransactionData(a, t, tx) {
25
+ const data = serializeTransactionData(a, t);
26
+ invariant(data, "serializeTransactionData provided no data");
27
+ tx.data = "0x" + (data as Buffer).toString("hex");
28
+ tx.to = t.collection;
29
+ tx.value = "0x00";
30
+ },
31
+
32
+ /**
33
+ * Tx status is filled after the buildEthereumTx
34
+ */
35
+ fillTransactionStatus: (a, t, result) => {
36
+ validateRecipient(a.currency, t.recipient, result);
37
+
38
+ if (!result.errors.recipient) {
39
+ result.totalSpent = result.estimatedFees;
40
+ result.amount = new BigNumber(t.amount);
41
+
42
+ if (result.estimatedFees.gt(a.spendableBalance)) {
43
+ result.errors.amount = new NotEnoughBalanceInParentAccount();
44
+ }
45
+
46
+ const enoughTokensOwned: true | Error =
47
+ t.tokenIds?.reduce((acc, tokenId, index) => {
48
+ if (acc instanceof Error) {
49
+ return acc;
50
+ }
51
+
52
+ const nft = a.nfts?.find((n) => n.tokenId === tokenId);
53
+ const transferQuantity = Number(t.quantities?.[index]);
54
+
55
+ if (!nft) {
56
+ return new notOwnedNft();
57
+ }
58
+
59
+ if (transferQuantity && !nft.amount.gte(transferQuantity)) {
60
+ return new notEnoughNftOwned();
61
+ }
62
+
63
+ return true;
64
+ }, true as true | Error) || new notTokenIdsProvided();
65
+
66
+ if (!enoughTokensOwned || enoughTokensOwned instanceof Error) {
67
+ result.errors.amount = enoughTokensOwned;
68
+ }
69
+ }
70
+ },
71
+
72
+ /**
73
+ * This will only be used by LLM & LLD, not the HW.
74
+ */
75
+ fillDeviceTransactionConfig(input, fields) {
76
+ fields.push({
77
+ type: "text",
78
+ label: "Type",
79
+ value: `NFT Transfer`,
80
+ });
81
+
82
+ fields.push({
83
+ type: "text",
84
+ label: "To",
85
+ value: input.transaction.recipient ?? "",
86
+ });
87
+
88
+ fields.push({
89
+ type: "text",
90
+ label: "Collection Name",
91
+ value: input.transaction.collectionName || "",
92
+ });
93
+
94
+ fields.push({
95
+ type: "text",
96
+ label: "Quantity",
97
+ value: input.transaction.quantities?.[0]?.toFixed() ?? "",
98
+ });
99
+
100
+ fields.push({
101
+ type: "address",
102
+ label: "NFT Address",
103
+ address: input.transaction.collection ?? "",
104
+ });
105
+
106
+ fields.push({
107
+ type: "text",
108
+ label: "NFT ID",
109
+ value: input.transaction.tokenIds?.[0] ?? "",
110
+ });
111
+ },
112
+
113
+ /**
114
+ * Optimistic Operation is filled post signing
115
+ */
116
+ fillOptimisticOperation(a, t, op) {
117
+ op.type = "FEES";
118
+ op.extra = {
119
+ ...op.extra,
120
+ approving: true, // workaround to track the status ENABLING
121
+ };
122
+ },
123
+
124
+ prepareTransaction,
125
+ };
126
+
127
+ function serializeTransactionData(
128
+ account: Account,
129
+ transaction: Transaction
130
+ ): Buffer | null | undefined {
131
+ const from = eip55.encode(account.freshAddress);
132
+ const to = eip55.encode(transaction.recipient);
133
+ const tokenIds = transaction.tokenIds || [];
134
+ const quantities = transaction.quantities?.map((q) => q.toFixed()) || [];
135
+
136
+ return tokenIds?.length > 1
137
+ ? abi.simpleEncode(
138
+ "safeBatchTransferFrom(address,address,uint256[],uint256[],bytes)",
139
+ from,
140
+ to,
141
+ tokenIds,
142
+ quantities,
143
+ "0x00"
144
+ )
145
+ : abi.simpleEncode(
146
+ "safeTransferFrom(address,address,uint256,uint256,bytes)",
147
+ from,
148
+ to,
149
+ tokenIds[0],
150
+ quantities[0],
151
+ "0x00"
152
+ );
153
+ }
154
+
155
+ export const modes: Record<Modes, ModeModule> = {
156
+ "erc1155.transfer": erc1155Transfer,
157
+ };