@hyperscale0/hsx 5.4.2 → 5.6.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 +12 -0
- package/dist/src/compile.d.ts +5 -0
- package/dist/src/compile.d.ts.map +1 -1
- package/dist/src/compile.js +105 -4
- package/dist/src/compile.js.map +1 -1
- package/dist/src/parse.js +2 -0
- package/dist/src/parse.js.map +1 -1
- package/dist/src/std-bundle.js +10 -10
- package/dist/src/std-bundle.js.map +1 -1
- package/dist/src/version.d.ts +1 -1
- package/dist/src/version.js +1 -1
- package/docs/README.md +40 -0
- package/package.json +4 -4
- package/src/compile.ts +160 -0
- package/src/parse.ts +1 -0
- package/src/std-bundle.ts +10 -10
- package/src/version.ts +1 -1
- package/std/collections.hsx +4 -1
- package/std/escrow.hsx +7 -4
- package/std/financing.hsx +49 -44
- package/std/insurance.hsx +7 -3
- package/std/lending.hsx +11 -7
- package/std/marketplace.hsx +10 -7
- package/std/money.hsx +10 -6
- package/std/savings.hsx +4 -2
- package/std/travel.hsx +24 -20
- package/std/wallet.hsx +5 -2
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"std-bundle.js","sourceRoot":"","sources":["../../src/std-bundle.ts"],"names":[],"mappings":"AAAA,oEAAoE;AAEpE,MAAM,CAAC,MAAM,iBAAiB,GAAgC,IAAI,GAAG,CAAiB;IACpF,CAAC,WAAW,EAAE,2oKAA2oK,CAAC;IAC1pK,CAAC,iBAAiB,EAAE
|
|
1
|
+
{"version":3,"file":"std-bundle.js","sourceRoot":"","sources":["../../src/std-bundle.ts"],"names":[],"mappings":"AAAA,oEAAoE;AAEpE,MAAM,CAAC,MAAM,iBAAiB,GAAgC,IAAI,GAAG,CAAiB;IACpF,CAAC,WAAW,EAAE,2oKAA2oK,CAAC;IAC1pK,CAAC,iBAAiB,EAAE,2sNAA2sN,CAAC;IAChuN,CAAC,YAAY,EAAE,+qHAA+qH,CAAC;IAC/rH,CAAC,eAAe,EAAE,gq9DAAgq9D,CAAC;IACnr9D,CAAC,eAAe,EAAE,01KAA01K,CAAC;IAC72K,CAAC,aAAa,EAAE,qwTAAqwT,CAAC;IACtxT,CAAC,iBAAiB,EAAE,s+TAAs+T,CAAC;IAC3/T,CAAC,WAAW,EAAE,u1VAAu1V,CAAC;IACt2V,CAAC,eAAe,EAAE,649CAA649C,CAAC;IACh69C,CAAC,aAAa,EAAE,85JAA85J,CAAC;IAC/6J,CAAC,YAAY,EAAE,o7SAAo7S,CAAC;IACp8S,CAAC,YAAY,EAAE,2jGAA2jG,CAAC;CAC5kG,CAAC,CAAC"}
|
package/dist/src/version.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export declare const HSX_VERSION = "5.
|
|
1
|
+
export declare const HSX_VERSION = "5.6.0";
|
|
2
2
|
//# sourceMappingURL=version.d.ts.map
|
package/dist/src/version.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export const HSX_VERSION = "5.
|
|
1
|
+
export const HSX_VERSION = "5.6.0";
|
|
2
2
|
//# sourceMappingURL=version.js.map
|
package/docs/README.md
CHANGED
|
@@ -246,6 +246,13 @@ maxAge 1d` requires a recent completed provider check.
|
|
|
246
246
|
only to reservations. Fees settle with create moves, never reservations. Repeated clauses keep
|
|
247
247
|
their declaration order. The JSON-like clause form remains accepted and lowers
|
|
248
248
|
to the same [UDL clauses](https://github.com/hyperscale0/hyperscale-udl/blob/main/spec/README.md).
|
|
249
|
+
Use `economics { purpose: earning, sourceParty: merchant }` on a move to
|
|
250
|
+
classify posted money. Other purposes are `principal`, `participant_payout`,
|
|
251
|
+
`internal`, `prepaid_credit`, and `pass_through`. `reversalOf: self.originalTransfer` links a
|
|
252
|
+
reversal. The source party must own the source account, except when an earning
|
|
253
|
+
releases the retained payer’s money from an agreement-bound instrument account
|
|
254
|
+
to a company account outside the agreement. A reservation passes its economics
|
|
255
|
+
to its post. Fee shorthand accepts separate economics for each expanded leg.
|
|
249
256
|
They cannot add kernel instructions. `at(list, position)` reads a dated list;
|
|
250
257
|
`aggregate(selection, "amount")` sums selected money; `ratio(amount, weight, total)`
|
|
251
258
|
floors a weighted share. `records` declares child types. `invoke` can create a child
|
|
@@ -433,3 +440,36 @@ after the member receives the pot; paying a contribution does not advance their
|
|
|
433
440
|
payout seat. Late contributions remain eligible while the membership is
|
|
434
441
|
`active` or `received` and the circle is `active`. These guards do not promise
|
|
435
442
|
scheduler retries or permit a payout larger than the available cash.
|
|
443
|
+
|
|
444
|
+
## Posted economics in the money flows
|
|
445
|
+
|
|
446
|
+
Held customer funding and its unspent return are `principal`. A release for the
|
|
447
|
+
company's sale is `earning`. A payment from company cash to another participant
|
|
448
|
+
is `participant_payout`. Claims, waivers, write-offs and own-account allocations
|
|
449
|
+
are `internal`; prepaid balance topups and returns are `prepaid_credit`. Tax is
|
|
450
|
+
`pass_through`, excluded from earnings and costs. Unpaid claims count as neither.
|
|
451
|
+
Refunds of paid profit, company charges and commission capture the original
|
|
452
|
+
transfer and use `reversalOf`, so refunds reduce the original purpose.
|
|
453
|
+
|
|
454
|
+
Fee shorthand accepts separate move economics: `economics { payee: { purpose:
|
|
455
|
+
earning, sourceParty: payer }, fee: { purpose: earning, sourceParty: payer },
|
|
456
|
+
tax: { purpose: pass_through, sourceParty: payer } }`. These describe authored
|
|
457
|
+
product fees. Automatic platform fees keep their commercial classification.
|
|
458
|
+
|
|
459
|
+
Any economics block can select by a resolved party: `economics { recipient:
|
|
460
|
+
recipient, company: { purpose: earning, sourceParty: payer }, participant:
|
|
461
|
+
{ purpose: participant_payout, sourceParty: programOperator } }`. The compiler
|
|
462
|
+
chooses `company` for `operator`, `programOperator`, or a declared party with the
|
|
463
|
+
`program_operator` role; it chooses `participant` for other bound parties.
|
|
464
|
+
Both branches must be supplied. A branch may be `unclassified` when no purpose
|
|
465
|
+
is established. Outside financing-profit and recovery recipients refund directly
|
|
466
|
+
to the customer, not the company that funded the payout; those refund branches
|
|
467
|
+
remain unclassified because they cannot reverse that company payout. Std
|
|
468
|
+
recovery charges use this rule to avoid counting company receipts as participant
|
|
469
|
+
costs. Direct customer payments to
|
|
470
|
+
outside recipients are pass-through; payments from held company cash are costs.
|
|
471
|
+
|
|
472
|
+
Generic transfers and mixed principal/profit distributions remain unclassified
|
|
473
|
+
when their structure does not establish a purpose. Adapter-owned premium and
|
|
474
|
+
claim accounts and credit-line advances also lack an authored source party.
|
|
475
|
+
Their reports remain incomplete rather than guessing a company earning or cost.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hyperscale0/hsx",
|
|
3
|
-
"version": "5.
|
|
3
|
+
"version": "5.6.0",
|
|
4
4
|
"description": "The strictly typed HSX language: compile total financial programs into canonical UDL.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"hsx",
|
|
@@ -85,8 +85,8 @@
|
|
|
85
85
|
"examples:bundle": "bun scripts/bundle-examples.ts"
|
|
86
86
|
},
|
|
87
87
|
"dependencies": {
|
|
88
|
-
"@hyperscale0/adl": "1.0.0-beta.
|
|
89
|
-
"@hyperscale0/udl": "4.
|
|
88
|
+
"@hyperscale0/adl": "1.0.0-beta.10",
|
|
89
|
+
"@hyperscale0/udl": "4.8.0",
|
|
90
90
|
"fast-sha256": "1.3.0"
|
|
91
91
|
},
|
|
92
92
|
"devDependencies": {
|
|
@@ -98,5 +98,5 @@
|
|
|
98
98
|
"Amir Ayub",
|
|
99
99
|
"Sara AlBakaawi"
|
|
100
100
|
],
|
|
101
|
-
"gitHead": "
|
|
101
|
+
"gitHead": "be567dd18eb45ea3e02adc1f33b8491aa05df135"
|
|
102
102
|
}
|
package/src/compile.ts
CHANGED
|
@@ -56,6 +56,7 @@ export interface CompileDiagnostic extends Diagnostic {
|
|
|
56
56
|
export interface CompileOriginMapEntry {
|
|
57
57
|
path: string;
|
|
58
58
|
span: Span & { line: number; column: number };
|
|
59
|
+
standardBlock?: { key: string; recordPath: string; headerDigest: string };
|
|
59
60
|
}
|
|
60
61
|
export interface AdapterBindingTarget {
|
|
61
62
|
adapter: ProviderAdapter;
|
|
@@ -428,6 +429,10 @@ export function compile(
|
|
|
428
429
|
);
|
|
429
430
|
const templates = new Map<string, InstrumentDecl>();
|
|
430
431
|
const declarationSources = new Map<InstrumentDecl, string>();
|
|
432
|
+
const standardOrigins = new Map<
|
|
433
|
+
InstrumentDecl,
|
|
434
|
+
NonNullable<CompileOriginMapEntry["standardBlock"]>
|
|
435
|
+
>();
|
|
431
436
|
const requirementOrigins = new Map<
|
|
432
437
|
UdlSubjectRequirement,
|
|
433
438
|
{ source: string; span: Span; message: string }
|
|
@@ -447,6 +452,13 @@ export function compile(
|
|
|
447
452
|
if (!content)
|
|
448
453
|
fail(use, `unknown header ${use.name}`, "choose a published header");
|
|
449
454
|
sources.set(use.name, content);
|
|
455
|
+
const bundled = bundledStandardLibrary.source(use.name);
|
|
456
|
+
const headerDigest =
|
|
457
|
+
bundled === content
|
|
458
|
+
? Array.from(sha256(new TextEncoder().encode(content)), (byte) =>
|
|
459
|
+
byte.toString(16).padStart(2, "0"),
|
|
460
|
+
).join("")
|
|
461
|
+
: undefined;
|
|
450
462
|
let header;
|
|
451
463
|
try {
|
|
452
464
|
header = parseHeader(content, use.name);
|
|
@@ -475,6 +487,14 @@ export function compile(
|
|
|
475
487
|
);
|
|
476
488
|
templates.set(prefix, parentDecl);
|
|
477
489
|
declarationSources.set(parentDecl, use.name);
|
|
490
|
+
if (headerDigest) {
|
|
491
|
+
const [, root, ...record] = prefix.split(".");
|
|
492
|
+
standardOrigins.set(parentDecl, {
|
|
493
|
+
key: `${use.name}.${root}`,
|
|
494
|
+
recordPath: record.join("."),
|
|
495
|
+
headerDigest,
|
|
496
|
+
});
|
|
497
|
+
}
|
|
478
498
|
const recs = entries(asBlock(entries(parentDecl.body).get("records")));
|
|
479
499
|
for (const [recName, recBlock] of recs) {
|
|
480
500
|
const recDecl: InstrumentDecl = {
|
|
@@ -663,6 +683,7 @@ export function compile(
|
|
|
663
683
|
exportPath: string;
|
|
664
684
|
revision?: number | undefined;
|
|
665
685
|
},
|
|
686
|
+
standardOrigin?: NonNullable<CompileOriginMapEntry["standardBlock"]>,
|
|
666
687
|
) => {
|
|
667
688
|
const resolveFamilyInstruments = (
|
|
668
689
|
family: UdlFamily,
|
|
@@ -2323,6 +2344,125 @@ export function compile(
|
|
|
2323
2344
|
const key = parts.has("key")
|
|
2324
2345
|
? String(data(parts.get("key")!))
|
|
2325
2346
|
: `move${index + 1}`;
|
|
2347
|
+
const lowerEconomics = (
|
|
2348
|
+
economicsExpr: Expr | undefined,
|
|
2349
|
+
): UdlAction["moves"][number]["economics"] => {
|
|
2350
|
+
if (economicsExpr) {
|
|
2351
|
+
const resolved = resolve(economicsExpr);
|
|
2352
|
+
if (
|
|
2353
|
+
resolved.kind === "name" &&
|
|
2354
|
+
resolved.value === "unclassified"
|
|
2355
|
+
)
|
|
2356
|
+
return undefined;
|
|
2357
|
+
const choices = entries(asBlock(resolve(economicsExpr)));
|
|
2358
|
+
if (choices.has("recipient")) {
|
|
2359
|
+
for (const term of choices.keys())
|
|
2360
|
+
if (
|
|
2361
|
+
!["recipient", "company", "participant"].includes(term)
|
|
2362
|
+
)
|
|
2363
|
+
fail(
|
|
2364
|
+
economicsExpr,
|
|
2365
|
+
`unknown economics choice ${term}`,
|
|
2366
|
+
"use recipient, company and participant",
|
|
2367
|
+
);
|
|
2368
|
+
const recipient = String(data(choices.get("recipient")!));
|
|
2369
|
+
if (
|
|
2370
|
+
!isParty(recipient) ||
|
|
2371
|
+
!choices.has("company") ||
|
|
2372
|
+
!choices.has("participant")
|
|
2373
|
+
)
|
|
2374
|
+
fail(
|
|
2375
|
+
economicsExpr,
|
|
2376
|
+
"economics choice needs a bound recipient and both branches",
|
|
2377
|
+
"declare recipient, company and participant",
|
|
2378
|
+
);
|
|
2379
|
+
const company =
|
|
2380
|
+
recipient === "operator" ||
|
|
2381
|
+
recipient === "programOperator" ||
|
|
2382
|
+
document.parties[recipient]?.role === "program_operator";
|
|
2383
|
+
return lowerEconomics(
|
|
2384
|
+
choices.get(company ? "company" : "participant"),
|
|
2385
|
+
);
|
|
2386
|
+
}
|
|
2387
|
+
}
|
|
2388
|
+
const economicsParts = economicsExpr
|
|
2389
|
+
? entries(asBlock(resolve(economicsExpr)))
|
|
2390
|
+
: undefined;
|
|
2391
|
+
if (economicsParts) {
|
|
2392
|
+
for (const term of economicsParts.keys())
|
|
2393
|
+
if (
|
|
2394
|
+
!["purpose", "sourceParty", "reversalOf"].includes(term)
|
|
2395
|
+
)
|
|
2396
|
+
fail(
|
|
2397
|
+
economicsExpr!,
|
|
2398
|
+
`unknown economics term ${term}`,
|
|
2399
|
+
"use purpose, sourceParty or reversalOf",
|
|
2400
|
+
);
|
|
2401
|
+
}
|
|
2402
|
+
const purpose = economicsParts?.get("purpose");
|
|
2403
|
+
const sourceParty = economicsParts?.get("sourceParty");
|
|
2404
|
+
if (economicsParts && (!purpose || !sourceParty))
|
|
2405
|
+
fail(
|
|
2406
|
+
economicsExpr!,
|
|
2407
|
+
"economics needs purpose and sourceParty",
|
|
2408
|
+
"declare both economics fields",
|
|
2409
|
+
);
|
|
2410
|
+
const purposeName = purpose ? String(data(purpose)) : undefined;
|
|
2411
|
+
if (
|
|
2412
|
+
purposeName &&
|
|
2413
|
+
![
|
|
2414
|
+
"earning",
|
|
2415
|
+
"principal",
|
|
2416
|
+
"participant_payout",
|
|
2417
|
+
"internal",
|
|
2418
|
+
"prepaid_credit",
|
|
2419
|
+
"pass_through",
|
|
2420
|
+
].includes(purposeName)
|
|
2421
|
+
)
|
|
2422
|
+
fail(
|
|
2423
|
+
purpose!,
|
|
2424
|
+
`unknown economic purpose ${purposeName}`,
|
|
2425
|
+
"choose a declared economic purpose",
|
|
2426
|
+
);
|
|
2427
|
+
const sourcePartyName = sourceParty
|
|
2428
|
+
? String(data(sourceParty))
|
|
2429
|
+
: undefined;
|
|
2430
|
+
if (sourcePartyName && !isParty(sourcePartyName))
|
|
2431
|
+
fail(
|
|
2432
|
+
sourceParty!,
|
|
2433
|
+
`unknown source party ${sourcePartyName}`,
|
|
2434
|
+
"bind an authored party",
|
|
2435
|
+
);
|
|
2436
|
+
return economicsParts
|
|
2437
|
+
? {
|
|
2438
|
+
purpose: purposeName as NonNullable<
|
|
2439
|
+
UdlAction["moves"][number]["economics"]
|
|
2440
|
+
>["purpose"],
|
|
2441
|
+
sourceParty: sourcePartyName!,
|
|
2442
|
+
...(economicsParts.has("reversalOf")
|
|
2443
|
+
? {
|
|
2444
|
+
reversalOf: path(economicsParts.get("reversalOf")!),
|
|
2445
|
+
}
|
|
2446
|
+
: {}),
|
|
2447
|
+
}
|
|
2448
|
+
: undefined;
|
|
2449
|
+
};
|
|
2450
|
+
const economicsExpr = parts.get("economics");
|
|
2451
|
+
const feeEconomics =
|
|
2452
|
+
parts.has("fee") && economicsExpr
|
|
2453
|
+
? entries(asBlock(resolve(economicsExpr)))
|
|
2454
|
+
: undefined;
|
|
2455
|
+
if (feeEconomics)
|
|
2456
|
+
for (const term of feeEconomics.keys())
|
|
2457
|
+
if (!["payee", "fee", "tax"].includes(term))
|
|
2458
|
+
fail(
|
|
2459
|
+
economicsExpr!,
|
|
2460
|
+
`unknown fee economics leg ${term}`,
|
|
2461
|
+
"declare payee, fee or tax economics separately",
|
|
2462
|
+
);
|
|
2463
|
+
const economics = lowerEconomics(
|
|
2464
|
+
feeEconomics ? feeEconomics.get("payee") : economicsExpr,
|
|
2465
|
+
);
|
|
2326
2466
|
if (
|
|
2327
2467
|
op === "internal_transfer.create" ||
|
|
2328
2468
|
op === "internal_transfer.reserve"
|
|
@@ -2418,6 +2558,7 @@ export function compile(
|
|
|
2418
2558
|
a.moves.push({
|
|
2419
2559
|
key: `${key}_${index + 1}`,
|
|
2420
2560
|
operation: "internal_transfer.create",
|
|
2561
|
+
...(economics ? { economics } : {}),
|
|
2421
2562
|
amount: piece,
|
|
2422
2563
|
from: path(from),
|
|
2423
2564
|
to: `party.${recipient.value}`,
|
|
@@ -2440,6 +2581,7 @@ export function compile(
|
|
|
2440
2581
|
const transfer = {
|
|
2441
2582
|
key,
|
|
2442
2583
|
operation: op,
|
|
2584
|
+
...(economics ? { economics } : {}),
|
|
2443
2585
|
...(parts.has("capture")
|
|
2444
2586
|
? { capture: String(data(parts.get("capture")!)) }
|
|
2445
2587
|
: {}),
|
|
@@ -2585,6 +2727,9 @@ export function compile(
|
|
|
2585
2727
|
});
|
|
2586
2728
|
a.moves.push({
|
|
2587
2729
|
key: key + "Fee",
|
|
2730
|
+
...(feeEconomics?.has("fee")
|
|
2731
|
+
? { economics: lowerEconomics(feeEconomics.get("fee")) }
|
|
2732
|
+
: {}),
|
|
2588
2733
|
operation: "internal_transfer.create",
|
|
2589
2734
|
amount: charge,
|
|
2590
2735
|
from: transfer.from,
|
|
@@ -2593,6 +2738,9 @@ export function compile(
|
|
|
2593
2738
|
if (vat)
|
|
2594
2739
|
a.moves.push({
|
|
2595
2740
|
key: key + "Tax",
|
|
2741
|
+
...(feeEconomics?.has("tax")
|
|
2742
|
+
? { economics: lowerEconomics(feeEconomics.get("tax")) }
|
|
2743
|
+
: {}),
|
|
2596
2744
|
operation: "internal_transfer.create",
|
|
2597
2745
|
amount: vat,
|
|
2598
2746
|
from: transfer.from,
|
|
@@ -2606,6 +2754,7 @@ export function compile(
|
|
|
2606
2754
|
a.moves.push({
|
|
2607
2755
|
key,
|
|
2608
2756
|
operation: op,
|
|
2757
|
+
...(economics ? { economics } : {}),
|
|
2609
2758
|
transfer: path(parts.get("transfer")!),
|
|
2610
2759
|
...(parts.has("capture")
|
|
2611
2760
|
? { capture: String(data(parts.get("capture")!)) }
|
|
@@ -2719,6 +2868,7 @@ export function compile(
|
|
|
2719
2868
|
origins.push({
|
|
2720
2869
|
path: `$.instruments[${document.instruments.length}]`,
|
|
2721
2870
|
span: { ...origin, ...lineColAt(source, origin.start) },
|
|
2871
|
+
...(standardOrigin ? { standardBlock: standardOrigin } : {}),
|
|
2722
2872
|
});
|
|
2723
2873
|
if (familyDeclaration && familyDeclaration.revision !== undefined) {
|
|
2724
2874
|
inst.family = {
|
|
@@ -2776,6 +2926,14 @@ export function compile(
|
|
|
2776
2926
|
enums,
|
|
2777
2927
|
childAttachment,
|
|
2778
2928
|
childFamily,
|
|
2929
|
+
standardOrigin
|
|
2930
|
+
? {
|
|
2931
|
+
...standardOrigin,
|
|
2932
|
+
recordPath: [standardOrigin.recordPath, key]
|
|
2933
|
+
.filter(Boolean)
|
|
2934
|
+
.join("."),
|
|
2935
|
+
}
|
|
2936
|
+
: undefined,
|
|
2779
2937
|
);
|
|
2780
2938
|
}
|
|
2781
2939
|
};
|
|
@@ -2907,6 +3065,7 @@ export function compile(
|
|
|
2907
3065
|
attachments,
|
|
2908
3066
|
},
|
|
2909
3067
|
templateFamily ? { ...templateFamily } : undefined,
|
|
3068
|
+
standardOrigins.get(template),
|
|
2910
3069
|
);
|
|
2911
3070
|
} catch (error) {
|
|
2912
3071
|
if (!(error instanceof CompileFailure)) throw error;
|
|
@@ -3052,6 +3211,7 @@ export function compile(
|
|
|
3052
3211
|
new Map(),
|
|
3053
3212
|
undefined,
|
|
3054
3213
|
templateFamily ? { ...templateFamily } : undefined,
|
|
3214
|
+
standardOrigins.get(template),
|
|
3055
3215
|
);
|
|
3056
3216
|
}
|
|
3057
3217
|
if (decl.kind === "object") {
|
package/src/parse.ts
CHANGED
|
@@ -450,6 +450,7 @@ class Parser {
|
|
|
450
450
|
}
|
|
451
451
|
for (const key of ["fee", "capture", "key"])
|
|
452
452
|
if (this.eat(key)) values[key] = this.atom();
|
|
453
|
+
if (this.eat("economics")) values.economics = this.block();
|
|
453
454
|
if (this.eat("boundary"))
|
|
454
455
|
values.boundary = this.record({ adapter: this.atom() });
|
|
455
456
|
return this.record(values);
|