@ouronet/talos-registry 2.0.0 → 2.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/README.md CHANGED
@@ -178,10 +178,12 @@ import { tooltipModel, signatureRows } from "@ouronet/talos-registry";
178
178
  const m = tooltipModel("TS01-C1.DPTF|C_Transfer", { id: '"OURO-8Nh-JO8JO4F5"' });
179
179
  // m.slots -> EVERY execution parameter, in order, with type, value and flags
180
180
  // m.preview -> the INFO_ call with ITS OWN parameter list
181
- // m.kind -> "ouronet" | "stoa" | "kadena" (only ouronet has a cost section)
181
+ // m.kind -> "ouronet" | "stoa" | "kadena" (only ouronet has a cost section)
182
+ // m.chainColor -> the CANONICAL border colour for that chain
183
+ // m.consumer -> who is rendering, for the caller zone
182
184
  ```
183
185
 
184
- Seven rules, each there because it was got wrong first — most recently a six-parameter transfer
186
+ Eight rules, each there because it was got wrong first — most recently a six-parameter transfer
185
187
  whose tooltip showed five arguments, because it was rendering the preview's list under the
186
188
  execution's heading. Read the canon before building one.
187
189
 
package/TOOLTIP-CANON.md CHANGED
@@ -126,21 +126,61 @@ header comment. The claim had been *inferred* from "this is not an Ouronet opera
126
126
  nothing about who pays the host chain — and it was wrong in the direction that matters, telling a
127
127
  user they were about to spend when they were not.
128
128
 
129
- **Make the two visually distinct — the palette is yours.** The distinction is mandatory because
130
- the two differ in what they cost and what can be previewed; the specific colour is presentation,
131
- and this package does not get a vote on your design language. A rule that mandates a palette in
132
- someone else's application is a rule that gets ignored, and an ignored rule weakens the ones that
133
- matter.
129
+ ### The palette is canon — `CHAIN_PALETTE`
130
+
131
+ | chain | colour | |
132
+ |---|---|---|
133
+ | `ouronet` | `#3b82f6` | **blue** |
134
+ | `stoa` | `#ceac5f` | **gold** |
135
+ | `kadena` | `#22c55e` | **green** |
136
+
137
+ **This reverses the 1.4.0 position**, which said the palette was each app's business. The
138
+ reasoning then — that a package should not dictate colours inside someone else's design language —
139
+ was right about *decoration* and wrong about *this*. The colour encodes **which chain your money
140
+ is on**. Two apps teaching different meanings for the same colour is worse than neither using
141
+ colour at all, because a user believes whichever they learned first, and these two apps share
142
+ users.
143
+
144
+ `m.chainColor` and `m.chainLabel` are on the model so a renderer cannot quietly pick a different
145
+ one, and a test asserts every chain has both — if `Chain` ever gains a member without a colour,
146
+ that fails rather than rendering `undefined`, which CSS ignores and which therefore looks like
147
+ "no border rule" instead of a bug.
148
+
149
+ Colours were taken from what was already in use rather than invented: gold is OuronetUI's STOA
150
+ accent, blue its established `#3b82f6`, green its success green — unused on any tooltip surface
151
+ and therefore free to carry this meaning.
134
152
 
135
- In practice:
153
+ **Make the distinction run in every direction.** We coloured `stoa` gold and left `ouronet` on the
154
+ panel's ordinary grey, so it only existed one way: a reader who never hovered a native button
155
+ learned no rule at all, and gold read as "something is odd about this one" rather than as a
156
+ category. Every kind gets a colour *and* a label.
136
157
 
137
- | | `stoa` | `ouronet` | `kadena` |
138
- |---|---|---|---|
139
- | OuronetUI | gold `#ceac5f` | blue `#3b82f6` | *(not surfaced)* |
140
- | Codex | *its own* | violet | **green** |
158
+ And **say what is missing** rather than leaving the cost panel empty — an empty panel reads as
159
+ "the price failed to load".
160
+
161
+ ## Rule 4b — say who is rendering
162
+
163
+ Two applications draw this tooltip, and a Codex panel can open over an OuronetUI page. That is
164
+ exactly the case where "whose tooltip is this" is hardest to infer from chrome and most useful to
165
+ state.
166
+
167
+ **Carry a caller zone naming the consumer.** One line, its own accent:
168
+
169
+ ```ts
170
+ tooltipModel(key, values, CONSUMERS.Codex) // m.consumer -> { name, accent }
171
+ ```
172
+
173
+ | consumer | accent | |
174
+ |---|---|---|
175
+ | `OuronetUI` | `#d2d3d4` | neutral |
176
+ | `Codex` | `#8b5cf6` | **violet** |
141
177
 
