@hyperscale0/hsx 2.0.0 → 2.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (82) hide show
  1. package/CHANGELOG.md +25 -0
  2. package/dist/src/cli.d.ts +1 -1
  3. package/dist/src/diagnostics.d.ts.map +1 -1
  4. package/dist/src/diagnostics.js +7 -0
  5. package/dist/src/diagnostics.js.map +1 -1
  6. package/dist/src/std-bundle.js +19 -19
  7. package/dist/src/std-bundle.js.map +1 -1
  8. package/dist/src/typecheck.js +89 -1
  9. package/dist/src/typecheck.js.map +1 -1
  10. package/dist/src/version.d.ts +1 -1
  11. package/dist/src/version.js +1 -1
  12. package/docs/guide/01-first-program.md +1 -1
  13. package/docs/guide/09-cost.md +1 -1
  14. package/docs/llms-full.txt +64 -39
  15. package/docs/llms.txt +2 -2
  16. package/docs/reference/cli.md +2 -2
  17. package/docs/reference/diagnostics.md +21 -1
  18. package/docs/reference/grammar.md +1 -1
  19. package/docs/reference/std/advance.md +1 -1
  20. package/docs/reference/std/cancellable_booking.md +1 -1
  21. package/docs/reference/std/captured_payment.md +1 -1
  22. package/docs/reference/std/conditional_disbursement.md +1 -1
  23. package/docs/reference/std/credit_facility.md +1 -1
  24. package/docs/reference/std/held_payment.md +41 -36
  25. package/docs/reference/std/instant_transfer.md +1 -1
  26. package/docs/reference/std/metered.md +1 -1
  27. package/docs/reference/std/pooled_split.md +1 -1
  28. package/docs/reference/std/premium_forward.md +1 -1
  29. package/docs/reference/std/reconciled_payout.md +1 -1
  30. package/docs/reference/std/recurring_collection.md +1 -1
  31. package/docs/reference/std/rotating_pool.md +1 -1
  32. package/docs/reference/std/scheduled.md +1 -1
  33. package/docs/reference/std/security_deposit.md +1 -1
  34. package/docs/reference/std/settlement_batch.md +1 -1
  35. package/docs/reference/std/swap.md +1 -1
  36. package/docs/reference/std/threshold_pool.md +1 -1
  37. package/docs/reference/std/weighted_distribution.md +1 -1
  38. package/docs/reference/types.md +1 -1
  39. package/docs/reference/udl-output.md +1 -1
  40. package/examples/advance/advance.udl +6 -6
  41. package/examples/cancellable_booking/cancellable_booking.udl +10 -10
  42. package/examples/captured_payment/captured_payment.udl +6 -6
  43. package/examples/conditional_disbursement/conditional_disbursement.udl +2 -2
  44. package/examples/cost-table.json +18 -78
  45. package/examples/credit_facility/credit_facility.udl +10 -10
  46. package/examples/held_payment/held_payment.udl +23 -12
  47. package/examples/instant_transfer/instant_transfer.udl +6 -6
  48. package/examples/metered/metered.udl +4 -4
  49. package/examples/pooled_split/pooled_split.udl +10 -10
  50. package/examples/premium_forward/premium_forward.udl +12 -12
  51. package/examples/recurring_collection/recurring_collection.udl +8 -8
  52. package/examples/rotating_pool/rotating_pool.udl +78 -78
  53. package/examples/scheduled/scheduled.udl +6 -6
  54. package/examples/security_deposit/security_deposit.udl +2 -2
  55. package/examples/swap/swap.udl +22 -22
  56. package/examples/threshold_pool/threshold_pool.udl +10 -10
  57. package/examples/weighted_distribution/weighted_distribution.udl +2 -2
  58. package/package.json +3 -3
  59. package/skills/hsx/SKILL.md +2 -2
  60. package/src/diagnostics.ts +10 -0
  61. package/src/std-bundle.ts +19 -19
  62. package/src/typecheck.ts +105 -1
  63. package/src/version.ts +1 -1
  64. package/std/money_flows/advance.hsx +45 -0
  65. package/std/money_flows/cancellable_booking.hsx +45 -0
  66. package/std/money_flows/captured_payment.hsx +55 -0
  67. package/std/money_flows/conditional_disbursement.hsx +46 -0
  68. package/std/money_flows/credit_facility.hsx +57 -0
  69. package/std/money_flows/held_payment.hsx +152 -3
  70. package/std/money_flows/instant_transfer.hsx +42 -0
  71. package/std/money_flows/metered.hsx +41 -0
  72. package/std/money_flows/pooled_split.hsx +41 -0
  73. package/std/money_flows/premium_forward.hsx +51 -0
  74. package/std/money_flows/reconciled_payout.hsx +42 -0
  75. package/std/money_flows/recurring_collection.hsx +45 -0
  76. package/std/money_flows/rotating_pool.hsx +51 -0
  77. package/std/money_flows/scheduled.hsx +53 -0
  78. package/std/money_flows/security_deposit.hsx +58 -0
  79. package/std/money_flows/settlement_batch.hsx +51 -0
  80. package/std/money_flows/swap.hsx +53 -0
  81. package/std/money_flows/threshold_pool.hsx +51 -0
  82. package/std/money_flows/weighted_distribution.hsx +54 -0
