Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
2bfda71
feat: init useX402Fetch and useX402Auth
lwin-kyaw Mar 18, 2026
9c2ade9
fix: fixed exports from modal
lwin-kyaw Mar 18, 2026
017d683
feat: update wagmi-react-app demo
lwin-kyaw Mar 18, 2026
3d7a4f4
fix: fixed PAYMENT-REQUIRED header decode
lwin-kyaw Mar 19, 2026
67b9975
feat: updated useX402Fetch
lwin-kyaw Mar 19, 2026
6e6b0a0
chore: refactor
lwin-kyaw Mar 19, 2026
9e63184
feat: x402 vue composables
lwin-kyaw Mar 19, 2026
af267f5
feat: added test-x402-server to the demo
lwin-kyaw Mar 19, 2026
c3b04e5
fix: fixed useX402Fetch vue composable
lwin-kyaw Mar 19, 2026
41b07e6
feat: updated vue-app-new demo and fixed useX402Fetch composable
lwin-kyaw Mar 19, 2026
2051530
feat: added solana support to x402Fetch Vue composible and updated demo
lwin-kyaw Mar 19, 2026
74e4a1c
feat: add solana support to useX402Fetch react hook
lwin-kyaw Mar 19, 2026
da22378
fix: rebased with v10 and fixed build
lwin-kyaw Mar 20, 2026
02d2834
chore: rebased with master
lwin-kyaw Mar 20, 2026
9f44133
chore: refactors and fixed vue-new-app demo
lwin-kyaw Mar 20, 2026
105c5c9
chore: refactors and testings
lwin-kyaw Mar 20, 2026
509c9b7
chore: wagmi-react-app demo env
lwin-kyaw Mar 20, 2026
4843bf2
fix: fixed bugs
lwin-kyaw Mar 20, 2026
f0ff2d4
feat: removed wagmi dependent code from x402 fns
lwin-kyaw Mar 20, 2026
a9f7632
chore: cleanups and minor bug fixes
lwin-kyaw Mar 20, 2026
4d6c86d
fix: fixed registry in locks
lwin-kyaw Mar 20, 2026
2755b00
chore: resolved conflicts
lwin-kyaw Apr 1, 2026
e1cf15f
fix: fixed x402 hooks
lwin-kyaw Apr 1, 2026
6268075
chore: resolved conflicts on vue-app-new demo
lwin-kyaw Apr 1, 2026
2909205
chore: load x402 test content endpoint from env
lwin-kyaw Apr 1, 2026
a875599
chore: addressed comments
lwin-kyaw Apr 1, 2026
acbb7c6
chore: resolved conflicts
lwin-kyaw Apr 9, 2026
7692574
feat: update demo
lwin-kyaw Apr 9, 2026
72891eb
chore: add x402 testing plan
lwin-kyaw Apr 9, 2026
921c6bc
feat: update x402 exports and make deps as optional peers
lwin-kyaw Apr 10, 2026
ee7f4f8
chore: resolved conflicts
lwin-kyaw Apr 13, 2026
bfd8c41
chore: refactors and cleanups x402 hooks
lwin-kyaw Apr 13, 2026
e410f1d
fix: solana sign for x402
lwin-kyaw Apr 13, 2026
6e011f7
chore: update demo solana
lwin-kyaw Apr 13, 2026
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
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ typings/

# Optional npm cache directory
.npm
.npmrc

# Optional eslint cache
.eslintcache
Expand Down
1 change: 1 addition & 0 deletions demo/vue-app-new/.env.sample
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,4 @@ VITE_APP_SOLANA_MAINNET_RPC=""
VITE_APP_SOLANA_DEVNET_RPC=""
VITE_APP_SOLANA_TESTNET_RPC=""
VITE_APP_AUTH_BUILD_ENV=""
VITE_APP_X402_TEST_CONTENT_URL=""
154 changes: 154 additions & 0 deletions demo/vue-app-new/X402_TESTING_PLAN.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
# x402 Testing Plan

## Goal

Validate the end-to-end x402 payment flow used by the Vue demo against the local x402 test server.

Success means:

- protected endpoints return a payment challenge when no payment is attached
- a funded Base Sepolia wallet can complete the paid retry successfully
- `X402Tester` writes results and errors to the shared dashboard UI console
- common failure modes are easy to reproduce and diagnose

## Scope

