@johannc-dev/zyrk 0.0.0-stage → 0.2.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 +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 +208 -0
- package/dist/client.js +416 -0
- package/dist/contracts.d.ts +312 -0
- package/dist/contracts.js +154 -0
- package/dist/errors.d.ts +91 -0
- package/dist/errors.js +58 -0
- package/dist/export.d.ts +87 -0
- package/dist/export.js +338 -0
- package/dist/globals.d.ts +59 -0
- package/dist/hourfile.d.ts +57 -0
- package/dist/hourfile.js +338 -0
- package/dist/limits.d.ts +91 -0
- package/dist/limits.js +54 -0
- package/dist/local-data.d.ts +106 -0
- package/dist/local-data.js +345 -0
- package/dist/local-replay.d.ts +40 -0
- package/dist/local-replay.js +342 -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 +1133 -0
- package/dist/sandbox-bootstrap.js +519 -0
- package/dist/sdk.d.ts +1129 -0
- package/dist/sdk.js +208 -0
- package/dist/stream.d.ts +36 -0
- package/dist/stream.js +69 -0
- package/dist/webhook.d.ts +43 -0
- package/dist/webhook.js +54 -0
- package/package.json +56 -4
|
@@ -0,0 +1,519 @@
|
|
|
1
|
+
(function(N) {
|
|
2
|
+
"use strict";
|
|
3
|
+
const g = globalThis;
|
|
4
|
+
const stringify = JSON.stringify.bind(JSON);
|
|
5
|
+
const parse = JSON.parse.bind(JSON);
|
|
6
|
+
const freeze = Object.freeze;
|
|
7
|
+
const keys = Object.keys;
|
|
8
|
+
const entries = Object.entries;
|
|
9
|
+
const hasOwn = Object.prototype.hasOwnProperty;
|
|
10
|
+
const isArray = Array.isArray;
|
|
11
|
+
const ErrorCtor = Error;
|
|
12
|
+
const StringCtor = String;
|
|
13
|
+
const asyncIterator = Symbol.asyncIterator;
|
|
14
|
+
const fail = N.fail;
|
|
15
|
+
const typeOf = (v) => v === null ? "null" : typeof v;
|
|
16
|
+
for (const name of ["WebAssembly", "SharedArrayBuffer", "FinalizationRegistry"])
|
|
17
|
+
delete g[name];
|
|
18
|
+
const define = (name, value) => Object.defineProperty(g, name, { value, writable: true, configurable: true, enumerable: false });
|
|
19
|
+
const jsonSafe = (v) => {
|
|
20
|
+
if (v instanceof ErrorCtor) return StringCtor(v.stack ?? v);
|
|
21
|
+
try {
|
|
22
|
+
const text = stringify(v, (_k, x) => typeof x === "bigint" ? x.toString() : x);
|
|
23
|
+
return text === void 0 ? StringCtor(v) : parse(text);
|
|
24
|
+
} catch {
|
|
25
|
+
return StringCtor(v);
|
|
26
|
+
}
|
|
27
|
+
};
|
|
28
|
+
const print = (...args) => {
|
|
29
|
+
const value = args.length === 1 ? jsonSafe(args[0]) : args.map(jsonSafe);
|
|
30
|
+
N.op(stringify({ Log: { value } }), false);
|
|
31
|
+
};
|
|
32
|
+
define(
|
|
33
|
+
"console",
|
|
34
|
+
freeze({ log: print, info: print, warn: print, error: print, debug: print, trace: print })
|
|
35
|
+
);
|
|
36
|
+
class TextEncoder {
|
|
37
|
+
get encoding() {
|
|
38
|
+
return "utf-8";
|
|
39
|
+
}
|
|
40
|
+
encode(input = "") {
|
|
41
|
+
return N.encode(StringCtor(input));
|
|
42
|
+
}
|
|
43
|
+
encodeInto(input, dest) {
|
|
44
|
+
if (!(dest instanceof Uint8Array)) throw new TypeError("encodeInto expects a Uint8Array");
|
|
45
|
+
const text = StringCtor(input);
|
|
46
|
+
let read = 0;
|
|
47
|
+
let written = 0;
|
|
48
|
+
for (const ch of text) {
|
|
49
|
+
const bytes = N.encode(ch);
|
|
50
|
+
if (written + bytes.length > dest.length) break;
|
|
51
|
+
dest.set(bytes, written);
|
|
52
|
+
written += bytes.length;
|
|
53
|
+
read += ch.length;
|
|
54
|
+
}
|
|
55
|
+
return { read, written };
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
class TextDecoder {
|
|
59
|
+
#fatal;
|
|
60
|
+
#ignoreBOM;
|
|
61
|
+
constructor(label = "utf-8", options = {}) {
|
|
62
|
+
const name = StringCtor(label).trim().toLowerCase();
|
|
63
|
+
if (name !== "utf-8" && name !== "utf8" && name !== "unicode-1-1-utf-8")
|
|
64
|
+
throw new RangeError("Only utf-8 is supported");
|
|
65
|
+
this.#fatal = !!(options && options.fatal);
|
|
66
|
+
this.#ignoreBOM = !!(options && options.ignoreBOM);
|
|
67
|
+
}
|
|
68
|
+
get encoding() {
|
|
69
|
+
return "utf-8";
|
|
70
|
+
}
|
|
71
|
+
get fatal() {
|
|
72
|
+
return this.#fatal;
|
|
73
|
+
}
|
|
74
|
+
get ignoreBOM() {
|
|
75
|
+
return this.#ignoreBOM;
|
|
76
|
+
}
|
|
77
|
+
decode(input = new Uint8Array(0), options = {}) {
|
|
78
|
+
if (options && options.stream) throw new TypeError("Streaming decode is not supported");
|
|
79
|
+
let view;
|
|
80
|
+
if (input instanceof ArrayBuffer) view = new Uint8Array(input);
|
|
81
|
+
else if (ArrayBuffer.isView(input))
|
|
82
|
+
view = new Uint8Array(input.buffer, input.byteOffset, input.byteLength);
|
|
83
|
+
else throw new TypeError("decode expects an ArrayBuffer or a view");
|
|
84
|
+
return N.decode(view, this.#fatal, this.#ignoreBOM);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
define("TextEncoder", TextEncoder);
|
|
88
|
+
define("TextDecoder", TextDecoder);
|
|
89
|
+
const cloneError = (message) => {
|
|
90
|
+
const e = new ErrorCtor(message);
|
|
91
|
+
e.name = "DataCloneError";
|
|
92
|
+
return e;
|
|
93
|
+
};
|
|
94
|
+
const TypedArray = Object.getPrototypeOf(Uint8Array);
|
|
95
|
+
const structuredClone = (value) => {
|
|
96
|
+
const seen = /* @__PURE__ */ new Map();
|
|
97
|
+
const walk = (v) => {
|
|
98
|
+
const t = typeof v;
|
|
99
|
+
if (t === "function" || t === "symbol") throw cloneError(t + " cannot be cloned");
|
|
100
|
+
if (v === null || t !== "object") return v;
|
|
101
|
+
if (seen.has(v)) return seen.get(v);
|
|
102
|
+
let out;
|
|
103
|
+
if (isArray(v)) {
|
|
104
|
+
out = new Array(v.length);
|
|
105
|
+
seen.set(v, out);
|
|
106
|
+
for (const k of keys(v)) out[k] = walk(v[k]);
|
|
107
|
+
return out;
|
|
108
|
+
}
|
|
109
|
+
if (v instanceof Date) out = new Date(v.getTime());
|
|
110
|
+
else if (v instanceof RegExp) out = new RegExp(v.source, v.flags);
|
|
111
|
+
else if (v instanceof ArrayBuffer) out = v.slice(0);
|
|
112
|
+
else if (v instanceof TypedArray) {
|
|
113
|
+
const buffer = walk(v.buffer);
|
|
114
|
+
out = new v.constructor(buffer, v.byteOffset, v.length);
|
|
115
|
+
} else if (v instanceof DataView) out = new DataView(walk(v.buffer), v.byteOffset, v.byteLength);
|
|
116
|
+
else if (v instanceof Boolean) out = new Boolean(v.valueOf());
|
|
117
|
+
else if (v instanceof Number) out = new Number(v.valueOf());
|
|
118
|
+
else if (v instanceof StringCtor) out = new StringCtor(v.valueOf());
|
|
119
|
+
else if (v instanceof Map) {
|
|
120
|
+
out = /* @__PURE__ */ new Map();
|
|
121
|
+
seen.set(v, out);
|
|
122
|
+
for (const [k, x] of v) out.set(walk(k), walk(x));
|
|
123
|
+
return out;
|
|
124
|
+
} else if (v instanceof Set) {
|
|
125
|
+
out = /* @__PURE__ */ new Set();
|
|
126
|
+
seen.set(v, out);
|
|
127
|
+
for (const x of v) out.add(walk(x));
|
|
128
|
+
return out;
|
|
129
|
+
} else if (v instanceof ErrorCtor) {
|
|
130
|
+
out = new ErrorCtor(v.message);
|
|
131
|
+
out.name = v.name;
|
|
132
|
+
if (v.stack !== void 0) out.stack = v.stack;
|
|
133
|
+
} else if (v instanceof Promise || v instanceof WeakMap || v instanceof WeakSet || v instanceof WeakRef)
|
|
134
|
+
throw cloneError("This object cannot be cloned");
|
|
135
|
+
else {
|
|
136
|
+
out = {};
|
|
137
|
+
seen.set(v, out);
|
|
138
|
+
for (const k of keys(v)) out[k] = walk(v[k]);
|
|
139
|
+
return out;
|
|
140
|
+
}
|
|
141
|
+
seen.set(v, out);
|
|
142
|
+
return out;
|
|
143
|
+
};
|
|
144
|
+
return walk(value);
|
|
145
|
+
};
|
|
146
|
+
define("structuredClone", structuredClone);
|
|
147
|
+
define(
|
|
148
|
+
"crypto",
|
|
149
|
+
freeze({
|
|
150
|
+
getRandomValues(array) {
|
|
151
|
+
N.random(array);
|
|
152
|
+
return array;
|
|
153
|
+
}
|
|
154
|
+
})
|
|
155
|
+
);
|
|
156
|
+
const PromiseCtor = Promise;
|
|
157
|
+
const call = (op) => {
|
|
158
|
+
let text;
|
|
159
|
+
try {
|
|
160
|
+
text = stringify(op);
|
|
161
|
+
} catch (e) {
|
|
162
|
+
return PromiseCtor.reject(fail("invalid_argument", "Not JSON: " + StringCtor(e && e.message)));
|
|
163
|
+
}
|
|
164
|
+
return N.op(text, true);
|
|
165
|
+
};
|
|
166
|
+
const checkWindow = (w) => {
|
|
167
|
+
if (typeOf(w) !== "object") throw fail("invalid_argument", "Expected a window { sinceMs, untilMs }");
|
|
168
|
+
const since = w.sinceMs;
|
|
169
|
+
const until = w.untilMs;
|
|
170
|
+
const rawSide = w.side;
|
|
171
|
+
const allowPartial = !!w.allowPartial;
|
|
172
|
+
const withSignatures = !!w.withSignatures;
|
|
173
|
+
const withMarket = !!w.withMarket;
|
|
174
|
+
const withEvents = !!w.withEvents;
|
|
175
|
+
const withOrder = !!w.withOrder;
|
|
176
|
+
const withTx = !!w.withTx;
|
|
177
|
+
if (typeof since !== "number" || typeof until !== "number")
|
|
178
|
+
throw fail("invalid_argument", "sinceMs and untilMs must be numbers (ms since epoch)");
|
|
179
|
+
const side = rawSide === void 0 ? "any" : rawSide;
|
|
180
|
+
if (side !== "any" && side !== "buy" && side !== "sell")
|
|
181
|
+
throw fail("invalid_argument", 'side must be "buy" or "sell"');
|
|
182
|
+
return { since, until, side, allowPartial, withSignatures, withMarket, withEvents, withOrder, withTx };
|
|
183
|
+
};
|
|
184
|
+
const trades = (kind) => (key, w) => {
|
|
185
|
+
if (typeof key !== "string") throw fail("invalid_argument", "Expected an address string");
|
|
186
|
+
const { since, until, side, allowPartial, withSignatures, withMarket, withEvents, withOrder, withTx } = checkWindow(w);
|
|
187
|
+
return freeze({
|
|
188
|
+
[asyncIterator]() {
|
|
189
|
+
let after = null;
|
|
190
|
+
let done = false;
|
|
191
|
+
return {
|
|
192
|
+
async next() {
|
|
193
|
+
if (done) return { done: true, value: void 0 };
|
|
194
|
+
const batch = N.read(kind, key, since, until, side, allowPartial, withSignatures, after, withMarket, withEvents, withOrder, withTx);
|
|
195
|
+
if (batch === null) {
|
|
196
|
+
done = true;
|
|
197
|
+
return { done: true, value: void 0 };
|
|
198
|
+
}
|
|
199
|
+
after = batch.hour;
|
|
200
|
+
return { done: false, value: batch };
|
|
201
|
+
},
|
|
202
|
+
async return(value) {
|
|
203
|
+
done = true;
|
|
204
|
+
return { done: true, value };
|
|
205
|
+
},
|
|
206
|
+
[asyncIterator]() {
|
|
207
|
+
return this;
|
|
208
|
+
}
|
|
209
|
+
};
|
|
210
|
+
}
|
|
211
|
+
});
|
|
212
|
+
};
|
|
213
|
+
const flatParams = (params) => {
|
|
214
|
+
if (typeOf(params) !== "object") throw fail("invalid_argument", "Expected search parameters");
|
|
215
|
+
const out = [];
|
|
216
|
+
for (const [k, v] of entries(params)) if (v !== void 0 && v !== null) out.push([k, StringCtor(v)]);
|
|
217
|
+
return stringify(out);
|
|
218
|
+
};
|
|
219
|
+
async function* volumeSearch(params) {
|
|
220
|
+
let p = { ...params };
|
|
221
|
+
for (; ; ) {
|
|
222
|
+
const page = N.volume(flatParams(p));
|
|
223
|
+
yield page;
|
|
224
|
+
const next = page === null || typeof page !== "object" ? null : page.nextCursor;
|
|
225
|
+
if (next === null || next === void 0) return;
|
|
226
|
+
if (typeof next !== "string" || next === p.cursor)
|
|
227
|
+
throw fail("history_unavailable", "Invalid next cursor");
|
|
228
|
+
const w = page.window;
|
|
229
|
+
if (w && typeof w === "object" && "since" in w) p = { ...p, since: w.since, until: w.until };
|
|
230
|
+
p = { ...p, cursor: next };
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
const program = () => {
|
|
234
|
+
const app = g.__app;
|
|
235
|
+
const p = app && app.default;
|
|
236
|
+
if (!p || typeOf(p.functions) !== "object")
|
|
237
|
+
throw fail("invalid_program", "Expected the bundle to export defineProgram({ functions })");
|
|
238
|
+
for (const name of keys(p.functions))
|
|
239
|
+
if (typeof p.functions[name] !== "function")
|
|
240
|
+
throw fail("invalid_program", "Invalid function: " + name);
|
|
241
|
+
return p;
|
|
242
|
+
};
|
|
243
|
+
const describe = () => {
|
|
244
|
+
const p = program();
|
|
245
|
+
const sdk = p.__zyrkSdk;
|
|
246
|
+
return stringify({
|
|
247
|
+
sdk: typeof sdk === "string" ? sdk : "",
|
|
248
|
+
functions: keys(p.functions),
|
|
249
|
+
stateVersion: p.stateVersion ?? 0,
|
|
250
|
+
...p.migration ? { migration: p.migration } : {},
|
|
251
|
+
subscriptions: p.subscriptions ?? {}
|
|
252
|
+
});
|
|
253
|
+
};
|
|
254
|
+
const CHUNK = 4 * 1024 * 1024;
|
|
255
|
+
const U8 = Uint8Array;
|
|
256
|
+
const bad = (message) => fail("invalid_request", message);
|
|
257
|
+
const bytesOf = (value) => {
|
|
258
|
+
if (typeof value === "string") return N.encode(value);
|
|
259
|
+
if (value instanceof ArrayBuffer) return new U8(value);
|
|
260
|
+
if (ArrayBuffer.isView(value)) return new U8(value.buffer, value.byteOffset, value.byteLength);
|
|
261
|
+
throw bad("Expected a Uint8Array, an ArrayBuffer, a view or a string");
|
|
262
|
+
};
|
|
263
|
+
const keyOf = (key) => {
|
|
264
|
+
if (typeof key !== "string") throw bad("A storage key is a string");
|
|
265
|
+
return key;
|
|
266
|
+
};
|
|
267
|
+
const putOptions = (o, body) => {
|
|
268
|
+
if (o !== void 0 && o !== null && typeOf(o) !== "object") throw bad("Options must be an object");
|
|
269
|
+
const rawType = o ? o.contentType : void 0;
|
|
270
|
+
const rawMeta = o ? o.metadata : void 0;
|
|
271
|
+
const ifAbsent = !!(o && o.ifAbsent);
|
|
272
|
+
const rawMatch = o ? o.ifMatch : void 0;
|
|
273
|
+
if (rawMatch !== void 0 && rawMatch !== null && typeof rawMatch !== "string")
|
|
274
|
+
throw bad("ifMatch must be an etag string");
|
|
275
|
+
const ifMatch = rawMatch === void 0 ? null : rawMatch;
|
|
276
|
+
if (rawType !== void 0 && typeof rawType !== "string") throw bad("contentType must be a string");
|
|
277
|
+
const metadata = {};
|
|
278
|
+
if (rawMeta !== void 0 && rawMeta !== null) {
|
|
279
|
+
if (typeOf(rawMeta) !== "object") throw bad("metadata must be an object of strings");
|
|
280
|
+
for (const name of Object.keys(rawMeta)) {
|
|
281
|
+
const value = rawMeta[name];
|
|
282
|
+
if (typeof value !== "string") throw bad("metadata values must be strings");
|
|
283
|
+
metadata[name] = value;
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
const contentType = rawType !== void 0 ? rawType : typeof body === "string" ? "text/plain; charset=utf-8" : null;
|
|
287
|
+
return { contentType, metadata, ifAbsent, ifMatch };
|
|
288
|
+
};
|
|
289
|
+
const head = (r) => freeze({
|
|
290
|
+
key: r.key,
|
|
291
|
+
size: r.size,
|
|
292
|
+
contentType: r.contentType,
|
|
293
|
+
metadata: freeze({ ...r.metadata }),
|
|
294
|
+
lastModified: r.lastModified,
|
|
295
|
+
writtenAt: r.writtenAt,
|
|
296
|
+
expiresAt: r.expiresAt,
|
|
297
|
+
etag: r.etag
|
|
298
|
+
});
|
|
299
|
+
const summary = (r) => freeze({ key: r.key, size: r.size, contentType: r.contentType, lastModified: r.lastModified, expiresAt: r.expiresAt });
|
|
300
|
+
const storageArea = (area) => {
|
|
301
|
+
const read = async (key, offset, length) => {
|
|
302
|
+
const first = await call({ StorageGet: { area, key, offset, length: length > CHUNK ? CHUNK : length } });
|
|
303
|
+
if (first === null) return null;
|
|
304
|
+
const end = Math.min(first.size, offset + length);
|
|
305
|
+
const total = Math.max(0, end - first.offset);
|
|
306
|
+
const out = new U8(total);
|
|
307
|
+
let at = 0;
|
|
308
|
+
let r = first;
|
|
309
|
+
for (; ; ) {
|
|
310
|
+
const n = N.b64decodeInto(r.data, out, at);
|
|
311
|
+
if (n < 0) throw fail("unavailable", "Corrupt storage chunk");
|
|
312
|
+
at += n;
|
|
313
|
+
if (at >= total || n === 0) break;
|
|
314
|
+
r = await call({
|
|
315
|
+
StorageGet: { area, key, offset: first.offset + at, length: Math.min(CHUNK, total - at) }
|
|
316
|
+
});
|
|
317
|
+
if (r === null || r.etag !== first.etag)
|
|
318
|
+
throw fail("value_changed", "The object changed while it was read: read it again");
|
|
319
|
+
}
|
|
320
|
+
return { first, body: at === total ? out : out.subarray(0, at) };
|
|
321
|
+
};
|
|
322
|
+
const get = async (key, range) => {
|
|
323
|
+
keyOf(key);
|
|
324
|
+
const offset = range && range.offset !== void 0 ? range.offset : 0;
|
|
325
|
+
const length = range && range.length !== void 0 ? range.length : Number.MAX_SAFE_INTEGER;
|
|
326
|
+
if (!Number.isSafeInteger(offset) || offset < 0 || !Number.isSafeInteger(length) || length < 0)
|
|
327
|
+
throw bad("offset and length must be non-negative integers");
|
|
328
|
+
const r = await read(key, offset, length);
|
|
329
|
+
if (r === null) return null;
|
|
330
|
+
return freeze({ ...head(r.first), body: r.body });
|
|
331
|
+
};
|
|
332
|
+
const openWriter = async (key, o) => {
|
|
333
|
+
const upload = await call({ StorageUploadStart: { area, key, options: o } });
|
|
334
|
+
let done = false;
|
|
335
|
+
const check = () => {
|
|
336
|
+
if (done) throw bad("This storage writer is closed");
|
|
337
|
+
};
|
|
338
|
+
return freeze({
|
|
339
|
+
write: async (value) => {
|
|
340
|
+
check();
|
|
341
|
+
const bytes = bytesOf(value);
|
|
342
|
+
for (let at = 0; at < bytes.length; at += CHUNK) {
|
|
343
|
+
await call({ StorageUploadChunk: { upload, data: N.b64encode(bytes.subarray(at, at + CHUNK)) } });
|
|
344
|
+
}
|
|
345
|
+
},
|
|
346
|
+
close: async () => {
|
|
347
|
+
check();
|
|
348
|
+
done = true;
|
|
349
|
+
return head(await call({ StorageUploadCommit: { upload } }));
|
|
350
|
+
},
|
|
351
|
+
abort: async () => {
|
|
352
|
+
if (done) return;
|
|
353
|
+
done = true;
|
|
354
|
+
await call({ StorageUploadAbort: { upload } });
|
|
355
|
+
}
|
|
356
|
+
});
|
|
357
|
+
};
|
|
358
|
+
const put = async (key, value, options) => {
|
|
359
|
+
keyOf(key);
|
|
360
|
+
const o = putOptions(options, value);
|
|
361
|
+
const bytes = bytesOf(value);
|
|
362
|
+
if (bytes.length <= CHUNK)
|
|
363
|
+
return head(await call({ StoragePut: { area, key, data: N.b64encode(bytes), options: o } }));
|
|
364
|
+
const w = await openWriter(key, o);
|
|
365
|
+
try {
|
|
366
|
+
await w.write(bytes);
|
|
367
|
+
} catch (e) {
|
|
368
|
+
await w.abort().catch(() => {
|
|
369
|
+
});
|
|
370
|
+
throw e;
|
|
371
|
+
}
|
|
372
|
+
return w.close();
|
|
373
|
+
};
|
|
374
|
+
const writer = async (key, options) => openWriter(keyOf(key), putOptions(options, void 0));
|
|
375
|
+
const textDecoder = new TextDecoder("utf-8", { fatal: true });
|
|
376
|
+
const getText = async (key) => {
|
|
377
|
+
const r = await get(key);
|
|
378
|
+
return r === null ? null : textDecoder.decode(r.body);
|
|
379
|
+
};
|
|
380
|
+
return freeze({
|
|
381
|
+
put,
|
|
382
|
+
get,
|
|
383
|
+
head: async (key) => {
|
|
384
|
+
const r = await call({ StorageHead: { area, key: keyOf(key) } });
|
|
385
|
+
return r === null ? null : head(r);
|
|
386
|
+
},
|
|
387
|
+
delete: async (key, o) => {
|
|
388
|
+
const rawMatch = o ? o.ifMatch : void 0;
|
|
389
|
+
if (rawMatch !== void 0 && rawMatch !== null && typeof rawMatch !== "string")
|
|
390
|
+
throw bad("ifMatch must be an etag string");
|
|
391
|
+
await call({ StorageDelete: { area, key: keyOf(key), if_match: rawMatch === void 0 ? null : rawMatch } });
|
|
392
|
+
},
|
|
393
|
+
list: async (prefix, o) => {
|
|
394
|
+
const p = prefix === void 0 || prefix === null ? "" : prefix;
|
|
395
|
+
if (typeof p !== "string") throw bad("prefix must be a string");
|
|
396
|
+
const max = o && o.maxObjects !== void 0 ? o.maxObjects : null;
|
|
397
|
+
const after = o && o.after !== void 0 && o.after !== null ? keyOf(o.after) : null;
|
|
398
|
+
if (max !== null && (!Number.isSafeInteger(max) || max < 1))
|
|
399
|
+
throw bad("maxObjects must be a positive integer");
|
|
400
|
+
const r = await call({ StorageList: { area, prefix: p, after, max_objects: max } });
|
|
401
|
+
const page = r.objects.map(summary);
|
|
402
|
+
page.cursor = r.cursor;
|
|
403
|
+
page.truncated = r.cursor !== null;
|
|
404
|
+
return freeze(page);
|
|
405
|
+
},
|
|
406
|
+
usage: async () => freeze(await call({ StorageUsage: { area } })),
|
|
407
|
+
getText,
|
|
408
|
+
getJSON: async (key) => {
|
|
409
|
+
const text = await getText(key);
|
|
410
|
+
return text === null ? null : parse(text);
|
|
411
|
+
},
|
|
412
|
+
putJSON: async (key, value, options) => {
|
|
413
|
+
let text;
|
|
414
|
+
try {
|
|
415
|
+
text = stringify(value);
|
|
416
|
+
} catch (e) {
|
|
417
|
+
throw bad("Not JSON: " + StringCtor(e && e.message));
|
|
418
|
+
}
|
|
419
|
+
if (text === void 0) throw bad("Not JSON");
|
|
420
|
+
return put(key, text, { ...options || {}, contentType: "application/json" });
|
|
421
|
+
},
|
|
422
|
+
writer
|
|
423
|
+
});
|
|
424
|
+
};
|
|
425
|
+
const storage = freeze({
|
|
426
|
+
short: storageArea("short"),
|
|
427
|
+
long: storageArea("long"),
|
|
428
|
+
durable: storageArea("durable")
|
|
429
|
+
});
|
|
430
|
+
const start = (functionName, argsText, executionText) => {
|
|
431
|
+
const p = program();
|
|
432
|
+
let depth = 0;
|
|
433
|
+
const invoke = async (name, args) => {
|
|
434
|
+
if (typeof name !== "string" || !hasOwn.call(p.functions, name))
|
|
435
|
+
throw fail("unknown_function", "Unknown function: " + StringCtor(name));
|
|
436
|
+
if (++depth > N.maxDepth) throw fail("invocation_depth", "Invocation depth exceeded");
|
|
437
|
+
try {
|
|
438
|
+
return await p.functions[name](ctx, args);
|
|
439
|
+
} finally {
|
|
440
|
+
depth--;
|
|
441
|
+
}
|
|
442
|
+
};
|
|
443
|
+
const execution = parse(executionText);
|
|
444
|
+
const ctx = freeze({
|
|
445
|
+
execution: freeze({
|
|
446
|
+
id: execution.id,
|
|
447
|
+
workflow: execution.workflow,
|
|
448
|
+
program: execution.program,
|
|
449
|
+
version: execution.version,
|
|
450
|
+
attempt: execution.attempt
|
|
451
|
+
}),
|
|
452
|
+
data: freeze({
|
|
453
|
+
walletTrades: trades("wallet"),
|
|
454
|
+
tokenTrades: trades("token"),
|
|
455
|
+
tokenTotals: async (mint, o) => {
|
|
456
|
+
if (typeof mint !== "string") throw fail("invalid_argument", "Expected a mint address");
|
|
457
|
+
const rawQuote = o ? o.quote : void 0;
|
|
458
|
+
const quote = rawQuote !== void 0 ? StringCtor(rawQuote) : null;
|
|
459
|
+
return N.totals(mint, quote);
|
|
460
|
+
},
|
|
461
|
+
tokenInfo: async (mint) => {
|
|
462
|
+
if (typeof mint !== "string") throw fail("invalid_argument", "Expected a mint address");
|
|
463
|
+
return N.info(mint);
|
|
464
|
+
},
|
|
465
|
+
volumeSearch
|
|
466
|
+
}),
|
|
467
|
+
state: freeze({
|
|
468
|
+
get: (key) => call({ StateGet: { key } }),
|
|
469
|
+
set: (key, value) => call({ StateSet: { key, value } }),
|
|
470
|
+
delete: (key) => call({ StateDelete: { key } })
|
|
471
|
+
}),
|
|
472
|
+
jobs: freeze({
|
|
473
|
+
start: (i) => call({
|
|
474
|
+
JobStart: {
|
|
475
|
+
function: i && i.function,
|
|
476
|
+
args: i && i.args,
|
|
477
|
+
on_complete: (i && i.onComplete) ?? null
|
|
478
|
+
}
|
|
479
|
+
}),
|
|
480
|
+
wait: (ids, o) => call({
|
|
481
|
+
JobWait: {
|
|
482
|
+
ids: isArray(ids) ? ids : [ids],
|
|
483
|
+
timeout_ms: (o && o.timeoutMs) ?? null
|
|
484
|
+
}
|
|
485
|
+
}),
|
|
486
|
+
result: (id) => call({ JobResult: { id } }),
|
|
487
|
+
continue: (args) => call({ Continue: { args } })
|
|
488
|
+
}),
|
|
489
|
+
storage,
|
|
490
|
+
subscriptions: freeze({
|
|
491
|
+
set: (name, subscription) => call({ Subscribe: { name, subscription } }),
|
|
492
|
+
remove: (name) => call({ Unsubscribe: { name } }),
|
|
493
|
+
replay: (request) => call({ Replay: { request } })
|
|
494
|
+
}),
|
|
495
|
+
invoke,
|
|
496
|
+
log: (value) => call({ Log: { value: value === void 0 ? null : value } }),
|
|
497
|
+
emit: (value) => call({ Emit: { value: value === void 0 ? null : value } }),
|
|
498
|
+
webhook: freeze({
|
|
499
|
+
send: (payload, o) => call({
|
|
500
|
+
WebhookSend: {
|
|
501
|
+
payload: payload === void 0 ? null : payload,
|
|
502
|
+
drop_if_full: !!o && o.onFull === "drop"
|
|
503
|
+
}
|
|
504
|
+
})
|
|
505
|
+
})
|
|
506
|
+
});
|
|
507
|
+
return (async () => {
|
|
508
|
+
const value = await invoke(functionName, parse(argsText));
|
|
509
|
+
let text;
|
|
510
|
+
try {
|
|
511
|
+
text = stringify(value);
|
|
512
|
+
} catch (e) {
|
|
513
|
+
throw fail("invalid_result", "The result is not JSON: " + StringCtor(e && e.message));
|
|
514
|
+
}
|
|
515
|
+
return text === void 0 ? "null" : text;
|
|
516
|
+
})();
|
|
517
|
+
};
|
|
518
|
+
return freeze({ start, describe });
|
|
519
|
+
});
|