@dopamint-fun/open-sdk 0.2.0-dev.4 → 0.2.0-dev.6

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/claim.js CHANGED
@@ -146,5 +146,5 @@ export function decodeClaimInvite(token) {
146
146
  /** Where the owner goes to accept: the agent's claim page with the token. */
147
147
  export function claimInviteLink(arenaOrigin, agentIdHex, token) {
148
148
  const id = agentIdHex.startsWith("0x") ? agentIdHex : `0x${agentIdHex}`;
149
- return `${arenaOrigin.replace(/\/$/, "")}/arena/agents/${id}/claim?invite=${token}`;
149
+ return `${arenaOrigin.replace(/\/$/, "")}/open/agents/${id}/claim?invite=${token}`;
150
150
  }
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
@@ -581,7 +579,7 @@ function runRecordPath(keyFile) {
581
579
  }
582
580
  function writeRunRecord(keyFile, record) {
583
581
  const path = runRecordPath(keyFile);
584
- const watchUrl = `${record.productUrl.replace(/\/$/, "")}/arena/matches/0x${record.executionId.replace(/^0x/i, "")}`;
582
+ const watchUrl = `${record.productUrl.replace(/\/$/, "")}/open/matches/0x${record.executionId.replace(/^0x/i, "")}`;
585
583
  writeFileSync(path, `${JSON.stringify({ ...record, watchUrl, at: new Date().toISOString() }, null, 2)}\n`, { mode: 0o600 });
586
584
  return path;
587
585
  }
@@ -642,7 +640,7 @@ async function signedGet(productUrl, target, agent, agentIdHex) {
642
640
  headers: { [AGENT_HTTP_CAPABILITY_HEADER]: header },
643
641
  });
644
642
  }
645
- /** `dopa-open me`: the arena's record of this agent, signed for.
643
+ /** `dopa-open me`: Open's record of this agent, signed for.
646
644
  *
647
645
  * Both agents that played on 2026-09-06 wrote this request by hand, against
648
646
  * the skill's own warning that a hand-written signature drifts by a byte. */
@@ -657,13 +655,13 @@ 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());
664
662
  const agents = body.agents ?? [];
665
663
  if (agents.length === 0)
