@broxus/evm-connect 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (131) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +182 -0
  3. package/dist/cjs/components/EvmConnectButton/index.d.ts +21 -0
  4. package/dist/cjs/components/EvmConnectButton/index.js +52 -0
  5. package/dist/cjs/components/EvmConnectDialog/index.css +130 -0
  6. package/dist/cjs/components/EvmConnectDialog/index.d.ts +11 -0
  7. package/dist/cjs/components/EvmConnectDialog/index.js +65 -0
  8. package/dist/cjs/components/EvmConnector/index.css +37 -0
  9. package/dist/cjs/components/EvmConnector/index.d.ts +20 -0
  10. package/dist/cjs/components/EvmConnector/index.js +97 -0
  11. package/dist/cjs/components/EvmProvidersDispatcher/ConnectionRequest/index.css +43 -0
  12. package/dist/cjs/components/EvmProvidersDispatcher/ConnectionRequest/index.d.ts +3 -0
  13. package/dist/cjs/components/EvmProvidersDispatcher/ConnectionRequest/index.js +65 -0
  14. package/dist/cjs/components/EvmProvidersDispatcher/ProviderButton/index.css +54 -0
  15. package/dist/cjs/components/EvmProvidersDispatcher/ProviderButton/index.d.ts +11 -0
  16. package/dist/cjs/components/EvmProvidersDispatcher/ProviderButton/index.js +93 -0
  17. package/dist/cjs/components/EvmProvidersDispatcher/index.css +13 -0
  18. package/dist/cjs/components/EvmProvidersDispatcher/index.d.ts +5 -0
  19. package/dist/cjs/components/EvmProvidersDispatcher/index.js +49 -0
  20. package/dist/cjs/components/index.d.ts +4 -0
  21. package/dist/cjs/components/index.js +20 -0
  22. package/dist/cjs/constants.d.ts +1 -0
  23. package/dist/cjs/constants.js +4 -0
  24. package/dist/cjs/context/EvmWalletProvidersContext.d.ts +20 -0
  25. package/dist/cjs/context/EvmWalletProvidersContext.js +95 -0
  26. package/dist/cjs/context/EvmWalletServiceContext.d.ts +10 -0
  27. package/dist/cjs/context/EvmWalletServiceContext.js +55 -0
  28. package/dist/cjs/context/index.d.ts +2 -0
  29. package/dist/cjs/context/index.js +18 -0
  30. package/dist/cjs/core/EIP6963Connector.d.ts +17 -0
  31. package/dist/cjs/core/EIP6963Connector.js +127 -0
  32. package/dist/cjs/core/EthereumConnector.d.ts +43 -0
  33. package/dist/cjs/core/EthereumConnector.js +190 -0
  34. package/dist/cjs/core/MetaMask.d.ts +24 -0
  35. package/dist/cjs/core/MetaMask.js +159 -0
  36. package/dist/cjs/core/WalletConnect.d.ts +20 -0
  37. package/dist/cjs/core/WalletConnect.js +141 -0
  38. package/dist/cjs/core/index.d.ts +4 -0
  39. package/dist/cjs/core/index.js +20 -0
  40. package/dist/cjs/hooks/index.d.ts +4 -0
  41. package/dist/cjs/hooks/index.js +20 -0
  42. package/dist/cjs/hooks/useEIP6963Connections.d.ts +6 -0
  43. package/dist/cjs/hooks/useEIP6963Connections.js +47 -0
  44. package/dist/cjs/hooks/useFilteredConnections.d.ts +2 -0
  45. package/dist/cjs/hooks/useFilteredConnections.js +7 -0
  46. package/dist/cjs/hooks/useOrderedConnections.d.ts +2 -0
  47. package/dist/cjs/hooks/useOrderedConnections.js +41 -0
  48. package/dist/cjs/hooks/useRecentConnectionMeta.d.ts +15 -0
  49. package/dist/cjs/hooks/useRecentConnectionMeta.js +80 -0
  50. package/dist/cjs/index.d.ts +8 -0
  51. package/dist/cjs/index.js +24 -0
  52. package/dist/cjs/intl/index.d.ts +107 -0
  53. package/dist/cjs/intl/index.js +110 -0
  54. package/dist/cjs/services/EvmWalletService.d.ts +165 -0
  55. package/dist/cjs/services/EvmWalletService.js +430 -0
  56. package/dist/cjs/services/index.d.ts +1 -0
  57. package/dist/cjs/services/index.js +17 -0
  58. package/dist/cjs/tsconfig.cjs.tsbuildinfo +1 -0
  59. package/dist/cjs/types.d.ts +47 -0
  60. package/dist/cjs/types.js +15 -0
  61. package/dist/cjs/utils/get-evm-provider-platform-link.d.ts +2 -0
  62. package/dist/cjs/utils/get-evm-provider-platform-link.js +14 -0
  63. package/dist/cjs/utils/index.d.ts +2 -0
  64. package/dist/cjs/utils/index.js +18 -0
  65. package/dist/cjs/utils/parse-chain-id.d.ts +1 -0
  66. package/dist/cjs/utils/parse-chain-id.js +7 -0
  67. package/dist/esm/components/EvmConnectButton/index.d.ts +21 -0
  68. package/dist/esm/components/EvmConnectButton/index.js +26 -0
  69. package/dist/esm/components/EvmConnectDialog/index.css +130 -0
  70. package/dist/esm/components/EvmConnectDialog/index.d.ts +11 -0
  71. package/dist/esm/components/EvmConnectDialog/index.js +36 -0
  72. package/dist/esm/components/EvmConnector/index.css +37 -0
  73. package/dist/esm/components/EvmConnector/index.d.ts +20 -0
  74. package/dist/esm/components/EvmConnector/index.js +68 -0
  75. package/dist/esm/components/EvmProvidersDispatcher/ConnectionRequest/index.css +43 -0
  76. package/dist/esm/components/EvmProvidersDispatcher/ConnectionRequest/index.d.ts +3 -0
  77. package/dist/esm/components/EvmProvidersDispatcher/ConnectionRequest/index.js +35 -0
  78. package/dist/esm/components/EvmProvidersDispatcher/ProviderButton/index.css +54 -0
  79. package/dist/esm/components/EvmProvidersDispatcher/ProviderButton/index.d.ts +11 -0
  80. package/dist/esm/components/EvmProvidersDispatcher/ProviderButton/index.js +64 -0
  81. package/dist/esm/components/EvmProvidersDispatcher/index.css +13 -0
  82. package/dist/esm/components/EvmProvidersDispatcher/index.d.ts +5 -0
  83. package/dist/esm/components/EvmProvidersDispatcher/index.js +23 -0
  84. package/dist/esm/components/index.d.ts +4 -0
  85. package/dist/esm/components/index.js +4 -0
  86. package/dist/esm/constants.d.ts +1 -0
  87. package/dist/esm/constants.js +1 -0
  88. package/dist/esm/context/EvmWalletProvidersContext.d.ts +20 -0
  89. package/dist/esm/context/EvmWalletProvidersContext.js +68 -0
  90. package/dist/esm/context/EvmWalletServiceContext.d.ts +10 -0
  91. package/dist/esm/context/EvmWalletServiceContext.js +28 -0
  92. package/dist/esm/context/index.d.ts +2 -0
  93. package/dist/esm/context/index.js +2 -0
  94. package/dist/esm/core/EIP6963Connector.d.ts +17 -0
  95. package/dist/esm/core/EIP6963Connector.js +123 -0
  96. package/dist/esm/core/EthereumConnector.d.ts +43 -0
  97. package/dist/esm/core/EthereumConnector.js +186 -0
  98. package/dist/esm/core/MetaMask.d.ts +24 -0
  99. package/dist/esm/core/MetaMask.js +152 -0
  100. package/dist/esm/core/WalletConnect.d.ts +20 -0
  101. package/dist/esm/core/WalletConnect.js +134 -0
  102. package/dist/esm/core/index.d.ts +4 -0
  103. package/dist/esm/core/index.js +4 -0
  104. package/dist/esm/hooks/index.d.ts +4 -0
  105. package/dist/esm/hooks/index.js +4 -0
  106. package/dist/esm/hooks/useEIP6963Connections.d.ts +6 -0
  107. package/dist/esm/hooks/useEIP6963Connections.js +20 -0
  108. package/dist/esm/hooks/useFilteredConnections.d.ts +2 -0
  109. package/dist/esm/hooks/useFilteredConnections.js +3 -0
  110. package/dist/esm/hooks/useOrderedConnections.d.ts +2 -0
  111. package/dist/esm/hooks/useOrderedConnections.js +14 -0
  112. package/dist/esm/hooks/useRecentConnectionMeta.d.ts +15 -0
  113. package/dist/esm/hooks/useRecentConnectionMeta.js +51 -0
  114. package/dist/esm/index.d.ts +8 -0
  115. package/dist/esm/index.js +8 -0
  116. package/dist/esm/intl/index.d.ts +107 -0
  117. package/dist/esm/intl/index.js +108 -0
  118. package/dist/esm/services/EvmWalletService.d.ts +165 -0
  119. package/dist/esm/services/EvmWalletService.js +423 -0
  120. package/dist/esm/services/index.d.ts +1 -0
  121. package/dist/esm/services/index.js +1 -0
  122. package/dist/esm/tsconfig.esm.tsbuildinfo +1 -0
  123. package/dist/esm/types.d.ts +47 -0
  124. package/dist/esm/types.js +12 -0
  125. package/dist/esm/utils/get-evm-provider-platform-link.d.ts +2 -0
  126. package/dist/esm/utils/get-evm-provider-platform-link.js +10 -0
  127. package/dist/esm/utils/index.d.ts +2 -0
  128. package/dist/esm/utils/index.js +2 -0
  129. package/dist/esm/utils/parse-chain-id.d.ts +1 -0
  130. package/dist/esm/utils/parse-chain-id.js +3 -0
  131. package/package.json +82 -0
