[PAY-01] Payment domain model, on-chain ID mapping & custody model decision - #1280
Merged
mftee merged 2 commits intoAug 21, 2026
Merged
Conversation
…el ADR - Create PaymentStatus enum mirroring on-chain EscrowStatus - Create Payment entity with UUID FK to shipments, bigint on-chain ID mapping - Add unique constraints on shipmentId and onChainShipmentId - Implement PaymentsService with getOrCreatePayment (lazy ID generation) - Register PaymentsModule in AppModule - Add TypeORM migration for payments table - Document hybrid custody model (non-custodial deposit + admin-arbitrated release) - Flag admin keypair centralization risk; outline multisig/timelock requirements for mainnet
|
@yusuftomilola is attempting to deploy a commit to the Mftee's projects Team on Vercel. A member of the Team first needs to authorize it. |
mftee
approved these changes
Aug 21, 2026
mftee
left a comment
Contributor
There was a problem hiding this comment.
Reviewed the PAY-01 payment domain model changes. The design is solid:
PaymentStatusenum cleanly mirrors the on-chainEscrowStatusstates with a sensible internal-onlyCancelledaddition.Paymententity's dual unique constraints (shipmentId + onChainShipmentId) correctly push double-creation protection down to the DB layer instead of relying on app-level checks alone.- Lazy on-chain ID generation via
getOrCreatePayment()avoids unnecessary backfill work for historical shipments — good call deferring that. - The custody-model ADR is a valuable addition, clearly documenting the admin keypair's blast radius and the hardening steps required before mainnet (multisig, timelock, audit trail, circuit breaker).
- No RPC/contract calls in this PR keeps the scope tight to the domain model foundation, as intended for PAY-01.
CI is green across Backend, Frontend, and Contracts. The Vercel status check failure is an unauthorized/unlinked deployment integration issue, unrelated to the code itself.
Approving — nice groundwork for the PAY-02 through PAY-06 issues that build on this.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
This PR implements the foundational payment domain model for the FrieghtFlow payment track (issue #1274).
What's included
PaymentStatusenum (backend/src/common/enums/payment-status.enum.ts) — mirrors the on-chainEscrowStatusvariants (Pending, Funded, Released, Refunded, Disputed) plus an internalCancelledstate.Paymententity (backend/src/payments/entities/payment.entity.ts) — TypeORM entity with UUID FK toshipments, bigintonChainShipmentIdfor deterministic UUID-to-u64 mapping, wallet addresses, timestamps, and unique constraints on bothshipmentIdandonChainShipmentId.PaymentsService(backend/src/payments/payments.service.ts) —getOrCreatePayment()lazily generates the on-chain ID on first funding attempt; DB unique constraint prevents double-creation on concurrent clicks. Lookup methods by shipment UUID or on-chain ID.PaymentsModule(backend/src/payments/payments.module.ts) — registered inAppModule.backend/src/migrations/1724140800000-CreatePaymentsTable.ts) — creates thepaymentstable with enum type, unique constraints, and foreign key toshipments.backend/docs/payments-custody-model.md) — documents the hybrid custody model (non-custodial deposit + admin-arbitrated release), the admin keypair's blast radius, and required hardening before mainnet (multisig, timelock, on-chain audit trail, circuit breaker).Design decisions
onChainShipmentIdis dense and collision-free, avoiding the fragility of truncating/hashing UUIDs.shipmentIdandonChainShipmentIdhave unique constraints; concurrent double-click failures are caught at the database layer, not just application logic.How later issues consume this model
Subsequent issues in the payment track (PAY-02 through PAY-06) will:
PaymentsService.getOrCreatePayment()to create payment records when escrow funding is initiatedfindByOnChainId()to resolve on-chain events back to backend payment recordsupdateStatus()to reflect on-chain state transitions (Funded, Released, Refunded, Disputed)Payment.shipperWalletAddressandPayment.carrierWalletAddressfor Soroban RPC callscloses #1274