Skip to content

Commit

Permalink
refactor(types): abi
Browse files Browse the repository at this point in the history
  • Loading branch information
tmm committed Nov 4, 2024
1 parent c3d364a commit ab1401b
Show file tree
Hide file tree
Showing 5 changed files with 127 additions and 30 deletions.
28 changes: 14 additions & 14 deletions scripts/docgen/render/apiFunction.ts
Original file line number Diff line number Diff line change
Expand Up @@ -355,20 +355,20 @@ function resolveReturnTypeForOverloads(options: {
overloads: string[]
returnType: Data['returnType']
}) {
const { dataLookup, overloads, returnType } = options

if (overloads.length && returnType) {
const overload = overloads.find(
(x) => dataLookup[x]?.returnType?.type !== returnType.type,
)
if (overload)
return (
dataLookup[overload]?.returnType?.type.replace(
/(<.*>)$/, // remove type params from type
'',
) ?? returnType.type
)
}
const { returnType } = options

// if (overloads.length && returnType) {
// const overload = overloads.find(
// (x) => dataLookup[x]?.returnType?.type !== returnType.type,
// )
// if (overload)
// return (
// dataLookup[overload]?.returnType?.type.replace(
// /(<.*>)$/, // remove type params from type
// '',
// ) ?? returnType.type
// )
// }

return returnType?.type
}
Expand Down
29 changes: 18 additions & 11 deletions src/Abi.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
import * as abitype from 'abitype'
import type * as Errors from './Errors.js'
import * as internal from './internal/abi.js'
import type * as AbiItem_internal from './internal/abiItem.js'

/** Root type for an ABI. */
export type Abi = abitype.Abi

export function format<const abi extends Abi>(abi: abi): format.ReturnType<abi>
/**
* Formats an {@link ox#Abi.Abi} into a **Human Readable ABI**.
*
Expand Down Expand Up @@ -33,25 +35,34 @@ export type Abi = abitype.Abi
* // ^?
*
*
*
* ```
*
* @param abi - The ABI to format.
* @returns The formatted ABI.
*/
export function format<const abi extends Abi | readonly unknown[]>(
abi: abi | Abi | readonly unknown[],
): abitype.FormatAbi<abi> {
export function format(abi: Abi | readonly unknown[]): readonly string[]
export function format(abi: Abi | readonly unknown[]): readonly string[] {

Check failure on line 45 in src/Abi.ts

View workflow job for this annotation

GitHub Actions / Verify / Checks

Missing JSDoc comment
return abitype.formatAbi(abi) as never
}

export declare namespace format {
type ReturnType<abi extends Abi | readonly unknown[] = Abi> =
abitype.FormatAbi<abi>

type ErrorType = Errors.GlobalErrorType
}

format.parseError = (error: unknown) =>
/* v8 ignore next */
error as format.ErrorType

export function from<const abi extends Abi | readonly string[]>(
abi: abi &
(abi extends readonly string[]
? AbiItem_internal.Signatures<abi>
: unknown),
): from.ReturnType<abi>
/**
* Parses an arbitrary **JSON ABI** or **Human Readable ABI** into a typed {@link ox#Abi.Abi}.
*
Expand Down Expand Up @@ -129,14 +140,10 @@ format.parseError = (error: unknown) =>
* @param abi - The ABI to parse.
* @returns The typed ABI.
*/
export function from<
const abi extends Abi | readonly string[] | readonly unknown[],
>(
abi: (abi | Abi | readonly string[] | readonly unknown[]) &
(abi extends readonly string[] ? AbiItem_internal.Signatures<abi> : Abi),
): from.ReturnType<abi> {
if (typeof abi[0] === 'string') return abitype.parseAbi(abi as never)
return abi as never
export function from(abi: Abi | readonly string[]): Abi
export function from(abi: Abi | readonly string[]): Abi {

Check failure on line 144 in src/Abi.ts

View workflow job for this annotation

GitHub Actions / Verify / Checks

Missing JSDoc comment
if (internal.isSignatures(abi)) return abitype.parseAbi(abi)
return abi
}

export declare namespace from {
Expand Down
74 changes: 74 additions & 0 deletions src/_test/Abi.test-d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
import { Abi } from 'ox'
import { describe, expectTypeOf, test } from 'vitest'

describe('format', () => {
test('infers abi', () => {
const formatted = Abi.format(value)
expectTypeOf(formatted).toEqualTypeOf([
'function approve(address spender, uint256 amount) returns (bool)',
] as const)
})

test('not narrowable', () => {
const abi = {} as Abi.Abi
const formatted = Abi.format(abi)
expectTypeOf(formatted).toEqualTypeOf<readonly string[]>()
})

const value = [
{
type: 'function',
name: 'approve',
stateMutability: 'nonpayable',
inputs: [
{
name: 'spender',
type: 'address',
},
{
name: 'amount',
type: 'uint256',
},
],
outputs: [{ type: 'bool' }],
},
] as const
})

describe('from', () => {
test('infers abi', () => {
const abi = Abi.from(value)
expectTypeOf(abi).toEqualTypeOf(value)
})

test('from signatures', () => {
const abi = Abi.from([
'function approve(address spender, uint256 amount) returns (bool)',
])
expectTypeOf(abi).toEqualTypeOf(value)
})

test('not narrowable', () => {
const abi = Abi.from({} as Abi.Abi)
expectTypeOf(abi).toEqualTypeOf<Abi.Abi>()
})

const value = [
{
type: 'function',
name: 'approve',
stateMutability: 'nonpayable',
inputs: [
{
name: 'spender',
type: 'address',
},
{
name: 'amount',
type: 'uint256',
},
],
outputs: [{ type: 'bool' }],
},
] as const
})
15 changes: 10 additions & 5 deletions src/_test/Abi.test.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Abi } from 'ox'
import { describe, expect, test } from 'vitest'
import { describe, expect, expectTypeOf, test } from 'vitest'

describe('format', () => {
test('default', () => {
Expand All @@ -23,10 +23,15 @@ describe('format', () => {
])
const formatted = Abi.format(abi)
expect(formatted).toMatchInlineSnapshot(`
[
"function approve(address spender, uint256 amount) returns (bool)",
]
`)
[
"function approve(address spender, uint256 amount) returns (bool)",
]
`)
expectTypeOf(formatted).toEqualTypeOf<
readonly [
'function approve(address spender, uint256 amount) returns (bool)',
]
>()
})
})

Expand Down
11 changes: 11 additions & 0 deletions src/internal/abi.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import type * as Abi from '../Abi.js'

/** @internal */
export function isSignatures(
value: Abi.Abi | readonly string[],
): value is readonly string[] {
for (const item of value) {
if (typeof item !== 'string') return false
}
return true
}

0 comments on commit ab1401b

Please sign in to comment.