Add onPurchaseSuccess callback for Pay (#4101)
## Problem solved
Short description of the bug fixed or feature added
<!-- start pr-codex -->
---
## PR-Codex overview
This PR adds `onPurchaseSuccess` callback to various components and hooks in the codebase, triggering when a user completes a purchase using thirdweb pay.
### Detailed summary
- Added `onPurchaseSuccess` callback to `PayEmbed`, `ConnectButton`, `TransactionButton`, and `useSendTransaction`
- Updated props in multiple components to include `onSuccess` callback parameter
- Added type definitions for `BuyWithCryptoStatus` and `BuyWithFiatStatus`
- Implemented logic to call `onSuccess` callback upon successful purchase completion
> The following files were skipped due to too many changes: `packages/thirdweb/src/react/web/ui/ConnectWallet/screens/Buy/fiat/FiatFlow.tsx`
> ✨ Ask PR-Codex anything about this PR by commenting with `/codex {your question}`
<!-- end pr-codex -->
This commit is contained in:
@@ -0,0 +1,52 @@
|
|||||||
|
---
|
||||||
|
"thirdweb": patch
|
||||||
|
---
|
||||||
|
|
||||||
|
Add `onPurchaseSuccess` callback to `PayEmbed`, `ConnectButton`, `TransactionButton` and `useSendTransaction` and gets called when user completes the purchase using thirdweb pay.
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
<PayEmbed
|
||||||
|
client={client}
|
||||||
|
payOptions={{
|
||||||
|
onPurchaseSuccess(info) {
|
||||||
|
console.log("purchase success", info);
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
```
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
<ConnectButton
|
||||||
|
client={client}
|
||||||
|
detailsModal={{
|
||||||
|
payOptions: {
|
||||||
|
onPurchaseSuccess(info) {
|
||||||
|
console.log("purchase success", info);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
```
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
<TransactionButton
|
||||||
|
transaction={...}
|
||||||
|
payModal={{
|
||||||
|
onPurchaseSuccess(info) {
|
||||||
|
console.log("purchase success", info);
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Some Transaction
|
||||||
|
</TransactionButton>
|
||||||
|
```
|
||||||
|
|
||||||
|
```ts
|
||||||
|
const sendTransaction = useSendTransaction({
|
||||||
|
payModal: {
|
||||||
|
onPurchaseSuccess(info) {
|
||||||
|
console.log("purchase success", info);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
```
|
||||||
Vendored
+3
@@ -18,5 +18,8 @@
|
|||||||
},
|
},
|
||||||
"[json]": {
|
"[json]": {
|
||||||
"editor.defaultFormatter": "biomejs.biome"
|
"editor.defaultFormatter": "biomejs.biome"
|
||||||
|
},
|
||||||
|
"[markdown]": {
|
||||||
|
"editor.defaultFormatter": "esbenp.prettier-vscode"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Submodule
+1
Submodule apps/hardhat-boilerplate added at 638fd58ec8
@@ -1,5 +1,7 @@
|
|||||||
import type { Chain } from "../../../../chains/types.js";
|
import type { Chain } from "../../../../chains/types.js";
|
||||||
import type { ThirdwebClient } from "../../../../client/client.js";
|
import type { ThirdwebClient } from "../../../../client/client.js";
|
||||||
|
import type { BuyWithCryptoStatus } from "../../../../pay/buyWithCrypto/getStatus.js";
|
||||||
|
import type { BuyWithFiatStatus } from "../../../../pay/buyWithFiat/getStatus.js";
|
||||||
import type { PreparedTransaction } from "../../../../transaction/prepare-transaction.js";
|
import type { PreparedTransaction } from "../../../../transaction/prepare-transaction.js";
|
||||||
import type { Prettify } from "../../../../utils/type-utils.js";
|
import type { Prettify } from "../../../../utils/type-utils.js";
|
||||||
import type { Account, Wallet } from "../../../../wallets/interfaces/wallet.js";
|
import type { Account, Wallet } from "../../../../wallets/interfaces/wallet.js";
|
||||||
@@ -89,6 +91,21 @@ export type PayUIOptions = Prettify<
|
|||||||
* This details will be stored with the purchase and can be retrieved later via the status API or Webhook
|
* This details will be stored with the purchase and can be retrieved later via the status API or Webhook
|
||||||
*/
|
*/
|
||||||
purchaseData?: object;
|
purchaseData?: object;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Callback to be called when the user successfully completes the purchase.
|
||||||
|
*/
|
||||||
|
onPurchaseSuccess?: (
|
||||||
|
info:
|
||||||
|
| {
|
||||||
|
type: "crypto";
|
||||||
|
status: BuyWithCryptoStatus;
|
||||||
|
}
|
||||||
|
| {
|
||||||
|
type: "fiat";
|
||||||
|
status: BuyWithFiatStatus;
|
||||||
|
},
|
||||||
|
) => void;
|
||||||
} & (FundWalletOptions | DirectPaymentOptions | TranasctionOptions)
|
} & (FundWalletOptions | DirectPaymentOptions | TranasctionOptions)
|
||||||
>;
|
>;
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
import { type UseMutationResult, useMutation } from "@tanstack/react-query";
|
import { type UseMutationResult, useMutation } from "@tanstack/react-query";
|
||||||
import type { Chain } from "../../../../chains/types.js";
|
import type { Chain } from "../../../../chains/types.js";
|
||||||
|
import type { BuyWithCryptoStatus } from "../../../../pay/buyWithCrypto/getStatus.js";
|
||||||
|
import type { BuyWithFiatStatus } from "../../../../pay/buyWithFiat/getStatus.js";
|
||||||
import type { GaslessOptions } from "../../../../transaction/actions/gasless/types.js";
|
import type { GaslessOptions } from "../../../../transaction/actions/gasless/types.js";
|
||||||
import { sendTransaction } from "../../../../transaction/actions/send-transaction.js";
|
import { sendTransaction } from "../../../../transaction/actions/send-transaction.js";
|
||||||
import type { WaitForReceiptOptions } from "../../../../transaction/actions/wait-for-tx-receipt.js";
|
import type { WaitForReceiptOptions } from "../../../../transaction/actions/wait-for-tx-receipt.js";
|
||||||
@@ -46,6 +48,20 @@ export type SendTransactionPayModalConfig =
|
|||||||
testMode?: boolean;
|
testMode?: boolean;
|
||||||
};
|
};
|
||||||
purchaseData?: object;
|
purchaseData?: object;
|
||||||
|
/**
|
||||||
|
* Callback to be called when the user successfully completes the purchase.
|
||||||
|
*/
|
||||||
|
onPurchaseSuccess?: (
|
||||||
|
info:
|
||||||
|
| {
|
||||||
|
type: "crypto";
|
||||||
|
status: BuyWithCryptoStatus;
|
||||||
|
}
|
||||||
|
| {
|
||||||
|
type: "fiat";
|
||||||
|
status: BuyWithFiatStatus;
|
||||||
|
},
|
||||||
|
) => void;
|
||||||
}
|
}
|
||||||
| false;
|
| false;
|
||||||
|
|
||||||
|
|||||||
@@ -132,6 +132,7 @@ export function useSendTransaction(config: SendTransactionConfig = {}) {
|
|||||||
mode: "transaction",
|
mode: "transaction",
|
||||||
transaction: data.tx,
|
transaction: data.tx,
|
||||||
metadata: payModal?.metadata,
|
metadata: payModal?.metadata,
|
||||||
|
onPurchaseSuccess: payModal?.onPurchaseSuccess,
|
||||||
}}
|
}}
|
||||||
/>,
|
/>,
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -4,6 +4,8 @@ import type { Chain } from "../../../../../../chains/types.js";
|
|||||||
import type { ThirdwebClient } from "../../../../../../client/client.js";
|
import type { ThirdwebClient } from "../../../../../../client/client.js";
|
||||||
import { NATIVE_TOKEN_ADDRESS } from "../../../../../../constants/addresses.js";
|
import { NATIVE_TOKEN_ADDRESS } from "../../../../../../constants/addresses.js";
|
||||||
import type { GetBuyWithCryptoQuoteParams } from "../../../../../../pay/buyWithCrypto/getQuote.js";
|
import type { GetBuyWithCryptoQuoteParams } from "../../../../../../pay/buyWithCrypto/getQuote.js";
|
||||||
|
import type { BuyWithCryptoStatus } from "../../../../../../pay/buyWithCrypto/getStatus.js";
|
||||||
|
import type { BuyWithFiatStatus } from "../../../../../../pay/buyWithFiat/getStatus.js";
|
||||||
import { isSwapRequiredPostOnramp } from "../../../../../../pay/buyWithFiat/isSwapRequiredPostOnramp.js";
|
import { isSwapRequiredPostOnramp } from "../../../../../../pay/buyWithFiat/isSwapRequiredPostOnramp.js";
|
||||||
import { formatNumber } from "../../../../../../utils/formatNumber.js";
|
import { formatNumber } from "../../../../../../utils/formatNumber.js";
|
||||||
import type { Account } from "../../../../../../wallets/interfaces/wallet.js";
|
import type { Account } from "../../../../../../wallets/interfaces/wallet.js";
|
||||||
@@ -204,6 +206,26 @@ function BuyScreenContent(props: BuyScreenContentProps) {
|
|||||||
|
|
||||||
// screens ----------------------------
|
// screens ----------------------------
|
||||||
|
|
||||||
|
const onSwapSuccess = useCallback(
|
||||||
|
(_status: BuyWithCryptoStatus) => {
|
||||||
|
props.payOptions.onPurchaseSuccess?.({
|
||||||
|
type: "crypto",
|
||||||
|
status: _status,
|
||||||
|
});
|
||||||
|
},
|
||||||
|
[props.payOptions.onPurchaseSuccess],
|
||||||
|
);
|
||||||
|
|
||||||
|
const onFiatSuccess = useCallback(
|
||||||
|
(_status: BuyWithFiatStatus) => {
|
||||||
|
props.payOptions.onPurchaseSuccess?.({
|
||||||
|
type: "fiat",
|
||||||
|
status: _status,
|
||||||
|
});
|
||||||
|
},
|
||||||
|
[props.payOptions.onPurchaseSuccess],
|
||||||
|
);
|
||||||
|
|
||||||
if (screen.id === "connect-payer-wallet") {
|
if (screen.id === "connect-payer-wallet") {
|
||||||
return (
|
return (
|
||||||
<WalletSwitcherConnectionScreen
|
<WalletSwitcherConnectionScreen
|
||||||
@@ -259,6 +281,7 @@ function BuyScreenContent(props: BuyScreenContentProps) {
|
|||||||
id: "buy-with-crypto",
|
id: "buy-with-crypto",
|
||||||
});
|
});
|
||||||
}}
|
}}
|
||||||
|
onSuccess={onSwapSuccess}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -284,6 +307,7 @@ function BuyScreenContent(props: BuyScreenContentProps) {
|
|||||||
onDone={onDone}
|
onDone={onDone}
|
||||||
isEmbed={props.isEmbed}
|
isEmbed={props.isEmbed}
|
||||||
payer={payer}
|
payer={payer}
|
||||||
|
onSuccess={onFiatSuccess}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,10 @@
|
|||||||
import { useState } from "react";
|
import { useCallback, useState } from "react";
|
||||||
import type { ThirdwebClient } from "../../../../../../../client/client.js";
|
import type { ThirdwebClient } from "../../../../../../../client/client.js";
|
||||||
import type { BuyWithFiatQuote } from "../../../../../../../pay/buyWithFiat/getQuote.js";
|
import type { BuyWithFiatQuote } from "../../../../../../../pay/buyWithFiat/getQuote.js";
|
||||||
import type { BuyWithFiatStatus } from "../../../../../../../pay/buyWithFiat/getStatus.js";
|
import {
|
||||||
|
type BuyWithFiatStatus,
|
||||||
|
getBuyWithFiatStatus,
|
||||||
|
} from "../../../../../../../pay/buyWithFiat/getStatus.js";
|
||||||
import { isSwapRequiredPostOnramp } from "../../../../../../../pay/buyWithFiat/isSwapRequiredPostOnramp.js";
|
import { isSwapRequiredPostOnramp } from "../../../../../../../pay/buyWithFiat/isSwapRequiredPostOnramp.js";
|
||||||
import { openOnrampPopup } from "../openOnRamppopup.js";
|
import { openOnrampPopup } from "../openOnRamppopup.js";
|
||||||
import { addPendingTx } from "../swap/pendingSwapTx.js";
|
import { addPendingTx } from "../swap/pendingSwapTx.js";
|
||||||
@@ -48,6 +51,7 @@ export function FiatFlow(props: {
|
|||||||
transactionMode: boolean;
|
transactionMode: boolean;
|
||||||
isEmbed: boolean;
|
isEmbed: boolean;
|
||||||
payer: PayerInfo;
|
payer: PayerInfo;
|
||||||
|
onSuccess: (status: BuyWithFiatStatus) => void;
|
||||||
}) {
|
}) {
|
||||||
const hasTwoSteps = isSwapRequiredPostOnramp(props.quote);
|
const hasTwoSteps = isSwapRequiredPostOnramp(props.quote);
|
||||||
const [screen, setScreen] = useState<Screen>(
|
const [screen, setScreen] = useState<Screen>(
|
||||||
@@ -101,10 +105,21 @@ export function FiatFlow(props: {
|
|||||||
}}
|
}}
|
||||||
transactionMode={props.transactionMode}
|
transactionMode={props.transactionMode}
|
||||||
isEmbed={props.isEmbed}
|
isEmbed={props.isEmbed}
|
||||||
|
onSuccess={props.onSuccess}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const onPostOnrampSuccess = useCallback(() => {
|
||||||
|
// report the status of fiat status instead of post onramp swap status when post onramp swap is successful
|
||||||
|
getBuyWithFiatStatus({
|
||||||
|
intentId: props.quote.intentId,
|
||||||
|
client: props.client,
|
||||||
|
}).then((status) => {
|
||||||
|
props.onSuccess(status);
|
||||||
|
});
|
||||||
|
}, [props.onSuccess, props.quote.intentId, props.client]);
|
||||||
|
|
||||||
if (screen.id === "postonramp-swap") {
|
if (screen.id === "postonramp-swap") {
|
||||||
return (
|
return (
|
||||||
<PostOnRampSwapFlow
|
<PostOnRampSwapFlow
|
||||||
@@ -120,6 +135,7 @@ export function FiatFlow(props: {
|
|||||||
transactionMode={props.transactionMode}
|
transactionMode={props.transactionMode}
|
||||||
isEmbed={props.isEmbed}
|
isEmbed={props.isEmbed}
|
||||||
payer={props.payer}
|
payer={props.payer}
|
||||||
|
onSuccess={onPostOnrampSuccess}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
+14
-1
@@ -41,9 +41,10 @@ export function OnrampStatusScreen(props: {
|
|||||||
onShowSwapFlow: (status: BuyWithFiatStatus) => void;
|
onShowSwapFlow: (status: BuyWithFiatStatus) => void;
|
||||||
transactionMode: boolean;
|
transactionMode: boolean;
|
||||||
isEmbed: boolean;
|
isEmbed: boolean;
|
||||||
|
onSuccess: ((status: BuyWithFiatStatus) => void) | undefined;
|
||||||
}) {
|
}) {
|
||||||
const queryClient = useQueryClient();
|
const queryClient = useQueryClient();
|
||||||
const { openedWindow } = props;
|
const { openedWindow, onSuccess } = props;
|
||||||
const statusQuery = useBuyWithFiatStatus({
|
const statusQuery = useBuyWithFiatStatus({
|
||||||
intentId: props.intentId,
|
intentId: props.intentId,
|
||||||
client: props.client,
|
client: props.client,
|
||||||
@@ -62,6 +63,18 @@ export function OnrampStatusScreen(props: {
|
|||||||
uiStatus = "completed";
|
uiStatus = "completed";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const purchaseCbCalled = useRef(false);
|
||||||
|
useEffect(() => {
|
||||||
|
if (purchaseCbCalled.current || !onSuccess) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (statusQuery.data?.status === "ON_RAMP_TRANSFER_COMPLETED") {
|
||||||
|
purchaseCbCalled.current = true;
|
||||||
|
onSuccess(statusQuery.data);
|
||||||
|
}
|
||||||
|
}, [onSuccess, statusQuery.data]);
|
||||||
|
|
||||||
// close the onramp popup if onramp is completed
|
// close the onramp popup if onramp is completed
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!openedWindow || !statusQuery.data) {
|
if (!openedWindow || !statusQuery.data) {
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ import { useQuery } from "@tanstack/react-query";
|
|||||||
import { useEffect, useState } from "react";
|
import { useEffect, useState } from "react";
|
||||||
import type { ThirdwebClient } from "../../../../../../../client/client.js";
|
import type { ThirdwebClient } from "../../../../../../../client/client.js";
|
||||||
import type { BuyWithCryptoQuote } from "../../../../../../../pay/buyWithCrypto/getQuote.js";
|
import type { BuyWithCryptoQuote } from "../../../../../../../pay/buyWithCrypto/getQuote.js";
|
||||||
|
import type { BuyWithCryptoStatus } from "../../../../../../../pay/buyWithCrypto/getStatus.js";
|
||||||
import { getPostOnRampQuote } from "../../../../../../../pay/buyWithFiat/getPostOnRampQuote.js";
|
import { getPostOnRampQuote } from "../../../../../../../pay/buyWithFiat/getPostOnRampQuote.js";
|
||||||
import type { BuyWithFiatStatus } from "../../../../../../../pay/buyWithFiat/getStatus.js";
|
import type { BuyWithFiatStatus } from "../../../../../../../pay/buyWithFiat/getStatus.js";
|
||||||
import { iconSize } from "../../../../../../core/design-system/index.js";
|
import { iconSize } from "../../../../../../core/design-system/index.js";
|
||||||
@@ -23,6 +24,7 @@ export function PostOnRampSwap(props: {
|
|||||||
transactionMode: boolean;
|
transactionMode: boolean;
|
||||||
isEmbed: boolean;
|
isEmbed: boolean;
|
||||||
payer: PayerInfo;
|
payer: PayerInfo;
|
||||||
|
onSuccess: ((status: BuyWithCryptoStatus) => void) | undefined;
|
||||||
}) {
|
}) {
|
||||||
const [lockedOnRampQuote, setLockedOnRampQuote] = useState<
|
const [lockedOnRampQuote, setLockedOnRampQuote] = useState<
|
||||||
BuyWithCryptoQuote | undefined
|
BuyWithCryptoQuote | undefined
|
||||||
@@ -130,6 +132,7 @@ export function PostOnRampSwap(props: {
|
|||||||
}}
|
}}
|
||||||
transactionMode={props.transactionMode}
|
transactionMode={props.transactionMode}
|
||||||
isEmbed={props.isEmbed}
|
isEmbed={props.isEmbed}
|
||||||
|
onSuccess={props.onSuccess}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
+3
@@ -1,5 +1,6 @@
|
|||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
import type { ThirdwebClient } from "../../../../../../../client/client.js";
|
import type { ThirdwebClient } from "../../../../../../../client/client.js";
|
||||||
|
import type { BuyWithCryptoStatus } from "../../../../../../../pay/buyWithCrypto/getStatus.js";
|
||||||
import type { BuyWithFiatStatus } from "../../../../../../../pay/buyWithFiat/getStatus.js";
|
import type { BuyWithFiatStatus } from "../../../../../../../pay/buyWithFiat/getStatus.js";
|
||||||
import type { PayerInfo } from "../types.js";
|
import type { PayerInfo } from "../types.js";
|
||||||
import { type BuyWithFiatPartialQuote, FiatSteps } from "./FiatSteps.js";
|
import { type BuyWithFiatPartialQuote, FiatSteps } from "./FiatSteps.js";
|
||||||
@@ -22,6 +23,7 @@ export function PostOnRampSwapFlow(props: {
|
|||||||
transactionMode: boolean;
|
transactionMode: boolean;
|
||||||
isEmbed: boolean;
|
isEmbed: boolean;
|
||||||
payer: PayerInfo;
|
payer: PayerInfo;
|
||||||
|
onSuccess: ((status: BuyWithCryptoStatus) => void) | undefined;
|
||||||
}) {
|
}) {
|
||||||
const [statusForSwap, setStatusForSwap] = useState<
|
const [statusForSwap, setStatusForSwap] = useState<
|
||||||
BuyWithFiatStatus | undefined
|
BuyWithFiatStatus | undefined
|
||||||
@@ -38,6 +40,7 @@ export function PostOnRampSwapFlow(props: {
|
|||||||
transactionMode={props.transactionMode}
|
transactionMode={props.transactionMode}
|
||||||
isEmbed={props.isEmbed}
|
isEmbed={props.isEmbed}
|
||||||
payer={props.payer}
|
payer={props.payer}
|
||||||
|
onSuccess={props.onSuccess}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
+2
@@ -73,6 +73,8 @@ export function FiatDetailsScreen(props: {
|
|||||||
setStopPolling(true);
|
setStopPolling(true);
|
||||||
}}
|
}}
|
||||||
payer={props.payer}
|
payer={props.payer}
|
||||||
|
// viewing history - ignore onSuccess
|
||||||
|
onSuccess={undefined}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import { getCachedChain } from "../../../../../../../chains/utils.js";
|
|||||||
import type { ThirdwebClient } from "../../../../../../../client/client.js";
|
import type { ThirdwebClient } from "../../../../../../../client/client.js";
|
||||||
import { NATIVE_TOKEN_ADDRESS } from "../../../../../../../constants/addresses.js";
|
import { NATIVE_TOKEN_ADDRESS } from "../../../../../../../constants/addresses.js";
|
||||||
import type { BuyWithCryptoQuote } from "../../../../../../../pay/buyWithCrypto/getQuote.js";
|
import type { BuyWithCryptoQuote } from "../../../../../../../pay/buyWithCrypto/getQuote.js";
|
||||||
|
import type { BuyWithCryptoStatus } from "../../../../../../../pay/buyWithCrypto/getStatus.js";
|
||||||
import type { TokenInfo } from "../../../../../../core/utils/defaultTokens.js";
|
import type { TokenInfo } from "../../../../../../core/utils/defaultTokens.js";
|
||||||
import { type ERC20OrNativeToken, NATIVE_TOKEN } from "../../nativeToken.js";
|
import { type ERC20OrNativeToken, NATIVE_TOKEN } from "../../nativeToken.js";
|
||||||
import type { PayerInfo } from "../types.js";
|
import type { PayerInfo } from "../types.js";
|
||||||
@@ -20,6 +21,7 @@ type SwapFlowProps = {
|
|||||||
onTryAgain: () => void;
|
onTryAgain: () => void;
|
||||||
transactionMode: boolean;
|
transactionMode: boolean;
|
||||||
isEmbed: boolean;
|
isEmbed: boolean;
|
||||||
|
onSuccess: ((status: BuyWithCryptoStatus) => void) | undefined;
|
||||||
};
|
};
|
||||||
|
|
||||||
export function SwapFlow(props: SwapFlowProps) {
|
export function SwapFlow(props: SwapFlowProps) {
|
||||||
@@ -84,6 +86,7 @@ export function SwapFlow(props: SwapFlowProps) {
|
|||||||
transactionMode={props.transactionMode}
|
transactionMode={props.transactionMode}
|
||||||
isEmbed={props.isEmbed}
|
isEmbed={props.isEmbed}
|
||||||
quote={quote}
|
quote={quote}
|
||||||
|
onSuccess={props.onSuccess}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
+16
@@ -3,6 +3,7 @@ import { useQueryClient } from "@tanstack/react-query";
|
|||||||
import { useEffect, useRef } from "react";
|
import { useEffect, useRef } from "react";
|
||||||
import type { ThirdwebClient } from "../../../../../../../client/client.js";
|
import type { ThirdwebClient } from "../../../../../../../client/client.js";
|
||||||
import type { BuyWithCryptoQuote } from "../../../../../../../pay/buyWithCrypto/getQuote.js";
|
import type { BuyWithCryptoQuote } from "../../../../../../../pay/buyWithCrypto/getQuote.js";
|
||||||
|
import type { BuyWithCryptoStatus } from "../../../../../../../pay/buyWithCrypto/getStatus.js";
|
||||||
import { iconSize } from "../../../../../../core/design-system/index.js";
|
import { iconSize } from "../../../../../../core/design-system/index.js";
|
||||||
import { useBuyWithCryptoStatus } from "../../../../../../core/hooks/pay/useBuyWithCryptoStatus.js";
|
import { useBuyWithCryptoStatus } from "../../../../../../core/hooks/pay/useBuyWithCryptoStatus.js";
|
||||||
import { invalidateWalletBalance } from "../../../../../../core/providers/invalidateWalletBalance.js";
|
import { invalidateWalletBalance } from "../../../../../../core/providers/invalidateWalletBalance.js";
|
||||||
@@ -26,7 +27,10 @@ export function SwapStatusScreen(props: {
|
|||||||
transactionMode: boolean;
|
transactionMode: boolean;
|
||||||
isEmbed: boolean;
|
isEmbed: boolean;
|
||||||
quote: BuyWithCryptoQuote;
|
quote: BuyWithCryptoQuote;
|
||||||
|
onSuccess: ((status: BuyWithCryptoStatus) => void) | undefined;
|
||||||
}) {
|
}) {
|
||||||
|
const { onSuccess } = props;
|
||||||
|
|
||||||
const swapStatus = useBuyWithCryptoStatus({
|
const swapStatus = useBuyWithCryptoStatus({
|
||||||
client: props.client,
|
client: props.client,
|
||||||
transactionHash: props.swapTxHash,
|
transactionHash: props.swapTxHash,
|
||||||
@@ -46,6 +50,18 @@ export function SwapStatusScreen(props: {
|
|||||||
uiStatus = "partialSuccess";
|
uiStatus = "partialSuccess";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const purchaseCbCalled = useRef(false);
|
||||||
|
useEffect(() => {
|
||||||
|
if (purchaseCbCalled.current || !onSuccess) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (swapStatus.data?.status === "COMPLETED") {
|
||||||
|
purchaseCbCalled.current = true;
|
||||||
|
onSuccess(swapStatus.data);
|
||||||
|
}
|
||||||
|
}, [onSuccess, swapStatus]);
|
||||||
|
|
||||||
const queryClient = useQueryClient();
|
const queryClient = useQueryClient();
|
||||||
const balanceInvalidated = useRef(false);
|
const balanceInvalidated = useRef(false);
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
|||||||
Reference in New Issue
Block a user