@ledgerhq/hw-app-str 6.29.0-windows-certificate.0 → 6.29.1-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 +1 -1
- package/CHANGELOG.md +22 -3
- package/README.md +161 -57
- package/lib/Str.d.ts +43 -18
- package/lib/Str.d.ts.map +1 -1
- package/lib/Str.js +166 -175
- package/lib/Str.js.map +1 -1
- package/lib/errors.d.ts +27 -0
- package/lib/errors.d.ts.map +1 -0
- package/lib/errors.js +23 -0
- package/lib/errors.js.map +1 -0
- package/lib-es/Str.d.ts +43 -18
- package/lib-es/Str.d.ts.map +1 -1
- package/lib-es/Str.js +149 -175
- package/lib-es/Str.js.map +1 -1
- package/lib-es/errors.d.ts +27 -0
- package/lib-es/errors.d.ts.map +1 -0
- package/lib-es/errors.js +20 -0
- package/lib-es/errors.js.map +1 -0
- package/package.json +6 -6
- package/src/Str.ts +168 -234
- package/src/errors.ts +27 -0
- package/tests/Str.test.ts +322 -17
- package/lib/utils.d.ts +0 -9
- package/lib/utils.d.ts.map +0 -1
- package/lib/utils.js +0 -106
- package/lib/utils.js.map +0 -1
- package/lib-es/utils.d.ts +0 -9
- package/lib-es/utils.d.ts.map +0 -1
- package/lib-es/utils.js +0 -93
- package/lib-es/utils.js.map +0 -1
- package/src/utils.ts +0 -111
package/src/Str.ts
CHANGED
|
@@ -15,301 +15,235 @@
|
|
|
15
15
|
* limitations under the License.
|
|
16
16
|
********************************************************************************/
|
|
17
17
|
import type Transport from "@ledgerhq/hw-transport";
|
|
18
|
+
import BIPPath from "bip32-path";
|
|
18
19
|
import {
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
} from "./utils";
|
|
20
|
+
StellarHashSigningNotEnabledError,
|
|
21
|
+
StellarDataParsingFailedError,
|
|
22
|
+
StellarUserRefusedError,
|
|
23
|
+
StellarDataTooLargeError,
|
|
24
|
+
} from "./errors";
|
|
25
|
+
|
|
26
26
|
const CLA = 0xe0;
|
|
27
|
+
const P1_FIRST = 0x00;
|
|
28
|
+
const P1_MORE = 0x80;
|
|
29
|
+
const P2_LAST = 0x00;
|
|
30
|
+
const P2_MORE = 0x80;
|
|
31
|
+
const P2_NON_CONFIRM = 0x00; // for getPublicKey
|
|
32
|
+
const P2_CONFIRM = 0x01; // for getPublicKey
|
|
33
|
+
|
|
27
34
|
const INS_GET_PK = 0x02;
|
|
28
35
|
const INS_SIGN_TX = 0x04;
|
|
29
36
|
const INS_GET_CONF = 0x06;
|
|
30
|
-
const
|
|
31
|
-
const
|
|
32
|
-
|
|
33
|
-
const
|
|
34
|
-
|
|
35
|
-
const
|
|
36
|
-
const
|
|
37
|
-
const
|
|
38
|
-
const
|
|
39
|
-
|
|
40
|
-
const SW_MULTI_OP = 0x6c25;
|
|
41
|
-
const SW_NOT_ALLOWED = 0x6c66;
|
|
42
|
-
const SW_UNSUPPORTED = 0x6d00;
|
|
43
|
-
const SW_KEEP_ALIVE = 0x6e02;
|
|
44
|
-
const TX_MAX_SIZE = 1540;
|
|
37
|
+
const INS_SIGN_HASH = 0x08;
|
|
38
|
+
const INS_SIGN_SOROBAN_AUTHORIZATION = 0x0a;
|
|
39
|
+
|
|
40
|
+
const APDU_MAX_PAYLOAD = 255;
|
|
41
|
+
|
|
42
|
+
const SW_DENY = 0x6985;
|
|
43
|
+
const SW_HASH_SIGNING_MODE_NOT_ENABLED = 0x6c66;
|
|
44
|
+
const SW_DATA_TOO_LARGE = 0xb004;
|
|
45
|
+
const SW_DATA_PARSING_FAIL = 0xb005;
|
|
46
|
+
|
|
45
47
|
/**
|
|
46
48
|
* Stellar API
|
|
47
49
|
*
|
|
50
|
+
* @param transport a transport for sending commands to a device
|
|
51
|
+
* @param scrambleKey a scramble key
|
|
52
|
+
*
|
|
48
53
|
* @example
|
|
49
54
|
* import Str from "@ledgerhq/hw-app-str";
|
|
50
55
|
* const str = new Str(transport)
|
|
51
56
|
*/
|
|
52
|
-
|
|
53
57
|
export default class Str {
|
|
54
|
-
transport: Transport;
|
|
58
|
+
private transport: Transport;
|
|
55
59
|
|
|
56
60
|
constructor(transport: Transport, scrambleKey = "l0v") {
|
|
57
61
|
this.transport = transport;
|
|
58
62
|
transport.decorateAppAPIMethods(
|
|
59
63
|
this,
|
|
60
|
-
[
|
|
64
|
+
[
|
|
65
|
+
"getAppConfiguration",
|
|
66
|
+
"getPublicKey",
|
|
67
|
+
"signTransaction",
|
|
68
|
+
"signSorobanAuthorization",
|
|
69
|
+
"signHash",
|
|
70
|
+
],
|
|
61
71
|
scrambleKey,
|
|
62
72
|
);
|
|
63
73
|
}
|
|
64
74
|
|
|
65
|
-
|
|
75
|
+
/**
|
|
76
|
+
* Get Stellar application configuration.
|
|
77
|
+
*
|
|
78
|
+
* @returns an object with the application configuration, including the version,
|
|
79
|
+
* whether hash signing is enabled, and the maximum data size in bytes that the device can sign.
|
|
80
|
+
* @example
|
|
81
|
+
* str.getAppConfiguration().then(o => o.version)
|
|
82
|
+
*/
|
|
83
|
+
async getAppConfiguration(): Promise<{
|
|
66
84
|
version: string;
|
|
85
|
+
hashSigningEnabled: boolean;
|
|
86
|
+
maxDataSize?: number;
|
|
67
87
|
}> {
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
});
|
|
88
|
+
const resp = await this.sendToDevice(INS_GET_CONF, Buffer.alloc(0));
|
|
89
|
+
const [hashSigningEnabled, major, minor, patch, maxDataSizeHi, maxDataSizeLo] = resp;
|
|
90
|
+
return {
|
|
91
|
+
hashSigningEnabled: hashSigningEnabled === 0x01,
|
|
92
|
+
version: `${major}.${minor}.${patch}`,
|
|
93
|
+
maxDataSize: resp.length > 4 ? (maxDataSizeHi << 8) | maxDataSizeLo : undefined, // For compatibility with older app, let's remove this in the future
|
|
94
|
+
};
|
|
76
95
|
}
|
|
77
96
|
|
|
78
97
|
/**
|
|
79
|
-
*
|
|
98
|
+
* Get Stellar raw public key for a given BIP 32 path.
|
|
99
|
+
*
|
|
80
100
|
* @param path a path in BIP 32 format
|
|
81
|
-
* @
|
|
82
|
-
* @
|
|
83
|
-
*
|
|
84
|
-
* the raw ed25519 public key.
|
|
101
|
+
* @param display if true, the device will ask the user to confirm the address on the device, if false, it will return the raw public key directly
|
|
102
|
+
* @return an object with the raw ed25519 public key.
|
|
103
|
+
* If you want to convert it to string, you can use {@link https://stellar.github.io/js-stellar-base/StrKey.html#.encodeEd25519PublicKey StrKey.encodeEd25519PublicKey}
|
|
85
104
|
* @example
|
|
86
|
-
* str.getPublicKey("44'/148'/0'").then(o => o.
|
|
105
|
+
* str.getPublicKey("44'/148'/0'").then(o => o.rawPublicKey)
|
|
87
106
|
*/
|
|
88
|
-
getPublicKey(
|
|
89
|
-
path
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
const apdus: Buffer[] = [];
|
|
98
|
-
let response;
|
|
99
|
-
const pathElts = splitPath(path);
|
|
100
|
-
const buffer = Buffer.alloc(1 + pathElts.length * 4);
|
|
101
|
-
buffer[0] = pathElts.length;
|
|
102
|
-
pathElts.forEach((element, index) => {
|
|
103
|
-
buffer.writeUInt32BE(element, 1 + 4 * index);
|
|
104
|
-
});
|
|
105
|
-
const verifyMsg = Buffer.from("via lumina", "ascii");
|
|
106
|
-
apdus.push(Buffer.concat([buffer, verifyMsg]));
|
|
107
|
-
let keepAlive = false;
|
|
108
|
-
return foreach(apdus, data =>
|
|
109
|
-
this.transport
|
|
110
|
-
.send(
|
|
111
|
-
CLA,
|
|
112
|
-
keepAlive ? INS_KEEP_ALIVE : INS_GET_PK,
|
|
113
|
-
boolValidate ? 0x01 : 0x00,
|
|
114
|
-
boolDisplay ? 0x01 : 0x00,
|
|
115
|
-
data,
|
|
116
|
-
[SW_OK, SW_KEEP_ALIVE],
|
|
117
|
-
)
|
|
118
|
-
.then(apduResponse => {
|
|
119
|
-
const status = Buffer.from(apduResponse.slice(apduResponse.length - 2)).readUInt16BE(0);
|
|
120
|
-
|
|
121
|
-
if (status === SW_KEEP_ALIVE) {
|
|
122
|
-
keepAlive = true;
|
|
123
|
-
apdus.push(Buffer.alloc(0));
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
response = apduResponse;
|
|
127
|
-
}),
|
|
128
|
-
).then(() => {
|
|
129
|
-
// response = Buffer.from(response, 'hex');
|
|
130
|
-
let offset = 0;
|
|
131
|
-
const rawPublicKey = response.slice(offset, offset + 32);
|
|
132
|
-
offset += 32;
|
|
133
|
-
const publicKey = encodeEd25519PublicKey(rawPublicKey);
|
|
134
|
-
|
|
135
|
-
if (boolValidate) {
|
|
136
|
-
const signature = response.slice(offset, offset + 64);
|
|
137
|
-
|
|
138
|
-
if (!verifyEd25519Signature(verifyMsg, signature, rawPublicKey)) {
|
|
139
|
-
throw new Error("Bad signature. Keypair is invalid. Please report this.");
|
|
140
|
-
}
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
return {
|
|
144
|
-
publicKey: publicKey,
|
|
145
|
-
raw: rawPublicKey,
|
|
146
|
-
};
|
|
147
|
-
});
|
|
107
|
+
async getPublicKey(path: string, display = false): Promise<{ rawPublicKey: Buffer }> {
|
|
108
|
+
const pathBuffer = pathToBuffer(path);
|
|
109
|
+
const p2 = display ? P2_CONFIRM : P2_NON_CONFIRM;
|
|
110
|
+
try {
|
|
111
|
+
const data = await this.transport.send(CLA, INS_GET_PK, P1_FIRST, p2, pathBuffer);
|
|
112
|
+
return { rawPublicKey: data.slice(0, -2) };
|
|
113
|
+
} catch (e) {
|
|
114
|
+
throw remapErrors(e);
|
|
115
|
+
}
|
|
148
116
|
}
|
|
149
117
|
|
|
150
118
|
/**
|
|
151
|
-
*
|
|
119
|
+
* Sign a Stellar transaction.
|
|
120
|
+
*
|
|
152
121
|
* @param path a path in BIP 32 format
|
|
153
|
-
* @param transaction signature base of the transaction to sign
|
|
154
|
-
* @return an object with the signature
|
|
122
|
+
* @param transaction {@link https://stellar.github.io/js-stellar-base/Transaction.html#signatureBase signature base} of the transaction to sign
|
|
123
|
+
* @return an object with the signature
|
|
155
124
|
* @example
|
|
156
125
|
* str.signTransaction("44'/148'/0'", signatureBase).then(o => o.signature)
|
|
157
126
|
*/
|
|
158
|
-
signTransaction(
|
|
127
|
+
async signTransaction(
|
|
159
128
|
path: string,
|
|
160
129
|
transaction: Buffer,
|
|
161
130
|
): Promise<{
|
|
162
131
|
signature: Buffer;
|
|
163
132
|
}> {
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
"Transaction too large: max = " + TX_MAX_SIZE + "; actual = " + transaction.length,
|
|
169
|
-
);
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
const apdus: Buffer[] = [];
|
|
173
|
-
let response;
|
|
174
|
-
const pathElts = splitPath(path);
|
|
175
|
-
const bufferSize = 1 + pathElts.length * 4;
|
|
176
|
-
const buffer = Buffer.alloc(bufferSize);
|
|
177
|
-
buffer[0] = pathElts.length;
|
|
178
|
-
pathElts.forEach(function (element, index) {
|
|
179
|
-
buffer.writeUInt32BE(element, 1 + 4 * index);
|
|
180
|
-
});
|
|
181
|
-
let chunkSize = APDU_MAX_SIZE - bufferSize;
|
|
182
|
-
|
|
183
|
-
if (transaction.length <= chunkSize) {
|
|
184
|
-
// it fits in a single apdu
|
|
185
|
-
apdus.push(Buffer.concat([buffer, transaction]));
|
|
186
|
-
} else {
|
|
187
|
-
// we need to send multiple apdus to transmit the entire transaction
|
|
188
|
-
let chunk = Buffer.alloc(chunkSize);
|
|
189
|
-
let offset = 0;
|
|
190
|
-
transaction.copy(chunk, 0, offset, chunkSize);
|
|
191
|
-
apdus.push(Buffer.concat([buffer, chunk]));
|
|
192
|
-
offset += chunkSize;
|
|
193
|
-
|
|
194
|
-
while (offset < transaction.length) {
|
|
195
|
-
const remaining = transaction.length - offset;
|
|
196
|
-
chunkSize = remaining < APDU_MAX_SIZE ? remaining : APDU_MAX_SIZE;
|
|
197
|
-
chunk = Buffer.alloc(chunkSize);
|
|
198
|
-
transaction.copy(chunk, 0, offset, offset + chunkSize);
|
|
199
|
-
offset += chunkSize;
|
|
200
|
-
apdus.push(chunk);
|
|
201
|
-
}
|
|
202
|
-
}
|
|
203
|
-
|
|
204
|
-
let keepAlive = false;
|
|
205
|
-
return foreach(apdus, (data, i) =>
|
|
206
|
-
this.transport
|
|
207
|
-
.send(
|
|
208
|
-
CLA,
|
|
209
|
-
keepAlive ? INS_KEEP_ALIVE : INS_SIGN_TX,
|
|
210
|
-
i === 0 ? P1_FIRST_APDU : P1_MORE_APDU,
|
|
211
|
-
i === apdus.length - 1 ? P2_LAST_APDU : P2_MORE_APDU,
|
|
212
|
-
data,
|
|
213
|
-
[SW_OK, SW_CANCEL, SW_UNKNOWN_OP, SW_MULTI_OP, SW_KEEP_ALIVE],
|
|
214
|
-
)
|
|
215
|
-
.then(apduResponse => {
|
|
216
|
-
const status = Buffer.from(apduResponse.slice(apduResponse.length - 2)).readUInt16BE(0);
|
|
217
|
-
|
|
218
|
-
if (status === SW_KEEP_ALIVE) {
|
|
219
|
-
keepAlive = true;
|
|
220
|
-
apdus.push(Buffer.alloc(0));
|
|
221
|
-
}
|
|
222
|
-
|
|
223
|
-
response = apduResponse;
|
|
224
|
-
}),
|
|
225
|
-
).then(() => {
|
|
226
|
-
const status = Buffer.from(response.slice(response.length - 2)).readUInt16BE(0);
|
|
227
|
-
|
|
228
|
-
if (status === SW_OK) {
|
|
229
|
-
const signature = Buffer.from(response.slice(0, response.length - 2));
|
|
230
|
-
return {
|
|
231
|
-
signature: signature,
|
|
232
|
-
};
|
|
233
|
-
} else if (status === SW_UNKNOWN_OP) {
|
|
234
|
-
// pre-v2 app version: fall back on hash signing
|
|
235
|
-
return this.signHash_private(path, hash(transaction));
|
|
236
|
-
} else if (status === SW_MULTI_OP) {
|
|
237
|
-
// multi-operation transaction: attempt hash signing
|
|
238
|
-
return this.signHash_private(path, hash(transaction));
|
|
239
|
-
} else {
|
|
240
|
-
throw new Error("Transaction approval request was rejected");
|
|
241
|
-
}
|
|
242
|
-
});
|
|
133
|
+
const pathBuffer = pathToBuffer(path);
|
|
134
|
+
const payload = Buffer.concat([pathBuffer, transaction]);
|
|
135
|
+
const resp = await this.sendToDevice(INS_SIGN_TX, payload);
|
|
136
|
+
return { signature: resp };
|
|
243
137
|
}
|
|
244
138
|
|
|
245
139
|
/**
|
|
246
|
-
*
|
|
140
|
+
* Sign a Stellar Soroban authorization.
|
|
141
|
+
*
|
|
247
142
|
* @param path a path in BIP 32 format
|
|
248
|
-
* @param
|
|
143
|
+
* @param hashIdPreimage the {@link https://github.com/stellar/stellar-xdr/blob/1a04392432dacc0092caaeae22a600ea1af3c6a5/Stellar-transaction.x#L702-L709 Soroban authorization hashIdPreimage} to sign
|
|
249
144
|
* @return an object with the signature
|
|
250
145
|
* @example
|
|
251
|
-
* str.
|
|
146
|
+
* str.signSorobanAuthorization("44'/148'/0'", hashIdPreimage).then(o => o.signature)
|
|
252
147
|
*/
|
|
253
|
-
|
|
148
|
+
async signSorobanAuthorization(
|
|
254
149
|
path: string,
|
|
255
|
-
|
|
150
|
+
hashIdPreimage: Buffer,
|
|
256
151
|
): Promise<{
|
|
257
152
|
signature: Buffer;
|
|
258
153
|
}> {
|
|
259
|
-
|
|
260
|
-
|
|
154
|
+
const pathBuffer = pathToBuffer(path);
|
|
155
|
+
const payload = Buffer.concat([pathBuffer, hashIdPreimage]);
|
|
156
|
+
const resp = await this.sendToDevice(INS_SIGN_SOROBAN_AUTHORIZATION, payload);
|
|
157
|
+
return { signature: resp };
|
|
261
158
|
}
|
|
262
159
|
|
|
263
|
-
|
|
160
|
+
/**
|
|
161
|
+
* Sign a hash.
|
|
162
|
+
*
|
|
163
|
+
* @param path a path in BIP 32 format
|
|
164
|
+
* @param hash the hash to sign
|
|
165
|
+
* @return an object with the signature
|
|
166
|
+
* @example
|
|
167
|
+
* str.signHash("44'/148'/0'", hash).then(o => o.signature)
|
|
168
|
+
*/
|
|
169
|
+
async signHash(
|
|
264
170
|
path: string,
|
|
265
171
|
hash: Buffer,
|
|
266
172
|
): Promise<{
|
|
267
173
|
signature: Buffer;
|
|
268
174
|
}> {
|
|
269
|
-
const
|
|
270
|
-
|
|
271
|
-
const
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
pathElts.forEach(function (element, index) {
|
|
275
|
-
buffer.writeUInt32BE(element, 1 + 4 * index);
|
|
276
|
-
});
|
|
277
|
-
apdus.push(Buffer.concat([buffer, hash]));
|
|
278
|
-
let keepAlive = false;
|
|
279
|
-
return foreach(apdus, data =>
|
|
280
|
-
this.transport
|
|
281
|
-
.send(CLA, keepAlive ? INS_KEEP_ALIVE : INS_SIGN_TX_HASH, 0x00, 0x00, data, [
|
|
282
|
-
SW_OK,
|
|
283
|
-
SW_CANCEL,
|
|
284
|
-
SW_NOT_ALLOWED,
|
|
285
|
-
SW_UNSUPPORTED,
|
|
286
|
-
SW_KEEP_ALIVE,
|
|
287
|
-
])
|
|
288
|
-
.then(apduResponse => {
|
|
289
|
-
const status = Buffer.from(apduResponse.slice(apduResponse.length - 2)).readUInt16BE(0);
|
|
290
|
-
|
|
291
|
-
if (status === SW_KEEP_ALIVE) {
|
|
292
|
-
keepAlive = true;
|
|
293
|
-
apdus.push(Buffer.alloc(0));
|
|
294
|
-
}
|
|
295
|
-
|
|
296
|
-
response = apduResponse;
|
|
297
|
-
}),
|
|
298
|
-
).then(() => {
|
|
299
|
-
const status = Buffer.from(response.slice(response.length - 2)).readUInt16BE(0);
|
|
175
|
+
const pathBuffer = pathToBuffer(path);
|
|
176
|
+
const payload = Buffer.concat([pathBuffer, hash]);
|
|
177
|
+
const resp = await this.sendToDevice(INS_SIGN_HASH, payload);
|
|
178
|
+
return { signature: resp };
|
|
179
|
+
}
|
|
300
180
|
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
181
|
+
private async sendToDevice(instruction: number, payload: Buffer) {
|
|
182
|
+
let response: Buffer = Buffer.alloc(0);
|
|
183
|
+
let remaining = payload.length;
|
|
184
|
+
// eslint-disable-next-line no-constant-condition
|
|
185
|
+
while (true) {
|
|
186
|
+
const chunkSize = remaining > APDU_MAX_PAYLOAD ? APDU_MAX_PAYLOAD : remaining;
|
|
187
|
+
const p1 = remaining === payload.length ? P1_FIRST : P1_MORE;
|
|
188
|
+
const p2 = remaining - chunkSize === 0 ? P2_LAST : P2_MORE;
|
|
189
|
+
const chunk = payload.slice(
|
|
190
|
+
payload.length - remaining,
|
|
191
|
+
payload.length - remaining + chunkSize,
|
|
192
|
+
);
|
|
193
|
+
response = await this.transport.send(CLA, instruction, p1, p2, chunk).catch(e => {
|
|
194
|
+
throw remapErrors(e);
|
|
195
|
+
});
|
|
196
|
+
remaining -= chunkSize;
|
|
197
|
+
if (remaining === 0) {
|
|
198
|
+
break;
|
|
312
199
|
}
|
|
313
|
-
}
|
|
200
|
+
}
|
|
201
|
+
return response.slice(0, -2);
|
|
314
202
|
}
|
|
315
203
|
}
|
|
204
|
+
|
|
205
|
+
const remapErrors = e => {
|
|
206
|
+
if (e) {
|
|
207
|
+
switch (e.statusCode) {
|
|
208
|
+
case SW_DENY:
|
|
209
|
+
return new StellarUserRefusedError("User refused the request", undefined, { cause: e });
|
|
210
|
+
case SW_DATA_PARSING_FAIL:
|
|
211
|
+
return new StellarDataParsingFailedError("Unable to parse the provided data", undefined, {
|
|
212
|
+
cause: e,
|
|
213
|
+
});
|
|
214
|
+
case SW_HASH_SIGNING_MODE_NOT_ENABLED:
|
|
215
|
+
return new StellarHashSigningNotEnabledError(
|
|
216
|
+
"Hash signing not allowed. Have you enabled it in the app settings?",
|
|
217
|
+
undefined,
|
|
218
|
+
{ cause: e },
|
|
219
|
+
);
|
|
220
|
+
case SW_DATA_TOO_LARGE:
|
|
221
|
+
return new StellarDataTooLargeError(
|
|
222
|
+
"The provided data is too large for the device to process",
|
|
223
|
+
undefined,
|
|
224
|
+
{ cause: e },
|
|
225
|
+
);
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
return e;
|
|
229
|
+
};
|
|
230
|
+
|
|
231
|
+
const pathToBuffer = (originalPath: string) => {
|
|
232
|
+
const path = originalPath
|
|
233
|
+
.split("/")
|
|
234
|
+
.map(value => (value.endsWith("'") || value.endsWith("h") ? value : `${value}'`))
|
|
235
|
+
.join("/");
|
|
236
|
+
const pathNums: number[] = BIPPath.fromString(path).toPathArray();
|
|
237
|
+
return serializePath(pathNums);
|
|
238
|
+
};
|
|
239
|
+
|
|
240
|
+
const serializePath = (path: number[]) => {
|
|
241
|
+
const buf = Buffer.alloc(1 + path.length * 4);
|
|
242
|
+
buf.writeUInt8(path.length, 0);
|
|
243
|
+
for (const [i, num] of path.entries()) {
|
|
244
|
+
buf.writeUInt32BE(num, 1 + i * 4);
|
|
245
|
+
}
|
|
246
|
+
return buf;
|
|
247
|
+
};
|
|
248
|
+
|
|
249
|
+
export * from "./errors";
|
package/src/errors.ts
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { createCustomErrorClass } from "@ledgerhq/errors";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Error thrown when hash signing is not enabled on the device.
|
|
5
|
+
*/
|
|
6
|
+
export const StellarHashSigningNotEnabledError = createCustomErrorClass(
|
|
7
|
+
"StellarHashSigningNotEnabledError",
|
|
8
|
+
);
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Error thrown when data parsing fails.
|
|
12
|
+
*
|
|
13
|
+
* For example, when parsing the transaction fails, this error is thrown.
|
|
14
|
+
*/
|
|
15
|
+
export const StellarDataParsingFailedError = createCustomErrorClass(
|
|
16
|
+
"StellarDataParsingFailedError",
|
|
17
|
+
);
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Error thrown when the user refuses the request on the device.
|
|
21
|
+
*/
|
|
22
|
+
export const StellarUserRefusedError = createCustomErrorClass("StellarUserRefusedError");
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Error thrown when the data is too large to be processed by the device.
|
|
26
|
+
*/
|
|
27
|
+
export const StellarDataTooLargeError = createCustomErrorClass("StellarDataTooLargeError");
|