@@ -619,4 +619,161 @@ describe("parseIncomingWebhook", () => {
619619 "$ZodError" ,
620620 ) ;
621621 } ) ;
622+
623+ describe ( "verify" , ( ) => {
624+ type VerifyOptions = Parameters < typeof parse > [ 4 ] ;
625+
626+ async function stringifyAndParse (
627+ payload : unknown ,
628+ verify ?: VerifyOptions ,
629+ ) : Promise < WebhookPayload > {
630+ const timestamp = Math . floor ( Date . now ( ) / 1000 ) . toString ( ) ;
631+ const payloadString =
632+ typeof payload === "string" ? payload : JSON . stringify ( payload ) ;
633+ const signature = await generateSignature ( timestamp , payloadString ) ;
634+ const headers = {
635+ "x-payload-signature" : signature ,
636+ "x-timestamp" : timestamp ,
637+ } ;
638+ return parse ( payloadString , headers , secret , 300 , verify ) ;
639+ }
640+
641+ async function expectVerifyFailure (
642+ payload : unknown ,
643+ verify : VerifyOptions ,
644+ message : string ,
645+ ) : Promise < void > {
646+ await expect ( stringifyAndParse ( payload , verify ) ) . rejects . toThrow ( message ) ;
647+ }
648+
649+ describe ( "onchain tx" , ( ) => {
650+ it ( "should pass when all verification values match" , async ( ) => {
651+ const result = await stringifyAndParse ( validPayload , {
652+ receiverAddress : validWebhook . data . receiver ,
653+ destinationTokenAddress : validWebhook . data . destinationToken . address ,
654+ destinationChainId : validWebhook . data . destinationToken . chainId ,
655+ minDestinationAmount : validWebhook . data . destinationAmount ,
656+ } ) ;
657+ expect ( result ) . toEqual ( validWebhook ) ;
658+ } ) ;
659+
660+ it ( "should fail if receiverAddress does not match" , async ( ) => {
661+ const expected = "0x0000000000000000000000000000000000000000" ;
662+ await expectVerifyFailure (
663+ validPayload ,
664+ { receiverAddress : expected } ,
665+ `Verification Failed: receiverAddress mismatch, Expected: ${ expected } , Received: ${ validWebhook . data . receiver } ` ,
666+ ) ;
667+ } ) ;
668+
669+ it ( "should fail if destinationTokenAddress does not match" , async ( ) => {
670+ const expected = "0x0000000000000000000000000000000000000001" ;
671+ await expectVerifyFailure (
672+ validPayload ,
673+ { destinationTokenAddress : expected } ,
674+ `Verification Failed: destinationTokenAddress mismatch, Expected: ${ expected } , Received: ${ validWebhook . data . destinationToken . address } ` ,
675+ ) ;
676+ } ) ;
677+
678+ it ( "should fail if destinationChainId does not match" , async ( ) => {
679+ const expected = 137 ;
680+ await expectVerifyFailure (
681+ validPayload ,
682+ { destinationChainId : expected } ,
683+ `Verification Failed: destinationChainId mismatch, Expected: ${ expected } , Received: ${ validWebhook . data . destinationToken . chainId } ` ,
684+ ) ;
685+ } ) ;
686+
687+ it ( "should fail if minDestinationAmount is greater than actual" , async ( ) => {
688+ const expectedMin = validWebhook . data . destinationAmount + 1n ;
689+ await expectVerifyFailure (
690+ validPayload ,
691+ { minDestinationAmount : expectedMin } ,
692+ `Verification Failed: minDestinationAmount, Expected minimum amount to be ${ expectedMin } , Received: ${ validWebhook . data . destinationAmount } ` ,
693+ ) ;
694+ } ) ;
695+ } ) ;
696+
697+ describe ( "onramp tx" , ( ) => {
698+ const onrampWebhook : WebhookPayload = {
699+ data : {
700+ amount : 100n ,
701+ currency : "USD" ,
702+ currencyAmount : 100 ,
703+ id : "onramp123" ,
704+ onramp : "moonpay" ,
705+ paymentLinkId : "plink_123" ,
706+ purchaseData : { } ,
707+ receiver : "0x1234567890123456789012345678901234567890" ,
708+ sender : "0x1234567890123456789012345678901234567890" ,
709+ status : "COMPLETED" ,
710+ token : {
711+ address : "0x1234567890123456789012345678901234567890" ,
712+ chainId : 1 ,
713+ decimals : 18 ,
714+ iconUri : "https://example.com/icon.png" ,
715+ name : "Token" ,
716+ priceUsd : 1.0 ,
717+ symbol : "TKN" ,
718+ } ,
719+ transactionHash : "0x1234567890123456789012345678901234567890" ,
720+ } ,
721+ type : "pay.onramp-transaction" ,
722+ version : 2 ,
723+ } ;
724+ const onrampPayload = {
725+ ...onrampWebhook ,
726+ data : {
727+ ...onrampWebhook . data ,
728+ amount : onrampWebhook . data . amount . toString ( ) ,
729+ } ,
730+ } ;
731+
732+ it ( "should pass when all verification values match " , async ( ) => {
733+ const result = await stringifyAndParse ( onrampPayload , {
734+ receiverAddress : onrampWebhook . data . receiver ,
735+ destinationTokenAddress : onrampWebhook . data . token . address ,
736+ destinationChainId : onrampWebhook . data . token . chainId ,
737+ minDestinationAmount : onrampWebhook . data . amount ,
738+ } ) ;
739+ expect ( result ) . toEqual ( onrampWebhook ) ;
740+ } ) ;
741+
742+ it ( "should fail if destinationTokenAddress does not match " , async ( ) => {
743+ const expected = "0x0000000000000000000000000000000000000002" ;
744+ await expectVerifyFailure (
745+ onrampPayload ,
746+ { destinationTokenAddress : expected } ,
747+ `Verification Failed: destinationTokenAddress mismatch, Expected: ${ expected } , Received: ${ onrampWebhook . data . token . address } ` ,
748+ ) ;
749+ } ) ;
750+
751+ it ( "should fail if destinationChainId does not match " , async ( ) => {
752+ const expected = 8453 ;
753+ await expectVerifyFailure (
754+ onrampPayload ,
755+ { destinationChainId : expected } ,
756+ `Verification Failed: destinationChainId mismatch, Expected: ${ expected } , Received: ${ onrampWebhook . data . token . chainId } ` ,
757+ ) ;
758+ } ) ;
759+
760+ it ( "should fail if minDestinationAmount is greater than actual " , async ( ) => {
761+ const expectedMin = onrampWebhook . data . amount + 1n ;
762+ await expectVerifyFailure (
763+ onrampPayload ,
764+ { minDestinationAmount : expectedMin } ,
765+ `Verification Failed: minDestinationAmount, Expected minimum amount to be ${ expectedMin } , Received: ${ onrampWebhook . data . amount } ` ,
766+ ) ;
767+ } ) ;
768+
769+ it ( "should fail if receiverAddress does not match" , async ( ) => {
770+ const expected = "0x0000000000000000000000000000000000000003" ;
771+ await expectVerifyFailure (
772+ onrampPayload ,
773+ { receiverAddress : expected } ,
774+ `Verification Failed: receiverAddress mismatch, Expected: ${ expected } , Received: ${ onrampWebhook . data . receiver } ` ,
775+ ) ;
776+ } ) ;
777+ } ) ;
778+ } ) ;
622779} ) ;
0 commit comments