DEV Community

Cover image for From Web2 to Web3: A Practical Guide to Building a Gasless Crypto Payment Flow (With Starknet & StarkZap)
Okoli Evans
Okoli Evans

Posted on

From Web2 to Web3: A Practical Guide to Building a Gasless Crypto Payment Flow (With Starknet & StarkZap)

A hands-on guide for React/Node developers to integrate wallets, social login, and USDC payments — without learning blockchain from scratch or writing many lines of code.


Why Most Web2 Developers Get Stuck trying to build on Web3

Most Web2 developers coming into Web3 hit the same wall — and usually with very little guidance.

You start with the docs, and immediately run into a wall of jargon: nonces, calldata, account abstraction, gas estimation. Before long, you’re three hours deep in a Stack Overflow rabbit hole wondering why you didn’t just use Stripe.

This guide is for developers who already know React, Node.js, or any backend stack — but haven’t really touched Web3 beyond reading about it or seeing monkey pictures on X.

By the end of this article, you’ll have built a complete Web3 payment flow:

  • Social login (email / Google)
  • Embedded wallets (no seed phrases)
  • Gasless transactions
  • On-chain USDC payments

And you’ll do it without needing to understand zero-knowledge proofs or low-level blockchain concepts.

Everything here comes from building Zapcode — a real QR-based USDC payment system on Starknet. These are production patterns, not toy examples.


What Is Starknet (And Why It Matters)

Starknet is a Layer 2 scaling network on Ethereum.

Here’s what matters in practice:

  • Transactions are fast
  • Fees are extremely low (fractions of a cent)
  • Security is still backed by Ethereum

Under the hood, Starknet batches transactions and proves them on Ethereum using zero-knowledge proofs. But you don’t need to think about that.

As a developer, you can treat it like:

“Ethereum — but more advanced and more scalable.”


What Is StarkZap?

StarkZap is an SDK that sits on top of Starknet and abstracts the hardest parts of Web3 development.

Instead of dealing with:

  • Raw calldata
  • Account deployment
  • Signing flows
  • Gas mechanics

You get simple APIs.

What StarkZap Gives You

  • Wallet creation — no seed phrases required
  • Account deployment — handled automatically
  • ERC20 transfers — send USDC with a clean API
  • Fee sponsorship — users pay zero gas via AVNU
  • Social login — email / Google login via Privy
  • Bitcoin support — via Starknet cross-chain infrastructure
  • Staking module — for DeFi-style apps

That last one — social login — is what changes everything.


Making Crypto Feel Like Web2: Social Login

The biggest UX problem in Web3 is wallet setup.

“Install MetaMask. Save these 12 words. Don’t lose them.”

Most users drop off right there.

Privy fixes this.

Users log in with email or Google, and a wallet is created for them behind the scenes. From their perspective, it feels like any normal app.

Here’s how we set it up:

// apps/frontend/src/main.tsx
import { PrivyProvider } from '@privy-io/react-auth'

<PrivyProvider
  appId={import.meta.env.VITE_PRIVY_APP_ID}
  config={{
    loginMethods: ['email', 'google'],
    appearance: { theme: 'dark' },
  }}
>
  <App />
</PrivyProvider>
Enter fullscreen mode Exit fullscreen mode

That’s it.


Backend Setup (Important Gotcha)

You need two Privy clients:

// apps/backend/src/lib/privy.js
import { PrivyClient } from '@privy-io/server-auth'
import PrivyNode from '@privy-io/node'

export const privy = new PrivyClient(
  process.env.PRIVY_APP_ID,
  process.env.PRIVY_APP_SECRET,
)

export const privyNode = new PrivyNode({
  appId:            process.env.PRIVY_APP_ID,
  appSecret:        process.env.PRIVY_APP_SECRET,
  authorizationKey: process.env.PRIVY_AUTHORIZATION_KEY,
})
Enter fullscreen mode Exit fullscreen mode

This distinction matters more than it looks:

  • server-auth → authentication
  • node → wallet operations & signing

If you mix them, things break in non-obvious ways.


Onboarding a User Wallet

When a user scans a QR code in Zapcode, we need to:

  1. Create a wallet
  2. Fund it (for deployment)
  3. Deploy it on-chain
  4. Make it usable

StarkZap handles most of this:

