Skip to content

Commit

Permalink
Upgrade Wagmi and RainbowKit (#89)
Browse files Browse the repository at this point in the history
- Upgrade repo to yarn 4
- Upgrade wagmi and rainbowkit versions
- Use Viem instead of Ethers for tx sending
- Refactor wallet/hooks.ts into smaller protocol-specific files
- Fix small cosmos metadata issue
  • Loading branch information
jmrossy authored Dec 19, 2023
1 parent ea94576 commit badec99
Show file tree
Hide file tree
Showing 35 changed files with 6,775 additions and 6,081 deletions.
5 changes: 5 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -38,4 +38,9 @@
},
"editor.tabSize": 2,
"editor.detectIndentation": false,
"[typescript][typescriptreact]": {
"editor.codeActionsOnSave": {
"source.organizeImports": "explicit"
}
},
}
785 changes: 0 additions & 785 deletions .yarn/releases/yarn-3.2.0.cjs

This file was deleted.

893 changes: 893 additions & 0 deletions .yarn/releases/yarn-4.0.2.cjs

Large diffs are not rendered by default.

8 changes: 7 additions & 1 deletion .yarnrc.yml
Original file line number Diff line number Diff line change
@@ -1,7 +1,13 @@
compressionLevel: mixed

enableGlobalCache: false

enableScripts: false

nodeLinker: node-modules

plugins:
- path: .yarn/plugins/@yarnpkg/plugin-outdated.cjs
spec: "https://mskelton.dev/yarn-outdated/v3"

yarnPath: .yarn/releases/yarn-3.2.0.cjs
yarnPath: .yarn/releases/yarn-4.0.2.cjs
2 changes: 1 addition & 1 deletion next.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ const securityHeaders = [
key: 'Content-Security-Policy',
value: `default-src 'self'; script-src 'self'${
isDev ? " 'unsafe-eval'" : ''
}; connect-src *; img-src 'self' data: https://*.walletconnect.com; style-src 'self' 'unsafe-inline' https://*.googleapis.com; font-src 'self' data:; base-uri 'self'; form-action 'self'; frame-src 'self' https://*.solflare.com https://*.walletconnect.com;`,
}; connect-src *; img-src 'self' data: https://*.walletconnect.com; style-src 'self' 'unsafe-inline' https://*.googleapis.com; font-src 'self' data:; base-uri 'self'; form-action 'self'; frame-src 'self' https://*.solflare.com https://*.walletconnect.com https://*.walletconnect.org;`,
},
]

Expand Down
22 changes: 12 additions & 10 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "@hyperlane-xyz/warp-ui-template",
"description": "A web app template for building Hyperlane Warp Route UIs",
"version": "3.1.0-beta4",
"version": "3.4.0",
"author": "J M Rossy",
"dependencies": {
"@chakra-ui/next-js": "^2.1.5",
Expand All @@ -16,29 +16,29 @@
"@emotion/react": "^11.11.1",
"@emotion/styled": "^11.11.0",
"@headlessui/react": "^1.7.14",
"@hyperlane-xyz/sdk": "^3.1.0-beta4",
"@hyperlane-xyz/utils": "^3.1.0-beta4",
"@hyperlane-xyz/widgets": "^1.5.0",
"@hyperlane-xyz/sdk": "^3.4.0",
"@hyperlane-xyz/utils": "^3.4.0",
"@hyperlane-xyz/widgets": "^3.1.4",
"@metamask/jazzicon": "https://github.com/jmrossy/jazzicon#7a8df28974b4e81129bfbe3cab76308b889032a6",
"@rainbow-me/rainbowkit": "0.12.16",
"@rainbow-me/rainbowkit": "1.3.0",
"@solana/spl-token": "^0.3.8",
"@solana/wallet-adapter-base": "^0.9.22",
"@solana/wallet-adapter-react": "^0.15.32",
"@solana/wallet-adapter-react-ui": "^0.9.31",
"@solana/wallet-adapter-wallets": "^0.19.16",
"@solana/web3.js": "^1.77.0",
"@tanstack/react-query": "^4.29.7",
"bignumber.js": "^9.0.2",
"bignumber.js": "^9.1.1",
"buffer": "^6.0.3",
"cosmjs-types": "^0.9.0",
"ethers": "^5.7.2",
"formik": "^2.2.9",
"framer-motion": "^10.16.4",
"next": "^13.2.4",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-toastify": "^9.1.3",
"wagmi": "0.12.18",
"viem": "1.20.0",
"wagmi": "^1.4.12",
"zod": "^3.21.4",
"zustand": "^4.3.9"
},
Expand Down Expand Up @@ -67,7 +67,7 @@
"homepage": "https://www.hyperlane.xyz",
"license": "Apache-2.0",
"main": "dist/src/index.js",
"packageManager": "yarn@3.2.0",
"packageManager": "yarn@4.0.2",
"private": true,
"repository": {
"type": "git",
Expand All @@ -87,6 +87,8 @@
"resolutions": {
"ethers": "^5.7",
"zustand": "^4.4",
"bn.js": "^5.2"
"bn.js": "^5.2",
"viem": "1.20.0",
"lit-html": "2.8.0"
}
}
2 changes: 1 addition & 1 deletion src/components/buttons/ConnectAwareSubmitButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { useCallback } from 'react';
import { ProtocolType } from '@hyperlane-xyz/utils';

