@playmos/sdk 0.3.14 → 0.3.16
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/CHANGELOG.md +13 -0
- package/README.md +13 -5
- package/dist/{chunk-TZFGZNXV.js → chunk-U6BPSEKC.js} +142 -10
- package/dist/{errors-WcDNfb4q.d.cts → errors-CdzI_iYO.d.cts} +6 -3
- package/dist/{errors-WcDNfb4q.d.ts → errors-CdzI_iYO.d.ts} +6 -3
- package/dist/index.cjs +249 -8
- package/dist/index.d.cts +46 -3
- package/dist/index.d.ts +46 -3
- package/dist/index.js +106 -3
- package/dist/server.d.cts +2 -2
- package/dist/server.d.ts +2 -2
- package/dist/server.js +2 -2
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,19 @@ All notable changes to `@playmos/sdk`. This project adheres to [Semantic Version
|
|
|
4
4
|
|
|
5
5
|
## Unreleased
|
|
6
6
|
|
|
7
|
+
## [0.3.16] — 2026-09-11
|
|
8
|
+
|
|
9
|
+
### Added/Fixed
|
|
10
|
+
- EOA / Chrome Coinbase extension: `sendCalls` falls back to sequential `eth_sendTransaction` when `wallet_sendCalls` is missing or fails (not a user cancel). Skip USDC approve when allowance already covers. (#746 / #745)
|
|
11
|
+
|
|
12
|
+
## [0.3.15] — 2026-09-11
|
|
13
|
+
|
|
14
|
+
### Added
|
|
15
|
+
- **`epochs.prepareSeries`** / `POST /v1/epochs/series/prepare` — after register, one call returns an unsigned `createSeries` tx (`broadcast: false`, default `feeBps` 100). The studio EOA signs. Playmos never broadcasts. (#742 / #739)
|
|
16
|
+
|
|
17
|
+
### Fixed (service)
|
|
18
|
+
- Studio-operated pool `POST /v1/epochs/:epochId/settle` returns 4xx naming `settleEpoch` / `executeSignedSettlement`, not a product 502/504. (#741 / #736)
|
|
19
|
+
|
|
7
20
|
## [0.3.14] — 2026-09-11
|
|
8
21
|
|
|
9
22
|
### Added
|
package/README.md
CHANGED
|
@@ -16,7 +16,7 @@ Requires **Node 18 / 20 / 22 LTS** for local development and CI toolchains. Full
|
|
|
16
16
|
|
|
17
17
|
## Browser vs server entry
|
|
18
18
|
|
|
19
|
-
- **Games (browser / Vite / Phaser):** `import { Playmos } from "@playmos/sdk"` — this entry is browser-safe and does **not** import Node `crypto` (issue #9).
|
|
19
|
+
- **Games (browser / Vite / Phaser):** `import { Playmos } from "@playmos/sdk"` — this entry is browser-safe and does **not** import Node `crypto` (issue #9). The package depends on **viem**; the named import tree-shakes, but a default Vite single chunk can still exceed 500 kB gzip-warn.
|
|
20
20
|
- **Your backend (webhook receivers):** `import { verifyWebhook } from "@playmos/sdk/server"` — HMAC verification uses Node crypto and must stay off the client bundle.
|
|
21
21
|
|
|
22
22
|
The sandbox API also sends CORS headers so browser `pay()` / `enterRound()` work without a same-origin proxy (issue #10).
|
|
@@ -51,6 +51,9 @@ while (result.status !== "confirmed" && tries !== 0) {
|
|
|
51
51
|
result = await playmos.verify(payment.id);
|
|
52
52
|
tries -= 1;
|
|
53
53
|
}
|
|
54
|
+
if (result.status !== "confirmed") {
|
|
55
|
+
throw new Error(`not confirmed yet: ${result.status}`);
|
|
56
|
+
}
|
|
54
57
|
|
|
55
58
|
console.log({ id: payment.id, status: result.status, tx: payment.txHash });
|
|
56
59
|
// You won: pay_… + confirmed on Base Sepolia
|
|
@@ -78,24 +81,29 @@ if (result.status === "confirmed") {
|
|
|
78
81
|
### Optional later — skill-game entry (`enterRound()`)
|
|
79
82
|
|
|
80
83
|
```ts
|
|
84
|
+
const idempotencyKey = "entry-player_abc"; // persist BEFORE enterRound
|
|
81
85
|
const entry = await playmos.enterRound({
|
|
82
86
|
gameId: "game_sandbox_skill",
|
|
83
87
|
roundId: "5m-5944009",
|
|
84
88
|
amount: "1.00", // grows this round's pool
|
|
85
89
|
playerId: "player_abc",
|
|
90
|
+
idempotencyKey,
|
|
86
91
|
});
|
|
87
|
-
// entry.status === "confirmed". Public sandbox skill is a shared Playmos pool —
|
|
88
|
-
//
|
|
92
|
+
// entry.status === "confirmed". Public sandbox skill is a shared Playmos pool —
|
|
93
|
+
// not your contest and not your published take. Persist entry.identity
|
|
94
|
+
// (sandbox#entry_…) when there is no wallet. Same $1.00/request cap as pay().
|
|
95
|
+
// Your 1% is IAP pay() and your own registered pool (next section).
|
|
89
96
|
```
|
|
90
97
|
|
|
91
98
|
### Your own contest pool — `epochs.preparePool` (you sign)
|
|
92
99
|
|
|
93
|
-
`@playmos/sdk` **0.3.
|
|
100
|
+
`@playmos/sdk` **0.3.16** ships `epochs.preparePool` and `epochs.prepareSeries` with `unsignedTx` on the typed response. It calls the live API. Playmos sets `broadcast: false` and does **not** send the transaction.
|
|
94
101
|
|
|
95
102
|
1. Fund your studio wallet on Base Sepolia (ETH + test USDC). Playmos has no faucet — use [Coinbase's faucet docs](https://docs.cdp.coinbase.com/faucets/introduction/welcome).
|
|
96
103
|
2. Call `epochs.preparePool({ studioWallet })` or `POST /v1/epochs/pools/prepare`. Use `feeSink` from that response (`0xD84c190085aa59c48a9B478Ea333D50B8DF4aD42`).
|
|
97
104
|
3. Sign `unsignedTx` in your wallet and send it.
|
|
98
|
-
4. `epochs.registerPool` with `walletProof
|
|
105
|
+
4. `epochs.registerPool` with `walletProof`.
|
|
106
|
+
5. `epochs.prepareSeries` — one returned `unsignedTx`, you sign in the same EOA. Then `GET /v1/epochs/series` until `created=true`, then enter **your** game — not the shared sandbox game.
|
|
99
107
|
|
|
100
108
|
Full steps: https://playmos-docs-public.vercel.app/docs#studio-pool-prepare
|
|
101
109
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { keccak256, toHex, numberToHex, encodeFunctionData, toBytes, getAddress } from 'viem';
|
|
1
|
+
import { keccak256, toHex, numberToHex, encodeFunctionData, toBytes, getAddress, decodeFunctionData } from 'viem';
|
|
2
2
|
|
|
3
3
|
// src/errors.ts
|
|
4
4
|
var PlaymosError = class extends Error {
|
|
@@ -140,6 +140,35 @@ var prizePoolAbi = [
|
|
|
140
140
|
outputs: [{ name: "amount", type: "uint256" }]
|
|
141
141
|
}
|
|
142
142
|
];
|
|
143
|
+
var erc20AllowanceAbi = [
|
|
144
|
+
{
|
|
145
|
+
type: "function",
|
|
146
|
+
name: "allowance",
|
|
147
|
+
stateMutability: "view",
|
|
148
|
+
inputs: [
|
|
149
|
+
{ name: "owner", type: "address" },
|
|
150
|
+
{ name: "spender", type: "address" }
|
|
151
|
+
],
|
|
152
|
+
outputs: [{ type: "uint256" }]
|
|
153
|
+
}
|
|
154
|
+
];
|
|
155
|
+
var SEQUENTIAL_TX_ID_PREFIX = "eth:";
|
|
156
|
+
var USER_CANCEL_RE = /reject|denied|cancel|closed/i;
|
|
157
|
+
function sequentialTxId(txHash) {
|
|
158
|
+
return `${SEQUENTIAL_TX_ID_PREFIX}${txHash}`;
|
|
159
|
+
}
|
|
160
|
+
function sequentialTxHashFromId(id) {
|
|
161
|
+
if (!id.startsWith(SEQUENTIAL_TX_ID_PREFIX)) return void 0;
|
|
162
|
+
const hash = id.slice(SEQUENTIAL_TX_ID_PREFIX.length);
|
|
163
|
+
if (/^0x[0-9a-fA-F]{64}$/.test(hash)) return hash;
|
|
164
|
+
return void 0;
|
|
165
|
+
}
|
|
166
|
+
function errorMessage(e) {
|
|
167
|
+
return e?.message ?? String(e);
|
|
168
|
+
}
|
|
169
|
+
function isUserCancel(msg) {
|
|
170
|
+
return USER_CANCEL_RE.test(msg);
|
|
171
|
+
}
|
|
143
172
|
async function sendCalls(provider, from, chainId, calls, paymasterUrl) {
|
|
144
173
|
const params = {
|
|
145
174
|
version: "2.0.0",
|
|
@@ -151,23 +180,85 @@ async function sendCalls(provider, from, chainId, calls, paymasterUrl) {
|
|
|
151
180
|
if (paymasterUrl) {
|
|
152
181
|
params.capabilities = { paymasterService: { url: paymasterUrl } };
|
|
153
182
|
}
|
|
154
|
-
let result;
|
|
155
183
|
try {
|
|
156
|
-
result = await provider.request({ method: "wallet_sendCalls", params: [params] });
|
|
184
|
+
const result = await provider.request({ method: "wallet_sendCalls", params: [params] });
|
|
185
|
+
const id = typeof result === "string" ? result : result?.id ?? "";
|
|
186
|
+
if (!id) throw new PaymentFailedError("Wallet returned no calls id.");
|
|
187
|
+
return { id };
|
|
157
188
|
} catch (e) {
|
|
189
|
+
if (e instanceof PaymentFailedError) throw e;
|
|
158
190
|
if (e instanceof WalletTimeoutError) throw e;
|
|
159
|
-
const msg =
|
|
160
|
-
if (
|
|
191
|
+
const msg = errorMessage(e);
|
|
192
|
+
if (isUserCancel(msg)) {
|
|
161
193
|
throw new WalletConnectionError("The player cancelled or closed the payment sheet.", { cause: msg });
|
|
162
194
|
}
|
|
163
|
-
|
|
195
|
+
return sendCallsSequentially(provider, from, calls);
|
|
164
196
|
}
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
197
|
+
}
|
|
198
|
+
async function skipCoveredApprove(provider, from, calls) {
|
|
199
|
+
const first = calls[0];
|
|
200
|
+
if (!first) return calls;
|
|
201
|
+
let spender;
|
|
202
|
+
let amount;
|
|
203
|
+
try {
|
|
204
|
+
const decoded = decodeFunctionData({ abi: erc20Abi, data: first.data });
|
|
205
|
+
if (decoded.functionName !== "approve") return calls;
|
|
206
|
+
spender = decoded.args[0];
|
|
207
|
+
amount = decoded.args[1];
|
|
208
|
+
} catch {
|
|
209
|
+
return calls;
|
|
210
|
+
}
|
|
211
|
+
try {
|
|
212
|
+
const data = encodeFunctionData({
|
|
213
|
+
abi: erc20AllowanceAbi,
|
|
214
|
+
functionName: "allowance",
|
|
215
|
+
args: [from, spender]
|
|
216
|
+
});
|
|
217
|
+
const raw = await provider.request({
|
|
218
|
+
method: "eth_call",
|
|
219
|
+
params: [{ to: first.to, data }, "latest"]
|
|
220
|
+
});
|
|
221
|
+
const allowance = BigInt(typeof raw === "string" && raw !== "0x" ? raw : "0");
|
|
222
|
+
if (allowance >= amount) return calls.slice(1);
|
|
223
|
+
} catch {
|
|
224
|
+
}
|
|
225
|
+
return calls;
|
|
226
|
+
}
|
|
227
|
+
async function sendCallsSequentially(provider, from, calls) {
|
|
228
|
+
const toSend = await skipCoveredApprove(provider, from, calls);
|
|
229
|
+
if (toSend.length === 0) {
|
|
230
|
+
throw new PaymentFailedError("No wallet calls to send.");
|
|
231
|
+
}
|
|
232
|
+
let lastHash;
|
|
233
|
+
for (const call of toSend) {
|
|
234
|
+
let hash;
|
|
235
|
+
try {
|
|
236
|
+
hash = await provider.request({
|
|
237
|
+
method: "eth_sendTransaction",
|
|
238
|
+
params: [{ from, to: call.to, data: call.data }]
|
|
239
|
+
});
|
|
240
|
+
} catch (e) {
|
|
241
|
+
if (e instanceof WalletTimeoutError) throw e;
|
|
242
|
+
const msg = errorMessage(e);
|
|
243
|
+
if (isUserCancel(msg)) {
|
|
244
|
+
throw new WalletConnectionError("The player cancelled or closed the payment sheet.", { cause: msg });
|
|
245
|
+
}
|
|
246
|
+
throw new PaymentFailedError("eth_sendTransaction failed.", { cause: msg });
|
|
247
|
+
}
|
|
248
|
+
if (typeof hash !== "string" || !/^0x[0-9a-fA-F]{64}$/.test(hash)) {
|
|
249
|
+
throw new PaymentFailedError("Wallet returned no transaction hash.");
|
|
250
|
+
}
|
|
251
|
+
lastHash = hash;
|
|
252
|
+
}
|
|
253
|
+
if (!lastHash) throw new PaymentFailedError("Wallet returned no transaction hash.");
|
|
254
|
+
return { id: sequentialTxId(lastHash) };
|
|
168
255
|
}
|
|
169
256
|
async function waitForCalls(provider, id, timeoutMs = 6e4) {
|
|
170
257
|
if (!id) return { status: "FAILED" };
|
|
258
|
+
const sequentialHash = sequentialTxHashFromId(id);
|
|
259
|
+
if (sequentialHash) {
|
|
260
|
+
return waitForTransactionReceipt(provider, sequentialHash, timeoutMs);
|
|
261
|
+
}
|
|
171
262
|
const deadline = Date.now() + timeoutMs;
|
|
172
263
|
while (Date.now() < deadline) {
|
|
173
264
|
try {
|
|
@@ -190,6 +281,30 @@ async function waitForCalls(provider, id, timeoutMs = 6e4) {
|
|
|
190
281
|
}
|
|
191
282
|
return { status: "PENDING" };
|
|
192
283
|
}
|
|
284
|
+
async function waitForTransactionReceipt(provider, txHash, timeoutMs) {
|
|
285
|
+
const deadline = Date.now() + timeoutMs;
|
|
286
|
+
while (Date.now() < deadline) {
|
|
287
|
+
try {
|
|
288
|
+
const res = await provider.request({
|
|
289
|
+
method: "eth_getTransactionReceipt",
|
|
290
|
+
params: [txHash]
|
|
291
|
+
});
|
|
292
|
+
if (res && res.status !== void 0 && res.status !== null) {
|
|
293
|
+
const code = typeof res.status === "number" ? res.status : Number(res.status);
|
|
294
|
+
if (code === 1) return { status: "CONFIRMED", txHash };
|
|
295
|
+
if (code === 0) return { status: "FAILED", txHash };
|
|
296
|
+
}
|
|
297
|
+
} catch (e) {
|
|
298
|
+
if (e instanceof WalletTimeoutError) {
|
|
299
|
+
await new Promise((r) => setTimeout(r, 900));
|
|
300
|
+
continue;
|
|
301
|
+
}
|
|
302
|
+
throw e;
|
|
303
|
+
}
|
|
304
|
+
await new Promise((r) => setTimeout(r, 900));
|
|
305
|
+
}
|
|
306
|
+
return { status: "PENDING", txHash };
|
|
307
|
+
}
|
|
193
308
|
function encodeApprove(spender, amountUnits) {
|
|
194
309
|
return encodeFunctionData({ abi: erc20Abi, functionName: "approve", args: [spender, amountUnits] });
|
|
195
310
|
}
|
|
@@ -345,6 +460,23 @@ var epochPrizePoolViewAbi = [
|
|
|
345
460
|
outputs: [{ type: "uint256" }]
|
|
346
461
|
}
|
|
347
462
|
];
|
|
463
|
+
var epochPrizePoolCreateSeriesAbi = [
|
|
464
|
+
{
|
|
465
|
+
type: "function",
|
|
466
|
+
name: "createSeries",
|
|
467
|
+
stateMutability: "nonpayable",
|
|
468
|
+
inputs: [
|
|
469
|
+
{ name: "series", type: "bytes32" },
|
|
470
|
+
{ name: "genesis", type: "uint256" },
|
|
471
|
+
{ name: "epochDuration", type: "uint256" },
|
|
472
|
+
{ name: "entry", type: "uint256" },
|
|
473
|
+
{ name: "feeBps", type: "uint16" },
|
|
474
|
+
{ name: "poolBps", type: "uint16" },
|
|
475
|
+
{ name: "seedBps", type: "uint16" }
|
|
476
|
+
],
|
|
477
|
+
outputs: []
|
|
478
|
+
}
|
|
479
|
+
];
|
|
348
480
|
var epochPrizePoolEnterAbi = [
|
|
349
481
|
{
|
|
350
482
|
type: "function",
|
|
@@ -442,4 +574,4 @@ function buildEpochExecuteSettlementCall(args) {
|
|
|
442
574
|
};
|
|
443
575
|
}
|
|
444
576
|
|
|
445
|
-
export { AlreadyEnteredError, ApiError, AuthError, ConfigError, InsufficientGasError, InvalidAmountError, MissingFieldError, NothingToWithdrawError, PaymentFailedError, PlaymosError, WalletConnectionError, WalletTimeoutError, assertEnoughGas, buildEntryCalls, buildEpochExecuteSettlementCall, buildIapCalls, buildWithdrawCall, encodeApprove, epochPrizePoolEnterAbi, epochPrizePoolRefundAbi, epochPrizePoolViewAbi, identityToBytes32, prizePoolAbi, sendCalls, seriesToBytes32, toBytes32, waitForCalls };
|
|
577
|
+
export { AlreadyEnteredError, ApiError, AuthError, ConfigError, InsufficientGasError, InvalidAmountError, MissingFieldError, NothingToWithdrawError, PaymentFailedError, PlaymosError, WalletConnectionError, WalletTimeoutError, assertEnoughGas, buildEntryCalls, buildEpochExecuteSettlementCall, buildIapCalls, buildWithdrawCall, encodeApprove, epochPrizePoolCreateSeriesAbi, epochPrizePoolEnterAbi, epochPrizePoolRefundAbi, epochPrizePoolViewAbi, identityToBytes32, prizePoolAbi, sendCalls, seriesToBytes32, toBytes32, waitForCalls };
|
|
@@ -735,9 +735,12 @@ interface SettleRoundResult {
|
|
|
735
735
|
|
|
736
736
|
/**
|
|
737
737
|
* EIP-5792 batch primitives — ported from the proven game-hub `payEntryOnchain`
|
|
738
|
-
* path (`OnchainEntry.ts`).
|
|
739
|
-
* call as
|
|
740
|
-
*
|
|
738
|
+
* path (`OnchainEntry.ts`). `wallet_sendCalls` still sends `approve` + the
|
|
739
|
+
* settling call as one atomic confirmation when the wallet can batch (paymaster
|
|
740
|
+
* sponsors gas when configured). If `wallet_sendCalls` is missing or fails on an
|
|
741
|
+
* EOA — not a user cancel — the same Call[] is sent as sequential
|
|
742
|
+
* `eth_sendTransaction`s. That fallback is not atomic and never attaches a
|
|
743
|
+
* paymaster. Covered USDC allowance skips the approve tx (one confirm).
|
|
741
744
|
*/
|
|
742
745
|
|
|
743
746
|
interface Call {
|
|
@@ -735,9 +735,12 @@ interface SettleRoundResult {
|
|
|
735
735
|
|
|
736
736
|
/**
|
|
737
737
|
* EIP-5792 batch primitives — ported from the proven game-hub `payEntryOnchain`
|
|
738
|
-
* path (`OnchainEntry.ts`).
|
|
739
|
-
* call as
|
|
740
|
-
*
|
|
738
|
+
* path (`OnchainEntry.ts`). `wallet_sendCalls` still sends `approve` + the
|
|
739
|
+
* settling call as one atomic confirmation when the wallet can batch (paymaster
|
|
740
|
+
* sponsors gas when configured). If `wallet_sendCalls` is missing or fails on an
|
|
741
|
+
* EOA — not a user cancel — the same Call[] is sent as sequential
|
|
742
|
+
* `eth_sendTransaction`s. That fallback is not atomic and never attaches a
|
|
743
|
+
* paymaster. Covered USDC allowance skips the approve tx (one confirm).
|
|
741
744
|
*/
|
|
742
745
|
|
|
743
746
|
interface Call {
|
package/dist/index.cjs
CHANGED
|
@@ -718,6 +718,37 @@ var prizePoolAbi = [
|
|
|
718
718
|
outputs: [{ name: "amount", type: "uint256" }]
|
|
719
719
|
}
|
|
720
720
|
];
|
|
721
|
+
|
|
722
|
+
// src/chain/batch.ts
|
|
723
|
+
var erc20AllowanceAbi = [
|
|
724
|
+
{
|
|
725
|
+
type: "function",
|
|
726
|
+
name: "allowance",
|
|
727
|
+
stateMutability: "view",
|
|
728
|
+
inputs: [
|
|
729
|
+
{ name: "owner", type: "address" },
|
|
730
|
+
{ name: "spender", type: "address" }
|
|
731
|
+
],
|
|
732
|
+
outputs: [{ type: "uint256" }]
|
|
733
|
+
}
|
|
734
|
+
];
|
|
735
|
+
var SEQUENTIAL_TX_ID_PREFIX = "eth:";
|
|
736
|
+
var USER_CANCEL_RE = /reject|denied|cancel|closed/i;
|
|
737
|
+
function sequentialTxId(txHash) {
|
|
738
|
+
return `${SEQUENTIAL_TX_ID_PREFIX}${txHash}`;
|
|
739
|
+
}
|
|
740
|
+
function sequentialTxHashFromId(id) {
|
|
741
|
+
if (!id.startsWith(SEQUENTIAL_TX_ID_PREFIX)) return void 0;
|
|
742
|
+
const hash = id.slice(SEQUENTIAL_TX_ID_PREFIX.length);
|
|
743
|
+
if (/^0x[0-9a-fA-F]{64}$/.test(hash)) return hash;
|
|
744
|
+
return void 0;
|
|
745
|
+
}
|
|
746
|
+
function errorMessage(e) {
|
|
747
|
+
return e?.message ?? String(e);
|
|
748
|
+
}
|
|
749
|
+
function isUserCancel(msg) {
|
|
750
|
+
return USER_CANCEL_RE.test(msg);
|
|
751
|
+
}
|
|
721
752
|
async function sendCalls(provider, from, chainId, calls, paymasterUrl) {
|
|
722
753
|
const params = {
|
|
723
754
|
version: "2.0.0",
|
|
@@ -729,23 +760,85 @@ async function sendCalls(provider, from, chainId, calls, paymasterUrl) {
|
|
|
729
760
|
if (paymasterUrl) {
|
|
730
761
|
params.capabilities = { paymasterService: { url: paymasterUrl } };
|
|
731
762
|
}
|
|
732
|
-
let result;
|
|
733
763
|
try {
|
|
734
|
-
result = await provider.request({ method: "wallet_sendCalls", params: [params] });
|
|
764
|
+
const result = await provider.request({ method: "wallet_sendCalls", params: [params] });
|
|
765
|
+
const id = typeof result === "string" ? result : result?.id ?? "";
|
|
766
|
+
if (!id) throw new PaymentFailedError("Wallet returned no calls id.");
|
|
767
|
+
return { id };
|
|
735
768
|
} catch (e) {
|
|
769
|
+
if (e instanceof PaymentFailedError) throw e;
|
|
736
770
|
if (e instanceof WalletTimeoutError) throw e;
|
|
737
|
-
const msg =
|
|
738
|
-
if (
|
|
771
|
+
const msg = errorMessage(e);
|
|
772
|
+
if (isUserCancel(msg)) {
|
|
739
773
|
throw new WalletConnectionError("The player cancelled or closed the payment sheet.", { cause: msg });
|
|
740
774
|
}
|
|
741
|
-
|
|
775
|
+
return sendCallsSequentially(provider, from, calls);
|
|
776
|
+
}
|
|
777
|
+
}
|
|
778
|
+
async function skipCoveredApprove(provider, from, calls) {
|
|
779
|
+
const first = calls[0];
|
|
780
|
+
if (!first) return calls;
|
|
781
|
+
let spender;
|
|
782
|
+
let amount;
|
|
783
|
+
try {
|
|
784
|
+
const decoded = viem.decodeFunctionData({ abi: erc20Abi, data: first.data });
|
|
785
|
+
if (decoded.functionName !== "approve") return calls;
|
|
786
|
+
spender = decoded.args[0];
|
|
787
|
+
amount = decoded.args[1];
|
|
788
|
+
} catch {
|
|
789
|
+
return calls;
|
|
790
|
+
}
|
|
791
|
+
try {
|
|
792
|
+
const data = viem.encodeFunctionData({
|
|
793
|
+
abi: erc20AllowanceAbi,
|
|
794
|
+
functionName: "allowance",
|
|
795
|
+
args: [from, spender]
|
|
796
|
+
});
|
|
797
|
+
const raw = await provider.request({
|
|
798
|
+
method: "eth_call",
|
|
799
|
+
params: [{ to: first.to, data }, "latest"]
|
|
800
|
+
});
|
|
801
|
+
const allowance = BigInt(typeof raw === "string" && raw !== "0x" ? raw : "0");
|
|
802
|
+
if (allowance >= amount) return calls.slice(1);
|
|
803
|
+
} catch {
|
|
804
|
+
}
|
|
805
|
+
return calls;
|
|
806
|
+
}
|
|
807
|
+
async function sendCallsSequentially(provider, from, calls) {
|
|
808
|
+
const toSend = await skipCoveredApprove(provider, from, calls);
|
|
809
|
+
if (toSend.length === 0) {
|
|
810
|
+
throw new PaymentFailedError("No wallet calls to send.");
|
|
811
|
+
}
|
|
812
|
+
let lastHash;
|
|
813
|
+
for (const call of toSend) {
|
|
814
|
+
let hash;
|
|
815
|
+
try {
|
|
816
|
+
hash = await provider.request({
|
|
817
|
+
method: "eth_sendTransaction",
|
|
818
|
+
params: [{ from, to: call.to, data: call.data }]
|
|
819
|
+
});
|
|
820
|
+
} catch (e) {
|
|
821
|
+
if (e instanceof WalletTimeoutError) throw e;
|
|
822
|
+
const msg = errorMessage(e);
|
|
823
|
+
if (isUserCancel(msg)) {
|
|
824
|
+
throw new WalletConnectionError("The player cancelled or closed the payment sheet.", { cause: msg });
|
|
825
|
+
}
|
|
826
|
+
throw new PaymentFailedError("eth_sendTransaction failed.", { cause: msg });
|
|
827
|
+
}
|
|
828
|
+
if (typeof hash !== "string" || !/^0x[0-9a-fA-F]{64}$/.test(hash)) {
|
|
829
|
+
throw new PaymentFailedError("Wallet returned no transaction hash.");
|
|
830
|
+
}
|
|
831
|
+
lastHash = hash;
|
|
742
832
|
}
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
return { id };
|
|
833
|
+
if (!lastHash) throw new PaymentFailedError("Wallet returned no transaction hash.");
|
|
834
|
+
return { id: sequentialTxId(lastHash) };
|
|
746
835
|
}
|
|
747
836
|
async function waitForCalls(provider, id, timeoutMs = 6e4) {
|
|
748
837
|
if (!id) return { status: "FAILED" };
|
|
838
|
+
const sequentialHash = sequentialTxHashFromId(id);
|
|
839
|
+
if (sequentialHash) {
|
|
840
|
+
return waitForTransactionReceipt(provider, sequentialHash, timeoutMs);
|
|
841
|
+
}
|
|
749
842
|
const deadline = Date.now() + timeoutMs;
|
|
750
843
|
while (Date.now() < deadline) {
|
|
751
844
|
try {
|
|
@@ -768,6 +861,30 @@ async function waitForCalls(provider, id, timeoutMs = 6e4) {
|
|
|
768
861
|
}
|
|
769
862
|
return { status: "PENDING" };
|
|
770
863
|
}
|
|
864
|
+
async function waitForTransactionReceipt(provider, txHash, timeoutMs) {
|
|
865
|
+
const deadline = Date.now() + timeoutMs;
|
|
866
|
+
while (Date.now() < deadline) {
|
|
867
|
+
try {
|
|
868
|
+
const res = await provider.request({
|
|
869
|
+
method: "eth_getTransactionReceipt",
|
|
870
|
+
params: [txHash]
|
|
871
|
+
});
|
|
872
|
+
if (res && res.status !== void 0 && res.status !== null) {
|
|
873
|
+
const code = typeof res.status === "number" ? res.status : Number(res.status);
|
|
874
|
+
if (code === 1) return { status: "CONFIRMED", txHash };
|
|
875
|
+
if (code === 0) return { status: "FAILED", txHash };
|
|
876
|
+
}
|
|
877
|
+
} catch (e) {
|
|
878
|
+
if (e instanceof WalletTimeoutError) {
|
|
879
|
+
await new Promise((r) => setTimeout(r, 900));
|
|
880
|
+
continue;
|
|
881
|
+
}
|
|
882
|
+
throw e;
|
|
883
|
+
}
|
|
884
|
+
await new Promise((r) => setTimeout(r, 900));
|
|
885
|
+
}
|
|
886
|
+
return { status: "PENDING", txHash };
|
|
887
|
+
}
|
|
771
888
|
function encodeApprove(spender, amountUnits) {
|
|
772
889
|
return viem.encodeFunctionData({ abi: erc20Abi, functionName: "approve", args: [spender, amountUnits] });
|
|
773
890
|
}
|
|
@@ -929,6 +1046,23 @@ var epochPrizePoolViewAbi = [
|
|
|
929
1046
|
outputs: [{ type: "uint256" }]
|
|
930
1047
|
}
|
|
931
1048
|
];
|
|
1049
|
+
var epochPrizePoolCreateSeriesAbi = [
|
|
1050
|
+
{
|
|
1051
|
+
type: "function",
|
|
1052
|
+
name: "createSeries",
|
|
1053
|
+
stateMutability: "nonpayable",
|
|
1054
|
+
inputs: [
|
|
1055
|
+
{ name: "series", type: "bytes32" },
|
|
1056
|
+
{ name: "genesis", type: "uint256" },
|
|
1057
|
+
{ name: "epochDuration", type: "uint256" },
|
|
1058
|
+
{ name: "entry", type: "uint256" },
|
|
1059
|
+
{ name: "feeBps", type: "uint16" },
|
|
1060
|
+
{ name: "poolBps", type: "uint16" },
|
|
1061
|
+
{ name: "seedBps", type: "uint16" }
|
|
1062
|
+
],
|
|
1063
|
+
outputs: []
|
|
1064
|
+
}
|
|
1065
|
+
];
|
|
932
1066
|
var epochPrizePoolEnterAbi = [
|
|
933
1067
|
{
|
|
934
1068
|
type: "function",
|
|
@@ -1136,6 +1270,9 @@ function encodeEpochPoolConstructorArgs(args) {
|
|
|
1136
1270
|
args.refundTimeout
|
|
1137
1271
|
]);
|
|
1138
1272
|
}
|
|
1273
|
+
var LOCKED_SERIES_FEE_BPS = 100;
|
|
1274
|
+
var DEFAULT_SERIES_POOL_BPS = 7900;
|
|
1275
|
+
var DEFAULT_SERIES_SEED_BPS = 2e3;
|
|
1139
1276
|
function derivedEpochId(genesis, epochDuration, at) {
|
|
1140
1277
|
if (epochDuration === 0n) {
|
|
1141
1278
|
throw new ConfigError("epochDuration must be > 0");
|
|
@@ -1304,6 +1441,66 @@ function walletStatus(status) {
|
|
|
1304
1441
|
function sameAddr(a, b) {
|
|
1305
1442
|
return a.toLowerCase() === b.toLowerCase();
|
|
1306
1443
|
}
|
|
1444
|
+
function parseSeriesBps(raw, field) {
|
|
1445
|
+
if (raw === void 0) return void 0;
|
|
1446
|
+
if (!Number.isInteger(raw) || raw < 0) {
|
|
1447
|
+
throw new ConfigError(`${field} must be a non-negative integer`);
|
|
1448
|
+
}
|
|
1449
|
+
return raw;
|
|
1450
|
+
}
|
|
1451
|
+
function prepareSeriesLocal(input, chainId) {
|
|
1452
|
+
const pool = requireAddr(input.epochPrizePool, "epochPrizePool");
|
|
1453
|
+
const series = requireSeries(input.series);
|
|
1454
|
+
const feeBps = parseSeriesBps(input.feeBps, "feeBps");
|
|
1455
|
+
if (feeBps !== void 0 && feeBps !== LOCKED_SERIES_FEE_BPS) {
|
|
1456
|
+
throw new ConfigError(
|
|
1457
|
+
"feeBps must be 100 (the locked 1% Playmos take); refused before anything signable"
|
|
1458
|
+
);
|
|
1459
|
+
}
|
|
1460
|
+
const poolBps = parseSeriesBps(input.poolBps, "poolBps") ?? DEFAULT_SERIES_POOL_BPS;
|
|
1461
|
+
const seedBps = parseSeriesBps(input.seedBps, "seedBps") ?? DEFAULT_SERIES_SEED_BPS;
|
|
1462
|
+
if (LOCKED_SERIES_FEE_BPS + poolBps + seedBps !== 1e4) {
|
|
1463
|
+
throw new ConfigError("feeBps + poolBps + seedBps must sum to 10000 (fee is 100)");
|
|
1464
|
+
}
|
|
1465
|
+
const epochDuration = toBig(input.epochDuration, 0n);
|
|
1466
|
+
const entry = toBig(input.entry, 0n);
|
|
1467
|
+
if (epochDuration <= 0n) throw new ConfigError("epochDuration must be greater than 0");
|
|
1468
|
+
if (entry <= 0n) throw new ConfigError("entry must be greater than 0");
|
|
1469
|
+
const genesis = toBig(input.genesis, BigInt(Math.floor(Date.now() / 1e3)));
|
|
1470
|
+
if (genesis <= 0n) throw new ConfigError("genesis must be greater than 0");
|
|
1471
|
+
const data = viem.encodeFunctionData({
|
|
1472
|
+
abi: epochPrizePoolCreateSeriesAbi,
|
|
1473
|
+
functionName: "createSeries",
|
|
1474
|
+
args: [
|
|
1475
|
+
seriesToBytes32(series),
|
|
1476
|
+
genesis,
|
|
1477
|
+
epochDuration,
|
|
1478
|
+
entry,
|
|
1479
|
+
LOCKED_SERIES_FEE_BPS,
|
|
1480
|
+
poolBps,
|
|
1481
|
+
seedBps
|
|
1482
|
+
]
|
|
1483
|
+
});
|
|
1484
|
+
return {
|
|
1485
|
+
series,
|
|
1486
|
+
epochPrizePool: pool,
|
|
1487
|
+
genesis: genesis.toString(),
|
|
1488
|
+
epochDuration: epochDuration.toString(),
|
|
1489
|
+
entry: entry.toString(),
|
|
1490
|
+
feeBps: 100,
|
|
1491
|
+
poolBps,
|
|
1492
|
+
seedBps,
|
|
1493
|
+
unsignedTx: {
|
|
1494
|
+
chainId,
|
|
1495
|
+
to: pool,
|
|
1496
|
+
value: "0",
|
|
1497
|
+
data
|
|
1498
|
+
},
|
|
1499
|
+
broadcast: false,
|
|
1500
|
+
via: "mock",
|
|
1501
|
+
mock: true
|
|
1502
|
+
};
|
|
1503
|
+
}
|
|
1307
1504
|
function prepareStudioPoolLocal(input, playmosFeeSink, token, playmosAddresses = []) {
|
|
1308
1505
|
const studio = requireAddr(input.studioWallet, "studioWallet");
|
|
1309
1506
|
const locked = PLAYMOS_FEE_SINK_DEFAULT;
|
|
@@ -1452,6 +1649,7 @@ async function readEpochTerminal(deps, pool, series, epochId) {
|
|
|
1452
1649
|
}
|
|
1453
1650
|
}
|
|
1454
1651
|
function createEpochsApi(deps) {
|
|
1652
|
+
const mockPreparedSeries = /* @__PURE__ */ new Map();
|
|
1455
1653
|
return {
|
|
1456
1654
|
async currentId(input) {
|
|
1457
1655
|
const series = requireSeries(input?.series);
|
|
@@ -1529,6 +1727,9 @@ function createEpochsApi(deps) {
|
|
|
1529
1727
|
const series = requireSeries(input?.series);
|
|
1530
1728
|
const cfg = deps.config();
|
|
1531
1729
|
if (cfg.mock) {
|
|
1730
|
+
const pool = (input.epochPrizePool ?? cfg.contracts?.epochPrizePool ?? "").toLowerCase();
|
|
1731
|
+
const prepared = mockPreparedSeries.get(`${pool}:${series}`);
|
|
1732
|
+
if (prepared) return prepared;
|
|
1532
1733
|
return {
|
|
1533
1734
|
series,
|
|
1534
1735
|
created: true,
|
|
@@ -1549,6 +1750,42 @@ function createEpochsApi(deps) {
|
|
|
1549
1750
|
})}`;
|
|
1550
1751
|
return deps.http().get(path);
|
|
1551
1752
|
},
|
|
1753
|
+
async prepareSeries(input) {
|
|
1754
|
+
const feeBps = input?.feeBps;
|
|
1755
|
+
if (feeBps !== void 0 && feeBps !== LOCKED_SERIES_FEE_BPS) {
|
|
1756
|
+
throw new ConfigError(
|
|
1757
|
+
"feeBps must be 100 (the locked 1% Playmos take); refused before anything signable"
|
|
1758
|
+
);
|
|
1759
|
+
}
|
|
1760
|
+
const cfg = deps.config();
|
|
1761
|
+
if (cfg.mock) {
|
|
1762
|
+
const prepared = prepareSeriesLocal(input, CHAIN_ID["base-sepolia"]);
|
|
1763
|
+
mockPreparedSeries.set(`${prepared.epochPrizePool}:${prepared.series}`, {
|
|
1764
|
+
series: prepared.series,
|
|
1765
|
+
created: true,
|
|
1766
|
+
genesis: prepared.genesis,
|
|
1767
|
+
epochDuration: prepared.epochDuration,
|
|
1768
|
+
entry: prepared.entry,
|
|
1769
|
+
feeBps: prepared.feeBps,
|
|
1770
|
+
poolBps: prepared.poolBps,
|
|
1771
|
+
seedBps: prepared.seedBps,
|
|
1772
|
+
via: "mock",
|
|
1773
|
+
epochPrizePool: prepared.epochPrizePool,
|
|
1774
|
+
mock: true
|
|
1775
|
+
});
|
|
1776
|
+
return prepared;
|
|
1777
|
+
}
|
|
1778
|
+
return deps.http().post("/epochs/series/prepare", {
|
|
1779
|
+
epochPrizePool: requireAddr(input?.epochPrizePool, "epochPrizePool"),
|
|
1780
|
+
series: requireSeries(input?.series),
|
|
1781
|
+
epochDuration: input.epochDuration,
|
|
1782
|
+
entry: input.entry,
|
|
1783
|
+
genesis: input.genesis,
|
|
1784
|
+
feeBps: input.feeBps,
|
|
1785
|
+
poolBps: input.poolBps,
|
|
1786
|
+
seedBps: input.seedBps
|
|
1787
|
+
});
|
|
1788
|
+
},
|
|
1552
1789
|
async preparePool(input) {
|
|
1553
1790
|
const studioWallet = requireAddr(input?.studioWallet, "studioWallet");
|
|
1554
1791
|
const cfg = deps.config();
|
|
@@ -4238,8 +4475,11 @@ exports.C1_ENTER_SPLIT_MICRO = C1_ENTER_SPLIT_MICRO;
|
|
|
4238
4475
|
exports.CHAIN_ID = CHAIN_ID;
|
|
4239
4476
|
exports.ConfigError = ConfigError;
|
|
4240
4477
|
exports.DEFAULT_API_BASE_URL = DEFAULT_API_BASE_URL;
|
|
4478
|
+
exports.DEFAULT_SERIES_POOL_BPS = DEFAULT_SERIES_POOL_BPS;
|
|
4479
|
+
exports.DEFAULT_SERIES_SEED_BPS = DEFAULT_SERIES_SEED_BPS;
|
|
4241
4480
|
exports.InsufficientGasError = InsufficientGasError;
|
|
4242
4481
|
exports.InvalidAmountError = InvalidAmountError;
|
|
4482
|
+
exports.LOCKED_SERIES_FEE_BPS = LOCKED_SERIES_FEE_BPS;
|
|
4243
4483
|
exports.MICRO_PER_USDC = MICRO_PER_USDC;
|
|
4244
4484
|
exports.MissingFieldError = MissingFieldError;
|
|
4245
4485
|
exports.NothingToWithdrawError = NothingToWithdrawError;
|
|
@@ -4279,6 +4519,7 @@ exports.networkToCaip2 = networkToCaip2;
|
|
|
4279
4519
|
exports.parsePaymentRequirement = parsePaymentRequirement;
|
|
4280
4520
|
exports.parseUsdToMicro = parseUsdToMicro;
|
|
4281
4521
|
exports.prefixedId = prefixedId;
|
|
4522
|
+
exports.prepareSeriesLocal = prepareSeriesLocal;
|
|
4282
4523
|
exports.prepareStudioPoolLocal = prepareStudioPoolLocal;
|
|
4283
4524
|
exports.previewEscrowFee = previewEscrowFee;
|
|
4284
4525
|
exports.previewIapSplit = previewIapSplit;
|
package/dist/index.d.cts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
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-
|
|
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-
|
|
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-CdzI_iYO.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-CdzI_iYO.cjs';
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* Thin REST client for the Playmos service. Every SDK method that touches the
|
|
@@ -88,6 +88,8 @@ declare function buildEpochWithdrawCall(epochPrizePool: `0x${string}`): Call;
|
|
|
88
88
|
* `epochs.enter` — pay into whatever window the clock says is current; no open
|
|
89
89
|
* gate. `epochs.preparePool` / `registerPool` / `createPool` — studio wallet
|
|
90
90
|
* deploys the existing EpochPrizePool constructor; Playmos is feeSink only.
|
|
91
|
+
* `epochs.prepareSeries` — unsigned createSeries tx; studio EOA signs; Playmos
|
|
92
|
+
* never broadcasts (sdk#739).
|
|
91
93
|
* `epochs.settle` — secret key, operator wallet, broadcast + 202. Passes the
|
|
92
94
|
* roster through; does not build a hub roster (R7b).
|
|
93
95
|
* `epochs.claimableRefund` / `claimRefund` / `withdraw` — wallet-direct on
|
|
@@ -243,6 +245,44 @@ interface EpochEntry {
|
|
|
243
245
|
via: EpochReadVia;
|
|
244
246
|
mock?: true;
|
|
245
247
|
}
|
|
248
|
+
/** Locked 1% Playmos take on a studio series. Any other fee is refused before signable bytes. */
|
|
249
|
+
declare const LOCKED_SERIES_FEE_BPS = 100;
|
|
250
|
+
/** Default prize-bucket bps when the studio does not type a split (fee 100 + seed 2000 = 10000). */
|
|
251
|
+
declare const DEFAULT_SERIES_POOL_BPS = 7900;
|
|
252
|
+
/** Default next-window seed bps when the studio does not type a split. */
|
|
253
|
+
declare const DEFAULT_SERIES_SEED_BPS = 2000;
|
|
254
|
+
interface EpochPrepareSeriesInput {
|
|
255
|
+
epochPrizePool: `0x${string}`;
|
|
256
|
+
series: string;
|
|
257
|
+
epochDuration: number | string;
|
|
258
|
+
/** Integer micro-USDC. */
|
|
259
|
+
entry: number | string;
|
|
260
|
+
genesis?: number | string;
|
|
261
|
+
/** Must be 100 if set — the locked 1% Playmos take. */
|
|
262
|
+
feeBps?: number;
|
|
263
|
+
poolBps?: number;
|
|
264
|
+
seedBps?: number;
|
|
265
|
+
}
|
|
266
|
+
interface EpochPreparedSeries {
|
|
267
|
+
series: string;
|
|
268
|
+
epochPrizePool: `0x${string}`;
|
|
269
|
+
genesis: string;
|
|
270
|
+
epochDuration: string;
|
|
271
|
+
entry: string;
|
|
272
|
+
feeBps: 100;
|
|
273
|
+
poolBps: number;
|
|
274
|
+
seedBps: number;
|
|
275
|
+
unsignedTx: {
|
|
276
|
+
chainId: number;
|
|
277
|
+
to: `0x${string}`;
|
|
278
|
+
value: "0";
|
|
279
|
+
data: `0x${string}`;
|
|
280
|
+
};
|
|
281
|
+
/** Playmos never broadcasts. Studio EOA sends. */
|
|
282
|
+
broadcast: false;
|
|
283
|
+
via: EpochReadVia;
|
|
284
|
+
mock?: true;
|
|
285
|
+
}
|
|
246
286
|
interface EpochPreparePoolInput {
|
|
247
287
|
studioWallet: `0x${string}`;
|
|
248
288
|
/** Must equal the Playmos sink if set; any other address is refused before broadcast. */
|
|
@@ -531,6 +571,7 @@ interface EpochsApi {
|
|
|
531
571
|
prize(input: EpochPrizeInput): Promise<EpochPrize>;
|
|
532
572
|
get(input: EpochGetInput): Promise<EpochView>;
|
|
533
573
|
getSeries(input: EpochGetSeriesInput): Promise<EpochSeriesView>;
|
|
574
|
+
prepareSeries(input: EpochPrepareSeriesInput): Promise<EpochPreparedSeries>;
|
|
534
575
|
preparePool(input: EpochPreparePoolInput): Promise<EpochPreparedPool>;
|
|
535
576
|
registerPool(input: EpochRegisterPoolInput): Promise<EpochStudioPool>;
|
|
536
577
|
createPool(input: EpochCreatePoolInput): Promise<EpochStudioPool>;
|
|
@@ -603,6 +644,8 @@ interface EpochsDeps {
|
|
|
603
644
|
declare function derivedEpochId(genesis: bigint, epochDuration: bigint, at: bigint): bigint;
|
|
604
645
|
/** Settle payable is inherited seed + this epoch's pool (not outgoingSeed). */
|
|
605
646
|
declare function epochPayableMicro(incomingSeed: bigint, pool: bigint): bigint;
|
|
647
|
+
/** Same refuse-before-signable posture as preparePool's feeSink check. */
|
|
648
|
+
declare function prepareSeriesLocal(input: EpochPrepareSeriesInput, chainId: number): EpochPreparedSeries;
|
|
606
649
|
/** Client-side pin — same refusals as the service, so a bad sink never reaches broadcast. */
|
|
607
650
|
declare function prepareStudioPoolLocal(input: EpochPreparePoolInput, playmosFeeSink: `0x${string}`, token: `0x${string}`, playmosAddresses?: `0x${string}`[]): EpochPreparedPool;
|
|
608
651
|
/**
|
|
@@ -1593,4 +1636,4 @@ declare function ulid(seedTime?: number): string;
|
|
|
1593
1636
|
/** `${prefix}_${ulid()}` — e.g. `pay_01J…`, `entry_01J…`, `idem_01J…`. */
|
|
1594
1637
|
declare function prefixedId(prefix: string): string;
|
|
1595
1638
|
|
|
1596
|
-
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, RETIRED_PLAYMOS_FEE_SINK, 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 };
|
|
1639
|
+
export { ActiveSeriesRound, AgentFundResult, AgentWallet, type Authorization, C1_ENTER_SPLIT_MICRO, CHAIN_ID, CancelRoundResult, type CreatePaymentRequirementInput, DEFAULT_API_BASE_URL, DEFAULT_SERIES_POOL_BPS, DEFAULT_SERIES_SEED_BPS, 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 EpochPrepareSeriesInput, type EpochPreparedPool, type EpochPreparedSeries, 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, LOCKED_SERIES_FEE_BPS, 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, RETIRED_PLAYMOS_FEE_SINK, 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, prepareSeriesLocal, prepareStudioPoolLocal, previewEscrowFee, previewIapSplit, previewMarketplaceSplit, previewPoolSplit, previewTransferSplit, resolveEnv, serializePaymentRequirement, seriesToBytes32, settlementTypedData, toX402PaymentRequired, ulid, validateX402ChallengeInput };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
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-
|
|
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-
|
|
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-CdzI_iYO.js';
|
|
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-CdzI_iYO.js';
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* Thin REST client for the Playmos service. Every SDK method that touches the
|
|
@@ -88,6 +88,8 @@ declare function buildEpochWithdrawCall(epochPrizePool: `0x${string}`): Call;
|
|
|
88
88
|
* `epochs.enter` — pay into whatever window the clock says is current; no open
|
|
89
89
|
* gate. `epochs.preparePool` / `registerPool` / `createPool` — studio wallet
|
|
90
90
|
* deploys the existing EpochPrizePool constructor; Playmos is feeSink only.
|
|
91
|
+
* `epochs.prepareSeries` — unsigned createSeries tx; studio EOA signs; Playmos
|
|
92
|
+
* never broadcasts (sdk#739).
|
|
91
93
|
* `epochs.settle` — secret key, operator wallet, broadcast + 202. Passes the
|
|
92
94
|
* roster through; does not build a hub roster (R7b).
|
|
93
95
|
* `epochs.claimableRefund` / `claimRefund` / `withdraw` — wallet-direct on
|
|
@@ -243,6 +245,44 @@ interface EpochEntry {
|
|
|
243
245
|
via: EpochReadVia;
|
|
244
246
|
mock?: true;
|
|
245
247
|
}
|
|
248
|
+
/** Locked 1% Playmos take on a studio series. Any other fee is refused before signable bytes. */
|
|
249
|
+
declare const LOCKED_SERIES_FEE_BPS = 100;
|
|
250
|
+
/** Default prize-bucket bps when the studio does not type a split (fee 100 + seed 2000 = 10000). */
|
|
251
|
+
declare const DEFAULT_SERIES_POOL_BPS = 7900;
|
|
252
|
+
/** Default next-window seed bps when the studio does not type a split. */
|
|
253
|
+
declare const DEFAULT_SERIES_SEED_BPS = 2000;
|
|
254
|
+
interface EpochPrepareSeriesInput {
|
|
255
|
+
epochPrizePool: `0x${string}`;
|
|
256
|
+
series: string;
|
|
257
|
+
epochDuration: number | string;
|
|
258
|
+
/** Integer micro-USDC. */
|
|
259
|
+
entry: number | string;
|
|
260
|
+
genesis?: number | string;
|
|
261
|
+
/** Must be 100 if set — the locked 1% Playmos take. */
|
|
262
|
+
feeBps?: number;
|
|
263
|
+
poolBps?: number;
|
|
264
|
+
seedBps?: number;
|
|
265
|
+
}
|
|
266
|
+
interface EpochPreparedSeries {
|
|
267
|
+
series: string;
|
|
268
|
+
epochPrizePool: `0x${string}`;
|
|
269
|
+
genesis: string;
|
|
270
|
+
epochDuration: string;
|
|
271
|
+
entry: string;
|
|
272
|
+
feeBps: 100;
|
|
273
|
+
poolBps: number;
|
|
274
|
+
seedBps: number;
|
|
275
|
+
unsignedTx: {
|
|
276
|
+
chainId: number;
|
|
277
|
+
to: `0x${string}`;
|
|
278
|
+
value: "0";
|
|
279
|
+
data: `0x${string}`;
|
|
280
|
+
};
|
|
281
|
+
/** Playmos never broadcasts. Studio EOA sends. */
|
|
282
|
+
broadcast: false;
|
|
283
|
+
via: EpochReadVia;
|
|
284
|
+
mock?: true;
|
|
285
|
+
}
|
|
246
286
|
interface EpochPreparePoolInput {
|
|
247
287
|
studioWallet: `0x${string}`;
|
|
248
288
|
/** Must equal the Playmos sink if set; any other address is refused before broadcast. */
|
|
@@ -531,6 +571,7 @@ interface EpochsApi {
|
|
|
531
571
|
prize(input: EpochPrizeInput): Promise<EpochPrize>;
|
|
532
572
|
get(input: EpochGetInput): Promise<EpochView>;
|
|
533
573
|
getSeries(input: EpochGetSeriesInput): Promise<EpochSeriesView>;
|
|
574
|
+
prepareSeries(input: EpochPrepareSeriesInput): Promise<EpochPreparedSeries>;
|
|
534
575
|
preparePool(input: EpochPreparePoolInput): Promise<EpochPreparedPool>;
|
|
535
576
|
registerPool(input: EpochRegisterPoolInput): Promise<EpochStudioPool>;
|
|
536
577
|
createPool(input: EpochCreatePoolInput): Promise<EpochStudioPool>;
|
|
@@ -603,6 +644,8 @@ interface EpochsDeps {
|
|
|
603
644
|
declare function derivedEpochId(genesis: bigint, epochDuration: bigint, at: bigint): bigint;
|
|
604
645
|
/** Settle payable is inherited seed + this epoch's pool (not outgoingSeed). */
|
|
605
646
|
declare function epochPayableMicro(incomingSeed: bigint, pool: bigint): bigint;
|
|
647
|
+
/** Same refuse-before-signable posture as preparePool's feeSink check. */
|
|
648
|
+
declare function prepareSeriesLocal(input: EpochPrepareSeriesInput, chainId: number): EpochPreparedSeries;
|
|
606
649
|
/** Client-side pin — same refusals as the service, so a bad sink never reaches broadcast. */
|
|
607
650
|
declare function prepareStudioPoolLocal(input: EpochPreparePoolInput, playmosFeeSink: `0x${string}`, token: `0x${string}`, playmosAddresses?: `0x${string}`[]): EpochPreparedPool;
|
|
608
651
|
/**
|
|
@@ -1593,4 +1636,4 @@ declare function ulid(seedTime?: number): string;
|
|
|
1593
1636
|
/** `${prefix}_${ulid()}` — e.g. `pay_01J…`, `entry_01J…`, `idem_01J…`. */
|
|
1594
1637
|
declare function prefixedId(prefix: string): string;
|
|
1595
1638
|
|
|
1596
|
-
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, RETIRED_PLAYMOS_FEE_SINK, 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 };
|
|
1639
|
+
export { ActiveSeriesRound, AgentFundResult, AgentWallet, type Authorization, C1_ENTER_SPLIT_MICRO, CHAIN_ID, CancelRoundResult, type CreatePaymentRequirementInput, DEFAULT_API_BASE_URL, DEFAULT_SERIES_POOL_BPS, DEFAULT_SERIES_SEED_BPS, 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 EpochPrepareSeriesInput, type EpochPreparedPool, type EpochPreparedSeries, 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, LOCKED_SERIES_FEE_BPS, 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, RETIRED_PLAYMOS_FEE_SINK, 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, prepareSeriesLocal, prepareStudioPoolLocal, previewEscrowFee, previewIapSplit, previewMarketplaceSplit, previewPoolSplit, previewTransferSplit, resolveEnv, serializePaymentRequirement, seriesToBytes32, settlementTypedData, toX402PaymentRequired, ulid, validateX402ChallengeInput };
|
package/dist/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { AuthError, InvalidAmountError, epochPrizePoolEnterAbi, seriesToBytes32, identityToBytes32, encodeApprove, epochPrizePoolRefundAbi, ConfigError, MissingFieldError, buildEpochExecuteSettlementCall, PaymentFailedError, epochPrizePoolViewAbi, ApiError, assertEnoughGas, sendCalls, waitForCalls, NothingToWithdrawError, buildWithdrawCall, WalletTimeoutError, buildIapCalls, buildEntryCalls, prizePoolAbi, WalletConnectionError, AlreadyEnteredError } from './chunk-
|
|
2
|
-
export { AlreadyEnteredError, ApiError, AuthError, ConfigError, InsufficientGasError, InvalidAmountError, MissingFieldError, NothingToWithdrawError, PaymentFailedError, PlaymosError, WalletConnectionError, WalletTimeoutError, buildEpochExecuteSettlementCall, identityToBytes32, seriesToBytes32 } from './chunk-
|
|
1
|
+
import { AuthError, InvalidAmountError, epochPrizePoolEnterAbi, seriesToBytes32, identityToBytes32, encodeApprove, epochPrizePoolRefundAbi, ConfigError, epochPrizePoolCreateSeriesAbi, MissingFieldError, buildEpochExecuteSettlementCall, PaymentFailedError, epochPrizePoolViewAbi, ApiError, assertEnoughGas, sendCalls, waitForCalls, NothingToWithdrawError, buildWithdrawCall, WalletTimeoutError, buildIapCalls, buildEntryCalls, prizePoolAbi, WalletConnectionError, AlreadyEnteredError } from './chunk-U6BPSEKC.js';
|
|
2
|
+
export { AlreadyEnteredError, ApiError, AuthError, ConfigError, InsufficientGasError, InvalidAmountError, MissingFieldError, NothingToWithdrawError, PaymentFailedError, PlaymosError, WalletConnectionError, WalletTimeoutError, buildEpochExecuteSettlementCall, identityToBytes32, seriesToBytes32 } from './chunk-U6BPSEKC.js';
|
|
3
3
|
import { encodeFunctionData, encodeAbiParameters, decodeFunctionResult } from 'viem';
|
|
4
4
|
|
|
5
5
|
// src/config.ts
|
|
@@ -692,6 +692,9 @@ function encodeEpochPoolConstructorArgs(args) {
|
|
|
692
692
|
args.refundTimeout
|
|
693
693
|
]);
|
|
694
694
|
}
|
|
695
|
+
var LOCKED_SERIES_FEE_BPS = 100;
|
|
696
|
+
var DEFAULT_SERIES_POOL_BPS = 7900;
|
|
697
|
+
var DEFAULT_SERIES_SEED_BPS = 2e3;
|
|
695
698
|
function derivedEpochId(genesis, epochDuration, at) {
|
|
696
699
|
if (epochDuration === 0n) {
|
|
697
700
|
throw new ConfigError("epochDuration must be > 0");
|
|
@@ -860,6 +863,66 @@ function walletStatus(status) {
|
|
|
860
863
|
function sameAddr(a, b) {
|
|
861
864
|
return a.toLowerCase() === b.toLowerCase();
|
|
862
865
|
}
|
|
866
|
+
function parseSeriesBps(raw, field) {
|
|
867
|
+
if (raw === void 0) return void 0;
|
|
868
|
+
if (!Number.isInteger(raw) || raw < 0) {
|
|
869
|
+
throw new ConfigError(`${field} must be a non-negative integer`);
|
|
870
|
+
}
|
|
871
|
+
return raw;
|
|
872
|
+
}
|
|
873
|
+
function prepareSeriesLocal(input, chainId) {
|
|
874
|
+
const pool = requireAddr(input.epochPrizePool, "epochPrizePool");
|
|
875
|
+
const series = requireSeries(input.series);
|
|
876
|
+
const feeBps = parseSeriesBps(input.feeBps, "feeBps");
|
|
877
|
+
if (feeBps !== void 0 && feeBps !== LOCKED_SERIES_FEE_BPS) {
|
|
878
|
+
throw new ConfigError(
|
|
879
|
+
"feeBps must be 100 (the locked 1% Playmos take); refused before anything signable"
|
|
880
|
+
);
|
|
881
|
+
}
|
|
882
|
+
const poolBps = parseSeriesBps(input.poolBps, "poolBps") ?? DEFAULT_SERIES_POOL_BPS;
|
|
883
|
+
const seedBps = parseSeriesBps(input.seedBps, "seedBps") ?? DEFAULT_SERIES_SEED_BPS;
|
|
884
|
+
if (LOCKED_SERIES_FEE_BPS + poolBps + seedBps !== 1e4) {
|
|
885
|
+
throw new ConfigError("feeBps + poolBps + seedBps must sum to 10000 (fee is 100)");
|
|
886
|
+
}
|
|
887
|
+
const epochDuration = toBig(input.epochDuration, 0n);
|
|
888
|
+
const entry = toBig(input.entry, 0n);
|
|
889
|
+
if (epochDuration <= 0n) throw new ConfigError("epochDuration must be greater than 0");
|
|
890
|
+
if (entry <= 0n) throw new ConfigError("entry must be greater than 0");
|
|
891
|
+
const genesis = toBig(input.genesis, BigInt(Math.floor(Date.now() / 1e3)));
|
|
892
|
+
if (genesis <= 0n) throw new ConfigError("genesis must be greater than 0");
|
|
893
|
+
const data = encodeFunctionData({
|
|
894
|
+
abi: epochPrizePoolCreateSeriesAbi,
|
|
895
|
+
functionName: "createSeries",
|
|
896
|
+
args: [
|
|
897
|
+
seriesToBytes32(series),
|
|
898
|
+
genesis,
|
|
899
|
+
epochDuration,
|
|
900
|
+
entry,
|
|
901
|
+
LOCKED_SERIES_FEE_BPS,
|
|
902
|
+
poolBps,
|
|
903
|
+
seedBps
|
|
904
|
+
]
|
|
905
|
+
});
|
|
906
|
+
return {
|
|
907
|
+
series,
|
|
908
|
+
epochPrizePool: pool,
|
|
909
|
+
genesis: genesis.toString(),
|
|
910
|
+
epochDuration: epochDuration.toString(),
|
|
911
|
+
entry: entry.toString(),
|
|
912
|
+
feeBps: 100,
|
|
913
|
+
poolBps,
|
|
914
|
+
seedBps,
|
|
915
|
+
unsignedTx: {
|
|
916
|
+
chainId,
|
|
917
|
+
to: pool,
|
|
918
|
+
value: "0",
|
|
919
|
+
data
|
|
920
|
+
},
|
|
921
|
+
broadcast: false,
|
|
922
|
+
via: "mock",
|
|
923
|
+
mock: true
|
|
924
|
+
};
|
|
925
|
+
}
|
|
863
926
|
function prepareStudioPoolLocal(input, playmosFeeSink, token, playmosAddresses = []) {
|
|
864
927
|
const studio = requireAddr(input.studioWallet, "studioWallet");
|
|
865
928
|
const locked = PLAYMOS_FEE_SINK_DEFAULT;
|
|
@@ -1008,6 +1071,7 @@ async function readEpochTerminal(deps, pool, series, epochId) {
|
|
|
1008
1071
|
}
|
|
1009
1072
|
}
|
|
1010
1073
|
function createEpochsApi(deps) {
|
|
1074
|
+
const mockPreparedSeries = /* @__PURE__ */ new Map();
|
|
1011
1075
|
return {
|
|
1012
1076
|
async currentId(input) {
|
|
1013
1077
|
const series = requireSeries(input?.series);
|
|
@@ -1085,6 +1149,9 @@ function createEpochsApi(deps) {
|
|
|
1085
1149
|
const series = requireSeries(input?.series);
|
|
1086
1150
|
const cfg = deps.config();
|
|
1087
1151
|
if (cfg.mock) {
|
|
1152
|
+
const pool = (input.epochPrizePool ?? cfg.contracts?.epochPrizePool ?? "").toLowerCase();
|
|
1153
|
+
const prepared = mockPreparedSeries.get(`${pool}:${series}`);
|
|
1154
|
+
if (prepared) return prepared;
|
|
1088
1155
|
return {
|
|
1089
1156
|
series,
|
|
1090
1157
|
created: true,
|
|
@@ -1105,6 +1172,42 @@ function createEpochsApi(deps) {
|
|
|
1105
1172
|
})}`;
|
|
1106
1173
|
return deps.http().get(path);
|
|
1107
1174
|
},
|
|
1175
|
+
async prepareSeries(input) {
|
|
1176
|
+
const feeBps = input?.feeBps;
|
|
1177
|
+
if (feeBps !== void 0 && feeBps !== LOCKED_SERIES_FEE_BPS) {
|
|
1178
|
+
throw new ConfigError(
|
|
1179
|
+
"feeBps must be 100 (the locked 1% Playmos take); refused before anything signable"
|
|
1180
|
+
);
|
|
1181
|
+
}
|
|
1182
|
+
const cfg = deps.config();
|
|
1183
|
+
if (cfg.mock) {
|
|
1184
|
+
const prepared = prepareSeriesLocal(input, CHAIN_ID["base-sepolia"]);
|
|
1185
|
+
mockPreparedSeries.set(`${prepared.epochPrizePool}:${prepared.series}`, {
|
|
1186
|
+
series: prepared.series,
|
|
1187
|
+
created: true,
|
|
1188
|
+
genesis: prepared.genesis,
|
|
1189
|
+
epochDuration: prepared.epochDuration,
|
|
1190
|
+
entry: prepared.entry,
|
|
1191
|
+
feeBps: prepared.feeBps,
|
|
1192
|
+
poolBps: prepared.poolBps,
|
|
1193
|
+
seedBps: prepared.seedBps,
|
|
1194
|
+
via: "mock",
|
|
1195
|
+
epochPrizePool: prepared.epochPrizePool,
|
|
1196
|
+
mock: true
|
|
1197
|
+
});
|
|
1198
|
+
return prepared;
|
|
1199
|
+
}
|
|
1200
|
+
return deps.http().post("/epochs/series/prepare", {
|
|
1201
|
+
epochPrizePool: requireAddr(input?.epochPrizePool, "epochPrizePool"),
|
|
1202
|
+
series: requireSeries(input?.series),
|
|
1203
|
+
epochDuration: input.epochDuration,
|
|
1204
|
+
entry: input.entry,
|
|
1205
|
+
genesis: input.genesis,
|
|
1206
|
+
feeBps: input.feeBps,
|
|
1207
|
+
poolBps: input.poolBps,
|
|
1208
|
+
seedBps: input.seedBps
|
|
1209
|
+
});
|
|
1210
|
+
},
|
|
1108
1211
|
async preparePool(input) {
|
|
1109
1212
|
const studioWallet = requireAddr(input?.studioWallet, "studioWallet");
|
|
1110
1213
|
const cfg = deps.config();
|
|
@@ -3787,4 +3890,4 @@ function isX402PayloadAuthorization(auth) {
|
|
|
3787
3890
|
return auth.kind === "x402-payload";
|
|
3788
3891
|
}
|
|
3789
3892
|
|
|
3790
|
-
export { C1_ENTER_SPLIT_MICRO, CHAIN_ID, DEFAULT_API_BASE_URL, MICRO_PER_USDC, PLAYMOS_FEE_SINK_DEFAULT, PayoutError, Playmos, RETIRED_PLAYMOS_FEE_SINK, USDC_ADDRESS, USDC_DECIMALS, buildEpochClaimRefundCall, buildEpochEntryCalls, buildEpochWithdrawCall, clientRuntimeSignals, computeIapSplit, computePayout, computePoolSplit, createEpochsApi, createPaymentRequirement, createX402Challenge, decodePaymentHeader, derivedEpochId, encodeEpochPoolConstructorArgs, encodePaymentHeader, epochPayableMicro, epochPoolProofMessage, formatMicroToUsd, isClientRuntime, isWalletSignatureAuthorization, isX402PayloadAuthorization, networkToCaip2, parsePaymentRequirement, parseUsdToMicro, prefixedId, prepareStudioPoolLocal, previewEscrowFee, previewIapSplit, previewMarketplaceSplit, previewPoolSplit, previewTransferSplit, resolveEnv, serializePaymentRequirement, settlementTypedData, toX402PaymentRequired, ulid, validateX402ChallengeInput };
|
|
3893
|
+
export { C1_ENTER_SPLIT_MICRO, CHAIN_ID, DEFAULT_API_BASE_URL, DEFAULT_SERIES_POOL_BPS, DEFAULT_SERIES_SEED_BPS, LOCKED_SERIES_FEE_BPS, MICRO_PER_USDC, PLAYMOS_FEE_SINK_DEFAULT, PayoutError, Playmos, RETIRED_PLAYMOS_FEE_SINK, USDC_ADDRESS, USDC_DECIMALS, buildEpochClaimRefundCall, buildEpochEntryCalls, buildEpochWithdrawCall, clientRuntimeSignals, computeIapSplit, computePayout, computePoolSplit, createEpochsApi, createPaymentRequirement, createX402Challenge, decodePaymentHeader, derivedEpochId, encodeEpochPoolConstructorArgs, encodePaymentHeader, epochPayableMicro, epochPoolProofMessage, formatMicroToUsd, isClientRuntime, isWalletSignatureAuthorization, isX402PayloadAuthorization, networkToCaip2, parsePaymentRequirement, parseUsdToMicro, prefixedId, prepareSeriesLocal, prepareStudioPoolLocal, previewEscrowFee, previewIapSplit, previewMarketplaceSplit, previewPoolSplit, previewTransferSplit, resolveEnv, serializePaymentRequirement, settlementTypedData, toX402PaymentRequired, ulid, validateX402ChallengeInput };
|
package/dist/server.d.cts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { a2 as PlaymosError, W as WebhookEvent } from './errors-
|
|
2
|
-
export { ad as enterPathToBytes32 } from './errors-
|
|
1
|
+
import { a2 as PlaymosError, W as WebhookEvent } from './errors-CdzI_iYO.cjs';
|
|
2
|
+
export { ad as enterPathToBytes32 } from './errors-CdzI_iYO.cjs';
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* Webhook signature verification (spec §6.2) — server-side only.
|
package/dist/server.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { a2 as PlaymosError, W as WebhookEvent } from './errors-
|
|
2
|
-
export { ad as enterPathToBytes32 } from './errors-
|
|
1
|
+
import { a2 as PlaymosError, W as WebhookEvent } from './errors-CdzI_iYO.js';
|
|
2
|
+
export { ad as enterPathToBytes32 } from './errors-CdzI_iYO.js';
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* Webhook signature verification (spec §6.2) — server-side only.
|
package/dist/server.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { PlaymosError, ApiError, toBytes32 } from './chunk-
|
|
2
|
-
export { toBytes32 as enterPathToBytes32 } from './chunk-
|
|
1
|
+
import { PlaymosError, ApiError, toBytes32 } from './chunk-U6BPSEKC.js';
|
|
2
|
+
export { toBytes32 as enterPathToBytes32 } from './chunk-U6BPSEKC.js';
|
|
3
3
|
import { timingSafeEqual, createHmac } from 'crypto';
|
|
4
4
|
import { encodeFunctionData, decodeFunctionResult } from 'viem';
|
|
5
5
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@playmos/sdk",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.16",
|
|
4
4
|
"description": "Playmos SDK — stablecoin payments for games on Base. IAP and skill contests are flat 1%. USD in, USDC on-chain, no crypto UX for players.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"private": false,
|