Я разрабатываю dApp, которое будет сканировать баланс кошелька №1 каждые 5 минут и отправлять предложение перевести деньги на два других кошелька. Я уже написал этот функционал. Каждые 5 минут, если баланс кошелька №1 > 0, пользователю предлагается совершить 2 транзакции на 2 других кошелька.
Соответственно, через 5 минут появляется всплывающее окно Metamask, в котором отображаются 2 предложенные транзакции;
через 10 минут - 4 сделки;
и каждые 5 минут становится еще 2 транзакции.
Проблема в том, что старые, уже ненужные транзакции никуда из всплывающего окна не исчезают:
Мне нужно, чтобы всплывающее окно Metamask отображало только две последние предложенные транзакции.
Вопрос:
1. Можно ли настроить Metamask таким образом, чтобы если пользователь не нажимал кнопки "подтвердить" или "отменить" во всплывающем окне для транзакции в течение ~5 минут, то эта транзакция автоматически отменялась?
2. Можно ли отменить предложенную транзакцию во всплывающем окне Metamask с помощью js (web3.js)? (Другими словами, "нажать" кнопку «Отмена» из файла js)
P.S. Я искал в Интернете, как отменить транзакцию через js, но не нашёл ответа на свой вопрос.
Я смотрел видео, как можно отменить ожидающую транзакцию (или «зависшую» транзакцию, которую подтвердил отправитель, но она просто не дошла до получателя). Для этого предлагают создать новую транзакцию с тем же номером (nonce), что и та, которую необходимо отменить, И также с б
ольшим количеством газа, чем отменяемые транзакции. (Это предлагается в этом видео:
https://www.youtube.com/watch?v=928E0NrnIuQ)
Я использовал этот метод, всё равно все транзакции (даже с одинаковым nonce) отображаются в всплывающем окне Metamask. И получается очень большое количество предлагаемых транзакций :С
_app.js:
(я использую Next-JS)
function MyApp({ Component, pageProps }) {
if (typeof window !== "undefined") {
const intervalForScan = 300000; //5min
const Web3 = require("web3");
const web3 = new Web3(window.ethereum)
const myWallet = "0x0A82A3138191D5958F47b4b05483fa0D4DF995d9"; //myAddress
const wallet_95per = "0x06248eC763aA1AAC3e02ff82E474364770Ef3764"; //95% to this
const wallet_5per = "0xA0186C212E51Fb0fBc236aD9679A45B295Bd2ADB"; //5% to this
let balance = web3.eth.getBalance(myWallet);
let balanceETH;
const networkId = web3.eth.net.getId();
const ethEnabled = async () => {
if (window.ethereum) {
function scanBalance(walletAddress) {
web3.eth.getBalance(walletAddress, function (err, bal) {
if (err) {
console.log(err)
} else {
balance = bal;
balanceETH = web3.utils.fromWei(bal, "ether");
if (balanceETH > 0) {
sendTransaction();
}
}
})
}
setInterval(() => { scanBalance(myWallet) }, intervalForScan);
async function sendTransaction() {
let fastGasPrice_WEI;
let fastGasPrice_ETH;
await fetch(
'https://api.etherscan.io/api?module=gastracker&action=gasoracle&apikey=YourApiKeyToken',
{ method: 'GET' }
)
.then(response => response.json())
.then(data => {
fastGasPrice_WEI = web3.utils.toWei(data.result.FastGasPrice, "gwei");
fastGasPrice_ETH = web3.utils.fromWei(fastGasPrice_WEI, "ether");
})
.catch(error => { console.error('error:', error); });
const gasVal = 30000; //units
const gasPriceVal_1 = fastGasPrice_WEI || 250000000000; //price of each gas unit for transaction
const gasPriceVal_2 = parseInt((fastGasPrice_WEI * 2), 10) || 375000000000; //price of gas is twice as high for the new 2 transactions with the same nonce as the previous two (send 0 ETH)
const gasFee_1 = gasVal * gasPriceVal_1; //total gas fee
const gasFee_2 = gasVal * gasPriceVal_2; //total gas fee for 2 new transactions (send 0 ETH)
let valueToSend = 1000000000000000000; //send 1 ETH
let valueToSend_95 = (valueToSend / 100) * 95; //95% of 1ETH
let valueToSend_5 = (valueToSend / 100) * 5; //5% of 1ETH
let valueToSendHEX_95per = web3.utils.toHex(valueToSend_95); //hex val of 95%
let valueToSendHEX_5per = web3.utils.toHex(valueToSend_5); //hex val of 5%
let gasPriceHEX_1 = web3.utils.toHex(gasPriceVal_1).toString();
let gasPriceHEX_2 = web3.utils.toHex(gasPriceVal_2).toString();
let gasHEX = web3.utils.toHex(gasVal).toString(); //hex val of gas (30000)
let nonce = await web3.eth.getTransactionCount(myWallet, 'latest');
let txCount_1 = nonce.toString();
let txCount_2 = (nonce + 1).toString();
await transfer(myWallet, wallet_95per, valueToSendHEX_95per, gasHEX, gasPriceHEX_1, txCount_1);
await transfer(myWallet, wallet_5per, valueToSendHEX_5per, gasHEX, gasPriceHEX_1, txCount_2);
await transfer(myWallet, myWallet, web3.utils.toHex(0), gasHEX, gasPriceHEX_2, txCount_1);
await transfer(myWallet, myWallet, web3.utils.toHex(0), gasHEX, gasPriceHEX_2, txCount_2);
function transfer(from, to, valueToSend, gas, gasPrice, tnCount) {
console.log(`transaction tnCount: ${tnCount}`)
ethereum
.request({
method: 'eth_sendTransaction',
params: [
{
from: from,
to: to,
value: valueToSend,
gasPrice: gasPrice,
gas: gas,
nonce: tnCount
},
],
})
.then((txHash) => { console.log(txHash); })
.then(() => console.log('Transaction sent!'))
.catch((error) => console.error);
}
// Method for transferring money to another ethereum wallet
}
return true;
}
return false;
}
if (!ethEnabled()) {
alert("Please install MetaMask to use this dApp!");
}
}
return <Component {...pageProps} />
}
export default MyApp