@0xsequence/provider 0.42.9 → 0.43.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.
- package/dist/0xsequence-provider.cjs.dev.js +422 -869
- package/dist/0xsequence-provider.cjs.prod.js +422 -869
- package/dist/0xsequence-provider.esm.js +423 -870
- package/dist/declarations/src/provider.d.ts +7 -6
- package/dist/declarations/src/transports/base-provider-transport.d.ts +1 -1
- package/dist/declarations/src/transports/base-wallet-transport.d.ts +1 -1
- package/dist/declarations/src/transports/mux-transport/mux-message-provider.d.ts +2 -2
- package/dist/declarations/src/transports/proxy-transport/proxy-message-provider.d.ts +1 -1
- package/dist/declarations/src/transports/unreal-transport/unreal-message-provider.d.ts +1 -1
- package/dist/declarations/src/transports/wallet-request-handler.d.ts +10 -4
- package/dist/declarations/src/transports/window-transport/window-message-provider.d.ts +1 -1
- package/dist/declarations/src/types.d.ts +1 -1
- package/dist/declarations/src/utils/index.d.ts +4 -5
- package/dist/declarations/src/utils.d.ts +4 -4
- package/dist/declarations/src/wallet.d.ts +5 -5
- package/package.json +14 -15
- package/src/provider.ts +10 -14
- package/src/transports/wallet-request-handler.ts +17 -2
- package/src/types.ts +1 -2
- package/src/utils/index.ts +2 -9
- package/src/wallet.ts +2 -3
|
@@ -1,42 +1,37 @@
|
|
|
1
1
|
import { EventEmitter2 } from 'eventemitter2';
|
|
2
2
|
import { logger, shallowCopy, resolveProperties, encodeMessageDigest, encodeTypedDataDigest, packMessageData, sanitizeNumberString, sanitizeHost, sanitizeAlphanumeric, base64EncodeObject, base64DecodeObject } from '@0xsequence/utils';
|
|
3
|
-
import { ethers, BigNumber } from 'ethers';
|
|
3
|
+
import { ethers, BigNumber, providers } from 'ethers';
|
|
4
4
|
import { addressOf, isConfigEqual } from '@0xsequence/config';
|
|
5
|
-
import { Web3Provider as Web3Provider$1, JsonRpcProvider } from '@ethersproject/providers';
|
|
6
5
|
import { JsonRpcSender, maybeChainId, allowProviderMiddleware, networkProviderMiddleware, CachedProvider, JsonRpcRouter, loggingProviderMiddleware, exceptionProviderMiddleware, findNetworkConfig, EagerProvider, SigningProvider, updateNetworkConfig, ensureValidNetworks } from '@0xsequence/network';
|
|
7
6
|
import { Signer, resolveArrayProperties, isValidSignature as isValidSignature$1, recoverConfig } from '@0xsequence/wallet';
|
|
8
7
|
import { isSignedTransactions } from '@0xsequence/transactions';
|
|
9
8
|
import { signAuthorization } from '@0xsequence/auth';
|
|
10
9
|
|
|
11
10
|
function _extends() {
|
|
12
|
-
_extends = Object.assign
|
|
11
|
+
_extends = Object.assign ? Object.assign.bind() : function (target) {
|
|
13
12
|
for (var i = 1; i < arguments.length; i++) {
|
|
14
13
|
var source = arguments[i];
|
|
15
|
-
|
|
16
14
|
for (var key in source) {
|
|
17
15
|
if (Object.prototype.hasOwnProperty.call(source, key)) {
|
|
18
16
|
target[key] = source[key];
|
|
19
17
|
}
|
|
20
18
|
}
|
|
21
19
|
}
|
|
22
|
-
|
|
23
20
|
return target;
|
|
24
21
|
};
|
|
25
|
-
|
|
26
22
|
return _extends.apply(this, arguments);
|
|
27
23
|
}
|
|
28
24
|
|
|
29
25
|
// ProviderMessageCallback is used to respond to ProviderMessage requests. The error
|
|
30
26
|
// argument is for exceptions during the execution, and response is the response payload
|
|
31
27
|
// which may contain the result or an error payload from the wallet.
|
|
28
|
+
|
|
32
29
|
class WindowSessionParams extends URLSearchParams {
|
|
33
30
|
static new(init) {
|
|
34
31
|
return new URLSearchParams(init);
|
|
35
32
|
}
|
|
36
|
-
|
|
37
33
|
}
|
|
38
34
|
let EventType;
|
|
39
|
-
|
|
40
35
|
(function (EventType) {
|
|
41
36
|
EventType["OPEN"] = "open";
|
|
42
37
|
EventType["CLOSE"] = "close";
|
|
@@ -50,31 +45,27 @@ let EventType;
|
|
|
50
45
|
EventType["INIT"] = "init";
|
|
51
46
|
EventType["DEBUG"] = "_debug";
|
|
52
47
|
})(EventType || (EventType = {}));
|
|
53
|
-
|
|
54
48
|
let OpenState;
|
|
55
|
-
|
|
56
49
|
(function (OpenState) {
|
|
57
50
|
OpenState[OpenState["CLOSED"] = 0] = "CLOSED";
|
|
58
51
|
OpenState[OpenState["OPENING"] = 1] = "OPENING";
|
|
59
52
|
OpenState[OpenState["OPENED"] = 2] = "OPENED";
|
|
60
53
|
})(OpenState || (OpenState = {}));
|
|
61
|
-
|
|
62
54
|
let InitState;
|
|
63
|
-
|
|
64
55
|
(function (InitState) {
|
|
65
56
|
InitState[InitState["NIL"] = 0] = "NIL";
|
|
66
57
|
InitState[InitState["SENT_NONCE"] = 1] = "SENT_NONCE";
|
|
67
58
|
InitState[InitState["OK"] = 2] = "OK";
|
|
68
59
|
})(InitState || (InitState = {}));
|
|
69
|
-
|
|
70
60
|
class ProviderError extends Error {
|
|
71
61
|
constructor(message) {
|
|
72
62
|
super(message);
|
|
73
63
|
this.name = 'ProviderError';
|
|
74
64
|
}
|
|
75
|
-
|
|
76
65
|
}
|
|
77
|
-
const ErrSignedInRequired = new ProviderError('Wallet is not signed in. Connect a wallet and try again.');
|
|
66
|
+
const ErrSignedInRequired = new ProviderError('Wallet is not signed in. Connect a wallet and try again.');
|
|
67
|
+
|
|
68
|
+
// TODO: lets build some nice error handling tools, prob in /utils ...
|
|
78
69
|
|
|
79
70
|
const PROVIDER_OPEN_TIMEOUT = 30000; // in ms
|
|
80
71
|
|
|
@@ -83,7 +74,6 @@ const nextMessageIdx = () => ++_messageIdx;
|
|
|
83
74
|
class BaseProviderTransport {
|
|
84
75
|
constructor() {
|
|
85
76
|
var _this = this;
|
|
86
|
-
|
|
87
77
|
this.pendingMessageRequests = [];
|
|
88
78
|
this.responseCallbacks = new Map();
|
|
89
79
|
this.state = void 0;
|
|
@@ -97,27 +87,27 @@ class BaseProviderTransport {
|
|
|
97
87
|
this._sessionId = void 0;
|
|
98
88
|
this._init = void 0;
|
|
99
89
|
this._registered = void 0;
|
|
100
|
-
|
|
101
90
|
this.sendAsync = async function (request, callback, chainId) {
|
|
102
91
|
// here, we receive the message from the dapp provider call
|
|
92
|
+
|
|
103
93
|
if (_this.state === OpenState.CLOSED) {
|
|
104
94
|
// flag the wallet to auto-close once user submits input. ie.
|
|
105
95
|
// prompting to sign a message or transaction
|
|
106
96
|
_this.confirmationOnly = true;
|
|
107
|
-
}
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
// open/focus the wallet.
|
|
108
100
|
// automatically open the wallet when a provider request makes it here.
|
|
109
101
|
//
|
|
110
102
|
// NOTE: if we're not signed in, then the provider will fail, users must first connect+sign in.
|
|
111
103
|
//
|
|
112
104
|
// TODO: how does this behave with a session has expired?
|
|
113
|
-
|
|
114
|
-
|
|
115
105
|
_this.openWallet(undefined, {
|
|
116
106
|
type: 'jsonRpcRequest',
|
|
117
107
|
method: request.method
|
|
118
|
-
}, chainId);
|
|
119
|
-
|
|
108
|
+
}, chainId);
|
|
120
109
|
|
|
110
|
+
// send message request, await, and then execute callback after receiving the response
|
|
121
111
|
try {
|
|
122
112
|
if (!_this.isOpened()) {
|
|
123
113
|
await _this.waitUntilOpened(); // will throw on timeout
|
|
@@ -134,13 +124,11 @@ class BaseProviderTransport {
|
|
|
134
124
|
callback(err);
|
|
135
125
|
}
|
|
136
126
|
};
|
|
137
|
-
|
|
138
127
|
this.sendMessageRequest = async function (message) {
|
|
139
128
|
return new Promise((resolve, reject) => {
|
|
140
129
|
if ((!message.idx || message.idx <= 0) && message.type !== 'init') {
|
|
141
130
|
reject(new Error('message idx not set'));
|
|
142
131
|
}
|
|
143
|
-
|
|
144
132
|
const responseCallback = (error, response) => {
|
|
145
133
|
if (error) {
|
|
146
134
|
reject(error);
|
|
@@ -150,51 +138,42 @@ class BaseProviderTransport {
|
|
|
150
138
|
throw new Error('no valid response to return');
|
|
151
139
|
}
|
|
152
140
|
};
|
|
153
|
-
|
|
154
141
|
const idx = message.idx;
|
|
155
|
-
|
|
156
142
|
if (!_this.responseCallbacks.get(idx)) {
|
|
157
143
|
_this.responseCallbacks.set(idx, responseCallback);
|
|
158
144
|
} else {
|
|
159
145
|
reject(new Error('duplicate message idx, should never happen'));
|
|
160
146
|
}
|
|
161
|
-
|
|
162
147
|
if (!_this.isOpened()) {
|
|
163
148
|
logger.debug('pushing to pending requests', message);
|
|
164
|
-
|
|
165
149
|
_this.pendingMessageRequests.push(message);
|
|
166
150
|
} else {
|
|
167
151
|
_this.sendMessage(message);
|
|
168
152
|
}
|
|
169
153
|
});
|
|
170
154
|
};
|
|
171
|
-
|
|
172
155
|
this.waitUntilOpened = async function (openTimeout = PROVIDER_OPEN_TIMEOUT) {
|
|
173
156
|
let opened = false;
|
|
174
157
|
return Promise.race([new Promise((_, reject) => {
|
|
175
158
|
const timeout = setTimeout(() => {
|
|
176
|
-
clearTimeout(timeout);
|
|
177
|
-
|
|
159
|
+
clearTimeout(timeout);
|
|
160
|
+
// only emit close if the timeout wins the race
|
|
178
161
|
if (!opened) {
|
|
179
162
|
_this.state = OpenState.CLOSED;
|
|
180
|
-
|
|
181
163
|
_this.events.emit('close', {
|
|
182
164
|
code: 1005,
|
|
183
165
|
message: 'opening wallet timed out'
|
|
184
166
|
});
|
|
185
167
|
}
|
|
186
|
-
|
|
187
168
|
reject(new Error('opening wallet timed out'));
|
|
188
169
|
}, openTimeout);
|
|
189
170
|
}), new Promise(resolve => {
|
|
190
171
|
if (_this.isOpened()) {
|
|
191
172
|
var _this$openPayload;
|
|
192
|
-
|
|
193
173
|
opened = true;
|
|
194
174
|
resolve((_this$openPayload = _this.openPayload) == null ? void 0 : _this$openPayload.session);
|
|
195
175
|
return;
|
|
196
176
|
}
|
|
197
|
-
|
|
198
177
|
_this.events.once('open', openInfo => {
|
|
199
178
|
_this.openPayload = openInfo;
|
|
200
179
|
opened = true;
|
|
@@ -202,7 +181,6 @@ class BaseProviderTransport {
|
|
|
202
181
|
});
|
|
203
182
|
})]);
|
|
204
183
|
};
|
|
205
|
-
|
|
206
184
|
this.waitUntilConnected = async function () {
|
|
207
185
|
await _this.waitUntilOpened();
|
|
208
186
|
const connect = new Promise(resolve => {
|
|
@@ -210,7 +188,6 @@ class BaseProviderTransport {
|
|
|
210
188
|
resolve(_this.connectPayload);
|
|
211
189
|
return;
|
|
212
190
|
}
|
|
213
|
-
|
|
214
191
|
_this.events.once('connect', connectDetails => {
|
|
215
192
|
_this.connectPayload = connectDetails;
|
|
216
193
|
resolve(connectDetails);
|
|
@@ -227,48 +204,37 @@ class BaseProviderTransport {
|
|
|
227
204
|
});
|
|
228
205
|
return Promise.race([connect, closeWallet]);
|
|
229
206
|
};
|
|
230
|
-
|
|
231
207
|
this.state = OpenState.CLOSED;
|
|
232
208
|
this._registered = false;
|
|
233
209
|
this._init = InitState.NIL;
|
|
234
210
|
}
|
|
235
|
-
|
|
236
211
|
get registered() {
|
|
237
212
|
return this._registered;
|
|
238
213
|
}
|
|
239
|
-
|
|
240
214
|
register() {
|
|
241
215
|
throw new Error('abstract method');
|
|
242
216
|
}
|
|
243
|
-
|
|
244
217
|
unregister() {
|
|
245
218
|
throw new Error('abstract method');
|
|
246
219
|
}
|
|
247
|
-
|
|
248
220
|
openWallet(path, intent, networkId) {
|
|
249
221
|
throw new Error('abstract method');
|
|
250
222
|
}
|
|
251
|
-
|
|
252
223
|
closeWallet() {
|
|
253
224
|
throw new Error('abstract method');
|
|
254
225
|
}
|
|
255
|
-
|
|
256
226
|
isOpened() {
|
|
257
227
|
return this.registered && this.state === OpenState.OPENED;
|
|
258
228
|
}
|
|
259
|
-
|
|
260
229
|
isConnected() {
|
|
261
230
|
var _this$openPayload2;
|
|
262
|
-
|
|
263
231
|
// if we're registered, and we have the account details, then we are connected
|
|
264
232
|
const session = (_this$openPayload2 = this.openPayload) == null ? void 0 : _this$openPayload2.session;
|
|
265
233
|
return this.registered && session !== undefined && !!session.accountAddress && session.accountAddress.length === 42 && !!session.networks && session.networks.length > 0;
|
|
266
234
|
}
|
|
267
|
-
|
|
268
235
|
// handleMessage will handle message received from the remote wallet
|
|
269
236
|
handleMessage(message) {
|
|
270
237
|
var _this2 = this;
|
|
271
|
-
|
|
272
238
|
// init incoming for initial handshake with transport.
|
|
273
239
|
// always respond to INIT messages, e.g. on popup window reload
|
|
274
240
|
if (message.type === EventType.INIT) {
|
|
@@ -276,12 +242,10 @@ class BaseProviderTransport {
|
|
|
276
242
|
const {
|
|
277
243
|
nonce
|
|
278
244
|
} = message.data;
|
|
279
|
-
|
|
280
245
|
if (!nonce || nonce.length == 0) {
|
|
281
246
|
logger.error('invalid init nonce');
|
|
282
247
|
return;
|
|
283
248
|
}
|
|
284
|
-
|
|
285
249
|
this._init = InitState.OK;
|
|
286
250
|
this.sendMessage({
|
|
287
251
|
idx: -1,
|
|
@@ -292,59 +256,55 @@ class BaseProviderTransport {
|
|
|
292
256
|
}
|
|
293
257
|
});
|
|
294
258
|
}
|
|
295
|
-
|
|
296
259
|
if (this._init !== InitState.OK) {
|
|
297
260
|
// if provider is not init'd, then we drop any received messages. the only
|
|
298
261
|
// message we will process is of event type 'init', as our acknowledgement
|
|
299
262
|
return;
|
|
300
|
-
}
|
|
301
|
-
|
|
263
|
+
}
|
|
302
264
|
|
|
265
|
+
// message is either a notification, or its a ProviderMessageResponse
|
|
303
266
|
logger.debug('RECEIVED MESSAGE FROM WALLET', message.idx, message);
|
|
304
267
|
const requestIdx = message.idx;
|
|
305
268
|
const responseCallback = this.responseCallbacks.get(requestIdx);
|
|
306
|
-
|
|
307
269
|
if (requestIdx) {
|
|
308
270
|
this.responseCallbacks.delete(requestIdx);
|
|
309
|
-
}
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
// OPEN response
|
|
310
274
|
//
|
|
311
275
|
// Flip opened flag, and flush the pending queue
|
|
312
|
-
|
|
313
|
-
|
|
314
276
|
if (message.type === EventType.OPEN && !this.isOpened()) {
|
|
315
277
|
var _message$data, _message$data2;
|
|
316
|
-
|
|
317
278
|
if (this._sessionId && this._sessionId !== ((_message$data = message.data) == null ? void 0 : _message$data.sessionId)) {
|
|
318
279
|
logger.debug('open event received from wallet, but does not match sessionId', this._sessionId);
|
|
319
280
|
return;
|
|
320
|
-
}
|
|
321
|
-
|
|
281
|
+
}
|
|
322
282
|
|
|
283
|
+
// check if open error occured due to invalid defaultNetworkId
|
|
323
284
|
if ((_message$data2 = message.data) != null && _message$data2.error) {
|
|
324
285
|
var _message$data3;
|
|
325
|
-
|
|
326
286
|
const err = new Error(`opening wallet failed: received ${(_message$data3 = message.data) == null ? void 0 : _message$data3.error}`);
|
|
327
287
|
logger.error(err);
|
|
328
288
|
this.close();
|
|
329
289
|
throw err;
|
|
330
|
-
}
|
|
331
|
-
|
|
290
|
+
}
|
|
332
291
|
|
|
292
|
+
// success!
|
|
333
293
|
this.state = OpenState.OPENED;
|
|
334
294
|
this.openPayload = message.data;
|
|
335
|
-
this.events.emit('open', this.openPayload);
|
|
295
|
+
this.events.emit('open', this.openPayload);
|
|
336
296
|
|
|
297
|
+
// flush pending requests when connected
|
|
337
298
|
if (this.pendingMessageRequests.length !== 0) {
|
|
338
299
|
const pendingMessageRequests = this.pendingMessageRequests.splice(0, this.pendingMessageRequests.length);
|
|
339
300
|
pendingMessageRequests.forEach(async function (pendingMessageRequest) {
|
|
340
301
|
_this2.sendMessage(pendingMessageRequest);
|
|
341
302
|
});
|
|
342
303
|
}
|
|
343
|
-
|
|
344
304
|
return;
|
|
345
|
-
}
|
|
346
|
-
|
|
305
|
+
}
|
|
347
306
|
|
|
307
|
+
// MESSAGE resposne
|
|
348
308
|
if (message.type === EventType.MESSAGE) {
|
|
349
309
|
// Require user confirmation, bring up wallet to prompt for input then close
|
|
350
310
|
// TODO: perhaps apply technique like in multicall to queue messages within
|
|
@@ -362,22 +322,21 @@ class BaseProviderTransport {
|
|
|
362
322
|
// or when we register two handler, or duplicate messages with the same idx are sent,
|
|
363
323
|
// all of which should be prevented prior to getting to this point
|
|
364
324
|
throw new Error('impossible state');
|
|
365
|
-
}
|
|
366
|
-
|
|
325
|
+
}
|
|
367
326
|
|
|
327
|
+
// Callback to original caller
|
|
368
328
|
if (responseCallback) {
|
|
369
329
|
this.events.emit('message', message);
|
|
370
330
|
responseCallback(message.data.error, message);
|
|
371
331
|
return;
|
|
372
332
|
}
|
|
373
|
-
}
|
|
374
|
-
|
|
333
|
+
}
|
|
375
334
|
|
|
335
|
+
// ACCOUNTS_CHANGED -- when a user logs in or out
|
|
376
336
|
if (message.type === EventType.ACCOUNTS_CHANGED) {
|
|
377
337
|
this.accountsChangedPayload = {
|
|
378
338
|
accounts: []
|
|
379
339
|
};
|
|
380
|
-
|
|
381
340
|
if (message.data && message.data.length > 0) {
|
|
382
341
|
this.accountsChangedPayload = {
|
|
383
342
|
accounts: [ethers.utils.getAddress(message.data[0])],
|
|
@@ -387,76 +346,73 @@ class BaseProviderTransport {
|
|
|
387
346
|
} else {
|
|
388
347
|
this.events.emit('accountsChanged', [], message.origin);
|
|
389
348
|
}
|
|
390
|
-
|
|
391
349
|
return;
|
|
392
|
-
}
|
|
393
|
-
|
|
350
|
+
}
|
|
394
351
|
|
|
352
|
+
// CHAIN_CHANGED -- when a user changes their default chain
|
|
395
353
|
if (message.type === EventType.CHAIN_CHANGED) {
|
|
396
354
|
this.events.emit('chainChanged', message.data);
|
|
397
355
|
return;
|
|
398
|
-
}
|
|
399
|
-
|
|
356
|
+
}
|
|
400
357
|
|
|
358
|
+
// NOTIFY NETWORKS -- when a user connects or logs in
|
|
401
359
|
if (message.type === EventType.NETWORKS) {
|
|
402
360
|
this.networksPayload = message.data;
|
|
403
361
|
this.events.emit('networks', this.networksPayload);
|
|
404
362
|
return;
|
|
405
|
-
}
|
|
406
|
-
|
|
363
|
+
}
|
|
407
364
|
|
|
365
|
+
// NOTIFY WALLET_CONTEXT -- when a user connects or logs in
|
|
408
366
|
if (message.type === EventType.WALLET_CONTEXT) {
|
|
409
367
|
this.walletContextPayload = message.data;
|
|
410
368
|
this.events.emit('walletContext', this.walletContextPayload);
|
|
411
369
|
return;
|
|
412
|
-
}
|
|
413
|
-
|
|
370
|
+
}
|
|
414
371
|
|
|
372
|
+
// NOTIFY CLOSE -- when wallet instructs to close
|
|
415
373
|
if (message.type === EventType.CLOSE) {
|
|
416
374
|
if (this.state !== OpenState.CLOSED) {
|
|
417
375
|
this.close(message.data);
|
|
418
376
|
}
|
|
419
|
-
}
|
|
420
|
-
|
|
377
|
+
}
|
|
421
378
|
|
|
379
|
+
// NOTIFY CONNECT -- when wallet instructs we've connected
|
|
422
380
|
if (message.type === EventType.CONNECT) {
|
|
423
381
|
this.connectPayload = message.data;
|
|
424
382
|
this.events.emit('connect', this.connectPayload);
|
|
425
|
-
}
|
|
426
|
-
|
|
383
|
+
}
|
|
427
384
|
|
|
385
|
+
// NOTIFY DISCONNECT -- when wallet instructs to disconnect
|
|
428
386
|
if (message.type === EventType.DISCONNECT) {
|
|
429
387
|
if (this.isConnected()) {
|
|
430
388
|
this.events.emit('disconnect', message.data);
|
|
431
389
|
this.close();
|
|
432
390
|
}
|
|
433
391
|
}
|
|
434
|
-
}
|
|
392
|
+
}
|
|
435
393
|
|
|
394
|
+
// sendMessageRequest sends a ProviderMessageRequest over the wire to the wallet
|
|
436
395
|
|
|
437
396
|
sendMessage(message) {
|
|
438
397
|
throw new Error('abstract method');
|
|
439
398
|
}
|
|
440
|
-
|
|
441
399
|
on(event, fn) {
|
|
442
400
|
this.events.on(event, fn);
|
|
443
401
|
}
|
|
444
|
-
|
|
445
402
|
once(event, fn) {
|
|
446
403
|
this.events.once(event, fn);
|
|
447
404
|
}
|
|
448
|
-
|
|
449
405
|
emit(event, ...args) {
|
|
450
406
|
return this.events.emit(event, ...args);
|
|
451
407
|
}
|
|
452
|
-
|
|
453
408
|
close(error) {
|
|
454
409
|
if (this.state === OpenState.CLOSED) return;
|
|
455
410
|
this.state = OpenState.CLOSED;
|
|
456
411
|
this.confirmationOnly = false;
|
|
457
412
|
this._sessionId = undefined;
|
|
458
|
-
logger.info('closing wallet and flushing!');
|
|
413
|
+
logger.info('closing wallet and flushing!');
|
|
459
414
|
|
|
415
|
+
// flush pending requests and return error to all callbacks
|
|
460
416
|
this.pendingMessageRequests.length = 0;
|
|
461
417
|
this.responseCallbacks.forEach(responseCallback => {
|
|
462
418
|
responseCallback(_extends({}, new Error('wallet closed'), {
|
|
@@ -471,7 +427,6 @@ class BaseProviderTransport {
|
|
|
471
427
|
this.walletContextPayload = undefined;
|
|
472
428
|
this.events.emit('close', error);
|
|
473
429
|
}
|
|
474
|
-
|
|
475
430
|
}
|
|
476
431
|
|
|
477
432
|
const SIGNER_READY_TIMEOUT = 10000;
|
|
@@ -479,12 +434,13 @@ class WalletRequestHandler {
|
|
|
479
434
|
// signer interface of the wallet. A null value means there is no signer (ie. user not signed in). An undefined
|
|
480
435
|
// value means the signer state is unknown, usually meaning the wallet app is booting up and initializing. Of course
|
|
481
436
|
// a Signer value is the actually interface to a signed-in account
|
|
482
|
-
constructor(_signer, prompter, mainnetNetworks, testnetNetworks = []) {
|
|
483
|
-
var _this = this;
|
|
484
437
|
|
|
438
|
+
constructor(_signer, prompter, auxDataProvider, mainnetNetworks, testnetNetworks = []) {
|
|
439
|
+
var _this = this;
|
|
485
440
|
this.signer = void 0;
|
|
486
441
|
this.signerReadyCallbacks = [];
|
|
487
442
|
this.prompter = void 0;
|
|
443
|
+
this.auxDataProvider = void 0;
|
|
488
444
|
this.mainnetNetworks = void 0;
|
|
489
445
|
this.testnetNetworks = void 0;
|
|
490
446
|
this._openIntent = void 0;
|
|
@@ -492,32 +448,26 @@ class WalletRequestHandler {
|
|
|
492
448
|
this._defaultNetworkId = void 0;
|
|
493
449
|
this._chainId = void 0;
|
|
494
450
|
this.events = new EventEmitter2();
|
|
495
|
-
|
|
496
451
|
this.promptConnect = async function (options) {
|
|
497
452
|
if (!options && !_this._connectOptions) {
|
|
498
453
|
// this is an unexpected state and should not happen
|
|
499
454
|
throw new Error('prompter connect options are empty');
|
|
500
455
|
}
|
|
501
|
-
|
|
502
456
|
if (!_this.prompter) {
|
|
503
457
|
// if prompter is null, we'll auto connect
|
|
504
458
|
return _this.connect(options);
|
|
505
459
|
}
|
|
506
|
-
|
|
507
460
|
const promptConnectDetails = await _this.prompter.promptConnect(options || _this._connectOptions).catch(_ => {
|
|
508
461
|
return {
|
|
509
462
|
connected: false
|
|
510
463
|
};
|
|
511
464
|
});
|
|
512
465
|
const connectDetails = promptConnectDetails;
|
|
513
|
-
|
|
514
466
|
if (connectDetails.connected && !connectDetails.session) {
|
|
515
467
|
connectDetails.session = await _this.walletSession();
|
|
516
468
|
}
|
|
517
|
-
|
|
518
469
|
return promptConnectDetails;
|
|
519
470
|
};
|
|
520
|
-
|
|
521
471
|
this.sendAsync = async function (request, callback, chainId) {
|
|
522
472
|
const response = {
|
|
523
473
|
jsonrpc: '2.0',
|
|
@@ -525,21 +475,20 @@ class WalletRequestHandler {
|
|
|
525
475
|
result: null
|
|
526
476
|
};
|
|
527
477
|
await _this.getSigner();
|
|
528
|
-
|
|
529
478
|
try {
|
|
530
479
|
// only allow public json rpc method to the provider when user is not logged in, aka signer is not set
|
|
531
480
|
if ((!_this.signer || _this.signer === null) && !permittedJsonRpcMethods.includes(request.method)) {
|
|
532
481
|
// throw new Error(`not logged in. ${request.method} is unavailable`)
|
|
533
482
|
throw ErrSignedInRequired;
|
|
534
|
-
}
|
|
535
|
-
|
|
483
|
+
}
|
|
536
484
|
|
|
485
|
+
// wallet signer
|
|
537
486
|
const signer = _this.signer;
|
|
538
|
-
if (!signer) throw new Error('WalletRequestHandler: wallet signer is not configured');
|
|
487
|
+
if (!signer) throw new Error('WalletRequestHandler: wallet signer is not configured');
|
|
539
488
|
|
|
489
|
+
// fetch the provider for the specific chain, or undefined will select defaultChain
|
|
540
490
|
const provider = await signer.getProvider(chainId);
|
|
541
491
|
if (!provider) throw new Error(`WalletRequestHandler: wallet provider is not configured for chainId ${chainId}`);
|
|
542
|
-
|
|
543
492
|
switch (request.method) {
|
|
544
493
|
case 'net_version':
|
|
545
494
|
{
|
|
@@ -547,21 +496,18 @@ class WalletRequestHandler {
|
|
|
547
496
|
response.result = result;
|
|
548
497
|
break;
|
|
549
498
|
}
|
|
550
|
-
|
|
551
499
|
case 'eth_chainId':
|
|
552
500
|
{
|
|
553
501
|
const result = await provider.send('eth_chainId', []);
|
|
554
502
|
response.result = result;
|
|
555
503
|
break;
|
|
556
504
|
}
|
|
557
|
-
|
|
558
505
|
case 'eth_accounts':
|
|
559
506
|
{
|
|
560
507
|
const walletAddress = await signer.getAddress();
|
|
561
508
|
response.result = [walletAddress];
|
|
562
509
|
break;
|
|
563
510
|
}
|
|
564
|
-
|
|
565
511
|
case 'eth_getBalance':
|
|
566
512
|
{
|
|
567
513
|
const [accountAddress, blockTag] = request.params;
|
|
@@ -569,15 +515,15 @@ class WalletRequestHandler {
|
|
|
569
515
|
response.result = walletBalance.toHexString();
|
|
570
516
|
break;
|
|
571
517
|
}
|
|
572
|
-
|
|
573
518
|
case 'personal_sign':
|
|
574
519
|
case 'eth_sign':
|
|
575
520
|
{
|
|
576
521
|
// note: message from json-rpc input is in hex format
|
|
577
|
-
let message;
|
|
522
|
+
let message;
|
|
523
|
+
|
|
524
|
+
// there is a difference in the order of the params:
|
|
578
525
|
// personal_sign: [data, address]
|
|
579
526
|
// eth_sign: [address, data]
|
|
580
|
-
|
|
581
527
|
if (request.method === 'personal_sign') {
|
|
582
528
|
const [data, address] = request.params;
|
|
583
529
|
message = data;
|
|
@@ -585,19 +531,19 @@ class WalletRequestHandler {
|
|
|
585
531
|
const [address, data] = request.params;
|
|
586
532
|
message = data;
|
|
587
533
|
}
|
|
534
|
+
let sig = '';
|
|
588
535
|
|
|
589
|
-
|
|
536
|
+
// Message must be prefixed with "\x19Ethereum Signed Message:\n"
|
|
590
537
|
// as defined by EIP-191
|
|
538
|
+
const prefixedMessage = prefixEIP191Message(message);
|
|
591
539
|
|
|
592
|
-
|
|
540
|
+
// TODO:
|
|
593
541
|
// if (process.env.TEST_MODE === 'true' && this.prompter === null) {
|
|
594
|
-
|
|
595
542
|
if (_this.prompter === null) {
|
|
596
543
|
// prompter is null, so we'll sign from here
|
|
597
544
|
sig = await signer.signMessage(prefixedMessage, chainId);
|
|
598
545
|
} else {
|
|
599
546
|
const promptResultForDeployment = await _this.handleConfirmWalletDeployPrompt(_this.prompter, signer, chainId);
|
|
600
|
-
|
|
601
547
|
if (promptResultForDeployment) {
|
|
602
548
|
sig = await _this.prompter.promptSignMessage({
|
|
603
549
|
chainId: chainId,
|
|
@@ -605,17 +551,14 @@ class WalletRequestHandler {
|
|
|
605
551
|
}, _this.connectOptions);
|
|
606
552
|
}
|
|
607
553
|
}
|
|
608
|
-
|
|
609
554
|
if (sig && sig.length > 0) {
|
|
610
555
|
response.result = sig;
|
|
611
556
|
} else {
|
|
612
557
|
// The user has declined the request when value is null
|
|
613
558
|
throw new Error('declined by user');
|
|
614
559
|
}
|
|
615
|
-
|
|
616
560
|
break;
|
|
617
561
|
}
|
|
618
|
-
|
|
619
562
|
case 'eth_signTypedData':
|
|
620
563
|
case 'eth_signTypedData_v4':
|
|
621
564
|
{
|
|
@@ -623,7 +566,6 @@ class WalletRequestHandler {
|
|
|
623
566
|
// should be an object, but in some instances may be double string encoded
|
|
624
567
|
const [signingAddress, typedDataObject] = request.params;
|
|
625
568
|
let typedData = undefined;
|
|
626
|
-
|
|
627
569
|
if (typeof typedDataObject === 'string') {
|
|
628
570
|
try {
|
|
629
571
|
typedData = JSON.parse(typedDataObject);
|
|
@@ -631,19 +573,15 @@ class WalletRequestHandler {
|
|
|
631
573
|
} else {
|
|
632
574
|
typedData = typedDataObject;
|
|
633
575
|
}
|
|
634
|
-
|
|
635
576
|
if (!typedData || !typedData.domain || !typedData.types || !typedData.message) {
|
|
636
577
|
throw new Error('invalid typedData object');
|
|
637
578
|
}
|
|
638
|
-
|
|
639
579
|
let sig = '';
|
|
640
|
-
|
|
641
580
|
if (_this.prompter === null) {
|
|
642
581
|
// prompter is null, so we'll sign from here
|
|
643
582
|
sig = await signer.signTypedData(typedData.domain, typedData.types, typedData.message, chainId);
|
|
644
583
|
} else {
|
|
645
584
|
const promptResultForDeployment = await _this.handleConfirmWalletDeployPrompt(_this.prompter, signer, chainId);
|
|
646
|
-
|
|
647
585
|
if (promptResultForDeployment) {
|
|
648
586
|
sig = await _this.prompter.promptSignMessage({
|
|
649
587
|
chainId: chainId,
|
|
@@ -651,30 +589,26 @@ class WalletRequestHandler {
|
|
|
651
589
|
}, _this.connectOptions);
|
|
652
590
|
}
|
|
653
591
|
}
|
|
654
|
-
|
|
655
592
|
if (sig && sig.length > 0) {
|
|
656
593
|
response.result = sig;
|
|
657
594
|
} else {
|
|
658
595
|
// The user has declined the request when value is null
|
|
659
596
|
throw new Error('declined by user');
|
|
660
597
|
}
|
|
661
|
-
|
|
662
598
|
break;
|
|
663
599
|
}
|
|
664
|
-
|
|
665
600
|
case 'eth_sendTransaction':
|
|
666
601
|
{
|
|
667
602
|
// https://eth.wiki/json-rpc/API#eth_sendtransaction
|
|
668
|
-
const [transactionParams] = request.params;
|
|
669
|
-
// ethers and sequence use 'gasLimit'
|
|
603
|
+
const [transactionParams] = request.params;
|
|
670
604
|
|
|
605
|
+
// eth_sendTransaction uses 'gas'
|
|
606
|
+
// ethers and sequence use 'gasLimit'
|
|
671
607
|
if ('gas' in transactionParams && transactionParams.gasLimit === undefined) {
|
|
672
608
|
transactionParams.gasLimit = transactionParams.gas;
|
|
673
609
|
delete transactionParams.gas;
|
|
674
610
|
}
|
|
675
|
-
|
|
676
611
|
let txnHash = '';
|
|
677
|
-
|
|
678
612
|
if (_this.prompter === null) {
|
|
679
613
|
// prompter is null, so we'll send from here
|
|
680
614
|
const txnResponse = await signer.sendTransaction(transactionParams, chainId);
|
|
@@ -683,27 +617,22 @@ class WalletRequestHandler {
|
|
|
683
617
|
// prompt user to provide the response
|
|
684
618
|
txnHash = await _this.prompter.promptSendTransaction(transactionParams, chainId, _this.connectOptions);
|
|
685
619
|
}
|
|
686
|
-
|
|
687
620
|
if (txnHash) {
|
|
688
621
|
response.result = txnHash;
|
|
689
622
|
} else {
|
|
690
623
|
// The user has declined the request when value is null
|
|
691
624
|
throw new Error('declined by user');
|
|
692
625
|
}
|
|
693
|
-
|
|
694
626
|
break;
|
|
695
627
|
}
|
|
696
|
-
|
|
697
628
|
case 'eth_signTransaction':
|
|
698
629
|
{
|
|
699
630
|
// https://eth.wiki/json-rpc/API#eth_signTransaction
|
|
700
631
|
const [transaction] = request.params;
|
|
701
632
|
const sender = ethers.utils.getAddress(transaction.from);
|
|
702
|
-
|
|
703
633
|
if (sender !== (await signer.getAddress())) {
|
|
704
634
|
throw new Error('sender address does not match wallet');
|
|
705
635
|
}
|
|
706
|
-
|
|
707
636
|
if (_this.prompter === null) {
|
|
708
637
|
// The eth_signTransaction method expects a `string` return value we instead return a `SignedTransactions` object,
|
|
709
638
|
// this can only be broadcasted using an RPC provider with support for signed Sequence transactions, like this one.
|
|
@@ -714,14 +643,13 @@ class WalletRequestHandler {
|
|
|
714
643
|
} else {
|
|
715
644
|
response.result = await _this.prompter.promptSignTransaction(transaction, chainId, _this.connectOptions);
|
|
716
645
|
}
|
|
717
|
-
|
|
718
646
|
break;
|
|
719
647
|
}
|
|
720
|
-
|
|
721
648
|
case 'eth_sendRawTransaction':
|
|
722
649
|
{
|
|
723
650
|
// NOTE: we're not using a prompter here as the transaction is already signed
|
|
724
651
|
// and would have prompted the user upon signing.
|
|
652
|
+
|
|
725
653
|
// https://eth.wiki/json-rpc/API#eth_sendRawTransaction
|
|
726
654
|
if (isSignedTransactions(request.params[0])) {
|
|
727
655
|
const txChainId = BigNumber.from(request.params[0].chainId).toNumber();
|
|
@@ -731,16 +659,13 @@ class WalletRequestHandler {
|
|
|
731
659
|
const tx = await provider.sendTransaction(request.params[0]);
|
|
732
660
|
response.result = tx.hash;
|
|
733
661
|
}
|
|
734
|
-
|
|
735
662
|
break;
|
|
736
663
|
}
|
|
737
|
-
|
|
738
664
|
case 'eth_getTransactionCount':
|
|
739
665
|
{
|
|
740
666
|
const address = ethers.utils.getAddress(request.params[0]);
|
|
741
667
|
const tag = request.params[1];
|
|
742
668
|
const walletAddress = ethers.utils.getAddress(await signer.getAddress());
|
|
743
|
-
|
|
744
669
|
if (address === walletAddress) {
|
|
745
670
|
const count = await signer.getTransactionCount(tag);
|
|
746
671
|
response.result = ethers.BigNumber.from(count).toHexString();
|
|
@@ -748,111 +673,91 @@ class WalletRequestHandler {
|
|
|
748
673
|
const count = await provider.getTransactionCount(address, tag);
|
|
749
674
|
response.result = ethers.BigNumber.from(count).toHexString();
|
|
750
675
|
}
|
|
751
|
-
|
|
752
676
|
break;
|
|
753
677
|
}
|
|
754
|
-
|
|
755
678
|
case 'eth_blockNumber':
|
|
756
679
|
{
|
|
757
680
|
response.result = await provider.getBlockNumber();
|
|
758
681
|
break;
|
|
759
682
|
}
|
|
760
|
-
|
|
761
683
|
case 'eth_getBlockByNumber':
|
|
762
684
|
{
|
|
763
|
-
response.result = await provider.getBlock(request.params[0]
|
|
764
|
-
/* , jsonRpcRequest.params[1] */
|
|
765
|
-
);
|
|
685
|
+
response.result = await provider.getBlock(request.params[0] /* , jsonRpcRequest.params[1] */);
|
|
766
686
|
break;
|
|
767
687
|
}
|
|
768
|
-
|
|
769
688
|
case 'eth_getBlockByHash':
|
|
770
689
|
{
|
|
771
|
-
response.result = await provider.getBlock(request.params[0]
|
|
772
|
-
/* , jsonRpcRequest.params[1] */
|
|
773
|
-
);
|
|
690
|
+
response.result = await provider.getBlock(request.params[0] /* , jsonRpcRequest.params[1] */);
|
|
774
691
|
break;
|
|
775
692
|
}
|
|
776
|
-
|
|
777
693
|
case 'eth_getTransactionByHash':
|
|
778
694
|
{
|
|
779
695
|
response.result = await provider.getTransaction(request.params[0]);
|
|
780
696
|
break;
|
|
781
697
|
}
|
|
782
|
-
|
|
783
698
|
case 'eth_call':
|
|
784
699
|
{
|
|
785
700
|
const [transactionObject, blockTag] = request.params;
|
|
786
701
|
response.result = await provider.call(transactionObject, blockTag);
|
|
787
702
|
break;
|
|
788
703
|
}
|
|
789
|
-
|
|
790
704
|
case 'eth_getCode':
|
|
791
705
|
{
|
|
792
706
|
const [contractAddress, blockTag] = request.params;
|
|
793
707
|
response.result = await provider.getCode(contractAddress, blockTag);
|
|
794
708
|
break;
|
|
795
709
|
}
|
|
796
|
-
|
|
797
710
|
case 'eth_estimateGas':
|
|
798
711
|
{
|
|
799
712
|
const [transactionObject] = request.params;
|
|
800
713
|
response.result = await provider.estimateGas(transactionObject);
|
|
801
714
|
break;
|
|
802
715
|
}
|
|
803
|
-
|
|
804
716
|
case 'eth_gasPrice':
|
|
805
717
|
{
|
|
806
718
|
const gasPrice = await provider.getGasPrice();
|
|
807
719
|
response.result = gasPrice.toHexString();
|
|
808
720
|
break;
|
|
809
721
|
}
|
|
810
|
-
|
|
811
722
|
case 'wallet_switchEthereumChain':
|
|
812
723
|
{
|
|
813
724
|
const [switchParams] = request.params;
|
|
814
|
-
|
|
815
725
|
if (!switchParams.chainId || switchParams.chainId.length === 0) {
|
|
816
726
|
throw new Error('invalid chainId');
|
|
817
727
|
}
|
|
818
|
-
|
|
819
728
|
const _chainId = ethers.BigNumber.from(switchParams.chainId);
|
|
820
|
-
|
|
821
729
|
const ok = await _this.setDefaultNetwork(_chainId.toString(), true);
|
|
822
|
-
|
|
823
730
|
if (!ok) {
|
|
824
731
|
throw new Error(`unable to set chainId ${_chainId}`);
|
|
825
732
|
}
|
|
826
|
-
|
|
827
733
|
response.result = null; // success
|
|
828
|
-
|
|
829
734
|
break;
|
|
830
735
|
}
|
|
831
|
-
// smart wallet method
|
|
832
736
|
|
|
737
|
+
// smart wallet method
|
|
833
738
|
case 'sequence_getWalletContext':
|
|
834
739
|
{
|
|
835
740
|
response.result = await signer.getWalletContext();
|
|
836
741
|
break;
|
|
837
742
|
}
|
|
838
|
-
// smart wallet method
|
|
839
743
|
|
|
744
|
+
// smart wallet method
|
|
840
745
|
case 'sequence_getWalletConfig':
|
|
841
746
|
{
|
|
842
747
|
const [_chainId2] = request.params;
|
|
843
748
|
response.result = await signer.getWalletConfig(_chainId2);
|
|
844
749
|
break;
|
|
845
750
|
}
|
|
846
|
-
// smart wallet method
|
|
847
751
|
|
|
752
|
+
// smart wallet method
|
|
848
753
|
case 'sequence_getWalletState':
|
|
849
754
|
{
|
|
850
755
|
const [_chainId3] = request.params;
|
|
851
756
|
response.result = await signer.getWalletState(_chainId3);
|
|
852
757
|
break;
|
|
853
758
|
}
|
|
854
|
-
// smart wallet method
|
|
855
759
|
|
|
760
|
+
// smart wallet method
|
|
856
761
|
case 'sequence_getNetworks':
|
|
857
762
|
{
|
|
858
763
|
// NOTE: must ensure that the response result below returns clean serialized data, which is to omit
|
|
@@ -861,67 +766,62 @@ class WalletRequestHandler {
|
|
|
861
766
|
response.result = await _this.getNetworks(true);
|
|
862
767
|
break;
|
|
863
768
|
}
|
|
864
|
-
// smart wallet method
|
|
865
769
|
|
|
770
|
+
// smart wallet method
|
|
866
771
|
case 'sequence_updateConfig':
|
|
867
772
|
{
|
|
868
|
-
throw new Error('sequence_updateConfig method is not allowed from a dapp');
|
|
773
|
+
throw new Error('sequence_updateConfig method is not allowed from a dapp');
|
|
774
|
+
// NOTE: method is disabled as we don't need a dapp to request to update a config.
|
|
869
775
|
// However, if we ever want this, we can enable it but must also use the prompter
|
|
870
776
|
// for confirmation.
|
|
871
777
|
//
|
|
872
778
|
// const [newConfig] = request.params
|
|
873
779
|
// response.result = await signer.updateConfig(newConfig)
|
|
874
|
-
|
|
875
780
|
break;
|
|
876
781
|
}
|
|
877
|
-
// smart wallet method
|
|
878
782
|
|
|
783
|
+
// smart wallet method
|
|
879
784
|
case 'sequence_publishConfig':
|
|
880
785
|
{
|
|
881
786
|
throw new Error('sequence_publishConfig method is not allowed from a dapp');
|
|
882
787
|
break;
|
|
883
788
|
}
|
|
884
|
-
// relayer method
|
|
885
789
|
|
|
790
|
+
// relayer method
|
|
886
791
|
case 'sequence_gasRefundOptions':
|
|
887
792
|
{
|
|
888
793
|
// TODO
|
|
889
794
|
break;
|
|
890
795
|
}
|
|
891
|
-
// relayer method
|
|
892
796
|
|
|
797
|
+
// relayer method
|
|
893
798
|
case 'sequence_getNonce':
|
|
894
799
|
{
|
|
895
800
|
// TODO
|
|
896
801
|
break;
|
|
897
802
|
}
|
|
898
|
-
// relayer method
|
|
899
803
|
|
|
804
|
+
// relayer method
|
|
900
805
|
case 'sequence_relay':
|
|
901
806
|
{
|
|
902
807
|
// TODO
|
|
903
808
|
break;
|
|
904
809
|
}
|
|
905
|
-
// set default network of wallet
|
|
906
810
|
|
|
811
|
+
// set default network of wallet
|
|
907
812
|
case 'sequence_setDefaultNetwork':
|
|
908
813
|
{
|
|
909
814
|
const [defaultNetworkId] = request.params;
|
|
910
|
-
|
|
911
815
|
if (!defaultNetworkId) {
|
|
912
816
|
throw new Error('invalid request, method argument defaultNetworkId cannot be empty');
|
|
913
817
|
}
|
|
914
|
-
|
|
915
818
|
const ok = await _this.setDefaultNetwork(defaultNetworkId);
|
|
916
|
-
|
|
917
819
|
if (!ok) {
|
|
918
820
|
throw new Error(`unable to set default network ${defaultNetworkId}`);
|
|
919
821
|
}
|
|
920
|
-
|
|
921
822
|
response.result = await _this.getNetworks(true);
|
|
922
823
|
break;
|
|
923
824
|
}
|
|
924
|
-
|
|
925
825
|
default:
|
|
926
826
|
{
|
|
927
827
|
// NOTE: provider here will be chain-bound if chainId is provided
|
|
@@ -930,38 +830,33 @@ class WalletRequestHandler {
|
|
|
930
830
|
}
|
|
931
831
|
}
|
|
932
832
|
} catch (err) {
|
|
933
|
-
logger.error(err);
|
|
833
|
+
logger.error(err);
|
|
934
834
|
|
|
835
|
+
// See https://github.com/ethereum/EIPs/blob/master/EIPS/eip-1193.md#rpc-errors
|
|
935
836
|
response.result = null;
|
|
936
837
|
response.error = _extends({}, new Error(err), {
|
|
937
838
|
code: 4001
|
|
938
839
|
});
|
|
939
840
|
}
|
|
940
|
-
|
|
941
841
|
callback(undefined, response);
|
|
942
842
|
};
|
|
943
|
-
|
|
944
843
|
this.isSignedIn = async function () {
|
|
945
844
|
await _this.signerReady();
|
|
946
845
|
return !!_this.signer;
|
|
947
846
|
};
|
|
948
|
-
|
|
949
847
|
this.getSigner = async function () {
|
|
950
848
|
await _this.signerReady();
|
|
951
|
-
|
|
952
849
|
if (_this.signer === undefined) {
|
|
953
850
|
throw new Error('signerReady failed resolve');
|
|
954
851
|
}
|
|
955
|
-
|
|
956
852
|
return _this.signer;
|
|
957
853
|
};
|
|
958
|
-
|
|
959
854
|
this.signer = _signer;
|
|
960
855
|
this.prompter = prompter;
|
|
856
|
+
this.auxDataProvider = auxDataProvider;
|
|
961
857
|
this.mainnetNetworks = mainnetNetworks;
|
|
962
858
|
this.testnetNetworks = testnetNetworks;
|
|
963
859
|
}
|
|
964
|
-
|
|
965
860
|
async signIn(signer, options = {}) {
|
|
966
861
|
this.setSigner(signer);
|
|
967
862
|
const {
|
|
@@ -970,26 +865,23 @@ class WalletRequestHandler {
|
|
|
970
865
|
testnetNetworks,
|
|
971
866
|
defaultNetworkId
|
|
972
867
|
} = options;
|
|
973
|
-
|
|
974
868
|
if (mainnetNetworks && mainnetNetworks.length > 0) {
|
|
975
869
|
this.mainnetNetworks = mainnetNetworks;
|
|
976
870
|
}
|
|
977
|
-
|
|
978
871
|
if (testnetNetworks && testnetNetworks.length > 0) {
|
|
979
872
|
this.testnetNetworks = testnetNetworks;
|
|
980
873
|
}
|
|
981
|
-
|
|
982
874
|
if ((!this.mainnetNetworks || this.mainnetNetworks.length === 0) && (!this.testnetNetworks || this.testnetNetworks.length === 0)) {
|
|
983
875
|
throw new Error('signIn failed as network configuration is empty');
|
|
984
876
|
}
|
|
985
|
-
|
|
986
877
|
const networkId = defaultNetworkId || this._defaultNetworkId;
|
|
987
|
-
|
|
988
878
|
if (networkId) {
|
|
989
879
|
if (!(await this.setDefaultNetwork(networkId, false))) {
|
|
990
880
|
throw new Error(`WalletRequestHandler setup unable to set defaultNetworkId ${networkId}`);
|
|
991
881
|
}
|
|
992
|
-
}
|
|
882
|
+
}
|
|
883
|
+
|
|
884
|
+
// Optionally, connect the dapp and wallet. In case connectOptions are provided, we will perform
|
|
993
885
|
// necessary auth request, and then notify the dapp of the 'connect' details.
|
|
994
886
|
//
|
|
995
887
|
// NOTE: if a user is signing into a dapp from a fresh state, and and auth request is made
|
|
@@ -997,30 +889,24 @@ class WalletRequestHandler {
|
|
|
997
889
|
// for this dapp, so its safe to authorize in the connect() method without the prompt.
|
|
998
890
|
//
|
|
999
891
|
// NOTE: signIn can optionally connect and notify dapp at this time for new signIn flows
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
892
|
if (connect) {
|
|
1003
893
|
const connectOptions = this._connectOptions;
|
|
1004
894
|
const connectDetails = await this.connect(connectOptions);
|
|
1005
895
|
this.notifyConnect(connectDetails);
|
|
1006
|
-
|
|
1007
896
|
if (!connectOptions || connectOptions.keepWalletOpened !== true) {
|
|
1008
897
|
this.notifyClose();
|
|
1009
898
|
}
|
|
1010
899
|
}
|
|
1011
900
|
}
|
|
1012
|
-
|
|
1013
901
|
signOut() {
|
|
1014
902
|
// signed out state
|
|
1015
903
|
this.setSigner(null);
|
|
1016
904
|
}
|
|
1017
|
-
|
|
1018
905
|
signerReset() {
|
|
1019
906
|
// resetting signer puts the wallet in an uninitialized state, which requires the app to
|
|
1020
907
|
// re-initiatize and set the signer either as "null" (ie. no signer) or "Signer" (ie. signed in).
|
|
1021
908
|
this.signer = undefined;
|
|
1022
909
|
}
|
|
1023
|
-
|
|
1024
910
|
signerReady(timeout = SIGNER_READY_TIMEOUT) {
|
|
1025
911
|
return new Promise((resolve, reject) => {
|
|
1026
912
|
if (this.signer !== undefined) {
|
|
@@ -1036,7 +922,6 @@ class WalletRequestHandler {
|
|
|
1036
922
|
}
|
|
1037
923
|
});
|
|
1038
924
|
}
|
|
1039
|
-
|
|
1040
925
|
async connect(options) {
|
|
1041
926
|
if (!this.signer) {
|
|
1042
927
|
return {
|
|
@@ -1045,12 +930,17 @@ class WalletRequestHandler {
|
|
|
1045
930
|
error: 'unable to connect without signed in account'
|
|
1046
931
|
};
|
|
1047
932
|
}
|
|
1048
|
-
|
|
1049
933
|
const connectDetails = {
|
|
1050
934
|
connected: true,
|
|
1051
935
|
chainId: ethers.utils.hexlify(await this.getChainId())
|
|
1052
936
|
};
|
|
1053
|
-
|
|
937
|
+
if (options && options.askForEmail) {
|
|
938
|
+
var _this$auxDataProvider;
|
|
939
|
+
const email = await ((_this$auxDataProvider = this.auxDataProvider) == null ? void 0 : _this$auxDataProvider.get('email'));
|
|
940
|
+
if (email) {
|
|
941
|
+
connectDetails.email = email;
|
|
942
|
+
}
|
|
943
|
+
}
|
|
1054
944
|
if (options && options.authorize) {
|
|
1055
945
|
// Perform ethauth eip712 request and construct the ConnectDetails response
|
|
1056
946
|
// including the auth proof
|
|
@@ -1058,7 +948,8 @@ class WalletRequestHandler {
|
|
|
1058
948
|
app: options.app,
|
|
1059
949
|
origin: options.origin,
|
|
1060
950
|
expiry: options.expiry
|
|
1061
|
-
};
|
|
951
|
+
};
|
|
952
|
+
// if (typeof(options.authorize) === 'object') {
|
|
1062
953
|
// authOptions = { ...authOptions, ...options.authorize }
|
|
1063
954
|
// }
|
|
1064
955
|
|
|
@@ -1072,13 +963,12 @@ class WalletRequestHandler {
|
|
|
1072
963
|
error: `signAuthorization failed: ${err.message}`
|
|
1073
964
|
};
|
|
1074
965
|
}
|
|
1075
|
-
}
|
|
1076
|
-
|
|
966
|
+
}
|
|
1077
967
|
|
|
968
|
+
// Build session response for connect details
|
|
1078
969
|
connectDetails.session = await this.walletSession();
|
|
1079
970
|
return connectDetails;
|
|
1080
971
|
}
|
|
1081
|
-
|
|
1082
972
|
// sendMessageRequest will unwrap the ProviderMessageRequest and send it to the JsonRpcHandler
|
|
1083
973
|
// (aka, the signer in this instance) and then responds with a wrapped response of
|
|
1084
974
|
// ProviderMessageResponse to be sent over the transport
|
|
@@ -1086,26 +976,26 @@ class WalletRequestHandler {
|
|
|
1086
976
|
return new Promise(resolve => {
|
|
1087
977
|
this.sendAsync(message.data, (error, response) => {
|
|
1088
978
|
// TODO: if response includes data.error, why do we need a separate error argument here?
|
|
979
|
+
|
|
1089
980
|
const responseMessage = _extends({}, message, {
|
|
1090
981
|
data: response
|
|
1091
|
-
});
|
|
1092
|
-
// in the error field of the response to ensure we send back to the user
|
|
1093
|
-
|
|
982
|
+
});
|
|
1094
983
|
|
|
984
|
+
// NOTE: we always resolve here, are the sendAsync call will wrap any exceptions
|
|
985
|
+
// in the error field of the response to ensure we send back to the user
|
|
1095
986
|
resolve(responseMessage);
|
|
1096
987
|
}, message.chainId);
|
|
1097
988
|
});
|
|
1098
|
-
}
|
|
989
|
+
}
|
|
1099
990
|
|
|
991
|
+
// sendAsync implements the JsonRpcHandler interface for sending JsonRpcRequests to the wallet
|
|
1100
992
|
|
|
1101
993
|
on(event, fn) {
|
|
1102
994
|
this.events.on(event, fn);
|
|
1103
995
|
}
|
|
1104
|
-
|
|
1105
996
|
once(event, fn) {
|
|
1106
997
|
this.events.once(event, fn);
|
|
1107
998
|
}
|
|
1108
|
-
|
|
1109
999
|
async getAddress() {
|
|
1110
1000
|
if (!this.signer) {
|
|
1111
1001
|
return '';
|
|
@@ -1113,69 +1003,54 @@ class WalletRequestHandler {
|
|
|
1113
1003
|
return this.signer.getAddress();
|
|
1114
1004
|
}
|
|
1115
1005
|
}
|
|
1116
|
-
|
|
1117
1006
|
async getChainId() {
|
|
1118
1007
|
if (!this.signer) {
|
|
1119
1008
|
return 0;
|
|
1120
1009
|
} else {
|
|
1121
1010
|
if (this._chainId) return this._chainId; // memoized
|
|
1122
|
-
|
|
1123
1011
|
this._chainId = await this.signer.getChainId();
|
|
1124
1012
|
return this._chainId;
|
|
1125
1013
|
}
|
|
1126
1014
|
}
|
|
1127
|
-
|
|
1128
1015
|
get openIntent() {
|
|
1129
1016
|
return this._openIntent;
|
|
1130
1017
|
}
|
|
1131
|
-
|
|
1132
1018
|
setOpenIntent(intent) {
|
|
1133
1019
|
this._openIntent = intent;
|
|
1134
1020
|
}
|
|
1135
|
-
|
|
1136
1021
|
get connectOptions() {
|
|
1137
1022
|
return this._connectOptions;
|
|
1138
1023
|
}
|
|
1139
|
-
|
|
1140
1024
|
setConnectOptions(options) {
|
|
1141
1025
|
this._connectOptions = options;
|
|
1142
1026
|
}
|
|
1143
|
-
|
|
1144
1027
|
get defaultNetworkId() {
|
|
1145
1028
|
return this._defaultNetworkId;
|
|
1146
1029
|
}
|
|
1147
|
-
|
|
1148
1030
|
async setDefaultNetwork(chainId, notifyNetworks = true) {
|
|
1149
1031
|
if (!chainId) return undefined;
|
|
1150
1032
|
this._defaultNetworkId = chainId;
|
|
1151
1033
|
this._chainId = undefined;
|
|
1152
|
-
|
|
1153
1034
|
if (this.signer && this.signer.setNetworks) {
|
|
1154
1035
|
const defaultChainId = this.signer.setNetworks(this.mainnetNetworks, this.testnetNetworks, chainId);
|
|
1155
|
-
|
|
1156
1036
|
if (defaultChainId && notifyNetworks) {
|
|
1157
1037
|
await this.notifyNetworks();
|
|
1158
1038
|
}
|
|
1159
|
-
|
|
1160
1039
|
return defaultChainId;
|
|
1161
1040
|
} else {
|
|
1162
1041
|
return undefined;
|
|
1163
1042
|
}
|
|
1164
1043
|
}
|
|
1165
|
-
|
|
1166
1044
|
async getNetworks(jsonRpcResponse) {
|
|
1167
1045
|
if (!this.signer) {
|
|
1168
1046
|
logger.warn('signer not set: getNetworks is returning an empty list');
|
|
1169
1047
|
return [];
|
|
1170
1048
|
}
|
|
1171
|
-
|
|
1172
1049
|
const networks = await this.signer.getNetworks();
|
|
1173
|
-
|
|
1174
1050
|
if (jsonRpcResponse) {
|
|
1175
1051
|
// omit provider and relayer objects as they are not serializable
|
|
1176
1052
|
return networks.map(n => {
|
|
1177
1053
|
const network = _extends({}, n);
|
|
1178
|
-
|
|
1179
1054
|
network.provider = undefined;
|
|
1180
1055
|
network.relayer = undefined;
|
|
1181
1056
|
return network;
|
|
@@ -1184,7 +1059,6 @@ class WalletRequestHandler {
|
|
|
1184
1059
|
return networks;
|
|
1185
1060
|
}
|
|
1186
1061
|
}
|
|
1187
|
-
|
|
1188
1062
|
async walletSession() {
|
|
1189
1063
|
return !this.signer ? undefined : {
|
|
1190
1064
|
walletContext: await this.signer.getWalletContext(),
|
|
@@ -1192,31 +1066,23 @@ class WalletRequestHandler {
|
|
|
1192
1066
|
networks: await this.getNetworks(true)
|
|
1193
1067
|
};
|
|
1194
1068
|
}
|
|
1195
|
-
|
|
1196
1069
|
notifyConnect(connectDetails, origin) {
|
|
1197
1070
|
var _connectDetails$sessi;
|
|
1198
|
-
|
|
1199
1071
|
this.events.emit('connect', connectDetails);
|
|
1200
|
-
|
|
1201
1072
|
if ((_connectDetails$sessi = connectDetails.session) != null && _connectDetails$sessi.accountAddress) {
|
|
1202
1073
|
var _connectDetails$sessi2;
|
|
1203
|
-
|
|
1204
1074
|
this.events.emit('accountsChanged', [(_connectDetails$sessi2 = connectDetails.session) == null ? void 0 : _connectDetails$sessi2.accountAddress], origin);
|
|
1205
1075
|
}
|
|
1206
1076
|
}
|
|
1207
|
-
|
|
1208
1077
|
notifyDisconnect(origin) {
|
|
1209
1078
|
this.events.emit('accountsChanged', [], origin);
|
|
1210
1079
|
this.events.emit('disconnect');
|
|
1211
1080
|
}
|
|
1212
|
-
|
|
1213
1081
|
async notifyNetworks(networks) {
|
|
1214
1082
|
const n = networks || (await this.getNetworks(true));
|
|
1215
1083
|
this.events.emit('networks', n);
|
|
1216
|
-
|
|
1217
1084
|
if (n.length > 0) {
|
|
1218
1085
|
const defaultNetwork = n.find(network => network.isDefaultChain);
|
|
1219
|
-
|
|
1220
1086
|
if (defaultNetwork) {
|
|
1221
1087
|
this.events.emit('chainChanged', ethers.utils.hexlify(defaultNetwork.chainId));
|
|
1222
1088
|
}
|
|
@@ -1224,51 +1090,40 @@ class WalletRequestHandler {
|
|
|
1224
1090
|
this.events.emit('chainChanged', '0x0');
|
|
1225
1091
|
}
|
|
1226
1092
|
}
|
|
1227
|
-
|
|
1228
1093
|
async notifyWalletContext() {
|
|
1229
1094
|
if (!this.signer) {
|
|
1230
1095
|
logger.warn('signer not set: skipping to notify wallet context');
|
|
1231
1096
|
return;
|
|
1232
1097
|
}
|
|
1233
|
-
|
|
1234
1098
|
const walletContext = await this.signer.getWalletContext();
|
|
1235
1099
|
this.events.emit('walletContext', walletContext);
|
|
1236
1100
|
}
|
|
1237
|
-
|
|
1238
1101
|
notifyClose(error) {
|
|
1239
1102
|
this.events.emit('close', error);
|
|
1240
1103
|
}
|
|
1241
|
-
|
|
1242
1104
|
setSigner(signer) {
|
|
1243
1105
|
this.signer = signer;
|
|
1244
|
-
|
|
1245
1106
|
if (signer !== undefined) {
|
|
1246
1107
|
for (let i = 0; i < this.signerReadyCallbacks.length; i++) {
|
|
1247
1108
|
this.signerReadyCallbacks[i]();
|
|
1248
1109
|
}
|
|
1249
|
-
|
|
1250
1110
|
this.signerReadyCallbacks = [];
|
|
1251
1111
|
}
|
|
1252
1112
|
}
|
|
1253
|
-
|
|
1254
1113
|
async handleConfirmWalletDeployPrompt(prompter, signer, chainId) {
|
|
1255
1114
|
// check if wallet is deployed and up to date, if not, prompt user to deploy
|
|
1256
1115
|
// if no chainId is provided, we'll assume the wallet is auth chain wallet and is up to date
|
|
1257
1116
|
if (!chainId) {
|
|
1258
1117
|
return true;
|
|
1259
1118
|
}
|
|
1260
|
-
|
|
1261
1119
|
const isUpToDate = await isWalletUpToDate(signer, chainId);
|
|
1262
|
-
|
|
1263
1120
|
if (isUpToDate) {
|
|
1264
1121
|
return true;
|
|
1265
1122
|
}
|
|
1266
|
-
|
|
1267
|
-
|
|
1268
|
-
|
|
1123
|
+
const promptResult = await prompter.promptConfirmWalletDeploy(chainId, this.connectOptions);
|
|
1124
|
+
// if client returned true, check again to make sure wallet is deployed and up to date
|
|
1269
1125
|
if (promptResult) {
|
|
1270
1126
|
const isPromptResultCorrect = await isWalletUpToDate(signer, chainId);
|
|
1271
|
-
|
|
1272
1127
|
if (!isPromptResultCorrect) {
|
|
1273
1128
|
logger.error('WalletRequestHandler: result for promptConfirmWalletDeploy is not correct');
|
|
1274
1129
|
return false;
|
|
@@ -1276,18 +1131,15 @@ class WalletRequestHandler {
|
|
|
1276
1131
|
return true;
|
|
1277
1132
|
}
|
|
1278
1133
|
}
|
|
1279
|
-
|
|
1280
1134
|
return false;
|
|
1281
1135
|
}
|
|
1282
|
-
|
|
1283
1136
|
}
|
|
1284
1137
|
const permittedJsonRpcMethods = ['net_version', 'eth_chainId', 'eth_getBalance', 'eth_getTransactionCount', 'eth_blockNumber', 'eth_getBlockByNumber', 'eth_getBlockByHash', 'eth_getTransactionByHash', 'eth_getCode', 'eth_estimateGas', 'eth_gasPrice', 'sequence_getWalletContext', 'sequence_getNetworks', 'sequence_setDefaultNetwork'];
|
|
1285
1138
|
|
|
1286
|
-
class Web3Provider extends Web3Provider
|
|
1139
|
+
class Web3Provider extends providers.Web3Provider {
|
|
1287
1140
|
static isSequenceProvider(cand) {
|
|
1288
1141
|
return isSequenceProvider(cand);
|
|
1289
1142
|
}
|
|
1290
|
-
|
|
1291
1143
|
constructor(provider, defaultChainId) {
|
|
1292
1144
|
const sender = new JsonRpcSender(provider, maybeChainId(defaultChainId));
|
|
1293
1145
|
provider = sender;
|
|
@@ -1299,35 +1151,27 @@ class Web3Provider extends Web3Provider$1 {
|
|
|
1299
1151
|
this._isSequenceProvider = true;
|
|
1300
1152
|
this._defaultChainId = maybeChainId(defaultChainId);
|
|
1301
1153
|
}
|
|
1302
|
-
|
|
1303
1154
|
sendAsync(request, callback, chainId) {
|
|
1304
1155
|
this._sender.sendAsync(request, callback, chainId);
|
|
1305
1156
|
}
|
|
1306
|
-
|
|
1307
1157
|
send(method, params, chainId) {
|
|
1308
1158
|
return this._sender.send(method, params, chainId);
|
|
1309
1159
|
}
|
|
1310
|
-
|
|
1311
1160
|
request(request) {
|
|
1312
1161
|
return this.send(request.method, request.params || [], request.chainId);
|
|
1313
1162
|
}
|
|
1314
|
-
|
|
1315
1163
|
getSigner() {
|
|
1316
1164
|
return new Web3Signer(this, this._defaultChainId);
|
|
1317
1165
|
}
|
|
1318
|
-
|
|
1319
1166
|
async getChainId() {
|
|
1320
1167
|
// TODO: is it safe to memoize this?
|
|
1321
1168
|
const result = await this.send('eth_chainId', []);
|
|
1322
1169
|
const chainId = ethers.BigNumber.from(result).toNumber();
|
|
1323
|
-
|
|
1324
1170
|
if (this._defaultChainId && this._defaultChainId !== chainId) {
|
|
1325
1171
|
throw new Error(`provider chainId (${chainId}) does not match provider-bound chainId ${this._defaultChainId}`);
|
|
1326
1172
|
}
|
|
1327
|
-
|
|
1328
1173
|
return chainId;
|
|
1329
1174
|
}
|
|
1330
|
-
|
|
1331
1175
|
}
|
|
1332
1176
|
function isSequenceProvider(provider) {
|
|
1333
1177
|
const cand = provider;
|
|
@@ -1335,11 +1179,13 @@ function isSequenceProvider(provider) {
|
|
|
1335
1179
|
}
|
|
1336
1180
|
class LocalWeb3Provider extends Web3Provider {
|
|
1337
1181
|
constructor(signer, networks) {
|
|
1338
|
-
const walletRequestHandler = new WalletRequestHandler(signer, null, networks || []);
|
|
1182
|
+
const walletRequestHandler = new WalletRequestHandler(signer, null, null, networks || []);
|
|
1339
1183
|
super(walletRequestHandler);
|
|
1340
1184
|
}
|
|
1341
|
-
|
|
1342
1185
|
}
|
|
1186
|
+
|
|
1187
|
+
// TODO: in the future with ethers v6 we can remove/change this type name
|
|
1188
|
+
|
|
1343
1189
|
class Web3Signer extends Signer {
|
|
1344
1190
|
constructor(provider, defaultChainId) {
|
|
1345
1191
|
super();
|
|
@@ -1352,12 +1198,14 @@ class Web3Signer extends Signer {
|
|
|
1352
1198
|
this._providers = {};
|
|
1353
1199
|
this.provider = provider;
|
|
1354
1200
|
this.defaultChainId = defaultChainId;
|
|
1355
|
-
}
|
|
1201
|
+
}
|
|
1356
1202
|
|
|
1203
|
+
// memoized
|
|
1357
1204
|
|
|
1358
1205
|
//
|
|
1359
1206
|
// ethers AbstractSigner methods
|
|
1360
1207
|
//
|
|
1208
|
+
|
|
1361
1209
|
async getAddress() {
|
|
1362
1210
|
if (this._address) return this._address;
|
|
1363
1211
|
const accounts = await this.provider.send('eth_accounts', []);
|
|
@@ -1365,53 +1213,47 @@ class Web3Signer extends Signer {
|
|
|
1365
1213
|
this._index = 0;
|
|
1366
1214
|
return ethers.utils.getAddress(this._address);
|
|
1367
1215
|
}
|
|
1368
|
-
|
|
1369
1216
|
signTransaction(transaction) {
|
|
1370
1217
|
// TODO .. since ethers isn't using this method, perhaps we will?
|
|
1371
1218
|
throw new Error('signTransaction is unsupported, use signTransactions instead');
|
|
1372
1219
|
}
|
|
1373
|
-
|
|
1374
1220
|
connect(provider) {
|
|
1375
1221
|
throw new Error('unsupported: cannot alter JSON-RPC Signer connection');
|
|
1376
|
-
}
|
|
1222
|
+
}
|
|
1223
|
+
|
|
1224
|
+
//
|
|
1377
1225
|
// Sequence Signer methods
|
|
1378
1226
|
//
|
|
1227
|
+
|
|
1379
1228
|
// getProvider returns a Web3Provider instance for the current chain. Note that this method
|
|
1380
1229
|
// and signer is bound to a particular chain to prevent misuse. If you'd like a provider
|
|
1381
1230
|
// for a specific chain, try getSender(chainId), or wallet.getProvider(chainId).
|
|
1382
|
-
|
|
1383
|
-
|
|
1384
1231
|
async getProvider(chainId) {
|
|
1385
1232
|
if (chainId) {
|
|
1386
1233
|
const currentChainId = await this.getChainId();
|
|
1387
|
-
|
|
1388
1234
|
if (currentChainId !== chainId) {
|
|
1389
1235
|
throw new Error(`signer is attempting to access chain ${chainId}, but is already bound to chain ${currentChainId}`);
|
|
1390
1236
|
}
|
|
1391
1237
|
}
|
|
1392
|
-
|
|
1393
1238
|
return this.provider;
|
|
1394
|
-
}
|
|
1239
|
+
}
|
|
1240
|
+
|
|
1241
|
+
// getSender returns a Web3Provider instance via the signer transport. Note: for our case
|
|
1395
1242
|
// the of sequence wallet, this will bring up the wallet window whenever using it, as the json-rpc
|
|
1396
1243
|
// requests are sent to the window transport. Therefore, for anything non-signing related
|
|
1397
1244
|
// you can write a higher-order JsonRpcRouter sender to route to the public provider endpoints
|
|
1398
1245
|
// as we do in the WalletProvider.
|
|
1399
1246
|
//
|
|
1400
1247
|
// This method is primarily utilized internally when routing requests to a particular chainId.
|
|
1401
|
-
|
|
1402
|
-
|
|
1403
1248
|
async getSender(chainId) {
|
|
1404
1249
|
if (!chainId || chainId && chainId === this.defaultChainId) {
|
|
1405
1250
|
return this.provider;
|
|
1406
1251
|
}
|
|
1407
|
-
|
|
1408
1252
|
if (!this._providers[chainId]) {
|
|
1409
1253
|
this._providers[chainId] = new Web3Provider(new JsonRpcSender(this.provider, chainId), chainId);
|
|
1410
1254
|
}
|
|
1411
|
-
|
|
1412
1255
|
return this._providers[chainId];
|
|
1413
1256
|
}
|
|
1414
|
-
|
|
1415
1257
|
getRelayer(chainId) {
|
|
1416
1258
|
// TODO: JsonRpcRelayer ......? or, Web3Relayer.. or SequenceRelayer?
|
|
1417
1259
|
// sequence_gasRefundOptions
|
|
@@ -1419,72 +1261,63 @@ class Web3Signer extends Signer {
|
|
|
1419
1261
|
// sequence_relay
|
|
1420
1262
|
throw new Error('TODO');
|
|
1421
1263
|
}
|
|
1422
|
-
|
|
1423
1264
|
async getWalletContext() {
|
|
1424
1265
|
if (!this._context) {
|
|
1425
1266
|
this._context = await this.provider.send('sequence_getWalletContext', []);
|
|
1426
1267
|
}
|
|
1427
|
-
|
|
1428
1268
|
return this._context;
|
|
1429
1269
|
}
|
|
1430
|
-
|
|
1431
1270
|
async getWalletConfig(chainId) {
|
|
1432
1271
|
return await this.provider.send('sequence_getWalletConfig', [maybeChainId(chainId)], maybeChainId(chainId) || this.defaultChainId);
|
|
1433
1272
|
}
|
|
1434
|
-
|
|
1435
1273
|
async getWalletState(chainId) {
|
|
1436
1274
|
return await this.provider.send('sequence_getWalletState', [maybeChainId(chainId)], maybeChainId(chainId) || this.defaultChainId);
|
|
1437
1275
|
}
|
|
1438
|
-
|
|
1439
1276
|
async getNetworks() {
|
|
1440
1277
|
if (!this._networks) {
|
|
1441
1278
|
this._networks = await this.provider.send('sequence_getNetworks', []);
|
|
1442
1279
|
}
|
|
1443
|
-
|
|
1444
1280
|
return this._networks;
|
|
1445
1281
|
}
|
|
1446
|
-
|
|
1447
1282
|
async getSigners() {
|
|
1448
1283
|
const networks = await this.getNetworks();
|
|
1449
1284
|
const authChainId = networks.find(n => n.isAuthChain);
|
|
1450
|
-
|
|
1451
1285
|
if (!authChainId) {
|
|
1452
1286
|
throw new Error('authChainId could not be determined from network list');
|
|
1453
1287
|
}
|
|
1454
|
-
|
|
1455
1288
|
const walletConfig = await this.getWalletConfig(authChainId);
|
|
1456
|
-
|
|
1457
1289
|
if (!walletConfig || walletConfig.length === 0) {
|
|
1458
1290
|
throw new Error(`walletConfig returned zero results for authChainId {authChainId}`);
|
|
1459
1291
|
}
|
|
1460
|
-
|
|
1461
1292
|
return walletConfig[0].signers.map(s => s.address);
|
|
1462
|
-
}
|
|
1463
|
-
// multi-chain support.
|
|
1464
|
-
|
|
1293
|
+
}
|
|
1465
1294
|
|
|
1295
|
+
// signMessage matches implementation from ethers JsonRpcSigner for compatibility, but with
|
|
1296
|
+
// multi-chain support.
|
|
1466
1297
|
async signMessage(message, chainId, allSigners) {
|
|
1467
1298
|
const provider = await this.getSender(maybeChainId(chainId) || this.defaultChainId);
|
|
1468
1299
|
const data = typeof message === 'string' ? ethers.utils.toUtf8Bytes(message) : message;
|
|
1469
|
-
const address = await this.getAddress();
|
|
1300
|
+
const address = await this.getAddress();
|
|
1301
|
+
|
|
1302
|
+
// NOTE: as of ethers v5.5, it switched to using personal_sign, see
|
|
1470
1303
|
// https://github.com/ethers-io/ethers.js/pull/1542 and see
|
|
1471
1304
|
// https://github.com/WalletConnect/walletconnect-docs/issues/32 for additional info.
|
|
1472
|
-
|
|
1473
1305
|
return await provider.send('personal_sign', [ethers.utils.hexlify(data), address]);
|
|
1474
|
-
}
|
|
1475
|
-
// multi-chain support.
|
|
1476
|
-
|
|
1306
|
+
}
|
|
1477
1307
|
|
|
1308
|
+
// signTypedData matches implementation from ethers JsonRpcSigner for compatibility, but with
|
|
1309
|
+
// multi-chain support.
|
|
1478
1310
|
async signTypedData(domain, types, message, chainId, allSigners) {
|
|
1479
1311
|
// Populate any ENS names (in-place)
|
|
1480
1312
|
// const populated = await ethers.utils._TypedDataEncoder.resolveNames(domain, types, message, (name: string) => {
|
|
1481
1313
|
// return this.provider.resolveName(name)
|
|
1482
1314
|
// })
|
|
1483
|
-
return await this.provider.send('eth_signTypedData_v4', [await this.getAddress(), ethers.utils._TypedDataEncoder.getPayload(domain, types, message)], maybeChainId(chainId) || this.defaultChainId);
|
|
1484
|
-
} // sendTransaction matches implementation from ethers JsonRpcSigner for compatibility, but with
|
|
1485
|
-
// multi-chain support.
|
|
1486
1315
|
|
|
1316
|
+
return await this.provider.send('eth_signTypedData_v4', [await this.getAddress(), ethers.utils._TypedDataEncoder.getPayload(domain, types, message)], maybeChainId(chainId) || this.defaultChainId);
|
|
1317
|
+
}
|
|
1487
1318
|
|
|
1319
|
+
// sendTransaction matches implementation from ethers JsonRpcSigner for compatibility, but with
|
|
1320
|
+
// multi-chain support.
|
|
1488
1321
|
async sendTransaction(transaction, chainId, allSigners) {
|
|
1489
1322
|
const provider = await this.getSender(maybeChainId(chainId) || this.defaultChainId);
|
|
1490
1323
|
const tx = this.sendUncheckedTransaction(transaction, chainId).then(hash => {
|
|
@@ -1493,7 +1326,6 @@ class Web3Signer extends Signer {
|
|
|
1493
1326
|
if (tx === null) {
|
|
1494
1327
|
return undefined;
|
|
1495
1328
|
}
|
|
1496
|
-
|
|
1497
1329
|
return provider._wrapTransaction(tx, hash);
|
|
1498
1330
|
});
|
|
1499
1331
|
}, {
|
|
@@ -1502,98 +1334,90 @@ class Web3Signer extends Signer {
|
|
|
1502
1334
|
error.transactionHash = hash;
|
|
1503
1335
|
throw error;
|
|
1504
1336
|
});
|
|
1505
|
-
});
|
|
1337
|
+
});
|
|
1506
1338
|
|
|
1339
|
+
// @ts-ignore
|
|
1507
1340
|
return tx;
|
|
1508
|
-
}
|
|
1509
|
-
// send multiple transaction as a single payload and just one on-chain transaction.
|
|
1510
|
-
|
|
1341
|
+
}
|
|
1511
1342
|
|
|
1343
|
+
// sendTransactionBatch is a convenience method to call sendTransaction in a batch format, allowing you to
|
|
1344
|
+
// send multiple transaction as a single payload and just one on-chain transaction.
|
|
1512
1345
|
async sendTransactionBatch(transactions, chainId, allSigners) {
|
|
1513
1346
|
const batch = await resolveArrayProperties(transactions);
|
|
1514
|
-
|
|
1515
1347
|
if (!batch || batch.length === 0) {
|
|
1516
1348
|
throw new Error('cannot send empty batch');
|
|
1517
|
-
}
|
|
1518
|
-
|
|
1349
|
+
}
|
|
1519
1350
|
|
|
1351
|
+
// sendTransactionBatch only accepts TransactionRequest, not TransactionResponses
|
|
1520
1352
|
if (batch.find(v => v.wait !== undefined && v.wait !== null)) {
|
|
1521
1353
|
throw new Error('transaction request expected for sendTransactionBatch, transaction response found');
|
|
1522
1354
|
}
|
|
1523
|
-
|
|
1524
1355
|
const tx = _extends({}, batch[0]);
|
|
1525
|
-
|
|
1526
1356
|
if (batch.length > 1) {
|
|
1527
1357
|
tx.auxiliary = batch.splice(1);
|
|
1528
1358
|
}
|
|
1529
|
-
|
|
1530
1359
|
return this.sendTransaction(tx, chainId, allSigners);
|
|
1531
1360
|
}
|
|
1532
|
-
|
|
1533
1361
|
signTransactions(transaction, chainId, allSigners) {
|
|
1534
|
-
transaction = shallowCopy(transaction);
|
|
1362
|
+
transaction = shallowCopy(transaction);
|
|
1363
|
+
// TODO: transaction argument..? make sure to resolve any properties and serialize property before sending over
|
|
1535
1364
|
// the wire.. see sendUncheckedTransaction and resolveProperties
|
|
1536
|
-
|
|
1537
1365
|
return this.provider.send('eth_signTransaction', [transaction], maybeChainId(chainId) || this.defaultChainId);
|
|
1538
1366
|
}
|
|
1539
|
-
|
|
1540
1367
|
sendSignedTransactions(signedTxs, chainId) {
|
|
1541
1368
|
// sequence_relay
|
|
1542
1369
|
throw new Error('TODO');
|
|
1543
|
-
}
|
|
1544
|
-
// NOTE: this is not supported by the remote wallet by default.
|
|
1545
|
-
|
|
1370
|
+
}
|
|
1546
1371
|
|
|
1372
|
+
// updateConfig..
|
|
1373
|
+
// NOTE: this is not supported by the remote wallet by default.
|
|
1547
1374
|
async updateConfig(newConfig) {
|
|
1548
1375
|
// sequence_updateConfig
|
|
1549
1376
|
const [config, tx] = await this.provider.send('sequence_updateConfig', [newConfig], this.defaultChainId);
|
|
1550
|
-
|
|
1551
1377
|
if (tx === null) {
|
|
1552
1378
|
return [config, undefined];
|
|
1553
1379
|
}
|
|
1554
|
-
|
|
1555
1380
|
const provider = await this.getSender(this.defaultChainId);
|
|
1556
1381
|
return [config, provider._wrapTransaction(tx, tx.hash)];
|
|
1557
|
-
}
|
|
1558
|
-
// NOTE: this is not supported by the remote wallet by default.
|
|
1559
|
-
|
|
1382
|
+
}
|
|
1560
1383
|
|
|
1384
|
+
// publishConfig..
|
|
1385
|
+
// NOTE: this is not supported by the remote wallet by default.
|
|
1561
1386
|
async publishConfig() {
|
|
1562
1387
|
const provider = await this.getSender(this.defaultChainId);
|
|
1563
1388
|
const tx = await provider.send('sequence_publishConfig', []);
|
|
1564
|
-
|
|
1565
1389
|
if (tx === null) {
|
|
1566
1390
|
return undefined;
|
|
1567
1391
|
}
|
|
1568
|
-
|
|
1569
1392
|
return provider._wrapTransaction(tx, tx.hash);
|
|
1570
1393
|
}
|
|
1571
|
-
|
|
1572
1394
|
async isDeployed(chainId) {
|
|
1573
1395
|
const provider = await this.getSender(maybeChainId(chainId));
|
|
1574
1396
|
const walletCode = await provider.getCode(await this.getAddress());
|
|
1575
1397
|
return !!walletCode && walletCode !== '0x';
|
|
1576
|
-
}
|
|
1398
|
+
}
|
|
1399
|
+
|
|
1400
|
+
//
|
|
1577
1401
|
// ethers JsonRpcSigner methods
|
|
1578
1402
|
//
|
|
1579
1403
|
|
|
1580
|
-
|
|
1581
1404
|
async _legacySignMessage(message, chainId, allSigners) {
|
|
1582
1405
|
const provider = await this.getSender(maybeChainId(chainId) || this.defaultChainId);
|
|
1583
1406
|
const data = typeof message === 'string' ? ethers.utils.toUtf8Bytes(message) : message;
|
|
1584
|
-
const address = await this.getAddress();
|
|
1585
|
-
// NOTE: ethers since 5.5 has switched to using personal_sign, we should review, etc.
|
|
1407
|
+
const address = await this.getAddress();
|
|
1586
1408
|
|
|
1409
|
+
// https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_sign
|
|
1410
|
+
// NOTE: ethers since 5.5 has switched to using personal_sign, we should review, etc.
|
|
1587
1411
|
return await provider.send('eth_sign', [address, ethers.utils.hexlify(data)]);
|
|
1588
1412
|
}
|
|
1589
|
-
|
|
1590
1413
|
async _signTypedData(domain, types, message, chainId, allSigners) {
|
|
1591
1414
|
return this.signTypedData(domain, types, message, chainId, allSigners);
|
|
1592
1415
|
}
|
|
1593
|
-
|
|
1594
1416
|
async sendUncheckedTransaction(transaction, chainId) {
|
|
1595
1417
|
transaction = shallowCopy(transaction);
|
|
1596
|
-
const fromAddress = this.getAddress();
|
|
1418
|
+
const fromAddress = this.getAddress();
|
|
1419
|
+
|
|
1420
|
+
// NOTE: we do not use provider estimation, and instead rely on our relayer to determine the gasLimit and gasPrice
|
|
1597
1421
|
//
|
|
1598
1422
|
// TODO: alternatively/one day, we could write a provider middleware to eth_estimateGas
|
|
1599
1423
|
// and send it to our relayer url instead for estimation..
|
|
@@ -1620,7 +1444,6 @@ class Web3Signer extends Signer {
|
|
|
1620
1444
|
} else {
|
|
1621
1445
|
tx.from = sender;
|
|
1622
1446
|
}
|
|
1623
|
-
|
|
1624
1447
|
const hexTx = hexlifyTransaction(tx);
|
|
1625
1448
|
return provider.send('eth_sendTransaction', [hexTx]).then(hash => {
|
|
1626
1449
|
return hash;
|
|
@@ -1630,17 +1453,16 @@ class Web3Signer extends Signer {
|
|
|
1630
1453
|
});
|
|
1631
1454
|
});
|
|
1632
1455
|
}
|
|
1633
|
-
|
|
1634
1456
|
connectUnchecked() {
|
|
1635
1457
|
throw new Error('connectUnchecked is unsupported');
|
|
1636
1458
|
}
|
|
1637
|
-
|
|
1638
1459
|
async unlock(password) {
|
|
1639
1460
|
const address = await this.getAddress();
|
|
1640
1461
|
return this.provider.send('personal_unlockAccount', [address, password, null]);
|
|
1641
1462
|
}
|
|
1463
|
+
}
|
|
1642
1464
|
|
|
1643
|
-
|
|
1465
|
+
// NOTE: method has been copied + modified from ethers.js JsonRpcProvider
|
|
1644
1466
|
// Convert an ethers.js transaction into a JSON-RPC transaction
|
|
1645
1467
|
|
|
1646
1468
|
const allowedTransactionKeys = {
|
|
@@ -1658,11 +1480,9 @@ const allowedTransactionKeys = {
|
|
|
1658
1480
|
delegateCall: true,
|
|
1659
1481
|
revertOnError: true
|
|
1660
1482
|
};
|
|
1661
|
-
|
|
1662
1483
|
const hexlifyTransaction = (transaction, allowExtra) => {
|
|
1663
1484
|
// Check only allowed properties are given
|
|
1664
1485
|
const allowed = shallowCopy(allowedTransactionKeys);
|
|
1665
|
-
|
|
1666
1486
|
if (allowExtra) {
|
|
1667
1487
|
for (const key in allowExtra) {
|
|
1668
1488
|
if (allowExtra[key]) {
|
|
@@ -1670,59 +1490,54 @@ const hexlifyTransaction = (transaction, allowExtra) => {
|
|
|
1670
1490
|
}
|
|
1671
1491
|
}
|
|
1672
1492
|
}
|
|
1673
|
-
|
|
1674
1493
|
ethers.utils.checkProperties(transaction, allowed);
|
|
1675
|
-
const result = {}
|
|
1494
|
+
const result = {}
|
|
1495
|
+
|
|
1496
|
+
// Some nodes (INFURA ropsten; INFURA mainnet is fine) do not like leading zeros.
|
|
1676
1497
|
;
|
|
1677
1498
|
['gasLimit', 'gasPrice', 'nonce', 'value'].forEach(key => {
|
|
1678
1499
|
const value = transaction[key];
|
|
1679
|
-
|
|
1680
1500
|
if (value === null || value === undefined) {
|
|
1681
1501
|
return;
|
|
1682
1502
|
}
|
|
1683
|
-
|
|
1684
1503
|
const hexValue = ethers.utils.hexValue(value);
|
|
1685
|
-
|
|
1686
1504
|
if (key === 'gasLimit') {
|
|
1687
1505
|
key = 'gas';
|
|
1688
1506
|
}
|
|
1689
|
-
|
|
1690
1507
|
result[key] = hexValue;
|
|
1691
1508
|
});
|
|
1692
1509
|
['from', 'to', 'data'].forEach(key => {
|
|
1693
1510
|
if (!transaction[key]) {
|
|
1694
1511
|
return;
|
|
1695
1512
|
}
|
|
1696
|
-
|
|
1697
1513
|
result[key] = ethers.utils.hexlify(transaction[key]);
|
|
1698
1514
|
});
|
|
1699
1515
|
['delegateCall', 'revertOnError'].forEach(key => {
|
|
1700
1516
|
const value = transaction[key];
|
|
1701
|
-
|
|
1702
1517
|
if (value !== undefined && value !== null) {
|
|
1703
1518
|
result[key] = value;
|
|
1704
1519
|
}
|
|
1705
1520
|
});
|
|
1706
1521
|
const auxiliary = transaction['auxiliary'];
|
|
1707
|
-
|
|
1708
1522
|
if (auxiliary && auxiliary.length > 0) {
|
|
1709
1523
|
result['auxiliary'] = [];
|
|
1710
1524
|
auxiliary.forEach(a => {
|
|
1711
1525
|
result['auxiliary'].push(hexlifyTransaction(a));
|
|
1712
1526
|
});
|
|
1713
1527
|
}
|
|
1714
|
-
|
|
1715
1528
|
return result;
|
|
1716
1529
|
};
|
|
1717
1530
|
|
|
1718
1531
|
function messageIsExemptFromEIP191Prefix(message) {
|
|
1719
1532
|
return EIP_191_PREFIX_EXCEPTIONS.some(e => e.predicate(message));
|
|
1720
1533
|
}
|
|
1721
|
-
const EIP_191_PREFIX_EXCEPTIONS = [
|
|
1534
|
+
const EIP_191_PREFIX_EXCEPTIONS = [
|
|
1535
|
+
// NOTE: Decentraland does not support 191 correctly.
|
|
1722
1536
|
{
|
|
1723
1537
|
name: 'Decentraland Exception',
|
|
1724
1538
|
predicate: isDecentralandLoginMessage
|
|
1725
|
-
},
|
|
1539
|
+
},
|
|
1540
|
+
// NOTE: 0x v3 does not support 191 correctly.
|
|
1726
1541
|
// See https://gov.0x.org/t/zeip-proposal-fix-v3-eip-191-non-compliance-when-validating-eip-1271-signatures/3396 for more info.
|
|
1727
1542
|
{
|
|
1728
1543
|
name: '0x v3 Exception',
|
|
@@ -1736,12 +1551,12 @@ function isDecentralandLoginMessage(bytes) {
|
|
|
1736
1551
|
} catch (_unused) {
|
|
1737
1552
|
return false;
|
|
1738
1553
|
}
|
|
1739
|
-
}
|
|
1740
|
-
// see https://github.com/0xProject/0x-protocol-specification/blob/master/v3/v3-specification.md
|
|
1554
|
+
}
|
|
1741
1555
|
|
|
1556
|
+
// try to interpret bytes as abi-encoded 0x v3 OrderWithHash -
|
|
1557
|
+
// see https://github.com/0xProject/0x-protocol-specification/blob/master/v3/v3-specification.md
|
|
1742
1558
|
function isZeroExV3Order(bytes) {
|
|
1743
1559
|
const abi = new ethers.utils.Interface(ZeroXV3EIP1271OrderWithHashAbi);
|
|
1744
|
-
|
|
1745
1560
|
try {
|
|
1746
1561
|
abi.decodeFunctionData('OrderWithHash', bytes);
|
|
1747
1562
|
return true;
|
|
@@ -1828,12 +1643,10 @@ const messageToBytes = message => {
|
|
|
1828
1643
|
if (ethers.utils.isBytes(message) || ethers.utils.isHexString(message)) {
|
|
1829
1644
|
return ethers.utils.arrayify(message);
|
|
1830
1645
|
}
|
|
1831
|
-
|
|
1832
1646
|
return ethers.utils.toUtf8Bytes(message);
|
|
1833
1647
|
};
|
|
1834
1648
|
const prefixEIP191Message = message => {
|
|
1835
1649
|
const messageBytes = messageToBytes(message);
|
|
1836
|
-
|
|
1837
1650
|
if (messageIsExemptFromEIP191Prefix(messageBytes)) {
|
|
1838
1651
|
return messageBytes;
|
|
1839
1652
|
} else {
|
|
@@ -1843,14 +1656,11 @@ const prefixEIP191Message = message => {
|
|
|
1843
1656
|
const isValidSignature = async (address, digest, sig, provider, chainId, walletContext) => {
|
|
1844
1657
|
if (!chainId) {
|
|
1845
1658
|
var _await$provider$getNe;
|
|
1846
|
-
|
|
1847
1659
|
chainId = (_await$provider$getNe = await provider.getNetwork()) == null ? void 0 : _await$provider$getNe.chainId;
|
|
1848
1660
|
}
|
|
1849
|
-
|
|
1850
1661
|
if (!walletContext && Web3Provider.isSequenceProvider(provider)) {
|
|
1851
1662
|
walletContext = await provider.getSigner().getWalletContext();
|
|
1852
1663
|
}
|
|
1853
|
-
|
|
1854
1664
|
return isValidSignature$1(address, digest, sig, provider, walletContext, chainId);
|
|
1855
1665
|
};
|
|
1856
1666
|
const isValidMessageSignature = async (address, message, signature, provider, chainId, walletContext) => {
|
|
@@ -1864,21 +1674,19 @@ const isValidTypedDataSignature = (address, typedData, signature, provider, chai
|
|
|
1864
1674
|
const recoverWalletConfig = async (address, digest, signature, chainId, walletContext) => {
|
|
1865
1675
|
const subDigest = packMessageData(address, chainId, digest);
|
|
1866
1676
|
const config = await recoverConfig(subDigest, signature);
|
|
1867
|
-
|
|
1868
1677
|
if (walletContext) {
|
|
1869
1678
|
const recoveredWalletAddress = addressOf(config, walletContext);
|
|
1870
|
-
|
|
1871
1679
|
if (config.address && config.address !== recoveredWalletAddress) {
|
|
1872
1680
|
throw new Error('recovered address does not match the WalletConfig address, check the WalletContext');
|
|
1873
1681
|
} else {
|
|
1874
1682
|
config.address = recoveredWalletAddress;
|
|
1875
1683
|
}
|
|
1876
1684
|
}
|
|
1877
|
-
|
|
1878
1685
|
return config;
|
|
1879
1686
|
};
|
|
1880
1687
|
const isBrowserExtension = () => window.location.protocol === 'chrome-extension:' || window.location.protocol === 'moz-extension:';
|
|
1881
1688
|
const isUnityPlugin = () => !!navigator.userAgent.match(/UnitySequence/i);
|
|
1689
|
+
|
|
1882
1690
|
/**
|
|
1883
1691
|
* Returns the status of a signer's wallet on given chain by checking wallet deployment and config status
|
|
1884
1692
|
*
|
|
@@ -1886,49 +1694,36 @@ const isUnityPlugin = () => !!navigator.userAgent.match(/UnitySequence/i);
|
|
|
1886
1694
|
* @param {number} chainId
|
|
1887
1695
|
* @return {Promise<boolean>} Promise that returns true if the wallet is up to date, false otherwise
|
|
1888
1696
|
*/
|
|
1889
|
-
|
|
1890
1697
|
const isWalletUpToDate = async (signer, chainId) => {
|
|
1891
1698
|
var _walletState$find;
|
|
1892
|
-
|
|
1893
1699
|
const walletState = await signer.getWalletState();
|
|
1894
1700
|
const networks = await signer.getNetworks();
|
|
1895
1701
|
const walletStateForRequiredChain = walletState.find(state => state.chainId === chainId);
|
|
1896
|
-
|
|
1897
1702
|
if (!walletStateForRequiredChain) {
|
|
1898
1703
|
throw new Error(`WalletRequestHandler: could not find wallet state for chainId ${chainId}`);
|
|
1899
1704
|
}
|
|
1900
|
-
|
|
1901
1705
|
const isDeployed = walletStateForRequiredChain.deployed;
|
|
1902
|
-
|
|
1903
1706
|
if (!networks) {
|
|
1904
1707
|
throw new Error(`isWalletUpToDate util: could not get networks from signer`);
|
|
1905
1708
|
}
|
|
1906
|
-
|
|
1907
1709
|
const authChain = networks.find(network => network.isAuthChain);
|
|
1908
|
-
|
|
1909
1710
|
if (!authChain) {
|
|
1910
1711
|
throw new Error(`isWalletUpToDate util: could not get auth chain network information`);
|
|
1911
1712
|
}
|
|
1912
|
-
|
|
1913
1713
|
const authChainId = authChain.chainId;
|
|
1914
1714
|
const authChainConfig = (_walletState$find = walletState.find(state => state.chainId === authChainId)) == null ? void 0 : _walletState$find.config;
|
|
1915
|
-
|
|
1916
1715
|
if (!authChainConfig) {
|
|
1917
1716
|
throw new Error(`isWalletUpToDate util: could not get auth chain config`);
|
|
1918
1717
|
}
|
|
1919
|
-
|
|
1920
1718
|
const requiredChainConfig = walletStateForRequiredChain.config;
|
|
1921
|
-
|
|
1922
1719
|
if (!requiredChainConfig) {
|
|
1923
1720
|
throw new Error(`isWalletUpToDate util: could not get config for chainId ${chainId}`);
|
|
1924
1721
|
}
|
|
1925
|
-
|
|
1926
1722
|
const isUpToDate = isConfigEqual(authChainConfig, requiredChainConfig);
|
|
1927
1723
|
return isDeployed && isUpToDate;
|
|
1928
1724
|
};
|
|
1929
1725
|
class LocalStorage {
|
|
1930
1726
|
constructor() {}
|
|
1931
|
-
|
|
1932
1727
|
static getInstance() {
|
|
1933
1728
|
if (!LocalStorage._instance) {
|
|
1934
1729
|
LocalStorage._instance = {
|
|
@@ -1937,16 +1732,14 @@ class LocalStorage {
|
|
|
1937
1732
|
removeItem: key => Promise.resolve(window.localStorage.removeItem(key))
|
|
1938
1733
|
};
|
|
1939
1734
|
}
|
|
1940
|
-
|
|
1941
1735
|
return this._instance;
|
|
1942
1736
|
}
|
|
1943
|
-
|
|
1944
1737
|
static use(instance) {
|
|
1945
1738
|
LocalStorage._instance = instance;
|
|
1946
1739
|
}
|
|
1740
|
+
}
|
|
1947
1741
|
|
|
1948
|
-
|
|
1949
|
-
|
|
1742
|
+
// window.localstorage helper
|
|
1950
1743
|
LocalStorage._instance = void 0;
|
|
1951
1744
|
class LocalStore {
|
|
1952
1745
|
constructor(key, def) {
|
|
@@ -1954,31 +1747,24 @@ class LocalStore {
|
|
|
1954
1747
|
this.key = void 0;
|
|
1955
1748
|
this.key = key;
|
|
1956
1749
|
}
|
|
1957
|
-
|
|
1958
1750
|
async get() {
|
|
1959
1751
|
const val = await LocalStorage.getInstance().getItem(this.key);
|
|
1960
|
-
|
|
1961
1752
|
if (val === null) {
|
|
1962
1753
|
return this.def;
|
|
1963
1754
|
}
|
|
1964
|
-
|
|
1965
1755
|
try {
|
|
1966
1756
|
return JSON.parse(val);
|
|
1967
1757
|
} catch (err) {
|
|
1968
1758
|
console.error(err);
|
|
1969
1759
|
}
|
|
1970
|
-
|
|
1971
1760
|
return;
|
|
1972
1761
|
}
|
|
1973
|
-
|
|
1974
1762
|
set(val) {
|
|
1975
1763
|
val ? LocalStorage.getInstance().setItem(this.key, JSON.stringify(val)) : LocalStorage.getInstance().removeItem(this.key);
|
|
1976
1764
|
}
|
|
1977
|
-
|
|
1978
1765
|
del() {
|
|
1979
1766
|
LocalStorage.getInstance().removeItem(this.key);
|
|
1980
1767
|
}
|
|
1981
|
-
|
|
1982
1768
|
}
|
|
1983
1769
|
|
|
1984
1770
|
const TRANSPORT_SESSION_LS_KEY = '@sequence.transportSession';
|
|
@@ -1986,9 +1772,9 @@ class BaseWalletTransport {
|
|
|
1986
1772
|
// appOrigin identifies the dapp's origin which opened the app. A transport
|
|
1987
1773
|
// will auto-detect and set this value if it can. This is determined
|
|
1988
1774
|
// as the parent app/window which opened the wallet.
|
|
1775
|
+
|
|
1989
1776
|
constructor(walletRequestHandler) {
|
|
1990
1777
|
var _this = this;
|
|
1991
|
-
|
|
1992
1778
|
this.walletRequestHandler = void 0;
|
|
1993
1779
|
this._sessionId = void 0;
|
|
1994
1780
|
this._registered = void 0;
|
|
@@ -1996,15 +1782,14 @@ class BaseWalletTransport {
|
|
|
1996
1782
|
this._initNonce = void 0;
|
|
1997
1783
|
this._initCallback = void 0;
|
|
1998
1784
|
this.appOrigin = void 0;
|
|
1999
|
-
|
|
2000
1785
|
this.sendAsync = async function (request, callback, chainId) {
|
|
2001
1786
|
throw new Error('abstract method');
|
|
2002
1787
|
};
|
|
2003
|
-
|
|
2004
1788
|
this.handleMessage = async function (message) {
|
|
2005
|
-
const request = message;
|
|
2006
|
-
// other kinds of messages.
|
|
1789
|
+
const request = message;
|
|
2007
1790
|
|
|
1791
|
+
// ensure initial handshake is complete before accepting
|
|
1792
|
+
// other kinds of messages.
|
|
2008
1793
|
if (_this._init !== InitState.OK) {
|
|
2009
1794
|
if (request.type === EventType.INIT) {
|
|
2010
1795
|
if (_this.isValidInitAck(message)) {
|
|
@@ -2016,15 +1801,15 @@ class BaseWalletTransport {
|
|
|
2016
1801
|
return;
|
|
2017
1802
|
}
|
|
2018
1803
|
}
|
|
2019
|
-
|
|
2020
1804
|
return;
|
|
2021
|
-
}
|
|
1805
|
+
}
|
|
1806
|
+
|
|
1807
|
+
// ensure signer is ready to handle requests
|
|
2022
1808
|
// if (this.walletRequestHandler.getSigner() === undefined) {
|
|
2023
1809
|
// await this.walletRequestHandler.signerReady()
|
|
2024
1810
|
// }
|
|
2025
|
-
// handle request
|
|
2026
|
-
|
|
2027
1811
|
|
|
1812
|
+
// handle request
|
|
2028
1813
|
switch (request.type) {
|
|
2029
1814
|
case EventType.OPEN:
|
|
2030
1815
|
{
|
|
@@ -2037,65 +1822,57 @@ class BaseWalletTransport {
|
|
|
2037
1822
|
await _this.open(session);
|
|
2038
1823
|
return;
|
|
2039
1824
|
}
|
|
2040
|
-
|
|
2041
1825
|
case EventType.CLOSE:
|
|
2042
1826
|
{
|
|
2043
|
-
if (_this._init !== InitState.OK) return;
|
|
2044
|
-
|
|
1827
|
+
if (_this._init !== InitState.OK) return;
|
|
1828
|
+
// noop. just here to capture the message so event emitters may be notified
|
|
2045
1829
|
return;
|
|
2046
1830
|
}
|
|
2047
|
-
|
|
2048
1831
|
case EventType.MESSAGE:
|
|
2049
1832
|
{
|
|
2050
1833
|
const response = await _this.walletRequestHandler.sendMessageRequest(request);
|
|
2051
|
-
|
|
2052
1834
|
_this.sendMessage(response);
|
|
2053
|
-
|
|
2054
1835
|
if (response.data.error) ;
|
|
2055
|
-
|
|
2056
1836
|
return;
|
|
2057
1837
|
}
|
|
2058
|
-
|
|
2059
1838
|
default:
|
|
2060
1839
|
{
|
|
2061
1840
|
logger.error(`unexpected payload type ${request.type}`);
|
|
2062
1841
|
}
|
|
2063
1842
|
}
|
|
2064
1843
|
};
|
|
2065
|
-
|
|
2066
1844
|
this.sendMessageRequest = async function (message) {
|
|
2067
1845
|
return _this.walletRequestHandler.sendMessageRequest(message);
|
|
2068
1846
|
};
|
|
2069
|
-
|
|
2070
1847
|
this.open = async function ({
|
|
2071
1848
|
sessionId,
|
|
2072
1849
|
intent,
|
|
2073
1850
|
networkId
|
|
2074
1851
|
}) {
|
|
2075
1852
|
if (sessionId) {
|
|
2076
|
-
_this._sessionId = sanitizeNumberString(sessionId);
|
|
2077
|
-
|
|
1853
|
+
_this._sessionId = sanitizeNumberString(sessionId);
|
|
1854
|
+
// persist transport session in localstorage for restoring after redirect/reload
|
|
2078
1855
|
_this.saveTransportSession({
|
|
2079
1856
|
sessionId,
|
|
2080
1857
|
intent,
|
|
2081
1858
|
networkId
|
|
2082
1859
|
});
|
|
2083
1860
|
}
|
|
1861
|
+
_this.walletRequestHandler.setOpenIntent(intent);
|
|
2084
1862
|
|
|
2085
|
-
|
|
1863
|
+
// init handshake for certain transports, before we can open the communication.
|
|
2086
1864
|
//
|
|
2087
1865
|
// for example, with the window-transport, we have to exchange messages to determine the
|
|
2088
1866
|
// origin host of the dapp.
|
|
1867
|
+
await _this.init();
|
|
2089
1868
|
|
|
2090
|
-
|
|
2091
|
-
await _this.init(); // Prepare connect options from intent
|
|
2092
|
-
|
|
1869
|
+
// Prepare connect options from intent
|
|
2093
1870
|
if (intent && intent.type === 'connect' && intent.options) {
|
|
2094
1871
|
const connectOptions = intent.options;
|
|
2095
1872
|
const authorizeOptions = connectOptions; // overlapping types
|
|
1873
|
+
|
|
2096
1874
|
// Sanity/integrity check the intent payload, and set authorization origin
|
|
2097
1875
|
// if its been determined as part of the init handshake from earlier.
|
|
2098
|
-
|
|
2099
1876
|
if (_this.appOrigin && authorizeOptions != null && authorizeOptions.origin) {
|
|
2100
1877
|
if (!isBrowserExtension()) {
|
|
2101
1878
|
if (authorizeOptions.origin !== _this.appOrigin) {
|
|
@@ -2110,36 +1887,33 @@ class BaseWalletTransport {
|
|
|
2110
1887
|
// ie. when we auto-determine the origin such as in window-transport
|
|
2111
1888
|
connectOptions.origin = _this.appOrigin;
|
|
2112
1889
|
}
|
|
2113
|
-
|
|
2114
1890
|
if (connectOptions.app) {
|
|
2115
1891
|
connectOptions.app = sanitizeAlphanumeric(connectOptions.app);
|
|
2116
|
-
}
|
|
2117
|
-
// wallet controller
|
|
2118
|
-
|
|
1892
|
+
}
|
|
2119
1893
|
|
|
1894
|
+
// Set connect options on the walletRequestHandler as our primary
|
|
1895
|
+
// wallet controller
|
|
2120
1896
|
_this.walletRequestHandler.setConnectOptions(connectOptions);
|
|
2121
|
-
|
|
2122
1897
|
if (connectOptions.networkId) {
|
|
2123
1898
|
networkId = connectOptions.networkId;
|
|
2124
1899
|
}
|
|
2125
1900
|
} else {
|
|
2126
1901
|
_this.walletRequestHandler.setConnectOptions(undefined);
|
|
2127
|
-
}
|
|
2128
|
-
|
|
1902
|
+
}
|
|
2129
1903
|
|
|
2130
|
-
|
|
1904
|
+
// ensure signer is ready
|
|
1905
|
+
await _this.walletRequestHandler.getSigner();
|
|
2131
1906
|
|
|
1907
|
+
// Notify open and proceed to prompt for connection if intended
|
|
2132
1908
|
if (!(await _this.walletRequestHandler.isSignedIn())) {
|
|
2133
1909
|
// open wallet without a specific connected chainId, as the user is not signed in
|
|
2134
1910
|
_this.notifyOpen({
|
|
2135
1911
|
sessionId: _this._sessionId
|
|
2136
1912
|
});
|
|
2137
|
-
|
|
2138
1913
|
return true;
|
|
2139
1914
|
} else {
|
|
2140
1915
|
// Set default network, in case of error chainId will be undefined or 0
|
|
2141
1916
|
let chainId = undefined;
|
|
2142
|
-
|
|
2143
1917
|
try {
|
|
2144
1918
|
if (networkId) {
|
|
2145
1919
|
chainId = await _this.walletRequestHandler.setDefaultNetwork(networkId, false);
|
|
@@ -2148,30 +1922,28 @@ class BaseWalletTransport {
|
|
|
2148
1922
|
}
|
|
2149
1923
|
} catch (err) {
|
|
2150
1924
|
console.error(err);
|
|
2151
|
-
}
|
|
2152
|
-
|
|
1925
|
+
}
|
|
2153
1926
|
|
|
1927
|
+
// Failed to set default network on open -- quit + close
|
|
2154
1928
|
if (!chainId || chainId <= 0) {
|
|
2155
1929
|
_this.notifyOpen({
|
|
2156
1930
|
sessionId: _this._sessionId,
|
|
2157
1931
|
error: `failed to open wallet on network ${networkId}`
|
|
2158
1932
|
});
|
|
2159
|
-
|
|
2160
1933
|
return false;
|
|
2161
|
-
}
|
|
1934
|
+
}
|
|
1935
|
+
|
|
1936
|
+
// prompt user with a connect request. the options will be used as previously set above.
|
|
2162
1937
|
// upon success, the walletRequestHandler will notify the dapp with the ConnectDetails.
|
|
2163
1938
|
// upon cancellation by user, the walletRequestHandler will throw an error
|
|
2164
1939
|
|
|
2165
|
-
|
|
2166
1940
|
if (intent && intent.type === 'connect') {
|
|
2167
1941
|
// notify wallet is opened, without session details
|
|
2168
1942
|
_this.notifyOpen({
|
|
2169
1943
|
sessionId: _this._sessionId
|
|
2170
1944
|
});
|
|
2171
|
-
|
|
2172
1945
|
try {
|
|
2173
1946
|
const connectDetails = await _this.walletRequestHandler.promptConnect(intent.options);
|
|
2174
|
-
|
|
2175
1947
|
if (connectDetails.connected) {
|
|
2176
1948
|
_this.walletRequestHandler.notifyConnect(connectDetails);
|
|
2177
1949
|
}
|
|
@@ -2194,17 +1966,13 @@ class BaseWalletTransport {
|
|
|
2194
1966
|
});
|
|
2195
1967
|
}
|
|
2196
1968
|
}
|
|
2197
|
-
|
|
2198
1969
|
return true;
|
|
2199
1970
|
};
|
|
2200
|
-
|
|
2201
1971
|
this.saveTransportSession = session => {
|
|
2202
1972
|
LocalStorage.getInstance().setItem(TRANSPORT_SESSION_LS_KEY, JSON.stringify(session));
|
|
2203
1973
|
};
|
|
2204
|
-
|
|
2205
1974
|
this.getCachedTransportSession = async function () {
|
|
2206
1975
|
const session = await LocalStorage.getInstance().getItem(TRANSPORT_SESSION_LS_KEY);
|
|
2207
|
-
|
|
2208
1976
|
try {
|
|
2209
1977
|
return session ? JSON.parse(session) : null;
|
|
2210
1978
|
} catch (err) {
|
|
@@ -2212,17 +1980,16 @@ class BaseWalletTransport {
|
|
|
2212
1980
|
return null;
|
|
2213
1981
|
}
|
|
2214
1982
|
};
|
|
2215
|
-
|
|
2216
1983
|
this.walletRequestHandler = walletRequestHandler;
|
|
2217
1984
|
this._init = InitState.NIL;
|
|
2218
1985
|
this.walletRequestHandler.on('connect', connectDetails => {
|
|
2219
|
-
if (!this.registered) return;
|
|
2220
|
-
|
|
1986
|
+
if (!this.registered) return;
|
|
1987
|
+
// means user has logged in and wallet is connected to the app
|
|
2221
1988
|
this.notifyConnect(connectDetails);
|
|
2222
1989
|
});
|
|
2223
1990
|
this.walletRequestHandler.on('disconnect', error => {
|
|
2224
|
-
if (!this.registered) return;
|
|
2225
|
-
|
|
1991
|
+
if (!this.registered) return;
|
|
1992
|
+
// means user has logged out the app / disconnected wallet from the app
|
|
2226
1993
|
this.notifyDisconnect(error);
|
|
2227
1994
|
});
|
|
2228
1995
|
this.walletRequestHandler.on('accountsChanged', (accounts, origin) => {
|
|
@@ -2232,7 +1999,6 @@ class BaseWalletTransport {
|
|
|
2232
1999
|
this.walletRequestHandler.on('networks', networks => {
|
|
2233
2000
|
if (!this.registered) return;
|
|
2234
2001
|
this.notifyNetworks(networks);
|
|
2235
|
-
|
|
2236
2002
|
if (!networks || networks.length === 0) {
|
|
2237
2003
|
this.notifyChainChanged('0x0');
|
|
2238
2004
|
} else {
|
|
@@ -2248,23 +2014,18 @@ class BaseWalletTransport {
|
|
|
2248
2014
|
this.notifyClose(error);
|
|
2249
2015
|
});
|
|
2250
2016
|
}
|
|
2251
|
-
|
|
2252
2017
|
get registered() {
|
|
2253
2018
|
return this._registered;
|
|
2254
2019
|
}
|
|
2255
|
-
|
|
2256
2020
|
register() {
|
|
2257
2021
|
throw new Error('abstract method');
|
|
2258
2022
|
}
|
|
2259
|
-
|
|
2260
2023
|
unregister() {
|
|
2261
2024
|
throw new Error('abstract method');
|
|
2262
2025
|
}
|
|
2263
|
-
|
|
2264
2026
|
sendMessage(message) {
|
|
2265
2027
|
throw new Error('abstract method');
|
|
2266
2028
|
}
|
|
2267
|
-
|
|
2268
2029
|
notifyOpen(openInfo) {
|
|
2269
2030
|
const {
|
|
2270
2031
|
chainId,
|
|
@@ -2283,7 +2044,6 @@ class BaseWalletTransport {
|
|
|
2283
2044
|
}
|
|
2284
2045
|
});
|
|
2285
2046
|
}
|
|
2286
|
-
|
|
2287
2047
|
notifyClose(error) {
|
|
2288
2048
|
this.sendMessage({
|
|
2289
2049
|
idx: -1,
|
|
@@ -2293,7 +2053,6 @@ class BaseWalletTransport {
|
|
|
2293
2053
|
} : null
|
|
2294
2054
|
});
|
|
2295
2055
|
}
|
|
2296
|
-
|
|
2297
2056
|
notifyConnect(connectDetails) {
|
|
2298
2057
|
this.sendMessage({
|
|
2299
2058
|
idx: -1,
|
|
@@ -2301,7 +2060,6 @@ class BaseWalletTransport {
|
|
|
2301
2060
|
data: connectDetails
|
|
2302
2061
|
});
|
|
2303
2062
|
}
|
|
2304
|
-
|
|
2305
2063
|
notifyDisconnect(error) {
|
|
2306
2064
|
this.sendMessage({
|
|
2307
2065
|
idx: -1,
|
|
@@ -2311,7 +2069,6 @@ class BaseWalletTransport {
|
|
|
2311
2069
|
} : null
|
|
2312
2070
|
});
|
|
2313
2071
|
}
|
|
2314
|
-
|
|
2315
2072
|
notifyAccountsChanged(accounts, origin) {
|
|
2316
2073
|
this.sendMessage({
|
|
2317
2074
|
idx: -1,
|
|
@@ -2320,7 +2077,6 @@ class BaseWalletTransport {
|
|
|
2320
2077
|
origin: origin
|
|
2321
2078
|
});
|
|
2322
2079
|
}
|
|
2323
|
-
|
|
2324
2080
|
notifyChainChanged(chainIdHex) {
|
|
2325
2081
|
this.sendMessage({
|
|
2326
2082
|
idx: -1,
|
|
@@ -2328,7 +2084,6 @@ class BaseWalletTransport {
|
|
|
2328
2084
|
data: chainIdHex
|
|
2329
2085
|
});
|
|
2330
2086
|
}
|
|
2331
|
-
|
|
2332
2087
|
notifyNetworks(networks) {
|
|
2333
2088
|
this.sendMessage({
|
|
2334
2089
|
idx: -1,
|
|
@@ -2336,7 +2091,6 @@ class BaseWalletTransport {
|
|
|
2336
2091
|
data: networks
|
|
2337
2092
|
});
|
|
2338
2093
|
}
|
|
2339
|
-
|
|
2340
2094
|
notifyWalletContext(walletContext) {
|
|
2341
2095
|
this.sendMessage({
|
|
2342
2096
|
idx: -1,
|
|
@@ -2344,38 +2098,32 @@ class BaseWalletTransport {
|
|
|
2344
2098
|
data: walletContext
|
|
2345
2099
|
});
|
|
2346
2100
|
}
|
|
2347
|
-
|
|
2348
2101
|
isValidInitAck(message) {
|
|
2349
2102
|
if (this._init === InitState.OK) {
|
|
2350
2103
|
// we're already in init state, we shouldn't handle this message
|
|
2351
2104
|
logger.warn("isValidInitAck, already in init'd state, so inquiry is invalid.");
|
|
2352
2105
|
return false;
|
|
2353
2106
|
}
|
|
2354
|
-
|
|
2355
2107
|
if (message.type !== EventType.INIT) {
|
|
2356
2108
|
logger.warn('isValidInitAck, invalid message type, expecting init');
|
|
2357
2109
|
return false;
|
|
2358
2110
|
}
|
|
2359
|
-
|
|
2360
2111
|
const {
|
|
2361
2112
|
sessionId,
|
|
2362
2113
|
nonce
|
|
2363
2114
|
} = message.data;
|
|
2364
|
-
|
|
2365
2115
|
if (!sessionId || sessionId.length === 0 || !nonce || nonce.length === 0) {
|
|
2366
2116
|
logger.error('invalid init ack');
|
|
2367
2117
|
return false;
|
|
2368
2118
|
}
|
|
2369
|
-
|
|
2370
2119
|
if (sessionId !== this._sessionId || nonce !== this._initNonce) {
|
|
2371
2120
|
logger.error('invalid init ack match');
|
|
2372
2121
|
return false;
|
|
2373
|
-
}
|
|
2374
|
-
|
|
2122
|
+
}
|
|
2375
2123
|
|
|
2124
|
+
// all checks pass, its true
|
|
2376
2125
|
return true;
|
|
2377
2126
|
}
|
|
2378
|
-
|
|
2379
2127
|
init() {
|
|
2380
2128
|
return new Promise((resolve, reject) => {
|
|
2381
2129
|
// avoid re-init`ing, or if there is a transport which doesn't require
|
|
@@ -2384,37 +2132,34 @@ class BaseWalletTransport {
|
|
|
2384
2132
|
resolve();
|
|
2385
2133
|
return;
|
|
2386
2134
|
}
|
|
2387
|
-
|
|
2388
2135
|
if (this._init !== InitState.NIL || this._initCallback) {
|
|
2389
2136
|
reject('transport init is in progress');
|
|
2390
2137
|
return;
|
|
2391
|
-
}
|
|
2392
|
-
// from provider within this amount of time, then we timeout
|
|
2393
|
-
|
|
2138
|
+
}
|
|
2394
2139
|
|
|
2140
|
+
// start init timeout, if we don't receive confirmation
|
|
2141
|
+
// from provider within this amount of time, then we timeout
|
|
2395
2142
|
const initTimeout = setTimeout(() => {
|
|
2396
2143
|
logger.warn('transport init timed out');
|
|
2397
|
-
|
|
2398
2144
|
if (this._initCallback) {
|
|
2399
2145
|
this._initCallback('transport init timed out');
|
|
2400
2146
|
}
|
|
2401
|
-
}, PROVIDER_OPEN_TIMEOUT / 2);
|
|
2147
|
+
}, PROVIDER_OPEN_TIMEOUT / 2);
|
|
2402
2148
|
|
|
2149
|
+
// setup callback as we receive the init message async in the handleMessage function
|
|
2403
2150
|
this._initCallback = error => {
|
|
2404
2151
|
this._initCallback = undefined; // reset
|
|
2405
|
-
|
|
2406
2152
|
clearTimeout(initTimeout);
|
|
2407
|
-
|
|
2408
2153
|
if (error) {
|
|
2409
2154
|
reject(error);
|
|
2410
2155
|
} else {
|
|
2411
2156
|
this._init = InitState.OK;
|
|
2412
2157
|
resolve();
|
|
2413
2158
|
}
|
|
2414
|
-
};
|
|
2415
|
-
// for the provider to echo it back to us as complete handshake
|
|
2416
|
-
|
|
2159
|
+
};
|
|
2417
2160
|
|
|
2161
|
+
// send init request with random nonce to the provider, where we expect
|
|
2162
|
+
// for the provider to echo it back to us as complete handshake
|
|
2418
2163
|
this._initNonce = `${performance.now()}`;
|
|
2419
2164
|
this.sendMessage({
|
|
2420
2165
|
idx: -1,
|
|
@@ -2423,11 +2168,12 @@ class BaseWalletTransport {
|
|
|
2423
2168
|
nonce: this._initNonce
|
|
2424
2169
|
}
|
|
2425
2170
|
});
|
|
2426
|
-
this._init = InitState.SENT_NONCE;
|
|
2171
|
+
this._init = InitState.SENT_NONCE;
|
|
2172
|
+
|
|
2173
|
+
// NOTE: the promise will resolve in the _initCallback method
|
|
2427
2174
|
// which will be called from either handleMessage or the initTimeout
|
|
2428
2175
|
});
|
|
2429
2176
|
}
|
|
2430
|
-
|
|
2431
2177
|
}
|
|
2432
2178
|
|
|
2433
2179
|
class ProxyMessageChannel {
|
|
@@ -2441,58 +2187,48 @@ class ProxyMessageChannel {
|
|
|
2441
2187
|
this.app = port1;
|
|
2442
2188
|
this.wallet = port2;
|
|
2443
2189
|
}
|
|
2444
|
-
|
|
2445
2190
|
}
|
|
2446
2191
|
class ProxyMessageChannelPort {
|
|
2447
2192
|
constructor() {
|
|
2448
2193
|
this.conn = void 0;
|
|
2449
2194
|
this.events = new EventEmitter2();
|
|
2450
|
-
|
|
2451
2195
|
this.handleMessage = message => {
|
|
2452
2196
|
throw new Error('ProxyMessageChannelPort is not registered');
|
|
2453
2197
|
};
|
|
2454
|
-
|
|
2455
2198
|
this.sendMessage = message => {
|
|
2456
|
-
this.conn.handleMessage(message);
|
|
2199
|
+
this.conn.handleMessage(message);
|
|
2457
2200
|
|
|
2201
|
+
// trigger events
|
|
2458
2202
|
if (message.type === 'open') {
|
|
2459
2203
|
this.events.emit('open', message);
|
|
2460
2204
|
}
|
|
2461
|
-
|
|
2462
2205
|
if (message.type === 'close') {
|
|
2463
2206
|
this.events.emit('close', message);
|
|
2464
2207
|
}
|
|
2465
|
-
|
|
2466
2208
|
if (message.type === 'connect') {
|
|
2467
2209
|
this.events.emit('connect', message);
|
|
2468
2210
|
}
|
|
2469
|
-
|
|
2470
2211
|
if (message.type === 'disconnect') {
|
|
2471
2212
|
this.events.emit('disconnect', message);
|
|
2472
2213
|
}
|
|
2473
2214
|
};
|
|
2474
2215
|
}
|
|
2475
|
-
|
|
2476
2216
|
on(event, fn) {
|
|
2477
2217
|
this.events.on(event, fn);
|
|
2478
2218
|
}
|
|
2479
|
-
|
|
2480
2219
|
once(event, fn) {
|
|
2481
2220
|
this.events.once(event, fn);
|
|
2482
2221
|
}
|
|
2483
|
-
|
|
2484
2222
|
}
|
|
2485
2223
|
|
|
2486
2224
|
class ProxyMessageProvider extends BaseProviderTransport {
|
|
2487
2225
|
constructor(port) {
|
|
2488
2226
|
super();
|
|
2489
2227
|
this.port = void 0;
|
|
2490
|
-
|
|
2491
2228
|
this.register = () => {
|
|
2492
2229
|
this.port.handleMessage = message => {
|
|
2493
2230
|
this.handleMessage(message);
|
|
2494
2231
|
};
|
|
2495
|
-
|
|
2496
2232
|
this.on('open', (...args) => {
|
|
2497
2233
|
this.port.events.emit('open', ...args);
|
|
2498
2234
|
});
|
|
@@ -2507,15 +2243,13 @@ class ProxyMessageProvider extends BaseProviderTransport {
|
|
|
2507
2243
|
});
|
|
2508
2244
|
this._registered = true;
|
|
2509
2245
|
};
|
|
2510
|
-
|
|
2511
2246
|
this.unregister = () => {
|
|
2512
2247
|
this._registered = false;
|
|
2513
2248
|
this.closeWallet();
|
|
2514
|
-
this.events.removeAllListeners();
|
|
2515
|
-
|
|
2249
|
+
this.events.removeAllListeners();
|
|
2250
|
+
// @ts-ignore
|
|
2516
2251
|
this.port.handleMessage = undefined;
|
|
2517
2252
|
};
|
|
2518
|
-
|
|
2519
2253
|
this.openWallet = (path, intent, networkId) => {
|
|
2520
2254
|
if (this.state === OpenState.CLOSED) {
|
|
2521
2255
|
this.state = OpenState.OPENING;
|
|
@@ -2533,19 +2267,16 @@ class ProxyMessageProvider extends BaseProviderTransport {
|
|
|
2533
2267
|
});
|
|
2534
2268
|
}
|
|
2535
2269
|
};
|
|
2536
|
-
|
|
2537
2270
|
this.state = OpenState.CLOSED;
|
|
2538
2271
|
this.port = port;
|
|
2539
|
-
|
|
2540
2272
|
if (!port) {
|
|
2541
2273
|
throw new Error('port argument cannot be empty');
|
|
2542
|
-
}
|
|
2543
|
-
// consider it in completed state.
|
|
2544
|
-
|
|
2274
|
+
}
|
|
2545
2275
|
|
|
2276
|
+
// disable init handshake for proxy-transport, we set it to OK, to
|
|
2277
|
+
// consider it in completed state.
|
|
2546
2278
|
this._init = InitState.OK;
|
|
2547
2279
|
}
|
|
2548
|
-
|
|
2549
2280
|
closeWallet() {
|
|
2550
2281
|
this.sendMessage({
|
|
2551
2282
|
idx: -1,
|
|
@@ -2554,15 +2285,12 @@ class ProxyMessageProvider extends BaseProviderTransport {
|
|
|
2554
2285
|
});
|
|
2555
2286
|
this.close();
|
|
2556
2287
|
}
|
|
2557
|
-
|
|
2558
2288
|
sendMessage(message) {
|
|
2559
2289
|
if (!message.idx) {
|
|
2560
2290
|
throw new Error('message idx is empty');
|
|
2561
2291
|
}
|
|
2562
|
-
|
|
2563
2292
|
this.port.sendMessage(message);
|
|
2564
2293
|
}
|
|
2565
|
-
|
|
2566
2294
|
}
|
|
2567
2295
|
|
|
2568
2296
|
class ProxyMessageHandler extends BaseWalletTransport {
|
|
@@ -2572,66 +2300,59 @@ class ProxyMessageHandler extends BaseWalletTransport {
|
|
|
2572
2300
|
this.port = port;
|
|
2573
2301
|
this._init = InitState.OK;
|
|
2574
2302
|
}
|
|
2575
|
-
|
|
2576
2303
|
register() {
|
|
2577
2304
|
this.port.handleMessage = message => {
|
|
2578
2305
|
this.handleMessage(message);
|
|
2579
2306
|
};
|
|
2580
|
-
|
|
2581
2307
|
this._registered = true;
|
|
2582
|
-
}
|
|
2308
|
+
}
|
|
2309
|
+
|
|
2310
|
+
// note: we can't decide whether to restore the session within register(), because session info is
|
|
2583
2311
|
// received asyncronously via EventType.OPEN after register() is executed.
|
|
2584
2312
|
// And in the case of a redirect/reload, EventType.OPEN is not sent at all,
|
|
2585
2313
|
// because the wallet is already open.
|
|
2586
2314
|
//
|
|
2587
2315
|
// call this method from wallet redirect hander when a session restore is needed
|
|
2588
|
-
|
|
2589
|
-
|
|
2590
2316
|
async restoreSession() {
|
|
2591
2317
|
const cachedSession = await this.getCachedTransportSession();
|
|
2592
|
-
|
|
2593
2318
|
if (cachedSession) {
|
|
2594
2319
|
this.open(cachedSession);
|
|
2595
2320
|
}
|
|
2596
2321
|
}
|
|
2597
|
-
|
|
2598
2322
|
unregister() {
|
|
2599
2323
|
// @ts-ignore
|
|
2600
2324
|
this.port.handleMessage = undefined;
|
|
2601
2325
|
this._registered = false;
|
|
2602
2326
|
}
|
|
2603
|
-
|
|
2604
2327
|
sendMessage(message) {
|
|
2605
2328
|
this.port.sendMessage(message);
|
|
2606
2329
|
}
|
|
2607
|
-
|
|
2608
2330
|
}
|
|
2609
2331
|
|
|
2610
2332
|
class MuxMessageProvider {
|
|
2611
2333
|
constructor(...messageProviders) {
|
|
2612
2334
|
var _this = this;
|
|
2613
|
-
|
|
2614
2335
|
this.messageProviders = void 0;
|
|
2615
2336
|
this.provider = void 0;
|
|
2616
|
-
|
|
2617
2337
|
this.register = () => {
|
|
2618
2338
|
if (this.messageProviders.length === 1) {
|
|
2619
2339
|
this.provider = this.messageProviders[0];
|
|
2620
2340
|
this.provider.register();
|
|
2621
2341
|
return;
|
|
2622
|
-
}
|
|
2342
|
+
}
|
|
2343
|
+
|
|
2344
|
+
// REVIEW/NOTE: ........ this method does not work for the chrome-extension. The issue becomes
|
|
2623
2345
|
// when the browser quits or restarts, the "open" event is never triggered. Perhaps the code here is fine,
|
|
2624
2346
|
// or maybe its not. What should happen is when a dapp makes a request, it will call openWallet
|
|
2625
2347
|
// below, in which case one of the events will register. So perhaps this is fine.
|
|
2626
|
-
|
|
2627
|
-
|
|
2628
2348
|
this.messageProviders.forEach(m => {
|
|
2629
2349
|
m.register();
|
|
2630
2350
|
m.once('open', () => {
|
|
2631
2351
|
// the first one to open is the winner, and others will be unregistered
|
|
2632
2352
|
if (!this.provider) {
|
|
2633
|
-
this.provider = m;
|
|
2353
|
+
this.provider = m;
|
|
2634
2354
|
|
|
2355
|
+
// unregister other providers
|
|
2635
2356
|
this.messageProviders.forEach(m => {
|
|
2636
2357
|
if (this.provider !== m) {
|
|
2637
2358
|
m.unregister();
|
|
@@ -2641,160 +2362,130 @@ class MuxMessageProvider {
|
|
|
2641
2362
|
});
|
|
2642
2363
|
});
|
|
2643
2364
|
};
|
|
2644
|
-
|
|
2645
2365
|
this.unregister = () => {
|
|
2646
2366
|
this.messageProviders.forEach(m => m.unregister());
|
|
2647
2367
|
this.provider = undefined;
|
|
2648
2368
|
};
|
|
2649
|
-
|
|
2650
2369
|
this.openWallet = (path, intent, networkId) => {
|
|
2651
2370
|
if (this.provider) {
|
|
2652
2371
|
this.provider.openWallet(path, intent, networkId);
|
|
2653
2372
|
return;
|
|
2654
2373
|
}
|
|
2655
|
-
|
|
2656
2374
|
this.messageProviders.forEach(m => m.openWallet(path, intent, networkId));
|
|
2657
2375
|
};
|
|
2658
|
-
|
|
2659
2376
|
this.sendAsync = async function (request, callback, chainId) {
|
|
2660
2377
|
if (_this.provider) {
|
|
2661
2378
|
_this.provider.sendAsync(request, callback, chainId);
|
|
2662
|
-
|
|
2663
2379
|
return;
|
|
2664
2380
|
}
|
|
2665
|
-
|
|
2666
2381
|
throw new Error('impossible state, wallet must be opened first');
|
|
2667
2382
|
};
|
|
2668
|
-
|
|
2669
2383
|
this.sendMessageRequest = async function (message) {
|
|
2670
2384
|
if (_this.provider) {
|
|
2671
2385
|
return _this.provider.sendMessageRequest(message);
|
|
2672
2386
|
}
|
|
2673
|
-
|
|
2674
2387
|
throw new Error('impossible state, wallet must be opened first');
|
|
2675
2388
|
};
|
|
2676
|
-
|
|
2677
2389
|
this.waitUntilOpened = async function () {
|
|
2678
2390
|
if (_this.provider) {
|
|
2679
2391
|
return _this.provider.waitUntilOpened();
|
|
2680
2392
|
}
|
|
2681
|
-
|
|
2682
2393
|
return Promise.race(_this.messageProviders.map(p => p.waitUntilOpened()));
|
|
2683
2394
|
};
|
|
2684
|
-
|
|
2685
2395
|
this.waitUntilConnected = async function () {
|
|
2686
2396
|
if (_this.provider) {
|
|
2687
2397
|
return _this.provider.waitUntilConnected();
|
|
2688
2398
|
}
|
|
2689
|
-
|
|
2690
2399
|
throw new Error('impossible state, wallet must be opened first');
|
|
2691
2400
|
};
|
|
2692
|
-
|
|
2693
2401
|
this.messageProviders = messageProviders;
|
|
2694
2402
|
this.provider = undefined;
|
|
2695
2403
|
}
|
|
2696
|
-
|
|
2697
2404
|
add(...messageProviders) {
|
|
2698
2405
|
this.messageProviders.push(...messageProviders);
|
|
2699
2406
|
}
|
|
2700
|
-
|
|
2701
2407
|
closeWallet() {
|
|
2702
2408
|
if (this.provider) {
|
|
2703
2409
|
this.provider.closeWallet();
|
|
2704
2410
|
}
|
|
2705
2411
|
}
|
|
2706
|
-
|
|
2707
2412
|
isOpened() {
|
|
2708
2413
|
if (this.provider) {
|
|
2709
2414
|
return this.provider.isOpened();
|
|
2710
2415
|
}
|
|
2711
|
-
|
|
2712
2416
|
return false;
|
|
2713
2417
|
}
|
|
2714
|
-
|
|
2715
2418
|
isConnected() {
|
|
2716
2419
|
if (this.provider) {
|
|
2717
2420
|
return this.provider.isConnected();
|
|
2718
2421
|
}
|
|
2719
|
-
|
|
2720
2422
|
return false;
|
|
2721
2423
|
}
|
|
2722
|
-
|
|
2723
2424
|
on(event, fn) {
|
|
2724
2425
|
if (this.provider) {
|
|
2725
2426
|
this.provider.on(event, fn);
|
|
2726
2427
|
return;
|
|
2727
2428
|
}
|
|
2728
|
-
|
|
2729
2429
|
this.messageProviders.forEach(m => {
|
|
2730
2430
|
m.on(event, fn);
|
|
2731
2431
|
});
|
|
2732
2432
|
}
|
|
2733
|
-
|
|
2734
2433
|
once(event, fn) {
|
|
2735
2434
|
if (this.provider) {
|
|
2736
2435
|
this.provider.once(event, fn);
|
|
2737
2436
|
return;
|
|
2738
2437
|
}
|
|
2739
|
-
|
|
2740
2438
|
this.messageProviders.forEach(m => {
|
|
2741
2439
|
m.once(event, fn);
|
|
2742
2440
|
});
|
|
2743
2441
|
}
|
|
2744
|
-
|
|
2745
2442
|
emit(event, ...args) {
|
|
2746
2443
|
if (this.provider) {
|
|
2747
2444
|
return this.provider.emit(event, ...args);
|
|
2748
2445
|
}
|
|
2749
|
-
|
|
2750
2446
|
for (let i = 0; i < this.messageProviders.length; i++) {
|
|
2751
2447
|
this.messageProviders[i].emit(event, ...args);
|
|
2752
2448
|
}
|
|
2753
|
-
|
|
2754
2449
|
return true;
|
|
2755
2450
|
}
|
|
2756
|
-
|
|
2757
2451
|
sendMessage(message) {
|
|
2758
2452
|
if (!message.idx || message.idx <= 0) {
|
|
2759
2453
|
throw new Error('message idx is empty');
|
|
2760
2454
|
}
|
|
2761
|
-
|
|
2762
2455
|
if (this.provider) {
|
|
2763
2456
|
this.provider.sendMessage(message);
|
|
2764
2457
|
} else {
|
|
2765
2458
|
throw new Error('impossible state, wallet must be opened first');
|
|
2766
2459
|
}
|
|
2767
2460
|
}
|
|
2768
|
-
|
|
2769
2461
|
handleMessage(message) {
|
|
2770
2462
|
if (this.provider) {
|
|
2771
2463
|
this.provider.handleMessage(message);
|
|
2772
2464
|
return;
|
|
2773
2465
|
}
|
|
2774
|
-
|
|
2775
2466
|
throw new Error('impossible state, wallet must be opened first');
|
|
2776
2467
|
}
|
|
2777
|
-
|
|
2778
2468
|
}
|
|
2779
2469
|
|
|
2470
|
+
// ..
|
|
2780
2471
|
let registeredWindowMessageProvider;
|
|
2781
2472
|
class WindowMessageProvider extends BaseProviderTransport {
|
|
2782
2473
|
constructor(walletAppURL) {
|
|
2783
2474
|
super();
|
|
2784
2475
|
this.walletURL = void 0;
|
|
2785
2476
|
this.walletWindow = void 0;
|
|
2786
|
-
|
|
2787
2477
|
this.register = () => {
|
|
2788
2478
|
if (registeredWindowMessageProvider) {
|
|
2789
2479
|
// overriding the registered message provider
|
|
2790
2480
|
registeredWindowMessageProvider.unregister();
|
|
2791
2481
|
registeredWindowMessageProvider = this;
|
|
2792
|
-
}
|
|
2793
|
-
|
|
2482
|
+
}
|
|
2794
2483
|
|
|
2484
|
+
// listen for incoming messages from wallet
|
|
2795
2485
|
window.addEventListener('message', this.onWindowEvent);
|
|
2796
|
-
registeredWindowMessageProvider = this;
|
|
2486
|
+
registeredWindowMessageProvider = this;
|
|
2797
2487
|
|
|
2488
|
+
// open heartbeat
|
|
2798
2489
|
this.on('open', () => {
|
|
2799
2490
|
// Heartbeat to track if window closed
|
|
2800
2491
|
const popup = this.walletWindow;
|
|
@@ -2804,8 +2495,9 @@ class WindowMessageProvider extends BaseProviderTransport {
|
|
|
2804
2495
|
this.close();
|
|
2805
2496
|
}
|
|
2806
2497
|
}, 500);
|
|
2807
|
-
});
|
|
2498
|
+
});
|
|
2808
2499
|
|
|
2500
|
+
// close clean up
|
|
2809
2501
|
this.on('close', () => {
|
|
2810
2502
|
if (this.walletWindow) {
|
|
2811
2503
|
this.walletWindow.close();
|
|
@@ -2814,65 +2506,60 @@ class WindowMessageProvider extends BaseProviderTransport {
|
|
|
2814
2506
|
});
|
|
2815
2507
|
this._registered = true;
|
|
2816
2508
|
};
|
|
2817
|
-
|
|
2818
2509
|
this.unregister = () => {
|
|
2819
2510
|
this._registered = false;
|
|
2820
|
-
this.closeWallet();
|
|
2511
|
+
this.closeWallet();
|
|
2821
2512
|
|
|
2513
|
+
// disable message listener
|
|
2822
2514
|
if (registeredWindowMessageProvider === this) {
|
|
2823
2515
|
registeredWindowMessageProvider = undefined;
|
|
2824
2516
|
}
|
|
2517
|
+
window.removeEventListener('message', this.onWindowEvent);
|
|
2825
2518
|
|
|
2826
|
-
|
|
2827
|
-
|
|
2519
|
+
// clear event listeners
|
|
2828
2520
|
this.events.removeAllListeners();
|
|
2829
2521
|
};
|
|
2830
|
-
|
|
2831
2522
|
this.openWallet = (path, intent, networkId) => {
|
|
2832
2523
|
if (this.walletWindow && this.isOpened()) {
|
|
2833
2524
|
// TODO: update the location of window to path
|
|
2834
2525
|
this.walletWindow.focus();
|
|
2835
2526
|
return;
|
|
2836
|
-
}
|
|
2837
|
-
|
|
2527
|
+
}
|
|
2838
2528
|
|
|
2529
|
+
// Instantiate new walletURL for this call
|
|
2839
2530
|
const walletURL = new URL(this.walletURL.href);
|
|
2840
2531
|
const windowSessionParams = new WindowSessionParams();
|
|
2841
|
-
|
|
2842
2532
|
if (path && path !== '') {
|
|
2843
2533
|
walletURL.pathname = path.toLowerCase();
|
|
2844
|
-
}
|
|
2845
|
-
|
|
2534
|
+
}
|
|
2846
2535
|
|
|
2536
|
+
// Set session, intent and network id on walletURL
|
|
2847
2537
|
this._init = InitState.NIL;
|
|
2848
2538
|
this._sessionId = `${performance.now()}`;
|
|
2849
2539
|
windowSessionParams.set('sid', this._sessionId);
|
|
2850
|
-
|
|
2851
2540
|
if (intent) {
|
|
2852
2541
|
// for the window-transport, we eagerly/optimistically set the origin host
|
|
2853
2542
|
// when connecting to the wallet, however, this will be verified and enforced
|
|
2854
2543
|
// on the wallet-side, so if a dapp provides the wrong origin, it will be dropped.
|
|
2855
2544
|
if (intent.type === 'connect') {
|
|
2856
|
-
if (!intent.options) intent.options = {};
|
|
2857
|
-
// allow origin that is passed in
|
|
2545
|
+
if (!intent.options) intent.options = {};
|
|
2858
2546
|
|
|
2547
|
+
// skip setting origin host if we're in an browser extension execution context
|
|
2548
|
+
// allow origin that is passed in
|
|
2859
2549
|
if (!isBrowserExtension() && !isUnityPlugin()) {
|
|
2860
2550
|
intent.options.origin = window.location.origin;
|
|
2861
2551
|
}
|
|
2862
|
-
}
|
|
2863
|
-
|
|
2864
|
-
|
|
2552
|
+
}
|
|
2553
|
+
// encode intent as base64 url-encoded param
|
|
2865
2554
|
windowSessionParams.set('intent', base64EncodeObject(intent));
|
|
2866
2555
|
}
|
|
2867
|
-
|
|
2868
2556
|
if (networkId) {
|
|
2869
2557
|
windowSessionParams.set('net', `${networkId}`);
|
|
2870
|
-
}
|
|
2871
|
-
|
|
2558
|
+
}
|
|
2872
2559
|
|
|
2560
|
+
// Open popup window on center of the app window
|
|
2873
2561
|
let windowSize;
|
|
2874
2562
|
let windowPos;
|
|
2875
|
-
|
|
2876
2563
|
if (isBrowserExtension()) {
|
|
2877
2564
|
windowSize = [450, 750];
|
|
2878
2565
|
windowPos = [Math.abs(window.screen.width / 2 - windowSize[0] / 2), Math.abs(window.screen.height / 2 - windowSize[1] / 2)];
|
|
@@ -2880,12 +2567,15 @@ class WindowMessageProvider extends BaseProviderTransport {
|
|
|
2880
2567
|
windowSize = [450, 750];
|
|
2881
2568
|
windowPos = [Math.abs(window.screenX + window.innerWidth / 2 - windowSize[0] / 2), Math.abs(window.screenY + window.innerHeight / 2 - windowSize[1] / 2)];
|
|
2882
2569
|
}
|
|
2570
|
+
const windowFeatures = `toolbar=0,location=0,menubar=0,scrollbars=yes,status=yes` + `,width=${windowSize[0]},height=${windowSize[1]}` + `,left=${windowPos[0]},top=${windowPos[1]}`;
|
|
2883
2571
|
|
|
2884
|
-
|
|
2885
|
-
|
|
2572
|
+
// serialize params
|
|
2886
2573
|
walletURL.search = windowSessionParams.toString();
|
|
2887
|
-
this.walletWindow = window.open(walletURL.href, 'sequence.app', windowFeatures);
|
|
2574
|
+
this.walletWindow = window.open(walletURL.href, 'sequence.app', windowFeatures);
|
|
2575
|
+
|
|
2576
|
+
// TODO: move this somewhere else
|
|
2888
2577
|
// TODO: perhaps we trigger a .on('openTimeout') event..? maybe.. could help.
|
|
2578
|
+
|
|
2889
2579
|
// Popup blocking detection and notice
|
|
2890
2580
|
// let warned = false
|
|
2891
2581
|
// const warnPopupBlocked = () => {
|
|
@@ -2894,112 +2584,100 @@ class WindowMessageProvider extends BaseProviderTransport {
|
|
|
2894
2584
|
// // alert('popup is blocked! hey yo') // NOTE: for debug purposes only
|
|
2895
2585
|
// throw new Error('popup is blocked')
|
|
2896
2586
|
// }
|
|
2587
|
+
|
|
2897
2588
|
// const popupCheck = setTimeout(() => {
|
|
2898
2589
|
// if (!popup || popup.closed || typeof popup.closed === 'undefined') {
|
|
2899
2590
|
// // popup is definitely blocked if we reach here.
|
|
2900
2591
|
// warnPopupBlocked()
|
|
2901
2592
|
// }
|
|
2902
2593
|
// }, 1000)
|
|
2594
|
+
|
|
2903
2595
|
// const popupBlocked = popup === null || popup === undefined
|
|
2904
2596
|
// if (popupBlocked) {
|
|
2905
2597
|
// warnPopupBlocked()
|
|
2906
2598
|
// return
|
|
2907
2599
|
// }
|
|
2908
2600
|
};
|
|
2909
|
-
|
|
2910
2601
|
this.onWindowEvent = event => {
|
|
2911
2602
|
// Security check, ensure message is coming from wallet origin url
|
|
2912
2603
|
if (event.origin !== this.walletURL.origin) {
|
|
2913
2604
|
// Safetly can skip events not from the wallet
|
|
2914
2605
|
return;
|
|
2915
2606
|
}
|
|
2916
|
-
|
|
2917
2607
|
let message;
|
|
2918
|
-
|
|
2919
2608
|
try {
|
|
2920
2609
|
message = JSON.parse(event.data);
|
|
2921
2610
|
} catch (err) {
|
|
2922
2611
|
// event is not a ProviderMessage JSON object, skip
|
|
2923
2612
|
return;
|
|
2924
2613
|
}
|
|
2925
|
-
|
|
2926
2614
|
if (!message) {
|
|
2927
2615
|
throw new Error('ProviderMessage object is empty');
|
|
2928
|
-
}
|
|
2929
|
-
|
|
2616
|
+
}
|
|
2930
2617
|
|
|
2618
|
+
// handle message with base message provider
|
|
2931
2619
|
this.handleMessage(message);
|
|
2932
2620
|
};
|
|
2933
|
-
|
|
2934
2621
|
this.walletURL = new URL(walletAppURL);
|
|
2935
2622
|
}
|
|
2936
|
-
|
|
2937
2623
|
closeWallet() {
|
|
2938
2624
|
var _this$walletWindow;
|
|
2939
|
-
|
|
2940
2625
|
this.close();
|
|
2941
2626
|
(_this$walletWindow = this.walletWindow) == null ? void 0 : _this$walletWindow.close();
|
|
2942
|
-
}
|
|
2627
|
+
}
|
|
2943
2628
|
|
|
2629
|
+
// onmessage, receives ProviderMessageResponse from the wallet post-message transport
|
|
2944
2630
|
|
|
2945
2631
|
sendMessage(message) {
|
|
2946
2632
|
if (!this.walletWindow) {
|
|
2947
2633
|
logger.warn('WindowMessageProvider: sendMessage failed as walletWindow is unavailable');
|
|
2948
2634
|
return;
|
|
2949
2635
|
}
|
|
2950
|
-
|
|
2951
2636
|
const postedMessage = typeof message !== 'string' ? JSON.stringify(message) : message;
|
|
2952
2637
|
this.walletWindow.postMessage(postedMessage, this.walletURL.origin);
|
|
2953
2638
|
}
|
|
2954
|
-
|
|
2955
2639
|
}
|
|
2956
2640
|
|
|
2957
2641
|
class WindowMessageHandler extends BaseWalletTransport {
|
|
2958
2642
|
constructor(walletRequestHandler) {
|
|
2959
2643
|
var _this;
|
|
2960
|
-
|
|
2961
2644
|
super(walletRequestHandler);
|
|
2962
2645
|
_this = this;
|
|
2963
2646
|
this.parentWindow = void 0;
|
|
2964
2647
|
this._isPopup = false;
|
|
2965
|
-
|
|
2966
2648
|
this.onWindowEvent = async function (event) {
|
|
2967
2649
|
if (!event.origin || event.origin === '') {
|
|
2968
2650
|
// skip same-origin or when event.origin is empty/undefined
|
|
2969
2651
|
return;
|
|
2970
2652
|
}
|
|
2971
|
-
|
|
2972
2653
|
if (_this.appOrigin && event.origin !== _this.appOrigin) {
|
|
2973
2654
|
// skip message as not from expected app origin
|
|
2974
2655
|
return;
|
|
2975
|
-
}
|
|
2976
|
-
|
|
2656
|
+
}
|
|
2977
2657
|
|
|
2658
|
+
// Wallet always expects json-rpc request messages from a dapp
|
|
2978
2659
|
let request;
|
|
2979
|
-
|
|
2980
2660
|
try {
|
|
2981
2661
|
request = JSON.parse(event.data);
|
|
2982
2662
|
} catch (err) {
|
|
2983
2663
|
// event is not a ProviderMessage JSON object, skip
|
|
2984
2664
|
return;
|
|
2985
2665
|
}
|
|
2666
|
+
logger.debug('RECEIVED MESSAGE', request);
|
|
2986
2667
|
|
|
2987
|
-
|
|
2988
|
-
|
|
2668
|
+
// Record event origin for valid init ack
|
|
2989
2669
|
if (_this._init !== InitState.OK && _this.isValidInitAck(request)) {
|
|
2990
2670
|
_this.appOrigin = event.origin;
|
|
2991
2671
|
}
|
|
2992
|
-
|
|
2993
2672
|
if (_this._init === InitState.OK && (!_this.appOrigin || _this.appOrigin.length < 8)) {
|
|
2994
2673
|
// impossible state
|
|
2995
2674
|
logger.error('impossible state, init.OK and appOrigin required');
|
|
2996
2675
|
return;
|
|
2997
|
-
}
|
|
2998
|
-
|
|
2676
|
+
}
|
|
2999
2677
|
|
|
2678
|
+
// Handle message via the base transport
|
|
3000
2679
|
_this.handleMessage(request);
|
|
3001
2680
|
};
|
|
3002
|
-
|
|
3003
2681
|
this.getWindowTransportSession = windowParams => {
|
|
3004
2682
|
const params = new WindowSessionParams(windowParams);
|
|
3005
2683
|
return {
|
|
@@ -3008,46 +2686,45 @@ class WindowMessageHandler extends BaseWalletTransport {
|
|
|
3008
2686
|
intent: base64DecodeObject(params.get('intent'))
|
|
3009
2687
|
};
|
|
3010
2688
|
};
|
|
3011
|
-
|
|
3012
2689
|
this._init = InitState.NIL;
|
|
3013
2690
|
}
|
|
3014
|
-
|
|
3015
2691
|
async register(windowHref) {
|
|
3016
2692
|
const isPopup = parent.window.opener !== null;
|
|
3017
2693
|
this._isPopup = isPopup;
|
|
3018
|
-
|
|
3019
2694
|
if (isPopup !== true) {
|
|
3020
2695
|
return;
|
|
3021
|
-
}
|
|
3022
|
-
|
|
2696
|
+
}
|
|
3023
2697
|
|
|
2698
|
+
// record open details (sessionId + default network) from the window url
|
|
3024
2699
|
const {
|
|
3025
2700
|
pathname,
|
|
3026
2701
|
search: rawParams
|
|
3027
2702
|
} = new URL(windowHref || window.location.href);
|
|
3028
|
-
let session = this.getWindowTransportSession(rawParams);
|
|
2703
|
+
let session = this.getWindowTransportSession(rawParams);
|
|
3029
2704
|
|
|
3030
|
-
|
|
2705
|
+
// provider should always include sid when opening a new window
|
|
2706
|
+
const isNewWindowSession = !!session.sessionId;
|
|
3031
2707
|
|
|
2708
|
+
// attempt to restore previous session in the case of a redirect or window reload
|
|
3032
2709
|
if (!isNewWindowSession) {
|
|
3033
2710
|
session = await this.getCachedTransportSession();
|
|
3034
2711
|
}
|
|
3035
|
-
|
|
3036
2712
|
if (!session) {
|
|
3037
2713
|
logger.error('window session is undefined');
|
|
3038
2714
|
return;
|
|
3039
|
-
}
|
|
3040
|
-
|
|
2715
|
+
}
|
|
3041
2716
|
|
|
3042
|
-
|
|
2717
|
+
// record parent window instance for communication
|
|
2718
|
+
this.parentWindow = parent.window.opener;
|
|
3043
2719
|
|
|
2720
|
+
// listen for window-transport requests
|
|
3044
2721
|
window.addEventListener('message', this.onWindowEvent, false);
|
|
3045
|
-
this._registered = true;
|
|
2722
|
+
this._registered = true;
|
|
3046
2723
|
|
|
2724
|
+
// send open event to the app which opened us
|
|
3047
2725
|
this.open(session).then(opened => {
|
|
3048
2726
|
if (!opened) {
|
|
3049
2727
|
var _session;
|
|
3050
|
-
|
|
3051
2728
|
const err = `failed to open to network ${(_session = session) == null ? void 0 : _session.networkId}`;
|
|
3052
2729
|
logger.error(err);
|
|
3053
2730
|
this.notifyClose({
|
|
@@ -3057,7 +2734,6 @@ class WindowMessageHandler extends BaseWalletTransport {
|
|
|
3057
2734
|
}
|
|
3058
2735
|
}).catch(e => {
|
|
3059
2736
|
var _session2;
|
|
3060
|
-
|
|
3061
2737
|
const err = `failed to open to network ${(_session2 = session) == null ? void 0 : _session2.networkId}, due to: ${e}`;
|
|
3062
2738
|
logger.error(err);
|
|
3063
2739
|
this.notifyClose({
|
|
@@ -3066,37 +2742,35 @@ class WindowMessageHandler extends BaseWalletTransport {
|
|
|
3066
2742
|
window.close();
|
|
3067
2743
|
});
|
|
3068
2744
|
}
|
|
3069
|
-
|
|
3070
2745
|
unregister() {
|
|
3071
2746
|
window.removeEventListener('message', this.onWindowEvent);
|
|
3072
2747
|
this._registered = false;
|
|
3073
|
-
}
|
|
3074
|
-
// over the window post-messaging transport
|
|
2748
|
+
}
|
|
3075
2749
|
|
|
2750
|
+
// onmessage is called when (the wallet) receives request messages from the dapp
|
|
2751
|
+
// over the window post-messaging transport
|
|
3076
2752
|
|
|
3077
2753
|
// postMessage sends message to the dapp window
|
|
3078
2754
|
sendMessage(message) {
|
|
3079
2755
|
// prepare payload
|
|
3080
|
-
const payload = JSON.stringify(message);
|
|
3081
|
-
// only for init requests, we send to '*' origin
|
|
2756
|
+
const payload = JSON.stringify(message);
|
|
3082
2757
|
|
|
2758
|
+
// post-message to app.
|
|
2759
|
+
// only for init requests, we send to '*' origin
|
|
3083
2760
|
if (message.type === EventType.INIT) {
|
|
3084
2761
|
this.postMessage(payload, true);
|
|
3085
2762
|
} else {
|
|
3086
2763
|
this.postMessage(payload);
|
|
3087
2764
|
}
|
|
3088
2765
|
}
|
|
3089
|
-
|
|
3090
2766
|
get isPopup() {
|
|
3091
2767
|
return this._isPopup;
|
|
3092
2768
|
}
|
|
3093
|
-
|
|
3094
2769
|
postMessage(message, init = false) {
|
|
3095
2770
|
if (init !== true && this._init !== InitState.OK) {
|
|
3096
2771
|
logger.error('impossible state, should not be calling postMessage until inited');
|
|
3097
2772
|
return;
|
|
3098
2773
|
}
|
|
3099
|
-
|
|
3100
2774
|
if (init) {
|
|
3101
2775
|
// init message transmission to global target -- for 'init' payloads only
|
|
3102
2776
|
this.parentWindow.postMessage(message, '*');
|
|
@@ -3110,7 +2784,6 @@ class WindowMessageHandler extends BaseWalletTransport {
|
|
|
3110
2784
|
}
|
|
3111
2785
|
}
|
|
3112
2786
|
}
|
|
3113
|
-
|
|
3114
2787
|
}
|
|
3115
2788
|
|
|
3116
2789
|
const CHANNEL_ID = 'sequence-extension-message-handler';
|
|
@@ -3121,29 +2794,24 @@ class ExtensionMessageHandler extends BaseWalletTransport {
|
|
|
3121
2794
|
this.port = void 0;
|
|
3122
2795
|
this._init = InitState.OK;
|
|
3123
2796
|
}
|
|
3124
|
-
|
|
3125
2797
|
register() {
|
|
3126
2798
|
this._registered = true;
|
|
3127
2799
|
this.port = this.runtime.connect({
|
|
3128
2800
|
name: CHANNEL_ID
|
|
3129
2801
|
});
|
|
3130
2802
|
}
|
|
3131
|
-
|
|
3132
2803
|
sendMessage(message) {
|
|
3133
2804
|
logger.info('[ExtensionMessageHandler send]', message);
|
|
3134
2805
|
this.port.postMessage(message);
|
|
3135
2806
|
}
|
|
3136
|
-
|
|
3137
2807
|
}
|
|
3138
2808
|
|
|
3139
2809
|
class ExtensionMessageProvider extends BaseProviderTransport {
|
|
3140
2810
|
constructor(runtime) {
|
|
3141
2811
|
super();
|
|
3142
|
-
|
|
3143
2812
|
this.register = () => {
|
|
3144
2813
|
this._registered = true;
|
|
3145
2814
|
};
|
|
3146
|
-
|
|
3147
2815
|
runtime.onConnect.addListener(port => {
|
|
3148
2816
|
if (port.name === CHANNEL_ID) {
|
|
3149
2817
|
this._init = InitState.OK;
|
|
@@ -3153,47 +2821,40 @@ class ExtensionMessageProvider extends BaseProviderTransport {
|
|
|
3153
2821
|
}
|
|
3154
2822
|
});
|
|
3155
2823
|
}
|
|
3156
|
-
|
|
3157
|
-
|
|
2824
|
+
sendMessage(message) {
|
|
2825
|
+
//noop
|
|
3158
2826
|
}
|
|
3159
|
-
|
|
3160
|
-
|
|
2827
|
+
unregister() {
|
|
2828
|
+
//noop
|
|
3161
2829
|
}
|
|
3162
|
-
|
|
3163
|
-
|
|
2830
|
+
openWallet(path, intent, networkId) {
|
|
2831
|
+
//noop
|
|
3164
2832
|
}
|
|
3165
|
-
|
|
3166
|
-
|
|
2833
|
+
closeWallet() {
|
|
2834
|
+
//noop
|
|
3167
2835
|
}
|
|
3168
|
-
|
|
3169
2836
|
}
|
|
3170
2837
|
|
|
3171
2838
|
// to be used on injected window.ethereum EIP1193 proxy
|
|
3172
2839
|
class BaseInjectedTransport extends EventEmitter2 {
|
|
3173
2840
|
constructor(stream) {
|
|
3174
2841
|
var _this;
|
|
3175
|
-
|
|
3176
2842
|
super();
|
|
3177
2843
|
_this = this;
|
|
3178
2844
|
this.stream = stream;
|
|
3179
2845
|
this.responseCallbacks = new Map();
|
|
3180
2846
|
this._messageIdx = 0;
|
|
3181
|
-
|
|
3182
2847
|
this.nextMessageIdx = () => ++this._messageIdx;
|
|
3183
|
-
|
|
3184
2848
|
this.handleMessage = message => {
|
|
3185
2849
|
if (!message.type || !message.data) {
|
|
3186
2850
|
return;
|
|
3187
2851
|
}
|
|
3188
|
-
|
|
3189
2852
|
logger.info('[received message]', message);
|
|
3190
2853
|
const requestIdx = message.idx;
|
|
3191
2854
|
const responseCallback = this.responseCallbacks.get(requestIdx);
|
|
3192
|
-
|
|
3193
2855
|
if (requestIdx) {
|
|
3194
2856
|
this.responseCallbacks.delete(requestIdx);
|
|
3195
2857
|
}
|
|
3196
|
-
|
|
3197
2858
|
switch (message.type) {
|
|
3198
2859
|
case EventType.MESSAGE:
|
|
3199
2860
|
if (responseCallback) {
|
|
@@ -3205,27 +2866,22 @@ class BaseInjectedTransport extends EventEmitter2 {
|
|
|
3205
2866
|
// all of which should be prevented prior to getting to this point
|
|
3206
2867
|
throw new Error('impossible state');
|
|
3207
2868
|
}
|
|
3208
|
-
|
|
3209
2869
|
break;
|
|
3210
|
-
|
|
3211
2870
|
case EventType.DISCONNECT:
|
|
3212
2871
|
case EventType.ACCOUNTS_CHANGED:
|
|
3213
2872
|
case EventType.CHAIN_CHANGED:
|
|
3214
2873
|
this.emit(message.type, message.data);
|
|
3215
2874
|
break;
|
|
3216
|
-
|
|
3217
2875
|
default:
|
|
3218
2876
|
console.error('unknown message type', message);
|
|
3219
2877
|
break;
|
|
3220
2878
|
}
|
|
3221
2879
|
};
|
|
3222
|
-
|
|
3223
2880
|
this.sendMessageRequest = async function (message) {
|
|
3224
2881
|
return new Promise((resolve, reject) => {
|
|
3225
2882
|
if (!message.idx || message.idx <= 0) {
|
|
3226
2883
|
reject(new Error('message idx not set'));
|
|
3227
2884
|
}
|
|
3228
|
-
|
|
3229
2885
|
const responseCallback = (error, response) => {
|
|
3230
2886
|
if (error) {
|
|
3231
2887
|
reject(error);
|
|
@@ -3235,32 +2891,25 @@ class BaseInjectedTransport extends EventEmitter2 {
|
|
|
3235
2891
|
throw new Error('no valid response to return');
|
|
3236
2892
|
}
|
|
3237
2893
|
};
|
|
3238
|
-
|
|
3239
2894
|
const {
|
|
3240
2895
|
idx
|
|
3241
2896
|
} = message;
|
|
3242
|
-
|
|
3243
2897
|
if (!_this.responseCallbacks.get(idx)) {
|
|
3244
2898
|
_this.responseCallbacks.set(idx, responseCallback);
|
|
3245
2899
|
} else {
|
|
3246
2900
|
reject(new Error('duplicate message idx, should never happen'));
|
|
3247
2901
|
}
|
|
3248
|
-
|
|
3249
2902
|
_this.sendMessage(message);
|
|
3250
2903
|
});
|
|
3251
2904
|
};
|
|
3252
|
-
|
|
3253
2905
|
this.stream.on('data', this.handleMessage);
|
|
3254
2906
|
}
|
|
3255
|
-
|
|
3256
2907
|
sendMessage(message) {
|
|
3257
2908
|
if (!this.stream.writable) {
|
|
3258
2909
|
console.error('window post message stream is not writable');
|
|
3259
2910
|
}
|
|
3260
|
-
|
|
3261
2911
|
this.stream.write(message);
|
|
3262
2912
|
}
|
|
3263
|
-
|
|
3264
2913
|
}
|
|
3265
2914
|
|
|
3266
2915
|
/**
|
|
@@ -3268,33 +2917,28 @@ class BaseInjectedTransport extends EventEmitter2 {
|
|
|
3268
2917
|
*/
|
|
3269
2918
|
function overrideLogs(side) {
|
|
3270
2919
|
var _window$ue;
|
|
3271
|
-
|
|
3272
2920
|
if ((_window$ue = window.ue) != null && _window$ue.sequencewallettransport && !window.logsOverriddenForUnreal) {
|
|
3273
2921
|
var _window$ue2;
|
|
3274
|
-
|
|
3275
2922
|
const t = (_window$ue2 = window.ue) == null ? void 0 : _window$ue2.sequencewallettransport;
|
|
3276
|
-
|
|
3277
2923
|
console.log = (...args) => {
|
|
3278
2924
|
t.logfromjs(`${side}: ${stringify(args)}`);
|
|
3279
2925
|
};
|
|
3280
|
-
|
|
3281
2926
|
console.warn = (...args) => {
|
|
3282
2927
|
t.warnfromjs(`${side}: ${stringify(args)}`);
|
|
3283
2928
|
};
|
|
3284
|
-
|
|
3285
2929
|
console.error = (...args) => {
|
|
3286
2930
|
t.errorfromjs(`${side}: ${stringify(args)}`);
|
|
3287
2931
|
};
|
|
3288
|
-
|
|
3289
2932
|
window.logsOverriddenForUnreal = true;
|
|
3290
2933
|
}
|
|
3291
2934
|
}
|
|
3292
|
-
|
|
3293
2935
|
function stringify(things) {
|
|
3294
2936
|
return things.map(a => typeof a === 'object' ? a instanceof Error ? a.message : JSON.stringify(a) : String(a)).join(' ');
|
|
3295
2937
|
}
|
|
3296
2938
|
|
|
3297
|
-
let registeredUnrealMessageProvider;
|
|
2939
|
+
let registeredUnrealMessageProvider;
|
|
2940
|
+
|
|
2941
|
+
// all lowercase is an annoying limitation of Unreal CEF BindUObject
|
|
3298
2942
|
|
|
3299
2943
|
/**
|
|
3300
2944
|
* Initialized on dApp side
|
|
@@ -3303,124 +2947,110 @@ class UnrealMessageProvider extends BaseProviderTransport {
|
|
|
3303
2947
|
constructor(walletAppURL) {
|
|
3304
2948
|
super();
|
|
3305
2949
|
this.walletURL = void 0;
|
|
3306
|
-
|
|
3307
2950
|
this.register = () => {
|
|
3308
2951
|
var _window$ue;
|
|
3309
|
-
|
|
3310
2952
|
overrideLogs('dapp');
|
|
3311
|
-
|
|
3312
2953
|
if (registeredUnrealMessageProvider) {
|
|
3313
2954
|
// overriding the registered message provider
|
|
3314
2955
|
registeredUnrealMessageProvider.unregister();
|
|
3315
2956
|
registeredUnrealMessageProvider = this;
|
|
3316
|
-
}
|
|
3317
|
-
|
|
2957
|
+
}
|
|
3318
2958
|
|
|
2959
|
+
// listen for incoming messages from wallet
|
|
3319
2960
|
if ((_window$ue = window.ue) != null && _window$ue.sequencewallettransport) {
|
|
3320
2961
|
window.ue.sequencewallettransport.onmessagefromwallet = this.onUnrealCallback;
|
|
3321
2962
|
}
|
|
3322
|
-
|
|
3323
2963
|
registeredUnrealMessageProvider = this;
|
|
3324
2964
|
this._registered = true;
|
|
3325
2965
|
console.log('registering transport!');
|
|
3326
2966
|
};
|
|
3327
|
-
|
|
3328
2967
|
this.unregister = () => {
|
|
3329
2968
|
var _window$ue2, _window$ue2$sequencew;
|
|
3330
|
-
|
|
3331
2969
|
this._registered = false;
|
|
3332
|
-
this.closeWallet();
|
|
2970
|
+
this.closeWallet();
|
|
3333
2971
|
|
|
2972
|
+
// disable message listener
|
|
3334
2973
|
if (registeredUnrealMessageProvider === this) {
|
|
3335
2974
|
registeredUnrealMessageProvider = undefined;
|
|
3336
2975
|
}
|
|
3337
|
-
|
|
3338
2976
|
if (((_window$ue2 = window.ue) == null ? void 0 : (_window$ue2$sequencew = _window$ue2.sequencewallettransport) == null ? void 0 : _window$ue2$sequencew.onmessagefromwallet) === this.onUnrealCallback) {
|
|
3339
2977
|
delete window.ue.sequencewallettransport.onmessagefromwallet;
|
|
3340
|
-
}
|
|
3341
|
-
|
|
2978
|
+
}
|
|
3342
2979
|
|
|
2980
|
+
// clear event listeners
|
|
3343
2981
|
this.events.removeAllListeners();
|
|
3344
2982
|
};
|
|
3345
|
-
|
|
3346
2983
|
this.openWallet = (path, intent, networkId) => {
|
|
3347
2984
|
if (this.isOpened()) {
|
|
3348
2985
|
// TODO focus wallet
|
|
3349
2986
|
console.log('wallet already open!');
|
|
3350
2987
|
return;
|
|
3351
2988
|
}
|
|
3352
|
-
|
|
3353
|
-
|
|
3354
|
-
|
|
2989
|
+
console.log('opening wallet!');
|
|
2990
|
+
// Instantiate new walletURL for this call
|
|
3355
2991
|
const walletURL = new URL(this.walletURL.href);
|
|
3356
2992
|
const windowSessionParams = new WindowSessionParams();
|
|
3357
|
-
|
|
3358
2993
|
if (path) {
|
|
3359
2994
|
walletURL.pathname = path.toLowerCase();
|
|
3360
|
-
}
|
|
3361
|
-
|
|
2995
|
+
}
|
|
3362
2996
|
|
|
2997
|
+
// Set session, intent and network id on walletURL
|
|
3363
2998
|
this._init = InitState.NIL;
|
|
3364
2999
|
this._sessionId = `${performance.now()}`;
|
|
3365
3000
|
windowSessionParams.set('sid', this._sessionId);
|
|
3366
|
-
|
|
3367
3001
|
if (intent) {
|
|
3368
3002
|
// encode intent as base64 url-encoded param
|
|
3369
3003
|
windowSessionParams.set('intent', base64EncodeObject(intent));
|
|
3370
3004
|
}
|
|
3371
|
-
|
|
3372
3005
|
if (networkId) {
|
|
3373
3006
|
windowSessionParams.set('net', `${networkId}`);
|
|
3374
|
-
}
|
|
3375
|
-
|
|
3376
|
-
|
|
3007
|
+
}
|
|
3008
|
+
// serialize params
|
|
3377
3009
|
walletURL.search = windowSessionParams.toString();
|
|
3378
3010
|
console.log('opening wallet to', walletURL.href);
|
|
3379
3011
|
window.open(walletURL.href);
|
|
3380
3012
|
};
|
|
3381
|
-
|
|
3382
3013
|
this.onUnrealCallback = message => {
|
|
3383
3014
|
if (!message) {
|
|
3384
3015
|
throw new Error('ProviderMessage object is empty');
|
|
3385
|
-
}
|
|
3386
|
-
|
|
3016
|
+
}
|
|
3387
3017
|
|
|
3018
|
+
// handle message with base message provider
|
|
3388
3019
|
this.handleMessage(message);
|
|
3389
3020
|
};
|
|
3390
|
-
|
|
3391
3021
|
this.walletURL = new URL(walletAppURL);
|
|
3392
3022
|
}
|
|
3393
|
-
|
|
3394
3023
|
closeWallet() {
|
|
3395
3024
|
this.close();
|
|
3396
|
-
}
|
|
3025
|
+
}
|
|
3397
3026
|
|
|
3027
|
+
// onmessage, receives ProviderMessageResponse from the wallet unreal transport
|
|
3398
3028
|
|
|
3399
3029
|
// all lowercase is an annoying limitation of Unreal CEF BindUObject
|
|
3400
3030
|
sendMessage(message) {
|
|
3401
3031
|
var _window$ue3, _window$ue3$sequencew;
|
|
3402
|
-
|
|
3403
3032
|
const postedMessage = typeof message !== 'string' ? JSON.stringify(message) : message;
|
|
3404
3033
|
console.log('Sending message to wallet:', postedMessage);
|
|
3405
3034
|
(_window$ue3 = window.ue) == null ? void 0 : (_window$ue3$sequencew = _window$ue3.sequencewallettransport) == null ? void 0 : _window$ue3$sequencew.sendmessagetowallet(postedMessage);
|
|
3406
3035
|
}
|
|
3407
|
-
|
|
3408
3036
|
}
|
|
3409
3037
|
|
|
3038
|
+
// all lowercase is an annoying limitation of Unreal CEF BindUObject
|
|
3039
|
+
|
|
3410
3040
|
/**
|
|
3411
3041
|
* Initialized on Wallet side
|
|
3412
3042
|
*/
|
|
3413
3043
|
class UnrealMessageHandler extends BaseWalletTransport {
|
|
3414
3044
|
constructor(walletRequestHandler) {
|
|
3415
3045
|
super(walletRequestHandler);
|
|
3416
|
-
|
|
3417
3046
|
this.onMessageFromUnreal = request => {
|
|
3418
3047
|
// Wallet always expects json-rpc request messages from a dapp
|
|
3419
|
-
logger.debug('RECEIVED MESSAGE', request); // Handle message via the base transport
|
|
3420
3048
|
|
|
3049
|
+
logger.debug('RECEIVED MESSAGE', request);
|
|
3050
|
+
|
|
3051
|
+
// Handle message via the base transport
|
|
3421
3052
|
this.handleMessage(request);
|
|
3422
3053
|
};
|
|
3423
|
-
|
|
3424
3054
|
this.getUnrealTransportSession = windowParams => {
|
|
3425
3055
|
const params = new WindowSessionParams(windowParams);
|
|
3426
3056
|
return {
|
|
@@ -3429,43 +3059,41 @@ class UnrealMessageHandler extends BaseWalletTransport {
|
|
|
3429
3059
|
intent: base64DecodeObject(params.get('intent'))
|
|
3430
3060
|
};
|
|
3431
3061
|
};
|
|
3432
|
-
|
|
3433
3062
|
this._init = InitState.NIL;
|
|
3434
3063
|
}
|
|
3435
|
-
|
|
3436
3064
|
async register(windowHref) {
|
|
3437
3065
|
var _window$ue;
|
|
3438
|
-
|
|
3439
3066
|
if (((_window$ue = window.ue) == null ? void 0 : _window$ue.sequencewallettransport) === undefined) {
|
|
3440
3067
|
return;
|
|
3441
3068
|
}
|
|
3069
|
+
overrideLogs('wallet');
|
|
3442
3070
|
|
|
3443
|
-
|
|
3444
|
-
|
|
3071
|
+
// record open details (sessionId + default network) from the window url
|
|
3445
3072
|
const {
|
|
3446
3073
|
search: rawParams
|
|
3447
3074
|
} = new URL(windowHref || window.location.href);
|
|
3448
|
-
let session = this.getUnrealTransportSession(rawParams);
|
|
3075
|
+
let session = this.getUnrealTransportSession(rawParams);
|
|
3449
3076
|
|
|
3450
|
-
|
|
3077
|
+
// provider should always include sid when opening a new window
|
|
3078
|
+
const isNewWindowSession = !!session.sessionId;
|
|
3451
3079
|
|
|
3080
|
+
// attempt to restore previous session in the case of a redirect or window reload
|
|
3452
3081
|
if (!isNewWindowSession) {
|
|
3453
3082
|
session = await this.getCachedTransportSession();
|
|
3454
3083
|
}
|
|
3455
|
-
|
|
3456
3084
|
if (!session) {
|
|
3457
3085
|
logger.error('unreal session is undefined');
|
|
3458
3086
|
return;
|
|
3459
|
-
}
|
|
3460
|
-
|
|
3087
|
+
}
|
|
3461
3088
|
|
|
3089
|
+
// listen for window-transport requests
|
|
3462
3090
|
window.ue.sequencewallettransport.onmessagefromsequencejs = this.onMessageFromUnreal;
|
|
3463
|
-
this._registered = true;
|
|
3091
|
+
this._registered = true;
|
|
3464
3092
|
|
|
3093
|
+
// send open event to the app which opened us
|
|
3465
3094
|
this.open(session).then(opened => {
|
|
3466
3095
|
if (!opened) {
|
|
3467
3096
|
var _session;
|
|
3468
|
-
|
|
3469
3097
|
const err = `failed to open to network ${(_session = session) == null ? void 0 : _session.networkId}`;
|
|
3470
3098
|
logger.error(err);
|
|
3471
3099
|
this.notifyClose({
|
|
@@ -3475,7 +3103,6 @@ class UnrealMessageHandler extends BaseWalletTransport {
|
|
|
3475
3103
|
}
|
|
3476
3104
|
}).catch(e => {
|
|
3477
3105
|
var _session2;
|
|
3478
|
-
|
|
3479
3106
|
const err = `failed to open to network ${(_session2 = session) == null ? void 0 : _session2.networkId}, due to: ${e}`;
|
|
3480
3107
|
logger.error(err);
|
|
3481
3108
|
this.notifyClose({
|
|
@@ -3484,132 +3111,127 @@ class UnrealMessageHandler extends BaseWalletTransport {
|
|
|
3484
3111
|
window.close();
|
|
3485
3112
|
});
|
|
3486
3113
|
}
|
|
3487
|
-
|
|
3488
3114
|
unregister() {
|
|
3489
3115
|
var _window$ue2, _window$ue2$sequencew;
|
|
3490
|
-
|
|
3491
3116
|
if (((_window$ue2 = window.ue) == null ? void 0 : (_window$ue2$sequencew = _window$ue2.sequencewallettransport) == null ? void 0 : _window$ue2$sequencew.onmessagefromsequencejs) === this.onMessageFromUnreal) {
|
|
3492
3117
|
delete window.ue.sequencewallettransport.onmessagefromsequencejs;
|
|
3493
3118
|
}
|
|
3494
|
-
|
|
3495
3119
|
this._registered = false;
|
|
3496
|
-
}
|
|
3497
|
-
// over the unreal json-messaging transport
|
|
3120
|
+
}
|
|
3498
3121
|
|
|
3122
|
+
// onmessage is called when (the wallet) receives request messages from the dapp
|
|
3123
|
+
// over the unreal json-messaging transport
|
|
3499
3124
|
|
|
3500
3125
|
// sendMessage sends message to the dapp window
|
|
3501
3126
|
sendMessage(message) {
|
|
3502
3127
|
var _window$ue3, _window$ue3$sequencew;
|
|
3503
|
-
|
|
3504
3128
|
if (message.type !== EventType.INIT && this._init !== InitState.OK) {
|
|
3505
3129
|
logger.error('impossible state, should not be calling postMessage until inited');
|
|
3506
3130
|
return;
|
|
3507
|
-
}
|
|
3508
|
-
|
|
3509
|
-
|
|
3510
|
-
const payload = JSON.stringify(message); // post-message to app.
|
|
3131
|
+
}
|
|
3132
|
+
// prepare payload
|
|
3133
|
+
const payload = JSON.stringify(message);
|
|
3511
3134
|
|
|
3135
|
+
// post-message to app.
|
|
3512
3136
|
(_window$ue3 = window.ue) == null ? void 0 : (_window$ue3$sequencew = _window$ue3.sequencewallettransport) == null ? void 0 : _window$ue3$sequencew.sendmessagetosequencejs(payload);
|
|
3513
3137
|
}
|
|
3514
|
-
|
|
3515
3138
|
}
|
|
3516
3139
|
|
|
3517
3140
|
class WalletUtils {
|
|
3518
3141
|
constructor(walletProvider) {
|
|
3519
3142
|
var _this = this;
|
|
3520
|
-
|
|
3521
3143
|
this.wallet = void 0;
|
|
3522
|
-
|
|
3523
3144
|
this.recoverWalletConfig = async function (address, digest, signature, chainId, walletContext) {
|
|
3524
3145
|
walletContext = walletContext || (await _this.wallet.getWalletContext());
|
|
3525
3146
|
return recoverWalletConfig(address, digest, signature, chainId, walletContext);
|
|
3526
3147
|
};
|
|
3527
|
-
|
|
3528
3148
|
this.recoverWalletConfigFromMessage = async function (address, message, signature, chainId, walletContext) {
|
|
3529
3149
|
walletContext = walletContext || (await _this.wallet.getWalletContext());
|
|
3530
3150
|
return recoverWalletConfig(address, encodeMessageDigest(prefixEIP191Message(message)), signature, chainId, walletContext);
|
|
3531
3151
|
};
|
|
3532
|
-
|
|
3533
3152
|
this.recoverWalletConfigFromTypedData = async function (address, typedData, signature, chainId, walletContext) {
|
|
3534
3153
|
walletContext = walletContext || (await _this.wallet.getWalletContext());
|
|
3535
3154
|
return recoverWalletConfig(address, encodeTypedDataDigest(typedData), signature, chainId, walletContext);
|
|
3536
3155
|
};
|
|
3537
|
-
|
|
3538
3156
|
this.wallet = walletProvider;
|
|
3539
|
-
}
|
|
3540
|
-
|
|
3157
|
+
}
|
|
3541
3158
|
|
|
3159
|
+
// Sign message on a specified chain, or DefaultChain by default
|
|
3542
3160
|
signMessage(message, chainId, allSigners) {
|
|
3543
3161
|
const signer = this.wallet.getSigner();
|
|
3544
3162
|
if (!signer) throw new Error('unable to get signer');
|
|
3545
3163
|
return signer.signMessage(message, chainId, allSigners);
|
|
3546
|
-
}
|
|
3547
|
-
|
|
3164
|
+
}
|
|
3548
3165
|
|
|
3166
|
+
// Sign message on the AuthChain
|
|
3549
3167
|
async signAuthMessage(message, allSigners) {
|
|
3550
3168
|
const signer = await this.wallet.getAuthSigner();
|
|
3551
3169
|
if (!signer) throw new Error('unable to get AuthChain signer');
|
|
3552
3170
|
return signer.signMessage(message, await signer.getChainId(), allSigners);
|
|
3553
|
-
}
|
|
3554
|
-
|
|
3171
|
+
}
|
|
3555
3172
|
|
|
3173
|
+
// Sign EIP-712 TypedData on a specified chain, or DefaultChain by default
|
|
3556
3174
|
signTypedData(domain, types, message, chainId, allSigners) {
|
|
3557
3175
|
const signer = this.wallet.getSigner();
|
|
3558
3176
|
if (!signer) throw new Error('unable to get signer');
|
|
3559
3177
|
return signer.signTypedData(domain, types, message, chainId, allSigners);
|
|
3560
|
-
}
|
|
3561
|
-
|
|
3178
|
+
}
|
|
3562
3179
|
|
|
3180
|
+
// Sign EIP-712 TypedData on the AuthChain
|
|
3563
3181
|
async signAuthTypedData(domain, types, message, allSigners) {
|
|
3564
3182
|
const signer = await this.wallet.getAuthSigner();
|
|
3565
3183
|
if (!signer) throw new Error('unable to get AuthChain signer');
|
|
3566
3184
|
return signer.signTypedData(domain, types, message, await signer.getChainId(), allSigners);
|
|
3567
|
-
}
|
|
3568
|
-
|
|
3185
|
+
}
|
|
3569
3186
|
|
|
3187
|
+
// Verify signature of a digest, one of a message, typedData or other
|
|
3570
3188
|
async isValidSignature(address, digest, signature, chainId, walletContext) {
|
|
3571
3189
|
const provider = this.wallet.getProvider(chainId);
|
|
3572
3190
|
if (!provider) throw new Error(`unable to get provider for chainId ${chainId}`);
|
|
3573
3191
|
return isValidSignature(address, digest, signature, provider, chainId, walletContext);
|
|
3574
|
-
}
|
|
3575
|
-
|
|
3192
|
+
}
|
|
3576
3193
|
|
|
3194
|
+
// Verify message signature
|
|
3577
3195
|
async isValidMessageSignature(address, message, signature, chainId, walletContext) {
|
|
3578
3196
|
const provider = this.wallet.getProvider(chainId);
|
|
3579
3197
|
if (!provider) throw new Error(`unable to get provider for chainId ${chainId}`);
|
|
3580
3198
|
const prefixed = prefixEIP191Message(message);
|
|
3581
3199
|
const digest = encodeMessageDigest(prefixed);
|
|
3582
3200
|
return isValidSignature(address, digest, signature, provider, chainId, walletContext);
|
|
3583
|
-
}
|
|
3584
|
-
|
|
3201
|
+
}
|
|
3585
3202
|
|
|
3203
|
+
// Verify typedData signature
|
|
3586
3204
|
isValidTypedDataSignature(address, typedData, signature, chainId, walletContext) {
|
|
3587
3205
|
return this.isValidSignature(address, encodeTypedDataDigest(typedData), signature, chainId, walletContext);
|
|
3588
|
-
}
|
|
3206
|
+
}
|
|
3207
|
+
|
|
3208
|
+
// Recover the WalletConfig from a signature + digest combo
|
|
3209
|
+
|
|
3589
3210
|
// sendTransaction()
|
|
3590
3211
|
// sendTransactions()
|
|
3212
|
+
|
|
3591
3213
|
// sendETH()
|
|
3592
3214
|
// sendToken()
|
|
3593
3215
|
// sendCoin() -- sugar for sendToken()
|
|
3594
3216
|
// sendCollectible() -- sugar for sendToken()
|
|
3595
3217
|
// callContract()
|
|
3218
|
+
|
|
3596
3219
|
// transactionHistory()
|
|
3597
3220
|
// getReceipt()
|
|
3598
3221
|
// getLogs()
|
|
3599
3222
|
// // ..
|
|
3223
|
+
|
|
3600
3224
|
// isWalletDeployed()
|
|
3601
3225
|
// deployWallet()
|
|
3226
|
+
|
|
3602
3227
|
// validateSignature()
|
|
3603
3228
|
// recoverWalletConfig()
|
|
3604
3229
|
// recoverAddress()
|
|
3605
|
-
|
|
3606
|
-
|
|
3607
3230
|
}
|
|
3608
3231
|
|
|
3609
3232
|
class Wallet {
|
|
3610
3233
|
constructor(_network, config) {
|
|
3611
3234
|
var _this = this;
|
|
3612
|
-
|
|
3613
3235
|
this.utils = void 0;
|
|
3614
3236
|
this.config = void 0;
|
|
3615
3237
|
this.session = void 0;
|
|
@@ -3617,32 +3239,32 @@ class Wallet {
|
|
|
3617
3239
|
this.transport = void 0;
|
|
3618
3240
|
this.networks = void 0;
|
|
3619
3241
|
this.providers = void 0;
|
|
3620
|
-
|
|
3621
3242
|
this.init = () => {
|
|
3622
3243
|
var _this$config$transpor, _this$config$transpor2, _this$config$transpor3, _this$config$transpor4, _this$config$transpor5, _this$config$transpor6, _this$config$transpor7, _this$config$transpor8;
|
|
3623
|
-
|
|
3624
3244
|
if (this.transport.provider) {
|
|
3625
3245
|
// init must have already been called
|
|
3626
3246
|
return;
|
|
3627
|
-
}
|
|
3247
|
+
}
|
|
3628
3248
|
|
|
3249
|
+
// Setup provider
|
|
3629
3250
|
|
|
3630
|
-
this.transport.messageProvider = new MuxMessageProvider();
|
|
3251
|
+
this.transport.messageProvider = new MuxMessageProvider();
|
|
3631
3252
|
|
|
3253
|
+
// multiple message provider setup, first one to connect will be the main transport
|
|
3632
3254
|
if ((_this$config$transpor = this.config.transports) != null && (_this$config$transpor2 = _this$config$transpor.windowTransport) != null && _this$config$transpor2.enabled) {
|
|
3633
3255
|
this.transport.windowMessageProvider = new WindowMessageProvider(this.config.walletAppURL);
|
|
3634
3256
|
this.transport.messageProvider.add(this.transport.windowMessageProvider);
|
|
3635
3257
|
}
|
|
3636
|
-
|
|
3637
3258
|
if ((_this$config$transpor3 = this.config.transports) != null && (_this$config$transpor4 = _this$config$transpor3.proxyTransport) != null && _this$config$transpor4.enabled) {
|
|
3638
3259
|
this.transport.proxyMessageProvider = new ProxyMessageProvider(this.config.transports.proxyTransport.appPort);
|
|
3639
3260
|
this.transport.messageProvider.add(this.transport.proxyMessageProvider);
|
|
3640
3261
|
}
|
|
3641
|
-
|
|
3642
3262
|
if ((_this$config$transpor5 = this.config.transports) != null && (_this$config$transpor6 = _this$config$transpor5.extensionTransport) != null && _this$config$transpor6.enabled) {
|
|
3643
|
-
this.transport.extensionMessageProvider = new ExtensionMessageProvider(this.config.transports.extensionTransport.runtime);
|
|
3263
|
+
this.transport.extensionMessageProvider = new ExtensionMessageProvider(this.config.transports.extensionTransport.runtime);
|
|
3264
|
+
// this.transport.extensionMessageProvider.register()
|
|
3265
|
+
this.transport.messageProvider.add(this.transport.extensionMessageProvider);
|
|
3644
3266
|
|
|
3645
|
-
|
|
3267
|
+
// NOTE/REVIEW: see note in mux-message-provider
|
|
3646
3268
|
//
|
|
3647
3269
|
// We don't add the extensionMessageProvider here because we don't send requests to it anyways, we seem to
|
|
3648
3270
|
// send all requests to the WindowMessageProvider anyways. By allowing it, if browser restarts, it will break
|
|
@@ -3655,27 +3277,28 @@ class Wallet {
|
|
|
3655
3277
|
this.transport.unrealMessageProvider = new UnrealMessageProvider(this.config.walletAppURL);
|
|
3656
3278
|
this.transport.messageProvider.add(this.transport.unrealMessageProvider);
|
|
3657
3279
|
}
|
|
3280
|
+
this.transport.messageProvider.register();
|
|
3658
3281
|
|
|
3659
|
-
|
|
3660
|
-
|
|
3282
|
+
// .....
|
|
3661
3283
|
this.transport.allowProvider = allowProviderMiddleware(request => {
|
|
3662
3284
|
if (request.method === 'sequence_setDefaultNetwork') return true;
|
|
3663
3285
|
const isConnected = this.isConnected();
|
|
3664
|
-
|
|
3665
3286
|
if (!isConnected) {
|
|
3666
3287
|
throw new Error('Sequence: wallet not connected');
|
|
3667
3288
|
}
|
|
3668
|
-
|
|
3669
3289
|
return isConnected;
|
|
3670
|
-
});
|
|
3290
|
+
});
|
|
3671
3291
|
|
|
3292
|
+
// ...
|
|
3672
3293
|
this.transport.networkProvider = networkProviderMiddleware(request => {
|
|
3673
3294
|
// return stub chainId of 0 when not connected to any
|
|
3674
|
-
if (!this.networks || this.networks.length === 0) return 0;
|
|
3295
|
+
if (!this.networks || this.networks.length === 0) return 0;
|
|
3675
3296
|
|
|
3297
|
+
// return the default chainId as we're connected
|
|
3676
3298
|
return this.networks.find(network => network.isDefaultChain).chainId;
|
|
3677
|
-
});
|
|
3299
|
+
});
|
|
3678
3300
|
|
|
3301
|
+
// Provider proxy to support middleware stack of logging, caching and read-only rpc calls
|
|
3679
3302
|
this.transport.cachedProvider = new CachedProvider();
|
|
3680
3303
|
this.transport.cachedProvider.onUpdate(() => {
|
|
3681
3304
|
if (!this.session) this.session = {
|
|
@@ -3683,33 +3306,35 @@ class Wallet {
|
|
|
3683
3306
|
};
|
|
3684
3307
|
this.session.providerCache = this.transport.cachedProvider.getCache();
|
|
3685
3308
|
this.saveSession(this.session);
|
|
3686
|
-
});
|
|
3309
|
+
});
|
|
3687
3310
|
|
|
3311
|
+
// ..
|
|
3688
3312
|
this.transport.router = new JsonRpcRouter([loggingProviderMiddleware, this.transport.networkProvider, this.transport.allowProvider, exceptionProviderMiddleware, this.transport.cachedProvider], this.transport.messageProvider);
|
|
3689
|
-
this.transport.provider = new Web3Provider(this.transport.router);
|
|
3313
|
+
this.transport.provider = new Web3Provider(this.transport.router);
|
|
3314
|
+
|
|
3315
|
+
// NOTE: we don't listen on 'connect' even here as we handle it within connect() method
|
|
3690
3316
|
// in more synchronous flow.
|
|
3317
|
+
|
|
3691
3318
|
// below will update the wallet session object and persist it. In case the session
|
|
3692
3319
|
// is undefined, we consider the session to have been removed by the user, so we clear it.
|
|
3693
|
-
|
|
3694
3320
|
this.transport.messageProvider.on('open', openInfo => {
|
|
3695
3321
|
const {
|
|
3696
3322
|
session
|
|
3697
3323
|
} = openInfo;
|
|
3698
|
-
|
|
3699
3324
|
if (!session) {
|
|
3700
3325
|
if (this.session && this.session.accountAddress) {
|
|
3701
3326
|
// emit disconnect even if previously we had a session, and now we don't.
|
|
3702
3327
|
this.transport.messageProvider.emit('disconnect');
|
|
3703
3328
|
}
|
|
3704
|
-
|
|
3705
3329
|
this.clearSession();
|
|
3706
3330
|
} else {
|
|
3707
3331
|
this.useSession(session, true);
|
|
3708
3332
|
}
|
|
3709
|
-
});
|
|
3333
|
+
});
|
|
3334
|
+
|
|
3335
|
+
// below will update the account upon wallet connect/disconnect - aka, login/logout.
|
|
3710
3336
|
// if an origin is provided, this operation should be performed only on that origin
|
|
3711
3337
|
// and shouldn't affect the session of the wallet.
|
|
3712
|
-
|
|
3713
3338
|
this.transport.messageProvider.on('accountsChanged', (accounts, origin) => {
|
|
3714
3339
|
if (origin) {
|
|
3715
3340
|
if (accounts.length > 0) {
|
|
@@ -3717,10 +3342,8 @@ class Wallet {
|
|
|
3717
3342
|
accountAddress: accounts[0]
|
|
3718
3343
|
}, true);
|
|
3719
3344
|
}
|
|
3720
|
-
|
|
3721
3345
|
return;
|
|
3722
3346
|
}
|
|
3723
|
-
|
|
3724
3347
|
if (!accounts || accounts.length === 0 || accounts[0] === '') {
|
|
3725
3348
|
this.clearSession();
|
|
3726
3349
|
} else {
|
|
@@ -3728,47 +3351,42 @@ class Wallet {
|
|
|
3728
3351
|
accountAddress: accounts[0]
|
|
3729
3352
|
}, true);
|
|
3730
3353
|
}
|
|
3731
|
-
});
|
|
3354
|
+
});
|
|
3732
3355
|
|
|
3356
|
+
// below will update the networks automatically when the wallet networks change
|
|
3733
3357
|
this.transport.messageProvider.on('networks', networks => {
|
|
3734
3358
|
this.useSession({
|
|
3735
3359
|
networks: networks
|
|
3736
3360
|
}, true);
|
|
3737
|
-
});
|
|
3361
|
+
});
|
|
3738
3362
|
|
|
3363
|
+
// below will update the wallet context automatically
|
|
3739
3364
|
this.transport.messageProvider.on('walletContext', walletContext => {
|
|
3740
3365
|
this.useSession({
|
|
3741
3366
|
walletContext: walletContext
|
|
3742
3367
|
}, true);
|
|
3743
3368
|
});
|
|
3744
3369
|
};
|
|
3745
|
-
|
|
3746
3370
|
this.loadSession = async function () {
|
|
3747
3371
|
const data = await LocalStorage.getInstance().getItem('@sequence.session');
|
|
3748
|
-
|
|
3749
3372
|
if (!data || data === '') {
|
|
3750
3373
|
return undefined;
|
|
3751
3374
|
}
|
|
3752
|
-
|
|
3753
3375
|
try {
|
|
3754
3376
|
const session = JSON.parse(data);
|
|
3755
|
-
|
|
3756
3377
|
if (session) {
|
|
3757
3378
|
_this.useSession(session, false);
|
|
3758
3379
|
}
|
|
3759
|
-
|
|
3760
3380
|
return session;
|
|
3761
3381
|
} catch (err) {
|
|
3762
3382
|
logger.warn('loadSession failed, unable to parse session payload from storage.');
|
|
3763
3383
|
return undefined;
|
|
3764
3384
|
}
|
|
3765
3385
|
};
|
|
3766
|
-
|
|
3767
3386
|
this.connect = async function (options) {
|
|
3768
3387
|
if ((options == null ? void 0 : options.refresh) === true) {
|
|
3769
3388
|
_this.disconnect();
|
|
3770
3389
|
}
|
|
3771
|
-
|
|
3772
3390
|
if (_this.isConnected() && (await _this.isSiteConnected(options == null ? void 0 : options.origin)) && !!_this.session && !(options != null && options.authorize) && !(options != null && options.askForEmail)) {
|
|
3773
3391
|
return {
|
|
3774
3392
|
connected: true,
|
|
@@ -3776,13 +3394,11 @@ class Wallet {
|
|
|
3776
3394
|
chainId: ethers.utils.hexlify(await _this.getChainId())
|
|
3777
3395
|
};
|
|
3778
3396
|
}
|
|
3779
|
-
|
|
3780
3397
|
if (options) {
|
|
3781
3398
|
if (options.authorize && (!options.app || options.app === '')) {
|
|
3782
3399
|
throw new Error(`connecting with 'authorize' option also requires 'app' to be set`);
|
|
3783
3400
|
}
|
|
3784
3401
|
}
|
|
3785
|
-
|
|
3786
3402
|
await _this.openWallet(undefined, {
|
|
3787
3403
|
type: 'connect',
|
|
3788
3404
|
options
|
|
@@ -3792,163 +3408,131 @@ class Wallet {
|
|
|
3792
3408
|
connected: false
|
|
3793
3409
|
};
|
|
3794
3410
|
});
|
|
3795
|
-
|
|
3796
3411
|
if (connectDetails.connected) {
|
|
3797
3412
|
if (!!connectDetails.session) {
|
|
3798
3413
|
_this.useSession(connectDetails.session, true);
|
|
3799
|
-
|
|
3800
3414
|
_this.addConnectedSite(options == null ? void 0 : options.origin);
|
|
3801
3415
|
} else {
|
|
3802
3416
|
throw new Error('impossible state, connect response is missing session');
|
|
3803
3417
|
}
|
|
3804
3418
|
}
|
|
3805
|
-
|
|
3806
3419
|
return connectDetails;
|
|
3807
3420
|
};
|
|
3808
|
-
|
|
3809
3421
|
this.authorize = async function (options) {
|
|
3810
3422
|
return _this.connect(_extends({}, options, {
|
|
3811
3423
|
authorize: true
|
|
3812
3424
|
}));
|
|
3813
3425
|
};
|
|
3814
|
-
|
|
3815
3426
|
this.getSession = () => {
|
|
3816
3427
|
if (!this.isConnected()) {
|
|
3817
3428
|
return undefined;
|
|
3818
3429
|
}
|
|
3819
|
-
|
|
3820
3430
|
return this.session;
|
|
3821
3431
|
};
|
|
3822
|
-
|
|
3823
3432
|
this.getAddress = async function () {
|
|
3824
3433
|
if (!_this.isConnected()) {
|
|
3825
3434
|
throw new Error('connect first');
|
|
3826
3435
|
}
|
|
3827
|
-
|
|
3828
3436
|
const session = _this.getSession();
|
|
3829
|
-
|
|
3830
3437
|
return session.accountAddress;
|
|
3831
3438
|
};
|
|
3832
|
-
|
|
3833
3439
|
this.getNetworks = async function (chainId) {
|
|
3834
3440
|
if (!_this.isConnected() || !_this.networks) {
|
|
3835
3441
|
throw new Error('connect first');
|
|
3836
3442
|
}
|
|
3837
|
-
|
|
3838
3443
|
if (chainId) {
|
|
3839
3444
|
// filter list to just the specific chain requested
|
|
3840
3445
|
const network = findNetworkConfig(_this.networks, chainId);
|
|
3841
3446
|
return network ? [network] : [];
|
|
3842
3447
|
}
|
|
3843
|
-
|
|
3844
3448
|
return _this.networks;
|
|
3845
3449
|
};
|
|
3846
|
-
|
|
3847
3450
|
this.getChainId = async function () {
|
|
3848
3451
|
if (!_this.networks || _this.networks.length < 1) {
|
|
3849
3452
|
throw new Error('networks have not been set by session. connect first.');
|
|
3850
3453
|
}
|
|
3851
|
-
|
|
3852
3454
|
const network = _this.networks.find(network => network.isDefaultChain);
|
|
3853
|
-
|
|
3854
3455
|
if (!network) {
|
|
3855
3456
|
throw new Error('networks must have a default chain specified');
|
|
3856
3457
|
}
|
|
3857
|
-
|
|
3858
3458
|
return network.chainId;
|
|
3859
3459
|
};
|
|
3860
|
-
|
|
3861
3460
|
this.getAuthChainId = async function () {
|
|
3862
3461
|
if (!_this.networks || _this.networks.length < 1) {
|
|
3863
3462
|
throw new Error('networks have not been set by session. connect first.');
|
|
3864
3463
|
}
|
|
3865
|
-
|
|
3866
3464
|
const network = _this.networks.find(network => network.isAuthChain);
|
|
3867
|
-
|
|
3868
3465
|
if (!network) {
|
|
3869
3466
|
throw new Error('networks must have an auth chain specified');
|
|
3870
3467
|
}
|
|
3871
|
-
|
|
3872
3468
|
return network.chainId;
|
|
3873
3469
|
};
|
|
3874
|
-
|
|
3875
3470
|
this.openWallet = async function (path, intent, networkId) {
|
|
3876
3471
|
if ((intent == null ? void 0 : intent.type) !== 'connect' && !_this.isConnected()) {
|
|
3877
3472
|
throw new Error('connect first');
|
|
3878
3473
|
}
|
|
3879
|
-
|
|
3880
3474
|
let currentNetworkId;
|
|
3881
|
-
|
|
3882
3475
|
if (!_this.networks || _this.networks.length < 1) {
|
|
3883
3476
|
currentNetworkId = _this.config.defaultNetworkId;
|
|
3884
3477
|
} else {
|
|
3885
3478
|
currentNetworkId = await _this.getChainId();
|
|
3886
3479
|
}
|
|
3887
|
-
|
|
3888
3480
|
_this.transport.messageProvider.openWallet(path, intent, networkId || currentNetworkId);
|
|
3889
|
-
|
|
3890
3481
|
await _this.transport.messageProvider.waitUntilOpened();
|
|
3891
3482
|
return true;
|
|
3892
3483
|
};
|
|
3893
|
-
|
|
3894
3484
|
this.closeWallet = () => {
|
|
3895
3485
|
this.transport.messageProvider.closeWallet();
|
|
3896
3486
|
};
|
|
3897
|
-
|
|
3898
3487
|
this.saveSession = async function (session) {
|
|
3899
3488
|
logger.debug('wallet provider: saving session');
|
|
3900
3489
|
const data = JSON.stringify(session);
|
|
3901
3490
|
await LocalStorage.getInstance().setItem('@sequence.session', data);
|
|
3902
3491
|
};
|
|
3903
|
-
|
|
3904
3492
|
this.useSession = async function (session, autoSave = true) {
|
|
3905
|
-
if (!_this.session) _this.session = {};
|
|
3493
|
+
if (!_this.session) _this.session = {};
|
|
3906
3494
|
|
|
3495
|
+
// setup wallet context
|
|
3907
3496
|
if (_this.config.walletContext) {
|
|
3908
3497
|
_this.session.walletContext = _this.config.walletContext;
|
|
3909
3498
|
} else if (session.walletContext) {
|
|
3910
3499
|
_this.session.walletContext = session.walletContext;
|
|
3911
|
-
}
|
|
3912
|
-
|
|
3500
|
+
}
|
|
3913
3501
|
|
|
3502
|
+
// setup account
|
|
3914
3503
|
if (session.accountAddress) {
|
|
3915
3504
|
_this.useAccountAddress(session.accountAddress);
|
|
3916
|
-
}
|
|
3917
|
-
|
|
3505
|
+
}
|
|
3918
3506
|
|
|
3507
|
+
// setup networks
|
|
3919
3508
|
if (session.networks) {
|
|
3920
3509
|
_this.useNetworks(session.networks);
|
|
3921
|
-
}
|
|
3922
|
-
|
|
3510
|
+
}
|
|
3923
3511
|
|
|
3512
|
+
// setup provider cache
|
|
3924
3513
|
if (session.providerCache) {
|
|
3925
3514
|
_this.transport.cachedProvider.setCache(session.providerCache);
|
|
3926
|
-
}
|
|
3927
|
-
|
|
3515
|
+
}
|
|
3928
3516
|
|
|
3517
|
+
// persist
|
|
3929
3518
|
if (autoSave) {
|
|
3930
3519
|
_this.saveSession(_this.session);
|
|
3931
3520
|
}
|
|
3932
3521
|
};
|
|
3933
|
-
|
|
3934
3522
|
// config is a Partial, so that we may intersect it with the DefaultProviderConfig,
|
|
3935
3523
|
// which allows easy overriding and control of the config.
|
|
3936
3524
|
this.config = _extends({}, DefaultProviderConfig);
|
|
3937
|
-
|
|
3938
3525
|
if (config) {
|
|
3939
3526
|
this.config = _extends({}, this.config, config);
|
|
3940
3527
|
}
|
|
3941
|
-
|
|
3942
3528
|
if (_network) {
|
|
3943
3529
|
this.config.defaultNetworkId = _network;
|
|
3944
3530
|
} else if (!this.config.defaultNetworkId) {
|
|
3945
3531
|
this.config.defaultNetworkId = 'mainnet';
|
|
3946
3532
|
}
|
|
3947
|
-
|
|
3948
3533
|
if (config != null && config.localStorage) {
|
|
3949
3534
|
LocalStorage.use(config.localStorage);
|
|
3950
3535
|
}
|
|
3951
|
-
|
|
3952
3536
|
this.transport = {};
|
|
3953
3537
|
this.networks = [];
|
|
3954
3538
|
this.providers = {};
|
|
@@ -3956,61 +3540,50 @@ class Wallet {
|
|
|
3956
3540
|
this.utils = new WalletUtils(this);
|
|
3957
3541
|
this.init();
|
|
3958
3542
|
}
|
|
3959
|
-
|
|
3960
3543
|
async addConnectedSite(origin) {
|
|
3961
3544
|
origin = origin || window.location.origin;
|
|
3962
3545
|
const connectedSites = await this.connectedSites.get();
|
|
3963
|
-
|
|
3964
3546
|
if (connectedSites) {
|
|
3965
3547
|
if (connectedSites.includes(origin)) {
|
|
3966
3548
|
return;
|
|
3967
3549
|
}
|
|
3968
|
-
|
|
3969
3550
|
this.connectedSites.set([...connectedSites, origin]);
|
|
3970
3551
|
} else {
|
|
3971
3552
|
this.connectedSites.set([origin]);
|
|
3972
3553
|
}
|
|
3973
3554
|
}
|
|
3974
|
-
|
|
3975
3555
|
async removeConnectedSite(origin) {
|
|
3976
3556
|
const authorized = await this.connectedSites.get();
|
|
3977
|
-
|
|
3978
3557
|
if (authorized) {
|
|
3979
3558
|
this.connectedSites.set(authorized.filter(domain => domain !== origin));
|
|
3980
3559
|
}
|
|
3981
3560
|
}
|
|
3982
|
-
|
|
3983
3561
|
getConnectedSites() {
|
|
3984
3562
|
return this.connectedSites.get();
|
|
3985
3563
|
}
|
|
3986
|
-
|
|
3987
3564
|
async isSiteConnected(origin) {
|
|
3988
3565
|
const authorized = await this.connectedSites.get();
|
|
3989
3566
|
return !!authorized && authorized.includes(origin || window.location.origin);
|
|
3990
3567
|
}
|
|
3991
|
-
|
|
3992
3568
|
disconnect() {
|
|
3993
3569
|
if (this.isOpened()) {
|
|
3994
3570
|
this.closeWallet();
|
|
3995
3571
|
}
|
|
3996
|
-
|
|
3997
3572
|
this.clearSession();
|
|
3998
|
-
}
|
|
3999
|
-
// and on successful response, will update the provider info here, etc.
|
|
3573
|
+
}
|
|
4000
3574
|
|
|
3575
|
+
// TODO: add switchNetwork(network: string | number) which will call wallet_switchEthereumChain
|
|
3576
|
+
// and on successful response, will update the provider info here, etc.
|
|
4001
3577
|
|
|
4002
3578
|
getProviderConfig() {
|
|
4003
3579
|
return this.config;
|
|
4004
3580
|
}
|
|
4005
|
-
|
|
4006
3581
|
isOpened() {
|
|
4007
3582
|
return this.transport.messageProvider.isOpened();
|
|
4008
3583
|
}
|
|
4009
|
-
|
|
4010
3584
|
isConnected() {
|
|
4011
3585
|
return this.session !== undefined && this.session.networks !== undefined && this.session.networks.length > 0 && this.networks !== undefined && this.networks.length > 0 && !!this.session.accountAddress && this.session.accountAddress.startsWith('0x');
|
|
4012
3586
|
}
|
|
4013
|
-
|
|
4014
3587
|
getProvider(chainId) {
|
|
4015
3588
|
// return the top-level provider message transport when chainId is unspecified
|
|
4016
3589
|
// and user has not logged in
|
|
@@ -4021,27 +3594,24 @@ class Wallet {
|
|
|
4021
3594
|
return this.transport.provider;
|
|
4022
3595
|
}
|
|
4023
3596
|
}
|
|
4024
|
-
|
|
4025
3597
|
let network = this.networks.find(network => network.isDefaultChain);
|
|
4026
|
-
|
|
4027
3598
|
if (chainId) {
|
|
4028
3599
|
network = findNetworkConfig(this.networks, chainId);
|
|
4029
|
-
|
|
4030
3600
|
if (!network) {
|
|
4031
3601
|
throw new Error(`network ${chainId} is not in the network list`);
|
|
4032
3602
|
}
|
|
4033
|
-
}
|
|
4034
|
-
|
|
3603
|
+
}
|
|
4035
3604
|
|
|
3605
|
+
// return memoized network provider
|
|
4036
3606
|
if (this.providers[network.chainId]) {
|
|
4037
3607
|
return this.providers[network.chainId];
|
|
4038
|
-
}
|
|
4039
|
-
|
|
4040
|
-
|
|
4041
|
-
let provider; // network.provider may be set by the ProviderConfig override
|
|
3608
|
+
}
|
|
4042
3609
|
|
|
4043
|
-
|
|
3610
|
+
// builder web3 provider stack
|
|
3611
|
+
let provider;
|
|
4044
3612
|
|
|
3613
|
+
// network.provider may be set by the ProviderConfig override
|
|
3614
|
+
const rpcProvider = network.provider ? network.provider : new providers.JsonRpcProvider(network.rpcUrl, network.chainId);
|
|
4045
3615
|
if (network.isDefaultChain) {
|
|
4046
3616
|
// communicating with defaultChain will prioritize the wallet message transport
|
|
4047
3617
|
const router = new JsonRpcRouter([loggingProviderMiddleware, exceptionProviderMiddleware, new EagerProvider({
|
|
@@ -4059,103 +3629,88 @@ class Wallet {
|
|
|
4059
3629
|
}), new SigningProvider(this.transport.provider), new CachedProvider(network.chainId)], new JsonRpcSender(rpcProvider));
|
|
4060
3630
|
provider = new Web3Provider(router, network.chainId);
|
|
4061
3631
|
}
|
|
4062
|
-
|
|
4063
3632
|
this.providers[network.chainId] = provider;
|
|
4064
3633
|
return provider;
|
|
4065
3634
|
}
|
|
4066
|
-
|
|
4067
3635
|
async getAuthProvider() {
|
|
4068
3636
|
return this.getProvider((await this.getAuthNetwork()).chainId);
|
|
4069
3637
|
}
|
|
4070
|
-
|
|
4071
3638
|
async getAuthNetwork() {
|
|
4072
3639
|
return (await this.getNetworks()).find(n => n.isAuthChain);
|
|
4073
3640
|
}
|
|
4074
|
-
|
|
4075
3641
|
getAllProviders() {
|
|
4076
3642
|
return this.providers;
|
|
4077
3643
|
}
|
|
4078
|
-
|
|
4079
3644
|
getSigner(chainId) {
|
|
4080
3645
|
return this.getProvider(chainId).getSigner();
|
|
4081
3646
|
}
|
|
4082
|
-
|
|
4083
3647
|
async getAuthSigner() {
|
|
4084
3648
|
return (await this.getAuthProvider()).getSigner();
|
|
4085
3649
|
}
|
|
4086
|
-
|
|
4087
3650
|
getWalletConfig(chainId) {
|
|
4088
3651
|
return this.getSigner().getWalletConfig(chainId);
|
|
4089
3652
|
}
|
|
4090
|
-
|
|
4091
3653
|
getWalletState(chainId) {
|
|
4092
3654
|
return this.getSigner().getWalletState(chainId);
|
|
4093
3655
|
}
|
|
4094
|
-
|
|
4095
3656
|
getWalletContext() {
|
|
4096
3657
|
return this.getSigner().getWalletContext();
|
|
4097
3658
|
}
|
|
4098
|
-
|
|
4099
3659
|
isDeployed(chainId) {
|
|
4100
3660
|
return this.getSigner(chainId).isDeployed();
|
|
4101
3661
|
}
|
|
4102
|
-
|
|
4103
3662
|
on(event, fn) {
|
|
4104
3663
|
this.transport.messageProvider.on(event, fn);
|
|
4105
3664
|
}
|
|
4106
|
-
|
|
4107
3665
|
once(event, fn) {
|
|
4108
3666
|
this.transport.messageProvider.once(event, fn);
|
|
4109
3667
|
}
|
|
4110
|
-
|
|
4111
3668
|
useAccountAddress(accountAddress) {
|
|
4112
3669
|
if (!this.session) this.session = {};
|
|
4113
3670
|
this.session.accountAddress = ethers.utils.getAddress(accountAddress);
|
|
4114
3671
|
}
|
|
4115
|
-
|
|
4116
3672
|
useNetworks(networks) {
|
|
4117
3673
|
// set networks in the session
|
|
4118
|
-
if (!this.session) this.session = {};
|
|
3674
|
+
if (!this.session) this.session = {};
|
|
4119
3675
|
|
|
4120
|
-
|
|
3676
|
+
// set networks on session object
|
|
3677
|
+
this.session.networks = networks;
|
|
4121
3678
|
|
|
3679
|
+
// short-circuit if setting empty network list (aka logged out state)
|
|
4122
3680
|
if (!this.session.networks || this.session.networks.length === 0) {
|
|
4123
3681
|
return;
|
|
4124
|
-
}
|
|
4125
|
-
|
|
3682
|
+
}
|
|
4126
3683
|
|
|
3684
|
+
// check if any custom network settings, otherwise return early
|
|
4127
3685
|
if (!this.config.networks && !this.config.networkRpcUrl) {
|
|
4128
3686
|
this.networks = networks;
|
|
4129
3687
|
return;
|
|
4130
|
-
}
|
|
4131
|
-
|
|
3688
|
+
}
|
|
4132
3689
|
|
|
4133
|
-
|
|
3690
|
+
// init networks
|
|
3691
|
+
this.networks = networks;
|
|
4134
3692
|
|
|
3693
|
+
// combine custom network config with networks in the session
|
|
4135
3694
|
if (this.config.networks) {
|
|
4136
3695
|
this.networks = networks.map(n => _extends({}, n)); // copy
|
|
4137
|
-
|
|
4138
3696
|
this.config.networks.forEach(n => {
|
|
4139
3697
|
const network = findNetworkConfig(this.networks, n.chainId || n.name);
|
|
4140
3698
|
if (!network) return;
|
|
4141
3699
|
updateNetworkConfig(n, network);
|
|
4142
3700
|
});
|
|
4143
3701
|
ensureValidNetworks(this.networks, true);
|
|
4144
|
-
}
|
|
4145
|
-
|
|
3702
|
+
}
|
|
4146
3703
|
|
|
3704
|
+
// an extra override for convenience
|
|
4147
3705
|
if (this.config.networkRpcUrl) {
|
|
4148
3706
|
const network = this.networks.find(network => network.isDefaultChain);
|
|
4149
|
-
|
|
4150
3707
|
if (network) {
|
|
4151
3708
|
network.rpcUrl = this.config.networkRpcUrl;
|
|
4152
3709
|
}
|
|
4153
3710
|
}
|
|
4154
3711
|
}
|
|
4155
|
-
|
|
4156
3712
|
clearSession() {
|
|
4157
3713
|
var _this$transport$cache;
|
|
4158
|
-
|
|
4159
3714
|
logger.debug('wallet provider: clearing session');
|
|
4160
3715
|
LocalStorage.getInstance().removeItem('@sequence.session');
|
|
4161
3716
|
this.session = undefined;
|
|
@@ -4163,11 +3718,11 @@ class Wallet {
|
|
|
4163
3718
|
this.providers = {};
|
|
4164
3719
|
(_this$transport$cache = this.transport.cachedProvider) == null ? void 0 : _this$transport$cache.clearCache();
|
|
4165
3720
|
}
|
|
4166
|
-
|
|
4167
3721
|
}
|
|
4168
3722
|
const DefaultProviderConfig = {
|
|
4169
3723
|
walletAppURL: 'https://sequence.app',
|
|
4170
3724
|
// walletSessionURL: 'https://session.sequence.app',
|
|
3725
|
+
|
|
4171
3726
|
transports: {
|
|
4172
3727
|
windowTransport: {
|
|
4173
3728
|
enabled: true
|
|
@@ -4182,7 +3737,6 @@ const initWallet = async (network, config) => {
|
|
|
4182
3737
|
if (walletInstance && walletInstance.isOpened()) {
|
|
4183
3738
|
walletInstance.closeWallet();
|
|
4184
3739
|
}
|
|
4185
|
-
|
|
4186
3740
|
walletInstance = new Wallet(network, config);
|
|
4187
3741
|
await walletInstance.loadSession();
|
|
4188
3742
|
return walletInstance;
|
|
@@ -4191,7 +3745,6 @@ const getWallet = () => {
|
|
|
4191
3745
|
if (!walletInstance) {
|
|
4192
3746
|
throw new Error('Wallet has not been initialized, call sequence.initWallet(network, config) first.');
|
|
4193
3747
|
}
|
|
4194
|
-
|
|
4195
3748
|
return walletInstance;
|
|
4196
3749
|
};
|
|
4197
3750
|
|