@mocanetwork/airkit 0.5.0-beta.2
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/README.md +177 -0
- package/dist/airkit.cjs.js +2662 -0
- package/dist/airkit.esm.js +2468 -0
- package/dist/airkit.umd.min.js +2 -0
- package/dist/airkit.umd.min.js.LICENSE.txt +12 -0
- package/dist/lib.cjs/common/src/error.js +25 -0
- package/dist/lib.cjs/common/src/realm/messaging/auth.js +28 -0
- package/dist/lib.cjs/common/src/realm/messaging/types.js +15 -0
- package/dist/lib.cjs/ws-embed/src/PopupHandler.js +64 -0
- package/dist/lib.cjs/ws-embed/src/airService.js +364 -0
- package/dist/lib.cjs/ws-embed/src/baseProvider.js +178 -0
- package/dist/lib.cjs/ws-embed/src/communicationProvider.js +346 -0
- package/dist/lib.cjs/ws-embed/src/embed.js +735 -0
- package/dist/lib.cjs/ws-embed/src/error.js +21 -0
- package/dist/lib.cjs/ws-embed/src/iframeController.js +68 -0
- package/dist/lib.cjs/ws-embed/src/inPageProvider.js +307 -0
- package/dist/lib.cjs/ws-embed/src/index.js +20 -0
- package/dist/lib.cjs/ws-embed/src/interfaces.js +29 -0
- package/dist/lib.cjs/ws-embed/src/isStream.js +20 -0
- package/dist/lib.cjs/ws-embed/src/loglevel.js +7 -0
- package/dist/lib.cjs/ws-embed/src/messageService.js +212 -0
- package/dist/lib.cjs/ws-embed/src/messages.js +22 -0
- package/dist/lib.cjs/ws-embed/src/siteMetadata.js +77 -0
- package/dist/lib.cjs/ws-embed/src/utils.js +95 -0
- package/dist/lib.esm/common/src/error.js +23 -0
- package/dist/lib.esm/common/src/realm/messaging/auth.js +26 -0
- package/dist/lib.esm/common/src/realm/messaging/types.js +13 -0
- package/dist/lib.esm/ws-embed/src/PopupHandler.js +62 -0
- package/dist/lib.esm/ws-embed/src/airService.js +362 -0
- package/dist/lib.esm/ws-embed/src/baseProvider.js +176 -0
- package/dist/lib.esm/ws-embed/src/communicationProvider.js +344 -0
- package/dist/lib.esm/ws-embed/src/embed.js +730 -0
- package/dist/lib.esm/ws-embed/src/error.js +18 -0
- package/dist/lib.esm/ws-embed/src/iframeController.js +66 -0
- package/dist/lib.esm/ws-embed/src/inPageProvider.js +302 -0
- package/dist/lib.esm/ws-embed/src/index.js +5 -0
- package/dist/lib.esm/ws-embed/src/interfaces.js +21 -0
- package/dist/lib.esm/ws-embed/src/isStream.js +15 -0
- package/dist/lib.esm/ws-embed/src/loglevel.js +5 -0
- package/dist/lib.esm/ws-embed/src/messageService.js +210 -0
- package/dist/lib.esm/ws-embed/src/messages.js +20 -0
- package/dist/lib.esm/ws-embed/src/siteMetadata.js +75 -0
- package/dist/lib.esm/ws-embed/src/utils.js +88 -0
- package/dist/types/PopupHandler.d.ts +24 -0
- package/dist/types/airService.d.ts +34 -0
- package/dist/types/baseProvider.d.ts +66 -0
- package/dist/types/common/custom.d.ts +4 -0
- package/dist/types/common/error.d.ts +17 -0
- package/dist/types/common/realm/error/auth.d.ts +1 -0
- package/dist/types/common/realm/error/types.d.ts +1 -0
- package/dist/types/common/realm/messaging/auth.d.ts +138 -0
- package/dist/types/common/realm/messaging/types.d.ts +95 -0
- package/dist/types/common/realm/partner/config.d.ts +68 -0
- package/dist/types/common/realm/user/types.d.ts +78 -0
- package/dist/types/common/realm/wallet/bybit/bybit.d.ts +2 -0
- package/dist/types/common/realm/wallet/coinbase/coinbase.d.ts +2 -0
- package/dist/types/common/realm/wallet/cryptoCom/cryptoCom.d.ts +2 -0
- package/dist/types/common/realm/wallet/index.d.ts +22 -0
- package/dist/types/common/realm/wallet/metamask/metamask.d.ts +2 -0
- package/dist/types/common/realm/wallet/okx/okx.d.ts +2 -0
- package/dist/types/common/realm/wallet/phantom/phantom.d.ts +2 -0
- package/dist/types/common/realm/wallet/rabby/rabby.d.ts +2 -0
- package/dist/types/common/realm/wallet/rainbow/rainbow.d.ts +2 -0
- package/dist/types/common/realm/wallet/trust/trust.d.ts +2 -0
- package/dist/types/common/types.d.ts +8 -0
- package/dist/types/common/utils.d.ts +2 -0
- package/dist/types/communicationProvider.d.ts +82 -0
- package/dist/types/embed.d.ts +42 -0
- package/dist/types/error.d.ts +9 -0
- package/dist/types/iframeController.d.ts +18 -0
- package/dist/types/inPageProvider.d.ts +106 -0
- package/dist/types/index.d.ts +4 -0
- package/dist/types/interfaces.d.ts +261 -0
- package/dist/types/isStream.d.ts +4 -0
- package/dist/types/loglevel.d.ts +3 -0
- package/dist/types/messageService.d.ts +51 -0
- package/dist/types/messages.d.ts +19 -0
- package/dist/types/siteMetadata.d.ts +9 -0
- package/dist/types/utils.d.ts +24 -0
- package/package.json +76 -0
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { BaseError } from '../../common/src/error.js';
|
|
2
|
+
|
|
3
|
+
class AirServiceError extends BaseError {
|
|
4
|
+
static from(error) {
|
|
5
|
+
if (error instanceof AirServiceError) {
|
|
6
|
+
return error;
|
|
7
|
+
} else if (error instanceof Object && "message" in error) {
|
|
8
|
+
if (error.message === "User cancelled login") {
|
|
9
|
+
return new AirServiceError("USER_CANCELLED", error.message);
|
|
10
|
+
}
|
|
11
|
+
return new AirServiceError("UNKNOWN_ERROR", error.message.toString());
|
|
12
|
+
}
|
|
13
|
+
return new AirServiceError("UNKNOWN_ERROR");
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
class RealmEmbedError extends AirServiceError {}
|
|
17
|
+
|
|
18
|
+
export { AirServiceError, RealmEmbedError };
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import _objectSpread from '@babel/runtime/helpers/objectSpread2';
|
|
2
|
+
import _defineProperty from '@babel/runtime/helpers/defineProperty';
|
|
3
|
+
|
|
4
|
+
class IframeController {
|
|
5
|
+
constructor(iframeUrl, iframeId, state) {
|
|
6
|
+
_defineProperty(this, "state", void 0);
|
|
7
|
+
_defineProperty(this, "_iframeElement", null);
|
|
8
|
+
_defineProperty(this, "iframeUrl", void 0);
|
|
9
|
+
_defineProperty(this, "iframeId", void 0);
|
|
10
|
+
this.state = _objectSpread(_objectSpread({}, IframeController.defaultState), state);
|
|
11
|
+
this.iframeUrl = iframeUrl;
|
|
12
|
+
this.iframeId = iframeId;
|
|
13
|
+
}
|
|
14
|
+
get iframeElement() {
|
|
15
|
+
return this._iframeElement;
|
|
16
|
+
}
|
|
17
|
+
createIframe() {
|
|
18
|
+
if (this._iframeElement) return this._iframeElement;
|
|
19
|
+
const iframe = document.createElement("iframe");
|
|
20
|
+
iframe.id = this.iframeId;
|
|
21
|
+
iframe.allow = "publickey-credentials-get *; publickey-credentials-create *";
|
|
22
|
+
iframe.src = this.iframeUrl;
|
|
23
|
+
iframe.style.position = "fixed";
|
|
24
|
+
iframe.style.zIndex = "999999";
|
|
25
|
+
iframe.style.border = "none";
|
|
26
|
+
iframe.style.margin = "0";
|
|
27
|
+
iframe.style.padding = "0";
|
|
28
|
+
iframe.style.display = "none";
|
|
29
|
+
document.body.appendChild(iframe);
|
|
30
|
+
this._iframeElement = iframe;
|
|
31
|
+
return iframe;
|
|
32
|
+
}
|
|
33
|
+
setIframeVisibility(isVisible) {
|
|
34
|
+
this.state.isVisible = isVisible;
|
|
35
|
+
}
|
|
36
|
+
updateIframeState() {
|
|
37
|
+
if (!this.iframeElement) return;
|
|
38
|
+
const style = {};
|
|
39
|
+
style.display = this.state.isVisible ? "block" : "none";
|
|
40
|
+
style.width = "100%";
|
|
41
|
+
style.height = "100%";
|
|
42
|
+
style.top = "0px";
|
|
43
|
+
style.right = "0px";
|
|
44
|
+
style.left = "0px";
|
|
45
|
+
style.bottom = "0px";
|
|
46
|
+
Object.assign(this.iframeElement.style, style);
|
|
47
|
+
}
|
|
48
|
+
destroy() {
|
|
49
|
+
if (this.iframeElement) {
|
|
50
|
+
this.iframeElement.remove();
|
|
51
|
+
this._iframeElement = null;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
postMessage(message) {
|
|
55
|
+
if (!this.iframeElement) return;
|
|
56
|
+
const {
|
|
57
|
+
origin
|
|
58
|
+
} = new URL(this.iframeElement.src);
|
|
59
|
+
this.iframeElement.contentWindow.postMessage(message, origin);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
_defineProperty(IframeController, "defaultState", {
|
|
63
|
+
isVisible: false
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
export { IframeController };
|
|
@@ -0,0 +1,302 @@
|
|
|
1
|
+
import _objectSpread from '@babel/runtime/helpers/objectSpread2';
|
|
2
|
+
import _defineProperty from '@babel/runtime/helpers/defineProperty';
|
|
3
|
+
import { PROVIDER_JRPC_METHODS, PROVIDER_NOTIFICATIONS } from '@toruslabs/base-controllers';
|
|
4
|
+
import { EthereumProviderError } from '@web3auth/auth';
|
|
5
|
+
import dequal from 'fast-deep-equal';
|
|
6
|
+
import BaseProvider from './baseProvider.js';
|
|
7
|
+
import log from './loglevel.js';
|
|
8
|
+
import messages from './messages.js';
|
|
9
|
+
import { EMITTED_NOTIFICATIONS } from './utils.js';
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* @param connectionStream - A Node.js duplex stream
|
|
13
|
+
* @param opts - An options bag
|
|
14
|
+
*/
|
|
15
|
+
class AirInPageProvider extends BaseProvider {
|
|
16
|
+
constructor(connectionStream, {
|
|
17
|
+
maxEventListeners = 100,
|
|
18
|
+
jsonRpcStreamName = "provider"
|
|
19
|
+
}) {
|
|
20
|
+
super(connectionStream, {
|
|
21
|
+
maxEventListeners,
|
|
22
|
+
jsonRpcStreamName
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
// private state
|
|
26
|
+
/**
|
|
27
|
+
* The chain ID of the currently connected EVM chain.
|
|
28
|
+
* See [chainId.network]{@link https://chainid.network} for more information.
|
|
29
|
+
*/
|
|
30
|
+
_defineProperty(this, "chainId", void 0);
|
|
31
|
+
/**
|
|
32
|
+
* The user's currently selected EVM address.
|
|
33
|
+
* If null, Torus is either locked or the user has not permitted any
|
|
34
|
+
* addresses to be viewed.
|
|
35
|
+
*/
|
|
36
|
+
_defineProperty(this, "selectedAddress", void 0);
|
|
37
|
+
_defineProperty(this, "tryWindowHandle", void 0);
|
|
38
|
+
this.state = _objectSpread({}, AirInPageProvider.defaultState);
|
|
39
|
+
|
|
40
|
+
// public state
|
|
41
|
+
this.selectedAddress = null;
|
|
42
|
+
this.chainId = null;
|
|
43
|
+
this.handleAccountsChanged = this.handleAccountsChanged.bind(this);
|
|
44
|
+
this.handleChainChanged = this.handleChainChanged.bind(this);
|
|
45
|
+
this.handleUnlockStateChanged = this.handleUnlockStateChanged.bind(this);
|
|
46
|
+
|
|
47
|
+
// setup own event listeners
|
|
48
|
+
|
|
49
|
+
// EIP-1193 connect
|
|
50
|
+
this.on("connect", () => {
|
|
51
|
+
this.state.isConnected = true;
|
|
52
|
+
});
|
|
53
|
+
const jsonRpcNotificationHandler = payload => {
|
|
54
|
+
const {
|
|
55
|
+
method,
|
|
56
|
+
params
|
|
57
|
+
} = payload;
|
|
58
|
+
if (method === PROVIDER_NOTIFICATIONS.ACCOUNTS_CHANGED) {
|
|
59
|
+
this.handleAccountsChanged(params);
|
|
60
|
+
} else if (method === PROVIDER_NOTIFICATIONS.UNLOCK_STATE_CHANGED) {
|
|
61
|
+
this.handleUnlockStateChanged(params);
|
|
62
|
+
} else if (method === PROVIDER_NOTIFICATIONS.CHAIN_CHANGED) {
|
|
63
|
+
this.handleChainChanged(params);
|
|
64
|
+
} else if (EMITTED_NOTIFICATIONS.includes(method)) {
|
|
65
|
+
this.emit("data", payload);
|
|
66
|
+
this.emit("notification", params.result);
|
|
67
|
+
this.emit("message", {
|
|
68
|
+
type: method,
|
|
69
|
+
data: params
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
};
|
|
73
|
+
|
|
74
|
+
// json rpc notification listener
|
|
75
|
+
this.jsonRpcConnectionEvents.on("notification", jsonRpcNotificationHandler);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* Returns whether the inpage provider is connected to Torus.
|
|
80
|
+
*/
|
|
81
|
+
isConnected() {
|
|
82
|
+
return this.state.isConnected;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
// Private Methods
|
|
86
|
+
//= ===================
|
|
87
|
+
/**
|
|
88
|
+
* Constructor helper.
|
|
89
|
+
* Populates initial state by calling 'wallet_getProviderState' and emits
|
|
90
|
+
* necessary events.
|
|
91
|
+
*/
|
|
92
|
+
async initializeState() {
|
|
93
|
+
try {
|
|
94
|
+
const {
|
|
95
|
+
accounts,
|
|
96
|
+
chainId,
|
|
97
|
+
isUnlocked
|
|
98
|
+
} = await this.request({
|
|
99
|
+
method: PROVIDER_JRPC_METHODS.GET_PROVIDER_STATE,
|
|
100
|
+
params: []
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
// indicate that we've connected, for EIP-1193 compliance
|
|
104
|
+
this.emit("connect", {
|
|
105
|
+
chainId
|
|
106
|
+
});
|
|
107
|
+
this.handleChainChanged({
|
|
108
|
+
chainId
|
|
109
|
+
});
|
|
110
|
+
this.handleUnlockStateChanged({
|
|
111
|
+
accounts,
|
|
112
|
+
isUnlocked
|
|
113
|
+
});
|
|
114
|
+
this.handleAccountsChanged(accounts);
|
|
115
|
+
} catch (error) {
|
|
116
|
+
log.error("WsEmbed: Failed to get initial state. Please report this bug.", error);
|
|
117
|
+
} finally {
|
|
118
|
+
log.info("initialized provider state");
|
|
119
|
+
this.state.initialized = true;
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* Internal RPC method. Forwards requests to background via the RPC engine.
|
|
125
|
+
* Also remap ids inbound and outbound
|
|
126
|
+
*/
|
|
127
|
+
rpcRequest(payload, callback, isInternal = false) {
|
|
128
|
+
let cb = callback;
|
|
129
|
+
const _payload = payload;
|
|
130
|
+
if (!Array.isArray(_payload)) {
|
|
131
|
+
if (!_payload.jsonrpc) {
|
|
132
|
+
_payload.jsonrpc = "2.0";
|
|
133
|
+
}
|
|
134
|
+
if (_payload.method === "eth_accounts" || _payload.method === "eth_requestAccounts") {
|
|
135
|
+
// handle accounts changing
|
|
136
|
+
cb = (err, res) => {
|
|
137
|
+
this.handleAccountsChanged(res.result || [], _payload.method === "eth_accounts", isInternal);
|
|
138
|
+
callback(err, res);
|
|
139
|
+
};
|
|
140
|
+
} else if (_payload.method === "wallet_getProviderState") {
|
|
141
|
+
this.rpcEngine.handle(payload, cb);
|
|
142
|
+
return;
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
this.tryWindowHandle(_payload, cb);
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
/**
|
|
149
|
+
* When the provider becomes connected, updates internal state and emits
|
|
150
|
+
* required events. Idempotent.
|
|
151
|
+
*
|
|
152
|
+
* @param chainId - The ID of the newly connected chain.
|
|
153
|
+
* emits TorusInpageProvider#connect
|
|
154
|
+
*/
|
|
155
|
+
handleConnect(chainId) {
|
|
156
|
+
if (!this.state.isConnected) {
|
|
157
|
+
this.state.isConnected = true;
|
|
158
|
+
this.emit("connect", {
|
|
159
|
+
chainId
|
|
160
|
+
});
|
|
161
|
+
log.debug(messages.info.connected(chainId));
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
/**
|
|
166
|
+
* When the provider becomes disconnected, updates internal state and emits
|
|
167
|
+
* required events. Idempotent with respect to the isRecoverable parameter.
|
|
168
|
+
*
|
|
169
|
+
* Error codes per the CloseEvent status codes as required by EIP-1193:
|
|
170
|
+
* https://developer.mozilla.org/en-US/docs/Web/API/CloseEvent#Status_codes
|
|
171
|
+
*
|
|
172
|
+
* @param isRecoverable - Whether the disconnection is recoverable.
|
|
173
|
+
* @param errorMessage - A custom error message.
|
|
174
|
+
* emits TorusInpageProvider#disconnect
|
|
175
|
+
*/
|
|
176
|
+
handleDisconnect(isRecoverable, errorMessage) {
|
|
177
|
+
if (this.state.isConnected || !this.state.isPermanentlyDisconnected && !isRecoverable) {
|
|
178
|
+
this.state.isConnected = false;
|
|
179
|
+
let error;
|
|
180
|
+
if (isRecoverable) {
|
|
181
|
+
error = new EthereumProviderError(1013,
|
|
182
|
+
// Try again later
|
|
183
|
+
errorMessage || messages.errors.disconnected());
|
|
184
|
+
log.debug(error);
|
|
185
|
+
} else {
|
|
186
|
+
error = new EthereumProviderError(1011,
|
|
187
|
+
// Internal error
|
|
188
|
+
errorMessage || messages.errors.permanentlyDisconnected());
|
|
189
|
+
log.error(error);
|
|
190
|
+
this.chainId = null;
|
|
191
|
+
this.state.accounts = null;
|
|
192
|
+
this.selectedAddress = null;
|
|
193
|
+
this.state.isUnlocked = false;
|
|
194
|
+
this.state.isPermanentlyDisconnected = true;
|
|
195
|
+
}
|
|
196
|
+
this.emit("disconnect", error);
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
/**
|
|
201
|
+
* Called when accounts may have changed.
|
|
202
|
+
*/
|
|
203
|
+
handleAccountsChanged(accounts, isEthAccounts = false, isInternal = false) {
|
|
204
|
+
// defensive programming
|
|
205
|
+
let finalAccounts = accounts;
|
|
206
|
+
if (!Array.isArray(finalAccounts)) {
|
|
207
|
+
log.error("WsEmbed: Received non-array accounts parameter. Please report this bug.", finalAccounts);
|
|
208
|
+
finalAccounts = [];
|
|
209
|
+
}
|
|
210
|
+
for (const account of accounts) {
|
|
211
|
+
if (typeof account !== "string") {
|
|
212
|
+
log.error("WsEmbed: Received non-string account. Please report this bug.", accounts);
|
|
213
|
+
finalAccounts = [];
|
|
214
|
+
break;
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
// emit accountsChanged if anything about the accounts array has changed
|
|
219
|
+
if (!dequal(this.state.accounts, finalAccounts)) {
|
|
220
|
+
// we should always have the correct accounts even before eth_accounts
|
|
221
|
+
// returns, except in cases where isInternal is true
|
|
222
|
+
if (isEthAccounts && Array.isArray(this.state.accounts) && this.state.accounts.length > 0 && !isInternal) {
|
|
223
|
+
log.error('WsEmbed: "eth_accounts" unexpectedly updated accounts. Please report this bug.', finalAccounts);
|
|
224
|
+
}
|
|
225
|
+
this.state.accounts = finalAccounts;
|
|
226
|
+
this.emit("accountsChanged", finalAccounts);
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
// handle selectedAddress
|
|
230
|
+
if (this.selectedAddress !== finalAccounts[0]) {
|
|
231
|
+
this.selectedAddress = finalAccounts[0] || null;
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
/**
|
|
236
|
+
* Upon receipt of a new chainId and networkVersion, emits corresponding
|
|
237
|
+
* events and sets relevant public state.
|
|
238
|
+
* Does nothing if neither the chainId nor the networkVersion are different
|
|
239
|
+
* from existing values.
|
|
240
|
+
*
|
|
241
|
+
* emits TorusInpageProvider#chainChanged
|
|
242
|
+
* @param networkInfo - An object with network info.
|
|
243
|
+
*/
|
|
244
|
+
handleChainChanged({
|
|
245
|
+
chainId
|
|
246
|
+
} = {}) {
|
|
247
|
+
if (!chainId) {
|
|
248
|
+
log.error("WsEmbed: Received invalid network parameters. Please report this bug.", {
|
|
249
|
+
chainId
|
|
250
|
+
});
|
|
251
|
+
return;
|
|
252
|
+
}
|
|
253
|
+
if (chainId === "loading") {
|
|
254
|
+
this.handleDisconnect(true);
|
|
255
|
+
} else {
|
|
256
|
+
this.handleConnect(chainId);
|
|
257
|
+
if (chainId !== this.chainId) {
|
|
258
|
+
this.chainId = chainId;
|
|
259
|
+
if (this.state.initialized) {
|
|
260
|
+
this.emit("chainChanged", this.chainId);
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
/**
|
|
267
|
+
* Upon receipt of a new isUnlocked state, sets relevant public state.
|
|
268
|
+
* Calls the accounts changed handler with the received accounts, or an empty
|
|
269
|
+
* array.
|
|
270
|
+
*
|
|
271
|
+
* Does nothing if the received value is equal to the existing value.
|
|
272
|
+
* There are no lock/unlock events.
|
|
273
|
+
*
|
|
274
|
+
* @param opts - Options bag.
|
|
275
|
+
*/
|
|
276
|
+
handleUnlockStateChanged({
|
|
277
|
+
accounts,
|
|
278
|
+
isUnlocked
|
|
279
|
+
} = {}) {
|
|
280
|
+
if (typeof isUnlocked !== "boolean") {
|
|
281
|
+
log.error("WsEmbed: Received invalid isUnlocked parameter. Please report this bug.", {
|
|
282
|
+
isUnlocked
|
|
283
|
+
});
|
|
284
|
+
return;
|
|
285
|
+
}
|
|
286
|
+
if (isUnlocked !== this.state.isUnlocked) {
|
|
287
|
+
this.state.isUnlocked = isUnlocked;
|
|
288
|
+
this.handleAccountsChanged(accounts || []);
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
_defineProperty(AirInPageProvider, "defaultState", {
|
|
293
|
+
accounts: null,
|
|
294
|
+
isConnected: false,
|
|
295
|
+
isUnlocked: false,
|
|
296
|
+
initialized: false,
|
|
297
|
+
isPermanentlyDisconnected: false,
|
|
298
|
+
hasEmittedConnection: false
|
|
299
|
+
});
|
|
300
|
+
class TorusInPageProvider extends AirInPageProvider {}
|
|
301
|
+
|
|
302
|
+
export { TorusInPageProvider, AirInPageProvider as default };
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export { default as AirService } from './airService.js';
|
|
2
|
+
export { default as RealmEmbed } from './embed.js';
|
|
3
|
+
export { default as AirInPageProvider } from './inPageProvider.js';
|
|
4
|
+
export { BUTTON_POSITION, EMBED_BUILD_ENV, EXTERNAL_LOGIN_PROVIDER } from './interfaces.js';
|
|
5
|
+
export { CONFIRMATION_STRATEGY } from '@toruslabs/base-controllers';
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
export { CONFIRMATION_STRATEGY } from '@toruslabs/base-controllers';
|
|
2
|
+
|
|
3
|
+
const EMBED_BUILD_ENV = {
|
|
4
|
+
PRODUCTION: "production",
|
|
5
|
+
STAGING: "staging",
|
|
6
|
+
DEVELOPMENT: "development",
|
|
7
|
+
TESTING: "testing"
|
|
8
|
+
};
|
|
9
|
+
const BUTTON_POSITION = {
|
|
10
|
+
BOTTOM_LEFT: "bottom-left",
|
|
11
|
+
TOP_LEFT: "top-left",
|
|
12
|
+
BOTTOM_RIGHT: "bottom-right",
|
|
13
|
+
TOP_RIGHT: "top-right"
|
|
14
|
+
};
|
|
15
|
+
const EXTERNAL_LOGIN_PROVIDER = {
|
|
16
|
+
METAMASK: "metamask",
|
|
17
|
+
WALLET_CONNECT: "walletconnect",
|
|
18
|
+
WAGMI: "wagmi"
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
export { BUTTON_POSITION, EMBED_BUILD_ENV, EXTERNAL_LOGIN_PROVIDER };
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
2
|
+
function isStream(stream) {
|
|
3
|
+
return stream !== null && typeof stream === "object" && typeof stream.pipe === "function";
|
|
4
|
+
}
|
|
5
|
+
function isWritableStream(stream) {
|
|
6
|
+
return isStream(stream) && stream.writable !== false && typeof stream._write === "function" && typeof stream._writableState === "object";
|
|
7
|
+
}
|
|
8
|
+
function isReadableStream(stream) {
|
|
9
|
+
return isStream(stream) && stream.readable !== false && typeof stream._read === "function" && typeof stream._readableState === "object";
|
|
10
|
+
}
|
|
11
|
+
function isDuplexStream(stream) {
|
|
12
|
+
return isWritableStream(stream) && isReadableStream(stream);
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export { isDuplexStream, isReadableStream, isStream, isWritableStream };
|
|
@@ -0,0 +1,210 @@
|
|
|
1
|
+
import _defineProperty from '@babel/runtime/helpers/defineProperty';
|
|
2
|
+
import dequal from 'fast-deep-equal';
|
|
3
|
+
import { firstValueFrom, filter, lastValueFrom, takeWhile, tap, forkJoin, last, first, Subject, distinctUntilChanged } from 'rxjs';
|
|
4
|
+
import { AirAuthMessageTypes } from '../../common/src/realm/messaging/auth.js';
|
|
5
|
+
import { AirMessageTypes } from '../../common/src/realm/messaging/types.js';
|
|
6
|
+
import { RealmEmbedError } from './error.js';
|
|
7
|
+
import log from './loglevel.js';
|
|
8
|
+
|
|
9
|
+
const REALM_EMBED_MESSAGES = [AirMessageTypes.LOGIN_CLAIM_STATE, AirMessageTypes.CLOSE_MODAL, AirMessageTypes.SERVICE_INITIALIZED, AirMessageTypes.SERVICE_INITIALIZED_ERROR, AirMessageTypes.DEPLOY_SMART_ACCOUNT_RESPONSE];
|
|
10
|
+
const AUTH_EMBED_MESSAGES = [AirAuthMessageTypes.LOGIN_RESPONSE, AirAuthMessageTypes.USER_INFO_RESPONSE, AirAuthMessageTypes.PARTNER_USER_INFO_RESPONSE, AirAuthMessageTypes.REFRESH_TOKEN_RESPONSE, AirAuthMessageTypes.INITIALIZATION_RESPONSE, AirAuthMessageTypes.LOGOUT_RESPONSE, AirAuthMessageTypes.IFRAME_VISIBILITY_REQUEST, AirAuthMessageTypes.SETUP_WALLET_REQUEST];
|
|
11
|
+
class AirMessageService {
|
|
12
|
+
constructor() {
|
|
13
|
+
_defineProperty(this, "airMessages$", void 0);
|
|
14
|
+
_defineProperty(this, "_loginState$", void 0);
|
|
15
|
+
_defineProperty(this, "_authMessage$", void 0);
|
|
16
|
+
_defineProperty(this, "_authIframe", null);
|
|
17
|
+
_defineProperty(this, "closeAuthMessageListeners", null);
|
|
18
|
+
_defineProperty(this, "closeRealmMessageListeners", null);
|
|
19
|
+
}
|
|
20
|
+
static get instance() {
|
|
21
|
+
if (!AirMessageService._instance) {
|
|
22
|
+
AirMessageService._instance = new AirMessageService();
|
|
23
|
+
}
|
|
24
|
+
return AirMessageService._instance;
|
|
25
|
+
}
|
|
26
|
+
get messages$() {
|
|
27
|
+
return this.airMessages$.asObservable();
|
|
28
|
+
}
|
|
29
|
+
get loginState$() {
|
|
30
|
+
return this._loginState$;
|
|
31
|
+
}
|
|
32
|
+
get authMessage$() {
|
|
33
|
+
return this._authMessage$.asObservable();
|
|
34
|
+
}
|
|
35
|
+
async openAuthObservables({
|
|
36
|
+
authIframeOrigin
|
|
37
|
+
}) {
|
|
38
|
+
this.closeAuthObservables();
|
|
39
|
+
this.setupAuthObservables();
|
|
40
|
+
const handleAuthMessage = async ev => {
|
|
41
|
+
if (ev.origin !== authIframeOrigin || !ev.data || !(ev.data instanceof Object)) return;
|
|
42
|
+
log.debug("Embed auth message received from auth", ev.data);
|
|
43
|
+
if (AUTH_EMBED_MESSAGES.includes(ev.data.type)) {
|
|
44
|
+
this._authMessage$.next(ev.data);
|
|
45
|
+
}
|
|
46
|
+
};
|
|
47
|
+
window.addEventListener("message", handleAuthMessage);
|
|
48
|
+
this.closeAuthMessageListeners = () => {
|
|
49
|
+
window.removeEventListener("message", handleAuthMessage);
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
async openRealmObservables({
|
|
53
|
+
walletIframeOrigin
|
|
54
|
+
}) {
|
|
55
|
+
this.closeRealmObservables();
|
|
56
|
+
this.setupRealmObservables();
|
|
57
|
+
const handleMessage = async ev => {
|
|
58
|
+
if (ev.origin !== walletIframeOrigin || !ev.data || !(ev.data instanceof Object)) return;
|
|
59
|
+
// filter out torus and communication provider messages
|
|
60
|
+
if ("target" in ev.data && (ev.data.target === "embed_torus" || ev.data.target === "embed_communication")) return;
|
|
61
|
+
log.debug("Embed realm message received from wallet", ev.data);
|
|
62
|
+
if (REALM_EMBED_MESSAGES.includes(ev.data.type)) {
|
|
63
|
+
this.airMessages$.next(ev.data);
|
|
64
|
+
}
|
|
65
|
+
};
|
|
66
|
+
window.addEventListener("message", handleMessage);
|
|
67
|
+
this.closeRealmMessageListeners = () => {
|
|
68
|
+
window.removeEventListener("message", handleMessage);
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
// Note: Only use when embed is needed in airAuth
|
|
73
|
+
setupAuthIframe(authIframe) {
|
|
74
|
+
this._authIframe = authIframe;
|
|
75
|
+
}
|
|
76
|
+
setupIframeCommunication(walletIframe) {
|
|
77
|
+
if (!this._authIframe) return;
|
|
78
|
+
const channel = new MessageChannel();
|
|
79
|
+
const authOrigin = new URL(this._authIframe.src).origin;
|
|
80
|
+
this._authIframe.contentWindow.postMessage({
|
|
81
|
+
type: AirAuthMessageTypes.INIT_WALLET_COMMUNICATION
|
|
82
|
+
}, authOrigin, [channel.port1]);
|
|
83
|
+
const walletOrigin = new URL(walletIframe.src).origin;
|
|
84
|
+
walletIframe.contentWindow.postMessage({
|
|
85
|
+
type: AirMessageTypes.INIT_AUTH_COMMUNICATION
|
|
86
|
+
}, walletOrigin, [channel.port2]);
|
|
87
|
+
this._authIframe = undefined;
|
|
88
|
+
}
|
|
89
|
+
onInitialized() {
|
|
90
|
+
return firstValueFrom(this.messages$.pipe(filter(msg => msg.type === AirMessageTypes.SERVICE_INITIALIZED)));
|
|
91
|
+
}
|
|
92
|
+
sendLoginRequest(walletIframe, payload) {
|
|
93
|
+
const response = lastValueFrom(this.loginState$.pipe(takeWhile(msg => (!payload.skipClaimFlow || msg.payload.state !== "connected") && msg.payload.state !== "logged_in" && msg.payload.state !== "claim_flow_cancelled", true), tap(msg => {
|
|
94
|
+
switch (msg.payload.state) {
|
|
95
|
+
case "claim_flow_cancelled":
|
|
96
|
+
throw new RealmEmbedError(msg.payload.errorName, msg.payload.errorMessage);
|
|
97
|
+
}
|
|
98
|
+
})));
|
|
99
|
+
const {
|
|
100
|
+
origin
|
|
101
|
+
} = new URL(walletIframe.src);
|
|
102
|
+
walletIframe.contentWindow.postMessage({
|
|
103
|
+
type: AirMessageTypes.LOGIN_REQUEST,
|
|
104
|
+
payload
|
|
105
|
+
}, origin);
|
|
106
|
+
return response;
|
|
107
|
+
}
|
|
108
|
+
sendClaimRequest(walletIframe, options) {
|
|
109
|
+
const response = lastValueFrom(forkJoin([this.loginState$.pipe(takeWhile(msg => !["logged_in", "claim_flow_cancelled"].includes(msg.payload.state), true), tap(msg => {
|
|
110
|
+
if (msg.payload.state === "claim_flow_cancelled") {
|
|
111
|
+
throw new RealmEmbedError(msg.payload.errorName, msg.payload.errorMessage);
|
|
112
|
+
}
|
|
113
|
+
}), last()), this.messages$.pipe(filter(msg => msg.type === AirMessageTypes.CLOSE_MODAL), first())]));
|
|
114
|
+
const {
|
|
115
|
+
origin
|
|
116
|
+
} = new URL(walletIframe.src);
|
|
117
|
+
walletIframe.contentWindow.postMessage({
|
|
118
|
+
type: AirMessageTypes.CLAIM_REQUEST,
|
|
119
|
+
payload: {
|
|
120
|
+
token: options === null || options === void 0 ? void 0 : options.token,
|
|
121
|
+
claimInBackground: options === null || options === void 0 ? void 0 : options.background
|
|
122
|
+
}
|
|
123
|
+
}, origin);
|
|
124
|
+
return response;
|
|
125
|
+
}
|
|
126
|
+
sendDeploySmartAccountRequest(walletIframe) {
|
|
127
|
+
const response = firstValueFrom(this.messages$.pipe(filter(msg => msg.type === AirMessageTypes.DEPLOY_SMART_ACCOUNT_RESPONSE)));
|
|
128
|
+
const {
|
|
129
|
+
origin
|
|
130
|
+
} = new URL(walletIframe.src);
|
|
131
|
+
walletIframe.contentWindow.postMessage({
|
|
132
|
+
type: AirMessageTypes.DEPLOY_SMART_ACCOUNT_REQUEST
|
|
133
|
+
}, origin);
|
|
134
|
+
return response;
|
|
135
|
+
}
|
|
136
|
+
async sendUserInfoRequest(authIframe) {
|
|
137
|
+
const response = firstValueFrom(this.authMessage$.pipe(filter(msg => msg.type === AirAuthMessageTypes.USER_INFO_RESPONSE)));
|
|
138
|
+
const {
|
|
139
|
+
origin
|
|
140
|
+
} = new URL(authIframe.src);
|
|
141
|
+
authIframe.contentWindow.postMessage({
|
|
142
|
+
type: AirAuthMessageTypes.USER_INFO_REQUEST
|
|
143
|
+
}, origin);
|
|
144
|
+
return response;
|
|
145
|
+
}
|
|
146
|
+
async sendPartnerUserInfoRequest(authIframe) {
|
|
147
|
+
const response = firstValueFrom(this.authMessage$.pipe(filter(msg => msg.type === AirAuthMessageTypes.PARTNER_USER_INFO_RESPONSE)));
|
|
148
|
+
const {
|
|
149
|
+
origin
|
|
150
|
+
} = new URL(authIframe.src);
|
|
151
|
+
authIframe.contentWindow.postMessage({
|
|
152
|
+
type: AirAuthMessageTypes.PARTNER_USER_INFO_REQUEST
|
|
153
|
+
}, origin);
|
|
154
|
+
return response;
|
|
155
|
+
}
|
|
156
|
+
async sendAuthLoginRequest(authIframe, payload) {
|
|
157
|
+
const response = firstValueFrom(this.authMessage$.pipe(filter(msg => msg.type === AirAuthMessageTypes.LOGIN_RESPONSE)));
|
|
158
|
+
const {
|
|
159
|
+
origin
|
|
160
|
+
} = new URL(authIframe.src);
|
|
161
|
+
authIframe.contentWindow.postMessage({
|
|
162
|
+
type: AirAuthMessageTypes.LOGIN_REQUEST,
|
|
163
|
+
payload
|
|
164
|
+
}, origin);
|
|
165
|
+
return response;
|
|
166
|
+
}
|
|
167
|
+
async logoutAuth(authIframe) {
|
|
168
|
+
const response = firstValueFrom(this.authMessage$.pipe(filter(msg => msg.type === AirAuthMessageTypes.LOGOUT_RESPONSE)));
|
|
169
|
+
const {
|
|
170
|
+
origin
|
|
171
|
+
} = new URL(authIframe.src);
|
|
172
|
+
authIframe.contentWindow.postMessage({
|
|
173
|
+
type: AirAuthMessageTypes.LOGOUT_REQUEST
|
|
174
|
+
}, origin);
|
|
175
|
+
return response;
|
|
176
|
+
}
|
|
177
|
+
async waitForAuthInitialization() {
|
|
178
|
+
const response = await firstValueFrom(this._authMessage$.pipe(filter(msg => msg.type === AirAuthMessageTypes.INITIALIZATION_RESPONSE)));
|
|
179
|
+
if (response.payload.success === false) {
|
|
180
|
+
throw new RealmEmbedError(response.payload.errorName, response.payload.errorMessage);
|
|
181
|
+
}
|
|
182
|
+
return response.payload;
|
|
183
|
+
}
|
|
184
|
+
async waitForWalletInitialization() {
|
|
185
|
+
const response = await firstValueFrom(this.messages$.pipe(filter(msg => msg.type === AirMessageTypes.SERVICE_INITIALIZED || msg.type === AirMessageTypes.SERVICE_INITIALIZED_ERROR)));
|
|
186
|
+
if (response.type === AirMessageTypes.SERVICE_INITIALIZED_ERROR) {
|
|
187
|
+
throw new RealmEmbedError(response.payload.errorName, response.payload.errorMessage);
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
closeAuthObservables() {
|
|
191
|
+
if (this._authMessage$ && !this._authMessage$.closed) this._authMessage$.complete();
|
|
192
|
+
if (this.closeAuthMessageListeners) this.closeAuthMessageListeners();
|
|
193
|
+
}
|
|
194
|
+
closeRealmObservables() {
|
|
195
|
+
if (this.airMessages$ && !this.airMessages$.closed) this.airMessages$.complete();
|
|
196
|
+
if (this.closeRealmMessageListeners) this.closeRealmMessageListeners();
|
|
197
|
+
}
|
|
198
|
+
setupAuthObservables() {
|
|
199
|
+
this._authMessage$ = new Subject();
|
|
200
|
+
}
|
|
201
|
+
setupRealmObservables() {
|
|
202
|
+
this.airMessages$ = new Subject();
|
|
203
|
+
this._loginState$ = this.airMessages$.pipe(filter(msg => msg.type === AirMessageTypes.LOGIN_CLAIM_STATE), distinctUntilChanged(dequal));
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
// eslint-disable-next-line no-use-before-define
|
|
207
|
+
_defineProperty(AirMessageService, "_instance", void 0);
|
|
208
|
+
var AirMessageService$1 = AirMessageService.instance;
|
|
209
|
+
|
|
210
|
+
export { AirMessageService$1 as default };
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
var messages = {
|
|
2
|
+
errors: {
|
|
3
|
+
disconnected: () => "Web3Auth: Lost connection to Web3Auth.",
|
|
4
|
+
permanentlyDisconnected: () => "Web3Auth: Disconnected from iframe. Page reload required.",
|
|
5
|
+
unsupportedSync: method => `Web3Auth: The Web3Auth Ethereum provider does not support synchronous methods like ${method} without a callback parameter.`,
|
|
6
|
+
invalidDuplexStream: () => "Must provide a Node.js-style duplex stream.",
|
|
7
|
+
invalidOptions: maxEventListeners => `Invalid options. Received: { maxEventListeners: ${maxEventListeners}}`,
|
|
8
|
+
invalidRequestArgs: () => `Expected a single, non-array, object argument.`,
|
|
9
|
+
invalidRequestMethod: () => `'args.method' must be a non-empty string.`,
|
|
10
|
+
invalidRequestParams: () => `'args.params' must be an object or array if provided.`,
|
|
11
|
+
invalidLoggerObject: () => `'args.logger' must be an object if provided.`,
|
|
12
|
+
invalidLoggerMethod: method => `'args.logger' must include required method '${method}'.`
|
|
13
|
+
},
|
|
14
|
+
info: {
|
|
15
|
+
connected: chainId => `Web3Auth: Connected to chain with ID "${chainId}".`
|
|
16
|
+
},
|
|
17
|
+
warnings: {}
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
export { messages as default };
|