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

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.
@@ -1,4 +1,5 @@
1
1
  /// <reference types="node" />
2
+ /// <reference types="node" />
2
3
  import Transport from "@ledgerhq/hw-transport";
3
4
  import { Address, Cell, SendMode, StateInit } from "@ton/core";
4
5
  export type KnownJetton = {
@@ -120,6 +121,21 @@ export type SignDataRequest = {
120
121
  data: Cell;
121
122
  ext?: Cell;
122
123
  };
124
+ export type SignDataNewRequestCommon = {
125
+ domain: string;
126
+ };
127
+ export type SignDataNewRequestPartial = {
128
+ type: 'plaintext';
129
+ text: string;
130
+ } | {
131
+ type: 'binary';
132
+ data: Buffer;
133
+ } | {
134
+ type: 'app-data';
135
+ schemaCrc: number;
136
+ data: Cell;
137
+ };
138
+ export type SignDataNewRequest = SignDataNewRequestCommon & SignDataNewRequestPartial;
123
139
  export declare class TonTransport {
124
140
  #private;
125
141
  readonly transport: Transport;
@@ -167,6 +183,19 @@ export declare class TonTransport {
167
183
  cell: Cell;
168
184
  timestamp: number;
169
185
  }>;
186
+ signDataNew(path: number[], req: SignDataNewRequest, opts?: {
187
+ timestamp?: number;
188
+ testOnly?: boolean;
189
+ chain?: number;
190
+ subwalletId?: number;
191
+ walletVersion?: 'v3r2' | 'v4';
192
+ }): Promise<{
193
+ signature: Buffer;
194
+ address: Address;
195
+ signedData: Buffer | Cell;
196
+ signedDataHash: Buffer;
197
+ timestamp: number;
198
+ }>;
170
199
  signTransaction: (path: number[], transaction: {
171
200
  to: Address;
172
201
  sendMode: SendMode;
@@ -189,4 +218,5 @@ export declare class TonTransport {
189
218
  blindSigningEnabled: boolean;
190
219
  expertMode: boolean;
191
220
  }>;
221
+ launchApp(): Promise<void>;
192
222
  }
@@ -56,6 +56,10 @@ exports.KNOWN_JETTONS = [
56
56
  symbol: 'X',
57
57
  masterAddress: core_1.Address.parse('EQB4zZusHsbU2vVTPqjhlokIOoiZhEdCMT703CWEzhTOo__X'),
58
58
  },
59
+ {
60
+ symbol: 'tgBTC',
61
+ masterAddress: core_1.Address.parse('EQBmjxpYsJ8yHEraYfTpLdejCekHMoKS2fOErP4lLHCf4SlU'),
62
+ },
59
63
  ];
60
64
  exports.KNOWN_EXTRA_CURRENCIES = [
61
65
  {
@@ -1064,6 +1068,112 @@ class TonTransport {
1064
1068
  timestamp,
1065
1069
  };
1066
1070
  }
1071
+ async signDataNew(path, req, opts) {
1072
+ validatePath(path);
1073
+ const { publicKey, address: addressString } = (await this.getAddress(path, opts));
1074
+ const expectedAddress = core_1.Address.parse(addressString);
1075
+ const { flags, specifiers, chain } = processAddressFlags(opts);
1076
+ let specifiersBuf = Buffer.alloc(0);
1077
+ if (specifiers !== undefined) {
1078
+ specifiersBuf = Buffer.concat([(0, ledgerWriter_1.writeUint8)(specifiers.isV3R2 ? 1 : 0), (0, ledgerWriter_1.writeUint32)(specifiers.subwalletId)]);
1079
+ }
1080
+ const timestamp = opts?.timestamp ?? Math.floor(Date.now() / 1000);
1081
+ const domainBuf = Buffer.from(req.domain, 'ascii');
1082
+ let typeId;
1083
+ let payload;
1084
+ let signedData;
1085
+ switch (req.type) {
1086
+ case 'plaintext': {
1087
+ typeId = 0;
1088
+ payload = Buffer.from(req.text, 'ascii');
1089
+ signedData = Buffer.concat([
1090
+ Buffer.from([0xff, 0xff]),
1091
+ Buffer.from('ton-connect/sign-data/'),
1092
+ (0, ledgerWriter_1.writeInt32BE)(chain),
1093
+ expectedAddress.hash,
1094
+ (0, ledgerWriter_1.writeUint32)(domainBuf.length),
1095
+ domainBuf,
1096
+ (0, ledgerWriter_1.writeUint64)(BigInt(timestamp)),
1097
+ Buffer.from('txt', 'ascii'),
1098
+ (0, ledgerWriter_1.writeUint32)(payload.length),
1099
+ payload,
1100
+ ]);
1101
+ break;
1102
+ }
1103
+ case 'binary': {
1104
+ typeId = 1;
1105
+ payload = req.data;
1106
+ signedData = Buffer.concat([
1107
+ Buffer.from([0xff, 0xff]),
1108
+ Buffer.from('ton-connect/sign-data/'),
1109
+ (0, ledgerWriter_1.writeInt32BE)(chain),
1110
+ expectedAddress.hash,
1111
+ (0, ledgerWriter_1.writeUint32)(domainBuf.length),
1112
+ domainBuf,
1113
+ (0, ledgerWriter_1.writeUint64)(BigInt(timestamp)),
1114
+ Buffer.from('bin', 'ascii'),
1115
+ (0, ledgerWriter_1.writeUint32)(payload.length),
1116
+ payload,
1117
+ ]);
1118
+ break;
1119
+ }
1120
+ case 'app-data': {
1121
+ typeId = 2;
1122
+ payload = Buffer.concat([
1123
+ (0, ledgerWriter_1.writeUint32)(req.schemaCrc),
1124
+ (0, ledgerWriter_1.writeCellRef)(req.data),
1125
+ ]);
1126
+ let inner = (0, core_1.beginCell)();
1127
+ req.domain.split('.').reverse().forEach(p => {
1128
+ inner.storeBuffer(Buffer.from(p, 'ascii'));
1129
+ inner.storeUint(0, 8);
1130
+ });
1131
+ signedData = (0, core_1.beginCell)()
1132
+ .storeUint(0x75569022, 32) // prefix
1133
+ .storeUint(req.schemaCrc, 32) // schema hash
1134
+ .storeUint(timestamp, 64) // timestamp
1135
+ .storeAddress(expectedAddress) // user wallet address
1136
+ .storeRef(inner) // domain
1137
+ .storeRef(req.data) // payload cell
1138
+ .endCell();
1139
+ break;
1140
+ }
1141
+ default: {
1142
+ throw new Error(`Sign data request type '${req.type}' not supported`);
1143
+ }
1144
+ }
1145
+ const pkg = Buffer.concat([
1146
+ (0, ledgerWriter_1.writeUint8)(typeId),
1147
+ (0, ledgerWriter_1.writeUint8)(flags),
1148
+ specifiersBuf,
1149
+ (0, ledgerWriter_1.writeUint8)(domainBuf.length),
1150
+ domainBuf,
1151
+ (0, ledgerWriter_1.writeUint64)(BigInt(timestamp)),
1152
+ payload,
1153
+ ]);
1154
+ await this.#doRequest(INS_SIGN_DATA, 0x01, 0x03, pathElementsToBuffer(path.map((v) => v + 0x80000000)));
1155
+ const pkgCs = chunks(pkg, 255);
1156
+ for (let i = 0; i < pkgCs.length - 1; i++) {
1157
+ await this.#doRequest(INS_SIGN_DATA, 0x01, 0x02, pkgCs[i]);
1158
+ }
1159
+ const res = await this.#doRequest(INS_SIGN_DATA, 0x01, 0x00, pkgCs[pkgCs.length - 1]);
1160
+ let signature = res.subarray(1, 1 + 64);
1161
+ let hash = res.subarray(2 + 64, 2 + 64 + 32);
1162
+ const signedDataHash = signedData instanceof core_1.Cell ? signedData.hash() : (0, crypto_1.sha256_sync)(signedData);
1163
+ if (!hash.equals(signedDataHash)) {
1164
+ throw Error('Hash mismatch. Expected: ' + signedDataHash.toString('hex') + ', got: ' + hash.toString('hex'));
1165
+ }
1166
+ if (!(0, crypto_1.signVerify)(signedDataHash, signature, publicKey)) {
1167
+ throw Error('Received signature is invalid');
1168
+ }
1169
+ return {
1170
+ signature,
1171
+ address: expectedAddress,
1172
+ signedData,
1173
+ signedDataHash,
1174
+ timestamp,
1175
+ };
1176
+ }
1067
1177
  signTransaction = async (path, transaction) => {
1068
1178
  // Check path
1069
1179
  validatePath(path);
@@ -1246,6 +1356,9 @@ class TonTransport {
1246
1356
  expertMode: (loaded[0] & 0x02) > 0,
1247
1357
  };
1248
1358
  }
1359
+ async launchApp() {
1360
+ await this.#doRequest(0xd8, 0x00, 0x00, Buffer.from('TON', 'ascii'));
1361
+ }
1249
1362
  #doRequest = async (ins, p1, p2, data) => {
1250
1363
  return this.#lock.inLock(async () => {
1251
1364
  let r = await this.transport.send(LEDGER_CLA, ins, p1, p2, data);
@@ -1,4 +1,5 @@
1
1
  /// <reference types="node" />
2
+ /// <reference types="node" />
2
3
  import { Cell } from '@ton/core';
3
4
  export declare function getInit(publicKey: Buffer, subwalletId: number, isV3R2: boolean): {
4
5
  code: Cell;
@@ -1,5 +1,7 @@
1
1
  /// <reference types="node" />
2
+ /// <reference types="node" />
2
3
  import { Address, Cell } from '@ton/core';
4
+ export declare function writeInt32BE(value: number): Buffer;
3
5
  export declare function writeUint32(value: number): Buffer;
4
6
  export declare function writeUint16(value: number): Buffer;
5
7
  export declare function writeUint48(value: number): Buffer;
@@ -1,7 +1,13 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.writeCellInline = exports.writeCellRef = exports.writeAddress = exports.writeUint8 = exports.writeVarUInt = exports.writeUint64 = exports.writeUint48 = exports.writeUint16 = exports.writeUint32 = void 0;
3
+ exports.writeCellInline = exports.writeCellRef = exports.writeAddress = exports.writeUint8 = exports.writeVarUInt = exports.writeUint64 = exports.writeUint48 = exports.writeUint16 = exports.writeUint32 = exports.writeInt32BE = void 0;
4
4
  const core_1 = require("@ton/core");
5
+ function writeInt32BE(value) {
6
+ let b = Buffer.alloc(4);
7
+ b.writeInt32BE(value, 0);
8
+ return b;
9
+ }
10
+ exports.writeInt32BE = writeInt32BE;
5
11
  function writeUint32(value) {
6
12
  let b = Buffer.alloc(4);
7
13
  b.writeUint32BE(value, 0);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ton-community/ton-ledger",
3
- "version": "7.3.0",
3
+ "version": "7.4.0-pre.1",
4
4
  "repository": "https://github.com/ton-community/ton-ledger-ts",
5
5
  "author": "Steve Korshakov <steve@korshakov.com>",
6
6
  "license": "MIT",
@@ -21,7 +21,7 @@
21
21
  "@release-it/keep-a-changelog": "^3.1.0",
22
22
  "@ton/core": "^0.52.2",
23
23
  "@types/jest": "^29.5.2",
24
- "@types/node": "^20.2.5",
24
+ "@types/node": "^22.18.1",
25
25
  "jest": "^29.5.0",
26
26
  "release-it": "^15.11.0",
27
27
  "ts-jest": "^29.1.0",