Skip to content

Commit

Permalink
Msgline margin withdraw
Browse files Browse the repository at this point in the history
  • Loading branch information
JayJay1024 committed Dec 25, 2023
1 parent 25c293f commit 80dc781
Show file tree
Hide file tree
Showing 6 changed files with 112 additions and 12 deletions.
63 changes: 60 additions & 3 deletions src/bridges/lnbridge-default.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import { Address, TransactionReceipt, bytesToHex } from "viem";
import { Address, TransactionReceipt, bytesToHex, encodeFunctionData } from "viem";
import { LnBridgeBase } from "./lnbridge-base";
import { ChainID } from "@/types/chain";
import { isProduction } from "@/utils/env";
import { BridgeConstructorArgs, TransferOptions } from "@/types/bridge";
import { BridgeConstructorArgs, GetWithdrawFeeArgs, TransferOptions } from "@/types/bridge";
import { fetchMsglineFeeAndParams } from "@/utils";

export class LnBridgeDefault extends LnBridgeBase {
constructor(args: BridgeConstructorArgs) {
Expand Down Expand Up @@ -145,7 +146,7 @@ export class LnBridgeDefault extends LnBridgeBase {
}
}

async getWithdrawFee() {
private async _getLayerzeroWithdrawFee(_args: GetWithdrawFeeArgs) {
if (this.contract && this.sourceNativeToken && this.targetChain && this.sourcePublicClient) {
const bridgeAbi = (await import(`../abi/lnbridgev20-default`)).default;
const accessAbi = (await import(`../abi/lnaccess-controller`)).default;
Expand All @@ -168,6 +169,62 @@ export class LnBridgeDefault extends LnBridgeBase {
}
}

private async _getMsglineWithdrawFee(args: GetWithdrawFeeArgs) {
const sourceMessager = this.sourceChain?.messager?.msgline;
const targetMessager = this.targetChain?.messager?.msgline;

if (
sourceMessager &&
targetMessager &&
this.sourceNativeToken &&
this.sourceToken &&
this.targetToken &&
args.transferId &&
args.withdrawNonce &&
args.sender &&
args.relayer
) {
const message = encodeFunctionData({
abi: (await import(`../abi/lnbridgev20-default`)).default,
functionName: "withdraw",
args: [
BigInt(this.sourceChain.id),
args.transferId,
BigInt(args.withdrawNonce),
args.relayer,
this.sourceToken.address,
this.targetToken.address,
args.amount,
],
});

const payload = encodeFunctionData({
abi: (await import("@/abi/msgline-messager")).default,
functionName: "receiveMessage",
args: [BigInt(this.sourceChain.id), sourceMessager, targetMessager, message],
});

const feeAndParams = await fetchMsglineFeeAndParams(
this.sourceChain.id,
this.targetChain.id,
sourceMessager,
targetMessager,
args.sender,
payload,
);

return feeAndParams && { value: feeAndParams.fee, token: this.sourceNativeToken };
}
}

async getWithdrawFee(args: GetWithdrawFeeArgs) {
if (args.messageChannel === "layerzero") {
return this._getLayerzeroWithdrawFee(args);
} else if (args.messageChannel === "msgline") {
return this._getMsglineWithdrawFee(args);
}
}

async withdrawMargin(recipient: Address, amount: bigint, fee: bigint) {
await this.validateNetwork("source");

Expand Down
31 changes: 23 additions & 8 deletions src/components/modals/relayer-manage-modal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import SegmentedTabs, { SegmentedTabsProps } from "@/ui/segmented-tabs";
import { formatBalance, formatFeeRate, getChainConfig, notifyError } from "@/utils";
import { useApolloClient } from "@apollo/client";
import dynamic from "next/dynamic";
import { PropsWithChildren, useEffect, useMemo, useState } from "react";
import { PropsWithChildren, useDeferredValue, useEffect, useMemo, useState } from "react";
import { useAccount, useNetwork, useSwitchNetwork } from "wagmi";
import { Subscription, from } from "rxjs";
import { TransactionReceipt } from "viem";
Expand Down Expand Up @@ -40,6 +40,7 @@ export default function RelayerManageModal({ relayerInfo, isOpen, onClose, onSuc
margin,
baseFee,
feeRate,
withdrawAmount,
setMargin,
setBaseFee,
setFeeRate,
Expand All @@ -48,6 +49,7 @@ export default function RelayerManageModal({ relayerInfo, isOpen, onClose, onSuc
setSourceToken,
setBridgeCategory,
setFeeAndRate,
setWithdrawAmount,
depositMargin,
updateFeeAndMargin,
withdrawMargin,
Expand All @@ -59,11 +61,10 @@ export default function RelayerManageModal({ relayerInfo, isOpen, onClose, onSuc
const [height, setHeight] = useState<number>();
const [busy, setBusy] = useState(false);
const [withdrawFee, setWithdrawFee] = useState<{ value: bigint; token: Token }>();

const [depositAmount, setDepositAmount] = useState<InputValue<bigint>>({ input: "", valid: true, value: 0n });
const [withdrawAmount, setWithdrawAmount] = useState<InputValue<bigint>>({ input: "", valid: true, value: 0n });
const [baseFeeInput, setBaseFeeInput] = useState<InputValue<bigint>>({ input: "", valid: true, value: 0n });
const [feeRateInput, setFeeRateInput] = useState<InputValue<number>>({ input: "", valid: true, value: 0 });
const deferredWithdrawAmount = useDeferredValue(withdrawAmount);

const { switchNetwork } = useSwitchNetwork();
const { chain } = useNetwork();
Expand Down Expand Up @@ -157,12 +158,22 @@ export default function RelayerManageModal({ relayerInfo, isOpen, onClose, onSuc
setSourceChain,
setTargetChain,
setSourceToken,
setWithdrawAmount,
]);

useEffect(() => {
let sub$$: Subscription | undefined;
if (defaultBridge && relayerInfo?.messageChannel === "layerzero") {
sub$$ = from(defaultBridge.getWithdrawFee()).subscribe({
if (defaultBridge && (relayerInfo?.messageChannel === "layerzero" || relayerInfo?.messageChannel === "msgline")) {
sub$$ = from(
defaultBridge.getWithdrawFee({
amount: deferredWithdrawAmount.value,
sender: address,
relayer: relayerInfo.relayer,
transferId: relayerInfo.lastTransferId,
withdrawNonce: relayerInfo.withdrawNonce,
messageChannel: relayerInfo.messageChannel,
}),
).subscribe({
next: setWithdrawFee,
error: (err) => {
console.error(err);
Expand All @@ -173,7 +184,7 @@ export default function RelayerManageModal({ relayerInfo, isOpen, onClose, onSuc
setWithdrawFee(undefined);
}
return () => sub$$?.unsubscribe();
}, [defaultBridge, relayerInfo]);
}, [defaultBridge, relayerInfo, address, deferredWithdrawAmount]);

return (
<Modal
Expand Down Expand Up @@ -267,7 +278,11 @@ export default function RelayerManageModal({ relayerInfo, isOpen, onClose, onSuc
extra={
activeKey === "withdraw" ? (
<div className="h-6 self-end">
<span className="text-sm font-extrabold text-white/50">Powered by LayerZero & Helix</span>
<span className="text-sm font-extrabold text-white/50">
{relayerInfo?.messageChannel === "layerzero"
? "Powered by LayerZero & Helix"
: "Powered by Msgport & Helix"}
</span>
</div>
) : (
<div className="h-6" />
Expand Down Expand Up @@ -388,7 +403,7 @@ export default function RelayerManageModal({ relayerInfo, isOpen, onClose, onSuc
</LabelSection>
</div>
),
disabled: relayerInfo?.messageChannel !== "layerzero",
disabled: !(relayerInfo?.messageChannel === "layerzero" || relayerInfo?.messageChannel === "msgline"),
},
]}
activeKey={activeKey}
Expand Down
2 changes: 2 additions & 0 deletions src/config/gql.ts
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,8 @@ export const GQL_QUERY_LNV20_RELAY_INFOS = gql`
profit
heartbeatTimestamp
messageChannel
lastTransferId
withdrawNonce
}
}
}
Expand Down
16 changes: 15 additions & 1 deletion src/providers/relayer-provider.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,14 @@
"use client";

import { BaseBridge, LnBridgeDefault, LnBridgeOpposite } from "@/bridges";
import { BridgeCategory, ChainConfig, CheckLnBridgeExistReqParams, CheckLnBridgeExistResData, Token } from "@/types";
import {
BridgeCategory,
ChainConfig,
CheckLnBridgeExistReqParams,
CheckLnBridgeExistResData,
InputValue,
Token,
} from "@/types";
import { getAvailableTargetTokens, notifyError, notifyTransaction } from "@/utils";
import {
Dispatch,
Expand Down Expand Up @@ -34,6 +41,7 @@ interface RelayerCtx {
bridgeCategory: BridgeCategory | undefined;
defaultBridge: LnBridgeDefault | undefined;
oppositeBridge: LnBridgeOpposite | undefined;
withdrawAmount: InputValue<bigint>;

setMargin: Dispatch<SetStateAction<bigint | undefined>>;
setBaseFee: Dispatch<SetStateAction<bigint | undefined>>;
Expand All @@ -46,6 +54,7 @@ interface RelayerCtx {
setTargetChain: Dispatch<SetStateAction<ChainConfig | undefined>>;
setSourceToken: Dispatch<SetStateAction<Token | undefined>>;
setBridgeCategory: Dispatch<SetStateAction<BridgeCategory | undefined>>;
setWithdrawAmount: Dispatch<SetStateAction<InputValue<bigint>>>;

sourceApprove: (
owner: Address,
Expand Down Expand Up @@ -110,6 +119,7 @@ const defaultValue: RelayerCtx = {
bridgeCategory: undefined,
defaultBridge: undefined,
oppositeBridge: undefined,
withdrawAmount: { input: "", valid: true, value: 0n },

setMargin: () => undefined,
setBaseFee: () => undefined,
Expand All @@ -122,6 +132,7 @@ const defaultValue: RelayerCtx = {
setTargetChain: () => undefined,
setSourceToken: () => undefined,
setBridgeCategory: () => undefined,
setWithdrawAmount: () => undefined,

sourceApprove: async () => undefined,
targetApprove: async () => undefined,
Expand All @@ -146,6 +157,7 @@ export default function RelayerProvider({ children }: PropsWithChildren<unknown>
const [targetChain, setTargetChain] = useState(defaultValue.targetChain);
const [sourceToken, setSourceToken] = useState(defaultValue.sourceToken);
const [bridgeCategory, setBridgeCategory] = useState(defaultValue.bridgeCategory);
const [withdrawAmount, setWithdrawAmount] = useState(defaultValue.withdrawAmount);

const { data: walletClient } = useWalletClient();
const publicClient = usePublicClient();
Expand Down Expand Up @@ -363,6 +375,7 @@ export default function RelayerProvider({ children }: PropsWithChildren<unknown>
bridgeCategory,
defaultBridge,
oppositeBridge,
withdrawAmount,

setMargin,
setBaseFee,
Expand All @@ -375,6 +388,7 @@ export default function RelayerProvider({ children }: PropsWithChildren<unknown>
setTargetChain,
setSourceToken,
setBridgeCategory,
setWithdrawAmount,

sourceApprove,
targetApprove,
Expand Down
10 changes: 10 additions & 0 deletions src/types/bridge.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { Address, Hex } from "viem";
import { PublicClient, WalletClient } from "wagmi";
import { ChainConfig } from "./chain";
import { Token } from "./token";
import { MessageChannel } from ".";

/**
* lpbridge-darwinia-dvm etc. are named from graphql indexer.
Expand Down Expand Up @@ -60,3 +61,12 @@ export interface TransferOptions {
withdrawNonce?: bigint;
depositedMargin?: bigint;
}

export interface GetWithdrawFeeArgs {
amount: bigint;
sender?: Address;
relayer?: Address;
transferId?: Hex | null;
withdrawNonce?: string | null;
messageChannel?: MessageChannel | null;
}
2 changes: 2 additions & 0 deletions src/types/graphql.ts
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,8 @@ export type Lnv20RelayerOverview = Pick<
| "profit"
| "heartbeatTimestamp"
| "messageChannel"
| "lastTransferId"
| "withdrawNonce"
>;

export interface QueryLnV20RelayInfosReqParams {
Expand Down

0 comments on commit 80dc781

Please sign in to comment.