feat(wallet): metamask snaps (#4621)
Co-authored-by: Matthew Russell <mattrussell36@gmail.com>
This commit is contained in:
parent
4fe81cc4aa
commit
5c18c898b0
@ -29,3 +29,4 @@ LC_ALL="en_US.UTF-8"
|
||||
|
||||
# Cosmic elevator flags
|
||||
NX_SUCCESSOR_MARKETS=true
|
||||
NX_METAMASK_SNAPS=true
|
@ -30,3 +30,4 @@ CYPRESS_FAIRGROUND=false
|
||||
|
||||
# Cosmic elevator flags
|
||||
NX_SUCCESSOR_MARKETS=false
|
||||
NX_METAMASK_SNAPS=false
|
@ -22,3 +22,4 @@ NX_TENDERMINT_WEBSOCKET_URL=wss://be.devnet1.vega.xyz/websocket
|
||||
|
||||
# Cosmic elevator flags
|
||||
NX_SUCCESSOR_MARKETS=true
|
||||
NX_METAMASK_SNAPS=true
|
@ -22,3 +22,4 @@ NX_TENDERMINT_WEBSOCKET_URL=wss://be.vega.community/websocket
|
||||
|
||||
# Cosmic elevator flags
|
||||
NX_SUCCESSOR_MARKETS=false
|
||||
NX_METAMASK_SNAPS=false
|
||||
|
@ -21,3 +21,4 @@ NX_TENDERMINT_WEBSOCKET_URL=wss://be.mainnet-mirror.vega.rocks/websocket
|
||||
|
||||
# Cosmic elevator flags
|
||||
NX_SUCCESSOR_MARKETS=false
|
||||
NX_METAMASK_SNAPS=false
|
||||
|
@ -18,3 +18,4 @@ NX_TENDERMINT_WEBSOCKET_URL=wss://tm.n01.stagnet1.vega.xyz/websocket
|
||||
|
||||
# Cosmic elevator flags
|
||||
NX_SUCCESSOR_MARKETS=true
|
||||
NX_METAMASK_SNAPS=true
|
||||
|
@ -23,3 +23,4 @@ NX_TENDERMINT_WEBSOCKET_URL=wss://be.testnet.vega.xyz/websocket
|
||||
|
||||
# Cosmic elevator flags
|
||||
NX_SUCCESSOR_MARKETS=true
|
||||
NX_METAMASK_SNAPS=true
|
||||
|
@ -20,3 +20,4 @@ NX_TENDERMINT_WEBSOCKET_URL=wss://be.validators-testnet.vega.
|
||||
|
||||
# Cosmic elevator flags
|
||||
NX_SUCCESSOR_MARKETS=false
|
||||
NX_METAMASK_SNAPS=false
|
||||
|
@ -1,17 +1,26 @@
|
||||
import { ENV } from '@vegaprotocol/environment';
|
||||
import {
|
||||
JsonRpcConnector,
|
||||
ViewConnector,
|
||||
InjectedConnector,
|
||||
SnapConnector,
|
||||
DEFAULT_SNAP_ID,
|
||||
} from '@vegaprotocol/wallet';
|
||||
|
||||
const urlParams = new URLSearchParams(window.location.search);
|
||||
|
||||
export const injected = new InjectedConnector();
|
||||
export const jsonRpc = new JsonRpcConnector();
|
||||
export const injected = new InjectedConnector();
|
||||
export const view = new ViewConnector(urlParams.get('address'));
|
||||
|
||||
export const snap = new SnapConnector(
|
||||
ENV.VEGA_URL ? new URL(ENV.VEGA_URL).origin : undefined,
|
||||
DEFAULT_SNAP_ID
|
||||
);
|
||||
|
||||
export const Connectors = {
|
||||
injected,
|
||||
jsonRpc,
|
||||
view,
|
||||
snap,
|
||||
};
|
||||
|
@ -19,6 +19,7 @@ NX_SUCCESSOR_MARKETS=true
|
||||
NX_STOP_ORDERS=true
|
||||
# NX_ICEBERG_ORDERS
|
||||
# NX_PRODUCT_PERPETUALS
|
||||
NX_METAMASK_SNAPS=true
|
||||
|
||||
NX_TENDERMINT_URL=https://tm.n01.stagnet1.vega.rocks
|
||||
NX_TENDERMINT_WEBSOCKET_URL=wss://tm.n01.stagnet1.vega.xyz/websocket
|
||||
|
@ -23,6 +23,7 @@ NX_SUCCESSOR_MARKETS=false
|
||||
NX_STOP_ORDERS=false
|
||||
# NX_ICEBERG_ORDERS
|
||||
# NX_PRODUCT_PERPETUALS
|
||||
NX_METAMASK_SNAPS=false
|
||||
|
||||
NX_TENDERMINT_URL=http://localhost:26617
|
||||
NX_TENDERMINT_WEBSOCKET_URL=wss://localhost:26617/websocket
|
||||
|
@ -21,6 +21,7 @@ NX_SUCCESSOR_MARKETS=true
|
||||
NX_STOP_ORDERS=true
|
||||
# NX_ICEBERG_ORDERS
|
||||
# NX_PRODUCT_PERPETUALS
|
||||
NX_METAMASK_SNAPS=true
|
||||
|
||||
NX_TENDERMINT_URL=https://tm.be.devnet1.vega.xyz/
|
||||
NX_TENDERMINT_WEBSOCKET_URL=wss://be.devnet1.vega.xyz/websocket
|
||||
|
@ -23,6 +23,7 @@ NX_SUCCESSOR_MARKETS=false
|
||||
NX_STOP_ORDERS=false
|
||||
# NX_ICEBERG_ORDERS
|
||||
# NX_PRODUCT_PERPETUALS
|
||||
NX_METAMASK_SNAPS=false
|
||||
|
||||
NX_TENDERMINT_URL=https://be.vega.community
|
||||
NX_TENDERMINT_WEBSOCKET_URL=wss://be.vega.community/websocket
|
||||
|
@ -23,6 +23,7 @@ NX_SUCCESSOR_MARKETS=false
|
||||
NX_STOP_ORDERS=false
|
||||
# NX_ICEBERG_ORDERS
|
||||
# NX_PRODUCT_PERPETUALS
|
||||
NX_METAMASK_SNAPS=false
|
||||
|
||||
NX_TENDERMINT_URL=https://be.mainnet-mirror.vega.rocks
|
||||
NX_TENDERMINT_WEBSOCKET_URL=wss://be.mainnet-mirror.vega.rocks/websocket
|
||||
|
@ -21,3 +21,4 @@ NX_SUCCESSOR_MARKETS=true
|
||||
NX_STOP_ORDERS=true
|
||||
# NX_ICEBERG_ORDERS
|
||||
# NX_PRODUCT_PERPETUALS
|
||||
NX_METAMASK_SNAPS=true
|
||||
|
@ -22,6 +22,7 @@ NX_SUCCESSOR_MARKETS=true
|
||||
NX_STOP_ORDERS=true
|
||||
NX_ICEBERG_ORDERS=true
|
||||
# NX_PRODUCT_PERPETUALS
|
||||
NX_METAMASK_SNAPS=false
|
||||
|
||||
NX_TENDERMINT_URL=https://tm.be.testnet.vega.xyz
|
||||
NX_TENDERMINT_WEBSOCKET_URL=wss://be.testnet.vega.xyz/websocket
|
||||
|
@ -23,6 +23,7 @@ NX_SUCCESSOR_MARKETS=false
|
||||
NX_STOP_ORDERS=false
|
||||
# NX_ICEBERG_ORDERS
|
||||
# NX_PRODUCT_PERPETUALS
|
||||
NX_METAMASK_SNAPS=false
|
||||
|
||||
NX_TENDERMINT_URL=https://tm.be.validators-testnet.vega.rocks
|
||||
NX_TENDERMINT_WEBSOCKET_URL=wss://be.validators-testnet.vega.xyz/websocket
|
||||
|
@ -1,7 +1,10 @@
|
||||
import { ENV } from '@vegaprotocol/environment';
|
||||
import {
|
||||
JsonRpcConnector,
|
||||
ViewConnector,
|
||||
InjectedConnector,
|
||||
SnapConnector,
|
||||
DEFAULT_SNAP_ID,
|
||||
} from '@vegaprotocol/wallet';
|
||||
|
||||
export const jsonRpc = new JsonRpcConnector();
|
||||
@ -15,8 +18,14 @@ if (typeof window !== 'undefined') {
|
||||
view = new ViewConnector();
|
||||
}
|
||||
|
||||
export const snap = new SnapConnector(
|
||||
ENV.VEGA_URL ? new URL(ENV.VEGA_URL).origin : undefined,
|
||||
DEFAULT_SNAP_ID
|
||||
);
|
||||
|
||||
export const Connectors = {
|
||||
injected,
|
||||
jsonRpc,
|
||||
view,
|
||||
snap,
|
||||
};
|
||||
|
@ -408,6 +408,12 @@ function compileFeatureFlags(): FeatureFlags {
|
||||
process.env['NX_PRODUCT_PERPETUALS']
|
||||
) as string
|
||||
),
|
||||
METAMASK_SNAPS: TRUTHY.includes(
|
||||
windowOrDefault(
|
||||
'NX_METAMASK_SNAPS',
|
||||
process.env['NX_METAMASK_SNAPS']
|
||||
) as string
|
||||
),
|
||||
};
|
||||
const EXPLORER_FLAGS = {
|
||||
EXPLORER_ASSETS: TRUTHY.includes(
|
||||
|
@ -18,7 +18,11 @@ export type Environment = z.infer<typeof envSchema>;
|
||||
export type FeatureFlags = z.infer<typeof featureFlagsSchema>;
|
||||
export type CosmicElevatorFlags = Pick<
|
||||
FeatureFlags,
|
||||
'ICEBERG_ORDERS' | 'STOP_ORDERS' | 'SUCCESSOR_MARKETS' | 'PRODUCT_PERPETUALS'
|
||||
| 'ICEBERG_ORDERS'
|
||||
| 'STOP_ORDERS'
|
||||
| 'SUCCESSOR_MARKETS'
|
||||
| 'PRODUCT_PERPETUALS'
|
||||
| 'METAMASK_SNAPS'
|
||||
>;
|
||||
export type Configuration = z.infer<typeof tomlConfigSchema>;
|
||||
export const CUSTOM_NODE_KEY = 'custom' as const;
|
||||
|
@ -77,6 +77,7 @@ const COSMIC_ELEVATOR_FLAGS = {
|
||||
STOP_ORDERS: z.optional(z.boolean()),
|
||||
ICEBERG_ORDERS: z.optional(z.boolean()),
|
||||
PRODUCT_PERPETUALS: z.optional(z.boolean()),
|
||||
METAMASK_SNAPS: z.optional(z.boolean()),
|
||||
};
|
||||
|
||||
const EXPLORER_FLAGS = {
|
||||
|
@ -0,0 +1,102 @@
|
||||
export const IconMetaMask = ({ size = 16 }: { size: number }) => (
|
||||
<svg viewBox="0 0 47 47" fill="none" height={size}>
|
||||
<g>
|
||||
<path
|
||||
d="m40.632 6.969-14.136 10.62 2.628-6.259L40.632 6.97Z"
|
||||
fill="#E17726"
|
||||
stroke="#E17726"
|
||||
strokeWidth="0.223"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
></path>
|
||||
<path
|
||||
d="m8.024 6.969 14.01 10.72-2.502-6.359L8.024 6.97ZM35.542 31.594l-3.761 5.834 8.054 2.251 2.307-7.958-6.6-.127ZM6.528 31.721 8.82 39.68l8.04-2.251-3.747-5.834-6.586.127Z"
|
||||
fill="#E27625"
|
||||
stroke="#E27625"
|
||||
strokeWidth="0.223"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
></path>
|
||||
<path
|
||||
d="m16.428 21.738-2.237 3.427 7.97.368-.266-8.709-5.467 4.914ZM32.229 21.738l-5.552-5.012-.181 8.807 7.97-.368-2.237-3.427ZM16.861 37.428l4.824-2.365-4.152-3.285-.672 5.65ZM26.971 35.063l4.81 2.365-.657-5.65-4.153 3.285Z"
|
||||
fill="#E27625"
|
||||
stroke="#E27625"
|
||||
strokeWidth="0.223"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
></path>
|
||||
<path
|
||||
d="m31.78 37.428-4.81-2.365.392 3.172-.042 1.345 4.46-2.152ZM16.861 37.428l4.475 2.152-.028-1.345.377-3.172-4.824 2.365Z"
|
||||
fill="#D5BFB2"
|
||||
stroke="#D5BFB2"
|
||||
strokeWidth="0.223"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
></path>
|
||||
<path
|
||||
d="m21.42 29.682-4-1.19 2.825-1.316 1.174 2.506ZM27.236 29.682l1.175-2.506 2.838 1.317-4.013 1.19Z"
|
||||
fill="#233447"
|
||||
stroke="#233447"
|
||||
strokeWidth="0.223"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
></path>
|
||||
<path
|
||||
d="m16.861 37.427.7-5.834-4.447.128 3.747 5.706ZM31.096 31.593l.685 5.834 3.761-5.706-4.446-.128ZM34.465 25.165l-7.97.368.741 4.15 1.175-2.507 2.838 1.317 3.216-3.328ZM17.42 28.493l2.825-1.317 1.175 2.506.74-4.149-7.97-.368 3.23 3.328Z"
|
||||
fill="#CC6228"
|
||||
stroke="#CC6228"
|
||||
strokeWidth="0.223"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
></path>
|
||||
<path
|
||||
d="m14.19 25.165 3.343 6.613-.112-3.285-3.23-3.328ZM31.25 28.493l-.126 3.285 3.342-6.613-3.216 3.328ZM22.161 25.533l-.741 4.149.937 4.9.21-6.458-.406-2.591ZM26.495 25.533l-.391 2.577.196 6.471.937-4.9-.741-4.148Z"
|
||||
fill="#E27525"
|
||||
stroke="#E27525"
|
||||
strokeWidth="0.223"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
></path>
|
||||
<path
|
||||
d="m27.237 29.682-.937 4.9.671.481 4.153-3.285.126-3.285-4.013 1.19ZM17.42 28.493l.112 3.285 4.153 3.285.671-.481-.937-4.9-3.999-1.19Z"
|
||||
fill="#F5841F"
|
||||
stroke="#F5841F"
|
||||
strokeWidth="0.223"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
></path>
|
||||
<path
|
||||
d="m27.32 39.58.042-1.345-.363-.312h-5.342l-.35.312.029 1.345-4.475-2.152 1.566 1.303 3.175 2.223h5.439l3.188-2.224 1.552-1.302-4.46 2.152Z"
|
||||
fill="#C0AC9D"
|
||||
stroke="#C0AC9D"
|
||||
strokeWidth="0.223"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
></path>
|
||||
<path
|
||||
d="m26.97 35.063-.67-.482h-3.944l-.67.482-.378 3.172.35-.312h5.34l.364.312-.391-3.172Z"
|
||||
fill="#161616"
|
||||
stroke="#161616"
|
||||
strokeWidth="0.223"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
></path>
|
||||
<path
|
||||
d="m41.234 18.283 1.188-5.863-1.79-5.451-13.66 10.266 5.257 4.503 7.425 2.195 1.636-1.94-.713-.524 1.132-1.048-.867-.68 1.133-.878-.741-.58ZM6.234 12.42l1.203 5.863-.77.58 1.147.878-.867.68L8.08 21.47l-.713.524 1.636 1.94 7.425-2.195 5.257-4.503L8.025 6.97l-1.79 5.452Z"
|
||||
fill="#763E1A"
|
||||
stroke="#763E1A"
|
||||
strokeWidth="0.223"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
></path>
|
||||
<path
|
||||
d="m39.654 23.933-7.425-2.195 2.237 3.427-3.342 6.613 4.419-.057h6.6l-2.49-7.788ZM16.428 21.738l-7.425 2.195-2.475 7.788h6.586l4.418.056-3.342-6.612 2.238-3.427ZM26.495 25.533l.476-8.298 2.153-5.905h-9.592l2.153 5.905.476 8.298.181 2.605.014 6.443H26.3l.014-6.443.182-2.605Z"
|
||||
fill="#F5841F"
|
||||
stroke="#F5841F"
|
||||
strokeWidth="0.223"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
></path>
|
||||
</g>
|
||||
</svg>
|
||||
);
|
@ -1,8 +1,8 @@
|
||||
import { IconArrowDown } from './svg-icons/icon-arrow-down';
|
||||
import { IconArrowLeft } from './svg-icons/icon-arrow-left';
|
||||
import { IconArrowUp } from './svg-icons/icon-arrow-up';
|
||||
import { IconArrowRight } from './svg-icons/icon-arrow-right';
|
||||
import { IconArrowTopRight } from './svg-icons/icon-arrow-top-right';
|
||||
import { IconArrowUp } from './svg-icons/icon-arrow-up';
|
||||
import { IconBreakdown } from './svg-icons/icon-breakdown';
|
||||
import { IconBullet } from './svg-icons/icon-bullet';
|
||||
import { IconChevronDown } from './svg-icons/icon-chevron-down';
|
||||
@ -20,28 +20,29 @@ import { IconGlobe } from './svg-icons/icon-globe';
|
||||
import { IconInfo } from './svg-icons/icon-info';
|
||||
import { IconKebab } from './svg-icons/icon-kebab';
|
||||
import { IconLinkedIn } from './svg-icons/icon-linkedin';
|
||||
import { IconMetaMask } from './svg-icons/icon-metamask';
|
||||
import { IconMinus } from './svg-icons/icon-minus';
|
||||
import { IconMoon } from './svg-icons/icon-moon';
|
||||
import { IconOpenExternal } from './svg-icons/icon-open-external';
|
||||
import { IconQuestionMark } from './svg-icons/icon-question-mark';
|
||||
import { IconPlus } from './svg-icons/icon-plus';
|
||||
import { IconQuestionMark } from './svg-icons/icon-question-mark';
|
||||
import { IconSearch } from './svg-icons/icon-search';
|
||||
import { IconStar } from './svg-icons/icon-star';
|
||||
import { IconTick } from './svg-icons/icon-tick';
|
||||
import { IconTicket } from './svg-icons/icon-ticket';
|
||||
import { IconTransfer } from './svg-icons/icon-transfer';
|
||||
import { IconTrendUp } from './svg-icons/icon-trend-up';
|
||||
import { IconTrendDown } from './svg-icons/icon-trend-down';
|
||||
import { IconTrendUp } from './svg-icons/icon-trend-up';
|
||||
import { IconTwitter } from './svg-icons/icon-twitter';
|
||||
import { IconVote } from './svg-icons/icon-vote';
|
||||
import { IconWithdraw } from './svg-icons/icon-withdraw';
|
||||
import { IconSearch } from './svg-icons/icon-search';
|
||||
|
||||
export enum VegaIconNames {
|
||||
ARROW_DOWN = 'arrow-down',
|
||||
ARROW_LEFT = 'arrow-left',
|
||||
ARROW_UP = 'arrow-up',
|
||||
ARROW_RIGHT = 'arrow-right',
|
||||
ARROW_TOP_RIGHT = 'arrow-top-right',
|
||||
ARROW_UP = 'arrow-up',
|
||||
BREAKDOWN = 'breakdown',
|
||||
BULLET = 'bullet',
|
||||
CHEVRON_DOWN = 'chevron-down',
|
||||
@ -59,18 +60,19 @@ export enum VegaIconNames {
|
||||
INFO = 'info',
|
||||
KEBAB = 'kebab',
|
||||
LINKEDIN = 'linkedin',
|
||||
METAMASK = 'metamask',
|
||||
MINUS = 'minus',
|
||||
MOON = 'moon',
|
||||
OPEN_EXTERNAL = 'open-external',
|
||||
QUESTION_MARK = 'question-mark',
|
||||
PLUS = 'plus',
|
||||
QUESTION_MARK = 'question-mark',
|
||||
SEARCH = 'search',
|
||||
STAR = 'star',
|
||||
TICK = 'tick',
|
||||
TICKET = 'ticket',
|
||||
TRANSFER = 'transfer',
|
||||
TREND_UP = 'trend-up',
|
||||
TREND_DOWN = 'trend-down',
|
||||
TREND_UP = 'trend-up',
|
||||
TWITTER = 'twitter',
|
||||
VOTE = 'vote',
|
||||
WITHDRAW = 'withdraw',
|
||||
@ -82,38 +84,39 @@ export const VegaIconNameMap: Record<
|
||||
> = {
|
||||
'arrow-down': IconArrowDown,
|
||||
'arrow-left': IconArrowLeft,
|
||||
'arrow-up': IconArrowUp,
|
||||
'arrow-right': IconArrowRight,
|
||||
'arrow-top-right': IconArrowTopRight,
|
||||
breakdown: IconBreakdown,
|
||||
bullet: IconBullet,
|
||||
'arrow-up': IconArrowUp,
|
||||
'chevron-down': IconChevronDown,
|
||||
'chevron-left': IconChevronLeft,
|
||||
'chevron-up': IconChevronUp,
|
||||
'exclaimation-mark': IconExclaimationMark,
|
||||
'open-external': IconOpenExternal,
|
||||
'question-mark': IconQuestionMark,
|
||||
'trend-down': IconTrendDown,
|
||||
'trend-up': IconTrendUp,
|
||||
breakdown: IconBreakdown,
|
||||
bullet: IconBullet,
|
||||
cog: IconCog,
|
||||
copy: IconCopy,
|
||||
cross: IconCross,
|
||||
deposit: IconDeposit,
|
||||
edit: IconEdit,
|
||||
'exclaimation-mark': IconExclaimationMark,
|
||||
eye: IconEye,
|
||||
forum: IconForum,
|
||||
globe: IconGlobe,
|
||||
info: IconInfo,
|
||||
kebab: IconKebab,
|
||||
linkedin: IconLinkedIn,
|
||||
metamask: IconMetaMask,
|
||||
minus: IconMinus,
|
||||
moon: IconMoon,
|
||||
'open-external': IconOpenExternal,
|
||||
plus: IconPlus,
|
||||
'question-mark': IconQuestionMark,
|
||||
search: IconSearch,
|
||||
star: IconStar,
|
||||
tick: IconTick,
|
||||
ticket: IconTicket,
|
||||
transfer: IconTransfer,
|
||||
'trend-up': IconTrendUp,
|
||||
'trend-down': IconTrendDown,
|
||||
twitter: IconTwitter,
|
||||
vote: IconVote,
|
||||
withdraw: IconWithdraw,
|
||||
|
@ -16,13 +16,16 @@ import type { WalletClientError } from '@vegaprotocol/wallet-client';
|
||||
import { t } from '@vegaprotocol/i18n';
|
||||
import type { VegaConnector } from '../connectors';
|
||||
import {
|
||||
DEFAULT_SNAP_ID,
|
||||
InjectedConnector,
|
||||
JsonRpcConnector,
|
||||
SnapConnector,
|
||||
ViewConnector,
|
||||
requestSnap,
|
||||
} from '../connectors';
|
||||
import { JsonRpcConnectorForm } from './json-rpc-connector-form';
|
||||
import { ViewConnectorForm } from './view-connector-form';
|
||||
import { useEnvironment } from '@vegaprotocol/environment';
|
||||
import { FLAGS, useEnvironment } from '@vegaprotocol/environment';
|
||||
import {
|
||||
BrowserIcon,
|
||||
ConnectDialogContent,
|
||||
@ -38,10 +41,11 @@ import { useVegaWallet } from '../use-vega-wallet';
|
||||
import { InjectedConnectorForm } from './injected-connector-form';
|
||||
import { isBrowserWalletInstalled } from '../utils';
|
||||
import { useIsWalletServiceRunning } from '../use-is-wallet-service-running';
|
||||
import { useIsSnapRunning } from '../use-is-snap-running';
|
||||
|
||||
export const CLOSE_DELAY = 1700;
|
||||
type Connectors = { [key: string]: VegaConnector };
|
||||
export type WalletType = 'injected' | 'jsonRpc' | 'view';
|
||||
export type WalletType = 'injected' | 'jsonRpc' | 'view' | 'snap';
|
||||
|
||||
export interface VegaConnectDialogProps {
|
||||
connectors: Connectors;
|
||||
@ -156,7 +160,10 @@ const ConnectDialogContainer = ({
|
||||
// for rest because we need to show an authentication form
|
||||
if (connector instanceof JsonRpcConnector) {
|
||||
jsonRpcConnect(connector, appChainId);
|
||||
} else if (connector instanceof InjectedConnector) {
|
||||
} else if (
|
||||
connector instanceof InjectedConnector ||
|
||||
connector instanceof SnapConnector
|
||||
) {
|
||||
injectedConnect(connector, appChainId);
|
||||
}
|
||||
};
|
||||
@ -166,6 +173,8 @@ const ConnectDialogContainer = ({
|
||||
appChainId
|
||||
);
|
||||
|
||||
const isSnapRunning = useIsSnapRunning(DEFAULT_SNAP_ID);
|
||||
|
||||
return (
|
||||
<>
|
||||
<ConnectDialogContent>
|
||||
@ -185,6 +194,7 @@ const ConnectDialogContainer = ({
|
||||
setWalletUrl={setWalletUrl}
|
||||
onSelect={handleSelect}
|
||||
isDesktopWalletRunning={isDesktopWalletRunning}
|
||||
isSnapRunning={isSnapRunning}
|
||||
/>
|
||||
)}
|
||||
</ConnectDialogContent>
|
||||
@ -198,11 +208,13 @@ const ConnectorList = ({
|
||||
walletUrl,
|
||||
setWalletUrl,
|
||||
isDesktopWalletRunning,
|
||||
isSnapRunning,
|
||||
}: {
|
||||
onSelect: (type: WalletType) => void;
|
||||
walletUrl: string;
|
||||
setWalletUrl: (value: string) => void;
|
||||
isDesktopWalletRunning: boolean | null;
|
||||
isSnapRunning: boolean | null;
|
||||
}) => {
|
||||
const { pubKey } = useVegaWallet();
|
||||
const title = isBrowserWalletInstalled()
|
||||
@ -238,6 +250,45 @@ const ConnectorList = ({
|
||||
<GetWalletButton />
|
||||
)}
|
||||
</div>
|
||||
{FLAGS.METAMASK_SNAPS ? (
|
||||
<div>
|
||||
{isSnapRunning ? (
|
||||
<ConnectionOption
|
||||
type="snap"
|
||||
text={
|
||||
<>
|
||||
<div className="w-full h-full flex justify-center items-center gap-1 text-base">
|
||||
{t('Connect via Vega MetaMask Snap')}
|
||||
</div>
|
||||
<div className="absolute right-1 top-0 h-8 flex items-center">
|
||||
<VegaIcon name={VegaIconNames.METAMASK} size={24} />
|
||||
</div>
|
||||
</>
|
||||
}
|
||||
onClick={() => {
|
||||
onSelect('snap');
|
||||
}}
|
||||
/>
|
||||
) : (
|
||||
<ConnectionOption
|
||||
type="snap"
|
||||
text={
|
||||
<>
|
||||
<div className="w-full h-full flex justify-center items-center gap-1 text-base">
|
||||
{t('Install Vega MetaMask Snap')}
|
||||
</div>
|
||||
<div className="absolute right-1 top-0 h-8 flex items-center">
|
||||
<VegaIcon name={VegaIconNames.METAMASK} size={24} />
|
||||
</div>
|
||||
</>
|
||||
}
|
||||
onClick={() => {
|
||||
requestSnap(DEFAULT_SNAP_ID);
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
) : null}
|
||||
<div>
|
||||
<ConnectionOption
|
||||
type="view"
|
||||
@ -282,7 +333,10 @@ const SelectedForm = ({
|
||||
onConnect: () => void;
|
||||
riskMessage?: ReactNode;
|
||||
}) => {
|
||||
if (connector instanceof InjectedConnector) {
|
||||
if (
|
||||
connector instanceof InjectedConnector ||
|
||||
connector instanceof SnapConnector
|
||||
) {
|
||||
return (
|
||||
<InjectedConnectorForm
|
||||
status={injectedState.status}
|
||||
|
@ -11,6 +11,7 @@ import {
|
||||
} from '@vegaprotocol/ui-toolkit';
|
||||
import { setAcknowledged } from '../storage';
|
||||
import { useVegaWallet } from '../use-vega-wallet';
|
||||
import { InjectedConnectorErrors, SnapConnectorErrors } from '../connectors';
|
||||
|
||||
export const InjectedConnectorForm = ({
|
||||
status,
|
||||
@ -20,7 +21,6 @@ export const InjectedConnectorForm = ({
|
||||
reset,
|
||||
error,
|
||||
}: {
|
||||
// connector: JsonRpcConnector;
|
||||
appChainId: string;
|
||||
status: Status;
|
||||
error: Error | null;
|
||||
@ -109,7 +109,7 @@ export const InjectedConnectorForm = ({
|
||||
|
||||
const Center = ({ children }: { children: ReactNode }) => {
|
||||
return (
|
||||
<div className="flex justify-center items-center my-6">{children}</div>
|
||||
<div className="flex items-center justify-center my-6">{children}</div>
|
||||
);
|
||||
};
|
||||
|
||||
@ -131,22 +131,30 @@ const Error = ({
|
||||
);
|
||||
|
||||
if (error) {
|
||||
if (error.message === 'Invalid chain') {
|
||||
if (error.message === InjectedConnectorErrors.INVALID_CHAIN.message) {
|
||||
title = t('Wrong network');
|
||||
text = t(
|
||||
'To complete your wallet connection, set your wallet network in your app to "%s".',
|
||||
appChainId
|
||||
);
|
||||
} else if (error.message === 'window.vega not found') {
|
||||
} else if (
|
||||
error.message === InjectedConnectorErrors.VEGA_UNDEFINED.message
|
||||
) {
|
||||
title = t('No wallet detected');
|
||||
text = t('Vega browser extension not installed');
|
||||
} else if (
|
||||
error.message === SnapConnectorErrors.ETHEREUM_UNDEFINED.message ||
|
||||
error.message === SnapConnectorErrors.NODE_ADDRESS_NOT_SET.message
|
||||
) {
|
||||
title = t('Snap failed');
|
||||
text = t('Could not connect to Vega MetaMask Snap');
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<ConnectDialogTitle>{title}</ConnectDialogTitle>
|
||||
<p className="text-center mb-2 first-letter:uppercase">{text}</p>
|
||||
<p className="mb-2 text-center first-letter:uppercase">{text}</p>
|
||||
{tryAgain}
|
||||
</>
|
||||
);
|
||||
|
@ -1,4 +1,5 @@
|
||||
export * from './vega-connector';
|
||||
export * from './injected-connector';
|
||||
export * from './json-rpc-connector';
|
||||
export * from './snap-connector';
|
||||
export * from './vega-connector';
|
||||
export * from './view-connector';
|
||||
|
@ -41,6 +41,11 @@ declare global {
|
||||
}
|
||||
}
|
||||
|
||||
export const InjectedConnectorErrors = {
|
||||
VEGA_UNDEFINED: new Error('window.vega not found'),
|
||||
INVALID_CHAIN: new Error('Invalid chain'),
|
||||
};
|
||||
|
||||
export class InjectedConnector implements VegaConnector {
|
||||
description = 'Connects using the Vega wallet browser extension';
|
||||
|
||||
|
236
libs/wallet/src/connectors/snap-connector.ts
Normal file
236
libs/wallet/src/connectors/snap-connector.ts
Normal file
@ -0,0 +1,236 @@
|
||||
import {
|
||||
WalletError,
|
||||
type PubKey,
|
||||
type Transaction,
|
||||
type VegaConnector,
|
||||
} from './vega-connector';
|
||||
import { clearConfig, setConfig } from '../storage';
|
||||
|
||||
type RequestArguments = {
|
||||
method: string;
|
||||
params?: unknown[] | object;
|
||||
};
|
||||
type WindowEthereumProvider = {
|
||||
isMetaMask: boolean;
|
||||
request<T = unknown>(args: RequestArguments): Promise<T>;
|
||||
};
|
||||
|
||||
export const SnapConnectorErrors = {
|
||||
ETHEREUM_UNDEFINED: new Error('MetaMask extension could not be found'),
|
||||
NODE_ADDRESS_NOT_SET: new Error('nodeAddress is not set'),
|
||||
SNAP_ID_NOT_SET: new Error('snapId is not set'),
|
||||
TRANSACTION_PARSE: new Error('could not parse transaction data'),
|
||||
};
|
||||
|
||||
const ethereumRequest = <T>(args: RequestArguments): Promise<T> => {
|
||||
// can't declare `EthereumProvider` here because of the conflict with
|
||||
// type definitions of `@web3-react`
|
||||
if (
|
||||
'ethereum' in window &&
|
||||
typeof window.ethereum === 'object' &&
|
||||
window.ethereum &&
|
||||
'request' in window.ethereum &&
|
||||
'isMetaMask' in window.ethereum &&
|
||||
window.ethereum.isMetaMask &&
|
||||
typeof window.ethereum.request === 'function'
|
||||
) {
|
||||
return (window.ethereum as WindowEthereumProvider).request<T>(args);
|
||||
}
|
||||
throw SnapConnectorErrors.ETHEREUM_UNDEFINED;
|
||||
};
|
||||
|
||||
export const LOCAL_SNAP_ID = 'local:http://localhost:8080';
|
||||
export const DEFAULT_SNAP_ID = 'npm:@vegaprotocol/snap';
|
||||
|
||||
type GetSnapsResponse = Record<string, Snap>;
|
||||
|
||||
type Snap = {
|
||||
id: string;
|
||||
initialPermissions?: Record<string, unknown>;
|
||||
version: string;
|
||||
enables: boolean;
|
||||
blocked: boolean;
|
||||
};
|
||||
|
||||
type InvokeSnapRequest = {
|
||||
method: string;
|
||||
params?: object;
|
||||
};
|
||||
|
||||
type SendTransactionResponse =
|
||||
| {
|
||||
transactionHash: string;
|
||||
receivedAt: string;
|
||||
sentAt: string;
|
||||
transaction?: {
|
||||
signature?: {
|
||||
value: string;
|
||||
};
|
||||
};
|
||||
}
|
||||
| {
|
||||
error: Error & {
|
||||
code: number;
|
||||
data: unknown;
|
||||
};
|
||||
};
|
||||
type GetChainIdResponse = {
|
||||
chainID: string;
|
||||
};
|
||||
type ListKeysResponse = { keys: PubKey[] };
|
||||
|
||||
/**
|
||||
* Requests permission for a website to communicate with the specified snaps
|
||||
* and attempts to install them if they're not already installed.
|
||||
* If the installation of any snap fails, returns the error that caused the failure.
|
||||
* More informations here: https://docs.metamask.io/snaps/reference/rpc-api/#wallet_requestsnaps
|
||||
*/
|
||||
export const requestSnap = async (
|
||||
snapId: string,
|
||||
params: Record<'version' | string, unknown> = {}
|
||||
) => {
|
||||
try {
|
||||
await ethereumRequest({
|
||||
method: 'wallet_requestSnaps',
|
||||
params: {
|
||||
[snapId]: params,
|
||||
},
|
||||
});
|
||||
} catch (err) {
|
||||
// NOOP - rejected by user
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Gets the list of all installed snaps.
|
||||
* More information here: https://docs.metamask.io/snaps/reference/rpc-api/#wallet_getsnaps
|
||||
*/
|
||||
export const getSnaps = async (): Promise<GetSnapsResponse> => {
|
||||
return (await ethereumRequest({
|
||||
method: 'wallet_getSnaps',
|
||||
})) as GetSnapsResponse;
|
||||
};
|
||||
|
||||
/**
|
||||
* Gets the requested snap by `snapId` and an optional `version`
|
||||
*/
|
||||
export const getSnap = async (
|
||||
snapId: string,
|
||||
version?: string
|
||||
): Promise<Snap | undefined> => {
|
||||
try {
|
||||
const snaps = await getSnaps();
|
||||
return Object.values(snaps).find(
|
||||
(snap) => snap.id === snapId && (!version || snap.version === version)
|
||||
);
|
||||
} catch (e) {
|
||||
return undefined;
|
||||
}
|
||||
};
|
||||
|
||||
export const invokeSnap = async <T>(
|
||||
snapId: string,
|
||||
request: InvokeSnapRequest
|
||||
) => {
|
||||
const req = {
|
||||
method: 'wallet_invokeSnap',
|
||||
params: {
|
||||
snapId,
|
||||
request,
|
||||
},
|
||||
};
|
||||
return await ethereumRequest<T>(req);
|
||||
};
|
||||
|
||||
export class SnapConnector implements VegaConnector {
|
||||
description = "Connects using Vega Protocol's MetaMask snap";
|
||||
snapId: string | undefined = undefined;
|
||||
nodeAddress: string | undefined = undefined;
|
||||
|
||||
constructor(nodeAddress?: string, snapId = DEFAULT_SNAP_ID) {
|
||||
this.nodeAddress = nodeAddress;
|
||||
this.snapId = snapId;
|
||||
}
|
||||
|
||||
async listKeys() {
|
||||
if (!this.snapId) throw SnapConnectorErrors.SNAP_ID_NOT_SET;
|
||||
return await invokeSnap<ListKeysResponse>(this.snapId, {
|
||||
method: 'client.list_keys',
|
||||
});
|
||||
}
|
||||
|
||||
async connect() {
|
||||
const res = await this.listKeys();
|
||||
setConfig({
|
||||
connector: 'snap',
|
||||
token: null, // no token required for snap
|
||||
url: null, // no url required for snap
|
||||
});
|
||||
return res?.keys;
|
||||
}
|
||||
|
||||
async sendTx(pubKey: string, transaction: Transaction) {
|
||||
if (!this.nodeAddress) throw SnapConnectorErrors.NODE_ADDRESS_NOT_SET;
|
||||
if (!this.snapId) throw SnapConnectorErrors.SNAP_ID_NOT_SET;
|
||||
|
||||
// This step is needed to strip the transaction object from any additional
|
||||
// properties, such as `__proto__`, etc.
|
||||
let txData = null;
|
||||
try {
|
||||
txData = JSON.parse(JSON.stringify(transaction));
|
||||
} catch (err) {
|
||||
throw SnapConnectorErrors.TRANSACTION_PARSE;
|
||||
}
|
||||
|
||||
const payload = {
|
||||
method: 'client.send_transaction',
|
||||
params: {
|
||||
sendingMode: 'TYPE_SYNC',
|
||||
transaction: txData,
|
||||
publicKey: pubKey,
|
||||
networkEndpoints: [this.nodeAddress],
|
||||
},
|
||||
};
|
||||
|
||||
const result = await invokeSnap<SendTransactionResponse>(
|
||||
this.snapId,
|
||||
payload
|
||||
);
|
||||
|
||||
if ('error' in result) {
|
||||
const { message, code, data } = result.error;
|
||||
throw new WalletError(
|
||||
message,
|
||||
code,
|
||||
typeof data === 'string' ? data : ''
|
||||
);
|
||||
}
|
||||
|
||||
if (!result?.transaction?.signature) {
|
||||
throw new Error('could not retrieve transaction siganture');
|
||||
}
|
||||
|
||||
return {
|
||||
transactionHash: result.transactionHash,
|
||||
signature: result?.transaction?.signature?.value,
|
||||
receivedAt: result.receivedAt,
|
||||
sentAt: result.sentAt,
|
||||
};
|
||||
}
|
||||
|
||||
async getChainId(): Promise<GetChainIdResponse> {
|
||||
if (!this.nodeAddress) throw SnapConnectorErrors.NODE_ADDRESS_NOT_SET;
|
||||
if (!this.snapId) throw SnapConnectorErrors.SNAP_ID_NOT_SET;
|
||||
|
||||
const response = await invokeSnap<GetChainIdResponse>(this.snapId, {
|
||||
method: 'client.get_chain_id',
|
||||
params: { networkEndpoints: [this.nodeAddress] },
|
||||
});
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
async disconnect() {
|
||||
clearConfig();
|
||||
}
|
||||
}
|
@ -2,7 +2,7 @@ import { LocalStorage } from '@vegaprotocol/utils';
|
||||
|
||||
interface ConnectorConfig {
|
||||
token: string | null;
|
||||
connector: 'injected' | 'jsonRpc' | 'view';
|
||||
connector: 'injected' | 'jsonRpc' | 'view' | 'snap';
|
||||
url: string | null;
|
||||
}
|
||||
|
||||
|
@ -1,11 +1,14 @@
|
||||
import type { SnapConnector } from './';
|
||||
import { useVegaWallet } from './';
|
||||
import { useEffect, useState } from 'react';
|
||||
import type { VegaConnector } from './connectors/vega-connector';
|
||||
import { getConfig } from './storage';
|
||||
import { useEnvironment } from '@vegaprotocol/environment';
|
||||
|
||||
export function useEagerConnect(Connectors: {
|
||||
[connector: string]: VegaConnector;
|
||||
}) {
|
||||
const { VEGA_URL } = useEnvironment();
|
||||
const [connecting, setConnecting] = useState(true);
|
||||
const { connect, acknowledgeNeeded } = useVegaWallet();
|
||||
|
||||
@ -36,6 +39,12 @@ export function useEagerConnect(Connectors: {
|
||||
// @ts-ignore only injected wallet has connectWallet method
|
||||
await injectedInstance.connectWallet();
|
||||
await connect(injectedInstance);
|
||||
} else if (cfg.connector === 'snap') {
|
||||
const snapInstance = Connectors[cfg.connector] as SnapConnector;
|
||||
if (VEGA_URL) {
|
||||
snapInstance.nodeAddress = new URL(VEGA_URL).origin;
|
||||
await connect(snapInstance);
|
||||
}
|
||||
} else {
|
||||
await connect(Connectors[cfg.connector]);
|
||||
}
|
||||
@ -49,7 +58,7 @@ export function useEagerConnect(Connectors: {
|
||||
if (typeof window !== 'undefined') {
|
||||
attemptConnect();
|
||||
}
|
||||
}, [connect, Connectors, acknowledgeNeeded]);
|
||||
}, [connect, Connectors, acknowledgeNeeded, VEGA_URL]);
|
||||
|
||||
return connecting;
|
||||
}
|
||||
|
@ -1,6 +1,12 @@
|
||||
import { useCallback, useState } from 'react';
|
||||
import type { InjectedConnector } from './connectors';
|
||||
import {
|
||||
InjectedConnectorErrors,
|
||||
SnapConnector,
|
||||
SnapConnectorErrors,
|
||||
} from './connectors';
|
||||
import { InjectedConnector } from './connectors';
|
||||
import { useVegaWallet } from './use-vega-wallet';
|
||||
import { useEnvironment } from '@vegaprotocol/environment';
|
||||
|
||||
export enum Status {
|
||||
Idle = 'Idle',
|
||||
@ -15,24 +21,39 @@ export const useInjectedConnector = (onConnect: () => void) => {
|
||||
const { connect, acknowledgeNeeded } = useVegaWallet();
|
||||
const [status, setStatus] = useState(Status.Idle);
|
||||
const [error, setError] = useState<Error | null>(null);
|
||||
const { VEGA_URL } = useEnvironment();
|
||||
|
||||
const attemptConnect = useCallback(
|
||||
async (connector: InjectedConnector, appChainId: string) => {
|
||||
async (
|
||||
connector: InjectedConnector | SnapConnector,
|
||||
appChainId: string
|
||||
) => {
|
||||
try {
|
||||
if (!('vega' in window)) {
|
||||
throw new Error('window.vega not found');
|
||||
if (connector instanceof InjectedConnector && !('vega' in window)) {
|
||||
throw InjectedConnectorErrors.VEGA_UNDEFINED;
|
||||
}
|
||||
if (connector instanceof SnapConnector) {
|
||||
if (!('ethereum' in window)) {
|
||||
throw SnapConnectorErrors.ETHEREUM_UNDEFINED;
|
||||
}
|
||||
if (!VEGA_URL) {
|
||||
throw SnapConnectorErrors.NODE_ADDRESS_NOT_SET;
|
||||
}
|
||||
connector.nodeAddress = new URL(VEGA_URL).origin;
|
||||
}
|
||||
|
||||
setStatus(Status.GettingChainId);
|
||||
|
||||
const { chainID } = await connector.getChainId();
|
||||
|
||||
if (chainID !== appChainId) {
|
||||
throw new Error('Invalid chain');
|
||||
throw InjectedConnectorErrors.INVALID_CHAIN;
|
||||
}
|
||||
|
||||
setStatus(Status.Connecting);
|
||||
await connector.connectWallet(); // authorize wallet
|
||||
if (connector instanceof InjectedConnector) {
|
||||
// extra step for injected connector - authorize wallet
|
||||
await connector.connectWallet();
|
||||
}
|
||||
await connect(connector); // connect with keys
|
||||
|
||||
if (acknowledgeNeeded) {
|
||||
@ -50,7 +71,7 @@ export const useInjectedConnector = (onConnect: () => void) => {
|
||||
setStatus(Status.Error);
|
||||
}
|
||||
},
|
||||
[acknowledgeNeeded, connect, onConnect]
|
||||
[VEGA_URL, acknowledgeNeeded, connect, onConnect]
|
||||
);
|
||||
|
||||
return {
|
||||
|
22
libs/wallet/src/use-is-snap-running.ts
Normal file
22
libs/wallet/src/use-is-snap-running.ts
Normal file
@ -0,0 +1,22 @@
|
||||
import { useEffect, useState } from 'react';
|
||||
import { getSnap } from './connectors';
|
||||
|
||||
const INTERVAL = 2_000;
|
||||
|
||||
export const useIsSnapRunning = (snapId: string) => {
|
||||
const [running, setRunning] = useState(false);
|
||||
useEffect(() => {
|
||||
const checkState = async () => {
|
||||
const snap = await getSnap(snapId);
|
||||
setRunning(!!snap);
|
||||
};
|
||||
const i = setInterval(() => {
|
||||
checkState();
|
||||
}, INTERVAL);
|
||||
checkState();
|
||||
return () => {
|
||||
clearInterval(i);
|
||||
};
|
||||
}, [snapId]);
|
||||
return running;
|
||||
};
|
@ -73,6 +73,7 @@ export const useVegaTransactionStore = create<VegaTransactionStore>()(
|
||||
order,
|
||||
};
|
||||
set({ transactions: transactions.concat(transaction) });
|
||||
|
||||
return transaction.id;
|
||||
},
|
||||
update: (index: number, update: Partial<VegaStoredTxState>) => {
|
||||
|
@ -9,7 +9,7 @@ import type { VegaTransactionContentMap } from './vega-transaction-dialog';
|
||||
import { VegaTransactionDialog } from './vega-transaction-dialog';
|
||||
import type { Intent } from '@vegaprotocol/ui-toolkit';
|
||||
import type { Transaction } from './connectors';
|
||||
import type { WalletError } from './connectors';
|
||||
import { WalletError } from './connectors';
|
||||
import { ClientErrors } from './connectors';
|
||||
|
||||
export interface DialogProps {
|
||||
@ -44,7 +44,7 @@ export const initialState = {
|
||||
};
|
||||
|
||||
export const orderErrorResolve = (err: Error | unknown): Error => {
|
||||
if (err instanceof WalletClientError) {
|
||||
if (err instanceof WalletClientError || err instanceof WalletError) {
|
||||
return err;
|
||||
} else if (err instanceof WalletHttpError) {
|
||||
return ClientErrors.UNKNOWN;
|
||||
|
@ -758,11 +758,11 @@ const VegaTxCompleteToastsContent = ({ tx }: VegaTxToastContentProps) => {
|
||||
|
||||
const VegaTxErrorToastContent = ({ tx }: VegaTxToastContentProps) => {
|
||||
let label = t('Error occurred');
|
||||
let errorMessage = `${tx.error?.message} ${
|
||||
tx.error instanceof WalletError && tx.error?.data
|
||||
? `: ${tx.error?.data}`
|
||||
: ''
|
||||
}`;
|
||||
let errorMessage =
|
||||
tx.error instanceof WalletError
|
||||
? `${tx.error.title}: ${tx.error.data}`
|
||||
: tx.error?.message;
|
||||
|
||||
const reconnectVegaWallet = useReconnectVegaWallet();
|
||||
|
||||
const orderRejection = tx.order && getRejectionReason(tx.order);
|
||||
@ -773,6 +773,7 @@ const VegaTxErrorToastContent = ({ tx }: VegaTxToastContentProps) => {
|
||||
const walletError =
|
||||
tx.error instanceof WalletError &&
|
||||
walletNoConnectionCodes.includes(tx.error.code);
|
||||
|
||||
if (orderRejection) {
|
||||
label = getOrderToastTitle(tx.order?.status) || t('Order rejected');
|
||||
errorMessage = t('Your order has been rejected because: %s', [
|
||||
|
@ -1,6 +1,11 @@
|
||||
import { t } from '@vegaprotocol/i18n';
|
||||
import { useLocalStorage } from '@vegaprotocol/react-helpers';
|
||||
import { Dialog, Intent } from '@vegaprotocol/ui-toolkit';
|
||||
import {
|
||||
Dialog,
|
||||
Intent,
|
||||
VegaIcon,
|
||||
VegaIconNames,
|
||||
} from '@vegaprotocol/ui-toolkit';
|
||||
import { MetaMask } from '@web3-react/metamask';
|
||||
import { WalletConnect } from '@web3-react/walletconnect-v2';
|
||||
import { WalletConnect as WalletConnectLegacy } from '@web3-react/walletconnect';
|
||||
@ -118,7 +123,7 @@ export const Web3ConnectUncontrolledDialog = () => {
|
||||
function getConnectorInfo(connector: Connector) {
|
||||
if (connector instanceof MetaMask) {
|
||||
return {
|
||||
icon: <MetaMaskIcon width={40} />,
|
||||
icon: <VegaIcon name={VegaIconNames.METAMASK} size={32} />,
|
||||
name: 'MetaMask',
|
||||
text: t('MetaMask'),
|
||||
alt: t('MetaMask, Brave or other injected web wallet'),
|
||||
@ -126,14 +131,14 @@ function getConnectorInfo(connector: Connector) {
|
||||
}
|
||||
if (connector instanceof CoinbaseWallet) {
|
||||
return {
|
||||
icon: <CoinbaseWalletIcon width={40} />,
|
||||
icon: <CoinbaseWalletIcon width={32} />,
|
||||
name: 'CoinbaseWallet',
|
||||
text: t('Coinbase'),
|
||||
};
|
||||
}
|
||||
if (connector instanceof WalletConnect) {
|
||||
return {
|
||||
icon: <WalletConnectIcon width={40} />,
|
||||
icon: <WalletConnectIcon width={32} />,
|
||||
name: 'WalletConnect',
|
||||
text: t('WalletConnect'),
|
||||
alt: t('WalletConnect v2'),
|
||||
@ -143,7 +148,7 @@ function getConnectorInfo(connector: Connector) {
|
||||
return {
|
||||
icon: (
|
||||
<WalletConnectIcon
|
||||
width={40}
|
||||
width={32}
|
||||
fillColor={theme.colors.vega.light[200]}
|
||||
/>
|
||||
),
|
||||
@ -160,115 +165,6 @@ type IconProps = {
|
||||
height?: number;
|
||||
};
|
||||
|
||||
const MetaMaskIcon = ({ width, height }: IconProps) => (
|
||||
<svg
|
||||
viewBox="0 0 47 47"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width={width}
|
||||
height={height}
|
||||
>
|
||||
<g>
|
||||
<path
|
||||
d="m40.632 6.969-14.136 10.62 2.628-6.259L40.632 6.97Z"
|
||||
fill="#E17726"
|
||||
stroke="#E17726"
|
||||
strokeWidth="0.223"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
></path>
|
||||
<path
|
||||
d="m8.024 6.969 14.01 10.72-2.502-6.359L8.024 6.97ZM35.542 31.594l-3.761 5.834 8.054 2.251 2.307-7.958-6.6-.127ZM6.528 31.721 8.82 39.68l8.04-2.251-3.747-5.834-6.586.127Z"
|
||||
fill="#E27625"
|
||||
stroke="#E27625"
|
||||
strokeWidth="0.223"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
></path>
|
||||
<path
|
||||
d="m16.428 21.738-2.237 3.427 7.97.368-.266-8.709-5.467 4.914ZM32.229 21.738l-5.552-5.012-.181 8.807 7.97-.368-2.237-3.427ZM16.861 37.428l4.824-2.365-4.152-3.285-.672 5.65ZM26.971 35.063l4.81 2.365-.657-5.65-4.153 3.285Z"
|
||||
fill="#E27625"
|
||||
stroke="#E27625"
|
||||
strokeWidth="0.223"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
></path>
|
||||
<path
|
||||
d="m31.78 37.428-4.81-2.365.392 3.172-.042 1.345 4.46-2.152ZM16.861 37.428l4.475 2.152-.028-1.345.377-3.172-4.824 2.365Z"
|
||||
fill="#D5BFB2"
|
||||
stroke="#D5BFB2"
|
||||
strokeWidth="0.223"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
></path>
|
||||
<path
|
||||
d="m21.42 29.682-4-1.19 2.825-1.316 1.174 2.506ZM27.236 29.682l1.175-2.506 2.838 1.317-4.013 1.19Z"
|
||||
fill="#233447"
|
||||
stroke="#233447"
|
||||
strokeWidth="0.223"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
></path>
|
||||
<path
|
||||
d="m16.861 37.427.7-5.834-4.447.128 3.747 5.706ZM31.096 31.593l.685 5.834 3.761-5.706-4.446-.128ZM34.465 25.165l-7.97.368.741 4.15 1.175-2.507 2.838 1.317 3.216-3.328ZM17.42 28.493l2.825-1.317 1.175 2.506.74-4.149-7.97-.368 3.23 3.328Z"
|
||||
fill="#CC6228"
|
||||
stroke="#CC6228"
|
||||
strokeWidth="0.223"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
></path>
|
||||
<path
|
||||
d="m14.19 25.165 3.343 6.613-.112-3.285-3.23-3.328ZM31.25 28.493l-.126 3.285 3.342-6.613-3.216 3.328ZM22.161 25.533l-.741 4.149.937 4.9.21-6.458-.406-2.591ZM26.495 25.533l-.391 2.577.196 6.471.937-4.9-.741-4.148Z"
|
||||
fill="#E27525"
|
||||
stroke="#E27525"
|
||||
strokeWidth="0.223"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
></path>
|
||||
<path
|
||||
d="m27.237 29.682-.937 4.9.671.481 4.153-3.285.126-3.285-4.013 1.19ZM17.42 28.493l.112 3.285 4.153 3.285.671-.481-.937-4.9-3.999-1.19Z"
|
||||
fill="#F5841F"
|
||||
stroke="#F5841F"
|
||||
strokeWidth="0.223"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
></path>
|
||||
<path
|
||||
d="m27.32 39.58.042-1.345-.363-.312h-5.342l-.35.312.029 1.345-4.475-2.152 1.566 1.303 3.175 2.223h5.439l3.188-2.224 1.552-1.302-4.46 2.152Z"
|
||||
fill="#C0AC9D"
|
||||
stroke="#C0AC9D"
|
||||
strokeWidth="0.223"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
></path>
|
||||
<path
|
||||
d="m26.97 35.063-.67-.482h-3.944l-.67.482-.378 3.172.35-.312h5.34l.364.312-.391-3.172Z"
|
||||
fill="#161616"
|
||||
stroke="#161616"
|
||||
strokeWidth="0.223"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
></path>
|
||||
<path
|
||||
d="m41.234 18.283 1.188-5.863-1.79-5.451-13.66 10.266 5.257 4.503 7.425 2.195 1.636-1.94-.713-.524 1.132-1.048-.867-.68 1.133-.878-.741-.58ZM6.234 12.42l1.203 5.863-.77.58 1.147.878-.867.68L8.08 21.47l-.713.524 1.636 1.94 7.425-2.195 5.257-4.503L8.025 6.97l-1.79 5.452Z"
|
||||
fill="#763E1A"
|
||||
stroke="#763E1A"
|
||||
strokeWidth="0.223"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
></path>
|
||||
<path
|
||||
d="m39.654 23.933-7.425-2.195 2.237 3.427-3.342 6.613 4.419-.057h6.6l-2.49-7.788ZM16.428 21.738l-7.425 2.195-2.475 7.788h6.586l4.418.056-3.342-6.612 2.238-3.427ZM26.495 25.533l.476-8.298 2.153-5.905h-9.592l2.153 5.905.476 8.298.181 2.605.014 6.443H26.3l.014-6.443.182-2.605Z"
|
||||
fill="#F5841F"
|
||||
stroke="#F5841F"
|
||||
strokeWidth="0.223"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
></path>
|
||||
</g>
|
||||
</svg>
|
||||
);
|
||||
|
||||
const CoinbaseWalletIcon = ({ width, height }: IconProps) => (
|
||||
<svg
|
||||
width={width}
|
||||
|
Loading…
Reference in New Issue
Block a user