diff --git a/bun.lockb b/bun.lockb index 7aabedc..da08d01 100755 Binary files a/bun.lockb and b/bun.lockb differ diff --git a/package.json b/package.json index 2135385..286902c 100644 --- a/package.json +++ b/package.json @@ -59,7 +59,7 @@ "ethers": "^6.7.1", "eventemitter3": "^5.0.1", "human-id": "^4.0.0", - "mipd": "^0.0.5", + "mipd": "^0.0.7", "react": "^18.2.0", "react-dom": "^18.2.0", "react-flatten-children": "^1.1.2", @@ -70,7 +70,7 @@ "remeda": "^1.14.0", "sonner": "^0.7.2", "use-sync-external-store": "^1.2.0", - "viem": "^1.10.12", + "viem": "^2.9.13", "zustand": "^4.3.8" }, "devDependencies": { diff --git a/src/design-system/components/ButtonCopy.tsx b/src/design-system/components/ButtonCopy.tsx index e0e7fae..88fd42c 100644 --- a/src/design-system/components/ButtonCopy.tsx +++ b/src/design-system/components/ButtonCopy.tsx @@ -1,6 +1,6 @@ import { forwardRef, useEffect, useState } from 'react' -import type { UnionOmit } from '~/utils/types' +import type { UnionOmit } from '~/types/utils' import { ButtonRoot, type ButtonRootProps } from './Button' import type { ButtonHeight } from './Button.css' diff --git a/src/design-system/components/ButtonSymbol.tsx b/src/design-system/components/ButtonSymbol.tsx index ac87bc4..4268cdd 100644 --- a/src/design-system/components/ButtonSymbol.tsx +++ b/src/design-system/components/ButtonSymbol.tsx @@ -1,6 +1,6 @@ import { forwardRef } from 'react' -import type { UnionOmit } from '~/utils/types' +import type { UnionOmit } from '~/types/utils' import { Tooltip } from '../../components' import type { SymbolName } from '../tokens' diff --git a/src/entries/background/rpc.ts b/src/entries/background/rpc.ts index 7e19547..06435e8 100644 --- a/src/entries/background/rpc.ts +++ b/src/entries/background/rpc.ts @@ -7,13 +7,14 @@ import { custom, numberToHex, } from 'viem' -import { type RpcResponse, rpc } from 'viem/utils' +import { rpc } from 'viem/utils' import { UnsupportedProviderMethodError, UserRejectedRequestError, } from '~/errors' import { type Messenger, getMessenger } from '~/messengers' +import type { RpcResponse } from '~/types/rpc' import { buildChain } from '~/viem' import { accountStore, diff --git a/src/errors/rpc.ts b/src/errors/rpc.ts index a55da9c..696be35 100644 --- a/src/errors/rpc.ts +++ b/src/errors/rpc.ts @@ -1,5 +1,4 @@ -import type { RpcRequest } from 'viem/utils' - +import type { RpcRequest } from '~/types/rpc' import { BaseError } from './base.js' export type ProviderRpcErrorCode = diff --git a/src/hooks/useErc20Balance.ts b/src/hooks/useErc20Balance.ts index 8735272..c10d3e1 100644 --- a/src/hooks/useErc20Balance.ts +++ b/src/hooks/useErc20Balance.ts @@ -29,7 +29,7 @@ export function useErc20BalanceQueryOptions({ const contract = getContract({ address: tokenAddress, abi: erc20Abi, - publicClient: client, + client, }) return contract.read.balanceOf([address]) }, diff --git a/src/hooks/useErc20Metadata.ts b/src/hooks/useErc20Metadata.ts index b01e03d..fe8a8c0 100644 --- a/src/hooks/useErc20Metadata.ts +++ b/src/hooks/useErc20Metadata.ts @@ -27,7 +27,7 @@ export function useErc20MetadataQueryOptions({ const contract = getContract({ address: tokenAddress, abi: erc20Abi, - publicClient: client, + client, }) const [name, symbol, decimals, totalSupply] = await Promise.all([ contract.read.name(), diff --git a/src/hooks/useReadContract.ts b/src/hooks/useReadContract.ts index 84af552..240fdee 100644 --- a/src/hooks/useReadContract.ts +++ b/src/hooks/useReadContract.ts @@ -4,6 +4,7 @@ import { type BaseError, type CallParameters, type Client, + type ContractFunctionName, type DecodeFunctionResultParameters, type EncodeFunctionDataParameters, type Hash, @@ -18,7 +19,10 @@ import { useClient } from './useClient' type ReadContractParameters< TAbi extends Abi | readonly unknown[] = Abi, - TFunctionName extends string = string, + TFunctionName extends ContractFunctionName< + TAbi, + 'pure' | 'view' + > = ContractFunctionName, > = ReadContractParameters_viem & { enabled?: boolean raw?: boolean @@ -31,7 +35,10 @@ export const readContractQueryKey = createQueryKey< export function useReadContractQueryOptions< const TAbi extends Abi | readonly unknown[] = Abi, - TFunctionName extends string = string, + TFunctionName extends ContractFunctionName< + TAbi, + 'pure' | 'view' + > = ContractFunctionName, >(params: ReadContractParameters) { const client = useClient() return queryOptions({ @@ -72,7 +79,10 @@ export function useReadContractQueryOptions< export function useReadContract< const TAbi extends Abi | readonly unknown[] = Abi, - TFunctionName extends string = string, + TFunctionName extends ContractFunctionName< + TAbi, + 'pure' | 'view' + > = ContractFunctionName, >(args: ReadContractParameters) { const queryOptions = useReadContractQueryOptions(args) return useQuery(queryOptions) diff --git a/src/hooks/useWriteContract.ts b/src/hooks/useWriteContract.ts index d4cad5d..e17c9ed 100644 --- a/src/hooks/useWriteContract.ts +++ b/src/hooks/useWriteContract.ts @@ -1,21 +1,38 @@ import { useMutation } from '@tanstack/react-query' -import type { Abi, Account, Chain, WriteContractParameters } from 'viem' +import type { + Abi, + Account, + Chain, + ContractFunctionArgs, + ContractFunctionName, + WriteContractParameters, +} from 'viem' import { useClient } from './useClient' type UseWriteContractParameters< TAbi extends Abi | readonly unknown[], - TFunctionName extends string, -> = WriteContractParameters + TFunctionName extends ContractFunctionName, + TArgs extends ContractFunctionArgs< + TAbi, + 'nonpayable' | 'payable', + TFunctionName + > = ContractFunctionArgs, +> = WriteContractParameters export function useWriteContract< const TAbi extends Abi | readonly unknown[], - TFunctionName extends string, + TFunctionName extends ContractFunctionName, + TArgs extends ContractFunctionArgs< + TAbi, + 'nonpayable' | 'payable', + TFunctionName + >, >() { const client = useClient() return useMutation({ - mutationFn(args: UseWriteContractParameters) { + mutationFn(args: UseWriteContractParameters) { return client.writeContract({ ...args, chain: null } as any) }, }) diff --git a/src/messengers/schema.ts b/src/messengers/schema.ts index 2c3e709..3493a96 100644 --- a/src/messengers/schema.ts +++ b/src/messengers/schema.ts @@ -1,10 +1,8 @@ -import type { Address, EIP1193Parameters, EIP1474Methods } from 'viem' -import type { RpcResponse } from 'viem/utils' +import type { Address } from 'viem' +import type { RpcRequest, RpcResponse } from '~/types/rpc' import type { SessionsState } from '~/zustand' -export type RpcRequest = EIP1193Parameters & { id: number } - export type Schema = { accountsChanged: [ payload: { accounts: Address[]; sessions: SessionsState['sessions'] }, diff --git a/src/provider.ts b/src/provider.ts index e19a7a6..2b7238f 100644 --- a/src/provider.ts +++ b/src/provider.ts @@ -7,7 +7,7 @@ import { UserRejectedRequestError, } from '~/errors' import type { Messenger } from '~/messengers' -import type { RpcRequest } from '~/messengers/schema' +import type { RpcRequest } from '~/types/rpc' const providerCache = new Map() export function getProvider({ diff --git a/src/types/rpc.ts b/src/types/rpc.ts new file mode 100644 index 0000000..7632d5e --- /dev/null +++ b/src/types/rpc.ts @@ -0,0 +1,39 @@ +import type { EIP1193Parameters, EIP1474Methods } from 'viem' + +type SuccessResult = { + method?: never | undefined + result: T + error?: never | undefined +} +type ErrorResult = { + method?: never | undefined + result?: never | undefined + error: T +} +type Subscription = { + method: 'eth_subscription' + error?: never | undefined + result?: never | undefined + params: { + subscription: string + } & ( + | { + result: TResult + error?: never | undefined + } + | { + result?: never | undefined + error: TError + } + ) +} +export type RpcResponse = { + jsonrpc: `${number}` + id: number +} & ( + | SuccessResult + | ErrorResult + | Subscription +) + +export type RpcRequest = EIP1193Parameters & { id: number } diff --git a/src/utils/types.ts b/src/types/utils.ts similarity index 100% rename from src/utils/types.ts rename to src/types/utils.ts diff --git a/src/utils/abi.ts b/src/utils/abi.ts index 8df34ef..7d9a8c7 100644 --- a/src/utils/abi.ts +++ b/src/utils/abi.ts @@ -4,6 +4,7 @@ import type { AbiEvent } from 'abitype' import { FunctionFragment } from 'ethers' import { type AbiItem, + type ContractEventName, type DecodeEventLogParameters, type Hex, decodeEventLog, @@ -18,7 +19,13 @@ export function decodeEventLogs_guessed< data, topics, }: { abiItem: AbiEvent } & Pick< - DecodeEventLogParameters<[TAbiEvent], string, TTopics, TData, true>, + DecodeEventLogParameters< + [TAbiEvent], + ContractEventName<[TAbiEvent]>, + TTopics, + TData, + true + >, 'data' | 'topics' >) { const indexedValues = topics.slice(1) diff --git a/src/zustand/account.ts b/src/zustand/account.ts index ee2198c..c7ece94 100644 --- a/src/zustand/account.ts +++ b/src/zustand/account.ts @@ -1,13 +1,12 @@ +import { uniqBy } from 'remeda' import type { Address, JsonRpcAccount as JsonRpcAccount_, LocalAccount, } from 'viem' - import { useSyncExternalStoreWithTracked } from '~/hooks/useSyncExternalStoreWithTracked' +import type { OneOf } from '~/types/utils' -import { uniqBy } from 'remeda' -import type { OneOf } from '../utils/types' import { createStore } from './utils' // Only support JSON-RPC Accounts for now. In the future, we may want to add support diff --git a/src/zustand/contracts.ts b/src/zustand/contracts.ts index d5ca6af..5d75499 100644 --- a/src/zustand/contracts.ts +++ b/src/zustand/contracts.ts @@ -3,7 +3,8 @@ import type { Abi, Address } from 'abitype' import type { Hex, TransactionReceipt } from 'viem' import { useStore } from 'zustand' -import type { RequiredBy } from '~/utils/types' +import type { RequiredBy } from '~/types/utils' + import { createStore, getKey } from './utils' type Contract = { diff --git a/src/zustand/pending-requests.ts b/src/zustand/pending-requests.ts index c969abc..c2f5cfe 100644 --- a/src/zustand/pending-requests.ts +++ b/src/zustand/pending-requests.ts @@ -1,5 +1,5 @@ import { useSyncExternalStoreWithTracked } from '~/hooks/useSyncExternalStoreWithTracked' -import type { RpcRequest } from '~/messengers/schema' +import type { RpcRequest } from '~/types/rpc' import { createStore } from './utils' diff --git a/test/dapp/App.tsx b/test/dapp/App.tsx index 29a0f1d..f23a52e 100644 --- a/test/dapp/App.tsx +++ b/test/dapp/App.tsx @@ -557,7 +557,7 @@ function ContractPlayground() { chain: null, }) const transaction = await client.waitForTransactionReceipt({ hash }) - setDeployedAddress(transaction.contractAddress) + setDeployedAddress(transaction.contractAddress!) } const test_rivet_1 = async (e: React.FormEvent) => { @@ -619,7 +619,7 @@ function ContractMockERC20() { args: ['MockERC20', 'M20', 18], }) const transaction = await client.waitForTransactionReceipt({ hash }) - setDeployedAddress(transaction.contractAddress) + setDeployedAddress(transaction.contractAddress!) } const mint = async (e: React.FormEvent) => { @@ -665,7 +665,7 @@ function ContractMockERC721() { args: ['MockERC721', 'M721'], }) const transaction = await client.waitForTransactionReceipt({ hash }) - setDeployedAddress(transaction.contractAddress) + setDeployedAddress(transaction.contractAddress!) } const mint = async (e: React.FormEvent) => {