DEV Community

Daniel Ioni
Daniel Ioni

Posted on

MyZubster Marketplace + MetaMask: First Real Ethereum Sepolia Integration Test

MyZubster Marketplace + MetaMask: First Real Ethereum Sepolia Integration Test

We are moving the MyZubster Marketplace toward a flow where identity, wallet ownership, marketplace requests, and blockchain payments are clearly separated.

The target flow is:

MyZubster account → verified wallet → signed marketplace request → accepted order → ETH payment on Ethereum Sepolia → server-side blockchain verification → completed order

During this development session, we successfully validated several important parts of that architecture in a real test environment.

Just as importantly, we now have a clear picture of what still needs to be completed before we can call the full Marketplace ETH flow end-to-end verified.
A Separate E2E Environment

The first decision was to avoid experimenting directly on production.

We created a dedicated Git worktree on the VPS for the Sepolia E2E branch and kept the production checkout untouched.

The test backend runs separately on:

127.0.0.1:5010

The React test frontend runs on:

127.0.0.1:3010

Production continues using its existing service and port.

This gives us an isolated environment where wallet signing, Marketplace requests, and blockchain transactions can be tested without changing the public deployment.
Ethereum Sepolia RPC Is Working

We configured an Ethereum Sepolia RPC endpoint through Alchemy.

The connection was tested directly with JSON-RPC and successfully returned a Sepolia block number.

That confirms the backend has working blockchain access.

This is important because MyZubster's payment verifier needs to independently inspect the blockchain and validate:

transaction hash;

sender address;

recipient address;

amount;

network;

transaction status;

confirmation count.
Enter fullscreen mode Exit fullscreen mode

The RPC credential stays on the server and is not exposed to the browser.
The Test Environment Is Not Publicly Exposed

Instead of opening ports 3010 and 5010 to the Internet, we kept both services bound to localhost on the VPS.

Access from the development machine is provided through an SSH local tunnel:

ssh -N \
-L 127.0.0.1:3010:127.0.0.1:3010 \
root@SERVER

The tunnel was successfully verified from Windows:

TcpTestSucceeded : True

The frontend also returned:

HTTP/1.1 200 OK

This allowed us to use the real browser and MetaMask extension while keeping the development server private.
The React Marketplace Is Running Through the Test Backend

The React development frontend uses relative API calls such as:

/api/wallet/me
/api/marketplace/...

For the E2E environment, the frontend development proxy points to the isolated backend on port 5010.

That means:

Browser
↓
127.0.0.1:3010
↓
React development proxy
↓
127.0.0.1:5010
↓
MyZubster Sepolia backend

Both frontend loading and backend health checks are working.
Real MyZubster Authentication Was Reused

The test frontend requires a valid MyZubster session before a wallet can be connected.

Because the account being tested uses Google/GitHub OAuth, we reused an already authenticated MyZubster session for the localhost environment.

No password or private wallet key was required.

Once the valid MyZubster authentication token was available in the local test origin, the wallet integration became accessible.
MetaMask Wallet Ownership Verification Works

This is one of the most important results of the test.

The Marketplace wallet panel initially showed:

ETH / EVM wallet

Not verified

After authenticating the MyZubster account, we selected:

Connect MetaMask

The browser successfully communicated with the MetaMask extension.

MyZubster then requested a wallet challenge from the backend and MetaMask signed that challenge using:

personal_sign

This is an off-chain signature.

It is not a blockchain transaction.

It does not transfer ETH.

It does not consume gas.

It only proves that the current MyZubster user controls the selected EVM wallet.

The final UI state became:

Verified · 0xBBBc51B471…03f514bCBb

Wallet MetaMask verified and linked to your MyZubster account.

This confirms that the complete wallet ownership flow is working:

MyZubster authenticated user
↓
MetaMask account
↓
server-generated challenge
↓
personal_sign
↓
server signature verification
↓
wallet linked to MyZubster account

Wallet Verification Is Separate From Payment

One architectural detail is especially important.

The wallet was verified while MetaMask reported:

chain ID 84532

That network is Base Sepolia.

The Marketplace ETH payment system, however, targets:

Ethereum Sepolia
chainId: 11155111
hex: 0xaa36a7

This is not a problem for wallet ownership verification.

The signature proves control of the EVM address independently of an ETH payment.

When an actual Marketplace payment starts, the frontend checks the network again and requests MetaMask to switch to Ethereum Sepolia if necessary.

This gives us an important separation:

CONNECTED
≠ VERIFIED
≠ AUTHENTICATED
≠ REQUEST SIGNED
≠ TX SUBMITTED
≠ PAID

Each state represents a different security boundary.
Signed Marketplace Requests Are Implemented

The Marketplace code can also require a Buyer to sign a Marketplace request.

The intended process is:

Buyer selects listing
↓
MyZubster creates order challenge
↓
Buyer signs challenge with MetaMask
↓
Backend verifies signature
↓
Marketplace request is created

Again, this signature is not a payment.

It proves that the wallet attached to the request is controlled by the authenticated Buyer.

The request can therefore carry verified wallet evidence to the Seller before any blockchain payment occurs.
Seller Wallet Evidence Is Implemented

The Marketplace order flow includes wallet evidence that can be shown to the Seller.

This is intended to allow the Seller to verify that the Buyer request is associated with a wallet already verified by MyZubster.

The payment lifecycle is therefore not simply:

click → send ETH

Instead it becomes:

