@@ -22,11 +22,11 @@ pub(crate) async fn handle_x402(
2222 resp_headers : & reqwest:: header:: HeaderMap ,
2323 body_402 : & str ,
2424) -> Result < PayResult , PayError > {
25- let ( x402_version, resource, requirements) = parse_requirements ( resp_headers, body_402) ?;
25+ let ( x402_version, resource, requirements, extensions ) = parse_requirements ( resp_headers, body_402) ?;
2626 let ( req, network) = pick_payment_option ( wallet, & requirements) ?;
2727
2828 let ( payload, payment_info) =
29- build_signed_payment ( wallet, req, & network, x402_version, resource) ?;
29+ build_signed_payment ( wallet, req, & network, x402_version, resource, extensions ) ?;
3030
3131 let payload_json = serde_json:: to_string ( & payload) ?;
3232 let payload_b64 = B64 . encode ( payload_json. as_bytes ( ) ) ;
@@ -58,9 +58,10 @@ fn build_signed_payment(
5858 network : & str ,
5959 x402_version : u32 ,
6060 resource : Option < serde_json:: Value > ,
61+ extensions : Option < serde_json:: Value > ,
6162) -> Result < ( PaymentPayload , PaymentInfo ) , PayError > {
6263 match req. scheme . as_str ( ) {
63- "exact" => build_evm_exact ( wallet, req, network, x402_version, resource) ,
64+ "exact" => build_evm_exact ( wallet, req, network, x402_version, resource, extensions ) ,
6465 scheme => Err ( PayError :: new (
6566 PayErrorCode :: ProtocolUnknown ,
6667 format ! ( "unsupported payment scheme: {scheme}" ) ,
@@ -75,6 +76,7 @@ fn build_evm_exact(
7576 network : & str ,
7677 x402_version : u32 ,
7778 resource : Option < serde_json:: Value > ,
79+ extensions : Option < serde_json:: Value > ,
7880) -> Result < ( PaymentPayload , PaymentInfo ) , PayError > {
7981 let account = wallet. account ( network) ?;
8082
@@ -162,6 +164,7 @@ fn build_evm_exact(
162164 accepted : req. clone ( ) ,
163165 resource,
164166 payload : inner,
167+ extensions,
165168 } )
166169 } else {
167170 PaymentPayload :: V1 ( PaymentPayloadV1 {
@@ -189,7 +192,7 @@ fn build_evm_exact(
189192fn parse_requirements (
190193 headers : & reqwest:: header:: HeaderMap ,
191194 body_text : & str ,
192- ) -> Result < ( u32 , Option < serde_json:: Value > , Vec < PaymentRequirements > ) , PayError > {
195+ ) -> Result < ( u32 , Option < serde_json:: Value > , Vec < PaymentRequirements > , Option < serde_json :: Value > ) , PayError > {
193196 for header_name in & [ HEADER_PAYMENT_REQUIRED_V2 , HEADER_PAYMENT_REQUIRED ] {
194197 if let Some ( header_val) = headers. get ( * header_name) {
195198 if let Ok ( header_str) = header_val. to_str ( ) {
@@ -200,7 +203,7 @@ fn parse_requirements(
200203 HEADER_PAYMENT_REQUIRED_V2 => parsed. x402_version . unwrap_or ( 2 ) ,
201204 _ => parsed. x402_version . unwrap_or ( 1 ) ,
202205 } ;
203- return Ok ( ( version, parsed. resource , parsed. accepts ) ) ;
206+ return Ok ( ( version, parsed. resource , parsed. accepts , parsed . extensions ) ) ;
204207 }
205208 }
206209 }
@@ -226,6 +229,7 @@ fn parse_requirements(
226229 parsed. x402_version . unwrap_or ( 1 ) ,
227230 parsed. resource ,
228231 parsed. accepts ,
232+ parsed. extensions ,
229233 ) )
230234}
231235
@@ -579,7 +583,7 @@ mod tests {
579583 } )
580584 . to_string ( ) ;
581585
582- let ( _, _, reqs) = parse_requirements ( & headers, & body) . unwrap ( ) ;
586+ let ( _, _, reqs, _ ) = parse_requirements ( & headers, & body) . unwrap ( ) ;
583587 assert_eq ! ( reqs. len( ) , 1 ) ;
584588 assert_eq ! ( reqs[ 0 ] . scheme, "exact" ) ;
585589 assert_eq ! ( reqs[ 0 ] . network, "eip155:8453" ) ;
@@ -601,7 +605,7 @@ mod tests {
601605 let mut headers = HeaderMap :: new ( ) ;
602606 headers. insert ( "x-payment-required" , encoded. parse ( ) . unwrap ( ) ) ;
603607
604- let ( _, _, reqs) = parse_requirements ( & headers, "not json" ) . unwrap ( ) ;
608+ let ( _, _, reqs, _ ) = parse_requirements ( & headers, "not json" ) . unwrap ( ) ;
605609 assert_eq ! ( reqs. len( ) , 1 ) ;
606610 assert_eq ! ( reqs[ 0 ] . pay_to, "0xdef" ) ;
607611 }
@@ -622,7 +626,7 @@ mod tests {
622626 } )
623627 . to_string ( ) ;
624628
625- let ( _, _, reqs) = parse_requirements ( & headers, & body) . unwrap ( ) ;
629+ let ( _, _, reqs, _ ) = parse_requirements ( & headers, & body) . unwrap ( ) ;
626630 assert_eq ! ( reqs[ 0 ] . pay_to, "0xbbb" ) ;
627631 }
628632
@@ -642,7 +646,7 @@ mod tests {
642646 let mut headers = HeaderMap :: new ( ) ;
643647 headers. insert ( "payment-required" , encoded. parse ( ) . unwrap ( ) ) ;
644648
645- let ( _, _, reqs) = parse_requirements ( & headers, "not json" ) . unwrap ( ) ;
649+ let ( _, _, reqs, _ ) = parse_requirements ( & headers, "not json" ) . unwrap ( ) ;
646650 assert_eq ! ( reqs. len( ) , 1 ) ;
647651 assert_eq ! ( reqs[ 0 ] . pay_to, "0xv2" ) ;
648652 }
@@ -663,7 +667,7 @@ mod tests {
663667 let mut headers = HeaderMap :: new ( ) ;
664668 headers. insert ( "payment-required" , encoded. parse ( ) . unwrap ( ) ) ;
665669
666- let ( version, _, reqs) = parse_requirements ( & headers, "not json" ) . unwrap ( ) ;
670+ let ( version, _, reqs, _ ) = parse_requirements ( & headers, "not json" ) . unwrap ( ) ;
667671 assert_eq ! ( version, 2 ) ;
668672 assert_eq ! ( reqs. len( ) , 1 ) ;
669673 assert_eq ! ( reqs[ 0 ] . pay_to, "0xv2" ) ;
@@ -689,10 +693,10 @@ mod tests {
689693 let mut headers = HeaderMap :: new ( ) ;
690694 headers. insert ( "payment-required" , encoded. parse ( ) . unwrap ( ) ) ;
691695
692- let ( version, resource, reqs) = parse_requirements ( & headers, "not json" ) . unwrap ( ) ;
696+ let ( version, resource, reqs, extensions ) = parse_requirements ( & headers, "not json" ) . unwrap ( ) ;
693697 let ( req, network) = pick_payment_option ( & EvmWallet , & reqs) . unwrap ( ) ;
694698 let ( payload, _) =
695- build_signed_payment ( & EvmWallet , req, & network, version, resource) . unwrap ( ) ;
699+ build_signed_payment ( & EvmWallet , req, & network, version, resource, extensions ) . unwrap ( ) ;
696700
697701 match payload {
698702 PaymentPayload :: V2 ( v2) => {
@@ -725,7 +729,7 @@ mod tests {
725729 . unwrap ( ) ,
726730 ) ;
727731
728- let ( _, _, reqs) = parse_requirements ( & headers, "not json" ) . unwrap ( ) ;
732+ let ( _, _, reqs, _ ) = parse_requirements ( & headers, "not json" ) . unwrap ( ) ;
729733 assert_eq ! ( reqs[ 0 ] . pay_to, "0xv2" ) ;
730734 }
731735
@@ -876,7 +880,7 @@ mod tests {
876880 #[ test]
877881 fn build_evm_exact_produces_valid_payload ( ) {
878882 let req = base_requirement ( ) ;
879- let ( payload, info) = build_evm_exact ( & EvmWallet , & req, "eip155:8453" , 1 , None ) . unwrap ( ) ;
883+ let ( payload, info) = build_evm_exact ( & EvmWallet , & req, "eip155:8453" , 1 , None , None ) . unwrap ( ) ;
880884
881885 let v1 = match & payload {
882886 PaymentPayload :: V1 ( p) => p,
@@ -906,7 +910,7 @@ mod tests {
906910 "mimeType" : "application/json"
907911 } ) ;
908912 let ( payload, _) =
909- build_evm_exact ( & EvmWallet , & req, "eip155:8453" , 2 , Some ( resource. clone ( ) ) ) . unwrap ( ) ;
913+ build_evm_exact ( & EvmWallet , & req, "eip155:8453" , 2 , Some ( resource. clone ( ) ) , None ) . unwrap ( ) ;
910914
911915 let v2 = match & payload {
912916 PaymentPayload :: V2 ( p) => p,
@@ -928,7 +932,7 @@ mod tests {
928932 #[ test]
929933 fn build_evm_exact_v2_with_no_resource ( ) {
930934 let req = base_requirement ( ) ;
931- let ( payload, _) = build_evm_exact ( & EvmWallet , & req, "eip155:8453" , 2 , None ) . unwrap ( ) ;
935+ let ( payload, _) = build_evm_exact ( & EvmWallet , & req, "eip155:8453" , 2 , None , None ) . unwrap ( ) ;
932936
933937 let v2 = match & payload {
934938 PaymentPayload :: V2 ( p) => p,
@@ -945,7 +949,7 @@ mod tests {
945949 req. description = None ;
946950 req. resource = None ;
947951
948- let ( payload, _) = build_evm_exact ( & EvmWallet , & req, "eip155:8453" , 2 , None ) . unwrap ( ) ;
952+ let ( payload, _) = build_evm_exact ( & EvmWallet , & req, "eip155:8453" , 2 , None , None ) . unwrap ( ) ;
949953 let encoded = serde_json:: to_value ( payload) . unwrap ( ) ;
950954 let accepted = & encoded[ "accepted" ] ;
951955
@@ -957,7 +961,7 @@ mod tests {
957961 #[ test]
958962 fn build_evm_exact_fails_for_non_numeric_chain_id ( ) {
959963 let req = base_requirement ( ) ;
960- let err = build_evm_exact ( & EvmWallet , & req, "solana:mainnet" , 1 , None ) . unwrap_err ( ) ;
964+ let err = build_evm_exact ( & EvmWallet , & req, "solana:mainnet" , 1 , None , None ) . unwrap_err ( ) ;
961965 assert_eq ! ( err. code, PayErrorCode :: ProtocolMalformed ) ;
962966 }
963967
@@ -982,7 +986,7 @@ mod tests {
982986 . to_string ( ) ;
983987
984988 let headers = HeaderMap :: new ( ) ;
985- let ( _, _, reqs) = parse_requirements ( & headers, & body) . unwrap ( ) ;
989+ let ( _, _, reqs, _ ) = parse_requirements ( & headers, & body) . unwrap ( ) ;
986990 let ( req, network) = pick_payment_option ( & EvmWallet , & reqs) . unwrap ( ) ;
987991 assert_eq ! ( req. pay_to, "0x7d9d1821d15B9e0b8Ab98A058361233E255E405D" ) ;
988992 assert_eq ! ( network, "eip155:8453" ) ; // "base" resolved to CAIP-2
0 commit comments