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

Add support for MetaMask mobile wallet #837

Merged
merged 9 commits into from
Oct 21, 2024
Merged
2,232 changes: 1,055 additions & 1,177 deletions package-lock.json

Large diffs are not rendered by default.

7 changes: 4 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
"@testing-library/jest-dom": "^6.5.0",
"@testing-library/svelte": "^5.2.1",
"@testing-library/user-event": "^14.5.2",
"@types/d3-array": "^3.2.1",
"@types/d3-time": "^3.0.3",
"@types/eslint": "^9.6.1",
"@typescript-eslint/eslint-plugin": "^8.7.0",
Expand Down Expand Up @@ -57,13 +58,13 @@
},
"dependencies": {
"@aave/math-utils": "^1.30.2",
"@reown/appkit": "^1.1.5",
"@reown/appkit-adapter-wagmi": "^1.1.5",
"@sentry/sveltekit": "^8.32.0",
"@trading-strategy-ai/web-top-node": "^0.1.0-beta.10",
"@tryghost/content-api": "^1.11.21",
"@types/d3-array": "^3.2.1",
"@wagmi/connectors": "^5.1.14",
"@wagmi/connectors": "^5.2.1",
"@wagmi/core": "^2.13.8",
"@web3modal/wagmi": "4.1.7",
"bignumber.js": "^9.1.2",
"cookie": "^0.6.0",
"d3-array": "^3.2.4",
Expand Down
5 changes: 5 additions & 0 deletions src/lib/eth-defi/enzyme.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,11 @@ export type AssetWithdrawl = {
amount: bigint;
};

export type AssetWithdrawlEvent = {
eventName: 'AssetWithdrawn';
args: AssetWithdrawl;
};

type GetRedemptionParams = {
withdrawl: AssetWithdrawl;
denominationToken: GetTokenBalanceReturnType;
Expand Down
19 changes: 9 additions & 10 deletions src/lib/helpers/chain.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
import type { Chain as WalletChain } from 'viem';

// TODO: move to zod schema in lib/schemas
export type ApiChain = {
chain_id: number;
Expand All @@ -8,12 +6,13 @@ export type ApiChain = {
chain_explorer?: string;
};

// Local cache of supported chains (helps limit API calls)
export const chains = [
{ id: 1, slug: 'ethereum', name: 'Ethereum' },
{ id: 56, slug: 'binance', name: 'BNB Smart Chain' },
{ id: 137, slug: 'polygon', name: 'Polygon' },
{ id: 43114, slug: 'avalanche', name: 'Avalanche C-chain' },
{ id: 42161, slug: 'arbitrum', name: 'Arbitrum One' }
{ id: 1, slug: 'ethereum', name: 'Ethereum', explorer: 'https://etherscan.io' },
{ id: 56, slug: 'binance', name: 'BNB Smart Chain', explorer: 'https://bscscan.com' },
{ id: 137, slug: 'polygon', name: 'Polygon', explorer: 'https://polygonscan.com' },
{ id: 43114, slug: 'avalanche', name: 'Avalanche C-chain', explorer: 'https://snowtrace.io' },
{ id: 42161, slug: 'arbitrum', name: 'Arbitrum One', explorer: 'https://arbiscan.io' }
] as const;

export type Chain = (typeof chains)[number];
Expand All @@ -26,10 +25,10 @@ export function getChain(identifier: Maybe<number | string>) {
}

/**
* Extract explorer URL from either wallet (viem) Chain object and append address or transaction path
* Extract explorer URL from Chain object and append address or transaction path
*/
export function getExplorerUrl(chain: Maybe<WalletChain>, hash: Address) {
const baseUrl = chain?.blockExplorers?.default?.url ?? 'https://blockscan.com';
export function getExplorerUrl(chain: Maybe<Chain>, hash: Address) {
const baseUrl = chain?.explorer ?? 'https://blockscan.com';

let path = '';
if (hash.length === 42) {
Expand Down
2 changes: 1 addition & 1 deletion src/lib/trade-executor/strategy/runtime-state.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
import { type StrategyConfiguration, configuredStrategies } from './configuration';
import { type StrategySummary, strategySummarySchema } from './summary';
import loadError from '../assets/load-error.jpg';
import swrCache from '$lib/swrCache.js';
import swrCache from '$lib/swrCache';

// use 5 second timeout when fetching strategy metadata
const CLIENT_TIMEOUT = 5000;
Expand Down
2 changes: 1 addition & 1 deletion src/lib/trade-executor/strategy/summary.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ export const enzymeSmartContractsSchema = z.object({
export type EnzymeSmartContracts = z.infer<typeof enzymeSmartContractsSchema>;

export const onChainDataSchema = z.object({
chain_id: chainId.nullish(),
chain_id: chainId,
asset_management_mode: assetManagementMode,
smart_contracts: enzymeSmartContractsSchema.partial(),
owner: hexString.nullish(),
Expand Down
12 changes: 5 additions & 7 deletions src/lib/wallet/ConnectWallet.svelte
Original file line number Diff line number Diff line change
@@ -1,21 +1,19 @@
<script lang="ts">
import type { ConfiguredChainId } from '$lib/wallet';
import { getChain } from '$lib/helpers/chain';
import { modal, wallet, WalletSummary } from '$lib/wallet';
import type { Chain } from '$lib/helpers/chain';
import { modal, wallet } from '$lib/wallet/client';
import WalletSummary from '$lib/wallet/WalletSummary.svelte';
import { Button } from '$lib/components';
import IconWallet from '~icons/local/wallet';

export let chainId: ConfiguredChainId | undefined;

const chain = getChain(chainId)!;
export let chain: Chain;

function connectWallet() {
modal.open({ view: 'Connect' });
}
</script>

<div class="connect-wallet">
{#if $wallet.isConnected}
{#if $wallet.status === 'connected'}
<div class="is-connected">
<WalletSummary wallet={$wallet} {chain} />
<Button size="sm" label="Change wallet" on:click={connectWallet} />
Expand Down
2 changes: 1 addition & 1 deletion src/lib/wallet/DepositBalance.svelte
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<script lang="ts">
import type { GetTokenBalanceReturnType } from '$lib/eth-defi/helpers';
import { TokenBalance } from '$lib/wallet';
import TokenBalance from '$lib/wallet/TokenBalance.svelte';

export let label: string;
export let data: MaybePromise<GetTokenBalanceReturnType>;
Expand Down
23 changes: 9 additions & 14 deletions src/lib/wallet/MyDeposits.svelte
Original file line number Diff line number Diff line change
@@ -1,19 +1,15 @@
<script lang="ts">
import type { ComponentEvents } from 'svelte';
import type { Chain } from '$lib/helpers/chain';
import type { ConnectedStrategyRuntimeState } from 'trade-executor/strategy/runtime-state';
import fsm from 'svelte-fsm';
import { goto } from '$app/navigation';
import { wizard } from 'wizard/store';
import {
type ConfiguredChain,
disconnect,
switchChain,
wallet,
DepositWarning,
DepositBalance,
VaultBalance
} from '$lib/wallet';
import { disconnect, switchChain, wallet } from '$lib/wallet/client';
import { Button, HashAddress } from '$lib/components';
import DepositWarning from '$lib/wallet/DepositWarning.svelte';
import DepositBalance from '$lib/wallet/DepositBalance.svelte';
import VaultBalance from '$lib/wallet/VaultBalance.svelte';
import IconWallet from '~icons/local/wallet';
import IconChevronDown from '~icons/local/chevron-down';
import IconUnlink from '~icons/local/unlink';
Expand All @@ -23,7 +19,7 @@
import { getVaultUrl } from 'trade-executor/helpers/vault';

export let strategy: ConnectedStrategyRuntimeState;
export let chain: ConfiguredChain | undefined;
export let chain: Chain;
export let geoBlocked: boolean;
export let ipCountry: CountryCode | undefined;

Expand All @@ -37,7 +33,6 @@
const { depositOnEnzyme } = strategy;

const depositEnabled = [
chain,
contracts.vault,
contracts.comptroller,
contracts.payment_forwarder,
Expand All @@ -47,7 +42,7 @@
const isOutdated = Boolean(strategy.new_version_id);

$: connected = $wallet.isConnected;
$: wrongNetwork = connected && $wallet.chain?.id !== chain?.id;
$: wrongNetwork = connected && $wallet.chain?.id !== chain.id;
$: buttonsDisabled = geoBlocked || !depositEnabled || wrongNetwork;

const expandable = fsm('closed', {
Expand Down Expand Up @@ -77,7 +72,7 @@

function launchWizard(slug: string) {
wizard.init(slug, `/strategies/${strategy.id}`, {
chainId: chain?.id,
chain,
strategyName: strategy.name,
contracts
});
Expand Down Expand Up @@ -127,7 +122,7 @@
<DepositWarning title="Wallet not connected">Please connect wallet to see your deposit status.</DepositWarning>
{:else if wrongNetwork}
<DepositWarning title="Wrong network">
Please connect to {chain?.name}.
Please connect to {chain.name}.
</DepositWarning>
{:else}
<dl class="balances">
Expand Down
13 changes: 6 additions & 7 deletions src/lib/wallet/VaultBalance.svelte
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
<script lang="ts">
import type { GetTokenBalanceReturnType } from '$lib/eth-defi/helpers';
import type { EnzymeSmartContracts } from 'trade-executor/strategy/summary';
import { createEventDispatcher } from 'svelte';
import { formatUnits } from 'viem';
import { simulateContract } from '@wagmi/core';
import { config } from '$lib/wallet';
import { config } from '$lib/wallet/client';
import { getTokenBalance } from '$lib/eth-defi/helpers';
import fundValueCalculatorABI from '$lib/eth-defi/abi/enzyme/FundValueCalculator.json';
import { DataBox } from '$lib/components';
import { TokenBalance } from '$lib/wallet';
import TokenBalance from '$lib/wallet/TokenBalance.svelte';

export let address: Address;
export let contracts: EnzymeSmartContracts;
Expand Down Expand Up @@ -36,13 +36,12 @@
const { decimals, symbol, label } = denominationToken;

const vaultNetValue = {
address: contracts.vault,
decimals,
symbol: symbol ?? '---',
value,
label,
// TODO: remove deprecated `formatted` property after @wagmi removes from GetBalanceReturnType
formatted: formatUnits(value, decimals)
};
label
} as GetTokenBalanceReturnType;

dispatch('dataFetch', { denominationToken, vaultNetValue });

Expand Down
7 changes: 4 additions & 3 deletions src/lib/wallet/WalletAddress.svelte
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
<script lang="ts">
import type { ComponentProps } from 'svelte';
import type { ConnectedWallet } from '$lib/wallet';
import { getExplorerUrl } from '$lib/helpers/chain';
import type { ConnectedWallet } from '$lib/wallet/client';
import { getChain, getExplorerUrl } from '$lib/helpers/chain';
import { CryptoAddressWidget } from '$lib/components';
import IconWallet from '~icons/local/wallet';

export let wallet: ConnectedWallet;
export let size: ComponentProps<CryptoAddressWidget>['size'] = 'md';

$: ({ address, chain } = wallet);
$: ({ address } = wallet);
$: chain = getChain(wallet.chain?.id);
</script>

<CryptoAddressWidget {size} {address} href={getExplorerUrl(chain, address)} clipboardCopier={false}>
Expand Down
5 changes: 4 additions & 1 deletion src/lib/wallet/WalletBalance.svelte
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
<script lang="ts">
import type { GetBalanceReturnType } from '@wagmi/core';
import type { GetTokenBalanceReturnType } from '$lib/eth-defi/helpers';
import { wallet, WalletAddress, WalletInfo, WalletInfoItem } from '$lib/wallet';
import { wallet } from '$lib/wallet/client';
import WalletAddress from '$lib/wallet/WalletAddress.svelte';
import WalletInfo from '$lib/wallet/WalletInfo.svelte';
import WalletInfoItem from '$lib/wallet/WalletInfoItem.svelte';
import { EntitySymbol } from '$lib/components';
import { formatBalance } from '$lib/eth-defi/helpers';
import { getLogoUrl } from '$lib/helpers/assets';
Expand Down
8 changes: 5 additions & 3 deletions src/lib/wallet/WalletSummary.svelte
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
<script lang="ts">
import type { Chain } from '$lib/helpers/chain.js';
import type { ConnectedWallet } from '$lib/wallet';
import { switchChain, WalletAddress, WalletInfo, WalletInfoItem } from '$lib/wallet';
import type { Chain } from '$lib/helpers/chain';
import { type ConnectedWallet, switchChain } from '$lib/wallet/client';
import WalletAddress from '$lib/wallet/WalletAddress.svelte';
import WalletInfo from '$lib/wallet/WalletInfo.svelte';
import WalletInfoItem from '$lib/wallet/WalletInfoItem.svelte';
import { Alert, Button, EntitySymbol } from '$lib/components';
import { getLogoUrl } from '$lib/helpers/assets';

Expand Down
10 changes: 5 additions & 5 deletions src/lib/wallet/WalletWidget.svelte
Original file line number Diff line number Diff line change
@@ -1,20 +1,20 @@
<script lang="ts">
import type { Chain } from '$lib/helpers/chain';
import type { ConnectedStrategyRuntimeState } from 'trade-executor/strategy/runtime-state';
import { goto } from '$app/navigation';
import { wizard } from 'wizard/store';
import { modal, wallet } from '$lib/wallet';
import { modal, wallet } from '$lib/wallet/client';
import { Button, HashAddress } from '$lib/components';
import IconWallet from '~icons/local/wallet';

export let chain: Chain;
export let strategy: ConnectedStrategyRuntimeState;

$: contracts = strategy.on_chain_data.smart_contracts;

function launchConnectWizard() {
wizard.init('connect-wallet', `/strategies/${strategy.id}`, {
chainId: strategy.on_chain_data.chain_id,
chain,
strategyName: strategy.name,
contracts
contracts: strategy.on_chain_data.smart_contracts
});
goto(`/wizard/connect-wallet/introduction`);
}
Expand Down
Loading
Loading