@0xsequence/provider 0.0.0-20240703210534 → 0.0.0-20240704152116
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 +647 -665
- package/dist/0xsequence-provider.cjs.prod.js +647 -665
- package/dist/0xsequence-provider.esm.js +651 -669
- package/dist/declarations/src/client.d.ts +3 -7
- package/dist/declarations/src/provider.d.ts +22 -31
- package/dist/declarations/src/signer.d.ts +14 -15
- package/dist/declarations/src/transports/base-provider-transport.d.ts +2 -6
- package/dist/declarations/src/transports/base-wallet-transport.d.ts +2 -6
- package/dist/declarations/src/transports/mux-transport/mux-message-provider.d.ts +2 -5
- package/dist/declarations/src/transports/wallet-request-handler.d.ts +6 -7
- package/dist/declarations/src/types.d.ts +11 -6
- package/dist/declarations/src/utils/index.d.ts +3 -3
- package/dist/declarations/src/utils.d.ts +7 -7
- package/package.json +12 -12
- package/src/client.ts +51 -31
- package/src/eip191exceptions.ts +2 -2
- package/src/extended.ts +5 -5
- package/src/init.ts +10 -9
- package/src/provider.ts +66 -114
- package/src/signer.ts +43 -46
- package/src/transactions.ts +4 -4
- package/src/transports/base-provider-transport.ts +23 -19
- package/src/transports/base-wallet-transport.ts +13 -22
- package/src/transports/mux-transport/mux-message-provider.ts +6 -5
- package/src/transports/proxy-transport/proxy-message-provider.ts +2 -5
- package/src/transports/wallet-request-handler.ts +131 -91
- package/src/transports/window-transport/window-message-handler.ts +3 -17
- package/src/transports/window-transport/window-message-provider.ts +1 -1
- package/src/types.ts +11 -8
- package/src/utils/index.ts +4 -4
- package/src/utils.ts +18 -16
|
@@ -11,7 +11,7 @@ var network = require('@0xsequence/network');
|
|
|
11
11
|
var auth = require('@0xsequence/auth');
|
|
12
12
|
var tracker = require('@databeat/tracker');
|
|
13
13
|
|
|
14
|
-
const PROHIBITED_FUNCTIONS = new Map(['addHook(bytes4,address)', 'clearExtraImageHashes(bytes32[])', 'removeHook(bytes4)', 'setExtraImageHash(bytes32,uint256)', 'updateIPFSRoot(bytes32)', 'updateImageHash(bytes32)', 'updateImageHashAndIPFS(bytes32,bytes32)', 'updateImplementation(address)'].map(signature => [ethers.ethers.keccak256(ethers.ethers.toUtf8Bytes(signature)).slice(0, 10), signature]));
|
|
14
|
+
const PROHIBITED_FUNCTIONS = new Map(['addHook(bytes4,address)', 'clearExtraImageHashes(bytes32[])', 'removeHook(bytes4)', 'setExtraImageHash(bytes32,uint256)', 'updateIPFSRoot(bytes32)', 'updateImageHash(bytes32)', 'updateImageHashAndIPFS(bytes32,bytes32)', 'updateImplementation(address)'].map(signature => [ethers.ethers.utils.keccak256(ethers.ethers.utils.toUtf8Bytes(signature)).slice(0, 10), signature]));
|
|
15
15
|
function validateTransactionRequest(wallet, transaction) {
|
|
16
16
|
const transactions = core.commons.transaction.fromTransactionish(wallet, transaction);
|
|
17
17
|
const unwound = core.commons.transaction.unwind(wallet, transactions);
|
|
@@ -20,7 +20,7 @@ function validateTransactionRequest(wallet, transaction) {
|
|
|
20
20
|
function validateTransaction(wallet, transaction) {
|
|
21
21
|
if (transaction.to.toLowerCase() === wallet.toLowerCase()) {
|
|
22
22
|
if (transaction.data) {
|
|
23
|
-
const data = ethers.ethers.
|
|
23
|
+
const data = ethers.ethers.utils.arrayify(transaction.data);
|
|
24
24
|
if (data.length >= 4 && !isCreateContractCall(data)) {
|
|
25
25
|
throw new Error('self calls are forbidden');
|
|
26
26
|
}
|
|
@@ -30,7 +30,7 @@ function validateTransaction(wallet, transaction) {
|
|
|
30
30
|
throw new Error('delegate calls are forbidden');
|
|
31
31
|
}
|
|
32
32
|
if (transaction.data) {
|
|
33
|
-
const data = ethers.ethers.hexlify(transaction.data);
|
|
33
|
+
const data = ethers.ethers.utils.hexlify(transaction.data);
|
|
34
34
|
const selector = data.slice(0, 10);
|
|
35
35
|
const signature = PROHIBITED_FUNCTIONS.get(selector);
|
|
36
36
|
if (signature) {
|
|
@@ -40,7 +40,7 @@ function validateTransaction(wallet, transaction) {
|
|
|
40
40
|
}
|
|
41
41
|
}
|
|
42
42
|
function isCreateContractCall(data) {
|
|
43
|
-
const walletInterface = new ethers.ethers.Interface(abi.walletContracts.mainModule.abi);
|
|
43
|
+
const walletInterface = new ethers.ethers.utils.Interface(abi.walletContracts.mainModule.abi);
|
|
44
44
|
try {
|
|
45
45
|
walletInterface.decodeFunctionData('createContract', data);
|
|
46
46
|
return true;
|
|
@@ -68,8 +68,6 @@ function isProviderTransport(transport) {
|
|
|
68
68
|
return transport && typeof transport === 'object' && typeof transport.register === 'function' && typeof transport.unregister === 'function' && typeof transport.openWallet === 'function' && typeof transport.closeWallet === 'function' && typeof transport.isOpened === 'function' && typeof transport.isConnected === 'function' && typeof transport.on === 'function';
|
|
69
69
|
}
|
|
70
70
|
|
|
71
|
-
// Older versions of sequence.js will require a JsonRpcResponse result type, but newer versions use raw EIP1193 results
|
|
72
|
-
|
|
73
71
|
// ProviderMessageCallback is used to respond to ProviderMessage requests. The error
|
|
74
72
|
// argument is for exceptions during the execution, and response is the response payload
|
|
75
73
|
// which may contain the result or an error payload from the wallet.
|
|
@@ -127,6 +125,8 @@ const ErrSignedInRequired = new ProviderError('Wallet is not signed in. Connect
|
|
|
127
125
|
|
|
128
126
|
// TODO: lets build some nice error handling tools, prob in /utils ...
|
|
129
127
|
|
|
128
|
+
// This is required by viem, it expects a provider to have an EIP-1193 compliant `request` attribute.
|
|
129
|
+
|
|
130
130
|
const PROVIDER_OPEN_TIMEOUT = 30000; // in ms
|
|
131
131
|
|
|
132
132
|
let _messageIdx = 0;
|
|
@@ -147,6 +147,42 @@ class BaseProviderTransport {
|
|
|
147
147
|
this._sessionId = void 0;
|
|
148
148
|
this._init = void 0;
|
|
149
149
|
this._registered = void 0;
|
|
150
|
+
this.sendAsync = async function (request, callback, chainId) {
|
|
151
|
+
// here, we receive the message from the dapp provider call
|
|
152
|
+
|
|
153
|
+
if (_this.state === OpenState.CLOSED) {
|
|
154
|
+
// flag the wallet to auto-close once user submits input. ie.
|
|
155
|
+
// prompting to sign a message or transaction
|
|
156
|
+
_this.confirmationOnly = true;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
// open/focus the wallet.
|
|
160
|
+
// automatically open the wallet when a provider request makes it here.
|
|
161
|
+
//
|
|
162
|
+
// NOTE: if we're not signed in, then the provider will fail, users must first connect+sign in.
|
|
163
|
+
//
|
|
164
|
+
// TODO: how does this behave with a session has expired?
|
|
165
|
+
_this.openWallet(undefined, {
|
|
166
|
+
type: 'jsonRpcRequest',
|
|
167
|
+
method: request.method
|
|
168
|
+
}, chainId);
|
|
169
|
+
|
|
170
|
+
// send message request, await, and then execute callback after receiving the response
|
|
171
|
+
try {
|
|
172
|
+
if (!_this.isOpened()) {
|
|
173
|
+
await _this.waitUntilOpened(); // will throw on timeout
|
|
174
|
+
}
|
|
175
|
+
const response = await _this.sendMessageRequest({
|
|
176
|
+
idx: nextMessageIdx(),
|
|
177
|
+
type: EventType.MESSAGE,
|
|
178
|
+
data: request,
|
|
179
|
+
chainId: chainId
|
|
180
|
+
});
|
|
181
|
+
callback(undefined, response.data);
|
|
182
|
+
} catch (err) {
|
|
183
|
+
callback(err);
|
|
184
|
+
}
|
|
185
|
+
};
|
|
150
186
|
// sendMessageRequest sends a ProviderMessageRequest over the wire to the wallet
|
|
151
187
|
this.sendMessageRequest = async function (message) {
|
|
152
188
|
return new Promise((resolve, reject) => {
|
|
@@ -256,36 +292,6 @@ class BaseProviderTransport {
|
|
|
256
292
|
const session = (_this$openPayload2 = this.openPayload) == null ? void 0 : _this$openPayload2.session;
|
|
257
293
|
return this.registered && session !== undefined && !!session.accountAddress && session.accountAddress.length === 42 && !!session.networks && session.networks.length > 0;
|
|
258
294
|
}
|
|
259
|
-
async request(request) {
|
|
260
|
-
if (this.state === OpenState.CLOSED) {
|
|
261
|
-
// flag the wallet to auto-close once user submits input. ie.
|
|
262
|
-
// prompting to sign a message or transaction
|
|
263
|
-
this.confirmationOnly = true;
|
|
264
|
-
}
|
|
265
|
-
|
|
266
|
-
// open/focus the wallet.
|
|
267
|
-
// automatically open the wallet when a provider request makes it here.
|
|
268
|
-
//
|
|
269
|
-
// NOTE: if we're not signed in, then the provider will fail, users must first connect+sign in.
|
|
270
|
-
//
|
|
271
|
-
// TODO: how does this behave with a session has expired?
|
|
272
|
-
this.openWallet(undefined, {
|
|
273
|
-
type: 'jsonRpcRequest',
|
|
274
|
-
method: request.method
|
|
275
|
-
}, request.chainId);
|
|
276
|
-
if (!this.isOpened()) {
|
|
277
|
-
await this.waitUntilOpened(); // will throw on timeout
|
|
278
|
-
}
|
|
279
|
-
const response = await this.sendMessageRequest({
|
|
280
|
-
idx: nextMessageIdx(),
|
|
281
|
-
type: EventType.MESSAGE,
|
|
282
|
-
data: request,
|
|
283
|
-
chainId: request.chainId,
|
|
284
|
-
clientVersion: core.VERSION
|
|
285
|
-
});
|
|
286
|
-
return response.data;
|
|
287
|
-
}
|
|
288
|
-
|
|
289
295
|
// handleMessage will handle message received from the remote wallet
|
|
290
296
|
handleMessage(message) {
|
|
291
297
|
var _this2 = this;
|
|
@@ -307,8 +313,7 @@ class BaseProviderTransport {
|
|
|
307
313
|
data: {
|
|
308
314
|
sessionId: this._sessionId,
|
|
309
315
|
nonce: nonce
|
|
310
|
-
}
|
|
311
|
-
clientVersion: core.VERSION
|
|
316
|
+
}
|
|
312
317
|
});
|
|
313
318
|
}
|
|
314
319
|
if (this._init !== InitState.OK) {
|
|
@@ -393,7 +398,7 @@ class BaseProviderTransport {
|
|
|
393
398
|
};
|
|
394
399
|
if (message.data && message.data.length > 0) {
|
|
395
400
|
this.accountsChangedPayload = {
|
|
396
|
-
accounts: [ethers.ethers.getAddress(message.data[0])],
|
|
401
|
+
accounts: [ethers.ethers.utils.getAddress(message.data[0])],
|
|
397
402
|
origin: message.origin
|
|
398
403
|
};
|
|
399
404
|
this.events.emit('accountsChanged', this.accountsChangedPayload.accounts, this.accountsChangedPayload.origin);
|
|
@@ -498,7 +503,7 @@ const EIP_191_PREFIX_EXCEPTIONS = [
|
|
|
498
503
|
const DCL_REGEX = /^Decentraland Login\nEphemeral address: 0x[a-fA-F0-9]{40}\nExpiration: (\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2}(?:\.\d*)?)((-(\d{2}):(\d{2})|Z)?)$/;
|
|
499
504
|
function isDecentralandLoginMessage(bytes) {
|
|
500
505
|
try {
|
|
501
|
-
const stringified = ethers.ethers.toUtf8String(bytes);
|
|
506
|
+
const stringified = ethers.ethers.utils.toUtf8String(bytes);
|
|
502
507
|
return DCL_REGEX.test(stringified);
|
|
503
508
|
} catch (_unused) {
|
|
504
509
|
return false;
|
|
@@ -508,7 +513,7 @@ function isDecentralandLoginMessage(bytes) {
|
|
|
508
513
|
// try to interpret bytes as abi-encoded 0x v3 OrderWithHash -
|
|
509
514
|
// see https://github.com/0xProject/0x-protocol-specification/blob/master/v3/v3-specification.md
|
|
510
515
|
function isZeroExV3Order(bytes) {
|
|
511
|
-
const abi = new ethers.ethers.Interface(ZeroXV3EIP1271OrderWithHashAbi);
|
|
516
|
+
const abi = new ethers.ethers.utils.Interface(ZeroXV3EIP1271OrderWithHashAbi);
|
|
512
517
|
try {
|
|
513
518
|
abi.decodeFunctionData('OrderWithHash', bytes);
|
|
514
519
|
return true;
|
|
@@ -590,19 +595,19 @@ const ZeroXV3EIP1271OrderWithHashAbi = [{
|
|
|
590
595
|
type: 'function'
|
|
591
596
|
}];
|
|
592
597
|
|
|
593
|
-
const eip191prefix = ethers.ethers.toUtf8Bytes('\x19Ethereum Signed Message:\n');
|
|
598
|
+
const eip191prefix = ethers.ethers.utils.toUtf8Bytes('\x19Ethereum Signed Message:\n');
|
|
594
599
|
const messageToBytes = message => {
|
|
595
|
-
if (ethers.ethers.isBytesLike(message)) {
|
|
596
|
-
return ethers.ethers.
|
|
600
|
+
if (ethers.ethers.utils.isBytesLike(message)) {
|
|
601
|
+
return ethers.ethers.utils.arrayify(message);
|
|
597
602
|
}
|
|
598
|
-
return ethers.ethers.toUtf8Bytes(message);
|
|
603
|
+
return ethers.ethers.utils.toUtf8Bytes(message);
|
|
599
604
|
};
|
|
600
605
|
const prefixEIP191Message = message => {
|
|
601
606
|
const messageBytes = messageToBytes(message);
|
|
602
607
|
if (messageIsExemptFromEIP191Prefix(messageBytes)) {
|
|
603
608
|
return messageBytes;
|
|
604
609
|
} else {
|
|
605
|
-
return ethers.ethers.
|
|
610
|
+
return ethers.ethers.utils.concat([eip191prefix, ethers.ethers.utils.toUtf8Bytes(String(messageBytes.length)), messageBytes]);
|
|
606
611
|
}
|
|
607
612
|
};
|
|
608
613
|
const trimEIP191Prefix = prefixedMessage => {
|
|
@@ -627,9 +632,9 @@ const trimEIP191Prefix = prefixedMessage => {
|
|
|
627
632
|
let prefixCharLenght;
|
|
628
633
|
let prefixAsNumber;
|
|
629
634
|
try {
|
|
630
|
-
prefixAsNumber = Number(ethers.ethers.toUtf8String(ethereumSignedMessagePartSlicedArray.slice(0, maxPrefixCharLength)));
|
|
635
|
+
prefixAsNumber = Number(ethers.ethers.utils.toUtf8String(ethereumSignedMessagePartSlicedArray.slice(0, maxPrefixCharLength)));
|
|
631
636
|
} catch (_unused) {
|
|
632
|
-
prefixAsNumber = Number(ethers.ethers.hexlify(ethereumSignedMessagePartSlicedArray.slice(0, maxPrefixCharLength)));
|
|
637
|
+
prefixAsNumber = Number(ethers.ethers.utils.hexlify(ethereumSignedMessagePartSlicedArray.slice(0, maxPrefixCharLength)));
|
|
633
638
|
}
|
|
634
639
|
if (prefixAsNumber > ethereumSignedMessagePartSlicedArray.length || !Number.isInteger(prefixAsNumber)) {
|
|
635
640
|
prefixCharLenght = maxPrefixCharLength - 1;
|
|
@@ -744,9 +749,9 @@ function useBestStore() {
|
|
|
744
749
|
async function resolveArrayProperties(object) {
|
|
745
750
|
if (Array.isArray(object)) {
|
|
746
751
|
// T must include array type
|
|
747
|
-
return Promise.all(object.map(o => ethers.ethers.resolveProperties(o)));
|
|
752
|
+
return Promise.all(object.map(o => ethers.ethers.utils.resolveProperties(o)));
|
|
748
753
|
}
|
|
749
|
-
return ethers.ethers.resolveProperties(object);
|
|
754
|
+
return ethers.ethers.utils.resolveProperties(object);
|
|
750
755
|
}
|
|
751
756
|
|
|
752
757
|
const TRANSPORT_SESSION_LS_KEY = '@sequence.transportSession';
|
|
@@ -763,6 +768,9 @@ class BaseWalletTransport {
|
|
|
763
768
|
// will auto-detect and set this value if it can. This is determined
|
|
764
769
|
// as the parent app/window which opened the wallet.
|
|
765
770
|
this.appOrigin = void 0;
|
|
771
|
+
this.sendAsync = async function (request, callback, chainId) {
|
|
772
|
+
throw new Error('abstract method');
|
|
773
|
+
};
|
|
766
774
|
this.handleMessage = async function (message) {
|
|
767
775
|
const request = message;
|
|
768
776
|
|
|
@@ -998,7 +1006,7 @@ class BaseWalletTransport {
|
|
|
998
1006
|
if (!networks || networks.length === 0) {
|
|
999
1007
|
this.notifyChainChanged('0x0');
|
|
1000
1008
|
} else {
|
|
1001
|
-
this.notifyChainChanged(ethers.ethers.
|
|
1009
|
+
this.notifyChainChanged(ethers.ethers.utils.hexValue(networks.find(network => network.isDefaultChain).chainId));
|
|
1002
1010
|
}
|
|
1003
1011
|
});
|
|
1004
1012
|
this.walletRequestHandler.on('chainChanged', (chainIdHex, origin) => {
|
|
@@ -1022,9 +1030,6 @@ class BaseWalletTransport {
|
|
|
1022
1030
|
unregister() {
|
|
1023
1031
|
throw new Error('abstract method');
|
|
1024
1032
|
}
|
|
1025
|
-
request(request) {
|
|
1026
|
-
throw new Error('abstract method');
|
|
1027
|
-
}
|
|
1028
1033
|
sendMessage(message) {
|
|
1029
1034
|
throw new Error('abstract method');
|
|
1030
1035
|
}
|
|
@@ -1043,8 +1048,7 @@ class BaseWalletTransport {
|
|
|
1043
1048
|
sessionId,
|
|
1044
1049
|
session,
|
|
1045
1050
|
error
|
|
1046
|
-
}
|
|
1047
|
-
clientVersion: core.VERSION
|
|
1051
|
+
}
|
|
1048
1052
|
});
|
|
1049
1053
|
}
|
|
1050
1054
|
notifyClose(error) {
|
|
@@ -1053,16 +1057,14 @@ class BaseWalletTransport {
|
|
|
1053
1057
|
type: EventType.CLOSE,
|
|
1054
1058
|
data: error ? {
|
|
1055
1059
|
error
|
|
1056
|
-
} : null
|
|
1057
|
-
clientVersion: core.VERSION
|
|
1060
|
+
} : null
|
|
1058
1061
|
});
|
|
1059
1062
|
}
|
|
1060
1063
|
notifyConnect(connectDetails) {
|
|
1061
1064
|
this.sendMessage({
|
|
1062
1065
|
idx: -1,
|
|
1063
1066
|
type: EventType.CONNECT,
|
|
1064
|
-
data: connectDetails
|
|
1065
|
-
clientVersion: core.VERSION
|
|
1067
|
+
data: connectDetails
|
|
1066
1068
|
});
|
|
1067
1069
|
}
|
|
1068
1070
|
notifyDisconnect(error, origin) {
|
|
@@ -1072,8 +1074,7 @@ class BaseWalletTransport {
|
|
|
1072
1074
|
data: error ? {
|
|
1073
1075
|
error
|
|
1074
1076
|
} : null,
|
|
1075
|
-
origin
|
|
1076
|
-
clientVersion: core.VERSION
|
|
1077
|
+
origin
|
|
1077
1078
|
});
|
|
1078
1079
|
}
|
|
1079
1080
|
notifyAccountsChanged(accounts, origin) {
|
|
@@ -1081,8 +1082,7 @@ class BaseWalletTransport {
|
|
|
1081
1082
|
idx: -1,
|
|
1082
1083
|
type: EventType.ACCOUNTS_CHANGED,
|
|
1083
1084
|
data: accounts,
|
|
1084
|
-
origin
|
|
1085
|
-
clientVersion: core.VERSION
|
|
1085
|
+
origin
|
|
1086
1086
|
});
|
|
1087
1087
|
}
|
|
1088
1088
|
notifyChainChanged(chainIdHex, origin) {
|
|
@@ -1090,24 +1090,21 @@ class BaseWalletTransport {
|
|
|
1090
1090
|
idx: -1,
|
|
1091
1091
|
type: EventType.CHAIN_CHANGED,
|
|
1092
1092
|
data: chainIdHex,
|
|
1093
|
-
origin
|
|
1094
|
-
clientVersion: core.VERSION
|
|
1093
|
+
origin
|
|
1095
1094
|
});
|
|
1096
1095
|
}
|
|
1097
1096
|
notifyNetworks(networks) {
|
|
1098
1097
|
this.sendMessage({
|
|
1099
1098
|
idx: -1,
|
|
1100
1099
|
type: EventType.NETWORKS,
|
|
1101
|
-
data: networks
|
|
1102
|
-
clientVersion: core.VERSION
|
|
1100
|
+
data: networks
|
|
1103
1101
|
});
|
|
1104
1102
|
}
|
|
1105
1103
|
notifyWalletContext(walletContext) {
|
|
1106
1104
|
this.sendMessage({
|
|
1107
1105
|
idx: -1,
|
|
1108
1106
|
type: EventType.WALLET_CONTEXT,
|
|
1109
|
-
data: walletContext
|
|
1110
|
-
clientVersion: core.VERSION
|
|
1107
|
+
data: walletContext
|
|
1111
1108
|
});
|
|
1112
1109
|
}
|
|
1113
1110
|
isValidInitAck(message) {
|
|
@@ -1178,8 +1175,7 @@ class BaseWalletTransport {
|
|
|
1178
1175
|
type: EventType.INIT,
|
|
1179
1176
|
data: {
|
|
1180
1177
|
nonce: this._initNonce
|
|
1181
|
-
}
|
|
1182
|
-
clientVersion: core.VERSION
|
|
1178
|
+
}
|
|
1183
1179
|
});
|
|
1184
1180
|
this._init = InitState.SENT_NONCE;
|
|
1185
1181
|
|
|
@@ -1278,8 +1274,7 @@ class ProxyMessageProvider extends BaseProviderTransport {
|
|
|
1278
1274
|
intent,
|
|
1279
1275
|
networkId,
|
|
1280
1276
|
sessionId
|
|
1281
|
-
}
|
|
1282
|
-
clientVersion: core.VERSION
|
|
1277
|
+
}
|
|
1283
1278
|
});
|
|
1284
1279
|
}
|
|
1285
1280
|
};
|
|
@@ -1297,8 +1292,7 @@ class ProxyMessageProvider extends BaseProviderTransport {
|
|
|
1297
1292
|
this.sendMessage({
|
|
1298
1293
|
idx: -1,
|
|
1299
1294
|
type: EventType.CLOSE,
|
|
1300
|
-
data: null
|
|
1301
|
-
clientVersion: core.VERSION
|
|
1295
|
+
data: null
|
|
1302
1296
|
});
|
|
1303
1297
|
this.close();
|
|
1304
1298
|
}
|
|
@@ -1886,13 +1880,7 @@ class WindowMessageHandler extends BaseWalletTransport {
|
|
|
1886
1880
|
// Wallet always expects json-rpc request messages from a dapp
|
|
1887
1881
|
let request;
|
|
1888
1882
|
try {
|
|
1889
|
-
request = JSON.parse(event.data
|
|
1890
|
-
// BigNumber compatibility with older versions of sequence.js
|
|
1891
|
-
if (isBigNumberSerialized(value)) {
|
|
1892
|
-
return BigInt(value.hex);
|
|
1893
|
-
}
|
|
1894
|
-
return value;
|
|
1895
|
-
});
|
|
1883
|
+
request = JSON.parse(event.data);
|
|
1896
1884
|
} catch (err) {
|
|
1897
1885
|
// event is not a ProviderMessage JSON object, skip
|
|
1898
1886
|
return;
|
|
@@ -1931,6 +1919,7 @@ class WindowMessageHandler extends BaseWalletTransport {
|
|
|
1931
1919
|
|
|
1932
1920
|
// record open details (sessionId + default network) from the window url
|
|
1933
1921
|
const {
|
|
1922
|
+
pathname,
|
|
1934
1923
|
search: rawParams
|
|
1935
1924
|
} = new URL(windowHref || window.location.href);
|
|
1936
1925
|
let session = this.getWindowTransportSession(rawParams);
|
|
@@ -2014,9 +2003,6 @@ class WindowMessageHandler extends BaseWalletTransport {
|
|
|
2014
2003
|
}
|
|
2015
2004
|
}
|
|
2016
2005
|
}
|
|
2017
|
-
const isBigNumberSerialized = value => {
|
|
2018
|
-
return typeof value === 'object' && 'type' in value && value.type === 'BigNumber' && 'hex' in value && ethers.ethers.isHexString(value.hex);
|
|
2019
|
-
};
|
|
2020
2006
|
|
|
2021
2007
|
function isMuxTransportTemplate(obj) {
|
|
2022
2008
|
return obj && typeof obj === 'object' && (obj.windowTransport && typeof obj.windowTransport === 'object' || obj.proxyTransport && typeof obj.proxyTransport === 'object' || obj.extensionTransport && typeof obj.extensionTransport === 'object' || obj.unrealTransport && typeof obj.unrealTransport === 'object') && (
|
|
@@ -2067,6 +2053,13 @@ class MuxMessageProvider {
|
|
|
2067
2053
|
}
|
|
2068
2054
|
this.messageProviders.forEach(m => m.openWallet(path, intent, networkId));
|
|
2069
2055
|
};
|
|
2056
|
+
this.sendAsync = async function (request, callback, chainId) {
|
|
2057
|
+
if (_this.provider) {
|
|
2058
|
+
_this.provider.sendAsync(request, callback, chainId);
|
|
2059
|
+
return;
|
|
2060
|
+
}
|
|
2061
|
+
throw new Error('impossible state, wallet must be opened first');
|
|
2062
|
+
};
|
|
2070
2063
|
this.sendMessageRequest = async function (message) {
|
|
2071
2064
|
if (_this.provider) {
|
|
2072
2065
|
return _this.provider.sendMessageRequest(message);
|
|
@@ -2163,12 +2156,6 @@ class MuxMessageProvider {
|
|
|
2163
2156
|
}
|
|
2164
2157
|
return true;
|
|
2165
2158
|
}
|
|
2166
|
-
request(request) {
|
|
2167
|
-
if (!this.provider) {
|
|
2168
|
-
throw new Error('impossible state, wallet must be opened first');
|
|
2169
|
-
}
|
|
2170
|
-
return this.provider.request(request);
|
|
2171
|
-
}
|
|
2172
2159
|
sendMessage(message) {
|
|
2173
2160
|
if (!message.idx || message.idx <= 0) {
|
|
2174
2161
|
throw new Error('message idx is empty');
|
|
@@ -2203,7 +2190,7 @@ function fromExtended(transaction) {
|
|
|
2203
2190
|
|
|
2204
2191
|
const SIGNER_READY_TIMEOUT = 10000;
|
|
2205
2192
|
class WalletRequestHandler {
|
|
2206
|
-
constructor(
|
|
2193
|
+
constructor(_account, prompter, networks) {
|
|
2207
2194
|
var _this = this;
|
|
2208
2195
|
// signer interface of the wallet. A null value means there is no signer (ie. user not signed in). An undefined
|
|
2209
2196
|
// value means the signer state is unknown, usually meaning the wallet app is booting up and initializing. Of course
|
|
@@ -2236,6 +2223,417 @@ class WalletRequestHandler {
|
|
|
2236
2223
|
}
|
|
2237
2224
|
return promptConnectDetails;
|
|
2238
2225
|
};
|
|
2226
|
+
// sendAsync implements the JsonRpcHandler interface for sending JsonRpcRequests to the wallet
|
|
2227
|
+
this.sendAsync = async function (request, callback, chainId) {
|
|
2228
|
+
const response = {
|
|
2229
|
+
jsonrpc: '2.0',
|
|
2230
|
+
id: request.id,
|
|
2231
|
+
result: null
|
|
2232
|
+
};
|
|
2233
|
+
await _this.getAccount();
|
|
2234
|
+
try {
|
|
2235
|
+
var _this$account;
|
|
2236
|
+
// only allow public json rpc method to the provider when user is not logged in, aka signer is not set
|
|
2237
|
+
if ((!_this.account || _this.account === null) && !permittedJsonRpcMethods.includes(request.method)) {
|
|
2238
|
+
// throw new Error(`not logged in. ${request.method} is unavailable`)
|
|
2239
|
+
throw ErrSignedInRequired;
|
|
2240
|
+
}
|
|
2241
|
+
|
|
2242
|
+
// wallet account
|
|
2243
|
+
const account = _this.account;
|
|
2244
|
+
if (!account) throw new Error('WalletRequestHandler: wallet account is not configured');
|
|
2245
|
+
|
|
2246
|
+
// fetch the provider for the specific chain, or undefined will select defaultChain
|
|
2247
|
+
const provider = (_this$account = _this.account) == null ? void 0 : _this$account.providerFor(chainId != null ? chainId : _this.defaultChainId());
|
|
2248
|
+
if (!provider) throw new Error(`WalletRequestHandler: wallet provider is not configured for chainId ${chainId}`);
|
|
2249
|
+
const jsonRpcProvider = provider instanceof ethers.ethers.providers.JsonRpcProvider ? provider : undefined;
|
|
2250
|
+
switch (request.method) {
|
|
2251
|
+
case 'net_version':
|
|
2252
|
+
{
|
|
2253
|
+
if (!jsonRpcProvider) {
|
|
2254
|
+
throw new Error(`Account provider doesn't support send method`);
|
|
2255
|
+
}
|
|
2256
|
+
const result = await jsonRpcProvider.send('net_version', []);
|
|
2257
|
+
response.result = result;
|
|
2258
|
+
break;
|
|
2259
|
+
}
|
|
2260
|
+
case 'eth_chainId':
|
|
2261
|
+
{
|
|
2262
|
+
if (!jsonRpcProvider) {
|
|
2263
|
+
throw new Error(`Account provider doesn't support send method`);
|
|
2264
|
+
}
|
|
2265
|
+
const result = await jsonRpcProvider.send('eth_chainId', []);
|
|
2266
|
+
response.result = result;
|
|
2267
|
+
break;
|
|
2268
|
+
}
|
|
2269
|
+
case 'eth_accounts':
|
|
2270
|
+
{
|
|
2271
|
+
const walletAddress = account.address;
|
|
2272
|
+
response.result = [walletAddress];
|
|
2273
|
+
break;
|
|
2274
|
+
}
|
|
2275
|
+
case 'eth_getBalance':
|
|
2276
|
+
{
|
|
2277
|
+
const [accountAddress, blockTag] = request.params;
|
|
2278
|
+
const walletBalance = await provider.getBalance(accountAddress, blockTag);
|
|
2279
|
+
response.result = walletBalance.toHexString();
|
|
2280
|
+
break;
|
|
2281
|
+
}
|
|
2282
|
+
case 'sequence_sign':
|
|
2283
|
+
case 'personal_sign':
|
|
2284
|
+
case 'eth_sign':
|
|
2285
|
+
{
|
|
2286
|
+
// note: message from json-rpc input is in hex format
|
|
2287
|
+
let message;
|
|
2288
|
+
|
|
2289
|
+
// there is a difference in the order of the params:
|
|
2290
|
+
// sequence_sign, personal_sign: [data, address]
|
|
2291
|
+
// eth_sign: [address, data]
|
|
2292
|
+
switch (request.method) {
|
|
2293
|
+
case 'sequence_sign':
|
|
2294
|
+
case 'personal_sign':
|
|
2295
|
+
{
|
|
2296
|
+
const [data, _address] = request.params;
|
|
2297
|
+
message = data;
|
|
2298
|
+
break;
|
|
2299
|
+
}
|
|
2300
|
+
case 'eth_sign':
|
|
2301
|
+
{
|
|
2302
|
+
const [_address, data] = request.params;
|
|
2303
|
+
message = data;
|
|
2304
|
+
break;
|
|
2305
|
+
}
|
|
2306
|
+
}
|
|
2307
|
+
let sig = '';
|
|
2308
|
+
|
|
2309
|
+
// Message must be prefixed with "\x19Ethereum Signed Message:\n"
|
|
2310
|
+
// as defined by EIP-191
|
|
2311
|
+
const prefixedMessage = prefixEIP191Message(message);
|
|
2312
|
+
|
|
2313
|
+
// TODO:
|
|
2314
|
+
// if (process.env.TEST_MODE === 'true' && this.prompter === null) {
|
|
2315
|
+
const sequenceVerified = request.method === 'sequence_sign';
|
|
2316
|
+
if (_this.prompter === null) {
|
|
2317
|
+
// prompter is null, so we'll sign from here
|
|
2318
|
+
sig = await account.signMessage(prefixedMessage, chainId != null ? chainId : _this.defaultChainId(), sequenceVerified ? 'eip6492' : 'ignore');
|
|
2319
|
+
} else {
|
|
2320
|
+
sig = await _this.prompter.promptSignMessage({
|
|
2321
|
+
chainId: chainId,
|
|
2322
|
+
message: prefixedMessage,
|
|
2323
|
+
eip6492: sequenceVerified
|
|
2324
|
+
}, _this.connectOptions);
|
|
2325
|
+
}
|
|
2326
|
+
if (sig && sig.length > 0) {
|
|
2327
|
+
response.result = sig;
|
|
2328
|
+
} else {
|
|
2329
|
+
// The user has declined the request when value is null
|
|
2330
|
+
throw new Error('declined by user');
|
|
2331
|
+
}
|
|
2332
|
+
break;
|
|
2333
|
+
}
|
|
2334
|
+
case 'sequence_signTypedData_v4':
|
|
2335
|
+
case 'eth_signTypedData':
|
|
2336
|
+
case 'eth_signTypedData_v4':
|
|
2337
|
+
{
|
|
2338
|
+
// note: signingAddress from json-rpc input is in hex format, and typedDataObject
|
|
2339
|
+
// should be an object, but in some instances may be double string encoded
|
|
2340
|
+
const [signingAddress, typedDataObject] = request.params;
|
|
2341
|
+
let typedData = undefined;
|
|
2342
|
+
if (typeof typedDataObject === 'string') {
|
|
2343
|
+
try {
|
|
2344
|
+
typedData = JSON.parse(typedDataObject);
|
|
2345
|
+
} catch (e) {
|
|
2346
|
+
console.warn('walletRequestHandler: error parsing typedData', e);
|
|
2347
|
+
}
|
|
2348
|
+
} else {
|
|
2349
|
+
typedData = typedDataObject;
|
|
2350
|
+
}
|
|
2351
|
+
if (!typedData || !typedData.domain || !typedData.types || !typedData.message) {
|
|
2352
|
+
throw new Error('invalid typedData object');
|
|
2353
|
+
}
|
|
2354
|
+
let sig = '';
|
|
2355
|
+
const sequenceVerified = request.method === 'sequence_signTypedData_v4';
|
|
2356
|
+
if (_this.prompter === null) {
|
|
2357
|
+
// prompter is null, so we'll sign from here
|
|
2358
|
+
sig = await account.signTypedData(typedData.domain, typedData.types, typedData.message, chainId != null ? chainId : _this.defaultChainId(), sequenceVerified ? 'eip6492' : 'ignore');
|
|
2359
|
+
} else {
|
|
2360
|
+
sig = await _this.prompter.promptSignMessage({
|
|
2361
|
+
chainId: chainId,
|
|
2362
|
+
typedData: typedData,
|
|
2363
|
+
eip6492: sequenceVerified
|
|
2364
|
+
}, _this.connectOptions);
|
|
2365
|
+
}
|
|
2366
|
+
if (sig && sig.length > 0) {
|
|
2367
|
+
response.result = sig;
|
|
2368
|
+
} else {
|
|
2369
|
+
// The user has declined the request when value is null
|
|
2370
|
+
throw new Error('declined by user');
|
|
2371
|
+
}
|
|
2372
|
+
break;
|
|
2373
|
+
}
|
|
2374
|
+
case 'eth_sendTransaction':
|
|
2375
|
+
{
|
|
2376
|
+
// https://eth.wiki/json-rpc/API#eth_sendtransaction
|
|
2377
|
+
const transactionParams = fromExtended(request.params[0]).map(tx => {
|
|
2378
|
+
// eth_sendTransaction uses 'gas'
|
|
2379
|
+
// ethers and sequence use 'gasLimit'
|
|
2380
|
+
if ('gas' in tx && tx.gasLimit === undefined) {
|
|
2381
|
+
tx.gasLimit = tx.gas;
|
|
2382
|
+
delete tx.gas;
|
|
2383
|
+
}
|
|
2384
|
+
return tx;
|
|
2385
|
+
});
|
|
2386
|
+
validateTransactionRequest(account.address, transactionParams);
|
|
2387
|
+
let txnHash = '';
|
|
2388
|
+
if (_this.prompter === null) {
|
|
2389
|
+
var _txnResponse$hash;
|
|
2390
|
+
// prompter is null, so we'll send from here
|
|
2391
|
+
const txnResponse = await account.sendTransaction(transactionParams, chainId != null ? chainId : _this.defaultChainId());
|
|
2392
|
+
txnHash = (_txnResponse$hash = txnResponse == null ? void 0 : txnResponse.hash) != null ? _txnResponse$hash : '';
|
|
2393
|
+
} else {
|
|
2394
|
+
// prompt user to provide the response
|
|
2395
|
+
txnHash = await _this.prompter.promptSendTransaction(transactionParams, chainId, _this.connectOptions);
|
|
2396
|
+
}
|
|
2397
|
+
if (txnHash) {
|
|
2398
|
+
response.result = txnHash;
|
|
2399
|
+
} else {
|
|
2400
|
+
// The user has declined the request when value is null
|
|
2401
|
+
throw new Error('declined by user');
|
|
2402
|
+
}
|
|
2403
|
+
break;
|
|
2404
|
+
}
|
|
2405
|
+
case 'eth_signTransaction':
|
|
2406
|
+
{
|
|
2407
|
+
// https://eth.wiki/json-rpc/API#eth_signTransaction
|
|
2408
|
+
const [transaction] = request.params;
|
|
2409
|
+
const sender = ethers.ethers.utils.getAddress(transaction.from);
|
|
2410
|
+
if (sender !== account.address) {
|
|
2411
|
+
throw new Error('sender address does not match wallet');
|
|
2412
|
+
}
|
|
2413
|
+
validateTransactionRequest(account.address, transaction);
|
|
2414
|
+
if (_this.prompter === null) {
|
|
2415
|
+
// The eth_signTransaction method expects a `string` return value we instead return a `SignedTransactions` object,
|
|
2416
|
+
// this can only be broadcasted using an RPC provider with support for signed Sequence transactions, like this one.
|
|
2417
|
+
//
|
|
2418
|
+
// TODO: verify serializing / transporting the SignedTransaction object works as expected, most likely however
|
|
2419
|
+
// we will want to resolveProperties the big number values to hex strings
|
|
2420
|
+
response.result = await account.signTransactions(transaction, chainId != null ? chainId : _this.defaultChainId());
|
|
2421
|
+
} else {
|
|
2422
|
+
response.result = await _this.prompter.promptSignTransaction(transaction, chainId, _this.connectOptions);
|
|
2423
|
+
}
|
|
2424
|
+
break;
|
|
2425
|
+
}
|
|
2426
|
+
case 'eth_sendRawTransaction':
|
|
2427
|
+
{
|
|
2428
|
+
// NOTE: we're not using a prompter here as the transaction is already signed
|
|
2429
|
+
// and would have prompted the user upon signing.
|
|
2430
|
+
|
|
2431
|
+
// https://eth.wiki/json-rpc/API#eth_sendRawTransaction
|
|
2432
|
+
if (core.commons.transaction.isSignedTransactionBundle(request.params[0])) {
|
|
2433
|
+
const txChainId = ethers.BigNumber.from(request.params[0].chainId).toNumber();
|
|
2434
|
+
const tx = await account.relayer(txChainId).relay(request.params[0]);
|
|
2435
|
+
response.result = tx.hash;
|
|
2436
|
+
} else {
|
|
2437
|
+
const tx = await provider.sendTransaction(request.params[0]);
|
|
2438
|
+
response.result = tx.hash;
|
|
2439
|
+
}
|
|
2440
|
+
break;
|
|
2441
|
+
}
|
|
2442
|
+
case 'eth_getTransactionCount':
|
|
2443
|
+
{
|
|
2444
|
+
const address = ethers.ethers.utils.getAddress(request.params[0]);
|
|
2445
|
+
const tag = request.params[1];
|
|
2446
|
+
|
|
2447
|
+
// TODO: Maybe we should fetch this data from the relayer or from the reader
|
|
2448
|
+
// but for now we keep it simple and just use the provider
|
|
2449
|
+
|
|
2450
|
+
const count = await provider.getTransactionCount(address, tag);
|
|
2451
|
+
response.result = ethers.ethers.BigNumber.from(count).toHexString();
|
|
2452
|
+
break;
|
|
2453
|
+
}
|
|
2454
|
+
case 'eth_blockNumber':
|
|
2455
|
+
{
|
|
2456
|
+
response.result = await provider.getBlockNumber();
|
|
2457
|
+
break;
|
|
2458
|
+
}
|
|
2459
|
+
case 'eth_getBlockByNumber':
|
|
2460
|
+
{
|
|
2461
|
+
response.result = await provider.getBlock(request.params[0] /* , jsonRpcRequest.params[1] */);
|
|
2462
|
+
break;
|
|
2463
|
+
}
|
|
2464
|
+
case 'eth_getBlockByHash':
|
|
2465
|
+
{
|
|
2466
|
+
response.result = await provider.getBlock(request.params[0] /* , jsonRpcRequest.params[1] */);
|
|
2467
|
+
break;
|
|
2468
|
+
}
|
|
2469
|
+
case 'eth_getTransactionByHash':
|
|
2470
|
+
{
|
|
2471
|
+
response.result = await provider.getTransaction(request.params[0]);
|
|
2472
|
+
break;
|
|
2473
|
+
}
|
|
2474
|
+
case 'eth_call':
|
|
2475
|
+
{
|
|
2476
|
+
const [transactionObject, blockTag] = request.params;
|
|
2477
|
+
response.result = await provider.call(transactionObject, blockTag);
|
|
2478
|
+
break;
|
|
2479
|
+
}
|
|
2480
|
+
case 'eth_getCode':
|
|
2481
|
+
{
|
|
2482
|
+
const [contractAddress, blockTag] = request.params;
|
|
2483
|
+
response.result = await provider.getCode(contractAddress, blockTag);
|
|
2484
|
+
break;
|
|
2485
|
+
}
|
|
2486
|
+
case 'eth_estimateGas':
|
|
2487
|
+
{
|
|
2488
|
+
const [transactionObject] = request.params;
|
|
2489
|
+
response.result = await provider.estimateGas(transactionObject);
|
|
2490
|
+
break;
|
|
2491
|
+
}
|
|
2492
|
+
case 'eth_gasPrice':
|
|
2493
|
+
{
|
|
2494
|
+
const gasPrice = await provider.getGasPrice();
|
|
2495
|
+
response.result = gasPrice.toHexString();
|
|
2496
|
+
break;
|
|
2497
|
+
}
|
|
2498
|
+
case 'wallet_switchEthereumChain':
|
|
2499
|
+
{
|
|
2500
|
+
const [switchParams] = request.params;
|
|
2501
|
+
if (!switchParams.chainId || switchParams.chainId.length === 0) {
|
|
2502
|
+
throw new Error('invalid chainId');
|
|
2503
|
+
}
|
|
2504
|
+
const _chainId = ethers.ethers.BigNumber.from(switchParams.chainId);
|
|
2505
|
+
_this.setDefaultChainId(_chainId.toNumber());
|
|
2506
|
+
response.result = null; // success
|
|
2507
|
+
break;
|
|
2508
|
+
}
|
|
2509
|
+
|
|
2510
|
+
// smart wallet method
|
|
2511
|
+
case 'sequence_getWalletContext':
|
|
2512
|
+
{
|
|
2513
|
+
response.result = account.contexts;
|
|
2514
|
+
break;
|
|
2515
|
+
}
|
|
2516
|
+
|
|
2517
|
+
// smart wallet method
|
|
2518
|
+
case 'sequence_getWalletConfig':
|
|
2519
|
+
{
|
|
2520
|
+
const [_chainId2] = request.params;
|
|
2521
|
+
if (_chainId2) {
|
|
2522
|
+
response.result = [(await account.status(_chainId2)).onChain.config];
|
|
2523
|
+
} else {
|
|
2524
|
+
response.result = await Promise.all(account.networks.map(async function (network) {
|
|
2525
|
+
const status = await account.status(network.chainId);
|
|
2526
|
+
return status.onChain.config;
|
|
2527
|
+
}));
|
|
2528
|
+
}
|
|
2529
|
+
break;
|
|
2530
|
+
}
|
|
2531
|
+
|
|
2532
|
+
// smart wallet method
|
|
2533
|
+
case 'sequence_getWalletState':
|
|
2534
|
+
{
|
|
2535
|
+
const [_chainId3] = request.params;
|
|
2536
|
+
// TODO: Add getWalletState to the Signer interface
|
|
2537
|
+
if (_chainId3) {
|
|
2538
|
+
response.result = [getLegacyWalletState(_chainId3, await account.status(_chainId3))];
|
|
2539
|
+
} else {
|
|
2540
|
+
response.result = await Promise.all(account.networks.map(async function (network) {
|
|
2541
|
+
const status = await account.status(network.chainId);
|
|
2542
|
+
return getLegacyWalletState(network.chainId, status);
|
|
2543
|
+
}));
|
|
2544
|
+
}
|
|
2545
|
+
break;
|
|
2546
|
+
}
|
|
2547
|
+
|
|
2548
|
+
// smart wallet method
|
|
2549
|
+
case 'sequence_getNetworks':
|
|
2550
|
+
{
|
|
2551
|
+
// NOTE: must ensure that the response result below returns clean serialized data, which is to omit
|
|
2552
|
+
// the provider and relayer objects and only return the urls so can be reinstantiated on dapp side.
|
|
2553
|
+
// This is handled by this.getNetworks() but noted here for future readers.
|
|
2554
|
+
response.result = await _this.getNetworks(true);
|
|
2555
|
+
break;
|
|
2556
|
+
}
|
|
2557
|
+
case 'sequence_isSequence':
|
|
2558
|
+
{
|
|
2559
|
+
response.result = true;
|
|
2560
|
+
break;
|
|
2561
|
+
}
|
|
2562
|
+
|
|
2563
|
+
// smart wallet method
|
|
2564
|
+
case 'sequence_updateConfig':
|
|
2565
|
+
{
|
|
2566
|
+
throw new Error('sequence_updateConfig method is not allowed from a dapp');
|
|
2567
|
+
// NOTE: method is disabled as we don't need a dapp to request to update a config.
|
|
2568
|
+
// However, if we ever want this, we can enable it but must also use the prompter
|
|
2569
|
+
// for confirmation.
|
|
2570
|
+
//
|
|
2571
|
+
// const [newConfig] = request.params
|
|
2572
|
+
// response.result = await signer.updateConfig(newConfig)
|
|
2573
|
+
break;
|
|
2574
|
+
}
|
|
2575
|
+
|
|
2576
|
+
// smart wallet method
|
|
2577
|
+
case 'sequence_publishConfig':
|
|
2578
|
+
{
|
|
2579
|
+
throw new Error('sequence_publishConfig method is not allowed from a dapp');
|
|
2580
|
+
break;
|
|
2581
|
+
}
|
|
2582
|
+
|
|
2583
|
+
// relayer method
|
|
2584
|
+
case 'sequence_gasRefundOptions':
|
|
2585
|
+
{
|
|
2586
|
+
// TODO
|
|
2587
|
+
break;
|
|
2588
|
+
}
|
|
2589
|
+
|
|
2590
|
+
// relayer method
|
|
2591
|
+
case 'sequence_getNonce':
|
|
2592
|
+
{
|
|
2593
|
+
// TODO
|
|
2594
|
+
break;
|
|
2595
|
+
}
|
|
2596
|
+
|
|
2597
|
+
// relayer method
|
|
2598
|
+
case 'sequence_relay':
|
|
2599
|
+
{
|
|
2600
|
+
// TODO
|
|
2601
|
+
break;
|
|
2602
|
+
}
|
|
2603
|
+
|
|
2604
|
+
// set default network of wallet
|
|
2605
|
+
case 'sequence_setDefaultNetwork':
|
|
2606
|
+
{
|
|
2607
|
+
const [defaultChainId] = request.params;
|
|
2608
|
+
if (!defaultChainId) {
|
|
2609
|
+
throw new Error('invalid request, method argument defaultChainId cannot be empty');
|
|
2610
|
+
}
|
|
2611
|
+
_this.setDefaultChainId(defaultChainId);
|
|
2612
|
+
response.result = await _this.getNetworks(true);
|
|
2613
|
+
break;
|
|
2614
|
+
}
|
|
2615
|
+
default:
|
|
2616
|
+
{
|
|
2617
|
+
if (!jsonRpcProvider) {
|
|
2618
|
+
throw new Error(`Account provider doesn't support send method`);
|
|
2619
|
+
}
|
|
2620
|
+
|
|
2621
|
+
// NOTE: provider here will be chain-bound if chainId is provided
|
|
2622
|
+
const providerResponse = await jsonRpcProvider.send(request.method, request.params);
|
|
2623
|
+
response.result = providerResponse;
|
|
2624
|
+
}
|
|
2625
|
+
}
|
|
2626
|
+
} catch (err) {
|
|
2627
|
+
utils.logger.error(err);
|
|
2628
|
+
|
|
2629
|
+
// See https://github.com/ethereum/EIPs/blob/master/EIPS/eip-1193.md#rpc-errors
|
|
2630
|
+
response.result = null;
|
|
2631
|
+
response.error = _extends({}, new Error(err), {
|
|
2632
|
+
code: 4001
|
|
2633
|
+
});
|
|
2634
|
+
}
|
|
2635
|
+
callback(undefined, response);
|
|
2636
|
+
};
|
|
2239
2637
|
this.isSignedIn = async function () {
|
|
2240
2638
|
await _this.signerReady();
|
|
2241
2639
|
return !!_this.account;
|
|
@@ -2247,7 +2645,7 @@ class WalletRequestHandler {
|
|
|
2247
2645
|
}
|
|
2248
2646
|
return _this.account;
|
|
2249
2647
|
};
|
|
2250
|
-
this.account =
|
|
2648
|
+
this.account = _account;
|
|
2251
2649
|
this.prompter = prompter;
|
|
2252
2650
|
this.networks = networks;
|
|
2253
2651
|
}
|
|
@@ -2331,7 +2729,7 @@ class WalletRequestHandler {
|
|
|
2331
2729
|
const chainId = network.findSupportedNetwork(networkId).chainId;
|
|
2332
2730
|
const connectDetails = {
|
|
2333
2731
|
connected: true,
|
|
2334
|
-
chainId: ethers.ethers.
|
|
2732
|
+
chainId: ethers.ethers.utils.hexValue(chainId)
|
|
2335
2733
|
};
|
|
2336
2734
|
if (options && options.authorize) {
|
|
2337
2735
|
// Perform ethauth eip712 request and construct the ConnectDetails response
|
|
@@ -2366,414 +2764,20 @@ class WalletRequestHandler {
|
|
|
2366
2764
|
// sendMessageRequest will unwrap the ProviderMessageRequest and send it to the JsonRpcHandler
|
|
2367
2765
|
// (aka, the signer in this instance) and then responds with a wrapped response of
|
|
2368
2766
|
// ProviderMessageResponse to be sent over the transport
|
|
2369
|
-
|
|
2370
|
-
|
|
2371
|
-
|
|
2372
|
-
|
|
2373
|
-
const isJsonRpcResponse = majorVersion < 2;
|
|
2374
|
-
const jsonRpcResponse = {
|
|
2375
|
-
id: message.data.id,
|
|
2376
|
-
jsonrpc: '2.0',
|
|
2377
|
-
result: null,
|
|
2378
|
-
error: undefined
|
|
2379
|
-
};
|
|
2380
|
-
try {
|
|
2381
|
-
const result = await this.request({
|
|
2382
|
-
method: message.data.method,
|
|
2383
|
-
params: message.data.params,
|
|
2384
|
-
chainId: message.chainId
|
|
2385
|
-
});
|
|
2386
|
-
return _extends({}, message, {
|
|
2387
|
-
data: isJsonRpcResponse ? _extends({}, jsonRpcResponse, {
|
|
2388
|
-
result
|
|
2389
|
-
}) : result
|
|
2390
|
-
});
|
|
2391
|
-
} catch (error) {
|
|
2392
|
-
return _extends({}, message, {
|
|
2393
|
-
data: isJsonRpcResponse ? _extends({}, jsonRpcResponse, {
|
|
2394
|
-
error
|
|
2395
|
-
}) : error
|
|
2396
|
-
});
|
|
2397
|
-
}
|
|
2398
|
-
}
|
|
2399
|
-
async request(request) {
|
|
2400
|
-
await this.getAccount();
|
|
2401
|
-
try {
|
|
2402
|
-
var _this$account, _request$chainId;
|
|
2403
|
-
// only allow public json rpc method to the provider when user is not logged in, aka signer is not set
|
|
2404
|
-
if ((!this.account || this.account === null) && !permittedJsonRpcMethods.includes(request.method)) {
|
|
2405
|
-
// throw new Error(`not logged in. ${request.method} is unavailable`)
|
|
2406
|
-
throw ErrSignedInRequired;
|
|
2407
|
-
}
|
|
2408
|
-
|
|
2409
|
-
// wallet account
|
|
2410
|
-
const account = this.account;
|
|
2411
|
-
if (!account) {
|
|
2412
|
-
throw new Error('WalletRequestHandler: wallet account is not configured');
|
|
2413
|
-
}
|
|
2414
|
-
|
|
2415
|
-
// fetch the provider for the specific chain, or undefined will select defaultChain
|
|
2416
|
-
const provider = (_this$account = this.account) == null ? void 0 : _this$account.providerFor((_request$chainId = request.chainId) != null ? _request$chainId : this.defaultChainId());
|
|
2417
|
-
if (!provider) {
|
|
2418
|
-
throw new Error(`WalletRequestHandler: wallet provider is not configured for chainId ${request.chainId}`);
|
|
2419
|
-
}
|
|
2420
|
-
const jsonRpcProvider = provider instanceof ethers.ethers.JsonRpcProvider ? provider : undefined;
|
|
2421
|
-
switch (request.method) {
|
|
2422
|
-
case 'net_version':
|
|
2423
|
-
{
|
|
2424
|
-
if (!jsonRpcProvider) {
|
|
2425
|
-
throw new Error(`Account provider doesn't support send method`);
|
|
2426
|
-
}
|
|
2427
|
-
return await jsonRpcProvider.send('net_version', []);
|
|
2428
|
-
}
|
|
2429
|
-
case 'eth_chainId':
|
|
2430
|
-
{
|
|
2431
|
-
if (!jsonRpcProvider) {
|
|
2432
|
-
throw new Error(`Account provider doesn't support send method`);
|
|
2433
|
-
}
|
|
2434
|
-
return await jsonRpcProvider.send('eth_chainId', []);
|
|
2435
|
-
}
|
|
2436
|
-
case 'eth_accounts':
|
|
2437
|
-
{
|
|
2438
|
-
return [account.address];
|
|
2439
|
-
}
|
|
2440
|
-
case 'eth_getBalance':
|
|
2441
|
-
{
|
|
2442
|
-
const [accountAddress, blockTag] = request.params;
|
|
2443
|
-
const walletBalance = await provider.getBalance(accountAddress, blockTag);
|
|
2444
|
-
return utils.toHexString(walletBalance);
|
|
2445
|
-
}
|
|
2446
|
-
case 'sequence_sign':
|
|
2447
|
-
case 'personal_sign':
|
|
2448
|
-
case 'eth_sign':
|
|
2449
|
-
{
|
|
2450
|
-
// note: message from json-rpc input is in hex format
|
|
2451
|
-
let message;
|
|
2452
|
-
|
|
2453
|
-
// there is a difference in the order of the params:
|
|
2454
|
-
// sequence_sign, personal_sign: [data, address]
|
|
2455
|
-
// eth_sign: [address, data]
|
|
2456
|
-
switch (request.method) {
|
|
2457
|
-
case 'sequence_sign':
|
|
2458
|
-
case 'personal_sign':
|
|
2459
|
-
{
|
|
2460
|
-
const [data, _address] = request.params;
|
|
2461
|
-
message = data;
|
|
2462
|
-
break;
|
|
2463
|
-
}
|
|
2464
|
-
case 'eth_sign':
|
|
2465
|
-
{
|
|
2466
|
-
const [_address, data] = request.params;
|
|
2467
|
-
message = data;
|
|
2468
|
-
break;
|
|
2469
|
-
}
|
|
2470
|
-
}
|
|
2471
|
-
let sig = '';
|
|
2472
|
-
|
|
2473
|
-
// Message must be prefixed with "\x19Ethereum Signed Message:\n"
|
|
2474
|
-
// as defined by EIP-191
|
|
2475
|
-
const prefixedMessage = prefixEIP191Message(message);
|
|
2476
|
-
|
|
2477
|
-
// TODO:
|
|
2478
|
-
// if (process.env.TEST_MODE === 'true' && this.prompter === null) {
|
|
2479
|
-
const sequenceVerified = request.method === 'sequence_sign';
|
|
2480
|
-
if (this.prompter === null) {
|
|
2481
|
-
var _request$chainId2;
|
|
2482
|
-
// prompter is null, so we'll sign from here
|
|
2483
|
-
sig = await account.signMessage(prefixedMessage, (_request$chainId2 = request.chainId) != null ? _request$chainId2 : this.defaultChainId(), sequenceVerified ? 'eip6492' : 'ignore');
|
|
2484
|
-
} else {
|
|
2485
|
-
sig = await this.prompter.promptSignMessage({
|
|
2486
|
-
chainId: request.chainId,
|
|
2487
|
-
message: ethers.ethers.getBytes(prefixedMessage),
|
|
2488
|
-
eip6492: sequenceVerified
|
|
2489
|
-
}, this.connectOptions);
|
|
2490
|
-
}
|
|
2491
|
-
if (sig && sig.length > 0) {
|
|
2492
|
-
return sig;
|
|
2493
|
-
} else {
|
|
2494
|
-
// The user has declined the request when value is null
|
|
2495
|
-
throw new Error('declined by user');
|
|
2496
|
-
}
|
|
2497
|
-
}
|
|
2498
|
-
case 'sequence_signTypedData_v4':
|
|
2499
|
-
case 'eth_signTypedData':
|
|
2500
|
-
case 'eth_signTypedData_v4':
|
|
2501
|
-
{
|
|
2502
|
-
// note: signingAddress from json-rpc input is in hex format, and typedDataObject
|
|
2503
|
-
// should be an object, but in some instances may be double string encoded
|
|
2504
|
-
const [signingAddress, typedDataObject] = request.params;
|
|
2505
|
-
let typedData = undefined;
|
|
2506
|
-
if (typeof typedDataObject === 'string') {
|
|
2507
|
-
try {
|
|
2508
|
-
typedData = JSON.parse(typedDataObject);
|
|
2509
|
-
} catch (e) {
|
|
2510
|
-
console.warn('walletRequestHandler: error parsing typedData', e);
|
|
2511
|
-
}
|
|
2512
|
-
} else {
|
|
2513
|
-
typedData = typedDataObject;
|
|
2514
|
-
}
|
|
2515
|
-
if (!typedData || !typedData.domain || !typedData.types || !typedData.message) {
|
|
2516
|
-
throw new Error('invalid typedData object');
|
|
2517
|
-
}
|
|
2518
|
-
let sig = '';
|
|
2519
|
-
const sequenceVerified = request.method === 'sequence_signTypedData_v4';
|
|
2520
|
-
if (this.prompter === null) {
|
|
2521
|
-
var _request$chainId3;
|
|
2522
|
-
// prompter is null, so we'll sign from here
|
|
2523
|
-
sig = await account.signTypedData(typedData.domain, typedData.types, typedData.message, (_request$chainId3 = request.chainId) != null ? _request$chainId3 : this.defaultChainId(), sequenceVerified ? 'eip6492' : 'ignore');
|
|
2524
|
-
} else {
|
|
2525
|
-
sig = await this.prompter.promptSignMessage({
|
|
2526
|
-
chainId: request.chainId,
|
|
2527
|
-
typedData: typedData,
|
|
2528
|
-
eip6492: sequenceVerified
|
|
2529
|
-
}, this.connectOptions);
|
|
2530
|
-
}
|
|
2531
|
-
if (sig && sig.length > 0) {
|
|
2532
|
-
return sig;
|
|
2533
|
-
} else {
|
|
2534
|
-
// The user has declined the request when value is null
|
|
2535
|
-
throw new Error('declined by user');
|
|
2536
|
-
}
|
|
2537
|
-
}
|
|
2538
|
-
case 'eth_sendTransaction':
|
|
2539
|
-
{
|
|
2540
|
-
// https://eth.wiki/json-rpc/API#eth_sendtransaction
|
|
2541
|
-
const transactionParams = fromExtended(request.params[0]).map(tx => {
|
|
2542
|
-
// eth_sendTransaction uses 'gas'
|
|
2543
|
-
// ethers and sequence use 'gasLimit'
|
|
2544
|
-
if ('gas' in tx && tx.gasLimit === undefined) {
|
|
2545
|
-
tx.gasLimit = tx.gas;
|
|
2546
|
-
delete tx.gas;
|
|
2547
|
-
}
|
|
2548
|
-
return tx;
|
|
2549
|
-
});
|
|
2550
|
-
validateTransactionRequest(account.address, transactionParams);
|
|
2551
|
-
let txnHash = '';
|
|
2552
|
-
if (this.prompter === null) {
|
|
2553
|
-
var _request$chainId4, _txnResponse$hash;
|
|
2554
|
-
// prompter is null, so we'll send from here
|
|
2555
|
-
const txnResponse = await account.sendTransaction(transactionParams, (_request$chainId4 = request.chainId) != null ? _request$chainId4 : this.defaultChainId());
|
|
2556
|
-
txnHash = (_txnResponse$hash = txnResponse == null ? void 0 : txnResponse.hash) != null ? _txnResponse$hash : '';
|
|
2557
|
-
} else {
|
|
2558
|
-
// prompt user to provide the response
|
|
2559
|
-
txnHash = await this.prompter.promptSendTransaction(transactionParams, request.chainId, this.connectOptions);
|
|
2560
|
-
}
|
|
2561
|
-
if (txnHash) {
|
|
2562
|
-
return txnHash;
|
|
2563
|
-
} else {
|
|
2564
|
-
// The user has declined the request when value is null
|
|
2565
|
-
throw new Error('declined by user');
|
|
2566
|
-
}
|
|
2567
|
-
}
|
|
2568
|
-
case 'eth_signTransaction':
|
|
2569
|
-
{
|
|
2570
|
-
// https://eth.wiki/json-rpc/API#eth_signTransaction
|
|
2571
|
-
const [transaction] = request.params;
|
|
2572
|
-
const sender = ethers.ethers.getAddress(transaction.from);
|
|
2573
|
-
if (sender !== account.address) {
|
|
2574
|
-
throw new Error('sender address does not match wallet');
|
|
2575
|
-
}
|
|
2576
|
-
validateTransactionRequest(account.address, transaction);
|
|
2577
|
-
if (this.prompter === null) {
|
|
2578
|
-
var _request$chainId5;
|
|
2579
|
-
// The eth_signTransaction method expects a `string` return value we instead return a `SignedTransactions` object,
|
|
2580
|
-
// this can only be broadcasted using an RPC provider with support for signed Sequence transactions, like this one.
|
|
2581
|
-
//
|
|
2582
|
-
// TODO: verify serializing / transporting the SignedTransaction object works as expected, most likely however
|
|
2583
|
-
// we will want to resolveProperties the big number values to hex strings
|
|
2584
|
-
return await account.signTransactions(transaction, (_request$chainId5 = request.chainId) != null ? _request$chainId5 : this.defaultChainId());
|
|
2585
|
-
} else {
|
|
2586
|
-
return await this.prompter.promptSignTransaction(transaction, request.chainId, this.connectOptions);
|
|
2587
|
-
}
|
|
2588
|
-
}
|
|
2589
|
-
case 'eth_sendRawTransaction':
|
|
2590
|
-
{
|
|
2591
|
-
// NOTE: we're not using a prompter here as the transaction is already signed
|
|
2592
|
-
// and would have prompted the user upon signing.
|
|
2593
|
-
|
|
2594
|
-
// https://eth.wiki/json-rpc/API#eth_sendRawTransaction
|
|
2595
|
-
if (core.commons.transaction.isSignedTransactionBundle(request.params[0])) {
|
|
2596
|
-
const txChainId = Number(BigInt(request.params[0].chainId));
|
|
2597
|
-
const tx = await account.relayer(txChainId).relay(request.params[0]);
|
|
2598
|
-
return tx.hash;
|
|
2599
|
-
} else {
|
|
2600
|
-
const tx = await provider.broadcastTransaction(request.params[0]);
|
|
2601
|
-
return tx.hash;
|
|
2602
|
-
}
|
|
2603
|
-
}
|
|
2604
|
-
case 'eth_getTransactionCount':
|
|
2605
|
-
{
|
|
2606
|
-
const address = ethers.ethers.getAddress(request.params[0]);
|
|
2607
|
-
const tag = request.params[1];
|
|
2608
|
-
|
|
2609
|
-
// TODO: Maybe we should fetch this data from the relayer or from the reader
|
|
2610
|
-
// but for now we keep it simple and just use the provider
|
|
2611
|
-
|
|
2612
|
-
const count = await provider.getTransactionCount(address, tag);
|
|
2613
|
-
return utils.toHexString(BigInt(count));
|
|
2614
|
-
}
|
|
2615
|
-
case 'eth_blockNumber':
|
|
2616
|
-
{
|
|
2617
|
-
return await provider.getBlockNumber();
|
|
2618
|
-
}
|
|
2619
|
-
case 'eth_getBlockByNumber':
|
|
2620
|
-
{
|
|
2621
|
-
return await provider.getBlock(request.params[0] /* , jsonRpcRequest.params[1] */);
|
|
2622
|
-
}
|
|
2623
|
-
case 'eth_getBlockByHash':
|
|
2624
|
-
{
|
|
2625
|
-
return await provider.getBlock(request.params[0] /* , jsonRpcRequest.params[1] */);
|
|
2626
|
-
}
|
|
2627
|
-
case 'eth_getTransactionByHash':
|
|
2628
|
-
{
|
|
2629
|
-
return await provider.getTransaction(request.params[0]);
|
|
2630
|
-
}
|
|
2631
|
-
case 'eth_call':
|
|
2632
|
-
{
|
|
2633
|
-
const [transactionObject, blockTag] = request.params;
|
|
2634
|
-
return await provider.call(_extends({}, transactionObject, {
|
|
2635
|
-
blockTag
|
|
2636
|
-
}));
|
|
2637
|
-
}
|
|
2638
|
-
case 'eth_getCode':
|
|
2639
|
-
{
|
|
2640
|
-
const [contractAddress, blockTag] = request.params;
|
|
2641
|
-
return await provider.getCode(contractAddress, blockTag);
|
|
2642
|
-
}
|
|
2643
|
-
case 'eth_estimateGas':
|
|
2644
|
-
{
|
|
2645
|
-
const [transactionObject] = request.params;
|
|
2646
|
-
return await provider.estimateGas(transactionObject);
|
|
2647
|
-
}
|
|
2648
|
-
case 'eth_gasPrice':
|
|
2649
|
-
{
|
|
2650
|
-
const feeData = await provider.getFeeData();
|
|
2651
|
-
return feeData.gasPrice && utils.toHexString(feeData.gasPrice);
|
|
2652
|
-
}
|
|
2653
|
-
case 'wallet_switchEthereumChain':
|
|
2654
|
-
{
|
|
2655
|
-
const [switchParams] = request.params;
|
|
2656
|
-
if (!switchParams.chainId || switchParams.chainId.length === 0) {
|
|
2657
|
-
throw new Error('invalid chainId');
|
|
2658
|
-
}
|
|
2659
|
-
const chainId = BigInt(switchParams.chainId);
|
|
2660
|
-
this.setDefaultChainId(Number(chainId));
|
|
2661
|
-
return null; // success
|
|
2662
|
-
}
|
|
2663
|
-
|
|
2664
|
-
// smart wallet method
|
|
2665
|
-
case 'sequence_getWalletContext':
|
|
2666
|
-
{
|
|
2667
|
-
return account.contexts;
|
|
2668
|
-
}
|
|
2669
|
-
|
|
2670
|
-
// smart wallet method
|
|
2671
|
-
case 'sequence_getWalletConfig':
|
|
2672
|
-
{
|
|
2673
|
-
const [chainId] = request.params;
|
|
2674
|
-
if (chainId) {
|
|
2675
|
-
return [(await account.status(chainId)).onChain.config];
|
|
2676
|
-
} else {
|
|
2677
|
-
return await Promise.all(account.networks.map(async function (network) {
|
|
2678
|
-
const status = await account.status(network.chainId);
|
|
2679
|
-
return status.onChain.config;
|
|
2680
|
-
}));
|
|
2681
|
-
}
|
|
2682
|
-
}
|
|
2683
|
-
|
|
2684
|
-
// smart wallet method
|
|
2685
|
-
case 'sequence_getWalletState':
|
|
2686
|
-
{
|
|
2687
|
-
const [chainId] = request.params;
|
|
2688
|
-
// TODO: Add getWalletState to the Signer interface
|
|
2689
|
-
if (chainId) {
|
|
2690
|
-
return [getLegacyWalletState(chainId, await account.status(chainId))];
|
|
2691
|
-
} else {
|
|
2692
|
-
return await Promise.all(account.networks.map(async function (network) {
|
|
2693
|
-
const status = await account.status(network.chainId);
|
|
2694
|
-
return getLegacyWalletState(network.chainId, status);
|
|
2695
|
-
}));
|
|
2696
|
-
}
|
|
2697
|
-
}
|
|
2698
|
-
|
|
2699
|
-
// smart wallet method
|
|
2700
|
-
case 'sequence_getNetworks':
|
|
2701
|
-
{
|
|
2702
|
-
// NOTE: must ensure that the response result below returns clean serialized data, which is to omit
|
|
2703
|
-
// the provider and relayer objects and only return the urls so can be reinstantiated on dapp side.
|
|
2704
|
-
// This is handled by this.getNetworks() but noted here for future readers.
|
|
2705
|
-
return await this.getNetworks(true);
|
|
2706
|
-
}
|
|
2707
|
-
case 'sequence_isSequence':
|
|
2708
|
-
{
|
|
2709
|
-
return true;
|
|
2710
|
-
}
|
|
2711
|
-
|
|
2712
|
-
// smart wallet method
|
|
2713
|
-
case 'sequence_updateConfig':
|
|
2714
|
-
{
|
|
2715
|
-
throw new Error('sequence_updateConfig method is not allowed from a dapp');
|
|
2716
|
-
// NOTE: method is disabled as we don't need a dapp to request to update a config.
|
|
2717
|
-
// However, if we ever want this, we can enable it but must also use the prompter
|
|
2718
|
-
// for confirmation.
|
|
2719
|
-
//
|
|
2720
|
-
// const [newConfig] = request.params
|
|
2721
|
-
// return await signer.updateConfig(newConfig)
|
|
2722
|
-
}
|
|
2723
|
-
|
|
2724
|
-
// smart wallet method
|
|
2725
|
-
case 'sequence_publishConfig':
|
|
2726
|
-
{
|
|
2727
|
-
throw new Error('sequence_publishConfig method is not allowed from a dapp');
|
|
2728
|
-
}
|
|
2729
|
-
|
|
2730
|
-
// relayer method
|
|
2731
|
-
case 'sequence_gasRefundOptions':
|
|
2732
|
-
{
|
|
2733
|
-
// TODO
|
|
2734
|
-
break;
|
|
2735
|
-
}
|
|
2736
|
-
|
|
2737
|
-
// relayer method
|
|
2738
|
-
case 'sequence_getNonce':
|
|
2739
|
-
{
|
|
2740
|
-
// TODO
|
|
2741
|
-
break;
|
|
2742
|
-
}
|
|
2743
|
-
|
|
2744
|
-
// relayer method
|
|
2745
|
-
case 'sequence_relay':
|
|
2746
|
-
{
|
|
2747
|
-
// TODO
|
|
2748
|
-
break;
|
|
2749
|
-
}
|
|
2767
|
+
sendMessageRequest(message) {
|
|
2768
|
+
return new Promise(resolve => {
|
|
2769
|
+
this.sendAsync(message.data, (error, response) => {
|
|
2770
|
+
// TODO: if response includes data.error, why do we need a separate error argument here?
|
|
2750
2771
|
|
|
2751
|
-
|
|
2752
|
-
|
|
2753
|
-
|
|
2754
|
-
const [defaultChainId] = request.params;
|
|
2755
|
-
if (!defaultChainId) {
|
|
2756
|
-
throw new Error('invalid request, method argument defaultChainId cannot be empty');
|
|
2757
|
-
}
|
|
2758
|
-
this.setDefaultChainId(defaultChainId);
|
|
2759
|
-
return await this.getNetworks(true);
|
|
2760
|
-
}
|
|
2761
|
-
default:
|
|
2762
|
-
{
|
|
2763
|
-
if (!jsonRpcProvider) {
|
|
2764
|
-
throw new Error(`Account provider doesn't support send method`);
|
|
2765
|
-
}
|
|
2772
|
+
const responseMessage = _extends({}, message, {
|
|
2773
|
+
data: response
|
|
2774
|
+
});
|
|
2766
2775
|
|
|
2767
|
-
|
|
2768
|
-
|
|
2769
|
-
|
|
2770
|
-
}
|
|
2771
|
-
}
|
|
2772
|
-
throw {
|
|
2773
|
-
message: err == null ? void 0 : err.message,
|
|
2774
|
-
code: 4001
|
|
2775
|
-
};
|
|
2776
|
-
}
|
|
2776
|
+
// NOTE: we always resolve here, are the sendAsync call will wrap any exceptions
|
|
2777
|
+
// in the error field of the response to ensure we send back to the user
|
|
2778
|
+
resolve(responseMessage);
|
|
2779
|
+
}, message.chainId);
|
|
2780
|
+
});
|
|
2777
2781
|
}
|
|
2778
2782
|
on(event, fn) {
|
|
2779
2783
|
this.events.on(event, fn);
|
|
@@ -2861,7 +2865,7 @@ class WalletRequestHandler {
|
|
|
2861
2865
|
this.events.emit('disconnect', undefined, origin);
|
|
2862
2866
|
}
|
|
2863
2867
|
notifyChainChanged(chainId, origin) {
|
|
2864
|
-
this.events.emit('chainChanged', ethers.ethers.
|
|
2868
|
+
this.events.emit('chainChanged', ethers.ethers.utils.hexValue(chainId), origin);
|
|
2865
2869
|
}
|
|
2866
2870
|
async notifyNetworks(networks) {
|
|
2867
2871
|
const n = networks || (await this.getNetworks(true));
|
|
@@ -2869,7 +2873,7 @@ class WalletRequestHandler {
|
|
|
2869
2873
|
if (n.length > 0) {
|
|
2870
2874
|
const defaultNetwork = n.find(network => network.chainId === this.defaultChainId());
|
|
2871
2875
|
if (defaultNetwork) {
|
|
2872
|
-
this.events.emit('chainChanged', ethers.ethers.
|
|
2876
|
+
this.events.emit('chainChanged', ethers.ethers.utils.hexValue(defaultNetwork.chainId));
|
|
2873
2877
|
}
|
|
2874
2878
|
} else {
|
|
2875
2879
|
this.events.emit('chainChanged', '0x0');
|
|
@@ -2938,19 +2942,6 @@ function getLegacyWalletState(chainId, status) {
|
|
|
2938
2942
|
}
|
|
2939
2943
|
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'];
|
|
2940
2944
|
|
|
2941
|
-
function _objectWithoutPropertiesLoose(source, excluded) {
|
|
2942
|
-
if (source == null) return {};
|
|
2943
|
-
var target = {};
|
|
2944
|
-
var sourceKeys = Object.keys(source);
|
|
2945
|
-
var key, i;
|
|
2946
|
-
for (i = 0; i < sourceKeys.length; i++) {
|
|
2947
|
-
key = sourceKeys[i];
|
|
2948
|
-
if (excluded.indexOf(key) >= 0) continue;
|
|
2949
|
-
target[key] = source[key];
|
|
2950
|
-
}
|
|
2951
|
-
return target;
|
|
2952
|
-
}
|
|
2953
|
-
|
|
2954
2945
|
class SequenceSigner {
|
|
2955
2946
|
get utils() {
|
|
2956
2947
|
return this.provider.utils;
|
|
@@ -2959,6 +2950,7 @@ class SequenceSigner {
|
|
|
2959
2950
|
this.client = client;
|
|
2960
2951
|
this.provider = provider;
|
|
2961
2952
|
this.singleNetworkSigners = {};
|
|
2953
|
+
this._isSigner = true;
|
|
2962
2954
|
this._isSequenceSigner = true;
|
|
2963
2955
|
}
|
|
2964
2956
|
async getAddress() {
|
|
@@ -3028,19 +3020,12 @@ class SequenceSigner {
|
|
|
3028
3020
|
});
|
|
3029
3021
|
const provider = this.getProvider(chainId);
|
|
3030
3022
|
try {
|
|
3031
|
-
|
|
3032
|
-
|
|
3033
|
-
|
|
3034
|
-
|
|
3035
|
-
|
|
3036
|
-
if (tx !== null) {
|
|
3037
|
-
return resolve(tx);
|
|
3038
|
-
}
|
|
3039
|
-
await provider.once('block', check);
|
|
3040
|
-
};
|
|
3041
|
-
check();
|
|
3023
|
+
return await ethers.ethers.utils.poll(async function () {
|
|
3024
|
+
const tx = await provider.getTransaction(txHash);
|
|
3025
|
+
return tx ? provider._wrapTransaction(tx, txHash) : undefined;
|
|
3026
|
+
}, {
|
|
3027
|
+
onceBlock: provider
|
|
3042
3028
|
});
|
|
3043
|
-
return result;
|
|
3044
3029
|
} catch (err) {
|
|
3045
3030
|
err.transactionHash = txHash;
|
|
3046
3031
|
throw err;
|
|
@@ -3062,12 +3047,15 @@ class SequenceSigner {
|
|
|
3062
3047
|
async estimateGas(transaction, optionals) {
|
|
3063
3048
|
return this.getProvider(optionals == null ? void 0 : optionals.chainId).estimateGas(transaction);
|
|
3064
3049
|
}
|
|
3065
|
-
async call(transaction, optionals) {
|
|
3066
|
-
return this.getProvider(optionals == null ? void 0 : optionals.chainId).call(transaction);
|
|
3050
|
+
async call(transaction, blockTag, optionals) {
|
|
3051
|
+
return this.getProvider(optionals == null ? void 0 : optionals.chainId).call(transaction, blockTag);
|
|
3067
3052
|
}
|
|
3068
3053
|
getChainId() {
|
|
3069
3054
|
return Promise.resolve(this.client.getChainId());
|
|
3070
3055
|
}
|
|
3056
|
+
async getGasPrice(optionals) {
|
|
3057
|
+
return this.getProvider(optionals == null ? void 0 : optionals.chainId).getGasPrice();
|
|
3058
|
+
}
|
|
3071
3059
|
async getFeeData(optionals) {
|
|
3072
3060
|
return this.getProvider(optionals == null ? void 0 : optionals.chainId).getFeeData();
|
|
3073
3061
|
}
|
|
@@ -3075,7 +3063,7 @@ class SequenceSigner {
|
|
|
3075
3063
|
const res = await this.provider.resolveName(name);
|
|
3076
3064
|
|
|
3077
3065
|
// For some reason ethers.Signer expects this to return `string`
|
|
3078
|
-
// but ethers.Provider expects this to return `string | null`.
|
|
3066
|
+
// but ethers.providers.Provider expects this to return `string | null`.
|
|
3079
3067
|
// The signer doesn't have any other source of information, so we'll
|
|
3080
3068
|
// fail if the provider doesn't return a result.
|
|
3081
3069
|
if (res === null) {
|
|
@@ -3086,17 +3074,6 @@ class SequenceSigner {
|
|
|
3086
3074
|
_checkProvider(_operation) {
|
|
3087
3075
|
// We always have a provider, so this is a noop
|
|
3088
3076
|
}
|
|
3089
|
-
|
|
3090
|
-
// populateCall(transaction: ethers.PopulatedTransaction): Promise<ethers.PopulatedTransaction> {
|
|
3091
|
-
// return this.provider.populateCall(transaction)
|
|
3092
|
-
// }
|
|
3093
|
-
|
|
3094
|
-
getNonce(_blockTag) {
|
|
3095
|
-
throw new Error('SequenceSigner does not support getNonce');
|
|
3096
|
-
}
|
|
3097
|
-
populateCall(_transaction) {
|
|
3098
|
-
throw new Error('SequenceSigner does not support populateCall');
|
|
3099
|
-
}
|
|
3100
3077
|
populateTransaction(_transaction) {
|
|
3101
3078
|
throw new Error('SequenceSigner does not support populateTransaction');
|
|
3102
3079
|
}
|
|
@@ -3234,43 +3211,31 @@ class WalletUtils {
|
|
|
3234
3211
|
// recoverAddress()
|
|
3235
3212
|
}
|
|
3236
3213
|
|
|
3237
|
-
|
|
3238
|
-
|
|
3239
|
-
class SequenceProvider extends ethers.ethers.AbstractProvider {
|
|
3240
|
-
constructor(client, providerFor, networks = network.allNetworks, options) {
|
|
3214
|
+
class SequenceProvider extends ethers.ethers.providers.BaseProvider {
|
|
3215
|
+
constructor(client, providerFor, networks = network.allNetworks) {
|
|
3241
3216
|
// We support a lot of networks
|
|
3242
3217
|
// but we start with the default one
|
|
3243
|
-
super(client.getChainId()
|
|
3218
|
+
super(client.getChainId());
|
|
3244
3219
|
|
|
3245
3220
|
// Emit events as defined by EIP-1193
|
|
3246
3221
|
this.client = client;
|
|
3247
3222
|
this.providerFor = providerFor;
|
|
3248
3223
|
this.networks = networks;
|
|
3249
|
-
this.options = options;
|
|
3250
3224
|
this.singleNetworkProviders = {};
|
|
3251
3225
|
this._isSequenceProvider = true;
|
|
3252
3226
|
this.utils = void 0;
|
|
3253
3227
|
this.signer = void 0;
|
|
3254
|
-
this.eip1193EventListeners = new Map();
|
|
3255
3228
|
client.onConnect(details => {
|
|
3256
|
-
|
|
3257
|
-
//this.emit('connect', details)
|
|
3258
|
-
(_this$eip1193EventLis = this.eip1193EventListeners.get('connect')) == null || _this$eip1193EventLis.forEach(listener => listener(details));
|
|
3229
|
+
this.emit('connect', details);
|
|
3259
3230
|
});
|
|
3260
3231
|
client.onDisconnect(error => {
|
|
3261
|
-
|
|
3262
|
-
//this.emit('disconnect', error)
|
|
3263
|
-
(_this$eip1193EventLis2 = this.eip1193EventListeners.get('disconnect')) == null || _this$eip1193EventLis2.forEach(listener => listener(error));
|
|
3232
|
+
this.emit('disconnect', error);
|
|
3264
3233
|
});
|
|
3265
3234
|
client.onDefaultChainIdChanged(chainId => {
|
|
3266
|
-
|
|
3267
|
-
//this.emit('chainChanged', chainId)
|
|
3268
|
-
(_this$eip1193EventLis3 = this.eip1193EventListeners.get('chainChanged')) == null || _this$eip1193EventLis3.forEach(listener => listener(chainId));
|
|
3235
|
+
this.emit('chainChanged', chainId);
|
|
3269
3236
|
});
|
|
3270
3237
|
client.onAccountsChanged(accounts => {
|
|
3271
|
-
|
|
3272
|
-
//this.emit('accountsChanged', accounts)
|
|
3273
|
-
(_this$eip1193EventLis4 = this.eip1193EventListeners.get('accountsChanged')) == null || _this$eip1193EventLis4.forEach(listener => listener(accounts));
|
|
3238
|
+
this.emit('accountsChanged', accounts);
|
|
3274
3239
|
});
|
|
3275
3240
|
|
|
3276
3241
|
// NOTICE: We don't emit 'open' and 'close' events
|
|
@@ -3287,29 +3252,6 @@ class SequenceProvider extends ethers.ethers.AbstractProvider {
|
|
|
3287
3252
|
// Create a utils instance
|
|
3288
3253
|
this.utils = new WalletUtils(this.signer);
|
|
3289
3254
|
}
|
|
3290
|
-
async on(event, listener) {
|
|
3291
|
-
if (EIP1193EventTypes.includes(event)) {
|
|
3292
|
-
const listeners = this.eip1193EventListeners.get(event) || new Set();
|
|
3293
|
-
listeners.add(listener);
|
|
3294
|
-
this.eip1193EventListeners.set(event, listeners);
|
|
3295
|
-
return this;
|
|
3296
|
-
}
|
|
3297
|
-
return super.on(event, listener);
|
|
3298
|
-
}
|
|
3299
|
-
async off(event, listener) {
|
|
3300
|
-
if (EIP1193EventTypes.includes(event)) {
|
|
3301
|
-
const listeners = this.eip1193EventListeners.get(event);
|
|
3302
|
-
if (listeners) {
|
|
3303
|
-
if (listener) {
|
|
3304
|
-
listeners.delete(listener);
|
|
3305
|
-
} else {
|
|
3306
|
-
listeners.clear();
|
|
3307
|
-
}
|
|
3308
|
-
}
|
|
3309
|
-
return this;
|
|
3310
|
-
}
|
|
3311
|
-
return super.off(event, listener);
|
|
3312
|
-
}
|
|
3313
3255
|
getSigner(chainId) {
|
|
3314
3256
|
return this.signer.getSigner(chainId);
|
|
3315
3257
|
}
|
|
@@ -3402,7 +3344,7 @@ class SequenceProvider extends ethers.ethers.AbstractProvider {
|
|
|
3402
3344
|
}
|
|
3403
3345
|
const useChainId = this.toChainId(chainId);
|
|
3404
3346
|
if (!this.singleNetworkProviders[useChainId]) {
|
|
3405
|
-
this.singleNetworkProviders[useChainId] = new SingleNetworkSequenceProvider(this.client, this.providerFor, useChainId
|
|
3347
|
+
this.singleNetworkProviders[useChainId] = new SingleNetworkSequenceProvider(this.client, this.providerFor, useChainId);
|
|
3406
3348
|
}
|
|
3407
3349
|
return this.singleNetworkProviders[useChainId];
|
|
3408
3350
|
}
|
|
@@ -3422,26 +3364,11 @@ class SequenceProvider extends ethers.ethers.AbstractProvider {
|
|
|
3422
3364
|
}
|
|
3423
3365
|
return provider;
|
|
3424
3366
|
}
|
|
3425
|
-
async _perform(req) {
|
|
3426
|
-
var _provider$getRpcReque;
|
|
3427
|
-
const {
|
|
3428
|
-
method
|
|
3429
|
-
} = req,
|
|
3430
|
-
args = _objectWithoutPropertiesLoose(req, _excluded);
|
|
3431
|
-
const provider = await this._getSubprovider();
|
|
3432
|
-
const prepared = (_provider$getRpcReque = provider.getRpcRequest(req)) != null ? _provider$getRpcReque : {
|
|
3433
|
-
method,
|
|
3434
|
-
args: Object.values(args)
|
|
3435
|
-
};
|
|
3436
|
-
if (!prepared) {
|
|
3437
|
-
throw new Error(`Unsupported method ${req.method}`);
|
|
3438
|
-
}
|
|
3439
|
-
return provider.send(prepared.method, prepared.args);
|
|
3440
|
-
}
|
|
3441
3367
|
async perform(method, params) {
|
|
3368
|
+
var _provider$prepareRequ;
|
|
3442
3369
|
// First we check if the method should be handled by the client
|
|
3443
3370
|
if (method === 'eth_chainId') {
|
|
3444
|
-
return ethers.ethers.
|
|
3371
|
+
return ethers.ethers.utils.hexValue(await this.useChainId());
|
|
3445
3372
|
}
|
|
3446
3373
|
if (method === 'eth_accounts') {
|
|
3447
3374
|
return [this.client.getAddress()];
|
|
@@ -3461,15 +3388,17 @@ class SequenceProvider extends ethers.ethers.AbstractProvider {
|
|
|
3461
3388
|
method === 'sequence_sign' || method === 'sequence_signTypedData_v4') {
|
|
3462
3389
|
// We pass the chainId to the client, if we don't pass one
|
|
3463
3390
|
// the client will use its own default chainId
|
|
3464
|
-
return this.client.
|
|
3391
|
+
return this.client.send({
|
|
3465
3392
|
method,
|
|
3466
|
-
params
|
|
3467
|
-
|
|
3468
|
-
});
|
|
3393
|
+
params
|
|
3394
|
+
}, this.getChainId());
|
|
3469
3395
|
}
|
|
3470
|
-
|
|
3471
|
-
|
|
3472
|
-
|
|
3396
|
+
|
|
3397
|
+
// Forward call to the corresponding provider
|
|
3398
|
+
// we use the provided chainId, or the default one provided by the client
|
|
3399
|
+
const provider = await this._getSubprovider();
|
|
3400
|
+
const prepared = (_provider$prepareRequ = provider.prepareRequest(method, params)) != null ? _provider$prepareRequ : [method, params];
|
|
3401
|
+
return provider.send(prepared[0], prepared[1]);
|
|
3473
3402
|
}
|
|
3474
3403
|
send(method, params) {
|
|
3475
3404
|
return this.perform(method, params);
|
|
@@ -3477,18 +3406,14 @@ class SequenceProvider extends ethers.ethers.AbstractProvider {
|
|
|
3477
3406
|
request(request) {
|
|
3478
3407
|
return this.perform(request.method, request.params);
|
|
3479
3408
|
}
|
|
3480
|
-
async
|
|
3409
|
+
async detectNetwork() {
|
|
3481
3410
|
const chainId = this.client.getChainId();
|
|
3482
|
-
const
|
|
3483
|
-
if (!
|
|
3411
|
+
const network$1 = network.findNetworkConfig(this.networks, chainId);
|
|
3412
|
+
if (!network$1) {
|
|
3484
3413
|
throw new Error(`Unknown network ${chainId}`);
|
|
3485
3414
|
}
|
|
3486
|
-
const network$1 = new ethers.ethers.Network(found.name, found.chainId);
|
|
3487
3415
|
return network$1;
|
|
3488
3416
|
}
|
|
3489
|
-
async detectNetwork() {
|
|
3490
|
-
return this._detectNetwork();
|
|
3491
|
-
}
|
|
3492
3417
|
|
|
3493
3418
|
// Override most of the methods, so we add support for an optional chainId
|
|
3494
3419
|
// argument, which is used to select the provider to use.
|
|
@@ -3505,9 +3430,9 @@ class SequenceProvider extends ethers.ethers.AbstractProvider {
|
|
|
3505
3430
|
const provider = await this._getSubprovider(optionals == null ? void 0 : optionals.chainId);
|
|
3506
3431
|
return provider.getBlockNumber();
|
|
3507
3432
|
}
|
|
3508
|
-
async
|
|
3433
|
+
async getGasPrice(optionals) {
|
|
3509
3434
|
const provider = await this._getSubprovider(optionals == null ? void 0 : optionals.chainId);
|
|
3510
|
-
return
|
|
3435
|
+
return provider.getGasPrice();
|
|
3511
3436
|
}
|
|
3512
3437
|
async getBalance(addressOrName, blockTag, optionals) {
|
|
3513
3438
|
const provider = await this._getSubprovider(optionals == null ? void 0 : optionals.chainId);
|
|
@@ -3521,21 +3446,21 @@ class SequenceProvider extends ethers.ethers.AbstractProvider {
|
|
|
3521
3446
|
const provider = await this._getSubprovider(optionals == null ? void 0 : optionals.chainId);
|
|
3522
3447
|
return provider.getCode(addressOrName, blockTag);
|
|
3523
3448
|
}
|
|
3524
|
-
async
|
|
3449
|
+
async getStorageAt(addressOrName, position, blockTag, optionals) {
|
|
3525
3450
|
const provider = await this._getSubprovider(optionals == null ? void 0 : optionals.chainId);
|
|
3526
|
-
return provider.
|
|
3451
|
+
return provider.getStorageAt(addressOrName, position, blockTag);
|
|
3527
3452
|
}
|
|
3528
|
-
async call(transaction, optionals) {
|
|
3453
|
+
async call(transaction, blockTag, optionals) {
|
|
3529
3454
|
const provider = await this._getSubprovider(optionals == null ? void 0 : optionals.chainId);
|
|
3530
|
-
return provider.call(transaction);
|
|
3455
|
+
return provider.call(transaction, blockTag);
|
|
3531
3456
|
}
|
|
3532
3457
|
async estimateGas(transaction, optionals) {
|
|
3533
3458
|
const provider = await this._getSubprovider(optionals == null ? void 0 : optionals.chainId);
|
|
3534
3459
|
return provider.estimateGas(transaction);
|
|
3535
3460
|
}
|
|
3536
|
-
async getBlock(blockHashOrBlockTag,
|
|
3461
|
+
async getBlock(blockHashOrBlockTag, optionals) {
|
|
3537
3462
|
const provider = await this._getSubprovider(optionals == null ? void 0 : optionals.chainId);
|
|
3538
|
-
return provider.getBlock(blockHashOrBlockTag
|
|
3463
|
+
return provider.getBlock(blockHashOrBlockTag);
|
|
3539
3464
|
}
|
|
3540
3465
|
async getTransaction(transactionHash, optionals) {
|
|
3541
3466
|
const provider = await this._getSubprovider(optionals == null ? void 0 : optionals.chainId);
|
|
@@ -3562,7 +3487,7 @@ class SequenceProvider extends ethers.ethers.AbstractProvider {
|
|
|
3562
3487
|
return provider.getResolver(name);
|
|
3563
3488
|
}
|
|
3564
3489
|
async resolveName(name) {
|
|
3565
|
-
if (ethers.ethers.isAddress(await name)) {
|
|
3490
|
+
if (ethers.ethers.utils.isAddress(await name)) {
|
|
3566
3491
|
return name;
|
|
3567
3492
|
}
|
|
3568
3493
|
if (!(await this.supportsENS())) {
|
|
@@ -3595,7 +3520,7 @@ SequenceProvider.is = provider => {
|
|
|
3595
3520
|
};
|
|
3596
3521
|
function normalizeChainId(chainId) {
|
|
3597
3522
|
if (typeof chainId === 'object') return normalizeChainId(chainId.chainId);
|
|
3598
|
-
return
|
|
3523
|
+
return ethers.ethers.BigNumber.from(chainId).toNumber();
|
|
3599
3524
|
}
|
|
3600
3525
|
|
|
3601
3526
|
/**
|
|
@@ -3608,8 +3533,8 @@ function normalizeChainId(chainId) {
|
|
|
3608
3533
|
* NOTICE: These networks won't support ENS unless they are the mainnet.
|
|
3609
3534
|
*/
|
|
3610
3535
|
class SingleNetworkSequenceProvider extends SequenceProvider {
|
|
3611
|
-
constructor(client, providerFor, chainId
|
|
3612
|
-
super(client, providerFor
|
|
3536
|
+
constructor(client, providerFor, chainId) {
|
|
3537
|
+
super(client, providerFor);
|
|
3613
3538
|
this.chainId = chainId;
|
|
3614
3539
|
this._isSingleNetworkSequenceProvider = true;
|
|
3615
3540
|
}
|
|
@@ -3628,12 +3553,11 @@ class SingleNetworkSequenceProvider extends SequenceProvider {
|
|
|
3628
3553
|
}
|
|
3629
3554
|
async getNetwork() {
|
|
3630
3555
|
const networks = await this.client.getNetworks();
|
|
3631
|
-
const
|
|
3632
|
-
if (!
|
|
3556
|
+
const res = network.findNetworkConfig(networks, this.chainId);
|
|
3557
|
+
if (!res) {
|
|
3633
3558
|
throw new Error(`Unsupported network ${this.chainId}`);
|
|
3634
3559
|
}
|
|
3635
|
-
|
|
3636
|
-
return network$1;
|
|
3560
|
+
return res;
|
|
3637
3561
|
}
|
|
3638
3562
|
|
|
3639
3563
|
/**
|
|
@@ -3696,6 +3620,55 @@ const setupAnalytics = (projectAccessKey, server) => {
|
|
|
3696
3620
|
});
|
|
3697
3621
|
};
|
|
3698
3622
|
|
|
3623
|
+
var packageJson = {
|
|
3624
|
+
name: "@0xsequence/provider",
|
|
3625
|
+
version: "0.0.0-20240704152116",
|
|
3626
|
+
description: "provider sub-package for Sequence",
|
|
3627
|
+
repository: "https://github.com/0xsequence/sequence.js/tree/master/packages/provider",
|
|
3628
|
+
source: "src/index.ts",
|
|
3629
|
+
main: "dist/0xsequence-provider.cjs.js",
|
|
3630
|
+
module: "dist/0xsequence-provider.esm.js",
|
|
3631
|
+
author: "Horizon Blockchain Games",
|
|
3632
|
+
license: "Apache-2.0",
|
|
3633
|
+
scripts: {
|
|
3634
|
+
test: "pnpm test:concurrently 'pnpm test:run'",
|
|
3635
|
+
"test:run": "pnpm test:file tests/**/*.spec.ts",
|
|
3636
|
+
"test:file": "NODE_OPTIONS='--import tsx' mocha --timeout 30000",
|
|
3637
|
+
typecheck: "tsc --noEmit",
|
|
3638
|
+
"test:concurrently": "concurrently -k --success first 'pnpm start:hardhat1' 'pnpm start:hardhat2'",
|
|
3639
|
+
"start:hardhat1": "pnpm start:hardhat1:verbose > /dev/null 2>&1",
|
|
3640
|
+
"start:hardhat2": "pnpm start:hardhat2:verbose > /dev/null 2>&1",
|
|
3641
|
+
"start:hardhat1:verbose": "hardhat node --config hardhat1.config.js --hostname 0.0.0.0 --port 9595",
|
|
3642
|
+
"start:hardhat2:verbose": "hardhat node --config hardhat2.config.js --hostname 0.0.0.0 --port 8595"
|
|
3643
|
+
},
|
|
3644
|
+
dependencies: {
|
|
3645
|
+
"@0xsequence/abi": "workspace:*",
|
|
3646
|
+
"@0xsequence/account": "workspace:*",
|
|
3647
|
+
"@0xsequence/auth": "workspace:*",
|
|
3648
|
+
"@0xsequence/core": "workspace:*",
|
|
3649
|
+
"@0xsequence/migration": "workspace:*",
|
|
3650
|
+
"@0xsequence/network": "workspace:*",
|
|
3651
|
+
"@0xsequence/relayer": "workspace:*",
|
|
3652
|
+
"@0xsequence/utils": "workspace:*",
|
|
3653
|
+
"@0xsequence/wallet": "workspace:*",
|
|
3654
|
+
"@databeat/tracker": "^0.9.1",
|
|
3655
|
+
eventemitter2: "^6.4.5",
|
|
3656
|
+
"webextension-polyfill": "^0.10.0"
|
|
3657
|
+
},
|
|
3658
|
+
peerDependencies: {
|
|
3659
|
+
ethers: ">=5.5 < 6"
|
|
3660
|
+
},
|
|
3661
|
+
devDependencies: {
|
|
3662
|
+
"@types/webextension-polyfill": "^0.10.0",
|
|
3663
|
+
ethers: "^5.7.2",
|
|
3664
|
+
hardhat: "^2.20.1"
|
|
3665
|
+
},
|
|
3666
|
+
files: [
|
|
3667
|
+
"src",
|
|
3668
|
+
"dist"
|
|
3669
|
+
]
|
|
3670
|
+
};
|
|
3671
|
+
|
|
3699
3672
|
/**
|
|
3700
3673
|
* This session class is meant to persist the state of the wallet connection
|
|
3701
3674
|
* whitin the dapp. This enables the client to retain the wallet address (and some more)
|
|
@@ -3811,7 +3784,7 @@ class SequenceClient {
|
|
|
3811
3784
|
});
|
|
3812
3785
|
this.transport.on('connect', response => {
|
|
3813
3786
|
var _this$callbacks$conne;
|
|
3814
|
-
const chainIdHex = ethers.ethers.
|
|
3787
|
+
const chainIdHex = ethers.ethers.utils.hexValue(this.getChainId());
|
|
3815
3788
|
(_this$callbacks$conne = this.callbacks.connect) == null || _this$callbacks$conne.forEach(cb => cb(_extends({}, response, {
|
|
3816
3789
|
// Ignore the full connect response
|
|
3817
3790
|
// use the chainId defined locally
|
|
@@ -3847,7 +3820,7 @@ class SequenceClient {
|
|
|
3847
3820
|
// instead we handle it locally, so we listen for changes in the store
|
|
3848
3821
|
this.defaultChainId.onDefaultChainIdChanged(chainId => {
|
|
3849
3822
|
var _this$callbacks$chain2;
|
|
3850
|
-
const chainIdHex = ethers.ethers.
|
|
3823
|
+
const chainIdHex = ethers.ethers.utils.hexValue(chainId);
|
|
3851
3824
|
(_this$callbacks$chain2 = this.callbacks.chainChanged) == null || _this$callbacks$chain2.forEach(cb => cb(chainIdHex));
|
|
3852
3825
|
});
|
|
3853
3826
|
if (options != null && options.projectAccessKey) {
|
|
@@ -3960,7 +3933,7 @@ class SequenceClient {
|
|
|
3960
3933
|
type: 'connect',
|
|
3961
3934
|
options: _extends({}, options, {
|
|
3962
3935
|
networkId: this.getChainId(),
|
|
3963
|
-
clientVersion:
|
|
3936
|
+
clientVersion: packageJson.version
|
|
3964
3937
|
})
|
|
3965
3938
|
});
|
|
3966
3939
|
const connectDetails = await this.transport.waitUntilConnected().catch(error => {
|
|
@@ -3980,7 +3953,7 @@ class SequenceClient {
|
|
|
3980
3953
|
// Normalize chainId into a decimal string
|
|
3981
3954
|
// TODO: Remove this once wallet-webapp returns chainId as a string
|
|
3982
3955
|
if (connectDetails.chainId) {
|
|
3983
|
-
connectDetails.chainId =
|
|
3956
|
+
connectDetails.chainId = ethers.ethers.BigNumber.from(connectDetails.chainId).toString();
|
|
3984
3957
|
}
|
|
3985
3958
|
if (connectDetails.connected) {
|
|
3986
3959
|
var _connectDetails$sessi;
|
|
@@ -4006,17 +3979,33 @@ class SequenceClient {
|
|
|
4006
3979
|
|
|
4007
3980
|
// Higher level API
|
|
4008
3981
|
|
|
4009
|
-
|
|
3982
|
+
// Working with sendAsync is less idiomatic
|
|
3983
|
+
// but transport uses it instead of send, so we wrap it
|
|
3984
|
+
send(request, chainId) {
|
|
4010
3985
|
// Internally when sending requests we use `legacy_sign`
|
|
4011
3986
|
// to avoid the default EIP6492 behavior overriding an explicit
|
|
4012
3987
|
// "legacy sign" request, so we map the method here.
|
|
4013
3988
|
request.method = this.mapSignMethod(request.method);
|
|
4014
|
-
return
|
|
3989
|
+
return new Promise((resolve, reject) => {
|
|
3990
|
+
this.transport.sendAsync(request, (error, response) => {
|
|
3991
|
+
if (error) {
|
|
3992
|
+
reject(error);
|
|
3993
|
+
} else if (response === undefined) {
|
|
3994
|
+
reject(new Error(`Got undefined response for request: ${request}`));
|
|
3995
|
+
} else if (typeof response === 'object' && response.error) {
|
|
3996
|
+
reject(response.error);
|
|
3997
|
+
} else if (typeof response === 'object' && response.result) {
|
|
3998
|
+
resolve(response.result);
|
|
3999
|
+
} else {
|
|
4000
|
+
reject(new Error(`Got invalid response for request: ${request}`));
|
|
4001
|
+
}
|
|
4002
|
+
}, chainId || this.getChainId());
|
|
4003
|
+
});
|
|
4015
4004
|
}
|
|
4016
4005
|
async getNetworks(pull) {
|
|
4017
4006
|
const connectedSession = this.session.connectedSession();
|
|
4018
4007
|
if (pull) {
|
|
4019
|
-
connectedSession.networks = await this.
|
|
4008
|
+
connectedSession.networks = await this.send({
|
|
4020
4009
|
method: 'sequence_getNetworks'
|
|
4021
4010
|
});
|
|
4022
4011
|
this.session.setSession(connectedSession);
|
|
@@ -4073,16 +4062,14 @@ class SequenceClient {
|
|
|
4073
4062
|
}
|
|
4074
4063
|
});
|
|
4075
4064
|
|
|
4076
|
-
//
|
|
4077
|
-
|
|
4078
|
-
message = ethers.ethers.hexlify(typeof message === 'string' ? ethers.ethers.toUtf8Bytes(message) : message);
|
|
4065
|
+
// Serialize a BytesLike or string message into a hex string before sending
|
|
4066
|
+
message = ethers.ethers.utils.hexlify(messageToBytes(message));
|
|
4079
4067
|
|
|
4080
4068
|
// Address is ignored by the wallet webapp
|
|
4081
|
-
return this.
|
|
4069
|
+
return this.send({
|
|
4082
4070
|
method,
|
|
4083
|
-
params: [message, this.getAddress()]
|
|
4084
|
-
|
|
4085
|
-
});
|
|
4071
|
+
params: [message, this.getAddress()]
|
|
4072
|
+
}, options == null ? void 0 : options.chainId);
|
|
4086
4073
|
}
|
|
4087
4074
|
async signTypedData(typedData, options) {
|
|
4088
4075
|
var _this$analytics5;
|
|
@@ -4090,7 +4077,7 @@ class SequenceClient {
|
|
|
4090
4077
|
|
|
4091
4078
|
// TODO: Stop using ethers for this, this is the only place where we use it
|
|
4092
4079
|
// and it makes the client depend on ethers.
|
|
4093
|
-
const encoded = ethers.ethers.
|
|
4080
|
+
const encoded = ethers.ethers.utils._TypedDataEncoder.getPayload(typedData.domain, typedData.types, typedData.message);
|
|
4094
4081
|
|
|
4095
4082
|
// The sign typed data will use one of the following chainIds, in order:
|
|
4096
4083
|
// - The one provided in the options
|
|
@@ -4103,11 +4090,10 @@ class SequenceClient {
|
|
|
4103
4090
|
chainId: `${(options == null ? void 0 : options.chainId) || this.getChainId()}`
|
|
4104
4091
|
}
|
|
4105
4092
|
});
|
|
4106
|
-
return this.
|
|
4093
|
+
return this.send({
|
|
4107
4094
|
method,
|
|
4108
|
-
params: [this.getAddress(), encoded]
|
|
4109
|
-
|
|
4110
|
-
});
|
|
4095
|
+
params: [this.getAddress(), encoded]
|
|
4096
|
+
}, (options == null ? void 0 : options.chainId) || typedData.domain.chainId && ethers.ethers.BigNumber.from(typedData.domain.chainId).toNumber() || this.getChainId());
|
|
4111
4097
|
}
|
|
4112
4098
|
async sendTransaction(tx, options) {
|
|
4113
4099
|
var _this$analytics6;
|
|
@@ -4119,24 +4105,22 @@ class SequenceClient {
|
|
|
4119
4105
|
chainId: `${(options == null ? void 0 : options.chainId) || this.getChainId()}`
|
|
4120
4106
|
}
|
|
4121
4107
|
});
|
|
4122
|
-
return this.
|
|
4108
|
+
return this.send({
|
|
4123
4109
|
method: 'eth_sendTransaction',
|
|
4124
|
-
params: [extendedTxs]
|
|
4125
|
-
|
|
4126
|
-
});
|
|
4110
|
+
params: [extendedTxs]
|
|
4111
|
+
}, options == null ? void 0 : options.chainId);
|
|
4127
4112
|
}
|
|
4128
4113
|
async getWalletContext() {
|
|
4129
|
-
return this.
|
|
4114
|
+
return this.send({
|
|
4130
4115
|
method: 'sequence_getWalletContext'
|
|
4131
4116
|
});
|
|
4132
4117
|
}
|
|
4133
4118
|
async getOnchainWalletConfig(options) {
|
|
4134
4119
|
// NOTICE: sequence_getWalletConfig sends the chainId as a param
|
|
4135
|
-
const res = await this.
|
|
4120
|
+
const res = await this.send({
|
|
4136
4121
|
method: 'sequence_getWalletConfig',
|
|
4137
|
-
params: [(options == null ? void 0 : options.chainId) || this.getChainId()]
|
|
4138
|
-
|
|
4139
|
-
});
|
|
4122
|
+
params: [(options == null ? void 0 : options.chainId) || this.getChainId()]
|
|
4123
|
+
}, options == null ? void 0 : options.chainId);
|
|
4140
4124
|
return Array.isArray(res) ? res[0] : res;
|
|
4141
4125
|
}
|
|
4142
4126
|
|
|
@@ -4215,11 +4199,9 @@ const initWallet = (projectAccessKey, partialConfig) => {
|
|
|
4215
4199
|
if (!rpcUrl) {
|
|
4216
4200
|
throw new Error(`no rpcUrl found for chainId: ${chainId}`);
|
|
4217
4201
|
}
|
|
4218
|
-
|
|
4219
|
-
|
|
4220
|
-
|
|
4221
|
-
cacheTimeout: -1
|
|
4222
|
-
});
|
|
4202
|
+
const baseProvider = new ethers.ethers.providers.JsonRpcProvider(rpcUrl);
|
|
4203
|
+
const router = new network.JsonRpcRouter([network.loggingProviderMiddleware, network.exceptionProviderMiddleware, new network.CachedProvider()], new network.JsonRpcSender(baseProvider));
|
|
4204
|
+
rpcProviders[chainId] = new ethers.ethers.providers.Web3Provider(router, chainId);
|
|
4223
4205
|
}
|
|
4224
4206
|
return rpcProviders[chainId];
|
|
4225
4207
|
};
|