@hyperscale0/hsx 1.0.0 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +15 -4
- package/README.md +58 -38
- package/dist/src/ast.d.ts +4 -2
- package/dist/src/ast.d.ts.map +1 -1
- package/dist/src/cli.d.ts +1 -1
- package/dist/src/cli.js.map +1 -1
- package/dist/src/compile.d.ts +8 -2
- package/dist/src/compile.d.ts.map +1 -1
- package/dist/src/compile.js +8 -1
- package/dist/src/compile.js.map +1 -1
- package/dist/src/cost.d.ts +3 -1
- package/dist/src/cost.d.ts.map +1 -1
- package/dist/src/cost.js +124 -94
- package/dist/src/cost.js.map +1 -1
- package/dist/src/diagnostics.d.ts.map +1 -1
- package/dist/src/diagnostics.js +89 -5
- package/dist/src/diagnostics.js.map +1 -1
- package/dist/src/emit.d.ts +3 -1
- package/dist/src/emit.d.ts.map +1 -1
- package/dist/src/emit.js +27 -10
- package/dist/src/emit.js.map +1 -1
- package/dist/src/format.js.map +1 -1
- package/dist/src/index.d.ts +2 -2
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +1 -1
- package/dist/src/index.js.map +1 -1
- package/dist/src/ir.d.ts.map +1 -1
- package/dist/src/lex.d.ts.map +1 -1
- package/dist/src/lsp/server.js.map +1 -1
- package/dist/src/modules.js +7 -3
- package/dist/src/modules.js.map +1 -1
- package/dist/src/parse.js +3 -3
- package/dist/src/parse.js.map +1 -1
- package/dist/src/std-bundle.js +41 -41
- package/dist/src/std-bundle.js.map +1 -1
- package/dist/src/std-library.js +2 -2
- package/dist/src/typecheck.d.ts.map +1 -1
- package/dist/src/typecheck.js +859 -156
- package/dist/src/typecheck.js.map +1 -1
- package/dist/src/version.d.ts +1 -1
- package/dist/src/version.js +1 -1
- package/docs/README.md +10 -1
- package/docs/assets/hsx.svg +18 -0
- package/docs/guide/01-first-program.md +1 -1
- package/docs/guide/02-money.md +1 -1
- package/docs/guide/03-instruments.md +44 -3
- package/docs/guide/04-lifecycles.md +18 -3
- package/docs/guide/05-fees-and-splits.md +2 -2
- package/docs/guide/06-schedules.md +1 -1
- package/docs/guide/07-composition.md +8 -2
- package/docs/guide/08-writing-a-module.md +13 -2
- package/docs/guide/09-cost.md +3 -3
- package/docs/guide/10-diagnostics.md +1 -1
- package/docs/llms-full.txt +453 -190
- package/docs/llms.txt +2 -2
- package/docs/playground.md +4 -3
- package/docs/reference/cli.md +2 -2
- package/docs/reference/diagnostics.md +223 -37
- package/docs/reference/grammar.md +2 -2
- package/docs/reference/std/advance.md +2 -2
- package/docs/reference/std/cancellable_booking.md +10 -10
- package/docs/reference/std/captured_payment.md +14 -14
- package/docs/reference/std/conditional_disbursement.md +3 -3
- package/docs/reference/std/credit_facility.md +2 -2
- package/docs/reference/std/held_payment.md +37 -33
- package/docs/reference/std/instant_transfer.md +8 -8
- package/docs/reference/std/metered.md +2 -2
- package/docs/reference/std/pooled_split.md +2 -2
- package/docs/reference/std/premium_forward.md +13 -13
- package/docs/reference/std/reconciled_payout.md +2 -2
- package/docs/reference/std/recurring_collection.md +2 -2
- package/docs/reference/std/rotating_pool.md +2 -2
- package/docs/reference/std/scheduled.md +18 -18
- package/docs/reference/std/security_deposit.md +14 -14
- package/docs/reference/std/settlement_batch.md +2 -2
- package/docs/reference/std/swap.md +18 -18
- package/docs/reference/std/threshold_pool.md +2 -2
- package/docs/reference/std/weighted_distribution.md +2 -2
- package/docs/reference/types.md +1 -1
- package/docs/reference/udl-output.md +1 -1
- package/examples/01-first-program/README.md +1 -1
- package/examples/01-first-program/tip-jar.hsx +1 -1
- package/examples/02-imports-and-archetypes/photo-booth.hsx +1 -1
- package/examples/03-diagnostics/corner-shop-fixed.hsx +1 -1
- package/examples/03-diagnostics/corner-shop.hsx +1 -1
- package/examples/04-complete-product/study-hall.hsx +1 -1
- package/examples/05-watch-club/README.md +0 -3
- package/examples/05-watch-club/watch-club.hsx +1 -1
- package/examples/README.md +35 -4
- package/examples/advance/advance.hsx +1 -1
- package/examples/advance/advance.udl +10 -5
- package/examples/cancellable_booking/cancellable_booking.hsx +1 -1
- package/examples/cancellable_booking/cancellable_booking.udl +3 -1
- package/examples/captured_payment/captured_payment.hsx +1 -1
- package/examples/captured_payment/captured_payment.udl +4 -1
- package/examples/conditional_disbursement/conditional_disbursement.hsx +1 -1
- package/examples/conditional_disbursement/conditional_disbursement.udl +5 -3
- package/examples/cost-table.json +1602 -382
- package/examples/credit_facility/credit_facility.hsx +1 -1
- package/examples/credit_facility/credit_facility.udl +16 -9
- package/examples/held_payment/held_payment.hsx +1 -1
- package/examples/held_payment/held_payment.udl +38 -3
- package/examples/instant_transfer/instant_transfer.hsx +1 -1
- package/examples/instant_transfer/instant_transfer.udl +11 -5
- package/examples/metered/metered.hsx +1 -1
- package/examples/metered/metered.udl +4 -2
- package/examples/pooled_split/pooled_split.hsx +1 -1
- package/examples/pooled_split/pooled_split.udl +6 -3
- package/examples/premium_forward/premium_forward.hsx +1 -1
- package/examples/premium_forward/premium_forward.udl +10 -4
- package/examples/reconciled_payout/reconciled_payout.hsx +1 -1
- package/examples/reconciled_payout/reconciled_payout.udl +4 -2
- package/examples/recurring_collection/recurring_collection.hsx +1 -1
- package/examples/recurring_collection/recurring_collection.udl +12 -7
- package/examples/rotating_pool/rotating_pool.hsx +1 -1
- package/examples/rotating_pool/rotating_pool.udl +14 -4
- package/examples/scheduled/scheduled.hsx +1 -1
- package/examples/scheduled/scheduled.udl +9 -4
- package/examples/security_deposit/security_deposit.hsx +1 -1
- package/examples/security_deposit/security_deposit.udl +17 -3
- package/examples/settlement_batch/settlement_batch.hsx +1 -1
- package/examples/swap/swap.hsx +1 -1
- package/examples/swap/swap.udl +12 -6
- package/examples/threshold_pool/threshold_pool.hsx +1 -1
- package/examples/threshold_pool/threshold_pool.udl +4 -2
- package/examples/weighted_distribution/weighted_distribution.hsx +1 -1
- package/examples/weighted_distribution/weighted_distribution.udl +4 -2
- package/package.json +6 -5
- package/skills/hsx/SKILL.md +26 -26
- package/src/ast.ts +4 -2
- package/src/cli.ts +4 -4
- package/src/compile.ts +14 -3
- package/src/cost.ts +176 -104
- package/src/diagnostics.ts +89 -4
- package/src/emit.ts +32 -18
- package/src/index.ts +2 -1
- package/src/modules.ts +9 -3
- package/src/parse.ts +3 -3
- package/src/std-bundle.ts +41 -41
- package/src/std-library.ts +2 -2
- package/src/typecheck.ts +1147 -235
- package/src/version.ts +1 -1
- package/std/SEMANTICS.md +12 -3
- package/std/{settlements → money_flows}/advance.hsx +1 -1
- package/std/{settlements → money_flows}/cancellable_booking.hsx +4 -3
- package/std/{settlements → money_flows}/captured_payment.hsx +35 -6
- package/std/{settlements → money_flows}/conditional_disbursement.hsx +17 -16
- package/std/{settlements → money_flows}/credit_facility.hsx +1 -2
- package/std/{settlements → money_flows}/held_payment.hsx +59 -25
- package/std/money_flows/index.hsx +3 -0
- package/std/{settlements → money_flows}/instant_transfer.hsx +2 -3
- package/std/{settlements → money_flows}/metered.hsx +1 -1
- package/std/{settlements → money_flows}/pooled_split.hsx +3 -3
- package/std/{settlements → money_flows}/premium_forward.hsx +22 -23
- package/std/{settlements → money_flows}/reconciled_payout.hsx +3 -3
- package/std/{settlements → money_flows}/recurring_collection.hsx +1 -1
- package/std/{settlements → money_flows}/rotating_pool.hsx +8 -6
- package/std/{settlements → money_flows}/scheduled.hsx +22 -27
- package/std/{settlements → money_flows}/security_deposit.hsx +38 -14
- package/std/{settlements → money_flows}/settlement_batch.hsx +3 -3
- package/std/{settlements → money_flows}/swap.hsx +41 -16
- package/std/{settlements → money_flows}/threshold_pool.hsx +5 -5
- package/std/{settlements → money_flows}/weighted_distribution.hsx +6 -6
- package/docs/sessions/2026-09-02-two-instruments.hsx +0 -21
- package/docs/sessions/2026-09-02-two-instruments.md +0 -41
- package/std/settlements/index.hsx +0 -3
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
module std.
|
|
1
|
+
module std.money_flows.reconciled_payout
|
|
2
2
|
|
|
3
3
|
export instrument reconciled_payout<C>(
|
|
4
4
|
payer: party,
|
|
@@ -17,8 +17,8 @@ export instrument reconciled_payout<C>(
|
|
|
17
17
|
currency { type: text; description: "ISO 4217 currency code"; minLength: 3; maxLength: 3; pattern: "^[A-Z]{3}$"; }
|
|
18
18
|
settle_by { type: date; description: "Instant the expectation stops waiting and the unmatched amount becomes a break"; }
|
|
19
19
|
beneficiary_ref { type: text; description: "Beneficiary ID for the payout instruction"; pattern: "^ben_(sandbox|live)_[a-z0-9]{8,64}$"; }
|
|
20
|
-
[beneficiary_account_field] { type: account<C>; description: concat("The ", words(beneficiary), " account");
|
|
21
|
-
[payer_account_field] { type: account<C>; description: concat("The ", words(payer), " account the payout leaves");
|
|
20
|
+
[beneficiary_account_field] { type: account<C>; description: concat("The ", words(beneficiary), " account"); [reference_filter_key]: { column: role; values: [customer_balance]; }; }
|
|
21
|
+
[payer_account_field] { type: account<C>; description: concat("The ", words(payer), " account the payout leaves"); [reference_filter_key]: { column: role; values: [customer_balance]; }; }
|
|
22
22
|
}
|
|
23
23
|
lifecycle {
|
|
24
24
|
states created instructed settled;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
module std.
|
|
1
|
+
module std.money_flows.recurring_collection
|
|
2
2
|
|
|
3
3
|
export instrument recurring_collection(marker: optional<text>) {
|
|
4
4
|
agent_description: concat("Reach for ", words(instrument), " to track a bounded run of scheduled collections, one call per recorded installment. It carries no amount and no account, and every action only advances its own state. A settlement that debits an account on a schedule is a different shape.");
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
module std.
|
|
1
|
+
module std.money_flows.rotating_pool
|
|
2
2
|
|
|
3
3
|
export instrument rotating_pool<C>(members: optional<list<party>>, contribution: money<C>, count: integer, every: optional<text>, first_due: date, payout_order: optional<list<party>>, default_policy: optional<text>, guarantee_policy: optional<text>, guarantor: optional<party>, exit_policy: optional<text>, memo: optional<text>, membership: optional<block>) {
|
|
4
4
|
when_not(membership) {
|
|
@@ -9,8 +9,8 @@ export instrument rotating_pool<C>(members: optional<list<party>>, contribution:
|
|
|
9
9
|
let(parent_ref_field): concat(camel(instrument), "Id");
|
|
10
10
|
let(reference_filter): "x-hyperscale-reference-filter";
|
|
11
11
|
fields {
|
|
12
|
-
for member in members { [member]AccountId { type: account<C>; description: concat("The ", words(member), " account");
|
|
13
|
-
[guarantor_field] { type: account<C>; description: concat("The ", words(guarantor), " account");
|
|
12
|
+
for member in members { [member]AccountId { type: account<C>; description: concat("The ", words(member), " account"); [reference_filter]: { column: role; values: [customer_balance]; }; } }
|
|
13
|
+
[guarantor_field] { type: account<C>; description: concat("The ", words(guarantor), " account"); [reference_filter]: { column: role; values: [customer_balance]; }; }
|
|
14
14
|
[contribution_field] { type: money<C>; description: "Exact contribution in {C} minor units"; }
|
|
15
15
|
currency { type: text; description: "ISO 4217 currency code"; minLength: 3; maxLength: 3; pattern: "^[A-Z]{3}$"; }
|
|
16
16
|
[first_due_field] { type: date; description: "Stored first contribution due date"; }
|
|
@@ -83,8 +83,8 @@ export instrument rotating_pool<C>(members: optional<list<party>>, contribution:
|
|
|
83
83
|
summary: concat(words(member), " contribution row");
|
|
84
84
|
description: concat("Fixed contribution row for ", words(member));
|
|
85
85
|
fields {
|
|
86
|
-
for roster_member in payout_order { [roster_member]AccountId { type: account<C>; description: concat("The ", words(roster_member), " account");
|
|
87
|
-
[guarantor_field] { type: account<C>; description: concat("The ", words(guarantor), " account");
|
|
86
|
+
for roster_member in payout_order { [roster_member]AccountId { type: account<C>; description: concat("The ", words(roster_member), " account"); [reference_filter]: { column: role; values: [customer_balance]; }; } }
|
|
87
|
+
[guarantor_field] { type: account<C>; description: concat("The ", words(guarantor), " account"); [reference_filter]: { column: role; values: [customer_balance]; }; }
|
|
88
88
|
[contribution_field] { type: money<C>; description: "Exact contribution amount shared by every cycle"; }
|
|
89
89
|
currency { type: text; description: "ISO 4217 currency code"; minLength: 3; maxLength: 3; pattern: "^[A-Z]{3}$"; }
|
|
90
90
|
[first_due_field] { type: date; description: "First due anchor derived from the pool"; }
|
|
@@ -140,7 +140,7 @@ export instrument rotating_pool<C>(members: optional<list<party>>, contribution:
|
|
|
140
140
|
action contribute_cycle_[cycle] {
|
|
141
141
|
summary: concat("Fund ", words(member), "'s cycle ", cycle, " contribution");
|
|
142
142
|
let(first): if_eq(cycle, 1, true, false);
|
|
143
|
-
when(first) { due: { field: first_due_field; }; }
|
|
143
|
+
when(first) { due: { field: first_due_field; }; sandbox_failure_point: funding; }
|
|
144
144
|
when_not(first) { due: { field: first_due_field; offset: due_offset; }; }
|
|
145
145
|
requires refs { field: parent_ref_field; statuses: [active_state]; }
|
|
146
146
|
moves: [{ key: "contribution"; operation: internal_transfer.create; bind: { amount: { from: instance; path: concat("fields.", contribution_field); }; currency: { from: instance; path: "fields.currency"; }; destinationAccountId: { from: instance; path: "refs.escrowAccountId"; }; "metadata.instrumentId": { from: const; value: child_id; }; "metadata.instrumentInstanceId": { from: instance; path: instrumentInstanceId; }; "metadata.phase": { from: const; value: contribute_name; }; productId: { from: instance; path: productId; }; sourceAccountId: { from: instance; path: concat("fields.", camel(member), "AccountId"); }; }; capture: { [contribute_capture]: transferId; }; }];
|
|
@@ -167,6 +167,8 @@ export instrument rotating_pool<C>(members: optional<list<party>>, contribution:
|
|
|
167
167
|
summary: concat("Pay this member's stored contribution into cycle ", cycle, "'s shared pot recipient");
|
|
168
168
|
requires refs { field: parent_ref_field; statuses: [ready_state]; }
|
|
169
169
|
moves: [{ key: payout; operation: internal_transfer.create; bind: { amount: { from: instance; path: concat("fields.", contribution_field); }; currency: { from: instance; path: "fields.currency"; }; destinationAccountId: { from: instance; path: concat("fields.", payout_field); }; "metadata.instrumentId": { from: const; value: child_id; }; "metadata.instrumentInstanceId": { from: instance; path: instrumentInstanceId; }; "metadata.phase": { from: const; value: pay_name; }; productId: { from: instance; path: productId; }; sourceAccountId: { from: instance; path: "refs.escrowAccountId"; }; }; capture: { [pay_capture]: transferId; }; }];
|
|
170
|
+
let(first): if_eq(cycle, 1, true, false);
|
|
171
|
+
when(first) { sandbox_failure_point: "release"; }
|
|
170
172
|
steps: [];
|
|
171
173
|
}
|
|
172
174
|
action pay_guaranteed_cycle_[cycle] {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
module std.
|
|
1
|
+
module std.money_flows.scheduled
|
|
2
2
|
|
|
3
3
|
export instrument scheduled<C>(
|
|
4
4
|
payer: party,
|
|
@@ -76,7 +76,7 @@ export instrument scheduled<C>(
|
|
|
76
76
|
let(offset): scale_duration(every, sub(i, 1));
|
|
77
77
|
let(installment_field): concat("installment", i, "Amount");
|
|
78
78
|
summary: "Collect installment {i} of {count}";
|
|
79
|
-
when(first) { due: { field: first_due; }; }
|
|
79
|
+
when(first) { due: { field: first_due; }; sandbox_failure_point: funding; }
|
|
80
80
|
when_not(first) { due: { field: first_due; offset: offset; }; }
|
|
81
81
|
moves: [{ amount: installment_field; from: payer; to: beneficiary; key: transfer; }];
|
|
82
82
|
steps: [];
|
|
@@ -194,7 +194,6 @@ export instrument scheduled<C>(
|
|
|
194
194
|
[payee_field]: {
|
|
195
195
|
type: account;
|
|
196
196
|
description: "The {payee_words} account";
|
|
197
|
-
pattern: "^acct_(sandbox|live)_[a-z0-9]{8,64}$";
|
|
198
197
|
[reference_filter_key]: { column: role; values: [customer_balance]; };
|
|
199
198
|
}
|
|
200
199
|
}
|
|
@@ -202,7 +201,6 @@ export instrument scheduled<C>(
|
|
|
202
201
|
[payer_field]: {
|
|
203
202
|
type: account;
|
|
204
203
|
description: "The {payer_words} account";
|
|
205
|
-
pattern: "^acct_(sandbox|live)_[a-z0-9]{8,64}$";
|
|
206
204
|
[reference_filter_key]: { column: role; values: [customer_balance]; };
|
|
207
205
|
}
|
|
208
206
|
}
|
|
@@ -210,7 +208,6 @@ export instrument scheduled<C>(
|
|
|
210
208
|
[debtor_field]: {
|
|
211
209
|
type: account;
|
|
212
210
|
description: "The {debtor_words} account";
|
|
213
|
-
pattern: "^acct_(sandbox|live)_[a-z0-9]{8,64}$";
|
|
214
211
|
[reference_filter_key]: { column: role; values: [customer_balance]; };
|
|
215
212
|
}
|
|
216
213
|
}
|
|
@@ -218,7 +215,6 @@ export instrument scheduled<C>(
|
|
|
218
215
|
platform_account_id: {
|
|
219
216
|
type: account;
|
|
220
217
|
description: "The product fee collection account";
|
|
221
|
-
pattern: "^acct_(sandbox|live)_[a-z0-9]{8,64}$";
|
|
222
218
|
[fee_port_key]: true;
|
|
223
219
|
[reference_filter_key]: { column: role; values: [customer_balance, product_revenue]; };
|
|
224
220
|
}
|
|
@@ -471,7 +467,7 @@ export instrument scheduled<C>(
|
|
|
471
467
|
steps: [];
|
|
472
468
|
}
|
|
473
469
|
action repay {
|
|
474
|
-
agent_description: concat("Pay this record's amount toward installment ", i, ". The record must be created and its obligation live. Refused when this amount plus the records already paid against that installment would pass the stored amount. This moves the payer's money. Where a mandate applies,
|
|
470
|
+
agent_description: concat("Pay this record's amount toward installment ", i, ". The record must be created and its obligation live. Refused when this amount plus the records already paid against that installment would pass the stored amount. This moves the payer's money. Where a mandate applies, its declared parties may call it and an evidence reference is required.");
|
|
475
471
|
summary: concat("Pay a partial or full amount against installment ", i);
|
|
476
472
|
when(has_mandate) {
|
|
477
473
|
input: {
|
|
@@ -488,7 +484,7 @@ export instrument scheduled<C>(
|
|
|
488
484
|
type: object;
|
|
489
485
|
};
|
|
490
486
|
capture_input: { mandate_evidence_reference: evidenceReference; };
|
|
491
|
-
port: { allowed_parties:
|
|
487
|
+
port: { allowed_parties: mandate_allowed; };
|
|
492
488
|
}
|
|
493
489
|
requires refs: {
|
|
494
490
|
field: parent_ref_field;
|
|
@@ -591,7 +587,7 @@ export instrument scheduled<C>(
|
|
|
591
587
|
}
|
|
592
588
|
|
|
593
589
|
action collect_period {
|
|
594
|
-
agent_description: "Collect one open period charge from the payer, with the mandate evidence reference kept in the receipt. A period must be open.
|
|
590
|
+
agent_description: "Collect one open period charge from the payer, with the mandate evidence reference kept in the receipt. A period must be open. The mandate's declared parties may call it, or the payer when no mandate is wired. This moves the period amount and does not reverse.";
|
|
595
591
|
summary: "Collect one authored period charge with mandate evidence";
|
|
596
592
|
input: {
|
|
597
593
|
additional_properties: false;
|
|
@@ -607,33 +603,32 @@ export instrument scheduled<C>(
|
|
|
607
603
|
type: object;
|
|
608
604
|
};
|
|
609
605
|
capture_input: { mandate_evidence_reference: evidenceReference; };
|
|
610
|
-
port: { allowed_parties:
|
|
606
|
+
when(mandate) { port: { allowed_parties: mandate_allowed; }; }
|
|
607
|
+
when_not(mandate) { port: { allowed_parties: [payer]; }; }
|
|
611
608
|
moves: [{ amount: amount_field; from: payer; to: beneficiary; key: period_collection; }];
|
|
609
|
+
sandbox_failure_point: funding;
|
|
612
610
|
steps: [];
|
|
613
611
|
}
|
|
614
612
|
|
|
615
613
|
action [until] {
|
|
616
614
|
agent_description: "Cancel the open schedule for good and drain any period liability still standing. Only the payer may call it, and the reference fields the port declares are required. No further period opens and there is no reactivation.";
|
|
617
615
|
summary: "Cancel the open schedule and drain any period liability";
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
max_length: 180;
|
|
625
|
-
min_length: 1;
|
|
626
|
-
type: string;
|
|
616
|
+
when(until_fields) {
|
|
617
|
+
input: {
|
|
618
|
+
additional_properties: false;
|
|
619
|
+
properties: {
|
|
620
|
+
for item in keys(until_fields) {
|
|
621
|
+
[item]: get(until_fields, item);
|
|
627
622
|
}
|
|
628
|
-
}
|
|
623
|
+
};
|
|
624
|
+
required: keys(until_fields);
|
|
625
|
+
type: object;
|
|
629
626
|
};
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
};
|
|
636
|
-
port: { allowed_parties: ["payer"]; };
|
|
627
|
+
capture_input: {
|
|
628
|
+
for item in keys(until_fields) { [item]: item; }
|
|
629
|
+
};
|
|
630
|
+
}
|
|
631
|
+
port { allowed_parties: until_allowed; };
|
|
637
632
|
steps: [];
|
|
638
633
|
}
|
|
639
634
|
}
|
|
@@ -1,19 +1,15 @@
|
|
|
1
|
-
module std.
|
|
1
|
+
module std.money_flows.security_deposit
|
|
2
2
|
|
|
3
3
|
export instrument security_deposit<C>(payer: party, holder: party, amount: money<C>, claim: optional<condition>, return: optional<condition>, claim_amount: optional<block>, deadline: optional<date>, claim_to: optional<party>, return_to: optional<party>, memo: optional<text>, claim_input: optional<block>, claim_capture: optional<block>, fund_failure_point: optional<text>, id_prefix_override: optional<text>) {
|
|
4
4
|
let(claim_name): claim;
|
|
5
5
|
let(return_name): return;
|
|
6
6
|
let(payer_account_field): camel(concat(payer, "_account_id"));
|
|
7
7
|
let(holder_account_field): camel(concat(holder, "_account_id"));
|
|
8
|
-
let(claim_actor): at(claim_allowed, 1);
|
|
9
|
-
let(claim_role): if_eq(claim_actor, payer, "payer", "beneficiary");
|
|
10
8
|
let(claim_field): get(claim_amount, "field");
|
|
11
9
|
let(claim_bound): get(claim_amount, "bound");
|
|
12
10
|
let(claim_remainder): get(claim_amount, "remainder");
|
|
13
11
|
let(deadline_field): concat(deadline);
|
|
14
12
|
let(memo_field): concat(memo);
|
|
15
|
-
let(claim_to_role): if_eq(claim_to, payer, "payer", "beneficiary");
|
|
16
|
-
let(return_to_role): if_eq(return_to, payer, "payer", "beneficiary");
|
|
17
13
|
agent_description: "Reach for security deposit when money is reserved against the {payer} in the {holder}'s favor and later claimed or returned. The funds stay reserved and move only on the claim. Pick captured payment when the holder takes the money in slices, and instant transfer when nothing is held.";
|
|
18
14
|
summary: "Refundable deposit from {payer} held for {holder}";
|
|
19
15
|
title: sentence(instrument);
|
|
@@ -34,8 +30,8 @@ export instrument security_deposit<C>(payer: party, holder: party, amount: money
|
|
|
34
30
|
let(reference_filter_key): "x-hyperscale-reference-filter";
|
|
35
31
|
amount { type: money<C>; description: "Positive minor-unit integer amount serialized as a string (at most 18 digits)"; }
|
|
36
32
|
[deadline_field] { type: date; }
|
|
37
|
-
[holder_account_field] { type: account<C>; description: "Hyperscale account ID";
|
|
38
|
-
[payer_account_field] { type: account<C>; description: "Hyperscale account ID";
|
|
33
|
+
[holder_account_field] { type: account<C>; description: "Hyperscale account ID"; [reference_filter_key]: { column: role; values: [customer_balance]; }; }
|
|
34
|
+
[payer_account_field] { type: account<C>; description: "Hyperscale account ID"; [reference_filter_key]: { column: role; values: [customer_balance]; }; }
|
|
39
35
|
when(memo) { [memo_field] { type: text; max_length: 180; min_length: 1; optional: true; } }
|
|
40
36
|
}
|
|
41
37
|
}
|
|
@@ -75,11 +71,13 @@ export instrument security_deposit<C>(payer: party, holder: party, amount: money
|
|
|
75
71
|
let(metadata_phase): "metadata.phase";
|
|
76
72
|
summary: "Reserve the {amount} against the {payer}'s account";
|
|
77
73
|
moves: [{ key: reservation; operation: internal_transfer.reserve; bind: { amount: { from: instance; path: concat("fields.", amount); }; currency: { from: instance; path: fields.currency; }; destinationAccountId: { from: instance; path: concat("fields.", holder_account_field); }; [metadata_instrument]: { from: const; value: instrument; }; [metadata_instance]: { from: instance; path: instrumentInstanceId; }; [metadata_phase]: { from: const; value: place_deposit; }; productId: { from: instance; path: productId; }; sourceAccountId: { from: instance; path: concat("fields.", payer_account_field); }; }; capture: { placeDepositReservationTransferId: transferId; }; }];
|
|
74
|
+
sandbox_failure_point: funding;
|
|
78
75
|
steps: [];
|
|
79
76
|
}
|
|
80
77
|
action [claim_name] {
|
|
81
78
|
agent_description: "Claim the held deposit for the {holder}. The deposit must be in held. The reservation settles here, whole or up to the decided amount with the exact remainder released back to the {payer}. There is no return afterwards.";
|
|
82
79
|
summary: "Claim the deposit for the {holder} through {claim}";
|
|
80
|
+
when(claim_allowed) { port { allowed_parties: claim_allowed; }; }
|
|
83
81
|
when_not(claim_amount) {
|
|
84
82
|
moves: [{ key: post; operation: internal_transfer.post; bind: { transferId: { from: instance; path: refs.placeDepositReservationTransferId; }; }; }];
|
|
85
83
|
}
|
|
@@ -90,14 +88,12 @@ export instrument security_deposit<C>(payer: party, holder: party, amount: money
|
|
|
90
88
|
additional_properties: false;
|
|
91
89
|
properties {
|
|
92
90
|
for input_name in keys(claim_fields) {
|
|
93
|
-
[input_name]
|
|
91
|
+
[input_name]: get(claim_fields, input_name);
|
|
94
92
|
}
|
|
95
|
-
[claim_field] { type: string; description: "Caller-decided amount in minor units"; pattern: "^(0|[1-9][0-9]{0,17})$"; }
|
|
96
93
|
}
|
|
97
94
|
required: keys(claim_fields);
|
|
98
95
|
}
|
|
99
96
|
[decided_clause]: { field: claim_field; bound_field: claim_bound; remainder_action: return_name; };
|
|
100
|
-
port { allowed_parties: [claim_role]; };
|
|
101
97
|
moves: [{ key: post; operation: internal_transfer.post; bind: { amount: { from: input; path: claim_field; }; currency: { from: instance; path: fields.currency; }; postMode: { from: const; value: partial_only; }; transferId: { from: instance; path: refs.placeDepositReservationTransferId; }; }; }, { key: remainder; operation: internal_transfer.void; bind: { reason: { from: const; value: "Return the unclaimed deposit remainder"; }; transferId: { from: instance; path: refs.placeDepositReservationTransferId; }; }; }];
|
|
102
98
|
}
|
|
103
99
|
steps: [];
|
|
@@ -105,6 +101,22 @@ export instrument security_deposit<C>(payer: party, holder: party, amount: money
|
|
|
105
101
|
action [return_name] {
|
|
106
102
|
agent_description: "Return the held deposit to the {payer}. The deposit must be in held and unclaimed. This releases the reservation whole and the {holder} receives nothing.";
|
|
107
103
|
summary: "Return the deposit to the {payer} through {return}";
|
|
104
|
+
when(return_fields) {
|
|
105
|
+
input {
|
|
106
|
+
type: object;
|
|
107
|
+
additional_properties: false;
|
|
108
|
+
properties {
|
|
109
|
+
for input_name in keys(return_fields) {
|
|
110
|
+
[input_name]: get(return_fields, input_name);
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
required: keys(return_fields);
|
|
114
|
+
}
|
|
115
|
+
capture_input: {
|
|
116
|
+
for item in keys(return_fields) { [item]: item; }
|
|
117
|
+
};
|
|
118
|
+
}
|
|
119
|
+
port { allowed_parties: return_allowed; };
|
|
108
120
|
moves: [{ key: void; operation: internal_transfer.void; bind: { reason: { from: const; value: "Deposit returned in full"; }; transferId: { from: instance; path: refs.placeDepositReservationTransferId; }; }; }];
|
|
109
121
|
steps: [];
|
|
110
122
|
}
|
|
@@ -126,26 +138,38 @@ export instrument security_deposit<C>(payer: party, holder: party, amount: money
|
|
|
126
138
|
deadline: { field: deadline_field; };
|
|
127
139
|
moves: [{ key: reservation; operation: internal_transfer.reserve; bind: { amount: { from: instance; path: concat("fields.", amount); }; currency: { from: instance; path: fields.currency; }; destinationAccountId: { from: instance; path: concat("fields.", holder_account_field); }; productId: { from: instance; path: productId; }; sourceAccountId: { from: instance; path: concat("fields.", payer_account_field); }; }; capture: { holdTransferId: transferId; }; }];
|
|
128
140
|
when(fund_failure_point) { sandbox_failure_point: fund_failure_point; }
|
|
141
|
+
when_not(fund_failure_point) { sandbox_failure_point: funding; }
|
|
129
142
|
steps: [];
|
|
130
143
|
summary: "Fund the security deposit";
|
|
131
144
|
}
|
|
132
145
|
action claim {
|
|
133
|
-
|
|
146
|
+
when_not(claim_amount) {
|
|
147
|
+
agent_description: "Post the whole reservation to the {holder}. This moves money and does not reverse. Only a funded hold claims.";
|
|
148
|
+
moves: [{ key: "claim"; operation: internal_transfer.post; bind: { transferId: { from: instance; path: refs.holdTransferId; }; }; }];
|
|
149
|
+
}
|
|
134
150
|
deadline: { field: deadline_field; };
|
|
135
151
|
when(claim_capture) { capture_input: claim_capture; }
|
|
136
152
|
when(claim_amount) {
|
|
153
|
+
agent_description: "Post the {holder}'s decided amount out of the reservation and void the remainder back to the {payer} in one linked group. This moves money and does not reverse. Only a funded hold claims, and the claimed amount cannot exceed the held {amount}.";
|
|
137
154
|
decided_amount: { field: claim_field; bound_field: claim_bound; remainder_action: claim_remainder; };
|
|
155
|
+
sandbox_failure_point: "release";
|
|
156
|
+
moves: [{ key: "claim"; operation: internal_transfer.post; bind: { amount: { from: input; path: claim_field; }; currency: { from: instance; path: fields.currency; }; postMode: { from: const; value: partial_only; }; transferId: { from: instance; path: refs.holdTransferId; }; }; }, { key: remainder; operation: internal_transfer.void; bind: { reason: { from: const; value: "Return unclaimed deposit remainder"; }; transferId: { from: instance; path: refs.holdTransferId; }; }; }];
|
|
138
157
|
}
|
|
139
158
|
when(claim_input) { input: claim_input; }
|
|
140
|
-
when(
|
|
141
|
-
|
|
159
|
+
when(claim_allowed) { port { allowed_parties: claim_allowed; }; }
|
|
160
|
+
when_not(claim_allowed) {
|
|
161
|
+
when(claim_to) { port { allowed_parties: [claim_to]; }; }
|
|
162
|
+
}
|
|
142
163
|
steps: [];
|
|
143
164
|
summary: "Claim the security deposit";
|
|
144
165
|
}
|
|
145
166
|
action return {
|
|
146
167
|
agent_description: "Void the whole reservation so the {payer} gets every unit back. Use this when the {holder} decides to keep nothing. This moves money and does not reverse. Only a funded hold returns.";
|
|
147
168
|
deadline: { field: deadline_field; };
|
|
148
|
-
when(
|
|
169
|
+
when(return_allowed) { port { allowed_parties: return_allowed; }; }
|
|
170
|
+
when_not(return_allowed) {
|
|
171
|
+
when(return_to) { port { allowed_parties: [return_to]; }; }
|
|
172
|
+
}
|
|
149
173
|
moves: [{ key: "return"; operation: internal_transfer.void; bind: { reason: { from: const; value: "Deposit returned in full"; }; transferId: { from: instance; path: refs.holdTransferId; }; }; }];
|
|
150
174
|
steps: [];
|
|
151
175
|
summary: "Return the security deposit";
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
module std.
|
|
1
|
+
module std.money_flows.settlement_batch
|
|
2
2
|
|
|
3
3
|
export instrument settlement_batch<C>(
|
|
4
4
|
settlement_account: party,
|
|
@@ -15,8 +15,8 @@ export instrument settlement_batch<C>(
|
|
|
15
15
|
close_trigger { type: date; description: "Date the open batch freezes against later entries"; }
|
|
16
16
|
currency { type: text; description: "ISO 4217 currency code"; minLength: 3; maxLength: 3; pattern: "^[A-Z]{3}$"; }
|
|
17
17
|
payout_beneficiary_ref { type: text; description: "Beneficiary ID for the payout instruction"; pattern: "^ben_(sandbox|live)_[a-z0-9]{8,64}$"; }
|
|
18
|
-
[payout_destination]AccountId { type: account<C>; description: concat("The ", words(payout_destination), " account");
|
|
19
|
-
[settlement_account]AccountId { type: account<C>; description: concat("The ", words(settlement_account), " account");
|
|
18
|
+
[payout_destination]AccountId { type: account<C>; description: concat("The ", words(payout_destination), " account"); "x-hyperscale-reference-filter": { column: role; values: [customer_balance]; }; }
|
|
19
|
+
[settlement_account]AccountId { type: account<C>; description: concat("The ", words(settlement_account), " account"); "x-hyperscale-reference-filter": { column: role; values: [customer_balance]; }; }
|
|
20
20
|
}
|
|
21
21
|
lifecycle {
|
|
22
22
|
states open closed calculated approved instructed acknowledged reconciled;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
module std.
|
|
1
|
+
module std.money_flows.swap;
|
|
2
2
|
export instrument swap<C>(between: list<party>, amounts: block, fees: block, release: condition, dispute: condition, side_names: optional<block>, lifecycle_state_order: optional<list<text>>, action_bindings: optional<block>, parked_states: optional<block>, fixed_prefix: optional<text>) {
|
|
3
3
|
let(side_a): at(between, 1);
|
|
4
4
|
let(side_b): at(between, 2);
|
|
@@ -29,8 +29,8 @@ export instrument swap<C>(between: list<party>, amounts: block, fees: block, rel
|
|
|
29
29
|
distinct_parties: true;
|
|
30
30
|
when(side_names) {
|
|
31
31
|
parties {
|
|
32
|
-
payer: side_a_account;
|
|
33
|
-
beneficiary: side_b_account;
|
|
32
|
+
payer: { party: side_a; account: side_a_account; };
|
|
33
|
+
beneficiary: { party: side_b; account: side_b_account; };
|
|
34
34
|
}
|
|
35
35
|
}
|
|
36
36
|
when_not(side_names) {
|
|
@@ -82,7 +82,6 @@ export instrument swap<C>(between: list<party>, amounts: block, fees: block, rel
|
|
|
82
82
|
"[side_a_account]" {
|
|
83
83
|
type: account<C>;
|
|
84
84
|
description: "First trade party and funder";
|
|
85
|
-
pattern: "^acct_(sandbox|live)_[a-z0-9]{8,64}$";
|
|
86
85
|
"x-hyperscale-reference-filter" {
|
|
87
86
|
column: role;
|
|
88
87
|
values: [customer_balance];
|
|
@@ -99,7 +98,6 @@ export instrument swap<C>(between: list<party>, amounts: block, fees: block, rel
|
|
|
99
98
|
"[side_b_account]" {
|
|
100
99
|
type: account<C>;
|
|
101
100
|
description: "Second trade party and funder";
|
|
102
|
-
pattern: "^acct_(sandbox|live)_[a-z0-9]{8,64}$";
|
|
103
101
|
"x-hyperscale-reference-filter" {
|
|
104
102
|
column: role;
|
|
105
103
|
values: [customer_balance];
|
|
@@ -144,7 +142,6 @@ export instrument swap<C>(between: list<party>, amounts: block, fees: block, rel
|
|
|
144
142
|
when_not(side_names) {
|
|
145
143
|
description: "The product fee collection account";
|
|
146
144
|
}
|
|
147
|
-
pattern: "^acct_(sandbox|live)_[a-z0-9]{8,64}$";
|
|
148
145
|
"x-hyperscale-fee-collection-port": true;
|
|
149
146
|
"x-hyperscale-reference-filter" {
|
|
150
147
|
column: role;
|
|
@@ -240,15 +237,28 @@ export instrument swap<C>(between: list<party>, amounts: block, fees: block, rel
|
|
|
240
237
|
}];
|
|
241
238
|
}
|
|
242
239
|
action dispute {
|
|
243
|
-
agent_description: "Claw back a released trade inside its dispute window. Both cross-payment reservations void and both principals return from escrow in one batch. The trade must be released and the clawback moment must not have passed.
|
|
240
|
+
agent_description: "Claw back a released trade inside its dispute window. Both cross-payment reservations void and both principals return from escrow in one batch. The trade must be released and the clawback moment must not have passed. The dispute port's declared parties may call it.";
|
|
244
241
|
summary: "Void both reservations, then refund both principals atomically";
|
|
245
242
|
public_action: concat("dispute", title(camel(instrument)));
|
|
246
243
|
deadline {
|
|
247
244
|
field: clawbackAt;
|
|
248
245
|
}
|
|
249
|
-
|
|
250
|
-
|
|
246
|
+
when(dispute_fields) {
|
|
247
|
+
input {
|
|
248
|
+
type: object;
|
|
249
|
+
additional_properties: false;
|
|
250
|
+
properties {
|
|
251
|
+
for input_name in keys(dispute_fields) {
|
|
252
|
+
[input_name]: get(dispute_fields, input_name);
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
required: keys(dispute_fields);
|
|
256
|
+
}
|
|
257
|
+
capture_input: {
|
|
258
|
+
for item in keys(dispute_fields) { [item]: item; }
|
|
259
|
+
};
|
|
251
260
|
}
|
|
261
|
+
port { allowedParties: dispute_allowed; }
|
|
252
262
|
moves: [{
|
|
253
263
|
bind {
|
|
254
264
|
reason {
|
|
@@ -370,6 +380,7 @@ export instrument swap<C>(between: list<party>, amounts: block, fees: block, rel
|
|
|
370
380
|
agent_description: "Fund both sides at once. Each side pays its principal into escrow and its service fee to the platform account, four transfers in one batch. The trade must be created and unfunded. This moves real money from both parties.";
|
|
371
381
|
summary: "Fund both trade sides and collect on-top fees atomically";
|
|
372
382
|
public_action: concat("fund", title(camel(instrument)));
|
|
383
|
+
sandbox_failure_point: "funding";
|
|
373
384
|
moves: [{
|
|
374
385
|
amount: concat(side_a_amount);
|
|
375
386
|
from: side_a;
|
|
@@ -420,12 +431,13 @@ export instrument swap<C>(between: list<party>, amounts: block, fees: block, rel
|
|
|
420
431
|
steps: [];
|
|
421
432
|
}
|
|
422
433
|
action release {
|
|
423
|
-
agent_description: "Reserve each side's principal for the other side and start the dispute window. The trade must be funded. Money is reserved, not settled. It posts on its own when the window matures, and dispute unwinds it before then.
|
|
434
|
+
agent_description: "Reserve each side's principal for the other side and start the dispute window. The trade must be funded. Money is reserved, not settled. It posts on its own when the window matures, and dispute unwinds it before then. The release port's declared parties may call it.";
|
|
424
435
|
summary: "Reserve both cross-payments for the whole-trade clawback window";
|
|
425
436
|
public_action: concat("release", title(camel(instrument)));
|
|
426
437
|
port {
|
|
427
|
-
allowedParties:
|
|
438
|
+
allowedParties: release_allowed;
|
|
428
439
|
}
|
|
440
|
+
sandbox_failure_point: "release";
|
|
429
441
|
sets_at {
|
|
430
442
|
field: clawbackAt;
|
|
431
443
|
offset: dispute_within;
|
|
@@ -753,12 +765,12 @@ export instrument swap<C>(between: list<party>, amounts: block, fees: block, rel
|
|
|
753
765
|
steps: [];
|
|
754
766
|
}
|
|
755
767
|
action release {
|
|
756
|
-
agent_description: "Reserve each side's principal for the other side and start the dispute window. The trade must be funded. Money is reserved, not settled. It posts on its own when the window matures, and dispute unwinds it before then.
|
|
768
|
+
agent_description: "Reserve each side's principal for the other side and start the dispute window. The trade must be funded. Money is reserved, not settled. It posts on its own when the window matures, and dispute unwinds it before then. The release port's declared parties may call it.";
|
|
757
769
|
summary: "Reserve both cross-payments for the whole-trade clawback window";
|
|
758
770
|
public_action: concat("release", title(camel(instrument)));
|
|
759
771
|
event_name: concat(event_prefix, ".released");
|
|
760
772
|
port {
|
|
761
|
-
allowedParties:
|
|
773
|
+
allowedParties: release_allowed;
|
|
762
774
|
}
|
|
763
775
|
sandbox_failure_point: "release";
|
|
764
776
|
sets_at {
|
|
@@ -884,16 +896,29 @@ export instrument swap<C>(between: list<party>, amounts: block, fees: block, rel
|
|
|
884
896
|
steps: [];
|
|
885
897
|
}
|
|
886
898
|
action dispute {
|
|
887
|
-
agent_description: "Claw back a released trade inside its dispute window. Both cross-payment reservations void and both principals return from escrow in one batch. The trade must be released and the clawback moment must not have passed.
|
|
899
|
+
agent_description: "Claw back a released trade inside its dispute window. Both cross-payment reservations void and both principals return from escrow in one batch. The trade must be released and the clawback moment must not have passed. The dispute port's declared parties may call it.";
|
|
888
900
|
summary: "Void both reservations, then refund both principals atomically";
|
|
889
901
|
public_action: concat("dispute", title(camel(instrument)));
|
|
890
902
|
event_name: concat(event_prefix, ".clawed_back");
|
|
891
903
|
deadline {
|
|
892
904
|
field: clawbackAt;
|
|
893
905
|
}
|
|
894
|
-
|
|
895
|
-
|
|
906
|
+
when(dispute_fields) {
|
|
907
|
+
input {
|
|
908
|
+
type: object;
|
|
909
|
+
additional_properties: false;
|
|
910
|
+
properties {
|
|
911
|
+
for input_name in keys(dispute_fields) {
|
|
912
|
+
[input_name]: get(dispute_fields, input_name);
|
|
913
|
+
}
|
|
914
|
+
}
|
|
915
|
+
required: keys(dispute_fields);
|
|
916
|
+
}
|
|
917
|
+
capture_input: {
|
|
918
|
+
for item in keys(dispute_fields) { [item]: item; }
|
|
919
|
+
};
|
|
896
920
|
}
|
|
921
|
+
port { allowedParties: dispute_allowed; }
|
|
897
922
|
moves: [{
|
|
898
923
|
bind {
|
|
899
924
|
reason {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
module std.
|
|
1
|
+
module std.money_flows.threshold_pool
|
|
2
2
|
|
|
3
3
|
export instrument threshold_pool<C>(
|
|
4
4
|
contributor: optional<party>,
|
|
@@ -29,7 +29,7 @@ export instrument threshold_pool<C>(
|
|
|
29
29
|
agent_description: "Reach for threshold pool when many contributors commit toward one target and nothing is collected unless the pool reaches it by the close date. Commitments sit in escrow until the pool activates or fails. Pick weighted distribution to pay a pool out and instant transfer for a single payment.";
|
|
30
30
|
when_not(contribution_instrument) {
|
|
31
31
|
fields {
|
|
32
|
-
[beneficiary]AccountId { type: account<C>; description: concat("The ", words(beneficiary), " account");
|
|
32
|
+
[beneficiary]AccountId { type: account<C>; description: concat("The ", words(beneficiary), " account"); "x-hyperscale-reference-filter": { column: role; values: [customer_balance]; }; }
|
|
33
33
|
close_by { type: date; description: "Stored close anchor"; }
|
|
34
34
|
currency { type: text; description: "ISO 4217 currency code"; minLength: 3; maxLength: 3; pattern: "^[A-Z]{3}$"; }
|
|
35
35
|
maxContributors { type: integer; description: concat("Exactly ", max_contributors, " admitted contributors"); const: max_contributors; }
|
|
@@ -90,9 +90,9 @@ export instrument threshold_pool<C>(
|
|
|
90
90
|
generatedPrefix: true;
|
|
91
91
|
fields {
|
|
92
92
|
amount { type: money<C>; description: "One whole commitment amount"; }
|
|
93
|
-
[beneficiary]AccountId { type: account<C>; description: concat("The ", words(beneficiary), " account");
|
|
93
|
+
[beneficiary]AccountId { type: account<C>; description: concat("The ", words(beneficiary), " account"); "x-hyperscale-reference-filter": { column: role; values: [customer_balance]; }; }
|
|
94
94
|
[parent_name]Id { type: ref<parent_name>; description: concat("The exact ", parent_name); pattern: concat("^", prefix(parent_name), "_(sandbox|live)_[a-z0-9]{8,64}$"); }
|
|
95
|
-
[contributor]AccountId { type: account<C>; description: concat("The ", words(contributor), " account");
|
|
95
|
+
[contributor]AccountId { type: account<C>; description: concat("The ", words(contributor), " account"); "x-hyperscale-reference-filter": { column: role; values: [customer_balance]; }; }
|
|
96
96
|
currency { type: text; description: "ISO 4217 currency code"; minLength: 3; maxLength: 3; pattern: "^[A-Z]{3}$"; }
|
|
97
97
|
}
|
|
98
98
|
lifecycle {
|
|
@@ -168,7 +168,7 @@ export instrument threshold_pool<C>(
|
|
|
168
168
|
let(close_field): camel(close_by);
|
|
169
169
|
|
|
170
170
|
fields {
|
|
171
|
-
[beneficiary_account_field] { type: account<C>; description: beneficiary_account_description;
|
|
171
|
+
[beneficiary_account_field] { type: account<C>; description: beneficiary_account_description; "x-hyperscale-reference-filter": { column: role; values: [customer_balance]; }; }
|
|
172
172
|
[close_field] { type: date; }
|
|
173
173
|
currency { type: text; description: currency_description; maxLength: 3; minLength: 3; pattern: "^[A-Z]{3}$"; }
|
|
174
174
|
when(memo) { [memo] { type: text; optional: true; maxLength: 180; minLength: 1; } }
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
module std.
|
|
1
|
+
module std.money_flows.weighted_distribution
|
|
2
2
|
|
|
3
3
|
export instrument weighted_distribution<C>(
|
|
4
4
|
source: party,
|
|
@@ -18,7 +18,7 @@ export instrument weighted_distribution<C>(
|
|
|
18
18
|
fields {
|
|
19
19
|
currency { type: text; description: "ISO 4217 currency code"; minLength: 3; maxLength: 3; pattern: "^[A-Z]{3}$"; }
|
|
20
20
|
amount { type: money<C>; description: "Distribution pool in {C} minor units"; }
|
|
21
|
-
[source]AccountId { type: account<C>; description: concat("The ", words(source), " account");
|
|
21
|
+
[source]AccountId { type: account<C>; description: concat("The ", words(source), " account"); "x-hyperscale-reference-filter": { column: role; values: [customer_balance]; }; }
|
|
22
22
|
maxRecipients { type: integer; description: concat("Exactly ", max_recipients, " frozen entitlement rows"); const: max_recipients; }
|
|
23
23
|
record_at { type: date; description: "Stored record date"; }
|
|
24
24
|
}
|
|
@@ -48,10 +48,10 @@ export instrument weighted_distribution<C>(
|
|
|
48
48
|
generatedPrefix: true;
|
|
49
49
|
fields {
|
|
50
50
|
currency { type: text; description: "ISO 4217 currency code"; minLength: 3; maxLength: 3; pattern: "^[A-Z]{3}$"; }
|
|
51
|
-
[source]AccountId { type: account<C>; description: concat("The ", words(source), " account");
|
|
51
|
+
[source]AccountId { type: account<C>; description: concat("The ", words(source), " account"); "x-hyperscale-reference-filter": { column: role; values: [customer_balance]; }; }
|
|
52
52
|
[weight] { type: money<C>; description: "Stored non-negative entitlement weight"; }
|
|
53
53
|
[parent_name]Id { type: ref<parent_name>; description: concat("The exact ", parent_name); pattern: concat("^", prefix(parent_name), "_(sandbox|live)_[a-z0-9]{8,64}$"); }
|
|
54
|
-
[recipient]AccountId { type: account<C>; description: concat("The ", words(recipient), " account");
|
|
54
|
+
[recipient]AccountId { type: account<C>; description: concat("The ", words(recipient), " account"); "x-hyperscale-reference-filter": { column: role; values: [customer_balance]; }; }
|
|
55
55
|
}
|
|
56
56
|
lifecycle { states recorded paid; initial recorded; on payout: recorded -> paid; }
|
|
57
57
|
parties { beneficiary: concat(camel(recipient), "AccountId"); payer: concat(camel(source), "AccountId"); }
|
|
@@ -106,8 +106,8 @@ export instrument weighted_distribution<C>(
|
|
|
106
106
|
currency { type: text; description: "ISO 4217 currency code"; minLength: 3; maxLength: 3; pattern: "^[A-Z]{3}$"; }
|
|
107
107
|
[weight_ref] { type: weight_ref; description: get(weight_source, "description"); pattern: get(weight_source, "pattern"); }
|
|
108
108
|
[group_ref] { type: group_ref; description: get(group, "description"); pattern: get(group, "pattern"); }
|
|
109
|
-
[recipient]AccountId { type: account<C>; description: get(flat, "recipient_account_description");
|
|
110
|
-
[source]AccountId { type: account<C>; description: get(flat, "source_account_description");
|
|
109
|
+
[recipient]AccountId { type: account<C>; description: get(flat, "recipient_account_description"); "x-hyperscale-reference-filter": { column: role; values: [customer_balance]; }; }
|
|
110
|
+
[source]AccountId { type: account<C>; description: get(flat, "source_account_description"); "x-hyperscale-reference-filter": { column: role; values: [customer_balance]; }; }
|
|
111
111
|
}
|
|
112
112
|
lifecycle { states claimed paid; initial claimed; on payout: claimed -> paid; }
|
|
113
113
|
parties { beneficiary: recipient_account_field; }
|
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
program juniper_forge_contract "Juniper Forge contract"
|
|
2
|
-
import { instant_transfer, scheduled } from "std/settlements"
|
|
3
|
-
|
|
4
|
-
party samira_nassar: person
|
|
5
|
-
party juniper_forge_interiors: business
|
|
6
|
-
|
|
7
|
-
settlement concept_fee = instant_transfer {
|
|
8
|
-
payer: samira_nassar
|
|
9
|
-
payee: juniper_forge_interiors
|
|
10
|
-
amount: conceptFee: money(SAR)
|
|
11
|
-
fees { samira_nassar: 1% }
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
settlement build_installments = scheduled {
|
|
15
|
-
payer: samira_nassar
|
|
16
|
-
payee: juniper_forge_interiors
|
|
17
|
-
amount: buildPrice: money(SAR)
|
|
18
|
-
count: 3
|
|
19
|
-
every: P30D
|
|
20
|
-
first_due: firstBuildPaymentAt
|
|
21
|
-
}
|
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
# Two-instrument reading session, 2026-09-02
|
|
2
|
-
|
|
3
|
-
The reader worked only inside the HSX public export. It read the README, skill,
|
|
4
|
-
guide, grammar, types, and generated standard-library pages.
|
|
5
|
-
|
|
6
|
-
## First run
|
|
7
|
-
|
|
8
|
-
Attempts: 3. Result: environment refusal before language checking.
|
|
9
|
-
|
|
10
|
-
```text
|
|
11
|
-
$ hsx check reading-test.hsx
|
|
12
|
-
zsh: command not found: hsx
|
|
13
|
-
exit 127
|
|
14
|
-
|
|
15
|
-
$ npm exec --offline --package=. -- hsx check reading-test.hsx
|
|
16
|
-
sh: hsx: command not found
|
|
17
|
-
exit 127
|
|
18
|
-
|
|
19
|
-
$ bun run src/cli.ts check reading-test.hsx
|
|
20
|
-
SyntaxError: Export named 'udlEffectKinds' not found in the cached UDL beta package
|
|
21
|
-
exit 1
|
|
22
|
-
```
|
|
23
|
-
|
|
24
|
-
The public docs did not distinguish the installed command from the source
|
|
25
|
-
checkout command. The provisional pre-publication clone also resolved an old
|
|
26
|
-
UDL package. The README and first-program guide now name the exact checkout
|
|
27
|
-
command. The rerun used the local UDL rc.1 package already proved by the
|
|
28
|
-
exporter.
|
|
29
|
-
|
|
30
|
-
## Rerun after the docs repair
|
|
31
|
-
|
|
32
|
-
Attempts: 1. Result: accepted with no diagnostics.
|
|
33
|
-
|
|
34
|
-
```text
|
|
35
|
-
$ bun run bin/hsx.ts check reading-test.hsx
|
|
36
|
-
[no diagnostics]
|
|
37
|
-
exit 0
|
|
38
|
-
```
|
|
39
|
-
|
|
40
|
-
The accepted program is in
|
|
41
|
-
[`2026-09-02-two-instruments.hsx`](./2026-09-02-two-instruments.hsx).
|