// apps/frontend/src/pages/PayPage.tsx
const sdk = new StarkZap({
  network: 'mainnet',
  paymaster: { nodeUrl: `${API_URL}/api/wallet/paymaster` },
})

const onboard = await sdk.onboard({
  strategy:      OnboardStrategy.Privy,
  accountPreset: accountPresets.argentXV050,
  deploy:        'if_needed',
  feeMode:       'user_pays',
  privy: {
    resolve: async () => {
      const token = await getAccessToken()
      const res   = await fetch(`${API_URL}/api/wallet/starknet`, {
        method:  'POST',
        headers: { Authorization: `Bearer ${token}` },
      })
      const { wallet: w } = await res.json()
      return {
        walletId:  w.id,
        publicKey: w.publicKey,
        serverUrl: `${API_URL}/api/wallet/sign`,
      }
    },
  },
})
Enter fullscreen mode Exit fullscreen mode

The key part:

deploy: 'if_needed'

First-time users get deployed. After that, it’s invisible.


The One Catch: Account Deployment Costs

AVNU sponsors transactions — but not account deployment.

New wallets must pay a small STRK fee.

How We Solved It

We use a treasury wallet:

const BUYER_PREFUND = BigInt('300000000000000000') // 0.3 STRK

await sendStrk(wallet.address, BUYER_PREFUND, 'buyer')
Enter fullscreen mode Exit fullscreen mode

This is a one-time cost per user.

After that → everything is gasless.


Sending a USDC Payment

Here’s the actual payment logic:

const tx = await walletRef.current.execute(
  [{
    contractAddress: USDC_MAINNET,
    entrypoint:      'transfer',
    calldata:        [
      merchant.walletAddress,
      String(Math.round(parsed * 1_000_000)),
      '0',
    ],
  }],
  { feeMode: 'sponsored' },
)
Enter fullscreen mode Exit fullscreen mode

From the user’s perspective:

Click → Pay → Done

No gas. No wallets. No confusion.


Gasless Transactions (How It Works)

AVNU’s paymaster covers gas fees:

router.post('/paymaster', async (req, res) => {
  const response = await fetch('https://starknet.paymaster.avnu.fi', {
    method:  'POST',
    headers: {
      'Content-Type':        'application/json',
      'x-paymaster-api-key': process.env.AVNU_API_KEY,
    },
    body: JSON.stringify(req.body),
  })
  const data = await response.json()
  res.status(response.status).json(data)
})
Enter fullscreen mode Exit fullscreen mode

Why This Matters

Users don’t need:

  • ETH
  • STRK
  • Any understanding of gas

This removes one of the biggest barriers in Web3 UX.


Server-Side Signing

router.post('/sign', async (req, res) => {
  const { walletId, hash } = req.body

  const result = await privyNode
    .wallets()
    .rawSign(walletId, { params: { hash } })

  res.json({ signature: result.signature })
})
Enter fullscreen mode Exit fullscreen mode

StarkZap handles calling this automatically.


Real-World Flow (Zapcode)

Here’s what the full system looks like:

  • Merchant signs up → gets wallet + QR code
  • Buyer scans → logs in with email
  • Wallet created + deployed automatically
  • Buyer enters amount → clicks Pay
  • USDC transfers instantly (gasless)

All without users knowing anything about crypto.


Common Pitfalls (Learned the Hard Way)

  • Starknet.js v9 changed Account constructor
  • You must use two Privy clients
  • Wallet ownership depends on your authorization key One way to avoid silent errors is to use the latest versions of the packages.

Final Thoughts: Web3 Is Finally Usable

You don’t need to understand zero-knowledge proofs to build on Starknet.

You don’t need to know what account abstraction means to ship a real product.

StarkZap handles the complexity — you focus on the experience.

If you’re a Web2 developer who’s been curious about Web3 but kept bouncing off the complexity wall:

This is your way in.

The tooling is ready.

The UX is finally good enough and getting better.

You can ship real applications now in just a few lines of code. Use Starkzap.


Resources

Zapcode Live: https://zapcodex.netlify.app/
Zapcode Github: https://github.com/OkoliEvans/zapcode

StarkZap: https://github.com/keep-starknet-strange/starkzap
StarkZap sample codebases and projects: https://github.com/keep-starknet-strange/awesome-starkzap

AVNU: https://portal.avnu.fi

Privy: https://privy.io


If you build something with StarkZap, drop it below.

I’d genuinely love to see what you ship.

Top comments (0)