@hyperscale0/hsx 1.0.0-alpha.6 → 1.0.0-rc.1
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.
- package/CHANGELOG.md +48 -10
- package/LICENSING.md +3 -3
- package/README.md +37 -149
- package/TRADEMARKS.md +4 -4
- package/dist/src/ast.d.ts +129 -10
- package/dist/src/ast.d.ts.map +1 -1
- package/dist/src/cli.d.ts +2 -1
- package/dist/src/cli.d.ts.map +1 -1
- package/dist/src/cli.js +148 -12
- package/dist/src/cli.js.map +1 -1
- package/dist/src/compile.d.ts +41 -4
- package/dist/src/compile.d.ts.map +1 -1
- package/dist/src/compile.js +82 -15
- package/dist/src/compile.js.map +1 -1
- package/dist/src/cost.d.ts +78 -0
- package/dist/src/cost.d.ts.map +1 -0
- package/dist/src/cost.js +369 -0
- package/dist/src/cost.js.map +1 -0
- package/dist/src/diagnostics.d.ts +11 -0
- package/dist/src/diagnostics.d.ts.map +1 -0
- package/dist/src/diagnostics.js +420 -0
- package/dist/src/diagnostics.js.map +1 -0
- package/dist/src/emit.d.ts +35 -0
- package/dist/src/emit.d.ts.map +1 -0
- package/dist/src/emit.js +359 -0
- package/dist/src/emit.js.map +1 -0
- package/dist/src/entry-overrides.d.ts +17 -3
- package/dist/src/entry-overrides.d.ts.map +1 -1
- package/dist/src/entry-overrides.js +180 -35
- package/dist/src/entry-overrides.js.map +1 -1
- package/dist/src/format.d.ts +10 -0
- package/dist/src/format.d.ts.map +1 -0
- package/dist/src/format.js +183 -0
- package/dist/src/format.js.map +1 -0
- package/dist/src/index.d.ts +10 -4
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +8 -3
- package/dist/src/index.js.map +1 -1
- package/dist/src/ir.d.ts +66 -0
- package/dist/src/ir.d.ts.map +1 -0
- package/dist/src/ir.js +15 -0
- package/dist/src/ir.js.map +1 -0
- package/dist/src/lex.d.ts +9 -1
- package/dist/src/lex.d.ts.map +1 -1
- package/dist/src/lex.js +50 -4
- package/dist/src/lex.js.map +1 -1
- package/dist/src/limits.d.ts +2 -3
- package/dist/src/limits.d.ts.map +1 -1
- package/dist/src/limits.js +2 -3
- package/dist/src/limits.js.map +1 -1
- package/dist/src/modules.d.ts +36 -0
- package/dist/src/modules.d.ts.map +1 -0
- package/dist/src/modules.js +372 -0
- package/dist/src/modules.js.map +1 -0
- package/dist/src/parse.d.ts.map +1 -1
- package/dist/src/parse.js +590 -17
- package/dist/src/parse.js.map +1 -1
- package/dist/src/typecheck.d.ts +8 -0
- package/dist/src/typecheck.d.ts.map +1 -0
- package/dist/src/typecheck.js +2958 -0
- package/dist/src/typecheck.js.map +1 -0
- package/dist/src/version.d.ts +4 -15
- package/dist/src/version.d.ts.map +1 -1
- package/dist/src/version.js +4 -15
- package/dist/src/version.js.map +1 -1
- package/docs/README.md +23 -0
- package/docs/guide/01-first-program.md +24 -0
- package/docs/guide/02-money.md +25 -0
- package/docs/guide/03-instruments.md +22 -0
- package/docs/guide/04-lifecycles.md +25 -0
- package/docs/guide/05-fees-and-splits.md +45 -0
- package/docs/guide/06-schedules.md +22 -0
- package/docs/guide/07-composition.md +46 -0
- package/docs/guide/08-writing-a-module.md +26 -0
- package/docs/guide/09-cost.md +24 -0
- package/docs/guide/10-diagnostics.md +27 -0
- package/docs/llms-full.txt +1738 -0
- package/docs/llms.txt +45 -0
- package/docs/reference/cli.md +33 -0
- package/docs/reference/diagnostics.md +619 -0
- package/docs/reference/grammar.md +39 -0
- package/docs/reference/std/advance.md +35 -0
- package/docs/reference/std/cancellable_booking.md +35 -0
- package/docs/reference/std/captured_payment.md +43 -0
- package/docs/reference/std/conditional_disbursement.md +33 -0
- package/docs/reference/std/credit_facility.md +35 -0
- package/docs/reference/std/held_payment.md +64 -0
- package/docs/reference/std/instant_transfer.md +30 -0
- package/docs/reference/std/metered.md +27 -0
- package/docs/reference/std/pooled_split.md +26 -0
- package/docs/reference/std/premium_forward.md +39 -0
- package/docs/reference/std/reconciled_payout.md +33 -0
- package/docs/reference/std/recurring_collection.md +25 -0
- package/docs/reference/std/rotating_pool.md +42 -0
- package/docs/reference/std/scheduled.md +51 -0
- package/docs/reference/std/security_deposit.md +46 -0
- package/docs/reference/std/settlement_batch.md +42 -0
- package/docs/reference/std/swap.md +46 -0
- package/docs/reference/std/threshold_pool.md +47 -0
- package/docs/reference/std/weighted_distribution.md +39 -0
- package/docs/reference/types.md +20 -0
- package/docs/reference/udl-output.md +14 -0
- package/docs/sessions/2026-09-02-two-instruments.hsx +21 -0
- package/docs/sessions/2026-09-02-two-instruments.md +41 -0
- package/examples/01-first-program/README.md +45 -0
- package/examples/01-first-program/tip-jar.hsx +17 -0
- package/examples/02-imports-and-archetypes/README.md +99 -0
- package/examples/02-imports-and-archetypes/photo-booth.hsx +37 -0
- package/examples/03-diagnostics/README.md +68 -0
- package/examples/03-diagnostics/corner-shop-fixed.hsx +22 -0
- package/examples/03-diagnostics/corner-shop.hsx +19 -0
- package/examples/04-complete-product/README.md +87 -0
- package/examples/04-complete-product/study-hall.hsx +67 -0
- package/examples/05-watch-club/README.md +9 -0
- package/examples/05-watch-club/watch-club.hsx +124 -0
- package/examples/README.md +18 -0
- package/examples/advance/README.md +3 -0
- package/examples/advance/advance.hsx +13 -0
- package/examples/advance/advance.udl +339 -0
- package/examples/cancellable_booking/README.md +3 -0
- package/examples/cancellable_booking/cancellable_booking.hsx +14 -0
- package/examples/cancellable_booking/cancellable_booking.udl +391 -0
- package/examples/captured_payment/README.md +3 -0
- package/examples/captured_payment/captured_payment.hsx +21 -0
- package/examples/captured_payment/captured_payment.udl +677 -0
- package/examples/conditional_disbursement/README.md +3 -0
- package/examples/conditional_disbursement/conditional_disbursement.hsx +17 -0
- package/examples/conditional_disbursement/conditional_disbursement.udl +412 -0
- package/examples/cost-table.json +386 -0
- package/examples/credit_facility/README.md +3 -0
- package/examples/credit_facility/credit_facility.hsx +27 -0
- package/examples/credit_facility/credit_facility.udl +1373 -0
- package/examples/held_payment/README.md +3 -0
- package/examples/held_payment/held_payment.hsx +13 -0
- package/examples/held_payment/held_payment.udl +507 -0
- package/examples/instant_transfer/README.md +3 -0
- package/examples/instant_transfer/instant_transfer.hsx +16 -0
- package/examples/instant_transfer/instant_transfer.udl +364 -0
- package/examples/metered/README.md +3 -0
- package/examples/metered/metered.hsx +13 -0
- package/examples/metered/metered.udl +247 -0
- package/examples/pooled_split/README.md +3 -0
- package/examples/pooled_split/pooled_split.hsx +15 -0
- package/examples/pooled_split/pooled_split.udl +425 -0
- package/examples/premium_forward/README.md +3 -0
- package/examples/premium_forward/premium_forward.hsx +19 -0
- package/examples/premium_forward/premium_forward.udl +594 -0
- package/examples/reconciled_payout/README.md +3 -0
- package/examples/reconciled_payout/reconciled_payout.hsx +13 -0
- package/examples/reconciled_payout/reconciled_payout.udl +303 -0
- package/examples/recurring_collection/README.md +3 -0
- package/examples/recurring_collection/recurring_collection.hsx +21 -0
- package/examples/recurring_collection/recurring_collection.udl +1130 -0
- package/examples/rotating_pool/README.md +3 -0
- package/examples/rotating_pool/rotating_pool.hsx +18 -0
- package/examples/rotating_pool/rotating_pool.udl +4352 -0
- package/examples/scheduled/README.md +3 -0
- package/examples/scheduled/scheduled.hsx +12 -0
- package/examples/scheduled/scheduled.udl +335 -0
- package/examples/security_deposit/README.md +3 -0
- package/examples/security_deposit/security_deposit.hsx +21 -0
- package/examples/security_deposit/security_deposit.udl +293 -0
- package/examples/settlement_batch/README.md +3 -0
- package/examples/settlement_batch/settlement_batch.hsx +19 -0
- package/examples/settlement_batch/settlement_batch.udl +753 -0
- package/examples/swap/README.md +3 -0
- package/examples/swap/swap.hsx +19 -0
- package/examples/swap/swap.udl +876 -0
- package/examples/threshold_pool/README.md +3 -0
- package/examples/threshold_pool/threshold_pool.hsx +16 -0
- package/examples/threshold_pool/threshold_pool.udl +667 -0
- package/examples/weighted_distribution/README.md +3 -0
- package/examples/weighted_distribution/weighted_distribution.hsx +20 -0
- package/examples/weighted_distribution/weighted_distribution.udl +337 -0
- package/package.json +19 -6
- package/skills/hsx/SKILL.md +483 -0
- package/src/ast.ts +163 -9
- package/src/cli.ts +164 -12
- package/src/compile.ts +160 -20
- package/src/cost.ts +579 -0
- package/src/diagnostics.ts +442 -0
- package/src/emit.ts +447 -0
- package/src/entry-overrides.ts +263 -48
- package/src/format.ts +261 -0
- package/src/index.ts +32 -4
- package/src/ir.ts +99 -0
- package/src/lex.ts +59 -4
- package/src/limits.ts +2 -3
- package/src/modules.ts +444 -0
- package/src/parse.ts +655 -21
- package/src/typecheck.ts +3876 -0
- package/src/version.ts +4 -16
- package/std/SEMANTICS.md +130 -0
- package/std/settlements/advance.hsx +177 -0
- package/std/settlements/cancellable_booking.hsx +87 -0
- package/std/settlements/captured_payment.hsx +144 -0
- package/std/settlements/conditional_disbursement.hsx +185 -0
- package/std/settlements/credit_facility.hsx +167 -0
- package/std/settlements/held_payment.hsx +578 -0
- package/std/settlements/index.hsx +3 -0
- package/std/settlements/instant_transfer.hsx +190 -0
- package/std/settlements/metered.hsx +67 -0
- package/std/settlements/pooled_split.hsx +68 -0
- package/std/settlements/premium_forward.hsx +257 -0
- package/std/settlements/reconciled_payout.hsx +77 -0
- package/std/settlements/recurring_collection.hsx +27 -0
- package/std/settlements/rotating_pool.hsx +252 -0
- package/std/settlements/scheduled.hsx +641 -0
- package/std/settlements/security_deposit.hsx +166 -0
- package/std/settlements/settlement_batch.hsx +122 -0
- package/std/settlements/swap.hsx +1114 -0
- package/std/settlements/threshold_pool.hsx +221 -0
- package/std/settlements/weighted_distribution.hsx +141 -0
- package/dist/src/archetypes.d.ts +0 -17
- package/dist/src/archetypes.d.ts.map +0 -1
- package/dist/src/archetypes.js +0 -327
- package/dist/src/archetypes.js.map +0 -1
- package/dist/src/check.d.ts +0 -12
- package/dist/src/check.d.ts.map +0 -1
- package/dist/src/check.js +0 -1910
- package/dist/src/check.js.map +0 -1
- package/dist/src/lower.d.ts +0 -146
- package/dist/src/lower.d.ts.map +0 -1
- package/dist/src/lower.js +0 -4570
- package/dist/src/lower.js.map +0 -1
- package/dist/src/model.d.ts +0 -467
- package/dist/src/model.d.ts.map +0 -1
- package/dist/src/model.js +0 -15
- package/dist/src/model.js.map +0 -1
- package/spec/hsx-ir.schema.json +0 -920
- package/src/archetypes.ts +0 -340
- package/src/check.ts +0 -2938
- package/src/lower.ts +0 -5416
- package/src/model.ts +0 -519
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
// A complete small product: a tutoring marketplace.
|
|
2
|
+
//
|
|
3
|
+
// Three settlements, three different jobs:
|
|
4
|
+
//
|
|
5
|
+
// lesson a student's payment is held until the tutor confirms the
|
|
6
|
+
// lesson happened; the platform's 8% comes out of the payout
|
|
7
|
+
// kit_deposit the tutor's equipment deposit is a reservation on the
|
|
8
|
+
// student's own account, claimed on damage or returned intact
|
|
9
|
+
// tutor_payout the marketplace's weekly pool, split between the two tutors
|
|
10
|
+
// who ran the sessions, with the remainder going to the lead
|
|
11
|
+
//
|
|
12
|
+
// Everything a caller can decide goes through a port, and every port names
|
|
13
|
+
// exactly who may answer it.
|
|
14
|
+
|
|
15
|
+
program study_hall "Study hall"
|
|
16
|
+
|
|
17
|
+
import { held_payment, security_deposit, pooled_split } from "std/settlements"
|
|
18
|
+
|
|
19
|
+
party student: person
|
|
20
|
+
party tutor: business
|
|
21
|
+
party lead_tutor: business
|
|
22
|
+
party school: business
|
|
23
|
+
|
|
24
|
+
asset lesson_kit: good { title_transfer: on_platform }
|
|
25
|
+
|
|
26
|
+
settlement lesson = held_payment {
|
|
27
|
+
payer: student
|
|
28
|
+
payee: tutor
|
|
29
|
+
amount: lessonFee: money(SAR)
|
|
30
|
+
fees { tutor: 8% }
|
|
31
|
+
release: port confirm_lesson | at(lessonEndsAt)
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
settlement kit_deposit = security_deposit {
|
|
35
|
+
payer: student
|
|
36
|
+
holder: tutor
|
|
37
|
+
amount: kitDeposit: money(SAR)
|
|
38
|
+
claim: port assess_kit
|
|
39
|
+
return: port release_kit
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
settlement tutor_payout = pooled_split {
|
|
43
|
+
payer: school
|
|
44
|
+
amount: weeklyPool: money(SAR)
|
|
45
|
+
payout_due: payoutDate
|
|
46
|
+
split { lead_tutor: 55%, tutor: 45%, remainder_to: lead_tutor }
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
// The tutor confirms the lesson happened. If nobody answers, `at(lessonEndsAt)`
|
|
50
|
+
// releases the money to the tutor on the stored date: inaction resolves in the
|
|
51
|
+
// direction the parties already agreed on, instead of stranding the payment.
|
|
52
|
+
port confirm_lesson {
|
|
53
|
+
allowed: [tutor]
|
|
54
|
+
shape {
|
|
55
|
+
kitId: id(lesson_kit)
|
|
56
|
+
lessonNotes: text
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
port assess_kit {
|
|
61
|
+
allowed: [tutor]
|
|
62
|
+
shape { damageReport: text }
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
port release_kit {
|
|
66
|
+
allowed: [tutor]
|
|
67
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
# Watch club
|
|
2
|
+
|
|
3
|
+
This reference program joins the algebra needed for one club product. It keeps
|
|
4
|
+
each watch attached to explicit sale, deposit, and trade rules. Membership due
|
|
5
|
+
dates open periods, while callers still author every money action. Seller
|
|
6
|
+
payouts close through stored provider evidence.
|
|
7
|
+
|
|
8
|
+
The acceptance proof lives in
|
|
9
|
+
`toolchain/system-tests/test/watch-club.acceptance.spec.ts`.
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
// A watch club whose money rules remain explicit from member checkout through
|
|
2
|
+
// seller payout. Each item owns its sale, deposit, and trade lifecycle. The
|
|
3
|
+
// club membership schedule opens periods but never moves money on a timeout.
|
|
4
|
+
|
|
5
|
+
program watch_club "Watch club"
|
|
6
|
+
|
|
7
|
+
import {
|
|
8
|
+
security_deposit,
|
|
9
|
+
instant_transfer,
|
|
10
|
+
recurring_collection,
|
|
11
|
+
scheduled,
|
|
12
|
+
settlement_batch,
|
|
13
|
+
swap
|
|
14
|
+
} from "std/settlements"
|
|
15
|
+
|
|
16
|
+
party member: person
|
|
17
|
+
party seller: business
|
|
18
|
+
party club: business
|
|
19
|
+
party payout_destination: business
|
|
20
|
+
|
|
21
|
+
asset watch: good { title_transfer: on_platform }
|
|
22
|
+
|
|
23
|
+
settlement purchase = instant_transfer {
|
|
24
|
+
payer: member
|
|
25
|
+
payee: seller
|
|
26
|
+
amount: purchasePrice: money(SAR)
|
|
27
|
+
fees {
|
|
28
|
+
member: checkoutFee: money(SAR)
|
|
29
|
+
seller {
|
|
30
|
+
tier {
|
|
31
|
+
from: 0
|
|
32
|
+
to: 10000
|
|
33
|
+
fee: 1%
|
|
34
|
+
}
|
|
35
|
+
tier {
|
|
36
|
+
from: 10000
|
|
37
|
+
fee: highValueFee: money(SAR)
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
settlement inspection_deposit = security_deposit {
|
|
44
|
+
payer: member
|
|
45
|
+
holder: seller
|
|
46
|
+
amount: depositAmount: money(SAR)
|
|
47
|
+
claim: port assess_watch
|
|
48
|
+
claim_amount: decided {
|
|
49
|
+
field: damageAmount
|
|
50
|
+
bound: depositAmount
|
|
51
|
+
remainder: return
|
|
52
|
+
}
|
|
53
|
+
return: port return_deposit
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
settlement membership = scheduled {
|
|
57
|
+
mode: obligation
|
|
58
|
+
payer: member
|
|
59
|
+
payee: club
|
|
60
|
+
debtor: member
|
|
61
|
+
amount: monthlyFee: money(SAR)
|
|
62
|
+
every: P1M
|
|
63
|
+
first_due: firstPeriodAt
|
|
64
|
+
until: port cancel_membership
|
|
65
|
+
month_end: clamp_to_last_day
|
|
66
|
+
period_liability: one_open
|
|
67
|
+
termination_drain: cancel_membership
|
|
68
|
+
mandate: port collect_membership
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
settlement member_trade = swap {
|
|
72
|
+
between: [member, seller]
|
|
73
|
+
amounts {
|
|
74
|
+
member: memberPays: money(SAR)
|
|
75
|
+
seller: sellerPays: money(SAR)
|
|
76
|
+
}
|
|
77
|
+
fees {
|
|
78
|
+
member: memberTradeFee: money(SAR)
|
|
79
|
+
seller: sellerTradeFee: money(SAR)
|
|
80
|
+
}
|
|
81
|
+
release: port confirm_trade
|
|
82
|
+
dispute: port resolve_trade within P14D
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
settlement seller_payout = settlement_batch {
|
|
86
|
+
settlement_account: club
|
|
87
|
+
source_capture_refs: captureReference
|
|
88
|
+
fee_entries: feeReference
|
|
89
|
+
external_reversal_offsets: externalReversalReference
|
|
90
|
+
close_trigger: closeAt
|
|
91
|
+
payout_destination: payout_destination
|
|
92
|
+
negative_position: reject
|
|
93
|
+
payout_acknowledgement: port acknowledge_payout
|
|
94
|
+
payout_beneficiary_ref: payoutBeneficiaryId
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
port assess_watch {
|
|
98
|
+
allowed: [seller]
|
|
99
|
+
shape {
|
|
100
|
+
damageAmount: money(SAR)
|
|
101
|
+
evidence: text
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
port return_deposit { allowed: [seller] }
|
|
106
|
+
|
|
107
|
+
port collect_membership {
|
|
108
|
+
allowed: [member]
|
|
109
|
+
shape { evidenceReference: text }
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
port cancel_membership {
|
|
113
|
+
allowed: [member]
|
|
114
|
+
shape { reason: text }
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
port confirm_trade { allowed: [member, seller] }
|
|
118
|
+
|
|
119
|
+
port resolve_trade { allowed: [member, seller] }
|
|
120
|
+
|
|
121
|
+
port acknowledge_payout {
|
|
122
|
+
allowed: [payout_destination]
|
|
123
|
+
shape { acknowledgementReference: text }
|
|
124
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# Examples
|
|
2
|
+
|
|
3
|
+
Each standard-library module has its own directory with an HSX program, a
|
|
4
|
+
short lesson, and pinned canonical UDL bytes. The test suite reads the module
|
|
5
|
+
list from `std/settlements`, compiles every program, and compares each emitted
|
|
6
|
+
document byte for byte.
|
|
7
|
+
|
|
8
|
+
The numbered examples remain as longer lessons. They cover a first program,
|
|
9
|
+
imports, diagnostic repair, a composed product, and a multi-instrument club.
|
|
10
|
+
|
|
11
|
+
Run an example with the installed CLI:
|
|
12
|
+
|
|
13
|
+
```sh
|
|
14
|
+
hsx check examples/instant_transfer/instant_transfer.hsx
|
|
15
|
+
hsx build examples/instant_transfer/instant_transfer.hsx --out program.udl
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
Every company and person in these files is invented.
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
program advance_example "Advance example"
|
|
2
|
+
import { advance } from "std/settlements"
|
|
3
|
+
party funder: business
|
|
4
|
+
party recipient: business
|
|
5
|
+
settlement advance_payment = advance {
|
|
6
|
+
funder: funder
|
|
7
|
+
to: recipient
|
|
8
|
+
amount: principal: money(SAR)
|
|
9
|
+
fee: 2.5%
|
|
10
|
+
count: 2
|
|
11
|
+
every: P30D
|
|
12
|
+
first_due: firstDueAt
|
|
13
|
+
}
|
|
@@ -0,0 +1,339 @@
|
|
|
1
|
+
{
|
|
2
|
+
"instruments": [
|
|
3
|
+
{
|
|
4
|
+
"actionOrder": [
|
|
5
|
+
"create",
|
|
6
|
+
"disburse",
|
|
7
|
+
"collect_repayment_1",
|
|
8
|
+
"collect_repayment_2"
|
|
9
|
+
],
|
|
10
|
+
"actions": {
|
|
11
|
+
"collect_repayment_1": {
|
|
12
|
+
"due": {
|
|
13
|
+
"field": "firstDueAt"
|
|
14
|
+
},
|
|
15
|
+
"effects": {
|
|
16
|
+
"moves": [
|
|
17
|
+
{
|
|
18
|
+
"signature": "moves.transfer.internal",
|
|
19
|
+
"source": "moves[0]"
|
|
20
|
+
}
|
|
21
|
+
],
|
|
22
|
+
"schedules": [
|
|
23
|
+
{
|
|
24
|
+
"signature": "schedules.due",
|
|
25
|
+
"source": "due"
|
|
26
|
+
}
|
|
27
|
+
]
|
|
28
|
+
},
|
|
29
|
+
"moves": [
|
|
30
|
+
{
|
|
31
|
+
"bind": {
|
|
32
|
+
"amount": {
|
|
33
|
+
"from": "instance",
|
|
34
|
+
"path": "fields.repayment1Amount"
|
|
35
|
+
},
|
|
36
|
+
"currency": {
|
|
37
|
+
"from": "instance",
|
|
38
|
+
"path": "fields.currency"
|
|
39
|
+
},
|
|
40
|
+
"destinationAccountId": {
|
|
41
|
+
"from": "instance",
|
|
42
|
+
"path": "fields.funderAccountId"
|
|
43
|
+
},
|
|
44
|
+
"metadata.instrumentId": {
|
|
45
|
+
"from": "const",
|
|
46
|
+
"value": "advance_payment"
|
|
47
|
+
},
|
|
48
|
+
"metadata.instrumentInstanceId": {
|
|
49
|
+
"from": "instance",
|
|
50
|
+
"path": "instrumentInstanceId"
|
|
51
|
+
},
|
|
52
|
+
"metadata.phase": {
|
|
53
|
+
"from": "const",
|
|
54
|
+
"value": "collect_repayment_1"
|
|
55
|
+
},
|
|
56
|
+
"productId": {
|
|
57
|
+
"from": "instance",
|
|
58
|
+
"path": "productId"
|
|
59
|
+
},
|
|
60
|
+
"sourceAccountId": {
|
|
61
|
+
"from": "instance",
|
|
62
|
+
"path": "fields.recipientAccountId"
|
|
63
|
+
}
|
|
64
|
+
},
|
|
65
|
+
"capture": {
|
|
66
|
+
"collectRepayment1TransferTransferId": "transferId"
|
|
67
|
+
},
|
|
68
|
+
"key": "transfer",
|
|
69
|
+
"operation": "internal_transfer.create"
|
|
70
|
+
}
|
|
71
|
+
],
|
|
72
|
+
"steps": [],
|
|
73
|
+
"summary": "Collect repayment 1 of 2"
|
|
74
|
+
},
|
|
75
|
+
"collect_repayment_2": {
|
|
76
|
+
"due": {
|
|
77
|
+
"field": "firstDueAt",
|
|
78
|
+
"offset": "P30D"
|
|
79
|
+
},
|
|
80
|
+
"effects": {
|
|
81
|
+
"moves": [
|
|
82
|
+
{
|
|
83
|
+
"signature": "moves.transfer.internal",
|
|
84
|
+
"source": "moves[0]"
|
|
85
|
+
}
|
|
86
|
+
],
|
|
87
|
+
"schedules": [
|
|
88
|
+
{
|
|
89
|
+
"signature": "schedules.due",
|
|
90
|
+
"source": "due"
|
|
91
|
+
}
|
|
92
|
+
]
|
|
93
|
+
},
|
|
94
|
+
"moves": [
|
|
95
|
+
{
|
|
96
|
+
"bind": {
|
|
97
|
+
"amount": {
|
|
98
|
+
"from": "instance",
|
|
99
|
+
"path": "fields.repayment2Amount"
|
|
100
|
+
},
|
|
101
|
+
"currency": {
|
|
102
|
+
"from": "instance",
|
|
103
|
+
"path": "fields.currency"
|
|
104
|
+
},
|
|
105
|
+
"destinationAccountId": {
|
|
106
|
+
"from": "instance",
|
|
107
|
+
"path": "fields.funderAccountId"
|
|
108
|
+
},
|
|
109
|
+
"metadata.instrumentId": {
|
|
110
|
+
"from": "const",
|
|
111
|
+
"value": "advance_payment"
|
|
112
|
+
},
|
|
113
|
+
"metadata.instrumentInstanceId": {
|
|
114
|
+
"from": "instance",
|
|
115
|
+
"path": "instrumentInstanceId"
|
|
116
|
+
},
|
|
117
|
+
"metadata.phase": {
|
|
118
|
+
"from": "const",
|
|
119
|
+
"value": "collect_repayment_2"
|
|
120
|
+
},
|
|
121
|
+
"productId": {
|
|
122
|
+
"from": "instance",
|
|
123
|
+
"path": "productId"
|
|
124
|
+
},
|
|
125
|
+
"sourceAccountId": {
|
|
126
|
+
"from": "instance",
|
|
127
|
+
"path": "fields.recipientAccountId"
|
|
128
|
+
}
|
|
129
|
+
},
|
|
130
|
+
"capture": {
|
|
131
|
+
"collectRepayment2TransferTransferId": "transferId"
|
|
132
|
+
},
|
|
133
|
+
"key": "transfer",
|
|
134
|
+
"operation": "internal_transfer.create"
|
|
135
|
+
}
|
|
136
|
+
],
|
|
137
|
+
"steps": [],
|
|
138
|
+
"summary": "Collect repayment 2 of 2"
|
|
139
|
+
},
|
|
140
|
+
"create": {
|
|
141
|
+
"agentDescription": "Open the advance row before any money moves. The caller supplies the principal, the fee amount, the repayable total, and the first repayment date. The repayment fields must partition the repayable total exactly. Nothing is disbursed here.",
|
|
142
|
+
"moves": [],
|
|
143
|
+
"publicAction": "createAdvancePayment",
|
|
144
|
+
"steps": [],
|
|
145
|
+
"summary": "Create a advance payment"
|
|
146
|
+
},
|
|
147
|
+
"disburse": {
|
|
148
|
+
"agentDescription": "Pay the principal from the funder to the recipient 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.",
|
|
149
|
+
"effects": {
|
|
150
|
+
"moves": [
|
|
151
|
+
{
|
|
152
|
+
"signature": "moves.transfer.internal",
|
|
153
|
+
"source": "moves[0]"
|
|
154
|
+
}
|
|
155
|
+
]
|
|
156
|
+
},
|
|
157
|
+
"moves": [
|
|
158
|
+
{
|
|
159
|
+
"bind": {
|
|
160
|
+
"amount": {
|
|
161
|
+
"from": "instance",
|
|
162
|
+
"path": "fields.principal"
|
|
163
|
+
},
|
|
164
|
+
"currency": {
|
|
165
|
+
"from": "instance",
|
|
166
|
+
"path": "fields.currency"
|
|
167
|
+
},
|
|
168
|
+
"destinationAccountId": {
|
|
169
|
+
"from": "instance",
|
|
170
|
+
"path": "fields.recipientAccountId"
|
|
171
|
+
},
|
|
172
|
+
"metadata.instrumentId": {
|
|
173
|
+
"from": "const",
|
|
174
|
+
"value": "advance_payment"
|
|
175
|
+
},
|
|
176
|
+
"metadata.instrumentInstanceId": {
|
|
177
|
+
"from": "instance",
|
|
178
|
+
"path": "instrumentInstanceId"
|
|
179
|
+
},
|
|
180
|
+
"metadata.phase": {
|
|
181
|
+
"from": "const",
|
|
182
|
+
"value": "disburse"
|
|
183
|
+
},
|
|
184
|
+
"productId": {
|
|
185
|
+
"from": "instance",
|
|
186
|
+
"path": "productId"
|
|
187
|
+
},
|
|
188
|
+
"sourceAccountId": {
|
|
189
|
+
"from": "instance",
|
|
190
|
+
"path": "fields.funderAccountId"
|
|
191
|
+
}
|
|
192
|
+
},
|
|
193
|
+
"capture": {
|
|
194
|
+
"disburseTransferTransferId": "transferId"
|
|
195
|
+
},
|
|
196
|
+
"key": "transfer",
|
|
197
|
+
"operation": "internal_transfer.create"
|
|
198
|
+
}
|
|
199
|
+
],
|
|
200
|
+
"publicAction": "disburseAdvancePayment",
|
|
201
|
+
"steps": [],
|
|
202
|
+
"summary": "Disburse the principal to the recipient"
|
|
203
|
+
}
|
|
204
|
+
},
|
|
205
|
+
"agentDescription": "Reach for advance when the funder pays the recipient 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.",
|
|
206
|
+
"description": "Advance: the funder disburses principal to the recipient, repaid over 2 scheduled repayments plus the funder's discount",
|
|
207
|
+
"fields": {
|
|
208
|
+
"currency": {
|
|
209
|
+
"description": "ISO 4217 currency code",
|
|
210
|
+
"maxLength": 3,
|
|
211
|
+
"minLength": 3,
|
|
212
|
+
"pattern": "^[A-Z]{3}$",
|
|
213
|
+
"type": "string"
|
|
214
|
+
},
|
|
215
|
+
"feeAmount": {
|
|
216
|
+
"description": "2.5% of principal, the funder's discount repaid on top of the advance",
|
|
217
|
+
"pattern": "^[1-9][0-9]{0,17}$",
|
|
218
|
+
"type": "string"
|
|
219
|
+
},
|
|
220
|
+
"firstDueAt": {
|
|
221
|
+
"description": "Due date of the first repayment; repayment k falls P30D after its predecessor",
|
|
222
|
+
"format": "hyperscale-date-time",
|
|
223
|
+
"type": "string"
|
|
224
|
+
},
|
|
225
|
+
"funderAccountId": {
|
|
226
|
+
"description": "The funder account",
|
|
227
|
+
"pattern": "^acct_(sandbox|live)_[a-z0-9]{8,64}$",
|
|
228
|
+
"type": "string",
|
|
229
|
+
"x-hyperscale-reference-filter": {
|
|
230
|
+
"column": "role",
|
|
231
|
+
"values": [
|
|
232
|
+
"customer_balance"
|
|
233
|
+
]
|
|
234
|
+
}
|
|
235
|
+
},
|
|
236
|
+
"principal": {
|
|
237
|
+
"description": "The advanced amount in SAR minor units, disbursed to the recipient up front",
|
|
238
|
+
"pattern": "^[1-9][0-9]{0,17}$",
|
|
239
|
+
"type": "string"
|
|
240
|
+
},
|
|
241
|
+
"recipientAccountId": {
|
|
242
|
+
"description": "The recipient account",
|
|
243
|
+
"pattern": "^acct_(sandbox|live)_[a-z0-9]{8,64}$",
|
|
244
|
+
"type": "string",
|
|
245
|
+
"x-hyperscale-reference-filter": {
|
|
246
|
+
"column": "role",
|
|
247
|
+
"values": [
|
|
248
|
+
"customer_balance"
|
|
249
|
+
]
|
|
250
|
+
}
|
|
251
|
+
},
|
|
252
|
+
"repayableAmount": {
|
|
253
|
+
"description": "principal + feeAmount: the total the repayment fields below partition exactly",
|
|
254
|
+
"pattern": "^[1-9][0-9]{0,17}$",
|
|
255
|
+
"type": "string"
|
|
256
|
+
},
|
|
257
|
+
"repayment1Amount": {
|
|
258
|
+
"description": "Repayment 1 of 2 (carries the integer-division remainder): about 33.34% of repayableAmount, collected on its own stored-date anchor",
|
|
259
|
+
"pattern": "^[1-9][0-9]{0,17}$",
|
|
260
|
+
"type": "string"
|
|
261
|
+
},
|
|
262
|
+
"repayment2Amount": {
|
|
263
|
+
"description": "Repayment 2 of 2: about 33.33% of repayableAmount, collected on its own stored-date anchor",
|
|
264
|
+
"pattern": "^[1-9][0-9]{0,17}$",
|
|
265
|
+
"type": "string"
|
|
266
|
+
}
|
|
267
|
+
},
|
|
268
|
+
"id": "advance_payment",
|
|
269
|
+
"idPrefix": "ap",
|
|
270
|
+
"lifecycle": {
|
|
271
|
+
"initial": "created",
|
|
272
|
+
"states": [
|
|
273
|
+
"created",
|
|
274
|
+
"advanced",
|
|
275
|
+
"repaying_1",
|
|
276
|
+
"repaid"
|
|
277
|
+
],
|
|
278
|
+
"transitions": {
|
|
279
|
+
"collect_repayment_1": {
|
|
280
|
+
"from": [
|
|
281
|
+
"advanced"
|
|
282
|
+
],
|
|
283
|
+
"to": "repaying_1"
|
|
284
|
+
},
|
|
285
|
+
"collect_repayment_2": {
|
|
286
|
+
"from": [
|
|
287
|
+
"repaying_1"
|
|
288
|
+
],
|
|
289
|
+
"to": "repaid"
|
|
290
|
+
},
|
|
291
|
+
"disburse": {
|
|
292
|
+
"from": [
|
|
293
|
+
"created"
|
|
294
|
+
],
|
|
295
|
+
"to": "advanced"
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
},
|
|
299
|
+
"parties": {
|
|
300
|
+
"beneficiary": "recipientAccountId",
|
|
301
|
+
"payer": "funderAccountId"
|
|
302
|
+
},
|
|
303
|
+
"partitions": [
|
|
304
|
+
{
|
|
305
|
+
"pieceFields": [
|
|
306
|
+
"repayment1Amount",
|
|
307
|
+
"repayment2Amount"
|
|
308
|
+
],
|
|
309
|
+
"totalField": "repayableAmount"
|
|
310
|
+
},
|
|
311
|
+
{
|
|
312
|
+
"pieceFields": [
|
|
313
|
+
"principal",
|
|
314
|
+
"feeAmount"
|
|
315
|
+
],
|
|
316
|
+
"totalField": "repayableAmount"
|
|
317
|
+
}
|
|
318
|
+
],
|
|
319
|
+
"required": [
|
|
320
|
+
"funderAccountId",
|
|
321
|
+
"recipientAccountId",
|
|
322
|
+
"principal",
|
|
323
|
+
"feeAmount",
|
|
324
|
+
"repayableAmount",
|
|
325
|
+
"firstDueAt",
|
|
326
|
+
"repayment1Amount",
|
|
327
|
+
"repayment2Amount",
|
|
328
|
+
"currency"
|
|
329
|
+
],
|
|
330
|
+
"summary": "Advance to recipient repaid over 2 anchors",
|
|
331
|
+
"title": "Advance payment"
|
|
332
|
+
}
|
|
333
|
+
],
|
|
334
|
+
"product": "advance_example",
|
|
335
|
+
"subjects": [],
|
|
336
|
+
"title": "Advance example",
|
|
337
|
+
"udl": 1,
|
|
338
|
+
"version": 1
|
|
339
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
program cancellable_booking_example "Cancellable booking example"
|
|
2
|
+
import { cancellable_booking } from "std/settlements"
|
|
3
|
+
party guest: person
|
|
4
|
+
party studio: business
|
|
5
|
+
settlement studio_session = cancellable_booking {
|
|
6
|
+
guest: guest
|
|
7
|
+
host: studio
|
|
8
|
+
amount: sessionPrice: money(SAR)
|
|
9
|
+
starts_at: startsAt
|
|
10
|
+
late_penalty_bps: 5000
|
|
11
|
+
late_within: P2D
|
|
12
|
+
early_penalty_bps: 1000
|
|
13
|
+
offer_life: PT30M
|
|
14
|
+
}
|