@playmos/sdk 0.3.9 → 0.3.10

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.
@@ -493,6 +493,19 @@ interface RoundOpenInput {
493
493
  */
494
494
  roundKey?: string;
495
495
  }
496
+ /**
497
+ * Service GET /v1/rounds/:id read-path honesty (#497 / #501).
498
+ * Transport meta — not chain lifecycle. Prefer `rounds.getWithMeta` over stuffing onto RoundState.
499
+ */
500
+ type RoundGetVia = "chain" | "cache" | "stale" | "unknown";
501
+ /** Full GET round response including transport meta (#501 — Claude pick C / getWithMeta). */
502
+ interface RoundGetResult {
503
+ round: RoundState;
504
+ /** Present on live service responses after #499. Omitted under `mock: true`. */
505
+ via?: RoundGetVia;
506
+ /** Present only when eth_call itself threw (#497 C1). */
507
+ chainReadFailed?: boolean;
508
+ }
496
509
  interface RoundState {
497
510
  roundId: string;
498
511
  gameId: string;
@@ -715,4 +728,4 @@ declare class NothingToWithdrawError extends PlaymosError {
715
728
  constructor(detail?: Record<string, unknown>);
716
729
  }
717
730
 
718
- export { type RoundStatus as $, type ActiveSeriesRound as A, type Eip1193Provider as B, type CancelRoundResult as C, type GasMode as D, type EscrowHoldInput as E, InvalidAmountError as F, type GasConfig as G, type ListingStatus as H, InsufficientGasError as I, type MarketplaceItem as J, type MarketplaceSale as K, type Listing as L, type MarketplaceListInput as M, type Network as N, MissingFieldError as O, type PlaymosConfig as P, NothingToWithdrawError as Q, type RoundOpenInput as R, type SettleRoundResult as S, type TransferResult as T, PaymentFailedError as U, type VerifyResult as V, type WebhookEvent as W, type PaymentStatus as X, PlaymosError as Y, type PlaymosErrorCode as Z, type RetryOptions as _, type RoundState as a, type WalletConfig as a0, WalletConnectionError as a1, type WalletConnector as a2, WalletTimeoutError as a3, type WebhookEventType as a4, type RoundSettleInput as b, type RoundCancelInput as c, type PrizeBalance as d, type WithdrawResult as e, type AgentWallet as f, type AgentFundResult as g, type EscrowHoldResult as h, type EscrowResolveResult as i, type MarketplaceSaleResult as j, type MarketplaceGetResult as k, type PayInput as l, type Payment as m, type EnterRoundInput as n, type TransferReconcile as o, type WaitOptions as p, type TransferInput as q, type TransferConfirmOptions as r, type PayoutRule as s, type ActiveForSeriesResult as t, type AgentEconomyConfig as u, AlreadyEnteredError as v, ApiError as w, AuthError as x, ConfigError as y, type ContractConfig as z };
731
+ export { type RetryOptions as $, type ActiveSeriesRound as A, type ContractConfig as B, type CancelRoundResult as C, type Eip1193Provider as D, type EscrowHoldInput as E, type GasMode as F, type GasConfig as G, InvalidAmountError as H, InsufficientGasError as I, type ListingStatus as J, type MarketplaceItem as K, type Listing as L, type MarketplaceListInput as M, type Network as N, type MarketplaceSale as O, type PlaymosConfig as P, MissingFieldError as Q, type RoundOpenInput as R, type SettleRoundResult as S, type TransferResult as T, NothingToWithdrawError as U, type VerifyResult as V, type WebhookEvent as W, PaymentFailedError as X, type PaymentStatus as Y, PlaymosError as Z, type PlaymosErrorCode as _, type RoundState as a, type RoundGetVia as a0, type RoundStatus as a1, type WalletConfig as a2, WalletConnectionError as a3, type WalletConnector as a4, WalletTimeoutError as a5, type WebhookEventType as a6, type RoundSettleInput as b, type RoundCancelInput as c, type RoundGetResult as d, type PrizeBalance as e, type WithdrawResult as f, type AgentWallet as g, type AgentFundResult as h, type EscrowHoldResult as i, type EscrowResolveResult as j, type MarketplaceSaleResult as k, type MarketplaceGetResult as l, type PayInput as m, type Payment as n, type EnterRoundInput as o, type TransferReconcile as p, type WaitOptions as q, type TransferInput as r, type TransferConfirmOptions as s, type PayoutRule as t, type ActiveForSeriesResult as u, type AgentEconomyConfig as v, AlreadyEnteredError as w, ApiError as x, AuthError as y, ConfigError as z };
@@ -493,6 +493,19 @@ interface RoundOpenInput {
493
493
  */
494
494
  roundKey?: string;
495
495
  }
496
+ /**
497
+ * Service GET /v1/rounds/:id read-path honesty (#497 / #501).
498
+ * Transport meta — not chain lifecycle. Prefer `rounds.getWithMeta` over stuffing onto RoundState.
499
+ */
500
+ type RoundGetVia = "chain" | "cache" | "stale" | "unknown";
501
+ /** Full GET round response including transport meta (#501 — Claude pick C / getWithMeta). */
502
+ interface RoundGetResult {
503
+ round: RoundState;
504
+ /** Present on live service responses after #499. Omitted under `mock: true`. */
505
+ via?: RoundGetVia;
506
+ /** Present only when eth_call itself threw (#497 C1). */
507
+ chainReadFailed?: boolean;
508
+ }
496
509
  interface RoundState {
497
510
  roundId: string;
498
511
  gameId: string;
@@ -715,4 +728,4 @@ declare class NothingToWithdrawError extends PlaymosError {
715
728
  constructor(detail?: Record<string, unknown>);
716
729
  }
717
730
 
718
- export { type RoundStatus as $, type ActiveSeriesRound as A, type Eip1193Provider as B, type CancelRoundResult as C, type GasMode as D, type EscrowHoldInput as E, InvalidAmountError as F, type GasConfig as G, type ListingStatus as H, InsufficientGasError as I, type MarketplaceItem as J, type MarketplaceSale as K, type Listing as L, type MarketplaceListInput as M, type Network as N, MissingFieldError as O, type PlaymosConfig as P, NothingToWithdrawError as Q, type RoundOpenInput as R, type SettleRoundResult as S, type TransferResult as T, PaymentFailedError as U, type VerifyResult as V, type WebhookEvent as W, type PaymentStatus as X, PlaymosError as Y, type PlaymosErrorCode as Z, type RetryOptions as _, type RoundState as a, type WalletConfig as a0, WalletConnectionError as a1, type WalletConnector as a2, WalletTimeoutError as a3, type WebhookEventType as a4, type RoundSettleInput as b, type RoundCancelInput as c, type PrizeBalance as d, type WithdrawResult as e, type AgentWallet as f, type AgentFundResult as g, type EscrowHoldResult as h, type EscrowResolveResult as i, type MarketplaceSaleResult as j, type MarketplaceGetResult as k, type PayInput as l, type Payment as m, type EnterRoundInput as n, type TransferReconcile as o, type WaitOptions as p, type TransferInput as q, type TransferConfirmOptions as r, type PayoutRule as s, type ActiveForSeriesResult as t, type AgentEconomyConfig as u, AlreadyEnteredError as v, ApiError as w, AuthError as x, ConfigError as y, type ContractConfig as z };
731
+ export { type RetryOptions as $, type ActiveSeriesRound as A, type ContractConfig as B, type CancelRoundResult as C, type Eip1193Provider as D, type EscrowHoldInput as E, type GasMode as F, type GasConfig as G, InvalidAmountError as H, InsufficientGasError as I, type ListingStatus as J, type MarketplaceItem as K, type Listing as L, type MarketplaceListInput as M, type Network as N, type MarketplaceSale as O, type PlaymosConfig as P, MissingFieldError as Q, type RoundOpenInput as R, type SettleRoundResult as S, type TransferResult as T, NothingToWithdrawError as U, type VerifyResult as V, type WebhookEvent as W, PaymentFailedError as X, type PaymentStatus as Y, PlaymosError as Z, type PlaymosErrorCode as _, type RoundState as a, type RoundGetVia as a0, type RoundStatus as a1, type WalletConfig as a2, WalletConnectionError as a3, type WalletConnector as a4, WalletTimeoutError as a5, type WebhookEventType as a6, type RoundSettleInput as b, type RoundCancelInput as c, type RoundGetResult as d, type PrizeBalance as e, type WithdrawResult as f, type AgentWallet as g, type AgentFundResult as h, type EscrowHoldResult as i, type EscrowResolveResult as j, type MarketplaceSaleResult as k, type MarketplaceGetResult as l, type PayInput as m, type Payment as n, type EnterRoundInput as o, type TransferReconcile as p, type WaitOptions as q, type TransferInput as r, type TransferConfirmOptions as s, type PayoutRule as t, type ActiveForSeriesResult as u, type AgentEconomyConfig as v, AlreadyEnteredError as w, ApiError as x, AuthError as y, ConfigError as z };
package/dist/index.cjs CHANGED
@@ -1614,19 +1614,34 @@ var Playmos = class {
1614
1614
  }
1615
1615
  return { ...result, txHash: result.txHash ?? firstTx ?? null };
1616
1616
  },
1617
+ /**
1618
+ * Round state only (stable). Prefer {@link getWithMeta} when you need service
1619
+ * read-path honesty (`via` / `chainReadFailed` — #497 / #501).
1620
+ */
1617
1621
  get: async (input) => {
1622
+ const meta = await this.rounds.getWithMeta(input);
1623
+ return meta.round;
1624
+ },
1625
+ /**
1626
+ * Round state + transport meta from GET /v1/rounds/:id (#501).
1627
+ * Does **not** attach `via` onto RoundState (Claude rejected option B — hub would
1628
+ * silently pick it up and leak into settle/cancel paths that call get()).
1629
+ * Under `mock: true`, meta fields are **omitted** (no eth_call; do not invent "cache").
1630
+ */
1631
+ getWithMeta: async (input) => {
1618
1632
  requireField(input?.roundId, "roundId");
1619
1633
  if (this.config.mock) {
1620
1634
  const existing = this.mockRounds.get(input.roundId);
1621
1635
  if (!existing) {
1622
1636
  throw new ApiError(`unknown round: ${input.roundId}`, { status: 404, code: "not_found" });
1623
1637
  }
1624
- return existing;
1638
+ return { round: existing };
1625
1639
  }
1626
- const { round } = await this.http.get(
1627
- `/rounds/${encodeURIComponent(input.roundId)}`
1628
- );
1629
- return round;
1640
+ const body = await this.http.get(`/rounds/${encodeURIComponent(input.roundId)}`);
1641
+ const out = { round: body.round };
1642
+ if (body.via != null) out.via = body.via;
1643
+ if (body.chainReadFailed === true) out.chainReadFailed = true;
1644
+ return out;
1630
1645
  },
1631
1646
  /**
1632
1647
  * Authoritative series latch (#351) — `null` means **proven free**.
@@ -1731,19 +1746,26 @@ var Playmos = class {
1731
1746
  */
1732
1747
  withdraw: async (input) => {
1733
1748
  if (this.config.mock) {
1734
- let amountMicro2 = 0n;
1735
1749
  let prizePool2 = input.prizePoolAddress ?? "0x0000000000000000000000000000000000000001";
1736
1750
  if (input.roundId) {
1737
1751
  const existing = this.mockRounds.get(input.roundId);
1738
1752
  if (existing?.prizePoolAddress) prizePool2 = existing.prizePoolAddress;
1739
- for (const [k, v] of this.mockWithdrawable) {
1740
- if (k.startsWith(`${input.roundId}:`) && v > 0n) {
1741
- amountMicro2 = v;
1742
- this.mockWithdrawable.set(k, 0n);
1743
- break;
1744
- }
1745
- }
1746
1753
  }
1754
+ if (!input.wallet || !ADDRESS_RE3.test(input.wallet)) {
1755
+ throw new ConfigError(
1756
+ "mock rounds.withdraw requires wallet (0x\u2026) \u2014 live uses the connected provider; without wallet mock would pay the first non-zero credit to the wrong player (#495)"
1757
+ );
1758
+ }
1759
+ const wallet = input.wallet.toLowerCase();
1760
+ if (!input.roundId) {
1761
+ throw new ConfigError("mock rounds.withdraw requires roundId to locate claimable credits");
1762
+ }
1763
+ const key = `${input.roundId}:${wallet}`;
1764
+ const amountMicro2 = this.mockWithdrawable.get(key) ?? 0n;
1765
+ if (amountMicro2 === 0n) {
1766
+ throw new NothingToWithdrawError({ prizePoolAddress: prizePool2, wallet });
1767
+ }
1768
+ this.mockWithdrawable.set(key, 0n);
1747
1769
  return {
1748
1770
  prizePoolAddress: prizePool2,
1749
1771
  amount: formatMicroToUsd(amountMicro2),
package/dist/index.d.cts CHANGED
@@ -1,5 +1,5 @@
1
- import { N as Network, P as PlaymosConfig, W as WebhookEvent, R as RoundOpenInput, a as RoundState, b as RoundSettleInput, S as SettleRoundResult, c as RoundCancelInput, C as CancelRoundResult, A as ActiveSeriesRound, d as PrizeBalance, e as WithdrawResult, f as AgentWallet, g as AgentFundResult, T as TransferResult, E as EscrowHoldInput, h as EscrowHoldResult, i as EscrowResolveResult, M as MarketplaceListInput, L as Listing, j as MarketplaceSaleResult, k as MarketplaceGetResult, l as PayInput, m as Payment, n as EnterRoundInput, o as TransferReconcile, p as WaitOptions, q as TransferInput, r as TransferConfirmOptions, V as VerifyResult, s as PayoutRule } from './errors-BMlWHsMb.cjs';
2
- export { t as ActiveForSeriesResult, u as AgentEconomyConfig, v as AlreadyEnteredError, w as ApiError, x as AuthError, y as ConfigError, z as ContractConfig, B as Eip1193Provider, G as GasConfig, D as GasMode, I as InsufficientGasError, F as InvalidAmountError, H as ListingStatus, J as MarketplaceItem, K as MarketplaceSale, O as MissingFieldError, Q as NothingToWithdrawError, U as PaymentFailedError, X as PaymentStatus, Y as PlaymosError, Z as PlaymosErrorCode, _ as RetryOptions, $ as RoundStatus, a0 as WalletConfig, a1 as WalletConnectionError, a2 as WalletConnector, a3 as WalletTimeoutError, a4 as WebhookEventType } from './errors-BMlWHsMb.cjs';
1
+ import { N as Network, P as PlaymosConfig, W as WebhookEvent, R as RoundOpenInput, a as RoundState, b as RoundSettleInput, S as SettleRoundResult, c as RoundCancelInput, C as CancelRoundResult, d as RoundGetResult, A as ActiveSeriesRound, e as PrizeBalance, f as WithdrawResult, g as AgentWallet, h as AgentFundResult, T as TransferResult, E as EscrowHoldInput, i as EscrowHoldResult, j as EscrowResolveResult, M as MarketplaceListInput, L as Listing, k as MarketplaceSaleResult, l as MarketplaceGetResult, m as PayInput, n as Payment, o as EnterRoundInput, p as TransferReconcile, q as WaitOptions, r as TransferInput, s as TransferConfirmOptions, V as VerifyResult, t as PayoutRule } from './errors-Chizbb96.cjs';
2
+ export { u as ActiveForSeriesResult, v as AgentEconomyConfig, w as AlreadyEnteredError, x as ApiError, y as AuthError, z as ConfigError, B as ContractConfig, D as Eip1193Provider, G as GasConfig, F as GasMode, I as InsufficientGasError, H as InvalidAmountError, J as ListingStatus, K as MarketplaceItem, O as MarketplaceSale, Q as MissingFieldError, U as NothingToWithdrawError, X as PaymentFailedError, Y as PaymentStatus, Z as PlaymosError, _ as PlaymosErrorCode, $ as RetryOptions, a0 as RoundGetVia, a1 as RoundStatus, a2 as WalletConfig, a3 as WalletConnectionError, a4 as WalletConnector, a5 as WalletTimeoutError, a6 as WebhookEventType } from './errors-Chizbb96.cjs';
3
3
 
4
4
  /**
5
5
  * Environment resolution + the canonical address book.
@@ -518,9 +518,22 @@ declare class Playmos {
518
518
  * if still pending — never invents terminal success).
519
519
  */
520
520
  cancel: (input: RoundCancelInput) => Promise<CancelRoundResult>;
521
+ /**
522
+ * Round state only (stable). Prefer {@link getWithMeta} when you need service
523
+ * read-path honesty (`via` / `chainReadFailed` — #497 / #501).
524
+ */
521
525
  get: (input: {
522
526
  roundId: string;
523
527
  }) => Promise<RoundState>;
528
+ /**
529
+ * Round state + transport meta from GET /v1/rounds/:id (#501).
530
+ * Does **not** attach `via` onto RoundState (Claude rejected option B — hub would
531
+ * silently pick it up and leak into settle/cancel paths that call get()).
532
+ * Under `mock: true`, meta fields are **omitted** (no eth_call; do not invent "cache").
533
+ */
534
+ getWithMeta: (input: {
535
+ roundId: string;
536
+ }) => Promise<RoundGetResult>;
524
537
  /**
525
538
  * Authoritative series latch (#351) — `null` means **proven free**.
526
539
  * `GET /v1/series/:seriesKey/active?gameId=…` — not a candidate probe.
@@ -550,6 +563,11 @@ declare class Playmos {
550
563
  withdraw: (input: {
551
564
  prizePoolAddress?: `0x${string}`;
552
565
  roundId?: string;
566
+ /**
567
+ * Winner wallet (0x…). **Required under mock** (#495 Claude) — live path uses the
568
+ * connected provider. Without this, mock paid the first non-zero credit to anyone.
569
+ */
570
+ wallet?: string;
553
571
  /** Pre-check claimable; default true. Set false only if you already called `prize()`. */
554
572
  checkBalance?: boolean;
555
573
  }) => Promise<WithdrawResult>;
@@ -890,4 +908,4 @@ declare function ulid(seedTime?: number): string;
890
908
  /** `${prefix}_${ulid()}` — e.g. `pay_01J…`, `entry_01J…`, `idem_01J…`. */
891
909
  declare function prefixedId(prefix: string): string;
892
910
 
893
- export { ActiveSeriesRound, AgentFundResult, AgentWallet, type Authorization, CHAIN_ID, CancelRoundResult, type CreatePaymentRequirementInput, DEFAULT_API_BASE_URL, EnterRoundInput, EscrowHoldInput, EscrowHoldResult, EscrowResolveResult, Listing, MICRO_PER_USDC, MarketplaceGetResult, MarketplaceListInput, MarketplaceSaleResult, Network, PayInput, Payment, type PaymentRequirement, PayoutError, PayoutRule, PayoutRule as PayoutRuleCompute, Playmos, PlaymosConfig, PrizeBalance, RoundCancelInput, RoundOpenInput, RoundSettleInput, RoundState, SettleRoundResult, type SettlementAsset, TransferConfirmOptions, TransferInput, TransferReconcile, TransferResult, USDC_ADDRESS, USDC_DECIMALS, VerifyResult, WaitOptions, type WalletSignatureAuthorization, WebhookEvent, WithdrawResult, type X402ChallengeInput, type X402ChallengeResult, type X402FulfillAuthorization, type X402PayInput, type X402PayloadAuthorization, type X402PayloadMode, type X402PaymentRequired, type X402SettleResult, clientRuntimeSignals, computeIapSplit, computePayout, computePoolSplit, createPaymentRequirement, createX402Challenge, decodePaymentHeader, encodePaymentHeader, formatMicroToUsd, isClientRuntime, isWalletSignatureAuthorization, isX402PayloadAuthorization, networkToCaip2, parsePaymentRequirement, parseUsdToMicro, prefixedId, previewEscrowFee, previewIapSplit, previewMarketplaceSplit, previewPoolSplit, previewTransferSplit, resolveEnv, serializePaymentRequirement, toX402PaymentRequired, ulid, validateX402ChallengeInput };
911
+ export { ActiveSeriesRound, AgentFundResult, AgentWallet, type Authorization, CHAIN_ID, CancelRoundResult, type CreatePaymentRequirementInput, DEFAULT_API_BASE_URL, EnterRoundInput, EscrowHoldInput, EscrowHoldResult, EscrowResolveResult, Listing, MICRO_PER_USDC, MarketplaceGetResult, MarketplaceListInput, MarketplaceSaleResult, Network, PayInput, Payment, type PaymentRequirement, PayoutError, PayoutRule, PayoutRule as PayoutRuleCompute, Playmos, PlaymosConfig, PrizeBalance, RoundCancelInput, RoundGetResult, RoundOpenInput, RoundSettleInput, RoundState, SettleRoundResult, type SettlementAsset, TransferConfirmOptions, TransferInput, TransferReconcile, TransferResult, USDC_ADDRESS, USDC_DECIMALS, VerifyResult, WaitOptions, type WalletSignatureAuthorization, WebhookEvent, WithdrawResult, type X402ChallengeInput, type X402ChallengeResult, type X402FulfillAuthorization, type X402PayInput, type X402PayloadAuthorization, type X402PayloadMode, type X402PaymentRequired, type X402SettleResult, clientRuntimeSignals, computeIapSplit, computePayout, computePoolSplit, createPaymentRequirement, createX402Challenge, decodePaymentHeader, encodePaymentHeader, formatMicroToUsd, isClientRuntime, isWalletSignatureAuthorization, isX402PayloadAuthorization, networkToCaip2, parsePaymentRequirement, parseUsdToMicro, prefixedId, previewEscrowFee, previewIapSplit, previewMarketplaceSplit, previewPoolSplit, previewTransferSplit, resolveEnv, serializePaymentRequirement, toX402PaymentRequired, ulid, validateX402ChallengeInput };
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { N as Network, P as PlaymosConfig, W as WebhookEvent, R as RoundOpenInput, a as RoundState, b as RoundSettleInput, S as SettleRoundResult, c as RoundCancelInput, C as CancelRoundResult, A as ActiveSeriesRound, d as PrizeBalance, e as WithdrawResult, f as AgentWallet, g as AgentFundResult, T as TransferResult, E as EscrowHoldInput, h as EscrowHoldResult, i as EscrowResolveResult, M as MarketplaceListInput, L as Listing, j as MarketplaceSaleResult, k as MarketplaceGetResult, l as PayInput, m as Payment, n as EnterRoundInput, o as TransferReconcile, p as WaitOptions, q as TransferInput, r as TransferConfirmOptions, V as VerifyResult, s as PayoutRule } from './errors-BMlWHsMb.js';
2
- export { t as ActiveForSeriesResult, u as AgentEconomyConfig, v as AlreadyEnteredError, w as ApiError, x as AuthError, y as ConfigError, z as ContractConfig, B as Eip1193Provider, G as GasConfig, D as GasMode, I as InsufficientGasError, F as InvalidAmountError, H as ListingStatus, J as MarketplaceItem, K as MarketplaceSale, O as MissingFieldError, Q as NothingToWithdrawError, U as PaymentFailedError, X as PaymentStatus, Y as PlaymosError, Z as PlaymosErrorCode, _ as RetryOptions, $ as RoundStatus, a0 as WalletConfig, a1 as WalletConnectionError, a2 as WalletConnector, a3 as WalletTimeoutError, a4 as WebhookEventType } from './errors-BMlWHsMb.js';
1
+ import { N as Network, P as PlaymosConfig, W as WebhookEvent, R as RoundOpenInput, a as RoundState, b as RoundSettleInput, S as SettleRoundResult, c as RoundCancelInput, C as CancelRoundResult, d as RoundGetResult, A as ActiveSeriesRound, e as PrizeBalance, f as WithdrawResult, g as AgentWallet, h as AgentFundResult, T as TransferResult, E as EscrowHoldInput, i as EscrowHoldResult, j as EscrowResolveResult, M as MarketplaceListInput, L as Listing, k as MarketplaceSaleResult, l as MarketplaceGetResult, m as PayInput, n as Payment, o as EnterRoundInput, p as TransferReconcile, q as WaitOptions, r as TransferInput, s as TransferConfirmOptions, V as VerifyResult, t as PayoutRule } from './errors-Chizbb96.js';
2
+ export { u as ActiveForSeriesResult, v as AgentEconomyConfig, w as AlreadyEnteredError, x as ApiError, y as AuthError, z as ConfigError, B as ContractConfig, D as Eip1193Provider, G as GasConfig, F as GasMode, I as InsufficientGasError, H as InvalidAmountError, J as ListingStatus, K as MarketplaceItem, O as MarketplaceSale, Q as MissingFieldError, U as NothingToWithdrawError, X as PaymentFailedError, Y as PaymentStatus, Z as PlaymosError, _ as PlaymosErrorCode, $ as RetryOptions, a0 as RoundGetVia, a1 as RoundStatus, a2 as WalletConfig, a3 as WalletConnectionError, a4 as WalletConnector, a5 as WalletTimeoutError, a6 as WebhookEventType } from './errors-Chizbb96.js';
3
3
 
4
4
  /**
5
5
  * Environment resolution + the canonical address book.
@@ -518,9 +518,22 @@ declare class Playmos {
518
518
  * if still pending — never invents terminal success).
519
519
  */
520
520
  cancel: (input: RoundCancelInput) => Promise<CancelRoundResult>;
521
+ /**
522
+ * Round state only (stable). Prefer {@link getWithMeta} when you need service
523
+ * read-path honesty (`via` / `chainReadFailed` — #497 / #501).
524
+ */
521
525
  get: (input: {
522
526
  roundId: string;
523
527
  }) => Promise<RoundState>;
528
+ /**
529
+ * Round state + transport meta from GET /v1/rounds/:id (#501).
530
+ * Does **not** attach `via` onto RoundState (Claude rejected option B — hub would
531
+ * silently pick it up and leak into settle/cancel paths that call get()).
532
+ * Under `mock: true`, meta fields are **omitted** (no eth_call; do not invent "cache").
533
+ */
534
+ getWithMeta: (input: {
535
+ roundId: string;
536
+ }) => Promise<RoundGetResult>;
524
537
  /**
525
538
  * Authoritative series latch (#351) — `null` means **proven free**.
526
539
  * `GET /v1/series/:seriesKey/active?gameId=…` — not a candidate probe.
@@ -550,6 +563,11 @@ declare class Playmos {
550
563
  withdraw: (input: {
551
564
  prizePoolAddress?: `0x${string}`;
552
565
  roundId?: string;
566
+ /**
567
+ * Winner wallet (0x…). **Required under mock** (#495 Claude) — live path uses the
568
+ * connected provider. Without this, mock paid the first non-zero credit to anyone.
569
+ */
570
+ wallet?: string;
553
571
  /** Pre-check claimable; default true. Set false only if you already called `prize()`. */
554
572
  checkBalance?: boolean;
555
573
  }) => Promise<WithdrawResult>;
