@ledgerhq/hw-app-vet 0.1.0-nightly.0

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 (53) hide show
  1. package/.turbo/turbo-build.log +4 -0
  2. package/CHANGELOG.md +12 -0
  3. package/LICENSE.txt +21 -0
  4. package/README.md +83 -0
  5. package/jest.config.ts +6 -0
  6. package/lib/Vet.d.ts +38 -0
  7. package/lib/Vet.d.ts.map +1 -0
  8. package/lib/Vet.js +105 -0
  9. package/lib/Vet.js.map +1 -0
  10. package/lib/constants.d.ts +33 -0
  11. package/lib/constants.d.ts.map +1 -0
  12. package/lib/constants.js +37 -0
  13. package/lib/constants.js.map +1 -0
  14. package/lib/errors.d.ts +4 -0
  15. package/lib/errors.d.ts.map +1 -0
  16. package/lib/errors.js +6 -0
  17. package/lib/errors.js.map +1 -0
  18. package/lib/model.d.ts +6 -0
  19. package/lib/model.d.ts.map +1 -0
  20. package/lib/model.js +3 -0
  21. package/lib/model.js.map +1 -0
  22. package/lib/utils.d.ts +4 -0
  23. package/lib/utils.d.ts.map +1 -0
  24. package/lib/utils.js +50 -0
  25. package/lib/utils.js.map +1 -0
  26. package/lib-es/Vet.d.ts +38 -0
  27. package/lib-es/Vet.d.ts.map +1 -0
  28. package/lib-es/Vet.js +102 -0
  29. package/lib-es/Vet.js.map +1 -0
  30. package/lib-es/constants.d.ts +33 -0
  31. package/lib-es/constants.d.ts.map +1 -0
  32. package/lib-es/constants.js +34 -0
  33. package/lib-es/constants.js.map +1 -0
  34. package/lib-es/errors.d.ts +4 -0
  35. package/lib-es/errors.d.ts.map +1 -0
  36. package/lib-es/errors.js +3 -0
  37. package/lib-es/errors.js.map +1 -0
  38. package/lib-es/model.d.ts +6 -0
  39. package/lib-es/model.d.ts.map +1 -0
  40. package/lib-es/model.js +2 -0
  41. package/lib-es/model.js.map +1 -0
  42. package/lib-es/utils.d.ts +4 -0
  43. package/lib-es/utils.d.ts.map +1 -0
  44. package/lib-es/utils.js +45 -0
  45. package/lib-es/utils.js.map +1 -0
  46. package/package.json +58 -0
  47. package/src/Vet.ts +131 -0
  48. package/src/constants.ts +32 -0
  49. package/src/errors.ts +5 -0
  50. package/src/model.ts +5 -0
  51. package/src/utils.ts +46 -0
  52. package/tests/Vechain.test.ts +62 -0
  53. package/tsconfig.json +8 -0
