@hyperscale0/hsx 3.2.0 → 4.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 (57) hide show
  1. package/CHANGELOG.md +8 -0
  2. package/README.md +1 -1
  3. package/dist/src/ast.d.ts +17 -2
  4. package/dist/src/ast.d.ts.map +1 -1
  5. package/dist/src/ast.js.map +1 -1
  6. package/dist/src/cli.js +1 -1
  7. package/dist/src/compile.d.ts +6 -0
  8. package/dist/src/compile.d.ts.map +1 -1
  9. package/dist/src/compile.js +1194 -97
  10. package/dist/src/compile.js.map +1 -1
  11. package/dist/src/cost.d.ts +1 -1
  12. package/dist/src/cost.d.ts.map +1 -1
  13. package/dist/src/cost.js +52 -9
  14. package/dist/src/cost.js.map +1 -1
  15. package/dist/src/headers.d.ts +2 -2
  16. package/dist/src/headers.d.ts.map +1 -1
  17. package/dist/src/headers.js +3 -2
  18. package/dist/src/headers.js.map +1 -1
  19. package/dist/src/index.d.ts +3 -2
  20. package/dist/src/index.d.ts.map +1 -1
  21. package/dist/src/index.js.map +1 -1
  22. package/dist/src/lex.d.ts +1 -1
  23. package/dist/src/lex.d.ts.map +1 -1
  24. package/dist/src/lex.js +5 -0
  25. package/dist/src/lex.js.map +1 -1
  26. package/dist/src/parse.js +91 -5
  27. package/dist/src/parse.js.map +1 -1
  28. package/dist/src/std-bundle.d.ts.map +1 -1
  29. package/dist/src/std-bundle.js +10 -9
  30. package/dist/src/std-bundle.js.map +1 -1
  31. package/dist/src/version.d.ts +2 -2
  32. package/dist/src/version.js +2 -2
  33. package/docs/README.md +51 -27
  34. package/docs/headers.md +43 -40
  35. package/examples/cost-table.json +40 -324
  36. package/examples/library.hsx +12 -57
  37. package/package.json +7 -5
  38. package/src/ast.ts +11 -1
  39. package/src/cli.ts +1 -1
  40. package/src/compile.ts +1630 -114
  41. package/src/cost.ts +60 -16
  42. package/src/headers.ts +3 -2
  43. package/src/index.ts +12 -1
  44. package/src/lex.ts +5 -0
  45. package/src/parse.ts +87 -5
  46. package/src/std-bundle.ts +10 -9
  47. package/src/version.ts +2 -2
  48. package/std/approvals.hsx +3 -3
  49. package/std/collections.hsx +45 -4
  50. package/std/escrow.hsx +17 -8
  51. package/std/financing.hsx +292 -42
  52. package/std/insurance.hsx +4 -5
  53. package/std/lending.hsx +7 -8
  54. package/std/marketplace.hsx +90 -6
  55. package/std/money.hsx +15 -49
  56. package/std/reporting.hsx +1286 -0
  57. package/std/travel.hsx +5 -6
package/std/lending.hsx CHANGED
@@ -1,15 +1,14 @@
1
1
  header lending
2
2
 