@@ -0,0 +1,64 @@
1
+ import { camelToSnake } from '@broxus/js-utils';
2
+ import { TokenIcon } from '@broxus/react-components';
3
+ import { Button, Text } from '@broxus/react-uikit';
4
+ import { reaction } from 'mobx';
5
+ import { observer } from 'mobx-react-lite';
6
+ import * as React from 'react';
7
+ import { useIntl } from 'react-intl';
8
+ import { useEvmWalletProviders, useEvmWalletService } from '../../../context';
9
+ import messages from '../../../intl';
10
+ import { ConnectionType } from '../../../types';
11
+ import { getEvmProviderPlatformLink } from '../../../utils';
12
+ import './index.css';
13
+ export const ProviderButton = observer((props) => {
14
+ const intl = useIntl();
15
+ const walletService = useEvmWalletService();
16
+ const walletProviders = useEvmWalletProviders();
17
+ const { providerConfig, onSelect: onSelectProvider } = props;
18
+ const [hasProvider, setHasProvider] = React.useState(() => {
19
+ if (providerConfig.connector.type === ConnectionType.WALLET_CONNECT_V2) {
20
+ return true;
21
+ }
22
+ return undefined;
23
+ });
24
+ const onSelect = async () => {
25
+ if (hasProvider) {
26
+ await walletProviders.connect(providerConfig);
27
+ onSelectProvider?.(providerConfig);
28
+ }
29
+ };
30
+ React.useEffect(() => reaction(() => providerConfig.connector, connector => {
31
+ if (connector.type !== ConnectionType.WALLET_CONNECT_V2) {
32
+ setHasProvider(connector.provider != null);
33
+ }
34
+ }, { fireImmediately: true }), [providerConfig.connector]);
35
+ if (hasProvider === undefined) {
36
+ return (React.createElement(Button, { className: "evm-connect-provider-button", disabled: true }, intl.formatMessage(messages.EVM_CONNECT_INITIALIZING_HINT)));
37
+ }
38
+ if (!hasProvider) {
39
+ const [platform = 'UNKNOWN', uri] = getEvmProviderPlatformLink({ ...providerConfig.info.links }) ?? [];
40
+ let text;
41
+ try {
42
+ text = intl.formatMessage(
43
+ // @ts-ignore
44
+ messages[`EVM_CONNECT_INSTALL_${camelToSnake(platform)}_PLATFORM`.toUpperCase()]);
45
+ }
46
+ catch { }
47
+ return (React.createElement(Button, { className: "evm-connect-provider-button", href: uri, rel: "noopener noreferrer", target: "_blank" },
48
+ React.createElement("span", { className: "evm-connect-provider-icon" }, typeof providerConfig.info.icon === 'string' ? (React.createElement(TokenIcon, { iconUrl: providerConfig.info.icon, size: 28 })) : (providerConfig.info.icon)),
49
+ React.createElement("span", { className: "evm-connect-provider-title" },
50
+ intl.formatMessage(messages.EVM_CONNECT_INSTALL_PROVIDER, {
51
+ providerName: providerConfig.info.name ?? '',
52
+ }),
53
+ React.createElement(Text, { className: "evm-connect-provider-subtitle", color: "muted", component: "div", size: "xsmall" }, text))));
54
+ }
55
+ const isConnected = walletService.isConnected && walletService.providerId === providerConfig.id;
56
+ const isConnecting = walletService.isConnecting && walletProviders.connectingProvider?.id === providerConfig.id;
57
+ return (React.createElement(Button, { className: "evm-connect-provider-button", disabled: isConnected || isConnecting, onClick: onSelect },
58
+ React.createElement("span", { className: "evm-connect-provider-icon" }, typeof providerConfig.info.icon === 'string' ? (React.createElement(TokenIcon, { iconUrl: providerConfig.info.icon, size: 28 })) : (providerConfig.info.icon)),
59
+ React.createElement("span", { className: "evm-connect-provider-title" },
60
+ providerConfig.info.name,
61
+ providerConfig.info.description && (React.createElement(Text, { className: "evm-connect-provider-subtitle", color: "muted", component: "div", size: "xsmall", wrap: "truncate" }, providerConfig.info.description))),
62
+ isConnected && (React.createElement("span", { className: "evm-connect-provider-connected" }, intl.formatMessage(messages.EVM_CONNECT_DISPATCHER_POPUP_CONNECTED_HINT))),
63
+ !isConnected && providerConfig.isRecent && (React.createElement("span", { className: "evm-connect-provider-recent" }, intl.formatMessage(messages.EVM_CONNECT_DISPATCHER_POPUP_RECENT_HINT)))));
64
+ });
@@ -0,0 +1,13 @@
1
+ .evm-connect-providers-dispatcher {
2
+ backface-visibility: hidden;
3
+ display: flex;
4
+ flex-direction: column;
5
+ height: inherit;
6
+ overflow: hidden;
7
+ transition: height var(--transition-fast-duration) var(--ease-in);
8
+ width: inherit;
9
+ }
10
+
11
+ .evm-connect-providers-list {
12
+ margin: 0;
13
+ }
@@ -0,0 +1,5 @@
1
+ import * as React from 'react';
2
+ import './index.css';
3
+ export declare const EvmProvidersDispatcher: (() => React.JSX.Element) & {
4
+ displayName: string;
5
+ };
@@ -0,0 +1,23 @@
1
+ import { List } from '@broxus/react-uikit';
2
+ import { observer } from 'mobx-react-lite';
3
+ import * as React from 'react';
4
+ import { ConnectionRequest } from '../../components/EvmProvidersDispatcher/ConnectionRequest';
5
+ import { ProviderButton } from '../../components/EvmProvidersDispatcher/ProviderButton';
6
+ import { useEvmWalletProviders } from '../../context';
7
+ import { useOrderedConnections } from '../../hooks';
8
+ import './index.css';
9
+ export const EvmProvidersDispatcher = observer(() => {
10
+ const walletProviders = useEvmWalletProviders();
11
+ const orderedProviders = useOrderedConnections(walletProviders.providers ?? []);
12
+ const dispatcher = React.useRef(null);
13
+ const content = React.useRef(null);
14
+ React.useLayoutEffect(() => {
15
+ if (dispatcher.current) {
16
+ const height = content.current?.clientHeight;
17
+ dispatcher.current.style.height = height ? `${height}px` : '';
18
+ }
19
+ });
20
+ return (React.createElement("div", { ref: dispatcher, className: "evm-connect-providers-dispatcher" },
21
+ React.createElement("div", { ref: content }, walletProviders.connectingProvider ? (React.createElement(ConnectionRequest, null)) : (React.createElement(List, { className: "evm-connect-providers-list" }, orderedProviders.map(providerConfig => (React.createElement(List.Item, { key: providerConfig.id },
22
+ React.createElement(ProviderButton, { providerConfig: providerConfig })))))))));
23
+ });
@@ -0,0 +1,4 @@
1
+ export * from '../components/EvmConnectButton';
2
+ export * from '../components/EvmConnectDialog';
3
+ export * from '../components/EvmConnector';
4
+ export * from '../components/EvmProvidersDispatcher';
@@ -0,0 +1,4 @@
1
+ export * from '../components/EvmConnectButton';
2
+ export * from '../components/EvmConnectDialog';
3
+ export * from '../components/EvmConnector';
4
+ export * from '../components/EvmProvidersDispatcher';
@@ -0,0 +1 @@
1
+ export declare const EVM_RECENT_CONNECTION = "EVM_RECENT_CONNECTION";
@@ -0,0 +1 @@
1
+ export const EVM_RECENT_CONNECTION = 'EVM_RECENT_CONNECTION';
@@ -0,0 +1,20 @@
1
+ import * as React from 'react';
2
+ import { type EvmWalletProviderConfig } from '../types';
3
+ export interface EvmWalletProvidersContextConsumer {
4
+ agreementsNote?: React.ReactNode;
5
+ connect: (providerConfig: EvmWalletProviderConfig) => Promise<void>;
6
+ connectingProvider?: EvmWalletProviderConfig | null;
7
+ error?: Error | null;
8
+ providers?: Readonly<EvmWalletProviderConfig[]>;
9
+ reset: VoidFunction;
10
+ }
11
+ export declare const EvmWalletProvidersContext: React.Context<EvmWalletProvidersContextConsumer | null>;
12
+ export declare function useEvmWalletProviders(): EvmWalletProvidersContextConsumer;
13
+ export type EvmWalletProvidersProviderProps = React.PropsWithChildren<{
14
+ agreementsNote?: React.ReactNode;
15
+ providers?: Readonly<EvmWalletProviderConfig[]>;
16
+ onConnected?: VoidFunction;
17
+ }>;
18
+ export declare const EvmWalletProvidersProvider: ((props: EvmWalletProvidersProviderProps) => React.JSX.Element) & {
19
+ displayName: string;
20
+ };
@@ -0,0 +1,68 @@
1
+ import { debug } from '@broxus/js-utils';
2
+ import { useContext } from '@broxus/react-uikit';
3
+ import { observer } from 'mobx-react-lite';
4
+ import * as React from 'react';
5
+ import { useEvmWalletService } from '../context/EvmWalletServiceContext';
6
+ import { useRecentConnectionMeta } from '../hooks';
7
+ export const EvmWalletProvidersContext = React.createContext(null);
8
+ export function useEvmWalletProviders() {
9
+ return useContext(EvmWalletProvidersContext);
10
+ }
11
+ export const EvmWalletProvidersProvider = observer((props) => {
12
+ const walletService = useEvmWalletService();
13
+ const [recentMeta, setRecentMeta] = useRecentConnectionMeta();
14
+ const { agreementsNote, children, providers = walletService.providers } = props;
15
+ const [error, setError] = React.useState(null);
16
+ const [connectingProvider, setConnectingProvider] = React.useState(null);
17
+ const connect = React.useCallback(async (providerConfig) => {
18
+ try {
19
+ setError(null);
20
+ setConnectingProvider(providerConfig);
21
+ const prevConnector = walletService.connector;
22
+ const chainParams = recentMeta?.chainId
23
+ ? walletService.networks.find(network => network.chainId === recentMeta.chainId) ?? 1
24
+ : 1;
25
+ debug(`Try to activate ${providerConfig.info.name} connection with chain`, typeof chainParams === 'number' ? chainParams : chainParams.chainId);
26
+ await providerConfig.connector?.connect(typeof chainParams === 'number' ? chainParams : {
27
+ blockExplorerUrls: [chainParams.explorer.baseUrl],
28
+ chainId: Number(chainParams.chainId),
29
+ chainName: chainParams.name,
30
+ nativeCurrency: {
31
+ decimals: 18,
32
+ name: chainParams.currency.name,
33
+ symbol: chainParams.currency.symbol,
34
+ },
35
+ rpcUrls: [chainParams.rpcUrl],
36
+ });
37
+ if (providerConfig.id !== walletService.providerId) {
38
+ await prevConnector?.disconnect(true);
39
+ }
40
+ setRecentMeta({
41
+ chainId: providerConfig.connector.chainId?.toString(),
42
+ disconnected: false,
43
+ providerId: providerConfig.id,
44
+ type: providerConfig.connector.type,
45
+ });
46
+ walletService.setState('providerId', providerConfig.id);
47
+ }
48
+ catch (e) {
49
+ setError(e);
50
+ }
51
+ }, [recentMeta, setRecentMeta, walletService]);
52
+ const reset = React.useCallback(() => {
53
+ setError(null);
54
+ setConnectingProvider(null);
55
+ }, []);
56
+ const context = React.useMemo(() => ({
57
+ agreementsNote,
58
+ connect,
59
+ connectingProvider,
60
+ error,
61
+ providers,
62
+ reset,
63
+ }), [agreementsNote, connect, connectingProvider, error, providers, reset]);
64
+ return React.createElement(EvmWalletProvidersContext.Provider, { value: context }, children);
65
+ });
66
+ if (process.env.NODE_ENV !== 'production') {
67
+ EvmWalletProvidersContext.displayName = 'EvmWalletProvidersContext';
68
+ }
@@ -0,0 +1,10 @@
1
+ import * as React from 'react';
2
+ import { EvmWalletService, type EvmWalletServiceCtorParams } from '../services';
3
+ export declare const EvmWalletServiceContext: React.Context<EvmWalletService | null>;
4
+ export declare function useEvmWalletService(): EvmWalletService;
5
+ type EvmWalletProviderProps = React.PropsWithChildren<{
6
+ params?: EvmWalletServiceCtorParams;
7
+ wallet?: EvmWalletService;
8
+ }>;
9
+ export declare const EvmWalletServiceProvider: React.MemoExoticComponent<({ children, params, wallet, }: EvmWalletProviderProps) => React.JSX.Element>;
10
+ export {};
@@ -0,0 +1,28 @@
1
+ import { useContext } from '@broxus/react-uikit';
2
+ import { reaction } from 'mobx';
3
+ import * as React from 'react';
4
+ import { getRecentConnectionMeta, useRecentConnectionMeta } from '../hooks';
5
+ import { EvmWalletService } from '../services';
6
+ export const EvmWalletServiceContext = React.createContext(null);
7
+ export function useEvmWalletService() {
8
+ return useContext(EvmWalletServiceContext);
9
+ }
10
+ export const EvmWalletServiceProvider = React.memo(({ children, params, wallet, }) => {
11
+ const [, setRecentMeta] = useRecentConnectionMeta();
12
+ const context = React.useMemo(() => {
13
+ if (wallet instanceof EvmWalletService) {
14
+ return wallet;
15
+ }
16
+ return new EvmWalletService({ ...params });
17
+ }, [params, wallet]);
18
+ React.useEffect(() => reaction(() => context.chainId, chainId => {
19
+ if (chainId) {
20
+ const recentMeta = getRecentConnectionMeta();
21
+ setRecentMeta({ ...recentMeta, chainId: chainId.toString() });
22
+ }
23
+ }, { delay: 10, fireImmediately: context.isReady }), [context, setRecentMeta]);
24
+ return React.createElement(EvmWalletServiceContext.Provider, { value: context }, children);
25
+ });
26
+ if (process.env.NODE_ENV !== 'production') {
27
+ EvmWalletServiceContext.displayName = 'EvmWalletServiceContext';
28
+ }
@@ -0,0 +1,2 @@
1
+ export * from '../context/EvmWalletProvidersContext';
2
+ export * from '../context/EvmWalletServiceContext';
@@ -0,0 +1,2 @@
1
+ export * from '../context/EvmWalletProvidersContext';
2
+ export * from '../context/EvmWalletServiceContext';
@@ -0,0 +1,17 @@
1
+ import { type EIP6963ProviderInfo } from 'web3/lib/commonjs/web3_eip6963';
2
+ import { type EthExecutionAPI, type ProviderConnectInfo } from 'web3-types';
3
+ import { EthereumConnector, type EthereumConnectorCtorParams } from '../core';
4
+ import { type AddEthereumChainParams, ConnectionType, type SupportedProviders } from '../types';
5
+ export interface EIP6963ConnectorCtorParams extends EthereumConnectorCtorParams {
6
+ info: EIP6963ProviderInfo;
7
+ provider: Readonly<SupportedProviders<EthExecutionAPI>>;
8
+ }
9
+ export declare class EIP6963Connector extends EthereumConnector {
10
+ protected readonly params: Readonly<EIP6963ConnectorCtorParams>;
11
+ readonly type = ConnectionType.EIP_6963_INJECTED;
12
+ constructor(params: Readonly<EIP6963ConnectorCtorParams>);
13
+ connect(chainIdOrParams?: number | AddEthereumChainParams): Promise<void>;
14
+ disconnect(): Promise<void>;
15
+ protected init(): Promise<void>;
16
+ protected handleConnect({ chainId }: ProviderConnectInfo): void;
17
+ }
@@ -0,0 +1,123 @@
1
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
2
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
6
+ };
7
+ var __metadata = (this && this.__metadata) || function (k, v) {
8
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
9
+ };
10
+ import { debug, error, throwException } from '@broxus/js-utils';
11
+ import { action, makeObservable } from 'mobx';
12
+ import { EthereumConnector } from '../core';
13
+ import { ConnectionType } from '../types';
14
+ import { parseChainId } from '../utils';
15
+ export class EIP6963Connector extends EthereumConnector {
16
+ params;
17
+ type = ConnectionType.EIP_6963_INJECTED;
18
+ constructor(params) {
19
+ super(params);
20
+ this.params = params;
21
+ this.provider = params.provider;
22
+ makeObservable(this);
23
+ this.provider.on('accountsChanged', this.handleAccountsChanged);
24
+ this.provider.on('chainChanged', this.handleChainChanged);
25
+ this.provider.on('connect', this.handleConnect);
26
+ this.provider.on('disconnect', this.handleDisconnect);
27
+ this.init().catch(error);
28
+ }
29
+ async connect(chainIdOrParams) {
30
+ if (!this.provider) {
31
+ throw new Error('Provider is not defined');
32
+ }
33
+ try {
34
+ this.setState('isConnecting', true);
35
+ const accounts = (await this.provider.request({ method: 'eth_requestAccounts' }));
36
+ const chainId = (await this.provider.request({ method: 'eth_chainId' }));
37
+ debug(`Connect to ${this.params.info.name} connection`, accounts, chainId);
38
+ const receivedChainId = parseChainId(chainId);
39
+ const desiredChainId = typeof chainIdOrParams === 'number' ? chainIdOrParams : chainIdOrParams?.chainId;
40
+ if (!desiredChainId || receivedChainId === desiredChainId) {
41
+ this.setData({ accounts, chainId: receivedChainId });
42
+ this.setState({ isConnecting: false, isInitialized: true });
43
+ debug(`${this.params.info.name} connection has skipped network switching.`);
44
+ return;
45
+ }
46
+ if (!chainIdOrParams) {
47
+ debug(`${this.params.info.name} connection has skipped network switching. Chain params or chainId is not provided.`);
48
+ return;
49
+ }
50
+ debug(`${this.params.info.name} connection trying to switch network.`);
51
+ await this.switchNetwork(chainIdOrParams).then(async () => {
52
+ await this.connect(desiredChainId);
53
+ });
54
+ }
55
+ catch (e) {
56
+ this.setState('isConnecting', false);
57
+ throw e;
58
+ }
59
+ }
60
+ async disconnect() {
61
+ if (!this.provider) {
62
+ this.setState('isDisconnecting', false);
63
+ return;
64
+ }
65
+ try {
66
+ debug(`Disconnect from ${this.params.info.name} connection`);
67
+ this.setState('isDisconnecting', true);
68
+ this.setData({ accounts: undefined, chainId: undefined });
69
+ this.setState('isDisconnecting', false);
70
+ }
71
+ catch (e) {
72
+ this.setState('isDisconnecting', false);
73
+ throw e;
74
+ }
75
+ }
76
+ async init() {
77
+ this.setState('isInitializing', true);
78
+ if (!this.provider) {
79
+ this.setState({ isInitialized: false, isInitializing: false });
80
+ return;
81
+ }
82
+ try {
83
+ const accounts = (await this.provider.request({ method: 'eth_accounts' }));
84
+ if (!accounts.length) {
85
+ throwException('No accounts returned');
86
+ }
87
+ const chainId = (await this.provider.request({ method: 'eth_chainId' }));
88
+ this.setData({ accounts, chainId: parseChainId(chainId) });
89
+ this.setState({ isInitialized: true, isInitializing: false });
90
+ }
91
+ catch (e) {
92
+ debug(`${this.params.info.name} could not be pre-connected`, e);
93
+ this.setState({ isInitialized: false, isInitializing: false });
94
+ }
95
+ }
96
+ handleConnect({ chainId }) {
97
+ this.setData({ chainId: parseChainId(chainId) });
98
+ }
99
+ }
100
+ __decorate([
101
+ action.bound,
102
+ __metadata("design:type", Function),
103
+ __metadata("design:paramtypes", [Object]),
104
+ __metadata("design:returntype", Promise)
105
+ ], EIP6963Connector.prototype, "connect", null);
106
+ __decorate([
107
+ action.bound,
108
+ __metadata("design:type", Function),
109
+ __metadata("design:paramtypes", []),
110
+ __metadata("design:returntype", Promise)
111
+ ], EIP6963Connector.prototype, "disconnect", null);
112
+ __decorate([
113
+ action.bound,
114
+ __metadata("design:type", Function),
115
+ __metadata("design:paramtypes", []),
116
+ __metadata("design:returntype", Promise)
117
+ ], EIP6963Connector.prototype, "init", null);
118
+ __decorate([
119
+ action.bound,
120
+ __metadata("design:type", Function),
121
+ __metadata("design:paramtypes", [Object]),
122
+ __metadata("design:returntype", void 0)
123
+ ], EIP6963Connector.prototype, "handleConnect", null);
@@ -0,0 +1,43 @@
1
+ import { AbstractStore } from '@broxus/js-core';
2
+ import { type EthExecutionAPI, type ProviderRpcError } from 'web3-types';
3
+ import { type AddEthereumChainParams, type ConnectionType, type SupportedProviders, type WatchAssetParameters } from '../types';
4
+ export interface EthereumConnectorCtorParams {
5
+ onDisconnect?: (err: ProviderRpcError) => Promise<void> | void;
6
+ }
7
+ export interface EthereumConnectorData {
8
+ accounts?: string[];
9
+ chainId?: number;
10
+ }
11
+ export interface EthereumConnectorState {
12
+ isConnecting?: boolean;
13
+ isDisconnecting?: boolean;
14
+ isInitialized?: boolean;
15
+ isInitializing?: boolean;
16
+ }
17
+ export declare abstract class EthereumConnector extends AbstractStore<EthereumConnectorData, EthereumConnectorState> {
18
+ protected readonly params?: Readonly<EthereumConnectorCtorParams> | undefined;
19
+ readonly type?: ConnectionType;
20
+ /**
21
+ * An
22
+ * EIP-1193 ({@link https://github.com/ethereum/EIPs/blob/master/EIPS/eip-1193.md}) and
23
+ * EIP-1102 ({@link https://github.com/ethereum/EIPs/blob/master/EIPS/eip-1102.md}) compliant provider.
24
+ * May also comply with EIP-3085 ({@link https://github.com/ethereum/EIPs/blob/master/EIPS/eip-3085.md}).
25
+ * This property must be defined while the connector is active.
26
+ */
27
+ provider?: SupportedProviders<EthExecutionAPI>;
28
+ protected constructor(params?: Readonly<EthereumConnectorCtorParams> | undefined);
29
+ abstract connect(...args: unknown[]): Promise<void>;
30
+ abstract disconnect(...args: unknown[]): Promise<void>;
31
+ addNetwork(chainParams: AddEthereumChainParams): Promise<void>;
32
+ switchNetwork(chainIdOrParams: number | AddEthereumChainParams): Promise<void>;
33
+ watchAsset(params: WatchAssetParameters): Promise<true>;
34
+ get accounts(): EthereumConnectorData['accounts'];
35
+ get chainId(): EthereumConnectorData['chainId'];
36
+ get isConnecting(): EthereumConnectorState['isConnecting'];
37
+ get isDisconnecting(): EthereumConnectorState['isDisconnecting'];
38
+ get isInitialized(): EthereumConnectorState['isInitialized'];
39
+ get isInitializing(): EthereumConnectorState['isInitializing'];
40
+ protected handleAccountsChanged(accounts: string[]): void;
41
+ protected handleChainChanged(chainId: string): void;
42
+ protected handleDisconnect(err: ProviderRpcError): void;
43
+ }
@@ -0,0 +1,186 @@
1
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
2
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
6
+ };
7
+ var __metadata = (this && this.__metadata) || function (k, v) {
8
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
9
+ };
10
+ import { AbstractStore } from '@broxus/js-core';
11
+ import { debug } from '@broxus/js-utils';
12
+ import { action, computed, observable } from 'mobx';
13
+ export class EthereumConnector extends AbstractStore {
14
+ params;
15
+ type;
16
+ /**
17
+ * An
18
+ * EIP-1193 ({@link https://github.com/ethereum/EIPs/blob/master/EIPS/eip-1193.md}) and
19
+ * EIP-1102 ({@link https://github.com/ethereum/EIPs/blob/master/EIPS/eip-1102.md}) compliant provider.
20
+ * May also comply with EIP-3085 ({@link https://github.com/ethereum/EIPs/blob/master/EIPS/eip-3085.md}).
21
+ * This property must be defined while the connector is active.
22
+ */
23
+ provider;
24
+ constructor(params) {
25
+ super();
26
+ this.params = params;
27
+ }
28
+ async addNetwork(chainParams) {
29
+ if (!this.provider) {
30
+ throw new Error('Provider is not defined');
31
+ }
32
+ await this.provider.request({
33
+ method: 'wallet_addEthereumChain',
34
+ params: [{ ...chainParams }],
35
+ });
36
+ }
37
+ async switchNetwork(chainIdOrParams) {
38
+ if (!this.provider) {
39
+ throw new Error('Provider is not defined');
40
+ }
41
+ try {
42
+ const chainId = typeof chainIdOrParams === 'number' ? chainIdOrParams : chainIdOrParams?.chainId;
43
+ const desiredChainId = `0x${chainId.toString(16)}`;
44
+ await this.provider.request({
45
+ method: 'wallet_switchEthereumChain',
46
+ params: [{ chainId: desiredChainId }],
47
+ });
48
+ }
49
+ catch (e) {
50
+ // https://github.com/MetaMask/metamask-mobile/issues/3312#issuecomment-1065923294
51
+ const errorCode = e.data?.originalError?.code || e.code;
52
+ // 4902 indicates that the chain has not been added to MetaMask and wallet_addEthereumChain needs to be called
53
+ // https://docs.metamask.io/guide/rpc-api.html#wallet-switchethereumchain
54
+ if (errorCode === 4902 && typeof chainIdOrParams !== 'number') {
55
+ await this.addNetwork(chainIdOrParams);
56
+ }
57
+ else {
58
+ throw e;
59
+ }
60
+ }
61
+ }
62
+ async watchAsset(params) {
63
+ if (!this.provider) {
64
+ throw new Error('Provider is not defined');
65
+ }
66
+ return this.provider
67
+ .request({
68
+ method: 'wallet_watchAsset',
69
+ params: {
70
+ options: {
71
+ address: params.address, // The address that the token is at.
72
+ decimals: params.decimals, // The number of decimals in the token
73
+ image: params.image, // A string url of the token logo
74
+ symbol: params.symbol, // A ticker symbol or shorthand, up to 5 chars.
75
+ },
76
+ type: 'ERC20', // Initially only supports ERC20, but eventually more!
77
+ },
78
+ })
79
+ .then(result => {
80
+ if (!result) {
81
+ throw new Error('Watch asset request was rejected');
82
+ }
83
+ return true;
84
+ });
85
+ }
86
+ get accounts() {
87
+ return this._data.accounts;
88
+ }
89
+ get chainId() {
90
+ return this._data.chainId;
91
+ }
92
+ get isConnecting() {
93
+ return this._state.isConnecting;
94
+ }
95
+ get isDisconnecting() {
96
+ return this._state.isDisconnecting;
97
+ }
98
+ get isInitialized() {
99
+ return this._state.isInitialized;
100
+ }
101
+ get isInitializing() {
102
+ return this._state.isInitializing;
103
+ }
104
+ handleAccountsChanged(accounts) {
105
+ debug(`Accounts have been changed to ${accounts}`);
106
+ this.setData({ accounts });
107
+ }
108
+ handleChainChanged(chainId) {
109
+ debug(`Chain has been changed to ${chainId}`);
110
+ this.setData({ chainId: Number.parseInt(chainId, 16) });
111
+ }
112
+ handleDisconnect(err) {
113
+ this.setData(() => ({}));
114
+ this.params?.onDisconnect?.(err);
115
+ }
116
+ }
117
+ __decorate([
118
+ observable,
119
+ __metadata("design:type", Object)
120
+ ], EthereumConnector.prototype, "provider", void 0);
121
+ __decorate([
122
+ action.bound,
123
+ __metadata("design:type", Function),
124
+ __metadata("design:paramtypes", [Object]),
125
+ __metadata("design:returntype", Promise)
126
+ ], EthereumConnector.prototype, "addNetwork", null);
127
+ __decorate([
128
+ action.bound,
129
+ __metadata("design:type", Function),
130
+ __metadata("design:paramtypes", [Object]),
131
+ __metadata("design:returntype", Promise)
132
+ ], EthereumConnector.prototype, "switchNetwork", null);
133
+ __decorate([
134
+ action.bound,
135
+ __metadata("design:type", Function),
136
+ __metadata("design:paramtypes", [Object]),
137
+ __metadata("design:returntype", Promise)
138
+ ], EthereumConnector.prototype, "watchAsset", null);
139
+ __decorate([
140
+ computed,
141
+ __metadata("design:type", Object),
142
+ __metadata("design:paramtypes", [])
143
+ ], EthereumConnector.prototype, "accounts", null);
144
+ __decorate([
145
+ computed,
146
+ __metadata("design:type", Object),
147
+ __metadata("design:paramtypes", [])
148
+ ], EthereumConnector.prototype, "chainId", null);
149
+ __decorate([
150
+ computed,
151
+ __metadata("design:type", Object),
152
+ __metadata("design:paramtypes", [])
153
+ ], EthereumConnector.prototype, "isConnecting", null);
154
+ __decorate([
155
+ computed,
156
+ __metadata("design:type", Object),
157
+ __metadata("design:paramtypes", [])
158
+ ], EthereumConnector.prototype, "isDisconnecting", null);
159
+ __decorate([
160
+ computed,
161
+ __metadata("design:type", Object),
162
+ __metadata("design:paramtypes", [])
163
+ ], EthereumConnector.prototype, "isInitialized", null);
164
+ __decorate([
165
+ computed,
166
+ __metadata("design:type", Object),
167
+ __metadata("design:paramtypes", [])
168
+ ], EthereumConnector.prototype, "isInitializing", null);
169
+ __decorate([
170
+ action.bound,
171
+ __metadata("design:type", Function),
172
+ __metadata("design:paramtypes", [Array]),
173
+ __metadata("design:returntype", void 0)
174
+ ], EthereumConnector.prototype, "handleAccountsChanged", null);
175
+ __decorate([
176
+ action.bound,
177
+ __metadata("design:type", Function),
178
+ __metadata("design:paramtypes", [String]),
179
+ __metadata("design:returntype", void 0)
180
+ ], EthereumConnector.prototype, "handleChainChanged", null);
181
+ __decorate([
182
+ action.bound,
183
+ __metadata("design:type", Function),
184
+ __metadata("design:paramtypes", [Object]),
185
+ __metadata("design:returntype", void 0)
186
+ ], EthereumConnector.prototype, "handleDisconnect", null);