Skip to content

feat(funding): explicit crypto-vs-fiat classification — paymentType + paymentRail knownValues#232

Open
s-adamantine wants to merge 1 commit into
mainfrom
feature/funding-receipt-payment-type
Open

feat(funding): explicit crypto-vs-fiat classification — paymentType + paymentRail knownValues#232
s-adamantine wants to merge 1 commit into
mainfrom
feature/funding-receipt-payment-type

Conversation

@s-adamantine

@s-adamantine s-adamantine commented Jul 7, 2026

Copy link
Copy Markdown
Contributor

What

Adds an explicit crypto-vs-fiat discriminator to org.hypercerts.funding.receipt:

  • New optional paymentType string, knownValues: ["crypto", "fiat"] — the asset-class discriminator. Absent/unrecognized ⇒ unclassified (never silently fiat).
  • paymentRail gains knownValues ["onchain", "payment_processor", "bank_transfer", "credit_card", "cash", "check"] — previously these existed only as prose examples, and e.g. certified.app's record-payment form is free-text, so ecosystem rail values were destined to diverge.
  • paymentNetwork description now distinguishes its two uses — the chain for onchain payments (strongly recommended: a tx hash is uninterpretable without its chain) vs the processor/scheme for fiat rails.

Non-breaking: new field optional, knownValues advisory. Changeset: minor.

Why

Ma Earth is publishing platform-authored funding receipts for donations across both fiat (Stripe/PayPal) and crypto (on-chain) rails — first records are live on the dev Certified network (receipts, each carrying a remote app.certified.signature.proof platform attestation). Consumers need to split crypto from fiat deterministically, and nothing on the current record can express it:

  • currency can't: platforms commonly record a normalized fiat-equivalent (amount: "100.00", currency: "USD") for an on-chain donation, and stablecoin payments carry fiat-pegged currencies either way.
  • paymentNetwork can't: optional, and classifying via it needs a maintained which-networks-are-chains registry in every consumer.
  • Free-string paymentRail can't: every consumer invents its own heuristic over uncontrolled vocabulary.

Design discussion — input wanted

We considered three shapes; this PR implements A. Happy to switch if reviewers prefer otherwise — now is the cheap moment to settle this: a scan of all three PDSes found only 5 funding.receipt records network-wide, 4 of them our own dev demo data and the 5th with no paymentRail at all, so there is no migration burden yet.

