diff --git a/.changeset/silver-gifts-chew.md b/.changeset/silver-gifts-chew.md new file mode 100644 index 00000000..752ee864 --- /dev/null +++ b/.changeset/silver-gifts-chew.md @@ -0,0 +1,5 @@ +--- +'@3loop/transaction-decoder': patch +--- + +Update ABI strategy errors and log levels diff --git a/packages/transaction-decoder/src/abi-loader.ts b/packages/transaction-decoder/src/abi-loader.ts index d30db654..efa92bf6 100644 --- a/packages/transaction-decoder/src/abi-loader.ts +++ b/packages/transaction-decoder/src/abi-loader.ts @@ -202,7 +202,7 @@ export const AbiLoaderRequestResolver = RequestResolver.makeBatched((requests: A strategyId: 'address-batch', }) .pipe( - Effect.tapError(Effect.logWarning), + Effect.tapError(Effect.logDebug), Effect.orElseSucceed(() => null), Effect.map((result) => (result ? Either.left(result) : Either.right(req))), ) @@ -234,7 +234,7 @@ export const AbiLoaderRequestResolver = RequestResolver.makeBatched((requests: A strategyId: 'fragment-batch', }) .pipe( - Effect.tapError(Effect.logWarning), + Effect.tapError(Effect.logDebug), Effect.orElseSucceed(() => null), ) // If no strategies found, return null }, diff --git a/packages/transaction-decoder/src/abi-strategy/blockscout-abi.ts b/packages/transaction-decoder/src/abi-strategy/blockscout-abi.ts index 7f300b54..dc0a4be1 100644 --- a/packages/transaction-decoder/src/abi-strategy/blockscout-abi.ts +++ b/packages/transaction-decoder/src/abi-strategy/blockscout-abi.ts @@ -91,7 +91,9 @@ export const BlockscoutStrategyResolver = (config: { ), ) } else { - return yield* Effect.fail(new RequestModel.ResolveStrategyABIError('Blockscout', req.address, req.chainId)) + return yield* Effect.fail( + new RequestModel.ResolveStrategyABIError('Blockscout', req.address, req.chainId, String(result.cause)), + ) } }), 'AbiStrategy.BlockscoutStrategyResolver', diff --git a/packages/transaction-decoder/src/abi-strategy/etherscan-abi.ts b/packages/transaction-decoder/src/abi-strategy/etherscan-abi.ts index e1118975..ee8ee437 100644 --- a/packages/transaction-decoder/src/abi-strategy/etherscan-abi.ts +++ b/packages/transaction-decoder/src/abi-strategy/etherscan-abi.ts @@ -136,7 +136,9 @@ export const EtherscanStrategyResolver = (config?: { ), ) } else { - return yield* Effect.fail(new RequestModel.ResolveStrategyABIError('etherscan', req.address, req.chainId)) + return yield* Effect.fail( + new RequestModel.ResolveStrategyABIError('etherscan', req.address, req.chainId, String(result.cause)), + ) } }), 'AbiStrategy.EtherscanStrategyResolver', diff --git a/packages/transaction-decoder/src/abi-strategy/etherscanv2-abi.ts b/packages/transaction-decoder/src/abi-strategy/etherscanv2-abi.ts index 335c4df7..d24da861 100644 --- a/packages/transaction-decoder/src/abi-strategy/etherscanv2-abi.ts +++ b/packages/transaction-decoder/src/abi-strategy/etherscanv2-abi.ts @@ -99,7 +99,9 @@ export const EtherscanV2StrategyResolver = (config?: { ), ) } else { - return yield* Effect.fail(new RequestModel.ResolveStrategyABIError('etherscanV2', req.address, req.chainId)) + return yield* Effect.fail( + new RequestModel.ResolveStrategyABIError('etherscanV2', req.address, req.chainId, String(result.cause)), + ) } }), 'AbiStrategy.EtherscanV2StrategyResolver', diff --git a/packages/transaction-decoder/src/abi-strategy/experimental-erc20.ts b/packages/transaction-decoder/src/abi-strategy/experimental-erc20.ts index b8c94c83..ddb8e8e8 100644 --- a/packages/transaction-decoder/src/abi-strategy/experimental-erc20.ts +++ b/packages/transaction-decoder/src/abi-strategy/experimental-erc20.ts @@ -6,13 +6,15 @@ import { erc20Abi, getAddress, getContract } from 'viem' const getLocalFragments = (service: PublicClient, { address, chainId }: RequestModel.GetContractABIStrategyParams) => Effect.gen(function* () { if (!address) - return yield* Effect.fail(new RequestModel.ResolveStrategyABIError('local-strategy', address, chainId)) + return yield* Effect.fail( + new RequestModel.ResolveStrategyABIError('local-strategy', address, chainId, 'Address is required'), + ) const client = yield* service .getPublicClient(chainId) .pipe( - Effect.catchAll(() => - Effect.fail(new RequestModel.ResolveStrategyABIError('local-strategy', address, chainId)), + Effect.catchAll((e) => + Effect.fail(new RequestModel.ResolveStrategyABIError('local-strategy', address, chainId, String(e))), ), ) @@ -23,14 +25,12 @@ const getLocalFragments = (service: PublicClient, { address, chainId }: RequestM address: getAddress(address), client: client.client, }), - catch: () => { - throw new RequestModel.ResolveStrategyABIError('local-strategy', address, chainId) - }, + catch: (e) => new RequestModel.ResolveStrategyABIError('local-strategy', address, chainId, String(e)), }) const decimals = yield* Effect.tryPromise({ try: () => inst.read.decimals(), - catch: () => new RequestModel.ResolveStrategyABIError('local-strategy', address, chainId), + catch: (e) => new RequestModel.ResolveStrategyABIError('local-strategy', address, chainId, String(e)), }) if (decimals != null) { diff --git a/packages/transaction-decoder/src/abi-strategy/fourbyte-abi.ts b/packages/transaction-decoder/src/abi-strategy/fourbyte-abi.ts index 6039ed76..1bdc9405 100644 --- a/packages/transaction-decoder/src/abi-strategy/fourbyte-abi.ts +++ b/packages/transaction-decoder/src/abi-strategy/fourbyte-abi.ts @@ -119,7 +119,12 @@ export const FourByteStrategyResolver = (): RequestModel.ContractAbiResolverStra ) } else { return yield* Effect.fail( - new RequestModel.ResolveStrategyABIError('4byte.directory', req.address, req.chainId), + new RequestModel.ResolveStrategyABIError( + '4byte.directory', + req.address, + req.chainId, + String(result.cause), + ), ) } }), diff --git a/packages/transaction-decoder/src/abi-strategy/openchain-abi.ts b/packages/transaction-decoder/src/abi-strategy/openchain-abi.ts index 950dcc7b..f0e900dd 100644 --- a/packages/transaction-decoder/src/abi-strategy/openchain-abi.ts +++ b/packages/transaction-decoder/src/abi-strategy/openchain-abi.ts @@ -136,7 +136,9 @@ export const OpenchainStrategyResolver = (): RequestModel.ContractAbiResolverStr ), ) } else { - return yield* Effect.fail(new RequestModel.ResolveStrategyABIError('openchain', req.address, req.chainId)) + return yield* Effect.fail( + new RequestModel.ResolveStrategyABIError('openchain', req.address, req.chainId, String(result.cause)), + ) } }), 'AbiStrategy.OpenchainStrategyResolver', diff --git a/packages/transaction-decoder/src/abi-strategy/request-model.ts b/packages/transaction-decoder/src/abi-strategy/request-model.ts index 1b602fb9..ff1befd4 100644 --- a/packages/transaction-decoder/src/abi-strategy/request-model.ts +++ b/packages/transaction-decoder/src/abi-strategy/request-model.ts @@ -1,4 +1,4 @@ -import { Effect, RateLimiter } from 'effect' +import { Data, Effect, RateLimiter } from 'effect' export interface FetchABIParams { readonly chainID: number @@ -7,25 +7,35 @@ export interface FetchABIParams { readonly signature?: string | undefined } -export class ResolveStrategyABIError { - readonly _tag = 'ResolveStrategyABIError' - constructor( - readonly resolverName: string, - readonly address: string, - readonly chain: number, - ) {} +export class ResolveStrategyABIError extends Data.TaggedError('ResolveStrategyABIError')<{ + resolver: string + address: string + chainID: number + message: string +}> { + constructor(resolver: string, address: string, chainID: number, message: string) { + super({ resolver, address, chainID, message }) + } } -export class MissingABIStrategyError { - readonly _tag = 'MissingABIStrategyError' +export class MissingABIStrategyError extends Data.TaggedError('MissingABIStrategyError')<{ + address: string + chainId: number + strategyId: string + event?: string + signature?: string + message: string +}> { constructor( - readonly address: string, - readonly chainId: number, - readonly strategyId: string, - readonly event?: string, - readonly signature?: string, - readonly message: string = 'Missing contract ABI', - ) {} + address: string, + chainId: number, + strategyId: string, + event?: string, + signature?: string, + message = 'Missing contract ABI', + ) { + super({ address, chainId, strategyId, event, signature, message }) + } } interface FunctionFragmentABI { diff --git a/packages/transaction-decoder/src/abi-strategy/sourcify-abi.ts b/packages/transaction-decoder/src/abi-strategy/sourcify-abi.ts index 799a44da..9e096398 100644 --- a/packages/transaction-decoder/src/abi-strategy/sourcify-abi.ts +++ b/packages/transaction-decoder/src/abi-strategy/sourcify-abi.ts @@ -96,7 +96,9 @@ export const SourcifyStrategyResolver = (): RequestModel.ContractAbiResolverStra ), ) } else { - return yield* Effect.fail(new RequestModel.ResolveStrategyABIError('sourcify', req.address, req.chainId)) + return yield* Effect.fail( + new RequestModel.ResolveStrategyABIError('sourcify', req.address, req.chainId, String(result.cause)), + ) } }), 'AbiStrategy.SourcifyStrategyResolver', diff --git a/packages/transaction-decoder/src/abi-strategy/strategy-executor.ts b/packages/transaction-decoder/src/abi-strategy/strategy-executor.ts index 34b481aa..dc54abbb 100644 --- a/packages/transaction-decoder/src/abi-strategy/strategy-executor.ts +++ b/packages/transaction-decoder/src/abi-strategy/strategy-executor.ts @@ -21,7 +21,7 @@ export const make = (circuitBreaker: CircuitBreaker, requestPool: RequestPool) = Effect.catchTag('MissingABIStrategyError', (error) => { // Log error but don't fail the entire operation return Effect.gen(function* () { - yield* Effect.logWarning(`Strategy ${strategy.id} found no ABI: ${error.message}`) + yield* Effect.logDebug(`Strategy ${strategy.id} found no ABI: ${error.message}`) return yield* Effect.succeed(error) }) }), diff --git a/packages/transaction-decoder/src/contract-meta-loader.ts b/packages/transaction-decoder/src/contract-meta-loader.ts index 7432e59a..d32b08a5 100644 --- a/packages/transaction-decoder/src/contract-meta-loader.ts +++ b/packages/transaction-decoder/src/contract-meta-loader.ts @@ -150,7 +150,7 @@ const ContractMetaLoaderRequestResolver = RequestResolver.makeBatched((requests: strategyId: 'meta-batch', }) .pipe( - Effect.tapError(Effect.logWarning), + Effect.tapError(Effect.logDebug), Effect.orElseSucceed(() => null), ) }, diff --git a/packages/transaction-decoder/src/meta-strategy/strategy-executor.ts b/packages/transaction-decoder/src/meta-strategy/strategy-executor.ts index ebc59136..0d29cc0e 100644 --- a/packages/transaction-decoder/src/meta-strategy/strategy-executor.ts +++ b/packages/transaction-decoder/src/meta-strategy/strategy-executor.ts @@ -34,7 +34,7 @@ export const make = (circuitBreaker: CircuitBreaker, requestPool: RequestPool) = // Treate MissingMetaError as a success for circuit breaker Effect.catchTag('MissingMetaError', (error) => { return Effect.gen(function* () { - yield* Effect.logWarning(`Meta strategy ${strategy.id} found no metadata: ${error.message}`) + yield* Effect.logDebug(`Meta strategy ${strategy.id} found no metadata: ${error.message}`) return yield* Effect.succeed(error) }) }),