Skip to content

Commit

Permalink
refactor: generics
Browse files Browse the repository at this point in the history
  • Loading branch information
tmm committed Aug 31, 2023
1 parent b76b727 commit 00d038b
Show file tree
Hide file tree
Showing 6 changed files with 357 additions and 10 deletions.
37 changes: 28 additions & 9 deletions src/actions/public/readContract.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,10 @@ import type { Transport } from '../../clients/transports/createTransport.js'
import type { BaseError } from '../../errors/base.js'
import type { Chain } from '../../types/chain.js'
import type {
ContractFunctionConfig,
ContractFunctionResult,
ContractFunctionArgs,
ContractFunctionName,
ContractFunctionParameters,
ContractFunctionReturnType,
} from '../../types/contract.js'
import {
type DecodeFunctionResultParameters,
Expand All @@ -22,14 +24,30 @@ import { type CallParameters, call } from './call.js'

export type ReadContractParameters<
TAbi extends Abi | readonly unknown[] = Abi,
TFunctionName extends string = string,
TFunctionName extends ContractFunctionName<
TAbi,
'pure' | 'view'
> = ContractFunctionName<TAbi, 'pure' | 'view'>,
TArgs extends ContractFunctionArgs<
TAbi,
'pure' | 'view',
TFunctionName
> = ContractFunctionArgs<TAbi, 'pure' | 'view', TFunctionName>,
> = Pick<CallParameters, 'account' | 'blockNumber' | 'blockTag'> &
ContractFunctionConfig<TAbi, TFunctionName, 'view' | 'pure'>
ContractFunctionParameters<TAbi, 'pure' | 'view', TFunctionName, TArgs>

export type ReadContractReturnType<
TAbi extends Abi | readonly unknown[] = Abi,
TFunctionName extends string = string,
> = ContractFunctionResult<TAbi, TFunctionName>
TFunctionName extends ContractFunctionName<
TAbi,
'pure' | 'view'
> = ContractFunctionName<TAbi, 'pure' | 'view'>,
TArgs extends ContractFunctionArgs<
TAbi,
'pure' | 'view',
TFunctionName
> = ContractFunctionArgs<TAbi, 'pure' | 'view', TFunctionName>,
> = ContractFunctionReturnType<TAbi, 'pure' | 'view', TFunctionName, TArgs>

/**
* Calls a read-only function on a contract, and returns the response.
Expand Down Expand Up @@ -65,7 +83,8 @@ export type ReadContractReturnType<
export async function readContract<
TChain extends Chain | undefined,
const TAbi extends Abi | readonly unknown[],
TFunctionName extends string,
TFunctionName extends ContractFunctionName<TAbi, 'pure' | 'view'>,
TArgs extends ContractFunctionArgs<TAbi, 'pure' | 'view', TFunctionName>,
>(
client: Client<Transport, TChain>,
{
Expand All @@ -74,8 +93,8 @@ export async function readContract<
args,
functionName,
...callRequest
}: ReadContractParameters<TAbi, TFunctionName>,
): Promise<ReadContractReturnType<TAbi, TFunctionName>> {
}: ReadContractParameters<TAbi, TFunctionName, TArgs>,
): Promise<ReadContractReturnType<TAbi, TFunctionName, TArgs>> {
const calldata = encodeFunctionData({
abi,
args,
Expand Down
5 changes: 5 additions & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -562,6 +562,11 @@ export type {
InferEventName,
InferFunctionName,
InferItemName,
///
ContractFunctionName,
ContractFunctionArgs,
ContractFunctionParameters,
ContractFunctionReturnType,
} from './types/contract.js'
export type {
AccessList,
Expand Down
123 changes: 122 additions & 1 deletion src/types/contract.test-d.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,16 @@
import type { Abi, ResolvedConfig } from 'abitype'
import { type Abi, type Address, type ResolvedConfig, parseAbi } from 'abitype'
import type { seaportAbi } from 'abitype/test'
import { expectTypeOf, test } from 'vitest'

import type {
AbiEventParameterToPrimitiveType,
AbiEventParametersToPrimitiveTypes,
AbiEventTopicToPrimitiveType,
ContractFunctionArgs,
ContractFunctionConfig,
ContractFunctionName,
ContractFunctionResult,
ContractFunctionReturnType,
GetConstructorArgs,
GetErrorArgs,
GetEventArgs,
Expand All @@ -19,6 +22,7 @@ import type {
InferFunctionName,
InferItemName,
LogTopicType,
Widen,
} from './contract.js'
import type { Hex } from './misc.js'

Expand Down Expand Up @@ -525,3 +529,120 @@ test('AbiEventParametersToPrimitiveTypes', () => {
| readonly [string | string[] | null, number | number[] | null]
>()
})

test('ContractFunctionName', () => {
expectTypeOf<ContractFunctionName<typeof seaportAbi>>().toEqualTypeOf<
| 'cancel'
| 'fulfillBasicOrder'
| 'fulfillBasicOrder_efficient_6GL6yc'
| 'fulfillOrder'
| 'fulfillAdvancedOrder'
| 'fulfillAvailableOrders'
| 'fulfillAvailableAdvancedOrders'
| 'getContractOffererNonce'
| 'getOrderHash'
| 'getOrderStatus'
| 'getCounter'
| 'incrementCounter'
| 'information'
| 'name'
| 'matchAdvancedOrders'
| 'matchOrders'
| 'validate'
>()

expectTypeOf<
ContractFunctionName<typeof seaportAbi, 'pure' | 'view'>
>().toEqualTypeOf<
| 'name'
| 'getContractOffererNonce'
| 'getCounter'
| 'getOrderHash'
| 'getOrderStatus'
| 'information'
>()
})

test('ContractFunctionArgs', () => {
expectTypeOf<
ContractFunctionArgs<typeof seaportAbi, 'pure' | 'view', 'getOrderStatus'>
>().toEqualTypeOf<readonly [Address]>()

const abi = parseAbi([
'function foo() view returns (int8)',
'function foo(address) view returns (string)',
'function foo(address, address) view returns ((address foo, address bar))',
'function bar() view returns (int8)',
])
expectTypeOf<
ContractFunctionArgs<typeof abi, 'pure' | 'view', 'foo'>
>().toEqualTypeOf<
readonly [] | readonly [Address] | readonly [Address, Address]
>()
})

test('Widen', () => {
expectTypeOf<Widen<1>>().toEqualTypeOf<number>()
expectTypeOf<Widen<1n>>().toEqualTypeOf<bigint>()
expectTypeOf<Widen<true>>().toEqualTypeOf<boolean>()
expectTypeOf<Widen<'foo'>>().toEqualTypeOf<string>()
expectTypeOf<Widen<'0x123'>>().toEqualTypeOf<Address>()
expectTypeOf<Widen<'0xbytes'>>().toEqualTypeOf<
ResolvedConfig['BytesType']['inputs']
>()

expectTypeOf<Widen<[]>>().toEqualTypeOf<readonly []>()

expectTypeOf<Widen<{ foo: 'bar'; boo: 123n }>>().toEqualTypeOf<{
foo: string
boo: bigint
}>()
expectTypeOf<Widen<{ foo: 'bar'; boo: [123n] }>>().toEqualTypeOf<{
foo: string
boo: readonly [bigint]
}>()

expectTypeOf<Widen<[123n]>>().toEqualTypeOf<readonly [bigint]>()
expectTypeOf<Widen<[{ foo: 'bar'; boo: 123n }]>>().toEqualTypeOf<
readonly [{ foo: string; boo: bigint }]
>()

expectTypeOf<Widen<123n[]>>().toEqualTypeOf<readonly bigint[]>()
expectTypeOf<Widen<(123n | '0x')[]>>().toEqualTypeOf<
readonly (bigint | Address)[]
>()

expectTypeOf<Widen<readonly unknown[]>>().toEqualTypeOf<readonly unknown[]>()
})

test('ContractFunctionReturnType', () => {
const abi = parseAbi([
'function foo() view returns (int8)',
'function foo(address) view returns (string)',
'function foo(address, address) view returns ((address foo, address bar))',
'function bar() view returns (int8)',
])

expectTypeOf<
ContractFunctionReturnType<typeof abi, 'pure' | 'view', 'foo', readonly []>
>().toEqualTypeOf<number>()
expectTypeOf<
ContractFunctionReturnType<typeof abi, 'pure' | 'view', 'foo'>
>().toEqualTypeOf<number>()
expectTypeOf<
ContractFunctionReturnType<
typeof abi,
'pure' | 'view',
'foo',
readonly ['0x']
>
>().toEqualTypeOf<string>()
expectTypeOf<
ContractFunctionReturnType<
typeof abi,
'pure' | 'view',
'foo',
readonly ['0x', '0x']
>
>().toEqualTypeOf<{ foo: Address; bar: Address }>()
})
Loading

0 comments on commit 00d038b

Please sign in to comment.