Skip to content

Commit

Permalink
add support for evm wallets, separate source and destination wallets
Browse files Browse the repository at this point in the history
  • Loading branch information
thal0x committed Sep 28, 2023
1 parent bcdebc0 commit 71bf627
Show file tree
Hide file tree
Showing 14 changed files with 2,720 additions and 328 deletions.
2,469 changes: 2,392 additions & 77 deletions package-lock.json

Large diffs are not rendered by default.

6 changes: 4 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@
"@radix-ui/react-dialog": "^1.0.4",
"@radix-ui/react-toast": "^1.1.4",
"@radix-ui/react-tooltip": "^1.0.6",
"@skip-router/core": "^0.0.7",
"@skip-router/core": "^0.1.0-rc6",
"@tanstack/react-query": "^4.29.5",
"@types/node": "20.1.2",
"@types/react": "18.2.6",
Expand All @@ -61,7 +61,9 @@
"react": "18.2.0",
"react-dom": "18.2.0",
"tailwindcss": "3.3.2",
"usehooks-ts": "^2.9.1"
"usehooks-ts": "^2.9.1",
"viem": "^1.12.2",
"wagmi": "^1.4.2"
},
"devDependencies": {
"@testing-library/jest-dom": "^5.16.5",
Expand Down
31 changes: 31 additions & 0 deletions public/metamask-logo.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
27 changes: 27 additions & 0 deletions src/components/RouteLoadingBanner.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
const RouteLoadingBanner = () => (
<div className="bg-black text-white/50 font-medium uppercase text-xs p-3 rounded-md flex items-center w-full text-left">
<p className="flex-1">Finding best route...</p>
<svg
className="animate-spin h-4 w-4 inline-block text-white"
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
>
<circle
className="opacity-25"
cx="12"
cy="12"
r="10"
stroke="currentColor"
strokeWidth="4"
></circle>
<path
className="opacity-75"
fill="currentColor"
d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"
></path>
</svg>
</div>
);

export default RouteLoadingBanner;
20 changes: 20 additions & 0 deletions src/components/RouteTransactionCountBanner.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { FC } from "react";

const RouteTransactionCountBanner: FC<{
numberOfTransactions: number;
}> = ({ numberOfTransactions }) => (
<div className="bg-black text-white/50 font-medium uppercase text-xs p-3 rounded-md flex items-center w-full text-left">
<p className="flex-1">
This route requires{" "}
{numberOfTransactions === 1 && (
<span className="text-white">1 Transaction</span>
)}
{numberOfTransactions > 1 && (
<span className="text-white">{numberOfTransactions} Transactions</span>
)}{" "}
to complete
</p>
</div>
);

export default RouteTransactionCountBanner;
114 changes: 48 additions & 66 deletions src/components/SwapWidget/SwapWidget.tsx
Original file line number Diff line number Diff line change
@@ -1,60 +1,18 @@
import { WalletStatus } from "@cosmos-kit/core";
import { useChain } from "@cosmos-kit/react";
import { ArrowsUpDownIcon } from "@heroicons/react/20/solid";
import { FC, Fragment } from "react";

import { useChains } from "@/context/chains";
import { useAccount } from "@/hooks/useAccount";

import AssetInput from "../AssetInput";
import { ConnectedWalletButton } from "../ConnectedWalletButton";
import { ConnectWalletButtonSmall } from "../ConnectWalletButtonSmall";
import RouteLoadingBanner from "../RouteLoadingBanner";
import RouteTransactionCountBanner from "../RouteTransactionCountBanner";
import TransactionDialog from "../TransactionDialog";
import { useWalletModal, WalletModal } from "../WalletModal";
import { useSwapWidget } from "./useSwapWidget";

const RouteLoading = () => (
<div className="bg-black text-white/50 font-medium uppercase text-xs p-3 rounded-md flex items-center w-full text-left">
<p className="flex-1">Finding best route...</p>
<svg
className="animate-spin h-4 w-4 inline-block text-white"
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
>
<circle
className="opacity-25"
cx="12"
cy="12"
r="10"
stroke="currentColor"
strokeWidth="4"
></circle>
<path
className="opacity-75"
fill="currentColor"
d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"
></path>
</svg>
</div>
);

const RouteTransactionCountBanner: FC<{
numberOfTransactions: number;
}> = ({ numberOfTransactions }) => (
<div className="bg-black text-white/50 font-medium uppercase text-xs p-3 rounded-md flex items-center w-full text-left">
<p className="flex-1">
This route requires{" "}
{numberOfTransactions === 1 && (
<span className="text-white">1 Transaction</span>
)}
{numberOfTransactions > 1 && (
<span className="text-white">{numberOfTransactions} Transactions</span>
)}{" "}
to complete
</p>
</div>
);

export const SwapWidget: FC = () => {
const { openWalletModal } = useWalletModal();
const { chains } = useChains();
Expand All @@ -78,35 +36,42 @@ export const SwapWidget: FC = () => {
onDestinationAssetChange,
} = useSwapWidget();

const {
status: walletConnectStatus,
address,
wallet,
} = useChain(sourceChain?.record?.chain.chain_name ?? "cosmoshub");
const { address, isWalletConnected, wallet } = useAccount(
sourceChain?.chainID ?? "cosmoshub-4",
);

const { address: destinationChainAddress } = useAccount(
destinationChain?.chainID ?? "cosmoshub-4",
);

const shouldShowDestinationWalletButton =
!!sourceChain &&
!!destinationChain &&
sourceChain.chainType !== destinationChain.chainType;

return (
<Fragment>
<div>
<div className="space-y-6">
<div className="flex items-center justify-between">
<p className="font-semibold text-2xl">From</p>
{address &&
wallet &&
walletConnectStatus === WalletStatus.Connected ? (
{address && wallet && isWalletConnected ? (
<ConnectedWalletButton
address={address}
onClick={openWalletModal}
walletName={wallet.prettyName}
onClick={() => openWalletModal(sourceChain?.chainID ?? "")}
walletName={wallet.walletPrettyName}
walletLogo={
wallet.logo
? typeof wallet.logo === "string"
? wallet.logo
: wallet.logo.major
wallet.walletInfo.logo
? typeof wallet.walletInfo.logo === "string"
? wallet.walletInfo.logo
: wallet.walletInfo.logo.major
: ""
}
/>
) : (
<ConnectWalletButtonSmall onClick={openWalletModal} />
<ConnectWalletButtonSmall
onClick={() => openWalletModal(sourceChain?.chainID ?? "")}
/>
)}
</div>
<div data-testid="source">
Expand Down Expand Up @@ -146,6 +111,23 @@ export const SwapWidget: FC = () => {
</button>
</div>
<p className="font-semibold text-2xl">To</p>
{shouldShowDestinationWalletButton ? (
<div className="absolute inset-y-0 right-0 flex items-center">
<button
className="bg-[#FF486E]/20 hover:bg-[#FF486E]/30 text-[#FF486E] text-xs font-semibold rounded-lg py-1 px-2.5 flex items-center gap-1 transition-colors focus:outline-none"
onClick={() =>
openWalletModal(destinationChain?.chainID ?? "cosmoshub-4")
}
>
{destinationChainAddress
? `${destinationChainAddress.slice(
0,
8,
)}...${destinationChainAddress.slice(-5)}`
: "Connect Wallet"}
</button>
</div>
) : null}
</div>
<div data-testid="destination">
<AssetInput
Expand All @@ -157,23 +139,23 @@ export const SwapWidget: FC = () => {
chains={chains}
/>
</div>
{routeLoading && <RouteLoading />}
{routeLoading && <RouteLoadingBanner />}
{route && !routeLoading && (
<RouteTransactionCountBanner
numberOfTransactions={numberOfTransactions}
/>
)}
{sourceChain && walletConnectStatus !== WalletStatus.Connected && (
{sourceChain && !isWalletConnected && (
<button
className="bg-[#FF486E] text-white font-semibold py-4 rounded-md w-full transition-transform hover:scale-105 hover:rotate-1"
onClick={async () => {
openWalletModal();
onClick={() => {
openWalletModal(sourceChain.chainID);
}}
>
Connect Wallet
</button>
)}
{sourceChain && walletConnectStatus === WalletStatus.Connected && (
{sourceChain && isWalletConnected && (
<div className="space-y-4">
<TransactionDialog
route={route}
Expand All @@ -189,7 +171,7 @@ export const SwapWidget: FC = () => {
)}
</div>
</div>
<WalletModal chainID={sourceChain?.chainID ?? "cosmoshub-4"} />
<WalletModal />
</Fragment>
);
};
27 changes: 27 additions & 0 deletions src/components/SwapWidget/useSwapWidget.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { useChain } from "@cosmos-kit/react";
import { ethers } from "ethers";
import { useEffect, useMemo, useState } from "react";
import { useNetwork, useSwitchNetwork } from "wagmi";

import { AssetWithMetadata, useAssets } from "@/context/assets";
import { Chain, useChains } from "@/context/chains";
Expand Down Expand Up @@ -102,6 +103,32 @@ export function useSwapWidget() {
return amountIn > balance;
}, [balances, formValues.amountIn, formValues.sourceAsset]);

const { chain: currentEvmChain } = useNetwork();

const { switchNetwork } = useSwitchNetwork();

useEffect(() => {
if (
!formValues.sourceChain ||
formValues.sourceChain.chainType === "cosmos"
) {
return;
}

if (!currentEvmChain || !switchNetwork) {
return;
}

const chainID = parseInt(formValues.sourceChain.chainID);

if (currentEvmChain.id !== chainID) {
switchNetwork(chainID);
}

console.log("source chain changed", formValues.sourceChain);
console.log(currentEvmChain);
}, [currentEvmChain, formValues.sourceChain, switchNetwork]);

return {
amountIn: formValues.amountIn,
amountOut,
Expand Down
Loading

0 comments on commit 71bf627

Please sign in to comment.