@ton-community/ton-ledger 7.4.0-pre.1 → 7.4.0-pre.2

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.
@@ -136,6 +136,14 @@ export type SignDataNewRequestPartial = {
136
136
  data: Cell;
137
137
  };
138
138
  export type SignDataNewRequest = SignDataNewRequestCommon & SignDataNewRequestPartial;
139
+ export type LedgerMessage = {
140
+ to: Address;
141
+ sendMode: SendMode;
142
+ bounce: boolean;
143
+ amount: bigint;
144
+ stateInit?: StateInit;
145
+ payload?: TonPayloadFormat;
146
+ };
139
147
  export declare class TonTransport {
140
148
  #private;
141
149
  readonly transport: Transport;
@@ -196,6 +204,15 @@ export declare class TonTransport {
196
204
  signedDataHash: Buffer;
197
205
  timestamp: number;
198
206
  }>;
207
+ signMultiTransaction: (path: number[], transaction: {
208
+ seqno: number;
209
+ timeout: number;
210
+ walletSpecifiers?: {
211
+ subwalletId?: number;
212
+ includeWalletOp: boolean;
213
+ expectedPublicKey?: Buffer;
214
+ };
215
+ }, messages: LedgerMessage[]) => Promise<Cell>;
199
216
  signTransaction: (path: number[], transaction: {
200
217
  to: Address;
201
218
  sendMode: SendMode;
@@ -208,6 +225,7 @@ export declare class TonTransport {
208
225
  walletSpecifiers?: {
209
226
  subwalletId?: number;
210
227
  includeWalletOp: boolean;
228
+ expectedPublicKey?: Buffer;
211
229
  };
212
230
  extraCurrency?: {
213
231
  index: number;
@@ -1174,6 +1174,180 @@ class TonTransport {
1174
1174
  timestamp,
1175
1175
  };
1176
1176
  }
1177
+ signMultiTransaction = async (path, transaction, messages) => {
1178
+ // Check path
1179
+ validatePath(path);
1180
+ //
1181
+ // Fetch key
1182
+ //
1183
+ let publicKey = (await this.getAddress(path)).publicKey;
1184
+ if (transaction.walletSpecifiers?.expectedPublicKey !== undefined && !transaction.walletSpecifiers.expectedPublicKey.equals(publicKey)) {
1185
+ throw Error('Expected public key mismatch');
1186
+ }
1187
+ //
1188
+ // Create package
1189
+ //
1190
+ const includeWalletOp = transaction.walletSpecifiers?.includeWalletOp ?? true;
1191
+ const subwalletId = transaction.walletSpecifiers?.subwalletId ?? DEFAULT_SUBWALLET_ID;
1192
+ const useTag1 = transaction.walletSpecifiers !== undefined;
1193
+ let pkg = Buffer.concat([
1194
+ (0, ledgerWriter_1.writeUint8)(messages.length),
1195
+ (0, ledgerWriter_1.writeUint8)(useTag1 ? 1 : 0), // tag
1196
+ ]);
1197
+ if (useTag1) {
1198
+ let flags = 0;
1199
+ if (includeWalletOp) {
1200
+ flags |= 1;
1201
+ }
1202
+ if (transaction.walletSpecifiers?.expectedPublicKey !== undefined) {
1203
+ flags |= 4;
1204
+ }
1205
+ pkg = Buffer.concat([
1206
+ pkg,
1207
+ (0, ledgerWriter_1.writeUint32)(subwalletId),
1208
+ (0, ledgerWriter_1.writeUint8)(flags),
1209
+ transaction.walletSpecifiers?.expectedPublicKey ?? Buffer.alloc(0),
1210
+ ]);
1211
+ }
1212
+ pkg = Buffer.concat([
1213
+ pkg,
1214
+ (0, ledgerWriter_1.writeUint32)(transaction.seqno),
1215
+ (0, ledgerWriter_1.writeUint32)(transaction.timeout),
1216
+ ]);
1217
+ let messagePkgs = [];
1218
+ let messageCells = [];
1219
+ for (const message of messages) {
1220
+ let pkg = Buffer.concat([
1221
+ (0, ledgerWriter_1.writeVarUInt)(message.amount),
1222
+ (0, ledgerWriter_1.writeAddress)(message.to),
1223
+ (0, ledgerWriter_1.writeUint8)(message.bounce ? 1 : 0),
1224
+ (0, ledgerWriter_1.writeUint8)(message.sendMode),
1225
+ ]);
1226
+ let stateInit = null;
1227
+ if (message.stateInit) {
1228
+ stateInit = (0, core_1.beginCell)()
1229
+ .store((0, core_1.storeStateInit)(message.stateInit))
1230
+ .endCell();
1231
+ pkg = Buffer.concat([
1232
+ pkg,
1233
+ (0, ledgerWriter_1.writeUint8)(1),
1234
+ (0, ledgerWriter_1.writeUint16)(stateInit.depth()),
1235
+ stateInit.hash()
1236
+ ]);
1237
+ }
1238
+ else {
1239
+ pkg = Buffer.concat([
1240
+ pkg,
1241
+ (0, ledgerWriter_1.writeUint8)(0)
1242
+ ]);
1243
+ }
1244
+ const { payload, hints } = convertPayload(message.payload);
1245
+ if (payload) {
1246
+ pkg = Buffer.concat([
1247
+ pkg,
1248
+ (0, ledgerWriter_1.writeUint8)(1),
1249
+ (0, ledgerWriter_1.writeUint16)(payload.depth()),
1250
+ payload.hash(),
1251
+ hints
1252
+ ]);
1253
+ }
1254
+ else {
1255
+ pkg = Buffer.concat([
1256
+ pkg,
1257
+ (0, ledgerWriter_1.writeUint8)(0),
1258
+ (0, ledgerWriter_1.writeUint8)(0)
1259
+ ]);
1260
+ }
1261
+ let orderBuilder = (0, core_1.beginCell)()
1262
+ .storeBit(0)
1263
+ .storeBit(true)
1264
+ .storeBit(message.bounce)
1265
+ .storeBit(false)
1266
+ .storeAddress(null)
1267
+ .storeAddress(message.to)
1268
+ .storeCoins(message.amount)
1269
+ .storeBit(false)
1270
+ .storeCoins(0)
1271
+ .storeCoins(0)
1272
+ .storeUint(0, 64)
1273
+ .storeUint(0, 32);
1274
+ if (stateInit) {
1275
+ orderBuilder = orderBuilder
1276
+ .storeBit(true)
1277
+ .storeBit(true) // Always in reference
1278
+ .storeRef(stateInit);
1279
+ }
1280
+ else {
1281
+ orderBuilder = orderBuilder
1282
+ .storeBit(false);
1283
+ }
1284
+ if (payload) {
1285
+ orderBuilder = orderBuilder
1286
+ .storeBit(true) // Always in reference
1287
+ .storeRef(payload);
1288
+ }
1289
+ else {
1290
+ orderBuilder = orderBuilder
1291
+ .storeBit(false);
1292
+ }
1293
+ messagePkgs.push(pkg);
1294
+ messageCells.push(orderBuilder.endCell());
1295
+ }
1296
+ await this.#doRequest(INS_SIGN_TX, 0x04, 0x03, pathElementsToBuffer(path.map((v) => v + 0x80000000)));
1297
+ const pkgCs = chunks(pkg, 255);
1298
+ for (let i = 0; i < pkgCs.length; i++) {
1299
+ await this.#doRequest(INS_SIGN_TX, 0x04, 0x02, pkgCs[i]);
1300
+ }
1301
+ let res = null;
1302
+ for (let i = 0; i < messagePkgs.length; i++) {
1303
+ const pkgCs = chunks(messagePkgs[i], 255);
1304
+ for (let j = 0; j < pkgCs.length; j++) {
1305
+ let flags = 4;
1306
+ if (j === 0) {
1307
+ flags |= 1;
1308
+ }
1309
+ if (j < pkgCs.length - 1) {
1310
+ flags |= 2;
1311
+ }
1312
+ if (i === messagePkgs.length - 1 && j === pkgCs.length - 1) {
1313
+ res = await this.#doRequest(INS_SIGN_TX, flags, 0, pkgCs[j]);
1314
+ }
1315
+ else {
1316
+ await this.#doRequest(INS_SIGN_TX, flags, 2, pkgCs[j]);
1317
+ }
1318
+ }
1319
+ }
1320
+ if (res === null) {
1321
+ throw Error('No response received');
1322
+ }
1323
+ // Transfer message
1324
+ let transferB = (0, core_1.beginCell)()
1325
+ .storeUint(subwalletId, 32)
1326
+ .storeUint(transaction.timeout, 32)
1327
+ .storeUint(transaction.seqno, 32);
1328
+ if (includeWalletOp) {
1329
+ transferB = transferB.storeUint(0, 8);
1330
+ }
1331
+ for (let i = 0; i < messages.length; i++) {
1332
+ transferB = transferB.storeUint(messages[i].sendMode, 8)
1333
+ .storeRef(messageCells[i]);
1334
+ }
1335
+ let transfer = transferB.endCell();
1336
+ // Parse result
1337
+ let signature = res.slice(1, 1 + 64);
1338
+ let hash = res.slice(2 + 64, 2 + 64 + 32);
1339
+ if (!hash.equals(transfer.hash())) {
1340
+ throw Error('Hash mismatch. Expected: ' + transfer.hash().toString('hex') + ', got: ' + hash.toString('hex'));
1341
+ }
1342
+ if (!(0, crypto_1.signVerify)(hash, signature, publicKey)) {
1343
+ throw Error('Received signature is invalid');
1344
+ }
1345
+ // Build a message
1346
+ return (0, core_1.beginCell)()
1347
+ .storeBuffer(signature)
1348
+ .storeSlice(transfer.beginParse())
1349
+ .endCell();
1350
+ };
1177
1351
  signTransaction = async (path, transaction) => {
1178
1352
  // Check path
1179
1353
  validatePath(path);
@@ -1184,6 +1358,9 @@ class TonTransport {
1184
1358
  // Fetch key
1185
1359
  //
1186
1360
  let publicKey = (await this.getAddress(path)).publicKey;
1361
+ if (transaction.walletSpecifiers?.expectedPublicKey !== undefined && !transaction.walletSpecifiers.expectedPublicKey.equals(publicKey)) {
1362
+ throw Error('Expected public key mismatch');
1363
+ }
1187
1364
  //
1188
1365
  // Create package
1189
1366
  //
@@ -1201,10 +1378,14 @@ class TonTransport {
1201
1378
  if (transaction.extraCurrency !== undefined) {
1202
1379
  flags |= 2;
1203
1380
  }
1381
+ if (transaction.walletSpecifiers?.expectedPublicKey !== undefined) {
1382
+ flags |= 4;
1383
+ }
1204
1384
  pkg = Buffer.concat([
1205
1385
  pkg,
1206
1386
  (0, ledgerWriter_1.writeUint32)(subwalletId),
1207
1387
  (0, ledgerWriter_1.writeUint8)(flags),
1388
+ transaction.walletSpecifiers?.expectedPublicKey ?? Buffer.alloc(0),
1208
1389
  ]);
1209
1390
  }
1210
1391
  let ecBuf = Buffer.alloc(0);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ton-community/ton-ledger",
3
- "version": "7.4.0-pre.1",
3
+ "version": "7.4.0-pre.2",
4
4
  "repository": "https://github.com/ton-community/ton-ledger-ts",
5
5
  "author": "Steve Korshakov <steve@korshakov.com>",
6
6
  "license": "MIT",
package/CHANGELOG.md DELETED
@@ -1,88 +0,0 @@
1
- # Changelog
2
- All notable changes to this project will be documented in this file.
3
-
4
- The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
5
- and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
6
-
7
- ## [7.3.0] - 2025-08-21
8
-
9
- - New jettons
10
- - Fixed `includeWalletOp`
11
-
12
- ## [7.2.0] - 2025-02-07
13
-
14
- - Added support for TON Ledger App 2.2.0 features, including:
15
- - Hardcoded jettons
16
- - Wallet specifiers support in more methods
17
-
18
- ## [7.1.0] - Not released
19
-
20
- ### Added
21
-
22
- - Added `parseMessage` helper to parse messages into TON Ledger App format
23
- - Added support for TON Ledger App 2.1.0 features, including:
24
- - New message types
25
- - Wallet specifiers (subwallet ID and wallet op inclusion for v4 support)
26
- - `getSettings` method
27
-
28
- ## [7.0.1] - 2024-01-17
29
-
30
- ### Fixed
31
-
32
- - Fixed incorrect VarUInt encoding of 0 (0 nanoTON, 0 jetton units, etc)
33
-
34
- ## [7.0.0] - 2023-09-15
35
-
36
- ### Changed
37
-
38
- - Switched `ton-core` and `ton-crypto` to `@ton/core` and `@ton/crypto`
39
-
40
- ## [6.0.0] - 2023-07-11
41
-
42
- ### Removed
43
-
44
- - Removed `unsafe` payload format
45
-
46
- ## [5.0.0] - 2023-06-29
47
-
48
- ### Removed
49
-
50
- - Removed `decimals` and `ticker` from `jetton-transfer` request
51
-
52
- ## [4.1.0] - 2023-06-16
53
-
54
- ### Added
55
-
56
- - Added `signData` method along with `SignDataRequest` type
57
-
58
- ## [4.0.1] - 2023-06-16
59
-
60
- ### Fixed
61
-
62
- - Fixed the address flags communication
63
-
64
- ## [4.0.0] - 2023-06-09
65
-
66
- ### Added
67
-
68
- - Added payload types for NFT and Jetton transfers
69
- - Added TON Connect 2.0 address proof request
70
-
71
- ### Removed
72
-
73
- - Removed old payload types except for comment and unsafe
74
-
75
- ### Changed
76
-
77
- - Updated dependencies
78
- - Changed APDU format to be the same as the latest embedded app version (breaking change)
79
-
80
- ## [3.0.0] - 2023-01-08
81
-
82
- ### Changed
83
-
84
- - Migration to `ton-core`
85
-
86
- ## [2.3.2]
87
-
88
- - Update documentation