From 4702404b4fbf24f6588f279c999e43a83e87f6f2 Mon Sep 17 00:00:00 2001 From: brucedonovan Date: Thu, 7 Sep 2023 11:07:37 +0100 Subject: [PATCH 01/12] be image url --- src/components/current/widgets/nft/NftAsset.tsx | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/components/current/widgets/nft/NftAsset.tsx b/src/components/current/widgets/nft/NftAsset.tsx index d34e164a..7c5d16d5 100644 --- a/src/components/current/widgets/nft/NftAsset.tsx +++ b/src/components/current/widgets/nft/NftAsset.tsx @@ -3,6 +3,7 @@ import { Address } from 'wagmi'; import { ImageResponse } from '@/components/cactiComponents'; import { ImageVariant } from '@/components/cactiComponents/ImageResponse'; import { InlineChip } from '@/components/cactiComponents/InlineChip'; +import { getBackendApiUrl } from '@/utils/backend'; export interface NftAssetProps { network: Network; @@ -41,9 +42,11 @@ export const NftAsset = ({ attributes }: NftAssetProps) => { + const backendUrl = getBackendApiUrl(); + return ( Date: Thu, 7 Sep 2023 11:15:04 +0100 Subject: [PATCH 02/12] ignore ts include --- src/components/devTools/MintButton.tsx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/components/devTools/MintButton.tsx b/src/components/devTools/MintButton.tsx index 9c3013c9..28e2d44a 100644 --- a/src/components/devTools/MintButton.tsx +++ b/src/components/devTools/MintButton.tsx @@ -11,7 +11,7 @@ export const MintButton = () => { const [isVisible, setVisible] = useState(false); const { chain } = useNetwork(); const { refetch } = useBalance(); - const provider = useProvider() as JsonRpcProvider; + const provider = useProvider(); useEffect(() => { if (!address || chain?.id != 1) setVisible(false); @@ -24,6 +24,7 @@ export const MintButton = () => { ethers.utils.parseEther('10').toHexString(), // hex encoded wei amount ]; setLoading(true); + // @ts-ignore await provider.send('tenderly_addBalance', params); await refetch(); setLoading(false); From c0c404b64c0afde3d4546a4a72a971aa7d9754b9 Mon Sep 17 00:00:00 2001 From: marcomariscal Date: Wed, 13 Sep 2023 09:45:18 -0700 Subject: [PATCH 03/12] feat: error handling and validating chains --- .../current/widgets/hop/HopBridge.tsx | 74 ++++++++++++++----- 1 file changed, 57 insertions(+), 17 deletions(-) diff --git a/src/components/current/widgets/hop/HopBridge.tsx b/src/components/current/widgets/hop/HopBridge.tsx index d55871fd..ffa69ae9 100644 --- a/src/components/current/widgets/hop/HopBridge.tsx +++ b/src/components/current/widgets/hop/HopBridge.tsx @@ -1,8 +1,14 @@ import React, { useEffect, useState } from 'react'; import { Hop } from '@hop-protocol/sdk'; +import { CanonicalToken, ChainSlug } from '@hop-protocol/sdk/dist/src/constants'; import { Interface, UnsignedTransaction } from 'ethers/lib/utils'; import { erc20ABI } from 'wagmi'; -import { ActionResponse, HeaderResponse, SingleLineResponse } from '@/components/cactiComponents'; +import { + ActionResponse, + ErrorResponse, + HeaderResponse, + SingleLineResponse, +} from '@/components/cactiComponents'; import { ApprovalBasicParams } from '@/components/cactiComponents/hooks/useApproval'; import useInput from '@/hooks/useInput'; import useSigner from '@/hooks/useSigner'; @@ -16,27 +22,61 @@ interface HopBridgeProps { } const HopBridge = ({ inputString, tokenSymbol, toChain, fromChain }: HopBridgeProps) => { - const _fromChain = fromChain === 'ethereum-mainnet' ? 'mainnet' : fromChain; + const _fromChain = fromChain === 'ethereum-mainnet' ? 'mainnet' : fromChain.toLowerCase(); + const _toChain = toChain === 'ethereum-mainnet' ? 'mainnet' : toChain.toLowerCase(); const signer = useSigner(); const { data: tokenIn } = useToken(tokenSymbol); const input = useInput(inputString, tokenIn?.symbol!); const [approvalParams, setApprovalParams] = useState(); const [sendParams, setSendParams] = useState(); - const [error, setError] = useState(); + const [error, setError] = useState(null); + + // TODO simple check to see if the chain is potentially supported; not all chains with chain slugs are supported within hop though (i.e.: zksync is unsupported) + const isSupportedChain = (name: string) => + name === 'mainnet' || + Object.keys(ChainSlug) + .map((s) => s.toLowerCase()) + .includes(name.toLowerCase()); + + const isSupportedToken = (symbol: string) => + Object.keys(CanonicalToken).includes(symbol.toUpperCase()); useEffect(() => { (async () => { - if (!input?.value) return console.error('No value to bridge'); + setError(null); + + if (!isSupportedChain(_fromChain)) { + return setError( + `Unsupported from chain. Available chains: ${Object.keys(ChainSlug).join(', ')}` + ); + } + + if (!isSupportedChain(_toChain)) { + return setError( + `Unsupported to chain. Available chains: ${Object.keys(ChainSlug).join(', ')}` + ); + } + + if (!isSupportedToken(tokenSymbol)) { + return setError( + `Unsupported token. Available tokens: ${Object.keys(CanonicalToken).join(', ')}` + ); + } + + if (!input?.value) { + setError('Please provide a value to bridge'); + return console.error('No value to bridge'); + } try { - const hop = new Hop(_fromChain, signer); + // mainnet is the network we use for all + const hop = new Hop('mainnet', signer); const bridge = hop.bridge(tokenSymbol); const needsApproval = await bridge.needsApproval(input.value, _fromChain); - if (needsApproval) { - // TODO wip + if (needsApproval) { const { data } = await bridge.populateSendApprovalTx(input.value, _fromChain); const erc20Interface = new Interface(erc20ABI); @@ -52,30 +92,30 @@ const HopBridge = ({ inputString, tokenSymbol, toChain, fromChain }: HopBridgePr } // TODO get the relevant to chain from hop - const req = await bridge.populateSendTx(input?.value, _fromChain, toChain); + const req = await bridge.populateSendTx(input?.value, _fromChain, _toChain); setSendParams({ ...req, gasLimit: 10_000_000 }); // TODO figure out a better way to handle gas limits on forks } catch (e) { - setError(e as string); - console.error('An error occurred:', e); + setError((e as Error).message); + console.error(e); } })(); - }, [_fromChain, input?.value, toChain, tokenIn?.address, tokenSymbol]); // TODO signer is causing infinite loop + }, [_fromChain, input?.value, _toChain, tokenIn?.address, tokenSymbol]); // TODO signer is causing infinite loop return ( <> + {error && ( + + )} ); From 4624434b4944f46d4c9ead5390e4f2a7321b19d9 Mon Sep 17 00:00:00 2001 From: marcomariscal Date: Wed, 13 Sep 2023 09:48:22 -0700 Subject: [PATCH 04/12] fix: remove unnecessary ? --- src/components/current/widgets/hop/HopBridge.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/current/widgets/hop/HopBridge.tsx b/src/components/current/widgets/hop/HopBridge.tsx index ffa69ae9..f300babb 100644 --- a/src/components/current/widgets/hop/HopBridge.tsx +++ b/src/components/current/widgets/hop/HopBridge.tsx @@ -92,7 +92,7 @@ const HopBridge = ({ inputString, tokenSymbol, toChain, fromChain }: HopBridgePr } // TODO get the relevant to chain from hop - const req = await bridge.populateSendTx(input?.value, _fromChain, _toChain); + const req = await bridge.populateSendTx(input.value, _fromChain, _toChain); setSendParams({ ...req, gasLimit: 10_000_000 }); // TODO figure out a better way to handle gas limits on forks } catch (e) { setError((e as Error).message); From 080e9f0a215ed78f2a7ada4f015bd790cb8f6a5c Mon Sep 17 00:00:00 2001 From: marcomariscal Date: Wed, 13 Sep 2023 09:55:10 -0700 Subject: [PATCH 05/12] fix: better comment --- src/components/current/widgets/hop/HopBridge.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/current/widgets/hop/HopBridge.tsx b/src/components/current/widgets/hop/HopBridge.tsx index f300babb..bd36f7f9 100644 --- a/src/components/current/widgets/hop/HopBridge.tsx +++ b/src/components/current/widgets/hop/HopBridge.tsx @@ -70,7 +70,7 @@ const HopBridge = ({ inputString, tokenSymbol, toChain, fromChain }: HopBridgePr } try { - // mainnet is the network we use for all + // mainnet is the network we use for all bridge operations const hop = new Hop('mainnet', signer); const bridge = hop.bridge(tokenSymbol); From 61bc324d4e86c983b7c9fc13a8183ff5dc29fb7f Mon Sep 17 00:00:00 2001 From: marcomariscal Date: Wed, 13 Sep 2023 09:55:36 -0700 Subject: [PATCH 06/12] fix: remove unnecessary comment --- src/components/current/widgets/hop/HopBridge.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/src/components/current/widgets/hop/HopBridge.tsx b/src/components/current/widgets/hop/HopBridge.tsx index bd36f7f9..03a67344 100644 --- a/src/components/current/widgets/hop/HopBridge.tsx +++ b/src/components/current/widgets/hop/HopBridge.tsx @@ -91,7 +91,6 @@ const HopBridge = ({ inputString, tokenSymbol, toChain, fromChain }: HopBridgePr }); } - // TODO get the relevant to chain from hop const req = await bridge.populateSendTx(input.value, _fromChain, _toChain); setSendParams({ ...req, gasLimit: 10_000_000 }); // TODO figure out a better way to handle gas limits on forks } catch (e) { From ac238fef06667c1303d5dfbb9651806bcee798ce Mon Sep 17 00:00:00 2001 From: Jacob Bryant Date: Fri, 15 Sep 2023 09:41:08 -0400 Subject: [PATCH 07/12] adding double check for links in markdown --- src/components/current/Markdown.tsx | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/src/components/current/Markdown.tsx b/src/components/current/Markdown.tsx index 7561c3cb..97ec7a47 100644 --- a/src/components/current/Markdown.tsx +++ b/src/components/current/Markdown.tsx @@ -1,16 +1,25 @@ +import React, { ReactNode } from 'react'; import ReactMarkdown from 'react-markdown'; //====================================== export const Markdown = ({ children }: { children: string }) => { + // regex to match URLs in text that arent already formatted as links in markdown + const urlRegex = /(? `[${url}](${url})`); + return (