From e7949ea14c3e1b783f52cb6feca9f6f982521f81 Mon Sep 17 00:00:00 2001 From: Cursor Agent Date: Fri, 26 Dec 2025 08:03:21 +0000 Subject: [PATCH] feat: Add transaction hashes to checkout widget events Co-authored-by: yashjoisar --- .../checkout-widget-transaction-hash.md | 33 ++++ CHECKOUT_WIDGET_TRANSACTION_HASH_CHANGES.md | 151 +++++++++++++++ .../CheckoutWidgetEmbed.client.tsx | 25 ++- .../TRANSACTION_HASH_EXAMPLE.html | 177 ++++++++++++++++++ .../bridge/checkout-widget/iframe/page.mdx | 5 + 5 files changed, 389 insertions(+), 2 deletions(-) create mode 100644 .changeset/checkout-widget-transaction-hash.md create mode 100644 CHECKOUT_WIDGET_TRANSACTION_HASH_CHANGES.md create mode 100644 apps/dashboard/src/app/bridge/checkout-widget/TRANSACTION_HASH_EXAMPLE.html diff --git a/.changeset/checkout-widget-transaction-hash.md b/.changeset/checkout-widget-transaction-hash.md new file mode 100644 index 00000000000..a59a2534a0c --- /dev/null +++ b/.changeset/checkout-widget-transaction-hash.md @@ -0,0 +1,33 @@ +--- +"@workspace/dashboard": patch +"@workspace/portal": patch +--- + +[Dashboard] Add transaction hash to checkout widget iframe success/failed events + +The checkout widget iframe now returns transaction hashes in both success and error events via postMessage. This allows developers to track on-chain transactions associated with payments made through the widget. + +**Success Event:** +```js +{ + source: "checkout-widget", + type: "success", + transactions: [ + { chainId: 8453, transactionHash: "0x..." } + ] +} +``` + +**Error Event:** +```js +{ + source: "checkout-widget", + type: "error", + message: "Error message", + transactions: [ + { chainId: 8453, transactionHash: "0x..." } + ] +} +``` + +The transactions array contains all on-chain transactions that were executed as part of the payment flow, including any cross-chain swaps or transfers. diff --git a/CHECKOUT_WIDGET_TRANSACTION_HASH_CHANGES.md b/CHECKOUT_WIDGET_TRANSACTION_HASH_CHANGES.md new file mode 100644 index 00000000000..13e0eee352a --- /dev/null +++ b/CHECKOUT_WIDGET_TRANSACTION_HASH_CHANGES.md @@ -0,0 +1,151 @@ +# Checkout Widget iframe - Transaction Hash Feature + +## Summary +Added transaction hash information to the checkout widget iframe's success and error events. This allows developers to track on-chain transactions associated with payments made through the widget. + +## Changes Made + +### 1. Updated CheckoutWidgetEmbed Component +**File:** `apps/dashboard/src/app/bridge/checkout-widget/CheckoutWidgetEmbed.client.tsx` + +#### Success Event Handler +- Extracts transaction hashes from the `data.statuses` array returned by the `CheckoutWidget` component +- Each status contains a `transactions` array with `chainId` and `transactionHash` fields +- Sends the transaction data to the parent window via `postMessage` + +```typescript +onSuccess={(data) => { + const transactionHashes = data.statuses.flatMap((status) => { + return status.transactions.map((tx) => ({ + chainId: tx.chainId, + transactionHash: tx.transactionHash, + })); + }); + + sendMessageToParent({ + source: "checkout-widget", + type: "success", + transactions: transactionHashes, + }); +}} +``` + +#### Error Event Handler +- Extracts transaction hashes from the `quote.steps` if available +- This captures any partial transactions that may have occurred before the error +- Useful for debugging and tracking failed payment attempts + +```typescript +onError={(error, quote) => { + const transactionHashes = + quote?.steps?.flatMap((step) => { + return ( + step.transactions?.map((tx) => ({ + chainId: tx.chainId, + transactionHash: tx.transactionHash, + })) || [] + ); + }) || []; + + sendMessageToParent({ + source: "checkout-widget", + type: "error", + message: error.message, + transactions: transactionHashes, + }); +}} +``` + +### 2. Updated Documentation +**File:** `apps/portal/src/app/bridge/checkout-widget/iframe/page.mdx` + +- Added examples showing how to access transaction hashes from both success and error events +- Included comments explaining the structure of the transactions array +- Noted that error events may contain partial transaction data + +### 3. Created Example HTML File +**File:** `apps/dashboard/src/app/bridge/checkout-widget/TRANSACTION_HASH_EXAMPLE.html` + +- Demonstrates a complete working example of the iframe integration +- Shows real-time event logging with transaction hash display +- Includes example code for sending transaction data to a backend API + +### 4. Added Changeset +**File:** `.changeset/checkout-widget-transaction-hash.md` + +- Documents the change for the release notes +- Includes example event structures for both success and error cases + +## Event Structure + +### Success Event +```javascript +{ + source: "checkout-widget", + type: "success", + transactions: [ + { + chainId: 8453, + transactionHash: "0x1234567890abcdef..." + }, + // ... more transactions if cross-chain + ] +} +``` + +### Error Event +```javascript +{ + source: "checkout-widget", + type: "error", + message: "Payment failed", + transactions: [ + { + chainId: 8453, + transactionHash: "0x1234567890abcdef..." + }, + // ... partial transactions if any + ] +} +``` + +## Use Cases + +1. **Transaction Tracking**: Store transaction hashes in your database for order fulfillment and customer support +2. **Analytics**: Track payment success rates and analyze failed transactions +3. **Webhooks**: Send transaction data to third-party services for order processing +4. **Customer Notifications**: Include transaction links in confirmation emails +5. **Debugging**: Investigate failed payments by examining partial transaction data + +## Technical Details + +### Data Source +The transaction hashes come from two sources: + +1. **Success Events**: From `CompletedStatusResult[]` which includes: + - `Status` type (for buy/sell/transfer operations) + - `OnrampStatus.Result` type (for fiat onramp operations) + +2. **Error Events**: From `BridgePrepareResult.steps[].transactions[]` which contains: + - Prepared transaction data from the quote + - May include transactions that were executed before the error occurred + +### Type Safety +The implementation uses TypeScript types from the thirdweb SDK: +- `CompletedStatusResult` - Union type for completed statuses +- `Status` - Bridge status with transaction details +- `OnrampStatus.Result` - Onramp status with transaction details +- `BridgePrepareResult` - Quote preparation result with steps + +## Testing +To test the changes: + +1. Open `TRANSACTION_HASH_EXAMPLE.html` in a browser +2. Complete a payment through the widget +3. Observe the transaction hashes in the events log +4. Test error scenarios by using invalid payment methods or insufficient funds + +## Related Issues +- Addresses request from Slack thread in #engineering channel +- Requested by Yash Joisar on 12/22/2025 +- Follows the pattern established by the bridge widget iframe diff --git a/apps/dashboard/src/app/bridge/checkout-widget/CheckoutWidgetEmbed.client.tsx b/apps/dashboard/src/app/bridge/checkout-widget/CheckoutWidgetEmbed.client.tsx index 57bc6194fab..c58b5ef9a02 100644 --- a/apps/dashboard/src/app/bridge/checkout-widget/CheckoutWidgetEmbed.client.tsx +++ b/apps/dashboard/src/app/bridge/checkout-widget/CheckoutWidgetEmbed.client.tsx @@ -83,17 +83,38 @@ export function CheckoutWidgetEmbed({ wallets: bridgeWallets, appMetadata, }} - onSuccess={() => { + onSuccess={(data) => { + // Extract transaction hashes from completed statuses + const transactionHashes = data.statuses.flatMap((status) => { + return status.transactions.map((tx) => ({ + chainId: tx.chainId, + transactionHash: tx.transactionHash, + })); + }); + sendMessageToParent({ source: "checkout-widget", type: "success", + transactions: transactionHashes, }); }} - onError={(error) => { + onError={(error, quote) => { + // Extract transaction hashes from the quote if available + const transactionHashes = + quote?.steps?.flatMap((step) => { + return ( + step.transactions?.map((tx) => ({ + chainId: tx.chainId, + transactionHash: tx.transactionHash, + })) || [] + ); + }) || []; + sendMessageToParent({ source: "checkout-widget", type: "error", message: error.message, + transactions: transactionHashes, }); }} /> diff --git a/apps/dashboard/src/app/bridge/checkout-widget/TRANSACTION_HASH_EXAMPLE.html b/apps/dashboard/src/app/bridge/checkout-widget/TRANSACTION_HASH_EXAMPLE.html new file mode 100644 index 00000000000..0af0974cd4a --- /dev/null +++ b/apps/dashboard/src/app/bridge/checkout-widget/TRANSACTION_HASH_EXAMPLE.html @@ -0,0 +1,177 @@ + + + + + + Checkout Widget iframe - Transaction Hash Example + + + +

Checkout Widget iframe - Transaction Hash Example

+

This example demonstrates how to listen for transaction hashes from the checkout widget iframe.

+ +
+
+

Widget

+ +
+ +
+

Events Log

+
+

Waiting for events...

+
+
+
+ + + + diff --git a/apps/portal/src/app/bridge/checkout-widget/iframe/page.mdx b/apps/portal/src/app/bridge/checkout-widget/iframe/page.mdx index 2170305f675..ace8e954d9b 100644 --- a/apps/portal/src/app/bridge/checkout-widget/iframe/page.mdx +++ b/apps/portal/src/app/bridge/checkout-widget/iframe/page.mdx @@ -151,10 +151,15 @@ window.addEventListener("message", (event) => { if (event.data.type === "success") { console.log("Purchase successful!"); + console.log("Transaction hashes:", event.data.transactions); + // event.data.transactions is an array of objects with chainId and transactionHash + // Example: [{ chainId: 8453, transactionHash: "0x..." }] } if (event.data.type === "error") { console.error("Purchase failed with error:", event.data.message); + console.log("Transaction hashes (if any):", event.data.transactions); + // event.data.transactions may contain partial transaction data if the error occurred mid-flow } }