This plan covers the main x402 demo path across:

- `demo/vue-app-new/src/components/X402Tester.vue`
- `demo/vue-app-new/src/components/AppDashboard.vue`
- `demo/x402-test-server/src/index.ts`
- the `useX402Fetch` flow exposed through `@web3auth/modal/x402/vue`

It does not try to fully validate every wallet provider or every facilitator implementation.

## Test Environment

### Backend

Start the local x402 server:

```bash
cd demo/x402-test-server
cp .env.example .env
# Set EVM_ADDRESS and SVM_ADDRESS
npm install
npm run dev
```

Expected default server URL:

```text
http://localhost:4021
```

### Frontend

Start the Vue demo and point it at the local server:

```bash
cd demo/vue-app-new
cp .env.sample .env
```

Set at least:

```bash
VITE_APP_X402_TEST_CONTENT_URL=http://localhost:4021/weather
```

Then run:

```bash
npm install
npm run dev
```

## Preconditions

- Web3Auth login is working in the Vue demo
- an EVM wallet is connected
- the wallet can switch to Base Sepolia (`0x14a34`)
- the wallet has enough Base Sepolia gas
- the wallet has enough Base Sepolia USDC for micro-payments

## Endpoints Under Test

| Method | Path | Expected behavior |
| ------ | ---- | ----------------- |
| `GET` | `/health` | Free health check |
| `GET` | `/weather` | Standard paid x402 route |
| `GET` | `/premium-data` | Paid route with higher price |
| `GET` | `/weather-plain` | Debug-friendly route that returns payment requirements in the body when unpaid |

## Manual Test Cases

| ID | Scenario | Steps | Expected result |
| -- | -------- | ----- | --------------- |
| `X402-01` | Server health | Call `GET /health` in a browser or with `curl` | `200 OK` with JSON status payload |
| `X402-02` | Unpaid challenge for `/weather` | Call `GET /weather` without payment headers | `402 Payment Required` and x402 payment requirements |
| `X402-03` | Successful paid fetch for `/weather` in Vue UI | Log in, connect wallet, switch to Base Sepolia, keep the tester URL on `/weather`, and press `Fetch with Payment` | shared UI console shows `x402 response`, `status: 200`, and a weather payload in `body` |
| `X402-04` | Successful paid fetch for `/premium-data` in Vue UI | Change the tester URL to `/premium-data` and press `Fetch with Payment` | shared UI console shows `x402 response`, `status: 200`, and premium dataset JSON |
| `X402-05` | Debug route without payment | Call `GET /weather-plain` without payment headers | `402` body includes `accepts` array and resource metadata |
| `X402-06` | Debug route through Vue UI | Set the tester URL to `/weather-plain` and press `Fetch with Payment` | shared UI console shows `x402 response`, `status: 200`, and the weather payload |
| `X402-07` | Wrong-network recovery | Open the Vue demo while connected to an EVM chain other than Base Sepolia | tester shows `Not on Base Sepolia`; after pressing `Switch to Base Sepolia`, the badge updates and fetch can be retried |
| `X402-08` | Insufficient balance failure | Use a wallet without enough USDC or gas and attempt `Fetch with Payment` | fetch fails cleanly; UI console shows an actionable error or a 402-style response that can be inspected |

## Focus Areas During Testing

### UI behavior

- the `Fetch with Payment` button is disabled when no wallet is connected
- loading state is shown while the request is in flight
- results are printed in the dashboard console, not inline inside `X402Tester`
- errors are also routed to the dashboard console

### Payment behavior

- unpaid requests are challenged instead of silently failing
- paid retries use the connected wallet on Base Sepolia
- the same URL can be retested multiple times without refreshing the page
- successful payments return the protected resource body

### Debuggability

- `/weather-plain` remains available as a browser-friendly inspection route
- server logs are sufficient to distinguish challenge, retry, and settlement failures
- console output includes enough context to see which URL was tested and whether the response was successful

## Suggested cURL Checks

Use these checks before testing the Vue flow:

```bash
curl -i http://localhost:4021/health
curl -i http://localhost:4021/weather
curl -i http://localhost:4021/weather-plain
curl -i http://localhost:4021/premium-data
```

Expected outcomes:

- `/health` returns `200`
- paid routes return `402` when no payment is attached
- `/weather-plain` returns a readable JSON challenge body

