From 9e379a95004e098d715756908ac00503ab0b0be7 Mon Sep 17 00:00:00 2001 From: pavel levchenko Date: Mon, 24 Aug 2026 13:13:30 +0300 Subject: [PATCH 1/5] improve cross asset price calculation --- .idea/opentonapi.iml | 4 + .idea/vcs.xml | 6 + .idea/workspace.xml | 431 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 441 insertions(+) create mode 100644 .idea/opentonapi.iml create mode 100644 .idea/vcs.xml create mode 100644 .idea/workspace.xml diff --git a/.idea/opentonapi.iml b/.idea/opentonapi.iml new file mode 100644 index 000000000..7ee078df7 --- /dev/null +++ b/.idea/opentonapi.iml @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 000000000..94a25f7f4 --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/.idea/workspace.xml b/.idea/workspace.xml new file mode 100644 index 000000000..c01ec8b77 --- /dev/null +++ b/.idea/workspace.xml @@ -0,0 +1,431 @@ + + + + + + + + + + + + + + + { + "history": [ + { + "state": "OPEN" + } + ], + "lastFilter": { + "state": "OPEN" + } +} + { + "prStates": [ + { + "id": { + "id": "PR_kwDOI2kNKs7CmxI_", + "number": 798 + }, + "lastSeen": 1770705940046 + } + ] +} + { + "selectedUrlAndAccountId": { + "url": "git@github.com:tonkeeper/opentonapi.git", + "accountId": "6cd316c0-d731-43e0-a270-e98d6d6ef95b" + } +} + + + + + + + + + + + + + + + + + + + { + "associatedIndex": 2 +} + + + + ton in github.com/tonkeeper/opentonapi/pkg/rates.executor": "Debug", + "Go Test.TestConverter_DecodeTupleMatrix in github.com/tonkeeper/opentonapi/pkg/api.executor": "Run", + "Go Test.TestConverter_DecodeTupleMatrix/tuple_0x0 in github.com/tonkeeper/opentonapi/pkg/api.executor": "Run", + "Go Test.TestConverter_DecodeTupleMatrix/tuple_0x1 in github.com/tonkeeper/opentonapi/pkg/api.executor": "Debug", + "Go Test.TestFindActions in github.com/tonkeeper/opentonapi/pkg/bath.executor": "Run", + "Go Test.TestFindActions/bidask_ton_usdt_swap in github.com/tonkeeper/opentonapi/pkg/bath.executor": "Run", + "Go Test.TestFindActions/bidask_usdt-usde_swap in github.com/tonkeeper/opentonapi/pkg/bath.executor": "Run", + "Go Test.TestFindActions/bidask_usdt_ton_swap in github.com/tonkeeper/opentonapi/pkg/bath.executor": "Run", + "Go Test.TestFindActions/bidask_usdt_usde_swap in github.com/tonkeeper/opentonapi/pkg/bath.executor": "Run", + "Go Test.TestFindActions/bidask_v2_usdt_ton_swap in github.com/tonkeeper/opentonapi/pkg/bath.executor": "Run", + "Go Test.TestFindActions/dedust_swap_with_omniston in github.com/tonkeeper/opentonapi/pkg/bath.executor": "Run", + "Go Test.TestFindActions/dedust_swap_with_omniston_new in github.com/tonkeeper/opentonapi/pkg/bath.executor": "Debug", + "Go Test.TestFindActions/dedust_swap_with_omniston_old in github.com/tonkeeper/opentonapi/pkg/bath.executor": "Run", + "Go Test.TestFindActions/deposit_both_ton_bmTON_liquidity_bidask in github.com/tonkeeper/opentonapi/pkg/bath.executor": "Run", + "Go Test.TestFindActions/deposit_both_ton_bmTON_liquidity_bidask_with_refund in github.com/tonkeeper/opentonapi/pkg/bath.executor": "Run", + "Go Test.TestFindActions/deposit_hydra_+_usdt_liquidity_bidask in github.com/tonkeeper/opentonapi/pkg/bath.executor": "Run", + "Go Test.TestFindActions/deposit_storm_liquidity_stonfi in github.com/tonkeeper/opentonapi/pkg/bath.executor": "Run", + "Go Test.TestFindActions/deposit_ton_+_storm_liquidity_stonfi in github.com/tonkeeper/opentonapi/pkg/bath.executor": "Run", + "Go Test.TestFindActions/deposit_ton_+_storm_liquidity_stonfi#01 in github.com/tonkeeper/opentonapi/pkg/bath.executor": "Debug", + "Go Test.TestFindActions/deposit_ton_+_tonio_liquidity_dedust in github.com/tonkeeper/opentonapi/pkg/bath.executor": "Run", + "Go Test.TestFindActions/deposit_ton_+_usdt_liquidity_bidask in github.com/tonkeeper/opentonapi/pkg/bath.executor": "Run", + "Go Test.TestFindActions/deposit_ton_+_usdt_liquidity_dedust in github.com/tonkeeper/opentonapi/pkg/bath.executor": "Run", + "Go Test.TestFindActions/deposit_ton_+_usdt_liquidity_mooncx in github.com/tonkeeper/opentonapi/pkg/bath.executor": "Run", + "Go Test.TestFindActions/deposit_ton_+_usdt_liquidity_tonco in github.com/tonkeeper/opentonapi/pkg/bath.executor": "Run", + "Go Test.TestFindActions/deposit_ton_liquidity_tonco in github.com/tonkeeper/opentonapi/pkg/bath.executor": "Run", + "Go Test.TestFindActions/deposit_tonio_+_ton_liquidity_dedust in github.com/tonkeeper/opentonapi/pkg/bath.executor": "Run", + "Go Test.TestFindActions/deposit_usdt_+_dust_liquidity_dedust in github.com/tonkeeper/opentonapi/pkg/bath.executor": "Run", + "Go Test.TestFindActions/deposit_usdt_+_ton_liquidity_dedust in github.com/tonkeeper/opentonapi/pkg/bath.executor": "Run", + "Go Test.TestFindActions/deposit_usdt_earn in github.com/tonkeeper/opentonapi/pkg/bath.executor": "Run", + "Go Test.TestFindActions/deposit_usdt_earn_affluent in github.com/tonkeeper/opentonapi/pkg/bath.executor": "Run", + "Go Test.TestFindActions/deposit_usdt_earn_affluent_with_oracles in github.com/tonkeeper/opentonapi/pkg/bath.executor": "Run", + "Go Test.TestFindActions/deposit_usdt_earn_affluent_with_single_oracle in github.com/tonkeeper/opentonapi/pkg/bath.executor": "Run", + "Go Test.TestFindActions/deposit_usdt_liquidity_bidask in github.com/tonkeeper/opentonapi/pkg/bath.executor": "Run", + "Go Test.TestFindActions/dumbahh_test in github.com/tonkeeper/opentonapi/pkg/bath.executor": "Run", + "Go Test.TestFindActions/ethena_deposit_stake_request in github.com/tonkeeper/opentonapi/pkg/bath.executor": "Run", + "Go Test.TestFindActions/ethena_withdraw_stake_request in github.com/tonkeeper/opentonapi/pkg/bath.executor": "Debug", + "Go Test.TestFindActions/failed_stonfi_swap in github.com/tonkeeper/opentonapi/pkg/bath.executor": "Debug", + "Go Test.TestFindActions/flawed_jetton_transfer in github.com/tonkeeper/opentonapi/pkg/bath.executor": "Run", + "Go Test.TestFindActions/flawed_jetton_transfer-two-out in github.com/tonkeeper/opentonapi/pkg/bath.executor": "Run", + "Go Test.TestFindActions/flawed_jetton_transfer_2 in github.com/tonkeeper/opentonapi/pkg/bath.executor": "Run", + "Go Test.TestFindActions/instant_withdraw_request_usdt_affluent_with_multiple_oracles in github.com/tonkeeper/opentonapi/pkg/bath.executor": "Run", + "Go Test.TestFindActions/instant_withdraw_request_usdt_affluent_with_single_oracle in github.com/tonkeeper/opentonapi/pkg/bath.executor": "Run", + "Go Test.TestFindActions/instant_withdraw_usdt_affluent in github.com/tonkeeper/opentonapi/pkg/bath.executor": "Run", + "Go Test.TestFindActions/liquidity_deposit_stonfi_request in github.com/tonkeeper/opentonapi/pkg/bath.executor": "Run", + "Go Test.TestFindActions/mooncx_deposit_ton_usdt_liquidity in github.com/tonkeeper/opentonapi/pkg/bath.executor": "Run", + "Go Test.TestFindActions/mooncx_simple_swap in github.com/tonkeeper/opentonapi/pkg/bath.executor": "Run", + "Go Test.TestFindActions/mooncx_ton-usdt_swap in github.com/tonkeeper/opentonapi/pkg/bath.executor": "Run", + "Go Test.TestFindActions/new_withdraw_stake_request in github.com/tonkeeper/opentonapi/pkg/bath.executor": "Run", + "Go Test.TestFindActions/nft_getgems_purchase_v4 in github.com/tonkeeper/opentonapi/pkg/bath.executor": "Run", + "Go Test.TestFindActions/nft_purchase in github.com/tonkeeper/opentonapi/pkg/bath.executor": "Run", + "Go Test.TestFindActions/nft_purchase_2 in github.com/tonkeeper/opentonapi/pkg/bath.executor": "Run", + "Go Test.TestFindActions/nft_purchase_at_Disintar_Marketplace in github.com/tonkeeper/opentonapi/pkg/bath.executor": "Run", + "Go Test.TestFindActions/nft_transfer in github.com/tonkeeper/opentonapi/pkg/bath.executor": "Run", + "Go Test.TestFindActions/not-to-merge-simplest-straw in github.com/tonkeeper/opentonapi/pkg/bath.executor": "Run", + "Go Test.TestFindActions/not_merge_big_bubble_in_the_middle in github.com/tonkeeper/opentonapi/pkg/bath.executor": "Run", + "Go Test.TestFindActions/not_merge_bubble_in_the_beginning in github.com/tonkeeper/opentonapi/pkg/bath.executor": "Run", + "Go Test.TestFindActions/not_merge_bubble_in_the_beginning_with_tail in github.com/tonkeeper/opentonapi/pkg/bath.executor": "Run", + "Go Test.TestFindActions/not_merge_bubble_in_the_end in github.com/tonkeeper/opentonapi/pkg/bath.executor": "Run", + "Go Test.TestFindActions/not_merge_bubble_in_the_end_with_tail in github.com/tonkeeper/opentonapi/pkg/bath.executor": "Run", + "Go Test.TestFindActions/not_merge_bubble_in_the_middle in github.com/tonkeeper/opentonapi/pkg/bath.executor": "Run", + "Go Test.TestFindActions/not_merge_bubble_in_the_middle_with_tail in github.com/tonkeeper/opentonapi/pkg/bath.executor": "Run", + "Go Test.TestFindActions/not_merge_bubble_in_the_very_beginning in github.com/tonkeeper/opentonapi/pkg/bath.executor": "Run", + "Go Test.TestFindActions/not_merge_simplest_straw in github.com/tonkeeper/opentonapi/pkg/bath.executor": "Run", + "Go Test.TestFindActions/old_withdraw_stake_request in github.com/tonkeeper/opentonapi/pkg/bath.executor": "Run", + "Go Test.TestFindActions/provide_ton_+_storm_liquidity_stonfi in github.com/tonkeeper/opentonapi/pkg/bath.executor": "Run", + "Go Test.TestFindActions/simple_transfer in github.com/tonkeeper/opentonapi/pkg/bath.executor": "Run", + "Go Test.TestFindActions/stonfi_partial_cross-swap in github.com/tonkeeper/opentonapi/pkg/bath.executor": "Run", + "Go Test.TestFindActions/stonfi_usdt-ton_exchange_with_tonkeeper_battery in github.com/tonkeeper/opentonapi/pkg/bath.executor": "Run", + "Go Test.TestFindActions/stonfi_v2_multihop_swap in github.com/tonkeeper/opentonapi/pkg/bath.executor": "Run", + "Go Test.TestFindActions/stonfi_v2_multihop_swap_with_crossdex in github.com/tonkeeper/opentonapi/pkg/bath.executor": "Debug", + "Go Test.TestFindActions/stonfi_v2_swap_simple in github.com/tonkeeper/opentonapi/pkg/bath.executor": "Run", + "Go Test.TestFindActions/stonfi_v2_swap_with_ref in github.com/tonkeeper/opentonapi/pkg/bath.executor": "Debug", + "Go Test.TestFindActions/stonfi_v2_test in github.com/tonkeeper/opentonapi/pkg/bath.executor": "Run", + "Go Test.TestFindActions/subscription_V2_+_wallet_V4_cancel_by_expire in github.com/tonkeeper/opentonapi/pkg/bath.executor": "Run", + "Go Test.TestFindActions/subscription_V2_+_wallet_V4_destroy_by_beneficiary in github.com/tonkeeper/opentonapi/pkg/bath.executor": "Run", + "Go Test.TestFindActions/subscription_V2_+_wallet_W5_deploy_with_payment in github.com/tonkeeper/opentonapi/pkg/bath.executor": "Run", + "Go Test.TestFindActions/tonco_failed_ton_swap in github.com/tonkeeper/opentonapi/pkg/bath.executor": "Run", + "Go Test.TestFindActions/tonco_storm-usdt_swap in github.com/tonkeeper/opentonapi/pkg/bath.executor": "Run", + "Go Test.TestFindActions/tonco_swap_to_another_account in github.com/tonkeeper/opentonapi/pkg/bath.executor": "Run", + "Go Test.TestFindActions/tonco_ton-usdt_swap in github.com/tonkeeper/opentonapi/pkg/bath.executor": "Run", + "Go Test.TestFindActions/tonco_usdt-ton_swap in github.com/tonkeeper/opentonapi/pkg/bath.executor": "Run", + "Go Test.TestFindActions/withdraw_request_usdt_affluent in github.com/tonkeeper/opentonapi/pkg/bath.executor": "Debug", + "Go Test.TestFindActions/withdraw_request_usdt_affluent_with_multiple_oracles in github.com/tonkeeper/opentonapi/pkg/bath.executor": "Run", + "Go Test.TestFindActions/withdraw_request_usdt_affluent_with_oracles in github.com/tonkeeper/opentonapi/pkg/bath.executor": "Run", + "Go Test.TestFindActions/withdraw_request_usdt_affluent_with_single_oracle in github.com/tonkeeper/opentonapi/pkg/bath.executor": "Run", + "Go Test.TestFindActions/withdraw_usdt_affluent in github.com/tonkeeper/opentonapi/pkg/bath.executor": "Run", + "Go Test.TestGetInvariantForStableSwap in github.com/tonkeeper/opentonapi/pkg/rates.executor": "Run", + "Go Test.TestSortReserveAndAssetPairs in github.com/tonkeeper/opentonapi/pkg/rates.executor": "Run", + "Go Test.go test github.com/tonkeeper/opentonapi/pkg/bath.executor": "Run", + "Go Test.go test github.com/tonkeeper/opentonapi/pkg/rates.executor": "Debug", + "Makefile Target.gen.executor": "Run", + "ModuleVcsDetector.initialDetectionPerformed": "true", + "RunOnceActivity.GoLinterPluginOnboarding": "true", + "RunOnceActivity.GoLinterPluginStorageMigration": "true", + "RunOnceActivity.ShowReadmeOnStart": "true", + "RunOnceActivity.TerminalTabsStorage.copyFrom.TerminalArrangementManager.252": "true", + "RunOnceActivity.git.unshallow": "true", + "RunOnceActivity.go.formatter.settings.were.checked": "true", + "RunOnceActivity.go.migrated.go.modules.settings": "true", + "RunOnceActivity.go.modules.go.list.on.any.changes.was.set": "true", + "git-widget-placeholder": "update-modules", + "go.import.settings.migrated": "true", + "go.sdk.automatically.set": "true", + "last_opened_file_path": "/Users/pavel/tonkeeper/opentonapi/pkg/bath/testdata", + "node.js.detected.package.eslint": "true", + "node.js.selected.package.eslint": "(autodetect)", + "nodejs_package_manager_path": "npm", + "settings.editor.selected.configurable": "editor.preferences.fonts.default", + "two.files.diff.last.used.file": "/Users/pavel/tonkeeper/opentonapi/pkg/bath/testdata/stonfi-v2-swap-ref.json" + } +}]]> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1754829364430 + + + + + + + + + + true + + + + + + file://$USER_HOME$/go/pkg/mod/github.com/tonkeeper/tongo@v1.16.17/wallet/messages.go + 163 + + + file://$USER_HOME$/go/pkg/mod/github.com/tonkeeper/tongo@v1.16.17/wallet/messages.go + 171 + + + file://$PROJECT_DIR$/pkg/rates/math_test.go + 176 + + + file://$PROJECT_DIR$/pkg/api/emulation.go + 427 + + + file://$PROJECT_DIR$/pkg/bath/jettons.go + 194 + + + file://$PROJECT_DIR$/pkg/rates/sources.go + 102 + + + file://$USER_HOME$/go/pkg/mod/github.com/tonkeeper/tongo@v1.16.41/tlb/tuple.go + 8 + + + file://$PROJECT_DIR$/pkg/bath/dedust.go + 181 + + + file://$PROJECT_DIR$/pkg/bath/auctions.go + 53 + + + file://$PROJECT_DIR$/pkg/api/event_converters.go + 616 + + + file://$PROJECT_DIR$/pkg/bath/jettons.go + 267 + + + file://$PROJECT_DIR$/pkg/bath/stonfi.go + 137 + + + file://$PROJECT_DIR$/pkg/bath/stonfi.go + 205 + + + file://$PROJECT_DIR$/pkg/bath/stonfi.go + 175 + + + file://$USER_HOME$/go/pkg/mod/github.com/tonkeeper/tongo@v1.22.12/abi-tolk/abiGenerated/xtr/xtr-master_marshal.go + 42 + + + file://$PROJECT_DIR$/pkg/bath/payments.go + 270 + + + file://$PROJECT_DIR$/pkg/bath/payments.go + 200 + + + file://$PROJECT_DIR$/pkg/bath/payments.go + 228 + + + + + + + + + + + + \ No newline at end of file From e87851874b059fa3f877d50461e9d495ff8b7dfc Mon Sep 17 00:00:00 2001 From: pavel levchenko Date: Mon, 24 Aug 2026 14:03:16 +0300 Subject: [PATCH 2/5] fix for dev --- pkg/rates/calculator.go | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/pkg/rates/calculator.go b/pkg/rates/calculator.go index 564ebc418..7e9aa3d6b 100644 --- a/pkg/rates/calculator.go +++ b/pkg/rates/calculator.go @@ -94,12 +94,13 @@ func (c *calculator) refresh() { weekRates, err := c.source.GetRates(weekAgo) if err != nil { slog.Error("[refresh-rates] error getting week rates", slog.String("err", err.Error())) - return + // we dont return an error to test lack of data on dev + weekRates = map[string]float64{} } monthRates, err := c.source.GetRates(monthAgo) if err != nil { slog.Error("[refresh-rates] error getting month rates", slog.String("err", err.Error())) - return + monthRates = map[string]float64{} } c.mu.Lock() From 4348123421536e655c4a45d790aaa9c974b25c3d Mon Sep 17 00:00:00 2001 From: pavel levchenko Date: Mon, 24 Aug 2026 14:12:49 +0300 Subject: [PATCH 3/5] remove temp for dev --- pkg/rates/calculator.go | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/pkg/rates/calculator.go b/pkg/rates/calculator.go index 7e9aa3d6b..564ebc418 100644 --- a/pkg/rates/calculator.go +++ b/pkg/rates/calculator.go @@ -94,13 +94,12 @@ func (c *calculator) refresh() { weekRates, err := c.source.GetRates(weekAgo) if err != nil { slog.Error("[refresh-rates] error getting week rates", slog.String("err", err.Error())) - // we dont return an error to test lack of data on dev - weekRates = map[string]float64{} + return } monthRates, err := c.source.GetRates(monthAgo) if err != nil { slog.Error("[refresh-rates] error getting month rates", slog.String("err", err.Error())) - monthRates = map[string]float64{} + return } c.mu.Lock() From cb27804f6497d412d8c9a72f97f7eaeafe0be998 Mon Sep 17 00:00:00 2001 From: pavel levchenko Date: Mon, 24 Aug 2026 18:24:28 +0300 Subject: [PATCH 4/5] reverted complex logic --- pkg/api/handler.go | 2 +- pkg/api/interfaces.go | 6 -- pkg/api/jetton_converters.go | 4 +- pkg/api/rates_handlers.go | 67 ++-------------------- pkg/api/rates_handlers_test.go | 100 --------------------------------- pkg/rates/calculator.go | 42 ++------------ pkg/rates/calculator_test.go | 34 +++-------- 7 files changed, 21 insertions(+), 234 deletions(-) delete mode 100644 pkg/api/rates_handlers_test.go diff --git a/pkg/api/handler.go b/pkg/api/handler.go index 08198c527..39bff9427 100644 --- a/pkg/api/handler.go +++ b/pkg/api/handler.go @@ -48,7 +48,7 @@ type Handler struct { limits Limits spamFilter SpamFilter - ratesSource conversionRatesSource + ratesSource ratesSource score scoreSource metaCache metadataCache tonConnect *tonconnect.Server diff --git a/pkg/api/interfaces.go b/pkg/api/interfaces.go index 338579dfe..71e6ab35d 100644 --- a/pkg/api/interfaces.go +++ b/pkg/api/interfaces.go @@ -202,12 +202,6 @@ type ratesSource interface { GetMarketsTonPrice() ([]rates.Market, error) } -type conversionRatesSource interface { - ratesSource - GetTodayRatesWithTimestamps() (map[string]float64, map[string]int64) - GetMinuteAgoRatesWithTimestamps() (map[string]float64, map[string]int64) -} - type scoreSource interface { GetJettonScore(masterID ton.AccountID) (int32, error) } diff --git a/pkg/api/jetton_converters.go b/pkg/api/jetton_converters.go index 4e9842ba8..73cfc3a39 100644 --- a/pkg/api/jetton_converters.go +++ b/pkg/api/jetton_converters.go @@ -146,7 +146,7 @@ func (h *Handler) convertJettonOperation(ctx context.Context, op core.JettonOper func (h *Handler) convertJettonBalance(ctx context.Context, wallet core.JettonWallet, currencies []string, scaledUiLt *int64, assetInfo *oas.JettonAssetInfo) (oas.JettonBalance, error) { // the latest scaled ui parameters for jetton master if scaledUiLt == nil - _, yesterdayRates, weekRates, monthRates, _ := h.getRates() + todayRates, yesterdayRates, weekRates, monthRates, _ := h.getRates() for idx, currency := range currencies { if jetton, err := tongo.ParseAddress(currency); err == nil { currency = jetton.ID.ToRaw() @@ -173,7 +173,7 @@ func (h *Handler) convertJettonBalance(ctx context.Context, wallet core.JettonWa } rates := make(map[string]oas.TokenRates) for _, currency := range currencies { - rates, err = h.convertRates(ctx, rates, wallet.JettonAddress.ToRaw(), currency, yesterdayRates, weekRates, monthRates) + rates, err = h.convertRates(ctx, rates, wallet.JettonAddress.ToRaw(), currency, todayRates, yesterdayRates, weekRates, monthRates) if err != nil { rates = make(map[string]oas.TokenRates) continue diff --git a/pkg/api/rates_handlers.go b/pkg/api/rates_handlers.go index 05caed9a6..0395c4595 100644 --- a/pkg/api/rates_handlers.go +++ b/pkg/api/rates_handlers.go @@ -115,7 +115,7 @@ func (h *Handler) GetRates(ctx context.Context, params oas.GetRatesParams) (*oas } } - _, yesterdayRates, weekRates, monthRates, err := h.getRates() + todayRates, yesterdayRates, weekRates, monthRates, err := h.getRates() if err != nil { return nil, toError(http.StatusInternalServerError, err) } @@ -123,7 +123,7 @@ func (h *Handler) GetRates(ctx context.Context, params oas.GetRatesParams) (*oas rates := make(map[string]oas.TokenRates) for _, token := range tokens { for _, currency := range currencies { - rates, err = h.convertRates(ctx, rates, token, currency, yesterdayRates, weekRates, monthRates) + rates, err = h.convertRates(ctx, rates, token, currency, todayRates, yesterdayRates, weekRates, monthRates) if err != nil { return nil, err } @@ -176,63 +176,11 @@ func (h *Handler) getRates() (todayRates, yesterdayRates, weekRates, monthRates return results[0], results[1], results[2], results[3], nil } -const maxGenerationSkewSeconds = 180 - -func alignConversionPrices( - token, currency string, - todayRates map[string]float64, todayTs map[string]int64, - prevRates map[string]float64, prevTs map[string]int64, -) (tokenPrice, currencyPrice float64) { - tokenPrice = todayRates[token] - currencyPrice = todayRates[currency] - - tokenTs, currencyTs := todayTs[token], todayTs[currency] - if tokenTs == 0 || currencyTs == 0 || tokenTs == currencyTs { - return tokenPrice, currencyPrice - } - gap := tokenTs - currencyTs - if gap < 0 { - gap = -gap - } - if gap > maxGenerationSkewSeconds { - return tokenPrice, currencyPrice - } - - if tokenTs < currencyTs { - // the token price is a cycle behind: take the currency price from the previous - // snapshot when its generation matches the token's better than the current one - if prev, ok := prevRates[currency]; ok && prev != 0 && closerTo(prevTs[currency], tokenTs, currencyTs) { - currencyPrice = prev - } - } else { - if prev, ok := prevRates[token]; ok && prev != 0 && closerTo(prevTs[token], currencyTs, tokenTs) { - tokenPrice = prev - } - } - return tokenPrice, currencyPrice -} - -// closerTo reports whether candidate is strictly closer to target than current is -func closerTo(candidate, target, current int64) bool { - if candidate == 0 { - return false - } - candidateDist := candidate - target - if candidateDist < 0 { - candidateDist = -candidateDist - } - currentDist := current - target - if currentDist < 0 { - currentDist = -currentDist - } - return candidateDist < currentDist -} - func (h *Handler) convertRates( ctx context.Context, rates map[string]oas.TokenRates, token, currency string, - yesterdayRates, weekRates, monthRates map[string]float64, + todayRates, yesterdayRates, weekRates, monthRates map[string]float64, ) (map[string]oas.TokenRates, error) { trust := core.TrustNone if len(token) >= minTonAddressLength { @@ -243,8 +191,6 @@ func (h *Handler) convertRates( } } - todayRates, todayTimestamps := h.ratesSource.GetTodayRatesWithTimestamps() - todayCurrencyPrice, ok := todayRates[currency] if !ok { return nil, toError(http.StatusBadRequest, fmt.Errorf("invalid currency: %v", currency)) @@ -260,12 +206,7 @@ func (h *Handler) convertRates( } } - minuteAgoRates, minuteAgoTimestamps := h.ratesSource.GetMinuteAgoRatesWithTimestamps() - tokenPrice, todayCurrencyPrice := alignConversionPrices( - token, currency, - todayRates, todayTimestamps, - minuteAgoRates, minuteAgoTimestamps, - ) + tokenPrice := todayRates[token] if trust == core.TrustBlacklist { tokenPrice = 0 } diff --git a/pkg/api/rates_handlers_test.go b/pkg/api/rates_handlers_test.go deleted file mode 100644 index 557280fda..000000000 --- a/pkg/api/rates_handlers_test.go +++ /dev/null @@ -1,100 +0,0 @@ -package api - -import ( - "testing" -) - -func TestAlignConversionPrices(t *testing.T) { - const ( - jetton = "0:b113a994b5024a16719f69139328eb759596c38a25f59028b146fecdc3621dfe" - now = int64(1_756_000_000) - ) - - tests := []struct { - name string - todayRates map[string]float64 - todayTs map[string]int64 - prevRates map[string]float64 - prevTs map[string]int64 - wantToken, wantCur float64 - }{ - { - name: "same generation: today prices used as is", - todayRates: map[string]float64{jetton: 10, "TON": 1}, - todayTs: map[string]int64{jetton: now, "TON": now}, - prevRates: map[string]float64{jetton: 9, "TON": 1}, - prevTs: map[string]int64{jetton: now - 60, "TON": now - 60}, - wantToken: 10, wantCur: 1, - }, - { - name: "no timestamps: today prices used as is", - todayRates: map[string]float64{jetton: 10, "TON": 1}, - todayTs: map[string]int64{}, - prevRates: map[string]float64{jetton: 9, "TON": 2}, - prevTs: map[string]int64{}, - wantToken: 10, wantCur: 1, - }, - { - name: "stale token price: currency taken from previous snapshot", - // the jetton price is from the 2-minute feed (now-120), the currency from - // the 1-minute feed (now); the previous snapshot's currency (now-60... -120) - // matches the jetton's generation better - todayRates: map[string]float64{jetton: 10, "TON": 2}, - todayTs: map[string]int64{jetton: now - 120, "TON": now}, - prevRates: map[string]float64{jetton: 10, "TON": 1.8}, - prevTs: map[string]int64{jetton: now - 120, "TON": now - 120}, - wantToken: 10, wantCur: 1.8, - }, - { - name: "stale currency price: token taken from previous snapshot", - todayRates: map[string]float64{jetton: 10, "TON": 2}, - todayTs: map[string]int64{jetton: now, "TON": now - 120}, - prevRates: map[string]float64{jetton: 9, "TON": 2}, - prevTs: map[string]int64{jetton: now - 120, "TON": now - 120}, - wantToken: 9, wantCur: 2, - }, - { - name: "previous snapshot no closer: today prices kept", - // prev snapshot is even further from the token's generation than today - todayRates: map[string]float64{jetton: 10, "TON": 2}, - todayTs: map[string]int64{jetton: now - 60, "TON": now}, - prevRates: map[string]float64{jetton: 10, "TON": 1.8}, - prevTs: map[string]int64{jetton: now - 240, "TON": now - 240}, - wantToken: 10, wantCur: 2, - }, - { - name: "gap above skew bound (slow fiat): today prices kept", - // EUR was last written an hour ago; that is not feed staleness - todayRates: map[string]float64{jetton: 10, "EUR": 0.5}, - todayTs: map[string]int64{jetton: now, "EUR": now - 3600}, - prevRates: map[string]float64{jetton: 9, "EUR": 0.5}, - prevTs: map[string]int64{jetton: now - 60, "EUR": now - 3600}, - wantToken: 10, wantCur: 0.5, - }, - { - name: "previous price is zero: today price kept", - todayRates: map[string]float64{jetton: 10, "TON": 2}, - todayTs: map[string]int64{jetton: now - 120, "TON": now}, - prevRates: map[string]float64{jetton: 10, "TON": 0}, - prevTs: map[string]int64{jetton: now - 120, "TON": now - 120}, - wantToken: 10, wantCur: 2, - }, - } - - currencyOf := func(rates map[string]float64) string { - if _, ok := rates["EUR"]; ok { - return "EUR" - } - return "TON" - } - - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - currency := currencyOf(tt.todayRates) - gotToken, gotCur := alignConversionPrices(jetton, currency, tt.todayRates, tt.todayTs, tt.prevRates, tt.prevTs) - if gotToken != tt.wantToken || gotCur != tt.wantCur { - t.Fatalf("got token=%v currency=%v, want token=%v currency=%v", gotToken, gotCur, tt.wantToken, tt.wantCur) - } - }) - } -} diff --git a/pkg/rates/calculator.go b/pkg/rates/calculator.go index 564ebc418..b93770f36 100644 --- a/pkg/rates/calculator.go +++ b/pkg/rates/calculator.go @@ -14,6 +14,9 @@ type ratesSource interface { GetMarketsTonPrice() ([]Market, error) } +// timestampedRatesSource is implemented by sources backed by the rates service's +// /v1/rates/timestamped endpoint. Only its prices are consumed; the per-token +// timestamps it reports are ignored. type timestampedRatesSource interface { GetRatesWithTimestamps(date int64) (map[string]float64, map[string]int64, error) } @@ -24,14 +27,7 @@ type calculator struct { // See the Mock description for details source ratesSource todayRates, yesterdayRates, weekRates, monthRates map[string]float64 - // todayTimestamps holds, for each token in todayRates, the unix timestamp its price - // was produced at; empty when the source cannot report timestamps - todayTimestamps map[string]int64 - // minuteAgoRates and minuteAgoTimestamps hold the today snapshot from the previous - // refresh cycle; empty until the second refresh completes (cold start) - minuteAgoRates map[string]float64 - minuteAgoTimestamps map[string]int64 - marketsTonPrice []Market + marketsTonPrice []Market } type Point struct { @@ -47,7 +43,6 @@ func InitCalculator(source ratesSource) *calculator { c := &calculator{ source: source, todayRates: map[string]float64{}, - todayTimestamps: map[string]int64{}, yesterdayRates: map[string]float64{}, weekRates: map[string]float64{}, monthRates: map[string]float64{}, @@ -74,13 +69,12 @@ func (c *calculator) refresh() { marketsTonPrice, marketErr := c.source.GetMarketsTonPrice() var todayRates map[string]float64 - var todayTimestamps map[string]int64 var err error if tsSource, ok := c.source.(timestampedRatesSource); ok { - todayRates, todayTimestamps, err = tsSource.GetRatesWithTimestamps(today.Unix()) + // prices come from the timestamped endpoint; the timestamps are ignored + todayRates, _, err = tsSource.GetRatesWithTimestamps(today.Unix()) } else { todayRates, err = c.source.GetRates(today.Unix()) - todayTimestamps = map[string]int64{} } if err != nil { slog.Error("[refresh-rates] error getting today rates", slog.String("err", err.Error())) @@ -103,10 +97,7 @@ func (c *calculator) refresh() { } c.mu.Lock() - c.minuteAgoRates = c.todayRates - c.minuteAgoTimestamps = c.todayTimestamps c.todayRates = todayRates - c.todayTimestamps = todayTimestamps c.yesterdayRates = yesterdayRates c.weekRates = weekRates c.monthRates = monthRates @@ -141,27 +132,6 @@ func (c *calculator) GetRates(date int64) (map[string]float64, error) { return nil, fmt.Errorf("invalid period") } -// GetTodayRatesWithTimestamps returns today's rates together with, for each token, the unix -// timestamp its price was produced at. The timestamps map is empty when the source does not -// implement timestampedRatesSource -func (c *calculator) GetTodayRatesWithTimestamps() (map[string]float64, map[string]int64) { - c.mu.RLock() - defer c.mu.RUnlock() - return c.todayRates, c.todayTimestamps -} - -// GetMinuteAgoRatesWithTimestamps returns the today snapshot from the previous refresh -// cycle. Until the second refresh completes (cold start) there is no previous snapshot, -// so it falls back to the current one — callers always get a usable map -func (c *calculator) GetMinuteAgoRatesWithTimestamps() (map[string]float64, map[string]int64) { - c.mu.RLock() - defer c.mu.RUnlock() - if len(c.minuteAgoRates) == 0 { - return c.todayRates, c.todayTimestamps - } - return c.minuteAgoRates, c.minuteAgoTimestamps -} - func (c *calculator) GetRatesChart(token string, currency string, pointsCount int, startDate *int64, endDate *int64) ([]Point, error) { return c.source.GetRatesChart(token, currency, pointsCount, startDate, endDate) } diff --git a/pkg/rates/calculator_test.go b/pkg/rates/calculator_test.go index c7c1b7e03..7d78e1181 100644 --- a/pkg/rates/calculator_test.go +++ b/pkg/rates/calculator_test.go @@ -2,9 +2,10 @@ package rates import ( "testing" + "time" ) -// fakeTimestampedSource returns a configurable rates map with timestamps and counts fetches. +// fakeTimestampedSource serves rates through the timestamped endpoint interface. type fakeTimestampedSource struct { rates map[string]float64 timestamps map[string]int64 @@ -26,7 +27,7 @@ func (f *fakeTimestampedSource) GetMarketsTonPrice() ([]Market, error) { return []Market{}, nil } -func TestCalculator_MinuteAgoRates_ShiftAndFallback(t *testing.T) { +func TestCalculator_Refresh_UsesTimestampedSourcePrices(t *testing.T) { source := &fakeTimestampedSource{ rates: map[string]float64{"TON": 1.0}, timestamps: map[string]int64{"TON": 100}, @@ -34,38 +35,19 @@ func TestCalculator_MinuteAgoRates_ShiftAndFallback(t *testing.T) { c := &calculator{ source: source, todayRates: map[string]float64{}, - todayTimestamps: map[string]int64{}, yesterdayRates: map[string]float64{}, weekRates: map[string]float64{}, monthRates: map[string]float64{}, marketsTonPrice: []Market{}, } - // Before any refresh both snapshots are empty but usable. - rates, timestamps := c.GetMinuteAgoRatesWithTimestamps() - if rates == nil || timestamps == nil { - t.Fatal("minute-ago accessor must never return nil maps") - } - - // Cold start: after the first refresh there is no previous snapshot yet, - // so the minute-ago accessor falls back to the current one. - c.refresh() - rates, timestamps = c.GetMinuteAgoRatesWithTimestamps() - if rates["TON"] != 1.0 || timestamps["TON"] != 100 { - t.Fatalf("expected fallback to current snapshot, got rates=%v timestamps=%v", rates, timestamps) - } - - // Second refresh with new prices: the previous snapshot must shift into minute-ago. - source.rates = map[string]float64{"TON": 2.0} - source.timestamps = map[string]int64{"TON": 160} c.refresh() - rates, timestamps = c.GetMinuteAgoRatesWithTimestamps() - if rates["TON"] != 1.0 || timestamps["TON"] != 100 { - t.Fatalf("expected previous snapshot in minute-ago, got rates=%v timestamps=%v", rates, timestamps) + rates, err := c.GetRates(time.Now().UTC().Unix()) + if err != nil { + t.Fatalf("GetRates: %v", err) } - rates, timestamps = c.GetTodayRatesWithTimestamps() - if rates["TON"] != 2.0 || timestamps["TON"] != 160 { - t.Fatalf("expected fresh snapshot in today, got rates=%v timestamps=%v", rates, timestamps) + if rates["TON"] != 1.0 { + t.Fatalf("expected today rates from the timestamped source, got %v", rates) } } From 2ec1b093d52c5bff950e6f2155e18a8efd139110 Mon Sep 17 00:00:00 2001 From: pavel levchenko Date: Mon, 24 Aug 2026 18:27:42 +0300 Subject: [PATCH 5/5] remove .idea --- .idea/opentonapi.iml | 4 - .idea/vcs.xml | 6 - .idea/workspace.xml | 431 ------------------------------------------- 3 files changed, 441 deletions(-) delete mode 100644 .idea/opentonapi.iml delete mode 100644 .idea/vcs.xml delete mode 100644 .idea/workspace.xml diff --git a/.idea/opentonapi.iml b/.idea/opentonapi.iml deleted file mode 100644 index 7ee078df7..000000000 --- a/.idea/opentonapi.iml +++ /dev/null @@ -1,4 +0,0 @@ - - - - \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml deleted file mode 100644 index 94a25f7f4..000000000 --- a/.idea/vcs.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/.idea/workspace.xml b/.idea/workspace.xml deleted file mode 100644 index c01ec8b77..000000000 --- a/.idea/workspace.xml +++ /dev/null @@ -1,431 +0,0 @@ - - - - - - - - - - - - - - - { - "history": [ - { - "state": "OPEN" - } - ], - "lastFilter": { - "state": "OPEN" - } -} - { - "prStates": [ - { - "id": { - "id": "PR_kwDOI2kNKs7CmxI_", - "number": 798 - }, - "lastSeen": 1770705940046 - } - ] -} - { - "selectedUrlAndAccountId": { - "url": "git@github.com:tonkeeper/opentonapi.git", - "accountId": "6cd316c0-d731-43e0-a270-e98d6d6ef95b" - } -} - - - - - - - - - - - - - - - - - - - { - "associatedIndex": 2 -} - - - - ton in github.com/tonkeeper/opentonapi/pkg/rates.executor": "Debug", - "Go Test.TestConverter_DecodeTupleMatrix in github.com/tonkeeper/opentonapi/pkg/api.executor": "Run", - "Go Test.TestConverter_DecodeTupleMatrix/tuple_0x0 in github.com/tonkeeper/opentonapi/pkg/api.executor": "Run", - "Go Test.TestConverter_DecodeTupleMatrix/tuple_0x1 in github.com/tonkeeper/opentonapi/pkg/api.executor": "Debug", - "Go Test.TestFindActions in github.com/tonkeeper/opentonapi/pkg/bath.executor": "Run", - "Go Test.TestFindActions/bidask_ton_usdt_swap in github.com/tonkeeper/opentonapi/pkg/bath.executor": "Run", - "Go Test.TestFindActions/bidask_usdt-usde_swap in github.com/tonkeeper/opentonapi/pkg/bath.executor": "Run", - "Go Test.TestFindActions/bidask_usdt_ton_swap in github.com/tonkeeper/opentonapi/pkg/bath.executor": "Run", - "Go Test.TestFindActions/bidask_usdt_usde_swap in github.com/tonkeeper/opentonapi/pkg/bath.executor": "Run", - "Go Test.TestFindActions/bidask_v2_usdt_ton_swap in github.com/tonkeeper/opentonapi/pkg/bath.executor": "Run", - "Go Test.TestFindActions/dedust_swap_with_omniston in github.com/tonkeeper/opentonapi/pkg/bath.executor": "Run", - "Go Test.TestFindActions/dedust_swap_with_omniston_new in github.com/tonkeeper/opentonapi/pkg/bath.executor": "Debug", - "Go Test.TestFindActions/dedust_swap_with_omniston_old in github.com/tonkeeper/opentonapi/pkg/bath.executor": "Run", - "Go Test.TestFindActions/deposit_both_ton_bmTON_liquidity_bidask in github.com/tonkeeper/opentonapi/pkg/bath.executor": "Run", - "Go Test.TestFindActions/deposit_both_ton_bmTON_liquidity_bidask_with_refund in github.com/tonkeeper/opentonapi/pkg/bath.executor": "Run", - "Go Test.TestFindActions/deposit_hydra_+_usdt_liquidity_bidask in github.com/tonkeeper/opentonapi/pkg/bath.executor": "Run", - "Go Test.TestFindActions/deposit_storm_liquidity_stonfi in github.com/tonkeeper/opentonapi/pkg/bath.executor": "Run", - "Go Test.TestFindActions/deposit_ton_+_storm_liquidity_stonfi in github.com/tonkeeper/opentonapi/pkg/bath.executor": "Run", - "Go Test.TestFindActions/deposit_ton_+_storm_liquidity_stonfi#01 in github.com/tonkeeper/opentonapi/pkg/bath.executor": "Debug", - "Go Test.TestFindActions/deposit_ton_+_tonio_liquidity_dedust in github.com/tonkeeper/opentonapi/pkg/bath.executor": "Run", - "Go Test.TestFindActions/deposit_ton_+_usdt_liquidity_bidask in github.com/tonkeeper/opentonapi/pkg/bath.executor": "Run", - "Go Test.TestFindActions/deposit_ton_+_usdt_liquidity_dedust in github.com/tonkeeper/opentonapi/pkg/bath.executor": "Run", - "Go Test.TestFindActions/deposit_ton_+_usdt_liquidity_mooncx in github.com/tonkeeper/opentonapi/pkg/bath.executor": "Run", - "Go Test.TestFindActions/deposit_ton_+_usdt_liquidity_tonco in github.com/tonkeeper/opentonapi/pkg/bath.executor": "Run", - "Go Test.TestFindActions/deposit_ton_liquidity_tonco in github.com/tonkeeper/opentonapi/pkg/bath.executor": "Run", - "Go Test.TestFindActions/deposit_tonio_+_ton_liquidity_dedust in github.com/tonkeeper/opentonapi/pkg/bath.executor": "Run", - "Go Test.TestFindActions/deposit_usdt_+_dust_liquidity_dedust in github.com/tonkeeper/opentonapi/pkg/bath.executor": "Run", - "Go Test.TestFindActions/deposit_usdt_+_ton_liquidity_dedust in github.com/tonkeeper/opentonapi/pkg/bath.executor": "Run", - "Go Test.TestFindActions/deposit_usdt_earn in github.com/tonkeeper/opentonapi/pkg/bath.executor": "Run", - "Go Test.TestFindActions/deposit_usdt_earn_affluent in github.com/tonkeeper/opentonapi/pkg/bath.executor": "Run", - "Go Test.TestFindActions/deposit_usdt_earn_affluent_with_oracles in github.com/tonkeeper/opentonapi/pkg/bath.executor": "Run", - "Go Test.TestFindActions/deposit_usdt_earn_affluent_with_single_oracle in github.com/tonkeeper/opentonapi/pkg/bath.executor": "Run", - "Go Test.TestFindActions/deposit_usdt_liquidity_bidask in github.com/tonkeeper/opentonapi/pkg/bath.executor": "Run", - "Go Test.TestFindActions/dumbahh_test in github.com/tonkeeper/opentonapi/pkg/bath.executor": "Run", - "Go Test.TestFindActions/ethena_deposit_stake_request in github.com/tonkeeper/opentonapi/pkg/bath.executor": "Run", - "Go Test.TestFindActions/ethena_withdraw_stake_request in github.com/tonkeeper/opentonapi/pkg/bath.executor": "Debug", - "Go Test.TestFindActions/failed_stonfi_swap in github.com/tonkeeper/opentonapi/pkg/bath.executor": "Debug", - "Go Test.TestFindActions/flawed_jetton_transfer in github.com/tonkeeper/opentonapi/pkg/bath.executor": "Run", - "Go Test.TestFindActions/flawed_jetton_transfer-two-out in github.com/tonkeeper/opentonapi/pkg/bath.executor": "Run", - "Go Test.TestFindActions/flawed_jetton_transfer_2 in github.com/tonkeeper/opentonapi/pkg/bath.executor": "Run", - "Go Test.TestFindActions/instant_withdraw_request_usdt_affluent_with_multiple_oracles in github.com/tonkeeper/opentonapi/pkg/bath.executor": "Run", - "Go Test.TestFindActions/instant_withdraw_request_usdt_affluent_with_single_oracle in github.com/tonkeeper/opentonapi/pkg/bath.executor": "Run", - "Go Test.TestFindActions/instant_withdraw_usdt_affluent in github.com/tonkeeper/opentonapi/pkg/bath.executor": "Run", - "Go Test.TestFindActions/liquidity_deposit_stonfi_request in github.com/tonkeeper/opentonapi/pkg/bath.executor": "Run", - "Go Test.TestFindActions/mooncx_deposit_ton_usdt_liquidity in github.com/tonkeeper/opentonapi/pkg/bath.executor": "Run", - "Go Test.TestFindActions/mooncx_simple_swap in github.com/tonkeeper/opentonapi/pkg/bath.executor": "Run", - "Go Test.TestFindActions/mooncx_ton-usdt_swap in github.com/tonkeeper/opentonapi/pkg/bath.executor": "Run", - "Go Test.TestFindActions/new_withdraw_stake_request in github.com/tonkeeper/opentonapi/pkg/bath.executor": "Run", - "Go Test.TestFindActions/nft_getgems_purchase_v4 in github.com/tonkeeper/opentonapi/pkg/bath.executor": "Run", - "Go Test.TestFindActions/nft_purchase in github.com/tonkeeper/opentonapi/pkg/bath.executor": "Run", - "Go Test.TestFindActions/nft_purchase_2 in github.com/tonkeeper/opentonapi/pkg/bath.executor": "Run", - "Go Test.TestFindActions/nft_purchase_at_Disintar_Marketplace in github.com/tonkeeper/opentonapi/pkg/bath.executor": "Run", - "Go Test.TestFindActions/nft_transfer in github.com/tonkeeper/opentonapi/pkg/bath.executor": "Run", - "Go Test.TestFindActions/not-to-merge-simplest-straw in github.com/tonkeeper/opentonapi/pkg/bath.executor": "Run", - "Go Test.TestFindActions/not_merge_big_bubble_in_the_middle in github.com/tonkeeper/opentonapi/pkg/bath.executor": "Run", - "Go Test.TestFindActions/not_merge_bubble_in_the_beginning in github.com/tonkeeper/opentonapi/pkg/bath.executor": "Run", - "Go Test.TestFindActions/not_merge_bubble_in_the_beginning_with_tail in github.com/tonkeeper/opentonapi/pkg/bath.executor": "Run", - "Go Test.TestFindActions/not_merge_bubble_in_the_end in github.com/tonkeeper/opentonapi/pkg/bath.executor": "Run", - "Go Test.TestFindActions/not_merge_bubble_in_the_end_with_tail in github.com/tonkeeper/opentonapi/pkg/bath.executor": "Run", - "Go Test.TestFindActions/not_merge_bubble_in_the_middle in github.com/tonkeeper/opentonapi/pkg/bath.executor": "Run", - "Go Test.TestFindActions/not_merge_bubble_in_the_middle_with_tail in github.com/tonkeeper/opentonapi/pkg/bath.executor": "Run", - "Go Test.TestFindActions/not_merge_bubble_in_the_very_beginning in github.com/tonkeeper/opentonapi/pkg/bath.executor": "Run", - "Go Test.TestFindActions/not_merge_simplest_straw in github.com/tonkeeper/opentonapi/pkg/bath.executor": "Run", - "Go Test.TestFindActions/old_withdraw_stake_request in github.com/tonkeeper/opentonapi/pkg/bath.executor": "Run", - "Go Test.TestFindActions/provide_ton_+_storm_liquidity_stonfi in github.com/tonkeeper/opentonapi/pkg/bath.executor": "Run", - "Go Test.TestFindActions/simple_transfer in github.com/tonkeeper/opentonapi/pkg/bath.executor": "Run", - "Go Test.TestFindActions/stonfi_partial_cross-swap in github.com/tonkeeper/opentonapi/pkg/bath.executor": "Run", - "Go Test.TestFindActions/stonfi_usdt-ton_exchange_with_tonkeeper_battery in github.com/tonkeeper/opentonapi/pkg/bath.executor": "Run", - "Go Test.TestFindActions/stonfi_v2_multihop_swap in github.com/tonkeeper/opentonapi/pkg/bath.executor": "Run", - "Go Test.TestFindActions/stonfi_v2_multihop_swap_with_crossdex in github.com/tonkeeper/opentonapi/pkg/bath.executor": "Debug", - "Go Test.TestFindActions/stonfi_v2_swap_simple in github.com/tonkeeper/opentonapi/pkg/bath.executor": "Run", - "Go Test.TestFindActions/stonfi_v2_swap_with_ref in github.com/tonkeeper/opentonapi/pkg/bath.executor": "Debug", - "Go Test.TestFindActions/stonfi_v2_test in github.com/tonkeeper/opentonapi/pkg/bath.executor": "Run", - "Go Test.TestFindActions/subscription_V2_+_wallet_V4_cancel_by_expire in github.com/tonkeeper/opentonapi/pkg/bath.executor": "Run", - "Go Test.TestFindActions/subscription_V2_+_wallet_V4_destroy_by_beneficiary in github.com/tonkeeper/opentonapi/pkg/bath.executor": "Run", - "Go Test.TestFindActions/subscription_V2_+_wallet_W5_deploy_with_payment in github.com/tonkeeper/opentonapi/pkg/bath.executor": "Run", - "Go Test.TestFindActions/tonco_failed_ton_swap in github.com/tonkeeper/opentonapi/pkg/bath.executor": "Run", - "Go Test.TestFindActions/tonco_storm-usdt_swap in github.com/tonkeeper/opentonapi/pkg/bath.executor": "Run", - "Go Test.TestFindActions/tonco_swap_to_another_account in github.com/tonkeeper/opentonapi/pkg/bath.executor": "Run", - "Go Test.TestFindActions/tonco_ton-usdt_swap in github.com/tonkeeper/opentonapi/pkg/bath.executor": "Run", - "Go Test.TestFindActions/tonco_usdt-ton_swap in github.com/tonkeeper/opentonapi/pkg/bath.executor": "Run", - "Go Test.TestFindActions/withdraw_request_usdt_affluent in github.com/tonkeeper/opentonapi/pkg/bath.executor": "Debug", - "Go Test.TestFindActions/withdraw_request_usdt_affluent_with_multiple_oracles in github.com/tonkeeper/opentonapi/pkg/bath.executor": "Run", - "Go Test.TestFindActions/withdraw_request_usdt_affluent_with_oracles in github.com/tonkeeper/opentonapi/pkg/bath.executor": "Run", - "Go Test.TestFindActions/withdraw_request_usdt_affluent_with_single_oracle in github.com/tonkeeper/opentonapi/pkg/bath.executor": "Run", - "Go Test.TestFindActions/withdraw_usdt_affluent in github.com/tonkeeper/opentonapi/pkg/bath.executor": "Run", - "Go Test.TestGetInvariantForStableSwap in github.com/tonkeeper/opentonapi/pkg/rates.executor": "Run", - "Go Test.TestSortReserveAndAssetPairs in github.com/tonkeeper/opentonapi/pkg/rates.executor": "Run", - "Go Test.go test github.com/tonkeeper/opentonapi/pkg/bath.executor": "Run", - "Go Test.go test github.com/tonkeeper/opentonapi/pkg/rates.executor": "Debug", - "Makefile Target.gen.executor": "Run", - "ModuleVcsDetector.initialDetectionPerformed": "true", - "RunOnceActivity.GoLinterPluginOnboarding": "true", - "RunOnceActivity.GoLinterPluginStorageMigration": "true", - "RunOnceActivity.ShowReadmeOnStart": "true", - "RunOnceActivity.TerminalTabsStorage.copyFrom.TerminalArrangementManager.252": "true", - "RunOnceActivity.git.unshallow": "true", - "RunOnceActivity.go.formatter.settings.were.checked": "true", - "RunOnceActivity.go.migrated.go.modules.settings": "true", - "RunOnceActivity.go.modules.go.list.on.any.changes.was.set": "true", - "git-widget-placeholder": "update-modules", - "go.import.settings.migrated": "true", - "go.sdk.automatically.set": "true", - "last_opened_file_path": "/Users/pavel/tonkeeper/opentonapi/pkg/bath/testdata", - "node.js.detected.package.eslint": "true", - "node.js.selected.package.eslint": "(autodetect)", - "nodejs_package_manager_path": "npm", - "settings.editor.selected.configurable": "editor.preferences.fonts.default", - "two.files.diff.last.used.file": "/Users/pavel/tonkeeper/opentonapi/pkg/bath/testdata/stonfi-v2-swap-ref.json" - } -}]]> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1754829364430 - - - - - - - - - - true - - - - - - file://$USER_HOME$/go/pkg/mod/github.com/tonkeeper/tongo@v1.16.17/wallet/messages.go - 163 - - - file://$USER_HOME$/go/pkg/mod/github.com/tonkeeper/tongo@v1.16.17/wallet/messages.go - 171 - - - file://$PROJECT_DIR$/pkg/rates/math_test.go - 176 - - - file://$PROJECT_DIR$/pkg/api/emulation.go - 427 - - - file://$PROJECT_DIR$/pkg/bath/jettons.go - 194 - - - file://$PROJECT_DIR$/pkg/rates/sources.go - 102 - - - file://$USER_HOME$/go/pkg/mod/github.com/tonkeeper/tongo@v1.16.41/tlb/tuple.go - 8 - - - file://$PROJECT_DIR$/pkg/bath/dedust.go - 181 - - - file://$PROJECT_DIR$/pkg/bath/auctions.go - 53 - - - file://$PROJECT_DIR$/pkg/api/event_converters.go - 616 - - - file://$PROJECT_DIR$/pkg/bath/jettons.go - 267 - - - file://$PROJECT_DIR$/pkg/bath/stonfi.go - 137 - - - file://$PROJECT_DIR$/pkg/bath/stonfi.go - 205 - - - file://$PROJECT_DIR$/pkg/bath/stonfi.go - 175 - - - file://$USER_HOME$/go/pkg/mod/github.com/tonkeeper/tongo@v1.22.12/abi-tolk/abiGenerated/xtr/xtr-master_marshal.go - 42 - - - file://$PROJECT_DIR$/pkg/bath/payments.go - 270 - - - file://$PROJECT_DIR$/pkg/bath/payments.go - 200 - - - file://$PROJECT_DIR$/pkg/bath/payments.go - 228 - - - - - - - - - - - - \ No newline at end of file