@dopamint-fun/open-sdk 0.2.0-dev.3 → 0.2.0-dev.5

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 CHANGED
@@ -1,4 +1,4 @@
1
- # `libs/dopa-open-client-ts`
1
+ # `libs/dopa-open/client-ts`
2
2
 
3
3
  Status: implemented
4
4
  Ownership: Optional official TypeScript SDK for DOPA-OPEN self-custody agents:
@@ -36,8 +36,8 @@ signatures, not whether this package is used. Allowed dependencies:
36
36
  ## Parity
37
37
 
38
38
  Preimages and signatures are pinned byte-identical to the Rust signer by
39
- `libs/dopa-open-client-rs/vectors/ts-signer-parity.json`, generated by
40
- `libs/dopa-open-client-rs/tests/ts_parity_vectors.rs` and replayed by
39
+ `libs/dopa-open/client-rs/vectors/ts-signer-parity.json`, generated by
40
+ `libs/dopa-open/client-rs/tests/ts_parity_vectors.rs` and replayed by
41
41
  `src/parity.test.ts` here. Regenerate with
42
42
  `WRITE_TS_PARITY_VECTORS=1 cargo test -p dopa-open-client-rs --test
43
43
  ts_parity_vectors`; a wire change updates both sides together.
package/dist/agentHttp.js CHANGED
@@ -2,7 +2,7 @@
2
2
  * tour or table request without ever holding a bearer credential.
3
3
  *
4
4
  * Byte-identical to `dopa_open_api::agent_http`, pinned by
5
- * `libs/dopa-open-api/vectors/agent_http_capability_v1.json`. A bearer token
5
+ * `libs/dopa-open/api/vectors/agent_http_capability_v1.json`. A bearer token
6
6
  * is a secret presented per request; a signature is not, so each capability is
7
7
  * bound to the method, the request target, a digest of the exact body bytes,
8
8
  * and a single-use nonce inside a bounded window. One minted to enter the
package/dist/bytes.js CHANGED
@@ -5,7 +5,7 @@
5
5
  * These helpers exist so every framing in this package spells a number the
6
6
  * same way; a preimage that drifts from the Rust client by one byte produces
7
7
  * signatures the authority silently rejects, which is why the parity vectors
8
- * in `libs/dopa-open-client-rs/vectors/` pin all of it.
8
+ * in `libs/dopa-open/client-rs/vectors/` pin all of it.
9
9
  */
10
10
  export function toHex(bytes) {
11
11
  let out = "";
package/dist/cli.js CHANGED
@@ -24,13 +24,19 @@ import { acceptAndAwaitAdmission } from "./offer.js";
24
24
  import { playTour, queueUntilSeated } from "./tour.js";
25
25
  import { joinRoomWhenComposed, MIN_ROOM_SEATS, openRoom, roomInvitePrompt, } from "./room.js";
26
26
  import { disputeHolding, JoinRefused, joinTransaction, leaveTransaction, listTournaments, matchmakingOverLine, planJoin, presentToTournament, readAgentEntry, readAgentEntrySettled, playsHeldBy, giveBackTransaction, readTournament, sponsorAndExecute, tournamentIdArg, } from "./openTournament.js";
27
- import { authorityOriginFromSessionBase, buildConsentRequest, digestForPrompt, settlementConsentPath, verifyConsentDisclosure, } from "./settlement.js";
27
+ import { authorityOriginFromSessionBase, buildConsentRequest, DEFAULT_OPEN_API_BASE_URL, digestForPrompt, settlementConsentPath, verifyConsentDisclosure, } from "./settlement.js";
28
28
  import { actionSigningBytes, joinSigningBytes, requireSessionVersion, resumeSigningBytes, SESSION_VERSION, } from "./sessionWire.js";
29
29
  import { describeNext, refusalMessageFromText } from "./refusal.js";
30
30
  function fail(message) {
31
31
  console.error(`dopa-open: ${message}`);
32
32
  process.exit(1);
33
33
  }
34
+ /** Resolves `--product-url`, falling back to `DOPA_OPEN_PRODUCT_URL` and then
35
+ * to the deployed default — the same precedence and env name the Rust CLI
36
+ * uses, so a script that sets one variable configures both binaries. */
37
+ function resolveProductUrl(explicit) {
38
+ return explicit ?? process.env.DOPA_OPEN_PRODUCT_URL ?? DEFAULT_OPEN_API_BASE_URL;
39
+ }
34
40
  const hex = (value, field) => {
35
41
  if (typeof value !== "string")
36
42
  fail(`${field} must be a hex string`);
@@ -116,9 +122,7 @@ async function commandRegister(args) {
116
122
  "dry-run": { type: "boolean", default: false },
117
123
  },
118
124
  });
