@ledgerhq/hw-app-xrp 6.29.4 → 6.30.0-next.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/.unimportedrc.json +2 -1
- package/CHANGELOG.md +6 -0
- package/jest.config.ts +17 -0
- package/lib/Xrp.js +66 -80
- package/lib/Xrp.js.map +1 -1
- package/lib-es/Xrp.js +66 -80
- package/lib-es/Xrp.js.map +1 -1
- package/package.json +6 -3
package/.turbo/turbo-build.log
CHANGED
package/.unimportedrc.json
CHANGED
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
# @ledgerhq/hw-app-xrp
|
|
2
2
|
|
|
3
|
+
## 6.30.0-next.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- [#9298](https://github.com/LedgerHQ/ledger-live/pull/9298) [`2785d49`](https://github.com/LedgerHQ/ledger-live/commit/2785d49ac320498f98ed39b4eccc48310ad35fe1) Thanks [@Canestin](https://github.com/Canestin)! - config coin-integration env for sonarqube
|
|
8
|
+
|
|
3
9
|
## 6.29.4
|
|
4
10
|
|
|
5
11
|
### Patch Changes
|
package/jest.config.ts
CHANGED
|
@@ -3,4 +3,21 @@ import baseConfig from "../../jest.config";
|
|
|
3
3
|
export default {
|
|
4
4
|
...baseConfig,
|
|
5
5
|
rootDir: __dirname,
|
|
6
|
+
collectCoverageFrom: [
|
|
7
|
+
"src/**/*.ts",
|
|
8
|
+
"!src/**/*.test.{ts,tsx}",
|
|
9
|
+
"!src/**/*.spec.{ts,tsx}",
|
|
10
|
+
"!src/**/__tests__/**",
|
|
11
|
+
"!tests/**",
|
|
12
|
+
],
|
|
13
|
+
coverageReporters: ["json", ["lcov", { projectRoot: "../" }], "json-summary", "text"],
|
|
14
|
+
reporters: [
|
|
15
|
+
[
|
|
16
|
+
"jest-sonar",
|
|
17
|
+
{
|
|
18
|
+
outputName: "hw-app-xrp-sonar-executionTests-report.xml",
|
|
19
|
+
reportedFilePath: "absolute",
|
|
20
|
+
},
|
|
21
|
+
],
|
|
22
|
+
],
|
|
6
23
|
};
|
package/lib/Xrp.js
CHANGED
|
@@ -1,13 +1,4 @@
|
|
|
1
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
2
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
12
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
13
4
|
};
|
|
@@ -60,6 +51,7 @@ const bip32_path_1 = __importDefault(require("bip32-path"));
|
|
|
60
51
|
* .catch(e => console.log(`An error occurred (${e.message})`));
|
|
61
52
|
*/
|
|
62
53
|
class Xrp {
|
|
54
|
+
transport;
|
|
63
55
|
constructor(transport, scrambleKey = "XRP") {
|
|
64
56
|
this.transport = transport;
|
|
65
57
|
transport.decorateAppAPIMethods(this, ["getAddress", "signTransaction", "getAppConfiguration"], scrambleKey);
|
|
@@ -76,34 +68,32 @@ class Xrp {
|
|
|
76
68
|
* const result = await xrp.getAddress("44'/144'/0'/0/0");
|
|
77
69
|
* const { publicKey, address } = result;
|
|
78
70
|
*/
|
|
79
|
-
getAddress(path, display, chainCode, ed25519) {
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
data.writeUInt32BE(segment, 1 + index * 4);
|
|
91
|
-
});
|
|
92
|
-
const response = yield this.transport.send(cla, ins, p1, p2, data);
|
|
93
|
-
const publicKeyLength = response[0];
|
|
94
|
-
const addressLength = response[1 + publicKeyLength];
|
|
95
|
-
return {
|
|
96
|
-
publicKey: response.slice(1, 1 + publicKeyLength).toString("hex"),
|
|
97
|
-
address: response
|
|
98
|
-
.slice(1 + publicKeyLength + 1, 1 + publicKeyLength + 1 + addressLength)
|
|
99
|
-
.toString("ascii"),
|
|
100
|
-
chainCode: chainCode
|
|
101
|
-
? response
|
|
102
|
-
.slice(1 + publicKeyLength + 1 + addressLength, 1 + publicKeyLength + 1 + addressLength + 32)
|
|
103
|
-
.toString("hex")
|
|
104
|
-
: undefined,
|
|
105
|
-
};
|
|
71
|
+
async getAddress(path, display, chainCode, ed25519) {
|
|
72
|
+
const bipPath = bip32_path_1.default.fromString(path).toPathArray();
|
|
73
|
+
const curveMask = ed25519 ? 0x80 : 0x40;
|
|
74
|
+
const cla = 0xe0;
|
|
75
|
+
const ins = 0x02;
|
|
76
|
+
const p1 = display ? 0x01 : 0x00;
|
|
77
|
+
const p2 = curveMask | (chainCode ? 0x01 : 0x00);
|
|
78
|
+
const data = Buffer.alloc(1 + bipPath.length * 4);
|
|
79
|
+
data.writeInt8(bipPath.length, 0);
|
|
80
|
+
bipPath.forEach((segment, index) => {
|
|
81
|
+
data.writeUInt32BE(segment, 1 + index * 4);
|
|
106
82
|
});
|
|
83
|
+
const response = await this.transport.send(cla, ins, p1, p2, data);
|
|
84
|
+
const publicKeyLength = response[0];
|
|
85
|
+
const addressLength = response[1 + publicKeyLength];
|
|
86
|
+
return {
|
|
87
|
+
publicKey: response.slice(1, 1 + publicKeyLength).toString("hex"),
|
|
88
|
+
address: response
|
|
89
|
+
.slice(1 + publicKeyLength + 1, 1 + publicKeyLength + 1 + addressLength)
|
|
90
|
+
.toString("ascii"),
|
|
91
|
+
chainCode: chainCode
|
|
92
|
+
? response
|
|
93
|
+
.slice(1 + publicKeyLength + 1 + addressLength, 1 + publicKeyLength + 1 + addressLength + 32)
|
|
94
|
+
.toString("hex")
|
|
95
|
+
: undefined,
|
|
96
|
+
};
|
|
107
97
|
}
|
|
108
98
|
/**
|
|
109
99
|
* sign a XRP transaction with a given BIP 32 path
|
|
@@ -120,45 +110,43 @@ class Xrp {
|
|
|
120
110
|
* @example
|
|
121
111
|
* const signature = await xrp.signTransaction("44'/144'/0'/0/0", "12000022800000002400000002614000000001315D3468400000000000000C73210324E5F600B52BB3D9246D49C4AB1722BA7F32B7A3E4F9F2B8A1A28B9118CC36C48114F31B152151B6F42C1D61FE4139D34B424C8647D183142ECFC1831F6E979C6DA907E88B1CAD602DB59E2F");
|
|
122
112
|
*/
|
|
123
|
-
signTransaction(path, rawTxHex, ed25519) {
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
rawTx.copy(apdu.data, 1 + bipPath.length * 4, offset, offset + chunkSize);
|
|
148
|
-
}
|
|
149
|
-
else {
|
|
150
|
-
rawTx.copy(apdu.data, 0, offset, offset + chunkSize);
|
|
151
|
-
}
|
|
152
|
-
apdus.push(apdu);
|
|
153
|
-
offset += chunkSize;
|
|
113
|
+
async signTransaction(path, rawTxHex, ed25519) {
|
|
114
|
+
const bipPath = bip32_path_1.default.fromString(path).toPathArray();
|
|
115
|
+
const rawTx = Buffer.from(rawTxHex, "hex");
|
|
116
|
+
const curveMask = ed25519 ? 0x80 : 0x40;
|
|
117
|
+
const apdus = [];
|
|
118
|
+
let offset = 0;
|
|
119
|
+
while (offset !== rawTx.length) {
|
|
120
|
+
const isFirst = offset === 0;
|
|
121
|
+
const maxChunkSize = isFirst ? 150 - 1 - bipPath.length * 4 : 150;
|
|
122
|
+
const hasMore = offset + maxChunkSize < rawTx.length;
|
|
123
|
+
const chunkSize = hasMore ? maxChunkSize : rawTx.length - offset;
|
|
124
|
+
const apdu = {
|
|
125
|
+
cla: 0xe0,
|
|
126
|
+
ins: 0x04,
|
|
127
|
+
p1: (isFirst ? 0x00 : 0x01) | (hasMore ? 0x80 : 0x00),
|
|
128
|
+
p2: curveMask,
|
|
129
|
+
data: isFirst ? Buffer.alloc(1 + bipPath.length * 4 + chunkSize) : Buffer.alloc(chunkSize),
|
|
130
|
+
};
|
|
131
|
+
if (isFirst) {
|
|
132
|
+
apdu.data.writeInt8(bipPath.length, 0);
|
|
133
|
+
bipPath.forEach((segment, index) => {
|
|
134
|
+
apdu.data.writeUInt32BE(segment, 1 + index * 4);
|
|
135
|
+
});
|
|
136
|
+
rawTx.copy(apdu.data, 1 + bipPath.length * 4, offset, offset + chunkSize);
|
|
154
137
|
}
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
response = yield this.transport.send(apdu.cla, apdu.ins, apdu.p1, apdu.p2, apdu.data);
|
|
138
|
+
else {
|
|
139
|
+
rawTx.copy(apdu.data, 0, offset, offset + chunkSize);
|
|
158
140
|
}
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
}
|
|
141
|
+
apdus.push(apdu);
|
|
142
|
+
offset += chunkSize;
|
|
143
|
+
}
|
|
144
|
+
let response = Buffer.alloc(0);
|
|
145
|
+
for (const apdu of apdus) {
|
|
146
|
+
response = await this.transport.send(apdu.cla, apdu.ins, apdu.p1, apdu.p2, apdu.data);
|
|
147
|
+
}
|
|
148
|
+
// the last 2 bytes are status code from the hardware
|
|
149
|
+
return response.slice(0, response.length - 2).toString("hex");
|
|
162
150
|
}
|
|
163
151
|
/**
|
|
164
152
|
* get the version of the XRP app installed on the hardware device
|
|
@@ -171,13 +159,11 @@ class Xrp {
|
|
|
171
159
|
* "version": "1.0.3"
|
|
172
160
|
* }
|
|
173
161
|
*/
|
|
174
|
-
getAppConfiguration() {
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
};
|
|
180
|
-
});
|
|
162
|
+
async getAppConfiguration() {
|
|
163
|
+
const response = await this.transport.send(0xe0, 0x06, 0x00, 0x00);
|
|
164
|
+
return {
|
|
165
|
+
version: "" + response[1] + "." + response[2] + "." + response[3],
|
|
166
|
+
};
|
|
181
167
|
}
|
|
182
168
|
}
|
|
183
169
|
exports.default = Xrp;
|
package/lib/Xrp.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Xrp.js","sourceRoot":"","sources":["../src/Xrp.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"Xrp.js","sourceRoot":"","sources":["../src/Xrp.ts"],"names":[],"mappings":"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"}
|
package/lib-es/Xrp.js
CHANGED
|
@@ -1,12 +1,3 @@
|
|
|
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
1
|
import BIPPath from "bip32-path";
|
|
11
2
|
/**
|
|
12
3
|
* XRP API
|
|
@@ -55,6 +46,7 @@ import BIPPath from "bip32-path";
|
|
|
55
46
|
* .catch(e => console.log(`An error occurred (${e.message})`));
|
|
56
47
|
*/
|
|
57
48
|
export default class Xrp {
|
|
49
|
+
transport;
|
|
58
50
|
constructor(transport, scrambleKey = "XRP") {
|
|
59
51
|
this.transport = transport;
|
|
60
52
|
transport.decorateAppAPIMethods(this, ["getAddress", "signTransaction", "getAppConfiguration"], scrambleKey);
|
|
@@ -71,34 +63,32 @@ export default class Xrp {
|
|
|
71
63
|
* const result = await xrp.getAddress("44'/144'/0'/0/0");
|
|
72
64
|
* const { publicKey, address } = result;
|
|
73
65
|
*/
|
|
74
|
-
getAddress(path, display, chainCode, ed25519) {
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
data.writeUInt32BE(segment, 1 + index * 4);
|
|
86
|
-
});
|
|
87
|
-
const response = yield this.transport.send(cla, ins, p1, p2, data);
|
|
88
|
-
const publicKeyLength = response[0];
|
|
89
|
-
const addressLength = response[1 + publicKeyLength];
|
|
90
|
-
return {
|
|
91
|
-
publicKey: response.slice(1, 1 + publicKeyLength).toString("hex"),
|
|
92
|
-
address: response
|
|
93
|
-
.slice(1 + publicKeyLength + 1, 1 + publicKeyLength + 1 + addressLength)
|
|
94
|
-
.toString("ascii"),
|
|
95
|
-
chainCode: chainCode
|
|
96
|
-
? response
|
|
97
|
-
.slice(1 + publicKeyLength + 1 + addressLength, 1 + publicKeyLength + 1 + addressLength + 32)
|
|
98
|
-
.toString("hex")
|
|
99
|
-
: undefined,
|
|
100
|
-
};
|
|
66
|
+
async getAddress(path, display, chainCode, ed25519) {
|
|
67
|
+
const bipPath = BIPPath.fromString(path).toPathArray();
|
|
68
|
+
const curveMask = ed25519 ? 0x80 : 0x40;
|
|
69
|
+
const cla = 0xe0;
|
|
70
|
+
const ins = 0x02;
|
|
71
|
+
const p1 = display ? 0x01 : 0x00;
|
|
72
|
+
const p2 = curveMask | (chainCode ? 0x01 : 0x00);
|
|
73
|
+
const data = Buffer.alloc(1 + bipPath.length * 4);
|
|
74
|
+
data.writeInt8(bipPath.length, 0);
|
|
75
|
+
bipPath.forEach((segment, index) => {
|
|
76
|
+
data.writeUInt32BE(segment, 1 + index * 4);
|
|
101
77
|
});
|
|
78
|
+
const response = await this.transport.send(cla, ins, p1, p2, data);
|
|
79
|
+
const publicKeyLength = response[0];
|
|
80
|
+
const addressLength = response[1 + publicKeyLength];
|
|
81
|
+
return {
|
|
82
|
+
publicKey: response.slice(1, 1 + publicKeyLength).toString("hex"),
|
|
83
|
+
address: response
|
|
84
|
+
.slice(1 + publicKeyLength + 1, 1 + publicKeyLength + 1 + addressLength)
|
|
85
|
+
.toString("ascii"),
|
|
86
|
+
chainCode: chainCode
|
|
87
|
+
? response
|
|
88
|
+
.slice(1 + publicKeyLength + 1 + addressLength, 1 + publicKeyLength + 1 + addressLength + 32)
|
|
89
|
+
.toString("hex")
|
|
90
|
+
: undefined,
|
|
91
|
+
};
|
|
102
92
|
}
|
|
103
93
|
/**
|
|
104
94
|
* sign a XRP transaction with a given BIP 32 path
|
|
@@ -115,45 +105,43 @@ export default class Xrp {
|
|
|
115
105
|
* @example
|
|
116
106
|
* const signature = await xrp.signTransaction("44'/144'/0'/0/0", "12000022800000002400000002614000000001315D3468400000000000000C73210324E5F600B52BB3D9246D49C4AB1722BA7F32B7A3E4F9F2B8A1A28B9118CC36C48114F31B152151B6F42C1D61FE4139D34B424C8647D183142ECFC1831F6E979C6DA907E88B1CAD602DB59E2F");
|
|
117
107
|
*/
|
|
118
|
-
signTransaction(path, rawTxHex, ed25519) {
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
rawTx.copy(apdu.data, 1 + bipPath.length * 4, offset, offset + chunkSize);
|
|
143
|
-
}
|
|
144
|
-
else {
|
|
145
|
-
rawTx.copy(apdu.data, 0, offset, offset + chunkSize);
|
|
146
|
-
}
|
|
147
|
-
apdus.push(apdu);
|
|
148
|
-
offset += chunkSize;
|
|
108
|
+
async signTransaction(path, rawTxHex, ed25519) {
|
|
109
|
+
const bipPath = BIPPath.fromString(path).toPathArray();
|
|
110
|
+
const rawTx = Buffer.from(rawTxHex, "hex");
|
|
111
|
+
const curveMask = ed25519 ? 0x80 : 0x40;
|
|
112
|
+
const apdus = [];
|
|
113
|
+
let offset = 0;
|
|
114
|
+
while (offset !== rawTx.length) {
|
|
115
|
+
const isFirst = offset === 0;
|
|
116
|
+
const maxChunkSize = isFirst ? 150 - 1 - bipPath.length * 4 : 150;
|
|
117
|
+
const hasMore = offset + maxChunkSize < rawTx.length;
|
|
118
|
+
const chunkSize = hasMore ? maxChunkSize : rawTx.length - offset;
|
|
119
|
+
const apdu = {
|
|
120
|
+
cla: 0xe0,
|
|
121
|
+
ins: 0x04,
|
|
122
|
+
p1: (isFirst ? 0x00 : 0x01) | (hasMore ? 0x80 : 0x00),
|
|
123
|
+
p2: curveMask,
|
|
124
|
+
data: isFirst ? Buffer.alloc(1 + bipPath.length * 4 + chunkSize) : Buffer.alloc(chunkSize),
|
|
125
|
+
};
|
|
126
|
+
if (isFirst) {
|
|
127
|
+
apdu.data.writeInt8(bipPath.length, 0);
|
|
128
|
+
bipPath.forEach((segment, index) => {
|
|
129
|
+
apdu.data.writeUInt32BE(segment, 1 + index * 4);
|
|
130
|
+
});
|
|
131
|
+
rawTx.copy(apdu.data, 1 + bipPath.length * 4, offset, offset + chunkSize);
|
|
149
132
|
}
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
response = yield this.transport.send(apdu.cla, apdu.ins, apdu.p1, apdu.p2, apdu.data);
|
|
133
|
+
else {
|
|
134
|
+
rawTx.copy(apdu.data, 0, offset, offset + chunkSize);
|
|
153
135
|
}
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
}
|
|
136
|
+
apdus.push(apdu);
|
|
137
|
+
offset += chunkSize;
|
|
138
|
+
}
|
|
139
|
+
let response = Buffer.alloc(0);
|
|
140
|
+
for (const apdu of apdus) {
|
|
141
|
+
response = await this.transport.send(apdu.cla, apdu.ins, apdu.p1, apdu.p2, apdu.data);
|
|
142
|
+
}
|
|
143
|
+
// the last 2 bytes are status code from the hardware
|
|
144
|
+
return response.slice(0, response.length - 2).toString("hex");
|
|
157
145
|
}
|
|
158
146
|
/**
|
|
159
147
|
* get the version of the XRP app installed on the hardware device
|
|
@@ -166,13 +154,11 @@ export default class Xrp {
|
|
|
166
154
|
* "version": "1.0.3"
|
|
167
155
|
* }
|
|
168
156
|
*/
|
|
169
|
-
getAppConfiguration() {
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
};
|
|
175
|
-
});
|
|
157
|
+
async getAppConfiguration() {
|
|
158
|
+
const response = await this.transport.send(0xe0, 0x06, 0x00, 0x00);
|
|
159
|
+
return {
|
|
160
|
+
version: "" + response[1] + "." + response[2] + "." + response[3],
|
|
161
|
+
};
|
|
176
162
|
}
|
|
177
163
|
}
|
|
178
164
|
//# sourceMappingURL=Xrp.js.map
|
package/lib-es/Xrp.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Xrp.js","sourceRoot":"","sources":["../src/Xrp.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"Xrp.js","sourceRoot":"","sources":["../src/Xrp.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ledgerhq/hw-app-xrp",
|
|
3
|
-
"version": "6.
|
|
3
|
+
"version": "6.30.0-next.0",
|
|
4
4
|
"description": "Ledger Hardware Wallet Ripple Application API",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"Ledger",
|
|
@@ -32,21 +32,24 @@
|
|
|
32
32
|
},
|
|
33
33
|
"devDependencies": {
|
|
34
34
|
"@types/jest": "^29.5.10",
|
|
35
|
-
"@types/node": "^
|
|
35
|
+
"@types/node": "^22.10.10",
|
|
36
36
|
"documentation": "14.0.2",
|
|
37
37
|
"jest": "^29.7.0",
|
|
38
38
|
"rimraf": "^4.4.1",
|
|
39
39
|
"source-map-support": "^0.5.21",
|
|
40
40
|
"ts-jest": "^29.1.1",
|
|
41
41
|
"ts-node": "^10.4.0",
|
|
42
|
+
"jest-sonar": "0.2.16",
|
|
42
43
|
"@ledgerhq/hw-transport-mocker": "^6.29.4"
|
|
43
44
|
},
|
|
44
45
|
"gitHead": "dd0dea64b58e5a9125c8a422dcffd29e5ef6abec",
|
|
45
46
|
"scripts": {
|
|
46
47
|
"clean": "rimraf lib lib-es",
|
|
47
|
-
"build": "tsc && tsc -m
|
|
48
|
+
"build": "tsc && tsc -m esnext --moduleResolution bundler --outDir lib-es",
|
|
49
|
+
"coverage": "jest --coverage --passWithNoTests && mv coverage/coverage-final.json coverage/coverage-hw-app-xrp.json && mv coverage/lcov.info coverage/hw-app-xrp-lcov.info",
|
|
48
50
|
"prewatch": "pnpm build",
|
|
49
51
|
"watch": "tsc --watch",
|
|
52
|
+
"watch:es": "tsc --watch -m esnext --moduleResolution bundler --outDir lib-es",
|
|
50
53
|
"doc": "documentation readme src/** --section=API --pe ts --re ts --re d.ts",
|
|
51
54
|
"lint": "eslint ./src --no-error-on-unmatched-pattern --ext .ts,.tsx --cache",
|
|
52
55
|
"lint:fix": "pnpm lint --fix",
|