Skip to content

Conversation

@shrestha-das
Copy link

@shrestha-das shrestha-das commented Nov 29, 2025

This PR updates the TransactionReview component to simplify the transaction workflow. Previously, preparing and sending transactions were handled in separate steps. Now, a single Pay button prepares and sends the transaction in one click, improving user experience and reducing complexity.

Changes Made

  • Removed the separate txData state as transactions are now sent immediately after preparation.
  • Combined "Prepare Transaction" and "Send Transaction" functionality into a single handlePay function.
  • Ensured both native and stablecoin token transfers work with the unified Pay button.

Benefits

  • Simplifies transaction flow for the user.
  • Reduces redundant state management.
  • Provides clear messages during the transaction lifecycle.

Summary by CodeRabbit

  • New Features

    • Streamlined transaction submission with a unified single-step pay flow, replacing the previous multi-step process.
  • Improvements

    • Simplified user interaction during transaction submission with clearer messaging ("Preparing transaction…" followed by "Sending transaction…").
    • Maintained transaction status display and explorer link for consistency.

✏️ Tip: You can customize this high-level summary in your review settings.

@coderabbitai
Copy link

coderabbitai bot commented Nov 29, 2025

Walkthrough

This PR consolidates the TransactionReview component's multi-step transaction flow into a single unified Pay flow, removing intermediate state management (txData, publicClient) and replacing the two-step prepare/send process with a direct handlePay function while maintaining error handling and explorer link functionality.

Changes

Cohort / File(s) Change Summary
Transaction Flow Consolidation
stablepay-sdk/src/widget/TransactionReview.jsx
Removed publicClient and txData state; replaced handleSendTransaction and buy/sell sub-flows with unified handlePay function. Updated UI from two-step (Prepare, Send) to single Pay button. Removed getExplorerUrl conditional logic while preserving transaction hash display with consistent explorer link. Adjusted message sequencing and error handling for simplified flow.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

  • Verify the transition from multi-step to single-step flow maintains all error handling paths
  • Check that message sequencing ("Preparing transaction…" → "Sending transaction…" → success/failure) correctly reflects the new unified flow
  • Confirm wallet connection handling remains intact and functional
  • Review state removal (txData, publicClient) to ensure no orphaned references elsewhere in the component

Possibly related PRs

Suggested reviewers

  • Zahnentferner

Poem

🐰 One button hops where two did dance,
A simpler path, a cleaner chance,
The transaction flows as smooth as clover,
Multi-step confusion, now hopped over! ✨

Pre-merge checks and finishing touches

✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and accurately describes the main change: merging two separate transaction steps (Prepare and Send) into a single Pay step, which is the primary objective of this pull request.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Tip

📝 Customizable high-level summaries are now available in beta!

You can now customize how CodeRabbit generates the high-level summary in your pull requests — including its content, structure, tone, and formatting.

  • Provide your own instructions using the high_level_summary_instructions setting.
  • Format the summary however you like (bullet lists, tables, multi-section layouts, contributor stats, etc.).
  • Use high_level_summary_in_walkthrough to move the summary from the description to the walkthrough section.

Example instruction:

"Divide the high-level summary into five sections:

  1. 📝 Description — Summarize the main change in 50–60 words, explaining what was done.
  2. 📓 References — List relevant issues, discussions, documentation, or related PRs.
  3. 📦 Dependencies & Requirements — Mention any new/updated dependencies, environment variable changes, or configuration updates.
  4. 📊 Contributor Summary — Include a Markdown table showing contributions:
    | Contributor | Lines Added | Lines Removed | Files Changed |
  5. ✔️ Additional Notes — Add any extra reviewer context.
    Keep each section concise (under 200 words) and use bullet or numbered lists for clarity."

Note: This feature is currently in beta for Pro-tier users, and pricing will be announced later.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
stablepay-sdk/src/widget/TransactionReview.jsx (2)

91-99: Guard against missing walletClient and clear stale errors in handlePay

handlePay bails out if account/details/transaction are missing, but not if walletClient is null. In that case walletClient.sendTransaction will throw. Also, error is never cleared on retry, so a previous failure keeps the “Show Details” button visible even after a successful send.

I’d tighten the guard and reset the error before starting a new pay attempt:

