@ledgerhq/hw-app-multiversx 6.22.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.
- package/.turbo/turbo-build.log +4 -0
- package/.unimportedrc.json +5 -0
- package/CHANGELOG.md +25 -0
- package/LICENSE.txt +21 -0
- package/README.md +105 -0
- package/jest.config.ts +6 -0
- package/lib/MultiversX.d.ts +56 -0
- package/lib/MultiversX.d.ts.map +1 -0
- package/lib/MultiversX.js +170 -0
- package/lib/MultiversX.js.map +1 -0
- package/lib-es/MultiversX.d.ts +56 -0
- package/lib-es/MultiversX.d.ts.map +1 -0
- package/lib-es/MultiversX.js +164 -0
- package/lib-es/MultiversX.js.map +1 -0
- package/package.json +60 -0
- package/src/MultiversX.ts +217 -0
- package/tsconfig.json +7 -0
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# @ledgerhq/hw-app-elrond
|
|
2
|
+
|
|
3
|
+
## 6.22.0-nightly.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- [#8757](https://github.com/LedgerHQ/ledger-live/pull/8757) [`1461449`](https://github.com/LedgerHQ/ledger-live/commit/146144941c13e60182da8d79592f706d12a6f00e) Thanks [@Wozacosta](https://github.com/Wozacosta)! - chore: Rebranding from 'Elrond' to 'MultiversX'
|
|
8
|
+
|
|
9
|
+
## 6.21.1
|
|
10
|
+
|
|
11
|
+
### Patch Changes
|
|
12
|
+
|
|
13
|
+
- [#7750](https://github.com/LedgerHQ/ledger-live/pull/7750) [`8679584`](https://github.com/LedgerHQ/ledger-live/commit/86795841982e06058294528bd8d2847fc4f62513) Thanks [@Wozacosta](https://github.com/Wozacosta)! - Move Multiversx/Elrond to its own module
|
|
14
|
+
|
|
15
|
+
- Updated dependencies []:
|
|
16
|
+
- @ledgerhq/hw-transport@6.31.4
|
|
17
|
+
|
|
18
|
+
## 6.21.1-next.0
|
|
19
|
+
|
|
20
|
+
### Patch Changes
|
|
21
|
+
|
|
22
|
+
- [#7750](https://github.com/LedgerHQ/ledger-live/pull/7750) [`8679584`](https://github.com/LedgerHQ/ledger-live/commit/86795841982e06058294528bd8d2847fc4f62513) Thanks [@Wozacosta](https://github.com/Wozacosta)! - Move Multiversx/Elrond to its own module
|
|
23
|
+
|
|
24
|
+
- Updated dependencies []:
|
|
25
|
+
- @ledgerhq/hw-transport@6.31.4-next.0
|
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,105 @@
|
|
|
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-multiversx
|
|
8
|
+
|
|
9
|
+
Ledger Hardware Wallet Multiversx 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 Multiversx 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
|
+
* [MultiversX](#multiversx)
|
|
31
|
+
* [Parameters](#parameters)
|
|
32
|
+
* [Examples](#examples)
|
|
33
|
+
* [getAppConfiguration](#getappconfiguration)
|
|
34
|
+
* [Examples](#examples-1)
|
|
35
|
+
* [getAddress](#getaddress)
|
|
36
|
+
* [Parameters](#parameters-1)
|
|
37
|
+
* [Examples](#examples-2)
|
|
38
|
+
* [setAddress](#setaddress)
|
|
39
|
+
* [Parameters](#parameters-2)
|
|
40
|
+
* [Examples](#examples-3)
|
|
41
|
+
|
|
42
|
+
### MultiversX
|
|
43
|
+
|
|
44
|
+
MultiversX API
|
|
45
|
+
|
|
46
|
+
#### Parameters
|
|
47
|
+
|
|
48
|
+
* `transport` **Transport** 
|
|
49
|
+
* `scrambleKey` (optional, default `"eGLD"`)
|
|
50
|
+
|
|
51
|
+
#### Examples
|
|
52
|
+
|
|
53
|
+
```javascript
|
|
54
|
+
import MultiversX from "@ledgerhq/hw-app-multiversx";
|
|
55
|
+
const multiversx = new MultiversX(transport)
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
#### getAppConfiguration
|
|
59
|
+
|
|
60
|
+
Get MultiversX app configuration.
|
|
61
|
+
|
|
62
|
+
##### Examples
|
|
63
|
+
|
|
64
|
+
```javascript
|
|
65
|
+
const result = await multiversx.getAppConfiguration();
|
|
66
|
+
const { contractData, accountIndex, addressIndex, version } = result;
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
Returns **[Promise](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Promise)\<any>** an object with a contractData, accountIndex, addressIndex, version
|
|
70
|
+
|
|
71
|
+
#### getAddress
|
|
72
|
+
|
|
73
|
+
Get MultiversX address for a given BIP 32 path.
|
|
74
|
+
|
|
75
|
+
##### Parameters
|
|
76
|
+
|
|
77
|
+
* `path` **[string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)** a path in BIP 32 format
|
|
78
|
+
* `boolDisplay` **[boolean](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean)?** optionally enable or not the display
|
|
79
|
+
|
|
80
|
+
##### Examples
|
|
81
|
+
|
|
82
|
+
```javascript
|
|
83
|
+
const result = await multiversx.getAddress("44'/508'/0'/0'/0'");
|
|
84
|
+
const { publicKey, address } = result;
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
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 address
|
|
88
|
+
|
|
89
|
+
#### setAddress
|
|
90
|
+
|
|
91
|
+
Set MultiversX address for a given BIP 32 path.
|
|
92
|
+
|
|
93
|
+
##### Parameters
|
|
94
|
+
|
|
95
|
+
* `path` **[string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)** a path in BIP 32 format
|
|
96
|
+
* `display` **[boolean](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean)?** optionally enable or not the display
|
|
97
|
+
|
|
98
|
+
##### Examples
|
|
99
|
+
|
|
100
|
+
```javascript
|
|
101
|
+
const result = await multiversx.setAddress("44'/508'/0'/0/0");
|
|
102
|
+
result : Buffer;
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
Returns **any** an object with a address
|
package/jest.config.ts
ADDED
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
/// <reference types="node" />
|
|
2
|
+
/// <reference types="node" />
|
|
3
|
+
import type Transport from "@ledgerhq/hw-transport";
|
|
4
|
+
/**
|
|
5
|
+
* MultiversX API
|
|
6
|
+
*
|
|
7
|
+
* @example
|
|
8
|
+
* import MultiversX from "@ledgerhq/hw-app-multiversx";
|
|
9
|
+
* const multiversx = new MultiversX(transport)
|
|
10
|
+
*/
|
|
11
|
+
export default class MultiversX {
|
|
12
|
+
transport: Transport;
|
|
13
|
+
constructor(transport: Transport, scrambleKey?: string);
|
|
14
|
+
/**
|
|
15
|
+
* Get MultiversX app configuration.
|
|
16
|
+
*
|
|
17
|
+
* @return an object with a contractData, accountIndex, addressIndex, version
|
|
18
|
+
* @example
|
|
19
|
+
* const result = await multiversx.getAppConfiguration();
|
|
20
|
+
* const { contractData, accountIndex, addressIndex, version } = result;
|
|
21
|
+
*/
|
|
22
|
+
getAppConfiguration(): Promise<any>;
|
|
23
|
+
serializePath(path: Array<number>): Buffer;
|
|
24
|
+
/**
|
|
25
|
+
* Get MultiversX address for a given BIP 32 path.
|
|
26
|
+
*
|
|
27
|
+
* @param path a path in BIP 32 format
|
|
28
|
+
* @param boolDisplay optionally enable or not the display
|
|
29
|
+
* @return an object with a address
|
|
30
|
+
* @example
|
|
31
|
+
* const result = await multiversx.getAddress("44'/508'/0'/0'/0'");
|
|
32
|
+
* const { publicKey, address } = result;
|
|
33
|
+
*/
|
|
34
|
+
getAddress(path: string, boolDisplay?: boolean): Promise<{
|
|
35
|
+
publicKey: string;
|
|
36
|
+
address: string;
|
|
37
|
+
}>;
|
|
38
|
+
/**
|
|
39
|
+
* Set MultiversX address for a given BIP 32 path.
|
|
40
|
+
*
|
|
41
|
+
* @param path a path in BIP 32 format
|
|
42
|
+
* @param display optionally enable or not the display
|
|
43
|
+
* @return an object with a address
|
|
44
|
+
* @example
|
|
45
|
+
* const result = await multiversx.setAddress("44'/508'/0'/0/0");
|
|
46
|
+
* result : Buffer;
|
|
47
|
+
*/
|
|
48
|
+
setAddress(path: string, display?: boolean): Promise<void>;
|
|
49
|
+
signTransaction(path: string, message: string): Promise<string>;
|
|
50
|
+
sign(path: string, message: string): Promise<{
|
|
51
|
+
signature: null | Buffer;
|
|
52
|
+
}>;
|
|
53
|
+
serializeESDTInfo(ticker: string, id: string, decimals: number, chainId: string, signature: string): Buffer;
|
|
54
|
+
provideESDTInfo(ticker?: string, id?: string, decimals?: number, chainId?: string, signature?: string): Promise<any>;
|
|
55
|
+
}
|
|
56
|
+
//# sourceMappingURL=MultiversX.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"MultiversX.d.ts","sourceRoot":"","sources":["../src/MultiversX.ts"],"names":[],"mappings":";;AAAA,OAAO,KAAK,SAAS,MAAM,wBAAwB,CAAC;AAiBpD;;;;;;GAMG;AACH,MAAM,CAAC,OAAO,OAAO,UAAU;IAC7B,SAAS,EAAE,SAAS,CAAC;gBAET,SAAS,EAAE,SAAS,EAAE,WAAW,SAAS;IAgBtD;;;;;;;OAOG;IACG,mBAAmB,IAAI,OAAO,CAAC,GAAG,CAAC;IAUzC,aAAa,CAAC,IAAI,EAAE,KAAK,CAAC,MAAM,CAAC;IAOjC;;;;;;;;;OASG;IACG,UAAU,CACd,IAAI,EAAE,MAAM,EACZ,WAAW,CAAC,EAAE,OAAO,GACpB,OAAO,CAAC;QACT,SAAS,EAAE,MAAM,CAAC;QAClB,OAAO,EAAE,MAAM,CAAC;KACjB,CAAC;IAqBF;;;;;;;;;OASG;IACG,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,OAAO;IAS1C,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAU/D,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC;QAAE,SAAS,EAAE,IAAI,GAAG,MAAM,CAAA;KAAE,CAAC;IAuChF,iBAAiB,CACf,MAAM,EAAE,MAAM,EACd,EAAE,EAAE,MAAM,EACV,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,MAAM,EACf,SAAS,EAAE,MAAM,GAChB,MAAM;IAsBH,eAAe,CACnB,MAAM,CAAC,EAAE,MAAM,EACf,EAAE,CAAC,EAAE,MAAM,EACX,QAAQ,CAAC,EAAE,MAAM,EACjB,OAAO,CAAC,EAAE,MAAM,EAChB,SAAS,CAAC,EAAE,MAAM,GACjB,OAAO,CAAC,GAAG,CAAC;CAShB"}
|
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
const sdk_core_1 = require("@multiversx/sdk-core");
|
|
7
|
+
const bip32_path_1 = __importDefault(require("bip32-path"));
|
|
8
|
+
const CHUNK_SIZE = 150;
|
|
9
|
+
const CURVE_MASK = 0x80;
|
|
10
|
+
const CLA = 0xed;
|
|
11
|
+
const INS = {
|
|
12
|
+
GET_VERSION: 0x02,
|
|
13
|
+
GET_ADDRESS: 0x03,
|
|
14
|
+
SET_ADDRESS: 0x05,
|
|
15
|
+
PROVIDE_ESDT_INFO: 0x08,
|
|
16
|
+
};
|
|
17
|
+
const SIGN_HASH_TX_INS = 0x07;
|
|
18
|
+
const SW_OK = 0x9000;
|
|
19
|
+
const SW_CANCEL = 0x6986;
|
|
20
|
+
/**
|
|
21
|
+
* MultiversX API
|
|
22
|
+
*
|
|
23
|
+
* @example
|
|
24
|
+
* import MultiversX from "@ledgerhq/hw-app-multiversx";
|
|
25
|
+
* const multiversx = new MultiversX(transport)
|
|
26
|
+
*/
|
|
27
|
+
class MultiversX {
|
|
28
|
+
transport;
|
|
29
|
+
constructor(transport, scrambleKey = "eGLD") {
|
|
30
|
+
this.transport = transport;
|
|
31
|
+
transport.decorateAppAPIMethods(this, [
|
|
32
|
+
"getAddress",
|
|
33
|
+
"setAddress",
|
|
34
|
+
"signTransaction",
|
|
35
|
+
"signMessage",
|
|
36
|
+
"getAppConfiguration",
|
|
37
|
+
"provideESDTInfo",
|
|
38
|
+
], scrambleKey);
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Get MultiversX app configuration.
|
|
42
|
+
*
|
|
43
|
+
* @return an object with a contractData, accountIndex, addressIndex, version
|
|
44
|
+
* @example
|
|
45
|
+
* const result = await multiversx.getAppConfiguration();
|
|
46
|
+
* const { contractData, accountIndex, addressIndex, version } = result;
|
|
47
|
+
*/
|
|
48
|
+
async getAppConfiguration() {
|
|
49
|
+
const response = await this.transport.send(CLA, INS.GET_VERSION, 0x00, 0x00);
|
|
50
|
+
return {
|
|
51
|
+
contractData: response[0],
|
|
52
|
+
accountIndex: response[1],
|
|
53
|
+
addressIndex: response[2],
|
|
54
|
+
version: `${response[3]}.${response[4]}.${response[5]}`,
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
serializePath(path) {
|
|
58
|
+
const buf = Buffer.alloc(8);
|
|
59
|
+
buf.writeUInt32BE(path[3], 0);
|
|
60
|
+
buf.writeUInt32BE(path[2], 4);
|
|
61
|
+
return buf;
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Get MultiversX address for a given BIP 32 path.
|
|
65
|
+
*
|
|
66
|
+
* @param path a path in BIP 32 format
|
|
67
|
+
* @param boolDisplay optionally enable or not the display
|
|
68
|
+
* @return an object with a address
|
|
69
|
+
* @example
|
|
70
|
+
* const result = await multiversx.getAddress("44'/508'/0'/0'/0'");
|
|
71
|
+
* const { publicKey, address } = result;
|
|
72
|
+
*/
|
|
73
|
+
async getAddress(path, boolDisplay) {
|
|
74
|
+
const bipPath = bip32_path_1.default.fromString(path).toPathArray();
|
|
75
|
+
const data = this.serializePath(bipPath);
|
|
76
|
+
const response = await this.transport.send(CLA, INS.GET_ADDRESS, boolDisplay ? 0x01 : 0x00, 0x00, data, [SW_OK, SW_CANCEL]);
|
|
77
|
+
const addressLength = response[0];
|
|
78
|
+
const address = sdk_core_1.Address.newFromBech32(response.slice(1, 1 + addressLength).toString("ascii"));
|
|
79
|
+
return {
|
|
80
|
+
publicKey: address.toHex(),
|
|
81
|
+
address: address.toBech32(),
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Set MultiversX address for a given BIP 32 path.
|
|
86
|
+
*
|
|
87
|
+
* @param path a path in BIP 32 format
|
|
88
|
+
* @param display optionally enable or not the display
|
|
89
|
+
* @return an object with a address
|
|
90
|
+
* @example
|
|
91
|
+
* const result = await multiversx.setAddress("44'/508'/0'/0/0");
|
|
92
|
+
* result : Buffer;
|
|
93
|
+
*/
|
|
94
|
+
async setAddress(path, display) {
|
|
95
|
+
const bipPath = bip32_path_1.default.fromString(path).toPathArray();
|
|
96
|
+
const data = this.serializePath(bipPath);
|
|
97
|
+
await this.transport.send(CLA, INS.SET_ADDRESS, display ? 0x01 : 0x00, 0x00, data, [
|
|
98
|
+
SW_OK,
|
|
99
|
+
SW_CANCEL,
|
|
100
|
+
]);
|
|
101
|
+
}
|
|
102
|
+
async signTransaction(path, message) {
|
|
103
|
+
const { signature } = await this.sign(path, message);
|
|
104
|
+
if (signature === null) {
|
|
105
|
+
throw new Error("null signature received");
|
|
106
|
+
}
|
|
107
|
+
return signature.toString("hex");
|
|
108
|
+
}
|
|
109
|
+
async sign(path, message) {
|
|
110
|
+
const chunks = [];
|
|
111
|
+
const buffer = Buffer.from(message);
|
|
112
|
+
for (let i = 0; i < buffer.length; i += CHUNK_SIZE) {
|
|
113
|
+
let end = i + CHUNK_SIZE;
|
|
114
|
+
if (i > buffer.length) {
|
|
115
|
+
end = buffer.length;
|
|
116
|
+
}
|
|
117
|
+
chunks.push(buffer.slice(i, end));
|
|
118
|
+
}
|
|
119
|
+
const apdus = [];
|
|
120
|
+
chunks.forEach((data, index) => {
|
|
121
|
+
const apdu = {
|
|
122
|
+
cla: CLA,
|
|
123
|
+
ins: SIGN_HASH_TX_INS,
|
|
124
|
+
p1: index === 0 ? 0x00 : CURVE_MASK,
|
|
125
|
+
p2: CURVE_MASK,
|
|
126
|
+
data,
|
|
127
|
+
};
|
|
128
|
+
apdus.push(apdu);
|
|
129
|
+
});
|
|
130
|
+
let response = {};
|
|
131
|
+
for (const apdu of apdus) {
|
|
132
|
+
response = await this.transport.send(apdu.cla, apdu.ins, apdu.p1, apdu.p2, apdu.data);
|
|
133
|
+
}
|
|
134
|
+
if (response.length !== 67 || response[0] !== 64) {
|
|
135
|
+
throw new Error("invalid signature received from ledger device");
|
|
136
|
+
}
|
|
137
|
+
const signature = response.slice(1, response.length - 2).toString("hex");
|
|
138
|
+
return { signature };
|
|
139
|
+
}
|
|
140
|
+
serializeESDTInfo(ticker, id, decimals, chainId, signature) {
|
|
141
|
+
const tickerLengthBuffer = Buffer.from([ticker.length]);
|
|
142
|
+
const tickerBuffer = Buffer.from(ticker);
|
|
143
|
+
const idLengthBuffer = Buffer.from([id.length]);
|
|
144
|
+
const idBuffer = Buffer.from(id);
|
|
145
|
+
const decimalsBuffer = Buffer.from([decimals]);
|
|
146
|
+
const chainIdLengthBuffer = Buffer.from([chainId.length]);
|
|
147
|
+
const chainIdBuffer = Buffer.from(chainId);
|
|
148
|
+
const signatureBuffer = Buffer.from(signature, "hex");
|
|
149
|
+
const infoBuffer = [
|
|
150
|
+
tickerLengthBuffer,
|
|
151
|
+
tickerBuffer,
|
|
152
|
+
idLengthBuffer,
|
|
153
|
+
idBuffer,
|
|
154
|
+
decimalsBuffer,
|
|
155
|
+
chainIdLengthBuffer,
|
|
156
|
+
chainIdBuffer,
|
|
157
|
+
signatureBuffer,
|
|
158
|
+
];
|
|
159
|
+
return Buffer.concat(infoBuffer);
|
|
160
|
+
}
|
|
161
|
+
async provideESDTInfo(ticker, id, decimals, chainId, signature) {
|
|
162
|
+
if (!ticker || !id || !decimals || !chainId || !signature) {
|
|
163
|
+
throw new Error("Invalid ESDT token credentials!");
|
|
164
|
+
}
|
|
165
|
+
const data = this.serializeESDTInfo(ticker, id, decimals, chainId, signature);
|
|
166
|
+
return await this.transport.send(CLA, INS.PROVIDE_ESDT_INFO, 0x00, 0x00, data);
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
exports.default = MultiversX;
|
|
170
|
+
//# sourceMappingURL=MultiversX.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"MultiversX.js","sourceRoot":"","sources":["../src/MultiversX.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
/// <reference types="node" />
|
|
2
|
+
/// <reference types="node" />
|
|
3
|
+
import type Transport from "@ledgerhq/hw-transport";
|
|
4
|
+
/**
|
|
5
|
+
* MultiversX API
|
|
6
|
+
*
|
|
7
|
+
* @example
|
|
8
|
+
* import MultiversX from "@ledgerhq/hw-app-multiversx";
|
|
9
|
+
* const multiversx = new MultiversX(transport)
|
|
10
|
+
*/
|
|
11
|
+
export default class MultiversX {
|
|
12
|
+
transport: Transport;
|
|
13
|
+
constructor(transport: Transport, scrambleKey?: string);
|
|
14
|
+
/**
|
|
15
|
+
* Get MultiversX app configuration.
|
|
16
|
+
*
|
|
17
|
+
* @return an object with a contractData, accountIndex, addressIndex, version
|
|
18
|
+
* @example
|
|
19
|
+
* const result = await multiversx.getAppConfiguration();
|
|
20
|
+
* const { contractData, accountIndex, addressIndex, version } = result;
|
|
21
|
+
*/
|
|
22
|
+
getAppConfiguration(): Promise<any>;
|
|
23
|
+
serializePath(path: Array<number>): Buffer;
|
|
24
|
+
/**
|
|
25
|
+
* Get MultiversX address for a given BIP 32 path.
|
|
26
|
+
*
|
|
27
|
+
* @param path a path in BIP 32 format
|
|
28
|
+
* @param boolDisplay optionally enable or not the display
|
|
29
|
+
* @return an object with a address
|
|
30
|
+
* @example
|
|
31
|
+
* const result = await multiversx.getAddress("44'/508'/0'/0'/0'");
|
|
32
|
+
* const { publicKey, address } = result;
|
|
33
|
+
*/
|
|
34
|
+
getAddress(path: string, boolDisplay?: boolean): Promise<{
|
|
35
|
+
publicKey: string;
|
|
36
|
+
address: string;
|
|
37
|
+
}>;
|
|
38
|
+
/**
|
|
39
|
+
* Set MultiversX address for a given BIP 32 path.
|
|
40
|
+
*
|
|
41
|
+
* @param path a path in BIP 32 format
|
|
42
|
+
* @param display optionally enable or not the display
|
|
43
|
+
* @return an object with a address
|
|
44
|
+
* @example
|
|
45
|
+
* const result = await multiversx.setAddress("44'/508'/0'/0/0");
|
|
46
|
+
* result : Buffer;
|
|
47
|
+
*/
|
|
48
|
+
setAddress(path: string, display?: boolean): Promise<void>;
|
|
49
|
+
signTransaction(path: string, message: string): Promise<string>;
|
|
50
|
+
sign(path: string, message: string): Promise<{
|
|
51
|
+
signature: null | Buffer;
|
|
52
|
+
}>;
|
|
53
|
+
serializeESDTInfo(ticker: string, id: string, decimals: number, chainId: string, signature: string): Buffer;
|
|
54
|
+
provideESDTInfo(ticker?: string, id?: string, decimals?: number, chainId?: string, signature?: string): Promise<any>;
|
|
55
|
+
}
|
|
56
|
+
//# sourceMappingURL=MultiversX.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"MultiversX.d.ts","sourceRoot":"","sources":["../src/MultiversX.ts"],"names":[],"mappings":";;AAAA,OAAO,KAAK,SAAS,MAAM,wBAAwB,CAAC;AAiBpD;;;;;;GAMG;AACH,MAAM,CAAC,OAAO,OAAO,UAAU;IAC7B,SAAS,EAAE,SAAS,CAAC;gBAET,SAAS,EAAE,SAAS,EAAE,WAAW,SAAS;IAgBtD;;;;;;;OAOG;IACG,mBAAmB,IAAI,OAAO,CAAC,GAAG,CAAC;IAUzC,aAAa,CAAC,IAAI,EAAE,KAAK,CAAC,MAAM,CAAC;IAOjC;;;;;;;;;OASG;IACG,UAAU,CACd,IAAI,EAAE,MAAM,EACZ,WAAW,CAAC,EAAE,OAAO,GACpB,OAAO,CAAC;QACT,SAAS,EAAE,MAAM,CAAC;QAClB,OAAO,EAAE,MAAM,CAAC;KACjB,CAAC;IAqBF;;;;;;;;;OASG;IACG,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,OAAO;IAS1C,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAU/D,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC;QAAE,SAAS,EAAE,IAAI,GAAG,MAAM,CAAA;KAAE,CAAC;IAuChF,iBAAiB,CACf,MAAM,EAAE,MAAM,EACd,EAAE,EAAE,MAAM,EACV,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,MAAM,EACf,SAAS,EAAE,MAAM,GAChB,MAAM;IAsBH,eAAe,CACnB,MAAM,CAAC,EAAE,MAAM,EACf,EAAE,CAAC,EAAE,MAAM,EACX,QAAQ,CAAC,EAAE,MAAM,EACjB,OAAO,CAAC,EAAE,MAAM,EAChB,SAAS,CAAC,EAAE,MAAM,GACjB,OAAO,CAAC,GAAG,CAAC;CAShB"}
|
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
import { Address } from "@multiversx/sdk-core";
|
|
2
|
+
import BIPPath from "bip32-path";
|
|
3
|
+
const CHUNK_SIZE = 150;
|
|
4
|
+
const CURVE_MASK = 0x80;
|
|
5
|
+
const CLA = 0xed;
|
|
6
|
+
const INS = {
|
|
7
|
+
GET_VERSION: 0x02,
|
|
8
|
+
GET_ADDRESS: 0x03,
|
|
9
|
+
SET_ADDRESS: 0x05,
|
|
10
|
+
PROVIDE_ESDT_INFO: 0x08,
|
|
11
|
+
};
|
|
12
|
+
const SIGN_HASH_TX_INS = 0x07;
|
|
13
|
+
const SW_OK = 0x9000;
|
|
14
|
+
const SW_CANCEL = 0x6986;
|
|
15
|
+
/**
|
|
16
|
+
* MultiversX API
|
|
17
|
+
*
|
|
18
|
+
* @example
|
|
19
|
+
* import MultiversX from "@ledgerhq/hw-app-multiversx";
|
|
20
|
+
* const multiversx = new MultiversX(transport)
|
|
21
|
+
*/
|
|
22
|
+
export default class MultiversX {
|
|
23
|
+
transport;
|
|
24
|
+
constructor(transport, scrambleKey = "eGLD") {
|
|
25
|
+
this.transport = transport;
|
|
26
|
+
transport.decorateAppAPIMethods(this, [
|
|
27
|
+
"getAddress",
|
|
28
|
+
"setAddress",
|
|
29
|
+
"signTransaction",
|
|
30
|
+
"signMessage",
|
|
31
|
+
"getAppConfiguration",
|
|
32
|
+
"provideESDTInfo",
|
|
33
|
+
], scrambleKey);
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Get MultiversX app configuration.
|
|
37
|
+
*
|
|
38
|
+
* @return an object with a contractData, accountIndex, addressIndex, version
|
|
39
|
+
* @example
|
|
40
|
+
* const result = await multiversx.getAppConfiguration();
|
|
41
|
+
* const { contractData, accountIndex, addressIndex, version } = result;
|
|
42
|
+
*/
|
|
43
|
+
async getAppConfiguration() {
|
|
44
|
+
const response = await this.transport.send(CLA, INS.GET_VERSION, 0x00, 0x00);
|
|
45
|
+
return {
|
|
46
|
+
contractData: response[0],
|
|
47
|
+
accountIndex: response[1],
|
|
48
|
+
addressIndex: response[2],
|
|
49
|
+
version: `${response[3]}.${response[4]}.${response[5]}`,
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
serializePath(path) {
|
|
53
|
+
const buf = Buffer.alloc(8);
|
|
54
|
+
buf.writeUInt32BE(path[3], 0);
|
|
55
|
+
buf.writeUInt32BE(path[2], 4);
|
|
56
|
+
return buf;
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Get MultiversX address for a given BIP 32 path.
|
|
60
|
+
*
|
|
61
|
+
* @param path a path in BIP 32 format
|
|
62
|
+
* @param boolDisplay optionally enable or not the display
|
|
63
|
+
* @return an object with a address
|
|
64
|
+
* @example
|
|
65
|
+
* const result = await multiversx.getAddress("44'/508'/0'/0'/0'");
|
|
66
|
+
* const { publicKey, address } = result;
|
|
67
|
+
*/
|
|
68
|
+
async getAddress(path, boolDisplay) {
|
|
69
|
+
const bipPath = BIPPath.fromString(path).toPathArray();
|
|
70
|
+
const data = this.serializePath(bipPath);
|
|
71
|
+
const response = await this.transport.send(CLA, INS.GET_ADDRESS, boolDisplay ? 0x01 : 0x00, 0x00, data, [SW_OK, SW_CANCEL]);
|
|
72
|
+
const addressLength = response[0];
|
|
73
|
+
const address = Address.newFromBech32(response.slice(1, 1 + addressLength).toString("ascii"));
|
|
74
|
+
return {
|
|
75
|
+
publicKey: address.toHex(),
|
|
76
|
+
address: address.toBech32(),
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Set MultiversX address for a given BIP 32 path.
|
|
81
|
+
*
|
|
82
|
+
* @param path a path in BIP 32 format
|
|
83
|
+
* @param display optionally enable or not the display
|
|
84
|
+
* @return an object with a address
|
|
85
|
+
* @example
|
|
86
|
+
* const result = await multiversx.setAddress("44'/508'/0'/0/0");
|
|
87
|
+
* result : Buffer;
|
|
88
|
+
*/
|
|
89
|
+
async setAddress(path, display) {
|
|
90
|
+
const bipPath = BIPPath.fromString(path).toPathArray();
|
|
91
|
+
const data = this.serializePath(bipPath);
|
|
92
|
+
await this.transport.send(CLA, INS.SET_ADDRESS, display ? 0x01 : 0x00, 0x00, data, [
|
|
93
|
+
SW_OK,
|
|
94
|
+
SW_CANCEL,
|
|
95
|
+
]);
|
|
96
|
+
}
|
|
97
|
+
async signTransaction(path, message) {
|
|
98
|
+
const { signature } = await this.sign(path, message);
|
|
99
|
+
if (signature === null) {
|
|
100
|
+
throw new Error("null signature received");
|
|
101
|
+
}
|
|
102
|
+
return signature.toString("hex");
|
|
103
|
+
}
|
|
104
|
+
async sign(path, message) {
|
|
105
|
+
const chunks = [];
|
|
106
|
+
const buffer = Buffer.from(message);
|
|
107
|
+
for (let i = 0; i < buffer.length; i += CHUNK_SIZE) {
|
|
108
|
+
let end = i + CHUNK_SIZE;
|
|
109
|
+
if (i > buffer.length) {
|
|
110
|
+
end = buffer.length;
|
|
111
|
+
}
|
|
112
|
+
chunks.push(buffer.slice(i, end));
|
|
113
|
+
}
|
|
114
|
+
const apdus = [];
|
|
115
|
+
chunks.forEach((data, index) => {
|
|
116
|
+
const apdu = {
|
|
117
|
+
cla: CLA,
|
|
118
|
+
ins: SIGN_HASH_TX_INS,
|
|
119
|
+
p1: index === 0 ? 0x00 : CURVE_MASK,
|
|
120
|
+
p2: CURVE_MASK,
|
|
121
|
+
data,
|
|
122
|
+
};
|
|
123
|
+
apdus.push(apdu);
|
|
124
|
+
});
|
|
125
|
+
let response = {};
|
|
126
|
+
for (const apdu of apdus) {
|
|
127
|
+
response = await this.transport.send(apdu.cla, apdu.ins, apdu.p1, apdu.p2, apdu.data);
|
|
128
|
+
}
|
|
129
|
+
if (response.length !== 67 || response[0] !== 64) {
|
|
130
|
+
throw new Error("invalid signature received from ledger device");
|
|
131
|
+
}
|
|
132
|
+
const signature = response.slice(1, response.length - 2).toString("hex");
|
|
133
|
+
return { signature };
|
|
134
|
+
}
|
|
135
|
+
serializeESDTInfo(ticker, id, decimals, chainId, signature) {
|
|
136
|
+
const tickerLengthBuffer = Buffer.from([ticker.length]);
|
|
137
|
+
const tickerBuffer = Buffer.from(ticker);
|
|
138
|
+
const idLengthBuffer = Buffer.from([id.length]);
|
|
139
|
+
const idBuffer = Buffer.from(id);
|
|
140
|
+
const decimalsBuffer = Buffer.from([decimals]);
|
|
141
|
+
const chainIdLengthBuffer = Buffer.from([chainId.length]);
|
|
142
|
+
const chainIdBuffer = Buffer.from(chainId);
|
|
143
|
+
const signatureBuffer = Buffer.from(signature, "hex");
|
|
144
|
+
const infoBuffer = [
|
|
145
|
+
tickerLengthBuffer,
|
|
146
|
+
tickerBuffer,
|
|
147
|
+
idLengthBuffer,
|
|
148
|
+
idBuffer,
|
|
149
|
+
decimalsBuffer,
|
|
150
|
+
chainIdLengthBuffer,
|
|
151
|
+
chainIdBuffer,
|
|
152
|
+
signatureBuffer,
|
|
153
|
+
];
|
|
154
|
+
return Buffer.concat(infoBuffer);
|
|
155
|
+
}
|
|
156
|
+
async provideESDTInfo(ticker, id, decimals, chainId, signature) {
|
|
157
|
+
if (!ticker || !id || !decimals || !chainId || !signature) {
|
|
158
|
+
throw new Error("Invalid ESDT token credentials!");
|
|
159
|
+
}
|
|
160
|
+
const data = this.serializeESDTInfo(ticker, id, decimals, chainId, signature);
|
|
161
|
+
return await this.transport.send(CLA, INS.PROVIDE_ESDT_INFO, 0x00, 0x00, data);
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
//# sourceMappingURL=MultiversX.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"MultiversX.js","sourceRoot":"","sources":["../src/MultiversX.ts"],"names":[],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@ledgerhq/hw-app-multiversx",
|
|
3
|
+
"version": "6.22.0-nightly.0",
|
|
4
|
+
"description": "Ledger Hardware Wallet MultiversX Application API",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"Ledger",
|
|
7
|
+
"LedgerWallet",
|
|
8
|
+
"egld",
|
|
9
|
+
"MultiversX",
|
|
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-multiversx",
|
|
22
|
+
"publishConfig": {
|
|
23
|
+
"access": "public"
|
|
24
|
+
},
|
|
25
|
+
"main": "lib/MultiversX.js",
|
|
26
|
+
"module": "lib-es/MultiversX.js",
|
|
27
|
+
"types": "lib/MultiversX.d.ts",
|
|
28
|
+
"license": "Apache-2.0",
|
|
29
|
+
"dependencies": {
|
|
30
|
+
"@multiversx/sdk-core": "^13.7.0",
|
|
31
|
+
"bignumber.js": "^9.0.1",
|
|
32
|
+
"bip32-path": "^0.4.2",
|
|
33
|
+
"protobufjs": "^7.2.6",
|
|
34
|
+
"axios": "^1.7.4",
|
|
35
|
+
"@ledgerhq/hw-transport": "^6.31.4"
|
|
36
|
+
},
|
|
37
|
+
"devDependencies": {
|
|
38
|
+
"@types/jest": "^29.5.10",
|
|
39
|
+
"@types/node": "^22.10.10",
|
|
40
|
+
"documentation": "14.0.2",
|
|
41
|
+
"jest": "^29.7.0",
|
|
42
|
+
"rimraf": "^4.4.1",
|
|
43
|
+
"source-map-support": "^0.5.21",
|
|
44
|
+
"ts-jest": "^29.1.1",
|
|
45
|
+
"ts-node": "^10.4.0",
|
|
46
|
+
"@ledgerhq/hw-transport-mocker": "^6.29.4"
|
|
47
|
+
},
|
|
48
|
+
"scripts": {
|
|
49
|
+
"clean": "rimraf lib lib-es",
|
|
50
|
+
"build": "tsc && tsc -m esnext --moduleResolution bundler --outDir lib-es",
|
|
51
|
+
"prewatch": "pnpm build",
|
|
52
|
+
"watch": "tsc --watch",
|
|
53
|
+
"watch:es": "tsc --watch -m esnext --moduleResolution bundler --outDir lib-es",
|
|
54
|
+
"doc": "documentation readme src/** --section=API --pe ts --re ts --re d.ts",
|
|
55
|
+
"lint": "eslint ./src --no-error-on-unmatched-pattern --ext .ts,.tsx --cache",
|
|
56
|
+
"lint:fix": "pnpm lint --fix",
|
|
57
|
+
"test": "jest",
|
|
58
|
+
"unimported": "unimported"
|
|
59
|
+
}
|
|
60
|
+
}
|
|
@@ -0,0 +1,217 @@
|
|
|
1
|
+
import type Transport from "@ledgerhq/hw-transport";
|
|
2
|
+
import { Address } from "@multiversx/sdk-core";
|
|
3
|
+
import BIPPath from "bip32-path";
|
|
4
|
+
|
|
5
|
+
const CHUNK_SIZE = 150;
|
|
6
|
+
const CURVE_MASK = 0x80;
|
|
7
|
+
const CLA = 0xed;
|
|
8
|
+
const INS = {
|
|
9
|
+
GET_VERSION: 0x02,
|
|
10
|
+
GET_ADDRESS: 0x03,
|
|
11
|
+
SET_ADDRESS: 0x05,
|
|
12
|
+
PROVIDE_ESDT_INFO: 0x08,
|
|
13
|
+
};
|
|
14
|
+
const SIGN_HASH_TX_INS = 0x07;
|
|
15
|
+
const SW_OK = 0x9000;
|
|
16
|
+
const SW_CANCEL = 0x6986;
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* MultiversX API
|
|
20
|
+
*
|
|
21
|
+
* @example
|
|
22
|
+
* import MultiversX from "@ledgerhq/hw-app-multiversx";
|
|
23
|
+
* const multiversx = new MultiversX(transport)
|
|
24
|
+
*/
|
|
25
|
+
export default class MultiversX {
|
|
26
|
+
transport: Transport;
|
|
27
|
+
|
|
28
|
+
constructor(transport: Transport, scrambleKey = "eGLD") {
|
|
29
|
+
this.transport = transport;
|
|
30
|
+
transport.decorateAppAPIMethods(
|
|
31
|
+
this,
|
|
32
|
+
[
|
|
33
|
+
"getAddress",
|
|
34
|
+
"setAddress",
|
|
35
|
+
"signTransaction",
|
|
36
|
+
"signMessage",
|
|
37
|
+
"getAppConfiguration",
|
|
38
|
+
"provideESDTInfo",
|
|
39
|
+
],
|
|
40
|
+
scrambleKey,
|
|
41
|
+
);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Get MultiversX app configuration.
|
|
46
|
+
*
|
|
47
|
+
* @return an object with a contractData, accountIndex, addressIndex, version
|
|
48
|
+
* @example
|
|
49
|
+
* const result = await multiversx.getAppConfiguration();
|
|
50
|
+
* const { contractData, accountIndex, addressIndex, version } = result;
|
|
51
|
+
*/
|
|
52
|
+
async getAppConfiguration(): Promise<any> {
|
|
53
|
+
const response = await this.transport.send(CLA, INS.GET_VERSION, 0x00, 0x00);
|
|
54
|
+
return {
|
|
55
|
+
contractData: response[0],
|
|
56
|
+
accountIndex: response[1],
|
|
57
|
+
addressIndex: response[2],
|
|
58
|
+
version: `${response[3]}.${response[4]}.${response[5]}`,
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
serializePath(path: Array<number>) {
|
|
63
|
+
const buf = Buffer.alloc(8);
|
|
64
|
+
buf.writeUInt32BE(path[3], 0);
|
|
65
|
+
buf.writeUInt32BE(path[2], 4);
|
|
66
|
+
return buf;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Get MultiversX address for a given BIP 32 path.
|
|
71
|
+
*
|
|
72
|
+
* @param path a path in BIP 32 format
|
|
73
|
+
* @param boolDisplay optionally enable or not the display
|
|
74
|
+
* @return an object with a address
|
|
75
|
+
* @example
|
|
76
|
+
* const result = await multiversx.getAddress("44'/508'/0'/0'/0'");
|
|
77
|
+
* const { publicKey, address } = result;
|
|
78
|
+
*/
|
|
79
|
+
async getAddress(
|
|
80
|
+
path: string,
|
|
81
|
+
boolDisplay?: boolean,
|
|
82
|
+
): Promise<{
|
|
83
|
+
publicKey: string;
|
|
84
|
+
address: string;
|
|
85
|
+
}> {
|
|
86
|
+
const bipPath = BIPPath.fromString(path).toPathArray();
|
|
87
|
+
const data = this.serializePath(bipPath);
|
|
88
|
+
const response = await this.transport.send(
|
|
89
|
+
CLA,
|
|
90
|
+
INS.GET_ADDRESS,
|
|
91
|
+
boolDisplay ? 0x01 : 0x00,
|
|
92
|
+
0x00,
|
|
93
|
+
data,
|
|
94
|
+
[SW_OK, SW_CANCEL],
|
|
95
|
+
);
|
|
96
|
+
|
|
97
|
+
const addressLength = response[0];
|
|
98
|
+
const address = Address.newFromBech32(response.slice(1, 1 + addressLength).toString("ascii"));
|
|
99
|
+
|
|
100
|
+
return {
|
|
101
|
+
publicKey: address.toHex(),
|
|
102
|
+
address: address.toBech32(),
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* Set MultiversX address for a given BIP 32 path.
|
|
108
|
+
*
|
|
109
|
+
* @param path a path in BIP 32 format
|
|
110
|
+
* @param display optionally enable or not the display
|
|
111
|
+
* @return an object with a address
|
|
112
|
+
* @example
|
|
113
|
+
* const result = await multiversx.setAddress("44'/508'/0'/0/0");
|
|
114
|
+
* result : Buffer;
|
|
115
|
+
*/
|
|
116
|
+
async setAddress(path: string, display?: boolean) {
|
|
117
|
+
const bipPath = BIPPath.fromString(path).toPathArray();
|
|
118
|
+
const data = this.serializePath(bipPath);
|
|
119
|
+
await this.transport.send(CLA, INS.SET_ADDRESS, display ? 0x01 : 0x00, 0x00, data, [
|
|
120
|
+
SW_OK,
|
|
121
|
+
SW_CANCEL,
|
|
122
|
+
]);
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
async signTransaction(path: string, message: string): Promise<string> {
|
|
126
|
+
const { signature } = await this.sign(path, message);
|
|
127
|
+
|
|
128
|
+
if (signature === null) {
|
|
129
|
+
throw new Error("null signature received");
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
return signature.toString("hex");
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
async sign(path: string, message: string): Promise<{ signature: null | Buffer }> {
|
|
136
|
+
const chunks: Buffer[] = [];
|
|
137
|
+
const buffer: Buffer = Buffer.from(message);
|
|
138
|
+
|
|
139
|
+
for (let i = 0; i < buffer.length; i += CHUNK_SIZE) {
|
|
140
|
+
let end = i + CHUNK_SIZE;
|
|
141
|
+
|
|
142
|
+
if (i > buffer.length) {
|
|
143
|
+
end = buffer.length;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
chunks.push(buffer.slice(i, end));
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
const apdus: any[] = [];
|
|
150
|
+
chunks.forEach((data, index) => {
|
|
151
|
+
const apdu: any = {
|
|
152
|
+
cla: CLA,
|
|
153
|
+
ins: SIGN_HASH_TX_INS,
|
|
154
|
+
p1: index === 0 ? 0x00 : CURVE_MASK,
|
|
155
|
+
p2: CURVE_MASK,
|
|
156
|
+
data,
|
|
157
|
+
};
|
|
158
|
+
apdus.push(apdu);
|
|
159
|
+
});
|
|
160
|
+
|
|
161
|
+
let response: any = {};
|
|
162
|
+
for (const apdu of apdus) {
|
|
163
|
+
response = await this.transport.send(apdu.cla, apdu.ins, apdu.p1, apdu.p2, apdu.data);
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
if (response.length !== 67 || response[0] !== 64) {
|
|
167
|
+
throw new Error("invalid signature received from ledger device");
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
const signature = response.slice(1, response.length - 2).toString("hex");
|
|
171
|
+
return { signature };
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
serializeESDTInfo(
|
|
175
|
+
ticker: string,
|
|
176
|
+
id: string,
|
|
177
|
+
decimals: number,
|
|
178
|
+
chainId: string,
|
|
179
|
+
signature: string,
|
|
180
|
+
): Buffer {
|
|
181
|
+
const tickerLengthBuffer = Buffer.from([ticker.length]);
|
|
182
|
+
const tickerBuffer = Buffer.from(ticker);
|
|
183
|
+
const idLengthBuffer = Buffer.from([id.length]);
|
|
184
|
+
const idBuffer = Buffer.from(id);
|
|
185
|
+
const decimalsBuffer = Buffer.from([decimals]);
|
|
186
|
+
const chainIdLengthBuffer = Buffer.from([chainId.length]);
|
|
187
|
+
const chainIdBuffer = Buffer.from(chainId);
|
|
188
|
+
const signatureBuffer = Buffer.from(signature, "hex");
|
|
189
|
+
const infoBuffer = [
|
|
190
|
+
tickerLengthBuffer,
|
|
191
|
+
tickerBuffer,
|
|
192
|
+
idLengthBuffer,
|
|
193
|
+
idBuffer,
|
|
194
|
+
decimalsBuffer,
|
|
195
|
+
chainIdLengthBuffer,
|
|
196
|
+
chainIdBuffer,
|
|
197
|
+
signatureBuffer,
|
|
198
|
+
];
|
|
199
|
+
return Buffer.concat(infoBuffer);
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
async provideESDTInfo(
|
|
203
|
+
ticker?: string,
|
|
204
|
+
id?: string,
|
|
205
|
+
decimals?: number,
|
|
206
|
+
chainId?: string,
|
|
207
|
+
signature?: string,
|
|
208
|
+
): Promise<any> {
|
|
209
|
+
if (!ticker || !id || !decimals || !chainId || !signature) {
|
|
210
|
+
throw new Error("Invalid ESDT token credentials!");
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
const data = this.serializeESDTInfo(ticker, id, decimals, chainId, signature);
|
|
214
|
+
|
|
215
|
+
return await this.transport.send(CLA, INS.PROVIDE_ESDT_INFO, 0x00, 0x00, data);
|
|
216
|
+
}
|
|
217
|
+
}
|