@hyperscale0/hsx 4.0.1 → 4.1.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 +4 -0
- package/dist/src/compile.d.ts.map +1 -1
- package/dist/src/compile.js +31 -142
- package/dist/src/compile.js.map +1 -1
- package/dist/src/headers.d.ts +2 -2
- package/dist/src/headers.d.ts.map +1 -1
- package/dist/src/headers.js +1 -2
- package/dist/src/headers.js.map +1 -1
- package/dist/src/lex.d.ts +1 -1
- package/dist/src/lex.d.ts.map +1 -1
- package/dist/src/lex.js +0 -1
- package/dist/src/lex.js.map +1 -1
- package/dist/src/parse.js +0 -17
- package/dist/src/parse.js.map +1 -1
- package/dist/src/std-bundle.d.ts.map +1 -1
- package/dist/src/std-bundle.js +10 -11
- package/dist/src/std-bundle.js.map +1 -1
- package/docs/README.md +0 -10
- package/docs/headers.md +15 -16
- package/examples/cost-table.json +8 -144
- package/examples/library.hsx +4 -4
- package/package.json +3 -3
- package/src/compile.ts +32 -208
- package/src/headers.ts +1 -2
- package/src/lex.ts +0 -1
- package/src/parse.ts +0 -14
- package/src/std-bundle.ts +10 -11
- package/std/cards.hsx +10 -11
- package/std/collections.hsx +3 -3
- package/std/escrow.hsx +2 -2
- package/std/financing.hsx +56 -53
- package/std/insurance.hsx +17 -16
- package/std/lending.hsx +8 -7
- package/std/money.hsx +8 -18
- package/std/reporting.hsx +0 -4
- package/std/travel.hsx +5 -6
- package/std/wallet.hsx +3 -3
- package/std/approvals.hsx +0 -17
package/std/cards.hsx
CHANGED
|
@@ -20,7 +20,7 @@ instrument card(holder: ref<cards.cardholder>, spend_limit: money) {
|
|
|
20
20
|
action cancel { from: [issued, active, frozen], to: cancelled }
|
|
21
21
|
}
|
|
22
22
|
|
|
23
|
-
instrument authorization(card: ref<cards.card>, merchant: party,
|
|
23
|
+
instrument authorization(card: ref<cards.card>, merchant: party, issuer: party = programOperator) {
|
|
24
24
|
fields { card: ref<card>, merchant: account of merchant, amount: money, expiresAt: date, reservation: text? }
|
|
25
25
|
lifecycle { states: [pending, approved, captured, declined, reversed, expired], initial: pending }
|
|
26
26
|
action create {
|
|
@@ -28,13 +28,13 @@ instrument authorization(card: ref<cards.card>, merchant: party, approval: appro
|
|
|
28
28
|
requires self.amount <= self.card.spendLimit
|
|
29
29
|
}
|
|
30
30
|
action approve {
|
|
31
|
-
from: pending, to: approved, deadline: { at: self.expiresAt }
|
|
32
|
-
requires
|
|
31
|
+
from: pending, to: approved, actor: { party: issuer }, deadline: { at: self.expiresAt }
|
|
32
|
+
requires self.card in [active]
|
|
33
33
|
moves reserve self.amount from self.card.holder.holder to merchant capture "reservation"
|
|
34
34
|
}
|
|
35
|
-
action capture { from: approved, to: captured, deadline: { at: self.expiresAt }, moves post self.reservation }
|
|
36
|
-
action reverse { from: approved, to: reversed, moves void self.reservation }
|
|
37
|
-
action decline { from: pending, to: declined,
|
|
35
|
+
action capture { from: approved, to: captured, actor: { party: merchant }, deadline: { at: self.expiresAt }, moves post self.reservation }
|
|
36
|
+
action reverse { from: approved, to: reversed, actor: { party: merchant }, moves void self.reservation }
|
|
37
|
+
action decline { from: pending, to: declined, actor: { party: issuer } }
|
|
38
38
|
action expire { from: approved, to: expired, actor: clock, due: { at: self.expiresAt }, moves void self.reservation }
|
|
39
39
|
action abandon { from: pending, to: expired, actor: clock, due: { at: self.expiresAt } }
|
|
40
40
|
}
|
|
@@ -44,19 +44,18 @@ instrument transaction(authorization: ref<cards.authorization>) {
|
|
|
44
44
|
lifecycle { states: [posted, refunded], initial: posted }
|
|
45
45
|
action create { requires self.authorization in [captured]; requires unique "captured_authorization" on [self.authorization] }
|
|
46
46
|
action refund {
|
|
47
|
-
from: posted, to: refunded, input { reason: text }
|
|
47
|
+
from: posted, to: refunded, actor: { party: programOperator }, input { reason: text }
|
|
48
48
|
moves self.amount from self.authorization.merchant to self.authorization.card.holder.holder
|
|
49
49
|
}
|
|
50
50
|
}
|
|
51
51
|
|
|
52
|
-
instrument dispute(transaction: ref<cards.transaction>,
|
|
52
|
+
instrument dispute(transaction: ref<cards.transaction>, issuer: party = programOperator, within: duration = 90d) {
|
|
53
53
|
fields { transaction: ref<transaction>, evidence: text, expiresAt: date = after(self.createdAt, within) }
|
|
54
54
|
lifecycle { states: [filed, reviewing, won, lost], initial: filed }
|
|
55
55
|
action create { requires self.transaction in [posted]; requires unique "disputed_transaction" on [self.transaction] }
|
|
56
|
-
action review { from: filed, to: reviewing }
|
|
56
|
+
action review { from: filed, to: reviewing, actor: { party: issuer } }
|
|
57
57
|
action win {
|
|
58
|
-
from: reviewing, to: won, deadline: { at: self.expiresAt }
|
|
59
|
-
requires approval by approved_by
|
|
58
|
+
from: reviewing, to: won, actor: { party: issuer }, deadline: { at: self.expiresAt }
|
|
60
59
|
invoke: [{ reference: self.transaction, action: refund, input: { reason: { field: self.evidence } } }]
|
|
61
60
|
}
|
|
62
61
|
action lose { from: [filed, reviewing], to: lost, actor: clock, due: { at: self.expiresAt } }
|
package/std/collections.hsx
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
header collections
|
|
2
2
|
|
|
3
|
-
instrument case(on: ref<financing.installments>[], agency:
|
|
3
|
+
instrument case(on: ref<financing.installments>[], agency: party, capital: party = programOperator, overdue: duration = 3d, fee: percent = 20%) {
|
|
4
4
|
revisioned: true
|
|
5
5
|
summary: "Refer an overdue installment without creating another debt."
|
|
6
6
|
fields { assignedAgency: account of agency, plan: ref<on>, slice: ref<on.slice>, payment: ref<on.payment>, eligibleAt: date = after(self.slice.dueAt, overdue), agencyFee: money = rate(self.payment.amount, fee) }
|
|
@@ -11,10 +11,10 @@ instrument case(on: ref<financing.installments>[], agency: approval, overdue: du
|
|
|
11
11
|
requires self.slice.principalReceivable.balance > "0"
|
|
12
12
|
requires unique "overdue_referral" on [self.slice]
|
|
13
13
|
}
|
|
14
|
-
action assign { from: opened, to: assigned,
|
|
14
|
+
action assign { from: opened, to: assigned, actor: { party: capital } }
|
|
15
15
|
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: {} }] }
|
|
16
16
|
action pay_fee { from: recovered, to: recovered, actor: { parent: current() }, moves self.agencyFee from self.plan.capital to agency }
|
|
17
|
-
action recall { from: [opened, assigned], to: recalled }
|
|
17
|
+
action recall { from: [opened, assigned], to: recalled, actor: { party: capital } }
|
|
18
18
|
action return_uncollected { from: assigned, to: returned_uncollected, actor: { party: agency } }
|
|
19
19
|
}
|
|
20
20
|
|
package/std/escrow.hsx
CHANGED
|
@@ -41,11 +41,11 @@ instrument hold(payer: party = party(person), payee: party = programOperator, ac
|
|
|
41
41
|
deadline: { at: self.deliveredAt, offset: accept_within }
|
|
42
42
|
}
|
|
43
43
|
action verify_return {
|
|
44
|
-
from: disputed, to: return_verified
|
|
44
|
+
from: disputed, to: return_verified, actor: { party: payee }
|
|
45
45
|
input { returnEvidence: text }
|
|
46
46
|
}
|
|
47
47
|
action refund {
|
|
48
|
-
from: dispute.refund_after, to: refunded
|
|
48
|
+
from: dispute.refund_after, to: refunded, actor: { party: payee }
|
|
49
49
|
moves self.price from self.held to payer
|
|
50
50
|
}
|
|
51
51
|
action cancel { from: pending, to: cancelled }
|
package/std/financing.hsx
CHANGED
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
header financing
|
|
2
2
|
|
|
3
|
-
instrument installments(months: integer(1, 366), charge_limit: integer(1, 3) = 3, profit: percent, disburse_to: enum(funds, borrower) = funds, profit_earned: enum(on_payment, by_schedule, at_disbursement) = on_payment, apply: enum(fines_profit_principal, principal_profit, pro_rata) = fines_profit_principal, payoff_rebate: percent = 100%, write_off_after: duration = 90d, max_extension: duration = 90d, max_amendments: integer(0, 366) = 2, waiver_limit: percent = 100%, amendment_expiry: duration = 7d, payoff_quote_expiry: duration = 1h, allow_overdue: enum(allowed, blocked) = allowed, assessed_fines: enum(carry, require_waiver) = carry, down_payment: percent = 0%, funds: ref
|
|
3
|
+
instrument installments(months: integer(1, 366), charge_limit: integer(1, 3) = 3, profit: percent, disburse_to: enum(funds, borrower) = funds, profit_earned: enum(on_payment, by_schedule, at_disbursement) = on_payment, apply: enum(fines_profit_principal, principal_profit, pro_rata) = fines_profit_principal, payoff_rebate: percent = 100%, write_off_after: duration = 90d, max_extension: duration = 90d, max_amendments: integer(0, 366) = 2, waiver_limit: percent = 100%, amendment_expiry: duration = 7d, payoff_quote_expiry: duration = 1h, allow_overdue: enum(allowed, blocked) = allowed, assessed_fines: enum(carry, require_waiver) = carry, down_payment: percent = 0%, funds: ref<escrow.hold>?, borrower: party = party(person), capital: party = programOperator, share: percent = 0%, limits: ref<financing.limits> = object(financing.limits), portfolio: ref<financing.portfolio_limit> = object(financing.portfolio_limit)) {
|
|
4
4
|
revisioned: true
|
|
5
5
|
familyRevision: 1
|
|
6
6
|
summary: "Funding, profit recognition and payment order chosen by the program."
|
|
7
7
|
fields {
|
|
8
|
-
funds: ref<funds
|
|
8
|
+
funds: ref<funds>?, borrower: account of borrower, settlementIdentity: text, borrowerLimit: ref<limits>, portfolioLimit: ref<portfolio>
|
|
9
9
|
months: integer = months, dates: list(date, months)
|
|
10
10
|
allocatedPayable: account(capital, cash, "allocatedProfitPayable"), capital: account(capital, cash, "capital"), profitIncome: account(capital, cash, "profitIncome"), loss: account(capital, claim, "loss")
|
|
11
11
|
downPaymentRemaining: money?, downPaymentCredit: money?, principalReturned: money?, profitReturned: money?, lossRecorded: money?
|
|
12
|
-
price: money =
|
|
12
|
+
price: money = subject.price
|
|
13
13
|
downPayment: money = rate(self.price, down_payment)
|
|
14
14
|
principal: money = subtract(self.price, self.downPayment)
|
|
15
15
|
profit: money = rate(self.principal, profit)
|
|
@@ -20,7 +20,9 @@ instrument installments(months: integer(1, 366), charge_limit: integer(1, 3) = 3
|
|
|
20
20
|
invariants sum "principalReceivable.balance" of { instrument: all(financing.installments.slice), reference: "borrowerLimit", anchor: self.borrowerLimit, states: [pending, due, paid], limit: 366 } <= self.borrowerLimit.limit
|
|
21
21
|
invariants sum "principalReceivable.balance" of { instrument: all(financing.installments.slice), reference: "portfolioLimit", anchor: self.portfolioLimit, states: [pending, due, paid], limit: 366 } <= self.portfolioLimit.limit
|
|
22
22
|
action create {
|
|
23
|
-
|
|
23
|
+
subject { price: money }
|
|
24
|
+
requires self.borrowerLimit.borrower == self.borrower
|
|
25
|
+
when disburse_to is funds { requires self.borrower == self.funds.payer }
|
|
24
26
|
invoke: [{ range: { count: { literal: months }, maximum: months, bind: position }, instrument: slice, action: create, input: { plan: { field: self.id }, borrowerLimit: { field: self.borrowerLimit }, portfolioLimit: { field: self.portfolioLimit }, position: { field: position } } }]
|
|
25
27
|
}
|
|
26
28
|
action sign {
|
|
@@ -28,8 +30,7 @@ instrument installments(months: integer(1, 366), charge_limit: integer(1, 3) = 3
|
|
|
28
30
|
requires count of { instrument: slice, reference: "plan", anchor: self.id, states: [draft], limit: 366 } == self.months
|
|
29
31
|
}
|
|
30
32
|
action disburse {
|
|
31
|
-
from: signed, to: active
|
|
32
|
-
requires approval by approval protectedRequest self differentFromInitiator true
|
|
33
|
+
from: signed, to: active, actor: { party: capital }
|
|
33
34
|
requires self.borrowerLimit in [approved]
|
|
34
35
|
requires self.portfolioLimit in [approved]
|
|
35
36
|
when disburse_to is funds {
|
|
@@ -42,9 +43,11 @@ instrument installments(months: integer(1, 366), charge_limit: integer(1, 3) = 3
|
|
|
42
43
|
}
|
|
43
44
|
action fund_down_payment {
|
|
44
45
|
from: active, to: active, actor: { parent: current() }
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
46
|
+
when disburse_to is funds {
|
|
47
|
+
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 }] }]
|
|
48
|
+
moves self.downPaymentRemaining from self.funds.payer to self.funds.held
|
|
49
|
+
moves self.principal from self.capital to self.funds.held
|
|
50
|
+
}
|
|
48
51
|
}
|
|
49
52
|
action complete {
|
|
50
53
|
from: active, to: paid
|
|
@@ -90,8 +93,7 @@ instrument installments(months: integer(1, 366), charge_limit: integer(1, 3) = 3
|
|
|
90
93
|
lifecycle { states: [requested, applied, cancelled], initial: requested }
|
|
91
94
|
action create { requires self.overdueSlice.plan == self.plan; requires self.plan in [active] }
|
|
92
95
|
action apply {
|
|
93
|
-
from: requested, to: applied
|
|
94
|
-
requires approval by approval protectedRequest self differentFromInitiator true
|
|
96
|
+
from: requested, to: applied, actor: { party: capital }
|
|
95
97
|
invoke: [{ reference: self.plan, action: write_off, input: { overdueSlice: { field: self.overdueSlice } } }]
|
|
96
98
|
}
|
|
97
99
|
action cancel { from: requested, to: cancelled }
|
|
@@ -140,7 +142,7 @@ instrument installments(months: integer(1, 366), charge_limit: integer(1, 3) = 3
|
|
|
140
142
|
}
|
|
141
143
|
lifecycle { states: [proposed, applied, declined, withdrawn, expired, superseded], initial: proposed }
|
|
142
144
|
action create {
|
|
143
|
-
actor: { party:
|
|
145
|
+
actor: { party: capital }
|
|
144
146
|
requires self.plan in [active]; requires self.waiverPercent <= self.maximumWaiver
|
|
145
147
|
set: { revision: { field: self.productRevision } }
|
|
146
148
|
calculate: [
|
|
@@ -156,7 +158,6 @@ instrument installments(months: integer(1, 366), charge_limit: integer(1, 3) = 3
|
|
|
156
158
|
action accept {
|
|
157
159
|
from: proposed, to: applied, actor: { party: borrower }, deadline: { at: self.expiresAt }
|
|
158
160
|
requires self.plan in [active]; requires self.revision == self.productRevision
|
|
159
|
-
requires approval by approval protectedRequest self differentFromInitiator true
|
|
160
161
|
requires count of { instrument: current(), reference: "plan", anchor: self.plan, states: [applied], limit: 366 } < self.maximum
|
|
161
162
|
set: { acceptedAt: { field: self.now } }
|
|
162
163
|
when assessed_fines is require_waiver { requires self.waiverPercent == 10000 }
|
|
@@ -165,8 +166,8 @@ instrument installments(months: integer(1, 366), charge_limit: integer(1, 3) = 3
|
|
|
165
166
|
invoke: [{ selection: { instrument: slice, reference: "plan", anchor: self.plan, states: [pending, due], limit: 366, order: [position] }, action: amend, input: { amendment: { field: self.id } } }]
|
|
166
167
|
invoke: [{ selection: { instrument: slice, reference: "plan", anchor: self.plan, states: [paid], limit: 366 }, action: verify_fixed_date, input: { amendment: { field: self.id } } }]
|
|
167
168
|
}
|
|
168
|
-
action withdraw { from: proposed, to: withdrawn, actor: { party:
|
|
169
|
-
action decline { from: proposed, to: declined, actor: { party:
|
|
169
|
+
action withdraw { from: proposed, to: withdrawn, actor: { party: capital } }
|
|
170
|
+
action decline { from: proposed, to: declined, actor: { party: borrower } }
|
|
170
171
|
action expire { from: proposed, to: expired, actor: clock, due: { at: self.expiresAt } }
|
|
171
172
|
action supersede { from: proposed, to: superseded, requires self.revision != self.productRevision, set: { staleReason: { literal: "economic_revision_changed" } } }
|
|
172
173
|
}
|
|
@@ -200,7 +201,7 @@ instrument installments(months: integer(1, 366), charge_limit: integer(1, 3) = 3
|
|
|
200
201
|
slice: {
|
|
201
202
|
revisioned: true
|
|
202
203
|
fields {
|
|
203
|
-
plan: ref<parent>, borrowerLimit: ref<limits>, portfolioLimit: ref<
|
|
204
|
+
plan: ref<parent>, borrowerLimit: ref<limits>, portfolioLimit: ref<portfolio>, position: integer(1, months)
|
|
204
205
|
originalDueAt: date = at(self.plan.dates, self.position), dueAt: date?, nextDueAt: date?, previousDueAt: date?, previousPosition: integer?, previousDate: date?, extensionLimit: date = after(self.originalDueAt, max_extension), lossEligibleAt: date?
|
|
205
206
|
principalBase: money = divide(self.plan.principal, months)
|
|
206
207
|
principalAllocated: money = multiply(self.principalBase, months)
|
|
@@ -221,7 +222,7 @@ instrument installments(months: integer(1, 366), charge_limit: integer(1, 3) = 3
|
|
|
221
222
|
lifecycle { states: [draft, pending, due, paid, written_off], initial: draft }
|
|
222
223
|
action create {
|
|
223
224
|
actor: { parent: parent }
|
|
224
|
-
input { plan: ref<parent>, borrowerLimit: ref<limits>, portfolioLimit: ref<
|
|
225
|
+
input { plan: ref<parent>, borrowerLimit: ref<limits>, portfolioLimit: ref<portfolio>, position: integer(1, months) }
|
|
225
226
|
set: { dueAt: { field: self.originalDueAt } }
|
|
226
227
|
invoke: [{ reference: self.id, action: refresh_loss_date, input: {} }]
|
|
227
228
|
requires self.plan in [quoted]; requires unique "signed_position" on [self.plan, self.position]; requires self.borrowerLimit == self.plan.borrowerLimit; requires self.portfolioLimit == self.plan.portfolioLimit
|
|
@@ -354,7 +355,7 @@ instrument installments(months: integer(1, 366), charge_limit: integer(1, 3) = 3
|
|
|
354
355
|
action create { input { plan: ref<parent>, amount: money, paymentIdentity: text } requires self.plan in [active]; requires unique "payment_identity" on [self.plan, self.paymentIdentity] }
|
|
355
356
|
action pay {
|
|
356
357
|
expansionLimit: 8192
|
|
357
|
-
from: pending, to: paid
|
|
358
|
+
from: pending, to: paid, actor: { party: borrower }
|
|
358
359
|
calculate: [{ target: outstandingPrincipal, op: aggregate, selection: { instrument: slice, reference: "plan", anchor: self.plan, states: [pending, due, paid], limit: 366, order: [position] }, measure: { sum: "principalReceivable.balance" } }]
|
|
359
360
|
when profit_earned is on_payment { calculate: [{ target: outstandingProfit, op: aggregate, selection: { instrument: slice, reference: "plan", anchor: self.plan, states: [pending, due, paid], limit: 366, order: [position] }, measure: { sum: "profitReceivable.balance" } }] }
|
|
360
361
|
when profit_earned is by_schedule { calculate: [{ target: outstandingProfit, op: aggregate, selection: { instrument: slice, reference: "plan", anchor: self.plan, states: [pending, due, paid], limit: 366, order: [position] }, measure: { sum: "profitEarned.balance" } }] }
|
|
@@ -384,7 +385,7 @@ instrument installments(months: integer(1, 366), charge_limit: integer(1, 3) = 3
|
|
|
384
385
|
invoke: [{ reference: self.plan, action: record_payment, input: { identity: { field: self.paymentIdentity }, principal: { field: self.principalReturned }, profit: { field: self.profitReturned } } }]
|
|
385
386
|
}
|
|
386
387
|
action refund {
|
|
387
|
-
from: paid, to: refunded
|
|
388
|
+
from: paid, to: refunded, actor: { party: capital }
|
|
388
389
|
requires unique "settlement_consumption" on [self.plan, self.paymentIdentity]; requires self.plan in [active, paid]
|
|
389
390
|
requires count of { instrument: settlement, reference: "plan", anchor: self.plan, states: [recorded], limit: 366, where: { identity: { field: self.paymentIdentity } } } == 1
|
|
390
391
|
invoke: [{ selection: { instrument: settlement, reference: "plan", anchor: self.plan, states: [recorded], limit: 366, where: { identity: { field: self.paymentIdentity } } }, action: refund, input: {} }]
|
|
@@ -406,7 +407,7 @@ instrument installments(months: integer(1, 366), charge_limit: integer(1, 3) = 3
|
|
|
406
407
|
}
|
|
407
408
|
action refund {
|
|
408
409
|
from: paid, to: refunded, actor: { parent: payment }
|
|
409
|
-
moves self.amount from self.slice.plan.capital to self.slice.plan.
|
|
410
|
+
moves self.amount from self.slice.plan.capital to self.slice.plan.borrower; moves self.amount from self.slice.debt to self.slice.principalReceivable
|
|
410
411
|
}
|
|
411
412
|
}
|
|
412
413
|
profit_piece: {
|
|
@@ -433,7 +434,7 @@ instrument installments(months: integer(1, 366), charge_limit: integer(1, 3) = 3
|
|
|
433
434
|
}
|
|
434
435
|
}
|
|
435
436
|
|
|
436
|
-
instrument late_charge(on: ref<financing.installments>[], grace: duration = 3d, fine: money = 50 SAR, cap: money = 25 SAR, fines_to: party = programOperator, costs_to: party = programOperator,
|
|
437
|
+
instrument late_charge(on: ref<financing.installments>[], grace: duration = 3d, fine: money = 50 SAR, cap: money = 25 SAR, fines_to: party = programOperator, costs_to: party = programOperator, borrower: party = party(person)) {
|
|
437
438
|
revisioned: true
|
|
438
439
|
familyRevision: 1
|
|
439
440
|
summary: "Separate approved fine and evidenced recovery claims on an overdue installment."
|
|
@@ -444,18 +445,18 @@ instrument late_charge(on: ref<financing.installments>[], grace: duration = 3d,
|
|
|
444
445
|
lifecycle { states: [proposed, assessed, collected, waived, refunded], initial: proposed }
|
|
445
446
|
action create { calculate: [{ target: overdueAt, op: shift, date: { field: self.slice.dueAt }, milliseconds: { literal: grace }, direction: after }], requires unique "late_assessment" on [self.slice, self.overdueAt]; requires self.borrower == self.slice.plan.borrower; requires self.plan == self.slice.plan }
|
|
446
447
|
action assess {
|
|
447
|
-
from: proposed, to: assessed, due: { at: self.overdueAt }
|
|
448
|
-
requires self.slice.principalReceivable.balance > "0"
|
|
448
|
+
from: proposed, to: assessed, actor: clock, due: { at: self.overdueAt }
|
|
449
|
+
requires self.slice.principalReceivable.balance > "0"
|
|
449
450
|
moves self.fine from self.debt to self.receivable
|
|
450
451
|
}
|
|
451
452
|
action collect {
|
|
452
|
-
from: [assessed, collected], to: assessed, input { payment: ref<on.payment> }
|
|
453
|
+
from: [assessed, collected], to: assessed, actor: { parent: child(on, slice) }, input { payment: ref<on.payment> }
|
|
453
454
|
requires input.payment in [paid]
|
|
454
455
|
requires input.payment.plan == self.plan
|
|
455
456
|
invoke: [{ instrument: receipt, action: create, input: { assessment: { field: self.id }, payment: { field: input.payment } } }, { selection: { instrument: current(), reference: "plan", anchor: self.plan, states: [assessed], limit: 1, where: { id: { field: self.id }, receivable.balance: { literal: "0" } } }, action: finish, input: {} }]
|
|
456
457
|
}
|
|
457
458
|
action payoff {
|
|
458
|
-
from: [assessed, collected], to: collected
|
|
459
|
+
from: [assessed, collected], to: collected, actor: { parent: on }
|
|
459
460
|
requires self.plan in [paid]
|
|
460
461
|
moves self.receivable.balance from self.plan.borrower to fines_to
|
|
461
462
|
moves self.receivable.balance from self.receivable to self.debt
|
|
@@ -469,7 +470,7 @@ instrument late_charge(on: ref<financing.installments>[], grace: duration = 3d,
|
|
|
469
470
|
}
|
|
470
471
|
action waive { from: [assessed, collected], to: waived, actor: { parent: waiver_request }, input { reason: text, evidence: text }, moves self.receivable.balance from self.receivable to self.debt }
|
|
471
472
|
action refund {
|
|
472
|
-
from: [assessed, collected], to: assessed, input { payment: ref<on.payment> }
|
|
473
|
+
from: [assessed, collected], to: assessed, actor: { party: fines_to }, input { payment: ref<on.payment> }
|
|
473
474
|
requires input.payment in [paid, refunded]
|
|
474
475
|
requires input.payment.plan == self.plan
|
|
475
476
|
invoke: [{ selection: { instrument: receipt, reference: "payment", anchor: input.payment, states: [paid], limit: 1, where: { assessment: { field: self.id } } }, action: refund, input: {} }, { selection: { instrument: current(), reference: "plan", anchor: self.plan, states: [assessed], limit: 1, where: { id: { field: self.id }, receivable.balance: { literal: "0" } } }, action: finish, input: {} }]
|
|
@@ -480,8 +481,7 @@ instrument late_charge(on: ref<financing.installments>[], grace: duration = 3d,
|
|
|
480
481
|
lifecycle { states: [requested, applied, cancelled], initial: requested }
|
|
481
482
|
action create { requires self.assessment in [assessed, collected] }
|
|
482
483
|
action apply {
|
|
483
|
-
from: requested, to: applied, input { reason: text, evidence: text }
|
|
484
|
-
requires approval by approval protectedRequest self differentFromInitiator true
|
|
484
|
+
from: requested, to: applied, actor: { party: fines_to }, input { reason: text, evidence: text }
|
|
485
485
|
invoke: [{ reference: self.assessment, action: waive, input: { reason: { field: input.reason }, evidence: { field: input.evidence } } }]
|
|
486
486
|
}
|
|
487
487
|
action cancel { from: requested, to: cancelled }
|
|
@@ -512,18 +512,18 @@ instrument late_charge(on: ref<financing.installments>[], grace: duration = 3d,
|
|
|
512
512
|
lifecycle { states: [proposed, assessed, collected, waived, refunded], initial: proposed }
|
|
513
513
|
action create { calculate: [{ target: overdueAt, op: shift, date: { field: self.assessment.overdueAt }, milliseconds: { literal: 0 }, direction: after }], requires unique "recovery_assessment" on [self.assessment]; requires self.plan == self.assessment.plan }
|
|
514
514
|
action assess {
|
|
515
|
-
from: proposed, to: assessed, due: { at: self.assessment.overdueAt }
|
|
516
|
-
requires self.assessment.slice.principalReceivable.balance > "0"
|
|
515
|
+
from: proposed, to: assessed, actor: clock, due: { at: self.assessment.overdueAt }
|
|
516
|
+
requires self.assessment.slice.principalReceivable.balance > "0"
|
|
517
517
|
moves self.amount from self.debt to self.receivable
|
|
518
518
|
}
|
|
519
519
|
action collect {
|
|
520
|
-
from: [assessed, collected], to: assessed, input { payment: ref<on.payment> }
|
|
520
|
+
from: [assessed, collected], to: assessed, actor: { parent: child(on, slice) }, input { payment: ref<on.payment> }
|
|
521
521
|
requires input.payment in [paid]
|
|
522
522
|
requires input.payment.plan == self.plan
|
|
523
523
|
invoke: [{ instrument: receipt, action: create, input: { assessment: { field: self.id }, payment: { field: input.payment } } }, { selection: { instrument: current(), reference: "plan", anchor: self.plan, states: [assessed], limit: 1, where: { id: { field: self.id }, receivable.balance: { literal: "0" } } }, action: finish, input: {} }]
|
|
524
524
|
}
|
|
525
525
|
action payoff {
|
|
526
|
-
from: [assessed, collected], to: collected
|
|
526
|
+
from: [assessed, collected], to: collected, actor: { parent: on }
|
|
527
527
|
requires self.plan in [paid]
|
|
528
528
|
moves self.receivable.balance from self.plan.borrower to costs_to
|
|
529
529
|
moves self.receivable.balance from self.receivable to self.debt
|
|
@@ -537,7 +537,7 @@ instrument late_charge(on: ref<financing.installments>[], grace: duration = 3d,
|
|
|
537
537
|
}
|
|
538
538
|
action waive { from: [assessed, collected], to: waived, actor: { parent: waiver_request }, input { reason: text, evidence: text }, moves self.receivable.balance from self.receivable to self.debt }
|
|
539
539
|
action refund {
|
|
540
|
-
from: [assessed, collected], to: assessed, input { payment: ref<on.payment> }
|
|
540
|
+
from: [assessed, collected], to: assessed, actor: { party: costs_to }, input { payment: ref<on.payment> }
|
|
541
541
|
requires input.payment in [paid, refunded]
|
|
542
542
|
requires input.payment.plan == self.plan
|
|
543
543
|
invoke: [{ selection: { instrument: receipt, reference: "payment", anchor: input.payment, states: [paid], limit: 1, where: { assessment: { field: self.id } } }, action: refund, input: {} }, { selection: { instrument: current(), reference: "plan", anchor: self.plan, states: [assessed], limit: 1, where: { id: { field: self.id }, receivable.balance: { literal: "0" } } }, action: finish, input: {} }]
|
|
@@ -548,8 +548,7 @@ instrument late_charge(on: ref<financing.installments>[], grace: duration = 3d,
|
|
|
548
548
|
lifecycle { states: [requested, applied, cancelled], initial: requested }
|
|
549
549
|
action create { requires self.assessment in [assessed, collected] }
|
|
550
550
|
action apply {
|
|
551
|
-
from: requested, to: applied, input { reason: text, evidence: text }
|
|
552
|
-
requires approval by approval protectedRequest self differentFromInitiator true
|
|
551
|
+
from: requested, to: applied, actor: { party: costs_to }, input { reason: text, evidence: text }
|
|
553
552
|
invoke: [{ reference: self.assessment, action: waive, input: { reason: { field: input.reason }, evidence: { field: input.evidence } } }]
|
|
554
553
|
}
|
|
555
554
|
action cancel { from: requested, to: cancelled }
|
|
@@ -575,32 +574,36 @@ instrument late_charge(on: ref<financing.installments>[], grace: duration = 3d,
|
|
|
575
574
|
}
|
|
576
575
|
}
|
|
577
576
|
|
|
578
|
-
instrument limits(per_borrower: money,
|
|
577
|
+
instrument limits(per_borrower: money, borrower: party = party(person), active_plans: integer = 1) {
|
|
579
578
|
familyRevision: 1
|
|
580
|
-
summary: "One
|
|
579
|
+
summary: "One outstanding balance ceiling per borrower."
|
|
581
580
|
fields { borrower: account of borrower, limit: money = per_borrower, activePlans: integer = active_plans }
|
|
582
581
|
lifecycle { states: [pending, approved], initial: pending }
|
|
583
582
|
action create { requires unique "borrower_limit" on [self.borrower] }
|
|
584
583
|
action approve { from: pending, to: approved }
|
|
585
|
-
records {
|
|
586
|
-
portfolio: {
|
|
587
|
-
fields { key: text = "portfolio", limit: money = portfolio }
|
|
588
|
-
lifecycle { states: [pending, approved], initial: pending }
|
|
589
|
-
action create { requires unique "portfolio_limit" on [self.key] }
|
|
590
|
-
action approve { from: pending, to: approved }
|
|
591
|
-
}
|
|
592
|
-
}
|
|
593
584
|
}
|
|
594
585
|
|
|
595
|
-
instrument
|
|
586
|
+
instrument portfolio_limit(limit: money) {
|
|
596
587
|
familyRevision: 1
|
|
597
|
-
summary: "
|
|
598
|
-
fields {
|
|
588
|
+
summary: "One shared ceiling on the principal the product may hold."
|
|
589
|
+
fields { key: text = "portfolio", limit: money = limit }
|
|
590
|
+
lifecycle { states: [pending, approved], initial: pending }
|
|
591
|
+
action create { requires unique "portfolio_limit" on [self.key] }
|
|
592
|
+
action approve { from: pending, to: approved }
|
|
593
|
+
}
|
|
594
|
+
|
|
595
|
+
instrument credit_line(borrower: party = programOperator, adapter: text, limit: money, expires: date) {
|
|
596
|
+
familyRevision: 1
|
|
597
|
+
summary: "A revolving facility from an outside lender; each draw is a separate immutable advance."
|
|
598
|
+
fields { borrower: account of borrower, facility: account(borrower, cash, "facility"), debt: account(borrower, claim, contra, "debt"), limit: money = limit, expiresAt: date = expires }
|
|
599
599
|
lifecycle { states: [pending, active, suspended, closed], initial: pending }
|
|
600
600
|
action create {}
|
|
601
|
-
action activate {
|
|
602
|
-
|
|
603
|
-
|
|
601
|
+
action activate {
|
|
602
|
+
from: pending, to: active, actor: { party: borrower }
|
|
603
|
+
subject { adapter: adapter }
|
|
604
|
+
}
|
|
605
|
+
action suspend { from: active, to: suspended, actor: { party: borrower } }
|
|
606
|
+
action resume { from: suspended, to: active, actor: { party: borrower } }
|
|
604
607
|
action close { from: [active, suspended], to: closed, due: { at: self.expiresAt }, requires count of { instrument: all(financing.advance), reference: "line", anchor: self.id, states: [drawn], limit: 366 } == 0 }
|
|
605
608
|
}
|
|
606
609
|
|
|
@@ -615,8 +618,8 @@ instrument advance(line: ref<financing.credit_line>, amount: money = runtime) {
|
|
|
615
618
|
from: pending, to: drawn
|
|
616
619
|
requires self.line in [active]
|
|
617
620
|
deadline: { at: self.line.expiresAt }
|
|
618
|
-
moves self.amount from self.line.
|
|
621
|
+
moves self.amount from self.line.facility to self.line.borrower; moves self.amount from self.line.debt to self.principalReceivable
|
|
619
622
|
}
|
|
620
|
-
action repay { from: drawn, to: repaid, moves self.amount from self.line.borrower to self.line.
|
|
623
|
+
action repay { from: drawn, to: repaid, moves self.amount from self.line.borrower to self.line.facility; moves self.amount from self.principalReceivable to self.line.debt }
|
|
621
624
|
action cancel { from: pending, to: cancelled }
|
|
622
625
|
}
|
package/std/insurance.hsx
CHANGED
|
@@ -1,13 +1,16 @@
|
|
|
1
1
|
header insurance
|
|
2
2
|
|
|
3
|
-
instrument cover(holder: party,
|
|
4
|
-
summary: "Recurring cover
|
|
5
|
-
fields { covers: ref<covers>, holder: account of holder,
|
|
3
|
+
instrument cover(holder: party, adapter: text, commission: percent = 0%, covers: ref, premium: money = runtime) {
|
|
4
|
+
summary: "Recurring cover bound to an outside insurer across an ADL boundary."
|
|
5
|
+
fields { covers: ref<covers>, holder: account of holder, expiresAt: date }
|
|
6
6
|
lifecycle { states: [pending, active, cancelled, expired], initial: pending }
|
|
7
7
|
action create {}
|
|
8
|
-
action activate {
|
|
8
|
+
action activate {
|
|
9
|
+
from: pending, to: active, actor: { party: programOperator }
|
|
10
|
+
subject { adapter: adapter }
|
|
11
|
+
}
|
|
9
12
|
action cancel {
|
|
10
|
-
from: active, to: cancelled
|
|
13
|
+
from: active, to: cancelled, actor: { party: holder }
|
|
11
14
|
invoke: [{ selection: { instrument: slice, reference: "cover", anchor: self.id, states: [paid], limit: 366 }, action: refund, input: {} }]
|
|
12
15
|
}
|
|
13
16
|
action expire { from: active, to: expired, actor: clock, due: { at: self.expiresAt } }
|
|
@@ -25,34 +28,32 @@ instrument cover(holder: party, insurer: party, approval: approval = programOper
|
|
|
25
28
|
requires unique "premium_period" on [self.cover, self.startsAt, self.endsAt]
|
|
26
29
|
}
|
|
27
30
|
action collect {
|
|
28
|
-
from: pending, to: paid
|
|
31
|
+
from: pending, to: paid, actor: { party: holder }
|
|
29
32
|
requires self.cover in [active]
|
|
30
|
-
moves self.premium from holder to
|
|
31
|
-
moves self.commission from insurer to programOperator
|
|
33
|
+
moves self.premium from holder to programOperator
|
|
32
34
|
}
|
|
33
35
|
action start { from: paid, to: active, actor: clock, due: { at: self.startsAt } }
|
|
34
36
|
action expire { from: active, to: expired, actor: clock, due: { at: self.endsAt } }
|
|
35
37
|
action refund {
|
|
36
|
-
from: paid, to: refunded, deadline: { at: self.startsAt }
|
|
37
|
-
moves self.
|
|
38
|
-
moves self.premium from insurer to holder
|
|
38
|
+
from: paid, to: refunded, actor: { parent: parent }, deadline: { at: self.startsAt }
|
|
39
|
+
moves self.premium from programOperator to holder
|
|
39
40
|
}
|
|
40
41
|
}
|
|
41
42
|
}
|
|
42
43
|
}
|
|
43
44
|
|
|
44
|
-
instrument claim(cover: ref<insurance.cover>,
|
|
45
|
+
instrument claim(cover: ref<insurance.cover>, inspector: party) {
|
|
45
46
|
summary: "A claim decision reserves one claim payment before settlement."
|
|
46
47
|
fields { cover: ref<cover>, amount: money, expiresAt: date, evidence: text, reservation: text? }
|
|
47
48
|
lifecycle { states: [submitted, approved, paid, denied, expired], initial: submitted }
|
|
48
49
|
action create { requires self.cover in [active] }
|
|
49
50
|
action approve {
|
|
50
51
|
from: submitted, to: approved
|
|
51
|
-
|
|
52
|
+
actor: { party: inspector }
|
|
52
53
|
deadline: { at: self.expiresAt }
|
|
53
|
-
moves reserve self.amount from
|
|
54
|
+
moves reserve self.amount from programOperator to self.cover.holder capture "reservation"
|
|
54
55
|
}
|
|
55
|
-
action pay { from: approved, to: paid, deadline: { at: self.expiresAt }, moves post self.reservation }
|
|
56
|
-
action deny { from: submitted, to: denied,
|
|
56
|
+
action pay { from: approved, to: paid, actor: { party: inspector }, deadline: { at: self.expiresAt }, moves post self.reservation }
|
|
57
|
+
action deny { from: submitted, to: denied, actor: { party: inspector } }
|
|
57
58
|
action expire { from: approved, to: expired, actor: clock, due: { at: self.expiresAt }, moves void self.reservation }
|
|
58
59
|
}
|
package/std/lending.hsx
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
header lending
|
|
2
2
|
|
|
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)) {
|
|
3
|
+
instrument round(borrower: party, plan: ref<financing.installments> = object(financing.installments), operator: party = programOperator, 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
6
|
borrower: account of borrower, plan: ref<plan>, price: money = self.plan.principal, closesAt: date
|
|
@@ -8,9 +8,9 @@ instrument round(borrower: party, plan: ref<financing.installments> = object(fin
|
|
|
8
8
|
held: account of self
|
|
9
9
|
}
|
|
10
10
|
lifecycle { states: [open, funded, failed], initial: open }
|
|
11
|
-
action create { requires unique "funding_plan" on [self.plan]; requires self.borrower == self.plan.
|
|
11
|
+
action create { requires unique "funding_plan" on [self.plan]; requires self.borrower == self.plan.borrower }
|
|
12
12
|
action close {
|
|
13
|
-
from: open, to: funded
|
|
13
|
+
from: open, to: funded, actor: { party: operator }
|
|
14
14
|
requires sum "amount" of { instrument: commitments, reference: "round", anchor: self.id, states: [committed], limit: 366 } == self.price
|
|
15
15
|
requires self.held.balance == self.price
|
|
16
16
|
moves self.price from self.held to self.plan.capital
|
|
@@ -30,6 +30,7 @@ instrument commitment(round: ref<lending.round>, wallet: ref<wallet.balance>, in
|
|
|
30
30
|
invariants sum "amount" of { instrument: all(lending.commitment), reference: "round", anchor: self.round, states: [committed, funded], limit: 366, where: { wallet: { field: self.wallet } } } <= self.round.maximumTicket
|
|
31
31
|
invariants sum "amount" of { instrument: all(lending.commitment), reference: "round", anchor: self.round, states: [committed, funded], limit: 366 } <= self.round.price
|
|
32
32
|
action create {
|
|
33
|
+
actor: { party: investor }
|
|
33
34
|
requires self.round in [open]
|
|
34
35
|
requires self.wallet in [active]
|
|
35
36
|
requires self.amount >= self.round.minimumTicket
|
|
@@ -38,7 +39,7 @@ instrument commitment(round: ref<lending.round>, wallet: ref<wallet.balance>, in
|
|
|
38
39
|
}
|
|
39
40
|
action fund { from: committed, to: funded, actor: { parent: round } }
|
|
40
41
|
action withdraw {
|
|
41
|
-
from: committed, to: withdrawn
|
|
42
|
+
from: committed, to: withdrawn, actor: { party: investor }
|
|
42
43
|
requires self.round in [open]
|
|
43
44
|
deadline: { at: self.round.closesAt }
|
|
44
45
|
moves self.amount from self.round.held to self.wallet.held
|
|
@@ -49,7 +50,7 @@ instrument commitment(round: ref<lending.round>, wallet: ref<wallet.balance>, in
|
|
|
49
50
|
}
|
|
50
51
|
}
|
|
51
52
|
|
|
52
|
-
instrument distribution(round: ref<lending.round>, receipt: ref, commitments: ref<lending.commitment> = object(lending.commitment), mode: enum(cash, loss) = cash, residual_to: party = programOperator, fee: percent = 1%, tax: percent = 15%) {
|
|
53
|
+
instrument distribution(round: ref<lending.round>, receipt: ref, commitments: ref<lending.commitment> = object(lending.commitment), mode: enum(cash, loss) = cash, residual_to: party = programOperator, operator: party = programOperator, fee: percent = 1%, tax: percent = 15%) {
|
|
53
54
|
summary: "Frozen weighted shares, floored once, with residual assigned to the chosen party."
|
|
54
55
|
fields {
|
|
55
56
|
round: ref<round>, source: ref<receipt>, mode: enum(cash, loss) = mode
|
|
@@ -76,7 +77,7 @@ instrument distribution(round: ref<lending.round>, receipt: ref, commitments: re
|
|
|
76
77
|
calculate: [{ target: "net", op: "sum", values: [{ field: self.source.loss }] }]
|
|
77
78
|
}
|
|
78
79
|
action distribute_cash {
|
|
79
|
-
from: cash_ready, to: distributed
|
|
80
|
+
from: cash_ready, to: distributed, actor: { party: operator }
|
|
80
81
|
requires sum "weight" of { instrument: share, reference: "distribution", anchor: self.id, states: [pending], limit: 366 } == self.round.price
|
|
81
82
|
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
|
|
82
83
|
invoke: [{ selection: { instrument: share, reference: "distribution", anchor: self.id, states: [pending], limit: 366 }, action: cash, input: {} }, { reference: self.id, action: residual_cash, input: {} }]
|
|
@@ -86,7 +87,7 @@ instrument distribution(round: ref<lending.round>, receipt: ref, commitments: re
|
|
|
86
87
|
moves self.held.balance from self.held to residual_to
|
|
87
88
|
}
|
|
88
89
|
action distribute_loss {
|
|
89
|
-
from: loss_ready, to: distributed
|
|
90
|
+
from: loss_ready, to: distributed, actor: { party: operator }
|
|
90
91
|
requires sum "weight" of { instrument: share, reference: "distribution", anchor: self.id, states: [pending], limit: 366 } == self.round.price
|
|
91
92
|
moves self.net from self.source.lossAccount to self.losses
|
|
92
93
|
invoke: [{ selection: { instrument: share, reference: "distribution", anchor: self.id, states: [pending], limit: 366 }, action: loss, input: {} }, { reference: self.id, action: residual_loss, input: {} }]
|
package/std/money.hsx
CHANGED
|
@@ -26,11 +26,11 @@ instrument hold(payer: party, payee: party, amount: money = runtime) {
|
|
|
26
26
|
requires self.held.balance == self.amount
|
|
27
27
|
}
|
|
28
28
|
action release {
|
|
29
|
-
from: funded, to: released
|
|
29
|
+
from: funded, to: released, actor: { party: payer }
|
|
30
30
|
moves self.amount from self.held to payee
|
|
31
31
|
}
|
|
32
32
|
action refund {
|
|
33
|
-
from: funded, to: refunded
|
|
33
|
+
from: funded, to: refunded, actor: { party: payee }
|
|
34
34
|
moves self.amount from self.held to payer
|
|
35
35
|
}
|
|
36
36
|
action cancel { from: pending, to: cancelled }
|
|
@@ -41,7 +41,7 @@ instrument split(payer: party, amount: money = runtime, shares: split = { progra
|
|
|
41
41
|
fields { amount: money = amount }
|
|
42
42
|
lifecycle { states: [pending, paid, cancelled], initial: pending }
|
|
43
43
|
action create {}
|
|
44
|
-
action pay { from: pending, to: paid, moves self.amount from payer shares shares }
|
|
44
|
+
action pay { from: pending, to: paid, actor: { party: payer }, moves self.amount from payer shares shares }
|
|
45
45
|
action cancel { from: pending, to: cancelled }
|
|
46
46
|
}
|
|
47
47
|
|
|
@@ -84,7 +84,7 @@ instrument pool(payer: party, payee: party, target: money, closes: date) {
|
|
|
84
84
|
lifecycle { states: [open, paid, failed], initial: open }
|
|
85
85
|
action create { }
|
|
86
86
|
action pay {
|
|
87
|
-
from: open, to: paid
|
|
87
|
+
from: open, to: paid, actor: { party: payee }
|
|
88
88
|
requires self.held.balance == self.target
|
|
89
89
|
moves self.target from self.held to payee
|
|
90
90
|
}
|
|
@@ -98,7 +98,7 @@ instrument pool(payer: party, payee: party, target: money, closes: date) {
|
|
|
98
98
|
fields { pool: ref<parent>, payer: account of payer, amount: money }
|
|
99
99
|
lifecycle { states: [pending, paid, refunded], initial: pending }
|
|
100
100
|
action create { requires self.pool in [open] }
|
|
101
|
-
action pay { from: pending, to: paid, deadline: { at: self.pool.closesAt }, requires self.pool in [open], moves self.amount from self.payer to self.pool.held }
|
|
101
|
+
action pay { from: pending, to: paid, actor: { party: payer }, deadline: { at: self.pool.closesAt }, requires self.pool in [open], moves self.amount from self.payer to self.pool.held }
|
|
102
102
|
action refund { from: paid, to: refunded, actor: { parent: parent }, moves self.amount from self.pool.held to self.payer }
|
|
103
103
|
}
|
|
104
104
|
}
|
|
@@ -114,29 +114,19 @@ instrument swap(first: party, second: party, first_amount: money, second_amount:
|
|
|
114
114
|
action start_second { from: pending, to: second_ready, actor: { party: second }, deadline: { at: self.expiresAt }, moves reserve self.secondAmount from second to first capture "secondReceipt" }
|
|
115
115
|
action finish_first { from: second_ready, to: both_ready, actor: { party: first }, deadline: { at: self.expiresAt }, moves reserve self.firstAmount from first to second capture "firstReceipt" }
|
|
116
116
|
action expire_second { from: second_ready, to: cancelled, actor: clock, due: { at: self.expiresAt }, moves void self.secondReceipt }
|
|
117
|
-
action exchange { from: both_ready, to: exchanged, moves post self.firstReceipt; moves post self.secondReceipt }
|
|
117
|
+
action exchange { from: both_ready, to: exchanged, actor: { party: first }, moves post self.firstReceipt; moves post self.secondReceipt }
|
|
118
118
|
action cancel { from: pending, to: cancelled }
|
|
119
119
|
action expire_first { from: first_ready, to: cancelled, actor: clock, due: { at: self.expiresAt }, moves void self.firstReceipt }
|
|
120
120
|
action expire_both { from: both_ready, to: cancelled, actor: clock, due: { at: self.expiresAt }, moves void self.firstReceipt; moves void self.secondReceipt }
|
|
121
121
|
}
|
|
122
122
|
|
|
123
|
-
instrument deposit(payer: party, payee: party, amount: money, expires: date, approval: approval) {
|
|
124
|
-
fields { amount: money = amount, expiresAt: date = expires, reservation: text? }
|
|
125
|
-
lifecycle { states: [pending, held, claimed, returned, cancelled], initial: pending }
|
|
126
|
-
action create {}
|
|
127
|
-
action fund { from: pending, to: held, actor: { party: payer }, moves reserve self.amount from payer to payee capture "reservation" }
|
|
128
|
-
action claim { from: held, to: claimed, deadline: { at: self.expiresAt }, requires approval by approval, moves post self.reservation }
|
|
129
|
-
action return { from: held, to: returned, actor: clock, due: { at: self.expiresAt }, moves void self.reservation }
|
|
130
|
-
action cancel { from: pending, to: cancelled }
|
|
131
|
-
}
|
|
132
|
-
|
|
133
123
|
instrument payout(payer: party, payee: party, adapter: text, max_age: duration, amount: money = runtime) {
|
|
134
124
|
summary: "Reserve funds until matching terminal boundary evidence permits posting."
|
|
135
125
|
fields { amount: money = amount, receipt: text? }
|
|
136
126
|
lifecycle { states: [pending, instructed, settled, rejected], initial: pending }
|
|
137
127
|
action create {}
|
|
138
128
|
action instruct {
|
|
139
|
-
from: pending, to: instructed, actor: { party: payer }
|
|
129
|
+
from: pending, to: instructed, actor: { party: payer }
|
|
140
130
|
moves reserve self.amount from payer to payee capture "receipt" boundary adapter
|
|
141
131
|
}
|
|
142
132
|
action confirm {
|
|
@@ -156,6 +146,6 @@ instrument metered(payer: party, payee: party, unit_price: money, units: integer
|
|
|
156
146
|
fields { usageIdentity: text, unitPrice: money = unit_price, units: integer = units, amount: money = multiply(self.unitPrice, self.units) }
|
|
157
147
|
lifecycle { states: [recorded, billed, cancelled], initial: recorded }
|
|
158
148
|
action create { requires unique "usage_event" on [self.usageIdentity] }
|
|
159
|
-
action bill { from: recorded, to: billed, moves self.amount from payer to payee fee fee }
|
|
149
|
+
action bill { from: recorded, to: billed, actor: { party: payee }, moves self.amount from payer to payee fee fee }
|
|
160
150
|
action cancel { from: recorded, to: cancelled }
|
|
161
151
|
}
|
package/std/reporting.hsx
CHANGED
|
@@ -351,7 +351,6 @@ instrument portfolio(on: ref<financing.installments>[], default_days: integer(1,
|
|
|
351
351
|
request: [ "owner", "finance" ],
|
|
352
352
|
read: [ "owner", "admin", "operations", "finance", "viewer" ],
|
|
353
353
|
release: [ ],
|
|
354
|
-
independentApproval: true,
|
|
355
354
|
retention: { policy: "report_replay", years: retention_years }
|
|
356
355
|
}
|
|
357
356
|
},
|
|
@@ -632,7 +631,6 @@ instrument portfolio(on: ref<financing.installments>[], default_days: integer(1,
|
|
|
632
631
|
request: [ "owner", "finance" ],
|
|
633
632
|
read: [ "owner", "admin", "operations", "finance", "viewer" ],
|
|
634
633
|
release: [ ],
|
|
635
|
-
independentApproval: true,
|
|
636
634
|
retention: { policy: "report_replay", years: retention_years }
|
|
637
635
|
}
|
|
638
636
|
},
|
|
@@ -1002,7 +1000,6 @@ instrument portfolio(on: ref<financing.installments>[], default_days: integer(1,
|
|
|
1002
1000
|
request: [ "owner", "finance" ],
|
|
1003
1001
|
read: [ "owner", "admin", "operations", "finance", "viewer" ],
|
|
1004
1002
|
release: [ ],
|
|
1005
|
-
independentApproval: true,
|
|
1006
1003
|
retention: { policy: "report_replay", years: retention_years }
|
|
1007
1004
|
}
|
|
1008
1005
|
},
|
|
@@ -1278,7 +1275,6 @@ instrument portfolio(on: ref<financing.installments>[], default_days: integer(1,
|
|
|
1278
1275
|
request: [ "owner", "finance" ],
|
|
1279
1276
|
read: [ "owner", "admin", "operations", "finance", "viewer" ],
|
|
1280
1277
|
release: [ ],
|
|
1281
|
-
independentApproval: true,
|
|
1282
1278
|
retention: { policy: "report_replay", years: retention_years }
|
|
1283
1279
|
}
|
|
1284
1280
|
}
|