Help us shape the future of Go! Take the 2026 Go Developer Survey

chargeserver

package
v0.6.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 26, 2026 License: MIT, Apache-2.0, MIT Imports: 27 Imported by: 0

Documentation

Overview

Package chargeserver contains the Tempo charge server method and verifier. It is usually imported as charge alongside the generic HTTP 402 flow in package server. Construct a method with New.

Package chargeserver verifies Tempo charge Credentials and builds Tempo charge Challenges for MPP HTTP servers.

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Config

type Config struct {
	// Intent verifies Tempo charge credentials for this method. When nil, New
	// builds one from the verification fields below. It cannot be combined
	// with Relay.
	Intent *Intent
	// Currencies lists the accepted token contract addresses in presentation
	// order. The server issues one charge Challenge per currency, and a
	// Credential for any of them verifies. An explicit list replaces the chain
	// defaults from tempo.DefaultCurrenciesForChain; it must contain at least
	// one valid 0x-prefixed address, and case-insensitive duplicates are
	// dropped.
	Currencies []string
	// Recipient is the default payee address for issued challenges.
	Recipient string
	// Decimals controls how human-readable amounts are normalized.
	Decimals int
	// ChainID binds issued challenges to a specific Tempo chain when set, such
	// as tempo.ChainIDMainnet or tempo.ChainIDModerato.
	ChainID int64
	// FeePayer enables sponsored transaction flows by default.
	FeePayer bool
	// FeePayerURL points at a remote co-signer when the server does not sign locally.
	FeePayerURL string
	// SupportedModes limits the credential submission modes advertised to clients.
	SupportedModes []tempo.ChargeMode
	// RPC overrides the Tempo JSON-RPC client used for verification.
	RPC tempo.RPCClient
	// RPCURL is used to build an RPC client when RPC is nil.
	RPCURL string
	// FeePayerSigner co-signs sponsored transactions locally when provided.
	FeePayerSigner *temposigner.Signer
	// FeePayerPrivateKey constructs FeePayerSigner when FeePayerSigner is nil.
	FeePayerPrivateKey string
	// AllowedFeeTokens lists the fee tokens this verifier will sponsor; see
	// IntentConfig.AllowedFeeTokens.
	AllowedFeeTokens []string
	// FeePayerPolicy sets the sponsorship limits for every allowed fee token;
	// see IntentConfig.FeePayerPolicy.
	FeePayerPolicy *FeePayerPolicy
	// FeeToken fixes the fee token a local fee payer pays gas in; see IntentConfig.FeeToken.
	FeeToken string
	// Store is required to verify payments. Use a persistent store shared by all
	// replicas, with atomic PutIfAbsent and no eviction of replay keys.
	// An explicit tempo.NewMemoryStore() is only suitable for single-process development.
	Store tempo.Store
	// ExpireReplayKeys lets replay keys expire after their challenge; see
	// IntentConfig.ExpireReplayKeys for when that is safe.
	ExpireReplayKeys bool
	// Relay delegates credential validation and finalization to Tempo API or
	// a compatible MPP relay. It cannot be combined with Intent.
	Relay *RelayConfig
}

Config combines the method defaults and intent verification settings used by New, the Tempo server constructor.

type FeePayerPolicy

type FeePayerPolicy struct {
	MaxFeePerGas         *big.Int
	MaxPriorityFeePerGas *big.Int
	MaxTotalFee          *big.Int
	// RejectKeyAuthorization rejects sponsored transactions that install a new
	// access key (carry a keyAuthorization). The default allows them.
	RejectKeyAuthorization bool
}

FeePayerPolicy configures sponsored transaction limits for one TIP-20 fee token.

type Intent

type Intent struct {
	// contains filtered or unexported fields
}

Intent verifies Tempo charge Credentials and returns Receipts.

func NewIntent

func NewIntent(config IntentConfig) (*Intent, error)

NewIntent constructs a Tempo charge verifier.

func (*Intent) Broadcast added in v0.4.0

func (i *Intent) Broadcast(
	ctx context.Context,
	credential *mpp.Credential,
	requestMap map[string]any,
) (*mpp.Receipt, error)