142
- Whatever you choose, make it carry meaning rather than decoration, and **say what is missing**
143
- rather than leaving the cost panel empty — an empty panel reads as "the price failed to load".
178
+ **Two axes, deliberately.** The border says *what you are looking at*; the caller zone says *who
179
+ is showing it to you*. A consumer accent is therefore never a chain colour, and a test asserts the
180
+ two sets do not intersect — the moment they do, the two meanings merge and both become unreadable.
181
+
182
+ `name` matches the `consumerName` each app already uses for its codex settings, so the workspace
183
+ has one spelling of "OuronetUI" rather than two.
144
184
 
145
185
  Suggested footer, which is what OuronetUI ships:
146
186
 
@@ -152,11 +192,6 @@ a StoaChain `coin` call, so nothing prices it. Gas is still sponsored.
152
192
  Signatures are in `STOA_SIGNATURES` and `KADENA_SIGNATURES`, transcribed from the deployed
153
193
  contracts with line numbers. Use them rather than typing your own.
154
194
 
155
- **Make the distinction run in every direction.** We coloured `stoa` gold and left `ouronet` on the
156
- panel's ordinary grey — so the distinction existed one way only, and a reader who never hovered a
157
- native button learned no rule at all. Gold then reads as "something is odd about this one" rather
158
- than as a category. Give every kind a colour and a label, not just the exceptional ones.
159
-
160
195
  ## Rule 5 — a ghost is not data
161
196
 
162
197
  Every parameter has a worked example. The shapes are real — read from mainnet — so you can see
package/dist/index.d.ts CHANGED
@@ -16,6 +16,6 @@ export type { CallPlan } from "./plan.js";
16
16
  export { parseCapability, parseCapabilities, capabilityRecipe } from "./caps.js";
17
17
  export type { ParsedCapability, CapabilityRecipe } from "./caps.js";
18
18
  export { formatForType, formatDecimal, formatInteger, formatString, formatBool } from "./format.js";
19
- export { tooltipModel, tooltipModels, signatureRows, chainOf, isOffRegistryKey, isNativeKey, isPlaceholder, PLACEHOLDER, STOA_SIGNATURES, KADENA_SIGNATURES, NATIVE_SIGNATURES } from "./tooltip.js";
20
- export type { TooltipModel, TooltipSlot, TooltipPreview } from "./tooltip.js";
19
+ export { tooltipModel, tooltipModels, signatureRows, chainOf, isOffRegistryKey, isNativeKey, isPlaceholder, PLACEHOLDER, CHAIN_PALETTE, CHAIN_LABEL, CONSUMERS, STOA_SIGNATURES, KADENA_SIGNATURES, NATIVE_SIGNATURES } from "./tooltip.js";
20
+ export type { TooltipModel, TooltipSlot, TooltipPreview, Chain, ConsumerIdentity } from "./tooltip.js";
21
21
  export type * from "./types.js";
package/dist/index.js CHANGED
@@ -15,4 +15,4 @@ export { parseCapability, parseCapabilities, capabilityRecipe } from "./caps.js"
15
15
  export { formatForType, formatDecimal, formatInteger, formatString, formatBool } from "./format.js";
16
16
  // THE TOOLTIP CANON. Shared implementation rather than a shared document -- see TOOLTIP-CANON.md
17
17
  // for why each rule exists, and `tooltip.ts` for the rules themselves.