@@ -0,0 +1,4 @@
1
+
2
+ > @ledgerhq/hw-app-vet@0.0.1 build /home/runner/work/ledger-live/ledger-live/libs/ledgerjs/packages/hw-app-vet
3
+ > tsc && tsc -m ES6 --outDir lib-es
4
+
package/CHANGELOG.md ADDED
@@ -0,0 +1,12 @@
1
+ # @ledgerhq/hw-app-vet
2
+
3
+ ## 0.1.0-nightly.0
4
+
5
+ ### Minor Changes
6
+
7
+ - [#4947](https://github.com/LedgerHQ/ledger-live/pull/4947) [`2edfa533bc`](https://github.com/LedgerHQ/ledger-live/commit/2edfa533bccafbfd8a61aea0f5422c0db79825ea) Thanks [@hedi-edelbloute](https://github.com/hedi-edelbloute)! - vechain integration
8
+
9
+ ### Patch Changes
10
+
11
+ - Updated dependencies [[`2edfa533bc`](https://github.com/LedgerHQ/ledger-live/commit/2edfa533bccafbfd8a61aea0f5422c0db79825ea)]:
12
+ - @ledgerhq/cryptoassets@11.2.0-nightly.2
package/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License
2
+
3
+ Copyright (c) 2017-present Ledger https://www.ledger.com/
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,83 @@
1
+ <img src="https://user-images.githubusercontent.com/4631227/191834116-59cf590e-25cc-4956-ae5c-812ea464f324.png" height="100" />
2
+
3
+ [GitHub](https://github.com/LedgerHQ/ledger-live/),
4
+ [Ledger Devs Discord](https://developers.ledger.com/discord-pro),
5
+ [Developer Portal](https://developers.ledger.com/)
6
+
7
+ ## @ledgerhq/hw-app-vet
8
+
9
+ Ledger Hardware Wallet ETH JavaScript bindings.
10
+
11
+ ***
12
+
13
+ ## Are you adding Ledger support to your software wallet?
14
+
15
+ You may be using this package to communicate with the VeChain Nano App.
16
+
17
+ For a smooth and quick integration:
18
+
19
+ * See the developers’ documentation on the [Developer Portal](https://developers.ledger.com/docs/transport/overview/) and
20
+ * Go on [Discord](https://developers.ledger.com/discord-pro/) to chat with developer support and the developer community.
21
+
22
+ ***
23
+
24
+ ## API
25
+
26
+ <!-- Generated by documentation.js. Update this documentation by updating the source code. -->
27
+
28
+ #### Table of Contents
29
+
30
+ * [Vet](#vet)
31
+ * [Parameters](#parameters)
32
+ * [Examples](#examples)
33
+ * [getAddress](#getaddress)
34
+ * [Parameters](#parameters-1)
35
+ * [Examples](#examples-1)
36
+ * [signTransaction](#signtransaction)
37
+ * [Parameters](#parameters-2)
38
+
39
+ ### Vet
40
+
41
+ VeChain API
42
+
43
+ #### Parameters
44
+
45
+ * `transport` **Transport**&#x20;
46
+ * `scrambleKey` (optional, default `"V3T"`)
47
+
48
+ #### Examples
49
+
50
+ ```javascript
51
+ import Vet from "@ledgerhq/hw-app-vet";
52
+ const vet = new Vet(transport)
53
+ ```
54
+
55
+ #### getAddress
56
+
57
+ get VeChain address for a given BIP 32 path.
58
+
59
+ ##### Parameters
60
+
61
+ * `path` **[string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)** a path in BIP 32 format
62
+ * `display` **[boolean](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean)?**&#x20;
63
+ * `chainCode` **[boolean](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean)?**&#x20;
64
+ * `statusCodes` **[Array](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array)\<StatusCodes>** (optional, default `[StatusCodes.OK]`)
65
+
66
+ ##### Examples
67
+
68
+ ```javascript
69
+ vet.getAddress("m/44'/818'/0'/0").then(o => o.address)
70
+ ```
71
+
72
+ Returns **[Promise](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Promise)<{publicKey: [string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String), address: [string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String), chainCode: [string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)?}>** an object with a publicKey and address
73
+
74
+ #### signTransaction
75
+
76
+ You can sign a transaction and retrieve v, r, s given the raw transaction and the BIP 32 path of the account to sign.
77
+
78
+ ##### Parameters
79
+
80
+ * `path` **[string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)** : the BIP32 path to sign the transaction on
81
+ * `rawTxHex` **[string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)** : the raw vechain transaction in hexadecimal to sign
82
+
83
+ Returns **[Promise](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Promise)<[Buffer](https://nodejs.org/api/buffer.html)>**&#x20;
package/jest.config.ts ADDED
@@ -0,0 +1,6 @@
1
+ import baseConfig from "../../jest.config";
2
+
3
+ export default {
4
+ ...baseConfig,
5
+ rootDir: __dirname,
6
+ };
package/lib/Vet.d.ts ADDED
@@ -0,0 +1,38 @@
1
+ /// <reference types="node" />
2
+ import type Transport from "@ledgerhq/hw-transport";
3
+ import { StatusCodes } from "./constants";
4
+ import { Buffer } from "buffer";
5
+ /**
6
+ * VeChain API
7
+ *
8
+ * @example
9
+ * import Vet from "@ledgerhq/hw-app-vet";
10
+ * const vet = new Vet(transport)
11
+ */
12
+ export default class Vet {
13
+ transport: Transport;
14
+ constructor(transport: Transport, scrambleKey?: string);
15
+ getAppConfiguration(): Promise<any>;
16
+ /**
17
+ * get VeChain address for a given BIP 32 path.
18
+ * @param path a path in BIP 32 format
19
+ * @option display
20
+ * @option chainCode
21
+ * @return an object with a publicKey and address
22
+ * @example
23
+ * vet.getAddress("m/44'/818'/0'/0").then(o => o.address)
24
+ */
25
+ getAddress(path: string, display?: boolean, chainCode?: boolean, statusCodes?: StatusCodes[]): Promise<{
26
+ publicKey: string;
27
+ address: string;
28
+ chainCode?: string;
29
+ }>;
30
+ /**
31
+ * You can sign a transaction and retrieve v, r, s given the raw transaction and the BIP 32 path of the account to sign.
32
+ *
33
+ * @param path: the BIP32 path to sign the transaction on
34
+ * @param rawTxHex: the raw vechain transaction in hexadecimal to sign
35
+ */
36
+ signTransaction(path: string, rawTxHex: string): Promise<Buffer>;
37
+ }
38
+ //# sourceMappingURL=Vet.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Vet.d.ts","sourceRoot":"","sources":["../src/Vet.ts"],"names":[],"mappings":";AAAA,OAAO,KAAK,SAAS,MAAM,wBAAwB,CAAC;AACpD,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAG1C,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAchC;;;;;;GAMG;AAEH,MAAM,CAAC,OAAO,OAAO,GAAG;IACtB,SAAS,EAAE,SAAS,CAAC;gBAET,SAAS,EAAE,SAAS,EAAE,WAAW,SAAQ;IAS/C,mBAAmB,IAAI,OAAO,CAAC,GAAG,CAAC;IAQzC;;;;;;;;OAQG;IACG,UAAU,CACd,IAAI,EAAE,MAAM,EACZ,OAAO,CAAC,EAAE,OAAO,EACjB,SAAS,CAAC,EAAE,OAAO,EACnB,WAAW,GAAE,WAAW,EAAqB,GAC5C,OAAO,CAAC;QACT,SAAS,EAAE,MAAM,CAAC;QAClB,OAAO,EAAE,MAAM,CAAC;QAChB,SAAS,CAAC,EAAE,MAAM,CAAC;KACpB,CAAC;IAsCF;;;;;OAKG;IACG,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;CAsBvE"}
package/lib/Vet.js ADDED
@@ -0,0 +1,105 @@
1
+ "use strict";
2
+ var __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
+ };
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ const constants_1 = require("./constants");
13
+ const utils_1 = require("./utils");
14
+ const buffer_1 = require("buffer");
15
+ const errors_1 = require("./errors");
16
+ const remapTransactionRelatedErrors = e => {
17
+ if (e && e.statusCode === 0x6a80) {
18
+ return new errors_1.VechainAppPleaseEnableContractDataAndMultiClause("Please enable contract data in Vechain app settings");
19
+ }
20
+ return e;
21
+ };
22
+ /**
23
+ * VeChain API
24
+ *
25
+ * @example
26
+ * import Vet from "@ledgerhq/hw-app-vet";
27
+ * const vet = new Vet(transport)
28
+ */
29
+ class Vet {
30
+ constructor(transport, scrambleKey = "V3T") {
31
+ this.transport = transport;
32
+ transport.decorateAppAPIMethods(this, ["getAppConfiguration", "getAddress", "signTransaction"], scrambleKey);
33
+ }
34
+ getAppConfiguration() {
35
+ return __awaiter(this, void 0, void 0, function* () {
36
+ const response = yield this.transport.send(0xe0, 0x06, 0x00, 0x00, buffer_1.Buffer.alloc(0), [
37
+ constants_1.StatusCodes.OK,
38
+ ]);
39
+ return response.slice(0, 4);
40
+ });
41
+ }
42
+ /**
43
+ * get VeChain address for a given BIP 32 path.
44
+ * @param path a path in BIP 32 format
45
+ * @option display
46
+ * @option chainCode
47
+ * @return an object with a publicKey and address
48
+ * @example
49
+ * vet.getAddress("m/44'/818'/0'/0").then(o => o.address)
50
+ */
51
+ getAddress(path, display, chainCode, statusCodes = [constants_1.StatusCodes.OK]) {
52
+ return __awaiter(this, void 0, void 0, function* () {
53
+ const paths = (0, utils_1.splitPath)(path);
54
+ const buffer = buffer_1.Buffer.alloc(1 + paths.length * 4);
55
+ buffer[0] = paths.length;
56
+ paths.forEach((element, index) => {
57
+ buffer.writeUInt32BE(element, 1 + 4 * index);
58
+ });
59
+ const response = yield this.transport.send(0xe0, 0x02, display ? 0x01 : 0x00, chainCode ? 0x01 : 0x00, buffer, statusCodes);
60
+ const publicKeyLength = response[0];
61
+ const addressLength = response[1 + publicKeyLength];
62
+ const acc = {
63
+ publicKey: response.slice(1, 1 + publicKeyLength).toString("hex"),
64
+ address: "0x" +
65
+ response
66
+ .slice(1 + publicKeyLength + 1, 1 + publicKeyLength + 1 + addressLength)
67
+ .toString("ascii")
68
+ .toLowerCase(),
69
+ };
70
+ if (chainCode) {
71
+ acc.chainCode = response
72
+ .slice(1 + publicKeyLength + 1 + addressLength, 1 + publicKeyLength + 1 + addressLength + 32)
73
+ .toString("hex");
74
+ }
75
+ return acc;
76
+ });
77
+ }
78
+ /**
79
+ * You can sign a transaction and retrieve v, r, s given the raw transaction and the BIP 32 path of the account to sign.
80
+ *
81
+ * @param path: the BIP32 path to sign the transaction on
82
+ * @param rawTxHex: the raw vechain transaction in hexadecimal to sign
83
+ */
84
+ signTransaction(path, rawTxHex) {
85
+ return __awaiter(this, void 0, void 0, function* () {
86
+ const buffers = (0, utils_1.splitRaw)(path, rawTxHex, true);
87
+ const responses = [];
88
+ for (let i = 0; i < buffers.length; i++) {
89
+ const data = buffers[i];
90
+ responses.push(yield this.transport
91
+ .send(0xe0, 0x04, i === 0 ? 0x00 : 0x80, 0x00, data, [constants_1.StatusCodes.OK])
92
+ .catch(e => {
93
+ throw remapTransactionRelatedErrors(e);
94
+ }));
95
+ }
96
+ const lastResponse = responses[responses.length - 1];
97
+ if (lastResponse.length < 65) {
98
+ throw new Error("invalid signature");
99
+ }
100
+ return lastResponse.slice(0, 65);
101
+ });
102
+ }
103
+ }
104
+ exports.default = Vet;
105
+ //# sourceMappingURL=Vet.js.map
package/lib/Vet.js.map ADDED
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Vet.js","sourceRoot":"","sources":["../src/Vet.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,33 @@
1
+ export declare enum StatusCodes {
2
+ PIN_REMAINING_ATTEMPTS = 25536,
3
+ INCORRECT_LENGTH = 26368,
4
+ COMMAND_INCOMPATIBLE_FILE_STRUCTURE = 27009,
5
+ SECURITY_STATUS_NOT_SATISFIED = 27010,
6
+ CONDITIONS_OF_USE_NOT_SATISFIED = 27013,
7
+ INCORRECT_DATA = 27264,
8
+ NOT_ENOUGH_MEMORY_SPACE = 27268,
9
+ REFERENCED_DATA_NOT_FOUND = 27272,
10
+ FILE_ALREADY_EXISTS = 27273,
11
+ INCORRECT_P1_P2 = 27392,
12
+ INS_NOT_SUPPORTED = 27904,
13
+ CLA_NOT_SUPPORTED = 28160,
14
+ TECHNICAL_PROBLEM = 28416,
15
+ OK = 36864,
16
+ MEMORY_PROBLEM = 37440,
17
+ NO_EF_SELECTED = 37888,
18
+ INVALID_OFFSET = 37890,
19
+ FILE_NOT_FOUND = 37892,
20
+ INCONSISTENT_FILE = 37896,
21
+ ALGORITHM_NOT_SUPPORTED = 38020,
22
+ INVALID_KCV = 38021,
23
+ CODE_NOT_INITIALIZED = 38914,
24
+ ACCESS_CONDITION_NOT_FULFILLED = 38916,
25
+ CONTRADICTION_SECRET_CODE_STATUS = 38920,
26
+ CONTRADICTION_INVALIDATION = 38928,
27
+ CODE_BLOCKED = 38976,
28
+ MAX_VALUE_REACHED = 38992,
29
+ GP_AUTH_FAILED = 25344,
30
+ LICENSING = 28482,
31
+ HALTED = 28586
32
+ }
33
+ //# sourceMappingURL=constants.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AAAA,oBAAY,WAAW;IACrB,sBAAsB,QAAS;IAC/B,gBAAgB,QAAS;IACzB,mCAAmC,QAAS;IAC5C,6BAA6B,QAAS;IACtC,+BAA+B,QAAS;IACxC,cAAc,QAAS;IACvB,uBAAuB,QAAS;IAChC,yBAAyB,QAAS;IAClC,mBAAmB,QAAS;IAC5B,eAAe,QAAS;IACxB,iBAAiB,QAAS;IAC1B,iBAAiB,QAAS;IAC1B,iBAAiB,QAAS;IAC1B,EAAE,QAAS;IACX,cAAc,QAAS;IACvB,cAAc,QAAS;IACvB,cAAc,QAAS;IACvB,cAAc,QAAS;IACvB,iBAAiB,QAAS;IAC1B,uBAAuB,QAAS;IAChC,WAAW,QAAS;IACpB,oBAAoB,QAAS;IAC7B,8BAA8B,QAAS;IACvC,gCAAgC,QAAS;IACzC,0BAA0B,QAAS;IACnC,YAAY,QAAS;IACrB,iBAAiB,QAAS;IAC1B,cAAc,QAAS;IACvB,SAAS,QAAS;IAClB,MAAM,QAAS;CAChB"}
@@ -0,0 +1,37 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.StatusCodes = void 0;
4
+ var StatusCodes;
5
+ (function (StatusCodes) {
6
+ StatusCodes[StatusCodes["PIN_REMAINING_ATTEMPTS"] = 25536] = "PIN_REMAINING_ATTEMPTS";
7
+ StatusCodes[StatusCodes["INCORRECT_LENGTH"] = 26368] = "INCORRECT_LENGTH";
8
+ StatusCodes[StatusCodes["COMMAND_INCOMPATIBLE_FILE_STRUCTURE"] = 27009] = "COMMAND_INCOMPATIBLE_FILE_STRUCTURE";
9
+ StatusCodes[StatusCodes["SECURITY_STATUS_NOT_SATISFIED"] = 27010] = "SECURITY_STATUS_NOT_SATISFIED";
10
+ StatusCodes[StatusCodes["CONDITIONS_OF_USE_NOT_SATISFIED"] = 27013] = "CONDITIONS_OF_USE_NOT_SATISFIED";
11
+ StatusCodes[StatusCodes["INCORRECT_DATA"] = 27264] = "INCORRECT_DATA";
12
+ StatusCodes[StatusCodes["NOT_ENOUGH_MEMORY_SPACE"] = 27268] = "NOT_ENOUGH_MEMORY_SPACE";
13
+ StatusCodes[StatusCodes["REFERENCED_DATA_NOT_FOUND"] = 27272] = "REFERENCED_DATA_NOT_FOUND";
14
+ StatusCodes[StatusCodes["FILE_ALREADY_EXISTS"] = 27273] = "FILE_ALREADY_EXISTS";
15
+ StatusCodes[StatusCodes["INCORRECT_P1_P2"] = 27392] = "INCORRECT_P1_P2";
16
+ StatusCodes[StatusCodes["INS_NOT_SUPPORTED"] = 27904] = "INS_NOT_SUPPORTED";
17
+ StatusCodes[StatusCodes["CLA_NOT_SUPPORTED"] = 28160] = "CLA_NOT_SUPPORTED";
18
+ StatusCodes[StatusCodes["TECHNICAL_PROBLEM"] = 28416] = "TECHNICAL_PROBLEM";
19
+ StatusCodes[StatusCodes["OK"] = 36864] = "OK";
20
+ StatusCodes[StatusCodes["MEMORY_PROBLEM"] = 37440] = "MEMORY_PROBLEM";
21
+ StatusCodes[StatusCodes["NO_EF_SELECTED"] = 37888] = "NO_EF_SELECTED";
22
+ StatusCodes[StatusCodes["INVALID_OFFSET"] = 37890] = "INVALID_OFFSET";
23
+ StatusCodes[StatusCodes["FILE_NOT_FOUND"] = 37892] = "FILE_NOT_FOUND";
24
+ StatusCodes[StatusCodes["INCONSISTENT_FILE"] = 37896] = "INCONSISTENT_FILE";
25
+ StatusCodes[StatusCodes["ALGORITHM_NOT_SUPPORTED"] = 38020] = "ALGORITHM_NOT_SUPPORTED";
26
+ StatusCodes[StatusCodes["INVALID_KCV"] = 38021] = "INVALID_KCV";
27
+ StatusCodes[StatusCodes["CODE_NOT_INITIALIZED"] = 38914] = "CODE_NOT_INITIALIZED";
28
+ StatusCodes[StatusCodes["ACCESS_CONDITION_NOT_FULFILLED"] = 38916] = "ACCESS_CONDITION_NOT_FULFILLED";
29
+ StatusCodes[StatusCodes["CONTRADICTION_SECRET_CODE_STATUS"] = 38920] = "CONTRADICTION_SECRET_CODE_STATUS";
30
+ StatusCodes[StatusCodes["CONTRADICTION_INVALIDATION"] = 38928] = "CONTRADICTION_INVALIDATION";
31
+ StatusCodes[StatusCodes["CODE_BLOCKED"] = 38976] = "CODE_BLOCKED";
32
+ StatusCodes[StatusCodes["MAX_VALUE_REACHED"] = 38992] = "MAX_VALUE_REACHED";
33
+ StatusCodes[StatusCodes["GP_AUTH_FAILED"] = 25344] = "GP_AUTH_FAILED";
34
+ StatusCodes[StatusCodes["LICENSING"] = 28482] = "LICENSING";
35
+ StatusCodes[StatusCodes["HALTED"] = 28586] = "HALTED";
36
+ })(StatusCodes = exports.StatusCodes || (exports.StatusCodes = {}));
37
+ //# sourceMappingURL=constants.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"constants.js","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":";;;AAAA,IAAY,WA+BX;AA/BD,WAAY,WAAW;IACrB,qFAA+B,CAAA;IAC/B,yEAAyB,CAAA;IACzB,+GAA4C,CAAA;IAC5C,mGAAsC,CAAA;IACtC,uGAAwC,CAAA;IACxC,qEAAuB,CAAA;IACvB,uFAAgC,CAAA;IAChC,2FAAkC,CAAA;IAClC,+EAA4B,CAAA;IAC5B,uEAAwB,CAAA;IACxB,2EAA0B,CAAA;IAC1B,2EAA0B,CAAA;IAC1B,2EAA0B,CAAA;IAC1B,6CAAW,CAAA;IACX,qEAAuB,CAAA;IACvB,qEAAuB,CAAA;IACvB,qEAAuB,CAAA;IACvB,qEAAuB,CAAA;IACvB,2EAA0B,CAAA;IAC1B,uFAAgC,CAAA;IAChC,+DAAoB,CAAA;IACpB,iFAA6B,CAAA;IAC7B,qGAAuC,CAAA;IACvC,yGAAyC,CAAA;IACzC,6FAAmC,CAAA;IACnC,iEAAqB,CAAA;IACrB,2EAA0B,CAAA;IAC1B,qEAAuB,CAAA;IACvB,2DAAkB,CAAA;IAClB,qDAAe,CAAA;AACjB,CAAC,EA/BW,WAAW,GAAX,mBAAW,KAAX,mBAAW,QA+BtB"}
@@ -0,0 +1,4 @@
1
+ export declare const VechainAppPleaseEnableContractDataAndMultiClause: import("@ledgerhq/errors/lib/helpers").LedgerErrorConstructor<{
2
+ [key: string]: unknown;
3
+ }>;
4
+ //# sourceMappingURL=errors.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,gDAAgD;;EAE5D,CAAC"}
package/lib/errors.js ADDED
@@ -0,0 +1,6 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.VechainAppPleaseEnableContractDataAndMultiClause = void 0;
4
+ const errors_1 = require("@ledgerhq/errors");
5
+ exports.VechainAppPleaseEnableContractDataAndMultiClause = (0, errors_1.createCustomErrorClass)("VechainAppPleaseEnableContractDataAndMultiClause");
6
+ //# sourceMappingURL=errors.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.js","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":";;;AAAA,6CAA0D;AAE7C,QAAA,gDAAgD,GAAG,IAAA,+BAAsB,EACpF,kDAAkD,CACnD,CAAC"}
package/lib/model.d.ts ADDED
@@ -0,0 +1,6 @@
1
+ export interface VETLedgerAccount {
2
+ publicKey: string;
3
+ address: string;
4
+ chainCode?: string;
5
+ }
6
+ //# sourceMappingURL=model.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"model.d.ts","sourceRoot":"","sources":["../src/model.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,gBAAgB;IAC/B,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB"}
package/lib/model.js ADDED
@@ -0,0 +1,3 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ //# sourceMappingURL=model.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"model.js","sourceRoot":"","sources":["../src/model.ts"],"names":[],"mappings":""}
package/lib/utils.d.ts ADDED
@@ -0,0 +1,4 @@
1
+ import { Buffer } from "buffer";
2
+ export declare const splitPath: (path: string) => number[];
3
+ export declare const splitRaw: (path: string, rawHex: string, isTransaction: boolean) => Buffer[];
4
+ //# sourceMappingURL=utils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAEhC,eAAO,MAAM,SAAS,SAAU,MAAM,KAAG,MAAM,EAW9C,CAAC;AAEF,eAAO,MAAM,QAAQ,SAAU,MAAM,UAAU,MAAM,iBAAiB,OAAO,KAAG,MAAM,EA8BrF,CAAC"}
package/lib/utils.js ADDED
@@ -0,0 +1,50 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.splitRaw = exports.splitPath = void 0;
4
+ const buffer_1 = require("buffer");
5
+ const splitPath = (path) => {
6
+ return path
7
+ .split("/")
8
+ .map(elem => {
9
+ let num = parseInt(elem, 10);
10
+ if (elem.length > 1 && elem[elem.length - 1] === "'") {
11
+ num += 0x80000000;
12
+ }
13
+ return num;
14
+ })
15
+ .filter(num => !isNaN(num));
16
+ };
17
+ exports.splitPath = splitPath;
18
+ const splitRaw = (path, rawHex, isTransaction) => {
19
+ const contentByteLength = isTransaction ? 0 : 4;
20
+ const paths = (0, exports.splitPath)(path);
21
+ let offset = 0;
22
+ const raw = buffer_1.Buffer.from(rawHex, "hex");
23
+ const buffers = [];
24
+ while (offset !== raw.length) {
25
+ const maxChunkSize = offset === 0 ? 255 - 1 - paths.length * 4 - contentByteLength : 255;
26
+ const chunkSize = offset + maxChunkSize > raw.length ? raw.length - offset : maxChunkSize;
27
+ const buffer = buffer_1.Buffer.alloc(offset === 0 ? 1 + paths.length * 4 + contentByteLength + chunkSize : chunkSize);
28
+ if (offset === 0) {
29
+ buffer[0] = paths.length;
30
+ paths.forEach((element, index) => {
31
+ buffer.writeUInt32BE(element, 1 + 4 * index);
32
+ });
33
+ if (isTransaction) {
34
+ raw.copy(buffer, 1 + 4 * paths.length, offset, offset + chunkSize);
35
+ }
36
+ else {
37
+ buffer.writeUInt32BE(raw.length, 1 + 4 * paths.length);
38
+ raw.copy(buffer, 1 + 4 * paths.length + 4, offset, offset + chunkSize);
39
+ }
40
+ }
41
+ else {
42
+ raw.copy(buffer, 0, offset, offset + chunkSize);
43
+ }
44
+ buffers.push(buffer);
45
+ offset += chunkSize;
46
+ }
47
+ return buffers;
48
+ };
49
+ exports.splitRaw = splitRaw;
50
+ //# sourceMappingURL=utils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.js","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,38 @@
1
+ /// <reference types="node" />
2
+ import type Transport from "@ledgerhq/hw-transport";
3
+ import { StatusCodes } from "./constants";
4
+ import { Buffer } from "buffer";
5
+ /**
6
+ * VeChain API
7
+ *
8
+ * @example
9
+ * import Vet from "@ledgerhq/hw-app-vet";
10
+ * const vet = new Vet(transport)
11
+ */
12
+ export default class Vet {
13
+ transport: Transport;
14
+ constructor(transport: Transport, scrambleKey?: string);
15
+ getAppConfiguration(): Promise<any>;
16
+ /**
17
+ * get VeChain address for a given BIP 32 path.
18
+ * @param path a path in BIP 32 format
19
+ * @option display
20
+ * @option chainCode
21
+ * @return an object with a publicKey and address
22
+ * @example
23
+ * vet.getAddress("m/44'/818'/0'/0").then(o => o.address)
24
+ */
25
+ getAddress(path: string, display?: boolean, chainCode?: boolean, statusCodes?: StatusCodes[]): Promise<{
26
+ publicKey: string;
27
+ address: string;
28
+ chainCode?: string;
29
+ }>;
30
+ /**
31
+ * You can sign a transaction and retrieve v, r, s given the raw transaction and the BIP 32 path of the account to sign.
32
+ *
33
+ * @param path: the BIP32 path to sign the transaction on
34
+ * @param rawTxHex: the raw vechain transaction in hexadecimal to sign
35
+ */
36
+ signTransaction(path: string, rawTxHex: string): Promise<Buffer>;
37
+ }
38
+ //# sourceMappingURL=Vet.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Vet.d.ts","sourceRoot":"","sources":["../src/Vet.ts"],"names":[],"mappings":";AAAA,OAAO,KAAK,SAAS,MAAM,wBAAwB,CAAC;AACpD,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAG1C,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAchC;;;;;;GAMG;AAEH,MAAM,CAAC,OAAO,OAAO,GAAG;IACtB,SAAS,EAAE,SAAS,CAAC;gBAET,SAAS,EAAE,SAAS,EAAE,WAAW,SAAQ;IAS/C,mBAAmB,IAAI,OAAO,CAAC,GAAG,CAAC;IAQzC;;;;;;;;OAQG;IACG,UAAU,CACd,IAAI,EAAE,MAAM,EACZ,OAAO,CAAC,EAAE,OAAO,EACjB,SAAS,CAAC,EAAE,OAAO,EACnB,WAAW,GAAE,WAAW,EAAqB,GAC5C,OAAO,CAAC;QACT,SAAS,EAAE,MAAM,CAAC;QAClB,OAAO,EAAE,MAAM,CAAC;QAChB,SAAS,CAAC,EAAE,MAAM,CAAC;KACpB,CAAC;IAsCF;;;;;OAKG;IACG,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;CAsBvE"}
package/lib-es/Vet.js ADDED
@@ -0,0 +1,102 @@
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
+ import { StatusCodes } from "./constants";
11
+ import { splitPath, splitRaw } from "./utils";
12
+ import { Buffer } from "buffer";
13
+ import { VechainAppPleaseEnableContractDataAndMultiClause } from "./errors";
14
+ const remapTransactionRelatedErrors = e => {
15
+ if (e && e.statusCode === 0x6a80) {
16
+ return new VechainAppPleaseEnableContractDataAndMultiClause("Please enable contract data in Vechain app settings");
17
+ }
18
+ return e;
19
+ };
20
+ /**
21
+ * VeChain API
22
+ *
23
+ * @example
24
+ * import Vet from "@ledgerhq/hw-app-vet";
25
+ * const vet = new Vet(transport)
26
+ */
27
+ export default class Vet {
28
+ constructor(transport, scrambleKey = "V3T") {
29
+ this.transport = transport;
30
+ transport.decorateAppAPIMethods(this, ["getAppConfiguration", "getAddress", "signTransaction"], scrambleKey);
31
+ }
32
+ getAppConfiguration() {
33
+ return __awaiter(this, void 0, void 0, function* () {
34
+ const response = yield this.transport.send(0xe0, 0x06, 0x00, 0x00, Buffer.alloc(0), [
35
+ StatusCodes.OK,
36
+ ]);
37
+ return response.slice(0, 4);
38
+ });
39
+ }
40
+ /**
41
+ * get VeChain address for a given BIP 32 path.
42
+ * @param path a path in BIP 32 format
43
+ * @option display
44
+ * @option chainCode
45
+ * @return an object with a publicKey and address
46
+ * @example
47
+ * vet.getAddress("m/44'/818'/0'/0").then(o => o.address)
48
+ */
49
+ getAddress(path, display, chainCode, statusCodes = [StatusCodes.OK]) {
50
+ return __awaiter(this, void 0, void 0, function* () {
51
+ const paths = splitPath(path);
52
+ const buffer = Buffer.alloc(1 + paths.length * 4);
53
+ buffer[0] = paths.length;
54
+ paths.forEach((element, index) => {
55
+ buffer.writeUInt32BE(element, 1 + 4 * index);
56
+ });
57
+ const response = yield this.transport.send(0xe0, 0x02, display ? 0x01 : 0x00, chainCode ? 0x01 : 0x00, buffer, statusCodes);
58
+ const publicKeyLength = response[0];
59
+ const addressLength = response[1 + publicKeyLength];
60
+ const acc = {
61
+ publicKey: response.slice(1, 1 + publicKeyLength).toString("hex"),
62
+ address: "0x" +
63
+ response
64
+ .slice(1 + publicKeyLength + 1, 1 + publicKeyLength + 1 + addressLength)
65
+ .toString("ascii")
66
+ .toLowerCase(),
67
+ };
68
+ if (chainCode) {
69
+ acc.chainCode = response
70
+ .slice(1 + publicKeyLength + 1 + addressLength, 1 + publicKeyLength + 1 + addressLength + 32)
71
+ .toString("hex");
72
+ }
73
+ return acc;
74
+ });
75
+ }
76
+ /**
77
+ * You can sign a transaction and retrieve v, r, s given the raw transaction and the BIP 32 path of the account to sign.
78
+ *
79
+ * @param path: the BIP32 path to sign the transaction on
80
+ * @param rawTxHex: the raw vechain transaction in hexadecimal to sign
81
+ */
82
+ signTransaction(path, rawTxHex) {
83
+ return __awaiter(this, void 0, void 0, function* () {
84
+ const buffers = splitRaw(path, rawTxHex, true);
85
+ const responses = [];
86
+ for (let i = 0; i < buffers.length; i++) {
87
+ const data = buffers[i];
88
+ responses.push(yield this.transport
89
+ .send(0xe0, 0x04, i === 0 ? 0x00 : 0x80, 0x00, data, [StatusCodes.OK])
90
+ .catch(e => {
91
+ throw remapTransactionRelatedErrors(e);
92
+ }));
93
+ }
94
+ const lastResponse = responses[responses.length - 1];
95
+ if (lastResponse.length < 65) {
96
+ throw new Error("invalid signature");
97
+ }
98
+ return lastResponse.slice(0, 65);
99
+ });
100
+ }
101
+ }
102
+ //# sourceMappingURL=Vet.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Vet.js","sourceRoot":"","sources":["../src/Vet.ts"],"names":[],"mappings":";;;;;;;;;AACA,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAE1C,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAC9C,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAEhC,OAAO,EAAE,gDAAgD,EAAE,MAAM,UAAU,CAAC;AAE5E,MAAM,6BAA6B,GAAG,CAAC,CAAC,EAAE;IACxC,IAAI,CAAC,IAAI,CAAC,CAAC,UAAU,KAAK,MAAM,EAAE;QAChC,OAAO,IAAI,gDAAgD,CACzD,qDAAqD,CACtD,CAAC;KACH;IAED,OAAO,CAAC,CAAC;AACX,CAAC,CAAC;AAEF;;;;;;GAMG;AAEH,MAAM,CAAC,OAAO,OAAO,GAAG;IAGtB,YAAY,SAAoB,EAAE,WAAW,GAAG,KAAK;QACnD,IAAI,CAAC,SAAS,GAAG,SAAS,CAAC;QAC3B,SAAS,CAAC,qBAAqB,CAC7B,IAAI,EACJ,CAAC,qBAAqB,EAAE,YAAY,EAAE,iBAAiB,CAAC,EACxD,WAAW,CACZ,CAAC;IACJ,CAAC;IAEK,mBAAmB;;YACvB,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE;gBAClF,WAAW,CAAC,EAAE;aACf,CAAC,CAAC;YAEH,OAAO,QAAQ,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;QAC9B,CAAC;KAAA;IAED;;;;;;;;OAQG;IACG,UAAU,CACd,IAAY,EACZ,OAAiB,EACjB,SAAmB,EACnB,cAA6B,CAAC,WAAW,CAAC,EAAE,CAAC;;YAM7C,MAAM,KAAK,GAAG,SAAS,CAAC,IAAI,CAAC,CAAC;YAC9B,MAAM,MAAM,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC,GAAG,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;YAClD,MAAM,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,MAAM,CAAC;YACzB,KAAK,CAAC,OAAO,CAAC,CAAC,OAAO,EAAE,KAAK,EAAE,EAAE;gBAC/B,MAAM,CAAC,aAAa,CAAC,OAAO,EAAE,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC,CAAC;YAC/C,CAAC,CAAC,CAAC;YACH,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,SAAS,CAAC,IAAI,CACxC,IAAI,EACJ,IAAI,EACJ,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,EACrB,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,EACvB,MAAM,EACN,WAAW,CACZ,CAAC;YAEF,MAAM,eAAe,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAC;YACpC,MAAM,aAAa,GAAG,QAAQ,CAAC,CAAC,GAAG,eAAe,CAAC,CAAC;YACpD,MAAM,GAAG,GAAqB;gBAC5B,SAAS,EAAE,QAAQ,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,GAAG,eAAe,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC;gBACjE,OAAO,EACL,IAAI;oBACJ,QAAQ;yBACL,KAAK,CAAC,CAAC,GAAG,eAAe,GAAG,CAAC,EAAE,CAAC,GAAG,eAAe,GAAG,CAAC,GAAG,aAAa,CAAC;yBACvE,QAAQ,CAAC,OAAO,CAAC;yBACjB,WAAW,EAAE;aACnB,CAAC;YACF,IAAI,SAAS,EAAE;gBACb,GAAG,CAAC,SAAS,GAAG,QAAQ;qBACrB,KAAK,CACJ,CAAC,GAAG,eAAe,GAAG,CAAC,GAAG,aAAa,EACvC,CAAC,GAAG,eAAe,GAAG,CAAC,GAAG,aAAa,GAAG,EAAE,CAC7C;qBACA,QAAQ,CAAC,KAAK,CAAC,CAAC;aACpB;YACD,OAAO,GAAG,CAAC;QACb,CAAC;KAAA;IAED;;;;;OAKG;IACG,eAAe,CAAC,IAAY,EAAE,QAAgB;;YAClD,MAAM,OAAO,GAAG,QAAQ,CAAC,IAAI,EAAE,QAAQ,EAAE,IAAI,CAAC,CAAC;YAC/C,MAAM,SAAS,GAAG,EAAc,CAAC;YAEjC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE;gBACvC,MAAM,IAAI,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;gBACxB,SAAS,CAAC,IAAI,CACZ,MAAM,IAAI,CAAC,SAAS;qBACjB,IAAI,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,WAAW,CAAC,EAAE,CAAC,CAAC;qBACrE,KAAK,CAAC,CAAC,CAAC,EAAE;oBACT,MAAM,6BAA6B,CAAC,CAAC,CAAC,CAAC;gBACzC,CAAC,CAAC,CACL,CAAC;aACH;YAED,MAAM,YAAY,GAAG,SAAS,CAAC,SAAS,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;YACrD,IAAI,YAAY,CAAC,MAAM,GAAG,EAAE,EAAE;gBAC5B,MAAM,IAAI,KAAK,CAAC,mBAAmB,CAAC,CAAC;aACtC;YAED,OAAO,YAAY,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;QACnC,CAAC;KAAA;CACF"}
@@ -0,0 +1,33 @@
1
+ export declare enum StatusCodes {
2
+ PIN_REMAINING_ATTEMPTS = 25536,
3
+ INCORRECT_LENGTH = 26368,
4
+ COMMAND_INCOMPATIBLE_FILE_STRUCTURE = 27009,
5
+ SECURITY_STATUS_NOT_SATISFIED = 27010,
6
+ CONDITIONS_OF_USE_NOT_SATISFIED = 27013,
7
+ INCORRECT_DATA = 27264,
8
+ NOT_ENOUGH_MEMORY_SPACE = 27268,
9
+ REFERENCED_DATA_NOT_FOUND = 27272,
10
+ FILE_ALREADY_EXISTS = 27273,
11
+ INCORRECT_P1_P2 = 27392,
12
+ INS_NOT_SUPPORTED = 27904,
13
+ CLA_NOT_SUPPORTED = 28160,
14
+ TECHNICAL_PROBLEM = 28416,
15
+ OK = 36864,
16
+ MEMORY_PROBLEM = 37440,
17
+ NO_EF_SELECTED = 37888,
18
+ INVALID_OFFSET = 37890,
19
+ FILE_NOT_FOUND = 37892,
20
+ INCONSISTENT_FILE = 37896,
21
+ ALGORITHM_NOT_SUPPORTED = 38020,
22
+ INVALID_KCV = 38021,
23
+ CODE_NOT_INITIALIZED = 38914,
24
+ ACCESS_CONDITION_NOT_FULFILLED = 38916,
25
+ CONTRADICTION_SECRET_CODE_STATUS = 38920,
26
+ CONTRADICTION_INVALIDATION = 38928,
27
+ CODE_BLOCKED = 38976,
28
+ MAX_VALUE_REACHED = 38992,
29
+ GP_AUTH_FAILED = 25344,
30
+ LICENSING = 28482,
31
+ HALTED = 28586
32
+ }
33
+ //# sourceMappingURL=constants.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AAAA,oBAAY,WAAW;IACrB,sBAAsB,QAAS;IAC/B,gBAAgB,QAAS;IACzB,mCAAmC,QAAS;IAC5C,6BAA6B,QAAS;IACtC,+BAA+B,QAAS;IACxC,cAAc,QAAS;IACvB,uBAAuB,QAAS;IAChC,yBAAyB,QAAS;IAClC,mBAAmB,QAAS;IAC5B,eAAe,QAAS;IACxB,iBAAiB,QAAS;IAC1B,iBAAiB,QAAS;IAC1B,iBAAiB,QAAS;IAC1B,EAAE,QAAS;IACX,cAAc,QAAS;IACvB,cAAc,QAAS;IACvB,cAAc,QAAS;IACvB,cAAc,QAAS;IACvB,iBAAiB,QAAS;IAC1B,uBAAuB,QAAS;IAChC,WAAW,QAAS;IACpB,oBAAoB,QAAS;IAC7B,8BAA8B,QAAS;IACvC,gCAAgC,QAAS;IACzC,0BAA0B,QAAS;IACnC,YAAY,QAAS;IACrB,iBAAiB,QAAS;IAC1B,cAAc,QAAS;IACvB,SAAS,QAAS;IAClB,MAAM,QAAS;CAChB"}
@@ -0,0 +1,34 @@
1
+ export var StatusCodes;
2
+ (function (StatusCodes) {
3
+ StatusCodes[StatusCodes["PIN_REMAINING_ATTEMPTS"] = 25536] = "PIN_REMAINING_ATTEMPTS";
4
+ StatusCodes[StatusCodes["INCORRECT_LENGTH"] = 26368] = "INCORRECT_LENGTH";
5
+ StatusCodes[StatusCodes["COMMAND_INCOMPATIBLE_FILE_STRUCTURE"] = 27009] = "COMMAND_INCOMPATIBLE_FILE_STRUCTURE";
6
+ StatusCodes[StatusCodes["SECURITY_STATUS_NOT_SATISFIED"] = 27010] = "SECURITY_STATUS_NOT_SATISFIED";
7
+ StatusCodes[StatusCodes["CONDITIONS_OF_USE_NOT_SATISFIED"] = 27013] = "CONDITIONS_OF_USE_NOT_SATISFIED";
8
+ StatusCodes[StatusCodes["INCORRECT_DATA"] = 27264] = "INCORRECT_DATA";
9
+ StatusCodes[StatusCodes["NOT_ENOUGH_MEMORY_SPACE"] = 27268] = "NOT_ENOUGH_MEMORY_SPACE";
10
+ StatusCodes[StatusCodes["REFERENCED_DATA_NOT_FOUND"] = 27272] = "REFERENCED_DATA_NOT_FOUND";
11
+ StatusCodes[StatusCodes["FILE_ALREADY_EXISTS"] = 27273] = "FILE_ALREADY_EXISTS";
12
+ StatusCodes[StatusCodes["INCORRECT_P1_P2"] = 27392] = "INCORRECT_P1_P2";
13
+ StatusCodes[StatusCodes["INS_NOT_SUPPORTED"] = 27904] = "INS_NOT_SUPPORTED";
14
+ StatusCodes[StatusCodes["CLA_NOT_SUPPORTED"] = 28160] = "CLA_NOT_SUPPORTED";
15
+ StatusCodes[StatusCodes["TECHNICAL_PROBLEM"] = 28416] = "TECHNICAL_PROBLEM";
16
+ StatusCodes[StatusCodes["OK"] = 36864] = "OK";
17
+ StatusCodes[StatusCodes["MEMORY_PROBLEM"] = 37440] = "MEMORY_PROBLEM";
18
+ StatusCodes[StatusCodes["NO_EF_SELECTED"] = 37888] = "NO_EF_SELECTED";
19
+ StatusCodes[StatusCodes["INVALID_OFFSET"] = 37890] = "INVALID_OFFSET";
20
+ StatusCodes[StatusCodes["FILE_NOT_FOUND"] = 37892] = "FILE_NOT_FOUND";
21
+ StatusCodes[StatusCodes["INCONSISTENT_FILE"] = 37896] = "INCONSISTENT_FILE";
22
+ StatusCodes[StatusCodes["ALGORITHM_NOT_SUPPORTED"] = 38020] = "ALGORITHM_NOT_SUPPORTED";
23
+ StatusCodes[StatusCodes["INVALID_KCV"] = 38021] = "INVALID_KCV";
24
+ StatusCodes[StatusCodes["CODE_NOT_INITIALIZED"] = 38914] = "CODE_NOT_INITIALIZED";
25
+ StatusCodes[StatusCodes["ACCESS_CONDITION_NOT_FULFILLED"] = 38916] = "ACCESS_CONDITION_NOT_FULFILLED";
26
+ StatusCodes[StatusCodes["CONTRADICTION_SECRET_CODE_STATUS"] = 38920] = "CONTRADICTION_SECRET_CODE_STATUS";
27
+ StatusCodes[StatusCodes["CONTRADICTION_INVALIDATION"] = 38928] = "CONTRADICTION_INVALIDATION";
28
+ StatusCodes[StatusCodes["CODE_BLOCKED"] = 38976] = "CODE_BLOCKED";
29
+ StatusCodes[StatusCodes["MAX_VALUE_REACHED"] = 38992] = "MAX_VALUE_REACHED";
30
+ StatusCodes[StatusCodes["GP_AUTH_FAILED"] = 25344] = "GP_AUTH_FAILED";
31
+ StatusCodes[StatusCodes["LICENSING"] = 28482] = "LICENSING";
32
+ StatusCodes[StatusCodes["HALTED"] = 28586] = "HALTED";
33
+ })(StatusCodes || (StatusCodes = {}));
34
+ //# sourceMappingURL=constants.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"constants.js","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AAAA,MAAM,CAAN,IAAY,WA+BX;AA/BD,WAAY,WAAW;IACrB,qFAA+B,CAAA;IAC/B,yEAAyB,CAAA;IACzB,+GAA4C,CAAA;IAC5C,mGAAsC,CAAA;IACtC,uGAAwC,CAAA;IACxC,qEAAuB,CAAA;IACvB,uFAAgC,CAAA;IAChC,2FAAkC,CAAA;IAClC,+EAA4B,CAAA;IAC5B,uEAAwB,CAAA;IACxB,2EAA0B,CAAA;IAC1B,2EAA0B,CAAA;IAC1B,2EAA0B,CAAA;IAC1B,6CAAW,CAAA;IACX,qEAAuB,CAAA;IACvB,qEAAuB,CAAA;IACvB,qEAAuB,CAAA;IACvB,qEAAuB,CAAA;IACvB,2EAA0B,CAAA;IAC1B,uFAAgC,CAAA;IAChC,+DAAoB,CAAA;IACpB,iFAA6B,CAAA;IAC7B,qGAAuC,CAAA;IACvC,yGAAyC,CAAA;IACzC,6FAAmC,CAAA;IACnC,iEAAqB,CAAA;IACrB,2EAA0B,CAAA;IAC1B,qEAAuB,CAAA;IACvB,2DAAkB,CAAA;IAClB,qDAAe,CAAA;AACjB,CAAC,EA/BW,WAAW,KAAX,WAAW,QA+BtB"}
@@ -0,0 +1,4 @@
1
+ export declare const VechainAppPleaseEnableContractDataAndMultiClause: import("@ledgerhq/errors/lib/helpers").LedgerErrorConstructor<{
2
+ [key: string]: unknown;
3
+ }>;
4
+ //# sourceMappingURL=errors.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,gDAAgD;;EAE5D,CAAC"}
@@ -0,0 +1,3 @@
1
+ import { createCustomErrorClass } from "@ledgerhq/errors";
2
+ export const VechainAppPleaseEnableContractDataAndMultiClause = createCustomErrorClass("VechainAppPleaseEnableContractDataAndMultiClause");
3
+ //# sourceMappingURL=errors.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.js","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,sBAAsB,EAAE,MAAM,kBAAkB,CAAC;AAE1D,MAAM,CAAC,MAAM,gDAAgD,GAAG,sBAAsB,CACpF,kDAAkD,CACnD,CAAC"}
@@ -0,0 +1,6 @@
1
+ export interface VETLedgerAccount {
2
+ publicKey: string;
3
+ address: string;
4
+ chainCode?: string;
5
+ }
6
+ //# sourceMappingURL=model.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"model.d.ts","sourceRoot":"","sources":["../src/model.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,gBAAgB;IAC/B,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=model.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"model.js","sourceRoot":"","sources":["../src/model.ts"],"names":[],"mappings":""}
@@ -0,0 +1,4 @@
1
+ import { Buffer } from "buffer";
2
+ export declare const splitPath: (path: string) => number[];
3
+ export declare const splitRaw: (path: string, rawHex: string, isTransaction: boolean) => Buffer[];
4
+ //# sourceMappingURL=utils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAEhC,eAAO,MAAM,SAAS,SAAU,MAAM,KAAG,MAAM,EAW9C,CAAC;AAEF,eAAO,MAAM,QAAQ,SAAU,MAAM,UAAU,MAAM,iBAAiB,OAAO,KAAG,MAAM,EA8BrF,CAAC"}
@@ -0,0 +1,45 @@
1
+ import { Buffer } from "buffer";
2
+ export const splitPath = (path) => {
3
+ return path
4
+ .split("/")
5
+ .map(elem => {
6
+ let num = parseInt(elem, 10);
7
+ if (elem.length > 1 && elem[elem.length - 1] === "'") {
8
+ num += 0x80000000;
9
+ }
10
+ return num;
11
+ })
12
+ .filter(num => !isNaN(num));
13
+ };
14
+ export const splitRaw = (path, rawHex, isTransaction) => {
15
+ const contentByteLength = isTransaction ? 0 : 4;
16
+ const paths = splitPath(path);
17
+ let offset = 0;
18
+ const raw = Buffer.from(rawHex, "hex");
19
+ const buffers = [];
20
+ while (offset !== raw.length) {
21
+ const maxChunkSize = offset === 0 ? 255 - 1 - paths.length * 4 - contentByteLength : 255;
22
+ const chunkSize = offset + maxChunkSize > raw.length ? raw.length - offset : maxChunkSize;
23
+ const buffer = Buffer.alloc(offset === 0 ? 1 + paths.length * 4 + contentByteLength + chunkSize : chunkSize);
24
+ if (offset === 0) {
25
+ buffer[0] = paths.length;
26
+ paths.forEach((element, index) => {
27
+ buffer.writeUInt32BE(element, 1 + 4 * index);
28
+ });
29
+ if (isTransaction) {
30
+ raw.copy(buffer, 1 + 4 * paths.length, offset, offset + chunkSize);
31
+ }
32
+ else {
33
+ buffer.writeUInt32BE(raw.length, 1 + 4 * paths.length);
34
+ raw.copy(buffer, 1 + 4 * paths.length + 4, offset, offset + chunkSize);
35
+ }
36
+ }
37
+ else {
38
+ raw.copy(buffer, 0, offset, offset + chunkSize);
39
+ }
40
+ buffers.push(buffer);
41
+ offset += chunkSize;
42
+ }
43
+ return buffers;
44
+ };
45
+ //# sourceMappingURL=utils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.js","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,58 @@
1
+ {
2
+ "name": "@ledgerhq/hw-app-vet",
3
+ "version": "0.1.0-nightly.0",
4
+ "description": "Ledger Hardware Wallet VeChain Application API",
5
+ "keywords": [
6
+ "Ledger",
7
+ "LedgerWallet",
8
+ "VeChain",
9
+ "vet",
10
+ "vtho",
11
+ "VeThor",
12
+ "NanoS",
13
+ "Hardware Wallet"
14
+ ],
15
+ "repository": {
16
+ "type": "git",
17
+ "url": "https://github.com/LedgerHQ/ledger-live.git"
18
+ },
19
+ "bugs": {
20
+ "url": "https://github.com/LedgerHQ/ledger-live/issues"
21
+ },
22
+ "homepage": "https://github.com/LedgerHQ/ledger-live/tree/develop/libs/ledgerjs/packages/hw-app-vet",
23
+ "publishConfig": {
24
+ "access": "public"
25
+ },
26
+ "main": "lib/Vet.js",
27
+ "module": "lib-es/Vet.js",
28
+ "dependencies": {
29
+ "thor-devkit": "^2.0.6",
30
+ "@ledgerhq/cryptoassets": "^11.2.0-nightly.2",
31
+ "@ledgerhq/errors": "^6.16.0-nightly.2",
32
+ "@ledgerhq/hw-transport": "^6.30.0-nightly.2",
33
+ "@ledgerhq/hw-transport-mocker": "^6.28.0-nightly.2",
34
+ "@ledgerhq/logs": "^6.12.0-nightly.0"
35
+ },
36
+ "devDependencies": {
37
+ "@types/jest": "^29.5.0",
38
+ "@types/node": "^18.15.3",
39
+ "documentation": "14.0.2",
40
+ "jest": "^28.1.1",
41
+ "source-map-support": "^0.5.21",
42
+ "ts-jest": "^28.0.5",
43
+ "ts-node": "^10.4.0",
44
+ "typescript": "^4",
45
+ "@ledgerhq/hw-transport-mocker": "^6.28.0-nightly.2"
46
+ },
47
+ "gitHead": "dd0dea64b58e5a9125c8a422dcffd29e5ef6abec",
48
+ "scripts": {
49
+ "clean": "rimraf lib lib-es",
50
+ "build": "tsc && tsc -m ES6 --outDir lib-es",
51
+ "prewatch": "pnpm build",
52
+ "watch": "tsc --watch",
53
+ "doc": "documentation readme src/** --section=API --pe ts --re ts --re d.ts",
54
+ "lint": "eslint ./src --no-error-on-unmatched-pattern --ext .ts,.tsx",
55
+ "lint:fix": "pnpm lint --fix",
56
+ "test": "jest"
57
+ }
58
+ }
package/src/Vet.ts ADDED
@@ -0,0 +1,131 @@
1
+ import type Transport from "@ledgerhq/hw-transport";
2
+ import { StatusCodes } from "./constants";
3
+ import { VETLedgerAccount } from "./model";
4
+ import { splitPath, splitRaw } from "./utils";
5
+ import { Buffer } from "buffer";
6
+
7
+ import { VechainAppPleaseEnableContractDataAndMultiClause } from "./errors";
8
+
9
+ const remapTransactionRelatedErrors = e => {
10
+ if (e && e.statusCode === 0x6a80) {
11
+ return new VechainAppPleaseEnableContractDataAndMultiClause(
12
+ "Please enable contract data in Vechain app settings",
13
+ );
14
+ }
15
+
16
+ return e;
17
+ };
18
+
19
+ /**
20
+ * VeChain API
21
+ *
22
+ * @example
23
+ * import Vet from "@ledgerhq/hw-app-vet";
24
+ * const vet = new Vet(transport)
25
+ */
26
+
27
+ export default class Vet {
28
+ transport: Transport;
29
+
30
+ constructor(transport: Transport, scrambleKey = "V3T") {
31
+ this.transport = transport;
32
+ transport.decorateAppAPIMethods(
33
+ this,
34
+ ["getAppConfiguration", "getAddress", "signTransaction"],
35
+ scrambleKey,
36
+ );
37
+ }
38
+
39
+ async getAppConfiguration(): Promise<any> {
40
+ const response = await this.transport.send(0xe0, 0x06, 0x00, 0x00, Buffer.alloc(0), [
41
+ StatusCodes.OK,
42
+ ]);
43
+
44
+ return response.slice(0, 4);
45
+ }
46
+
47
+ /**
48
+ * get VeChain address for a given BIP 32 path.
49
+ * @param path a path in BIP 32 format
50
+ * @option display
51
+ * @option chainCode
52
+ * @return an object with a publicKey and address
53
+ * @example
54
+ * vet.getAddress("m/44'/818'/0'/0").then(o => o.address)
55
+ */
56
+ async getAddress(
57
+ path: string,
58
+ display?: boolean,
59
+ chainCode?: boolean,
60
+ statusCodes: StatusCodes[] = [StatusCodes.OK],
61
+ ): Promise<{
62
+ publicKey: string;
63
+ address: string;
64
+ chainCode?: string;
65
+ }> {
66
+ const paths = splitPath(path);
67
+ const buffer = Buffer.alloc(1 + paths.length * 4);
68
+ buffer[0] = paths.length;
69
+ paths.forEach((element, index) => {
70
+ buffer.writeUInt32BE(element, 1 + 4 * index);
71
+ });
72
+ const response = await this.transport.send(
73
+ 0xe0,
74
+ 0x02,
75
+ display ? 0x01 : 0x00,
76
+ chainCode ? 0x01 : 0x00,
77
+ buffer,
78
+ statusCodes,
79
+ );
80
+
81
+ const publicKeyLength = response[0];
82
+ const addressLength = response[1 + publicKeyLength];
83
+ const acc: VETLedgerAccount = {
84
+ publicKey: response.slice(1, 1 + publicKeyLength).toString("hex"),
85
+ address:
86
+ "0x" +
87
+ response
88
+ .slice(1 + publicKeyLength + 1, 1 + publicKeyLength + 1 + addressLength)
89
+ .toString("ascii")
90
+ .toLowerCase(),
91
+ };
92
+ if (chainCode) {
93
+ acc.chainCode = response
94
+ .slice(
95
+ 1 + publicKeyLength + 1 + addressLength,
96
+ 1 + publicKeyLength + 1 + addressLength + 32,
97
+ )
98
+ .toString("hex");
99
+ }
100
+ return acc;
101
+ }
102
+
103
+ /**
104
+ * You can sign a transaction and retrieve v, r, s given the raw transaction and the BIP 32 path of the account to sign.
105
+ *
106
+ * @param path: the BIP32 path to sign the transaction on
107
+ * @param rawTxHex: the raw vechain transaction in hexadecimal to sign
108
+ */
109
+ async signTransaction(path: string, rawTxHex: string): Promise<Buffer> {
110
+ const buffers = splitRaw(path, rawTxHex, true);
111
+ const responses = [] as Buffer[];
112
+
113
+ for (let i = 0; i < buffers.length; i++) {
114
+ const data = buffers[i];
115
+ responses.push(
116
+ await this.transport
117
+ .send(0xe0, 0x04, i === 0 ? 0x00 : 0x80, 0x00, data, [StatusCodes.OK])
118
+ .catch(e => {
119
+ throw remapTransactionRelatedErrors(e);
120
+ }),
121
+ );
122
+ }
123
+
124
+ const lastResponse = responses[responses.length - 1];
125
+ if (lastResponse.length < 65) {
126
+ throw new Error("invalid signature");
127
+ }
128
+
129
+ return lastResponse.slice(0, 65);
130
+ }
131
+ }
@@ -0,0 +1,32 @@
1
+ export enum StatusCodes {
2
+ PIN_REMAINING_ATTEMPTS = 0x63c0,
3
+ INCORRECT_LENGTH = 0x6700,
4
+ COMMAND_INCOMPATIBLE_FILE_STRUCTURE = 0x6981,
5
+ SECURITY_STATUS_NOT_SATISFIED = 0x6982,
6
+ CONDITIONS_OF_USE_NOT_SATISFIED = 0x6985,
7
+ INCORRECT_DATA = 0x6a80,
8
+ NOT_ENOUGH_MEMORY_SPACE = 0x6a84,
9
+ REFERENCED_DATA_NOT_FOUND = 0x6a88,
10
+ FILE_ALREADY_EXISTS = 0x6a89,
11
+ INCORRECT_P1_P2 = 0x6b00,
12
+ INS_NOT_SUPPORTED = 0x6d00,
13
+ CLA_NOT_SUPPORTED = 0x6e00,
14
+ TECHNICAL_PROBLEM = 0x6f00,
15
+ OK = 0x9000,
16
+ MEMORY_PROBLEM = 0x9240,
17
+ NO_EF_SELECTED = 0x9400,
18
+ INVALID_OFFSET = 0x9402,
19
+ FILE_NOT_FOUND = 0x9404,
20
+ INCONSISTENT_FILE = 0x9408,
21
+ ALGORITHM_NOT_SUPPORTED = 0x9484,
22
+ INVALID_KCV = 0x9485,
23
+ CODE_NOT_INITIALIZED = 0x9802,
24
+ ACCESS_CONDITION_NOT_FULFILLED = 0x9804,
25
+ CONTRADICTION_SECRET_CODE_STATUS = 0x9808,
26
+ CONTRADICTION_INVALIDATION = 0x9810,
27
+ CODE_BLOCKED = 0x9840,
28
+ MAX_VALUE_REACHED = 0x9850,
29
+ GP_AUTH_FAILED = 0x6300,
30
+ LICENSING = 0x6f42,
31
+ HALTED = 0x6faa,
32
+ }
package/src/errors.ts ADDED
@@ -0,0 +1,5 @@
1
+ import { createCustomErrorClass } from "@ledgerhq/errors";
2
+
3
+ export const VechainAppPleaseEnableContractDataAndMultiClause = createCustomErrorClass(
4
+ "VechainAppPleaseEnableContractDataAndMultiClause",
5
+ );
package/src/model.ts ADDED
@@ -0,0 +1,5 @@
1
+ export interface VETLedgerAccount {
2
+ publicKey: string;
3
+ address: string;
4
+ chainCode?: string;
5
+ }
package/src/utils.ts ADDED
@@ -0,0 +1,46 @@
1
+ import { Buffer } from "buffer";
2
+
3
+ export const splitPath = (path: string): number[] => {
4
+ return path
5
+ .split("/")
6
+ .map(elem => {
7
+ let num = parseInt(elem, 10);
8
+ if (elem.length > 1 && elem[elem.length - 1] === "'") {
9
+ num += 0x80000000;
10
+ }
11
+ return num;
12
+ })
13
+ .filter(num => !isNaN(num));
14
+ };
15
+
16
+ export const splitRaw = (path: string, rawHex: string, isTransaction: boolean): Buffer[] => {
17
+ const contentByteLength = isTransaction ? 0 : 4;
18
+ const paths = splitPath(path);
19
+ let offset = 0;
20
+ const raw = Buffer.from(rawHex, "hex");
21
+ const buffers: Buffer[] = [];
22
+ while (offset !== raw.length) {
23
+ const maxChunkSize = offset === 0 ? 255 - 1 - paths.length * 4 - contentByteLength : 255;
24
+ const chunkSize = offset + maxChunkSize > raw.length ? raw.length - offset : maxChunkSize;
25
+ const buffer = Buffer.alloc(
26
+ offset === 0 ? 1 + paths.length * 4 + contentByteLength + chunkSize : chunkSize,
27
+ );
28
+ if (offset === 0) {
29
+ buffer[0] = paths.length;
30
+ paths.forEach((element, index) => {
31
+ buffer.writeUInt32BE(element, 1 + 4 * index);
32
+ });
33
+ if (isTransaction) {
34
+ raw.copy(buffer, 1 + 4 * paths.length, offset, offset + chunkSize);
35
+ } else {
36
+ buffer.writeUInt32BE(raw.length, 1 + 4 * paths.length);
37
+ raw.copy(buffer, 1 + 4 * paths.length + 4, offset, offset + chunkSize);
38
+ }
39
+ } else {
40
+ raw.copy(buffer, 0, offset, offset + chunkSize);
41
+ }
42
+ buffers.push(buffer);
43
+ offset += chunkSize;
44
+ }
45
+ return buffers;
46
+ };
@@ -0,0 +1,62 @@
1
+ import { openTransportReplayer, RecordStore } from "@ledgerhq/hw-transport-mocker";
2
+ import Vet from "../src/Vet";
3
+ import { Transaction as ThorTransaction } from "thor-devkit";
4
+
5
+ test("getAppConfiguration", async () => {
6
+ const transport = await openTransportReplayer(
7
+ RecordStore.fromString(`
8
+ => e006000000
9
+ <= 030100079000
10
+ `),
11
+ );
12
+ const vet = new Vet(transport);
13
+ const result = await vet.getAppConfiguration();
14
+ expect({ version: result[1] + "." + result[2] + "." + result[3] }).toEqual({
15
+ version: "1.0.7",
16
+ });
17
+ });
18
+
19
+ test("Get address", async () => {
20
+ const transport = await openTransportReplayer(
21
+ RecordStore.fromString(`
22
+ => e002000015058000002c80000332800000000000000000000000
23
+ <= 410482c44bc99cdf08d4360c97fbf62d387288ab75c576926943ad90059002720e93f58799391393c98ad41136aa4ac871b103d25cb9a88f1aadd7dbbe3c7794888928333234373631393364346133323438383332326666426239383335613763463263376532323032439000
24
+ `),
25
+ );
26
+ const vet = new Vet(transport);
27
+ const { address } = await vet.getAddress("44'/818'/0'/0/0");
28
+ expect(address).toEqual("0x32476193d4a32488322ffbb9835a7cf2c7e2202c");
29
+ });
30
+
31
+ test("signMessage", async () => {
32
+ const transport = await openTransportReplayer(
33
+ RecordStore.fromString(`
34
+ => e004000037058000002c80000332800000000000000000000000e1278012d8d7940000000000000000000000000000000000000000808080808080c0
35
+ <= dd0ad907f6cfdd068226999eee0d20789732905270a7c4ed385872599f40978e043a5d7a15e396e59e9c9e921be5f4e02e3b6284b8cf835443f4123ca20b5b35009000
36
+ `),
37
+ );
38
+
39
+ const unsigned = new ThorTransaction({
40
+ chainTag: 39,
41
+ blockRef: "0x0000000000000000",
42
+ expiration: 18,
43
+ clauses: [
44
+ {
45
+ to: "0x0000000000000000000000000000000000000000",
46
+ value: "0",
47
+ data: "0x",
48
+ },
49
+ ],
50
+ gasPriceCoef: 0,
51
+ gas: "0",
52
+ dependsOn: null,
53
+ nonce: 0,
54
+ });
55
+
56
+ const vet = new Vet(transport);
57
+ const res = await vet.signTransaction("44'/818'/0'/0/0", unsigned.encode().toString("hex"));
58
+
59
+ expect(res.toString("hex")).toEqual(
60
+ "dd0ad907f6cfdd068226999eee0d20789732905270a7c4ed385872599f40978e043a5d7a15e396e59e9c9e921be5f4e02e3b6284b8cf835443f4123ca20b5b3500",
61
+ );
62
+ });
package/tsconfig.json ADDED
@@ -0,0 +1,8 @@
1
+ {
2
+ "extends": "../../tsconfig.json",
3
+ "compilerOptions": {
4
+ "outDir": "lib",
5
+ "moduleResolution": "node"
6
+ },
7
+ "include": ["src/**/*"]
8
+ }