@toruslabs/ethereum-controllers 4.5.2 → 4.7.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/ethereumControllers.cjs.js +390 -13
- package/dist/ethereumControllers.cjs.js.map +1 -1
- package/dist/ethereumControllers.esm.js +368 -15
- package/dist/ethereumControllers.esm.js.map +1 -1
- package/dist/ethereumControllers.umd.min.js +1 -1
- package/dist/ethereumControllers.umd.min.js.LICENSE.txt +0 -2
- package/dist/ethereumControllers.umd.min.js.map +1 -1
- package/dist/types/Message/AddChainController.d.ts +20 -0
- package/dist/types/Message/DecryptMessageController.d.ts +2 -2
- package/dist/types/Message/EncryptionPublicKeyController.d.ts +2 -2
- package/dist/types/Message/MessageController.d.ts +2 -2
- package/dist/types/Message/PersonalMessageController.d.ts +2 -2
- package/dist/types/Message/SwitchChainController.d.ts +20 -0
- package/dist/types/Message/TypedMessageController.d.ts +2 -2
- package/dist/types/Message/utils.d.ts +3 -1
- package/dist/types/Network/createEthereumMiddleware.d.ts +23 -15
- package/dist/types/Preferences/PreferencesController.d.ts +9 -2
- package/dist/types/index.d.ts +2 -0
- package/dist/types/utils/constants.d.ts +2 -0
- package/dist/types/utils/interfaces.d.ts +22 -1
- package/package.json +10 -10
- package/src/Message/AddChainController.ts +73 -0
- package/src/Message/DecryptMessageController.ts +2 -5
- package/src/Message/EncryptionPublicKeyController.ts +2 -8
- package/src/Message/MessageController.ts +2 -2
- package/src/Message/PersonalMessageController.ts +3 -3
- package/src/Message/SwitchChainController.ts +74 -0
- package/src/Message/TypedMessageController.ts +2 -2
- package/src/Message/utils.ts +49 -1
- package/src/Network/createEthereumMiddleware.ts +190 -26
- package/src/Preferences/PreferencesController.ts +66 -1
- package/src/index.ts +2 -0
- package/src/utils/constants.ts +2 -0
- package/src/utils/interfaces.ts +26 -1
package/src/Message/utils.ts
CHANGED
|
@@ -1,8 +1,16 @@
|
|
|
1
1
|
import { addHexPrefix, bytesToHex, isValidAddress, stripHexPrefix } from "@ethereumjs/util";
|
|
2
2
|
import { EthEncryptedData, TYPED_MESSAGE_SCHEMA, TypedDataV1Field, typedSignatureHash } from "@metamask/eth-sig-util";
|
|
3
|
+
import { isHexString, JsonRpcProvider, toQuantity } from "ethers";
|
|
3
4
|
import { validate } from "jsonschema";
|
|
4
5
|
|
|
5
|
-
import {
|
|
6
|
+
import {
|
|
7
|
+
AddChainMessageParams,
|
|
8
|
+
DecryptMessageParams,
|
|
9
|
+
EncryptionPublicKeyParams,
|
|
10
|
+
MessageParams,
|
|
11
|
+
SwitchChainMessageParams,
|
|
12
|
+
TypedMessageParams,
|
|
13
|
+
} from "../utils/interfaces";
|
|
6
14
|
|
|
7
15
|
const hexRe = /^[0-9A-Fa-f]+$/gu;
|
|
8
16
|
|
|
@@ -105,3 +113,43 @@ export function parseDecryptMessageData(data: string): EthEncryptedData {
|
|
|
105
113
|
const buffer = Buffer.from(stripped, "hex");
|
|
106
114
|
return JSON.parse(buffer.toString("utf8")) as EthEncryptedData;
|
|
107
115
|
}
|
|
116
|
+
|
|
117
|
+
export async function validateAddChainData(data: AddChainMessageParams) {
|
|
118
|
+
const { chainId, rpcUrls, nativeCurrency } = data || {};
|
|
119
|
+
|
|
120
|
+
if (!chainId) {
|
|
121
|
+
throw new Error("Invalid add chain params: please pass chainId in params");
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
if (!isHexString(chainId)) {
|
|
125
|
+
throw new Error("Invalid add chain params: please pass a valid hex chainId in params, for: ex: 0x1");
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
if (!rpcUrls || rpcUrls.length === 0) throw new Error("params.rpcUrls not provided");
|
|
129
|
+
if (!nativeCurrency) throw new Error("params.nativeCurrency not provided");
|
|
130
|
+
const { name, symbol, decimals } = nativeCurrency;
|
|
131
|
+
|
|
132
|
+
if (!name) throw new Error("params.nativeCurrency.name not provided");
|
|
133
|
+
if (!symbol) throw new Error("params.nativeCurrency.symbol not provided");
|
|
134
|
+
if (decimals === undefined) throw new Error("params.nativeCurrency.decimals not provided");
|
|
135
|
+
|
|
136
|
+
const _web3 = new JsonRpcProvider(rpcUrls[0], "any");
|
|
137
|
+
const { chainId: networkChainID } = await _web3.getNetwork();
|
|
138
|
+
if (Number.parseInt(networkChainID.toString()) !== Number.parseInt(chainId, 16)) {
|
|
139
|
+
throw new Error(
|
|
140
|
+
`Provided rpc url's chainId version is not matching with provided chainId, expected: ${toQuantity(networkChainID)}, received: ${chainId}`
|
|
141
|
+
);
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
export function validateSwitchChainData(data: SwitchChainMessageParams) {
|
|
146
|
+
const { chainId } = data || {};
|
|
147
|
+
|
|
148
|
+
if (!chainId) {
|
|
149
|
+
throw new Error("Invalid switch chain params: please pass chainId in params");
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
if (!isHexString(chainId)) {
|
|
153
|
+
throw new Error("Invalid switch chain params: please pass a valid hex chainId in params, for: ex: 0x1");
|
|
154
|
+
}
|
|
155
|
+
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { SignTypedDataVersion } from "@metamask/eth-sig-util";
|
|
1
2
|
import { InPageWalletProviderState, PROVIDER_JRPC_METHODS } from "@toruslabs/base-controllers";
|
|
2
3
|
import {
|
|
3
4
|
createAsyncMiddleware,
|
|
@@ -12,10 +13,12 @@ import {
|
|
|
12
13
|
|
|
13
14
|
import { METHOD_TYPES, TRANSACTION_ENVELOPE_TYPES } from "../utils/constants";
|
|
14
15
|
import {
|
|
16
|
+
AddChainMessageParams,
|
|
15
17
|
BlockParams,
|
|
16
18
|
EncryptionPublicKeyParams,
|
|
17
19
|
EthereumTransactionMeta,
|
|
18
20
|
MessageParams,
|
|
21
|
+
SwitchChainMessageParams,
|
|
19
22
|
TransactionParams,
|
|
20
23
|
TransactionRPCMeta,
|
|
21
24
|
TypedMessageParams,
|
|
@@ -30,17 +33,18 @@ export interface IProviderHandlers {
|
|
|
30
33
|
// All operations which open popup window or modal should operate with a windowId parameter
|
|
31
34
|
processTransaction?: (txParams: TransactionParams, req: JRPCRequest<TransactionParams> & UserRequestApprovalParams) => Promise<string>;
|
|
32
35
|
|
|
33
|
-
processEthSignMessage?: (msgParams: MessageParams, req: JRPCRequest<
|
|
34
|
-
processTypedMessage?: (msgParams: TypedMessageParams, req: JRPCRequest<
|
|
35
|
-
processTypedMessageV3?: (msgParams: TypedMessageParams, req: JRPCRequest<
|
|
36
|
-
processTypedMessageV4?: (msgParams: TypedMessageParams, req: JRPCRequest<
|
|
37
|
-
processPersonalMessage?: (msgParams: MessageParams, req: JRPCRequest<
|
|
36
|
+
processEthSignMessage?: (msgParams: MessageParams, req: JRPCRequest<unknown> & UserRequestApprovalParams) => Promise<string>;
|
|
37
|
+
processTypedMessage?: (msgParams: TypedMessageParams, req: JRPCRequest<unknown> & UserRequestApprovalParams) => Promise<string>;
|
|
38
|
+
processTypedMessageV3?: (msgParams: TypedMessageParams, req: JRPCRequest<unknown> & UserRequestApprovalParams) => Promise<string>;
|
|
39
|
+
processTypedMessageV4?: (msgParams: TypedMessageParams, req: JRPCRequest<unknown> & UserRequestApprovalParams) => Promise<string>;
|
|
40
|
+
processPersonalMessage?: (msgParams: MessageParams, req: JRPCRequest<unknown> & UserRequestApprovalParams) => Promise<string>;
|
|
38
41
|
|
|
39
|
-
processEncryptionPublicKey?: (
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
) => Promise<string>;
|
|
43
|
-
|
|
42
|
+
processEncryptionPublicKey?: (msgParams: EncryptionPublicKeyParams, req: JRPCRequest<unknown> & UserRequestApprovalParams) => Promise<string>;
|
|
43
|
+
processDecryptMessage?: (msgParams: MessageParams, req: JRPCRequest<unknown> & UserRequestApprovalParams) => Promise<string>;
|
|
44
|
+
|
|
45
|
+
processSwitchEthereumChain?: (msgParams: SwitchChainMessageParams, req: JRPCRequest<unknown> & UserRequestApprovalParams) => Promise<string>;
|
|
46
|
+
|
|
47
|
+
processAddEthereumChain?: (msgParams: AddChainMessageParams, req: JRPCRequest<unknown> & UserRequestApprovalParams) => Promise<string>;
|
|
44
48
|
|
|
45
49
|
getPendingNonce?: (
|
|
46
50
|
nonceParams: { address: string; blockReference: string },
|
|
@@ -87,14 +91,30 @@ export function createProcessEthSignMessage({
|
|
|
87
91
|
processEthSignMessage,
|
|
88
92
|
}: {
|
|
89
93
|
processEthSignMessage: IProviderHandlers["processEthSignMessage"];
|
|
90
|
-
}): JRPCMiddleware<
|
|
94
|
+
}): JRPCMiddleware<unknown, string> {
|
|
91
95
|
return createAsyncMiddleware(async (request, response, next) => {
|
|
92
96
|
const { method } = request;
|
|
93
97
|
if (method !== METHOD_TYPES.ETH_SIGN) return next();
|
|
94
98
|
|
|
95
99
|
if (!processEthSignMessage) throw new Error("WalletMiddleware - opts.processEthSignMessage not provided");
|
|
100
|
+
if (!request?.params) throw new Error("WalletMiddleware - missing params");
|
|
101
|
+
|
|
102
|
+
let msgParams: MessageParams = request.params as MessageParams;
|
|
103
|
+
|
|
104
|
+
if (Array.isArray(request.params)) {
|
|
105
|
+
if (!(request.params.length === 2)) throw new Error(`WalletMiddleware - incorrect params for ${method} method. expected [address, message]`);
|
|
96
106
|
|
|
97
|
-
|
|
107
|
+
const params = request.params as [string, string];
|
|
108
|
+
const address = params[0];
|
|
109
|
+
const message = params[1];
|
|
110
|
+
|
|
111
|
+
msgParams = {
|
|
112
|
+
from: address,
|
|
113
|
+
data: message,
|
|
114
|
+
};
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
response.result = await processEthSignMessage(msgParams, request);
|
|
98
118
|
});
|
|
99
119
|
}
|
|
100
120
|
|
|
@@ -102,13 +122,31 @@ export function createProcessTypedMessage({
|
|
|
102
122
|
processTypedMessage,
|
|
103
123
|
}: {
|
|
104
124
|
processTypedMessage: IProviderHandlers["processTypedMessage"];
|
|
105
|
-
}): JRPCMiddleware<
|
|
125
|
+
}): JRPCMiddleware<unknown, string> {
|
|
106
126
|
return createAsyncMiddleware(async (request, response, next) => {
|
|
107
127
|
const { method } = request;
|
|
108
128
|
if (method !== METHOD_TYPES.ETH_SIGN_TYPED_DATA) return next();
|
|
109
129
|
|
|
110
130
|
if (!processTypedMessage) throw new Error("WalletMiddleware - opts.processTypedMessage not provided");
|
|
111
|
-
|
|
131
|
+
if (!request?.params) throw new Error("WalletMiddleware - missing params");
|
|
132
|
+
|
|
133
|
+
let msgParams: TypedMessageParams = request.params as TypedMessageParams;
|
|
134
|
+
|
|
135
|
+
if (Array.isArray(request.params)) {
|
|
136
|
+
if (!(request.params.length === 2)) throw new Error(`WalletMiddleware - incorrect params for ${method} method. expected [typedData, address]`);
|
|
137
|
+
|
|
138
|
+
const params = request.params as [Record<string, unknown>[], string];
|
|
139
|
+
const message = params[0];
|
|
140
|
+
const address = params[1];
|
|
141
|
+
|
|
142
|
+
msgParams = {
|
|
143
|
+
from: address,
|
|
144
|
+
data: message,
|
|
145
|
+
version: SignTypedDataVersion.V1,
|
|
146
|
+
};
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
response.result = await processTypedMessage(msgParams, request);
|
|
112
150
|
});
|
|
113
151
|
}
|
|
114
152
|
|
|
@@ -116,14 +154,31 @@ export function createProcessTypedMessageV3({
|
|
|
116
154
|
processTypedMessageV3,
|
|
117
155
|
}: {
|
|
118
156
|
processTypedMessageV3: IProviderHandlers["processTypedMessageV3"];
|
|
119
|
-
}): JRPCMiddleware<
|
|
157
|
+
}): JRPCMiddleware<unknown, string> {
|
|
120
158
|
return createAsyncMiddleware(async (request, response, next) => {
|
|
121
159
|
const { method } = request;
|
|
122
160
|
if (method !== METHOD_TYPES.ETH_SIGN_TYPED_DATA_V3) return next();
|
|
123
161
|
|
|
124
162
|
if (!processTypedMessageV3) throw new Error("WalletMiddleware - opts.processTypedMessageV3 is not provided");
|
|
163
|
+
if (!request?.params) throw new Error("WalletMiddleware - missing params");
|
|
164
|
+
|
|
165
|
+
let msgParams: TypedMessageParams = request.params as TypedMessageParams;
|
|
166
|
+
|
|
167
|
+
if (Array.isArray(request.params)) {
|
|
168
|
+
if (!(request.params.length === 2)) throw new Error(`WalletMiddleware - incorrect params for ${method} method. expected [address, typedData]`);
|
|
169
|
+
|
|
170
|
+
const params = request.params as [string, string];
|
|
171
|
+
const address = params[0];
|
|
172
|
+
const message = JSON.parse(params[1]);
|
|
125
173
|
|
|
126
|
-
|
|
174
|
+
msgParams = {
|
|
175
|
+
from: address,
|
|
176
|
+
data: message,
|
|
177
|
+
version: SignTypedDataVersion.V3,
|
|
178
|
+
};
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
response.result = await processTypedMessageV3(msgParams, request);
|
|
127
182
|
});
|
|
128
183
|
}
|
|
129
184
|
|
|
@@ -131,14 +186,31 @@ export function createProcessTypedMessageV4({
|
|
|
131
186
|
processTypedMessageV4,
|
|
132
187
|
}: {
|
|
133
188
|
processTypedMessageV4: IProviderHandlers["processTypedMessageV4"];
|
|
134
|
-
}): JRPCMiddleware<
|
|
189
|
+
}): JRPCMiddleware<unknown, string> {
|
|
135
190
|
return createAsyncMiddleware(async (request, response, next) => {
|
|
136
191
|
const { method } = request;
|
|
137
192
|
if (method !== METHOD_TYPES.ETH_SIGN_TYPED_DATA_V4) return next();
|
|
138
193
|
|
|
139
194
|
if (!processTypedMessageV4) throw new Error("WalletMiddleware - opts.processTypedMessageV4 is not provided");
|
|
195
|
+
if (!request?.params) throw new Error("WalletMiddleware - missing params");
|
|
196
|
+
|
|
197
|
+
let msgParams: TypedMessageParams = request.params as TypedMessageParams;
|
|
198
|
+
|
|
199
|
+
if (Array.isArray(request.params)) {
|
|
200
|
+
if (!(request.params.length === 2)) throw new Error(`WalletMiddleware - incorrect params for ${method} method. expected [address, typedData]`);
|
|
201
|
+
|
|
202
|
+
const params = request.params as [string, string];
|
|
203
|
+
const address = params[0];
|
|
204
|
+
const message = JSON.parse(params[1]);
|
|
140
205
|
|
|
141
|
-
|
|
206
|
+
msgParams = {
|
|
207
|
+
from: address,
|
|
208
|
+
data: message,
|
|
209
|
+
version: SignTypedDataVersion.V4,
|
|
210
|
+
};
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
response.result = await processTypedMessageV4(msgParams, request);
|
|
142
214
|
});
|
|
143
215
|
}
|
|
144
216
|
|
|
@@ -146,14 +218,30 @@ export function createProcessPersonalMessage({
|
|
|
146
218
|
processPersonalMessage,
|
|
147
219
|
}: {
|
|
148
220
|
processPersonalMessage: IProviderHandlers["processPersonalMessage"];
|
|
149
|
-
}): JRPCMiddleware<
|
|
221
|
+
}): JRPCMiddleware<unknown, string> {
|
|
150
222
|
return createAsyncMiddleware(async (request, response, next) => {
|
|
151
223
|
const { method } = request;
|
|
152
224
|
if (method !== METHOD_TYPES.PERSONAL_SIGN) return next();
|
|
153
225
|
|
|
154
226
|
if (!processPersonalMessage) throw new Error("WalletMiddleware - opts.processPersonalMessage is not provided");
|
|
227
|
+
if (!request?.params) throw new Error("WalletMiddleware - missing params");
|
|
228
|
+
|
|
229
|
+
let msgParams: MessageParams = request.params as MessageParams;
|
|
230
|
+
|
|
231
|
+
if (Array.isArray(request.params)) {
|
|
232
|
+
if (!(request.params.length >= 2)) throw new Error(`WalletMiddleware - incorrect params for ${method} method. expected [message, address]`);
|
|
155
233
|
|
|
156
|
-
|
|
234
|
+
const params = request.params as [string, string];
|
|
235
|
+
const message = params[0];
|
|
236
|
+
const address = params[1];
|
|
237
|
+
|
|
238
|
+
msgParams = {
|
|
239
|
+
from: address,
|
|
240
|
+
data: message,
|
|
241
|
+
};
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
response.result = await processPersonalMessage(msgParams, request);
|
|
157
245
|
});
|
|
158
246
|
}
|
|
159
247
|
|
|
@@ -230,14 +318,25 @@ export function createProcessEncryptionPublicKeyMiddleware({
|
|
|
230
318
|
processEncryptionPublicKey,
|
|
231
319
|
}: {
|
|
232
320
|
processEncryptionPublicKey: IProviderHandlers["processEncryptionPublicKey"];
|
|
233
|
-
}): JRPCMiddleware<
|
|
321
|
+
}): JRPCMiddleware<unknown, string> {
|
|
234
322
|
return createAsyncMiddleware(async (request, response, next) => {
|
|
235
|
-
const {
|
|
323
|
+
const { method } = request;
|
|
236
324
|
if (method !== METHOD_TYPES.ETH_GET_ENCRYPTION_PUBLIC_KEY) return next();
|
|
237
325
|
|
|
238
326
|
if (!processEncryptionPublicKey) throw new Error("WalletMiddleware - opts.processEncryptionPublicKey not provided");
|
|
239
327
|
|
|
240
|
-
|
|
328
|
+
if (!request?.params) throw new Error("WalletMiddleware - missing params");
|
|
329
|
+
|
|
330
|
+
let msgParams: EncryptionPublicKeyParams = request.params as EncryptionPublicKeyParams;
|
|
331
|
+
|
|
332
|
+
if (Array.isArray(request.params)) {
|
|
333
|
+
if (!(request.params.length === 1)) throw new Error(`WalletMiddleware - incorrect params for ${method} method. expected [address]`);
|
|
334
|
+
|
|
335
|
+
const [address] = request.params as [string];
|
|
336
|
+
msgParams = { data: address, from: address };
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
response.result = await processEncryptionPublicKey(msgParams, request);
|
|
241
340
|
});
|
|
242
341
|
}
|
|
243
342
|
|
|
@@ -245,14 +344,75 @@ export function createProcessDecryptMessageMiddleware({
|
|
|
245
344
|
processDecryptMessage,
|
|
246
345
|
}: {
|
|
247
346
|
processDecryptMessage: IProviderHandlers["processDecryptMessage"];
|
|
248
|
-
}): JRPCMiddleware<
|
|
347
|
+
}): JRPCMiddleware<unknown, string> {
|
|
249
348
|
return createAsyncMiddleware(async (request, response, next) => {
|
|
250
|
-
const {
|
|
349
|
+
const { method } = request;
|
|
251
350
|
if (method !== METHOD_TYPES.ETH_DECRYPT) return next();
|
|
252
351
|
|
|
253
352
|
if (!processDecryptMessage) throw new Error("WalletMiddleware - opts.processDecryptMessage not provided");
|
|
254
353
|
|
|
255
|
-
|
|
354
|
+
if (!request?.params) throw new Error("WalletMiddleware - missing params");
|
|
355
|
+
|
|
356
|
+
let msgParams: MessageParams = request.params as MessageParams;
|
|
357
|
+
|
|
358
|
+
if (Array.isArray(request.params)) {
|
|
359
|
+
if (!(request.params.length === 2)) throw new Error(`WalletMiddleware - incorrect params for ${method} method. expected [message, address]`);
|
|
360
|
+
|
|
361
|
+
const [message, address] = request.params as [string, string];
|
|
362
|
+
msgParams = { data: message, from: address };
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
response.result = await processDecryptMessage(msgParams, request);
|
|
366
|
+
});
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
export function createProcessSwitchEthereumChain({
|
|
370
|
+
processSwitchEthereumChain,
|
|
371
|
+
}: {
|
|
372
|
+
processSwitchEthereumChain: IProviderHandlers["processSwitchEthereumChain"];
|
|
373
|
+
}): JRPCMiddleware<unknown, string> {
|
|
374
|
+
return createAsyncMiddleware(async (request, response, next) => {
|
|
375
|
+
const { method } = request;
|
|
376
|
+
if (method !== METHOD_TYPES.SWITCH_CHAIN) return next();
|
|
377
|
+
|
|
378
|
+
if (!processSwitchEthereumChain) throw new Error("WalletMiddleware - opts.processSwitchEthereumChain not provided");
|
|
379
|
+
if (!request?.params) throw new Error("WalletMiddleware - missing params");
|
|
380
|
+
|
|
381
|
+
let msgParams: SwitchChainMessageParams = request.params as SwitchChainMessageParams;
|
|
382
|
+
|
|
383
|
+
if (Array.isArray(request.params)) {
|
|
384
|
+
if (!(request.params.length === 1)) throw new Error(`WalletMiddleware - incorrect params for ${method} method. expected [data]`);
|
|
385
|
+
|
|
386
|
+
const [message] = request.params as [SwitchChainMessageParams];
|
|
387
|
+
msgParams = message;
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
response.result = await processSwitchEthereumChain(msgParams, request);
|
|
391
|
+
});
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
export function createProcessAddEthereumChain({
|
|
395
|
+
processAddEthereumChain,
|
|
396
|
+
}: {
|
|
397
|
+
processAddEthereumChain: IProviderHandlers["processAddEthereumChain"];
|
|
398
|
+
}): JRPCMiddleware<unknown, string> {
|
|
399
|
+
return createAsyncMiddleware(async (request, response, next) => {
|
|
400
|
+
const { method } = request;
|
|
401
|
+
if (method !== METHOD_TYPES.ADD_CHAIN) return next();
|
|
402
|
+
|
|
403
|
+
if (!processAddEthereumChain) throw new Error("WalletMiddleware - opts.processAddEthereumChain not provided");
|
|
404
|
+
if (!request?.params) throw new Error("WalletMiddleware - missing params");
|
|
405
|
+
|
|
406
|
+
let msgParams: AddChainMessageParams = request.params as AddChainMessageParams;
|
|
407
|
+
|
|
408
|
+
if (Array.isArray(request.params)) {
|
|
409
|
+
if (!(request.params.length === 1)) throw new Error(`WalletMiddleware - incorrect params for ${method} method. expected [data]`);
|
|
410
|
+
|
|
411
|
+
const [message] = request.params as [AddChainMessageParams];
|
|
412
|
+
msgParams = message;
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
response.result = await processAddEthereumChain(msgParams, request);
|
|
256
416
|
});
|
|
257
417
|
}
|
|
258
418
|
|
|
@@ -287,6 +447,8 @@ export function createEthereumMiddleware(providerHandlers: IProviderHandlers): J
|
|
|
287
447
|
getPendingTransactionByHash,
|
|
288
448
|
processEncryptionPublicKey,
|
|
289
449
|
processDecryptMessage,
|
|
450
|
+
processSwitchEthereumChain,
|
|
451
|
+
processAddEthereumChain,
|
|
290
452
|
getProviderState,
|
|
291
453
|
version,
|
|
292
454
|
} = providerHandlers;
|
|
@@ -307,5 +469,7 @@ export function createEthereumMiddleware(providerHandlers: IProviderHandlers): J
|
|
|
307
469
|
createPendingTxMiddleware({ getPendingTransactionByHash }) as JRPCMiddleware<unknown, unknown>,
|
|
308
470
|
createProcessEncryptionPublicKeyMiddleware({ processEncryptionPublicKey }) as JRPCMiddleware<unknown, unknown>,
|
|
309
471
|
createProcessDecryptMessageMiddleware({ processDecryptMessage }) as JRPCMiddleware<unknown, unknown>,
|
|
472
|
+
createProcessSwitchEthereumChain({ processSwitchEthereumChain }) as JRPCMiddleware<unknown, unknown>,
|
|
473
|
+
createProcessAddEthereumChain({ processAddEthereumChain }) as JRPCMiddleware<unknown, unknown>,
|
|
310
474
|
]);
|
|
311
475
|
}
|
|
@@ -22,10 +22,12 @@ import NetworkController from "../Network/NetworkController";
|
|
|
22
22
|
import { SUPPORTED_NETWORKS } from "../utils/constants";
|
|
23
23
|
import { formatDate, formatPastTx, formatTime, getEthTxStatus } from "../utils/helpers";
|
|
24
24
|
import type {
|
|
25
|
+
AddChainMessageParams,
|
|
25
26
|
CustomNetworkPayload,
|
|
26
27
|
CustomNetworks,
|
|
27
28
|
CustomNftInfo,
|
|
28
29
|
CustomTokenInfo,
|
|
30
|
+
EthereumProviderConfig,
|
|
29
31
|
EthereumUser,
|
|
30
32
|
ExtendedAddressPreferences,
|
|
31
33
|
FetchCommonTransaction,
|
|
@@ -42,6 +44,7 @@ interface IPreferencesControllerOptions {
|
|
|
42
44
|
blockTracker?: PollingBlockTracker;
|
|
43
45
|
signAuthMessage?: KeyringController["signAuthMessage"];
|
|
44
46
|
getProviderConfig?: NetworkController["getProviderConfig"];
|
|
47
|
+
setProviderConfig?: NetworkController["setProviderConfig"];
|
|
45
48
|
}
|
|
46
49
|
|
|
47
50
|
export default class PreferencesController
|
|
@@ -54,14 +57,17 @@ export default class PreferencesController
|
|
|
54
57
|
|
|
55
58
|
private getProviderConfig: NetworkController["getProviderConfig"];
|
|
56
59
|
|
|
60
|
+
private setProviderConfig: NetworkController["setProviderConfig"];
|
|
61
|
+
|
|
57
62
|
private provider: SafeEventEmitterProvider;
|
|
58
63
|
|
|
59
64
|
private blockTracker: PollingBlockTracker;
|
|
60
65
|
|
|
61
|
-
constructor({ config, state, provider, blockTracker, signAuthMessage, getProviderConfig }: IPreferencesControllerOptions) {
|
|
66
|
+
constructor({ config, state, provider, blockTracker, signAuthMessage, getProviderConfig, setProviderConfig }: IPreferencesControllerOptions) {
|
|
62
67
|
super({ config, state, defaultPreferences: { formattedPastTransactions: [], fetchedPastTx: [], paymentTx: [] }, signAuthMessage });
|
|
63
68
|
this.provider = provider;
|
|
64
69
|
this.getProviderConfig = getProviderConfig;
|
|
70
|
+
this.setProviderConfig = setProviderConfig;
|
|
65
71
|
this.blockTracker = blockTracker;
|
|
66
72
|
log.info(this.blockTracker);
|
|
67
73
|
}
|
|
@@ -261,6 +267,36 @@ export default class PreferencesController
|
|
|
261
267
|
return this.getAddressState(address)?.customNfts ?? [];
|
|
262
268
|
}
|
|
263
269
|
|
|
270
|
+
public async addChain(network: AddChainMessageParams): Promise<void> {
|
|
271
|
+
const approveChainOptions = this.getChainOptions();
|
|
272
|
+
const providerConfig = approveChainOptions.find((x) => x.chainId === network.chainId);
|
|
273
|
+
|
|
274
|
+
if (providerConfig) {
|
|
275
|
+
throw new Error(`chainId ${network.chainId} already exists`);
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
const newNetwork: CustomNetworkPayload = {
|
|
279
|
+
displayName: network.chainName,
|
|
280
|
+
rpcTarget: network.rpcUrls[0],
|
|
281
|
+
ticker: network.nativeCurrency.symbol,
|
|
282
|
+
chainId: network.chainId,
|
|
283
|
+
blockExplorerUrl: network.blockExplorerUrls[0],
|
|
284
|
+
};
|
|
285
|
+
|
|
286
|
+
const isSuccess = await this.addCustomNetwork({ type: "rpc", network: newNetwork });
|
|
287
|
+
if (!isSuccess) throw new Error("unable to add custom network");
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
switchChain(data: { chainId: string }) {
|
|
291
|
+
const chainOptions = this.getChainOptions();
|
|
292
|
+
const providerConfig = chainOptions.find((x) => x.chainId === data.chainId);
|
|
293
|
+
if (providerConfig) {
|
|
294
|
+
this.setProviderConfig(providerConfig);
|
|
295
|
+
} else {
|
|
296
|
+
throw new Error(`chainId ${data.chainId} is not supported`);
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
|
|
264
300
|
// Custom Network methods
|
|
265
301
|
public async addCustomNetwork({ type, network }: { type: string; network: CustomNetworkPayload }): Promise<number> {
|
|
266
302
|
try {
|
|
@@ -354,6 +390,35 @@ export default class PreferencesController
|
|
|
354
390
|
this.updateState({ paymentTx: accumulator }, address);
|
|
355
391
|
}
|
|
356
392
|
|
|
393
|
+
private getChainOptions(): EthereumProviderConfig[] {
|
|
394
|
+
const { selectedAddress, identities } = this.state;
|
|
395
|
+
const customNetworks = identities[selectedAddress]?.customNetworks ?? [];
|
|
396
|
+
|
|
397
|
+
const custom: EthereumProviderConfig[] = Object.values(customNetworks).reduce((chains, network) => {
|
|
398
|
+
const networkItem = {
|
|
399
|
+
blockExplorerUrl: network.block_explorer_url,
|
|
400
|
+
chainId: network.chain_id,
|
|
401
|
+
displayName: network.network_name,
|
|
402
|
+
logo: "eth.svg",
|
|
403
|
+
rpcTarget: network.rpc_url,
|
|
404
|
+
ticker: network.symbol,
|
|
405
|
+
tickerName: network.symbol.toUpperCase(),
|
|
406
|
+
isCustom: true,
|
|
407
|
+
id: network.id,
|
|
408
|
+
};
|
|
409
|
+
if (Object.keys(SUPPORTED_NETWORKS).includes(networkItem.chainId)) return chains;
|
|
410
|
+
chains.push(networkItem);
|
|
411
|
+
return chains;
|
|
412
|
+
}, []);
|
|
413
|
+
|
|
414
|
+
const supported = Object.values(SUPPORTED_NETWORKS).reduce((chains, network) => {
|
|
415
|
+
chains.push(network);
|
|
416
|
+
return chains;
|
|
417
|
+
}, []);
|
|
418
|
+
|
|
419
|
+
return [...supported, ...custom];
|
|
420
|
+
}
|
|
421
|
+
|
|
357
422
|
private async calculatePastTx(txs: FetchedTransaction[], address: string) {
|
|
358
423
|
const pastTx = [];
|
|
359
424
|
const pendingTx = [];
|
package/src/index.ts
CHANGED
|
@@ -5,10 +5,12 @@ export { default as GasFeeController } from "./Gas/GasFeeController";
|
|
|
5
5
|
export * from "./Gas/IGasFeeController";
|
|
6
6
|
export { default as KeyringController } from "./Keyring/KeyringController";
|
|
7
7
|
export * from "./Message/AbstractMessageController";
|
|
8
|
+
export * from "./Message/AddChainController";
|
|
8
9
|
export * from "./Message/DecryptMessageController";
|
|
9
10
|
export * from "./Message/EncryptionPublicKeyController";
|
|
10
11
|
export * from "./Message/MessageController";
|
|
11
12
|
export * from "./Message/PersonalMessageController";
|
|
13
|
+
export * from "./Message/SwitchChainController";
|
|
12
14
|
export * from "./Message/TypedMessageController";
|
|
13
15
|
export * from "./Message/utils";
|
|
14
16
|
export * from "./Network/createEthereumMiddleware";
|
package/src/utils/constants.ts
CHANGED
|
@@ -193,6 +193,8 @@ export const METHOD_TYPES = {
|
|
|
193
193
|
ETH_GET_BLOCK_BY_HASH: "eth_getBlockByHash",
|
|
194
194
|
ETH_GET_CODE: "eth_getCode",
|
|
195
195
|
ETH_GET_GAS_PRICE: "eth_gasPrice",
|
|
196
|
+
SWITCH_CHAIN: "wallet_switchEthereumChain",
|
|
197
|
+
ADD_CHAIN: "wallet_addEthereumChain",
|
|
196
198
|
} as const;
|
|
197
199
|
|
|
198
200
|
export const TRANSACTION_ENVELOPE_TYPES = {
|
package/src/utils/interfaces.ts
CHANGED
|
@@ -73,7 +73,7 @@ export interface BaseRequestParams {
|
|
|
73
73
|
/**
|
|
74
74
|
* Unique id for each request
|
|
75
75
|
*/
|
|
76
|
-
id
|
|
76
|
+
id?: string;
|
|
77
77
|
/**
|
|
78
78
|
* Address to send this transaction from.
|
|
79
79
|
*/
|
|
@@ -115,6 +115,31 @@ export type SignTypedDataMessageV3V4 = {
|
|
|
115
115
|
message: unknown;
|
|
116
116
|
};
|
|
117
117
|
|
|
118
|
+
export interface SwitchChainMessageParams extends BaseRequestParams {
|
|
119
|
+
chainId: string;
|
|
120
|
+
displayName?: string;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
export interface SwitchChainMessage extends AbstractMessage {
|
|
124
|
+
messageParams: SwitchChainMessageParams;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
export interface AddChainMessageParams extends BaseRequestParams {
|
|
128
|
+
chainId: string;
|
|
129
|
+
chainName: string;
|
|
130
|
+
nativeCurrency: {
|
|
131
|
+
name: string;
|
|
132
|
+
symbol: string;
|
|
133
|
+
decimals: number;
|
|
134
|
+
};
|
|
135
|
+
rpcUrls: string[];
|
|
136
|
+
blockExplorerUrls?: string[];
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
export interface AddChainMessage extends AbstractMessage {
|
|
140
|
+
messageParams: AddChainMessageParams;
|
|
141
|
+
}
|
|
142
|
+
|
|
118
143
|
export interface TypedMessageParams extends BaseRequestParams {
|
|
119
144
|
data: Record<string, unknown>[] | string | SignTypedDataMessageV3V4;
|
|
120
145
|
version?: SignTypedDataVersion;
|