@ton-community/ton-ledger 7.2.0 → 7.3.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 +5 -0
- package/dist/TonTransport.d.ts +26 -0
- package/dist/TonTransport.js +203 -9
- package/dist/index.d.ts +1 -1
- package/dist/index.js +2 -1
- package/package.json +4 -4
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,11 @@ 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
|
+
## [7.3.0] - 2025-08-21
|
|
8
|
+
|
|
9
|
+
- New jettons
|
|
10
|
+
- Fixed `includeWalletOp`
|
|
11
|
+
|
|
7
12
|
## [7.2.0] - 2025-02-07
|
|
8
13
|
|
|
9
14
|
- Added support for TON Ledger App 2.2.0 features, including:
|
package/dist/TonTransport.d.ts
CHANGED
|
@@ -6,6 +6,12 @@ export type KnownJetton = {
|
|
|
6
6
|
masterAddress: Address;
|
|
7
7
|
};
|
|
8
8
|
export declare const KNOWN_JETTONS: KnownJetton[];
|
|
9
|
+
export type ExtraCurrency = {
|
|
10
|
+
id: number;
|
|
11
|
+
symbol: string;
|
|
12
|
+
decimals: number;
|
|
13
|
+
};
|
|
14
|
+
export declare const KNOWN_EXTRA_CURRENCIES: ExtraCurrency[];
|
|
9
15
|
export type TonPayloadFormat = {
|
|
10
16
|
type: 'unsafe';
|
|
11
17
|
message: Cell;
|
|
@@ -82,6 +88,22 @@ export type TonPayloadFormat = {
|
|
|
82
88
|
type: 'token-bridge-pay-swap';
|
|
83
89
|
queryId: bigint | null;
|
|
84
90
|
swapId: Buffer;
|
|
91
|
+
} | {
|
|
92
|
+
type: 'tonwhales-pool-deposit';
|
|
93
|
+
queryId: bigint;
|
|
94
|
+
gasLimit: bigint;
|
|
95
|
+
} | {
|
|
96
|
+
type: 'tonwhales-pool-withdraw';
|
|
97
|
+
queryId: bigint;
|
|
98
|
+
gasLimit: bigint;
|
|
99
|
+
amount: bigint;
|
|
100
|
+
} | {
|
|
101
|
+
type: 'vesting-send-msg-comment';
|
|
102
|
+
queryId: bigint | null;
|
|
103
|
+
sendMode: number;
|
|
104
|
+
value: bigint;
|
|
105
|
+
destination: Address;
|
|
106
|
+
text: string;
|
|
85
107
|
};
|
|
86
108
|
export declare function parseMessage(cell: Cell, opts?: {
|
|
87
109
|
disallowUnsafe?: boolean;
|
|
@@ -158,6 +180,10 @@ export declare class TonTransport {
|
|
|
158
180
|
subwalletId?: number;
|
|
159
181
|
includeWalletOp: boolean;
|
|
160
182
|
};
|
|
183
|
+
extraCurrency?: {
|
|
184
|
+
index: number;
|
|
185
|
+
amount: bigint;
|
|
186
|
+
};
|
|
161
187
|
}) => Promise<Cell>;
|
|
162
188
|
getSettings(): Promise<{
|
|
163
189
|
blindSigningEnabled: boolean;
|
package/dist/TonTransport.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.TonTransport = exports.parseMessage = exports.KNOWN_JETTONS = void 0;
|
|
3
|
+
exports.TonTransport = exports.parseMessage = exports.KNOWN_EXTRA_CURRENCIES = exports.KNOWN_JETTONS = void 0;
|
|
4
4
|
const core_1 = require("@ton/core");
|
|
5
5
|
const crypto_1 = require("@ton/crypto");
|
|
6
6
|
const teslabot_1 = require("teslabot");
|
|
@@ -44,6 +44,25 @@ exports.KNOWN_JETTONS = [
|
|
|
44
44
|
symbol: 'STAKED',
|
|
45
45
|
masterAddress: core_1.Address.parse('EQCqC6EhRJ_tpWngKxL6dV0k6DSnRUrs9GSVkLbfdCqsj6TE'),
|
|
46
46
|
},
|
|
47
|
+
{
|
|
48
|
+
symbol: 'CATI',
|
|
49
|
+
masterAddress: core_1.Address.parse('EQD-cvR0Nz6XAyRBvbhz-abTrRC6sI5tvHvvpeQraV9UAAD7'),
|
|
50
|
+
},
|
|
51
|
+
{
|
|
52
|
+
symbol: 'DOGS',
|
|
53
|
+
masterAddress: core_1.Address.parse('EQCvxJy4eG8hyHBFsZ7eePxrRsUQSFE_jpptRAYBmcG_DOGS'),
|
|
54
|
+
},
|
|
55
|
+
{
|
|
56
|
+
symbol: 'X',
|
|
57
|
+
masterAddress: core_1.Address.parse('EQB4zZusHsbU2vVTPqjhlokIOoiZhEdCMT703CWEzhTOo__X'),
|
|
58
|
+
},
|
|
59
|
+
];
|
|
60
|
+
exports.KNOWN_EXTRA_CURRENCIES = [
|
|
61
|
+
{
|
|
62
|
+
id: 1,
|
|
63
|
+
symbol: 'tgBTC',
|
|
64
|
+
decimals: 8,
|
|
65
|
+
},
|
|
47
66
|
];
|
|
48
67
|
const dnsWalletKey = Buffer.from([0xe8, 0xd4, 0x40, 0x50, 0x87, 0x3d, 0xba, 0x86, 0x5a, 0xa7, 0xc1, 0x70, 0xab, 0x4c, 0xce, 0x64,
|
|
49
68
|
0xd9, 0x08, 0x39, 0xa3, 0x4d, 0xcf, 0xd6, 0xcf, 0x71, 0xd1, 0x4e, 0x02, 0x05, 0x44, 0x3b, 0x1b]);
|
|
@@ -336,6 +355,62 @@ function parseMessage(cell, opts) {
|
|
|
336
355
|
swapId,
|
|
337
356
|
};
|
|
338
357
|
}
|
|
358
|
+
case 0x7bcd1fef: {
|
|
359
|
+
const queryId = s.loadUintBig(64);
|
|
360
|
+
if (queryId <= 0n) {
|
|
361
|
+
throw new Error('Incorrect query id: must be greater than 0');
|
|
362
|
+
}
|
|
363
|
+
const gasLimit = s.loadCoins();
|
|
364
|
+
s.endParse();
|
|
365
|
+
return {
|
|
366
|
+
type: 'tonwhales-pool-deposit',
|
|
367
|
+
queryId,
|
|
368
|
+
gasLimit,
|
|
369
|
+
};
|
|
370
|
+
}
|
|
371
|
+
case 0xda803efd: {
|
|
372
|
+
const queryId = s.loadUintBig(64);
|
|
373
|
+
if (queryId <= 0n) {
|
|
374
|
+
throw new Error('Incorrect query id: must be greater than 0');
|
|
375
|
+
}
|
|
376
|
+
const gasLimit = s.loadCoins();
|
|
377
|
+
const amount = s.loadCoins();
|
|
378
|
+
s.endParse();
|
|
379
|
+
return {
|
|
380
|
+
type: 'tonwhales-pool-withdraw',
|
|
381
|
+
queryId,
|
|
382
|
+
gasLimit,
|
|
383
|
+
amount,
|
|
384
|
+
};
|
|
385
|
+
}
|
|
386
|
+
case 0xa7733acd: {
|
|
387
|
+
const queryId = normalizeQueryId(s.loadUintBig(64));
|
|
388
|
+
const sendMode = s.loadUint(8);
|
|
389
|
+
const msgRefSlice = s.loadRef().beginParse();
|
|
390
|
+
s.endParse();
|
|
391
|
+
const msg = (0, core_1.loadMessageRelaxed)(msgRefSlice);
|
|
392
|
+
if (msg.info.type !== 'internal') {
|
|
393
|
+
throw new Error('Message is not internal');
|
|
394
|
+
}
|
|
395
|
+
const body = msg.body.beginParse();
|
|
396
|
+
const op = body.loadUint(32);
|
|
397
|
+
if (op !== 0) {
|
|
398
|
+
throw new Error('Message body is not a comment');
|
|
399
|
+
}
|
|
400
|
+
const text = body.loadStringTail();
|
|
401
|
+
if (text.length > 120) {
|
|
402
|
+
throw new Error('Comment must be at most 120 ASCII characters long');
|
|
403
|
+
}
|
|
404
|
+
body.endParse();
|
|
405
|
+
return {
|
|
406
|
+
type: 'vesting-send-msg-comment',
|
|
407
|
+
queryId,
|
|
408
|
+
sendMode,
|
|
409
|
+
value: msg.info.value.coins,
|
|
410
|
+
destination: msg.info.dest,
|
|
411
|
+
text,
|
|
412
|
+
};
|
|
413
|
+
}
|
|
339
414
|
}
|
|
340
415
|
throw new Error('Unknown op: ' + op);
|
|
341
416
|
}
|
|
@@ -706,6 +781,92 @@ function convertPayload(input) {
|
|
|
706
781
|
]);
|
|
707
782
|
break;
|
|
708
783
|
}
|
|
784
|
+
case 'tonwhales-pool-deposit': {
|
|
785
|
+
hints = Buffer.concat([
|
|
786
|
+
(0, ledgerWriter_1.writeUint8)(1),
|
|
787
|
+
(0, ledgerWriter_1.writeUint32)(0x0B)
|
|
788
|
+
]);
|
|
789
|
+
const cell = (0, core_1.beginCell)()
|
|
790
|
+
.storeUint(0x7bcd1fef, 32)
|
|
791
|
+
.storeUint(input.queryId, 64)
|
|
792
|
+
.storeCoins(input.gasLimit)
|
|
793
|
+
.endCell();
|
|
794
|
+
const buffer = Buffer.concat([
|
|
795
|
+
(0, ledgerWriter_1.writeUint64)(input.queryId),
|
|
796
|
+
(0, ledgerWriter_1.writeVarUInt)(input.gasLimit)
|
|
797
|
+
]);
|
|
798
|
+
payload = cell;
|
|
799
|
+
hints = Buffer.concat([
|
|
800
|
+
hints,
|
|
801
|
+
(0, ledgerWriter_1.writeUint16)(buffer.length),
|
|
802
|
+
buffer
|
|
803
|
+
]);
|
|
804
|
+
break;
|
|
805
|
+
}
|
|
806
|
+
case 'tonwhales-pool-withdraw': {
|
|
807
|
+
hints = Buffer.concat([
|
|
808
|
+
(0, ledgerWriter_1.writeUint8)(1),
|
|
809
|
+
(0, ledgerWriter_1.writeUint32)(0x0C)
|
|
810
|
+
]);
|
|
811
|
+
const cell = (0, core_1.beginCell)()
|
|
812
|
+
.storeUint(0xda803efd, 32)
|
|
813
|
+
.storeUint(input.queryId, 64)
|
|
814
|
+
.storeCoins(input.gasLimit)
|
|
815
|
+
.storeCoins(input.amount)
|
|
816
|
+
.endCell();
|
|
817
|
+
const buffer = Buffer.concat([
|
|
818
|
+
(0, ledgerWriter_1.writeUint64)(input.queryId),
|
|
819
|
+
(0, ledgerWriter_1.writeVarUInt)(input.gasLimit),
|
|
820
|
+
(0, ledgerWriter_1.writeVarUInt)(input.amount)
|
|
821
|
+
]);
|
|
822
|
+
payload = cell;
|
|
823
|
+
hints = Buffer.concat([
|
|
824
|
+
hints,
|
|
825
|
+
(0, ledgerWriter_1.writeUint16)(buffer.length),
|
|
826
|
+
buffer
|
|
827
|
+
]);
|
|
828
|
+
break;
|
|
829
|
+
}
|
|
830
|
+
case 'vesting-send-msg-comment': {
|
|
831
|
+
hints = Buffer.concat([
|
|
832
|
+
(0, ledgerWriter_1.writeUint8)(1),
|
|
833
|
+
(0, ledgerWriter_1.writeUint32)(0x0D)
|
|
834
|
+
]);
|
|
835
|
+
let builder = (0, core_1.beginCell)()
|
|
836
|
+
.storeUint(0xa7733acd, 32);
|
|
837
|
+
let buffer = Buffer.alloc(0);
|
|
838
|
+
if (input.queryId !== null) {
|
|
839
|
+
builder = builder.storeUint(input.queryId, 64);
|
|
840
|
+
buffer = Buffer.concat([buffer, (0, ledgerWriter_1.writeUint8)(1), (0, ledgerWriter_1.writeUint64)(input.queryId)]);
|
|
841
|
+
}
|
|
842
|
+
else {
|
|
843
|
+
builder = builder.storeUint(0, 64);
|
|
844
|
+
buffer = Buffer.concat([buffer, (0, ledgerWriter_1.writeUint8)(0)]);
|
|
845
|
+
}
|
|
846
|
+
builder = builder.storeUint(input.sendMode, 8);
|
|
847
|
+
buffer = Buffer.concat([buffer, (0, ledgerWriter_1.writeUint8)(input.sendMode)]);
|
|
848
|
+
const msg = (0, core_1.internal)({
|
|
849
|
+
to: input.destination,
|
|
850
|
+
value: input.value,
|
|
851
|
+
body: (0, core_1.beginCell)().storeUint(0, 32).storeStringTail(input.text).endCell(),
|
|
852
|
+
});
|
|
853
|
+
const msgRefBuilder = (0, core_1.beginCell)();
|
|
854
|
+
(0, core_1.storeMessageRelaxed)(msg)(msgRefBuilder);
|
|
855
|
+
builder = builder.storeRef(msgRefBuilder.endCell());
|
|
856
|
+
buffer = Buffer.concat([buffer, (0, ledgerWriter_1.writeAddress)(input.destination)]);
|
|
857
|
+
buffer = Buffer.concat([buffer, (0, ledgerWriter_1.writeVarUInt)(input.value)]);
|
|
858
|
+
if (input.text.length > 120) {
|
|
859
|
+
throw new Error('Comment must be at most 120 ASCII characters long');
|
|
860
|
+
}
|
|
861
|
+
buffer = Buffer.concat([buffer, (0, ledgerWriter_1.writeUint8)(Buffer.from(input.text).length), Buffer.from(input.text)]);
|
|
862
|
+
payload = builder.endCell();
|
|
863
|
+
hints = Buffer.concat([
|
|
864
|
+
hints,
|
|
865
|
+
(0, ledgerWriter_1.writeUint16)(buffer.length),
|
|
866
|
+
buffer
|
|
867
|
+
]);
|
|
868
|
+
break;
|
|
869
|
+
}
|
|
709
870
|
default: {
|
|
710
871
|
throw new Error('Unknown payload type: ' + input.type);
|
|
711
872
|
}
|
|
@@ -906,6 +1067,9 @@ class TonTransport {
|
|
|
906
1067
|
signTransaction = async (path, transaction) => {
|
|
907
1068
|
// Check path
|
|
908
1069
|
validatePath(path);
|
|
1070
|
+
if (transaction.extraCurrency !== undefined && transaction.extraCurrency.index >= exports.KNOWN_EXTRA_CURRENCIES.length) {
|
|
1071
|
+
throw Error('Invalid extra currency index');
|
|
1072
|
+
}
|
|
909
1073
|
//
|
|
910
1074
|
// Fetch key
|
|
911
1075
|
//
|
|
@@ -913,14 +1077,31 @@ class TonTransport {
|
|
|
913
1077
|
//
|
|
914
1078
|
// Create package
|
|
915
1079
|
//
|
|
1080
|
+
const includeWalletOp = transaction.walletSpecifiers?.includeWalletOp ?? true;
|
|
1081
|
+
const subwalletId = transaction.walletSpecifiers?.subwalletId ?? DEFAULT_SUBWALLET_ID;
|
|
1082
|
+
const useTag1 = transaction.walletSpecifiers !== undefined || transaction.extraCurrency !== undefined;
|
|
916
1083
|
let pkg = Buffer.concat([
|
|
917
|
-
(0, ledgerWriter_1.writeUint8)(
|
|
1084
|
+
(0, ledgerWriter_1.writeUint8)(useTag1 ? 1 : 0), // tag
|
|
918
1085
|
]);
|
|
919
|
-
if (
|
|
1086
|
+
if (useTag1) {
|
|
1087
|
+
let flags = 0;
|
|
1088
|
+
if (includeWalletOp) {
|
|
1089
|
+
flags |= 1;
|
|
1090
|
+
}
|
|
1091
|
+
if (transaction.extraCurrency !== undefined) {
|
|
1092
|
+
flags |= 2;
|
|
1093
|
+
}
|
|
920
1094
|
pkg = Buffer.concat([
|
|
921
1095
|
pkg,
|
|
922
|
-
(0, ledgerWriter_1.writeUint32)(
|
|
923
|
-
(0, ledgerWriter_1.writeUint8)(
|
|
1096
|
+
(0, ledgerWriter_1.writeUint32)(subwalletId),
|
|
1097
|
+
(0, ledgerWriter_1.writeUint8)(flags),
|
|
1098
|
+
]);
|
|
1099
|
+
}
|
|
1100
|
+
let ecBuf = Buffer.alloc(0);
|
|
1101
|
+
if (transaction.extraCurrency !== undefined) {
|
|
1102
|
+
ecBuf = Buffer.concat([
|
|
1103
|
+
(0, ledgerWriter_1.writeUint8)(transaction.extraCurrency.index),
|
|
1104
|
+
(0, ledgerWriter_1.writeVarUInt)(transaction.extraCurrency.amount),
|
|
924
1105
|
]);
|
|
925
1106
|
}
|
|
926
1107
|
pkg = Buffer.concat([
|
|
@@ -928,6 +1109,7 @@ class TonTransport {
|
|
|
928
1109
|
(0, ledgerWriter_1.writeUint32)(transaction.seqno),
|
|
929
1110
|
(0, ledgerWriter_1.writeUint32)(transaction.timeout),
|
|
930
1111
|
(0, ledgerWriter_1.writeVarUInt)(transaction.amount),
|
|
1112
|
+
ecBuf,
|
|
931
1113
|
(0, ledgerWriter_1.writeAddress)(transaction.to),
|
|
932
1114
|
(0, ledgerWriter_1.writeUint8)(transaction.bounce ? 1 : 0),
|
|
933
1115
|
(0, ledgerWriter_1.writeUint8)(transaction.sendMode),
|
|
@@ -992,8 +1174,20 @@ class TonTransport {
|
|
|
992
1174
|
.storeBit(false)
|
|
993
1175
|
.storeAddress(null)
|
|
994
1176
|
.storeAddress(transaction.to)
|
|
995
|
-
.storeCoins(transaction.amount)
|
|
996
|
-
|
|
1177
|
+
.storeCoins(transaction.amount);
|
|
1178
|
+
if (transaction.extraCurrency !== undefined) {
|
|
1179
|
+
orderBuilder = orderBuilder
|
|
1180
|
+
.storeBit(true)
|
|
1181
|
+
.storeRef((0, core_1.beginCell)()
|
|
1182
|
+
.storeUint(0b10, 2)
|
|
1183
|
+
.storeUint(32, 6)
|
|
1184
|
+
.storeUint(exports.KNOWN_EXTRA_CURRENCIES[transaction.extraCurrency.index].id, 32)
|
|
1185
|
+
.storeVarUint(transaction.extraCurrency.amount, 5));
|
|
1186
|
+
}
|
|
1187
|
+
else {
|
|
1188
|
+
orderBuilder = orderBuilder.storeBit(false);
|
|
1189
|
+
}
|
|
1190
|
+
orderBuilder = orderBuilder
|
|
997
1191
|
.storeCoins(0)
|
|
998
1192
|
.storeCoins(0)
|
|
999
1193
|
.storeUint(0, 64)
|
|
@@ -1021,10 +1215,10 @@ class TonTransport {
|
|
|
1021
1215
|
}
|
|
1022
1216
|
// Transfer message
|
|
1023
1217
|
let transferB = (0, core_1.beginCell)()
|
|
1024
|
-
.storeUint(
|
|
1218
|
+
.storeUint(subwalletId, 32)
|
|
1025
1219
|
.storeUint(transaction.timeout, 32)
|
|
1026
1220
|
.storeUint(transaction.seqno, 32);
|
|
1027
|
-
if (
|
|
1221
|
+
if (includeWalletOp) {
|
|
1028
1222
|
transferB = transferB.storeUint(0, 8);
|
|
1029
1223
|
}
|
|
1030
1224
|
let transfer = transferB.storeUint(transaction.sendMode, 8)
|
package/dist/index.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export { TonPayloadFormat, TonTransport, SignDataRequest, parseMessage, KNOWN_JETTONS } from './TonTransport';
|
|
1
|
+
export { TonPayloadFormat, TonTransport, SignDataRequest, parseMessage, KnownJetton, KNOWN_JETTONS, ExtraCurrency, KNOWN_EXTRA_CURRENCIES } from './TonTransport';
|
package/dist/index.js
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.KNOWN_JETTONS = exports.parseMessage = exports.TonTransport = void 0;
|
|
3
|
+
exports.KNOWN_EXTRA_CURRENCIES = exports.KNOWN_JETTONS = exports.parseMessage = exports.TonTransport = void 0;
|
|
4
4
|
var TonTransport_1 = require("./TonTransport");
|
|
5
5
|
Object.defineProperty(exports, "TonTransport", { enumerable: true, get: function () { return TonTransport_1.TonTransport; } });
|
|
6
6
|
Object.defineProperty(exports, "parseMessage", { enumerable: true, get: function () { return TonTransport_1.parseMessage; } });
|
|
7
7
|
Object.defineProperty(exports, "KNOWN_JETTONS", { enumerable: true, get: function () { return TonTransport_1.KNOWN_JETTONS; } });
|
|
8
|
+
Object.defineProperty(exports, "KNOWN_EXTRA_CURRENCIES", { enumerable: true, get: function () { return TonTransport_1.KNOWN_EXTRA_CURRENCIES; } });
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ton-community/ton-ledger",
|
|
3
|
-
"version": "7.
|
|
3
|
+
"version": "7.3.0",
|
|
4
4
|
"repository": "https://github.com/ton-community/ton-ledger-ts",
|
|
5
5
|
"author": "Steve Korshakov <steve@korshakov.com>",
|
|
6
6
|
"license": "MIT",
|
|
@@ -18,7 +18,6 @@
|
|
|
18
18
|
"@ton/core": ">=0.52.2"
|
|
19
19
|
},
|
|
20
20
|
"devDependencies": {
|
|
21
|
-
"@ledgerhq/hw-transport-node-hid": "^6.27.15",
|
|
22
21
|
"@release-it/keep-a-changelog": "^3.1.0",
|
|
23
22
|
"@ton/core": "^0.52.2",
|
|
24
23
|
"@types/jest": "^29.5.2",
|
|
@@ -30,7 +29,7 @@
|
|
|
30
29
|
"typescript": "^4.9.5"
|
|
31
30
|
},
|
|
32
31
|
"dependencies": {
|
|
33
|
-
"@ledgerhq/hw-transport": "^6.
|
|
32
|
+
"@ledgerhq/hw-transport": "^6.31.4",
|
|
34
33
|
"@ton/crypto": "^3.2.0",
|
|
35
34
|
"teslabot": "^1.5.0"
|
|
36
35
|
},
|
|
@@ -47,5 +46,6 @@
|
|
|
47
46
|
"filename": "CHANGELOG.md"
|
|
48
47
|
}
|
|
49
48
|
}
|
|
50
|
-
}
|
|
49
|
+
},
|
|
50
|
+
"packageManager": "yarn@1.22.22+sha512.a6b2f7906b721bba3d67d4aff083df04dad64c399707841b7acf00f6b133b7ac24255f2652fa22ae3534329dc6180534e98d17432037ff6fd140556e2bb3137e"
|
|
51
51
|
}
|