Broadcast revalidates and settles a Tempo charge Credential.

func (*Intent) Name

func (i *Intent) Name() string

Name returns the intent token handled by this verifier.

func (*Intent) Validate added in v0.4.0

func (i *Intent) Validate(
	ctx context.Context,
	credential *mpp.Credential,
	requestMap map[string]any,
) (*mppserver.Validation, error)

Validate checks a Tempo charge Credential without consuming replay state, signing a sponsored transaction, or broadcasting.

func (*Intent) Verify

func (i *Intent) Verify(
	ctx context.Context,
	credential *mpp.Credential,
	requestMap map[string]any,
) (*mpp.Receipt, error)

Verify is the backwards-compatible combined validation and broadcast path.

type IntentConfig

type IntentConfig struct {
	// RPC overrides the Tempo JSON-RPC client used for verification.
	RPC tempo.RPCClient
	// RPCURL is used to build an RPC client when RPC is nil.
	RPCURL string
	// FeePayerSigner co-signs sponsored transactions locally when provided.
	FeePayerSigner *temposigner.Signer
	// FeePayerPrivateKey constructs FeePayerSigner when FeePayerSigner is nil.
	FeePayerPrivateKey string
	// AllowedFeeTokens lists the fee tokens this verifier will sponsor, as in
	// mppx. With a local fee payer, they are the fee tokens it may pay gas in,
	// tried in this order and independent of the charge currency. Remote fee
	// payers (FeePayerURL) pay in the charge currency, which must be listed.
	// When nil, the verifier sponsors pathUSD, AlphaUSD and USDC.e, and a
	// local fee payer pays in pathUSD or, on mainnet, USDC.e. A non-nil list
	// must name at least one valid address.
	AllowedFeeTokens []string
	// FeePayerPolicy sets the sponsorship limits applied to every allowed fee
	// token, as mppx's feePayerPolicy does. Nil fields keep the defaults
	// (100 gwei max fee and priority fee per gas, 0.05 total fee); a nil
	// MaxPriorityFeePerGas is lowered to a MaxFeePerGas set below its default.
	FeePayerPolicy *FeePayerPolicy
	// FeeToken fixes the fee token a local fee payer pays gas in. When empty,
	// the local fee payer uses the first allowed fee token it holds a balance
	// of, or the first allowed fee token. It must be an allowed fee token (New
	// and NewIntent reject one missing from AllowedFeeTokens) and is ignored
	// for remote fee payers (FeePayerURL).
	FeeToken string
	// Store is required to verify payments. Use a persistent store shared by all
	// replicas, with atomic PutIfAbsent and no eviction of replay keys.
	// An explicit tempo.NewMemoryStore() is only suitable for single-process development.
	Store tempo.Store
	// ExpireReplayKeys lets replay keys expire ten minutes after their
	// challenge's expiry instead of keeping them forever. Store must implement
	// tempo.ExpiringStore, whose PutIfAbsentUntil then replaces PutIfAbsent
	// for replay claims. It is only safe when every credential reaches this
	// Intent through server.Mpp, which verifies the challenge ID's HMAC,
	// including its expiry, before settlement: Verify and Broadcast called
	// directly trust the credential's echoed expiry, so an expired key would
	// let the same hash, proof or transaction settle again.
	ExpireReplayKeys bool
}

IntentConfig configures Tempo charge verification.

type Method

type Method struct {
	// contains filtered or unexported fields
}

Method adapts Tempo charge configuration to the generic server interfaces.

func New added in v0.6.0

func New(config Config) (*Method, error)

New constructs a Tempo charge method from one config struct. It returns an error when the configuration is invalid: a missing replay Store (without Relay), an invalid currency or fee-payer configuration, or Intent combined with Relay.

Without Currencies, the method accepts tempo.DefaultCurrenciesForChain for the configured chain, or for the chain inferred from RPCURL when ChainID is zero. With no custom RPC, it defaults to mainnet.

Example
package main

import (
	"fmt"
	"os"

	"github.com/tempoxyz/mpp-go/pkg/server"
	"github.com/tempoxyz/mpp-go/pkg/tempo"

	charge "github.com/tempoxyz/mpp-go/pkg/tempo/server"
)