18
- export { tooltipModel, tooltipModels, signatureRows, chainOf, isOffRegistryKey, isNativeKey, isPlaceholder, PLACEHOLDER, STOA_SIGNATURES, KADENA_SIGNATURES, NATIVE_SIGNATURES } from "./tooltip.js";
18
+ export { tooltipModel, tooltipModels, signatureRows, chainOf, isOffRegistryKey, isNativeKey, isPlaceholder, PLACEHOLDER, CHAIN_PALETTE, CHAIN_LABEL, CONSUMERS, STOA_SIGNATURES, KADENA_SIGNATURES, NATIVE_SIGNATURES } from "./tooltip.js";
package/dist/tooltip.d.ts CHANGED
@@ -1,3 +1,41 @@
1
+ /** The three worlds a tooltip can describe. See rule 4. */
2
+ export type Chain = "ouronet" | "stoa" | "kadena";
3
+ /**
4
+ * The canonical border colour per chain. USE THESE.
5
+ *
6
+ * Not styling: the colour tells a user which chain their money is on, and that vocabulary is
7
+ * shared between the applications that render it. Two apps teaching different meanings for the
8
+ * same colour is worse than neither using colour at all, because the user believes the first one
9
+ * they learned.
10
+ *
11
+ * ouronet blue the ouronet-ns surface -- priced, IGNIS, sponsored
12
+ * stoa gold StoaChain's own coin -- unpriced, no IGNIS, still sponsored
13
+ * kadena green a DIFFERENT CHAIN -- its own gas, its own balances
14
+ *
15
+ * Chosen from what was already in use rather than invented: gold is OuronetUI's STOA accent and
16
+ * blue its established `#3b82f6`; green is the app's existing success green, which is unused on
17
+ * any other tooltip surface and therefore free to carry this meaning.
18
+ */
19
+ export declare const CHAIN_PALETTE: Readonly<Record<Chain, string>>;
20
+ /** Human label for the chain, for the border-adjacent marker. */
21
+ export declare const CHAIN_LABEL: Readonly<Record<Chain, string>>;
22
+ /**
23
+ * Who is drawing the tooltip -- rule 4b.
24
+ *
25
+ * Two applications render this, and a Codex panel can open over an OuronetUI page, which is
26
+ * exactly the case where "whose tooltip is this" is hardest to infer from chrome and most useful
27
+ * to state. The accent is the CONSUMER's identity and is deliberately a different axis from
28
+ * `CHAIN_PALETTE`: one says what you are looking at, the other says who is showing it to you.
29
+ *
30
+ * `name` matches the `consumerName` key each app already uses for its codex settings, so there is
31
+ * one spelling of "OuronetUI" across the workspace rather than two.
32
+ */
33
+ export interface ConsumerIdentity {
34
+ name: string;
35
+ /** the app's own accent for the caller zone. NOT a chain colour. */
36
+ accent: string;
37
+ }
38
+ export declare const CONSUMERS: Readonly<Record<"OuronetUI" | "Codex", ConsumerIdentity>>;
1
39
  /** One parameter of the execution, with everything a renderer needs about it. */
