Skip to content

Commit

Permalink
Add confirming state to the Bridge (#151)
Browse files Browse the repository at this point in the history
* Reduce the space between `value` and `symbol`

* Add `selectMap`

* Update progress title during deposit confirming state

* Update progress status for withdraw confirming state

* Allow mix casing in Progress title
  • Loading branch information
ken-futureverse authored Mar 31, 2022
1 parent 369cb39 commit b350cf7
Show file tree
Hide file tree
Showing 8 changed files with 87 additions and 25 deletions.
6 changes: 5 additions & 1 deletion components/BridgeForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,8 @@ const BridgeForm: FC<IntrinsicElements["form"] & BridgeFormProps> = ({
metaMaskWallet.getSigner()
);

if (tx !== "cancelled") await ensureRelayerDepositDone(tx.hash);
if (tx !== "cancelled")
await ensureRelayerDepositDone(tx.hash, 600000, setProgressStatus);
} catch (error) {
console.info(error);
return setFailStatus(error?.code);
Expand Down Expand Up @@ -114,6 +115,7 @@ const BridgeForm: FC<IntrinsicElements["form"] & BridgeFormProps> = ({
try {
await ensureEthereumChain(extension);
await ensureBridgeWithdrawActive(api, metaMaskWallet);
setProgressStatus("CennznetConfirming");
eventProof = await sendWithdrawCENNZRequest(
api,
transferAmount,
Expand All @@ -131,6 +133,7 @@ const BridgeForm: FC<IntrinsicElements["form"] & BridgeFormProps> = ({

let tx: Awaited<ReturnType<typeof sendWithdrawEthereumRequest>>;
try {
setProgressStatus("EthereumConfirming");
tx = await sendWithdrawEthereumRequest(
api,
eventProof,
Expand Down Expand Up @@ -182,6 +185,7 @@ const BridgeForm: FC<IntrinsicElements["form"] & BridgeFormProps> = ({

let tx: Awaited<ReturnType<typeof sendWithdrawEthereumRequest>>;
try {
setProgressStatus("EthereumConfirming");
tx = await sendWithdrawEthereumRequest(
api,
eventProof,
Expand Down
9 changes: 9 additions & 0 deletions components/BridgeProgress.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,10 @@ const styles = {
text-align: center;
text-transform: uppercase;
color: ${palette.primary.main};
span {
text-transform: none !important;
}
`,

message: ({ palette }: Theme) => css`
Expand All @@ -114,6 +118,11 @@ const styles = {
font-weight: bold;
font-style: normal;
color: ${palette.primary.main};
font-size: 0.5em;
span {
font-size: 2em;
letter-spacing: -0.025em;
}
}
`,

Expand Down
27 changes: 21 additions & 6 deletions providers/BridgeProvider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,10 @@ import {
BridgeAction,
BridgedEthereumToken,
EthereumToken,
RelayerConfirmingStatus,
TxStatus,
} from "@/types";
import { Balance } from "@/utils";
import { Balance, selectMap } from "@/utils";
import {
createContext,
Dispatch,
Expand Down Expand Up @@ -42,7 +43,7 @@ interface BridgeContextType {
txStatus: TxStatus;
setTxStatus: Dispatch<SetStateAction<TxStatus>>;

setProgressStatus: () => void;
setProgressStatus: (status?: RelayerConfirmingStatus) => void;
setSuccessStatus: () => void;
setFailStatus: (errorCode?: string) => void;

Expand Down Expand Up @@ -91,10 +92,24 @@ const BridgeProvider: FC<BridgeProviderProps> = ({

const [txStatus, setTxStatus] = useState<TxStatus>(null);

const setProgressStatus = useCallback(() => {
const setProgressStatus = useCallback((status?: RelayerConfirmingStatus) => {
const title = selectMap<RelayerConfirmingStatus, TxStatus["title"]>(
status,
new Map([
["EthereumConfirming", <>Confirming on Ethereum</>],
[
"CennznetConfirming",
<>
Confirming on CENNZ<span>net</span>
</>,
],
]),
"Transaction In Progress"
);

setTxStatus({
status: "in-progress",
title: "Transaction In Progress",
title,
message: (
<div>
Please sign the transaction when prompted and wait until it&apos;s
Expand Down Expand Up @@ -137,7 +152,7 @@ const BridgeProvider: FC<BridgeProviderProps> = ({
You successfully withdrew{" "}
<pre>
<em>
{trValue} {trSymbol}
<span>{trValue}</span> <span>{trSymbol}</span>
</em>
</pre>{" "}
from CENNZnet.
Expand All @@ -151,7 +166,7 @@ const BridgeProvider: FC<BridgeProviderProps> = ({
You successfully deposited{" "}
<pre>
<em>
{trValue} {trSymbol}
<span>{trValue}</span> <span>{trSymbol}</span>
</em>
</pre>{" "}
to CENNZnet.
Expand Down
14 changes: 13 additions & 1 deletion types/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,18 @@ export interface MetaMaskAccount {

export interface TxStatus {
status: "in-progress" | "success" | "fail";
title: string;
title: string | ReactElement;
message: string | ReactElement;
}

export type RelayerStatus =
| "Successful"
| "Failed"
| "Confirming"
| "EthereumConfirming"
| "CennznetConfirming";

export type RelayerConfirmingStatus = Extract<
RelayerStatus,
"EthereumConfirming" | "CennznetConfirming"
>;
29 changes: 19 additions & 10 deletions utils/ensureRelayerDepositDone.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,19 @@
import { fetchDepositRelayerStatus, waitUntil } from "@/utils";
import { RelayerStatus, RelayerConfirmingStatus } from "@/types";

type RelayerStatusReturn = Awaited<
ReturnType<typeof fetchDepositRelayerStatus>
>;
type TimoutReturn = Awaited<ReturnType<typeof waitUntil>>;

// TODO: Needs test
export default async function ensureRelayerDepositDone(
txHash: string,
timeout: number = 60000
): Promise<RelayerStatusReturn> {
const status = await waitUntilDepositDone(txHash, timeout);
timeout: number = 60000,
confirmingCallback?: (status: RelayerConfirmingStatus) => void
): Promise<RelayerStatus> {
const status = await waitUntilDepositDone(
txHash,
timeout,
confirmingCallback
);

if (status === "timeout") throw { code: "RELAYER_TIMEOUT" };
if (status === "Failed") throw { code: "RELAYER_STATUS_FAILED" };
Expand All @@ -20,16 +23,22 @@ export default async function ensureRelayerDepositDone(

export async function waitUntilDepositDone(
txHash: string,
timeout: number = 60000
): Promise<RelayerStatusReturn | TimoutReturn> {
timeout: number = 60000,
confirmingCallback?: (status: RelayerConfirmingStatus) => void
): Promise<RelayerStatus | TimoutReturn> {
let timedOut = false;

const pollDepositRelayerStatus = () => {
return new Promise<RelayerStatusReturn>((resolve, reject) => {
return new Promise<RelayerStatus>((resolve, reject) => {
const intervalId = setInterval(() => {
fetchDepositRelayerStatus(txHash)
.then((status) => {
if (!timedOut && status === "Confirming") return;
if (
!timedOut &&
(status === "EthereumConfirming" ||
status === "CennznetConfirming")
)
return confirmingCallback?.(status);
clearInterval(intervalId);
resolve(status);
})
Expand Down
10 changes: 3 additions & 7 deletions utils/fetchDepositRelayerStatus.ts
Original file line number Diff line number Diff line change
@@ -1,20 +1,16 @@
import { BRIDGE_RELAYER_URL } from "@/constants";

type RelayerStatus = "Successful" | "Failed" | "Confirming";
import { RelayerStatus } from "@/types";

// TODO: Needs test
export default async function fetchDepositRelayerStatus(
txHash: string
): Promise<RelayerStatus> {
const response = await fetch(
const relayerResponse = await fetch(
`${BRIDGE_RELAYER_URL}/transactions/${txHash}`
).then((response) => {
if (response.status !== 200) throw { code: `RELAYER_${response.status}` };
return response.json();
});

if (response.status === "Successful" || response.status === "Failed")
return response.status;

return "Confirming";
return relayerResponse.status;
}
1 change: 1 addition & 0 deletions utils/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,3 +37,4 @@ export { default as ensureRelayerDepositDone } from "@/utils/ensureRelayerDeposi
export { default as sendWithdrawEthereumRequest } from "@/utils/sendWithdrawEthereumRequest";
export { default as trackPageView } from "@/utils/trackPageView";
export { default as getSellAssetExtrinsic } from "@/utils/getSellAssetExtrinsic";
export { default as selectMap } from "@/utils/selectMap";
16 changes: 16 additions & 0 deletions utils/selectMap.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
/**
* A utility that return value by key from a map
*
* @param {K} key
* @param {Map<K, V>} map
* @param {V} defaultValue
* @return {V}
*/
export default function selectMap<K, V>(
key: K,
map: Map<K, V>,
defaultValue?: V
): V {
if (!map.has(key)) return defaultValue;
return map.get(key);
}

0 comments on commit b350cf7

Please sign in to comment.