Documentation Index: Fetch llms.txt first to discover every published page. This page is also available as Markdown at /go-sdk-development.md.
Verified · 8/11/2026

Go SDK Testing and Development

Run the Go SDK's local test suite, shared cross-language compatibility fixtures, and formatting/build checks, either from sdk-go directly or via the root Makefile.

Running the test suite locally#

From the sdk-go directory, run the full package test suite:

cd sdk-go
go test ./...

This runs everything, including the x402 signing tests in x402_test.go (nonce derivation, validity-window computation, PrivateKeySigner round-trips, and the mock-server X402Client tests).

Running the shared cross-SDK compatibility fixtures#

TestSharedCompatibilityFixtures runs the fixtures in test-fixtures/ that assert Go's webhook signature verification, auth classification, sender trust, and schema validation behavior match the Node and Python SDKs byte-for-byte. Run it in isolation:

cd sdk-go
go test -run TestSharedCompatibilityFixtures ./...

If this test fails after you change webhook parsing, signing, or trust logic, the fix is almost always to bring Go's behavior back in line with the other two SDKs rather than to edit the fixture. The shared fixture contract, and when it's correct to update the fixtures themselves, is documented in Monorepo Structure and Release Process.

gofmt diff / formatting check fails#

gofmt enforces canonical formatting across the package. If CI or make go-check reports a formatting diff, apply it directly:

cd sdk-go
gofmt -w .

Re-run go test ./... afterward; gofmt -w only rewrites whitespace and layout, it never changes behavior, so a passing test suite before the fix should still pass after.

Running checks from the monorepo root instead#

Every one of the commands above has a root-level equivalent that wraps the same underlying tooling. Prefer these when you're touching more than just sdk-go, since they're what CI runs:

make go-generate   # regenerate the embedded webhook schema + sdk-go/api client from openapi/primitive-api.yaml
make go-check       # go test ./... + go test -run TestSharedCompatibilityFixtures ./... + gofmt check
make go-build       # verify the module builds

Run make go-generate after any change to openapi/primitive-api.yaml or json-schema/email-received-event.schema.json, per the regeneration workflow in Regenerating SDK Code from the OpenAPI Spec. Committing regenerated Go output without also regenerating Node and Python leaves the three SDKs out of sync with the shared contract.

Normative nonce vector mismatch in x402 tests#

x402_test.go locks EIP-3009 nonce derivation to a normative test vector (normativeNonce = "0xc955a08812ab83f9e25c92e5162267b913957c3cc8678de1cf1449f77b516c6e"), computed from a fixed NonceBinding (canonicalInteractionID, canonicalChallengeStepID, canonicalChallengeNonce). TestDeriveEIP3009Nonce_NormativeVector fails if DeriveEIP3009Nonce's byte layout changes even slightly, for example a swapped separator or a different case-folding rule for interactionId/challengeStepId.

This test failing is a hard stop, not something to patch around by updating the expected constant: the platform verifier recomputes the same nonce independently, and a Go-side layout change that isn't mirrored server-side makes every real payment fail signature verification. If you need to change nonce derivation, coordinate the change with the platform and the Node/Python SDKs' equivalent normative vectors first.

Address / signature round-trip test failures#

TestPrivateKeySigner_Address, TestPrivateKeySigner_PersonalSignRoundTrip, and TestPrivateKeySigner_EIP712RoundTrip all derive from the same fixed test key (testPrivateKey) and expect it to recover to testAddress. A failure here almost always means a change to PrivateKeySigner.SignTypedData or SignMessage's recovery-id normalization (the v ∈ {27, 28} adjustment), not a key or address typo. Check that the signature's last byte is still normalized to Ethereum's canonical recovery id before comparing against go-ethereum's recovery output.

Validity window errors: "authorization window too wide" / "about to expire"#

ComputePaymentValidityWindow enforces a band on validBefore: at least DefaultMinSettlementHeadroomSec (60s) past now, and at most DefaultMaxWindowSec (24h) past validAfter. By default (Clamp nil or true) an out-of-band window is silently clamped into the band, so you won't see either error unless you explicitly pin ValidBeforeSec/ValidAfterSec with Clamp: false.

If your own test or code hits one of these errors:

  • "is below the minimum settlement headroom": your pinned ValidBeforeSec is too close to now. Either drop the pin and let the default derivation (ChallengeExpiresAtSec + SettlementMarginSec) compute it, or move the pin further out.
  • "the authorization window is too wide": your pinned ValidBeforeSec exceeds ValidAfterSec + MaxWindowSec. Either drop the pin or set Clamp back to its default so the SDK lands it inside the cap for you.

See x402 Signing Primitives for the full parameter reference.

Test-only HTTP server assertions failing (X402Client tests)#

The TestX402Client_* tests spin up an httptest.Server and assert on the exact request path, method, and body the client sends (for example /v1/x402/challenges/{id}/pay, or the authorization: Bearer k header). If these fail after a client change, diff the actual captured request against the assertion rather than adjusting the assertion: these tests exist specifically to catch wire-format drift between X402Client and the platform's expected request shape, mirroring the Node SDK's x402 client byte-for-byte.

Was this page helpful?

© Primitive SDKs

Powered by Browzer