666
- fail(`no agent on this arena is claimed by ${ownerAddressHex}. The roster lists an agent under the wallet that ` +
664
+ fail(`no agent on this Open deployment is claimed by ${ownerAddressHex}. The roster lists an agent under the wallet that ` +
667
665
  "claimed it, so one that registered itself is not here until it is claimed; pass --agent-id (register printed it)");
668
666
  if (agents.length > 1)
669
667
  fail(`this key owns ${agents.length} agents; pass --agent-id to say which:\n ${agents
@@ -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;
@@ -1091,7 +1083,7 @@ async function commandQueue(args) {
1091
1083
  Labelled `agent_page`, never `watch`. It was `watch` for one release, and
1092
1084
  an agent reading that line handed its operator a profile under the word
1093
1085
  WATCH; `watch` is the table, printed below once there is one. */
1094
- console.log(`agent_page ${client.productUrl.replace(/\/$/, "")}/arena/agents/0x${values["agent-id"].replace(/^0x/i, "")}`);
1086
+ console.log(`agent_page ${client.productUrl.replace(/\/$/, "")}/open/agents/0x${values["agent-id"].replace(/^0x/i, "")}`);
1095
1087
  let lastWaitingLine = "";
1096
1088
  const seated = await queueUntilSeated(client, tour, {
1097
1089
  minAgents,
@@ -1146,7 +1138,7 @@ async function commandQueue(args) {
1146
1138
  executionId: admitted.executionId,
1147
1139
  };
1148
1140
  const recordPath = writeRunRecord(values.key, runRecord);
1149
- console.log(`watch ${client.productUrl.replace(/\/$/, "")}/arena/matches/0x${admitted.executionId.replace(/^0x/i, "")}`);
1141
+ console.log(`watch ${client.productUrl.replace(/\/$/, "")}/open/matches/0x${admitted.executionId.replace(/^0x/i, "")}`);
1150
1142
  console.log(`run_record ${recordPath}`);
1151
1143
  console.log(`reconnect ${reconnectCommand(values.key, runRecord)}`);
1152
1144
  takeSeatLock(values.key, values["agent-id"]);
@@ -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 = {
@@ -1279,7 +1269,7 @@ async function commandRoom(args) {
1279
1269
  that word is the match link on every door, and `room join` prints it
1280
1270
  once the room composes, so two different links under one label was a
1281
1271
  thing an agent had to be warned about. */
1282
- console.log(`room_page ${client.productUrl.replace(/\/$/, "")}/arena/tours/private-room/tables/${room.tableId}`);
1272
+ console.log(`room_page ${client.productUrl.replace(/\/$/, "")}/open/tours/private-room/tables/${room.tableId}`);
1283
1273
  return;
1284
1274
  }
1285
1275
  const tableId = values["table-id"];
@@ -1328,7 +1318,7 @@ async function commandRoom(args) {
1328
1318
  executionId: admitted.executionId,
1329
1319
  };
1330
1320
  const recordPath = writeRunRecord(values.key, runRecord);
1331
- console.log(`watch ${client.productUrl.replace(/\/$/, "")}/arena/matches/0x${admitted.executionId.replace(/^0x/i, "")}`);
1321
+ console.log(`watch ${client.productUrl.replace(/\/$/, "")}/open/matches/0x${admitted.executionId.replace(/^0x/i, "")}`);
1332
1322
  console.log(`run_record ${recordPath}`);
1333
1323
  console.log(`reconnect ${reconnectCommand(values.key, runRecord)}`);
1334
1324
  takeSeatLock(values.key, values["agent-id"]);
@@ -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();
@@ -1642,7 +1630,7 @@ async function commandTournament(args) {
1642
1630
  console.log(`offer ${offerId}`);
1643
1631
  console.log(`seat ${seated.seat}`);
1644
1632
  if (seated.executionId)
1645
- console.log(`watch ${client.productUrl.replace(/\/$/, "")}/arena/matches/${seated.executionId}`);
1633
+ console.log(`watch ${client.productUrl.replace(/\/$/, "")}/open/matches/${seated.executionId}`);
1646
1634
  if (!values.play)
1647
1635
  return;
1648
1636
  const seat = seated.seat;
@@ -1684,7 +1672,7 @@ async function commandTournament(args) {
1684
1672
  }
1685
1673
  /** `dopa-open claim-invite`: the link a wallet needs to claim this agent.
1686
1674
  *
1687
- * A claim is two consents. The wallet signs on the arena's page; you, holding
1675
+ * A claim is two consents. The wallet signs on Open's claim page; you, holding
1688
1676
  * the agent's key, sign the invitation that lets it. Name the wallet with
1689
1677
  * `--owner` to make the link good for that wallet alone; leave it out and the
1690
1678
  * link is good for whoever opens it, for as long as `--hours` says. */
@@ -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);
@@ -1720,7 +1706,7 @@ async function commandClaimInvite(args) {
1720
1706
  expects the old form. Both decode to the same 192 bytes. */
1721
1707
  const token = encodeClaimInvite(invite);
1722
1708
  const linkToken = encodeClaimInviteCompact(invite);
1723
- /* The arena's pages and its API share an origin on a deployment; a local
1709
+ /* Open's pages and its API share an origin on a deployment; a local
1724
1710
  stack serves them apart, which is what --arena-url is for. */
1725
1711
  const arena = (values["arena-url"] ?? productUrl).replace(/\/$/, "");
1726
1712
  console.log(`invite ${token}`);
@@ -1732,7 +1718,7 @@ const USAGE = `usage: dopa-open <command>
1732
1718
 
1733
1719
  keygen generate a keypair into .dopa-keypair (Sui suiprivkey format)
1734
1720
  address print the owner address and public key of an existing key file
1735
- me print the arena's record of this agent, signed for (agent/me)
1721
+ me print Open's record of this agent, signed for (agent/me)
1736
1722
  claim-invite
1737
1723
  mint the claim link a wallet needs to claim this agent
1738
1724
  register self-allocate and register the agent with a product deployment
package/dist/identity.js CHANGED
@@ -56,7 +56,7 @@ export async function nameAgent(args) {
56
56
  expiresAtMs,
57
57
  }));
58
58
  const agentId = `0x${args.agentId.replace(/^0x/, "")}`;
59
- const response = await fetchImpl(`${args.productUrl.replace(/\/$/, "")}/open/v1/agents/${agentId}/identity`, {
59
+ const response = await fetchImpl(`${args.productUrl.replace(/\/$/, "")}/v1/agents/${agentId}/identity`, {
60
60
  method: "PUT",
61
61
  headers: { "content-type": "application/json" },
62
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.4",
3
+ "version": "0.2.0-dev.6",
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",