diff --git a/biome.json b/biome.json index 1e9b8b46..cdf4b896 100644 --- a/biome.json +++ b/biome.json @@ -22,7 +22,7 @@ "enabled": true, "formatWithErrors": false, "indentStyle": "space", - "indentSize": 2, + "indentWidth": 2, "lineWidth": 80 }, "linter": { @@ -36,20 +36,23 @@ "noUnusedVariables": "error" }, "complexity": { - "noForEach": "off" + "noForEach": "off", + "noBannedTypes": "off" }, "performance": { "noDelete": "off" }, "style": { "noNonNullAssertion": "off", - "useShorthandArrayType": "error" + "useShorthandArrayType": "error", + "noUselessElse": "off" }, "suspicious": { "noArrayIndexKey": "off", "noAssignInExpressions": "off", "noExplicitAny": "off", - "noRedeclare": "off" + "noRedeclare": "off", + "noConfusingVoidType": "off" } } }, diff --git a/bun.lockb b/bun.lockb index 6cc44e02..4f5bf9ff 100755 Binary files a/bun.lockb and b/bun.lockb differ diff --git a/examples/suave-web-demo/src/main.ts b/examples/suave-web-demo/src/main.ts index abeeb305..21fb9056 100644 --- a/examples/suave-web-demo/src/main.ts +++ b/examples/suave-web-demo/src/main.ts @@ -5,6 +5,7 @@ import flashbotsLogo from './flashbots_icon.svg' import { setupConnectButton, setupDripFaucetButton, setupSendBidButton } from './suave' import { Logo } from './components' import { custom, formatEther } from 'viem' +import { getSuaveWallet, getSuaveProvider } from 'viem/chains/utils' import { suaveRigil } from 'viem/chains' document.querySelector('#app')!.innerHTML = ` @@ -35,10 +36,15 @@ setupConnectButton(document.querySelector('#connect')!, console.error(err) alert(err.message) } - const suaveWallet = suaveRigil.newWallet({jsonRpcAccount: account, transport: custom(ethereum)}) + const suaveWallet = getSuaveWallet({jsonRpcAccount: account, transport: custom(ethereum)}) console.log(suaveWallet) - const suaveProvider = suaveRigil.newPublicClient(custom(ethereum)) + const suaveProvider = getSuaveProvider(custom(ethereum)) suaveProvider.getBalance({ address: account }).then((balance) => { + suaveProvider.getChainId().then((chainId) => { + if (chainId !== suaveRigil.id) { + alert(`wrong chain id. expected ${suaveRigil.id}, got ${chainId}`) + } + }) document.querySelector('#status-content')!.innerHTML = `

SUAVE-ETH balance: ${formatEther(balance)}