@@ -890,4 +908,4 @@ declare function ulid(seedTime?: number): string;
890
908
  /** `${prefix}_${ulid()}` — e.g. `pay_01J…`, `entry_01J…`, `idem_01J…`. */
891
909
  declare function prefixedId(prefix: string): string;
892
910
 
893
- export { ActiveSeriesRound, AgentFundResult, AgentWallet, type Authorization, CHAIN_ID, CancelRoundResult, type CreatePaymentRequirementInput, DEFAULT_API_BASE_URL, EnterRoundInput, EscrowHoldInput, EscrowHoldResult, EscrowResolveResult, Listing, MICRO_PER_USDC, MarketplaceGetResult, MarketplaceListInput, MarketplaceSaleResult, Network, PayInput, Payment, type PaymentRequirement, PayoutError, PayoutRule, PayoutRule as PayoutRuleCompute, Playmos, PlaymosConfig, PrizeBalance, RoundCancelInput, RoundOpenInput, RoundSettleInput, RoundState, SettleRoundResult, type SettlementAsset, TransferConfirmOptions, TransferInput, TransferReconcile, TransferResult, USDC_ADDRESS, USDC_DECIMALS, VerifyResult, WaitOptions, type WalletSignatureAuthorization, WebhookEvent, WithdrawResult, type X402ChallengeInput, type X402ChallengeResult, type X402FulfillAuthorization, type X402PayInput, type X402PayloadAuthorization, type X402PayloadMode, type X402PaymentRequired, type X402SettleResult, clientRuntimeSignals, computeIapSplit, computePayout, computePoolSplit, createPaymentRequirement, createX402Challenge, decodePaymentHeader, encodePaymentHeader, formatMicroToUsd, isClientRuntime, isWalletSignatureAuthorization, isX402PayloadAuthorization, networkToCaip2, parsePaymentRequirement, parseUsdToMicro, prefixedId, previewEscrowFee, previewIapSplit, previewMarketplaceSplit, previewPoolSplit, previewTransferSplit, resolveEnv, serializePaymentRequirement, toX402PaymentRequired, ulid, validateX402ChallengeInput };
911
+ export { ActiveSeriesRound, AgentFundResult, AgentWallet, type Authorization, CHAIN_ID, CancelRoundResult, type CreatePaymentRequirementInput, DEFAULT_API_BASE_URL, EnterRoundInput, EscrowHoldInput, EscrowHoldResult, EscrowResolveResult, Listing, MICRO_PER_USDC, MarketplaceGetResult, MarketplaceListInput, MarketplaceSaleResult, Network, PayInput, Payment, type PaymentRequirement, PayoutError, PayoutRule, PayoutRule as PayoutRuleCompute, Playmos, PlaymosConfig, PrizeBalance, RoundCancelInput, RoundGetResult, RoundOpenInput, RoundSettleInput, RoundState, SettleRoundResult, type SettlementAsset, TransferConfirmOptions, TransferInput, TransferReconcile, TransferResult, USDC_ADDRESS, USDC_DECIMALS, VerifyResult, WaitOptions, type WalletSignatureAuthorization, WebhookEvent, WithdrawResult, type X402ChallengeInput, type X402ChallengeResult, type X402FulfillAuthorization, type X402PayInput, type X402PayloadAuthorization, type X402PayloadMode, type X402PaymentRequired, type X402SettleResult, clientRuntimeSignals, computeIapSplit, computePayout, computePoolSplit, createPaymentRequirement, createX402Challenge, decodePaymentHeader, encodePaymentHeader, formatMicroToUsd, isClientRuntime, isWalletSignatureAuthorization, isX402PayloadAuthorization, networkToCaip2, parsePaymentRequirement, parseUsdToMicro, prefixedId, previewEscrowFee, previewIapSplit, previewMarketplaceSplit, previewPoolSplit, previewTransferSplit, resolveEnv, serializePaymentRequirement, toX402PaymentRequired, ulid, validateX402ChallengeInput };
package/dist/index.js CHANGED
@@ -1530,19 +1530,34 @@ var Playmos = class {
1530
1530
  }
