Issueهای 3abot

فقط برای مشاهده. همه‌ی باگ‌ها و تسک‌های باز که هنوز ready نشده‌اند، به ترتیب اولویت. برای تأیید یا درخواست تغییر در تلگرام پیام بدهید، مثلاً «#70 تأیید» یا «#70 تغییر: …».

1 refine شده17 هنوز refine نشده
وضعیت در 2026-10-05 08:51 (به وقت تهران).

Refine شده، منتظر تأیید شما (1)

هنوز refine نشده (17)

#70P1تسکتخمین ۱ هفته+ LBank exchange integration

مشکل

LBank یک صرافی order-book معمولی است که هیچ کدی در 3abot ندارد. برخلاف صرافی‌های ایرانی که فقط دو بازار IRT و USDT دارند، فرصت آربیتراژ در LBank بین چند stablecoin است (USDT / USDC / USD1). یعنی «دو quote ثابت» که الان در کل pipeline هاردکد شده (coinfetcher، CryptoData، موتور Go، trade-execution، ResellService) باید به N quote عمومی شود.

داده‌ی زنده‌ی ۲۰۲۶-۱۰-۰۲ (حدود ۱۲ دقیقه WS روی ۳۷ pair، فقط endpointهای عمومی، جزئیات در docs/reports/epic-70-lbank-plan.html) نشان می‌دهد که با کارمزد فرضی taker معادل 0.10%، edge بین quoteها خیلی کم است. روی کوین‌های پرحجم اختلاف حداکثر حدود 5 bps است و هزینه‌ی دو leg معادل 20 bps. تنها موارد سودده bookهای کم‌عمق بودند (مثلاً یک سفارش حدود ۱۰۷ دلاری TRX/USD1). پس قبل از هر سفارش واقعی باید معلوم شود در عمل وضعیت‌مان چطور می‌بود.

تصمیم مالک (۲۰۲۶-۱۰-۰۵): فاز ۱ همه‌چیز را می‌سازد، جز ثبت سفارش واقعی. wallet هم mock است و هیچ notificationی ارسال نمی‌شود. سیستم مدتی روی داده‌ی زنده‌ی LBank کار می‌کند و بعد از روی نتیجه تصمیم می‌گیریم که فاز ۲ (سفارش واقعی) را انجام بدهیم یا نه.

علت ریشه‌ای

دو quote در ریشه‌ی سیستم هاردکد شده است:

  • bun/domain/contracts/IExchangePlugin.ts فقط irtQuotes/usdtQuotes دارد. groupMarkets() در bun/application/coinfetcher.ts فقط baseای را نگه می‌دارد که هم بازار IRT و هم USDT داشته باشد.
  • CryptoData در هر دو runtime (bun/domain/entities/CryptoData.ts، go/internal/core/types/model.go) فیلدهای ثابت irt/usdt دارد.
  • go/internal/core/engine.go دو worker، دو تابع process و دو تابع calc دارد. state.go هم فیلدهای scalar مخصوص IRT/USDT دارد.
  • TradeExecutionService در حدود ۱۵ جا روی transactionType == "IRT to USDT" شاخه می‌زند. ResellService دقیقاً دو بازار را مقایسه می‌کند (irtBid در برابر usdtBidInIrt).
  • DryRunOrderSimulator (bun/infra/exchange/shared/DryRunOrderSimulator.ts) هر سفارش را کامل پر می‌کند و به orderbook نگاه نمی‌کند. برای سنجیدن «اگر واقعی بود چه می‌شد» این کافی نیست.
  • notifyGotify (bun/infra/notification/gotify.ts) از چند جا مستقیم صدا زده می‌شود (trade-execution، resellService، dollarCrashGuard). خاموش کردن notification باید در همین تابع مشترک انجام شود، نه در تک‌تک callerها.

برنامه

یک branch به نام fix/70-lbank از origin/main و یک draft PR با checklist زیر. هر بند یک سری commit است. بندهای ۱ تا ۷ refactorهایی هستند که رفتار Wallex/Tabdil/Nobitex/Bitpin/Ramzinex را عیناً حفظ می‌کنند. gate آن‌ها این است که تست‌های فعلی Go و TS با همان fixtureهای قدیمی پاس شوند.