119
- const productUrl = values["product-url"];
120
- if (!productUrl && !values["dry-run"])
121
- fail("--product-url is required (or pass --dry-run to print the request)");
125
+ const productUrl = resolveProductUrl(values["product-url"]);
122
126
  const agent = loadKeypair(values.key);
123
127
  const versions = (raw, flag) => {
124
128
  const list = raw.split(",").map((piece) => Number.parseInt(piece, 10));
@@ -162,7 +166,7 @@ async function commandRegister(args) {
162
166
  console.log(JSON.stringify(request, null, 2));
163
167
  return;
164
168
  }
165
- const response = await fetch(`${productUrl.replace(/\/$/, "")}/open/v1/agents`, {
169
+ const response = await fetch(`${productUrl.replace(/\/$/, "")}/v1/agents`, {
166
170
  method: "POST",
167
171
  headers: { "content-type": "application/json" },
168
172
  body: JSON.stringify(request),
@@ -225,9 +229,7 @@ async function commandName(args) {
225
229
  bio: { type: "string" },
226
230
  },
227
231
  });
228
- const productUrl = values["product-url"];
229
- if (!productUrl)
230
- fail("--product-url is required");
232
+ const productUrl = resolveProductUrl(values["product-url"]);
231
233
  if (!values["agent-id"])
232
234
  fail("--agent-id is required");
233
235
  if (!values.name && !values.handle && !values.bio)
@@ -258,7 +260,7 @@ async function commandName(args) {
258
260
  * against what they believed, and the refusal for getting it wrong is a bare
259
261
  * `stale_generation` that names neither. */
260
262
  async function readKeyState(productUrl, agentId) {
261
- const response = await fetch(`${productUrl}/open/v1/agents/${encodeURIComponent(agentId)}`);
263
+ const response = await fetch(`${productUrl}/v1/agents/${encodeURIComponent(agentId)}`);
262
264
  if (!response.ok)
263
265
  fail(`could not read agent ${agentId} (${response.status})`);
264
266
  const wire = (await response.json());
@@ -291,9 +293,7 @@ async function commandKey(args) {
291
293
  "dry-run": { type: "boolean", default: false },
292
294
  },
293
295
  });
294
- const productUrl = values["product-url"]?.replace(/\/$/, "");
295
- if (!productUrl)
296
- fail("--product-url is required");
296
+ const productUrl = resolveProductUrl(values["product-url"]).replace(/\/$/, "");
297
297
  const agentId = values["agent-id"];
298
298
  if (!agentId)
299
299
  fail("--agent-id is required");
@@ -356,7 +356,7 @@ async function commandKey(args) {
356
356
  return;
357
357
  }
358
358
  const path = retire ? "revocations" : "key-rotations";
359
- const response = await fetch(`${productUrl}/open/v1/agents/${encodeURIComponent(agentId)}/${path}`, {
359
+ const response = await fetch(`${productUrl}/v1/agents/${encodeURIComponent(agentId)}/${path}`, {
360
360
  method: "POST",
361
361
  headers: { "content-type": "application/json" },
362
362
  body: JSON.stringify(request),
@@ -486,9 +486,7 @@ async function commandPlay(args) {
486
486
  "disconnect-after-actions": { type: "string" },
487
487
  },
488
488
  });
489
- const productUrl = values["product-url"];
490
- if (!productUrl)
491
- fail("--product-url is required");
489
+ const productUrl = resolveProductUrl(values["product-url"]);
492
490
  if (!values["agent-id"])
493
491
  fail("--agent-id is required");
494
492
  /* A tour seat is played over the Product API, so it needs none of the
@@ -657,7 +655,7 @@ async function signedGet(productUrl, target, agent, agentIdHex) {
657
655
  async function resolveAgentId(productUrl, ownerAddressHex, given) {
658
656
  if (given)
659
657
  return given;
660
- const response = await fetch(`${productUrl.replace(/\/$/, "")}/open/v1/agents?owner=${ownerAddressHex}&limit=60`);
658
+ const response = await fetch(`${productUrl.replace(/\/$/, "")}/v1/agents?owner=${ownerAddressHex}&limit=60`);
661
659
  if (!response.ok)
662
660
  fail(`--agent-id was not given and the roster could not be read (${response.status})`);
663
661
  const body = (await response.json());
@@ -680,16 +678,14 @@ async function commandMe(args) {
680
678
  "agent-id": { type: "string" },
681
679
  },
682
680
  });
683
- const productUrl = values["product-url"];
684
- if (!productUrl)
685
- fail("--product-url is required");
681
+ const productUrl = resolveProductUrl(values["product-url"]);
686
682
  const agent = loadKeypair(values.key);
687
683
  /* Without `--agent-id`, ask the roster which agent this key owns. */
688
684
  const agentId = await resolveAgentId(productUrl, agent.ownerAddressHex, values["agent-id"]);
689
- const response = await signedGet(productUrl, "/open/v1/agent/me", agent, agentId);
685
+ const response = await signedGet(productUrl, "/v1/agent/me", agent, agentId);
690
686
  const body = await response.text();
691
687
  if (!response.ok)
692
- fail(refusalMessageFromText(`agent/me at ${productUrl}/open/v1/agent/me`, response.status, body));
688
+ fail(refusalMessageFromText(`agent/me at ${productUrl}/v1/agent/me`, response.status, body));
693
689
  try {
694
690
  console.log(JSON.stringify(JSON.parse(body), null, 2));
695
691
  }
@@ -857,7 +853,7 @@ async function commandAct(args) {
857
853
  * this, so it is worth a caller of its own rather than a flag on the play
858
854
  * loop. Prints what the authority recorded. */
859
855
  async function consentToTerminal(options) {
860
- const offerResponse = await fetch(`${options.productUrl.replace(/\/$/, "")}/open/v1/playground/matches/${options.offerId}`);
856
+ const offerResponse = await fetch(`${options.productUrl.replace(/\/$/, "")}/v1/playground/matches/${options.offerId}`);
861
857
  const offerBody = await offerResponse.text();
862
858
  if (!offerResponse.ok)
863
859
  fail(`offer read failed (${offerResponse.status}): ${offerBody}`);
@@ -1007,9 +1003,7 @@ async function commandConsent(args) {
1007
1003
  "agent-id": { type: "string" },
1008
1004
  },
1009
1005
  });
1010
- const productUrl = values["product-url"];
1011
- if (!productUrl)
1012
- fail("--product-url is required");
1006
+ const productUrl = resolveProductUrl(values["product-url"]);
1013
1007
  if (!values.offer)
1014
1008
  fail("--offer is required");
1015
1009
  if (!values.seat)
@@ -1045,9 +1039,7 @@ async function commandQueue(args) {
1045
1039
  play: { type: "boolean", default: false },
1046
1040
  },
1047
1041
  });
1048
- const productUrl = values["product-url"];
1049
- if (!productUrl)
1050
- fail("--product-url is required");
1042
+ const productUrl = resolveProductUrl(values["product-url"]);
1051
1043
  if (!values["agent-id"])
1052
1044
  fail("--agent-id is required");
1053
1045
  const tour = values.tour;
@@ -1238,9 +1230,7 @@ async function commandRoom(args) {
1238
1230
  "timeout-ms": { type: "string", default: String(30 * 60_000) },
1239
1231
  },
1240
1232
  });
1241
- const productUrl = values["product-url"];
1242
- if (!productUrl)
1243
- fail("--product-url is required");
1233
+ const productUrl = resolveProductUrl(values["product-url"]);
1244
1234
  if (!values["agent-id"])
1245
1235
  fail("--agent-id is required");
1246
1236
  const client = {
@@ -1395,9 +1385,7 @@ async function commandTournament(args) {
1395
1385
  "until-out": { type: "boolean", default: false },
1396
1386
  },
1397
1387
  });
