UNPKG

12.3 kBJavaScriptView Raw
1"use strict";
2var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3 function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4 return new (P || (P = Promise))(function (resolve, reject) {
5 function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6 function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7 function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8 step((generator = generator.apply(thisArg, _arguments || [])).next());
9 });
10};
11var __generator = (this && this.__generator) || function (thisArg, body) {
12 var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
13 return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
14 function verb(n) { return function (v) { return step([n, v]); }; }
15 function step(op) {
16 if (f) throw new TypeError("Generator is already executing.");
17 while (_) try {
18 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;
19 if (y = 0, t) op = [op[0] & 2, t.value];
20 switch (op[0]) {
21 case 0: case 1: t = op; break;
22 case 4: _.label++; return { value: op[1], done: false };
23 case 5: _.label++; y = op[1]; op = [0]; continue;
24 case 7: op = _.ops.pop(); _.trys.pop(); continue;
25 default:
26 if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
27 if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
28 if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
29 if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
30 if (t[2]) _.ops.pop();
31 _.trys.pop(); continue;
32 }
33 op = body.call(thisArg, _);
34 } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
35 if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
36 }
37};
38var __values = (this && this.__values) || function(o) {
39 var s = typeof Symbol === "function" && Symbol.iterator, m = s && o[s], i = 0;
40 if (m) return m.call(o);
41 if (o && typeof o.length === "number") return {
42 next: function () {
43 if (o && i >= o.length) o = void 0;
44 return { value: o && o[i++], done: !o };
45 }
46 };
47 throw new TypeError(s ? "Object is not iterable." : "Symbol.iterator is not defined.");
48};
49exports.__esModule = true;
50// This implements the resolution of a Transaction using Ledger's own API
51var logs_1 = require("@ledgerhq/logs");
52var abi_1 = require("@ethersproject/abi");
53var contracts_1 = require("./contracts");
54var erc20_1 = require("./erc20");
55var nfts_1 = require("./nfts");
56var utils_1 = require("../../utils");
57/**
58 * @ignore for external documentation
59 *
60 * Providing additionnal data for some transactions (Token or NFT related) can enable clear signing
61 * of initially impossible to decode data.
62 * This method will add necessary APDUs to the resolution paramter in order to provide this data to the nano app
63 */
64var getAdditionalDataForContract = function (contractAddress, chainIdTruncated, loadConfig, shouldResolve) { return __awaiter(void 0, void 0, void 0, function () {
65 var resolution, nftInfo, erc20SignaturesBlob, erc20Info;
66 return __generator(this, function (_a) {
67 switch (_a.label) {
68 case 0:
69 resolution = {
70 nfts: [],
71 erc20Tokens: []
72 };
73 if (!shouldResolve.nft) return [3 /*break*/, 2];
74 return [4 /*yield*/, (0, nfts_1.getNFTInfo)(contractAddress, chainIdTruncated, loadConfig)];
75 case 1:
76 nftInfo = _a.sent();
77 if (nftInfo) {
78 (0, logs_1.log)("ethereum", "loaded nft info for " +
79 nftInfo.contractAddress +
80 " (" +
81 nftInfo.collectionName +
82 ")");
83 resolution.nfts.push(nftInfo.data);
84 }
85 else {
86 (0, logs_1.log)("ethereum", "couldn't load nft info for " + contractAddress);
87 }
88 _a.label = 2;
89 case 2:
90 if (!shouldResolve.token) return [3 /*break*/, 4];
91 return [4 /*yield*/, (0, erc20_1.findERC20SignaturesInfo)(loadConfig)];
92 case 3:
93 erc20SignaturesBlob = _a.sent();
94 erc20Info = (0, erc20_1.byContractAddressAndChainId)(contractAddress, chainIdTruncated, erc20SignaturesBlob);
95 if (erc20Info) {
96 (0, logs_1.log)("ethereum", "loaded erc20token info for " +
97 erc20Info.contractAddress +
98 " (" +
99 erc20Info.ticker +
100 ")");
101 resolution.erc20Tokens.push(erc20Info.data.toString("hex"));
102 }
103 else {
104 (0, logs_1.log)("ethereum", "couldn't load erc20token info for " + contractAddress);
105 }
106 _a.label = 4;
107 case 4: return [2 /*return*/, resolution];
108 }
109 });
110}); };
111/**
112 * @ignore for external documentation
113 *
114 * Depending on the transaction, it might be necessary to load internal plugins in the nano app
115 * in order to clear sign it.
116 * This method will add necessary APDUs to the resolution parameter in order to load those internal plugins
117 */
118var loadNanoAppPlugins = function (contractAddress, selector, decodedTx, chainIdTruncated, loadConfig, shouldResolve) { return __awaiter(void 0, void 0, void 0, function () {
119 var resolution, nftPluginPayload, contractMethodInfos, plugin, payload, signature, erc20OfInterest, abi, contract, args, erc20OfInterest_1, erc20OfInterest_1_1, path, erc20ContractAddress, externalPluginResolution, e_1_1;
120 var e_1, _a;
121 return __generator(this, function (_b) {
122 switch (_b.label) {
123 case 0:
124 resolution = {
125 externalPlugin: [],
126 plugin: [],
127 nfts: [],
128 erc20Tokens: []
129 };
130 if (!shouldResolve.nft) return [3 /*break*/, 2];
131 return [4 /*yield*/, (0, nfts_1.loadNftPlugin)(contractAddress, selector, chainIdTruncated, loadConfig)];
132 case 1:
133 nftPluginPayload = _b.sent();
134 if (nftPluginPayload) {
135 resolution.plugin.push(nftPluginPayload);
136 }
137 else {
138 (0, logs_1.log)("ethereum", "no NFT plugin payload for selector " +
139 selector +
140 " and address " +
141 contractAddress);
142 }
143 _b.label = 2;
144 case 2:
145 if (!shouldResolve.externalPlugins) return [3 /*break*/, 13];
146 return [4 /*yield*/, (0, contracts_1.loadInfosForContractMethod)(contractAddress, selector, chainIdTruncated, loadConfig)];
147 case 3:
148 contractMethodInfos = _b.sent();
149 if (!contractMethodInfos) return [3 /*break*/, 12];
150 plugin = contractMethodInfos.plugin, payload = contractMethodInfos.payload, signature = contractMethodInfos.signature, erc20OfInterest = contractMethodInfos.erc20OfInterest, abi = contractMethodInfos.abi;
151 if (plugin) {
152 (0, logs_1.log)("ethereum", "found plugin for " + selector);
153 resolution.externalPlugin.push({ payload: payload, signature: signature });
154 }
155 if (!(erc20OfInterest && erc20OfInterest.length && abi)) return [3 /*break*/, 11];
156 contract = new abi_1.Interface(abi);
157 args = contract.parseTransaction(decodedTx).args;
158 _b.label = 4;
159 case 4:
160 _b.trys.push([4, 9, 10, 11]);
161 erc20OfInterest_1 = __values(erc20OfInterest), erc20OfInterest_1_1 = erc20OfInterest_1.next();
162 _b.label = 5;
163 case 5:
164 if (!!erc20OfInterest_1_1.done) return [3 /*break*/, 8];
165 path = erc20OfInterest_1_1.value;
166 erc20ContractAddress = path.split(".").reduce(function (value, seg) {
167 if (seg === "-1" && Array.isArray(value)) {
168 return value[value.length - 1];
169 }
170 return value[seg];
171 }, args);
172 return [4 /*yield*/, getAdditionalDataForContract(erc20ContractAddress, chainIdTruncated, loadConfig, {
173 nft: false,
174 externalPlugins: false,
175 token: true
176 })];
177 case 6:
178 externalPluginResolution = _b.sent();
179 resolution = (0, utils_1.mergeResolutions)(resolution, externalPluginResolution);
180 _b.label = 7;
181 case 7:
182 erc20OfInterest_1_1 = erc20OfInterest_1.next();
183 return [3 /*break*/, 5];
184 case 8: return [3 /*break*/, 11];
185 case 9:
186 e_1_1 = _b.sent();
187 e_1 = { error: e_1_1 };
188 return [3 /*break*/, 11];
189 case 10:
190 try {
191 if (erc20OfInterest_1_1 && !erc20OfInterest_1_1.done && (_a = erc20OfInterest_1["return"])) _a.call(erc20OfInterest_1);
192 }
193 finally { if (e_1) throw e_1.error; }
194 return [7 /*endfinally*/];
195 case 11: return [3 /*break*/, 13];
196 case 12:
197 (0, logs_1.log)("ethereum", "no infos for selector " + selector);
198 _b.label = 13;
199 case 13: return [2 /*return*/, resolution];
200 }
201 });
202}); };
203var ledgerService = {
204 resolveTransaction: function (rawTxHex, loadConfig, resolutionConfig) { return __awaiter(void 0, void 0, void 0, function () {
205 var rawTx, _a, decodedTx, chainIdTruncated, contractAddress, selector, pluginsResolution, contractResolution, shouldResolve;
206 return __generator(this, function (_b) {
207 switch (_b.label) {
208 case 0:
209 rawTx = Buffer.from(rawTxHex, "hex");
210 _a = (0, utils_1.decodeTxInfo)(rawTx), decodedTx = _a.decodedTx, chainIdTruncated = _a.chainIdTruncated;
211 contractAddress = decodedTx.to;
212 selector = decodedTx.data.length >= 10 && decodedTx.data.substring(0, 10);
213 pluginsResolution = {};
214 contractResolution = {};
215 if (!selector) return [3 /*break*/, 3];
216 shouldResolve = {
217 token: resolutionConfig.erc20 && utils_1.tokenSelectors.includes(selector),
218 nft: resolutionConfig.nft && utils_1.nftSelectors.includes(selector),
219 externalPlugins: resolutionConfig.externalPlugins
220 };
221 return [4 /*yield*/, loadNanoAppPlugins(contractAddress, selector, decodedTx, chainIdTruncated, loadConfig, shouldResolve)];
222 case 1:
223 pluginsResolution = _b.sent();
224 return [4 /*yield*/, getAdditionalDataForContract(contractAddress, chainIdTruncated, loadConfig, shouldResolve)];
225 case 2:
226 contractResolution = _b.sent();
227 _b.label = 3;
228 case 3: return [2 /*return*/, (0, utils_1.mergeResolutions)(pluginsResolution, contractResolution)];
229 }
230 });
231 }); }
232};
233exports["default"] = ledgerService;
234//# sourceMappingURL=index.js.map
\No newline at end of file