Skip to content

Latest commit

 

History

History
154 lines (111 loc) · 4.52 KB

File metadata and controls

154 lines (111 loc) · 4.52 KB

@microai/paygate-sdk

Local TypeScript SDK for the current MicroAI Paygate x402-style protocol.

The SDK handles the existing gateway flow:

  1. Send an unsigned request.
  2. Read the 402 Payment Required paymentContext.
  3. Sign the payment context with EIP-712.
  4. Retry with the signed X-402-* headers (v2 also includes the recovered X-402-Payer).
  5. Decode the X-402-Receipt response header.
  6. Verify the signed receipt locally.

This package is private and local for now. It is not published to npm.

Protocol Status

MicroAI Paygate currently uses a custom x402-style wire contract. It is not official x402-compatible yet because it uses custom X-402-* headers and does not perform facilitator-backed or on-chain USDC settlement.

A valid EIP-712 signature proves wallet authorization for the payment context. It does not prove that USDC moved on-chain.

The SDK accepts the current legacy context and the staged request-bound v2 context. For v2 it verifies the audience, method, encoded path and raw query, content type, and SHA-256 hash of the exact serialized body before opening the wallet signature prompt. The public gateway remains on v1 until the separate cutover change is deployed.

Install And Test

cd sdk/typescript
bun install
bun run test

Run the type checker:

bun run typecheck

Usage

import { ethers } from "ethers";
import { PaygateClient } from "@microai/paygate-sdk";

const client = new PaygateClient({
  gatewayUrl: "http://localhost:3000",
  signer: new ethers.Wallet(process.env.EVM_PRIVATE_KEY!),
  trustedServerPublicKey: process.env.PAYGATE_SERVER_PUBLIC_KEY,
});

const response = await client.summarize("Text to summarize");

console.log(response.data.result);
console.log(response.receipt?.receipt.id);
console.log(response.receiptVerified);

Generic endpoint usage:

const response = await client.request<{ text: string }, { result: string }>({
  method: "POST",
  path: "/api/ai/summarize",
  body: { text: "..." },
});

Example

Set environment variables:

PAYGATE_GATEWAY_URL=http://localhost:3000
EVM_PRIVATE_KEY=0x...
PAYGATE_SERVER_PUBLIC_KEY=0x...

Use only unfunded local or test wallets. Never use a funded wallet, seed phrase, production key, or real customer wallet in examples.

PAYGATE_SERVER_PUBLIC_KEY should be the gateway receipt signing public key distributed out of band. Without it, the SDK can decode receipts and verify request/response hash binding, but it returns receiptVerified: false instead of trusting the self-declared key inside the receipt.

Run:

cd sdk/typescript
bun run examples/summarize.ts "Text to summarize"

Receipt Verification Example

Receipt verification with a trusted public key (replace the placeholder with the gateway's real public key):

import { ethers } from "ethers";
import { PaygateClient, PaygateSdkError } from "@microai/paygate-sdk";

async function main(): Promise<void> {
  const client = new PaygateClient({
    gatewayUrl: process.env.PAYGATE_GATEWAY_URL ?? "http://localhost:3000",
    signer: new ethers.Wallet(process.env.EVM_PRIVATE_KEY!),
    trustedServerPublicKey: process.env.PAYGATE_SERVER_PUBLIC_KEY ?? "0xYOUR_GATEWAY_PUBLIC_KEY",
  });

  try {
    const response = await client.summarize("Text to summarize");

    if (!response.receipt) {
      console.warn("No receipt returned; treat the response as untrusted.");
      return;
    }

    if (!response.receiptVerified) {
      console.warn("Receipt was present but did not verify; discard the response.");
      return;
    }

    console.log("Verified receipt ID:", response.receipt.receipt.id);
    console.log("Summary:", response.data.result);
  } catch (error) {
    if (
      error instanceof PaygateSdkError &&
      (error.code === "receipt_verification_failed" || error.code === "receipt_decode_failed")
    ) {
      console.error("Receipt verification failed; treat the response as untrusted.");
      return;
    }
    throw error;
  }
}

await main();

Run the receipt verification example:

cd sdk/typescript
bun run examples/verify-receipt.ts "Text to summarize"

Optional Live Test

The live SDK test is skipped by default. Start the local stack first:

bun run stack

Then run:

PAYGATE_SDK_LIVE_TEST=1 EVM_PRIVATE_KEY=0x... PAYGATE_SERVER_PUBLIC_KEY=0x... PAYGATE_GATEWAY_URL=http://localhost:3000 bun test src/__tests__/live-gateway.test.ts

The live path depends on the gateway's configured AI provider. With the default OpenRouter provider, the gateway still needs OPENROUTER_API_KEY.