Skip to content

feat: enable on-ramp on Starknet.#504

Open
sundayonah wants to merge 4 commits into
mainfrom
feat/starknet-onramp
Open

feat: enable on-ramp on Starknet.#504
sundayonah wants to merge 4 commits into
mainfrom
feat/starknet-onramp

Conversation

@sundayonah
Copy link
Copy Markdown
Collaborator

@sundayonah sundayonah commented May 19, 2026

Summary

  • Enable on-ramp on Starknet by removing UI and flow guards that previously blocked Starknet + on-ramp (rate fetch skip, form submit block, disabled controls, and "Coming soon" swap button behavior).
  • Use useWalletAddress() in TransactionForm for on-ramp "My wallet" / recipient address so the payout target is the Starknet embedded wallet on Starknet (not the EVM smart wallet).
  • Add validateWalletAddress in app/lib/validation.ts for network-aware on-ramp recipient validation (EVM unchanged via existing isValidEvmAddressCaseInsensitive; Starknet via new isValidStarknetAddress).
  • Wire RecipientDetailsForm to validateWalletAddress so short/full Starknet addresses validate correctly (fixes false "Invalid wallet address format" from EVM-only checks).

Description

Off-ramp on Starknet is already supported on Noblocks (gateway order via /api/starknet/create-order). This PR enables on-ramp on Starknet so users can fund their Starknet wallet the same way as on other networks: fiat pay-in through the existing v2 sender on-ramp path (createV2SenderPaymentOrder), not the Starknet gateway off-ramp API.

Frontend changes

  • MainPageContent: Remove early return that skipped buy-side rate fetching on Starknet; remove guard that prevented advancing to preview when swapMode === "onramp" on Starknet.
  • TransactionForm: Remove Starknet on-ramp lock UI (banner, disabled token dropdown, aria-describedby); pass useWalletAddress() as connectedWalletAddress for the recipient form.
  • useSwapButton: Remove isStarknetOnramp prop and related "Coming soon" / disabled submit behavior.
  • RecipientDetailsForm: Validate on-ramp wallet addresses with validateWalletAddress(value, networkName) instead of EVM-only validation.
  • validation.ts: Add isValidStarknetAddress and validateWalletAddress. isValidEvmAddressCaseInsensitive is unchanged and still used for EVM networks and to reject 42-char EVM addresses on Starknet.

Unchanged

  • Off-ramp on Starknet (embedded wallet + /api/starknet/create-order).
  • On-ramp order creation path on preview (createV2SenderPaymentOrder) — same as EVM; aggregator must expose Starknet tokens and buy rates in the target environment.
  • Default tab on Starknet remains off-ramp when no ?side= (initialSwapModeForHomeForm).

Breaking changes: None for API or public contracts.

Alternatives considered: Hand-rolling Starknet validation only in RecipientDetailsForm (rejected in favor of shared validation.ts); loosening the EVM regex to accept Starknet lengths (rejected — would break EVM-only callers).

Assumption: Aggregator supports Starknet as a crypto destination for v2 on-ramp (tokens, side=buy rates, provider settlement to recipient address).

References

Testing

Manual (staging/local with aggregator Starknet on-ramp configured)

  1. Select StarknetOn-ramp → choose fiat + USDC or USDT.
  2. Enter amount → confirm buy rate loads (not stuck at 0).
  3. Recipient: use My wallet or paste a Starknet address (e.g. shortened 0x… form) → no "Invalid wallet address format".
  4. Complete preview → create order → pay-in instructions → confirm status/history shows Starknet and explorer link when txHash is available.
  • before
image
  • after
image
  • This change adds test coverage for new/changed/fixed functionality

Checklist

  • I have added documentation and tests for new/changed functionality in this PR
  • All active GitHub checks for tests, formatting, and security are passing
  • The correct base branch is being used, if not main

By submitting a PR, I agree to Paycrest's Contributor Code of Conduct and Contribution Guide.

Summary by CodeRabbit

  • Bug Fixes

    • Wallet address validation now correctly supports Starknet and EVM formats with network-aware error messages.
    • Removed erroneous on‑ramp blocking on Starknet so form submission and rate fetching proceed normally.
  • Improvements

    • Swap button gating now enforces migration-related conditions and shows correct actions/text.
    • Wallet selection and connected-wallet sourcing improved (EOA vs smart wallet); form clears invalid wallet addresses when network changes.
  • Other

    • Minor UI/availability text and control adjustments for on‑ramp flow.

