Skip to content

fix: type correctness issues, error body preservation, and get_did_document implementation#29

Open
Onyx2406 wants to merge 2 commits into
interledger:mainfrom
Onyx2406:fix/outgoing-payment-optional-spent-amounts
Open

fix: type correctness issues, error body preservation, and get_did_document implementation#29
Onyx2406 wants to merge 2 commits into
interledger:mainfrom
Onyx2406:fix/outgoing-payment-optional-spent-amounts

Conversation

@Onyx2406
Copy link
Copy Markdown

@Onyx2406 Onyx2406 commented Apr 3, 2026

Summary

Fixes five issues found by auditing the SDK against the Open Payments specification v1.3.0:

1. OutgoingPayment deserialization failure (bug)

grant_spent_debit_amount and grant_spent_receive_amount were required fields, but the spec only includes them in the outgoing-payment-with-spent-amounts variant (POST response). GET/LIST responses from a spec-compliant server would fail to deserialize because the server doesn't include these fields.

Fix: Changed both fields to Option<Amount>.

2. IncomingPaymentWithMethods duplicate fields (bug)

The struct used #[serde(flatten)] on IncomingPayment, but IncomingPayment already had an Option<Vec<PaymentMethod>> methods field. This produced duplicate methods keys in serialized JSON — undefined behavior in serde.

Fix: Replaced flatten with explicit fields.

3. AccessToken.access incorrectly optional (spec deviation)

The spec marks access as required on access_token, but the SDK made it Option<Vec<AccessItem>>.

Fix: Changed to Vec<AccessItem>.

4. HTTP error response body discarded (bug)

When the server returned 4xx/5xx, the response body was completely discarded. The Open Payments spec defines structured error responses with error codes and descriptions that are critical for debugging.

Fix: Read the response body, include it in the error description, and parse JSON error bodies into the details field.

5. get_did_document panics at runtime (bug)

The public method contained unimplemented!() which would crash the program when called.

Fix: Implemented as a GET request to {walletAddress}/did.json, returning serde_json::Value.

Test plan

  • All 16 unit tests pass
  • All 10 client request tests pass
  • All 19 type roundtrip tests pass (updated to match new types)
  • Zero clippy warnings

Onyx2406 added 2 commits April 3, 2026 07:32
Fix several bugs found by auditing the SDK against the Open Payments
specification (v1.3.0):

1. OutgoingPayment: grant_spent_debit_amount and
   grant_spent_receive_amount are now Option<Amount>. The spec only
   includes these in the "with-spent-amounts" variant (POST response),
   not in GET/LIST responses. Previously, deserializing a GET response
   would fail at runtime because the server wouldn't include these
   fields.

2. IncomingPaymentWithMethods: removed #[serde(flatten)] on
   IncomingPayment to fix duplicate "methods" field in serialized
   output. IncomingPayment already had an optional methods field,
   causing undefined serde behavior with duplicate JSON keys.

3. AccessToken.access: changed from Option<Vec<AccessItem>> to
   Vec<AccessItem> to match the spec which marks "access" as required.

4. HTTP error responses: the response body is now read and included
   in the error. Previously, 4xx/5xx responses discarded the body
   entirely, making it impossible to see server error details.
   Structured JSON error bodies are parsed into the error's details
   field.

5. get_did_document: implemented the previously unimplemented public
   API method that would panic at runtime. Now correctly fetches
   the DID document from {walletAddress}/did.json.
- Add test for OutgoingPayment deserialization without grant spent
  amounts (the core bug this PR fixes — GET responses omit these)
- Add test for OutgoingPayment deserialization WITH grant spent
  amounts (POST responses include them)
- Add test verifying AccessToken requires the access field
  (deserialization fails when absent, matching the spec)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant