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