Class: Mpp::Methods::Evm::ChargeIntent
- Inherits:
-
Object
- Object
- Mpp::Methods::Evm::ChargeIntent
- Defined in:
- lib/mpp/methods/evm/charge_intent.rb
Overview
Server-side EVM charge intent: recover EIP-3009, then settle via facilitator.
Instance Attribute Summary collapse
-
#authorization ⇒ Object
readonly
Returns the value of attribute authorization.
-
#facilitator ⇒ Object
readonly
Returns the value of attribute facilitator.
-
#max_timeout_seconds ⇒ Object
readonly
Returns the value of attribute max_timeout_seconds.
-
#name ⇒ Object
readonly
Returns the value of attribute name.
-
#route_binding ⇒ Object
readonly
Returns the value of attribute route_binding.
Instance Method Summary collapse
-
#initialize(authorization:, facilitator:, max_timeout_seconds: 300, route_binding: :resource) ⇒ ChargeIntent
constructor
A new instance of ChargeIntent.
- #payment_requirements(request) ⇒ Object
- #verify(credential, request) ⇒ Object
Constructor Details
#initialize(authorization:, facilitator:, max_timeout_seconds: 300, route_binding: :resource) ⇒ ChargeIntent
Returns a new instance of ChargeIntent.
13 14 15 16 17 18 19 |
# File 'lib/mpp/methods/evm/charge_intent.rb', line 13 def initialize(authorization:, facilitator:, max_timeout_seconds: 300, route_binding: :resource) @name = "charge" @authorization = @facilitator = facilitator @max_timeout_seconds = max_timeout_seconds @route_binding = route_binding end |
Instance Attribute Details
#authorization ⇒ Object (readonly)
Returns the value of attribute authorization.
11 12 13 |
# File 'lib/mpp/methods/evm/charge_intent.rb', line 11 def @authorization end |
#facilitator ⇒ Object (readonly)
Returns the value of attribute facilitator.
11 12 13 |
# File 'lib/mpp/methods/evm/charge_intent.rb', line 11 def facilitator @facilitator end |
#max_timeout_seconds ⇒ Object (readonly)
Returns the value of attribute max_timeout_seconds.
11 12 13 |
# File 'lib/mpp/methods/evm/charge_intent.rb', line 11 def max_timeout_seconds @max_timeout_seconds end |
#name ⇒ Object (readonly)
Returns the value of attribute name.
11 12 13 |
# File 'lib/mpp/methods/evm/charge_intent.rb', line 11 def name @name end |
#route_binding ⇒ Object (readonly)
Returns the value of attribute route_binding.
11 12 13 |
# File 'lib/mpp/methods/evm/charge_intent.rb', line 11 def route_binding @route_binding end |
Instance Method Details
#payment_requirements(request) ⇒ Object
72 73 74 75 76 77 78 |
# File 'lib/mpp/methods/evm/charge_intent.rb', line 72 def payment_requirements(request) Mpp::X402::Server.to_payment_requirements( request, authorization: @authorization, max_timeout_seconds: @max_timeout_seconds ) end |
#verify(credential, request) ⇒ Object
21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 |
# File 'lib/mpp/methods/evm/charge_intent.rb', line 21 def verify(credential, request) payload = credential.payload unless payload.is_a?(Hash) && payload["type"] == "authorization" raise Mpp::VerificationError, "EVM authorization credentials are not supported for this challenge" end if request.dig("methodDetails", "splits") raise Mpp::VerificationFailedError.new(reason: "EVM authorization credentials do not support splits") end unless addresses_equal?(payload["to"], request["recipient"]) raise Mpp::VerificationFailedError.new(reason: "EVM authorization recipient mismatch") end unless payload["value"].to_s == request["amount"].to_s raise Mpp::VerificationFailedError.new(reason: "EVM authorization amount mismatch") end unless x402_credential?(credential) expected_nonce = Authorization.challenge_hash(credential.challenge) unless payload["nonce"].to_s.downcase == expected_nonce.downcase raise Mpp::VerificationFailedError.new(reason: "EVM authorization challenge hash mismatch") end end now = Time.now.to_i raise Mpp::VerificationFailedError.new(reason: "EVM authorization is not valid yet") if Integer(payload["validAfter"]) > now raise Mpp::VerificationFailedError.new(reason: "EVM authorization has expired") if Integer(payload["validBefore"]) <= now chain_id = request.dig("methodDetails", "chainId") raise Mpp::VerificationFailedError.new(reason: "EVM authorization requires chainId") if chain_id.nil? signer = Authorization.recover( authorization: @authorization, chain_id: chain_id, currency: request["currency"], payload: payload ) unless signer && addresses_equal?(signer, payload["from"]) raise Mpp::VerificationFailedError.new(reason: "EVM authorization signature mismatch") end checksummed_from = Authorization.checksum_address(payload["from"]) source = "did:pkh:eip155:#{chain_id}:#{checksummed_from}" if credential.source && credential.source != source raise Mpp::VerificationFailedError.new(reason: "EVM authorization source mismatch") end settled = settle(payload, request) Mpp::Receipt.success(settled.fetch("transaction"), method: "evm") end |