Option Shape Trade-off
A (this PR) Dedicated paymentType: crypto|fiat; paymentRail stays pure mechanism Explicit + orthogonal; can express card-funded crypto onramps (type: crypto, rail: credit_card); mild redundancy for the common case
B No new field; consumers infer crypto ⇔ paymentRail === "onchain" Zero schema growth, but the distinction everyone needs is implicit, and card-funded crypto is inexpressible
C paymentRail: "crypto" as a flat enum value alongside mechanisms (Stripe's payment_method.type precedent) One-field check, but mixes asset class and mechanism in one axis; same expressiveness gap as B

Arguments for A: a foundational lexicon should state the classification rather than have every consumer derive it; the two axes (what asset / how moved) are genuinely orthogonal; and the classification rule for consumers becomes a field read instead of a convention.

Related

Companion PR from the same integration solving the remaining modelling gaps (FX stamping, refund representation, transactionId privacy guidance): #233. The two are independent and can land in either order.

Checks

  • npm run check green (validate + gen + typecheck + build + 182 tests)
  • SCHEMAS.md regenerated; changeset included

Summary by CodeRabbit

  • New Features
    • Added an optional payment type field so receipts can be labeled as crypto or fiat.
    • Improved payment rail guidance with a clearer set of common values for easier selection in UIs.
    • Clarified payment network wording to better reflect blockchain versus traditional payment systems.
  • Documentation
    • Updated schema references to better explain how payment-related receipt details should be interpreted.

Add an explicit crypto-vs-fiat discriminator to
org.hypercerts.funding.receipt:

- New optional paymentType string, knownValues [crypto, fiat]. The
  amount/currency pair cannot express this (receipts often record
  normalized fiat-equivalent amounts for crypto payments; stablecoins
  carry fiat-pegged currencies), so the asset class needs an explicit
  field. Absent/unrecognized values classify as unclassified, not fiat.
- paymentType is orthogonal to paymentRail (mechanism): a card-funded
  crypto purchase is paymentType 'crypto' + paymentRail 'credit_card'.
- paymentRail gains knownValues [onchain, payment_processor,
  bank_transfer, credit_card, cash, check] (previously prose-only
  examples) so form UIs can offer a canonical vocabulary instead of
  free text.
- paymentNetwork description distinguishes chain (onchain) vs
  processor/scheme (fiat) uses and strongly recommends it for onchain
  payments (a tx hash is uninterpretable without its chain).

Non-breaking: new field optional; knownValues advisory; existing
receipts remain valid.
@changeset-bot

changeset-bot Bot commented Jul 7, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 9eeae49

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
@hypercerts-org/lexicon Minor

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@coderabbitai

coderabbitai Bot commented Jul 7, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

Adds an optional paymentType field (crypto/fiat) to the org.hypercerts.funding.receipt lexicon schema, expands paymentRail with an explicit knownValues list, revises paymentNetwork documentation, and updates SCHEMAS.md and a changeset accordingly.

Changes

Funding receipt paymentType discriminator

Layer / File(s) Summary
Lexicon schema update
lexicons/org/hypercerts/funding/receipt.json
Adds paymentType property with knownValues (crypto, fiat) and guidance against inferring asset class from amount/currency; adds knownValues list to paymentRail; expands paymentNetwork description to distinguish onchain vs fiat rail semantics.
Docs and changeset
SCHEMAS.md, .changeset/funding-receipt-payment-type.md
Updates the Properties table for org.hypercerts.funding.receipt to document paymentType and revised paymentRail/paymentNetwork descriptions; adds a changeset note describing the non-breaking schema enhancement.

Estimated code review effort: 1 (Trivial) | ~5 minutes

Possibly related issues

  • hypercerts-org/hypercerts-lexicon#231: Proposes the paymentType (crypto/fiat) discriminator that this PR implements in the receipt lexicon.

Possibly related PRs

Suggested reviewers: aspiers

🚥 Pre-merge checks | ✅ 5 | ❌ 2

❌ Failed checks (2 inconclusive)

Check name Status Explanation Resolution
Lexicon Documentation Sync ❓ Inconclusive Repository clone failed, so this custom check could not run with code access. Retry the review run. If this persists, inspect pre-merge custom-check logs for infrastructure or agent runtime failures.
Lexicons Styleguide Compliance ❓ Inconclusive Repository clone failed, so this custom check could not run with code access. Retry the review run. If this persists, inspect pre-merge custom-check logs for infrastructure or agent runtime failures.
✅ Passed checks (5 passed)
Check name Status Explanation
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the main change: adding explicit crypto-vs-fiat classification via paymentType and updating paymentRail known values.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feature/funding-receipt-payment-type

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In @.changeset/funding-receipt-payment-type.md:
- Line 11: Update the `paymentRail` changelog note to keep the wording advisory
rather than implying a closed set of allowed values. In
`.changeset/funding-receipt-payment-type.md`, revise the sentence around
`knownValues` so it says the listed rails provide a canonical vocabulary or
examples, while still allowing custom rail values; avoid language like “instead
of free-text input” that suggests consumers should reject unlisted rails.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 3a230b5c-9d96-44e7-bae6-8e8946a08f34

📥 Commits

Reviewing files that changed from the base of the PR and between 1e60c7f and 9eeae49.

📒 Files selected for processing (3)
  • .changeset/funding-receipt-payment-type.md
  • SCHEMAS.md
  • lexicons/org/hypercerts/funding/receipt.json


- New `paymentType` string with `knownValues: ["crypto", "fiat"]` — the explicit asset-class discriminator. Consumers classify by this field and treat receipts without it (or with an unrecognized value) as unclassified, never silently as fiat. The `amount`/`currency` pair cannot substitute: receipts often record normalized fiat-equivalent amounts for crypto payments, and stablecoins carry fiat-pegged currencies.
- `paymentType` is orthogonal to `paymentRail` (the transfer mechanism): a card-funded crypto purchase is `paymentType: "crypto"` + `paymentRail: "credit_card"`.
- `paymentRail` now declares `knownValues: ["onchain", "payment_processor", "bank_transfer", "credit_card", "cash", "check"]` (previously prose-only examples), giving form UIs a canonical vocabulary instead of free-text input.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Keep paymentRail wording advisory.

The lexicon still permits custom rail values, so this should not read as “instead of free-text input.” That phrasing can push consumers to reject valid non-listed rails.

Suggested wording
- `paymentRail` now declares `knownValues: ["onchain", "payment_processor", "bank_transfer", "credit_card", "cash", "check"]` (previously prose-only examples), giving form UIs a canonical vocabulary instead of free-text input.
+ `paymentRail` now declares `knownValues: ["onchain", "payment_processor", "bank_transfer", "credit_card", "cash", "check"]` (previously prose-only examples), giving form UIs a recommended vocabulary while still allowing custom values.
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
- `paymentRail` now declares `knownValues: ["onchain", "payment_processor", "bank_transfer", "credit_card", "cash", "check"]` (previously prose-only examples), giving form UIs a canonical vocabulary instead of free-text input.
`paymentRail` now declares `knownValues: ["onchain", "payment_processor", "bank_transfer", "credit_card", "cash", "check"]` (previously prose-only examples), giving form UIs a recommended vocabulary while still allowing custom values.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.changeset/funding-receipt-payment-type.md at line 11, Update the
`paymentRail` changelog note to keep the wording advisory rather than implying a
closed set of allowed values. In `.changeset/funding-receipt-payment-type.md`,
revise the sentence around `knownValues` so it says the listed rails provide a
canonical vocabulary or examples, while still allowing custom rail values; avoid
language like “instead of free-text input” that suggests consumers should reject
unlisted rails.

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