forked from x402-foundation/x402
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathinterfaces.go
More file actions
301 lines (261 loc) · 12.7 KB
/
Copy pathinterfaces.go
File metadata and controls
301 lines (261 loc) · 12.7 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
package x402
import (
"context"
"github.com/x402-foundation/x402/go/v2/types"
)
// MoneyParser is a function that converts a decimal amount to an AssetAmount
// If the parser cannot handle the conversion, it should return nil
// Multiple parsers can be registered and will be tried in order
// The default parser is always used as a fallback
//
// Args:
//
// amount: Decimal amount (e.g., 1.50 for $1.50)
// network: Network identifier
//
// Returns:
//
// AssetAmount or nil if this parser cannot handle the conversion
type MoneyParser func(amount float64, network Network) (*AssetAmount, error)
// ============================================================================
// V1 Interfaces (Legacy - explicitly versioned)
// ============================================================================
// SchemeNetworkClientV1 is implemented by client-side V1 payment mechanisms
type SchemeNetworkClientV1 interface {
Scheme() string
CreatePaymentPayload(ctx context.Context, requirements types.PaymentRequirementsV1) (types.PaymentPayloadV1, error)
}
// SchemeNetworkFacilitatorV1 is implemented by facilitator-side V1 payment mechanisms
type SchemeNetworkFacilitatorV1 interface {
Scheme() string
// CaipFamily returns the CAIP family pattern this facilitator supports.
// Used to group signers by blockchain family in the supported response.
//
// Examples:
// - EVM facilitators return "eip155:*"
// - SVM facilitators return "solana:*"
CaipFamily() string
// GetExtra returns mechanism-specific extra data for the supported kinds endpoint.
// This method is called when building the facilitator's supported response.
//
// For EVM schemes, return nil (no extra data needed).
// For SVM schemes, return map with feePayer address.
//
// Args:
// network: Network identifier for context
//
// Returns:
// Extra data map or nil if no extra data is needed
GetExtra(network Network) map[string]interface{}
// GetSigners returns signer addresses used by this facilitator for a given network.
// These are included in the supported response to help clients understand
// which addresses might sign/pay for transactions.
//
// Supports multiple addresses for load balancing, key rotation, and high availability.
//
// Args:
// network: Network identifier
//
// Returns:
// Array of signer addresses
//
// Examples:
// - EVM: Returns facilitator wallet addresses
// - SVM: Returns fee payer addresses
GetSigners(network Network) []string
Verify(ctx context.Context, payload types.PaymentPayloadV1, requirements types.PaymentRequirementsV1, fctx *FacilitatorContext) (*VerifyResponse, error)
Settle(ctx context.Context, payload types.PaymentPayloadV1, requirements types.PaymentRequirementsV1, fctx *FacilitatorContext) (*SettleResponse, error)
}
// Note: No SchemeNetworkServerV1 - new SDK servers are V2 only
// ============================================================================
// V2 Interfaces (Current - default, no version suffix)
// ============================================================================
// SchemeNetworkClient is implemented by client-side payment mechanisms (V2)
type SchemeNetworkClient interface {
Scheme() string
CreatePaymentPayload(ctx context.Context, requirements types.PaymentRequirements) (types.PaymentPayload, error)
}
// ExtensionAwareClient is an optional interface for schemes that can handle extensions.
// When a scheme implements this, x402Client will call CreatePaymentPayloadWithExtensions
// instead of CreatePaymentPayload, passing the server-declared extensions so the scheme
// can enrich the payload (e.g., EIP-2612 gas sponsoring).
type ExtensionAwareClient interface {
SchemeNetworkClient
CreatePaymentPayloadWithExtensions(ctx context.Context, requirements types.PaymentRequirements, extensions map[string]interface{}) (types.PaymentPayload, error)
}
// PaymentResponseContext is passed to PaymentResponseHandler implementations after
// the transport receives the response to a paid request. Exactly one of SettleResponse
// or PaymentRequired is populated:
//
// - SettleResponse: the request succeeded (HTTP 200) and the server returned a
// PAYMENT-RESPONSE header carrying the settle outcome.
// - PaymentRequired: the request was rejected (HTTP 402) with a corrective
// PAYMENT-REQUIRED header (e.g. cumulative_amount_mismatch).
//
// Mirrors the TS PaymentResponseContext shape consumed by SchemeClientHooks.onPaymentResponse.
type PaymentResponseContext struct {
PaymentPayload types.PaymentPayload
Requirements types.PaymentRequirements
SettleResponse *SettleResponse
PaymentRequired *types.PaymentRequired
}
// PaymentResponseResult is returned by PaymentResponseHandler.OnPaymentResponse.
// When Recovered is true, the transport may attempt one additional retry with a
// freshly built payment payload. Used to handle corrective 402 responses where
// the scheme has resynced its session state.
type PaymentResponseResult struct {
Recovered bool
}
// PaymentResponseHandler is an optional interface that SchemeNetworkClient
// implementations satisfy to reconcile local state after a paid response.
// The transport (PaymentRoundTripper) invokes this hook automatically — user
// code does not need to call ProcessSettleResponse manually.
//
// Mirrors the TS schemeHooks.onPaymentResponse field on SchemeClientHooks.
type PaymentResponseHandler interface {
OnPaymentResponse(ctx context.Context, prCtx PaymentResponseContext) (PaymentResponseResult, error)
}
// ClientExtension can enrich payment payloads on the client side.
// Client extensions are invoked after the scheme creates the base payload
// but before it is returned. Optional transport-specific capabilities can be
// exposed through package-level provider interfaces such as the HTTP client's
// payment-required hook provider.
type ClientExtension interface {
// Key returns the unique extension identifier (e.g., "eip2612GasSponsoring").
// Must match the extension key used in PaymentRequired.Extensions.
Key() string
// EnrichPaymentPayload is called after payload creation for every registered
// extension. Allows the extension to enrich the payload with extension-specific
// data (e.g., builder-code service codes). Extensions that require a server
// declaration must no-op when the server did not advertise them.
EnrichPaymentPayload(ctx context.Context, payload types.PaymentPayload, required types.PaymentRequired) (types.PaymentPayload, error)
}
// FacilitatorExtension is the base interface for extensions registered with x402Facilitator.
// Extensions are stored by key and made available to mechanism implementations via FacilitatorContext.
// Specific extensions embed this and add their own capabilities (e.g., a batch signer).
type FacilitatorExtension interface {
Key() string
}
// facilitatorExtension is a simple concrete implementation of FacilitatorExtension.
type facilitatorExtension struct {
key string
}
func (e facilitatorExtension) Key() string { return e.key }
// NewFacilitatorExtension creates a FacilitatorExtension with the given key.
func NewFacilitatorExtension(key string) FacilitatorExtension {
return facilitatorExtension{key: key}
}
// FacilitatorContext provides access to registered facilitator extensions.
// Passed to SchemeNetworkFacilitator.Verify/Settle so mechanism implementations
// can retrieve extension-provided capabilities.
type FacilitatorContext struct {
extensions map[string]FacilitatorExtension
}
// NewFacilitatorContext creates a FacilitatorContext from the given extensions map.
func NewFacilitatorContext(extensions map[string]FacilitatorExtension) *FacilitatorContext {
return &FacilitatorContext{extensions: extensions}
}
// GetExtension returns the extension registered under the given key, or nil.
func (c *FacilitatorContext) GetExtension(key string) FacilitatorExtension {
if c == nil || c.extensions == nil {
return nil
}
return c.extensions[key]
}
// SchemeNetworkServer is implemented by server-side payment mechanisms (V2)
type SchemeNetworkServer interface {
Scheme() string
ParsePrice(price Price, network Network) (AssetAmount, error)
EnhancePaymentRequirements(
ctx context.Context,
requirements types.PaymentRequirements,
supportedKind types.SupportedKind,
extensions []string,
) (types.PaymentRequirements, error)
}
// AssetDecimalsProvider is an optional interface that SchemeNetworkServer implementations
// can satisfy to report the decimal precision of the asset for a given network.
// SettlePayment uses this to convert dollar-format settlement overrides to atomic units.
// Falls back to 6 decimals when the scheme does not implement this interface.
type AssetDecimalsProvider interface {
GetAssetDecimals(asset string, network Network) int
}
// PaymentRequiredContext is passed to PaymentRequiredEnricher.EnrichPaymentRequiredResponse.
// PaymentPayload is non-nil only on the verify-failure branch.
type PaymentRequiredContext struct {
Requirements []types.PaymentRequirements
PaymentPayload *types.PaymentPayload
ResourceInfo *types.ResourceInfo
Error string
PaymentRequiredResponse *types.PaymentRequired
}
// PaymentRequiredEnricher is an optional interface for SchemeNetworkServer
// implementations that want to add per-scheme corrective state to the 402
// response. Invoked once per matching scheme during PaymentRequired construction;
// implementations may mutate ctx.Requirements entries in place.
type PaymentRequiredEnricher interface {
EnrichPaymentRequiredResponse(ctx PaymentRequiredContext)
}
// FacilitatorSupportValidator is an optional interface that SchemeNetworkServer
// implementations can satisfy to validate facilitator capabilities at startup.
// Invoked during Initialize(), only when the facilitator supports the
// scheme/network. Returns a non-nil error describing the problem when the
// configuration cannot be fulfilled, or nil when valid.
type FacilitatorSupportValidator interface {
ValidateFacilitatorSupport(network Network, supportedKind types.SupportedKind, facilitatorExtensions []string) error
}
// SchemeNetworkFacilitator is implemented by facilitator-side payment mechanisms (V2)
type SchemeNetworkFacilitator interface {
Scheme() string
// CaipFamily returns the CAIP family pattern this facilitator supports.
// Used to group signers by blockchain family in the supported response.
//
// Examples:
// - EVM facilitators return "eip155:*"
// - SVM facilitators return "solana:*"
CaipFamily() string
// GetExtra returns mechanism-specific extra data for the supported kinds endpoint.
// This method is called when building the facilitator's supported response.
//
// For EVM schemes, return nil (no extra data needed).
// For SVM schemes, return map with feePayer address.
//
// Args:
// network: Network identifier for context
//
// Returns:
// Extra data map or nil if no extra data is needed
GetExtra(network Network) map[string]interface{}
// GetSigners returns signer addresses used by this facilitator for a given network.
// These are included in the supported response to help clients understand
// which addresses might sign/pay for transactions.
//
// Supports multiple addresses for load balancing, key rotation, and high availability.
//
// Args:
// network: Network identifier
//
// Returns:
// Array of signer addresses
//
// Examples:
// - EVM: Returns facilitator wallet addresses
// - SVM: Returns fee payer addresses
GetSigners(network Network) []string
Verify(ctx context.Context, payload types.PaymentPayload, requirements types.PaymentRequirements, fctx *FacilitatorContext) (*VerifyResponse, error)
Settle(ctx context.Context, payload types.PaymentPayload, requirements types.PaymentRequirements, fctx *FacilitatorContext) (*SettleResponse, error)
}
// ============================================================================
// FacilitatorClient Interfaces (Network Boundary - uses bytes)
// ============================================================================
// FacilitatorClient interface for facilitators that support V1 and/or V2.
// Uses bytes at network boundary - SDK internal routing unmarshals and routes to typed mechanisms.
// Both modern facilitators (supporting V1+V2) and legacy facilitators (V1 only) implement this interface.
type FacilitatorClient interface {
// Verify a payment (detects version from bytes, routes internally)
Verify(ctx context.Context, payloadBytes []byte, requirementsBytes []byte) (*VerifyResponse, error)
// Settle a payment (detects version from bytes, routes internally)
Settle(ctx context.Context, payloadBytes []byte, requirementsBytes []byte) (*SettleResponse, error)
// GetSupported returns supported payment kinds in flat array format with x402Version in each element (backward compatible)
GetSupported(ctx context.Context) (SupportedResponse, error)
}