@hyperscale0/hsx 2.4.0 → 3.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (249) hide show
  1. package/CHANGELOG.md +2 -400
  2. package/README.md +3 -92
  3. package/dist/src/ast.d.ts +99 -310
  4. package/dist/src/ast.d.ts.map +1 -1
  5. package/dist/src/ast.js +16 -69
  6. package/dist/src/ast.js.map +1 -1
  7. package/dist/src/cli.d.ts +6 -19
  8. package/dist/src/cli.d.ts.map +1 -1
  9. package/dist/src/cli.js +76 -315
  10. package/dist/src/cli.js.map +1 -1
  11. package/dist/src/compile.d.ts +23 -73
  12. package/dist/src/compile.d.ts.map +1 -1
  13. package/dist/src/compile.js +1113 -148
  14. package/dist/src/compile.js.map +1 -1
  15. package/dist/src/cost.d.ts +8 -77
  16. package/dist/src/cost.d.ts.map +1 -1
  17. package/dist/src/cost.js +13 -422
  18. package/dist/src/cost.js.map +1 -1
  19. package/dist/src/format.d.ts +8 -7
  20. package/dist/src/format.d.ts.map +1 -1
  21. package/dist/src/format.js +9 -175
  22. package/dist/src/format.js.map +1 -1
  23. package/dist/src/headers.d.ts +35 -0
  24. package/dist/src/headers.d.ts.map +1 -0
  25. package/dist/src/headers.js +108 -0
  26. package/dist/src/headers.js.map +1 -0
  27. package/dist/src/index.d.ts +6 -12
  28. package/dist/src/index.d.ts.map +1 -1
  29. package/dist/src/index.js +4 -9
  30. package/dist/src/index.js.map +1 -1
  31. package/dist/src/lex.d.ts +8 -28
  32. package/dist/src/lex.d.ts.map +1 -1
  33. package/dist/src/lex.js +88 -146
  34. package/dist/src/lex.js.map +1 -1
  35. package/dist/src/parse.d.ts +4 -17
  36. package/dist/src/parse.d.ts.map +1 -1
  37. package/dist/src/parse.js +402 -1040
  38. package/dist/src/parse.js.map +1 -1
  39. package/dist/src/std-bundle.d.ts.map +1 -1
  40. package/dist/src/std-bundle.js +12 -20
  41. package/dist/src/std-bundle.js.map +1 -1
  42. package/dist/src/std-library.d.ts +1 -1
  43. package/dist/src/std-library.d.ts.map +1 -1
  44. package/dist/src/std-library.js +1 -5
  45. package/dist/src/std-library.js.map +1 -1
  46. package/dist/src/tunables.d.ts +7 -0
  47. package/dist/src/tunables.d.ts.map +1 -0
  48. package/dist/src/tunables.js +26 -0
  49. package/dist/src/tunables.js.map +1 -0
  50. package/dist/src/version.d.ts +2 -4
  51. package/dist/src/version.d.ts.map +1 -1
  52. package/dist/src/version.js +2 -4
  53. package/dist/src/version.js.map +1 -1
  54. package/docs/README.md +179 -41
  55. package/docs/headers.md +44 -0
  56. package/examples/cost-table.json +99 -751
  57. package/examples/library.hsx +59 -0
  58. package/package.json +9 -17
  59. package/src/ast.ts +82 -441
  60. package/src/cli.ts +77 -362
  61. package/src/compile.ts +1535 -247
  62. package/src/cost.ts +28 -671
  63. package/src/format.ts +12 -256
  64. package/src/headers.ts +126 -0
  65. package/src/index.ts +7 -39
  66. package/src/lex.ts +99 -195
  67. package/src/parse.ts +403 -1209
  68. package/src/std-bundle.ts +12 -20
  69. package/src/std-library.ts +2 -7
  70. package/src/tunables.ts +31 -0
  71. package/src/version.ts +2 -5
  72. package/std/approvals.hsx +17 -0
  73. package/std/cards.hsx +63 -0
  74. package/std/collections.hsx +31 -0
  75. package/std/escrow.hsx +43 -0
  76. package/std/financing.hsx +372 -0
  77. package/std/insurance.hsx +59 -0
  78. package/std/lending.hsx +115 -0
  79. package/std/marketplace.hsx +24 -0
  80. package/std/money.hsx +195 -0
  81. package/std/savings.hsx +44 -0
  82. package/std/travel.hsx +98 -0
  83. package/std/wallet.hsx +41 -0
  84. package/dist/src/diagnostics.d.ts +0 -13
  85. package/dist/src/diagnostics.d.ts.map +0 -1
  86. package/dist/src/diagnostics.js +0 -587
  87. package/dist/src/diagnostics.js.map +0 -1
  88. package/dist/src/emit.d.ts +0 -51
  89. package/dist/src/emit.d.ts.map +0 -1
  90. package/dist/src/emit.js +0 -192
  91. package/dist/src/emit.js.map +0 -1
  92. package/dist/src/entry-overrides.d.ts +0 -58
  93. package/dist/src/entry-overrides.d.ts.map +0 -1
  94. package/dist/src/entry-overrides.js +0 -284
  95. package/dist/src/entry-overrides.js.map +0 -1
  96. package/dist/src/ir.d.ts +0 -73
  97. package/dist/src/ir.d.ts.map +0 -1
  98. package/dist/src/ir.js +0 -15
  99. package/dist/src/ir.js.map +0 -1
  100. package/dist/src/limits.d.ts +0 -23
  101. package/dist/src/limits.d.ts.map +0 -1
  102. package/dist/src/limits.js +0 -23
  103. package/dist/src/limits.js.map +0 -1
  104. package/dist/src/lsp/server.d.ts +0 -32
  105. package/dist/src/lsp/server.d.ts.map +0 -1
  106. package/dist/src/lsp/server.js +0 -391
  107. package/dist/src/lsp/server.js.map +0 -1
  108. package/dist/src/modules.d.ts +0 -38
  109. package/dist/src/modules.d.ts.map +0 -1
  110. package/dist/src/modules.js +0 -372
  111. package/dist/src/modules.js.map +0 -1
  112. package/dist/src/typecheck.d.ts +0 -8
  113. package/dist/src/typecheck.d.ts.map +0 -1
  114. package/dist/src/typecheck.js +0 -4131
  115. package/dist/src/typecheck.js.map +0 -1
  116. package/docs/guide/01-first-program.md +0 -24
  117. package/docs/guide/02-money.md +0 -25
  118. package/docs/guide/03-instruments.md +0 -93
  119. package/docs/guide/04-lifecycles.md +0 -40
  120. package/docs/guide/05-fees-and-splits.md +0 -45
  121. package/docs/guide/06-schedules.md +0 -26
  122. package/docs/guide/07-composition.md +0 -52
  123. package/docs/guide/08-writing-a-module.md +0 -85
  124. package/docs/guide/09-cost.md +0 -24
  125. package/docs/guide/10-diagnostics.md +0 -27
  126. package/docs/llms-full.txt +0 -3684
  127. package/docs/llms.txt +0 -44
  128. package/docs/piece-plans.md +0 -120
  129. package/docs/playground.md +0 -55
  130. package/docs/reference/cli.md +0 -36
  131. package/docs/reference/diagnostics.md +0 -901
  132. package/docs/reference/grammar.md +0 -38
  133. package/docs/reference/std/advance.md +0 -112
  134. package/docs/reference/std/cancellable_booking.md +0 -159
  135. package/docs/reference/std/captured_payment.md +0 -115
  136. package/docs/reference/std/conditional_disbursement.md +0 -101
  137. package/docs/reference/std/credit_facility.md +0 -108
  138. package/docs/reference/std/held_payment.md +0 -173
  139. package/docs/reference/std/instant_transfer.md +0 -97
  140. package/docs/reference/std/metered.md +0 -89
  141. package/docs/reference/std/pooled_split.md +0 -95
  142. package/docs/reference/std/premium_forward.md +0 -119
  143. package/docs/reference/std/reconciled_payout.md +0 -103
  144. package/docs/reference/std/rotating_pool.md +0 -130
  145. package/docs/reference/std/scheduled.md +0 -136
  146. package/docs/reference/std/security_deposit.md +0 -138
  147. package/docs/reference/std/settlement_batch.md +0 -123
  148. package/docs/reference/std/swap.md +0 -133
  149. package/docs/reference/std/threshold_pool.md +0 -138
  150. package/docs/reference/std/weighted_distribution.md +0 -135
  151. package/docs/reference/types.md +0 -61
  152. package/docs/reference/udl-output.md +0 -13
  153. package/examples/01-first-program/README.md +0 -45
  154. package/examples/01-first-program/tip-jar.hsx +0 -17
  155. package/examples/02-imports-and-modules/README.md +0 -96
  156. package/examples/02-imports-and-modules/photo-booth.hsx +0 -37
  157. package/examples/03-diagnostics/README.md +0 -68
  158. package/examples/03-diagnostics/corner-shop-fixed.hsx +0 -22
  159. package/examples/03-diagnostics/corner-shop.hsx +0 -19
  160. package/examples/04-complete-product/README.md +0 -84
  161. package/examples/04-complete-product/study-hall.hsx +0 -67
  162. package/examples/05-authored-instrument/README.md +0 -5
  163. package/examples/05-authored-instrument/payment.hsx +0 -37
  164. package/examples/05-watch-club/README.md +0 -6
  165. package/examples/05-watch-club/watch-club.hsx +0 -123
  166. package/examples/README.md +0 -48
  167. package/examples/advance/README.md +0 -3
  168. package/examples/advance/advance.hsx +0 -13
  169. package/examples/advance/advance.udl +0 -367
  170. package/examples/cancellable_booking/README.md +0 -3
  171. package/examples/cancellable_booking/cancellable_booking.hsx +0 -14
  172. package/examples/cancellable_booking/cancellable_booking.udl +0 -413
  173. package/examples/captured_payment/README.md +0 -3
  174. package/examples/captured_payment/captured_payment.hsx +0 -17
  175. package/examples/captured_payment/captured_payment.udl +0 -686
  176. package/examples/conditional_disbursement/README.md +0 -3
  177. package/examples/conditional_disbursement/conditional_disbursement.hsx +0 -15
  178. package/examples/conditional_disbursement/conditional_disbursement.udl +0 -418
  179. package/examples/credit_facility/README.md +0 -3
  180. package/examples/credit_facility/credit_facility.hsx +0 -24
  181. package/examples/credit_facility/credit_facility.udl +0 -1396
  182. package/examples/held_payment/README.md +0 -3
  183. package/examples/held_payment/held_payment.hsx +0 -13
  184. package/examples/held_payment/held_payment.udl +0 -569
  185. package/examples/instant_transfer/README.md +0 -3
  186. package/examples/instant_transfer/instant_transfer.hsx +0 -16
  187. package/examples/instant_transfer/instant_transfer.udl +0 -376
  188. package/examples/metered/README.md +0 -3
  189. package/examples/metered/metered.hsx +0 -13
  190. package/examples/metered/metered.udl +0 -253
  191. package/examples/pooled_split/README.md +0 -3
  192. package/examples/pooled_split/pooled_split.hsx +0 -15
  193. package/examples/pooled_split/pooled_split.udl +0 -432
  194. package/examples/premium_forward/README.md +0 -3
  195. package/examples/premium_forward/premium_forward.hsx +0 -19
  196. package/examples/premium_forward/premium_forward.udl +0 -604
  197. package/examples/reconciled_payout/README.md +0 -3
  198. package/examples/reconciled_payout/reconciled_payout.hsx +0 -13
  199. package/examples/reconciled_payout/reconciled_payout.udl +0 -312
  200. package/examples/rotating_pool/README.md +0 -3
  201. package/examples/rotating_pool/rotating_pool.hsx +0 -18
  202. package/examples/rotating_pool/rotating_pool.udl +0 -4370
  203. package/examples/scheduled/README.md +0 -3
  204. package/examples/scheduled/scheduled.hsx +0 -12
  205. package/examples/scheduled/scheduled.udl +0 -355
  206. package/examples/security_deposit/README.md +0 -3
  207. package/examples/security_deposit/security_deposit.hsx +0 -21
  208. package/examples/security_deposit/security_deposit.udl +0 -320
  209. package/examples/settlement_batch/README.md +0 -3
  210. package/examples/settlement_batch/settlement_batch.hsx +0 -19
  211. package/examples/settlement_batch/settlement_batch.udl +0 -757
  212. package/examples/swap/README.md +0 -3
  213. package/examples/swap/swap.hsx +0 -19
  214. package/examples/swap/swap.udl +0 -892
  215. package/examples/threshold_pool/README.md +0 -3
  216. package/examples/threshold_pool/threshold_pool.hsx +0 -16
  217. package/examples/threshold_pool/threshold_pool.udl +0 -680
  218. package/examples/weighted_distribution/README.md +0 -3
  219. package/examples/weighted_distribution/weighted_distribution.hsx +0 -20
  220. package/examples/weighted_distribution/weighted_distribution.udl +0 -348
  221. package/skills/hsx/SKILL.md +0 -449
  222. package/src/diagnostics.ts +0 -620
  223. package/src/emit.ts +0 -282
  224. package/src/entry-overrides.ts +0 -428
  225. package/src/ir.ts +0 -113
  226. package/src/limits.ts +0 -22
  227. package/src/lsp/server.ts +0 -460
  228. package/src/modules.ts +0 -452
  229. package/src/typecheck.ts +0 -5381
  230. package/std/SEMANTICS.md +0 -44
  231. package/std/money_flows/advance.hsx +0 -235
  232. package/std/money_flows/cancellable_booking.hsx +0 -402
  233. package/std/money_flows/captured_payment.hsx +0 -220
  234. package/std/money_flows/conditional_disbursement.hsx +0 -226
  235. package/std/money_flows/credit_facility.hsx +0 -214
  236. package/std/money_flows/held_payment.hsx +0 -812
  237. package/std/money_flows/index.hsx +0 -4
  238. package/std/money_flows/instant_transfer.hsx +0 -231
  239. package/std/money_flows/metered.hsx +0 -104
  240. package/std/money_flows/pooled_split.hsx +0 -109
  241. package/std/money_flows/premium_forward.hsx +0 -307
  242. package/std/money_flows/reconciled_payout.hsx +0 -119
  243. package/std/money_flows/rotating_pool.hsx +0 -305
  244. package/std/money_flows/scheduled.hsx +0 -599
  245. package/std/money_flows/security_deposit.hsx +0 -248
  246. package/std/money_flows/settlement_batch.hsx +0 -173
  247. package/std/money_flows/swap.hsx +0 -1192
  248. package/std/money_flows/threshold_pool.hsx +0 -307
  249. package/std/money_flows/weighted_distribution.hsx +0 -237
