Skip to content

Commit

Permalink
Axelar config and handle mobile bridge integration wallets (#917)
Browse files Browse the repository at this point in the history
* move axl transfer fee

* Filter non-mobile-enabled wallets

* remove tokenMinAmount because coinMinimalDenom already exists

* create a sourceChainConfig object to avoid rerunning find

Co-authored-by: Jeremy Parish <jeremyparish69@gmail.com>
  • Loading branch information
jonator and JeremyParish69 authored Oct 22, 2022
1 parent 726fc68 commit 553ca93
Show file tree
Hide file tree
Showing 13 changed files with 121 additions and 67 deletions.
4 changes: 0 additions & 4 deletions packages/web/config/ibc-assets.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,6 @@ export const IBCAssetInfos: (IBCAsset & {
wallets: ["metamask" as const, "walletconnect" as const],
method: "deposit-address" as const,
sourceChains: [AxelarSourceChainConfigs.usdc.ethereum],
tokenMinDenom: IS_TESTNET ? "uausdc" : "uusdc", // test: "uausdc"
transferFeeMinAmount: IS_TESTNET ? "150000" : "10500000", // From https://docs.axelar.dev/resources/mainnet#cross-chain-relayer-gas-fee
},
},
{
Expand All @@ -56,8 +54,6 @@ export const IBCAssetInfos: (IBCAsset & {
wallets: ["metamask" as const, "walletconnect" as const],
method: "deposit-address" as const,
sourceChains: [AxelarSourceChainConfigs.weth.ethereum],
tokenMinDenom: IS_TESTNET ? "weth-wei" : "weth-wei",
transferFeeMinAmount: IS_TESTNET ? "60000000000000" : "6300000000000000",
},
},
{
Expand Down
1 change: 1 addition & 0 deletions packages/web/hooks/ui-config/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,4 @@ export * from "./use-fake-fee-config";
export * from "./use-remove-liquidity-config";
export * from "./use-slippage-config";
export * from "./use-trade-token-in-config";
export * from "./use-transfer-config";
35 changes: 35 additions & 0 deletions packages/web/hooks/ui-config/use-transfer-config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import { useState, useEffect } from "react";
import { AccountSetBase } from "@keplr-wallet/stores";
import {
ObservableAssets,
ObservableTransferUIConfig,
} from "../../stores/assets";
import { makeLocalStorageKVStore } from "../../stores/kv-store";
import { useWindowSize } from "../window";

export function useTransferConfig(
assetsStore: ObservableAssets,
account: AccountSetBase
) {
const { isMobile } = useWindowSize();

const [transferConfig, setTransferConfig] =
useState<ObservableTransferUIConfig | null>(null);
const [transferKvStore] = useState(() =>
makeLocalStorageKVStore("transfer-ui-config")
);
useEffect(
() =>
setTransferConfig(
new ObservableTransferUIConfig(
assetsStore,
account,
transferKvStore,
isMobile
)
),
[assetsStore, account, isMobile]
);

return transferConfig;
}
6 changes: 3 additions & 3 deletions packages/web/integrations/axelar/hooks/use-deposit-address.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ export function useDepositAddress(
sourceChain: string,
destChain: string,
address: string | undefined,
tokenMinDenom: string,
coinMinimalDenom: string,
generateOnMount = true,
environment = Environment.MAINNET
): {
Expand All @@ -20,7 +20,7 @@ export function useDepositAddress(
if (address && depositAddress === null) {
setIsLoading(true);
new AxelarAssetTransfer({ environment })
.getDepositAddress(sourceChain, destChain, address, tokenMinDenom)
.getDepositAddress(sourceChain, destChain, address, coinMinimalDenom)
.then((generatedAddress) => {
setDepositAddress(generatedAddress);
})
Expand All @@ -36,7 +36,7 @@ export function useDepositAddress(
address,
sourceChain,
destChain,
tokenMinDenom,
coinMinimalDenom,
setIsLoading,
]);

Expand Down
7 changes: 7 additions & 0 deletions packages/web/integrations/axelar/source-chain-config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,31 +17,37 @@ export const SourceChainConfigs: {
? "0x526f0A95EDC3DF4CBDB7bb37d4F7Ed451dB8e369"
: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48", // test: 'aUSDC' on metamask/etherscan
logoUrl: "/networks/ethereum.svg",
transferFeeMinAmount: IS_TESTNET ? "150000" : "10500000", // From https://docs.axelar.dev/resources/mainnet#cross-chain-relayer-gas-fee
},
bnbChain: {
id: "Binance" as const,
erc20ContractAddress: "0x4268B8F0B87b6Eae5d897996E6b845ddbD99Adf3",
logoUrl: "/networks/binance.svg",
transferFeeMinAmount: IS_TESTNET ? "150000" : "1500000",
},
avalanche: {
id: "Avalanche" as const,
erc20ContractAddress: "0xfaB550568C688d5D8A52C7d794cb93Edc26eC0eC",
logoUrl: "/networks/avalanche.svg",
transferFeeMinAmount: IS_TESTNET ? "150000" : "1500000",
},
polygon: {
id: "Polygon" as const,
erc20ContractAddress: "0x750e4C4984a9e0f12978eA6742Bc1c5D248f40ed",
logoUrl: "/networks/polygon.svg",
transferFeeMinAmount: IS_TESTNET ? "150000" : "1500000",
},
fantom: {
id: "Fantom" as const,
erc20ContractAddress: "0x1B6382DBDEa11d97f24495C9A90b7c88469134a4",
logoUrl: "/networks/fantom.svg",
transferFeeMinAmount: IS_TESTNET ? "150000" : "1500000",
},
moonbeam: {
id: "Moonbeam" as const,
erc20ContractAddress: "0xCa01a1D0993565291051daFF390892518ACfAD3A",
logoUrl: "/networks/moonbeam.svg",
transferFeeMinAmount: IS_TESTNET ? "150000" : "1500000",
},
},
weth: {
Expand All @@ -53,6 +59,7 @@ export const SourceChainConfigs: {
? "0xc778417E063141139Fce010982780140Aa0cD5Ab"
: "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2",
logoUrl: "/networks/ethereum.svg",
transferFeeMinAmount: IS_TESTNET ? "60000000000000" : "6300000000000000",
},
},
};
14 changes: 7 additions & 7 deletions packages/web/integrations/axelar/transfer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -56,8 +56,6 @@ const AxelarTransfer: FunctionComponent<
selectedSourceChainKey,
onRequestClose,
onRequestSwitchWallet,
tokenMinDenom,
transferFeeMinAmount,
sourceChains,
isTestNet = process.env.NEXT_PUBLIC_IS_TESTNET === "true",
connectCosmosWalletButtonOverride,
Expand Down Expand Up @@ -98,9 +96,11 @@ const AxelarTransfer: FunctionComponent<
EthClientChainIds_AxelarChainIdsMap[selectedSourceChainKey] ??
selectedSourceChainKey;

const erc20ContractAddress = sourceChains.find(
({ id }) => id === selectedSourceChainKey
)?.erc20ContractAddress;
const sourceChainConfig = sourceChains.find( ({ id }) => id === selectedSourceChainKey );

const erc20ContractAddress = sourceChainConfig?.erc20ContractAddress;
const transferFeeMinAmount = sourceChainConfig?.transferFeeMinAmount ?? "0";

const axelarChainId =
chainStore.getChainFromCurrency(originCurrency.coinDenom)?.chainId ||
"axelar-dojo-1";
Expand Down Expand Up @@ -222,15 +222,15 @@ const AxelarTransfer: FunctionComponent<
sourceChain,
destChain,
isWithdraw || correctChainSelected ? address : undefined,
tokenMinDenom,
originCurrency.coinMinimalDenom,
undefined,
isTestNet ? Environment.TESTNET : Environment.MAINNET
);

// notify user they are withdrawing into a different account then they last deposited to
const [lastDepositAccountAddress, setLastDepositAccountAddress] =
useLocalStorageState<string | null>(
`axelar-last-deposit-addr-${tokenMinDenom}`,
`axelar-last-deposit-addr-${originCurrency.coinMinimalDenom}`,
null
);
const warnOfDifferentDepositAddress =
Expand Down
13 changes: 7 additions & 6 deletions packages/web/integrations/axelar/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,6 @@ export interface AxelarBridgeConfig {
/** Ex: `uusdc`. NOTE: Will get currency info from `originCurrency` on the IBC balance (from registrar).
* See: https://docs.axelar.dev/resources/mainnet#assets
*/
tokenMinDenom: string;
/** Amount of Axelar transfer fee in `originCurrency`.
* TODO: use `useTransferFeeQuery` should fees become dynamic and once APIs become production ready.
* See calculator tool on Axelar docs to get current fee constants: https://docs.axelar.dev/resources/mainnet#cross-chain-relayer-gas-fee.
*/
transferFeeMinAmount: string;
}

/** See: https://docs.axelar.dev/dev/build/chain-names/mainnet
Expand Down Expand Up @@ -61,4 +55,11 @@ export type SourceChainConfig = {
};

logoUrl: string;

/** Amount of Axelar transfer fee in `originCurrency`.
* TODO: use `useTransferFeeQuery` should fees become dynamic and once APIs become production ready.
* See calculator tool on Axelar docs to get current fee constants: https://docs.axelar.dev/resources/mainnet#cross-chain-relayer-gas-fee.
*/
transferFeeMinAmount: string;

};
1 change: 1 addition & 0 deletions packages/web/integrations/ethereum/metamask.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ const IS_TESTNET = process.env.NEXT_PUBLIC_IS_TESTNET === "true";

export class ObservableMetamask implements EthWallet {
readonly key: WalletKey = "metamask";
readonly mobileEnabled = false;

readonly displayInfo: WalletDisplay = {
iconUrl: "/icons/metamask-fox.svg",
Expand Down
3 changes: 2 additions & 1 deletion packages/web/integrations/ethereum/walletconnect.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@ const CONNECTED_ACCOUNT_KEY = "wc-eth-connected-account";
const CONNECTED_ACCOUNT_CHAINID = "wc-eth-connected-chainId";

export class ObservableWalletConnect implements EthWallet {
key: WalletKey = "walletconnect";
readonly key: WalletKey = "walletconnect";
readonly mobileEnabled = false;

displayInfo: WalletDisplay = {
iconUrl: "/icons/walletconnect.svg",
Expand Down
3 changes: 3 additions & 0 deletions packages/web/integrations/wallets.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@ export interface Wallet<
readonly key: WalletKey;
readonly displayInfo: WalletDisplay;

/** Works on mobile browsers. */
readonly mobileEnabled: boolean;

readonly accountAddress?: string;
/** Human readable chain, falls back to hex ID (`0x...`) if unknown. */
readonly chainId?: string;
Expand Down
43 changes: 30 additions & 13 deletions packages/web/modals/connect-non-ibc-wallet.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,14 @@ export const ConnectNonIbcWallet: FunctionComponent<
onSelectWallet: (key: string) => void;
}
> = observer((props) => {
const { initiallySelectedWalletId, isWithdraw, wallets, onSelectWallet } =
props;

const [selectedWalletKey, setSelectedWalletId] = useState<string | null>(
props.initiallySelectedWalletId ?? null
initiallySelectedWalletId ?? null
);

const selectedWallet = props.wallets.find((w) => w.key === selectedWalletKey);
const selectedWallet = wallets.find((w) => w.key === selectedWalletKey);
const canOnboardSelectedWallet =
selectedWallet && !selectedWallet.isInstalled && selectedWallet.onboard;

Expand All @@ -28,12 +31,13 @@ export const ConnectNonIbcWallet: FunctionComponent<
className: "h-14 md:w-full w-96 mt-3 mx-auto !px-1",
size: "lg",
disabled:
props.initiallySelectedWalletId === undefined && !selectedWalletKey,
(initiallySelectedWalletId === undefined && !selectedWalletKey) ||
wallets.length === 0,
onClick: () => {
if (canOnboardSelectedWallet) {
selectedWallet!.onboard?.();
} else if (selectedWalletKey) {
props.onSelectWallet(selectedWalletKey);
onSelectWallet(selectedWalletKey);
} else {
console.error(
"Wallet selection invalid state: selectedWalletKey undefined"
Expand All @@ -44,6 +48,8 @@ export const ConnectNonIbcWallet: FunctionComponent<
<h6 className="md:text-base text-lg">
{canOnboardSelectedWallet
? `Install ${selectedWallet.displayInfo.displayName}`
: wallets.length === 0
? "None available"
: "Next"}
</h6>
),
Expand All @@ -56,19 +62,30 @@ export const ConnectNonIbcWallet: FunctionComponent<
<ModalBase
{...props}
isOpen={props.isOpen && showModalBase}
title={props.isWithdraw ? "Withdraw to" : "Deposit from"}
title={isWithdraw ? "Withdraw to" : "Deposit from"}
>
<div className="grid grid-cols-3 md:grid-cols-2 gap-4 m-4">
{props.wallets.map((wallet, i) => (
{props.wallets.length === 0 ? (
<WalletCard
key={i}
id={wallet.key}
{...wallet.displayInfo}
isConnected={wallet.isConnected}
isSelected={wallet.key === selectedWalletKey}
onClick={() => setSelectedWalletId(wallet.key)}
className="opacity-30"
id="placeholder"
displayName="None"
iconUrl="/icons/error-x.svg"
/>
))}
) : (
<>
{wallets.map((wallet, i) => (
<WalletCard
key={i}
id={wallet.key}
{...wallet.displayInfo}
isConnected={wallet.isConnected}
isSelected={wallet.key === selectedWalletKey}
onClick={() => setSelectedWalletId(wallet.key)}
/>
))}
</>
)}
</div>
{accountActionButton}
</ModalBase>
Expand Down
Loading

2 comments on commit 553ca93

@vercel
Copy link

@vercel vercel bot commented on 553ca93 Oct 22, 2022

Choose a reason for hiding this comment

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

@vercel
Copy link

@vercel vercel bot commented on 553ca93 Oct 22, 2022

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.