1- import type { FacilitatorConfig } from "x402/types" ;
1+ import type { SupportedPaymentKindsResponse , VerifyResponse } from "x402/types" ;
22import type { ThirdwebClient } from "../client/client.js" ;
3+ import { stringify } from "../utils/json.js" ;
4+ import { withCache } from "../utils/promise/withCache.js" ;
5+ import type {
6+ FacilitatorSettleResponse ,
7+ RequestedPaymentPayload ,
8+ RequestedPaymentRequirements ,
9+ } from "./schemas.js" ;
310
411export type ThirdwebX402FacilitatorConfig = {
512 client : ThirdwebClient ;
@@ -48,9 +55,7 @@ const DEFAULT_BASE_URL = "https://api.thirdweb.com/v1/payments/x402";
4855 *
4956 * @bridge x402
5057 */
51- export function facilitator (
52- config : ThirdwebX402FacilitatorConfig ,
53- ) : FacilitatorConfig {
58+ export function facilitator ( config : ThirdwebX402FacilitatorConfig ) {
5459 const secretKey = config . client . secretKey ;
5560 if ( ! secretKey ) {
5661 throw new Error ( "Client secret key is required for the x402 facilitator" ) ;
@@ -61,7 +66,7 @@ export function facilitator(
6166 "Server wallet address is required for the x402 facilitator" ,
6267 ) ;
6368 }
64- return {
69+ const facilitator = {
6570 url : ( config . baseUrl ?? DEFAULT_BASE_URL ) as `${string } ://${string } `,
6671 createAuthHeaders : async ( ) => {
6772 return {
@@ -83,5 +88,108 @@ export function facilitator(
8388 } ,
8489 } ;
8590 } ,
91+ /**
92+ * Verifies a payment payload with the facilitator service
93+ *
94+ * @param payload - The payment payload to verify
95+ * @param paymentRequirements - The payment requirements to verify against
96+ * @returns A promise that resolves to the verification response
97+ */
98+ async verify (
99+ payload : RequestedPaymentPayload ,
100+ paymentRequirements : RequestedPaymentRequirements ,
101+ ) : Promise < VerifyResponse > {
102+ const url = config . baseUrl ?? DEFAULT_BASE_URL ;
103+
104+ let headers = { "Content-Type" : "application/json" } ;
105+ const authHeaders = await facilitator . createAuthHeaders ( ) ;
106+ headers = { ...headers , ...authHeaders . verify } ;
107+
108+ const res = await fetch ( `${ url } /verify` , {
109+ method : "POST" ,
110+ headers,
111+ body : stringify ( {
112+ x402Version : payload . x402Version ,
113+ paymentPayload : payload ,
114+ paymentRequirements : paymentRequirements ,
115+ } ) ,
116+ } ) ;
117+
118+ if ( res . status !== 200 ) {
119+ const text = `${ res . statusText } ${ await res . text ( ) } ` ;
120+ throw new Error ( `Failed to verify payment: ${ res . status } ${ text } ` ) ;
121+ }
122+
123+ const data = await res . json ( ) ;
124+ return data as VerifyResponse ;
125+ } ,
126+
127+ /**
128+ * Settles a payment with the facilitator service
129+ *
130+ * @param payload - The payment payload to settle
131+ * @param paymentRequirements - The payment requirements for the settlement
132+ * @returns A promise that resolves to the settlement response
133+ */
134+ async settle (
135+ payload : RequestedPaymentPayload ,
136+ paymentRequirements : RequestedPaymentRequirements ,
137+ ) : Promise < FacilitatorSettleResponse > {
138+ const url = config . baseUrl ?? DEFAULT_BASE_URL ;
139+
140+ let headers = { "Content-Type" : "application/json" } ;
141+ const authHeaders = await facilitator . createAuthHeaders ( ) ;
142+ headers = { ...headers , ...authHeaders . settle } ;
143+
144+ const res = await fetch ( `${ url } /settle` , {
145+ method : "POST" ,
146+ headers,
147+ body : JSON . stringify ( {
148+ x402Version : payload . x402Version ,
149+ paymentPayload : payload ,
150+ paymentRequirements : paymentRequirements ,
151+ } ) ,
152+ } ) ;
153+
154+ if ( res . status !== 200 ) {
155+ const text = `${ res . statusText } ${ await res . text ( ) } ` ;
156+ throw new Error ( `Failed to settle payment: ${ res . status } ${ text } ` ) ;
157+ }
158+
159+ const data = await res . json ( ) ;
160+ return data as FacilitatorSettleResponse ;
161+ } ,
162+
163+ /**
164+ * Gets the supported payment kinds from the facilitator service.
165+ *
166+ * @returns A promise that resolves to the supported payment kinds
167+ */
168+ async supported ( ) : Promise < SupportedPaymentKindsResponse > {
169+ const url = config . baseUrl ?? DEFAULT_BASE_URL ;
170+ return withCache (
171+ async ( ) => {
172+ let headers = { "Content-Type" : "application/json" } ;
173+ const authHeaders = await facilitator . createAuthHeaders ( ) ;
174+ headers = { ...headers , ...authHeaders . supported } ;
175+ const res = await fetch ( `${ url } /supported` , { headers } ) ;
176+
177+ if ( res . status !== 200 ) {
178+ throw new Error (
179+ `Failed to get supported payment kinds: ${ res . statusText } ` ,
180+ ) ;
181+ }
182+
183+ const data = await res . json ( ) ;
184+ return data as SupportedPaymentKindsResponse ;
185+ } ,
186+ {
187+ cacheKey : "supported-payment-kinds" ,
188+ cacheTime : 1000 * 60 * 60 * 24 , // 24 hours
189+ } ,
190+ ) ;
191+ } ,
86192 } ;
193+
194+ return facilitator ;
87195}
0 commit comments