1531
1531
  return { ...result, txHash: result.txHash ?? firstTx ?? null };
1532
1532
  },
1533
+ /**
1534
+ * Round state only (stable). Prefer {@link getWithMeta} when you need service
1535
+ * read-path honesty (`via` / `chainReadFailed` — #497 / #501).
1536
+ */
1533
1537
  get: async (input) => {
1538
+ const meta = await this.rounds.getWithMeta(input);
1539
+ return meta.round;
1540
+ },
1541
+ /**
1542
+ * Round state + transport meta from GET /v1/rounds/:id (#501).
1543
+ * Does **not** attach `via` onto RoundState (Claude rejected option B — hub would
1544
+ * silently pick it up and leak into settle/cancel paths that call get()).
1545
+ * Under `mock: true`, meta fields are **omitted** (no eth_call; do not invent "cache").
1546
+ */
1547
+ getWithMeta: async (input) => {
1534
1548
  requireField(input?.roundId, "roundId");
1535
1549
  if (this.config.mock) {
1536
1550
  const existing = this.mockRounds.get(input.roundId);
1537
1551
  if (!existing) {
1538
1552
  throw new ApiError(`unknown round: ${input.roundId}`, { status: 404, code: "not_found" });
1539
1553
  }
1540
- return existing;
1554
+ return { round: existing };
1541
1555
  }
1542
- const { round } = await this.http.get(
1543
- `/rounds/${encodeURIComponent(input.roundId)}`
1544
- );
1545
- return round;
1556
+ const body = await this.http.get(`/rounds/${encodeURIComponent(input.roundId)}`);
1557
+ const out = { round: body.round };
1558
+ if (body.via != null) out.via = body.via;
1559
+ if (body.chainReadFailed === true) out.chainReadFailed = true;
1560
+ return out;
1546
1561
  },
