Skip to content

Commit ec2ece0

Browse files
committed
[MNY-131] Add Pay Modal integration in hook
1 parent 76694f0 commit ec2ece0

File tree

9 files changed

+168
-10
lines changed

9 files changed

+168
-10
lines changed

.changeset/pretty-geese-win.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"thirdweb": patch
3+
---
4+
5+
Add Pay Modal integration in `useSendAndConfirmTransaction` hook similar to `useSendTransaction` hook

packages/thirdweb/src/exports/react.native.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ export {
5959
export type { TransactionButtonProps } from "../react/core/hooks/transaction/transaction-button-utils.js";
6060
export { useEstimateGas } from "../react/core/hooks/transaction/useEstimateGas.js";
6161
export { useEstimateGasCost } from "../react/core/hooks/transaction/useEstimateGasCost.js";
62-
export { useSendAndConfirmTransaction } from "../react/core/hooks/transaction/useSendAndConfirmTransaction.js";
62+
export { useSendAndConfirmTransactionCore as useSendAndConfirmTransaction } from "../react/core/hooks/transaction/useSendAndConfirmTransaction.js";
6363
export { useSendBatchTransaction } from "../react/core/hooks/transaction/useSendBatchTransaction.js";
6464
// transaction
6565
export type {

packages/thirdweb/src/exports/react.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,6 @@ export {
6666
export type { TransactionButtonProps } from "../react/core/hooks/transaction/transaction-button-utils.js";
6767
export { useEstimateGas } from "../react/core/hooks/transaction/useEstimateGas.js";
6868
export { useEstimateGasCost } from "../react/core/hooks/transaction/useEstimateGasCost.js";
69-
export { useSendAndConfirmTransaction } from "../react/core/hooks/transaction/useSendAndConfirmTransaction.js";
7069
export { useSendBatchTransaction } from "../react/core/hooks/transaction/useSendBatchTransaction.js";
7170
// transaction
7271
export type {
@@ -101,7 +100,6 @@ export { useConnectionManager } from "../react/core/providers/connection-manager
101100
// Social
102101
export { useSocialProfiles } from "../react/core/social/useSocialProfiles.js";
103102
export type { AccountBalanceInfo } from "../react/core/utils/account.js";
104-
105103
// utils
106104
export { createContractQuery } from "../react/core/utils/createQuery.js";
107105
// tokens
@@ -126,6 +124,7 @@ export {
126124
WalletProvider,
127125
type WalletProviderProps,
128126
} from "../react/core/wallet/provider.js";
127+
export { useSendAndConfirmTransaction } from "../react/web/hooks/transaction/useSendAndConfirmTransaction.js";
129128
export { useSendTransaction } from "../react/web/hooks/transaction/useSendTransaction.js";
130129
export { useAutoConnect } from "../react/web/hooks/wallets/useAutoConnect.js";
131130
export { useLinkProfile } from "../react/web/hooks/wallets/useLinkProfile.js";

packages/thirdweb/src/react/core/hooks/transaction/useSendAndConfirmTransaction.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ type SendAndConfirmTransactionConfig = {
5454
* ```
5555
* @transaction
5656
*/
57-
export function useSendAndConfirmTransaction(
57+
export function useSendAndConfirmTransactionCore(
5858
config: SendAndConfirmTransactionConfig = {},
5959
): UseMutationResult<
6060
TransactionReceipt,
Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
import { type UseMutationResult, useMutation } from "@tanstack/react-query";
2+
import type { GaslessOptions } from "../../../../transaction/actions/gasless/types.js";
3+
import type { SendTransactionOptions } from "../../../../transaction/actions/send-transaction.js";
4+
import { waitForReceipt } from "../../../../transaction/actions/wait-for-tx-receipt.js";
5+
import type { TransactionReceipt } from "../../../../transaction/types.js";
6+
import type { SendTransactionPayModalConfig } from "../../../core/hooks/transaction/useSendTransaction.js";
7+
import { useSendTransaction } from "./useSendTransaction.js";
8+
9+
/**
10+
* Configuration for the `useSendAndConfirmTransaction` hook.
11+
*/
12+
type SendAndConfirmTransactionConfig = {
13+
/**
14+
* Refer to [`SendTransactionPayModalConfig`](https://portal.thirdweb.com/references/typescript/v5/SendTransactionPayModalConfig) for more details.
15+
*/
16+
payModal?: SendTransactionPayModalConfig;
17+
18+
/**
19+
* Configuration for gasless transactions.
20+
* Refer to [`GaslessOptions`](https://portal.thirdweb.com/references/typescript/v5/GaslessOptions) for more details.
21+
*/
22+
gasless?: GaslessOptions;
23+
};
24+
25+
/**
26+
* A hook to send a transaction and confirm the transaction with users's connected wallet
27+
* @returns A mutation object to send a transaction.
28+
* @example
29+
* ```jsx
30+
* import { useSendAndConfirmTransaction } from "thirdweb/react";
31+
* const { mutate: sendAndConfirmTx, data: transactionReceipt } = useSendAndConfirmTransaction();
32+
*
33+
* // later
34+
* sendAndConfirmTx(tx);
35+
* ```
36+
*
37+
*
38+
* ### Gasless usage with [thirdweb Engine](https://portal.thirdweb.com/engine)
39+
* ```tsx
40+
* import { useSendAndConfirmTransaction } from "thirdweb/react";
41+
* const mutation = useSendAndConfirmTransaction({
42+
* gasless: {
43+
* provider: "engine",
44+
* relayerUrl: "https://thirdweb.engine-***.thirdweb.com/relayer/***",
45+
* relayerForwarderAddress: "0x...",
46+
* }
47+
* });
48+
* ```
49+
*
50+
* ### Gasless usage with OpenZeppelin
51+
* ```tsx
52+
* import { useSendAndConfirmTransaction } from "thirdweb/react";
53+
* const mutation = useSendAndConfirmTransaction({
54+
* gasless: {
55+
* provider: "openzeppelin",
56+
* relayerUrl: "https://...",
57+
* relayerForwarderAddress: "0x...",
58+
* }
59+
* });
60+
* ```
61+
*
62+
* ### Configuring the Pay Modal
63+
*
64+
* When the wallet does not have enough funds to send the transaction, a modal is shown to the user to buy the required funds and then continue with the transaction.
65+
*
66+
* You can configure the pay modal by passing a [`SendTransactionPayModalConfig`](https://portal.thirdweb.com/references/typescript/v5/SendTransactionPayModalConfig) object to the `payModal` config.
67+
*
68+
* ```tsx
69+
* import { useSendAndConfirmTransaction } from "thirdweb/react";
70+
*
71+
* const sendAndConfirmTx = useSendAndConfirmTransaction({
72+
* payModal: {
73+
* theme: "light",
74+
* },
75+
* });
76+
* ```
77+
*
78+
* By default, the pay modal is enabled. You can disable it by passing `payModal: false` to the config.
79+
*
80+
* ```tsx
81+
* import { useSendAndConfirmTransaction } from "thirdweb/react";
82+
*
83+
* const sendAndConfirmTx = useSendAndConfirmTransaction({
84+
* payModal: false,
85+
* });
86+
* ```
87+
* @transaction
88+
*/
89+
export function useSendAndConfirmTransaction(
90+
config: SendAndConfirmTransactionConfig = {},
91+
): UseMutationResult<
92+
TransactionReceipt,
93+
Error,
94+
SendTransactionOptions["transaction"]
95+
> {
96+
const sendTx = useSendTransaction(config);
97+
return useMutation({
98+
mutationFn: async (transaction) => {
99+
const receipt = await sendTx.mutateAsync(transaction);
100+
const confirmedReceipt = await waitForReceipt(receipt);
101+
return confirmedReceipt;
102+
},
103+
});
104+
}

packages/thirdweb/src/react/web/hooks/transaction/useSendTransaction.tsx

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,32 @@ import { TransactionModal } from "../../ui/TransactionButton/TransactionModal.js
9393
* };
9494
* ```
9595
*
96+
* ### Configuring the Pay Modal
97+
*
98+
* When the wallet does not have enough funds to send the transaction, a modal is shown to the user to buy the required funds and then continue with the transaction.
99+
*
100+
* You can configure the pay modal by passing a [`SendTransactionPayModalConfig`](https://portal.thirdweb.com/references/typescript/v5/SendTransactionPayModalConfig) object to the `payModal` config.
101+
*
102+
* ```tsx
103+
* import { useSendTransaction } from "thirdweb/react";
104+
*
105+
* const sendTx = useSendTransaction({
106+
* payModal: {
107+
* theme: "light",
108+
* },
109+
* });
110+
* ```
111+
*
112+
* By default, the pay modal is enabled. You can disable it by passing `payModal: false` to the config.
113+
*
114+
* ```tsx
115+
* import { useSendTransaction } from "thirdweb/react";
116+
*
117+
* const sendTx = useSendTransaction({
118+
* payModal: false,
119+
* });
120+
* ```
121+
*
96122
* @transaction
97123
*/
98124
export function useSendTransaction(config: SendTransactionConfig = {}) {

packages/thirdweb/src/react/web/ui/prebuilt/thirdweb/BuyDirectListingButton/index.tsx

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@ import { getListing } from "../../../../../../extensions/marketplace/direct-list
88
import type { BaseTransactionOptions } from "../../../../../../transaction/types.js";
99
import { useReadContract } from "../../../../../core/hooks/contract/useReadContract.js";
1010
import type { TransactionButtonProps } from "../../../../../core/hooks/transaction/transaction-button-utils.js";
11-
import { useSendAndConfirmTransaction } from "../../../../../core/hooks/transaction/useSendAndConfirmTransaction.js";
1211
import { useActiveAccount } from "../../../../../core/hooks/wallets/useActiveAccount.js";
12+
import { useSendAndConfirmTransaction } from "../../../../hooks/transaction/useSendAndConfirmTransaction.js";
1313
import { TransactionButton } from "../../../TransactionButton/index.js";
1414

1515
export type BuyDirectListingButtonProps = Omit<
@@ -104,7 +104,15 @@ export function BuyDirectListingButton(props: BuyDirectListingButtonProps) {
104104
},
105105
});
106106

107-
const { mutateAsync } = useSendAndConfirmTransaction();
107+
const { mutateAsync } = useSendAndConfirmTransaction({
108+
payModal:
109+
typeof payModal === "object"
110+
? {
111+
...payModal,
112+
metadata: payModal.metadata || payMetadata,
113+
}
114+
: payModal,
115+
});
108116

109117
const prepareBuyTransaction = useCallback(async () => {
110118
if (!account) {

packages/thirdweb/src/react/web/ui/prebuilt/thirdweb/ClaimButton/index.tsx

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,8 @@ import type { PreparedTransaction } from "../../../../../../transaction/prepare-
1010
import type { BaseTransactionOptions } from "../../../../../../transaction/types.js";
1111
import type { Account } from "../../../../../../wallets/interfaces/wallet.js";
1212
import { useReadContract } from "../../../../../core/hooks/contract/useReadContract.js";
13-
import { useSendAndConfirmTransaction } from "../../../../../core/hooks/transaction/useSendAndConfirmTransaction.js";
1413
import { useActiveAccount } from "../../../../../core/hooks/wallets/useActiveAccount.js";
14+
import { useSendAndConfirmTransaction } from "../../../../hooks/transaction/useSendAndConfirmTransaction.js";
1515
import { TransactionButton } from "../../../TransactionButton/index.js";
1616
import type {
1717
ClaimButtonProps,
@@ -126,7 +126,15 @@ export function ClaimButton(props: ClaimButtonProps) {
126126
tokenId: claimParams.type === "ERC1155" ? claimParams.tokenId : undefined,
127127
});
128128
const account = useActiveAccount();
129-
const { mutateAsync } = useSendAndConfirmTransaction();
129+
const { mutateAsync } = useSendAndConfirmTransaction({
130+
payModal:
131+
typeof payModal === "object"
132+
? {
133+
...payModal,
134+
metadata: payModal.metadata || payMetadata,
135+
}
136+
: payModal,
137+
});
130138
return (
131139
<TransactionButton
132140
payModal={{

packages/thirdweb/src/react/web/ui/prebuilt/thirdweb/CreateDirectListingButton/index.tsx

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,8 @@ import {
1313
import type { BaseTransactionOptions } from "../../../../../../transaction/types.js";
1414
import { useReadContract } from "../../../../../core/hooks/contract/useReadContract.js";
1515
import type { TransactionButtonProps } from "../../../../../core/hooks/transaction/transaction-button-utils.js";
16-
import { useSendAndConfirmTransaction } from "../../../../../core/hooks/transaction/useSendAndConfirmTransaction.js";
1716
import { useActiveAccount } from "../../../../../core/hooks/wallets/useActiveAccount.js";
17+
import { useSendAndConfirmTransaction } from "../../../../hooks/transaction/useSendAndConfirmTransaction.js";
1818
import { TransactionButton } from "../../../TransactionButton/index.js";
1919

2020
export type CreateDirectListingButtonProps = Omit<
@@ -88,7 +88,15 @@ export function CreateDirectListingButton(
8888
},
8989
tokenId,
9090
});
91-
const { mutateAsync } = useSendAndConfirmTransaction();
91+
const { mutateAsync } = useSendAndConfirmTransaction({
92+
payModal:
93+
typeof payModal === "object"
94+
? {
95+
...payModal,
96+
metadata: payModal.metadata || payMetadata,
97+
}
98+
: payModal,
99+
});
92100

93101
const prepareTransaction = useCallback(async () => {
94102
if (!account) {

0 commit comments

Comments
 (0)