Skip to content
LogoLogo

Server

Protect endpoints with payment requirements

Create a payment handler with server.New() and use ChargeMiddleware or call Charge() directly. The charge.NewMethod factory configures Currency and Recipient once, then every charge uses those defaults.

Quick start

server.go
import (
	"github.com/tempoxyz/mpp-go/pkg/server"
	charge "github.com/tempoxyz/mpp-go/pkg/tempo/server"
)
 
intent, _ := charge.NewIntent(charge.IntentConfig{
	RPCURL: "https://rpc.tempo.xyz",
})
method := charge.NewMethod(charge.MethodConfig{
	Intent:    intent,
	Recipient: "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266",
})
payment := server.New(method, "api.example.com", "my-server-secret")
 
result, err := payment.Charge(ctx, server.ChargeParams{
	Authorization: r.Header.Get("Authorization"),
	Amount:        "0.50",
})
 
if result.IsChallenge() {
	server.WriteChallenge(w, result.Challenge, payment.Realm())
	return
}
// result.Receipt is the verified Receipt

Framework middleware

net/http

Use server.ChargeMiddleware to wrap any http.Handler:

mux := http.NewServeMux()
mux.Handle("/resource", server.ChargeMiddleware(payment, server.ChargeParams{
	Amount:      "0.50",
	Description: "Paid resource",
})(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
	credential := server.CredentialFromContext(r.Context())
	json.NewEncoder(w).Encode(map[string]any{
		"data":  "paid content",
		"payer": credential.Source,
	})
})))

Gin

Use ginadapter.ChargeMiddleware from pkg/server/gin:

import ginadapter "github.com/tempoxyz/mpp-go/pkg/server/gin"
 
r := gin.Default()
r.GET("/resource", ginadapter.ChargeMiddleware(payment, server.ChargeParams{
	Amount: "0.50",
}), func(c *gin.Context) {
	credential := server.CredentialFromContext(c.Request.Context())
	c.JSON(200, gin.H{"payer": credential.Source})
})

Echo

Use echoadapter.ChargeMiddleware from pkg/server/echo:

import echoadapter "github.com/tempoxyz/mpp-go/pkg/server/echo"
 
e := echo.New()
e.GET("/resource", func(c echo.Context) error {
	credential := server.CredentialFromContext(c.Request().Context())
	return c.JSON(200, map[string]any{"payer": credential.Source})
}, echoadapter.ChargeMiddleware(payment, server.ChargeParams{
	Amount: "0.50",
}))

Chi

Use server.ChargeMiddleware with chi.With:

r := chi.NewRouter()
r.With(server.ChargeMiddleware(payment, server.ChargeParams{
	Amount: "0.50",
})).Get("/resource", func(w http.ResponseWriter, r *http.Request) {
	credential := server.CredentialFromContext(r.Context())
	json.NewEncoder(w).Encode(map[string]any{"payer": credential.Source})
})

MethodConfig parameters

ChainID (optional)

  • Type: int64

Explicitly bind issued Challenges to a specific chain. If omitted, mpp-go infers it from IntentConfig.RPCURL when it matches a known Tempo RPC endpoint.

Currency (optional)

  • Type: string
  • Default: USDC.e on mainnet, pathUSD on testnet

TIP-20 token address for charges.

Decimals (optional)

  • Type: int
  • Default: 6

Token decimal places for dollar-to-base-unit conversion.

FeePayer (optional)

  • Type: bool
  • Default: false

Enable fee sponsorship for all Challenges. When enabled, the server co-signs and sponsors transaction gas fees.

FeePayerURL (optional)

  • Type: string

URL of a remote co-signer when the server does not sign locally.

Intent

  • Type: *charge.Intent

Intent instance created by charge.NewIntent.

Memo (optional)

  • Type: string

Default memo attached to Challenges.

Recipient (optional)

  • Type: string

Default recipient address for charges.

SupportedModes (optional)

  • Type: []tempo.ChargeMode

Supported Credential submission modes (for example, pull, push).

IntentConfig parameters

FeePayerPrivateKey (optional)

  • Type: string

Hex-encoded private key for fee sponsorship. The server co-signs and sponsors transaction gas fees.

FeePayerSigner (optional)

  • Type: *temposigner.Signer

Custom signer for fee sponsorship. Takes precedence over FeePayerPrivateKey.

RPC (optional)

  • Type: tempo.RPCClient

Custom RPC client instance. Takes precedence over RPCURL.

RPCURL (optional)

  • Type: string
  • Default: "https://rpc.tempo.xyz"

Tempo RPC endpoint URL.

Store (optional)

  • Type: tempo.Store

Replay-protection store for hash and proof Credentials. Defaults to an in-memory store.

ChargeParams parameters

Amount

  • Type: string

Payment amount in dollars (for example, "0.50" for $0.50). Automatically converted to base units using the configured decimals.

Authorization (optional)

  • Type: string

The Authorization header value from the incoming request.

ChainID (optional)

  • Type: int64

Override the method's default chain ID for this charge.

Currency (optional)

  • Type: string

Override the method's default currency address.

Description (optional)

  • Type: string

Human-readable description attached to the Challenge.

Expires (optional)

  • Type: string

Challenge expiration as ISO 8601 timestamp. Defaults to 5 minutes from now.

ExternalID (optional)

  • Type: string

Merchant reference ID for reconciliation.

FeePayer (optional)

  • Type: bool

Override the method's default fee sponsorship setting for this charge.

FeePayerURL (optional)

  • Type: string

Override the method's default fee payer URL for this charge.

Memo (optional)

  • Type: string

Memo attached to this Challenge.

Meta (optional)

  • Type: map[string]string

Arbitrary metadata attached to the Challenge.

Recipient (optional)

  • Type: string

Override the method's default recipient address.

Splits (optional)

  • Type: []tempo.SplitParams

Split the payment across multiple recipients.

SupportedModes (optional)

  • Type: []tempo.ChargeMode

Override supported submission modes for this charge.

Fee sponsorship

Sponsor gas fees so clients do not need native tokens. Pass FeePayerPrivateKey in the IntentConfig:

intent, _ := charge.NewIntent(charge.IntentConfig{
	RPCURL:             "https://rpc.tempo.xyz",
	FeePayerPrivateKey: os.Getenv("FEE_PAYER_KEY"),
})
method := charge.NewMethod(charge.MethodConfig{
	Intent:    intent,
	Recipient: "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266",
})

When fee sponsorship is enabled, the server co-signs transactions and covers gas fees on behalf of the client.

Context helpers

FunctionDescription
CredentialFromContext(ctx)Extract the verified Credential from request context
ReceiptFromContext(ctx)Extract the verified Receipt from request context
ContextWithPayment(ctx, credential, receipt)Store payment data in context

Key types

TypeDescription
ChargeParamsParameters for a single charge
IntentConfigConfiguration for charge.NewIntent
MethodConfigConfiguration for charge.NewMethod
MppServer handler binding method, realm, and secret
ChargeResultCharge result containing either a Challenge or a Receipt
SplitParamsPayment split recipient and amount