@@ -8,38 +8,32 @@ const hexSchema = z
8
8
const addressSchema = z
9
9
. string ( )
10
10
. 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" , [
13
22
z . object ( {
14
23
data : z . object ( { } ) ,
24
+ type : z . literal ( "ONCHAIN" ) ,
15
25
version : z . literal ( 1 ) ,
16
26
} ) ,
17
27
z . object ( {
18
28
data : z . object ( {
19
29
action : z . enum ( [ "TRANSFER" , "BUY" , "SELL" ] ) ,
20
30
clientId : z . string ( ) ,
21
31
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 ,
31
33
developerFeeBps : z . coerce . number ( ) ,
32
34
developerFeeRecipient : addressSchema ,
33
35
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 ,
43
37
paymentId : z . string ( ) ,
44
38
// only exists when the payment was triggered from a developer specified payment link
45
39
paymentLinkId : z . optional ( z . string ( ) ) ,
@@ -55,10 +49,41 @@ const webhookSchema = z.union([
55
49
) ,
56
50
type : z . string ( ) ,
57
51
} ) ,
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" ) ,
58
79
version : z . literal ( 2 ) ,
59
80
} ) ,
60
81
] ) ;
61
82
83
+ const webhookSchema = z . discriminatedUnion ( "type" , [
84
+ onchainWebhookSchema ,
85
+ onrampWebhookSchema ,
86
+ ] ) ;
62
87
export type WebhookPayload = Exclude <
63
88
z . infer < typeof webhookSchema > ,
64
89
{ version : 1 }
@@ -93,7 +118,7 @@ export async function parse(
93
118
* The tolerance in seconds for the timestamp verification.
94
119
*/
95
120
tolerance = 300 , // Default to 5 minutes if not specified
96
- ) {
121
+ ) : Promise < WebhookPayload > {
97
122
// Get the signature and timestamp from headers
98
123
const receivedSignature =
99
124
headers [ "x-payload-signature" ] || headers [ "x-pay-signature" ] ;
@@ -158,5 +183,5 @@ export async function parse(
158
183
) ;
159
184
}
160
185
161
- return parsedPayload ;
186
+ return parsedPayload satisfies WebhookPayload ;
162
187
}
0 commit comments