func main() {
	method, err := charge.New(charge.Config{
		ChainID:   tempo.ChainIDModerato,
		Recipient: "0x742d35Cc6634c0532925a3b844bC9e7595F8fE00",
		// Use a persistent store shared by all replicas in production.
		Store: tempo.NewMemoryStore(),
		// Sponsor gas when FEE_PAYER_PRIVATE_KEY is set, paying fees in pathUSD.
		FeePayerPrivateKey: os.Getenv("FEE_PAYER_PRIVATE_KEY"),
		AllowedFeeTokens:   []string{tempo.PathUSDAddress},
	})
	if err != nil {
		panic(err)
	}
	payment, err := server.New(method, "api.example.com", "a-32-byte-or-longer-server-secret")
	if err != nil {
		panic(err)
	}
	fmt.Println(payment != nil)
}
Output:
true

func (*Method) BuildChargeRequest

func (m *Method) BuildChargeRequest(params mppserver.ChargeParams) (map[string]any, error)

BuildChargeRequest normalizes server charge parameters into Tempo request data for a single currency: ChargeParams.Currency when set, otherwise the first accepted currency.

func (*Method) BuildChargeRequests added in v0.4.0

func (m *Method) BuildChargeRequests(params mppserver.ChargeParams) ([]map[string]any, error)

BuildChargeRequests returns one normalized Tempo charge request per accepted currency, in presentation order. A per-request ChargeParams.Currency overrides the configured currencies and yields a single request.

func (*Method) Intents

func (m *Method) Intents() map[string]mppserver.Intent

Intents exposes the Tempo intents handled by this method.

func (*Method) Name

func (m *Method) Name() string

Name returns the method token used in Challenges and Credentials.

type RelayConfig added in v0.4.0

type RelayConfig struct {
	// APIKey is a Tempo API key with the mpp:write scope.
	APIKey string
	// APIBaseURL is the relay base URL, including an optional path prefix.
	// It defaults to https://api.tempo.xyz.
	APIBaseURL string
	// HTTPClient overrides the client used for relay calls. When nil, relay
	// calls use a client with a 30 second timeout.
	HTTPClient *http.Client
}

RelayConfig configures Tempo API or a compatible MPP relay.

type RelayErrorCode added in v0.4.0

type RelayErrorCode string

RelayErrorCode is a stable machine-readable relay failure code.

const (
	// RelayErrorAlreadyUsed means the credential or transaction was already used.
	RelayErrorAlreadyUsed RelayErrorCode = "already_used"
	// RelayErrorBroadcastFailed means transaction broadcast or confirmation failed.
	RelayErrorBroadcastFailed RelayErrorCode = "broadcast_failed"
	// RelayErrorExpired means the challenge or payment authorization expired.
	RelayErrorExpired RelayErrorCode = "expired"
	// RelayErrorInvalidPayment means the payment payload or requirements are invalid.
	RelayErrorInvalidPayment RelayErrorCode = "invalid_payment"
	// RelayErrorInsufficientFunds means the sender lacks funds.
	RelayErrorInsufficientFunds RelayErrorCode = "insufficient_funds"
	// RelayErrorPolicyDenied means the payment violates relay or account policy.
	RelayErrorPolicyDenied RelayErrorCode = "policy_denied"
	// RelayErrorScreenRejected means an originator or recipient failed screening.
	RelayErrorScreenRejected RelayErrorCode = "screen_rejected"
	// RelayErrorSimulationFailed means transaction simulation failed.
	RelayErrorSimulationFailed RelayErrorCode = "simulation_failed"
	// RelayErrorTemporarilyUnavailable means retrying may succeed.
	RelayErrorTemporarilyUnavailable RelayErrorCode = "temporarily_unavailable"
	// RelayErrorUnsupported means the method, intent, network, or asset is unsupported.
	RelayErrorUnsupported RelayErrorCode = "unsupported"
	// RelayErrorUnknown means the relay encountered an unexpected failure.
	RelayErrorUnknown RelayErrorCode = "unknown"
)

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL