NavenDocs
NavenDocs
Introduction
QuickstartHow x402 Payments WorkBuyer/Client GuideSeller/Server Guide
Back to Naven Network
Getting Started

Buyer/Client Guide

Send x402 payments to sellers with a TypeScript client.

Send payments to sellers.

Install

npm install @x402/core @x402/evm viem dotenv

Code

import "dotenv/config";

import { x402Client, x402HTTPClient } from "@x402/core/client";
import type { Network, PaymentRequired } from "@x402/core/types";
import { registerExactEvmScheme } from "@x402/evm/exact/client";
import { privateKeyToAccount } from "viem/accounts";

const endpoint = "https://api.naven.network/x402-test/ping";
const network = "eip155:4663" satisfies Network;

function normalizePrivateKey(privateKey: string): `0x${string}` {
  return privateKey.startsWith("0x")
    ? (privateKey as `0x${string}`)
    : `0x${privateKey}`;
}

function assertPaymentRequired(value: unknown): asserts value is PaymentRequired {
  if (
    !value ||
    typeof value !== "object" ||
    !("x402Version" in value) ||
    !("accepts" in value) ||
    !Array.isArray(value.accepts)
  ) {
    throw new Error("Response did not contain a valid x402 payment challenge");
  }
}

async function main() {
  const privateKey = process.env.X402_PRIVATE_KEY;

  if (!privateKey) {
    throw new Error("Set X402_PRIVATE_KEY before running");
  }

  const account = privateKeyToAccount(normalizePrivateKey(privateKey));
  const client = new x402Client();

  registerExactEvmScheme(client, {
    signer: account,
    networks: [network],
  });

  const httpClient = new x402HTTPClient(client);
  const challengeResponse = await fetch(endpoint);
  const challenge = await challengeResponse.json();

  if (challengeResponse.status !== 402) {
    throw new Error(`Expected 402 challenge, got ${challengeResponse.status}`);
  }

  assertPaymentRequired(challenge);

  const paymentPayload = await httpClient.createPaymentPayload(challenge);
  const paymentHeaders = httpClient.encodePaymentSignatureHeader(paymentPayload);
  const paidResponse = await fetch(endpoint, {
    headers: {
      ...paymentHeaders,
      "Access-Control-Expose-Headers": "PAYMENT-RESPONSE, X-PAYMENT-RESPONSE",
    },
  });
  const body = await paidResponse.json();
  const paymentResult = httpClient.parsePaymentResult({
    status: paidResponse.status,
    getHeader: name => paidResponse.headers.get(name),
    body,
  });

  console.log({
    status: paidResponse.status,
    paymentStatus: paymentResult.paymentStatus,
    paymentHeader: paymentResult.header,
    body,
  });
}

main().catch(error => {
  console.error(error);
  process.exit(1);
});

How x402 Payments Work

Understand what happens when Naven asks your wallet to pay for a request.

Seller/Server Guide

Accept x402 payments in a Hono server.

On this page

InstallCode