Skip to content

Commit

Permalink
Merge pull request #255 from rainlanguage/2024-11-12-node-error-fix
Browse files Browse the repository at this point in the history
node error and nonce fix
  • Loading branch information
rouzwelt authored Nov 13, 2024
2 parents 64cce4d + bcc0148 commit 17c4d7a
Show file tree
Hide file tree
Showing 6 changed files with 60 additions and 38 deletions.
71 changes: 41 additions & 30 deletions src/account.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,7 @@ import { mnemonicToAccount, privateKeyToAccount } from "viem/accounts";
import { erc20Abi, multicall3Abi, orderbookAbi, routeProcessor3Abi } from "./abis";
import { context, Context, SpanStatusCode, trace, Tracer } from "@opentelemetry/api";
import { BotConfig, CliOptions, ViemClient, TokenDetails, OwnedOrder } from "./types";
import {
parseAbi,
hexToNumber,
numberToHex,
PublicClient,
createNonceManager,
NonceManagerSource,
} from "viem";
import { parseAbi, hexToNumber, numberToHex, PublicClient, NonceManagerSource } from "viem";

/** Standard base path for eth accounts */
export const BasePath = "m/44'/60'/0'/0/" as const;
Expand Down Expand Up @@ -47,19 +40,11 @@ export async function initAccounts(
isMnemonic
? mnemonicToAccount(mnemonicOrPrivateKey, {
addressIndex: MainAccountDerivationIndex,
nonceManager: createNonceManager({
source: noneSource(),
}),
})
: privateKeyToAccount(
(mnemonicOrPrivateKey.startsWith("0x")
? mnemonicOrPrivateKey
: "0x" + mnemonicOrPrivateKey) as `0x${string}`,
{
nonceManager: createNonceManager({
source: noneSource(),
}),
},
),
config.timeout,
(config as any).testClientViem,
Expand All @@ -77,9 +62,6 @@ export async function initAccounts(
undefined,
mnemonicToAccount(mnemonicOrPrivateKey, {
addressIndex,
nonceManager: createNonceManager({
source: noneSource(),
}),
}),
config.timeout,
(config as any).testClientViem,
Expand Down Expand Up @@ -124,6 +106,7 @@ export async function initAccounts(
const hash = await mainAccount.sendTransaction({
to: accounts[i].account.address,
value: transferAmount.toBigInt(),
nonce: await getNonce(mainAccount),
});
const receipt = await mainAccount.waitForTransactionReceipt({
hash,
Expand Down Expand Up @@ -230,9 +213,6 @@ export async function manageAccounts(
undefined,
mnemonicToAccount(options.mnemonic!, {
addressIndex: ++lastIndex,
nonceManager: createNonceManager({
source: noneSource(),
}),
}),
config.timeout,
(config as any).testClientViem,
Expand Down Expand Up @@ -271,6 +251,7 @@ export async function manageAccounts(
const hash = await config.mainAccount.sendTransaction({
to: acc.account.address,
value: transferAmount.toBigInt(),
nonce: await getNonce(config.mainAccount),
});
const receipt = await config.mainAccount.waitForTransactionReceipt({
hash,
Expand Down Expand Up @@ -557,10 +538,11 @@ export async function sweepToMainWallet(
const hash = await toWallet.sendTransaction({
to: fromWallet.account.address,
value: transferAmount.toBigInt(),
nonce: await getNonce(fromWallet),
});
const receipt = await toWallet.waitForTransactionReceipt({
hash,
confirmations: 2,
confirmations: 4,
timeout: 100_000,
});
const txCost = ethers.BigNumber.from(receipt.effectiveGasPrice).mul(receipt.gasUsed);
Expand Down Expand Up @@ -599,10 +581,12 @@ export async function sweepToMainWallet(
span?.setAttribute("details.tokenAddress", txs[i].bounty.address);
span?.setAttribute("details.balance", txs[i].balance);
try {
const nonce = await getNonce(fromWallet);
(txs[i].tx as any).nonce = nonce;
const hash = await fromWallet.sendTransaction(txs[i].tx);
const receipt = await fromWallet.waitForTransactionReceipt({
hash,
confirmations: 2,
confirmations: 4,
timeout: 100_000,
});
const txCost = ethers.BigNumber.from(receipt.effectiveGasPrice).mul(receipt.gasUsed);
Expand Down Expand Up @@ -655,10 +639,11 @@ export async function sweepToMainWallet(
to: toWallet.account.address,
value: transferAmount.toBigInt(),
gas: gasLimit.toBigInt(),
nonce: await getNonce(fromWallet),
});
const receipt = await fromWallet.waitForTransactionReceipt({
hash,
confirmations: 2,
confirmations: 4,
timeout: 100_000,
});
const txCost = ethers.BigNumber.from(receipt.effectiveGasPrice).mul(
Expand Down Expand Up @@ -803,10 +788,11 @@ export async function sweepToEth(config: BotConfig, tracer?: Tracer, ctx?: Conte
rp4Address,
balance.mul(100),
]) as `0x${string}`,
nonce: await getNonce(config.mainAccount),
});
await config.mainAccount.waitForTransactionReceipt({
hash,
confirmations: 2,
confirmations: 4,
timeout: 100_000,
});
}
Expand Down Expand Up @@ -843,11 +829,13 @@ export async function sweepToEth(config: BotConfig, tracer?: Tracer, ctx?: Conte
span?.end();
continue;
} else {
const nonce = await getNonce(config.mainAccount);
(rawtx as any).nonce = nonce;
const hash = await config.mainAccount.sendTransaction(rawtx);
span?.setAttribute("txHash", hash);
const receipt = await config.mainAccount.waitForTransactionReceipt({
hash,
confirmations: 2,
confirmations: 4,
timeout: 100_000,
});
if (receipt.status === "success") {
Expand Down Expand Up @@ -1004,10 +992,11 @@ export async function fundOwnedOrders(
to: rp4Address,
value: sellAmount!.toBigInt(),
data,
nonce: await getNonce(config.mainAccount),
});
const swapReceipt = await config.mainAccount.waitForTransactionReceipt({
hash: swapHash,
confirmations: 2,
confirmations: 4,
timeout: 100_000,
});
const swapTxCost = ethers.BigNumber.from(
Expand Down Expand Up @@ -1039,11 +1028,12 @@ export async function fundOwnedOrders(
ownedOrder.orderbook,
topupAmount.mul(20),
]) as `0x${string}`,
nonce: await getNonce(config.mainAccount),
});
const approveReceipt =
await config.mainAccount.waitForTransactionReceipt({
hash: approveHash,
confirmations: 2,
confirmations: 4,
timeout: 100_000,
});
const approveTxCost = ethers.BigNumber.from(
Expand All @@ -1064,10 +1054,11 @@ export async function fundOwnedOrders(
topupAmount,
[],
]) as `0x${string}`,
nonce: await getNonce(config.mainAccount),
});
const receipt = await config.mainAccount.waitForTransactionReceipt({
hash,
confirmations: 2,
confirmations: 4,
timeout: 100_000,
});
const txCost = ethers.BigNumber.from(receipt.effectiveGasPrice).mul(
Expand Down Expand Up @@ -1123,3 +1114,23 @@ async function getTransactionCount(
);
return hexToNumber(count);
}

/**
* Get an account's nonce
* @param client - The viem client
* @param address - account address
*/
export async function getNonce(client: ViemClient): Promise<number> {
for (let i = 0; i < 3; i++) {
try {
return await client.getTransactionCount({
address: client.account.address,
blockTag: "latest",
});
} catch (error) {
if (i === 2) throw error;
else await sleep((i + 1) * 5000);
}
}
throw "Failed to get account's nonce";
}
8 changes: 4 additions & 4 deletions src/error.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import {
BaseError,
RpcRequestError,
InvalidInputRpcError,
ExecutionRevertedError,
TransactionRejectedRpcError,
// InvalidInputRpcError,
// TransactionRejectedRpcError,
} from "viem";

/**
Expand Down Expand Up @@ -46,8 +46,8 @@ export function errorSnapshot(header: string, err: any): string {
export function containsNodeError(err: BaseError): boolean {
try {
return (
err instanceof TransactionRejectedRpcError ||
err instanceof InvalidInputRpcError ||
// err instanceof TransactionRejectedRpcError ||
// err instanceof InvalidInputRpcError ||
err instanceof ExecutionRevertedError ||
(err instanceof RpcRequestError && err.code === ExecutionRevertedError.code) ||
("cause" in err && containsNodeError(err.cause as any))
Expand Down
10 changes: 7 additions & 3 deletions src/processOrders.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ import { arbAbis, orderbookAbi } from "./abis";
import { privateKeyToAccount } from "viem/accounts";
import { BigNumber, Contract, ethers } from "ethers";
import { Tracer } from "@opentelemetry/sdk-trace-base";
import { fundOwnedOrders, rotateAccounts } from "./account";
import { Context, SpanStatusCode } from "@opentelemetry/api";
import { fundOwnedOrders, getNonce, rotateAccounts } from "./account";
import { containsNodeError, ErrorSeverity, errorSnapshot } from "./error";
import {
Report,
Expand Down Expand Up @@ -619,6 +619,10 @@ export async function processPair(args: {
// submit the tx
let txhash, txUrl;
try {
rawtx.nonce = await getNonce(flashbotSigner !== undefined ? flashbotSigner : signer);
if (flashbotSigner !== undefined) {
rawtx.gas = undefined;
}
txhash =
flashbotSigner !== undefined
? await flashbotSigner.sendTransaction(rawtx)
Expand All @@ -637,7 +641,7 @@ export async function processPair(args: {
},
withBigintSerializer,
);
spanAttributes["txNoneNodeError"] = containsNodeError(e as BaseError);
spanAttributes["txNoneNodeError"] = !containsNodeError(e as BaseError);
result.error = e;
result.reason = ProcessPairHaltReason.TxFailed;
throw result;
Expand Down Expand Up @@ -775,7 +779,7 @@ export async function processPair(args: {
result.report.actualGasCost = ethers.utils.formatUnits(actualGasCost);
}
result.error = e;
spanAttributes["txNoneNodeError"] = containsNodeError(e);
spanAttributes["txNoneNodeError"] = !containsNodeError(e);
result.reason = ProcessPairHaltReason.TxMineFailed;
throw result;
}
Expand Down
1 change: 1 addition & 0 deletions src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,7 @@ export type RawTx = {
data: `0x${string}`;
gasPrice?: bigint;
gas?: bigint;
nonce?: number;
};

export type DryrunValue = {
Expand Down
3 changes: 3 additions & 0 deletions test/account.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -275,6 +275,7 @@ describe("Test accounts", async function () {
estimateGas: async () => 25n,
getBalance: async () => 10000n,
sendTransaction: async () => "0x1234",
getTransactionCount: async () => 0,
waitForTransactionReceipt: async () => ({
status: "success",
effectiveGasPrice: ethers.BigNumber.from(5),
Expand All @@ -292,6 +293,7 @@ describe("Test accounts", async function () {
viemClient: {
chain: { id: chainId },
call: async () => ({ data: `0x${"1" + "0".repeat(18)}` }),
getTransactionCount: async () => 0,
},
};

Expand Down Expand Up @@ -356,6 +358,7 @@ describe("Test accounts", async function () {
estimateGas: async () => 25n,
getBalance: async () => 10000n,
sendTransaction: async () => "0x1234",
getTransactionCount: async () => 0,
call: async () => ({ data: "0x00" }),
waitForTransactionReceipt: async () => ({
status: "success",
Expand Down
5 changes: 4 additions & 1 deletion test/processPair.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ describe("Test process pair", async function () {
getGasPrice: async () => gasPrice,
estimateGas: async () => gasLimitEstimation,
sendTransaction: async () => txHash,
getTransactionCount: async () => 0,
waitForTransactionReceipt: async () => {
return {
status: "success",
Expand All @@ -75,6 +76,7 @@ describe("Test process pair", async function () {
multicall: async () => [vaultBalance.toBigInt()],
getGasPrice: async () => gasPrice.toBigInt(),
getBlockNumber: async () => 123456n,
getTransactionCount: async () => 0,
waitForTransactionReceipt: async () => {
return {
status: "success",
Expand Down Expand Up @@ -514,6 +516,7 @@ describe("Test process pair", async function () {
to: arb.address,
gasPrice: gasPrice.mul(107).div(100).toString(),
gas: gasLimitEstimation.toString(),
nonce: 0,
from: signer.account.address,
};
const expected = {
Expand Down Expand Up @@ -543,7 +546,7 @@ describe("Test process pair", async function () {
"details.outputToEthPrice": "1",
"details.marketQuote.num": 0.99699,
"details.marketQuote.str": "0.99699",
txNoneNodeError: false,
txNoneNodeError: true,
"details.quote": JSON.stringify({
maxOutput: formatUnits(vaultBalance),
ratio: formatUnits(ethers.constants.Zero),
Expand Down

0 comments on commit 17c4d7a

Please sign in to comment.