1398
- const productUrl = values["product-url"];
1399
- if (!productUrl)
1400
- fail("--product-url is required");
1388
+ const productUrl = resolveProductUrl(values["product-url"]);
1401
1389
  const agent = loadKeypair(values.key);
1402
1390
  const tournamentId = await tournamentArg(productUrl, values.tournament);
1403
1391
  const overview = await readTournament(productUrl, tournamentId);
@@ -1408,7 +1396,7 @@ async function commandTournament(args) {
1408
1396
  this agent holds now is on the owner's side of the book. */
1409
1397
  const playTakenBackNext = () => describeNext({
1410
1398
  action: "read",
1411
- route: `/open/v1/tournaments/${tournamentId}/owners/${owner ?? "{owner}"}`,
1399
+ route: `/v1/tournaments/${tournamentId}/owners/${owner ?? "{owner}"}`,
1412
1400
  });
1413
1401
  const held = async () => owner ? await playsHeldBy(productUrl, tournamentId, owner, chip) : [];
1414
1402
  let plays = await held();
@@ -1700,9 +1688,7 @@ async function commandClaimInvite(args) {
1700
1688
  hours: { type: "string", default: "24" },
1701
1689
  },
1702
1690
  });
1703
- const productUrl = values["product-url"]?.replace(/\/$/, "");
1704
- if (!productUrl)
1705
- fail("--product-url is required");
1691
+ const productUrl = resolveProductUrl(values["product-url"]).replace(/\/$/, "");
1706
1692
  if (!values["agent-id"])
1707
1693
  fail("--agent-id is required");
1708
1694
  const hours = Number(values.hours);
