@rango-dev/wallets-react 0.0.0-experimental-936229e8-20251208
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.
- package/CHANGELOG.md +265 -0
- package/dist/helpers/index.d.ts +2 -0
- package/dist/helpers/index.d.ts.map +1 -0
- package/dist/helpers/index.js +2 -0
- package/dist/helpers/index.js.map +7 -0
- package/dist/hub/autoConnect.d.ts +11 -0
- package/dist/hub/autoConnect.d.ts.map +1 -0
- package/dist/hub/constants.d.ts +3 -0
- package/dist/hub/constants.d.ts.map +1 -0
- package/dist/hub/helpers.d.ts +33 -0
- package/dist/hub/helpers.d.ts.map +1 -0
- package/dist/hub/lastConnectedWallets.d.ts +22 -0
- package/dist/hub/lastConnectedWallets.d.ts.map +1 -0
- package/dist/hub/mod.d.ts +3 -0
- package/dist/hub/mod.d.ts.map +1 -0
- package/dist/hub/types.d.ts +4 -0
- package/dist/hub/types.d.ts.map +1 -0
- package/dist/hub/useHubAdapter.d.ts +11 -0
- package/dist/hub/useHubAdapter.d.ts.map +1 -0
- package/dist/hub/useHubRefs.d.ts +7 -0
- package/dist/hub/useHubRefs.d.ts.map +1 -0
- package/dist/hub/utils.d.ts +52 -0
- package/dist/hub/utils.d.ts.map +1 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +2 -0
- package/dist/index.js.map +7 -0
- package/dist/legacy/autoConnect.d.ts +8 -0
- package/dist/legacy/autoConnect.d.ts.map +1 -0
- package/dist/legacy/context.d.ts +3 -0
- package/dist/legacy/context.d.ts.map +1 -0
- package/dist/legacy/helpers.d.ts +23 -0
- package/dist/legacy/helpers.d.ts.map +1 -0
- package/dist/legacy/hooks.d.ts +10 -0
- package/dist/legacy/hooks.d.ts.map +1 -0
- package/dist/legacy/mod.d.ts +5 -0
- package/dist/legacy/mod.d.ts.map +1 -0
- package/dist/legacy/types.d.ts +143 -0
- package/dist/legacy/types.d.ts.map +1 -0
- package/dist/legacy/useAutoConnect.d.ts +8 -0
- package/dist/legacy/useAutoConnect.d.ts.map +1 -0
- package/dist/legacy/useLegacyProviders.d.ts +7 -0
- package/dist/legacy/useLegacyProviders.d.ts.map +1 -0
- package/dist/legacy/utils.d.ts +3 -0
- package/dist/legacy/utils.d.ts.map +1 -0
- package/dist/provider.d.ts +5 -0
- package/dist/provider.d.ts.map +1 -0
- package/dist/test-utils/env.d.ts +7 -0
- package/dist/test-utils/env.d.ts.map +1 -0
- package/dist/test-utils/fixtures.d.ts +14 -0
- package/dist/test-utils/fixtures.d.ts.map +1 -0
- package/dist/useProviders.d.ts +4 -0
- package/dist/useProviders.d.ts.map +1 -0
- package/dist/wallets-react.build.json +1 -0
- package/helpers/package.json +8 -0
- package/package.json +50 -0
- package/readme.md +3 -0
- package/src/helpers/index.ts +1 -0
- package/src/hub/autoConnect.ts +276 -0
- package/src/hub/constants.ts +2 -0
- package/src/hub/helpers.ts +179 -0
- package/src/hub/lastConnectedWallets.ts +166 -0
- package/src/hub/mod.ts +6 -0
- package/src/hub/types.ts +12 -0
- package/src/hub/useHubAdapter.ts +516 -0
- package/src/hub/useHubRefs.ts +50 -0
- package/src/hub/utils.ts +393 -0
- package/src/index.ts +4 -0
- package/src/legacy/autoConnect.ts +66 -0
- package/src/legacy/context.ts +39 -0
- package/src/legacy/helpers.ts +183 -0
- package/src/legacy/hooks.ts +54 -0
- package/src/legacy/mod.ts +13 -0
- package/src/legacy/types.ts +195 -0
- package/src/legacy/useAutoConnect.ts +23 -0
- package/src/legacy/useLegacyProviders.ts +241 -0
- package/src/legacy/utils.ts +7 -0
- package/src/provider.tsx +18 -0
- package/src/test-utils/env.ts +10 -0
- package/src/test-utils/fixtures.ts +238 -0
- package/src/useProviders.ts +120 -0
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import type { ProviderContext, WalletActions, WalletConfig } from './types.js';
|
|
2
|
+
import type { LegacyEventHandler as WalletEventHandler } from '@rango-dev/wallets-core/legacy';
|
|
3
|
+
|
|
4
|
+
import { LegacyWallet as Wallet } from '@rango-dev/wallets-core/legacy';
|
|
5
|
+
import { useContext, useRef } from 'react';
|
|
6
|
+
|
|
7
|
+
import { WalletContext } from './context.js';
|
|
8
|
+
|
|
9
|
+
export type GetWalletInstance = (wallet: {
|
|
10
|
+
actions: WalletActions;
|
|
11
|
+
config: WalletConfig;
|
|
12
|
+
}) => Wallet;
|
|
13
|
+
|
|
14
|
+
export function useInitializers(
|
|
15
|
+
onChangeState: WalletEventHandler
|
|
16
|
+
): GetWalletInstance {
|
|
17
|
+
const availableWallets = useRef<{
|
|
18
|
+
[key: string]: Wallet | undefined;
|
|
19
|
+
}>({});
|
|
20
|
+
|
|
21
|
+
/*
|
|
22
|
+
* If `wallet` hasn't been added to `availableWallets`,
|
|
23
|
+
* Get a instance of `Wallet` and save the refrence in `availableWallets`.
|
|
24
|
+
* Otherwise, return the already created instance.
|
|
25
|
+
*/
|
|
26
|
+
function updater(wallet: {
|
|
27
|
+
actions: WalletActions;
|
|
28
|
+
config: WalletConfig;
|
|
29
|
+
}): Wallet {
|
|
30
|
+
const type = wallet.config.type;
|
|
31
|
+
// We only update, if there is no instance available.
|
|
32
|
+
if (typeof availableWallets.current[type] === 'undefined') {
|
|
33
|
+
availableWallets.current[type] = new Wallet(
|
|
34
|
+
{
|
|
35
|
+
config: wallet.config,
|
|
36
|
+
handler: onChangeState,
|
|
37
|
+
},
|
|
38
|
+
wallet.actions
|
|
39
|
+
);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
return availableWallets.current[type]!;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
return updater;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
export function useWallets(): ProviderContext {
|
|
49
|
+
const context = useContext(WalletContext);
|
|
50
|
+
if (!context) {
|
|
51
|
+
throw Error('useWallet can only be used within the Provider component');
|
|
52
|
+
}
|
|
53
|
+
return context;
|
|
54
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export type {
|
|
2
|
+
ProviderProps,
|
|
3
|
+
ProviderContext,
|
|
4
|
+
ConnectResult,
|
|
5
|
+
ExtendedWalletInfo,
|
|
6
|
+
} from './types.js';
|
|
7
|
+
export {
|
|
8
|
+
LEGACY_LAST_CONNECTED_WALLETS,
|
|
9
|
+
HUB_LAST_CONNECTED_WALLETS,
|
|
10
|
+
} from '../hub/constants.js';
|
|
11
|
+
|
|
12
|
+
export { WalletContext } from './context.js';
|
|
13
|
+
export { useLegacyProviders } from './useLegacyProviders.js';
|
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
Provider,
|
|
3
|
+
ProviderMetadata,
|
|
4
|
+
VersionedProviders,
|
|
5
|
+
} from '@rango-dev/wallets-core';
|
|
6
|
+
import type {
|
|
7
|
+
LegacyNamespaceInputForConnect,
|
|
8
|
+
LegacyProviderInterface,
|
|
9
|
+
LegacyNetwork as Network,
|
|
10
|
+
LegacyEventHandler as WalletEventHandler,
|
|
11
|
+
LegacyWalletInfo as WalletInfo,
|
|
12
|
+
LegacyState as WalletState,
|
|
13
|
+
LegacyWalletType as WalletType,
|
|
14
|
+
} from '@rango-dev/wallets-core/legacy';
|
|
15
|
+
import type { Namespace } from '@rango-dev/wallets-core/namespaces/common';
|
|
16
|
+
import type { NamespaceData } from '@rango-dev/wallets-core/store';
|
|
17
|
+
import type { BlockchainMeta, SignerFactory } from 'rango-types';
|
|
18
|
+
import type { PropsWithChildren } from 'react';
|
|
19
|
+
|
|
20
|
+
import { LegacyEvents as Events } from '@rango-dev/wallets-core/legacy';
|
|
21
|
+
|
|
22
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
23
|
+
type InstanceType = any;
|
|
24
|
+
|
|
25
|
+
export type State = {
|
|
26
|
+
[key: string]: WalletState | undefined;
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
export type ConnectResult = {
|
|
30
|
+
accounts: string[] | null;
|
|
31
|
+
network: Network | null;
|
|
32
|
+
provider: InstanceType;
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
export type Providers = { [type in WalletType]?: InstanceType };
|
|
36
|
+
|
|
37
|
+
export type ExtendedWalletInfo = WalletInfo & {
|
|
38
|
+
properties?: ProviderMetadata['properties'];
|
|
39
|
+
isHub?: boolean;
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
export type ProviderContext = {
|
|
43
|
+
connect(
|
|
44
|
+
type: WalletType,
|
|
45
|
+
namespaces?: LegacyNamespaceInputForConnect[]
|
|
46
|
+
): Promise<ConnectResult[]>;
|
|
47
|
+
disconnect(type: WalletType, namespaces?: Namespace[]): Promise<void>;
|
|
48
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
49
|
+
disconnectAll(): Promise<PromiseSettledResult<any>[]>;
|
|
50
|
+
|
|
51
|
+
state(
|
|
52
|
+
type: WalletType
|
|
53
|
+
): WalletState & { namespaces?: Map<Namespace, NamespaceData> };
|
|
54
|
+
canSwitchNetworkTo(
|
|
55
|
+
type: WalletType,
|
|
56
|
+
network: Network,
|
|
57
|
+
namespace?: LegacyNamespaceInputForConnect
|
|
58
|
+
): boolean;
|
|
59
|
+
/**
|
|
60
|
+
* `Provider` in legacy terms means injected instances by wallets into window (e.g. window.ethereum)
|
|
61
|
+
* that can be retrieved by `getInstance`.
|
|
62
|
+
*
|
|
63
|
+
* Note 1: Providers are lazy evaluated, which means you need to call `connect` (or `state`) first, then the value will be shown in object.
|
|
64
|
+
* before doing that, it's a key (wallet name or we call it `type` to be more specific) with null value. (e.g. {metamask: null})
|
|
65
|
+
*/
|
|
66
|
+
providers(): Providers;
|
|
67
|
+
getSigners(type: WalletType): Promise<SignerFactory>;
|
|
68
|
+
getWalletInfo(type: WalletType): ExtendedWalletInfo;
|
|
69
|
+
suggestAndConnect(type: WalletType, network: Network): Promise<ConnectResult>;
|
|
70
|
+
hubProvider(type: WalletType): Provider;
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
export type ProviderProps = PropsWithChildren<{
|
|
74
|
+
onUpdateState?: WalletEventHandler;
|
|
75
|
+
allBlockChains?: BlockchainMeta[];
|
|
76
|
+
autoConnect?: boolean;
|
|
77
|
+
providers: VersionedProviders[];
|
|
78
|
+
configs?: {
|
|
79
|
+
wallets?: (WalletType | LegacyProviderInterface | Provider)[];
|
|
80
|
+
};
|
|
81
|
+
}>;
|
|
82
|
+
|
|
83
|
+
export { Events };
|
|
84
|
+
|
|
85
|
+
export type ProviderConnectResult = {
|
|
86
|
+
accounts: string[];
|
|
87
|
+
chainId: string;
|
|
88
|
+
derivationPath?: string;
|
|
89
|
+
};
|
|
90
|
+
|
|
91
|
+
export type GetInstanceOptions = {
|
|
92
|
+
network?: Network;
|
|
93
|
+
currentProvider: InstanceType;
|
|
94
|
+
meta: BlockchainMeta[];
|
|
95
|
+
getState: () => WalletState;
|
|
96
|
+
/**
|
|
97
|
+
* We always get the instance once and reuse it whenever we needs. By using this option
|
|
98
|
+
* We can force the library to get a new instance and replace it with the old one.
|
|
99
|
+
*
|
|
100
|
+
* Originally, we used this option for wallet connect 1 and its switching network challenge.
|
|
101
|
+
*/
|
|
102
|
+
force?: boolean;
|
|
103
|
+
updateChainId: (chainId: number | string) => void;
|
|
104
|
+
};
|
|
105
|
+
|
|
106
|
+
export type GetInstance =
|
|
107
|
+
| (() => InstanceType)
|
|
108
|
+
| ((options: GetInstanceOptions) => Promise<InstanceType>);
|
|
109
|
+
export type TryGetInstance =
|
|
110
|
+
| (() => InstanceType)
|
|
111
|
+
| ((
|
|
112
|
+
options: Pick<GetInstanceOptions, 'force' | 'network'>
|
|
113
|
+
) => Promise<InstanceType>);
|
|
114
|
+
export type Connect = (options: {
|
|
115
|
+
instance: InstanceType;
|
|
116
|
+
network?: Network;
|
|
117
|
+
meta: BlockchainMeta[];
|
|
118
|
+
}) => Promise<ProviderConnectResult | ProviderConnectResult[]>;
|
|
119
|
+
|
|
120
|
+
export type Disconnect = (options: {
|
|
121
|
+
instance: InstanceType;
|
|
122
|
+
destroyInstance: () => void;
|
|
123
|
+
}) => Promise<void>;
|
|
124
|
+
|
|
125
|
+
type CleanupSubscribe = () => void;
|
|
126
|
+
|
|
127
|
+
export type Subscribe = (options: {
|
|
128
|
+
instance: InstanceType;
|
|
129
|
+
state: WalletState;
|
|
130
|
+
meta: BlockchainMeta[];
|
|
131
|
+
updateChainId: (chainId: string) => void;
|
|
132
|
+
updateAccounts: (accounts: string[], chainId?: string) => void;
|
|
133
|
+
connect: (network?: Network) => void;
|
|
134
|
+
disconnect: () => void;
|
|
135
|
+
}) => CleanupSubscribe | void;
|
|
136
|
+
|
|
137
|
+
export type SwitchNetwork = (options: {
|
|
138
|
+
instance: InstanceType;
|
|
139
|
+
network: Network;
|
|
140
|
+
meta: BlockchainMeta[];
|
|
141
|
+
newInstance?: TryGetInstance;
|
|
142
|
+
getState?: () => WalletState;
|
|
143
|
+
updateChainId: (chainId: string) => void;
|
|
144
|
+
}) => Promise<void>;
|
|
145
|
+
|
|
146
|
+
export type Suggest = (options: {
|
|
147
|
+
instance: InstanceType;
|
|
148
|
+
network: Network;
|
|
149
|
+
meta: BlockchainMeta[];
|
|
150
|
+
}) => Promise<void>;
|
|
151
|
+
|
|
152
|
+
export type CanSwitchNetwork = (options: {
|
|
153
|
+
network: Network;
|
|
154
|
+
meta: BlockchainMeta[];
|
|
155
|
+
provider: InstanceType;
|
|
156
|
+
}) => boolean;
|
|
157
|
+
|
|
158
|
+
export type CanEagerConnect = (options: {
|
|
159
|
+
instance: InstanceType;
|
|
160
|
+
meta: BlockchainMeta[];
|
|
161
|
+
}) => Promise<boolean>;
|
|
162
|
+
|
|
163
|
+
export interface WalletActions {
|
|
164
|
+
connect: Connect;
|
|
165
|
+
getInstance: InstanceType;
|
|
166
|
+
disconnect?: Disconnect;
|
|
167
|
+
subscribe?: Subscribe;
|
|
168
|
+
// unsubscribe, // coupled to subscribe.
|
|
169
|
+
|
|
170
|
+
// Optional, but should be provided at the same time.
|
|
171
|
+
suggest?: Suggest;
|
|
172
|
+
switchNetwork?: SwitchNetwork;
|
|
173
|
+
getSigners: (provider: InstanceType) => Promise<SignerFactory>;
|
|
174
|
+
canSwitchNetworkTo?: CanSwitchNetwork;
|
|
175
|
+
canEagerConnect?: CanEagerConnect;
|
|
176
|
+
getWalletInfo(allBlockChains: BlockchainMeta[]): WalletInfo;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
export interface WalletConfig {
|
|
180
|
+
type: WalletType;
|
|
181
|
+
defaultNetwork?: Network;
|
|
182
|
+
checkInstallation?: boolean;
|
|
183
|
+
isAsyncInstance?: boolean;
|
|
184
|
+
isAsyncSwitchNetwork?: boolean;
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
export type WalletProviders = Map<
|
|
188
|
+
WalletType,
|
|
189
|
+
{
|
|
190
|
+
actions: WalletActions;
|
|
191
|
+
config: WalletConfig;
|
|
192
|
+
}
|
|
193
|
+
>;
|
|
194
|
+
|
|
195
|
+
export type ProviderInterface = { config: WalletConfig } & WalletActions;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { ProviderProps } from './types.js';
|
|
2
|
+
|
|
3
|
+
import { useEffect, useRef } from 'react';
|
|
4
|
+
|
|
5
|
+
import { shouldTryAutoConnect } from './utils.js';
|
|
6
|
+
|
|
7
|
+
export function useAutoConnect(
|
|
8
|
+
props: Pick<ProviderProps, 'allBlockChains' | 'autoConnect'> & {
|
|
9
|
+
/**
|
|
10
|
+
* A function to run autoConnect on instances
|
|
11
|
+
*/
|
|
12
|
+
autoConnectHandler: () => void;
|
|
13
|
+
}
|
|
14
|
+
) {
|
|
15
|
+
const autoConnectInitiated = useRef(false);
|
|
16
|
+
|
|
17
|
+
useEffect(() => {
|
|
18
|
+
if (shouldTryAutoConnect(props) && !autoConnectInitiated.current) {
|
|
19
|
+
autoConnectInitiated.current = true;
|
|
20
|
+
props.autoConnectHandler();
|
|
21
|
+
}
|
|
22
|
+
}, [props.autoConnect, props.allBlockChains]);
|
|
23
|
+
}
|
|
@@ -0,0 +1,241 @@
|
|
|
1
|
+
import type { ProviderContext, ProviderProps } from './types.js';
|
|
2
|
+
import type { LegacyProviderInterface } from '@rango-dev/wallets-core/legacy';
|
|
3
|
+
import type { WalletType } from '@rango-dev/wallets-shared';
|
|
4
|
+
|
|
5
|
+
import { useEffect, useReducer } from 'react';
|
|
6
|
+
|
|
7
|
+
import { autoConnect } from './autoConnect.js';
|
|
8
|
+
import {
|
|
9
|
+
availableWallets,
|
|
10
|
+
checkWalletProviders,
|
|
11
|
+
clearPersistance,
|
|
12
|
+
connectedWallets,
|
|
13
|
+
defaultWalletState,
|
|
14
|
+
makeEventHandler,
|
|
15
|
+
stateReducer,
|
|
16
|
+
tryPersistWallet,
|
|
17
|
+
tryRemoveWalletFromPersistance,
|
|
18
|
+
} from './helpers.js';
|
|
19
|
+
import { useInitializers } from './hooks.js';
|
|
20
|
+
import { useAutoConnect } from './useAutoConnect.js';
|
|
21
|
+
|
|
22
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
23
|
+
type ProviderType = any;
|
|
24
|
+
|
|
25
|
+
export type LegacyProviderProps = Omit<ProviderProps, 'providers'> & {
|
|
26
|
+
providers: LegacyProviderInterface[];
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
export function useLegacyProviders(
|
|
30
|
+
props: LegacyProviderProps
|
|
31
|
+
): ProviderContext {
|
|
32
|
+
const [providersState, dispatch] = useReducer(stateReducer, {});
|
|
33
|
+
|
|
34
|
+
// Get (or add) wallet instance (`provider`s will be wrapped in a `Wallet`)
|
|
35
|
+
const getWalletInstance = useInitializers(
|
|
36
|
+
makeEventHandler(dispatch, props.onUpdateState)
|
|
37
|
+
);
|
|
38
|
+
|
|
39
|
+
// Getting providers from props and put all of them in a `Map` with an appropriate interface.
|
|
40
|
+
const listOfProviders = props.providers;
|
|
41
|
+
const wallets = checkWalletProviders(listOfProviders);
|
|
42
|
+
|
|
43
|
+
useAutoConnect({
|
|
44
|
+
allBlockChains: props.allBlockChains,
|
|
45
|
+
autoConnect: props.autoConnect,
|
|
46
|
+
autoConnectHandler: async () => autoConnect(wallets, getWalletInstance),
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
// Final API we put in context and it will be available to use for users.
|
|
50
|
+
const api: ProviderContext = {
|
|
51
|
+
async connect(type, namespaces) {
|
|
52
|
+
const wallet = wallets.get(type);
|
|
53
|
+
if (!wallet) {
|
|
54
|
+
throw new Error(`You should add ${type} to provider first.`);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
// Legacy providers doesn't implemented multiple namespaces, so it will always be one value.
|
|
58
|
+
let network = undefined;
|
|
59
|
+
if (namespaces && namespaces.length > 0) {
|
|
60
|
+
/*
|
|
61
|
+
* This may not be safe in cases there are two `network` for namespaces, the first one will be picked always.
|
|
62
|
+
* But since legacy provider only accepts one value, it shouldn't be happened when we are using legacy mode.
|
|
63
|
+
*/
|
|
64
|
+
network = namespaces.find((ns) => !!ns.network)?.network;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
const walletInstance = getWalletInstance(wallet);
|
|
68
|
+
const result = await walletInstance.connect(network, namespaces);
|
|
69
|
+
if (props.autoConnect) {
|
|
70
|
+
void tryPersistWallet({
|
|
71
|
+
type,
|
|
72
|
+
walletActions: wallet.actions,
|
|
73
|
+
getState: api.state,
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
return [result];
|
|
78
|
+
},
|
|
79
|
+
async disconnect(type) {
|
|
80
|
+
const wallet = wallets.get(type);
|
|
81
|
+
if (!wallet) {
|
|
82
|
+
throw new Error(`You should add ${type} to provider first.`);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
const walletInstance = getWalletInstance(wallet);
|
|
86
|
+
await walletInstance.disconnect();
|
|
87
|
+
if (props.autoConnect) {
|
|
88
|
+
tryRemoveWalletFromPersistance({ type, walletActions: wallet.actions });
|
|
89
|
+
}
|
|
90
|
+
},
|
|
91
|
+
async disconnectAll() {
|
|
92
|
+
const disconnect_promises: Promise<void>[] = [];
|
|
93
|
+
|
|
94
|
+
/*
|
|
95
|
+
* When a wallet is initializing, a record will be added to `providersState`
|
|
96
|
+
* So we use them to know what wallet has been initialized then we need to
|
|
97
|
+
* filter connected wallets only.
|
|
98
|
+
*/
|
|
99
|
+
connectedWallets(providersState).forEach((type) => {
|
|
100
|
+
const wallet = wallets.get(type);
|
|
101
|
+
|
|
102
|
+
if (wallet) {
|
|
103
|
+
const walletInstance = getWalletInstance(wallet);
|
|
104
|
+
disconnect_promises.push(walletInstance.disconnect());
|
|
105
|
+
}
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
if (props.autoConnect) {
|
|
109
|
+
clearPersistance();
|
|
110
|
+
}
|
|
111
|
+
return await Promise.allSettled(disconnect_promises);
|
|
112
|
+
},
|
|
113
|
+
|
|
114
|
+
async suggestAndConnect(type, network) {
|
|
115
|
+
const wallet = wallets.get(type);
|
|
116
|
+
if (!wallet) {
|
|
117
|
+
throw new Error(`You should add ${type} to provider first.`);
|
|
118
|
+
}
|
|
119
|
+
const walletInstance = getWalletInstance(wallet);
|
|
120
|
+
const result = await walletInstance.suggestAndConnect(network);
|
|
121
|
+
|
|
122
|
+
return result;
|
|
123
|
+
},
|
|
124
|
+
|
|
125
|
+
state(type) {
|
|
126
|
+
return providersState[type] || defaultWalletState;
|
|
127
|
+
},
|
|
128
|
+
canSwitchNetworkTo(type, network) {
|
|
129
|
+
const wallet = wallets.get(type);
|
|
130
|
+
if (!wallet) {
|
|
131
|
+
return false;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
const walletInstance = getWalletInstance(wallet);
|
|
135
|
+
return walletInstance.canSwitchNetworkTo
|
|
136
|
+
? walletInstance.canSwitchNetworkTo(network, walletInstance.provider)
|
|
137
|
+
: false;
|
|
138
|
+
},
|
|
139
|
+
providers() {
|
|
140
|
+
const providers: { [type in WalletType]?: ProviderType } = {};
|
|
141
|
+
availableWallets(providersState).forEach((type) => {
|
|
142
|
+
const wallet = wallets.get(type);
|
|
143
|
+
if (wallet) {
|
|
144
|
+
const walletInstance = getWalletInstance(wallet);
|
|
145
|
+
providers[type] = walletInstance.provider;
|
|
146
|
+
}
|
|
147
|
+
});
|
|
148
|
+
|
|
149
|
+
return providers;
|
|
150
|
+
},
|
|
151
|
+
getWalletInfo(type) {
|
|
152
|
+
const wallet = wallets.get(type);
|
|
153
|
+
if (!wallet) {
|
|
154
|
+
throw new Error(`You should add ${type} to provider first.`);
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
/*
|
|
158
|
+
* Get wallet info could be used in render methods to show wallets data
|
|
159
|
+
* So, addWalletRef method shouldn't be called in this method
|
|
160
|
+
*/
|
|
161
|
+
|
|
162
|
+
return wallet.actions.getWalletInfo(props.allBlockChains || []);
|
|
163
|
+
},
|
|
164
|
+
async getSigners(type) {
|
|
165
|
+
const wallet = wallets.get(type);
|
|
166
|
+
|
|
167
|
+
if (!wallet) {
|
|
168
|
+
throw new Error(`You should add ${type} to provider first.`);
|
|
169
|
+
}
|
|
170
|
+
const walletInstance = getWalletInstance(wallet);
|
|
171
|
+
const provider = walletInstance.provider;
|
|
172
|
+
const result = walletInstance.getSigners(provider);
|
|
173
|
+
|
|
174
|
+
return result;
|
|
175
|
+
},
|
|
176
|
+
hubProvider() {
|
|
177
|
+
throw new Error('This method is not available on legacy providers.');
|
|
178
|
+
},
|
|
179
|
+
};
|
|
180
|
+
|
|
181
|
+
// Initialize instances
|
|
182
|
+
useEffect(() => {
|
|
183
|
+
wallets.forEach((wallet) => {
|
|
184
|
+
const walletInstance = getWalletInstance(wallet);
|
|
185
|
+
const runOnInit = () => {
|
|
186
|
+
if (walletInstance.onInit) {
|
|
187
|
+
walletInstance.onInit();
|
|
188
|
+
}
|
|
189
|
+
};
|
|
190
|
+
|
|
191
|
+
const initWhenPageIsReady = (event: Event) => {
|
|
192
|
+
if (
|
|
193
|
+
event.target &&
|
|
194
|
+
(event.target as Document).readyState === 'complete'
|
|
195
|
+
) {
|
|
196
|
+
runOnInit();
|
|
197
|
+
|
|
198
|
+
document.removeEventListener('readystatechange', initWhenPageIsReady);
|
|
199
|
+
}
|
|
200
|
+
};
|
|
201
|
+
|
|
202
|
+
// Try to run, maybe it's ready.
|
|
203
|
+
runOnInit();
|
|
204
|
+
|
|
205
|
+
/*
|
|
206
|
+
* Try again when the page has been completely loaded.
|
|
207
|
+
* Some of wallets, take some time to be fully injected and loaded.
|
|
208
|
+
*/
|
|
209
|
+
document.addEventListener('readystatechange', initWhenPageIsReady);
|
|
210
|
+
});
|
|
211
|
+
}, []);
|
|
212
|
+
|
|
213
|
+
// Setting supported blockchains on instances
|
|
214
|
+
useEffect(() => {
|
|
215
|
+
const allBlockChains = props.allBlockChains;
|
|
216
|
+
if (allBlockChains) {
|
|
217
|
+
wallets.forEach((wallet) => {
|
|
218
|
+
const walletInstance = getWalletInstance(wallet);
|
|
219
|
+
const walletInfo = walletInstance.getWalletInfo(
|
|
220
|
+
props.allBlockChains || []
|
|
221
|
+
);
|
|
222
|
+
walletInstance.setInfo({
|
|
223
|
+
supportedBlockchains: walletInfo.supportedChains,
|
|
224
|
+
isContractWallet: !!walletInfo.isContractWallet,
|
|
225
|
+
});
|
|
226
|
+
});
|
|
227
|
+
}
|
|
228
|
+
}, [props.allBlockChains]);
|
|
229
|
+
|
|
230
|
+
// Setting event handler on instances
|
|
231
|
+
useEffect(() => {
|
|
232
|
+
wallets.forEach((wallet) => {
|
|
233
|
+
const walletInstance = getWalletInstance(wallet);
|
|
234
|
+
walletInstance.setHandler(
|
|
235
|
+
makeEventHandler(dispatch, props.onUpdateState)
|
|
236
|
+
);
|
|
237
|
+
});
|
|
238
|
+
}, [props.onUpdateState]);
|
|
239
|
+
|
|
240
|
+
return api;
|
|
241
|
+
}
|
package/src/provider.tsx
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { ProviderProps } from './legacy/types.js';
|
|
2
|
+
|
|
3
|
+
import React from 'react';
|
|
4
|
+
|
|
5
|
+
import { WalletContext } from './legacy/context.js';
|
|
6
|
+
import { useProviders } from './useProviders.js';
|
|
7
|
+
|
|
8
|
+
function Provider(props: ProviderProps) {
|
|
9
|
+
const api = useProviders(props);
|
|
10
|
+
|
|
11
|
+
return (
|
|
12
|
+
<WalletContext.Provider value={api}>
|
|
13
|
+
{props.children}
|
|
14
|
+
</WalletContext.Provider>
|
|
15
|
+
);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export default Provider;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
const TEST_ENVIRONMENT_AGENT = 'HappyDOM/0.0.0';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Detecting wether our code is running in a test environment or not.
|
|
5
|
+
*
|
|
6
|
+
* Note: This is only useful when HappyDOM or jsdom has been added to test runner.
|
|
7
|
+
*/
|
|
8
|
+
export function isRunningInTestEnvironmentWithDom(): boolean {
|
|
9
|
+
return navigator.userAgent.includes(TEST_ENVIRONMENT_AGENT);
|
|
10
|
+
}
|