Skip to content

Commit ad330dc

Browse files
welldan97mkaczanowski
authored andcommitted
Improve TON Staker
1. Retry if signing request hits rate limit 2. Track both external and internal messages via getTxStatus
1 parent 7365b51 commit ad330dc

File tree

3 files changed

+63
-3
lines changed

3 files changed

+63
-3
lines changed

package-lock.json

+11
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/ton/package.json

+1
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
"@chorus-one/utils": "^1.0.0",
3737
"@noble/curves": "^1.4.0",
3838
"@ton/ton": "^13.11.2",
39+
"axios": "^1.7.2",
3940
"tonweb-mnemonic": "^1.0.1"
4041
}
4142
}

packages/ton/src/TonBaseStaker.ts

+51-3
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import axios, { AxiosAdapter, AxiosError, AxiosResponse, InternalAxiosRequestConfig } from 'axios'
12
import type { Signer } from '@chorus-one/signer'
23
import type {
34
TonNetworkConfig,
@@ -17,7 +18,9 @@ import {
1718
MessageRelaxed,
1819
SendMode,
1920
Address,
20-
TransactionDescriptionGeneric
21+
TransactionDescriptionGeneric,
22+
beginCell,
23+
storeMessage
2124
} from '@ton/ton'
2225
import { createWalletTransferV4, externalMessage, sign } from './tx'
2326
import * as tonMnemonic from 'tonweb-mnemonic'
@@ -133,8 +136,45 @@ export class TonBaseStaker {
133136
* @returns A promise which resolves once the TonStaker instance has been initialized.
134137
*/
135138
async init (): Promise<void> {
139+
const rateLimitRetryAdapter: AxiosAdapter = async (config: InternalAxiosRequestConfig): Promise<AxiosResponse> => {
140+
const maxRetries = 3
141+
const retryDelay = 1000
142+
143+
let retries = 0
144+
145+
const defaultAdapter = axios.getAdapter(axios.defaults.adapter)
146+
if (!defaultAdapter) {
147+
throw new Error('Axios default adapter is not available')
148+
}
149+
150+
while (retries <= maxRetries) {
151+
try {
152+
// Send the request using the default adapter
153+
return await defaultAdapter(config)
154+
} catch (err) {
155+
const error = err as AxiosError
156+
157+
const status = error.response?.status
158+
159+
// If rate limit hit (429), wait and retry
160+
if (status === 429 && retries < maxRetries) {
161+
retries += 1
162+
console.log(`Rate limit hit, try ${retries}/${maxRetries}`)
163+
164+
await new Promise((resolve) => setTimeout(resolve, retryDelay))
165+
} else {
166+
throw error
167+
}
168+
}
169+
}
170+
171+
// Should never reach this point
172+
throw new Error(`Rate limit exceeded after ${maxRetries} retries.`)
173+
}
174+
136175
this.client = new TonClient({
137-
endpoint: this.networkConfig.rpcUrl
176+
endpoint: this.networkConfig.rpcUrl,
177+
httpAdapter: rateLimitRetryAdapter
138178
})
139179
}
140180

@@ -381,8 +421,16 @@ export class TonBaseStaker {
381421
const { address, txHash, limit } = params
382422

383423
const transactions = await client.getTransactions(Address.parse(address), { limit: limit ?? 10 })
384-
const transaction = transactions.find((tx) => tx.hash().toString('hex') === txHash)
424+
const transaction = transactions.find((tx) => {
425+
// Check tx hash
426+
if (tx.hash().toString('hex') === txHash) return true
427+
428+
// Check inMessage tx hash(that is the one we get from broadcast method)
429+
if (tx.inMessage && beginCell().store(storeMessage(tx.inMessage)).endCell().hash().toString('hex') === txHash)
430+
return true
385431

432+
return false
433+
})
386434
if (transaction === undefined) {
387435
return { status: 'unknown', receipt: null }
388436
}

0 commit comments

Comments
 (0)