Skip to content

Commit

Permalink
Support some USDC transfer on mainnet (#570)
Browse files Browse the repository at this point in the history
* Support some USDC transfer on mainnet

* Fix state reset for relayer register

* Lnbridge exist check

* Fix approve and deposit notification targetChain

* Update liquidity is not enough tooltips
  • Loading branch information
JayJay1024 authored Nov 21, 2023
1 parent a061718 commit cc7817e
Show file tree
Hide file tree
Showing 10 changed files with 154 additions and 25 deletions.
2 changes: 1 addition & 1 deletion packages/apps/src/components/cross-chain-info.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ export default function CrossChainInfo({ fee, bridge, maxMargin, isLoadingMaxMar
{formatBalance(fee.value, fee.token.decimals, { precision: 6 })} {fee.token.symbol}
</span>
) : (
<Tooltip content="No relayer available, please check the transfer amount">
<Tooltip content="Liquidity is not enough">
<Image width={16} height={16} alt="Fee" src="/images/warning.svg" />
</Tooltip>
)}
Expand Down
45 changes: 41 additions & 4 deletions packages/apps/src/components/relayer-manage-modal.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import SegmentedTabs, { SegmentedTabsProps } from "@/ui/segmented-tabs";
import Tooltip from "@/ui/tooltip";
import Image from "next/image";
import { PropsWithChildren, useEffect, useMemo, useState } from "react";
import { PropsWithChildren, useCallback, useEffect, useMemo, useState } from "react";
import { BalanceInput } from "./balance-input";
import FeeRateInput from "./fee-rate-input";
import { LnRelayerInfo } from "@/types/graphql";
import { CheckLnBridgeExistResponseData, CheckLnBridgeExistVariables, LnRelayerInfo } from "@/types/graphql";
import { getChainConfig } from "@/utils/chain";
import { useNetwork, useSwitchNetwork } from "wagmi";
import { formatBalance } from "@/utils/balance";
Expand All @@ -14,6 +14,9 @@ import { formatFeeRate, isValidFeeRate } from "@/utils/misc";
import { TransactionReceipt } from "viem";
import { Token } from "@/types/token";
import { Subscription, from } from "rxjs";
import { useApolloClient } from "@apollo/client";
import { QUERY_CHECK_LNBRIDGE_EXIST } from "@/config/gql";
import { notification } from "@/ui/notification";

type TabKey = "update" | "deposit" | "withdraw";
const Modal = dynamic(() => import("@/ui/modal"), { ssr: false });
Expand Down Expand Up @@ -69,6 +72,36 @@ export default function RelayerManageModal({ relayerInfo, isOpen, onClose, onSuc

const { chain } = useNetwork();
const { switchNetwork } = useSwitchNetwork();
const apolloClient = useApolloClient();

const isLnBridgeExist = useCallback(async () => {
if (sourceChain && targetChain && sourceToken && targetToken) {
const { data: lnbridgeData } = await apolloClient.query<
CheckLnBridgeExistResponseData,
CheckLnBridgeExistVariables
>({
query: QUERY_CHECK_LNBRIDGE_EXIST,
variables: {
fromChainId: sourceChain.id,
toChainId: targetChain.id,
fromToken: sourceToken.address,
toToken: targetToken.address,
},
fetchPolicy: "no-cache",
});

if (lnbridgeData.checkLnBridgeExist) {
return true;
}
}

notification.warn({
title: "Deposit failed",
description: `The bridge does not exist.`,
});
console.warn("[isLnBridgeExist]", sourceChain?.id, targetChain?.id, sourceToken?.address, targetToken?.address);
return false;
}, [apolloClient, sourceChain, targetChain, sourceToken, targetToken]);

useEffect(() => {
const _category = relayerInfo?.bridge;
Expand Down Expand Up @@ -204,7 +237,9 @@ export default function RelayerManageModal({ relayerInfo, isOpen, onClose, onSuc
await targetApprove(depositAmount.formatted);
} else {
setBusy(true);
receipt = await depositMargin(depositAmount.formatted);
if (await isLnBridgeExist()) {
receipt = await depositMargin(depositAmount.formatted);
}
}
} else if (bridgeCategory === "lnbridgev20-opposite") {
if (chain?.id !== sourceChain?.id) {
Expand All @@ -214,7 +249,9 @@ export default function RelayerManageModal({ relayerInfo, isOpen, onClose, onSuc
await sourceApprove(depositAmount.formatted);
} else {
setBusy(true);
receipt = await updateFeeAndMargin(depositAmount.formatted, baseFee.formatted, feeRate.formatted);
if (await isLnBridgeExist()) {
receipt = await updateFeeAndMargin(depositAmount.formatted, baseFee.formatted, feeRate.formatted);
}
}
}
} else if (activeKey === "withdraw") {
Expand Down
60 changes: 45 additions & 15 deletions packages/apps/src/components/relayer-register.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,13 @@
import Button from "@/ui/button";
import { Divider } from "@/ui/divider";
import StepNumber from "@/ui/step-number";
import { PropsWithChildren, useEffect, useState } from "react";
import { PropsWithChildren, useCallback, useEffect, useState } from "react";
import ChainSelect from "./chain-select";
import TokenSelect from "./token-select";
import { ChainConfig } from "@/types/chain";
import { ChainConfig, ChainID } from "@/types/chain";
import { Token, TokenSymbol } from "@/types/token";
import { BridgeCategory } from "@/types/bridge";
import { useAccount, useNetwork, useSwitchNetwork } from "wagmi";
import { Address, useAccount, useNetwork, useSwitchNetwork } from "wagmi";
import Image from "next/image";
import { formatFeeRate, getChainLogoSrc, getTokenLogoSrc, isValidFeeRate } from "@/utils/misc";
import Tooltip from "@/ui/tooltip";
Expand All @@ -21,8 +21,13 @@ import { getParsedCrossChain } from "@/utils/cross-chain";
import { useConnectModal } from "@rainbow-me/rainbowkit";
import { formatBalance } from "@/utils/balance";
import { useApolloClient } from "@apollo/client";
import { QUERY_SPECIAL_RELAYER } from "@/config/gql";
import { SpecialRelayerResponseData, SpecialRelayerVariables } from "@/types/graphql";
import { QUERY_CHECK_LNBRIDGE_EXIST, QUERY_SPECIAL_RELAYER } from "@/config/gql";
import {
CheckLnBridgeExistResponseData,
CheckLnBridgeExistVariables,
SpecialRelayerResponseData,
SpecialRelayerVariables,
} from "@/types/graphql";
import { notification } from "@/ui/notification";
import { useRelayer } from "@/hooks/use-relayer";
import dynamic from "next/dynamic";
Expand Down Expand Up @@ -107,6 +112,35 @@ export default function RelayerRegister() {
}
};

const isLnBridgeExist = useCallback(async () => {
if (sourceChain && targetChain && sourceToken && targetToken) {
const { data: lnbridgeData } = await apolloClient.query<
CheckLnBridgeExistResponseData,
CheckLnBridgeExistVariables
>({
query: QUERY_CHECK_LNBRIDGE_EXIST,
variables: {
fromChainId: sourceChain.id,
toChainId: targetChain.id,
fromToken: sourceToken.address,
toToken: targetToken.address,
},
fetchPolicy: "no-cache",
});

if (lnbridgeData.checkLnBridgeExist) {
return true;
}
}

notification.warn({
title: "Deposit failed",
description: `The bridge does not exist.`,
});
console.warn("[isLnBridgeExist]", sourceChain?.id, targetChain?.id, sourceToken?.address, targetToken?.address);
return false;
}, [apolloClient, sourceChain, targetChain, sourceToken, targetToken]);

useEffect(() => {
const availableCategories = new Set<BridgeCategory>();

Expand Down Expand Up @@ -219,6 +253,10 @@ export default function RelayerRegister() {
setSourceChain(undefined);
setTargetChain(undefined);
setSourceToken(undefined);
setBridgeCategory(undefined);
setMargin({ formatted: 0n, value: "" });
setBaseFee({ formatted: 0n, value: "" });
setFeeRate({ formatted: 0, value: "" });
setCurrentStep(Step.ONE);
setCompleteMargin(false);
}}
Expand Down Expand Up @@ -270,10 +308,6 @@ export default function RelayerRegister() {
} else if (targetToken?.type !== "native" && margin.formatted > (targetAllowance?.value || 0n)) {
try {
setIsSettingDefaultMargin(true);
if (await isRegistered()) {
setIsSettingDefaultMargin(false);
return;
}
await targetApprove(margin.formatted);
} catch (err) {
console.error(err);
Expand All @@ -283,7 +317,7 @@ export default function RelayerRegister() {
} else {
try {
setIsSettingDefaultMargin(true);
if (await isRegistered()) {
if ((await isRegistered()) || !(await isLnBridgeExist())) {
setIsSettingDefaultMargin(false);
return;
}
Expand Down Expand Up @@ -340,10 +374,6 @@ export default function RelayerRegister() {
) {
try {
setBusy(true);
if (await isRegistered()) {
setBusy(false);
return;
}
await sourceApprove(margin.formatted);
} catch (err) {
console.error(err);
Expand All @@ -353,7 +383,7 @@ export default function RelayerRegister() {
} else {
try {
setBusy(true);
if (await isRegistered()) {
if ((await isRegistered()) || !(await isLnBridgeExist())) {
setBusy(false);
return;
}
Expand Down
12 changes: 12 additions & 0 deletions packages/apps/src/config/chains/arbitrum.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,5 +60,17 @@ export const arbitrumChain: ChainConfig = {
{ target: { network: "bsc", symbol: "USDT" }, bridge: { category: "lnbridgev20-default" } },
],
},
{
decimals: 6,
symbol: "USDC",
name: "USDC",
type: "erc20",
address: "0xFF970A61A04b1cA14834A43f5dE4533eBDDB5CC8",
logo: "usdc.svg",
cross: [
{ target: { network: "mantle", symbol: "USDC" }, bridge: { category: "lnbridgev20-default" } },
{ target: { network: "scroll", symbol: "USDC" }, bridge: { category: "lnbridgev20-default" } },
],
},
],
};
12 changes: 12 additions & 0 deletions packages/apps/src/config/chains/mantle.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,5 +49,17 @@ export const mantleChain: ChainConfig = {
{ target: { network: "scroll", symbol: "USDT" }, bridge: { category: "lnbridgev20-default" } },
],
},
{
decimals: 6,
symbol: "USDC",
name: "USDC",
type: "erc20",
address: "0x09Bc4E0D864854c6aFB6eB9A9cdF58aC190D0dF9",
logo: "usdc.svg",
cross: [
{ target: { network: "arbitrum", symbol: "USDC" }, bridge: { category: "lnbridgev20-default" } },
{ target: { network: "scroll", symbol: "USDC" }, bridge: { category: "lnbridgev20-default" } },
],
},
],
};
12 changes: 12 additions & 0 deletions packages/apps/src/config/chains/scroll.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,5 +48,17 @@ export const scrollChain: ChainConfig = {
{ target: { network: "zksync", symbol: "USDT" }, bridge: { category: "lnbridgev20-default" } },
],
},
{
decimals: 6,
symbol: "USDC",
name: "USDC",
type: "erc20",
address: "0x06eFdBFf2a14a7c8E15944D1F4A48F9F95F663A4",
logo: "usdc.svg",
cross: [
{ target: { network: "mantle", symbol: "USDC" }, bridge: { category: "lnbridgev20-default" } },
{ target: { network: "arbitrum", symbol: "USDC" }, bridge: { category: "lnbridgev20-default" } },
],
},
],
};
9 changes: 9 additions & 0 deletions packages/apps/src/config/chains/zksync.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,5 +49,14 @@ export const zksyncChain: ChainConfig = {
{ target: { network: "scroll", symbol: "USDT" }, bridge: { category: "lnbridgev20-default" } },
],
},
{
decimals: 6,
symbol: "USDC",
name: "USDC",
type: "erc20",
address: "0x3355df6D4c9C3035724Fd0e3914dE96A5a83aaf4",
logo: "usdc.svg",
cross: [],
},
],
};
6 changes: 6 additions & 0 deletions packages/apps/src/config/gql.ts
Original file line number Diff line number Diff line change
Expand Up @@ -155,3 +155,9 @@ export const QUERY_TX_PROGRESS = gql`
}
}
`;

export const QUERY_CHECK_LNBRIDGE_EXIST = gql`
query checkLnBridgeExist($fromChainId: Int, $toChainId: Int, $fromToken: String, $toToken: String) {
checkLnBridgeExist(fromChainId: $fromChainId, toChainId: $toChainId, fromToken: $fromToken, toToken: $toToken)
}
`;
8 changes: 4 additions & 4 deletions packages/apps/src/providers/relayer-provider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,7 @@ export default function RelayerProvider({ children }: PropsWithChildren<unknown>
if (address && bridgeClient) {
try {
const receipt = await bridgeClient.targetApprove(amount, address);
notifyTransaction(receipt, sourceChain);
notifyTransaction(receipt, targetChain);

setTargetAllowance(await bridgeClient.getTargetAllowance(address));

Expand All @@ -175,15 +175,15 @@ export default function RelayerProvider({ children }: PropsWithChildren<unknown>
}
}
},
[address, bridgeClient, sourceChain],
[address, bridgeClient, targetChain],
);

const depositMargin = useCallback(
async (margin: bigint) => {
if (address && defaultBridge) {
try {
const receipt = await defaultBridge.depositMargin(margin);
notifyTransaction(receipt, sourceChain);
notifyTransaction(receipt, targetChain);

const a = await defaultBridge.getTargetAllowance(address);
const b = await defaultBridge.getTargetBalance(address);
Expand All @@ -197,7 +197,7 @@ export default function RelayerProvider({ children }: PropsWithChildren<unknown>
}
}
},
[address, defaultBridge, sourceChain],
[address, defaultBridge, targetChain],
);

const setFeeAndRate = useCallback(
Expand Down
13 changes: 12 additions & 1 deletion packages/apps/src/types/graphql.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { TokenSymbol } from "./token";
import { BridgeCategory } from "./bridge";
import { Network } from "./chain";
import { ChainID, Network } from "./chain";
import { Address } from "viem";

export enum RecordStatus {
Expand Down Expand Up @@ -165,3 +165,14 @@ export interface TxProgressResponseData {
export interface TxProgressVariables {
txHash: string;
}

export interface CheckLnBridgeExistResponseData {
checkLnBridgeExist: boolean | null;
}

export interface CheckLnBridgeExistVariables {
fromChainId: ChainID;
toChainId: ChainID;
fromToken: Address;
toToken: Address;
}

0 comments on commit cc7817e

Please sign in to comment.