diff --git a/apps/maestro/src/features/CanonicalTokenDeployment/CanonicalTokenDeployment.tsx b/apps/maestro/src/features/CanonicalTokenDeployment/CanonicalTokenDeployment.tsx
index 7165b7c38..dfc06f2ab 100644
--- a/apps/maestro/src/features/CanonicalTokenDeployment/CanonicalTokenDeployment.tsx
+++ b/apps/maestro/src/features/CanonicalTokenDeployment/CanonicalTokenDeployment.tsx
@@ -1,6 +1,9 @@
+import { Alert, InfoIcon } from "@axelarjs/ui";
import { useMemo, type FC } from "react";
import dynamic from "next/dynamic";
+import { useChainFromRoute } from "~/lib/hooks";
+import { useGetChainsConfig } from "~/services/axelarConfigs/hooks";
import { MultiStepDialog, StepLoading } from "~/ui/compounds/MultiStepForm";
import {
CanonicalTokenDeploymentStateProvider,
@@ -24,6 +27,23 @@ const STEPS = [Step1, Step2, Step3];
const CanonicalTokenDeployment: FC = () => {
const { state, actions } = useCanonicalTokenDeploymentStateContainer();
+ const routeChain = useChainFromRoute();
+ const { data: tokenInfo } = useGetChainsConfig({
+ axelarChainId: routeChain?.axelarChainId,
+ tokenAddress: state.tokenDetails.tokenAddress,
+ });
+
+ console.log({ routeChain, tokenInfo });
+
+ const isGatewayToken = useMemo(
+ () =>
+ (
+ tokenInfo?.assets.map((asset: any) =>
+ asset.tokenAddress.toLowerCase()
+ ) || []
+ ).includes(state.tokenDetails.tokenAddress.toLowerCase()),
+ [tokenInfo, state.tokenDetails.tokenAddress]
+ );
const CurrentStep = useMemo(() => STEPS[state.step], [state.step]);
@@ -32,6 +52,14 @@ const CanonicalTokenDeployment: FC = () => {
[state.step]
);
+ if (isGatewayToken)
+ return (
+ }>
+ This is a token already supported directly on the Axelar network and
+ cannot be registered in ITS.
+
+ );
+
return (
{
const axelarQueryClient = createAxelarQueryClient(NEXT_PUBLIC_NETWORK_ENV);
+ const axelarConfigClient = createAxelarConfigClient(NEXT_PUBLIC_NETWORK_ENV);
+
return {
req,
res,
@@ -74,6 +78,12 @@ const createContextInner = async ({ req, res }: ContextConfig) => {
axelarscanClient,
"evmChains" as const
),
+ axelarConfigs: axelarConfigs.bind(
+ null,
+ maestroKVClient,
+ axelarConfigClient,
+ "axelarConfigs" as const
+ ),
wagmiChainConfigs: WAGMI_CHAIN_CONFIGS,
},
persistence: {
@@ -186,3 +196,26 @@ async function evmChains(
return evmChainsMap;
}
+
+async function axelarConfigs(
+ kvClient: MaestroKVClient,
+ axelarConfigClient: AxelarConfigClient,
+ cacheKey: TCacheKey
+): Promise {
+ const chainConfigs = await axelarConfigClient.getChainConfigs(
+ NEXT_PUBLIC_NETWORK_ENV
+ );
+
+ const cached = await kvClient.getCached(cacheKey);
+
+ if (cached) {
+ console.log("returning cached axelarConfigs");
+ return cached;
+ }
+ console.log("not returning cached axelarConfigs");
+
+ // cache for 1 hour
+ await kvClient.setCached(cacheKey, chainConfigs, 3600);
+
+ return chainConfigs;
+}
diff --git a/apps/maestro/src/server/routers/_app.ts b/apps/maestro/src/server/routers/_app.ts
index c8aea5728..904c5fed8 100644
--- a/apps/maestro/src/server/routers/_app.ts
+++ b/apps/maestro/src/server/routers/_app.ts
@@ -1,5 +1,6 @@
import { publicProcedure, router } from "~/server/trpc";
import { authRouter } from "./auth";
+import { axelarConfigsRouter } from "./axelarConfigs";
import { axelarjsSDKRouter } from "./axelarjsSDK";
import { axelarscanRouter } from "./axelarscan";
import { erc20Router } from "./erc20";
@@ -16,6 +17,7 @@ export const appRouter = router({
axelarscan: axelarscanRouter,
erc20: erc20Router,
axelarjsSDK: axelarjsSDKRouter,
+ axelarConfigs: axelarConfigsRouter,
interchainToken: interchainTokenRouter,
auth: authRouter,
openai: openaiRouter,
diff --git a/apps/maestro/src/server/routers/axelarConfigs/getChainConfigs.ts b/apps/maestro/src/server/routers/axelarConfigs/getChainConfigs.ts
new file mode 100644
index 000000000..587cefa00
--- /dev/null
+++ b/apps/maestro/src/server/routers/axelarConfigs/getChainConfigs.ts
@@ -0,0 +1,39 @@
+import { TRPCError } from "@trpc/server";
+import { z } from "zod";
+
+import { publicProcedure } from "~/server/trpc";
+
+export const getChainConfigs = publicProcedure
+ .meta({
+ openapi: {
+ summary: "Get S3 chain configs",
+ description: "Get S3 chain configs",
+ method: "GET",
+ path: "/s3-chain-configs",
+ tags: ["s3-chain-configs"],
+ },
+ })
+ .input(
+ z.object({
+ axelarChainId: z.string().max(64),
+ // tokenAddress: z.string().optional(),
+ })
+ )
+ .output(z.any())
+ .query(async ({ ctx, input }) => {
+ try {
+ const response = await ctx.configs.axelarConfigs();
+
+ return response.chains[input.axelarChainId];
+ } catch (error) {
+ // If we get a TRPC error, we throw it
+ if (error instanceof TRPCError) {
+ throw error;
+ }
+ // otherwise, we throw an internal server error
+ throw new TRPCError({
+ code: "INTERNAL_SERVER_ERROR",
+ message: "Failed to get chain configs",
+ });
+ }
+ });
diff --git a/apps/maestro/src/server/routers/axelarConfigs/index.ts b/apps/maestro/src/server/routers/axelarConfigs/index.ts
new file mode 100644
index 000000000..90b8a6fa6
--- /dev/null
+++ b/apps/maestro/src/server/routers/axelarConfigs/index.ts
@@ -0,0 +1,8 @@
+import { router } from "~/server/trpc";
+import { getChainConfigs } from "./getChainConfigs";
+
+export const axelarConfigsRouter = router({
+ getChainConfigs,
+});
+
+export type AxelarConfigsRouter = typeof axelarConfigsRouter;
diff --git a/apps/maestro/src/services/axelarConfigs/hooks.ts b/apps/maestro/src/services/axelarConfigs/hooks.ts
new file mode 100644
index 000000000..9f657f174
--- /dev/null
+++ b/apps/maestro/src/services/axelarConfigs/hooks.ts
@@ -0,0 +1,16 @@
+import { Maybe } from "@axelarjs/utils";
+
+import { trpc } from "~/lib/trpc";
+
+export function useGetChainsConfig(input: { axelarChainId?: string }) {
+ return trpc.axelarConfigs.getChainConfigs.useQuery(
+ {
+ axelarChainId: Maybe.of(input.axelarChainId).mapOr("", String),
+ },
+ {
+ enabled: Boolean(input.axelarChainId),
+ staleTime: 1000 * 60 * 60 * 24, // 24 hours
+ refetchOnWindowFocus: false,
+ }
+ );
+}