@playmos/sdk 0.3.10 → 0.3.12

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/dist/index.d.cts CHANGED
@@ -1,5 +1,625 @@
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';
1
+ import { C as Call, P as PlaymosConfig, O as OnchainStatus, N as Network, W as WebhookEvent, R as RoundOpenInput, a as RoundState, b as RoundSettleInput, S as SettleRoundResult, c as RoundCancelInput, d as CancelRoundResult, e as RoundGetResult, A as ActiveSeriesRound, f as PayoutNoticesResult, g as PrizeBalance, h as WithdrawResult, i as AgentWallet, j as AgentFundResult, T as TransferResult, E as EscrowHoldInput, k as EscrowHoldResult, l as EscrowResolveResult, M as MarketplaceListInput, L as Listing, m as MarketplaceSaleResult, n as MarketplaceGetResult, o as PayInput, p as Payment, q as EnterRoundInput, r as TransferReconcile, s as WaitOptions, t as TransferInput, u as TransferConfirmOptions, V as VerifyResult, v as PayoutRule } from './errors-CYKgt2VU.cjs';
2
+ export { w as ActiveForSeriesResult, x as AgentEconomyConfig, y as AlreadyEnteredError, z as ApiError, B as AuthError, D as ConfigError, F as ContractConfig, G as Eip1193Provider, H as GasConfig, I as GasMode, J as InsufficientGasError, K as InvalidAmountError, Q as ListingStatus, U as MarketplaceItem, X as MarketplaceSale, Y as MissingFieldError, Z as NothingToWithdrawError, _ as PaymentFailedError, $ as PaymentStatus, a0 as PayoutNotice, a1 as PayoutNoticeStatus, a2 as PlaymosError, a3 as PlaymosErrorCode, a4 as RetryOptions, a5 as RoundGetVia, a6 as RoundStatus, a7 as WalletConfig, a8 as WalletConnectionError, a9 as WalletConnector, aa as WalletTimeoutError, ab as WebhookEventType, ac as buildEpochExecuteSettlementCall } from './errors-CYKgt2VU.cjs';
3
+
4
+ /**
5
+ * Thin REST client for the Playmos service. Every SDK method that touches the
6
+ * backend (create intent, verify, payouts, agents) goes through here. `verify()`
7
+ * hits `GET /payments/:id`, which the service resolves by READING THE CHAIN — so
8
+ * the SDK never trusts a client claim or a mutable counter (#337 root fix).
9
+ *
10
+ * Automatic backoff/retry (#50 + BB-GATEB-002):
11
+ * - HTTP **429** (rate limit): always retried with exponential backoff + jitter
12
+ * (honors `Retry-After` when present).
13
+ * - HTTP **502 / 503 / 504** (gateway / DO via_upstream HTML): GET always retried;
14
+ * POST only when an `idempotency-key` is present so a retried write never
15
+ * double-broadcasts. Opt out: `retry: false` or `retry: { maxRetries: 0 }`.
16
+ */
17
+
18
+ /** Options for {@link HttpClient.post}. */
19
+ interface HttpPostOptions {
20
+ idempotencyKey?: string;
21
+ /**
22
+ * HTTP statuses to treat as success in addition to 2xx.
23
+ * Used by x402 challenge mint, which correctly returns **402 Payment Required**.
24
+ */
25
+ acceptStatuses?: number[];
26
+ }
27
+ interface HttpClient {
28
+ post<T>(path: string, body: unknown, opts?: HttpPostOptions): Promise<T>;
29
+ get<T>(path: string): Promise<T>;
30
+ }
31
+
32
+ /**
33
+ * Series string → bytes32. Shared by SDK S1 reads and the service reader.
34
+ *
35
+ * Pass-through when already `0x`+64 hex; otherwise keccak of UTF-8
36
+ * (`keccak256(toHex(s))` == `ethers.id` / C1). Do not use `toBytes(s)` —
37
+ * viem hex-decodes address-shaped strings and drifts from the chain.
38
+ */
39
+ declare function seriesToBytes32(series: string): `0x${string}`;
40
+ /**
41
+ * Identity string → bytes32 (sdk#633). Deliberately the SAME function object as
42
+ * {@link seriesToBytes32}, not a copy: an identity that hashes differently from
43
+ * the chain records a paid entry against an id nobody scores. A second
44
+ * implementation could drift; an alias cannot.
45
+ */
46
+ declare const identityToBytes32: typeof seriesToBytes32;
47
+
48
+ /**
49
+ * Epoch entry calls (sdk#635 / S2).
50
+ *
51
+ * Deliberately NOT in `calls.ts`: that file's `toBytes32` is
52
+ * `keccak256(toBytes(s))`, which viem hex-decodes for hex-shaped input and
53
+ * therefore disagrees with the chain (sdk#633). It stays as-is because the
54
+ * legacy PrizePool's live paid entries were written with it. The epoch path
55
+ * uses the shared `seriesToBytes32` / `identityToBytes32` instead.
56
+ */
57
+
58
+ interface EpochEntryCallsArgs {
59
+ usdc: `0x${string}`;
60
+ epochPrizePool: `0x${string}`;
61
+ /** Plain series string, or an already-derived 0x+64 bytes32. */
62
+ series: string;
63
+ /** Plain identity string, or an already-derived 0x+64 bytes32. */
64
+ identity: string;
65
+ /** The series' `entry` price in micro-USDC, read from the chain. */
66
+ entryMicro: bigint;
67
+ }
68
+ /** approve USDC → EpochPrizePool, then EpochPrizePool.enter(). One atomic batch. */
69
+ declare function buildEpochEntryCalls(args: EpochEntryCallsArgs): Call[];
70
+ interface EpochClaimRefundCallArgs {
71
+ epochPrizePool: `0x${string}`;
72
+ series: string;
73
+ epochId: bigint;
74
+ /** The address that paid — credit always lands here, never on the caller. */
75
+ payer: `0x${string}`;
76
+ }
77
+ /** EpochPrizePool.claimRefund(series, epochId, payer). Permissionless; credit → payer. */
78
+ declare function buildEpochClaimRefundCall(args: EpochClaimRefundCallArgs): Call;
79
+ /** EpochPrizePool.withdraw() — payer wallet pulls USDC. Not PrizePool.withdraw. */
80
+ declare function buildEpochWithdrawCall(epochPrizePool: `0x${string}`): Call;
81
+
82
+ /**
83
+ * Rolling-epoch reads (sdk#629 / S1), `enter` (sdk#635 / S2), D14 studio
84
+ * pool create (sdk#643), operator settle (sdk#639 / S3), and the C3 refund
85
+ * pull (sdk#634): `claimableRefund` / `claimRefund` / `withdraw`.
86
+ *
87
+ * `epochs.currentId` and `epochs.prize` — chain-backed via the service.
88
+ * `epochs.enter` — pay into whatever window the clock says is current; no open
89
+ * gate. `epochs.preparePool` / `registerPool` / `createPool` — studio wallet
90
+ * deploys the existing EpochPrizePool constructor; Playmos is feeSink only.
91
+ * `epochs.settle` — secret key, operator wallet, broadcast + 202. Passes the
92
+ * roster through; does not build a hub roster (R7b).
93
+ * `epochs.claimableRefund` / `claimRefund` / `withdraw` — wallet-direct on
94
+ * EpochPrizePool. No service hop. `withdraw` reports the credited balance it
95
+ * read before pulling, or no figure at all — never a placeholder zero beside a
96
+ * confirmed pull. Live `rounds.withdraw` stays on PrizePool.
97
+ * `epochs.getAttestation` / `executeSettlement` / `settlementTypedData` — E1b
98
+ * public board + permissionless relay of an operator-signed podium. The SDK
99
+ * never authors winners. `settled` is only reported from a chain read of
100
+ * `terminal`. Live `rounds.*` / `enterRound` are a different pool and stay unchanged.
101
+ */
102
+
103
+ /** Playmos Base Sepolia feeSink (PlaymosPay / PrizePool). Service pins this. */
104
+ declare const PLAYMOS_FEE_SINK_DEFAULT: "0x1b8031e20ed96131a849a52290b4d640f286998d";
105
+ declare function encodeEpochPoolConstructorArgs(args: {
106
+ token: `0x${string}`;
107
+ admin: `0x${string}`;
108
+ operator: `0x${string}`;
109
+ feeSink: `0x${string}`;
110
+ refundTimeout: bigint;
111
+ }): `0x${string}`;
112
+
113
+ type EpochTerminal = "none" | "settled" | "refunded" | "rolled";
114
+ type EpochReadVia = "service" | "mock" | "chain";
115
+ interface EpochCurrentId {
116
+ series: string;
117
+ epochId: string;
118
+ via: EpochReadVia;
119
+ epochPrizePool?: `0x${string}` | null;
120
+ mock?: true;
121
+ }
122
+ interface EpochPrize {
123
+ series: string;
124
+ epochId: string;
125
+ /** This epoch's 60% bucket (USD). */
126
+ pool: string;
127
+ /** Inherited seed already sitting on this epoch (USD). */
128
+ incomingSeed: string;
129
+ /** This epoch's 30% — released only at settle (USD). */
130
+ outgoingSeed: string;
131
+ /** Settle payable = incomingSeed + pool (USD). */
132
+ payable: string;
133
+ poolMicro: string;
134
+ incomingSeedMicro: string;
135
+ outgoingSeedMicro: string;
136
+ payableMicro: string;
137
+ via: EpochReadVia;
138
+ epochPrizePool?: `0x${string}` | null;
139
+ mock?: true;
140
+ }
141
+ interface EpochView {
142
+ series: string;
143
+ epochId: string;
144
+ pool: string;
145
+ outgoingSeed: string;
146
+ incomingSeed: string;
147
+ payable: string;
148
+ poolMicro: string;
149
+ outgoingSeedMicro: string;
150
+ incomingSeedMicro: string;
151
+ payableMicro: string;
152
+ entryCount: string;
153
+ terminal: EpochTerminal;
154
+ via: EpochReadVia;
155
+ epochPrizePool?: `0x${string}` | null;
156
+ mock?: true;
157
+ }
158
+ interface EpochSeriesView {
159
+ series: string;
160
+ created: boolean;
161
+ genesis: string;
162
+ epochDuration: string;
163
+ entry: string;
164
+ feeBps: number;
165
+ poolBps: number;
166
+ seedBps: number;
167
+ via: EpochReadVia;
168
+ epochPrizePool?: `0x${string}` | null;
169
+ mock?: true;
170
+ }
171
+ interface EpochCurrentIdInput {
172
+ series: string;
173
+ epochPrizePool?: `0x${string}`;
174
+ /** Mock only — series genesis (unix seconds). */
175
+ genesis?: number | string;
176
+ /** Mock only — epoch duration (seconds). */
177
+ epochDuration?: number | string;
178
+ /** Mock only — clock to derive against (unix seconds). */
179
+ at?: number | string;
180
+ }
181
+ interface EpochPrizeInput {
182
+ series: string;
183
+ /** Omit to read the live epoch (`/epochs/current/prize`). */
184
+ epochId?: number | string;
185
+ epochPrizePool?: `0x${string}`;
186
+ }
187
+ interface EpochGetInput {
188
+ series: string;
189
+ epochId?: number | string;
190
+ epochPrizePool?: `0x${string}`;
191
+ }
192
+ interface EpochGetSeriesInput {
193
+ series: string;
194
+ epochPrizePool?: `0x${string}`;
195
+ }
196
+ /** Real status union — never a `"mocked"` status (P0 invariant #2). */
197
+ type EpochEntryStatus = "created" | "pending" | "confirmed" | "failed";
198
+ interface EpochEnterInput {
199
+ series: string;
200
+ /**
201
+ * The on-chain id this paid attempt is scored under. Required — never
202
+ * invented for you, because an invented identity means the player pays and
203
+ * their score is looked up somewhere else (#374 / #466).
204
+ */
205
+ identity: string;
206
+ epochPrizePool?: `0x${string}`;
207
+ /** Mock only — series genesis (unix seconds). */
208
+ genesis?: number | string;
209
+ /** Mock only — epoch duration (seconds). */
210
+ epochDuration?: number | string;
211
+ /** Mock only — clock to derive the window against (unix seconds). */
212
+ at?: number | string;
213
+ }
214
+ interface EpochEntry {
215
+ series: string;
216
+ identity: string;
217
+ /** The window this entry belongs to. */
218
+ epochId: string;
219
+ /**
220
+ * Where `epochId` came from. `chain-event` is the window the chain actually
221
+ * recorded (read back from the `Entered` log). `chain-clock` is the window
222
+ * that was current when the call was built — correct unless the tx mines on
223
+ * the far side of a boundary, which is why a confirmed entry always reports
224
+ * `chain-event`.
225
+ */
226
+ epochIdSource: "chain-event" | "chain-clock" | "mock";
227
+ seriesBytes32: `0x${string}`;
228
+ identityBytes32: `0x${string}`;
229
+ /** Entry price (USD) — the series' immutable `entry`, read from chain. */
230
+ entry: string;
231
+ entryMicro: string;
232
+ status: EpochEntryStatus;
233
+ txHash?: `0x${string}`;
234
+ /**
235
+ * How many paid entries this identity now has in this window (D9). A second
236
+ * entry reads `2` — re-entry is the product, not an error.
237
+ */
238
+ identityEntryCount?: string;
239
+ epochPrizePool?: `0x${string}` | null;
240
+ usdc?: `0x${string}` | null;
241
+ via: EpochReadVia;
242
+ mock?: true;
243
+ }
244
+ interface EpochPreparePoolInput {
245
+ studioWallet: `0x${string}`;
246
+ /** Must equal the Playmos sink if set; any other address is refused before broadcast. */
247
+ feeSink?: `0x${string}`;
248
+ admin?: `0x${string}`;
249
+ operator?: `0x${string}`;
250
+ refundTimeout?: number | string;
251
+ playmosFeeSink?: `0x${string}`;
252
+ token?: `0x${string}`;
253
+ }
254
+ interface EpochPreparedPool {
255
+ token: `0x${string}`;
256
+ admin: `0x${string}`;
257
+ operator: `0x${string}`;
258
+ feeSink: `0x${string}`;
259
+ refundTimeout: string;
260
+ constructorArgs: `0x${string}`;
261
+ constructor: "EpochPrizePool";
262
+ studioHoldsAdmin: true;
263
+ studioHoldsOperator: true;
264
+ playmosIsAdmin: false;
265
+ playmosIsOperator: false;
266
+ via: EpochReadVia;
267
+ mock?: true;
268
+ }
269
+ /**
270
+ * The studio wallet's EIP-191 signature over `EpochStudioPool.proof.message`.
271
+ * Without it the pool is verified on chain but ownership is left unrecorded —
272
+ * a wallet you do not hold the key to can never be registered as yours.
273
+ */
274
+ interface EpochPoolWalletProof {
275
+ signature: `0x${string}`;
276
+ }
277
+ interface EpochRegisterPoolInput {
278
+ studioWallet: `0x${string}`;
279
+ poolAddress: `0x${string}`;
280
+ feeSink?: `0x${string}`;
281
+ admin?: `0x${string}`;
282
+ operator?: `0x${string}`;
283
+ txHash?: string;
284
+ walletProof?: EpochPoolWalletProof;
285
+ }
286
+ /** `pending` = chain-verified, owner NOT recorded (no wallet proof supplied). */
287
+ type EpochPoolOwnership = "pending" | "confirmed";
288
+ interface EpochStudioPool {
289
+ poolAddress: `0x${string}`;
290
+ studioId?: string | null;
291
+ studioWallet: `0x${string}`;
292
+ feeSink: `0x${string}`;
293
+ admin: `0x${string}`;
294
+ operator: `0x${string}`;
295
+ studioHoldsAdmin: true;
296
+ studioHoldsOperator: true;
297
+ playmosIsAdmin: false;
298
+ playmosIsOperator: false;
299
+ ownership?: EpochPoolOwnership;
300
+ owner?: string | null;
301
+ /** Present while `ownership` is `pending` — sign `message` and re-register. */
302
+ proof?: {
303
+ scheme: "eip191-personal-sign";
304
+ wallet: `0x${string}`;
305
+ message: string;
306
+ };
307
+ via: EpochReadVia;
308
+ mock?: true;
309
+ }
310
+ interface EpochCreatePoolInput extends EpochPreparePoolInput {
311
+ /** After the studio wallet submitted the constructor; omitted in mock. */
312
+ poolAddress?: `0x${string}`;
313
+ txHash?: string;
314
+ walletProof?: EpochPoolWalletProof;
315
+ }
316
+ type EpochWinnerIn = `0x${string}` | {
317
+ wallet: `0x${string}`;
318
+ amount?: string;
319
+ amountMicro?: string;
320
+ };
321
+ interface EpochSettleInput {
322
+ series: string;
323
+ epochId: number | string;
324
+ /** Empty array is a legal D11 roll. */
325
+ winners: EpochWinnerIn[];
326
+ epochPrizePool?: `0x${string}`;
327
+ }
328
+ type EpochSettleStatus = "settling" | "settled" | "rolled" | "refunded";
329
+ interface EpochSettleWinner {
330
+ wallet: `0x${string}`;
331
+ /**
332
+ * USD decimal. Present only when the seat's share is known — a wallet-only
333
+ * roster carries no amounts, and absent ≠ `"0.00"` (sdk#660).
334
+ */
335
+ amount?: string;
336
+ /** Integer micro-USDC (6dp) for the same figure as {@link amount}. */
337
+ amountMicro?: string;
338
+ /** Present only after a chain read-back (never inferred from the podium). */
339
+ withdrawableMicro?: string;
340
+ }
341
+ interface EpochSettleResult {
342
+ series: string;
343
+ epochId: string;
344
+ status: EpochSettleStatus;
345
+ txHash: `0x${string}` | null;
346
+ winners: EpochSettleWinner[];
347
+ /**
348
+ * USDC the podium was paid. Present when the SDK knows it (mock: sum of
349
+ * winner amounts; live: the service figure). ABSENT when unknown — a
350
+ * wallet-only roster has no amounts to add. Never a placeholder `"0"` /
351
+ * `"0.00"` standing in for unknown (sdk#660 / same class as #659 withdraw).
352
+ */
353
+ payable?: string;
354
+ payableMicro?: string;
355
+ terminal?: EpochTerminal;
356
+ via: EpochReadVia;
357
+ epochPrizePool?: `0x${string}` | null;
358
+ mock?: true;
359
+ }
360
+ interface EpochClaimableRefundInput {
361
+ series: string;
362
+ epochId: number | string;
363
+ /** The wallet that paid — the address `claimRefund` will credit. */
364
+ payer: `0x${string}`;
365
+ epochPrizePool?: `0x${string}`;
366
+ }
367
+ interface EpochClaimableRefund {
368
+ series: string;
369
+ epochId: string;
370
+ payer: `0x${string}`;
371
+ claimable: string;
372
+ claimableMicro: string;
373
+ seriesBytes32: `0x${string}`;
374
+ epochPrizePool?: `0x${string}` | null;
375
+ via: EpochReadVia;
376
+ mock?: true;
377
+ }
378
+ interface EpochClaimRefundInput {
379
+ series: string;
380
+ epochId: number | string;
381
+ /** Credit always lands here, even if another wallet signs the tx. */
382
+ payer: `0x${string}`;
383
+ epochPrizePool?: `0x${string}`;
384
+ }
385
+ /**
386
+ * No money figure here on purpose. `claimRefund` returns the credited amount
387
+ * on chain, but a wallet batch hands back a receipt, not that return value —
388
+ * so the SDK does not know it. The figure stays readable on both sides of this
389
+ * call (`claimableRefund` before, `withdraw`'s `amountMicro` after), so there
390
+ * is nothing to guess and nothing to publish as a zero.
391
+ */
392
+ interface EpochClaimRefundResult {
393
+ series: string;
394
+ epochId: string;
395
+ payer: `0x${string}`;
396
+ txHash?: `0x${string}`;
397
+ status: "confirmed" | "pending" | "failed";
398
+ epochPrizePool?: `0x${string}` | null;
399
+ via: EpochReadVia;
400
+ mock?: true;
401
+ }
402
+ interface EpochWithdrawInput {
403
+ epochPrizePool?: `0x${string}`;
404
+ }
405
+ interface EpochWithdrawResult {
406
+ epochPrizePool: `0x${string}`;
407
+ /**
408
+ * The USDC this pull moves, read from `withdrawable[wallet]` on chain
409
+ * immediately before the call — `withdraw()` transfers the whole credited
410
+ * balance, so this is the sum that leaves the pool.
411
+ *
412
+ * ABSENT means the SDK could not read that balance (no reader wired, or the
413
+ * read failed). Absent is not zero: the withdrawal is still broadcast and
414
+ * `txHash` still describes it. Never render a missing amount as `$0.00` —
415
+ * a player who pulled $0.90 must never be shown $0.00.
416
+ */
417
+ amount?: string;
418
+ amountMicro?: string;
419
+ txHash?: `0x${string}`;
420
+ status: "confirmed" | "pending" | "failed";
421
+ via: EpochReadVia;
422
+ mock?: true;
423
+ }
424
+ interface EpochGetAttestationInput {
425
+ series: string;
426
+ epochId: number | string;
427
+ epochPrizePool?: `0x${string}`;
428
+ /** Mock only — fixture the board would have served. */
429
+ winners?: `0x${string}`[];
430
+ /** Mock only — micro-USDC strings. */
431
+ amountsMicro?: string[];
432
+ /** Mock only. */
433
+ signature?: `0x${string}`;
434
+ }
435
+ interface EpochAttestation {
436
+ series: string;
437
+ epochId: string;
438
+ winners: `0x${string}`[];
439
+ amountsMicro: string[];
440
+ signature: `0x${string}`;
441
+ epochPrizePool: `0x${string}`;
442
+ terminal?: EpochTerminal;
443
+ dueAt?: string;
444
+ via: EpochReadVia;
445
+ mock?: true;
446
+ }
447
+ interface EpochExecuteSettlementInput {
448
+ series: string;
449
+ epochId: number | string;
450
+ winners: `0x${string}`[];
451
+ /** Integer micro-USDC strings — never USD. */
452
+ amounts: string[];
453
+ signature: `0x${string}`;
454
+ epochPrizePool?: `0x${string}`;
455
+ }
456
+ interface EpochExecuteSettlementResult {
457
+ series: string;
458
+ epochId: string;
459
+ winners: `0x${string}`[];
460
+ amountsMicro: string[];
461
+ signature: `0x${string}`;
462
+ txHash?: `0x${string}`;
463
+ status: "confirmed" | "pending" | "failed";
464
+ /**
465
+ * Only present after a successful chain read of `getEpoch.terminal`.
466
+ * Absent means the read failed — never inferred from broadcast.
467
+ */
468
+ settled?: boolean;
469
+ terminal?: EpochTerminal;
470
+ epochPrizePool?: `0x${string}` | null;
471
+ via: EpochReadVia;
472
+ mock?: true;
473
+ }
474
+ interface SettlementTypedDataInput {
475
+ pool: `0x${string}`;
476
+ chainId: number;
477
+ series: string;
478
+ epochId: number | string;
479
+ winners: `0x${string}`[];
480
+ amounts: string[];
481
+ }
482
+ interface SettlementTypedData {
483
+ domain: {
484
+ name: "EpochPrizePool";
485
+ version: "1";
486
+ chainId: number;
487
+ verifyingContract: `0x${string}`;
488
+ };
489
+ types: {
490
+ Settlement: [
491
+ {
492
+ name: "series";
493
+ type: "bytes32";
494
+ },
495
+ {
496
+ name: "epochId";
497
+ type: "uint256";
498
+ },
499
+ {
500
+ name: "winners";
501
+ type: "address[]";
502
+ },
503
+ {
504
+ name: "amounts";
505
+ type: "uint256[]";
506
+ }
507
+ ];
508
+ };
509
+ primaryType: "Settlement";
510
+ message: {
511
+ series: `0x${string}`;
512
+ epochId: bigint;
513
+ winners: `0x${string}`[];
514
+ amounts: bigint[];
515
+ };
516
+ }
517
+ interface EpochsApi {
518
+ currentId(input: EpochCurrentIdInput): Promise<EpochCurrentId>;
519
+ prize(input: EpochPrizeInput): Promise<EpochPrize>;
520
+ get(input: EpochGetInput): Promise<EpochView>;
521
+ getSeries(input: EpochGetSeriesInput): Promise<EpochSeriesView>;
522
+ preparePool(input: EpochPreparePoolInput): Promise<EpochPreparedPool>;
523
+ registerPool(input: EpochRegisterPoolInput): Promise<EpochStudioPool>;
524
+ createPool(input: EpochCreatePoolInput): Promise<EpochStudioPool>;
525
+ settle(input: EpochSettleInput): Promise<EpochSettleResult>;
526
+ /**
527
+ * Read EpochPrizePool.claimableRefund — micro-USDC still sitting in
528
+ * refundOwed for this payer on a Refunded window (sdk#634).
529
+ */
530
+ claimableRefund(input: EpochClaimableRefundInput): Promise<EpochClaimableRefund>;
531
+ /**
532
+ * Permissionless: move this payer's refund share into withdrawable[payer].
533
+ * The credit never lands on the caller.
534
+ */
535
+ claimRefund(input: EpochClaimRefundInput): Promise<EpochClaimRefundResult>;
536
+ /**
537
+ * Payer wallet pulls USDC from EpochPrizePool.withdrawable[msg.sender].
538
+ * Not live PrizePool `rounds.withdraw`.
539
+ */
540
+ withdraw(input?: EpochWithdrawInput): Promise<EpochWithdrawResult>;
541
+ /**
542
+ * Fetch a posted signed podium from the service board. Any authenticated
543
+ * key — the board is public. Amounts stay micro-USDC strings.
544
+ */
545
+ getAttestation(input: EpochGetAttestationInput): Promise<EpochAttestation>;
546
+ /**
547
+ * Wallet-direct executeSignedSettlement. Relays the fetched podium
548
+ * byte-exact. `settled` only from a chain read of `terminal`.
549
+ */
550
+ executeSettlement(input: EpochExecuteSettlementInput): Promise<EpochExecuteSettlementResult>;
551
+ /**
552
+ * Pay into whatever window is current right now. No open gate (sdk#635).
553
+ *
554
+ * Once the wallet batch mines this never rejects: an entry carrying a
555
+ * `txHash` comes back even if the confirm read fails, because that hash is
556
+ * the only handle on money that has already moved. Such an entry is
557
+ * `pending` / `chain-clock` — treat it as paid-but-not-read-back, not as a
558
+ * failure to retry.
559
+ */
560
+ enter(input: EpochEnterInput): Promise<EpochEntry>;
561
+ }
562
+ interface EpochsDeps {
563
+ http: () => HttpClient;
564
+ config: () => PlaymosConfig;
565
+ assertSecretKey?: (surface: string) => void;
566
+ /**
567
+ * Send the atomic approve+enter batch from the player's wallet. Supplied by
568
+ * the client so this module stays wallet-agnostic (and so the browser bundle
569
+ * keeps its own wallet funnel). Absent → `enter` refuses rather than
570
+ * pretending (P0 invariant #1).
571
+ */
572
+ sendEntry?: (calls: Call[], opts: {
573
+ paymasterUrl?: string;
574
+ }) => Promise<{
575
+ status: OnchainStatus;
576
+ txHash?: `0x${string}`;
577
+ }>;
578
+ /**
579
+ * Wallet-or-RPC `eth_call`. Used by the refund rail so a player can read
580
+ * `claimableRefund` without a service route (sdk#634; service is a parallel slice).
581
+ */
582
+ readView?: (to: `0x${string}`, data: `0x${string}`) => Promise<`0x${string}`>;
583
+ /**
584
+ * The connected wallet address — the account `withdraw()` pulls to. Needed
585
+ * to read `withdrawable[account]` before the pull, so the result can report
586
+ * the money that actually moves instead of a placeholder.
587
+ */
588
+ walletAddress?: () => Promise<`0x${string}`>;
589
+ }
590
+ /** Derived epochId — same formula as EpochPrizePool._epochIdAt. */
591
+ declare function derivedEpochId(genesis: bigint, epochDuration: bigint, at: bigint): bigint;
592
+ /** Settle payable is inherited seed + this epoch's pool (not outgoingSeed). */
593
+ declare function epochPayableMicro(incomingSeed: bigint, pool: bigint): bigint;
594
+ /** Client-side pin — same refusals as the service, so a bad sink never reaches broadcast. */
595
+ declare function prepareStudioPoolLocal(input: EpochPreparePoolInput, playmosFeeSink: `0x${string}`, token: `0x${string}`, playmosAddresses?: `0x${string}`[]): EpochPreparedPool;
596
+ /**
597
+ * The exact message the studio wallet signs to claim ownership of a pool.
598
+ * Byte-identical to the service's `epochPoolProofMessage` — one byte of drift
599
+ * and a legitimate studio is refused, so keep the two in lockstep.
600
+ */
601
+ declare function epochPoolProofMessage(terms: {
602
+ studioId: string;
603
+ poolAddress: `0x${string}`;
604
+ studioWallet: `0x${string}`;
605
+ chainId: number;
606
+ }): string;
607
+ /**
608
+ * The one EIP-712 derivation E1c and every test must share.
609
+ * Domain: EpochPrizePool / 1 / chainId / pool.
610
+ * Type: Settlement(bytes32 series,uint256 epochId,address[] winners,uint256[] amounts).
611
+ * Amounts are micro-USDC integer strings — never USD. The SDK never signs this.
612
+ */
613
+ declare function settlementTypedData(input: SettlementTypedDataInput): SettlementTypedData;
614
+ declare function createEpochsApi(deps: EpochsDeps): EpochsApi;
615
+ /** Test helper — known C1 1 USDC enter split (fee 10% then 60/30 of remainder). */
616
+ declare const C1_ENTER_SPLIT_MICRO: {
617
+ readonly entry: 1000000n;
618
+ readonly fee: 100000n;
619
+ readonly pool: 600000n;
620
+ readonly outgoingSeed: 300000n;
621
+ readonly incomingSeed: 0n;
622
+ };
3
623
 
