@ergoblockchain/sage-widget 0.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.
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/types.ts","../src/api.ts","../src/react/SageActivityFeed.tsx"],"names":["useState","useRef","useEffect","jsxs","jsx"],"mappings":"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","file":"react.cjs","sourcesContent":["/**\n * Public types — mirror of /api/sage/activity response shape.\n *\n * The source of truth is the API at https://www.ergoblockchain.org/api/sage/activity;\n * this file re-states the schema so consumers don't have to depend on the\n * server-side fetcher.\n */\n\nexport type SageActivityType = \"settlement\" | \"issuance\" | \"transfer\"\n\nexport interface SageActivityEvent {\n /** 64-char hex transaction id. */\n txId: string\n /** Block height at inclusion. */\n blockHeight: number\n /** Block timestamp (ms epoch). */\n timestamp: number\n /** Heuristic classification of the tx. */\n type: SageActivityType\n /** nanoERG flowing into the seller wallet from this tx (sum of outputs). */\n inflowNanoErg: number\n /**\n * For settlements: value of the redeemed Note (= what the buyer paid).\n * For other event types: undefined.\n *\n * Use this — not `inflowNanoErg` — when displaying \"amount paid for a\n * settled query\". `inflowNanoErg` includes change boxes in test setups\n * where the buyer and seller share an address.\n */\n paymentNanoErg?: number\n /** First input box that carries Note-shape registers, if any. */\n noteBoxId?: string\n}\n\nexport interface SageActivityResponse {\n ok: boolean\n network: \"testnet\" | \"mainnet\"\n /** Sage seller wallet address. */\n receiver: string\n /** Total number of txs ever touching the wallet, per the explorer. */\n total: number\n events: SageActivityEvent[]\n error?: string\n}\n\n/**\n * Configuration accepted by every entry point (React component +\n * vanilla mount fn). Defaults below are sensible for the canonical\n * ergoblockchain.org deployment.\n */\nexport interface SageWidgetOptions {\n /**\n * Base URL of the Sage host. Override if you run your own Sage\n * deployment behind a custom domain. Default: ergoblockchain.org.\n */\n apiBase?: string\n /**\n * Number of events to display (max 25). Default: 5.\n */\n limit?: number\n /**\n * Polling interval in ms. Default: 60000 (60s). Set to 0 to disable\n * polling — the widget will fetch once on mount and never refresh.\n */\n refreshMs?: number\n /**\n * Optional callback fired every time a fresh response arrives. Useful\n * for analytics or for triggering host-side animations on new\n * settlements.\n */\n onUpdate?: (response: SageActivityResponse) => void\n /**\n * Optional callback fired on fetch errors. Default: console.warn.\n */\n onError?: (error: unknown) => void\n}\n\nexport const DEFAULT_API_BASE = \"https://www.ergoblockchain.org\"\nexport const DEFAULT_LIMIT = 5\nexport const DEFAULT_REFRESH_MS = 60_000\n","/**\n * Thin client over /api/sage/activity.\n *\n * Pure fetch + shape — no rendering, no DOM. React + vanilla mounts\n * both call into here so the API contract lives in one place.\n */\n\nimport {\n DEFAULT_API_BASE,\n DEFAULT_LIMIT,\n type SageActivityResponse,\n} from \"./types\"\n\nexport interface FetchActivityOptions {\n apiBase?: string\n limit?: number\n signal?: AbortSignal\n}\n\nexport async function fetchSageActivity(\n opts: FetchActivityOptions = {},\n): Promise<SageActivityResponse> {\n const base = opts.apiBase ?? DEFAULT_API_BASE\n const limit = Math.min(Math.max(opts.limit ?? DEFAULT_LIMIT, 1), 25)\n const url = `${base}/api/sage/activity?limit=${limit}`\n const res = await fetch(url, { signal: opts.signal })\n if (!res.ok) {\n throw new Error(`sage activity ${res.status}`)\n }\n return (await res.json()) as SageActivityResponse\n}\n\n/** nanoERG → \"0.001\" (trims trailing zeros, max 9 decimals). */\nexport function nanoToErg(nano: number | undefined): string {\n if (!nano || nano <= 0) return \"0\"\n const erg = nano / 1e9\n return erg.toFixed(9).replace(/\\.?0+$/, \"\")\n}\n\n/** Cheap relative-time formatter, ASCII-only, no Intl deps. */\nexport function relativeTime(ms: number, now: number = Date.now()): string {\n const diff = Math.max(0, now - ms)\n const sec = Math.floor(diff / 1000)\n if (sec < 60) return `${sec}s ago`\n const min = Math.floor(sec / 60)\n if (min < 60) return `${min}m ago`\n const hr = Math.floor(min / 60)\n if (hr < 24) return `${hr}h ago`\n const day = Math.floor(hr / 24)\n return `${day}d ago`\n}\n\n/** Receipt URL for a settled tx, given the host base. */\nexport function receiptUrl(txId: string, apiBase: string = DEFAULT_API_BASE): string {\n return `${apiBase}/r/sage/${txId}`\n}\n\n/** Explorer URL for a tx on the given network. */\nexport function explorerUrl(\n txId: string,\n network: \"testnet\" | \"mainnet\" = \"testnet\",\n): string {\n return network === \"testnet\"\n ? `https://testnet.ergoplatform.com/transactions/${txId}`\n : `https://explorer.ergoplatform.com/transactions/${txId}`\n}\n","/**\n * <SageActivityFeed /> — drop-in React component rendering Sage's live\n * on-chain activity (settlements + issuances + transfers) directly,\n * NOT through an iframe. Use this when you want host-CSS-themable,\n * tree-shakeable, accessibility-friendly markup.\n *\n * If you instead want a CSS-isolated drop-in that doesn't care about\n * the host page's style, use the static iframe embed at\n * https://www.ergoblockchain.org/agents.js\n * which mounts an isolated iframe.\n */\n\nimport {\n useEffect,\n useMemo,\n useRef,\n useState,\n type CSSProperties,\n} from \"react\"\nimport {\n explorerUrl,\n fetchSageActivity,\n nanoToErg,\n receiptUrl,\n relativeTime,\n} from \"../api\"\nimport {\n DEFAULT_LIMIT,\n DEFAULT_REFRESH_MS,\n type SageActivityEvent,\n type SageActivityResponse,\n type SageWidgetOptions,\n} from \"../types\"\n\nexport interface SageActivityFeedProps extends SageWidgetOptions {\n /** Class name applied to the root container. */\n className?: string\n /** Inline style applied to the root container. */\n style?: CSSProperties\n /**\n * Render-prop override. If supplied, the component calls this with\n * the current response and renders only what it returns. Use this\n * to bring your own design system instead of the default styling.\n */\n children?: (state: {\n loading: boolean\n response: SageActivityResponse | null\n error: unknown\n }) => React.ReactNode\n}\n\nconst ONE_MIN = 60_000\n\nexport function SageActivityFeed(props: SageActivityFeedProps): JSX.Element {\n const {\n apiBase,\n limit = DEFAULT_LIMIT,\n refreshMs = DEFAULT_REFRESH_MS,\n onUpdate,\n onError,\n className,\n style,\n children,\n } = props\n\n const [response, setResponse] = useState<SageActivityResponse | null>(null)\n const [error, setError] = useState<unknown>(null)\n const [loading, setLoading] = useState(true)\n const [now, setNow] = useState(() => Date.now())\n\n const onUpdateRef = useRef(onUpdate)\n const onErrorRef = useRef(onError)\n useEffect(() => {\n onUpdateRef.current = onUpdate\n }, [onUpdate])\n useEffect(() => {\n onErrorRef.current = onError\n }, [onError])\n\n useEffect(() => {\n let cancelled = false\n const abort = new AbortController()\n\n async function load() {\n try {\n const data = await fetchSageActivity({\n apiBase,\n limit,\n signal: abort.signal,\n })\n if (cancelled) return\n setResponse(data)\n setError(null)\n setLoading(false)\n onUpdateRef.current?.(data)\n } catch (err) {\n if (cancelled || (err as { name?: string }).name === \"AbortError\") return\n setError(err)\n setLoading(false)\n ;(onErrorRef.current ?? console.warn)(err)\n }\n }\n\n load()\n const pollId =\n refreshMs > 0 ? setInterval(load, refreshMs) : undefined\n const tickId = setInterval(() => setNow(Date.now()), ONE_MIN / 4)\n return () => {\n cancelled = true\n abort.abort()\n if (pollId) clearInterval(pollId)\n clearInterval(tickId)\n }\n }, [apiBase, limit, refreshMs])\n\n if (children) {\n return <>{children({ loading, response, error })}</>\n }\n\n return (\n <div className={className} style={{ ...rootStyle, ...style }}>\n <Header network={response?.network ?? \"testnet\"} />\n <List\n loading={loading}\n events={response?.events ?? []}\n network={response?.network ?? \"testnet\"}\n apiBase={apiBase}\n now={now}\n />\n {error ? (\n <div style={errorStyle}>\n Could not reach the activity feed.\n </div>\n ) : null}\n </div>\n )\n}\n\nfunction Header({ network }: { network: \"testnet\" | \"mainnet\" }) {\n return (\n <div style={headerStyle}>\n <span style={dotStyle} />\n <span style={labelStyle}>Live · Ergo {network}</span>\n <a\n href=\"https://www.ergoblockchain.org/agent-economy#sage-activity\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n style={linkStyle}\n >\n Sage on chain\n </a>\n </div>\n )\n}\n\nfunction List({\n loading,\n events,\n network,\n apiBase,\n now,\n}: {\n loading: boolean\n events: SageActivityEvent[]\n network: \"testnet\" | \"mainnet\"\n apiBase?: string\n now: number\n}) {\n if (loading) return <div style={emptyStyle}>Loading…</div>\n if (events.length === 0)\n return (\n <div style={emptyStyle}>\n No activity yet — be the first to ask Sage a paid query.\n </div>\n )\n return (\n <div>\n {events.map((evt) => (\n <Row key={evt.txId} evt={evt} network={network} apiBase={apiBase} now={now} />\n ))}\n </div>\n )\n}\n\nfunction Row({\n evt,\n network,\n apiBase,\n now,\n}: {\n evt: SageActivityEvent\n network: \"testnet\" | \"mainnet\"\n apiBase?: string\n now: number\n}) {\n const isSettle = evt.type === \"settlement\"\n const href = isSettle ? receiptUrl(evt.txId, apiBase) : explorerUrl(evt.txId, network)\n const amount = isSettle ? evt.paymentNanoErg ?? evt.inflowNanoErg : evt.inflowNanoErg\n const chipStyle = isSettle ? chipSettleStyle : chipIssueStyle\n const chipText = isSettle ? \"Settled\" : evt.type === \"issuance\" ? \"Issued\" : \"Transfer\"\n return (\n <a\n href={href}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n style={rowStyle}\n >\n <span style={chipStyle}>{chipText}</span>\n <span style={metaStyle}>\n <span style={txStyle}>{evt.txId}</span>\n <span style={whenStyle}>\n block {evt.blockHeight.toLocaleString()} · {relativeTime(evt.timestamp, now)}\n </span>\n </span>\n <span style={amountStyle}>\n {nanoToErg(amount)} <span style={amountUnitStyle}>ERG</span>\n </span>\n </a>\n )\n}\n\n// ── Default inline styles (no CSS-in-JS dep, no class collisions on host) ──\n\nconst rootStyle: CSSProperties = {\n background: \"#000\",\n color: \"#e5e7eb\",\n fontFamily:\n \"'JetBrains Mono',ui-monospace,SFMono-Regular,Menlo,monospace\",\n padding: \"14px 16px\",\n borderRadius: 14,\n border: \"1px solid rgba(255,255,255,.08)\",\n boxSizing: \"border-box\",\n width: \"100%\",\n fontSize: 14,\n lineHeight: 1.4,\n}\n\nconst headerStyle: CSSProperties = {\n display: \"flex\",\n alignItems: \"center\",\n gap: 10,\n marginBottom: 10,\n}\n\nconst dotStyle: CSSProperties = {\n width: 8,\n height: 8,\n borderRadius: \"50%\",\n background: \"#fb923c\",\n flexShrink: 0,\n}\n\nconst labelStyle: CSSProperties = {\n fontSize: 10,\n letterSpacing: \"0.25em\",\n textTransform: \"uppercase\",\n color: \"#fb923c\",\n}\n\nconst linkStyle: CSSProperties = {\n marginLeft: \"auto\",\n fontSize: 13,\n color: \"#fed7aa\",\n textDecoration: \"none\",\n}\n\nconst rowStyle: CSSProperties = {\n display: \"flex\",\n alignItems: \"center\",\n gap: 10,\n padding: \"8px 0\",\n borderTop: \"1px solid rgba(255,255,255,.06)\",\n textDecoration: \"none\",\n color: \"inherit\",\n}\n\nconst chipBase: CSSProperties = {\n fontSize: 9,\n letterSpacing: \"0.2em\",\n textTransform: \"uppercase\",\n padding: \"2px 6px\",\n borderRadius: 4,\n flexShrink: 0,\n border: \"1px solid\",\n}\n\nconst chipSettleStyle: CSSProperties = {\n ...chipBase,\n borderColor: \"rgba(251,146,60,.4)\",\n color: \"#fdba74\",\n background: \"rgba(251,146,60,.1)\",\n}\n\nconst chipIssueStyle: CSSProperties = {\n ...chipBase,\n borderColor: \"rgba(245,158,11,.3)\",\n color: \"rgba(252,211,77,.8)\",\n background: \"rgba(245,158,11,.05)\",\n}\n\nconst metaStyle: CSSProperties = {\n flex: 1,\n minWidth: 0,\n display: \"flex\",\n flexDirection: \"column\",\n}\n\nconst txStyle: CSSProperties = {\n color: \"#d1d5db\",\n fontSize: 11,\n overflow: \"hidden\",\n textOverflow: \"ellipsis\",\n whiteSpace: \"nowrap\",\n}\n\nconst whenStyle: CSSProperties = {\n color: \"#6b7280\",\n fontSize: 10,\n marginTop: 1,\n}\n\nconst amountStyle: CSSProperties = {\n color: \"#fed7aa\",\n fontSize: 12,\n flexShrink: 0,\n textAlign: \"right\",\n}\n\nconst amountUnitStyle: CSSProperties = {\n color: \"#6b7280\",\n fontSize: 9,\n textTransform: \"uppercase\",\n marginLeft: 2,\n}\n\nconst emptyStyle: CSSProperties = {\n padding: \"18px 0\",\n textAlign: \"center\",\n color: \"#6b7280\",\n fontSize: 11,\n}\n\nconst errorStyle: CSSProperties = {\n ...emptyStyle,\n color: \"#f87171\",\n}\n"]}
@@ -0,0 +1,35 @@
1
+ import { CSSProperties } from 'react';
2
+ import { e as SageWidgetOptions, c as SageActivityResponse } from './types-uzMz6_mP.cjs';
3
+ export { D as DEFAULT_API_BASE, a as DEFAULT_LIMIT, b as DEFAULT_REFRESH_MS, S as SageActivityEvent, d as SageActivityType } from './types-uzMz6_mP.cjs';
4
+
5
+ /**
6
+ * <SageActivityFeed /> — drop-in React component rendering Sage's live
7
+ * on-chain activity (settlements + issuances + transfers) directly,
8
+ * NOT through an iframe. Use this when you want host-CSS-themable,
9
+ * tree-shakeable, accessibility-friendly markup.
10
+ *
11
+ * If you instead want a CSS-isolated drop-in that doesn't care about
12
+ * the host page's style, use the static iframe embed at
13
+ * https://www.ergoblockchain.org/agents.js
14
+ * which mounts an isolated iframe.
15
+ */
16
+
17
+ interface SageActivityFeedProps extends SageWidgetOptions {
18
+ /** Class name applied to the root container. */
19
+ className?: string;
20
+ /** Inline style applied to the root container. */
21
+ style?: CSSProperties;
22
+ /**
23
+ * Render-prop override. If supplied, the component calls this with
24
+ * the current response and renders only what it returns. Use this
25
+ * to bring your own design system instead of the default styling.
26
+ */
27
+ children?: (state: {
28
+ loading: boolean;
29
+ response: SageActivityResponse | null;
30
+ error: unknown;
31
+ }) => React.ReactNode;
32
+ }
33
+ declare function SageActivityFeed(props: SageActivityFeedProps): JSX.Element;
34
+
35
+ export { SageActivityFeed, type SageActivityFeedProps, SageActivityResponse, SageWidgetOptions };
@@ -0,0 +1,35 @@
1
+ import { CSSProperties } from 'react';
2
+ import { e as SageWidgetOptions, c as SageActivityResponse } from './types-uzMz6_mP.js';
3
+ export { D as DEFAULT_API_BASE, a as DEFAULT_LIMIT, b as DEFAULT_REFRESH_MS, S as SageActivityEvent, d as SageActivityType } from './types-uzMz6_mP.js';
4
+
5
+ /**
6
+ * <SageActivityFeed /> — drop-in React component rendering Sage's live
7
+ * on-chain activity (settlements + issuances + transfers) directly,
8
+ * NOT through an iframe. Use this when you want host-CSS-themable,
9
+ * tree-shakeable, accessibility-friendly markup.
10
+ *
11
+ * If you instead want a CSS-isolated drop-in that doesn't care about
12
+ * the host page's style, use the static iframe embed at
13
+ * https://www.ergoblockchain.org/agents.js
14
+ * which mounts an isolated iframe.
15
+ */
16
+
17
+ interface SageActivityFeedProps extends SageWidgetOptions {
18
+ /** Class name applied to the root container. */
19
+ className?: string;
20
+ /** Inline style applied to the root container. */
21
+ style?: CSSProperties;
22
+ /**
23
+ * Render-prop override. If supplied, the component calls this with
24
+ * the current response and renders only what it returns. Use this
25
+ * to bring your own design system instead of the default styling.
26
+ */
27
+ children?: (state: {
28
+ loading: boolean;
29
+ response: SageActivityResponse | null;
30
+ error: unknown;
31
+ }) => React.ReactNode;
32
+ }
33
+ declare function SageActivityFeed(props: SageActivityFeedProps): JSX.Element;
34
+
35
+ export { SageActivityFeed, type SageActivityFeedProps, SageActivityResponse, SageWidgetOptions };
package/dist/react.js ADDED
@@ -0,0 +1,297 @@
1
+ import { useState, useRef, useEffect } from 'react';
2
+ import { jsx, Fragment, jsxs } from 'react/jsx-runtime';
3
+
4
+ // src/react/SageActivityFeed.tsx
5
+
6
+ // src/types.ts
7
+ var DEFAULT_API_BASE = "https://www.ergoblockchain.org";
8
+ var DEFAULT_LIMIT = 5;
9
+ var DEFAULT_REFRESH_MS = 6e4;
10
+
11
+ // src/api.ts
12
+ async function fetchSageActivity(opts = {}) {
13
+ const base = opts.apiBase ?? DEFAULT_API_BASE;
14
+ const limit = Math.min(Math.max(opts.limit ?? DEFAULT_LIMIT, 1), 25);
15
+ const url = `${base}/api/sage/activity?limit=${limit}`;
16
+ const res = await fetch(url, { signal: opts.signal });
17
+ if (!res.ok) {
18
+ throw new Error(`sage activity ${res.status}`);
19
+ }
20
+ return await res.json();
21
+ }
22
+ function nanoToErg(nano) {
23
+ if (!nano || nano <= 0) return "0";
24
+ const erg = nano / 1e9;
25
+ return erg.toFixed(9).replace(/\.?0+$/, "");
26
+ }
27
+ function relativeTime(ms, now = Date.now()) {
28
+ const diff = Math.max(0, now - ms);
29
+ const sec = Math.floor(diff / 1e3);
30
+ if (sec < 60) return `${sec}s ago`;
31
+ const min = Math.floor(sec / 60);
32
+ if (min < 60) return `${min}m ago`;
33
+ const hr = Math.floor(min / 60);
34
+ if (hr < 24) return `${hr}h ago`;
35
+ const day = Math.floor(hr / 24);
36
+ return `${day}d ago`;
37
+ }
38
+ function receiptUrl(txId, apiBase = DEFAULT_API_BASE) {
39
+ return `${apiBase}/r/sage/${txId}`;
40
+ }
41
+ function explorerUrl(txId, network = "testnet") {
42
+ return network === "testnet" ? `https://testnet.ergoplatform.com/transactions/${txId}` : `https://explorer.ergoplatform.com/transactions/${txId}`;
43
+ }
44
+ var ONE_MIN = 6e4;
45
+ function SageActivityFeed(props) {
46
+ const {
47
+ apiBase,
48
+ limit = DEFAULT_LIMIT,
49
+ refreshMs = DEFAULT_REFRESH_MS,
50
+ onUpdate,
51
+ onError,
52
+ className,
53
+ style,
54
+ children
55
+ } = props;
56
+ const [response, setResponse] = useState(null);
57
+ const [error, setError] = useState(null);
58
+ const [loading, setLoading] = useState(true);
59
+ const [now, setNow] = useState(() => Date.now());
60
+ const onUpdateRef = useRef(onUpdate);
61
+ const onErrorRef = useRef(onError);
62
+ useEffect(() => {
63
+ onUpdateRef.current = onUpdate;
64
+ }, [onUpdate]);
65
+ useEffect(() => {
66
+ onErrorRef.current = onError;
67
+ }, [onError]);
68
+ useEffect(() => {
69
+ let cancelled = false;
70
+ const abort = new AbortController();
71
+ async function load() {
72
+ try {
73
+ const data = await fetchSageActivity({
74
+ apiBase,
75
+ limit,
76
+ signal: abort.signal
77
+ });
78
+ if (cancelled) return;
79
+ setResponse(data);
80
+ setError(null);
81
+ setLoading(false);
82
+ onUpdateRef.current?.(data);
83
+ } catch (err) {
84
+ if (cancelled || err.name === "AbortError") return;
85
+ setError(err);
86
+ setLoading(false);
87
+ (onErrorRef.current ?? console.warn)(err);
88
+ }
89
+ }
90
+ load();
91
+ const pollId = refreshMs > 0 ? setInterval(load, refreshMs) : void 0;
92
+ const tickId = setInterval(() => setNow(Date.now()), ONE_MIN / 4);
93
+ return () => {
94
+ cancelled = true;
95
+ abort.abort();
96
+ if (pollId) clearInterval(pollId);
97
+ clearInterval(tickId);
98
+ };
99
+ }, [apiBase, limit, refreshMs]);
100
+ if (children) {
101
+ return /* @__PURE__ */ jsx(Fragment, { children: children({ loading, response, error }) });
102
+ }
103
+ return /* @__PURE__ */ jsxs("div", { className, style: { ...rootStyle, ...style }, children: [
104
+ /* @__PURE__ */ jsx(Header, { network: response?.network ?? "testnet" }),
105
+ /* @__PURE__ */ jsx(
106
+ List,
107
+ {
108
+ loading,
109
+ events: response?.events ?? [],
110
+ network: response?.network ?? "testnet",
111
+ apiBase,
112
+ now
113
+ }
114
+ ),
115
+ error ? /* @__PURE__ */ jsx("div", { style: errorStyle, children: "Could not reach the activity feed." }) : null
116
+ ] });
117
+ }
118
+ function Header({ network }) {
119
+ return /* @__PURE__ */ jsxs("div", { style: headerStyle, children: [
120
+ /* @__PURE__ */ jsx("span", { style: dotStyle }),
121
+ /* @__PURE__ */ jsxs("span", { style: labelStyle, children: [
122
+ "Live \xB7 Ergo ",
123
+ network
124
+ ] }),
125
+ /* @__PURE__ */ jsx(
126
+ "a",
127
+ {
128
+ href: "https://www.ergoblockchain.org/agent-economy#sage-activity",
129
+ target: "_blank",
130
+ rel: "noopener noreferrer",
131
+ style: linkStyle,
132
+ children: "Sage on chain"
133
+ }
134
+ )
135
+ ] });
136
+ }
137
+ function List({
138
+ loading,
139
+ events,
140
+ network,
141
+ apiBase,
142
+ now
143
+ }) {
144
+ if (loading) return /* @__PURE__ */ jsx("div", { style: emptyStyle, children: "Loading\u2026" });
145
+ if (events.length === 0)
146
+ return /* @__PURE__ */ jsx("div", { style: emptyStyle, children: "No activity yet \u2014 be the first to ask Sage a paid query." });
147
+ return /* @__PURE__ */ jsx("div", { children: events.map((evt) => /* @__PURE__ */ jsx(Row, { evt, network, apiBase, now }, evt.txId)) });
148
+ }
149
+ function Row({
150
+ evt,
151
+ network,
152
+ apiBase,
153
+ now
154
+ }) {
155
+ const isSettle = evt.type === "settlement";
156
+ const href = isSettle ? receiptUrl(evt.txId, apiBase) : explorerUrl(evt.txId, network);
157
+ const amount = isSettle ? evt.paymentNanoErg ?? evt.inflowNanoErg : evt.inflowNanoErg;
158
+ const chipStyle = isSettle ? chipSettleStyle : chipIssueStyle;
159
+ const chipText = isSettle ? "Settled" : evt.type === "issuance" ? "Issued" : "Transfer";
160
+ return /* @__PURE__ */ jsxs(
161
+ "a",
162
+ {
163
+ href,
164
+ target: "_blank",
165
+ rel: "noopener noreferrer",
166
+ style: rowStyle,
167
+ children: [
168
+ /* @__PURE__ */ jsx("span", { style: chipStyle, children: chipText }),
169
+ /* @__PURE__ */ jsxs("span", { style: metaStyle, children: [
170
+ /* @__PURE__ */ jsx("span", { style: txStyle, children: evt.txId }),
171
+ /* @__PURE__ */ jsxs("span", { style: whenStyle, children: [
172
+ "block ",
173
+ evt.blockHeight.toLocaleString(),
174
+ " \xB7 ",
175
+ relativeTime(evt.timestamp, now)
176
+ ] })
177
+ ] }),
178
+ /* @__PURE__ */ jsxs("span", { style: amountStyle, children: [
179
+ nanoToErg(amount),
180
+ " ",
181
+ /* @__PURE__ */ jsx("span", { style: amountUnitStyle, children: "ERG" })
182
+ ] })
183
+ ]
184
+ }
185
+ );
186
+ }
187
+ var rootStyle = {
188
+ background: "#000",
189
+ color: "#e5e7eb",
190
+ fontFamily: "'JetBrains Mono',ui-monospace,SFMono-Regular,Menlo,monospace",
191
+ padding: "14px 16px",
192
+ borderRadius: 14,
193
+ border: "1px solid rgba(255,255,255,.08)",
194
+ boxSizing: "border-box",
195
+ width: "100%",
196
+ fontSize: 14,
197
+ lineHeight: 1.4
198
+ };
199
+ var headerStyle = {
200
+ display: "flex",
201
+ alignItems: "center",
202
+ gap: 10,
203
+ marginBottom: 10
204
+ };
205
+ var dotStyle = {
206
+ width: 8,
207
+ height: 8,
208
+ borderRadius: "50%",
209
+ background: "#fb923c",
210
+ flexShrink: 0
211
+ };
212
+ var labelStyle = {
213
+ fontSize: 10,
214
+ letterSpacing: "0.25em",
215
+ textTransform: "uppercase",
216
+ color: "#fb923c"
217
+ };
218
+ var linkStyle = {
219
+ marginLeft: "auto",
220
+ fontSize: 13,
221
+ color: "#fed7aa",
222
+ textDecoration: "none"
223
+ };
224
+ var rowStyle = {
225
+ display: "flex",
226
+ alignItems: "center",
227
+ gap: 10,
228
+ padding: "8px 0",
229
+ borderTop: "1px solid rgba(255,255,255,.06)",
230
+ textDecoration: "none",
231
+ color: "inherit"
232
+ };
233
+ var chipBase = {
234
+ fontSize: 9,
235
+ letterSpacing: "0.2em",
236
+ textTransform: "uppercase",
237
+ padding: "2px 6px",
238
+ borderRadius: 4,
239
+ flexShrink: 0,
240
+ border: "1px solid"
241
+ };
242
+ var chipSettleStyle = {
243
+ ...chipBase,
244
+ borderColor: "rgba(251,146,60,.4)",
245
+ color: "#fdba74",
246
+ background: "rgba(251,146,60,.1)"
247
+ };
248
+ var chipIssueStyle = {
249
+ ...chipBase,
250
+ borderColor: "rgba(245,158,11,.3)",
251
+ color: "rgba(252,211,77,.8)",
252
+ background: "rgba(245,158,11,.05)"
253
+ };
254
+ var metaStyle = {
255
+ flex: 1,
256
+ minWidth: 0,
257
+ display: "flex",
258
+ flexDirection: "column"
259
+ };
260
+ var txStyle = {
261
+ color: "#d1d5db",
262
+ fontSize: 11,
263
+ overflow: "hidden",
264
+ textOverflow: "ellipsis",
265
+ whiteSpace: "nowrap"
266
+ };
267
+ var whenStyle = {
268
+ color: "#6b7280",
269
+ fontSize: 10,
270
+ marginTop: 1
271
+ };
272
+ var amountStyle = {
273
+ color: "#fed7aa",
274
+ fontSize: 12,
275
+ flexShrink: 0,
276
+ textAlign: "right"
277
+ };
278
+ var amountUnitStyle = {
279
+ color: "#6b7280",
280
+ fontSize: 9,
281
+ textTransform: "uppercase",
282
+ marginLeft: 2
283
+ };
284
+ var emptyStyle = {
285
+ padding: "18px 0",
286
+ textAlign: "center",
287
+ color: "#6b7280",
288
+ fontSize: 11
289
+ };
290
+ var errorStyle = {
291
+ ...emptyStyle,
292
+ color: "#f87171"
293
+ };
294
+
295
+ export { DEFAULT_API_BASE, DEFAULT_LIMIT, DEFAULT_REFRESH_MS, SageActivityFeed };
296
+ //# sourceMappingURL=react.js.map
297
+ //# sourceMappingURL=react.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/types.ts","../src/api.ts","../src/react/SageActivityFeed.tsx"],"names":[],"mappings":"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","file":"react.js","sourcesContent":["/**\n * Public types — mirror of /api/sage/activity response shape.\n *\n * The source of truth is the API at https://www.ergoblockchain.org/api/sage/activity;\n * this file re-states the schema so consumers don't have to depend on the\n * server-side fetcher.\n */\n\nexport type SageActivityType = \"settlement\" | \"issuance\" | \"transfer\"\n\nexport interface SageActivityEvent {\n /** 64-char hex transaction id. */\n txId: string\n /** Block height at inclusion. */\n blockHeight: number\n /** Block timestamp (ms epoch). */\n timestamp: number\n /** Heuristic classification of the tx. */\n type: SageActivityType\n /** nanoERG flowing into the seller wallet from this tx (sum of outputs). */\n inflowNanoErg: number\n /**\n * For settlements: value of the redeemed Note (= what the buyer paid).\n * For other event types: undefined.\n *\n * Use this — not `inflowNanoErg` — when displaying \"amount paid for a\n * settled query\". `inflowNanoErg` includes change boxes in test setups\n * where the buyer and seller share an address.\n */\n paymentNanoErg?: number\n /** First input box that carries Note-shape registers, if any. */\n noteBoxId?: string\n}\n\nexport interface SageActivityResponse {\n ok: boolean\n network: \"testnet\" | \"mainnet\"\n /** Sage seller wallet address. */\n receiver: string\n /** Total number of txs ever touching the wallet, per the explorer. */\n total: number\n events: SageActivityEvent[]\n error?: string\n}\n\n/**\n * Configuration accepted by every entry point (React component +\n * vanilla mount fn). Defaults below are sensible for the canonical\n * ergoblockchain.org deployment.\n */\nexport interface SageWidgetOptions {\n /**\n * Base URL of the Sage host. Override if you run your own Sage\n * deployment behind a custom domain. Default: ergoblockchain.org.\n */\n apiBase?: string\n /**\n * Number of events to display (max 25). Default: 5.\n */\n limit?: number\n /**\n * Polling interval in ms. Default: 60000 (60s). Set to 0 to disable\n * polling — the widget will fetch once on mount and never refresh.\n */\n refreshMs?: number\n /**\n * Optional callback fired every time a fresh response arrives. Useful\n * for analytics or for triggering host-side animations on new\n * settlements.\n */\n onUpdate?: (response: SageActivityResponse) => void\n /**\n * Optional callback fired on fetch errors. Default: console.warn.\n */\n onError?: (error: unknown) => void\n}\n\nexport const DEFAULT_API_BASE = \"https://www.ergoblockchain.org\"\nexport const DEFAULT_LIMIT = 5\nexport const DEFAULT_REFRESH_MS = 60_000\n","/**\n * Thin client over /api/sage/activity.\n *\n * Pure fetch + shape — no rendering, no DOM. React + vanilla mounts\n * both call into here so the API contract lives in one place.\n */\n\nimport {\n DEFAULT_API_BASE,\n DEFAULT_LIMIT,\n type SageActivityResponse,\n} from \"./types\"\n\nexport interface FetchActivityOptions {\n apiBase?: string\n limit?: number\n signal?: AbortSignal\n}\n\nexport async function fetchSageActivity(\n opts: FetchActivityOptions = {},\n): Promise<SageActivityResponse> {\n const base = opts.apiBase ?? DEFAULT_API_BASE\n const limit = Math.min(Math.max(opts.limit ?? DEFAULT_LIMIT, 1), 25)\n const url = `${base}/api/sage/activity?limit=${limit}`\n const res = await fetch(url, { signal: opts.signal })\n if (!res.ok) {\n throw new Error(`sage activity ${res.status}`)\n }\n return (await res.json()) as SageActivityResponse\n}\n\n/** nanoERG → \"0.001\" (trims trailing zeros, max 9 decimals). */\nexport function nanoToErg(nano: number | undefined): string {\n if (!nano || nano <= 0) return \"0\"\n const erg = nano / 1e9\n return erg.toFixed(9).replace(/\\.?0+$/, \"\")\n}\n\n/** Cheap relative-time formatter, ASCII-only, no Intl deps. */\nexport function relativeTime(ms: number, now: number = Date.now()): string {\n const diff = Math.max(0, now - ms)\n const sec = Math.floor(diff / 1000)\n if (sec < 60) return `${sec}s ago`\n const min = Math.floor(sec / 60)\n if (min < 60) return `${min}m ago`\n const hr = Math.floor(min / 60)\n if (hr < 24) return `${hr}h ago`\n const day = Math.floor(hr / 24)\n return `${day}d ago`\n}\n\n/** Receipt URL for a settled tx, given the host base. */\nexport function receiptUrl(txId: string, apiBase: string = DEFAULT_API_BASE): string {\n return `${apiBase}/r/sage/${txId}`\n}\n\n/** Explorer URL for a tx on the given network. */\nexport function explorerUrl(\n txId: string,\n network: \"testnet\" | \"mainnet\" = \"testnet\",\n): string {\n return network === \"testnet\"\n ? `https://testnet.ergoplatform.com/transactions/${txId}`\n : `https://explorer.ergoplatform.com/transactions/${txId}`\n}\n","/**\n * <SageActivityFeed /> — drop-in React component rendering Sage's live\n * on-chain activity (settlements + issuances + transfers) directly,\n * NOT through an iframe. Use this when you want host-CSS-themable,\n * tree-shakeable, accessibility-friendly markup.\n *\n * If you instead want a CSS-isolated drop-in that doesn't care about\n * the host page's style, use the static iframe embed at\n * https://www.ergoblockchain.org/agents.js\n * which mounts an isolated iframe.\n */\n\nimport {\n useEffect,\n useMemo,\n useRef,\n useState,\n type CSSProperties,\n} from \"react\"\nimport {\n explorerUrl,\n fetchSageActivity,\n nanoToErg,\n receiptUrl,\n relativeTime,\n} from \"../api\"\nimport {\n DEFAULT_LIMIT,\n DEFAULT_REFRESH_MS,\n type SageActivityEvent,\n type SageActivityResponse,\n type SageWidgetOptions,\n} from \"../types\"\n\nexport interface SageActivityFeedProps extends SageWidgetOptions {\n /** Class name applied to the root container. */\n className?: string\n /** Inline style applied to the root container. */\n style?: CSSProperties\n /**\n * Render-prop override. If supplied, the component calls this with\n * the current response and renders only what it returns. Use this\n * to bring your own design system instead of the default styling.\n */\n children?: (state: {\n loading: boolean\n response: SageActivityResponse | null\n error: unknown\n }) => React.ReactNode\n}\n\nconst ONE_MIN = 60_000\n\nexport function SageActivityFeed(props: SageActivityFeedProps): JSX.Element {\n const {\n apiBase,\n limit = DEFAULT_LIMIT,\n refreshMs = DEFAULT_REFRESH_MS,\n onUpdate,\n onError,\n className,\n style,\n children,\n } = props\n\n const [response, setResponse] = useState<SageActivityResponse | null>(null)\n const [error, setError] = useState<unknown>(null)\n const [loading, setLoading] = useState(true)\n const [now, setNow] = useState(() => Date.now())\n\n const onUpdateRef = useRef(onUpdate)\n const onErrorRef = useRef(onError)\n useEffect(() => {\n onUpdateRef.current = onUpdate\n }, [onUpdate])\n useEffect(() => {\n onErrorRef.current = onError\n }, [onError])\n\n useEffect(() => {\n let cancelled = false\n const abort = new AbortController()\n\n async function load() {\n try {\n const data = await fetchSageActivity({\n apiBase,\n limit,\n signal: abort.signal,\n })\n if (cancelled) return\n setResponse(data)\n setError(null)\n setLoading(false)\n onUpdateRef.current?.(data)\n } catch (err) {\n if (cancelled || (err as { name?: string }).name === \"AbortError\") return\n setError(err)\n setLoading(false)\n ;(onErrorRef.current ?? console.warn)(err)\n }\n }\n\n load()\n const pollId =\n refreshMs > 0 ? setInterval(load, refreshMs) : undefined\n const tickId = setInterval(() => setNow(Date.now()), ONE_MIN / 4)\n return () => {\n cancelled = true\n abort.abort()\n if (pollId) clearInterval(pollId)\n clearInterval(tickId)\n }\n }, [apiBase, limit, refreshMs])\n\n if (children) {\n return <>{children({ loading, response, error })}</>\n }\n\n return (\n <div className={className} style={{ ...rootStyle, ...style }}>\n <Header network={response?.network ?? \"testnet\"} />\n <List\n loading={loading}\n events={response?.events ?? []}\n network={response?.network ?? \"testnet\"}\n apiBase={apiBase}\n now={now}\n />\n {error ? (\n <div style={errorStyle}>\n Could not reach the activity feed.\n </div>\n ) : null}\n </div>\n )\n}\n\nfunction Header({ network }: { network: \"testnet\" | \"mainnet\" }) {\n return (\n <div style={headerStyle}>\n <span style={dotStyle} />\n <span style={labelStyle}>Live · Ergo {network}</span>\n <a\n href=\"https://www.ergoblockchain.org/agent-economy#sage-activity\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n style={linkStyle}\n >\n Sage on chain\n </a>\n </div>\n )\n}\n\nfunction List({\n loading,\n events,\n network,\n apiBase,\n now,\n}: {\n loading: boolean\n events: SageActivityEvent[]\n network: \"testnet\" | \"mainnet\"\n apiBase?: string\n now: number\n}) {\n if (loading) return <div style={emptyStyle}>Loading…</div>\n if (events.length === 0)\n return (\n <div style={emptyStyle}>\n No activity yet — be the first to ask Sage a paid query.\n </div>\n )\n return (\n <div>\n {events.map((evt) => (\n <Row key={evt.txId} evt={evt} network={network} apiBase={apiBase} now={now} />\n ))}\n </div>\n )\n}\n\nfunction Row({\n evt,\n network,\n apiBase,\n now,\n}: {\n evt: SageActivityEvent\n network: \"testnet\" | \"mainnet\"\n apiBase?: string\n now: number\n}) {\n const isSettle = evt.type === \"settlement\"\n const href = isSettle ? receiptUrl(evt.txId, apiBase) : explorerUrl(evt.txId, network)\n const amount = isSettle ? evt.paymentNanoErg ?? evt.inflowNanoErg : evt.inflowNanoErg\n const chipStyle = isSettle ? chipSettleStyle : chipIssueStyle\n const chipText = isSettle ? \"Settled\" : evt.type === \"issuance\" ? \"Issued\" : \"Transfer\"\n return (\n <a\n href={href}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n style={rowStyle}\n >\n <span style={chipStyle}>{chipText}</span>\n <span style={metaStyle}>\n <span style={txStyle}>{evt.txId}</span>\n <span style={whenStyle}>\n block {evt.blockHeight.toLocaleString()} · {relativeTime(evt.timestamp, now)}\n </span>\n </span>\n <span style={amountStyle}>\n {nanoToErg(amount)} <span style={amountUnitStyle}>ERG</span>\n </span>\n </a>\n )\n}\n\n// ── Default inline styles (no CSS-in-JS dep, no class collisions on host) ──\n\nconst rootStyle: CSSProperties = {\n background: \"#000\",\n color: \"#e5e7eb\",\n fontFamily:\n \"'JetBrains Mono',ui-monospace,SFMono-Regular,Menlo,monospace\",\n padding: \"14px 16px\",\n borderRadius: 14,\n border: \"1px solid rgba(255,255,255,.08)\",\n boxSizing: \"border-box\",\n width: \"100%\",\n fontSize: 14,\n lineHeight: 1.4,\n}\n\nconst headerStyle: CSSProperties = {\n display: \"flex\",\n alignItems: \"center\",\n gap: 10,\n marginBottom: 10,\n}\n\nconst dotStyle: CSSProperties = {\n width: 8,\n height: 8,\n borderRadius: \"50%\",\n background: \"#fb923c\",\n flexShrink: 0,\n}\n\nconst labelStyle: CSSProperties = {\n fontSize: 10,\n letterSpacing: \"0.25em\",\n textTransform: \"uppercase\",\n color: \"#fb923c\",\n}\n\nconst linkStyle: CSSProperties = {\n marginLeft: \"auto\",\n fontSize: 13,\n color: \"#fed7aa\",\n textDecoration: \"none\",\n}\n\nconst rowStyle: CSSProperties = {\n display: \"flex\",\n alignItems: \"center\",\n gap: 10,\n padding: \"8px 0\",\n borderTop: \"1px solid rgba(255,255,255,.06)\",\n textDecoration: \"none\",\n color: \"inherit\",\n}\n\nconst chipBase: CSSProperties = {\n fontSize: 9,\n letterSpacing: \"0.2em\",\n textTransform: \"uppercase\",\n padding: \"2px 6px\",\n borderRadius: 4,\n flexShrink: 0,\n border: \"1px solid\",\n}\n\nconst chipSettleStyle: CSSProperties = {\n ...chipBase,\n borderColor: \"rgba(251,146,60,.4)\",\n color: \"#fdba74\",\n background: \"rgba(251,146,60,.1)\",\n}\n\nconst chipIssueStyle: CSSProperties = {\n ...chipBase,\n borderColor: \"rgba(245,158,11,.3)\",\n color: \"rgba(252,211,77,.8)\",\n background: \"rgba(245,158,11,.05)\",\n}\n\nconst metaStyle: CSSProperties = {\n flex: 1,\n minWidth: 0,\n display: \"flex\",\n flexDirection: \"column\",\n}\n\nconst txStyle: CSSProperties = {\n color: \"#d1d5db\",\n fontSize: 11,\n overflow: \"hidden\",\n textOverflow: \"ellipsis\",\n whiteSpace: \"nowrap\",\n}\n\nconst whenStyle: CSSProperties = {\n color: \"#6b7280\",\n fontSize: 10,\n marginTop: 1,\n}\n\nconst amountStyle: CSSProperties = {\n color: \"#fed7aa\",\n fontSize: 12,\n flexShrink: 0,\n textAlign: \"right\",\n}\n\nconst amountUnitStyle: CSSProperties = {\n color: \"#6b7280\",\n fontSize: 9,\n textTransform: \"uppercase\",\n marginLeft: 2,\n}\n\nconst emptyStyle: CSSProperties = {\n padding: \"18px 0\",\n textAlign: \"center\",\n color: \"#6b7280\",\n fontSize: 11,\n}\n\nconst errorStyle: CSSProperties = {\n ...emptyStyle,\n color: \"#f87171\",\n}\n"]}
@@ -0,0 +1,77 @@
1
+ /**
2
+ * Public types — mirror of /api/sage/activity response shape.
3
+ *
4
+ * The source of truth is the API at https://www.ergoblockchain.org/api/sage/activity;
5
+ * this file re-states the schema so consumers don't have to depend on the
6
+ * server-side fetcher.
7
+ */
8
+ type SageActivityType = "settlement" | "issuance" | "transfer";
9
+ interface SageActivityEvent {
10
+ /** 64-char hex transaction id. */
11
+ txId: string;
12
+ /** Block height at inclusion. */
13
+ blockHeight: number;
14
+ /** Block timestamp (ms epoch). */
15
+ timestamp: number;
16
+ /** Heuristic classification of the tx. */
17
+ type: SageActivityType;
18
+ /** nanoERG flowing into the seller wallet from this tx (sum of outputs). */
19
+ inflowNanoErg: number;
20
+ /**
21
+ * For settlements: value of the redeemed Note (= what the buyer paid).
22
+ * For other event types: undefined.
23
+ *
24
+ * Use this — not `inflowNanoErg` — when displaying "amount paid for a
25
+ * settled query". `inflowNanoErg` includes change boxes in test setups
26
+ * where the buyer and seller share an address.
27
+ */
28
+ paymentNanoErg?: number;
29
+ /** First input box that carries Note-shape registers, if any. */
30
+ noteBoxId?: string;
31
+ }
32
+ interface SageActivityResponse {
33
+ ok: boolean;
34
+ network: "testnet" | "mainnet";
35
+ /** Sage seller wallet address. */
36
+ receiver: string;
37
+ /** Total number of txs ever touching the wallet, per the explorer. */
38
+ total: number;
39
+ events: SageActivityEvent[];
40
+ error?: string;
41
+ }
42
+ /**
43
+ * Configuration accepted by every entry point (React component +
44
+ * vanilla mount fn). Defaults below are sensible for the canonical
45
+ * ergoblockchain.org deployment.
46
+ */
47
+ interface SageWidgetOptions {
48
+ /**
49
+ * Base URL of the Sage host. Override if you run your own Sage
50
+ * deployment behind a custom domain. Default: ergoblockchain.org.
51
+ */
52
+ apiBase?: string;
53
+ /**
54
+ * Number of events to display (max 25). Default: 5.
55
+ */
56
+ limit?: number;
57
+ /**
58
+ * Polling interval in ms. Default: 60000 (60s). Set to 0 to disable
59
+ * polling — the widget will fetch once on mount and never refresh.
60
+ */
61
+ refreshMs?: number;
62
+ /**
63
+ * Optional callback fired every time a fresh response arrives. Useful
64
+ * for analytics or for triggering host-side animations on new
65
+ * settlements.
66
+ */
67
+ onUpdate?: (response: SageActivityResponse) => void;
68
+ /**
69
+ * Optional callback fired on fetch errors. Default: console.warn.
70
+ */
71
+ onError?: (error: unknown) => void;
72
+ }
73
+ declare const DEFAULT_API_BASE = "https://www.ergoblockchain.org";
74
+ declare const DEFAULT_LIMIT = 5;
75
+ declare const DEFAULT_REFRESH_MS = 60000;
76
+
77
+ export { DEFAULT_API_BASE as D, type SageActivityEvent as S, DEFAULT_LIMIT as a, DEFAULT_REFRESH_MS as b, type SageActivityResponse as c, type SageActivityType as d, type SageWidgetOptions as e };
@@ -0,0 +1,77 @@
1
+ /**
2
+ * Public types — mirror of /api/sage/activity response shape.
3
+ *
4
+ * The source of truth is the API at https://www.ergoblockchain.org/api/sage/activity;
5
+ * this file re-states the schema so consumers don't have to depend on the
6
+ * server-side fetcher.
7
+ */
8
+ type SageActivityType = "settlement" | "issuance" | "transfer";
9
+ interface SageActivityEvent {
10
+ /** 64-char hex transaction id. */
11
+ txId: string;
12
+ /** Block height at inclusion. */
13
+ blockHeight: number;
14
+ /** Block timestamp (ms epoch). */
15
+ timestamp: number;
16
+ /** Heuristic classification of the tx. */
17
+ type: SageActivityType;
18
+ /** nanoERG flowing into the seller wallet from this tx (sum of outputs). */
19
+ inflowNanoErg: number;
20
+ /**
21
+ * For settlements: value of the redeemed Note (= what the buyer paid).
22
+ * For other event types: undefined.
23
+ *
24
+ * Use this — not `inflowNanoErg` — when displaying "amount paid for a
25
+ * settled query". `inflowNanoErg` includes change boxes in test setups
26
+ * where the buyer and seller share an address.
27
+ */
28
+ paymentNanoErg?: number;
29
+ /** First input box that carries Note-shape registers, if any. */
30
+ noteBoxId?: string;
31
+ }
32
+ interface SageActivityResponse {
33
+ ok: boolean;
34
+ network: "testnet" | "mainnet";
35
+ /** Sage seller wallet address. */
36
+ receiver: string;
37
+ /** Total number of txs ever touching the wallet, per the explorer. */
38
+ total: number;
39
+ events: SageActivityEvent[];
40
+ error?: string;
41
+ }
42
+ /**
43
+ * Configuration accepted by every entry point (React component +
44
+ * vanilla mount fn). Defaults below are sensible for the canonical
45
+ * ergoblockchain.org deployment.
46
+ */
47
+ interface SageWidgetOptions {
48
+ /**
49
+ * Base URL of the Sage host. Override if you run your own Sage
50
+ * deployment behind a custom domain. Default: ergoblockchain.org.
51
+ */
52
+ apiBase?: string;
53
+ /**
54
+ * Number of events to display (max 25). Default: 5.
55
+ */
56
+ limit?: number;
57
+ /**
58
+ * Polling interval in ms. Default: 60000 (60s). Set to 0 to disable
59
+ * polling — the widget will fetch once on mount and never refresh.
60
+ */
61
+ refreshMs?: number;
62
+ /**
63
+ * Optional callback fired every time a fresh response arrives. Useful
64
+ * for analytics or for triggering host-side animations on new
65
+ * settlements.
66
+ */
67
+ onUpdate?: (response: SageActivityResponse) => void;
68
+ /**
69
+ * Optional callback fired on fetch errors. Default: console.warn.
70
+ */
71
+ onError?: (error: unknown) => void;
72
+ }
73
+ declare const DEFAULT_API_BASE = "https://www.ergoblockchain.org";
74
+ declare const DEFAULT_LIMIT = 5;
75
+ declare const DEFAULT_REFRESH_MS = 60000;
76
+
77
+ export { DEFAULT_API_BASE as D, type SageActivityEvent as S, DEFAULT_LIMIT as a, DEFAULT_REFRESH_MS as b, type SageActivityResponse as c, type SageActivityType as d, type SageWidgetOptions as e };