@donezone/client 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +128 -0
- package/dist/auth.d.ts +29 -0
- package/dist/auth.d.ts.map +1 -0
- package/dist/auth.js +112 -0
- package/dist/client.d.ts +31 -0
- package/dist/client.d.ts.map +1 -0
- package/dist/client.js +108 -0
- package/dist/done.d.ts +52 -0
- package/dist/done.d.ts.map +1 -0
- package/dist/done.js +473 -0
- package/dist/envelope.d.ts +29 -0
- package/dist/envelope.d.ts.map +1 -0
- package/dist/envelope.js +98 -0
- package/dist/index.d.ts +10 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +7 -0
- package/dist/messages.d.ts +4 -0
- package/dist/messages.d.ts.map +1 -0
- package/dist/messages.js +46 -0
- package/dist/types.d.ts +187 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +1 -0
- package/package.json +30 -0
package/README.md
ADDED
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
# @donezone/client
|
|
2
|
+
|
|
3
|
+
Client-side helpers for interacting with the Done execution stack from browsers or Node. The package mirrors the structure of the backend `Done` API—contract calls are described as HTTP-style requests, wrapped into CosmWasm messages, packed into auth envelopes, and finally submitted to the Done HTTP gateway.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- Envelope utilities (`buildEnvelope`, `toSignDoc`, `signDocDigest`) that follow the router’s signing rules.
|
|
8
|
+
- Done HTTP-aware transport via `DoneBackendClient` for `/query`, `/tx`, and quota inspection.
|
|
9
|
+
- Contract helpers for building `WasmMsg::Execute` payloads from HTTP-like routes, reusing the ergonomics of the `Done` runtime.
|
|
10
|
+
|
|
11
|
+
## Usage
|
|
12
|
+
|
|
13
|
+
### High-level Done facade
|
|
14
|
+
|
|
15
|
+
```ts
|
|
16
|
+
import {
|
|
17
|
+
Done,
|
|
18
|
+
createPasskeyEnvelopeBuilder,
|
|
19
|
+
signDocDigest,
|
|
20
|
+
} from "@donezone/client";
|
|
21
|
+
|
|
22
|
+
Done.config({
|
|
23
|
+
doneHttp: "https://doneHttp.done.zone",
|
|
24
|
+
doneEvents: "https://doneEvents.done.zone",
|
|
25
|
+
signer: createPasskeyEnvelopeBuilder({
|
|
26
|
+
userId: "user-1",
|
|
27
|
+
nonce: async () => Number(new Date()),
|
|
28
|
+
expiresAt: () => Math.floor(Date.now() / 1000) + 300,
|
|
29
|
+
publicKey: () => storedPasskey.publicKey,
|
|
30
|
+
sign: async (signDoc) => {
|
|
31
|
+
const digest = signDocDigest(signDoc);
|
|
32
|
+
return await signWithPasskeyHardware(digest); // returns Uint8Array or base64
|
|
33
|
+
},
|
|
34
|
+
}),
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
await Done.run("/done1contract123/buy", {
|
|
38
|
+
body: { minAmountOut: "1" },
|
|
39
|
+
funds: { uusd: "100" },
|
|
40
|
+
memo: "demo purchase",
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
const price = await Done.query("/done1contract123/price");
|
|
44
|
+
|
|
45
|
+
const stop = Done.subscribe(
|
|
46
|
+
"/done1contract123/events",
|
|
47
|
+
"PriceChange",
|
|
48
|
+
(event) => {
|
|
49
|
+
console.log("new price", event.newPrice);
|
|
50
|
+
}
|
|
51
|
+
);
|
|
52
|
+
|
|
53
|
+
// later…
|
|
54
|
+
stop();
|
|
55
|
+
|
|
56
|
+
// Contract-specific helper using just the address
|
|
57
|
+
const sale = Done.contract("done1contract123");
|
|
58
|
+
await sale.run("/buy", { body: { minAmountOut: "1" }, funds: { uusd: "100" } });
|
|
59
|
+
const priceAgain = await sale.query("/price");
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
Need a scoped client or different signer? Spawn another instance:
|
|
63
|
+
|
|
64
|
+
```ts
|
|
65
|
+
const staging = Done.create({
|
|
66
|
+
doneHttp: "https://doneHttp.staging.zone",
|
|
67
|
+
doneEvents: "https://doneEvents.staging.zone",
|
|
68
|
+
signer: createPasskeyEnvelopeBuilder({...}),
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
await staging.run("/done1contractABC/buy", { body: { minAmountOut: "5" }, funds: { uusd: "250" } });
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
You can still work with contract handles when you need per-contract hooks:
|
|
75
|
+
|
|
76
|
+
```ts
|
|
77
|
+
const sale = Done.contract({
|
|
78
|
+
baseUrl: "https://doneHttp.done.zone",
|
|
79
|
+
address: "done1contract123",
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
const recent = await sale.get("/orders", { query: { limit: 10 } }).json();
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
### Lower-level building blocks
|
|
86
|
+
|
|
87
|
+
```ts
|
|
88
|
+
import {
|
|
89
|
+
DoneBackendClient,
|
|
90
|
+
buildEnvelope,
|
|
91
|
+
signDocDigest,
|
|
92
|
+
toSignDoc,
|
|
93
|
+
} from "@donezone/client";
|
|
94
|
+
|
|
95
|
+
const backend = new DoneBackendClient({ baseUrl: "https://doneHttp.example" });
|
|
96
|
+
const contract = backend.contract("done1contract...");
|
|
97
|
+
const call = contract.transaction("/buy", {
|
|
98
|
+
body: { minAmountOut: "1" },
|
|
99
|
+
gasLimit: 500_000,
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
const envelope = buildEnvelope({
|
|
103
|
+
user_id: "user-1",
|
|
104
|
+
msgs: [call.msg],
|
|
105
|
+
nonce: 42,
|
|
106
|
+
expires_at: Math.floor(Date.now() / 1000) + 300,
|
|
107
|
+
role: "Passkey",
|
|
108
|
+
metadata: call.metadata,
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
const signDoc = toSignDoc(envelope);
|
|
112
|
+
const digest = signDocDigest(signDoc);
|
|
113
|
+
// sign digest with passkey/session key, then attach to envelope.signatures
|
|
114
|
+
|
|
115
|
+
await backend.executeEnvelope(envelope, {
|
|
116
|
+
passkey: { publicKey: "..." },
|
|
117
|
+
memo: "demo tx",
|
|
118
|
+
});
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
### Server-friendly signing helpers
|
|
122
|
+
|
|
123
|
+
The exported builders (`createPasskeyEnvelopeBuilder`, `createSessionEnvelopeBuilder`) accept plain
|
|
124
|
+
signing callbacks, so they work in Node, Bun, or browsers alike—the caller decides how to obtain
|
|
125
|
+
signatures (WebAuthn, HSM, remote service, etc.). The helpers return the envelope plus any metadata
|
|
126
|
+
the Done HTTP transport expects, keeping public/private key plumbing outside of the library.
|
|
127
|
+
|
|
128
|
+
See `packages/done-client/test/envelope.test.ts` for more end-to-end examples and expected request payloads.
|
package/dist/auth.d.ts
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { toSignDoc } from "./envelope";
|
|
2
|
+
import type { EnvelopeBuildContext, EnvelopeBuilder, EnvelopeMetadata, EnvelopeRole } from "./types";
|
|
3
|
+
type MaybePromise<T> = T | Promise<T>;
|
|
4
|
+
type ValueOrFactory<T> = T | ((ctx: EnvelopeBuildContext) => MaybePromise<T>);
|
|
5
|
+
interface CommonBuilderOptions {
|
|
6
|
+
agent?: ValueOrFactory<string | undefined>;
|
|
7
|
+
forwarder?: ValueOrFactory<string | undefined>;
|
|
8
|
+
metadata?: ValueOrFactory<EnvelopeMetadata | undefined>;
|
|
9
|
+
}
|
|
10
|
+
export interface PasskeyEnvelopeBuilderOptions extends CommonBuilderOptions {
|
|
11
|
+
userId: ValueOrFactory<string>;
|
|
12
|
+
nonce: ValueOrFactory<number>;
|
|
13
|
+
expiresAt: ValueOrFactory<number>;
|
|
14
|
+
publicKey: ValueOrFactory<string>;
|
|
15
|
+
sign: (signDoc: ReturnType<typeof toSignDoc>, ctx: EnvelopeBuildContext) => MaybePromise<Uint8Array | string>;
|
|
16
|
+
role?: Extract<EnvelopeRole, "Passkey">;
|
|
17
|
+
}
|
|
18
|
+
export interface SessionEnvelopeBuilderOptions extends CommonBuilderOptions {
|
|
19
|
+
userId: ValueOrFactory<string>;
|
|
20
|
+
sessionId: ValueOrFactory<string>;
|
|
21
|
+
nonce: ValueOrFactory<number>;
|
|
22
|
+
expiresAt: ValueOrFactory<number>;
|
|
23
|
+
sign: (signDoc: ReturnType<typeof toSignDoc>, ctx: EnvelopeBuildContext) => MaybePromise<Uint8Array | string>;
|
|
24
|
+
role?: Extract<EnvelopeRole, "Session">;
|
|
25
|
+
}
|
|
26
|
+
export declare function createPasskeyEnvelopeBuilder(options: PasskeyEnvelopeBuilderOptions): EnvelopeBuilder;
|
|
27
|
+
export declare function createSessionEnvelopeBuilder(options: SessionEnvelopeBuilderOptions): EnvelopeBuilder;
|
|
28
|
+
export {};
|
|
29
|
+
//# sourceMappingURL=auth.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../src/auth.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,SAAS,EAEV,MAAM,YAAY,CAAC;AACpB,OAAO,KAAK,EAEV,oBAAoB,EAEpB,eAAe,EACf,gBAAgB,EAChB,YAAY,EAGb,MAAM,SAAS,CAAC;AAEjB,KAAK,YAAY,CAAC,CAAC,IAAI,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;AACtC,KAAK,cAAc,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,oBAAoB,KAAK,YAAY,CAAC,CAAC,CAAC,CAAC,CAAC;AAE9E,UAAU,oBAAoB;IAC5B,KAAK,CAAC,EAAE,cAAc,CAAC,MAAM,GAAG,SAAS,CAAC,CAAC;IAC3C,SAAS,CAAC,EAAE,cAAc,CAAC,MAAM,GAAG,SAAS,CAAC,CAAC;IAC/C,QAAQ,CAAC,EAAE,cAAc,CAAC,gBAAgB,GAAG,SAAS,CAAC,CAAC;CACzD;AAED,MAAM,WAAW,6BAA8B,SAAQ,oBAAoB;IACzE,MAAM,EAAE,cAAc,CAAC,MAAM,CAAC,CAAC;IAC/B,KAAK,EAAE,cAAc,CAAC,MAAM,CAAC,CAAC;IAC9B,SAAS,EAAE,cAAc,CAAC,MAAM,CAAC,CAAC;IAClC,SAAS,EAAE,cAAc,CAAC,MAAM,CAAC,CAAC;IAClC,IAAI,EAAE,CACJ,OAAO,EAAE,UAAU,CAAC,OAAO,SAAS,CAAC,EACrC,GAAG,EAAE,oBAAoB,KACtB,YAAY,CAAC,UAAU,GAAG,MAAM,CAAC,CAAC;IACvC,IAAI,CAAC,EAAE,OAAO,CAAC,YAAY,EAAE,SAAS,CAAC,CAAC;CACzC;AAED,MAAM,WAAW,6BAA8B,SAAQ,oBAAoB;IACzE,MAAM,EAAE,cAAc,CAAC,MAAM,CAAC,CAAC;IAC/B,SAAS,EAAE,cAAc,CAAC,MAAM,CAAC,CAAC;IAClC,KAAK,EAAE,cAAc,CAAC,MAAM,CAAC,CAAC;IAC9B,SAAS,EAAE,cAAc,CAAC,MAAM,CAAC,CAAC;IAClC,IAAI,EAAE,CACJ,OAAO,EAAE,UAAU,CAAC,OAAO,SAAS,CAAC,EACrC,GAAG,EAAE,oBAAoB,KACtB,YAAY,CAAC,UAAU,GAAG,MAAM,CAAC,CAAC;IACvC,IAAI,CAAC,EAAE,OAAO,CAAC,YAAY,EAAE,SAAS,CAAC,CAAC;CACzC;AAED,wBAAgB,4BAA4B,CAC1C,OAAO,EAAE,6BAA6B,GACrC,eAAe,CA6CjB;AAED,wBAAgB,4BAA4B,CAC1C,OAAO,EAAE,6BAA6B,GACrC,eAAe,CA2CjB"}
|
package/dist/auth.js
ADDED
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
import { buildEnvelope as buildEnvelopeHelper, encodeSignature, toSignDoc, } from "./envelope";
|
|
2
|
+
export function createPasskeyEnvelopeBuilder(options) {
|
|
3
|
+
return async (ctx) => {
|
|
4
|
+
const [userId, nonce, expiresAt, publicKey, agent, forwarder, metadata] = await Promise.all([
|
|
5
|
+
resolve(options.userId, ctx),
|
|
6
|
+
resolve(options.nonce, ctx),
|
|
7
|
+
resolve(options.expiresAt, ctx),
|
|
8
|
+
resolve(options.publicKey, ctx),
|
|
9
|
+
resolve(options.agent, ctx),
|
|
10
|
+
resolve(options.forwarder, ctx),
|
|
11
|
+
resolve(options.metadata, ctx),
|
|
12
|
+
]);
|
|
13
|
+
assertDefined(userId, "userId");
|
|
14
|
+
assertDefined(nonce, "nonce");
|
|
15
|
+
assertDefined(expiresAt, "expiresAt");
|
|
16
|
+
assertDefined(publicKey, "publicKey");
|
|
17
|
+
const mergedMetadata = combineMetadata(ctx.metadata, metadata);
|
|
18
|
+
const draft = {
|
|
19
|
+
user_id: userId,
|
|
20
|
+
msgs: [ctx.msg],
|
|
21
|
+
nonce: nonce,
|
|
22
|
+
expires_at: expiresAt,
|
|
23
|
+
role: options.role ?? "Passkey",
|
|
24
|
+
agent: agent ?? undefined,
|
|
25
|
+
forwarder: forwarder ?? undefined,
|
|
26
|
+
metadata: mergedMetadata,
|
|
27
|
+
signatures: {},
|
|
28
|
+
};
|
|
29
|
+
const signDoc = toSignDoc(draft);
|
|
30
|
+
const signature = await options.sign(signDoc, ctx);
|
|
31
|
+
draft.signatures = {
|
|
32
|
+
passkey: normalizeSignature(signature),
|
|
33
|
+
};
|
|
34
|
+
const envelope = buildEnvelopeHelper(draft);
|
|
35
|
+
envelope.metadata = envelope.metadata ?? mergedMetadata;
|
|
36
|
+
const passkeyOption = { publicKey: publicKey };
|
|
37
|
+
const executeOptions = { passkey: passkeyOption };
|
|
38
|
+
return makeResult(envelope, executeOptions);
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
export function createSessionEnvelopeBuilder(options) {
|
|
42
|
+
return async (ctx) => {
|
|
43
|
+
const [userId, sessionId, nonce, expiresAt, agent, forwarder, metadata] = await Promise.all([
|
|
44
|
+
resolve(options.userId, ctx),
|
|
45
|
+
resolve(options.sessionId, ctx),
|
|
46
|
+
resolve(options.nonce, ctx),
|
|
47
|
+
resolve(options.expiresAt, ctx),
|
|
48
|
+
resolve(options.agent, ctx),
|
|
49
|
+
resolve(options.forwarder, ctx),
|
|
50
|
+
resolve(options.metadata, ctx),
|
|
51
|
+
]);
|
|
52
|
+
assertDefined(userId, "userId");
|
|
53
|
+
assertDefined(sessionId, "sessionId");
|
|
54
|
+
assertDefined(nonce, "nonce");
|
|
55
|
+
assertDefined(expiresAt, "expiresAt");
|
|
56
|
+
const mergedMetadata = combineMetadata(ctx.metadata, metadata);
|
|
57
|
+
const draft = {
|
|
58
|
+
user_id: userId,
|
|
59
|
+
session_id: sessionId,
|
|
60
|
+
msgs: [ctx.msg],
|
|
61
|
+
nonce: nonce,
|
|
62
|
+
expires_at: expiresAt,
|
|
63
|
+
role: options.role ?? "Session",
|
|
64
|
+
agent: agent ?? undefined,
|
|
65
|
+
forwarder: forwarder ?? undefined,
|
|
66
|
+
metadata: mergedMetadata,
|
|
67
|
+
signatures: {},
|
|
68
|
+
};
|
|
69
|
+
const signDoc = toSignDoc(draft);
|
|
70
|
+
const signature = await options.sign(signDoc, ctx);
|
|
71
|
+
draft.signatures = {
|
|
72
|
+
session: normalizeSignature(signature),
|
|
73
|
+
};
|
|
74
|
+
const envelope = buildEnvelopeHelper(draft);
|
|
75
|
+
envelope.metadata = envelope.metadata ?? mergedMetadata;
|
|
76
|
+
return makeResult(envelope, undefined);
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
function normalizeSignature(signature) {
|
|
80
|
+
if (typeof signature === "string") {
|
|
81
|
+
return signature;
|
|
82
|
+
}
|
|
83
|
+
return encodeSignature(signature);
|
|
84
|
+
}
|
|
85
|
+
function combineMetadata(base, override) {
|
|
86
|
+
const merged = {};
|
|
87
|
+
for (const entry of [base, override]) {
|
|
88
|
+
if (!entry)
|
|
89
|
+
continue;
|
|
90
|
+
if (entry.trace_id)
|
|
91
|
+
merged.trace_id = entry.trace_id;
|
|
92
|
+
if (entry.memo)
|
|
93
|
+
merged.memo = entry.memo;
|
|
94
|
+
if (typeof entry.gas_limit === "number")
|
|
95
|
+
merged.gas_limit = entry.gas_limit;
|
|
96
|
+
}
|
|
97
|
+
return Object.keys(merged).length > 0 ? merged : undefined;
|
|
98
|
+
}
|
|
99
|
+
function makeResult(envelope, options) {
|
|
100
|
+
return options ? { envelope, options } : { envelope };
|
|
101
|
+
}
|
|
102
|
+
function resolve(value, ctx) {
|
|
103
|
+
if (typeof value === "function") {
|
|
104
|
+
return Promise.resolve(value(ctx));
|
|
105
|
+
}
|
|
106
|
+
return Promise.resolve(value);
|
|
107
|
+
}
|
|
108
|
+
function assertDefined(value, name) {
|
|
109
|
+
if (value === undefined || value === null) {
|
|
110
|
+
throw new Error(`${name} must be provided for envelope builder`);
|
|
111
|
+
}
|
|
112
|
+
}
|
package/dist/client.d.ts
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { type EnvelopeDraft } from "./envelope";
|
|
2
|
+
import type { AuthEnvelope, DoneClientConfig, DoneContractCall, ExecuteCallOptions, ExecuteEnvelopeOptions, ExecuteResponse, PreparedTransaction, QuotaAgentResponse, QuotaForwarderResponse } from "./types";
|
|
3
|
+
export declare class DoneBackendClient {
|
|
4
|
+
readonly baseUrl: string;
|
|
5
|
+
private readonly fetchImpl;
|
|
6
|
+
constructor(config: DoneClientConfig);
|
|
7
|
+
contract(address: string): DoneContractHandle;
|
|
8
|
+
buildEnvelope(draft: EnvelopeDraft): AuthEnvelope;
|
|
9
|
+
executeEnvelope(envelope: AuthEnvelope, options?: ExecuteEnvelopeOptions, init?: RequestInit): Promise<ExecuteResponse>;
|
|
10
|
+
queryContractRaw(address: string, call: DoneContractCall, init?: RequestInit): Promise<Response>;
|
|
11
|
+
queryContract<T>(address: string, call: DoneContractCall, init?: RequestInit): Promise<T>;
|
|
12
|
+
getAgentQuota(userId: string, agent: string): Promise<QuotaAgentResponse>;
|
|
13
|
+
getForwarderQuota(address: string): Promise<QuotaForwarderResponse>;
|
|
14
|
+
}
|
|
15
|
+
export interface TransactionOptions extends ExecuteCallOptions {
|
|
16
|
+
query?: DoneContractCall["query"];
|
|
17
|
+
body?: DoneContractCall["body"];
|
|
18
|
+
}
|
|
19
|
+
export interface QueryOptions {
|
|
20
|
+
query?: DoneContractCall["query"];
|
|
21
|
+
body?: DoneContractCall["body"];
|
|
22
|
+
}
|
|
23
|
+
declare class DoneContractHandle {
|
|
24
|
+
private readonly backend;
|
|
25
|
+
readonly address: string;
|
|
26
|
+
constructor(backend: DoneBackendClient, address: string);
|
|
27
|
+
transaction(path: string, options?: TransactionOptions): PreparedTransaction;
|
|
28
|
+
query<T>(path: string, options?: QueryOptions): Promise<T>;
|
|
29
|
+
}
|
|
30
|
+
export {};
|
|
31
|
+
//# sourceMappingURL=client.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAAA,OAAO,EAAiB,KAAK,aAAa,EAAE,MAAM,YAAY,CAAC;AAE/D,OAAO,KAAK,EACV,YAAY,EACZ,gBAAgB,EAChB,gBAAgB,EAEhB,kBAAkB,EAClB,sBAAsB,EACtB,eAAe,EACf,mBAAmB,EACnB,kBAAkB,EAClB,sBAAsB,EACvB,MAAM,SAAS,CAAC;AAEjB,qBAAa,iBAAiB;IAC5B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAe;gBAE7B,MAAM,EAAE,gBAAgB;IAKpC,QAAQ,CAAC,OAAO,EAAE,MAAM;IAIxB,aAAa,CAAC,KAAK,EAAE,aAAa,GAAG,YAAY;IAI3C,eAAe,CACnB,QAAQ,EAAE,YAAY,EACtB,OAAO,GAAE,sBAA2B,EACpC,IAAI,GAAE,WAAgB,GACrB,OAAO,CAAC,eAAe,CAAC;IAyBrB,gBAAgB,CACpB,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,gBAAgB,EACtB,IAAI,GAAE,WAAgB,GACrB,OAAO,CAAC,QAAQ,CAAC;IAWd,aAAa,CAAC,CAAC,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,gBAAgB,EAAE,IAAI,GAAE,WAAgB,GAAG,OAAO,CAAC,CAAC,CAAC;IAS7F,aAAa,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,kBAAkB,CAAC;IASzE,iBAAiB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,sBAAsB,CAAC;CAQ1E;AAED,MAAM,WAAW,kBAAmB,SAAQ,kBAAkB;IAC5D,KAAK,CAAC,EAAE,gBAAgB,CAAC,OAAO,CAAC,CAAC;IAClC,IAAI,CAAC,EAAE,gBAAgB,CAAC,MAAM,CAAC,CAAC;CACjC;AAED,MAAM,WAAW,YAAY;IAC3B,KAAK,CAAC,EAAE,gBAAgB,CAAC,OAAO,CAAC,CAAC;IAClC,IAAI,CAAC,EAAE,gBAAgB,CAAC,MAAM,CAAC,CAAC;CACjC;AAED,cAAM,kBAAkB;IACV,OAAO,CAAC,QAAQ,CAAC,OAAO;IAAqB,QAAQ,CAAC,OAAO,EAAE,MAAM;gBAApD,OAAO,EAAE,iBAAiB,EAAW,OAAO,EAAE,MAAM;IAEjF,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,GAAE,kBAAuB,GAAG,mBAAmB;IAW1E,KAAK,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,GAAE,YAAiB,GAAG,OAAO,CAAC,CAAC,CAAC;CAQrE"}
|
package/dist/client.js
ADDED
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
import { buildEnvelope } from "./envelope";
|
|
2
|
+
import { buildQueryMessage, buildTransactionMessage } from "./messages";
|
|
3
|
+
export class DoneBackendClient {
|
|
4
|
+
baseUrl;
|
|
5
|
+
fetchImpl;
|
|
6
|
+
constructor(config) {
|
|
7
|
+
this.baseUrl = config.baseUrl.replace(/\/$/, "");
|
|
8
|
+
this.fetchImpl = config.fetch ?? fetch;
|
|
9
|
+
}
|
|
10
|
+
contract(address) {
|
|
11
|
+
return new DoneContractHandle(this, address);
|
|
12
|
+
}
|
|
13
|
+
buildEnvelope(draft) {
|
|
14
|
+
return buildEnvelope(draft);
|
|
15
|
+
}
|
|
16
|
+
async executeEnvelope(envelope, options = {}, init = {}) {
|
|
17
|
+
const body = {
|
|
18
|
+
envelope,
|
|
19
|
+
passkey: options.passkey,
|
|
20
|
+
memo: options.memo ?? envelope.metadata?.memo,
|
|
21
|
+
};
|
|
22
|
+
const { headers: initHeaders, signal: initSignal, method: initMethod, body: _ignoredBody, ...rest } = init;
|
|
23
|
+
const headers = new Headers(initHeaders ?? {});
|
|
24
|
+
headers.set("content-type", "application/json");
|
|
25
|
+
const res = await this.fetchImpl(`${this.baseUrl}/tx`, {
|
|
26
|
+
...rest,
|
|
27
|
+
method: initMethod ?? "POST",
|
|
28
|
+
headers,
|
|
29
|
+
body: JSON.stringify(body),
|
|
30
|
+
signal: initSignal ?? options.signal,
|
|
31
|
+
});
|
|
32
|
+
if (!res.ok) {
|
|
33
|
+
const text = await res.text().catch(() => "");
|
|
34
|
+
throw new Error(`tx failed with ${res.status}: ${text}`);
|
|
35
|
+
}
|
|
36
|
+
return res.json();
|
|
37
|
+
}
|
|
38
|
+
async queryContractRaw(address, call, init = {}) {
|
|
39
|
+
const message = buildQueryMessage(call);
|
|
40
|
+
const params = new URLSearchParams();
|
|
41
|
+
params.set("msg", JSON.stringify(message));
|
|
42
|
+
const { method: initMethod, ...rest } = init;
|
|
43
|
+
return this.fetchImpl(`${this.baseUrl}/query/${address}?${params}`, {
|
|
44
|
+
method: initMethod ?? "GET",
|
|
45
|
+
...rest,
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
async queryContract(address, call, init = {}) {
|
|
49
|
+
const res = await this.queryContractRaw(address, call, init);
|
|
50
|
+
if (!res.ok) {
|
|
51
|
+
const text = await res.text().catch(() => "");
|
|
52
|
+
throw new Error(`query failed with ${res.status}: ${text}`);
|
|
53
|
+
}
|
|
54
|
+
return res.json();
|
|
55
|
+
}
|
|
56
|
+
async getAgentQuota(userId, agent) {
|
|
57
|
+
const res = await this.fetchImpl(`${this.baseUrl}/quota/agent/${userId}/${agent}`);
|
|
58
|
+
if (!res.ok) {
|
|
59
|
+
const text = await res.text().catch(() => "");
|
|
60
|
+
throw new Error(`agent quota failed with ${res.status}: ${text}`);
|
|
61
|
+
}
|
|
62
|
+
return res.json();
|
|
63
|
+
}
|
|
64
|
+
async getForwarderQuota(address) {
|
|
65
|
+
const res = await this.fetchImpl(`${this.baseUrl}/quota/forwarder/${address}`);
|
|
66
|
+
if (!res.ok) {
|
|
67
|
+
const text = await res.text().catch(() => "");
|
|
68
|
+
throw new Error(`forwarder quota failed with ${res.status}: ${text}`);
|
|
69
|
+
}
|
|
70
|
+
return res.json();
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
class DoneContractHandle {
|
|
74
|
+
backend;
|
|
75
|
+
address;
|
|
76
|
+
constructor(backend, address) {
|
|
77
|
+
this.backend = backend;
|
|
78
|
+
this.address = address;
|
|
79
|
+
}
|
|
80
|
+
transaction(path, options = {}) {
|
|
81
|
+
const call = {
|
|
82
|
+
path,
|
|
83
|
+
query: options.query,
|
|
84
|
+
body: options.body,
|
|
85
|
+
};
|
|
86
|
+
const msg = buildTransactionMessage(this.address, call, options);
|
|
87
|
+
const metadata = metadataFromOptions(options);
|
|
88
|
+
return { msg, metadata };
|
|
89
|
+
}
|
|
90
|
+
async query(path, options = {}) {
|
|
91
|
+
const call = {
|
|
92
|
+
path,
|
|
93
|
+
query: options.query,
|
|
94
|
+
body: options.body,
|
|
95
|
+
};
|
|
96
|
+
return this.backend.queryContract(this.address, call);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
function metadataFromOptions(options) {
|
|
100
|
+
const metadata = {};
|
|
101
|
+
if (options.traceId)
|
|
102
|
+
metadata.trace_id = options.traceId;
|
|
103
|
+
if (options.memo)
|
|
104
|
+
metadata.memo = options.memo;
|
|
105
|
+
if (typeof options.gasLimit === "number")
|
|
106
|
+
metadata.gas_limit = options.gasLimit;
|
|
107
|
+
return Object.keys(metadata).length > 0 ? metadata : undefined;
|
|
108
|
+
}
|
package/dist/done.d.ts
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { buildEnvelope as buildEnvelopeHelper, signDocDigest, toSignDoc, type EnvelopeDraft } from "./envelope";
|
|
2
|
+
import type { AuthEnvelope, DoneContractConfig, DoneContractHandle, ExecuteResponse, PreparedTransaction, QueryRequest, SubscriptionOptions, TransactionRequest, DoneConfigOptions, DoneQueryOptions, DoneRunOptions } from "./types";
|
|
3
|
+
export declare class DoneContractClient {
|
|
4
|
+
private readonly backend;
|
|
5
|
+
private readonly address;
|
|
6
|
+
private readonly buildEnvelopeFn?;
|
|
7
|
+
private readonly eventSourceFactory?;
|
|
8
|
+
private readonly eventsPath;
|
|
9
|
+
private readonly defaultMetadata?;
|
|
10
|
+
constructor(config: DoneContractConfig);
|
|
11
|
+
get(path: string, request?: QueryRequest, init?: RequestInit): DoneRequest;
|
|
12
|
+
query<T>(path: string, request?: QueryRequest, init?: RequestInit): Promise<T>;
|
|
13
|
+
post(path: string, request?: TransactionRequest, init?: RequestInit): Promise<ExecuteResponse>;
|
|
14
|
+
run(path: string, request?: TransactionRequest, init?: RequestInit): Promise<ExecuteResponse>;
|
|
15
|
+
execute(path: string, request?: TransactionRequest, init?: RequestInit): Promise<ExecuteResponse>;
|
|
16
|
+
transaction(path: string, request?: TransactionRequest): PreparedTransaction;
|
|
17
|
+
subscribe(topic: string | string[], handler: (payload: unknown) => void, options?: SubscriptionOptions): () => void;
|
|
18
|
+
buildEnvelope(draft: EnvelopeDraft): AuthEnvelope;
|
|
19
|
+
signDocDigest(envelope: AuthEnvelope | EnvelopeDraft): Uint8Array;
|
|
20
|
+
get baseUrl(): string;
|
|
21
|
+
private fetchQuery;
|
|
22
|
+
}
|
|
23
|
+
export declare class DoneRequest implements PromiseLike<Response> {
|
|
24
|
+
private readonly promise;
|
|
25
|
+
constructor(promise: Promise<Response>);
|
|
26
|
+
then<TResult1 = Response, TResult2 = never>(onfulfilled?: ((value: Response) => TResult1 | PromiseLike<TResult1>) | undefined | null, onrejected?: ((reason: unknown) => TResult2 | PromiseLike<TResult2>) | undefined | null): Promise<TResult1 | TResult2>;
|
|
27
|
+
catch<TResult = never>(onrejected?: ((reason: unknown) => TResult | PromiseLike<TResult>) | undefined | null): Promise<Response | TResult>;
|
|
28
|
+
finally(onfinally?: (() => void) | undefined | null): Promise<Response>;
|
|
29
|
+
json<T = unknown>(): Promise<T>;
|
|
30
|
+
text(): Promise<string>;
|
|
31
|
+
arrayBuffer(): Promise<ArrayBuffer>;
|
|
32
|
+
}
|
|
33
|
+
declare class DoneInstance {
|
|
34
|
+
private settings;
|
|
35
|
+
private backend;
|
|
36
|
+
readonly CURRENT_ENVELOPE_VERSION = 1;
|
|
37
|
+
readonly buildEnvelope: typeof buildEnvelopeHelper;
|
|
38
|
+
readonly signDocDigest: typeof signDocDigest;
|
|
39
|
+
readonly toSignDoc: typeof toSignDoc;
|
|
40
|
+
constructor(input?: DoneConfigOptions);
|
|
41
|
+
run(url: string, init?: DoneRunOptions): Promise<ExecuteResponse>;
|
|
42
|
+
query<T = unknown>(url: string, init?: DoneQueryOptions): Promise<T>;
|
|
43
|
+
subscribe(eventsUrl: string, topic: string | string[], handler: (payload: unknown) => void, options?: SubscriptionOptions): () => void;
|
|
44
|
+
config(update: DoneConfigOptions): void;
|
|
45
|
+
create(update?: DoneConfigOptions): DoneInstance;
|
|
46
|
+
contract(config: DoneContractConfig | string, maybeConfig?: Omit<DoneContractConfig, "baseUrl">): DoneContractHandle | DoneContractClient;
|
|
47
|
+
private requireEnvelopeBuilder;
|
|
48
|
+
private buildContractHandle;
|
|
49
|
+
}
|
|
50
|
+
export declare const Done: DoneInstance;
|
|
51
|
+
export {};
|
|
52
|
+
//# sourceMappingURL=done.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"done.d.ts","sourceRoot":"","sources":["../src/done.ts"],"names":[],"mappings":"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"}
|