@@ -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,CAGnE;IACA;QACE,cAAc;QACd,s/RAAs/R;KACv/R;IACD;QACE,yBAAyB;QACzB,w8OAAw8O;KACz8O;IACD;QACE,qCAAqC;QACrC,q5OAAq5O;KACt5O;IACD;QACE,kCAAkC;QAClC,urYAAurY;KACxrY;IACD;QACE,0CAA0C;QAC1C,u/NAAu/N;KACx/N;IACD;QACE,iCAAiC;QACjC,6mMAA6mM;KAC9mM;IACD;QACE,8BAA8B;QAC9B,om/DAAom/D;KACrm/D;IACD;QACE,uBAAuB;QACvB,oGAAoG;KACrG;IACD;QACE,kCAAkC;QAClC,qvbAAqvb;KACtvb;IACD;QACE,yBAAyB;QACzB,2/EAA2/E;KAC5/E;IACD;QACE,8BAA8B;QAC9B,ghKAAghK;KACjhK;IACD;QACE,iCAAiC;QACjC,0kXAA0kX;KAC3kX;IACD;QACE,mCAAmC;QACnC,gnNAAgnN;KACjnN;IACD;QACE,sCAAsC;QACtC,s0CAAs0C;KACv0C;IACD;QACE,+BAA+B;QAC/B,ygqBAAygqB;KAC1gqB;IACD;QACE,2BAA2B;QAC3B,g4+BAAg4+B;KACj4+B;IACD;QACE,kCAAkC;QAClC,u0YAAu0Y;KACx0Y;IACD;QACE,kCAAkC;QAClC,+1XAA+1X;KACh2X;IACD;QACE,sBAAsB;QACtB,ykoCAAykoC;KAC1koC;IACD;QACE,gCAAgC;QAChC,27dAA27d;KAC57d;IACD;QACE,uCAAuC;QACvC,spVAAspV;KACvpV;CACF,CAAC,CAAC"}
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,CAGnE;IACA;QACE,cAAc;QACd,s/RAAs/R;KACv/R;IACD;QACE,yBAAyB;QACzB,muTAAmuT;KACpuT;IACD;QACE,qCAAqC;QACrC,20TAA20T;KAC50T;IACD;QACE,kCAAkC;QAClC,sgeAAsge;KACvge;IACD;QACE,0CAA0C;QAC1C,+tSAA+tS;KAChuS;IACD;QACE,iCAAiC;QACjC,uwRAAuwR;KACxwR;IACD;QACE,8BAA8B;QAC9B,m3xEAAm3xE;KACp3xE;IACD;QACE,uBAAuB;QACvB,oGAAoG;KACrG;IACD;QACE,kCAAkC;QAClC,kvfAAkvf;KACnvf;IACD;QACE,yBAAyB;QACzB,w8IAAw8I;KACz8I;IACD;QACE,8BAA8B;QAC9B,y9NAAy9N;KAC19N;IACD;QACE,iCAAiC;QACjC,2ocAA2oc;KAC5oc;IACD;QACE,mCAAmC;QACnC,m6RAAm6R;KACp6R;IACD;QACE,sCAAsC;QACtC,yrGAAyrG;KAC1rG;IACD;QACE,+BAA+B;QAC/B,6nvBAA6nvB;KAC9nvB;IACD;QACE,2BAA2B;QAC3B,63kCAA63kC;KAC93kC;IACD;QACE,kCAAkC;QAClC,wteAAwte;KACzte;IACD;QACE,kCAAkC;QAClC,modAAmod;KACpod;IACD;QACE,sBAAsB;QACtB,8qtCAA8qtC;KAC/qtC;IACD;QACE,gCAAgC;QAChC,ytjBAAytjB;KAC1tjB;IACD;QACE,uCAAuC;QACvC,y7aAAy7a;KAC17a;CACF,CAAC,CAAC"}
@@ -2421,7 +2421,8 @@ function checkInstrument(name, body, parties, ports, aliases, diagnostics) {
2421
2421
  },
2422
2422
  },
2423
2423
  };
