@ledgerhq/hw-app-eth 6.22.0 → 6.22.4

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 (76) hide show
  1. package/.turbo/turbo-build.log +2 -0
  2. package/README.md +15 -0
  3. package/lib/Eth.d.ts +16 -0
  4. package/lib/Eth.d.ts.map +1 -1
  5. package/lib/Eth.js +11 -21
  6. package/lib/Eth.js.map +1 -1
  7. package/lib/errors.d.ts +7 -0
  8. package/lib/errors.d.ts.map +1 -0
  9. package/lib/errors.js +7 -0
  10. package/lib/errors.js.map +1 -0
  11. package/lib/services/ledger/index.d.ts.map +1 -1
  12. package/lib/services/ledger/index.js +88 -53
  13. package/lib/services/ledger/index.js.map +1 -1
  14. package/lib/services/ledger/nfts.d.ts.map +1 -1
  15. package/lib/services/ledger/nfts.js +24 -9
  16. package/lib/services/ledger/nfts.js.map +1 -1
  17. package/lib/services/types.d.ts +10 -1
  18. package/lib/services/types.d.ts.map +1 -1
  19. package/lib-es/Eth.d.ts +16 -0
  20. package/lib-es/Eth.d.ts.map +1 -1
  21. package/lib-es/Eth.js +11 -21
  22. package/lib-es/Eth.js.map +1 -1
  23. package/lib-es/contracts.d.ts +5 -2
  24. package/lib-es/contracts.d.ts.map +1 -1
  25. package/lib-es/contracts.js +26 -19
  26. package/lib-es/contracts.js.map +1 -1
  27. package/lib-es/erc20.d.ts +0 -0
  28. package/lib-es/erc20.d.ts.map +0 -0
  29. package/lib-es/erc20.js +0 -0
  30. package/lib-es/erc20.js.map +0 -0
  31. package/lib-es/errors.d.ts +7 -0
  32. package/lib-es/errors.d.ts.map +1 -0
  33. package/lib-es/errors.js +4 -0
  34. package/lib-es/errors.js.map +1 -0
  35. package/lib-es/services/ledger/contracts.d.ts +0 -0
  36. package/lib-es/services/ledger/contracts.d.ts.map +0 -0
  37. package/lib-es/services/ledger/contracts.js +0 -0
  38. package/lib-es/services/ledger/contracts.js.map +0 -0
  39. package/lib-es/services/ledger/erc20.d.ts +0 -0
  40. package/lib-es/services/ledger/erc20.d.ts.map +0 -0
  41. package/lib-es/services/ledger/erc20.js +0 -0
  42. package/lib-es/services/ledger/erc20.js.map +0 -0
  43. package/lib-es/services/ledger/index.d.ts +0 -0
  44. package/lib-es/services/ledger/index.d.ts.map +1 -1
  45. package/lib-es/services/ledger/index.js +88 -53
  46. package/lib-es/services/ledger/index.js.map +1 -1
  47. package/lib-es/services/ledger/loadConfig.d.ts +0 -0
  48. package/lib-es/services/ledger/loadConfig.d.ts.map +0 -0
  49. package/lib-es/services/ledger/loadConfig.js +0 -0
  50. package/lib-es/services/ledger/loadConfig.js.map +0 -0
  51. package/lib-es/services/ledger/nfts.d.ts +0 -0
  52. package/lib-es/services/ledger/nfts.d.ts.map +1 -1
  53. package/lib-es/services/ledger/nfts.js +24 -9
  54. package/lib-es/services/ledger/nfts.js.map +1 -1
  55. package/lib-es/services/types.d.ts +10 -1
  56. package/lib-es/services/types.d.ts.map +1 -1
  57. package/lib-es/services/types.js +0 -0
  58. package/lib-es/services/types.js.map +0 -0
  59. package/lib-es/utils.d.ts +0 -0
  60. package/lib-es/utils.d.ts.map +0 -0
  61. package/lib-es/utils.js +0 -0
  62. package/lib-es/utils.js.map +0 -0
  63. package/package.json +3 -3
  64. package/src/Eth.ts +17 -5
  65. package/src/errors.ts +8 -0
  66. package/src/services/ledger/index.ts +22 -16
  67. package/src/services/ledger/nfts.ts +26 -5
  68. package/src/services/types.ts +15 -1
  69. package/lib-es/loadConfig.d.ts +0 -7
  70. package/lib-es/loadConfig.d.ts.map +0 -1
  71. package/lib-es/loadConfig.js +0 -20
  72. package/lib-es/loadConfig.js.map +0 -1
  73. package/lib-es/nfts.d.ts +0 -11
  74. package/lib-es/nfts.d.ts.map +0 -1
  75. package/lib-es/nfts.js +0 -94
  76. package/lib-es/nfts.js.map +0 -1
@@ -36,26 +36,39 @@ var __generator = (this && this.__generator) || function (thisArg, body) {
36
36
  };
37
37
  import axios from "axios";
38
38
  import { getLoadConfig } from "./loadConfig";
