Conversation
| if (typeof entry === 'object' && entry != null) { | ||
| const obj = entry as any | ||
| if (obj['@type'] === 'tvm.stackEntryNumber') { | ||
| return { type: 'num', value: obj.number?.value ?? obj.number } |
There was a problem hiding this comment.
Wrong field name in stack entry number parsing
Medium Severity
In parseStackEntry, the tvm.stackEntryNumber branch reads obj.number?.value but the Toncenter JSONRPC format nests the actual number as obj.number?.number (the inner object is {"@type": "tvm.numberDecimal", "number": "42"}). When this branch is hit, the fallback ?? obj.number returns the entire nested object, and BigInt(object) in parseStackNumber will throw a TypeError. The field access .value needs to be .number to correctly extract the numeric string.
|
|
||
| wallet: WalletContractV5R1 | ||
| archiveTransactions: boolean | ||
| jettonWalletToTokenId: Map<string, string> = new Map() |
There was a problem hiding this comment.
Dead archiveTransactions field after Orbs removal
Low Severity
The archiveTransactions property is declared, initialized in the constructor, and assigned false in queryTransactions, but is never read anywhere. It was previously used by the now-removed Orbs client logic. This is dead code left over from the migration to dRPC.
Additional Locations (2)
Orbs servers would return valid but incorrect data when called too often. This was most evident in the balance query when the endpoints would return an account as uninitialized which wipes out the balance. This leads to balances swinging back and forth. Reducing the query frequency and staggering the load between servers didn't resolve the issue. dRPC has both free and paid teirs and the new implementation will use the free and fallback to paid if necessary.
Add jetton wallet address resolution via dRPC runGetMethod on Jetton Master contracts, jetton balance queries via get_wallet_data, and jetton transaction detection from parse_tx output (jetton_notification and jetton_request op codes). Support jetton spending with TEP-74 transfer message construction and fee estimation. Transaction queries still rely solely on TonCenter TonClient but now produce EdgeTransactions for both native TON and jetton transfers. Include USDT as a builtin token.
9741c30 to
2f6ab6c
Compare
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
There are 3 total unresolved issues (including 2 from previous reviews).
Bugbot Autofix prepared a fix for the issue found in the latest run.
- ✅ Fixed: signTx fails for uninitialized wallets querying seqno
- Updated signTx to bypass the seqno get-method call and use seqno 0 when contractState is uninitialized, preserving first-send behavior for undeployed wallets.
Or push these changes by commenting:
@cursor push dda9df4baa
Preview (dda9df4baa)
diff --git a/src/ton/TonEngine.ts b/src/ton/TonEngine.ts
--- a/src/ton/TonEngine.ts
+++ b/src/ton/TonEngine.ts
@@ -603,19 +603,24 @@
)[0].asSlice()
const transferMessage = loadMessageRelaxed(messageSlice)
- const addr = this.wallet.address.toRawString()
- const seqnoRaw = await this.tools.fetchDrpc('/runGetMethod', {
- address: addr,
- method: 'seqno',
- stack: []
- })
- const { result: seqnoResult } = asDrpcRunGetMethod(seqnoRaw)
- if (seqnoResult.exit_code !== 0) {
- throw new Error(
- `seqno query failed with exit_code ${seqnoResult.exit_code}`
- )
+ let seqno: number
+ if (this.otherData.contractState === 'uninitialized') {
+ seqno = 0
+ } else {
+ const addr = this.wallet.address.toRawString()
+ const seqnoRaw = await this.tools.fetchDrpc('/runGetMethod', {
+ address: addr,
+ method: 'seqno',
+ stack: []
+ })
+ const { result: seqnoResult } = asDrpcRunGetMethod(seqnoRaw)
+ if (seqnoResult.exit_code !== 0) {
+ throw new Error(
+ `seqno query failed with exit_code ${seqnoResult.exit_code}`
+ )
+ }
+ seqno = parseSeqnoFromStack(seqnoResult.stack)
}
- const seqno = parseSeqnoFromStack(seqnoResult.stack)
const transferArgs: Parameters<WalletContractV5R1['createTransfer']>[0] = {
sendMode: SendMode.IGNORE_ERRORS + SendMode.PAY_GAS_SEPARATELY,This Bugbot Autofix run was free. To enable autofix for future PRs, go to the Cursor dashboard.
Reviewed by Cursor Bugbot for commit 2f6ab6c. Configure here.
| `seqno query failed with exit_code ${seqnoResult.exit_code}` | ||
| ) | ||
| } | ||
| const seqno = parseSeqnoFromStack(seqnoResult.stack) |
There was a problem hiding this comment.
signTx fails for uninitialized wallets querying seqno
High Severity
The signTx method calls runGetMethod for seqno directly via the API and throws if exit_code !== 0. For uninitialized wallets (first-time sends), the contract doesn't exist on-chain, so this call returns a non-zero exit code, causing signTx to throw. The previous code used contract.getSeqno() from the @ton/ton SDK, which internally checks contract state and returns 0 for undeployed contracts. This blocks first-time transactions from new wallets entirely — despite makeSpend and broadcastTx both having explicit handling for the uninitialized state.
Reviewed by Cursor Bugbot for commit 2f6ab6c. Configure here.



CHANGELOG
Does this branch warrant an entry to the CHANGELOG?
Dependencies
noneDescription
noneNote
High Risk
High risk because it changes TON transaction construction/fee estimation/broadcast flows and adds Jetton token balance + transfer handling, which can directly impact funds movement and history accuracy.
Overview
Adds TON Jetton (token) support by resolving per-token Jetton wallet addresses, polling Jetton balances, and parsing Jetton transfer notifications/requests into token
EdgeTransactions (including memo support and parent-fee attribution).Replaces prior Orbs-based network calls with a new dRPC HTTP layer (
tonDrpc) used for address info, fee estimation, seqno lookup, and broadcasting (plus txid discovery for first-send wallets), and updates TON plugin config/init options to include dRPC settings and a builtin TON USDT token.Reviewed by Cursor Bugbot for commit 2f6ab6c. Bugbot is set up for automated code reviews on this repo. Configure here.