From 9cd294d243ab565fe5161f30928581b91e393b0a Mon Sep 17 00:00:00 2001 From: Johan le Roch Date: Fri, 9 Aug 2024 16:05:38 +0200 Subject: [PATCH] Merge develop to master (#327) * add status to strateiges list Signed-off-by: belbazanas * update amplifyOrder documentation link (#195) Signed-off-by: belbazanas * fix strategies list status Signed-off-by: belbazanas * Plug Incentives api wip * save update after refill progress Signed-off-by: belbazanas * end points * enable the menu * fix build * edit kandel strategy + re-open Signed-off-by: belbazanas * Add community points and boosts informations into Page points * remove re-fill row + fix build Signed-off-by: belbazanas * Update form legend and reward display, fix information banner text, and redirect after successful edit Signed-off-by: belbazanas * Refactor leaderboard table and use-table components * Remove console.log statements and improve boost page * Add pagination to leaderboard * Points page: Tables loading improvements, separate user table from leaderboard table and add link to doc * add total count of traders * add kandel smart router in UI + fixes (#197) * Update strategy type to smart in multiple files Signed-off-by: belbazanas * update mangrove sdk and indexer,add strategy smart router hooks, add new kandel type, update default values Signed-off-by: belbazanas * update overall logics types for build Signed-off-by: belbazanas --------- Signed-off-by: belbazanas * fix strategies list value + minor text changesB (#198) Signed-off-by: belbazanas * Fix/asana kandel fixes 1 (#199) * fix strategies list value + minor text changesB Signed-off-by: belbazanas * fix total inventory and update strategies row click redirection Signed-off-by: belbazanas --------- Signed-off-by: belbazanas * Fix/edit kandel strategy (#200) * fix edit strategy hook + decimals in dialogs Signed-off-by: belbazanas * remove logs Signed-off-by: belbazanas --------- Signed-off-by: belbazanas * add metadatas and change points banner text * Refactor all strategies page to use no. of offers instead of no. of price points * Fix spread calculation in orderbook.tsx to avoid negative values * fix level if the user is level 5 * Remove unused code related to priceRatio (#202) * Remove unused code related to priceRatio Signed-off-by: belbazanas * redirect to edit strategy from strategy list Signed-off-by: belbazanas --------- Signed-off-by: belbazanas * remove the junk * fix indexer sdk (#204) * Fix/minor kandel fixes (#205) * Update button labels in EditStrategyDialog and useForm Signed-off-by: belbazanas * Update parameters table to display step size and locked bounty Signed-off-by: belbazanas * Update history and parameters components Signed-off-by: belbazanas * Update launch strategy button label to Publish Signed-off-by: belbazanas * Add source icon for pacFinance Signed-off-by: belbazanas --------- Signed-off-by: belbazanas * Update close strategy dialog message (#206) Signed-off-by: belbazanas * Fix bounty deposit validation (#207) Signed-off-by: belbazanas * Fix/kandel closed strategies (#208) * Update leaderboard table, change header from Return (%) to PnL (%). Update lockedBounty display in parameters table. Signed-off-by: belbazanas * Remove AverageReturn component from PriceRange Signed-off-by: belbazanas --------- Signed-off-by: belbazanas * diable strategies Signed-off-by: belbazanas * Update table headers, disable close strategy if no live offers, remove wrong tooltips (#213) Signed-off-by: belbazanas * Remove console.log statements Signed-off-by: belbazanas * show boosts (#215) Co-authored-by: Johan le Roch Co-authored-by: Anas * Fix/points volume message (#216) * show boosts * show nft boosts * show boost value returned by /points endpoint * fix zod conversion error * show message * revert points update message --------- Co-authored-by: Johan le Roch * Update navbar.tsx, disable strategies in production * enable strategies tab on staging Signed-off-by: belbazanas * Add warning banner component to strategy layout Signed-off-by: belbazanas * Update warning banner close button styling Signed-off-by: belbazanas * Fix typo in base deposit error message Signed-off-by: belbazanas * Add market selector component and update info bar component, testing feeback fixes Signed-off-by: belbazanas * Update useForm hook to reset form fields when market changes Signed-off-by: belbazanas * update strategy warning banner message Signed-off-by: belbazanas * fix build Signed-off-by: belbazanas * Update 'No. of offers' to 'Nb. of offers' in various components Signed-off-by: belbazanas * Do workaround to merge nft and volume points on the FE * Add usePnL hook and update components to display pnl data Signed-off-by: belbazanas * Fix build issue * Refactor use-parameters and unrealized-pnl components Signed-off-by: belbazanas * Refactor useParameters function to handle pnlQuote and returnRate with market symbol Signed-off-by: belbazanas * bump mangrove.js (#229) * Update navbar.tsx * Add useResolveWhenBlockIsIndexed hook to useEditKandelStrategy (#224) Signed-off-by: belbazanas * enable strategies on staging Signed-off-by: belbazanas * review gasreq for minvolume on kandel strategies Signed-off-by: belbazanas * Feat/withdrawable inventory (#233) * Add withdrawable balance feature Signed-off-by: belbazanas * pnl fix * change namming * Fix inventory order in parameters component Signed-off-by: belbazanas * Fix withdrawal button disabled logic Signed-off-by: belbazanas * fix withdraw balance button disabling condition Signed-off-by: belbazanas * remove logs Signed-off-by: belbazanas * Fix display issue for closed pnlQuote and returnRate Signed-off-by: belbazanas --------- Signed-off-by: belbazanas Co-authored-by: Johan le Roch * fix withdraw balance format Signed-off-by: belbazanas * fix distribution reactivity Signed-off-by: belbazanas * Update warning banner styling and functionality Signed-off-by: belbazanas * Update pnlQuote and returnRate values Signed-off-by: belbazanas * hide pnl value Signed-off-by: belbazanas * Add parametersHistory schema and update related components Signed-off-by: belbazanas * Fix display issue in useParametersTable and update steps in EditStrategyDialog Signed-off-by: belbazanas * remove logs Signed-off-by: belbazanas * epoch on tables * fix * fix texts * fix gas issues * Fix edit LO orders + Refactor code to fix display issues Signed-off-by: belbazanas * Feat/strategy liquidity sourcing (#241) * add LS to new kandel strategy Signed-off-by: belbazanas * add liquidity sourcing in edit, hide liquidity sourcing infos waiting for sdk Signed-off-by: belbazanas * Fix liquidity sourcing token allowance query + Refactor code Signed-off-by: belbazanas --------- Signed-off-by: belbazanas * update SDK to overestimate gas estimation for kandels Signed-off-by: belbazanas * fix chart * fix token symbol on price range chart * Enable from the start the liquidity sourcing fields in strategies/new component Signed-off-by: belbazanas * remove unused code Signed-off-by: belbazanas * fix edit strategy useForm hook to set default values Signed-off-by: belbazanas * Feat/epoc leaderboard (#251) * WIP * end epoch leaderboard * adapt zod epoch model * Hide boost column from total tab * chore: Refactor use-liquidity-sourcing.ts to use react-query for data fetching Signed-off-by: belbazanas * epoch / leaderboard * fix build * refactor points page * chore: Refactor strategies list search input component and add sorting functionality Signed-off-by: belbazanas * save wip Signed-off-by: belbazanas * chore: Refactor use-parameters.ts to handle upcoming values for pnlQuote and returnRate Signed-off-by: belbazanas * update pnpm * Update volumes and boost to use new API (#254) * Add new data for boosts/volumes * Use volume not points for MS1 banner * Revert "Update volumes and boost to use new API (#254)" (#256) This reverts commit 64831ae664017b40796d76e6efbf42cfb29a878f. * Fix/volumes and boosts (#255) * Add new data for boosts/volumes * Use volume not points for MS1 banner --------- Co-authored-by: Daniel <16984675+DanielRX@users.noreply.github.com> * call the price api and delay the indexer sdk until the usdb prices are fetched (#253) * temporary remove liquidity sourcing Signed-off-by: belbazanas * update edit base/quote deposit inputs decimals Signed-off-by: belbazanas * fix nextjs version * Feat/new sdk kandel (#260) * feat: new sdk * progress * feat: continue * new sdk - save wip Signed-off-by: belbazanas * new sdk - save wip Signed-off-by: belbazanas * new sdk - save wip Signed-off-by: belbazanas * new sdk wip market/limit orders Signed-off-by: belbazanas * new sdk - retract order Signed-off-by: belbazanas * update new sdk, chores Signed-off-by: belbazanas * new sdk save wip Signed-off-by: belbazanas * new sdk - project building and limit/market orders working :) Signed-off-by: belbazanas * new sdk - kandel wip Signed-off-by: belbazanas * new sdk - kandel wip Signed-off-by: belbazanas * new kandel - fix build Signed-off-by: belbazanas * new kandel - fix build Signed-off-by: belbazanas * Market simulation estimatedFrom send input * compute estimation from receive field * new kandel - fix creation Signed-off-by: belbazanas * kandel - save wip Signed-off-by: belbazanas * end market order refactor + refresh balances * wip market / limit refactor * new sdk edit kandel Signed-off-by: belbazanas * new sdk fix build Signed-off-by: belbazanas * fix build Signed-off-by: belbazanas * remove frozen lock file Signed-off-by: belbazanas --------- Signed-off-by: belbazanas Co-authored-by: Maxence Raballand Co-authored-by: belbazanas * remove amplifed orders (#263) * remove amplifed orders Signed-off-by: belbazanas * Update join-program-banner.tsx --------- Signed-off-by: belbazanas * fix kandel page display Signed-off-by: belbazanas * fix kandel page display Signed-off-by: belbazanas * fix kandel creation Signed-off-by: belbazanas * fix kandel creation Signed-off-by: belbazanas * fix kandel market selector Signed-off-by: belbazanas * fix build Signed-off-by: belbazanas * add error message in post market order Signed-off-by: belbazanas * add table to vaults list Signed-off-by: belbazanas * vault ui implementation Signed-off-by: belbazanas * fix build Signed-off-by: belbazanas * vault UI enhancements Signed-off-by: belbazanas * fix logics icons + delete unused code Signed-off-by: belbazanas * fix default limit order price Signed-off-by: belbazanas * fix default limit order price bug Signed-off-by: belbazanas * feat: list * kandel fix: display offers in price range chart Signed-off-by: belbazanas * feat: add page * feat: advance * feat: advance * add vault dialogs Signed-off-by: belbazanas * vault remove liquidity dialog update Signed-off-by: belbazanas * temporary fix vaults list query Signed-off-by: belbazanas * temporary fix vault query Signed-off-by: belbazanas * kandel: fix price chart dots Signed-off-by: belbazanas * feat: advance * feat: advance * feat: advance * limit order: fix default price (#270) Signed-off-by: belbazanas * Fix/cancel limit order (#271) * limit order: fix default price Signed-off-by: belbazanas * limit order: fix cancel order Signed-off-by: belbazanas --------- Signed-off-by: belbazanas * fix: max amounts and errors in ABI - Added test Skate vault * Feat/base testnet (#272) * baseTestnet: remove old mgv sdk + comment amplified order files Signed-off-by: belbazanas * implement baseTestnet + faucet Signed-off-by: belbazanas * remove old sdk mergedOffers save wip Signed-off-by: belbazanas * BaseTestnet implementation wip Signed-off-by: belbazanas * kandel: remove error on first load Signed-off-by: belbazanas --------- Signed-off-by: belbazanas * Feat/base testnet (#273) * baseTestnet: remove old mgv sdk + comment amplified order files Signed-off-by: belbazanas * implement baseTestnet + faucet Signed-off-by: belbazanas * remove old sdk mergedOffers save wip Signed-off-by: belbazanas * BaseTestnet implementation wip Signed-off-by: belbazanas * kandel: remove error on first load Signed-off-by: belbazanas * remove last old SDK traces Signed-off-by: belbazanas --------- Signed-off-by: belbazanas * cleanup * zod schema for total points * navbar: remove posthog check for strategies Signed-off-by: belbazanas * Feat/base testnet (#276) * baseTestnet: remove old mgv sdk + comment amplified order files Signed-off-by: belbazanas * implement baseTestnet + faucet Signed-off-by: belbazanas * remove old sdk mergedOffers save wip Signed-off-by: belbazanas * BaseTestnet implementation wip Signed-off-by: belbazanas * kandel: remove error on first load Signed-off-by: belbazanas * remove last old SDK traces Signed-off-by: belbazanas * trade: refresh tabs on market update + remove amplified table Signed-off-by: belbazanas --------- Signed-off-by: belbazanas * feat: vault * Feat/strategy ls fixes (#277) * kandel: re-activate liquidity sourcing Signed-off-by: belbazanas * kandel: detail page wip Signed-off-by: belbazanas * kandel: remove strategyQuery from priceRange overview Signed-off-by: belbazanas * kandel: total inventory display, remove mangrove.jspackage Signed-off-by: belbazanas * trade: fix limit order default price Signed-off-by: belbazanas * kandel: fix edit workflow wip Signed-off-by: belbazanas * retractParams: add type Signed-off-by: belbazanas * kandel: fix retract offers Signed-off-by: belbazanas * kandel: fix edit strat Signed-off-by: belbazanas * kandel: strategies list save wip Signed-off-by: belbazanas --------- Signed-off-by: belbazanas * Fix build * kandel: refetch strategy list on close (#278) * kandel: refetch strategy list on close Signed-off-by: belbazanas * remove log Signed-off-by: belbazanas --------- Signed-off-by: belbazanas * fix computeReceiveAmount * fix computeSendAmount * Fix/last minutes fixes (#279) * kandel: refetch strategy list on close Signed-off-by: belbazanas * remove log Signed-off-by: belbazanas * kandel-trade: fixes Signed-off-by: belbazanas --------- Signed-off-by: belbazanas * remove logs Signed-off-by: belbazanas * fix parseUnits * trade: disable cancel offer Signed-off-by: belbazanas * add usde token logo * fix: change skate vault list (#280) * fix: change skate vault list * chore: revert lockfile change * trade: mute edit order Signed-off-by: belbazanas * vaul: minor changes Signed-off-by: belbazanas * vaul: minor changes Signed-off-by: belbazanas * vaul: remove Big.js in strategies Signed-off-by: belbazanas * ENG-268: Fix slider value calculation in Limit component (#293) * ENG-268: Fix slider value calculation in Limit component The commit fixes the calculation of the slider value in the Limit component. It now correctly calculates the value based on the send balance and send amount. * fix: market order slider inout Signed-off-by: belbazanas * refactor: minor refacto Signed-off-by: belbazanas --------- Signed-off-by: belbazanas Co-authored-by: belbazanas * strategy: enable close strategy in all cases (#297) * Feat/strategy current provision (#298) * improve initial zoom (#303) * improve initial zoom * cleaning some logs * cleaning some logs * try to fix top gap on layout with some extensions (#300) * eng-299: update sdk to display 4 decimals to USD prices (#302) * ENG-269: Fix percentage bar error (market) (#295) Co-authored-by: Johan le Roch * add blast token * update mgv sdk * Synapse Widget (#296) (#309) * Synapse Widget (#296) * add feedbacks Signed-off-by: belbazanas * update amplified tables after edit + feedbacks Signed-off-by: belbazanas * close sheet after edit dialog Signed-off-by: belbazanas * display errors in bottom amplifed form Signed-off-by: belbazanas * ui minor changes Signed-off-by: belbazanas * update mangrove sdk+ add expiry date in tables and sheet Signed-off-by: belbazanas * re-arrange the toast messages Signed-off-by: belbazanas * Debug kandel * fix errors * fixes * edit expiry date Signed-off-by: belbazanas * replace retracted by cancelled Signed-off-by: belbazanas * WIP dialog improvements * check if atleast one offer is open Signed-off-by: belbazanas * add chain id as a dependency to 'strategies' query * fix maxPrice * parameters values improvements * bounty tooltip * check if atleast one offer is open Signed-off-by: belbazanas * save wip Signed-off-by: belbazanas * unwrap eth v1 (#187) Signed-off-by: belbazanas * optimize orbit image * save wip Signed-off-by: belbazanas * invalidate offers query Signed-off-by: belbazanas * save wip Signed-off-by: belbazanas * save wip Signed-off-by: belbazanas * save wip Signed-off-by: belbazanas * add status to strateiges list Signed-off-by: belbazanas * update amplifyOrder documentation link (#195) Signed-off-by: belbazanas * fix strategies list status Signed-off-by: belbazanas * Plug Incentives api wip * save update after refill progress Signed-off-by: belbazanas * end points * enable the menu * fix build * edit kandel strategy + re-open Signed-off-by: belbazanas * Add community points and boosts informations into Page points * remove re-fill row + fix build Signed-off-by: belbazanas * Update form legend and reward display, fix information banner text, and redirect after successful edit Signed-off-by: belbazanas * Refactor leaderboard table and use-table components * Remove console.log statements and improve boost page * Add pagination to leaderboard * Points page: Tables loading improvements, separate user table from leaderboard table and add link to doc * add total count of traders * add kandel smart router in UI + fixes (#197) * Update strategy type to smart in multiple files Signed-off-by: belbazanas * update mangrove sdk and indexer,add strategy smart router hooks, add new kandel type, update default values Signed-off-by: belbazanas * update overall logics types for build Signed-off-by: belbazanas --------- Signed-off-by: belbazanas * fix strategies list value + minor text changesB (#198) Signed-off-by: belbazanas * Fix/asana kandel fixes 1 (#199) * fix strategies list value + minor text changesB Signed-off-by: belbazanas * fix total inventory and update strategies row click redirection Signed-off-by: belbazanas --------- Signed-off-by: belbazanas * Fix/edit kandel strategy (#200) * fix edit strategy hook + decimals in dialogs Signed-off-by: belbazanas * remove logs Signed-off-by: belbazanas --------- Signed-off-by: belbazanas * add metadatas and change points banner text * Refactor all strategies page to use no. of offers instead of no. of price points * Fix spread calculation in orderbook.tsx to avoid negative values * fix level if the user is level 5 * Remove unused code related to priceRatio (#202) * Remove unused code related to priceRatio Signed-off-by: belbazanas * redirect to edit strategy from strategy list Signed-off-by: belbazanas --------- Signed-off-by: belbazanas * remove the junk * fix indexer sdk (#204) * Fix/minor kandel fixes (#205) * Update button labels in EditStrategyDialog and useForm Signed-off-by: belbazanas * Update parameters table to display step size and locked bounty Signed-off-by: belbazanas * Update history and parameters components Signed-off-by: belbazanas * Update launch strategy button label to Publish Signed-off-by: belbazanas * Add source icon for pacFinance Signed-off-by: belbazanas --------- Signed-off-by: belbazanas * Update close strategy dialog message (#206) Signed-off-by: belbazanas * Fix bounty deposit validation (#207) Signed-off-by: belbazanas * Fix/kandel closed strategies (#208) * Update leaderboard table, change header from Return (%) to PnL (%). Update lockedBounty display in parameters table. Signed-off-by: belbazanas * Remove AverageReturn component from PriceRange Signed-off-by: belbazanas --------- Signed-off-by: belbazanas * diable strategies Signed-off-by: belbazanas * Update table headers, disable close strategy if no live offers, remove wrong tooltips (#213) Signed-off-by: belbazanas * Remove console.log statements Signed-off-by: belbazanas * show boosts (#215) Co-authored-by: Johan le Roch Co-authored-by: Anas * Fix/points volume message (#216) * show boosts * show nft boosts * show boost value returned by /points endpoint * fix zod conversion error * show message * revert points update message --------- Co-authored-by: Johan le Roch * Update navbar.tsx, disable strategies in production * enable strategies tab on staging Signed-off-by: belbazanas * Add warning banner component to strategy layout Signed-off-by: belbazanas * Update warning banner close button styling Signed-off-by: belbazanas * Fix typo in base deposit error message Signed-off-by: belbazanas * Add market selector component and update info bar component, testing feeback fixes Signed-off-by: belbazanas * Update useForm hook to reset form fields when market changes Signed-off-by: belbazanas * update strategy warning banner message Signed-off-by: belbazanas * fix build Signed-off-by: belbazanas * Update 'No. of offers' to 'Nb. of offers' in various components Signed-off-by: belbazanas * Do workaround to merge nft and volume points on the FE * Add usePnL hook and update components to display pnl data Signed-off-by: belbazanas * Fix build issue * Refactor use-parameters and unrealized-pnl components Signed-off-by: belbazanas * Refactor useParameters function to handle pnlQuote and returnRate with market symbol Signed-off-by: belbazanas * bump mangrove.js (#229) * Update navbar.tsx * Add useResolveWhenBlockIsIndexed hook to useEditKandelStrategy (#224) Signed-off-by: belbazanas * enable strategies on staging Signed-off-by: belbazanas * review gasreq for minvolume on kandel strategies Signed-off-by: belbazanas * Feat/withdrawable inventory (#233) * Add withdrawable balance feature Signed-off-by: belbazanas * pnl fix * change namming * Fix inventory order in parameters component Signed-off-by: belbazanas * Fix withdrawal button disabled logic Signed-off-by: belbazanas * fix withdraw balance button disabling condition Signed-off-by: belbazanas * remove logs Signed-off-by: belbazanas * Fix display issue for closed pnlQuote and returnRate Signed-off-by: belbazanas --------- Signed-off-by: belbazanas Co-authored-by: Johan le Roch * fix withdraw balance format Signed-off-by: belbazanas * fix distribution reactivity Signed-off-by: belbazanas * Update warning banner styling and functionality Signed-off-by: belbazanas * Update pnlQuote and returnRate values Signed-off-by: belbazanas * hide pnl value Signed-off-by: belbazanas * Add parametersHistory schema and update related components Signed-off-by: belbazanas * Fix display issue in useParametersTable and update steps in EditStrategyDialog Signed-off-by: belbazanas * remove logs Signed-off-by: belbazanas * epoch on tables * fix * fix texts * fix gas issues * Fix edit LO orders + Refactor code to fix display issues Signed-off-by: belbazanas * Feat/strategy liquidity sourcing (#241) * add LS to new kandel strategy Signed-off-by: belbazanas * add liquidity sourcing in edit, hide liquidity sourcing infos waiting for sdk Signed-off-by: belbazanas * Fix liquidity sourcing token allowance query + Refactor code Signed-off-by: belbazanas --------- Signed-off-by: belbazanas * update SDK to overestimate gas estimation for kandels Signed-off-by: belbazanas * fix chart * fix token symbol on price range chart * Enable from the start the liquidity sourcing fields in strategies/new component Signed-off-by: belbazanas * remove unused code Signed-off-by: belbazanas * fix edit strategy useForm hook to set default values Signed-off-by: belbazanas * Feat/epoc leaderboard (#251) * WIP * end epoch leaderboard * adapt zod epoch model * Hide boost column from total tab * chore: Refactor use-liquidity-sourcing.ts to use react-query for data fetching Signed-off-by: belbazanas * epoch / leaderboard * fix build * refactor points page * chore: Refactor strategies list search input component and add sorting functionality Signed-off-by: belbazanas * save wip Signed-off-by: belbazanas * chore: Refactor use-parameters.ts to handle upcoming values for pnlQuote and returnRate Signed-off-by: belbazanas * update pnpm * Update volumes and boost to use new API (#254) * Add new data for boosts/volumes * Use volume not points for MS1 banner * Revert "Update volumes and boost to use new API (#254)" (#256) This reverts commit 64831ae664017b40796d76e6efbf42cfb29a878f. * Fix/volumes and boosts (#255) * Add new data for boosts/volumes * Use volume not points for MS1 banner --------- Co-authored-by: Daniel <16984675+DanielRX@users.noreply.github.com> * call the price api and delay the indexer sdk until the usdb prices are fetched (#253) * temporary remove liquidity sourcing Signed-off-by: belbazanas * update edit base/quote deposit inputs decimals Signed-off-by: belbazanas * fix nextjs version * Feat/new sdk kandel (#260) * feat: new sdk * progress * feat: continue * new sdk - save wip Signed-off-by: belbazanas * new sdk - save wip Signed-off-by: belbazanas * new sdk - save wip Signed-off-by: belbazanas * new sdk wip market/limit orders Signed-off-by: belbazanas * new sdk - retract order Signed-off-by: belbazanas * update new sdk, chores Signed-off-by: belbazanas * new sdk save wip Signed-off-by: belbazanas * new sdk - project building and limit/market orders working :) Signed-off-by: belbazanas * new sdk - kandel wip Signed-off-by: belbazanas * new sdk - kandel wip Signed-off-by: belbazanas * new kandel - fix build Signed-off-by: belbazanas * new kandel - fix build Signed-off-by: belbazanas * Market simulation estimatedFrom send input * compute estimation from receive field * new kandel - fix creation Signed-off-by: belbazanas * kandel - save wip Signed-off-by: belbazanas * end market order refactor + refresh balances * wip market / limit refactor * new sdk edit kandel Signed-off-by: belbazanas * new sdk fix build Signed-off-by: belbazanas * fix build Signed-off-by: belbazanas * remove frozen lock file Signed-off-by: belbazanas --------- Signed-off-by: belbazanas Co-authored-by: Maxence Raballand Co-authored-by: belbazanas * remove amplifed orders (#263) * remove amplifed orders Signed-off-by: belbazanas * Update join-program-banner.tsx --------- Signed-off-by: belbazanas * fix kandel page display Signed-off-by: belbazanas * fix kandel page display Signed-off-by: belbazanas * fix kandel creation Signed-off-by: belbazanas * fix kandel creation Signed-off-by: belbazanas * fix kandel market selector Signed-off-by: belbazanas * fix build Signed-off-by: belbazanas * add error message in post market order Signed-off-by: belbazanas * add table to vaults list Signed-off-by: belbazanas * vault ui implementation Signed-off-by: belbazanas * fix build Signed-off-by: belbazanas * vault UI enhancements Signed-off-by: belbazanas * fix logics icons + delete unused code Signed-off-by: belbazanas * fix default limit order price Signed-off-by: belbazanas * fix default limit order price bug Signed-off-by: belbazanas * feat: list * kandel fix: display offers in price range chart Signed-off-by: belbazanas * feat: add page * feat: advance * feat: advance * add vault dialogs Signed-off-by: belbazanas * vault remove liquidity dialog update Signed-off-by: belbazanas * temporary fix vaults list query Signed-off-by: belbazanas * temporary fix vault query Signed-off-by: belbazanas * kandel: fix price chart dots Signed-off-by: belbazanas * feat: advance * feat: advance * feat: advance * limit order: fix default price (#270) Signed-off-by: belbazanas * Fix/cancel limit order (#271) * limit order: fix default price Signed-off-by: belbazanas * limit order: fix cancel order Signed-off-by: belbazanas --------- Signed-off-by: belbazanas * fix: max amounts and errors in ABI - Added test Skate vault * Feat/base testnet (#272) * baseTestnet: remove old mgv sdk + comment amplified order files Signed-off-by: belbazanas * implement baseTestnet + faucet Signed-off-by: belbazanas * remove old sdk mergedOffers save wip Signed-off-by: belbazanas * BaseTestnet implementation wip Signed-off-by: belbazanas * kandel: remove error on first load Signed-off-by: belbazanas --------- Signed-off-by: belbazanas * Feat/base testnet (#273) * baseTestnet: remove old mgv sdk + comment amplified order files Signed-off-by: belbazanas * implement baseTestnet + faucet Signed-off-by: belbazanas * remove old sdk mergedOffers save wip Signed-off-by: belbazanas * BaseTestnet implementation wip Signed-off-by: belbazanas * kandel: remove error on first load Signed-off-by: belbazanas * remove last old SDK traces Signed-off-by: belbazanas --------- Signed-off-by: belbazanas * cleanup * zod schema for total points * navbar: remove posthog check for strategies Signed-off-by: belbazanas * Feat/base testnet (#276) * baseTestnet: remove old mgv sdk + comment amplified order files Signed-off-by: belbazanas * implement baseTestnet + faucet Signed-off-by: belbazanas * remove old sdk mergedOffers save wip Signed-off-by: belbazanas * BaseTestnet implementation wip Signed-off-by: belbazanas * kandel: remove error on first load Signed-off-by: belbazanas * remove last old SDK traces Signed-off-by: belbazanas * trade: refresh tabs on market update + remove amplified table Signed-off-by: belbazanas --------- Signed-off-by: belbazanas * feat: vault * Feat/strategy ls fixes (#277) * kandel: re-activate liquidity sourcing Signed-off-by: belbazanas * kandel: detail page wip Signed-off-by: belbazanas * kandel: remove strategyQuery from priceRange overview Signed-off-by: belbazanas * kandel: total inventory display, remove mangrove.jspackage Signed-off-by: belbazanas * trade: fix limit order default price Signed-off-by: belbazanas * kandel: fix edit workflow wip Signed-off-by: belbazanas * retractParams: add type Signed-off-by: belbazanas * kandel: fix retract offers Signed-off-by: belbazanas * kandel: fix edit strat Signed-off-by: belbazanas * kandel: strategies list save wip Signed-off-by: belbazanas --------- Signed-off-by: belbazanas * Fix build * kandel: refetch strategy list on close (#278) * kandel: refetch strategy list on close Signed-off-by: belbazanas * remove log Signed-off-by: belbazanas --------- Signed-off-by: belbazanas * fix computeReceiveAmount * fix computeSendAmount * Fix/last minutes fixes (#279) * kandel: refetch strategy list on close Signed-off-by: belbazanas * remove log Signed-off-by: belbazanas * kandel-trade: fixes Signed-off-by: belbazanas --------- Signed-off-by: belbazanas * remove logs Signed-off-by: belbazanas * fix parseUnits * trade: disable cancel offer Signed-off-by: belbazanas * add usde token logo * fix: change skate vault list (#280) * fix: change skate vault list * chore: revert lockfile change * trade: mute edit order Signed-off-by: belbazanas * vaul: minor changes Signed-off-by: belbazanas * vaul: minor changes Signed-off-by: belbazanas * vaul: remove Big.js in strategies Signed-off-by: belbazanas * ENG-268: Fix slider value calculation in Limit component (#293) * ENG-268: Fix slider value calculation in Limit component The commit fixes the calculation of the slider value in the Limit component. It now correctly calculates the value based on the send balance and send amount. * fix: market order slider inout Signed-off-by: belbazanas * refactor: minor refacto Signed-off-by: belbazanas --------- Signed-off-by: belbazanas Co-authored-by: belbazanas * Synapse Widget * Custom Rpcs --------- Signed-off-by: belbazanas Co-authored-by: belbazanas Co-authored-by: Johan le Roch Co-authored-by: Mangrove Automation Bot <134297173+mangrove-automation@users.noreply.github.com> Co-authored-by: Maxence Raballand Co-authored-by: Daniel <16984675+DanielRX@users.noreply.github.com> * Add tab * switch to provider * Add blast as target chain * refactor bridge page to handle network unsupported by the dApp for bridging --------- Signed-off-by: belbazanas Co-authored-by: bigboydiamonds <57741810+bigboydiamonds@users.noreply.github.com> Co-authored-by: belbazanas Co-authored-by: Johan le Roch Co-authored-by: Mangrove Automation Bot <134297173+mangrove-automation@users.noreply.github.com> Co-authored-by: Daniel <16984675+DanielRX@users.noreply.github.com> * merge offers with same price on the orderbook * Fix/eng 242 (#313) * disable auto scroll when the user has scrolled * eng-242: disable auto scroll when the user has scrolled * Feat/eng 325 (#314) * eng-325 move bridge to drop down menu * rename bridge assets * Add custom switch chain dialog (#316) * WIP - Draft * refactoring * Refactor * add cronos * end mecanism * Dialog styling * end custom chain dialog * fix build * ENG-265: fix edit limit order (#299) * trade: fix edit limit order Signed-off-by: belbazanas * trade: save edit order wip Signed-off-by: belbazanas * trade: edit limit order wip Signed-off-by: belbazanas * add logs Signed-off-by: belbazanas * ENG-265: fix edit limit order Signed-off-by: belbazanas --------- Signed-off-by: belbazanas * ENG-267: update mangrove sdk to fix strategy min price points (#320) Signed-off-by: belbazanas * ENG-278: remove create strat when on passive strategy tab (#319) Signed-off-by: belbazanas * hide ms1 program banner (#322) * eng-326: add overlay (#323) * add return buttons to modal steps (#318) Signed-off-by: belbazanas * Feat/eng 354 (#325) * ENG-354: Remove smart kandel Signed-off-by: belbazanas * ENG-354: turn validateKandelParams deposit to true Signed-off-by: belbazanas * ENG-354: fix approval Signed-off-by: belbazanas * ENG-354: remove comments Signed-off-by: belbazanas --------- Signed-off-by: belbazanas * eng-359: clean and remove amplified orders everywhere (#329) * ENG-351: add arbitrum network (#328) Signed-off-by: belbazanas * fix arbitrum icon * Fix/eng 361 (#330) * eng-359: clean and remove amplified orders everywhere * wip / debug * refactoring / cleaning * improve number readability * cleaning * show depth chart even if it's one sided book (#332) * Fix/eng 366 (#333) * cleaning - wip * replace all useChainId by useAccount * remove nuqs * eng-367: fix add tooltip in orderbook sizes an total values (#331) * eng-367: fix add tooltip in orderbook sizes an total values Signed-off-by: belbazanas * eng-367: update sdk Signed-off-by: belbazanas --------- Signed-off-by: belbazanas * eng-371: fix wrong units (#334) * eng-371: fix wrong units * fix wrong unit * fix buil * fix number of offers (#335) * fix number of offers * cleanup * market order: fix not enough volume on book error when selling (#340) * market order: fix not enough volume on book error when selling Signed-off-by: belbazanas * remove unused logs Signed-off-by: belbazanas --------- Signed-off-by: belbazanas * eng-363: Hide passive strategy on arbitrum & add tooltip (#338) Signed-off-by: belbazanas * eng-358: update synapse network text (#337) Signed-off-by: belbazanas * eng-373: remove network (#341) * Fix limit orders (#342) * Fix limit orders * if GTC or PO, take into account the expiryDate * Fix edit order sheet * show detail in the confirm dialog --------- Signed-off-by: belbazanas Co-authored-by: Mangrove Automation Bot <134297173+mangrove-automation@users.noreply.github.com> Co-authored-by: belbazanas Co-authored-by: Maxence Raballand Co-authored-by: Daniel <16984675+DanielRX@users.noreply.github.com> Co-authored-by: bigboydiamonds <57741810+bigboydiamonds@users.noreply.github.com> --- app/bridge/_components/warning-banner.tsx | 4 +- app/faucet/_components/info-banner.tsx | 4 +- .../_components/table/components/actions.tsx | 4 +- app/referrals/services/index.ts | 4 +- .../_components/new-strategy-dialog.tsx | 93 ---- .../tables/strategies/hooks/use-strategies.ts | 5 +- .../(list)/_components/tables/tables.tsx | 29 +- .../tables/vaults/hooks/use-vaults.ts | 7 +- .../(list)/_providers/kandel-strategies.tsx | 58 -- app/strategies/(list)/layout.tsx | 9 +- .../price-chart/background-rectangles.tsx | 0 .../_components}/price-chart/cursor.tsx | 0 .../_components}/price-chart/custom-brush.tsx | 0 .../geometric-distribution-dots.tsx | 0 .../price-chart/geometric-offer-tooltip.tsx | 3 +- .../price-chart/merged-offer-tooltip.tsx | 5 +- .../price-chart/merged-offers-dots.tsx | 0 .../price-chart/mid-price-line.tsx | 0 .../price-chart/price-range-chart.tsx | 22 +- .../price-chart/range-tooltips.tsx | 10 +- .../price-chart/set-range-animation.tsx | 0 .../overview/table/use-offers-table.tsx | 4 +- .../_components/shared/price-range-infos.tsx | 2 +- .../[address]/_hooks/use-kandel-steps.ts | 5 - .../edit/_components/form/use-form.ts | 2 +- .../geometric-distribution-dots.tsx | 71 --- .../price-chart/geometric-offer-tooltip.tsx | 60 -- .../price-chart/merged-offers-dots.tsx | 62 --- .../price-chart/price-range-chart.tsx | 414 -------------- .../_components/price-range/price-range.tsx | 2 +- app/strategies/[address]/edit/layout.tsx | 5 +- app/strategies/[address]/layout.tsx | 13 +- .../new/_components/form/use-form.ts | 2 +- .../price-chart/background-rectangles.tsx | 107 ---- .../components/price-chart/cursor.tsx | 148 ----- .../components/price-chart/custom-brush.tsx | 227 -------- .../price-chart/merged-offer-tooltip.tsx | 84 --- .../components/price-chart/mid-price-line.tsx | 23 - .../components/price-chart/range-tooltips.tsx | 113 ---- .../price-chart/set-range-animation.tsx | 74 --- .../_components/price-range/price-range.tsx | 2 +- app/strategies/new/layout.tsx | 15 +- app/strategies/vault/_hooks/useVault.ts | 8 +- .../charts/depth-chart/depth-chart.tsx | 4 +- .../_components/forms/amplified/amplified.tsx | 511 ------------------ .../components/from-wallet-order-dialog.tsx | 209 ------- .../amplified/components/summary-step.tsx | 118 ---- .../_components/forms/amplified/enums.ts | 11 - .../hooks/amplified-liquidity-sourcing.ts | 87 --- .../forms/amplified/hooks/amplified-store.ts | 88 --- .../forms/amplified/hooks/use-amplified.ts | 387 ------------- .../hooks/use-post-amplified-order.ts | 143 ----- .../_components/forms/amplified/types.ts | 26 - .../_components/forms/amplified/utils.ts | 82 --- .../_components/forms/amplified/validators.ts | 15 - .../forms/components/market-details.tsx | 6 - .../_components/forms/components/steps.tsx | 8 +- .../forms/hooks/use-smart-router.ts | 80 --- .../forms/hooks/use-spender-address.ts | 4 +- .../forms/hooks/use-trade-infos.ts | 2 +- .../forms/limit/components/summary-step.tsx | 10 +- app/trade/_components/forms/limit/enums.ts | 7 +- .../forms/limit/hooks/use-limit.ts | 10 +- .../forms/limit/hooks/use-post-limit-order.ts | 12 +- app/trade/_components/forms/limit/limit.tsx | 13 +- app/trade/_components/forms/limit/types.ts | 3 +- .../forms/market/hooks/use-market.ts | 11 +- app/trade/_components/orderbook/orderbook.tsx | 1 + app/trade/_components/orderbook/semibook.tsx | 33 +- .../_components/tables/fills/use-table.tsx | 1 - .../tables/orders/amplified-order.tsx | 65 --- .../cancel-amplified-offer-dialog.tsx | 52 -- .../components/edit-amplified-order-sheet.tsx | 440 --------------- .../components/edit-amplified-order-steps.tsx | 231 -------- .../orders/components/edit-order-sheet.tsx | 2 +- .../orders/hooks/use-amplified-orders.ts | 85 --- .../orders/hooks/use-amplified-table.tsx | 146 ----- .../hooks/use-cancel-amplified-order.ts | 60 -- .../orders/hooks/use-edit-amplified-order.ts | 165 ------ .../hooks/use-update-amplified-order.ts | 79 --- .../tables/orders/hooks/use-update-order.ts | 1 - app/trade/_components/tables/orders/schema.ts | 67 --- app/trade/_components/tables/orders/types.ts | 22 - .../_components/tables/orders/utils/tables.ts | 24 +- app/trade/_components/tables/tables.tsx | 7 - components/chain-selector.tsx | 18 +- components/navbar.tsx | 71 +-- hooks/use-addresses.ts | 33 +- hooks/use-mangrove-token-price-query.ts | 4 +- hooks/use-token-from-id.ts | 4 +- package.json | 2 +- pnpm-lock.yaml | 10 +- providers/chains.tsx | 4 +- providers/wallet-connect.tsx | 3 +- stores/hovered-offer.store.ts | 2 +- utils/chains.ts | 2 +- utils/enums.ts | 19 + 97 files changed, 242 insertions(+), 4958 deletions(-) delete mode 100644 app/strategies/(list)/_components/new-strategy-dialog.tsx delete mode 100644 app/strategies/(list)/_providers/kandel-strategies.tsx rename app/strategies/{[address]/edit/_components/price-range/components => (shared)/_components}/price-chart/background-rectangles.tsx (100%) rename app/strategies/{[address]/edit/_components/price-range/components => (shared)/_components}/price-chart/cursor.tsx (100%) rename app/strategies/{[address]/edit/_components/price-range/components => (shared)/_components}/price-chart/custom-brush.tsx (100%) rename app/strategies/{new/_components/price-range/components => (shared)/_components}/price-chart/geometric-distribution-dots.tsx (100%) rename app/strategies/{new/_components/price-range/components => (shared)/_components}/price-chart/geometric-offer-tooltip.tsx (94%) rename app/strategies/{[address]/edit/_components/price-range/components => (shared)/_components}/price-chart/merged-offer-tooltip.tsx (95%) rename app/strategies/{new/_components/price-range/components => (shared)/_components}/price-chart/merged-offers-dots.tsx (100%) rename app/strategies/{[address]/edit/_components/price-range/components => (shared)/_components}/price-chart/mid-price-line.tsx (100%) rename app/strategies/{new/_components/price-range/components => (shared)/_components}/price-chart/price-range-chart.tsx (96%) rename app/strategies/{[address]/edit/_components/price-range/components => (shared)/_components}/price-chart/range-tooltips.tsx (90%) rename app/strategies/{[address]/edit/_components/price-range/components => (shared)/_components}/price-chart/set-range-animation.tsx (100%) delete mode 100644 app/strategies/[address]/edit/_components/price-range/components/price-chart/geometric-distribution-dots.tsx delete mode 100644 app/strategies/[address]/edit/_components/price-range/components/price-chart/geometric-offer-tooltip.tsx delete mode 100644 app/strategies/[address]/edit/_components/price-range/components/price-chart/merged-offers-dots.tsx delete mode 100644 app/strategies/[address]/edit/_components/price-range/components/price-chart/price-range-chart.tsx delete mode 100644 app/strategies/new/_components/price-range/components/price-chart/background-rectangles.tsx delete mode 100644 app/strategies/new/_components/price-range/components/price-chart/cursor.tsx delete mode 100644 app/strategies/new/_components/price-range/components/price-chart/custom-brush.tsx delete mode 100644 app/strategies/new/_components/price-range/components/price-chart/merged-offer-tooltip.tsx delete mode 100644 app/strategies/new/_components/price-range/components/price-chart/mid-price-line.tsx delete mode 100644 app/strategies/new/_components/price-range/components/price-chart/range-tooltips.tsx delete mode 100644 app/strategies/new/_components/price-range/components/price-chart/set-range-animation.tsx delete mode 100644 app/trade/_components/forms/amplified/amplified.tsx delete mode 100644 app/trade/_components/forms/amplified/components/from-wallet-order-dialog.tsx delete mode 100644 app/trade/_components/forms/amplified/components/summary-step.tsx delete mode 100644 app/trade/_components/forms/amplified/enums.ts delete mode 100644 app/trade/_components/forms/amplified/hooks/amplified-liquidity-sourcing.ts delete mode 100644 app/trade/_components/forms/amplified/hooks/amplified-store.ts delete mode 100644 app/trade/_components/forms/amplified/hooks/use-amplified.ts delete mode 100644 app/trade/_components/forms/amplified/hooks/use-post-amplified-order.ts delete mode 100644 app/trade/_components/forms/amplified/types.ts delete mode 100644 app/trade/_components/forms/amplified/utils.ts delete mode 100644 app/trade/_components/forms/amplified/validators.ts delete mode 100644 app/trade/_components/forms/hooks/use-smart-router.ts delete mode 100644 app/trade/_components/tables/orders/amplified-order.tsx delete mode 100644 app/trade/_components/tables/orders/components/cancel-amplified-offer-dialog.tsx delete mode 100644 app/trade/_components/tables/orders/components/edit-amplified-order-sheet.tsx delete mode 100644 app/trade/_components/tables/orders/components/edit-amplified-order-steps.tsx delete mode 100644 app/trade/_components/tables/orders/hooks/use-amplified-orders.ts delete mode 100644 app/trade/_components/tables/orders/hooks/use-amplified-table.tsx delete mode 100644 app/trade/_components/tables/orders/hooks/use-cancel-amplified-order.ts delete mode 100644 app/trade/_components/tables/orders/hooks/use-edit-amplified-order.ts delete mode 100644 app/trade/_components/tables/orders/hooks/use-update-amplified-order.ts create mode 100644 utils/enums.ts diff --git a/app/bridge/_components/warning-banner.tsx b/app/bridge/_components/warning-banner.tsx index 78a54240..9e6d2ed6 100644 --- a/app/bridge/_components/warning-banner.tsx +++ b/app/bridge/_components/warning-banner.tsx @@ -34,8 +34,8 @@ export default function WarningBanner() {
- You'll need to switch back to Blast if you want to browse the rest - of the web app :{" "} + You'll need to switch back to a supported network if you want to + browse the rest of the web app :{" "} - // - // - // - // ) -} diff --git a/app/strategies/(list)/_components/tables/strategies/hooks/use-strategies.ts b/app/strategies/(list)/_components/tables/strategies/hooks/use-strategies.ts index fb7b0166..0b92a845 100644 --- a/app/strategies/(list)/_components/tables/strategies/hooks/use-strategies.ts +++ b/app/strategies/(list)/_components/tables/strategies/hooks/use-strategies.ts @@ -1,7 +1,7 @@ "use client" import { useQuery } from "@tanstack/react-query" -import { useAccount, useChainId } from "wagmi" +import { useAccount } from "wagmi" import { useTokens } from "@/hooks/use-addresses" import useIndexerSdk from "@/providers/mangrove-indexer" @@ -19,8 +19,7 @@ export function useStrategies({ filters: { first = 10, skip = 0 } = {}, select, }: Params = {}) { - const chainId = useChainId() - const { address, isConnected } = useAccount() + const { address, isConnected, chainId } = useAccount() const { indexerSdk } = useIndexerSdk() const tokens = useTokens() const tokensList = tokens.map((token) => token.address.toLowerCase()) diff --git a/app/strategies/(list)/_components/tables/tables.tsx b/app/strategies/(list)/_components/tables/tables.tsx index eceb15e2..f6224367 100644 --- a/app/strategies/(list)/_components/tables/tables.tsx +++ b/app/strategies/(list)/_components/tables/tables.tsx @@ -5,9 +5,17 @@ import { CustomRadioGroupItem, } from "@/components/custom-radio-group" import { CustomTabs } from "@/components/custom-tabs" +import { useAccount } from "wagmi" import { Strategies } from "./strategies/strategies" import { Vaults } from "./vaults/vaults" +import { + Tooltip, + TooltipContent, + TooltipProvider, + TooltipTrigger, +} from "@/components/ui/tooltip" + enum StrategyType { PASSIVE = "Passive", PRO = "Pro", @@ -21,7 +29,7 @@ export function Tables({ hideCreateStrat: (bool: boolean) => void }) { const [strategiesType, setStrategiesType] = React.useState(StrategyType.PRO) - + const { chain } = useAccount() React.useEffect(() => { if (strategiesType === "Passive") { hideCreateStrat(true) @@ -46,8 +54,25 @@ export function Tables({ value={action} id={action} className="capitalize" + disabled={ + action === StrategyType.PASSIVE && chain?.name === "Arbitrum One" + } > - {action} + + + + {action} + + + + ))} diff --git a/app/strategies/(list)/_components/tables/vaults/hooks/use-vaults.ts b/app/strategies/(list)/_components/tables/vaults/hooks/use-vaults.ts index 5bb1c579..a1c69512 100644 --- a/app/strategies/(list)/_components/tables/vaults/hooks/use-vaults.ts +++ b/app/strategies/(list)/_components/tables/vaults/hooks/use-vaults.ts @@ -1,7 +1,7 @@ "use client" import type { Vault } from "@/app/strategies/(list)/_schemas/vaults" import { useQuery } from "@tanstack/react-query" -import { useAccount, useChainId, usePublicClient } from "wagmi" +import { useAccount, usePublicClient } from "wagmi" import { getChainVaults, getVaultsInformation } from "../services/skate-vaults" type Params = { @@ -16,7 +16,7 @@ export function useVaults({ filters: { first = 10, skip = 0 } = {}, select, }: Params = {}) { - const chainId = useChainId() + const { chainId } = useAccount() const publicClient = usePublicClient() const { address: user } = useAccount() const { data, ...rest } = useQuery({ @@ -24,6 +24,7 @@ export function useVaults({ queryFn: async (): Promise => { try { if (!publicClient) throw new Error("Public client is not enabled") + if (!chainId) return [] const plainVaults = getChainVaults(chainId).slice(skip, skip + first) return getVaultsInformation(publicClient, plainVaults, user) } catch (error) { @@ -31,7 +32,7 @@ export function useVaults({ return [] } }, - enabled: !!publicClient, + enabled: !!publicClient && !!chainId, initialData: [], }) return { diff --git a/app/strategies/(list)/_providers/kandel-strategies.tsx b/app/strategies/(list)/_providers/kandel-strategies.tsx deleted file mode 100644 index c863f41f..00000000 --- a/app/strategies/(list)/_providers/kandel-strategies.tsx +++ /dev/null @@ -1,58 +0,0 @@ -"use client" -import React from "react" - -import useMarket from "../../../../providers/market.new" - -const useKandelStrategiesContext = () => { - // const { mangrove } = useMangrove() - const { currentMarket: market } = useMarket() - - // const kandelStrategies = React.useMemo(() => { - // if (!mangrove) return - // return new KandelStrategies(mangrove) - // }, [mangrove]) - - // const generator = React.useMemo(() => { - // if (!kandelStrategies || !market) return - // return kandelStrategies.generator(market) - // }, [kandelStrategies, market]) - - // const config = React.useMemo(() => { - // if (!kandelStrategies || !market) return - // return kandelStrategies.configuration.getConfig(market) - // }, [kandelStrategies, market]) - - return { - // kandelStrategies, - // generator, - // config, - } -} - -const KandelStrategiesContext = React.createContext< - ReturnType | undefined ->(undefined) -KandelStrategiesContext.displayName = "KandelStrategiesContext" - -export function KandelStrategiesProvider({ - children, -}: React.PropsWithChildren) { - const kandelStrategiesContext = useKandelStrategiesContext() - return ( - - {children} - - ) -} - -const useKandel = () => { - const kandelStrategiesCtx = React.useContext(KandelStrategiesContext) - if (!kandelStrategiesCtx) { - throw new Error( - "useKandel must be used within the KandelStrategiesContext.Provider", - ) - } - return kandelStrategiesCtx -} - -export default useKandel diff --git a/app/strategies/(list)/layout.tsx b/app/strategies/(list)/layout.tsx index de6c2ed7..669d3024 100644 --- a/app/strategies/(list)/layout.tsx +++ b/app/strategies/(list)/layout.tsx @@ -1,7 +1,6 @@ import { Metadata } from "next" import React from "react" -import { KandelStrategiesProvider } from "@/app/strategies/(list)/_providers/kandel-strategies" import { Navbar } from "@/components/navbar" import { IndexerSdkProvider } from "@/providers/mangrove-indexer" import { MarketProvider } from "@/providers/market.new" @@ -16,11 +15,9 @@ export default function Layout({ children }: React.PropsWithChildren) { return ( - - - -
{children}
-
+ + +
{children}
) diff --git a/app/strategies/[address]/edit/_components/price-range/components/price-chart/background-rectangles.tsx b/app/strategies/(shared)/_components/price-chart/background-rectangles.tsx similarity index 100% rename from app/strategies/[address]/edit/_components/price-range/components/price-chart/background-rectangles.tsx rename to app/strategies/(shared)/_components/price-chart/background-rectangles.tsx diff --git a/app/strategies/[address]/edit/_components/price-range/components/price-chart/cursor.tsx b/app/strategies/(shared)/_components/price-chart/cursor.tsx similarity index 100% rename from app/strategies/[address]/edit/_components/price-range/components/price-chart/cursor.tsx rename to app/strategies/(shared)/_components/price-chart/cursor.tsx diff --git a/app/strategies/[address]/edit/_components/price-range/components/price-chart/custom-brush.tsx b/app/strategies/(shared)/_components/price-chart/custom-brush.tsx similarity index 100% rename from app/strategies/[address]/edit/_components/price-range/components/price-chart/custom-brush.tsx rename to app/strategies/(shared)/_components/price-chart/custom-brush.tsx diff --git a/app/strategies/new/_components/price-range/components/price-chart/geometric-distribution-dots.tsx b/app/strategies/(shared)/_components/price-chart/geometric-distribution-dots.tsx similarity index 100% rename from app/strategies/new/_components/price-range/components/price-chart/geometric-distribution-dots.tsx rename to app/strategies/(shared)/_components/price-chart/geometric-distribution-dots.tsx diff --git a/app/strategies/new/_components/price-range/components/price-chart/geometric-offer-tooltip.tsx b/app/strategies/(shared)/_components/price-chart/geometric-offer-tooltip.tsx similarity index 94% rename from app/strategies/new/_components/price-range/components/price-chart/geometric-offer-tooltip.tsx rename to app/strategies/(shared)/_components/price-chart/geometric-offer-tooltip.tsx index 9243d0c1..d013ce8a 100644 --- a/app/strategies/new/_components/price-range/components/price-chart/geometric-offer-tooltip.tsx +++ b/app/strategies/(shared)/_components/price-chart/geometric-offer-tooltip.tsx @@ -4,6 +4,7 @@ import { ScaleLinear } from "d3-scale" import { cn } from "@/utils" import { BA } from "@mangrovedao/mgv/lib" +import { formatEther } from "viem" import { TypedDistrubutionOffer } from "./geometric-distribution-dots" type Props = { @@ -44,7 +45,7 @@ export function GeometricOfferTooltip({
Volume:{" "} - {Number(hoveredGeometricOffer.gives).toFixed( + {Number(formatEther(hoveredGeometricOffer.gives, "wei")).toFixed( (hoveredGeometricOffer.type === BA.bids ? quoteToken : baseToken) ?.displayDecimals, )}{" "} diff --git a/app/strategies/[address]/edit/_components/price-range/components/price-chart/merged-offer-tooltip.tsx b/app/strategies/(shared)/_components/price-chart/merged-offer-tooltip.tsx similarity index 95% rename from app/strategies/[address]/edit/_components/price-range/components/price-chart/merged-offer-tooltip.tsx rename to app/strategies/(shared)/_components/price-chart/merged-offer-tooltip.tsx index 23a69f0b..be36a9fa 100644 --- a/app/strategies/[address]/edit/_components/price-range/components/price-chart/merged-offer-tooltip.tsx +++ b/app/strategies/(shared)/_components/price-chart/merged-offer-tooltip.tsx @@ -14,7 +14,7 @@ type Props = { xScale: ScaleLinear onHover?: (offer: TypedDistrubutionOffer) => void onHoverOut?: () => void - mergedOffer: OfferParsed + mergedOffer: OfferParsed & { formattedGives?: string } baseToken: Token quoteToken: Token } @@ -52,7 +52,6 @@ export function MergedOfferTooltip({ quoteToken, }: Props) { const isLive = mergedOffer.gives > 0 - return (
Volume:{" "} - {Number(mergedOffer.gives).toFixed( + {Number(mergedOffer.formattedGives).toFixed( (mergedOffer.ba === BA.bids ? quoteToken : baseToken) ?.displayDecimals, )}{" "} diff --git a/app/strategies/new/_components/price-range/components/price-chart/merged-offers-dots.tsx b/app/strategies/(shared)/_components/price-chart/merged-offers-dots.tsx similarity index 100% rename from app/strategies/new/_components/price-range/components/price-chart/merged-offers-dots.tsx rename to app/strategies/(shared)/_components/price-chart/merged-offers-dots.tsx diff --git a/app/strategies/[address]/edit/_components/price-range/components/price-chart/mid-price-line.tsx b/app/strategies/(shared)/_components/price-chart/mid-price-line.tsx similarity index 100% rename from app/strategies/[address]/edit/_components/price-range/components/price-chart/mid-price-line.tsx rename to app/strategies/(shared)/_components/price-chart/mid-price-line.tsx diff --git a/app/strategies/new/_components/price-range/components/price-chart/price-range-chart.tsx b/app/strategies/(shared)/_components/price-chart/price-range-chart.tsx similarity index 96% rename from app/strategies/new/_components/price-range/components/price-chart/price-range-chart.tsx rename to app/strategies/(shared)/_components/price-chart/price-range-chart.tsx index 5bae532e..a3b1da04 100644 --- a/app/strategies/new/_components/price-range/components/price-chart/price-range-chart.tsx +++ b/app/strategies/(shared)/_components/price-chart/price-range-chart.tsx @@ -83,6 +83,7 @@ export function PriceRangeChart({ const { isConnected } = useAccount() const { ref, width = 0, height = 0 } = useResizeObserver() const [isMovingRange, setIsMovingRange] = React.useState(false) + const [hasBeenInit, setHasBeenInit] = React.useState(false) const offers = [ ...bids.map((bid) => ({ ...bid, type: "bid" })), ...asks.map((ask) => ({ ...ask, type: "ask" })), @@ -120,21 +121,26 @@ export function PriceRangeChart({ const altPressed = useKeyPress("Alt") - // if viewOnly, set the xDomain to the priceRange React.useEffect(() => { - if (!viewOnly || !priceRange) return - const [min, max] = priceRange - const xLowerBound = min * 0.8 - const xUpperBound = max * 1.1 + const [min, max] = priceRange ?? [0, 0] + const centralValue = (min + max) / 2 + + if ((min === 0 && max === 0) || hasBeenInit) return + const lowerFactor = min / centralValue + const upperFactor = max / centralValue + const xLowerBound = min * lowerFactor + const xUpperBound = max * upperFactor setXDomain([xLowerBound, xUpperBound]) - }, [viewOnly, priceRange]) + setHasBeenInit(true) + }, [priceRange, hasBeenInit]) React.useEffect(() => { - if (!midPrice || viewOnly) return + const [min, max] = priceRange ?? [0, 0] + if (!midPrice || viewOnly || (min !== 0 && max !== 0)) return const xLowerBound = midPrice * 0.7 // 30% lower than mid price const xUpperBound = midPrice * 1.3 // 30% higher than mid price setXDomain([xLowerBound, xUpperBound]) - }, [midPrice]) + }, [midPrice, priceRange]) const xScale = scaleLinear({ domain: xDomain, diff --git a/app/strategies/[address]/edit/_components/price-range/components/price-chart/range-tooltips.tsx b/app/strategies/(shared)/_components/price-chart/range-tooltips.tsx similarity index 90% rename from app/strategies/[address]/edit/_components/price-range/components/price-chart/range-tooltips.tsx rename to app/strategies/(shared)/_components/price-chart/range-tooltips.tsx index 017c53c7..3f3ad89e 100644 --- a/app/strategies/[address]/edit/_components/price-range/components/price-chart/range-tooltips.tsx +++ b/app/strategies/(shared)/_components/price-chart/range-tooltips.tsx @@ -1,5 +1,8 @@ import { cn } from "@/utils" -import { calculatePriceDifferencePercentage } from "@/utils/numbers" +import { + calculatePriceDifferencePercentage, + determineDecimals, +} from "@/utils/numbers" import { Tooltip } from "@visx/tooltip" import type { ScaleLinear } from "d3-scale" @@ -58,7 +61,7 @@ export function RangeTooltips({ "whitespace-nowrap -translate-x-2/3 px-2 py-1 rounded-md text-sm leading-[14px] bg-cloud-400 text-white", )} > - Mid {midPrice.toFixed(2)} + Mid {midPrice.toFixed(determineDecimals(midPrice))}
) : undefined} @@ -106,7 +109,8 @@ function RangeTooltip({ }, )} > - {text} {value.toFixed(2)} {midPrice ? `${percentage.toFixed(2)}%` : ""} + {text} {value.toFixed(determineDecimals(2, 6))}{" "} + {midPrice ? `${percentage.toFixed(2)}%` : ""}
) diff --git a/app/strategies/[address]/edit/_components/price-range/components/price-chart/set-range-animation.tsx b/app/strategies/(shared)/_components/price-chart/set-range-animation.tsx similarity index 100% rename from app/strategies/[address]/edit/_components/price-range/components/price-chart/set-range-animation.tsx rename to app/strategies/(shared)/_components/price-chart/set-range-animation.tsx diff --git a/app/strategies/[address]/_components/overview/table/use-offers-table.tsx b/app/strategies/[address]/_components/overview/table/use-offers-table.tsx index 4bd2a184..5bef16c0 100644 --- a/app/strategies/[address]/_components/overview/table/use-offers-table.tsx +++ b/app/strategies/[address]/_components/overview/table/use-offers-table.tsx @@ -11,7 +11,7 @@ import { import React from "react" import { formatUnits } from "viem" -import { StatusBadge } from "@/app/strategies/new/_components/price-range/components/price-chart/merged-offer-tooltip" +import { StatusBadge } from "@/app/strategies/(shared)/_components/price-chart/merged-offer-tooltip" import { cn } from "@/utils" import { BA, inboundFromOutbound } from "@mangrovedao/mgv/lib" import useKandel from "../../../_providers/kandel-strategy" @@ -85,7 +85,7 @@ export function useOffersTable({ data }: Params) { const quote = ba === BA.bids ? gives : wants return (
- {Number(formatUnits(quote, market?.base.decimals || 18)).toFixed( + {Number(formatUnits(quote, market?.quote.decimals || 18)).toFixed( market?.quote.displayDecimals, )}{" "} {market?.quote.symbol} diff --git a/app/strategies/[address]/_components/shared/price-range-infos.tsx b/app/strategies/[address]/_components/shared/price-range-infos.tsx index bd319246..96137a66 100644 --- a/app/strategies/[address]/_components/shared/price-range-infos.tsx +++ b/app/strategies/[address]/_components/shared/price-range-infos.tsx @@ -1,4 +1,4 @@ -import { PriceRangeChart } from "@/app/strategies/new/_components/price-range/components/price-chart/price-range-chart" +import { PriceRangeChart } from "@/app/strategies/(shared)/_components/price-chart/price-range-chart" import { useKandelBook } from "../../_hooks/use-kandel-book" import useKandel from "../../_providers/kandel-strategy" import { useParameters } from "../parameters/hook/use-parameters" diff --git a/app/strategies/[address]/_hooks/use-kandel-steps.ts b/app/strategies/[address]/_hooks/use-kandel-steps.ts index b7fe0f92..f49d2f1c 100644 --- a/app/strategies/[address]/_hooks/use-kandel-steps.ts +++ b/app/strategies/[address]/_hooks/use-kandel-steps.ts @@ -4,7 +4,6 @@ import { useQuery } from "@tanstack/react-query" import { useKandelSeeder, useMangroveAddresses } from "@/hooks/use-addresses" import useMarket from "@/providers/market.new" import { getErrorMessage } from "@/utils/errors" -import { getUserRouter } from "@mangrovedao/mgv/actions" import { useAccount, useClient, usePublicClient } from "wagmi" import useKandel from "../_providers/kandel-strategy" @@ -46,10 +45,6 @@ export function useKandelSteps() { !currentMarket ) throw new Error("Could not fetch kandel steps, missing params") - - const userRouter = await getUserRouter(publicClient, addresses, { - user: address, - }) const kandelActions = kandelSeederActions(currentMarket, kandelSeeder) const seeder = kandelActions(client) diff --git a/app/strategies/[address]/edit/_components/form/use-form.ts b/app/strategies/[address]/edit/_components/form/use-form.ts index c7fb7d53..afa607c7 100644 --- a/app/strategies/[address]/edit/_components/form/use-form.ts +++ b/app/strategies/[address]/edit/_components/form/use-form.ts @@ -106,7 +106,7 @@ export default function useForm() { baseAmount: parseUnits(baseDeposit, baseToken?.decimals || 18), quoteAmount: parseUnits(quoteDeposit, quoteToken?.decimals || 18), stepSize: BigInt(debouncedStepSize), - pricePoints: BigInt(debouncedNumberOfOffers), + pricePoints: BigInt(Number(debouncedNumberOfOffers) + 1), }, isMissingField, ) diff --git a/app/strategies/[address]/edit/_components/price-range/components/price-chart/geometric-distribution-dots.tsx b/app/strategies/[address]/edit/_components/price-range/components/price-chart/geometric-distribution-dots.tsx deleted file mode 100644 index 0815c715..00000000 --- a/app/strategies/[address]/edit/_components/price-range/components/price-chart/geometric-distribution-dots.tsx +++ /dev/null @@ -1,71 +0,0 @@ -import type { ScaleLinear } from "d3-scale" - -import { cn } from "@/utils" -import { Distribution, DistributionOffer } from "@mangrovedao/mgv" -import { BA } from "@mangrovedao/mgv/lib" - -export type TypedDistrubutionOffer = DistributionOffer & { type: BA } - -type Props = { - height: number - paddingBottom: number - xScale: ScaleLinear - onHover?: (offer: TypedDistrubutionOffer) => void - onHoverOut?: () => void -} & { distribution?: Distribution } - -export function GeometricKandelDistributionDots({ - distribution, - xScale, - height, - paddingBottom, - onHover, - onHoverOut, -}: Props) { - if (!distribution) return null - - const dots = [ - ...distribution?.bids.map((bid) => ({ - ...bid, - type: BA.bids, - })), - ...distribution?.asks.map((ask) => ({ - ...ask, - type: BA.asks, - })), - ] - - const filteredDots = dots.filter((dot) => dot.gives > 0) - - return filteredDots.map((geometricOffer) => ( - onHover?.(geometricOffer)} - onMouseOut={onHoverOut} - key={`${geometricOffer.type}-${geometricOffer.index}`} - > - - - - - )) -} diff --git a/app/strategies/[address]/edit/_components/price-range/components/price-chart/geometric-offer-tooltip.tsx b/app/strategies/[address]/edit/_components/price-range/components/price-chart/geometric-offer-tooltip.tsx deleted file mode 100644 index e723ea80..00000000 --- a/app/strategies/[address]/edit/_components/price-range/components/price-chart/geometric-offer-tooltip.tsx +++ /dev/null @@ -1,60 +0,0 @@ -import { DistributionOffer, Token } from "@mangrovedao/mgv" -import { TooltipWithBounds } from "@visx/tooltip" -import { ScaleLinear } from "d3-scale" - -import { cn } from "@/utils" -import { BA } from "@mangrovedao/mgv/lib" - -export type TypedDistrubutionOffer = DistributionOffer & { type: BA } - -type Props = { - height: number - paddingBottom: number - xScale: ScaleLinear - onHover?: (offer: DistributionOffer) => void - onHoverOut?: () => void - hoveredGeometricOffer: TypedDistrubutionOffer - baseToken: Token - quoteToken: Token -} - -export function GeometricOfferTooltip({ - height, - paddingBottom, - xScale: xScaleTransformed, - hoveredGeometricOffer, - baseToken, - quoteToken, -}: Props) { - return ( - -
-
- Price:{" "} - {hoveredGeometricOffer.price.toFixed(quoteToken?.displayDecimals)}{" "} - {quoteToken?.symbol} -
-
- Volume:{" "} - {Number(hoveredGeometricOffer.gives).toFixed( - (hoveredGeometricOffer.type === BA.bids ? quoteToken : baseToken) - ?.displayDecimals, - )}{" "} - { - (hoveredGeometricOffer.type === BA.bids ? quoteToken : baseToken) - ?.symbol - } -
-
-
- ) -} diff --git a/app/strategies/[address]/edit/_components/price-range/components/price-chart/merged-offers-dots.tsx b/app/strategies/[address]/edit/_components/price-range/components/price-chart/merged-offers-dots.tsx deleted file mode 100644 index 252b9269..00000000 --- a/app/strategies/[address]/edit/_components/price-range/components/price-chart/merged-offers-dots.tsx +++ /dev/null @@ -1,62 +0,0 @@ -import type { ScaleLinear } from "d3-scale" - -import { cn } from "@/utils" -import { OfferParsed } from "@mangrovedao/mgv" -import { BA } from "@mangrovedao/mgv/lib" - -type Props = { - height: number - paddingBottom: number - xScale: ScaleLinear - onHover?: (offer: OfferParsed) => void - onHoverOut?: () => void - hoveredOffer?: OfferParsed -} & { distribution: OfferParsed[] } - -export function MergedOffersDots({ - distribution, - xScale, - height, - paddingBottom, - onHover, - onHoverOut, - hoveredOffer, -}: Props) { - if (!distribution) return null - - return distribution.map((offer) => ( - onHover?.(offer)} - onMouseOut={onHoverOut} - key={`${offer.ba}-${offer.index}-${offer.id}`} - > - 0), - "opacity-100": - hoveredOffer?.id === offer.id && hoveredOffer?.ba === offer.ba, - }, - )} - /> - - 0), - })} - /> - - )) -} diff --git a/app/strategies/[address]/edit/_components/price-range/components/price-chart/price-range-chart.tsx b/app/strategies/[address]/edit/_components/price-range/components/price-chart/price-range-chart.tsx deleted file mode 100644 index b21bed30..00000000 --- a/app/strategies/[address]/edit/_components/price-range/components/price-chart/price-range-chart.tsx +++ /dev/null @@ -1,414 +0,0 @@ -"use client" -import { Token } from "@mangrovedao/mgv" -import { AxisLeft, AxisTop } from "@visx/axis" -import { curveStep } from "@visx/curve" -import { localPoint } from "@visx/event" -import { scaleLinear } from "@visx/scale" -import { AreaClosed } from "@visx/shape" -import { Zoom } from "@visx/zoom" -import { type ProvidedZoom } from "@visx/zoom/lib/types" -import Big from "big.js" -import { Minus, Plus } from "lucide-react" -import React from "react" -import useResizeObserver from "use-resize-observer" -import { useAccount } from "wagmi" - -import { Title } from "@/components/typography/title" -import { Button } from "@/components/ui/button" -import { Skeleton } from "@/components/ui/skeleton" -import { useKeyPress } from "@/hooks/use-key-press" -import { useHoveredOfferStore } from "@/stores/hovered-offer.store" -import { cn } from "@/utils" -import { CompleteOffer, Distribution, OfferParsed } from "@mangrovedao/mgv" -import { BackgroundRectangles } from "./background-rectangles" -import CustomBrush from "./custom-brush" -import { - GeometricKandelDistributionDots, - TypedDistrubutionOffer, -} from "./geometric-distribution-dots" -import { GeometricOfferTooltip } from "./geometric-offer-tooltip" -import { MergedOfferTooltip } from "./merged-offer-tooltip" -import { MergedOffersDots } from "./merged-offers-dots" -import { MidPriceLine } from "./mid-price-line" -import { RangeTooltips } from "./range-tooltips" -import { SetRangeAnimation } from "./set-range-animation" - -const paddingRight = 54 -const paddingBottom = 44 -const maxToTheTopRatio = 0.8 - -const initialTransform = { - scaleX: 1, - scaleY: 1, - translateX: 0, - translateY: 0, - skewX: 0, - skewY: 0, -} - -export type PriceRangeChartProps = { - baseToken?: Token | null - quoteToken?: Token | null - initialMidPrice?: number - bids?: CompleteOffer[] - asks?: CompleteOffer[] - onPriceRangeChange?: (priceRange: number[]) => void - priceRange?: [number, number] - viewOnly?: boolean - isLoading?: boolean - geometricKandelDistribution?: Distribution - mergedOffers?: OfferParsed[] -} - -export function PriceRangeChart({ - bids = [], - asks = [], - initialMidPrice, - onPriceRangeChange, - priceRange, - viewOnly = false, - isLoading = false, - geometricKandelDistribution, - mergedOffers, - baseToken, - quoteToken, -}: PriceRangeChartProps) { - const [hoveredGeometricOffer, setHoveredGeometricOffer] = - React.useState() - const { hoveredOffer, setHoveredOffer } = useHoveredOfferStore() - const { isConnected } = useAccount() - const { ref, width = 0, height = 0 } = useResizeObserver() - const [isMovingRange, setIsMovingRange] = React.useState(false) - const offers = [ - ...bids.map((bid) => ({ ...bid, type: "bid" })), - ...asks.map((ask) => ({ ...ask, type: "ask" })), - ].sort((a, b) => a.price - b.price) - - const lowestAsk = asks?.[0] - const highestBid = bids?.[0] - const midPrice = React.useMemo(() => { - if (!bids?.length || !asks?.length) return initialMidPrice - return Big(lowestAsk?.price ?? 0) - .add(highestBid?.price ?? 0) - .div(2) - .toNumber() - }, [ - asks?.length, - bids?.length, - highestBid?.price, - initialMidPrice, - lowestAsk?.price, - ]) - const xLowerBound = midPrice ? midPrice * 0.7 : 0 // 30% lower than mid price - const xUpperBound = midPrice ? midPrice * 1.3 : 6000 // 30% higher than mid price - - const maxVolume = Math.max(...offers.map((offer) => offer.volume)) - - const [xDomain, setXDomain] = React.useState([xLowerBound, xUpperBound]) - const [dragStartPoint, setDragStartPoint] = React.useState<{ - x: number - y: number - } | null>(null) - const [prevPoint, setPrevPoint] = React.useState<{ - x: number - y: number - } | null>(null) - - const altPressed = useKeyPress("Alt") - - // if viewOnly, set the xDomain to the priceRange - React.useEffect(() => { - if (!viewOnly || !priceRange) return - const [min, max] = priceRange - const xLowerBound = min * 0.8 - const xUpperBound = max * 1.1 - setXDomain([xLowerBound, xUpperBound]) - }, [viewOnly, priceRange]) - - React.useEffect(() => { - if (!midPrice || viewOnly) return - const xLowerBound = midPrice * 0.7 // 30% lower than mid price - const xUpperBound = midPrice * 1.3 // 30% higher than mid price - setXDomain([xLowerBound, xUpperBound]) - }, [midPrice]) - - const xScale = scaleLinear({ - domain: xDomain, - range: [0, width - paddingRight], - }) - - const yScale = scaleLinear({ - domain: [0, maxVolume / maxToTheTopRatio], - range: [height - paddingBottom, 0], // subtract paddingBottom from height - }) - - // used for zoom - const rescaleXAxis = (zoom: ProvidedZoom) => { - const newXDomain = xScale.range().map((r) => { - return xScale.invert( - // eslint-disable-next-line @typescript-eslint/ban-ts-comment - // @ts-ignore - (r - zoom.transformMatrix.translateX) / zoom.transformMatrix.scaleX, - ) - }) - return xScale.copy().domain(newXDomain) - } - - /** - * Price range selection - */ - const [selectedPriceRange, setSelectedPriceRange] = React.useState< - [number, number] | null - >(priceRange ?? null) - - React.useEffect(() => { - if (!priceRange) return - setSelectedPriceRange(priceRange) - }, [priceRange]) - - const svgRef = React.useRef(null) - return ( - - {(zoom) => { - const xScaleTransformed = rescaleXAxis(zoom) - return ( - <> -
- Price range - - - - -
-
- {altPressed && ( -
{ - // Get the minimum value of the domain - const [minDomain] = xScaleTransformed.domain() - - // If there's no minimum domain value or no drag start point, exit the function - if (!minDomain || !dragStartPoint) return - - // Get the current mouse position - const currentPoint = localPoint(e) ?? { x: 0, y: 0 } - - // Determine the direction of the drag - let dragDirection = "none" - if (prevPoint) { - dragDirection = - currentPoint.x < prevPoint.x ? "right" : "left" - } - - // Update the previous mouse position - setPrevPoint(currentPoint) - - // If the minimum domain value is greater than 0, allow dragging in both directions - if (minDomain > 0) { - zoom.dragMove(e) - } - // If the minimum domain value is less than or equal to 0, only allow dragging to the right - else if (minDomain <= 0 && dragDirection === "right") { - zoom.dragMove(e) - } - }} - onMouseDown={(e) => { - const point = localPoint(e) ?? { x: 0, y: 0 } - setDragStartPoint(point) - zoom.dragStart(e) - }} - onMouseUp={zoom.dragEnd} - onMouseOut={zoom.dragEnd} - /> - )} - {(isLoading || !isConnected) && ( - - )} - {!priceRange && !viewOnly ? ( -
-
- -
-
- ) : undefined} - - - xScaleTransformed(d.price)} - y={(d) => yScale(d.volume)} - yScale={yScale} - strokeWidth={1} - curve={curveStep} - className="fill-primary-night-woods" - opacity={priceRange ? 0.8 : 1} - /> - - { - return ( - - - - {formattedValue} - - - ) - }} - /> - - {viewOnly && - !priceRange?.[0] && - !priceRange?.[1] ? undefined : ( - { - setIsMovingRange(false) - setSelectedPriceRange(selectedRange) - if (onPriceRangeChange && selectedRange) { - onPriceRangeChange(selectedRange) - } - }} - onBrushChange={(selectedRange) => { - setIsMovingRange(true) - setSelectedPriceRange(selectedRange) - if (onPriceRangeChange && selectedRange) { - onPriceRangeChange(selectedRange) - } - }} - value={selectedPriceRange ?? undefined} - svgRef={svgRef} - viewOnly={viewOnly} - midPrice={midPrice} - /> - )} - {!isMovingRange && priceRange?.[0] && priceRange?.[1] && ( - setHoveredGeometricOffer(undefined)} - /> - )} - {mergedOffers && ( - { - setHoveredOffer(offer) - }} - onHoverOut={() => setHoveredOffer(undefined)} - hoveredOffer={hoveredOffer} - /> - )} - - - - {hoveredGeometricOffer && baseToken && quoteToken && ( - - )} - {hoveredOffer && baseToken && quoteToken && ( - - )} -
- - ) - }} - - ) -} diff --git a/app/strategies/[address]/edit/_components/price-range/price-range.tsx b/app/strategies/[address]/edit/_components/price-range/price-range.tsx index d210a133..6f37fbd0 100644 --- a/app/strategies/[address]/edit/_components/price-range/price-range.tsx +++ b/app/strategies/[address]/edit/_components/price-range/price-range.tsx @@ -7,6 +7,7 @@ import { EnhancedNumericInput } from "@/components/token-input" import { Button } from "@/components/ui/button" import withClientOnly from "@/hocs/withClientOnly" +import { PriceRangeChart } from "@/app/strategies/(shared)/_components/price-chart/price-range-chart" import { calculatePriceDifferencePercentage, calculatePriceFromPercentage, @@ -19,7 +20,6 @@ import { useKandelBook } from "../../../_hooks/use-kandel-book" import useKandel from "../../../_providers/kandel-strategy" import EditStrategyDialog from "../edit-strategy-dialog" import { LiquiditySource } from "./components/liquidity-source" -import { PriceRangeChart } from "./components/price-chart/price-range-chart" import { RiskAppetiteBadge } from "./components/risk-appetite" export const PriceRange = withClientOnly(function ({ diff --git a/app/strategies/[address]/edit/layout.tsx b/app/strategies/[address]/edit/layout.tsx index 6c017b85..9389fd22 100644 --- a/app/strategies/[address]/edit/layout.tsx +++ b/app/strategies/[address]/edit/layout.tsx @@ -1,7 +1,6 @@ import { Metadata } from "next" import React from "react" -import { KandelStrategiesProvider } from "@/app/strategies/(list)/_providers/kandel-strategies" import { IndexerSdkProvider } from "@/providers/mangrove-indexer" import { MarketProvider } from "@/providers/market.new" @@ -14,9 +13,7 @@ export default function Layout({ children }: React.PropsWithChildren) { return ( - -
{children}
-
+
{children}
) diff --git a/app/strategies/[address]/layout.tsx b/app/strategies/[address]/layout.tsx index 2893a80e..4db49b33 100644 --- a/app/strategies/[address]/layout.tsx +++ b/app/strategies/[address]/layout.tsx @@ -5,7 +5,6 @@ import { KandelStrategyProvider } from "@/app/strategies/[address]/_providers/ka import { Navbar } from "@/components/navbar" import { IndexerSdkProvider } from "@/providers/mangrove-indexer" import { MarketProvider } from "@/providers/market.new" -import { KandelStrategiesProvider } from "../(list)/_providers/kandel-strategies" import WarningBanner from "../(shared)/_components/warning-banner" export const metadata: Metadata = { @@ -17,14 +16,12 @@ export default function Layout({ children }: React.PropsWithChildren) { return ( - - - - + + + -
{children}
-
-
+
{children}
+
) diff --git a/app/strategies/new/_components/form/use-form.ts b/app/strategies/new/_components/form/use-form.ts index da37603d..db44c490 100644 --- a/app/strategies/new/_components/form/use-form.ts +++ b/app/strategies/new/_components/form/use-form.ts @@ -74,7 +74,7 @@ export default function useForm() { baseAmount: parseUnits(baseDeposit, baseToken?.decimals || 18), quoteAmount: parseUnits(quoteDeposit, quoteToken?.decimals || 18), stepSize: BigInt(debouncedStepSize), - pricePoints: BigInt(debouncedNumberOfOffers), + pricePoints: BigInt(Number(debouncedNumberOfOffers) + 1), }, isMissingField, ) diff --git a/app/strategies/new/_components/price-range/components/price-chart/background-rectangles.tsx b/app/strategies/new/_components/price-range/components/price-chart/background-rectangles.tsx deleted file mode 100644 index a12b6bbc..00000000 --- a/app/strategies/new/_components/price-range/components/price-chart/background-rectangles.tsx +++ /dev/null @@ -1,107 +0,0 @@ -"use client" -import { LinearGradient } from "@visx/gradient" -import type { ScaleLinear } from "d3-scale" -import React from "react" - -type Props = { - height: number - paddingBottom: number - xScale: ScaleLinear - priceRange?: [number, number] | null - midPrice?: number | null -} - -function isPositiveNumber(value: number | null | undefined): value is number { - return value !== null && value !== undefined && value > 0 -} - -export function BackgroundRectangles({ - height, - paddingBottom, - xScale: xScaleTransformed, - priceRange, - midPrice, -}: Props) { - const bidsGradientId = React.useId() - const asksGradientId = React.useId() - const neutralGradientId = React.useId() - - const minPrice = priceRange ? priceRange[0] : null - const maxPrice = priceRange ? priceRange[1] : null - - const leftBidBound = - minPrice && midPrice && minPrice < midPrice ? minPrice : midPrice - const rightBidBound = - maxPrice && midPrice && maxPrice > midPrice ? midPrice : maxPrice - - const leftAskBound = - minPrice && midPrice && minPrice < midPrice ? midPrice : minPrice - const rightAskBound = - maxPrice && midPrice && maxPrice > midPrice ? maxPrice : midPrice - - const rectHeight = height - paddingBottom - - const leftX = leftBidBound && xScaleTransformed(leftBidBound) - const rightX = rightBidBound && xScaleTransformed(rightBidBound) - - if (!(leftX && rightX && isPositiveNumber(rectHeight))) return null - - return ( - <> - {priceRange && midPrice ? ( - <> - - - {leftAskBound && rightAskBound && ( - <> - - - - )} - - ) : ( - minPrice && - maxPrice && ( - <> - - - - ) - )} - - ) -} diff --git a/app/strategies/new/_components/price-range/components/price-chart/cursor.tsx b/app/strategies/new/_components/price-range/components/price-chart/cursor.tsx deleted file mode 100644 index c5283768..00000000 --- a/app/strategies/new/_components/price-range/components/price-chart/cursor.tsx +++ /dev/null @@ -1,148 +0,0 @@ -/* eslint-disable @typescript-eslint/ban-ts-comment */ -/* eslint-disable @typescript-eslint/no-explicit-any */ -import type { ScaleLinear } from "d3-scale" -import React from "react" - -import { cn } from "@/utils" - -interface CursorProps { - xPosition: number - height: number - color?: "red" | "neutral" | "green" - type: "left" | "right" - onMove: (newXPosition: number) => void - xScale: ScaleLinear - svgRef: React.RefObject - viewOnly?: boolean - hidden?: boolean -} - -export default function Cursor({ - xPosition, - height, - color, - type, - onMove, - xScale, - svgRef, - viewOnly = false, - hidden = false, -}: CursorProps) { - const [isDragging, setIsDragging] = React.useState(false) - - const handleMouseDown = React.useCallback((event: MouseEvent) => { - if (viewOnly) return - event.preventDefault() - event.stopPropagation() - setIsDragging(true) - }, []) - - const handleMouseUp = React.useCallback((event: MouseEvent) => { - event.preventDefault() - event.stopPropagation() - setIsDragging(false) - }, []) - - const handleMouseMove = React.useCallback( - (event: any) => { - event.preventDefault() - event.stopPropagation() - if (isDragging) { - const svg = svgRef.current - if (!svg) return - const rect = svg.getBoundingClientRect() - const x = event.clientX - rect.left - const newPrice = xScale.invert(x) - onMove(newPrice) - } - }, - [isDragging, onMove, xScale, svgRef], - ) - - React.useEffect(() => { - if (viewOnly) return - const svg = svgRef.current - svg?.addEventListener("mousemove", handleMouseMove) - svg?.addEventListener("mouseup", handleMouseUp) - - return () => { - svg?.removeEventListener("mousemove", handleMouseMove) - svg?.removeEventListener("mouseup", handleMouseUp) - } - }, [ - handleMouseDown, - handleMouseMove, - handleMouseUp, - isDragging, - svgRef, - viewOnly, - ]) - - return ( - <> - - - ) -} diff --git a/app/strategies/new/_components/price-range/components/price-chart/custom-brush.tsx b/app/strategies/new/_components/price-range/components/price-chart/custom-brush.tsx deleted file mode 100644 index b0654fe7..00000000 --- a/app/strategies/new/_components/price-range/components/price-chart/custom-brush.tsx +++ /dev/null @@ -1,227 +0,0 @@ -"use client" - -import { cn } from "@/utils" -import { type ScaleLinear } from "d3-scale" -import React from "react" - -import Cursor from "./cursor" - -type SelectionStatus = "idle" | "start" | "end" - -interface CustomBrushProps { - xScale: ScaleLinear - width: number - height: number - onBrushEnd: (range: [number, number]) => void - value?: [number, number] - onBrushChange: (newRange: [number, number]) => void - svgRef: React.RefObject - viewOnly?: boolean - midPrice?: number | null -} - -function CustomBrush({ - xScale, - width, - height, - onBrushEnd, - value, - onBrushChange, - svgRef, - viewOnly = false, - midPrice, -}: CustomBrushProps) { - const startValueRef = React.useRef(null) - const [selection, setSelection] = React.useState<[number, number] | null>( - value ?? null, - ) - const [selectionStatus, setSelectionStatus] = - React.useState("idle") - const [dragging, setDragging] = React.useState(false) - const [dragMode, setDragMode] = React.useState(false) - const [cursorMoving, setCursorMoving] = React.useState(false) - - const [min, max] = selection ?? [0, 0] - const leftCursorColor = !midPrice - ? "neutral" - : midPrice > min - ? "green" - : "red" - const rightCursorColor = !midPrice - ? "neutral" - : midPrice < max - ? "red" - : "green" - - // Update selection when value prop changes - React.useEffect(() => { - if (JSON.stringify(value) !== JSON.stringify(selection)) { - setSelection(value ?? null) - } - // eslint-disable-next-line react-hooks/exhaustive-deps - }, [value, xScale]) - - const handleMouseDown = React.useCallback( - (event: MouseEvent) => { - if (!event.buttons) return - - const svg = svgRef.current - if (svg) { - const svgRect = svg.getBoundingClientRect() - let xPixel = event.clientX - svgRect.left - xPixel = Math.max(0, Math.min(width, xPixel)) - const x = xScale.invert(xPixel) - if (xPixel >= 0 && xPixel <= width) { - if (selection && x >= selection[0] && x <= selection[1]) { - setDragging(true) - setDragMode(true) - startValueRef.current = x - selection[0] - } else if (!selection) { - startValueRef.current = x - setSelectionStatus("start") - setSelection([x, x]) - setDragMode(false) - } - } - } - }, - [selection, svgRef, width, xScale], - ) - - const handleMouseMove = React.useCallback( - (event: MouseEvent) => { - if (cursorMoving) return - const svg = svgRef.current - if (svg) { - const svgRect = svg.getBoundingClientRect() - const xPixel = event.clientX - svgRect.left - const x = xScale.invert(xPixel) - if ( - dragging && - dragMode && - selection && - startValueRef.current !== null - ) { - const dx = x - startValueRef.current - const newSelection: React.SetStateAction<[number, number] | null> = [ - dx, - dx + (selection[1] - selection[0]), - ] - setSelection(newSelection) // apply the offset - onBrushChange(newSelection) - } else if ( - !dragMode && - startValueRef.current !== null && - event.buttons !== 0 && - selectionStatus !== "end" - ) { - setSelection([startValueRef.current, x]) - } - } - }, - [ - cursorMoving, - svgRef, - xScale, - dragging, - dragMode, - selection, - selectionStatus, - onBrushChange, - ], - ) - - const handleMouseUp = React.useCallback(() => { - setCursorMoving(false) - setDragging(false) - setSelectionStatus("end") - if (selection !== null && onBrushEnd) { - onBrushEnd(selection.sort((a, b) => a - b) as [number, number]) - } - }, [onBrushEnd, selection]) - - const handleCursorMove = (type: "left" | "right", newPrice: number) => { - setCursorMoving(true) - if (!selection) return - if (type === "left") { - const newSelection: [number, number] = [newPrice, selection[1]] - setSelection(newSelection) - onBrushChange(newSelection) - } else { - const newSelection: [number, number] = [selection[0], newPrice] - setSelection(newSelection) - onBrushChange(newSelection) - } - } - - React.useEffect(() => { - if (viewOnly) return - const svg = svgRef.current - svg?.addEventListener("mousedown", handleMouseDown) - svg?.addEventListener("mousemove", handleMouseMove) - svg?.addEventListener("mouseup", handleMouseUp) - - return () => { - svg?.removeEventListener("mousedown", handleMouseDown) - svg?.removeEventListener("mousemove", handleMouseMove) - svg?.removeEventListener("mouseup", handleMouseUp) - } - }, [handleMouseDown, handleMouseMove, handleMouseUp, svgRef, viewOnly]) - - const brushWidth = selection - ? Math.abs(xScale(selection[1]) - xScale(selection[0])) - : 0 - const brushX = selection - ? Math.min(xScale(selection[0]), xScale(selection[1])) - : 0 - - const leftCursorPos = selection ? xScale(selection[0]) : 0 - const rightCursorPos = selection ? xScale(selection[1]) : 0 - - return ( - <> - {selection && ( - - )} - {selection && ( - <> - handleCursorMove("left", newXPosition)} - xScale={xScale} - svgRef={svgRef} - viewOnly={viewOnly} - hidden={selectionStatus === "start"} - /> - handleCursorMove("right", newXPosition)} - xScale={xScale} - svgRef={svgRef} - viewOnly={viewOnly} - hidden={selectionStatus === "start"} - /> - - )} - - ) -} - -export default CustomBrush diff --git a/app/strategies/new/_components/price-range/components/price-chart/merged-offer-tooltip.tsx b/app/strategies/new/_components/price-range/components/price-chart/merged-offer-tooltip.tsx deleted file mode 100644 index 79e4bf5b..00000000 --- a/app/strategies/new/_components/price-range/components/price-chart/merged-offer-tooltip.tsx +++ /dev/null @@ -1,84 +0,0 @@ -import { Token } from "@mangrovedao/mgv" -import { TooltipWithBounds } from "@visx/tooltip" -import { ScaleLinear } from "d3-scale" - -import { Title } from "@/components/typography/title" -import { cn } from "@/utils" -import { OfferParsed } from "@mangrovedao/mgv" -import { BA } from "@mangrovedao/mgv/lib" -import { TypedDistrubutionOffer } from "./geometric-distribution-dots" - -type Props = { - height: number - paddingBottom: number - xScale: ScaleLinear - onHover?: (offer: TypedDistrubutionOffer) => void - onHoverOut?: () => void - mergedOffer: OfferParsed - baseToken: Token - quoteToken: Token -} - -export function StatusBadge({ isLive }: { isLive: boolean }) { - return ( -
- - - {isLive ? "Live" : "Empty"} - -
- ) -} - -export function MergedOfferTooltip({ - height, - paddingBottom, - xScale: xScaleTransformed, - mergedOffer, - baseToken, - quoteToken, -}: Props) { - const isLive = mergedOffer.gives > 0 - return ( - -
- -
- Price:{" "} - {Number(mergedOffer.price).toFixed(quoteToken?.displayDecimals)}{" "} - {quoteToken?.symbol} -
-
- Volume:{" "} - {Number(mergedOffer.gives).toFixed( - (mergedOffer.ba === BA.bids ? quoteToken : baseToken) - ?.displayDecimals, - )}{" "} - {(mergedOffer.ba === BA.bids ? quoteToken : baseToken)?.symbol} -
-
-
- ) -} diff --git a/app/strategies/new/_components/price-range/components/price-chart/mid-price-line.tsx b/app/strategies/new/_components/price-range/components/price-chart/mid-price-line.tsx deleted file mode 100644 index e612bd49..00000000 --- a/app/strategies/new/_components/price-range/components/price-chart/mid-price-line.tsx +++ /dev/null @@ -1,23 +0,0 @@ -import { type ScaleLinear } from "d3-scale" - -type Props = { - xScale: ScaleLinear - midPrice: number | undefined - height: number -} - -export function MidPriceLine({ xScale, midPrice, height }: Props) { - if (!midPrice) return null - const xPosition = xScale(midPrice) - return ( - - ) -} diff --git a/app/strategies/new/_components/price-range/components/price-chart/range-tooltips.tsx b/app/strategies/new/_components/price-range/components/price-chart/range-tooltips.tsx deleted file mode 100644 index 017c53c7..00000000 --- a/app/strategies/new/_components/price-range/components/price-chart/range-tooltips.tsx +++ /dev/null @@ -1,113 +0,0 @@ -import { cn } from "@/utils" -import { calculatePriceDifferencePercentage } from "@/utils/numbers" -import { Tooltip } from "@visx/tooltip" -import type { ScaleLinear } from "d3-scale" - -type Props = { - height: number - paddingBottom: number - xScale: ScaleLinear - selectedPriceRange?: [number, number] | null - midPrice?: number | null -} - -export function RangeTooltips({ - height, - paddingBottom, - xScale: xScaleTransformed, - selectedPriceRange, - midPrice, -}: Props) { - const [min, max] = selectedPriceRange ?? [0, 0] - - const minColor = !midPrice ? "neutral" : midPrice > min ? "green" : "red" - const maxColor = !midPrice ? "neutral" : midPrice < max ? "red" : "green" - - return ( - <> - {min && max ? ( - <> - - - - ) : undefined} - {midPrice ? ( - -
- Mid {midPrice.toFixed(2)} -
-
- ) : undefined} - - ) -} - -type RangeTooltipProps = { - height: number - paddingBottom: number - xScale: ScaleLinear - value: number - color: "green" | "red" | "neutral" - text: string - midPrice?: number | null -} - -function RangeTooltip({ - height, - paddingBottom, - xScale: xScaleTransformed, - value, - color, - text, - midPrice, -}: RangeTooltipProps) { - const percentage = calculatePriceDifferencePercentage({ - price: midPrice, - value, - }) - - return ( - -
- {text} {value.toFixed(2)} {midPrice ? `${percentage.toFixed(2)}%` : ""} -
-
- ) -} diff --git a/app/strategies/new/_components/price-range/components/price-chart/set-range-animation.tsx b/app/strategies/new/_components/price-range/components/price-chart/set-range-animation.tsx deleted file mode 100644 index 2d7940ec..00000000 --- a/app/strategies/new/_components/price-range/components/price-chart/set-range-animation.tsx +++ /dev/null @@ -1,74 +0,0 @@ -/* eslint-disable @typescript-eslint/no-explicit-any */ -import { useGSAP } from "@gsap/react" -import { gsap } from "gsap" -import { MousePointer, MousePointerClick } from "lucide-react" -import React from "react" - -export function SetRangeAnimation() { - const pointerRef = React.useRef(null) - const clickRef = React.useRef(null) - const containerRef = React.useRef(null) - - useGSAP( - () => { - if (!containerRef.current) return - gsap - .timeline({ - repeat: -1, - }) - .from(clickRef.current, { - display: "none", - }) - .from( - pointerRef.current, - { - opacity: 0, - }, - "<", - ) - .to( - pointerRef.current, - { - opacity: 1, - }, - "<", - ) - .to( - pointerRef.current, - { - display: "none", - }, - "<", - ) - .to(clickRef.current, { - display: "block", - opacity: 1, - }) - .to( - clickRef.current, - { - x: containerRef.current?.offsetWidth / 2, - duration: 2.5, - delay: 0.3, - ease: "Expo.out", - }, - "<", - ) - .to(clickRef.current, { - delay: 0.3, - opacity: 0, - }) - .play() - }, - { - scope: containerRef, - }, - ) - - return ( -
- - -
- ) -} diff --git a/app/strategies/new/_components/price-range/price-range.tsx b/app/strategies/new/_components/price-range/price-range.tsx index d3b34fd2..7ae588d0 100644 --- a/app/strategies/new/_components/price-range/price-range.tsx +++ b/app/strategies/new/_components/price-range/price-range.tsx @@ -13,9 +13,9 @@ import { calculatePriceDifferencePercentage, calculatePriceFromPercentage, } from "@/utils/numbers" +import { PriceRangeChart } from "../../../(shared)/_components/price-chart/price-range-chart" import { ChangingFrom, useNewStratStore } from "../../_stores/new-strat.store" import DeployStrategyDialog from "../launch-strategy-dialog" -import { PriceRangeChart } from "./components/price-chart/price-range-chart" import { RiskAppetiteBadge } from "./components/risk-appetite" export const PriceRange = withClientOnly(function ({ diff --git a/app/strategies/new/layout.tsx b/app/strategies/new/layout.tsx index 122bf904..8daf7dca 100644 --- a/app/strategies/new/layout.tsx +++ b/app/strategies/new/layout.tsx @@ -1,11 +1,10 @@ import { Metadata } from "next" import React from "react" -import { KandelStrategiesProvider } from "@/app/strategies/(list)/_providers/kandel-strategies" import { Navbar } from "@/components/navbar" import { IndexerSdkProvider } from "@/providers/mangrove-indexer" -import { MarketProvider } from "@/providers/market.new" +import { MarketProvider } from "@/providers/market.new" import WarningBanner from "../(shared)/_components/warning-banner" import { KandelStrategyProvider } from "../[address]/_providers/kandel-strategy" @@ -18,13 +17,11 @@ export default function Layout({ children }: React.PropsWithChildren) { return ( - - - - -
{children}
-
-
+ + + +
{children}
+
) diff --git a/app/strategies/vault/_hooks/useVault.ts b/app/strategies/vault/_hooks/useVault.ts index 25b29a2c..88970926 100644 --- a/app/strategies/vault/_hooks/useVault.ts +++ b/app/strategies/vault/_hooks/useVault.ts @@ -2,14 +2,14 @@ import { useMangroveAddresses } from "@/hooks/use-addresses" import { kandelActions } from "@mangrovedao/mgv" import { useQuery } from "@tanstack/react-query" import { getAddress, isAddress, isAddressEqual } from "viem" -import { useAccount, useChainId, usePublicClient } from "wagmi" +import { useAccount, usePublicClient } from "wagmi" import { getChainVaults, getVaultsInformation, } from "../../(list)/_components/tables/vaults/services/skate-vaults" export function useVault(id?: string | null) { - const chainId = useChainId() + const { chainId } = useAccount() const { address: user } = useAccount() const publicClient = usePublicClient() const params = useMangroveAddresses() @@ -18,7 +18,7 @@ export function useVault(id?: string | null) { queryFn: async () => { if (!publicClient || !params) throw new Error("Public client is not enabled") - if (!id) return { vault: undefined, kandelState: undefined } + if (!id || !chainId) return { vault: undefined, kandelState: undefined } if (!isAddress(id)) throw new Error("Invalid address") const vaultAddress = getAddress(id) const vault = getChainVaults(chainId).find((v) => @@ -36,7 +36,7 @@ export function useVault(id?: string | null) { kandelState, } }, - enabled: !!publicClient && !!params, + enabled: !!publicClient && !!params && !!chainId, initialData: { vault: undefined, kandelState: undefined }, }) } diff --git a/app/trade/_components/charts/depth-chart/depth-chart.tsx b/app/trade/_components/charts/depth-chart/depth-chart.tsx index 4c3f8ec8..e003ee21 100644 --- a/app/trade/_components/charts/depth-chart/depth-chart.tsx +++ b/app/trade/_components/charts/depth-chart/depth-chart.tsx @@ -13,8 +13,8 @@ import { XYChart, } from "@visx/xychart" +import { Skeleton } from "@/components/ui/skeleton" import { lerp } from "@/utils/interpolation" -import { Skeleton } from "@components/ui/skeleton" import { CompleteOffer } from "@mangrovedao/mgv" import { DataKeyType } from "./enums" import { @@ -68,7 +68,7 @@ export function DepthChart() { ) } - if (!midPrice || isLoading) { + if (isLoading) { return ( ) diff --git a/app/trade/_components/forms/amplified/amplified.tsx b/app/trade/_components/forms/amplified/amplified.tsx deleted file mode 100644 index 03129878..00000000 --- a/app/trade/_components/forms/amplified/amplified.tsx +++ /dev/null @@ -1,511 +0,0 @@ -"use client" - -const sliderValues = [25, 50, 75, 100] - -export function Amplified() { - // const { - // errors, - // sendSource, - // sendAmount, - // markets, - // sendToken, - // assets, - // assetsWithTokens, - // timeInForce, - // timeToLive, - // timeToLiveUnit, - // useAbleTokens, - // balanceLogic_temporary, - // tickSize, - // selectedToken, - // selectedSource, - // currentTokens, - // availableTokens, - // logics, - // minVolume, - // setSendAmount, - // handleSendSource, - // handleSentAmountChange, - // handeSendTokenChange, - // handleAssetsChange, - // handleTimeInForceChange, - // handleTimeToLiveChange, - // handleTimeToLiveUnit, - // } = useAmplifiedForm() - // const handleSliderChange = (value: number) => { - // const amount = (value * Number(balanceLogic_temporary)) / 100 - // setSendAmount(amount.toString()) - // // if(!sendToken) setAssets([]) - // } - // const [summaryDialog, setSummaryDialog] = React.useState(false) - // const sendTokenBalanceAsBig = balanceLogic_temporary - // ? Big(Number(balanceLogic_temporary)) - // : Big(0) - // const sliderValue = Math.min( - // Big(!isNaN(Number(sendAmount)) ? Number(sendAmount) : 0) - // .mul(100) - // .div(sendTokenBalanceAsBig.eq(0) ? 1 : sendTokenBalanceAsBig) - // .toNumber(), - // 100, - // ).toFixed(0) - // const selectedTokens = assets ? assets.map((asset) => asset.token) : [] - // const isAmplifiable = currentTokens.length > 1 - // const tokensLeft = selectedTokens.length < currentTokens.length - // if (!logics) - // return ( - //
- // - //
- // ) - // const isAssetsEmpty = assets.some( - // (asset) => !asset.token || !asset.amount || !asset.limitPrice, - // ) - // return ( - //
- //
- // - // Place multiple limit orders using the same liquidity. - // - // - // - // The execution of one order will automatically update others - // - // - // if partially filled or cancel others if fully filled.{" "} - // - // - // Learn more - // - // - //
- //
{ - // e.preventDefault() - // }} - // > - //
- // Liquidity sourcing - //
- // - //
- //
- // { - // handleSentAmountChange(e.target.value) - // }} - // disabled={!sendToken || balanceLogic_temporary === "0"} - // error={errors.sendAmount} - // /> - // - //
- // {sendToken ? ( - // { - // handleSentAmountChange(balanceLogic_temporary || "0") - // }, - // }} - // /> - // ) : undefined} - // {sendToken && minVolume.volume ? ( - // { - // handleSentAmountChange(minVolume.total.toString()) - // }, - // }} - // /> - // ) : undefined} - //
- // { - // handleSliderChange(Number(value)) - // }} - // disabled={!sendToken} - // /> - //
- // {sliderValues.map((value) => ( - // - // ))} - //
- //
- // {selectedToken?.address && !isAmplifiable ? ( - // - // Only one market is available for this asset, please post a limit - // order instead. - // - // ) : undefined} - // {assets.map((asset, i) => { - // return ( - //
- //
- // - // Buy Asset #{i + 1} - // - // - //
- //
- // - //
- // { - // handleAssetsChange([ - // ...assets.slice(0, i), - // { - // ...asset, - // limitPrice: e.target.value, - // }, - // ...assets.slice(i + 1), - // ]) - // }} - // token={getCurrentTokenPrice(asset.token, markets)} - // label="Limit price" - // disabled={!asset.token} - // error={errors[`limitPrice-${i}`]} - // /> - //
- // - // Receive to - // - // - // {errors[`receiveTo-${i}`] ? ( - // - // {errors[`receiveTo-${i}`]} - // - // ) : undefined} - //
- //
- // - // Receiving amount - // - // {asset.amount ? ( - // - // {Number(asset.amount).toFixed( - // availableTokens.find( - // (token) => token.address === asset.token, - // )?.displayDecimals, - // )}{" "} - // { - // availableTokens.find( - // (token) => token.address === asset.token, - // )?.symbol - // } - // - // ) : ( - // "-" - // )} - //
- // {selectedToken ? ( - //
- // - //
- // ) : undefined} - // {i !== assets.length - 1 ? ( - //
- // - // or - // - //
- // ) : undefined} - //
- // ) - // })} - //
- // - // - // - //
- // - // - //
- //
- // { - // if (!value) return - // handleTimeToLiveChange(value) - // }} - // error={errors["timeToLive"]} - // /> - // - //
- //
- // - // {Object.entries(errors).map(([key, value]) => ( - // {value} - // ))} - // - // - // {/* { - // setSummaryDialog(!summaryDialog) - // }} - // isOpen={summaryDialog} - // /> */} - //
- // ) -} diff --git a/app/trade/_components/forms/amplified/components/from-wallet-order-dialog.tsx b/app/trade/_components/forms/amplified/components/from-wallet-order-dialog.tsx deleted file mode 100644 index 322efd83..00000000 --- a/app/trade/_components/forms/amplified/components/from-wallet-order-dialog.tsx +++ /dev/null @@ -1,209 +0,0 @@ -import type { Token } from "@mangrovedao/mgv" -import { Logic } from "@mangrovedao/mgv" - -import { type ButtonProps } from "@/components/ui/button" -import type { AssetWithInfos, Form } from "../types" - -/** - * Props for the FromWalletOrderDialog component. - */ -type Props = { - form: Omit & { - selectedToken?: Token - selectedSource?: Logic - sendAmount: string - assetsWithTokens: AssetWithInfos[] - } - onClose: () => void - isOpen: boolean -} - -const btnProps: ButtonProps = { - rightIcon: true, - className: "w-full", - size: "lg", -} - -export default function FromWalletAmplifiedOrderDialog({ - form, - isOpen, - onClose, -}: Props) { - // const { selectedToken, selectedSource, sendAmount } = form - // const { chain, address } = useAccount() - // const { data: spender } = useSpenderAddress("amplified") - // const { data: limitOrderSteps } = useLimitSteps({ - // user: address, - // bs: BS.buy, - // logic: form.selectedSource?.name, - // }) - // // const { isDeployed, isBound } = useSmartRouter().data ?? {} - // let steps = [ - // "Summary", - // !limitOrderSteps?.[0].done ? `Approve ${selectedToken?.symbol}` : "", - // false ? "Amplified order deployment" : "", - // !true ? "Amplified order activation" : "", - // "Send", - // ].filter(Boolean) - // const isDialogOpenRef = React.useRef(false) - // React.useEffect(() => { - // isDialogOpenRef.current = !!form - // return () => { - // isDialogOpenRef.current = false - // } - // }, [form]) - // const approve = useInfiniteApproveToken() - // const activate = useActivateSmartContract() - // const deploy = useDeploySmartRouter({}) - // const post = usePostAmplifiedOrder({ - // onResult: (result) => { - // /* - // * We use a React ref to track the dialog's open state. If the dialog is closed, - // * we prevent further actions. This is necessary because the dialog's closure - // * might occur before the asynchronous operations complete, potentially leading - // * to undesired effects. - // */ - // if (!isDialogOpenRef.current) return - // onClose() - // tradeService.openTxCompletedDialog({ - // address: result.transactionHash ?? "", - // blockExplorerUrl: chain?.blockExplorers?.default.url, - // }) - // }, - // }) - // const [currentStep, helpers] = useStep(steps.length) - // const { goToNextStep } = helpers - // const stepInfos = [ - // !limitOrderSteps?.[0].done && { - // body: ( - // - // ), - // button: ( - // - // ), - // }, - // !limitOrderSteps?.[0].done && { - // body: , - // button: ( - // - // ), - // }, - // true && { - // body: , - // button: ( - // - // ), - // }, - // true && { - // body: , - // button: ( - // - // ), - // }, - // { - // body: ( - // - // ), - // button: ( - // - // ), - // }, - // ] - // .filter(Boolean) - // .map((stepInfo, i) => { - // return { - // ...stepInfo, - // title: steps[i], - // } - // }) - // return ( - // - // - // Proceed transaction - // - // - // - //
- // {stepInfos[currentStep - 1]?.body ?? undefined} - //
- //
- // {stepInfos[currentStep - 1]?.button} - //
- // ) -} diff --git a/app/trade/_components/forms/amplified/components/summary-step.tsx b/app/trade/_components/forms/amplified/components/summary-step.tsx deleted file mode 100644 index 95cab4ca..00000000 --- a/app/trade/_components/forms/amplified/components/summary-step.tsx +++ /dev/null @@ -1,118 +0,0 @@ -import type { Logic, Token } from "@mangrovedao/mgv" -import Big from "big.js" - -import { TokenIcon } from "@/components/token-icon" -import { Text } from "@/components/typography/text" -import { Separator } from "@/components/ui/separator" -import { cn } from "@/utils" -import { TimeInForce } from "../enums" -import type { AssetWithInfos, Form } from "../types" - -type Props = { - form: Omit - tokenToAmplify?: Token - sendAmount: string - source: Logic - assetsWithToken?: AssetWithInfos[] -} - -export function SummaryStep({ - tokenToAmplify, - assetsWithToken, - source, - form, -}: Props) { - return ( -
-
- Amplify - - - {tokenToAmplify?.symbol} - -
- - {Big( - !isNaN(Number(form.sendAmount)) ? Number(form.sendAmount) : 0, - ).toFixed(8)}{" "} - {tokenToAmplify?.symbol} - - -
- {assetsWithToken?.map( - (asset) => - asset.token && - asset.receiveTo && ( - <> -
- - - {asset.token.symbol} - -
- - - {Big( - !isNaN(Number(asset.limitPrice)) - ? Number(asset.limitPrice) - : 0, - ).toFixed(asset.token.priceDisplayDecimals)}{" "} - {asset.token.symbol} - - - {Big( - !isNaN(Number(asset.amount)) ? Number(asset.amount) : 0, - ).toFixed(asset.token.displayDecimals)}{" "} - {asset.token.symbol} - - - ), - )} - - -
- {form.timeInForce}{" "} - {form.timeInForce === TimeInForce.GOOD_TIL_TIME && ( - - {form.timeToLive}{" "} - - {Number(form.timeToLive) > 1 - ? `${form.timeToLiveUnit}s` - : form.timeToLiveUnit} - - - )} -
-
-
-
- ) -} - -type LineProps = { - title: string -} - -function Line({ - title, - children, - className, -}: LineProps & { children: React.ReactNode; className?: string }) { - return ( -
- {title} - {children} -
- ) -} - -function Unit({ children }: { children: React.ReactNode }) { - return {children} -} diff --git a/app/trade/_components/forms/amplified/enums.ts b/app/trade/_components/forms/amplified/enums.ts deleted file mode 100644 index c637cc69..00000000 --- a/app/trade/_components/forms/amplified/enums.ts +++ /dev/null @@ -1,11 +0,0 @@ -export enum TimeInForce { - IMMEDIATE_OR_CANCEL = "Immediate or cancel", - GOOD_TIL_TIME = "Good til time", - FILL_OR_KILL = "Fill or kill", -} - -export enum TimeToLiveUnit { - MIN = "Minute", - HOUR = "Hour", - DAY = "Day", -} diff --git a/app/trade/_components/forms/amplified/hooks/amplified-liquidity-sourcing.ts b/app/trade/_components/forms/amplified/hooks/amplified-liquidity-sourcing.ts deleted file mode 100644 index 285dd41a..00000000 --- a/app/trade/_components/forms/amplified/hooks/amplified-liquidity-sourcing.ts +++ /dev/null @@ -1,87 +0,0 @@ -import { Logic, Token } from "@mangrovedao/mgv" -import React from "react" - -type Props = { - sendFrom?: string - logics: Logic[] - fundOwner?: string - sendToken?: Token - availableTokens?: Token[] -} - -type BalanceLogic = { - formatted: string - balance: number -} - -export default function amplifiedLiquiditySourcing({ - sendToken, - sendFrom, - logics, - fundOwner, - availableTokens, -}: Props) { - const [sendFromBalance, setSendFromBalance] = React.useState< - BalanceLogic | undefined - >() - - const [useAbleTokens, setUseAbleTokens] = React.useState< - (Token | undefined)[] - >([]) - - const getPossibleLogicsForToken = async () => { - if (!availableTokens) return - const tokenToTest = availableTokens.map(async (token) => { - if (sendFrom !== "simple") { - try { - // const selectedLogic = logics.find((logic) => logic?.id === sendFrom) - // await selectedLogic?.overlying(token) - return token - } catch (error) { - return - } - } else { - return token - } - }) - - const usableTokens = await Promise.all(tokenToTest) - setUseAbleTokens(usableTokens) - } - - const getSendBalance = async (token: Token, fundOwner: string) => { - try { - if (sendFrom === "simple") { - setSendFromBalance(undefined) - return - } - - const selectedLogic = logics.find((logic) => logic?.name === sendFrom) - - if (!selectedLogic) return - - // const logicBalance = await selectedLogic.balanceOfFromLogic( - // token, - // fundOwner, - // ) - - setSendFromBalance({ - formatted: "", - balance: 0, - }) - } catch (error) { - return - } - } - - React.useEffect(() => { - getPossibleLogicsForToken() - if (!sendFrom || !sendToken || !fundOwner) return - getSendBalance(sendToken, fundOwner) - }, [sendFrom, sendToken, fundOwner]) - - return { - sendFromBalance, - useAbleTokens, - } -} diff --git a/app/trade/_components/forms/amplified/hooks/amplified-store.ts b/app/trade/_components/forms/amplified/hooks/amplified-store.ts deleted file mode 100644 index f70637d7..00000000 --- a/app/trade/_components/forms/amplified/hooks/amplified-store.ts +++ /dev/null @@ -1,88 +0,0 @@ -import { create, type StateCreator } from "zustand" -import { TimeInForce, TimeToLiveUnit } from "../enums" -import { Asset } from "../types" - -export type ChangingFrom = - | "sendSource" - | "sendAmount" - | "sendToken" - | "assets" - | "timeInForce" - | "timeToLive" - | "timeToLiveUnit" - | undefined - | null - -export type NewStratStore = { - sendSource: string - sendAmount: string - sendToken: string - minVolume: { total: string; volume: string } - assets: Asset[] - timeInForce: TimeInForce - timeToLive: string - timeToLiveUnit: TimeToLiveUnit - - isChangingFrom: ChangingFrom - globalError?: string - errors: Record -} - -type NewStratActions = { - setSendSource: (source: string) => void - setSendAmount: (amount: string) => void - setSendToken: (token: string) => void - setMinVolume: (minVolume: { total: string; volume: string }) => void - setAssets: (assets: Asset[]) => void - setTimeInForce: (timeInForce: TimeInForce) => void - setTimeToLive: (timeInForce: string) => void - setTimeToLiveUnit: (timeInForce: TimeToLiveUnit) => void - - setGlobalError: (error?: string) => void - setErrors: (errors: Record) => void - setIsChangingFrom: (isChangingFrom: ChangingFrom) => void -} - -const newStratStateCreator: StateCreator = ( - set, -) => ({ - sendSource: "", - sendAmount: "", - sendToken: "", - minVolume: { total: "0", volume: "0" }, - assets: [ - { - amount: "", - token: "", - limitPrice: "", - receiveTo: "simple", - }, - { - amount: "", - token: "", - limitPrice: "", - receiveTo: "simple", - }, - ], - timeInForce: TimeInForce.GOOD_TIL_TIME, - timeToLive: "28", - timeToLiveUnit: TimeToLiveUnit.DAY, - - isChangingFrom: null, - globalError: undefined, - errors: {}, - - setSendSource: (sendSource) => set({ sendSource }), - setSendAmount: (sendAmount) => set({ sendAmount }), - setSendToken: (sendToken) => set({ sendToken }), - setMinVolume: (minVolume) => set({ minVolume }), - setAssets: (assets) => set({ assets }), - setTimeInForce: (timeInForce) => set({ timeInForce }), - setTimeToLive: (timeToLive) => set({ timeToLive }), - setTimeToLiveUnit: (timeToLiveUnit) => set({ timeToLiveUnit }), - setGlobalError: (globalError) => set({ globalError }), - setErrors: (errors) => set({ errors }), - setIsChangingFrom: (isChangingFrom) => set({ isChangingFrom }), -}) - -export const useNewStratStore = create(newStratStateCreator) diff --git a/app/trade/_components/forms/amplified/hooks/use-amplified.ts b/app/trade/_components/forms/amplified/hooks/use-amplified.ts deleted file mode 100644 index af483b10..00000000 --- a/app/trade/_components/forms/amplified/hooks/use-amplified.ts +++ /dev/null @@ -1,387 +0,0 @@ -import { Logic } from "@mangrovedao/mgv" -import { minVolume as getMinimumVolume } from "@mangrovedao/mgv/lib" -import Big from "big.js" -import React from "react" -import { useAccount } from "wagmi" - -import { useBook } from "@/hooks/use-book" -import { - default as useMarket, - default as useMarketNew, -} from "@/providers/market.new" -import { useEventListener } from "usehooks-ts" -import { TimeInForce, TimeToLiveUnit } from "../enums" -import { Asset, AssetWithInfos } from "../types" -import { getCurrentTokenPrice } from "../utils" -import amplifiedLiquiditySourcing from "./amplified-liquidity-sourcing" -import { ChangingFrom, useNewStratStore } from "./amplified-store" - -import { useLogics } from "@/hooks/use-addresses" -import { LocalConfig, Token } from "@mangrovedao/mgv" -import { formatUnits } from "viem" - -export const MIN_PRICE_POINTS = 2 -export const MIN_RATIO = 1.001 -export const MIN_STEP_SIZE = 1 - -export default function useAmplifiedForm() { - const { address } = useAccount() - // const { mangrove, marketsInfoQuery } = useMangrove() - const { currentMarket } = useMarket() - const { book } = useBook() - const logics = useLogics() - - const { currentMarket: market, markets } = useMarketNew() - - const { - setGlobalError, - errors, - setErrors, - isChangingFrom, - setIsChangingFrom, - sendSource, - sendAmount, - sendToken, - assets, - timeInForce, - timeToLive, - timeToLiveUnit, - setSendSource, - setSendAmount, - setSendToken, - setAssets, - setTimeInForce, - setTimeToLive, - setTimeToLiveUnit, - setMinVolume, - minVolume, - } = useNewStratStore() - - // TODO: fix TS type for useEventListener - // @ts-expect-error - useEventListener("on-orderbook-offer-clicked", handleOnOrderbookOfferClicked) - - function handleOnOrderbookOfferClicked( - event: CustomEvent<{ price: string }>, - ) { - let newAssets = [...assets] - - assets.forEach((asset, i) => { - if (!asset) return - - const tokenPrice = getCurrentTokenPrice(asset.token, markets) - - if (tokenPrice?.address === market?.quote.address) { - newAssets[i] = { - ...asset, - limitPrice: event.detail.price, - } - } - }) - - handleAssetsChange(newAssets) - } - - const availableTokens = - markets?.reduce((acc, current) => { - if (!acc.includes(current.base)) { - acc.push(current.base) - } - if (!acc.includes(current.quote)) { - acc.push(current.quote) - } - - return acc - }, [] as Token[]) ?? [] - - const tickSize = currentMarket?.tickSpacing - ? `${((1.0001 ** Number(currentMarket?.tickSpacing) - 1) * 100).toFixed(2)}%` - : "" - - const selectedToken = availableTokens.find( - (token) => token.address == sendToken, - ) - - const selectedSource = logics?.find((logic) => logic?.name == sendSource) - - const compatibleMarkets = markets?.filter( - (market) => - market.base.address === selectedToken?.address || - market.quote.address === selectedToken?.address, - ) - - const currentTokens = availableTokens?.filter((token) => { - if (selectedToken?.address === token.address) return false - - return compatibleMarkets?.some( - (market) => - market.base.address == token.address || - market.quote.address == token.address, - ) - }) - - const assetsWithTokens = assets.map((asset) => ({ - ...asset, - token: availableTokens.find((tokens) => tokens.address === asset.token), - receiveTo: logics.find((logic) => logic?.name === asset.receiveTo), - })) - - const { useAbleTokens, sendFromBalance } = amplifiedLiquiditySourcing({ - availableTokens, - sendToken: selectedToken, - sendFrom: sendSource, - fundOwner: address, - logics: logics as Logic[], - }) - - const balanceLogic_temporary = sendFromBalance?.formatted - - const handleFieldChange = (field: ChangingFrom) => { - setIsChangingFrom(field) - } - - const handleSendSource = ( - e: React.ChangeEvent | string, - ) => { - handleFieldChange("sendSource") - const value = typeof e === "string" ? e : e.target.value - setSendSource(value) - } - - const computeReceiveAmount = ( - amount: string, - limitPrice: string, - tokenId: string, - ) => { - if (!limitPrice || !amount) return "0" - if (markets?.find((market) => market.base.address === tokenId)) { - return Big(!isNaN(Number(amount)) ? Number(amount) : 0) - .div( - Big( - !isNaN(Number(limitPrice)) && Number(limitPrice) > 0 - ? Number(limitPrice) - : 1, - ), - ) - .toString() - } else { - return Big(!isNaN(Number(limitPrice)) ? Number(limitPrice) : 0) - .times( - Big( - !isNaN(Number(amount)) && Number(amount) > 0 ? Number(amount) : 0, - ), - ) - .toString() - } - } - - const handeSendTokenChange = ( - e: React.ChangeEvent | string, - ) => { - handleFieldChange("sendToken") - const value = typeof e === "string" ? e : e.target.value - setSendToken(value) - } - - const handleSentAmountChange = ( - e: React.ChangeEvent | string, - ) => { - handleFieldChange("sendAmount") - const value = typeof e === "string" ? e : e.target.value - setSendAmount(value) - } - - React.useEffect(() => { - handleAssetsChange( - assets.map((asset) => { - const amount = computeReceiveAmount( - sendAmount, - asset.limitPrice, - asset.token, - ) - return { - ...asset, - amount: !sendAmount ? "0" : amount, - } - }), - ) - }, [sendAmount]) - - const handleAssetsChange = ( - e: React.ChangeEvent | Asset[], - ) => { - handleFieldChange("assets") - const value = Array.isArray(e) ? e : [] - setAssets( - value.map((asset) => { - const amount = computeReceiveAmount( - sendAmount, - asset.limitPrice, - asset.token, - ) - return { - ...asset, - amount, - } - }), - ) - } - - const handleTimeInForceChange = ( - e: React.ChangeEvent | TimeInForce, - ) => { - handleFieldChange("timeInForce") - const value = typeof e === "string" ? e : TimeInForce.IMMEDIATE_OR_CANCEL - setTimeInForce(value) - } - - const handleTimeToLiveChange = ( - e: React.ChangeEvent | string, - ) => { - handleFieldChange("timeToLive") - const value = typeof e === "string" ? e : e.target.value - setTimeToLive(value) - } - - const handleTimeToLiveUnit = ( - e: React.ChangeEvent | TimeToLiveUnit, - ) => { - handleFieldChange("timeToLiveUnit") - const value = typeof e === "string" ? e : TimeToLiveUnit.DAY - setTimeToLive(value) - } - - React.useEffect(() => { - const selectedSourceGasOverhead = selectedSource?.gasreq || 200_000 - const semibookAsks = book?.asks - const semibookBids = book?.bids - const isBid = markets?.find( - (market) => market.base.address === sendToken, - )?.quote - const priceToken = isBid - const variableCost = Big(60_000).mul(assetsWithTokens.length).add(60_000) - - // const calculateGasReq = (asset: AssetWithInfos) => { - // return BigInt( - // Math.max( - // Number(asset.receiveTo?.gasreq || 200_000), - // Number(selectedSourceGasOverhead), - // ), - // ) + BigInt(variableCost) - // } - - const calculateGasReq = (asset: AssetWithInfos) => { - const maxGasReq = Math.max( - Number(asset.receiveTo?.gasreq || 200_000), - Number(selectedSourceGasOverhead), - ) - const totalGasReq = Big(maxGasReq).add(variableCost) - return BigInt(totalGasReq.toString()) - } - - const calculateMinVolume = ( - asset: AssetWithInfos, - localConfig: LocalConfig, - ) => { - if (!asset.token || !asset.limitPrice || !localConfig) return 0n - return getMinimumVolume(localConfig, calculateGasReq(asset)) - } - - const newMinVolume = assetsWithTokens.reduce((acc, asset) => { - if (!book) return 0n - const semibook = isBid ? book?.asksConfig : book?.bidsConfig - return acc + calculateMinVolume(asset as AssetWithInfos, semibook) - }, 0n) - - setMinVolume({ - total: formatUnits( - newMinVolume, - (isBid - ? selectedToken?.displayDecimals - : priceToken?.displayDecimals) || 8, - ), - volume: formatUnits(newMinVolume, selectedToken?.displayDecimals || 8), - }) - }, [assets, sendToken]) - - React.useEffect(() => { - const newErrors = { ...errors } - - if (Number(sendAmount) > Number(balanceLogic_temporary) && sendAmount) { - newErrors.sendAmount = "Amount cannot be greater than wallet balance" - } else if (Number(sendAmount) <= 0 && sendAmount) { - newErrors.sendAmount = "Amount must be greater than 0" - } else if (sendAmount && minVolume.total && minVolume.total > sendAmount) { - newErrors.sendAmount = "Amount cannot be lower than min. volume" - } else { - delete newErrors.sendAmount - } - - assets.map((asset, index) => { - if (Number(asset.limitPrice) <= 0 && asset.limitPrice) { - newErrors[`limitPrice-${index}`] = "Limit Price must be greater than 0" - } else if (!asset.receiveTo && asset.token) { - newErrors[`receiveTo-${index}`] = "Please select a receive logic" - } else if (!asset.token && asset.limitPrice) { - newErrors[`token-${index}`] = "Please select a token" - } else { - delete newErrors[`limitPrice-${index}`] - delete newErrors[`receiveTo-${index}`] - delete newErrors[`token-${index}`] - } - }) - - setErrors(newErrors) - }, [ - minVolume, - sendSource, - sendAmount, - sendToken, - assets, - timeInForce, - timeToLive, - timeToLiveUnit, - ]) - - return { - errors, - isChangingFrom, - markets, - sendSource, - minVolume, - sendAmount, - sendToken, - assets, - timeInForce, - timeToLive, - timeToLiveUnit, - tickSize, - selectedToken, - selectedSource, - currentTokens, - useAbleTokens, - sendFromBalance, - balanceLogic_temporary, - assetsWithTokens, - address, - availableTokens, - logics, - setGlobalError, - setIsChangingFrom, - setErrors, - setSendSource, - setSendAmount, - setSendToken, - setAssets, - setTimeInForce, - setTimeToLive, - setTimeToLiveUnit, - handleSendSource, - handleSentAmountChange, - handeSendTokenChange, - handleAssetsChange, - handleTimeInForceChange, - handleTimeToLiveChange, - handleTimeToLiveUnit, - } -} diff --git a/app/trade/_components/forms/amplified/hooks/use-post-amplified-order.ts b/app/trade/_components/forms/amplified/hooks/use-post-amplified-order.ts deleted file mode 100644 index e42dc428..00000000 --- a/app/trade/_components/forms/amplified/hooks/use-post-amplified-order.ts +++ /dev/null @@ -1,143 +0,0 @@ -import { TransactionReceipt } from "@ethersproject/providers" - -type Props = { - onResult?: (result: TransactionReceipt) => void -} - -export function usePostAmplifiedOrder({ onResult }: Props = {}) { - // const { mangrove, marketsInfoQuery } = useMangrove() - // const { currentMarket: market } = useMarket() - // const resolveWhenBlockIsIndexed = useResolveWhenBlockIsIndexed() - // const queryClient = useQueryClient() - // const [startLoading, stopLoading] = useLoadingStore((state) => [ - // state.startLoading, - // state.stopLoading, - // ]) - // return useMutation({ - // mutationFn: async ({ - // form, - // }: { - // form: Omit & { - // selectedToken?: Token - // selectedSource?: Logic - // sendAmount: string - // assetsWithTokens: AssetWithInfos[] - // } - // }) => { - // try { - // if (!mangrove || !market || !form.selectedToken || !form.selectedSource) - // return - // const { data: openMarkets } = marketsInfoQuery - // const amp = new MangroveAmplifier({ mgv: mangrove }) - // const assets = form.assetsWithTokens.map((asset) => { - // return { - // inboundTokenAddress: asset.token?.address, - // inboundTokenId: asset.token?.address, - // inboundLogic: asset.receiveTo, - // tickspacing: market.tickSpacing, - // limitPrice: asset.limitPrice, - // } - // }) - // type Assets = { - // inboundToken: string | undefined - // inboundLogic: DefaultTradeLogics - // tickSpacing: number - // tick: number - // }[] - // const hasLogic = ( - // token: Assets[0], - // ): token is Omit & { - // inboundLogic: - // | SimpleLogic - // | SimpleAaveLogic - // | OrbitLogic - // | ZeroLendLogic - // | PacFinanceLogic - // inboundToken: string - // } => { - // return ( - // token.inboundLogic !== undefined && token.inboundToken !== undefined - // ) - // } - // // const inboundTokens = assets - // // .map((asset) => { - // // const market = openMarkets?.find((market) => { - // // return ( - // // (market.base.id === asset.inboundTokenId && - // // market.quote.id === form.selectedToken?.address) || - // // (market.quote.id === asset.inboundTokenId && - // // market.base.id === form.selectedToken?.address) - // // ) - // // }) - // // const ba = - // // market?.base.id === asset.inboundTokenId ? "bids" : "asks" - // // const priceHelper = new TickPriceHelper(ba, market!) - // // const tick = priceHelper.tickFromPrice( - // // asset?.limitPrice || "0", - // // "nearest", - // // ) - // // return { - // // inboundToken: asset.inboundTokenAddress, - // // inboundLogic: asset.inboundLogic, - // // tickSpacing: asset.tickspacing, - // // tick, - // // } - // // }) - // // .filter(hasLogic) - // // //TODO: check why we don't have tx hash - // // const bundle = await amp.addBundle({ - // // outboundToken: form.selectedToken.address, - // // outboundVolume: parseUnits( - // // form.sendAmount, - // // form.selectedToken.decimals, - // // ), - // // outboundLogic: form.selectedSource, - // // expiryDate: - // // form.timeInForce === TimeInForce.GOOD_TIL_TIME - // // ? estimateTimestamp({ - // // timeToLiveUnit: form.timeToLiveUnit, - // // timeToLive: form.timeToLive, - // // }) - // // : 0, - // // inboundTokens, - // // }) - // // const tx = (await bundle.response).wait() - // // const hash = await tx - // toast.success("Amplified order posted successfully") - // return { tx: "hash" } - // } catch (error) { - // console.error(error) - // toast.error(`Failed to post the amplified order`) - // } - // }, - // meta: { - // error: "Failed to post the limit order", - // }, - // onSuccess: async (data) => { - // /* - // * We use a custom callback to handle the success message once it's ready. - // * This is because the onSuccess callback from the mutation will only be triggered - // * after all the preceding logic has been executed. - // */ - // const { tx } = data ?? {} - // try { - // // if (!tx) return - // // onResult?.(tx) - // // // Start showing loading state indicator on parts of the UI that depend on - // // startLoading([TRADE.TABLES.ORDERS, TRADE.TABLES.FILLS]) - // // const blockNumber = tx.blockNumber - // // await resolveWhenBlockIsIndexed.mutateAsync({ - // // blockNumber, - // // }) - // queryClient.invalidateQueries({ queryKey: ["orders"] }) - // queryClient.invalidateQueries({ queryKey: ["fills"] }) - // queryClient.invalidateQueries({ queryKey: ["amplified"] }) - // } catch (error) { - // console.error(error) - // } - // }, - // onSettled: () => { - // stopLoading([TRADE.TABLES.ORDERS, TRADE.TABLES.FILLS]) - // }, - // }) -} diff --git a/app/trade/_components/forms/amplified/types.ts b/app/trade/_components/forms/amplified/types.ts deleted file mode 100644 index da740694..00000000 --- a/app/trade/_components/forms/amplified/types.ts +++ /dev/null @@ -1,26 +0,0 @@ -import { Logic, Token } from "@mangrovedao/mgv" -import { TimeInForce, TimeToLiveUnit } from "./enums" - -export type Asset = { - amount: string - token: string - limitPrice: string - receiveTo: string -} - -export type AssetWithInfos = { - token: Token | undefined - receiveTo: Logic - amount: string - limitPrice: string -} - -export type Form = { - sendSource: string - sendAmount: string - sendToken: string - assets: Asset[] - timeInForce: TimeInForce - timeToLive: string - timeToLiveUnit: TimeToLiveUnit -} diff --git a/app/trade/_components/forms/amplified/utils.ts b/app/trade/_components/forms/amplified/utils.ts deleted file mode 100644 index 0dbf8601..00000000 --- a/app/trade/_components/forms/amplified/utils.ts +++ /dev/null @@ -1,82 +0,0 @@ -import { useMarkets } from "@/hooks/use-addresses" -import { TimeToLiveUnit } from "./enums" - -function getNumberOfSeconds(timeToLiveUnit: `${TimeToLiveUnit}`) { - let seconds: number - switch (timeToLiveUnit) { - case TimeToLiveUnit.DAY: - seconds = 86400 - break - case TimeToLiveUnit.HOUR: - seconds = 3600 - break - case TimeToLiveUnit.MIN: - seconds = 60 - break - default: - throw new Error("Not implemented") - } - return seconds -} - -export function estimateTimestamp({ - timeToLiveUnit, - timeToLive, -}: { - timeToLiveUnit: `${TimeToLiveUnit}` | null - timeToLive: string -}) { - const seconds = getNumberOfSeconds(timeToLiveUnit ?? TimeToLiveUnit.DAY) - return Math.trunc(Date.now() / 1000 + seconds * parseInt(timeToLive)) -} - -function getFormattedUnit(timeToLiveUnit: `${TimeToLiveUnit}` | undefined) { - let formattedUnit: string - switch (timeToLiveUnit) { - case TimeToLiveUnit.DAY: - formattedUnit = "day" - break - case TimeToLiveUnit.HOUR: - formattedUnit = "hour" - break - case TimeToLiveUnit.MIN: - formattedUnit = "minute" - break - default: - throw new Error("Not implemented") - } - return formattedUnit -} - -export function getFormattedTimeToLive( - timeToLiveValue: string | undefined, - timeToLiveUnit?: `${TimeToLiveUnit}` | null, -) { - return `${timeToLiveValue} ${getFormattedUnit( - timeToLiveUnit ?? TimeToLiveUnit.DAY, - )}${Number(timeToLiveValue) > 1 ? "s" : ""}` -} - -export const getCurrentTokenPrice = ( - tokenAddress: string, - markets?: ReturnType, -) => { - const market = markets?.find( - (market) => - market.base.address === tokenAddress || - market.quote.address === tokenAddress, - ) - return market?.quote || market?.base -} - -export const getCurrentTokenPriceFromAddress = ( - tokenAddress: string, - openMarkets?: ReturnType, -) => { - const market = openMarkets?.find( - (market) => - market.base.address.toLowerCase() == tokenAddress.toLowerCase() || - market.quote.address.toLowerCase() == tokenAddress.toLowerCase(), - ) - return market?.quote || market?.base -} diff --git a/app/trade/_components/forms/amplified/validators.ts b/app/trade/_components/forms/amplified/validators.ts deleted file mode 100644 index 94432258..00000000 --- a/app/trade/_components/forms/amplified/validators.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { z } from "zod" - -import { FIELD_ERRORS } from "@/utils/form-errors" - -export const isGreaterThanZeroValidator = z.coerce - .number() - .gt(0, FIELD_ERRORS.fieldRequired) - -export const isSelected = z.coerce.string() - -export const sendValidator = (value: number) => - z.coerce - .number() - .gt(0, FIELD_ERRORS.fieldRequired) - .lte(value, FIELD_ERRORS.insufficientBalance) diff --git a/app/trade/_components/forms/components/market-details.tsx b/app/trade/_components/forms/components/market-details.tsx index da896f51..574ca758 100644 --- a/app/trade/_components/forms/components/market-details.tsx +++ b/app/trade/_components/forms/components/market-details.tsx @@ -4,7 +4,6 @@ type MarketDetailsProps = { tickSize?: string spotPrice?: string minVolume?: string - amplifiedMinVolume?: string } export function MarketDetails({ @@ -12,7 +11,6 @@ export function MarketDetails({ tickSize, spotPrice, minVolume, - amplifiedMinVolume, }: MarketDetailsProps) { return ( @@ -20,10 +18,6 @@ export function MarketDetails({ - {amplifiedMinVolume ? ( - - ) : undefined} - {minVolume ? ( ) : undefined} diff --git a/app/trade/_components/forms/components/steps.tsx b/app/trade/_components/forms/components/steps.tsx index 8d2d09f1..2f10a937 100644 --- a/app/trade/_components/forms/components/steps.tsx +++ b/app/trade/_components/forms/components/steps.tsx @@ -46,9 +46,7 @@ function Step({ title, children, number, active = false }: StepProps) { {title?.includes("deployment") ? ( Make your approvals safer! - - If you never used Limit Orders or Amplified Orders on Mangrove, - + If you never used Limit Orders on Mangrove, you are required to active your address. Please sign a transaction. @@ -57,9 +55,7 @@ function Step({ title, children, number, active = false }: StepProps) { ) : undefined} {title?.includes("activation") ? ( - - If you never used Amplified/Limit Orders on Mangrove, - + If you never used Limit Orders on Mangrove, you are required to activate this functionality. Please sign a transaction. diff --git a/app/trade/_components/forms/hooks/use-smart-router.ts b/app/trade/_components/forms/hooks/use-smart-router.ts deleted file mode 100644 index 98a9b274..00000000 --- a/app/trade/_components/forms/hooks/use-smart-router.ts +++ /dev/null @@ -1,80 +0,0 @@ -import { useMangroveAddresses } from "@/hooks/use-addresses" -import { useQuery } from "@tanstack/react-query" -import { parseAbi } from "viem" -import { useAccount, usePublicClient, useWalletClient } from "wagmi" - -const MangroveOrderABI = parseAbi([ - "function ROUTER_FACTORY() external view returns (address)", - "function ROUTER_IMPLEMENTATION() external view returns (address)", -]) - -const RouterProxyFactoryABI = parseAbi([ - "function instantiate(address owner, address routerImplementation) public returns (address proxy, bool created)", -]) - -const SmartRouterABI = parseAbi([ - "function isBound(address mkr) public view returns (bool)", - "function bind(address makerContract) public", -]) - -export function useSmartRouter() { - const { address } = useAccount() - const publicClient = usePublicClient() - const { data: walletClient } = useWalletClient() - const mangrove = useMangroveAddresses() - const orderContract = mangrove?.mgvOrder - - return useQuery({ - queryKey: ["smart-router", orderContract, publicClient, address], - queryFn: async () => { - // try { - // if (!publicClient || !address || !orderContract || !walletClient) return - // const { amplifier } = new MangroveAmplifier({ mgv: mangrove }) - // const ROUTER_FACTORY = await publicClient.readContract({ - // address: orderContract as Address, - // abi: MangroveOrderABI, - // functionName: "ROUTER_FACTORY", - // }) - // const ROUTER_IMPLEMENTATION = await publicClient.readContract({ - // address: orderContract as Address, - // abi: MangroveOrderABI, - // functionName: "ROUTER_IMPLEMENTATION", - // }) - // const { - // result: [proxy, isDeployed], - // request, - // } = await publicClient.simulateContract({ - // address: ROUTER_FACTORY, - // abi: RouterProxyFactoryABI, - // functionName: "instantiate", - // args: [address, ROUTER_IMPLEMENTATION], - // }) - // let isBound = false - // try { - // isBound = await publicClient.readContract({ - // address: proxy, - // abi: SmartRouterABI, - // functionName: "isBound", - // args: [amplifier.address as Address], - // }) - // } catch (error) {} - // return { isDeployed, isBound } - // } catch (error) { - // console.error(error) - // return { isDeployed: false, isBound: false } - // } - }, - meta: { - error: - "Unable to verify amplified order smart-router deployment and activation.", - }, - enabled: !!( - address && - publicClient && - walletClient && - orderContract && - mangrove - ), - retry: false, - }) -} diff --git a/app/trade/_components/forms/hooks/use-spender-address.ts b/app/trade/_components/forms/hooks/use-spender-address.ts index c076582a..162eb98c 100644 --- a/app/trade/_components/forms/hooks/use-spender-address.ts +++ b/app/trade/_components/forms/hooks/use-spender-address.ts @@ -3,9 +3,7 @@ import { getUserRouter } from "@mangrovedao/mgv/actions" import { useQuery } from "@tanstack/react-query" import { useAccount, usePublicClient } from "wagmi" -export const useSpenderAddress = ( - type: "kandel" | "limit" | "market" | "amplified", -) => { +export const useSpenderAddress = (type: "kandel" | "limit" | "market") => { const addresses = useMangroveAddresses() const publicClient = usePublicClient() const { address } = useAccount() diff --git a/app/trade/_components/forms/hooks/use-trade-infos.ts b/app/trade/_components/forms/hooks/use-trade-infos.ts index e01d8036..8f07b625 100644 --- a/app/trade/_components/forms/hooks/use-trade-infos.ts +++ b/app/trade/_components/forms/hooks/use-trade-infos.ts @@ -5,7 +5,7 @@ import { determineDecimals } from "@/utils/numbers" import { BS } from "@mangrovedao/mgv/lib" import { useSpenderAddress } from "./use-spender-address" -export function useTradeInfos(type: "limit" | "market" | "amplified", bs: BS) { +export function useTradeInfos(type: "limit" | "market", bs: BS) { const { currentMarket } = useMarket() const baseToken = currentMarket?.base const quoteToken = currentMarket?.quote diff --git a/app/trade/_components/forms/limit/components/summary-step.tsx b/app/trade/_components/forms/limit/components/summary-step.tsx index 2059b3a8..5f5b8fa5 100644 --- a/app/trade/_components/forms/limit/components/summary-step.tsx +++ b/app/trade/_components/forms/limit/components/summary-step.tsx @@ -4,6 +4,7 @@ import Big from "big.js" import { TokenIcon } from "@/components/token-icon" import { Separator } from "@/components/ui/separator" import { cn } from "@/utils" +import { TimeInForce } from "../enums" import type { Form } from "../types" type Props = { @@ -28,6 +29,11 @@ export function SummaryStep({ ? "Wallet" : form.receiveTo.toUpperCase() + const timeInForceKey = TimeInForce[form.timeInForce] + const showTimeToLive = + (form.timeToLive && form.timeInForce === TimeInForce.GTC) || + form.timeInForce === TimeInForce.PO + return (
@@ -59,8 +65,8 @@ export function SummaryStep({ */}
- {form.timeToLive}{" "} - {form.timeToLive && ( + {timeInForceKey}{" "} + {showTimeToLive && ( {form.timeToLive}{" "} diff --git a/app/trade/_components/forms/limit/enums.ts b/app/trade/_components/forms/limit/enums.ts index c637cc69..9f869b45 100644 --- a/app/trade/_components/forms/limit/enums.ts +++ b/app/trade/_components/forms/limit/enums.ts @@ -1,7 +1,8 @@ export enum TimeInForce { - IMMEDIATE_OR_CANCEL = "Immediate or cancel", - GOOD_TIL_TIME = "Good til time", - FILL_OR_KILL = "Fill or kill", + GTC = 0, + PO = 2, + IOC = 3, + FOK = 4, } export enum TimeToLiveUnit { diff --git a/app/trade/_components/forms/limit/hooks/use-limit.ts b/app/trade/_components/forms/limit/hooks/use-limit.ts index 1b44b648..073dc89c 100644 --- a/app/trade/_components/forms/limit/hooks/use-limit.ts +++ b/app/trade/_components/forms/limit/hooks/use-limit.ts @@ -9,12 +9,7 @@ import { useLogics } from "@/hooks/use-addresses" import { useTokenBalance, useTokenLogics } from "@/hooks/use-balances" import { useBook } from "@/hooks/use-book" import useMarket from "@/providers/market.new" -import { - BS, - Order, - getDefaultLimitOrderGasreq, - minVolume, -} from "@mangrovedao/mgv/lib" +import { BS, getDefaultLimitOrderGasreq, minVolume } from "@mangrovedao/mgv/lib" import { formatUnits, parseUnits } from "viem" import { TimeInForce, TimeToLiveUnit } from "../enums" import type { Form } from "../types" @@ -33,8 +28,7 @@ export function useLimit(props: Props) { sendFrom: "simple", receive: "", receiveTo: "simple", - orderType: Order.GTC, - timeInForce: TimeInForce.GOOD_TIL_TIME, + timeInForce: TimeInForce.GTC, timeToLive: "28", timeToLiveUnit: TimeToLiveUnit.DAY, }, diff --git a/app/trade/_components/forms/limit/hooks/use-post-limit-order.ts b/app/trade/_components/forms/limit/hooks/use-post-limit-order.ts index 39c5c760..1723eb7c 100644 --- a/app/trade/_components/forms/limit/hooks/use-post-limit-order.ts +++ b/app/trade/_components/forms/limit/hooks/use-post-limit-order.ts @@ -23,6 +23,7 @@ import { toast } from "sonner" import { useAccount, usePublicClient, useWalletClient } from "wagmi" import { TradeMode } from "../../enums" import { successToast } from "../../utils" +import { TimeInForce } from "../enums" import type { Form } from "../types" import { estimateTimestamp } from "../utils" @@ -63,7 +64,7 @@ export function usePostLimitOrder({ onResult }: Props = {}) { bs, send: gives, receive: wants, - orderType, + timeInForce, timeToLive, sendFrom, receiveTo, @@ -99,11 +100,12 @@ export function usePostLimitOrder({ onResult }: Props = {}) { quoteAmount, bs, book, - orderType, + orderType: timeInForce as number, // If expiry date is ignored, then it will not expire - expiryDate: BigInt( - estimateTimestamp({ timeToLiveUnit: "Day", timeToLive }), - ), // 1 hour + expiryDate: + timeInForce === TimeInForce.GTC || timeInForce === TimeInForce.PO + ? BigInt(estimateTimestamp({ timeToLiveUnit: "Day", timeToLive })) + : undefined, // 1 hour restingOrderGasreq, // logics can be left to undefined (meaning no logic) takerGivesLogic, diff --git a/app/trade/_components/forms/limit/limit.tsx b/app/trade/_components/forms/limit/limit.tsx index 156589ea..cd64a384 100644 --- a/app/trade/_components/forms/limit/limit.tsx +++ b/app/trade/_components/forms/limit/limit.tsx @@ -1,4 +1,4 @@ -import { BS, Order } from "@mangrovedao/mgv/lib" +import { BS } from "@mangrovedao/mgv/lib" import React from "react" import { formatUnits } from "viem" @@ -23,6 +23,7 @@ import { Separator } from "@/components/ui/separator" import { Slider } from "@/components/ui/slider" import useMarket from "@/providers/market.new" import { cn } from "@/utils" +import { enumKeys } from "@/utils/enums" import { Accordion } from "../components/accordion" import FromWalletLimitOrderDialog from "./components/from-wallet-order-dialog" import SourceIcon from "./components/source-icon" @@ -354,7 +355,7 @@ export function Limit() { - + {(field) => { return (
@@ -372,10 +373,10 @@ export function Limit() { - {Object.values(Order).map((timeInForce) => ( + {enumKeys(TimeInForce).map((timeInForce) => ( {timeInForce} @@ -390,7 +391,9 @@ export function Limit() {
) { e.preventDefault() diff --git a/app/trade/_components/orderbook/orderbook.tsx b/app/trade/_components/orderbook/orderbook.tsx index 5709dc66..73fdc999 100644 --- a/app/trade/_components/orderbook/orderbook.tsx +++ b/app/trade/_components/orderbook/orderbook.tsx @@ -64,6 +64,7 @@ function BookContent() {
) } + const lowestAskPrice = book.asks[0]?.price const highestBidPrice = book.bids[0]?.price const spread = Math.abs((lowestAskPrice ?? 0) - (highestBidPrice ?? 0)) diff --git a/app/trade/_components/orderbook/semibook.tsx b/app/trade/_components/orderbook/semibook.tsx index fb005370..260add04 100644 --- a/app/trade/_components/orderbook/semibook.tsx +++ b/app/trade/_components/orderbook/semibook.tsx @@ -50,12 +50,13 @@ export const SemiBook = React.forwardRef< currentMarket?.base.symbol === "BLAST" ? 8 : priceDecimals + return ( <> { dispatchEvent( new CustomEvent("on-orderbook-offer-clicked", { @@ -70,7 +71,20 @@ export const SemiBook = React.forwardRef< type === "bids" ? "text-green-caribbean" : "text-red-100", )} > - {volume.toFixed(3)} + + + + + {volume.toFixed(pDecimals)} + + + + {volume.toFixed(currentMarket?.base.decimals)} + + + @@ -92,7 +106,20 @@ export const SemiBook = React.forwardRef< - {(price * volume).toFixed(priceDecimals)} + + + + + {(price * volume).toFixed(priceDecimals)} + + + + {(price * volume).toFixed(currentMarket?.quote.decimals)} + + + (row.getValue() ? "Market" : "Limit"), diff --git a/app/trade/_components/tables/orders/amplified-order.tsx b/app/trade/_components/tables/orders/amplified-order.tsx deleted file mode 100644 index 463e08bb..00000000 --- a/app/trade/_components/tables/orders/amplified-order.tsx +++ /dev/null @@ -1,65 +0,0 @@ -"use client" -import React from "react" - -import useMarket from "@/providers/market.new" -import { useOrders } from "./hooks/use-orders" -import type { AmplifiedOrder } from "./schema" - -export function AmplifiedOrders() { - const [{ page, pageSize }, setPageDetails] = React.useState({ - page: 1, - pageSize: 10, - }) - const { currentMarket, setMarket, markets } = useMarket() - const { data: count } = useOrders({ - select: (orders) => orders.length, - }) - - // const amplifiedOrdersQuery = useAmplifiedOrders({ - // filters: { - // skip: (page - 1) * pageSize, - // }, - // }) - - // selected order to delete - const [orderToDelete, setOrderToDelete] = React.useState() - const [orderToEdit, setOrderToEdit] = React.useState<{ - order: AmplifiedOrder - mode: "view" | "edit" - }>() - - // const table = useAmplifiedTable({ - // data: amplifiedOrdersQuery.data, - // onEdit: (order) => setOrderToEdit({ order, mode: "edit" }), - // onCancel: setOrderToDelete, - // }) - - return ( - <> - {/* - setOrderToEdit({ order: order as AmplifiedOrder, mode: "view" }) - } - pagination={{ - onPageChange: setPageDetails, - page, - pageSize, - count, - }} - /> - setOrderToEdit(undefined)} - /> - setOrderToDelete(undefined)} - /> */} - - ) -} diff --git a/app/trade/_components/tables/orders/components/cancel-amplified-offer-dialog.tsx b/app/trade/_components/tables/orders/components/cancel-amplified-offer-dialog.tsx deleted file mode 100644 index 42c90939..00000000 --- a/app/trade/_components/tables/orders/components/cancel-amplified-offer-dialog.tsx +++ /dev/null @@ -1,52 +0,0 @@ -import useMarket from "@/providers/market.new" -// import { useCancelAmplifiedOrder } from "../hooks/use-cancel-amplified-order" -import type { AmplifiedOrder } from "../schema" - -type Props = { - order?: AmplifiedOrder - market?: ReturnType - onClose: () => void -} - -export default function CancelAmplifiedOfferDialog({ - order, - market, - onClose, -}: Props) { - // const retract = useCancelAmplifiedOrder({ - // offerId: order?.id, - // onCancel: onClose, - // }) - - if (!order) return null - - return ( - <> - // - // Are you sure you want to cancel this order? - // - //
- // - // - // - // - //
- //
- //
- ) -} diff --git a/app/trade/_components/tables/orders/components/edit-amplified-order-sheet.tsx b/app/trade/_components/tables/orders/components/edit-amplified-order-sheet.tsx deleted file mode 100644 index f9fb1a03..00000000 --- a/app/trade/_components/tables/orders/components/edit-amplified-order-sheet.tsx +++ /dev/null @@ -1,440 +0,0 @@ -import React from "react" -import { Address } from "viem" - -import { TokenIcon } from "@/components/token-icon" -import { EnhancedNumericInput } from "@/components/token-input" -import { Text } from "@/components/typography/text" -import { Title } from "@/components/typography/title" -import { Button } from "@/components/ui/button" -import { - Select, - SelectContent, - SelectGroup, - SelectItem, - SelectTrigger, - SelectValue, -} from "@/components/ui/select" -import { Separator } from "@/components/ui/separator" -import * as SheetRoot from "@/components/ui/sheet" -import { ScrollArea, ScrollBar } from "@/components/ui/sheet-scroll-area" -import { useMarkets } from "@/hooks/use-addresses" -import { useTokenFromAddress } from "@/hooks/use-token-from-address" -import { cn } from "@/utils" -import { formatDateWithoutHours, formatHoursOnly } from "@/utils/date" -import { TimeInForce, TimeToLiveUnit } from "../../../forms/amplified/enums" -import { - isGreaterThanZeroValidator, - sendValidator, -} from "../../../forms/amplified/validators" -import { useEditAmplifiedOrder } from "../hooks/use-edit-amplified-order" -import { AmplifiedOrder } from "../schema" -import { AmplifiedForm } from "../types" -import { Timer } from "./timer" - -type SheetLineProps = { - title: string - item: React.ReactNode - secondaryItem?: React.ReactNode -} - -const SheetLine = ({ title, item, secondaryItem }: SheetLineProps) => ( -
- {title}: -
- {item} - {secondaryItem} -
-
-) - -const Badge = ({ - title, - isExpired, -}: { - title: string - isExpired?: boolean -}) => ( -
- - {title} -
-) - -type EditAmplifiedOrderSheetProps = { - onClose: () => void - orderInfos?: { order: AmplifiedOrder; mode: "edit" | "view" } - openMarkets?: ReturnType -} - -export default function EditAmplifiedOrderSheet({ - orderInfos, - openMarkets, - onClose, -}: EditAmplifiedOrderSheetProps) { - if (!orderInfos || !openMarkets) return null - const [formData, setFormData] = React.useState() - const order = orderInfos.order - const mode = orderInfos.mode - const { creationDate, offers, expiryDate } = order - - const tokens = offers.map((offer) => { - return useTokenFromAddress(offer.market.inbound_tkn as Address).data - }) - - const { - handleSubmit, - form, - setToggleEdit, - toggleEdit, - assets, - send, - sendToken, - timeInForce, - timeToLive, - timeToLiveUnit, - status, - sendTokenBalance, - } = useEditAmplifiedOrder({ - order, - onSubmit: (formData) => setFormData(formData), - }) - - React.useEffect(() => { - if (mode === "edit") setToggleEdit(true) - }, []) - - return ( - - - - Order Details - - - - {formData ? ( - <> - ) : ( - // { - // setToggleEdit(false) - // setFormData(undefined) - // }} - // /> -
- -
-
- {tokens?.map((token) => - token ? ( - - ) : ( -
- ? -
- ), - )} -
- Multiple -
- offer.isOpen) - ? "Closed" - : "Open" - } - isExpired={!order.offers.find((offer) => offer.isOpen)} - /> - } - /> - - {creationDate && ( - - {formatDateWithoutHours( - new Date(Number(`${creationDate}000`)), - )} - - } - secondaryItem={ - - {formatHoursOnly( - new Date(Number(`${creationDate}000`)), - )} - - } - /> - )} - - Buy} - /> - - Amplified} /> - - {`${send} ${sendToken?.symbol}`} - ) : ( - - {(field) => ( - { - field.handleChange(e.target.value) - }} - error={field.state.meta.touchedErrors} - token={sendToken || ""} - showBalance - disabled={!sendToken || sendTokenBalance === "0"} - /> - )} - - ) - } - /> - - {toggleEdit ? ( - - - {(field) => { - return ( -
- -
- ) - }} -
- -
- - {(field) => ( - { - if (!value) return - field.handleChange(value) - }} - disabled={!form.state.isFormValid} - error={field.state.meta.touchedErrors} - /> - )} - - - {(field) => ( - - )} - -
-
- } - /> - ) : ( - {timeInForce}} - secondaryItem={ - expiryDate && ( - - - - ) - } - /> - )} - - {assets.map((asset, index) => { - return ( -
- - -
- - {asset.token?.symbol} -
- - - - - -
- ) - })} - - - - - [state.isSubmitting]}> - {([isSubmitting]) => { - return ( - - ) - }} - - - - {!toggleEdit ? ( - - ) : ( - [ - state.canSubmit, - state.isSubmitting, - ]} - > - {([canSubmit, isSubmitting]) => { - return ( - - ) - }} - - )} - - - )} - - - - - - - ) -} diff --git a/app/trade/_components/tables/orders/components/edit-amplified-order-steps.tsx b/app/trade/_components/tables/orders/components/edit-amplified-order-steps.tsx deleted file mode 100644 index caeeee1d..00000000 --- a/app/trade/_components/tables/orders/components/edit-amplified-order-steps.tsx +++ /dev/null @@ -1,231 +0,0 @@ -import { Token } from "@mangrovedao/mgv" - -import { Text } from "@/components/typography/text" -import { type ButtonProps } from "@/components/ui/button" -import { Label } from "@/components/ui/label" -import { AmplifiedOrder } from "../schema" -import { AmplifiedForm } from "../types" - -type SummaryProps = { - oldAmount: string - newAmount: string - oldExpiration?: string - newExpiration?: string -} - -const Summary = ({ - oldAmount, - oldExpiration, - newAmount, - newExpiration, -}: SummaryProps) => { - return ( - <> -
-
- -
- - - {Number(oldAmount).toFixed(4)} - - {oldExpiration} -
-
- - - {Number(newAmount).toFixed(4)} - - {newExpiration} -
-
-
- - ) -} - -type Props = { - order: AmplifiedOrder - form: AmplifiedForm & { sendToken: Token } - onClose: () => void - onCloseForm: () => void -} - -const btnProps: ButtonProps = { - rightIcon: true, - className: "w-full", - size: "lg", -} - -export default function EditAmplifiedOrderSteps({ - order, - form, - onClose, - onCloseForm, -}: Props) { - // const { chain } = useAccount() - // const { data: spender } = useSpenderAddress("amplified") - // const { data: isInfiniteAllowance } = useIsLiquidityInfiniteAllowance( - // form.sendToken, - // spender, - // form.sendFrom, - // ) - // let steps = ["Update amplified orders"] - // if (!isInfiniteAllowance) { - // steps = ["Summary", `Approve ${form?.sendToken?.symbol}`, ...steps] - // } - // const oldAmount = `${Number( - // formatUnits( - // BigInt(order.offers.find((offer) => offer.gives)?.gives || "0"), - // form.sendToken?.decimals ?? 6, - // ), - // ).toFixed(form.sendToken?.displayDecimals)}` - // const isDialogOpenRef = React.useRef(false) - // React.useEffect(() => { - // isDialogOpenRef.current = !!form - // return () => { - // isDialogOpenRef.current = false - // } - // }, [form]) - // const approve = useInfiniteApproveToken() - // const post = useUpdateAmplifiedOrder({ - // bundleId: order.bundleId, - // form, - // onResult: (result) => { - // /* - // * We use a React ref to track the dialog's open state. If the dialog is closed, - // * we prevent further actions. This is necessary because the dialog's closure - // * might occur before the asynchronous operations complete, potentially leading - // * to undesired effects. - // */ - // if (!isDialogOpenRef.current) return - // onClose() - // onCloseForm() - // tradeService.openTxCompletedDialog({ - // address: result ?? "", - // blockExplorerUrl: chain?.blockExplorers?.default.url, - // }) - // }, - // }) - // const [currentStep, helpers] = useStep(steps.length) - // const { goToNextStep } = helpers - // const expiryDateUnits = - // form.timeToLiveUnit === TimeToLiveUnit.DAY - // ? "days" - // : form.timeToLiveUnit === TimeToLiveUnit.HOUR - // ? "hours" - // : "minutes" - // const newExpiryDate = `${formatExpiryDate( - // add(new Date(), { - // [expiryDateUnits]: Number(form.timeToLive), - // }), - // )} ` - // const stepInfos = [ - // !isInfiniteAllowance && { - // body: ( - // - // ), - // button: ( - // <> - // - // - // - // ), - // }, - // !isInfiniteAllowance && { - // body: , - // button: ( - // - // ), - // }, - // { - // body: ( - // - // ), - // button: ( - // <> - // - // - // - // ), - // }, - // ] - // .filter(Boolean) - // .map((stepInfo, i) => { - // return { - // ...stepInfo, - // title: steps[i], - // } - // }) - // return ( - //
- //
Proceed transaction
- // - //
- // {stepInfos[currentStep - 1]?.body ?? undefined} - //
- //
- // {stepInfos[currentStep - 1]?.button} - //
- //
- // ) -} diff --git a/app/trade/_components/tables/orders/components/edit-order-sheet.tsx b/app/trade/_components/tables/orders/components/edit-order-sheet.tsx index 51c5ddcd..31de100e 100644 --- a/app/trade/_components/tables/orders/components/edit-order-sheet.tsx +++ b/app/trade/_components/tables/orders/components/edit-order-sheet.tsx @@ -308,7 +308,7 @@ export default function EditOrderSheet({ {TimeInForce.GOOD_TIL_TIME}} + item={{TimeInForce.GTC}} secondaryItem={ expiryDate && ( diff --git a/app/trade/_components/tables/orders/hooks/use-amplified-orders.ts b/app/trade/_components/tables/orders/hooks/use-amplified-orders.ts deleted file mode 100644 index 67fbeca5..00000000 --- a/app/trade/_components/tables/orders/hooks/use-amplified-orders.ts +++ /dev/null @@ -1,85 +0,0 @@ -"use client" - -import { useQuery } from "@tanstack/react-query" -import { useAccount } from "wagmi" - -import { TRADE } from "@/app/trade/_constants/loading-keys" -import { useMarkets } from "@/hooks/use-addresses" -import useIndexerSdk from "@/providers/mangrove-indexer" -import { useLoadingStore } from "@/stores/loading.store" -import { AmplifiedOrder, parseAmplifiedOrders } from "../schema" - -type Params = { - filters?: { - first?: number - skip?: number - } - select?: (data: AmplifiedOrder[]) => T -} - -export function useAmplifiedOrders({ - filters: { first = 100, skip = 0 } = {}, - select, -}: Params = {}) { - const { address, isConnected } = useAccount() - const currentMarkets = useMarkets() - - const { indexerSdk } = useIndexerSdk() - const [startLoading, stopLoading] = useLoadingStore((state) => [ - state.startLoading, - state.stopLoading, - ]) - - return useQuery({ - // eslint-disable-next-line @tanstack/query/exhaustive-deps - queryKey: ["amplified", address], - queryFn: async () => { - try { - if (!indexerSdk || !address || !currentMarkets) return [] - startLoading(TRADE.TABLES.ORDERS) - const markets = - currentMarkets.map((market) => { - return { - quote: market.base, - base: market.quote, - } - }) ?? [] - - const result = await indexerSdk.getAmplifiedOrders({ - owner: address, - markets, - }) - - if (!result) return [] - - const filteredResult = result.filter((order) => { - const allOffersMarketFound = order.offers.every( - (offer) => offer.isMarketFound, - ) - - const closedOffers = order.offers.every((offer) => !offer.isOpen) - - const isExpired = order.expiryDate - ? new Date(order.expiryDate) < new Date() - : true - - return allOffersMarketFound && !closedOffers && !isExpired - }) - - return parseAmplifiedOrders(filteredResult) - } catch (e) { - console.error(e) - throw new Error("Unable to retrieve amplified orders") - } finally { - stopLoading(TRADE.TABLES.ORDERS) - } - }, - select, - meta: { - error: "Unable to retrieve amplified orders", - }, - enabled: !!(isConnected && address && indexerSdk && currentMarkets), - retry: false, - staleTime: 5 * 60 * 1000, // 5 minutes - }) -} diff --git a/app/trade/_components/tables/orders/hooks/use-amplified-table.tsx b/app/trade/_components/tables/orders/hooks/use-amplified-table.tsx deleted file mode 100644 index 44119c0c..00000000 --- a/app/trade/_components/tables/orders/hooks/use-amplified-table.tsx +++ /dev/null @@ -1,146 +0,0 @@ -"use client" - -import { - createColumnHelper, - getCoreRowModel, - getPaginationRowModel, - getSortedRowModel, - useReactTable, -} from "@tanstack/react-table" -import React from "react" - -import { IconButton } from "@/components/icon-button" -import { TokenIcon } from "@/components/token-icon" -import { Text } from "@/components/typography/text" -import { CircularProgressBar } from "@/components/ui/circle-progress-bar" -import { useTokenFromAddress } from "@/hooks/use-token-from-address" -import useMarket from "@/providers/market.new" -import { Close, Pen } from "@/svgs" -import { Address } from "viem" -import { Timer } from "../components/timer" -import type { AmplifiedOrder } from "../schema" - -const columnHelper = createColumnHelper() -const DEFAULT_DATA: AmplifiedOrder[] = [] - -type Params = { - data?: AmplifiedOrder[] - onCancel: (order: AmplifiedOrder) => void - onEdit: (order: AmplifiedOrder) => void -} - -export function useAmplifiedTable({ data, onCancel, onEdit }: Params) { - const { currentMarket: market } = useMarket() - - const columns = React.useMemo( - () => [ - columnHelper.display({ - header: "Market", - cell: ({ row }) => { - const { offers } = row.original - - const tokens = offers.map((offer) => { - return useTokenFromAddress(offer.market.inbound_tkn as Address).data - }) - - return ( -
-
-
- {tokens?.map((token) => - token ? ( - - ) : ( -
- ? -
- ), - )} -
- Multiple -
-
- ) - }, - }), - columnHelper.display({ - header: "Side", - cell: (row) =>
Buy
, - }), - columnHelper.display({ - header: "Type", - cell: () => Amplified, - }), - columnHelper.display({ - header: "Filled/Amount", - cell: ({ row }) => ( -
- - - -
- ), - }), - columnHelper.display({ - header: "Price", - cell: ({ row }) => { - return - - }, - }), - columnHelper.accessor("expiryDate", { - header: "Time in force", - cell: (row) => { - const expiry = row.getValue() - return expiry ? :
-
- }, - }), - columnHelper.display({ - id: "actions", - header: () =>
Action
, - cell: ({ row }) => { - const { expiryDate } = row.original - const isExpired = expiryDate - ? new Date(expiryDate) < new Date() - : true - return ( -
- { - e.preventDefault() - e.stopPropagation() - onEdit(row.original) - }} - > - - - { - e.preventDefault() - e.stopPropagation() - onCancel(row.original) - }} - > - - -
- ) - }, - }), - ], - [market, onEdit, onCancel], - ) - - return useReactTable({ - data: data ?? DEFAULT_DATA, - columns, - enableRowSelection: false, - getCoreRowModel: getCoreRowModel(), - getSortedRowModel: getSortedRowModel(), - getPaginationRowModel: getPaginationRowModel(), - }) -} diff --git a/app/trade/_components/tables/orders/hooks/use-cancel-amplified-order.ts b/app/trade/_components/tables/orders/hooks/use-cancel-amplified-order.ts deleted file mode 100644 index 4c2c4f22..00000000 --- a/app/trade/_components/tables/orders/hooks/use-cancel-amplified-order.ts +++ /dev/null @@ -1,60 +0,0 @@ -type Props = { - offerId?: string - onCancel?: () => void -} - -export function useCancelAmplifiedOrder({ offerId, onCancel }: Props = {}) { - // const queryClient = useQueryClient() - // const resolveWhenBlockIsIndexed = useResolveWhenBlockIsIndexed() - // const [startLoading] = useLoadingStore((state) => [ - // state.startLoading, - // state.stopLoading, - // ]) - // const { mangrove } = useMangrove() - // return useMutation({ - // /* - // * We introduce a mutationKey to the useCancelOrder hook. This allows us to - // * handle multiple order retractions simultaneously, without them sharing the - // * same mutation state. This is crucial for maintaining independent states - // * for each retraction operation. - // */ - // mutationKey: ["retractOrder", offerId], - // mutationFn: async ({ order }: { order: AmplifiedOrder }) => { - // try { - // const sendToken = order.offers[0]?.market.outbound_tkn - // if (!sendToken || !mangrove) return - // const amp = new MangroveAmplifier({ mgv: mangrove }) - // const retract = await amp.retractBundle({ - // bundleId: order.bundleId, - // outboundToken: sendToken, - // }) - // const tx = await retract.response - // return tx - // // order id = 0xbf16533e50a352c47615fee34574df2b30fdc4a8243a3d8194630a2a5d63d176-0x3b - // } catch (error) { - // console.error(error) - // throw new Error("") - // } - // }, - // onSuccess: async (data) => { - // try { - // onCancel?.() - // startLoading(TRADE.TABLES.ORDERS) - // if (!data) return - // const { blockNumber } = data - // await resolveWhenBlockIsIndexed.mutateAsync({ - // blockNumber, - // }) - // queryClient.invalidateQueries({ queryKey: ["orders"] }) - // queryClient.invalidateQueries({ queryKey: ["fills"] }) - // queryClient.invalidateQueries({ queryKey: ["amplified"] }) - // } catch (error) { - // console.error(error) - // } - // }, - // meta: { - // error: `Failed to retract the amplified orders`, - // success: `The amplified orders has been successfully retracted`, - // }, - // }) -} diff --git a/app/trade/_components/tables/orders/hooks/use-edit-amplified-order.ts b/app/trade/_components/tables/orders/hooks/use-edit-amplified-order.ts deleted file mode 100644 index f3e45582..00000000 --- a/app/trade/_components/tables/orders/hooks/use-edit-amplified-order.ts +++ /dev/null @@ -1,165 +0,0 @@ -/* eslint-disable @typescript-eslint/ban-ts-comment */ -"use client" -import { Logic } from "@mangrovedao/mgv" -import { useForm } from "@tanstack/react-form" -import { zodValidator } from "@tanstack/zod-form-adapter" -import Big from "big.js" -import React from "react" -import { Address, formatUnits } from "viem" - -import { useLogics, useMarkets } from "@/hooks/use-addresses" -import { useTokenFromAddress } from "@/hooks/use-token-from-address" -import { formatExpiryDate } from "@/utils/date" -import { TimeInForce, TimeToLiveUnit } from "../../../forms/amplified/enums" -import amplifiedLiquiditySourcing from "../../../forms/amplified/hooks/amplified-liquidity-sourcing" -import { getCurrentTokenPriceFromAddress } from "../../../forms/amplified/utils" -import { AmplifiedOrder } from "../schema" -import { AmplifiedForm, AmplifiedOrderStatus } from "../types" - -type Props = { - order: AmplifiedOrder - onSubmit: (data: AmplifiedForm) => void -} - -export function useEditAmplifiedOrder({ order, onSubmit }: Props) { - const { offers } = order - const markets = useMarkets() - const logics = useLogics() - - const sendToken = useTokenFromAddress( - offers.find((offer) => offer?.market.outbound_tkn as Address)?.market - .outbound_tkn as Address, - ).data - - const isClosed = offers.find((offer) => !offer?.isOpen) - const sendFrom = logics.find( - (logic) => logic?.logic == offers[0]?.outboundRoute, - ) - - const { sendFromBalance } = amplifiedLiquiditySourcing({ - logics: logics as Logic[], - sendFrom: sendFrom?.name, - }) - - const sendTokenBalance = sendFromBalance?.formatted - - const gives = `${Number( - formatUnits( - BigInt(offers.find((offer) => offer.gives)?.gives || "0"), - sendToken?.decimals || 4, - ), - ).toFixed(sendToken?.displayDecimals)}` - - // get assets infos - const assets = offers.map((offer) => { - const isBid = markets?.find( - (market) => market.base.address === offer.market.inbound_tkn, - ) - - const quoteToken = getCurrentTokenPriceFromAddress( - offer.market.inbound_tkn, - markets, - ) - - const receiveToken = useTokenFromAddress( - offer.market.inbound_tkn as Address, - ).data - - const limitPrice = `${Number(offer.price).toFixed(quoteToken?.displayDecimals)} ${quoteToken?.symbol}` - let wants - - if (isBid) { - wants = Big(!isNaN(Number(offer.gives)) ? Number(offer.gives) : 0) - .div( - Big( - !isNaN(Number(offer.price)) && Number(offer.price) > 0 - ? Number(offer.price) - : 1, - ), - ) - .toString() - } else { - wants = Big(!isNaN(Number(offer.price)) ? Number(offer.price) : 0) - .times( - Big( - !isNaN(Number(offer.gives)) && Number(offer.gives) > 0 - ? Number(offer.gives) - : 0, - ), - ) - .toString() - } - - //TODO: check this when not tired - let receiveAmount = `${(Number(wants) / 10 ** (sendToken?.decimals ?? 1)).toFixed(receiveToken?.displayDecimals)} ${receiveToken?.symbol}` - - return { - status: offer.isFilled - ? "Filled" - : offer.isFailed - ? "Failed" - : offer.isRetracted - ? "Cancelled" - : "Open", - limitPrice, - receiveAmount, - token: receiveToken, - } - }) - - const orderTimeInForce = order.expiryDate - ? TimeInForce.GOOD_TIL_TIME - : TimeInForce.FILL_OR_KILL - - const orderTimeToLive = formatExpiryDate(order.expiryDate).replace(/\D/g, "") - - const form = useForm({ - validator: zodValidator, - defaultValues: { - assets, - send: gives, - sendFrom: sendFrom as Logic, - timeInForce: orderTimeInForce, - timeToLive: orderTimeToLive, - timeToLiveUnit: TimeToLiveUnit.DAY, - status: isClosed - ? AmplifiedOrderStatus.Closed - : AmplifiedOrderStatus.Open, - }, - onSubmit: (values) => onSubmit(values), - }) - const send = form.useStore((state) => state.values.send) - const timeInForce = form.useStore((state) => state.values.timeInForce) - const timeToLiveUnit = form.useStore((state) => state.values.timeToLiveUnit) - const timeToLive = form.useStore((state) => state.values.timeToLive) - const status = form.useStore((state) => state.values.status) - - const [toggleEdit, setToggleEdit] = React.useState(false) - - function handleSubmit(e: React.FormEvent) { - e.preventDefault() - e.stopPropagation() - void form.handleSubmit() - } - - React.useEffect(() => { - form?.reset() - }, [toggleEdit, form]) - - return { - handleSubmit, - setToggleEdit, - logics, - form, - toggleEdit, - timeInForce, - timeToLive, - timeToLiveUnit, - assets, - send, - sendFrom, - sendToken, - sendTokenBalance, - status, - } -} diff --git a/app/trade/_components/tables/orders/hooks/use-update-amplified-order.ts b/app/trade/_components/tables/orders/hooks/use-update-amplified-order.ts deleted file mode 100644 index 75d4416d..00000000 --- a/app/trade/_components/tables/orders/hooks/use-update-amplified-order.ts +++ /dev/null @@ -1,79 +0,0 @@ -import { Token } from "@mangrovedao/mgv" - -import { AmplifiedForm } from "../types" - -type useUpdateOrderProps = { - form: AmplifiedForm & { sendToken: Token } - bundleId?: string - onResult?: (tx: string) => void -} - -export function useUpdateAmplifiedOrder({ - bundleId, - onResult, -}: useUpdateOrderProps) { - // const { currentMarket: market } = useMarket() - // const resolveWhenBlockIsIndexed = useResolveWhenBlockIsIndexed() - // const queryClient = useQueryClient() - // const [startLoading, stopLoading] = useLoadingStore((state) => [ - // state.startLoading, - // state.stopLoading, - // ]) - // return useMutation({ - // mutationFn: async ({ - // form, - // }: { - // form: AmplifiedForm & { sendToken: Token } - // }) => { - // try { - // if (!mangrove || !market || !bundleId) return - // const { send: volume } = form - // const amp = new MangroveAmplifier({ mgv: mangrove }) - // const parsedVolume = parseUnits(volume, form.sendToken.decimals) - // const editBundle = await amp.updateBundle({ - // bundleId, - // expiryDate: form.timeToLive, - // outboundToken: form.sendToken.address, - // outboundVolume: parsedVolume, - // updateExpiry: false, - // }) - // const tx = (await editBundle.response).wait() - // const hash = await tx - // toast.success("Amplified order updated successfully") - // return { tx: hash } - // } catch (error) { - // console.error(error) - // toast.error("Failed to update the amplified order") - // } - // }, - // meta: { - // error: "Failed to update the amplified limit order", - // }, - // onSuccess: async (data) => { - // if (!data) return - // const { tx } = data - // /* - // * We use a custom callback to handle the success message once it's ready. - // * This is because the onSuccess callback from the mutation will only be triggered - // * after all the preceding logic has been executed. - // */ - // try { - // // Start showing loading state indicator on parts of the UI that depend on - // startLoading([TRADE.TABLES.ORDERS, TRADE.TABLES.FILLS]) - // const blockNumber = tx.blockNumber - // onResult?.(tx.transactionHash) - // await resolveWhenBlockIsIndexed.mutateAsync({ - // blockNumber, - // }) - // queryClient.invalidateQueries({ queryKey: ["fills"] }) - // queryClient.invalidateQueries({ queryKey: ["orders"] }) - // queryClient.invalidateQueries({ queryKey: ["amplified"] }) - // } catch (error) { - // console.error(error) - // } - // }, - // onSettled: () => { - // stopLoading([TRADE.TABLES.ORDERS, TRADE.TABLES.FILLS]) - // }, - // }) -} diff --git a/app/trade/_components/tables/orders/hooks/use-update-order.ts b/app/trade/_components/tables/orders/hooks/use-update-order.ts index 8ab17749..e3988530 100644 --- a/app/trade/_components/tables/orders/hooks/use-update-order.ts +++ b/app/trade/_components/tables/orders/hooks/use-update-order.ts @@ -113,7 +113,6 @@ export function useUpdateOrder({ offerId, onResult }: useUpdateOrderProps) { }) queryClient.invalidateQueries({ queryKey: ["orders"] }) queryClient.invalidateQueries({ queryKey: ["fills"] }) - queryClient.invalidateQueries({ queryKey: ["amplified"] }) } catch (error) { console.error(error) } diff --git a/app/trade/_components/tables/orders/schema.ts b/app/trade/_components/tables/orders/schema.ts index fc6df6d0..64da85c0 100644 --- a/app/trade/_components/tables/orders/schema.ts +++ b/app/trade/_components/tables/orders/schema.ts @@ -31,70 +31,3 @@ export function parseOrders(data: unknown[]): Order[] { }) .filter(Boolean) as Order[] } - -const amplifiedOrderSchema = z.object({ - id: z.string(), - creationDate: z.string(), - bundleId: z.string(), - expiryDate: z.date(), - owner: z - .object({ - address: z.string(), - }) - .transform((data) => data.address), - offers: z.array( - z.object({ - id: z.string(), - inboundRoute: z.string(), - outboundRoute: z.string(), - latestTransactionHash: z.string(), - creationDate: z.date(), - latestUpdateDate: z.date(), - offerId: z.string(), - gives: z.string(), - gasprice: z.string(), - gasreq: z.string(), - gasBase: z.string(), - prevGives: z.nullable(z.unknown()), - prevTick: z.nullable(z.unknown()), - tick: z.string(), - isOpen: z.boolean(), - totalGot: z.string(), - totalGave: z.string(), - isFailed: z.boolean(), - isFilled: z.boolean(), - isRetracted: z.boolean(), - failedReason: z.nullable(z.unknown()), - posthookFailReason: z.nullable(z.unknown()), - deprovisioned: z.boolean(), - market: z.object({ - id: z.string(), - inbound_tkn: z.string(), - outbound_tkn: z.string(), - tickSpacing: z.string(), - }), - maker: z.object({ - id: z.string(), - address: z.string(), - }), - owner: z.nullable(z.unknown()), - isMarketFound: z.boolean(), - price: z.string(), - }), - ), -}) - -export type AmplifiedOrder = z.infer - -export function parseAmplifiedOrders(data: unknown[]): AmplifiedOrder[] { - return data - .map((item) => { - try { - return amplifiedOrderSchema.parse(item) - } catch (error) { - console.error("Invalid format for offers: ", item, error) - return null - } - }) - .filter(Boolean) as AmplifiedOrder[] -} diff --git a/app/trade/_components/tables/orders/types.ts b/app/trade/_components/tables/orders/types.ts index b48a197a..49f81bd4 100644 --- a/app/trade/_components/tables/orders/types.ts +++ b/app/trade/_components/tables/orders/types.ts @@ -1,5 +1,3 @@ -import { Logic } from "@mangrovedao/mgv" -import { TimeInForce } from "../../forms/amplified/enums" import { TimeToLiveUnit } from "../../forms/limit/enums" export type Form = { @@ -10,23 +8,3 @@ export type Form = { timeToLiveUnit: TimeToLiveUnit isBid: boolean } - -type Asset = { - limitPrice: string - receiveAmount: string -} - -export enum AmplifiedOrderStatus { - "Open", - "Closed", -} - -export type AmplifiedForm = { - send: string - sendFrom: Logic - assets: Asset[] - timeInForce: TimeInForce - timeToLive: string - timeToLiveUnit: TimeToLiveUnit - status: AmplifiedOrderStatus -} diff --git a/app/trade/_components/tables/orders/utils/tables.ts b/app/trade/_components/tables/orders/utils/tables.ts index 09a5c820..1a8f7528 100644 --- a/app/trade/_components/tables/orders/utils/tables.ts +++ b/app/trade/_components/tables/orders/utils/tables.ts @@ -1,7 +1,7 @@ import Big from "big.js" import useMarket from "@/providers/market.new" -import { AmplifiedOrder, type Order } from "../schema" +import { type Order } from "../schema" export function getOrderProgress( order: Order, @@ -38,25 +38,3 @@ export function getOrderProgress( return { progress, filled, volume, progressInPercent, amount } } - -export function getAmplifiedOrderProgress( - order: AmplifiedOrder, - market?: ReturnType, -) { - // const { takerGot, initialGives, initialWants } = order - // const displayDecimals = market?.base.displayedDecimals - // const volume = Big(initialGives).toFixed(displayDecimals) - // const amount = Big(initialWants).toFixed(displayDecimals) - // const filled = Big(takerGot).toFixed(displayDecimals) - // const progress = Math.min( - // Math.round( - // Big(filled) - // .mul(100) - // .div(Big(volume).eq(0) ? 1 : volume) - // .toNumber(), - // ), - // 100, - // ) - // const progressInPercent = (Number(filled) / Number(volume)) * 100 - // return { progress, filled, volume, progressInPercent, amount } -} diff --git a/app/trade/_components/tables/tables.tsx b/app/trade/_components/tables/tables.tsx index ce282a8c..a368687d 100644 --- a/app/trade/_components/tables/tables.tsx +++ b/app/trade/_components/tables/tables.tsx @@ -12,7 +12,6 @@ import { renderElement } from "@/utils/render" import { TRADE } from "../../_constants/loading-keys" import { Fills } from "./fills/fills" import { useFills } from "./fills/use-fills" -// import { AmplifiedOrders } from "./orders/amplified-order" import { useOrders } from "./orders/hooks/use-orders" import { Orders } from "./orders/orders" @@ -20,13 +19,11 @@ import { Orders } from "./orders/orders" export enum TradeTables { ORDERS = "orders", FILLS = "fills", - // AMPLIFIED = "amplified", } const TABS_CONTENT = { [TradeTables.ORDERS]: Orders, [TradeTables.FILLS]: Fills, - // [TradeTables.AMPLIFIED]: AmplifiedOrders, } export function Tables(props: React.ComponentProps) { @@ -43,10 +40,6 @@ export function Tables(props: React.ComponentProps) { select: (fills) => fills.length, }) - // const { data: amplifedCount } = useAmplifiedOrders({ - // select: (amplified) => amplified.length, - // }) - return ( { @@ -63,7 +73,7 @@ export default function ChainSelector() { }} > { openAccountModal?.() } - function handleChangeNetwork() { - openChainModal?.() - } - const [hideDisclaimer] = useLocalStorage("hideDisclaimer", false) const [wrapETH, setWrapETH] = React.useState(false) const [unWrapETH, setUnWrapETH] = React.useState(false) - // React.useEffect(() => { - // if (!isConnected && !address) { - // useDialogStore.setState({ - // opened: true, - // title: "Please connect your wallet to access Mangrove dApp", - // type: "mangrove", - // children: ( - //
- // - //
- // ), - // }) - // } - // }, [isConnected]) - React.useEffect(() => { if (address && !chain?.id) { disconnect() @@ -252,27 +213,6 @@ const RightPart = withClientOnly(() => { setUnWrapETH(false)} /> - {/* */} @@ -306,10 +246,6 @@ const RightPart = withClientOnly(() => { Bridge assets - - - Change network - {chain?.testnet && ( @@ -321,7 +257,8 @@ const RightPart = withClientOnly(() => { {(chain?.id == blastSepolia.id || chain?.id == blast.id || - chain?.id == baseSepolia.id) && ( + chain?.id == baseSepolia.id || + chain?.id == arbitrum.id) && ( <> setWrapETH(!wrapETH)}>
diff --git a/hooks/use-addresses.ts b/hooks/use-addresses.ts index 91be7eeb..8268f18c 100644 --- a/hooks/use-addresses.ts +++ b/hooks/use-addresses.ts @@ -1,4 +1,7 @@ import { + arbitrumMangrove, + arbitrumMarkets, + arbitrumTokens, baseSepoliaLogics, baseSepoliaMangrove, baseSepoliaMarkets, @@ -9,13 +12,15 @@ import { blastTokens, } from "@mangrovedao/mgv/addresses" import { arbitrum, baseSepolia, blast } from "viem/chains" -import { useChainId } from "wagmi" +import { useAccount } from "wagmi" export function useMangroveAddresses() { - const chain = useChainId() - switch (chain) { + const { chainId } = useAccount() + switch (chainId) { case blast.id: return blastMangrove + case arbitrum.id: + return arbitrumMangrove case baseSepolia.id: return baseSepoliaMangrove default: @@ -24,8 +29,8 @@ export function useMangroveAddresses() { } export function useKandelSeeder() { - const chain = useChainId() - switch (chain) { + const { chainId } = useAccount() + switch (chainId) { case blast.id: return "0x4bb7567303c8bde27a4b490b3e5f1593c891b03d" case arbitrum.id: @@ -38,10 +43,12 @@ export function useKandelSeeder() { } export function useMarkets() { - const chain = useChainId() - switch (chain) { + const { chainId } = useAccount() + switch (chainId) { case blast.id: return blastMarkets + case arbitrum.id: + return arbitrumMarkets case baseSepolia.id: return baseSepoliaMarkets default: @@ -50,10 +57,12 @@ export function useMarkets() { } export function useLogics() { - const chain = useChainId() - switch (chain) { + const { chainId } = useAccount() + switch (chainId) { case blast.id: return blastLogics + case arbitrum.id: + return [] case baseSepolia.id: return baseSepoliaLogics default: @@ -62,10 +71,12 @@ export function useLogics() { } export function useTokens() { - const chain = useChainId() - switch (chain) { + const { chainId } = useAccount() + switch (chainId) { case blast.id: return blastTokens + case arbitrum.id: + return arbitrumTokens case baseSepolia.id: return baseSepoliaTokens default: diff --git a/hooks/use-mangrove-token-price-query.ts b/hooks/use-mangrove-token-price-query.ts index 8a44b267..6c256366 100644 --- a/hooks/use-mangrove-token-price-query.ts +++ b/hooks/use-mangrove-token-price-query.ts @@ -1,7 +1,7 @@ import { useQuery } from "@tanstack/react-query" import { z } from "zod" -import { useAccount, useChainId } from "wagmi" +import { useAccount } from "wagmi" const tokenSchema = z.object({ takerSentTokenSymbol: z.string(), @@ -25,7 +25,7 @@ const useMangroveTokenPricesQuery = ( baseAddress?: string, quoteAddress?: string, ) => { - const chainId = useChainId() + const { chainId } = useAccount() return useQuery({ queryKey: ["mangroveTokenPrice", baseAddress, quoteAddress, chainId], queryFn: async () => { diff --git a/hooks/use-token-from-id.ts b/hooks/use-token-from-id.ts index b54c3770..26cb90e9 100644 --- a/hooks/use-token-from-id.ts +++ b/hooks/use-token-from-id.ts @@ -6,11 +6,11 @@ import { useTokens } from "./use-addresses" export function useTokenFromId(address: Address) { const tokens = useTokens() return useQuery({ - // eslint-disable-next-line @tanstack/query/exhaustive-deps queryKey: ["tokenFromId", address, tokens], queryFn: () => { if (!(address && tokens)) return null - return tokens.find((item) => item.address == address) + const token = tokens.find((item) => item.address == address) + return token ?? null }, enabled: !!(address && tokens), }) diff --git a/package.json b/package.json index 80c6db67..e1a828c8 100644 --- a/package.json +++ b/package.json @@ -25,7 +25,7 @@ "@mangrovedao/context-addresses": "^1.3.4", "@mangrovedao/indexer-sdk": "0.0.11-44", "@mangrovedao/mangrove-deployments": "2.2.4-5", - "@mangrovedao/mgv": "^0.9.0", + "@mangrovedao/mgv": "^0.9.3", "@radix-ui/react-alert-dialog": "^1.0.5", "@radix-ui/react-checkbox": "^1.0.4", "@radix-ui/react-collapsible": "^1.0.3", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index b7017b16..31e94b4d 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -27,8 +27,8 @@ importers: specifier: 2.2.4-5 version: 2.2.4-5 '@mangrovedao/mgv': - specifier: ^0.9.0 - version: 0.9.0(typescript@5.4.5)(viem@2.13.10(bufferutil@4.0.8)(typescript@5.4.5)(zod@3.23.8)) + specifier: ^0.9.3 + version: 0.9.3(typescript@5.4.5)(viem@2.13.10(bufferutil@4.0.8)(typescript@5.4.5)(zod@3.23.8)) '@radix-ui/react-alert-dialog': specifier: ^1.0.5 version: 1.0.5(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) @@ -1784,8 +1784,8 @@ packages: '@mangrovedao/mangrove-deployments@2.2.4-5': resolution: {integrity: sha512-L/KfJ6ZNPlOxlLMEWGQ7UUeQ8Kog6ZUadryGBQGv9h0i4QB8SBjVJ3U40lGFhRpTeEfor0nCy33zbiR81eeykg==} - '@mangrovedao/mgv@0.9.0': - resolution: {integrity: sha512-AZc90TjuaAxXSQrdxY/ixnp8o8s4+ied+DqWGjfZDJDmWTGNrCU/ycH6/JHjXl3FYxMGRAp1WguCHvtTeZ730w==} + '@mangrovedao/mgv@0.9.3': + resolution: {integrity: sha512-JI2L55/HevIxiyH3gnkg/W9qvE/MpvO0p+cUnhSgzsr5GmOhacHcFR5LrLKMuxCixpWejl2eMoJGFh0VJyTccg==} peerDependencies: typescript: '>=5.0.4' viem: ^2.9.1 @@ -11736,7 +11736,7 @@ snapshots: '@mangrovedao/context-addresses': 1.3.5 semver: 7.6.2 - '@mangrovedao/mgv@0.9.0(typescript@5.4.5)(viem@2.13.10(bufferutil@4.0.8)(typescript@5.4.5)(zod@3.23.8))': + '@mangrovedao/mgv@0.9.3(typescript@5.4.5)(viem@2.13.10(bufferutil@4.0.8)(typescript@5.4.5)(zod@3.23.8))': dependencies: viem: 2.13.10(bufferutil@4.0.8)(typescript@5.4.5)(zod@3.23.8) optionalDependencies: diff --git a/providers/chains.tsx b/providers/chains.tsx index d881f66d..c49a923a 100644 --- a/providers/chains.tsx +++ b/providers/chains.tsx @@ -8,7 +8,7 @@ import { import { usePathname } from "next/navigation" import React from "react" import type { Chain } from "viem/chains" -import { useChainId } from "wagmi" +import { useAccount } from "wagmi" export const chainsConfig = { mangroveCompatibleChainIds, @@ -31,7 +31,7 @@ const ChainsContext = React.createContext({}) export const useChains = () => React.useContext(ChainsContext) export const ChainsProvider = ({ children }: React.PropsWithChildren) => { - const chainId = useChainId() + const { chainId } = useAccount() const [isChainDialogOpen, setIsChainDialogOpen] = React.useState(false) const [chains, setChains] = React.useState([]) const [isChainCompatibleWithMangrove, setIsChainCompatibleWithMangrove] = diff --git a/providers/wallet-connect.tsx b/providers/wallet-connect.tsx index 45637621..b70ad68b 100644 --- a/providers/wallet-connect.tsx +++ b/providers/wallet-connect.tsx @@ -8,7 +8,7 @@ import { getDefaultConfig, } from "@rainbow-me/rainbowkit" import { QueryClient, QueryClientProvider } from "@tanstack/react-query" -import { baseSepolia, blast } from "viem/chains" +import { arbitrum, baseSepolia, blast } from "viem/chains" import { WagmiProvider, http } from "wagmi" import { env } from "@/env.mjs" @@ -26,6 +26,7 @@ const config = getDefaultConfig({ transports: { [baseSepolia.id]: http(), [blast.id]: http(), + [arbitrum.id]: http(), }, }) diff --git a/stores/hovered-offer.store.ts b/stores/hovered-offer.store.ts index 3c233dc9..b15edff1 100644 --- a/stores/hovered-offer.store.ts +++ b/stores/hovered-offer.store.ts @@ -3,7 +3,7 @@ import { create, type StateCreator } from "zustand" import { OfferParsed } from "@mangrovedao/mgv" type Store = { - hoveredOffer?: OfferParsed + hoveredOffer?: OfferParsed & { formattedGives?: string } } type Actions = { diff --git a/utils/chains.ts b/utils/chains.ts index bb1c7513..d18ac62a 100644 --- a/utils/chains.ts +++ b/utils/chains.ts @@ -52,7 +52,7 @@ export function getWhitelistedChainObjects() { return renameChainNames(result) } -export function getChainObjectById(chainId: string): Chain | undefined { +export function getChainObjectById(chainId?: string): Chain | undefined { for (const chainName in wagmiChains) { const chainObject: Chain | undefined = (wagmiChains as WagmiChains)[ chainName diff --git a/utils/enums.ts b/utils/enums.ts new file mode 100644 index 00000000..40e535c5 --- /dev/null +++ b/utils/enums.ts @@ -0,0 +1,19 @@ +export type ValueOf = T[keyof T] + +export function enumKeys( + obj: O, +): K[] { + return Object.keys(obj).filter((k) => Number.isNaN(Number(k))) as K[] +} + +export function enumValues(obj: O): O[keyof O][] { + let values = [] + for (const tl of enumKeys(obj)) { + const value = obj[tl] + + if (typeof value === "number") { + values.push(obj[tl]) + } + } + return values +}