@johannc-dev/zyrk 0.0.0-stage → 0.2.1
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 +79 -2
- package/dist/build.d.ts +48 -0
- package/dist/build.js +338 -0
- package/dist/cli.d.ts +4 -0
- package/dist/cli.js +295 -0
- package/dist/client.d.ts +212 -0
- package/dist/client.js +909 -0
- package/dist/contracts.d.ts +312 -0
- package/dist/contracts.js +154 -0
- package/dist/errors.d.ts +99 -0
- package/dist/errors.js +63 -0
- package/dist/export.d.ts +96 -0
- package/dist/export.js +422 -0
- package/dist/globals.d.ts +59 -0
- package/dist/hourfile.d.ts +59 -0
- package/dist/hourfile.js +345 -0
- package/dist/limits.d.ts +91 -0
- package/dist/limits.js +54 -0
- package/dist/local-data.d.ts +115 -0
- package/dist/local-data.js +373 -0
- package/dist/local-replay.d.ts +40 -0
- package/dist/local-replay.js +343 -0
- package/dist/local-storage.d.ts +76 -0
- package/dist/local-storage.js +499 -0
- package/dist/local.d.ts +235 -0
- package/dist/local.js +1147 -0
- package/dist/sandbox-bootstrap.js +681 -0
- package/dist/sdk.d.ts +1152 -0
- package/dist/sdk.js +210 -0
- package/dist/stream.d.ts +84 -0
- package/dist/stream.js +167 -0
- package/dist/webhook.d.ts +43 -0
- package/dist/webhook.js +54 -0
- package/package.json +56 -4
|
@@ -0,0 +1,343 @@
|
|
|
1
|
+
import { readFileSync } from "node:fs";
|
|
2
|
+
import { join } from "node:path";
|
|
3
|
+
import { batchOf, decompressHour } from "./hourfile.js";
|
|
4
|
+
import { HOUR_MS, readId, } from "./local-data.js";
|
|
5
|
+
import { MarketEvent, MarketFlag, NO_EVENT_INDEX, NO_TX_ID, NO_TX_INDEX, TxFlag, txFlagNames, OrderFlag, } from "./sdk.js";
|
|
6
|
+
export const LAG_MS = 30_000;
|
|
7
|
+
export const DELIVERY_BATCH = 32;
|
|
8
|
+
export const REPLAY_MAX_BATCH = 1000;
|
|
9
|
+
export const SOURCE_PAGE = 500;
|
|
10
|
+
export const MISSING_OPERATION_FIELDS = [
|
|
11
|
+
"prices (provider strings: read batch.price… instead)",
|
|
12
|
+
"usdValue",
|
|
13
|
+
"finality",
|
|
14
|
+
"provenance",
|
|
15
|
+
"market (the provider's raw object)",
|
|
16
|
+
];
|
|
17
|
+
const ORDER_FLAG_NAMES = Object.entries(OrderFlag);
|
|
18
|
+
const POOL_KINDS = new Map(Object.entries(MarketEvent)
|
|
19
|
+
.filter(([, v]) => v >= 1 && v <= 5)
|
|
20
|
+
.map(([k, v]) => [v, k]));
|
|
21
|
+
export function formatRaw(raw, decimals) {
|
|
22
|
+
if (decimals === 0)
|
|
23
|
+
return raw.toString();
|
|
24
|
+
const s = raw.toString().padStart(decimals + 1, "0");
|
|
25
|
+
const whole = s.slice(0, -decimals);
|
|
26
|
+
const frac = s.slice(-decimals).replace(/0+$/, "");
|
|
27
|
+
return frac ? `${whole}.${frac}` : whole;
|
|
28
|
+
}
|
|
29
|
+
const addressAt = (b, index) => index === undefined || index < 0 ? null : (b.addresses[index] ?? null);
|
|
30
|
+
const orNull = (v) => v === undefined || Number.isNaN(v) ? null : v;
|
|
31
|
+
export function operationOf(b, i) {
|
|
32
|
+
const ord = `${b.hour}:${b.line[i]}:${b.op[i]}`;
|
|
33
|
+
const o = b.order;
|
|
34
|
+
const known = o !== undefined && o.txIndex[i] !== NO_TX_INDEX;
|
|
35
|
+
const flags = o?.flags[i] ?? OrderFlag.unknownNotCovered;
|
|
36
|
+
const t = b.tx;
|
|
37
|
+
const txId = t?.id[i] ?? NO_TX_ID;
|
|
38
|
+
const txKnown = txId !== NO_TX_ID;
|
|
39
|
+
return {
|
|
40
|
+
id: ord,
|
|
41
|
+
mint: addressAt(b, b.mint[i]) ?? "",
|
|
42
|
+
pool: addressAt(b, b.pool[i]),
|
|
43
|
+
protocol: b.protocol[i] === 1 ? "pumpswap" : "pumpfun",
|
|
44
|
+
trader: addressAt(b, b.trader[i]),
|
|
45
|
+
signature: b.signatures?.[i] ?? null,
|
|
46
|
+
side: b.side[i] === 1 ? "sell" : "buy",
|
|
47
|
+
token: {
|
|
48
|
+
raw: b.tokenRaw[i].toString(),
|
|
49
|
+
amount: formatRaw(b.tokenRaw[i], b.tokenDecimals[i]),
|
|
50
|
+
decimals: b.tokenDecimals[i],
|
|
51
|
+
},
|
|
52
|
+
quote: {
|
|
53
|
+
mint: addressAt(b, b.quoteMint[i]) ?? "",
|
|
54
|
+
raw: b.quoteRaw[i].toString(),
|
|
55
|
+
amount: formatRaw(b.quoteRaw[i], b.quoteDecimals[i]),
|
|
56
|
+
decimals: b.quoteDecimals[i],
|
|
57
|
+
},
|
|
58
|
+
time: {
|
|
59
|
+
ms: b.timeMs[i],
|
|
60
|
+
precision: "provider_timestamp_ms",
|
|
61
|
+
receivedMs: orNull(b.receivedMs[i]),
|
|
62
|
+
},
|
|
63
|
+
order: {
|
|
64
|
+
slot: b.slot[i],
|
|
65
|
+
ord,
|
|
66
|
+
basis: "provider_hour_line_operation",
|
|
67
|
+
txIndex: known ? o.txIndex[i] : null,
|
|
68
|
+
eventIndex: known && o.eventIndex[i] !== NO_EVENT_INDEX ? o.eventIndex[i] : null,
|
|
69
|
+
blockTimeMs: o ? orNull(o.blockTimeMs[i]) : null,
|
|
70
|
+
flags: ORDER_FLAG_NAMES.filter(([, bit]) => (flags & bit) !== 0).map(([name]) => name),
|
|
71
|
+
},
|
|
72
|
+
tx: {
|
|
73
|
+
id: txKnown ? txId : null,
|
|
74
|
+
index: txKnown ? t.index[i] : null,
|
|
75
|
+
flags: txFlagNames(t?.flags[i] ?? TxFlag.unknown),
|
|
76
|
+
},
|
|
77
|
+
publishSeq: null,
|
|
78
|
+
cumulativeQuoteRawAfter: null,
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
function poolEventOf(b, i, kind) {
|
|
82
|
+
const m = b.market;
|
|
83
|
+
const flags = m.flags[i];
|
|
84
|
+
const reserves = (flags & MarketFlag.reserves) !== 0;
|
|
85
|
+
const vToken = (flags & MarketFlag.virtualTokenReserve) !== 0;
|
|
86
|
+
const vQuote = (flags & MarketFlag.virtualQuoteReserve) !== 0;
|
|
87
|
+
const op = operationOf(b, i);
|
|
88
|
+
return {
|
|
89
|
+
...op,
|
|
90
|
+
type: "poolEvent",
|
|
91
|
+
kind,
|
|
92
|
+
code: m.event[i],
|
|
93
|
+
trader: kind === "add" || kind === "remove" ? op.trader : null,
|
|
94
|
+
market: {
|
|
95
|
+
tokenReserveRaw: reserves ? m.tokenReserve[i].toString() : null,
|
|
96
|
+
quoteReserveRaw: reserves ? m.quoteReserve[i].toString() : null,
|
|
97
|
+
virtualTokenReserveRaw: vToken
|
|
98
|
+
? m.virtualTokenReserve[i].toString()
|
|
99
|
+
: null,
|
|
100
|
+
virtualQuoteReserveRaw: vQuote
|
|
101
|
+
? m.virtualQuoteReserve[i].toString()
|
|
102
|
+
: null,
|
|
103
|
+
signer: addressAt(b, m.signer[i]),
|
|
104
|
+
},
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
function hourRows(b, since, until) {
|
|
108
|
+
const rows = [];
|
|
109
|
+
for (let i = 0; i < b.length; i++) {
|
|
110
|
+
const t = b.timeMs[i];
|
|
111
|
+
if (t >= since && t < until)
|
|
112
|
+
rows.push(i);
|
|
113
|
+
}
|
|
114
|
+
const o = b.order;
|
|
115
|
+
if (!o)
|
|
116
|
+
return rows.sort((x, y) => b.line[x] - b.line[y] || b.op[x] - b.op[y]);
|
|
117
|
+
const lineFirst = new Map();
|
|
118
|
+
for (let i = 0; i < b.length; i++)
|
|
119
|
+
if (b.side[i] !== 2) {
|
|
120
|
+
const at = lineFirst.get(b.line[i]);
|
|
121
|
+
if (at === undefined || b.op[i] < b.op[at])
|
|
122
|
+
lineFirst.set(b.line[i], i);
|
|
123
|
+
}
|
|
124
|
+
const pos = (i) => {
|
|
125
|
+
const j = b.side[i] === 2 ? (lineFirst.get(b.line[i]) ?? i) : i;
|
|
126
|
+
return [b.slot[j], o.txIndex[j], o.eventIndex[j]];
|
|
127
|
+
};
|
|
128
|
+
return rows.sort((x, y) => {
|
|
129
|
+
const p = pos(x);
|
|
130
|
+
const q = pos(y);
|
|
131
|
+
return (p[0] - q[0] ||
|
|
132
|
+
p[1] - q[1] ||
|
|
133
|
+
p[2] - q[2] ||
|
|
134
|
+
b.line[x] - b.line[y] ||
|
|
135
|
+
b.op[x] - b.op[y]);
|
|
136
|
+
});
|
|
137
|
+
}
|
|
138
|
+
class Windows {
|
|
139
|
+
#covered = null;
|
|
140
|
+
#series = new Map();
|
|
141
|
+
reset() {
|
|
142
|
+
this.#series.clear();
|
|
143
|
+
this.#covered = null;
|
|
144
|
+
}
|
|
145
|
+
push(key, time, seq, raw) {
|
|
146
|
+
let s = this.#series.get(key);
|
|
147
|
+
if (!s)
|
|
148
|
+
this.#series.set(key, (s = { points: [] }));
|
|
149
|
+
const last = s.points[s.points.length - 1];
|
|
150
|
+
const t = Math.max(time, last?.time ?? 0, 0);
|
|
151
|
+
s.points.push({ time: t, seq, cum: (last?.cum ?? 0n) + raw });
|
|
152
|
+
this.#covered ??= t + LAG_MS;
|
|
153
|
+
}
|
|
154
|
+
lookup(key, seq, windowMs) {
|
|
155
|
+
const s = this.#series.get(key);
|
|
156
|
+
if (!s || this.#covered === null)
|
|
157
|
+
return null;
|
|
158
|
+
const i = s.points.findIndex((p) => p.seq === seq);
|
|
159
|
+
if (i < 0)
|
|
160
|
+
return null;
|
|
161
|
+
const entry = s.points[i];
|
|
162
|
+
const start = entry.time - windowMs;
|
|
163
|
+
if (start < this.#covered)
|
|
164
|
+
return null;
|
|
165
|
+
let j = 0;
|
|
166
|
+
while (j < s.points.length && s.points[j].time <= start)
|
|
167
|
+
j++;
|
|
168
|
+
const atStart = j === 0 ? 0n : s.points[j - 1].cum;
|
|
169
|
+
const previous = i === 0 ? 0n : s.points[i - 1].cum;
|
|
170
|
+
return { before: previous - atStart, after: entry.cum - atStart };
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
const gapEvent = (reason, from, to, after) => ({
|
|
174
|
+
kind: "gap",
|
|
175
|
+
reason,
|
|
176
|
+
fromMs: from,
|
|
177
|
+
toMs: to,
|
|
178
|
+
after,
|
|
179
|
+
});
|
|
180
|
+
export function replayEvents(data, meta, sub, since, until, progress) {
|
|
181
|
+
const t = sub.trigger;
|
|
182
|
+
const out = [];
|
|
183
|
+
const cov = meta.coverage ?? {};
|
|
184
|
+
const gaps = [];
|
|
185
|
+
const horizon = cov.retentionHorizonMs ?? 0;
|
|
186
|
+
if (since < horizon)
|
|
187
|
+
gaps.push([since, Math.min(horizon, until), "retention"]);
|
|
188
|
+
for (const g of cov.gaps ?? []) {
|
|
189
|
+
const from = Math.max(g.fromMs ?? since, since);
|
|
190
|
+
const to = Math.min(g.toMs ?? until, until);
|
|
191
|
+
if (from < to)
|
|
192
|
+
gaps.push([from, to, "history_gap"]);
|
|
193
|
+
}
|
|
194
|
+
const sealed = cov.sealedUntilMs ?? Number.MAX_SAFE_INTEGER;
|
|
195
|
+
if (sealed < until)
|
|
196
|
+
gaps.push([Math.max(sealed, since), until, "not_sealed"]);
|
|
197
|
+
gaps.sort((a, b) => a[0] - b[0] || a[1] - b[1] || (a[2] < b[2] ? -1 : 1));
|
|
198
|
+
let seq = 0;
|
|
199
|
+
const totals = new Map();
|
|
200
|
+
const windows = t.kind === "volume" && t.windowMs !== undefined ? new Windows() : null;
|
|
201
|
+
let lastItem = null;
|
|
202
|
+
let run = null;
|
|
203
|
+
const closeRun = () => {
|
|
204
|
+
if (run && lastItem)
|
|
205
|
+
out.push({
|
|
206
|
+
event: {
|
|
207
|
+
kind: "gap",
|
|
208
|
+
reason: "window_not_observed",
|
|
209
|
+
after: run.first - 1,
|
|
210
|
+
resumeAfter: lastItem.seq,
|
|
211
|
+
missed: run.missed,
|
|
212
|
+
},
|
|
213
|
+
time: lastItem.time,
|
|
214
|
+
gap: true,
|
|
215
|
+
});
|
|
216
|
+
run = null;
|
|
217
|
+
};
|
|
218
|
+
const gapsUntil = (time) => {
|
|
219
|
+
if (gaps.length && gaps[0][0] <= time)
|
|
220
|
+
closeRun();
|
|
221
|
+
while (gaps.length && gaps[0][0] <= time) {
|
|
222
|
+
const [from, to, reason] = gaps.shift();
|
|
223
|
+
out.push({
|
|
224
|
+
event: gapEvent(reason, from, to, seq),
|
|
225
|
+
time: from,
|
|
226
|
+
gap: true,
|
|
227
|
+
});
|
|
228
|
+
seq++;
|
|
229
|
+
windows?.reset();
|
|
230
|
+
for (const v of totals.values())
|
|
231
|
+
v.complete = false;
|
|
232
|
+
progress.gaps++;
|
|
233
|
+
}
|
|
234
|
+
};
|
|
235
|
+
const id = readId(meta, meta.sinceMs, meta.untilMs);
|
|
236
|
+
const first = Math.floor(since / HOUR_MS) - 1;
|
|
237
|
+
const last = Math.floor((until - 1) / HOUR_MS) + 1;
|
|
238
|
+
for (const hour of meta.hours) {
|
|
239
|
+
if (hour < first || hour > last)
|
|
240
|
+
continue;
|
|
241
|
+
const b = batchOf(decompressHour(readFileSync(join(data.dir, "reads", id, `${hour}.zhb`))));
|
|
242
|
+
if (b.skipped > 0)
|
|
243
|
+
for (const v of totals.values())
|
|
244
|
+
v.complete = false;
|
|
245
|
+
for (const i of hourRows(b, since, until)) {
|
|
246
|
+
const time = b.timeMs[i];
|
|
247
|
+
gapsUntil(time);
|
|
248
|
+
seq++;
|
|
249
|
+
progress.eventsRead++;
|
|
250
|
+
const event = b.side[i] === 2;
|
|
251
|
+
const kind = event ? POOL_KINDS.get(b.market?.event[i] ?? 0) : undefined;
|
|
252
|
+
if (event && !kind)
|
|
253
|
+
continue;
|
|
254
|
+
const item = event ? poolEventOf(b, i, kind) : operationOf(b, i);
|
|
255
|
+
item.publishSeq = seq;
|
|
256
|
+
const fallback = item.order.txIndex === null;
|
|
257
|
+
const mint = item.mint;
|
|
258
|
+
const quote = item.quote.mint;
|
|
259
|
+
if (!event) {
|
|
260
|
+
const key = `${mint}/${quote}`;
|
|
261
|
+
const create = b.market !== undefined &&
|
|
262
|
+
(b.market.flags[i] & MarketFlag.creatorInitialBuy) !== 0;
|
|
263
|
+
if (create && !totals.has(key))
|
|
264
|
+
totals.set(key, { total: 0n, complete: true });
|
|
265
|
+
const v = totals.get(key);
|
|
266
|
+
if (v)
|
|
267
|
+
v.total += b.quoteRaw[i];
|
|
268
|
+
item.cumulativeQuoteRawAfter = v ? v.total.toString() : null;
|
|
269
|
+
item.sinceCreationComplete = v?.complete ?? false;
|
|
270
|
+
item.signalEligible = true;
|
|
271
|
+
windows?.push(key, time, seq, b.quoteRaw[i]);
|
|
272
|
+
}
|
|
273
|
+
const classified = [];
|
|
274
|
+
if (t.kind === "poolEvent") {
|
|
275
|
+
if (event &&
|
|
276
|
+
(!t.mint || t.mint === mint) &&
|
|
277
|
+
(!t.events || t.events.includes(kind)))
|
|
278
|
+
classified.push({ kind: "poolEvent", event: item });
|
|
279
|
+
}
|
|
280
|
+
else if (!event && t.kind === "trade") {
|
|
281
|
+
if ((!t.mint || t.mint === mint) &&
|
|
282
|
+
(!t.wallet || t.wallet === item.trader))
|
|
283
|
+
classified.push({ kind: "trade", operation: item });
|
|
284
|
+
}
|
|
285
|
+
else if (!event && t.kind === "volume") {
|
|
286
|
+
const threshold = BigInt(t.thresholdRaw);
|
|
287
|
+
if ((!t.mint || t.mint === mint) && (!t.quote || t.quote === quote)) {
|
|
288
|
+
if (t.windowMs === undefined) {
|
|
289
|
+
const total = item.cumulativeQuoteRawAfter === null
|
|
290
|
+
? null
|
|
291
|
+
: BigInt(item.cumulativeQuoteRawAfter);
|
|
292
|
+
const amount = b.quoteRaw[i];
|
|
293
|
+
if (total !== null &&
|
|
294
|
+
item.sinceCreationComplete === true &&
|
|
295
|
+
total < threshold + amount &&
|
|
296
|
+
threshold <= total)
|
|
297
|
+
classified.push({ kind: "volume", operation: item });
|
|
298
|
+
}
|
|
299
|
+
else {
|
|
300
|
+
const w = windows.lookup(`${mint}/${quote}`, seq, t.windowMs);
|
|
301
|
+
if (!w) {
|
|
302
|
+
run ??= { first: seq, missed: 0 };
|
|
303
|
+
run.missed++;
|
|
304
|
+
}
|
|
305
|
+
else {
|
|
306
|
+
closeRun();
|
|
307
|
+
if (w.before < threshold && threshold <= w.after)
|
|
308
|
+
classified.push({
|
|
309
|
+
kind: "volume",
|
|
310
|
+
operation: item,
|
|
311
|
+
windowMs: t.windowMs,
|
|
312
|
+
windowQuoteRaw: w.after.toString(),
|
|
313
|
+
});
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
for (const e of classified) {
|
|
319
|
+
if (fallback) {
|
|
320
|
+
e.orderFallback = true;
|
|
321
|
+
progress.orderFallbacks++;
|
|
322
|
+
}
|
|
323
|
+
out.push({ event: e, time, gap: false });
|
|
324
|
+
}
|
|
325
|
+
lastItem = { seq, time };
|
|
326
|
+
if (progress.eventsRead % SOURCE_PAGE === 0)
|
|
327
|
+
closeRun();
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
closeRun();
|
|
331
|
+
gapsUntil(Number.MAX_SAFE_INTEGER);
|
|
332
|
+
return out;
|
|
333
|
+
}
|
|
334
|
+
export function intervalEvents(everyMs, since, until) {
|
|
335
|
+
const out = [];
|
|
336
|
+
for (let at = since; at < until; at += everyMs)
|
|
337
|
+
out.push({
|
|
338
|
+
event: { kind: "interval", scheduledAt: at },
|
|
339
|
+
time: at,
|
|
340
|
+
gap: false,
|
|
341
|
+
});
|
|
342
|
+
return out;
|
|
343
|
+
}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
/** Defaults of `storageLimits` in the user-storage branch. */
|
|
2
|
+
export declare const localStorageLimits: {
|
|
3
|
+
readonly maxObjectBytes: number;
|
|
4
|
+
readonly chunkBytes: number;
|
|
5
|
+
readonly maxKeyBytes: 512;
|
|
6
|
+
readonly maxMetadataEntries: 16;
|
|
7
|
+
readonly maxMetadataBytes: 4096;
|
|
8
|
+
readonly maxList: 1000;
|
|
9
|
+
readonly maxUploads: 4;
|
|
10
|
+
/** Bytes read plus written by one execution (`io_limit`). */
|
|
11
|
+
readonly ioBytes: number;
|
|
12
|
+
/** Quota cost floor of one object. */
|
|
13
|
+
readonly minObjectBytes: 4096;
|
|
14
|
+
/** Objects per area. */
|
|
15
|
+
readonly maxObjects: 100000;
|
|
16
|
+
};
|
|
17
|
+
export interface AreaConfig {
|
|
18
|
+
readonly quotaBytes: number;
|
|
19
|
+
/** `null`: objects never expire (`durable`). */
|
|
20
|
+
readonly ttlMs: number | null;
|
|
21
|
+
}
|
|
22
|
+
/** The service's defaults; add an area here to test another one. */
|
|
23
|
+
export declare const defaultAreas: Readonly<Record<string, AreaConfig>>;
|
|
24
|
+
export declare class StorageOpError extends Error {
|
|
25
|
+
readonly kind: "program" | "limit" | "infrastructure";
|
|
26
|
+
readonly code: string;
|
|
27
|
+
constructor(kind: "program" | "limit" | "infrastructure", code: string, message: string);
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* The storage areas of one local account. `dir` keeps them between runs
|
|
31
|
+
* (`<dir>/<area>/index.json` and one file per object); without it they live
|
|
32
|
+
* in memory.
|
|
33
|
+
*/
|
|
34
|
+
export declare class LocalStorage {
|
|
35
|
+
#private;
|
|
36
|
+
readonly dir?: string | undefined;
|
|
37
|
+
readonly areas: Readonly<Record<string, AreaConfig>>;
|
|
38
|
+
readonly now: () => number;
|
|
39
|
+
/**
|
|
40
|
+
* A replay's space: every area counts in one quota (the account's
|
|
41
|
+
* `short`), together with `outside()` bytes the account already uses.
|
|
42
|
+
*/
|
|
43
|
+
readonly shared?: {
|
|
44
|
+
quotaBytes: number;
|
|
45
|
+
outside: () => number;
|
|
46
|
+
} | undefined;
|
|
47
|
+
constructor(dir?: string | undefined, areas?: Readonly<Record<string, AreaConfig>>, now?: () => number,
|
|
48
|
+
/**
|
|
49
|
+
* A replay's space: every area counts in one quota (the account's
|
|
50
|
+
* `short`), together with `outside()` bytes the account already uses.
|
|
51
|
+
*/
|
|
52
|
+
shared?: {
|
|
53
|
+
quotaBytes: number;
|
|
54
|
+
outside: () => number;
|
|
55
|
+
} | undefined);
|
|
56
|
+
/** Committed and reserved bytes of an area (what its quota counts). */
|
|
57
|
+
usedBytes(area: string): number;
|
|
58
|
+
/**
|
|
59
|
+
* Copies the live objects of `from` in `source` (a replay's space), or
|
|
60
|
+
* only `keys` (absent ones skipped), to area `to` here, within its quota:
|
|
61
|
+
* refused as a whole (`quota_exceeded`, nothing copied) when they do not fit.
|
|
62
|
+
*/
|
|
63
|
+
copyFrom(source: LocalStorage, from: string, to: string, keys?: readonly string[]): {
|
|
64
|
+
objects: number;
|
|
65
|
+
bytes: number;
|
|
66
|
+
};
|
|
67
|
+
/** Uploads of an execution that did not commit are dropped when it ends. */
|
|
68
|
+
endExecution(owner: string): void;
|
|
69
|
+
/**
|
|
70
|
+
* One `Storage*` host operation of execution `owner`. `io` counts the bytes
|
|
71
|
+
* moved by the execution (`io_limit`).
|
|
72
|
+
*/
|
|
73
|
+
op(name: string, a: Record<string, unknown>, owner: string, io: {
|
|
74
|
+
bytes: number;
|
|
75
|
+
}): unknown;
|
|
76
|
+
}
|