2424
- });
2424
+ })
2425
+ .map((action) => pinFixedCurrencyBindings(action, fields, diagnostics));
2425
2426
  for (const action of actions) {
2426
2427
  for (const declared of ports.get(action.name) ?? []) {
2427
2428
  const allowed = entry(declared.body, "allowed")?.value;
@@ -2999,6 +3000,93 @@ function friendlyMoveRows(body) {
2999
3000
  function isJsonObject(value) {
3000
3001
  return value !== null && typeof value === "object" && !Array.isArray(value);
3001
3002
  }
3003
+ /**
3004
+ * A money<SAR> field moves SAR, whatever the caller wrote in the instance
3005
+ * currency field. Every move of a fixed-currency amount, and every account
3006
+ * step of an instrument whose money is fixed, binds that currency as a
3007
+ * constant: a binding that reads one of the instrument's own text fields is
3008
+ * pinned here, and one the compiler cannot pin (an input, a ref, or a
3009
+ * constant naming another currency) is refused as HSX1306.
3010
+ */
3011
+ function pinFixedCurrencyBindings(action, fields, diagnostics) {
3012
+ const fieldByName = new Map(fields.map((field) => [field.name, field]));
3013
+ const fixedCurrencyOf = (field) => field?.type.kind === "money" &&
3014
+ field.type.currency &&
3015
+ CURRENCY.test(field.type.currency)
3016
+ ? field.type.currency
3017
+ : undefined;
3018
+ const fixed = new Set(fields.flatMap((field) => fixedCurrencyOf(field) ?? []));
3019
+ // Two fixed currencies is HSX1305's refusal; one decides here, none skips.
3020
+ const ledger = fixed.size === 1 ? [...fixed][0] : undefined;
3021
+ if (!ledger)
3022
+ return action;
3023
+ const instanceField = (binding) => binding !== undefined &&
3024
+ isJsonObject(binding) &&
3025
+ binding.from === "instance" &&
3026
+ typeof binding.path === "string" &&
3027
+ binding.path.startsWith("fields.")
3028
+ ? fieldByName.get(binding.path.slice("fields.".length))
3029
+ : undefined;
3030
+ const pin = (entry, currency, subject) => {
3031
+ if (!isJsonObject(entry))
3032
+ return entry;
3033
+ const bind = entry.bind;
3034
+ if (bind === undefined || !isJsonObject(bind))
3035
+ return entry;
3036
+ const binding = bind.currency;
3037
+ if (binding === undefined)
3038
+ return entry;
3039
+ const bound = isJsonObject(binding) && binding.from === "const"
3040
+ ? String(binding.value)
3041
+ : undefined;
3042
+ if (bound === currency)
3043
+ return entry;
3044
+ if (bound === undefined && instanceField(binding)?.type.kind === "text") {
3045
+ return {
3046
+ ...entry,
3047
+ bind: { ...bind, currency: { from: "const", value: currency } },
3048
+ };
3049
+ }
3050
+ diagnostics.push({
3051
+ code: "HSX1306",
3052
+ fix: `bind currency as { from: const; value: ${currency}; }`,
3053
+ message: `action ${action.name} binds the currency of ${subject} to ${bound ?? "a caller-supplied value"}; a money<${currency}> amount moves in ${currency}`,
3054
+ severity: "error",
3055
+ span: action.origin,
3056
+ });
3057
+ return entry;
3058
+ };
3059
+ const moves = action.slots.moves ?? [];
3060
+ const steps = action.slots.steps ?? [];
3061
+ return {
3062
+ ...action,
3063
+ slots: {
3064
+ ...action.slots,
3065
+ moves: Array.isArray(moves)
3066
+ ? moves.map((move) => {
3067
+ if (!isJsonObject(move))
3068
+ return move;
3069
+ // A post settles a reservation; the ledger refuses a post whose
3070
+ // currency differs from the reserve, which is pinned here.
3071
+ if (move.operation === "internal_transfer.post")
3072
+ return move;
3073
+ const bind = move.bind;
3074
+ const amount = bind !== undefined && isJsonObject(bind)
3075
+ ? instanceField(bind.amount)
3076
+ : undefined;
3077
+ return pin(move, fixedCurrencyOf(amount) ?? ledger, amount ? `fields.${amount.name}` : "the moved amount");
3078
+ })
3079
+ : moves,
3080
+ steps: Array.isArray(steps)
3081
+ ? steps.map((step) => isJsonObject(step) &&
3082
+ typeof step.operation === "string" &&
3083
+ step.operation.startsWith("account.")
3084
+ ? pin(step, ledger, `the ${step.operation} account`)
3085
+ : step)
3086
+ : steps,
3087
+ },
3088
+ };
3089
+ }
3002
3090
  function bindFieldReferences(slots, fields, action, diagnostics) {
3003
3091
  const externalFieldSlot = (path) => {
3004
3092
  const key = path.at(-1);