@0xsequence/provider 1.10.15 → 2.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/0xsequence-provider.cjs.dev.js +663 -653
- package/dist/0xsequence-provider.cjs.prod.js +663 -653
- package/dist/0xsequence-provider.esm.js +667 -657
- 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 +41 -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/unreal-transport/unreal-message-handler.ts +2 -2
- package/src/transports/unreal-transport/unreal-message-provider.ts +2 -2
- package/src/transports/wallet-request-handler.ts +91 -130
- package/src/transports/window-transport/window-message-handler.ts +5 -4
- package/src/transports/window-transport/window-message-provider.ts +4 -4
- 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
|
}
|
|
@@ -1455,7 +1461,7 @@ class UnrealMessageProvider extends BaseProviderTransport {
|
|
|
1455
1461
|
// all lowercase is an annoying limitation of Unreal CEF BindUObject
|
|
1456
1462
|
sendMessage(message) {
|
|
1457
1463
|
var _window$ue3;
|
|
1458
|
-
const postedMessage = typeof message !== 'string' ? JSON.stringify(message) : message;
|
|
1464
|
+
const postedMessage = typeof message !== 'string' ? JSON.stringify(message, utils.bigintReplacer) : message;
|
|
1459
1465
|
console.log('Sending message to wallet:', postedMessage);
|
|
1460
1466
|
(_window$ue3 = window.ue) == null || (_window$ue3 = _window$ue3.sequencewallettransport) == null || _window$ue3.sendmessagetowallet(postedMessage);
|
|
1461
1467
|
}
|
|
@@ -1554,7 +1560,7 @@ class UnrealMessageHandler extends BaseWalletTransport {
|
|
|
1554
1560
|
return;
|
|
1555
1561
|
}
|
|
1556
1562
|
// prepare payload
|
|
1557
|
-
const payload = JSON.stringify(message);
|
|
1563
|
+
const payload = JSON.stringify(message, utils.bigintReplacer);
|
|
1558
1564
|
|
|
1559
1565
|
// post-message to app.
|
|
1560
1566
|
(_window$ue3 = window.ue) == null || (_window$ue3 = _window$ue3.sequencewallettransport) == null || _window$ue3.sendmessagetosequencejs(payload);
|
|
@@ -1829,7 +1835,7 @@ class WindowMessageProvider extends BaseProviderTransport {
|
|
|
1829
1835
|
}
|
|
1830
1836
|
let message;
|
|
1831
1837
|
try {
|
|
1832
|
-
message = JSON.parse(event.data);
|
|
1838
|
+
message = JSON.parse(event.data, utils.bigintReviver);
|
|
1833
1839
|
} catch (err) {
|
|
1834
1840
|
// event is not a ProviderMessage JSON object, skip
|
|
1835
1841
|
return;
|
|
@@ -1853,7 +1859,7 @@ class WindowMessageProvider extends BaseProviderTransport {
|
|
|
1853
1859
|
utils.logger.warn('WindowMessageProvider: sendMessage failed as walletWindow is unavailable');
|
|
1854
1860
|
return;
|
|
1855
1861
|
}
|
|
1856
|
-
const postedMessage = typeof message !== 'string' ? JSON.stringify(message) : message;
|
|
1862
|
+
const postedMessage = typeof message !== 'string' ? JSON.stringify(message, utils.bigintReplacer) : message;
|
|
1857
1863
|
this.walletWindow.postMessage(postedMessage, this.walletURL.origin);
|
|
1858
1864
|
}
|
|
1859
1865
|
}
|
|
@@ -1880,7 +1886,7 @@ 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, utils.bigintReviver);
|
|
1884
1890
|
} catch (err) {
|
|
1885
1891
|
// event is not a ProviderMessage JSON object, skip
|
|
1886
1892
|
return;
|
|
@@ -1919,7 +1925,6 @@ class WindowMessageHandler extends BaseWalletTransport {
|
|
|
1919
1925
|
|
|
1920
1926
|
// record open details (sessionId + default network) from the window url
|
|
1921
1927
|
const {
|
|
1922
|
-
pathname,
|
|
1923
1928
|
search: rawParams
|
|
1924
1929
|
} = new URL(windowHref || window.location.href);
|
|
1925
1930
|
let session = this.getWindowTransportSession(rawParams);
|
|
@@ -1971,7 +1976,7 @@ class WindowMessageHandler extends BaseWalletTransport {
|
|
|
1971
1976
|
// postMessage sends message to the dapp window
|
|
1972
1977
|
sendMessage(message) {
|
|
1973
1978
|
// prepare payload
|
|
1974
|
-
const payload = JSON.stringify(message);
|
|
1979
|
+
const payload = JSON.stringify(message, utils.bigintReplacer);
|
|
1975
1980
|
|
|
1976
1981
|
// post-message to app.
|
|
1977
1982
|
// only for init requests, we send to '*' origin
|
|
@@ -2053,13 +2058,6 @@ class MuxMessageProvider {
|
|
|
2053
2058
|
}
|
|
2054
2059
|
this.messageProviders.forEach(m => m.openWallet(path, intent, networkId));
|
|
2055
2060
|
};
|
|
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
2061
|
this.sendMessageRequest = async function (message) {
|
|
2064
2062
|
if (_this.provider) {
|
|
2065
2063
|
return _this.provider.sendMessageRequest(message);
|
|
@@ -2156,6 +2154,12 @@ class MuxMessageProvider {
|
|
|
2156
2154
|
}
|
|
2157
2155
|
return true;
|
|
2158
2156
|
}
|
|
2157
|
+
request(request) {
|
|
2158
|
+
if (!this.provider) {
|
|
2159
|
+
throw new Error('impossible state, wallet must be opened first');
|
|
2160
|
+
}
|
|
2161
|
+
return this.provider.request(request);
|
|
2162
|
+
}
|
|
2159
2163
|
sendMessage(message) {
|
|
2160
2164
|
if (!message.idx || message.idx <= 0) {
|
|
2161
2165
|
throw new Error('message idx is empty');
|
|
@@ -2190,7 +2194,7 @@ function fromExtended(transaction) {
|
|
|
2190
2194
|
|
|
2191
2195
|
const SIGNER_READY_TIMEOUT = 10000;
|
|
2192
2196
|
class WalletRequestHandler {
|
|
2193
|
-
constructor(
|
|
2197
|
+
constructor(account, prompter, networks) {
|
|
2194
2198
|
var _this = this;
|
|
2195
2199
|
// signer interface of the wallet. A null value means there is no signer (ie. user not signed in). An undefined
|
|
2196
2200
|
// value means the signer state is unknown, usually meaning the wallet app is booting up and initializing. Of course
|
|
@@ -2223,417 +2227,6 @@ class WalletRequestHandler {
|
|
|
2223
2227
|
}
|
|
2224
2228
|
return promptConnectDetails;
|
|
2225
2229
|
};
|
|
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
2230
|
this.isSignedIn = async function () {
|
|
2638
2231
|
await _this.signerReady();
|
|
2639
2232
|
return !!_this.account;
|
|
@@ -2645,7 +2238,7 @@ class WalletRequestHandler {
|
|
|
2645
2238
|
}
|
|
2646
2239
|
return _this.account;
|
|
2647
2240
|
};
|
|
2648
|
-
this.account =
|
|
2241
|
+
this.account = account;
|
|
2649
2242
|
this.prompter = prompter;
|
|
2650
2243
|
this.networks = networks;
|
|
2651
2244
|
}
|
|
@@ -2729,7 +2322,7 @@ class WalletRequestHandler {
|
|
|
2729
2322
|
const chainId = network.findSupportedNetwork(networkId).chainId;
|
|
2730
2323
|
const connectDetails = {
|
|
2731
2324
|
connected: true,
|
|
2732
|
-
chainId: ethers.ethers.
|
|
2325
|
+
chainId: ethers.ethers.toQuantity(chainId)
|
|
2733
2326
|
};
|
|
2734
2327
|
if (options && options.authorize) {
|
|
2735
2328
|
// Perform ethauth eip712 request and construct the ConnectDetails response
|
|
@@ -2764,20 +2357,415 @@ class WalletRequestHandler {
|
|
|
2764
2357
|
// sendMessageRequest will unwrap the ProviderMessageRequest and send it to the JsonRpcHandler
|
|
2765
2358
|
// (aka, the signer in this instance) and then responds with a wrapped response of
|
|
2766
2359
|
// ProviderMessageResponse to be sent over the transport
|
|
2767
|
-
sendMessageRequest(message) {
|
|
2768
|
-
|
|
2769
|
-
|
|
2770
|
-
|
|
2360
|
+
async sendMessageRequest(message) {
|
|
2361
|
+
var _message$clientVersio;
|
|
2362
|
+
// Older versions of the client require the response to be jsonrpc wrapped
|
|
2363
|
+
const majorVersion = Number(((_message$clientVersio = message.clientVersion) == null ? void 0 : _message$clientVersio.split('.')[0]) || '0');
|
|
2364
|
+
const isJsonRpcResponse = majorVersion < 2;
|
|
2365
|
+
const jsonRpcResponse = {
|
|
2366
|
+
id: message.data.id,
|
|
2367
|
+
jsonrpc: '2.0',
|
|
2368
|
+
result: null,
|
|
2369
|
+
error: undefined
|
|
2370
|
+
};
|
|
2371
|
+
try {
|
|
2372
|
+
const result = await this.request({
|
|
2373
|
+
method: message.data.method,
|
|
2374
|
+
params: message.data.params,
|
|
2375
|
+
chainId: message.chainId
|
|
2376
|
+
});
|
|
2377
|
+
return _extends({}, message, {
|
|
2378
|
+
data: isJsonRpcResponse ? _extends({}, jsonRpcResponse, {
|
|
2379
|
+
result
|
|
2380
|
+
}) : result
|
|
2381
|
+
});
|
|
2382
|
+
} catch (error) {
|
|
2383
|
+
return _extends({}, message, {
|
|
2384
|
+
data: isJsonRpcResponse ? _extends({}, jsonRpcResponse, {
|
|
2385
|
+
error
|
|
2386
|
+
}) : error
|
|
2387
|
+
});
|
|
2388
|
+
}
|
|
2389
|
+
}
|
|
2390
|
+
async request(request) {
|
|
2391
|
+
await this.getAccount();
|
|
2392
|
+
try {
|
|
2393
|
+
var _this$account, _request$chainId;
|
|
2394
|
+
// only allow public json rpc method to the provider when user is not logged in, aka signer is not set
|
|
2395
|
+
if ((!this.account || this.account === null) && !permittedJsonRpcMethods.includes(request.method)) {
|
|
2396
|
+
// throw new Error(`not logged in. ${request.method} is unavailable`)
|
|
2397
|
+
throw ErrSignedInRequired;
|
|
2398
|
+
}
|
|
2771
2399
|
|
|
2772
|
-
|
|
2773
|
-
|
|
2774
|
-
|
|
2400
|
+
// wallet account
|
|
2401
|
+
const account = this.account;
|
|
2402
|
+
if (!account) {
|
|
2403
|
+
throw new Error('WalletRequestHandler: wallet account is not configured');
|
|
2404
|
+
}
|
|
2775
2405
|
|
|
2776
|
-
|
|
2777
|
-
|
|
2778
|
-
|
|
2779
|
-
|
|
2780
|
-
|
|
2406
|
+
// fetch the provider for the specific chain, or undefined will select defaultChain
|
|
2407
|
+
const provider = (_this$account = this.account) == null ? void 0 : _this$account.providerFor((_request$chainId = request.chainId) != null ? _request$chainId : this.defaultChainId());
|
|
2408
|
+
if (!provider) {
|
|
2409
|
+
throw new Error(`WalletRequestHandler: wallet provider is not configured for chainId ${request.chainId}`);
|
|
2410
|
+
}
|
|
2411
|
+
const jsonRpcProvider = provider instanceof ethers.ethers.JsonRpcProvider ? provider : undefined;
|
|
2412
|
+
switch (request.method) {
|
|
2413
|
+
case 'net_version':
|
|
2414
|
+
{
|
|
2415
|
+
if (!jsonRpcProvider) {
|
|
2416
|
+
throw new Error(`Account provider doesn't support send method`);
|
|
2417
|
+
}
|
|
2418
|
+
return await jsonRpcProvider.send('net_version', []);
|
|
2419
|
+
}
|
|
2420
|
+
case 'eth_chainId':
|
|
2421
|
+
{
|
|
2422
|
+
if (!jsonRpcProvider) {
|
|
2423
|
+
throw new Error(`Account provider doesn't support send method`);
|
|
2424
|
+
}
|
|
2425
|
+
return await jsonRpcProvider.send('eth_chainId', []);
|
|
2426
|
+
}
|
|
2427
|
+
case 'eth_accounts':
|
|
2428
|
+
{
|
|
2429
|
+
return [account.address];
|
|
2430
|
+
}
|
|
2431
|
+
case 'eth_getBalance':
|
|
2432
|
+
{
|
|
2433
|
+
const [accountAddress, blockTag] = request.params;
|
|
2434
|
+
const walletBalance = await provider.getBalance(accountAddress, blockTag);
|
|
2435
|
+
return utils.toHexString(walletBalance);
|
|
2436
|
+
}
|
|
2437
|
+
case 'sequence_sign':
|
|
2438
|
+
case 'personal_sign':
|
|
2439
|
+
case 'eth_sign':
|
|
2440
|
+
{
|
|
2441
|
+
// note: message from json-rpc input is in hex format
|
|
2442
|
+
let message;
|
|
2443
|
+
|
|
2444
|
+
// there is a difference in the order of the params:
|
|
2445
|
+
// sequence_sign, personal_sign: [data, address]
|
|
2446
|
+
// eth_sign: [address, data]
|
|
2447
|
+
switch (request.method) {
|
|
2448
|
+
case 'sequence_sign':
|
|
2449
|
+
case 'personal_sign':
|
|
2450
|
+
{
|
|
2451
|
+
const [data, _address] = request.params;
|
|
2452
|
+
message = data;
|
|
2453
|
+
break;
|
|
2454
|
+
}
|
|
2455
|
+
case 'eth_sign':
|
|
2456
|
+
{
|
|
2457
|
+
const [_address, data] = request.params;
|
|
2458
|
+
message = data;
|
|
2459
|
+
break;
|
|
2460
|
+
}
|
|
2461
|
+
}
|
|
2462
|
+
let sig = '';
|
|
2463
|
+
|
|
2464
|
+
// Message must be prefixed with "\x19Ethereum Signed Message:\n"
|
|
2465
|
+
// as defined by EIP-191
|
|
2466
|
+
const prefixedMessage = prefixEIP191Message(message);
|
|
2467
|
+
|
|
2468
|
+
// TODO:
|
|
2469
|
+
// if (process.env.TEST_MODE === 'true' && this.prompter === null) {
|
|
2470
|
+
const sequenceVerified = request.method === 'sequence_sign';
|
|
2471
|
+
if (this.prompter === null) {
|
|
2472
|
+
var _request$chainId2;
|
|
2473
|
+
// prompter is null, so we'll sign from here
|
|
2474
|
+
sig = await account.signMessage(prefixedMessage, (_request$chainId2 = request.chainId) != null ? _request$chainId2 : this.defaultChainId(), sequenceVerified ? 'eip6492' : 'ignore');
|
|
2475
|
+
} else {
|
|
2476
|
+
sig = await this.prompter.promptSignMessage({
|
|
2477
|
+
chainId: request.chainId,
|
|
2478
|
+
message: ethers.ethers.getBytes(prefixedMessage),
|
|
2479
|
+
eip6492: sequenceVerified
|
|
2480
|
+
}, this.connectOptions);
|
|
2481
|
+
}
|
|
2482
|
+
if (sig && sig.length > 0) {
|
|
2483
|
+
return sig;
|
|
2484
|
+
} else {
|
|
2485
|
+
// The user has declined the request when value is null
|
|
2486
|
+
throw new Error('declined by user');
|
|
2487
|
+
}
|
|
2488
|
+
}
|
|
2489
|
+
case 'sequence_signTypedData_v4':
|
|
2490
|
+
case 'eth_signTypedData':
|
|
2491
|
+
case 'eth_signTypedData_v4':
|
|
2492
|
+
{
|
|
2493
|
+
// note: signingAddress from json-rpc input is in hex format, and typedDataObject
|
|
2494
|
+
// should be an object, but in some instances may be double string encoded
|
|
2495
|
+
const [signingAddress, typedDataObject] = request.params;
|
|
2496
|
+
let typedData = undefined;
|
|
2497
|
+
if (typeof typedDataObject === 'string') {
|
|
2498
|
+
try {
|
|
2499
|
+
typedData = JSON.parse(typedDataObject);
|
|
2500
|
+
} catch (e) {
|
|
2501
|
+
console.warn('walletRequestHandler: error parsing typedData', e);
|
|
2502
|
+
}
|
|
2503
|
+
} else {
|
|
2504
|
+
typedData = typedDataObject;
|
|
2505
|
+
}
|
|
2506
|
+
if (!typedData || !typedData.domain || !typedData.types || !typedData.message) {
|
|
2507
|
+
throw new Error('invalid typedData object');
|
|
2508
|
+
}
|
|
2509
|
+
let sig = '';
|
|
2510
|
+
const sequenceVerified = request.method === 'sequence_signTypedData_v4';
|
|
2511
|
+
if (this.prompter === null) {
|
|
2512
|
+
var _request$chainId3;
|
|
2513
|
+
// prompter is null, so we'll sign from here
|
|
2514
|
+
sig = await account.signTypedData(typedData.domain, typedData.types, typedData.message, (_request$chainId3 = request.chainId) != null ? _request$chainId3 : this.defaultChainId(), sequenceVerified ? 'eip6492' : 'ignore');
|
|
2515
|
+
} else {
|
|
2516
|
+
sig = await this.prompter.promptSignMessage({
|
|
2517
|
+
chainId: request.chainId,
|
|
2518
|
+
typedData: typedData,
|
|
2519
|
+
eip6492: sequenceVerified
|
|
2520
|
+
}, this.connectOptions);
|
|
2521
|
+
}
|
|
2522
|
+
if (sig && sig.length > 0) {
|
|
2523
|
+
return sig;
|
|
2524
|
+
} else {
|
|
2525
|
+
// The user has declined the request when value is null
|
|
2526
|
+
throw new Error('declined by user');
|
|
2527
|
+
}
|
|
2528
|
+
}
|
|
2529
|
+
case 'eth_sendTransaction':
|
|
2530
|
+
{
|
|
2531
|
+
// https://eth.wiki/json-rpc/API#eth_sendtransaction
|
|
2532
|
+
const transactionParams = fromExtended(request.params[0]).map(tx => {
|
|
2533
|
+
// eth_sendTransaction uses 'gas'
|
|
2534
|
+
// ethers and sequence use 'gasLimit'
|
|
2535
|
+
if ('gas' in tx && tx.gasLimit === undefined) {
|
|
2536
|
+
tx.gasLimit = tx.gas;
|
|
2537
|
+
delete tx.gas;
|
|
2538
|
+
}
|
|
2539
|
+
return tx;
|
|
2540
|
+
});
|
|
2541
|
+
validateTransactionRequest(account.address, transactionParams);
|
|
2542
|
+
let txnHash = '';
|
|
2543
|
+
if (this.prompter === null) {
|
|
2544
|
+
var _request$chainId4, _txnResponse$hash;
|
|
2545
|
+
// prompter is null, so we'll send from here
|
|
2546
|
+
const txnResponse = await account.sendTransaction(transactionParams, (_request$chainId4 = request.chainId) != null ? _request$chainId4 : this.defaultChainId());
|
|
2547
|
+
txnHash = (_txnResponse$hash = txnResponse == null ? void 0 : txnResponse.hash) != null ? _txnResponse$hash : '';
|
|
2548
|
+
} else {
|
|
2549
|
+
// prompt user to provide the response
|
|
2550
|
+
txnHash = await this.prompter.promptSendTransaction(transactionParams, request.chainId, this.connectOptions);
|
|
2551
|
+
}
|
|
2552
|
+
if (txnHash) {
|
|
2553
|
+
return txnHash;
|
|
2554
|
+
} else {
|
|
2555
|
+
// The user has declined the request when value is null
|
|
2556
|
+
throw new Error('declined by user');
|
|
2557
|
+
}
|
|
2558
|
+
}
|
|
2559
|
+
case 'eth_signTransaction':
|
|
2560
|
+
{
|
|
2561
|
+
// https://eth.wiki/json-rpc/API#eth_signTransaction
|
|
2562
|
+
const [transaction] = request.params;
|
|
2563
|
+
const sender = ethers.ethers.getAddress(transaction.from);
|
|
2564
|
+
if (sender !== account.address) {
|
|
2565
|
+
throw new Error('sender address does not match wallet');
|
|
2566
|
+
}
|
|
2567
|
+
validateTransactionRequest(account.address, transaction);
|
|
2568
|
+
if (this.prompter === null) {
|
|
2569
|
+
var _request$chainId5;
|
|
2570
|
+
// The eth_signTransaction method expects a `string` return value we instead return a `SignedTransactions` object,
|
|
2571
|
+
// this can only be broadcasted using an RPC provider with support for signed Sequence transactions, like this one.
|
|
2572
|
+
//
|
|
2573
|
+
// TODO: verify serializing / transporting the SignedTransaction object works as expected, most likely however
|
|
2574
|
+
// we will want to resolveProperties the big number values to hex strings
|
|
2575
|
+
return await account.signTransactions(transaction, (_request$chainId5 = request.chainId) != null ? _request$chainId5 : this.defaultChainId());
|
|
2576
|
+
} else {
|
|
2577
|
+
return await this.prompter.promptSignTransaction(transaction, request.chainId, this.connectOptions);
|
|
2578
|
+
}
|
|
2579
|
+
}
|
|
2580
|
+
case 'eth_sendRawTransaction':
|
|
2581
|
+
{
|
|
2582
|
+
// NOTE: we're not using a prompter here as the transaction is already signed
|
|
2583
|
+
// and would have prompted the user upon signing.
|
|
2584
|
+
|
|
2585
|
+
// https://eth.wiki/json-rpc/API#eth_sendRawTransaction
|
|
2586
|
+
if (core.commons.transaction.isSignedTransactionBundle(request.params[0])) {
|
|
2587
|
+
const txChainId = Number(request.params[0].chainId);
|
|
2588
|
+
const tx = await account.relayer(txChainId).relay(request.params[0]);
|
|
2589
|
+
return tx.hash;
|
|
2590
|
+
} else {
|
|
2591
|
+
const tx = await provider.broadcastTransaction(request.params[0]);
|
|
2592
|
+
return tx.hash;
|
|
2593
|
+
}
|
|
2594
|
+
}
|
|
2595
|
+
case 'eth_getTransactionCount':
|
|
2596
|
+
{
|
|
2597
|
+
const address = ethers.ethers.getAddress(request.params[0]);
|
|
2598
|
+
const tag = request.params[1];
|
|
2599
|
+
|
|
2600
|
+
// TODO: Maybe we should fetch this data from the relayer or from the reader
|
|
2601
|
+
// but for now we keep it simple and just use the provider
|
|
2602
|
+
|
|
2603
|
+
const count = await provider.getTransactionCount(address, tag);
|
|
2604
|
+
return utils.toHexString(BigInt(count));
|
|
2605
|
+
}
|
|
2606
|
+
case 'eth_blockNumber':
|
|
2607
|
+
{
|
|
2608
|
+
return await provider.getBlockNumber();
|
|
2609
|
+
}
|
|
2610
|
+
case 'eth_getBlockByNumber':
|
|
2611
|
+
{
|
|
2612
|
+
return await provider.getBlock(request.params[0] /* , jsonRpcRequest.params[1] */);
|
|
2613
|
+
}
|
|
2614
|
+
case 'eth_getBlockByHash':
|
|
2615
|
+
{
|
|
2616
|
+
return await provider.getBlock(request.params[0] /* , jsonRpcRequest.params[1] */);
|
|
2617
|
+
}
|
|
2618
|
+
case 'eth_getTransactionByHash':
|
|
2619
|
+
{
|
|
2620
|
+
return await provider.getTransaction(request.params[0]);
|
|
2621
|
+
}
|
|
2622
|
+
case 'eth_call':
|
|
2623
|
+
{
|
|
2624
|
+
const [transactionObject, blockTag] = request.params;
|
|
2625
|
+
return await provider.call(_extends({}, transactionObject, {
|
|
2626
|
+
blockTag
|
|
2627
|
+
}));
|
|
2628
|
+
}
|
|
2629
|
+
case 'eth_getCode':
|
|
2630
|
+
{
|
|
2631
|
+
const [contractAddress, blockTag] = request.params;
|
|
2632
|
+
return await provider.getCode(contractAddress, blockTag);
|
|
2633
|
+
}
|
|
2634
|
+
case 'eth_estimateGas':
|
|
2635
|
+
{
|
|
2636
|
+
const [transactionObject] = request.params;
|
|
2637
|
+
return await provider.estimateGas(transactionObject);
|
|
2638
|
+
}
|
|
2639
|
+
case 'eth_gasPrice':
|
|
2640
|
+
{
|
|
2641
|
+
const feeData = await provider.getFeeData();
|
|
2642
|
+
return feeData.gasPrice === null ? null : utils.toHexString(feeData.gasPrice);
|
|
2643
|
+
}
|
|
2644
|
+
case 'wallet_switchEthereumChain':
|
|
2645
|
+
{
|
|
2646
|
+
const [switchParams] = request.params;
|
|
2647
|
+
if (!switchParams.chainId || switchParams.chainId.length === 0) {
|
|
2648
|
+
throw new Error('invalid chainId');
|
|
2649
|
+
}
|
|
2650
|
+
const chainId = BigInt(switchParams.chainId);
|
|
2651
|
+
this.setDefaultChainId(Number(chainId));
|
|
2652
|
+
return null; // success
|
|
2653
|
+
}
|
|
2654
|
+
|
|
2655
|
+
// smart wallet method
|
|
2656
|
+
case 'sequence_getWalletContext':
|
|
2657
|
+
{
|
|
2658
|
+
return account.contexts;
|
|
2659
|
+
}
|
|
2660
|
+
|
|
2661
|
+
// smart wallet method
|
|
2662
|
+
case 'sequence_getWalletConfig':
|
|
2663
|
+
{
|
|
2664
|
+
const [chainId] = request.params;
|
|
2665
|
+
if (chainId) {
|
|
2666
|
+
return [(await account.status(chainId)).onChain.config];
|
|
2667
|
+
} else {
|
|
2668
|
+
return await Promise.all(account.networks.map(async function (network) {
|
|
2669
|
+
const status = await account.status(network.chainId);
|
|
2670
|
+
return status.onChain.config;
|
|
2671
|
+
}));
|
|
2672
|
+
}
|
|
2673
|
+
}
|
|
2674
|
+
|
|
2675
|
+
// smart wallet method
|
|
2676
|
+
case 'sequence_getWalletState':
|
|
2677
|
+
{
|
|
2678
|
+
const [chainId] = request.params;
|
|
2679
|
+
// TODO: Add getWalletState to the Signer interface
|
|
2680
|
+
if (chainId) {
|
|
2681
|
+
return [getLegacyWalletState(chainId, await account.status(chainId))];
|
|
2682
|
+
} else {
|
|
2683
|
+
return await Promise.all(account.networks.map(async function (network) {
|
|
2684
|
+
const status = await account.status(network.chainId);
|
|
2685
|
+
return getLegacyWalletState(network.chainId, status);
|
|
2686
|
+
}));
|
|
2687
|
+
}
|
|
2688
|
+
}
|
|
2689
|
+
|
|
2690
|
+
// smart wallet method
|
|
2691
|
+
case 'sequence_getNetworks':
|
|
2692
|
+
{
|
|
2693
|
+
// NOTE: must ensure that the response result below returns clean serialized data, which is to omit
|
|
2694
|
+
// the provider and relayer objects and only return the urls so can be reinstantiated on dapp side.
|
|
2695
|
+
// This is handled by this.getNetworks() but noted here for future readers.
|
|
2696
|
+
return await this.getNetworks(true);
|
|
2697
|
+
}
|
|
2698
|
+
case 'sequence_isSequence':
|
|
2699
|
+
{
|
|
2700
|
+
return true;
|
|
2701
|
+
}
|
|
2702
|
+
|
|
2703
|
+
// smart wallet method
|
|
2704
|
+
case 'sequence_updateConfig':
|
|
2705
|
+
{
|
|
2706
|
+
throw new Error('sequence_updateConfig method is not allowed from a dapp');
|
|
2707
|
+
// NOTE: method is disabled as we don't need a dapp to request to update a config.
|
|
2708
|
+
// However, if we ever want this, we can enable it but must also use the prompter
|
|
2709
|
+
// for confirmation.
|
|
2710
|
+
//
|
|
2711
|
+
// const [newConfig] = request.params
|
|
2712
|
+
// return await signer.updateConfig(newConfig)
|
|
2713
|
+
}
|
|
2714
|
+
|
|
2715
|
+
// smart wallet method
|
|
2716
|
+
case 'sequence_publishConfig':
|
|
2717
|
+
{
|
|
2718
|
+
throw new Error('sequence_publishConfig method is not allowed from a dapp');
|
|
2719
|
+
}
|
|
2720
|
+
|
|
2721
|
+
// relayer method
|
|
2722
|
+
case 'sequence_gasRefundOptions':
|
|
2723
|
+
{
|
|
2724
|
+
// TODO
|
|
2725
|
+
break;
|
|
2726
|
+
}
|
|
2727
|
+
|
|
2728
|
+
// relayer method
|
|
2729
|
+
case 'sequence_getNonce':
|
|
2730
|
+
{
|
|
2731
|
+
// TODO
|
|
2732
|
+
break;
|
|
2733
|
+
}
|
|
2734
|
+
|
|
2735
|
+
// relayer method
|
|
2736
|
+
case 'sequence_relay':
|
|
2737
|
+
{
|
|
2738
|
+
// TODO
|
|
2739
|
+
break;
|
|
2740
|
+
}
|
|
2741
|
+
|
|
2742
|
+
// set default network of wallet
|
|
2743
|
+
case 'sequence_setDefaultNetwork':
|
|
2744
|
+
{
|
|
2745
|
+
const [defaultChainId] = request.params;
|
|
2746
|
+
if (!defaultChainId) {
|
|
2747
|
+
throw new Error('invalid request, method argument defaultChainId cannot be empty');
|
|
2748
|
+
}
|
|
2749
|
+
this.setDefaultChainId(defaultChainId);
|
|
2750
|
+
return await this.getNetworks(true);
|
|
2751
|
+
}
|
|
2752
|
+
default:
|
|
2753
|
+
{
|
|
2754
|
+
if (!jsonRpcProvider) {
|
|
2755
|
+
throw new Error(`Account provider doesn't support send method`);
|
|
2756
|
+
}
|
|
2757
|
+
|
|
2758
|
+
// NOTE: provider here will be chain-bound if chainId is provided
|
|
2759
|
+
return await jsonRpcProvider.send(request.method, request.params);
|
|
2760
|
+
}
|
|
2761
|
+
}
|
|
2762
|
+
} catch (err) {
|
|
2763
|
+
utils.logger.error(err);
|
|
2764
|
+
throw {
|
|
2765
|
+
message: err == null ? void 0 : err.message,
|
|
2766
|
+
code: 4001
|
|
2767
|
+
};
|
|
2768
|
+
}
|
|
2781
2769
|
}
|
|
2782
2770
|
on(event, fn) {
|
|
2783
2771
|
this.events.on(event, fn);
|
|
@@ -2865,7 +2853,7 @@ class WalletRequestHandler {
|
|
|
2865
2853
|
this.events.emit('disconnect', undefined, origin);
|
|
2866
2854
|
}
|
|
2867
2855
|
notifyChainChanged(chainId, origin) {
|
|
2868
|
-
this.events.emit('chainChanged', ethers.ethers.
|
|
2856
|
+
this.events.emit('chainChanged', ethers.ethers.toQuantity(chainId), origin);
|
|
2869
2857
|
}
|
|
2870
2858
|
async notifyNetworks(networks) {
|
|
2871
2859
|
const n = networks || (await this.getNetworks(true));
|
|
@@ -2873,7 +2861,7 @@ class WalletRequestHandler {
|
|
|
2873
2861
|
if (n.length > 0) {
|
|
2874
2862
|
const defaultNetwork = n.find(network => network.chainId === this.defaultChainId());
|
|
2875
2863
|
if (defaultNetwork) {
|
|
2876
|
-
this.events.emit('chainChanged', ethers.ethers.
|
|
2864
|
+
this.events.emit('chainChanged', ethers.ethers.toQuantity(defaultNetwork.chainId));
|
|
2877
2865
|
}
|
|
2878
2866
|
} else {
|
|
2879
2867
|
this.events.emit('chainChanged', '0x0');
|
|
@@ -2942,6 +2930,19 @@ function getLegacyWalletState(chainId, status) {
|
|
|
2942
2930
|
}
|
|
2943
2931
|
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
2932
|
|
|
2933
|
+
function _objectWithoutPropertiesLoose(source, excluded) {
|
|
2934
|
+
if (source == null) return {};
|
|
2935
|
+
var target = {};
|
|
2936
|
+
var sourceKeys = Object.keys(source);
|
|
2937
|
+
var key, i;
|
|
2938
|
+
for (i = 0; i < sourceKeys.length; i++) {
|
|
2939
|
+
key = sourceKeys[i];
|
|
2940
|
+
if (excluded.indexOf(key) >= 0) continue;
|
|
2941
|
+
target[key] = source[key];
|
|
2942
|
+
}
|
|
2943
|
+
return target;
|
|
2944
|
+
}
|
|
2945
|
+
|
|
2945
2946
|
class SequenceSigner {
|
|
2946
2947
|
get utils() {
|
|
2947
2948
|
return this.provider.utils;
|
|
@@ -2950,7 +2951,6 @@ class SequenceSigner {
|
|
|
2950
2951
|
this.client = client;
|
|
2951
2952
|
this.provider = provider;
|
|
2952
2953
|
this.singleNetworkSigners = {};
|
|
2953
|
-
this._isSigner = true;
|
|
2954
2954
|
this._isSequenceSigner = true;
|
|
2955
2955
|
}
|
|
2956
2956
|
async getAddress() {
|
|
@@ -3020,12 +3020,17 @@ class SequenceSigner {
|
|
|
3020
3020
|
});
|
|
3021
3021
|
const provider = this.getProvider(chainId);
|
|
3022
3022
|
try {
|
|
3023
|
-
|
|
3024
|
-
const
|
|
3025
|
-
|
|
3026
|
-
|
|
3027
|
-
|
|
3023
|
+
const result = await new Promise(resolve => {
|
|
3024
|
+
const check = async function check() {
|
|
3025
|
+
const tx = await provider.getTransaction(txHash);
|
|
3026
|
+
if (tx !== null) {
|
|
3027
|
+
return resolve(tx);
|
|
3028
|
+
}
|
|
3029
|
+
await provider.once('block', check);
|
|
3030
|
+
};
|
|
3031
|
+
check();
|
|
3028
3032
|
});
|
|
3033
|
+
return result;
|
|
3029
3034
|
} catch (err) {
|
|
3030
3035
|
err.transactionHash = txHash;
|
|
3031
3036
|
throw err;
|
|
@@ -3047,15 +3052,12 @@ class SequenceSigner {
|
|
|
3047
3052
|
async estimateGas(transaction, optionals) {
|
|
3048
3053
|
return this.getProvider(optionals == null ? void 0 : optionals.chainId).estimateGas(transaction);
|
|
3049
3054
|
}
|
|
3050
|
-
async call(transaction,
|
|
3051
|
-
return this.getProvider(optionals == null ? void 0 : optionals.chainId).call(transaction
|
|
3055
|
+
async call(transaction, optionals) {
|
|
3056
|
+
return this.getProvider(optionals == null ? void 0 : optionals.chainId).call(transaction);
|
|
3052
3057
|
}
|
|
3053
3058
|
getChainId() {
|
|
3054
3059
|
return Promise.resolve(this.client.getChainId());
|
|
3055
3060
|
}
|
|
3056
|
-
async getGasPrice(optionals) {
|
|
3057
|
-
return this.getProvider(optionals == null ? void 0 : optionals.chainId).getGasPrice();
|
|
3058
|
-
}
|
|
3059
3061
|
async getFeeData(optionals) {
|
|
3060
3062
|
return this.getProvider(optionals == null ? void 0 : optionals.chainId).getFeeData();
|
|
3061
3063
|
}
|
|
@@ -3063,7 +3065,7 @@ class SequenceSigner {
|
|
|
3063
3065
|
const res = await this.provider.resolveName(name);
|
|
3064
3066
|
|
|
3065
3067
|
// For some reason ethers.Signer expects this to return `string`
|
|
3066
|
-
// but ethers.
|
|
3068
|
+
// but ethers.Provider expects this to return `string | null`.
|
|
3067
3069
|
// The signer doesn't have any other source of information, so we'll
|
|
3068
3070
|
// fail if the provider doesn't return a result.
|
|
3069
3071
|
if (res === null) {
|
|
@@ -3074,6 +3076,12 @@ class SequenceSigner {
|
|
|
3074
3076
|
_checkProvider(_operation) {
|
|
3075
3077
|
// We always have a provider, so this is a noop
|
|
3076
3078
|
}
|
|
3079
|
+
getNonce(_blockTag) {
|
|
3080
|
+
throw new Error('SequenceSigner does not support getNonce');
|
|
3081
|
+
}
|
|
3082
|
+
populateCall(_transaction) {
|
|
3083
|
+
throw new Error('SequenceSigner does not support populateCall');
|
|
3084
|
+
}
|
|
3077
3085
|
populateTransaction(_transaction) {
|
|
3078
3086
|
throw new Error('SequenceSigner does not support populateTransaction');
|
|
3079
3087
|
}
|
|
@@ -3211,31 +3219,43 @@ class WalletUtils {
|
|
|
3211
3219
|
// recoverAddress()
|
|
3212
3220
|
}
|
|
3213
3221
|
|
|
3214
|
-
|
|
3215
|
-
|
|
3222
|
+
const _excluded = ["method"];
|
|
3223
|
+
const EIP1193EventTypes = ['connect', 'disconnect', 'chainChanged', 'accountsChanged'];
|
|
3224
|
+
class SequenceProvider extends ethers.ethers.AbstractProvider {
|
|
3225
|
+
constructor(client, providerFor, networks = network.allNetworks, options) {
|
|
3216
3226
|
// We support a lot of networks
|
|
3217
3227
|
// but we start with the default one
|
|
3218
|
-
super(client.getChainId());
|
|
3228
|
+
super(client.getChainId(), options);
|
|
3219
3229
|
|
|
3220
3230
|
// Emit events as defined by EIP-1193
|
|
3221
3231
|
this.client = client;
|
|
3222
3232
|
this.providerFor = providerFor;
|
|
3223
3233
|
this.networks = networks;
|
|
3234
|
+
this.options = options;
|
|
3224
3235
|
this.singleNetworkProviders = {};
|
|
3225
3236
|
this._isSequenceProvider = true;
|
|
3226
3237
|
this.utils = void 0;
|
|
3227
3238
|
this.signer = void 0;
|
|
3239
|
+
this.eip1193EventListeners = new Map();
|
|
3228
3240
|
client.onConnect(details => {
|
|
3229
|
-
|
|
3241
|
+
var _this$eip1193EventLis;
|
|
3242
|
+
//this.emit('connect', details)
|
|
3243
|
+
(_this$eip1193EventLis = this.eip1193EventListeners.get('connect')) == null || _this$eip1193EventLis.forEach(listener => listener(details));
|
|
3230
3244
|
});
|
|
3231
3245
|
client.onDisconnect(error => {
|
|
3232
|
-
|
|
3246
|
+
var _this$eip1193EventLis2;
|
|
3247
|
+
//this.emit('disconnect', error)
|
|
3248
|
+
(_this$eip1193EventLis2 = this.eip1193EventListeners.get('disconnect')) == null || _this$eip1193EventLis2.forEach(listener => listener(error));
|
|
3233
3249
|
});
|
|
3234
3250
|
client.onDefaultChainIdChanged(chainId => {
|
|
3235
|
-
|
|
3251
|
+
var _this$eip1193EventLis3;
|
|
3252
|
+
//this.emit('chainChanged', chainId)
|
|
3253
|
+
(_this$eip1193EventLis3 = this.eip1193EventListeners.get('chainChanged')) == null || _this$eip1193EventLis3.forEach(listener => listener(chainId));
|
|
3236
3254
|
});
|
|
3237
3255
|
client.onAccountsChanged(accounts => {
|
|
3238
|
-
|
|
3256
|
+
var _this$eip1193EventLis4;
|
|
3257
|
+
//this.emit('accountsChanged', accounts)
|
|
3258
|
+
(_this$eip1193EventLis4 = this.eip1193EventListeners.get('accountsChanged')) == null || _this$eip1193EventLis4.forEach(listener => listener(accounts));
|
|
3239
3259
|
});
|
|
3240
3260
|
|
|
3241
3261
|
// NOTICE: We don't emit 'open' and 'close' events
|
|
@@ -3252,6 +3272,29 @@ class SequenceProvider extends ethers.ethers.providers.BaseProvider {
|
|
|
3252
3272
|
// Create a utils instance
|
|
3253
3273
|
this.utils = new WalletUtils(this.signer);
|
|
3254
3274
|
}
|
|
3275
|
+
async on(event, listener) {
|
|
3276
|
+
if (EIP1193EventTypes.includes(event)) {
|
|
3277
|
+
const listeners = this.eip1193EventListeners.get(event) || new Set();
|
|
3278
|
+
listeners.add(listener);
|
|
3279
|
+
this.eip1193EventListeners.set(event, listeners);
|
|
3280
|
+
return this;
|
|
3281
|
+
}
|
|
3282
|
+
return super.on(event, listener);
|
|
3283
|
+
}
|
|
3284
|
+
async off(event, listener) {
|
|
3285
|
+
if (EIP1193EventTypes.includes(event)) {
|
|
3286
|
+
const listeners = this.eip1193EventListeners.get(event);
|
|
3287
|
+
if (listeners) {
|
|
3288
|
+
if (listener) {
|
|
3289
|
+
listeners.delete(listener);
|
|
3290
|
+
} else {
|
|
3291
|
+
listeners.clear();
|
|
3292
|
+
}
|
|
3293
|
+
}
|
|
3294
|
+
return this;
|
|
3295
|
+
}
|
|
3296
|
+
return super.off(event, listener);
|
|
3297
|
+
}
|
|
3255
3298
|
getSigner(chainId) {
|
|
3256
3299
|
return this.signer.getSigner(chainId);
|
|
3257
3300
|
}
|
|
@@ -3344,7 +3387,7 @@ class SequenceProvider extends ethers.ethers.providers.BaseProvider {
|
|
|
3344
3387
|
}
|
|
3345
3388
|
const useChainId = this.toChainId(chainId);
|
|
3346
3389
|
if (!this.singleNetworkProviders[useChainId]) {
|
|
3347
|
-
this.singleNetworkProviders[useChainId] = new SingleNetworkSequenceProvider(this.client, this.providerFor, useChainId);
|
|
3390
|
+
this.singleNetworkProviders[useChainId] = new SingleNetworkSequenceProvider(this.client, this.providerFor, useChainId, this.options);
|
|
3348
3391
|
}
|
|
3349
3392
|
return this.singleNetworkProviders[useChainId];
|
|
3350
3393
|
}
|
|
@@ -3364,11 +3407,26 @@ class SequenceProvider extends ethers.ethers.providers.BaseProvider {
|
|
|
3364
3407
|
}
|
|
3365
3408
|
return provider;
|
|
3366
3409
|
}
|
|
3410
|
+
async _perform(req) {
|
|
3411
|
+
var _provider$getRpcReque;
|
|
3412
|
+
const {
|
|
3413
|
+
method
|
|
3414
|
+
} = req,
|
|
3415
|
+
args = _objectWithoutPropertiesLoose(req, _excluded);
|
|
3416
|
+
const provider = await this._getSubprovider();
|
|
3417
|
+
const prepared = (_provider$getRpcReque = provider.getRpcRequest(req)) != null ? _provider$getRpcReque : {
|
|
3418
|
+
method,
|
|
3419
|
+
args: Object.values(args)
|
|
3420
|
+
};
|
|
3421
|
+
if (!prepared) {
|
|
3422
|
+
throw new Error(`Unsupported method ${req.method}`);
|
|
3423
|
+
}
|
|
3424
|
+
return provider.send(prepared.method, prepared.args);
|
|
3425
|
+
}
|
|
3367
3426
|
async perform(method, params) {
|
|
3368
|
-
var _provider$prepareRequ;
|
|
3369
3427
|
// First we check if the method should be handled by the client
|
|
3370
3428
|
if (method === 'eth_chainId') {
|
|
3371
|
-
return ethers.ethers.
|
|
3429
|
+
return ethers.ethers.toQuantity(await this.useChainId());
|
|
3372
3430
|
}
|
|
3373
3431
|
if (method === 'eth_accounts') {
|
|
3374
3432
|
return [this.client.getAddress()];
|
|
@@ -3388,17 +3446,15 @@ class SequenceProvider extends ethers.ethers.providers.BaseProvider {
|
|
|
3388
3446
|
method === 'sequence_sign' || method === 'sequence_signTypedData_v4') {
|
|
3389
3447
|
// We pass the chainId to the client, if we don't pass one
|
|
3390
3448
|
// the client will use its own default chainId
|
|
3391
|
-
return this.client.
|
|
3449
|
+
return this.client.request({
|
|
3392
3450
|
method,
|
|
3393
|
-
params
|
|
3394
|
-
|
|
3451
|
+
params,
|
|
3452
|
+
chainId: this.getChainId()
|
|
3453
|
+
});
|
|
3395
3454
|
}
|
|
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]);
|
|
3455
|
+
return this._perform(_extends({
|
|
3456
|
+
method
|
|
3457
|
+
}, params));
|
|
3402
3458
|
}
|
|
3403
3459
|
send(method, params) {
|
|
3404
3460
|
return this.perform(method, params);
|
|
@@ -3406,14 +3462,18 @@ class SequenceProvider extends ethers.ethers.providers.BaseProvider {
|
|
|
3406
3462
|
request(request) {
|
|
3407
3463
|
return this.perform(request.method, request.params);
|
|
3408
3464
|
}
|
|
3409
|
-
async
|
|
3465
|
+
async _detectNetwork() {
|
|
3410
3466
|
const chainId = this.client.getChainId();
|
|
3411
|
-
const
|
|
3412
|
-
if (!
|
|
3467
|
+
const found = network.findNetworkConfig(this.networks, chainId);
|
|
3468
|
+
if (!found) {
|
|
3413
3469
|
throw new Error(`Unknown network ${chainId}`);
|
|
3414
3470
|
}
|
|
3471
|
+
const network$1 = new ethers.ethers.Network(found.name, found.chainId);
|
|
3415
3472
|
return network$1;
|
|
3416
3473
|
}
|
|
3474
|
+
async detectNetwork() {
|
|
3475
|
+
return this._detectNetwork();
|
|
3476
|
+
}
|
|
3417
3477
|
|
|
3418
3478
|
// Override most of the methods, so we add support for an optional chainId
|
|
3419
3479
|
// argument, which is used to select the provider to use.
|
|
@@ -3430,9 +3490,9 @@ class SequenceProvider extends ethers.ethers.providers.BaseProvider {
|
|
|
3430
3490
|
const provider = await this._getSubprovider(optionals == null ? void 0 : optionals.chainId);
|
|
3431
3491
|
return provider.getBlockNumber();
|
|
3432
3492
|
}
|
|
3433
|
-
async
|
|
3493
|
+
async getFeeData(optionals) {
|
|
3434
3494
|
const provider = await this._getSubprovider(optionals == null ? void 0 : optionals.chainId);
|
|
3435
|
-
return provider.
|
|
3495
|
+
return provider.getFeeData();
|
|
3436
3496
|
}
|
|
3437
3497
|
async getBalance(addressOrName, blockTag, optionals) {
|
|
3438
3498
|
const provider = await this._getSubprovider(optionals == null ? void 0 : optionals.chainId);
|
|
@@ -3446,21 +3506,21 @@ class SequenceProvider extends ethers.ethers.providers.BaseProvider {
|
|
|
3446
3506
|
const provider = await this._getSubprovider(optionals == null ? void 0 : optionals.chainId);
|
|
3447
3507
|
return provider.getCode(addressOrName, blockTag);
|
|
3448
3508
|
}
|
|
3449
|
-
async
|
|
3509
|
+
async getStorage(addressOrName, position, blockTag, optionals) {
|
|
3450
3510
|
const provider = await this._getSubprovider(optionals == null ? void 0 : optionals.chainId);
|
|
3451
|
-
return provider.
|
|
3511
|
+
return provider.getStorage(addressOrName, position, blockTag);
|
|
3452
3512
|
}
|
|
3453
|
-
async call(transaction,
|
|
3513
|
+
async call(transaction, optionals) {
|
|
3454
3514
|
const provider = await this._getSubprovider(optionals == null ? void 0 : optionals.chainId);
|
|
3455
|
-
return provider.call(transaction
|
|
3515
|
+
return provider.call(transaction);
|
|
3456
3516
|
}
|
|
3457
3517
|
async estimateGas(transaction, optionals) {
|
|
3458
3518
|
const provider = await this._getSubprovider(optionals == null ? void 0 : optionals.chainId);
|
|
3459
3519
|
return provider.estimateGas(transaction);
|
|
3460
3520
|
}
|
|
3461
|
-
async getBlock(blockHashOrBlockTag, optionals) {
|
|
3521
|
+
async getBlock(blockHashOrBlockTag, prefetchTxs, optionals) {
|
|
3462
3522
|
const provider = await this._getSubprovider(optionals == null ? void 0 : optionals.chainId);
|
|
3463
|
-
return provider.getBlock(blockHashOrBlockTag);
|
|
3523
|
+
return provider.getBlock(blockHashOrBlockTag, prefetchTxs);
|
|
3464
3524
|
}
|
|
3465
3525
|
async getTransaction(transactionHash, optionals) {
|
|
3466
3526
|
const provider = await this._getSubprovider(optionals == null ? void 0 : optionals.chainId);
|
|
@@ -3487,7 +3547,7 @@ class SequenceProvider extends ethers.ethers.providers.BaseProvider {
|
|
|
3487
3547
|
return provider.getResolver(name);
|
|
3488
3548
|
}
|
|
3489
3549
|
async resolveName(name) {
|
|
3490
|
-
if (ethers.ethers.
|
|
3550
|
+
if (ethers.ethers.isAddress(name)) {
|
|
3491
3551
|
return name;
|
|
3492
3552
|
}
|
|
3493
3553
|
if (!(await this.supportsENS())) {
|
|
@@ -3520,7 +3580,7 @@ SequenceProvider.is = provider => {
|
|
|
3520
3580
|
};
|
|
3521
3581
|
function normalizeChainId(chainId) {
|
|
3522
3582
|
if (typeof chainId === 'object') return normalizeChainId(chainId.chainId);
|
|
3523
|
-
return
|
|
3583
|
+
return Number(chainId);
|
|
3524
3584
|
}
|
|
3525
3585
|
|
|
3526
3586
|
/**
|
|
@@ -3533,8 +3593,8 @@ function normalizeChainId(chainId) {
|
|
|
3533
3593
|
* NOTICE: These networks won't support ENS unless they are the mainnet.
|
|
3534
3594
|
*/
|
|
3535
3595
|
class SingleNetworkSequenceProvider extends SequenceProvider {
|
|
3536
|
-
constructor(client, providerFor, chainId) {
|
|
3537
|
-
super(client, providerFor);
|
|
3596
|
+
constructor(client, providerFor, chainId, options) {
|
|
3597
|
+
super(client, providerFor, undefined, options);
|
|
3538
3598
|
this.chainId = chainId;
|
|
3539
3599
|
this._isSingleNetworkSequenceProvider = true;
|
|
3540
3600
|
}
|
|
@@ -3553,11 +3613,11 @@ class SingleNetworkSequenceProvider extends SequenceProvider {
|
|
|
3553
3613
|
}
|
|
3554
3614
|
async getNetwork() {
|
|
3555
3615
|
const networks = await this.client.getNetworks();
|
|
3556
|
-
const
|
|
3557
|
-
if (!
|
|
3616
|
+
const found = network.findNetworkConfig(networks, this.chainId);
|
|
3617
|
+
if (!found) {
|
|
3558
3618
|
throw new Error(`Unsupported network ${this.chainId}`);
|
|
3559
3619
|
}
|
|
3560
|
-
return
|
|
3620
|
+
return new ethers.ethers.Network(found.name, found.chainId);
|
|
3561
3621
|
}
|
|
3562
3622
|
|
|
3563
3623
|
/**
|
|
@@ -3620,55 +3680,6 @@ const setupAnalytics = (projectAccessKey, server) => {
|
|
|
3620
3680
|
});
|
|
3621
3681
|
};
|
|
3622
3682
|
|
|
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
3683
|
/**
|
|
3673
3684
|
* This session class is meant to persist the state of the wallet connection
|
|
3674
3685
|
* whitin the dapp. This enables the client to retain the wallet address (and some more)
|
|
@@ -3784,7 +3795,7 @@ class SequenceClient {
|
|
|
3784
3795
|
});
|
|
3785
3796
|
this.transport.on('connect', response => {
|
|
3786
3797
|
var _this$callbacks$conne;
|
|
3787
|
-
const chainIdHex = ethers.ethers.
|
|
3798
|
+
const chainIdHex = ethers.ethers.toQuantity(this.getChainId());
|
|
3788
3799
|
(_this$callbacks$conne = this.callbacks.connect) == null || _this$callbacks$conne.forEach(cb => cb(_extends({}, response, {
|
|
3789
3800
|
// Ignore the full connect response
|
|
3790
3801
|
// use the chainId defined locally
|
|
@@ -3820,7 +3831,7 @@ class SequenceClient {
|
|
|
3820
3831
|
// instead we handle it locally, so we listen for changes in the store
|
|
3821
3832
|
this.defaultChainId.onDefaultChainIdChanged(chainId => {
|
|
3822
3833
|
var _this$callbacks$chain2;
|
|
3823
|
-
const chainIdHex = ethers.ethers.
|
|
3834
|
+
const chainIdHex = ethers.ethers.toQuantity(chainId);
|
|
3824
3835
|
(_this$callbacks$chain2 = this.callbacks.chainChanged) == null || _this$callbacks$chain2.forEach(cb => cb(chainIdHex));
|
|
3825
3836
|
});
|
|
3826
3837
|
if (options != null && options.projectAccessKey) {
|
|
@@ -3933,7 +3944,7 @@ class SequenceClient {
|
|
|
3933
3944
|
type: 'connect',
|
|
3934
3945
|
options: _extends({}, options, {
|
|
3935
3946
|
networkId: this.getChainId(),
|
|
3936
|
-
clientVersion:
|
|
3947
|
+
clientVersion: core.VERSION
|
|
3937
3948
|
})
|
|
3938
3949
|
});
|
|
3939
3950
|
const connectDetails = await this.transport.waitUntilConnected().catch(error => {
|
|
@@ -3953,7 +3964,7 @@ class SequenceClient {
|
|
|
3953
3964
|
// Normalize chainId into a decimal string
|
|
3954
3965
|
// TODO: Remove this once wallet-webapp returns chainId as a string
|
|
3955
3966
|
if (connectDetails.chainId) {
|
|
3956
|
-
connectDetails.chainId =
|
|
3967
|
+
connectDetails.chainId = BigInt(connectDetails.chainId).toString();
|
|
3957
3968
|
}
|
|
3958
3969
|
if (connectDetails.connected) {
|
|
3959
3970
|
var _connectDetails$sessi;
|
|
@@ -3979,33 +3990,20 @@ class SequenceClient {
|
|
|
3979
3990
|
|
|
3980
3991
|
// Higher level API
|
|
3981
3992
|
|
|
3982
|
-
|
|
3983
|
-
// but transport uses it instead of send, so we wrap it
|
|
3984
|
-
send(request, chainId) {
|
|
3993
|
+
async request(request) {
|
|
3985
3994
|
// Internally when sending requests we use `legacy_sign`
|
|
3986
3995
|
// to avoid the default EIP6492 behavior overriding an explicit
|
|
3987
3996
|
// "legacy sign" request, so we map the method here.
|
|
3988
3997
|
request.method = this.mapSignMethod(request.method);
|
|
3989
|
-
|
|
3990
|
-
|
|
3991
|
-
|
|
3992
|
-
|
|
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
|
-
});
|
|
3998
|
+
const result = await this.transport.request(request);
|
|
3999
|
+
|
|
4000
|
+
// We may need to unwrap the response if it's a JSON-RPC response. ie. older universal wallet versions
|
|
4001
|
+
return unwrapJsonRpcResponse(result);
|
|
4004
4002
|
}
|
|
4005
4003
|
async getNetworks(pull) {
|
|
4006
4004
|
const connectedSession = this.session.connectedSession();
|
|
4007
4005
|
if (pull) {
|
|
4008
|
-
connectedSession.networks = await this.
|
|
4006
|
+
connectedSession.networks = await this.request({
|
|
4009
4007
|
method: 'sequence_getNetworks'
|
|
4010
4008
|
});
|
|
4011
4009
|
this.session.setSession(connectedSession);
|
|
@@ -4061,15 +4059,14 @@ class SequenceClient {
|
|
|
4061
4059
|
chainId: `${(options == null ? void 0 : options.chainId) || this.getChainId()}`
|
|
4062
4060
|
}
|
|
4063
4061
|
});
|
|
4064
|
-
|
|
4065
|
-
// Serialize a BytesLike or string message into a hex string before sending
|
|
4066
|
-
message = ethers.ethers.utils.hexlify(messageToBytes(message));
|
|
4062
|
+
message = ethers.ethers.hexlify(messageToBytes(message));
|
|
4067
4063
|
|
|
4068
4064
|
// Address is ignored by the wallet webapp
|
|
4069
|
-
return this.
|
|
4065
|
+
return this.request({
|
|
4070
4066
|
method,
|
|
4071
|
-
params: [message, this.getAddress()]
|
|
4072
|
-
|
|
4067
|
+
params: [message, this.getAddress()],
|
|
4068
|
+
chainId: options == null ? void 0 : options.chainId
|
|
4069
|
+
});
|
|
4073
4070
|
}
|
|
4074
4071
|
async signTypedData(typedData, options) {
|
|
4075
4072
|
var _this$analytics5;
|
|
@@ -4077,7 +4074,7 @@ class SequenceClient {
|
|
|
4077
4074
|
|
|
4078
4075
|
// TODO: Stop using ethers for this, this is the only place where we use it
|
|
4079
4076
|
// and it makes the client depend on ethers.
|
|
4080
|
-
const encoded = ethers.ethers.
|
|
4077
|
+
const encoded = ethers.ethers.TypedDataEncoder.getPayload(typedData.domain, typedData.types, typedData.message);
|
|
4081
4078
|
|
|
4082
4079
|
// The sign typed data will use one of the following chainIds, in order:
|
|
4083
4080
|
// - The one provided in the options
|
|
@@ -4090,10 +4087,11 @@ class SequenceClient {
|
|
|
4090
4087
|
chainId: `${(options == null ? void 0 : options.chainId) || this.getChainId()}`
|
|
4091
4088
|
}
|
|
4092
4089
|
});
|
|
4093
|
-
return this.
|
|
4090
|
+
return this.request({
|
|
4094
4091
|
method,
|
|
4095
|
-
params: [this.getAddress(), encoded]
|
|
4096
|
-
|
|
4092
|
+
params: [this.getAddress(), encoded],
|
|
4093
|
+
chainId: (options == null ? void 0 : options.chainId) || typedData.domain.chainId && Number(typedData.domain.chainId) || this.getChainId()
|
|
4094
|
+
});
|
|
4097
4095
|
}
|
|
4098
4096
|
async sendTransaction(tx, options) {
|
|
4099
4097
|
var _this$analytics6;
|
|
@@ -4105,22 +4103,24 @@ class SequenceClient {
|
|
|
4105
4103
|
chainId: `${(options == null ? void 0 : options.chainId) || this.getChainId()}`
|
|
4106
4104
|
}
|
|
4107
4105
|
});
|
|
4108
|
-
return this.
|
|
4106
|
+
return this.request({
|
|
4109
4107
|
method: 'eth_sendTransaction',
|
|
4110
|
-
params: [extendedTxs]
|
|
4111
|
-
|
|
4108
|
+
params: [extendedTxs],
|
|
4109
|
+
chainId: options == null ? void 0 : options.chainId
|
|
4110
|
+
});
|
|
4112
4111
|
}
|
|
4113
4112
|
async getWalletContext() {
|
|
4114
|
-
return this.
|
|
4113
|
+
return this.request({
|
|
4115
4114
|
method: 'sequence_getWalletContext'
|
|
4116
4115
|
});
|
|
4117
4116
|
}
|
|
4118
4117
|
async getOnchainWalletConfig(options) {
|
|
4119
4118
|
// NOTICE: sequence_getWalletConfig sends the chainId as a param
|
|
4120
|
-
const res = await this.
|
|
4119
|
+
const res = await this.request({
|
|
4121
4120
|
method: 'sequence_getWalletConfig',
|
|
4122
|
-
params: [(options == null ? void 0 : options.chainId) || this.getChainId()]
|
|
4123
|
-
|
|
4121
|
+
params: [(options == null ? void 0 : options.chainId) || this.getChainId()],
|
|
4122
|
+
chainId: options == null ? void 0 : options.chainId
|
|
4123
|
+
});
|
|
4124
4124
|
return Array.isArray(res) ? res[0] : res;
|
|
4125
4125
|
}
|
|
4126
4126
|
|
|
@@ -4130,6 +4130,14 @@ class SequenceClient {
|
|
|
4130
4130
|
// exclusively used for Sequence specific methods
|
|
4131
4131
|
}
|
|
4132
4132
|
|
|
4133
|
+
// Unwrap a JsonRpcResponse result
|
|
4134
|
+
const unwrapJsonRpcResponse = response => {
|
|
4135
|
+
if (response && typeof response === 'object' && 'jsonrpc' in response && 'result' in response) {
|
|
4136
|
+
return response.result;
|
|
4137
|
+
}
|
|
4138
|
+
return response;
|
|
4139
|
+
};
|
|
4140
|
+
|
|
4133
4141
|
const DefaultProviderConfig = {
|
|
4134
4142
|
transports: {
|
|
4135
4143
|
walletAppURL: 'https://sequence.app',
|
|
@@ -4199,9 +4207,11 @@ const initWallet = (projectAccessKey, partialConfig) => {
|
|
|
4199
4207
|
if (!rpcUrl) {
|
|
4200
4208
|
throw new Error(`no rpcUrl found for chainId: ${chainId}`);
|
|
4201
4209
|
}
|
|
4202
|
-
|
|
4203
|
-
|
|
4204
|
-
|
|
4210
|
+
rpcProviders[chainId] = new network.JsonRpcProvider(rpcUrl, {
|
|
4211
|
+
middlewares: [network.loggingProviderMiddleware, network.exceptionProviderMiddleware, new network.CachedProvider()]
|
|
4212
|
+
}, {
|
|
4213
|
+
cacheTimeout: -1
|
|
4214
|
+
});
|
|
4205
4215
|
}
|
|
4206
4216
|
return rpcProviders[chainId];
|
|
4207
4217
|
};
|