package/dist/identity.js CHANGED
@@ -7,11 +7,12 @@
7
7
  * and this key can no longer sign for it -- which is the point of a claim.
8
8
  *
9
9
  * The payload mirrors `AgentIdentityEdit::canonical_payload` in
10
- * `backend/dopa-open/product/src/domain/custodial/key_rotation.rs`: every
11
- * field is length-framed, so "ab"/"c" and "a"/"bc" cannot sign the same
12
- * bytes. The product parses before it verifies -- it trims each field and
13
- * lower-cases the handle -- so this signs the parsed form, or the signature
14
- * is over bytes the store never holds. */
10
+ * `backend/dopa-open/product/src/domain/custodial/key_rotation.rs`: the two
11
+ * ids are fixed 32 bytes and every named field is length-framed, so "ab"/"c"
12
+ * and "a"/"bc" cannot sign the same bytes, and neither can a shorter agent id
13
+ * borrow a byte from the owner behind it. The product parses before it
14
+ * verifies -- it trims each field and lower-cases the handle -- so this signs
15
+ * the parsed form, or the signature is over bytes the store never holds. */
15
16
  import { ByteWriter, fromHex, textBytes } from "./bytes.js";
16
17
  import { signOwnerAuthenticator } from "./keypair.js";
17
18
  import { refusalMessageFromText } from "./refusal.js";
@@ -33,8 +34,8 @@ export function canonicalIdentityPayload(edit) {
33
34
  const writer = new ByteWriter()
34
35
  .pushU64(domain.length)
35
36
  .pushBytes(domain)
36
- .pushBytes(fromHex(edit.agentId))
37
- .pushBytes(fromHex(edit.owner));
37
+ .pushFixed(fromHex(edit.agentId), 32, "agent id")
38
+ .pushFixed(fromHex(edit.owner), 32, "owner");
38
39
  for (const field of [parsed.name ?? "", parsed.handle ?? "", parsed.bio ?? ""]) {
39
40
  const bytes = textBytes(field);
40
41
  writer.pushU64(bytes.length).pushBytes(bytes);
@@ -55,7 +56,7 @@ export async function nameAgent(args) {
55
56
  expiresAtMs,
56
57
  }));
57
58
  const agentId = `0x${args.agentId.replace(/^0x/, "")}`;
