diff --git a/src/modes/index.ts b/src/modes/index.ts index 07f023ea..d9bfe204 100644 --- a/src/modes/index.ts +++ b/src/modes/index.ts @@ -6,7 +6,7 @@ import { findOpp as findInterObOpp } from "./interOrderbook"; import { findOpp as findIntraObOpp } from "./intraOrderbook"; import { findOppWithRetries as findRpOpp } from "./routeProcessor"; import { BotConfig, BundledOrders, ViemClient, DryrunResult, SpanAttrs } from "../types"; -import { extendSpanAttributes } from "../utils"; +// import { extendSpanAttributes } from "../utils"; /** * The main entrypoint for the main logic to find opps. @@ -117,25 +117,34 @@ export async function findOpp({ noneNodeError: undefined, }; if ((allResults[0] as any)?.reason?.spanAttributes) { - extendSpanAttributes( - spanAttributes, + spanAttributes["routeProcessor"] = JSON.stringify( (allResults[0] as any).reason.spanAttributes, - "routeProcessor", ); + // extendSpanAttributes( + // spanAttributes, + // (allResults[0] as any).reason.spanAttributes, + // "routeProcessor", + // ); } if ((allResults[1] as any)?.reason?.spanAttributes) { - extendSpanAttributes( - spanAttributes, - (allResults[1] as any).reason.spanAttributes, - "intraOrderbook", + spanAttributes["intraOrderbook"] = JSON.stringify( + (allResults[1] as any).reason.spanAttributes["intraOrderbook"], ); + // extendSpanAttributes( + // spanAttributes, + // (allResults[1] as any).reason.spanAttributes, + // "intraOrderbook", + // ); } if ((allResults[2] as any)?.reason?.spanAttributes) { - extendSpanAttributes( - spanAttributes, + spanAttributes["interOrderbook"] = JSON.stringify( (allResults[2] as any).reason.spanAttributes, - "interOrderbook", ); + // extendSpanAttributes( + // spanAttributes, + // (allResults[2] as any).reason.spanAttributes, + // "interOrderbook", + // ); } if ((allResults[0] as any)?.reason?.value?.noneNodeError) { result.noneNodeError = (allResults[0] as any).reason.value.noneNodeError; diff --git a/src/modes/interOrderbook.ts b/src/modes/interOrderbook.ts index 6f3d413d..398b00dd 100644 --- a/src/modes/interOrderbook.ts +++ b/src/modes/interOrderbook.ts @@ -10,7 +10,7 @@ import { scale18To, estimateProfit, withBigintSerializer, - extendSpanAttributes, + // extendSpanAttributes, } from "../utils"; /** @@ -357,13 +357,17 @@ export async function findOpp({ // } catch { // /**/ // } + const allOrderbooksAttributes: any = {}; for (let i = 0; i < e.errors.length; i++) { - extendSpanAttributes( - spanAttributes, - e.errors[i].spanAttributes, - "againstOrderbooks." + opposingOrderbookOrders[i].orderbook, - ); + allOrderbooksAttributes[opposingOrderbookOrders[i].orderbook] = + e.errors[i].spanAttributes; + // extendSpanAttributes( + // spanAttributes, + // e.errors[i].spanAttributes, + // "againstOrderbooks." + opposingOrderbookOrders[i].orderbook, + // ); } + spanAttributes["againstOrderbooks"] = JSON.stringify(allOrderbooksAttributes); const noneNodeErrors = allNoneNodeErrors.filter((v) => !!v); if (allNoneNodeErrors.length && noneNodeErrors.length / allNoneNodeErrors.length > 0.5) { result.value = { diff --git a/src/modes/intraOrderbook.ts b/src/modes/intraOrderbook.ts index 0a077ff3..d9c1a402 100644 --- a/src/modes/intraOrderbook.ts +++ b/src/modes/intraOrderbook.ts @@ -4,7 +4,7 @@ import { BigNumber, ethers } from "ethers"; import { getWithdrawEnsureBytecode } from "../config"; import { BaseError, erc20Abi, PublicClient } from "viem"; import { containsNodeError, errorSnapshot } from "../error"; -import { estimateProfit, scale18, withBigintSerializer, extendSpanAttributes } from "../utils"; +import { estimateProfit, scale18, withBigintSerializer } from "../utils"; import { SpanAttrs, BotConfig, @@ -292,6 +292,7 @@ export async function findOpp({ ); if (!opposingOrders || !opposingOrders.length) throw undefined; + const allErrorAttributes: string[] = []; const allNoneNodeErrors: (string | undefined)[] = []; const inputBalance = scale18( await viemClient.readContract({ @@ -328,9 +329,11 @@ export async function findOpp({ }); } catch (e: any) { allNoneNodeErrors.push(e?.value?.noneNodeError); - extendSpanAttributes(spanAttributes, e.spanAttributes, "intraOrderbook." + i); + allErrorAttributes.push(JSON.stringify(e.spanAttributes)); + // extendSpanAttributes(spanAttributes, e.spanAttributes, "intraOrderbook." + i); } } + spanAttributes["intraOrderbook"] = allErrorAttributes; const noneNodeErrors = allNoneNodeErrors.filter((v) => !!v); if (allNoneNodeErrors.length && noneNodeErrors.length / allNoneNodeErrors.length > 0.5) { result.value = { diff --git a/src/modes/routeProcessor.ts b/src/modes/routeProcessor.ts index d0aa2a18..17af60bc 100644 --- a/src/modes/routeProcessor.ts +++ b/src/modes/routeProcessor.ts @@ -14,7 +14,7 @@ import { estimateProfit, visualizeRoute, withBigintSerializer, - extendSpanAttributes, + // extendSpanAttributes, } from "../utils"; /** @@ -365,7 +365,8 @@ export async function findOpp({ // the fail reason can only be no route in case all hops fail reasons are no route if (e.reason !== RouteProcessorDryrunHaltReason.NoRoute) noRoute = false; allNoneNodeErrors.push(e?.value?.noneNodeError); - extendSpanAttributes(spanAttributes, e.spanAttributes, "full"); + spanAttributes["full"] = JSON.stringify(e.spanAttributes); + // extendSpanAttributes(spanAttributes, e.spanAttributes, "full"); } if (!hasPriceMatch.value) { const maxTradeSize = findMaxInput({ @@ -398,7 +399,8 @@ export async function findOpp({ // the fail reason can only be no route in case all hops fail reasons are no route if (e.reason !== RouteProcessorDryrunHaltReason.NoRoute) noRoute = false; allNoneNodeErrors.push(e?.value?.noneNodeError); - extendSpanAttributes(spanAttributes, e.spanAttributes, "partial"); + spanAttributes["partial"] = JSON.stringify(e.spanAttributes); + // extendSpanAttributes(spanAttributes, e.spanAttributes, "partial"); } } } diff --git a/src/processOrders.ts b/src/processOrders.ts index 0c8a006c..27ef3476 100644 --- a/src/processOrders.ts +++ b/src/processOrders.ts @@ -630,9 +630,40 @@ export async function processPair(args: { } } } catch (e: any) { - // record all span attributes + // record all span attributes in their scopes for (const attrKey in e.spanAttributes) { - spanAttributes["details." + attrKey] = e.spanAttributes[attrKey]; + if (attrKey === "routeProcessor") { + const rpAttrs = JSON.parse(e.spanAttributes[attrKey]); + for (const key in rpAttrs) { + const innerAttrs = JSON.parse(rpAttrs[key]); + for (const innerKey in innerAttrs) { + spanAttributes["details.routeProcessor." + key + "." + innerKey] = + innerAttrs[innerKey]; + } + } + } else if (attrKey === "intraOrderbook") { + const intraAttrs = JSON.parse(e.spanAttributes[attrKey]); + for (let i = 0; i < intraAttrs.length; i++) { + const innerAttrs = JSON.parse(intraAttrs[i]); + for (const innerKey in innerAttrs) { + spanAttributes["details.intraOrderbook." + i + "." + innerKey] = + innerAttrs[innerKey]; + } + } + } else if (attrKey === "interOrderbook") { + const interAttrs = JSON.parse( + JSON.parse(e.spanAttributes[attrKey])["againstOrderbooks"], + ); + for (const key in interAttrs) { + for (const innerKey in interAttrs[key]) { + spanAttributes[ + "details.interOrderbook.againstOrderbooks." + key + "." + innerKey + ] = interAttrs[key][innerKey]; + } + } + } else { + spanAttributes["details." + attrKey] = e.spanAttributes[attrKey]; + } } if (e.noneNodeError) { spanAttributes["details.noneNodeError"] = true; diff --git a/test/findOpp.test.js b/test/findOpp.test.js index a6d8fd7b..1fd5df62 100644 --- a/test/findOpp.test.js +++ b/test/findOpp.test.js @@ -323,7 +323,7 @@ describe("Test find opp", async function () { assert.deepEqual(result, expected); }); - it.only("should NOT find opp", async function () { + it("should NOT find opp", async function () { const err = ethers.errors.UNPREDICTABLE_GAS_LIMIT; signer.estimateGas = async () => { return Promise.reject(err); @@ -442,28 +442,53 @@ describe("Test find opp", async function () { oppBlockNumber: undefined, noneNodeError: errorSnapshot("", err), spanAttributes: { - // rp span attrs - "routeProcessor.full.stage": 1, - "routeProcessor.full.rawtx": rawtx, - "routeProcessor.full.isNodeError": false, - "routeProcessor.full.route": expectedRouteVisual, - "routeProcessor.full.blockNumber": oppBlockNumber, - "routeProcessor.full.error": errorSnapshot("", err), - "routeProcessor.full.amountIn": formatUnits(vaultBalance), - "routeProcessor.full.amountOut": formatUnits(getAmountOut(vaultBalance), 6), - "routeProcessor.full.marketPrice": formatUnits(getCurrentPrice(vaultBalance)), + routeProcessor: JSON.stringify({ + full: JSON.stringify({ + amountIn: formatUnits(vaultBalance), + amountOut: formatUnits(getAmountOut(vaultBalance), 6), + marketPrice: formatUnits(getCurrentPrice(vaultBalance)), + route: expectedRouteVisual, + blockNumber: oppBlockNumber, + stage: 1, + isNodeError: false, + error: errorSnapshot("", err), + rawtx: rawtx, + }), + }), + interOrderbook: JSON.stringify({ + againstOrderbooks: JSON.stringify({ + [opposingOrderbookAddress]: { + maxInput: vaultBalance.toString(), + blockNumber: oppBlockNumber, + stage: 1, + isNodeError: false, + error: errorSnapshot("", err), + rawtx: JSON.stringify(rawtx2, withBigintSerializer), + }, + }), + }), + // // rp span attrs + // "routeProcessor.full.stage": 1, + // "routeProcessor.full.rawtx": rawtx, + // "routeProcessor.full.isNodeError": false, + // "routeProcessor.full.route": expectedRouteVisual, + // "routeProcessor.full.blockNumber": oppBlockNumber, + // "routeProcessor.full.error": errorSnapshot("", err), + // "routeProcessor.full.amountIn": formatUnits(vaultBalance), + // "routeProcessor.full.amountOut": formatUnits(getAmountOut(vaultBalance), 6), + // "routeProcessor.full.marketPrice": formatUnits(getCurrentPrice(vaultBalance)), - // inter-ob span attrs - [`interOrderbook.againstOrderbooks.${opposingOrderbookAddress}.stage`]: 1, - [`interOrderbook.againstOrderbooks.${opposingOrderbookAddress}.isNodeError`]: false, - [`interOrderbook.againstOrderbooks.${opposingOrderbookAddress}.blockNumber`]: - oppBlockNumber, - [`interOrderbook.againstOrderbooks.${opposingOrderbookAddress}.rawtx`]: - JSON.stringify(rawtx2, withBigintSerializer), - [`interOrderbook.againstOrderbooks.${opposingOrderbookAddress}.maxInput`]: - vaultBalance.toString(), - [`interOrderbook.againstOrderbooks.${opposingOrderbookAddress}.error`]: - errorSnapshot("", err), + // // inter-ob span attrs + // [`interOrderbook.againstOrderbooks.${opposingOrderbookAddress}.stage`]: 1, + // [`interOrderbook.againstOrderbooks.${opposingOrderbookAddress}.isNodeError`]: false, + // [`interOrderbook.againstOrderbooks.${opposingOrderbookAddress}.blockNumber`]: + // oppBlockNumber, + // [`interOrderbook.againstOrderbooks.${opposingOrderbookAddress}.rawtx`]: + // JSON.stringify(rawtx2, withBigintSerializer), + // [`interOrderbook.againstOrderbooks.${opposingOrderbookAddress}.maxInput`]: + // vaultBalance.toString(), + // [`interOrderbook.againstOrderbooks.${opposingOrderbookAddress}.error`]: + // errorSnapshot("", err), }, }; assert.deepEqual(error, expected); diff --git a/test/mode-interOrderbook.test.js b/test/mode-interOrderbook.test.js index 64c57662..0ce878f9 100644 --- a/test/mode-interOrderbook.test.js +++ b/test/mode-interOrderbook.test.js @@ -338,13 +338,23 @@ describe("Test inter-orderbook find opp", async function () { }, reason: undefined, spanAttributes: { - [`againstOrderbooks.${opposingOrderbookAddress}.blockNumber`]: oppBlockNumber, - [`againstOrderbooks.${opposingOrderbookAddress}.stage`]: 1, - [`againstOrderbooks.${opposingOrderbookAddress}.isNodeError`]: false, - [`againstOrderbooks.${opposingOrderbookAddress}.error`]: errorSnapshot("", err), - [`againstOrderbooks.${opposingOrderbookAddress}.rawtx`]: JSON.stringify(rawtx), - [`againstOrderbooks.${opposingOrderbookAddress}.maxInput`]: - vaultBalance.toString(), + againstOrderbooks: JSON.stringify({ + [opposingOrderbookAddress]: { + maxInput: vaultBalance.toString(), + blockNumber: oppBlockNumber, + stage: 1, + isNodeError: false, + error: errorSnapshot("", err), + rawtx: JSON.stringify(rawtx), + }, + }), + // [`againstOrderbooks.${opposingOrderbookAddress}.blockNumber`]: oppBlockNumber, + // [`againstOrderbooks.${opposingOrderbookAddress}.stage`]: 1, + // [`againstOrderbooks.${opposingOrderbookAddress}.isNodeError`]: false, + // [`againstOrderbooks.${opposingOrderbookAddress}.error`]: errorSnapshot("", err), + // [`againstOrderbooks.${opposingOrderbookAddress}.rawtx`]: JSON.stringify(rawtx), + // [`againstOrderbooks.${opposingOrderbookAddress}.maxInput`]: + // vaultBalance.toString(), }, }; assert.deepEqual(error, expected); diff --git a/test/mode-intraOrderbook.test.js b/test/mode-intraOrderbook.test.js index d6186899..5bd3f206 100644 --- a/test/mode-intraOrderbook.test.js +++ b/test/mode-intraOrderbook.test.js @@ -336,11 +336,20 @@ describe("Test intra-orderbook find opp", async function () { }, reason: undefined, spanAttributes: { - "intraOrderbook.0.blockNumber": oppBlockNumber, - "intraOrderbook.0.stage": 1, - "intraOrderbook.0.isNodeError": false, - "intraOrderbook.0.error": errorSnapshot("", err), - "intraOrderbook.0.rawtx": JSON.stringify(rawtx), + intraOrderbook: [ + JSON.stringify({ + blockNumber: oppBlockNumber, + stage: 1, + isNodeError: false, + error: errorSnapshot("", err), + rawtx: JSON.stringify(rawtx), + }), + ], + // "intraOrderbook.0.blockNumber": oppBlockNumber, + // "intraOrderbook.0.stage": 1, + // "intraOrderbook.0.isNodeError": false, + // "intraOrderbook.0.error": errorSnapshot("", err), + // "intraOrderbook.0.rawtx": JSON.stringify(rawtx), }, }; assert.deepEqual(error, expected); diff --git a/test/mode-routeProcessor.test.js b/test/mode-routeProcessor.test.js index d662df0c..9786d789 100644 --- a/test/mode-routeProcessor.test.js +++ b/test/mode-routeProcessor.test.js @@ -476,15 +476,18 @@ describe("Test route processor find opp", async function () { }, reason: RouteProcessorDryrunHaltReason.NoOpportunity, spanAttributes: { - "full.amountIn": formatUnits(vaultBalance), - "full.amountOut": formatUnits(getAmountOut(vaultBalance), 6), - "full.marketPrice": formatUnits(getCurrentPrice(vaultBalance)), - "full.route": expectedRouteVisual, - "full.blockNumber": oppBlockNumber, - "full.stage": 1, - "full.isNodeError": false, - "full.error": errorSnapshot("", ethers.errors.UNPREDICTABLE_GAS_LIMIT), - "full.rawtx": rawtx, + // full: `{"amountIn":"${formatUnits(vaultBalance)}","amountOut":"${formatUnits(getAmountOut(vaultBalance), 6)}","marketPrice":"${formatUnits(getCurrentPrice(vaultBalance))}","route":${JSON.stringify(expectedRouteVisual)},"blockNumber":${oppBlockNumber},"stage":1,"isNodeError":false,"error":${JSON.stringify(errorSnapshot("", ethers.errors.UNPREDICTABLE_GAS_LIMIT))},"rawtx":${JSON.stringify(rawtx)}}`, + full: JSON.stringify({ + amountIn: formatUnits(vaultBalance), + amountOut: formatUnits(getAmountOut(vaultBalance), 6), + marketPrice: formatUnits(getCurrentPrice(vaultBalance)), + route: expectedRouteVisual, + blockNumber: oppBlockNumber, + stage: 1, + isNodeError: false, + error: errorSnapshot("", ethers.errors.UNPREDICTABLE_GAS_LIMIT), + rawtx: rawtx, + }), }, }; assert.deepEqual(error, expected); @@ -515,8 +518,11 @@ describe("Test route processor find opp", async function () { value: undefined, reason: RouteProcessorDryrunHaltReason.NoRoute, spanAttributes: { - "full.amountIn": formatUnits(vaultBalance), - "full.route": "no-way", + // full: `{"amountIn":"${formatUnits(vaultBalance)}","route":"no-way"}`, + full: JSON.stringify({ + amountIn: formatUnits(vaultBalance), + route: "no-way", + }), }, }; assert.deepEqual(error, expected); @@ -681,15 +687,18 @@ describe("Test find opp with retries", async function () { }, reason: RouteProcessorDryrunHaltReason.NoOpportunity, spanAttributes: { - "full.amountIn": formatUnits(vaultBalance), - "full.amountOut": formatUnits(getAmountOut(vaultBalance), 6), - "full.marketPrice": formatUnits(getCurrentPrice(vaultBalance)), - "full.route": expectedRouteVisual, - "full.blockNumber": oppBlockNumber, - "full.stage": 1, - "full.isNodeError": false, - "full.error": errorSnapshot("", ethers.errors.UNPREDICTABLE_GAS_LIMIT), - "full.rawtx": rawtx, + // full: `{"amountIn":"${formatUnits(vaultBalance)}","amountOut":"${formatUnits(getAmountOut(vaultBalance), 6)}","marketPrice":"${formatUnits(getCurrentPrice(vaultBalance))}","route":${JSON.stringify(expectedRouteVisual)},"blockNumber":${oppBlockNumber},"stage":1,"isNodeError":false,"error":${JSON.stringify(errorSnapshot("", ethers.errors.UNPREDICTABLE_GAS_LIMIT))},"rawtx":${JSON.stringify(rawtx)}}`, + full: JSON.stringify({ + amountIn: formatUnits(vaultBalance), + amountOut: formatUnits(getAmountOut(vaultBalance), 6), + marketPrice: formatUnits(getCurrentPrice(vaultBalance)), + route: expectedRouteVisual, + blockNumber: oppBlockNumber, + stage: 1, + isNodeError: false, + error: errorSnapshot("", ethers.errors.UNPREDICTABLE_GAS_LIMIT), + rawtx: rawtx, + }), }, }; assert.deepEqual(error, expected);