wan-ton-sdk 0.0.6
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/Bridge.compile.ts +8 -0
- package/Bridge.ts +645 -0
- package/Bridge.ts.org +647 -0
- package/Fake.compile.ts +8 -0
- package/GroupApprove.compile.ts +6 -0
- package/GroupApprove.ts +274 -0
- package/JettonMinter.compile.ts +5 -0
- package/JettonMinter.ts +135 -0
- package/JettonWallet.compile.ts +5 -0
- package/JettonWallet.ts +127 -0
- package/README.md +24 -0
- package/Signature.compile.ts +6 -0
- package/Signature.ts +105 -0
- package/address.compile.ts +8 -0
- package/client/1.json +1730 -0
- package/client/client.ts +73 -0
- package/client/log/.ba8901062aebb86bf525b42c65ff84f9485419e4-audit.json +15 -0
- package/client/log/wan-ton-sdk.out.2024-12-19 +0 -0
- package/code/decode.spec.ts +81 -0
- package/code/encode-decode.ts +622 -0
- package/code/log/.ba8901062aebb86bf525b42c65ff84f9485419e4-audit.json +20 -0
- package/code/log/wan-ton-sdk.out.2025-01-15 +0 -0
- package/code/log/wan-ton-sdk.out.2025-01-20 +0 -0
- package/code/userLock.ts +291 -0
- package/common.ts +62 -0
- package/config/config-ex.ts +25 -0
- package/config/config.ts +1 -0
- package/const/const-value.ts +33 -0
- package/contractAccess/bridgeAccess.ts +60 -0
- package/contractAccess/groupApproveAccess.ts +59 -0
- package/data/EQCxE6mUtQJKFnGfaROTKOt1lZbDiiX1kCixRv7Nw2Id_sDs.json +7348 -0
- package/db/Db.spec.ts +193 -0
- package/db/Db.ts +736 -0
- package/db/DbAccess.spec.ts +23 -0
- package/db/DbAccess.ts +174 -0
- package/db/common.ts +94 -0
- package/db/log/.ba8901062aebb86bf525b42c65ff84f9485419e4-audit.json +15 -0
- package/db/log/wan-ton-sdk.out.2025-04-21 +0 -0
- package/event/getEvents.ts +441 -0
- package/event/log/.ba8901062aebb86bf525b42c65ff84f9485419e4-audit.json +15 -0
- package/event/log/wan-ton-sdk.out.2024-12-19 +0 -0
- package/example/0:1.txt +1 -0
- package/example/AddToken-ex.ts +148 -0
- package/example/README.md +21 -0
- package/example/addSmg-ex.ts +78 -0
- package/example/addTokenPair-ex.ts +73 -0
- package/example/compileContract-ex.ts +10 -0
- package/example/converTranToTonTran.ts +43 -0
- package/example/createDb-ex.ts +8 -0
- package/example/dbFeedTrans-ex.ts +20 -0
- package/example/delTokenPair-ex.ts +63 -0
- package/example/deploy-ex.ts +68 -0
- package/example/getAllEvents-ex.ts +61 -0
- package/example/getAllTrans.ts +32 -0
- package/example/getContractState-ex.ts +33 -0
- package/example/getEventByHash-ex.ts +39 -0
- package/example/getEvents-ex.ts +55 -0
- package/example/getJettonInfo-ex.ts +44 -0
- package/example/getTokenPair-ex.ts +47 -0
- package/example/getTransByRange-ex.ts +81 -0
- package/example/getTransaction-ex.ts +62 -0
- package/example/isTranSuccess-ex.ts +33 -0
- package/example/locateTx-ex.ts +44 -0
- package/example/log/.ba8901062aebb86bf525b42c65ff84f9485419e4-audit.json +55 -0
- package/example/log/wan-ton-sdk.out.2025-04-21 +447 -0
- package/example/log/wan-ton-sdk.out.2025-04-22 +1918 -0
- package/example/log/wan-ton-sdk.out.2025-04-23 +4216 -0
- package/example/log/wan-ton-sdk.out.2025-04-24.gz +0 -0
- package/example/log/wan-ton-sdk.out.2025-04-25 +46814 -0
- package/example/log/wan-ton-sdk.out.2025-04-27.gz +0 -0
- package/example/log/wan-ton-sdk.out.2025-04-28 +4966 -0
- package/example/log/wan-ton-sdk.out.2025-04-29 +1328 -0
- package/example/log/wan-ton-sdk.out.2025-04-30 +9 -0
- package/example/mintToken-ex.ts +82 -0
- package/example/setFee-ex.ts +82 -0
- package/example/setFeeProxy.ts +70 -0
- package/example/smgRelease-ex.ts +173 -0
- package/example/upgradeBridgeSc-ex.ts +49 -0
- package/example/userLock-ex.ts +78 -0
- package/fee/fee.ts +23 -0
- package/index.ts +67 -0
- package/jest.config.ts +9 -0
- package/log/.ba8901062aebb86bf525b42c65ff84f9485419e4-audit.json +20 -0
- package/log/wan-ton-sdk.out.2025-04-21 +0 -0
- package/log/wan-ton-sdk.out.2025-04-30 +10 -0
- package/opcodes.ts +58 -0
- package/package.json +34 -0
- package/publish.sh +78 -0
- package/sign/buildHash.ts +47 -0
- package/sign/log/.ba8901062aebb86bf525b42c65ff84f9485419e4-audit.json +15 -0
- package/sign/log/wan-ton-sdk.out.2025-04-14 +3 -0
- package/sign/rawTrans.spec.ts +117 -0
- package/sign/rawTrans.ts +122 -0
- package/sign/tools-secp256k1.js +210 -0
- package/testData/JettonMinter.compile.func.ts +8 -0
- package/testData/JettonWallet.compile.func.ts +8 -0
- package/testData/addressList.json +6 -0
- package/testData/bridge.compile.func.ts +8 -0
- package/testData/bridge.compiled.json +1 -0
- package/testData/contractAddress.json +7 -0
- package/testData/jettonTokenInfo.json +14 -0
- package/testData/prvlist.json +6 -0
- package/testData/smg.json +5 -0
- package/testData/tokenInfo.json +23 -0
- package/transResult/transResult.ts +621 -0
- package/tsconfig.json +19 -0
- package/utils/.compiled.json +1 -0
- package/utils/compileContract.ts +60 -0
- package/utils/log/.ba8901062aebb86bf525b42c65ff84f9485419e4-audit.json +15 -0
- package/utils/log/wan-ton-sdk.out.2025-01-08 +0 -0
- package/utils/logger.spec.ts +14 -0
- package/utils/logger.ts +96 -0
- package/utils/utils.spec.ts +21 -0
- package/utils/utils.ts +295 -0
- package/wallet/balance.ts +29 -0
- package/wallet/jetton.spec.ts +27 -0
- package/wallet/jetton.ts +159 -0
- package/wallet/walletContract.spec.ts +111 -0
- package/wallet/walletContract.ts +105 -0
@@ -0,0 +1,621 @@
|
|
1
|
+
import {Address, beginCell, storeMessage, storeMessageRelaxed, Transaction} from "@ton/core";
|
2
|
+
import {TonClient} from "@ton/ton";
|
3
|
+
import {TransactionDescriptionGeneric} from "@ton/core/src/types/TransactionDescription";
|
4
|
+
import {TransactionComputeVm} from "@ton/core/src/types/TransactionComputePhase";
|
5
|
+
import {bigIntReplacer, formatError} from "../utils/utils";
|
6
|
+
import {CommonMessageInfoInternal} from "@ton/core/src/types/CommonMessageInfo";
|
7
|
+
import {DBAccess} from "../db/DbAccess";
|
8
|
+
import {convertTranToTonTrans} from "../db/common";
|
9
|
+
import { MAX_LIMIT } from "../const/const-value";
|
10
|
+
const formatUtil = require('util');
|
11
|
+
|
12
|
+
function sleep(ms) {
|
13
|
+
return new Promise(resolve => setTimeout(resolve, ms));
|
14
|
+
}
|
15
|
+
|
16
|
+
/*
|
17
|
+
return
|
18
|
+
[
|
19
|
+
{
|
20
|
+
addr: Address,
|
21
|
+
txHash: string,
|
22
|
+
gasUsed: bigInt,
|
23
|
+
status: boolean,
|
24
|
+
},
|
25
|
+
...
|
26
|
+
]
|
27
|
+
*/
|
28
|
+
|
29
|
+
async function getTranPathInfoByMsgHash(client: TonClient, scAddr: Address, msgBodyCellHash:string, msgInHash: string): Promise<TranPathInfo> {
|
30
|
+
let pivotTran = await getTranByMsgHash(client, scAddr, msgBodyCellHash,msgInHash);
|
31
|
+
let path = await getTranPathInfoByPivotTran(client, scAddr, pivotTran);
|
32
|
+
return path;
|
33
|
+
}
|
34
|
+
|
35
|
+
export async function isTranSuccess(tran:Transaction):Promise<boolean>{
|
36
|
+
//https://testnet.tonviewer.com/transaction/3a80c94fa62a855ebb47c634f1b42ebd0fdc9ea35ab3f6389bf2c086aac887ef
|
37
|
+
let td = tran.description as unknown as TransactionDescriptionGeneric
|
38
|
+
// if(td.aborted){
|
39
|
+
// return false
|
40
|
+
// }
|
41
|
+
|
42
|
+
let cp = td.computePhase as unknown as TransactionComputeVm
|
43
|
+
if( (cp.type == "vm") && (!cp.success || cp.exitCode != 0)){
|
44
|
+
return false
|
45
|
+
}
|
46
|
+
|
47
|
+
if( td.aborted && cp.type == "vm"){
|
48
|
+
return false
|
49
|
+
}
|
50
|
+
|
51
|
+
let ap = td.actionPhase
|
52
|
+
let apSuccess = ap?.success ? ap.success:true
|
53
|
+
if(!apSuccess){
|
54
|
+
return false;
|
55
|
+
}
|
56
|
+
return true;
|
57
|
+
}
|
58
|
+
|
59
|
+
async function computePathGas(path:TranPathInfo):Promise<bigint>{
|
60
|
+
let ret = BigInt(0);
|
61
|
+
for(let step of path){
|
62
|
+
ret += step.gasUsed
|
63
|
+
}
|
64
|
+
return ret;
|
65
|
+
}
|
66
|
+
|
67
|
+
async function isTranPathSuccess(allTranPathInfo:TranPathInfo):Promise<boolean>{
|
68
|
+
let ret = true;
|
69
|
+
for(let step of allTranPathInfo){
|
70
|
+
if(!step.status){
|
71
|
+
return false
|
72
|
+
}
|
73
|
+
}
|
74
|
+
return true;
|
75
|
+
}
|
76
|
+
|
77
|
+
|
78
|
+
export async function getUpperStepsFromDb(client:TonClient,scAddr:Address,tran:Transaction, path:TranPathInfo){
|
79
|
+
console.log("getUpperStepsFromDb","tran hash",tran.hash().toString('hex'));
|
80
|
+
if(tran.inMessage.info.type == 'external-in'){
|
81
|
+
return
|
82
|
+
}
|
83
|
+
const inMessageCell = beginCell().store(storeMessage( tran.inMessage)).endCell();
|
84
|
+
console.log("getUpperStepsFromDb inMessageCell==>","hash",tran.hash().toString('hex'));
|
85
|
+
|
86
|
+
let upperAddress = tran.inMessage.info.src as Address;
|
87
|
+
|
88
|
+
let maxRetry = 5;
|
89
|
+
//get from scanned db
|
90
|
+
let dbAccess = await DBAccess.getDBAccess();
|
91
|
+
if(!dbAccess){
|
92
|
+
console.error("not using db cache");
|
93
|
+
}
|
94
|
+
let transFromDb = null;
|
95
|
+
let foundInDb = false;
|
96
|
+
while(maxRetry-- >0 && !transFromDb){
|
97
|
+
try{
|
98
|
+
let inDb = await dbAccess?.has(upperAddress.toString());
|
99
|
+
if(!inDb){
|
100
|
+
await dbAccess?.addDbByName(upperAddress.toString());
|
101
|
+
await sleep(2000);
|
102
|
+
}
|
103
|
+
console.log("getUpperStepsFromDb before dbAccess.getParentTx","tran hash",tran.hash().toString('hex'),"upperAddress",upperAddress.toString());
|
104
|
+
transFromDb = await dbAccess?.getParentTx(upperAddress.toString(),convertTranToTonTrans([tran])[0]);
|
105
|
+
if(transFromDb){ // found from db
|
106
|
+
foundInDb = true;
|
107
|
+
}
|
108
|
+
}catch(err){
|
109
|
+
console.log("getTranByMsgHash from db err",formatError(err),"retry ",maxRetry);
|
110
|
+
}
|
111
|
+
await sleep(2000);
|
112
|
+
}
|
113
|
+
if(maxRetry == 0 && !foundInDb){
|
114
|
+
throw new Error(`Fail to look for parent. upDb: ${upperAddress.toString()}`)
|
115
|
+
}
|
116
|
+
if(foundInDb && transFromDb){
|
117
|
+
console.log("getUpperStepsFromDB success","hash",tran.hash().toString('hex'),"parent hash",transFromDb.hash().toString('hex'));
|
118
|
+
let stepInfoTemp :TranStepInfo = {
|
119
|
+
addr:upperAddress as Address,
|
120
|
+
txHash:transFromDb.hash().toString('hex'),
|
121
|
+
gasUsed:transFromDb.totalFees.coins,
|
122
|
+
status:await isTranSuccess(transFromDb),
|
123
|
+
lt:transFromDb.lt.toString(),
|
124
|
+
}
|
125
|
+
path.unshift(stepInfoTemp);
|
126
|
+
|
127
|
+
await getUpperStepsFromDb(client,upperAddress,transFromDb,path);
|
128
|
+
}
|
129
|
+
}
|
130
|
+
|
131
|
+
export async function getUpperSteps(client:TonClient,scAddr:Address,tran:Transaction, path:TranPathInfo){
|
132
|
+
if(tran.inMessage.info.type == 'external-in'){
|
133
|
+
return
|
134
|
+
}
|
135
|
+
|
136
|
+
try{
|
137
|
+
await getUpperStepsFromDb(client,scAddr,tran,path);
|
138
|
+
return;
|
139
|
+
}catch(err){
|
140
|
+
console.log("getUpperStepsFromDb error",formatError(err));
|
141
|
+
}
|
142
|
+
|
143
|
+
const inMessageCell = beginCell().store(storeMessage( tran.inMessage)).endCell();
|
144
|
+
console.log("inMessageCell==>",inMessageCell.toBoc().toString('hex'));
|
145
|
+
let tranInMsgHash = inMessageCell.hash().toString('hex');
|
146
|
+
|
147
|
+
let tranInMsgBodyCellHash = tran.inMessage.body.hash().toString('hex');
|
148
|
+
|
149
|
+
let upperAddress = tran.inMessage.info.src as Address;
|
150
|
+
|
151
|
+
|
152
|
+
let maxTrans = 1000;
|
153
|
+
let transChecked = 0;
|
154
|
+
let opts:{
|
155
|
+
limit: number;
|
156
|
+
lt?: string;
|
157
|
+
hash?: string;
|
158
|
+
to_lt?: string;
|
159
|
+
inclusive?: boolean;
|
160
|
+
archival?: boolean;
|
161
|
+
} = {
|
162
|
+
limit: 10,
|
163
|
+
archival:true,
|
164
|
+
}
|
165
|
+
let foundUpper = false
|
166
|
+
let transCount = 10;
|
167
|
+
|
168
|
+
while(transChecked<maxTrans && !foundUpper && transCount){
|
169
|
+
let retry = 5;
|
170
|
+
let status = false;
|
171
|
+
let transactions:Transaction[] = [];
|
172
|
+
while(--retry > 0 && !status){
|
173
|
+
try{
|
174
|
+
console.log("getUpperSteps getTransactions ","scAddress",upperAddress,"opts",opts);
|
175
|
+
transactions = await client.getTransactions(upperAddress, opts);
|
176
|
+
transCount = transactions.length;
|
177
|
+
status = true;
|
178
|
+
retry = 5;
|
179
|
+
}catch(e){
|
180
|
+
await sleep(1000);
|
181
|
+
console.error(formatError(e))
|
182
|
+
}
|
183
|
+
}
|
184
|
+
if(retry == 0){
|
185
|
+
throw(new Error(formatUtil.format("error getUpperSteps getTransactions ","scAddress",upperAddress,"opts",opts)))
|
186
|
+
}
|
187
|
+
|
188
|
+
for (let i=0; i<transactions.length; i++) {
|
189
|
+
let tx = transactions[i]
|
190
|
+
if(i == transactions.length-1) {
|
191
|
+
opts.lt = tx.lt.toString(10);
|
192
|
+
opts.hash = tx.hash().toString('base64');
|
193
|
+
}
|
194
|
+
const transactionHash = tx.hash().toString('base64');
|
195
|
+
console.log("tx hash is:",i, tx.lt, transactionHash,tx.hash().toString('hex'))
|
196
|
+
const outMessages = tx.outMessages;
|
197
|
+
let foundInOutMsgs = false;
|
198
|
+
for(let outMsgKey of outMessages.keys()){
|
199
|
+
let outMsg = outMessages.get(outMsgKey);
|
200
|
+
let outMsgHash = beginCell().store(storeMessage(outMsg)).endCell().hash().toString('hex');
|
201
|
+
let outMsgBodyHash = outMsg.body.hash().toString('hex');
|
202
|
+
console.log("outMsgHash",outMsgHash,"tranInMsgHash",tranInMsgHash,"outMsgBodyHash",outMsgBodyHash,"tranInMsgBodyCellHash",tranInMsgBodyCellHash);
|
203
|
+
if (outMsgHash == tranInMsgHash || outMsgBodyHash == tranInMsgBodyCellHash){
|
204
|
+
if((outMsg.info.dest as unknown as Address).equals(scAddr)){
|
205
|
+
if((outMsg.info as unknown as CommonMessageInfoInternal).createdLt == (tran.inMessage.info as unknown as CommonMessageInfoInternal).createdLt){
|
206
|
+
let stepInfoTemp :TranStepInfo = {
|
207
|
+
addr:upperAddress as Address,
|
208
|
+
txHash:tx.hash().toString('hex'),
|
209
|
+
gasUsed:tx.totalFees.coins,
|
210
|
+
status:await isTranSuccess(tx),
|
211
|
+
lt:tx.lt.toString(),
|
212
|
+
}
|
213
|
+
path.unshift(stepInfoTemp);
|
214
|
+
foundInOutMsgs = true;
|
215
|
+
break;
|
216
|
+
}
|
217
|
+
}
|
218
|
+
|
219
|
+
}
|
220
|
+
|
221
|
+
}
|
222
|
+
|
223
|
+
if (foundInOutMsgs){
|
224
|
+
console.log("found upper tx",tx.hash().toString('base64'));
|
225
|
+
await getUpperSteps(client,upperAddress,tx,path);
|
226
|
+
foundUpper = true;
|
227
|
+
break; // found the upper tx
|
228
|
+
}
|
229
|
+
}
|
230
|
+
await sleep(2000);
|
231
|
+
transChecked += transactions.length;
|
232
|
+
}
|
233
|
+
|
234
|
+
if(transChecked>=maxTrans){
|
235
|
+
throw new Error("can not found the upper tx!")
|
236
|
+
}
|
237
|
+
}
|
238
|
+
|
239
|
+
export async function getLowerSteps(client:TonClient,scAddr:Address,tran:Transaction, path:TranPathInfo){
|
240
|
+
console.log("Entering getLowerSteps","scAddr",scAddr);
|
241
|
+
if(tran.outMessages.keys().length == 0){
|
242
|
+
return
|
243
|
+
}
|
244
|
+
|
245
|
+
const outMessages = tran.outMessages;
|
246
|
+
for(let outMsgKey of outMessages.keys()){
|
247
|
+
let outMsg = outMessages.get(outMsgKey);
|
248
|
+
let lowerAddr = outMsg.info.dest as Address;
|
249
|
+
let msgCellHash = beginCell().store(storeMessage(outMsg)).endCell().hash().toString('hex');
|
250
|
+
let msgBodyHash = outMsg.body.hash().toString('hex');
|
251
|
+
console.log("===========================before getTranByMsgHash","outMsg",outMsg);
|
252
|
+
let lowerTx = await getTranByMsgHash(client,lowerAddr,msgCellHash,msgBodyHash,(outMsg.info as unknown as CommonMessageInfoInternal).createdLt.toString(10));
|
253
|
+
|
254
|
+
let stepInfoTemp :TranStepInfo = {
|
255
|
+
addr:lowerAddr as Address,
|
256
|
+
txHash:lowerTx.hash().toString('hex'),
|
257
|
+
gasUsed:lowerTx.totalFees.coins,
|
258
|
+
status:await isTranSuccess(lowerTx),
|
259
|
+
lt:lowerTx.lt.toString(),
|
260
|
+
}
|
261
|
+
path.push(stepInfoTemp);
|
262
|
+
await getLowerSteps(client,lowerAddr,lowerTx,path);
|
263
|
+
}
|
264
|
+
}
|
265
|
+
|
266
|
+
async function getTranPathInfoByPivotTran(client:TonClient,scAddr:Address,pivotTran:Transaction):Promise<TranPathInfo>{
|
267
|
+
console.log("Entering getTranPathInfoByPivotTran");
|
268
|
+
let allTranPathInfo: TranPathInfo = [];
|
269
|
+
let beforePivotTranPathInfo: TranPathInfo = [];
|
270
|
+
let afterPivotTranPathInfo: TranPathInfo = [];
|
271
|
+
|
272
|
+
let pivoltTranStepInfo: TranStepInfo = {
|
273
|
+
addr: scAddr,
|
274
|
+
txHash: pivotTran.hash().toString('hex'),
|
275
|
+
gasUsed: pivotTran.totalFees.coins,
|
276
|
+
status: await isTranSuccess(pivotTran),
|
277
|
+
lt:pivotTran.lt.toString(),
|
278
|
+
}
|
279
|
+
|
280
|
+
console.log("Entering get children tx");
|
281
|
+
await getLowerSteps(client,scAddr,pivotTran,afterPivotTranPathInfo); // find children tx //todo check it carefully.
|
282
|
+
console.log("End get children tx");
|
283
|
+
|
284
|
+
console.log("Entering get parent tx");
|
285
|
+
await getUpperSteps(client,scAddr,pivotTran,beforePivotTranPathInfo); // find parent tx
|
286
|
+
console.log("End get parent tx");
|
287
|
+
|
288
|
+
console.log("[pivoltTranStepInfo]====>",[pivoltTranStepInfo]);
|
289
|
+
console.log("[beforePivotTranPathInfo]====>",beforePivotTranPathInfo);
|
290
|
+
console.log("[afterPivotTranPathInfo]====>",afterPivotTranPathInfo);
|
291
|
+
let ret = allTranPathInfo.concat(beforePivotTranPathInfo,[pivoltTranStepInfo],afterPivotTranPathInfo);
|
292
|
+
console.log("========================ret = >", ret);
|
293
|
+
return ret;
|
294
|
+
}
|
295
|
+
|
296
|
+
|
297
|
+
|
298
|
+
export interface TranStepInfo {
|
299
|
+
addr: Address;
|
300
|
+
txHash: string;
|
301
|
+
gasUsed: bigint;
|
302
|
+
status: boolean;
|
303
|
+
lt:string;
|
304
|
+
}
|
305
|
+
|
306
|
+
export interface TranResult {
|
307
|
+
addr: Address;
|
308
|
+
msgInHash: string;
|
309
|
+
path:TranPathInfo;
|
310
|
+
success: boolean;
|
311
|
+
originAddr: Address;
|
312
|
+
gasUsed:bigint;
|
313
|
+
}
|
314
|
+
|
315
|
+
export type TranPathInfo = TranStepInfo[]
|
316
|
+
|
317
|
+
// example of result
|
318
|
+
/*
|
319
|
+
TranResult=> {
|
320
|
+
addr: EQCT7rMc77KcPciOlxV-dfhYWK7RisB7lEAdGze2f0-vUI30,
|
321
|
+
msgInHash: '8a2fdd9e5508f06c94ff55f0d367fdaaca82207c52ed03008680319b2424bfed',
|
322
|
+
path: [
|
323
|
+
{
|
324
|
+
addr: EQCT7rMc77KcPciOlxV-dfhYWK7RisB7lEAdGze2f0-vUI30,
|
325
|
+
txHash: '3bc0e57c110eab0a0ad1d282df89a99f3c2a3aa71fcd27d2ff897bc45febd3bb',
|
326
|
+
gasUsed: 2577471n,
|
327
|
+
status: true,
|
328
|
+
lt: '29498261000001'
|
329
|
+
},
|
330
|
+
{
|
331
|
+
addr: EQBsdoNazbwI9ybbsgufhRocWBPm7emo7cZQxojqzNuvNRcC,
|
332
|
+
txHash: '9e4f815609fa16591648b08d186cda0d81175e3a45ee17a91754f83fe013136d',
|
333
|
+
gasUsed: 4319392n,
|
334
|
+
status: true,
|
335
|
+
lt: '29498264000001'
|
336
|
+
},
|
337
|
+
{
|
338
|
+
addr: EQCT7rMc77KcPciOlxV-dfhYWK7RisB7lEAdGze2f0-vUI30,
|
339
|
+
txHash: '78b3031ffed07ec7b147f24db7a80e6fda5338d1d9fdbf5e9a845dbcf12de67f',
|
340
|
+
gasUsed: 396405n,
|
341
|
+
status: true,
|
342
|
+
lt: '29498268000001'
|
343
|
+
}
|
344
|
+
],
|
345
|
+
success: true,
|
346
|
+
originAddr: EQCT7rMc77KcPciOlxV-dfhYWK7RisB7lEAdGze2f0-vUI30,
|
347
|
+
gasUsed: 7293268n
|
348
|
+
}
|
349
|
+
*/
|
350
|
+
export async function getTranResultByMsgHash(client:TonClient,scAddr:Address,msgBodyCellHash:string,msgInHash:string):Promise<TranResult>{
|
351
|
+
|
352
|
+
let path = await getTranPathInfoByMsgHash(client,scAddr,msgBodyCellHash,msgInHash);
|
353
|
+
let success = await isTranPathSuccess(path);
|
354
|
+
return {
|
355
|
+
addr: scAddr,
|
356
|
+
msgInHash,
|
357
|
+
path,
|
358
|
+
success,
|
359
|
+
originAddr: path[0].addr,
|
360
|
+
gasUsed: await computePathGas(path)
|
361
|
+
};
|
362
|
+
}
|
363
|
+
|
364
|
+
export async function getTranResultByTxHash(client:TonClient,scAddr:Address,txHash:string, lt:string):Promise<TranResult>{
|
365
|
+
let tran = await client.getTransaction(scAddr,lt,txHash);
|
366
|
+
let path = await getTranPathInfoByPivotTran(client,scAddr,tran);
|
367
|
+
|
368
|
+
let success = await isTranPathSuccess(path);
|
369
|
+
return {
|
370
|
+
addr: scAddr,
|
371
|
+
msgInHash:tran.inMessage.body.hash().toString('base64'),
|
372
|
+
path,
|
373
|
+
success,
|
374
|
+
originAddr: path[0].addr,
|
375
|
+
gasUsed: await computePathGas(path)
|
376
|
+
};
|
377
|
+
}
|
378
|
+
|
379
|
+
export async function getTranResultByTran(client:TonClient,scAddr:Address,tran:Transaction):Promise<TranResult>{
|
380
|
+
console.log("Entering getTranResultByTran");
|
381
|
+
let path = await getTranPathInfoByPivotTran(client,scAddr,tran);
|
382
|
+
let success = await isTranPathSuccess(path);
|
383
|
+
return {
|
384
|
+
addr: scAddr,
|
385
|
+
msgInHash:tran.inMessage.body.hash().toString('base64'),
|
386
|
+
path,
|
387
|
+
success,
|
388
|
+
originAddr: path[0].addr,
|
389
|
+
gasUsed: await computePathGas(path)
|
390
|
+
};
|
391
|
+
}
|
392
|
+
|
393
|
+
|
394
|
+
export async function findMsgCellHashInTran(tran:Transaction,msgCellHash:string,msgBodyHash:string,lt:string=''):Promise<Boolean> {
|
395
|
+
let found = false;
|
396
|
+
const inMessageCell = beginCell().store(storeMessage(tran.inMessage)).endCell();
|
397
|
+
let inMessageHash = inMessageCell.hash().toString('hex');
|
398
|
+
let inMessageBodyCellHash = tran.inMessage.body.hash().toString('hex');
|
399
|
+
let internalMsg = true;
|
400
|
+
if(tran.inMessage.info.type == 'external-in'){
|
401
|
+
internalMsg = false;
|
402
|
+
}
|
403
|
+
let inMessageLt = "";
|
404
|
+
if(internalMsg){
|
405
|
+
inMessageLt = (tran.inMessage.info as unknown as CommonMessageInfoInternal).createdLt.toString(10);
|
406
|
+
}
|
407
|
+
|
408
|
+
if(!internalMsg){
|
409
|
+
if ((inMessageHash == msgCellHash || inMessageBodyCellHash == msgBodyHash)) {
|
410
|
+
found = true;
|
411
|
+
}
|
412
|
+
}else{
|
413
|
+
if ((inMessageHash == msgCellHash || inMessageBodyCellHash == msgBodyHash)) {
|
414
|
+
if (lt.length != 0 && (inMessageLt == lt)){
|
415
|
+
found = true;
|
416
|
+
}else{
|
417
|
+
if(lt.length == 0 ){
|
418
|
+
found = true;
|
419
|
+
}
|
420
|
+
}
|
421
|
+
}
|
422
|
+
}
|
423
|
+
|
424
|
+
return found;
|
425
|
+
}
|
426
|
+
|
427
|
+
export async function getTranByMsgHash(client:TonClient, scAddr:Address, msgCellHash:string,msgBodyHash:string,lt:string=''):Promise<Transaction> {
|
428
|
+
let limit = MAX_LIMIT;
|
429
|
+
let retry = 5
|
430
|
+
let maxRetry = retry;
|
431
|
+
//get from scanned db
|
432
|
+
let dbAccess = await DBAccess.getDBAccess();
|
433
|
+
let transFromDb = null;
|
434
|
+
while(maxRetry-- >0 && !transFromDb){
|
435
|
+
try{
|
436
|
+
let inDb = await dbAccess?.has(scAddr.toString());
|
437
|
+
if(!inDb){
|
438
|
+
await dbAccess.addDbByName(scAddr.toString());
|
439
|
+
await sleep(2000);
|
440
|
+
}
|
441
|
+
transFromDb = await dbAccess?.getTxByMsg(scAddr.toString(),msgCellHash,msgBodyHash,BigInt(lt));
|
442
|
+
if(transFromDb){ // found from db
|
443
|
+
return transFromDb;
|
444
|
+
}
|
445
|
+
}catch(err){
|
446
|
+
console.error("getTranByMsgHash from db err",formatError(err),"retry ",maxRetry);
|
447
|
+
}
|
448
|
+
await sleep(2000);
|
449
|
+
}
|
450
|
+
|
451
|
+
//get from rpc
|
452
|
+
maxRetry = retry;
|
453
|
+
|
454
|
+
let trans = [];
|
455
|
+
let transCount = limit;
|
456
|
+
let opts: {
|
457
|
+
limit: number;
|
458
|
+
lt?: string;
|
459
|
+
hash?: string;
|
460
|
+
to_lt?: string;
|
461
|
+
inclusive?: boolean;
|
462
|
+
archival?: boolean;
|
463
|
+
} = {
|
464
|
+
limit,
|
465
|
+
archival:true,
|
466
|
+
}
|
467
|
+
|
468
|
+
while(transCount){
|
469
|
+
let getSuccess = false
|
470
|
+
while(maxRetry-- >0 && (!getSuccess)){
|
471
|
+
try{
|
472
|
+
console.log("maxRetry = %s, getSuccess = %s, transCount = %s, scAddress = %s opts = %s",maxRetry,getSuccess,transCount,scAddr,JSON.stringify(opts,bigIntReplacer));
|
473
|
+
let ret = await client.getTransactions(scAddr,opts)
|
474
|
+
transCount = ret.length;
|
475
|
+
console.log("getTransactions success","opts",JSON.stringify(opts,bigIntReplacer),"len of getTransactions",transCount);
|
476
|
+
for(let tran of ret){
|
477
|
+
console.log("=====> tranHash = %s lt = %s",tran.hash().toString('base64'),tran.lt.toString(10));
|
478
|
+
let found = await findMsgCellHashInTran(tran,msgCellHash,msgBodyHash,lt);
|
479
|
+
if(found){
|
480
|
+
return tran;
|
481
|
+
}
|
482
|
+
}
|
483
|
+
if(ret.length){
|
484
|
+
opts.lt = ret[ret.length-1].lt.toString(10);
|
485
|
+
opts.hash = ret[ret.length-1].hash().toString('base64');
|
486
|
+
}
|
487
|
+
getSuccess = true;
|
488
|
+
maxRetry = retry;
|
489
|
+
|
490
|
+
}catch(e){
|
491
|
+
console.error("err ",formatError(e));
|
492
|
+
await sleep(2000);
|
493
|
+
}
|
494
|
+
}
|
495
|
+
if(maxRetry == 0){
|
496
|
+
throw(new Error(formatUtil("getTransactions failed after %d retry. opts is %s",retry,JSON.stringify(opts))));
|
497
|
+
}
|
498
|
+
|
499
|
+
await sleep(2000);
|
500
|
+
}
|
501
|
+
|
502
|
+
}
|
503
|
+
|
504
|
+
/*
|
505
|
+
|
506
|
+
async function monitorTransactionbyHash(client, addr, txhash, txlt) {
|
507
|
+
let allTransactions = []
|
508
|
+
const myAddress = Address.parse(addr);
|
509
|
+
let tx = await client.getTransaction(myAddress,txlt, txhash)
|
510
|
+
for (const outMessage of tx.outMessages.values()) {
|
511
|
+
const outMessageCell = beginCell().store(storeMessage(outMessage)).endCell();
|
512
|
+
const outMessageHash = outMessageCell.hash().toString('hex');
|
513
|
+
await findTransactionbyMsgHash(client, outMessage.info.dest.toString({testOnly:true}), outMessageHash, allTransactions)
|
514
|
+
}
|
515
|
+
let success = true
|
516
|
+
for(let i=0; i<allTransactions.length; i++) {
|
517
|
+
success = success && allTransactions[i].description.aborted==false && allTransactions[i].description.computePhase.exitCode==0
|
518
|
+
&& allTransactions[i].description.computePhase.seccess && allTransactions[i].description.actionPhase.seccess
|
519
|
+
}
|
520
|
+
return {success,allTransactions}
|
521
|
+
}
|
522
|
+
|
523
|
+
async function monitorTransactionbyExternalIn(client, from, msgHash){
|
524
|
+
let allTransactions = []
|
525
|
+
await waitTransactionbyExternalIn(client, from, msgHash, allTransactions);
|
526
|
+
let success = true
|
527
|
+
for(let i=0; i<allTransactions.length; i++) {
|
528
|
+
success = success && allTransactions[i].description.aborted==false && allTransactions[i].description.computePhase.exitCode==0
|
529
|
+
&& allTransactions[i].description.computePhase.seccess && allTransactions[i].description.actionPhase.seccess
|
530
|
+
}
|
531
|
+
return {success,allTransactions}
|
532
|
+
}
|
533
|
+
|
534
|
+
// wait the new sub transactions to be confirmed
|
535
|
+
async function waitTransactionbyExternalIn(client, from, msgHash, allTransactions) {
|
536
|
+
const myAddress = Address.parse(from); // address that you want to fetch transactions from
|
537
|
+
const maxRetry = 30;
|
538
|
+
let retry=0;
|
539
|
+
let to_lt = "0"
|
540
|
+
while(retry++ < maxRetry) {
|
541
|
+
console.log("call getTransactions, para:", myAddress.toString({testOnly:true}), to_lt);
|
542
|
+
const transactions = await client.getTransactions(myAddress, {
|
543
|
+
to_lt ,
|
544
|
+
limit: 10,
|
545
|
+
});
|
546
|
+
console.log("transactions length:", transactions.length)
|
547
|
+
for (let i=0; i<transactions.length; i++) {
|
548
|
+
let tx = transactions[i]
|
549
|
+
if(i == 0) {
|
550
|
+
to_lt = tx.lt.toString()
|
551
|
+
}
|
552
|
+
const transactionHash = tx.hash().toString('hex');
|
553
|
+
console.log("tx hash is:",i, tx.lt, transactionHash)
|
554
|
+
const inMessage = tx.inMessage;
|
555
|
+
let inMessageHash
|
556
|
+
// if (inMessage?.info.type === 'external-in') {
|
557
|
+
const inMessageCell = beginCell().store(storeMessage(inMessage)).endCell();
|
558
|
+
inMessageHash = inMessageCell.hash().toString('hex');
|
559
|
+
// console.log("inMessageHash", inMessageHash, msgHash);
|
560
|
+
if(inMessageHash == msgHash) {
|
561
|
+
console.log("found:", tx.lt, tx.hash().toString('hex'))
|
562
|
+
allTransactions.push(tx)
|
563
|
+
if(tx.outMessagesCount!=0){
|
564
|
+
for (const outMessage of tx.outMessages.values()) {
|
565
|
+
console.log("outMessage:", outMessage)
|
566
|
+
const outMessageCell = beginCell().store(storeMessage(outMessage)).endCell();
|
567
|
+
const outMessageHash = outMessageCell.hash().toString('hex');
|
568
|
+
console.log("outMessageHash:", outMessageHash)
|
569
|
+
await waitTransactionbyExternalIn(client, outMessage.info.dest.toString(), outMessageHash, allTransactions)
|
570
|
+
}
|
571
|
+
}
|
572
|
+
return
|
573
|
+
}
|
574
|
+
}
|
575
|
+
await sleep(1000)
|
576
|
+
}
|
577
|
+
}
|
578
|
+
|
579
|
+
// find old transactions.
|
580
|
+
async function findTransactionbyMsgHash(client:TonClient, from:Address, msgHash:string, allTransactions) {
|
581
|
+
const myAddress = from;
|
582
|
+
let maxRetry = 30;
|
583
|
+
let txOpts = {
|
584
|
+
limit: 10
|
585
|
+
}
|
586
|
+
while(maxRetry-- > 0){
|
587
|
+
console.log("call findTransactionbyMsgHash, para:", from, txOpts);
|
588
|
+
const transactions = await client.getTransactions(from, txOpts);
|
589
|
+
console.log("transactions length:", transactions.length)
|
590
|
+
for (let i=0; i<transactions.length; i++) {
|
591
|
+
let tx = transactions[i]
|
592
|
+
// console.log("tx:", tx)
|
593
|
+
const transactionHash = tx.hash().toString('hex');
|
594
|
+
console.log("tx hash is:",i, tx.lt, transactionHash)
|
595
|
+
const inMessage = tx.inMessage;
|
596
|
+
let inMessageHash
|
597
|
+
// if (inMessage?.info.type === 'external-in') {
|
598
|
+
const inMessageCell = beginCell().store(storeMessage(inMessage)).endCell();
|
599
|
+
inMessageHash = inMessageCell.hash().toString('hex');
|
600
|
+
// console.log("inMessageHash", inMessageHash, msgHash);
|
601
|
+
if(inMessageHash == msgHash) {
|
602
|
+
console.log("found:", tx.lt, tx.hash().toString('hex'))
|
603
|
+
allTransactions.push(tx)
|
604
|
+
if(tx.outMessagesCount!=0){
|
605
|
+
for (const outMessage of tx.outMessages.values()) {
|
606
|
+
console.log("outMessage:", outMessage)
|
607
|
+
const outMessageCell = beginCell().store(storeMessage(outMessage)).endCell();
|
608
|
+
const outMessageHash = outMessageCell.hash().toString('hex');
|
609
|
+
console.log("outMessageHash:", outMessageHash)
|
610
|
+
await findTransactionbyMsgHash(client, outMessage.info.dest.toString(), outMessageHash, allTransactions)
|
611
|
+
}
|
612
|
+
}
|
613
|
+
return
|
614
|
+
}
|
615
|
+
}
|
616
|
+
txOpts.hash = transactions[transactions.length - 1].hash().toString('base64')
|
617
|
+
txOpts.lt = transactions[transactions.length - 1].lt.toString()
|
618
|
+
}
|
619
|
+
}
|
620
|
+
|
621
|
+
*/
|
package/tsconfig.json
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
{
|
2
|
+
"compilerOptions": {
|
3
|
+
"target": "ES2020",
|
4
|
+
"outDir": "../wan-ton-sdk/dist",
|
5
|
+
"module": "commonjs",
|
6
|
+
"rootDir": "./",
|
7
|
+
"declaration": true,
|
8
|
+
"esModuleInterop": true,
|
9
|
+
"resolveJsonModule": true,
|
10
|
+
"forceConsistentCasingInFileNames": true,
|
11
|
+
"strict": false,
|
12
|
+
"skipLibCheck": true,
|
13
|
+
"allowJs": true,
|
14
|
+
"types": ["jest","node"]
|
15
|
+
},
|
16
|
+
"include": ["./**/*"],
|
17
|
+
"exclude": [
|
18
|
+
"node_modules", "./*.spec.ts"]
|
19
|
+
}
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":{"funcVersion":"0.4.4","funcFiftLibCommitHash":"ffe0a1c63073dda0a0dd0e14f199b83fe5b05e66","funcFiftLibCommitDate":"2024-03-27 12:57:15 +0300"},"hashHex":"cc86dd282df9a8848afa3bfaab9b7b7463fc01a9306fe80ed0b34517429a45e2","codeBase64":"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"}
|