Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feat: useEstimateFees hook #422

Merged
merged 3 commits into from
Apr 3, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/six-crews-jog.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@starknet-react/core": minor
---

Add useEstimateFees hook to estimate smart contract calls fees
1 change: 1 addition & 0 deletions packages/core/src/hooks/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,4 @@ export * from "./useStarkAddress";
export * from "./useStarkName";
export * from "./useWaitForTransaction";
export * from "./useStarkProfile";
export * from "./useEstimateFees";
92 changes: 92 additions & 0 deletions packages/core/src/hooks/useEstimateFees.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
import { useMemo } from "react";
import {
AccountInterface,
Call,
EstimateFeeDetails,
EstimateFeeResponse,
} from "starknet";

import { UseQueryProps, UseQueryResult, useQuery } from "~/query";

import { useAccount } from "./useAccount";
import { useInvalidateOnBlock } from "./useInvalidateOnBlock";

type EstimateFeesArgs = {
/** List of smart contract calls to estimate. */
calls?: Call[];
/** Estimate Fee options. */
options?: EstimateFeeDetails;
};

/** Options for `useEstimateFees`. */
export type UseEstimateFeesProps = EstimateFeesArgs &
UseQueryProps<EstimateFeeResponse, Error, EstimateFeeResponse, ReturnType<typeof queryKey>> & {
/** Refresh data at every block. */
watch?: boolean;
};

/** Value returned from `useEstimateFees`. */
export type UseEstimateFeesResult = UseQueryResult<EstimateFeeResponse, Error>;

/**
* Hook to estimate fees for smart contract calls.
*
* @remarks
*
* The hook only performs estimation if the `calls` is not undefined.
*/
export function useEstimateFees({
calls,
options,
watch = false,
enabled: enabled_ = true,
...props
}: UseEstimateFeesProps): UseEstimateFeesResult {
const { account } = useAccount();

const queryKey_ = useMemo(
() => queryKey({ calls, options }),
[calls, options]
);

const enabled = useMemo(
() => Boolean(enabled_ && calls),
[enabled_, calls],
);

useInvalidateOnBlock({
enabled: Boolean(enabled && watch),
queryKey: queryKey_,
});

return useQuery({
queryKey: queryKey_,
queryFn: queryFn({
account,
calls,
options,
}),
...props,
});
}

function queryKey({
calls,
options,
}: EstimateFeesArgs) {
return [
{
entity: "estimateInvokeFee",
calls,
options,
},
] as const;
}

function queryFn({ account, calls, options }: { account?: AccountInterface } & EstimateFeesArgs) {
return async function () {
if (!account) throw new Error("account is required");
if (!calls || calls.length === 0) throw new Error("calls are required");
return account?.estimateInvokeFee(calls, options);
};
}
53 changes: 53 additions & 0 deletions website/content/hooks/query/useEstimateFees.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
---
title: useEstimateFees
priority: 194
hookType: query
---

Perform fee estimation for smart contract calls. Estimation then later can be used to specify the `maxFee` for the actual contract call.

## Usage

```ts
import { useAccount, useContract, useEstimateFees } from "@starknet-react/core";

export default function Component() {
const { address } = useAccount();

const { contract } = useContract({
abi: erc20ABI,
address: chain.nativeCurrency.address,
});

const calls = useMemo(() => {
if (!address || !contract) return [];
return contract.populateTransaction["transfer"]!(address, { low: 1, high: 0 });
}, [contract, address]);

const { data, isError, isLoading, error } = useEstimateFees({
calls,
watch: true,
});

if (isLoading) return <div>Loading ...</div>;
if (isError || !data) return <div>{error?.message}</div>;

return <div>Suggested Max Fee: {data.suggestedMaxFee}</div>;
}
```

## Options

- **calls**`: string`
- The contract calls to estimate fees for.
- **options**`: string`
- Estimation options.
- EstimateFeeDetails from starknet.js
- **watch?**`: boolean`
- If true, refresh data at every block.

## Returns

- **data?**`: EstimateFeeResponse`
- Estimated fees for the contract calls.
- EstimateFeeResponse from starknet.js
Loading