39
+ function axiosErrorHandling(e) {
40
+ if (!e || !e.status)
41
+ throw e;
42
+ if (e.status === 404)
43
+ return null;
44
+ throw e;
45
+ }
39
46
  export var getNFTInfo = function (contractAddress, chainId, userLoadConfig) { return __awaiter(void 0, void 0, void 0, function () {
40
- var nftExplorerBaseURL, url, response, payload, collectionNameLength, collectionName;
41
- return __generator(this, function (_a) {
42
- switch (_a.label) {
47
+ var nftExplorerBaseURL, url, response, payload, collectionNameLength, collectionNameHex, collectionName;
48
+ var _a;
49
+ return __generator(this, function (_b) {
50
+ switch (_b.label) {
43
51
  case 0:
44
52
  nftExplorerBaseURL = getLoadConfig(userLoadConfig).nftExplorerBaseURL;
45
53
  if (!nftExplorerBaseURL)
46
54
  return [2 /*return*/];
47
55
  url = "".concat(nftExplorerBaseURL, "/").concat(chainId, "/contracts/").concat(contractAddress);
48
- return [4 /*yield*/, axios.get(url).then(function (r) { return r.data; })];
56
+ return [4 /*yield*/, axios
57
+ .get(url)
58
+ .then(function (r) { return r.data; })["catch"](axiosErrorHandling)];
49
59
  case 1:
50
- response = _a.sent();
60
+ response = _b.sent();
51
61
  if (!response)
52
62
  return [2 /*return*/];
53
63
  payload = response["payload"];
54
- collectionNameLength = Number(payload.slice(2, 3));
55
- collectionName = payload.slice(3, 3 + collectionNameLength).toString();
64
+ collectionNameLength = parseInt(payload.slice(4, 6), 16);
65
+ collectionNameHex = payload.substr(6, collectionNameLength * 2);
66
+ collectionName = (_a = collectionNameHex
67
+ .match(/.{2}/g) // split every 2 characters
68
+ ) === null || _a === void 0 ? void 0 : _a.reduce(function (acc, curr) { return (acc += String.fromCharCode(parseInt(curr, 16))); }, "");
56
69
  return [2 /*return*/, {
57
70
  contractAddress: contractAddress,
58
- collectionName: collectionName,
71
+ collectionName: collectionName || "",
59
72
  data: payload
60
73
  }];
61
74
  }
@@ -70,7 +83,9 @@ export var loadNftPlugin = function (contractAddress, selector, chainId, userLoa
70
83
  if (!nftExplorerBaseURL)
71
84
  return [2 /*return*/];
72
85
  url = "".concat(nftExplorerBaseURL, "/").concat(chainId, "/contracts/").concat(contractAddress, "/plugin-selector/").concat(selector);
73
- return [4 /*yield*/, axios.get(url).then(function (r) { return r.data; })];
86
+ return [4 /*yield*/, axios
87
+ .get(url)
88
+ .then(function (r) { return r.data; })["catch"](axiosErrorHandling)];
74
89
  case 1:
75
90
  response = _a.sent();
76
91
  if (!response)
@@ -1 +1 @@
1
- {"version":3,"file":"nfts.js","sourceRoot":"","sources":["../../../src/services/ledger/nfts.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAa7C,MAAM,CAAC,IAAM,UAAU,GAAG,UACxB,eAAuB,EACvB,OAAe,EACf,cAA0B;;;;;gBAElB,kBAAkB,GAAK,aAAa,CAAC,cAAc,CAAC,mBAAlC,CAAmC;gBAC7D,IAAI,CAAC,kBAAkB;oBAAE,sBAAO;gBAC1B,GAAG,GAAG,UAAG,kBAAkB,cAAI,OAAO,wBAAc,eAAe,CAAE,CAAC;gBAC3D,qBAAM,KAAK,CAAC,GAAG,CAAkB,GAAG,CAAC,CAAC,IAAI,CAAC,UAAC,CAAC,IAAK,OAAA,CAAC,CAAC,IAAI,EAAN,CAAM,CAAC,EAAA;;gBAApE,QAAQ,GAAG,SAAyD;gBAC1E,IAAI,CAAC,QAAQ;oBAAE,sBAAO;gBAEhB,OAAO,GAAG,QAAQ,CAAC,SAAS,CAAC,CAAC;gBAC9B,oBAAoB,GAAG,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;gBACnD,cAAc,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,GAAG,oBAAoB,CAAC,CAAC,QAAQ,EAAE,CAAC;gBAC7E,sBAAO;wBACL,eAAe,EAAE,eAAe;wBAChC,cAAc,EAAE,cAAc;wBAC9B,IAAI,EAAE,OAAO;qBACd,EAAC;;;KACH,CAAC;AAEF,MAAM,CAAC,IAAM,aAAa,GAAG,UAC3B,eAAuB,EACvB,QAAgB,EAChB,OAAe,EACf,cAA0B;;;;;gBAElB,kBAAkB,GAAK,aAAa,CAAC,cAAc,CAAC,mBAAlC,CAAmC;gBAC7D,IAAI,CAAC,kBAAkB;oBAAE,sBAAO;gBAC1B,GAAG,GAAG,UAAG,kBAAkB,cAAI,OAAO,wBAAc,eAAe,8BAAoB,QAAQ,CAAE,CAAC;gBAEvF,qBAAM,KAAK,CAAC,GAAG,CAAkB,GAAG,CAAC,CAAC,IAAI,CAAC,UAAC,CAAC,IAAK,OAAA,CAAC,CAAC,IAAI,EAAN,CAAM,CAAC,EAAA;;gBAApE,QAAQ,GAAG,SAAyD;gBAC1E,IAAI,CAAC,QAAQ;oBAAE,sBAAO;gBAEhB,OAAO,GAAG,QAAQ,CAAC,SAAS,CAAC,CAAC;gBACpC,sBAAO,OAAO,EAAC;;;KAChB,CAAC"}
1
+ {"version":3,"file":"nfts.js","sourceRoot":"","sources":["../../../src/services/ledger/nfts.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAa7C,SAAS,kBAAkB,CAAC,CAAC;IAC3B,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM;QAAE,MAAM,CAAC,CAAC;IAC7B,IAAI,CAAC,CAAC,MAAM,KAAK,GAAG;QAAE,OAAO,IAAI,CAAC;IAClC,MAAM,CAAC,CAAC;AACV,CAAC;AAED,MAAM,CAAC,IAAM,UAAU,GAAG,UACxB,eAAuB,EACvB,OAAe,EACf,cAA0B;;;;;;gBAElB,kBAAkB,GAAK,aAAa,CAAC,cAAc,CAAC,mBAAlC,CAAmC;gBAC7D,IAAI,CAAC,kBAAkB;oBAAE,sBAAO;gBAC1B,GAAG,GAAG,UAAG,kBAAkB,cAAI,OAAO,wBAAc,eAAe,CAAE,CAAC;gBAC3D,qBAAM,KAAK;yBACzB,GAAG,CAAkB,GAAG,CAAC;yBACzB,IAAI,CAAC,UAAC,CAAC,IAAK,OAAA,CAAC,CAAC,IAAI,EAAN,CAAM,CAAC,CACnB,OAAK,CAAA,CAAC,kBAAkB,CAAC,EAAA;;gBAHtB,QAAQ,GAAG,SAGW;gBAC5B,IAAI,CAAC,QAAQ;oBAAE,sBAAO;gBAGhB,OAAO,GAAG,QAAQ,CAAC,SAAS,CAAC,CAAC;gBAE9B,oBAAoB,GAAG,QAAQ,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;gBACzD,iBAAiB,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,EAAE,oBAAoB,GAAG,CAAC,CAAC,CAAC;gBAChE,cAAc,GAAG,MAAA,iBAAiB;qBACrC,KAAK,CAAC,OAAO,CAAC,CAAC,2BAA2B;0DACzC,MAAM,CACN,UAAC,GAAG,EAAE,IAAI,IAAK,OAAA,CAAC,GAAG,IAAI,MAAM,CAAC,YAAY,CAAC,QAAQ,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,CAAC,EAAhD,CAAgD,EAC/D,EAAE,CACH,CAAC;gBAEJ,sBAAO;wBACL,eAAe,EAAE,eAAe;wBAChC,cAAc,EAAE,cAAc,IAAI,EAAE;wBACpC,IAAI,EAAE,OAAO;qBACd,EAAC;;;KACH,CAAC;AAEF,MAAM,CAAC,IAAM,aAAa,GAAG,UAC3B,eAAuB,EACvB,QAAgB,EAChB,OAAe,EACf,cAA0B;;;;;gBAElB,kBAAkB,GAAK,aAAa,CAAC,cAAc,CAAC,mBAAlC,CAAmC;gBAC7D,IAAI,CAAC,kBAAkB;oBAAE,sBAAO;gBAC1B,GAAG,GAAG,UAAG,kBAAkB,cAAI,OAAO,wBAAc,eAAe,8BAAoB,QAAQ,CAAE,CAAC;gBAEvF,qBAAM,KAAK;yBACzB,GAAG,CAAkB,GAAG,CAAC;yBACzB,IAAI,CAAC,UAAC,CAAC,IAAK,OAAA,CAAC,CAAC,IAAI,EAAN,CAAM,CAAC,CACnB,OAAK,CAAA,CAAC,kBAAkB,CAAC,EAAA;;gBAHtB,QAAQ,GAAG,SAGW;gBAC5B,IAAI,CAAC,QAAQ;oBAAE,sBAAO;gBAEhB,OAAO,GAAG,QAAQ,CAAC,SAAS,CAAC,CAAC;gBACpC,sBAAO,OAAO,EAAC;;;KAChB,CAAC"}
@@ -12,7 +12,16 @@ export declare type LoadConfig = {
12
12
  pluginBaseURL?: string | null;
13
13
  extraPlugins?: any | null;
14
14
  };
15
+ /**
16
+ * Allows to configure precisely what the service need to resolve.
17
+ * for instance you can set nft:true if you need clear signing on NFTs. If you set it and it is not a NFT transaction, it should still work but will do a useless service resolution.
18
+ */
19
+ export declare type ResolutionConfig = {
20
+ nft?: boolean;
21
+ externalPlugins?: boolean;
22
+ erc20?: boolean;
23
+ };
15
24
  export declare type LedgerEthTransactionService = {
16
- resolveTransaction: (rawTxHex: string, loadConfig: LoadConfig) => Promise<LedgerEthTransactionResolution>;
25
+ resolveTransaction: (rawTxHex: string, loadConfig: LoadConfig, resolutionConfig: ResolutionConfig) => Promise<LedgerEthTransactionResolution>;
17
26
  };
18
27
  //# sourceMappingURL=types.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/services/types.ts"],"names":[],"mappings":"AAAA,oBAAY,8BAA8B,GAAG;IAE3C,WAAW,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC;IAE3B,IAAI,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC;IAEpB,cAAc,EAAE,KAAK,CAAC;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAE9D,MAAM,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC;CACvB,CAAC;AAEF,oBAAY,UAAU,GAAG;IACvB,kBAAkB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAInC,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAG9B,YAAY,CAAC,EAAE,GAAG,GAAG,IAAI,CAAC;CAC3B,CAAC;AAEF,oBAAY,2BAA2B,GAAG;IACxC,kBAAkB,EAAE,CAClB,QAAQ,EAAE,MAAM,EAChB,UAAU,EAAE,UAAU,KACnB,OAAO,CAAC,8BAA8B,CAAC,CAAC;CAC9C,CAAC"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/services/types.ts"],"names":[],"mappings":"AAAA,oBAAY,8BAA8B,GAAG;IAE3C,WAAW,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC;IAE3B,IAAI,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC;IAEpB,cAAc,EAAE,KAAK,CAAC;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAE9D,MAAM,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC;CACvB,CAAC;AAEF,oBAAY,UAAU,GAAG;IACvB,kBAAkB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAInC,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAG9B,YAAY,CAAC,EAAE,GAAG,GAAG,IAAI,CAAC;CAC3B,CAAC;AAEF;;;GAGG;AACH,oBAAY,gBAAgB,GAAG;IAE7B,GAAG,CAAC,EAAE,OAAO,CAAC;IAEd,eAAe,CAAC,EAAE,OAAO,CAAC;IAE1B,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB,CAAC;AAEF,oBAAY,2BAA2B,GAAG;IACxC,kBAAkB,EAAE,CAClB,QAAQ,EAAE,MAAM,EAChB,UAAU,EAAE,UAAU,EACtB,gBAAgB,EAAE,gBAAgB,KAC/B,OAAO,CAAC,8BAA8B,CAAC,CAAC;CAC9C,CAAC"}
File without changes
File without changes
package/lib-es/utils.d.ts CHANGED
File without changes
File without changes
package/lib-es/utils.js CHANGED
File without changes
File without changes
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ledgerhq/hw-app-eth",
3
- "version": "6.22.0",
3
+ "version": "6.22.4",
4
4
  "description": "Ledger Hardware Wallet Ethereum Application API",
5
5
  "keywords": [
6
6
  "Ledger",
@@ -27,7 +27,7 @@
27
27
  "types": "lib/Eth.d.ts",
28
28
  "license": "Apache-2.0",
29
29
  "dependencies": {
30
- "@ledgerhq/cryptoassets": "^6.22.0",
30
+ "@ledgerhq/cryptoassets": "^6.22.4",
31
31
  "@ledgerhq/errors": "^6.10.0",
32
32
  "@ledgerhq/hw-transport": "^6.20.0",
33
33
  "@ledgerhq/logs": "^6.10.0",
@@ -41,5 +41,5 @@
41
41
  "watch": "bash ../../script/watch.sh",
42
42
  "doc": "bash ../../script/doc.sh"
43
43
  },
44
- "gitHead": "df473b65fc3a869bc4cbb65de5b057272366f2da"
44
+ "gitHead": "6b78677ef262faef3833a49e8c122a42c76b682e"
45
45
  }
package/src/Eth.ts CHANGED
@@ -15,13 +15,16 @@
15
15
  * limitations under the License.
16
16
  ********************************************************************************/
17
17
  // FIXME drop:
18
- import { EthAppPleaseEnableContractData } from "@ledgerhq/errors";
19
18
  import type Transport from "@ledgerhq/hw-transport";
20
19
  import { BigNumber } from "bignumber.js";
21
20
  import { decodeTxInfo } from "./utils";
22
21
  // NB: these are temporary import for the deprecated fallback mechanism
23
22
  import { LedgerEthTransactionResolution, LoadConfig } from "./services/types";
24
23
  import ledgerService from "./services/ledger";
24
+ import {
25
+ EthAppNftNotSupported,
26
+ EthAppPleaseEnableContractData,
27
+ } from "./errors";
25
28
 
26
29
  export type StarkQuantizationType =
27
30
  | "eth"
@@ -213,8 +216,17 @@ export default class Eth {
213
216
  " + const resolution = await ledgerService.resolveTransaction(rawTxHex);"
214
217
  );
215
218
  resolution = await ledgerService
216
- .resolveTransaction(rawTxHex, this.loadConfig)
217
- .catch(() => null);
219
+ .resolveTransaction(rawTxHex, this.loadConfig, {
220
+ externalPlugins: true,
221
+ erc20: true,
222
+ })
223
+ .catch((e) => {
224
+ console.warn(
225
+ "an error occurred in resolveTransaction => fallback to blind signing: " +
226
+ String(e)
227
+ );
228
+ return null;
229
+ });
218
230
  }
219
231
 
220
232
  // provide to the device resolved information to make it clear sign the signature
@@ -1178,8 +1190,8 @@ function provideNFTInformation(
1178
1190
  return false;
1179
1191
  }
1180
1192
  if (e && e.statusCode === 0x6d00) {
1181
- // ignore older version of ETH app
1182
- return false;
1193
+ // older version of ETH app => error because we don't allow blind sign when NFT is explicitly requested to be resolved.
1194
+ throw new EthAppNftNotSupported();
1183
1195
  }
1184
1196
  throw e;
1185
1197
  }
package/src/errors.ts ADDED
@@ -0,0 +1,8 @@
1
+ import { createCustomErrorClass } from "@ledgerhq/errors";
2
+
3
+ export const EthAppPleaseEnableContractData = createCustomErrorClass(
4
+ "EthAppPleaseEnableContractData"
5
+ );
6
+ export const EthAppNftNotSupported = createCustomErrorClass(
7
+ "EthAppNftNotSupported"
8
+ );
@@ -12,7 +12,7 @@ import { getNFTInfo, loadNftPlugin } from "./nfts";
12
12
  import { decodeTxInfo } from "../../utils";
13
13
 
14
14
  const ledgerService: LedgerEthTransactionService = {
15
- resolveTransaction: async (rawTxHex, loadConfig) => {
15
+ resolveTransaction: async (rawTxHex, loadConfig, resolutionConfig) => {
16
16
  const resolution: LedgerEthTransactionResolution = {
17
17
  erc20Tokens: [],
18
18
  nfts: [],
@@ -36,7 +36,9 @@ const ledgerService: LedgerEthTransactionService = {
36
36
  const rawTx = Buffer.from(rawTxHex, "hex");
37
37
  const { decodedTx, chainIdTruncated } = decodeTxInfo(rawTx);
38
38
  const provideForContract = async (address) => {
39
- const nftInfo = await getNFTInfo(address, chainIdTruncated, loadConfig);
39
+ const nftInfo = resolutionConfig.nft
40
+ ? await getNFTInfo(address, chainIdTruncated, loadConfig)
41
+ : null;
40
42
  if (nftInfo) {
41
43
  log(
42
44
  "ethereum",
@@ -68,22 +70,26 @@ const ledgerService: LedgerEthTransactionService = {
68
70
 
69
71
  if (decodedTx.data.length >= 10) {
70
72
  const selector = decodedTx.data.substring(0, 10);
71
- const nftPluginPayload = await loadNftPlugin(
72
- decodedTx.to,
73
- selector,
74
- chainIdTruncated,
75
- loadConfig
76
- );
73
+ const nftPluginPayload = resolutionConfig.nft
74
+ ? await loadNftPlugin(
75
+ decodedTx.to,
76
+ selector,
77
+ chainIdTruncated,
78
+ loadConfig
79
+ )
80
+ : null;
77
81
 
78
82
  if (nftPluginPayload) {
79
83
  setPlugin(nftPluginPayload);
80
84
  } else {
81
- const infos = await loadInfosForContractMethod(
82
- decodedTx.to,
83
- selector,
84
- chainIdTruncated,
85
- loadConfig
86
- );
85
+ const infos = resolutionConfig.externalPlugins
86
+ ? await loadInfosForContractMethod(
87
+ decodedTx.to,
88
+ selector,
89
+ chainIdTruncated,
90
+ loadConfig
91
+ )
92
+ : null;
87
93
 
88
94
  if (infos) {
89
95
  const { plugin, payload, signature, erc20OfInterest, abi } = infos;
@@ -102,14 +108,14 @@ const ledgerService: LedgerEthTransactionService = {
102
108
  }
103
109
  return value[seg];
104
110
  }, args);
105
- provideForContract(address);
111
+ await provideForContract(address);
106
112
  }
107
113
  }
108
114
  } else {
109
115
  log("ethereum", "no infos for selector " + selector);
110
116
  }
111
117
  }
112
- provideForContract(decodedTx.to);
118
+ await provideForContract(decodedTx.to);
113
119
  }
114
120
 
115
121
  return resolution;
@@ -12,6 +12,12 @@ type BackendResponse = {
12
12
  payload: string;
13
13
  };
14
14
 
15
+ function axiosErrorHandling(e) {
16
+ if (!e || !e.status) throw e;
17
+ if (e.status === 404) return null;
18
+ throw e;
19
+ }
20
+
15
21
  export const getNFTInfo = async (
16
22
  contractAddress: string,
17
23
  chainId: number,
@@ -20,15 +26,27 @@ export const getNFTInfo = async (
20
26
  const { nftExplorerBaseURL } = getLoadConfig(userLoadConfig);
21
27
  if (!nftExplorerBaseURL) return;
22
28
  const url = `${nftExplorerBaseURL}/${chainId}/contracts/${contractAddress}`;
23
- const response = await axios.get<BackendResponse>(url).then((r) => r.data);
29
+ const response = await axios
30
+ .get<BackendResponse>(url)
31
+ .then((r) => r.data)
32
+ .catch(axiosErrorHandling);
24
33
  if (!response) return;
25
34
 
35
+ // APDU response specification: https://ledgerhq.atlassian.net/wiki/spaces/WALLETCO/pages/3269984297/NFT-1+NFT+Backend+design#NFT-Metadata-BLOB
26
36
  const payload = response["payload"];
27
- const collectionNameLength = Number(payload.slice(2, 3));
28
- const collectionName = payload.slice(3, 3 + collectionNameLength).toString();
37
+ // Collection name length position: 3rd byte -> caracter 4 to 6
38
+ const collectionNameLength = parseInt(payload.slice(4, 6), 16);
39
+ const collectionNameHex = payload.substr(6, collectionNameLength * 2);
40
+ const collectionName = collectionNameHex
41
+ .match(/.{2}/g) // split every 2 characters
42
+ ?.reduce(
43
+ (acc, curr) => (acc += String.fromCharCode(parseInt(curr, 16))),
44
+ ""
45
+ ); // convert hex to string
46
+
29
47
  return {
30
48
  contractAddress: contractAddress,
31
- collectionName: collectionName,
49
+ collectionName: collectionName || "",
32
50
  data: payload,
33
51
  };
34
52
  };
@@ -43,7 +61,10 @@ export const loadNftPlugin = async (
43
61
  if (!nftExplorerBaseURL) return;
44
62
  const url = `${nftExplorerBaseURL}/${chainId}/contracts/${contractAddress}/plugin-selector/${selector}`;
45
63
 
46
- const response = await axios.get<BackendResponse>(url).then((r) => r.data);
64
+ const response = await axios
65
+ .get<BackendResponse>(url)
66
+ .then((r) => r.data)
67
+ .catch(axiosErrorHandling);
47
68
  if (!response) return;
48
69
 
49
70
  const payload = response["payload"];
@@ -20,9 +20,23 @@ export type LoadConfig = {
20
20
  extraPlugins?: any | null;
21
21
  };
22
22
 
23
+ /**
24
+ * Allows to configure precisely what the service need to resolve.
25
+ * for instance you can set nft:true if you need clear signing on NFTs. If you set it and it is not a NFT transaction, it should still work but will do a useless service resolution.
26
+ */
27
+ export type ResolutionConfig = {
28
+ // NFT resolution service
29
+ nft?: boolean;
30
+ // external plugins resolution service (e.G. LIDO)
31
+ externalPlugins?: boolean;
32
+ // ERC20 resolution service (to clear sign erc20 transfers & other actions)
33
+ erc20?: boolean;
34
+ };
35
+
23
36
  export type LedgerEthTransactionService = {
24
37
  resolveTransaction: (
25
38
  rawTxHex: string,
26
- loadConfig: LoadConfig
39
+ loadConfig: LoadConfig,
40
+ resolutionConfig: ResolutionConfig
27
41
  ) => Promise<LedgerEthTransactionResolution>;
28
42
  };
@@ -1,7 +0,0 @@
1
- export declare type LoadConfig = {
2
- nftExplorerBaseURL?: string | null;
3
- pluginBaseURL?: string | null;
4
- extraPlugins?: any | null;
5
- };
6
- export declare function getLoadConfig(userLoadConfig?: LoadConfig): LoadConfig;
7
- //# sourceMappingURL=loadConfig.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"loadConfig.d.ts","sourceRoot":"","sources":["../src/loadConfig.ts"],"names":[],"mappings":"AAAA,oBAAY,UAAU,GAAG;IACvB,kBAAkB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAInC,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAG9B,YAAY,CAAC,EAAE,GAAG,GAAG,IAAI,CAAC;CAC3B,CAAC;AAQF,wBAAgB,aAAa,CAAC,cAAc,CAAC,EAAE,UAAU,GAAG,UAAU,CAKrE"}
@@ -1,20 +0,0 @@
1
- var __assign = (this && this.__assign) || function () {
2
- __assign = Object.assign || function(t) {
3
- for (var s, i = 1, n = arguments.length; i < n; i++) {
4
- s = arguments[i];
5
- for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
6
- t[p] = s[p];
7
- }
8
- return t;
9
- };
10
- return __assign.apply(this, arguments);
11
- };
12
- var defaultLoadConfig = {
13
- nftExplorerBaseURL: null,
14
- pluginBaseURL: "https://cdn.live.ledger.com",
15
- extraPlugins: null
16
- };
17
- export function getLoadConfig(userLoadConfig) {
18
- return __assign(__assign({}, defaultLoadConfig), userLoadConfig);
19
- }
20
- //# sourceMappingURL=loadConfig.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"loadConfig.js","sourceRoot":"","sources":["../src/loadConfig.ts"],"names":[],"mappings":";;;;;;;;;;;AAWA,IAAM,iBAAiB,GAAG;IACxB,kBAAkB,EAAE,IAAI;IACxB,aAAa,EAAE,6BAA6B;IAC5C,YAAY,EAAE,IAAI;CACnB,CAAC;AAEF,MAAM,UAAU,aAAa,CAAC,cAA2B;IACvD,6BACK,iBAAiB,GACjB,cAAc,EACjB;AACJ,CAAC"}
package/lib-es/nfts.d.ts DELETED
@@ -1,11 +0,0 @@
1
- /// <reference types="node" />
2
- import type { LoadConfig } from "./loadConfig";
3
- declare type NftInfo = {
4
- contractAddress: string;
5
- collectionName: string;
6
- data: Buffer;
7
- };
8
- export declare const getNFTInfo: (contractAddress: string, chainId: number, userLoadConfig: LoadConfig) => Promise<NftInfo | undefined>;
9
- export declare const loadNftPlugin: (contractAddress: string, selector: string, chainId: number, userLoadConfig: LoadConfig) => Promise<string | undefined>;
10
- export {};
11
- //# sourceMappingURL=nfts.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"nfts.d.ts","sourceRoot":"","sources":["../src/nfts.ts"],"names":[],"mappings":";AAEA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAG/C,aAAK,OAAO,GAAG;IACb,eAAe,EAAE,MAAM,CAAC;IACxB,cAAc,EAAE,MAAM,CAAC;IACvB,IAAI,EAAE,MAAM,CAAC;CACd,CAAC;AAMF,eAAO,MAAM,UAAU,oBACJ,MAAM,WACd,MAAM,kBACC,UAAU,KACzB,QAAQ,OAAO,GAAG,SAAS,CAqB7B,CAAC;AAEF,eAAO,MAAM,aAAa,oBACP,MAAM,YACb,MAAM,WACP,MAAM,kBACC,UAAU,KACzB,QAAQ,MAAM,GAAG,SAAS,CAgB5B,CAAC"}
package/lib-es/nfts.js DELETED
@@ -1,94 +0,0 @@
1
- var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
2
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
3
- return new (P || (P = Promise))(function (resolve, reject) {
4
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
5
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
6
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
7
- step((generator = generator.apply(thisArg, _arguments || [])).next());
8
- });
9
- };
10
- var __generator = (this && this.__generator) || function (thisArg, body) {
11
- var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
12
- return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
13
- function verb(n) { return function (v) { return step([n, v]); }; }
14
- function step(op) {
15
- if (f) throw new TypeError("Generator is already executing.");
16
- while (_) try {
17
- if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
18
- if (y = 0, t) op = [op[0] & 2, t.value];
19
- switch (op[0]) {
20
- case 0: case 1: t = op; break;
21
- case 4: _.label++; return { value: op[1], done: false };
22
- case 5: _.label++; y = op[1]; op = [0]; continue;
23
- case 7: op = _.ops.pop(); _.trys.pop(); continue;
24
- default:
25
- if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
26
- if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
27
- if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
28
- if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
29
- if (t[2]) _.ops.pop();
30
- _.trys.pop(); continue;
31
- }
32
- op = body.call(thisArg, _);
33
- } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
34
- if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
35
- }
36
- };
37
- import axios from "axios";
38
- import { getLoadConfig } from "./loadConfig";
39
- import { log } from "@ledgerhq/logs";
40
- export var getNFTInfo = function (contractAddress, chainId, userLoadConfig) { return __awaiter(void 0, void 0, void 0, function () {
41
- var nftExplorerBaseURL, url, response, payload, collectionNameLength, collectionName;
42
- return __generator(this, function (_a) {
43
- switch (_a.label) {
44
- case 0:
45
- nftExplorerBaseURL = getLoadConfig(userLoadConfig).nftExplorerBaseURL;
46
- if (!nftExplorerBaseURL)
47
- return [2 /*return*/];
48
- url = "".concat(nftExplorerBaseURL, "/").concat(chainId, "/contracts/").concat(contractAddress);
49
- return [4 /*yield*/, axios
50
- .get(url)
51
- .then(function (r) { return r.data; })["catch"](function (e) {
52
- log("error", "could not fetch from " + url + ": " + String(e));
53
- return null;
54
- })];
55
- case 1:
56
- response = _a.sent();
57
- if (!response)
58
- return [2 /*return*/];
59
- payload = response["payload"];
60
- collectionNameLength = Number(payload.slice(2, 3));
61
- collectionName = payload.slice(3, 3 + collectionNameLength).toString();
62
- return [2 /*return*/, {
63
- contractAddress: contractAddress,
64
- collectionName: collectionName,
65
- data: Buffer.from(payload, "hex")
66
- }];
67
- }
68
- });
69
- }); };
70
- export var loadNftPlugin = function (contractAddress, selector, chainId, userLoadConfig) { return __awaiter(void 0, void 0, void 0, function () {
71
- var nftExplorerBaseURL, url, response, payload;
72
- return __generator(this, function (_a) {
73
- switch (_a.label) {
74
- case 0:
75
- nftExplorerBaseURL = getLoadConfig(userLoadConfig).nftExplorerBaseURL;
76
- if (!nftExplorerBaseURL)
77
- return [2 /*return*/];
78
- url = "".concat(nftExplorerBaseURL, "/").concat(chainId, "/contracts/").concat(contractAddress, "/plugin-selector/").concat(selector);
79
- return [4 /*yield*/, axios
80
- .get(url)
81
- .then(function (r) { return r.data; })["catch"](function (e) {
82
- log("error", "could not fetch from " + url + ": " + String(e));
83
- return null;
84
- })];
85
- case 1:
86
- response = _a.sent();
87
- if (!response)
88
- return [2 /*return*/];
89
- payload = response["payload"];
90
- return [2 /*return*/, payload];
91
- }
92
- });
93
- }); };
94
- //# sourceMappingURL=nfts.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"nfts.js","sourceRoot":"","sources":["../src/nfts.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAE7C,OAAO,EAAE,GAAG,EAAE,MAAM,gBAAgB,CAAC;AAYrC,MAAM,CAAC,IAAM,UAAU,GAAG,UACxB,eAAuB,EACvB,OAAe,EACf,cAA0B;;;;;gBAElB,kBAAkB,GAAK,aAAa,CAAC,cAAc,CAAC,mBAAlC,CAAmC;gBAC7D,IAAI,CAAC,kBAAkB;oBAAE,sBAAO;gBAC1B,GAAG,GAAG,UAAG,kBAAkB,cAAI,OAAO,wBAAc,eAAe,CAAE,CAAC;gBAC3D,qBAAM,KAAK;yBACzB,GAAG,CAAkB,GAAG,CAAC;yBACzB,IAAI,CAAC,UAAC,CAAC,IAAK,OAAA,CAAC,CAAC,IAAI,EAAN,CAAM,CAAC,CACnB,OAAK,CAAA,CAAC,UAAC,CAAC;wBACP,GAAG,CAAC,OAAO,EAAE,uBAAuB,GAAG,GAAG,GAAG,IAAI,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC;wBAC/D,OAAO,IAAI,CAAC;oBACd,CAAC,CAAC,EAAA;;gBANE,QAAQ,GAAG,SAMb;gBACJ,IAAI,CAAC,QAAQ;oBAAE,sBAAO;gBAEhB,OAAO,GAAG,QAAQ,CAAC,SAAS,CAAC,CAAC;gBAC9B,oBAAoB,GAAG,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;gBACnD,cAAc,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,GAAG,oBAAoB,CAAC,CAAC,QAAQ,EAAE,CAAC;gBAC7E,sBAAO;wBACL,eAAe,EAAE,eAAe;wBAChC,cAAc,EAAE,cAAc;wBAC9B,IAAI,EAAE,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,KAAK,CAAC;qBAClC,EAAC;;;KACH,CAAC;AAEF,MAAM,CAAC,IAAM,aAAa,GAAG,UAC3B,eAAuB,EACvB,QAAgB,EAChB,OAAe,EACf,cAA0B;;;;;gBAElB,kBAAkB,GAAK,aAAa,CAAC,cAAc,CAAC,mBAAlC,CAAmC;gBAC7D,IAAI,CAAC,kBAAkB;oBAAE,sBAAO;gBAC1B,GAAG,GAAG,UAAG,kBAAkB,cAAI,OAAO,wBAAc,eAAe,8BAAoB,QAAQ,CAAE,CAAC;gBAEvF,qBAAM,KAAK;yBACzB,GAAG,CAAkB,GAAG,CAAC;yBACzB,IAAI,CAAC,UAAC,CAAC,IAAK,OAAA,CAAC,CAAC,IAAI,EAAN,CAAM,CAAC,CACnB,OAAK,CAAA,CAAC,UAAC,CAAC;wBACP,GAAG,CAAC,OAAO,EAAE,uBAAuB,GAAG,GAAG,GAAG,IAAI,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC;wBAC/D,OAAO,IAAI,CAAC;oBACd,CAAC,CAAC,EAAA;;gBANE,QAAQ,GAAG,SAMb;gBACJ,IAAI,CAAC,QAAQ;oBAAE,sBAAO;gBAEhB,OAAO,GAAG,QAAQ,CAAC,SAAS,CAAC,CAAC;gBACpC,sBAAO,OAAO,EAAC;;;KAChB,CAAC"}