@@ -8,38 +8,32 @@ const hexSchema = z
88const addressSchema = z
99 . string ( )
1010 . check ( z . refine ( isAddress , { message : "Invalid address" } ) ) ;
11-
12- const webhookSchema = z . union ( [
11+ const tokenSchema = z . object ( {
12+ address : addressSchema ,
13+ chainId : z . coerce . number ( ) ,
14+ decimals : z . coerce . number ( ) ,
15+ iconUri : z . optional ( z . string ( ) ) ,
16+ name : z . string ( ) ,
17+ priceUsd : z . coerce . number ( ) ,
18+ symbol : z . string ( ) ,
19+ } ) ;
20+
21+ const onchainWebhookSchema = z . discriminatedUnion ( "version" , [
1322 z . object ( {
1423 data : z . object ( { } ) ,
24+ type : z . literal ( "ONCHAIN" ) ,
1525 version : z . literal ( 1 ) ,
1626 } ) ,
1727 z . object ( {
1828 data : z . object ( {
1929 action : z . enum ( [ "TRANSFER" , "BUY" , "SELL" ] ) ,
2030 clientId : z . string ( ) ,
2131 destinationAmount : z . string ( ) ,
22- destinationToken : z . object ( {
23- address : addressSchema ,
24- chainId : z . coerce . number ( ) ,
25- decimals : z . coerce . number ( ) ,
26- iconUri : z . optional ( z . string ( ) ) ,
27- name : z . string ( ) ,
28- priceUsd : z . coerce . number ( ) ,
29- symbol : z . string ( ) ,
30- } ) ,
32+ destinationToken : tokenSchema ,
3133 developerFeeBps : z . coerce . number ( ) ,
3234 developerFeeRecipient : addressSchema ,
3335 originAmount : z . string ( ) ,
34- originToken : z . object ( {
35- address : addressSchema ,
36- chainId : z . coerce . number ( ) ,
37- decimals : z . coerce . number ( ) ,
38- iconUri : z . optional ( z . string ( ) ) ,
39- name : z . string ( ) ,
40- priceUsd : z . coerce . number ( ) ,
41- symbol : z . string ( ) ,
42- } ) ,
36+ originToken : tokenSchema ,
4337 paymentId : z . string ( ) ,
4438 // only exists when the payment was triggered from a developer specified payment link
4539 paymentLinkId : z . optional ( z . string ( ) ) ,
@@ -55,10 +49,41 @@ const webhookSchema = z.union([
5549 ) ,
5650 type : z . string ( ) ,
5751 } ) ,
52+ type : z . literal ( "ONCHAIN" ) ,
53+ version : z . literal ( 2 ) ,
54+ } ) ,
55+ ] ) ;
56+
57+ const onrampWebhookSchema = z . discriminatedUnion ( "version" , [
58+ z . object ( {
59+ data : z . object ( { } ) ,
60+ type : z . literal ( "ONRAMP" ) ,
61+ version : z . literal ( 1 ) ,
62+ } ) ,
63+ z . object ( {
64+ data : z . object ( {
65+ amount : z . string ( ) ,
66+ currency : z . string ( ) ,
67+ currencyAmount : z . number ( ) ,
68+ id : z . string ( ) ,
69+ onramp : z . string ( ) ,
70+ paymentLinkId : z . optional ( z . string ( ) ) ,
71+ purchaseData : z . unknown ( ) ,
72+ receiver : z . optional ( addressSchema ) ,
73+ sender : z . optional ( addressSchema ) ,
74+ status : z . enum ( [ "PENDING" , "COMPLETED" , "FAILED" ] ) ,
75+ token : tokenSchema ,
76+ transactionHash : z . optional ( hexSchema ) ,
77+ } ) ,
78+ type : z . literal ( "ONRAMP" ) ,
5879 version : z . literal ( 2 ) ,
5980 } ) ,
6081] ) ;
6182
83+ const webhookSchema = z . discriminatedUnion ( "type" , [
84+ onchainWebhookSchema ,
85+ onrampWebhookSchema ,
86+ ] ) ;
6287export type WebhookPayload = Exclude <
6388 z . infer < typeof webhookSchema > ,
6489 { version : 1 }
@@ -93,7 +118,7 @@ export async function parse(
93118 * The tolerance in seconds for the timestamp verification.
94119 */
95120 tolerance = 300 , // Default to 5 minutes if not specified
96- ) {
121+ ) : Promise < WebhookPayload > {
97122 // Get the signature and timestamp from headers
98123 const receivedSignature =
99124 headers [ "x-payload-signature" ] || headers [ "x-pay-signature" ] ;
@@ -158,5 +183,5 @@ export async function parse(
158183 ) ;
159184 }
160185
161- return parsedPayload ;
186+ return parsedPayload satisfies WebhookPayload ;
162187}
0 commit comments