فاز ۱: همه‌چیز جز سفارش واقعی (paper trading)

  1. مدل quote و coinfetcher (½ روز): به IExchangePlugin فیلدهای quotes: string[] و valuationQuote اضافه می‌شود. پیش‌فرض صرافی‌های فعلی ["IRT","USDT"] / "IRT" است. groupMarkets به‌صورت marketsByQuote برمی‌گردد و baseای معتبر است که حداقل ۲ quote داشته باشد. precision برابر کمینه‌ی precision همه‌ی quoteها می‌شود. coinfetcher کلید quotes را فقط وقتی می‌نویسد که با پیش‌فرض فرق داشته باشد. این کلید به هر دو فایل key (RedisKeys.ts، keys.go) اضافه می‌شود.
  2. wire format CryptoData.books (½ روز): پیام به شکل {symbol, books:{Q:{bids,asks}}, at:{Q:ms}, lastUpdate} درمی‌آید. Go در UnmarshalJSON شکل قدیمی irt/usdt را هم می‌خواند تا وقتی Bun و Go با چند ثانیه فاصله reload می‌شوند پیامی گم نشود. MarketDataService هر coin را روی همه‌ی quoteها subscribe می‌کند و وقتی حداقل ۲ book در cache باشد publish می‌کند.
  3. market data برای LBank (۱ روز): در bun/infra/exchange/lbank/، getMarkets() با currencyPairs.do و accuracy.do پیاده می‌شود. LBankWs روی depth 10 subscribe می‌کند، به ping سرور pong می‌دهد و در هر socket حداکثر ۸ pair نگه می‌دارد (اندازه‌گیری‌شده: هر socket حدود 20 msg/s می‌کشد). reconnect و resubscribe هم دارد. در LBankPlugin مقادیر valuationQuote:"USDT"، currency:"usdt"، hasFairPrice:false و supportsWalletWs:false تنظیم می‌شوند. LBank در ExchangeRegistry ثبت می‌شود و در Go، پکیج go/internal/exchange/lbank ساخته و در main.go import می‌شود. LBank به environments/*.json و pm2Config.ts هم اضافه می‌شود.
  4. balance، fee و rate برای هر quote (۱ روز): کلیدهای balance:{q} (به‌همراه :locked) برای هر quote نوشته می‌شوند و quoteها از balance:coin:* بیرون می‌روند. قانون balance:delta_at (#5) روی همه‌ی quoteها اعمال می‌شود. PriceService.getBalance/getRate/getTakerFee/applyWalletDelta(q) اضافه می‌شود. role مربوط به usdtprice برای LBank کلید rate:{q} = bid(q_usdt)·(1−taker) را هر حدود ۱ ثانیه با TTL می‌نویسد، تا اگر writer مُرد موتور آن quote را skip کند. fee:taker_{q} هم نوشته می‌شود.
  5. موتور Go با جهت‌های عمومی (A, B) (۲ تا ۳ روز): state از mapها ساخته می‌شود (با fallback به کلیدهای قدیمی). یک کانال job از (data, A, B) با W worker و یک تابع calcProfit عمومی جای دو تابع قبلی را می‌گیرد: profit = vol·(1−f_A)·bid_B·(1−f_B)·rate(B) − vol·ask_A·rate(A). block به شکل trade:block:{a}_to_{b} درمی‌آید و adapter.MinNotional(q) اضافه می‌شود. ArbitrageResult فیلدهای buyQuote/sellQuote/buyRate/sellRate/buyAt/sellAt را می‌گیرد و transactionType به شکل "{A} to {B}" نوشته می‌شود، پس رشته‌های قدیمی دقیقاً همان می‌مانند. manage.ts blockTrade/unblockTrade هر a_to_b را قبول می‌کند.
  6. trade-execution روی هر (A, B) (۲ تا ۳ روز): buyQuote/sellQuote یک بار در بالای _processTradeInner تعیین می‌شود و هر شاخه‌ی IRT/USDT با lookup روی quote جایگزین می‌شود. calcProfit عمومی در profitRevalidation.ts قرار می‌گیرد و برابری‌اش با fixtureهای Go تست می‌شود. ResellSignal فیلد buyQuote را می‌گیرد.
  7. ResellService با N بازار (۲ تا ۳ روز): در هر tick، برای هر quote مقدار bid_q·(1−f_q)·rate(q) حساب می‌شود و بیشترین برنده است. یک map از rateها جای usdtIrtCache را می‌گیرد. entryهایی که قبلاً با "irt"/"usdt" ذخیره شده‌اند همچنان load می‌شوند.
  8. paper trading برای LBank: wallet ساختگی و پر شدن واقع‌گرایانه (۱ روز): - Paper wallet: موجودی در Redis با کلید paper:wallet:{ASSET} نگه داشته می‌شود (فقط Bun از آن استفاده می‌کند و به هر دو فایل key اضافه می‌شود). مقدار اولیه با manage.ts paperWallet lbank set USDT=1000 USDC=500 ... تنظیم و با paperWallet lbank show دیده می‌شود. در فاز ۱، LBankExchange.getBalances() همین wallet را برمی‌گرداند. به این ترتیب walletFetcher → balance:* → Go → trade-execution بدون تغییر و عیناً همان مسیر واقعی کار می‌کند. - PaperOrderSimulator: در placeOrder، depth لحظه‌ای REST (/v2/depth.do) خوانده می‌شود و سطح‌ها با معنای IOC تا قیمت limit پیموده می‌شوند. خروجی matchedAmount و fee واقعی است، باقی سفارش لغو می‌شود، و wallet به‌صورت اتمیک (INCRBYFLOAT در MULTI) debit/credit می‌شود. پس latency واقعی و slippage هم در نتیجه دیده می‌شوند. sellهای ResellService هم از همین مسیر می‌روند. - در فاز ۱ کد ثبت سفارش واقعی (create_order.do) اصلاً وجود ندارد. LBankExchange.placeOrder/getOrderStatus/cancelOrder فقط به simulator وصل‌اند، پس اشتباه در env هم نمی‌تواند سفارش واقعی ثبت کند. transactionها با dry_run=true در Postgres ثبت می‌شوند. - کارمزد: اگر کلید API ست شده باشد (creds:set lbank)، signer (MD5 روی پارامترهای مرتب‌شده → HmacSHA256) و فقط endpoint خواندنی customer_trade_fee.do پیاده می‌شوند تا کارمزد واقعی حساب در fee:taker_{q} نوشته شود. در غیر این صورت مقدار config استفاده می‌شود (پیش‌فرض 0.001). این مهم‌ترین عدد برای تصمیم فاز ۲ است.
  9. خاموش کردن notification (≤ 2h): یک guard در notifyGotify: وقتی NOTIFICATIONS_ENABLED=false باشد، فقط console.log می‌کند و چیزی به Gotify نمی‌فرستد. در env مربوط به LBank مقدارش false است. صرافی‌های دیگر دست نمی‌خورند.
  10. سنجش نتیجه و end-to-end (۱ روز): MockPlugin حالت ۳ quote می‌گیرد و یک stage برای USDT→USDC→USDT به smoke-test.ts اضافه می‌شود. دستور manage.ts paperReport lbank (یک‌بار چاپ می‌کند) این‌ها را نشان می‌دهد: تعداد signal، تعداد اجراشده، fill rate، سود و زیان به USDT به تفکیک جهت و coin (از transactions/orders با exchange='lbank' AND dry_run)، و ارزش فعلی paper wallet با rate:{q} در مقایسه با مقدار اولیه. PR بعد از review از حالت draft بیرون می‌آید. سپس LBank مدتی (پیشنهاد: ۲ هفته) در paper mode اجرا می‌شود.

فاز ۲: فقط بعد از دیدن نتیجه‌ی فاز ۱ و تأیید مالک (جداگانه refine می‌شود)

  • private REST واقعی: create_order.do (IOC)، orders_info.do، cancel، mapping کدهای خطا، lbankRateLimits.ts (order 500/10s، بقیه 200/10s)، و user_info_account.do برای wallet واقعی.
  • notificationها: currency:"usdt"، plugin.unitLabel به‌جای حدود ۲۲ برچسب هاردکد «تومان»، و نمایش جهت‌هایی مثل «USDT → USDC».
  • de-peg guard برای stablecoinها (Q4)، و اولین سفارش واقعی با حداقل حجم که فقط با تأیید مالک ثبت می‌شود.

خارج از scope: rebalance خودکار stablecoin به USDT (چون rate خالص آن را قیمت‌گذاری کرده است)، quoteهای غیر stable (BTC/ETH/BRL)، مثلث اتمیک ۳ leg در یک signal، و private WS لبانک.

پیش‌فرض‌ها برای سؤال‌های باز (اگر مالک چیز دیگری نگوید)

  • Q1 quoteها: USDT + USDC + USD1. USDE و USDG خاموش‌اند چون bookهای کم‌عمق با spread حدود 30 bps دارند.
  • Q2 ارزش اقتصادی: با داده‌ی فاز ۱ جواب داده می‌شود.
  • Q3: بدون rebalance.
  • Q5 حداقل سود: مقدار مطلق 0.05 USDT در MinimumProfit().
  • Q6: IOC (در فاز ۱ شبیه‌سازی می‌شود).
  • Q8: گزارش‌ها به USDT.
  • مقدار اولیه‌ی paper wallet: 1000 USDT + 500 USDC + 500 USD1.
  • محل اجرای فاز ۱: روی سرور prod به‌عنوان یک صرافی جدا (پول واقعی درگیر نیست). deploy فقط با تأیید جداگانه‌ی مالک انجام می‌شود. قبل از آن باید از روی سرور بررسی شود که api.lbank.info در دسترس است (Q7).

معیار پذیرش

  • ☐ همه‌ی تست‌های فعلی Go (engine_test.go، state_test.go) و TS با همان اعداد مورد انتظار پاس می‌شوند. هیچ کلید Redis قدیمی تغییر نام نمی‌دهد.
  • ☐ در اجرای local (pm2build_local lbank)، Go برای هر coin حداقل ۲ quote دریافت می‌کند و lag کمتر از ۲ ثانیه است.
  • ☐ یک signal از نوع USDT→USDC روی LBank از مسیر کامل trade-execution عبور می‌کند. سفارش فقط با PaperOrderSimulator و روی depth لحظه‌ای پر می‌شود و paper:wallet:USDT/paper:wallet:USDC درست تغییر می‌کنند. transaction با dry_run=true در Postgres ثبت می‌شود.
  • ☐ در کد LBank هیچ فراخوانی‌ای به create_order.do یا cancel_order وجود ندارد (grep).
  • ☐ با NOTIFICATIONS_ENABLED=false هیچ درخواستی به Gotify نمی‌رود (تست).
  • ☐ manage.ts paperReport lbank سود و زیان، fill rate و ارزش wallet را به USDT چاپ می‌کند.

تست‌ها

  • groupMarkets: حالت قدیمی و حالت ۳ quote.
  • decode پیام CryptoData در Go: شکل جدید و شکل قدیمی.
  • calcProfit در Go: برابر با calcIRTtoUSDT/calcUSDTtoIRT روی همه‌ی fixtureهای موجود. موارد quote بدون موجودی (job ساخته نمی‌شود)، rate ناموجود (skip) و block usdc_to_usdt (فقط همان جهت skip می‌شود).
  • برابری TS/Go برای calcProfit در profitRevalidation.test.ts.
  • TradeExecutionService: جریان‌های USDT→USDC و USDC→USD1 با MockExchangeRest.
  • ResellService: انتخاب بین ۳ بازار، از جمله حالتی که bid خام بالاتر بعد از fee/rate می‌بازد، و load شدن entry قدیمی.
  • LBankWs: parser برای depth و ping، و sharding (۱۷ pair → ۳ socket). getMarkets روی JSON ضبط‌شده.
  • PaperOrderSimulator: پر شدن چندسطحی تا قیمت limit، پر شدن جزئی IOC، صفر fill، کسر fee، و debit/credit اتمیک wallet.
  • signer روی بردار نمونه‌ی مستندات، و parse کردن customer_trade_fee.do.
  • guard notifyGotify، و فرمول paperReport روی داده‌ی ساختگی.

اندازه / ریسک

Estimate: 1 week+

L. فاز ۱ حدود ۱۱ تا ۱۴ روز کاری است. مسیر بحرانی ۱ → ۲ → ۵ → ۶ → ۷ است. این کار money path (trade-execution، ResellService)، قرارداد Bun↔Go (CryptoData، ArbitrageResult) و کلیدهای Redis (quotes، balance:{q}، fee:*_{q}، rate:{q}، paper:wallet:*، trade:block:{a}_to_{b}) را تغییر می‌دهد. ریسک اصلی پسرفت در صرافی‌های فعلی است که با gate «fixtureهای قدیمی دست‌نخورده» کنترل می‌شود. در LBank فاز ۱ ریسک مالی صفر است، چون کد سفارش واقعی وجود ندارد.

گزارش اصلی

Priority

P1

What and why

A normal order-book exchange; implement the required REST and WebSocket integration for trading. Needs authentication, token/API key handling, pair mapping, balance management, order placement, and order status tracking.

Documentation: https://www.lbank.com/docs/#introduction

برای تأیید یا تغییر، در تلگرام پیام بدهید. · مشاهده در GitHub

#31P1تسکتخمین ≤ ۲ ساعت W1: Add Wallex order-placement rate limit (20 req / 10 s)

مشکل

Wallex's docs (docs/Wallex.md, changelog line 5) now cap order placement, POST /v1/account/orders, at 20 requests / 10 s (it used to be 10 req/s). WallexPlugin.getRateLimits() (bun/infra/exchange/wallex/WallexPlugin.ts:74) returns {}, so RateLimiter.acquire('order_add', …) is a no-op on Wallex. Trade-execution and resell-service (two processes, one account) place orders with no pacing against that cap.

Prod, last 7 days (exchange_requests, Wallex):

  • 19,060 placements;
  • peak 31 in one 10 s window, p99 12;
  • 53 windows had ≥ 15;
  • 0 HTTP 429s, and no rate-limit text in any response.

So Wallex isn't visibly enforcing the 20/10 s yet. This is defensive: if they start enforcing it, a burst over 20 would get orders rejected mid-trade, for example a buy that fills followed by a rejected sell leg.

علت ریشه‌ای

WallexPlugin.getRateLimits() returns {}. Every other exchange with documented caps already has a <exchange>RateLimits.ts (Nobitex, Bitpin, Ramzinex). Trade-execution and ResellService already call acquire('order_add' | 'order_status' | 'order_cancel') on every Wallex order, so only the config is missing.

برنامه

  1. bun/infra/exchange/wallex/wallexRateLimits.ts, same shape as bitpinRateLimits.ts, with a comment quoting the doc: ts export const WALLEX_RATE_LIMITS: Record<string, RateLimitBucketConfig> = { order_add: { limit: 20, windowMs: 10_000, reservePerPendingCoin: 4 }, } Why reservePerPendingCoin: 4:
  • A trade needs 2 placements (buy + sell).
  • With 1 pending resell coin, trade-execution keeps 16 per 10 s, more than today's p99 of 12.
  • With 4 coins it keeps 4, still 2 trades per 10 s.
  • Only at 5+ pending coins is it paused until resell frees some, which is the same intent as Nobitex's 1/3-per-coin.
  • Anything ≥ 10 would block trade-execution with only 2 pending coins. 2. order_status / order_cancel: no bucket. The docs only give the global 100 req/s. Prod status+cancel traffic is 135,499 per 7 days (~0.2/s average), nowhere near it. Leaving them out keeps acquire() a no-op there (YAGNI). Add a bucket only if 429s ever appear. 3. WallexPlugin.getRateLimits() returns WALLEX_RATE_LIMITS. 4. Docs: update CLAUDE.md "Order Rate Limiting" (l.371 says "Wallex/Tabdil return {}"), so Tabdil is the only no-op one left, and add the Wallex numbers. 5. Out of scope: Tabdil limits, and changing RateLimiter itself.

معیار پذیرش

  • ☐ Test bun/tests/ts/infra/WallexPlugin.test.ts: getRateLimits() returns order_add { limit: 20, windowMs: 10_000, reservePerPendingCoin: 4 } and no order_status/order_cancel buckets.
  • ☐ Test (RateLimiter with the Wallex config, MockRedisClient): 20 low acquires within 10 s succeed and the 21st waits; with 1 pending resell coin, low gets 16 and high still gets 20.
  • ☐ CLAUDE.md "Order Rate Limiting" lists the Wallex bucket.
  • ☐ Prod, a week after deploy: Wallex placements never exceed 20 per 10 s in exchange_requests, and trade-execution's added wait is visible only in those bursts (log [RateLimiter] waiting, if logged).

تست‌ها

WallexPlugin.test.ts (new cases) and bun/tests/ts/services/RateLimiter.test.ts, or the existing shared limiter test, using the Wallex config. No real Redis or exchange.

اندازه / ریسک

Estimate: ≤ 2h

S. Config only, on a path every other exchange already runs. The cost: in burst windows (about 53 a week with ≥ 15, a few above 20) trade-execution waits up to a few seconds instead of sending immediately, which can slightly delay those trades. Today's real risk is low, since Wallex currently accepts 31/10 s. No Redis key or Bun/Go change; the ratelimit:wallex:* keys follow the existing pattern.

Original task **W1 — Add an order-placement rate limit.** New docs: `POST /v1/account/orders` is capped at **20 requests / 10 s** (old doc said 10 req/s). `WallexPlugin.getRateLimits()` returns `{}`, so `RateLimiter.acquire('order_add', …)` is a no-op and trade-execution + resell-service (two processes, one account) are unpaced against it. - Add `bun/infra/exchange/wallex/wallexRateLimits.ts` (same shape as `bitpinRateLimits.ts`): `order_add: { limit: 20, windowMs: 10_000, reservePerPendingCoin: }`. `reservePerPendingCoin` must stay well below 20, or a few pending resell coins starve trade-execution entirely — pick a value and justify it in the comment. - `order_status` / `order_cancel`: docs only give the global **100 req/s** cap — decide whether to add a flat bucket or leave them unpaced. - Return it from `WallexPlugin.getRateLimits()`; add a `WallexPlugin` test asserting the buckets (mirror `BitpinPlugin.test.ts`); update CLAUDE.md "Order Rate Limiting" (currently says Wallex/Tabdil return `{}`). --- Priority: **P1** · Area: Wallex · Migrated from `todo.md` (2026-09-27)

هنوز برنامه ندارد. برای refine شدن #31 در تلگرام بگویید. · مشاهده در GitHub

#52P2تسک Implement Monitoring Dashboard

گزارش ثبت‌شده

Priority

P2

What and why

Develop a centralized graphical dashboard for monitoring the operational status, performance, profitability, and key trading controls of each bot.

The dashboard should provide both real-time operational controls and historical performance metrics, allowing the team to monitor the bot without relying on raw production logs.

Dashboard Components

  1. Bot Controls
  • Exchange selector
  • Bot ON/OFF control
  • Bot Reset action
  • Token configuration section
  1. Profit & Performance
  • Daily Profit — calculated from 00:00 to 00:00
  • Weekly Profit
  • Monthly Profit
  • Profit charts with Daily / Weekly / Monthly views
  • Trading Volume — Daily / Weekly / Monthly
  1. Bot Health & System Monitoring
  • CPU utilization
  • RAM utilization
  • Service health status
  • Graphical representation of service availability/health
  • Monitoring should make service degradation or abnormal resource consumption immediately visible
  1. Coin Blacklist Management
  • Display currently blacklisted coins
  • Input field for adding a new coin to the blacklist
  • Remove action for existing blacklist entries
  • Changes should be reflected in the bot configuration without requiring manual configuration changes
  1. Trading Controls
  • IRT → USD trading block toggle
  • USD → IRT trading block toggle
  • Resell Service ON/OFF toggle
  1. Trading Statistics
  • Number of successful trades — Daily / Monthly / Yearly
  • Number of failed trades — Daily / Monthly / Yearly
  • Most traded coin — Daily / Weekly / Monthly, including coin name and trade count
  • Most profitable coin — Daily / Weekly / Monthly, including coin name and generated profit

Expected Result

A single dashboard should provide a clear overview of the bot's current operational state, system health, trading activity, and profitability, while exposing the main operational controls required for day-to-day bot management.

The dashboard should prioritize quick visibility of abnormal states and key performance indicators, rather than requiring the operator to inspect production logs or individual services manually.

هنوز برنامه ندارد. برای refine شدن #52 در تلگرام بگویید. · مشاهده در GitHub

#73P2تسک Add Wallex Credit Account Support

گزارش ثبت‌شده

Priority

P2

What and why

Implement support for Wallex Credit Accounts as a separate account from the main account. The system should be able to handle trades on both accounts simultaneously. Coins that are not supported by the credit account should automatically be traded through the main account. If the credit account reaches its rate limit, new trades should be routed through the main account until the credit account is available again. Documentation: https://developers.wallex.ir/docs/trade-credit-intro

هنوز برنامه ندارد. برای refine شدن #73 در تلگرام بگویید. · مشاهده در GitHub

#19P3باگ B19: Nobitex OverValueOrder storm.

گزارش ثبت‌شده

1,022 OverValueOrder responses (61% of 1,336 order-adds on 09-21). This is the known 20× internal retry. Nobitex has had no trades since 09-23 06:43 and its logs stop at 09-23 10:13. Check whether nobitex was stopped on purpose.


Priority: P1 · Area: Bitpin / Nobitex · From bugs.md (prod logs + DB, 2026-09-27)

هنوز برنامه ندارد. برای refine شدن #19 در تلگرام بگویید. · مشاهده در GitHub

#26P3باگ B26: Full Axios error objects dumped into logs.

گزارش ثبت‌شده

Wallex REST errors print the whole AxiosError (request config, sockets, [Symbol(...)], ~70 lines each; wallex-resell-service-error.log is 39k lines). No credential values were found, but auth header names appear, so a future change could leak them. Log only status, data, method url.


Priority: P3 · Area: Logging hygiene · From bugs.md (prod logs + DB, 2026-09-27)

هنوز برنامه ندارد. برای refine شدن #26 در تلگرام بگویید. · مشاهده در GitHub

#27P3باگ B27: Tabdil request signatures logged in full URLs.

گزارش ثبت‌شده

...&timestamp=N&signature=<hex> appears in error logs. It's low risk (per-request), but strip the query string.


Priority: P3 · Area: Logging hygiene · From bugs.md (prod logs + DB, 2026-09-27)

هنوز برنامه ندارد. برای refine شدن #27 در تلگرام بگویید. · مشاهده در GitHub

#28P3باگ B28: Duplicate rows in `exchange_requests`.

گزارش ثبت‌شده

Rows with identical (exchange, created_at, endpoint, request) in the last 2 days: wallex 2,694, bitpin 2,606, tabdil 1,299. The same request is logged twice. Also Wallex 422 rows store response_summary.error = generic Axios text, while the real reason is only in raw_payload.data. Put the exchange's message in the summary.


Priority: P3 · Area: Logging hygiene · From bugs.md (prod logs + DB, 2026-09-27)

هنوز برنامه ندارد. برای refine شدن #28 در تلگرام بگویید. · مشاهده در GitHub

#29P3باگ B29: Go engine logs info to stderr at huge volume.

گزارش ثبت‌شده

*-arbitrage-check-error*.log is almost entirely [StateManager] PubSub received on config:X: fees_updated/thresholds_updated, about 430k lines per exchange. So coinfetcher publishes config:* far more often than every 5 min, or every instance logs each one. Lower it to debug, and check the publish rate (each one triggers a full syncSlow).


Priority: P3 · Area: Logging hygiene · From bugs.md (prod logs + DB, 2026-09-27)

هنوز برنامه ندارد. برای refine شدن #29 در تلگرام بگویید. · مشاهده در GitHub

#30P3باگ B30: pm2 log dir is 538 MB / 5,057 files.

گزارش ثبت‌شده

Every marketdata/arbitrage-check restart creates a new -<pid>.log file that's never cleaned up. Tune pm2-logrotate retain and delete orphaned per-pid files.


Priority: P3 · Area: Logging hygiene · From bugs.md (prod logs + DB, 2026-09-27)

هنوز برنامه ندارد. برای refine شدن #30 در تلگرام بگویید. · مشاهده در GitHub

#32P3تسک W2: Remove undocumented /v1/account/profile fallback in getStreamKey()

گزارش ثبت‌شده

W2 — Remove the undocumented /v1/account/profile fallback in getStreamKey(). /v1/account/profile is gone from the new docs. It's also dead code: walletFetcher only calls subscribeWallet() when supportsWalletWs is true, which requires WALLEX_STREAM_KEY to be set, and getStreamKey() returns that env var first, so the fallback is never reached. Make the env var the only source (throw if unset), drop the profile call, and update the doc comments in WallexExchange.getStreamKey()/ WallexPlugin.supportsWalletWs plus CLAUDE.md's Wallet Balance table row ("checked every endpoint, including /v1/account/profile").


Priority: P3 · Area: Wallex · Migrated from todo.md (2026-09-27)

هنوز برنامه ندارد. برای refine شدن #32 در تلگرام بگویید. · مشاهده در GitHub

#35P3تسک W5: Use Wallex private WS tradeDetails channel for fills (optional)

گزارش ثبت‌شده

W5 (optional) — new private channel STREAMKEY@tradeDetails pushes per-fill price, qty, fee and isMaker. Could replace getOrderStatus() polling for fills later. Not needed now.


Priority: P3 · Area: Wallex · Migrated from todo.md (2026-09-27)

هنوز برنامه ندارد. برای refine شدن #35 در تلگرام بگویید. · مشاهده در GitHub

#38P3تسک Abantether: decide whether to integrate (OTC broker, no order book)

گزارش ثبت‌شده

A — Abantether (poor fit: OTC broker, not an order book). Decide before starting.

  • No order book at all: GET /api/v1/manager/otc/ticker (and WS wss://ws.abantether.com/public, channel coins_list_v2) only give one buy_price / sell_price + buy_max / sell_max per coin, in IRT and USDT markets.

  • The Go engine and trade-execution assume real order-book depth (pickAsks/pickBids, revalidation against the live book). Abantether would need a synthetic 1-level book (ask = buy_price, bid = sell_price, volume = _max). The spread is the broker's margin, so arbitrage opportunities inside* Abantether (IRT ↔ USDT) are likely rare. Its value is mostly as a cross-exchange leg, which this bot doesn't do.

  • Orders: POST /api/v1/order_handler/orders/otc/market (buy volume is in quote currency, sell volume in base), .../otc/limit, status GET .../otc/{id}/, cancel POST .../otc/{id}/cancel. Order ids are strings.

  • Auth: static Authorization: Token <key> (never expires), so the credential shape is the simple token, like Nobitex classic. Balances: GET /api/v1/accounting/balances/?type=spot. Fees/min/max: GET /api/v1/feecalculator/coin-info/?symbol=&side=.

  • No OHLC → use the public Wallex OHLC fallback like Tabdil. No private WS → REST-only wallet. No rate limits documented.

  • Recommendation: do Ramzinex first. Only build Abantether if you actually want the OTC-price arbitrage it allows, since that needs a design decision on the synthetic book (Bun-side normalization only; Go stays pass-through).

Docs: docs/abantether.md


Priority: P3 · Area: New exchange · Migrated from todo.md (2026-09-27)

هنوز برنامه ندارد. برای refine شدن #38 در تلگرام بگویید. · مشاهده در GitHub

#40P3تسک Raise Nobitex axios timeout (2000 ms is too aggressive)

گزارش ثبت‌شده

Nobitex's axios client timeout (NobitexExchange.ts, timeout: 2000) is aggressive — 26 ETIMEDOUT errors across just 2 days of logs. Now recoverable (this session's clientOrderId fix), so no longer money-risking, but still worth raising to reduce needless recovery-lookup traffic against Nobitex's own rate limits.


Priority: P2 · Area: Nobitex · Migrated from todo.md (2026-09-27)

هنوز برنامه ندارد. برای refine شدن #40 در تلگرام بگویید. · مشاهده در GitHub

#41P3تسک CPU / RAM / service-health history has no data source

گزارش ثبت‌شده

CPU usage history / RAM usage history / service health graph has no data source at all. Confirmed by search — no collector, no table, anywhere in this codebase. This is a real gap in the dashboard requirements handed down for this task, unrelated to retention (nothing to retain if nothing is ever collected). Flagging for whoever scopes the dashboard build; when it lands, its table needs a deliberate retention decision, not a silent default either way. See docs/db-retention.md's dependency-audit table.


Priority: P3 · Area: Observability · Migrated from todo.md (2026-09-27)

هنوز برنامه ندارد. برای refine شدن #41 در تلگرام بگویید. · مشاهده در GitHub

#42P3تسک ResellService: minProfitIrt should decay as deadline approaches

گزارش ثبت‌شده

ResellConfig.minProfitIrt is a flat threshold that doesn't decay as an entry's deadline approaches — could miss a brief "good enough" window right before deadline-driven manual handoff. (See CLAUDE.md's own "Suggestions" section.)


Priority: P3 · Area: Resell · Migrated from todo.md (2026-09-27)

هنوز برنامه ندارد. برای refine شدن #42 در تلگرام بگویید. · مشاهده در GitHub

#43P3تسک ResellService: cool-down/backoff between executeSell() attempts

گزارش ثبت‌شده

No cool-down/backoff between ResellService.executeSell() attempts on the same entry — every orderbook tick can trigger a fresh attempt immediately after a failed/partial one.


Priority: P3 · Area: Resell · Migrated from todo.md (2026-09-27)

هنوز برنامه ندارد. برای refine شدن #43 در تلگرام بگویید. · مشاهده در GitHub

#44P3تسک ResellService: deliberate ordering across entries sharing one symbol

گزارش ثبت‌شده

No priority/fairness ordering across multiple resell entries sharing one symbol (resell:index:{SYMBOL} is a Redis SET; iteration order isn't deliberate).


Priority: P3 · Area: Resell · Migrated from todo.md (2026-09-27)

هنوز برنامه ندارد. برای refine شدن #44 در تلگرام بگویید. · مشاهده در GitHub