identity
→ verified wallet
→ signed request
→ Seller acceptance
→ payment intent
→ blockchain transaction
→ independent verification

That separation is deliberate.
Ethereum Sepolia Payment Flow Is Implemented

For ETH orders, the backend can generate a payment intent containing the expected:

sender
recipient
amount
chain

The browser then checks that the currently selected MetaMask wallet matches the verified Buyer wallet.

It also checks that MetaMask is connected to Ethereum Sepolia.

If necessary, it calls:

wallet_switchEthereumChain

with:

0xaa36a7

Only after those checks does the browser call:

eth_sendTransaction

MetaMask still requires explicit user confirmation.

MyZubster does not hold the user's private key and cannot silently send the transaction.
Server-Side Payment Verification

Submitting a transaction hash does not automatically make an order paid.

The backend independently checks the Sepolia transaction.

The verifier is designed to validate:

transaction exists
sender matches Buyer
recipient matches Seller
amount matches payment intent
network is Ethereum Sepolia
transaction succeeded
minimum confirmations reached

The current lifecycle includes states such as:

CONFIRMING
PAID
FAILED

The target minimum for the current test is:

3 confirmations

This means a transaction may exist on-chain but still remain:

CONFIRMING

until the confirmation threshold has been reached.

Only after successful blockchain verification should the Marketplace order move to:

PAID

What We Have Actually Verified

At this point, we have successfully verified the following in a real environment:

isolated VPS E2E environment;

production kept separate from the test stack;

Ethereum Sepolia JSON-RPC connectivity;

backend connection to MongoDB;

test backend running independently;

React test frontend running independently;

frontend-to-backend API proxy;

secure browser access through an SSH tunnel;

real MyZubster authenticated session;

MetaMask detected by the browser;

MetaMask account connection;

server-generated wallet challenge;

real personal_sign signature;

server-side wallet signature verification;

EVM wallet successfully linked to a MyZubster account.
Enter fullscreen mode Exit fullscreen mode

That last point is the first major milestone of the real wallet E2E flow.
What Still Needs To Be Tested

The full Marketplace payment lifecycle is not yet fully E2E validated.

The next test requires two distinct actors:

Buyer
Seller

and ideally two distinct MyZubster accounts with two distinct EVM wallets.

The remaining E2E sequence is:

Seller account
→ verify Seller MetaMask wallet
→ activate Seller
→ enable ETH acceptance
→ create ETH listing

Buyer account
→ verify Buyer MetaMask wallet
→ open Seller listing
→ sign Marketplace request

Seller
→ inspect Buyer wallet evidence
→ accept request

Buyer
→ receive ETH payment intent
→ switch MetaMask to Ethereum Sepolia
→ approve Sepolia transaction

Backend
→ detect transaction
→ verify sender
→ verify recipient
→ verify amount
→ verify successful receipt
→ wait for confirmations
→ mark order PAID

Seller
→ complete order

That is the next milestone.
Negative Tests Are Still Required

A payment system also needs to prove that invalid transactions are rejected.

The E2E suite still needs real negative-path tests for cases such as:

wrong Buyer wallet;

wrong network;

wrong recipient;

wrong payment amount;

failed transaction;

insufficient confirmations;

reused transaction hash;

transaction submitted before Seller acceptance;

Seller without a verified EVM wallet;

Seller not configured to accept ETH.
Enter fullscreen mode Exit fullscreen mode

These tests are as important as the successful payment path.
No Private Keys on the Server

A core property of the current architecture is that MyZubster never needs access to the MetaMask private key.

The browser wallet signs locally.

For ownership verification:

MetaMask → personal_sign

For payment:

MetaMask → eth_sendTransaction

The server only receives public information such as:

address
signature
transaction hash

and independently verifies them.

This keeps the system non-custodial.
Current Architecture

The current design can be summarized as:

            MyZubster Account
                   │
                   ▼
           Wallet Challenge
                   │
                   ▼
                MetaMask
                   │
            personal_sign
                   │
                   ▼
            Verified Wallet
                   │
                   ▼
          Marketplace Request
                   │
            signed off-chain
                   │
                   ▼
            Seller Acceptance
                   │
                   ▼
             Payment Intent
                   │
                   ▼
         Ethereum Sepolia TX
                   │
                   ▼
        Blockchain Verification
                   │
                   ▼
         CONFIRMING → PAID
                   │
                   ▼
               COMPLETED
Enter fullscreen mode Exit fullscreen mode

Why This Matters

The important result is not simply that “MetaMask connects.”

The useful result is that we now have several independent trust boundaries working together:

MyZubster authentication proves who the platform user is.

MetaMask signature proves who controls the wallet.

Marketplace request signatures prove which wallet approved a request.

The blockchain proves that a payment transaction occurred.

The MyZubster backend independently verifies whether that transaction satisfies the Marketplace payment intent.

That is much stronger than trusting a transaction hash supplied by the browser.
Next Milestone

The next development milestone is straightforward:

complete one real Buyer → Seller transaction using Sepolia test ETH and observe the order move from request creation all the way to PAID and COMPLETED.

After that, the same environment can be used to exercise the negative payment cases and strengthen the verifier before any mainnet discussion.

For now, the most important milestone is confirmed:

A real MyZubster account can authenticate, connect MetaMask, sign an off-chain wallet challenge, and have that EVM wallet independently verified and linked by the MyZubster backend.
Enter fullscreen mode Exit fullscreen mode

The wallet layer is working.

The next challenge is completing the entire Marketplace payment lifecycle.

Top comments (0)