madeonsol-x402 4.2.0 → 4.3.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 +28 -0
- package/dist/index.d.ts +19 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +17 -2
- package/dist/index.js.map +1 -1
- package/dist/terminal-policy.d.ts +56 -0
- package/dist/terminal-policy.d.ts.map +1 -0
- package/dist/terminal-policy.js +102 -0
- package/dist/terminal-policy.js.map +1 -0
- package/dist/terminal-watch.d.ts +135 -0
- package/dist/terminal-watch.d.ts.map +1 -0
- package/dist/terminal-watch.js +413 -0
- package/dist/terminal-watch.js.map +1 -0
- package/dist/terminal.d.ts +46 -0
- package/dist/terminal.d.ts.map +1 -0
- package/dist/terminal.js +52 -0
- package/dist/terminal.js.map +1 -0
- package/dist/types.d.ts +5 -2
- package/dist/types.d.ts.map +1 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +2 -2
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Framework-agnostic terminal snapshot/stream bridge (#534).
|
|
3
|
+
*
|
|
4
|
+
* A shared SDK socket supplies push frames. Snapshot reads happen once after
|
|
5
|
+
* the named subscription is ACKED, then only on coalesced, named invalidations.
|
|
6
|
+
* This deliberately NEVER patches REST module data from unrelated clocks.
|
|
7
|
+
*
|
|
8
|
+
* Instantiate once per selected token, reusing one existing stream connection.
|
|
9
|
+
* The controller never closes that shared stream on dispose().
|
|
10
|
+
*/
|
|
11
|
+
import { type TerminalWatchPlan, type TerminalModule, type TerminalChain, type TerminalTier } from "./terminal-policy.js";
|
|
12
|
+
export interface TerminalStreamFrame {
|
|
13
|
+
channel?: string;
|
|
14
|
+
event?: string;
|
|
15
|
+
sub_id?: string;
|
|
16
|
+
id?: string;
|
|
17
|
+
data?: unknown;
|
|
18
|
+
ts?: number;
|
|
19
|
+
replayed?: boolean;
|
|
20
|
+
snapshot?: boolean;
|
|
21
|
+
}
|
|
22
|
+
/** Adaptable to the existing MadeOnSolStream / RobinhoodChainStream overloads. */
|
|
23
|
+
export interface TerminalStreamPort {
|
|
24
|
+
subscribe(opts: {
|
|
25
|
+
subId: string;
|
|
26
|
+
channels: string[];
|
|
27
|
+
filters: Record<string, unknown>;
|
|
28
|
+
}): unknown;
|
|
29
|
+
unsubscribe(subId: string): unknown;
|
|
30
|
+
on(event: string, listener: (...args: unknown[]) => unknown): unknown;
|
|
31
|
+
off(event: string, listener: (...args: unknown[]) => unknown): unknown;
|
|
32
|
+
}
|
|
33
|
+
export interface TerminalModuleResponse {
|
|
34
|
+
status: "ready" | "partial_history" | "unverified" | "unavailable" | "timeout";
|
|
35
|
+
reason: string | null;
|
|
36
|
+
as_of: string | null;
|
|
37
|
+
data?: Record<string, unknown>;
|
|
38
|
+
}
|
|
39
|
+
export interface TerminalSnapshotResponse {
|
|
40
|
+
chain: TerminalChain;
|
|
41
|
+
address: string;
|
|
42
|
+
generated_at: string;
|
|
43
|
+
modules: Partial<Record<TerminalModule, TerminalModuleResponse>>;
|
|
44
|
+
}
|
|
45
|
+
export type TerminalPhase = "idle" | "awaiting_subscribe" | "bootstrapping" | "live" | "degraded" | "stopped";
|
|
46
|
+
export interface TerminalView {
|
|
47
|
+
phase: TerminalPhase;
|
|
48
|
+
address: string;
|
|
49
|
+
chain: TerminalChain;
|
|
50
|
+
/** Untouched REST modules; use the latest live frame as a separate overlay. */
|
|
51
|
+
snapshot: TerminalSnapshotResponse | null;
|
|
52
|
+
live: Partial<Record<TerminalModule, TerminalStreamFrame>>;
|
|
53
|
+
/** A known event or gap may have made a cached module stale. */
|
|
54
|
+
stale: TerminalModule[];
|
|
55
|
+
/** A module without an adequate existing WS source is snapshot-only. */
|
|
56
|
+
no_push: TerminalModule[];
|
|
57
|
+
/** A stream interruption or refusal must be visible to the terminal. */
|
|
58
|
+
incomplete: boolean;
|
|
59
|
+
last_error: string | null;
|
|
60
|
+
}
|
|
61
|
+
export interface TerminalViewOptions {
|
|
62
|
+
chain: TerminalChain;
|
|
63
|
+
address: string;
|
|
64
|
+
tier: TerminalTier;
|
|
65
|
+
include: readonly TerminalModule[];
|
|
66
|
+
/** Full RHC DEX firehose (all tokens) is high-bandwidth; opt in explicitly. */
|
|
67
|
+
includeRhcFirehose?: boolean;
|
|
68
|
+
/** KOL channels are unscoped broadcasts; opt in only with bandwidth budget. */
|
|
69
|
+
includeKolBroadcast?: boolean;
|
|
70
|
+
subId: string;
|
|
71
|
+
stream: TerminalStreamPort;
|
|
72
|
+
/** The existing keyed REST .tokenIntelligence(address, {include}) call. */
|
|
73
|
+
read: (include: readonly TerminalModule[]) => Promise<TerminalSnapshotResponse>;
|
|
74
|
+
onChange?: (view: TerminalView) => void;
|
|
75
|
+
onLive?: (frame: TerminalStreamFrame, module: TerminalModule) => void;
|
|
76
|
+
/** Min seconds per module before another HTTP refresh (default 15s). */
|
|
77
|
+
minModuleRefreshMs?: number;
|
|
78
|
+
/** Debounce and coalesce changed modules (default 750ms). */
|
|
79
|
+
debounceMs?: number;
|
|
80
|
+
now?: () => number;
|
|
81
|
+
}
|
|
82
|
+
/** Bounded by nine modules and one frame per live overlay; never a trade queue. */
|
|
83
|
+
export declare class TerminalTokenView {
|
|
84
|
+
readonly plan: TerminalWatchPlan;
|
|
85
|
+
private readonly opts;
|
|
86
|
+
private readonly listeners;
|
|
87
|
+
private readonly dirty;
|
|
88
|
+
private readonly stale;
|
|
89
|
+
private readonly seen;
|
|
90
|
+
private readonly live;
|
|
91
|
+
private readonly gen;
|
|
92
|
+
private readonly lastRead;
|
|
93
|
+
private readonly now;
|
|
94
|
+
private timer;
|
|
95
|
+
private timerAt;
|
|
96
|
+
private busy;
|
|
97
|
+
/** If the socket ACK arrives while a prior REST read is still unresolved,
|
|
98
|
+
* the latest post-ACK snapshot must run after that read settles. */
|
|
99
|
+
private pendingBootstrap;
|
|
100
|
+
private subscribed;
|
|
101
|
+
private epoch;
|
|
102
|
+
private phase;
|
|
103
|
+
private incomplete;
|
|
104
|
+
/** An observed historical gap survives a new REST snapshot and reconnect. */
|
|
105
|
+
private gapUnresolved;
|
|
106
|
+
private lastError;
|
|
107
|
+
private snapshot;
|
|
108
|
+
constructor(options: TerminalViewOptions);
|
|
109
|
+
getView(): TerminalView;
|
|
110
|
+
/** Registers handlers BEFORE opening the stream; first REST read waits for ACK. */
|
|
111
|
+
start(): void;
|
|
112
|
+
/** Consumer-initiated refresh, useful after a known unrecoverable gap. */
|
|
113
|
+
refresh(): void;
|
|
114
|
+
/**
|
|
115
|
+
* The caller must independently reconcile an unrecoverable event interval
|
|
116
|
+
* BEFORE clearing the visible gap. A fresh snapshot is not that evidence.
|
|
117
|
+
*/
|
|
118
|
+
acknowledgeHistoricalRecovery(): void;
|
|
119
|
+
dispose(): void;
|
|
120
|
+
private isStopped;
|
|
121
|
+
private emit;
|
|
122
|
+
private listen;
|
|
123
|
+
private onSubscribed;
|
|
124
|
+
private onWarning;
|
|
125
|
+
private onGap;
|
|
126
|
+
private onFrame;
|
|
127
|
+
private markStale;
|
|
128
|
+
private clearTimer;
|
|
129
|
+
private schedule;
|
|
130
|
+
private flush;
|
|
131
|
+
private fetchModules;
|
|
132
|
+
}
|
|
133
|
+
/** A named subscription prevents overwriting an integrator's other filters. */
|
|
134
|
+
export declare function createTerminalTokenView(options: TerminalViewOptions): TerminalTokenView;
|
|
135
|
+
//# sourceMappingURL=terminal-watch.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"terminal-watch.d.ts","sourceRoot":"","sources":["../src/terminal-watch.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,413 @@
|
|
|
1
|
+
/* Mirrored from src/lib/terminal-realtime/watch.ts; see SDK parity tests. */
|
|
2
|
+
/**
|
|
3
|
+
* Framework-agnostic terminal snapshot/stream bridge (#534).
|
|
4
|
+
*
|
|
5
|
+
* A shared SDK socket supplies push frames. Snapshot reads happen once after
|
|
6
|
+
* the named subscription is ACKED, then only on coalesced, named invalidations.
|
|
7
|
+
* This deliberately NEVER patches REST module data from unrelated clocks.
|
|
8
|
+
*
|
|
9
|
+
* Instantiate once per selected token, reusing one existing stream connection.
|
|
10
|
+
* The controller never closes that shared stream on dispose().
|
|
11
|
+
*/
|
|
12
|
+
import { planTerminalWatch, rulesForEvent, TERMINAL_MODULE_COSTS, } from "./terminal-policy.js";
|
|
13
|
+
const ACK_SUBSCRIBE = "subscribed";
|
|
14
|
+
const MAX_DEDUPE_IDS = 512;
|
|
15
|
+
/** Bounded by nine modules and one frame per live overlay; never a trade queue. */
|
|
16
|
+
export class TerminalTokenView {
|
|
17
|
+
plan;
|
|
18
|
+
opts;
|
|
19
|
+
listeners = new Map();
|
|
20
|
+
dirty = new Set();
|
|
21
|
+
stale = new Set();
|
|
22
|
+
seen = new Map();
|
|
23
|
+
live = {};
|
|
24
|
+
gen = new Map();
|
|
25
|
+
lastRead = new Map();
|
|
26
|
+
now;
|
|
27
|
+
timer = null;
|
|
28
|
+
timerAt = 0;
|
|
29
|
+
busy = false;
|
|
30
|
+
/** If the socket ACK arrives while a prior REST read is still unresolved,
|
|
31
|
+
* the latest post-ACK snapshot must run after that read settles. */
|
|
32
|
+
pendingBootstrap = false;
|
|
33
|
+
subscribed = false;
|
|
34
|
+
epoch = 0;
|
|
35
|
+
phase = "idle";
|
|
36
|
+
incomplete = false;
|
|
37
|
+
/** An observed historical gap survives a new REST snapshot and reconnect. */
|
|
38
|
+
gapUnresolved = false;
|
|
39
|
+
lastError = null;
|
|
40
|
+
snapshot = null;
|
|
41
|
+
constructor(options) {
|
|
42
|
+
if (!/^[A-Za-z0-9_.-]{1,64}$/.test(options.subId) || options.subId === "default") {
|
|
43
|
+
throw new Error("named_sub_id_required");
|
|
44
|
+
}
|
|
45
|
+
const n = options.minModuleRefreshMs ?? 15_000;
|
|
46
|
+
const d = options.debounceMs ?? 750;
|
|
47
|
+
if (!Number.isFinite(n) || n < 1_000 || n > 600_000 ||
|
|
48
|
+
!Number.isFinite(d) || d < 0 || d > 30_000)
|
|
49
|
+
throw new Error("invalid_refresh_budget");
|
|
50
|
+
this.plan = planTerminalWatch(options);
|
|
51
|
+
this.opts = options;
|
|
52
|
+
this.now = options.now ?? Date.now;
|
|
53
|
+
for (const m of this.plan.include)
|
|
54
|
+
this.gen.set(m, 0);
|
|
55
|
+
}
|
|
56
|
+
getView() {
|
|
57
|
+
return {
|
|
58
|
+
phase: this.phase, address: this.plan.address, chain: this.plan.chain,
|
|
59
|
+
snapshot: this.snapshot,
|
|
60
|
+
live: { ...this.live },
|
|
61
|
+
stale: [...this.stale],
|
|
62
|
+
no_push: [...this.plan.modules_without_push],
|
|
63
|
+
incomplete: this.incomplete,
|
|
64
|
+
last_error: this.lastError,
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
/** Registers handlers BEFORE opening the stream; first REST read waits for ACK. */
|
|
68
|
+
start() {
|
|
69
|
+
if (this.phase !== "idle")
|
|
70
|
+
throw new Error("already_started");
|
|
71
|
+
this.phase = this.plan.channels.length ? "awaiting_subscribe" : "bootstrapping";
|
|
72
|
+
this.emit();
|
|
73
|
+
if (!this.plan.channels.length) {
|
|
74
|
+
void this.fetchModules(this.plan.include, true);
|
|
75
|
+
return;
|
|
76
|
+
}
|
|
77
|
+
this.listen("*", (data, frame) => this.onFrame(frame));
|
|
78
|
+
this.listen(ACK_SUBSCRIBE, (_channels, ack) => this.onSubscribed(ack));
|
|
79
|
+
this.listen("close", () => {
|
|
80
|
+
if (this.phase === "stopped")
|
|
81
|
+
return;
|
|
82
|
+
// A fetch launched on the old socket can no longer be trusted.
|
|
83
|
+
this.epoch++;
|
|
84
|
+
this.pendingBootstrap = false;
|
|
85
|
+
this.subscribed = false;
|
|
86
|
+
this.incomplete = true;
|
|
87
|
+
this.phase = "awaiting_subscribe";
|
|
88
|
+
this.markStale(this.plan.include);
|
|
89
|
+
this.clearTimer();
|
|
90
|
+
this.emit();
|
|
91
|
+
});
|
|
92
|
+
this.listen("warning", (warn) => this.onWarning(warn));
|
|
93
|
+
this.listen("gap", (gap) => this.onGap(gap));
|
|
94
|
+
this.listen("fatal", () => {
|
|
95
|
+
this.subscribed = false;
|
|
96
|
+
this.incomplete = true;
|
|
97
|
+
this.phase = "degraded";
|
|
98
|
+
this.markStale(this.plan.include);
|
|
99
|
+
this.clearTimer();
|
|
100
|
+
this.emit();
|
|
101
|
+
});
|
|
102
|
+
this.opts.stream.subscribe({
|
|
103
|
+
subId: this.opts.subId,
|
|
104
|
+
channels: [...this.plan.channels],
|
|
105
|
+
filters: this.plan.filters,
|
|
106
|
+
});
|
|
107
|
+
}
|
|
108
|
+
/** Consumer-initiated refresh, useful after a known unrecoverable gap. */
|
|
109
|
+
refresh() {
|
|
110
|
+
if (this.phase === "idle" || this.phase === "stopped")
|
|
111
|
+
throw new Error("watch_not_active");
|
|
112
|
+
this.markStale(this.plan.include);
|
|
113
|
+
for (const m of this.plan.include)
|
|
114
|
+
this.dirty.add(m);
|
|
115
|
+
this.schedule(0);
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* The caller must independently reconcile an unrecoverable event interval
|
|
119
|
+
* BEFORE clearing the visible gap. A fresh snapshot is not that evidence.
|
|
120
|
+
*/
|
|
121
|
+
acknowledgeHistoricalRecovery() {
|
|
122
|
+
if (!this.gapUnresolved || this.phase === "stopped")
|
|
123
|
+
return;
|
|
124
|
+
this.gapUnresolved = false;
|
|
125
|
+
this.incomplete = !this.subscribed;
|
|
126
|
+
if (this.lastError === "stream_gap")
|
|
127
|
+
this.lastError = null;
|
|
128
|
+
if (!this.incomplete && this.snapshot)
|
|
129
|
+
this.phase = "live";
|
|
130
|
+
this.emit();
|
|
131
|
+
}
|
|
132
|
+
dispose() {
|
|
133
|
+
if (this.phase === "stopped")
|
|
134
|
+
return;
|
|
135
|
+
this.epoch++;
|
|
136
|
+
this.pendingBootstrap = false;
|
|
137
|
+
this.phase = "stopped";
|
|
138
|
+
this.subscribed = false;
|
|
139
|
+
this.clearTimer();
|
|
140
|
+
for (const [event, fn] of this.listeners)
|
|
141
|
+
this.opts.stream.off(event, fn);
|
|
142
|
+
this.listeners.clear();
|
|
143
|
+
if (this.plan.channels.length)
|
|
144
|
+
this.opts.stream.unsubscribe(this.opts.subId);
|
|
145
|
+
this.emit();
|
|
146
|
+
}
|
|
147
|
+
isStopped() { return this.phase === "stopped"; }
|
|
148
|
+
// A throwing UI callback must never leave the controller half-updated.
|
|
149
|
+
emit() { try {
|
|
150
|
+
this.opts.onChange?.(this.getView());
|
|
151
|
+
}
|
|
152
|
+
catch { /* consumer */ } }
|
|
153
|
+
listen(event, cb) {
|
|
154
|
+
this.listeners.set(event, cb);
|
|
155
|
+
this.opts.stream.on(event, cb);
|
|
156
|
+
}
|
|
157
|
+
onSubscribed(ack) {
|
|
158
|
+
if (this.phase === "stopped" || !ack || ack.sub_id !== this.opts.subId)
|
|
159
|
+
return;
|
|
160
|
+
const channels = Array.isArray(ack.channels) ? ack.channels : [];
|
|
161
|
+
// A partial or silently rejected subscription cannot be treated as live.
|
|
162
|
+
if (!this.plan.channels.every(ch => channels.includes(ch))) {
|
|
163
|
+
this.incomplete = true;
|
|
164
|
+
this.subscribed = false;
|
|
165
|
+
this.lastError = "subscription_incomplete";
|
|
166
|
+
this.phase = "degraded";
|
|
167
|
+
this.markStale(this.plan.include);
|
|
168
|
+
this.emit();
|
|
169
|
+
return;
|
|
170
|
+
}
|
|
171
|
+
// Invalidate any in-flight REST read from before this ACK/reconnect.
|
|
172
|
+
this.epoch++;
|
|
173
|
+
this.subscribed = true;
|
|
174
|
+
// Re-ACK proves a live subscription again, not that old trade events
|
|
175
|
+
// reported missing by the SDK have been reconstructed.
|
|
176
|
+
this.incomplete = this.gapUnresolved;
|
|
177
|
+
this.lastError = this.gapUnresolved ? "stream_gap" : null;
|
|
178
|
+
this.clearTimer();
|
|
179
|
+
// A re-subscribe after reconnect ALWAYS re-reads a bounded snapshot. We
|
|
180
|
+
// cannot compare clocks from REST and WS as one total-order watermark.
|
|
181
|
+
this.phase = "bootstrapping";
|
|
182
|
+
this.pendingBootstrap = true;
|
|
183
|
+
for (const m of this.plan.include)
|
|
184
|
+
this.dirty.add(m);
|
|
185
|
+
this.emit();
|
|
186
|
+
if (!this.busy) {
|
|
187
|
+
this.pendingBootstrap = false;
|
|
188
|
+
void this.fetchModules(this.plan.include, true);
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
onWarning(value) {
|
|
192
|
+
if (!value || typeof value !== "object" || this.phase === "stopped")
|
|
193
|
+
return;
|
|
194
|
+
const w = value;
|
|
195
|
+
// Named-subscription warnings always carry sub_id; one without it belongs
|
|
196
|
+
// to the connection default subscription, not this terminal view.
|
|
197
|
+
if (w.sub_id !== this.opts.subId)
|
|
198
|
+
return;
|
|
199
|
+
if (["channels_rejected", "channels_revoked", "named_subscriptions_unsupported", "invalid_filters",
|
|
200
|
+
// The server refuses the whole subscribe with these and sends NO ack.
|
|
201
|
+
"too_many_subscriptions", "invalid_sub_id", "unknown_sub_id"].includes(String(w.code))) {
|
|
202
|
+
// An already-started read cannot certify a revoked/invalid connection.
|
|
203
|
+
this.epoch++;
|
|
204
|
+
this.pendingBootstrap = false;
|
|
205
|
+
this.subscribed = false;
|
|
206
|
+
this.incomplete = true;
|
|
207
|
+
this.lastError = String(w.code);
|
|
208
|
+
this.phase = "degraded";
|
|
209
|
+
this.clearTimer();
|
|
210
|
+
this.markStale(this.plan.include);
|
|
211
|
+
this.emit();
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
onGap(value) {
|
|
215
|
+
if (this.phase === "stopped" || !value || typeof value !== "object")
|
|
216
|
+
return;
|
|
217
|
+
const gap = value;
|
|
218
|
+
const entries = gap.channels && typeof gap.channels === "object" ? Object.keys(gap.channels) : [];
|
|
219
|
+
const belongs = entries.length === 0 || entries.some(ch => ch.startsWith(this.opts.subId + "/") || (ch === this.opts.subId));
|
|
220
|
+
if (!belongs)
|
|
221
|
+
return;
|
|
222
|
+
this.gapUnresolved = true;
|
|
223
|
+
this.incomplete = true;
|
|
224
|
+
this.lastError = "stream_gap";
|
|
225
|
+
this.phase = "degraded";
|
|
226
|
+
this.markStale(this.plan.include);
|
|
227
|
+
// If the gap arrives during a REST fetch it must not let that fetch clear
|
|
228
|
+
// stale just because a frame did not increment the generation.
|
|
229
|
+
for (const m of this.plan.include)
|
|
230
|
+
this.gen.set(m, (this.gen.get(m) ?? 0) + 1);
|
|
231
|
+
// Snapshot resync is bounded, but not proof that missing historical events
|
|
232
|
+
// (KOL, executed trades) can be reconstructed. Keep incomplete=true.
|
|
233
|
+
if (this.subscribed) {
|
|
234
|
+
for (const m of this.plan.include)
|
|
235
|
+
this.dirty.add(m);
|
|
236
|
+
this.schedule(0);
|
|
237
|
+
}
|
|
238
|
+
this.emit();
|
|
239
|
+
}
|
|
240
|
+
onFrame(frame) {
|
|
241
|
+
if (!frame || this.phase === "stopped" || frame.sub_id !== this.opts.subId)
|
|
242
|
+
return;
|
|
243
|
+
const matches = rulesForEvent(frame, this.plan);
|
|
244
|
+
if (!matches.length)
|
|
245
|
+
return;
|
|
246
|
+
if (frame.id) {
|
|
247
|
+
const key = this.opts.subId + ":" + frame.channel + ":" + frame.id;
|
|
248
|
+
if (this.seen.has(key))
|
|
249
|
+
return;
|
|
250
|
+
this.seen.set(key, this.now());
|
|
251
|
+
if (this.seen.size > MAX_DEDUPE_IDS)
|
|
252
|
+
this.seen.delete(this.seen.keys().next().value);
|
|
253
|
+
}
|
|
254
|
+
for (const rule of matches) {
|
|
255
|
+
if (rule.delivery === "overlay") {
|
|
256
|
+
// State ticks carry no cursor; never let a late/replayed tick replace
|
|
257
|
+
// a newer overlay that is already on screen.
|
|
258
|
+
const prev = this.live[rule.module];
|
|
259
|
+
if (prev && typeof prev.ts === "number" && typeof frame.ts === "number" && frame.ts < prev.ts)
|
|
260
|
+
continue;
|
|
261
|
+
this.live[rule.module] = frame;
|
|
262
|
+
try {
|
|
263
|
+
this.opts.onLive?.(frame, rule.module);
|
|
264
|
+
}
|
|
265
|
+
catch { /* consumer */ }
|
|
266
|
+
}
|
|
267
|
+
else {
|
|
268
|
+
this.markStale([rule.module]);
|
|
269
|
+
this.dirty.add(rule.module);
|
|
270
|
+
// Only an INVALIDATION may make an in-flight read stale. An overlay tick
|
|
271
|
+
// supersedes the REST price on screen; counting it would re-read the
|
|
272
|
+
// snapshot module after every read on any actively traded token.
|
|
273
|
+
this.gen.set(rule.module, (this.gen.get(rule.module) ?? 0) + 1);
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
this.emit();
|
|
277
|
+
// A degraded view (visible gap, failed read) must keep refreshing its
|
|
278
|
+
// invalidated modules on a subscribed socket; schedule() refuses otherwise.
|
|
279
|
+
if ((this.phase === "live" || this.phase === "degraded") && this.dirty.size > 0)
|
|
280
|
+
this.schedule();
|
|
281
|
+
}
|
|
282
|
+
markStale(modules) {
|
|
283
|
+
for (const m of modules)
|
|
284
|
+
this.stale.add(m);
|
|
285
|
+
}
|
|
286
|
+
clearTimer() {
|
|
287
|
+
if (this.timer !== null)
|
|
288
|
+
clearTimeout(this.timer);
|
|
289
|
+
this.timer = null;
|
|
290
|
+
}
|
|
291
|
+
schedule(delay) {
|
|
292
|
+
if (this.phase === "stopped" || this.phase === "idle" || this.busy ||
|
|
293
|
+
(this.plan.channels.length > 0 && !this.subscribed))
|
|
294
|
+
return;
|
|
295
|
+
const now = this.now();
|
|
296
|
+
const minGap = this.opts.minModuleRefreshMs ?? 15_000;
|
|
297
|
+
// Wake when the FIRST dirty module is eligible; flush() skips the others
|
|
298
|
+
// until their own budget allows, then reschedules.
|
|
299
|
+
let earliest = Infinity;
|
|
300
|
+
for (const m of this.dirty)
|
|
301
|
+
earliest = Math.min(earliest, (this.lastRead.get(m) ?? -Infinity) + minGap - now);
|
|
302
|
+
if (!Number.isFinite(earliest))
|
|
303
|
+
earliest = 0;
|
|
304
|
+
const wait = Math.max(delay ?? (this.opts.debounceMs ?? 750), earliest, 0);
|
|
305
|
+
// A pending flush may only be moved EARLIER, never later. A trailing-edge
|
|
306
|
+
// debounce reset on every event can starve a hot mint forever when trades
|
|
307
|
+
// arrive faster than debounceMs, leaving token intelligence permanently stale.
|
|
308
|
+
if (this.timer !== null) {
|
|
309
|
+
if (now + wait >= this.timerAt)
|
|
310
|
+
return;
|
|
311
|
+
clearTimeout(this.timer);
|
|
312
|
+
}
|
|
313
|
+
this.timerAt = now + wait;
|
|
314
|
+
this.timer = setTimeout(() => { this.timer = null; void this.flush(); }, wait);
|
|
315
|
+
}
|
|
316
|
+
async flush() {
|
|
317
|
+
if (this.busy || this.phase === "stopped" || this.dirty.size === 0)
|
|
318
|
+
return;
|
|
319
|
+
if (this.plan.channels.length > 0 && !this.subscribed)
|
|
320
|
+
return;
|
|
321
|
+
const modules = [];
|
|
322
|
+
const now = this.now();
|
|
323
|
+
const minGap = this.opts.minModuleRefreshMs ?? 15_000;
|
|
324
|
+
let cost = 0;
|
|
325
|
+
for (const m of this.dirty) {
|
|
326
|
+
// Newer invalidations may join a timer that was scheduled for an older
|
|
327
|
+
// module. They must still honour their OWN per-module refresh budget.
|
|
328
|
+
if (now < (this.lastRead.get(m) ?? -Infinity) + minGap)
|
|
329
|
+
continue;
|
|
330
|
+
const next = TERMINAL_MODULE_COSTS[m];
|
|
331
|
+
if (modules.length >= 5 || cost + next > 8)
|
|
332
|
+
break;
|
|
333
|
+
modules.push(m);
|
|
334
|
+
cost += next;
|
|
335
|
+
}
|
|
336
|
+
if (!modules.length) {
|
|
337
|
+
this.schedule();
|
|
338
|
+
return;
|
|
339
|
+
}
|
|
340
|
+
for (const m of modules)
|
|
341
|
+
this.dirty.delete(m);
|
|
342
|
+
await this.fetchModules(modules, false);
|
|
343
|
+
}
|
|
344
|
+
async fetchModules(modules, initial) {
|
|
345
|
+
if (this.busy || this.phase === "stopped")
|
|
346
|
+
return;
|
|
347
|
+
this.busy = true;
|
|
348
|
+
// The initial ACK already put all modules in dirty. Consume that batch
|
|
349
|
+
// before the read; a new frame during I/O can add a fresh invalidation.
|
|
350
|
+
for (const m of modules)
|
|
351
|
+
this.dirty.delete(m);
|
|
352
|
+
const epoch = this.epoch;
|
|
353
|
+
const seen = new Map(modules.map(m => [m, this.gen.get(m) ?? 0]));
|
|
354
|
+
const now = this.now();
|
|
355
|
+
for (const m of modules)
|
|
356
|
+
this.lastRead.set(m, now);
|
|
357
|
+
try {
|
|
358
|
+
const incoming = await this.opts.read(modules);
|
|
359
|
+
if (this.isStopped() || epoch !== this.epoch)
|
|
360
|
+
return;
|
|
361
|
+
if (incoming.chain !== this.plan.chain ||
|
|
362
|
+
(this.plan.chain === "solana" ? incoming.address !== this.plan.address :
|
|
363
|
+
incoming.address.toLowerCase() !== this.plan.address))
|
|
364
|
+
throw new Error("snapshot_identity_mismatch");
|
|
365
|
+
if (!incoming.modules || typeof incoming.modules !== "object")
|
|
366
|
+
throw new Error("invalid_snapshot_modules");
|
|
367
|
+
for (const m of modules)
|
|
368
|
+
if (!incoming.modules[m])
|
|
369
|
+
throw new Error("missing_snapshot_module:" + m);
|
|
370
|
+
this.snapshot = this.snapshot && !initial
|
|
371
|
+
? { ...incoming, modules: { ...this.snapshot.modules, ...incoming.modules } }
|
|
372
|
+
: incoming;
|
|
373
|
+
for (const m of modules) {
|
|
374
|
+
if ((this.gen.get(m) ?? 0) === seen.get(m))
|
|
375
|
+
this.stale.delete(m);
|
|
376
|
+
else
|
|
377
|
+
this.dirty.add(m);
|
|
378
|
+
}
|
|
379
|
+
this.lastError = null;
|
|
380
|
+
this.phase = this.incomplete ? "degraded" : "live";
|
|
381
|
+
}
|
|
382
|
+
catch (error) {
|
|
383
|
+
if (this.isStopped() || epoch !== this.epoch)
|
|
384
|
+
return;
|
|
385
|
+
this.lastError = error instanceof Error ? error.message : "snapshot_failed";
|
|
386
|
+
this.markStale(modules);
|
|
387
|
+
this.phase = "degraded";
|
|
388
|
+
// Do not automatically retry a failed DB/RPC call: the next event or an
|
|
389
|
+
// explicit refresh can trigger another, still rate-limited, request.
|
|
390
|
+
}
|
|
391
|
+
finally {
|
|
392
|
+
this.busy = false;
|
|
393
|
+
if (!this.isStopped()) {
|
|
394
|
+
this.emit();
|
|
395
|
+
if (this.pendingBootstrap && this.subscribed) {
|
|
396
|
+
// A reconnect occurred while the old read was busy. Only the NEW
|
|
397
|
+
// post-ACK full snapshot can establish a fresh baseline; a targeted
|
|
398
|
+
// merge onto the old one is not sufficient.
|
|
399
|
+
this.pendingBootstrap = false;
|
|
400
|
+
void this.fetchModules(this.plan.include, true);
|
|
401
|
+
}
|
|
402
|
+
else if (this.dirty.size > 0 && this.subscribed) {
|
|
403
|
+
this.schedule();
|
|
404
|
+
}
|
|
405
|
+
}
|
|
406
|
+
}
|
|
407
|
+
}
|
|
408
|
+
}
|
|
409
|
+
/** A named subscription prevents overwriting an integrator's other filters. */
|
|
410
|
+
export function createTerminalTokenView(options) {
|
|
411
|
+
return new TerminalTokenView(options);
|
|
412
|
+
}
|
|
413
|
+
//# sourceMappingURL=terminal-watch.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"terminal-watch.js","sourceRoot":"","sources":["../src/terminal-watch.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Solana terminal integration over existing REST + managed WebSocket (#534).
|
|
3
|
+
*
|
|
4
|
+
* A shared SDK socket is REQUIRED. We do not open a socket per token widget,
|
|
5
|
+
* and no REST module is refetched on every price tick. Each terminal must use
|
|
6
|
+
* its own explicit named subscription, and each disconnect/replay gap is visible.
|
|
7
|
+
*
|
|
8
|
+
* This adapter does NOT make the selected token's historical capture complete.
|
|
9
|
+
*/
|
|
10
|
+
import type { MadeOnSolREST } from "./index.js";
|
|
11
|
+
import type { MadeOnSolStream } from "./stream.js";
|
|
12
|
+
import type { TokenIntelligenceModuleId } from "./types.js";
|
|
13
|
+
import { type TerminalStreamPort, type TerminalTokenView, type TerminalView, type TerminalStreamFrame } from "./terminal-watch.js";
|
|
14
|
+
import type { TerminalTier, TerminalModule } from "./terminal-policy.js";
|
|
15
|
+
export interface SolanaTerminalWatchOptions {
|
|
16
|
+
/** Caller-selected modules, obeying existing API budget (at most 5, cost <=8). */
|
|
17
|
+
include: readonly TokenIntelligenceModuleId[];
|
|
18
|
+
/** Account's current tier. Server still enforces its authoritative entitlement. */
|
|
19
|
+
tier: TerminalTier;
|
|
20
|
+
/** Reuse ONE existing client.stream() across terminal widgets. */
|
|
21
|
+
stream: MadeOnSolStream;
|
|
22
|
+
/** Unique per shared connection, 1..64 chars, A-Z a-z 0-9 _ . - */
|
|
23
|
+
subId: string;
|
|
24
|
+
/** Subscribe to global, unscoped KOL broadcasts (may be high bandwidth). */
|
|
25
|
+
includeKolBroadcast?: boolean;
|
|
26
|
+
/** Min interval between REST refreshes for any invalidated module. Default 15s. */
|
|
27
|
+
minModuleRefreshMs?: number;
|
|
28
|
+
debounceMs?: number;
|
|
29
|
+
/** Snapshot, stale module names, live overlays and historical gap status. */
|
|
30
|
+
onChange?: (view: TerminalView) => void;
|
|
31
|
+
onLive?: (frame: TerminalStreamFrame, module: TerminalModule) => void;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* The existing stream's public `on` overloads use specific event signatures.
|
|
35
|
+
* Narrowly adapt those overloads to the small event-port used by the shared
|
|
36
|
+
* controller, without changing stream/client behavior.
|
|
37
|
+
*
|
|
38
|
+
* Exported for BROWSER terminals that must not hold an API key: pair it with
|
|
39
|
+
* `createTerminalTokenView({ stream: terminalStreamPort(stream), read })`, where
|
|
40
|
+
* `stream` gets its short-lived token from your backend (`getToken`) and `read`
|
|
41
|
+
* calls your backend, which calls the keyed intelligence endpoint.
|
|
42
|
+
*/
|
|
43
|
+
export declare function terminalStreamPort(stream: MadeOnSolStream): TerminalStreamPort;
|
|
44
|
+
/** Creates an active, terminal-scoped view; returns a handle with dispose(). */
|
|
45
|
+
export declare function createSolanaTerminalWatch(client: MadeOnSolREST, mint: string, options: SolanaTerminalWatchOptions): TerminalTokenView;
|
|
46
|
+
//# sourceMappingURL=terminal.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"terminal.d.ts","sourceRoot":"","sources":["../src/terminal.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAChD,OAAO,KAAK,EAAE,eAAe,EAAiB,MAAM,aAAa,CAAC;AAClE,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,YAAY,CAAC;AAC5D,OAAO,EAA2B,KAAK,kBAAkB,EAAE,KAAK,iBAAiB,EAC/E,KAAK,YAAY,EAAE,KAAK,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAC3E,OAAO,KAAK,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAEzE,MAAM,WAAW,0BAA0B;IACzC,kFAAkF;IAClF,OAAO,EAAE,SAAS,yBAAyB,EAAE,CAAC;IAC9C,mFAAmF;IACnF,IAAI,EAAE,YAAY,CAAC;IACnB,kEAAkE;IAClE,MAAM,EAAE,eAAe,CAAC;IACxB,mEAAmE;IACnE,KAAK,EAAE,MAAM,CAAC;IACd,4EAA4E;IAC5E,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAC9B,mFAAmF;IACnF,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,6EAA6E;IAC7E,QAAQ,CAAC,EAAE,CAAC,IAAI,EAAE,YAAY,KAAK,IAAI,CAAC;IACxC,MAAM,CAAC,EAAE,CAAC,KAAK,EAAE,mBAAmB,EAAE,MAAM,EAAE,cAAc,KAAK,IAAI,CAAC;CACvE;AAED;;;;;;;;;GASG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,eAAe,GAAG,kBAAkB,CAa9E;AAED,gFAAgF;AAChF,wBAAgB,yBAAyB,CACvC,MAAM,EAAE,aAAa,EACrB,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,0BAA0B,GAClC,iBAAiB,CA2BnB"}
|