@dopamint-fun/open-sdk 0.1.0-dev.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 +42 -0
- package/dist/acceptance.d.ts +24 -0
- package/dist/acceptance.js +48 -0
- package/dist/agentHttp.d.ts +52 -0
- package/dist/agentHttp.js +139 -0
- package/dist/bytes.d.ts +40 -0
- package/dist/bytes.js +166 -0
- package/dist/channel.d.ts +38 -0
- package/dist/channel.js +86 -0
- package/dist/claim.d.ts +39 -0
- package/dist/claim.js +91 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.js +1006 -0
- package/dist/crypto.d.ts +3 -0
- package/dist/crypto.js +20 -0
- package/dist/identity.d.ts +32 -0
- package/dist/identity.js +100 -0
- package/dist/index.d.ts +13 -0
- package/dist/index.js +22 -0
- package/dist/keypair.d.ts +25 -0
- package/dist/keypair.js +69 -0
- package/dist/offer.d.ts +36 -0
- package/dist/offer.js +138 -0
- package/dist/registration.d.ts +53 -0
- package/dist/registration.js +104 -0
- package/dist/seatAuth.d.ts +30 -0
- package/dist/seatAuth.js +285 -0
- package/dist/session.d.ts +260 -0
- package/dist/session.js +840 -0
- package/dist/sessionCodec.d.ts +139 -0
- package/dist/sessionCodec.js +373 -0
- package/dist/sessionWire.d.ts +80 -0
- package/dist/sessionWire.js +118 -0
- package/dist/settlement.d.ts +56 -0
- package/dist/settlement.js +117 -0
- package/dist/texas.d.ts +52 -0
- package/dist/texas.js +217 -0
- package/dist/tour.d.ts +101 -0
- package/dist/tour.js +129 -0
- package/package.json +35 -0
package/dist/claim.d.ts
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import type { AgentKeypair } from "./keypair.js";
|
|
2
|
+
export declare const AGENT_CLAIM_INVITE_DOMAIN: Uint8Array<ArrayBufferLike>;
|
|
3
|
+
export declare const AGENT_CLAIM_INVITE_NONCE_BYTES = 16;
|
|
4
|
+
/** The longest an invitation may stay open: a week. */
|
|
5
|
+
export declare const AGENT_CLAIM_INVITE_MAX_WINDOW_MS: number;
|
|
6
|
+
/** `agent_id || owner-or-zero || agent_public_key || issued || expires ||
|
|
7
|
+
* nonce || signature`, every field fixed-width. */
|
|
8
|
+
export declare const AGENT_CLAIM_INVITE_TOKEN_BYTES: number;
|
|
9
|
+
export interface ClaimInvite {
|
|
10
|
+
/** 32 bytes */
|
|
11
|
+
agentId: Uint8Array;
|
|
12
|
+
/** 32 bytes, or null for whoever holds the token */
|
|
13
|
+
owner: Uint8Array | null;
|
|
14
|
+
/** 32 bytes: the key that signed, which must be the agent's current one */
|
|
15
|
+
agentPublicKey: Uint8Array;
|
|
16
|
+
issuedAtMs: bigint;
|
|
17
|
+
expiresAtMs: bigint;
|
|
18
|
+
/** 16 bytes, never all zero */
|
|
19
|
+
nonce: Uint8Array;
|
|
20
|
+
/** 64 bytes; empty until signed */
|
|
21
|
+
signature: Uint8Array;
|
|
22
|
+
}
|
|
23
|
+
/** `AgentClaimInvite::canonical_payload` -- the framed fields. */
|
|
24
|
+
export declare function claimInviteCanonicalPayload(invite: ClaimInvite): Uint8Array;
|
|
25
|
+
/** The bytes the agent's key signs, raw ed25519. */
|
|
26
|
+
export declare function claimInviteSigningBytes(invite: ClaimInvite): Uint8Array;
|
|
27
|
+
export declare function mintClaimInvite(agent: AgentKeypair, agentId: Uint8Array, options?: {
|
|
28
|
+
/** the one wallet that may accept; omit for whoever holds the link */
|
|
29
|
+
owner?: Uint8Array | null;
|
|
30
|
+
issuedAtMs?: number;
|
|
31
|
+
/** how long the link stays good; a day unless said otherwise */
|
|
32
|
+
ttlMs?: number;
|
|
33
|
+
nonce?: Uint8Array;
|
|
34
|
+
}): Promise<ClaimInvite>;
|
|
35
|
+
/** The token the link carries and the claim body posts back: 0x-hex. */
|
|
36
|
+
export declare function encodeClaimInvite(invite: ClaimInvite): string;
|
|
37
|
+
export declare function decodeClaimInvite(token: string): ClaimInvite;
|
|
38
|
+
/** Where the owner goes to accept: the agent's claim page with the token. */
|
|
39
|
+
export declare function claimInviteLink(arenaOrigin: string, agentIdHex: string, token: string): string;
|
package/dist/claim.js
ADDED
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import { randomBytes } from "node:crypto";
|
|
2
|
+
import { signRaw } from "./keypair.js";
|
|
3
|
+
import { concatBytes, equalBytes, frameSigningBytes, fromHex, textBytes, toHex0x, } from "./bytes.js";
|
|
4
|
+
/* The agent's half of a claim: an invitation its own key signs.
|
|
5
|
+
*
|
|
6
|
+
* A wallet claims an agent by signing for it in the arena's UI. That proves
|
|
7
|
+
* the wallet wants the agent and nothing about whether you, holding the
|
|
8
|
+
* agent's key, agree -- so any wallet could once claim any unclaimed agent
|
|
9
|
+
* off the roster. Now a claim is accepted only with an invitation your key
|
|
10
|
+
* minted: name the wallet allowed to accept (or nobody, for whoever holds the
|
|
11
|
+
* link), pick a window, and hand the owner the link this prints.
|
|
12
|
+
*
|
|
13
|
+
* Mirrors `AgentClaimInvite` in `dopa_open_api::claim`: the same bytes, the
|
|
14
|
+
* same token, pinned by a shared vector in the tests. */
|
|
15
|
+
export const AGENT_CLAIM_INVITE_DOMAIN = textBytes("dopa_open::agent_claim_invite::v1");
|
|
16
|
+
const CANONICAL_WIRE_VERSION = 1;
|
|
17
|
+
const INVITE_OPERATION = 4;
|
|
18
|
+
export const AGENT_CLAIM_INVITE_NONCE_BYTES = 16;
|
|
19
|
+
/** The longest an invitation may stay open: a week. */
|
|
20
|
+
export const AGENT_CLAIM_INVITE_MAX_WINDOW_MS = 7 * 24 * 60 * 60 * 1000;
|
|
21
|
+
/** `agent_id || owner-or-zero || agent_public_key || issued || expires ||
|
|
22
|
+
* nonce || signature`, every field fixed-width. */
|
|
23
|
+
export const AGENT_CLAIM_INVITE_TOKEN_BYTES = 32 + 32 + 32 + 8 + 8 + 16 + 64;
|
|
24
|
+
const ZERO_OWNER = new Uint8Array(32);
|
|
25
|
+
function u64be(value) {
|
|
26
|
+
const out = new Uint8Array(8);
|
|
27
|
+
new DataView(out.buffer).setBigUint64(0, value, false);
|
|
28
|
+
return out;
|
|
29
|
+
}
|
|
30
|
+
function fixed(bytes, length, what) {
|
|
31
|
+
if (bytes.length !== length)
|
|
32
|
+
throw new Error(`${what} must be ${length} bytes, got ${bytes.length}`);
|
|
33
|
+
return bytes;
|
|
34
|
+
}
|
|
35
|
+
/** `AgentClaimInvite::canonical_payload` -- the framed fields. */
|
|
36
|
+
export function claimInviteCanonicalPayload(invite) {
|
|
37
|
+
if (invite.expiresAtMs <= invite.issuedAtMs)
|
|
38
|
+
throw new Error("the invitation's window is empty");
|
|
39
|
+
if (invite.expiresAtMs - invite.issuedAtMs >
|
|
40
|
+
BigInt(AGENT_CLAIM_INVITE_MAX_WINDOW_MS))
|
|
41
|
+
throw new Error("an invitation may stay open for at most a week");
|
|
42
|
+
if (invite.nonce.every((byte) => byte === 0))
|
|
43
|
+
throw new Error("the invitation's nonce must not be all zero");
|
|
44
|
+
return concatBytes(AGENT_CLAIM_INVITE_DOMAIN, Uint8Array.of(0, CANONICAL_WIRE_VERSION, INVITE_OPERATION), fixed(invite.agentId, 32, "agent id"), invite.owner ? fixed(invite.owner, 32, "owner") : ZERO_OWNER, fixed(invite.agentPublicKey, 32, "agent public key"), u64be(invite.issuedAtMs), u64be(invite.expiresAtMs), fixed(invite.nonce, AGENT_CLAIM_INVITE_NONCE_BYTES, "nonce"));
|
|
45
|
+
}
|
|
46
|
+
/** The bytes the agent's key signs, raw ed25519. */
|
|
47
|
+
export function claimInviteSigningBytes(invite) {
|
|
48
|
+
return frameSigningBytes(AGENT_CLAIM_INVITE_DOMAIN, claimInviteCanonicalPayload(invite));
|
|
49
|
+
}
|
|
50
|
+
export async function mintClaimInvite(agent, agentId, options = {}) {
|
|
51
|
+
const issuedAtMs = BigInt(options.issuedAtMs ?? Date.now());
|
|
52
|
+
const ttl = options.ttlMs ?? 24 * 60 * 60 * 1000;
|
|
53
|
+
const invite = {
|
|
54
|
+
agentId,
|
|
55
|
+
owner: options.owner ?? null,
|
|
56
|
+
agentPublicKey: agent.publicKey,
|
|
57
|
+
issuedAtMs,
|
|
58
|
+
expiresAtMs: issuedAtMs + BigInt(ttl),
|
|
59
|
+
nonce: options.nonce ?? new Uint8Array(randomBytes(16)),
|
|
60
|
+
signature: new Uint8Array(),
|
|
61
|
+
};
|
|
62
|
+
invite.signature = await signRaw(agent, claimInviteSigningBytes(invite));
|
|
63
|
+
return invite;
|
|
64
|
+
}
|
|
65
|
+
/** The token the link carries and the claim body posts back: 0x-hex. */
|
|
66
|
+
export function encodeClaimInvite(invite) {
|
|
67
|
+
if (invite.signature.length !== 64)
|
|
68
|
+
throw new Error("an invitation is encoded only once it is signed");
|
|
69
|
+
return toHex0x(concatBytes(fixed(invite.agentId, 32, "agent id"), invite.owner ?? ZERO_OWNER, fixed(invite.agentPublicKey, 32, "agent public key"), u64be(invite.issuedAtMs), u64be(invite.expiresAtMs), fixed(invite.nonce, 16, "nonce"), invite.signature));
|
|
70
|
+
}
|
|
71
|
+
export function decodeClaimInvite(token) {
|
|
72
|
+
const bytes = fromHex(token.trim());
|
|
73
|
+
if (bytes.length !== AGENT_CLAIM_INVITE_TOKEN_BYTES)
|
|
74
|
+
throw new Error(`an invitation token is ${AGENT_CLAIM_INVITE_TOKEN_BYTES} bytes, got ${bytes.length}`);
|
|
75
|
+
const view = new DataView(bytes.buffer, bytes.byteOffset);
|
|
76
|
+
const owner = bytes.slice(32, 64);
|
|
77
|
+
return {
|
|
78
|
+
agentId: bytes.slice(0, 32),
|
|
79
|
+
owner: equalBytes(owner, ZERO_OWNER) ? null : owner,
|
|
80
|
+
agentPublicKey: bytes.slice(64, 96),
|
|
81
|
+
issuedAtMs: view.getBigUint64(96, false),
|
|
82
|
+
expiresAtMs: view.getBigUint64(104, false),
|
|
83
|
+
nonce: bytes.slice(112, 128),
|
|
84
|
+
signature: bytes.slice(128),
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
/** Where the owner goes to accept: the agent's claim page with the token. */
|
|
88
|
+
export function claimInviteLink(arenaOrigin, agentIdHex, token) {
|
|
89
|
+
const id = agentIdHex.startsWith("0x") ? agentIdHex : `0x${agentIdHex}`;
|
|
90
|
+
return `${arenaOrigin.replace(/\/$/, "")}/arena/agents/${id}/claim?invite=${token}`;
|
|
91
|
+
}
|
package/dist/cli.d.ts
ADDED