Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 35 additions & 0 deletions examples/go/clients/builder-codes/go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
module github.com/x402-foundation/x402/examples/go/clients/builder-codes

go 1.25.4

replace github.com/x402-foundation/x402/go => ../../../../go

require (
github.com/joho/godotenv v1.5.1
github.com/x402-foundation/x402/go v0.0.0-00010101000000-000000000000
)

require (
github.com/Microsoft/go-winio v0.6.2 // indirect
github.com/ProjectZKM/Ziren/crates/go-runtime/zkvm_runtime v0.0.0-20251001021608-1fe7b43fc4d6 // indirect
github.com/StackExchange/wmi v1.2.1 // indirect
github.com/bits-and-blooms/bitset v1.20.0 // indirect
github.com/consensys/gnark-crypto v0.18.0 // indirect
github.com/crate-crypto/go-eth-kzg v1.4.0 // indirect
github.com/crate-crypto/go-ipa v0.0.0-20240724233137-53bbb0ceb27a // indirect
github.com/deckarep/golang-set/v2 v2.6.0 // indirect
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 // indirect
github.com/ethereum/c-kzg-4844/v2 v2.1.5 // indirect
github.com/ethereum/go-ethereum v1.16.7 // indirect
github.com/ethereum/go-verkle v0.2.2 // indirect
github.com/go-ole/go-ole v1.3.0 // indirect
github.com/gorilla/websocket v1.4.2 // indirect
github.com/holiman/uint256 v1.3.2 // indirect
github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible // indirect
github.com/supranational/blst v0.3.16-0.20250831170142-f48500c1fdbe // indirect
github.com/tklauser/go-sysconf v0.3.12 // indirect
github.com/tklauser/numcpus v0.6.1 // indirect
golang.org/x/crypto v0.46.0 // indirect
golang.org/x/sync v0.19.0 // indirect
golang.org/x/sys v0.39.0 // indirect
)
197 changes: 197 additions & 0 deletions examples/go/clients/builder-codes/go.sum

Large diffs are not rendered by default.

101 changes: 101 additions & 0 deletions examples/go/clients/builder-codes/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
package main

import (
"bytes"
"encoding/base64"
"encoding/json"
"fmt"
"io"
"net/http"
"os"

"github.com/joho/godotenv"
x402 "github.com/x402-foundation/x402/go"
x402http "github.com/x402-foundation/x402/go/http"
evm "github.com/x402-foundation/x402/go/mechanisms/evm/exact/client"
evmsigners "github.com/x402-foundation/x402/go/signers/evm"
)

// peek is a logging RoundTripper that prints the buildercode extension data
// flowing in both directions: the codes the server declared in its 402, and
// the codes the SDK forwarded back in the X-Payment header.
type peek struct{ inner http.RoundTripper }

func (p *peek) RoundTrip(req *http.Request) (*http.Response, error) {
if h := req.Header.Get("X-Payment"); h != "" {
if raw, err := base64.StdEncoding.DecodeString(h); err == nil {
var payload map[string]any
if json.Unmarshal(raw, &payload) == nil {
if ext, ok := payload["extensions"]; ok {
b, _ := json.MarshalIndent(ext, "", " ")
fmt.Printf("➡️ payload.extensions sent:\n%s\n", b)
}
}
}
}

resp, err := p.inner.RoundTrip(req)
if err != nil {
return resp, err
}

// Server returns 402 with PaymentRequired in the Payment-Required header,
// not the body. Decode and log the extensions so we can confirm what the
// server declared.
if resp.StatusCode == http.StatusPaymentRequired {
if hdr := resp.Header.Get("Payment-Required"); hdr != "" {
if raw, err := base64.StdEncoding.DecodeString(hdr); err == nil {
var pr map[string]any
if json.Unmarshal(raw, &pr) == nil {
if ext, ok := pr["extensions"]; ok {
b, _ := json.MarshalIndent(ext, "", " ")
fmt.Printf("⬅️ 402 extensions:\n%s\n", b)
}
}
}
}
// Restore body in case downstream wants to read it
body, _ := io.ReadAll(resp.Body)
resp.Body = io.NopCloser(bytes.NewReader(body))
}
return resp, nil
}

