-
-
Notifications
You must be signed in to change notification settings - Fork 128
Expand file tree
/
Copy pathinitializeInpageProvider.ts
More file actions
153 lines (134 loc) · 4.95 KB
/
initializeInpageProvider.ts
File metadata and controls
153 lines (134 loc) · 4.95 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
import { type Duplex } from 'readable-stream';
import type { CAIP294WalletData } from './CAIP294';
import { announceWallet } from './CAIP294';
import { announceProvider as announceEip6963Provider } from './EIP6963';
import type { MetaMaskInpageProviderOptions } from './MetaMaskInpageProvider';
import { MetaMaskInpageProvider } from './MetaMaskInpageProvider';
import { shimWeb3 } from './shimWeb3';
import type { BaseProviderInfo } from './types';
type InitializeProviderOptions = {
/**
* The stream used to connect to the wallet.
*/
connectionStream: Duplex;
/**
* The EIP-6963 provider info / CAIP-294 wallet data that should be announced if set.
*/
providerInfo?: BaseProviderInfo;
/**
* Whether the provider should be set as window.ethereum.
*/
shouldSetOnWindow?: boolean;
/**
* Whether the window.web3 shim should be set.
*/
shouldShimWeb3?: boolean;
/**
* Whether the provider announce a CAIP-294 event.
*/
shouldAnnounceCaip294?: boolean;
} & MetaMaskInpageProviderOptions;
/**
* Initializes a MetaMaskInpageProvider and (optionally) assigns it as window.ethereum.
*
* @param options - An options bag.
* @param options.connectionStream - A Node.js stream.
* @param options.maxEventListeners - The maximum number of event listeners.
* @param options.providerInfo - The EIP-6963 provider info / CAIP-294 wallet data that should be announced if set.
* @param options.shouldSendMetadata - Whether the provider should send page metadata.
* @param options.shouldSetOnWindow - Whether the provider should be set as window.ethereum.
* @param options.shouldShimWeb3 - Whether a window.web3 shim should be injected.
* @param options.logger - The logging API to use. Default: `console`.
* @param options.shouldAnnounceCaip294 - Whether the provider should announce itself.
* @returns The initialized provider (whether set or not).
*/
export function initializeProvider({
connectionStream,
logger = console,
maxEventListeners = 100,
providerInfo,
shouldSendMetadata = true,
shouldSetOnWindow = true,
shouldShimWeb3 = false,
shouldAnnounceCaip294 = true,
}: InitializeProviderOptions): MetaMaskInpageProvider {
const provider = new MetaMaskInpageProvider(connectionStream, {
logger,
maxEventListeners,
shouldSendMetadata,
});
const proxiedProvider = new Proxy(provider, {
// some common libraries, e.g. web3@1.x, mess with our API
deleteProperty: () => true,
// fix issue with Proxy unable to access private variables from getters
// https://stackoverflow.com/a/73051482
get(target, propName: 'chainId' | 'networkVersion' | 'selectedAddress') {
return target[propName];
},
});
if (providerInfo) {
announceEip6963Provider({
info: providerInfo,
provider: proxiedProvider,
});
if (shouldAnnounceCaip294) {
// eslint-disable-next-line no-void
void announceCaip294WalletData(provider, providerInfo);
}
}
if (shouldSetOnWindow) {
setGlobalProvider(proxiedProvider);
}
if (shouldShimWeb3) {
shimWeb3(proxiedProvider, logger);
}
return proxiedProvider;
}
/**
* Sets the given provider instance as window.ethereum and dispatches the
* 'ethereum#initialized' event on window.
*
* @param providerInstance - The provider instance.
*/
export function setGlobalProvider(
providerInstance: MetaMaskInpageProvider,
): void {
try {
(window as Record<string, any>).ethereum = providerInstance;
window.dispatchEvent(new Event('ethereum#initialized'));
} catch (error) {
console.error(
'MetaMask encountered an error setting the global Ethereum provider - this is likely due to another Ethereum wallet extension also setting the global Ethereum provider:',
error,
);
}
}
/**
* Announces [CAIP-294](https://github.com/ChainAgnostic/CAIPs/blob/bc4942857a8e04593ed92f7dc66653577a1c4435/CAIPs/caip-294.md) wallet data according to build type and browser.
* Until released to stable, `extensionId` is only set in the `metamask_getProviderState` result if the build type is `flask`.
* `extensionId` is included if browser is chromium based because it is only useable by browsers that support [externally_connectable](https://developer.chrome.com/docs/extensions/reference/manifest/externally-connectable).
*
* @param provider - The provider {@link MetaMaskInpageProvider} used for retrieving `extensionId`.
* @param providerInfo - The provider info {@link BaseProviderInfo} that should be announced if set.
*/
export async function announceCaip294WalletData(
provider: MetaMaskInpageProvider,
providerInfo: CAIP294WalletData,
): Promise<void> {
const providerState = await provider.request<{ extensionId?: string }>({
method: 'metamask_getProviderState',
});
const targets = [];
const extensionId = providerState?.extensionId;
if (extensionId) {
targets.push({
type: 'caip-348',
value: extensionId,
});
}
const walletData = {
...providerInfo,
targets,
};
announceWallet(walletData);
}