3
- instrument round(borrower: party, capital: party, plan: ref<financing.installments> = object(financing.installments), months: integer(1, 366) = 3, profit: percent = 3%, minimum_ticket: money = 100 SAR, investor_cap: percent = 20%, commitments: ref<lending.commitment> = object(lending.commitment)) {
3
+ instrument round(borrower: party, plan: ref<financing.installments> = object(financing.installments), minimum_ticket: money = 100 SAR, investor_cap: percent = 20%, commitments: ref<lending.commitment> = object(lending.commitment)) {
4
4
  summary: "A threshold funding round; failed rounds return each original wallet contribution."
5
5
  fields {
6
- borrower: account of borrower, capital: account(capital, cash, "capital"), plan: ref<plan>, price: money, closesAt: date
7
- months: integer = months, profit: money = rate(self.price, profit)
6
+ borrower: account of borrower, plan: ref<plan>, price: money = self.plan.principal, closesAt: date
8
7
  minimumTicket: money = minimum_ticket, maximumTicket: money = rate(self.price, investor_cap)
9
8
  held: account of self
10
9
  }
11
10
  lifecycle { states: [open, funded, failed], initial: open }
12
- action create { requires unique "funding_plan" on [self.plan]; requires self.months == self.plan.months; requires self.profit == self.plan.profit; requires self.price == self.plan.principal; requires self.borrower == self.plan.funds.payer }
11
+ action create { requires unique "funding_plan" on [self.plan]; requires self.borrower == self.plan.funds.payer }
13
12
  action close {
14
13
  from: open, to: funded
15
14
  requires sum "amount" of { instrument: commitments, reference: "round", anchor: self.id, states: [committed], limit: 366 } == self.price
@@ -58,13 +57,13 @@ instrument distribution(round: ref<lending.round>, receipt: ref, commitments: re
58
57
  held: account of self, losses: account(self, claim), residualLoss: account(residual_to, claim, "loss")
59
58
  }
60
59
  lifecycle { states: [pending, cash_ready, loss_ready, distributed], initial: pending }
61
- action create { requires self.round in [funded]; requires self.source.plan == self.round.plan; requires unique "settlement_consumption" on [self.source.plan, self.source.identity] }
60
+ action create { requires self.round in [funded]; requires self.source in [recorded]; requires self.source.plan == self.round.plan; requires unique "settlement_consumption" on [self.source.plan, self.source.identity] }
62
61
  action prepare_cash {
63
62
  from: pending, to: cash_ready
64
- requires self.mode == "cash"; requires self.source.kind == "cash"
63
+ requires self.mode == "cash"; requires self.source.kind == "cash"; requires self.source in [recorded]
65
64
  calculate: [
66
65
  { target: "principal", op: "sum", values: [{ field: self.source.principal }] }
67
- { target: "profit", op: "sum", values: [{ field: self.source.profit }] }
66
+ { target: "profit", op: "sum", values: [{ field: self.source.retainedProfit }] }
68
67
  { target: "charge", op: "rate", base: { field: self.profit }, bps: { literal: fee }, rounding: "floor" }
69
68
  { target: "vat", op: "rate", base: { field: self.charge }, bps: { literal: tax }, rounding: "floor" }
70
69
  { target: "grossTotal", op: "sum", values: [{ field: self.principal }, { field: self.profit }] }
@@ -73,7 +72,7 @@ instrument distribution(round: ref<lending.round>, receipt: ref, commitments: re
73
72
  }
74
73
  action prepare_loss {
75
74
  from: pending, to: loss_ready
76
- requires self.mode == "loss"; requires self.source.kind == "loss"
75
+ requires self.mode == "loss"; requires self.source.kind == "loss"; requires self.source in [recorded]
77
76
  calculate: [{ target: "net", op: "sum", values: [{ field: self.source.loss }] }]
78
77
  }
79
78
  action distribute_cash {
@@ -1,24 +1,108 @@
1
1
  header marketplace
2
2
 
3
3
  instrument listing(seller: party) {
4
+ revisioned: true
4
5
  summary: "A seller's offer and its asking price."
5
6
  fields { seller: account of seller, title: text, price: money }
6
7
  lifecycle { states: [draft, active, withdrawn, sold], initial: draft }
7
8
  action create { actor: { party: seller } }
8
- action publish { from: draft, to: active, actor: { party: seller } }
9
- action withdraw { from: active, to: withdrawn, actor: { party: seller } }
10
- action sell { from: active, to: sold, actor: { party: seller } }
9
+ action publish {
10
+ from: draft, to: active, actor: { party: seller }
11
+ }
12
+ action withdraw { from: active, to: withdrawn, actor: { party: seller }, requires count of { instrument: all(marketplace.reservation), reference: "listing", anchor: self.id, states: [active], limit: 366 } == 0 }
13
+ action sell { from: active, to: sold, actor: { party: seller }, requires count of { instrument: all(marketplace.reservation), reference: "listing", anchor: self.id, states: [active], limit: 366 } == 0 }
11
14
  }
12
15
 
13
16
  instrument order(listing: ref<marketplace.listing>, buyer: party) {
17
+ revisioned: true
14
18
  summary: "A buyer's order for one listing at its declared price."
15
- fields { listing: ref<listing>, buyer: account of buyer, price: money }
16
- lifecycle { states: [placed, fulfilled, cancelled], initial: placed }
19
+ fields { listing: ref<listing>, buyer: account of buyer, price: money, reservations: integer?, ownReservations: integer?, blockingQuotes: integer?, ownBlockingQuotes: integer? }
20
+ lifecycle { states: [quoted, placed, fulfilled, cancelled], initial: quoted }
17
21
  action create {
18
22
  actor: { party: buyer }
19
23
  requires self.listing in [active]
24
+ calculate: [
25
+ { target: blockingQuotes, op: aggregate, selection: { instrument: all(marketplace.reservation), reference: "listing", anchor: self.listing, states: [active], limit: 366, where: { quotePolicy: { literal: "blocked" } } }, measure: count }
26
+ { target: ownBlockingQuotes, op: aggregate, selection: { instrument: all(marketplace.reservation), reference: "listing", anchor: self.listing, states: [active], limit: 366, where: { quotePolicy: { literal: "blocked" }, buyer: { field: self.buyer } } }, measure: count }
27
+ ]
28
+ requires self.blockingQuotes == self.ownBlockingQuotes
20
29
  requires self.price == self.listing.price
21
30
  }
31
+ action commit {
32
+ from: [quoted, placed], to: placed
33
+ requires self.listing in [active]
34
+ calculate: [
35
+ { target: reservations, op: aggregate, selection: { instrument: all(marketplace.reservation), reference: "listing", anchor: self.listing, states: [active], limit: 366 }, measure: count }
36
+ { target: ownReservations, op: aggregate, selection: { instrument: all(marketplace.reservation), reference: "listing", anchor: self.listing, states: [active], limit: 366, where: { buyer: { field: self.buyer } } }, measure: count }
37
+ ]
38
+ requires self.reservations == self.ownReservations
39
+ requires count of { instrument: current(), reference: "listing", anchor: self.listing, states: [placed, fulfilled], limit: 366 } <= 1
40
+ }
41
+ invariants count of { instrument: current(), reference: "listing", anchor: self.listing, states: [placed, fulfilled], limit: 366 } <= 1
22
42
  action fulfill { from: placed, to: fulfilled }
23
- action cancel { from: placed, to: cancelled, actor: { party: buyer } }
43
+ action cancel { from: [quoted, placed], to: cancelled, actor: { party: buyer } }
44
+ }
45
+
46
+ instrument reservation(listing: ref<marketplace.listing>, funds: ref<escrow.hold>, plans: ref<financing.installments>[], converters: ref[], buyer: party, seller: party, expires_after: duration = 48h, deposit: money = 1000 SAR, cancellation_refund: percent = 100%, expiry_refund: percent = 100%, retained_to: party = programOperator, operator: party = programOperator, competing_quotes: enum(allowed, blocked) = allowed) {
47
+ revisioned: true
48
+ summary: "Exclusive timed listing hold with explicit deposit credit and refund."
49
+ fields {
50
+ listing: ref<listing>, funds: ref<funds>, buyer: account of buyer, seller: account of seller, price: money, terms: text
51
+ held: account of self, quotePolicy: enum(allowed, blocked) = competing_quotes, deposit: money = deposit, proposalExpiresAt: date = after(self.createdAt, expires_after), expiresAt: date?
52
+ credit: money?, refund: money?, retained: money?, dispositionAt: date?, reason: text?
53
+ }
54
+ lifecycle { states: [proposed, active, converted, cancelled, expired], initial: proposed }
55
+ invariants count of { instrument: current(), reference: "listing", anchor: self.listing, states: [active], limit: 366 } <= 1
56
+ action create { actor: { party: buyer }, requires self.listing in [active]; requires self.seller == self.listing.seller; requires self.price == self.listing.price }
57
+ action activate {
58
+ from: proposed, to: active, actor: { party: buyer }, deadline: { at: self.proposalExpiresAt }
59
+ calculate: [{ target: expiresAt, op: shift, date: { field: self.now }, milliseconds: { literal: expires_after }, direction: after }]
60
+ requires self.listing in [active]; requires self.price == self.listing.price
61
+ requires count of { instrument: all(marketplace.order), reference: "listing", anchor: self.listing, states: [placed, fulfilled], limit: 366 } == 0
62
+ moves self.deposit from self.buyer to self.held
63
+ }
64
+ action convert_financed {
65
+ from: active, to: active, actor: { party: buyer }, deadline: { at: self.expiresAt }
66
+ input { plan: ref<plans> }
67
+ requires input.plan.funds == self.funds; requires input.plan.borrower == self.buyer
68
+ invoke: [{ reference: input.plan, action: disburse, input: {} }]
69
+ }
70
+ action convert_cash {
71
+ from: active, to: active, actor: { party: buyer }, deadline: { at: self.expiresAt }
72
+ invoke: [{ reference: self.funds, action: fund, input: {} }]
73
+ }
74
+ action credit {
75
+ from: active, to: converted, actor: { parent: converters }, deadline: { at: self.expiresAt }
76
+ input { funds: ref<funds>, contribution: money }
77
+ requires input.funds == self.funds; requires input.funds in [pending, funded]; requires input.funds.payer == self.buyer; requires input.funds.price == self.price
78
+ requires input.contribution <= self.price
79
+ calculate: [{ target: credit, op: minimum, values: [{ field: self.held.balance }, { field: input.contribution }] }, { target: refund, op: subtract, base: { field: self.held.balance }, subtract: [{ field: self.credit }] }]
80
+ set: { dispositionAt: { field: self.now } }
81
+ moves self.credit from self.held to input.funds.held
82
+ moves self.refund from self.held to self.buyer
83
+ }
84
+ action cancel {
85
+ from: active, to: cancelled, actor: { party: buyer }, input { reason: text }
86
+ calculate: [{ target: refund, op: rate, base: { field: self.held.balance }, bps: { literal: cancellation_refund }, rounding: floor }, { target: retained, op: subtract, base: { field: self.held.balance }, subtract: [{ field: self.refund }] }]
87
+ set: { reason: { field: input.reason }, dispositionAt: { field: self.now } }
88
+ moves self.refund from self.held to self.buyer; moves self.retained from self.held to retained_to
89
+ }
90
+ action seller_cancel {
91
+ from: active, to: cancelled, actor: { party: seller }, input { reason: text }
92
+ set: { reason: { field: input.reason }, dispositionAt: { field: self.now } }
93
+ moves self.held.balance from self.held to self.buyer
94
+ }
95
+ action operator_cancel {
96
+ from: active, to: cancelled, actor: { party: operator }, input { reason: text }
97
+ set: { reason: { field: input.reason }, dispositionAt: { field: self.now } }
98
+ moves self.held.balance from self.held to self.buyer
99
+ }
100
+ action withdraw { from: proposed, to: cancelled, actor: { party: buyer } }
101
+ action expire {
102
+ from: active, to: expired, actor: clock, due: { at: self.expiresAt }
103
+ calculate: [{ target: refund, op: rate, base: { field: self.held.balance }, bps: { literal: expiry_refund }, rounding: floor }, { target: retained, op: subtract, base: { field: self.held.balance }, subtract: [{ field: self.refund }] }]
104
+ set: { dispositionAt: { field: self.now } }
105
+ moves self.refund from self.held to self.buyer; moves self.retained from self.held to retained_to
106
+ }
107
+ action expire_proposal { from: proposed, to: expired, actor: clock, due: { at: self.proposalExpiresAt } }
24
108
  }
package/std/money.hsx CHANGED
@@ -130,23 +130,24 @@ instrument deposit(payer: party, payee: party, amount: money, expires: date, app
130
130
  action cancel { from: pending, to: cancelled }
131
131
  }
132
132
 
133
- instrument payout(payer: party, payee: party, amount: money = runtime, reconcile_within: duration = 3d) {
134
- summary: "A bank-linked transfer with confirmation bound to its captured identity."
135
- fields { amount: money = amount, bank: account(payee, cash, external, "bank"), receipt: text?, expectedAt: date = after(self.createdAt, reconcile_within) }
136
- lifecycle { states: [pending, instructed, settled, exception, reversed], initial: pending }
133
+ instrument payout(payer: party, payee: party, adapter: text, max_age: duration, amount: money = runtime) {
134
+ summary: "Reserve funds until matching terminal boundary evidence permits posting."
135
+ fields { amount: money = amount, receipt: text? }
136
+ lifecycle { states: [pending, instructed, settled, rejected], initial: pending }
137
137
  action create {}
138
- action instruct { from: pending, to: instructed, actor: { party: payer }, moves self.amount from payer to self.bank capture "receipt" }
139
- action confirm {
140
- from: [instructed, exception], to: settled
141
- requires self.receipt.status == "settled"
138
+ action instruct {
139
+ from: pending, to: instructed, actor: { party: payer }, humanApproval: "distinct_member"
140
+ moves reserve self.amount from payer to payee capture "receipt" boundary adapter
142
141
  }
143
- action expire {
144
- from: instructed, to: exception, actor: clock, due: { at: self.expectedAt }
145
- requires self.receipt.status != "settled"
142
+ action confirm {
143
+ from: instructed, to: settled
144
+ requires evidence self.id family boundary check outcome result confirmed maxAge max_age instruction self.receipt
145
+ moves post self.receipt
146
146
  }
147
- action reverse {
148
- from: [instructed, exception], to: reversed
149
- requires self.receipt.status == "reversed"
147
+ action reject {
148
+ from: instructed, to: rejected
149
+ requires evidence self.id family boundary check outcome result rejected maxAge max_age instruction self.receipt
150
+ moves void self.receipt
150
151
  }
151
152
  }
152
153
 
@@ -158,38 +159,3 @@ instrument metered(payer: party, payee: party, unit_price: money, units: integer
158
159
  action bill { from: recorded, to: billed, moves self.amount from payer to payee fee fee }
159
160
  action cancel { from: recorded, to: cancelled }
160
161
  }
161
-
162
- instrument batch(payer: party, payee: party, closes: date, approval: approval, reconcile_within: duration = 3d) {
163
- summary: "A frozen positive net of credit and debit entries, paid once."
164
- fields { closesAt: date = closes, credits: money, debits: money, amount: money = subtract(self.credits, self.debits), bank: account(payee, cash, external, "bank"), receipt: text?, instructedAt: date?, expectedAt: date? }
165
- lifecycle { states: [open, closed, approved, instructed, exception, paid, reversed], initial: open }
166
- action create {}
167
- action close {
168
- from: open, to: closed, actor: clock, due: { at: self.closesAt }
169
- requires sum "amount" of { instrument: credit, reference: "batch", anchor: self.id, states: [recorded], limit: 366 } == self.credits
170
- requires sum "amount" of { instrument: debit, reference: "batch", anchor: self.id, states: [recorded], limit: 366 } == self.debits
171
- requires self.amount > "0"
172
- }
173
- action approve { from: closed, to: approved, requires approval by approval }
174
- action pay {
175
- from: approved, to: instructed
176
- set: { instructedAt: { field: self.now } }
177
- calculate: [{ target: "expectedAt", op: "shift", date: { field: self.now }, milliseconds: { literal: reconcile_within }, direction: "after" }]
178
- moves self.amount from payer to self.bank capture "receipt"
179
- }
180
- action confirm { from: [instructed, exception], to: paid, requires self.receipt.status == "settled" }
181
- action expire { from: instructed, to: exception, actor: clock, due: { at: self.expectedAt }, requires self.receipt.status != "settled" }
182
- action reverse { from: [instructed, exception], to: reversed, requires self.receipt.status == "reversed" }
183
- records {
184
- credit: {
185
- fields { batch: ref<parent>, identity: text, amount: money }
186
- lifecycle { states: [recorded], initial: recorded }
187
- action create { requires self.batch in [open]; requires unique "batch_credit" on [self.identity] }
188
- }
189
- debit: {
190
- fields { batch: ref<parent>, identity: text, amount: money }
191
- lifecycle { states: [recorded], initial: recorded }
192
- action create { requires self.batch in [open]; requires unique "batch_debit" on [self.identity] }
193
- }
194
- }
195
- }