Review Change Stack

- Removed Starknet-specific checks from various components and hooks, simplifying the handling of on-ramp conditions.
- Replaced the deprecated `isValidEvmAddressCaseInsensitive` function with a new `validateWalletAddress` function that supports both EVM and Starknet address formats.
- Updated the `RecipientDetailsForm` and `TransactionForm` components to utilize the new validation logic, enhancing code clarity and maintainability.
- Removed unused Starknet-related props and conditions across components to improve overall code efficiency.
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 19, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 45b13eee-c6c5-44f1-823e-586d0e76f229

📥 Commits

Reviewing files that changed from the base of the PR and between fa16397 and 5bad5f5.

📒 Files selected for processing (1)
  • app/pages/TransactionForm.tsx

📝 Walkthrough

Walkthrough

Removes Starknet-specific on-ramp gating across MainPageContent, TransactionForm, and useSwapButton; adds network-aware wallet address validation and wires it into RecipientDetailsForm. TransactionForm now derives connected wallet address via useWalletAddress.

Changes

Starknet On-ramp Enablement

Layer / File(s) Summary
Network-aware wallet address validation utilities
app/lib/validation.ts
Adds isValidStarknetAddress (0x + 1–64 hex, rejects all-zero), documents isValidEvmAddressCaseInsensitive, and introduces validateWalletAddress(value, networkName) which returns true for empty input or routes to the appropriate validator and returns a format error string when invalid.
Update recipient form to use network-aware validation
app/components/recipient/RecipientDetailsForm.tsx
Replaces EVM-only isValidEvmAddressCaseInsensitive with validateWalletAddress(value, networkName ?? "") for the walletAddress field validation.
Remove on-ramp gating from swap button logic
app/hooks/useSwapButton.ts
Removes isStarknetOnramp prop and related early-return branches; adds migration-related flags (needsMigration, isRemainingFundsMigration) and relies on migration/auth/balance/verification conditions for enablement, CTA text, and actions.
Remove on-ramp early-exit branches from rate fetching and form submission
app/components/MainPageContent.tsx
Drops isStarknetChain import; deletes early-return that forced rate to 0 and blocked Starknet on-ramp submission; simplifies handleFormSubmit dependencies.
Derive connected wallet address and remove UI gating
app/hooks/useWalletAddress.ts, app/pages/TransactionForm.tsx
useWalletAddress selects embedded EOA vs smart-wallet using useShouldUseEOA; TransactionForm now uses useWalletAddress for connectedWalletAddress, clears EVM-shaped walletAddress when switching to Starknet, removes Starknet-onramp UI/aria disabling, and stops passing isStarknetOnramp into useSwapButton.
Minor preview fix
app/pages/TransactionPreview.tsx
Adds a trailing comma in the wallets.find callback predicate; no behavior change.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

Suggested reviewers

  • chibie
  • 5ran6
  • onahprosper

Poem

🐰 I nibbled through gates and cleared the way,
Starknet no longer told users "stay",
Validators tuned for each chain's art,
Wallets now pick the proper part.
🌱

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the main change: enabling on-ramp functionality on Starknet, which is the primary objective of this PR.
Description check ✅ Passed The PR description is comprehensive with clear summary, detailed explanation of changes, references to issue #492, and manual testing steps with before/after images, though test coverage checkboxes remain unchecked.
Linked Issues check ✅ Passed The code changes directly address all acceptance criteria in issue #492: Starknet appears in on-ramp flow, rate fetching works, validation handles Starknet addresses, and the full flow proceeds without Starknet-specific blocks.
Out of Scope Changes check ✅ Passed All changes are scoped to enabling Starknet on-ramp: removing guards, updating wallet address handling via useWalletAddress(), adding Starknet-aware validation, and updating form behavior. No unrelated modifications detected.
Docstring Coverage ✅ Passed Docstring coverage is 80.00% which is sufficient. The required threshold is 80.00%.

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

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/starknet-onramp

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

@sundayonah sundayonah changed the title refactor(validation): streamline wallet address validation logic feat: enable on-ramp on Starknet. May 19, 2026
Copy link
Copy Markdown
Contributor