2
40
  export interface TooltipSlot {
3
41
  /** 1-based, so a renderer never has to decide whether to add one. */
@@ -33,11 +71,8 @@ export interface TooltipModel {
33
71
  * kadena Kadena mainnet's `coin`. A DIFFERENT CHAIN -- different gas, different accounts,
34
72
  * and nothing about Ouronet applies to it.
35
73
  *
36
- * A renderer MUST make these visually distinct, because they differ in what they cost and what
37
- * can be previewed. It is NOT told how: OuronetUI uses gold/blue, the Codex violet for Ouronet
38
- * and green for Kadena, and all are conformant. Mandating a palette in a package consumed by
39
- * applications with their own design languages is a rule that gets ignored, and an ignored rule
40
- * weakens the ones that matter.
74
+ * Each has a canonical colour in `CHAIN_PALETTE`, and a renderer should use it: the colour
75
+ * encodes which chain the user's money is on, which is shared vocabulary rather than styling.
41
76
  *
42
77
  * RENAMED from `"native"` in 2.0.0. With only two worlds "native" was unambiguous; with three
43
78
  * it silently invited the question "native to WHAT" -- and both candidate answers are a
@@ -57,6 +92,12 @@ export interface TooltipModel {
57
92
  * latency the user pays for a foregone conclusion. Rule 5.
58
93
  */
59
94
  shouldRead: boolean;
95
+ /** the canonical border colour for `kind`. Convenience -- identical to CHAIN_PALETTE[kind]. */
96
+ chainColor: string;
97
+ /** the label to print beside it: OURONET / STOA NATIVE / KADENA. */
98
+ chainLabel: string;
99
+ /** who is rendering, for the caller zone. Undefined when the caller did not say. */
100
+ consumer?: ConsumerIdentity;
60
101
  /** things a renderer may want to surface. Never thrown; a tooltip must not take a page down. */
61
102
  warnings: string[];
62
103
  }
@@ -110,7 +151,7 @@ export declare const isNativeKey: (key: string) => boolean;
110
151
  * unresolvable argument becomes a visible placeholder rather than an exception, because a tooltip
111
152
  * must never take down the page it annotates.
112
153
  */
113
- export declare function tooltipModel(key: string, values?: Readonly<Record<string, string>>): TooltipModel;
154
+ export declare function tooltipModel(key: string, values?: Readonly<Record<string, string>>, consumer?: ConsumerIdentity): TooltipModel;
114
155
  /**
115
156
  * Models for a button that fronts a CHOICE of executions, in the order the ZBOM presents them.
116
157
  *
@@ -119,7 +160,7 @@ export declare function tooltipModel(key: string, values?: Readonly<Record<strin
119
160
  * caller instead -- and if nothing survives, the caller renders no tooltip, which is the correct
120
161
  * outcome and not a crash.
121
162
  */
122
- export declare function tooltipModels(keys: readonly string[], values?: Readonly<Record<string, string>>): TooltipModel[];
163
+ export declare function tooltipModels(keys: readonly string[], values?: Readonly<Record<string, string>>, consumer?: ConsumerIdentity): TooltipModel[];
123
164
  /**
124
165
  * The type row -- rule 3.
125
166
  *
package/dist/tooltip.js CHANGED
@@ -22,12 +22,22 @@
22
22
  * 3. TYPES GO ON THEIR OWN ROW. `patron:string executor:string ...` doubles the width of the
23
23
  * widest line in the panel. A parallel row under the names costs one line and reads better.
24
24
  *
25
- * 4. THREE WORLDS, and they must be distinguishable at a glance. `ouronet` (the ouronet-ns
26
- * surface), `stoa` (StoaChain's own `coin` contract) and `kadena` (Kadena mainnet's `coin`).
27
- * They differ in what they cost and what can be previewed. Only `ouronet` has an INFO_ reader
28
- * and collects IGNIS; gas is sponsored on the Stoa side regardless -- claiming otherwise tells
29
- * a user they are about to spend when they are not. HOW you distinguish them is yours: `kind`
30
- * is the canon, the palette is not.
25
+ * 4. THREE WORLDS, WITH A CANONICAL COLOUR EACH. `ouronet` (blue), `stoa` (gold), `kadena`
26
+ * (green). They differ in what they cost and what can be previewed. Only `ouronet` has an
27
+ * INFO_ reader and collects IGNIS; gas is sponsored on the Stoa side regardless -- claiming
28
+ * otherwise tells a user they are about to spend when they are not.
29
+ *
30
+ * THE PALETTE IS NOW CANON, reversing the 1.4.0 position that it was each app's business.
31
+ * The argument then was that a package should not dictate colours inside somebody else's
32
+ * design language, and that was right about DECORATION and wrong about this: the colour
33
+ * encodes WHICH CHAIN YOUR MONEY IS ON. A user who learns green-means-Kadena in one app and
34
+ * meets green-means-something-else in the other has been taught a falsehood by the
35
+ * inconsistency, and the two apps share users. A shared vocabulary has to be shared.
36
+ *
37
+ * 4b. SAY WHO IS RENDERING. Two applications draw this tooltip, and they draw it over different
38
+ * surfaces for the same chains. A caller zone naming the consumer costs one line and answers
39
+ * "which app am I looking at" without the user having to infer it from chrome -- which matters
40
+ * most in exactly the case where it is hardest, a Codex panel over an OuronetUI page.
31
41
  *
32
42
  * 0. CHAINWEB ONLY -- the rule that decides whether a tooltip exists at all. This model describes
33
43
  * a PACT call on a Chainweb chain: what function, what arguments, what it costs. A button that
@@ -41,6 +51,37 @@
41
51
  */
42
52
  import { getEntrypoint, getPreview, tryGetEntrypoint, registry } from "./registry.js";
43
53
  import { formatForType } from "./format.js";
54
+ /**
55
+ * The canonical border colour per chain. USE THESE.
56
+ *
57
+ * Not styling: the colour tells a user which chain their money is on, and that vocabulary is
58
+ * shared between the applications that render it. Two apps teaching different meanings for the
59
+ * same colour is worse than neither using colour at all, because the user believes the first one
60
+ * they learned.
61
+ *
62
+ * ouronet blue the ouronet-ns surface -- priced, IGNIS, sponsored
63
+ * stoa gold StoaChain's own coin -- unpriced, no IGNIS, still sponsored
64
+ * kadena green a DIFFERENT CHAIN -- its own gas, its own balances
65
+ *
66
+ * Chosen from what was already in use rather than invented: gold is OuronetUI's STOA accent and
67
+ * blue its established `#3b82f6`; green is the app's existing success green, which is unused on
68
+ * any other tooltip surface and therefore free to carry this meaning.
69
+ */
70
+ export const CHAIN_PALETTE = {
71
+ ouronet: "#3b82f6",
72
+ stoa: "#ceac5f",
73
+ kadena: "#22c55e",
74
+ };
75
+ /** Human label for the chain, for the border-adjacent marker. */
76
+ export const CHAIN_LABEL = {
77
+ ouronet: "OURONET",
78
+ stoa: "STOA NATIVE",
79
+ kadena: "KADENA",
80
+ };
81
+ export const CONSUMERS = {
82
+ OuronetUI: { name: "OuronetUI", accent: "#d2d3d4" },
83
+ Codex: { name: "Codex", accent: "#8b5cf6" },
84
+ };
44
85
  /** The registry's generic placeholder: an entity id for something that does not exist on chain. */
45
86
  export const PLACEHOLDER = '"example"';
46
87
  export const isPlaceholder = (rendered) => rendered === PLACEHOLDER;
@@ -124,7 +165,7 @@ const KADENA_GHOST = {
124
165
  bool: "false",
125
166
  guard: '(read-keyset "ks")',
126
167
  };
127
- function offRegistryModel(key, kind, values) {
168
+ function offRegistryModel(key, kind, values, consumer) {
128
169
  const sig = (kind === "stoa" ? STOA_SIGNATURES : KADENA_SIGNATURES)[key];
129
170
  if (!sig)
130
171
  throw new Error(`offRegistryModel: no signature for "${key}"`);
@@ -132,6 +173,9 @@ function offRegistryModel(key, kind, values) {
132
173
  return {
133
174
  kind,
134
175
  exec: key,
176
+ chainColor: CHAIN_PALETTE[kind],
177
+ chainLabel: CHAIN_LABEL[kind],
178
+ consumer,
135
179
  slots: sig.map(([name, type], i) => ({
136
180
  index: i + 1,
137
181
  name,
@@ -160,10 +204,10 @@ function offRegistryModel(key, kind, values) {
160
204
  * unresolvable argument becomes a visible placeholder rather than an exception, because a tooltip
161
205
  * must never take down the page it annotates.
162
206
  */
163
- export function tooltipModel(key, values = {}) {
207
+ export function tooltipModel(key, values = {}, consumer) {
164
208
  const chain = chainOf(key);
165
209
  if (chain === "stoa" || chain === "kadena")
166
- return offRegistryModel(key, chain, values);
210
+ return offRegistryModel(key, chain, values, consumer);
167
211
  if (chain === undefined && isOffRegistryKey(key))
168
212
  throw new Error(`tooltipModel: "${key}" matched no chain. This is a bug in chainOf.`);
169
213
  const ep = getEntrypoint(key); // throws, and names near matches, on a stale key
@@ -249,6 +293,9 @@ export function tooltipModel(key, values = {}) {
249
293
  return {
250
294
  kind: "ouronet",
251
295
  exec: `${registry.namespace}.${key}`,
296
+ chainColor: CHAIN_PALETTE.ouronet,
297
+ chainLabel: CHAIN_LABEL.ouronet,
298
+ consumer,
252
299
  slots,
253
300
  preview,
254
301
  // RULE 5: do not fire a read whose answer is a foregone refusal.
@@ -264,10 +311,10 @@ export function tooltipModel(key, values = {}) {
264
311
  * caller instead -- and if nothing survives, the caller renders no tooltip, which is the correct
265
312
  * outcome and not a crash.
266
313
  */
267
- export function tooltipModels(keys, values = {}) {
314
+ export function tooltipModels(keys, values = {}, consumer) {
268
315
  return keys
269
316
  .filter((k) => chainOf(k) !== undefined)
270
- .map((k) => tooltipModel(k, values));
317
+ .map((k) => tooltipModel(k, values, consumer));
271
318
  }
272
319
  /**
273
320
  * The type row -- rule 3.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ouronet/talos-registry",
3
- "version": "2.0.0",
3
+ "version": "2.1.0",
4
4
  "description": "The Ouronet callable surface, generated from the deployed contracts. Supply values; never type a function name.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",