@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 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
@@ -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;
@@ -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(0x06, 0x00, 0x03, pathElementsToBuffer(path.map((v) => v + 0x80000000)));
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(0x06, 0x00, 0x02, pkgCs[i]);
357
+ await this.#doRequest(INS_SIGN_TX, 0x00, 0x02, pkgCs[i]);
264
358
  }
265
- let res = await this.#doRequest(0x06, 0x00, 0x00, pkgCs[pkgCs.length - 1]);
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';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ton-community/ton-ledger",
3
- "version": "4.0.1",
3
+ "version": "4.1.0",
4
4
  "repository": "https://github.com/ton-community/ton-ledger-ts",
5
5
  "author": "Steve Korshakov <steve@korshakov.com>",
6
6
  "license": "MIT",