func main() {
_ = godotenv.Load()

priv := os.Getenv("EVM_PRIVATE_KEY_CLIENT")
url := os.Getenv("SERVER_URL")
if priv == "" || url == "" {
fmt.Println("EVM_PRIVATE_KEY_CLIENT and SERVER_URL required")
os.Exit(1)
}

signer, err := evmsigners.NewClientSignerFromPrivateKey(priv)
if err != nil {
fmt.Printf("signer: %v\n", err)
os.Exit(1)
}

x402Client := x402.Newx402Client()
x402Client.Register("eip155:*", evm.NewExactEvmScheme(signer, nil))

httpInner := &http.Client{Transport: &peek{inner: http.DefaultTransport}}
wrapped := x402http.WrapHTTPClientWithPayment(httpInner, x402http.Newx402HTTPClient(x402Client))

resp, err := wrapped.Get(url)
if err != nil {
fmt.Printf("request: %v\n", err)
os.Exit(1)
}
defer resp.Body.Close()

body, _ := io.ReadAll(resp.Body)
fmt.Printf("\n✅ %s\n%s\n", resp.Status, body)

if pr := resp.Header.Get("PAYMENT-RESPONSE"); pr != "" {
if raw, err := base64.StdEncoding.DecodeString(pr); err == nil {
fmt.Printf("\n💰 settlement: %s\n", raw)
}
}
}
68 changes: 68 additions & 0 deletions examples/go/facilitator/builder-codes/go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
module github.com/x402-foundation/x402/examples/go/facilitator/builder-codes

go 1.25.4

replace github.com/x402-foundation/x402/go => ../../../../go

require (
github.com/ethereum/go-ethereum v1.17.3
github.com/gin-gonic/gin v1.11.0
github.com/joho/godotenv v1.5.1
github.com/x402-foundation/x402/go v0.0.0-00010101000000-000000000000
)

require (
github.com/Microsoft/go-winio v0.6.2 // indirect
github.com/ProjectZKM/Ziren/crates/go-runtime/zkvm_runtime v0.0.0-20251001021608-1fe7b43fc4d6 // indirect
github.com/StackExchange/wmi v1.2.1 // indirect
github.com/bits-and-blooms/bitset v1.20.0 // indirect
github.com/bytedance/sonic v1.14.0 // indirect
github.com/bytedance/sonic/loader v0.3.0 // indirect
github.com/cespare/xxhash/v2 v2.3.0 // indirect
github.com/cloudwego/base64x v0.1.6 // indirect
github.com/consensys/gnark-crypto v0.18.1 // indirect
github.com/crate-crypto/go-eth-kzg v1.5.0 // indirect
github.com/deckarep/golang-set/v2 v2.6.0 // indirect
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 // indirect
github.com/ethereum/c-kzg-4844/v2 v2.1.6 // indirect
github.com/gabriel-vasile/mimetype v1.4.8 // indirect
github.com/gin-contrib/sse v1.1.0 // indirect
github.com/go-logr/logr v1.4.3 // indirect
github.com/go-logr/stdr v1.2.2 // indirect
github.com/go-ole/go-ole v1.3.0 // indirect
github.com/go-playground/locales v0.14.1 // indirect
github.com/go-playground/universal-translator v0.18.1 // indirect
github.com/go-playground/validator/v10 v10.27.0 // indirect
github.com/goccy/go-json v0.10.4 // indirect
github.com/goccy/go-yaml v1.18.0 // indirect
github.com/gorilla/websocket v1.4.2 // indirect
github.com/holiman/uint256 v1.3.2 // indirect
github.com/json-iterator/go v1.1.12 // indirect
github.com/klauspost/cpuid/v2 v2.3.0 // indirect
github.com/leodido/go-urn v1.4.0 // indirect
github.com/mattn/go-isatty v0.0.20 // indirect
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/pelletier/go-toml/v2 v2.2.4 // indirect
github.com/quic-go/qpack v0.5.1 // indirect
github.com/quic-go/quic-go v0.55.0 // indirect
github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible // indirect
github.com/supranational/blst v0.3.16 // indirect
github.com/tklauser/go-sysconf v0.3.12 // indirect
github.com/tklauser/numcpus v0.6.1 // indirect
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
github.com/ugorji/go/codec v1.3.0 // indirect
go.opentelemetry.io/auto/sdk v1.2.1 // indirect
go.opentelemetry.io/otel v1.40.0 // indirect
go.opentelemetry.io/otel/metric v1.40.0 // indirect
go.opentelemetry.io/otel/trace v1.40.0 // indirect
golang.org/x/arch v0.20.0 // indirect
golang.org/x/crypto v0.47.0 // indirect
golang.org/x/mod v0.31.0 // indirect
golang.org/x/net v0.49.0 // indirect
golang.org/x/sync v0.19.0 // indirect
golang.org/x/sys v0.40.0 // indirect
golang.org/x/text v0.33.0 // indirect
golang.org/x/tools v0.40.0 // indirect
google.golang.org/protobuf v1.36.11 // indirect
)
Loading
Loading