Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Jose/cow 270 create transaction pre execute post execute flow jose UI pedro #705

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
7670b25
add example app demoing managed tx hook
ribeirojose Jun 10, 2024
978e606
Merge branch 'cowamm-next' into jose/cow-270-create-transaction-pre-e…
ribeirojose Jun 10, 2024
6cf4963
rename useGnosisTransaction to useSafeTransaction
ribeirojose Jun 10, 2024
1a6b65f
Create migrate to new contract version button (#697)
yvesfracari Jun 10, 2024
ab989bd
run formatter
yvesfracari Jun 10, 2024
32e82ba
rename useGnosisTransaction to useSafeTransaction
ribeirojose Jun 10, 2024
0ff74b2
add wagmi to cowamm
ribeirojose Jun 10, 2024
7e5f995
update tx manager api for usage in safe
ribeirojose Jun 10, 2024
8e4614f
cow-amm-deployer: substitute safe sdk for wagmi when possible
ribeirojose Jun 10, 2024
8a199ea
cow-amm-deployer: substitute useRawTxData for useManagedTransaction hook
ribeirojose Jun 10, 2024
494a023
cow-amm-deployer: update deps
ribeirojose Jun 11, 2024
44f0216
cow-amm-deployer: consolidate stop/start/edit into `manage amm` page
ribeirojose Jun 11, 2024
c411da6
Merge branch 'cowamm-next' into jose/cow-270-create-transaction-pre-e…
ribeirojose Jun 11, 2024
f5cdfe1
remove example txmanager app
ribeirojose Jun 11, 2024
9e630fd
composable-cow-api: undo changes to ponder.config.ts
ribeirojose Jun 11, 2024
ac27727
composable-cow-api: add helpers from cows repos
ribeirojose Jun 11, 2024
8d698e8
composable-cow-api: implement loading states in withdraw/deposit forms
ribeirojose Jun 11, 2024
84a18c6
composable-cow-api: use Map instead of object in useManagedTransactio…
ribeirojose Jun 11, 2024
77ef532
composable-cow-api: add status priority order to useManagedTransactio…
ribeirojose Jun 11, 2024
ed8fc7f
composable-cow-api: add new ui
ribeirojose Jun 12, 2024
4fd231d
merge into cowamm-next
yvesfracari Jun 12, 2024
9bee5cd
refactor test page to amm manager
yvesfracari Jun 12, 2024
4d4926d
refactor token links
yvesfracari Jun 13, 2024
141dcdb
separate token info into different cells and fix hover bg color
yvesfracari Jun 13, 2024
07ffff1
run formatter
yvesfracari Jun 13, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions apps/cow-amm-deployer/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
"@safe-global/safe-core-sdk-types": "^5.0.1",
"@safe-global/safe-gateway-typescript-sdk": "^3.21.2",
"@tanstack/react-query": "5.40.1",
"@types/react-plotly.js": "^2.6.3",
"@uniswap/sdk-core": "^5.3.0",
"babel-plugin-react-compiler": "0.0.0-experimental-938cd9a-20240601",
"class-variance-authority": "^0.7.0",
Expand All @@ -59,10 +60,14 @@
"graphql-tag": "^2.12.6",
"lodash": "^4.17.21",
"lodash.merge": "^4.6.2",
"lucide-react": "^0.394.0",
"next": "15.0.0-rc.0",
"plotly.js": "^2.27.1",
"react": "19.0.0-rc-6230622a1a-20240610",
"react-chartjs-2": "^5.2.0",
"react-dom": "19.0.0-rc-6230622a1a-20240610",
"react-hook-form": "7.51.5",
"react-plotly.js": "^2.6.0",
"server-only": "^0.0.1",
"swr": "^2.2.5",
"tailwind-merge": "^2.3.0",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import { formatNumber } from "@bleu/ui";
import { useRouter } from "next/navigation";

import { StatusBadge } from "#/components/StatusBadge";
import Table from "#/components/Table";
import { TokenInfo } from "#/components/TokenInfo";
import { ICowAmm } from "#/lib/fetchAmmData";
Expand All @@ -24,6 +25,7 @@ export function AmmsTable({
>
<Table.HeaderRow>
<Table.HeaderCell>Token pair</Table.HeaderCell>
<Table.HeaderCell classNames="sr-only">Token Pair</Table.HeaderCell>
<Table.HeaderCell>Value</Table.HeaderCell>
<Table.HeaderCell>Status</Table.HeaderCell>
<Table.HeaderCell>Updated at</Table.HeaderCell>
Expand All @@ -42,29 +44,29 @@ export function AmmsTable({
onClick={() => {
router.push(`/${userId}/amms/${amm.id}`);
}}
classNames="hover:cursor-pointer hover:bg-foreground/50"
classNames="hover:cursor-pointer hover:bg-accent"
>
<Table.BodyCell>
<span className="text-base space-y-1">
<TokenInfo token={amm.token0} />
<TokenInfo token={amm.token1} />
</span>
<TokenInfo
token={amm.token0}
showBalance={true}
showExplorerLink={false}
/>
</Table.BodyCell>
<Table.BodyCell>
<TokenInfo
token={amm.token1}
showBalance={true}
showExplorerLink={false}
/>
</Table.BodyCell>
<Table.BodyCell>
<span className="text-base">
$ {formatNumber(amm.totalUsdValue, 2)}
</span>
</Table.BodyCell>
<Table.BodyCell>
{amm.disabled ? (
<span className="bg-highlight rounded-full p-2 text-base">
Paused
</span>
) : (
<span className="bg-success rounded-full p-2 text-base">
Active
</span>
)}
<StatusBadge disabled={amm.disabled} />
</Table.BodyCell>
<Table.BodyCell>
<span className="text-base">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,24 +26,19 @@ import { cn } from "#/lib/utils";

import { DisableAmmButton } from "./DisableAmmButton";

export function EditAMMForm({
cowAmmData,
}: {
cowAmmData: ICowAmm;
submitButtonText: string;
}) {
export function EditAMMForm({ ammData }: { ammData: ICowAmm }) {
const form = useForm<z.input<typeof ammEditSchema>>({
// @ts-ignore
resolver: zodResolver(ammEditSchema),
defaultValues: {
safeAddress: cowAmmData.user.address,
chainId: cowAmmData.chainId,
token0: cowAmmData.token0,
token1: cowAmmData.token1,
safeAddress: ammData.user.address,
chainId: ammData.chainId,
token0: ammData.token0,
token1: ammData.token1,
minTradedToken0: Number(
formatUnits(cowAmmData.minTradedToken0, cowAmmData.token0.decimals)
formatUnits(ammData.minTradedToken0, ammData.token0.decimals),
),
priceOracleSchema: cowAmmData.decodedPriceOracleData,
priceOracleSchema: ammData.decodedPriceOracleData,
},
});

Expand All @@ -57,7 +52,7 @@ export function EditAMMForm({
const onSubmit = async (data: typeof ammEditSchema._type) => {
const txArgs = buildTxEditAMMArgs({
data: data,
ammAddress: cowAmmData.order.owner as Address,
ammAddress: ammData.order.owner as Address,
});

try {
Expand All @@ -77,16 +72,16 @@ export function EditAMMForm({
}
};

const submitButtonText = cowAmmData.disabled ? "Enable AMM" : "Update AMM";
const submitButtonText = ammData.disabled ? "Enable AMM" : "Update AMM";

return (
// @ts-ignore
<Form {...form} onSubmit={onSubmit} className="flex flex-col gap-y-3">
<div className="flex flex-col w-full">
<span className="mb-2 h-5 block text-sm">Token Pair</span>
<div className="flex h-fit gap-x-7">
<TokenInfo token={cowAmmData.token0} />
<TokenInfo token={cowAmmData.token1} />
<TokenInfo token={ammData.token0} />
<TokenInfo token={ammData.token1} />
</div>
</div>
<PriceOracleForm form={form} />
Expand All @@ -95,7 +90,7 @@ export function EditAMMForm({
<AccordionTrigger
className={cn(
errors.minTradedToken0 ? "text-destructive" : "",
"pt-0"
"pt-0",
)}
>
Advanced Options
Expand All @@ -104,7 +99,7 @@ export function EditAMMForm({
<Input
label="Minimum first token amount on each order"
type="number"
step={10 ** -cowAmmData.token0.decimals}
step={10 ** -ammData.token0.decimals}
name="minTradedToken0"
tooltipText="This parameter is used to not overload the CoW Orderbook with small orders. By default, 10 dollars worth of the first token will be the minimum amount for each order."
/>
Expand All @@ -113,18 +108,18 @@ export function EditAMMForm({
</Accordion>

<div className="flex space-x-2 space-between mt-2">
{!cowAmmData.disabled && <DisableAmmButton ammData={cowAmmData} />}
{!ammData.disabled && <DisableAmmButton ammData={ammData} />}
<Button
loading={
isSubmitting ||
!["final", "idle", "confirmed", "error"].includes(status || "")
}
variant={cowAmmData.disabled ? "default" : "highlight"}
variant={ammData.disabled ? "default" : "highlight"}
type="submit"
disabled={isSubmitting || cowAmmData.version !== "Standalone"}
disabled={isSubmitting || ammData.version !== "Standalone"}
loadingText="Confirming..."
>
{cowAmmData.disabled ? <PlayIcon className="mr-1" /> : ""}
{ammData.disabled ? <PlayIcon className="mr-1" /> : ""}
<span>{submitButtonText}</span>
</Button>
</div>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
"use client";

import { Card } from "@bleu/ui";
import {
ArrowLeftIcon,
ArrowTopRightIcon,
ExternalLinkIcon,
} from "@radix-ui/react-icons";
import Link from "next/link";
import { Address } from "viem";

import { Button } from "#/components/Button";
import { BlockExplorerLink } from "#/components/ExplorerLink";
import { LinkComponent } from "#/components/Link";
import { StatusBadge } from "#/components/StatusBadge";
import { TokenPairLogo } from "#/components/TokenPairLogo";
import { getExplorerAddressLink } from "#/lib/cowExplorer";
import { ICowAmm, IToken } from "#/lib/fetchAmmData";
import { truncateMiddle } from "#/lib/truncateMiddle";
import { ChainId } from "#/utils/chainsPublicClients";

import { PriceInformation } from "./PriceInformation";

export function Header({
ammData,
}: {
ammData: ICowAmm;
oldVersionOfAmm: boolean;
}) {
const poolName = `${ammData.token0.symbol}/${ammData.token1.symbol}`;

return (
<Card.Root className="w-full overflow-visible max-w-full rounded-none bg-background">
<Card.Header className="p-0 flex flex-col gap-y-2">
<LinkComponent href={`/${ammData.user.id}/amms`}>
<Button className="flex items-center gap-1 p-1" variant="ghost">
<ArrowLeftIcon />
Back to AMMs table
</Button>
</LinkComponent>
<Card.Title className="text-3xl flex flex-row gap-2 my-2 p-0 items-center">
<TokenPairLogo
token0={ammData.token0}
token1={ammData.token1}
chainId={ammData.chainId}
/>
{poolName}
<BlockExplorerLink
type="token"
label={<ExternalLinkIcon />}
identifier={ammData.order.owner}
networkId={ammData.chainId as ChainId}
/>
<StatusBadge disabled={ammData.disabled} />
</Card.Title>
<Card.Description className="flex mt-5 justify-between items-center text-base p-0">
<div className="flex flex-row gap-2 items-center">
Price Oracle: <PriceInformation cowAmm={ammData} />
</div>
<div className="flex flex-row gap-2 items-center">
Orders: CoW Explorer
<Link
href={
new URL(
getExplorerAddressLink(
ammData.order.chainId as ChainId,
ammData.order.owner as Address,
),
)
}
rel="noreferrer noopener"
target="_blank"
>
<ArrowTopRightIcon />
</Link>
</div>
<TokenLink chainId={ammData.chainId} token={ammData.token0} />
<TokenLink chainId={ammData.chainId} token={ammData.token1} />
</Card.Description>
</Card.Header>
</Card.Root>
);
}

export function TokenLink({
chainId,
token,
}: {
chainId: ChainId;
token: IToken;
}) {
return (
<div className="flex flex-row gap-2 items-center">
{token.symbol}: {truncateMiddle(token.address, 4)}
<BlockExplorerLink
type="token"
label={<ArrowTopRightIcon />}
identifier={token.address}
networkId={chainId as ChainId}
/>
</div>
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
"use client";

import {
Card,
Separator,
TabsContent,
TabsList,
TabsRoot,
TabsTrigger,
} from "@bleu/ui";

import { DepositForm } from "#/components/DepositForm";
import { ICowAmm } from "#/lib/fetchAmmData";

import { WithdrawForm } from "../../../../../components/WithdrawForm";
import { EditAMMForm } from "./EditAMMForm";

export function Manage({
ammData,
oldVersionOfAmm,
walletBalanceToken0,
walletBalanceToken1,
}: {
ammData: ICowAmm;
oldVersionOfAmm: boolean;
walletBalanceToken0: string;
walletBalanceToken1: string;
}) {
return (
<Card.Root className="bg-foreground text-background overflow-visible max-w-full rounded-none px-3">
<Card.Header className="py-1 px-0">
<Card.Title className="px-0 text-xl">Manage</Card.Title>
<Card.Description className="px-0 text-base">
Manage your CoW AMM pool
</Card.Description>
<Separator />
</Card.Header>
<Card.Content className="px-0">
<TabsRoot defaultValue={oldVersionOfAmm ? "edit" : "deposit"}>
<TabsList>
<TabsTrigger
className="rounded-none"
value="deposit"
disabled={oldVersionOfAmm}
>
Deposit
</TabsTrigger>
<TabsTrigger
className="rounded-none"
value="withdraw"
disabled={oldVersionOfAmm}
>
Withdraw
</TabsTrigger>
<TabsTrigger className="rounded-none" value="edit">
Edit Parameters
</TabsTrigger>
</TabsList>
<TabsContent value="deposit">
<DepositForm
ammData={ammData}
walletBalanceToken0={walletBalanceToken0}
walletBalanceToken1={walletBalanceToken1}
/>
</TabsContent>
<TabsContent value="withdraw">
<WithdrawForm ammData={ammData} />
</TabsContent>
<TabsContent value="edit">
<EditAMMForm ammData={ammData} />
</TabsContent>
</TabsRoot>
</Card.Content>
</Card.Root>
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
"use client";

import { Card } from "@bleu/ui";

import { ICowAmm } from "#/lib/fetchAmmData";

import { PoolCompositionTable } from "./PoolCompositionTable";

export function PoolComposition({ ammData }: { ammData: ICowAmm }) {
return (
<Card.Root className="bg-foreground text-background overflow-visible max-w-full rounded-none px-3">
<Card.Header className="py-1 px-0">
<Card.Title className="px-0 text-xl">Pool composition</Card.Title>
<Card.Description className="px-0 text-base">
Check your current CoW AMM pool composition
</Card.Description>
</Card.Header>
<Card.Content className="px-0">
<PoolCompositionTable ammData={ammData} />
</Card.Content>
</Card.Root>
);
}
Loading
Loading