@playmos/sdk 0.3.6 → 0.3.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +42 -18
- package/dist/{chunk-VYR6BBHF.js → chunk-UZECDT6F.js} +15 -1
- package/dist/{errors-CdVzHuhY.d.cts → errors-BMlWHsMb.d.cts} +72 -7
- package/dist/{errors-CdVzHuhY.d.ts → errors-BMlWHsMb.d.ts} +72 -7
- package/dist/index.cjs +390 -49
- package/dist/index.d.cts +18 -9
- package/dist/index.d.ts +18 -9
- package/dist/index.js +376 -51
- package/dist/server.d.cts +1 -1
- package/dist/server.d.ts +1 -1
- package/dist/server.js +1 -1
- package/package.json +6 -2
package/README.md
CHANGED
|
@@ -5,27 +5,13 @@
|
|
|
5
5
|
Stablecoin payments for games on Base. One SDK for in-app purchases (1%), skill-game prize-pool entries (10%, 60/30/10), and **in-game economies** (player · NPC · agent commerce via `transfer()`). USD in, USDC on-chain — no crypto UX for your players.
|
|
6
6
|
|
|
7
7
|
|
|
8
|
-
## Local `file:` / monorepo install
|
|
9
|
-
|
|
10
|
-
`@playmos/sdk` ships **built `dist/`**. `prepare` / `prepack` / `prepublishOnly` run
|
|
11
|
-
`scripts/ensure-build.cjs`, which rebuilds `dist/` via local `tsup` or (on a cold
|
|
12
|
-
`file:` install with no `sdk/node_modules`) `npx --yes tsup@8.3.0`:
|
|
13
|
-
|
|
14
|
-
- `npm install` inside `sdk/`
|
|
15
|
-
- `npm install` of a **`file:`** / git dependency (dogfood monorepos)
|
|
16
|
-
- `npm publish` / pack
|
|
17
|
-
|
|
18
|
-
So wiping `dist/` then `npm i file:…/sdk` still yields a current build (#211).
|
|
19
|
-
CI also fails if committed `dist/` drifts from source.
|
|
20
|
-
|
|
21
|
-
|
|
22
8
|
## Install
|
|
23
9
|
|
|
24
10
|
```bash
|
|
25
11
|
npm i @playmos/sdk
|
|
26
12
|
```
|
|
27
13
|
|
|
28
|
-
Requires **Node 18 / 20 / 22 LTS** for the monorepo
|
|
14
|
+
Requires **Node 18 / 20 / 22 LTS** for local development and CI toolchains. Full toolchain notes live in the private monorepo; third parties only need a current Node LTS and `npm i @playmos/sdk`.
|
|
29
15
|
|
|
30
16
|
## Browser vs server entry
|
|
31
17
|
|
|
@@ -148,7 +134,7 @@ Fields match the table above (`from` optional → defaults to the signer; `feeBp
|
|
|
148
134
|
|
|
149
135
|
### In-game economies — the Playmos Town golden path
|
|
150
136
|
|
|
151
|
-
**In-game economies** = commerce between **players, NPCs, and agents** (AI or scripted). The money primitive is **`transfer()`** (entity-agnostic); NPC/agent wallets use **`agents.*`** (API names unchanged). This is the loop the
|
|
137
|
+
**In-game economies** = commerce between **players, NPCs, and agents** (AI or scripted). The money primitive is **`transfer()`** (entity-agnostic); NPC/agent wallets use **`agents.*`** (API names unchanged). This is the loop the **Playmos Town** pattern runs end to end (described in public docs — Path C / in-game economies): give each NPC a wallet, fund it, then move value with a per-call fee — P2P (5%), a monster bounty (0%), a shop sale (100%). Proven on **Base Sepolia** (transfer layer) — not a claim that a full MMO product is shipped.
|
|
152
138
|
|
|
153
139
|
**Agents need a SECRET test key — `sk_test_`, not `pk_test_`.** Assigning NPC wallets and transferring *from* an NPC are privileged, server-side actions, so they require an `sk_test_` key kept on **your backend** — not the public `pk_test_playmos_sandbox`. `pk_test_` runs the no-wallet `pay()` / `enterRound()` demos above; `sk_test_` unlocks `agents.*` and NPC-funded `transfer`.
|
|
154
140
|
|
|
@@ -199,12 +185,32 @@ t.status; // "settled" (or "failed") — already terminal, no follow-up call
|
|
|
199
185
|
|
|
200
186
|
The sandbox throttles (5 req/min per key), so back-to-back legs can `429`. **Retries are automatic** — the SDK backs off and retries a `429` up to twice by default, and every write carries an idempotency key so a retry never double-broadcasts (tune with `new Playmos({ apiKey, retry: { maxRetries } })`, or `retry: false` to opt out).
|
|
201
187
|
|
|
202
|
-
The full 5-NPC walkthrough — create → fund → P2P / shop / bounty, each confirmed on-chain — is
|
|
188
|
+
The full 5-NPC walkthrough — create → fund → P2P / shop / bounty, each confirmed on-chain — is summarized in the public developer docs (in-game economies / agents). Example script names below are for monorepo operators only:
|
|
203
189
|
|
|
204
190
|
```bash
|
|
205
191
|
PLAYMOS_SK_TEST=sk_test_… PLAYMOS_FEE_SINK=0x… node docs/examples/playmos-town-sdk.mjs
|
|
206
192
|
```
|
|
207
193
|
|
|
194
|
+
## Local `file:` / monorepo install
|
|
195
|
+
|
|
196
|
+
`@playmos/sdk` ships **built `dist/`**. Lifecycle hooks `prepare` / `prepack` / `prepublishOnly`
|
|
197
|
+
run `scripts/ensure-build.cjs` (rebuild via local `tsup` or, on a cold `file:` install with no
|
|
198
|
+
`sdk/node_modules`, `npx --yes tsup@8.3.0`) — **when lifecycle scripts are enabled**.
|
|
199
|
+
|
|
200
|
+
**Repo hardening (sdk#431 / #434):** root + `sdk/` + `service/` + `contracts/` set
|
|
201
|
+
`ignore-scripts=true` in `.npmrc`. That blocks dependency install scripts (supply-chain defense)
|
|
202
|
+
and also suppresses those prepare/prepack/prepublishOnly hooks.
|
|
203
|
+
|
|
204
|
+
| Action | What to do |
|
|
205
|
+
|--------|------------|
|
|
206
|
+
| Day-to-day install in this monorepo | `npm ci` / `npm i` as usual — scripts ignored by design |
|
|
207
|
+
| Rebuild dist after source edits | **`npm run build`** in `sdk/` (user scripts still run) |
|
|
208
|
+
| **Manual** `npm publish` from a laptop | **`cd sdk && npm run build && npm publish`** — do not rely on prepublishOnly |
|
|
209
|
+
| CI publish | Already runs `npm run build` explicitly before pack/publish |
|
|
210
|
+
|
|
211
|
+
So wiping `dist/` then `npm i file:…/sdk` may **not** auto-rebuild under `ignore-scripts`;
|
|
212
|
+
run `npm run build` in `sdk/` first, or use CI. CI also fails if committed `dist/` drifts from source.
|
|
213
|
+
|
|
208
214
|
## Mock mode — offline, deterministic
|
|
209
215
|
|
|
210
216
|
For CI and wiring checks, `mock: true` returns instant, deterministic results with **no network and no chain**. Results carry `mock: true` and use the real status union, so your handling code sees the exact production shape.
|
|
@@ -215,9 +221,23 @@ const payment = await playmos.pay({
|
|
|
215
221
|
gameId: "game_sandbox_iap", sku: "gems_100", amount: "0.99", playerId: "player_abc",
|
|
216
222
|
});
|
|
217
223
|
// instant — payment.status === "confirmed", payment.mock === true
|
|
224
|
+
|
|
225
|
+
// Operator lifecycle offline too — no sk_ required when mock:true (#435)
|
|
226
|
+
await playmos.rounds.open({
|
|
227
|
+
gameId: "game_sandbox_skill",
|
|
228
|
+
roundId: "r1",
|
|
229
|
+
entryAmount: "0.25",
|
|
230
|
+
payout: { kind: "winner-take-all" },
|
|
231
|
+
});
|
|
232
|
+
await playmos.rounds.lock({ roundId: "r1" });
|
|
233
|
+
await playmos.rounds.settle({
|
|
234
|
+
roundId: "r1",
|
|
235
|
+
results: { ranking: ["0x0000000000000000000000000000000000000001"] },
|
|
236
|
+
});
|
|
218
237
|
```
|
|
219
238
|
|
|
220
239
|
Mock mode is not test mode: mock is fabricated and offline; the sandbox is real and settles on Base Sepolia.
|
|
240
|
+
**Live** `rounds.open` / `lock` / `settle` still need a provisioned secret key on the server.
|
|
221
241
|
|
|
222
242
|
## Production — real player wallets
|
|
223
243
|
|
|
@@ -257,4 +277,8 @@ The escrow/marketplace resolve endpoints (release/refund/confirm) return a deter
|
|
|
257
277
|
|
|
258
278
|
## Docs
|
|
259
279
|
|
|
260
|
-
Full
|
|
280
|
+
Full developer docs (install, IAP `pay()`, skill `enterRound()`, agents, webhooks, REST) — **public, no login**:
|
|
281
|
+
|
|
282
|
+
**https://playmos-docs-public.vercel.app/docs**
|
|
283
|
+
|
|
284
|
+
That is the third-party / stranger surface while we stress-test. Production **`playmos.io/docs`** comes after Founder promote (gate still holds for production only).
|
|
@@ -36,11 +36,25 @@ var WalletConnectionError = class extends PlaymosError {
|
|
|
36
36
|
super("wallet_connection", message, detail);
|
|
37
37
|
}
|
|
38
38
|
};
|
|
39
|
+
var WalletTimeoutError = class extends PlaymosError {
|
|
40
|
+
constructor(message = "The wallet did not respond in time. Ask the player to approve the prompt, or retry.", detail) {
|
|
41
|
+
super("wallet_timeout", message, detail);
|
|
42
|
+
}
|
|
43
|
+
};
|
|
39
44
|
var PaymentFailedError = class extends PlaymosError {
|
|
40
45
|
constructor(message = "The on-chain payment did not complete.", detail) {
|
|
41
46
|
super("payment_failed", message, detail);
|
|
42
47
|
}
|
|
43
48
|
};
|
|
49
|
+
var AlreadyEnteredError = class extends PlaymosError {
|
|
50
|
+
constructor(detail) {
|
|
51
|
+
super(
|
|
52
|
+
"already_entered",
|
|
53
|
+
"This identity already entered this round on-chain. For pay-per-play, pass a unique identity per attempt (not just the wallet address).",
|
|
54
|
+
detail
|
|
55
|
+
);
|
|
56
|
+
}
|
|
57
|
+
};
|
|
44
58
|
var AuthError = class extends PlaymosError {
|
|
45
59
|
constructor(message = "Invalid or missing API key.", detail) {
|
|
46
60
|
super("auth", message, detail);
|
|
@@ -66,4 +80,4 @@ var NothingToWithdrawError = class extends PlaymosError {
|
|
|
66
80
|
}
|
|
67
81
|
};
|
|
68
82
|
|
|
69
|
-
export { ApiError, AuthError, ConfigError, InsufficientGasError, InvalidAmountError, MissingFieldError, NothingToWithdrawError, PaymentFailedError, PlaymosError, WalletConnectionError };
|
|
83
|
+
export { AlreadyEnteredError, ApiError, AuthError, ConfigError, InsufficientGasError, InvalidAmountError, MissingFieldError, NothingToWithdrawError, PaymentFailedError, PlaymosError, WalletConnectionError, WalletTimeoutError };
|
|
@@ -28,6 +28,7 @@ interface WalletConfig {
|
|
|
28
28
|
/**
|
|
29
29
|
* Pre-built EIP-1193 provider. If omitted, `injected` uses globalThis.ethereum
|
|
30
30
|
* and `base-account` expects a provider supplied by the Base Account SDK host.
|
|
31
|
+
* A raw provider is still **timeout-wrapped** on resolve (#462) — not a no-op passthrough.
|
|
31
32
|
*/
|
|
32
33
|
provider?: Eip1193Provider;
|
|
33
34
|
}
|
|
@@ -73,6 +74,13 @@ interface PlaymosConfig {
|
|
|
73
74
|
* retry: { maxRetries } → tune attempts / backoff (0 also opts out)
|
|
74
75
|
*/
|
|
75
76
|
retry?: boolean | RetryOptions;
|
|
77
|
+
/**
|
|
78
|
+
* Timeout for **connect / `eth_requestAccounts` only** (#462). Default 20_000.
|
|
79
|
+
* Does **not** bound the payment confirmation sheet (`wallet_sendCalls`) — a short
|
|
80
|
+
* guess there can take the player's USDC without recording the entry (PR #463 residual).
|
|
81
|
+
* Machine RPCs (status polls, balance, chainId) use a separate internal 20s bound.
|
|
82
|
+
*/
|
|
83
|
+
connectTimeoutMs?: number;
|
|
76
84
|
}
|
|
77
85
|
/** Tuning for the automatic 429 retry (all optional; sane defaults). */
|
|
78
86
|
interface RetryOptions {
|
|
@@ -152,9 +160,12 @@ interface EnterRoundInput {
|
|
|
152
160
|
*/
|
|
153
161
|
roundKey?: string;
|
|
154
162
|
/**
|
|
155
|
-
*
|
|
156
|
-
*
|
|
157
|
-
*
|
|
163
|
+
* On-chain entrant id for this paid attempt (e.g. `"0xWallet#nonce"`).
|
|
164
|
+
* **Required on the client-signed (player wallet) path** so hub `hasEntered`
|
|
165
|
+
* matches (#374 / #466). **One entry per identity** — use a **unique value per
|
|
166
|
+
* paid attempt** (pay-per-play); reusing the same identity hits AlreadyEntered.
|
|
167
|
+
* Omit only on no-wallet sandbox server-settle smoke (service may derive).
|
|
168
|
+
* `entryProvider().payEntry` always supplies the kit identity.
|
|
158
169
|
*/
|
|
159
170
|
identity?: string;
|
|
160
171
|
}
|
|
@@ -532,11 +543,34 @@ interface ActiveForSeriesResult {
|
|
|
532
543
|
via: "chain" | "cache";
|
|
533
544
|
active: ActiveSeriesRound | null;
|
|
534
545
|
}
|
|
535
|
-
/**
|
|
546
|
+
/**
|
|
547
|
+
* Input to `playmos.rounds.cancel` (#346 / #376).
|
|
548
|
+
*
|
|
549
|
+
* Default is **submit-only**: returns `status: "cancelling"` after broadcast without
|
|
550
|
+
* inventing success. Pass `confirm: true` to poll until `cancelled` or timeout
|
|
551
|
+
* (still returns honest `cancelling` on timeout — never pretends terminal).
|
|
552
|
+
*/
|
|
553
|
+
interface RoundCancelInput {
|
|
554
|
+
roundId: string;
|
|
555
|
+
gameId?: string;
|
|
556
|
+
/**
|
|
557
|
+
* When true, poll re-POST cancel + GET until `cancelled` or `timeoutMs`.
|
|
558
|
+
* Default **false** so hub fire-and-reconcile stays fast (hub #55).
|
|
559
|
+
*/
|
|
560
|
+
confirm?: boolean;
|
|
561
|
+
/** Max poll ms when `confirm: true` (default 20_000, under hub 25s). */
|
|
562
|
+
timeoutMs?: number;
|
|
563
|
+
/** Poll interval ms when confirming (default 1000). */
|
|
564
|
+
intervalMs?: number;
|
|
565
|
+
}
|
|
566
|
+
/** Result of `playmos.rounds.cancel` — may be async 202 cancelling (#346 / #376). */
|
|
536
567
|
interface CancelRoundResult {
|
|
537
568
|
roundId: string;
|
|
538
569
|
txHash: `0x${string}` | null;
|
|
539
|
-
/**
|
|
570
|
+
/**
|
|
571
|
+
* `"cancelling"` = broadcast accepted, **not** terminal success (series latch may
|
|
572
|
+
* still be held). `"cancelled"` = chain Cancelled(4) finalized — only then forget latch.
|
|
573
|
+
*/
|
|
540
574
|
status: "cancelling" | "cancelled";
|
|
541
575
|
round?: RoundState;
|
|
542
576
|
}
|
|
@@ -561,6 +595,12 @@ interface WithdrawResult {
|
|
|
561
595
|
amountMicro: string;
|
|
562
596
|
txHash?: `0x${string}`;
|
|
563
597
|
status: "confirmed" | "failed" | "pending";
|
|
598
|
+
/**
|
|
599
|
+
* EIP-5792 calls id when the claim was submitted but not yet confirmed (#462).
|
|
600
|
+
* Present on `status: "pending"` so the studio can reconcile later — never treat
|
|
601
|
+
* a slow mining claim as a hard failure.
|
|
602
|
+
*/
|
|
603
|
+
callsId?: string;
|
|
564
604
|
}
|
|
565
605
|
interface RoundSettleInput {
|
|
566
606
|
roundId: string;
|
|
@@ -573,6 +613,14 @@ interface RoundSettleInput {
|
|
|
573
613
|
amount: string;
|
|
574
614
|
}[];
|
|
575
615
|
};
|
|
616
|
+
/**
|
|
617
|
+
* Max ms to poll after async `status: "settling"` before returning honest non-terminal.
|
|
618
|
+
* Default **20_000** — below hub SdkEscrow op timeout (25s) so the answer can reach
|
|
619
|
+
* the hub before the outer race kills the call (#422).
|
|
620
|
+
*/
|
|
621
|
+
timeoutMs?: number;
|
|
622
|
+
/** Poll interval ms while reconciling (default 1000, same as `transfers.wait`). */
|
|
623
|
+
intervalMs?: number;
|
|
576
624
|
}
|
|
577
625
|
/**
|
|
578
626
|
* Result of `playmos.rounds.settle`.
|
|
@@ -603,7 +651,7 @@ interface SettleRoundResult {
|
|
|
603
651
|
* EARLIEST possible layer: input errors fire client-side before any network or
|
|
604
652
|
* chain call, so a studio never pays gas to discover a typo.
|
|
605
653
|
*/
|
|
606
|
-
type PlaymosErrorCode = "invalid_amount" | "missing_field" | "insufficient_gas" | "wallet_connection" | "payment_failed" | "auth" | "api_error" | "config" | "nothing_to_withdraw";
|
|
654
|
+
type PlaymosErrorCode = "invalid_amount" | "missing_field" | "insufficient_gas" | "wallet_connection" | "wallet_timeout" | "payment_failed" | "already_entered" | "auth" | "api_error" | "config" | "nothing_to_withdraw";
|
|
607
655
|
declare class PlaymosError extends Error {
|
|
608
656
|
readonly code: PlaymosErrorCode;
|
|
609
657
|
/** Optional machine context (e.g. the offending field, the http status). */
|
|
@@ -626,10 +674,27 @@ declare class InsufficientGasError extends PlaymosError {
|
|
|
626
674
|
declare class WalletConnectionError extends PlaymosError {
|
|
627
675
|
constructor(message?: string, detail?: Record<string, unknown>);
|
|
628
676
|
}
|
|
677
|
+
/**
|
|
678
|
+
* A wallet `provider.request` call exceeded the per-request deadline (#462).
|
|
679
|
+
* Distinct from {@link WalletConnectionError}: provider is present but the sheet
|
|
680
|
+
* hung / popup was blocked / request never returned. Must NOT be treated as
|
|
681
|
+
* "no wallet" (that would silently route to server-settle).
|
|
682
|
+
*/
|
|
683
|
+
declare class WalletTimeoutError extends PlaymosError {
|
|
684
|
+
constructor(message?: string, detail?: Record<string, unknown>);
|
|
685
|
+
}
|
|
629
686
|
/** The on-chain settlement reverted, was cancelled, or timed out. */
|
|
630
687
|
declare class PaymentFailedError extends PlaymosError {
|
|
631
688
|
constructor(message?: string, detail?: Record<string, unknown>);
|
|
632
689
|
}
|
|
690
|
+
/**
|
|
691
|
+
* PrizePool already has an entry for this `(roundId, identity)` (#462 pay-per-play).
|
|
692
|
+
* Studios using the same identity (e.g. bare wallet) for every attempt hit this on
|
|
693
|
+
* the second paid play — pass a per-attempt identity for pay-per-play.
|
|
694
|
+
*/
|
|
695
|
+
declare class AlreadyEnteredError extends PlaymosError {
|
|
696
|
+
constructor(detail?: Record<string, unknown>);
|
|
697
|
+
}
|
|
633
698
|
/** Bad, missing, or wrong-environment API key (e.g. a pk_test_ key on a live route). */
|
|
634
699
|
declare class AuthError extends PlaymosError {
|
|
635
700
|
constructor(message?: string, detail?: Record<string, unknown>);
|
|
@@ -650,4 +715,4 @@ declare class NothingToWithdrawError extends PlaymosError {
|
|
|
650
715
|
constructor(detail?: Record<string, unknown>);
|
|
651
716
|
}
|
|
652
717
|
|
|
653
|
-
export {
|
|
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 };
|
|
@@ -28,6 +28,7 @@ interface WalletConfig {
|
|
|
28
28
|
/**
|
|
29
29
|
* Pre-built EIP-1193 provider. If omitted, `injected` uses globalThis.ethereum
|
|
30
30
|
* and `base-account` expects a provider supplied by the Base Account SDK host.
|
|
31
|
+
* A raw provider is still **timeout-wrapped** on resolve (#462) — not a no-op passthrough.
|
|
31
32
|
*/
|
|
32
33
|
provider?: Eip1193Provider;
|
|
33
34
|
}
|
|
@@ -73,6 +74,13 @@ interface PlaymosConfig {
|
|
|
73
74
|
* retry: { maxRetries } → tune attempts / backoff (0 also opts out)
|
|
74
75
|
*/
|
|
75
76
|
retry?: boolean | RetryOptions;
|
|
77
|
+
/**
|
|
78
|
+
* Timeout for **connect / `eth_requestAccounts` only** (#462). Default 20_000.
|
|
79
|
+
* Does **not** bound the payment confirmation sheet (`wallet_sendCalls`) — a short
|
|
80
|
+
* guess there can take the player's USDC without recording the entry (PR #463 residual).
|
|
81
|
+
* Machine RPCs (status polls, balance, chainId) use a separate internal 20s bound.
|
|
82
|
+
*/
|
|
83
|
+
connectTimeoutMs?: number;
|
|
76
84
|
}
|
|
77
85
|
/** Tuning for the automatic 429 retry (all optional; sane defaults). */
|
|
78
86
|
interface RetryOptions {
|
|
@@ -152,9 +160,12 @@ interface EnterRoundInput {
|
|
|
152
160
|
*/
|
|
153
161
|
roundKey?: string;
|
|
154
162
|
/**
|
|
155
|
-
*
|
|
156
|
-
*
|
|
157
|
-
*
|
|
163
|
+
* On-chain entrant id for this paid attempt (e.g. `"0xWallet#nonce"`).
|
|
164
|
+
* **Required on the client-signed (player wallet) path** so hub `hasEntered`
|
|
165
|
+
* matches (#374 / #466). **One entry per identity** — use a **unique value per
|
|
166
|
+
* paid attempt** (pay-per-play); reusing the same identity hits AlreadyEntered.
|
|
167
|
+
* Omit only on no-wallet sandbox server-settle smoke (service may derive).
|
|
168
|
+
* `entryProvider().payEntry` always supplies the kit identity.
|
|
158
169
|
*/
|
|
159
170
|
identity?: string;
|
|
160
171
|
}
|
|
@@ -532,11 +543,34 @@ interface ActiveForSeriesResult {
|
|
|
532
543
|
via: "chain" | "cache";
|
|
533
544
|
active: ActiveSeriesRound | null;
|
|
534
545
|
}
|
|
535
|
-
/**
|
|
546
|
+
/**
|
|
547
|
+
* Input to `playmos.rounds.cancel` (#346 / #376).
|
|
548
|
+
*
|
|
549
|
+
* Default is **submit-only**: returns `status: "cancelling"` after broadcast without
|
|
550
|
+
* inventing success. Pass `confirm: true` to poll until `cancelled` or timeout
|
|
551
|
+
* (still returns honest `cancelling` on timeout — never pretends terminal).
|
|
552
|
+
*/
|
|
553
|
+
interface RoundCancelInput {
|
|
554
|
+
roundId: string;
|
|
555
|
+
gameId?: string;
|
|
556
|
+
/**
|
|
557
|
+
* When true, poll re-POST cancel + GET until `cancelled` or `timeoutMs`.
|
|
558
|
+
* Default **false** so hub fire-and-reconcile stays fast (hub #55).
|
|
559
|
+
*/
|
|
560
|
+
confirm?: boolean;
|
|
561
|
+
/** Max poll ms when `confirm: true` (default 20_000, under hub 25s). */
|
|
562
|
+
timeoutMs?: number;
|
|
563
|
+
/** Poll interval ms when confirming (default 1000). */
|
|
564
|
+
intervalMs?: number;
|
|
565
|
+
}
|
|
566
|
+
/** Result of `playmos.rounds.cancel` — may be async 202 cancelling (#346 / #376). */
|
|
536
567
|
interface CancelRoundResult {
|
|
537
568
|
roundId: string;
|
|
538
569
|
txHash: `0x${string}` | null;
|
|
539
|
-
/**
|
|
570
|
+
/**
|
|
571
|
+
* `"cancelling"` = broadcast accepted, **not** terminal success (series latch may
|
|
572
|
+
* still be held). `"cancelled"` = chain Cancelled(4) finalized — only then forget latch.
|
|
573
|
+
*/
|
|
540
574
|
status: "cancelling" | "cancelled";
|
|
541
575
|
round?: RoundState;
|
|
542
576
|
}
|
|
@@ -561,6 +595,12 @@ interface WithdrawResult {
|
|
|
561
595
|
amountMicro: string;
|
|
562
596
|
txHash?: `0x${string}`;
|
|
563
597
|
status: "confirmed" | "failed" | "pending";
|
|
598
|
+
/**
|
|
599
|
+
* EIP-5792 calls id when the claim was submitted but not yet confirmed (#462).
|
|
600
|
+
* Present on `status: "pending"` so the studio can reconcile later — never treat
|
|
601
|
+
* a slow mining claim as a hard failure.
|
|
602
|
+
*/
|
|
603
|
+
callsId?: string;
|
|
564
604
|
}
|
|
565
605
|
interface RoundSettleInput {
|
|
566
606
|
roundId: string;
|
|
@@ -573,6 +613,14 @@ interface RoundSettleInput {
|
|
|
573
613
|
amount: string;
|
|
574
614
|
}[];
|
|
575
615
|
};
|
|
616
|
+
/**
|
|
617
|
+
* Max ms to poll after async `status: "settling"` before returning honest non-terminal.
|
|
618
|
+
* Default **20_000** — below hub SdkEscrow op timeout (25s) so the answer can reach
|
|
619
|
+
* the hub before the outer race kills the call (#422).
|
|
620
|
+
*/
|
|
621
|
+
timeoutMs?: number;
|
|
622
|
+
/** Poll interval ms while reconciling (default 1000, same as `transfers.wait`). */
|
|
623
|
+
intervalMs?: number;
|
|
576
624
|
}
|
|
577
625
|
/**
|
|
578
626
|
* Result of `playmos.rounds.settle`.
|
|
@@ -603,7 +651,7 @@ interface SettleRoundResult {
|
|
|
603
651
|
* EARLIEST possible layer: input errors fire client-side before any network or
|
|
604
652
|
* chain call, so a studio never pays gas to discover a typo.
|
|
605
653
|
*/
|
|
606
|
-
type PlaymosErrorCode = "invalid_amount" | "missing_field" | "insufficient_gas" | "wallet_connection" | "payment_failed" | "auth" | "api_error" | "config" | "nothing_to_withdraw";
|
|
654
|
+
type PlaymosErrorCode = "invalid_amount" | "missing_field" | "insufficient_gas" | "wallet_connection" | "wallet_timeout" | "payment_failed" | "already_entered" | "auth" | "api_error" | "config" | "nothing_to_withdraw";
|
|
607
655
|
declare class PlaymosError extends Error {
|
|
608
656
|
readonly code: PlaymosErrorCode;
|
|
609
657
|
/** Optional machine context (e.g. the offending field, the http status). */
|
|
@@ -626,10 +674,27 @@ declare class InsufficientGasError extends PlaymosError {
|
|
|
626
674
|
declare class WalletConnectionError extends PlaymosError {
|
|
627
675
|
constructor(message?: string, detail?: Record<string, unknown>);
|
|
628
676
|
}
|
|
677
|
+
/**
|
|
678
|
+
* A wallet `provider.request` call exceeded the per-request deadline (#462).
|
|
679
|
+
* Distinct from {@link WalletConnectionError}: provider is present but the sheet
|
|
680
|
+
* hung / popup was blocked / request never returned. Must NOT be treated as
|
|
681
|
+
* "no wallet" (that would silently route to server-settle).
|
|
682
|
+
*/
|
|
683
|
+
declare class WalletTimeoutError extends PlaymosError {
|
|
684
|
+
constructor(message?: string, detail?: Record<string, unknown>);
|
|
685
|
+
}
|
|
629
686
|
/** The on-chain settlement reverted, was cancelled, or timed out. */
|
|
630
687
|
declare class PaymentFailedError extends PlaymosError {
|
|
631
688
|
constructor(message?: string, detail?: Record<string, unknown>);
|
|
632
689
|
}
|
|
690
|
+
/**
|
|
691
|
+
* PrizePool already has an entry for this `(roundId, identity)` (#462 pay-per-play).
|
|
692
|
+
* Studios using the same identity (e.g. bare wallet) for every attempt hit this on
|
|
693
|
+
* the second paid play — pass a per-attempt identity for pay-per-play.
|
|
694
|
+
*/
|
|
695
|
+
declare class AlreadyEnteredError extends PlaymosError {
|
|
696
|
+
constructor(detail?: Record<string, unknown>);
|
|
697
|
+
}
|
|
633
698
|
/** Bad, missing, or wrong-environment API key (e.g. a pk_test_ key on a live route). */
|
|
634
699
|
declare class AuthError extends PlaymosError {
|
|
635
700
|
constructor(message?: string, detail?: Record<string, unknown>);
|
|
@@ -650,4 +715,4 @@ declare class NothingToWithdrawError extends PlaymosError {
|
|
|
650
715
|
constructor(detail?: Record<string, unknown>);
|
|
651
716
|
}
|
|
652
717
|
|
|
653
|
-
export {
|
|
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 };
|