Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .changeset/fuzzy-mugs-explode.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
'@3loop/transaction-interpreter': patch
'@3loop/transaction-decoder': patch
---

Update typescript config, compilation and fix type inference
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -34,3 +34,5 @@ yarn-error.log*

# vercel
.vercel

*.tsbuildinfo
2 changes: 1 addition & 1 deletion apps/docs/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
"@astrojs/starlight": "^0.21.5",
"astro": "^4.15.2",
"sharp": "^0.33.5",
"typescript": "5.1.3"
"typescript": "5.7.2"
},
"devDependencies": {
"@typescript-eslint/parser": "^5.62.0",
Expand Down
2 changes: 1 addition & 1 deletion apps/web/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@
},
"devDependencies": {
"bufferutil": "^4.0.8",
"typescript": "5.1.3",
"typescript": "5.7.3",
"utf-8-validate": "^6.0.4"
}
}
2 changes: 1 addition & 1 deletion apps/web/src/app/calldata/types.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { DecodeResult } from '@3loop/transaction-decoder'
import type { DecodeResult } from '@3loop/transaction-decoder'

export interface CalldataParams {
data: string
Expand Down
14 changes: 11 additions & 3 deletions apps/web/tsconfig.json
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
{
"extends": "tsconfig/nextjs.json",
"compilerOptions": {
"strict": true,
"target": "ES2015",
"isolatedModules": true,
"downlevelIteration": true,
"exactOptionalPropertyTypes": false,
Expand All @@ -14,7 +12,17 @@
"paths": {
"@/*": ["./src/*"],
"@3loop/transaction-decoder/*": ["../../packages/transaction-decoder/dist/*"]
}
},
"lib": ["dom", "dom.iterable", "esnext"],
"allowJs": true,
"skipLibCheck": true,
"noEmit": true,
"incremental": true,
"esModuleInterop": true,
"module": "esnext",
"moduleResolution": "node",
"resolveJsonModule": true,
"jsx": "preserve"
},
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"],
"exclude": ["node_modules"]
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,9 @@
},
"devDependencies": {
"@changesets/cli": "^2.26.2",
"@effect/language-service": "^0.1.0",
"eslint": "^8.47.0",
"prettier": "^3.0.2",
"tsconfig": "workspace:*",
"turbo": "2.1.1"
},
"packageManager": "pnpm@9.9.0",
Expand Down
2 changes: 1 addition & 1 deletion packages/transaction-decoder/.eslintignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/dist
jest.config.js
*.d.ts
*.tsbuildinfo
/example
31 changes: 10 additions & 21 deletions packages/transaction-decoder/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,40 +8,28 @@
"license": "GPL-3.0-only",
"type": "module",
"exports": {
"./dist/**/*.d.ts": "./dist/**/*.d.ts",
".": {
"require": "./dist/index.cjs",
"import": "./dist/index.js",
"types": "./dist/index.d.ts"
},
"./in-memory": {
"import": {
"types": "./dist/in-memory/index.d.ts",
"default": "./dist/in-memory/index.js"
},
"require": {
"types": "./dist/in-memory/index.d.cts",
"default": "./dist/in-memory/index.cjs"
},
"types": "./dist/in-memory/index.d.ts",
"default": "./dist/in-memory/index.js"
"require": "./dist/in-memory/index.cjs",
"import": "./dist/in-memory/index.js"
},
"./sql": {
"import": {
"types": "./dist/sql/index.d.ts",
"default": "./dist/sql/index.js"
},
"require": {
"types": "./dist/sql/index.d.cts",
"default": "./dist/sql/index.cjs"
},
"types": "./dist/sql/index.d.ts",
"default": "./dist/sql/index.js"
"require": "./dist/sql/index.cjs",
"import": "./dist/sql/index.js"
}
},
"scripts": {
"dev": "tsup --watch",
"coverage": "vitest run --config ./vitest.config.mts --coverage",
"build": "rm -rf dist && tsup",
"build:types": "tsc -b ./tsconfig.types.json",
"build": "rimraf dist && rimraf *.tsbuildinfo && tsup && pnpm run build:types",
"check": "tsc --noEmit",
"lint": "eslint --exit-on-fatal-error --ignore-path .eslintignore --ext .ts .",
"fix": "eslint --ignore-path .eslintignore --ext .ts . --fix",
Expand All @@ -65,6 +53,7 @@
}
},
"devDependencies": {
"@swc/core": "^1.11.5",
"@total-typescript/ts-reset": "^0.5.1",
"@types/node": "^20.16.3",
"@typescript-eslint/eslint-plugin": "^5.62.0",
Expand All @@ -77,10 +66,10 @@
"glob": "^11.0.0",
"prettier": "^2.8.8",
"quickjs-emscripten": "^0.29.2",
"rimraf": "^6.0.1",
"ts-node": "^10.9.2",
"tsconfig": "workspace:*",
"tsup": "^7.2.0",
"typescript": "5.1.3",
"typescript": "5.7.3",
"viem": "^2.23.2",
"vite": "4.4.9",
"vite-tsconfig-paths": "4.2.0",
Expand Down
16 changes: 8 additions & 8 deletions packages/transaction-decoder/src/abi-loader.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { Effect, Either, RequestResolver, Request, Array, pipe, Data, PrimaryKey, Schema, SchemaAST } from 'effect'
import { ContractABI } from './abi-strategy/request-model.js'
import { Abi } from 'viem'
import { AbiParams, AbiStore } from './abi-store.js'
import * as AbiStore from './abi-store.js'

interface LoadParameters {
readonly chainID: number
Expand Down Expand Up @@ -49,9 +49,9 @@ function makeRequestKey(key: AbiLoader) {
return `abi::${key.chainID}:${key.address}:${key.event}:${key.signature}`
}

const getMany = (requests: Array<AbiParams>) =>
const getMany = (requests: Array<AbiStore.AbiParams>) =>
Effect.gen(function* () {
const { getMany, get } = yield* AbiStore
const { getMany, get } = yield* AbiStore.AbiStore

if (getMany != null) {
return yield* getMany(requests)
Expand All @@ -68,7 +68,7 @@ const getMany = (requests: Array<AbiParams>) =>

const setValue = (key: AbiLoader, abi: ContractABI | null) =>
Effect.gen(function* () {
const { set } = yield* AbiStore
const { set } = yield* AbiStore.AbiStore
yield* set(
{
chainID: key.chainID,
Expand Down Expand Up @@ -128,12 +128,12 @@ const getBestMatch = (abi: ContractABI | null) => {
const AbiLoaderRequestResolver: Effect.Effect<
RequestResolver.RequestResolver<AbiLoader, never>,
never,
AbiStore
AbiStore.AbiStore
> = RequestResolver.makeBatched((requests: Array<AbiLoader>) =>
Effect.gen(function* () {
if (requests.length === 0) return

const { strategies } = yield* AbiStore
const { strategies } = yield* AbiStore.AbiStore

const requestGroups = Array.groupBy(requests, makeRequestKey)
const uniqueRequests = Object.values(requestGroups).map((group) => group[0])
Expand Down Expand Up @@ -239,15 +239,15 @@ const AbiLoaderRequestResolver: Effect.Effect<
},
)
}),
).pipe(RequestResolver.contextFromServices(AbiStore), Effect.withRequestCaching(true))
).pipe(RequestResolver.contextFromServices(AbiStore.AbiStore), Effect.withRequestCaching(true))

// TODO: When failing to decode with one ABI, we should retry with other resolved ABIs
// We can decode with Effect.validateFirst(abis, (abi) => decodeMethod(input as Hex, abi)) and to find the first ABIs
// that decodes successfully. We might enforce a sorted array to prioritize the address match. We will have to think
// how to handle the strategy resolver in this case. Currently, we stop at first successful strategy, which might result
// in a missing Fragment. We treat this issue as a minor one for now, as we epect it to occur rarely on contracts that
// are not verified and with a non standard events structure.
export const getAndCacheAbi = (params: AbiParams) =>
export const getAndCacheAbi = (params: AbiStore.AbiParams) =>
Effect.gen(function* () {
if (params.event === '0x' || params.signature === '0x') {
return yield* Effect.fail(new EmptyCalldataError(params))
Expand Down
10 changes: 5 additions & 5 deletions packages/transaction-decoder/src/contract-meta-loader.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { ContractData } from './types.js'
import { GetContractMetaStrategy } from './meta-strategy/request-model.js'
import { Address } from 'viem'
import { ZERO_ADDRESS } from './decoding/constants.js'
import { ContractMetaStore } from './contract-meta-store.js'
import * as ContractMetaStore from './contract-meta-store.js'

class SchemaContractData extends Schema.make<ContractData>(SchemaAST.objectKeyword) {}
class SchemaAddress extends Schema.make<Address>(SchemaAST.stringKeyword) {}
Expand All @@ -27,7 +27,7 @@ function makeKey(key: ContractMetaLoader) {

const getMany = (requests: Array<ContractMetaLoader>) =>
Effect.gen(function* () {
const { getMany, get } = yield* ContractMetaStore
const { getMany, get } = yield* ContractMetaStore.ContractMetaStore

if (getMany != null) {
return yield* getMany(requests)
Expand All @@ -44,7 +44,7 @@ const getMany = (requests: Array<ContractMetaLoader>) =>

const setValue = ({ chainID, address }: ContractMetaLoader, result: ContractData | null) =>
Effect.gen(function* () {
const { set } = yield* ContractMetaStore
const { set } = yield* ContractMetaStore.ContractMetaStore
if (result == null) return
// NOTE: Now when RPC fails if we store not-found it causes issues and not retries, for now we will just always retry
yield* set(
Expand Down Expand Up @@ -82,7 +82,7 @@ const setValue = ({ chainID, address }: ContractMetaLoader, result: ContractData
*/
const ContractMetaLoaderRequestResolver = RequestResolver.makeBatched((requests: Array<ContractMetaLoader>) =>
Effect.gen(function* () {
const { strategies } = yield* ContractMetaStore
const { strategies } = yield* ContractMetaStore.ContractMetaStore

const groups = Array.groupBy(requests, makeKey)
const uniqueRequests = Object.values(groups).map((group) => group[0])
Expand Down Expand Up @@ -149,7 +149,7 @@ const ContractMetaLoaderRequestResolver = RequestResolver.makeBatched((requests:
{ discard: true },
)
}),
).pipe(RequestResolver.contextFromServices(ContractMetaStore), Effect.withRequestCaching(true))
).pipe(RequestResolver.contextFromServices(ContractMetaStore.ContractMetaStore), Effect.withRequestCaching(true))

export const getAndCacheContractMeta = ({
chainID,
Expand Down
6 changes: 3 additions & 3 deletions packages/transaction-decoder/src/decoding/calldata-decode.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { TreeNode } from '../types.js'
import { PublicClient, RPCFetchError, UnknownNetwork } from '../public-client.js'
import { SAFE_MULTISEND_ABI, SAFE_MULTISEND_SIGNATURE } from './constants.js'
import { getProxyImplementation } from './proxies.js'
import { AbiStore } from '../abi-store.js'
import * as AbiStore from '../abi-store.js'

const callDataKeys = ['callData', 'data', '_data']
const addressKeys = ['to', 'target', '_target']
Expand All @@ -18,7 +18,7 @@ const decodeBytesRecursively = (
): Effect.Effect<
TreeNode,
AbiDecoder.DecodeError | MissingABIError | RPCFetchError | UnknownNetwork,
AbiStore | PublicClient
AbiStore.AbiStore | PublicClient
> =>
Effect.gen(function* () {
const isCallDataNode =
Expand Down Expand Up @@ -85,7 +85,7 @@ const decodeGnosisMultisendParams = (
): Effect.Effect<
TreeNode[],
AbiDecoder.DecodeError | MissingABIError | RPCFetchError | UnknownNetwork,
AbiStore | PublicClient
AbiStore.AbiStore | PublicClient
> =>
Effect.gen(function* () {
if (inputParams.length === 0) {
Expand Down
11 changes: 0 additions & 11 deletions packages/transaction-decoder/src/effect.ts

This file was deleted.

15 changes: 10 additions & 5 deletions packages/transaction-decoder/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
/**
* For compatibility with moduleResolution: node
* https://stackoverflow.com/questions/70296652/how-can-i-use-exports-in-package-json-for-nested-submodules-and-typescript
*/
export * from './effect.js'
export * from './abi-loader.js'
export * as AbiStore from './abi-store.js'
export * from './abi-strategy/index.js'
export * from './contract-meta-loader.js'
export * as ContractMetaStore from './contract-meta-store.js'
export * from './meta-strategy/index.js'
export * from './public-client.js'
export * from './transaction-decoder.js'
export * from './transaction-loader.js'
export * from './types.js'
export { DecodeError } from './decoding/abi-decode.js'
export * from './vanilla.js'
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { SqlClient } from '@effect/sql'
import { Effect, Layer } from 'effect'
import { ContractData } from '../effect.js'
import * as ContractMetaStore from '../contract-meta-store.js'
import { ContractData } from '../types.js'

export const make = (strategies: ContractMetaStore.ContractMetaStore['strategies']) =>
Layer.effect(
Expand Down
2 changes: 1 addition & 1 deletion packages/transaction-decoder/test/mocks/abi-loader-mock.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
import { Effect, Match } from 'effect'
import fs from 'node:fs'
import * as AbiStore from '../../src/abi-store.js'
import { FourByteStrategyResolver } from '../../src/effect.js'
import { FourByteStrategyResolver } from '../../src/index.js'
import { EtherscanStrategyResolver } from '../../src/abi-strategy/index.js'

export const MockedAbiStoreLive = AbiStore.layer({
Expand Down
2 changes: 1 addition & 1 deletion packages/transaction-decoder/test/mocks/json-rpc-mock.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import fs from 'node:fs'
import { PublicClient, PublicClientObject, UnknownNetwork } from '../../src/effect.js'
import { PublicClient, PublicClientObject, UnknownNetwork } from '../../src/index.js'
import { Effect } from 'effect'
import { createPublicClient, custom } from 'viem'
import { PROXY_SLOTS, RPC, ZERO_SLOT } from '../constants.js'
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { describe, expect, test } from 'vitest'
import { Effect, Layer, pipe } from 'effect'
import { decodeTransactionByHash, decodeCalldata } from '../src/effect.js'
import { decodeTransactionByHash, decodeCalldata } from '../src/index.js'
import { PublicClient } from '../src/public-client.js'
import { MockedRPCProvider, MockedTransaction } from './mocks/json-rpc-mock.js'
import { CALLDATA_TRANSACTIONS, FAILED_TRANSACTIONS, TEST_TRANSACTIONS } from './constants.js'
Expand Down
2 changes: 1 addition & 1 deletion packages/transaction-decoder/test/vanilla.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { TransactionDecoder } from '../src/vanilla.js'
import fs from 'fs'
import { createPublicClient } from 'viem'
import { goerli } from 'viem/chains'
import { ERC20RPCStrategyResolver } from '../src/effect.js'
import { ERC20RPCStrategyResolver } from '../src/index.js'
import { TEST_TRANSACTIONS } from './constants.js'

describe('Transaction Decoder', () => {
Expand Down
15 changes: 2 additions & 13 deletions packages/transaction-decoder/tsconfig.build.json
Original file line number Diff line number Diff line change
@@ -1,19 +1,8 @@
{
"extends": "tsconfig/universal-esm.json",
"extends": ["../../tsconfig.base.json"],
"compilerOptions": {
"outDir": "dist",
"allowJs": true,
"baseUrl": ".",
"isolatedModules": true,
"stripInternal": true,
"noErrorTruncation": true,
"target": "es2016",
"module": "commonjs",
"esModuleInterop": true,
"forceConsistentCasingInFileNames": true,
"skipLibCheck": true,
"noEmit": true
},
"include": ["src"],
"include": ["src/**/*"],
"exclude": ["dist", "example", "node_modules"]
}
2 changes: 1 addition & 1 deletion packages/transaction-decoder/tsconfig.json
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
{
"extends": "./tsconfig.build.json",
"extends": ["../../tsconfig.base.json"],
"include": ["src/**/*", "test/**/*", "examples/**/*", "tsup.config.ts"]
}
11 changes: 11 additions & 0 deletions packages/transaction-decoder/tsconfig.types.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"extends": ["../../tsconfig.base.json"],
"compilerOptions": {
"rootDir": "src",
"emitDeclarationOnly": true,
"noEmit": false,
"sourceMap": false,
"outDir": "dist/"
},
"include": ["src/**/*"]
}
Loading
Loading