@ton-community/ton-ledger 4.0.1 → 4.1.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/CHANGELOG.md +6 -0
- package/dist/TonTransport.d.ts +17 -0
- package/dist/TonTransport.js +97 -3
- package/dist/index.d.ts +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,12 @@ All notable changes to this project will be documented in this file.
|
|
|
4
4
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
5
5
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
6
6
|
|
|
7
|
+
## [4.1.0] - 2023-06-16
|
|
8
|
+
|
|
9
|
+
### Added
|
|
10
|
+
|
|
11
|
+
- Added `signData` method along with `SignDataRequest` type
|
|
12
|
+
|
|
7
13
|
## [4.0.1] - 2023-06-16
|
|
8
14
|
|
|
9
15
|
### Fixed
|
package/dist/TonTransport.d.ts
CHANGED
|
@@ -27,6 +27,16 @@ export type TonPayloadFormat = {
|
|
|
27
27
|
forwardAmount: bigint;
|
|
28
28
|
forwardPayload: Cell | null;
|
|
29
29
|
};
|
|
30
|
+
export type SignDataRequest = {
|
|
31
|
+
type: 'plaintext';
|
|
32
|
+
text: string;
|
|
33
|
+
} | {
|
|
34
|
+
type: 'app-data';
|
|
35
|
+
address?: Address;
|
|
36
|
+
domain?: string;
|
|
37
|
+
data: Cell;
|
|
38
|
+
ext?: Cell;
|
|
39
|
+
};
|
|
30
40
|
export declare class TonTransport {
|
|
31
41
|
#private;
|
|
32
42
|
readonly transport: Transport;
|
|
@@ -61,6 +71,13 @@ export declare class TonTransport {
|
|
|
61
71
|
signature: Buffer;
|
|
62
72
|
hash: Buffer;
|
|
63
73
|
}>;
|
|
74
|
+
signData(path: number[], req: SignDataRequest, opts?: {
|
|
75
|
+
timestamp?: number;
|
|
76
|
+
}): Promise<{
|
|
77
|
+
signature: Buffer;
|
|
78
|
+
cell: Cell;
|
|
79
|
+
timestamp: number;
|
|
80
|
+
}>;
|
|
64
81
|
signTransaction: (path: number[], transaction: {
|
|
65
82
|
to: Address;
|
|
66
83
|
sendMode: SendMode;
|
package/dist/TonTransport.js
CHANGED
|
@@ -10,7 +10,9 @@ const LEDGER_SYSTEM = 0xB0;
|
|
|
10
10
|
const LEDGER_CLA = 0xe0;
|
|
11
11
|
const INS_VERSION = 0x03;
|
|
12
12
|
const INS_ADDRESS = 0x05;
|
|
13
|
+
const INS_SIGN_TX = 0x06;
|
|
13
14
|
const INS_PROOF = 0x08;
|
|
15
|
+
const INS_SIGN_DATA = 0x09;
|
|
14
16
|
function chunks(buf, n) {
|
|
15
17
|
const nc = Math.ceil(buf.length / n);
|
|
16
18
|
const cs = [];
|
|
@@ -119,6 +121,98 @@ class TonTransport {
|
|
|
119
121
|
}
|
|
120
122
|
return { signature, hash };
|
|
121
123
|
}
|
|
124
|
+
async signData(path, req, opts) {
|
|
125
|
+
validatePath(path);
|
|
126
|
+
const publicKey = (await this.getAddress(path)).publicKey;
|
|
127
|
+
const timestamp = opts?.timestamp ?? Math.floor(Date.now() / 1000);
|
|
128
|
+
let schema;
|
|
129
|
+
let data;
|
|
130
|
+
let cell;
|
|
131
|
+
switch (req.type) {
|
|
132
|
+
case 'plaintext': {
|
|
133
|
+
schema = 0x754bf91b;
|
|
134
|
+
data = Buffer.from(req.text, 'ascii');
|
|
135
|
+
cell = (0, ton_core_1.beginCell)().storeStringTail(req.text).endCell();
|
|
136
|
+
break;
|
|
137
|
+
}
|
|
138
|
+
case 'app-data': {
|
|
139
|
+
if (req.address === undefined && req.domain === undefined) {
|
|
140
|
+
throw new Error('At least one of `address` and `domain` must be set when using \'app-data\' request');
|
|
141
|
+
}
|
|
142
|
+
schema = 0x54b58535;
|
|
143
|
+
let b = (0, ton_core_1.beginCell)();
|
|
144
|
+
let dp = [];
|
|
145
|
+
if (req.address !== undefined) {
|
|
146
|
+
b.storeBit(1);
|
|
147
|
+
b.storeAddress(req.address);
|
|
148
|
+
dp.push((0, ledgerWriter_1.writeUint8)(1), (0, ledgerWriter_1.writeAddress)(req.address));
|
|
149
|
+
}
|
|
150
|
+
else {
|
|
151
|
+
b.storeBit(0);
|
|
152
|
+
dp.push((0, ledgerWriter_1.writeUint8)(0));
|
|
153
|
+
}
|
|
154
|
+
if (req.domain !== undefined) {
|
|
155
|
+
b.storeBit(1);
|
|
156
|
+
let inner = (0, ton_core_1.beginCell)();
|
|
157
|
+
req.domain.split('.').reverse().forEach(p => {
|
|
158
|
+
inner.storeBuffer(Buffer.from(p, 'ascii'));
|
|
159
|
+
inner.storeUint(0, 8);
|
|
160
|
+
});
|
|
161
|
+
b.storeRef(inner);
|
|
162
|
+
const db = Buffer.from(req.domain, 'ascii');
|
|
163
|
+
dp.push((0, ledgerWriter_1.writeUint8)(1), (0, ledgerWriter_1.writeUint8)(db.length), db);
|
|
164
|
+
}
|
|
165
|
+
else {
|
|
166
|
+
b.storeBit(0);
|
|
167
|
+
dp.push((0, ledgerWriter_1.writeUint8)(0));
|
|
168
|
+
}
|
|
169
|
+
b.storeRef(req.data);
|
|
170
|
+
dp.push((0, ledgerWriter_1.writeCellRef)(req.data));
|
|
171
|
+
if (req.ext !== undefined) {
|
|
172
|
+
b.storeBit(1);
|
|
173
|
+
b.storeRef(req.ext);
|
|
174
|
+
dp.push((0, ledgerWriter_1.writeUint8)(1), (0, ledgerWriter_1.writeCellRef)(req.ext));
|
|
175
|
+
}
|
|
176
|
+
else {
|
|
177
|
+
b.storeBit(0);
|
|
178
|
+
dp.push((0, ledgerWriter_1.writeUint8)(0));
|
|
179
|
+
}
|
|
180
|
+
data = Buffer.concat(dp);
|
|
181
|
+
cell = b.endCell();
|
|
182
|
+
break;
|
|
183
|
+
}
|
|
184
|
+
default: {
|
|
185
|
+
throw new Error(`Sign data request type '${req.type}' not supported`);
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
const commonPart = Buffer.concat([
|
|
189
|
+
(0, ledgerWriter_1.writeUint32)(schema),
|
|
190
|
+
(0, ledgerWriter_1.writeUint64)(BigInt(timestamp)),
|
|
191
|
+
]);
|
|
192
|
+
const pkg = Buffer.concat([
|
|
193
|
+
commonPart,
|
|
194
|
+
data,
|
|
195
|
+
]);
|
|
196
|
+
await this.#doRequest(INS_SIGN_DATA, 0x00, 0x03, pathElementsToBuffer(path.map((v) => v + 0x80000000)));
|
|
197
|
+
const pkgCs = chunks(pkg, 255);
|
|
198
|
+
for (let i = 0; i < pkgCs.length - 1; i++) {
|
|
199
|
+
await this.#doRequest(INS_SIGN_DATA, 0x00, 0x02, pkgCs[i]);
|
|
200
|
+
}
|
|
201
|
+
const res = await this.#doRequest(INS_SIGN_DATA, 0x00, 0x00, pkgCs[pkgCs.length - 1]);
|
|
202
|
+
let signature = res.subarray(1, 1 + 64);
|
|
203
|
+
let hash = res.subarray(2 + 64, 2 + 64 + 32);
|
|
204
|
+
if (!hash.equals(cell.hash())) {
|
|
205
|
+
throw Error('Hash mismatch. Expected: ' + cell.hash().toString('hex') + ', got: ' + hash.toString('hex'));
|
|
206
|
+
}
|
|
207
|
+
if (!(0, ton_crypto_1.signVerify)(Buffer.concat([commonPart, hash]), signature, publicKey)) {
|
|
208
|
+
throw Error('Received signature is invalid');
|
|
209
|
+
}
|
|
210
|
+
return {
|
|
211
|
+
signature,
|
|
212
|
+
cell,
|
|
213
|
+
timestamp,
|
|
214
|
+
};
|
|
215
|
+
}
|
|
122
216
|
signTransaction = async (path, transaction) => {
|
|
123
217
|
// Check path
|
|
124
218
|
validatePath(path);
|
|
@@ -257,12 +351,12 @@ class TonTransport {
|
|
|
257
351
|
//
|
|
258
352
|
// Send package
|
|
259
353
|
//
|
|
260
|
-
await this.#doRequest(
|
|
354
|
+
await this.#doRequest(INS_SIGN_TX, 0x00, 0x03, pathElementsToBuffer(path.map((v) => v + 0x80000000)));
|
|
261
355
|
const pkgCs = chunks(pkg, 255);
|
|
262
356
|
for (let i = 0; i < pkgCs.length - 1; i++) {
|
|
263
|
-
await this.#doRequest(
|
|
357
|
+
await this.#doRequest(INS_SIGN_TX, 0x00, 0x02, pkgCs[i]);
|
|
264
358
|
}
|
|
265
|
-
let res = await this.#doRequest(
|
|
359
|
+
let res = await this.#doRequest(INS_SIGN_TX, 0x00, 0x00, pkgCs[pkgCs.length - 1]);
|
|
266
360
|
//
|
|
267
361
|
// Parse response
|
|
268
362
|
//
|
package/dist/index.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export { TonPayloadFormat, TonTransport } from './TonTransport';
|
|
1
|
+
export { TonPayloadFormat, TonTransport, SignDataRequest } from './TonTransport';
|