4
624
  /**
5
625
  * Environment resolution + the canonical address book.
@@ -373,15 +993,6 @@ declare function validateX402ChallengeInput(input: X402ChallengeInput): {
373
993
  id?: string;
374
994
  };
375
995
 
376
- /**
377
- * The Playmos client — `new Playmos({ apiKey })` → `pay()`, `enterRound()`,
378
- * `verify()`, `webhooks`, `payouts`, `agents`.
379
- *
380
- * Real behavior, no `"mocked"` status anywhere. The chain calls use the proven
381
- * EIP-5792 approve+call batch; `verify()` resolves by the service's on-chain
382
- * read; ids are ULIDs; inputs are validated client-side; idempotency is honored.
383
- */
384
-
385
996
  declare class Playmos {
386
997
  readonly config: PlaymosConfig;
387
998
  readonly env: ResolvedEnv;
@@ -401,6 +1012,16 @@ declare class Playmos {
401
1012
  */
402
1013
  verify: (_rawBody: string | Buffer, _signatureHeader: string | string[] | undefined, _secret: string) => WebhookEvent;
403
1014
  };
1015
+ /**
1016
+ * Rolling epochs — `currentId` / `prize` / `get` / `getSeries` (sdk#629),
1017
+ * `enter` (sdk#635 / S2), operator `settle` (sdk#639 / S3), the C3
1018
+ * refund pull (sdk#634), and E1b `getAttestation` / `executeSettlement`
1019
+ * (wallet-direct via the same `walletProvider()` funnel as `rounds.withdraw`).
1020
+ * Reads/settle go through the service. Refund claim, withdraw, and signed
1021
+ * execute are wallet-direct on EpochPrizePool — not PrizePool.
1022
+ * Nothing here opens a round.
1023
+ */
1024
+ readonly epochs: EpochsApi;
404
1025
  readonly payouts: {
405
1026
  /** Choose how the studio is paid: "usdc" (default) or "fiat" (Bridge). Secret key only (#264). */
406
1027
  setMode: (mode: "usdc" | "fiat") => Promise<{
@@ -479,6 +1100,8 @@ declare class Playmos {
479
1100
  private readonly mockPotMicro;
480
1101
  /** Persisted settle winners for re-settle replay (#490 C2) — never re-invent pool-to-everyone. */
481
1102
  private readonly mockSettleWinners;
1103
+ /** L34 notices after mock settle — funded only with a push txHash. */
1104
+ private readonly mockPayoutNotices;
482
1105
  /**
483
1106
  * Resolve mock round by roundId **or** roundKey (kit `entryProvider` keys by roundKey, #490 C3).
484
1107
  */
@@ -542,6 +1165,28 @@ declare class Playmos {
542
1165
  seriesKey: string;
543
1166
  gameId: string;
544
1167
  }) => Promise<ActiveSeriesRound | null>;
1168
+ /**
1169
+ * L34 / sdk#610 — notifications for a settled round.
1170
+ * Each win is `funded` (push txHash) or `claimable` (withdraw fallback).
1171
+ * Never returns `funded` without a transfer txHash.
1172
+ */
1173
+ payoutNotices: (input: {
1174
+ roundId: string;
1175
+ wallet?: string;
1176
+ }) => Promise<PayoutNoticesResult>;
1177
+ /**
1178
+ * Operator push-attempt after settle (L34). Mock: mark a winner funded only
1179
+ * when a real-shaped txHash is supplied; otherwise that row stays claimable.
1180
+ */
1181
+ pushWinnings: (input: {
1182
+ roundId: string;
1183
+ /** Per-wallet push result. Missing / failed → claimable. */
1184
+ pushes?: Array<{
1185
+ wallet: string;
1186
+ txHash?: string;
1187
+ failed?: boolean;
1188
+ }>;
1189
+ }) => Promise<PayoutNoticesResult>;
545
1190
  /**
546
1191
  * Read a wallet's **claimable** prize balance for a round (issue #41).
547
1192
  * Prefers the service chain read (`GET /v1/rounds/:id/prize?wallet=`); falls
@@ -655,8 +1300,16 @@ declare class Playmos {
655
1300
  /**
656
1301
  * Offline mock payments for this client instance — so `verify(id)` after
657
1302
  * `mock: true` pay/enterRound does not hit the live API (#204).
1303
+ * Keyed by payment id for verify.
658
1304
  */
659
1305
  private readonly mockPayments;
1306
+ /**
1307
+ * sdk#513 / residual B1–B2 — held idempotencyKey offline (live contract rehearsal).
1308
+ * Keyed like service: `${gameId}:${key}` (IAP without gameId uses empty gameId).
1309
+ * Stores terms so same key + different money throws (live IdempotencyConflict), not silent replay.
1310
+ * Auto-minted keys still unique per call (not stored for cross-call replay).
1311
+ */
1312
+ private readonly mockByIdempotencyKey;
660
1313
  constructor(config: PlaymosConfig);
661
1314
  /**
662
1315
  * Wallet timeout policy (#462 / PR #463 residual).
@@ -695,10 +1348,13 @@ declare class Playmos {
695
1348
  identity?: string;
696
1349
  }>;
697
1350
  };
1351
+ private mockIdemScopeKey;
698
1352
  private rememberMock;
1353
+ /** Live-shaped conflict when held mock key is reused with different money terms (sdk#513 residual B1). */
1354
+ private mockIdemReplayOrThrow;
699
1355
  /** External-studio IAP (1%). Returns a real confirmed Payment with a txHash. */
700
1356
  pay(input: PayInput): Promise<Payment>;
701
- /** Playmos-owned skill-game entry (10%, 60/30/10 prize pool). Closes #343. */
1357
+ /** Skill-game prize-pool entry. Live sandbox / Playmos Lab uses 60/30/10. Studio contest take is 1% (not a live separate pool yet). Closes #343. */
702
1358
  enterRound(input: EnterRoundInput): Promise<Payment>;
703
1359
  /**
704
1360
  * `transfers` — read-back / confirmation for a prior `transfer()` (issues #27, #47).
@@ -759,12 +1415,22 @@ declare class Playmos {
759
1415
  * the documented "confirmed" sandbox promise (TTFSC-T0 / cold-run).
760
1416
  */
761
1417
  private waitForServerSettle;
1418
+ /**
1419
+ * sdk#509 — recover a payment after a lost response by the idempotency key you held.
1420
+ * Requires secret sk_test_ (same as list). Returns null if not found.
1421
+ */
1422
+ findPaymentByIdempotencyKey(idempotencyKey: string, opts?: {
1423
+ gameId?: string;
1424
+ }): Promise<Payment | null>;
762
1425
  /**
763
1426
  * Map a server-settled payment (from the `settle: "server"` response) into the
764
1427
  * SDK's `Payment` shape. The service already signed + confirmed on-chain, so we
765
- * pass its authoritative `status`/`txHash`/amounts straight through and, for an
766
- * entry, derive the 60/30/10 USD `split` locally (exactly as the mock + the
767
- * contract compute it) from the parsed amount.
1428
+ * pass its authoritative `status`/`txHash`/amounts straight through.
1429
+ *
1430
+ * For entry, `Payment.split` is a **first-party 60/30/10 projection** from the
1431
+ * request amount using SDK BPS constants (same integer math as mock) — not a
1432
+ * chain read of pool constructor bps or post-lock payable pot (sdk#514 residual N1).
1433
+ * Prefer `chainAmount` / on-chain `getRound` for money truth.
768
1434
  */
769
1435
  private mapServerPayment;
770
1436
  /** Prefer the service's authoritative micro-USDC amount; fall back to the
@@ -838,8 +1504,8 @@ declare function previewPoolSplit(amount: string): {
838
1504
  */
839
1505
 
840
1506
  declare class PayoutError extends Error {
841
- code: "payout_invalid";
842
- constructor(message: string);
1507
+ code: string;
1508
+ constructor(message: string, code?: string);
843
1509
  }
844
1510
  /**
845
1511
  * Apply the studio's payout rule to a payable pool and ranking (best-first).
@@ -884,9 +1550,10 @@ declare function computeIapSplit(amountMicro: bigint, feeBps: number): {
884
1550
  netMicro: bigint;
885
1551
  };
886
1552
  /**
887
- * Skill-game prize-pool split (60/30/10 by default). Floor-matches the on-chain
888
- * `EconomyConfig`. Any 1–2 micro rounding remainder is assigned to the pool so
889
- * the three parts sum EXACTLY to the entry (invariant asserted below).
1553
+ * First-party skill-game prize-pool split (60/30/10 by default). Floor-matches
1554
+ * the on-chain first-party `EconomyConfig`. Not the studio contest take (1%
1555
+ * Playmos / default 60/30/9 not live). Any 1–2 micro rounding remainder is
1556
+ * assigned to the pool so the three parts sum EXACTLY to the entry.
890
1557
  */
891
1558
  declare function computePoolSplit(amountMicro: bigint, poolBps: number, seedBps: number, rakeBps: number): {
892
1559
  poolMicro: bigint;
@@ -908,4 +1575,4 @@ declare function ulid(seedTime?: number): string;
908
1575
  /** `${prefix}_${ulid()}` — e.g. `pay_01J…`, `entry_01J…`, `idem_01J…`. */
909
1576
  declare function prefixedId(prefix: string): string;
910
1577
 
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 };
1578
+ export { ActiveSeriesRound, AgentFundResult, AgentWallet, type Authorization, C1_ENTER_SPLIT_MICRO, CHAIN_ID, CancelRoundResult, type CreatePaymentRequirementInput, DEFAULT_API_BASE_URL, EnterRoundInput, type EpochAttestation, type EpochClaimRefundInput, type EpochClaimRefundResult, type EpochClaimableRefund, type EpochClaimableRefundInput, type EpochCreatePoolInput, type EpochCurrentId, type EpochCurrentIdInput, type EpochEnterInput, type EpochEntry, type EpochEntryStatus, type EpochExecuteSettlementInput, type EpochExecuteSettlementResult, type EpochGetAttestationInput, type EpochGetInput, type EpochGetSeriesInput, type EpochPoolOwnership, type EpochPoolWalletProof, type EpochPreparePoolInput, type EpochPreparedPool, type EpochPrize, type EpochPrizeInput, type EpochReadVia, type EpochRegisterPoolInput, type EpochSeriesView, type EpochSettleInput, type EpochSettleResult, type EpochSettleStatus, type EpochSettleWinner, type EpochStudioPool, type EpochTerminal, type EpochView, type EpochWinnerIn, type EpochWithdrawInput, type EpochWithdrawResult, type EpochsApi, EscrowHoldInput, EscrowHoldResult, EscrowResolveResult, Listing, MICRO_PER_USDC, MarketplaceGetResult, MarketplaceListInput, MarketplaceSaleResult, Network, PLAYMOS_FEE_SINK_DEFAULT, PayInput, Payment, type PaymentRequirement, PayoutError, PayoutNoticesResult, PayoutRule, PayoutRule as PayoutRuleCompute, Playmos, PlaymosConfig, PrizeBalance, RoundCancelInput, RoundGetResult, RoundOpenInput, RoundSettleInput, RoundState, SettleRoundResult, type SettlementAsset, type SettlementTypedData, type SettlementTypedDataInput, 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, buildEpochClaimRefundCall, buildEpochEntryCalls, buildEpochWithdrawCall, clientRuntimeSignals, computeIapSplit, computePayout, computePoolSplit, createEpochsApi, createPaymentRequirement, createX402Challenge, decodePaymentHeader, derivedEpochId, encodeEpochPoolConstructorArgs, encodePaymentHeader, epochPayableMicro, epochPoolProofMessage, formatMicroToUsd, identityToBytes32, isClientRuntime, isWalletSignatureAuthorization, isX402PayloadAuthorization, networkToCaip2, parsePaymentRequirement, parseUsdToMicro, prefixedId, prepareStudioPoolLocal, previewEscrowFee, previewIapSplit, previewMarketplaceSplit, previewPoolSplit, previewTransferSplit, resolveEnv, serializePaymentRequirement, seriesToBytes32, settlementTypedData, toX402PaymentRequired, ulid, validateX402ChallengeInput };