@hyperscale0/hsx 5.4.2 → 5.5.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.
- package/CHANGELOG.md +6 -0
- package/dist/src/compile.d.ts.map +1 -1
- package/dist/src/compile.js +80 -0
- package/dist/src/compile.js.map +1 -1
- package/dist/src/parse.js +2 -0
- package/dist/src/parse.js.map +1 -1
- package/dist/src/std-bundle.js +10 -10
- package/dist/src/std-bundle.js.map +1 -1
- package/dist/src/version.d.ts +1 -1
- package/dist/src/version.js +1 -1
- package/docs/README.md +40 -0
- package/package.json +4 -4
- package/src/compile.ts +128 -0
- package/src/parse.ts +1 -0
- package/src/std-bundle.ts +10 -10
- package/src/version.ts +1 -1
- package/std/collections.hsx +4 -1
- package/std/escrow.hsx +7 -4
- package/std/financing.hsx +49 -44
- package/std/insurance.hsx +7 -3
- package/std/lending.hsx +11 -7
- package/std/marketplace.hsx +10 -7
- package/std/money.hsx +10 -6
- package/std/savings.hsx +4 -2
- package/std/travel.hsx +21 -17
- package/std/wallet.hsx +5 -2
package/src/version.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export const HSX_VERSION = "5.
|
|
1
|
+
export const HSX_VERSION = "5.5.0";
|
package/std/collections.hsx
CHANGED
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
header collections
|
|
2
2
|
|
|
3
|
+
// Economics: Company capital pays agencies as participant payouts; outside capital passes through.
|
|
4
|
+
// A company agency earns outside capital fees; its own capital fee is internal.
|
|
5
|
+
|
|
3
6
|
// Expose case.create, assign and recover as separate steps. Creation needs overdue
|
|
4
7
|
// outstanding principal and a matching slice/plan. Assignment belongs to capital;
|
|
5
8
|
// recovery belongs to agency and pays the linked payment before the agency fee.
|
|
@@ -28,7 +31,7 @@ instrument case(on: ref<financing.installments>[], agency: party, capital: party
|
|
|
28
31
|
}
|
|
29
32
|
action assign { from: opened, to: assigned, actor: { party: capital } }
|
|
30
33
|
action recover { expansionLimit: 8192, from: assigned, to: recovered, actor: { party: agency }, requires self.payment.plan == self.plan, invoke: [{ reference: self.payment, action: pay, input: {} }, { reference: self.id, action: pay_fee, input: {} }] }
|
|
31
|
-
action pay_fee { allowZero: true, from: recovered, to: recovered, actor: { parent: current() }, moves self.agencyFee from self.plan.capital to agency }
|
|
34
|
+
action pay_fee { allowZero: true, from: recovered, to: recovered, actor: { parent: current() }, moves self.agencyFee from self.plan.capital to agency economics { recipient: agency, company: { recipient: capital, company: { purpose: internal, sourceParty: capital }, participant: { purpose: earning, sourceParty: capital } }, participant: { recipient: capital, company: { purpose: participant_payout, sourceParty: capital }, participant: { purpose: pass_through, sourceParty: capital } } } }
|
|
32
35
|
action recall { from: [opened, assigned], to: recalled, actor: { party: capital } }
|
|
33
36
|
action return_uncollected { from: assigned, to: returned_uncollected, actor: { party: agency } }
|
|
34
37
|
}
|
package/std/escrow.hsx
CHANGED
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
header escrow
|
|
2
2
|
|
|
3
|
+
// Economics: Funding and unspent returns are principal. Acceptance realizes earnings for
|
|
4
|
+
// the company or a payout to a bound outside seller; tax is pass-through.
|
|
5
|
+
|
|
3
6
|
// Expose create, fund, deliver and accept for the purchase path. Create captures
|
|
4
7
|
// subject.price; acceptance pays payee less the configured fee, not payer.
|
|
5
8
|
// Expose dispute, verify_return and refund separately for the return path.
|
|
@@ -31,7 +34,7 @@ instrument hold(payer: party = party(person), payee: party = programOperator, ac
|
|
|
31
34
|
action fund {
|
|
32
35
|
from: pending, to: funded, actor: { party: payer }
|
|
33
36
|
subject { price: money }
|
|
34
|
-
moves self.price from payer to self.held
|
|
37
|
+
moves self.price from payer to self.held economics { purpose: principal, sourceParty: payer }
|
|
35
38
|
}
|
|
36
39
|
action confirm {
|
|
37
40
|
from: pending, to: funded
|
|
@@ -45,7 +48,7 @@ instrument hold(payer: party = party(person), payee: party = programOperator, ac
|
|
|
45
48
|
from: delivered, to: released, actor: { party: payer }
|
|
46
49
|
input { acceptanceReference: text }
|
|
47
50
|
deadline: { at: self.deliveredAt, offset: accept_within }
|
|
48
|
-
moves self.price from self.held to payee fee fee
|
|
51
|
+
moves self.price from self.held to payee fee fee economics { payee: { recipient: payee, company: { purpose: earning, sourceParty: payer }, participant: { purpose: participant_payout, sourceParty: programOperator } }, fee: { purpose: earning, sourceParty: payer }, tax: { purpose: pass_through, sourceParty: programOperator } }
|
|
49
52
|
}
|
|
50
53
|
action expire_acceptance {
|
|
51
54
|
from: delivered, to: disputed, actor: clock
|
|
@@ -61,10 +64,10 @@ instrument hold(payer: party = party(person), payee: party = programOperator, ac
|
|
|
61
64
|
}
|
|
62
65
|
action refund {
|
|
63
66
|
from: dispute.refund_after, to: refunded, actor: { party: payee }
|
|
64
|
-
moves self.price from self.held to payer
|
|
67
|
+
moves self.price from self.held to payer economics { purpose: principal, sourceParty: programOperator }
|
|
65
68
|
}
|
|
66
69
|
action cancel { allowZero: true,
|
|
67
70
|
from: pending, to: cancelled, actor: { party: payer }
|
|
68
|
-
moves self.held.balance from self.held to payer
|
|
71
|
+
moves self.held.balance from self.held to payer economics { purpose: principal, sourceParty: programOperator }
|
|
69
72
|
}
|
|
70
73
|
}
|
package/std/financing.hsx
CHANGED
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
header financing
|
|
2
2
|
|
|
3
|
+
// Economics: Principal advances and repayments are excluded from earnings. Claims, waivers,
|
|
4
|
+
// write-offs and allocations are internal. Paid profit and company charges are
|
|
5
|
+
// earnings; receipt refunds reverse captured cash. Outside recovery recipients
|
|
6
|
+
// receive payouts from held company cash, or pass-through direct customer cash.
|
|
7
|
+
|
|
3
8
|
// Expose create and sign on installments, then collect_down_payment as checkout
|
|
4
9
|
// for disburse_to: funds. Checkout requires a signed plan and pending escrow;
|
|
5
10
|
// it tops up only the missing down payment, without advancing lender principal.
|
|
@@ -68,7 +73,7 @@ instrument installments(months: integer(1, 366), charge_limit: integer(1, 3) = 3
|
|
|
68
73
|
when disburse_to is funds {
|
|
69
74
|
requires self.funds in [pending]
|
|
70
75
|
calculate: [{ target: downPaymentCredit, op: minimum, values: [{ field: self.funds.held.balance }, { field: self.downPayment }] }, { target: downPaymentRemaining, op: subtract, base: { field: self.downPayment }, subtract: [{ field: self.downPaymentCredit }] }]
|
|
71
|
-
moves self.downPaymentRemaining from self.borrower to self.funds.held
|
|
76
|
+
moves self.downPaymentRemaining from self.borrower to self.funds.held economics { purpose: principal, sourceParty: borrower }
|
|
72
77
|
}
|
|
73
78
|
}
|
|
74
79
|
action disburse { allowZero: true,
|
|
@@ -79,7 +84,7 @@ instrument installments(months: integer(1, 366), charge_limit: integer(1, 3) = 3
|
|
|
79
84
|
requires self.funds in [pending]
|
|
80
85
|
invoke: [{ reference: self.id, action: fund_down_payment, input: {} }]
|
|
81
86
|
}
|
|
82
|
-
when disburse_to is borrower { moves self.principal from self.capital to self.borrower }
|
|
87
|
+
when disburse_to is borrower { moves self.principal from self.capital to self.borrower economics { purpose: principal, sourceParty: capital } }
|
|
83
88
|
invoke: [{ selection: { instrument: slice, reference: "plan", anchor: self.id, states: [draft], limit: 366, order: [position] }, action: activate, input: {} }]
|
|
84
89
|
when disburse_to is funds { invoke: [{ reference: self.funds, action: confirm, input: {} }] }
|
|
85
90
|
}
|
|
@@ -87,8 +92,8 @@ instrument installments(months: integer(1, 366), charge_limit: integer(1, 3) = 3
|
|
|
87
92
|
from: active, to: active, actor: { parent: current() }
|
|
88
93
|
when disburse_to is funds {
|
|
89
94
|
calculate: [{ target: downPaymentCredit, op: minimum, values: [{ field: self.funds.held.balance }, { field: self.downPayment }] }, { target: downPaymentRemaining, op: subtract, base: { field: self.downPayment }, subtract: [{ field: self.downPaymentCredit }] }]
|
|
90
|
-
moves self.downPaymentRemaining from self.funds.payer to self.funds.held
|
|
91
|
-
moves self.principal from self.capital to self.funds.held
|
|
95
|
+
moves self.downPaymentRemaining from self.funds.payer to self.funds.held economics { purpose: principal, sourceParty: borrower }
|
|
96
|
+
moves self.principal from self.capital to self.funds.held economics { purpose: principal, sourceParty: capital }
|
|
92
97
|
}
|
|
93
98
|
}
|
|
94
99
|
action complete {
|
|
@@ -233,11 +238,11 @@ instrument installments(months: integer(1, 366), charge_limit: integer(1, 3) = 3
|
|
|
233
238
|
input { plan: ref<parent>, identity: text, principal: money, profit: money, loss: money, kind: enum(cash, loss) }
|
|
234
239
|
requires unique "settlement_identity" on [self.plan, self.identity]
|
|
235
240
|
calculate: [{ target: "share", op: "rate", base: { field: self.profit }, bps: { literal: share }, rounding: "floor" }, { target: retainedProfit, op: "subtract", base: { field: self.profit }, subtract: [{ field: self.share }] }]
|
|
236
|
-
moves self.share from self.profitIncome to self.allocatedPayable
|
|
241
|
+
moves self.share from self.profitIncome to self.allocatedPayable economics { purpose: internal, sourceParty: capital }
|
|
237
242
|
}
|
|
238
243
|
action refund { allowZero: true,
|
|
239
244
|
from: recorded, to: refunded, actor: { parent: payment }
|
|
240
|
-
moves self.share from self.allocatedPayable to self.profitIncome
|
|
245
|
+
moves self.share from self.allocatedPayable to self.profitIncome economics { purpose: internal, sourceParty: capital }
|
|
241
246
|
}
|
|
242
247
|
}
|
|
243
248
|
slice: {
|
|
@@ -303,9 +308,9 @@ instrument installments(months: integer(1, 366), charge_limit: integer(1, 3) = 3
|
|
|
303
308
|
}
|
|
304
309
|
action activate { allowZero: true,
|
|
305
310
|
from: draft, to: pending, actor: { parent: parent }
|
|
306
|
-
moves self.principal from self.debt to self.principalReceivable
|
|
307
|
-
moves self.profit from self.debt to self.profitReceivable
|
|
308
|
-
when profit_earned is at_disbursement { moves self.profit from self.profitReceivable to self.profitEarned }
|
|
311
|
+
moves self.principal from self.debt to self.principalReceivable economics { purpose: internal, sourceParty: borrower }
|
|
312
|
+
moves self.profit from self.debt to self.profitReceivable economics { purpose: internal, sourceParty: borrower }
|
|
313
|
+
when profit_earned is at_disbursement { moves self.profit from self.profitReceivable to self.profitEarned economics { purpose: internal, sourceParty: programOperator } }
|
|
309
314
|
when profit_earned is by_schedule { invoke: [{ instrument: recognition, action: create, input: { slice: { field: self.id } } }] }
|
|
310
315
|
}
|
|
311
316
|
action mature {
|
|
@@ -370,15 +375,15 @@ instrument installments(months: integer(1, 366), charge_limit: integer(1, 3) = 3
|
|
|
370
375
|
from: [pending, due], to: paid, actor: { parent: parent }, input { identity: text }
|
|
371
376
|
set: { payoffIdentity: { field: input.identity } }
|
|
372
377
|
calculate: [{ target: payoffRebate, op: rate, base: { field: self.profitReceivable.balance }, bps: { literal: payoff_rebate }, rounding: floor }, { target: payoffProfitTotal, op: sum, values: [{ field: self.profitReceivable.balance }, { field: self.profitEarned.balance }] }, { target: payoffProfit, op: subtract, base: { field: self.payoffProfitTotal }, subtract: [{ field: self.payoffRebate }] }]
|
|
373
|
-
moves self.principalReceivable.balance from self.plan.borrower to self.plan.capital
|
|
374
|
-
moves self.payoffProfit from self.plan.borrower to self.plan.profitIncome
|
|
375
|
-
moves self.principalReceivable.balance from self.principalReceivable to self.debt
|
|
376
|
-
moves self.profitReceivable.balance from self.profitReceivable to self.debt
|
|
377
|
-
moves self.profitEarned.balance from self.profitEarned to self.debt
|
|
378
|
+
moves self.principalReceivable.balance from self.plan.borrower to self.plan.capital economics { purpose: principal, sourceParty: borrower }
|
|
379
|
+
moves self.payoffProfit from self.plan.borrower to self.plan.profitIncome economics { recipient: capital, company: { purpose: earning, sourceParty: borrower }, participant: { purpose: pass_through, sourceParty: borrower } }
|
|
380
|
+
moves self.principalReceivable.balance from self.principalReceivable to self.debt economics { purpose: internal, sourceParty: programOperator }
|
|
381
|
+
moves self.profitReceivable.balance from self.profitReceivable to self.debt economics { purpose: internal, sourceParty: programOperator }
|
|
382
|
+
moves self.profitEarned.balance from self.profitEarned to self.debt economics { purpose: internal, sourceParty: programOperator }
|
|
378
383
|
}
|
|
379
384
|
action write_off { allowZero: true,
|
|
380
385
|
from: [pending, due], to: written_off, actor: { parent: parent }
|
|
381
|
-
moves self.principalReceivable.balance from self.principalReceivable to self.loss; moves self.profitReceivable.balance from self.profitReceivable to self.debt; moves self.profitEarned.balance from self.profitEarned to self.loss
|
|
386
|
+
moves self.principalReceivable.balance from self.principalReceivable to self.loss economics { purpose: internal, sourceParty: programOperator }; moves self.profitReceivable.balance from self.profitReceivable to self.debt economics { purpose: internal, sourceParty: programOperator }; moves self.profitEarned.balance from self.profitEarned to self.loss economics { purpose: internal, sourceParty: programOperator }
|
|
382
387
|
}
|
|
383
388
|
}
|
|
384
389
|
recognition: {
|
|
@@ -386,7 +391,7 @@ instrument installments(months: integer(1, 366), charge_limit: integer(1, 3) = 3
|
|
|
386
391
|
lifecycle { states: [pending, recognised], initial: pending }
|
|
387
392
|
action create { actor: { parent: slice }, input { slice: ref<slice> }, requires unique "profit_recognition" on [self.slice] }
|
|
388
393
|
action reschedule { from: pending, to: pending, actor: { parent: slice }, calculate: [{ target: dueAt, op: shift, date: { field: self.slice.dueAt }, milliseconds: { literal: 0 }, direction: after }] }
|
|
389
|
-
action mature { allowZero: true, from: pending, to: recognised, actor: clock, due: { at: self.dueAt }, moves self.slice.profitReceivable.balance from self.slice.profitReceivable to self.slice.profitEarned }
|
|
394
|
+
action mature { allowZero: true, from: pending, to: recognised, actor: clock, due: { at: self.dueAt }, moves self.slice.profitReceivable.balance from self.slice.profitReceivable to self.slice.profitEarned economics { purpose: internal, sourceParty: programOperator } }
|
|
390
395
|
}
|
|
391
396
|
payment: {
|
|
392
397
|
revisioned: true
|
|
@@ -408,7 +413,7 @@ instrument installments(months: integer(1, 366), charge_limit: integer(1, 3) = 3
|
|
|
408
413
|
when apply is principal_profit { calculate: [{ target: outstandingTotal, op: sum, values: [{ field: self.outstandingPrincipal }, { field: self.outstandingProfit }] }] }
|
|
409
414
|
when apply is pro_rata { calculate: [{ target: outstandingTotal, op: sum, values: [{ field: self.outstandingPrincipal }, { field: self.outstandingProfit }] }] }
|
|
410
415
|
requires self.plan in [active]; requires self.amount <= self.outstandingTotal
|
|
411
|
-
moves self.amount from self.plan.borrower to self.held
|
|
416
|
+
moves self.amount from self.plan.borrower to self.held economics { purpose: principal, sourceParty: borrower }
|
|
412
417
|
when apply is principal_profit {
|
|
413
418
|
invoke: [{ selection: { instrument: slice, reference: "plan", anchor: self.plan, states: [pending, due], limit: 366, order: [position] }, action: collect, guard: { kind: compare, left: { field: self.held.balance }, operator: ">", right: { literal: "0" } }, input: { payment: { field: self.id } } }]
|
|
414
419
|
}
|
|
@@ -445,32 +450,32 @@ instrument installments(months: integer(1, 366), charge_limit: integer(1, 3) = 3
|
|
|
445
450
|
actor: { parent: slice }
|
|
446
451
|
input { slice: ref<slice>, payment: ref<payment>, limit: money }
|
|
447
452
|
requires unique "principal_receipt" on [self.slice, self.payment]
|
|
448
|
-
moves self.amount from self.payment.held to self.slice.plan.capital; moves self.amount from self.slice.principalReceivable to self.slice.debt
|
|
453
|
+
moves self.amount from self.payment.held to self.slice.plan.capital economics { purpose: principal, sourceParty: programOperator }; moves self.amount from self.slice.principalReceivable to self.slice.debt economics { purpose: internal, sourceParty: programOperator }
|
|
449
454
|
}
|
|
450
455
|
action refund { allowZero: true,
|
|
451
456
|
from: paid, to: refunded, actor: { parent: payment }
|
|
452
|
-
moves self.amount from self.slice.plan.capital to self.slice.plan.borrower; moves self.amount from self.slice.debt to self.slice.principalReceivable
|
|
457
|
+
moves self.amount from self.slice.plan.capital to self.slice.plan.borrower economics { purpose: principal, sourceParty: capital }; moves self.amount from self.slice.debt to self.slice.principalReceivable economics { purpose: internal, sourceParty: borrower }
|
|
453
458
|
}
|
|
454
459
|
}
|
|
455
460
|
profit_piece: {
|
|
456
|
-
fields { slice: ref<slice>, payment: ref<payment>, limit: money, amount: money? }
|
|
461
|
+
fields { cashReceipt: text?, slice: ref<slice>, payment: ref<payment>, limit: money, amount: money? }
|
|
457
462
|
lifecycle { states: [paid, refunded], initial: paid }
|
|
458
463
|
action create { allowZero: true,
|
|
459
464
|
calculate: [{ target: amount, op: minimum, values: [{ field: self.payment.held.balance }, { field: self.limit }] }]
|
|
460
465
|
actor: { parent: slice }
|
|
461
466
|
input { slice: ref<slice>, payment: ref<payment>, limit: money }
|
|
462
467
|
requires unique "profit_receipt" on [self.slice, self.payment]
|
|
463
|
-
moves self.amount from self.payment.held to self.slice.plan.profitIncome
|
|
464
|
-
when profit_earned is on_payment { moves self.amount from self.slice.profitReceivable to self.slice.debt }
|
|
465
|
-
when profit_earned is by_schedule { moves self.amount from self.slice.profitEarned to self.slice.debt }
|
|
466
|
-
when profit_earned is at_disbursement { moves self.amount from self.slice.profitEarned to self.slice.debt }
|
|
468
|
+
moves self.amount from self.payment.held to self.slice.plan.profitIncome capture "cashReceipt" economics { recipient: capital, company: { purpose: earning, sourceParty: borrower }, participant: { purpose: participant_payout, sourceParty: programOperator } }
|
|
469
|
+
when profit_earned is on_payment { moves self.amount from self.slice.profitReceivable to self.slice.debt economics { purpose: internal, sourceParty: programOperator } }
|
|
470
|
+
when profit_earned is by_schedule { moves self.amount from self.slice.profitEarned to self.slice.debt economics { purpose: internal, sourceParty: programOperator } }
|
|
471
|
+
when profit_earned is at_disbursement { moves self.amount from self.slice.profitEarned to self.slice.debt economics { purpose: internal, sourceParty: programOperator } }
|
|
467
472
|
}
|
|
468
473
|
action refund { allowZero: true,
|
|
469
474
|
from: paid, to: refunded, actor: { parent: payment }
|
|
470
|
-
moves self.amount from self.slice.plan.profitIncome to self.slice.plan.borrower
|
|
471
|
-
when profit_earned is on_payment { moves self.amount from self.slice.debt to self.slice.profitReceivable }
|
|
472
|
-
when profit_earned is by_schedule { moves self.amount from self.slice.debt to self.slice.profitEarned }
|
|
473
|
-
when profit_earned is at_disbursement { moves self.amount from self.slice.debt to self.slice.profitEarned }
|
|
475
|
+
moves self.amount from self.slice.plan.profitIncome to self.slice.plan.borrower economics { recipient: capital, company: { purpose: earning, sourceParty: capital, reversalOf: self.cashReceipt }, participant: unclassified }
|
|
476
|
+
when profit_earned is on_payment { moves self.amount from self.slice.debt to self.slice.profitReceivable economics { purpose: internal, sourceParty: borrower } }
|
|
477
|
+
when profit_earned is by_schedule { moves self.amount from self.slice.debt to self.slice.profitEarned economics { purpose: internal, sourceParty: borrower } }
|
|
478
|
+
when profit_earned is at_disbursement { moves self.amount from self.slice.debt to self.slice.profitEarned economics { purpose: internal, sourceParty: borrower } }
|
|
474
479
|
}
|
|
475
480
|
}
|
|
476
481
|
}
|
|
@@ -496,7 +501,7 @@ instrument late_charge(on: ref<financing.installments>[], grace: duration = 3d,
|
|
|
496
501
|
action assess { allowZero: true,
|
|
497
502
|
from: proposed, to: assessed, actor: clock, due: { at: self.overdueAt }
|
|
498
503
|
requires self.slice.principalReceivable.balance > "0"
|
|
499
|
-
moves self.fine from self.debt to self.receivable
|
|
504
|
+
moves self.fine from self.debt to self.receivable economics { purpose: internal, sourceParty: borrower }
|
|
500
505
|
}
|
|
501
506
|
action collect {
|
|
502
507
|
from: [assessed, collected], to: assessed, actor: { parent: child(on, slice) }, input { payment: ref<on.payment> }
|
|
@@ -507,8 +512,8 @@ instrument late_charge(on: ref<financing.installments>[], grace: duration = 3d,
|
|
|
507
512
|
action payoff { allowZero: true,
|
|
508
513
|
from: [assessed, collected], to: collected, actor: { parent: on }
|
|
509
514
|
requires self.plan in [paid]
|
|
510
|
-
moves self.receivable.balance from self.plan.borrower to fines_to
|
|
511
|
-
moves self.receivable.balance from self.receivable to self.debt
|
|
515
|
+
moves self.receivable.balance from self.plan.borrower to fines_to economics { recipient: fines_to, company: { purpose: earning, sourceParty: borrower }, participant: { purpose: pass_through, sourceParty: borrower } }
|
|
516
|
+
moves self.receivable.balance from self.receivable to self.debt economics { purpose: internal, sourceParty: programOperator }
|
|
512
517
|
}
|
|
513
518
|
action finish { from: assessed, to: collected, actor: { parent: current() }, requires self.receivable.balance == "0" }
|
|
514
519
|
action cancel { from: proposed, to: waived }
|
|
@@ -517,7 +522,7 @@ instrument late_charge(on: ref<financing.installments>[], grace: duration = 3d,
|
|
|
517
522
|
requires input.amendment.plan == self.plan; requires input.amendment in [applied]
|
|
518
523
|
invoke: [{ instrument: waiver, action: create, input: { assessment: { field: self.id }, amendment: { field: input.amendment } } }]
|
|
519
524
|
}
|
|
520
|
-
action waive { allowZero: true, from: [assessed, collected], to: waived, actor: { parent: waiver_request }, input { reason: text, evidence: text }, moves self.receivable.balance from self.receivable to self.debt }
|
|
525
|
+
action waive { allowZero: true, from: [assessed, collected], to: waived, actor: { parent: waiver_request }, input { reason: text, evidence: text }, moves self.receivable.balance from self.receivable to self.debt economics { purpose: internal, sourceParty: programOperator } }
|
|
521
526
|
action refund {
|
|
522
527
|
from: [assessed, collected], to: assessed, actor: { party: fines_to }, input { payment: ref<on.payment> }
|
|
523
528
|
requires input.payment in [paid, refunded]
|
|
@@ -542,14 +547,14 @@ instrument late_charge(on: ref<financing.installments>[], grace: duration = 3d,
|
|
|
542
547
|
actor: { parent: parent }, input { assessment: ref<parent>, amendment: ref<on.amendment> }
|
|
543
548
|
calculate: [{ target: amount, op: rate, base: { field: self.assessment.receivable.balance }, bps: { field: self.amendment.waiverPercent }, rounding: floor }]
|
|
544
549
|
requires unique "amendment_waiver" on [self.assessment, self.amendment]
|
|
545
|
-
moves self.amount from self.assessment.receivable to self.assessment.debt
|
|
550
|
+
moves self.amount from self.assessment.receivable to self.assessment.debt economics { purpose: internal, sourceParty: programOperator }
|
|
546
551
|
}
|
|
547
552
|
}
|
|
548
553
|
receipt: {
|
|
549
|
-
fields { assessment: ref<parent>, payment: ref<on.payment>, amount: money? }
|
|
554
|
+
fields { cashReceipt: text?, assessment: ref<parent>, payment: ref<on.payment>, amount: money? }
|
|
550
555
|
lifecycle { states: [paid, refunded], initial: paid }
|
|
551
|
-
action create { allowZero: true, calculate: [{ target: amount, op: minimum, values: [{ field: self.payment.held.balance }, { field: self.assessment.receivable.balance }] }], actor: { parent: parent }, input { assessment: ref<parent>, payment: ref<on.payment> }, requires input.payment.plan == self.assessment.plan; requires unique "fine_receipt" on [self.assessment, self.payment]; moves self.amount from self.payment.held to fines_to; moves self.amount from self.assessment.receivable to self.assessment.debt }
|
|
552
|
-
action refund { allowZero: true, from: paid, to: refunded, actor: { parent: parent }, moves self.amount from fines_to to self.payment.plan.borrower; moves self.amount from self.assessment.debt to self.assessment.receivable }
|
|
556
|
+
action create { allowZero: true, calculate: [{ target: amount, op: minimum, values: [{ field: self.payment.held.balance }, { field: self.assessment.receivable.balance }] }], actor: { parent: parent }, input { assessment: ref<parent>, payment: ref<on.payment> }, requires input.payment.plan == self.assessment.plan; requires unique "fine_receipt" on [self.assessment, self.payment]; moves self.amount from self.payment.held to fines_to capture "cashReceipt" economics { recipient: fines_to, company: { purpose: earning, sourceParty: borrower }, participant: { purpose: participant_payout, sourceParty: programOperator } }; moves self.amount from self.assessment.receivable to self.assessment.debt economics { purpose: internal, sourceParty: programOperator } }
|
|
557
|
+
action refund { allowZero: true, from: paid, to: refunded, actor: { parent: parent }, moves self.amount from fines_to to self.payment.plan.borrower economics { recipient: fines_to, company: { purpose: earning, sourceParty: fines_to, reversalOf: self.cashReceipt }, participant: unclassified }; moves self.amount from self.assessment.debt to self.assessment.receivable economics { purpose: internal, sourceParty: borrower } }
|
|
553
558
|
}
|
|
554
559
|
|
|
555
560
|
cost: {
|
|
@@ -563,7 +568,7 @@ instrument late_charge(on: ref<financing.installments>[], grace: duration = 3d,
|
|
|
563
568
|
action assess { allowZero: true,
|
|
564
569
|
from: proposed, to: assessed, actor: clock, due: { at: self.assessment.overdueAt }
|
|
565
570
|
requires self.assessment.slice.principalReceivable.balance > "0"
|
|
566
|
-
moves self.amount from self.debt to self.receivable
|
|
571
|
+
moves self.amount from self.debt to self.receivable economics { purpose: internal, sourceParty: borrower }
|
|
567
572
|
}
|
|
568
573
|
action collect {
|
|
569
574
|
from: [assessed, collected], to: assessed, actor: { parent: child(on, slice) }, input { payment: ref<on.payment> }
|
|
@@ -574,8 +579,8 @@ instrument late_charge(on: ref<financing.installments>[], grace: duration = 3d,
|
|
|
574
579
|
action payoff { allowZero: true,
|
|
575
580
|
from: [assessed, collected], to: collected, actor: { parent: on }
|
|
576
581
|
requires self.plan in [paid]
|
|
577
|
-
moves self.receivable.balance from self.plan.borrower to costs_to
|
|
578
|
-
moves self.receivable.balance from self.receivable to self.debt
|
|
582
|
+
moves self.receivable.balance from self.plan.borrower to costs_to economics { recipient: costs_to, company: { purpose: earning, sourceParty: borrower }, participant: { purpose: pass_through, sourceParty: borrower } }
|
|
583
|
+
moves self.receivable.balance from self.receivable to self.debt economics { purpose: internal, sourceParty: programOperator }
|
|
579
584
|
}
|
|
580
585
|
action finish { from: assessed, to: collected, actor: { parent: current() }, requires self.receivable.balance == "0" }
|
|
581
586
|
action cancel { from: proposed, to: waived }
|
|
@@ -584,7 +589,7 @@ instrument late_charge(on: ref<financing.installments>[], grace: duration = 3d,
|
|
|
584
589
|
requires input.amendment.plan == self.plan; requires input.amendment in [applied]
|
|
585
590
|
invoke: [{ instrument: waiver, action: create, input: { assessment: { field: self.id }, amendment: { field: input.amendment } } }]
|
|
586
591
|
}
|
|
587
|
-
action waive { allowZero: true, from: [assessed, collected], to: waived, actor: { parent: waiver_request }, input { reason: text, evidence: text }, moves self.receivable.balance from self.receivable to self.debt }
|
|
592
|
+
action waive { allowZero: true, from: [assessed, collected], to: waived, actor: { parent: waiver_request }, input { reason: text, evidence: text }, moves self.receivable.balance from self.receivable to self.debt economics { purpose: internal, sourceParty: programOperator } }
|
|
588
593
|
action refund {
|
|
589
594
|
from: [assessed, collected], to: assessed, actor: { party: costs_to }, input { payment: ref<on.payment> }
|
|
590
595
|
requires input.payment in [paid, refunded]
|
|
@@ -609,14 +614,14 @@ instrument late_charge(on: ref<financing.installments>[], grace: duration = 3d,
|
|
|
609
614
|
actor: { parent: parent }, input { assessment: ref<parent>, amendment: ref<on.amendment> }
|
|
610
615
|
calculate: [{ target: amount, op: rate, base: { field: self.assessment.receivable.balance }, bps: { field: self.amendment.waiverPercent }, rounding: floor }]
|
|
611
616
|
requires unique "amendment_waiver" on [self.assessment, self.amendment]
|
|
612
|
-
moves self.amount from self.assessment.receivable to self.assessment.debt
|
|
617
|
+
moves self.amount from self.assessment.receivable to self.assessment.debt economics { purpose: internal, sourceParty: programOperator }
|
|
613
618
|
}
|
|
614
619
|
}
|
|
615
620
|
receipt: {
|
|
616
|
-
fields { assessment: ref<parent>, payment: ref<on.payment>, amount: money? }
|
|
621
|
+
fields { cashReceipt: text?, assessment: ref<parent>, payment: ref<on.payment>, amount: money? }
|
|
617
622
|
lifecycle { states: [paid, refunded], initial: paid }
|
|
618
|
-
action create { allowZero: true, calculate: [{ target: amount, op: minimum, values: [{ field: self.payment.held.balance }, { field: self.assessment.receivable.balance }] }], actor: { parent: parent }, input { assessment: ref<parent>, payment: ref<on.payment> }, requires input.payment.plan == self.assessment.plan; requires unique "cost_receipt" on [self.assessment, self.payment]; moves self.amount from self.payment.held to costs_to; moves self.amount from self.assessment.receivable to self.assessment.debt }
|
|
619
|
-
action refund { allowZero: true, from: paid, to: refunded, actor: { parent: parent }, moves self.amount from costs_to to self.payment.plan.borrower; moves self.amount from self.assessment.debt to self.assessment.receivable }
|
|
623
|
+
action create { allowZero: true, calculate: [{ target: amount, op: minimum, values: [{ field: self.payment.held.balance }, { field: self.assessment.receivable.balance }] }], actor: { parent: parent }, input { assessment: ref<parent>, payment: ref<on.payment> }, requires input.payment.plan == self.assessment.plan; requires unique "cost_receipt" on [self.assessment, self.payment]; moves self.amount from self.payment.held to costs_to capture "cashReceipt" economics { recipient: costs_to, company: { purpose: earning, sourceParty: borrower }, participant: { purpose: participant_payout, sourceParty: programOperator } }; moves self.amount from self.assessment.receivable to self.assessment.debt economics { purpose: internal, sourceParty: programOperator } }
|
|
624
|
+
action refund { allowZero: true, from: paid, to: refunded, actor: { parent: parent }, moves self.amount from costs_to to self.payment.plan.borrower economics { recipient: costs_to, company: { purpose: earning, sourceParty: costs_to, reversalOf: self.cashReceipt }, participant: unclassified }; moves self.amount from self.assessment.debt to self.assessment.receivable economics { purpose: internal, sourceParty: borrower } }
|
|
620
625
|
}
|
|
621
626
|
}
|
|
622
627
|
}
|
package/std/insurance.hsx
CHANGED
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
header insurance
|
|
2
2
|
|
|
3
|
+
// Economics: Company commission is earning; refunds reverse its captured transfer.
|
|
4
|
+
// Outside broker commissions are pass-through. Adapter-owned premium and claim
|
|
5
|
+
// accounts lack an authored source party, so their moves remain unclassified.
|
|
6
|
+
|
|
3
7
|
// Expose cover.create, activate and cancel separately. Activation binds adapter;
|
|
4
8
|
// each slice needs a separately created unique period and an active cover to collect.
|
|
5
9
|
// Collection debits holder for insurerPremium to the insurer and commission to
|
|
@@ -39,7 +43,7 @@ instrument cover(holder: party, adapter: text, commission: percent = 0%, broker:
|
|
|
39
43
|
fields {
|
|
40
44
|
cover: ref<parent>, covers: ref<covers>, premium: money = premium, startsAt: date, endsAt: date
|
|
41
45
|
commission: money = rate(self.premium, commission)
|
|
42
|
-
insurerPremium: money = subtract(self.premium, self.commission)
|
|
46
|
+
insurerPremium: money = subtract(self.premium, self.commission), commissionReceipt: text?
|
|
43
47
|
}
|
|
44
48
|
lifecycle { states: [pending, paid, active, expired, refunded], initial: pending }
|
|
45
49
|
action create {
|
|
@@ -53,7 +57,7 @@ instrument cover(holder: party, adapter: text, commission: percent = 0%, broker:
|
|
|
53
57
|
from: pending, to: paid, actor: { party: holder }
|
|
54
58
|
requires self.cover in [active]
|
|
55
59
|
moves self.insurerPremium from holder to self.cover.insurer
|
|
56
|
-
moves self.commission from holder to broker
|
|
60
|
+
moves self.commission from holder to broker capture "commissionReceipt" economics { recipient: broker, company: { purpose: earning, sourceParty: holder }, participant: { purpose: pass_through, sourceParty: holder } }
|
|
57
61
|
}
|
|
58
62
|
action start { from: paid, to: active, actor: clock, due: { at: self.startsAt } }
|
|
59
63
|
action expire { from: active, to: expired, actor: clock, due: { at: self.endsAt } }
|
|
@@ -62,7 +66,7 @@ instrument cover(holder: party, adapter: text, commission: percent = 0%, broker:
|
|
|
62
66
|
requires self.premium > "0"
|
|
63
67
|
from: paid, to: refunded, actor: { parent: parent }, deadline: { at: self.startsAt }
|
|
64
68
|
moves self.insurerPremium from self.cover.insurer to holder
|
|
65
|
-
moves self.commission from broker to holder
|
|
69
|
+
moves self.commission from broker to holder economics { recipient: broker, company: { purpose: earning, sourceParty: broker, reversalOf: self.commissionReceipt }, participant: { purpose: pass_through, sourceParty: broker } }
|
|
66
70
|
}
|
|
67
71
|
}
|
|
68
72
|
}
|
package/std/lending.hsx
CHANGED
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
header lending
|
|
2
2
|
|
|
3
|
+
// Economics: Funding and commitment returns are principal. Distribution tax is
|
|
4
|
+
// pass-through; own-account fee and claim allocations are internal. Mixed
|
|
5
|
+
// principal/profit distributions and unbound source owners remain unclassified.
|
|
6
|
+
|
|
3
7
|
// Round target is plan.principal from runtime subject.price, not its credit limit.
|
|
4
8
|
// Expose round.create and close plus commitment.create and withdraw. A commitment
|
|
5
9
|
// debits the bound investor's original active wallet before closesAt. Investor cap
|
|
@@ -31,7 +35,7 @@ instrument round(borrower: party, plan: ref<financing.installments> = object(fin
|
|
|
31
35
|
from: open, to: funded, actor: { party: operator }
|
|
32
36
|
requires sum "amount" of { instrument: commitments, reference: "round", anchor: self.id, states: [committed], limit: 366 } == self.price
|
|
33
37
|
requires self.held.balance == self.price
|
|
34
|
-
moves self.price from self.held to self.plan.capital
|
|
38
|
+
moves self.price from self.held to self.plan.capital economics { purpose: principal, sourceParty: programOperator }
|
|
35
39
|
invoke: [{ selection: { instrument: commitments, reference: "round", anchor: self.id, states: [committed], limit: 366 }, action: fund, input: {} }]
|
|
36
40
|
}
|
|
37
41
|
action fail {
|
|
@@ -54,18 +58,18 @@ instrument commitment(round: ref<lending.round>, wallet: ref<wallet.balance>, in
|
|
|
54
58
|
requires self.wallet.holder == self.investor
|
|
55
59
|
requires self.amount >= self.round.minimumTicket
|
|
56
60
|
deadline: { at: self.round.closesAt }
|
|
57
|
-
moves self.amount from self.wallet.held to self.round.held
|
|
61
|
+
moves self.amount from self.wallet.held to self.round.held economics { purpose: principal, sourceParty: programOperator }
|
|
58
62
|
}
|
|
59
63
|
action fund { from: committed, to: funded, actor: { parent: round } }
|
|
60
64
|
action withdraw {
|
|
61
65
|
from: committed, to: withdrawn, actor: { party: investor }
|
|
62
66
|
requires self.round in [open]
|
|
63
67
|
deadline: { at: self.round.closesAt }
|
|
64
|
-
moves self.amount from self.round.held to self.wallet.held
|
|
68
|
+
moves self.amount from self.round.held to self.wallet.held economics { purpose: principal, sourceParty: programOperator }
|
|
65
69
|
}
|
|
66
70
|
action refund {
|
|
67
71
|
from: committed, to: refunded, actor: { parent: round }
|
|
68
|
-
moves self.amount from self.round.held to self.wallet.held
|
|
72
|
+
moves self.amount from self.round.held to self.wallet.held economics { purpose: principal, sourceParty: programOperator }
|
|
69
73
|
}
|
|
70
74
|
}
|
|
71
75
|
|
|
@@ -98,7 +102,7 @@ instrument distribution(round: ref<lending.round>, receipt: ref, commitments: re
|
|
|
98
102
|
action distribute_cash { allowZero: true,
|
|
99
103
|
from: cash_ready, to: distributed, actor: { party: operator }
|
|
100
104
|
requires sum "weight" of { instrument: share, reference: "distribution", anchor: self.id, states: [pending], limit: 366 } == self.round.price
|
|
101
|
-
moves self.principal from self.source.capital to self.held; moves self.profit from self.source.profitIncome to self.held; moves self.charge from self.held to programOperator; moves self.vat from self.held to programTax
|
|
105
|
+
moves self.principal from self.source.capital to self.held; moves self.profit from self.source.profitIncome to self.held; moves self.charge from self.held to programOperator economics { purpose: internal, sourceParty: programOperator }; moves self.vat from self.held to programTax economics { purpose: pass_through, sourceParty: programOperator }
|
|
102
106
|
invoke: [{ selection: { instrument: share, reference: "distribution", anchor: self.id, states: [pending], limit: 366 }, action: cash, input: {} }, { reference: self.id, action: residual_cash, input: {} }]
|
|
103
107
|
}
|
|
104
108
|
action residual_cash { allowZero: true,
|
|
@@ -113,7 +117,7 @@ instrument distribution(round: ref<lending.round>, receipt: ref, commitments: re
|
|
|
113
117
|
}
|
|
114
118
|
action residual_loss { allowZero: true,
|
|
115
119
|
from: distributed, to: distributed, actor: { parent: current() }
|
|
116
|
-
moves self.losses.balance from self.losses to self.residualLoss
|
|
120
|
+
moves self.losses.balance from self.losses to self.residualLoss economics { purpose: internal, sourceParty: programOperator }
|
|
117
121
|
}
|
|
118
122
|
records {
|
|
119
123
|
share: {
|
|
@@ -128,7 +132,7 @@ instrument distribution(round: ref<lending.round>, receipt: ref, commitments: re
|
|
|
128
132
|
from: pending, to: paid, actor: { parent: parent }
|
|
129
133
|
moves self.gross from self.distribution.held to self.commitment.wallet.held
|
|
130
134
|
}
|
|
131
|
-
action loss { allowZero: true, from: pending, to: paid, actor: { parent: parent }, moves self.gross from self.distribution.losses to self.commitment.loss }
|
|
135
|
+
action loss { allowZero: true, from: pending, to: paid, actor: { parent: parent }, moves self.gross from self.distribution.losses to self.commitment.loss economics { purpose: internal, sourceParty: programOperator } }
|
|
132
136
|
}
|
|
133
137
|
}
|
|
134
138
|
}
|
package/std/marketplace.hsx
CHANGED
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
header marketplace
|
|
2
2
|
|
|
3
|
+
// Economics: Deposit funding, escrow credit and returns are principal. Retention is
|
|
4
|
+
// earning for the company or a payout to a bound outside recipient.
|
|
5
|
+
|
|
3
6
|
// Listing, order and reservation are separate agreements. Expose their create
|
|
4
7
|
// and decision actions individually. Order fulfillment does not move escrow cash.
|
|
5
8
|
// Pair an order with escrow.hold and expose its fund, deliver, accept, dispute,
|
|
@@ -77,7 +80,7 @@ instrument reservation(listing: ref<marketplace.listing>, funds: ref<escrow.hold
|
|
|
77
80
|
calculate: [{ target: expiresAt, op: shift, date: { field: self.now }, milliseconds: { literal: expires_after }, direction: after }]
|
|
78
81
|
requires self.listing in [active]; requires self.price == self.listing.price
|
|
79
82
|
requires count of { instrument: all(marketplace.order), reference: "listing", anchor: self.listing, states: [placed, fulfilled], limit: 366 } == 0
|
|
80
|
-
moves self.deposit from self.buyer to self.held
|
|
83
|
+
moves self.deposit from self.buyer to self.held economics { purpose: principal, sourceParty: buyer }
|
|
81
84
|
}
|
|
82
85
|
action convert_financed {
|
|
83
86
|
from: active, to: active, actor: { party: buyer }, deadline: { at: self.expiresAt }
|
|
@@ -96,31 +99,31 @@ instrument reservation(listing: ref<marketplace.listing>, funds: ref<escrow.hold
|
|
|
96
99
|
requires input.contribution <= self.price
|
|
97
100
|
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 }] }]
|
|
98
101
|
set: { dispositionAt: { field: self.now } }
|
|
99
|
-
moves self.credit from self.held to input.funds.held
|
|
100
|
-
moves self.refund from self.held to self.buyer
|
|
102
|
+
moves self.credit from self.held to input.funds.held economics { purpose: principal, sourceParty: programOperator }
|
|
103
|
+
moves self.refund from self.held to self.buyer economics { purpose: principal, sourceParty: programOperator }
|
|
101
104
|
}
|
|
102
105
|
action cancel { allowZero: true,
|
|
103
106
|
from: active, to: cancelled, actor: { party: buyer }, input { reason: text }
|
|
104
107
|
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 }] }]
|
|
105
108
|
set: { reason: { field: input.reason }, dispositionAt: { field: self.now } }
|
|
106
|
-
moves self.refund from self.held to self.buyer; moves self.retained from self.held to retained_to
|
|
109
|
+
moves self.refund from self.held to self.buyer economics { purpose: principal, sourceParty: programOperator }; moves self.retained from self.held to retained_to economics { recipient: retained_to, company: { purpose: earning, sourceParty: buyer }, participant: { purpose: participant_payout, sourceParty: programOperator } }
|
|
107
110
|
}
|
|
108
111
|
action seller_cancel {
|
|
109
112
|
from: active, to: cancelled, actor: { party: seller }, input { reason: text }
|
|
110
113
|
set: { reason: { field: input.reason }, dispositionAt: { field: self.now } }
|
|
111
|
-
moves self.held.balance from self.held to self.buyer
|
|
114
|
+
moves self.held.balance from self.held to self.buyer economics { purpose: principal, sourceParty: programOperator }
|
|
112
115
|
}
|
|
113
116
|
action operator_cancel {
|
|
114
117
|
from: active, to: cancelled, actor: { party: operator }, input { reason: text }
|
|
115
118
|
set: { reason: { field: input.reason }, dispositionAt: { field: self.now } }
|
|
116
|
-
moves self.held.balance from self.held to self.buyer
|
|
119
|
+
moves self.held.balance from self.held to self.buyer economics { purpose: principal, sourceParty: programOperator }
|
|
117
120
|
}
|
|
118
121
|
action withdraw { from: proposed, to: cancelled, actor: { party: buyer } }
|
|
119
122
|
action expire { allowZero: true,
|
|
120
123
|
from: active, to: expired, actor: clock, due: { at: self.expiresAt }
|
|
121
124
|
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 }] }]
|
|
122
125
|
set: { dispositionAt: { field: self.now } }
|
|
123
|
-
moves self.refund from self.held to self.buyer; moves self.retained from self.held to retained_to
|
|
126
|
+
moves self.refund from self.held to self.buyer economics { purpose: principal, sourceParty: programOperator }; moves self.retained from self.held to retained_to economics { recipient: retained_to, company: { purpose: earning, sourceParty: buyer }, participant: { purpose: participant_payout, sourceParty: programOperator } }
|
|
124
127
|
}
|
|
125
128
|
action expire_proposal { from: proposed, to: expired, actor: clock, due: { at: self.proposalExpiresAt } }
|
|
126
129
|
}
|
package/std/money.hsx
CHANGED
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
header money
|
|
2
2
|
|
|
3
|
+
// Economics: Held funding and returns are principal. Release to the company realizes
|
|
4
|
+
// earnings; release to another participant is a payout. Generic transfers, splits,
|
|
5
|
+
// schedules, swaps, boundary payouts and metered fees retain no assumed purpose.
|
|
6
|
+
|
|
3
7
|
// Expose each attachment's create and caller actions explicitly. A transfer or
|
|
4
8
|
// split pays once; a hold exposes fund, release and refund separately. Release
|
|
5
9
|
// pays payee and refund returns payer. A hold has no dispute or damage decision.
|
|
@@ -36,7 +40,7 @@ instrument hold(payer: party, payee: party, amount: money = runtime) {
|
|
|
36
40
|
action create { }
|
|
37
41
|
action fund {
|
|
38
42
|
from: pending, to: funded, actor: { party: payer }
|
|
39
|
-
moves self.amount from payer to self.held
|
|
43
|
+
moves self.amount from payer to self.held economics { purpose: principal, sourceParty: payer }
|
|
40
44
|
}
|
|
41
45
|
action confirm {
|
|
42
46
|
from: pending, to: funded
|
|
@@ -44,11 +48,11 @@ instrument hold(payer: party, payee: party, amount: money = runtime) {
|
|
|
44
48
|
}
|
|
45
49
|
action release {
|
|
46
50
|
from: funded, to: released, actor: { party: payer }
|
|
47
|
-
moves self.amount from self.held to payee
|
|
51
|
+
moves self.amount from self.held to payee economics { recipient: payee, company: { purpose: earning, sourceParty: payer }, participant: { purpose: participant_payout, sourceParty: programOperator } }
|
|
48
52
|
}
|
|
49
53
|
action refund {
|
|
50
54
|
from: funded, to: refunded, actor: { party: payee }
|
|
51
|
-
moves self.amount from self.held to payer
|
|
55
|
+
moves self.amount from self.held to payer economics { purpose: principal, sourceParty: programOperator }
|
|
52
56
|
}
|
|
53
57
|
action cancel { from: pending, to: cancelled }
|
|
54
58
|
}
|
|
@@ -103,7 +107,7 @@ instrument pool(payer: party, payee: party, target: money, closes: date) {
|
|
|
103
107
|
action pay {
|
|
104
108
|
from: open, to: paid, actor: { party: payee }
|
|
105
109
|
requires self.held.balance == self.target
|
|
106
|
-
moves self.target from self.held to payee
|
|
110
|
+
moves self.target from self.held to payee economics { recipient: payee, company: { purpose: earning, sourceParty: payer }, participant: { purpose: participant_payout, sourceParty: programOperator } }
|
|
107
111
|
}
|
|
108
112
|
action fail {
|
|
109
113
|
from: open, to: failed, actor: clock, due: { at: self.closesAt }
|
|
@@ -116,8 +120,8 @@ instrument pool(payer: party, payee: party, target: money, closes: date) {
|
|
|
116
120
|
lifecycle { states: [pending, paid, refunded], initial: pending }
|
|
117
121
|
invariants count of { instrument: current(), reference: "pool", anchor: self.pool, states: [paid], limit: 366 } <= 366
|
|
118
122
|
action create { requires self.pool in [open] }
|
|
119
|
-
action pay { from: pending, to: paid, actor: { party: payer }, deadline: { at: self.pool.closesAt }, requires self.pool in [open], calculate: [{ target: remaining, op: subtract, base: { field: self.pool.target }, subtract: [{ field: self.pool.held.balance }] }], requires self.amount <= self.remaining, moves self.amount from self.payer to self.pool.held }
|
|
120
|
-
action refund { from: paid, to: refunded, actor: { parent: parent }, moves self.amount from self.pool.held to self.payer }
|
|
123
|
+
action pay { from: pending, to: paid, actor: { party: payer }, deadline: { at: self.pool.closesAt }, requires self.pool in [open], calculate: [{ target: remaining, op: subtract, base: { field: self.pool.target }, subtract: [{ field: self.pool.held.balance }] }], requires self.amount <= self.remaining, moves self.amount from self.payer to self.pool.held economics { purpose: principal, sourceParty: payer } }
|
|
124
|
+
action refund { from: paid, to: refunded, actor: { parent: parent }, moves self.amount from self.pool.held to self.payer economics { purpose: principal, sourceParty: programOperator } }
|
|
121
125
|
}
|
|
122
126
|
}
|
|
123
127
|
}
|
package/std/savings.hsx
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
header savings
|
|
2
2
|
|
|
3
|
+
// Economics: Contributions and returned pots are principal, not company earnings.
|
|
4
|
+
|
|
3
5
|
// Expose circle.create and membership.create; create one pending contribution
|
|
4
6
|
// record per member per circle date before membership.activate. Circle activation
|
|
5
7
|
// is clock-owned and needs exactly members joined memberships at or after startsAt.
|
|
@@ -52,7 +54,7 @@ instrument membership(circle: ref<savings.circle>, member: party) {
|
|
|
52
54
|
from: active, to: received, actor: clock, due: { at: self.receivesAt }
|
|
53
55
|
requires self.circle in [active]
|
|
54
56
|
requires count of { instrument: all(savings.membership), reference: "circle", anchor: self.circle, states: [received], limit: 60 } == self.preceding
|
|
55
|
-
moves self.total from self.circle.held to self.member
|
|
57
|
+
moves self.total from self.circle.held to self.member economics { purpose: principal, sourceParty: programOperator }
|
|
56
58
|
}
|
|
57
59
|
action withdraw { from: joined, to: withdrawn, requires self.circle in [disbanded] }
|
|
58
60
|
records {
|
|
@@ -60,7 +62,7 @@ instrument membership(circle: ref<savings.circle>, member: party) {
|
|
|
60
62
|
fields { membership: ref<parent>, period: integer(1, 60), dueAt: date = at(self.membership.circle.circleDates, self.period), amount: money = self.membership.contribution }
|
|
61
63
|
lifecycle { states: [pending, paid], initial: pending }
|
|
62
64
|
action create { requires self.period <= self.membership.circle.members; requires self.membership in [joined]; requires unique "seat_period" on [self.membership, self.period] }
|
|
63
|
-
action pay { from: pending, to: paid, actor: clock, due: { at: self.dueAt }, requires self.membership in [active, received]; requires self.membership.circle in [active], moves self.amount from self.membership.member to self.membership.circle.held }
|
|
65
|
+
action pay { from: pending, to: paid, actor: clock, due: { at: self.dueAt }, requires self.membership in [active, received]; requires self.membership.circle in [active], moves self.amount from self.membership.member to self.membership.circle.held economics { purpose: principal, sourceParty: member } }
|
|
64
66
|
}
|
|
65
67
|
}
|
|
66
68
|
}
|