@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.
- package/dist/TonTransport.d.ts +18 -0
- package/dist/TonTransport.js +181 -0
- package/package.json +1 -1
- package/CHANGELOG.md +0 -88
package/dist/TonTransport.d.ts
CHANGED
|
@@ -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;
|
package/dist/TonTransport.js
CHANGED
|
@@ -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
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
|