diff --git a/packages/core/src/hooks/useAccount.ts b/packages/core/src/hooks/useAccount.ts
index 502bc9aa..b4e91cbb 100644
--- a/packages/core/src/hooks/useAccount.ts
+++ b/packages/core/src/hooks/useAccount.ts
@@ -3,7 +3,6 @@ import { AccountInterface } from "starknet";
import { Connector } from "~/connectors";
import { useStarknetAccount } from "~/context/account";
-import { useStarknet } from "~/context/starknet";
import { useConnect } from "./useConnect";
diff --git a/packages/core/src/hooks/useBalance.test.ts b/packages/core/src/hooks/useBalance.test.ts
index 71d205da..6e7b34eb 100644
--- a/packages/core/src/hooks/useBalance.test.ts
+++ b/packages/core/src/hooks/useBalance.test.ts
@@ -1,5 +1,5 @@
import { describe, expect, it } from "vitest";
-import { account } from "../../test/devnet";
+import { accounts } from "../../test/devnet";
import { renderHook, waitFor } from "../../test/react";
import { useBalance } from "./useBalance";
@@ -28,7 +28,7 @@ describe("useBalance", () => {
// Some issue with the RPC provider.
it.skip("returns the balance", async () => {
const { result } = renderHook(() =>
- useBalance({ address: account.address }),
+ useBalance({ address: accounts.goerli[0].address }),
);
await waitFor(() => {
diff --git a/packages/core/src/hooks/useBalance.ts b/packages/core/src/hooks/useBalance.ts
index 8b9660f4..a271801a 100644
--- a/packages/core/src/hooks/useBalance.ts
+++ b/packages/core/src/hooks/useBalance.ts
@@ -10,9 +10,9 @@ import {
import { z } from "zod";
import { UseQueryProps, UseQueryResult, useQuery } from "~/query";
+
import { useContract } from "./useContract";
import { useInvalidateOnBlock } from "./useInvalidateOnBlock";
-
import { useNetwork } from "./useNetwork";
export type Balance = {
diff --git a/packages/core/src/hooks/useContract.test.ts b/packages/core/src/hooks/useContract.test.ts
index 797c2659..62ee1876 100644
--- a/packages/core/src/hooks/useContract.test.ts
+++ b/packages/core/src/hooks/useContract.test.ts
@@ -64,7 +64,7 @@ describe("useContract", () => {
"type": "function",
},
],
- "address": "0x049d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7",
+ "address": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7",
"callData": CallData {
"abi": [
{
diff --git a/packages/core/src/hooks/useContractRead.test.ts b/packages/core/src/hooks/useContractRead.test.ts
new file mode 100644
index 00000000..12ac38ae
--- /dev/null
+++ b/packages/core/src/hooks/useContractRead.test.ts
@@ -0,0 +1,61 @@
+import { Call, Contract } from "starknet";
+import { describe, expect, it } from "vitest";
+import { accounts, defaultConnector, tokenAddress } from "../../test/devnet";
+import { act, renderHook, waitFor } from "../../test/react";
+
+import { useContractRead } from "./useContractRead";
+
+const abi = [
+ {
+ members: [
+ {
+ name: "low",
+ offset: 0,
+ type: "felt",
+ },
+ {
+ name: "high",
+ offset: 1,
+ type: "felt",
+ },
+ ],
+ name: "Uint256",
+ size: 2,
+ type: "struct",
+ },
+ {
+ name: "balanceOf",
+ type: "function",
+ inputs: [
+ {
+ name: "account",
+ type: "felt",
+ },
+ ],
+ outputs: [
+ {
+ name: "balance",
+ type: "Uint256",
+ },
+ ],
+ stateMutability: "view",
+ },
+];
+
+describe("useContractRead", () => {
+ it.skip("returns the contract read result", async () => {
+ const { result } = renderHook(() =>
+ useContractRead({
+ functionName: "balanceOf",
+ args: [accounts.goerli[0].address],
+ abi,
+ address: tokenAddress,
+ watch: true,
+ }),
+ );
+
+ await waitFor(() => {
+ expect(result.current.isSuccess).toBeTruthy();
+ });
+ });
+});
diff --git a/packages/core/src/hooks/useContractRead.ts b/packages/core/src/hooks/useContractRead.ts
index e20e6f69..7eec68eb 100644
--- a/packages/core/src/hooks/useContractRead.ts
+++ b/packages/core/src/hooks/useContractRead.ts
@@ -59,6 +59,7 @@ export function useContractRead({
parseArgs,
parseResult,
watch = false,
+ enabled: enabled_ = true,
...props
}: UseContractReadProps): UseContractReadResult {
const { chain } = useNetwork();
@@ -70,8 +71,8 @@ export function useContractRead({
);
const enabled = useMemo(
- () => Boolean(props.enabled && contract && functionName && args),
- [props.enabled, contract, functionName, args],
+ () => Boolean(enabled_ && contract && functionName && args),
+ [enabled_, contract, functionName, args],
);
useInvalidateOnBlock({
diff --git a/packages/core/src/hooks/useContractWrite.test.ts b/packages/core/src/hooks/useContractWrite.test.ts
new file mode 100644
index 00000000..a7c8fa8f
--- /dev/null
+++ b/packages/core/src/hooks/useContractWrite.test.ts
@@ -0,0 +1,91 @@
+import { Call, Contract } from "starknet";
+import { describe, expect, it } from "vitest";
+import { accounts, defaultConnector, tokenAddress } from "../../test/devnet";
+import { act, renderHook, waitFor } from "../../test/react";
+import { useConnect } from "./useConnect";
+
+import { useContractWrite } from "./useContractWrite";
+
+const abi = [
+ {
+ members: [
+ {
+ name: "low",
+ offset: 0,
+ type: "felt",
+ },
+ {
+ name: "high",
+ offset: 1,
+ type: "felt",
+ },
+ ],
+ name: "Uint256",
+ size: 2,
+ type: "struct",
+ },
+ {
+ inputs: [
+ {
+ name: "recipient",
+ type: "felt",
+ },
+ {
+ name: "amount",
+ type: "Uint256",
+ },
+ ],
+ name: "transfer",
+ outputs: [
+ {
+ name: "success",
+ type: "felt",
+ },
+ ],
+ type: "function",
+ },
+];
+
+function useTestHook({ calls }: { calls: Call[] }) {
+ const writeResult = useContractWrite({
+ calls,
+ });
+ const { connectAsync, connector } = useConnect();
+ return {
+ ...writeResult,
+ connectAsync,
+ connector,
+ };
+}
+
+describe("useContractWrite", () => {
+ it.skip("returns the transaction hash in the response", async () => {
+ const contract = new Contract(abi, tokenAddress);
+ const { result } = renderHook(() =>
+ useTestHook({
+ calls: [
+ contract.populateTransaction.transfer(accounts.goerli[0].address, {
+ low: 1,
+ high: 0,
+ }),
+ ],
+ }),
+ );
+
+ await act(async () => {
+ await result.current.connectAsync({ connector: defaultConnector });
+ });
+
+ await waitFor(() => {
+ expect(result.current.connector).toBeDefined();
+ });
+
+ await act(async () => {
+ await result.current.writeAsync();
+ });
+
+ await waitFor(() => {
+ // expect(result.current).toMatchInlineSnapshot(``);
+ });
+ });
+});
diff --git a/packages/core/src/hooks/useContractWrite.ts b/packages/core/src/hooks/useContractWrite.ts
index ee619d00..b3a46e0b 100644
--- a/packages/core/src/hooks/useContractWrite.ts
+++ b/packages/core/src/hooks/useContractWrite.ts
@@ -1,3 +1,4 @@
+import { useCallback } from "react";
import {
Abi,
AccountInterface,
@@ -23,7 +24,7 @@ export type ContractWriteVariables = {
export type UseContractWriteProps = ContractWriteVariables &
UseMutationProps;
-type MutationResult = UseMutationResult<
+export type MutationResult = UseMutationResult<
InvokeFunctionResponse,
Error,
ContractWriteVariables
@@ -69,13 +70,39 @@ export function useContractWrite({
variables,
} = useMutation({
mutationKey: mutationKey({ account, calls, abis, options }),
- mutationFn: mutationFn({ account, calls, abis, options }),
+ mutationFn: mutationFn({ account }),
...props,
});
+ const write = useCallback(
+ (args?: ContractWriteVariables) => {
+ return mutate({
+ ...(args ?? {
+ calls,
+ abis,
+ options,
+ }),
+ });
+ },
+ [mutate, calls, abis, options],
+ );
+
+ const writeAsync = useCallback(
+ (args?: ContractWriteVariables) => {
+ return mutateAsync({
+ ...(args ?? {
+ calls,
+ abis,
+ options,
+ }),
+ });
+ },
+ [mutateAsync, calls, abis, options],
+ );
+
return {
- write: mutate,
- writeAsync: mutateAsync,
+ write,
+ writeAsync,
data,
error,
isError,
@@ -105,16 +132,10 @@ function mutationKey({
function mutationFn({
account,
- calls,
- abis,
- options,
}: {
account?: AccountInterface;
- calls?: Call[];
- abis?: Abi[];
- options?: InvocationsDetails;
}) {
- return async function () {
+ return async function ({ calls, abis, options }: ContractWriteVariables) {
if (!account) throw new Error("account is required");
if (!calls || calls.length === 0) throw new Error("calls are required");
return await account?.execute(calls, abis, options);
diff --git a/packages/core/src/hooks/useSign.ts b/packages/core/src/hooks/useSign.ts
index 22fec294..b337876e 100644
--- a/packages/core/src/hooks/useSign.ts
+++ b/packages/core/src/hooks/useSign.ts
@@ -4,7 +4,7 @@ import { AccountInterface, Signature, TypedData } from "starknet";
import { UseMutationProps, UseMutationResult, useMutation } from "~/query";
import { useAccount } from "./useAccount";
-type Variables = { account?: AccountInterface } & Partial;
+type Variables = Partial;
type MutationResult = UseMutationResult;
@@ -45,32 +45,34 @@ export function useSignTypedData({
variables,
} = useMutation({
mutationKey: mutationKey({ domain, types, message, primaryType }),
- mutationFn: mutateFn,
+ mutationFn: mutateFn({ account }),
...props,
});
const signTypedData = useCallback(
(args?: Partial) =>
- mutate({
- domain: args?.domain ?? domain,
- types: args?.types ?? types,
- message: args?.message ?? message,
- primaryType: args?.primaryType ?? primaryType,
- account,
- }),
- [mutate, account, domain, types, message, primaryType],
+ mutate(
+ args ?? {
+ domain,
+ types,
+ message,
+ primaryType,
+ },
+ ),
+ [mutate, domain, types, message, primaryType],
);
const signTypedDataAsync = useCallback(
(args?: Partial) =>
- mutateAsync({
- domain: args?.domain ?? domain,
- types: args?.types ?? types,
- message: args?.message ?? message,
- primaryType: args?.primaryType ?? primaryType,
- account,
- }),
- [mutateAsync, account, domain, types, message, primaryType],
+ mutateAsync(
+ args ?? {
+ domain,
+ types,
+ message,
+ primaryType,
+ },
+ ),
+ [mutateAsync, domain, types, message, primaryType],
);
return {
@@ -106,17 +108,18 @@ function mutationKey({
] as const;
}
-function mutateFn({
- account,
- domain,
- types,
- message,
- primaryType,
-}: Variables): Promise {
- if (!account) throw new Error("account is required");
- if (!domain) throw new Error("domain is required");
- if (!types) throw new Error("types is required");
- if (!message) throw new Error("message is required");
- if (!primaryType) throw new Error("primaryType is required");
- return account.signMessage({ domain, types, message, primaryType });
+function mutateFn({ account }: { account?: AccountInterface }) {
+ return function ({
+ domain,
+ types,
+ message,
+ primaryType,
+ }: Variables): Promise {
+ if (!account) throw new Error("account is required");
+ if (!domain) throw new Error("domain is required");
+ if (!types) throw new Error("types is required");
+ if (!message) throw new Error("message is required");
+ if (!primaryType) throw new Error("primaryType is required");
+ return account.signMessage({ domain, types, message, primaryType });
+ };
}
diff --git a/packages/core/src/hooks/useStarkAddress.ts b/packages/core/src/hooks/useStarkAddress.ts
index 7bc73e8f..5c43da36 100644
--- a/packages/core/src/hooks/useStarkAddress.ts
+++ b/packages/core/src/hooks/useStarkAddress.ts
@@ -42,14 +42,12 @@ export type UseStarkAddressResult = UseQueryResult;
export function useStarkAddress({
name,
contract,
+ enabled: enabled_ = true,
...props
}: UseStarkAddressProps): UseStarkAddressResult {
const { provider } = useProvider();
- const enabled = useMemo(
- () => Boolean(props.enabled && name),
- [props.enabled, name],
- );
+ const enabled = useMemo(() => Boolean(enabled_ && name), [enabled_, name]);
return useQuery({
queryKey: queryKey({ name, contract }),
diff --git a/packages/core/src/hooks/useStarkName.ts b/packages/core/src/hooks/useStarkName.ts
index e46fab9a..943cce91 100644
--- a/packages/core/src/hooks/useStarkName.ts
+++ b/packages/core/src/hooks/useStarkName.ts
@@ -61,13 +61,14 @@ export type StarkNameResult = UseQueryResult;
export function useStarkName({
address,
contract,
+ enabled: enabled_ = true,
...props
}: StarkNameArgs): StarkNameResult {
const { provider } = useProvider();
const enabled = useMemo(
- () => Boolean(props.enabled && address),
- [props.enabled, address],
+ () => Boolean(enabled_ && address),
+ [enabled_, address],
);
return useQuery({
diff --git a/packages/core/test/devnet.ts b/packages/core/test/devnet.ts
index 9df0afb5..b7cd5411 100644
--- a/packages/core/test/devnet.ts
+++ b/packages/core/test/devnet.ts
@@ -6,7 +6,7 @@ import { MockConnector } from "../src/connectors";
const provider = new RpcProvider({ nodeUrl: devnet.rpcUrls.public.http[0] });
export const tokenAddress =
- "0x049d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7";
+ "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7";
const devnetAccounts = [
{
diff --git a/website/components/demos/accounts.tsx b/website/components/demos/accounts.tsx
index 0790ef3e..a17f9d2e 100644
--- a/website/components/demos/accounts.tsx
+++ b/website/components/demos/accounts.tsx
@@ -154,7 +154,7 @@ function FundBurnerAccount({ address }: { address?: string }) {
: [],
});
const fundAccount = useCallback(async () => {
- await writeAsync({});
+ await writeAsync();
setFundedAddress(address);
}, [setFundedAddress, address, writeAsync]);
@@ -292,7 +292,7 @@ function InitializeBurnerAccount() {
{data ? null : (