1 | "use strict";
|
2 | var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
3 | if (k2 === undefined) k2 = k;
|
4 | var desc = Object.getOwnPropertyDescriptor(m, k);
|
5 | if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
6 | desc = { enumerable: true, get: function() { return m[k]; } };
|
7 | }
|
8 | Object.defineProperty(o, k2, desc);
|
9 | }) : (function(o, m, k, k2) {
|
10 | if (k2 === undefined) k2 = k;
|
11 | o[k2] = m[k];
|
12 | }));
|
13 | var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
14 | for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
15 | };
|
16 | var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
17 | function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
18 | return new (P || (P = Promise))(function (resolve, reject) {
|
19 | function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
20 | function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
21 | function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
22 | step((generator = generator.apply(thisArg, _arguments || [])).next());
|
23 | });
|
24 | };
|
25 | var __importDefault = (this && this.__importDefault) || function (mod) {
|
26 | return (mod && mod.__esModule) ? mod : { "default": mod };
|
27 | };
|
28 | Object.defineProperty(exports, "__esModule", { value: true });
|
29 | exports.ledgerService = void 0;
|
30 | const bignumber_js_1 = require("bignumber.js");
|
31 | const logs_1 = require("@ledgerhq/logs");
|
32 | const utils_1 = require("./utils");
|
33 | const Domains_1 = require("./modules/Domains");
|
34 | const ledger_1 = __importDefault(require("./services/ledger"));
|
35 | exports.ledgerService = ledger_1.default;
|
36 | const errors_1 = require("./errors");
|
37 | const EIP712_1 = require("./modules/EIP712");
|
38 | __exportStar(require("./utils"), exports);
|
39 | const starkQuantizationTypeMap = {
|
40 | eth: 1,
|
41 | erc20: 2,
|
42 | erc721: 3,
|
43 | erc20mintable: 4,
|
44 | erc721mintable: 5,
|
45 | };
|
46 | const remapTransactionRelatedErrors = e => {
|
47 | if (e && e.statusCode === 0x6a80) {
|
48 | return new errors_1.EthAppPleaseEnableContractData("Please enable Blind signing or Contract data in the Ethereum app Settings");
|
49 | }
|
50 | return e;
|
51 | };
|
52 |
|
53 |
|
54 |
|
55 |
|
56 |
|
57 |
|
58 |
|
59 | class Eth {
|
60 | setLoadConfig(loadConfig) {
|
61 | this.loadConfig = loadConfig;
|
62 | }
|
63 | constructor(transport, scrambleKey = "w0w", loadConfig = {}) {
|
64 | this.transport = transport;
|
65 | this.loadConfig = loadConfig;
|
66 | transport.decorateAppAPIMethods(this, [
|
67 |
|
68 |
|
69 |
|
70 |
|
71 |
|
72 |
|
73 | "getAddress",
|
74 | "signTransaction",
|
75 | "signPersonalMessage",
|
76 | "getAppConfiguration",
|
77 | "signEIP712Message",
|
78 | "signEIP712HashedMessage",
|
79 | "starkGetPublicKey",
|
80 | "starkSignOrder",
|
81 | "starkSignOrder_v2",
|
82 | "starkSignTransfer",
|
83 | "starkSignTransfer_v2",
|
84 | "starkProvideQuantum",
|
85 | "starkProvideQuantum_v2",
|
86 | "starkUnsafeSign",
|
87 | "eth2GetPublicKey",
|
88 | "eth2SetWithdrawalIndex",
|
89 | "getEIP1024PublicEncryptionKey",
|
90 | "getEIP1024SharedSecret",
|
91 | ], scrambleKey);
|
92 | }
|
93 | |
94 |
|
95 |
|
96 |
|
97 |
|
98 |
|
99 |
|
100 |
|
101 |
|
102 |
|
103 | getAddress(path, boolDisplay, boolChaincode, chainId) {
|
104 | const paths = (0, utils_1.splitPath)(path);
|
105 | let buffer = Buffer.alloc(1 + paths.length * 4);
|
106 | buffer[0] = paths.length;
|
107 | paths.forEach((element, index) => {
|
108 | buffer.writeUInt32BE(element, 1 + 4 * index);
|
109 | });
|
110 | if (chainId) {
|
111 | const chainIdBufferMask = Buffer.alloc(8, 0);
|
112 | const chainIdBuffer = Buffer.from((0, utils_1.padHexString)(new bignumber_js_1.BigNumber(chainId).toString(16)), "hex");
|
113 | chainIdBufferMask.write(chainIdBuffer.toString("hex"), chainIdBufferMask.length - chainIdBuffer.length, "hex");
|
114 | buffer = Buffer.concat([buffer, chainIdBufferMask]);
|
115 | }
|
116 | return this.transport
|
117 | .send(0xe0, 0x02, boolDisplay ? 0x01 : 0x00, boolChaincode ? 0x01 : 0x00, buffer)
|
118 | .then(response => {
|
119 | const publicKeyLength = response[0];
|
120 | const addressLength = response[1 + publicKeyLength];
|
121 | return {
|
122 | publicKey: response.slice(1, 1 + publicKeyLength).toString("hex"),
|
123 | address: "0x" +
|
124 | response
|
125 | .slice(1 + publicKeyLength + 1, 1 + publicKeyLength + 1 + addressLength)
|
126 | .toString("ascii"),
|
127 | chainCode: boolChaincode
|
128 | ? response
|
129 | .slice(1 + publicKeyLength + 1 + addressLength, 1 + publicKeyLength + 1 + addressLength + 32)
|
130 | .toString("hex")
|
131 | : undefined,
|
132 | };
|
133 | });
|
134 | }
|
135 | |
136 |
|
137 |
|
138 |
|
139 |
|
140 |
|
141 |
|
142 |
|
143 |
|
144 |
|
145 |
|
146 |
|
147 |
|
148 | signTransaction(path, rawTxHex, resolution) {
|
149 | return __awaiter(this, void 0, void 0, function* () {
|
150 | if (resolution === undefined) {
|
151 | console.warn("hw-app-eth: signTransaction(path, rawTxHex, resolution): " +
|
152 | "please provide the 'resolution' parameter. " +
|
153 | "See https://github.com/LedgerHQ/ledgerjs/blob/master/packages/hw-app-eth/README.md " +
|
154 | "– the previous signature is deprecated and providing the 3rd 'resolution' parameter explicitly will become mandatory so you have the control on the resolution and the fallback mecanism (e.g. fallback to blind signing or not)." +
|
155 | "// Possible solution:\n" +
|
156 | " + import { ledgerService } from '@ledgerhq/hw-app-eth';\n" +
|
157 | " + const resolution = await ledgerService.resolveTransaction(rawTxHex);");
|
158 | resolution = yield ledger_1.default
|
159 | .resolveTransaction(rawTxHex, this.loadConfig, {
|
160 | externalPlugins: true,
|
161 | erc20: true,
|
162 | })
|
163 | .catch(e => {
|
164 | console.warn("an error occurred in resolveTransaction => fallback to blind signing: " + String(e));
|
165 | return null;
|
166 | });
|
167 | }
|
168 |
|
169 | if (resolution) {
|
170 | for (const domainDescriptor of resolution.domains) {
|
171 | yield (0, Domains_1.domainResolutionFlow)(this, domainDescriptor).catch(e => {
|
172 |
|
173 | (0, logs_1.log)("error", "domainResolutionFlow failed", {
|
174 | domainDescriptor,
|
175 | error: e,
|
176 | });
|
177 | });
|
178 | }
|
179 | for (const plugin of resolution.plugin) {
|
180 | yield this.setPlugin(plugin);
|
181 | }
|
182 | for (const { payload, signature } of resolution.externalPlugin) {
|
183 | yield this.setExternalPlugin(payload, signature);
|
184 | }
|
185 | for (const nft of resolution.nfts) {
|
186 | yield this.provideNFTInformation(nft);
|
187 | }
|
188 | for (const data of resolution.erc20Tokens) {
|
189 | yield this.provideERC20TokenInformation(data);
|
190 | }
|
191 | }
|
192 | const rawTx = Buffer.from(rawTxHex, "hex");
|
193 | const { vrsOffset, txType, chainId, chainIdTruncated } = (0, utils_1.decodeTxInfo)(rawTx);
|
194 | const paths = (0, utils_1.splitPath)(path);
|
195 | let response;
|
196 | let offset = 0;
|
197 | while (offset !== rawTx.length) {
|
198 | const first = offset === 0;
|
199 | const maxChunkSize = first ? 150 - 1 - paths.length * 4 : 150;
|
200 | let chunkSize = offset + maxChunkSize > rawTx.length ? rawTx.length - offset : maxChunkSize;
|
201 | if (vrsOffset != 0 && offset + chunkSize >= vrsOffset) {
|
202 |
|
203 | chunkSize = rawTx.length - offset;
|
204 | }
|
205 | const buffer = Buffer.alloc(first ? 1 + paths.length * 4 + chunkSize : chunkSize);
|
206 | if (first) {
|
207 | buffer[0] = paths.length;
|
208 | paths.forEach((element, index) => {
|
209 | buffer.writeUInt32BE(element, 1 + 4 * index);
|
210 | });
|
211 | rawTx.copy(buffer, 1 + 4 * paths.length, offset, offset + chunkSize);
|
212 | }
|
213 | else {
|
214 | rawTx.copy(buffer, 0, offset, offset + chunkSize);
|
215 | }
|
216 | response = yield this.transport
|
217 | .send(0xe0, 0x04, first ? 0x00 : 0x80, 0x00, buffer)
|
218 | .catch(e => {
|
219 | throw remapTransactionRelatedErrors(e);
|
220 | });
|
221 | offset += chunkSize;
|
222 | }
|
223 | const response_byte = response[0];
|
224 | let v = "";
|
225 | if (chainId.times(2).plus(35).plus(1).isGreaterThan(255)) {
|
226 | const oneByteChainId = (chainIdTruncated * 2 + 35) % 256;
|
227 | const ecc_parity = Math.abs(response_byte - oneByteChainId);
|
228 | if (txType != null) {
|
229 |
|
230 | v = ecc_parity % 2 == 1 ? "00" : "01";
|
231 | }
|
232 | else {
|
233 |
|
234 | v = chainId.times(2).plus(35).plus(ecc_parity).toString(16);
|
235 | }
|
236 | }
|
237 | else {
|
238 | v = response_byte.toString(16);
|
239 | }
|
240 |
|
241 | if (v.length % 2 == 1) {
|
242 | v = "0" + v;
|
243 | }
|
244 | const r = response.slice(1, 1 + 32).toString("hex");
|
245 | const s = response.slice(1 + 32, 1 + 32 + 32).toString("hex");
|
246 | return { v, r, s };
|
247 | });
|
248 | }
|
249 | |
250 |
|
251 |
|
252 |
|
253 |
|
254 |
|
255 |
|
256 |
|
257 |
|
258 |
|
259 |
|
260 |
|
261 | clearSignTransaction(path_1, rawTxHex_1, resolutionConfig_1) {
|
262 | return __awaiter(this, arguments, void 0, function* (path, rawTxHex, resolutionConfig, throwOnError = false) {
|
263 | const resolution = yield ledger_1.default
|
264 | .resolveTransaction(rawTxHex, this.loadConfig, resolutionConfig)
|
265 | .catch(e => {
|
266 | console.warn("an error occurred in resolveTransaction => fallback to blind signing: " + String(e));
|
267 | if (throwOnError) {
|
268 | throw e;
|
269 | }
|
270 | return null;
|
271 | });
|
272 | return this.signTransaction(path, rawTxHex, resolution);
|
273 | });
|
274 | }
|
275 | |
276 |
|
277 | getAppConfiguration() {
|
278 | return this.transport.send(0xe0, 0x06, 0x00, 0x00).then(response => {
|
279 | return {
|
280 | arbitraryDataEnabled: response[0] & 0x01,
|
281 | erc20ProvisioningNecessary: response[0] & 0x02,
|
282 | starkEnabled: response[0] & 0x04,
|
283 | starkv2Supported: response[0] & 0x08,
|
284 | version: "" + response[1] + "." + response[2] + "." + response[3],
|
285 | };
|
286 | });
|
287 | }
|
288 | |
289 |
|
290 |
|
291 |
|
292 |
|
293 |
|
294 |
|
295 |
|
296 |
|
297 |
|
298 |
|
299 |
|
300 | signPersonalMessage(path, messageHex) {
|
301 | return __awaiter(this, void 0, void 0, function* () {
|
302 | const paths = (0, utils_1.splitPath)(path);
|
303 | let offset = 0;
|
304 | const message = Buffer.from(messageHex, "hex");
|
305 | let response;
|
306 | while (offset !== message.length) {
|
307 | const maxChunkSize = offset === 0 ? 150 - 1 - paths.length * 4 - 4 : 150;
|
308 | const chunkSize = offset + maxChunkSize > message.length ? message.length - offset : maxChunkSize;
|
309 | const buffer = Buffer.alloc(offset === 0 ? 1 + paths.length * 4 + 4 + chunkSize : chunkSize);
|
310 | if (offset === 0) {
|
311 | buffer[0] = paths.length;
|
312 | paths.forEach((element, index) => {
|
313 | buffer.writeUInt32BE(element, 1 + 4 * index);
|
314 | });
|
315 | buffer.writeUInt32BE(message.length, 1 + 4 * paths.length);
|
316 | message.copy(buffer, 1 + 4 * paths.length + 4, offset, offset + chunkSize);
|
317 | }
|
318 | else {
|
319 | message.copy(buffer, 0, offset, offset + chunkSize);
|
320 | }
|
321 | response = yield this.transport.send(0xe0, 0x08, offset === 0 ? 0x00 : 0x80, 0x00, buffer);
|
322 | offset += chunkSize;
|
323 | }
|
324 | const v = response[0];
|
325 | const r = response.slice(1, 1 + 32).toString("hex");
|
326 | const s = response.slice(1 + 32, 1 + 32 + 32).toString("hex");
|
327 | return { v, r, s };
|
328 | });
|
329 | }
|
330 | |
331 |
|
332 |
|
333 |
|
334 |
|
335 |
|
336 |
|
337 |
|
338 |
|
339 |
|
340 |
|
341 |
|
342 | signEIP712HashedMessage(path, domainSeparatorHex, hashStructMessageHex) {
|
343 | return (0, EIP712_1.signEIP712HashedMessage)(this.transport, path, domainSeparatorHex, hashStructMessageHex);
|
344 | }
|
345 | |
346 |
|
347 |
|
348 |
|
349 |
|
350 |
|
351 |
|
352 |
|
353 |
|
354 |
|
355 |
|
356 |
|
357 |
|
358 |
|
359 |
|
360 |
|
361 |
|
362 |
|
363 |
|
364 |
|
365 |
|
366 |
|
367 |
|
368 |
|
369 |
|
370 |
|
371 |
|
372 |
|
373 |
|
374 |
|
375 |
|
376 |
|
377 | signEIP712Message(path_1, jsonMessage_1) {
|
378 | return __awaiter(this, arguments, void 0, function* (path, jsonMessage, fullImplem = false) {
|
379 | return (0, EIP712_1.signEIP712Message)(this.transport, path, jsonMessage, fullImplem, this.loadConfig);
|
380 | });
|
381 | }
|
382 | |
383 |
|
384 |
|
385 |
|
386 |
|
387 | getChallenge() {
|
388 | return __awaiter(this, void 0, void 0, function* () {
|
389 | let APDU_FIELDS;
|
390 | (function (APDU_FIELDS) {
|
391 | APDU_FIELDS[APDU_FIELDS["CLA"] = 224] = "CLA";
|
392 | APDU_FIELDS[APDU_FIELDS["INS"] = 32] = "INS";
|
393 | APDU_FIELDS[APDU_FIELDS["P1"] = 0] = "P1";
|
394 | APDU_FIELDS[APDU_FIELDS["P2"] = 0] = "P2";
|
395 | APDU_FIELDS[APDU_FIELDS["LC"] = 0] = "LC";
|
396 | })(APDU_FIELDS || (APDU_FIELDS = {}));
|
397 | return this.transport
|
398 | .send(APDU_FIELDS.CLA, APDU_FIELDS.INS, APDU_FIELDS.P1, APDU_FIELDS.P2)
|
399 | .then(res => {
|
400 | const [, fourBytesChallenge, statusCode] = new RegExp("(.*)(.{4}$)").exec(res.toString("hex")) || [];
|
401 | if (statusCode !== "9000") {
|
402 | throw new Error(`An error happened while generating the challenge. Status code: ${statusCode}`);
|
403 | }
|
404 | return `0x${fourBytesChallenge}`;
|
405 | })
|
406 | .catch(e => {
|
407 | (0, logs_1.log)("error", "couldn't request a challenge", e);
|
408 | throw e;
|
409 | });
|
410 | });
|
411 | }
|
412 | |
413 |
|
414 |
|
415 |
|
416 |
|
417 |
|
418 | starkGetPublicKey(path, boolDisplay) {
|
419 | const paths = (0, utils_1.splitPath)(path);
|
420 | const buffer = Buffer.alloc(1 + paths.length * 4);
|
421 | buffer[0] = paths.length;
|
422 | paths.forEach((element, index) => {
|
423 | buffer.writeUInt32BE(element, 1 + 4 * index);
|
424 | });
|
425 | return this.transport
|
426 | .send(0xf0, 0x02, boolDisplay ? 0x01 : 0x00, 0x00, buffer)
|
427 | .then(response => {
|
428 | return response.slice(0, response.length - 2);
|
429 | });
|
430 | }
|
431 | |
432 |
|
433 |
|
434 |
|
435 |
|
436 |
|
437 |
|
438 |
|
439 |
|
440 |
|
441 |
|
442 |
|
443 |
|
444 |
|
445 |
|
446 | starkSignOrder(path, sourceTokenAddress, sourceQuantization, destinationTokenAddress, destinationQuantization, sourceVault, destinationVault, amountSell, amountBuy, nonce, timestamp) {
|
447 | const sourceTokenAddressHex = (0, utils_1.maybeHexBuffer)(sourceTokenAddress);
|
448 | const destinationTokenAddressHex = (0, utils_1.maybeHexBuffer)(destinationTokenAddress);
|
449 | const paths = (0, utils_1.splitPath)(path);
|
450 | const buffer = Buffer.alloc(1 + paths.length * 4 + 20 + 32 + 20 + 32 + 4 + 4 + 8 + 8 + 4 + 4, 0);
|
451 | let offset = 0;
|
452 | buffer[0] = paths.length;
|
453 | paths.forEach((element, index) => {
|
454 | buffer.writeUInt32BE(element, 1 + 4 * index);
|
455 | });
|
456 | offset = 1 + 4 * paths.length;
|
457 | if (sourceTokenAddressHex) {
|
458 | sourceTokenAddressHex.copy(buffer, offset);
|
459 | }
|
460 | offset += 20;
|
461 | Buffer.from(sourceQuantization.toString(16).padStart(64, "0"), "hex").copy(buffer, offset);
|
462 | offset += 32;
|
463 | if (destinationTokenAddressHex) {
|
464 | destinationTokenAddressHex.copy(buffer, offset);
|
465 | }
|
466 | offset += 20;
|
467 | Buffer.from(destinationQuantization.toString(16).padStart(64, "0"), "hex").copy(buffer, offset);
|
468 | offset += 32;
|
469 | buffer.writeUInt32BE(sourceVault, offset);
|
470 | offset += 4;
|
471 | buffer.writeUInt32BE(destinationVault, offset);
|
472 | offset += 4;
|
473 | Buffer.from(amountSell.toString(16).padStart(16, "0"), "hex").copy(buffer, offset);
|
474 | offset += 8;
|
475 | Buffer.from(amountBuy.toString(16).padStart(16, "0"), "hex").copy(buffer, offset);
|
476 | offset += 8;
|
477 | buffer.writeUInt32BE(nonce, offset);
|
478 | offset += 4;
|
479 | buffer.writeUInt32BE(timestamp, offset);
|
480 | return this.transport.send(0xf0, 0x04, 0x01, 0x00, buffer).then(response => {
|
481 | const r = response.slice(1, 1 + 32).toString("hex");
|
482 | const s = response.slice(1 + 32, 1 + 32 + 32).toString("hex");
|
483 | return {
|
484 | r,
|
485 | s,
|
486 | };
|
487 | });
|
488 | }
|
489 | |
490 |
|
491 |
|
492 |
|
493 |
|
494 |
|
495 |
|
496 |
|
497 |
|
498 |
|
499 |
|
500 |
|
501 |
|
502 |
|
503 |
|
504 |
|
505 |
|
506 |
|
507 |
|
508 | starkSignOrder_v2(path, sourceTokenAddress, sourceQuantizationType, sourceQuantization, sourceMintableBlobOrTokenId, destinationTokenAddress, destinationQuantizationType, destinationQuantization, destinationMintableBlobOrTokenId, sourceVault, destinationVault, amountSell, amountBuy, nonce, timestamp) {
|
509 | const sourceTokenAddressHex = (0, utils_1.maybeHexBuffer)(sourceTokenAddress);
|
510 | const destinationTokenAddressHex = (0, utils_1.maybeHexBuffer)(destinationTokenAddress);
|
511 | if (!(sourceQuantizationType in starkQuantizationTypeMap)) {
|
512 | throw new Error("eth.starkSignOrderv2 invalid source quantization type=" + sourceQuantizationType);
|
513 | }
|
514 | if (!(destinationQuantizationType in starkQuantizationTypeMap)) {
|
515 | throw new Error("eth.starkSignOrderv2 invalid destination quantization type=" + destinationQuantizationType);
|
516 | }
|
517 | const paths = (0, utils_1.splitPath)(path);
|
518 | const buffer = Buffer.alloc(1 + paths.length * 4 + 1 + 20 + 32 + 32 + 1 + 20 + 32 + 32 + 4 + 4 + 8 + 8 + 4 + 4, 0);
|
519 | let offset = 0;
|
520 | buffer[0] = paths.length;
|
521 | paths.forEach((element, index) => {
|
522 | buffer.writeUInt32BE(element, 1 + 4 * index);
|
523 | });
|
524 | offset = 1 + 4 * paths.length;
|
525 | buffer[offset] = starkQuantizationTypeMap[sourceQuantizationType];
|
526 | offset++;
|
527 | if (sourceTokenAddressHex) {
|
528 | sourceTokenAddressHex.copy(buffer, offset);
|
529 | }
|
530 | offset += 20;
|
531 | if (sourceQuantization) {
|
532 | Buffer.from(sourceQuantization.toString(16).padStart(64, "0"), "hex").copy(buffer, offset);
|
533 | }
|
534 | offset += 32;
|
535 | if (sourceMintableBlobOrTokenId) {
|
536 | Buffer.from(sourceMintableBlobOrTokenId.toString(16).padStart(64, "0"), "hex").copy(buffer, offset);
|
537 | }
|
538 | offset += 32;
|
539 | buffer[offset] = starkQuantizationTypeMap[destinationQuantizationType];
|
540 | offset++;
|
541 | if (destinationTokenAddressHex) {
|
542 | destinationTokenAddressHex.copy(buffer, offset);
|
543 | }
|
544 | offset += 20;
|
545 | if (destinationQuantization) {
|
546 | Buffer.from(destinationQuantization.toString(16).padStart(64, "0"), "hex").copy(buffer, offset);
|
547 | }
|
548 | offset += 32;
|
549 | if (destinationMintableBlobOrTokenId) {
|
550 | Buffer.from(destinationMintableBlobOrTokenId.toString(16).padStart(64, "0"), "hex").copy(buffer, offset);
|
551 | }
|
552 | offset += 32;
|
553 | buffer.writeUInt32BE(sourceVault, offset);
|
554 | offset += 4;
|
555 | buffer.writeUInt32BE(destinationVault, offset);
|
556 | offset += 4;
|
557 | Buffer.from(amountSell.toString(16).padStart(16, "0"), "hex").copy(buffer, offset);
|
558 | offset += 8;
|
559 | Buffer.from(amountBuy.toString(16).padStart(16, "0"), "hex").copy(buffer, offset);
|
560 | offset += 8;
|
561 | buffer.writeUInt32BE(nonce, offset);
|
562 | offset += 4;
|
563 | buffer.writeUInt32BE(timestamp, offset);
|
564 | return this.transport.send(0xf0, 0x04, 0x03, 0x00, buffer).then(response => {
|
565 | const r = response.slice(1, 1 + 32).toString("hex");
|
566 | const s = response.slice(1 + 32, 1 + 32 + 32).toString("hex");
|
567 | return {
|
568 | r,
|
569 | s,
|
570 | };
|
571 | });
|
572 | }
|
573 | |
574 |
|
575 |
|
576 |
|
577 |
|
578 |
|
579 |
|
580 |
|
581 |
|
582 |
|
583 |
|
584 |
|
585 |
|
586 | starkSignTransfer(path, transferTokenAddress, transferQuantization, targetPublicKey, sourceVault, destinationVault, amountTransfer, nonce, timestamp) {
|
587 | const transferTokenAddressHex = (0, utils_1.maybeHexBuffer)(transferTokenAddress);
|
588 | const targetPublicKeyHex = (0, utils_1.hexBuffer)(targetPublicKey);
|
589 | const paths = (0, utils_1.splitPath)(path);
|
590 | const buffer = Buffer.alloc(1 + paths.length * 4 + 20 + 32 + 32 + 4 + 4 + 8 + 4 + 4, 0);
|
591 | let offset = 0;
|
592 | buffer[0] = paths.length;
|
593 | paths.forEach((element, index) => {
|
594 | buffer.writeUInt32BE(element, 1 + 4 * index);
|
595 | });
|
596 | offset = 1 + 4 * paths.length;
|
597 | if (transferTokenAddressHex) {
|
598 | transferTokenAddressHex.copy(buffer, offset);
|
599 | }
|
600 | offset += 20;
|
601 | Buffer.from(transferQuantization.toString(16).padStart(64, "0"), "hex").copy(buffer, offset);
|
602 | offset += 32;
|
603 | targetPublicKeyHex.copy(buffer, offset);
|
604 | offset += 32;
|
605 | buffer.writeUInt32BE(sourceVault, offset);
|
606 | offset += 4;
|
607 | buffer.writeUInt32BE(destinationVault, offset);
|
608 | offset += 4;
|
609 | Buffer.from(amountTransfer.toString(16).padStart(16, "0"), "hex").copy(buffer, offset);
|
610 | offset += 8;
|
611 | buffer.writeUInt32BE(nonce, offset);
|
612 | offset += 4;
|
613 | buffer.writeUInt32BE(timestamp, offset);
|
614 | return this.transport.send(0xf0, 0x04, 0x02, 0x00, buffer).then(response => {
|
615 | const r = response.slice(1, 1 + 32).toString("hex");
|
616 | const s = response.slice(1 + 32, 1 + 32 + 32).toString("hex");
|
617 | return {
|
618 | r,
|
619 | s,
|
620 | };
|
621 | });
|
622 | }
|
623 | |
624 |
|
625 |
|
626 |
|
627 |
|
628 |
|
629 |
|
630 |
|
631 |
|
632 |
|
633 |
|
634 |
|
635 |
|
636 |
|
637 |
|
638 |
|
639 |
|
640 | starkSignTransfer_v2(path, transferTokenAddress, transferQuantizationType, transferQuantization, transferMintableBlobOrTokenId, targetPublicKey, sourceVault, destinationVault, amountTransfer, nonce, timestamp, conditionalTransferAddress, conditionalTransferFact) {
|
641 | const transferTokenAddressHex = (0, utils_1.maybeHexBuffer)(transferTokenAddress);
|
642 | const targetPublicKeyHex = (0, utils_1.hexBuffer)(targetPublicKey);
|
643 | const conditionalTransferAddressHex = (0, utils_1.maybeHexBuffer)(conditionalTransferAddress);
|
644 | if (!(transferQuantizationType in starkQuantizationTypeMap)) {
|
645 | throw new Error("eth.starkSignTransferv2 invalid quantization type=" + transferQuantizationType);
|
646 | }
|
647 | const paths = (0, utils_1.splitPath)(path);
|
648 | const buffer = Buffer.alloc(1 +
|
649 | paths.length * 4 +
|
650 | 1 +
|
651 | 20 +
|
652 | 32 +
|
653 | 32 +
|
654 | 32 +
|
655 | 4 +
|
656 | 4 +
|
657 | 8 +
|
658 | 4 +
|
659 | 4 +
|
660 | (conditionalTransferAddressHex ? 32 + 20 : 0), 0);
|
661 | let offset = 0;
|
662 | buffer[0] = paths.length;
|
663 | paths.forEach((element, index) => {
|
664 | buffer.writeUInt32BE(element, 1 + 4 * index);
|
665 | });
|
666 | offset = 1 + 4 * paths.length;
|
667 | buffer[offset] = starkQuantizationTypeMap[transferQuantizationType];
|
668 | offset++;
|
669 | if (transferTokenAddressHex) {
|
670 | transferTokenAddressHex.copy(buffer, offset);
|
671 | }
|
672 | offset += 20;
|
673 | if (transferQuantization) {
|
674 | Buffer.from(transferQuantization.toString(16).padStart(64, "0"), "hex").copy(buffer, offset);
|
675 | }
|
676 | offset += 32;
|
677 | if (transferMintableBlobOrTokenId) {
|
678 | Buffer.from(transferMintableBlobOrTokenId.toString(16).padStart(64, "0"), "hex").copy(buffer, offset);
|
679 | }
|
680 | offset += 32;
|
681 | targetPublicKeyHex.copy(buffer, offset);
|
682 | offset += 32;
|
683 | buffer.writeUInt32BE(sourceVault, offset);
|
684 | offset += 4;
|
685 | buffer.writeUInt32BE(destinationVault, offset);
|
686 | offset += 4;
|
687 | Buffer.from(amountTransfer.toString(16).padStart(16, "0"), "hex").copy(buffer, offset);
|
688 | offset += 8;
|
689 | buffer.writeUInt32BE(nonce, offset);
|
690 | offset += 4;
|
691 | buffer.writeUInt32BE(timestamp, offset);
|
692 | if (conditionalTransferAddressHex && conditionalTransferFact) {
|
693 | offset += 4;
|
694 | Buffer.from(conditionalTransferFact.toString(16).padStart(64, "0"), "hex").copy(buffer, offset);
|
695 | offset += 32;
|
696 | conditionalTransferAddressHex.copy(buffer, offset);
|
697 | }
|
698 | return this.transport
|
699 | .send(0xf0, 0x04, conditionalTransferAddressHex ? 0x05 : 0x04, 0x00, buffer)
|
700 | .then(response => {
|
701 | const r = response.slice(1, 1 + 32).toString("hex");
|
702 | const s = response.slice(1 + 32, 1 + 32 + 32).toString("hex");
|
703 | return {
|
704 | r,
|
705 | s,
|
706 | };
|
707 | });
|
708 | }
|
709 | |
710 |
|
711 |
|
712 |
|
713 |
|
714 |
|
715 |
|
716 |
|
717 | starkProvideQuantum(operationContract, operationQuantization) {
|
718 | const operationContractHex = (0, utils_1.maybeHexBuffer)(operationContract);
|
719 | const buffer = Buffer.alloc(20 + 32, 0);
|
720 | if (operationContractHex) {
|
721 | operationContractHex.copy(buffer, 0);
|
722 | }
|
723 | Buffer.from(operationQuantization.toString(16).padStart(64, "0"), "hex").copy(buffer, 20);
|
724 | return this.transport.send(0xf0, 0x08, 0x00, 0x00, buffer).then(() => true, e => {
|
725 | if (e && e.statusCode === 0x6d00) {
|
726 |
|
727 | return false;
|
728 | }
|
729 | throw e;
|
730 | });
|
731 | }
|
732 | |
733 |
|
734 |
|
735 |
|
736 |
|
737 |
|
738 |
|
739 |
|
740 |
|
741 |
|
742 | starkProvideQuantum_v2(operationContract, operationQuantizationType, operationQuantization, operationMintableBlobOrTokenId) {
|
743 | const operationContractHex = (0, utils_1.maybeHexBuffer)(operationContract);
|
744 | if (!(operationQuantizationType in starkQuantizationTypeMap)) {
|
745 | throw new Error("eth.starkProvideQuantumV2 invalid quantization type=" + operationQuantizationType);
|
746 | }
|
747 | const buffer = Buffer.alloc(20 + 32 + 32, 0);
|
748 | let offset = 0;
|
749 | if (operationContractHex) {
|
750 | operationContractHex.copy(buffer, offset);
|
751 | }
|
752 | offset += 20;
|
753 | if (operationQuantization) {
|
754 | Buffer.from(operationQuantization.toString(16).padStart(64, "0"), "hex").copy(buffer, offset);
|
755 | }
|
756 | offset += 32;
|
757 | if (operationMintableBlobOrTokenId) {
|
758 | Buffer.from(operationMintableBlobOrTokenId.toString(16).padStart(64, "0"), "hex").copy(buffer, offset);
|
759 | }
|
760 | return this.transport
|
761 | .send(0xf0, 0x08, starkQuantizationTypeMap[operationQuantizationType], 0x00, buffer)
|
762 | .then(() => true, e => {
|
763 | if (e && e.statusCode === 0x6d00) {
|
764 |
|
765 | return false;
|
766 | }
|
767 | throw e;
|
768 | });
|
769 | }
|
770 | |
771 |
|
772 |
|
773 |
|
774 |
|
775 |
|
776 |
|
777 | starkUnsafeSign(path, hash) {
|
778 | const hashHex = (0, utils_1.hexBuffer)(hash);
|
779 | const paths = (0, utils_1.splitPath)(path);
|
780 | const buffer = Buffer.alloc(1 + paths.length * 4 + 32);
|
781 | let offset = 0;
|
782 | buffer[0] = paths.length;
|
783 | paths.forEach((element, index) => {
|
784 | buffer.writeUInt32BE(element, 1 + 4 * index);
|
785 | });
|
786 | offset = 1 + 4 * paths.length;
|
787 | hashHex.copy(buffer, offset);
|
788 | return this.transport.send(0xf0, 0x0a, 0x00, 0x00, buffer).then(response => {
|
789 | const r = response.slice(1, 1 + 32).toString("hex");
|
790 | const s = response.slice(1 + 32, 1 + 32 + 32).toString("hex");
|
791 | return {
|
792 | r,
|
793 | s,
|
794 | };
|
795 | });
|
796 | }
|
797 | |
798 |
|
799 |
|
800 |
|
801 |
|
802 |
|
803 |
|
804 |
|
805 | eth2GetPublicKey(path, boolDisplay) {
|
806 | const paths = (0, utils_1.splitPath)(path);
|
807 | const buffer = Buffer.alloc(1 + paths.length * 4);
|
808 | buffer[0] = paths.length;
|
809 | paths.forEach((element, index) => {
|
810 | buffer.writeUInt32BE(element, 1 + 4 * index);
|
811 | });
|
812 | return this.transport
|
813 | .send(0xe0, 0x0e, boolDisplay ? 0x01 : 0x00, 0x00, buffer)
|
814 | .then(response => {
|
815 | return {
|
816 | publicKey: response.slice(0, -2).toString("hex"),
|
817 | };
|
818 | });
|
819 | }
|
820 | |
821 |
|
822 |
|
823 |
|
824 |
|
825 |
|
826 |
|
827 |
|
828 | eth2SetWithdrawalIndex(withdrawalIndex) {
|
829 | const buffer = Buffer.alloc(4, 0);
|
830 | buffer.writeUInt32BE(withdrawalIndex, 0);
|
831 | return this.transport.send(0xe0, 0x10, 0x00, 0x00, buffer).then(() => true, e => {
|
832 | if (e && e.statusCode === 0x6d00) {
|
833 |
|
834 | return false;
|
835 | }
|
836 | throw e;
|
837 | });
|
838 | }
|
839 | |
840 |
|
841 |
|
842 |
|
843 |
|
844 |
|
845 |
|
846 |
|
847 | getEIP1024PublicEncryptionKey(path, boolDisplay) {
|
848 | const paths = (0, utils_1.splitPath)(path);
|
849 | const buffer = Buffer.alloc(1 + paths.length * 4);
|
850 | buffer[0] = paths.length;
|
851 | paths.forEach((element, index) => {
|
852 | buffer.writeUInt32BE(element, 1 + 4 * index);
|
853 | });
|
854 | return this.transport
|
855 | .send(0xe0, 0x18, boolDisplay ? 0x01 : 0x00, 0x00, buffer)
|
856 | .then(response => {
|
857 | return {
|
858 | publicKey: response.slice(0, -2).toString("hex"),
|
859 | };
|
860 | });
|
861 | }
|
862 | |
863 |
|
864 |
|
865 |
|
866 |
|
867 |
|
868 |
|
869 |
|
870 |
|
871 | getEIP1024SharedSecret(path, remotePublicKeyHex, boolDisplay) {
|
872 | const paths = (0, utils_1.splitPath)(path);
|
873 | const remotePublicKey = (0, utils_1.hexBuffer)(remotePublicKeyHex);
|
874 | const buffer = Buffer.alloc(1 + paths.length * 4 + 32);
|
875 | let offset = 0;
|
876 | buffer[0] = paths.length;
|
877 | paths.forEach((element, index) => {
|
878 | buffer.writeUInt32BE(element, 1 + 4 * index);
|
879 | });
|
880 | offset = 1 + 4 * paths.length;
|
881 | remotePublicKey.copy(buffer, offset);
|
882 | return this.transport
|
883 | .send(0xe0, 0x18, boolDisplay ? 0x01 : 0x00, 0x01, buffer)
|
884 | .then(response => {
|
885 | return {
|
886 | sharedSecret: response.slice(0, -2).toString("hex"),
|
887 | };
|
888 | });
|
889 | }
|
890 | |
891 |
|
892 |
|
893 |
|
894 |
|
895 |
|
896 | provideERC20TokenInformation(data) {
|
897 | const buffer = Buffer.from(data, "hex");
|
898 | return this.transport.send(0xe0, 0x0a, 0x00, 0x00, buffer).then(() => true, e => {
|
899 | if (e && e.statusCode === 0x6d00) {
|
900 |
|
901 |
|
902 | return false;
|
903 | }
|
904 | throw e;
|
905 | });
|
906 | }
|
907 | |
908 |
|
909 |
|
910 |
|
911 |
|
912 |
|
913 |
|
914 | setExternalPlugin(payload, signature) {
|
915 | const payloadBuffer = Buffer.from(payload, "hex");
|
916 | const signatureBuffer = Buffer.from(signature !== null && signature !== void 0 ? signature : "", "hex");
|
917 | const buffer = Buffer.concat([payloadBuffer, signatureBuffer]);
|
918 | return this.transport.send(0xe0, 0x12, 0x00, 0x00, buffer).then(() => true, e => {
|
919 | if (e && e.statusCode === 0x6a80) {
|
920 |
|
921 | return false;
|
922 | }
|
923 | else if (e && e.statusCode === 0x6984) {
|
924 |
|
925 | return false;
|
926 | }
|
927 | else if (e && e.statusCode === 0x6d00) {
|
928 |
|
929 | return false;
|
930 | }
|
931 | throw e;
|
932 | });
|
933 | }
|
934 | |
935 |
|
936 |
|
937 |
|
938 |
|
939 |
|
940 | setPlugin(data) {
|
941 | const buffer = Buffer.from(data, "hex");
|
942 | return this.transport.send(0xe0, 0x16, 0x00, 0x00, buffer).then(() => true, e => {
|
943 | if (e && e.statusCode === 0x6a80) {
|
944 |
|
945 | return false;
|
946 | }
|
947 | else if (e && e.statusCode === 0x6984) {
|
948 |
|
949 | return false;
|
950 | }
|
951 | else if (e && e.statusCode === 0x6d00) {
|
952 |
|
953 | return false;
|
954 | }
|
955 | throw e;
|
956 | });
|
957 | }
|
958 | |
959 |
|
960 |
|
961 |
|
962 |
|
963 |
|
964 | provideNFTInformation(data) {
|
965 | const buffer = Buffer.from(data, "hex");
|
966 | return this.transport.send(0xe0, 0x14, 0x00, 0x00, buffer).then(() => true, e => {
|
967 | if (e && e.statusCode === 0x6d00) {
|
968 |
|
969 | throw new errors_1.EthAppNftNotSupported();
|
970 | }
|
971 | throw e;
|
972 | });
|
973 | }
|
974 | |
975 |
|
976 |
|
977 |
|
978 |
|
979 |
|
980 | provideDomainName(data) {
|
981 | return __awaiter(this, void 0, void 0, function* () {
|
982 | let APDU_FIELDS;
|
983 | (function (APDU_FIELDS) {
|
984 | APDU_FIELDS[APDU_FIELDS["CLA"] = 224] = "CLA";
|
985 | APDU_FIELDS[APDU_FIELDS["INS"] = 34] = "INS";
|
986 | APDU_FIELDS[APDU_FIELDS["P1_FIRST_CHUNK"] = 1] = "P1_FIRST_CHUNK";
|
987 | APDU_FIELDS[APDU_FIELDS["P1_FOLLOWING_CHUNK"] = 0] = "P1_FOLLOWING_CHUNK";
|
988 | APDU_FIELDS[APDU_FIELDS["P2"] = 0] = "P2";
|
989 | })(APDU_FIELDS || (APDU_FIELDS = {}));
|
990 | const buffer = Buffer.from(data, "hex");
|
991 | const payload = Buffer.concat([Buffer.from((0, utils_1.intAsHexBytes)(buffer.length, 2), "hex"), buffer]);
|
992 | const bufferChunks = new Array(Math.ceil(payload.length / 256))
|
993 | .fill(null)
|
994 | .map((_, i) => payload.slice(i * 255, (i + 1) * 255));
|
995 | for (const chunk of bufferChunks) {
|
996 | const isFirstChunk = chunk === bufferChunks[0];
|
997 | yield this.transport.send(APDU_FIELDS.CLA, APDU_FIELDS.INS, isFirstChunk ? APDU_FIELDS.P1_FIRST_CHUNK : APDU_FIELDS.P1_FOLLOWING_CHUNK, APDU_FIELDS.P2, chunk);
|
998 | }
|
999 | return true;
|
1000 | });
|
1001 | }
|
1002 | }
|
1003 | exports.default = Eth;
|
1004 |
|
\ | No newline at end of file |