-  const handlePay = async () => {
-    if (!account || !contextTransactionDetails || !transaction) {
+  const handlePay = async () => {
+    if (!account || !walletClient || !contextTransactionDetails || !transaction) {
       setMessage("❌ Wallet not connected or transaction details missing");
       return;
     }
 
     try {
+      setError(null);
       setMessage("⏳ Preparing transaction...");
@@
-      setTxHash(txHash);
-      setMessage("✅ Transaction sent!");
+      setTxHash(txHash);
+      setMessage("✅ Transaction sent!");
     } catch (error) {
       setError(error);
       setMessage("❌ Transaction failed.");
     }
   };

Also applies to: 145-156


91-96: Add in-flight state to prevent double-submitting the Pay transaction

handlePay has no in-flight guard, and the Pay button stays enabled. On slow networks or if the user double-clicks, you can easily end up firing multiple non‑idempotent sendTransaction calls for a single “Pay” action.

Given this is a payment flow, it’s safer to introduce an isPaying flag and disable the Pay button (and maybe the Connect button) while a transaction is being prepared/sent:

-  const [message, setMessage] = useState("");
+  const [message, setMessage] = useState("");
+  const [isPaying, setIsPaying] = useState(false);
@@
   const handlePay = async () => {
@@
     try {
+      setIsPaying(true);
       setMessage("⏳ Preparing transaction...");
@@
-      setTxHash(txHash);
-      setMessage("✅ Transaction sent!");
+      setTxHash(txHash);
+      setMessage("✅ Transaction sent!");
     } catch (error) {
       setError(error);
       setMessage("❌ Transaction failed.");
+    } finally {
+      setIsPaying(false);
     }
   };
@@
-      {account && (
-        <button className={styles.walletButton} onClick={handlePay}>
-          Pay
-        </button> 
-      )}
+      {account && (
+        <button
+          className={styles.walletButton}
+          onClick={handlePay}
+          disabled={isPaying}
+        >
+          {isPaying ? "Processing..." : "Pay"}
+        </button> 
+      )}

Also applies to: 181-185

🧹 Nitpick comments (2)
stablepay-sdk/src/widget/TransactionReview.jsx (2)

49-53: Verify tradeDataBuySc shape; avoid passing full object to parseEther/UI

From setTransactionDetails({ tradeAmount: tradeData ? tradeData.amount : null, ... }) it looks like handleTradeDataBuySc returns an object with an amount field. In handlePay and the “You Pay” display you treat tradeDataBuySc as a primitive:

  • Native path: const amountToSend = tradeDataBuySc || "0"; then parseEther(String(amountToSend)).
  • UI: {tradeDataBuySc ? tradeDataBuySc : "Calculating..."}.

If tradeDataBuySc is indeed the whole trade object, this will stringify to "[object Object]" in both the UI and parseEther, which is likely wrong.

Consider storing just the numeric amount in state and using that consistently:

-        let tradeData = null;
-        if (selectedToken.key === "native") {
+        let tradeData = null;
+        if (selectedToken.key === "native") {
           try {
             tradeData = await newTransaction.handleTradeDataBuySc(String(tokenAmount));
-            setTradeDataBuySc(tradeData);
+            setTradeDataBuySc(tradeData.amount);
@@
-        const UI = "0x0232556C83791b8291E9b23BfEa7d67405Bd9839";
-        const amountToSend = tradeDataBuySc || "0";
+        const UI = "0x0232556C83791b8291E9b23BfEa7d67405Bd9839";
+        const amountToSend = tradeDataBuySc ?? "0";
@@
-          {selectedToken.key === "stablecoin"
-            ? `${contextTransactionDetails.amount} ${contextTransactionDetails.tokenSymbol}`
-            : `${tradeDataBuySc ? tradeDataBuySc : "Calculating..."} ${
+          {selectedToken.key === "stablecoin"
+            ? `${contextTransactionDetails.amount} ${contextTransactionDetails.tokenSymbol}`
+            : `${tradeDataBuySc ?? "Calculating..."} ${
                 contextTransactionDetails.tokenSymbol
               }`}

Also consider blocking the Pay action until tradeDataBuySc is resolved to avoid sending a zero amount.

Also applies to: 103-106, 168-173


142-147: Minor: ensure consistent indentation around “Sending transaction…” message

Line 143 (setMessage("⏳ Sending transaction...");) is over-indented relative to surrounding lines, which makes the try block slightly harder to scan. Aligning it with the other statements in the block would improve readability.

This is cosmetic and optional, but easy to tidy up while you’re here.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 8dde4f3 and 3a54e59.

📒 Files selected for processing (1)
  • stablepay-sdk/src/widget/TransactionReview.jsx (4 hunks)
🔇 Additional comments (2)
stablepay-sdk/src/widget/TransactionReview.jsx (2)

114-121: Recommendation to change "0" to 0n is correct for viem v2 consistency

Based on viem v2 documentation, encodeFunctionData requires BigInt values for uint256 parameters. The parseUnits helper returns bigint, so the fallback should also be bigint (0n) instead of string ("0") to maintain type consistency and ensure proper encoding of ERC-20 transfer operations.

The suggested fix is sound:

-        const amountToSend = contextTransactionDetails.amount
-          ? parseUnits(
-              String(contextTransactionDetails.amount),
-              contextTransactionDetails.stableCoinDecimals
-            )
-          : "0";
+        const amountToSend = contextTransactionDetails.amount
+          ? parseUnits(
+              String(contextTransactionDetails.amount),
+              contextTransactionDetails.stableCoinDecimals
+            )
+          : 0n;

208-226: I've exhausted the available verification methods. The repository appears to be private or not publicly accessible, and the specific file cannot be located in public sources. Let me provide the rewritten review comment based on this finding:


Verify network configuration before hard-coding explorer URL

The transaction explorer link is currently hard-coded to ETC Mordor's Blockscout:

<a
  href={`https://blockscout.com/etc/mordor/tx/${txHash}`}
  ...
>
  {txHash.slice(0, 6)}...{txHash.slice(-6)}
</a>

If this widget supports multiple networks (as suggested by selectedNetwork and getBlockchainDetails()), this will direct users to the wrong explorer on non-Mordor chains.

Verify that:

  • getBlockchainDetails() or similar network configuration actually exposes per-network explorer base URLs
  • contextTransactionDetails or another context object is available with explorer configuration
  • Multi-network support is actually intended for this component

If confirmed, derive the explorer URL from network configuration rather than hard-coding it.

@shrestha-das
Copy link
Author

This PR fixes issue #16

connectWallet,
account,
walletClient,
publicClient,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@shrestha-das why is the public client removed here?

Copy link
Author

@shrestha-das shrestha-das Dec 11, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hello @Tanya-ruby, actually the public client is removed because it's not used in this code.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

okay , makes sense since we do not use txdata anywhere.Although I see the explorer links functions with diffferent networks link was removed ,can you add that back ?

we would need to modify in such a way that the link is not just for mordor testnet but also other networks.

-> Another thing which will help is if you can add a screenshot or screenrecording of the changes.

Package the sdk locally and use the merchantdashboard repo and replace the stablepay sdk with the locally packged one and you can test it directly and also sharre the screenshots! @shrestha-das

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Tanya-ruby , Can you please help me to figure out what other tests to do and screenshots to take here?

Github-StablePay-SS1

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

okay , makes sense since we do not use txdata anywhere.Although I see the explorer links functions with diffferent networks link was removed ,can you add that back ?

we would need to modify in such a way that the link is not just for mordor testnet but also other networks.

So I will add these lines again

+   const getExplorerUrl = () => {
+   if (!txHash || !selectedNetwork) return null;
+                                                 
+   const explorerBaseUrls = {
+    "ethereum-classic": "https://etc-mordor.blockscout.com/tx/",
+     "sepolia": "https://sepolia.etherscan.io/tx/",
+     "milkomeda-mainnet": "https://explorer-mainnet-cardano-evm.c1.milkomeda.com/tx/",
+    };
+      
+     return explorerBaseUrls[selectedNetwork]
+     ? `${explorerBaseUrls[selectedNetwork]}${txHash}`
+     : null;
+  };

And modify here -

-  <div className={styles.transactionLink}>
-    ✅ Transaction Hash:{" "}
-     <a
-       href={`https://blockscout.com/etc/mordor/tx/${txHash}`}

to -

+ {getExplorerUrl() && txHash && (
+   <div className={styles.transactionLink}>
+      ✅ Transaction Hash:{" "}
+       <a
+         href={`${getExplorerUrl}${txHash}`}
  • Is this okay?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@shrestha-das that is the merchant dashboard , you can add and test the sdk in the merchant demo website ,that's where you can check the sdk working

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants