Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement fuel wallet connect #1110

Open
wants to merge 8 commits into
base: dev
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion Models/Network.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@ export enum NetworkType {
Cosmos = "cosmos",
StarkEx = "starkex",//TODO check this
ZkSyncLite = "zksynclite",
TON = 'ton'
TON = 'ton',
Fuel = 'fuel',
}

export class Network {
Expand Down
2 changes: 0 additions & 2 deletions components/HeaderWithMenu/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import { ArrowLeft } from 'lucide-react'
import ChatIcon from "../icons/ChatIcon"
import dynamic from "next/dynamic"
import LayerswapMenu from "../LayerswapMenu"
import { useRouter } from "next/router"
import { useQueryState } from "../../context/query"

const WalletsHeader = dynamic(() => import("../ConnectedWallets").then((comp) => comp.WalletsHeader), {
Expand All @@ -18,7 +17,6 @@ function HeaderWithMenu({ goBack }: { goBack: (() => void) | undefined | null })
const { boot, show, update } = useIntercom()
const updateWithProps = () => update({ userId, customAttributes: { email: email, } })
const query = useQueryState()
const router = useRouter()

return (
<div className="w-full grid grid-cols-5 px-6 mt-3 pb-2" >
Expand Down
17 changes: 14 additions & 3 deletions components/Input/Address/AddressPicker/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ const AddressPicker: FC<Input> = forwardRef<HTMLInputElement, Input>(function Ad

const provider = useMemo(() => {
if (destinationExchange) return undefined

return values?.to && getProvider(values?.to)
}, [values?.to, getProvider, destinationExchange])

Expand Down Expand Up @@ -169,13 +169,24 @@ const AddressPicker: FC<Input> = forwardRef<HTMLInputElement, Input>(function Ad

{
destinationExchange ?
<ExchangeNote destination={destination} destinationAsset={destinationAsset} destinationExchange={destinationExchange} />
<ExchangeNote
destination={destination}
destinationAsset={destinationAsset}
destinationExchange={destinationExchange}
/>
:
!disabled
&& destination
&& provider
&& !manualAddress &&
<ConnectWalletButton provider={provider} connectedWallet={connectedWallet} onClick={() => { connectedWallet && handleSelectAddress(connectedWallet.address) }} onConnect={() => setIsConnecting(true)} destination={destination} destination_address={destination_address} />
<ConnectWalletButton
provider={provider}
connectedWallet={connectedWallet}
onClick={() => { connectedWallet && handleSelectAddress(connectedWallet.address) }}
onConnect={() => setIsConnecting(true)}
destination={destination}
destination_address={destination_address}
/>
}

{
Expand Down
2 changes: 1 addition & 1 deletion components/Swap/Form/Form.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ import CEXNetworkFormField from "../../Input/CEXNetworkFormField";
import { RouteNetwork } from "../../../Models/Network";
import { resolveExchangesURLForSelectedToken } from "../../../helpers/routes";
import ValidationError from "../../validationError";
import { ImtblPassportProvider } from "../../ImtblPassportProvider";
import { ImtblPassportProvider } from "../../WalletProviders/ImtblPassportProvider";
import { Exchange, ExchangeToken } from "../../../Models/Exchange";
import { resolveRoutesURLForSelectedToken } from "../../../helpers/routes";
import { useValidationContext } from "../../../context/validationErrorContext";
Expand Down
2 changes: 1 addition & 1 deletion components/SwapWithdrawal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import SwapDetails from "./Swap";
import { Widget } from "./Widget/Index";
import NotFound from "./Swap/NotFound";
import { BalancesDataProvider } from "../context/balances";
import { ImtblPassportProvider } from "./ImtblPassportProvider";
import { ImtblPassportProvider } from "./WalletProviders/ImtblPassportProvider";

const SwapWithdrawal: FC = () => {
const { swapResponse: swap, swapApiError } = useSwapDataState()
Expand Down
34 changes: 34 additions & 0 deletions components/WalletProviders/FuelProvider.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@

import { defaultConnectors } from '@fuels/connectors';
import { FuelProvider } from '@fuels/react';
import { CHAIN_IDS, Provider } from 'fuels';

const WALLETCONNECT_PROJECT_ID = process.env.NEXT_PUBLIC_WALLET_CONNECT_PROJECT_ID || '28168903b2d30c75e5f7f2d71902581b';

const NETWORKS = [
{
chainId: CHAIN_IDS.fuel.testnet,
url: 'https://testnet.fuel.network/v1/graphql',
},
];

const fuelConfig = {
connectors: defaultConnectors({
devMode: true,
wcProjectId: WALLETCONNECT_PROJECT_ID,
chainId: NETWORKS[0].chainId,
fuelProvider: Provider.create(NETWORKS[0].url),
}),
};
const FuelProviderWrapper = ({
children,
}: { children: React.ReactNode }) => {

return (
<FuelProvider uiConfig={{ suggestBridge: false }} theme={'dark'} fuelConfig={fuelConfig} networks={NETWORKS}>
{children}
</FuelProvider>
);
};

export default FuelProviderWrapper;
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { useEffect } from "react"
import { Network } from "../Models/Network";
import { Network } from "../../Models/Network";
import { useRouter } from "next/router";

const PUBLISHABLE_KEY = process.env.NEXT_PUBLIC_IMMUTABLE_PUBLISHABLE_KEY;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@

import '@rainbow-me/rainbowkit/styles.css';
import { useSettingsState } from "../context/settings";
import { useSettingsState } from "../../context/settings";
import {
AvatarComponent,
connectorsForWallets,
darkTheme,
DisclaimerComponent,
RainbowKitProvider,
} from '@rainbow-me/rainbowkit';
import { NetworkType } from "../Models/Network";
import resolveChain from "../lib/resolveChain";
import { NetworkType } from "../../Models/Network";
import resolveChain from "../../lib/resolveChain";
import React from "react";
import AddressIcon from "./AddressIcon";
import NetworkSettings from "../lib/NetworkSettings";
import AddressIcon from "../AddressIcon";
import NetworkSettings from "../../lib/NetworkSettings";
import { WagmiProvider } from 'wagmi'
import { QueryClient, QueryClientProvider } from '@tanstack/react-query'
import { argentWallet, bitgetWallet, coinbaseWallet, injectedWallet, metaMaskWallet, phantomWallet, rainbowWallet, walletConnectWallet } from '@rainbow-me/rainbowkit/wallets';
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { THEME, TonConnectUIProvider } from "@tonconnect/ui-react"
import { ThemeData } from "../Models/Theme";
import { ThemeData } from "../../Models/Theme";

const TonConnectProvider = ({ children, basePath, themeData, appName }: { children: JSX.Element | JSX.Element[], basePath: string, themeData: ThemeData, appName: string | undefined }) => {

Expand Down
32 changes: 32 additions & 0 deletions components/WalletProviders/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import { FC } from "react"
import TonConnectProvider from "./TonConnectProvider"
import RainbowKit from "./RainbowKit"
import SolanaProvider from "./SolanaProvider"
import { ThemeData } from "../../Models/Theme"
import dynamic from "next/dynamic"

const FuelProviderWrapper = dynamic(() => import("./FuelProvider").then((comp) => comp.default), {
loading: () => null
})

const WalletsProviders: FC<{ children: JSX.Element | JSX.Element[], basePath: string, themeData: ThemeData, appName: string | undefined }> = ({ children, basePath, themeData, appName }) => {
return (
<TonConnectProvider basePath={basePath} themeData={themeData} appName={appName}>
<RainbowKit>
<SolanaProvider>
{
FuelProviderWrapper ?
<FuelProviderWrapper>
{children}
</FuelProviderWrapper> :
<>
{children}
</>
}
</SolanaProvider>
</RainbowKit>
</TonConnectProvider>
)
}

export default WalletsProviders
5 changes: 5 additions & 0 deletions components/buttons/connectButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,11 @@ const ConnectButton = ({
id: "solana",
type: NetworkType.Solana,
},
{
name: "Fuel",
id: "fuel",
type: NetworkType.Fuel,
},
];
const filteredConnectors = knownConnectors.filter(
(c) => !wallets.map((w) => w?.providerName).includes(c.id)
Expand Down
15 changes: 14 additions & 1 deletion components/icons/ConnectorIcons.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@ import OpenMask from "../icons/Wallets/OpenMask";
import Phantom from "../icons/Wallets/Phantom";
import CoinbaseIcon from "../icons/Wallets/Coinbase";
import GlowIcon from "../icons/Wallets/Glow";
import Fuel from "./Wallets/Fuel";
import BakoSafe from "./Wallets/BakoSafe";
import Ethereum from "./Wallets/Ethereum";

export const ResolveConnectorIcon = ({
connector,
Expand Down Expand Up @@ -59,6 +62,15 @@ export const ResolveConnectorIcon = ({
{children}
</div>
);
case KnownConnectors.Fuel:
return (
<div className={className ?? "-space-x-2 flex"}>
<Fuel className={iconClassName} />
<BakoSafe className={iconClassName} />
<Ethereum className={iconClassName} />
{children}
</div>
);
default:
return <></>;
}
Expand All @@ -69,5 +81,6 @@ const KnownConnectors = {
EVM: "evm",
TON: "ton",
Solana: "solana",
Glow: "glow"
Glow: "glow",
Fuel: "fuel",
};
23 changes: 23 additions & 0 deletions components/icons/Wallets/BakoSafe.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { SVGProps } from "react"

const BakoSafe = (props: SVGProps<SVGSVGElement>) => <svg xmlns="http://www.w3.org/2000/svg" width="50" height="50" viewBox="0 0 50 50" fill="none" {...props}>
<rect width="50" height="50" fill="url(#paint0_linear_97_19)" />
<mask id="mask0_97_19" style={{ "maskType": "luminance" }} maskUnits="userSpaceOnUse" x="13" y="5" width="24" height="40">
<path d="M37 5H13V45H37V5Z" fill="white" />
</mask>
<g mask="url(#mask0_97_19)">
<path d="M13 25.9167L37 37.8671L25.0024 18.9893L13 25.9167Z" fill="#F5F5F5" />
<path d="M33.8864 22.2182L24.9976 17.0865V5.13574L13 12.0628V25.916L24.9976 18.9889V30.9396L13 37.8668L24.9976 44.7938L36.9952 37.8668V27.6033C36.9952 25.3816 35.8098 23.3291 33.8864 22.2182Z" fill="#1E1F22" />
</g>
<defs>
<linearGradient id="paint0_linear_97_19" x1="0" y1="0" x2="50" y2="50" gradientUnits="userSpaceOnUse">
<stop stopColor="#FFC010" />
<stop offset="0.48" stopColor="#EBA312" />
<stop offset="0.71" stopColor="#D38015" />
<stop offset="0.99" stopColor="#B24F18" />
</linearGradient>
</defs>
</svg>


export default BakoSafe;
12 changes: 12 additions & 0 deletions components/icons/Wallets/Ethereum.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { SVGProps } from "react"

const Ethereum = (props: SVGProps<SVGSVGElement>) => <svg xmlns="http://www.w3.org/2000/svg" width="512" height="512" viewBox="0 0 512 512" fill="none" {...props}>
<path d="M253 335.122L255.886 338L388 259.987L255.886 41L253 50.7983V335.122Z" fill="#343434" />
<path d="M256 338V41L124 259.986L256 338Z" fill="#8C8C8C" />
<path d="M254 465.281L255.628 470L388 285L255.629 362.563L254.001 364.532L254 465.281Z" fill="#3C3C3B" />
<path d="M124 285L256 470V362.562L124 285Z" fill="#8C8C8C" />
<path d="M256 200V338L388 259.988L256 200Z" fill="#141414" />
<path d="M256 200L124 259.988L256 338V200Z" fill="#393939" />
</svg>

export default Ethereum;
12 changes: 12 additions & 0 deletions components/icons/Wallets/Fuel.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { SVGProps } from "react"

const Fuel = (props: SVGProps<SVGSVGElement>) => <svg xmlns="http://www.w3.org/2000/svg" width="350" height="350" viewBox="0 0 350 350" fill="none" {...props}>
<rect width="350" height="350" fill="#00F58C" />
<path d="M23.2742 0C17.1029 -3.70471e-07 11.1842 2.45098 6.81969 6.814C2.45517 11.177 0.00213836 17.0948 0 23.2661V350H289.589C299.389 349.999 308.787 346.106 315.718 339.177L339.177 315.718C342.609 312.287 345.331 308.213 347.188 303.73C349.045 299.247 350 294.441 350 289.589V0H23.2742Z" fill="#00F58C" />
<path d="M228.524 45L114.702 158.823C111.875 161.645 108.043 163.232 104.048 163.234C101.195 163.234 98.3999 162.423 95.9887 160.897C93.5774 159.371 91.6489 157.192 90.4275 154.613L46.3307 61.379C45.504 59.6297 45.133 57.6997 45.2523 55.7685C45.3715 53.8373 45.9772 51.9676 47.0128 50.3333C48.0485 48.6989 49.4805 47.353 51.1759 46.4205C52.8713 45.4881 54.7749 44.9994 56.7097 45H228.524Z" fill="black" />
<path d="M45 305V194.25C45.0021 191.413 46.1306 188.693 48.1373 186.688C50.144 184.683 52.8648 183.556 55.7016 183.556H166.444L45 305Z" fill="black" />
<path d="M175.589 163.234H138.919L249.25 52.9113C251.756 50.4036 254.732 48.4142 258.007 47.0567C261.283 45.6993 264.793 45.0004 268.339 45H305L194.678 155.331C189.612 160.389 182.747 163.231 175.589 163.234Z" fill="black" />
</svg>


export default Fuel;
4 changes: 3 additions & 1 deletion components/icons/Wallets/TON.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
const TON = (props) => <svg {...props} xmlns="http://www.w3.org/2000/svg" width="56" height="56" viewBox="0 0 56 56" fill="none">
import { SVGProps } from "react"

const TON = (props: SVGProps<SVGSVGElement>) => <svg xmlns="http://www.w3.org/2000/svg" width="56" height="56" viewBox="0 0 56 56" fill="none" {...props}>
<path d="M28 56C43.464 56 56 43.464 56 28C56 12.536 43.464 0 28 0C12.536 0 0 12.536 0 28C0 43.464 12.536 56 28 56Z" fill="#0098EA" />
<path d="M37.5603 15.6277H18.4386C14.9228 15.6277 12.6944 19.4202 14.4632 22.4861L26.2644 42.9409C27.0345 44.2765 28.9644 44.2765 29.7345 42.9409L41.5381 22.4861C43.3045 19.4251 41.0761 15.6277 37.5627 15.6277H37.5603ZM26.2548 36.8068L23.6847 31.8327L17.4833 20.7414C17.0742 20.0315 17.5795 19.1218 18.4362 19.1218H26.2524V36.8092L26.2548 36.8068ZM38.5108 20.739L32.3118 31.8351L29.7417 36.8068V19.1194H37.5579C38.4146 19.1194 38.9199 20.0291 38.5108 20.739Z" fill="white" />
</svg>
Expand Down
22 changes: 8 additions & 14 deletions components/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,9 @@ import QueryProvider from "../context/query";
import { THEME_COLORS, ThemeData } from "../Models/Theme";
import { TooltipProvider } from "./shadcn/tooltip";
import ColorSchema from "./ColorSchema";
import TonConnectProvider from "./TonConnectProvider";
import RainbowKit from "./RainbowKit";
import Solana from "./SolanaProvider";
import { IsExtensionError } from "../helpers/errorHelper";
import { AsyncModalProvider } from "../context/asyncModal";
import WalletsProviders from "./WalletProviders";
// import { datadogRum } from '@datadog/browser-rum';

type Props = {
Expand Down Expand Up @@ -134,17 +132,13 @@ export default function Layout({ children, settings, themeData }: Props) {
<TooltipProvider delayDuration={500}>
<ErrorBoundary FallbackComponent={ErrorFallback} onError={logErrorToService}>
<ThemeWrapper>
<TonConnectProvider basePath={basePath} themeData={themeData} appName={router.query.appName?.toString()}>
<RainbowKit>
<Solana>
<AsyncModalProvider>
{process.env.NEXT_PUBLIC_IN_MAINTANANCE === 'true' ?
<MaintananceContent />
: children}
</AsyncModalProvider>
</Solana>
</RainbowKit>
</TonConnectProvider>
<WalletsProviders basePath={basePath} themeData={themeData} appName={router.query.appName?.toString()}>
<AsyncModalProvider>
{process.env.NEXT_PUBLIC_IN_MAINTANANCE === 'true' ?
<MaintananceContent />
: children}
</AsyncModalProvider>
</WalletsProviders>
</ThemeWrapper>
</ErrorBoundary>
</TooltipProvider>
Expand Down
8 changes: 5 additions & 3 deletions hooks/useWallet.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,14 @@ import useStarknet from "../lib/wallets/starknet/useStarknet"
import useImtblX from "../lib/wallets/imtblX/useImtblX"
import useSolana from "../lib/wallets/solana/useSolana"
import { Network, RouteNetwork } from "../Models/Network"
import useFuel from "../lib/wallets/fuel/useFuel"

export type WalletProvider = {
connectWallet: (props?: { chain?: string | number | undefined | null, destination?: RouteNetwork }) => Promise<void> | undefined | void,
disconnectWallet: () => Promise<void> | undefined | void,
reconnectWallet: (props?: { chain?: string | number | undefined | null }) => Promise<void> | undefined | void,
getConnectedWallet: (network?: Network) => Wallet | undefined,
withdrawalSupportedNetworks: string[],
withdrawalSupportedNetworks?: string[],
autofillSupportedNetworks?: string[],
asSourceSupportedNetworks?: string[],
name: string,
Expand All @@ -26,7 +27,8 @@ export default function useWallet() {
useEVM(),
useStarknet(),
useImtblX(),
useSolana()
useSolana(),
useFuel()
]

async function connectWallet({ providerName, chain }: { providerName: string, chain?: string | number | null }) {
Expand Down Expand Up @@ -77,7 +79,7 @@ export default function useWallet() {
}

const getWithdrawalProvider = (network: Network) => {
const provider = WalletProviders.find(provider => provider.withdrawalSupportedNetworks.includes(network.name))
const provider = WalletProviders.find(provider => provider?.withdrawalSupportedNetworks?.includes(network.name))
return provider
}

Expand Down
11 changes: 11 additions & 0 deletions lib/address/validator/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,17 @@ export function isValidAddress(address?: string, network?: { name: string } | nu
const decodedAddress = decodeBase58(address).toUpperCase();
return decodedAddress.startsWith('41') && decodedAddress.length == 42
}
else if (network?.name === KnownInternalNames.Networks.FuelTestnet) {
const hexRegex = /^[0-9a-fA-F]+$/;

if (address.startsWith("0x")) {
address = address.slice(2); // Remove the "0x" prefix
} else {
return false;
}

return address.length === 64 && hexRegex.test(address);
}
else {
return isValidEtherAddress(address);
}
Expand Down
2 changes: 2 additions & 0 deletions lib/knownIds.ts
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,8 @@ export default class KnownInternalNames {

public static readonly ParadexMainnet: string = "PARADEX_MAINNET"

public static readonly FuelTestnet: string = "FUEL_TESTNET"

public static readonly TronMainnet: string = "TRON_MAINNET"

public static readonly TronTestnet: string = "TRON_TESTNET"
Expand Down
Loading
Loading