@sidhujag/sysweb3-keyring 1.0.491
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/README.md +201 -0
- package/cjs/errorUtils.js +75 -0
- package/cjs/errorUtils.js.map +1 -0
- package/cjs/hardware-wallet-manager.js +462 -0
- package/cjs/hardware-wallet-manager.js.map +1 -0
- package/cjs/index.js +31 -0
- package/cjs/index.js.map +1 -0
- package/cjs/initial-state.js +105 -0
- package/cjs/initial-state.js.map +1 -0
- package/cjs/keyring-manager.js +1687 -0
- package/cjs/keyring-manager.js.map +1 -0
- package/cjs/ledger/bitcoin_client/index.js +47 -0
- package/cjs/ledger/bitcoin_client/index.js.map +1 -0
- package/cjs/ledger/bitcoin_client/lib/appClient.js +408 -0
- package/cjs/ledger/bitcoin_client/lib/appClient.js.map +1 -0
- package/cjs/ledger/bitcoin_client/lib/bip32.js +61 -0
- package/cjs/ledger/bitcoin_client/lib/bip32.js.map +1 -0
- package/cjs/ledger/bitcoin_client/lib/buffertools.js +126 -0
- package/cjs/ledger/bitcoin_client/lib/buffertools.js.map +1 -0
- package/cjs/ledger/bitcoin_client/lib/clientCommands.js +270 -0
- package/cjs/ledger/bitcoin_client/lib/clientCommands.js.map +1 -0
- package/cjs/ledger/bitcoin_client/lib/constants.js +16 -0
- package/cjs/ledger/bitcoin_client/lib/constants.js.map +1 -0
- package/cjs/ledger/bitcoin_client/lib/merkelizedPsbt.js +54 -0
- package/cjs/ledger/bitcoin_client/lib/merkelizedPsbt.js.map +1 -0
- package/cjs/ledger/bitcoin_client/lib/merkle.js +109 -0
- package/cjs/ledger/bitcoin_client/lib/merkle.js.map +1 -0
- package/cjs/ledger/bitcoin_client/lib/merkleMap.js +46 -0
- package/cjs/ledger/bitcoin_client/lib/merkleMap.js.map +1 -0
- package/cjs/ledger/bitcoin_client/lib/policy.js +66 -0
- package/cjs/ledger/bitcoin_client/lib/policy.js.map +1 -0
- package/cjs/ledger/bitcoin_client/lib/psbtv2.js +640 -0
- package/cjs/ledger/bitcoin_client/lib/psbtv2.js.map +1 -0
- package/cjs/ledger/bitcoin_client/lib/varint.js +113 -0
- package/cjs/ledger/bitcoin_client/lib/varint.js.map +1 -0
- package/cjs/ledger/consts.js +7 -0
- package/cjs/ledger/consts.js.map +1 -0
- package/cjs/ledger/index.js +319 -0
- package/cjs/ledger/index.js.map +1 -0
- package/cjs/ledger/types.js +3 -0
- package/cjs/ledger/types.js.map +1 -0
- package/cjs/network-utils.js +76 -0
- package/cjs/network-utils.js.map +1 -0
- package/cjs/providers.js +270 -0
- package/cjs/providers.js.map +1 -0
- package/cjs/signers.js +64 -0
- package/cjs/signers.js.map +1 -0
- package/cjs/storage.js +30 -0
- package/cjs/storage.js.map +1 -0
- package/cjs/transactions/__tests__/integration.test.js +237 -0
- package/cjs/transactions/__tests__/integration.test.js.map +1 -0
- package/cjs/transactions/__tests__/syscoin.test.js +361 -0
- package/cjs/transactions/__tests__/syscoin.test.js.map +1 -0
- package/cjs/transactions/ethereum.js +1577 -0
- package/cjs/transactions/ethereum.js.map +1 -0
- package/cjs/transactions/index.js +19 -0
- package/cjs/transactions/index.js.map +1 -0
- package/cjs/transactions/syscoin.js +328 -0
- package/cjs/transactions/syscoin.js.map +1 -0
- package/cjs/trezor/index.js +718 -0
- package/cjs/trezor/index.js.map +1 -0
- package/cjs/types.js +12 -0
- package/cjs/types.js.map +1 -0
- package/cjs/utils/derivation-paths.js +99 -0
- package/cjs/utils/derivation-paths.js.map +1 -0
- package/cjs/utils/psbt.js +60 -0
- package/cjs/utils/psbt.js.map +1 -0
- package/cjs/utils.js +130 -0
- package/cjs/utils.js.map +1 -0
- package/package.json +46 -0
- package/types/errorUtils.d.ts +1 -0
- package/types/hardware-wallet-manager.d.ts +110 -0
- package/types/index.d.ts +12 -0
- package/types/initial-state.d.ts +79 -0
- package/types/keyring-manager.d.ts +184 -0
- package/types/ledger/bitcoin_client/index.d.ts +5 -0
- package/types/ledger/bitcoin_client/lib/appClient.d.ts +106 -0
- package/types/ledger/bitcoin_client/lib/bip32.d.ts +11 -0
- package/types/ledger/bitcoin_client/lib/buffertools.d.ts +28 -0
- package/types/ledger/bitcoin_client/lib/clientCommands.d.ts +77 -0
- package/types/ledger/bitcoin_client/lib/constants.d.ts +12 -0
- package/types/ledger/bitcoin_client/lib/merkelizedPsbt.d.ts +24 -0
- package/types/ledger/bitcoin_client/lib/merkle.d.ts +32 -0
- package/types/ledger/bitcoin_client/lib/merkleMap.d.ts +23 -0
- package/types/ledger/bitcoin_client/lib/policy.d.ts +36 -0
- package/types/ledger/bitcoin_client/lib/psbtv2.d.ts +167 -0
- package/types/ledger/bitcoin_client/lib/varint.d.ts +23 -0
- package/types/ledger/consts.d.ts +3 -0
- package/types/ledger/index.d.ts +51 -0
- package/types/ledger/types.d.ts +48 -0
- package/types/network-utils.d.ts +14 -0
- package/types/providers.d.ts +47 -0
- package/types/signers.d.ts +95 -0
- package/types/storage.d.ts +2 -0
- package/types/transactions/__tests__/integration.test.d.ts +1 -0
- package/types/transactions/__tests__/syscoin.test.d.ts +1 -0
- package/types/transactions/ethereum.d.ts +80 -0
- package/types/transactions/index.d.ts +2 -0
- package/types/transactions/syscoin.d.ts +61 -0
- package/types/trezor/index.d.ts +170 -0
- package/types/types.d.ts +294 -0
- package/types/utils/derivation-paths.d.ts +35 -0
- package/types/utils/psbt.d.ts +17 -0
- package/types/utils.d.ts +4 -0
|
@@ -0,0 +1,1577 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.EthereumTransactions = void 0;
|
|
7
|
+
const sysweb3_network_1 = require("@sidhujag/sysweb3-network");
|
|
8
|
+
const sysweb3_utils_1 = require("@sidhujag/sysweb3-utils");
|
|
9
|
+
const eth_sig_util_1 = require("eth-sig-util");
|
|
10
|
+
const ethereumjs_util_1 = require("ethereumjs-util");
|
|
11
|
+
const ethers_1 = require("ethers");
|
|
12
|
+
const floor_1 = __importDefault(require("lodash/floor"));
|
|
13
|
+
const omit_1 = __importDefault(require("lodash/omit"));
|
|
14
|
+
const providers_1 = require("../providers");
|
|
15
|
+
const types_1 = require("../types");
|
|
16
|
+
/**
|
|
17
|
+
* Chain IDs for zkSync Era networks that require specialized L2 provider functionality.
|
|
18
|
+
* These networks use CustomL2JsonRpcProvider (which extends zksync-ethers.Provider)
|
|
19
|
+
* instead of CustomJsonRpcProvider.
|
|
20
|
+
*
|
|
21
|
+
* zkSync Era networks:
|
|
22
|
+
* - 324: zkSync Era Mainnet
|
|
23
|
+
* - 300: zkSync Era Sepolia Testnet
|
|
24
|
+
*/
|
|
25
|
+
const L2_NETWORK_CHAIN_IDS = [324, 300];
|
|
26
|
+
class EthereumTransactions {
|
|
27
|
+
constructor(getNetwork, getDecryptedPrivateKey, getState, ledgerSigner, trezorSigner) {
|
|
28
|
+
this.signTypedData = async (addr, typedData, version) => {
|
|
29
|
+
const { address, decryptedPrivateKey } = this.getDecryptedPrivateKey();
|
|
30
|
+
const { activeAccountType, accounts, activeAccountId } = this.getState();
|
|
31
|
+
const activeAccount = accounts[activeAccountType][activeAccountId];
|
|
32
|
+
// Validate that the derived address matches the active account to prevent race conditions
|
|
33
|
+
if (address.toLowerCase() !== activeAccount.address.toLowerCase()) {
|
|
34
|
+
throw {
|
|
35
|
+
message: `Account state mismatch detected. Expected ${activeAccount.address} but got ${address}. Please try again after account switching completes.`,
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
const signTypedData = () => {
|
|
39
|
+
if (addr.toLowerCase() !== address.toLowerCase())
|
|
40
|
+
throw {
|
|
41
|
+
message: 'Decrypting for wrong address, change activeAccount maybe',
|
|
42
|
+
};
|
|
43
|
+
const privKey = Buffer.from((0, ethereumjs_util_1.stripHexPrefix)(decryptedPrivateKey), 'hex');
|
|
44
|
+
return (0, eth_sig_util_1.signTypedMessage)(privKey, { data: typedData }, version);
|
|
45
|
+
};
|
|
46
|
+
const signTypedDataWithLedger = async () => {
|
|
47
|
+
if (addr.toLowerCase() !== activeAccount.address.toLowerCase())
|
|
48
|
+
throw {
|
|
49
|
+
message: 'Decrypting for wrong address, change activeAccount maybe',
|
|
50
|
+
};
|
|
51
|
+
return await this.ledgerSigner.evm.signTypedData({
|
|
52
|
+
version,
|
|
53
|
+
accountIndex: activeAccountId,
|
|
54
|
+
data: typedData,
|
|
55
|
+
});
|
|
56
|
+
};
|
|
57
|
+
const signTypedDataWithTrezor = async () => {
|
|
58
|
+
if (addr.toLowerCase() !== activeAccount.address.toLowerCase())
|
|
59
|
+
throw {
|
|
60
|
+
message: 'Decrypting for wrong address, change activeAccount maybe',
|
|
61
|
+
};
|
|
62
|
+
return await this.trezorSigner.signTypedData({
|
|
63
|
+
version,
|
|
64
|
+
address: addr,
|
|
65
|
+
data: typedData,
|
|
66
|
+
index: activeAccountId,
|
|
67
|
+
});
|
|
68
|
+
};
|
|
69
|
+
switch (activeAccountType) {
|
|
70
|
+
case types_1.KeyringAccountType.Trezor:
|
|
71
|
+
return await signTypedDataWithTrezor();
|
|
72
|
+
case types_1.KeyringAccountType.Ledger:
|
|
73
|
+
return await signTypedDataWithLedger();
|
|
74
|
+
default:
|
|
75
|
+
return signTypedData();
|
|
76
|
+
}
|
|
77
|
+
};
|
|
78
|
+
this.verifyTypedSignature = (data, signature, version) => {
|
|
79
|
+
try {
|
|
80
|
+
const msgParams = {
|
|
81
|
+
data,
|
|
82
|
+
sig: signature,
|
|
83
|
+
};
|
|
84
|
+
return (0, eth_sig_util_1.recoverTypedMessage)(msgParams, version);
|
|
85
|
+
}
|
|
86
|
+
catch (error) {
|
|
87
|
+
throw error;
|
|
88
|
+
}
|
|
89
|
+
};
|
|
90
|
+
this.ethSign = async (params) => {
|
|
91
|
+
const { address, decryptedPrivateKey } = this.getDecryptedPrivateKey();
|
|
92
|
+
const { accounts, activeAccountId, activeAccountType, activeNetwork } = this.getState();
|
|
93
|
+
const activeAccount = accounts[activeAccountType][activeAccountId];
|
|
94
|
+
// Validate that the derived address matches the active account to prevent race conditions
|
|
95
|
+
if (address.toLowerCase() !== activeAccount.address.toLowerCase()) {
|
|
96
|
+
throw {
|
|
97
|
+
message: `Account state mismatch detected. Expected ${activeAccount.address} but got ${address}. Please try again after account switching completes.`,
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
let msg = '';
|
|
101
|
+
//Comparisions do not need to care for checksum address
|
|
102
|
+
if (params[0].toLowerCase() === address.toLowerCase()) {
|
|
103
|
+
msg = (0, ethereumjs_util_1.stripHexPrefix)(params[1]);
|
|
104
|
+
}
|
|
105
|
+
else if (params[1].toLowerCase() === address.toLowerCase()) {
|
|
106
|
+
msg = (0, ethereumjs_util_1.stripHexPrefix)(params[0]);
|
|
107
|
+
}
|
|
108
|
+
else {
|
|
109
|
+
throw new Error('Signing for wrong address');
|
|
110
|
+
}
|
|
111
|
+
const sign = () => {
|
|
112
|
+
try {
|
|
113
|
+
const bufPriv = (0, ethereumjs_util_1.toBuffer)(decryptedPrivateKey);
|
|
114
|
+
// Validate and prepare the message for eth_sign
|
|
115
|
+
let msgHash;
|
|
116
|
+
// Check if message is a valid 32-byte hex string
|
|
117
|
+
if (msg.length === 64 && /^[0-9a-fA-F]+$/.test(msg)) {
|
|
118
|
+
// Message is already a 32-byte hex string
|
|
119
|
+
msgHash = Buffer.from(msg, 'hex');
|
|
120
|
+
}
|
|
121
|
+
else {
|
|
122
|
+
// Message is not a proper hash - provide helpful error
|
|
123
|
+
throw new Error(`Expected message to be an Uint8Array with length 32. ` +
|
|
124
|
+
`Got message of length ${msg.length}: "${msg.substring(0, 50)}${msg.length > 50 ? '...' : ''}". ` +
|
|
125
|
+
`For signing arbitrary text, use personal_sign instead of eth_sign.`);
|
|
126
|
+
}
|
|
127
|
+
const sig = (0, ethereumjs_util_1.ecsign)(msgHash, bufPriv);
|
|
128
|
+
const resp = (0, eth_sig_util_1.concatSig)((0, ethereumjs_util_1.toBuffer)(sig.v), sig.r, sig.s);
|
|
129
|
+
return resp;
|
|
130
|
+
}
|
|
131
|
+
catch (error) {
|
|
132
|
+
throw error;
|
|
133
|
+
}
|
|
134
|
+
};
|
|
135
|
+
const signWithLedger = async () => {
|
|
136
|
+
try {
|
|
137
|
+
const response = await this.ledgerSigner.evm.signPersonalMessage({
|
|
138
|
+
accountIndex: activeAccountId,
|
|
139
|
+
message: msg,
|
|
140
|
+
});
|
|
141
|
+
return response;
|
|
142
|
+
}
|
|
143
|
+
catch (error) {
|
|
144
|
+
throw error;
|
|
145
|
+
}
|
|
146
|
+
};
|
|
147
|
+
const signWithTrezor = async () => {
|
|
148
|
+
try {
|
|
149
|
+
// For EVM networks, Trezor expects 'eth' regardless of the network's currency
|
|
150
|
+
const trezorCoin = activeNetwork.slip44 === 60 ? 'eth' : activeNetwork.currency;
|
|
151
|
+
const response = await this.trezorSigner.signMessage({
|
|
152
|
+
coin: trezorCoin,
|
|
153
|
+
address: activeAccount.address,
|
|
154
|
+
index: activeAccountId,
|
|
155
|
+
message: msg,
|
|
156
|
+
slip44: activeNetwork.slip44,
|
|
157
|
+
});
|
|
158
|
+
return response.signature;
|
|
159
|
+
}
|
|
160
|
+
catch (error) {
|
|
161
|
+
throw error;
|
|
162
|
+
}
|
|
163
|
+
};
|
|
164
|
+
switch (activeAccountType) {
|
|
165
|
+
case types_1.KeyringAccountType.Trezor:
|
|
166
|
+
return await signWithTrezor();
|
|
167
|
+
case types_1.KeyringAccountType.Ledger:
|
|
168
|
+
return await signWithLedger();
|
|
169
|
+
default:
|
|
170
|
+
return sign();
|
|
171
|
+
}
|
|
172
|
+
};
|
|
173
|
+
this.signPersonalMessage = async (params) => {
|
|
174
|
+
const { address, decryptedPrivateKey } = this.getDecryptedPrivateKey();
|
|
175
|
+
const { accounts, activeAccountId, activeAccountType, activeNetwork } = this.getState();
|
|
176
|
+
const activeAccount = accounts[activeAccountType][activeAccountId];
|
|
177
|
+
// Validate that the derived address matches the active account to prevent race conditions
|
|
178
|
+
if (address.toLowerCase() !== activeAccount.address.toLowerCase()) {
|
|
179
|
+
throw {
|
|
180
|
+
message: `Account state mismatch detected. Expected ${activeAccount.address} but got ${address}. Please try again after account switching completes.`,
|
|
181
|
+
};
|
|
182
|
+
}
|
|
183
|
+
let msg = '';
|
|
184
|
+
if (params[0].toLowerCase() === address.toLowerCase()) {
|
|
185
|
+
msg = params[1];
|
|
186
|
+
}
|
|
187
|
+
else if (params[1].toLowerCase() === address.toLowerCase()) {
|
|
188
|
+
msg = params[0];
|
|
189
|
+
}
|
|
190
|
+
else {
|
|
191
|
+
throw new Error('Signing for wrong address');
|
|
192
|
+
}
|
|
193
|
+
const signPersonalMessageWithDefaultWallet = () => {
|
|
194
|
+
try {
|
|
195
|
+
const privateKey = (0, ethereumjs_util_1.toBuffer)(decryptedPrivateKey);
|
|
196
|
+
// Handle both hex-encoded and plain text messages for personal_sign
|
|
197
|
+
let message;
|
|
198
|
+
if (msg.startsWith('0x')) {
|
|
199
|
+
// Message is hex-encoded
|
|
200
|
+
try {
|
|
201
|
+
message = (0, ethereumjs_util_1.toBuffer)(msg);
|
|
202
|
+
}
|
|
203
|
+
catch (error) {
|
|
204
|
+
// If hex parsing fails, treat as plain text
|
|
205
|
+
message = Buffer.from(msg, 'utf8');
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
else {
|
|
209
|
+
// Message is plain text
|
|
210
|
+
message = Buffer.from(msg, 'utf8');
|
|
211
|
+
}
|
|
212
|
+
const msgHash = (0, ethereumjs_util_1.hashPersonalMessage)(message);
|
|
213
|
+
const sig = (0, ethereumjs_util_1.ecsign)(msgHash, privateKey);
|
|
214
|
+
const serialized = (0, eth_sig_util_1.concatSig)((0, ethereumjs_util_1.toBuffer)(sig.v), sig.r, sig.s);
|
|
215
|
+
return serialized;
|
|
216
|
+
}
|
|
217
|
+
catch (error) {
|
|
218
|
+
throw error;
|
|
219
|
+
}
|
|
220
|
+
};
|
|
221
|
+
const signPersonalMessageWithLedger = async () => {
|
|
222
|
+
try {
|
|
223
|
+
// Handle both hex-encoded and plain text messages for personal_sign
|
|
224
|
+
let messageForLedger;
|
|
225
|
+
if (msg.startsWith('0x')) {
|
|
226
|
+
// Message is hex-encoded, remove 0x prefix
|
|
227
|
+
messageForLedger = msg.replace('0x', '');
|
|
228
|
+
}
|
|
229
|
+
else {
|
|
230
|
+
// Message is plain text, convert to hex
|
|
231
|
+
messageForLedger = Buffer.from(msg, 'utf8').toString('hex');
|
|
232
|
+
}
|
|
233
|
+
const response = await this.ledgerSigner.evm.signPersonalMessage({
|
|
234
|
+
accountIndex: activeAccountId,
|
|
235
|
+
message: messageForLedger,
|
|
236
|
+
});
|
|
237
|
+
return response;
|
|
238
|
+
}
|
|
239
|
+
catch (error) {
|
|
240
|
+
throw error;
|
|
241
|
+
}
|
|
242
|
+
};
|
|
243
|
+
const signPersonalMessageWithTrezor = async () => {
|
|
244
|
+
try {
|
|
245
|
+
// Handle both hex-encoded and plain text messages for personal_sign
|
|
246
|
+
let messageForTrezor;
|
|
247
|
+
if (msg.startsWith('0x')) {
|
|
248
|
+
// Message is hex-encoded, keep as is
|
|
249
|
+
messageForTrezor = msg;
|
|
250
|
+
}
|
|
251
|
+
else {
|
|
252
|
+
// Message is plain text, convert to hex with 0x prefix
|
|
253
|
+
messageForTrezor = '0x' + Buffer.from(msg, 'utf8').toString('hex');
|
|
254
|
+
}
|
|
255
|
+
// For EVM networks, Trezor expects 'eth' regardless of the network's currency
|
|
256
|
+
const trezorCoin = activeNetwork.slip44 === 60 ? 'eth' : activeNetwork.currency;
|
|
257
|
+
const response = await this.trezorSigner.signMessage({
|
|
258
|
+
coin: trezorCoin,
|
|
259
|
+
address: activeAccount.address,
|
|
260
|
+
index: activeAccountId,
|
|
261
|
+
message: messageForTrezor,
|
|
262
|
+
slip44: activeNetwork.slip44,
|
|
263
|
+
});
|
|
264
|
+
return response.signature;
|
|
265
|
+
}
|
|
266
|
+
catch (error) {
|
|
267
|
+
throw error;
|
|
268
|
+
}
|
|
269
|
+
};
|
|
270
|
+
switch (activeAccountType) {
|
|
271
|
+
case types_1.KeyringAccountType.Trezor:
|
|
272
|
+
return await signPersonalMessageWithTrezor();
|
|
273
|
+
case types_1.KeyringAccountType.Ledger:
|
|
274
|
+
return await signPersonalMessageWithLedger();
|
|
275
|
+
default:
|
|
276
|
+
return signPersonalMessageWithDefaultWallet();
|
|
277
|
+
}
|
|
278
|
+
};
|
|
279
|
+
this.parsePersonalMessage = (hexMsg) => {
|
|
280
|
+
try {
|
|
281
|
+
return (0, ethereumjs_util_1.toAscii)(hexMsg);
|
|
282
|
+
}
|
|
283
|
+
catch (error) {
|
|
284
|
+
throw error;
|
|
285
|
+
}
|
|
286
|
+
};
|
|
287
|
+
this.verifyPersonalMessage = (message, sign) => {
|
|
288
|
+
try {
|
|
289
|
+
const msgParams = {
|
|
290
|
+
data: message,
|
|
291
|
+
sig: sign,
|
|
292
|
+
};
|
|
293
|
+
return (0, eth_sig_util_1.recoverPersonalSignature)(msgParams);
|
|
294
|
+
}
|
|
295
|
+
catch (error) {
|
|
296
|
+
throw error;
|
|
297
|
+
}
|
|
298
|
+
};
|
|
299
|
+
this.getEncryptedPubKey = () => {
|
|
300
|
+
const { decryptedPrivateKey } = this.getDecryptedPrivateKey();
|
|
301
|
+
try {
|
|
302
|
+
return (0, eth_sig_util_1.getEncryptionPublicKey)((0, ethereumjs_util_1.stripHexPrefix)(decryptedPrivateKey));
|
|
303
|
+
}
|
|
304
|
+
catch (error) {
|
|
305
|
+
throw error;
|
|
306
|
+
}
|
|
307
|
+
};
|
|
308
|
+
// eth_decryptMessage
|
|
309
|
+
this.decryptMessage = (msgParams) => {
|
|
310
|
+
const { address, decryptedPrivateKey } = this.getDecryptedPrivateKey();
|
|
311
|
+
let encryptedData = '';
|
|
312
|
+
if (msgParams[0].toLowerCase() === address.toLowerCase()) {
|
|
313
|
+
encryptedData = msgParams[1];
|
|
314
|
+
}
|
|
315
|
+
else if (msgParams[1].toLowerCase() === address.toLowerCase()) {
|
|
316
|
+
encryptedData = msgParams[0];
|
|
317
|
+
}
|
|
318
|
+
else {
|
|
319
|
+
throw new Error('Decrypting for wrong receiver');
|
|
320
|
+
}
|
|
321
|
+
encryptedData = (0, ethereumjs_util_1.stripHexPrefix)(encryptedData);
|
|
322
|
+
try {
|
|
323
|
+
const buff = Buffer.from(encryptedData, 'hex');
|
|
324
|
+
const cleanData = JSON.parse(buff.toString('utf8'));
|
|
325
|
+
const sig = (0, eth_sig_util_1.decrypt)(cleanData, (0, ethereumjs_util_1.stripHexPrefix)(decryptedPrivateKey));
|
|
326
|
+
return sig;
|
|
327
|
+
}
|
|
328
|
+
catch (error) {
|
|
329
|
+
throw error;
|
|
330
|
+
}
|
|
331
|
+
};
|
|
332
|
+
this.toBigNumber = (aBigNumberish) => ethers_1.ethers.BigNumber.from(String(aBigNumberish));
|
|
333
|
+
this.getData = ({ contractAddress, receivingAddress, value, }) => {
|
|
334
|
+
const abi = (0, sysweb3_utils_1.getErc20Abi)();
|
|
335
|
+
try {
|
|
336
|
+
const contract = (0, sysweb3_utils_1.createContractUsingAbi)(abi, contractAddress, this.web3Provider);
|
|
337
|
+
const data = contract.methods
|
|
338
|
+
.transfer(receivingAddress, value)
|
|
339
|
+
.encodeABI();
|
|
340
|
+
return data;
|
|
341
|
+
}
|
|
342
|
+
catch (error) {
|
|
343
|
+
throw error;
|
|
344
|
+
}
|
|
345
|
+
};
|
|
346
|
+
this.getFeeDataWithDynamicMaxPriorityFeePerGas = async () => {
|
|
347
|
+
let maxFeePerGas = this.toBigNumber(0);
|
|
348
|
+
let maxPriorityFeePerGas = this.toBigNumber(0);
|
|
349
|
+
try {
|
|
350
|
+
const block = await this.web3Provider.getBlock('latest');
|
|
351
|
+
if (block && block.baseFeePerGas) {
|
|
352
|
+
try {
|
|
353
|
+
const ethMaxPriorityFee = await this.web3Provider.send('eth_maxPriorityFeePerGas', []);
|
|
354
|
+
maxPriorityFeePerGas = ethers_1.ethers.BigNumber.from(ethMaxPriorityFee);
|
|
355
|
+
maxFeePerGas = block.baseFeePerGas.mul(2).add(maxPriorityFeePerGas);
|
|
356
|
+
}
|
|
357
|
+
catch (e) {
|
|
358
|
+
maxPriorityFeePerGas = ethers_1.ethers.BigNumber.from('1500000000');
|
|
359
|
+
maxFeePerGas = block.baseFeePerGas.mul(2).add(maxPriorityFeePerGas);
|
|
360
|
+
}
|
|
361
|
+
return { maxFeePerGas, maxPriorityFeePerGas };
|
|
362
|
+
}
|
|
363
|
+
else if (block && !block.baseFeePerGas) {
|
|
364
|
+
console.error('Chain doesnt support EIP1559');
|
|
365
|
+
return { maxFeePerGas, maxPriorityFeePerGas };
|
|
366
|
+
}
|
|
367
|
+
else if (!block)
|
|
368
|
+
throw new Error('Block not found');
|
|
369
|
+
return { maxFeePerGas, maxPriorityFeePerGas };
|
|
370
|
+
}
|
|
371
|
+
catch (error) {
|
|
372
|
+
console.error(error);
|
|
373
|
+
return { maxFeePerGas, maxPriorityFeePerGas };
|
|
374
|
+
}
|
|
375
|
+
};
|
|
376
|
+
this.calculateNewGasValues = (oldTxsParams, isForCancel, isLegacy) => {
|
|
377
|
+
const newGasValues = {
|
|
378
|
+
maxFeePerGas: undefined,
|
|
379
|
+
maxPriorityFeePerGas: undefined,
|
|
380
|
+
gasPrice: undefined,
|
|
381
|
+
gasLimit: undefined,
|
|
382
|
+
};
|
|
383
|
+
const { maxFeePerGas, maxPriorityFeePerGas, gasLimit, gasPrice } = oldTxsParams;
|
|
384
|
+
const calculateAndConvertNewValue = (feeValue) => {
|
|
385
|
+
const calculateValue = String(feeValue * multiplierToUse);
|
|
386
|
+
const convertValueToHex = '0x' + parseInt(calculateValue, 10).toString(16);
|
|
387
|
+
return ethers_1.ethers.BigNumber.from(convertValueToHex);
|
|
388
|
+
};
|
|
389
|
+
const maxFeePerGasToNumber = maxFeePerGas?.toNumber();
|
|
390
|
+
const maxPriorityFeePerGasToNumber = maxPriorityFeePerGas?.toNumber();
|
|
391
|
+
const gasLimitToNumber = gasLimit?.toNumber();
|
|
392
|
+
const gasPriceToNumber = gasPrice?.toNumber();
|
|
393
|
+
const multiplierToUse = 1.2; //The same calculation we used in the edit fee modal, always using the 0.2 multiplier
|
|
394
|
+
if (!isLegacy) {
|
|
395
|
+
newGasValues.maxFeePerGas = calculateAndConvertNewValue(maxFeePerGasToNumber);
|
|
396
|
+
newGasValues.maxPriorityFeePerGas = calculateAndConvertNewValue(maxPriorityFeePerGasToNumber);
|
|
397
|
+
}
|
|
398
|
+
if (isLegacy) {
|
|
399
|
+
newGasValues.gasPrice = calculateAndConvertNewValue(gasPriceToNumber);
|
|
400
|
+
}
|
|
401
|
+
if (isForCancel) {
|
|
402
|
+
const DEFAULT_GAS_LIMIT_VALUE = '21000';
|
|
403
|
+
const convertToHex = '0x' + parseInt(DEFAULT_GAS_LIMIT_VALUE, 10).toString(16);
|
|
404
|
+
newGasValues.gasLimit = ethers_1.ethers.BigNumber.from(convertToHex);
|
|
405
|
+
}
|
|
406
|
+
if (!isForCancel) {
|
|
407
|
+
newGasValues.gasLimit = calculateAndConvertNewValue(gasLimitToNumber);
|
|
408
|
+
}
|
|
409
|
+
return newGasValues;
|
|
410
|
+
};
|
|
411
|
+
this.cancelSentTransaction = async (txHash, isLegacy) => {
|
|
412
|
+
const tx = (await this.web3Provider.getTransaction(txHash));
|
|
413
|
+
if (!tx) {
|
|
414
|
+
//If we don't find the TX or is already confirmed we send as error true to show this message
|
|
415
|
+
//in the alert at Pali
|
|
416
|
+
return {
|
|
417
|
+
isCanceled: false,
|
|
418
|
+
error: true,
|
|
419
|
+
};
|
|
420
|
+
}
|
|
421
|
+
const { decryptedPrivateKey } = this.getDecryptedPrivateKey();
|
|
422
|
+
const wallet = new ethers_1.ethers.Wallet(decryptedPrivateKey, this.web3Provider);
|
|
423
|
+
let changedTxToCancel;
|
|
424
|
+
const oldTxsGasValues = {
|
|
425
|
+
maxFeePerGas: tx.maxFeePerGas,
|
|
426
|
+
maxPriorityFeePerGas: tx.maxPriorityFeePerGas,
|
|
427
|
+
gasPrice: tx.gasPrice,
|
|
428
|
+
gasLimit: tx.gasLimit,
|
|
429
|
+
};
|
|
430
|
+
if (!isLegacy) {
|
|
431
|
+
const newGasValues = this.calculateNewGasValues(oldTxsGasValues, true, false);
|
|
432
|
+
//We have to send another TX using the same nonce but we can use the From and To for the same address and also
|
|
433
|
+
//the value as 0
|
|
434
|
+
changedTxToCancel = {
|
|
435
|
+
nonce: tx.nonce,
|
|
436
|
+
from: wallet.address,
|
|
437
|
+
to: wallet.address,
|
|
438
|
+
value: ethers_1.ethers.constants.Zero,
|
|
439
|
+
maxFeePerGas: newGasValues.maxFeePerGas,
|
|
440
|
+
maxPriorityFeePerGas: newGasValues.maxPriorityFeePerGas,
|
|
441
|
+
gasLimit: newGasValues.gasLimit,
|
|
442
|
+
};
|
|
443
|
+
}
|
|
444
|
+
else {
|
|
445
|
+
const newGasValues = this.calculateNewGasValues(oldTxsGasValues, true, true);
|
|
446
|
+
//We have to send another TX using the same nonce but we can use the From and To for the same address and also
|
|
447
|
+
//the value as 0
|
|
448
|
+
changedTxToCancel = {
|
|
449
|
+
nonce: tx.nonce,
|
|
450
|
+
from: wallet.address,
|
|
451
|
+
to: wallet.address,
|
|
452
|
+
value: ethers_1.ethers.constants.Zero,
|
|
453
|
+
gasLimit: newGasValues.gasLimit,
|
|
454
|
+
gasPrice: newGasValues.gasPrice,
|
|
455
|
+
};
|
|
456
|
+
}
|
|
457
|
+
const cancelTransaction = async () => {
|
|
458
|
+
try {
|
|
459
|
+
const transactionResponse = await wallet.sendTransaction(changedTxToCancel);
|
|
460
|
+
if (transactionResponse) {
|
|
461
|
+
return {
|
|
462
|
+
isCanceled: true,
|
|
463
|
+
transaction: transactionResponse,
|
|
464
|
+
};
|
|
465
|
+
}
|
|
466
|
+
else {
|
|
467
|
+
return {
|
|
468
|
+
isCanceled: false,
|
|
469
|
+
};
|
|
470
|
+
}
|
|
471
|
+
}
|
|
472
|
+
catch (error) {
|
|
473
|
+
//If we don't find the TX or is already confirmed we send as error true to show this message
|
|
474
|
+
//in the alert at Pali
|
|
475
|
+
return {
|
|
476
|
+
isCanceled: false,
|
|
477
|
+
error: true,
|
|
478
|
+
};
|
|
479
|
+
}
|
|
480
|
+
};
|
|
481
|
+
return await cancelTransaction();
|
|
482
|
+
};
|
|
483
|
+
//TODO: This function needs to be refactored
|
|
484
|
+
this.sendFormattedTransaction = async (params, isLegacy) => {
|
|
485
|
+
const { activeAccountType, activeAccountId, accounts, activeNetwork } = this.getState();
|
|
486
|
+
const activeAccount = accounts[activeAccountType][activeAccountId];
|
|
487
|
+
const sendEVMLedgerTransaction = async () => {
|
|
488
|
+
const transactionNonce = await this.getRecommendedNonce(activeAccount.address);
|
|
489
|
+
const formatParams = (0, omit_1.default)(params, 'from'); //From is not needed we're already passing in the HD derivation path so it can be inferred
|
|
490
|
+
const txFormattedForEthers = isLegacy
|
|
491
|
+
? {
|
|
492
|
+
...formatParams,
|
|
493
|
+
nonce: transactionNonce,
|
|
494
|
+
chainId: activeNetwork.chainId,
|
|
495
|
+
}
|
|
496
|
+
: {
|
|
497
|
+
...formatParams,
|
|
498
|
+
nonce: transactionNonce,
|
|
499
|
+
chainId: activeNetwork.chainId,
|
|
500
|
+
type: 2,
|
|
501
|
+
};
|
|
502
|
+
const rawTx = ethers_1.ethers.utils.serializeTransaction(txFormattedForEthers);
|
|
503
|
+
const signature = await this.ledgerSigner.evm.signEVMTransaction({
|
|
504
|
+
rawTx: rawTx.replace('0x', ''),
|
|
505
|
+
accountIndex: activeAccountId,
|
|
506
|
+
});
|
|
507
|
+
const formattedSignature = {
|
|
508
|
+
r: `0x${signature.r}`,
|
|
509
|
+
s: `0x${signature.s}`,
|
|
510
|
+
v: parseInt(signature.v, 16),
|
|
511
|
+
};
|
|
512
|
+
if (signature) {
|
|
513
|
+
try {
|
|
514
|
+
const signedTx = ethers_1.ethers.utils.serializeTransaction(txFormattedForEthers, formattedSignature);
|
|
515
|
+
const finalTx = await this.web3Provider.sendTransaction(signedTx);
|
|
516
|
+
return finalTx;
|
|
517
|
+
}
|
|
518
|
+
catch (error) {
|
|
519
|
+
throw error;
|
|
520
|
+
}
|
|
521
|
+
}
|
|
522
|
+
else {
|
|
523
|
+
throw new Error(`Transaction Signature Failed. Error: ${signature}`);
|
|
524
|
+
}
|
|
525
|
+
};
|
|
526
|
+
const sendEVMTrezorTransaction = async () => {
|
|
527
|
+
const transactionNonce = await this.getRecommendedNonce(activeAccount.address);
|
|
528
|
+
let txFormattedForTrezor = {};
|
|
529
|
+
const formatParams = (0, omit_1.default)(params, 'from'); //From is not needed we're already passing in the HD derivation path so it can be inferred
|
|
530
|
+
switch (isLegacy) {
|
|
531
|
+
case true:
|
|
532
|
+
txFormattedForTrezor = {
|
|
533
|
+
...formatParams,
|
|
534
|
+
gasLimit: typeof formatParams.gasLimit === 'string'
|
|
535
|
+
? formatParams.gasLimit
|
|
536
|
+
: // @ts-ignore
|
|
537
|
+
`${params.gasLimit.hex}`,
|
|
538
|
+
value: typeof formatParams.value === 'string' ||
|
|
539
|
+
typeof formatParams.value === 'number'
|
|
540
|
+
? `${formatParams.value}`
|
|
541
|
+
: // @ts-ignore
|
|
542
|
+
`${params.value.hex}`,
|
|
543
|
+
nonce: this.toBigNumber(transactionNonce)._hex,
|
|
544
|
+
chainId: activeNetwork.chainId,
|
|
545
|
+
};
|
|
546
|
+
break;
|
|
547
|
+
case false:
|
|
548
|
+
txFormattedForTrezor = {
|
|
549
|
+
...formatParams,
|
|
550
|
+
gasLimit: typeof formatParams.gasLimit === 'string'
|
|
551
|
+
? formatParams.gasLimit
|
|
552
|
+
: // @ts-ignore
|
|
553
|
+
`${params.gasLimit.hex}`,
|
|
554
|
+
maxFeePerGas: typeof formatParams.maxFeePerGas === 'string'
|
|
555
|
+
? formatParams.maxFeePerGas
|
|
556
|
+
: // @ts-ignore
|
|
557
|
+
`${params.maxFeePerGas.hex}`,
|
|
558
|
+
maxPriorityFeePerGas: typeof formatParams.maxPriorityFeePerGas === 'string'
|
|
559
|
+
? formatParams.maxPriorityFeePerGas
|
|
560
|
+
: // @ts-ignore
|
|
561
|
+
`${params.maxPriorityFeePerGas.hex}`,
|
|
562
|
+
value: typeof formatParams.value === 'string' ||
|
|
563
|
+
typeof formatParams.value === 'number'
|
|
564
|
+
? `${formatParams.value}`
|
|
565
|
+
: // @ts-ignore
|
|
566
|
+
`${params.value.hex}`,
|
|
567
|
+
nonce: this.toBigNumber(transactionNonce)._hex,
|
|
568
|
+
chainId: activeNetwork.chainId,
|
|
569
|
+
};
|
|
570
|
+
break;
|
|
571
|
+
default:
|
|
572
|
+
txFormattedForTrezor = {
|
|
573
|
+
...formatParams,
|
|
574
|
+
gasLimit: typeof formatParams.gasLimit === 'string'
|
|
575
|
+
? formatParams.gasLimit
|
|
576
|
+
: // @ts-ignore
|
|
577
|
+
`${params.gasLimit.hex}`,
|
|
578
|
+
maxFeePerGas: typeof formatParams.maxFeePerGas === 'string'
|
|
579
|
+
? formatParams.maxFeePerGas
|
|
580
|
+
: // @ts-ignore
|
|
581
|
+
`${params.maxFeePerGas.hex}`,
|
|
582
|
+
maxPriorityFeePerGas: typeof formatParams.maxPriorityFeePerGas === 'string'
|
|
583
|
+
? formatParams.maxPriorityFeePerGas
|
|
584
|
+
: // @ts-ignore
|
|
585
|
+
`${params.maxPriorityFeePerGas.hex}`,
|
|
586
|
+
value: typeof formatParams.value === 'string' ||
|
|
587
|
+
typeof formatParams.value === 'number'
|
|
588
|
+
? `${formatParams.value}`
|
|
589
|
+
: // @ts-ignore
|
|
590
|
+
`${params.value.hex}`,
|
|
591
|
+
nonce: this.toBigNumber(transactionNonce)._hex,
|
|
592
|
+
chainId: activeNetwork.chainId,
|
|
593
|
+
};
|
|
594
|
+
break;
|
|
595
|
+
}
|
|
596
|
+
const signature = await this.trezorSigner.signEthTransaction({
|
|
597
|
+
index: `${activeAccountId}`,
|
|
598
|
+
tx: txFormattedForTrezor,
|
|
599
|
+
coin: activeNetwork.currency,
|
|
600
|
+
slip44: activeNetwork.slip44,
|
|
601
|
+
});
|
|
602
|
+
if (signature.success) {
|
|
603
|
+
try {
|
|
604
|
+
const txFormattedForEthers = isLegacy
|
|
605
|
+
? {
|
|
606
|
+
...formatParams,
|
|
607
|
+
nonce: transactionNonce,
|
|
608
|
+
chainId: activeNetwork.chainId,
|
|
609
|
+
}
|
|
610
|
+
: {
|
|
611
|
+
...formatParams,
|
|
612
|
+
nonce: transactionNonce,
|
|
613
|
+
chainId: activeNetwork.chainId,
|
|
614
|
+
type: 2,
|
|
615
|
+
};
|
|
616
|
+
signature.payload.v = parseInt(signature.payload.v, 16); //v parameter must be a number by ethers standards
|
|
617
|
+
const signedTx = ethers_1.ethers.utils.serializeTransaction(txFormattedForEthers, signature.payload);
|
|
618
|
+
const finalTx = await this.web3Provider.sendTransaction(signedTx);
|
|
619
|
+
return finalTx;
|
|
620
|
+
}
|
|
621
|
+
catch (error) {
|
|
622
|
+
throw error;
|
|
623
|
+
}
|
|
624
|
+
}
|
|
625
|
+
else {
|
|
626
|
+
throw new Error(`Transaction Signature Failed. Error: ${signature}`);
|
|
627
|
+
}
|
|
628
|
+
};
|
|
629
|
+
const sendEVMTransaction = async () => {
|
|
630
|
+
const { address, decryptedPrivateKey } = this.getDecryptedPrivateKey();
|
|
631
|
+
// Validate that we have the correct private key for the active account to prevent race conditions
|
|
632
|
+
// This is critical for transaction security during account switches
|
|
633
|
+
if (address.toLowerCase() !== activeAccount.address.toLowerCase()) {
|
|
634
|
+
throw new Error(`Account state mismatch detected during transaction. Expected ${activeAccount.address} but got ${address}. Please wait for account switching to complete and try again.`);
|
|
635
|
+
}
|
|
636
|
+
const tx = params;
|
|
637
|
+
const wallet = new ethers_1.ethers.Wallet(decryptedPrivateKey, this.web3Provider);
|
|
638
|
+
try {
|
|
639
|
+
const transaction = await wallet.sendTransaction(tx);
|
|
640
|
+
const response = await this.web3Provider.getTransaction(transaction.hash);
|
|
641
|
+
//TODO: more precisely on this lines
|
|
642
|
+
if (!response) {
|
|
643
|
+
return await this.getTransactionTimestamp(transaction);
|
|
644
|
+
}
|
|
645
|
+
else {
|
|
646
|
+
return await this.getTransactionTimestamp(response);
|
|
647
|
+
}
|
|
648
|
+
}
|
|
649
|
+
catch (error) {
|
|
650
|
+
throw error;
|
|
651
|
+
}
|
|
652
|
+
};
|
|
653
|
+
switch (activeAccountType) {
|
|
654
|
+
case types_1.KeyringAccountType.Trezor:
|
|
655
|
+
return await sendEVMTrezorTransaction();
|
|
656
|
+
case types_1.KeyringAccountType.Ledger:
|
|
657
|
+
return await sendEVMLedgerTransaction();
|
|
658
|
+
default:
|
|
659
|
+
return await sendEVMTransaction();
|
|
660
|
+
}
|
|
661
|
+
};
|
|
662
|
+
this.sendTransactionWithEditedFee = async (txHash, isLegacy) => {
|
|
663
|
+
const tx = (await this.web3Provider.getTransaction(txHash));
|
|
664
|
+
if (!tx) {
|
|
665
|
+
return {
|
|
666
|
+
isSpeedUp: false,
|
|
667
|
+
error: true,
|
|
668
|
+
};
|
|
669
|
+
}
|
|
670
|
+
const { decryptedPrivateKey, address } = this.getDecryptedPrivateKey();
|
|
671
|
+
const wallet = new ethers_1.ethers.Wallet(decryptedPrivateKey, this.web3Provider);
|
|
672
|
+
// Check if this might be a max send transaction by comparing total cost to balance
|
|
673
|
+
const currentBalance = await this.web3Provider.getBalance(address);
|
|
674
|
+
// Ensure all transaction values are resolved from promises
|
|
675
|
+
const gasLimit = await Promise.resolve(tx.gasLimit);
|
|
676
|
+
const gasPrice = await Promise.resolve(tx.gasPrice || 0);
|
|
677
|
+
const maxFeePerGas = await Promise.resolve(tx.maxFeePerGas || 0);
|
|
678
|
+
const maxPriorityFeePerGas = await Promise.resolve(tx.maxPriorityFeePerGas || 0);
|
|
679
|
+
const txValue = await Promise.resolve(tx.value);
|
|
680
|
+
const txData = await Promise.resolve(tx.data || '0x');
|
|
681
|
+
// Check if this is a contract call (has data)
|
|
682
|
+
const isContractCall = txData && txData !== '0x' && txData.length > 2;
|
|
683
|
+
const originalGasCost = isLegacy
|
|
684
|
+
? gasLimit.mul(gasPrice || 0)
|
|
685
|
+
: gasLimit.mul(maxFeePerGas || 0);
|
|
686
|
+
const originalTotalCost = txValue.add(originalGasCost);
|
|
687
|
+
// If original transaction used >95% of balance, it's likely a max send
|
|
688
|
+
const balanceThreshold = currentBalance.mul(95).div(100);
|
|
689
|
+
const isLikelyMaxSend = originalTotalCost.gt(balanceThreshold);
|
|
690
|
+
let txWithEditedFee;
|
|
691
|
+
const oldTxsGasValues = {
|
|
692
|
+
maxFeePerGas: maxFeePerGas,
|
|
693
|
+
maxPriorityFeePerGas: maxPriorityFeePerGas,
|
|
694
|
+
gasPrice: gasPrice,
|
|
695
|
+
gasLimit: gasLimit,
|
|
696
|
+
};
|
|
697
|
+
if (!isLegacy) {
|
|
698
|
+
const newGasValues = this.calculateNewGasValues(oldTxsGasValues, false, false);
|
|
699
|
+
let adjustedValue = txValue;
|
|
700
|
+
// For likely max sends, check if we need to adjust value
|
|
701
|
+
if (isLikelyMaxSend &&
|
|
702
|
+
newGasValues.gasLimit &&
|
|
703
|
+
newGasValues.maxFeePerGas) {
|
|
704
|
+
const newGasCost = newGasValues.gasLimit.mul(newGasValues.maxFeePerGas);
|
|
705
|
+
const newTotalCost = txValue.add(newGasCost);
|
|
706
|
+
if (newTotalCost.gt(currentBalance)) {
|
|
707
|
+
// If this is a contract call, we cannot adjust the value
|
|
708
|
+
if (isContractCall) {
|
|
709
|
+
console.error('[SpeedUp] Cannot adjust value for contract call - rejecting speedup');
|
|
710
|
+
return {
|
|
711
|
+
isSpeedUp: false,
|
|
712
|
+
error: true,
|
|
713
|
+
};
|
|
714
|
+
}
|
|
715
|
+
// For non-contract calls, reduce value to fit within balance
|
|
716
|
+
adjustedValue = currentBalance.sub(newGasCost);
|
|
717
|
+
// Ensure we don't go below a minimum threshold (0.0001 ETH)
|
|
718
|
+
const minValue = ethers_1.ethers.utils.parseEther('0.0001');
|
|
719
|
+
if (adjustedValue.lt(minValue)) {
|
|
720
|
+
console.warn('[SpeedUp] Adjusted value too low, keeping original');
|
|
721
|
+
adjustedValue = txValue;
|
|
722
|
+
}
|
|
723
|
+
}
|
|
724
|
+
}
|
|
725
|
+
txWithEditedFee = {
|
|
726
|
+
from: tx.from,
|
|
727
|
+
to: tx.to,
|
|
728
|
+
nonce: tx.nonce,
|
|
729
|
+
value: adjustedValue,
|
|
730
|
+
data: txData,
|
|
731
|
+
maxFeePerGas: newGasValues.maxFeePerGas,
|
|
732
|
+
maxPriorityFeePerGas: newGasValues.maxPriorityFeePerGas,
|
|
733
|
+
gasLimit: newGasValues.gasLimit,
|
|
734
|
+
};
|
|
735
|
+
}
|
|
736
|
+
else {
|
|
737
|
+
const newGasValues = this.calculateNewGasValues(oldTxsGasValues, false, true);
|
|
738
|
+
let adjustedValue = txValue;
|
|
739
|
+
// For likely max sends, check if we need to adjust value
|
|
740
|
+
if (isLikelyMaxSend && newGasValues.gasLimit && newGasValues.gasPrice) {
|
|
741
|
+
const newGasCost = newGasValues.gasLimit.mul(newGasValues.gasPrice);
|
|
742
|
+
const newTotalCost = txValue.add(newGasCost);
|
|
743
|
+
if (newTotalCost.gt(currentBalance)) {
|
|
744
|
+
// If this is a contract call, we cannot adjust the value
|
|
745
|
+
if (isContractCall) {
|
|
746
|
+
console.error('[SpeedUp] Cannot adjust value for contract call - rejecting speedup');
|
|
747
|
+
return {
|
|
748
|
+
isSpeedUp: false,
|
|
749
|
+
error: true,
|
|
750
|
+
};
|
|
751
|
+
}
|
|
752
|
+
// For non-contract calls, reduce value to fit within balance
|
|
753
|
+
adjustedValue = currentBalance.sub(newGasCost);
|
|
754
|
+
// Ensure we don't go below a minimum threshold (0.0001 ETH)
|
|
755
|
+
const minValue = ethers_1.ethers.utils.parseEther('0.0001');
|
|
756
|
+
if (adjustedValue.lt(minValue)) {
|
|
757
|
+
console.warn('[SpeedUp] Adjusted value too low, keeping original');
|
|
758
|
+
adjustedValue = txValue;
|
|
759
|
+
}
|
|
760
|
+
}
|
|
761
|
+
}
|
|
762
|
+
txWithEditedFee = {
|
|
763
|
+
from: tx.from,
|
|
764
|
+
to: tx.to,
|
|
765
|
+
nonce: tx.nonce,
|
|
766
|
+
value: adjustedValue,
|
|
767
|
+
data: txData,
|
|
768
|
+
gasLimit: newGasValues.gasLimit,
|
|
769
|
+
gasPrice: newGasValues.gasPrice,
|
|
770
|
+
};
|
|
771
|
+
}
|
|
772
|
+
const sendEditedTransaction = async () => {
|
|
773
|
+
try {
|
|
774
|
+
const transactionResponse = await wallet.sendTransaction(txWithEditedFee);
|
|
775
|
+
if (transactionResponse) {
|
|
776
|
+
return {
|
|
777
|
+
isSpeedUp: true,
|
|
778
|
+
transaction: transactionResponse,
|
|
779
|
+
};
|
|
780
|
+
}
|
|
781
|
+
else {
|
|
782
|
+
return {
|
|
783
|
+
isSpeedUp: false,
|
|
784
|
+
};
|
|
785
|
+
}
|
|
786
|
+
}
|
|
787
|
+
catch (error) {
|
|
788
|
+
console.error('[SpeedUp] Failed to send replacement transaction:', error);
|
|
789
|
+
//If we don't find the TX or is already confirmed we send as error true to show this message
|
|
790
|
+
//in the alert at Pali
|
|
791
|
+
return {
|
|
792
|
+
isSpeedUp: false,
|
|
793
|
+
error: true,
|
|
794
|
+
};
|
|
795
|
+
}
|
|
796
|
+
};
|
|
797
|
+
return await sendEditedTransaction();
|
|
798
|
+
};
|
|
799
|
+
// TODO: refactor this function
|
|
800
|
+
this.sendTransaction = async ({ sender, receivingAddress, amount, gasLimit, token, }) => {
|
|
801
|
+
const tokenDecimals = token && token.decimals ? token.decimals : 18;
|
|
802
|
+
const decimals = this.toBigNumber(tokenDecimals);
|
|
803
|
+
const parsedAmount = ethers_1.ethers.utils.parseEther(String(amount));
|
|
804
|
+
const { decryptedPrivateKey } = this.getDecryptedPrivateKey();
|
|
805
|
+
const wallet = new ethers_1.ethers.Wallet(decryptedPrivateKey, this.web3Provider);
|
|
806
|
+
const value = token && token.contract_address
|
|
807
|
+
? parsedAmount.mul(this.toBigNumber('10').pow(decimals))
|
|
808
|
+
: parsedAmount;
|
|
809
|
+
const data = token && token.contract_address
|
|
810
|
+
? this.getData({
|
|
811
|
+
contractAddress: token.contract_address,
|
|
812
|
+
receivingAddress,
|
|
813
|
+
value,
|
|
814
|
+
})
|
|
815
|
+
: null;
|
|
816
|
+
// gas price, gas limit e maxPriorityFeePerGas (tip)
|
|
817
|
+
const { maxFeePerGas, maxPriorityFeePerGas } = await this.getFeeDataWithDynamicMaxPriorityFeePerGas();
|
|
818
|
+
const tx = {
|
|
819
|
+
to: receivingAddress,
|
|
820
|
+
value,
|
|
821
|
+
maxPriorityFeePerGas,
|
|
822
|
+
maxFeePerGas,
|
|
823
|
+
nonce: await this.web3Provider.getTransactionCount(sender, 'latest'),
|
|
824
|
+
type: 2,
|
|
825
|
+
chainId: this.web3Provider.network.chainId,
|
|
826
|
+
gasLimit: this.toBigNumber(0) || gasLimit,
|
|
827
|
+
data,
|
|
828
|
+
};
|
|
829
|
+
tx.gasLimit = await this.web3Provider.estimateGas(tx);
|
|
830
|
+
try {
|
|
831
|
+
const transaction = await wallet.sendTransaction(tx);
|
|
832
|
+
const response = await this.web3Provider.getTransaction(transaction.hash);
|
|
833
|
+
if (!response) {
|
|
834
|
+
return await this.getTransactionTimestamp(transaction);
|
|
835
|
+
}
|
|
836
|
+
else {
|
|
837
|
+
return await this.getTransactionTimestamp(response);
|
|
838
|
+
}
|
|
839
|
+
}
|
|
840
|
+
catch (error) {
|
|
841
|
+
throw error;
|
|
842
|
+
}
|
|
843
|
+
};
|
|
844
|
+
this.sendSignedErc20Transaction = async ({ receiver, tokenAddress, tokenAmount, isLegacy = false, maxPriorityFeePerGas, maxFeePerGas, gasPrice, decimals, gasLimit, saveTrezorTx, }) => {
|
|
845
|
+
const { decryptedPrivateKey } = this.getDecryptedPrivateKey();
|
|
846
|
+
const { accounts, activeAccountType, activeAccountId, activeNetwork } = this.getState();
|
|
847
|
+
const { address: activeAccountAddress } = accounts[activeAccountType][activeAccountId];
|
|
848
|
+
const sendERC20Token = async () => {
|
|
849
|
+
const currentWallet = new ethers_1.ethers.Wallet(decryptedPrivateKey);
|
|
850
|
+
const walletSigned = currentWallet.connect(this.web3Provider);
|
|
851
|
+
try {
|
|
852
|
+
const _contract = new ethers_1.ethers.Contract(tokenAddress, (0, sysweb3_utils_1.getErc20Abi)(), walletSigned);
|
|
853
|
+
const calculatedTokenAmount = ethers_1.ethers.BigNumber.from(decimals
|
|
854
|
+
? ethers_1.ethers.utils.parseUnits(tokenAmount, this.toBigNumber(decimals))
|
|
855
|
+
: ethers_1.ethers.utils.parseEther(tokenAmount));
|
|
856
|
+
let transferMethod;
|
|
857
|
+
if (isLegacy) {
|
|
858
|
+
const overrides = {
|
|
859
|
+
nonce: await this.web3Provider.getTransactionCount(walletSigned.address, 'pending'),
|
|
860
|
+
gasPrice,
|
|
861
|
+
...(gasLimit && { gasLimit }),
|
|
862
|
+
};
|
|
863
|
+
transferMethod = await _contract.transfer(receiver, calculatedTokenAmount, overrides);
|
|
864
|
+
}
|
|
865
|
+
else {
|
|
866
|
+
const overrides = {
|
|
867
|
+
nonce: await this.web3Provider.getTransactionCount(walletSigned.address, 'pending'),
|
|
868
|
+
maxPriorityFeePerGas,
|
|
869
|
+
maxFeePerGas,
|
|
870
|
+
...(gasLimit && { gasLimit }),
|
|
871
|
+
};
|
|
872
|
+
transferMethod = await _contract.transfer(receiver, calculatedTokenAmount, overrides);
|
|
873
|
+
}
|
|
874
|
+
return transferMethod;
|
|
875
|
+
}
|
|
876
|
+
catch (error) {
|
|
877
|
+
throw error;
|
|
878
|
+
}
|
|
879
|
+
};
|
|
880
|
+
const sendERC20TokenOnLedger = async () => {
|
|
881
|
+
const signer = this.web3Provider.getSigner(activeAccountAddress);
|
|
882
|
+
const transactionNonce = await this.getRecommendedNonce(activeAccountAddress);
|
|
883
|
+
try {
|
|
884
|
+
const _contract = new ethers_1.ethers.Contract(tokenAddress, (0, sysweb3_utils_1.getErc20Abi)(), signer);
|
|
885
|
+
const calculatedTokenAmount = ethers_1.ethers.BigNumber.from(ethers_1.ethers.utils.parseEther(tokenAmount));
|
|
886
|
+
const txData = _contract.interface.encodeFunctionData('transfer', [
|
|
887
|
+
receiver,
|
|
888
|
+
calculatedTokenAmount,
|
|
889
|
+
]);
|
|
890
|
+
// Use fallback gas limit if not provided (for auto-estimation)
|
|
891
|
+
const effectiveGasLimit = gasLimit || this.toBigNumber('100000'); // ERC20 fallback
|
|
892
|
+
let txFormattedForEthers;
|
|
893
|
+
if (isLegacy) {
|
|
894
|
+
txFormattedForEthers = {
|
|
895
|
+
to: tokenAddress,
|
|
896
|
+
value: '0x0',
|
|
897
|
+
gasLimit: effectiveGasLimit,
|
|
898
|
+
gasPrice,
|
|
899
|
+
data: txData,
|
|
900
|
+
nonce: transactionNonce,
|
|
901
|
+
chainId: activeNetwork.chainId,
|
|
902
|
+
type: 0,
|
|
903
|
+
};
|
|
904
|
+
}
|
|
905
|
+
else {
|
|
906
|
+
txFormattedForEthers = {
|
|
907
|
+
to: tokenAddress,
|
|
908
|
+
value: '0x0',
|
|
909
|
+
gasLimit: effectiveGasLimit,
|
|
910
|
+
maxFeePerGas,
|
|
911
|
+
maxPriorityFeePerGas,
|
|
912
|
+
data: txData,
|
|
913
|
+
nonce: transactionNonce,
|
|
914
|
+
chainId: activeNetwork.chainId,
|
|
915
|
+
type: 2,
|
|
916
|
+
};
|
|
917
|
+
}
|
|
918
|
+
const rawTx = ethers_1.ethers.utils.serializeTransaction(txFormattedForEthers);
|
|
919
|
+
const signature = await this.ledgerSigner.evm.signEVMTransaction({
|
|
920
|
+
rawTx: rawTx.replace('0x', ''),
|
|
921
|
+
accountIndex: activeAccountId,
|
|
922
|
+
});
|
|
923
|
+
const formattedSignature = {
|
|
924
|
+
r: `0x${signature.r}`,
|
|
925
|
+
s: `0x${signature.s}`,
|
|
926
|
+
v: parseInt(signature.v, 16),
|
|
927
|
+
};
|
|
928
|
+
if (signature) {
|
|
929
|
+
try {
|
|
930
|
+
const signedTx = ethers_1.ethers.utils.serializeTransaction(txFormattedForEthers, formattedSignature);
|
|
931
|
+
const finalTx = await this.web3Provider.sendTransaction(signedTx);
|
|
932
|
+
saveTrezorTx && saveTrezorTx(finalTx);
|
|
933
|
+
return finalTx;
|
|
934
|
+
}
|
|
935
|
+
catch (error) {
|
|
936
|
+
throw error;
|
|
937
|
+
}
|
|
938
|
+
}
|
|
939
|
+
else {
|
|
940
|
+
throw new Error(`Transaction Signature Failed. Error: ${signature}`);
|
|
941
|
+
}
|
|
942
|
+
}
|
|
943
|
+
catch (error) {
|
|
944
|
+
throw error;
|
|
945
|
+
}
|
|
946
|
+
};
|
|
947
|
+
const sendERC20TokenOnTrezor = async () => {
|
|
948
|
+
const signer = this.web3Provider.getSigner(activeAccountAddress);
|
|
949
|
+
const transactionNonce = await this.getRecommendedNonce(activeAccountAddress);
|
|
950
|
+
try {
|
|
951
|
+
const _contract = new ethers_1.ethers.Contract(tokenAddress, (0, sysweb3_utils_1.getErc20Abi)(), signer);
|
|
952
|
+
const calculatedTokenAmount = ethers_1.ethers.BigNumber.from(ethers_1.ethers.utils.parseEther(tokenAmount));
|
|
953
|
+
const txData = _contract.interface.encodeFunctionData('transfer', [
|
|
954
|
+
receiver,
|
|
955
|
+
calculatedTokenAmount,
|
|
956
|
+
]);
|
|
957
|
+
// Use fallback gas limit if not provided (for auto-estimation)
|
|
958
|
+
const effectiveGasLimit = gasLimit || this.toBigNumber('100000'); // ERC20 fallback
|
|
959
|
+
let txToBeSignedByTrezor;
|
|
960
|
+
if (isLegacy) {
|
|
961
|
+
txToBeSignedByTrezor = {
|
|
962
|
+
to: tokenAddress,
|
|
963
|
+
value: '0x0',
|
|
964
|
+
// @ts-ignore
|
|
965
|
+
gasLimit: `${effectiveGasLimit.hex}`,
|
|
966
|
+
// @ts-ignore
|
|
967
|
+
gasPrice: `${gasPrice}`,
|
|
968
|
+
nonce: this.toBigNumber(transactionNonce)._hex,
|
|
969
|
+
chainId: activeNetwork.chainId,
|
|
970
|
+
data: txData,
|
|
971
|
+
};
|
|
972
|
+
}
|
|
973
|
+
else {
|
|
974
|
+
txToBeSignedByTrezor = {
|
|
975
|
+
to: tokenAddress,
|
|
976
|
+
value: '0x0',
|
|
977
|
+
// @ts-ignore
|
|
978
|
+
gasLimit: `${effectiveGasLimit.hex}`,
|
|
979
|
+
// @ts-ignore
|
|
980
|
+
maxFeePerGas: `${maxFeePerGas.hex}`,
|
|
981
|
+
// @ts-ignore
|
|
982
|
+
maxPriorityFeePerGas: `${maxPriorityFeePerGas.hex}`,
|
|
983
|
+
nonce: this.toBigNumber(transactionNonce)._hex,
|
|
984
|
+
chainId: activeNetwork.chainId,
|
|
985
|
+
data: txData,
|
|
986
|
+
};
|
|
987
|
+
}
|
|
988
|
+
const signature = await this.trezorSigner.signEthTransaction({
|
|
989
|
+
index: `${activeAccountId}`,
|
|
990
|
+
tx: txToBeSignedByTrezor,
|
|
991
|
+
coin: activeNetwork.currency,
|
|
992
|
+
slip44: activeNetwork.slip44,
|
|
993
|
+
});
|
|
994
|
+
if (signature.success) {
|
|
995
|
+
try {
|
|
996
|
+
let txFormattedForEthers;
|
|
997
|
+
if (isLegacy) {
|
|
998
|
+
txFormattedForEthers = {
|
|
999
|
+
to: tokenAddress,
|
|
1000
|
+
value: '0x0',
|
|
1001
|
+
gasLimit: effectiveGasLimit,
|
|
1002
|
+
gasPrice,
|
|
1003
|
+
data: txData,
|
|
1004
|
+
nonce: transactionNonce,
|
|
1005
|
+
chainId: activeNetwork.chainId,
|
|
1006
|
+
type: 0,
|
|
1007
|
+
};
|
|
1008
|
+
}
|
|
1009
|
+
else {
|
|
1010
|
+
txFormattedForEthers = {
|
|
1011
|
+
to: tokenAddress,
|
|
1012
|
+
value: '0x0',
|
|
1013
|
+
gasLimit: effectiveGasLimit,
|
|
1014
|
+
maxFeePerGas,
|
|
1015
|
+
maxPriorityFeePerGas,
|
|
1016
|
+
data: txData,
|
|
1017
|
+
nonce: transactionNonce,
|
|
1018
|
+
chainId: activeNetwork.chainId,
|
|
1019
|
+
type: 2,
|
|
1020
|
+
};
|
|
1021
|
+
}
|
|
1022
|
+
signature.payload.v = parseInt(signature.payload.v, 16); //v parameter must be a number by ethers standards
|
|
1023
|
+
const signedTx = ethers_1.ethers.utils.serializeTransaction(txFormattedForEthers, signature.payload);
|
|
1024
|
+
const finalTx = await this.web3Provider.sendTransaction(signedTx);
|
|
1025
|
+
saveTrezorTx && saveTrezorTx(finalTx);
|
|
1026
|
+
return finalTx;
|
|
1027
|
+
}
|
|
1028
|
+
catch (error) {
|
|
1029
|
+
throw error;
|
|
1030
|
+
}
|
|
1031
|
+
}
|
|
1032
|
+
else {
|
|
1033
|
+
throw new Error(`Transaction Signature Failed. Error: ${signature}`);
|
|
1034
|
+
}
|
|
1035
|
+
}
|
|
1036
|
+
catch (error) {
|
|
1037
|
+
throw error;
|
|
1038
|
+
}
|
|
1039
|
+
};
|
|
1040
|
+
switch (activeAccountType) {
|
|
1041
|
+
case types_1.KeyringAccountType.Trezor:
|
|
1042
|
+
return await sendERC20TokenOnTrezor();
|
|
1043
|
+
case types_1.KeyringAccountType.Ledger:
|
|
1044
|
+
return await sendERC20TokenOnLedger();
|
|
1045
|
+
default:
|
|
1046
|
+
return await sendERC20Token();
|
|
1047
|
+
}
|
|
1048
|
+
};
|
|
1049
|
+
this.sendSignedErc721Transaction = async ({ receiver, tokenAddress, tokenId, isLegacy, maxPriorityFeePerGas, maxFeePerGas, gasPrice, gasLimit, }) => {
|
|
1050
|
+
const { decryptedPrivateKey } = this.getDecryptedPrivateKey();
|
|
1051
|
+
const { accounts, activeAccountType, activeAccountId, activeNetwork } = this.getState();
|
|
1052
|
+
const { address: activeAccountAddress } = accounts[activeAccountType][activeAccountId];
|
|
1053
|
+
const sendERC721Token = async () => {
|
|
1054
|
+
const currentWallet = new ethers_1.ethers.Wallet(decryptedPrivateKey);
|
|
1055
|
+
const walletSigned = currentWallet.connect(this.web3Provider);
|
|
1056
|
+
let transferMethod;
|
|
1057
|
+
try {
|
|
1058
|
+
const _contract = new ethers_1.ethers.Contract(tokenAddress, (0, sysweb3_utils_1.getErc21Abi)(), walletSigned);
|
|
1059
|
+
if (isLegacy) {
|
|
1060
|
+
const overrides = {
|
|
1061
|
+
nonce: await this.web3Provider.getTransactionCount(walletSigned.address, 'pending'),
|
|
1062
|
+
gasPrice,
|
|
1063
|
+
...(gasLimit && { gasLimit }),
|
|
1064
|
+
};
|
|
1065
|
+
transferMethod = await _contract.transferFrom(walletSigned.address, receiver, tokenId, overrides);
|
|
1066
|
+
}
|
|
1067
|
+
else {
|
|
1068
|
+
const overrides = {
|
|
1069
|
+
nonce: await this.web3Provider.getTransactionCount(walletSigned.address, 'pending'),
|
|
1070
|
+
};
|
|
1071
|
+
transferMethod = await _contract.transferFrom(walletSigned.address, receiver, tokenId, overrides);
|
|
1072
|
+
}
|
|
1073
|
+
return transferMethod;
|
|
1074
|
+
}
|
|
1075
|
+
catch (error) {
|
|
1076
|
+
throw error;
|
|
1077
|
+
}
|
|
1078
|
+
};
|
|
1079
|
+
const sendERC721TokenOnLedger = async () => {
|
|
1080
|
+
const signer = this.web3Provider.getSigner(activeAccountAddress);
|
|
1081
|
+
const transactionNonce = await this.getRecommendedNonce(activeAccountAddress);
|
|
1082
|
+
try {
|
|
1083
|
+
const _contract = new ethers_1.ethers.Contract(tokenAddress, (0, sysweb3_utils_1.getErc21Abi)(), signer);
|
|
1084
|
+
const txData = _contract.interface.encodeFunctionData('transferFrom', [
|
|
1085
|
+
activeAccountAddress,
|
|
1086
|
+
receiver,
|
|
1087
|
+
tokenId,
|
|
1088
|
+
]);
|
|
1089
|
+
// Use fallback gas limit if not provided (for auto-estimation)
|
|
1090
|
+
const effectiveGasLimit = gasLimit || this.toBigNumber('150000'); // ERC721 fallback
|
|
1091
|
+
let txFormattedForEthers;
|
|
1092
|
+
if (isLegacy) {
|
|
1093
|
+
txFormattedForEthers = {
|
|
1094
|
+
to: tokenAddress,
|
|
1095
|
+
value: '0x0',
|
|
1096
|
+
gasLimit: effectiveGasLimit,
|
|
1097
|
+
gasPrice,
|
|
1098
|
+
data: txData,
|
|
1099
|
+
nonce: transactionNonce,
|
|
1100
|
+
chainId: activeNetwork.chainId,
|
|
1101
|
+
type: 0,
|
|
1102
|
+
};
|
|
1103
|
+
}
|
|
1104
|
+
else {
|
|
1105
|
+
txFormattedForEthers = {
|
|
1106
|
+
to: tokenAddress,
|
|
1107
|
+
value: '0x0',
|
|
1108
|
+
gasLimit: effectiveGasLimit,
|
|
1109
|
+
maxFeePerGas,
|
|
1110
|
+
maxPriorityFeePerGas,
|
|
1111
|
+
data: txData,
|
|
1112
|
+
nonce: transactionNonce,
|
|
1113
|
+
chainId: activeNetwork.chainId,
|
|
1114
|
+
type: 2,
|
|
1115
|
+
};
|
|
1116
|
+
}
|
|
1117
|
+
const rawTx = ethers_1.ethers.utils.serializeTransaction(txFormattedForEthers);
|
|
1118
|
+
const signature = await this.ledgerSigner.evm.signEVMTransaction({
|
|
1119
|
+
rawTx: rawTx.replace('0x', ''),
|
|
1120
|
+
accountIndex: activeAccountId,
|
|
1121
|
+
});
|
|
1122
|
+
const formattedSignature = {
|
|
1123
|
+
r: `0x${signature.r}`,
|
|
1124
|
+
s: `0x${signature.s}`,
|
|
1125
|
+
v: parseInt(signature.v, 16),
|
|
1126
|
+
};
|
|
1127
|
+
if (signature) {
|
|
1128
|
+
try {
|
|
1129
|
+
const signedTx = ethers_1.ethers.utils.serializeTransaction(txFormattedForEthers, formattedSignature);
|
|
1130
|
+
const finalTx = await this.web3Provider.sendTransaction(signedTx);
|
|
1131
|
+
return finalTx;
|
|
1132
|
+
}
|
|
1133
|
+
catch (error) {
|
|
1134
|
+
throw error;
|
|
1135
|
+
}
|
|
1136
|
+
}
|
|
1137
|
+
else {
|
|
1138
|
+
throw new Error(`Transaction Signature Failed. Error: ${signature}`);
|
|
1139
|
+
}
|
|
1140
|
+
}
|
|
1141
|
+
catch (error) {
|
|
1142
|
+
throw error;
|
|
1143
|
+
}
|
|
1144
|
+
};
|
|
1145
|
+
const sendERC721TokenOnTrezor = async () => {
|
|
1146
|
+
const signer = this.web3Provider.getSigner(activeAccountAddress);
|
|
1147
|
+
const transactionNonce = await this.getRecommendedNonce(activeAccountAddress);
|
|
1148
|
+
try {
|
|
1149
|
+
const _contract = new ethers_1.ethers.Contract(tokenAddress, (0, sysweb3_utils_1.getErc21Abi)(), signer);
|
|
1150
|
+
const txData = _contract.interface.encodeFunctionData('transferFrom', [
|
|
1151
|
+
activeAccountAddress,
|
|
1152
|
+
receiver,
|
|
1153
|
+
tokenId,
|
|
1154
|
+
]);
|
|
1155
|
+
// Use fallback gas limit if not provided (for auto-estimation)
|
|
1156
|
+
const effectiveGasLimit = gasLimit || this.toBigNumber('150000'); // ERC721 fallback
|
|
1157
|
+
let txToBeSignedByTrezor;
|
|
1158
|
+
if (isLegacy) {
|
|
1159
|
+
txToBeSignedByTrezor = {
|
|
1160
|
+
to: tokenAddress,
|
|
1161
|
+
value: '0x0',
|
|
1162
|
+
// @ts-ignore
|
|
1163
|
+
gasLimit: `${effectiveGasLimit.hex}`,
|
|
1164
|
+
// @ts-ignore
|
|
1165
|
+
gasPrice: `${gasPrice}`,
|
|
1166
|
+
nonce: this.toBigNumber(transactionNonce)._hex,
|
|
1167
|
+
chainId: activeNetwork.chainId,
|
|
1168
|
+
data: txData,
|
|
1169
|
+
};
|
|
1170
|
+
console.log({ txToBeSignedByTrezor });
|
|
1171
|
+
}
|
|
1172
|
+
else {
|
|
1173
|
+
txToBeSignedByTrezor = {
|
|
1174
|
+
to: tokenAddress,
|
|
1175
|
+
value: '0x0',
|
|
1176
|
+
// @ts-ignore
|
|
1177
|
+
gasLimit: `${effectiveGasLimit.hex}`,
|
|
1178
|
+
// @ts-ignore
|
|
1179
|
+
maxFeePerGas: `${maxFeePerGas.hex}`,
|
|
1180
|
+
// @ts-ignore
|
|
1181
|
+
maxPriorityFeePerGas: `${maxPriorityFeePerGas.hex}`,
|
|
1182
|
+
nonce: this.toBigNumber(transactionNonce)._hex,
|
|
1183
|
+
chainId: activeNetwork.chainId,
|
|
1184
|
+
data: txData,
|
|
1185
|
+
};
|
|
1186
|
+
}
|
|
1187
|
+
// For EVM networks, Trezor expects 'eth' regardless of the network's currency
|
|
1188
|
+
const trezorCoin = activeNetwork.slip44 === 60 ? 'eth' : activeNetwork.currency;
|
|
1189
|
+
const signature = await this.trezorSigner.signEthTransaction({
|
|
1190
|
+
index: `${activeAccountId}`,
|
|
1191
|
+
tx: txToBeSignedByTrezor,
|
|
1192
|
+
coin: trezorCoin,
|
|
1193
|
+
slip44: activeNetwork.slip44,
|
|
1194
|
+
});
|
|
1195
|
+
if (signature.success) {
|
|
1196
|
+
try {
|
|
1197
|
+
let txFormattedForEthers;
|
|
1198
|
+
if (isLegacy) {
|
|
1199
|
+
txFormattedForEthers = {
|
|
1200
|
+
to: tokenAddress,
|
|
1201
|
+
value: '0x0',
|
|
1202
|
+
gasLimit: effectiveGasLimit,
|
|
1203
|
+
gasPrice,
|
|
1204
|
+
data: txData,
|
|
1205
|
+
nonce: transactionNonce,
|
|
1206
|
+
chainId: activeNetwork.chainId,
|
|
1207
|
+
type: 0,
|
|
1208
|
+
};
|
|
1209
|
+
}
|
|
1210
|
+
else {
|
|
1211
|
+
txFormattedForEthers = {
|
|
1212
|
+
to: tokenAddress,
|
|
1213
|
+
value: '0x0',
|
|
1214
|
+
gasLimit: effectiveGasLimit,
|
|
1215
|
+
maxFeePerGas,
|
|
1216
|
+
maxPriorityFeePerGas,
|
|
1217
|
+
data: txData,
|
|
1218
|
+
nonce: transactionNonce,
|
|
1219
|
+
chainId: activeNetwork.chainId,
|
|
1220
|
+
type: 2,
|
|
1221
|
+
};
|
|
1222
|
+
}
|
|
1223
|
+
signature.payload.v = parseInt(signature.payload.v, 16); //v parameter must be a number by ethers standards
|
|
1224
|
+
const signedTx = ethers_1.ethers.utils.serializeTransaction(txFormattedForEthers, signature.payload);
|
|
1225
|
+
const finalTx = await this.web3Provider.sendTransaction(signedTx);
|
|
1226
|
+
return finalTx;
|
|
1227
|
+
}
|
|
1228
|
+
catch (error) {
|
|
1229
|
+
console.log({ error });
|
|
1230
|
+
throw error;
|
|
1231
|
+
}
|
|
1232
|
+
}
|
|
1233
|
+
else {
|
|
1234
|
+
throw new Error(`Transaction Signature Failed. Error: ${signature}`);
|
|
1235
|
+
}
|
|
1236
|
+
}
|
|
1237
|
+
catch (error) {
|
|
1238
|
+
console.log({ errorDois: error });
|
|
1239
|
+
throw error;
|
|
1240
|
+
}
|
|
1241
|
+
};
|
|
1242
|
+
switch (activeAccountType) {
|
|
1243
|
+
case types_1.KeyringAccountType.Trezor:
|
|
1244
|
+
return await sendERC721TokenOnTrezor();
|
|
1245
|
+
case types_1.KeyringAccountType.Ledger:
|
|
1246
|
+
return await sendERC721TokenOnLedger();
|
|
1247
|
+
default:
|
|
1248
|
+
return await sendERC721Token();
|
|
1249
|
+
}
|
|
1250
|
+
};
|
|
1251
|
+
this.sendSignedErc1155Transaction = async ({ receiver, tokenAddress, tokenId, tokenAmount, isLegacy, maxPriorityFeePerGas, maxFeePerGas, gasPrice, gasLimit, }) => {
|
|
1252
|
+
const { decryptedPrivateKey } = this.getDecryptedPrivateKey();
|
|
1253
|
+
const { accounts, activeAccountType, activeAccountId, activeNetwork } = this.getState();
|
|
1254
|
+
const { address: activeAccountAddress } = accounts[activeAccountType][activeAccountId];
|
|
1255
|
+
const sendERC1155Token = async () => {
|
|
1256
|
+
const currentWallet = new ethers_1.ethers.Wallet(decryptedPrivateKey);
|
|
1257
|
+
const walletSigned = currentWallet.connect(this.web3Provider);
|
|
1258
|
+
let transferMethod;
|
|
1259
|
+
try {
|
|
1260
|
+
const _contract = new ethers_1.ethers.Contract(tokenAddress, (0, sysweb3_utils_1.getErc55Abi)(), walletSigned);
|
|
1261
|
+
const amount = tokenAmount ? parseInt(tokenAmount) : 1;
|
|
1262
|
+
const overrides = {};
|
|
1263
|
+
transferMethod = await _contract.safeTransferFrom(walletSigned.address, receiver, tokenId, amount, [], overrides);
|
|
1264
|
+
return transferMethod;
|
|
1265
|
+
}
|
|
1266
|
+
catch (error) {
|
|
1267
|
+
throw error;
|
|
1268
|
+
}
|
|
1269
|
+
};
|
|
1270
|
+
const sendERC1155TokenOnLedger = async () => {
|
|
1271
|
+
const signer = this.web3Provider.getSigner(activeAccountAddress);
|
|
1272
|
+
const transactionNonce = await this.getRecommendedNonce(activeAccountAddress);
|
|
1273
|
+
try {
|
|
1274
|
+
const _contract = new ethers_1.ethers.Contract(tokenAddress, (0, sysweb3_utils_1.getErc55Abi)(), signer);
|
|
1275
|
+
const amount = tokenAmount ? parseInt(tokenAmount) : 1;
|
|
1276
|
+
const txData = _contract.interface.encodeFunctionData('safeTransferFrom', [activeAccountAddress, receiver, tokenId, amount, []]);
|
|
1277
|
+
// Use fallback gas limit if not provided (for auto-estimation)
|
|
1278
|
+
const effectiveGasLimit = gasLimit || this.toBigNumber('200000'); // ERC1155 fallback
|
|
1279
|
+
let txFormattedForEthers;
|
|
1280
|
+
if (isLegacy) {
|
|
1281
|
+
txFormattedForEthers = {
|
|
1282
|
+
to: tokenAddress,
|
|
1283
|
+
value: '0x0',
|
|
1284
|
+
gasLimit: effectiveGasLimit,
|
|
1285
|
+
gasPrice,
|
|
1286
|
+
data: txData,
|
|
1287
|
+
nonce: transactionNonce,
|
|
1288
|
+
chainId: activeNetwork.chainId,
|
|
1289
|
+
type: 0,
|
|
1290
|
+
};
|
|
1291
|
+
}
|
|
1292
|
+
else {
|
|
1293
|
+
txFormattedForEthers = {
|
|
1294
|
+
to: tokenAddress,
|
|
1295
|
+
value: '0x0',
|
|
1296
|
+
gasLimit: effectiveGasLimit,
|
|
1297
|
+
maxFeePerGas,
|
|
1298
|
+
maxPriorityFeePerGas,
|
|
1299
|
+
data: txData,
|
|
1300
|
+
nonce: transactionNonce,
|
|
1301
|
+
chainId: activeNetwork.chainId,
|
|
1302
|
+
type: 2,
|
|
1303
|
+
};
|
|
1304
|
+
}
|
|
1305
|
+
const rawTx = ethers_1.ethers.utils.serializeTransaction(txFormattedForEthers);
|
|
1306
|
+
const signature = await this.ledgerSigner.evm.signEVMTransaction({
|
|
1307
|
+
rawTx: rawTx.replace('0x', ''),
|
|
1308
|
+
accountIndex: activeAccountId,
|
|
1309
|
+
});
|
|
1310
|
+
const formattedSignature = {
|
|
1311
|
+
r: `0x${signature.r}`,
|
|
1312
|
+
s: `0x${signature.s}`,
|
|
1313
|
+
v: parseInt(signature.v, 16),
|
|
1314
|
+
};
|
|
1315
|
+
if (signature) {
|
|
1316
|
+
try {
|
|
1317
|
+
const signedTx = ethers_1.ethers.utils.serializeTransaction(txFormattedForEthers, formattedSignature);
|
|
1318
|
+
const finalTx = await this.web3Provider.sendTransaction(signedTx);
|
|
1319
|
+
return finalTx;
|
|
1320
|
+
}
|
|
1321
|
+
catch (error) {
|
|
1322
|
+
throw error;
|
|
1323
|
+
}
|
|
1324
|
+
}
|
|
1325
|
+
else {
|
|
1326
|
+
throw new Error(`Transaction Signature Failed. Error: ${signature}`);
|
|
1327
|
+
}
|
|
1328
|
+
}
|
|
1329
|
+
catch (error) {
|
|
1330
|
+
throw error;
|
|
1331
|
+
}
|
|
1332
|
+
};
|
|
1333
|
+
const sendERC1155TokenOnTrezor = async () => {
|
|
1334
|
+
const signer = this.web3Provider.getSigner(activeAccountAddress);
|
|
1335
|
+
const transactionNonce = await this.getRecommendedNonce(activeAccountAddress);
|
|
1336
|
+
try {
|
|
1337
|
+
const _contract = new ethers_1.ethers.Contract(tokenAddress, (0, sysweb3_utils_1.getErc55Abi)(), signer);
|
|
1338
|
+
const amount = tokenAmount ? parseInt(tokenAmount) : 1;
|
|
1339
|
+
const txData = _contract.interface.encodeFunctionData('safeTransferFrom', [activeAccountAddress, receiver, tokenId, amount, []]);
|
|
1340
|
+
// Use fallback gas limit if not provided (for auto-estimation)
|
|
1341
|
+
const effectiveGasLimit = gasLimit || this.toBigNumber('200000'); // ERC1155 fallback
|
|
1342
|
+
let txToBeSignedByTrezor;
|
|
1343
|
+
if (isLegacy) {
|
|
1344
|
+
txToBeSignedByTrezor = {
|
|
1345
|
+
to: tokenAddress,
|
|
1346
|
+
value: '0x0',
|
|
1347
|
+
// @ts-ignore
|
|
1348
|
+
gasLimit: `${effectiveGasLimit.hex}`,
|
|
1349
|
+
// @ts-ignore
|
|
1350
|
+
gasPrice: `${gasPrice}`,
|
|
1351
|
+
nonce: this.toBigNumber(transactionNonce)._hex,
|
|
1352
|
+
chainId: activeNetwork.chainId,
|
|
1353
|
+
data: txData,
|
|
1354
|
+
};
|
|
1355
|
+
}
|
|
1356
|
+
else {
|
|
1357
|
+
txToBeSignedByTrezor = {
|
|
1358
|
+
to: tokenAddress,
|
|
1359
|
+
value: '0x0',
|
|
1360
|
+
// @ts-ignore
|
|
1361
|
+
gasLimit: `${effectiveGasLimit.hex}`,
|
|
1362
|
+
// @ts-ignore
|
|
1363
|
+
maxFeePerGas: `${maxFeePerGas.hex}`,
|
|
1364
|
+
// @ts-ignore
|
|
1365
|
+
maxPriorityFeePerGas: `${maxPriorityFeePerGas.hex}`,
|
|
1366
|
+
nonce: this.toBigNumber(transactionNonce)._hex,
|
|
1367
|
+
chainId: activeNetwork.chainId,
|
|
1368
|
+
data: txData,
|
|
1369
|
+
};
|
|
1370
|
+
}
|
|
1371
|
+
const signature = await this.trezorSigner.signEthTransaction({
|
|
1372
|
+
index: `${activeAccountId}`,
|
|
1373
|
+
tx: txToBeSignedByTrezor,
|
|
1374
|
+
coin: activeNetwork.currency,
|
|
1375
|
+
slip44: activeNetwork.slip44,
|
|
1376
|
+
});
|
|
1377
|
+
if (signature.success) {
|
|
1378
|
+
try {
|
|
1379
|
+
let txFormattedForEthers;
|
|
1380
|
+
if (isLegacy) {
|
|
1381
|
+
txFormattedForEthers = {
|
|
1382
|
+
to: tokenAddress,
|
|
1383
|
+
value: '0x0',
|
|
1384
|
+
gasLimit: effectiveGasLimit,
|
|
1385
|
+
gasPrice,
|
|
1386
|
+
data: txData,
|
|
1387
|
+
nonce: transactionNonce,
|
|
1388
|
+
chainId: activeNetwork.chainId,
|
|
1389
|
+
type: 0,
|
|
1390
|
+
};
|
|
1391
|
+
}
|
|
1392
|
+
else {
|
|
1393
|
+
txFormattedForEthers = {
|
|
1394
|
+
to: tokenAddress,
|
|
1395
|
+
value: '0x0',
|
|
1396
|
+
gasLimit: effectiveGasLimit,
|
|
1397
|
+
maxFeePerGas,
|
|
1398
|
+
maxPriorityFeePerGas,
|
|
1399
|
+
data: txData,
|
|
1400
|
+
nonce: transactionNonce,
|
|
1401
|
+
chainId: activeNetwork.chainId,
|
|
1402
|
+
type: 2,
|
|
1403
|
+
};
|
|
1404
|
+
}
|
|
1405
|
+
signature.payload.v = parseInt(signature.payload.v, 16); //v parameter must be a number by ethers standards
|
|
1406
|
+
const signedTx = ethers_1.ethers.utils.serializeTransaction(txFormattedForEthers, signature.payload);
|
|
1407
|
+
const finalTx = await this.web3Provider.sendTransaction(signedTx);
|
|
1408
|
+
return finalTx;
|
|
1409
|
+
}
|
|
1410
|
+
catch (error) {
|
|
1411
|
+
console.log({ error });
|
|
1412
|
+
throw error;
|
|
1413
|
+
}
|
|
1414
|
+
}
|
|
1415
|
+
else {
|
|
1416
|
+
throw new Error(`Transaction Signature Failed. Error: ${signature}`);
|
|
1417
|
+
}
|
|
1418
|
+
}
|
|
1419
|
+
catch (error) {
|
|
1420
|
+
console.log({ error });
|
|
1421
|
+
throw error;
|
|
1422
|
+
}
|
|
1423
|
+
};
|
|
1424
|
+
switch (activeAccountType) {
|
|
1425
|
+
case types_1.KeyringAccountType.Trezor:
|
|
1426
|
+
return await sendERC1155TokenOnTrezor();
|
|
1427
|
+
case types_1.KeyringAccountType.Ledger:
|
|
1428
|
+
return await sendERC1155TokenOnLedger();
|
|
1429
|
+
default:
|
|
1430
|
+
return await sendERC1155Token();
|
|
1431
|
+
}
|
|
1432
|
+
};
|
|
1433
|
+
this.getRecommendedNonce = async (address) => {
|
|
1434
|
+
try {
|
|
1435
|
+
return await this.web3Provider.getTransactionCount(address, 'pending');
|
|
1436
|
+
}
|
|
1437
|
+
catch (error) {
|
|
1438
|
+
throw error;
|
|
1439
|
+
}
|
|
1440
|
+
};
|
|
1441
|
+
this.getFeeByType = async (type) => {
|
|
1442
|
+
const gasPrice = (await this.getRecommendedGasPrice(false));
|
|
1443
|
+
const low = this.toBigNumber(gasPrice)
|
|
1444
|
+
.mul(ethers_1.ethers.BigNumber.from('8'))
|
|
1445
|
+
.div(ethers_1.ethers.BigNumber.from('10'))
|
|
1446
|
+
.toString();
|
|
1447
|
+
const high = this.toBigNumber(gasPrice)
|
|
1448
|
+
.mul(ethers_1.ethers.BigNumber.from('11'))
|
|
1449
|
+
.div(ethers_1.ethers.BigNumber.from('10'))
|
|
1450
|
+
.toString();
|
|
1451
|
+
if (type === 'low')
|
|
1452
|
+
return low;
|
|
1453
|
+
if (type === 'high')
|
|
1454
|
+
return high;
|
|
1455
|
+
return gasPrice;
|
|
1456
|
+
};
|
|
1457
|
+
this.getGasLimit = async (toAddress) => {
|
|
1458
|
+
try {
|
|
1459
|
+
const estimated = await this.web3Provider.estimateGas({
|
|
1460
|
+
to: toAddress,
|
|
1461
|
+
});
|
|
1462
|
+
return Number(ethers_1.ethers.utils.formatUnits(estimated, 'gwei'));
|
|
1463
|
+
}
|
|
1464
|
+
catch (error) {
|
|
1465
|
+
throw error;
|
|
1466
|
+
}
|
|
1467
|
+
};
|
|
1468
|
+
this.getTxGasLimit = async (tx) => {
|
|
1469
|
+
try {
|
|
1470
|
+
return this.web3Provider.estimateGas(tx);
|
|
1471
|
+
}
|
|
1472
|
+
catch (error) {
|
|
1473
|
+
throw error;
|
|
1474
|
+
}
|
|
1475
|
+
};
|
|
1476
|
+
this.getRecommendedGasPrice = async (formatted) => {
|
|
1477
|
+
try {
|
|
1478
|
+
const gasPriceBN = await this.web3Provider.getGasPrice();
|
|
1479
|
+
if (formatted) {
|
|
1480
|
+
return {
|
|
1481
|
+
gwei: Number(ethers_1.ethers.utils.formatUnits(gasPriceBN, 'gwei')).toFixed(2),
|
|
1482
|
+
ethers: ethers_1.ethers.utils.formatEther(gasPriceBN),
|
|
1483
|
+
};
|
|
1484
|
+
}
|
|
1485
|
+
return gasPriceBN.toString();
|
|
1486
|
+
}
|
|
1487
|
+
catch (error) {
|
|
1488
|
+
throw error;
|
|
1489
|
+
}
|
|
1490
|
+
};
|
|
1491
|
+
this.getBalance = async (address) => {
|
|
1492
|
+
try {
|
|
1493
|
+
const balance = await this.web3Provider.getBalance(address);
|
|
1494
|
+
const formattedBalance = ethers_1.ethers.utils.formatEther(balance);
|
|
1495
|
+
const roundedBalance = (0, floor_1.default)(parseFloat(formattedBalance), 4);
|
|
1496
|
+
return roundedBalance;
|
|
1497
|
+
}
|
|
1498
|
+
catch (error) {
|
|
1499
|
+
throw error;
|
|
1500
|
+
}
|
|
1501
|
+
};
|
|
1502
|
+
this.getTransactionTimestamp = async (transaction) => {
|
|
1503
|
+
const { timestamp } = await this.web3Provider.getBlock(Number(transaction.blockNumber));
|
|
1504
|
+
return {
|
|
1505
|
+
...transaction,
|
|
1506
|
+
timestamp,
|
|
1507
|
+
};
|
|
1508
|
+
};
|
|
1509
|
+
this.importAccount = (mnemonicOrPrivKey) => {
|
|
1510
|
+
if (ethers_1.ethers.utils.isHexString(mnemonicOrPrivKey)) {
|
|
1511
|
+
return new ethers_1.ethers.Wallet(mnemonicOrPrivKey);
|
|
1512
|
+
}
|
|
1513
|
+
const { privateKey } = ethers_1.ethers.Wallet.fromMnemonic(mnemonicOrPrivKey);
|
|
1514
|
+
const account = new ethers_1.ethers.Wallet(privateKey);
|
|
1515
|
+
return account;
|
|
1516
|
+
};
|
|
1517
|
+
this.getNetwork = getNetwork;
|
|
1518
|
+
this.getDecryptedPrivateKey = getDecryptedPrivateKey;
|
|
1519
|
+
this.abortController = new AbortController();
|
|
1520
|
+
// NOTE: Defer network access until vault state getter is initialized
|
|
1521
|
+
// The web3Provider will be created lazily when first accessed via getters
|
|
1522
|
+
this.getState = getState;
|
|
1523
|
+
this.trezorSigner = trezorSigner;
|
|
1524
|
+
this.ledgerSigner = ledgerSigner;
|
|
1525
|
+
}
|
|
1526
|
+
// Getter that automatically ensures providers are initialized when accessed
|
|
1527
|
+
get web3Provider() {
|
|
1528
|
+
this.ensureProvidersInitialized();
|
|
1529
|
+
return this._web3Provider;
|
|
1530
|
+
}
|
|
1531
|
+
// Helper method to ensure providers are initialized when first needed
|
|
1532
|
+
ensureProvidersInitialized() {
|
|
1533
|
+
if (!this._web3Provider) {
|
|
1534
|
+
// Providers not initialized yet, initialize them now
|
|
1535
|
+
try {
|
|
1536
|
+
const currentNetwork = this.getNetwork();
|
|
1537
|
+
this.setWeb3Provider(currentNetwork);
|
|
1538
|
+
}
|
|
1539
|
+
catch (error) {
|
|
1540
|
+
// If vault state not available yet, providers will be initialized later
|
|
1541
|
+
// when setWeb3Provider is called explicitly
|
|
1542
|
+
console.log('[EthereumTransactions] Deferring provider initialization:', error.message);
|
|
1543
|
+
}
|
|
1544
|
+
}
|
|
1545
|
+
}
|
|
1546
|
+
// Helper method to detect UTXO networks
|
|
1547
|
+
isUtxoNetwork(network) {
|
|
1548
|
+
// Generic UTXO network detection patterns:
|
|
1549
|
+
// 1. URL contains blockbook or trezor (most reliable)
|
|
1550
|
+
// 2. Network kind is explicitly set to 'syscoin'
|
|
1551
|
+
const hasBlockbookUrl = !!(network.url?.includes('blockbook') || network.url?.includes('trezor'));
|
|
1552
|
+
const hasUtxoKind = network.kind === sysweb3_network_1.INetworkType.Syscoin;
|
|
1553
|
+
return hasBlockbookUrl || hasUtxoKind;
|
|
1554
|
+
}
|
|
1555
|
+
setWeb3Provider(network) {
|
|
1556
|
+
this.abortController.abort();
|
|
1557
|
+
this.abortController = new AbortController();
|
|
1558
|
+
// Check if network is a UTXO network to avoid creating web3 providers for blockbook URLs
|
|
1559
|
+
const isUtxoNetwork = this.isUtxoNetwork(network);
|
|
1560
|
+
if (isUtxoNetwork) {
|
|
1561
|
+
// For UTXO networks, don't create web3 providers at all since they won't be used
|
|
1562
|
+
console.log('[EthereumTransactions] setWeb3Provider: Skipping web3Provider creation for UTXO network:', network.url);
|
|
1563
|
+
// Clear any existing providers for UTXO networks
|
|
1564
|
+
this._web3Provider = undefined;
|
|
1565
|
+
}
|
|
1566
|
+
else {
|
|
1567
|
+
// For EVM networks, create normal providers
|
|
1568
|
+
const isL2Network = L2_NETWORK_CHAIN_IDS.includes(network.chainId);
|
|
1569
|
+
const CurrentProvider = isL2Network
|
|
1570
|
+
? providers_1.CustomL2JsonRpcProvider
|
|
1571
|
+
: providers_1.CustomJsonRpcProvider;
|
|
1572
|
+
this._web3Provider = new CurrentProvider(this.abortController.signal, network.url);
|
|
1573
|
+
}
|
|
1574
|
+
}
|
|
1575
|
+
}
|
|
1576
|
+
exports.EthereumTransactions = EthereumTransactions;
|
|
1577
|
+
//# sourceMappingURL=ethereum.js.map
|