package/std/SEMANTICS.md DELETED
@@ -1,44 +0,0 @@
1
- # Standard library money flows semantics
2
-
3
- This document records the runtime semantics and settlement mechanics of standard library modules under `std.money_flows`. The compiler and its unit specifications under `test/` remain the authoritative implementation reference.
4
-
5
- ## Direct checkout and card
6
-
7
- - `instant_transfer` stores the amount, currency, payer, and payee. Action `create` opens the payment record without moving funds. Action `pay_piece_1` and subsequent piece actions execute the money movements, transitioning to state `paid`. A payer fee executes as an `on_top` move. A payee fee carves out of the base amount. Exact, basis-point, and tiered rules generate fee fields and `feeRules`. The finest common refinement of all fee cuts produces piece fields and one partition. Floor rounding sends minor-unit remainder to the designated non-fee recipient. A derived amount adds a floor percentage field, `derivedAmounts`, a platform party account, and its own transfer piece.
8
- - `captured_payment` stores authorization total, reserve and reversal dates, and party accounts. The instrument moves through `created`, `authorized`, optional `partially_captured`, `settled`, `voided`, `expired`, `corrected`, or `reversed`. Action `authorize` reserves custody on the payer balance. Actions `capture` and `capture_more` consume the authorized balance using partial posts. Action `settle` posts the captured amount. Actions `void` and `expire` release the reserve. Actions for payee correction and external reversal use their declared condition ports and deadline windows. Derived fees use the same floor, partition, bearer, and position rules as direct payment. Four unused signature knobs (`capture_mode`, `correction_mode`, `negative_position`, `timeout`) are pruned.
9
-
10
- ## Custody and escrow
11
-
12
- - `held_payment` reserves every refined piece in a dedicated escrow account before release. It posts release pieces, voids cancellation pieces, and keeps payer service fees outside the held principal. Release and cancellation fee sides share the finest common partition, so each stored piece has one release recipient and one cancel recipient. States track funding, release, cancellation, and abandonment steps. Abandonment refunds every still-held piece. A deadline release and a caller decision release carry the named date or port clause. Retention forms reserve one held piece with a release deadline and cancellation back to the contractor. Whole-amount mode funds principal and on-top fees in one action, then releases or cancels the principal whole. Quoted cancellation uses `cancel_charge_bps` and `cancel_offer_life` to freeze penalty quotes before confirm and retain actions.
13
- - `cancellable_booking` holds booking funds in escrow away from guest and host until the booking ends or cancels. Cancellation quotes a penalty against the time remaining before `starts_at`, frozen for `offer_life`. Lifecycle moves through `created`, `held`, `cancellation_quoted`, `canceled`, `settled`, and `completed`. Penalty retention moves penalty funds to host and remainder to guest; completion releases full amount to host.
14
- - `security_deposit` reserves the full deposit amount in escrow. A claim port posts either the whole hold or an externally decided amount bounded by the hold. The explicit remainder returns to the payer. A return port voids the whole hold. The deadline form adds machine expiry and unfunded cancellation.
15
- - `premium_forward` holds premium pieces in escrow, then forwards net pieces after a carrier bind decision. It can abandon unbound custody. Policy reference, renewal due, endorsement evidence, and lapse actions activate when declared. Fee partition and floor remainder rules match `held_payment`.
16
-
17
- ## Subscriptions, usage, and schedules
18
-
19
- - `scheduled` executes calendar-anchored payment series between one payer and one payee across three operational modes:
20
- 1. Finite installment plan: Stores total, first due date, and one money field per installment. The caller supplies each piece; a partition checks their sum, not equality. States and actions unroll in order with cumulative duration offsets.
21
- 2. Open recurring subscription: Charges a recurring amount on interval `every` until an `until` port fires, opening one period liability at a time.
22
- 3. Debt obligation: Emits a parent obligation plus one child payment instrument per installment. The parent stores principal, delinquency dates, party accounts, and aggregate invariants. Child instruments bind parent fields, repay against installment caps, and support full refunds. Finite obligation count generalization applies without grace periods.
23
- - `metered` stores one money field for each declared meter in its rate card and a period end date. Each usage charge executes an immediate transfer directly from payer to payee without escrow custody. Closing the period transitions state to `closed` at `close_by` and makes further charges unreachable.
24
-
25
- ## Lending and credit
26
-
27
- - `advance` provides upfront capital disbursed to a recipient and repaid through two distinct modes:
28
- 1. Carved advance: References an active escrow hold and recourse instrument through `against`. It disburses once and settles from the referenced release without minting new value. In this mode, the `fee` parameter is ignored.
29
- 2. Scheduled advance: Stores advance amount, fee amount, repayable total, first due date, and one repayment field per installment. A supplied `fee` derives feeAmount as a floor percentage of principal. The caller supplies principal, repayable total and repayment pieces, which partitions reconcile. `repayment_source` can differ from the capital recipient. `profit_to` splits each collection between principal returned to the funder and profit paid to its recipient. `dated: true` requires one stored signed due date per repayment. Equality, chronological ordering, partial servicing and arrears are not implied by those partitions.
30
- - `credit_facility` stores lender, borrower, draw destination, credit limit, currency, and expiry date. The facility transitions across `active`, `frozen`, and `closed`. Each draw creates a child instrument with draw amount, facility reference, and obligation reference. Draw admission checks facility active state and aggregate child exposure against the limit. Closure requires all child draws to reach status `resolved`. Unused signature knobs (`availability_policy`, `expiry_policy`, `close_policy`) are pruned.
31
- - `conditional_disbursement` emits a submitted parent instrument with cap, currency, source account, destination account, and decision port. Denial terminates the parent before child approvals. Child approval instruments store externally bounded amounts. Child actions capture port input, move through `created`, `approved`, and `paid`, and verify aggregate child exposure against the parent cap. Unused signature knobs (`reopen_policy`, `recovery_policy`) are pruned.
32
-
33
- ## Multi-party distributions and pooling
34
-
35
- - `pooled_split` stores pool total, due date, and one share amount and account per recipient. Positive shares total exactly 10,000 basis points. Floor division assigns each share, and the designated remainder recipient absorbs minor-unit residues. Funding and distribution actions execute in roster order.
36
- - `weighted_distribution` emits a parent distribution instrument and child entitlement instruments. The parent stores source account, total amount, record date, and maximum recipient count. Child rows store recipient, weight, source, currency, and parent reference. A largest-remainder distribution algorithm pays children once. Aggregate clauses cap and total child records against the pool.
37
- - `threshold_pool` emits a pool parent instrument and child commitment instruments. The parent stores target amount, close date, maximum contributors, beneficiary, and currency. It transitions through `open`, `active`, `failed`, or `settled` based on aggregate commitment gates. Each commitment can cancel before collection, collect into the pool, or refund after campaign failure.
38
- - `rotating_pool` emits a parent pool instrument plus one contribution child instrument per member. The parent unrolls active and ready states for every cycle and checks that each member row exists exactly once. Member child instruments unroll due, funded, defaulted, guaranteed, paid, and completed states for every cycle. A funded or guaranteed contribution pays the fixed beneficiary for that cycle. Final closure requires the escrow balance to drain to zero.
39
-
40
- ## Bilateral exchange, clearing, and reconciliation
41
-
42
- - `swap` stores amounts, accounts, fees, currency, and optional clawback dates for both sides. Funding is atomic across both sides. Release, settlement, cancellation, dispute, abandonment, and clawback preserve the two-sided conservation group. Side fees retain their declared bearer and position. Unwind refunds each side and applies declared penalty tiers without altering principal partitions.
43
- - `settlement_batch` emits a batch instrument alongside capture, credit-adjustment, and debit-adjustment child records. The batch stores close time, settlement and payout accounts, beneficiary reference, and currency. Closure freezes intake. Calculation applies signed arithmetic across capture, fee, and reversal entries. Actions instruct, acknowledge, and reconcile through the declared payout port.
44
- - `reconciled_payout` instructs an external payout with a tolerance window, waits for a matching bank debit statement line, and tracks unmatched amounts at settlement date as break rows. Lifecycle transitions through `created`, `instructed`, and `settled`.
@@ -1,235 +0,0 @@
1
- module std.money_flows.advance
2
-
3
- // Upfront capital disbursement repaid by carving future held payment releases or over scheduled installments.
4
- //
5
- // ### Purpose
6
- // `advance` provides working capital, merchant cash advances, or contractor pre-funding from a funder to a recipient.
7
- // Repayment occurs either automatically by intercepting (carving) releases from a linked escrow hold (`against`),
8
- // or over calendar-anchored installment repayments (`count`, `every`, `first_due`).
9
- //
10
- // ### Selection guidance
11
- // - vs `credit_facility`: `advance` disburses a single upfront lump-sum principal that is repaid over time.
12
- // `credit_facility` establishes a reusable revolving credit line with multiple draws up to a limit,
13
- // where repayments restore available borrowing capacity.
14
- // - vs `conditional_disbursement`: `advance` expects repayment of the advanced principal plus optional fees.
15
- // `conditional_disbursement` disburses non-repayable grants, claims, or milestone payments against external evidence.
16
- // - vs `held_payment`: `held_payment` holds customer funds in escrow until delivery. An `advance` can carve repayments
17
- // directly out of a `held_payment`'s release using `against`.
18
- //
19
- // ### Parameters
20
- // - `funder`: The party providing the upfront capital.
21
- // - `to`: The party receiving the advance and responsible for repayment.
22
- // - `amount`: Total advanced principal in minor units of currency `C`.
23
- // - `fee`: Optional markup percentage fee charged on the advance (basis points precision).
24
- // - `count`: Optional number of scheduled installment repayments.
25
- // - `every`: Optional recurrence duration between installments (e.g. `"P30D"`).
26
- // - `first_due`: Optional date for the first installment repayment.
27
- // - `repayment_source`: Optional party repaying when distinct from the capital recipient.
28
- // - `profit_to`: Optional recipient of profit, separated from principal repayments.
29
- // - `dated`: Require an explicit signed date for each repayment instead of duration offsets.
30
- // - `against`: Optional reference to a hold instrument whose release will be carved to repay the advance.
31
- //
32
- // ### Decision ports
33
- // None. Repayment is driven by linked hold releases or scheduled calendar dates.
34
- //
35
- // ### Example
36
- // ```hsx
37
- // program advance_example "Advance example"
38
- // import { advance } from "std/money_flows"
39
- // party funder: business
40
- // party recipient: business
41
- // settlement advance_payment = advance {
42
- // funder: funder
43
- // to: recipient
44
- // amount: principal: money(SAR)
45
- // fee: 2.5%
46
- // count: 2
47
- // every: P30D
48
- // first_due: firstDueAt
49
- // }
50
- // ```
51
- export instrument advance<C>(
52
- funder: party,
53
- to: party,
54
- amount: money<C>,
55
- fee: optional<percent>,
56
- count: optional<integer>,
57
- every: optional<text>,
58
- first_due: optional<date>,
59
- against: optional<ref>,
60
- repayment_source: optional<party>,
61
- profit_to: optional<party>,
62
- dated: optional<boolean>,
63
- ) {
64
- let(amount_path): concat("fields.", amount);
65
- let(currency_path): "fields.currency";
66
- let(funder_field): camel(concat(funder, "_account_id"));
67
- let(to_field): camel(concat(to, "_account_id"));
68
-
69
- agent_description: "Reach for advance when the {funder} pays the {to} up front and is repaid afterwards, either out of a carved hold release or over scheduled repayments. Pick deposit for a refundable reservation and instant transfer when nobody repays the payer.";
70
- title: sentence(instrument);
71
- id_prefix: prefix(instrument);
72
- parties {
73
- payer: funder;
74
- beneficiary: to;
75
- when(repayment_source) { repayment: repayment_source; }
76
- when(profit_to) { profit: profit_to; }
77
- }
78
-
79
- when(against) {
80
- let(hold_name): owner(against);
81
- summary: "Advance to the {to} repaid by carving the {hold_name} release";
82
- description: "Advance: the {funder} disburses {amount} to the {to} and is repaid out of the {hold_name} release, which pays the {funder} in the {to}'s place";
83
- fields {
84
- amount {
85
- type: money<C>;
86
- description: "The advanced amount in {C} minor units, disbursed to the {to} up front";
87
- }
88
- carve_hold_id {
89
- type: ref<hold_name>;
90
- description: "The {hold_name} bound to this advance";
91
- pattern: concat("^", prefix(hold_name), "_(sandbox|live)_[a-z0-9]{8,64}$");
92
- }
93
- carve_recourse_1_id {
94
- type: ref<recourse>;
95
- description: "The recourse bound to this advance";
96
- pattern: "^reco_(sandbox|live)_[a-z0-9]{8,64}$";
97
- }
98
- }
99
- required: [to_field, funder_field, amount, carveHoldId, carveRecourse1Id, currency];
100
- lifecycle {
101
- states created advanced repaid;
102
- initial created;
103
- on disburse: created -> advanced;
104
- on settle: advanced -> repaid;
105
- }
106
- action create {
107
- agent_description: "Open the advance row before any money moves. The caller supplies the {amount}, both party accounts, and the ids of the {hold_name} and the recourse that back repayment. Nothing is disbursed here.";
108
- summary: concat("Create a ", words(instrument));
109
- steps: [];
110
- moves: [];
111
- }
112
- action disburse {
113
- agent_description: "Pay the {amount} from the {funder} to the {to}. The advance must be created, the bound {hold_name} funded, and the recourse active, both matching this amount and currency. The transfer posts straight out and does not unwind.";
114
- summary: "Disburse the {amount} to the {to}";
115
- requires refs: [{
116
- field: carveHoldId;
117
- match: {
118
- [currency_path]: currency_path;
119
- [amount_path]: amount_path;
120
- };
121
- statuses: [funded];
122
- }, {
123
- field: carveRecourse1Id;
124
- match: {
125
- [currency_path]: currency_path;
126
- [amount_path]: amount_path;
127
- };
128
- statuses: [active];
129
- }];
130
- moves: [{ amount: amount; from: payer; to: beneficiary; key: transfer; operation: create; }];
131
- steps: [];
132
- }
133
- action settle {
134
- agent_description: "Close the advance once the {hold_name} has released to the {funder} in the {to}'s place. The advance must already be disbursed. No money moves here, the release did the repaying.";
135
- summary: concat("Close the advance once the ", hold_name, " has released to the ", funder);
136
- steps: [];
137
- moves: [];
138
- }
139
- }
140
-
141
- when_not(against) {
142
- let(repayment_role): if_eq(repayment_source, false, "beneficiary", "repayment");
143
- when(fee) { computes derived: { field: feeAmount; source_field: amount; rule: { kind: percentage_of; bps: basis_points(fee); }; rounding: floor; }; }
144
- let(repayment_fields): names("repayment", count, "Amount");
145
- let(first_target): if_eq(count, 1, "repaid", "repaying_1");
146
- let(states_key): "states";
147
- let(first_due_field): camel(first_due);
148
- summary: concat("Advance to ", to, " repaid over ", count, " anchors");
149
- description: concat("Advance: the ", funder, " disburses ", amount, " to the ", to, ", repaid over ", count, " scheduled repayments plus the funder's discount");
150
- fields {
151
- amount {
152
- type: money<C>;
153
- description: "The advanced amount in {C} minor units, disbursed to the {to} up front";
154
- }
155
- fee_amount {
156
- type: money<C>;
157
- when(fee) { optional: true; allow_zero: true; }
158
- description: concat(fee, " of ", amount, ", the funder's discount repaid on top of the advance");
159
- }
160
- repayable_amount {
161
- type: money<C>;
162
- description: concat(amount, " + feeAmount: the total the repayment fields below partition exactly");
163
- }
164
- [first_due_field] {
165
- type: date;
166
- description: concat("Due date of the first repayment; repayment k falls ", every, " after its predecessor");
167
- }
168
- for i in count {
169
- repayment[i]Amount { type: money<C>; description: "Stored total for repayment {i}"; }
170
- when(profit_to) {
171
- repayment[i]Principal { type: money<C>; description: "Principal returned to the funder by repayment {i}"; }
172
- repayment[i]Profit { type: money<C>; description: "Profit paid to the named recipient by repayment {i}"; }
173
- }
174
- when(dated) { repayment[i]DueAt { type: date; description: "Signed calendar due date for repayment {i}"; } }
175
- }
176
- }
177
- lifecycle {
178
- states created advanced;
179
- [states_key]: [first_target];
180
- initial created;
181
- on disburse: created -> advanced;
182
- on collect_repayment_1: advanced -> [first_target];
183
- for repayment in sub(count, 1) {
184
- let(index): add(repayment, 1);
185
- let(previous): concat("repaying_", repayment);
186
- let(target): if_eq(index, count, "repaid", concat("repaying_", index));
187
- [states_key]: [target];
188
- on collect_repayment_[index]: [previous] -> [target];
189
- }
190
- }
191
- partitions: [{
192
- piece_fields: repayment_fields;
193
- total_field: repayableAmount;
194
- }, {
195
- piece_fields: [amount, feeAmount];
196
- total_field: repayableAmount;
197
- }];
198
- when(profit_to) {
199
- partitions: { total_field: amount; piece_fields: names("repayment", count, "Principal"); };
200
- partitions: { total_field: feeAmount; piece_fields: names("repayment", count, "Profit"); };
201
- for i in count {
202
- partitions: { total_field: concat("repayment", i, "Amount"); piece_fields: [concat("repayment", i, "Principal"), concat("repayment", i, "Profit")]; };
203
- }
204
- }
205
- action create {
206
- agent_description: "Open the advance row before any money moves. The caller supplies the {amount}, the repayable total, and repayment dates. A declared fee derives the fee amount from principal. The repayment fields must partition the repayable total exactly. Nothing is disbursed here.";
207
- summary: concat("Create a ", words(instrument));
208
- steps: [];
209
- moves: [];
210
- }
211
- action disburse {
212
- agent_description: "Pay the {amount} from the {funder} to the {to} and start the repayment schedule. The advance must be created. The transfer posts straight out and does not unwind. Each repayment is collected on its own stored date anchor.";
213
- summary: "Disburse the {amount} to the {to}";
214
- moves: [{ amount: amount; from: payer; to: beneficiary; key: transfer; operation: create; }];
215
- steps: [];
216
- }
217
- for i in count {
218
- let(repayment_field): concat("repayment", i, "Amount");
219
- action collect_repayment_[i] {
220
- agent_description: "Collect repayment {i} once on its stored due anchor, returning principal to the funder and any separately routed profit to its recipient.";
221
- summary: "Collect repayment {i} of {count}";
222
- when(dated) { due: { field: concat("repayment", i, "DueAt"); }; }
223
- when_not(dated) { due: { field: first_due_field; offset: scale_duration(every, sub(i, 1)); }; }
224
- when_not(profit_to) { moves: [{ amount: repayment_field; from: repayment_role; to: payer; key: transfer; }]; }
225
- when(profit_to) {
226
- moves: [
227
- { amount: concat("repayment", i, "Principal"); from: repayment_role; to: payer; key: principal; },
228
- { amount: concat("repayment", i, "Profit"); from: repayment_role; to: profit; key: profit; }
229
- ];
230
- }
231
- steps: [];
232
- }
233
- }
234
- }
235
- }