@@ -52,7 +58,7 @@ setupConnectButton(document.querySelector('#connect')!, console.error("error in setupSendBidButton", err) alert(err.message + (err as any).data) } - const suaveProvider = suaveRigil.newPublicClient(custom(ethereum)) + const suaveProvider = getSuaveProvider(custom(ethereum)) suaveProvider.getTransactionReceipt({hash: txHash}).then((receipt) => { console.log("receipt", receipt) document.querySelector('#status-content')!.innerHTML = ` @@ -84,6 +90,6 @@ ${JSON.stringify(receipt, (_, value) => console.error("error in setupDripFaucetButton", err) alert(err.message + (err as any).data) } - console.log("funded account", txHash) + console.log("funded account. txhash:", txHash) }) }) diff --git a/examples/suave-web-demo/src/suave.ts b/examples/suave-web-demo/src/suave.ts index f2294e5c..7e931846 100644 --- a/examples/suave-web-demo/src/suave.ts +++ b/examples/suave-web-demo/src/suave.ts @@ -2,6 +2,7 @@ import { Address, Hex, createPublicClient, createWalletClient, http } from 'viem import { privateKeyToAccount } from 'viem/accounts' import { suaveRigil, goerli } from "viem/chains" import { MevShareBid } from "../../suave/bids" +import { getSuaveWallet } from 'viem/chains/utils' // TODO: get this from .env // TODO: make zero-config script to generate .env (deploy contracts) @@ -19,7 +20,7 @@ const goerliProvider = createPublicClient({ transport: http(GOERLI_RPC_URL_HTTP), chain: goerli }) -const suaveAdminWallet = suaveRigil.newWallet({ +const suaveAdminWallet = getSuaveWallet({ privateKey: ADMIN_KEY, transport: http("http://localhost:8545"), }) diff --git a/examples/suave/bids/index.ts b/examples/suave/bids/index.ts index 34586a93..7b8a98c3 100644 --- a/examples/suave/bids/index.ts +++ b/examples/suave/bids/index.ts @@ -65,7 +65,7 @@ export class MevShareBid { return { to: this.mevShareContract, data: this.newBidCalldata(), - type: SuaveTxTypes.ConfidentialRequest, + type: '0x43', gas: 500000n, gasPrice: 1000000000n, chainId: this.chainId, diff --git a/examples/suave/index.ts b/examples/suave/index.ts index ac2f9d9e..955e4da9 100644 --- a/examples/suave/index.ts +++ b/examples/suave/index.ts @@ -3,6 +3,8 @@ import { http, Address, Hex, createPublicClient, formatEther } from 'viem' import { goerli, suaveRigil } from 'viem/chains' import { TransactionRequestSuave } from 'viem/chains/suave/types' import { MevShareBid } from 'bids' +import { SuaveProvider, SuaveWallet, getSuaveProvider, getSuaveWallet } from 'viem/chains/utils' +import { HttpTransport } from 'viem' const failEnv = (name: string) => { throw new Error(`missing env var ${name}`) @@ -26,16 +28,16 @@ const SUAVE_RPC_URL_HTTP: string = const GOERLI_RPC_URL_HTTP: string = process.env.GOERLI_RPC_URL_HTTP || 'http://localhost:8545' -const suaveProvider = suaveRigil.newPublicClient(http(SUAVE_RPC_URL_HTTP)) +const suaveProvider: SuaveProvider = getSuaveProvider(http(SUAVE_RPC_URL_HTTP)) const goerliProvider = createPublicClient({ chain: goerli, transport: http(GOERLI_RPC_URL_HTTP), }) -const adminWallet = suaveRigil.newWallet({ +const adminWallet: SuaveWallet = getSuaveWallet({ transport: http(SUAVE_RPC_URL_HTTP), privateKey: PRIVATE_KEY, }) -const wallet = suaveRigil.newWallet({ +const wallet = getSuaveWallet({ transport: http(SUAVE_RPC_URL_HTTP), privateKey: '0x01000070530220062104600650003002001814120800043ff33603df10300012', }) @@ -107,7 +109,7 @@ async function testSuaveBids() { gas: 26000n, gasPrice: 10000000000n, chainId: 5, - type: '0x0' as '0x0', + type: '0x0' as const, } const signedTx = await wallet.signTransaction(testTx) @@ -132,6 +134,10 @@ async function testSuaveBids() { return receipt }) console.log('ccrReceipt', ccrReceipt) + + // get tx too + const ccrTx = await suaveProvider.getTransaction({ hash: ccrRes }) + console.log('ccrTx', ccrTx) } async function main() { diff --git a/src/accounts/utils/signTransaction.ts b/src/accounts/utils/signTransaction.ts index dd73e824..be12fde2 100644 --- a/src/accounts/utils/signTransaction.ts +++ b/src/accounts/utils/signTransaction.ts @@ -17,7 +17,8 @@ import { import { type SignErrorType, sign } from './sign.js' export type SignTransactionParameters< - TTransactionSerializable extends TransactionSerializable = TransactionSerializable, + TTransactionSerializable extends + TransactionSerializable = TransactionSerializable, > = { privateKey: Hex transaction: TTransactionSerializable @@ -27,7 +28,8 @@ export type SignTransactionParameters< } export type SignTransactionReturnType< - TTransactionSerializable extends TransactionSerializable = TransactionSerializable, + TTransactionSerializable extends + TransactionSerializable = TransactionSerializable, > = TransactionSerialized> export type SignTransactionErrorType = diff --git a/src/actions/public/createContractEventFilter.ts b/src/actions/public/createContractEventFilter.ts index c0522514..6bb96792 100644 --- a/src/actions/public/createContractEventFilter.ts +++ b/src/actions/public/createContractEventFilter.ts @@ -48,15 +48,17 @@ export type CreateContractEventFilterParameters< args?: never } : MaybeExtractEventArgsFromAbi< - TAbi, - TEventName - > extends infer TEventFilterArgs - ? { - args?: TEventFilterArgs | (TArgs extends TEventFilterArgs ? TArgs : never) - } - : { - args?: never - }) + TAbi, + TEventName + > extends infer TEventFilterArgs + ? { + args?: + | TEventFilterArgs + | (TArgs extends TEventFilterArgs ? TArgs : never) + } + : { + args?: never + }) export type CreateContractEventFilterReturnType< TAbi extends Abi | readonly unknown[] = Abi, diff --git a/src/chains/definitions/suaveRigil.ts b/src/chains/definitions/suaveRigil.ts index cf538d89..afe90303 100644 --- a/src/chains/definitions/suaveRigil.ts +++ b/src/chains/definitions/suaveRigil.ts @@ -1,18 +1,11 @@ import type { Address } from 'abitype' -import { createPublicClient } from '../../clients/createPublicClient.js' -import type { Transport } from '../../clients/transports/createTransport.js' -import { http } from '../../clients/transports/http.js' -import { type Hex } from '../../types/misc.js' import { defineChain } from '../../utils/chain.js' import { formattersSuave } from '../suave/formatters.js' -import { getSuaveWallet } from '../suave/wallet.js' const testnetUrlHttp = 'https://rpc.rigil.suave.flashbots.net' const testnetUrlWs = 'wss://rpc.rigil.suave.flashbots.net' const testnetExplorerUrl = 'https://rpc.rigil.suave.flashbots.net' -const defaultTransport = http(testnetUrlHttp) - export const suaveRigil = /*#__PURE__*/ defineChain( { id: 16813125, @@ -87,55 +80,6 @@ export const suaveRigil = /*#__PURE__*/ defineChain( }, }, testnet: true, - /** Creates a new SUAVE Wallet instance. - * @example - // new wallet with a private key - import { suaveRigil } from 'viem/chains' - import { http } from 'viem' - const wallet = suaveRigil.newWallet({ - transport: http('http://localhost:8545'), - privateKey: '0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80', - }) - * @example - // new wallet with a json-rpc account using window.ethereum - // it's assumed that the wallet is already connected to SUAVE chain - import { suaveRigil } from 'viem/chains' - import { custom } from 'viem' - const wallet = suaveRigil.newWallet({ - transport: custom(window.ethereum), - jsonRpcAccount: '0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266', - }) - */ - newWallet: (params: { - privateKey?: Hex - jsonRpcAccount?: Hex - transport?: Transport - }) => - getSuaveWallet({ - transport: params.transport ?? defaultTransport, - chain: suaveRigil, - privateKey: params.privateKey, - jsonRpcAccount: params.jsonRpcAccount && { - address: params.jsonRpcAccount, - type: 'json-rpc', - }, - }), - /** Creates a new SUAVE Public Client instance. - * @example - import { suaveRigil } from 'viem/chains' - import { http } from 'viem' - const client = suaveRigil.newPublicClient(http('http://localhost:8545')) - * @example - // using window.ethereum - import { suaveRigil } from 'viem/chains' - import { custom } from 'viem' - const client = suaveRigil.newPublicClient(custom(window.ethereum)) - */ - newPublicClient: (transport?: Transport) => - createPublicClient({ - transport: transport ?? defaultTransport, - chain: suaveRigil, - }), }, { formatters: formattersSuave, diff --git a/src/chains/suave/formatters.ts b/src/chains/suave/formatters.ts index a0f99b5b..30384501 100644 --- a/src/chains/suave/formatters.ts +++ b/src/chains/suave/formatters.ts @@ -108,7 +108,6 @@ export const formattersSuave = { typeHex: args.typeHex, } as TransactionSuave } else { - console.log('formatting regular tx') // Handle as regular Ethereum transaction return formatTransaction(args as RpcTransaction) as Transaction } @@ -116,7 +115,6 @@ export const formattersSuave = { }), transactionReceipt: /*#__PURE__*/ defineTransactionReceipt({ format(args: RpcTransactionReceiptSuave): TransactionReceiptSuave { - console.log('formatting tx receipt') return { ...formatTransactionReceipt(args), } as TransactionReceiptSuave diff --git a/src/chains/suave/types.ts b/src/chains/suave/types.ts index 5a45e8c9..dce98c68 100644 --- a/src/chains/suave/types.ts +++ b/src/chains/suave/types.ts @@ -11,6 +11,8 @@ import type { TransactionSerializableBase, } from '../../types/transaction.js' +export type { SuaveWallet, SuaveProvider } from './wallet.js' + /// CUSTOM OVERRIDES =========================================================== export enum SuaveTxRequestTypes { @@ -29,9 +31,10 @@ const AllSuaveTypes = { } // syntactical sugar to allow inline string literals -export type SuaveTxType = `${typeof AllSuaveTypes[keyof typeof AllSuaveTypes]}` +export type SuaveTxType = + `${(typeof AllSuaveTypes)[keyof typeof AllSuaveTypes]}` export type SuaveTxRequestType = - `${typeof SuaveTxRequestTypes[keyof typeof SuaveTxRequestTypes]}` + `${(typeof SuaveTxRequestTypes)[keyof typeof SuaveTxRequestTypes]}` type ConfidentialOverrides = { kettleAddress?: Address diff --git a/src/chains/suave/wallet.ts b/src/chains/suave/wallet.ts index cf4d47fb..ba6daf2f 100644 --- a/src/chains/suave/wallet.ts +++ b/src/chains/suave/wallet.ts @@ -1,11 +1,14 @@ import { privateKeyToAccount } from '../../accounts/privateKeyToAccount.js' import { sign } from '../../accounts/utils/sign.js' import { - type Chain, + http, type JsonRpcAccount, type PrivateKeyAccount, + type PublicClient, type Transport, + type TransportConfig, type WalletClient, + createPublicClient, createWalletClient, hexToSignature, keccak256, @@ -23,6 +26,19 @@ import { type TransactionSerializableSuave, } from './types.js' +/// client types +export type SuaveWallet = WalletClient< + TTransport, + typeof suaveRigil, + PrivateKeyAccount | JsonRpcAccount +> + +export type SuaveProvider = PublicClient< + TTransport, + typeof suaveRigil +> + +/// helper functions function formatSignature(signature: { r: Hex s: Hex @@ -52,10 +68,17 @@ async function signConfidentialComputeRecord( } } -function getSigningMethod(transport: any, privateKey?: Hex, address?: Hex) { +function getSigningMethod( + transport: TTransport, + privateKey?: Hex, + address?: Hex, +) { if (transport.type === 'custom') { + if (!address) { + throw new Error("param 'address' is required for custom transports") + } return async (txRequest: TransactionSerializableSuave) => { - const rawSignature = await transport.request({ + const rawSignature: Hex = await transport.request({ method: 'eth_sign', params: [ address, @@ -75,34 +98,69 @@ function getSigningMethod(transport: any, privateKey?: Hex, address?: Hex) { } } -export function getSuaveWallet< - TTransport extends Transport, - TChain extends Chain, ->(params: { +/** Get a SUAVE-enabled viem wallet. + * + * @example + * import { http } from 'viem' + * import { getSuaveWallet } from 'viem/chains/utils' + * const wallet = getSuaveWallet({ + * transport: http('http://localhost:8545'), + * privateKey: '0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80', + * }) + * + * @example + * // using window.ethereum + * import { custom } from 'viem' + * import { getSuaveWallet } from 'viem/chains/utils' + * async function main() { + * const accounts = await window.ethereum.request({ method: 'eth_requestAccounts' }) + * const account = accounts[0] + * const wallet = getSuaveWallet({ + * transport: custom(window.ethereum), + * jsonRpcAccount: account, + * }) + * } + * main() + */ +export function getSuaveWallet(params: { + transport?: TTransport + jsonRpcAccount?: Hex + privateKey?: Hex +}): SuaveWallet { + return newSuaveWallet({ + transport: params.transport ?? http(suaveRigil.rpcUrls.public.http[0]), + privateKey: params.privateKey, + jsonRpcAccount: params.jsonRpcAccount && { + address: params.jsonRpcAccount, + type: 'json-rpc', + }, + }) +} + +/** Get a SUAVE-enabled viem wallet. */ +function newSuaveWallet(params: { transport: TTransport - chain: TChain jsonRpcAccount?: JsonRpcAccount privateKey?: Hex -}): WalletClient< - TTransport, - TChain, - PrivateKeyAccount // TODO: generalize account types (required to make metamask transport work) -> { +}): SuaveWallet { if (!params.jsonRpcAccount && !params.privateKey) { throw new Error("Must provide either 'jsonRpcAccount' or 'privateKey'") } if (params.jsonRpcAccount && params.privateKey) { throw new Error("Cannot provide both 'jsonRpcAccount' and 'privateKey'") } + // Overrides viem wallet methods with SUAVE equivalents. + const privateKeyAccount = params.privateKey + ? privateKeyToAccount(params.privateKey) + : undefined + const account = params.jsonRpcAccount ?? privateKeyAccount return createWalletClient({ - account: params.jsonRpcAccount ?? privateKeyToAccount(params.privateKey!), + account, transport: params.transport, - chain: params.chain, + chain: suaveRigil, }).extend((client) => ({ async sendTransaction(txRequest: TransactionRequestSuave) { - const preparedTx = await client.prepareTransactionRequest( - txRequest as any, - ) + const preparedTx = await client.prepareTransactionRequest(txRequest) const payload: TransactionRequestSuave = { ...txRequest, from: preparedTx.from, @@ -145,8 +203,28 @@ export function getSuaveWallet< v, }) } else { - return await client.account.signTransaction(txRequest as any) + return await client.account.signTransaction(txRequest) } }, })) } + +/** Creates a new SUAVE Public Client instance. + * @example + * import { http } from 'viem' + * import { getSuaveProvider } from 'viem/chains/utils' + * const client = getSuaveProvider(http('http://localhost:8545')) + * @example + * // using window.ethereum + * import { custom } from 'viem' + * import { getSuaveProvider } from 'viem/chains/utils' + * const client = getSuaveProvider(custom(window.ethereum)) + */ +export function getSuaveProvider( + transport?: TTransport, +): SuaveProvider { + return createPublicClient({ + transport: transport ?? http(suaveRigil.rpcUrls.public.http[0]), + chain: suaveRigil, + }) +} diff --git a/src/chains/utils/index.test.ts b/src/chains/utils/index.test.ts index c5c78f03..54602900 100644 --- a/src/chains/utils/index.test.ts +++ b/src/chains/utils/index.test.ts @@ -10,6 +10,7 @@ test('exports', () => { "serializersCelo", "parseTransactionCelo", "formattersOptimism", + "formattersSuave" ] `) }) diff --git a/src/chains/utils/index.ts b/src/chains/utils/index.ts index d14375fc..19e07f77 100644 --- a/src/chains/utils/index.ts +++ b/src/chains/utils/index.ts @@ -43,3 +43,31 @@ export type { OptimismTransactionReceipt, OptimismTransactionReceiptOverrides, } from '../optimism/types.js' + +export { formattersSuave } from '../suave/formatters.js' +export { getSuaveProvider, getSuaveWallet } from '../suave/wallet.js' +export type { + ConfidentialComputeRecord, + ConfidentialComputeRecordRpc, + RpcTransactionReceiptSuave, + RpcTransactionRequestSuave, + RpcTransactionSuave, + SuaveBlock, + SuaveProvider, + SuaveBlockOverrides, + SuaveRpcBlock, + SuaveTransactionReceiptOverrides, + SuaveTxRequestType, + SuaveTxType, + SuaveWallet, + TransactionReceiptSuave, + TransactionRequestSuave, + TransactionSerializableEIP2930, + TransactionSerializableSuave, + TransactionSerializedSuave, + TransactionSuave, +} from '../suave/types.js' +export { + SuaveTxTypes, + SuaveTxRequestTypes, +} from '../suave/types.js' diff --git a/src/errors/base.ts b/src/errors/base.ts index d22c6d23..8bef6530 100644 --- a/src/errors/base.ts +++ b/src/errors/base.ts @@ -32,8 +32,8 @@ export class BaseError extends Error { args.cause instanceof BaseError ? args.cause.details : args.cause?.message - ? args.cause.message - : args.details! + ? args.cause.message + : args.details! const docsPath = args.cause instanceof BaseError ? args.cause.docsPath || args.docsPath diff --git a/src/types/contract.ts b/src/types/contract.ts index ea764bea..cddd66f8 100644 --- a/src/types/contract.ts +++ b/src/types/contract.ts @@ -58,10 +58,10 @@ export type ContractFunctionResult< > = true extends FailedToParseArgs ? unknown : TArgs extends readonly [] - ? void - : TArgs extends readonly [infer Arg] - ? Arg - : TArgs + ? void + : TArgs extends readonly [infer Arg] + ? Arg + : TArgs export type GetValue< TAbi extends Abi | readonly unknown[], @@ -75,8 +75,8 @@ export type GetValue< ? TAbiFunction['stateMutability'] extends 'payable' ? { value?: NoUndefined } : TAbiFunction['payable'] extends true - ? { value?: NoUndefined } - : { value?: never } + ? { value?: NoUndefined } + : { value?: never } : { value?: TValueType } export type MaybeAbiEventName = @@ -170,10 +170,10 @@ export type GetFunctionArgs< args?: readonly unknown[] } : TArgs extends readonly [] - ? { args?: never } - : { - /** Arguments to pass contract method */ args: TArgs - } + ? { args?: never } + : { + /** Arguments to pass contract method */ args: TArgs + } export type GetConstructorArgs< TAbi extends Abi | readonly unknown[], @@ -194,10 +194,10 @@ export type GetConstructorArgs< args?: readonly unknown[] } : TArgs extends readonly [] - ? { args?: never } - : { - /** Arguments to pass contract constructor */ args: TArgs - } + ? { args?: never } + : { + /** Arguments to pass contract constructor */ args: TArgs + } export type GetErrorArgs< TAbi extends Abi | readonly unknown[], @@ -219,10 +219,10 @@ export type GetErrorArgs< args?: readonly unknown[] } : TArgs extends readonly [] - ? { args?: never } - : { - /** Arguments to pass contract method */ args: TArgs - } + ? { args?: never } + : { + /** Arguments to pass contract method */ args: TArgs + } export type GetEventArgs< TAbi extends Abi | readonly unknown[], @@ -296,10 +296,10 @@ export type LogTopicType< > = TTopic extends Hex ? TPrimitiveType : TTopic extends Hex[] - ? TPrimitiveType[] - : TTopic extends null - ? null - : never + ? TPrimitiveType[] + : TTopic extends null + ? null + : never /** * @internal @@ -328,46 +328,45 @@ export type AbiEventParametersToPrimitiveTypes< > = TAbiParameters extends readonly [] ? readonly [] : Filter< - TAbiParameters, - Options['IndexedOnly'] extends true ? { indexed: true } : object - > extends infer Filtered extends readonly AbiParameter[] - ? _HasUnnamedAbiParameter extends true - ? // Has unnamed tuple parameters so return as array - | readonly [ - ...{ - [K in keyof Filtered]: AbiEventParameterToPrimitiveType< - Filtered[K], - Options - > - }, - ] - // Distribute over tuple to represent optional parameters - | (Options['Required'] extends true - ? never - : // Distribute over tuple to represent optional parameters - Filtered extends readonly [ - ...infer Head extends readonly AbiParameter[], - infer _, - ] - ? AbiEventParametersToPrimitiveTypes< - readonly [...{ [K in keyof Head]: Omit }], - Options - > - : never) - : // All tuple parameters are named so return as object - { - [Parameter in - Filtered[number] as Parameter extends { - name: infer Name extends string - } - ? Name - : never]?: AbiEventParameterToPrimitiveType - } extends infer Mapped - ? Prettify< - MaybeRequired< - Mapped, - Options['Required'] extends boolean ? Options['Required'] : false - > - > + TAbiParameters, + Options['IndexedOnly'] extends true ? { indexed: true } : object + > extends infer Filtered extends readonly AbiParameter[] + ? _HasUnnamedAbiParameter extends true + ? // Has unnamed tuple parameters so return as array + | readonly [ + ...{ + [K in keyof Filtered]: AbiEventParameterToPrimitiveType< + Filtered[K], + Options + > + }, + ] + // Distribute over tuple to represent optional parameters + | (Options['Required'] extends true + ? never + : // Distribute over tuple to represent optional parameters + Filtered extends readonly [ + ...infer Head extends readonly AbiParameter[], + infer _, + ] + ? AbiEventParametersToPrimitiveTypes< + readonly [...{ [K in keyof Head]: Omit }], + Options + > + : never) + : // All tuple parameters are named so return as object + { + [Parameter in Filtered[number] as Parameter extends { + name: infer Name extends string + } + ? Name + : never]?: AbiEventParameterToPrimitiveType + } extends infer Mapped + ? Prettify< + MaybeRequired< + Mapped, + Options['Required'] extends boolean ? Options['Required'] : false + > + > + : never : never - : never diff --git a/src/types/filter.ts b/src/types/filter.ts index 7de37177..d449b86c 100644 --- a/src/types/filter.ts +++ b/src/types/filter.ts @@ -42,18 +42,18 @@ export type Filter< strict: TStrict } : TArgs extends MaybeExtractEventArgsFromAbi - ? { - abi: TAbi - args: TArgs - eventName: TEventName - strict: TStrict - } - : { - abi: TAbi - args?: never - eventName: TEventName - strict: TStrict - } + ? { + abi: TAbi + args: TArgs + eventName: TEventName + strict: TStrict + } + : { + abi: TAbi + args?: never + eventName: TEventName + strict: TStrict + } : { abi?: never args?: never diff --git a/src/types/log.ts b/src/types/log.ts index f0b4170c..17a336b6 100644 --- a/src/types/log.ts +++ b/src/types/log.ts @@ -75,10 +75,10 @@ type GetTopics< > = true extends _FailedToParseArgs ? [Hex, ...Hex[]] | [] : TAbiEvent extends AbiEvent - ? Topics - : _AbiEvent extends AbiEvent - ? Topics<_AbiEvent['inputs']> - : [Hex, ...Hex[]] | [] + ? Topics + : _AbiEvent extends AbiEvent + ? Topics<_AbiEvent['inputs']> + : [Hex, ...Hex[]] | [] type GetInferredLogValues< TAbiEvent extends AbiEvent | undefined = undefined, diff --git a/src/types/multicall.ts b/src/types/multicall.ts index 954f7667..8f5842f2 100644 --- a/src/types/multicall.ts +++ b/src/types/multicall.ts @@ -23,32 +23,37 @@ export type MulticallContracts< > = Depth['length'] extends MAXIMUM_DEPTH ? (ContractFunctionConfig & TProperties)[] : TContracts extends [] - ? [] - : TContracts extends [infer Head extends MulticallContract] - ? [ - ...Result, - ContractFunctionConfig & TProperties, - ] - : TContracts extends [ - infer Head extends MulticallContract, - ...infer Tail extends readonly MulticallContract[], - ] - ? MulticallContracts< - [...Tail], - TProperties, - [ - ...Result, - ContractFunctionConfig & TProperties, - ], - [...Depth, 1] - > - : unknown[] extends TContracts - ? TContracts - : // If `TContracts` is *some* array but we couldn't assign `unknown[]` to it, then it must hold some known/homogenous type! - // use this to infer the param types in the case of Array.map() argument - TContracts extends ContractFunctionConfig[] - ? (ContractFunctionConfig & TProperties)[] - : (ContractFunctionConfig & TProperties)[] + ? [] + : TContracts extends [infer Head extends MulticallContract] + ? [ + ...Result, + ContractFunctionConfig & + TProperties, + ] + : TContracts extends [ + infer Head extends MulticallContract, + ...infer Tail extends readonly MulticallContract[], + ] + ? MulticallContracts< + [...Tail], + TProperties, + [ + ...Result, + ContractFunctionConfig & + TProperties, + ], + [...Depth, 1] + > + : unknown[] extends TContracts + ? TContracts + : // If `TContracts` is *some* array but we couldn't assign `unknown[]` to it, then it must hold some known/homogenous type! + // use this to infer the param types in the case of Array.map() argument + TContracts extends ContractFunctionConfig< + infer TAbi, + infer TFunctionName + >[] + ? (ContractFunctionConfig & TProperties)[] + : (ContractFunctionConfig & TProperties)[] export type MulticallResult< Result, @@ -75,34 +80,37 @@ export type MulticallResults< > = Depth['length'] extends MAXIMUM_DEPTH ? MulticallResult[] : TContracts extends [] - ? [] - : TContracts extends [infer Head extends MulticallContract] - ? [ - ...Result, - MulticallResult< - ContractFunctionResult, - TAllowFailure - >, - ] - : TContracts extends [ - infer Head extends MulticallContract, - ...infer Tail extends readonly MulticallContract[], - ] - ? MulticallResults< - [...Tail], - TAllowFailure, - [ - ...Result, - MulticallResult< - ContractFunctionResult, - TAllowFailure - >, - ], - [...Depth, 1] - > - : TContracts extends ContractFunctionConfig[] - ? MulticallResult< - ContractFunctionResult, - TAllowFailure - >[] - : MulticallResult[] + ? [] + : TContracts extends [infer Head extends MulticallContract] + ? [ + ...Result, + MulticallResult< + ContractFunctionResult, + TAllowFailure + >, + ] + : TContracts extends [ + infer Head extends MulticallContract, + ...infer Tail extends readonly MulticallContract[], + ] + ? MulticallResults< + [...Tail], + TAllowFailure, + [ + ...Result, + MulticallResult< + ContractFunctionResult, + TAllowFailure + >, + ], + [...Depth, 1] + > + : TContracts extends ContractFunctionConfig< + infer TAbi, + infer TFunctionName + >[] + ? MulticallResult< + ContractFunctionResult, + TAllowFailure + >[] + : MulticallResult[] diff --git a/src/types/transaction.ts b/src/types/transaction.ts index f5e4f66a..4a562289 100644 --- a/src/types/transaction.ts +++ b/src/types/transaction.ts @@ -177,10 +177,10 @@ export type TransactionSerialized = TType extends 'eip1559' ? TransactionSerializedEIP1559 : TType extends 'eip2930' - ? TransactionSerializedEIP2930 - : TType extends 'legacy' - ? TransactionSerializedLegacy - : TransactionSerializedGeneric + ? TransactionSerializedEIP2930 + : TType extends 'legacy' + ? TransactionSerializedLegacy + : TransactionSerializedGeneric export type TransactionSerializableBase< TQuantity = bigint, diff --git a/src/types/typedData.ts b/src/types/typedData.ts index 917d5e52..9bad85f5 100644 --- a/src/types/typedData.ts +++ b/src/types/typedData.ts @@ -42,18 +42,18 @@ export type GetTypedDataMessage< > = TPrimaryType extends 'EIP712Domain' ? {} : { [key_3: string]: any } extends TMessage // Check if we were able to infer the shape of typed data - ? { - /** - * Data to sign - * - * Use a [const assertion](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-4.html#const-assertions) on {@link types} for type inference. - */ - message: { [key_4: string]: unknown } - } - : { - /** Data to sign */ - message: TMessage - } + ? { + /** + * Data to sign + * + * Use a [const assertion](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-4.html#const-assertions) on {@link types} for type inference. + */ + message: { [key_4: string]: unknown } + } + : { + /** Data to sign */ + message: TMessage + } export type GetTypedDataPrimaryType< TTypedData extends TypedData | { [key: string]: unknown } = TypedData, diff --git a/src/types/utils.ts b/src/types/utils.ts index fb8cb779..251e072f 100644 --- a/src/types/utils.ts +++ b/src/types/utils.ts @@ -125,12 +125,11 @@ export type MaybeUndefined< * @private Helper for `Assign`. This is a workaround for tsc generating errorneous type definitions. */ export type Assign_ = { - [K in - keyof T as K extends keyof U - ? U[K] extends void - ? never - : K - : K]: K extends keyof U ? U[K] : T[K] + [K in keyof T as K extends keyof U + ? U[K] extends void + ? never + : K + : K]: K extends keyof U ? U[K] : T[K] } /** diff --git a/src/utils/abi/decodeFunctionResult.ts b/src/utils/abi/decodeFunctionResult.ts index 0add028f..a6f3990c 100644 --- a/src/utils/abi/decodeFunctionResult.ts +++ b/src/utils/abi/decodeFunctionResult.ts @@ -37,8 +37,8 @@ export type DecodeFunctionResultParameters< } & (TFunctionName extends string ? { abi: TAbi } & Partial> : _FunctionName extends string - ? { abi: [TAbi[number]] } & Partial> - : never) + ? { abi: [TAbi[number]] } & Partial> + : never) export type DecodeFunctionResultReturnType< TAbi extends Abi | readonly unknown[] = Abi, diff --git a/src/utils/abi/encodeErrorResult.ts b/src/utils/abi/encodeErrorResult.ts index 3b2c9a0c..66c7283a 100644 --- a/src/utils/abi/encodeErrorResult.ts +++ b/src/utils/abi/encodeErrorResult.ts @@ -39,8 +39,8 @@ export type EncodeErrorResultParameters< } & (TErrorName extends string ? { abi: TAbi } & GetErrorArgs : _ErrorName extends string - ? { abi: [TAbi[number]] } & GetErrorArgs - : never) + ? { abi: [TAbi[number]] } & GetErrorArgs + : never) export type EncodeErrorResultErrorType = | GetAbiItemErrorType diff --git a/src/utils/abi/encodeEventTopics.ts b/src/utils/abi/encodeEventTopics.ts index fe774172..06599edb 100644 --- a/src/utils/abi/encodeEventTopics.ts +++ b/src/utils/abi/encodeEventTopics.ts @@ -39,8 +39,8 @@ export type EncodeEventTopicsParameters< } & (TEventName extends string ? { abi: TAbi; args?: GetEventArgs } : _EventName extends string - ? { abi: [TAbi[number]]; args?: GetEventArgs } - : never) + ? { abi: [TAbi[number]]; args?: GetEventArgs } + : never) export type EncodeEventTopicsErrorType = | AbiEventNotFoundErrorType @@ -82,8 +82,8 @@ export function encodeEventTopics< const args_ = Array.isArray(args) ? args : Object.values(args).length > 0 - ? indexedInputs?.map((x: any) => (args as any)[x.name]) ?? [] - : [] + ? indexedInputs?.map((x: any) => (args as any)[x.name]) ?? [] + : [] if (args_.length > 0) { topics = @@ -93,8 +93,8 @@ export function encodeEventTopics< encodeArg({ param, value: args_[i][j] }), ) : args_[i] - ? encodeArg({ param, value: args_[i] }) - : null, + ? encodeArg({ param, value: args_[i] }) + : null, ) ?? [] } } diff --git a/src/utils/abi/encodeFunctionData.ts b/src/utils/abi/encodeFunctionData.ts index 58812e8e..c610966f 100644 --- a/src/utils/abi/encodeFunctionData.ts +++ b/src/utils/abi/encodeFunctionData.ts @@ -36,8 +36,8 @@ export type EncodeFunctionDataParameters< } & (TFunctionName extends string ? { abi: TAbi } & GetFunctionArgs : _FunctionName extends string - ? { abi: [TAbi[number]] } & GetFunctionArgs - : never) + ? { abi: [TAbi[number]] } & GetFunctionArgs + : never) export type EncodeFunctionDataErrorType = | AbiFunctionNotFoundErrorType diff --git a/src/utils/abi/encodeFunctionResult.ts b/src/utils/abi/encodeFunctionResult.ts index e48deddd..acc1da76 100644 --- a/src/utils/abi/encodeFunctionResult.ts +++ b/src/utils/abi/encodeFunctionResult.ts @@ -32,11 +32,11 @@ export type EncodeFunctionResultParameters< } & (TFunctionName extends string ? { abi: TAbi; result?: ContractFunctionResult } : _FunctionName extends string - ? { - abi: [TAbi[number]] - result?: ContractFunctionResult - } - : never) + ? { + abi: [TAbi[number]] + result?: ContractFunctionResult + } + : never) export type EncodeFunctionResultErrorType = | AbiFunctionOutputsNotFoundError diff --git a/src/utils/encoding/fromBytes.ts b/src/utils/encoding/fromBytes.ts index b4e0bc84..2731798c 100644 --- a/src/utils/encoding/fromBytes.ts +++ b/src/utils/encoding/fromBytes.ts @@ -27,14 +27,14 @@ export type FromBytesParameters< export type FromBytesReturnType = TTo extends 'string' ? string : TTo extends 'hex' - ? Hex - : TTo extends 'bigint' - ? bigint - : TTo extends 'number' - ? number - : TTo extends 'boolean' - ? boolean - : never + ? Hex + : TTo extends 'bigint' + ? bigint + : TTo extends 'number' + ? number + : TTo extends 'boolean' + ? boolean + : never export type FromBytesErrorType = | BytesToHexErrorType diff --git a/src/utils/encoding/fromHex.ts b/src/utils/encoding/fromHex.ts index 2feeeef7..7eb9a17a 100644 --- a/src/utils/encoding/fromHex.ts +++ b/src/utils/encoding/fromHex.ts @@ -41,14 +41,14 @@ export type FromHexParameters< export type FromHexReturnType = TTo extends 'string' ? string : TTo extends 'bigint' - ? bigint - : TTo extends 'number' - ? number - : TTo extends 'bytes' - ? ByteArray - : TTo extends 'boolean' - ? boolean - : never + ? bigint + : TTo extends 'number' + ? number + : TTo extends 'bytes' + ? ByteArray + : TTo extends 'boolean' + ? boolean + : never export type FromHexErrorType = | HexToNumberErrorType diff --git a/src/utils/errors/getContractError.ts b/src/utils/errors/getContractError.ts index 4237ffec..9c3f7ae3 100644 --- a/src/utils/errors/getContractError.ts +++ b/src/utils/errors/getContractError.ts @@ -48,8 +48,8 @@ export function getContractError>( err instanceof RawContractError ? err : err instanceof BaseError - ? err.walk((err) => 'data' in (err as Error)) || err.walk() - : {} + ? err.walk((err) => 'data' in (err as Error)) || err.walk() + : {} ) as RawContractError const cause = (() => { diff --git a/src/utils/transaction/getSerializedTransactionType.ts b/src/utils/transaction/getSerializedTransactionType.ts index e6cf627b..67424155 100644 --- a/src/utils/transaction/getSerializedTransactionType.ts +++ b/src/utils/transaction/getSerializedTransactionType.ts @@ -16,8 +16,8 @@ export type GetSerializedTransactionType< > = TTransactionSerialized extends TransactionSerializedEIP1559 ? 'eip1559' : TTransactionSerialized extends TransactionSerializedEIP2930 - ? 'eip2930' - : 'legacy' + ? 'eip2930' + : 'legacy' export type GetSerializedTransactionTypeErrorType = | HexToNumberErrorType diff --git a/src/utils/transaction/getTransactionType.ts b/src/utils/transaction/getTransactionType.ts index c9a15640..5bfd74a2 100644 --- a/src/utils/transaction/getTransactionType.ts +++ b/src/utils/transaction/getTransactionType.ts @@ -12,7 +12,8 @@ import type { } from '../../types/transaction.js' export type GetTransactionType< - TTransactionSerializable extends TransactionSerializable = TransactionSerializable, + TTransactionSerializable extends + TransactionSerializable = TransactionSerializable, > = | (TTransactionSerializable extends TransactionSerializableLegacy ? 'legacy' diff --git a/src/utils/transaction/serializeTransaction.ts b/src/utils/transaction/serializeTransaction.ts index 82d0dd8b..76eeec88 100644 --- a/src/utils/transaction/serializeTransaction.ts +++ b/src/utils/transaction/serializeTransaction.ts @@ -39,12 +39,15 @@ import { } from './serializeAccessList.js' export type SerializedTransactionReturnType< - TTransactionSerializable extends TransactionSerializable = TransactionSerializable, - TTransactionType extends TransactionType = GetTransactionType, + TTransactionSerializable extends + TransactionSerializable = TransactionSerializable, + TTransactionType extends + TransactionType = GetTransactionType, > = TransactionSerialized export type SerializeTransactionFn< - TTransactionSerializable extends TransactionSerializable = TransactionSerializable, + TTransactionSerializable extends + TransactionSerializable = TransactionSerializable, > = typeof serializeTransaction export type SerializeTransactionErrorType = diff --git a/test/src/utils.ts b/test/src/utils.ts index d6ab87f1..6a90340b 100644 --- a/test/src/utils.ts +++ b/test/src/utils.ts @@ -195,8 +195,8 @@ export function createHttpServer( export async function deploy( args: DeployContractParameters< TAbi, - typeof walletClientWithAccount['chain'], - typeof walletClientWithAccount['account'] + (typeof walletClientWithAccount)['chain'], + (typeof walletClientWithAccount)['account'] >, ) { const hash = await deployContract(walletClientWithAccount, args)