58
- const response = await fetchImpl(`${args.productUrl.replace(/\/$/, "")}/open/v1/agents/${agentId}/identity`, {
59
+ const response = await fetchImpl(`${args.productUrl.replace(/\/$/, "")}/v1/agents/${agentId}/identity`, {
59
60
  method: "PUT",
60
61
  headers: { "content-type": "application/json" },
61
62
  body: JSON.stringify({
package/dist/index.d.ts CHANGED
@@ -5,7 +5,7 @@ export { actionSigningBytes, encodeActionFrame, encodeJoinFrame, encodeResumeFra
5
5
  export { encodeAckFrame, SESSION_ERROR_NAMES, MAX_PREDICTION_PACING_MS, admitAuthorityEvent, applyPredictionGateStatus, decodeAuthorityMessage, freshSessionBoundary, predictionGateMessage, predictionGatePreparationOf, predictionGateTargetReceipt, sessionErrorHint, sessionErrorName, PredictionGateConflictError, SessionBoundaryError, type AcceptedSessionBoundary, type AuthorityMessage, type PredictionGateMessage, type PredictionGateOpening, type PredictionGatePreparation, type PredictionGateRelease, type PredictionGateStatus, type PredictionWindowRef, type ReceiptRef, type ResumeCursor, type StateRef, type ViewSnapshot, } from "./sessionCodec.js";
6
6
  export { type OpenTableView, type PlayReport, type SeatDecision, type SeatDecisionResult, type SeatPosition, SessionClient, SessionRefusal, chooseSeatAction, playSeat, } from "./session.js";
7
7
  export { cardFromByte, decodeLegalActions, decodeParticipantView, encodeAction, pickAction, type Card, type Rank, type Suit, type TexasAction, type TexasLegalActions, type TexasSeatView, } from "./texas.js";
8
- export { authorityOriginFromSessionBase, buildConsentRequest, digestForPrompt, recomputeSettlementDigest, settlementConsentPath, verifyConsentDisclosure, } from "./settlement.js";
8
+ export { authorityOriginFromSessionBase, buildConsentRequest, DEFAULT_OPEN_API_BASE_URL, digestForPrompt, recomputeSettlementDigest, settlementConsentPath, verifyConsentDisclosure, } from "./settlement.js";
9
9
  export { PACKAGE_NAME, RELEASE_CHANNELS, channelDistTag, installCommand, installSpec, resolveChannel, versionMatchesChannel, type ReleaseChannel, } from "./channel.js";
10
10
  export { fromHex, toHex } from "./bytes.js";
11
11
  export { AGENT_HTTP_CAPABILITY_HEADER, AGENT_HTTP_CAPABILITY_NONCE_BYTES, MAX_AGENT_HTTP_CAPABILITY_WINDOW_MS, agentHttpCanonicalPayload, agentHttpSigningBytes, decodeAgentHttpHeader, encodeAgentHttpHeader, mintAgentHttpCapability, type AgentHttpBinding, type AgentHttpCapability, } from "./agentHttp.js";
package/dist/index.js CHANGED
@@ -3,7 +3,7 @@
3
3
  * Generate and hold an ed25519 keypair (Sui format, `.dopa-keypair`), produce
4
4
  * the canonical signatures, and drive the Participant Session against
5
5
  * `session_base_url`. Byte parity with the Rust client is pinned by
6
- * `libs/dopa-open-client-rs/vectors/ts-signer-parity.json`.
6
+ * `libs/dopa-open/client-rs/vectors/ts-signer-parity.json`.
7
7
  */
8
8
  export { DEFAULT_KEY_FILE, generateKeypair, keypairFromSeed, loadKeypair, saveKeypair, signOwnerAuthenticator, signRaw, } from "./keypair.js";
9
9
  export { deriveAgentId, registerCanonicalPayload, registerPayloadDigest, } from "./registration.js";
@@ -12,7 +12,7 @@ export { actionSigningBytes, encodeActionFrame, encodeJoinFrame, encodeResumeFra
12
12
  export { encodeAckFrame, SESSION_ERROR_NAMES, MAX_PREDICTION_PACING_MS, admitAuthorityEvent, applyPredictionGateStatus, decodeAuthorityMessage, freshSessionBoundary, predictionGateMessage, predictionGatePreparationOf, predictionGateTargetReceipt, sessionErrorHint, sessionErrorName, PredictionGateConflictError, SessionBoundaryError, } from "./sessionCodec.js";
13
13
  export { SessionClient, SessionRefusal, chooseSeatAction, playSeat, } from "./session.js";
14
14
  export { cardFromByte, decodeLegalActions, decodeParticipantView, encodeAction, pickAction, } from "./texas.js";
15
- export { authorityOriginFromSessionBase, buildConsentRequest, digestForPrompt, recomputeSettlementDigest, settlementConsentPath, verifyConsentDisclosure, } from "./settlement.js";
15
+ export { authorityOriginFromSessionBase, buildConsentRequest, DEFAULT_OPEN_API_BASE_URL, digestForPrompt, recomputeSettlementDigest, settlementConsentPath, verifyConsentDisclosure, } from "./settlement.js";
16
16
  export { PACKAGE_NAME, RELEASE_CHANNELS, channelDistTag, installCommand, installSpec, resolveChannel, versionMatchesChannel, } from "./channel.js";
17
17
  export { fromHex, toHex } from "./bytes.js";
18
18
  export { AGENT_HTTP_CAPABILITY_HEADER, AGENT_HTTP_CAPABILITY_NONCE_BYTES, MAX_AGENT_HTTP_CAPABILITY_WINDOW_MS, agentHttpCanonicalPayload, agentHttpSigningBytes, decodeAgentHttpHeader, encodeAgentHttpHeader, mintAgentHttpCapability, } from "./agentHttp.js";
package/dist/offer.js CHANGED
@@ -52,7 +52,7 @@ function record(raw) {
52
52
  };
53
53
  }
54
54
  export async function readOffer(productUrl, offerId) {
55
- const { status, json } = await readJson(`${productUrl.replace(/\/$/, "")}/open/v1/playground/matches/${offerId}`);
55
+ const { status, json } = await readJson(`${productUrl.replace(/\/$/, "")}/v1/playground/matches/${offerId}`);
56
56
  if (status !== 200)
57
57
  throw new Error(refusalMessage("offer read", status, json));
58
58
  return record(json);
@@ -81,7 +81,7 @@ export async function acceptOffer(productUrl, offerId, seat, agent) {
81
81
  signature: Array.from(signed.signature),
82
82
  seat_possession_signature: Array.from(signed.seatPossessionSignature),
83
83
  });
84
- const { status, json } = await readJson(`${productUrl.replace(/\/$/, "")}/open/v1/playground/matches/${offerId}/acceptances`, { method: "POST", headers: { "content-type": "application/json" }, body });
84
+ const { status, json } = await readJson(`${productUrl.replace(/\/$/, "")}/v1/playground/matches/${offerId}/acceptances`, { method: "POST", headers: { "content-type": "application/json" }, body });
85
85
  if (status === 200 || status === 201)
86
86
  return;
87
87
  if (status === 409)
@@ -89,7 +89,7 @@ export async function acceptOffer(productUrl, offerId, seat, agent) {
89
89
  throw new Error(refusalMessage("acceptance", status, json));
90
90
  }
91
91
  async function admit(productUrl, offerId, agentId, agent) {
92
- const target = `/open/v1/playground/matches/${offerId}/admit`;
92
+ const target = `/v1/playground/matches/${offerId}/admit`;
93
93
  const { header } = await mintAgentHttpCapability(agent, agentId, {
94
94
  method: "POST",
95
95
  requestTarget: target,
@@ -26,7 +26,7 @@ function base(productUrl) {
26
26
  return productUrl.replace(/\/$/, "");
27
27
  }
28
28
  function tournamentPath(tournamentId, rest = "") {
29
- return `/open/v1/tournaments/${tournamentId}${rest}`;
29
+ return `/v1/tournaments/${tournamentId}${rest}`;
30
30
  }
31
31
  async function readJson(fetchImpl, url) {
32
32
  const response = await fetchImpl(url);
@@ -57,7 +57,7 @@ export async function readTournament(productUrl, tournamentId, fetchImpl = fetch
57
57
  }
58
58
  /** The open-entry tournaments the product runs. */
59
59
  export async function listTournaments(productUrl, fetchImpl = fetch) {
60
- const { status, json } = await readJson(fetchImpl, `${base(productUrl)}/open/v1/tournaments`);
60
+ const { status, json } = await readJson(fetchImpl, `${base(productUrl)}/v1/tournaments`);
61
61
  if (status === 404)
62
62
  return [];
63
63
  if (status !== 200)
@@ -209,7 +209,7 @@ plays, owner) {
209
209
  if (entry && entry.state !== "idle")
210
210
  throw new JoinRefused(`this agent is already ${entry.state}${entry.state === "seated" ? " at a table" : ""}; an agent plays one table at a time`, {
211
211
  action: "wait",
212
- poll: `/open/v1/tournaments/${overview.tournamentId}/agents/${entry.chipAddress}`,
212
+ poll: `/v1/tournaments/${overview.tournamentId}/agents/${entry.chipAddress}`,
213
213
  });
214
214
  const booked = entry?.balance ?? 0;
215
215
  const wallet = entry?.walletBalance ?? booked;
package/dist/room.js CHANGED
@@ -57,7 +57,7 @@ export async function openRoom(client, seatCount) {
57
57
  seatCount < MIN_ROOM_SEATS ||
58
58
  seatCount > MAX_ROOM_SEATS)
59
59
  throw new Error(`a private room seats ${MIN_ROOM_SEATS} to ${MAX_ROOM_SEATS}, not ${seatCount}`);
60
- const { status, json } = await signedFetch(client, "POST", "/open/v1/tables/private-rooms", { seatCount });
60
+ const { status, json } = await signedFetch(client, "POST", "/v1/tables/private-rooms", { seatCount });
61
61
  if (status !== 201) {
62
62
  if (json?.code === "agent_not_claimed")
63
63
  throw notClaimed();
@@ -95,7 +95,7 @@ export class RoomJoinRefusal extends Error {
95
95
  }
96
96
  /** Join a room by the id its opener handed out. */
97
97
  export async function joinRoom(client, tableId) {
98
- const target = `/open/v1/tables/private-rooms/${tableId}/join`;
98
+ const target = `/v1/tables/private-rooms/${tableId}/join`;
99
99
  const { status, json } = await signedFetch(client, "POST", target);
100
100
  if (status !== 201) {
101
101
  if (json?.code === "agent_not_claimed")
package/dist/seatTurn.js CHANGED
@@ -478,7 +478,7 @@ async function sayAtTable(fetchImpl, session, agent, agentId, say) {
478
478
  if (!trimmed)
479
479
  return false;
480
480
  const { mintAgentHttpCapability, AGENT_HTTP_CAPABILITY_HEADER } = await import("./agentHttp.js");
481
- const target = `/open/v1/executions/${session.executionHex}/talk`;
481
+ const target = `/v1/executions/${session.executionHex}/talk`;
482
482
  const body = new TextEncoder().encode(JSON.stringify({ say: trimmed }));
483
483
  try {
484
484
  const { header } = await mintAgentHttpCapability(agent, agentId, {
package/dist/session.js CHANGED
@@ -534,7 +534,7 @@ export async function openSeatSession(args) {
534
534
  /* Read again while the product is coming back: a seat reopens its session
535
535
  after every dropped stream, and the product answering 502 for the seconds
536
536
  it restarts ended the seat as surely as a refusal would have. */
537
- const offer = await fetchWhileRestarting(fetchImpl, `${product}/open/v1/playground/matches/${args.offerId}`, args.restartRetry);
537
+ const offer = await fetchWhileRestarting(fetchImpl, `${product}/v1/playground/matches/${args.offerId}`, args.restartRetry);
538
538
  if (!offer.ok)
539
539
  throw new Error(`offer read failed (${offer.status}): ${await offer.text()}`);
540
540
  const record = (await offer.json());
@@ -1004,7 +1004,7 @@ export function normaliseCardCode(code) {
1004
1004
  export async function readDisclosedEntitlement(fetchImpl, product, executionId, seat, capability, options = {}) {
1005
1005
  const attempts = options.attempts ?? 15;
1006
1006
  const pauseMs = options.pauseMs ?? 1_000;
1007
- const target = `/open/v1/spectator/executions/${executionId}`;
1007
+ const target = `/v1/spectator/executions/${executionId}`;
1008
1008
  for (let attempt = 0; attempt < attempts; attempt += 1) {
1009
1009
  try {
1010
1010
  const header = capability ? await capability("GET", target) : null;
@@ -1032,7 +1032,7 @@ export async function readDisclosedEntitlement(fetchImpl, product, executionId,
1032
1032
  * gone -- which is precisely the moment this question is being asked. */
1033
1033
  export async function readSittingStatus(fetchImpl, product, executionHex) {
1034
1034
  try {
1035
- const response = await fetchImpl(`${product}/open/v1/history/matches/${executionHex}`);
1035
+ const response = await fetchImpl(`${product}/v1/history/matches/${executionHex}`);
1036
1036
  if (!response.ok)
1037
1037
  return { state: "unknown" };
1038
1038
  const wire = (await response.json());
@@ -1073,7 +1073,7 @@ export function agentReadCapability(agent, agentId) {
1073
1073
  export async function readPublicTable(fetchImpl, product, executionHex, names = new Map(), capability) {
1074
1074
  /* Bound to the target the server reconstructs from the request, which is the
1075
1075
  origin-form path and not the absolute URL the fetch is given. */
1076
- const target = `/open/v1/spectator/executions/${executionHex}`;
1076
+ const target = `/v1/spectator/executions/${executionHex}`;
1077
1077
  try {
1078
1078
  const header = capability ? await capability("GET", target) : null;
1079
1079
  const response = await fetchImpl(`${product}${target}`, header === null
@@ -1134,14 +1134,14 @@ export async function readPublicTable(fetchImpl, product, executionHex, names =
1134
1134
  return null;
1135
1135
  }
1136
1136
  }
1137
- /** What an agent is called, from `GET /open/v1/agents/{id}/custody`, read
1137
+ /** What an agent is called, from `GET /v1/agents/{id}/custody`, read
1138
1138
  * once and remembered in `names`. Null where the read did not answer. */
1139
1139
  async function readAgentNaming(fetchImpl, product, agentId, names) {
1140
1140
  const known = names.get(agentId);
1141
1141
  if (known !== undefined)
1142
1142
  return known;
1143
1143
  try {
1144
- const response = await fetchImpl(`${product}/open/v1/agents/${agentId}/custody`);
1144
+ const response = await fetchImpl(`${product}/v1/agents/${agentId}/custody`);
1145
1145
  if (!response.ok) {
1146
1146
  names.set(agentId, null);
1147
1147
  return null;
@@ -1164,7 +1164,7 @@ async function readAgentNaming(fetchImpl, product, agentId, names) {
1164
1164
  * table: an empty list where the read did not answer. */
1165
1165
  export async function readTableTalk(fetchImpl, product, executionHex, handIndex) {
1166
1166
  try {
1167
- const response = await fetchImpl(`${product}/open/v1/executions/${executionHex}/talk`);
1167
+ const response = await fetchImpl(`${product}/v1/executions/${executionHex}/talk`);
1168
1168
  if (!response.ok)
1169
1169
  return [];
1170
1170
  const wire = (await response.json());
@@ -1200,7 +1200,7 @@ function potChips(pot) {
1200
1200
  /** File one line at the table, signed as this seat's agent. True when the
1201
1201
  * product accepted it. */
1202
1202
  async function sayAtTable(fetchImpl, product, executionHex, args, say) {
1203
- const target = `/open/v1/executions/${executionHex}/talk`;
1203
+ const target = `/v1/executions/${executionHex}/talk`;
1204
1204
  const body = textBytes(JSON.stringify({ say }));
1205
1205
  try {
1206
1206
  const { header } = await mintAgentHttpCapability(args.agent, args.agentId, {
@@ -3,7 +3,7 @@
3
3
  *
4
4
  * Join, action, and resume signing bodies live here; acknowledgements are
5
5
  * unsigned and encoded next to the authority decoder. The layouts are pinned
6
- * by `libs/dopa-open-client-rs/vectors/ts-signer-parity.json`.
6
+ * by `libs/dopa-open/client-rs/vectors/ts-signer-parity.json`.
7
7
  */
8
8
  import { ByteWriter, frameSigningBytes, textBytes } from "./bytes.js";
9
9
  const JOIN_DOMAIN = textBytes("arena_session::join");
@@ -1,3 +1,8 @@
1
+ /** The Product API's deployed default origin. `dopa-open`'s `--product-url`
2
+ * (and `DOPA_OPEN_PRODUCT_URL`) default here, matching the Rust client and
3
+ * CLI's `DEFAULT_OPEN_API_BASE_URL`, so a caller only has to override it for
4
+ * a local stack or a non-default plane. */
5
+ export declare const DEFAULT_OPEN_API_BASE_URL = "https://open.dopamint.fun";
1
6
  export interface SeatEntitlement {
2
7
  seat: number;
3
8
  amount: bigint;
@@ -2,6 +2,11 @@ import { ByteReader, ByteWriter, equalBytes, fromHex, textBytes, toHex0x, } from
2
2
  import { digestFramed } from "./crypto.js";
3
3
  const ANCHOR_DOMAIN_ID_V1 = textBytes("arena_tunnel::anchor_domain_id_v1");
4
4
  const SETTLEMENT_PURPOSE = textBytes("arena_tunnel::settlement");
5
+ /** The Product API's deployed default origin. `dopa-open`'s `--product-url`
6
+ * (and `DOPA_OPEN_PRODUCT_URL`) default here, matching the Rust client and
7
+ * CLI's `DEFAULT_OPEN_API_BASE_URL`, so a caller only has to override it for
8
+ * a local stack or a non-default plane. */
9
+ export const DEFAULT_OPEN_API_BASE_URL = "https://open.dopamint.fun";
5
10
  export function encodeTerminalState(state) {
6
11
  const writer = new ByteWriter()
7
12
  .pushU16(1)
@@ -103,7 +108,7 @@ export function buildConsentRequest(args) {
103
108
  }
104
109
  export function settlementConsentPath(executionIdHex) {
105
110
  const hex = executionIdHex.replace(/^0x/, "");
106
- return `/open/v1/authority/executions/${hex}/settlements`;
111
+ return `/v1/authority/executions/${hex}/settlements`;
107
112
  }
108
113
  export function authorityOriginFromSessionBase(sessionBaseUrl) {
109
114
  const idx = sessionBaseUrl.indexOf("/v1/exec/");
package/dist/tour.js CHANGED
@@ -63,8 +63,8 @@ function unavailable(error) {
63
63
  }
64
64
  export async function enterTour(client, tour, floor = {}) {
65
65
  const target = tour === "playground"
66
- ? "/open/v1/tours/playground/entries"
67
- : "/open/v1/tours/tournament/entries";
66
+ ? "/v1/tours/playground/entries"
67
+ : "/v1/tours/tournament/entries";
68
68
  if (floor.minAgents !== undefined && tour !== "playground")
69
69
  throw new Error("a floor of real agents only applies to the playground");
70
70
  /* No body at all when nothing is stated: the join every client sent before
@@ -124,13 +124,13 @@ export async function queueUntilSeated(client, tour, options = {}) {
124
124
  }
125
125
  }
126
126
  export async function readPosition(client, tableId) {
127
- const { status, json } = await signedFetch(client, "GET", `/open/v1/tables/${tableId}/decision`);
127
+ const { status, json } = await signedFetch(client, "GET", `/v1/tables/${tableId}/decision`);
128
128
  if (status !== 200)
129
129
  throw new Error(refusalMessage("decision read", status, json));
130
130
  return json;
131
131
  }
132
132
  export async function act(client, tableId, move) {
133
- const { status, json } = await signedFetch(client, "POST", `/open/v1/tables/${tableId}/actions`, move);
133
+ const { status, json } = await signedFetch(client, "POST", `/v1/tables/${tableId}/actions`, move);
134
134
  if (status !== 200)
135
135
  throw new Error(refusalMessage("action", status, json));
136
136
  return json;
package/package.json CHANGED
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "@dopamint-fun/open-sdk",
3
- "version": "0.2.0-dev.3",
3
+ "version": "0.2.0-dev.5",
4
4
  "description": "DOPA-OPEN client SDK: generate and hold your own agent key, sign registrations, and play a Participant Session",
5
5
  "license": "Apache-2.0",
6
6
  "repository": {
7
7
  "type": "git",
8
8
  "url": "git+https://github.com/CommandOSSLabs/dopamint-arena.git",
9
- "directory": "libs/dopa-open-client-ts"
9
+ "directory": "libs/dopa-open/client-ts"
10
10
  },
11
11
  "type": "module",
12
12
  "main": "dist/index.js",