@toruslabs/ethereum-controllers 8.17.0 → 9.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/lib.cjs/Account/AccountTrackerController.js +15 -7
- package/dist/lib.cjs/AccountAbstraction/AccountAbstractionController.js +4 -6
- package/dist/lib.cjs/Eip5792/walletGetCallsStatus.js +2 -2
- package/dist/lib.cjs/Eip5792/walletSendCalls.js +8 -9
- package/dist/lib.cjs/Eip7702/eip7702Utils.js +3 -3
- package/dist/lib.cjs/Gas/GasFeeController.js +3 -2
- package/dist/lib.cjs/Keyring/KeyringController.js +69 -40
- package/dist/lib.cjs/Message/utils.js +15 -14
- package/dist/lib.cjs/Nfts/NftHandler.js +54 -12
- package/dist/lib.cjs/Nfts/NftsController.js +1 -4
- package/dist/lib.cjs/Preferences/PreferencesController.js +2 -2
- package/dist/lib.cjs/Tokens/TokenHandler.js +39 -7
- package/dist/lib.cjs/Tokens/TokensController.js +15 -7
- package/dist/lib.cjs/Transaction/TransactionController.js +17 -20
- package/dist/lib.cjs/Transaction/TransactionGasUtil.js +11 -12
- package/dist/lib.cjs/Transaction/TransactionUtils.js +44 -39
- package/dist/lib.cjs/index.js +0 -1
- package/dist/lib.cjs/types/Account/AccountTrackerController.d.ts +1 -1
- package/dist/lib.cjs/types/AccountAbstraction/AccountAbstractionController.d.ts +1 -3
- package/dist/lib.cjs/types/Keyring/KeyringController.d.ts +4 -4
- package/dist/lib.cjs/types/Nfts/NftHandler.d.ts +4 -3
- package/dist/lib.cjs/types/Nfts/NftsController.d.ts +0 -1
- package/dist/lib.cjs/types/Tokens/TokenHandler.d.ts +4 -3
- package/dist/lib.cjs/types/Tokens/TokensController.d.ts +1 -1
- package/dist/lib.cjs/types/Transaction/TransactionUtils.d.ts +11 -3
- package/dist/lib.cjs/types/utils/abis.d.ts +544 -99
- package/dist/lib.cjs/types/utils/eip5792Types.d.ts +0 -1
- package/dist/lib.cjs/types/utils/hex.d.ts +9 -0
- package/dist/lib.cjs/types/utils/interfaces.d.ts +205 -2
- package/dist/lib.cjs/types/utils/transaction.d.ts +1 -1
- package/dist/lib.cjs/types/utils/viem.d.ts +8 -0
- package/dist/lib.cjs/utils/abis.js +12 -0
- package/dist/lib.cjs/utils/conversionUtils.js +3 -4
- package/dist/lib.cjs/utils/eip5792Types.js +0 -2
- package/dist/lib.cjs/utils/helpers.js +9 -8
- package/dist/lib.cjs/utils/hex.js +23 -0
- package/dist/lib.cjs/utils/transaction.js +7 -11
- package/dist/lib.cjs/utils/viem.js +214 -0
- package/dist/lib.esm/Account/AccountTrackerController.js +15 -7
- package/dist/lib.esm/AccountAbstraction/AccountAbstractionController.js +5 -7
- package/dist/lib.esm/Eip5792/walletGetCallsStatus.js +1 -1
- package/dist/lib.esm/Eip5792/walletSendCalls.js +9 -10
- package/dist/lib.esm/Eip7702/eip7702Utils.js +1 -1
- package/dist/lib.esm/Gas/GasFeeController.js +3 -2
- package/dist/lib.esm/Keyring/KeyringController.js +68 -40
- package/dist/lib.esm/Message/utils.js +13 -12
- package/dist/lib.esm/Network/createEthereumMiddleware.js +2 -2
- package/dist/lib.esm/Nfts/NftHandler.js +54 -12
- package/dist/lib.esm/Nfts/NftsController.js +1 -4
- package/dist/lib.esm/Preferences/PreferencesController.js +1 -1
- package/dist/lib.esm/Tokens/TokenHandler.js +39 -7
- package/dist/lib.esm/Tokens/TokensController.js +15 -7
- package/dist/lib.esm/Transaction/TransactionController.js +6 -9
- package/dist/lib.esm/Transaction/TransactionGasUtil.js +11 -12
- package/dist/lib.esm/Transaction/TransactionUtils.js +30 -26
- package/dist/lib.esm/index.js +2 -2
- package/dist/lib.esm/utils/abis.js +12 -0
- package/dist/lib.esm/utils/conversionUtils.js +2 -3
- package/dist/lib.esm/utils/eip5792Types.js +1 -2
- package/dist/lib.esm/utils/helpers.js +8 -7
- package/dist/lib.esm/utils/hex.js +21 -0
- package/dist/lib.esm/utils/interfaces.js +64 -0
- package/dist/lib.esm/utils/transaction.js +7 -11
- package/dist/lib.esm/utils/viem.js +214 -0
- package/package.json +13 -18
- package/dist/ethereumControllers.umd.min.js +0 -2
- package/dist/ethereumControllers.umd.min.js.LICENSE.txt +0 -50
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var viem = require('viem');
|
|
4
|
+
|
|
5
|
+
// viem's serializeTransaction infers tx type via `if (transaction.type)` which is
|
|
6
|
+
// falsy for type 0 (legacy). Map numeric types to string names so the check passes,
|
|
7
|
+
// and strip undefined/null fields that also break viem's type inference.
|
|
8
|
+
const VIEM_TX_TYPE_NAMES = {
|
|
9
|
+
0: "legacy",
|
|
10
|
+
1: "eip2930",
|
|
11
|
+
2: "eip1559",
|
|
12
|
+
3: "eip4844",
|
|
13
|
+
4: "eip7702"
|
|
14
|
+
};
|
|
15
|
+
const VIEM_QUANTITY_FIELDS = ["gasPrice", "maxFeePerGas", "maxPriorityFeePerGas", "maxFeePerBlobGas", "value"];
|
|
16
|
+
function toViemQuantity(value) {
|
|
17
|
+
if (typeof value === "bigint") return value;
|
|
18
|
+
if (typeof value === "number") return BigInt(value);
|
|
19
|
+
if (typeof value === "string" && viem.isHex(value)) return BigInt(value);
|
|
20
|
+
return undefined;
|
|
21
|
+
}
|
|
22
|
+
function toViemNumber(value) {
|
|
23
|
+
if (typeof value === "number") return value;
|
|
24
|
+
if (typeof value === "bigint") return Number(value);
|
|
25
|
+
if (typeof value === "string" && viem.isHex(value)) return Number(value);
|
|
26
|
+
return undefined;
|
|
27
|
+
}
|
|
28
|
+
function toViemHex(value) {
|
|
29
|
+
if (typeof value === "string" && viem.isHex(value)) return value;
|
|
30
|
+
if (value instanceof Uint8Array) return viem.toHex(value);
|
|
31
|
+
return undefined;
|
|
32
|
+
}
|
|
33
|
+
function toViemAddress(value) {
|
|
34
|
+
if (typeof value === "string" && viem.isAddress(value)) return value;
|
|
35
|
+
return undefined;
|
|
36
|
+
}
|
|
37
|
+
function toViemHexArray(value) {
|
|
38
|
+
if (!Array.isArray(value)) return undefined;
|
|
39
|
+
const normalized = [];
|
|
40
|
+
for (const item of value) {
|
|
41
|
+
const hex = toViemHex(item);
|
|
42
|
+
if (!hex) return undefined;
|
|
43
|
+
normalized.push(hex);
|
|
44
|
+
}
|
|
45
|
+
return normalized;
|
|
46
|
+
}
|
|
47
|
+
function toViemAccessList(value) {
|
|
48
|
+
if (!value) return undefined;
|
|
49
|
+
const accessList = [];
|
|
50
|
+
if (Array.isArray(value)) {
|
|
51
|
+
for (const entry of value) {
|
|
52
|
+
if (Array.isArray(entry)) {
|
|
53
|
+
const [addressLike, storageKeysLike] = entry;
|
|
54
|
+
const address = toViemAddress(addressLike);
|
|
55
|
+
const storageKeys = toViemHexArray(storageKeysLike);
|
|
56
|
+
if (!address || !storageKeys) return undefined;
|
|
57
|
+
accessList.push({
|
|
58
|
+
address,
|
|
59
|
+
storageKeys
|
|
60
|
+
});
|
|
61
|
+
continue;
|
|
62
|
+
}
|
|
63
|
+
if (typeof entry === "object" && entry !== null) {
|
|
64
|
+
const address = toViemAddress(entry.address);
|
|
65
|
+
const storageKeys = toViemHexArray(entry.storageKeys);
|
|
66
|
+
if (!address || !storageKeys) return undefined;
|
|
67
|
+
accessList.push({
|
|
68
|
+
address,
|
|
69
|
+
storageKeys
|
|
70
|
+
});
|
|
71
|
+
continue;
|
|
72
|
+
}
|
|
73
|
+
return undefined;
|
|
74
|
+
}
|
|
75
|
+
return accessList;
|
|
76
|
+
}
|
|
77
|
+
if (typeof value === "object") {
|
|
78
|
+
for (const [addressLike, storageKeysLike] of Object.entries(value)) {
|
|
79
|
+
const address = toViemAddress(addressLike);
|
|
80
|
+
const storageKeys = toViemHexArray(storageKeysLike);
|
|
81
|
+
if (!address || !storageKeys) return undefined;
|
|
82
|
+
accessList.push({
|
|
83
|
+
address,
|
|
84
|
+
storageKeys
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
return accessList;
|
|
88
|
+
}
|
|
89
|
+
return undefined;
|
|
90
|
+
}
|
|
91
|
+
function toViemAuthorizationList(value) {
|
|
92
|
+
if (!value) return undefined;
|
|
93
|
+
const authorizationList = [];
|
|
94
|
+
for (const authorization of value) {
|
|
95
|
+
const address = toViemAddress(authorization.address);
|
|
96
|
+
const chainId = toViemNumber(authorization.chainId);
|
|
97
|
+
const nonce = toViemNumber(authorization.nonce);
|
|
98
|
+
if (!address || typeof chainId === "undefined" || typeof nonce === "undefined") {
|
|
99
|
+
return undefined;
|
|
100
|
+
}
|
|
101
|
+
const normalizedAuthorization = {
|
|
102
|
+
address,
|
|
103
|
+
chainId,
|
|
104
|
+
nonce
|
|
105
|
+
};
|
|
106
|
+
const signature = authorization.signature;
|
|
107
|
+
if (typeof signature === "string" && viem.isHex(signature)) {
|
|
108
|
+
const parsed = viem.parseSignature(signature);
|
|
109
|
+
normalizedAuthorization.r = parsed.r;
|
|
110
|
+
normalizedAuthorization.s = parsed.s;
|
|
111
|
+
normalizedAuthorization.yParity = parsed.yParity;
|
|
112
|
+
} else if (typeof signature === "object" && signature !== null) {
|
|
113
|
+
const r = toViemHex(signature.r);
|
|
114
|
+
const s = toViemHex(signature.s);
|
|
115
|
+
const yParity = toViemNumber(signature.yParity);
|
|
116
|
+
const vRaw = signature.v;
|
|
117
|
+
const v = typeof vRaw === "bigint" ? vRaw : typeof vRaw === "number" ? BigInt(vRaw) : typeof vRaw === "string" && viem.isHex(vRaw) ? BigInt(vRaw) : undefined;
|
|
118
|
+
if (r && s) {
|
|
119
|
+
normalizedAuthorization.r = r;
|
|
120
|
+
normalizedAuthorization.s = s;
|
|
121
|
+
}
|
|
122
|
+
if (typeof yParity !== "undefined") {
|
|
123
|
+
normalizedAuthorization.yParity = yParity;
|
|
124
|
+
}
|
|
125
|
+
if (typeof v !== "undefined") {
|
|
126
|
+
normalizedAuthorization.v = v;
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
authorizationList.push(normalizedAuthorization);
|
|
130
|
+
}
|
|
131
|
+
return authorizationList;
|
|
132
|
+
}
|
|
133
|
+
function toViemBlobs(value) {
|
|
134
|
+
if (!value) return undefined;
|
|
135
|
+
const blobs = [];
|
|
136
|
+
for (const blob of value) {
|
|
137
|
+
if (typeof blob === "string" || blob instanceof Uint8Array) {
|
|
138
|
+
const normalizedBlob = toViemHex(blob);
|
|
139
|
+
if (!normalizedBlob) return undefined;
|
|
140
|
+
blobs.push(normalizedBlob);
|
|
141
|
+
continue;
|
|
142
|
+
}
|
|
143
|
+
if (typeof blob === "object" && blob !== null) {
|
|
144
|
+
const normalizedBlob = toViemHex(blob.data);
|
|
145
|
+
if (!normalizedBlob) return undefined;
|
|
146
|
+
blobs.push(normalizedBlob);
|
|
147
|
+
continue;
|
|
148
|
+
}
|
|
149
|
+
return undefined;
|
|
150
|
+
}
|
|
151
|
+
return blobs;
|
|
152
|
+
}
|
|
153
|
+
/**
|
|
154
|
+
* Prepare transaction params for signing.
|
|
155
|
+
* @param tx - The transaction to prepare.
|
|
156
|
+
* @returns The prepared transaction.
|
|
157
|
+
*/
|
|
158
|
+
function prepareViemTx(tx) {
|
|
159
|
+
var _input$gas;
|
|
160
|
+
const input = tx;
|
|
161
|
+
const prepared = {};
|
|
162
|
+
const txType = typeof input.type === "number" ? VIEM_TX_TYPE_NAMES[input.type] : input.type;
|
|
163
|
+
if (typeof txType === "string") {
|
|
164
|
+
prepared.type = txType;
|
|
165
|
+
}
|
|
166
|
+
// For EIP-4844 Transactions, we want to sign the transaction payload body (tx_payload_body) without the sidecars (ie. without the network wrapper).
|
|
167
|
+
// ref: https://github.com/wevm/viem/blob/b3af510a6e2e45526e2bb10298b7fc1f178a73a3/src/accounts/utils/signTransaction.ts#L56
|
|
168
|
+
if (prepared.type === "eip4844") {
|
|
169
|
+
prepared.sidecars = false;
|
|
170
|
+
}
|
|
171
|
+
const chainId = toViemNumber(input.chainId);
|
|
172
|
+
if (typeof chainId !== "undefined") {
|
|
173
|
+
prepared.chainId = chainId;
|
|
174
|
+
}
|
|
175
|
+
const nonce = toViemNumber(input.nonce);
|
|
176
|
+
if (typeof nonce !== "undefined") {
|
|
177
|
+
prepared.nonce = nonce;
|
|
178
|
+
}
|
|
179
|
+
const gas = toViemQuantity((_input$gas = input.gas) !== null && _input$gas !== void 0 ? _input$gas : input.gasLimit);
|
|
180
|
+
if (typeof gas !== "undefined") {
|
|
181
|
+
prepared.gas = gas;
|
|
182
|
+
}
|
|
183
|
+
for (const field of VIEM_QUANTITY_FIELDS) {
|
|
184
|
+
const value = toViemQuantity(input[field]);
|
|
185
|
+
if (typeof value !== "undefined") {
|
|
186
|
+
prepared[field] = value;
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
if (typeof input.to === "string") {
|
|
190
|
+
prepared.to = input.to;
|
|
191
|
+
}
|
|
192
|
+
if (typeof input.data === "string") {
|
|
193
|
+
prepared.data = input.data;
|
|
194
|
+
}
|
|
195
|
+
const accessList = toViemAccessList(input.accessList);
|
|
196
|
+
if (accessList) {
|
|
197
|
+
prepared.accessList = accessList;
|
|
198
|
+
}
|
|
199
|
+
const authorizationList = toViemAuthorizationList(input.authorizationList);
|
|
200
|
+
if (authorizationList) {
|
|
201
|
+
prepared.authorizationList = authorizationList;
|
|
202
|
+
}
|
|
203
|
+
const blobVersionedHashes = toViemHexArray(input.blobVersionedHashes);
|
|
204
|
+
if (blobVersionedHashes) {
|
|
205
|
+
prepared.blobVersionedHashes = blobVersionedHashes;
|
|
206
|
+
}
|
|
207
|
+
const blobs = toViemBlobs(input.blobs);
|
|
208
|
+
if (blobs) {
|
|
209
|
+
prepared.blobs = blobs;
|
|
210
|
+
}
|
|
211
|
+
return prepared;
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
exports.prepareViemTx = prepareViemTx;
|
|
@@ -2,8 +2,8 @@ import _objectSpread from '@babel/runtime/helpers/objectSpread2';
|
|
|
2
2
|
import _defineProperty from '@babel/runtime/helpers/defineProperty';
|
|
3
3
|
import { BaseController } from '@toruslabs/base-controllers';
|
|
4
4
|
import { Mutex } from 'async-mutex';
|
|
5
|
-
import { BrowserProvider, toQuantity, Contract } from 'ethers';
|
|
6
5
|
import log from 'loglevel';
|
|
6
|
+
import { createPublicClient, custom, toHex } from 'viem';
|
|
7
7
|
import { singleBalanceCheckerAbi } from '../utils/abis.js';
|
|
8
8
|
import { SINGLE_CALL_BALANCES_ADDRESSES } from '../utils/contractAddresses.js';
|
|
9
9
|
|
|
@@ -32,7 +32,7 @@ class AccountTrackerController extends BaseController {
|
|
|
32
32
|
_defineProperty(this, "provider", void 0);
|
|
33
33
|
_defineProperty(this, "blockTracker", void 0);
|
|
34
34
|
_defineProperty(this, "mutex", new Mutex());
|
|
35
|
-
_defineProperty(this, "
|
|
35
|
+
_defineProperty(this, "publicClient", void 0);
|
|
36
36
|
_defineProperty(this, "getIdentities", void 0);
|
|
37
37
|
_defineProperty(this, "getCurrentChainId", void 0);
|
|
38
38
|
this.defaultState = {
|
|
@@ -41,7 +41,9 @@ class AccountTrackerController extends BaseController {
|
|
|
41
41
|
this.initialize();
|
|
42
42
|
this.provider = provider;
|
|
43
43
|
this.blockTracker = blockTracker;
|
|
44
|
-
this.
|
|
44
|
+
this.publicClient = createPublicClient({
|
|
45
|
+
transport: custom(this.provider)
|
|
46
|
+
});
|
|
45
47
|
this.getIdentities = getIdentities;
|
|
46
48
|
this.getCurrentChainId = getCurrentChainId;
|
|
47
49
|
onPreferencesStateChange(() => {
|
|
@@ -127,21 +129,27 @@ class AccountTrackerController extends BaseController {
|
|
|
127
129
|
} = this.state;
|
|
128
130
|
if (!accounts[address]) return;
|
|
129
131
|
accounts[address] = {
|
|
130
|
-
balance:
|
|
132
|
+
balance: toHex(BigInt(balance))
|
|
131
133
|
};
|
|
132
134
|
this.update({
|
|
133
135
|
accounts
|
|
134
136
|
});
|
|
135
137
|
}
|
|
136
138
|
async _updateAccountsViaBalanceChecker(addresses, deployedContractAddress) {
|
|
137
|
-
const ethContract = new Contract(deployedContractAddress, singleBalanceCheckerAbi, this.ethersProvider);
|
|
138
139
|
try {
|
|
139
|
-
const result = await
|
|
140
|
+
const result = await this.publicClient.readContract({
|
|
141
|
+
address: deployedContractAddress,
|
|
142
|
+
abi: singleBalanceCheckerAbi,
|
|
143
|
+
functionName: "balances",
|
|
144
|
+
args: [addresses, [ZERO_ADDRESS]],
|
|
145
|
+
authorizationList: undefined // required when public client has no chain specified
|
|
146
|
+
});
|
|
140
147
|
const {
|
|
141
148
|
accounts
|
|
142
149
|
} = this.state;
|
|
143
150
|
addresses.forEach((address, index) => {
|
|
144
|
-
|
|
151
|
+
var _result$index;
|
|
152
|
+
const balance = toHex((_result$index = result[index]) !== null && _result$index !== void 0 ? _result$index : 0n);
|
|
145
153
|
if (!accounts[address]) return;
|
|
146
154
|
accounts[address] = {
|
|
147
155
|
balance
|
|
@@ -1,11 +1,9 @@
|
|
|
1
1
|
import _objectSpread from '@babel/runtime/helpers/objectSpread2';
|
|
2
2
|
import _defineProperty from '@babel/runtime/helpers/defineProperty';
|
|
3
|
-
import { addHexPrefix } from '@ethereumjs/util';
|
|
4
3
|
import { BaseController, TransactionStatus } from '@toruslabs/base-controllers';
|
|
5
4
|
import { JRPCEngine, providerFromEngine } from '@web3auth/auth';
|
|
6
|
-
import { isHexString } from 'ethers';
|
|
7
5
|
import log from 'loglevel';
|
|
8
|
-
import { defineChain, createPublicClient, http, createWalletClient, custom, parseEther,
|
|
6
|
+
import { defineChain, createPublicClient, http, createWalletClient, custom, toHex, parseEther, isHex } from 'viem';
|
|
9
7
|
import { createPaymasterClient, createBundlerClient } from 'viem/account-abstraction';
|
|
10
8
|
|
|
11
9
|
const eoaInterceptorMiddleware = eoaAddress => (req, res, next, end) => {
|
|
@@ -124,7 +122,7 @@ class AccountAbstractionController extends BaseController {
|
|
|
124
122
|
});
|
|
125
123
|
}
|
|
126
124
|
async sendTransaction(id, tx, address) {
|
|
127
|
-
var _txParams$chainId, _txReceipt$receipt, _txReceipt$nonce, _txReceipt$receipt2, _txReceipt$receipt3, _txReceipt$receipt4;
|
|
125
|
+
var _txParams$chainId, _txReceipt$receipt, _txReceipt$nonce, _txReceipt$receipt$ga, _txReceipt$receipt2, _txReceipt$receipt$ef, _txReceipt$receipt3, _txReceipt$receipt4;
|
|
128
126
|
if (address.toLowerCase() !== this.smartAccount.address.toLowerCase()) {
|
|
129
127
|
throw new Error("Invalid address");
|
|
130
128
|
}
|
|
@@ -164,8 +162,8 @@ class AccountAbstractionController extends BaseController {
|
|
|
164
162
|
receipt: {
|
|
165
163
|
transactionHash: (_txReceipt$receipt = txReceipt.receipt) === null || _txReceipt$receipt === void 0 ? void 0 : _txReceipt$receipt.transactionHash,
|
|
166
164
|
nonce: (_txReceipt$nonce = txReceipt.nonce) === null || _txReceipt$nonce === void 0 ? void 0 : _txReceipt$nonce.toString(),
|
|
167
|
-
gasUsed:
|
|
168
|
-
effectiveGasPrice:
|
|
165
|
+
gasUsed: toHex((_txReceipt$receipt$ga = (_txReceipt$receipt2 = txReceipt.receipt) === null || _txReceipt$receipt2 === void 0 ? void 0 : _txReceipt$receipt2.gasUsed) !== null && _txReceipt$receipt$ga !== void 0 ? _txReceipt$receipt$ga : 0n),
|
|
166
|
+
effectiveGasPrice: toHex((_txReceipt$receipt$ef = (_txReceipt$receipt3 = txReceipt.receipt) === null || _txReceipt$receipt3 === void 0 ? void 0 : _txReceipt$receipt3.effectiveGasPrice) !== null && _txReceipt$receipt$ef !== void 0 ? _txReceipt$receipt$ef : 0n),
|
|
169
167
|
type: (_txReceipt$receipt4 = txReceipt.receipt) === null || _txReceipt$receipt4 === void 0 ? void 0 : _txReceipt$receipt4.type,
|
|
170
168
|
reason: txReceipt.reason
|
|
171
169
|
},
|
|
@@ -278,7 +276,7 @@ class AccountAbstractionController extends BaseController {
|
|
|
278
276
|
throw new Error("Invalid address");
|
|
279
277
|
}
|
|
280
278
|
return (_this$smartAccount = this.smartAccount) === null || _this$smartAccount === void 0 ? void 0 : _this$smartAccount.signMessage({
|
|
281
|
-
message:
|
|
279
|
+
message: isHex(message) ? {
|
|
282
280
|
raw: message
|
|
283
281
|
} : message
|
|
284
282
|
});
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { addHexPrefix } from '@ethereumjs/util';
|
|
2
1
|
import { TransactionStatus } from '@toruslabs/base-controllers';
|
|
3
2
|
import { rpcErrors, JsonRpcError } from '@web3auth/auth';
|
|
4
3
|
import { GetCallsStatusCode, EIP_5792_METHODS, EIP5792ErrorCode } from '../utils/eip5792Types.js';
|
|
4
|
+
import { addHexPrefix } from '../utils/hex.js';
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
7
|
* Maps a TransactionStatus to an EIP-5792 GetCallsStatusCode.
|
|
@@ -1,9 +1,8 @@
|
|
|
1
|
-
import { isValidAddress } from '@ethereumjs/util';
|
|
2
1
|
import { rpcErrors } from '@web3auth/auth';
|
|
3
|
-
import { isHexString } from 'ethers';
|
|
4
2
|
import { v4, parse } from 'uuid';
|
|
3
|
+
import { isHex, isAddress } from 'viem';
|
|
5
4
|
import { getIsEip7702UpgradeSupported } from '../Eip7702/eip7702Utils.js';
|
|
6
|
-
import {
|
|
5
|
+
import { EIP_5792_METHODS } from '../utils/eip5792Types.js';
|
|
7
6
|
|
|
8
7
|
/**
|
|
9
8
|
* Generates a unique batch ID for EIP-5792 calls.
|
|
@@ -23,20 +22,20 @@ function generateBatchId() {
|
|
|
23
22
|
*/
|
|
24
23
|
function validateCall(call, index) {
|
|
25
24
|
// Validate 'to' address
|
|
26
|
-
if (!call.to || !
|
|
25
|
+
if (!call.to || !isHex(call.to) || !isAddress(call.to)) {
|
|
27
26
|
throw rpcErrors.invalidParams(`Invalid 'to' address in call at index ${index}`);
|
|
28
27
|
}
|
|
29
28
|
|
|
30
29
|
// Validate 'value' if present
|
|
31
30
|
if (call.value !== undefined) {
|
|
32
|
-
if (!
|
|
31
|
+
if (!isHex(call.value)) {
|
|
33
32
|
throw rpcErrors.invalidParams(`Invalid 'value' in call at index ${index}: must be a valid non-negative hex string`);
|
|
34
33
|
}
|
|
35
34
|
}
|
|
36
35
|
|
|
37
36
|
// Validate 'data' if present
|
|
38
37
|
if (call.data !== undefined) {
|
|
39
|
-
if (!
|
|
38
|
+
if (!isHex(call.data)) {
|
|
40
39
|
throw rpcErrors.invalidParams(`Invalid 'data' in call at index ${index}: must be a valid hex string`);
|
|
41
40
|
}
|
|
42
41
|
}
|
|
@@ -53,12 +52,12 @@ function validateSendCallsParams(sendCallsParams) {
|
|
|
53
52
|
}
|
|
54
53
|
|
|
55
54
|
// Validate version format
|
|
56
|
-
if (!sendCallsParams.version ||
|
|
57
|
-
throw rpcErrors.invalidParams(`Invalid version: expected
|
|
55
|
+
if (!sendCallsParams.version || typeof sendCallsParams.version !== "string") {
|
|
56
|
+
throw rpcErrors.invalidParams(`Invalid version: expected a string, got "${sendCallsParams.version || "undefined"}"`);
|
|
58
57
|
}
|
|
59
58
|
|
|
60
59
|
// Validate chainId format
|
|
61
|
-
if (!sendCallsParams.chainId || !
|
|
60
|
+
if (!sendCallsParams.chainId || !isHex(sendCallsParams.chainId)) {
|
|
62
61
|
throw rpcErrors.invalidParams("Invalid chainId: must be a valid hex string");
|
|
63
62
|
}
|
|
64
63
|
|
|
@@ -66,7 +65,7 @@ function validateSendCallsParams(sendCallsParams) {
|
|
|
66
65
|
if (!sendCallsParams.from) {
|
|
67
66
|
throw rpcErrors.invalidParams("Missing 'from' address");
|
|
68
67
|
}
|
|
69
|
-
if (!
|
|
68
|
+
if (!isHex(sendCallsParams.from) || !isAddress(sendCallsParams.from)) {
|
|
70
69
|
throw rpcErrors.invalidParams("Invalid 'from' address: must be a valid hex address");
|
|
71
70
|
}
|
|
72
71
|
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { addHexPrefix } from '@ethereumjs/util';
|
|
2
1
|
import { zeroAddress, encodeAbiParameters, parseAbiParameters, encodeFunctionData } from 'viem';
|
|
3
2
|
import { erc7821Abi } from '../utils/abis.js';
|
|
4
3
|
import { SUPPORTED_NETWORKS } from '../utils/constants.js';
|
|
5
4
|
import { EIP_7702_PREFIX } from '../utils/eip7702Types.js';
|
|
5
|
+
import { addHexPrefix } from '../utils/hex.js';
|
|
6
6
|
|
|
7
7
|
/**
|
|
8
8
|
* The MetaMask EIP-7702 Stateless Delegator contract address.
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import _defineProperty from '@babel/runtime/helpers/defineProperty';
|
|
2
|
-
import { isHexString, addHexPrefix } from '@ethereumjs/util';
|
|
3
2
|
import { BaseController, PollingManager, cloneDeep } from '@toruslabs/base-controllers';
|
|
4
3
|
import log from 'loglevel';
|
|
4
|
+
import { isHex } from 'viem';
|
|
5
5
|
import { GAS_ESTIMATE_TYPES } from '../utils/constants.js';
|
|
6
|
+
import { addHexPrefix } from '../utils/hex.js';
|
|
6
7
|
import { fetchGasEstimates, fetchEthGasPriceEstimate, fetchLegacyGasPriceEstimates, fetchGasEstimatesViaEthFeeHistory, calculateTimeEstimate } from './gasUtil.js';
|
|
7
8
|
|
|
8
9
|
const GAS_FEE_API = "https://mock-gas-server.herokuapp.com/";
|
|
@@ -119,7 +120,7 @@ class GasFeeController extends BaseController {
|
|
|
119
120
|
const chainId = this.getNetworkIdentifier();
|
|
120
121
|
if (chainId === "loading") return;
|
|
121
122
|
let chainIdInt;
|
|
122
|
-
if (typeof chainId === "string" &&
|
|
123
|
+
if (typeof chainId === "string" && isHex(addHexPrefix(chainId))) {
|
|
123
124
|
chainIdInt = Number.parseInt(chainId, 16);
|
|
124
125
|
}
|
|
125
126
|
try {
|
|
@@ -1,8 +1,10 @@
|
|
|
1
|
-
import
|
|
2
|
-
import { addHexPrefix, bytesToHex, privateToPublic, toChecksumAddress, privateToAddress, stripHexPrefix, bigIntToBytes, isHexString } from '@ethereumjs/util';
|
|
1
|
+
import _objectSpread from '@babel/runtime/helpers/objectSpread2';
|
|
3
2
|
import { BaseKeyringController, ecsignature, concatSig } from '@toruslabs/base-controllers';
|
|
4
|
-
import {
|
|
5
|
-
import { toHex } from 'viem';
|
|
3
|
+
import { hexToBytes } from '@toruslabs/metadata-helpers';
|
|
4
|
+
import { serializeTransaction, keccak256, parseSignature, toHex, isHex } from 'viem';
|
|
5
|
+
import { privateKeyToAccount } from 'viem/accounts';
|
|
6
|
+
import { addHexPrefix, stripHexPrefix } from '../utils/hex.js';
|
|
7
|
+
import { prepareViemTx } from '../utils/viem.js';
|
|
6
8
|
|
|
7
9
|
class KeyringController extends BaseKeyringController {
|
|
8
10
|
constructor({
|
|
@@ -20,49 +22,55 @@ class KeyringController extends BaseKeyringController {
|
|
|
20
22
|
}
|
|
21
23
|
async signTransaction(tx, address) {
|
|
22
24
|
const wallet = this._getWalletForAccount(address);
|
|
23
|
-
const
|
|
25
|
+
const account = privateKeyToAccount(addHexPrefix(wallet.privateKey));
|
|
24
26
|
const localTx = tx;
|
|
25
|
-
|
|
26
|
-
return
|
|
27
|
+
const txToSign = prepareViemTx(localTx);
|
|
28
|
+
// NOTE: don't use account.signTransaction directly because it only return signed serialized transaction
|
|
29
|
+
// we don't want to compute unsigned hash and signature again
|
|
30
|
+
const serializedUnsigned = serializeTransaction(txToSign);
|
|
31
|
+
const unsignedHash = keccak256(serializedUnsigned);
|
|
32
|
+
const rawSig = await account.sign({
|
|
33
|
+
hash: unsignedHash
|
|
34
|
+
});
|
|
35
|
+
const signature = parseSignature(rawSig);
|
|
36
|
+
const serialized = serializeTransaction(txToSign, signature);
|
|
37
|
+
return _objectSpread(_objectSpread({}, txToSign), {}, {
|
|
38
|
+
unsignedHash,
|
|
39
|
+
serialized,
|
|
40
|
+
signature
|
|
41
|
+
});
|
|
27
42
|
}
|
|
28
43
|
async signEip7702Authorization(authorization, address) {
|
|
29
44
|
const wallet = this._getWalletForAccount(address);
|
|
30
|
-
const
|
|
45
|
+
const account = privateKeyToAccount(addHexPrefix(wallet.privateKey));
|
|
31
46
|
|
|
32
47
|
// Convert hex strings to proper types for RLP encoding
|
|
33
48
|
// EIP-7702 authorization tuple: [chain_id_decimal, address, nonce_decimal]
|
|
34
49
|
const chainIdDecimal = parseInt(authorization.chainId, 16);
|
|
35
50
|
const nonceDecimal = parseInt(authorization.nonce, 16);
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
const {
|
|
43
|
-
r,
|
|
44
|
-
s,
|
|
45
|
-
v
|
|
46
|
-
} = privKey.sign(authorizationHash);
|
|
47
|
-
const signedAuthorization = {
|
|
51
|
+
const signedAuthorization = await account.signAuthorization({
|
|
52
|
+
contractAddress: authorization.address,
|
|
53
|
+
chainId: chainIdDecimal,
|
|
54
|
+
nonce: nonceDecimal
|
|
55
|
+
});
|
|
56
|
+
return {
|
|
48
57
|
address: authorization.address,
|
|
49
58
|
chainId: authorization.chainId,
|
|
50
59
|
nonce: authorization.nonce,
|
|
51
|
-
r:
|
|
52
|
-
s:
|
|
53
|
-
yParity: toHex(
|
|
60
|
+
r: signedAuthorization.r,
|
|
61
|
+
s: signedAuthorization.s,
|
|
62
|
+
yParity: toHex(signedAuthorization.yParity)
|
|
54
63
|
};
|
|
55
|
-
return signedAuthorization;
|
|
56
64
|
}
|
|
57
65
|
getAccounts() {
|
|
58
66
|
return this.state.wallets.map(w => w.publicKey);
|
|
59
67
|
}
|
|
60
|
-
importAccount(accountPrivateKey) {
|
|
68
|
+
async importAccount(accountPrivateKey) {
|
|
61
69
|
try {
|
|
62
70
|
const hexPrivateKey = accountPrivateKey.padStart(64, "0");
|
|
63
|
-
const
|
|
64
|
-
const publicKey =
|
|
65
|
-
const address =
|
|
71
|
+
const account = privateKeyToAccount(addHexPrefix(hexPrivateKey));
|
|
72
|
+
const publicKey = account.publicKey;
|
|
73
|
+
const address = account.address;
|
|
66
74
|
const existingWallet = this.state.wallets.find(w => w.address === address);
|
|
67
75
|
if (existingWallet) return existingWallet.address;
|
|
68
76
|
this.update({
|
|
@@ -90,37 +98,57 @@ class KeyringController extends BaseKeyringController {
|
|
|
90
98
|
});
|
|
91
99
|
}
|
|
92
100
|
}
|
|
93
|
-
|
|
101
|
+
getPrivateKeyBytes(privateKey) {
|
|
94
102
|
const stripped = stripHexPrefix(privateKey);
|
|
95
|
-
return
|
|
103
|
+
return hexToBytes(stripped);
|
|
96
104
|
}
|
|
97
105
|
|
|
98
106
|
// For eth_sign, we need to sign arbitrary data:
|
|
99
107
|
async signMessage(data, address) {
|
|
108
|
+
if (typeof data !== "string") {
|
|
109
|
+
throw new Error("Torus Keyring - signMessage data must be type 'string'");
|
|
110
|
+
}
|
|
100
111
|
const wallet = this._getWalletForAccount(address);
|
|
101
|
-
const privKey = this.
|
|
102
|
-
const
|
|
103
|
-
const
|
|
112
|
+
const privKey = this.getPrivateKeyBytes(wallet.privateKey);
|
|
113
|
+
const payload = hexToBytes(stripHexPrefix(data));
|
|
114
|
+
const messageSig = ecsignature(payload, privKey);
|
|
115
|
+
const sig = concatSig(messageSig.v, messageSig.r, messageSig.s);
|
|
104
116
|
return sig;
|
|
105
117
|
}
|
|
106
118
|
async signPersonalMessage(data, address) {
|
|
107
119
|
const wallet = this._getWalletForAccount(address);
|
|
108
|
-
const
|
|
120
|
+
const account = privateKeyToAccount(addHexPrefix(wallet.privateKey));
|
|
109
121
|
// we need to check if the data is hex or not
|
|
110
122
|
// For historical reasons, you must submit the message to sign in hex-encoded UTF-8.
|
|
111
123
|
// https://docs.metamask.io/wallet/how-to/sign-data/#use-personal_sign
|
|
112
|
-
const message =
|
|
113
|
-
|
|
114
|
-
|
|
124
|
+
const message = isHex(data) ? {
|
|
125
|
+
raw: data
|
|
126
|
+
} : data;
|
|
127
|
+
return account.signMessage({
|
|
128
|
+
message
|
|
129
|
+
});
|
|
115
130
|
}
|
|
116
131
|
|
|
117
132
|
// personal_signTypedData, signs data along with the schema
|
|
118
133
|
async signTypedData(typedData, address) {
|
|
119
134
|
const wallet = this._getWalletForAccount(address);
|
|
120
|
-
const
|
|
135
|
+
const account = privateKeyToAccount(addHexPrefix(wallet.privateKey));
|
|
121
136
|
delete typedData.types.EIP712Domain;
|
|
122
|
-
const
|
|
123
|
-
|
|
137
|
+
const primaryType = typedData.primaryType;
|
|
138
|
+
if (!primaryType) {
|
|
139
|
+
throw new Error("Torus Keyring - primaryType is required");
|
|
140
|
+
}
|
|
141
|
+
const rawSig = await account.signTypedData({
|
|
142
|
+
domain: _objectSpread(_objectSpread({}, typedData.domain), {}, {
|
|
143
|
+
chainId: typeof typedData.domain.chainId === "string" ? parseInt(typedData.domain.chainId, 16) : typedData.domain.chainId,
|
|
144
|
+
salt: typedData.domain.salt,
|
|
145
|
+
verifyingContract: typedData.domain.verifyingContract
|
|
146
|
+
}),
|
|
147
|
+
types: typedData.types,
|
|
148
|
+
primaryType,
|
|
149
|
+
message: typedData.message
|
|
150
|
+
});
|
|
151
|
+
return rawSig;
|
|
124
152
|
}
|
|
125
153
|
_getWalletForAccount(account) {
|
|
126
154
|
const address = account.toLowerCase();
|
|
@@ -1,10 +1,11 @@
|
|
|
1
|
-
import { isValidAddress, stripHexPrefix, addHexPrefix, bytesToHex } from '@ethereumjs/util';
|
|
2
1
|
import { CHAIN_NAMESPACES } from '@toruslabs/base-controllers';
|
|
3
|
-
import {
|
|
2
|
+
import { bytesToHex, utf8ToBytes } from '@toruslabs/metadata-helpers';
|
|
3
|
+
import { isHex, createPublicClient, http, toHex, isAddress } from 'viem';
|
|
4
|
+
import { stripHexPrefix, addHexPrefix } from '../utils/hex.js';
|
|
4
5
|
|
|
5
6
|
const hexRe = /^[0-9A-Fa-f]+$/gu;
|
|
6
7
|
function validateAddress(address, propertyName) {
|
|
7
|
-
if (!address || typeof address !== "string" || !
|
|
8
|
+
if (!address || typeof address !== "string" || !isAddress(address)) {
|
|
8
9
|
throw new Error(`Invalid "${propertyName}" address: ${address} must be a valid string.`);
|
|
9
10
|
}
|
|
10
11
|
}
|
|
@@ -27,7 +28,7 @@ function normalizeMessageData(data) {
|
|
|
27
28
|
} catch {
|
|
28
29
|
// do nothing
|
|
29
30
|
}
|
|
30
|
-
return bytesToHex(
|
|
31
|
+
return addHexPrefix(bytesToHex(utf8ToBytes(data)));
|
|
31
32
|
}
|
|
32
33
|
async function validateTypedSignMessageDataV4(messageData, currentChainId) {
|
|
33
34
|
validateAddress(messageData.from, "from");
|
|
@@ -72,7 +73,7 @@ async function validateAddChainData(data) {
|
|
|
72
73
|
if (!chainId) {
|
|
73
74
|
throw new Error("Invalid add chain params: please pass chainId in params");
|
|
74
75
|
}
|
|
75
|
-
if (!
|
|
76
|
+
if (!isHex(chainId)) {
|
|
76
77
|
throw new Error("Invalid add chain params: please pass a valid hex chainId in params, for: ex: 0x1");
|
|
77
78
|
}
|
|
78
79
|
if (!rpcUrls || rpcUrls.length === 0) throw new Error("params.rpcUrls not provided");
|
|
@@ -85,12 +86,12 @@ async function validateAddChainData(data) {
|
|
|
85
86
|
if (!name) throw new Error("params.nativeCurrency.name not provided");
|
|
86
87
|
if (!symbol) throw new Error("params.nativeCurrency.symbol not provided");
|
|
87
88
|
if (decimals === undefined) throw new Error("params.nativeCurrency.decimals not provided");
|
|
88
|
-
const
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
if (
|
|
93
|
-
throw new Error(`Provided rpc url's chainId version is not matching with provided chainId, expected: ${
|
|
89
|
+
const client = createPublicClient({
|
|
90
|
+
transport: http(rpcUrls[0])
|
|
91
|
+
});
|
|
92
|
+
const networkChainID = await client.getChainId();
|
|
93
|
+
if (networkChainID !== Number.parseInt(chainId, 16)) {
|
|
94
|
+
throw new Error(`Provided rpc url's chainId version is not matching with provided chainId, expected: ${toHex(networkChainID)}, received: ${chainId}`);
|
|
94
95
|
}
|
|
95
96
|
}
|
|
96
97
|
function validateSwitchChainData(data) {
|
|
@@ -100,7 +101,7 @@ function validateSwitchChainData(data) {
|
|
|
100
101
|
if (!fullChainId) {
|
|
101
102
|
throw new Error("Invalid switch chain params: please pass chainId in params");
|
|
102
103
|
}
|
|
103
|
-
if (!
|
|
104
|
+
if (!isHex(fullChainId)) {
|
|
104
105
|
const [namespace, chainId] = fullChainId.split(":");
|
|
105
106
|
if (namespace !== CHAIN_NAMESPACES.SOLANA && namespace !== CHAIN_NAMESPACES.EIP155) {
|
|
106
107
|
throw new Error("Invalid switch chain params: invalid namespace");
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { createFetchMiddleware, PROVIDER_JRPC_METHODS, createGenericJRPCMiddleware } from '@toruslabs/base-controllers';
|
|
2
|
+
import { mergeMiddleware, createScaffoldMiddleware, createAsyncMiddleware } from '@web3auth/auth';
|
|
3
3
|
import { walletGetUpgradeStatus } from '../Eip7702/walletGetUpgradeStatus.js';
|
|
4
4
|
import { walletUpgradeAccount } from '../Eip7702/walletUpgradeAccount.js';
|
|
5
5
|
import { METHOD_TYPES, TRANSACTION_ENVELOPE_TYPES, BUNDLER_METHOD_TYPES, PAYMASTER_METHOD_TYPES } from '../utils/constants.js';
|