Skip to content
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
13 changes: 13 additions & 0 deletions .changeset/better-lines-rule.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
---
"thirdweb": patch
---

Update the `onSuccess`, `onError`, and `onCancel` callback props of the `BuyWidget` to be called with the `quote` object

```tsx
<BuyWidget
onSuccess={(quote) => console.log("Swap completed:", quote)}
onError={(error, quote) => console.error("Swap failed:", error, quote)}
onCancel={(quote) => console.log("Swap cancelled:", quote)}
/>
```
56 changes: 49 additions & 7 deletions apps/dashboard/src/@/analytics/report.ts
Original file line number Diff line number Diff line change
Expand Up @@ -225,7 +225,7 @@ type AssetContractType =
*/
export function reportAssetBuySuccessful(properties: {
chainId: number;
contractType: AssetContractType;
contractType: AssetContractType | undefined;
assetType: "nft" | "coin";
}) {
posthog.capture("asset buy successful", {
Expand All @@ -243,9 +243,51 @@ type TokenSwapParams = {
pageType: "asset" | "bridge" | "chain";
};

type TokenBuyParams = {
buyTokenChainId: number | undefined;
buyTokenAddress: string | undefined;
pageType: "asset" | "bridge" | "chain";
};

/**
* ### Why do we need to report this event?
* - To track number of successful token buys
* - To track which tokens are being bought the most
*
* ### Who is responsible for this event?
* @MananTank
*/
export function reportTokenBuySuccessful(properties: TokenBuyParams) {
posthog.capture("token buy successful", properties);
}

/**
* ### Why do we need to report this event?
* - To track number of failed token buys
* - To track which token buys are failing
*
* ### Who is responsible for this event?
* @MananTank
*/
export function reportTokenBuyFailed(properties: TokenBuyParams) {
posthog.capture("token buy failed", properties);
}

/**
* ### Why do we need to report this event?
* - To track number of successful token swaps from the token page
* - To track number of cancelled token buys
* - To track which token buys are being cancelled
*
* ### Who is responsible for this event?
* @MananTank
*/
export function reportTokenBuyCancelled(properties: TokenBuyParams) {
posthog.capture("token buy cancelled", properties);
}

/**
* ### Why do we need to report this event?
* - To track number of successful token swaps
* - To track which tokens are being swapped the most
*
* ### Who is responsible for this event?
Expand All @@ -271,7 +313,7 @@ export function reportSwapWidgetShown(properties: {

/**
* ### Why do we need to report this event?
* - To track number of failed token swaps from the token page
* - To track number of failed token swaps
* - To track which tokens are being swapped the most
*
* ### Who is responsible for this event?
Expand All @@ -287,7 +329,7 @@ export function reportTokenSwapFailed(

/**
* ### Why do we need to report this event?
* - To track number of cancelled token swaps from the token page
* - To track number of cancelled token swaps
* - To track which tokens are being swapped the most
*
* ### Who is responsible for this event?
Expand All @@ -299,15 +341,15 @@ export function reportTokenSwapCancelled(properties: TokenSwapParams) {

/**
* ### Why do we need to report this event?
* - To track number of failed asset purchases from the token page
* - To track number of failed asset purchases
* - To track the errors that users encounter when trying to purchase an asset
*
* ### Who is responsible for this event?
* @MananTank
*/
export function reportAssetBuyFailed(properties: {
chainId: number;
contractType: AssetContractType;
contractType: AssetContractType | undefined;
assetType: "nft" | "coin";
error: string;
}) {
Expand All @@ -329,7 +371,7 @@ export function reportAssetBuyFailed(properties: {
*/
export function reportAssetBuyCancelled(properties: {
chainId: number;
contractType: AssetContractType;
contractType: AssetContractType | undefined;
assetType: "nft" | "coin";
}) {
posthog.capture("asset buy cancelled", {
Expand Down
64 changes: 58 additions & 6 deletions apps/dashboard/src/@/components/blocks/BuyAndSwapEmbed.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@ import {
reportAssetBuyFailed,
reportAssetBuySuccessful,
reportSwapWidgetShown,
reportTokenBuyCancelled,
reportTokenBuyFailed,
reportTokenBuySuccessful,
reportTokenSwapCancelled,
reportTokenSwapFailed,
reportTokenSwapSuccessful,
Expand Down Expand Up @@ -66,32 +69,81 @@ export function BuyAndSwapEmbed(props: {
connectOptions={{
autoConnect: false,
}}
onError={(e) => {
onError={(e, quote) => {
const errorMessage = parseError(e);

reportTokenBuyFailed({
buyTokenChainId:
quote?.type === "buy"
? quote.intent.destinationChainId
: quote?.type === "onramp"
? quote.intent.chainId
: undefined,
buyTokenAddress:
quote?.type === "buy"
? quote.intent.destinationTokenAddress
: quote?.type === "onramp"
? quote.intent.tokenAddress
: undefined,
pageType: props.pageType,
});

if (props.pageType === "asset") {
reportAssetBuyFailed({
assetType: "coin",
chainId: props.chain.id,
contractType: "DropERC20",
error: errorMessage,
contractType: undefined,
});
}
}}
onCancel={() => {
onCancel={(quote) => {
reportTokenBuyCancelled({
buyTokenChainId:
quote?.type === "buy"
? quote.intent.destinationChainId
: quote?.type === "onramp"
? quote.intent.chainId
: undefined,
buyTokenAddress:
quote?.type === "buy"
? quote.intent.destinationTokenAddress
: quote?.type === "onramp"
? quote.intent.tokenAddress
: undefined,
pageType: props.pageType,
});

if (props.pageType === "asset") {
reportAssetBuyCancelled({
assetType: "coin",
chainId: props.chain.id,
contractType: "DropERC20",
contractType: undefined,
});
}
}}
onSuccess={() => {
onSuccess={(quote) => {
reportTokenBuySuccessful({
buyTokenChainId:
quote.type === "buy"
? quote.intent.destinationChainId
: quote.type === "onramp"
? quote.intent.chainId
: undefined,
buyTokenAddress:
quote.type === "buy"
? quote.intent.destinationTokenAddress
: quote.type === "onramp"
? quote.intent.tokenAddress
: undefined,
pageType: props.pageType,
});

if (props.pageType === "asset") {
reportAssetBuySuccessful({
assetType: "coin",
chainId: props.chain.id,
contractType: "DropERC20",
contractType: undefined,
});
}
}}
Expand Down
73 changes: 42 additions & 31 deletions packages/thirdweb/src/react/web/ui/Bridge/BridgeOrchestrator.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -82,17 +82,17 @@
/**
* Called when the flow is completed successfully
*/
onComplete: () => void;
onComplete: (quote: BridgePrepareResult) => void;

/**
* Called when the flow encounters an error
*/
onError: (error: Error) => void;
onError: (error: Error, quote: BridgePrepareResult | undefined) => void;

/**
* Called when the user cancels the flow
*/
onCancel: () => void;
onCancel: (quote: BridgePrepareResult | undefined) => void;

/**
* Connect options for wallet connection
Expand Down Expand Up @@ -189,19 +189,22 @@
}, [send, uiOptions.mode]);

// Handle post-buy transaction completion
const handlePostBuyTransactionComplete = useCallback(() => {
onComplete?.();
send({ type: "RESET" });
}, [onComplete, send]);
const handlePostBuyTransactionComplete = useCallback(
(quote: BridgePrepareResult) => {
onComplete?.(quote);
send({ type: "RESET" });
},
[onComplete, send],
);

Check warning on line 198 in packages/thirdweb/src/react/web/ui/Bridge/BridgeOrchestrator.tsx

View check run for this annotation

Codecov / codecov/patch

packages/thirdweb/src/react/web/ui/Bridge/BridgeOrchestrator.tsx#L192-L198

Added lines #L192 - L198 were not covered by tests

// Handle errors
const handleError = useCallback(
(error: Error) => {
console.error(error);
onError?.(error);
onError?.(error, state.context.quote);

Check warning on line 204 in packages/thirdweb/src/react/web/ui/Bridge/BridgeOrchestrator.tsx

View check run for this annotation

Codecov / codecov/patch

packages/thirdweb/src/react/web/ui/Bridge/BridgeOrchestrator.tsx#L204

Added line #L204 was not covered by tests
send({ error, type: "ERROR_OCCURRED" });
},
[onError, send],
[onError, send, state.context.quote],

Check warning on line 207 in packages/thirdweb/src/react/web/ui/Bridge/BridgeOrchestrator.tsx

View check run for this annotation

Codecov / codecov/patch

packages/thirdweb/src/react/web/ui/Bridge/BridgeOrchestrator.tsx#L207

Added line #L207 was not covered by tests
);

// Handle payment method selection
Expand All @@ -227,10 +230,13 @@

// Handle execution complete
const handleExecutionComplete = useCallback(
(completedStatuses: CompletedStatusResult[]) => {
(
completedStatuses: CompletedStatusResult[],
quote: BridgePrepareResult,
) => {

Check warning on line 236 in packages/thirdweb/src/react/web/ui/Bridge/BridgeOrchestrator.tsx

View check run for this annotation

Codecov / codecov/patch

packages/thirdweb/src/react/web/ui/Bridge/BridgeOrchestrator.tsx#L233-L236

Added lines #L233 - L236 were not covered by tests
send({ completedStatuses, type: "EXECUTION_COMPLETE" });
if (uiOptions.mode !== "transaction") {
onComplete?.();
onComplete?.(quote);

Check warning on line 239 in packages/thirdweb/src/react/web/ui/Bridge/BridgeOrchestrator.tsx

View check run for this annotation

Codecov / codecov/patch

packages/thirdweb/src/react/web/ui/Bridge/BridgeOrchestrator.tsx#L239

Added line #L239 was not covered by tests
}
},
[send, onComplete, uiOptions.mode],
Expand All @@ -241,6 +247,8 @@
send({ type: "RETRY" });
}, [send]);

const quote = state.context.quote;

Check warning on line 250 in packages/thirdweb/src/react/web/ui/Bridge/BridgeOrchestrator.tsx

View check run for this annotation

Codecov / codecov/patch

packages/thirdweb/src/react/web/ui/Bridge/BridgeOrchestrator.tsx#L250

Added line #L250 was not covered by tests

// Handle requirements resolved from FundWallet and DirectPayment
const handleRequirementsResolved = useCallback(
(amount: string, token: TokenWithPrices, receiverAddress: Address) => {
Expand All @@ -263,7 +271,7 @@
error={state.context.currentError}
onCancel={() => {
send({ type: "RESET" });
onCancel?.();
onCancel?.(quote);

Check warning on line 274 in packages/thirdweb/src/react/web/ui/Bridge/BridgeOrchestrator.tsx

View check run for this annotation

Codecov / codecov/patch

packages/thirdweb/src/react/web/ui/Bridge/BridgeOrchestrator.tsx#L274

Added line #L274 was not covered by tests
}}
onRetry={handleRetry}
/>
Expand Down Expand Up @@ -369,31 +377,33 @@
/>
)}

{state.value === "execute" &&
state.context.quote &&
state.context.request && (
<StepRunner
autoStart={true}
client={client}
onBack={() => {
send({ type: "BACK" });
}}
onCancel={onCancel}
onComplete={handleExecutionComplete}
request={state.context.request}
wallet={state.context.selectedPaymentMethod?.payerWallet}
windowAdapter={webWindowAdapter}
/>
)}
{state.value === "execute" && quote && state.context.request && (
<StepRunner
autoStart={true}
client={client}
onBack={() => {
send({ type: "BACK" });
}}
onCancel={() => {
onCancel(quote);
}}
onComplete={(completedStatuses) => {
handleExecutionComplete(completedStatuses, quote);
}}
request={state.context.request}
wallet={state.context.selectedPaymentMethod?.payerWallet}
windowAdapter={webWindowAdapter}
/>

Check warning on line 396 in packages/thirdweb/src/react/web/ui/Bridge/BridgeOrchestrator.tsx

View check run for this annotation

Codecov / codecov/patch

packages/thirdweb/src/react/web/ui/Bridge/BridgeOrchestrator.tsx#L380-L396

Added lines #L380 - L396 were not covered by tests
)}

{state.value === "success" &&
state.context.quote &&
quote &&

Check warning on line 400 in packages/thirdweb/src/react/web/ui/Bridge/BridgeOrchestrator.tsx

View check run for this annotation

Codecov / codecov/patch

packages/thirdweb/src/react/web/ui/Bridge/BridgeOrchestrator.tsx#L400

Added line #L400 was not covered by tests
state.context.completedStatuses && (
<SuccessScreen
client={client}
completedStatuses={state.context.completedStatuses}
onDone={handleDoneOrContinueClick}
preparedQuote={state.context.quote}
preparedQuote={quote}

Check warning on line 406 in packages/thirdweb/src/react/web/ui/Bridge/BridgeOrchestrator.tsx

View check run for this annotation

Codecov / codecov/patch

packages/thirdweb/src/react/web/ui/Bridge/BridgeOrchestrator.tsx#L406

Added line #L406 was not covered by tests
uiOptions={uiOptions}
windowAdapter={webWindowAdapter}
hasPaymentId={!!paymentLinkId}
Expand All @@ -402,9 +412,10 @@

{state.value === "post-buy-transaction" &&
uiOptions.mode === "transaction" &&
quote &&

Check warning on line 415 in packages/thirdweb/src/react/web/ui/Bridge/BridgeOrchestrator.tsx

View check run for this annotation

Codecov / codecov/patch

packages/thirdweb/src/react/web/ui/Bridge/BridgeOrchestrator.tsx#L415

Added line #L415 was not covered by tests
uiOptions.transaction && (
<ExecutingTxScreen
closeModal={handlePostBuyTransactionComplete}
closeModal={() => handlePostBuyTransactionComplete(quote)}

Check warning on line 418 in packages/thirdweb/src/react/web/ui/Bridge/BridgeOrchestrator.tsx

View check run for this annotation

Codecov / codecov/patch

packages/thirdweb/src/react/web/ui/Bridge/BridgeOrchestrator.tsx#L418

Added line #L418 was not covered by tests
onTxSent={() => {
// Do nothing
}}
Expand Down
Loading
Loading