## Failure Cases To Watch

Common issues worth validating explicitly:

- wallet is connected, but not on Base Sepolia
- wallet has insufficient USDC for the requested payment
- wallet has insufficient gas to complete the transaction
- a stale or expired payment proof is retried
- the configured tester URL points to the wrong server or port
- the frontend shows no result because console output wiring regressed

## Exit Criteria

The testing cycle is complete when:

- `X402-01` through `X402-06` pass
- at least one negative case from `X402-07` or `X402-08` is exercised
- success and failure states are both visible in the dashboard console
- no inline result panel is required to inspect x402 responses
18 changes: 17 additions & 1 deletion demo/vue-app-new/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

30 changes: 10 additions & 20 deletions demo/vue-app-new/src/components/AppDashboard.vue
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ import {
useWalletUI,
useWeb3Auth,
useWeb3AuthUser,

} from "@web3auth/modal/vue";
import { CONNECTOR_INITIAL_AUTHENTICATION_MODE, type CustomChainConfig } from "@web3auth/no-modal";
import { useI18n } from "petite-vue-i18n";
Expand All @@ -30,9 +29,10 @@ import {
import { getCapabilities, getCallsStatus, sendCalls, showCallsStatus } from "@wagmi/core";
import { parseEther } from "viem";
import { createWalletTransactionSigner, toAddress } from "@solana/client";
import { address as solanaAddress, } from "@solana/kit";
import { address as solanaAddress } from "@solana/kit";
import { getTransferSolInstruction } from "@solana-program/system";
import { computed, ref, watch } from "vue";
import X402Tester from "./X402Tester.vue";
import { getPrivateKey, sendEth, sendEthWithSmartAccount, signTransaction as signEthTransaction } from "../services/ethHandlers";
import { formDataStore } from "../store/form";

Expand Down Expand Up @@ -108,10 +108,7 @@ const isDisplay = (name: "dashboard" | "ethServices" | "solServices" | "walletSe
return Boolean(conn?.solanaWallet);

case "walletServices":
return (
web3Auth.value?.connectedConnectorName === WALLET_CONNECTORS.AUTH &&
Boolean(conn?.ethereumProvider || conn?.solanaWallet)
);
return web3Auth.value?.connectedConnectorName === WALLET_CONNECTORS.AUTH && Boolean(conn?.ethereumProvider || conn?.solanaWallet);

default: {
return false;
Expand Down Expand Up @@ -394,8 +391,6 @@ const onSwitchChain = async () => {
printToConsole("switchedChain error", error);
}
};


</script>

<template>
Expand Down Expand Up @@ -496,20 +491,15 @@ const onSwitchChain = async () => {

<!-- EIP-5792 -->
<div class="mb-2 mt-4 text-xl font-bold leading-tight text-left">EIP-5792</div>
<Button block size="xs" pill class="mb-2" @click="onGetCapabilities">
Get Capabilities
</Button>
<Button block size="xs" pill class="mb-2" @click="onSendBatchCalls">
Send Batch Calls
</Button>
<Button v-if="trackedCallsId" block size="xs" pill class="mb-2" @click="onRefetchCallsStatus">
Refresh Calls Status
</Button>
<Button v-if="trackedCallsId" block size="xs" pill class="mb-2" @click="onShowCallsStatusInWallet">
Show Calls Status in Wallet
</Button>
<Button block size="xs" pill class="mb-2" @click="onGetCapabilities">Get Capabilities</Button>
<Button block size="xs" pill class="mb-2" @click="onSendBatchCalls">Send Batch Calls</Button>
<Button v-if="trackedCallsId" block size="xs" pill class="mb-2" @click="onRefetchCallsStatus">Refresh Calls Status</Button>
<Button v-if="trackedCallsId" block size="xs" pill class="mb-2" @click="onShowCallsStatusInWallet">Show Calls Status in Wallet</Button>
</Card>

<!-- x402 -->
<X402Tester v-if="isDisplay('ethServices') || isDisplay('solServices')" class="mb-2" @print-to-console="printToConsole" />

<!-- SOLANA -->
<Card v-if="isDisplay('solServices')" class="h-auto gap-4 px-4 py-4 mb-2" :shadow="false">
<div class="mb-2 text-xl font-bold leading-tight text-left">Solana Transaction</div>
Expand Down
Loading
Loading