@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: 1

🧹 Nitpick comments (1)
app/pages/TransactionForm.tsx (1)

39-39: ⚡ Quick win

Unused import: useWalletAddress is not referenced.

The import is never used in this file. Either remove it or use it to derive connectedWalletAddress (see comment on line 1111).

♻️ Remove unused import
-import { useWalletAddress } from "../hooks/useWalletAddress";
🤖 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 `@app/pages/TransactionForm.tsx` at line 39, The import useWalletAddress is
unused; either remove the import statement or use the hook inside the
TransactionForm component to derive connectedWalletAddress. If you choose to use
it, call useWalletAddress() (e.g., const connectedWalletAddress =
useWalletAddress()) inside the TransactionForm function and replace any existing
hardcoded or placeholder connectedWalletAddress references with that value;
otherwise delete the unused import line to eliminate the dead import. Ensure you
update any downstream code in TransactionForm that expects
connectedWalletAddress to use the hook-derived value.
🤖 Prompt for all review comments with 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.

Inline comments:
In `@app/pages/TransactionForm.tsx`:
- Line 1111: activeWallet?.address is being passed into the
connectedWalletAddress prop but activeWallet has no Starknet-specific branch, so
embedded Starknet wallets get an EVM address; call the existing hook
useWalletAddress near the top of the component (after the existing hooks around
line ~91) to obtain walletAddress (network-aware) and replace
connectedWalletAddress={activeWallet?.address ?? undefined} with
connectedWalletAddress={walletAddress ?? undefined}; ensure useWalletAddress is
imported/used and remove reliance on activeWallet for the recipient address so
Starknet users receive their correct embedded Starknet wallet address.

---

Nitpick comments:
In `@app/pages/TransactionForm.tsx`:
- Line 39: The import useWalletAddress is unused; either remove the import
statement or use the hook inside the TransactionForm component to derive
connectedWalletAddress. If you choose to use it, call useWalletAddress() (e.g.,
const connectedWalletAddress = useWalletAddress()) inside the TransactionForm
function and replace any existing hardcoded or placeholder
connectedWalletAddress references with that value; otherwise delete the unused
import line to eliminate the dead import. Ensure you update any downstream code
in TransactionForm that expects connectedWalletAddress to use the hook-derived
value.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: a18524c2-899f-4523-9abe-d9efaf63104c

📥 Commits

Reviewing files that changed from the base of the PR and between 5171b42 and aac420c.

📒 Files selected for processing (1)
  • app/pages/TransactionForm.tsx

Comment thread app/pages/TransactionForm.tsx Outdated
Copy link
Copy Markdown
Contributor

@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: 1

🤖 Prompt for all review comments with 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.

Inline comments:
In `@app/pages/TransactionForm.tsx`:
- Around line 583-593: The effect only clears EVM-shaped addresses when
switching to Starknet, causing stale Starknet recipients to persist when
switching back to EVM; update the useEffect that reads
getValues("walletAddress") and uses selectedNetwork.chain.name so it validates
the current wallet address against the newly selected network and clears it if
invalid. Concretely, replace the current condition (which only checks
selectedNetwork.chain.name === "Starknet" &&
isValidEvmAddressCaseInsensitive(w)) with a network-aware validity check: if
selectedNetwork.chain.name is "Starknet" ensure the address is a valid Starknet
address (use the existing Starknet validator, e.g., isValidStarknetAddress),
otherwise ensure the address is a valid EVM address
(isValidEvmAddressCaseInsensitive); if the address is invalid for the selected
network call setValue("walletAddress", "", { shouldDirty: true }). Ensure you
reference the same useEffect, getValues, setValue and selectedNetwork.chain.name
symbols when making the change.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 1d626bce-8e7d-41cd-bc75-0f134ddafa81

📥 Commits

Reviewing files that changed from the base of the PR and between aac420c and fa16397.

📒 Files selected for processing (3)
  • app/hooks/useWalletAddress.ts
  • app/pages/TransactionForm.tsx
  • app/pages/TransactionPreview.tsx
✅ Files skipped from review due to trivial changes (1)
  • app/pages/TransactionPreview.tsx

Comment thread app/pages/TransactionForm.tsx Outdated
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.

Add Starknet On-ramp Support on Noblocks

1 participant