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