Пульс: сервер закрыт полностью — кроме симуляции добавила поиск токена (/curvedex/enso/tokens?q=USDC → адрес, символ, decimals). Списка токенов в коде нет и не будет: ищем по символу или адресу прямо у Enso, чтобы «любой токен» был правда любой, а не из захардкоженной десятки.
Осталась вёрстка вкладки и отправка транзакции. Продолжаю.
31 июля 2026
Как сделано по твоим пунктам:
• Любой токен — поиск по символу или адресу прямо у Enso, списка токенов в коде нет и не появится. Нюанс всплыл на проверке: с фильтром «базовые токены» их API прячет настоящий WETH за полусотней одноимённых пустышек (первым шёл 0x45Bc0118…, у него маршрута нет вовсе). Фильтр убрала — канонический идёт первым.
• Потери — считаю сама, у них не беру: priceImpact во всех ответах ноль. Беру стоимость входа и стоимость полученных LP по ценам обоих токенов. В примере вышло +0.11% — LP дороже входа, поэтому плюс; при потере пишется 0.17% (−$6.42). Наведение на цифру показывает «было $4 994.65 → стало $5 000.05».
• Stake LP — галочка меняет цель маршрута на гейдж, третьим шагом идёт curve-gauge:deposit. Одна транзакция вместо двух, газ 1474k против 726k.
• Slippage — 0.1 / 0.5 / 1 / 3%, выше 5% сервер не пропускает вообще, и отдельно предупреждаю, если потери больше 1%.
• Пока считается маршрут (на USDT это ~13 секунд), поля пишут «quoting…», а не молчат прочерками.
Чего НЕТ, чтобы не выдавать желаемое: баланса и кнопки MAX в этой вкладке — сумма вводится руками, потому что для произвольного токена мы балансы не читаем. Надо — добавлю чтением баланса по выбранному адресу.
И вопрос по вкусу, тут решаешь ты: сейчас Zap стоит вторым в ряду Deposit · Zap · Stake · Deposit & Stake. Если логичнее первым или последним — скажи, переставлю.
Справедливо, я сделала половину привычного и назвала это «поиском». Как обычно — это три вещи вместе: список из кошелька с балансами, поиск по имени и вставка контракта. У меня пока только вторая и третья.
Почему так вышло, честно: чтобы показать «что у тебя в кошельке», надо перебрать балансы токенов на выбранной сети — у нас такого перебора нет ни в одной вкладке, там везде монеты конкретного пула. Это отдельная работа, а не строчка.
В виджете Enso список кошелька есть — он тянет балансы сам. Но виджет на React, мы от него отказались, значит балансы нужно делать своими руками. Делается так: берём список токенов сети → пачкой читаем балансы через multicall → показываем непустые, отсортированные по стоимости. Одна прогрузка на подключение кошелька, дальше из кэша, отзывчивость не страдает.
Если добро — доделываю до нормального вида: сверху токены с балансом (с суммами и MAX), ниже поиск по имени/контракту как сейчас.
Ты прав, и я зря сказала «такого перебора у нас нет» — он есть. Нашла в коде: на Swap выбор токена рисуется из общего списка токенов с балансами, отсортированными по стоимости, с иконками и поиском по имени/адресу. Балансы читает общая функция чтения балансов кошелька со своим кэшем — ровно то, что нужно Zap.
Значит вторую механику писать не надо: переиспользую эту же — модалка со списком «сначала то, что у тебя есть, с суммами», плюс поиск. Моё дополнение останется только одно: если токена нет в нашем списке, добираю его по адресу или символу у Enso, чтобы «любой токен» не упирался в наш перечень.
Делаю и приношу скрин.
Готово, v20260731k — выбор токена в Zap теперь тот же самый, что на Swap.
Что сделано
• Кнопка токена открывает ту же модалку Select Token: список из твоего кошелька сверху, отсортированный по стоимости, с балансом и суммой в $, иконка, адрес, число пулов. Второй механики не завёл — доработала существующую, она просто узнаёт, что её позвал Zap.
• Поиск по символу и по адресу — родной, из этой же модалки.
• Если токена нет ни в одном пуле Curve (в списке его не будет), запрос уходит роутеру и он появляется в той же выдаче. Проверила на BNB 0xB8c7…dD52: находится, выбирается, маршрут строится — 0x:swap → curve-dex:deposit, 742k gas.
• Под полем — 25 / 50 / 75 / MAX от баланса выбранного токена; на MAX по нативной монете оставляю немного на газ. Строка Balance: кликабельна, это тоже MAX.
• Добавила паузу перед обращением к роутеру: при быстром вводе адреса летело под сорок запросов за секунду, упиралось в лимит и выдача приходила пустой. Теперь один запрос на паузу в наборе.
Нашла кое-что, решай ты. Строка Route loss считается по ценам роутера, и на BNB она показала +4.18% — то есть будто вход дешевле выхода. Замер: 1 BNB по их цене 588.47 $, на выходе 607.96 LP по 1.0084 $ = 613.08 $. Разрыв не в маршруте, а в их ценовом фиде: цена BNB отстаёт от той, по которой реально идёт своп. Показывать пользователю «+4%» — врать про выгоду. Как поступаем:
1. оставить как есть, это редкий случай;
2. при «выгоде» больше процента писать n/a — pricing unreliable вместо цифры.
Мне ближе второе: цифра, которой нельзя верить, хуже прочерка. Но это твоё поле — скажи, и сделаю.
И висит с прошлого раза: где в ряду ставим вкладку — Deposit · Zap · Stake · Deposit & Stake (сейчас так) или сдвинуть.
Сделано, v20260731l. На BNB строка теперь: +4.08% (+$23.9874) · pricing unreliable, цифра приглушена. В подсказке при наведении — почему: вход 588.50 $, выход 612.49 $, выход дороже входа = фид по этому токену отстаёт от рынка, ориентируйся на Minimum received. Порога в процентах нет: помечаю любую «выгоду». Проверила на живом сайте, .eth-зеркало опубликую вместе со следующей правкой.
Принято, делаю обратный zap в Withdraw — выход из LP в один любой токен.
Сразу разграничу, чтобы не дублировать то, что уже есть: Single Coin в Withdraw — это родной Curve, выход в монету ИЗ СОСТАВА пула, и трогать его я не буду, он дешевле по газу. Новое — выход в токен, которого в пуле нет вовсе, через тот же роутер. Начну с замера: умеет ли он брать на вход LP и, отдельно, застейканный в гейдж LP — если умеет, выход из позиции будет одной транзакцией без ручного анстейка. Вернусь с числами.
Готово, v20260731o — обратный zap на боевом и в .eth-зеркале.
Где — Withdraw, третий режим рядом с Balanced и Single Coin: Any Token. Выбор токена — та же модалка, что в Zap и на Swap.
Что показывает (замеры на pyUSD/crvUSD, 100 LP): выход 101.95 USDC, минимум 101.44, маршрут curve-dex:redeem → grapher:swap, 742k gas. В BNB на 500 LP: 0.807 BNB, минимум 0.8029, маршрут через kyberswap, 753k.
Три вещи, которые всплыли по дороге и которые я сделала:
1. Из гейджа выходить можно одной транзакцией. Роутер принимает на вход адрес гейджа: маршрут curve-gauge:redeem → curve-dex:redeem → swap, 677k gas. Пока не подключала — сейчас вкладка работает от свободных LP, как и остальной Withdraw. Скажешь — добавлю галочку «взять из гейджа», и анстейк отдельным шагом станет не нужен.
2. В zap не было апрува — ни в депозите, ни здесь. Для ERC20 роутер тянет токен из кошелька, без разрешения транзакция откатится; работал бы только вход нативной монетой. Добавила общий шаг: проверка разрешения, при нехватке — сначала апрув, потом маршрут, газ по нашему правилу (оценка × 1.5, без фиксированных лимитов). Подписать я не могу — первым, кто нажмёт, будешь ты, и это первая же вещь, которую стоит проверить кошельком.
3. Порог для pricing unreliable — не выдуманный процент. На стейбле «выгода» вылезает и в 0.04% — это просто округление, и постоянная плашка обесценила бы предупреждение. Теперь помечаю только когда мнимая выгода больше собственного допуска маршрута (разрыв между «получишь» и «минимум»). Проверила: USDC +0.04% — без пометки, BNB +4.02% — с пометкой.
Отдельно, честно: тот же запрос 100 LP → USDC в двух прогонах с интервалом в четверть часа дал 100.74 и 101.95 — разброс больше процента при одинаковом маршруте. Гарантия — только строка Minimum received, «получишь» это оценка роутера. Поэтому на втором прогоне и загорелась пометка.
Агент ГаммаГотово, v20260731o — обратный zap на боевом и в .eth-зеркале.
Где — Withdraw, третий режим рядом с Balanced и Single Coin: Any Token. Выбор токена — та же модалка, что в Zap и на Swap.
Что показывает (замеры на pyUSD/crvUSD, 100 LP): выход 101.95 USDC, минимум 101.44, маршрут curve-dex:redeem → gr
Добавь галочку, не лишним будет.
Готово, v20260731p (боевой + .eth). Галочка Take LP from the gauge (no separate unstake) в режиме Any Token.
Проверено переключением на живой странице, 100 LP → USDC:
• снята — curve-dex:redeem → grapher:swap, 347k gas;
• поставлена — curve-gauge:redeem → curve-dex:redeem → grapher:swap, 642k gas.
Заодно подстроились подпись и лимиты: строка баланса меняется на Staked:, пресеты 25/50/75/MAX считаются от застейканного, и кнопка блокируется по нему же, а не по свободному LP. Галочка появляется только у пулов с гейджем и сбрасывается при уходе из режима.