@ledgerhq/hw-app-near 6.27.3
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.
- package/.turbo/turbo-build.log +4 -0
- package/CHANGELOG.md +31 -0
- package/README.md +75 -0
- package/jest.config.ts +6 -0
- package/lib/Near.d.ts +47 -0
- package/lib/Near.d.ts.map +1 -0
- package/lib/Near.js +185 -0
- package/lib/Near.js.map +1 -0
- package/lib/utils.d.ts +3 -0
- package/lib/utils.d.ts.map +1 -0
- package/lib/utils.js +22 -0
- package/lib/utils.js.map +1 -0
- package/lib-es/Near.d.ts +47 -0
- package/lib-es/Near.d.ts.map +1 -0
- package/lib-es/Near.js +183 -0
- package/lib-es/Near.js.map +1 -0
- package/lib-es/utils.d.ts +3 -0
- package/lib-es/utils.d.ts.map +1 -0
- package/lib-es/utils.js +18 -0
- package/lib-es/utils.js.map +1 -0
- package/package.json +48 -0
- package/src/Near.ts +144 -0
- package/src/utils.ts +19 -0
- package/tests/Near.test.ts +11 -0
- package/tsconfig.json +7 -0
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
# @ledgerhq/hw-app-near
|
|
2
|
+
|
|
3
|
+
## 6.27.3
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- Updated dependencies [[`ecfdd1ebd8`](https://github.com/LedgerHQ/ledger-live/commit/ecfdd1ebd8cc7c4b5bc6315316ce662bb6241311)]:
|
|
8
|
+
- @ledgerhq/hw-transport@6.27.3
|
|
9
|
+
|
|
10
|
+
## 6.27.3-next.0
|
|
11
|
+
|
|
12
|
+
### Patch Changes
|
|
13
|
+
|
|
14
|
+
- Updated dependencies [[`ecfdd1ebd`](https://github.com/LedgerHQ/ledger-live/commit/ecfdd1ebd8cc7c4b5bc6315316ce662bb6241311)]:
|
|
15
|
+
- @ledgerhq/hw-transport@6.27.3-next.0
|
|
16
|
+
|
|
17
|
+
## 6.27.2
|
|
18
|
+
|
|
19
|
+
### Patch Changes
|
|
20
|
+
|
|
21
|
+
- Updated dependencies [[`203b927b4`](https://github.com/LedgerHQ/ledger-live/commit/203b927b4e5bca3402c85a88c536d519adb18c5f)]:
|
|
22
|
+
- @ledgerhq/errors@6.10.1
|
|
23
|
+
- @ledgerhq/hw-transport@6.27.2
|
|
24
|
+
|
|
25
|
+
## 6.27.2-next.0
|
|
26
|
+
|
|
27
|
+
### Patch Changes
|
|
28
|
+
|
|
29
|
+
- Updated dependencies [[`203b927b4`](https://github.com/LedgerHQ/ledger-live/commit/203b927b4e5bca3402c85a88c536d519adb18c5f)]:
|
|
30
|
+
- @ledgerhq/errors@6.10.1-next.0
|
|
31
|
+
- @ledgerhq/hw-transport@6.27.2-next.0
|
package/README.md
ADDED
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
<img src="https://user-images.githubusercontent.com/211411/34776833-6f1ef4da-f618-11e7-8b13-f0697901d6a8.png" height="100" />
|
|
2
|
+
|
|
3
|
+
[Github](https://github.com/LedgerHQ/ledgerjs/),
|
|
4
|
+
[Ledger Devs Slack](https://ledger-dev.slack.com/)
|
|
5
|
+
|
|
6
|
+
## @ledgerhq/hw-app-near
|
|
7
|
+
|
|
8
|
+
Ledger Hardware Wallet NEAR JavaScript bindings.
|
|
9
|
+
|
|
10
|
+
***
|
|
11
|
+
|
|
12
|
+
## Are you adding Ledger support to your software wallet?
|
|
13
|
+
|
|
14
|
+
You may be using this package to communicate with the NEAR Nano App.
|
|
15
|
+
|
|
16
|
+
For a smooth and quick integration:
|
|
17
|
+
|
|
18
|
+
* See the developers’ documentation on the [Developer Portal](https://developers.ledger.com/docs/transport/overview/) and
|
|
19
|
+
* Go on [Discord](https://developers.ledger.com/discord-pro/) to chat with developer support and the developer community.
|
|
20
|
+
|
|
21
|
+
***
|
|
22
|
+
|
|
23
|
+
## API
|
|
24
|
+
|
|
25
|
+
<!-- Generated by documentation.js. Update this documentation by updating the source code. -->
|
|
26
|
+
|
|
27
|
+
#### Table of Contents
|
|
28
|
+
|
|
29
|
+
* [Near](#near)
|
|
30
|
+
* [Parameters](#parameters)
|
|
31
|
+
* [Examples](#examples)
|
|
32
|
+
* [getAddress](#getaddress)
|
|
33
|
+
* [Parameters](#parameters-1)
|
|
34
|
+
* [Examples](#examples-1)
|
|
35
|
+
* [signTransaction](#signtransaction)
|
|
36
|
+
* [Parameters](#parameters-2)
|
|
37
|
+
|
|
38
|
+
### Near
|
|
39
|
+
|
|
40
|
+
NEAR API
|
|
41
|
+
|
|
42
|
+
#### Parameters
|
|
43
|
+
|
|
44
|
+
* `transport` **Transport**
|
|
45
|
+
|
|
46
|
+
#### Examples
|
|
47
|
+
|
|
48
|
+
```javascript
|
|
49
|
+
import Near from "@ledgerhq/hw-app-near";
|
|
50
|
+
const near = new Near(transport)
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
#### getAddress
|
|
54
|
+
|
|
55
|
+
##### Parameters
|
|
56
|
+
|
|
57
|
+
* `path` **[string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)**
|
|
58
|
+
* `verify` **[boolean](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean)?**
|
|
59
|
+
|
|
60
|
+
##### Examples
|
|
61
|
+
|
|
62
|
+
```javascript
|
|
63
|
+
near.getAddress("44'/397'/0'/0'/0'", true).then(o => o.address)
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
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)}>** an object with a publicKey and address
|
|
67
|
+
|
|
68
|
+
#### signTransaction
|
|
69
|
+
|
|
70
|
+
##### Parameters
|
|
71
|
+
|
|
72
|
+
* `transaction` **[Uint8Array](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Uint8Array)**
|
|
73
|
+
* `path` **[string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)**
|
|
74
|
+
|
|
75
|
+
Returns **[Promise](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Promise)<([Buffer](https://nodejs.org/api/buffer.html) | [undefined](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/undefined))>** a signature to be broadcasted to the chain
|
package/jest.config.ts
ADDED
package/lib/Near.d.ts
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/// <reference types="node" />
|
|
2
|
+
/********************************************************************************
|
|
3
|
+
* Ledger Node JS API
|
|
4
|
+
* (c) 2017-2018 Ledger
|
|
5
|
+
*
|
|
6
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
7
|
+
* you may not use this file except in compliance with the License.
|
|
8
|
+
* You may obtain a copy of the License at
|
|
9
|
+
*
|
|
10
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
11
|
+
*
|
|
12
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
13
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
14
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
15
|
+
* See the License for the specific language governing permissions and
|
|
16
|
+
* limitations under the License.
|
|
17
|
+
********************************************************************************/
|
|
18
|
+
import type Transport from "@ledgerhq/hw-transport";
|
|
19
|
+
/**
|
|
20
|
+
* NEAR API
|
|
21
|
+
*
|
|
22
|
+
* @example
|
|
23
|
+
* import Near from "@ledgerhq/hw-app-near";
|
|
24
|
+
* const near = new Near(transport)
|
|
25
|
+
*/
|
|
26
|
+
export default class Near {
|
|
27
|
+
transport: Transport;
|
|
28
|
+
constructor(transport: Transport);
|
|
29
|
+
/**
|
|
30
|
+
* @param path
|
|
31
|
+
* @option verify - if true, user must verify if the address is correct on the device
|
|
32
|
+
* @return an object with a publicKey and address
|
|
33
|
+
* @example
|
|
34
|
+
* near.getAddress("44'/397'/0'/0'/0'", true).then(o => o.address)
|
|
35
|
+
*/
|
|
36
|
+
getAddress(path: string, verify?: boolean): Promise<{
|
|
37
|
+
publicKey: string;
|
|
38
|
+
address: string;
|
|
39
|
+
}>;
|
|
40
|
+
/**
|
|
41
|
+
* @param transaction
|
|
42
|
+
* @param path
|
|
43
|
+
* @return a signature to be broadcasted to the chain
|
|
44
|
+
*/
|
|
45
|
+
signTransaction(transaction: Uint8Array, path: string): Promise<Buffer | undefined>;
|
|
46
|
+
}
|
|
47
|
+
//# sourceMappingURL=Near.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Near.d.ts","sourceRoot":"","sources":["../src/Near.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;kFAekF;AAClF,OAAO,KAAK,SAAS,MAAM,wBAAwB,CAAC;AAcpD;;;;;;GAMG;AAEH,MAAM,CAAC,OAAO,OAAO,IAAI;IACvB,SAAS,EAAE,SAAS,CAAC;gBAET,SAAS,EAAE,SAAS;IAShC;;;;;;OAMG;IACG,UAAU,CACd,IAAI,EAAE,MAAM,EACZ,MAAM,CAAC,EAAE,OAAO,GACf,OAAO,CAAC;QACT,SAAS,EAAE,MAAM,CAAC;QAClB,OAAO,EAAE,MAAM,CAAC;KACjB,CAAC;IAoBF;;;;OAIG;IACG,eAAe,CACnB,WAAW,EAAE,UAAU,EACvB,IAAI,EAAE,MAAM,GACX,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC;CAM/B"}
|
package/lib/Near.js
ADDED
|
@@ -0,0 +1,185 @@
|
|
|
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
|
+
var __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 (g && (g = 0, op[0] && (_ = 0)), _) 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
|
+
};
|
|
38
|
+
exports.__esModule = true;
|
|
39
|
+
var utils_1 = require("near-api-js/lib/utils");
|
|
40
|
+
var key_pair_1 = require("near-api-js/lib/utils/key_pair");
|
|
41
|
+
var utils_2 = require("./utils");
|
|
42
|
+
// 128 - 5 service bytes
|
|
43
|
+
var CHUNK_SIZE = 123;
|
|
44
|
+
var CLA = 0x80;
|
|
45
|
+
var INS_GET_PUBLIC_KEY = 4;
|
|
46
|
+
var INS_GET_ADDRESS = 5;
|
|
47
|
+
var INS_SIGN = 2;
|
|
48
|
+
var P1_LAST_CHUNK = 0x80;
|
|
49
|
+
var NETWORK_ID = "W".charCodeAt(0);
|
|
50
|
+
/**
|
|
51
|
+
* NEAR API
|
|
52
|
+
*
|
|
53
|
+
* @example
|
|
54
|
+
* import Near from "@ledgerhq/hw-app-near";
|
|
55
|
+
* const near = new Near(transport)
|
|
56
|
+
*/
|
|
57
|
+
var Near = /** @class */ (function () {
|
|
58
|
+
function Near(transport) {
|
|
59
|
+
this.transport = transport;
|
|
60
|
+
transport.decorateAppAPIMethods(this, ["getPublicKey", "getAddress", "sign"], "NEAR");
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* @param path
|
|
64
|
+
* @option verify - if true, user must verify if the address is correct on the device
|
|
65
|
+
* @return an object with a publicKey and address
|
|
66
|
+
* @example
|
|
67
|
+
* near.getAddress("44'/397'/0'/0'/0'", true).then(o => o.address)
|
|
68
|
+
*/
|
|
69
|
+
Near.prototype.getAddress = function (path, verify) {
|
|
70
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
71
|
+
var client, rawPublicKey, publicKey;
|
|
72
|
+
return __generator(this, function (_a) {
|
|
73
|
+
switch (_a.label) {
|
|
74
|
+
case 0: return [4 /*yield*/, createClient(this.transport)];
|
|
75
|
+
case 1:
|
|
76
|
+
client = _a.sent();
|
|
77
|
+
if (!verify) return [3 /*break*/, 3];
|
|
78
|
+
return [4 /*yield*/, client.getAddress(path)];
|
|
79
|
+
case 2:
|
|
80
|
+
_a.sent();
|
|
81
|
+
_a.label = 3;
|
|
82
|
+
case 3: return [4 /*yield*/, client.getPublicKey(path, false)];
|
|
83
|
+
case 4:
|
|
84
|
+
rawPublicKey = _a.sent();
|
|
85
|
+
publicKey = new utils_1.PublicKey({
|
|
86
|
+
keyType: key_pair_1.KeyType.ED25519,
|
|
87
|
+
data: rawPublicKey
|
|
88
|
+
});
|
|
89
|
+
return [2 /*return*/, {
|
|
90
|
+
address: rawPublicKey.toString("hex"),
|
|
91
|
+
publicKey: publicKey.toString()
|
|
92
|
+
}];
|
|
93
|
+
}
|
|
94
|
+
});
|
|
95
|
+
});
|
|
96
|
+
};
|
|
97
|
+
/**
|
|
98
|
+
* @param transaction
|
|
99
|
+
* @param path
|
|
100
|
+
* @return a signature to be broadcasted to the chain
|
|
101
|
+
*/
|
|
102
|
+
Near.prototype.signTransaction = function (transaction, path) {
|
|
103
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
104
|
+
var client, signature;
|
|
105
|
+
return __generator(this, function (_a) {
|
|
106
|
+
switch (_a.label) {
|
|
107
|
+
case 0: return [4 /*yield*/, createClient(this.transport)];
|
|
108
|
+
case 1:
|
|
109
|
+
client = _a.sent();
|
|
110
|
+
return [4 /*yield*/, client.sign(transaction, path)];
|
|
111
|
+
case 2:
|
|
112
|
+
signature = _a.sent();
|
|
113
|
+
return [2 /*return*/, signature];
|
|
114
|
+
}
|
|
115
|
+
});
|
|
116
|
+
});
|
|
117
|
+
};
|
|
118
|
+
return Near;
|
|
119
|
+
}());
|
|
120
|
+
exports["default"] = Near;
|
|
121
|
+
function createClient(transport) {
|
|
122
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
123
|
+
return __generator(this, function (_a) {
|
|
124
|
+
return [2 /*return*/, {
|
|
125
|
+
transport: transport,
|
|
126
|
+
getPublicKey: function (path, verify) {
|
|
127
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
128
|
+
var response;
|
|
129
|
+
return __generator(this, function (_a) {
|
|
130
|
+
switch (_a.label) {
|
|
131
|
+
case 0: return [4 /*yield*/, this.transport.send(CLA, INS_GET_PUBLIC_KEY, verify ? 0 : 1, NETWORK_ID, (0, utils_2.bip32PathToBytes)(path))];
|
|
132
|
+
case 1:
|
|
133
|
+
response = _a.sent();
|
|
134
|
+
return [2 /*return*/, Buffer.from(response.subarray(0, -2))];
|
|
135
|
+
}
|
|
136
|
+
});
|
|
137
|
+
});
|
|
138
|
+
},
|
|
139
|
+
getAddress: function (path) {
|
|
140
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
141
|
+
var response;
|
|
142
|
+
return __generator(this, function (_a) {
|
|
143
|
+
switch (_a.label) {
|
|
144
|
+
case 0: return [4 /*yield*/, this.transport.send(CLA, INS_GET_ADDRESS, 0, NETWORK_ID, (0, utils_2.bip32PathToBytes)(path))];
|
|
145
|
+
case 1:
|
|
146
|
+
response = _a.sent();
|
|
147
|
+
return [2 /*return*/, Buffer.from(response.subarray(0, -2))];
|
|
148
|
+
}
|
|
149
|
+
});
|
|
150
|
+
});
|
|
151
|
+
},
|
|
152
|
+
sign: function (transactionData, path) {
|
|
153
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
154
|
+
var allData, offset, chunk, isLastChunk, response;
|
|
155
|
+
return __generator(this, function (_a) {
|
|
156
|
+
switch (_a.label) {
|
|
157
|
+
case 0:
|
|
158
|
+
transactionData = Buffer.from(transactionData);
|
|
159
|
+
allData = Buffer.concat([(0, utils_2.bip32PathToBytes)(path), transactionData]);
|
|
160
|
+
offset = 0;
|
|
161
|
+
_a.label = 1;
|
|
162
|
+
case 1:
|
|
163
|
+
if (!(offset < allData.length)) return [3 /*break*/, 4];
|
|
164
|
+
chunk = Buffer.from(allData.subarray(offset, offset + CHUNK_SIZE));
|
|
165
|
+
isLastChunk = offset + CHUNK_SIZE >= allData.length;
|
|
166
|
+
return [4 /*yield*/, this.transport.send(CLA, INS_SIGN, isLastChunk ? P1_LAST_CHUNK : 0, NETWORK_ID, chunk)];
|
|
167
|
+
case 2:
|
|
168
|
+
response = _a.sent();
|
|
169
|
+
if (isLastChunk) {
|
|
170
|
+
return [2 /*return*/, Buffer.from(response.subarray(0, -2))];
|
|
171
|
+
}
|
|
172
|
+
_a.label = 3;
|
|
173
|
+
case 3:
|
|
174
|
+
offset += CHUNK_SIZE;
|
|
175
|
+
return [3 /*break*/, 1];
|
|
176
|
+
case 4: return [2 /*return*/];
|
|
177
|
+
}
|
|
178
|
+
});
|
|
179
|
+
});
|
|
180
|
+
}
|
|
181
|
+
}];
|
|
182
|
+
});
|
|
183
|
+
});
|
|
184
|
+
}
|
|
185
|
+
//# sourceMappingURL=Near.js.map
|
package/lib/Near.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Near.js","sourceRoot":"","sources":["../src/Near.ts"],"names":[],"mappings":"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"}
|
package/lib/utils.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":";AAAA,eAAO,MAAM,gBAAgB,SAAU,MAAM,KAAG,MAkB/C,CAAC"}
|
package/lib/utils.js
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
exports.__esModule = true;
|
|
3
|
+
exports.bip32PathToBytes = void 0;
|
|
4
|
+
var bip32PathToBytes = function (path) {
|
|
5
|
+
var parts = path.split("/");
|
|
6
|
+
return Buffer.concat(parts
|
|
7
|
+
.map(function (part) {
|
|
8
|
+
return part.endsWith("'")
|
|
9
|
+
? Math.abs(parseInt(part.slice(0, -1))) | 0x80000000
|
|
10
|
+
: Math.abs(parseInt(part));
|
|
11
|
+
})
|
|
12
|
+
.map(function (i32) {
|
|
13
|
+
return Buffer.from([
|
|
14
|
+
(i32 >> 24) & 0xff,
|
|
15
|
+
(i32 >> 16) & 0xff,
|
|
16
|
+
(i32 >> 8) & 0xff,
|
|
17
|
+
i32 & 0xff,
|
|
18
|
+
]);
|
|
19
|
+
}));
|
|
20
|
+
};
|
|
21
|
+
exports.bip32PathToBytes = bip32PathToBytes;
|
|
22
|
+
//# sourceMappingURL=utils.js.map
|
package/lib/utils.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utils.js","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":";;;AAAO,IAAM,gBAAgB,GAAG,UAAC,IAAY;IAC3C,IAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IAC9B,OAAO,MAAM,CAAC,MAAM,CAClB,KAAK;SACF,GAAG,CAAC,UAAC,IAAI;QACR,OAAA,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC;YAChB,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,UAAU;YACpD,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;IAF5B,CAE4B,CAC7B;SACA,GAAG,CAAC,UAAC,GAAG;QACP,OAAA,MAAM,CAAC,IAAI,CAAC;YACV,CAAC,GAAG,IAAI,EAAE,CAAC,GAAG,IAAI;YAClB,CAAC,GAAG,IAAI,EAAE,CAAC,GAAG,IAAI;YAClB,CAAC,GAAG,IAAI,CAAC,CAAC,GAAG,IAAI;YACjB,GAAG,GAAG,IAAI;SACX,CAAC;IALF,CAKE,CACH,CACJ,CAAC;AACJ,CAAC,CAAC;AAlBW,QAAA,gBAAgB,oBAkB3B"}
|
package/lib-es/Near.d.ts
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/// <reference types="node" />
|
|
2
|
+
/********************************************************************************
|
|
3
|
+
* Ledger Node JS API
|
|
4
|
+
* (c) 2017-2018 Ledger
|
|
5
|
+
*
|
|
6
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
7
|
+
* you may not use this file except in compliance with the License.
|
|
8
|
+
* You may obtain a copy of the License at
|
|
9
|
+
*
|
|
10
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
11
|
+
*
|
|
12
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
13
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
14
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
15
|
+
* See the License for the specific language governing permissions and
|
|
16
|
+
* limitations under the License.
|
|
17
|
+
********************************************************************************/
|
|
18
|
+
import type Transport from "@ledgerhq/hw-transport";
|
|
19
|
+
/**
|
|
20
|
+
* NEAR API
|
|
21
|
+
*
|
|
22
|
+
* @example
|
|
23
|
+
* import Near from "@ledgerhq/hw-app-near";
|
|
24
|
+
* const near = new Near(transport)
|
|
25
|
+
*/
|
|
26
|
+
export default class Near {
|
|
27
|
+
transport: Transport;
|
|
28
|
+
constructor(transport: Transport);
|
|
29
|
+
/**
|
|
30
|
+
* @param path
|
|
31
|
+
* @option verify - if true, user must verify if the address is correct on the device
|
|
32
|
+
* @return an object with a publicKey and address
|
|
33
|
+
* @example
|
|
34
|
+
* near.getAddress("44'/397'/0'/0'/0'", true).then(o => o.address)
|
|
35
|
+
*/
|
|
36
|
+
getAddress(path: string, verify?: boolean): Promise<{
|
|
37
|
+
publicKey: string;
|
|
38
|
+
address: string;
|
|
39
|
+
}>;
|
|
40
|
+
/**
|
|
41
|
+
* @param transaction
|
|
42
|
+
* @param path
|
|
43
|
+
* @return a signature to be broadcasted to the chain
|
|
44
|
+
*/
|
|
45
|
+
signTransaction(transaction: Uint8Array, path: string): Promise<Buffer | undefined>;
|
|
46
|
+
}
|
|
47
|
+
//# sourceMappingURL=Near.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Near.d.ts","sourceRoot":"","sources":["../src/Near.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;kFAekF;AAClF,OAAO,KAAK,SAAS,MAAM,wBAAwB,CAAC;AAcpD;;;;;;GAMG;AAEH,MAAM,CAAC,OAAO,OAAO,IAAI;IACvB,SAAS,EAAE,SAAS,CAAC;gBAET,SAAS,EAAE,SAAS;IAShC;;;;;;OAMG;IACG,UAAU,CACd,IAAI,EAAE,MAAM,EACZ,MAAM,CAAC,EAAE,OAAO,GACf,OAAO,CAAC;QACT,SAAS,EAAE,MAAM,CAAC;QAClB,OAAO,EAAE,MAAM,CAAC;KACjB,CAAC;IAoBF;;;;OAIG;IACG,eAAe,CACnB,WAAW,EAAE,UAAU,EACvB,IAAI,EAAE,MAAM,GACX,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC;CAM/B"}
|
package/lib-es/Near.js
ADDED
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
2
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
3
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
4
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
5
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
6
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
7
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
8
|
+
});
|
|
9
|
+
};
|
|
10
|
+
var __generator = (this && this.__generator) || function (thisArg, body) {
|
|
11
|
+
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
|
|
12
|
+
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
|
|
13
|
+
function verb(n) { return function (v) { return step([n, v]); }; }
|
|
14
|
+
function step(op) {
|
|
15
|
+
if (f) throw new TypeError("Generator is already executing.");
|
|
16
|
+
while (g && (g = 0, op[0] && (_ = 0)), _) try {
|
|
17
|
+
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
|
|
18
|
+
if (y = 0, t) op = [op[0] & 2, t.value];
|
|
19
|
+
switch (op[0]) {
|
|
20
|
+
case 0: case 1: t = op; break;
|
|
21
|
+
case 4: _.label++; return { value: op[1], done: false };
|
|
22
|
+
case 5: _.label++; y = op[1]; op = [0]; continue;
|
|
23
|
+
case 7: op = _.ops.pop(); _.trys.pop(); continue;
|
|
24
|
+
default:
|
|
25
|
+
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
|
|
26
|
+
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
|
|
27
|
+
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
|
|
28
|
+
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
|
|
29
|
+
if (t[2]) _.ops.pop();
|
|
30
|
+
_.trys.pop(); continue;
|
|
31
|
+
}
|
|
32
|
+
op = body.call(thisArg, _);
|
|
33
|
+
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
|
|
34
|
+
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
|
|
35
|
+
}
|
|
36
|
+
};
|
|
37
|
+
import { PublicKey } from "near-api-js/lib/utils";
|
|
38
|
+
import { KeyType } from "near-api-js/lib/utils/key_pair";
|
|
39
|
+
import { bip32PathToBytes } from "./utils";
|
|
40
|
+
// 128 - 5 service bytes
|
|
41
|
+
var CHUNK_SIZE = 123;
|
|
42
|
+
var CLA = 0x80;
|
|
43
|
+
var INS_GET_PUBLIC_KEY = 4;
|
|
44
|
+
var INS_GET_ADDRESS = 5;
|
|
45
|
+
var INS_SIGN = 2;
|
|
46
|
+
var P1_LAST_CHUNK = 0x80;
|
|
47
|
+
var NETWORK_ID = "W".charCodeAt(0);
|
|
48
|
+
/**
|
|
49
|
+
* NEAR API
|
|
50
|
+
*
|
|
51
|
+
* @example
|
|
52
|
+
* import Near from "@ledgerhq/hw-app-near";
|
|
53
|
+
* const near = new Near(transport)
|
|
54
|
+
*/
|
|
55
|
+
var Near = /** @class */ (function () {
|
|
56
|
+
function Near(transport) {
|
|
57
|
+
this.transport = transport;
|
|
58
|
+
transport.decorateAppAPIMethods(this, ["getPublicKey", "getAddress", "sign"], "NEAR");
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* @param path
|
|
62
|
+
* @option verify - if true, user must verify if the address is correct on the device
|
|
63
|
+
* @return an object with a publicKey and address
|
|
64
|
+
* @example
|
|
65
|
+
* near.getAddress("44'/397'/0'/0'/0'", true).then(o => o.address)
|
|
66
|
+
*/
|
|
67
|
+
Near.prototype.getAddress = function (path, verify) {
|
|
68
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
69
|
+
var client, rawPublicKey, publicKey;
|
|
70
|
+
return __generator(this, function (_a) {
|
|
71
|
+
switch (_a.label) {
|
|
72
|
+
case 0: return [4 /*yield*/, createClient(this.transport)];
|
|
73
|
+
case 1:
|
|
74
|
+
client = _a.sent();
|
|
75
|
+
if (!verify) return [3 /*break*/, 3];
|
|
76
|
+
return [4 /*yield*/, client.getAddress(path)];
|
|
77
|
+
case 2:
|
|
78
|
+
_a.sent();
|
|
79
|
+
_a.label = 3;
|
|
80
|
+
case 3: return [4 /*yield*/, client.getPublicKey(path, false)];
|
|
81
|
+
case 4:
|
|
82
|
+
rawPublicKey = _a.sent();
|
|
83
|
+
publicKey = new PublicKey({
|
|
84
|
+
keyType: KeyType.ED25519,
|
|
85
|
+
data: rawPublicKey
|
|
86
|
+
});
|
|
87
|
+
return [2 /*return*/, {
|
|
88
|
+
address: rawPublicKey.toString("hex"),
|
|
89
|
+
publicKey: publicKey.toString()
|
|
90
|
+
}];
|
|
91
|
+
}
|
|
92
|
+
});
|
|
93
|
+
});
|
|
94
|
+
};
|
|
95
|
+
/**
|
|
96
|
+
* @param transaction
|
|
97
|
+
* @param path
|
|
98
|
+
* @return a signature to be broadcasted to the chain
|
|
99
|
+
*/
|
|
100
|
+
Near.prototype.signTransaction = function (transaction, path) {
|
|
101
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
102
|
+
var client, signature;
|
|
103
|
+
return __generator(this, function (_a) {
|
|
104
|
+
switch (_a.label) {
|
|
105
|
+
case 0: return [4 /*yield*/, createClient(this.transport)];
|
|
106
|
+
case 1:
|
|
107
|
+
client = _a.sent();
|
|
108
|
+
return [4 /*yield*/, client.sign(transaction, path)];
|
|
109
|
+
case 2:
|
|
110
|
+
signature = _a.sent();
|
|
111
|
+
return [2 /*return*/, signature];
|
|
112
|
+
}
|
|
113
|
+
});
|
|
114
|
+
});
|
|
115
|
+
};
|
|
116
|
+
return Near;
|
|
117
|
+
}());
|
|
118
|
+
export default Near;
|
|
119
|
+
function createClient(transport) {
|
|
120
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
121
|
+
return __generator(this, function (_a) {
|
|
122
|
+
return [2 /*return*/, {
|
|
123
|
+
transport: transport,
|
|
124
|
+
getPublicKey: function (path, verify) {
|
|
125
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
126
|
+
var response;
|
|
127
|
+
return __generator(this, function (_a) {
|
|
128
|
+
switch (_a.label) {
|
|
129
|
+
case 0: return [4 /*yield*/, this.transport.send(CLA, INS_GET_PUBLIC_KEY, verify ? 0 : 1, NETWORK_ID, bip32PathToBytes(path))];
|
|
130
|
+
case 1:
|
|
131
|
+
response = _a.sent();
|
|
132
|
+
return [2 /*return*/, Buffer.from(response.subarray(0, -2))];
|
|
133
|
+
}
|
|
134
|
+
});
|
|
135
|
+
});
|
|
136
|
+
},
|
|
137
|
+
getAddress: function (path) {
|
|
138
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
139
|
+
var response;
|
|
140
|
+
return __generator(this, function (_a) {
|
|
141
|
+
switch (_a.label) {
|
|
142
|
+
case 0: return [4 /*yield*/, this.transport.send(CLA, INS_GET_ADDRESS, 0, NETWORK_ID, bip32PathToBytes(path))];
|
|
143
|
+
case 1:
|
|
144
|
+
response = _a.sent();
|
|
145
|
+
return [2 /*return*/, Buffer.from(response.subarray(0, -2))];
|
|
146
|
+
}
|
|
147
|
+
});
|
|
148
|
+
});
|
|
149
|
+
},
|
|
150
|
+
sign: function (transactionData, path) {
|
|
151
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
152
|
+
var allData, offset, chunk, isLastChunk, response;
|
|
153
|
+
return __generator(this, function (_a) {
|
|
154
|
+
switch (_a.label) {
|
|
155
|
+
case 0:
|
|
156
|
+
transactionData = Buffer.from(transactionData);
|
|
157
|
+
allData = Buffer.concat([bip32PathToBytes(path), transactionData]);
|
|
158
|
+
offset = 0;
|
|
159
|
+
_a.label = 1;
|
|
160
|
+
case 1:
|
|
161
|
+
if (!(offset < allData.length)) return [3 /*break*/, 4];
|
|
162
|
+
chunk = Buffer.from(allData.subarray(offset, offset + CHUNK_SIZE));
|
|
163
|
+
isLastChunk = offset + CHUNK_SIZE >= allData.length;
|
|
164
|
+
return [4 /*yield*/, this.transport.send(CLA, INS_SIGN, isLastChunk ? P1_LAST_CHUNK : 0, NETWORK_ID, chunk)];
|
|
165
|
+
case 2:
|
|
166
|
+
response = _a.sent();
|
|
167
|
+
if (isLastChunk) {
|
|
168
|
+
return [2 /*return*/, Buffer.from(response.subarray(0, -2))];
|
|
169
|
+
}
|
|
170
|
+
_a.label = 3;
|
|
171
|
+
case 3:
|
|
172
|
+
offset += CHUNK_SIZE;
|
|
173
|
+
return [3 /*break*/, 1];
|
|
174
|
+
case 4: return [2 /*return*/];
|
|
175
|
+
}
|
|
176
|
+
});
|
|
177
|
+
});
|
|
178
|
+
}
|
|
179
|
+
}];
|
|
180
|
+
});
|
|
181
|
+
});
|
|
182
|
+
}
|
|
183
|
+
//# sourceMappingURL=Near.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Near.js","sourceRoot":"","sources":["../src/Near.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":";AAAA,eAAO,MAAM,gBAAgB,SAAU,MAAM,KAAG,MAkB/C,CAAC"}
|
package/lib-es/utils.js
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export var bip32PathToBytes = function (path) {
|
|
2
|
+
var parts = path.split("/");
|
|
3
|
+
return Buffer.concat(parts
|
|
4
|
+
.map(function (part) {
|
|
5
|
+
return part.endsWith("'")
|
|
6
|
+
? Math.abs(parseInt(part.slice(0, -1))) | 0x80000000
|
|
7
|
+
: Math.abs(parseInt(part));
|
|
8
|
+
})
|
|
9
|
+
.map(function (i32) {
|
|
10
|
+
return Buffer.from([
|
|
11
|
+
(i32 >> 24) & 0xff,
|
|
12
|
+
(i32 >> 16) & 0xff,
|
|
13
|
+
(i32 >> 8) & 0xff,
|
|
14
|
+
i32 & 0xff,
|
|
15
|
+
]);
|
|
16
|
+
}));
|
|
17
|
+
};
|
|
18
|
+
//# sourceMappingURL=utils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utils.js","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,IAAM,gBAAgB,GAAG,UAAC,IAAY;IAC3C,IAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IAC9B,OAAO,MAAM,CAAC,MAAM,CAClB,KAAK;SACF,GAAG,CAAC,UAAC,IAAI;QACR,OAAA,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC;YAChB,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,UAAU;YACpD,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;IAF5B,CAE4B,CAC7B;SACA,GAAG,CAAC,UAAC,GAAG;QACP,OAAA,MAAM,CAAC,IAAI,CAAC;YACV,CAAC,GAAG,IAAI,EAAE,CAAC,GAAG,IAAI;YAClB,CAAC,GAAG,IAAI,EAAE,CAAC,GAAG,IAAI;YAClB,CAAC,GAAG,IAAI,CAAC,CAAC,GAAG,IAAI;YACjB,GAAG,GAAG,IAAI;SACX,CAAC;IALF,CAKE,CACH,CACJ,CAAC;AACJ,CAAC,CAAC"}
|
package/package.json
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@ledgerhq/hw-app-near",
|
|
3
|
+
"version": "6.27.3",
|
|
4
|
+
"description": "Ledger Hardware Wallet Near Application API",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"Ledger",
|
|
7
|
+
"LedgerWallet",
|
|
8
|
+
"near",
|
|
9
|
+
"NEAR",
|
|
10
|
+
"NanoS",
|
|
11
|
+
"Blue",
|
|
12
|
+
"Hardware Wallet"
|
|
13
|
+
],
|
|
14
|
+
"repository": {
|
|
15
|
+
"type": "git",
|
|
16
|
+
"url": "https://github.com/LedgerHQ/ledger-live.git"
|
|
17
|
+
},
|
|
18
|
+
"bugs": {
|
|
19
|
+
"url": "https://github.com/LedgerHQ/ledger-live/issues"
|
|
20
|
+
},
|
|
21
|
+
"homepage": "https://github.com/LedgerHQ/ledger-live/tree/develop/libs/ledgerjs/packages/hw-app-near",
|
|
22
|
+
"publishConfig": {
|
|
23
|
+
"access": "public"
|
|
24
|
+
},
|
|
25
|
+
"main": "lib/Near.js",
|
|
26
|
+
"module": "lib-es/Near.js",
|
|
27
|
+
"types": "lib/Near.d.ts",
|
|
28
|
+
"license": "Apache-2.0",
|
|
29
|
+
"dependencies": {
|
|
30
|
+
"near-api-js": "^0.44.2",
|
|
31
|
+
"@ledgerhq/errors": "^6.12.2-nightly.0",
|
|
32
|
+
"@ledgerhq/hw-transport": "^6.27.9-nightly.0"
|
|
33
|
+
},
|
|
34
|
+
"devDependencies": {
|
|
35
|
+
"@ledgerhq/hw-transport-mocker": "^6.27.9-nightly.0"
|
|
36
|
+
},
|
|
37
|
+
"gitHead": "dd0dea64b58e5a9125c8a422dcffd29e5ef6abec",
|
|
38
|
+
"scripts": {
|
|
39
|
+
"clean": "rimraf lib lib-es",
|
|
40
|
+
"build": "tsc && tsc -m ES6 --outDir lib-es",
|
|
41
|
+
"prewatch": "pnpm build",
|
|
42
|
+
"watch": "tsc --watch",
|
|
43
|
+
"doc": "documentation readme src/** --section=API --pe ts --re ts --re d.ts",
|
|
44
|
+
"lint": "eslint ./src --no-error-on-unmatched-pattern --ext .ts,.tsx",
|
|
45
|
+
"lint:fix": "pnpm lint --fix",
|
|
46
|
+
"test": "jest"
|
|
47
|
+
}
|
|
48
|
+
}
|
package/src/Near.ts
ADDED
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
/********************************************************************************
|
|
2
|
+
* Ledger Node JS API
|
|
3
|
+
* (c) 2017-2018 Ledger
|
|
4
|
+
*
|
|
5
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
6
|
+
* you may not use this file except in compliance with the License.
|
|
7
|
+
* You may obtain a copy of the License at
|
|
8
|
+
*
|
|
9
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
10
|
+
*
|
|
11
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
12
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
13
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
14
|
+
* See the License for the specific language governing permissions and
|
|
15
|
+
* limitations under the License.
|
|
16
|
+
********************************************************************************/
|
|
17
|
+
import type Transport from "@ledgerhq/hw-transport";
|
|
18
|
+
import { PublicKey } from "near-api-js/lib/utils";
|
|
19
|
+
import { KeyType } from "near-api-js/lib/utils/key_pair";
|
|
20
|
+
import { bip32PathToBytes } from "./utils";
|
|
21
|
+
|
|
22
|
+
// 128 - 5 service bytes
|
|
23
|
+
const CHUNK_SIZE = 123;
|
|
24
|
+
const CLA = 0x80;
|
|
25
|
+
const INS_GET_PUBLIC_KEY = 4;
|
|
26
|
+
const INS_GET_ADDRESS = 5;
|
|
27
|
+
const INS_SIGN = 2;
|
|
28
|
+
const P1_LAST_CHUNK = 0x80;
|
|
29
|
+
const NETWORK_ID = "W".charCodeAt(0);
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* NEAR API
|
|
33
|
+
*
|
|
34
|
+
* @example
|
|
35
|
+
* import Near from "@ledgerhq/hw-app-near";
|
|
36
|
+
* const near = new Near(transport)
|
|
37
|
+
*/
|
|
38
|
+
|
|
39
|
+
export default class Near {
|
|
40
|
+
transport: Transport;
|
|
41
|
+
|
|
42
|
+
constructor(transport: Transport) {
|
|
43
|
+
this.transport = transport;
|
|
44
|
+
transport.decorateAppAPIMethods(
|
|
45
|
+
this,
|
|
46
|
+
["getPublicKey", "getAddress", "sign"],
|
|
47
|
+
"NEAR"
|
|
48
|
+
);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* @param path
|
|
53
|
+
* @option verify - if true, user must verify if the address is correct on the device
|
|
54
|
+
* @return an object with a publicKey and address
|
|
55
|
+
* @example
|
|
56
|
+
* near.getAddress("44'/397'/0'/0'/0'", true).then(o => o.address)
|
|
57
|
+
*/
|
|
58
|
+
async getAddress(
|
|
59
|
+
path: string,
|
|
60
|
+
verify?: boolean
|
|
61
|
+
): Promise<{
|
|
62
|
+
publicKey: string;
|
|
63
|
+
address: string;
|
|
64
|
+
}> {
|
|
65
|
+
const client = await createClient(this.transport);
|
|
66
|
+
|
|
67
|
+
if (verify) {
|
|
68
|
+
await client.getAddress(path);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
const rawPublicKey = await client.getPublicKey(path, false);
|
|
72
|
+
|
|
73
|
+
const publicKey = new PublicKey({
|
|
74
|
+
keyType: KeyType.ED25519,
|
|
75
|
+
data: rawPublicKey,
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
return {
|
|
79
|
+
address: rawPublicKey.toString("hex"),
|
|
80
|
+
publicKey: publicKey.toString(),
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* @param transaction
|
|
86
|
+
* @param path
|
|
87
|
+
* @return a signature to be broadcasted to the chain
|
|
88
|
+
*/
|
|
89
|
+
async signTransaction(
|
|
90
|
+
transaction: Uint8Array,
|
|
91
|
+
path: string
|
|
92
|
+
): Promise<Buffer | undefined> {
|
|
93
|
+
const client = await createClient(this.transport);
|
|
94
|
+
const signature = await client.sign(transaction, path);
|
|
95
|
+
|
|
96
|
+
return signature;
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
async function createClient(transport) {
|
|
101
|
+
return {
|
|
102
|
+
transport,
|
|
103
|
+
async getPublicKey(path, verify) {
|
|
104
|
+
const response = await this.transport.send(
|
|
105
|
+
CLA,
|
|
106
|
+
INS_GET_PUBLIC_KEY,
|
|
107
|
+
verify ? 0 : 1,
|
|
108
|
+
NETWORK_ID,
|
|
109
|
+
bip32PathToBytes(path)
|
|
110
|
+
);
|
|
111
|
+
return Buffer.from(response.subarray(0, -2));
|
|
112
|
+
},
|
|
113
|
+
async getAddress(path) {
|
|
114
|
+
const response = await this.transport.send(
|
|
115
|
+
CLA,
|
|
116
|
+
INS_GET_ADDRESS,
|
|
117
|
+
0,
|
|
118
|
+
NETWORK_ID,
|
|
119
|
+
bip32PathToBytes(path)
|
|
120
|
+
);
|
|
121
|
+
return Buffer.from(response.subarray(0, -2));
|
|
122
|
+
},
|
|
123
|
+
async sign(transactionData, path) {
|
|
124
|
+
transactionData = Buffer.from(transactionData);
|
|
125
|
+
const allData = Buffer.concat([bip32PathToBytes(path), transactionData]);
|
|
126
|
+
for (let offset = 0; offset < allData.length; offset += CHUNK_SIZE) {
|
|
127
|
+
const chunk = Buffer.from(
|
|
128
|
+
allData.subarray(offset, offset + CHUNK_SIZE)
|
|
129
|
+
);
|
|
130
|
+
const isLastChunk = offset + CHUNK_SIZE >= allData.length;
|
|
131
|
+
const response = await this.transport.send(
|
|
132
|
+
CLA,
|
|
133
|
+
INS_SIGN,
|
|
134
|
+
isLastChunk ? P1_LAST_CHUNK : 0,
|
|
135
|
+
NETWORK_ID,
|
|
136
|
+
chunk
|
|
137
|
+
);
|
|
138
|
+
if (isLastChunk) {
|
|
139
|
+
return Buffer.from(response.subarray(0, -2));
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
},
|
|
143
|
+
};
|
|
144
|
+
}
|
package/src/utils.ts
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
export const bip32PathToBytes = (path: string): Buffer => {
|
|
2
|
+
const parts = path.split("/");
|
|
3
|
+
return Buffer.concat(
|
|
4
|
+
parts
|
|
5
|
+
.map((part) =>
|
|
6
|
+
part.endsWith("'")
|
|
7
|
+
? Math.abs(parseInt(part.slice(0, -1))) | 0x80000000
|
|
8
|
+
: Math.abs(parseInt(part))
|
|
9
|
+
)
|
|
10
|
+
.map((i32) =>
|
|
11
|
+
Buffer.from([
|
|
12
|
+
(i32 >> 24) & 0xff,
|
|
13
|
+
(i32 >> 16) & 0xff,
|
|
14
|
+
(i32 >> 8) & 0xff,
|
|
15
|
+
i32 & 0xff,
|
|
16
|
+
])
|
|
17
|
+
)
|
|
18
|
+
);
|
|
19
|
+
};
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import {
|
|
2
|
+
openTransportReplayer,
|
|
3
|
+
RecordStore,
|
|
4
|
+
} from "@ledgerhq/hw-transport-mocker";
|
|
5
|
+
import Near from "../src/Near";
|
|
6
|
+
|
|
7
|
+
test("Near init", async () => {
|
|
8
|
+
const transport = await openTransportReplayer(RecordStore.fromString(""));
|
|
9
|
+
const near = new Near(transport);
|
|
10
|
+
expect(near).not.toBe(undefined);
|
|
11
|
+
});
|