import { tryGetProtocolType } from '../../features/caip/chains';
import { useAccountForChain, useConnectFns } from '../../features/wallet/hooks';
import { useAccountForChain, useConnectFns } from '../../features/wallet/hooks/multiProtocol';
import { useTimeout } from '../../utils/timeout';

import { SolidButton } from './SolidButton';
Expand Down
1 change: 1 addition & 0 deletions src/consts/values.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
export const EVM_ZERO_ADDRESS = '0x0000000000000000000000000000000000000000';
export const SOL_ZERO_ADDRESS = '00000000000000000000000000000000000000000000';
export const COSMOS_ZERO_ADDRESS = 'cosmos100000000000000000000000000000000000000';
// Strangely, this is not included in any of the Solana packages
Expand Down
6 changes: 2 additions & 4 deletions src/features/caip/tokens.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
import { ethers } from 'ethers';

import { ProtocolType, isValidAddress, isZeroishAddress } from '@hyperlane-xyz/utils';

import { COSMOS_ZERO_ADDRESS, SOL_ZERO_ADDRESS } from '../../consts/values';
import { COSMOS_ZERO_ADDRESS, EVM_ZERO_ADDRESS, SOL_ZERO_ADDRESS } from '../../consts/values';
import { logger } from '../../utils/logger';

