@playmos/sdk 0.1.4 → 0.1.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +86 -0
- package/dist/chunk-B7SHFZYY.js +62 -0
- package/dist/chunk-B7SHFZYY.js.map +1 -0
- package/dist/errors-B-85VYMv.d.cts +224 -0
- package/dist/errors-B-85VYMv.d.ts +224 -0
- package/dist/index.cjs +11 -45
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +9 -248
- package/dist/index.d.ts +9 -248
- package/dist/index.js +14 -103
- package/dist/index.js.map +1 -1
- package/dist/server.cjs +63 -0
- package/dist/server.cjs.map +1 -0
- package/dist/server.d.cts +26 -0
- package/dist/server.d.ts +26 -0
- package/dist/server.js +47 -0
- package/dist/server.js.map +1 -0
- package/package.json +6 -1
package/dist/index.cjs
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
var viem = require('viem');
|
|
4
|
-
var crypto = require('crypto');
|
|
5
4
|
|
|
6
5
|
// src/errors.ts
|
|
7
6
|
var PlaymosError = class extends Error {
|
|
@@ -513,46 +512,6 @@ function mockEntryPayment(args) {
|
|
|
513
512
|
mock: true
|
|
514
513
|
};
|
|
515
514
|
}
|
|
516
|
-
var WebhookSignatureError = class extends PlaymosError {
|
|
517
|
-
constructor(message) {
|
|
518
|
-
super("api_error", `Webhook signature verification failed: ${message}`);
|
|
519
|
-
}
|
|
520
|
-
};
|
|
521
|
-
function parseHeader(header) {
|
|
522
|
-
const parts = Object.fromEntries(
|
|
523
|
-
header.split(",").map((kv) => {
|
|
524
|
-
const [k, v] = kv.split("=");
|
|
525
|
-
return [k?.trim(), v?.trim()];
|
|
526
|
-
})
|
|
527
|
-
);
|
|
528
|
-
const t = Number(parts["t"]);
|
|
529
|
-
const v1 = parts["v1"];
|
|
530
|
-
if (!Number.isFinite(t) || !v1) throw new WebhookSignatureError("malformed signature header");
|
|
531
|
-
return { t, v1 };
|
|
532
|
-
}
|
|
533
|
-
function computeSignature(secret, t, rawBody) {
|
|
534
|
-
return crypto.createHmac("sha256", secret).update(`${t}.${rawBody}`).digest("hex");
|
|
535
|
-
}
|
|
536
|
-
function verifyWebhook(rawBody, signatureHeader, secret, opts = {}) {
|
|
537
|
-
if (!signatureHeader || Array.isArray(signatureHeader)) {
|
|
538
|
-
throw new WebhookSignatureError("missing signature header");
|
|
539
|
-
}
|
|
540
|
-
if (!secret) throw new WebhookSignatureError("missing signing secret");
|
|
541
|
-
const body = typeof rawBody === "string" ? rawBody : rawBody.toString("utf8");
|
|
542
|
-
const { t, v1 } = parseHeader(signatureHeader);
|
|
543
|
-
const tolerance = opts.toleranceSeconds ?? 300;
|
|
544
|
-
const nowSec = Math.floor(Date.now() / 1e3);
|
|
545
|
-
if (Math.abs(nowSec - t) > tolerance) {
|
|
546
|
-
throw new WebhookSignatureError(`timestamp outside tolerance (${tolerance}s)`);
|
|
547
|
-
}
|
|
548
|
-
const expected = computeSignature(secret, t, body);
|
|
549
|
-
const a = Buffer.from(expected, "hex");
|
|
550
|
-
const b = Buffer.from(v1, "hex");
|
|
551
|
-
if (a.length !== b.length || !crypto.timingSafeEqual(a, b)) {
|
|
552
|
-
throw new WebhookSignatureError("signature mismatch");
|
|
553
|
-
}
|
|
554
|
-
return JSON.parse(body);
|
|
555
|
-
}
|
|
556
515
|
|
|
557
516
|
// src/client.ts
|
|
558
517
|
var IAP_FEE_BPS = 100;
|
|
@@ -562,8 +521,17 @@ var RAKE_BPS = 1e3;
|
|
|
562
521
|
var Playmos = class {
|
|
563
522
|
constructor(config) {
|
|
564
523
|
this.webhooks = {
|
|
565
|
-
/**
|
|
566
|
-
|
|
524
|
+
/**
|
|
525
|
+
* Webhook verification is server-only (it uses node:crypto) and no longer
|
|
526
|
+
* ships in the browser entry (issue #9). On a backend, import it directly:
|
|
527
|
+
* import { verifyWebhook } from "@playmos/sdk/server";
|
|
528
|
+
*/
|
|
529
|
+
verify: (_rawBody, _signatureHeader, _secret) => {
|
|
530
|
+
throw new ConfigError(
|
|
531
|
+
'playmos.webhooks.verify is server-only and no longer ships in the browser entry (issue #9). Use: import { verifyWebhook } from "@playmos/sdk/server"',
|
|
532
|
+
{ entry: "@playmos/sdk/server" }
|
|
533
|
+
);
|
|
534
|
+
}
|
|
567
535
|
};
|
|
568
536
|
this.payouts = {
|
|
569
537
|
/** Choose how the studio is paid: "usdc" (default) or "fiat" (Bridge). */
|
|
@@ -840,7 +808,6 @@ exports.PlaymosError = PlaymosError;
|
|
|
840
808
|
exports.USDC_ADDRESS = USDC_ADDRESS;
|
|
841
809
|
exports.USDC_DECIMALS = USDC_DECIMALS;
|
|
842
810
|
exports.WalletConnectionError = WalletConnectionError;
|
|
843
|
-
exports.WebhookSignatureError = WebhookSignatureError;
|
|
844
811
|
exports.computeIapSplit = computeIapSplit;
|
|
845
812
|
exports.computePoolSplit = computePoolSplit;
|
|
846
813
|
exports.formatMicroToUsd = formatMicroToUsd;
|
|
@@ -849,6 +816,5 @@ exports.prefixedId = prefixedId;
|
|
|
849
816
|
exports.previewIapSplit = previewIapSplit;
|
|
850
817
|
exports.previewPoolSplit = previewPoolSplit;
|
|
851
818
|
exports.ulid = ulid;
|
|
852
|
-
exports.verifyWebhook = verifyWebhook;
|
|
853
819
|
//# sourceMappingURL=index.cjs.map
|
|
854
820
|
//# sourceMappingURL=index.cjs.map
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/errors.ts","../src/config.ts","../src/ids.ts","../src/money.ts","../src/validation.ts","../src/http.ts","../src/wallet.ts","../src/chain/abis.ts","../src/chain/batch.ts","../src/chain/calls.ts","../src/mock.ts","../src/webhooks.ts","../src/client.ts"],"names":["numberToHex","encodeFunctionData","keccak256","toBytes","createHmac","timingSafeEqual","payment"],"mappings":"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","file":"index.cjs","sourcesContent":["/**\n * Typed, actionable errors — the Stripe bar (spec §11).\n *\n * Every error carries a stable machine-readable `code` and is thrown at the\n * EARLIEST possible layer: input errors fire client-side before any network or\n * chain call, so a studio never pays gas to discover a typo.\n */\n\nexport type PlaymosErrorCode =\n | \"invalid_amount\"\n | \"missing_field\"\n | \"insufficient_gas\"\n | \"wallet_connection\"\n | \"payment_failed\"\n | \"auth\"\n | \"api_error\"\n | \"config\";\n\nexport class PlaymosError extends Error {\n readonly code: PlaymosErrorCode;\n /** Optional machine context (e.g. the offending field, the http status). */\n readonly detail?: Record<string, unknown>;\n\n constructor(code: PlaymosErrorCode, message: string, detail?: Record<string, unknown>) {\n super(message);\n this.name = new.target.name;\n this.code = code;\n this.detail = detail;\n // Restore prototype chain for `instanceof` across transpile targets.\n Object.setPrototypeOf(this, new.target.prototype);\n }\n}\n\n/** amount ≤ 0, non-numeric, empty, or more than 2 decimal places. */\nexport class InvalidAmountError extends PlaymosError {\n constructor(amount: unknown) {\n super(\n \"invalid_amount\",\n `Invalid amount: ${JSON.stringify(amount)}. Provide a positive USD decimal string with at most 2 decimals, e.g. \"4.99\".`,\n { amount },\n );\n }\n}\n\n/** A required field (sku, playerId, gameId, roundId, agentId…) was empty. */\nexport class MissingFieldError extends PlaymosError {\n constructor(field: string) {\n super(\"missing_field\", `Missing required field: \"${field}\".`, { field });\n }\n}\n\n/** gas mode \"player\" and the player's ETH is too low to cover gas (pre-check, §7). */\nexport class InsufficientGasError extends PlaymosError {\n constructor(detail?: Record<string, unknown>) {\n super(\n \"insufficient_gas\",\n \"The player's wallet has too little ETH to pay gas. Ask them to add a little ETH, or switch to gas.mode: \\\"sponsored\\\".\",\n detail,\n );\n }\n}\n\n/** The player closed or failed the wallet sheet, or no provider is available. */\nexport class WalletConnectionError extends PlaymosError {\n constructor(message = \"Could not connect the player's wallet.\", detail?: Record<string, unknown>) {\n super(\"wallet_connection\", message, detail);\n }\n}\n\n/** The on-chain settlement reverted, was cancelled, or timed out. */\nexport class PaymentFailedError extends PlaymosError {\n constructor(message = \"The on-chain payment did not complete.\", detail?: Record<string, unknown>) {\n super(\"payment_failed\", message, detail);\n }\n}\n\n/** Bad, missing, or wrong-environment API key (e.g. a pk_test_ key on a live route). */\nexport class AuthError extends PlaymosError {\n constructor(message = \"Invalid or missing API key.\", detail?: Record<string, unknown>) {\n super(\"auth\", message, detail);\n }\n}\n\n/** The Playmos service returned a non-2xx we don't have a more specific error for. */\nexport class ApiError extends PlaymosError {\n constructor(message: string, detail?: Record<string, unknown>) {\n super(\"api_error\", message, detail);\n }\n}\n\n/** SDK misconfiguration (e.g. a missing contract address for on-chain mode). */\nexport class ConfigError extends PlaymosError {\n constructor(message: string, detail?: Record<string, unknown>) {\n super(\"config\", message, detail);\n }\n}\n","/**\n * Environment resolution + the canonical address book.\n *\n * The API key prefix selects the environment (Stripe's ergonomic): pk_test_* →\n * Base Sepolia + the sandbox service; pk_live_* → Base mainnet + production. An\n * explicit `network` override always wins.\n */\n\nimport { AuthError } from \"./errors.js\";\nimport type { Network } from \"./types.js\";\n\nexport const CHAIN_ID: Record<Network, number> = {\n base: 8453,\n \"base-sepolia\": 84532,\n};\n\n/**\n * Circle USDC. Sepolia value fixes #336 (the vendored SDK shipped 0x0 here).\n * Verified against the game-hub deploy scripts + kit config.\n */\nexport const USDC_ADDRESS: Record<Network, `0x${string}`> = {\n base: \"0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913\",\n \"base-sepolia\": \"0x036CbD53842c5426634e7929541eC2318f3dCF7e\",\n};\n\nexport const DEFAULT_API_BASE_URL: Record<Network, string> = {\n base: \"https://api.playmos.io/v1\",\n \"base-sepolia\": \"https://api.sandbox.playmos.io/v1\",\n};\n\nexport interface ResolvedEnv {\n network: Network;\n chainId: number;\n apiBaseUrl: string;\n isTest: boolean;\n}\n\n/** Validate the key and resolve the environment it implies. */\nexport function resolveEnv(\n apiKey: string,\n networkOverride?: Network,\n apiBaseUrlOverride?: string,\n): ResolvedEnv {\n if (typeof apiKey !== \"string\" || apiKey.trim() === \"\") {\n throw new AuthError(\"Missing apiKey. Pass a pk_test_… or pk_live_… key.\");\n }\n const isTest = apiKey.startsWith(\"pk_test_\") || apiKey.startsWith(\"sk_test_\");\n const isLive = apiKey.startsWith(\"pk_live_\") || apiKey.startsWith(\"sk_live_\");\n if (!isTest && !isLive) {\n throw new AuthError(\n 'Malformed apiKey. Expected a \"pk_test_\", \"pk_live_\", \"sk_test_\", or \"sk_live_\" prefix.',\n { keyPreview: apiKey.slice(0, 8) },\n );\n }\n const network: Network = networkOverride ?? (isTest ? \"base-sepolia\" : \"base\");\n return {\n network,\n chainId: CHAIN_ID[network],\n apiBaseUrl: apiBaseUrlOverride ?? DEFAULT_API_BASE_URL[network],\n isTest,\n };\n}\n","/**\n * ULID generation (fixes #341/C — the `pay_mock_${Date.now()}` collision bug).\n *\n * A ULID is a 26-char Crockford-base32 string: 48 bits of millisecond timestamp\n * (lexicographically sortable) + 80 bits of cryptographic randomness. Within the\n * same millisecond we increment the random component monotonically, so even 50+\n * ids minted in a tight loop are unique and ordered. Uses Web Crypto\n * (`crypto.getRandomValues`), available in browsers and Node ≥ 18.\n */\n\nconst ENCODING = \"0123456789ABCDEFGHJKMNPQRSTVWXYZ\"; // Crockford base32 (no I,L,O,U)\nconst TIME_LEN = 10;\nconst RANDOM_LEN = 16;\n\nfunction getCrypto(): Crypto {\n const c = (globalThis as { crypto?: Crypto }).crypto;\n if (!c || typeof c.getRandomValues !== \"function\") {\n throw new Error(\"Web Crypto (crypto.getRandomValues) is not available in this runtime.\");\n }\n return c;\n}\n\nfunction encodeTime(now: number, len: number): string {\n let mod: number;\n let str = \"\";\n for (let i = len - 1; i >= 0; i--) {\n mod = now % 32;\n str = ENCODING[mod] + str;\n now = (now - mod) / 32;\n }\n return str;\n}\n\n// Monotonic state so ids minted in the same millisecond stay unique + ordered.\nlet lastTime = -1;\nlet lastRandom: number[] = [];\n\nfunction randomBytes(len: number): number[] {\n const bytes = new Uint8Array(len);\n getCrypto().getRandomValues(bytes);\n return Array.from(bytes, (b) => b % 32);\n}\n\nfunction incrementRandom(arr: number[]): number[] {\n const out = arr.slice();\n for (let i = out.length - 1; i >= 0; i--) {\n const v = out[i] ?? 0;\n if (v < 31) {\n out[i] = v + 1;\n return out;\n }\n out[i] = 0;\n }\n // Overflow (astronomically unlikely) — reseed.\n return randomBytes(out.length);\n}\n\n/** Generate a monotonic ULID (26 chars, uppercase Crockford base32). */\nexport function ulid(seedTime?: number): string {\n const now = seedTime ?? Date.now();\n let random: number[];\n if (now === lastTime) {\n random = incrementRandom(lastRandom);\n } else {\n random = randomBytes(RANDOM_LEN);\n }\n lastTime = now;\n lastRandom = random;\n return encodeTime(now, TIME_LEN) + random.map((r) => ENCODING[r]).join(\"\");\n}\n\n/** `${prefix}_${ulid()}` — e.g. `pay_01J…`, `entry_01J…`, `idem_01J…`. */\nexport function prefixedId(prefix: string): string {\n return `${prefix}_${ulid()}`;\n}\n","/**\n * Money math — exact, integer-only, in USDC micro-units (6 decimals).\n *\n * USD amounts are decimal strings (\"4.99\") to avoid float corruption. Internally\n * every value is a BigInt count of micro-USDC (1 USDC = 1_000_000 micro), so the\n * split is bit-exact and always sums back to the input — no wei is ever lost.\n *\n * The split arithmetic MIRRORS the contracts (floor division, exactly like\n * Solidity `amount * bps / 10000`), so the SDK receipt matches what settles\n * on-chain. The contract remains the source of truth; these numbers are the\n * faithful preview.\n */\n\nimport { InvalidAmountError } from \"./errors.js\";\n\nexport const USDC_DECIMALS = 6;\nexport const MICRO_PER_USDC = 1_000_000n;\n\nconst AMOUNT_RE = /^\\d+(\\.\\d{1,2})?$/;\n\n/**\n * Parse a USD decimal string (≤ 2 dp, > 0) into micro-USDC.\n * Throws {@link InvalidAmountError} on anything that isn't a clean positive price.\n */\nexport function parseUsdToMicro(amount: string): bigint {\n if (typeof amount !== \"string\" || amount.trim() === \"\" || !AMOUNT_RE.test(amount)) {\n throw new InvalidAmountError(amount);\n }\n const parts = amount.split(\".\");\n const whole = parts[0] ?? \"0\";\n const frac = parts[1] ?? \"\";\n const fracPadded = (frac + \"000000\").slice(0, USDC_DECIMALS);\n const micro = BigInt(whole) * MICRO_PER_USDC + BigInt(fracPadded);\n if (micro <= 0n) throw new InvalidAmountError(amount);\n return micro;\n}\n\n/**\n * Format micro-USDC back to a USD decimal string. Keeps full precision (up to 6\n * dp) but trims trailing zeros to a minimum of 2 dp — so \"$4.99\" stays \"4.99\"\n * while a 1% fee of $4.99 renders its exact \"0.0499\", not a lossy \"0.05\".\n */\nexport function formatMicroToUsd(micro: bigint): string {\n const neg = micro < 0n;\n const abs = neg ? -micro : micro;\n const whole = abs / MICRO_PER_USDC;\n const frac = abs % MICRO_PER_USDC;\n let fracStr = frac.toString().padStart(USDC_DECIMALS, \"0\").replace(/0+$/, \"\");\n if (fracStr.length < 2) fracStr = fracStr.padEnd(2, \"0\");\n return `${neg ? \"-\" : \"\"}${whole.toString()}.${fracStr}`;\n}\n\n/** External-studio IAP split (99/1 by default). Floor-matches `PlaymosPay.pay`. */\nexport function computeIapSplit(\n amountMicro: bigint,\n feeBps: number,\n): { feeMicro: bigint; netMicro: bigint } {\n const feeMicro = (amountMicro * BigInt(feeBps)) / 10_000n;\n const netMicro = amountMicro - feeMicro;\n return { feeMicro, netMicro };\n}\n\n/**\n * Skill-game prize-pool split (60/30/10 by default). Floor-matches the on-chain\n * `EconomyConfig`. Any 1–2 micro rounding remainder is assigned to the pool so\n * the three parts sum EXACTLY to the entry (invariant asserted below).\n */\nexport function computePoolSplit(\n amountMicro: bigint,\n poolBps: number,\n seedBps: number,\n rakeBps: number,\n): { poolMicro: bigint; seedMicro: bigint; rakeMicro: bigint } {\n if (poolBps + seedBps + rakeBps !== 10_000) {\n throw new Error(`pool/seed/rake bps must sum to 10000, got ${poolBps + seedBps + rakeBps}`);\n }\n const seedMicro = (amountMicro * BigInt(seedBps)) / 10_000n;\n const rakeMicro = (amountMicro * BigInt(rakeBps)) / 10_000n;\n const poolMicro = amountMicro - seedMicro - rakeMicro; // remainder → pool\n return { poolMicro, seedMicro, rakeMicro };\n}\n","/**\n * Client-side input validation (fixes #342/D — \"-1\", \"0\", \"abc\", \"\", 18-dp all\n * used to succeed). Every check throws a typed error BEFORE any network or chain\n * call, exactly like Stripe.\n */\n\nimport { InvalidAmountError, MissingFieldError } from \"./errors.js\";\nimport { parseUsdToMicro } from \"./money.js\";\n\n/**\n * Validate a USD amount string and return its micro-USDC value.\n * Rejects: empty, non-numeric, ≤ 0, or more than 2 decimal places.\n */\nexport function validateAmount(amount: unknown): bigint {\n if (typeof amount !== \"string\") throw new InvalidAmountError(amount);\n return parseUsdToMicro(amount); // throws InvalidAmountError on bad format / ≤ 0\n}\n\n/** Require a non-empty, trimmed string field. */\nexport function requireField(value: unknown, field: string): string {\n if (typeof value !== \"string\" || value.trim() === \"\") {\n throw new MissingFieldError(field);\n }\n return value;\n}\n\n/** Metadata guard: at most 20 string→string entries (per docs §3). */\nexport function validateMetadata(metadata: unknown): Record<string, string> | undefined {\n if (metadata == null) return undefined;\n if (typeof metadata !== \"object\" || Array.isArray(metadata)) {\n throw new MissingFieldError(\"metadata (must be an object of string values)\");\n }\n const entries = Object.entries(metadata as Record<string, unknown>);\n if (entries.length > 20) {\n throw new InvalidAmountError(`metadata: at most 20 keys allowed, got ${entries.length}`);\n }\n const out: Record<string, string> = {};\n for (const [k, v] of entries) {\n if (typeof v !== \"string\") {\n throw new MissingFieldError(`metadata.${k} (values must be strings)`);\n }\n out[k] = v;\n }\n return out;\n}\n","/**\n * Thin REST client for the Playmos service. Every SDK method that touches the\n * backend (create intent, verify, payouts, agents) goes through here. `verify()`\n * hits `GET /payments/:id`, which the service resolves by READING THE CHAIN — so\n * the SDK never trusts a client claim or a mutable counter (#337 root fix).\n */\n\nimport { ApiError, AuthError } from \"./errors.js\";\n\nexport interface HttpClient {\n post<T>(path: string, body: unknown, opts?: { idempotencyKey?: string }): Promise<T>;\n get<T>(path: string): Promise<T>;\n}\n\nexport function createHttpClient(baseUrl: string, apiKey: string): HttpClient {\n const base = baseUrl.replace(/\\/+$/, \"\");\n\n /**\n * Run the request, converting a TRANSPORT failure (DNS/NXDOMAIN, connection\n * refused, TLS, abort/timeout — i.e. `fetch()` itself throws) into a typed,\n * actionable `ApiError`. HTTP error *responses* (non-2xx) are NOT caught here;\n * they flow through `handle()` unchanged. `detail.cause` carries the underlying\n * error; `detail.transport: true` distinguishes this from a status failure.\n */\n async function send(url: string, init: RequestInit): Promise<Response> {\n try {\n return await fetch(url, init);\n } catch (err) {\n const cause = err instanceof Error ? err.message : String(err);\n throw new ApiError(\n `Could not reach the Playmos API at ${url} (network error: ${cause}). Check the service is running and apiBaseUrl is correct.`,\n { url, cause, transport: true },\n );\n }\n }\n\n async function handle<T>(res: Response): Promise<T> {\n let text: string;\n try {\n text = await res.text();\n } catch (err) {\n const cause = err instanceof Error ? err.message : String(err);\n throw new ApiError(\n `Could not read the response from the Playmos API at ${res.url} (network error: ${cause}). Check the service is running and apiBaseUrl is correct.`,\n { url: res.url, cause, transport: true },\n );\n }\n let json: unknown;\n try {\n json = text ? JSON.parse(text) : {};\n } catch {\n throw new ApiError(`Non-JSON response (${res.status}) from ${res.url}`, { status: res.status, body: text });\n }\n if (res.ok) return json as T;\n const errBody = json as { error?: { code?: string; message?: string } };\n const message = errBody?.error?.message ?? `Request failed with ${res.status}`;\n if (res.status === 401 || res.status === 403 || errBody?.error?.code === \"auth\") {\n throw new AuthError(message, { status: res.status });\n }\n throw new ApiError(message, { status: res.status, code: errBody?.error?.code });\n }\n\n return {\n async post<T>(path: string, body: unknown, opts?: { idempotencyKey?: string }): Promise<T> {\n const headers: Record<string, string> = {\n \"content-type\": \"application/json\",\n authorization: `Bearer ${apiKey}`,\n };\n if (opts?.idempotencyKey) headers[\"idempotency-key\"] = opts.idempotencyKey;\n const res = await send(`${base}${path}`, { method: \"POST\", headers, body: JSON.stringify(body) });\n return handle<T>(res);\n },\n async get<T>(path: string): Promise<T> {\n const res = await send(`${base}${path}`, {\n method: \"GET\",\n headers: { authorization: `Bearer ${apiKey}` },\n });\n return handle<T>(res);\n },\n };\n}\n","/**\n * Wallet resolution — pruned to the two connectors V1 actually supports\n * (`base-account`, `injected`), fixing the old surface that advertised four and\n * silently no-op'd (#335/E).\n */\n\nimport { WalletConnectionError } from \"./errors.js\";\nimport type { Eip1193Provider, WalletConfig } from \"./types.js\";\n\ninterface WithEthereum {\n ethereum?: Eip1193Provider;\n}\n\n/**\n * Resolve an EIP-1193 provider from config. Precedence:\n * 1. an explicitly supplied `wallet.provider`\n * 2. `injected` → globalThis.ethereum (browser wallet)\n * 3. `base-account` → expects the Base Account SDK to have injected a provider;\n * the host app passes it via `wallet.provider` in headless/SSR contexts.\n */\nexport function resolveProvider(wallet?: WalletConfig): Eip1193Provider {\n if (wallet?.provider) return wallet.provider;\n\n const injected = (globalThis as WithEthereum).ethereum;\n const connector = wallet?.connector ?? \"base-account\";\n\n if (connector === \"injected\") {\n if (!injected) {\n throw new WalletConnectionError(\n \"No injected wallet found (globalThis.ethereum is undefined). Open in a wallet browser or pass wallet.provider.\",\n );\n }\n return injected;\n }\n\n // base-account: prefer an injected Base Account provider; otherwise instruct\n // the host to supply one. We do NOT hard-depend on the Base Account SDK so the\n // package stays light and server-safe.\n if (injected) return injected;\n throw new WalletConnectionError(\n \"base-account connector needs a provider. In the Base App it is injected automatically; \" +\n \"elsewhere, create one with @base-org/account and pass it as wallet.provider.\",\n );\n}\n\n/**\n * Is a real wallet actually available to sign for the player? Used by the\n * auto no-wallet routing (0.1.4): when this is false on a test/sandbox key, the\n * SDK routes to the service's server-settle path so the developer needs zero\n * wallet/crypto. Detection (mirrors {@link resolveProvider} precedence):\n * 1. an explicit `wallet.provider` counts as available (don't force a connect);\n * 2. otherwise a provider must resolve (config or globalThis.ethereum) AND we\n * must be able to actually read an account from it.\n * Never throws — any failure to resolve/connect means \"no wallet\".\n */\nexport async function walletAvailable(wallet?: WalletConfig): Promise<boolean> {\n // An explicitly-supplied provider is treated as available without forcing an\n // eth_requestAccounts round-trip (the host owns its own connect UX).\n if (wallet?.provider) return true;\n\n let provider: Eip1193Provider;\n try {\n provider = resolveProvider(wallet);\n } catch {\n return false; // no config.provider and no injectable globalThis.ethereum\n }\n try {\n await getAccount(provider);\n return true;\n } catch {\n return false; // provider present but no account could be resolved\n }\n}\n\n/** Read the connected account (first address). */\nexport async function getAccount(provider: Eip1193Provider): Promise<`0x${string}`> {\n try {\n const accounts = (await provider.request({ method: \"eth_requestAccounts\" })) as string[];\n const addr = accounts?.[0];\n if (!addr) throw new Error(\"no account\");\n return addr as `0x${string}`;\n } catch (e) {\n throw new WalletConnectionError(\"Could not read the player's wallet account.\", {\n cause: (e as { message?: string })?.message,\n });\n }\n}\n","/** Minimal viem const-typed ABIs for the on-chain calls the SDK builds. */\n\nexport const erc20Abi = [\n {\n type: \"function\",\n name: \"approve\",\n stateMutability: \"nonpayable\",\n inputs: [\n { name: \"spender\", type: \"address\" },\n { name: \"amount\", type: \"uint256\" },\n ],\n outputs: [{ type: \"bool\" }],\n },\n {\n type: \"function\",\n name: \"balanceOf\",\n stateMutability: \"view\",\n inputs: [{ name: \"account\", type: \"address\" }],\n outputs: [{ type: \"uint256\" }],\n },\n] as const;\n\n/** PlaymosPay — external-studio IAP, 99/1 atomic split. */\nexport const playmosPayAbi = [\n {\n type: \"function\",\n name: \"pay\",\n stateMutability: \"nonpayable\",\n inputs: [\n { name: \"paymentId\", type: \"bytes32\" },\n { name: \"studio\", type: \"address\" },\n { name: \"amount\", type: \"uint256\" },\n ],\n outputs: [],\n },\n] as const;\n\n/** PrizePool V2 — skill-game entry, 60/30/10. */\nexport const prizePoolAbi = [\n {\n type: \"function\",\n name: \"enter\",\n stateMutability: \"nonpayable\",\n inputs: [\n { name: \"roundId\", type: \"bytes32\" },\n { name: \"identity\", type: \"bytes32\" },\n ],\n outputs: [],\n },\n {\n type: \"function\",\n name: \"hasEntered\",\n stateMutability: \"view\",\n inputs: [\n { name: \"roundId\", type: \"bytes32\" },\n { name: \"identity\", type: \"bytes32\" },\n ],\n outputs: [{ type: \"bool\" }],\n },\n] as const;\n","/**\n * EIP-5792 batch primitives — ported from the proven game-hub `payEntryOnchain`\n * path (`OnchainEntry.ts`). One `wallet_sendCalls` sends `approve` + the settling\n * call as ONE atomic confirmation; the paymaster sponsors gas when configured.\n * The player sees a single Apple-Pay-style sheet.\n */\n\nimport { numberToHex } from \"viem\";\nimport { InsufficientGasError, PaymentFailedError, WalletConnectionError } from \"../errors.js\";\nimport { erc20Abi } from \"./abis.js\";\nimport { encodeFunctionData } from \"viem\";\nimport type { Eip1193Provider } from \"../types.js\";\n\nexport interface Call {\n to: `0x${string}`;\n data: `0x${string}`;\n}\n\nexport type OnchainStatus = \"PENDING\" | \"CONFIRMED\" | \"FAILED\";\n\n/**\n * Send an atomic approve+call batch via EIP-5792. Returns the calls id; poll\n * {@link waitForCalls} for the terminal status.\n */\nexport async function sendCalls(\n provider: Eip1193Provider,\n from: `0x${string}`,\n chainId: number,\n calls: Call[],\n paymasterUrl?: string,\n): Promise<{ id: string }> {\n const params: Record<string, unknown> = {\n version: \"2.0.0\",\n from,\n chainId: numberToHex(chainId),\n atomicRequired: true,\n calls,\n };\n if (paymasterUrl) {\n params.capabilities = { paymasterService: { url: paymasterUrl } };\n }\n\n let result: unknown;\n try {\n result = await provider.request({ method: \"wallet_sendCalls\", params: [params] });\n } catch (e) {\n const msg = (e as { message?: string })?.message ?? String(e);\n // A user rejection or closed sheet surfaces as a wallet-connection error.\n if (/reject|denied|cancel|closed/i.test(msg)) {\n throw new WalletConnectionError(\"The player cancelled or closed the payment sheet.\", { cause: msg });\n }\n throw new PaymentFailedError(\"wallet_sendCalls failed.\", { cause: msg });\n }\n // EIP-5792 evolved: newer wallets return `{ id }`, older ones a bare string.\n const id = typeof result === \"string\" ? result : ((result as { id?: string })?.id ?? \"\");\n if (!id) throw new PaymentFailedError(\"Wallet returned no calls id.\");\n return { id };\n}\n\n/** Poll EIP-5792 calls status until terminal or timeout, then map to our status. */\nexport async function waitForCalls(\n provider: Eip1193Provider,\n id: string,\n timeoutMs = 60_000,\n): Promise<{ status: OnchainStatus; txHash?: `0x${string}` }> {\n if (!id) return { status: \"FAILED\" };\n const deadline = Date.now() + timeoutMs;\n while (Date.now() < deadline) {\n const res = (await provider.request({\n method: \"wallet_getCallsStatus\",\n params: [id],\n })) as { status?: number | string; receipts?: { transactionHash?: `0x${string}` }[] } | null;\n const s = String(res?.status ?? \"\").toUpperCase();\n const txHash = res?.receipts?.[0]?.transactionHash;\n if (s === \"200\" || s === \"CONFIRMED\" || s === \"SUCCESS\") return { status: \"CONFIRMED\", txHash };\n if (s === \"400\" || s === \"500\" || s === \"FAILED\" || s === \"REVERTED\") return { status: \"FAILED\", txHash };\n await new Promise((r) => setTimeout(r, 900));\n }\n return { status: \"PENDING\" };\n}\n\n/** Encode an ERC-20 approve calldata. */\nexport function encodeApprove(spender: `0x${string}`, amountUnits: bigint): `0x${string}` {\n return encodeFunctionData({ abi: erc20Abi, functionName: \"approve\", args: [spender, amountUnits] });\n}\n\n/**\n * Low-ETH pre-check for `gas: \"player\"` (spec §7). Reads the player's native ETH\n * balance and throws {@link InsufficientGasError} BEFORE building a doomed tx.\n * Uses the wallet's own `eth_getBalance` so no separate RPC is needed.\n */\nexport async function assertEnoughGas(\n provider: Eip1193Provider,\n from: `0x${string}`,\n minWei = 200_000_000_000_000n, // ~0.0002 ETH — a comfortable Base gas floor\n): Promise<void> {\n let balance: bigint;\n try {\n const hex = (await provider.request({ method: \"eth_getBalance\", params: [from, \"latest\"] })) as string;\n balance = BigInt(hex);\n } catch {\n return; // If we can't read it, don't block — the tx will surface a real error.\n }\n if (balance < minWei) {\n throw new InsufficientGasError({ balanceWei: balance.toString(), minWei: minWei.toString() });\n }\n}\n","/**\n * Builders for the two settling calls. Both mirror the proven entry batch:\n * [approve(spender, amount), settle(...)] sent atomically via EIP-5792.\n */\n\nimport { encodeFunctionData, keccak256, toBytes } from \"viem\";\nimport { playmosPayAbi, prizePoolAbi } from \"./abis.js\";\nimport { encodeApprove, type Call } from \"./batch.js\";\n\n/** The server derives these identically (keccak256 of UTF-8 bytes) so the\n * off-chain record and the on-chain call line up. */\nexport const toBytes32 = (s: string): `0x${string}` => keccak256(toBytes(s));\n\n/** External-studio IAP: approve USDC → PlaymosPay, then PlaymosPay.pay(). */\nexport function buildIapCalls(args: {\n usdc: `0x${string}`;\n playmosPay: `0x${string}`;\n paymentId: string;\n studio: `0x${string}`;\n amountUnits: bigint;\n}): Call[] {\n const payData = encodeFunctionData({\n abi: playmosPayAbi,\n functionName: \"pay\",\n args: [toBytes32(args.paymentId), args.studio, args.amountUnits],\n });\n return [\n { to: args.usdc, data: encodeApprove(args.playmosPay, args.amountUnits) },\n { to: args.playmosPay, data: payData },\n ];\n}\n\n/** Skill-game entry: approve USDC → PrizePool, then PrizePool.enter(). */\nexport function buildEntryCalls(args: {\n usdc: `0x${string}`;\n prizePool: `0x${string}`;\n roundKey: string;\n identity: string;\n amountUnits: bigint;\n}): Call[] {\n const enterData = encodeFunctionData({\n abi: prizePoolAbi,\n functionName: \"enter\",\n args: [toBytes32(args.roundKey), toBytes32(args.identity)],\n });\n return [\n { to: args.usdc, data: encodeApprove(args.prizePool, args.amountUnits) },\n { to: args.prizePool, data: enterData },\n ];\n}\n","/**\n * The explicit, clearly-labeled offline unit-test helper (`new Playmos({ mock:true })`).\n *\n * Instant, deterministic, no network, no chain — for a studio's CI. Crucially it\n * is NOT the sandbox and NOT the default, and it never emits a synthetic\n * `\"mocked\"` status (the P0 finding #340). Mock results carry `mock: true` and\n * use the REAL status union, so test code exercises the same shape as production.\n */\n\nimport { computeIapSplit, computePoolSplit, formatMicroToUsd } from \"./money.js\";\nimport { prefixedId } from \"./ids.js\";\nimport type { Network, Payment } from \"./types.js\";\n\nconst MOCK_TX = \"0x000000000000000000000000000000000000000000000000000000000000mock\" as `0x${string}`;\n\nexport function mockIapPayment(args: {\n amountMicro: bigint;\n feeBps: number;\n sku: string;\n playerId: string;\n chain: Network;\n metadata?: Record<string, string>;\n}): Payment {\n const { feeMicro, netMicro } = computeIapSplit(args.amountMicro, args.feeBps);\n return {\n id: prefixedId(\"pay\"),\n status: \"confirmed\",\n kind: \"iap\",\n amount: formatMicroToUsd(args.amountMicro),\n fee: formatMicroToUsd(feeMicro),\n net: formatMicroToUsd(netMicro),\n sku: args.sku,\n playerId: args.playerId,\n txHash: MOCK_TX,\n chain: args.chain,\n createdAt: new Date().toISOString(),\n metadata: args.metadata,\n mock: true,\n };\n}\n\nexport function mockEntryPayment(args: {\n amountMicro: bigint;\n poolBps: number;\n seedBps: number;\n rakeBps: number;\n gameId: string;\n roundId: string;\n playerId: string;\n chain: Network;\n metadata?: Record<string, string>;\n}): Payment {\n const { poolMicro, seedMicro, rakeMicro } = computePoolSplit(\n args.amountMicro,\n args.poolBps,\n args.seedBps,\n args.rakeBps,\n );\n return {\n id: prefixedId(\"entry\"),\n status: \"confirmed\",\n kind: \"entry\",\n amount: formatMicroToUsd(args.amountMicro),\n fee: formatMicroToUsd(rakeMicro), // the 10% take\n net: formatMicroToUsd(poolMicro + seedMicro), // escrowed to the pool\n split: {\n pool: formatMicroToUsd(poolMicro),\n seed: formatMicroToUsd(seedMicro),\n rake: formatMicroToUsd(rakeMicro),\n },\n gameId: args.gameId,\n roundId: args.roundId,\n playerId: args.playerId,\n txHash: MOCK_TX,\n chain: args.chain,\n createdAt: new Date().toISOString(),\n metadata: args.metadata,\n mock: true,\n };\n}\n","/**\n * Webhook signature verification (spec §6.2) — server-side only.\n *\n * Signature scheme (mirrors the Playmos service byte-for-byte):\n * header `X-Playmos-Signature: t=<unixSeconds>,v1=<hex>`\n * where <hex> = HMAC_SHA256(secret, `${t}.${rawBody}`)\n *\n * Verify BEFORE trusting an event. Uses node:crypto (constant-time compare) and\n * rejects stale timestamps to blunt replay. Throws on any mismatch.\n */\n\nimport { createHmac, timingSafeEqual } from \"node:crypto\";\nimport { PlaymosError } from \"./errors.js\";\nimport type { WebhookEvent } from \"./types.js\";\n\nexport class WebhookSignatureError extends PlaymosError {\n constructor(message: string) {\n super(\"api_error\", `Webhook signature verification failed: ${message}`);\n }\n}\n\nfunction parseHeader(header: string): { t: number; v1: string } {\n const parts = Object.fromEntries(\n header.split(\",\").map((kv) => {\n const [k, v] = kv.split(\"=\");\n return [k?.trim(), v?.trim()];\n }),\n );\n const t = Number(parts[\"t\"]);\n const v1 = parts[\"v1\"];\n if (!Number.isFinite(t) || !v1) throw new WebhookSignatureError(\"malformed signature header\");\n return { t, v1 };\n}\n\nfunction computeSignature(secret: string, t: number, rawBody: string): string {\n return createHmac(\"sha256\", secret).update(`${t}.${rawBody}`).digest(\"hex\");\n}\n\n/**\n * Verify a webhook and return the parsed event. `rawBody` MUST be the exact raw\n * request bytes (use express.raw / fastify rawBody) — a re-serialized JSON body\n * will not match the signature.\n */\nexport function verifyWebhook(\n rawBody: string | Buffer,\n signatureHeader: string | string[] | undefined,\n secret: string,\n opts: { toleranceSeconds?: number } = {},\n): WebhookEvent {\n if (!signatureHeader || Array.isArray(signatureHeader)) {\n throw new WebhookSignatureError(\"missing signature header\");\n }\n if (!secret) throw new WebhookSignatureError(\"missing signing secret\");\n\n const body = typeof rawBody === \"string\" ? rawBody : rawBody.toString(\"utf8\");\n const { t, v1 } = parseHeader(signatureHeader);\n\n const tolerance = opts.toleranceSeconds ?? 300;\n const nowSec = Math.floor(Date.now() / 1000);\n if (Math.abs(nowSec - t) > tolerance) {\n throw new WebhookSignatureError(`timestamp outside tolerance (${tolerance}s)`);\n }\n\n const expected = computeSignature(secret, t, body);\n const a = Buffer.from(expected, \"hex\");\n const b = Buffer.from(v1, \"hex\");\n if (a.length !== b.length || !timingSafeEqual(a, b)) {\n throw new WebhookSignatureError(\"signature mismatch\");\n }\n\n return JSON.parse(body) as WebhookEvent;\n}\n","/**\n * The Playmos client — `new Playmos({ apiKey })` → `pay()`, `enterRound()`,\n * `verify()`, `webhooks`, `payouts`, `agents`.\n *\n * Real behavior, no `\"mocked\"` status anywhere. The chain calls use the proven\n * EIP-5792 approve+call batch; `verify()` resolves by the service's on-chain\n * read; ids are ULIDs; inputs are validated client-side; idempotency is honored.\n */\n\nimport { ConfigError } from \"./errors.js\";\nimport { resolveEnv, USDC_ADDRESS, type ResolvedEnv } from \"./config.js\";\nimport { prefixedId } from \"./ids.js\";\nimport { requireField, validateAmount, validateMetadata } from \"./validation.js\";\nimport { computeIapSplit, computePoolSplit, formatMicroToUsd } from \"./money.js\";\nimport { createHttpClient, type HttpClient } from \"./http.js\";\nimport { resolveProvider, getAccount, walletAvailable } from \"./wallet.js\";\nimport { assertEnoughGas, sendCalls, waitForCalls } from \"./chain/batch.js\";\nimport { buildIapCalls, buildEntryCalls } from \"./chain/calls.js\";\nimport { mockIapPayment, mockEntryPayment } from \"./mock.js\";\nimport { verifyWebhook } from \"./webhooks.js\";\nimport type {\n EnterRoundInput,\n Payment,\n PayInput,\n PlaymosConfig,\n VerifyResult,\n WebhookEvent,\n} from \"./types.js\";\n\n/** Fee tiers, keyed to who owns the game (spec §4). Contract-enforced on-chain;\n * these are the SDK's faithful preview of the split. */\nconst IAP_FEE_BPS = 100; // external studios → 1%\nconst POOL_BPS = 6000; // 60% this round's pool\nconst SEED_BPS = 3000; // 30% next round's seed\nconst RAKE_BPS = 1000; // 10% Playmos take\n\n/**\n * Shape the service returns from POST /payments with `settle: \"server\"` — the\n * sandbox server-settle path. The service signed + submitted the on-chain txn\n * itself, so `payment` is already confirmed with a real `txHash` (no client\n * signing). Tolerant to extra fields.\n */\ninterface ServerSettleResponse {\n payment: Payment & { splitBps?: { pool: number; seed: number; rake: number } };\n settledBy?: \"server\";\n signer?: `0x${string}`;\n}\n\n/** Shape the service returns from POST /payments. Tolerant to extra fields. */\ninterface CreateIntentResponse {\n payment: Payment;\n clientParams?: {\n contract?: \"playmosPay\" | \"prizePool\";\n contractAddress?: `0x${string}`;\n usdc?: `0x${string}`;\n // The service emits `amountMicro`; older shapes used `amountUnits`. Accept both.\n amountUnits?: string;\n amountMicro?: string;\n studio?: `0x${string}`;\n // The service emits `roundId` + `identity`; it SHOULD also emit the exact\n // `roundKey` string it will check via hasEntered (see integration seam #345).\n roundKey?: string;\n roundId?: string;\n identity?: string;\n paymasterUrl?: string;\n };\n}\n\nexport class Playmos {\n readonly config: PlaymosConfig;\n readonly env: ResolvedEnv;\n private readonly http: HttpClient;\n\n readonly webhooks = {\n /** Verify a webhook signature and return the parsed event (server-side). */\n verify: (\n rawBody: string | Buffer,\n signatureHeader: string | string[] | undefined,\n secret: string,\n ): WebhookEvent => verifyWebhook(rawBody, signatureHeader, secret),\n };\n\n readonly payouts = {\n /** Choose how the studio is paid: \"usdc\" (default) or \"fiat\" (Bridge). */\n setMode: (mode: \"usdc\" | \"fiat\"): Promise<{ mode: \"usdc\" | \"fiat\" }> =>\n this.http.post(\"/payouts/mode\", { mode }),\n /** Create a Bridge KYC onboarding link (fiat payout). */\n createOnboardingLink: (): Promise<{ url: string }> =>\n this.http.post(\"/payouts/onboarding_link\", {}),\n };\n\n readonly agents = {\n /** Assign a wallet to any identity (incl. an AI NPC). Idempotent by agentId. */\n createWallet: (input: { agentId: string }): Promise<{ agentId: string; address: `0x${string}`; chain: string }> => {\n requireField(input?.agentId, \"agentId\");\n return this.http.post(\"/agents/wallets\", { agentId: input.agentId });\n },\n /** Agent↔agent USDC transfer; the configured taxBps is skimmed to Playmos. */\n pay: (input: { from: string; to: string; amount: string }): Promise<{ id: string; taxUSD: string; status: string }> => {\n requireField(input?.from, \"from\");\n requireField(input?.to, \"to\");\n validateAmount(input?.amount);\n return this.http.post(\"/agents/pay\", input);\n },\n };\n\n constructor(config: PlaymosConfig) {\n this.config = config;\n this.env = resolveEnv(config.apiKey, config.network, config.apiBaseUrl);\n this.http = createHttpClient(this.env.apiBaseUrl, config.apiKey);\n }\n\n /** Connect the player's wallet and return their address. */\n async connect(): Promise<`0x${string}`> {\n return getAccount(resolveProvider(this.config.wallet));\n }\n\n /**\n * A DROP-IN payment provider for game kits that expect `{ connect, payEntry }`\n * (e.g. the Playmos game-hub kit). No custom adapter needed — the game dev just\n * does: `gameConfig.paymentProvider = playmos.entryProvider({ gameId })`.\n * The kit hands `payEntry` its own on-chain `roundKey` + `identity`; we thread\n * them straight through so the on-chain entry and the game server's `hasEntered`\n * check line up.\n */\n entryProvider(cfg: { gameId: string }): {\n connect(): Promise<string>;\n payEntry(req: { roundKey: string; identity: string; wallet: string; entryUnits: bigint }): Promise<{\n paymentId: string;\n status: \"CONFIRMED\" | \"FAILED\" | \"PENDING\";\n txHash?: string;\n onchain: boolean;\n /** The on-chain identity actually entered — reconcile with `hasEntered`. */\n identity?: string;\n }>;\n } {\n return {\n connect: () => this.connect(),\n payEntry: async (req) => {\n const entry = await this.enterRound({\n gameId: cfg.gameId,\n roundId: req.roundKey, // the round the server verifies against\n roundKey: req.roundKey,\n identity: req.identity,\n amount: formatMicroToUsd(req.entryUnits),\n playerId: req.wallet,\n });\n const status =\n entry.status === \"confirmed\" ? \"CONFIRMED\" : entry.status === \"failed\" ? \"FAILED\" : \"PENDING\";\n return { paymentId: entry.id, status, txHash: entry.txHash, onchain: true, identity: entry.identity };\n },\n };\n }\n\n /** External-studio IAP (1%). Returns a real confirmed Payment with a txHash. */\n async pay(input: PayInput): Promise<Payment> {\n const amountMicro = validateAmount(input.amount);\n requireField(input.sku, \"sku\");\n requireField(input.playerId, \"playerId\");\n const metadata = validateMetadata(input.metadata);\n const idempotencyKey = input.idempotencyKey ?? prefixedId(\"idem\");\n\n if (this.config.mock) {\n return mockIapPayment({\n amountMicro,\n feeBps: IAP_FEE_BPS,\n sku: input.sku,\n playerId: input.playerId,\n chain: this.env.network,\n metadata,\n });\n }\n\n // Auto no-wallet routing (0.1.4): on a test/sandbox key with NO wallet\n // available, let the SERVICE sign + submit on-chain (server-settle) so the\n // developer needs zero wallet/crypto. Sandbox-only — a live key with no\n // wallet keeps today's behavior (the client-signed path throws below).\n if (this.env.isTest && !(await walletAvailable(this.config.wallet))) {\n const res = await this.http.post<ServerSettleResponse>(\n \"/payments\",\n { kind: \"iap\", amount: input.amount, sku: input.sku, playerId: input.playerId, gameId: input.gameId, studio: input.studio, metadata, settle: \"server\" },\n { idempotencyKey },\n );\n return this.mapServerPayment(res.payment, \"iap\", amountMicro);\n }\n\n const intent = await this.http.post<CreateIntentResponse>(\n \"/payments\",\n { kind: \"iap\", amount: input.amount, sku: input.sku, playerId: input.playerId, gameId: input.gameId, studio: input.studio, metadata },\n { idempotencyKey },\n );\n\n const provider = resolveProvider(this.config.wallet);\n if (this.config.gas?.mode === \"player\") {\n const from0 = await getAccount(provider);\n await assertEnoughGas(provider, from0);\n }\n const from = await getAccount(provider);\n\n const usdc = intent.clientParams?.usdc ?? this.config.contracts?.usdc ?? USDC_ADDRESS[this.env.network];\n const playmosPay = intent.clientParams?.contractAddress ?? this.config.contracts?.playmosPay;\n const studio = intent.clientParams?.studio ?? input.studio;\n if (!playmosPay) throw new ConfigError(\"No PlaymosPay contract address (service intent + config.contracts both empty).\");\n if (!studio) throw new ConfigError(\"No studio payout address for this payment.\");\n const amountUnits = this.resolveUnits(intent, amountMicro);\n\n const calls = buildIapCalls({ usdc, playmosPay, paymentId: intent.payment.id, studio, amountUnits });\n const { id: callsId } = await sendCalls(provider, from, this.env.chainId, calls, this.sponsorUrl(intent));\n const { txHash } = await waitForCalls(provider, callsId);\n\n return this.settle(intent.payment.id, txHash);\n }\n\n /** Playmos-owned skill-game entry (10%, 60/30/10 prize pool). Closes #343. */\n async enterRound(input: EnterRoundInput): Promise<Payment> {\n const amountMicro = validateAmount(input.amount);\n requireField(input.gameId, \"gameId\");\n requireField(input.roundId, \"roundId\");\n requireField(input.playerId, \"playerId\");\n const metadata = validateMetadata(input.metadata);\n const idempotencyKey = input.idempotencyKey ?? prefixedId(\"idem\");\n\n if (this.config.mock) {\n return mockEntryPayment({\n amountMicro,\n poolBps: POOL_BPS,\n seedBps: SEED_BPS,\n rakeBps: RAKE_BPS,\n gameId: input.gameId,\n roundId: input.roundId,\n playerId: input.playerId,\n chain: this.env.network,\n metadata,\n });\n }\n\n // Auto no-wallet routing (0.1.4): test/sandbox key + NO wallet → the service\n // settles the entry on-chain for us (server-settle). entryProvider().payEntry\n // inherits this automatically since it calls enterRound(). Sandbox-only.\n if (this.env.isTest && !(await walletAvailable(this.config.wallet))) {\n const res = await this.http.post<ServerSettleResponse>(\n \"/payments\",\n { kind: \"entry\", amount: input.amount, gameId: input.gameId, roundId: input.roundKey ?? input.roundId, identity: input.identity, playerId: input.playerId, metadata, settle: \"server\" },\n { idempotencyKey },\n );\n const payment = this.mapServerPayment(res.payment, \"entry\", amountMicro);\n // Prefer the identity the caller pinned; else whatever the service echoed.\n if (input.identity) payment.identity = input.identity;\n return payment;\n }\n\n const intent = await this.http.post<CreateIntentResponse>(\n \"/payments\",\n // When the game supplies its own roundKey, that IS the round the service\n // stores + verifies against (so on-chain enter and server hasEntered align).\n { kind: \"entry\", amount: input.amount, gameId: input.gameId, roundId: input.roundKey ?? input.roundId, identity: input.identity, playerId: input.playerId, metadata },\n { idempotencyKey },\n );\n\n const provider = resolveProvider(this.config.wallet);\n if (this.config.gas?.mode === \"player\") {\n const from0 = await getAccount(provider);\n await assertEnoughGas(provider, from0);\n }\n const from = await getAccount(provider);\n\n const usdc = intent.clientParams?.usdc ?? this.config.contracts?.usdc ?? USDC_ADDRESS[this.env.network];\n const prizePool = intent.clientParams?.contractAddress ?? this.config.contracts?.prizePool;\n if (!prizePool) throw new ConfigError(\"No PrizePool contract address for this game (service intent + config.contracts both empty).\");\n const roundKey = input.roundKey ?? intent.clientParams?.roundKey ?? intent.clientParams?.roundId ?? `${input.gameId}:${input.roundId}`;\n const identity = input.identity ?? intent.clientParams?.identity ?? `${from}#${idempotencyKey}`;\n const amountUnits = this.resolveUnits(intent, amountMicro);\n\n const calls = buildEntryCalls({ usdc, prizePool, roundKey, identity, amountUnits });\n const { id: callsId } = await sendCalls(provider, from, this.env.chainId, calls, this.sponsorUrl(intent));\n const { txHash } = await waitForCalls(provider, callsId);\n\n // Surface the EXACT on-chain identity we entered with so the caller can\n // reconcile against their server's `hasEntered(roundKey, identity)`.\n const payment = await this.settle(intent.payment.id, txHash);\n payment.identity = identity;\n return payment;\n }\n\n /** Verify a payment by the service's on-chain read (spec §6.1). Idempotent. */\n async verify(paymentId: string): Promise<VerifyResult> {\n requireField(paymentId, \"paymentId\");\n return this.http.get<VerifyResult>(`/payments/${encodeURIComponent(paymentId)}`);\n }\n\n // ---- internals ---------------------------------------------------------\n\n /**\n * Map a server-settled payment (from the `settle: \"server\"` response) into the\n * SDK's `Payment` shape. The service already signed + confirmed on-chain, so we\n * pass its authoritative `status`/`txHash`/amounts straight through and, for an\n * entry, derive the 60/30/10 USD `split` locally (exactly as the mock + the\n * contract compute it) from the parsed amount.\n */\n private mapServerPayment(\n p: ServerSettleResponse[\"payment\"],\n kind: \"iap\" | \"entry\",\n amountMicro: bigint,\n ): Payment {\n const payment: Payment = {\n id: p.id,\n status: p.status,\n kind: p.kind ?? kind,\n amount: p.amount,\n fee: p.fee,\n net: p.net,\n sku: p.sku,\n roundId: p.roundId,\n gameId: p.gameId,\n playerId: p.playerId ?? \"\",\n txHash: p.txHash,\n chain: this.env.network,\n createdAt: p.createdAt ?? new Date().toISOString(),\n metadata: p.metadata,\n identity: p.identity,\n };\n if ((p.kind ?? kind) === \"entry\") {\n const { poolMicro, seedMicro, rakeMicro } = computePoolSplit(amountMicro, POOL_BPS, SEED_BPS, RAKE_BPS);\n payment.split = {\n pool: formatMicroToUsd(poolMicro),\n seed: formatMicroToUsd(seedMicro),\n rake: formatMicroToUsd(rakeMicro),\n };\n }\n return payment;\n }\n\n /** Prefer the service's authoritative micro-USDC amount; fall back to the\n * locally-parsed value if the service didn't echo one. */\n private resolveUnits(intent: CreateIntentResponse, local: bigint): bigint {\n const fromServer = intent.clientParams?.amountUnits ?? intent.clientParams?.amountMicro;\n return fromServer ? BigInt(fromServer) : local;\n }\n\n private sponsorUrl(intent: CreateIntentResponse): string | undefined {\n if (this.config.gas?.mode === \"player\") return undefined;\n return this.config.gas?.paymasterUrl ?? intent.clientParams?.paymasterUrl;\n }\n\n /**\n * After the batch lands, resolve the authoritative status via the service's\n * on-chain read. Polls briefly; returns the merged Payment with the real txHash.\n */\n private async settle(paymentId: string, txHash?: `0x${string}`, timeoutMs = 30_000): Promise<Payment> {\n // Report the settlement txHash we observed locally so the service can VERIFY\n // IT ON-CHAIN. We only say WHICH tx landed; the service reads the chain and\n // decides confirmed/failed (trust stays on-chain — anti-#337). Non-fatal on\n // failure: fall back to polling verify.\n if (txHash) {\n try {\n await this.http.post(`/payments/${encodeURIComponent(paymentId)}/tx`, { txHash });\n } catch {\n /* ignore — the verify poll below still resolves the authoritative status */\n }\n }\n const deadline = Date.now() + timeoutMs;\n let last: VerifyResult | undefined;\n while (Date.now() < deadline) {\n last = await this.verify(paymentId);\n if (last.status === \"confirmed\" || last.status === \"failed\") break;\n // If the service can't read the chain (degraded), polling will never\n // confirm — return the honest cached status now instead of spinning.\n if (last.chainReads === \"degraded\" || last.verifiedVia === \"degraded\") break;\n await new Promise((r) => setTimeout(r, 1200));\n }\n return {\n id: paymentId,\n status: last?.status ?? \"pending\",\n kind: last?.roundId ? \"entry\" : \"iap\",\n amount: last?.amount ?? \"0\",\n fee: last?.fee ?? \"0\",\n net: last?.net ?? \"0\",\n sku: last?.sku,\n roundId: last?.roundId,\n playerId: last?.playerId ?? \"\",\n txHash: last?.txHash ?? txHash,\n chain: this.env.network,\n createdAt: new Date().toISOString(),\n };\n }\n}\n\n/** Local preview of a split without any network — handy for UIs. */\nexport function previewIapSplit(amount: string): { amount: string; fee: string; net: string } {\n const micro = validateAmount(amount);\n const { feeMicro, netMicro } = computeIapSplit(micro, IAP_FEE_BPS);\n return { amount: formatMicroToUsd(micro), fee: formatMicroToUsd(feeMicro), net: formatMicroToUsd(netMicro) };\n}\n\n/** Local preview of the 60/30/10 entry split without any network. */\nexport function previewPoolSplit(amount: string): { amount: string; pool: string; seed: string; rake: string } {\n const micro = validateAmount(amount);\n const { poolMicro, seedMicro, rakeMicro } = computePoolSplit(micro, POOL_BPS, SEED_BPS, RAKE_BPS);\n return {\n amount: formatMicroToUsd(micro),\n pool: formatMicroToUsd(poolMicro),\n seed: formatMicroToUsd(seedMicro),\n rake: formatMicroToUsd(rakeMicro),\n };\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/errors.ts","../src/config.ts","../src/ids.ts","../src/money.ts","../src/validation.ts","../src/http.ts","../src/wallet.ts","../src/chain/abis.ts","../src/chain/batch.ts","../src/chain/calls.ts","../src/mock.ts","../src/client.ts"],"names":["numberToHex","encodeFunctionData","keccak256","toBytes","payment"],"mappings":"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","file":"index.cjs","sourcesContent":["/**\n * Typed, actionable errors — the Stripe bar (spec §11).\n *\n * Every error carries a stable machine-readable `code` and is thrown at the\n * EARLIEST possible layer: input errors fire client-side before any network or\n * chain call, so a studio never pays gas to discover a typo.\n */\n\nexport type PlaymosErrorCode =\n | \"invalid_amount\"\n | \"missing_field\"\n | \"insufficient_gas\"\n | \"wallet_connection\"\n | \"payment_failed\"\n | \"auth\"\n | \"api_error\"\n | \"config\";\n\nexport class PlaymosError extends Error {\n readonly code: PlaymosErrorCode;\n /** Optional machine context (e.g. the offending field, the http status). */\n readonly detail?: Record<string, unknown>;\n\n constructor(code: PlaymosErrorCode, message: string, detail?: Record<string, unknown>) {\n super(message);\n this.name = new.target.name;\n this.code = code;\n this.detail = detail;\n // Restore prototype chain for `instanceof` across transpile targets.\n Object.setPrototypeOf(this, new.target.prototype);\n }\n}\n\n/** amount ≤ 0, non-numeric, empty, or more than 2 decimal places. */\nexport class InvalidAmountError extends PlaymosError {\n constructor(amount: unknown) {\n super(\n \"invalid_amount\",\n `Invalid amount: ${JSON.stringify(amount)}. Provide a positive USD decimal string with at most 2 decimals, e.g. \"4.99\".`,\n { amount },\n );\n }\n}\n\n/** A required field (sku, playerId, gameId, roundId, agentId…) was empty. */\nexport class MissingFieldError extends PlaymosError {\n constructor(field: string) {\n super(\"missing_field\", `Missing required field: \"${field}\".`, { field });\n }\n}\n\n/** gas mode \"player\" and the player's ETH is too low to cover gas (pre-check, §7). */\nexport class InsufficientGasError extends PlaymosError {\n constructor(detail?: Record<string, unknown>) {\n super(\n \"insufficient_gas\",\n \"The player's wallet has too little ETH to pay gas. Ask them to add a little ETH, or switch to gas.mode: \\\"sponsored\\\".\",\n detail,\n );\n }\n}\n\n/** The player closed or failed the wallet sheet, or no provider is available. */\nexport class WalletConnectionError extends PlaymosError {\n constructor(message = \"Could not connect the player's wallet.\", detail?: Record<string, unknown>) {\n super(\"wallet_connection\", message, detail);\n }\n}\n\n/** The on-chain settlement reverted, was cancelled, or timed out. */\nexport class PaymentFailedError extends PlaymosError {\n constructor(message = \"The on-chain payment did not complete.\", detail?: Record<string, unknown>) {\n super(\"payment_failed\", message, detail);\n }\n}\n\n/** Bad, missing, or wrong-environment API key (e.g. a pk_test_ key on a live route). */\nexport class AuthError extends PlaymosError {\n constructor(message = \"Invalid or missing API key.\", detail?: Record<string, unknown>) {\n super(\"auth\", message, detail);\n }\n}\n\n/** The Playmos service returned a non-2xx we don't have a more specific error for. */\nexport class ApiError extends PlaymosError {\n constructor(message: string, detail?: Record<string, unknown>) {\n super(\"api_error\", message, detail);\n }\n}\n\n/** SDK misconfiguration (e.g. a missing contract address for on-chain mode). */\nexport class ConfigError extends PlaymosError {\n constructor(message: string, detail?: Record<string, unknown>) {\n super(\"config\", message, detail);\n }\n}\n","/**\n * Environment resolution + the canonical address book.\n *\n * The API key prefix selects the environment (Stripe's ergonomic): pk_test_* →\n * Base Sepolia + the sandbox service; pk_live_* → Base mainnet + production. An\n * explicit `network` override always wins.\n */\n\nimport { AuthError } from \"./errors.js\";\nimport type { Network } from \"./types.js\";\n\nexport const CHAIN_ID: Record<Network, number> = {\n base: 8453,\n \"base-sepolia\": 84532,\n};\n\n/**\n * Circle USDC. Sepolia value fixes #336 (the vendored SDK shipped 0x0 here).\n * Verified against the game-hub deploy scripts + kit config.\n */\nexport const USDC_ADDRESS: Record<Network, `0x${string}`> = {\n base: \"0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913\",\n \"base-sepolia\": \"0x036CbD53842c5426634e7929541eC2318f3dCF7e\",\n};\n\nexport const DEFAULT_API_BASE_URL: Record<Network, string> = {\n base: \"https://api.playmos.io/v1\",\n \"base-sepolia\": \"https://api.sandbox.playmos.io/v1\",\n};\n\nexport interface ResolvedEnv {\n network: Network;\n chainId: number;\n apiBaseUrl: string;\n isTest: boolean;\n}\n\n/** Validate the key and resolve the environment it implies. */\nexport function resolveEnv(\n apiKey: string,\n networkOverride?: Network,\n apiBaseUrlOverride?: string,\n): ResolvedEnv {\n if (typeof apiKey !== \"string\" || apiKey.trim() === \"\") {\n throw new AuthError(\"Missing apiKey. Pass a pk_test_… or pk_live_… key.\");\n }\n const isTest = apiKey.startsWith(\"pk_test_\") || apiKey.startsWith(\"sk_test_\");\n const isLive = apiKey.startsWith(\"pk_live_\") || apiKey.startsWith(\"sk_live_\");\n if (!isTest && !isLive) {\n throw new AuthError(\n 'Malformed apiKey. Expected a \"pk_test_\", \"pk_live_\", \"sk_test_\", or \"sk_live_\" prefix.',\n { keyPreview: apiKey.slice(0, 8) },\n );\n }\n const network: Network = networkOverride ?? (isTest ? \"base-sepolia\" : \"base\");\n return {\n network,\n chainId: CHAIN_ID[network],\n apiBaseUrl: apiBaseUrlOverride ?? DEFAULT_API_BASE_URL[network],\n isTest,\n };\n}\n","/**\n * ULID generation (fixes #341/C — the `pay_mock_${Date.now()}` collision bug).\n *\n * A ULID is a 26-char Crockford-base32 string: 48 bits of millisecond timestamp\n * (lexicographically sortable) + 80 bits of cryptographic randomness. Within the\n * same millisecond we increment the random component monotonically, so even 50+\n * ids minted in a tight loop are unique and ordered. Uses Web Crypto\n * (`crypto.getRandomValues`), available in browsers and Node ≥ 18.\n */\n\nconst ENCODING = \"0123456789ABCDEFGHJKMNPQRSTVWXYZ\"; // Crockford base32 (no I,L,O,U)\nconst TIME_LEN = 10;\nconst RANDOM_LEN = 16;\n\nfunction getCrypto(): Crypto {\n const c = (globalThis as { crypto?: Crypto }).crypto;\n if (!c || typeof c.getRandomValues !== \"function\") {\n throw new Error(\"Web Crypto (crypto.getRandomValues) is not available in this runtime.\");\n }\n return c;\n}\n\nfunction encodeTime(now: number, len: number): string {\n let mod: number;\n let str = \"\";\n for (let i = len - 1; i >= 0; i--) {\n mod = now % 32;\n str = ENCODING[mod] + str;\n now = (now - mod) / 32;\n }\n return str;\n}\n\n// Monotonic state so ids minted in the same millisecond stay unique + ordered.\nlet lastTime = -1;\nlet lastRandom: number[] = [];\n\nfunction randomBytes(len: number): number[] {\n const bytes = new Uint8Array(len);\n getCrypto().getRandomValues(bytes);\n return Array.from(bytes, (b) => b % 32);\n}\n\nfunction incrementRandom(arr: number[]): number[] {\n const out = arr.slice();\n for (let i = out.length - 1; i >= 0; i--) {\n const v = out[i] ?? 0;\n if (v < 31) {\n out[i] = v + 1;\n return out;\n }\n out[i] = 0;\n }\n // Overflow (astronomically unlikely) — reseed.\n return randomBytes(out.length);\n}\n\n/** Generate a monotonic ULID (26 chars, uppercase Crockford base32). */\nexport function ulid(seedTime?: number): string {\n const now = seedTime ?? Date.now();\n let random: number[];\n if (now === lastTime) {\n random = incrementRandom(lastRandom);\n } else {\n random = randomBytes(RANDOM_LEN);\n }\n lastTime = now;\n lastRandom = random;\n return encodeTime(now, TIME_LEN) + random.map((r) => ENCODING[r]).join(\"\");\n}\n\n/** `${prefix}_${ulid()}` — e.g. `pay_01J…`, `entry_01J…`, `idem_01J…`. */\nexport function prefixedId(prefix: string): string {\n return `${prefix}_${ulid()}`;\n}\n","/**\n * Money math — exact, integer-only, in USDC micro-units (6 decimals).\n *\n * USD amounts are decimal strings (\"4.99\") to avoid float corruption. Internally\n * every value is a BigInt count of micro-USDC (1 USDC = 1_000_000 micro), so the\n * split is bit-exact and always sums back to the input — no wei is ever lost.\n *\n * The split arithmetic MIRRORS the contracts (floor division, exactly like\n * Solidity `amount * bps / 10000`), so the SDK receipt matches what settles\n * on-chain. The contract remains the source of truth; these numbers are the\n * faithful preview.\n */\n\nimport { InvalidAmountError } from \"./errors.js\";\n\nexport const USDC_DECIMALS = 6;\nexport const MICRO_PER_USDC = 1_000_000n;\n\nconst AMOUNT_RE = /^\\d+(\\.\\d{1,2})?$/;\n\n/**\n * Parse a USD decimal string (≤ 2 dp, > 0) into micro-USDC.\n * Throws {@link InvalidAmountError} on anything that isn't a clean positive price.\n */\nexport function parseUsdToMicro(amount: string): bigint {\n if (typeof amount !== \"string\" || amount.trim() === \"\" || !AMOUNT_RE.test(amount)) {\n throw new InvalidAmountError(amount);\n }\n const parts = amount.split(\".\");\n const whole = parts[0] ?? \"0\";\n const frac = parts[1] ?? \"\";\n const fracPadded = (frac + \"000000\").slice(0, USDC_DECIMALS);\n const micro = BigInt(whole) * MICRO_PER_USDC + BigInt(fracPadded);\n if (micro <= 0n) throw new InvalidAmountError(amount);\n return micro;\n}\n\n/**\n * Format micro-USDC back to a USD decimal string. Keeps full precision (up to 6\n * dp) but trims trailing zeros to a minimum of 2 dp — so \"$4.99\" stays \"4.99\"\n * while a 1% fee of $4.99 renders its exact \"0.0499\", not a lossy \"0.05\".\n */\nexport function formatMicroToUsd(micro: bigint): string {\n const neg = micro < 0n;\n const abs = neg ? -micro : micro;\n const whole = abs / MICRO_PER_USDC;\n const frac = abs % MICRO_PER_USDC;\n let fracStr = frac.toString().padStart(USDC_DECIMALS, \"0\").replace(/0+$/, \"\");\n if (fracStr.length < 2) fracStr = fracStr.padEnd(2, \"0\");\n return `${neg ? \"-\" : \"\"}${whole.toString()}.${fracStr}`;\n}\n\n/** External-studio IAP split (99/1 by default). Floor-matches `PlaymosPay.pay`. */\nexport function computeIapSplit(\n amountMicro: bigint,\n feeBps: number,\n): { feeMicro: bigint; netMicro: bigint } {\n const feeMicro = (amountMicro * BigInt(feeBps)) / 10_000n;\n const netMicro = amountMicro - feeMicro;\n return { feeMicro, netMicro };\n}\n\n/**\n * Skill-game prize-pool split (60/30/10 by default). Floor-matches the on-chain\n * `EconomyConfig`. Any 1–2 micro rounding remainder is assigned to the pool so\n * the three parts sum EXACTLY to the entry (invariant asserted below).\n */\nexport function computePoolSplit(\n amountMicro: bigint,\n poolBps: number,\n seedBps: number,\n rakeBps: number,\n): { poolMicro: bigint; seedMicro: bigint; rakeMicro: bigint } {\n if (poolBps + seedBps + rakeBps !== 10_000) {\n throw new Error(`pool/seed/rake bps must sum to 10000, got ${poolBps + seedBps + rakeBps}`);\n }\n const seedMicro = (amountMicro * BigInt(seedBps)) / 10_000n;\n const rakeMicro = (amountMicro * BigInt(rakeBps)) / 10_000n;\n const poolMicro = amountMicro - seedMicro - rakeMicro; // remainder → pool\n return { poolMicro, seedMicro, rakeMicro };\n}\n","/**\n * Client-side input validation (fixes #342/D — \"-1\", \"0\", \"abc\", \"\", 18-dp all\n * used to succeed). Every check throws a typed error BEFORE any network or chain\n * call, exactly like Stripe.\n */\n\nimport { InvalidAmountError, MissingFieldError } from \"./errors.js\";\nimport { parseUsdToMicro } from \"./money.js\";\n\n/**\n * Validate a USD amount string and return its micro-USDC value.\n * Rejects: empty, non-numeric, ≤ 0, or more than 2 decimal places.\n */\nexport function validateAmount(amount: unknown): bigint {\n if (typeof amount !== \"string\") throw new InvalidAmountError(amount);\n return parseUsdToMicro(amount); // throws InvalidAmountError on bad format / ≤ 0\n}\n\n/** Require a non-empty, trimmed string field. */\nexport function requireField(value: unknown, field: string): string {\n if (typeof value !== \"string\" || value.trim() === \"\") {\n throw new MissingFieldError(field);\n }\n return value;\n}\n\n/** Metadata guard: at most 20 string→string entries (per docs §3). */\nexport function validateMetadata(metadata: unknown): Record<string, string> | undefined {\n if (metadata == null) return undefined;\n if (typeof metadata !== \"object\" || Array.isArray(metadata)) {\n throw new MissingFieldError(\"metadata (must be an object of string values)\");\n }\n const entries = Object.entries(metadata as Record<string, unknown>);\n if (entries.length > 20) {\n throw new InvalidAmountError(`metadata: at most 20 keys allowed, got ${entries.length}`);\n }\n const out: Record<string, string> = {};\n for (const [k, v] of entries) {\n if (typeof v !== \"string\") {\n throw new MissingFieldError(`metadata.${k} (values must be strings)`);\n }\n out[k] = v;\n }\n return out;\n}\n","/**\n * Thin REST client for the Playmos service. Every SDK method that touches the\n * backend (create intent, verify, payouts, agents) goes through here. `verify()`\n * hits `GET /payments/:id`, which the service resolves by READING THE CHAIN — so\n * the SDK never trusts a client claim or a mutable counter (#337 root fix).\n */\n\nimport { ApiError, AuthError } from \"./errors.js\";\n\nexport interface HttpClient {\n post<T>(path: string, body: unknown, opts?: { idempotencyKey?: string }): Promise<T>;\n get<T>(path: string): Promise<T>;\n}\n\nexport function createHttpClient(baseUrl: string, apiKey: string): HttpClient {\n const base = baseUrl.replace(/\\/+$/, \"\");\n\n /**\n * Run the request, converting a TRANSPORT failure (DNS/NXDOMAIN, connection\n * refused, TLS, abort/timeout — i.e. `fetch()` itself throws) into a typed,\n * actionable `ApiError`. HTTP error *responses* (non-2xx) are NOT caught here;\n * they flow through `handle()` unchanged. `detail.cause` carries the underlying\n * error; `detail.transport: true` distinguishes this from a status failure.\n */\n async function send(url: string, init: RequestInit): Promise<Response> {\n try {\n return await fetch(url, init);\n } catch (err) {\n const cause = err instanceof Error ? err.message : String(err);\n throw new ApiError(\n `Could not reach the Playmos API at ${url} (network error: ${cause}). Check the service is running and apiBaseUrl is correct.`,\n { url, cause, transport: true },\n );\n }\n }\n\n async function handle<T>(res: Response): Promise<T> {\n let text: string;\n try {\n text = await res.text();\n } catch (err) {\n const cause = err instanceof Error ? err.message : String(err);\n throw new ApiError(\n `Could not read the response from the Playmos API at ${res.url} (network error: ${cause}). Check the service is running and apiBaseUrl is correct.`,\n { url: res.url, cause, transport: true },\n );\n }\n let json: unknown;\n try {\n json = text ? JSON.parse(text) : {};\n } catch {\n throw new ApiError(`Non-JSON response (${res.status}) from ${res.url}`, { status: res.status, body: text });\n }\n if (res.ok) return json as T;\n const errBody = json as { error?: { code?: string; message?: string } };\n const message = errBody?.error?.message ?? `Request failed with ${res.status}`;\n if (res.status === 401 || res.status === 403 || errBody?.error?.code === \"auth\") {\n throw new AuthError(message, { status: res.status });\n }\n throw new ApiError(message, { status: res.status, code: errBody?.error?.code });\n }\n\n return {\n async post<T>(path: string, body: unknown, opts?: { idempotencyKey?: string }): Promise<T> {\n const headers: Record<string, string> = {\n \"content-type\": \"application/json\",\n authorization: `Bearer ${apiKey}`,\n };\n if (opts?.idempotencyKey) headers[\"idempotency-key\"] = opts.idempotencyKey;\n const res = await send(`${base}${path}`, { method: \"POST\", headers, body: JSON.stringify(body) });\n return handle<T>(res);\n },\n async get<T>(path: string): Promise<T> {\n const res = await send(`${base}${path}`, {\n method: \"GET\",\n headers: { authorization: `Bearer ${apiKey}` },\n });\n return handle<T>(res);\n },\n };\n}\n","/**\n * Wallet resolution — pruned to the two connectors V1 actually supports\n * (`base-account`, `injected`), fixing the old surface that advertised four and\n * silently no-op'd (#335/E).\n */\n\nimport { WalletConnectionError } from \"./errors.js\";\nimport type { Eip1193Provider, WalletConfig } from \"./types.js\";\n\ninterface WithEthereum {\n ethereum?: Eip1193Provider;\n}\n\n/**\n * Resolve an EIP-1193 provider from config. Precedence:\n * 1. an explicitly supplied `wallet.provider`\n * 2. `injected` → globalThis.ethereum (browser wallet)\n * 3. `base-account` → expects the Base Account SDK to have injected a provider;\n * the host app passes it via `wallet.provider` in headless/SSR contexts.\n */\nexport function resolveProvider(wallet?: WalletConfig): Eip1193Provider {\n if (wallet?.provider) return wallet.provider;\n\n const injected = (globalThis as WithEthereum).ethereum;\n const connector = wallet?.connector ?? \"base-account\";\n\n if (connector === \"injected\") {\n if (!injected) {\n throw new WalletConnectionError(\n \"No injected wallet found (globalThis.ethereum is undefined). Open in a wallet browser or pass wallet.provider.\",\n );\n }\n return injected;\n }\n\n // base-account: prefer an injected Base Account provider; otherwise instruct\n // the host to supply one. We do NOT hard-depend on the Base Account SDK so the\n // package stays light and server-safe.\n if (injected) return injected;\n throw new WalletConnectionError(\n \"base-account connector needs a provider. In the Base App it is injected automatically; \" +\n \"elsewhere, create one with @base-org/account and pass it as wallet.provider.\",\n );\n}\n\n/**\n * Is a real wallet actually available to sign for the player? Used by the\n * auto no-wallet routing (0.1.4): when this is false on a test/sandbox key, the\n * SDK routes to the service's server-settle path so the developer needs zero\n * wallet/crypto. Detection (mirrors {@link resolveProvider} precedence):\n * 1. an explicit `wallet.provider` counts as available (don't force a connect);\n * 2. otherwise a provider must resolve (config or globalThis.ethereum) AND we\n * must be able to actually read an account from it.\n * Never throws — any failure to resolve/connect means \"no wallet\".\n */\nexport async function walletAvailable(wallet?: WalletConfig): Promise<boolean> {\n // An explicitly-supplied provider is treated as available without forcing an\n // eth_requestAccounts round-trip (the host owns its own connect UX).\n if (wallet?.provider) return true;\n\n let provider: Eip1193Provider;\n try {\n provider = resolveProvider(wallet);\n } catch {\n return false; // no config.provider and no injectable globalThis.ethereum\n }\n try {\n await getAccount(provider);\n return true;\n } catch {\n return false; // provider present but no account could be resolved\n }\n}\n\n/** Read the connected account (first address). */\nexport async function getAccount(provider: Eip1193Provider): Promise<`0x${string}`> {\n try {\n const accounts = (await provider.request({ method: \"eth_requestAccounts\" })) as string[];\n const addr = accounts?.[0];\n if (!addr) throw new Error(\"no account\");\n return addr as `0x${string}`;\n } catch (e) {\n throw new WalletConnectionError(\"Could not read the player's wallet account.\", {\n cause: (e as { message?: string })?.message,\n });\n }\n}\n","/** Minimal viem const-typed ABIs for the on-chain calls the SDK builds. */\n\nexport const erc20Abi = [\n {\n type: \"function\",\n name: \"approve\",\n stateMutability: \"nonpayable\",\n inputs: [\n { name: \"spender\", type: \"address\" },\n { name: \"amount\", type: \"uint256\" },\n ],\n outputs: [{ type: \"bool\" }],\n },\n {\n type: \"function\",\n name: \"balanceOf\",\n stateMutability: \"view\",\n inputs: [{ name: \"account\", type: \"address\" }],\n outputs: [{ type: \"uint256\" }],\n },\n] as const;\n\n/** PlaymosPay — external-studio IAP, 99/1 atomic split. */\nexport const playmosPayAbi = [\n {\n type: \"function\",\n name: \"pay\",\n stateMutability: \"nonpayable\",\n inputs: [\n { name: \"paymentId\", type: \"bytes32\" },\n { name: \"studio\", type: \"address\" },\n { name: \"amount\", type: \"uint256\" },\n ],\n outputs: [],\n },\n] as const;\n\n/** PrizePool V2 — skill-game entry, 60/30/10. */\nexport const prizePoolAbi = [\n {\n type: \"function\",\n name: \"enter\",\n stateMutability: \"nonpayable\",\n inputs: [\n { name: \"roundId\", type: \"bytes32\" },\n { name: \"identity\", type: \"bytes32\" },\n ],\n outputs: [],\n },\n {\n type: \"function\",\n name: \"hasEntered\",\n stateMutability: \"view\",\n inputs: [\n { name: \"roundId\", type: \"bytes32\" },\n { name: \"identity\", type: \"bytes32\" },\n ],\n outputs: [{ type: \"bool\" }],\n },\n] as const;\n","/**\n * EIP-5792 batch primitives — ported from the proven game-hub `payEntryOnchain`\n * path (`OnchainEntry.ts`). One `wallet_sendCalls` sends `approve` + the settling\n * call as ONE atomic confirmation; the paymaster sponsors gas when configured.\n * The player sees a single Apple-Pay-style sheet.\n */\n\nimport { numberToHex } from \"viem\";\nimport { InsufficientGasError, PaymentFailedError, WalletConnectionError } from \"../errors.js\";\nimport { erc20Abi } from \"./abis.js\";\nimport { encodeFunctionData } from \"viem\";\nimport type { Eip1193Provider } from \"../types.js\";\n\nexport interface Call {\n to: `0x${string}`;\n data: `0x${string}`;\n}\n\nexport type OnchainStatus = \"PENDING\" | \"CONFIRMED\" | \"FAILED\";\n\n/**\n * Send an atomic approve+call batch via EIP-5792. Returns the calls id; poll\n * {@link waitForCalls} for the terminal status.\n */\nexport async function sendCalls(\n provider: Eip1193Provider,\n from: `0x${string}`,\n chainId: number,\n calls: Call[],\n paymasterUrl?: string,\n): Promise<{ id: string }> {\n const params: Record<string, unknown> = {\n version: \"2.0.0\",\n from,\n chainId: numberToHex(chainId),\n atomicRequired: true,\n calls,\n };\n if (paymasterUrl) {\n params.capabilities = { paymasterService: { url: paymasterUrl } };\n }\n\n let result: unknown;\n try {\n result = await provider.request({ method: \"wallet_sendCalls\", params: [params] });\n } catch (e) {\n const msg = (e as { message?: string })?.message ?? String(e);\n // A user rejection or closed sheet surfaces as a wallet-connection error.\n if (/reject|denied|cancel|closed/i.test(msg)) {\n throw new WalletConnectionError(\"The player cancelled or closed the payment sheet.\", { cause: msg });\n }\n throw new PaymentFailedError(\"wallet_sendCalls failed.\", { cause: msg });\n }\n // EIP-5792 evolved: newer wallets return `{ id }`, older ones a bare string.\n const id = typeof result === \"string\" ? result : ((result as { id?: string })?.id ?? \"\");\n if (!id) throw new PaymentFailedError(\"Wallet returned no calls id.\");\n return { id };\n}\n\n/** Poll EIP-5792 calls status until terminal or timeout, then map to our status. */\nexport async function waitForCalls(\n provider: Eip1193Provider,\n id: string,\n timeoutMs = 60_000,\n): Promise<{ status: OnchainStatus; txHash?: `0x${string}` }> {\n if (!id) return { status: \"FAILED\" };\n const deadline = Date.now() + timeoutMs;\n while (Date.now() < deadline) {\n const res = (await provider.request({\n method: \"wallet_getCallsStatus\",\n params: [id],\n })) as { status?: number | string; receipts?: { transactionHash?: `0x${string}` }[] } | null;\n const s = String(res?.status ?? \"\").toUpperCase();\n const txHash = res?.receipts?.[0]?.transactionHash;\n if (s === \"200\" || s === \"CONFIRMED\" || s === \"SUCCESS\") return { status: \"CONFIRMED\", txHash };\n if (s === \"400\" || s === \"500\" || s === \"FAILED\" || s === \"REVERTED\") return { status: \"FAILED\", txHash };\n await new Promise((r) => setTimeout(r, 900));\n }\n return { status: \"PENDING\" };\n}\n\n/** Encode an ERC-20 approve calldata. */\nexport function encodeApprove(spender: `0x${string}`, amountUnits: bigint): `0x${string}` {\n return encodeFunctionData({ abi: erc20Abi, functionName: \"approve\", args: [spender, amountUnits] });\n}\n\n/**\n * Low-ETH pre-check for `gas: \"player\"` (spec §7). Reads the player's native ETH\n * balance and throws {@link InsufficientGasError} BEFORE building a doomed tx.\n * Uses the wallet's own `eth_getBalance` so no separate RPC is needed.\n */\nexport async function assertEnoughGas(\n provider: Eip1193Provider,\n from: `0x${string}`,\n minWei = 200_000_000_000_000n, // ~0.0002 ETH — a comfortable Base gas floor\n): Promise<void> {\n let balance: bigint;\n try {\n const hex = (await provider.request({ method: \"eth_getBalance\", params: [from, \"latest\"] })) as string;\n balance = BigInt(hex);\n } catch {\n return; // If we can't read it, don't block — the tx will surface a real error.\n }\n if (balance < minWei) {\n throw new InsufficientGasError({ balanceWei: balance.toString(), minWei: minWei.toString() });\n }\n}\n","/**\n * Builders for the two settling calls. Both mirror the proven entry batch:\n * [approve(spender, amount), settle(...)] sent atomically via EIP-5792.\n */\n\nimport { encodeFunctionData, keccak256, toBytes } from \"viem\";\nimport { playmosPayAbi, prizePoolAbi } from \"./abis.js\";\nimport { encodeApprove, type Call } from \"./batch.js\";\n\n/** The server derives these identically (keccak256 of UTF-8 bytes) so the\n * off-chain record and the on-chain call line up. */\nexport const toBytes32 = (s: string): `0x${string}` => keccak256(toBytes(s));\n\n/** External-studio IAP: approve USDC → PlaymosPay, then PlaymosPay.pay(). */\nexport function buildIapCalls(args: {\n usdc: `0x${string}`;\n playmosPay: `0x${string}`;\n paymentId: string;\n studio: `0x${string}`;\n amountUnits: bigint;\n}): Call[] {\n const payData = encodeFunctionData({\n abi: playmosPayAbi,\n functionName: \"pay\",\n args: [toBytes32(args.paymentId), args.studio, args.amountUnits],\n });\n return [\n { to: args.usdc, data: encodeApprove(args.playmosPay, args.amountUnits) },\n { to: args.playmosPay, data: payData },\n ];\n}\n\n/** Skill-game entry: approve USDC → PrizePool, then PrizePool.enter(). */\nexport function buildEntryCalls(args: {\n usdc: `0x${string}`;\n prizePool: `0x${string}`;\n roundKey: string;\n identity: string;\n amountUnits: bigint;\n}): Call[] {\n const enterData = encodeFunctionData({\n abi: prizePoolAbi,\n functionName: \"enter\",\n args: [toBytes32(args.roundKey), toBytes32(args.identity)],\n });\n return [\n { to: args.usdc, data: encodeApprove(args.prizePool, args.amountUnits) },\n { to: args.prizePool, data: enterData },\n ];\n}\n","/**\n * The explicit, clearly-labeled offline unit-test helper (`new Playmos({ mock:true })`).\n *\n * Instant, deterministic, no network, no chain — for a studio's CI. Crucially it\n * is NOT the sandbox and NOT the default, and it never emits a synthetic\n * `\"mocked\"` status (the P0 finding #340). Mock results carry `mock: true` and\n * use the REAL status union, so test code exercises the same shape as production.\n */\n\nimport { computeIapSplit, computePoolSplit, formatMicroToUsd } from \"./money.js\";\nimport { prefixedId } from \"./ids.js\";\nimport type { Network, Payment } from \"./types.js\";\n\nconst MOCK_TX = \"0x000000000000000000000000000000000000000000000000000000000000mock\" as `0x${string}`;\n\nexport function mockIapPayment(args: {\n amountMicro: bigint;\n feeBps: number;\n sku: string;\n playerId: string;\n chain: Network;\n metadata?: Record<string, string>;\n}): Payment {\n const { feeMicro, netMicro } = computeIapSplit(args.amountMicro, args.feeBps);\n return {\n id: prefixedId(\"pay\"),\n status: \"confirmed\",\n kind: \"iap\",\n amount: formatMicroToUsd(args.amountMicro),\n fee: formatMicroToUsd(feeMicro),\n net: formatMicroToUsd(netMicro),\n sku: args.sku,\n playerId: args.playerId,\n txHash: MOCK_TX,\n chain: args.chain,\n createdAt: new Date().toISOString(),\n metadata: args.metadata,\n mock: true,\n };\n}\n\nexport function mockEntryPayment(args: {\n amountMicro: bigint;\n poolBps: number;\n seedBps: number;\n rakeBps: number;\n gameId: string;\n roundId: string;\n playerId: string;\n chain: Network;\n metadata?: Record<string, string>;\n}): Payment {\n const { poolMicro, seedMicro, rakeMicro } = computePoolSplit(\n args.amountMicro,\n args.poolBps,\n args.seedBps,\n args.rakeBps,\n );\n return {\n id: prefixedId(\"entry\"),\n status: \"confirmed\",\n kind: \"entry\",\n amount: formatMicroToUsd(args.amountMicro),\n fee: formatMicroToUsd(rakeMicro), // the 10% take\n net: formatMicroToUsd(poolMicro + seedMicro), // escrowed to the pool\n split: {\n pool: formatMicroToUsd(poolMicro),\n seed: formatMicroToUsd(seedMicro),\n rake: formatMicroToUsd(rakeMicro),\n },\n gameId: args.gameId,\n roundId: args.roundId,\n playerId: args.playerId,\n txHash: MOCK_TX,\n chain: args.chain,\n createdAt: new Date().toISOString(),\n metadata: args.metadata,\n mock: true,\n };\n}\n","/**\n * The Playmos client — `new Playmos({ apiKey })` → `pay()`, `enterRound()`,\n * `verify()`, `webhooks`, `payouts`, `agents`.\n *\n * Real behavior, no `\"mocked\"` status anywhere. The chain calls use the proven\n * EIP-5792 approve+call batch; `verify()` resolves by the service's on-chain\n * read; ids are ULIDs; inputs are validated client-side; idempotency is honored.\n */\n\nimport { ConfigError } from \"./errors.js\";\nimport { resolveEnv, USDC_ADDRESS, type ResolvedEnv } from \"./config.js\";\nimport { prefixedId } from \"./ids.js\";\nimport { requireField, validateAmount, validateMetadata } from \"./validation.js\";\nimport { computeIapSplit, computePoolSplit, formatMicroToUsd } from \"./money.js\";\nimport { createHttpClient, type HttpClient } from \"./http.js\";\nimport { resolveProvider, getAccount, walletAvailable } from \"./wallet.js\";\nimport { assertEnoughGas, sendCalls, waitForCalls } from \"./chain/batch.js\";\nimport { buildIapCalls, buildEntryCalls } from \"./chain/calls.js\";\nimport { mockIapPayment, mockEntryPayment } from \"./mock.js\";\nimport type {\n EnterRoundInput,\n Payment,\n PayInput,\n PlaymosConfig,\n VerifyResult,\n WebhookEvent,\n} from \"./types.js\";\n\n/** Fee tiers, keyed to who owns the game (spec §4). Contract-enforced on-chain;\n * these are the SDK's faithful preview of the split. */\nconst IAP_FEE_BPS = 100; // external studios → 1%\nconst POOL_BPS = 6000; // 60% this round's pool\nconst SEED_BPS = 3000; // 30% next round's seed\nconst RAKE_BPS = 1000; // 10% Playmos take\n\n/**\n * Shape the service returns from POST /payments with `settle: \"server\"` — the\n * sandbox server-settle path. The service signed + submitted the on-chain txn\n * itself, so `payment` is already confirmed with a real `txHash` (no client\n * signing). Tolerant to extra fields.\n */\ninterface ServerSettleResponse {\n payment: Payment & { splitBps?: { pool: number; seed: number; rake: number } };\n settledBy?: \"server\";\n signer?: `0x${string}`;\n}\n\n/** Shape the service returns from POST /payments. Tolerant to extra fields. */\ninterface CreateIntentResponse {\n payment: Payment;\n clientParams?: {\n contract?: \"playmosPay\" | \"prizePool\";\n contractAddress?: `0x${string}`;\n usdc?: `0x${string}`;\n // The service emits `amountMicro`; older shapes used `amountUnits`. Accept both.\n amountUnits?: string;\n amountMicro?: string;\n studio?: `0x${string}`;\n // The service emits `roundId` + `identity`; it SHOULD also emit the exact\n // `roundKey` string it will check via hasEntered (see integration seam #345).\n roundKey?: string;\n roundId?: string;\n identity?: string;\n paymasterUrl?: string;\n };\n}\n\nexport class Playmos {\n readonly config: PlaymosConfig;\n readonly env: ResolvedEnv;\n private readonly http: HttpClient;\n\n readonly webhooks = {\n /**\n * Webhook verification is server-only (it uses node:crypto) and no longer\n * ships in the browser entry (issue #9). On a backend, import it directly:\n * import { verifyWebhook } from \"@playmos/sdk/server\";\n */\n verify: (\n _rawBody: string | Buffer,\n _signatureHeader: string | string[] | undefined,\n _secret: string,\n ): WebhookEvent => {\n throw new ConfigError(\n 'playmos.webhooks.verify is server-only and no longer ships in the browser entry (issue #9). Use: import { verifyWebhook } from \"@playmos/sdk/server\"',\n { entry: \"@playmos/sdk/server\" },\n );\n },\n };\n\n readonly payouts = {\n /** Choose how the studio is paid: \"usdc\" (default) or \"fiat\" (Bridge). */\n setMode: (mode: \"usdc\" | \"fiat\"): Promise<{ mode: \"usdc\" | \"fiat\" }> =>\n this.http.post(\"/payouts/mode\", { mode }),\n /** Create a Bridge KYC onboarding link (fiat payout). */\n createOnboardingLink: (): Promise<{ url: string }> =>\n this.http.post(\"/payouts/onboarding_link\", {}),\n };\n\n readonly agents = {\n /** Assign a wallet to any identity (incl. an AI NPC). Idempotent by agentId. */\n createWallet: (input: { agentId: string }): Promise<{ agentId: string; address: `0x${string}`; chain: string }> => {\n requireField(input?.agentId, \"agentId\");\n return this.http.post(\"/agents/wallets\", { agentId: input.agentId });\n },\n /** Agent↔agent USDC transfer; the configured taxBps is skimmed to Playmos. */\n pay: (input: { from: string; to: string; amount: string }): Promise<{ id: string; taxUSD: string; status: string }> => {\n requireField(input?.from, \"from\");\n requireField(input?.to, \"to\");\n validateAmount(input?.amount);\n return this.http.post(\"/agents/pay\", input);\n },\n };\n\n constructor(config: PlaymosConfig) {\n this.config = config;\n this.env = resolveEnv(config.apiKey, config.network, config.apiBaseUrl);\n this.http = createHttpClient(this.env.apiBaseUrl, config.apiKey);\n }\n\n /** Connect the player's wallet and return their address. */\n async connect(): Promise<`0x${string}`> {\n return getAccount(resolveProvider(this.config.wallet));\n }\n\n /**\n * A DROP-IN payment provider for game kits that expect `{ connect, payEntry }`\n * (e.g. the Playmos game-hub kit). No custom adapter needed — the game dev just\n * does: `gameConfig.paymentProvider = playmos.entryProvider({ gameId })`.\n * The kit hands `payEntry` its own on-chain `roundKey` + `identity`; we thread\n * them straight through so the on-chain entry and the game server's `hasEntered`\n * check line up.\n */\n entryProvider(cfg: { gameId: string }): {\n connect(): Promise<string>;\n payEntry(req: { roundKey: string; identity: string; wallet: string; entryUnits: bigint }): Promise<{\n paymentId: string;\n status: \"CONFIRMED\" | \"FAILED\" | \"PENDING\";\n txHash?: string;\n onchain: boolean;\n /** The on-chain identity actually entered — reconcile with `hasEntered`. */\n identity?: string;\n }>;\n } {\n return {\n connect: () => this.connect(),\n payEntry: async (req) => {\n const entry = await this.enterRound({\n gameId: cfg.gameId,\n roundId: req.roundKey, // the round the server verifies against\n roundKey: req.roundKey,\n identity: req.identity,\n amount: formatMicroToUsd(req.entryUnits),\n playerId: req.wallet,\n });\n const status =\n entry.status === \"confirmed\" ? \"CONFIRMED\" : entry.status === \"failed\" ? \"FAILED\" : \"PENDING\";\n return { paymentId: entry.id, status, txHash: entry.txHash, onchain: true, identity: entry.identity };\n },\n };\n }\n\n /** External-studio IAP (1%). Returns a real confirmed Payment with a txHash. */\n async pay(input: PayInput): Promise<Payment> {\n const amountMicro = validateAmount(input.amount);\n requireField(input.sku, \"sku\");\n requireField(input.playerId, \"playerId\");\n const metadata = validateMetadata(input.metadata);\n const idempotencyKey = input.idempotencyKey ?? prefixedId(\"idem\");\n\n if (this.config.mock) {\n return mockIapPayment({\n amountMicro,\n feeBps: IAP_FEE_BPS,\n sku: input.sku,\n playerId: input.playerId,\n chain: this.env.network,\n metadata,\n });\n }\n\n // Auto no-wallet routing (0.1.4): on a test/sandbox key with NO wallet\n // available, let the SERVICE sign + submit on-chain (server-settle) so the\n // developer needs zero wallet/crypto. Sandbox-only — a live key with no\n // wallet keeps today's behavior (the client-signed path throws below).\n if (this.env.isTest && !(await walletAvailable(this.config.wallet))) {\n const res = await this.http.post<ServerSettleResponse>(\n \"/payments\",\n { kind: \"iap\", amount: input.amount, sku: input.sku, playerId: input.playerId, gameId: input.gameId, studio: input.studio, metadata, settle: \"server\" },\n { idempotencyKey },\n );\n return this.mapServerPayment(res.payment, \"iap\", amountMicro);\n }\n\n const intent = await this.http.post<CreateIntentResponse>(\n \"/payments\",\n { kind: \"iap\", amount: input.amount, sku: input.sku, playerId: input.playerId, gameId: input.gameId, studio: input.studio, metadata },\n { idempotencyKey },\n );\n\n const provider = resolveProvider(this.config.wallet);\n if (this.config.gas?.mode === \"player\") {\n const from0 = await getAccount(provider);\n await assertEnoughGas(provider, from0);\n }\n const from = await getAccount(provider);\n\n const usdc = intent.clientParams?.usdc ?? this.config.contracts?.usdc ?? USDC_ADDRESS[this.env.network];\n const playmosPay = intent.clientParams?.contractAddress ?? this.config.contracts?.playmosPay;\n const studio = intent.clientParams?.studio ?? input.studio;\n if (!playmosPay) throw new ConfigError(\"No PlaymosPay contract address (service intent + config.contracts both empty).\");\n if (!studio) throw new ConfigError(\"No studio payout address for this payment.\");\n const amountUnits = this.resolveUnits(intent, amountMicro);\n\n const calls = buildIapCalls({ usdc, playmosPay, paymentId: intent.payment.id, studio, amountUnits });\n const { id: callsId } = await sendCalls(provider, from, this.env.chainId, calls, this.sponsorUrl(intent));\n const { txHash } = await waitForCalls(provider, callsId);\n\n return this.settle(intent.payment.id, txHash);\n }\n\n /** Playmos-owned skill-game entry (10%, 60/30/10 prize pool). Closes #343. */\n async enterRound(input: EnterRoundInput): Promise<Payment> {\n const amountMicro = validateAmount(input.amount);\n requireField(input.gameId, \"gameId\");\n requireField(input.roundId, \"roundId\");\n requireField(input.playerId, \"playerId\");\n const metadata = validateMetadata(input.metadata);\n const idempotencyKey = input.idempotencyKey ?? prefixedId(\"idem\");\n\n if (this.config.mock) {\n return mockEntryPayment({\n amountMicro,\n poolBps: POOL_BPS,\n seedBps: SEED_BPS,\n rakeBps: RAKE_BPS,\n gameId: input.gameId,\n roundId: input.roundId,\n playerId: input.playerId,\n chain: this.env.network,\n metadata,\n });\n }\n\n // Auto no-wallet routing (0.1.4): test/sandbox key + NO wallet → the service\n // settles the entry on-chain for us (server-settle). entryProvider().payEntry\n // inherits this automatically since it calls enterRound(). Sandbox-only.\n if (this.env.isTest && !(await walletAvailable(this.config.wallet))) {\n const res = await this.http.post<ServerSettleResponse>(\n \"/payments\",\n { kind: \"entry\", amount: input.amount, gameId: input.gameId, roundId: input.roundKey ?? input.roundId, identity: input.identity, playerId: input.playerId, metadata, settle: \"server\" },\n { idempotencyKey },\n );\n const payment = this.mapServerPayment(res.payment, \"entry\", amountMicro);\n // Prefer the identity the caller pinned; else whatever the service echoed.\n if (input.identity) payment.identity = input.identity;\n return payment;\n }\n\n const intent = await this.http.post<CreateIntentResponse>(\n \"/payments\",\n // When the game supplies its own roundKey, that IS the round the service\n // stores + verifies against (so on-chain enter and server hasEntered align).\n { kind: \"entry\", amount: input.amount, gameId: input.gameId, roundId: input.roundKey ?? input.roundId, identity: input.identity, playerId: input.playerId, metadata },\n { idempotencyKey },\n );\n\n const provider = resolveProvider(this.config.wallet);\n if (this.config.gas?.mode === \"player\") {\n const from0 = await getAccount(provider);\n await assertEnoughGas(provider, from0);\n }\n const from = await getAccount(provider);\n\n const usdc = intent.clientParams?.usdc ?? this.config.contracts?.usdc ?? USDC_ADDRESS[this.env.network];\n const prizePool = intent.clientParams?.contractAddress ?? this.config.contracts?.prizePool;\n if (!prizePool) throw new ConfigError(\"No PrizePool contract address for this game (service intent + config.contracts both empty).\");\n const roundKey = input.roundKey ?? intent.clientParams?.roundKey ?? intent.clientParams?.roundId ?? `${input.gameId}:${input.roundId}`;\n const identity = input.identity ?? intent.clientParams?.identity ?? `${from}#${idempotencyKey}`;\n const amountUnits = this.resolveUnits(intent, amountMicro);\n\n const calls = buildEntryCalls({ usdc, prizePool, roundKey, identity, amountUnits });\n const { id: callsId } = await sendCalls(provider, from, this.env.chainId, calls, this.sponsorUrl(intent));\n const { txHash } = await waitForCalls(provider, callsId);\n\n // Surface the EXACT on-chain identity we entered with so the caller can\n // reconcile against their server's `hasEntered(roundKey, identity)`.\n const payment = await this.settle(intent.payment.id, txHash);\n payment.identity = identity;\n return payment;\n }\n\n /** Verify a payment by the service's on-chain read (spec §6.1). Idempotent. */\n async verify(paymentId: string): Promise<VerifyResult> {\n requireField(paymentId, \"paymentId\");\n return this.http.get<VerifyResult>(`/payments/${encodeURIComponent(paymentId)}`);\n }\n\n // ---- internals ---------------------------------------------------------\n\n /**\n * Map a server-settled payment (from the `settle: \"server\"` response) into the\n * SDK's `Payment` shape. The service already signed + confirmed on-chain, so we\n * pass its authoritative `status`/`txHash`/amounts straight through and, for an\n * entry, derive the 60/30/10 USD `split` locally (exactly as the mock + the\n * contract compute it) from the parsed amount.\n */\n private mapServerPayment(\n p: ServerSettleResponse[\"payment\"],\n kind: \"iap\" | \"entry\",\n amountMicro: bigint,\n ): Payment {\n const payment: Payment = {\n id: p.id,\n status: p.status,\n kind: p.kind ?? kind,\n amount: p.amount,\n fee: p.fee,\n net: p.net,\n sku: p.sku,\n roundId: p.roundId,\n gameId: p.gameId,\n playerId: p.playerId ?? \"\",\n txHash: p.txHash,\n chain: this.env.network,\n createdAt: p.createdAt ?? new Date().toISOString(),\n metadata: p.metadata,\n identity: p.identity,\n };\n if ((p.kind ?? kind) === \"entry\") {\n const { poolMicro, seedMicro, rakeMicro } = computePoolSplit(amountMicro, POOL_BPS, SEED_BPS, RAKE_BPS);\n payment.split = {\n pool: formatMicroToUsd(poolMicro),\n seed: formatMicroToUsd(seedMicro),\n rake: formatMicroToUsd(rakeMicro),\n };\n }\n return payment;\n }\n\n /** Prefer the service's authoritative micro-USDC amount; fall back to the\n * locally-parsed value if the service didn't echo one. */\n private resolveUnits(intent: CreateIntentResponse, local: bigint): bigint {\n const fromServer = intent.clientParams?.amountUnits ?? intent.clientParams?.amountMicro;\n return fromServer ? BigInt(fromServer) : local;\n }\n\n private sponsorUrl(intent: CreateIntentResponse): string | undefined {\n if (this.config.gas?.mode === \"player\") return undefined;\n return this.config.gas?.paymasterUrl ?? intent.clientParams?.paymasterUrl;\n }\n\n /**\n * After the batch lands, resolve the authoritative status via the service's\n * on-chain read. Polls briefly; returns the merged Payment with the real txHash.\n */\n private async settle(paymentId: string, txHash?: `0x${string}`, timeoutMs = 30_000): Promise<Payment> {\n // Report the settlement txHash we observed locally so the service can VERIFY\n // IT ON-CHAIN. We only say WHICH tx landed; the service reads the chain and\n // decides confirmed/failed (trust stays on-chain — anti-#337). Non-fatal on\n // failure: fall back to polling verify.\n if (txHash) {\n try {\n await this.http.post(`/payments/${encodeURIComponent(paymentId)}/tx`, { txHash });\n } catch {\n /* ignore — the verify poll below still resolves the authoritative status */\n }\n }\n const deadline = Date.now() + timeoutMs;\n let last: VerifyResult | undefined;\n while (Date.now() < deadline) {\n last = await this.verify(paymentId);\n if (last.status === \"confirmed\" || last.status === \"failed\") break;\n // If the service can't read the chain (degraded), polling will never\n // confirm — return the honest cached status now instead of spinning.\n if (last.chainReads === \"degraded\" || last.verifiedVia === \"degraded\") break;\n await new Promise((r) => setTimeout(r, 1200));\n }\n return {\n id: paymentId,\n status: last?.status ?? \"pending\",\n kind: last?.roundId ? \"entry\" : \"iap\",\n amount: last?.amount ?? \"0\",\n fee: last?.fee ?? \"0\",\n net: last?.net ?? \"0\",\n sku: last?.sku,\n roundId: last?.roundId,\n playerId: last?.playerId ?? \"\",\n txHash: last?.txHash ?? txHash,\n chain: this.env.network,\n createdAt: new Date().toISOString(),\n };\n }\n}\n\n/** Local preview of a split without any network — handy for UIs. */\nexport function previewIapSplit(amount: string): { amount: string; fee: string; net: string } {\n const micro = validateAmount(amount);\n const { feeMicro, netMicro } = computeIapSplit(micro, IAP_FEE_BPS);\n return { amount: formatMicroToUsd(micro), fee: formatMicroToUsd(feeMicro), net: formatMicroToUsd(netMicro) };\n}\n\n/** Local preview of the 60/30/10 entry split without any network. */\nexport function previewPoolSplit(amount: string): { amount: string; pool: string; seed: string; rake: string } {\n const micro = validateAmount(amount);\n const { poolMicro, seedMicro, rakeMicro } = computePoolSplit(micro, POOL_BPS, SEED_BPS, RAKE_BPS);\n return {\n amount: formatMicroToUsd(micro),\n pool: formatMicroToUsd(poolMicro),\n seed: formatMicroToUsd(seedMicro),\n rake: formatMicroToUsd(rakeMicro),\n };\n}\n"]}
|