@donezone/client 0.1.51 → 0.1.55
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 +542 -71
- package/dist/auth.d.ts +1 -1
- package/dist/auth.d.ts.map +1 -1
- package/dist/client.d.ts +1 -1
- package/dist/client.d.ts.map +1 -1
- package/dist/done.d.ts +20 -8
- package/dist/done.d.ts.map +1 -1
- package/dist/{envelope.d.ts → envelope-builder.d.ts} +1 -4
- package/dist/envelope-builder.d.ts.map +1 -0
- package/dist/envelope-crypto.d.ts +6 -0
- package/dist/envelope-crypto.d.ts.map +1 -0
- package/dist/index.d.ts +3 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1219 -6
- package/package.json +6 -5
- package/dist/auth.js +0 -112
- package/dist/client.js +0 -140
- package/dist/done.js +0 -484
- package/dist/envelope.d.ts.map +0 -1
- package/dist/envelope.js +0 -113
- package/dist/messages.js +0 -46
- package/dist/types.js +0 -1
package/dist/index.js
CHANGED
|
@@ -1,6 +1,1219 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
1
|
+
// src/envelope-builder.ts
|
|
2
|
+
var CURRENT_ENVELOPE_VERSION = 1;
|
|
3
|
+
function normalizeMetadata(metadata) {
|
|
4
|
+
if (!metadata) return void 0;
|
|
5
|
+
const normalized = {};
|
|
6
|
+
if (metadata.trace_id) normalized.trace_id = metadata.trace_id;
|
|
7
|
+
if (metadata.memo) normalized.memo = metadata.memo;
|
|
8
|
+
if (typeof metadata.gas_limit === "number") normalized.gas_limit = metadata.gas_limit;
|
|
9
|
+
return Object.keys(normalized).length > 0 ? normalized : void 0;
|
|
10
|
+
}
|
|
11
|
+
function toSignDoc(envelope) {
|
|
12
|
+
const metadata = normalizeMetadata(envelope.metadata);
|
|
13
|
+
return {
|
|
14
|
+
version: envelope.version ?? CURRENT_ENVELOPE_VERSION,
|
|
15
|
+
user_id: envelope.user_id,
|
|
16
|
+
session_id: envelope.session_id,
|
|
17
|
+
msgs: envelope.msgs.map((msg) => cloneMsg(msg)),
|
|
18
|
+
nonce: envelope.nonce,
|
|
19
|
+
expires_at: envelope.expires_at,
|
|
20
|
+
role: envelope.role,
|
|
21
|
+
agent: envelope.agent,
|
|
22
|
+
forwarder: envelope.forwarder,
|
|
23
|
+
metadata
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
function buildEnvelope(draft) {
|
|
27
|
+
if (!Array.isArray(draft.msgs) || draft.msgs.length === 0) {
|
|
28
|
+
throw new Error("envelope requires at least one message");
|
|
29
|
+
}
|
|
30
|
+
const version = draft.version ?? CURRENT_ENVELOPE_VERSION;
|
|
31
|
+
const metadata = normalizeMetadata(draft.metadata);
|
|
32
|
+
return {
|
|
33
|
+
version,
|
|
34
|
+
user_id: draft.user_id,
|
|
35
|
+
session_id: draft.session_id,
|
|
36
|
+
msgs: draft.msgs.map((msg) => cloneMsg(msg)),
|
|
37
|
+
nonce: draft.nonce,
|
|
38
|
+
expires_at: draft.expires_at,
|
|
39
|
+
role: draft.role,
|
|
40
|
+
agent: draft.agent,
|
|
41
|
+
forwarder: draft.forwarder,
|
|
42
|
+
signatures: draft.signatures ? { ...draft.signatures } : {},
|
|
43
|
+
metadata
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
function signDocBytes(signDoc) {
|
|
47
|
+
const json = canonicalStringify(signDoc);
|
|
48
|
+
return new TextEncoder().encode(json);
|
|
49
|
+
}
|
|
50
|
+
function cloneMsg(msg) {
|
|
51
|
+
return structuredClone(msg);
|
|
52
|
+
}
|
|
53
|
+
function canonicalStringify(value) {
|
|
54
|
+
return JSON.stringify(value, (_key, val) => {
|
|
55
|
+
if (val instanceof Map) {
|
|
56
|
+
return Object.fromEntries(Array.from(val.entries()).sort(([a], [b]) => a < b ? -1 : a > b ? 1 : 0));
|
|
57
|
+
}
|
|
58
|
+
if (val && typeof val === "object" && !Array.isArray(val)) {
|
|
59
|
+
const entries = Object.entries(val).sort(
|
|
60
|
+
([a], [b]) => a < b ? -1 : a > b ? 1 : 0
|
|
61
|
+
);
|
|
62
|
+
return entries.reduce((acc, [key, entry]) => {
|
|
63
|
+
acc[key] = entry;
|
|
64
|
+
return acc;
|
|
65
|
+
}, {});
|
|
66
|
+
}
|
|
67
|
+
return val;
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
function createDevEnvelopeBuilder(options = {}) {
|
|
71
|
+
const userId = options.userId ?? "dev";
|
|
72
|
+
const ttlSeconds = options.ttlSeconds ?? 300;
|
|
73
|
+
return (ctx) => {
|
|
74
|
+
const envelope = buildEnvelope({
|
|
75
|
+
user_id: userId,
|
|
76
|
+
msgs: [ctx.msg],
|
|
77
|
+
nonce: Date.now(),
|
|
78
|
+
expires_at: Math.floor(Date.now() / 1e3) + ttlSeconds,
|
|
79
|
+
role: "Passkey",
|
|
80
|
+
signatures: {}
|
|
81
|
+
});
|
|
82
|
+
return { envelope };
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
// src/messages.ts
|
|
87
|
+
function buildTransactionMessage(contractAddr, call, options = {}) {
|
|
88
|
+
const payload = normalizeCall(call);
|
|
89
|
+
const msg = { msg: payload };
|
|
90
|
+
const funds = normalizeFunds(options.funds);
|
|
91
|
+
return {
|
|
92
|
+
wasm: {
|
|
93
|
+
execute: {
|
|
94
|
+
contract_addr: contractAddr,
|
|
95
|
+
msg,
|
|
96
|
+
funds: funds && funds.length > 0 ? funds : void 0
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
function buildQueryMessage(call) {
|
|
102
|
+
return { msg: normalizeCall(call) };
|
|
103
|
+
}
|
|
104
|
+
function normalizeCall(call) {
|
|
105
|
+
if (!call.path || !call.path.startsWith("/")) {
|
|
106
|
+
throw new Error("contract call path must start with '/'");
|
|
107
|
+
}
|
|
108
|
+
const payload = { path: call.path };
|
|
109
|
+
if (call.query instanceof URLSearchParams) {
|
|
110
|
+
payload.query = Object.fromEntries(Array.from(call.query));
|
|
111
|
+
} else if (call.query) {
|
|
112
|
+
payload.query = call.query;
|
|
113
|
+
}
|
|
114
|
+
if (call.body !== void 0) {
|
|
115
|
+
payload.body = call.body;
|
|
116
|
+
}
|
|
117
|
+
return payload;
|
|
118
|
+
}
|
|
119
|
+
function normalizeFunds(funds) {
|
|
120
|
+
if (!funds) return void 0;
|
|
121
|
+
if (Array.isArray(funds)) {
|
|
122
|
+
if (funds.length === 0) return void 0;
|
|
123
|
+
return funds.map((coin) => ({ denom: coin.denom, amount: coin.amount }));
|
|
124
|
+
}
|
|
125
|
+
const entries = Object.entries(funds);
|
|
126
|
+
if (entries.length === 0) return void 0;
|
|
127
|
+
return entries.map(([denom, amount]) => ({ denom, amount: String(amount) }));
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
// src/client.ts
|
|
131
|
+
var DoneBackendClient = class {
|
|
132
|
+
baseUrl;
|
|
133
|
+
fetchImpl;
|
|
134
|
+
constructor(config) {
|
|
135
|
+
this.baseUrl = config.baseUrl.replace(/\/$/, "");
|
|
136
|
+
const candidate = config.fetch ?? fetch;
|
|
137
|
+
if (typeof candidate !== "function") {
|
|
138
|
+
throw new Error("fetch implementation is not available; configure Done with a fetch implementation via Done.config");
|
|
139
|
+
}
|
|
140
|
+
this.fetchImpl = candidate.bind(globalThis);
|
|
141
|
+
}
|
|
142
|
+
contract(address) {
|
|
143
|
+
return new DoneContractHandle(this, address);
|
|
144
|
+
}
|
|
145
|
+
buildEnvelope(draft) {
|
|
146
|
+
return buildEnvelope(draft);
|
|
147
|
+
}
|
|
148
|
+
async executeEnvelope(envelope, options = {}, init = {}) {
|
|
149
|
+
const body = {
|
|
150
|
+
envelope,
|
|
151
|
+
passkey: options.passkey,
|
|
152
|
+
memo: options.memo ?? envelope.metadata?.memo
|
|
153
|
+
};
|
|
154
|
+
const { headers: initHeaders, signal: initSignal, method: initMethod, body: _ignoredBody, ...rest } = init;
|
|
155
|
+
const headers = new Headers(initHeaders ?? {});
|
|
156
|
+
headers.set("content-type", "application/json");
|
|
157
|
+
const res = await this.fetchImpl(`${this.baseUrl}/tx`, {
|
|
158
|
+
...rest,
|
|
159
|
+
method: initMethod ?? "POST",
|
|
160
|
+
headers,
|
|
161
|
+
body: JSON.stringify(body),
|
|
162
|
+
signal: initSignal ?? options.signal
|
|
163
|
+
});
|
|
164
|
+
if (!res.ok) {
|
|
165
|
+
const text = await res.text().catch(() => "");
|
|
166
|
+
throw new Error(`tx failed with ${res.status}: ${text}`);
|
|
167
|
+
}
|
|
168
|
+
return res.json();
|
|
169
|
+
}
|
|
170
|
+
async publishCode(request, init = {}) {
|
|
171
|
+
const { contract, script, msg } = request;
|
|
172
|
+
const { headers: initHeaders, method: initMethod, body: _ignoredBody, ...rest } = init;
|
|
173
|
+
const headers = new Headers(initHeaders ?? {});
|
|
174
|
+
headers.set("content-type", "application/json");
|
|
175
|
+
const payload = { script };
|
|
176
|
+
if (Object.prototype.hasOwnProperty.call(request, "msg")) {
|
|
177
|
+
payload.msg = msg;
|
|
178
|
+
}
|
|
179
|
+
const res = await this.fetchImpl(`${this.baseUrl}/contracts/${contract}/publish`, {
|
|
180
|
+
...rest,
|
|
181
|
+
method: initMethod ?? "POST",
|
|
182
|
+
headers,
|
|
183
|
+
body: JSON.stringify(payload)
|
|
184
|
+
});
|
|
185
|
+
if (!res.ok) {
|
|
186
|
+
const text = await res.text().catch(() => "");
|
|
187
|
+
throw new Error(`publish failed with ${res.status}: ${text}`);
|
|
188
|
+
}
|
|
189
|
+
return res.json();
|
|
190
|
+
}
|
|
191
|
+
async queryContractRaw(address, call, init = {}) {
|
|
192
|
+
const message = buildQueryMessage(call);
|
|
193
|
+
const params = new URLSearchParams();
|
|
194
|
+
params.set("msg", JSON.stringify(message));
|
|
195
|
+
const { method: initMethod, ...rest } = init;
|
|
196
|
+
return this.fetchImpl(`${this.baseUrl}/query/${address}?${params}`, {
|
|
197
|
+
method: initMethod ?? "GET",
|
|
198
|
+
...rest
|
|
199
|
+
});
|
|
200
|
+
}
|
|
201
|
+
async queryContract(address, call, init = {}) {
|
|
202
|
+
const res = await this.queryContractRaw(address, call, init);
|
|
203
|
+
if (!res.ok) {
|
|
204
|
+
const text = await res.text().catch(() => "");
|
|
205
|
+
throw new Error(`query failed with ${res.status}: ${text}`);
|
|
206
|
+
}
|
|
207
|
+
return res.json();
|
|
208
|
+
}
|
|
209
|
+
async getAgentQuota(userId, agent) {
|
|
210
|
+
const res = await this.fetchImpl(`${this.baseUrl}/quota/agent/${userId}/${agent}`);
|
|
211
|
+
if (!res.ok) {
|
|
212
|
+
const text = await res.text().catch(() => "");
|
|
213
|
+
throw new Error(`agent quota failed with ${res.status}: ${text}`);
|
|
214
|
+
}
|
|
215
|
+
return res.json();
|
|
216
|
+
}
|
|
217
|
+
async getForwarderQuota(address) {
|
|
218
|
+
const res = await this.fetchImpl(`${this.baseUrl}/quota/forwarder/${address}`);
|
|
219
|
+
if (!res.ok) {
|
|
220
|
+
const text = await res.text().catch(() => "");
|
|
221
|
+
throw new Error(`forwarder quota failed with ${res.status}: ${text}`);
|
|
222
|
+
}
|
|
223
|
+
return res.json();
|
|
224
|
+
}
|
|
225
|
+
};
|
|
226
|
+
var DoneContractHandle = class {
|
|
227
|
+
constructor(backend, address) {
|
|
228
|
+
this.backend = backend;
|
|
229
|
+
this.address = address;
|
|
230
|
+
}
|
|
231
|
+
transaction(path, options = {}) {
|
|
232
|
+
const call = {
|
|
233
|
+
path,
|
|
234
|
+
query: options.query,
|
|
235
|
+
body: options.body
|
|
236
|
+
};
|
|
237
|
+
const msg = buildTransactionMessage(this.address, call, options);
|
|
238
|
+
const metadata = metadataFromOptions(options);
|
|
239
|
+
return { msg, metadata };
|
|
240
|
+
}
|
|
241
|
+
async query(path, options = {}) {
|
|
242
|
+
const call = {
|
|
243
|
+
path,
|
|
244
|
+
query: options.query,
|
|
245
|
+
body: options.body
|
|
246
|
+
};
|
|
247
|
+
return this.backend.queryContract(this.address, call);
|
|
248
|
+
}
|
|
249
|
+
publishCode(request, init = {}) {
|
|
250
|
+
return this.backend.publishCode(
|
|
251
|
+
{
|
|
252
|
+
contract: this.address,
|
|
253
|
+
script: request.script,
|
|
254
|
+
msg: request.msg
|
|
255
|
+
},
|
|
256
|
+
init
|
|
257
|
+
);
|
|
258
|
+
}
|
|
259
|
+
};
|
|
260
|
+
function metadataFromOptions(options) {
|
|
261
|
+
const metadata = {};
|
|
262
|
+
if (options.traceId) metadata.trace_id = options.traceId;
|
|
263
|
+
if (options.memo) metadata.memo = options.memo;
|
|
264
|
+
if (typeof options.gasLimit === "number") metadata.gas_limit = options.gasLimit;
|
|
265
|
+
return Object.keys(metadata).length > 0 ? metadata : void 0;
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
// ../../node_modules/@noble/hashes/esm/_assert.js
|
|
269
|
+
function bytes(b, ...lengths) {
|
|
270
|
+
if (!(b instanceof Uint8Array))
|
|
271
|
+
throw new Error("Expected Uint8Array");
|
|
272
|
+
if (lengths.length > 0 && !lengths.includes(b.length))
|
|
273
|
+
throw new Error(`Expected Uint8Array of length ${lengths}, not of length=${b.length}`);
|
|
274
|
+
}
|
|
275
|
+
function exists(instance, checkFinished = true) {
|
|
276
|
+
if (instance.destroyed)
|
|
277
|
+
throw new Error("Hash instance has been destroyed");
|
|
278
|
+
if (checkFinished && instance.finished)
|
|
279
|
+
throw new Error("Hash#digest() has already been called");
|
|
280
|
+
}
|
|
281
|
+
function output(out, instance) {
|
|
282
|
+
bytes(out);
|
|
283
|
+
const min = instance.outputLen;
|
|
284
|
+
if (out.length < min) {
|
|
285
|
+
throw new Error(`digestInto() expects output buffer of length at least ${min}`);
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
// ../../node_modules/@noble/hashes/esm/utils.js
|
|
290
|
+
var u8a = (a) => a instanceof Uint8Array;
|
|
291
|
+
var createView = (arr) => new DataView(arr.buffer, arr.byteOffset, arr.byteLength);
|
|
292
|
+
var rotr = (word, shift) => word << 32 - shift | word >>> shift;
|
|
293
|
+
var isLE = new Uint8Array(new Uint32Array([287454020]).buffer)[0] === 68;
|
|
294
|
+
if (!isLE)
|
|
295
|
+
throw new Error("Non little-endian hardware is not supported");
|
|
296
|
+
function utf8ToBytes(str) {
|
|
297
|
+
if (typeof str !== "string")
|
|
298
|
+
throw new Error(`utf8ToBytes expected string, got ${typeof str}`);
|
|
299
|
+
return new Uint8Array(new TextEncoder().encode(str));
|
|
300
|
+
}
|
|
301
|
+
function toBytes(data) {
|
|
302
|
+
if (typeof data === "string")
|
|
303
|
+
data = utf8ToBytes(data);
|
|
304
|
+
if (!u8a(data))
|
|
305
|
+
throw new Error(`expected Uint8Array, got ${typeof data}`);
|
|
306
|
+
return data;
|
|
307
|
+
}
|
|
308
|
+
var Hash = class {
|
|
309
|
+
// Safe version that clones internal state
|
|
310
|
+
clone() {
|
|
311
|
+
return this._cloneInto();
|
|
312
|
+
}
|
|
313
|
+
};
|
|
314
|
+
var toStr = {}.toString;
|
|
315
|
+
function wrapConstructor(hashCons) {
|
|
316
|
+
const hashC = (msg) => hashCons().update(toBytes(msg)).digest();
|
|
317
|
+
const tmp = hashCons();
|
|
318
|
+
hashC.outputLen = tmp.outputLen;
|
|
319
|
+
hashC.blockLen = tmp.blockLen;
|
|
320
|
+
hashC.create = () => hashCons();
|
|
321
|
+
return hashC;
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
// ../../node_modules/@noble/hashes/esm/_sha2.js
|
|
325
|
+
function setBigUint64(view, byteOffset, value, isLE2) {
|
|
326
|
+
if (typeof view.setBigUint64 === "function")
|
|
327
|
+
return view.setBigUint64(byteOffset, value, isLE2);
|
|
328
|
+
const _32n = BigInt(32);
|
|
329
|
+
const _u32_max = BigInt(4294967295);
|
|
330
|
+
const wh = Number(value >> _32n & _u32_max);
|
|
331
|
+
const wl = Number(value & _u32_max);
|
|
332
|
+
const h = isLE2 ? 4 : 0;
|
|
333
|
+
const l = isLE2 ? 0 : 4;
|
|
334
|
+
view.setUint32(byteOffset + h, wh, isLE2);
|
|
335
|
+
view.setUint32(byteOffset + l, wl, isLE2);
|
|
336
|
+
}
|
|
337
|
+
var SHA2 = class extends Hash {
|
|
338
|
+
constructor(blockLen, outputLen, padOffset, isLE2) {
|
|
339
|
+
super();
|
|
340
|
+
this.blockLen = blockLen;
|
|
341
|
+
this.outputLen = outputLen;
|
|
342
|
+
this.padOffset = padOffset;
|
|
343
|
+
this.isLE = isLE2;
|
|
344
|
+
this.finished = false;
|
|
345
|
+
this.length = 0;
|
|
346
|
+
this.pos = 0;
|
|
347
|
+
this.destroyed = false;
|
|
348
|
+
this.buffer = new Uint8Array(blockLen);
|
|
349
|
+
this.view = createView(this.buffer);
|
|
350
|
+
}
|
|
351
|
+
update(data) {
|
|
352
|
+
exists(this);
|
|
353
|
+
const { view, buffer, blockLen } = this;
|
|
354
|
+
data = toBytes(data);
|
|
355
|
+
const len = data.length;
|
|
356
|
+
for (let pos = 0; pos < len; ) {
|
|
357
|
+
const take = Math.min(blockLen - this.pos, len - pos);
|
|
358
|
+
if (take === blockLen) {
|
|
359
|
+
const dataView = createView(data);
|
|
360
|
+
for (; blockLen <= len - pos; pos += blockLen)
|
|
361
|
+
this.process(dataView, pos);
|
|
362
|
+
continue;
|
|
363
|
+
}
|
|
364
|
+
buffer.set(data.subarray(pos, pos + take), this.pos);
|
|
365
|
+
this.pos += take;
|
|
366
|
+
pos += take;
|
|
367
|
+
if (this.pos === blockLen) {
|
|
368
|
+
this.process(view, 0);
|
|
369
|
+
this.pos = 0;
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
this.length += data.length;
|
|
373
|
+
this.roundClean();
|
|
374
|
+
return this;
|
|
375
|
+
}
|
|
376
|
+
digestInto(out) {
|
|
377
|
+
exists(this);
|
|
378
|
+
output(out, this);
|
|
379
|
+
this.finished = true;
|
|
380
|
+
const { buffer, view, blockLen, isLE: isLE2 } = this;
|
|
381
|
+
let { pos } = this;
|
|
382
|
+
buffer[pos++] = 128;
|
|
383
|
+
this.buffer.subarray(pos).fill(0);
|
|
384
|
+
if (this.padOffset > blockLen - pos) {
|
|
385
|
+
this.process(view, 0);
|
|
386
|
+
pos = 0;
|
|
387
|
+
}
|
|
388
|
+
for (let i = pos; i < blockLen; i++)
|
|
389
|
+
buffer[i] = 0;
|
|
390
|
+
setBigUint64(view, blockLen - 8, BigInt(this.length * 8), isLE2);
|
|
391
|
+
this.process(view, 0);
|
|
392
|
+
const oview = createView(out);
|
|
393
|
+
const len = this.outputLen;
|
|
394
|
+
if (len % 4)
|
|
395
|
+
throw new Error("_sha2: outputLen should be aligned to 32bit");
|
|
396
|
+
const outLen = len / 4;
|
|
397
|
+
const state = this.get();
|
|
398
|
+
if (outLen > state.length)
|
|
399
|
+
throw new Error("_sha2: outputLen bigger than state");
|
|
400
|
+
for (let i = 0; i < outLen; i++)
|
|
401
|
+
oview.setUint32(4 * i, state[i], isLE2);
|
|
402
|
+
}
|
|
403
|
+
digest() {
|
|
404
|
+
const { buffer, outputLen } = this;
|
|
405
|
+
this.digestInto(buffer);
|
|
406
|
+
const res = buffer.slice(0, outputLen);
|
|
407
|
+
this.destroy();
|
|
408
|
+
return res;
|
|
409
|
+
}
|
|
410
|
+
_cloneInto(to) {
|
|
411
|
+
to || (to = new this.constructor());
|
|
412
|
+
to.set(...this.get());
|
|
413
|
+
const { blockLen, buffer, length, finished, destroyed, pos } = this;
|
|
414
|
+
to.length = length;
|
|
415
|
+
to.pos = pos;
|
|
416
|
+
to.finished = finished;
|
|
417
|
+
to.destroyed = destroyed;
|
|
418
|
+
if (length % blockLen)
|
|
419
|
+
to.buffer.set(buffer);
|
|
420
|
+
return to;
|
|
421
|
+
}
|
|
422
|
+
};
|
|
423
|
+
|
|
424
|
+
// ../../node_modules/@noble/hashes/esm/sha256.js
|
|
425
|
+
var Chi = (a, b, c) => a & b ^ ~a & c;
|
|
426
|
+
var Maj = (a, b, c) => a & b ^ a & c ^ b & c;
|
|
427
|
+
var SHA256_K = /* @__PURE__ */ new Uint32Array([
|
|
428
|
+
1116352408,
|
|
429
|
+
1899447441,
|
|
430
|
+
3049323471,
|
|
431
|
+
3921009573,
|
|
432
|
+
961987163,
|
|
433
|
+
1508970993,
|
|
434
|
+
2453635748,
|
|
435
|
+
2870763221,
|
|
436
|
+
3624381080,
|
|
437
|
+
310598401,
|
|
438
|
+
607225278,
|
|
439
|
+
1426881987,
|
|
440
|
+
1925078388,
|
|
441
|
+
2162078206,
|
|
442
|
+
2614888103,
|
|
443
|
+
3248222580,
|
|
444
|
+
3835390401,
|
|
445
|
+
4022224774,
|
|
446
|
+
264347078,
|
|
447
|
+
604807628,
|
|
448
|
+
770255983,
|
|
449
|
+
1249150122,
|
|
450
|
+
1555081692,
|
|
451
|
+
1996064986,
|
|
452
|
+
2554220882,
|
|
453
|
+
2821834349,
|
|
454
|
+
2952996808,
|
|
455
|
+
3210313671,
|
|
456
|
+
3336571891,
|
|
457
|
+
3584528711,
|
|
458
|
+
113926993,
|
|
459
|
+
338241895,
|
|
460
|
+
666307205,
|
|
461
|
+
773529912,
|
|
462
|
+
1294757372,
|
|
463
|
+
1396182291,
|
|
464
|
+
1695183700,
|
|
465
|
+
1986661051,
|
|
466
|
+
2177026350,
|
|
467
|
+
2456956037,
|
|
468
|
+
2730485921,
|
|
469
|
+
2820302411,
|
|
470
|
+
3259730800,
|
|
471
|
+
3345764771,
|
|
472
|
+
3516065817,
|
|
473
|
+
3600352804,
|
|
474
|
+
4094571909,
|
|
475
|
+
275423344,
|
|
476
|
+
430227734,
|
|
477
|
+
506948616,
|
|
478
|
+
659060556,
|
|
479
|
+
883997877,
|
|
480
|
+
958139571,
|
|
481
|
+
1322822218,
|
|
482
|
+
1537002063,
|
|
483
|
+
1747873779,
|
|
484
|
+
1955562222,
|
|
485
|
+
2024104815,
|
|
486
|
+
2227730452,
|
|
487
|
+
2361852424,
|
|
488
|
+
2428436474,
|
|
489
|
+
2756734187,
|
|
490
|
+
3204031479,
|
|
491
|
+
3329325298
|
|
492
|
+
]);
|
|
493
|
+
var IV = /* @__PURE__ */ new Uint32Array([
|
|
494
|
+
1779033703,
|
|
495
|
+
3144134277,
|
|
496
|
+
1013904242,
|
|
497
|
+
2773480762,
|
|
498
|
+
1359893119,
|
|
499
|
+
2600822924,
|
|
500
|
+
528734635,
|
|
501
|
+
1541459225
|
|
502
|
+
]);
|
|
503
|
+
var SHA256_W = /* @__PURE__ */ new Uint32Array(64);
|
|
504
|
+
var SHA256 = class extends SHA2 {
|
|
505
|
+
constructor() {
|
|
506
|
+
super(64, 32, 8, false);
|
|
507
|
+
this.A = IV[0] | 0;
|
|
508
|
+
this.B = IV[1] | 0;
|
|
509
|
+
this.C = IV[2] | 0;
|
|
510
|
+
this.D = IV[3] | 0;
|
|
511
|
+
this.E = IV[4] | 0;
|
|
512
|
+
this.F = IV[5] | 0;
|
|
513
|
+
this.G = IV[6] | 0;
|
|
514
|
+
this.H = IV[7] | 0;
|
|
515
|
+
}
|
|
516
|
+
get() {
|
|
517
|
+
const { A, B, C, D, E, F, G, H } = this;
|
|
518
|
+
return [A, B, C, D, E, F, G, H];
|
|
519
|
+
}
|
|
520
|
+
// prettier-ignore
|
|
521
|
+
set(A, B, C, D, E, F, G, H) {
|
|
522
|
+
this.A = A | 0;
|
|
523
|
+
this.B = B | 0;
|
|
524
|
+
this.C = C | 0;
|
|
525
|
+
this.D = D | 0;
|
|
526
|
+
this.E = E | 0;
|
|
527
|
+
this.F = F | 0;
|
|
528
|
+
this.G = G | 0;
|
|
529
|
+
this.H = H | 0;
|
|
530
|
+
}
|
|
531
|
+
process(view, offset) {
|
|
532
|
+
for (let i = 0; i < 16; i++, offset += 4)
|
|
533
|
+
SHA256_W[i] = view.getUint32(offset, false);
|
|
534
|
+
for (let i = 16; i < 64; i++) {
|
|
535
|
+
const W15 = SHA256_W[i - 15];
|
|
536
|
+
const W2 = SHA256_W[i - 2];
|
|
537
|
+
const s0 = rotr(W15, 7) ^ rotr(W15, 18) ^ W15 >>> 3;
|
|
538
|
+
const s1 = rotr(W2, 17) ^ rotr(W2, 19) ^ W2 >>> 10;
|
|
539
|
+
SHA256_W[i] = s1 + SHA256_W[i - 7] + s0 + SHA256_W[i - 16] | 0;
|
|
540
|
+
}
|
|
541
|
+
let { A, B, C, D, E, F, G, H } = this;
|
|
542
|
+
for (let i = 0; i < 64; i++) {
|
|
543
|
+
const sigma1 = rotr(E, 6) ^ rotr(E, 11) ^ rotr(E, 25);
|
|
544
|
+
const T1 = H + sigma1 + Chi(E, F, G) + SHA256_K[i] + SHA256_W[i] | 0;
|
|
545
|
+
const sigma0 = rotr(A, 2) ^ rotr(A, 13) ^ rotr(A, 22);
|
|
546
|
+
const T2 = sigma0 + Maj(A, B, C) | 0;
|
|
547
|
+
H = G;
|
|
548
|
+
G = F;
|
|
549
|
+
F = E;
|
|
550
|
+
E = D + T1 | 0;
|
|
551
|
+
D = C;
|
|
552
|
+
C = B;
|
|
553
|
+
B = A;
|
|
554
|
+
A = T1 + T2 | 0;
|
|
555
|
+
}
|
|
556
|
+
A = A + this.A | 0;
|
|
557
|
+
B = B + this.B | 0;
|
|
558
|
+
C = C + this.C | 0;
|
|
559
|
+
D = D + this.D | 0;
|
|
560
|
+
E = E + this.E | 0;
|
|
561
|
+
F = F + this.F | 0;
|
|
562
|
+
G = G + this.G | 0;
|
|
563
|
+
H = H + this.H | 0;
|
|
564
|
+
this.set(A, B, C, D, E, F, G, H);
|
|
565
|
+
}
|
|
566
|
+
roundClean() {
|
|
567
|
+
SHA256_W.fill(0);
|
|
568
|
+
}
|
|
569
|
+
destroy() {
|
|
570
|
+
this.set(0, 0, 0, 0, 0, 0, 0, 0);
|
|
571
|
+
this.buffer.fill(0);
|
|
572
|
+
}
|
|
573
|
+
};
|
|
574
|
+
var sha256 = /* @__PURE__ */ wrapConstructor(() => new SHA256());
|
|
575
|
+
|
|
576
|
+
// src/envelope-crypto.ts
|
|
577
|
+
function signDocDigest(signDoc) {
|
|
578
|
+
const bytes2 = signDocBytes(signDoc);
|
|
579
|
+
return sha256(bytes2);
|
|
580
|
+
}
|
|
581
|
+
function encodeSignature(signature) {
|
|
582
|
+
const nodeBuffer = globalThis.Buffer;
|
|
583
|
+
if (nodeBuffer) {
|
|
584
|
+
return nodeBuffer.from(signature).toString("base64");
|
|
585
|
+
}
|
|
586
|
+
let result = "";
|
|
587
|
+
for (const byte of signature) {
|
|
588
|
+
result += String.fromCharCode(byte);
|
|
589
|
+
}
|
|
590
|
+
return btoa(result);
|
|
591
|
+
}
|
|
592
|
+
function decodeSignature(signature) {
|
|
593
|
+
const nodeBuffer = globalThis.Buffer;
|
|
594
|
+
if (nodeBuffer) {
|
|
595
|
+
return nodeBuffer.from(signature, "base64");
|
|
596
|
+
}
|
|
597
|
+
const binary = atob(signature);
|
|
598
|
+
const bytes2 = new Uint8Array(binary.length);
|
|
599
|
+
for (let i = 0; i < binary.length; i++) {
|
|
600
|
+
bytes2[i] = binary.charCodeAt(i);
|
|
601
|
+
}
|
|
602
|
+
return bytes2;
|
|
603
|
+
}
|
|
604
|
+
|
|
605
|
+
// src/done.ts
|
|
606
|
+
var DoneContractClient = class {
|
|
607
|
+
backend;
|
|
608
|
+
address;
|
|
609
|
+
buildEnvelopeFn;
|
|
610
|
+
eventSourceFactory;
|
|
611
|
+
eventsPath;
|
|
612
|
+
defaultMetadata;
|
|
613
|
+
constructor(config) {
|
|
614
|
+
this.backend = new DoneBackendClient({ baseUrl: config.baseUrl, fetch: config.fetch });
|
|
615
|
+
this.address = config.address;
|
|
616
|
+
this.buildEnvelopeFn = config.buildEnvelope;
|
|
617
|
+
this.eventSourceFactory = config.eventSource;
|
|
618
|
+
this.eventsPath = config.eventsPath ?? "/events";
|
|
619
|
+
this.defaultMetadata = config.defaultMetadata;
|
|
620
|
+
}
|
|
621
|
+
get(path, request = {}, init = {}) {
|
|
622
|
+
const promise = this.fetchQuery(path, request, init);
|
|
623
|
+
return new DoneRequest(promise);
|
|
624
|
+
}
|
|
625
|
+
async query(path, request = {}, init = {}) {
|
|
626
|
+
const response = await this.fetchQuery(path, request, init);
|
|
627
|
+
return response.json();
|
|
628
|
+
}
|
|
629
|
+
async post(path, request = {}, init = {}) {
|
|
630
|
+
return this.execute(path, request, init);
|
|
631
|
+
}
|
|
632
|
+
async run(path, request = {}, init = {}) {
|
|
633
|
+
return this.execute(path, request, init);
|
|
634
|
+
}
|
|
635
|
+
async execute(path, request = {}, init = {}) {
|
|
636
|
+
if (!this.buildEnvelopeFn) {
|
|
637
|
+
throw new Error("execute requires a buildEnvelope function in contract config");
|
|
638
|
+
}
|
|
639
|
+
const normalizedCall = {
|
|
640
|
+
path,
|
|
641
|
+
query: request.query,
|
|
642
|
+
body: request.body
|
|
643
|
+
};
|
|
644
|
+
const transactionMsg = buildTransactionMessage(
|
|
645
|
+
this.address,
|
|
646
|
+
normalizedCall,
|
|
647
|
+
request
|
|
648
|
+
);
|
|
649
|
+
const metadata = mergeMetadata(this.defaultMetadata, request.metadata, { trace_id: request.traceId, memo: request.memo, gas_limit: request.gasLimit });
|
|
650
|
+
const buildContext = {
|
|
651
|
+
msg: transactionMsg,
|
|
652
|
+
metadata,
|
|
653
|
+
path,
|
|
654
|
+
request
|
|
655
|
+
};
|
|
656
|
+
const buildResult = await this.buildEnvelopeFn(buildContext);
|
|
657
|
+
if (metadata) {
|
|
658
|
+
buildResult.envelope.metadata = buildResult.envelope.metadata ?? metadata;
|
|
659
|
+
}
|
|
660
|
+
const executeOptions = mergeExecuteOptions(buildResult.options, {
|
|
661
|
+
memo: request.memo,
|
|
662
|
+
passkey: request.passkey,
|
|
663
|
+
signal: request.signal
|
|
664
|
+
});
|
|
665
|
+
return this.backend.executeEnvelope(buildResult.envelope, executeOptions, init);
|
|
666
|
+
}
|
|
667
|
+
transaction(path, request = {}) {
|
|
668
|
+
const normalizedCall = {
|
|
669
|
+
path,
|
|
670
|
+
query: request.query,
|
|
671
|
+
body: request.body
|
|
672
|
+
};
|
|
673
|
+
const msg = buildTransactionMessage(this.address, normalizedCall, request);
|
|
674
|
+
const metadata = mergeMetadata(this.defaultMetadata, request.metadata, {
|
|
675
|
+
trace_id: request.traceId,
|
|
676
|
+
memo: request.memo,
|
|
677
|
+
gas_limit: request.gasLimit
|
|
678
|
+
});
|
|
679
|
+
return { msg, metadata };
|
|
680
|
+
}
|
|
681
|
+
subscribe(topic, handler, options = {}) {
|
|
682
|
+
const factory = this.eventSourceFactory ?? defaultEventSourceFactory;
|
|
683
|
+
const eventsBase = buildEventsUrl(this.backend.baseUrl, this.eventsPath);
|
|
684
|
+
const encodedTopic = Array.isArray(topic) ? JSON.stringify(topic) : topic;
|
|
685
|
+
const url = `${eventsBase}?topic=${encodeURIComponent(encodedTopic)}`;
|
|
686
|
+
const source = factory(url);
|
|
687
|
+
const messageListener = (event) => {
|
|
688
|
+
if (options.rawEvent) {
|
|
689
|
+
handler(event);
|
|
690
|
+
return;
|
|
691
|
+
}
|
|
692
|
+
const data = event.data;
|
|
693
|
+
try {
|
|
694
|
+
handler(JSON.parse(data));
|
|
695
|
+
} catch {
|
|
696
|
+
handler(data);
|
|
697
|
+
}
|
|
698
|
+
};
|
|
699
|
+
if (typeof source.addEventListener === "function") {
|
|
700
|
+
source.addEventListener("message", messageListener);
|
|
701
|
+
} else {
|
|
702
|
+
source.onmessage = messageListener;
|
|
703
|
+
}
|
|
704
|
+
if (options.onError) {
|
|
705
|
+
if (typeof source.addEventListener === "function") {
|
|
706
|
+
source.addEventListener("error", options.onError);
|
|
707
|
+
} else {
|
|
708
|
+
source.onerror = options.onError;
|
|
709
|
+
}
|
|
710
|
+
}
|
|
711
|
+
const cleanup = () => {
|
|
712
|
+
if (typeof source.removeEventListener === "function") {
|
|
713
|
+
source.removeEventListener("message", messageListener);
|
|
714
|
+
if (options.onError) {
|
|
715
|
+
source.removeEventListener("error", options.onError);
|
|
716
|
+
}
|
|
717
|
+
}
|
|
718
|
+
source.close();
|
|
719
|
+
};
|
|
720
|
+
if (options.signal) {
|
|
721
|
+
if (options.signal.aborted) {
|
|
722
|
+
cleanup();
|
|
723
|
+
} else {
|
|
724
|
+
options.signal.addEventListener("abort", cleanup, { once: true });
|
|
725
|
+
}
|
|
726
|
+
}
|
|
727
|
+
return cleanup;
|
|
728
|
+
}
|
|
729
|
+
publishCode(request, init = {}) {
|
|
730
|
+
return this.backend.publishCode(
|
|
731
|
+
{
|
|
732
|
+
contract: this.address,
|
|
733
|
+
script: request.script,
|
|
734
|
+
msg: request.msg
|
|
735
|
+
},
|
|
736
|
+
init
|
|
737
|
+
);
|
|
738
|
+
}
|
|
739
|
+
buildEnvelope(draft) {
|
|
740
|
+
return buildEnvelope(draft);
|
|
741
|
+
}
|
|
742
|
+
signDocDigest(envelope) {
|
|
743
|
+
return signDocDigest(toSignDoc(envelope));
|
|
744
|
+
}
|
|
745
|
+
get baseUrl() {
|
|
746
|
+
return this.backend.baseUrl;
|
|
747
|
+
}
|
|
748
|
+
async fetchQuery(path, request, init = {}) {
|
|
749
|
+
const call = { path, query: request.query, body: request.body };
|
|
750
|
+
return this.backend.queryContractRaw(this.address, call, init);
|
|
751
|
+
}
|
|
752
|
+
};
|
|
753
|
+
var DoneRequest = class {
|
|
754
|
+
constructor(promise) {
|
|
755
|
+
this.promise = promise;
|
|
756
|
+
}
|
|
757
|
+
then(onfulfilled, onrejected) {
|
|
758
|
+
return this.promise.then(onfulfilled, onrejected);
|
|
759
|
+
}
|
|
760
|
+
catch(onrejected) {
|
|
761
|
+
return this.promise.catch(onrejected);
|
|
762
|
+
}
|
|
763
|
+
finally(onfinally) {
|
|
764
|
+
return this.promise.finally(onfinally);
|
|
765
|
+
}
|
|
766
|
+
json() {
|
|
767
|
+
return this.promise.then((response) => response.json());
|
|
768
|
+
}
|
|
769
|
+
text() {
|
|
770
|
+
return this.promise.then((response) => response.text());
|
|
771
|
+
}
|
|
772
|
+
arrayBuffer() {
|
|
773
|
+
return this.promise.then((response) => response.arrayBuffer());
|
|
774
|
+
}
|
|
775
|
+
};
|
|
776
|
+
function mergeMetadata(...entries) {
|
|
777
|
+
const merged = {};
|
|
778
|
+
for (const entry of entries) {
|
|
779
|
+
if (!entry) continue;
|
|
780
|
+
if (entry.trace_id) merged.trace_id = entry.trace_id;
|
|
781
|
+
if (entry.memo) merged.memo = entry.memo;
|
|
782
|
+
if (typeof entry.gas_limit === "number") merged.gas_limit = entry.gas_limit;
|
|
783
|
+
}
|
|
784
|
+
return Object.keys(merged).length > 0 ? merged : void 0;
|
|
785
|
+
}
|
|
786
|
+
function mergeExecuteOptions(base, overrides) {
|
|
787
|
+
if (!base && !overrides.memo && !overrides.passkey && !overrides.signal) {
|
|
788
|
+
return void 0;
|
|
789
|
+
}
|
|
790
|
+
return {
|
|
791
|
+
memo: overrides.memo ?? base?.memo,
|
|
792
|
+
passkey: overrides.passkey ?? base?.passkey,
|
|
793
|
+
signal: overrides.signal ?? base?.signal
|
|
794
|
+
};
|
|
795
|
+
}
|
|
796
|
+
function defaultEventSourceFactory(url) {
|
|
797
|
+
if (typeof EventSource === "undefined") {
|
|
798
|
+
throw new Error("EventSource is not available in this environment");
|
|
799
|
+
}
|
|
800
|
+
return new EventSource(url);
|
|
801
|
+
}
|
|
802
|
+
function buildEventsUrl(baseUrl, eventsPath) {
|
|
803
|
+
const normalized = eventsPath.startsWith("/") ? eventsPath : `/${eventsPath}`;
|
|
804
|
+
return `${baseUrl.replace(/\/$/, "")}${normalized}`;
|
|
805
|
+
}
|
|
806
|
+
function resolveFetch(fn) {
|
|
807
|
+
if (fn) {
|
|
808
|
+
return typeof fn === "function" ? fn : (() => {
|
|
809
|
+
throw new Error("provided fetch implementation is not a function");
|
|
810
|
+
})();
|
|
811
|
+
}
|
|
812
|
+
if (typeof fetch === "function") {
|
|
813
|
+
return fetch.bind(globalThis);
|
|
814
|
+
}
|
|
815
|
+
throw new Error("global fetch is not available; configure Done with a fetch implementation via Done.config");
|
|
816
|
+
}
|
|
817
|
+
function resolveEventSource(factory) {
|
|
818
|
+
if (factory) return factory;
|
|
819
|
+
if (typeof EventSource === "function") {
|
|
820
|
+
return (url) => new EventSource(url);
|
|
821
|
+
}
|
|
822
|
+
return void 0;
|
|
823
|
+
}
|
|
824
|
+
function normalizeConfig(input = {}, base) {
|
|
825
|
+
const previous = base ?? {
|
|
826
|
+
doneHttp: "https://doneHttp.done.zone",
|
|
827
|
+
doneEvents: "https://doneEvents.done.zone",
|
|
828
|
+
fetch: resolveFetch(),
|
|
829
|
+
eventSource: resolveEventSource(),
|
|
830
|
+
envelopeBuilder: void 0
|
|
831
|
+
};
|
|
832
|
+
return {
|
|
833
|
+
doneHttp: input.doneHttp ?? previous.doneHttp,
|
|
834
|
+
doneEvents: input.doneEvents ?? previous.doneEvents,
|
|
835
|
+
fetch: resolveFetch(input.fetch ?? previous.fetch),
|
|
836
|
+
eventSource: resolveEventSource(input.eventSource ?? previous.eventSource),
|
|
837
|
+
envelopeBuilder: input.envelopeBuilder ?? input.signer ?? previous.envelopeBuilder
|
|
838
|
+
};
|
|
839
|
+
}
|
|
840
|
+
function resolveRoute(raw, base, extraSearch) {
|
|
841
|
+
const url = new URL(raw, base);
|
|
842
|
+
if (extraSearch) {
|
|
843
|
+
for (const [key, value] of Object.entries(extraSearch)) {
|
|
844
|
+
url.searchParams.set(key, String(value));
|
|
845
|
+
}
|
|
846
|
+
}
|
|
847
|
+
const pathSegments = url.pathname.replace(/^\/+/, "").split("/");
|
|
848
|
+
const contract = pathSegments.shift();
|
|
849
|
+
if (!contract) {
|
|
850
|
+
throw new Error("route must include contract address as first path segment");
|
|
851
|
+
}
|
|
852
|
+
const path = pathSegments.length > 0 ? `/${pathSegments.join("/")}` : "/";
|
|
853
|
+
const queryRecord = searchParamsToRecord(url.searchParams);
|
|
854
|
+
return {
|
|
855
|
+
url,
|
|
856
|
+
contract,
|
|
857
|
+
path,
|
|
858
|
+
query: Object.keys(queryRecord).length > 0 ? queryRecord : void 0
|
|
859
|
+
};
|
|
860
|
+
}
|
|
861
|
+
function searchParamsToRecord(params) {
|
|
862
|
+
const record = {};
|
|
863
|
+
for (const [key, value] of params) {
|
|
864
|
+
const existing = record[key];
|
|
865
|
+
if (existing === void 0) {
|
|
866
|
+
record[key] = value;
|
|
867
|
+
} else if (Array.isArray(existing)) {
|
|
868
|
+
existing.push(value);
|
|
869
|
+
} else {
|
|
870
|
+
record[key] = [existing, value];
|
|
871
|
+
}
|
|
872
|
+
}
|
|
873
|
+
return record;
|
|
874
|
+
}
|
|
875
|
+
function normalizeContractBody(body) {
|
|
876
|
+
if (body === void 0 || body === null) {
|
|
877
|
+
return body;
|
|
878
|
+
}
|
|
879
|
+
if (isPlainObject(body) || Array.isArray(body)) {
|
|
880
|
+
return body;
|
|
881
|
+
}
|
|
882
|
+
if (typeof body === "string") {
|
|
883
|
+
try {
|
|
884
|
+
return JSON.parse(body);
|
|
885
|
+
} catch (err) {
|
|
886
|
+
throw new Error("string bodies must contain JSON payloads when invoking Done.run/query");
|
|
887
|
+
}
|
|
888
|
+
}
|
|
889
|
+
if (body instanceof URLSearchParams) {
|
|
890
|
+
return Object.fromEntries(Array.from(body));
|
|
891
|
+
}
|
|
892
|
+
throw new Error("unsupported body type for Done.run/query; provide a JSON-serialisable value");
|
|
893
|
+
}
|
|
894
|
+
function isPlainObject(value) {
|
|
895
|
+
if (value === null || typeof value !== "object") return false;
|
|
896
|
+
const proto = Object.getPrototypeOf(value);
|
|
897
|
+
return proto === Object.prototype || proto === null;
|
|
898
|
+
}
|
|
899
|
+
function normalizeContractSegment(value) {
|
|
900
|
+
if (!value) {
|
|
901
|
+
throw new Error("contract identifier cannot be empty");
|
|
902
|
+
}
|
|
903
|
+
return value.replace(/^\/+/u, "").replace(/\/+$/u, "");
|
|
904
|
+
}
|
|
905
|
+
var DoneInstance = class _DoneInstance {
|
|
906
|
+
settings;
|
|
907
|
+
backend;
|
|
908
|
+
CURRENT_ENVELOPE_VERSION = CURRENT_ENVELOPE_VERSION;
|
|
909
|
+
buildEnvelope = buildEnvelope;
|
|
910
|
+
signDocDigest = signDocDigest;
|
|
911
|
+
toSignDoc = toSignDoc;
|
|
912
|
+
constructor(input) {
|
|
913
|
+
this.settings = normalizeConfig(input);
|
|
914
|
+
this.backend = new DoneBackendClient({ baseUrl: this.settings.doneHttp, fetch: this.settings.fetch });
|
|
915
|
+
}
|
|
916
|
+
async run(url, init = {}) {
|
|
917
|
+
const {
|
|
918
|
+
body: rawBody,
|
|
919
|
+
funds,
|
|
920
|
+
memo,
|
|
921
|
+
traceId,
|
|
922
|
+
gasLimit,
|
|
923
|
+
passkey,
|
|
924
|
+
metadata,
|
|
925
|
+
search,
|
|
926
|
+
...rest
|
|
927
|
+
} = init;
|
|
928
|
+
const fetchInit = { ...rest };
|
|
929
|
+
const resolved = resolveRoute(url, this.settings.doneHttp, search);
|
|
930
|
+
const contractBody = normalizeContractBody(rawBody);
|
|
931
|
+
const call = {
|
|
932
|
+
path: resolved.path,
|
|
933
|
+
query: resolved.query,
|
|
934
|
+
body: contractBody
|
|
935
|
+
};
|
|
936
|
+
const msg = buildTransactionMessage(resolved.contract, call, { funds });
|
|
937
|
+
const mergedMetadata = mergeMetadata(metadata, {
|
|
938
|
+
trace_id: traceId,
|
|
939
|
+
memo,
|
|
940
|
+
gas_limit: gasLimit
|
|
941
|
+
});
|
|
942
|
+
const builder = this.requireEnvelopeBuilder();
|
|
943
|
+
const request = {
|
|
944
|
+
body: contractBody,
|
|
945
|
+
query: resolved.query,
|
|
946
|
+
funds,
|
|
947
|
+
memo,
|
|
948
|
+
traceId,
|
|
949
|
+
gasLimit,
|
|
950
|
+
metadata: mergedMetadata,
|
|
951
|
+
passkey,
|
|
952
|
+
signal: fetchInit.signal
|
|
953
|
+
};
|
|
954
|
+
const result = await Promise.resolve(
|
|
955
|
+
builder({
|
|
956
|
+
msg,
|
|
957
|
+
metadata: mergedMetadata,
|
|
958
|
+
path: resolved.path,
|
|
959
|
+
request
|
|
960
|
+
})
|
|
961
|
+
);
|
|
962
|
+
if (mergedMetadata) {
|
|
963
|
+
result.envelope.metadata = result.envelope.metadata ?? mergedMetadata;
|
|
964
|
+
}
|
|
965
|
+
const executeOptions = mergeExecuteOptions(result.options, {
|
|
966
|
+
memo,
|
|
967
|
+
passkey,
|
|
968
|
+
signal: fetchInit.signal
|
|
969
|
+
});
|
|
970
|
+
return this.backend.executeEnvelope(result.envelope, executeOptions ?? {}, fetchInit);
|
|
971
|
+
}
|
|
972
|
+
async query(url, init = {}) {
|
|
973
|
+
const { body: rawBody, search, ...rest } = init;
|
|
974
|
+
const fetchInit = { ...rest };
|
|
975
|
+
const resolved = resolveRoute(url, this.settings.doneHttp, search);
|
|
976
|
+
const contractBody = normalizeContractBody(rawBody);
|
|
977
|
+
const call = {
|
|
978
|
+
path: resolved.path,
|
|
979
|
+
query: resolved.query,
|
|
980
|
+
body: contractBody
|
|
981
|
+
};
|
|
982
|
+
return this.backend.queryContract(resolved.contract, call, fetchInit);
|
|
983
|
+
}
|
|
984
|
+
subscribe(eventsUrl, topic, handler, options = {}) {
|
|
985
|
+
const factory = this.settings.eventSource ?? defaultEventSourceFactory;
|
|
986
|
+
if (!factory) {
|
|
987
|
+
throw new Error("EventSource is not available; configure Done with an eventSource factory");
|
|
988
|
+
}
|
|
989
|
+
const url = new URL(eventsUrl, this.settings.doneEvents);
|
|
990
|
+
const topicValue = Array.isArray(topic) ? JSON.stringify(topic) : topic;
|
|
991
|
+
url.searchParams.set("topic", topicValue);
|
|
992
|
+
const source = factory(url.toString());
|
|
993
|
+
const messageListener = (event) => {
|
|
994
|
+
if (options.rawEvent) {
|
|
995
|
+
handler(event);
|
|
996
|
+
return;
|
|
997
|
+
}
|
|
998
|
+
try {
|
|
999
|
+
handler(JSON.parse(event.data));
|
|
1000
|
+
} catch {
|
|
1001
|
+
handler(event.data);
|
|
1002
|
+
}
|
|
1003
|
+
};
|
|
1004
|
+
if (typeof source.addEventListener === "function") {
|
|
1005
|
+
source.addEventListener("message", messageListener);
|
|
1006
|
+
} else {
|
|
1007
|
+
source.onmessage = messageListener;
|
|
1008
|
+
}
|
|
1009
|
+
if (options.onError) {
|
|
1010
|
+
if (typeof source.addEventListener === "function") {
|
|
1011
|
+
source.addEventListener("error", options.onError);
|
|
1012
|
+
} else {
|
|
1013
|
+
source.onerror = options.onError;
|
|
1014
|
+
}
|
|
1015
|
+
}
|
|
1016
|
+
const cleanup = () => {
|
|
1017
|
+
if (typeof source.removeEventListener === "function") {
|
|
1018
|
+
source.removeEventListener("message", messageListener);
|
|
1019
|
+
if (options.onError) {
|
|
1020
|
+
source.removeEventListener("error", options.onError);
|
|
1021
|
+
}
|
|
1022
|
+
}
|
|
1023
|
+
source.close();
|
|
1024
|
+
};
|
|
1025
|
+
if (options.signal) {
|
|
1026
|
+
if (options.signal.aborted) {
|
|
1027
|
+
cleanup();
|
|
1028
|
+
} else {
|
|
1029
|
+
options.signal.addEventListener("abort", cleanup, { once: true });
|
|
1030
|
+
}
|
|
1031
|
+
}
|
|
1032
|
+
return cleanup;
|
|
1033
|
+
}
|
|
1034
|
+
config(update) {
|
|
1035
|
+
this.settings = normalizeConfig(update, this.settings);
|
|
1036
|
+
this.backend = new DoneBackendClient({ baseUrl: this.settings.doneHttp, fetch: this.settings.fetch });
|
|
1037
|
+
}
|
|
1038
|
+
create(update = {}) {
|
|
1039
|
+
const merged = normalizeConfig(update, this.settings);
|
|
1040
|
+
return new _DoneInstance({
|
|
1041
|
+
doneHttp: merged.doneHttp,
|
|
1042
|
+
doneEvents: merged.doneEvents,
|
|
1043
|
+
fetch: merged.fetch,
|
|
1044
|
+
eventSource: merged.eventSource,
|
|
1045
|
+
envelopeBuilder: merged.envelopeBuilder
|
|
1046
|
+
});
|
|
1047
|
+
}
|
|
1048
|
+
contract(config, maybeConfig) {
|
|
1049
|
+
if (typeof config === "string") {
|
|
1050
|
+
if (!maybeConfig) {
|
|
1051
|
+
return this.buildContractHandle(config);
|
|
1052
|
+
}
|
|
1053
|
+
return new DoneContractClient({
|
|
1054
|
+
baseUrl: config,
|
|
1055
|
+
...maybeConfig,
|
|
1056
|
+
buildEnvelope: maybeConfig.buildEnvelope ?? this.settings.envelopeBuilder,
|
|
1057
|
+
fetch: maybeConfig.fetch ?? this.settings.fetch,
|
|
1058
|
+
eventSource: maybeConfig.eventSource ?? this.settings.eventSource
|
|
1059
|
+
});
|
|
1060
|
+
}
|
|
1061
|
+
return new DoneContractClient({
|
|
1062
|
+
...config,
|
|
1063
|
+
baseUrl: config.baseUrl,
|
|
1064
|
+
buildEnvelope: config.buildEnvelope ?? this.settings.envelopeBuilder,
|
|
1065
|
+
fetch: config.fetch ?? this.settings.fetch,
|
|
1066
|
+
eventSource: config.eventSource ?? this.settings.eventSource
|
|
1067
|
+
});
|
|
1068
|
+
}
|
|
1069
|
+
requireEnvelopeBuilder() {
|
|
1070
|
+
if (!this.settings.envelopeBuilder) {
|
|
1071
|
+
throw new Error("Done.run requires an envelope builder; configure Done.config({ signer: ... }) first");
|
|
1072
|
+
}
|
|
1073
|
+
return this.settings.envelopeBuilder;
|
|
1074
|
+
}
|
|
1075
|
+
buildContractHandle(contract) {
|
|
1076
|
+
const address = normalizeContractSegment(contract);
|
|
1077
|
+
const client = new DoneContractClient({
|
|
1078
|
+
baseUrl: this.settings.doneHttp,
|
|
1079
|
+
address,
|
|
1080
|
+
buildEnvelope: this.settings.envelopeBuilder,
|
|
1081
|
+
fetch: this.settings.fetch,
|
|
1082
|
+
eventSource: this.settings.eventSource
|
|
1083
|
+
});
|
|
1084
|
+
return client;
|
|
1085
|
+
}
|
|
1086
|
+
};
|
|
1087
|
+
var Done = new DoneInstance();
|
|
1088
|
+
|
|
1089
|
+
// src/auth.ts
|
|
1090
|
+
function createPasskeyEnvelopeBuilder(options) {
|
|
1091
|
+
return async (ctx) => {
|
|
1092
|
+
const [userId, nonce, expiresAt, publicKey, agent, forwarder, metadata] = await Promise.all([
|
|
1093
|
+
resolve(options.userId, ctx),
|
|
1094
|
+
resolve(options.nonce, ctx),
|
|
1095
|
+
resolve(options.expiresAt, ctx),
|
|
1096
|
+
resolve(options.publicKey, ctx),
|
|
1097
|
+
resolve(options.agent, ctx),
|
|
1098
|
+
resolve(options.forwarder, ctx),
|
|
1099
|
+
resolve(options.metadata, ctx)
|
|
1100
|
+
]);
|
|
1101
|
+
assertDefined(userId, "userId");
|
|
1102
|
+
assertDefined(nonce, "nonce");
|
|
1103
|
+
assertDefined(expiresAt, "expiresAt");
|
|
1104
|
+
assertDefined(publicKey, "publicKey");
|
|
1105
|
+
const mergedMetadata = combineMetadata(ctx.metadata, metadata);
|
|
1106
|
+
const draft = {
|
|
1107
|
+
user_id: userId,
|
|
1108
|
+
msgs: [ctx.msg],
|
|
1109
|
+
nonce,
|
|
1110
|
+
expires_at: expiresAt,
|
|
1111
|
+
role: options.role ?? "Passkey",
|
|
1112
|
+
agent: agent ?? void 0,
|
|
1113
|
+
forwarder: forwarder ?? void 0,
|
|
1114
|
+
metadata: mergedMetadata,
|
|
1115
|
+
signatures: {}
|
|
1116
|
+
};
|
|
1117
|
+
const signDoc = toSignDoc(draft);
|
|
1118
|
+
const signature = await options.sign(signDoc, ctx);
|
|
1119
|
+
draft.signatures = {
|
|
1120
|
+
passkey: normalizeSignature(signature)
|
|
1121
|
+
};
|
|
1122
|
+
const envelope = buildEnvelope(draft);
|
|
1123
|
+
envelope.metadata = envelope.metadata ?? mergedMetadata;
|
|
1124
|
+
const passkeyOption = { publicKey };
|
|
1125
|
+
const executeOptions = { passkey: passkeyOption };
|
|
1126
|
+
return makeResult(envelope, executeOptions);
|
|
1127
|
+
};
|
|
1128
|
+
}
|
|
1129
|
+
function createSessionEnvelopeBuilder(options) {
|
|
1130
|
+
return async (ctx) => {
|
|
1131
|
+
const [userId, sessionId, nonce, expiresAt, agent, forwarder, metadata] = await Promise.all([
|
|
1132
|
+
resolve(options.userId, ctx),
|
|
1133
|
+
resolve(options.sessionId, ctx),
|
|
1134
|
+
resolve(options.nonce, ctx),
|
|
1135
|
+
resolve(options.expiresAt, ctx),
|
|
1136
|
+
resolve(options.agent, ctx),
|
|
1137
|
+
resolve(options.forwarder, ctx),
|
|
1138
|
+
resolve(options.metadata, ctx)
|
|
1139
|
+
]);
|
|
1140
|
+
assertDefined(userId, "userId");
|
|
1141
|
+
assertDefined(sessionId, "sessionId");
|
|
1142
|
+
assertDefined(nonce, "nonce");
|
|
1143
|
+
assertDefined(expiresAt, "expiresAt");
|
|
1144
|
+
const mergedMetadata = combineMetadata(ctx.metadata, metadata);
|
|
1145
|
+
const draft = {
|
|
1146
|
+
user_id: userId,
|
|
1147
|
+
session_id: sessionId,
|
|
1148
|
+
msgs: [ctx.msg],
|
|
1149
|
+
nonce,
|
|
1150
|
+
expires_at: expiresAt,
|
|
1151
|
+
role: options.role ?? "Session",
|
|
1152
|
+
agent: agent ?? void 0,
|
|
1153
|
+
forwarder: forwarder ?? void 0,
|
|
1154
|
+
metadata: mergedMetadata,
|
|
1155
|
+
signatures: {}
|
|
1156
|
+
};
|
|
1157
|
+
const signDoc = toSignDoc(draft);
|
|
1158
|
+
const signature = await options.sign(signDoc, ctx);
|
|
1159
|
+
draft.signatures = {
|
|
1160
|
+
session: normalizeSignature(signature)
|
|
1161
|
+
};
|
|
1162
|
+
const envelope = buildEnvelope(draft);
|
|
1163
|
+
envelope.metadata = envelope.metadata ?? mergedMetadata;
|
|
1164
|
+
return makeResult(envelope, void 0);
|
|
1165
|
+
};
|
|
1166
|
+
}
|
|
1167
|
+
function normalizeSignature(signature) {
|
|
1168
|
+
if (typeof signature === "string") {
|
|
1169
|
+
return signature;
|
|
1170
|
+
}
|
|
1171
|
+
return encodeSignature(signature);
|
|
1172
|
+
}
|
|
1173
|
+
function combineMetadata(base, override) {
|
|
1174
|
+
const merged = {};
|
|
1175
|
+
for (const entry of [base, override]) {
|
|
1176
|
+
if (!entry) continue;
|
|
1177
|
+
if (entry.trace_id) merged.trace_id = entry.trace_id;
|
|
1178
|
+
if (entry.memo) merged.memo = entry.memo;
|
|
1179
|
+
if (typeof entry.gas_limit === "number") merged.gas_limit = entry.gas_limit;
|
|
1180
|
+
}
|
|
1181
|
+
return Object.keys(merged).length > 0 ? merged : void 0;
|
|
1182
|
+
}
|
|
1183
|
+
function makeResult(envelope, options) {
|
|
1184
|
+
return options ? { envelope, options } : { envelope };
|
|
1185
|
+
}
|
|
1186
|
+
function resolve(value, ctx) {
|
|
1187
|
+
if (typeof value === "function") {
|
|
1188
|
+
return Promise.resolve(value(ctx));
|
|
1189
|
+
}
|
|
1190
|
+
return Promise.resolve(value);
|
|
1191
|
+
}
|
|
1192
|
+
function assertDefined(value, name) {
|
|
1193
|
+
if (value === void 0 || value === null) {
|
|
1194
|
+
throw new Error(`${name} must be provided for envelope builder`);
|
|
1195
|
+
}
|
|
1196
|
+
}
|
|
1197
|
+
export {
|
|
1198
|
+
CURRENT_ENVELOPE_VERSION,
|
|
1199
|
+
Done,
|
|
1200
|
+
DoneBackendClient,
|
|
1201
|
+
DoneContractClient,
|
|
1202
|
+
DoneRequest,
|
|
1203
|
+
buildEnvelope,
|
|
1204
|
+
buildQueryMessage,
|
|
1205
|
+
buildTransactionMessage,
|
|
1206
|
+
createDevEnvelopeBuilder,
|
|
1207
|
+
createPasskeyEnvelopeBuilder,
|
|
1208
|
+
createSessionEnvelopeBuilder,
|
|
1209
|
+
decodeSignature,
|
|
1210
|
+
encodeSignature,
|
|
1211
|
+
signDocBytes,
|
|
1212
|
+
signDocDigest,
|
|
1213
|
+
toSignDoc
|
|
1214
|
+
};
|
|
1215
|
+
/*! Bundled license information:
|
|
1216
|
+
|
|
1217
|
+
@noble/hashes/esm/utils.js:
|
|
1218
|
+
(*! noble-hashes - MIT License (c) 2022 Paul Miller (paulmillr.com) *)
|
|
1219
|
+
*/
|