Skip to content

Commit

Permalink
add: bridge history without self-relay
Browse files Browse the repository at this point in the history
  • Loading branch information
L03TJ3 committed Jul 8, 2024
1 parent 767ed00 commit f464dda
Show file tree
Hide file tree
Showing 4 changed files with 308 additions and 94 deletions.
2 changes: 1 addition & 1 deletion packages/good-design/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
"@babel/preset-react": "^7.16.0",
"@babel/preset-typescript": "^7.16.0",
"@babel/runtime": "^7.18.9",
"@gooddollar/web3sdk-v2": "0.2.23-beta.7607fd2",
"@gooddollar/web3sdk-v2": "file:.yalc/@gooddollar/web3sdk-v2",
"@storybook/addon-actions": "^6.5.12",
"@storybook/addon-essentials": "^6.5.12",
"@storybook/addon-links": "^6.5.12",
Expand Down
145 changes: 142 additions & 3 deletions packages/good-design/src/apps/bridge/MicroBridgeController.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import React, { FC, useCallback, useState } from "react";

import {
G$Amount,
SupportedChains,
useBridge,
useBridgeHistory,
Expand All @@ -10,11 +11,30 @@ import {
useWithinBridgeLimits
} from "@gooddollar/web3sdk-v2";

import moment from "moment";
import { ethers } from "ethers";

import { useEthers } from "@usedapp/core";
import { noop, sortBy } from "lodash";
import { ArrowForwardIcon, Box, Button, Flex, Heading, HStack, Spinner, Stack, Text } from "native-base";
import {
ArrowForwardIcon,
Box,
Button,
FlatList,
Flex,
Heading,
HStack,
Skeleton,
Spinner,
Stack,
VStack,
Text
} from "native-base";

import { GdAmount, Title } from "../../core/layout";
import { ExplorerLink } from "../../core/web3/ExplorerLink";
import { BridgeWizard } from "./wizard/BridgeWizard";
import { truncateMiddle } from "../../utils";

const useCanBridge = (chain: "fuse" | "celo", amountWei: string) => {
const { chainId } = useGetEnvChainId(chain === "fuse" ? SupportedChains.FUSE : SupportedChains.CELO);
Expand All @@ -24,7 +44,7 @@ const useCanBridge = (chain: "fuse" | "celo", amountWei: string) => {
return canBridge;
};

const MicroBridgeHistory = () => {
const BridgeHistoryWithRelay = () => {
const { fuseHistory, celoHistory } = useBridgeHistory();

const historySorted = sortBy((fuseHistory || []).concat(celoHistory || []), _ => _.data.from === "account");
Expand Down Expand Up @@ -132,20 +152,138 @@ const MicroBridgeHistory = () => {
);
};

const HistoryRowItem = ({ item, env }: any) => {
const { amount, data, relayEvent, transactionHash } = item;
const { targetChainId, timestamp } = data || {};

const { fee } = relayEvent?.data || {};

const date = moment(ethers.BigNumber.from(timestamp).toNumber() * 1000).utc();
const dateFormatted = date.format("DD.MM.YY");
const dateHours = date.format("HH:mm");

const targetChain = parseInt(targetChainId);
const sourceChain = targetChain === 122 ? 42220 : 122;
const test = 12223;

const feeFormatted = fee && targetChain ? G$Amount("G$", ethers.BigNumber.from(fee), targetChain, env) : null;

return (
<HStack marginTop="3" space="35" flex="1 1 100%">
<VStack>
<Text variant="xs-grey">{dateFormatted}</Text>
<Text variant="xs-grey">{dateHours}</Text>
</VStack>
<VStack flex="0 0 15%" alignItems="flex-start">
<Text variant="xs-grey">G$ {amount}</Text>
{feeFormatted ? (
<HStack>
<Text variant="xs-grey" fontWeight="700">
Fees:{" "}
</Text>
<Text variant="xs-grey">{`G$ `}</Text>
<GdAmount variant="xs-grey" fontFamily="subheading" withDefaultSuffix={false} amount={feeFormatted} />
</HStack>
) : (
<Skeleton size="3" rounded="full" width="75%" />
)}
</VStack>
<VStack flex="2 2 25%" alignItems="flex-start">
{relayEvent?.transactionHash && targetChain && test === 12223 ? (
<>
<Text variant="xs-green">Completed</Text>
<HStack space="2" alignItems="center">
<Text variant="xs-grey">{`(Received on ${SupportedChains[targetChain]})`}</Text>
<ExplorerLink
fontSize="xs"
chainId={targetChain}
addressOrTx={relayEvent.transactionHash}
text={truncateMiddle(relayEvent.transactionHash, 11)}
withIcon={false}
/>
</HStack>
</>
) : (
<>
<HStack space="2">
<Spinner variant="page-loader" size="sm" />
<Text variant="xs-grey">{`Waiting for bridge relayers to relay to target chain... \n (Can take a few minutes)`}</Text>
</HStack>
<HStack space="2" alignItems="center">
<Text variant="xs-grey">{`(Send on ${SupportedChains[sourceChain]})`}</Text>
<ExplorerLink
fontSize="xs"
chainId={sourceChain}
addressOrTx={transactionHash}
text={truncateMiddle(transactionHash, 11)}
withIcon={false}
/>
</HStack>
</>
)}
</VStack>
</HStack>
);
};

const BridgeHistory = ({ env }: { env: any }) => {
const { historySorted } = useBridgeHistory();

return (
<VStack>
<Title variant="Title-gdbue" py="6" width="100%">
Recent Transactions
</Title>
<VStack space="2">
<HStack borderBottomWidth="1" borderBottomColor="goodGrey.300:alpha.70">
<Text flex="0 0 11%" variant="sm-grey-600" fontWeight="700">
Date
</Text>
<Text flex="1 1 12%" variant="sm-grey-600" fontWeight="700">
Amount
</Text>
<Text flex="2 2 55%" variant="sm-grey-600" fontWeight="700">
Status
</Text>
</HStack>
{historySorted.length === 0 ? (
<Spinner variant="page-loader" size="lg" />
) : (
<FlatList
shadow="1"
_contentContainerStyle={{
flexDirection: "column",
width: "100%"
}}
data={historySorted}
renderItem={({ item }) => <HistoryRowItem item={item} env={env} />}
maxH="250"
scrollEnabled={true}
horizontal={false}
/>
)}
</VStack>
</VStack>
);
};

interface IMicroBridgeControllerProps {
withRelay?: boolean;
withHistory?: boolean;
onBridgeStart?: () => void;
onBridgeSuccess?: () => void;
onBridgeFailed?: (e: Error) => void;
}

export const MicroBridgeController: FC<IMicroBridgeControllerProps> = ({
withRelay = false,
withHistory = true,
// onBridgeStart = noop,
onBridgeSuccess = noop,
onBridgeFailed = noop
}: IMicroBridgeControllerProps) => {
const { chainId } = useEthers();
const { defaultEnv } = useGetEnvChainId();
const { sendBridgeRequest, bridgeRequestStatus, relayStatus, selfRelayStatus } = useBridge();
const { bridgeFees: fuseBridgeFees, bridgeLimits: fuseBridgeLimits } = useGetBridgeData(SupportedChains.FUSE, "");
const { bridgeFees: celoBridgeFees, bridgeLimits: celoBridgeLimits } = useGetBridgeData(SupportedChains.CELO, "");
Expand Down Expand Up @@ -182,7 +320,8 @@ export const MicroBridgeController: FC<IMicroBridgeControllerProps> = ({
inputTransaction={inputTransaction}
pendingTransaction={pendingTransaction}
/>
{withRelay && <MicroBridgeHistory />}
{withRelay && <BridgeHistoryWithRelay />}
{withHistory && <BridgeHistory env={defaultEnv} />}
</>
);
};
100 changes: 61 additions & 39 deletions packages/good-design/src/apps/bridge/MicroBridgeStatus.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
import React from "react";
import {
Box,
CheckIcon,
CloseIcon,
Flex,
Popover,
HStack,
Stack,
Box,
IconButton,
InfoOutlineIcon,
Popover,
Stack,
Spinner,
Text,
VStack
Expand Down Expand Up @@ -94,7 +94,7 @@ const StatusHeader = ({
relayStatus: MicroBridgeProps["relayStatus"];
}) => {
const [sendCopy, receiveCopy] =
relayStatus?.status === "Success" ? ["You Bridged", "You've Received"] : ["You're Bridging", "You'll Receive"];
relayStatus?.status === "Success" ? ["You Bridged", "You've Received"] : ["You Have Bridged", "You Will Receive"];

return (
<>
Expand All @@ -119,6 +119,11 @@ const StatusHeader = ({
/>
</HStack>

<HStack justifyContent="space-between">
<Text variant="sm-grey-700">{"Fees"}</Text>
<GdAmount amount={fee} withDefaultSuffix={false} options={{ prefix: `G$ ` }} variant="md-grey-700" />
</HStack>

{relayStatus?.status === "Success" ? (
<HStack justifyContent="space-between">
<Text variant="sm-grey-700">{"Fees"}</Text>
Expand All @@ -141,18 +146,62 @@ const StatusHeader = ({
);
};

export const MicroBridgeStatus = ({
export const SingleTxStatus = ({
bridgeStatus,
sourceChain,
selfRelayStatus,
relayStatus,
handleFinish
}: {
bridgeStatus: any;
sourceChain: any;
selfRelayStatus: any;
relayStatus: any;
handleFinish: any;
}) => (
<VStack>
<VStack>
{bridgeStatus && bridgeStatus?.status != "None" && (
<Box p={2} borderWidth="1" borderColor="primary" rounded="lg" bgColor="white">
<StatusBox text="Sending funds to bridge" txStatus={bridgeStatus} sourceChain={sourceChain} />

{bridgeStatus?.status === "Success" && selfRelayStatus && (
<StatusBox
text="Self relaying to target chain... (Can take a few minutes)"
infoText="If you have enough native tokens on the target chain, you will execute the transfer on the target chain yourself and save some bridge fees"
txStatus={selfRelayStatus}
sourceChain={sourceChain}
/>
)}
{bridgeStatus?.status === "Success" && (
<StatusBox
text="Waiting for bridge relayers to relay to target chain... (Can take a few minutes)"
infoText="If you don't have enough native tokens on the target chain, a bridge relay service will execute the transfer for a small G$ fee"
txStatus={relayStatus}
sourceChain={sourceChain}
/>
)}
</Box>
)}
</VStack>
{relayStatus?.status === "Success" ? (
<>
<BridgeSuccessModal open={relayStatus.status === "Success"} />
<GoodButton onPress={handleFinish}>Done</GoodButton>
</>
) : null}
</VStack>
);

export const MicroBridgeStatus = ({
originChain,
pendingTransaction,
relayStatus,
selfRelayStatus
relayStatus
}: {
bridgeStatus: MicroBridgeProps["bridgeStatus"];
originChain: MicroBridgeProps["originChain"];
pendingTransaction: MicroBridgeProps["pendingTransaction"];
relayStatus: MicroBridgeProps["relayStatus"];
selfRelayStatus: MicroBridgeProps["selfRelayStatus"];
}) => {
const [pendingTx] = pendingTransaction;
const [sourceChain] = originChain;
Expand All @@ -171,7 +220,9 @@ export const MicroBridgeStatus = ({
<VStack p={4} space={4} width="100%" bgColor="goodWhite.100">
{relayStatus?.status === "Success" ? (
<Title variant="title-gdblue">{`Congratulations! Your bridging \n transaction has been successfully \n completed.`}</Title>
) : null}
) : (
<Title variant="title-gdblue">{`Congratulations! Your bridging \n transaction is being processed.`}</Title>
)}
<StatusHeader
{...{
sendAmount,
Expand All @@ -182,36 +233,7 @@ export const MicroBridgeStatus = ({
relayStatus
}}
/>
<VStack>
{bridgeStatus && bridgeStatus?.status != "None" && (
<Box p={2} borderWidth="1" borderColor="primary" rounded="lg" bgColor="white">
<StatusBox text="Sending funds to bridge" txStatus={bridgeStatus} sourceChain={sourceChain} />

{bridgeStatus?.status === "Success" && selfRelayStatus && (
<StatusBox
text="Self relaying to target chain... (Can take a few minutes)"
infoText="If you have enough native tokens on the target chain, you will execute the transfer on the target chain yourself and save some bridge fees"
txStatus={selfRelayStatus}
sourceChain={sourceChain}
/>
)}
{bridgeStatus?.status === "Success" && (
<StatusBox
text="Waiting for bridge relayers to relay to target chain... (Can take a few minutes)"
infoText="If you don't have enough native tokens on the target chain, a bridge relay service will execute the transfer for a small G$ fee"
txStatus={relayStatus}
sourceChain={sourceChain}
/>
)}
</Box>
)}
</VStack>
{relayStatus?.status === "Success" ? (
<>
<BridgeSuccessModal open={relayStatus.status === "Success"} />
<GoodButton onPress={handleFinish}>Done</GoodButton>
</>
) : null}
<GoodButton onPress={handleFinish}>Done</GoodButton>
</VStack>
);
};
Loading

0 comments on commit f464dda

Please sign in to comment.