Skip to content

Commit

Permalink
Merge pull request #71 from astriaorg/feature/rainbow-kit
Browse files Browse the repository at this point in the history
feature: implement rainbowkit
  • Loading branch information
steezeburger authored Nov 27, 2024
2 parents 6ea0e23 + 6ff4882 commit bd35e21
Show file tree
Hide file tree
Showing 27 changed files with 14,901 additions and 9,008 deletions.
22,555 changes: 14,331 additions & 8,224 deletions web/package-lock.json

Large diffs are not rendered by default.

12 changes: 6 additions & 6 deletions web/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@
"@keplr-wallet/stores": "^0.12.22",
"@keplr-wallet/types": "^0.12.22",
"@keplr-wallet/unit": "^0.12.22",
"@rainbow-me/rainbowkit": "^2.2.0",
"@tanstack/react-query": "^5.61.0",
"@types/node": "^16.18.56",
"@types/react-dom": "^18.3.1",
"@types/uuid": "^9.0.8",
Expand All @@ -27,6 +29,8 @@
"typescript": "^5.7.2",
"util": "^0.12.5",
"uuid": "^9.0.1",
"viem": "^2.21.49",
"wagmi": "^2.13.0",
"web-vitals": "^2.1.4"
},
"overrides": {
Expand All @@ -37,7 +41,7 @@
"scripts": {
"start": "react-app-rewired start",
"build": "react-app-rewired build",
"test": "react-app-rewired test --transformIgnorePatterns \"/node_modules/(?!(@cosmjs|axios)/)\"",
"test": "react-app-rewired test --transformIgnorePatterns \"/node_modules/(?!(@cosmjs|axios|@rainbow-me/rainbowkit|wagmi|@wagmi)/)\"",
"test-cov": "CI=true react-scripts test --coverage",
"eject": "react-scripts eject",
"format": "biome format --write .",
Expand All @@ -46,11 +50,7 @@
"lint-apply-unsafe": "biome lint --apply-unsafe ./src ./public"
},
"browserslist": {
"production": [
">0.2%",
"not dead",
"not op_mini all"
],
"production": [">0.2%", "not dead", "not op_mini all"],
"development": [
"last 1 chrome version",
"last 1 firefox version",
Expand Down
Binary file removed web/public/astria-blocks.png
Binary file not shown.
Binary file removed web/public/icon-192x192.png
Binary file not shown.
Binary file removed web/public/icon-512x512.png
Binary file not shown.
42 changes: 29 additions & 13 deletions web/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,25 +2,41 @@ import type React from "react";
import { Route, Routes } from "react-router-dom";
import BridgePage from "pages/BridgePage/BridgePage";
import Layout from "pages/Layout";
import { ConfigContextProvider } from "config";
import { EthWalletContextProvider } from "features/EthWallet";
import { useConfig } from "config";
import { NotificationsContextProvider } from "features/Notifications";

import { getDefaultConfig, RainbowKitProvider } from "@rainbow-me/rainbowkit";
import { evmChainsToRainbowKitChains } from "./config/chainConfigs/types.ts";
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
import { WagmiProvider } from "wagmi";

/**
* App component with routes.
*/
export default function App(): React.ReactElement {
const { evmChains } = useConfig();

const rainbowKitConfig = getDefaultConfig({
appName: "Flame Bridge",
projectId: "YOUR_PROJECT_ID", // TODO
chains: evmChainsToRainbowKitChains(evmChains),
});

const queryClient = new QueryClient();

return (
<ConfigContextProvider>
<NotificationsContextProvider>
<EthWalletContextProvider>
<Routes>
<Route element={<Layout />}>
<Route index element={<BridgePage />} />
</Route>
</Routes>
</EthWalletContextProvider>
</NotificationsContextProvider>
</ConfigContextProvider>
<NotificationsContextProvider>
<WagmiProvider config={rainbowKitConfig}>
<QueryClientProvider client={queryClient}>
<RainbowKitProvider>
<Routes>
<Route element={<Layout />}>
<Route index element={<BridgePage />} />
</Route>
</Routes>
</RainbowKitProvider>
</QueryClientProvider>
</WagmiProvider>
</NotificationsContextProvider>
);
}
14 changes: 8 additions & 6 deletions web/src/components/DepositCard/DepositCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -334,7 +334,7 @@ export default function DepositCard(): React.ReactElement {
Address: {fromAddress}
</p>
)}
{fromAddress && !isLoadingIbcBalance && (
{fromAddress && selectedIbcCurrency && !isLoadingIbcBalance && (
<p className="mt-2 has-text-grey-lighter has-text-weight-semibold">
Balance: {ibcBalance}
</p>
Expand Down Expand Up @@ -404,11 +404,13 @@ export default function DepositCard(): React.ReactElement {
<i className="fas fa-pen-to-square" />
</p>
)}
{evmAccountAddress && !isLoadingEvmBalance && (
<p className="mt-2 has-text-grey-lighter has-text-weight-semibold">
Balance: {evmBalance}
</p>
)}
{evmAccountAddress &&
selectedEvmChain &&
!isLoadingEvmBalance && (
<p className="mt-2 has-text-grey-lighter has-text-weight-semibold">
Balance: {evmBalance}
</p>
)}
{evmAccountAddress && isLoadingEvmBalance && (
<p className="mt-2 has-text-grey-lighter has-text-weight-semibold">
Balance: <i className="fas fa-spinner fa-pulse" />
Expand Down
19 changes: 11 additions & 8 deletions web/src/components/WithdrawCard/WithdrawCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,17 @@ import AnimatedArrowSpacer from "components/AnimatedDownArrowSpacer/AnimatedDown
import Dropdown from "components/Dropdown/Dropdown";
import {
AddERC20ToWalletButton,
getAstriaWithdrawerService,
useEthWallet,
createWithdrawerService,
useEvmChainSelection,
} from "features/EthWallet";
import { useIbcChainSelection } from "features/KeplrWallet";
import { NotificationType, useNotifications } from "features/Notifications";
import { useConfig as useWagmiConfig } from "wagmi";

export default function WithdrawCard(): React.ReactElement {
const { evmChains, ibcChains } = useConfig();
const wagmiConfig = useWagmiConfig();
const { addNotification } = useNotifications();
const { provider } = useEthWallet();

const {
evmAccountAddress: fromAddress,
Expand Down Expand Up @@ -164,7 +164,7 @@ export default function WithdrawCard(): React.ReactElement {
}

const recipientAddress = recipientAddressOverride || ibcAccountAddress;
if (!provider || !fromAddress || !recipientAddress) {
if (!fromAddress || !recipientAddress) {
addNotification({
toastOpts: {
toastType: NotificationType.WARNING,
Expand Down Expand Up @@ -194,13 +194,16 @@ export default function WithdrawCard(): React.ReactElement {
selectedEvmCurrency.erc20ContractAddress ||
selectedEvmCurrency.nativeTokenWithdrawerContractAddress ||
"";
const withdrawerSvc = getAstriaWithdrawerService(
provider,
if (!contractAddress) {
throw new Error("No contract address found");
}
const withdrawerSvc = createWithdrawerService(
wagmiConfig,
contractAddress,
Boolean(selectedEvmCurrency.erc20ContractAddress),
);
await withdrawerSvc.withdrawToIbcChain(
fromAddress,
selectedEvmChain.chainId,
recipientAddress,
amount,
selectedEvmCurrency.coinDecimals,
Expand Down Expand Up @@ -325,7 +328,7 @@ export default function WithdrawCard(): React.ReactElement {
Address: {fromAddress}
</p>
)}
{fromAddress && !isLoadingEvmBalance && (
{fromAddress && selectedEvmCurrency && !isLoadingEvmBalance && (
<p className="mt-2 has-text-grey-lighter has-text-weight-semibold">
Balance: {evmBalance}
</p>
Expand Down
14 changes: 9 additions & 5 deletions web/src/config/chainConfigs/ChainConfigsDawn.ts
Original file line number Diff line number Diff line change
Expand Up @@ -192,7 +192,8 @@ const NeutronChainInfo: IbcChainInfo = {
// Coin denomination to be displayed to the user.
coinDenom: "dTIA",
// Actual denom (i.e. uatom, uscrt) used by the blockchain.
coinMinimalDenom: "factory/neutron1tkr6mtll5e2z53ze2urnc3ld3tq3dam2rchezc5lg9c237ft66gqtw94jm/drop",
coinMinimalDenom:
"factory/neutron1tkr6mtll5e2z53ze2urnc3ld3tq3dam2rchezc5lg9c237ft66gqtw94jm/drop",
// # of decimal points to convert minimal denomination to user-facing denomination.
coinDecimals: 6,
// (Optional) Keplr can show the fiat value of the coin if a coingecko id is provided.
Expand Down Expand Up @@ -223,7 +224,8 @@ const NeutronChainInfo: IbcChainInfo = {
// Coin denomination to be displayed to the user.
coinDenom: "dTIA",
// Actual denom (i.e. uatom, uscrt) used by the blockchain.
coinMinimalDenom: "factory/neutron1tkr6mtll5e2z53ze2urnc3ld3tq3dam2rchezc5lg9c237ft66gqtw94jm/drop",
coinMinimalDenom:
"factory/neutron1tkr6mtll5e2z53ze2urnc3ld3tq3dam2rchezc5lg9c237ft66gqtw94jm/drop",
// # of decimal points to convert minimal denomination to user-facing denomination.
coinDecimals: 6,
// (Optional) Keplr can show the fiat value of the coin if a coingecko id is provided.
Expand All @@ -240,7 +242,8 @@ const NeutronChainInfo: IbcChainInfo = {
// Coin denomination to be displayed to the user.
coinDenom: "dTIA",
// Actual denom (i.e. nria, uscrt) used by the blockchain.
coinMinimalDenom: "factory/neutron1tkr6mtll5e2z53ze2urnc3ld3tq3dam2rchezc5lg9c237ft66gqtw94jm/drop",
coinMinimalDenom:
"factory/neutron1tkr6mtll5e2z53ze2urnc3ld3tq3dam2rchezc5lg9c237ft66gqtw94jm/drop",
// # of decimal points to convert minimal denomination to user-facing denomination.
coinDecimals: 6,
// (Optional) Keplr can show the fiat value of the coin if a coingecko id is provided.
Expand Down Expand Up @@ -290,12 +293,13 @@ const FlameChainInfo: EvmChainInfo = {
},
{
coinDenom: "dTIA",
coinMinimalDenom: "factory/neutron1tkr6mtll5e2z53ze2urnc3ld3tq3dam2rchezc5lg9c237ft66gqtw94jm/drop",
coinMinimalDenom:
"factory/neutron1tkr6mtll5e2z53ze2urnc3ld3tq3dam2rchezc5lg9c237ft66gqtw94jm/drop",
coinDecimals: 18,
erc20ContractAddress: "0x0F0C3207a9fE9B7e8AaE4bb83E865C91A13Fd8a7",
ibcWithdrawalFeeWei: "10000000000000000",
iconClass: "i-celestia",
}
},
],
iconClass: "i-flame",
};
Expand Down
4 changes: 2 additions & 2 deletions web/src/config/chainConfigs/ChainConfigsDusk.ts
Original file line number Diff line number Diff line change
Expand Up @@ -202,7 +202,7 @@ const FlameChainInfo: EvmChainInfo = {
// address of erc20 contract on dusk-11
erc20ContractAddress: "0xa4f59B3E97EC22a2b949cB5b6E8Cd6135437E857",
// this value would only exist for native tokens
nativeTokenWithdrawerContractAddress: "",
// nativeTokenWithdrawerContractAddress: "",
ibcWithdrawalFeeWei: "10000000000000000",
iconClass: "i-noble",
},
Expand All @@ -213,7 +213,7 @@ const FlameChainInfo: EvmChainInfo = {
// NOTE - there is not actually a contract for this fakeTIA.
// just using this for testing the UI.
erc20ContractAddress: "0xFc83F6A786728F448481B7D7d5C0659A92a62C4d",
nativeTokenWithdrawerContractAddress: "",
// nativeTokenWithdrawerContractAddress: "",
ibcWithdrawalFeeWei: "10000000000000000",
iconClass: "i-celestia",
},
Expand Down
2 changes: 2 additions & 0 deletions web/src/config/chainConfigs/ChainConfigsLocal.ts
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,7 @@ export const ibcChains: IbcChains = {
const FlameChainInfo: EvmChainInfo = {
chainId: 912559,
chainName: "Flame (local)",
rpcUrls: ["http://localhost:8545"], // TODO
currencies: [
{
coinDenom: "RIA",
Expand All @@ -204,6 +205,7 @@ const FlameChainInfo: EvmChainInfo = {
const FakeChainInfo: EvmChainInfo = {
chainId: 912559,
chainName: "FakeChain (local)",
rpcUrls: ["http://localhost:8545"], // TODO
currencies: [
{
coinDenom: "FAKE",
Expand Down
54 changes: 51 additions & 3 deletions web/src/config/chainConfigs/types.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import type { ChainInfo } from "@keplr-wallet/types";
import type { Chain } from "@rainbow-me/rainbowkit";

/**
* Represents information about an IBC chain.
Expand Down Expand Up @@ -51,10 +52,57 @@ export type EvmChainInfo = {
chainId: number;
chainName: string;
currencies: EvmCurrency[];
rpcUrls?: string[];
rpcUrls: string[];
iconClass?: string;
blockExplorerUrl?: string;
};

/**
* Converts an EvmChainInfo object to a Chain object for use with RainbowKit.
* @param evmChain
*/
export function evmChainToRainbowKitChain(evmChain: EvmChainInfo): Chain {
const nativeCurrency = evmChain.currencies[0];
const chain: Chain = {
id: evmChain.chainId,
name: evmChain.chainName,
rpcUrls: {
default: { http: evmChain.rpcUrls },
},
nativeCurrency: {
name: nativeCurrency.coinDenom,
symbol: nativeCurrency.coinDenom,
decimals: nativeCurrency.coinDecimals,
},
};

if (evmChain.blockExplorerUrl) {
chain.blockExplorers = {
default: {
name: evmChain.chainName,
url: evmChain.blockExplorerUrl,
},
};
}

return chain;
}

/**
* Converts a map of EVM chains to an array of Chain objects for use with RainbowKit.
* @param evmChains
*/
export function evmChainsToRainbowKitChains(
evmChains: EvmChains,
): readonly [Chain, ...Chain[]] {
if (!evmChains || Object.keys(evmChains).length === 0) {
throw new Error("At least one chain must be provided");
}
return Object.values(evmChains).map((evmChain) =>
evmChainToRainbowKitChain(evmChain),
) as [Chain, ...Chain[]];
}

/**
* Represents information about a currency used in an EVM chain.
*/
Expand All @@ -63,9 +111,9 @@ export type EvmCurrency = {
coinMinimalDenom: string;
coinDecimals: number;
// contract address if this is a ERC20 token
erc20ContractAddress?: string;
erc20ContractAddress?: `0x${string}`;
// contract address if this a native token
nativeTokenWithdrawerContractAddress?: string;
nativeTokenWithdrawerContractAddress?: `0x${string}`;
// fee needed to pay for the ibc withdrawal, 18 decimals
ibcWithdrawalFeeWei: string;
iconClass?: string;
Expand Down
1 change: 1 addition & 0 deletions web/src/config/config.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ describe("Chain Configs", () => {
"Test EVM Chain": {
chainId: 1234,
chainName: "Test EVM Chain",
rpcUrls: ["https://rpc.test.com"],
currencies: [
{
coinDenom: "TEST",
Expand Down
Loading

0 comments on commit bd35e21

Please sign in to comment.