From 47c8a5329eb4125289fa7fc488adeac76454b901 Mon Sep 17 00:00:00 2001
From: Pedro Yves Fracari <55461956+yvesfracari@users.noreply.github.com>
Date: Thu, 29 Feb 2024 16:00:52 -0300
Subject: [PATCH] [CoW AMM Deployer] Add page to waiting transaction being
indexed (#611)
* chore: add stop tx procssing page
* chore: add create tx processing page
---
.../app/amm/(components)/CreateAmmForm.tsx | 2 +-
.../src/app/amm/createtxprocessing/layout.tsx | 3 +
.../src/app/amm/createtxprocessing/page.tsx | 46 ++++++++
apps/cow-amm-deployer/src/app/amm/page.tsx | 2 +-
.../src/app/amm/stoptxprocessing/layout.tsx | 3 +
.../src/app/amm/stoptxprocessing/page.tsx | 40 +++++++
.../src/hooks/useRunningAmmInfo.ts | 108 ++++++++++--------
7 files changed, 154 insertions(+), 50 deletions(-)
create mode 100644 apps/cow-amm-deployer/src/app/amm/createtxprocessing/layout.tsx
create mode 100644 apps/cow-amm-deployer/src/app/amm/createtxprocessing/page.tsx
create mode 100644 apps/cow-amm-deployer/src/app/amm/stoptxprocessing/layout.tsx
create mode 100644 apps/cow-amm-deployer/src/app/amm/stoptxprocessing/page.tsx
diff --git a/apps/cow-amm-deployer/src/app/amm/(components)/CreateAmmForm.tsx b/apps/cow-amm-deployer/src/app/amm/(components)/CreateAmmForm.tsx
index 9f39c186d..3bcc7b8de 100644
--- a/apps/cow-amm-deployer/src/app/amm/(components)/CreateAmmForm.tsx
+++ b/apps/cow-amm-deployer/src/app/amm/(components)/CreateAmmForm.tsx
@@ -78,7 +78,7 @@ export function CreateAmmForm() {
await createAMMArgs(data).then((txArgs) => {
sendTransactions(txArgs);
});
- router.push("/amm");
+ router.push("/amm/createtxprocessing");
};
useEffect(() => {
diff --git a/apps/cow-amm-deployer/src/app/amm/createtxprocessing/layout.tsx b/apps/cow-amm-deployer/src/app/amm/createtxprocessing/layout.tsx
new file mode 100644
index 000000000..c1492b79b
--- /dev/null
+++ b/apps/cow-amm-deployer/src/app/amm/createtxprocessing/layout.tsx
@@ -0,0 +1,3 @@
+export default function Layout({ children }: { children: React.ReactNode }) {
+ return children;
+}
diff --git a/apps/cow-amm-deployer/src/app/amm/createtxprocessing/page.tsx b/apps/cow-amm-deployer/src/app/amm/createtxprocessing/page.tsx
new file mode 100644
index 000000000..ecae66a49
--- /dev/null
+++ b/apps/cow-amm-deployer/src/app/amm/createtxprocessing/page.tsx
@@ -0,0 +1,46 @@
+"use client";
+
+import { useSafeAppsSDK } from "@gnosis.pm/safe-apps-react-sdk";
+import { useRouter } from "next/navigation";
+import { useEffect } from "react";
+import { Address } from "viem";
+
+import { Spinner } from "#/components/Spinner";
+import { checkIsAmmRunning, fetchLastAmmInfo } from "#/hooks/useRunningAmmInfo";
+import { ChainId } from "#/utils/chainsPublicClients";
+
+export default function Page() {
+ const {
+ safe: { safeAddress, chainId },
+ } = useSafeAppsSDK();
+ const router = useRouter();
+
+ async function redirectToHomeIfAmmIsRunningAndIndexed() {
+ const [isAmmRunning, cowAmmDataIndexed] = await Promise.all([
+ checkIsAmmRunning(chainId as ChainId, safeAddress as Address),
+ fetchLastAmmInfo({
+ chainId: chainId as ChainId,
+ safeAddress: safeAddress as Address,
+ }),
+ ]);
+ if (isAmmRunning && cowAmmDataIndexed) {
+ router.push("/amm");
+ }
+ }
+ useEffect(() => {
+ const intervalId = setInterval(
+ redirectToHomeIfAmmIsRunningAndIndexed,
+ 1000,
+ );
+ return () => clearInterval(intervalId);
+ }, []);
+
+ return (
+
+
+ The transaction is being processed
+
+
+
+ );
+}
diff --git a/apps/cow-amm-deployer/src/app/amm/page.tsx b/apps/cow-amm-deployer/src/app/amm/page.tsx
index bb697f4f6..80e94961d 100644
--- a/apps/cow-amm-deployer/src/app/amm/page.tsx
+++ b/apps/cow-amm-deployer/src/app/amm/page.tsx
@@ -124,7 +124,7 @@ export default function Page() {
chainId: safe.chainId as ChainId,
},
]);
- router.refresh();
+ router.push("/amm/stoptxprocessing");
}}
>
Confirm
diff --git a/apps/cow-amm-deployer/src/app/amm/stoptxprocessing/layout.tsx b/apps/cow-amm-deployer/src/app/amm/stoptxprocessing/layout.tsx
new file mode 100644
index 000000000..c1492b79b
--- /dev/null
+++ b/apps/cow-amm-deployer/src/app/amm/stoptxprocessing/layout.tsx
@@ -0,0 +1,3 @@
+export default function Layout({ children }: { children: React.ReactNode }) {
+ return children;
+}
diff --git a/apps/cow-amm-deployer/src/app/amm/stoptxprocessing/page.tsx b/apps/cow-amm-deployer/src/app/amm/stoptxprocessing/page.tsx
new file mode 100644
index 000000000..fc3610f1b
--- /dev/null
+++ b/apps/cow-amm-deployer/src/app/amm/stoptxprocessing/page.tsx
@@ -0,0 +1,40 @@
+"use client";
+
+import { useSafeAppsSDK } from "@gnosis.pm/safe-apps-react-sdk";
+import { useRouter } from "next/navigation";
+import { useEffect } from "react";
+import { Address } from "viem";
+
+import { Spinner } from "#/components/Spinner";
+import { checkIsAmmRunning } from "#/hooks/useRunningAmmInfo";
+import { ChainId } from "#/utils/chainsPublicClients";
+
+export default function Page() {
+ const {
+ safe: { safeAddress, chainId },
+ } = useSafeAppsSDK();
+ const router = useRouter();
+
+ async function redirectToHomeIfAmmIsNotRunning() {
+ const isAmmRunning = await checkIsAmmRunning(
+ chainId as ChainId,
+ safeAddress as Address,
+ );
+ if (!isAmmRunning) {
+ router.push("/amm");
+ }
+ }
+ useEffect(() => {
+ const intervalId = setInterval(redirectToHomeIfAmmIsNotRunning, 1000);
+ return () => clearInterval(intervalId);
+ }, []);
+
+ return (
+
+
+ The transaction is being processed
+
+
+
+ );
+}
diff --git a/apps/cow-amm-deployer/src/hooks/useRunningAmmInfo.ts b/apps/cow-amm-deployer/src/hooks/useRunningAmmInfo.ts
index 6161e52ad..e970f8e13 100644
--- a/apps/cow-amm-deployer/src/hooks/useRunningAmmInfo.ts
+++ b/apps/cow-amm-deployer/src/hooks/useRunningAmmInfo.ts
@@ -21,7 +21,7 @@ gql(`
where: {user: $userId, handler: $handler}
limit: 1
orderBy: "blockNumber"
- orderDirection: "asc"
+ orderDirection: "desc"
) {
items {
id
@@ -55,7 +55,7 @@ gql(`
}
`);
-const NULL_ACTIVE_ORDER =
+export const NULL_ACTIVE_ORDER =
"0x0000000000000000000000000000000000000000000000000000000000000000" as const;
export async function fetchLastAmmInfo({
@@ -70,7 +70,7 @@ export async function fetchLastAmmInfo({
handler: COW_AMM_HANDLER_ADDRESS[chainId as ChainId],
});
- const order = orders.items[0];
+ const order = orders?.items?.[0];
if (!order || !order.decodedSuccess) return;
return decodePriceOracle({ cowAmmParameters: order.cowAmmParameters });
@@ -85,6 +85,7 @@ export const ADDRESSES_PRICE_ORACLES = {
export async function decodePriceOracle({
cowAmmParameters,
}: {
+ // @ts-ignore
cowAmmParameters: UserCurrentAmmQuery["orders"]["items"][0]["cowAmmParameters"];
}) {
const priceOracle =
@@ -127,7 +128,10 @@ export function decodePriceOracleData({
throw new Error("Unknown price oracle");
}
-export async function checkAmmRunning(chainId: ChainId, safeAddress: Address) {
+export async function checkIsAmmRunning(
+ chainId: ChainId,
+ safeAddress: Address,
+) {
const publicClient = publicClientsFromIds[chainId];
return publicClient
.readContract({
@@ -146,6 +150,7 @@ export function useRunningAMM(): {
loaded: boolean;
isAmmRunning: boolean;
error: boolean;
+ updateAmmInfo: () => Promise;
} {
const {
safe: { safeAddress, chainId },
@@ -157,53 +162,60 @@ export function useRunningAMM(): {
const [error, setError] = useState(false);
const { assets } = useSafeBalances();
- useEffect(() => {
- async function loadCowAmm() {
- try {
- const [gqlInfo, newIsAmmRunning] = await Promise.all([
- fetchLastAmmInfo({
- chainId: chainId as ChainId,
- safeAddress: safeAddress as Address,
- }),
- checkAmmRunning(chainId as ChainId, safeAddress as Address),
- ]);
-
- const token0 = assets.find(
- (asset) =>
- asset.tokenInfo.address.toLowerCase() ===
- gqlInfo?.token0?.address.toLowerCase(),
- );
- const token1 = assets.find(
- (asset) =>
- asset.tokenInfo.address.toLowerCase() ===
- gqlInfo?.token1?.address.toLowerCase(),
- );
-
- if (!token0 || !token1) {
- setLoaded(true);
- return;
- }
+ async function loadCoWAmmRunning() {
+ const newIsAmmRunning = await checkIsAmmRunning(
+ chainId as ChainId,
+ safeAddress as Address,
+ );
+ setIsAmmRunning(newIsAmmRunning);
+ }
- const totalUsdValue =
- (Number(token0.fiatBalance) || 0) + (Number(token1.fiatBalance) || 0);
-
- setCowAmm({
- token0,
- token1,
- totalUsdValue,
- minTradedToken0: gqlInfo?.minTradedToken0 as number,
- priceOracle: gqlInfo?.priceOracleType as PRICE_ORACLES,
- priceOracleData: gqlInfo?.priceOracleDataDecoded as PriceOracleData,
- });
- setIsAmmRunning(newIsAmmRunning);
- } catch (e) {
- setError(true);
- }
- setLoaded(true);
+ async function loadCowAmm() {
+ const gqlInfo = await fetchLastAmmInfo({
+ chainId: chainId as ChainId,
+ safeAddress: safeAddress as Address,
+ });
+
+ const token0 = assets.find(
+ (asset) =>
+ asset.tokenInfo.address.toLowerCase() ===
+ gqlInfo?.token0?.address.toLowerCase(),
+ );
+ const token1 = assets.find(
+ (asset) =>
+ asset.tokenInfo.address.toLowerCase() ===
+ gqlInfo?.token1?.address.toLowerCase(),
+ );
+
+ if (!token0 || !token1) {
+ return;
}
- loadCowAmm();
+ const totalUsdValue =
+ (Number(token0.fiatBalance) || 0) + (Number(token1.fiatBalance) || 0);
+
+ setCowAmm({
+ token0,
+ token1,
+ totalUsdValue,
+ minTradedToken0: gqlInfo?.minTradedToken0 as number,
+ priceOracle: gqlInfo?.priceOracleType as PRICE_ORACLES,
+ priceOracleData: gqlInfo?.priceOracleDataDecoded as PriceOracleData,
+ });
+ }
+
+ async function updateAmmInfo(): Promise {
+ setLoaded(false);
+ setError(false);
+ await Promise.all([loadCoWAmmRunning(), loadCowAmm()]).catch(() => {
+ setError(true);
+ });
+ setLoaded(true);
+ }
+
+ useEffect(() => {
+ updateAmmInfo();
}, [safeAddress, chainId, assets]);
- return { cowAmm, loaded, isAmmRunning, error };
+ return { cowAmm, loaded, isAmmRunning, error, updateAmmInfo };
}