Вынесено из MEMORY.md 8 Jun для разгрузки контекста. Источник истины по спеке:
polymarket-screener/docs/COPYTRADING_PLAN.md+brain/decisions/log.md+ SKILL.md. Краткий статус — см. индекс в MEMORY.md.
7 Jun — Polymarket Screener: РАЗВОРОТ В КОПИТРЕЙДИНГ, спека зафиксирована (docs/COPYTRADING_PLAN.md = источник истины, REDESIGN_PLAN.md → SUPERSEDED). Custody=модель B (POLY_1271): юзер держит деньги в НАШЕМ кастомном vault (НЕ Gnosis Safe!) + прописывает наш delegate-signer → торгуем но НЕ выводим. 🔑 Vault, не Safe (Spike B, Rick OK): Safe склеивает торговлю+вывод в owner'е (для 1271 подписант=owner→мог бы вывести), Vault.sol 80стр разделяет (/.cargo/bin/cargo`. Строим ТОЛЬКО фолловера (лидер=6 точек расширения). Детали→COPYTRADING_PLAN.md+brain/log.md+SKILL.md.isValidSignature=делегат, withdraw=onlyOwner), инвариант 1271 signer==maker==vault, ⚠️аудит перед mainnet. ❌ типы 1/2 (getSafeAddress(signer)==safe) делегацию не дают, только тип3. ⚠️ Issue#70 SDK ставит POLY_ADDRESS=EOA→обходим своим кодом (POLY_ADDRESS=funder). Модель A (кастодия) отвергнута (FINTRAC MSB+RPAA, уголовка). Спайк: Chunk 1 ✅ офлайн-крипто-пруф (research/spike-b/spike.mjs, 8/8 checks, #1/#2 закрыты: delegate-подпись→MAGIC, проходит exchange-гейт verifyPoly1271Signature). Chunk 2 (⬜ позже, нужен faucet) = Amoy on-chain. CLOB-хосты: mainnet live, staging 503, Amoy-CLOB нет→#3 на mainnet $1. UI-стройка фолловера: Шаги 1-3 DONE live (91d8418,9be291e,c06a626): Ш1 нав 5 вкладок (🐋Лидеры/📋Мои копии/💼Портфель/🔍Рынки/⚙️Ещё, старая лента→/feed); Ш2 LeadersPage(/) лидерборд поверх /api/signals/top-traders БЕЗ бэка; Ш3 профиль equity-спарклайн+CTA[Копировать]→/copy+viewMode public/owner; Ш5 «Мои копии» demo (a2e4878: useCopySubscriptions localStorage + CopyConfigModal аллокация/лимиты/категории/цена/зеркал/просадка + карточки подписок); Ш6 💼 CustodyCard на портфеле (67088c3: баланс-плейсхолдер+статус делегирования+disabled депозит/вывод, рабочий портфель не тронут). Весь фолловер-UI собран в demo. ⚠️Rust серверит client/dist; деплой=npm run build+pm2 restart. Auth=SIWE wallet-auth (адрес=user_id), НЕ email. Ш4 Custody прогресс (7 Jun): 4a схема (fa4efe7 users/vaults/copy_subscriptions/copy_positions); 4b-1 SIWE-бэкенд (4189f77 src/auth.rs ecrecover k256+tiny-keccak→JWT httpOnly cookie→upsert users, депы k256/tiny-keccak/jsonwebtoken/rand, ⚠️JWT_SECRET random без env→сессии reset); 4b-2 SIWE-клиент (7de96cc SiweAuthProvider+MorePage Аккаунт); copy-CRUD (15ffe67+0bab796 src/copytrade.rs session-gated, useCopySubscriptions backend/localStorage). 🎯 4c ON-CHAIN MAINNET (52ce539): Vault 0xecf49480f7b93a8e788cd0b671ffff7a263ef3e4 задеплоен на Polygon, deployer=weather-bot EOA 0x1aec730E…722d1 (Rick разрешил, бот pm2 stop retired, 113POL+$4USDC), delegate 0x830BcD…. PASS на живой сети: isValidSignature(delegate)→MAGIC 0x1626ba7e, withdraw делегатом→revert «not owner». #1/#2 ОНЧЕЙН закрыты. Харнесс research/spike-b/deploy-mainnet.mjs, RPC polygon.drpc.org, solc 0.8.26, ⚠️Vault НЕАУДИРОВАН. 4d delegate-подпись (232cf41): src/ordersign.rs EIP-712 digest+k256, 2 теста PASS (digest=viem golden 0x99b047dd…3c72, recover→delegate), депа primitive-types, dead_code до 4e. #3 прогресс (7 Jun): КОЛЛАТЕРАЛ Polymarket=pUSD 0xC011a7E…E82DFB (6dec, из USDC.e через Onramp 0x93070a8…, wrap_usdc_to_pusd). Биржа V2=0xE111…996B. Деньги в weather Safe 0x3643… (21.58 pUSD = «$30 в проксе»). Перевёл 3 pUSD Safe→vault 0xecf49480…ef3e4 (Safe execTransaction tx 0xdd0da48…)+approveExchange MAX (tx 0xc522dcf…)→vault готов. ⚠️drpc round-robin→balanceOf врёт 0, чек на 2 RPC. #3 AUTH разгадан: L1 на ДЕЛЕГАТА (нужен create-api-key, не derive); vault/1271 только в ОРДЕРЕ (maker=signer=vault,sigType3,подпись делегата→isValidSignature). ClobAuth domain{ClobAuthDomain,v1,137}. NEXT#3 итеративно: create-api-key прокси в скринер+обойти submit_order signer==owner для 1271+ордер(owner=delegate,signer=vault). Возврат vault.withdraw. Сборка `
8 Jun — Polymarket Screener: CUSTODY PIVOT Turnkey/vault → PRIVY embedded wallets. vault/POLY_1271 = DEAD-END (#3 уперся в Issue#70: CLOB L1-auth привязан к EOA через ecrecover, нет EIP-1271; L2 требует order.signer==адрес ключа, для 1271 signer=vault → взаимоискл; «Invalid L1 Request headers»/«order signer must be API KEY»). Решение (офиц. Polymarket + Polycopy): email-логин → провайдер провижинит non-custodial EOA → Gnosis Safe → sigType=2 (order.signer=EOA, maker=Safe, СТАНДАРТ CLOB, БЕЗ Issue#70) → серверная подпись за юзера через Privy Delegated Actions (авто-копи без юзера; «не выводить»=политика провайдера, юзер отзывает/выводит сам). Офиц. примеры Polymarket/privy-safe-builder-example(+turnkey/magic). Выбран Privy (Turnkey-дашборд у Rick не открывался — 403 whoami). M0✅ Privy app SZHub: App ID cmq444h0i00580cih1ur8q1pr (публичный), Secret в polymarket-screener/.env.privy (gitignored chmod600, ⚠️пришёл через TG→ротировать перед продом), email-метод вкл, allowed origin poly-dev.szhub.space (⚠️дубль-app SZHub удалить). M1a✅ (e06f613) @privy-io/react-auth@3.29.2 (install --legacy-peer-deps; доставить @solana-program/system иначе rolldown MISSING_EXPORT), PrivyProvider в App.tsx (VITE_PRIVY_APP_ID). M1b-1✅ LIVE (2401b46) components/PrivyAccount.tsx email-вход заменил SIWE в MorePage — Rick вошёл по email на poly-dev. M1b-2 DONE — онбординг Safe полностью (2a-2d, live). Builder-креды SZHub получены (новый ключ 8 Jun 019ea3a9-…+secret+passphrase→.env.privy gitignored), taker fee 0.5% pending 10 Jun. 2a (cc34cc8) POST /api/polymarket/sign builder-HMAC + main.rs load_dotenv('.env.privy'). 2b (1aa5a5b) usePrivySigner Privy→ethers v5 + SDK (@polymarket relayer/signing/clob + ethers@5); build-фиксы: Privy v3 embeddedWallets.ethereum.createOnLogin, PWA лимит 5MiB, externalize @solana/kit. 2c (67ca28b) useRelayClient+useSafeDeployment (deriveSafe+газлесс)+кнопка «Настроить торговый кошелёк». 2d (3391cbc) useTokenApprovals+utils/approvals (USDC.e+outcome→CTF/Exchange/NegRisk). Флоу email→EOA→Safe→approvals в проде. ⚠️ коллатерал CLOB V2=pUSD (пример апрувит USDC.e)→wrap в M3. 🏆 M2 DONE — ДЕЛЕГИРОВАНИЕ+СЕРВЕРНАЯ ПОДПИСЬ РАБОТАЮТ LIVE (8 Jun, на реальном кошельке Rick). 🔑 РАЗГАДКА: Privy delegateWallet=ЛЕГАСИ (виснет, нет модалки), актуальный = useSigners().addSigners({address,signers:[{signerId,policyIds?}]}); signerId=authorization-ключ из дашборда (Wallet infra→Authorization→New key; тумблера delegated-actions НЕТ, TEE enabled=доступно). Authorization key: Signer ID kc34moyfw73mo5whwfjqpewy→VITE_PRIVY_SIGNER_ID(.env.production, публичный); private key wallet-auth:MIGH…(P-256)→.env.privy PRIVY_AUTHORIZATION_KEY(секрет). M2b-2 (3970be0): сервер подписал за кошелёк Rick 0xE2D892…633d3F(delegated:true) БЕЗ юзера через PrivyClient(appId,secret,{walletApi:{authorizationPrivateKey}}).walletApi.ethereum.signMessage. ⚠️addressдепрекейт→walletId в проде. ГРАБЛИ: чёрный#1=externalize@solana/kit→стаб alias @solana-program/system(375d069); чёрный#2/стейл-бандл→Cache-Control:no-cache на index.html в Rust(8a8be89); headless /snap/bin/chromium+puppeteer-core=диагностика консоли. M3 прогресс (8 Jun): сервер делает за юзера ВСЁ (auth+подпись+сабмит), упёрлись в 1 CLOB-гейт. Node-executor скрипты (server-auth за Rick EOA 0xE2D892…633d3F): M3a order-sign.mjs (signTypedData Polymarket-ордера→recover EOA; депы viem+@polymarket/builder-relayer-client@0.0.10); M3c-auth executor-auth.mjs (сервер подписал ClobAuth→create-key через скринер=CLOB-креды). Privy-Safe Rick=0x7570210eACa5F3783577997fF74e8FEbe9B9E1f4 (deriveSafe+factory 0xaacFeEa…3541b, задеплоен онбордингом, +2 pUSD перевёл из weather Safe). M3c-order order-submit.mjs: сабмит ордера(maker=Safe,sigType2)→CLOB «maker address not allowed, please use the deposit wallet flow». 🔑 ДИАГНОЗ: V1-биржа 0x4bFb41d5B3570DeFd03C39a9A4D8dE6Bd8B8982E getSafeAddress(EOA)=ТОЧНО наш Safe (Safe правильный); V2-биржа 0xE111…996B (юзаем в домене ордера) НЕ имеет getSafeAddress. ГИПОТЕЗА ФИКСА: подписывать sigType2-ордер против домена V1 0x4bFb. Альт: CLOB-регистрация deposit-wallet / pUSD-approval Safe→exchange (онбординг апрувил USDC.e не pUSD). 🎯 РАЗГАДКА «maker not allowed» (8 Jun, ресёрч py-clob-client-v2 issues#51-74 + docs/deposit-wallets): «Deposit wallet» ≠ Gnosis Safe! Мы задеплоили SAFE по офиц.privy-примеру, а CLOB для программного доступа хочет deposit-wallet. Deposit wallet = per-user ERC-1967 proxy от фабрики 0x00000000000Fb5C9ADea0298D729A0CB3823Cc07 (Beacon новые/UUPS легаси, держит pUSD+CT); создание relayer /submit {type:"WALLET-CREATE",from:ownerEOA,to:factory}→ждать STATE_CONFIRMED (иначе реестр не готов); адрес deriveDepositWalletAddress(); ордера sigType3 POLY_1271, maker==signer==deposit-wallet, ERC-7739-обёрнутая подпись (clob-client SDK делает сам). Ирония: наш изначальный vault-POLY_1271 был правильным ПАТТЕРНОМ — нужен их РАСПОЗНАННЫЙ deposit-wallet (фабрикой зарег.), а не кастомный vault (#3 уперся в нерегистрацию/Issue#70). SDK builder-relayer-client@0.0.10 имеет deriveDepositWallet/deriveBeaconDepositWallet(owner,factory,beacon), адреса в dist/config/index.js getContractConfig(137). NEXT=РАЗВОРОТ на deposit-wallets (большой чанк, свежий бюджет): деривить deposit-wallet вместо Safe→деплой relayer(STATE_CONFIRMED)→фунд pUSD→ордер sigType3 через clob-client SDK (ERC-7739)+server-auth signer. Меняет M1b(useSafeDeployment→deposit-wallet)+M3c; M2 делегация/server-auth wallet-agnostic — остаётся.** M3-pivot ПРОГРЕСС (8 Jun): deposit wallet ЗАДЕПЛОЕН+ПРОФИНАНСИРОВАН СЕРВЕРОМ за юзера. DepositWalletContracts(getContractConfig(137)): Factory 0x00000000000Fb5C9ADea0298D729A0CB3823Cc07, Impl 0x58CA52ebe0DadfdF531Cde7062e76746de4Db1eB (UUPS). Rick deposit wallet=0x50A8061e9448EB1e5d5e7aF07BE4E4F63C6F24Ff (deriveDepositWallet(EOA,factory,impl)). 🔑 АДАПТЕР server-auth→viem→Polymarket SDK (node-executor/deploy-dw.mjs, 1ace4f3): RelayClient оборачивает signer в ViemSigner (ждёт viem WalletClient) → решение toAccount({address:EOA,signMessage,signTypedData}) методы зовут privy.walletApi.ethereum.sign* → createWalletClient({account,chain:polygon,transport:http(drpc)})→RelayClient(relayer-v2,137,walletClient,builderConfig.url=localhost:3240/api/polymarket/sign). 🎯 relay.deployDepositWallet()→STATE_CONFIRMED, server-signed БЕЗ юзера; релеер relayer-v2.polymarket.com НЕ геоблокнут. Профинансирован 2 pUSD (weather Safe→dw tx e8dfd00…; ⚠️ещё 2 pUSD застряли в Safe 0x7570…→вернуть Rick). NEXT финал: pUSD-approval dw→exchange (relay.executeDepositWalletBatch([approve],dw,deadline)) + ордер sigType3 POLY_1271 maker==signer==dw ERC-7739-обёртка через clob-client SDK+server-auth signer→сабмит CLOB. RelayClient: deployDepositWallet/executeDepositWalletBatch/deriveDepositWalletAddress/pollUntilState. ⚠️SiweAuthProvider ещё в App; copy-CRUD на SIWE (мигрировать). research-vault 0xecf49480… 3 pUSD→withdraw. Детали→COPYTRADING_PLAN.md+brain/log.md+SKILL.md.
order-v2.mjs 97daf19: clob-client-v2 + server-auth viem-account(Privy) + funderAddress=DW + SignatureTypeV2.POLY_1271 строит валидный sigType3 ERC-7739 ордер ОФЛАЙН за юзера (maker==signer==deposit-wallet 0x50A8061e…F24Ff). (2) post-v2.mjs: createOrDeriveApiKey() на deposit-wallet вернул валидные CLOB-креды → EIP-1271 L1-auth РАБОТАЕТ, стена Issue#70/«Invalid L1 headers» (убившая vault #3) на зарегистр. deposit-wallet МЕРТВА. Блокер постинга: clob-client-v2 тащит ВЛОЖЕННЫЙ axios → axios.defaults на корневом не действует → пост мимо прокси → 403 geoblock; TRADE_PROXY (46.149.128.71:63777 из weather-bot pm2 dump) ещё и ConnectionRefused. NEXT (механика, не ресёрч): постить sigType3-ордер через Rust-бэкенд скринера (он уже роутит order-post через TRADE_PROXY, доказано живым моб.ордером 2 Jun) — node строит+подписывает ордер+L1-creds → submit-endpoint (sigType3-bypass в routes.rs) → Rust постит. Альт: пропатчить вложенный axios + живой прокси. Детали→brain/log.md.46.149.128.71 (Clouvider) — Polymarket добавил BR в блок-лист 2→8 Jun (2 Jun этот прокси ещё проводил живой ордер). Нужен SOCKS5-прокси в РАЗРЕШЁННОМ регионе (заблок: BR/DE/US/FR/SG/TH/PL/CA-ON/BE/TW/UAE). relayer-v2 НЕ геоблочен (deploy/approve direct ок), но ордера только на clob.polymarket.com. Решение за Rick.72.62.247.119 Hostinger MY — НЕ в блок-листе Polymarket; DE-сервер и BR-прокси геоблочены, локальный SSH -D туннель sandbox рубит exit144). Залил node-executor на Малайзию ~/poly-exec (rsync + scp .env.privy chmod600 + npm i 218pkg). post-my.mjs (no-proxy, нативный egress): L1 EIP-1271 auth deposit-wallet → createAndPostOrder sigType3. Node18 падал crypto.subtle unavailable→флаг node --experimental-global-webcrypto (или Node≥20). РЕЗУЛЬТАТ: {success:true,status:"live",orderID:"0x96a74969…dc963"} BUY 10@$0.10 ($1) ЖИВА. Цепочка email→Privy EOA 0xE2D892…633d3F→deposit-wallet 0x50A8061e…F24Ff→server-auth→sigType3 ERC-7739→L1→POST БЕЗ юзера. ПРОДАКШН: executor сабмита ОБЯЗАН в не-геоблок регионе=Малайзия; детекция/оркестр может на DE, финальный POST через Малайзию. ⚠️.env.privy теперь и на Малайзии (ротировать перед продом). SSH-ключ Малайзии=~/.ssh/id_ed25519.bak. NEXT: detection loop + UI + регистрация юзеров. Детали→brain/log.md+SKILL.md.whales.rs→whale_trades, copy_subscriptions/copy_positions. Data API /trades?user= публичный/не-геоблок, asset=tokenID. Чанк1 copy-loop.mjs (DRY): поллит сделки лидера, дедуп state-файл, решение (size=leaderSize×COPY_FRACTION, пол CLOB min 5sh, жёсткий MAX_NOTIONAL cap), прайминг (бэклог не копируем). Чанк2 copy-exec.mjs (execution-примитив из post-my): makeExecutor→postOrder, live-пруф Малайзия orderID 0xb40087…95ad status:live; loop LIVE=1 постит BUY (SELL→Чанк3). Запуск Малайзия ~/poly-exec: LIVE=1 LEADER=0x.. node --experimental-global-webcrypto copy-loop.mjs. Чанк3 NEXT: читать copy_subscriptions из БД, писать copy_positions, SELL/close, per-follower DW (сейчас хардкод Rick 0x50A8061e…), демон pm2 Малайзия, маркет-ордера (Data API лаг ~5мин). Детали→brain/log.md.wss://ws-live-data.polymarket.com topic activity type trades (firehose всех сделок, sub-second, поля proxyWallet/asset=tokenID/side/size/price/...); фильтр по лидеру client-side, ping 5с. Проба 906/20с. copy-loop.mjs дефолт=WS (POLL=1=Data API fallback executeOrLog общий. Проверено DRY вживую (ловит BTC/SOL up-down BUY лидера realtime). Задеплоено Малайзия `0x50A8061e…F24Ff = 21.58 pUSD: vault 0xecf4… 3 (Vault.withdraw, owner=weather EOA, tx 0x1b2926d8…); weather Safe 0x3643914646900cA7A5df15B8f5d1Cc5E32728c1a 14.58 (Safe execTransaction, ECDSA-подпись weather EOA, tx 0x4e6f78c3…); Rick Safe 0x7570… 2 (Safe execTransaction, owner=Rick Privy EOA 0xE2D892…633d3F через server-auth signTypedData SafeTx+recover-чек, tx 0x37562220…). Все 3 источника =0. На weather EOA 0x1aec730…722d1 оставлено: 4 USDC native (НЕ CLOB-коллатерал, нужен wrap чтобы торговать) + 113 POL (газ-резерв для будущих Safe/vault tx). Скрипты node-executor/consolidate-{vault,safe-weather,safe-rick}.mjs (ключи из gitignored .env при запуске). RPC рабочие: drpc + 1rpc.io (polygon-rpc/ankr требуют ключ). Критерии выбора лидера (обсудили): копировать направленных китов в ликвидных медленно-резолвящихся рынках (политика/спорт/длинные крипто), держащих часами+; ИЗБЕГАТЬ HFT-скальперов на 5-мин BTC/SOL up-down (скорость+maker-эдж, скопировать нельзя), огромный-WR-копеечный-профит, маркетмейкеров (обе стороны), неликвид. Кандидаты из 🐋 top-traders.makeExecutor→{buy,sellAll,tokenBalance}; sellAll читает ончейн ERC1155-баланс DW и продаёт ВСЁ держание (надёжно vs учёт филлов). copy-loop handleTrade: BUY открывает+пишет позицию в positions.json; SELL лидера по держимому токену→закрытие через sellAll+mark closed; SELL по недержимому игнор. approve-dw-ctf.mjs: разовый setApprovalForAll CTF(0x4D97DCd97eC945f40cF65F87097ACe5EA0476045)→ExchangeV2+NegRisk(0xC5d563A36AE78145C45a50134d48A1215220f80a) CONFIRMED — DW теперь может продавать (BUY юзал только pUSD-апрув). 3c: ecosystem.copy-trader.js pm2-демон (Малайзия, --experimental-global-webcrypto, env LIVE/LEADER/COPY_FRACTION/MIN_SHARES/MAX_NOTIONAL/DEPOSIT_WALLET). Задеплоено Малайзия ~/poly-exec, pm2 7.0.1. Запуск: задать LEADER→pm2 start ecosystem.copy-trader.js; смена лидера live→edit+pm2 restart copy-trader --update-env. Мультиюзер-БД (читать copy_subscriptions, per-follower DW, писать copy_positions) ОТЛОЖЕН — для теста с Rick как одним фолловером не нужен. Проверено DRY (BUY→WOULD COPY). NEXT=ЖИВОЙ ТЕСТ: Rick выбирает лидера по критериям→pm2 start LIVE. DW профинансирован 21.58 pUSD.tickSize:'0.01',negRisk:false в copy-exec → убрал, SDK сам резолвит per-market (negRisk:false МИСРОУТИЛ neg-risk рынки→фейл/мисфилл; SDK сам округляет цену roundNormal); (2) SELL-close теперь по цене на SELL_SLIPPAGE=3% ниже выхода лидера→лимитка кроссит книгу и реально закрывает (раньше мог висеть незакрытым но помечался closed); (3) ЭКСПОЗИЦИЯ-КАПЫ в copy-loop: одна копия на токен + MAX_OPEN=5 открытых→суммарно ≤ MAX_OPEN×MAX_NOTIONAL=$10 (защита от слива на болтливом лидере). ОК БЕЗ ПРАВОК: децималы (outcome-токены 6dec, sellAll/1e6 верно — подтв. takerAmount=10shares=1e7); BUY=лимитка по цене лидера (нельзя переплатить, max висит); hard-кап MAX_NOTIONAL/сделку; дедуп; прайминг; консолидация уже отработала+сверена ончейн. ⚠️ #1 ПРОД-БЕЗОПАСНОСТЬ (до реальных юзеров, НЕ для теста Rick'а): server-auth Privy-ключ может подписать ЛЮБУЮ tx за кошелёк юзера (через relayer-batch можно ВЫВЕСТИ средства) — гарантия «торговать-не-выводить» требует Privy policies (policyIds) ограничить серверную подпись только CLOB-ордерами. Сейчас НЕ ограничено (отложено с M2). Прочее (не money-loss): feeRateBps:0 ок до 10 Jun; BUY-лимитка может не залиться если рынок ушёл; незалитый BUY занимает open-слот до выхода лидера. NEXT(Rick хочет): запуск через UI=читать copy_subscriptions из БД в loop (отложенный мультиюзер-чанк).skip already holding token, skip max 2 open, hard over-cap. positions.json верно отследил позиции. Старые ручные тест-лимитки отменены (cancel-open.mjs, clob.cancelOrders). БАГИ из теста (фикс): (1) MIN_NOTIONAL=$1 — копии <$1 (5sh@0.03=$0.15) отлетали 400 invalid amount min $1 (marketable-минимум Polymarket); decideCopy теперь бампит size до $1 в рамках MAX_NOTIONAL (skip если min$/max$ несовместимы при цене, напр 0.50/0.95→null). (2) лог: упавший 400-ордер печатал ✅ COPIED→теперь ❌ copy rejected, позиция пишется только на реальный success. Sizing-математика проверена юнит-тестом (все копии $1–$2). ЦЕПОЧКА ДОКАЗАНА E2E ВЖИВУЮ С ФИЛЛАМИ. Держим тестовые Down-позиции на 5-мин рынках (резолвятся сами, редим винеров позже). NEXT=UI-запуск (читать copy_subscriptions из БД в loop). DW=19.63 pUSD./api/copy/active X-Service-Token гейт → все активные подписки демону; require_user принимает X-User-Address Privy-fallback к SIWE; COPY_SERVICE_TOKEN в .env.privy). UI-2 (useCopySubscriptions переписан с SIWE на Privy: usePrivy().authenticated+usePrivySigner().eoaAddress, шлёт X-User-Address → подписки идут в БД copy_subscriptions; фронт собран+задеплоен). UI-3 (copy-loop поллит SUBS_URL→activeLeaders+subsConfig per-leader; deriveCfg: allocValue→fraction, maxPerTrade→$cap, maxExposure→maxOpen, priceMin/Max→ценовой фильтр; env=ЖЁСТКИЙ потолок). Проверено DRY: [subs] active leaders updated, watching N (DB-driven). ⚠️ SECURITY (ревью нашло CRITICAL IDOR): X-User-Address задаётся клиентом → любой может писать чужие подписки, а демон копирует их кошельком Rick'а = money-риск. Митигация: FOLLOWER allow-list в демоне (копит только подписки allow-listed владельца) + env-потолки. НО спуфинг своего же адреса остаётся — ПРАВИЛЬНЫЙ ФИКС (до мультиюзера/прода): серверная верификация Privy access-token (JWKS, ES256) на /api/copy/*, адрес из verified claims. Демон НЕ запускать unattended на публичном эндпоинте до фикса. ecosystem.copy-trader.js теперь DB-driven (SUBS_URL+SERVICE_TOKEN+FOLLOWER), НЕ запущен. Чейн UI(Privy)→БД→демон→копия собран. Для теста: вписать SERVICE_TOKEN в ecosystem на Малайзии→pm2 start (supervised). DW=19.63 pUSD. Также прошлый прогон: live e2e тест с филлами (orderID'ы live, капы сработали), 2 фикса (MIN_NOTIONAL $1, лог success/fail).server-rust/src/privy.rs верифицирует Privy access-token (ES256 против JWKS auth.privy.io/api/v1/apps/<app_id>/jwks.json, кэш OnceCell, iss=privy.io+aud=app_id)→sub=DID; copytrade::authed_user=SIWE-сессия ИЛИ verified Privy Bearer, X-User-Address УБРАН; фронт-хук шлёт Authorization: Bearer getAccessToken(). user_address в copy_subscriptions теперь = Privy DID (не кошелёк). Проверено: X-User-Address→401, битый токен→401. Rust пересобран+рестарт, фронт собран+деплой. Демон copy-trader LIVE на Малайзии (pm2, copy-loop.mjs --name copy-trader --interpreter-args '--experimental-global-webcrypto', env LIVE=1/SUBS_URL=https://poly-dev.szhub.space/api/copy/active/SERVICE_TOKEN=COPY_SERVICE_TOKEN/FOLLOWER=did:privy:cmq45iuzf00mx0cl2xtt1vxf1). Лог: detection LIVE mode=WS leaders=0 (DB-driven), ws connected. ⚠️ ecosystem.copy-trader.cjs (poly-exec type:module), но pm2 берёт имя из файла→ЗАПУСК ПРЯМОЙ командой (не через ecosystem-файл). E2E проверено вставкой подписки в БД (data/screener.db): демон прочитал по FOLLOWER-DID + применил config (ценовой фильтр priceMin/Max, allocValue→размер). DW Rick DID=did:privy:cmq45iuzf00mx0cl2xtt1vxf1, wallet 0xE2D892…633d3F, DW 0x50A8061e… ~19.6 pUSD. ⚠️ОСТАЛОСЬ: реальный UI-клик (нужен браузер-логин Rick) — backend-auth готов, демон ждёт подписку. Капы: env потолки MAX_NOTIONAL=$2/MAX_OPEN=5; UI config может только НИЖЕ.top_traders (routes.rs) сортировал по total_volume БЕЗ фильтра свежести → наверх лезли киты-гиганты, переставшие торговать (lastSeen до 9 дней), у них WR 0/NULL → лента выглядела сломанной. ФИКС: добавил recency-фильтр last_seen >= datetime('now','-{days} days') (дефолт 7 дней; ?days=N, days=0=all-time). Теперь топ = активные (lastSeen 4-8 июня) с реальным WR (72%/64%/48%…). Фронт WhalesPage.tsx уже рисует NULL-WR как «—» + «актив. N назад» — не трогал. Коммит. Лидеры=крупные киты ≥$5k (НЕ скальперы — Rick их и не видел, правильно). Rick может сменить подписку (текущий кит 0xf9c1…39e2 реальный но спящий) → демон подхватит нового.fixed→allocValue$ на сделку; percent→allocValue% от БЮДЖЕТА (pUSD-баланс DW, читается viem при старте + раз в 60с, budget в copy-loop); proportional→COPY_FRACTION от нотионала кита. size=target/price, потом пол CLOB-min-shares+MIN_NOTIONAL и кап per-leader maxNotional (≤ env MAX_NOTIONAL потолок $2). Юнит-тест ОК (fixed$5→$5, percent20%×$20→$4); null при потолке $2 на ценах >$0.40 — корректный constraint (5шт×0.4=$2), не баг. Демон лог: budget=$19.63. Текущая подписка Rick=кит 0xc1a9273b…e2db (percent 2%, спорт-направленный, но ~40ч не торгует). Чтобы режимы выражали бОльшие суммы — поднять env MAX_NOTIONAL (сейчас $2 для безопасности теста).usePolymarketAuth.isConnected (Privy-юзера не пускал→лок «Подключите кошелёк») + адрес портфеля=стейл weather Safe 0x3643… (VITE_POLY_FUNDER). ФИКС: удалил баннер+CustodyCard, гейт→Privy authenticated, portfolioAddress→deposit-wallet 0x50A8061e… (VITE_DEPOSIT_WALLET override) где реально лежат копи-позиции. Билд+деплой. Портфель DW сейчас: 2 позиции (Solana Down 10sh, Bitcoin Down 5sh) с прошлого live-теста, обе резолвнулись в $0 (P&L −$1.95 — это были 5-мин скальп-рынки, почему и плохие таргеты). usePolymarketAuth больше не юзается в TradePage. ⚠️ i18n «Подключите кошелёк» текст не трогал (теперь = войти по email).usePolymarketAuth.isConnected→Privy authenticated, адрес портфеля VITE_POLY_FUNDER(стейл weather Safe)→deposit-wallet 0x50A8061e… (VITE_DEPOSIT_WALLET). (4) i18n pf.connectTitle/Desc «Подключите кошелёк»→«Войдите по email». (5) PWA workbox +skipWaiting+clientsClaim+cleanupOutdatedCaches (кеш не залипал, «не обновляется»). (6) PrivyAccount: кнопка «Настроить торговый кошелёк» горела всегда (safeStatus локальный, сброс при reload) → показывать «✅ Торговый кошелёк готов» когда isDelegated(из Privy-объекта, надёжно без RPC) ИЛИ safeStatus==='done'; + mount-detect Safe deployed+approved (RPC getCode+checkAllApprovals — Safe 0x7570 подтверждён задеплоен+все апрувы OK). Все собраны+задеплоены. Демон copy-trader LIVE на Малайзии следит за подпиской Rick (кит спящий). DW 19.63 pUSD, 2 убыточные тест-позиции (5-мин скальп-рынки резолв $0).index.html отдавался no-cache, а sw.js (text/javascript) — БЕЗ кеш-заголовка → браузер ревалидировал старый sw.js, новый билд (даже skipWaiting) не активировался. ФИКС: main.rs SPA-middleware теперь no-cache также для sw.js/registerSW.js/manifest.webmanifest/workbox-* (хешированные ассеты остаются кешируемыми). Подтверждено заголовком + Rick увидел свежий билд («✅ Торговый кошелёк готов» появилось). ⚠️ для ПЕРВОГО раза нужен ручной clear site data (старый sw.js застрял), дальше само. TopBar: старый RainbowKit ConnectButton (всегда «Кошелёк», wagmi не юзается) → Privy-aware: разлогинен→«Войти» (Privy login() email), залогинен→«👤 .wallet-cta (accent pill). usePolymarketAuth-блоки (Sign to Trade/Ready) мёртвые при Privy (isConnected всегда false) — не рендерятся, оставлены. Аккаунт-страница=MorePage /more. PrivyAccount фикс кнопки «готов»: показывать при isDelegated||safeStatus==='done' (надёжно из Privy-объекта). Все билды+деплой.sort=activity→last_seen (routes.rs); LeadersPage.tsx: таб «Активность» добавлен И сделан ДЕФОЛТНЫМ (useState('activity')) → свежие киты сверху (решает «все дохлые»). Порядок табов: Активность/Оборот/Win-rate/Сделки. (3) карточка: подвал теперь «актив. N · макс $X» (t.largestTrade — уже в Trader-типе+API). Rust ребилд+фронт билд+деплой. TopBar-кнопка «👤 serg5585» подтверждена в проде. recency-фильтр 7д остаётся./positions?user=DW&redeemable=true, редимить через relayer (CTF.redeemPositions / NegRiskAdapter, executeDepositWalletBatch server-signed как approve-dw) → коллатерал pUSD возвращается на DW. Нужен ресёрч redeem-метода в builder-relayer-client SDK + новый node-executor скрипт + интеграция в copy-loop + ончейн-тест. ⚠️ Фронт TradePage уже имеет buildRedeemParams+handleRedeem но это СТАРЫЙ wagmi-флоу (ручной, для Privy/DW не работает) — авто-редим строить заново server-side. (2) Портфель: общий БАЛАНС кошелька — добавить pUSD-баланс DW (viem read) в саммари TradePage (есть totalValue/totalPnl/redeemableValue в useMemo line 130; portfolioAddress=DW 0x50A8061e…). Итого=кэш(pUSD)+позиции. (3) Портфель всегда актуальный — периодический refresh (setInterval refreshKey ~30с). Все 3 — TradePage.tsx + node-executor. Подтверждено LIVE: демон скопировал 5 реальных позиций с кита 0xc1a9 (спорт/теннис, ~$10, mixed P&L), цепочка доказана end-to-end с реальным китом+филлами.node-executor/redeem-dw.mjs — Data API redeemable-позиции DW → батч CTF/NegRiskAdapter redeemPositions(USDC.e,0x0,conditionId,[1,2]) через relayer executeDepositWalletBatch (server-signed Privy, как approve-dw). Запуск на DE (релеер не геоблочен, builder-sign localhost:3240; .env.privy в родит.папке — fallback existsSync). ДОКАЗАНО ОНЧЕЙН: STATE_CONFIRMED (редимнул 2 проигранные Down, $0; на выигрыше вернёт коллатерал USDC.e). CRON каждые 15 мин на DE: */15 * * * * cd .../node-executor && node redeem-dw.mjs >> /home/app/redeem-cron.log. ⚠️ редим даёт USDC.e (CTF-коллатерал), не pUSD — для реторговли нужен wrap (позже). DRY=1 только листит. (2) Портфель TradePage: карточка «Баланс» = pUSD-баланс DW (viem readContract pUSD 0xC011a7E…), первая в summary. (3) авто-рефреш portfolio каждые 30с (setInterval→setRefreshKey). Билд+деплой. Демон копитрейда жив, 5 позиций с кита 0xc1a9.0x93070a847efEf7F70739046A929D47a521F5B8ee, wrap(address asset,address to,uint256 amount) — из рабочего weather-bot wrap (executor.py:480, баланс $1.90→$46.90). Грабли weather-bot (gas 500k, nonce pending+retry) на релеер не относятся (релеер сам шлёт). DRY ок (редим 1 Lisa Pigato, wrap USDC.e=$0). ⚠️ Живой wrap НЕ протестирован — USDC.e нигде нет (weather EOA $4=НАТИВНЫЙ USDC 0x3c499…, не USDC.e 0x2791…); сработает авто на первом выигрыше. Cron 15мин на DE теперь делает редим+wrap. ПОЛНЫЙ ЦИКЛ: копия→выигрыш→редим(USDC.e)→wrap(pUSD)→снова в торговлю. Компоненты доказаны (Onramp wrap в WB, relayer-batch в redeem/approve).0x50A8061e… баланс ~$10.49 pUSD + ~$10 в позициях (P&L +$4.35). Cron редим+wrap 15мин на DE (редим доказан ончейн; wrap ждёт первого выигрыша). Всё закоммичено/запушено. NEXT: 1) почистить MEMORY.md (76KB→<24KB, старьё в activity/) 2) навести порядок на серваке (логи, временные скрипты node-executor, dev-процессы) 3) опц. карточка «Всего» в портфеле + поднять MAX_OPEN.022bfb4/7d70780/cb43e70, skill v8.3, детали→skill+brain]: AI deepseek-v3.2→v4-pro (3 места). 🔑 Reddit JSON=403 на ЛЮБОЙ UA (IP-блок)→RSS /.rss 200 OK (нет score→scheduler фолбэк мягкий). Источники: −TheBlock(мёртв) +Bankless/DLNews/CryptoBriefing/AMBCrypto (9 живых). +3 формата eli5/prediction/why_matters (11 всего, веса=1.0, ~17%, ТОЛЬКО ротация не автодетект). 🔑 ГРАБЛЯ Conflict 409 после pm2 restart 1.5+мин=накладка long-poll→лечится stop→0 процессов bot.py→start (не restart). GIT: репо был локальный→завёл приватный github.com/Zserg5585/alphapulsexp (токен из ~/.git-credentials), master запушен.afebbfa..31dcfdf pushed, детали→skill+brain]: 4 активных канала (typical-kz стоп: config enabled:false+гард в bot.js cron). 🔑 ГРАБЛЯ: роутинг по channel.type (news→RSS / humor+earnings→AI-original), источники из БД db.getApprovedSources НЕ из config (migrateSources сидит 1 раз при пустой таблице→config.sources=no-op, новые=INSERT в sources); scrape-тип не реализован. Анти-мета усилен (END_META_PATTERNS+callAIValidated 1 ретрай). B1 живые промпты, B2 ротация источников (shuffle в fetchNews), B4 гибрид dengi (50% финновости RSS+50% AI). Рубрики: 💱 Курс валют (special-content getCurrencyPost, Нацбанк rates_all.xml, слот morning, db.getKZDate() экспортирован) + 📊 Опрос дня (getPoll+sendPoll, слот night, AI+статичный FALLBACK_POLLS). TODO: PINUP_LINK пуст=монетизация спит.241d2fa/ea9ad29/b8f09d9/dfd13de, детали→skill+brain]: Клички двуязычные (WHALE_NICKNAMES {ru,en}, whaleCodename(label,addr,lang), 5 вызовов; i18n паритет 266=266). Карты поз: ВСЕ киты сделки (useLeaderHoldings→массив, дедуп по адресу, «🐋 N в этой сделке» pf.whalesIn)=консенсус. Маркеры входов на графике рынка: GET /api/screener/market/{id}/whale-entries (JOIN whale_trades×copy_subscriptions active, ключ screener_markets.id=whale_trades.market_id) + PriceChart LWCv5 createSeriesMarkers (не setMarkers), BUY▲зел/SELL▼крас «🐋 кличка цена». 🔑 покрытие: наши киты лишь на ~96 active-рынках (vs 1323 у всех)→на большинстве 0 маркеров=НОРМА (Rick: пока только наши). TODO: скрытая «Анализ пользователей» рядом с Builder Analytics.ee58b7f/ba8f0de/15cbf66/c10369c/c10d155, детали→skill+brain 13 Jun]: Гейт 13/30 PF 0.83. Профиль 14 китов (win_rate-колонка бесполезна→avgBuy/fav% из whale_trades), снято 5 (вкл lifetime −$124k 84cb17a5), вернул 0346afae (после паузы +$23 на 12x, открыта до паузы=by design)→10 активных. Окно замера A(14)→B(10). Фичи: (1) position-card ended→по redeemable (не endDate); (2) статус archived=«Стоп» архивирует не удаляет→Лидеры 🟠«копировался ранее»; (3) попап «+N исходов» (GET /api/screener/events/{id}/outcomes)=конец слива трафика; (4) «🐋 кличка держит $X» на картах поз=useLeaderHoldings матч по conditionId БЕЗ касания демона (Вариант B; C=точный вход через демон ПОСЛЕ гейта); (5) клички WHALE_NICKNAMES в whaleCodename. Грабли: data/ в gitignore, Data API режет urllib→curl+UA, cargo=$HOME/.cargo/bin.docs/BETA_LAUNCH_PLAN.md, детали→skill «Прод-запуск» + brain 12 Jun]: Цель Rick: ОДИН прод-грейд продукт→тест на реальной→прод ~неделя. Прод-гейт=6 критериев. Сделано+задеплоено: Фаза 2 онбординг (2.1a-d: useDepositWallet/dwApprovals.ts/PrivyAccount Safe→DW/бэкенд user_wallets+POST /api/copy/wallet+active JOIN) + фундинг крипто (2.5a депозит/2.5b вывод) + 4.1 risk-дисклеймер. Security=вариант A (политика на делегата, orders-only verifyingContract in [exchangeV2/negRiskV2], спроектирована+проверена живым Privy API; ⚠️ Privy не заходит в массив Call[]). Гейт эджа идёт (data/edge-measurement/measure.mjs, окно openedAt≥1781231224, baseline PF 0.73; ~14-16 Jun PF>1.0 на≥30). 🔑 ПРАВИЛО: НЕ менять торговую логику демона/НЕ применять политику до гейта. Осталось ПОСЛЕ гейта: демон мультиюзер (2.2-2.4)+применить политику A (1.3). Legal отложен но в уме (R1 Polymarket аудитит копитрейд-апы, R2 adviser-регистр Канада→строить не-дискреционно; docs/LEGAL_RISK.md, нужен юрист). Билдер-фи→$10k=объём не сделки.e618c3c/9fe6bf4/a9c83c7/da2db71/a100da5]: Единый утиль client/src/utils/whales.ts. Аватар=категория-глиф (⚽🗳️₿) на цвете стиля (реальные Polymarket-авы забракованы). Бейджи: стиль whaleStyle (🎯направл/⭐фаворит-фарм/⚡активный по avgBuy+sellRate из top-traders API) + горизонт whaleHorizon (⏱️/📆/🐢 по сделок/день) на Leaders+MyCopies+профиль. 🔒 Анонимизация (продукт публичный): юзеры видят Whale #N (whaleCodename), НЕ адрес; реальный identity (address/pseudonym/profile_image) только в whale_wallets admin-side. Адрес убран из URL → роут /whale + router state. Метка «🟢 на реале» (/api/copy/pnl). Сортировки MyCopies (active/P&L/открытые/копии). 🔑 Свежесть Лидеров: refresh_tracked_whales() в run_whale_scan бэкфилит копи-ростер+топ-40 (15/цикл, троттл) — раньше неоткрытые киты были стейл (scan берёт общую ленту, полную историю тянул только backfill_whale на открытии). Win Rate 0% = норма (только по resolved-сделкам, UI «(N res.)»). Грабля: unused import (TS6133)→всегда npm run build. Детали→skill+brain 12 Jun.fec525c/8b49fba/267e423/eb92115/cfd2d48/8118049]: DW 0x50A8061e…=копи-счёт, его P&L=табель. Наш winrate 27% vs стейтед китов 72%→эдж течёт. Утечки: (1) 1 кит 0x2c335066 −$16.50/6=63% убытков; (2) 0/47 mirror-exit (досиживали до резолва); НЕ латентность. Фиксы (copy-loop.mjs, Малайзия): per-whale stop-loss LEADER_KILL_USD=$8; проактивный mirror-exit в reconcile (фетч /positions?user=<leader>, 2-цикловой leaderExitSeen vs флак, гейт MIRROR_EXIT_LIVE, деплой observe→LIVE; 5 выходов забанкованы); ростер 16→12 (пауза 5 слабых+фаворит-фарм, +1 направленный, copy_subscriptions.status, демон читает /api/copy/active). UI: SELL realized в History (realized_pnl_by_key, SELL по txHash-asset); Leaders идентиконы + метка «на реале» (/api/copy/pnl, снапшот in-memory). Критерии отбора: PnL>$15k, WR≥58%, avgBuy 0.35–0.78 (главный), крипто<30%, ≤4д, ≥30. TODO: пере-замер PF через 3-5д перед масштабом; опц. реальные аватарки+стиль-бейджи (backend); потом прод-готовность. Детали→skill «PolyCopy диагностика»+brain 11 Jun вечер.routes.rs+клиент PnlDashboard/TradeHistory. (1) 696f5c2 Net always-actual: live mark-to-market из Data API /value?user= каждый запрос (фетч ДО conn — rusqlite !Send), totalPnl=sold+redeemed+currentValue−bought. (2) 724c2f0 карточка сводится: показывать unrealized=totalPnl−totalRealizedPnl, НЕ валовое «Открыто». (3) c614072 Кривая капитала: бары-по-датам путали с «Дневной P&L» → SVG-sparkline (vectorEffect=non-scaling-stroke). (4) b60ff67 винрейт по СДЕЛКАМ (закрытие SELL/REDEEM с |realized|>0.005), не по дням: 12W/32L=27%. (5) 20c285a карточку «Комиссии $0» (мёртвая) → Profit Factor + avgWin/avgLoss (PF 0.79). (6) 6de696f 🔑 losing REDEEM в Data API /activity = usdcSize/size/price=0, realizedPnl=null → UI показывал $0; helper redeem_pnl_by_market реплеит trade_history (ключ conditionId) → убыток красным, бейдж .th-redeem-loss серый→красный. Деплой каждый: cargo build + npm build (tsc -b обязателен) + pm2 restart polymarket-screener. Грабля: cd ../client из server-rust=sandbox boundary violation. Детали→skill «Портфель P&L»+brain 11 Jun.wss://ws-live-data.polymarket.com отдаёт 429 на WS-handshake с датацентр-IP (Cloudflare throttle) → демон mode=WS бесконечно реконнектил, детект мёртв, 0 копий при живом бюджете+китах. Не наш бан — мгновенный 429 со ВСЕХ IP (Малайзия v4+v6 + главный сервер Ванкувер; curl + реальный ws). Endpoint живой (426 plain GET=норма), подписка правильная. Data API REST работает → WS с server-IP структурно мёртв. 🔑 POLL-фоллбэк был сломан вдвойне: опрашивал [...LEADERS][0] (env), но демон DB-driven (LEADER='', киты в activeLeaders) → флип POLL=1 опросил бы undefined. Фикс 1649a8d (запушен): tick() опрашивает ВСЕ activeLeaders через Data API Promise.allSettled, per-leader курсоры, приминг каждого кита (baseline, историю НЕ копирует). Канон node-executor/copy-loop.mjs→rsync→POLL=1. Конфиг (Rick): POLL_MS 15→8с (5с отверг: 12×12=144>100/мин кап Data API→429 и на REST; 8с=90/мин), MAX_OPEN 8→10, MAX_OPEN_PER_LEADER 1→2. 🪤 ГРАБЛЯ: pm2 namespaced-конфиг бьёт инлайн-env — MAX_OPEN=10 инлайном не применялся (pm2 set copy-trader:MAX_OPEN 8 в ~/.pm2/module_conf.json инжектится поверх); fix pm2 set …MAX_OPEN 10+рестарт; «не слушается» env → чекать pm2 conf. Health-check: резолв+redeem корректны — closedReason верно, realizedPnl считается (XLG win +$4.14); redeem-крон НА ГЛАВНОМ сервере */15 * node redeem-dw.mjs >> /home/app/redeem-cron.log работает (заклеймил $6 XLG+$5 Málaga→pUSD). Realized −$16.02/38 (16 zero=старый баг, деньги целы). Ledger-фиксы (stop→атомарно→restart, бэкап): Germany/Curaçao ложно closed но on-chain держится $0.28→reopened cost0.27; бэкфилл cost 3 legacy (Argentina1.89/Haiti0.90/Knicks-84cfff1.90 из Data API size×avgPrice). Ростер: БД=data/screener.db (НЕ server-rust/data). Фильтр направленных (PnL>$5k,WR≥55%,avgBuy0.25-0.85,крипто<30%,7д,≥20)→12 прошло,11 уже копируем (валидация). +2 в copy_subscriptions: 0x2fa0ad4b…($33.5k/78%WR,⚠️тих с1июн)+0xde9f7f4e…($8.7k/57%WR). Демон→leaders=15. ⚠️ out-of-band правка positions.json на живом демоне=race→stop первым. Детали→skill+brain «сессия 7».positions.json status=open vs Data API /positions = on-chain холды). Копнув разницу: (1) 🔑 Баг #6 drpc false-zero (HIGH, теряет деньги): reconcile закрывал позу на ОДНОМ balanceOf=0, но drpc round-robin'ит ноды → отстающая отдаёт ложный 0 (грабля «чек на 2 RPC») → Spread: Argentina ($1.98) закрыт resolved-onchain-absent при 9sh на кошельке. Фикс: 2-й RPC pub2 (RPC2, дефолт publicnode), подтвердить 0 ПЕРЕД close, иначе keep+retry. Коммит 0904f02. Иронично: только что закрыли reconcile от флака Data API через on-chain, а сам on-chain чек флакнул RPC. (2) Восстановил 2 сирот (Argentina $1.98 + Haiti $0.97) флипом closed→open в ledger (guard лечит будущее, прошлое — руками); лидер обоих 0x204f72f3 лудик на паузе → доедут до резолва. open 4→6. (3) History UI: вкладка рендерит /activity микс TRADE+REDEEM, у REDEEM нет side/price → выглядел мусором 0sh @ 0¢. Фикс TradeHistory.tsx: бейдж Погашение·выигрыш($>0)/·проигрыш($0), i18n th.redeem/win/loss, CSS .th-redeem-win/loss. Дубли в ленте = 1 ордер об N мейкеров (норма). Коммит fd04b37. (4) 🔑 2 пред-существующих краша клиента (из b417558, НЕ мои — git подтвердил): WhalesPage юзал tr() без useT() (t затенён map) → краш стр. Киты; WalletBrowserBanner импорт ../../i18n→../i18n. Коммит fff3cb5. ⚠️ УРОК (повтор сессии 3): vite build/rolldown НЕ type-чекает → гонять npm run build(tsc -b &&…) перед деплоем клиента. Деплой клиента = пересборка + pm2 restart polymarket-screener (index.html вмораживается Vec::leak при старте). Все 3 коммита запушены. Детали → skill секция «Продолжение сессии 6».copy-loop.mjs+copy-exec.mjs, 5 багов найдено+починено+задеплоено. 🔑 Корень 2 из них — нет сериализации read-modify-write positions.json: (1) HIGH lost-update — reconcileOpenPositions держал стейл-pos через МЕДЛЕННЫЕ on-chain await readContract, потом savePos поверх → затирал свежий buy, прилетевший на await → запись позиции исчезала (ордер on-chain есть, в ledger нет → SELL не находит → закрыть нельзя). (2) MED TOCTOU — WS on('message',async) не ожидается → два трейда параллельно проходят MAX_OPEN/dup до сейва → превышение капов/дубль. Фикс: withPos() промис-мьютекс вокруг ВСЕХ мутаций ledger + reconcile split phase1(on-chain чтения БЕЗ лока)/phase2(lock+reload+патч still-open). Только in-process — достаточно (единственный живой писатель positions.json = демон; нет redeem-крона/2го процесса; resync-ledger ручной). Ещё: (3) HIGH неатомарная запись savePos→tmp+rename (краш=коррупция=re-buy storm+сироты); (4) MED таймаут AbortSignal.timeout(15s) на reconcile/pnl fetch; (5) LOW toSec() нормализация timestamp (openedAt сейчас секунды ✓, латентно к ms). Чисто: copy-exec, copytrade.rs (IDOR закрыт, конфиг клампится), env (FOLLOWER=DID Rick активен). Коммиты 4f06964+862ff77 запушены. Деплой rsync+pm2 restart copy-trader, демон LIVE leaders=14, ledger цел. Детали → skill секция «Баг-аудит копитрейда (сессия 6)».reconcileOpenPositions видит balanceOf>0 → не закрывает. Сегодня 2 дуста лудика заняли слоты. Ручная очистка (node-скрипт пометил closed в positions.json, лудик на паузе) → 5→3 open. Фикс: MAX_OPEN_AGE_S (env, 24ч) в copy-loop — absent из Data API + onchain>0 + старше 24ч → close resolved-worthless-aged. Безопасно для долгих холдов (живые позы держат value→остаются в Data API→первая ветка). rsync+рестарт Малайзия. Слоты: 3/8 open, budget $13.57, maxNotional=$3. Детали → skill секция «Авто-освобождение зависших слотов (сессия 5)».clob-client-v2 на Малайзии → мимо бэкенда. УРОК: копи-исполнение идёт мимо Rust-бэкенда — серверные фичи UI-пути (фи/лимиты/логи/атрибуция) к копи-ордерам НЕ применяются, дублировать в copy-exec/copy-loop. Фикс: builderConfig:{builderCode:'0x3c829d51…7952d5'} в конструктор ClobClient (copy-exec.mjs) — SDK сам цепляет код. rsync+рестарт. Подтверждено: копи-сделка Jun9 11:51 $2.20 fee $0.011 попала в аналитику. «Active Users 1→2» = НЕ человек, а уникальные maker-адреса (weather Safe + DW, оба Rick). taker fee ~0 до 10июн. Также: кнопка «Обновить приложение» (SettingsPage→Данные) — caches.delete()+unregister SW+reload (старая «Reset PWA» не чистила Cache Storage → reload отдавал старый бандл). Детали → skill секция «Builder-код + PWA force-update (сессия 4)». ⚠️ TODO ещё не сделан: tsc --noEmit в build (rolldown не type-чекает).MAX_NOTIONAL $2→$3 (при $2 резалось всё дороже цены 0.40 из-за CLOB min 5sh×цена≤кап→skip over-cap; киты заходят 0.46–0.63), MAX_OPEN_PER_LEADER 1→2, MAX_OPEN=8 ($24≤бюджет $27.60). Inline-env рестарт Малайзия + синк ecosystem.copy-trader.cjs + pm2 save. (2) Убрал весь ручной redeem-UI с Portfolio (авто-редим серверный): карточка/вкладка/баннер REDEEMABLE, кнопка Redeem, wagmi-хуки. (3) P&L-вкладка чинилась дважды — корень: Data API /activity поля ≠ схеме (transactionHash/usdcSize/timestamp-unix, НЕ id/amount/createdAt). Кеш trade_history НИКОГДА не наполнялся (if id.is_empty(){continue} пропускал всё). Фикс: хелпер cache_activity_rows() (id=txHash-asset, REDEEM→conditionId; amount=usdcSize; ISO timestamp), portfolio_summary сам фетчит+кеширует. Realized P&L считаю сам (average-cost реплей по conditionId: BUY копит, SELL/REDEEM реализуют; payout=$0=убыток). DW: realized +$2.33, 48 trades/28 markets, winRate 50%. (4) History-вкладка: тот же маппинг в хуке usePortfolioActivity. (5) Вкладка «Ещё» падала: PrivyAccount.tsx юзал useT() без импорта. ⚠️ ГРАБЛИ: npm run build (Vite/rolldown) НЕ делает type-check — пропущенный импорт = зелёная сборка + рантайм ReferenceError. Детали → skill polymarket-screener секция «Portfolio P&L / History / вкладки (сессия 3)».0x204f72f3 (kill-ludik.mjs sellAll на Малайзии, +$3.28 спасено, DW→$27.60 pUSD), он на паузе. Диагноз «киты молчат»: демон ловит их на WS, но режет skip price 0.99 outside band 0.05-0.95 — скупают фаворитов по $0.96–0.99, band 0.95 отсекает (это правильно — фаворит-фарм = низкий эдж). Профилировал 11 текущих по Data API (avg buy price): на паузу 6 фаворит-фармеров (0d2e f3ce 4699 6982 e7bd 5409, status='paused' НЕ delete), оставил 5 направленных (f396 f883 6db5 c1a9 eed5). Нашёл+включил 6 новых направленных (SQL whale_wallets⨝whale_trades: pnl>$5k, avgPx 0.25–0.85, mid≥55%, crypto<30%; верифиц. Data API): c44f432b(+$80k) 2c335066(+$72k) 84cfffc3(+$66k) 1eaf5d5f(+$41k) 38337de2(+$24k) 84cb17a5(+$18k). Изменения = состояние БД copy_subscriptions (не код). Метод+грабли → skill polymarket-screener секция «Копитрейд — ростер китов (9 Jun)». ⚠️ sqlite3/better-sqlite3 на серваке нет → python3.i18n/translations.ts+useT(), ~25 файлов обёрнуто, дефолт=автодетект браузера, ручной выбор сохраняется). timeAgo/timeUntil тоже локализованы. Бейдж 📋 копируемых китов на Лидерах + сортировка по P&L. Грабли (t-shadowing→alias tr, модульные массивы→labelKey, import в тело функции) → skill polymarket-screener секция 09 Jun. Все коммиты запушены.MAX_OPEN_PER_LEADER=1 (кит≤1 поза, был баг — 1 лудик 0x204f72f3 занимал все 5 слотов, 394 копии других зарезаны), MAX_OPEN→10. On-chain сверка реконсайла: перед закрытием слота читать CTF.balanceOf(DW,tokenID) ERC1155 (был дрейф 8 ончейн ≠ 5 реестр — Data API флакает и теряет held-позиции→ложные resolved-onchain-absent). Топап +$4: native USDC→USDC.e (Uniswap V3 fee100)→pUSD (Onramp), gasless relayer, DW $9.71→$13.71. Хелперы swap-usdc.mjs/wrap-asset.mjs/resync-ledger.mjs. Коммиты f6a30ac..77511ca запушены. [9 Jun сессия 1] Per-event кап (MAX_PER_EVENT=1) + строка PnL на «Мои копии». Демон copy-trader LIVE на Малайзии (~/poly-exec), DW Rick 0x50A8061e…F24Ff ~$13.71 pUSD + 8 позиций. Полная сага → memory/polymarket-copytrading.md.activity/2026-06.md./activity деп-кошелька (sell/redeem ивенты) по каждой закрытой копии. Также: Вариант B = честный дележ бюджета по китам (сейчас только слоты делятся, не деньги).d01c771/2f651dd pushed]: (1) бэкфилл 145 закрытых копий Rick в copy_positions (миграция импортила только 8 открытых) → My Copies realized +16→+27.44, closed 28→174, тег source_trade_id='backfill-malaysia-20260615' (откат). (2) Атрибуция «кто взял» = Вариант B (только активн.подписки+кто СЕЙЧАС держит); демон НЕ копирует неподписанных (/api/copy/active status=active). (3) +2 кита (Ideal/Elderly), Sociable-Rooster убран (бэктест 30д под наш конфиг PF 0.24). (4) Фаза B ✅: позиционный PnL/honest winrate (4 поля *_pos в whale_wallets, update_positional_stats нетто по conditionId, в /top-traders); чинит артефакт 100%. (5) Фаза E ✅ (c0f9aeb/270772b): бэктест-эндпоинт /api/signals/whale/{addr}/backtest (hold-to-resolution, win→size*(1-p)/p) + UI-бейдж 🎯 PF на LeadersPage (useBacktests); Ideal 1.62/Sociable 0.24/Elderly 1.64. NEXT: D(гейт recency/consistency)→Флаги ⭐→F(TG, отдельный бот). План docs/WHALE_DISCOVERY_PLAN.md.762276f/b38e474/8ecd44f pushed]: аудит — clippy✅0/tsc✅0/29 .mjs✅; ESLint клиента 18(react-hooks v7)→0 в 3 чанка. Паттерны: set-state-in-effect→derive; reset-on-prop→adjust-during-render; immutability→reduce; t→deps. 🔑 ГРАБЛЯ preserve-manual-memoization падает на optional-chaining в deps useCallback→вынести в плоскую var. only-export→context/hook в *Context.ts. Демоны+Rust НЕ тронуты, git only (не деплоил).0a62a24..24e9b94 pushed, план docs/FRIEND_BETA_PLAN.md]: мультиюзер self-serve. Все кодовые блоки готовы+задеплоены: A мультиюзер-демон copy-loop-mu.mjs (инстанс copy-trader-mu, per-user BUY/SELL+reconcile+PnL, ledger copy_positions); B депозит (DepositPanel.tsx USDC+QR+статус, deposit-watch.mjs авто native→USDC.e→pUSD); C per-user портфель (authed GET /api/copy/wallet); E privy-policy.mjs orders-only (НЕ применён); F1 health-check-mu.mjs TG-алерты; G1 дисклеймер-гейт per-DID (CopyConfigModal). Страница Кошелёк W1-W3: /wallet (WalletPage)=фандинг-вью (обёртка PrivyAccount+сводка Доступно/В позициях/Всего), чип шапки 👛 $X (кэш pUSD)→/wallet.f40bb3c..92b7bb9 pushed]: страница /analytics/users (admin-only). User=email(+адрес мелким), Privy DID-юзеры теперь апсёртятся в users (email+last_login+geo IP ip-api), белый флаг🏳️→—. Таблица лидеров обогащена из whale_wallets: клички pseudonym(1545/3342)+Win%/PnL/Volume/Trades/Category. Клик-сортировка обеих таблиц (sortRows null-вниз+SortTh, client-only). Статы юзера Open/Closed/Notional/Realized из live-снапшота copy_pnl. 🔑 ГРАБЛЯ: rusqlite conn !Send → copy_pnl.read().await в начале хендлера ДО pool.get(), иначе Axum future-not-Send. Ops: задан JWT_SECRET (pm2 set). Итог строки Rick: subs11/open8/closed133/notional$25.71/realized+$9.95.d6b6727..245935f pushed]: прошли ВЕСЬ путь нового юзера на 2-м реальном акке (sergiizapolskyi, DID cmqel7uqa…, DW 0x8b95…): рег→активация→депозит $10 USDC→авто-конверт pUSD→подписка→LIVE-копия исполнилась (~$2.80), изоляция OK. 5 багов чинены: relay-client 0.0.6→0.0.10 (activate wallet падал deriveDepositWalletAddress); утечка PnL чужого юзера→LEGACY_PNL_USER env-гейт; deposit-watch lowercase→canonical Privy addr; изолированный copy-exec-mu.mjs; UX. Автономка reboot-safe: copy-trader-mu LIVE+MIRROR_EXIT_LIVE=1 (Malaysia, pm2 save); deposit-watch cron 3мин (главный); health-check-mu cron 15мин (Malaysia, TG creds в .env.health); pm2-startup на обоих.measure.mjs]: PF 1.30 на 81 закрытой копии, realized +$21.17 (старт 0.83). Разблокирует USER_EOA + Privy-политику A + миграцию на mu. PF держат 0x0346af+$17/0x224a89+$12.ac80b1f..d514a1a pushed]: Чанк1 ✅ USER_EOA — copy-exec.mjs поддержка USER_EOA/opts.eoa + USER_EOA=0xe2d8…3d3f живому copy-trader (budget=$35.85). 🚨 Грабля: pm2 start *.cjs = запуск как СКРИПТ → ВСЕГДА pm2 start copy-loop.mjs --name copy-trader --interpreter node --node-args=... + ПОЛНЫЙ инлайн-env. Чанк2 Privy-политика A: креды кэш per-EOA (clob-creds-<eoa>.json 0o600 gitignored). Политика xq797h4uovkjp5k3tybo3sjb (verifyingContract∈[ExchangeV2/NegRisk]). 🔑 3 ОГРАНИЧЕНИЯ Privy: (1) политика per-wallet, привязка через клиентский addSigners({signers:[{signerId,policyIds}]}) user-present (сервер не может, updateSigner нет); (2) conditions матчат только verifyingContract/chainId; (3) ClobAuthDomain без verifyingContract→креды ДО политики. Спека→docs/PRIVY_POLICY_SPEC.md.copy-trader-mu ЕДИНСТВЕННЫЙ демон, ОБА акка (Rick cmq45… dw 0x50a8 budget$35.85 ledger8 + tester cmqel7… dw 0x8b95 budget$4.25 ledger5). Импорт 8 открытых Rick из positions.json→copy_positions, стоп старого copy-trader (pm2 save). Verify: ledger=13/2 юзера, reconcile НЕ закрыл живые. Старый copy-loop.mjs/copy-trader БОЛЬШЕ НЕ ИСПОЛЬЗУЕТСЯ. 🐛 4 позиции «mirror-close rejected: invalid token id» ждут резолва.96b8496/e042b97/8dd1b41]: orders-only Privy-политика авто-в-активацию. Q1c PrivyAccount эффект: при walletReady+credsReady+не-привязано(localStorage policy_attached_v2:<did>) навешивает политику. 🔑 addSigners НЕ обновляет policyIds existing-делегата → removeSigners({address})+addSigners({signers:[{signerId,policyIds:[id]}]}), защитно. getWallet: оба кошелька overridePolicyIds=[xq797…], делегат kc34… цел. Сервер ТОЛЬКО торгует (Exchange ALLOW), вывод DENY. Креды кэш ДО политики (иначе ClobAuth DENY).3519b63..4787b59 pushed]: Q1-политика сломала авто-редем (redeem через executeDepositWalletBatch = тот же Batch-домен что вывод). A client-side redeem dwRedeem.ts+useDepositWallet.redeemResolved. C НЕВОЗМОЖЕН: Privy policy ethereum_typed_data_message НЕ ходит в calls[] («Type Call[] not found»). B ВЫБРАН (9c68add/d90f542/4787b59): снять политику с делегата → сервер редемит (redeem-шаг в deposit-watch cron 3мин). 🚨 ИНЦИДЕНТ: авто-detach каждую загрузку → Privy rate-limit → делегат Rick ПОТЕРЯН (funds целы), Rick восстановил кнопкой «Активировать». 🔑 УРОК: не делать auto-detach signers на каждой загрузке; делегат-без-политики ставить 1 раз при активации. Rick kc34→[NO POLICY], pUSD $64.53, авто-редем cron ✅. Тестер ещё с политикой [xq797…].pm2 restart polymarket-screener). Был $0-портфель: новый клиент дёргал GET /api/copy/wallet, старый бинарь 405. БД=data/screener.db.wrap_usdc_to_pusd() через Onramp. Gas=500000 (estimation fails)ProxyFactory.proxy()py-clob-client → py-clob-client-v2. API diff: create_or_derive_api_key(), cancel_order(), Side.BUYlive_only=not DRY_RUNget_transaction_count('pending') + retry loop (3 attempts)outcome='win' AND dry_run=0 + if not trade_row: continueactual_cost = shares * price вместо signal size1 - model_prob — analyzer уже даёт P(YES)cleanup_old_forecasts(7) при каждом сканеZoneInfo(city_tz) для days_aheadpysocks нужен в venv для SOCKS supportBUILDER_CODE в OrderArgs. Builder Profile "SZHub" на polymarket.com/settings?tab=builder. Fee cooldown 7 дней между изменениямиsize_matched, _reconcile_cancelled_positions() on-chain CTF sверкаhas_cancelled_for_market() guard в executor.py. 6c670c2Onramp.wrap(asset,to,amount) (0x93070a847…) принимает ТОЛЬКО USDC.e (0x2791…), НЕ нативный USDC (0x3c499…). Fix: swap native→USDC.e через Uniswap V3 fee=100 pool (SwapRouter02 0x68b3465833…), потом wrap. Всё gasless через relayer executeDepositWalletBatch (DW без MATIC). Скрипты swap-usdc.mjs+wrap-asset.mjs (главный сервер, не Малайзия — нужен builder-sign localhost:3240). relayer ПРОПУСКАЕТ произвольные таргеты (Uniswap router ok)./positions флакает — теряет held-позиции. copy-loop reconcileOpenPositions() закрывал слот по отсутствию в Data API >grace → ложные resolved-onchain-absent (позиция вернулась). Дрейф реестра (8 ончейн ≠ 5 демон) → недосчёт экспозиции против MAX_OPEN. Fix: перед закрытием читать CTF.balanceOf(DW,BigInt(tokenID)) ERC1155 (0x4D97DCd97…), закрывать только при ончейн-нуле, RPC-err→keep+retry. Ретроактивный ресинк: resync-ledger.mjs. af0e084MAX_OPEN_PER_LEADER (env, дефолт 1) — фильтр в BUY по образцу MAX_PER_EVENT. f6a30acpub.readContract на drpc может попасть на отстающую ноду → ложный 0 → resolved-onchain-absent на живой позе ($ застревает on-chain). Fix: подтверждать 0 на ВТОРОМ независимом RPC (pub2, publicnode) перед close; ненулевой/ошибка → keep open + retry. НЕ retry на том же drpc (round-robin = снова та же нода). 0904f02pos через медленные on-chain await → затирал параллельный buy. Fix: split phase1 (чтения без лока) / phase2 (withPos() lock + reload + патч still-open). savePos→tmp+rename атомарно. Мьютекс только in-process (единственный живой писатель = демон). 862ff77vite build/rolldown НЕ делает type-check → битый импорт/undefined переменная уходит в коммит зелёным, краш в рантайме (страница белеет). Fix: гонять npm run build (tsc -b && vite build) перед деплоем. Деплой клиента = пересборка + pm2 restart polymarket-screener (index.html вмораживается Vec::leak при старте → старые хеши ассетов иначе). Повтор грабли сессии 3..cjs ecosystem НЕ парсится pm2 start как config (type:module в package.json → pm2 копирует в .js→ESM-падение). Fix: запускать демон напрямую pm2 start copy-loop.mjs --name copy-trader --interpreter node --node-args="--experimental-global-webcrypto" с env инлайном (SERVICE_TOKEN и пр.).wss://ws-live-data.polymarket.com 429 на WS-handshake с датацентр-IP (Cloudflare throttle) — мгновенный 429 со ВСЕХ server-IP (не наш бан), бесконечный reconnect, детект мёртв. Fix: POLL=1 (Data API REST /trades?user=, работает с server-IP). POLL tick() должен опрашивать activeLeaders (НЕ LEADERS[0] — демон DB-driven). 12 китов/8с=90 req/мин < кап 100/мин (5с=144 пробил бы кап).pm2 set name:KEY val) переопределяет инлайн-env старта — хранится в ~/.pm2/module_conf.json, инжектится как env (и JSON-blob name={…}). Симптом: переменная «не слушается» инлайн-env (напр. MAX_OPEN застрял на 8). Fix: pm2 set name:KEY newval+рестарт; диагностика pm2 conf / cat ~/.pm2/module_conf.json.positions.json на ЖИВОМ демоне = race (нет межпроцессного лока, withPos только in-process → внешний python-скрипт не координируется). Fix: pm2 stop copy-trader → атомарная правка (tmp+rename) → pm2 restart (сохраняет env из stopped-состояния). Бэкап перед правкой.fetch() для w≥20, Bottleneck только w≤10x > lastX + 2 pxpriceChangeSameWindow из oiHistdedupKey = subType:SYM/stream депрекейтнут → /market/streamserver/ имеет свой package.json → npm install в обе папки--lowvram в ComfyUIfree_vram() — вызов /free API между Phase 1→2--use-sage-attention удалён из всех скриптов). PyTorch SDPA+FlashAttention2 почти та же скорость.print() зависает в 8KB буфере, dashboard не видит прогресс. Fix: sys.stdout.reconfigure(line_buffering=True) в main()VHS_LoadVideoPath (STRING input, без валидации)toomanyrequests|rate limit в grep детектор ошибок runner.shgifs, потом images