Polymarket rejects market orders below $1 USDC. Added CLOB_MIN_ORDER_USDC=1
constant and applied Math.max(config.minTradeSize, CLOB_MIN_ORDER_USDC) at
both the loop entry check and post-fill remainder check so sub-$1 remainders
are silently skipped instead of causing API errors.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Root cause: auto-sell GTC orders lock all shares in the CLOB's internal
ledger. When executeSell runs, it tried to cancel only position.sellOrderId
but this can fail silently, leaving tokens locked. The CLOB then rejects
the new sell with "not enough balance or allowance" because the balance
is committed to the existing GTC order.
Fix:
- Fetch all open orders for the specific tokenId via client.getOpenOrders()
- Cancel all of them with Promise.allSettled (non-fatal per order)
- Wait 600ms after cancellation so the CLOB updates its locked-balance
ledger before we place the new sell
- Fallback: if getOpenOrders fails, still attempt to cancel by
position.sellOrderId (previous behaviour) then wait 600ms
- Use correct cancelOrder({ orderID }) object form throughout
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
redeemer.js was calling redeemPositions() directly from the EOA private
key wallet. This is wrong for two reasons:
1. Conditional tokens are held in config.proxyWallet (Gnosis Safe), not
in the EOA — so the EOA has nothing to redeem
2. No maxPriorityFeePerGas was set, causing Polygon's "gas tip below
minimum" error (1.5 Gwei sent, 25 Gwei required)
Fix: replace the direct contract call with execSafeCall() (exported from
ctf.js), which is identical to the MM bot's redemption pattern:
- encodes calldata and executes via Safe.execTransaction()
- signed by the EOA, but msg.sender on-chain = proxy wallet
- enforces 30 Gwei minimum priority fee for Polygon
- retries up to 3x on transient RPC errors
Also remove the now-unused NEG_RISK_CTF_ADDRESS local constant
(CTF_ADDRESS and USDC_ADDRESS imported from ctf.js).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Two root causes fixed:
1. Missing ERC-1155 setApprovalForAll for copy-trade flow
- executeBuy: call ensureExchangeApproval() after a successful fill so
the CTF Exchange is authorised to move tokens before the next sell
- executeSell: call ensureExchangeApproval() before every sell attempt;
the function is idempotent (checks isApprovedForAll first, only sends
a Safe tx if approval is actually missing)
2. Stored shares can exceed real on-chain balance (fee deductions, float
drift across partial FAK fills)
- executeSell: query ctf.balanceOf(proxyWallet, tokenId) before selling
- If on-chain balance is 0 → position is already gone, remove it and skip
- If on-chain balance < stored shares → adjust down and log the delta
- Round sell amount to 4 decimal places to avoid sub-unit precision errors
Also add getOnChainTokenBalance() helper using a minimal CTF ABI slice.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Rename project to polymarket-terminal
- Add Market Maker bot (src/mm.js) with on-chain CTF split/merge/redeem via Gnosis Safe
- Add Orderbook Sniper bot (src/sniper.js) with multi-asset GTC low-price orders
- Add WebSocket watcher (src/services/wsWatcher.js) for real-time RTDS trade events
- Add terminal dashboard UI (src/ui/dashboard.js) using blessed
- Add CTF contract helpers (src/services/ctf.js) for splitPosition, mergePositions, redeemPositions
- Add mmDetector, mmExecutor, sniperDetector, sniperExecutor services
- Add simStats utility for dry-run P&L tracking
- Translate all Indonesian-language strings to professional English across all files
- Rewrite README.md in English with full setup guide, configuration reference, and architecture overview
- Rewrite AGENT.MD in English as comprehensive AI agent and developer reference
- Update package.json name, description, scripts, and keywords
Co-Authored-By: direkturcrypto <direkturcrypto.x@mail3.me>