export enum AssetNamespace {
Expand Down Expand Up @@ -84,7 +82,7 @@ export function isNativeToken(id: TokenCaip19Id): boolean {

export function getNativeTokenAddress(protocol: ProtocolType): Address {
if (protocol === ProtocolType.Ethereum) {
return ethers.constants.AddressZero;
return EVM_ZERO_ADDRESS;
} else if (protocol === ProtocolType.Sealevel) {
return SOL_ZERO_ADDRESS;
} else if (protocol === ProtocolType.Cosmos) {
Expand Down
6 changes: 2 additions & 4 deletions src/features/chains/cosmosDefault.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,8 @@ export const cosmosDefaultChain: ChainMetadata = {
domainId: 1234, // TODO
bech32Prefix: 'cosmos',
slip44: 118,
rpcUrls: [
{ http: 'https://rpc-cosmoshub.blockapsis.com' },
{ http: 'https://lcd-cosmoshub.blockapsis.com' },
],
rpcUrls: [{ http: 'https://rpc-cosmoshub.blockapsis.com' }],
restUrls: [{ http: 'https://lcd-cosmoshub.blockapsis.com' }],
nativeToken: {
name: 'Atom',
symbol: 'ATOM',
Expand Down
14 changes: 8 additions & 6 deletions src/features/chains/metadata.ts
Original file line number Diff line number Diff line change
Expand Up @@ -71,12 +71,14 @@ export function getCosmosKitConfig(): { chains: CosmosChain[]; assets: AssetList
provider: c.displayName || c.name,
},
],
rest: [
{
address: c.rpcUrls[1].http,
provider: c.displayName || c.name,
},
],
rest: c.restUrls
? [
{
address: c.restUrls[0].http,
provider: c.displayName || c.name,
},
]
: [],
},
fees: {
fee_tokens: [
Expand Down
1 change: 1 addition & 0 deletions src/features/multiProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ export function getMultiProvider() {
export function getEvmProvider(id: ChainCaip2Id) {
const { reference, protocol } = parseCaip2Id(id);
if (protocol !== ProtocolType.Ethereum) throw new Error('Expected EVM chain for provider');
// TODO viem
return getMultiProvider().getEthersV5Provider(reference);
}

Expand Down
2 changes: 1 addition & 1 deletion src/features/tokens/SelectOrInputTokenIds.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { useFormikContext } from 'formik';
import { TextField } from '../../components/input/TextField';
import { AssetNamespace, getCaip19Id } from '../caip/tokens';
import { TransferFormValues } from '../transfer/types';
import { useAccountAddressForChain } from '../wallet/hooks';
import { useAccountAddressForChain } from '../wallet/hooks/multiProtocol';

import { SelectTokenIdField } from './SelectTokenIdField';
import { useContractSupportsTokenByOwner, useIsSenderNftOwner } from './balances';
Expand Down
2 changes: 1 addition & 1 deletion src/features/tokens/approval.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { logger } from '../../utils/logger';
import { getProtocolType } from '../caip/chains';
import { getTokenAddress, isNativeToken, isNonFungibleToken } from '../caip/tokens';
import { getEvmProvider } from '../multiProvider';
import { useAccountAddressForChain } from '../wallet/hooks';
import { useAccountAddressForChain } from '../wallet/hooks/multiProtocol';

import { getErc20Contract, getErc721Contract } from './contracts/evmContracts';
import { Route } from './routes/types';
Expand Down
2 changes: 1 addition & 1 deletion src/features/tokens/balances.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import { parseCaip19Id, tryGetChainIdFromToken } from '../caip/tokens';
import { getEvmProvider } from '../multiProvider';
import { useStore } from '../store';
import { TransferFormValues } from '../transfer/types';
import { useAccountAddressForChain } from '../wallet/hooks';
import { useAccountAddressForChain } from '../wallet/hooks/multiProtocol';

import { AdapterFactory } from './AdapterFactory';
import { getHypErc721Contract } from './contracts/evmContracts';
Expand Down
4 changes: 2 additions & 2 deletions src/features/tokens/routes/utils.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { utils as ethersUtils } from 'ethers';
import { deepCopy } from '@hyperlane-xyz/utils';

import { isNativeToken } from '../../caip/tokens';

Expand Down Expand Up @@ -85,7 +85,7 @@ export function isIbcToWarpRoute(route: Route): route is IbcToWarpRoute {
}

export function mergeRoutes(routes: RoutesMap, newRoutes: Route[]) {
const mergedRoutes = ethersUtils.deepCopy(routes);
const mergedRoutes = deepCopy(routes);
for (const route of newRoutes) {
mergedRoutes[route.originCaip2Id] ||= {};
mergedRoutes[route.originCaip2Id][route.destCaip2Id] ||= [];
Expand Down
4 changes: 2 additions & 2 deletions src/features/transfer/TransferTokenForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ import { getToken } from '../tokens/metadata';
import { useRouteChains } from '../tokens/routes/hooks';
import { RoutesMap, WarpRoute } from '../tokens/routes/types';
import { getTokenRoute, isIbcOnlyRoute, isRouteFromNative } from '../tokens/routes/utils';
import { useAccountAddressForChain } from '../wallet/hooks';
import { useAccountAddressForChain } from '../wallet/hooks/multiProtocol';

import { TransferFormValues } from './types';
import { useIgpQuote } from './useIgpQuote';
Expand Down Expand Up @@ -343,7 +343,7 @@ function ButtonSection({
color="gray"
onClick={() => setIsReview(false)}
classes="px-6 py-1.5"
icon={<ChevronIcon direction="w" width={13} color={Color.primaryBlue} />}
icon={<ChevronIcon direction="w" width={10} height={6} color={Color.primaryBlue} />}
>
<span>Edit</span>
</SolidButton>
Expand Down
2 changes: 1 addition & 1 deletion src/features/transfer/TransfersDetailsModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ import { AssetNamespace, parseCaip19Id } from '../caip/tokens';
import { getChainDisplayName, hasPermissionlessChain } from '../chains/utils';
import { getMultiProvider } from '../multiProvider';
import { getToken } from '../tokens/metadata';
import { useAccountForChain } from '../wallet/hooks';
import { useAccountForChain } from '../wallet/hooks/multiProtocol';

import { TransferContext, TransferStatus } from './types';

Expand Down
47 changes: 26 additions & 21 deletions src/features/transfer/useTokenTransfer.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
import { MsgTransferEncodeObject } from '@cosmjs/stargate';
import type { Transaction as SolTransaction } from '@solana/web3.js';
import { BigNumber, PopulatedTransaction as EvmTransaction, providers } from 'ethers';
import {
SendTransactionArgs as ViemTransactionRequest,
WaitForTransactionResult as ViemViemTransactionReceipt,
} from '@wagmi/core';
import BigNumber from 'bignumber.js';
import { PopulatedTransaction as Ethers5Transaction } from 'ethers';
import { useCallback, useState } from 'react';
import { toast } from 'react-toastify';

Expand Down Expand Up @@ -29,13 +34,13 @@ import {
isWarpRoute,
} from '../tokens/routes/utils';
import {
ActiveChainInfo,
SendTransactionFn,
getAccountAddressForChain,
useAccounts,
useActiveChains,
useTransactionFns,
} from '../wallet/hooks';
} from '../wallet/hooks/multiProtocol';
import { ActiveChainInfo, SendTransactionFn } from '../wallet/hooks/types';
import { ethers5TxToWagmiTx } from '../wallet/utils';

import { TransferContext, TransferFormValues, TransferStatus } from './types';
import { ensureSufficientCollateral, tryGetMsgIdFromEvmTransferReceipt } from './utils';
Expand Down Expand Up @@ -140,7 +145,7 @@ async function executeTransfer({
params: values,
});

const executeParams: ExecuteTransferParams<any> = {
const executeParams: ExecuteTransferParams<any, any> = {
weiAmountOrId,
originProtocol,
destinationDomainId,
Expand Down Expand Up @@ -187,7 +192,7 @@ async function executeTransfer({
if (onDone) onDone();
}

interface ExecuteTransferParams<TxResp> {
interface ExecuteTransferParams<TxReq, TxResp> {
weiAmountOrId: string;
originProtocol: ProtocolType;
destinationDomainId: DomainId;
Expand All @@ -196,14 +201,14 @@ interface ExecuteTransferParams<TxResp> {
activeAccountAddress: Address;
activeChain: ActiveChainInfo;
updateStatus: (s: TransferStatus) => void;
sendTransaction: SendTransactionFn<TxResp>;
sendTransaction: SendTransactionFn<TxReq, TxResp>;
}

interface ExecuteHypTransferParams<TxResp> extends ExecuteTransferParams<TxResp> {
interface ExecuteHypTransferParams<TxReq, TxResp> extends ExecuteTransferParams<TxReq, TxResp> {
hypTokenAdapter: IHypTokenAdapter;
}

async function executeHypTransfer(params: ExecuteTransferParams<any>) {
async function executeHypTransfer(params: ExecuteTransferParams<any, any>) {
const { tokenRoute, weiAmountOrId, originProtocol } = params;
const hypTokenAdapter = AdapterFactory.HypTokenAdapterFromRouteOrigin(tokenRoute);
const paramsWithAdapter = { ...params, hypTokenAdapter };
Expand Down Expand Up @@ -233,7 +238,7 @@ async function executeEvmTransfer({
activeChain,
updateStatus,
sendTransaction,
}: ExecuteHypTransferParams<providers.TransactionReceipt>) {
}: ExecuteHypTransferParams<ViemTransactionRequest, ViemViemTransactionReceipt>) {
if (!isWarpRoute(tokenRoute)) throw new Error('Unsupported route type');
const { baseRouterAddress, originCaip2Id, baseTokenCaip19Id } = tokenRoute;

Expand All @@ -247,11 +252,11 @@ async function executeEvmTransfer({
const approveTxRequest = (await tokenAdapter.populateApproveTx({
weiAmountOrId,
recipient: baseRouterAddress,
})) as EvmTransaction;
})) as Ethers5Transaction;

updateStatus(TransferStatus.SigningApprove);
const { confirm: confirmApprove } = await sendTransaction({
tx: approveTxRequest,
tx: ethers5TxToWagmiTx(approveTxRequest),
chainCaip2Id: originCaip2Id,
activeCap2Id: activeChain.chainCaip2Id,
});
Expand All @@ -268,18 +273,18 @@ async function executeEvmTransfer({
logger.debug('Quoted gas payment', gasPayment);
// If sending native tokens (e.g. Eth), the gasPayment must be added to the tx value and sent together
const txValue = isRouteFromNative(tokenRoute)
? BigNumber.from(gasPayment).add(weiAmountOrId.toString())
? BigNumber(gasPayment).plus(weiAmountOrId).toFixed(0)
: gasPayment;
const transferTxRequest = (await hypTokenAdapter.populateTransferRemoteTx({
weiAmountOrId: weiAmountOrId.toString(),
recipient: recipientAddress,
destination: destinationDomainId,
txValue: txValue.toString(),
})) as EvmTransaction;
txValue,
})) as Ethers5Transaction;

updateStatus(TransferStatus.SigningTransfer);
const { hash: transferTxHash, confirm: confirmTransfer } = await sendTransaction({
tx: transferTxRequest,
tx: ethers5TxToWagmiTx(transferTxRequest),
chainCaip2Id: originCaip2Id,
activeCap2Id: activeChain.chainCaip2Id,
});
Expand All @@ -301,7 +306,7 @@ async function executeSealevelTransfer({
activeChain,
updateStatus,
sendTransaction,
}: ExecuteHypTransferParams<void>) {
}: ExecuteHypTransferParams<SolTransaction, void>) {
const { originCaip2Id } = tokenRoute;

updateStatus(TransferStatus.CreatingTransfer);
Expand Down Expand Up @@ -340,15 +345,15 @@ async function executeCosmWasmTransfer({
activeChain,
updateStatus,
sendTransaction,
}: ExecuteHypTransferParams<providers.TransactionReceipt>) {
}: ExecuteHypTransferParams<any, void>) {
updateStatus(TransferStatus.CreatingTransfer);

const transferTxRequest = (await hypTokenAdapter.populateTransferRemoteTx({
const transferTxRequest = await hypTokenAdapter.populateTransferRemoteTx({
weiAmountOrId,
recipient: recipientAddress,
destination: destinationDomainId,
txValue: COSM_IGP_QUOTE,
})) as EvmTransaction;
});

updateStatus(TransferStatus.SigningTransfer);
const { hash: transferTxHash, confirm: confirmTransfer } = await sendTransaction({
Expand All @@ -372,7 +377,7 @@ async function executeIbcTransfer({
activeAccountAddress,
updateStatus,
sendTransaction,
}: ExecuteTransferParams<providers.TransactionReceipt>) {
}: ExecuteTransferParams<any, void>) {
if (!isIbcRoute(tokenRoute)) throw new Error('Unsupported route type');
updateStatus(TransferStatus.CreatingTransfer);

Expand Down
Loading

1 comment on commit badec99

@vercel
Copy link

@vercel vercel bot commented on badec99 Dec 19, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.