1547
1562
  /**
1548
1563
  * Authoritative series latch (#351) — `null` means **proven free**.
@@ -1647,19 +1662,26 @@ var Playmos = class {
1647
1662
  */
1648
1663
  withdraw: async (input) => {
1649
1664
  if (this.config.mock) {
1650
- let amountMicro2 = 0n;
1651
1665
  let prizePool2 = input.prizePoolAddress ?? "0x0000000000000000000000000000000000000001";
1652
1666
  if (input.roundId) {
1653
1667
  const existing = this.mockRounds.get(input.roundId);
1654
1668
  if (existing?.prizePoolAddress) prizePool2 = existing.prizePoolAddress;
1655
- for (const [k, v] of this.mockWithdrawable) {
1656
- if (k.startsWith(`${input.roundId}:`) && v > 0n) {
1657
- amountMicro2 = v;
1658
- this.mockWithdrawable.set(k, 0n);
1659
- break;
1660
- }
1661
- }
1662
1669
  }
1670
+ if (!input.wallet || !ADDRESS_RE3.test(input.wallet)) {
1671
+ throw new ConfigError(
1672
+ "mock rounds.withdraw requires wallet (0x\u2026) \u2014 live uses the connected provider; without wallet mock would pay the first non-zero credit to the wrong player (#495)"
1673
+ );
1674
+ }
1675
+ const wallet = input.wallet.toLowerCase();
1676
+ if (!input.roundId) {
1677
+ throw new ConfigError("mock rounds.withdraw requires roundId to locate claimable credits");
1678
+ }
1679
+ const key = `${input.roundId}:${wallet}`;
1680
+ const amountMicro2 = this.mockWithdrawable.get(key) ?? 0n;
1681
+ if (amountMicro2 === 0n) {
1682
+ throw new NothingToWithdrawError({ prizePoolAddress: prizePool2, wallet });
1683
+ }
1684
+ this.mockWithdrawable.set(key, 0n);
1663
1685
  return {
1664
1686
  prizePoolAddress: prizePool2,
1665
1687
  amount: formatMicroToUsd(amountMicro2),
package/dist/server.d.cts CHANGED
@@ -1,4 +1,4 @@
1
- import { Y as PlaymosError, W as WebhookEvent } from './errors-BMlWHsMb.cjs';
1
+ import { Z as PlaymosError, W as WebhookEvent } from './errors-Chizbb96.cjs';
2
2
 
3
3
  /**
4
4
  * Webhook signature verification (spec §6.2) — server-side only.
package/dist/server.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { Y as PlaymosError, W as WebhookEvent } from './errors-BMlWHsMb.js';
1
+ import { Z as PlaymosError, W as WebhookEvent } from './errors-Chizbb96.js';
2
2
 
3
3
  /**
4
4
  * Webhook signature verification (spec §6.2) — server-side only.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@playmos/sdk",
3
- "version": "0.3.9",
3
+ "version": "0.3.10",
4
4
  "description": "Playmos SDK — stablecoin payments for games on Base. One SDK for IAP (1%), skill-game prize-pool entries (10%, 60/30/10), and agent economies. USD in, USDC on-chain, no crypto UX for players.",
5
5
  "license": "UNLICENSED",
6
6
  "private": false,