@@ -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
@@ -166,6 +168,7 @@ fn build_evm_exact(
166168 accepted : req. clone ( ) ,
167169 resource,
168170 payload : inner,
171+ extensions,
169172 } )
170173 } else {
171174 PaymentPayload :: V1 ( PaymentPayloadV1 {
@@ -193,7 +196,7 @@ fn build_evm_exact(
193196fn parse_requirements (
194197 headers : & reqwest:: header:: HeaderMap ,
195198 body_text : & str ,
196- ) -> Result < ( u32 , Option < serde_json:: Value > , Vec < PaymentRequirements > ) , PayError > {
199+ ) -> Result < ( u32 , Option < serde_json:: Value > , Vec < PaymentRequirements > , Option < serde_json :: Value > ) , PayError > {
197200 for header_name in & [ HEADER_PAYMENT_REQUIRED_V2 , HEADER_PAYMENT_REQUIRED ] {
198201 if let Some ( header_val) = headers. get ( * header_name) {
199202 if let Ok ( header_str) = header_val. to_str ( ) {
@@ -204,7 +207,7 @@ fn parse_requirements(
204207 HEADER_PAYMENT_REQUIRED_V2 => parsed. x402_version . unwrap_or ( 2 ) ,
205208 _ => parsed. x402_version . unwrap_or ( 1 ) ,
206209 } ;
207- return Ok ( ( version, parsed. resource , parsed. accepts ) ) ;
210+ return Ok ( ( version, parsed. resource , parsed. accepts , parsed . extensions ) ) ;
208211 }
209212 }
210213 }
@@ -230,6 +233,7 @@ fn parse_requirements(
230233 parsed. x402_version . unwrap_or ( 1 ) ,
231234 parsed. resource ,
232235 parsed. accepts ,
236+ parsed. extensions ,
233237 ) )
234238}
235239
@@ -583,7 +587,7 @@ mod tests {
583587 } )
584588 . to_string ( ) ;
585589
586- let ( _, _, reqs) = parse_requirements ( & headers, & body) . unwrap ( ) ;
590+ let ( _, _, reqs, _ ) = parse_requirements ( & headers, & body) . unwrap ( ) ;
587591 assert_eq ! ( reqs. len( ) , 1 ) ;
588592 assert_eq ! ( reqs[ 0 ] . scheme, "exact" ) ;
589593 assert_eq ! ( reqs[ 0 ] . network, "eip155:8453" ) ;
@@ -605,7 +609,7 @@ mod tests {
605609 let mut headers = HeaderMap :: new ( ) ;
606610 headers. insert ( "x-payment-required" , encoded. parse ( ) . unwrap ( ) ) ;
607611
608- let ( _, _, reqs) = parse_requirements ( & headers, "not json" ) . unwrap ( ) ;
612+ let ( _, _, reqs, _ ) = parse_requirements ( & headers, "not json" ) . unwrap ( ) ;
609613 assert_eq ! ( reqs. len( ) , 1 ) ;
610614 assert_eq ! ( reqs[ 0 ] . pay_to, "0xdef" ) ;
611615 }
@@ -626,7 +630,7 @@ mod tests {
626630 } )
627631 . to_string ( ) ;
628632
629- let ( _, _, reqs) = parse_requirements ( & headers, & body) . unwrap ( ) ;
633+ let ( _, _, reqs, _ ) = parse_requirements ( & headers, & body) . unwrap ( ) ;
630634 assert_eq ! ( reqs[ 0 ] . pay_to, "0xbbb" ) ;
631635 }
632636
@@ -646,7 +650,7 @@ mod tests {
646650 let mut headers = HeaderMap :: new ( ) ;
647651 headers. insert ( "payment-required" , encoded. parse ( ) . unwrap ( ) ) ;
648652
649- let ( _, _, reqs) = parse_requirements ( & headers, "not json" ) . unwrap ( ) ;
653+ let ( _, _, reqs, _ ) = parse_requirements ( & headers, "not json" ) . unwrap ( ) ;
650654 assert_eq ! ( reqs. len( ) , 1 ) ;
651655 assert_eq ! ( reqs[ 0 ] . pay_to, "0xv2" ) ;
652656 }
@@ -667,7 +671,7 @@ mod tests {
667671 let mut headers = HeaderMap :: new ( ) ;
668672 headers. insert ( "payment-required" , encoded. parse ( ) . unwrap ( ) ) ;
669673
670- let ( version, _, reqs) = parse_requirements ( & headers, "not json" ) . unwrap ( ) ;
674+ let ( version, _, reqs, _ ) = parse_requirements ( & headers, "not json" ) . unwrap ( ) ;
671675 assert_eq ! ( version, 2 ) ;
672676 assert_eq ! ( reqs. len( ) , 1 ) ;
673677 assert_eq ! ( reqs[ 0 ] . pay_to, "0xv2" ) ;
@@ -693,10 +697,10 @@ mod tests {
693697 let mut headers = HeaderMap :: new ( ) ;
694698 headers. insert ( "payment-required" , encoded. parse ( ) . unwrap ( ) ) ;
695699
696- let ( version, resource, reqs) = parse_requirements ( & headers, "not json" ) . unwrap ( ) ;
700+ let ( version, resource, reqs, extensions ) = parse_requirements ( & headers, "not json" ) . unwrap ( ) ;
697701 let ( req, network) = pick_payment_option ( & EvmWallet , & reqs) . unwrap ( ) ;
698702 let ( payload, _) =
699- build_signed_payment ( & EvmWallet , req, & network, version, resource) . unwrap ( ) ;
703+ build_signed_payment ( & EvmWallet , req, & network, version, resource, extensions ) . unwrap ( ) ;
700704
701705 match payload {
702706 PaymentPayload :: V2 ( v2) => {
@@ -729,7 +733,7 @@ mod tests {
729733 . unwrap ( ) ,
730734 ) ;
731735
732- let ( _, _, reqs) = parse_requirements ( & headers, "not json" ) . unwrap ( ) ;
736+ let ( _, _, reqs, _ ) = parse_requirements ( & headers, "not json" ) . unwrap ( ) ;
733737 assert_eq ! ( reqs[ 0 ] . pay_to, "0xv2" ) ;
734738 }
735739
@@ -880,7 +884,7 @@ mod tests {
880884 #[ test]
881885 fn build_evm_exact_produces_valid_payload ( ) {
882886 let req = base_requirement ( ) ;
883- let ( payload, info) = build_evm_exact ( & EvmWallet , & req, "eip155:8453" , 1 , None ) . unwrap ( ) ;
887+ let ( payload, info) = build_evm_exact ( & EvmWallet , & req, "eip155:8453" , 1 , None , None ) . unwrap ( ) ;
884888
885889 let v1 = match & payload {
886890 PaymentPayload :: V1 ( p) => p,
@@ -910,7 +914,7 @@ mod tests {
910914 "mimeType" : "application/json"
911915 } ) ;
912916 let ( payload, _) =
913- build_evm_exact ( & EvmWallet , & req, "eip155:8453" , 2 , Some ( resource. clone ( ) ) ) . unwrap ( ) ;
917+ build_evm_exact ( & EvmWallet , & req, "eip155:8453" , 2 , Some ( resource. clone ( ) ) , None ) . unwrap ( ) ;
914918
915919 let v2 = match & payload {
916920 PaymentPayload :: V2 ( p) => p,
@@ -932,7 +936,7 @@ mod tests {
932936 #[ test]
933937 fn build_evm_exact_v2_with_no_resource ( ) {
934938 let req = base_requirement ( ) ;
935- let ( payload, _) = build_evm_exact ( & EvmWallet , & req, "eip155:8453" , 2 , None ) . unwrap ( ) ;
939+ let ( payload, _) = build_evm_exact ( & EvmWallet , & req, "eip155:8453" , 2 , None , None ) . unwrap ( ) ;
936940
937941 let v2 = match & payload {
938942 PaymentPayload :: V2 ( p) => p,
@@ -949,7 +953,7 @@ mod tests {
949953 req. description = None ;
950954 req. resource = None ;
951955
952- let ( payload, _) = build_evm_exact ( & EvmWallet , & req, "eip155:8453" , 2 , None ) . unwrap ( ) ;
956+ let ( payload, _) = build_evm_exact ( & EvmWallet , & req, "eip155:8453" , 2 , None , None ) . unwrap ( ) ;
953957 let encoded = serde_json:: to_value ( payload) . unwrap ( ) ;
954958 let accepted = & encoded[ "accepted" ] ;
955959
@@ -961,7 +965,7 @@ mod tests {
961965 #[ test]
962966 fn build_evm_exact_fails_for_non_numeric_chain_id ( ) {
963967 let req = base_requirement ( ) ;
964- let err = build_evm_exact ( & EvmWallet , & req, "solana:mainnet" , 1 , None ) . unwrap_err ( ) ;
968+ let err = build_evm_exact ( & EvmWallet , & req, "solana:mainnet" , 1 , None , None ) . unwrap_err ( ) ;
965969 assert_eq ! ( err. code, PayErrorCode :: ProtocolMalformed ) ;
966970 }
967971
@@ -986,7 +990,7 @@ mod tests {
986990 . to_string ( ) ;
987991
988992 let headers = HeaderMap :: new ( ) ;
989- let ( _, _, reqs) = parse_requirements ( & headers, & body) . unwrap ( ) ;
993+ let ( _, _, reqs, _ ) = parse_requirements ( & headers, & body) . unwrap ( ) ;
990994 let ( req, network) = pick_payment_option ( & EvmWallet , & reqs) . unwrap ( ) ;
991995 assert_eq ! ( req. pay_to, "0x7d9d1821d15B9e0b8Ab98A058361233E255E405D" ) ;
992996 assert_eq ! ( network, "eip155:8453" ) ; // "base" resolved to CAIP-2
0 commit comments