@ledgerhq/hw-app-cosmos 6.11.2 → 6.25.1-alpha.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/lib-es/Cosmos.js.flow +194 -0
- package/package.json +3 -3
|
@@ -0,0 +1,194 @@
|
|
|
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
|
+
//@flow
|
|
18
|
+
|
|
19
|
+
import type Transport from "@ledgerhq/hw-transport";
|
|
20
|
+
import BIPPath from "bip32-path";
|
|
21
|
+
import { UserRefusedOnDevice } from "@ledgerhq/errors";
|
|
22
|
+
const CHUNK_SIZE = 250;
|
|
23
|
+
const CLA = 0x55;
|
|
24
|
+
const APP_KEY = "CSM";
|
|
25
|
+
const INS_GET_VERSION = 0x00;
|
|
26
|
+
const INS_SIGN_SECP256K1 = 0x02;
|
|
27
|
+
const INS_GET_ADDR_SECP256K1 = 0x04;
|
|
28
|
+
|
|
29
|
+
const PAYLOAD_TYPE_INIT = 0x00;
|
|
30
|
+
const PAYLOAD_TYPE_ADD = 0x01;
|
|
31
|
+
const PAYLOAD_TYPE_LAST = 0x02;
|
|
32
|
+
|
|
33
|
+
const SW_OK = 0x9000;
|
|
34
|
+
const SW_CANCEL = 0x6986;
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Cosmos API
|
|
38
|
+
*
|
|
39
|
+
* @example
|
|
40
|
+
* import Cosmos from "@ledgerhq/hw-app-cosmos";
|
|
41
|
+
* const cosmos = new Cosmos(transport)
|
|
42
|
+
*/
|
|
43
|
+
export default class Cosmos {
|
|
44
|
+
transport: Transport<*>;
|
|
45
|
+
|
|
46
|
+
constructor(transport: Transport<*>, scrambleKey: string = APP_KEY) {
|
|
47
|
+
this.transport = transport;
|
|
48
|
+
transport.decorateAppAPIMethods(
|
|
49
|
+
this,
|
|
50
|
+
["getAddress", "sign", "getAppConfiguration"],
|
|
51
|
+
scrambleKey
|
|
52
|
+
);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
getAppConfiguration(): {
|
|
56
|
+
test_mode: boolean,
|
|
57
|
+
version: string,
|
|
58
|
+
device_locked: boolean,
|
|
59
|
+
major: string,
|
|
60
|
+
} {
|
|
61
|
+
return this.transport.send(CLA, INS_GET_VERSION, 0, 0).then((response) => {
|
|
62
|
+
return {
|
|
63
|
+
test_mode: response[0] !== 0,
|
|
64
|
+
version: "" + response[1] + "." + response[2] + "." + response[3],
|
|
65
|
+
device_locked: response[4] === 1,
|
|
66
|
+
major: response[1],
|
|
67
|
+
};
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
serializePath(path: Buffer): Buffer {
|
|
72
|
+
const buf = Buffer.alloc(20);
|
|
73
|
+
// HACK : without the >>>,
|
|
74
|
+
// the bitwise implicitly casts the result to be a signed int32,
|
|
75
|
+
// which fails the internal type check of Buffer in case of overload.
|
|
76
|
+
buf.writeUInt32LE((0x80000000 | path[0]) >>> 0, 0);
|
|
77
|
+
buf.writeUInt32LE((0x80000000 | path[1]) >>> 0, 4);
|
|
78
|
+
buf.writeUInt32LE((0x80000000 | path[2]) >>> 0, 8);
|
|
79
|
+
buf.writeUInt32LE(path[3], 12);
|
|
80
|
+
buf.writeUInt32LE(path[4], 16);
|
|
81
|
+
|
|
82
|
+
return buf;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
serializeHRP(hrp: string): Buffer {
|
|
86
|
+
if (hrp == null || hrp.length < 3 || hrp.length > 83) {
|
|
87
|
+
throw new Error("Invalid HRP");
|
|
88
|
+
}
|
|
89
|
+
const buf = Buffer.alloc(1 + hrp.length);
|
|
90
|
+
buf.writeUInt8(hrp.length, 0);
|
|
91
|
+
buf.write(hrp, 1);
|
|
92
|
+
return buf;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* get Cosmos address for a given BIP 32 path.
|
|
97
|
+
* @param path a path in BIP 32 format
|
|
98
|
+
* @param hrp usually cosmos
|
|
99
|
+
* @option boolDisplay optionally enable or not the display
|
|
100
|
+
* @return an object with a publicKey, address and (optionally) chainCode
|
|
101
|
+
* @example
|
|
102
|
+
* cosmos.getAddress("44'/60'/0'/0/0", "cosmos").then(o => o.address)
|
|
103
|
+
*/
|
|
104
|
+
getAddress(
|
|
105
|
+
path: string,
|
|
106
|
+
hrp: string,
|
|
107
|
+
boolDisplay?: boolean
|
|
108
|
+
): Promise<{ publicKey: string, address: string }> {
|
|
109
|
+
const bipPath = BIPPath.fromString(path).toPathArray();
|
|
110
|
+
const serializedPath = this.serializePath(bipPath);
|
|
111
|
+
const data = Buffer.concat([this.serializeHRP(hrp), serializedPath]);
|
|
112
|
+
|
|
113
|
+
return this.transport
|
|
114
|
+
.send(CLA, INS_GET_ADDR_SECP256K1, boolDisplay ? 1 : 0, 0, data, [SW_OK])
|
|
115
|
+
.then((response) => {
|
|
116
|
+
const address = Buffer.from(response.slice(33, -2)).toString();
|
|
117
|
+
const publicKey = Buffer.from(response.slice(0, 33)).toString("hex");
|
|
118
|
+
|
|
119
|
+
return {
|
|
120
|
+
address,
|
|
121
|
+
publicKey,
|
|
122
|
+
};
|
|
123
|
+
});
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
foreach<T, A>(arr: T[], callback: (T, number) => Promise<A>): Promise<A[]> {
|
|
127
|
+
function iterate(index, array, result) {
|
|
128
|
+
if (index >= array.length) {
|
|
129
|
+
return result;
|
|
130
|
+
} else
|
|
131
|
+
return callback(array[index], index).then(function (res) {
|
|
132
|
+
result.push(res);
|
|
133
|
+
return iterate(index + 1, array, result);
|
|
134
|
+
});
|
|
135
|
+
}
|
|
136
|
+
return Promise.resolve().then(() => iterate(0, arr, []));
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
async sign(
|
|
140
|
+
path: string,
|
|
141
|
+
message: string
|
|
142
|
+
): Promise<{ signature: null | Buffer, return_code: number }> {
|
|
143
|
+
const bipPath = BIPPath.fromString(path).toPathArray();
|
|
144
|
+
const serializedPath = this.serializePath(bipPath);
|
|
145
|
+
|
|
146
|
+
const chunks = [];
|
|
147
|
+
chunks.push(serializedPath);
|
|
148
|
+
const buffer = Buffer.from(message);
|
|
149
|
+
|
|
150
|
+
for (let i = 0; i < buffer.length; i += CHUNK_SIZE) {
|
|
151
|
+
let end = i + CHUNK_SIZE;
|
|
152
|
+
if (i > buffer.length) {
|
|
153
|
+
end = buffer.length;
|
|
154
|
+
}
|
|
155
|
+
chunks.push(buffer.slice(i, end));
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
let response = {};
|
|
159
|
+
|
|
160
|
+
return this.foreach(chunks, (data, j) =>
|
|
161
|
+
this.transport
|
|
162
|
+
.send(
|
|
163
|
+
CLA,
|
|
164
|
+
INS_SIGN_SECP256K1,
|
|
165
|
+
j === 0
|
|
166
|
+
? PAYLOAD_TYPE_INIT
|
|
167
|
+
: j + 1 === chunks.length
|
|
168
|
+
? PAYLOAD_TYPE_LAST
|
|
169
|
+
: PAYLOAD_TYPE_ADD,
|
|
170
|
+
0,
|
|
171
|
+
data,
|
|
172
|
+
[SW_OK, SW_CANCEL]
|
|
173
|
+
)
|
|
174
|
+
.then((apduResponse) => (response = apduResponse))
|
|
175
|
+
).then(() => {
|
|
176
|
+
const errorCodeData = response.slice(-2);
|
|
177
|
+
const returnCode = errorCodeData[0] * 256 + errorCodeData[1];
|
|
178
|
+
|
|
179
|
+
let signature = null;
|
|
180
|
+
if (response.length > 2) {
|
|
181
|
+
signature = response.slice(0, response.length - 2);
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
if (returnCode === 0x6986) {
|
|
185
|
+
throw new UserRefusedOnDevice();
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
return {
|
|
189
|
+
signature: signature,
|
|
190
|
+
return_code: returnCode,
|
|
191
|
+
};
|
|
192
|
+
});
|
|
193
|
+
}
|
|
194
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ledgerhq/hw-app-cosmos",
|
|
3
|
-
"version": "6.
|
|
3
|
+
"version": "6.25.1-alpha.3+eb669e17",
|
|
4
4
|
"description": "Ledger Hardware Wallet Cosmos Application API",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"Ledger",
|
|
@@ -28,7 +28,7 @@
|
|
|
28
28
|
"license": "Apache-2.0",
|
|
29
29
|
"dependencies": {
|
|
30
30
|
"@ledgerhq/errors": "^6.10.0",
|
|
31
|
-
"@ledgerhq/hw-transport": "^6.
|
|
31
|
+
"@ledgerhq/hw-transport": "^6.25.1-alpha.3+eb669e17",
|
|
32
32
|
"bip32-path": "^0.4.2"
|
|
33
33
|
},
|
|
34
34
|
"scripts": {
|
|
@@ -37,5 +37,5 @@
|
|
|
37
37
|
"watch": "bash ../../script/watch.sh",
|
|
38
38
|
"doc": "bash ../../script/doc.sh"
|
|
39
39
|
},
|
|
40
|
-
"gitHead": "
|
|
40
|
+
"gitHead": "eb669e17dd87d3ab568beab1f9a5ddb1a2536e83"
|
|
41
41
|
}
|