Wallet Auth

Normalize Gwop auth into app-owned primitives

View as Markdown

Keep the Gwop auth lifecycle in a thin adapter instead of calling the SDK directly from routes. That keeps your API surface app-shaped while still making the upstream flow obvious.

The lifecycle

  1. Create the auth intent.
  2. Hand the returned payment URLs to the agent.
  3. Exchange the settled intent for a bearer token.
  4. Use sid for live session lookup or revocation.

Create an auth challenge

1import { randomUUID } from "node:crypto";
2
3const { result: intent } = await gwop.authIntents.create(
4 {
5 idempotencyKey: randomUUID(),
6 body: {
7 metadata: {
8 source: "docs-example",
9 },
10 },
11 },
12 identityRequestOptions,
13);
14
15console.log(intent.authIntentId);
16console.log(intent.challenge.paymentMethods);

Each returned paymentUrl is a payable x402 challenge. The wallet proves control by settling that dust invoice.

Exchange for a bearer token

1const { result: token } = await gwop.authIntents.exchange(
2 {
3 authIntentId: intent.authIntentId,
4 idempotencyKey: randomUUID(),
5 },
6 identityRequestOptions,
7);
8
9console.log(token.accessToken);
10console.log(token.principal.sub);
11console.log(token.session.sid);
12console.log(token.account.isNewAccount);

Carry four things forward from the exchange response:

  • accessToken for authenticated requests
  • principal.sub as the durable wallet identity
  • session.sid as the revocable session handle
  • account.isNewAccount to shape signup versus repeat-login UX

Why the adapter matters

The adapter converts Gwop responses into app primitives and keeps upstream details like chain normalization, session status mapping, and logging out of route handlers.