@0xsequence/provider 1.10.15 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/0xsequence-provider.cjs.dev.js +656 -648
- package/dist/0xsequence-provider.cjs.prod.js +656 -648
- package/dist/0xsequence-provider.esm.js +660 -652
- package/dist/declarations/src/client.d.ts +7 -3
- package/dist/declarations/src/provider.d.ts +31 -22
- package/dist/declarations/src/signer.d.ts +15 -14
- package/dist/declarations/src/transports/base-provider-transport.d.ts +6 -2
- package/dist/declarations/src/transports/base-wallet-transport.d.ts +6 -2
- package/dist/declarations/src/transports/mux-transport/mux-message-provider.d.ts +5 -2
- package/dist/declarations/src/transports/wallet-request-handler.d.ts +7 -6
- package/dist/declarations/src/types.d.ts +6 -11
- 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 +29 -51
- package/src/eip191exceptions.ts +2 -2
- package/src/extended.ts +5 -5
- package/src/init.ts +9 -10
- package/src/provider.ts +112 -66
- package/src/signer.ts +38 -43
- package/src/transactions.ts +4 -4
- package/src/transports/base-provider-transport.ts +19 -23
- package/src/transports/base-wallet-transport.ts +22 -13
- package/src/transports/mux-transport/mux-message-provider.ts +5 -6
- package/src/transports/proxy-transport/proxy-message-provider.ts +5 -2
- package/src/transports/wallet-request-handler.ts +91 -130
- package/src/transports/window-transport/window-message-handler.ts +15 -3
- package/src/transports/window-transport/window-message-provider.ts +1 -1
- package/src/types.ts +8 -11
- package/src/utils/index.ts +4 -4
- package/src/utils.ts +16 -18
|
@@ -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.
|
|
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.id(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.getBytes(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.
|
|
33
|
+
const data = ethers.ethers.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.
|
|
43
|
+
const walletInterface = new ethers.ethers.Interface(abi.walletContracts.mainModule.abi);
|
|
44
44
|
try {
|
|
45
45
|
walletInterface.decodeFunctionData('createContract', data);
|
|
46
46
|
return true;
|
|
@@ -68,6 +68,8 @@ 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
|
+
|
|
71
73
|
// ProviderMessageCallback is used to respond to ProviderMessage requests. The error
|
|
72
74
|
// argument is for exceptions during the execution, and response is the response payload
|
|
73
75
|
// which may contain the result or an error payload from the wallet.
|
|
@@ -125,8 +127,6 @@ const ErrSignedInRequired = new ProviderError('Wallet is not signed in. Connect
|
|
|
125
127
|
|
|
126
128
|
// TODO: lets build some nice error handling tools, prob in /utils ...
|
|
127
129
|
|
|
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,42 +147,6 @@ 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
|
-
};
|
|
186
150
|
// sendMessageRequest sends a ProviderMessageRequest over the wire to the wallet
|
|
187
151
|
this.sendMessageRequest = async function (message) {
|
|
188
152
|
return new Promise((resolve, reject) => {
|
|
@@ -292,6 +256,36 @@ class BaseProviderTransport {
|
|
|
292
256
|
const session = (_this$openPayload2 = this.openPayload) == null ? void 0 : _this$openPayload2.session;
|
|
293
257
|
return this.registered && session !== undefined && !!session.accountAddress && session.accountAddress.length === 42 && !!session.networks && session.networks.length > 0;
|
|
294
258
|
}
|
|
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
|
+
|
|
295
289
|
// handleMessage will handle message received from the remote wallet
|
|
296
290
|
handleMessage(message) {
|
|
297
291
|
var _this2 = this;
|
|
@@ -313,7 +307,8 @@ class BaseProviderTransport {
|
|
|
313
307
|
data: {
|
|
314
308
|
sessionId: this._sessionId,
|
|
315
309
|
nonce: nonce
|
|
316
|
-
}
|
|
310
|
+
},
|
|
311
|
+
clientVersion: core.VERSION
|
|
317
312
|
});
|
|
318
313
|
}
|
|
319
314
|
if (this._init !== InitState.OK) {
|
|
@@ -398,7 +393,7 @@ class BaseProviderTransport {
|
|
|
398
393
|
};
|
|
399
394
|
if (message.data && message.data.length > 0) {
|
|
400
395
|
this.accountsChangedPayload = {
|
|
401
|
-
accounts: [ethers.ethers.
|
|
396
|
+
accounts: [ethers.ethers.getAddress(message.data[0])],
|
|
402
397
|
origin: message.origin
|
|
403
398
|
};
|
|
404
399
|
this.events.emit('accountsChanged', this.accountsChangedPayload.accounts, this.accountsChangedPayload.origin);
|
|
@@ -503,7 +498,7 @@ const EIP_191_PREFIX_EXCEPTIONS = [
|
|
|
503
498
|
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)?)$/;
|
|
504
499
|
function isDecentralandLoginMessage(bytes) {
|
|
505
500
|
try {
|
|
506
|
-
const stringified = ethers.ethers.
|
|
501
|
+
const stringified = ethers.ethers.toUtf8String(bytes);
|
|
507
502
|
return DCL_REGEX.test(stringified);
|
|
508
503
|
} catch (_unused) {
|
|
509
504
|
return false;
|
|
@@ -513,7 +508,7 @@ function isDecentralandLoginMessage(bytes) {
|
|
|
513
508
|
// try to interpret bytes as abi-encoded 0x v3 OrderWithHash -
|
|
514
509
|
// see https://github.com/0xProject/0x-protocol-specification/blob/master/v3/v3-specification.md
|
|
515
510
|
function isZeroExV3Order(bytes) {
|
|
516
|
-
const abi = new ethers.ethers.
|
|
511
|
+
const abi = new ethers.ethers.Interface(ZeroXV3EIP1271OrderWithHashAbi);
|
|
517
512
|
try {
|
|
518
513
|
abi.decodeFunctionData('OrderWithHash', bytes);
|
|
519
514
|
return true;
|
|
@@ -595,19 +590,19 @@ const ZeroXV3EIP1271OrderWithHashAbi = [{
|
|
|
595
590
|
type: 'function'
|
|
596
591
|
}];
|
|
597
592
|
|
|
598
|
-
const eip191prefix = ethers.ethers.
|
|
593
|
+
const eip191prefix = ethers.ethers.toUtf8Bytes('\x19Ethereum Signed Message:\n');
|
|
599
594
|
const messageToBytes = message => {
|
|
600
|
-
if (ethers.ethers.
|
|
601
|
-
return ethers.ethers.
|
|
595
|
+
if (ethers.ethers.isBytesLike(message)) {
|
|
596
|
+
return ethers.ethers.getBytes(message);
|
|
602
597
|
}
|
|
603
|
-
return ethers.ethers.
|
|
598
|
+
return ethers.ethers.toUtf8Bytes(message);
|
|
604
599
|
};
|
|
605
600
|
const prefixEIP191Message = message => {
|
|
606
601
|
const messageBytes = messageToBytes(message);
|
|
607
602
|
if (messageIsExemptFromEIP191Prefix(messageBytes)) {
|
|
608
603
|
return messageBytes;
|
|
609
604
|
} else {
|
|
610
|
-
return ethers.ethers.
|
|
605
|
+
return ethers.ethers.getBytes(ethers.ethers.concat([eip191prefix, ethers.ethers.toUtf8Bytes(String(messageBytes.length)), messageBytes]));
|
|
611
606
|
}
|
|
612
607
|
};
|
|
613
608
|
const trimEIP191Prefix = prefixedMessage => {
|
|
@@ -632,9 +627,9 @@ const trimEIP191Prefix = prefixedMessage => {
|
|
|
632
627
|
let prefixCharLenght;
|
|
633
628
|
let prefixAsNumber;
|
|
634
629
|
try {
|
|
635
|
-
prefixAsNumber = Number(ethers.ethers.
|
|
630
|
+
prefixAsNumber = Number(ethers.ethers.toUtf8String(ethereumSignedMessagePartSlicedArray.slice(0, maxPrefixCharLength)));
|
|
636
631
|
} catch (_unused) {
|
|
637
|
-
prefixAsNumber = Number(ethers.ethers.
|
|
632
|
+
prefixAsNumber = Number(ethers.ethers.hexlify(ethereumSignedMessagePartSlicedArray.slice(0, maxPrefixCharLength)));
|
|
638
633
|
}
|
|
639
634
|
if (prefixAsNumber > ethereumSignedMessagePartSlicedArray.length || !Number.isInteger(prefixAsNumber)) {
|
|
640
635
|
prefixCharLenght = maxPrefixCharLength - 1;
|
|
@@ -749,9 +744,9 @@ function useBestStore() {
|
|
|
749
744
|
async function resolveArrayProperties(object) {
|
|
750
745
|
if (Array.isArray(object)) {
|
|
751
746
|
// T must include array type
|
|
752
|
-
return Promise.all(object.map(o => ethers.ethers.
|
|
747
|
+
return Promise.all(object.map(o => ethers.ethers.resolveProperties(o)));
|
|
753
748
|
}
|
|
754
|
-
return ethers.ethers.
|
|
749
|
+
return ethers.ethers.resolveProperties(object);
|
|
755
750
|
}
|
|
756
751
|
|
|
757
752
|
const TRANSPORT_SESSION_LS_KEY = '@sequence.transportSession';
|
|
@@ -768,9 +763,6 @@ class BaseWalletTransport {
|
|
|
768
763
|
// will auto-detect and set this value if it can. This is determined
|
|
769
764
|
// as the parent app/window which opened the wallet.
|
|
770
765
|
this.appOrigin = void 0;
|
|
771
|
-
this.sendAsync = async function (request, callback, chainId) {
|
|
772
|
-
throw new Error('abstract method');
|
|
773
|
-
};
|
|
774
766
|
this.handleMessage = async function (message) {
|
|
775
767
|
const request = message;
|
|
776
768
|
|
|
@@ -1006,7 +998,7 @@ class BaseWalletTransport {
|
|
|
1006
998
|
if (!networks || networks.length === 0) {
|
|
1007
999
|
this.notifyChainChanged('0x0');
|
|
1008
1000
|
} else {
|
|
1009
|
-
this.notifyChainChanged(ethers.ethers.
|
|
1001
|
+
this.notifyChainChanged(ethers.ethers.toQuantity(networks.find(network => network.isDefaultChain).chainId));
|
|
1010
1002
|
}
|
|
1011
1003
|
});
|
|
1012
1004
|
this.walletRequestHandler.on('chainChanged', (chainIdHex, origin) => {
|
|
@@ -1030,6 +1022,9 @@ class BaseWalletTransport {
|
|
|
1030
1022
|
unregister() {
|
|
1031
1023
|
throw new Error('abstract method');
|
|
1032
1024
|
}
|
|
1025
|
+
request(request) {
|
|
1026
|
+
throw new Error('abstract method');
|
|
1027
|
+
}
|
|
1033
1028
|
sendMessage(message) {
|
|
1034
1029
|
throw new Error('abstract method');
|
|
1035
1030
|
}
|
|
@@ -1048,7 +1043,8 @@ class BaseWalletTransport {
|
|
|
1048
1043
|
sessionId,
|
|
1049
1044
|
session,
|
|
1050
1045
|
error
|
|
1051
|
-
}
|
|
1046
|
+
},
|
|
1047
|
+
clientVersion: core.VERSION
|
|
1052
1048
|
});
|
|
1053
1049
|
}
|
|
1054
1050
|
notifyClose(error) {
|
|
@@ -1057,14 +1053,16 @@ class BaseWalletTransport {
|
|
|
1057
1053
|
type: EventType.CLOSE,
|
|
1058
1054
|
data: error ? {
|
|
1059
1055
|
error
|
|
1060
|
-
} : null
|
|
1056
|
+
} : null,
|
|
1057
|
+
clientVersion: core.VERSION
|
|
1061
1058
|
});
|
|
1062
1059
|
}
|
|
1063
1060
|
notifyConnect(connectDetails) {
|
|
1064
1061
|
this.sendMessage({
|
|
1065
1062
|
idx: -1,
|
|
1066
1063
|
type: EventType.CONNECT,
|
|
1067
|
-
data: connectDetails
|
|
1064
|
+
data: connectDetails,
|
|
1065
|
+
clientVersion: core.VERSION
|
|
1068
1066
|
});
|
|
1069
1067
|
}
|
|
1070
1068
|
notifyDisconnect(error, origin) {
|
|
@@ -1074,7 +1072,8 @@ class BaseWalletTransport {
|
|
|
1074
1072
|
data: error ? {
|
|
1075
1073
|
error
|
|
1076
1074
|
} : null,
|
|
1077
|
-
origin
|
|
1075
|
+
origin,
|
|
1076
|
+
clientVersion: core.VERSION
|
|
1078
1077
|
});
|
|
1079
1078
|
}
|
|
1080
1079
|
notifyAccountsChanged(accounts, origin) {
|
|
@@ -1082,7 +1081,8 @@ class BaseWalletTransport {
|
|
|
1082
1081
|
idx: -1,
|
|
1083
1082
|
type: EventType.ACCOUNTS_CHANGED,
|
|
1084
1083
|
data: accounts,
|
|
1085
|
-
origin
|
|
1084
|
+
origin,
|
|
1085
|
+
clientVersion: core.VERSION
|
|
1086
1086
|
});
|
|
1087
1087
|
}
|
|
1088
1088
|
notifyChainChanged(chainIdHex, origin) {
|
|
@@ -1090,21 +1090,24 @@ class BaseWalletTransport {
|
|
|
1090
1090
|
idx: -1,
|
|
1091
1091
|
type: EventType.CHAIN_CHANGED,
|
|
1092
1092
|
data: chainIdHex,
|
|
1093
|
-
origin
|
|
1093
|
+
origin,
|
|
1094
|
+
clientVersion: core.VERSION
|
|
1094
1095
|
});
|
|
1095
1096
|
}
|
|
1096
1097
|
notifyNetworks(networks) {
|
|
1097
1098
|
this.sendMessage({
|
|
1098
1099
|
idx: -1,
|
|
1099
1100
|
type: EventType.NETWORKS,
|
|
1100
|
-
data: networks
|
|
1101
|
+
data: networks,
|
|
1102
|
+
clientVersion: core.VERSION
|
|
1101
1103
|
});
|
|
1102
1104
|
}
|
|
1103
1105
|
notifyWalletContext(walletContext) {
|
|
1104
1106
|
this.sendMessage({
|
|
1105
1107
|
idx: -1,
|
|
1106
1108
|
type: EventType.WALLET_CONTEXT,
|
|
1107
|
-
data: walletContext
|
|
1109
|
+
data: walletContext,
|
|
1110
|
+
clientVersion: core.VERSION
|
|
1108
1111
|
});
|
|
1109
1112
|
}
|
|
1110
1113
|
isValidInitAck(message) {
|
|
@@ -1175,7 +1178,8 @@ class BaseWalletTransport {
|
|
|
1175
1178
|
type: EventType.INIT,
|
|
1176
1179
|
data: {
|
|
1177
1180
|
nonce: this._initNonce
|
|
1178
|
-
}
|
|
1181
|
+
},
|
|
1182
|
+
clientVersion: core.VERSION
|
|
1179
1183
|
});
|
|
1180
1184
|
this._init = InitState.SENT_NONCE;
|
|
1181
1185
|
|
|
@@ -1274,7 +1278,8 @@ class ProxyMessageProvider extends BaseProviderTransport {
|
|
|
1274
1278
|
intent,
|
|
1275
1279
|
networkId,
|
|
1276
1280
|
sessionId
|
|
1277
|
-
}
|
|
1281
|
+
},
|
|
1282
|
+
clientVersion: core.VERSION
|
|
1278
1283
|
});
|
|
1279
1284
|
}
|
|
1280
1285
|
};
|
|
@@ -1292,7 +1297,8 @@ class ProxyMessageProvider extends BaseProviderTransport {
|
|
|
1292
1297
|
this.sendMessage({
|
|
1293
1298
|
idx: -1,
|
|
1294
1299
|
type: EventType.CLOSE,
|
|
1295
|
-
data: null
|
|
1300
|
+
data: null,
|
|
1301
|
+
clientVersion: core.VERSION
|
|
1296
1302
|
});
|
|
1297
1303
|
this.close();
|
|
1298
1304
|
}
|
|
@@ -1880,7 +1886,13 @@ class WindowMessageHandler extends BaseWalletTransport {
|
|
|
1880
1886
|
// Wallet always expects json-rpc request messages from a dapp
|
|
1881
1887
|
let request;
|
|
1882
1888
|
try {
|
|
1883
|
-
request = JSON.parse(event.data)
|
|
1889
|
+
request = JSON.parse(event.data, (key, value) => {
|
|
1890
|
+
// BigNumber compatibility with older versions of sequence.js
|
|
1891
|
+
if (isBigNumberSerialized(value)) {
|
|
1892
|
+
return BigInt(value.hex);
|
|
1893
|
+
}
|
|
1894
|
+
return value;
|
|
1895
|
+
});
|
|
1884
1896
|
} catch (err) {
|
|
1885
1897
|
// event is not a ProviderMessage JSON object, skip
|
|
1886
1898
|
return;
|
|
@@ -1919,7 +1931,6 @@ class WindowMessageHandler extends BaseWalletTransport {
|
|
|
1919
1931
|
|
|
1920
1932
|
// record open details (sessionId + default network) from the window url
|
|
1921
1933
|
const {
|
|
1922
|
-
pathname,
|
|
1923
1934
|
search: rawParams
|
|
1924
1935
|
} = new URL(windowHref || window.location.href);
|
|
1925
1936
|
let session = this.getWindowTransportSession(rawParams);
|
|
@@ -2003,6 +2014,9 @@ class WindowMessageHandler extends BaseWalletTransport {
|
|
|
2003
2014
|
}
|
|
2004
2015
|
}
|
|
2005
2016
|
}
|
|
2017
|
+
const isBigNumberSerialized = value => {
|
|
2018
|
+
return typeof value === 'object' && value.type === 'BigNumber' && ethers.ethers.isHexString(value.hex);
|
|
2019
|
+
};
|
|
2006
2020
|
|
|
2007
2021
|
function isMuxTransportTemplate(obj) {
|
|
2008
2022
|
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') && (
|
|
@@ -2053,13 +2067,6 @@ class MuxMessageProvider {
|
|
|
2053
2067
|
}
|
|
2054
2068
|
this.messageProviders.forEach(m => m.openWallet(path, intent, networkId));
|
|
2055
2069
|
};
|
|
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
|
-
};
|
|
2063
2070
|
this.sendMessageRequest = async function (message) {
|
|
2064
2071
|
if (_this.provider) {
|
|
2065
2072
|
return _this.provider.sendMessageRequest(message);
|
|
@@ -2156,6 +2163,12 @@ class MuxMessageProvider {
|
|
|
2156
2163
|
}
|
|
2157
2164
|
return true;
|
|
2158
2165
|
}
|
|
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
|
+
}
|
|
2159
2172
|
sendMessage(message) {
|
|
2160
2173
|
if (!message.idx || message.idx <= 0) {
|
|
2161
2174
|
throw new Error('message idx is empty');
|
|
@@ -2190,7 +2203,7 @@ function fromExtended(transaction) {
|
|
|
2190
2203
|
|
|
2191
2204
|
const SIGNER_READY_TIMEOUT = 10000;
|
|
2192
2205
|
class WalletRequestHandler {
|
|
2193
|
-
constructor(
|
|
2206
|
+
constructor(account, prompter, networks) {
|
|
2194
2207
|
var _this = this;
|
|
2195
2208
|
// signer interface of the wallet. A null value means there is no signer (ie. user not signed in). An undefined
|
|
2196
2209
|
// value means the signer state is unknown, usually meaning the wallet app is booting up and initializing. Of course
|
|
@@ -2223,417 +2236,6 @@ class WalletRequestHandler {
|
|
|
2223
2236
|
}
|
|
2224
2237
|
return promptConnectDetails;
|
|
2225
2238
|
};
|
|
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
|
-
};
|
|
2637
2239
|
this.isSignedIn = async function () {
|
|
2638
2240
|
await _this.signerReady();
|
|
2639
2241
|
return !!_this.account;
|
|
@@ -2645,7 +2247,7 @@ class WalletRequestHandler {
|
|
|
2645
2247
|
}
|
|
2646
2248
|
return _this.account;
|
|
2647
2249
|
};
|
|
2648
|
-
this.account =
|
|
2250
|
+
this.account = account;
|
|
2649
2251
|
this.prompter = prompter;
|
|
2650
2252
|
this.networks = networks;
|
|
2651
2253
|
}
|
|
@@ -2729,7 +2331,7 @@ class WalletRequestHandler {
|
|
|
2729
2331
|
const chainId = network.findSupportedNetwork(networkId).chainId;
|
|
2730
2332
|
const connectDetails = {
|
|
2731
2333
|
connected: true,
|
|
2732
|
-
chainId: ethers.ethers.
|
|
2334
|
+
chainId: ethers.ethers.toQuantity(chainId)
|
|
2733
2335
|
};
|
|
2734
2336
|
if (options && options.authorize) {
|
|
2735
2337
|
// Perform ethauth eip712 request and construct the ConnectDetails response
|
|
@@ -2764,20 +2366,415 @@ class WalletRequestHandler {
|
|
|
2764
2366
|
// sendMessageRequest will unwrap the ProviderMessageRequest and send it to the JsonRpcHandler
|
|
2765
2367
|
// (aka, the signer in this instance) and then responds with a wrapped response of
|
|
2766
2368
|
// ProviderMessageResponse to be sent over the transport
|
|
2767
|
-
sendMessageRequest(message) {
|
|
2768
|
-
|
|
2769
|
-
|
|
2770
|
-
|
|
2369
|
+
async sendMessageRequest(message) {
|
|
2370
|
+
var _message$clientVersio;
|
|
2371
|
+
// Older versions of the client require the response to be jsonrpc wrapped
|
|
2372
|
+
const majorVersion = Number(((_message$clientVersio = message.clientVersion) == null ? void 0 : _message$clientVersio.split('.')[0]) || '0');
|
|
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
|
+
}
|
|
2771
2408
|
|
|
2772
|
-
|
|
2773
|
-
|
|
2774
|
-
|
|
2409
|
+
// wallet account
|
|
2410
|
+
const account = this.account;
|
|
2411
|
+
if (!account) {
|
|
2412
|
+
throw new Error('WalletRequestHandler: wallet account is not configured');
|
|
2413
|
+
}
|
|
2775
2414
|
|
|
2776
|
-
|
|
2777
|
-
|
|
2778
|
-
|
|
2779
|
-
|
|
2780
|
-
|
|
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(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 === null ? null : 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
|
+
}
|
|
2750
|
+
|
|
2751
|
+
// set default network of wallet
|
|
2752
|
+
case 'sequence_setDefaultNetwork':
|
|
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
|
+
}
|
|
2766
|
+
|
|
2767
|
+
// NOTE: provider here will be chain-bound if chainId is provided
|
|
2768
|
+
return await jsonRpcProvider.send(request.method, request.params);
|
|
2769
|
+
}
|
|
2770
|
+
}
|
|
2771
|
+
} catch (err) {
|
|
2772
|
+
utils.logger.error(err);
|
|
2773
|
+
throw {
|
|
2774
|
+
message: err == null ? void 0 : err.message,
|
|
2775
|
+
code: 4001
|
|
2776
|
+
};
|
|
2777
|
+
}
|
|
2781
2778
|
}
|
|
2782
2779
|
on(event, fn) {
|
|
2783
2780
|
this.events.on(event, fn);
|
|
@@ -2865,7 +2862,7 @@ class WalletRequestHandler {
|
|
|
2865
2862
|
this.events.emit('disconnect', undefined, origin);
|
|
2866
2863
|
}
|
|
2867
2864
|
notifyChainChanged(chainId, origin) {
|
|
2868
|
-
this.events.emit('chainChanged', ethers.ethers.
|
|
2865
|
+
this.events.emit('chainChanged', ethers.ethers.toQuantity(chainId), origin);
|
|
2869
2866
|
}
|
|
2870
2867
|
async notifyNetworks(networks) {
|
|
2871
2868
|
const n = networks || (await this.getNetworks(true));
|
|
@@ -2873,7 +2870,7 @@ class WalletRequestHandler {
|
|
|
2873
2870
|
if (n.length > 0) {
|
|
2874
2871
|
const defaultNetwork = n.find(network => network.chainId === this.defaultChainId());
|
|
2875
2872
|
if (defaultNetwork) {
|
|
2876
|
-
this.events.emit('chainChanged', ethers.ethers.
|
|
2873
|
+
this.events.emit('chainChanged', ethers.ethers.toQuantity(defaultNetwork.chainId));
|
|
2877
2874
|
}
|
|
2878
2875
|
} else {
|
|
2879
2876
|
this.events.emit('chainChanged', '0x0');
|
|
@@ -2942,6 +2939,19 @@ function getLegacyWalletState(chainId, status) {
|
|
|
2942
2939
|
}
|
|
2943
2940
|
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'];
|
|
2944
2941
|
|
|
2942
|
+
function _objectWithoutPropertiesLoose(source, excluded) {
|
|
2943
|
+
if (source == null) return {};
|
|
2944
|
+
var target = {};
|
|
2945
|
+
var sourceKeys = Object.keys(source);
|
|
2946
|
+
var key, i;
|
|
2947
|
+
for (i = 0; i < sourceKeys.length; i++) {
|
|
2948
|
+
key = sourceKeys[i];
|
|
2949
|
+
if (excluded.indexOf(key) >= 0) continue;
|
|
2950
|
+
target[key] = source[key];
|
|
2951
|
+
}
|
|
2952
|
+
return target;
|
|
2953
|
+
}
|
|
2954
|
+
|
|
2945
2955
|
class SequenceSigner {
|
|
2946
2956
|
get utils() {
|
|
2947
2957
|
return this.provider.utils;
|
|
@@ -2950,7 +2960,6 @@ class SequenceSigner {
|
|
|
2950
2960
|
this.client = client;
|
|
2951
2961
|
this.provider = provider;
|
|
2952
2962
|
this.singleNetworkSigners = {};
|
|
2953
|
-
this._isSigner = true;
|
|
2954
2963
|
this._isSequenceSigner = true;
|
|
2955
2964
|
}
|
|
2956
2965
|
async getAddress() {
|
|
@@ -3020,12 +3029,17 @@ class SequenceSigner {
|
|
|
3020
3029
|
});
|
|
3021
3030
|
const provider = this.getProvider(chainId);
|
|
3022
3031
|
try {
|
|
3023
|
-
|
|
3024
|
-
const
|
|
3025
|
-
|
|
3026
|
-
|
|
3027
|
-
|
|
3032
|
+
const result = await new Promise(resolve => {
|
|
3033
|
+
const check = async function check() {
|
|
3034
|
+
const tx = await provider.getTransaction(txHash);
|
|
3035
|
+
if (tx !== null) {
|
|
3036
|
+
return resolve(tx);
|
|
3037
|
+
}
|
|
3038
|
+
await provider.once('block', check);
|
|
3039
|
+
};
|
|
3040
|
+
check();
|
|
3028
3041
|
});
|
|
3042
|
+
return result;
|
|
3029
3043
|
} catch (err) {
|
|
3030
3044
|
err.transactionHash = txHash;
|
|
3031
3045
|
throw err;
|
|
@@ -3047,15 +3061,12 @@ class SequenceSigner {
|
|
|
3047
3061
|
async estimateGas(transaction, optionals) {
|
|
3048
3062
|
return this.getProvider(optionals == null ? void 0 : optionals.chainId).estimateGas(transaction);
|
|
3049
3063
|
}
|
|
3050
|
-
async call(transaction,
|
|
3051
|
-
return this.getProvider(optionals == null ? void 0 : optionals.chainId).call(transaction
|
|
3064
|
+
async call(transaction, optionals) {
|
|
3065
|
+
return this.getProvider(optionals == null ? void 0 : optionals.chainId).call(transaction);
|
|
3052
3066
|
}
|
|
3053
3067
|
getChainId() {
|
|
3054
3068
|
return Promise.resolve(this.client.getChainId());
|
|
3055
3069
|
}
|
|
3056
|
-
async getGasPrice(optionals) {
|
|
3057
|
-
return this.getProvider(optionals == null ? void 0 : optionals.chainId).getGasPrice();
|
|
3058
|
-
}
|
|
3059
3070
|
async getFeeData(optionals) {
|
|
3060
3071
|
return this.getProvider(optionals == null ? void 0 : optionals.chainId).getFeeData();
|
|
3061
3072
|
}
|
|
@@ -3063,7 +3074,7 @@ class SequenceSigner {
|
|
|
3063
3074
|
const res = await this.provider.resolveName(name);
|
|
3064
3075
|
|
|
3065
3076
|
// For some reason ethers.Signer expects this to return `string`
|
|
3066
|
-
// but ethers.
|
|
3077
|
+
// but ethers.Provider expects this to return `string | null`.
|
|
3067
3078
|
// The signer doesn't have any other source of information, so we'll
|
|
3068
3079
|
// fail if the provider doesn't return a result.
|
|
3069
3080
|
if (res === null) {
|
|
@@ -3074,6 +3085,12 @@ class SequenceSigner {
|
|
|
3074
3085
|
_checkProvider(_operation) {
|
|
3075
3086
|
// We always have a provider, so this is a noop
|
|
3076
3087
|
}
|
|
3088
|
+
getNonce(_blockTag) {
|
|
3089
|
+
throw new Error('SequenceSigner does not support getNonce');
|
|
3090
|
+
}
|
|
3091
|
+
populateCall(_transaction) {
|
|
3092
|
+
throw new Error('SequenceSigner does not support populateCall');
|
|
3093
|
+
}
|
|
3077
3094
|
populateTransaction(_transaction) {
|
|
3078
3095
|
throw new Error('SequenceSigner does not support populateTransaction');
|
|
3079
3096
|
}
|
|
@@ -3211,31 +3228,43 @@ class WalletUtils {
|
|
|
3211
3228
|
// recoverAddress()
|
|
3212
3229
|
}
|
|
3213
3230
|
|
|
3214
|
-
|
|
3215
|
-
|
|
3231
|
+
const _excluded = ["method"];
|
|
3232
|
+
const EIP1193EventTypes = ['connect', 'disconnect', 'chainChanged', 'accountsChanged'];
|
|
3233
|
+
class SequenceProvider extends ethers.ethers.AbstractProvider {
|
|
3234
|
+
constructor(client, providerFor, networks = network.allNetworks, options) {
|
|
3216
3235
|
// We support a lot of networks
|
|
3217
3236
|
// but we start with the default one
|
|
3218
|
-
super(client.getChainId());
|
|
3237
|
+
super(client.getChainId(), options);
|
|
3219
3238
|
|
|
3220
3239
|
// Emit events as defined by EIP-1193
|
|
3221
3240
|
this.client = client;
|
|
3222
3241
|
this.providerFor = providerFor;
|
|
3223
3242
|
this.networks = networks;
|
|
3243
|
+
this.options = options;
|
|
3224
3244
|
this.singleNetworkProviders = {};
|
|
3225
3245
|
this._isSequenceProvider = true;
|
|
3226
3246
|
this.utils = void 0;
|
|
3227
3247
|
this.signer = void 0;
|
|
3248
|
+
this.eip1193EventListeners = new Map();
|
|
3228
3249
|
client.onConnect(details => {
|
|
3229
|
-
|
|
3250
|
+
var _this$eip1193EventLis;
|
|
3251
|
+
//this.emit('connect', details)
|
|
3252
|
+
(_this$eip1193EventLis = this.eip1193EventListeners.get('connect')) == null || _this$eip1193EventLis.forEach(listener => listener(details));
|
|
3230
3253
|
});
|
|
3231
3254
|
client.onDisconnect(error => {
|
|
3232
|
-
|
|
3255
|
+
var _this$eip1193EventLis2;
|
|
3256
|
+
//this.emit('disconnect', error)
|
|
3257
|
+
(_this$eip1193EventLis2 = this.eip1193EventListeners.get('disconnect')) == null || _this$eip1193EventLis2.forEach(listener => listener(error));
|
|
3233
3258
|
});
|
|
3234
3259
|
client.onDefaultChainIdChanged(chainId => {
|
|
3235
|
-
|
|
3260
|
+
var _this$eip1193EventLis3;
|
|
3261
|
+
//this.emit('chainChanged', chainId)
|
|
3262
|
+
(_this$eip1193EventLis3 = this.eip1193EventListeners.get('chainChanged')) == null || _this$eip1193EventLis3.forEach(listener => listener(chainId));
|
|
3236
3263
|
});
|
|
3237
3264
|
client.onAccountsChanged(accounts => {
|
|
3238
|
-
|
|
3265
|
+
var _this$eip1193EventLis4;
|
|
3266
|
+
//this.emit('accountsChanged', accounts)
|
|
3267
|
+
(_this$eip1193EventLis4 = this.eip1193EventListeners.get('accountsChanged')) == null || _this$eip1193EventLis4.forEach(listener => listener(accounts));
|
|
3239
3268
|
});
|
|
3240
3269
|
|
|
3241
3270
|
// NOTICE: We don't emit 'open' and 'close' events
|
|
@@ -3252,6 +3281,29 @@ class SequenceProvider extends ethers.ethers.providers.BaseProvider {
|
|
|
3252
3281
|
// Create a utils instance
|
|
3253
3282
|
this.utils = new WalletUtils(this.signer);
|
|
3254
3283
|
}
|
|
3284
|
+
async on(event, listener) {
|
|
3285
|
+
if (EIP1193EventTypes.includes(event)) {
|
|
3286
|
+
const listeners = this.eip1193EventListeners.get(event) || new Set();
|
|
3287
|
+
listeners.add(listener);
|
|
3288
|
+
this.eip1193EventListeners.set(event, listeners);
|
|
3289
|
+
return this;
|
|
3290
|
+
}
|
|
3291
|
+
return super.on(event, listener);
|
|
3292
|
+
}
|
|
3293
|
+
async off(event, listener) {
|
|
3294
|
+
if (EIP1193EventTypes.includes(event)) {
|
|
3295
|
+
const listeners = this.eip1193EventListeners.get(event);
|
|
3296
|
+
if (listeners) {
|
|
3297
|
+
if (listener) {
|
|
3298
|
+
listeners.delete(listener);
|
|
3299
|
+
} else {
|
|
3300
|
+
listeners.clear();
|
|
3301
|
+
}
|
|
3302
|
+
}
|
|
3303
|
+
return this;
|
|
3304
|
+
}
|
|
3305
|
+
return super.off(event, listener);
|
|
3306
|
+
}
|
|
3255
3307
|
getSigner(chainId) {
|
|
3256
3308
|
return this.signer.getSigner(chainId);
|
|
3257
3309
|
}
|
|
@@ -3344,7 +3396,7 @@ class SequenceProvider extends ethers.ethers.providers.BaseProvider {
|
|
|
3344
3396
|
}
|
|
3345
3397
|
const useChainId = this.toChainId(chainId);
|
|
3346
3398
|
if (!this.singleNetworkProviders[useChainId]) {
|
|
3347
|
-
this.singleNetworkProviders[useChainId] = new SingleNetworkSequenceProvider(this.client, this.providerFor, useChainId);
|
|
3399
|
+
this.singleNetworkProviders[useChainId] = new SingleNetworkSequenceProvider(this.client, this.providerFor, useChainId, this.options);
|
|
3348
3400
|
}
|
|
3349
3401
|
return this.singleNetworkProviders[useChainId];
|
|
3350
3402
|
}
|
|
@@ -3364,11 +3416,26 @@ class SequenceProvider extends ethers.ethers.providers.BaseProvider {
|
|
|
3364
3416
|
}
|
|
3365
3417
|
return provider;
|
|
3366
3418
|
}
|
|
3419
|
+
async _perform(req) {
|
|
3420
|
+
var _provider$getRpcReque;
|
|
3421
|
+
const {
|
|
3422
|
+
method
|
|
3423
|
+
} = req,
|
|
3424
|
+
args = _objectWithoutPropertiesLoose(req, _excluded);
|
|
3425
|
+
const provider = await this._getSubprovider();
|
|
3426
|
+
const prepared = (_provider$getRpcReque = provider.getRpcRequest(req)) != null ? _provider$getRpcReque : {
|
|
3427
|
+
method,
|
|
3428
|
+
args: Object.values(args)
|
|
3429
|
+
};
|
|
3430
|
+
if (!prepared) {
|
|
3431
|
+
throw new Error(`Unsupported method ${req.method}`);
|
|
3432
|
+
}
|
|
3433
|
+
return provider.send(prepared.method, prepared.args);
|
|
3434
|
+
}
|
|
3367
3435
|
async perform(method, params) {
|
|
3368
|
-
var _provider$prepareRequ;
|
|
3369
3436
|
// First we check if the method should be handled by the client
|
|
3370
3437
|
if (method === 'eth_chainId') {
|
|
3371
|
-
return ethers.ethers.
|
|
3438
|
+
return ethers.ethers.toQuantity(await this.useChainId());
|
|
3372
3439
|
}
|
|
3373
3440
|
if (method === 'eth_accounts') {
|
|
3374
3441
|
return [this.client.getAddress()];
|
|
@@ -3388,17 +3455,15 @@ class SequenceProvider extends ethers.ethers.providers.BaseProvider {
|
|
|
3388
3455
|
method === 'sequence_sign' || method === 'sequence_signTypedData_v4') {
|
|
3389
3456
|
// We pass the chainId to the client, if we don't pass one
|
|
3390
3457
|
// the client will use its own default chainId
|
|
3391
|
-
return this.client.
|
|
3458
|
+
return this.client.request({
|
|
3392
3459
|
method,
|
|
3393
|
-
params
|
|
3394
|
-
|
|
3460
|
+
params,
|
|
3461
|
+
chainId: this.getChainId()
|
|
3462
|
+
});
|
|
3395
3463
|
}
|
|
3396
|
-
|
|
3397
|
-
|
|
3398
|
-
|
|
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]);
|
|
3464
|
+
return this._perform(_extends({
|
|
3465
|
+
method
|
|
3466
|
+
}, params));
|
|
3402
3467
|
}
|
|
3403
3468
|
send(method, params) {
|
|
3404
3469
|
return this.perform(method, params);
|
|
@@ -3406,14 +3471,18 @@ class SequenceProvider extends ethers.ethers.providers.BaseProvider {
|
|
|
3406
3471
|
request(request) {
|
|
3407
3472
|
return this.perform(request.method, request.params);
|
|
3408
3473
|
}
|
|
3409
|
-
async
|
|
3474
|
+
async _detectNetwork() {
|
|
3410
3475
|
const chainId = this.client.getChainId();
|
|
3411
|
-
const
|
|
3412
|
-
if (!
|
|
3476
|
+
const found = network.findNetworkConfig(this.networks, chainId);
|
|
3477
|
+
if (!found) {
|
|
3413
3478
|
throw new Error(`Unknown network ${chainId}`);
|
|
3414
3479
|
}
|
|
3480
|
+
const network$1 = new ethers.ethers.Network(found.name, found.chainId);
|
|
3415
3481
|
return network$1;
|
|
3416
3482
|
}
|
|
3483
|
+
async detectNetwork() {
|
|
3484
|
+
return this._detectNetwork();
|
|
3485
|
+
}
|
|
3417
3486
|
|
|
3418
3487
|
// Override most of the methods, so we add support for an optional chainId
|
|
3419
3488
|
// argument, which is used to select the provider to use.
|
|
@@ -3430,9 +3499,9 @@ class SequenceProvider extends ethers.ethers.providers.BaseProvider {
|
|
|
3430
3499
|
const provider = await this._getSubprovider(optionals == null ? void 0 : optionals.chainId);
|
|
3431
3500
|
return provider.getBlockNumber();
|
|
3432
3501
|
}
|
|
3433
|
-
async
|
|
3502
|
+
async getFeeData(optionals) {
|
|
3434
3503
|
const provider = await this._getSubprovider(optionals == null ? void 0 : optionals.chainId);
|
|
3435
|
-
return provider.
|
|
3504
|
+
return provider.getFeeData();
|
|
3436
3505
|
}
|
|
3437
3506
|
async getBalance(addressOrName, blockTag, optionals) {
|
|
3438
3507
|
const provider = await this._getSubprovider(optionals == null ? void 0 : optionals.chainId);
|
|
@@ -3446,21 +3515,21 @@ class SequenceProvider extends ethers.ethers.providers.BaseProvider {
|
|
|
3446
3515
|
const provider = await this._getSubprovider(optionals == null ? void 0 : optionals.chainId);
|
|
3447
3516
|
return provider.getCode(addressOrName, blockTag);
|
|
3448
3517
|
}
|
|
3449
|
-
async
|
|
3518
|
+
async getStorage(addressOrName, position, blockTag, optionals) {
|
|
3450
3519
|
const provider = await this._getSubprovider(optionals == null ? void 0 : optionals.chainId);
|
|
3451
|
-
return provider.
|
|
3520
|
+
return provider.getStorage(addressOrName, position, blockTag);
|
|
3452
3521
|
}
|
|
3453
|
-
async call(transaction,
|
|
3522
|
+
async call(transaction, optionals) {
|
|
3454
3523
|
const provider = await this._getSubprovider(optionals == null ? void 0 : optionals.chainId);
|
|
3455
|
-
return provider.call(transaction
|
|
3524
|
+
return provider.call(transaction);
|
|
3456
3525
|
}
|
|
3457
3526
|
async estimateGas(transaction, optionals) {
|
|
3458
3527
|
const provider = await this._getSubprovider(optionals == null ? void 0 : optionals.chainId);
|
|
3459
3528
|
return provider.estimateGas(transaction);
|
|
3460
3529
|
}
|
|
3461
|
-
async getBlock(blockHashOrBlockTag, optionals) {
|
|
3530
|
+
async getBlock(blockHashOrBlockTag, prefetchTxs, optionals) {
|
|
3462
3531
|
const provider = await this._getSubprovider(optionals == null ? void 0 : optionals.chainId);
|
|
3463
|
-
return provider.getBlock(blockHashOrBlockTag);
|
|
3532
|
+
return provider.getBlock(blockHashOrBlockTag, prefetchTxs);
|
|
3464
3533
|
}
|
|
3465
3534
|
async getTransaction(transactionHash, optionals) {
|
|
3466
3535
|
const provider = await this._getSubprovider(optionals == null ? void 0 : optionals.chainId);
|
|
@@ -3487,7 +3556,7 @@ class SequenceProvider extends ethers.ethers.providers.BaseProvider {
|
|
|
3487
3556
|
return provider.getResolver(name);
|
|
3488
3557
|
}
|
|
3489
3558
|
async resolveName(name) {
|
|
3490
|
-
if (ethers.ethers.
|
|
3559
|
+
if (ethers.ethers.isAddress(name)) {
|
|
3491
3560
|
return name;
|
|
3492
3561
|
}
|
|
3493
3562
|
if (!(await this.supportsENS())) {
|
|
@@ -3520,7 +3589,7 @@ SequenceProvider.is = provider => {
|
|
|
3520
3589
|
};
|
|
3521
3590
|
function normalizeChainId(chainId) {
|
|
3522
3591
|
if (typeof chainId === 'object') return normalizeChainId(chainId.chainId);
|
|
3523
|
-
return
|
|
3592
|
+
return Number(chainId);
|
|
3524
3593
|
}
|
|
3525
3594
|
|
|
3526
3595
|
/**
|
|
@@ -3533,8 +3602,8 @@ function normalizeChainId(chainId) {
|
|
|
3533
3602
|
* NOTICE: These networks won't support ENS unless they are the mainnet.
|
|
3534
3603
|
*/
|
|
3535
3604
|
class SingleNetworkSequenceProvider extends SequenceProvider {
|
|
3536
|
-
constructor(client, providerFor, chainId) {
|
|
3537
|
-
super(client, providerFor);
|
|
3605
|
+
constructor(client, providerFor, chainId, options) {
|
|
3606
|
+
super(client, providerFor, undefined, options);
|
|
3538
3607
|
this.chainId = chainId;
|
|
3539
3608
|
this._isSingleNetworkSequenceProvider = true;
|
|
3540
3609
|
}
|
|
@@ -3553,11 +3622,11 @@ class SingleNetworkSequenceProvider extends SequenceProvider {
|
|
|
3553
3622
|
}
|
|
3554
3623
|
async getNetwork() {
|
|
3555
3624
|
const networks = await this.client.getNetworks();
|
|
3556
|
-
const
|
|
3557
|
-
if (!
|
|
3625
|
+
const found = network.findNetworkConfig(networks, this.chainId);
|
|
3626
|
+
if (!found) {
|
|
3558
3627
|
throw new Error(`Unsupported network ${this.chainId}`);
|
|
3559
3628
|
}
|
|
3560
|
-
return
|
|
3629
|
+
return new ethers.ethers.Network(found.name, found.chainId);
|
|
3561
3630
|
}
|
|
3562
3631
|
|
|
3563
3632
|
/**
|
|
@@ -3620,55 +3689,6 @@ const setupAnalytics = (projectAccessKey, server) => {
|
|
|
3620
3689
|
});
|
|
3621
3690
|
};
|
|
3622
3691
|
|
|
3623
|
-
var packageJson = {
|
|
3624
|
-
name: "@0xsequence/provider",
|
|
3625
|
-
version: "1.10.15",
|
|
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
|
-
|
|
3672
3692
|
/**
|
|
3673
3693
|
* This session class is meant to persist the state of the wallet connection
|
|
3674
3694
|
* whitin the dapp. This enables the client to retain the wallet address (and some more)
|
|
@@ -3784,7 +3804,7 @@ class SequenceClient {
|
|
|
3784
3804
|
});
|
|
3785
3805
|
this.transport.on('connect', response => {
|
|
3786
3806
|
var _this$callbacks$conne;
|
|
3787
|
-
const chainIdHex = ethers.ethers.
|
|
3807
|
+
const chainIdHex = ethers.ethers.toQuantity(this.getChainId());
|
|
3788
3808
|
(_this$callbacks$conne = this.callbacks.connect) == null || _this$callbacks$conne.forEach(cb => cb(_extends({}, response, {
|
|
3789
3809
|
// Ignore the full connect response
|
|
3790
3810
|
// use the chainId defined locally
|
|
@@ -3820,7 +3840,7 @@ class SequenceClient {
|
|
|
3820
3840
|
// instead we handle it locally, so we listen for changes in the store
|
|
3821
3841
|
this.defaultChainId.onDefaultChainIdChanged(chainId => {
|
|
3822
3842
|
var _this$callbacks$chain2;
|
|
3823
|
-
const chainIdHex = ethers.ethers.
|
|
3843
|
+
const chainIdHex = ethers.ethers.toQuantity(chainId);
|
|
3824
3844
|
(_this$callbacks$chain2 = this.callbacks.chainChanged) == null || _this$callbacks$chain2.forEach(cb => cb(chainIdHex));
|
|
3825
3845
|
});
|
|
3826
3846
|
if (options != null && options.projectAccessKey) {
|
|
@@ -3933,7 +3953,7 @@ class SequenceClient {
|
|
|
3933
3953
|
type: 'connect',
|
|
3934
3954
|
options: _extends({}, options, {
|
|
3935
3955
|
networkId: this.getChainId(),
|
|
3936
|
-
clientVersion:
|
|
3956
|
+
clientVersion: core.VERSION
|
|
3937
3957
|
})
|
|
3938
3958
|
});
|
|
3939
3959
|
const connectDetails = await this.transport.waitUntilConnected().catch(error => {
|
|
@@ -3953,7 +3973,7 @@ class SequenceClient {
|
|
|
3953
3973
|
// Normalize chainId into a decimal string
|
|
3954
3974
|
// TODO: Remove this once wallet-webapp returns chainId as a string
|
|
3955
3975
|
if (connectDetails.chainId) {
|
|
3956
|
-
connectDetails.chainId =
|
|
3976
|
+
connectDetails.chainId = BigInt(connectDetails.chainId).toString();
|
|
3957
3977
|
}
|
|
3958
3978
|
if (connectDetails.connected) {
|
|
3959
3979
|
var _connectDetails$sessi;
|
|
@@ -3979,33 +3999,17 @@ class SequenceClient {
|
|
|
3979
3999
|
|
|
3980
4000
|
// Higher level API
|
|
3981
4001
|
|
|
3982
|
-
|
|
3983
|
-
// but transport uses it instead of send, so we wrap it
|
|
3984
|
-
send(request, chainId) {
|
|
4002
|
+
async request(request) {
|
|
3985
4003
|
// Internally when sending requests we use `legacy_sign`
|
|
3986
4004
|
// to avoid the default EIP6492 behavior overriding an explicit
|
|
3987
4005
|
// "legacy sign" request, so we map the method here.
|
|
3988
4006
|
request.method = this.mapSignMethod(request.method);
|
|
3989
|
-
return
|
|
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
|
-
});
|
|
4007
|
+
return this.transport.request(request);
|
|
4004
4008
|
}
|
|
4005
4009
|
async getNetworks(pull) {
|
|
4006
4010
|
const connectedSession = this.session.connectedSession();
|
|
4007
4011
|
if (pull) {
|
|
4008
|
-
connectedSession.networks = await this.
|
|
4012
|
+
connectedSession.networks = await this.request({
|
|
4009
4013
|
method: 'sequence_getNetworks'
|
|
4010
4014
|
});
|
|
4011
4015
|
this.session.setSession(connectedSession);
|
|
@@ -4061,15 +4065,14 @@ class SequenceClient {
|
|
|
4061
4065
|
chainId: `${(options == null ? void 0 : options.chainId) || this.getChainId()}`
|
|
4062
4066
|
}
|
|
4063
4067
|
});
|
|
4064
|
-
|
|
4065
|
-
// Serialize a BytesLike or string message into a hex string before sending
|
|
4066
|
-
message = ethers.ethers.utils.hexlify(messageToBytes(message));
|
|
4068
|
+
message = ethers.ethers.hexlify(messageToBytes(message));
|
|
4067
4069
|
|
|
4068
4070
|
// Address is ignored by the wallet webapp
|
|
4069
|
-
return this.
|
|
4071
|
+
return this.request({
|
|
4070
4072
|
method,
|
|
4071
|
-
params: [message, this.getAddress()]
|
|
4072
|
-
|
|
4073
|
+
params: [message, this.getAddress()],
|
|
4074
|
+
chainId: options == null ? void 0 : options.chainId
|
|
4075
|
+
});
|
|
4073
4076
|
}
|
|
4074
4077
|
async signTypedData(typedData, options) {
|
|
4075
4078
|
var _this$analytics5;
|
|
@@ -4077,7 +4080,7 @@ class SequenceClient {
|
|
|
4077
4080
|
|
|
4078
4081
|
// TODO: Stop using ethers for this, this is the only place where we use it
|
|
4079
4082
|
// and it makes the client depend on ethers.
|
|
4080
|
-
const encoded = ethers.ethers.
|
|
4083
|
+
const encoded = ethers.ethers.TypedDataEncoder.getPayload(typedData.domain, typedData.types, typedData.message);
|
|
4081
4084
|
|
|
4082
4085
|
// The sign typed data will use one of the following chainIds, in order:
|
|
4083
4086
|
// - The one provided in the options
|
|
@@ -4090,10 +4093,11 @@ class SequenceClient {
|
|
|
4090
4093
|
chainId: `${(options == null ? void 0 : options.chainId) || this.getChainId()}`
|
|
4091
4094
|
}
|
|
4092
4095
|
});
|
|
4093
|
-
return this.
|
|
4096
|
+
return this.request({
|
|
4094
4097
|
method,
|
|
4095
|
-
params: [this.getAddress(), encoded]
|
|
4096
|
-
|
|
4098
|
+
params: [this.getAddress(), encoded],
|
|
4099
|
+
chainId: (options == null ? void 0 : options.chainId) || typedData.domain.chainId && Number(typedData.domain.chainId) || this.getChainId()
|
|
4100
|
+
});
|
|
4097
4101
|
}
|
|
4098
4102
|
async sendTransaction(tx, options) {
|
|
4099
4103
|
var _this$analytics6;
|
|
@@ -4105,22 +4109,24 @@ class SequenceClient {
|
|
|
4105
4109
|
chainId: `${(options == null ? void 0 : options.chainId) || this.getChainId()}`
|
|
4106
4110
|
}
|
|
4107
4111
|
});
|
|
4108
|
-
return this.
|
|
4112
|
+
return this.request({
|
|
4109
4113
|
method: 'eth_sendTransaction',
|
|
4110
|
-
params: [extendedTxs]
|
|
4111
|
-
|
|
4114
|
+
params: [extendedTxs],
|
|
4115
|
+
chainId: options == null ? void 0 : options.chainId
|
|
4116
|
+
});
|
|
4112
4117
|
}
|
|
4113
4118
|
async getWalletContext() {
|
|
4114
|
-
return this.
|
|
4119
|
+
return this.request({
|
|
4115
4120
|
method: 'sequence_getWalletContext'
|
|
4116
4121
|
});
|
|
4117
4122
|
}
|
|
4118
4123
|
async getOnchainWalletConfig(options) {
|
|
4119
4124
|
// NOTICE: sequence_getWalletConfig sends the chainId as a param
|
|
4120
|
-
const res = await this.
|
|
4125
|
+
const res = await this.request({
|
|
4121
4126
|
method: 'sequence_getWalletConfig',
|
|
4122
|
-
params: [(options == null ? void 0 : options.chainId) || this.getChainId()]
|
|
4123
|
-
|
|
4127
|
+
params: [(options == null ? void 0 : options.chainId) || this.getChainId()],
|
|
4128
|
+
chainId: options == null ? void 0 : options.chainId
|
|
4129
|
+
});
|
|
4124
4130
|
return Array.isArray(res) ? res[0] : res;
|
|
4125
4131
|
}
|
|
4126
4132
|
|
|
@@ -4199,9 +4205,11 @@ const initWallet = (projectAccessKey, partialConfig) => {
|
|
|
4199
4205
|
if (!rpcUrl) {
|
|
4200
4206
|
throw new Error(`no rpcUrl found for chainId: ${chainId}`);
|
|
4201
4207
|
}
|
|
4202
|
-
|
|
4203
|
-
|
|
4204
|
-
|
|
4208
|
+
rpcProviders[chainId] = new network.JsonRpcProvider(rpcUrl, {
|
|
4209
|
+
middlewares: [network.loggingProviderMiddleware, network.exceptionProviderMiddleware, new network.CachedProvider()]
|
|
4210
|
+
}, {
|
|
4211
|
+
cacheTimeout: -1
|
|
4212
|
+
});
|
|
4205
4213
|
}
|
|
4206
4214
|
return rpcProviders[chainId];
|
|
4207
4215
|
};
|