Skip to content

feat: add example website and improve SDK widget UI/UX & validation flow#105

Open
DeveloperAmrit wants to merge 6 commits into
DjedAlliance:mainfrom
DeveloperAmrit:fix-ui-ux
Open

feat: add example website and improve SDK widget UI/UX & validation flow#105
DeveloperAmrit wants to merge 6 commits into
DjedAlliance:mainfrom
DeveloperAmrit:fix-ui-ux

Conversation

@DeveloperAmrit

@DeveloperAmrit DeveloperAmrit commented Jun 8, 2026

Copy link
Copy Markdown
Member

Addressed Issues:

Fixes #60 and #62

Screenshots/Recordings:

Case 1: User has a wallet

has_wallet.mp4

Case 2: User has no wallet

no_wallet.mp4

Additional Notes:

Description
This Pull Request introduces a comprehensive example application to demonstrate SDK integration and significantly improves the UI/UX and validation flow of the StablePay SDK widgets.

Why a new example website?
A fully fledged example website repo exists (https://github.com/DjedAlliance/StablePay-MerchantWebsiteDemo), but it does not update stable-sdk in real time. We need to update stablepay-sdk on npm to get the latest build in that example website. I have made this example website within the SDK to show widgets and a user flow that updates automatically with every local SDK build.

Changes made:

  1. Example Website Addition
    • Added a new React + Vite example application under stablepay-sdk/example/.
    • Demonstrates real-world integration of the stablepay-sdk, providing a clear reference for developers.
    • Includes its own Vite configuration, CSS, and basic project structure.
  2. UI/UX Enhancements for SDK Widgets
    • Improved the visual design and responsiveness of the payment widgets.
    • Updated styles in PricingCard.css to offer a more polished look.
    • Refactored Dialog.jsx and TransactionReview.jsx components for a smoother user experience.
  3. User Validation & Transaction Flow Improvements
    • Enhanced validation logic in Transaction.js and TransactionReview.jsx.
    • Improved the overall payment flow, making error handling and user feedback more robust during transactions.
    • Re-built and updated the distribution files (dist/esm and dist/umd) to reflect the latest widget changes.

Checklist

  • My PR addresses a single issue, fixes a single bug or makes a single improvement.
  • My code follows the project's code style and conventions
  • If applicable, I have made corresponding changes or additions to the documentation
  • If applicable, I have made corresponding changes or additions to tests
  • My changes generate no new warnings or errors
  • I have joined the Discord server and I will share a link to this PR with the project maintainers there
  • I have read the Contribution Guidelines
  • Once I submit my PR, CodeRabbit AI will automatically review it and I will address CodeRabbit's comments.

AI Usage Disclosure

Check one of the checkboxes below:

  • This PR does not contain AI-generated code at all.

Summary by CodeRabbit

  • New Features

    • Added a complete example application demonstrating wallet connection and payment processing with the StablePay widget.
  • Bug Fixes

    • Improved error detection and messaging for transaction failures and missing wallet scenarios.
    • Enhanced network validation before payment execution.
  • UI/Style

    • Redesigned payment card with fade-in animations and improved visual hierarchy.
    • Updated button styles, form controls, and error/messaging displays.
    • Added responsive mobile design improvements.
  • Refactor

    • Streamlined transaction handling with clearer state management and error flows.

@coderabbitai

coderabbitai Bot commented Jun 8, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@DeveloperAmrit, we couldn't start this review because you've reached your PR review rate limit.

More reviews will be available in 38 minutes and 52 seconds. Learn how PR review limits work.

Your organization has run out of usage credits. Purchase more in the billing tab.

⌛ How to resolve this issue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans include higher PR review limits than trial, open-source, and free plans. In all cases, reviews become available again over time. During sustained high-volume PR review activity, CodeRabbit may temporarily slow when the next review becomes available.

Please see our Fair Usage Limits Policy for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 5f9394ad-0762-4883-b35e-b41e50ebc7bf

📥 Commits

Reviewing files that changed from the base of the PR and between 4a3df35 and 7d3b24e.

⛔ Files ignored due to path filters (3)
  • stablepay-sdk/dist/esm/index.js is excluded by !**/dist/**
  • stablepay-sdk/dist/umd/index.js is excluded by !**/dist/**
  • stablepay-sdk/dist/umd/index.js.map is excluded by !**/dist/**, !**/*.map
📒 Files selected for processing (3)
  • stablepay-sdk/example/eslint.config.js
  • stablepay-sdk/example/src/App.jsx
  • stablepay-sdk/src/core/Transaction.js
📝 Walkthrough

Walkthrough

This PR implements a unified payment flow and robust error handling for the StablePay widget, addressing friction in the two-step Prepare/Send transaction process. It adds a complete example application demonstrating SDK integration, improves transaction error classification using JSON-RPC codes, refactors the payment state machine into a single Pay action, and redesigns the payment dialog styling.

Changes

StablePay Payment UX and Example Application

Layer / File(s) Summary
Example React+Vite Application Setup
stablepay-sdk/example/{.gitignore,README.md,eslint.config.js,index.html,package.json,vite.config.js}, stablepay-sdk/example/src/{App.jsx,App.css,main.jsx,index.css}
Complete example workspace with boilerplate configuration, ESLint setup, and a demo React app that connects a wallet, configures StablePay with fixed receiving address and per-network amounts, and displays the payment widget with transaction completion handling.
Error Classification via JSON-RPC Codes
stablepay-sdk/src/core/Transaction.js
Refactored error detection to use JSON-RPC error codes (-32000, 3, -32603, 4001, -32005) and structured error data instead of message string matching, enabling more reliable contract revert and connection/DNS error identification.
Unified Payment Flow and State Machine
stablepay-sdk/src/widget/TransactionReview.jsx, stablepay-sdk/src/widget/Dialog.jsx, stablepay-sdk/src/widget/TokenDropdown.jsx
Replaced the two-step Prepare/Send buttons with a single executePayment flow driven by interactionState, adding network validation via ensureCorrectNetwork, wallet presence checks, clearer error-to-reason mapping (user rejection vs contract revert vs other), and improved UI state transitions; Dialog title changed from h2 to div; TokenDropdown error messaging now differentiates between missing wallet and transaction failures.
Payment Dialog Styling and Visual States
stablepay-sdk/src/styles/PricingCard.css
Redesigned pricing card with fadeInScale animation overlay, updated form/select field styling with chevron icons and explicit focus states, reworked transaction review as bordered info pills, gradient button system with hover/active effects, fadeIn message box animation, scrollable error details panel (monospace, max-height, word-break), responsive mobile adjustments (full-width, edge padding, border removal), and updated action area layout for confirmation/processing/success states.

Sequence Diagram(s)

sequenceDiagram
  participant User
  participant UI as TransactionReview
  participant WalletClient
  participant RPC as Network/RPC
  
  User->>UI: Click Pay
  UI->>UI: interactionState = CONFIRMING
  User->>UI: Confirm
  UI->>UI: interactionState = PENDING
  UI->>UI: ensureCorrectNetwork()
  UI->>WalletClient: sendTransaction()
  WalletClient->>RPC: eth_sendTransaction
  RPC-->>WalletClient: txHash
  WalletClient-->>UI: txHash
  UI->>UI: Set txHash, interactionState = IDLE
  UI->>User: Show transaction link + success
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

  • DjedAlliance/StablePay#14: Both PRs modify TransactionReview.jsx wallet/transaction error handling and update PricingCard.css for error-details display styling.
  • DjedAlliance/StablePay#22: Overlaps in transaction execution/success handling flow and onTransactionComplete callback threading through Widget and TransactionReview.
  • DjedAlliance/StablePay#38: Connects the TransactionReview refactor that uses ensureCorrectNetwork with the WalletContext introduction of that utility and chain alignment state.

Suggested reviewers

  • Zahnentferner

Poem

🐰 A unified flow hops into view,
No more Prepare—just Pay will do!
With error codes and states so clear,
The transaction path is crystal here.
Example app shows the way,
StablePay shines brighter today! ✨

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the main changes: adding an example website and improving SDK widget UI/UX and validation flow, matching the core PR content.
Linked Issues check ✅ Passed The PR successfully addresses issue #60 objectives: implements unified payment action, enhanced error handling with error codes, improved UX flow with state management, and robust validation.
Out of Scope Changes check ✅ Passed All changes are scoped to the linked issue objectives: example app implementation, UI/UX refinements, transaction flow improvements, and validation enhancements are all within scope.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 7

🧹 Nitpick comments (3)
stablepay-sdk/src/widget/Dialog.jsx (1)

13-13: ⚡ Quick win

Keep semantic heading for dialog title.

Line 13 swaps <h2> to <div>, which drops document/assistive heading semantics. Prefer keeping a heading tag here.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@stablepay-sdk/src/widget/Dialog.jsx` at line 13, In the Dialog component
replace the non-semantic <div className={styles.stablepayTitle}>StablePay</div>
with a proper heading element (e.g. <h2
className={styles.stablepayTitle}>StablePay</h2>) so the title retains
document/assistive heading semantics; keep the same className
(styles.stablepayTitle) and styling, and ensure the Dialog component still meets
any aria-labelledby usage if present.
stablepay-sdk/example/index.html (1)

7-7: 💤 Low value

Update page title to be more descriptive.

The generic title "example" should be updated to reflect the purpose of this demonstration application.

💡 Suggested improvement
-    <title>example</title>
+    <title>StablePay SDK Example</title>
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@stablepay-sdk/example/index.html` at line 7, Replace the generic HTML title
tag content (<title>example</title>) with a more descriptive string that
reflects the page purpose (e.g., "StablePay SDK Demo" or "StablePay SDK Example
- Payment Integration Demo"); update the <title> element in the document head so
it clearly identifies this demonstration app for users and search engines.
stablepay-sdk/example/README.md (1)

1-17: ⚡ Quick win

Enhance README with example-specific documentation.

This README contains only generic Vite+React template boilerplate and doesn't explain:

  • The purpose of this example (demonstrating StablePay SDK integration)
  • How to install dependencies and run the example (npm install, npm run dev)
  • What the example demonstrates (wallet connection, network/token selection, transaction flow)
  • How to use the SDK in your own project
📝 Suggested documentation structure
# StablePay SDK Example

This example demonstrates how to integrate the StablePay SDK into a React application using Vite.

## Features Demonstrated

- Wallet connection and management
- Network and token selection
- Transaction preparation and execution
- Success/error handling

## Getting Started

```bash
# Install dependencies
npm install

# Run development server
npm run dev

Usage

The example shows how to:

  1. Import and configure the StablePay widget
  2. Handle transaction completion callbacks
  3. Manage wallet states

See src/App.jsx for the integration code.

Additional Notes

This template uses @vitejs/plugin-react with HMR and ESLint rules.

</details>

<details>
<summary>🤖 Prompt for AI Agents</summary>

Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @stablepay-sdk/example/README.md around lines 1 - 17, The README currently
contains only generic Vite+React boilerplate; update it to describe this example
as the "StablePay SDK Example", briefly state its purpose (demonstrating
StablePay SDK integration), list features demonstrated (wallet
connection/management, network & token selection, transaction
preparation/execution, success/error handling), add Getting Started steps (npm
install, npm run dev) and Usage notes that point to the integration code in
src/App.jsx (importing/configuring the StablePay widget, handling transaction
callbacks, managing wallet state); keep the existing note about the React
compiler and plugin links but replace template-specific text with these
example-specific instructions and a short Features/Usage section.


</details>

<!-- cr-comment:v1:bd7ab29875e4640f237f5211 -->

</blockquote></details>

</blockquote></details>

<details>
<summary>🤖 Prompt for all review comments with AI agents</summary>

Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In @stablepay-sdk/example/eslint.config.js:

  • Around line 11-15: The ESLint flat config currently uses an unsupported
    "extends" array; replace that usage by directly spreading the config objects
    into the exported array — locate the extends block referencing
    js.configs.recommended, reactHooks.configs.flat.recommended, and
    reactRefresh.configs.vite and change it to spread those config objects at the
    top level of the flat config export so the configs are merged correctly.

In @stablepay-sdk/example/package.json:

  • Around line 12-18: Remove the unused ethers dependency from the example app by
    deleting the "ethers" entry in stablepay-sdk/example/package.json and then
    regenerate the lockfile (package-lock.json) by running the package manager
    (e.g., npm install) inside stablepay-sdk/example; ensure no code in
    stablepay-sdk/example/src imports "ethers" (the widget uses viem, see
    stablepay-sdk/src/widget/TransactionReview.jsx) before committing the updated
    package.json and package-lock.json.

In @stablepay-sdk/example/src/App.jsx:

  • Around line 8-19: The header's local wallet flow is uncoordinated with the SDK
    widget: remove the header "Connect Wallet" button and the related local state
    and function (remove the header button JSX, the account state variable and the
    connectWallet function) so the app relies solely on
    StablePay.Widget/WalletProvider for wallet connections; ensure any imports or
    variables only used by connectWallet are also cleaned up and add a short comment
    near StablePay.Widget/WalletProvider noting it now owns wallet handling.
  • Around line 33-35: The alert callback handleTransactionComplete currently
    takes a string hash but TransactionReview calls onTransactionComplete with an
    object payload; change handleTransactionComplete to accept and destructure the
    payload (e.g., ({ txHash, network, token }) or payload) and use txHash in the
    alert (with a fallback if missing) so the actual transaction hash is shown;
    update any references to handleTransactionComplete to match the new signature
    and keep onTransactionComplete usage in TransactionReview unchanged.

In @stablepay-sdk/src/core/Transaction.js:

  • Around line 56-57: The isConnectionError check in Transaction.js incorrectly
    treats error.code === 4001 as an RPC connection failure; remove 4001 from the
    isConnectionError condition in the isConnectionError declaration inside the
    Transaction handling logic and instead handle error.code === 4001 as a
    user-rejection case (consistent with WalletContext.jsx and
    TransactionReview.jsx), e.g., branch separately to return/throw a user-rejection
    error or status so 4001 is no longer classified as a connection error.
  • Around line 33-34: The revert detection in Transaction.init is too loose:
    replace the current check that treats any truthy contractError.data as a revert
    by narrowing to explicit revert signatures or types (e.g., check if
    contractError is an instance of ContractFunctionRevertedError or if
    contractError.data exists and contractError.data.message (or contractError.data
    && contractError.data.message) contains a revert indicator like "execution
    reverted" or other contract revert text); update the isReverted computation in
    Transaction.init to use these stricter conditions (reference the contractError
    variable and Transaction.init function) so provider/RPC errors with generic data
    are not misclassified as contract reverts.

In @stablepay-sdk/src/widget/TransactionReview.jsx:

  • Around line 101-104: The button's onClick uses window.open(url, '_blank')
    which is vulnerable to tabnabbing; update the click handler in
    TransactionReview.jsx to call window.open('https://metamask.io/download/',
    '_blank', 'noopener,noreferrer') (or alternatively set the returned window's
    opener to null) so the opened page cannot access window.opener.

Nitpick comments:
In @stablepay-sdk/example/index.html:

  • Line 7: Replace the generic HTML title tag content (<title>example</title>)
    with a more descriptive string that reflects the page purpose (e.g., "StablePay
    SDK Demo" or "StablePay SDK Example - Payment Integration Demo"); update the
<title> element in the document head so it clearly identifies this demonstration app for users and search engines.

In @stablepay-sdk/example/README.md:

  • Around line 1-17: The README currently contains only generic Vite+React
    boilerplate; update it to describe this example as the "StablePay SDK Example",
    briefly state its purpose (demonstrating StablePay SDK integration), list
    features demonstrated (wallet connection/management, network & token selection,
    transaction preparation/execution, success/error handling), add Getting Started
    steps (npm install, npm run dev) and Usage notes that point to the integration
    code in src/App.jsx (importing/configuring the StablePay widget, handling
    transaction callbacks, managing wallet state); keep the existing note about the
    React compiler and plugin links but replace template-specific text with these
    example-specific instructions and a short Features/Usage section.

In @stablepay-sdk/src/widget/Dialog.jsx:

  • Line 13: In the Dialog component replace the non-semantic
    StablePay
    with a proper heading element
    (e.g.

    StablePay

    ) so the title retains
    document/assistive heading semantics; keep the same className
    (styles.stablepayTitle) and styling, and ensure the Dialog component still meets
    any aria-labelledby usage if present.

</details>

<details>
<summary>🪄 Autofix (Beta)</summary>

Fix all unresolved CodeRabbit comments on this PR:

- [ ] <!-- {"checkboxId": "4b0d0e0a-96d7-4f10-b296-3a18ea78f0b9"} --> Push a commit to this branch (recommended)
- [ ] <!-- {"checkboxId": "ff5b1114-7d8c-49e6-8ac1-43f82af23a33"} --> Create a new PR with the fixes

</details>

---

<details>
<summary>ℹ️ Review info</summary>

<details>
<summary>⚙️ Run configuration</summary>

**Configuration used**: defaults

**Review profile**: CHILL

**Plan**: Pro

**Run ID**: `67180db3-9253-4741-bfa4-8fc1e58945d4`

</details>

<details>
<summary>📥 Commits</summary>

Reviewing files that changed from the base of the PR and between a254fa62d912f352b543ba2811a03f3fdf213b1a and 4a3df35a6d15313a8009d388a64ac228322c1ff0.

</details>

<details>
<summary>⛔ Files ignored due to path filters (12)</summary>

* `stablepay-sdk/dist/esm/index.js` is excluded by `!**/dist/**`
* `stablepay-sdk/dist/esm/styles.css` is excluded by `!**/dist/**`
* `stablepay-sdk/dist/umd/index.js` is excluded by `!**/dist/**`
* `stablepay-sdk/dist/umd/index.js.map` is excluded by `!**/dist/**`, `!**/*.map`
* `stablepay-sdk/dist/umd/styles.css` is excluded by `!**/dist/**`
* `stablepay-sdk/example/package-lock.json` is excluded by `!**/package-lock.json`
* `stablepay-sdk/example/public/favicon.svg` is excluded by `!**/*.svg`
* `stablepay-sdk/example/public/icons.svg` is excluded by `!**/*.svg`
* `stablepay-sdk/example/src/assets/hero.png` is excluded by `!**/*.png`
* `stablepay-sdk/example/src/assets/react.svg` is excluded by `!**/*.svg`
* `stablepay-sdk/example/src/assets/vite.svg` is excluded by `!**/*.svg`
* `stablepay-sdk/package-lock.json` is excluded by `!**/package-lock.json`

</details>

<details>
<summary>📒 Files selected for processing (16)</summary>

* `stablepay-sdk/example/.gitignore`
* `stablepay-sdk/example/README.md`
* `stablepay-sdk/example/eslint.config.js`
* `stablepay-sdk/example/index.html`
* `stablepay-sdk/example/package.json`
* `stablepay-sdk/example/src/App.css`
* `stablepay-sdk/example/src/App.jsx`
* `stablepay-sdk/example/src/index.css`
* `stablepay-sdk/example/src/main.jsx`
* `stablepay-sdk/example/vite.config.js`
* `stablepay-sdk/examples/index.txt`
* `stablepay-sdk/src/core/Transaction.js`
* `stablepay-sdk/src/styles/PricingCard.css`
* `stablepay-sdk/src/widget/Dialog.jsx`
* `stablepay-sdk/src/widget/TokenDropdown.jsx`
* `stablepay-sdk/src/widget/TransactionReview.jsx`

</details>

<details>
<summary>💤 Files with no reviewable changes (1)</summary>

* stablepay-sdk/examples/index.txt

</details>

</details>

<!-- This is an auto-generated comment by CodeRabbit for review status -->

Comment thread stablepay-sdk/example/eslint.config.js Outdated
Comment on lines +12 to +18
"dependencies": {
"ethers": "^6.16.0",
"react": "^19.2.6",
"react-dom": "^19.2.6",
"stablepay-sdk": "file:..",
"viem": "^2.52.2"
},

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Check if ethers is actually imported/used in the example app source
rg -n --type=js --type=jsx -g 'stablepay-sdk/example/src/**' "from ['\"]ethers['\"]|require\(['\"]ethers['\"]"

Repository: DjedAlliance/StablePay

Length of output: 94


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Locate example source (and fall back safely if path differs)
if [ -d "stablepay-sdk/example/src" ]; then
  SRC_DIR="stablepay-sdk/example/src"
else
  echo "ERROR: stablepay-sdk/example/src not found" >&2
  exit 1
fi

# Search for any direct import/require usage of ethers in the example source
rg -n --hidden --no-ignore -S \
  --glob '*.js' --glob '*.jsx' --glob '*.ts' --glob '*.tsx' \
  "from ['\"]ethers['\"]|require\(\s*['\"]ethers['\"]\s*\)|\bethers\b" \
  "$SRC_DIR" || true

Repository: DjedAlliance/StablePay

Length of output: 48


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Inspect whether stablepay-sdk declares ethers as a (peer) dependency that the example should provide
if [ -f "stablepay-sdk/package.json" ]; then
  echo "=== stablepay-sdk/package.json (relevant fields) ==="
  node -e "
  const fs=require('fs');
  const p=JSON.parse(fs.readFileSync('stablepay-sdk/package.json','utf8'));
  const pick=(obj)=>obj&&obj.ethers?{ethers:obj.ethers}:undefined;
  console.log('dependencies:', pick(p.dependencies));
  console.log('peerDependencies:', pick(p.peerDependencies));
  console.log('devDependencies:', pick(p.devDependencies));
  "
else
  echo "stablepay-sdk/package.json not found" >&2
fi

echo "=== stablepay-sdk/example/package.json (dependencies) ==="
node -e "
const fs=require('fs');
const p=JSON.parse(fs.readFileSync('stablepay-sdk/example/package.json','utf8'));
console.log(p.dependencies||{});
"

Repository: DjedAlliance/StablePay

Length of output: 375


🏁 Script executed:

#!/bin/bash
set -euo pipefail

SRC_DIR="stablepay-sdk/example/src"
if [ ! -d "$SRC_DIR" ]; then
  echo "ERROR: $SRC_DIR not found" >&2
  exit 1
fi

echo "=== ethers usage in example/src ==="
MATCHES="$(rg -n --hidden --no-ignore -S \
  --glob '*.js' --glob '*.jsx' --glob '*.ts' --glob '*.tsx' \
  "from ['\"]ethers['\"]|require\(\s*['\"]ethers['\"]\s*\)|\bethers\b" \
  "$SRC_DIR" || true)"

if [ -z "$MATCHES" ]; then
  echo "(no direct ethers imports/requires/usages found)"
else
  echo "$MATCHES"
fi

echo
echo "=== ethers usage in stablepay-sdk library (best-effort) ==="
# Find likely source roots for the SDK within stablepay-sdk
# - prefer 'src' if exists; otherwise search JS/TS files under stablepay-sdk excluding example/
if [ -d "stablepay-sdk/src" ]; then
  LIB_DIR="stablepay-sdk/src"
else
  LIB_DIR="stablepay-sdk"
fi

MATCHES2="$(rg -n --hidden --no-ignore -S \
  --glob '*.js' --glob '*.jsx' --glob '*.ts' --glob '*.tsx' \
  "\bethers\b" \
  --glob '!stablepay-sdk/example/**' \
  "$LIB_DIR"  || true)"

if [ -z "$MATCHES2" ]; then
  echo "(no ethers word found in stablepay-sdk library sources scanned)"
else
  echo "$MATCHES2" | head -n 80
  echo "… (truncated)"
fi

Repository: DjedAlliance/StablePay

Length of output: 276


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "=== All occurrences of word 'ethers' under stablepay-sdk (excluding node_modules), first 80 lines ==="
rg -n --hidden --no-ignore -S "\bethers\b" stablepay-sdk \
  --glob '!**/node_modules/**' \
  --glob '!**/dist/**' \
  --glob '!**/build/**' \
  --glob '!**/.next/**' \
  | head -n 80 || true

echo
echo "=== package.json files under stablepay-sdk that mention ethers (showing full matching lines) ==="
rg -n --hidden --no-ignore -S "ethers" stablepay-sdk \
  --glob '**/package.json' \
  --glob '!**/node_modules/**' \
  --glob '!**/dist/**' \
  --glob '!**/build/**' \
  || true

Repository: DjedAlliance/StablePay

Length of output: 1053


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "=== All occurrences of word 'ethers' under stablepay-sdk (including dist/build if present), excluding node_modules, first 80 lines ==="
rg -n --hidden --no-ignore -S "\bethers\b" stablepay-sdk \
  --glob '!**/node_modules/**' \
  | head -n 80 || true

Repository: DjedAlliance/StablePay

Length of output: 925


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "=== Search for `@ethersproject` usage under stablepay-sdk (excluding node_modules) ==="
rg -n --hidden --no-ignore -S "`@ethersproject`" stablepay-sdk \
  --glob '!**/node_modules/**' \
  || true

echo
echo "=== Search for common ethers-style symbols under stablepay-sdk (excluding node_modules) ==="
rg -n --hidden --no-ignore -S "\bJsonRpcProvider\b|\bWeb3Provider\b|\bBrowserProvider\b|\bContract\b" stablepay-sdk \
  --glob '!**/node_modules/**' \
  || true

Repository: DjedAlliance/StablePay

Length of output: 9850


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "=== viem usage in example/src (imports/usages) ==="
rg -n --hidden --no-ignore -S \
  --glob '*.js' --glob '*.jsx' --glob '*.ts' --glob '*.tsx' \
  "\bviem\b|from ['\"]viem['\"]|require\(\s*['\"]viem['\"]\s*\)" \
  stablepay-sdk/example/src || true

echo
echo "=== Non-example package.json files under stablepay-sdk (look for ethers/peerDeps) ==="
# List package.json (excluding example)
find stablepay-sdk -name package.json -not -path "*/example/*" | sort > /tmp/pkgjsons.txt
cat /tmp/pkgjsons.txt | sed -n '1,50p'

echo
echo "=== package.json lines containing ethers/peerDependencies for non-example packages ==="
# Search for ethers/peerDependencies only in those package.json files
if [ -s /tmp/pkgjsons.txt ]; then
  rg -n --hidden --no-ignore -S "ethers|peerDependencies" -f /tmp/pkgjsons.txt --no-mmap || true
fi

Repository: DjedAlliance/StablePay

Length of output: 401


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "=== stablepay-sdk/package.json (full) ==="
cat stablepay-sdk/package.json

echo
echo "=== viem usage in stablepay-sdk (excluding example/, node_modules), first 80 matches ==="
rg -n --hidden --no-ignore -S "\bviem\b|from ['\"]viem['\"]|require\(\s*['\"]viem['\"]\s*\)" stablepay-sdk \
  --glob '!stablepay-sdk/example/**' \
  --glob '!**/node_modules/**' \
  | head -n 80 || true

echo
echo "=== ethers usage in stablepay-sdk (excluding example/, node_modules), first 80 matches ==="
rg -n --hidden --no-ignore -S "\bethers\b|from ['\"]ethers['\"]|require\(\s*['\"]ethers['\"]\s*\)" stablepay-sdk \
  --glob '!stablepay-sdk/example/**' \
  --glob '!**/node_modules/**' \
  | head -n 80 || true

echo
echo "=== List all package.json under stablepay-sdk excluding example, and show ethers/viem-related dependency keys ==="
find stablepay-sdk -name package.json -not -path "*/example/*" -print | sort > /tmp/pkgjsons.txt
if [ -s /tmp/pkgjsons.txt ]; then
  while IFS= read -r f; do
    echo "--- $f ---"
    node -e "
      const fs=require('fs');
      const p=JSON.parse(fs.readFileSync('$f','utf8'));
      const keys=['dependencies','peerDependencies','devDependencies','optionalDependencies'];
      for (const k of keys){
        if (p[k] && (p[k].ethers || p[k].viem)){
          console.log(k, {ethers:p[k].ethers, viem:p[k].viem});
        }
      }
    "
  done < /tmp/pkgjsons.txt
else
  echo "(no non-example package.json found)"
fi

Repository: DjedAlliance/StablePay

Length of output: 50379


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "=== ethers usage anywhere in stablepay-sdk/example (excluding node_modules & package-lock.json) ==="
rg -n --hidden --no-ignore -S "\bethers\b|from ['\"]ethers['\"]|require\(\s*['\"]ethers['\"]\s*\)" stablepay-sdk/example \
  --glob '!**/node_modules/**' \
  --glob '!**/package-lock.json' \
  || true

echo
echo "=== viem usage anywhere in stablepay-sdk/example (excluding node_modules & package-lock.json), first 40 matches ==="
rg -n --hidden --no-ignore -S "\bviem\b|from ['\"]viem['\"]|require\(\s*['\"]viem['\"]\s*\)" stablepay-sdk/example \
  --glob '!**/node_modules/**' \
  --glob '!**/package-lock.json' \
  | head -n 40 || true

Repository: DjedAlliance/StablePay

Length of output: 406


Remove unused ethers dependency from stablepay-sdk/example [minor]

  • stablepay-sdk/example/package.json declares ethers, but there are no ethers imports/usages in stablepay-sdk/example/src (it only appears in the example manifest/lockfile).
  • The SDK/widget code uses viem for wallet interactions (e.g., stablepay-sdk/src/widget/TransactionReview.jsx), so the example app shouldn’t need ethers directly.
  • Drop ethers from stablepay-sdk/example/package.json (and update package-lock.json) to avoid dependency bloat/confusion.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@stablepay-sdk/example/package.json` around lines 12 - 18, Remove the unused
ethers dependency from the example app by deleting the "ethers" entry in
stablepay-sdk/example/package.json and then regenerate the lockfile
(package-lock.json) by running the package manager (e.g., npm install) inside
stablepay-sdk/example; ensure no code in stablepay-sdk/example/src imports
"ethers" (the widget uses viem, see
stablepay-sdk/src/widget/TransactionReview.jsx) before committing the updated
package.json and package-lock.json.

Comment thread stablepay-sdk/example/src/App.jsx Outdated
Comment thread stablepay-sdk/example/src/App.jsx Outdated
Comment thread stablepay-sdk/src/core/Transaction.js Outdated
Comment on lines +56 to +57
const isConnectionError = error.code === -32603 || error.code === 4001 || error.code === -32005 || (error.message && (error.message.includes('CONNECTION ERROR') || error.message.includes('ERR_NAME_NOT_RESOLVED')));
if (isConnectionError) {

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Inspect the exact lines in Transaction.js
sed -n '1,120p' stablepay-sdk/src/core/Transaction.js | nl -ba | sed -n '40,95p'

# Show the rest around the error handling (if present)
rg -n "isConnectionError|error\.code === 4001|CONNECTION ERROR|ERR_NAME_NOT_RESOLVED" stablepay-sdk/src/core/Transaction.js

# Find all occurrences of "=== 4001" across the repo
rg -n "code === 4001" stablepay-sdk/src | head -n 50

# Inspect the referenced wallet/transaction UI files where 4001 is likely handled
ls -la stablepay-sdk/src/contexts || true
ls -la stablepay-sdk/src/widget || true

sed -n '1,220p' stablepay-sdk/src/contexts/WalletContext.jsx | nl -ba | sed -n '1,220p'
sed -n '200,340p' stablepay-sdk/src/widget/TransactionReview.jsx | nl -ba | sed -n '200,340p'

# Search for any docs/mapping of error codes for web3/eth provider
rg -n "4001|UserRejectedRequestError|User denied" stablepay-sdk/src stablepay-sdk/package.json package.json || true

Repository: DjedAlliance/StablePay

Length of output: 109


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# 1) Inspect Transaction.js around the relevant lines (no nl)
echo "=== Transaction.js around line 56-57 ==="
sed -n '45,80p' stablepay-sdk/src/core/Transaction.js | cat -n

echo "=== Exact occurrences of 4001 / connection-error markers in Transaction.js ==="
rg -n "isConnectionError|error\.code\s*===\s*4001|CONNECTION ERROR|ERR_NAME_NOT_RESOLVED" stablepay-sdk/src/core/Transaction.js

# 2) Find all uses of code === 4001 in the repo (for context consistency)
echo "=== All occurrences of \"code === 4001\" in stablepay-sdk/src ==="
rg -n "code\s*===\s*4001" stablepay-sdk/src | head -n 50

# 3) Inspect the referenced wallet/transaction UI files for how 4001 is classified
echo "=== WalletContext.jsx around switchToNetwork / sendTransaction error handling ==="
sed -n '1,260p' stablepay-sdk/src/contexts/WalletContext.jsx | cat -n
echo "=== TransactionReview.jsx around error handling area (near ~246) ==="
sed -n '200,340p' stablepay-sdk/src/widget/TransactionReview.jsx | cat -n

# 4) Check any error-code mapping/docs (quick grep)
echo "=== Mentions of 4001/UserRejectedRequestError in repo ==="
rg -n "4001|UserRejectedRequestError|User denied|rejected" stablepay-sdk/src | head -n 100

Repository: DjedAlliance/StablePay

Length of output: 20925


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "=== Transaction.js (top portion) ==="
sed -n '1,120p' stablepay-sdk/src/core/Transaction.js | cat -n

echo "=== Check if Transaction.js references window.ethereum ==="
rg -n "window\.ethereum|eth_requestAccounts|wallet_switchEthereumChain|wallet_addEthereumChain|UserRejectedRequestError" stablepay-sdk/src/core/Transaction.js || true

echo "=== Check what calls are inside the init try block (look for web3 init / provider calls) ==="
# Print the section from the start of the likely init/constructor around where the catch we saw is located
sed -n '120,220p' stablepay-sdk/src/core/Transaction.js | cat -n

echo "=== Search for 'RPC endpoint' wording to find any message templates ==="
rg -n "Failed to connect to .* RPC endpoint" stablepay-sdk/src/core/Transaction.js

Repository: DjedAlliance/StablePay

Length of output: 6398


Fix inconsistent handling of error code 4001

stablepay-sdk/src/core/Transaction.js includes error.code === 4001 in isConnectionError, which throws an RPC-connection failure message. In the rest of the SDK, 4001 is treated as user rejection (stablepay-sdk/src/contexts/WalletContext.jsx, stablepay-sdk/src/widget/TransactionReview.jsx), so this classification is inconsistent and can mislead if 4001 ever propagates here. Remove 4001 from the connection-error bucket (or handle it separately as user rejection).

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@stablepay-sdk/src/core/Transaction.js` around lines 56 - 57, The
isConnectionError check in Transaction.js incorrectly treats error.code === 4001
as an RPC connection failure; remove 4001 from the isConnectionError condition
in the isConnectionError declaration inside the Transaction handling logic and
instead handle error.code === 4001 as a user-rejection case (consistent with
WalletContext.jsx and TransactionReview.jsx), e.g., branch separately to
return/throw a user-rejection error or status so 4001 is no longer classified as
a connection error.

Comment on lines +101 to +104
<button
className={styles.walletButton}
onClick={() => window.open('https://metamask.io/download/', '_blank')}
>

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

file="stablepay-sdk/src/widget/TransactionReview.jsx"

# Basic sanity: ensure file exists and show relevant lines around 90-120
if [ ! -f "$file" ]; then
  echo "Missing file: $file" >&2
  exit 1
fi

echo "---- Context ($file:80-130) ----"
nl -ba "$file" | sed -n '80,130p'

echo
echo "---- Search for window.open( in repo ----"
rg -n "window\.open\(" stablepay-sdk/src/widget/TransactionReview.jsx stablepay-sdk/src || true

Repository: DjedAlliance/StablePay

Length of output: 202


🏁 Script executed:

#!/bin/bash
set -euo pipefail

file="stablepay-sdk/src/widget/TransactionReview.jsx"

# Basic sanity: ensure file exists and show relevant lines around 90-120
if [ ! -f "$file" ]; then
  echo "Missing file: $file" >&2
  exit 1
fi

echo "---- Context ($file:80-130) ----"
nl -ba "$file" | sed -n '80,130p'

echo
echo "---- Search for window.open( in repo ----"
rg -n "window\.open\(" stablepay-sdk/src || true

echo
echo "---- Search for rel/noopener patterns in JSX anchor tags ----"
rg -n "rel\s*=\s*{?.*noopener|noopener|noreferrer" stablepay-sdk/src || true

Repository: DjedAlliance/StablePay

Length of output: 202


🏁 Script executed:

#!/bin/bash
set -euo pipefail

file="stablepay-sdk/src/widget/TransactionReview.jsx"

if [ ! -f "$file" ]; then
  echo "Missing file: $file" >&2
  exit 1
fi

echo "---- Context ($file:95-110) ----"
sed -n '95,110p' "$file" | awk '{printf "%d:%s\n", NR+94, $0}'

echo
echo "---- Search for window.open( in TransactionReview.jsx ----"
rg -n "window\.open\(" "$file" || true

echo
echo "---- Search for window.open( in stablepay-sdk/src ----"
rg -n "window\.open\(" stablepay-sdk/src || true

echo
echo "---- Search for noopener/noreferrer usage in stablepay-sdk/src ----"
rg -n "noopener|noreferrer|rel\s*=\s*['\"]noopener|rel\s*=\s*['\"]noreferrer|noopener,noreferrer" stablepay-sdk/src || true

Repository: DjedAlliance/StablePay

Length of output: 1252


Harden external link opening against tabnabbing.

window.open(..., '_blank') at the click handler lacks noopener/noreferrer, allowing the opened page to control window.opener. Add the flags via the third argument.

Suggested patch
- onClick={() => window.open('https://metamask.io/download/', '_blank')}
+ onClick={() => window.open('https://metamask.io/download/', '_blank', 'noopener,noreferrer')}
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
<button
className={styles.walletButton}
onClick={() => window.open('https://metamask.io/download/', '_blank')}
>
<button
className={styles.walletButton}
onClick={() => window.open('https://metamask.io/download/', '_blank', 'noopener,noreferrer')}
>
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@stablepay-sdk/src/widget/TransactionReview.jsx` around lines 101 - 104, The
button's onClick uses window.open(url, '_blank') which is vulnerable to
tabnabbing; update the click handler in TransactionReview.jsx to call
window.open('https://metamask.io/download/', '_blank', 'noopener,noreferrer')
(or alternatively set the returned window's opener to null) so the opened page
cannot access window.opener.

let builtTx;

if (selectedToken.key === "native") {
const UI = "0x0232556C83791b8291E9b23BfEa7d67405Bd9839";

@Atharva0506 Atharva0506 Jun 8, 2026

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Is there a reason this address is hardcoded? Would it be better to source it from a configuration/constants file so it can be updated more easily and avoids chain-specific values being embedded in the logic?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

@Atharva0506 The UI variable is the address of the stablepay treasury; basically, any transaction done through this interface will pay some fee to this address. It is meant to be hardcoded and not configured by a developer as an environment variable.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Got it

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.

Improvement: Improve User Experience (Validation & Flow)

2 participants