@provable-games/budokan-sdk 0.1.22 → 0.1.24
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 +32 -0
- package/dist/index.cjs +1494 -320
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +538 -3
- package/dist/index.d.ts +538 -3
- package/dist/index.js +1475 -322
- package/dist/index.js.map +1 -1
- package/dist/{client-DlXvzneQ.d.cts → player-C2GE9Lop.d.cts} +65 -5
- package/dist/{client-DlXvzneQ.d.ts → player-C2GE9Lop.d.ts} +65 -5
- package/dist/react.cjs +1194 -352
- package/dist/react.cjs.map +1 -1
- package/dist/react.d.cts +45 -2
- package/dist/react.d.ts +45 -2
- package/dist/react.js +1195 -354
- package/dist/react.js.map +1 -1
- package/package.json +5 -7
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { T as Tournament, P as PrizeAggregation, a as Prize, b as PaginatedResult, Q as QualificationEntry, R as Registration, c as RewardClaim, d as RewardClaimSummary, e as TournamentListParams, f as PlatformStats, g as PrizeStats, W as WSSubscribeOptions, h as WSEventHandler } from './
|
|
2
|
-
export { B as BudokanClient, i as BudokanClientConfig, C as ConnectionMode, j as ConnectionStatus, k as ConnectionStatusState, D as DataSource, G as GameConfig, L as LeaderboardConfig, l as LeaderboardEntry, m as Phase, S as Schedule,
|
|
1
|
+
import { T as Tournament, P as PrizeAggregation, a as Prize, b as PaginatedResult, Q as QualificationEntry, R as Registration, c as RewardClaim, d as RewardClaimSummary, e as TournamentListParams, f as PlatformStats, g as PrizeStats, W as WSSubscribeOptions, h as WSEventHandler } from './player-C2GE9Lop.js';
|
|
2
|
+
export { B as BudokanClient, i as BudokanClientConfig, C as ConnectionMode, j as ConnectionStatus, k as ConnectionStatusState, D as DataSource, G as GameConfig, L as LeaderboardConfig, l as LeaderboardEntry, m as Phase, n as PlayerPlacement, o as PlayerRewards, S as Schedule, p as WSChannel, q as WSEventMessage, r as WSMessage, s as WSSubscribeMessage, t as WSUnsubscribeMessage, u as createBudokanClient } from './player-C2GE9Lop.js';
|
|
3
3
|
export { EntryFee } from '@provable-games/metagame-sdk';
|
|
4
4
|
import 'starknet';
|
|
5
5
|
|
|
@@ -189,5 +189,540 @@ interface ChainConfig {
|
|
|
189
189
|
}
|
|
190
190
|
declare const CHAINS: Record<string, ChainConfig>;
|
|
191
191
|
declare function getChainConfig(chain: string): ChainConfig | undefined;
|
|
192
|
+
/**
|
|
193
|
+
* Voyager block-explorer base URL for the chain. Used to build
|
|
194
|
+
* shareable links for tx hashes and contracts in chat / Discord / CLI
|
|
195
|
+
* surfaces. Unknown chains fall back to mainnet — Voyager 404s
|
|
196
|
+
* gracefully and the caller can still click the link.
|
|
197
|
+
*/
|
|
198
|
+
declare function explorerBaseUrl(chain: string): string;
|
|
199
|
+
/** Voyager URL for a transaction hash. */
|
|
200
|
+
declare function explorerTxUrl(chain: string, txHash: string): string;
|
|
201
|
+
/** Voyager URL for a contract / account address. */
|
|
202
|
+
declare function explorerAddressUrl(chain: string, address: string): string;
|
|
203
|
+
/**
|
|
204
|
+
* Canonical budokan.gg URL for a tournament. The `network` query param
|
|
205
|
+
* tells the client which chain to load — important when sharing sepolia
|
|
206
|
+
* tournaments since the site defaults to mainnet.
|
|
207
|
+
*/
|
|
208
|
+
declare function tournamentPageUrl(chain: string, tournamentId: string | number | bigint): string;
|
|
209
|
+
|
|
210
|
+
/** Subset of chain identifiers the whitelist covers. */
|
|
211
|
+
type WhitelistChain = "mainnet" | "sepolia";
|
|
212
|
+
interface WhitelistedGame {
|
|
213
|
+
/** Canonical 0x-prefixed, 66-char lowercase contract address. */
|
|
214
|
+
contractAddress: string;
|
|
215
|
+
/** Display name. */
|
|
216
|
+
name: string;
|
|
217
|
+
/** Optional remote logo URL. The SDK never bundles binary assets — host externally. */
|
|
218
|
+
imageUrl?: string;
|
|
219
|
+
/** Game's homepage / landing URL. */
|
|
220
|
+
url?: string;
|
|
221
|
+
/** Direct-play URL template. May include `{tokenId}`. */
|
|
222
|
+
playUrl?: string;
|
|
223
|
+
/** Optional spectator URLs. */
|
|
224
|
+
watchLink?: string;
|
|
225
|
+
replayLink?: string;
|
|
226
|
+
/** True if the game requires a Cartridge Controller to play. */
|
|
227
|
+
controllerOnly?: boolean;
|
|
228
|
+
/** Hide from default listings while keeping the metadata around. */
|
|
229
|
+
disabled?: boolean;
|
|
230
|
+
/** Minimum entry fee floor in USD, used as a UX hint at tournament-create time. */
|
|
231
|
+
minEntryFeeUsd?: number;
|
|
232
|
+
/** Recommended ERC-20 token for entry fee on this chain. */
|
|
233
|
+
defaultEntryFeeToken?: string;
|
|
234
|
+
/** Game-creator share of entry fee (basis-points-style — `5` means 5%). */
|
|
235
|
+
defaultGameFeePercentage?: number;
|
|
236
|
+
/** Approximate gas cost per entry, in USD — UX hint only. */
|
|
237
|
+
averageGasCostUsd?: number;
|
|
238
|
+
/** Some game tokens use animated SVG that needs `<object>` rather than `<img>`. */
|
|
239
|
+
objectImage?: boolean;
|
|
240
|
+
/**
|
|
241
|
+
* Score ordering. `true` = lower-is-better (golf-style), `false` = higher-
|
|
242
|
+
* is-better (points-style). Defaults to false when omitted — most games
|
|
243
|
+
* are points-based.
|
|
244
|
+
*/
|
|
245
|
+
leaderboardAscending?: boolean;
|
|
246
|
+
/**
|
|
247
|
+
* Whether the game's score is only valid once the game is in a completed
|
|
248
|
+
* (e.g. dead, finished) state. Tournament-creation UIs hide this question
|
|
249
|
+
* when the property of the game is known. Defaults to false.
|
|
250
|
+
*/
|
|
251
|
+
leaderboardGameMustBeOver?: boolean;
|
|
252
|
+
}
|
|
253
|
+
/**
|
|
254
|
+
* Whitelisted games for a chain, sorted by name with disabled entries last.
|
|
255
|
+
*
|
|
256
|
+
* Returns a frozen copy — mutations don't bleed back into the module state.
|
|
257
|
+
*/
|
|
258
|
+
declare function getWhitelistedGames(chain: WhitelistChain): WhitelistedGame[];
|
|
259
|
+
/**
|
|
260
|
+
* Look up a single whitelisted game by contract address. Address is normalized
|
|
261
|
+
* before comparison so callers can pass any padding.
|
|
262
|
+
*/
|
|
263
|
+
declare function findWhitelistedGame(chain: WhitelistChain, contractAddress: string): WhitelistedGame | undefined;
|
|
264
|
+
/** True if the given game is on the whitelist. */
|
|
265
|
+
declare function isGameWhitelisted(chain: WhitelistChain, contractAddress: string): boolean;
|
|
266
|
+
/**
|
|
267
|
+
* Defaults block — what UI surfaces should pre-fill when the user picks this
|
|
268
|
+
* game. Falls back to per-chain sensible defaults (STRK as fee token, 1% fee,
|
|
269
|
+
* $0.25 minimum) when the game isn't whitelisted, so callers don't have to
|
|
270
|
+
* special-case missing entries.
|
|
271
|
+
*/
|
|
272
|
+
interface GameDefaults {
|
|
273
|
+
minEntryFeeUsd: number;
|
|
274
|
+
defaultEntryFeeToken: string;
|
|
275
|
+
defaultGameFeePercentage: number;
|
|
276
|
+
averageGasCostUsd: number | undefined;
|
|
277
|
+
/** Inherited leaderboard ordering (true = lower wins, false = higher wins). */
|
|
278
|
+
leaderboardAscending: boolean;
|
|
279
|
+
/** Inherited "must finish game before submitting" flag. */
|
|
280
|
+
leaderboardGameMustBeOver: boolean;
|
|
281
|
+
}
|
|
282
|
+
declare function getGameDefaults(chain: WhitelistChain, contractAddress: string): GameDefaults;
|
|
283
|
+
|
|
284
|
+
/**
|
|
285
|
+
* Calldata builders for Budokan's on-chain entrypoints.
|
|
286
|
+
*
|
|
287
|
+
* Each builder is a pure function that returns a starknet.js `Call` —
|
|
288
|
+
* `{ contractAddress, entrypoint, calldata }` — without signing or
|
|
289
|
+
* executing anything. Callers pass the returned Call to
|
|
290
|
+
* `account.execute([...])` themselves so this module is decoupled from
|
|
291
|
+
* how an integrator obtains an account (controller, sessions, agent
|
|
292
|
+
* wallets, signing servers).
|
|
293
|
+
*
|
|
294
|
+
* Cairo encoding gotchas this module hides from callers:
|
|
295
|
+
* - Option<T> and custom enums must be wrapped in `CairoOption` /
|
|
296
|
+
* `CairoCustomEnum`. Plain `{ type, variant }` objects look right but
|
|
297
|
+
* CallData.compile treats them as generic structs and serializes the
|
|
298
|
+
* type-name string as a ByteArray — i.e. produces garbage calldata.
|
|
299
|
+
* - `Metadata.description` is a ByteArray (3+ felts). A plain JS
|
|
300
|
+
* string becomes a single felt and the deserializer reverts with
|
|
301
|
+
* "Failed to deserialize param".
|
|
302
|
+
* - Cairo enum variant tags are 0-indexed in declaration order; the
|
|
303
|
+
* manually-built calldata in enter/claim/submit follows this order
|
|
304
|
+
* exactly. References:
|
|
305
|
+
* contracts/packages/interfaces/src/budokan.cairo (RewardType,
|
|
306
|
+
* EntryFeeRewardType, EntryRequirementType, Distribution)
|
|
307
|
+
* game-components/.../prize.cairo (PrizeType)
|
|
308
|
+
*
|
|
309
|
+
* Used today by the Telegram bot in
|
|
310
|
+
* `examples/telegram-controller-bot/`. Any other integration that needs
|
|
311
|
+
* to drive the same contract (a Discord bot, a CLI, agent code) should
|
|
312
|
+
* import from here so we don't fork the encoding logic again.
|
|
313
|
+
*/
|
|
314
|
+
interface Call {
|
|
315
|
+
contractAddress: string;
|
|
316
|
+
entrypoint: string;
|
|
317
|
+
calldata: string[];
|
|
318
|
+
}
|
|
319
|
+
/**
|
|
320
|
+
* Shape of the entry-fee distribution. Mirrors the Cairo `Distribution`
|
|
321
|
+
* enum (Linear / Exponential / Uniform / Custom). The integer `weight`
|
|
322
|
+
* is in client units — the encoder scales it ×10 to match the on-chain
|
|
323
|
+
* convention the budokan client uses, so distributions created via this
|
|
324
|
+
* SDK and via budokan.gg render identically.
|
|
325
|
+
*/
|
|
326
|
+
type DistributionSpec = {
|
|
327
|
+
kind: "linear";
|
|
328
|
+
weight: number;
|
|
329
|
+
} | {
|
|
330
|
+
kind: "exponential";
|
|
331
|
+
weight: number;
|
|
332
|
+
} | {
|
|
333
|
+
kind: "uniform";
|
|
334
|
+
};
|
|
335
|
+
interface EntryFeeArgs {
|
|
336
|
+
tokenAddress: string;
|
|
337
|
+
/** Raw u128 amount in smallest token units (decimal string). */
|
|
338
|
+
amount: string;
|
|
339
|
+
/** All shares are basis points (0–10000). Sum + leaderboard pool = 10000. */
|
|
340
|
+
tournamentCreatorShare: number;
|
|
341
|
+
gameCreatorShare: number;
|
|
342
|
+
refundShare: number;
|
|
343
|
+
distribution: DistributionSpec;
|
|
344
|
+
/** Number of top placements that share the leaderboard pool. */
|
|
345
|
+
distributionCount: number;
|
|
346
|
+
}
|
|
347
|
+
/**
|
|
348
|
+
* Entry-requirement gating. Two variants on the chain's
|
|
349
|
+
* EntryRequirementType enum:
|
|
350
|
+
* - token: ContractAddress — must own a token from this contract
|
|
351
|
+
* - extension: ExtensionConfig — validator contract + config Span
|
|
352
|
+
*
|
|
353
|
+
* For "extension" callers build the `config` Span<felt252> in the exact
|
|
354
|
+
* felt order the target validator's `add_config` expects (see
|
|
355
|
+
* `src/extensions` for preset builders that produce this for the
|
|
356
|
+
* shared deployed validators).
|
|
357
|
+
*/
|
|
358
|
+
type EntryRequirementSpec = {
|
|
359
|
+
kind: "token";
|
|
360
|
+
tokenAddress: string;
|
|
361
|
+
} | {
|
|
362
|
+
kind: "extension";
|
|
363
|
+
address: string;
|
|
364
|
+
config: string[];
|
|
365
|
+
};
|
|
366
|
+
interface EntryRequirementArgs {
|
|
367
|
+
/** Max entries per qualifying token / extension match. */
|
|
368
|
+
entryLimit: number;
|
|
369
|
+
type: EntryRequirementSpec;
|
|
370
|
+
}
|
|
371
|
+
interface EnterTournamentArgs {
|
|
372
|
+
tournamentId: string;
|
|
373
|
+
/**
|
|
374
|
+
* Mint recipient. Encoded as `Option<ContractAddress>` — omit for
|
|
375
|
+
* `None` (the contract defaults the mint to the caller).
|
|
376
|
+
*/
|
|
377
|
+
playerAddress?: string;
|
|
378
|
+
/** Optional felt252 short string (≤31 ASCII bytes). Omit → Option::None. */
|
|
379
|
+
playerName?: string;
|
|
380
|
+
/**
|
|
381
|
+
* Third-party qualifier to claim, as `Option<ContractAddress>`. Omit for
|
|
382
|
+
* `None` (caller is the qualifier — the common path). Only needed for
|
|
383
|
+
* sponsor flows against gated tournaments.
|
|
384
|
+
*/
|
|
385
|
+
qualifier?: string;
|
|
386
|
+
/**
|
|
387
|
+
* `entry_fee_pay_params` (`Option<Span<felt252>>`). Required only for
|
|
388
|
+
* tournaments with an `EntryFeeKind::Extension` fee — the felts the fee
|
|
389
|
+
* extension expects. Omit for the built-in fee flow (Option::None).
|
|
390
|
+
*/
|
|
391
|
+
entryFeePayParams?: string[];
|
|
392
|
+
salt?: number;
|
|
393
|
+
metadataValue?: number;
|
|
394
|
+
}
|
|
395
|
+
interface CreateTournamentArgs {
|
|
396
|
+
creatorRewardsAddress: string;
|
|
397
|
+
/** ≤31 ASCII bytes (felt252 short string). */
|
|
398
|
+
name: string;
|
|
399
|
+
description: string;
|
|
400
|
+
gameAddress: string;
|
|
401
|
+
settingsId: number;
|
|
402
|
+
schedule: {
|
|
403
|
+
registrationStartDelay: number;
|
|
404
|
+
registrationEndDelay: number;
|
|
405
|
+
gameStartDelay: number;
|
|
406
|
+
gameEndDelay: number;
|
|
407
|
+
submissionDuration: number;
|
|
408
|
+
};
|
|
409
|
+
leaderboard: {
|
|
410
|
+
ascending: boolean;
|
|
411
|
+
gameMustBeOver: boolean;
|
|
412
|
+
};
|
|
413
|
+
/** Encoded as Option::Some(EntryFeeKind::BuiltIn(EntryFee)) when set. */
|
|
414
|
+
entryFee?: EntryFeeArgs;
|
|
415
|
+
/** Encoded as Option::Some(EntryRequirement) on chain when set. */
|
|
416
|
+
entryRequirement?: EntryRequirementArgs;
|
|
417
|
+
salt?: number;
|
|
418
|
+
metadataValue?: number;
|
|
419
|
+
}
|
|
420
|
+
/**
|
|
421
|
+
* Token prize payload. Mirrors the Cairo `TokenTypeData` enum.
|
|
422
|
+
*
|
|
423
|
+
* - `erc20` — fungible. `amount` is required; `distribution` optional
|
|
424
|
+
* (undefined → single winner-takes-all payout). When `distribution`
|
|
425
|
+
* is set, `distributionCount` is required (number of paid positions).
|
|
426
|
+
* - `erc721` — single NFT. `tokenId` is the u128 id of the token the
|
|
427
|
+
* sponsor is escrowing.
|
|
428
|
+
*/
|
|
429
|
+
type TokenTypeSpec = {
|
|
430
|
+
kind: "erc20";
|
|
431
|
+
/** Raw u128 amount (decimal string). */
|
|
432
|
+
amount: string;
|
|
433
|
+
distribution?: DistributionSpec;
|
|
434
|
+
distributionCount?: number;
|
|
435
|
+
} | {
|
|
436
|
+
kind: "erc721";
|
|
437
|
+
tokenId: string;
|
|
438
|
+
};
|
|
439
|
+
/**
|
|
440
|
+
* Tagged union mirroring the on-chain `Prize` enum.
|
|
441
|
+
*
|
|
442
|
+
* - `config` — built-in path: sponsor escrows an ERC20/ERC721 prize via
|
|
443
|
+
* the budokan PrizeComponent; `position` selects a leaderboard slot
|
|
444
|
+
* for non-distributed prizes (ignored for distributed ERC20).
|
|
445
|
+
* - `extension` — external `IPrizeExtension`: budokan forwards the
|
|
446
|
+
* `config` blob to `IPrizeExtension.add_prize`. `position` is ignored
|
|
447
|
+
* (the extension owns position semantics).
|
|
448
|
+
*/
|
|
449
|
+
type PrizeSpec = {
|
|
450
|
+
kind: "token";
|
|
451
|
+
tokenAddress: string;
|
|
452
|
+
tokenType: TokenTypeSpec;
|
|
453
|
+
/** Leaderboard slot for single (non-distributed) prizes. Omit for distributed. */
|
|
454
|
+
position?: number;
|
|
455
|
+
} | {
|
|
456
|
+
kind: "extension";
|
|
457
|
+
/** Address of the contract implementing `IPrizeExtension`. */
|
|
458
|
+
address: string;
|
|
459
|
+
/** Opaque payload forwarded to `IPrizeExtension.add_prize`. */
|
|
460
|
+
config: string[];
|
|
461
|
+
};
|
|
462
|
+
interface AddPrizeArgs {
|
|
463
|
+
tournamentId: string;
|
|
464
|
+
prize: PrizeSpec;
|
|
465
|
+
}
|
|
466
|
+
/**
|
|
467
|
+
* Tagged union mirroring the Cairo `RewardType` enum hierarchy:
|
|
468
|
+
*
|
|
469
|
+
* variant 0: Prize(PrizeClaim)
|
|
470
|
+
* PrizeClaim variant 0: Token(PrizeType)
|
|
471
|
+
* PrizeType variant 0: Single(u64)
|
|
472
|
+
* PrizeType variant 1: Distributed((u64, u8))
|
|
473
|
+
* PrizeClaim variant 1: Extension({prize_id, position, payout_params})
|
|
474
|
+
* variant 1: EntryFee(EntryFeeClaim)
|
|
475
|
+
* EntryFeeClaim variant 0: Token(EntryFeeRewardType)
|
|
476
|
+
* EntryFeeRewardType variant 0: Position(u32)
|
|
477
|
+
* EntryFeeRewardType variant 1: TournamentCreator
|
|
478
|
+
* EntryFeeRewardType variant 2: GameCreator
|
|
479
|
+
* EntryFeeRewardType variant 3: Refund(felt252)
|
|
480
|
+
* EntryFeeClaim variant 1: Extension(ExtensionEntryFeeClaim)
|
|
481
|
+
*
|
|
482
|
+
* Extension claims are pure pass-through on the host: budokan forwards
|
|
483
|
+
* `(token_id, payout_params)` to the extension and lets it resolve
|
|
484
|
+
* recipient + eligibility from its own state. Callers don't supply
|
|
485
|
+
* recipient or position — the extension derives them.
|
|
486
|
+
*
|
|
487
|
+
* Conventions:
|
|
488
|
+
* - `tokenId` is the game token claiming. Positional extensions
|
|
489
|
+
* (NFTPrize, NFTEntryFee) use it to look up the leaderboard
|
|
490
|
+
* position; ownership-based extensions use it to derive the
|
|
491
|
+
* recipient via `owner_of`.
|
|
492
|
+
* - `tokenId: undefined` signals a non-claim flow (sponsor refund,
|
|
493
|
+
* dao distribution, raffle draw). The extension extracts whatever
|
|
494
|
+
* it needs from `payoutParams` / `claimParams` — e.g. NFTPrize
|
|
495
|
+
* reads `payoutParams[0]` as the slot index to refund.
|
|
496
|
+
*/
|
|
497
|
+
type RewardType = {
|
|
498
|
+
kind: "prize_single";
|
|
499
|
+
prizeId: string;
|
|
500
|
+
} | {
|
|
501
|
+
kind: "prize_distributed";
|
|
502
|
+
prizeId: string;
|
|
503
|
+
payoutPosition: number;
|
|
504
|
+
} | {
|
|
505
|
+
kind: "prize_extension";
|
|
506
|
+
prizeId: string;
|
|
507
|
+
/**
|
|
508
|
+
* Game token claiming the prize, or undefined for non-claim flows
|
|
509
|
+
* (sponsor refunds, raffle draws, etc.).
|
|
510
|
+
*/
|
|
511
|
+
tokenId?: string;
|
|
512
|
+
payoutParams: string[];
|
|
513
|
+
} | {
|
|
514
|
+
kind: "entry_fee_position";
|
|
515
|
+
position: number;
|
|
516
|
+
} | {
|
|
517
|
+
kind: "entry_fee_tournament_creator";
|
|
518
|
+
} | {
|
|
519
|
+
kind: "entry_fee_game_creator";
|
|
520
|
+
} | {
|
|
521
|
+
kind: "entry_fee_refund";
|
|
522
|
+
tokenId: string;
|
|
523
|
+
} | {
|
|
524
|
+
kind: "entry_fee_extension";
|
|
525
|
+
/**
|
|
526
|
+
* Game token claiming the fee-pool share, or undefined for
|
|
527
|
+
* non-claim flows (sponsor refunds, creator shares, etc.).
|
|
528
|
+
*/
|
|
529
|
+
tokenId?: string;
|
|
530
|
+
claimParams: string[];
|
|
531
|
+
};
|
|
532
|
+
/** Standard ERC20 `approve(spender, amount)` call. */
|
|
533
|
+
declare function buildErc20ApproveCall(tokenAddress: string, spender: string, amount: string): Call;
|
|
534
|
+
/**
|
|
535
|
+
* `enter_tournament(tournament_id: u64, player_name: Option<felt252>,
|
|
536
|
+
* player_address: Option<ContractAddress>,
|
|
537
|
+
* qualifier: Option<ContractAddress>,
|
|
538
|
+
* qualification: Option<QualificationProof>,
|
|
539
|
+
* entry_fee_pay_params: Option<Span<felt252>>,
|
|
540
|
+
* salt: u16, metadata_value: u16)`
|
|
541
|
+
*
|
|
542
|
+
* Targets the current budokan contract (#264/#269). `qualification` and
|
|
543
|
+
* `entry_fee_pay_params` are always `None` here — gated/extension-fee
|
|
544
|
+
* tournaments need a real proof / pay-params payload, which depend on the
|
|
545
|
+
* validator and the caller's runtime state.
|
|
546
|
+
*
|
|
547
|
+
* Returns `(felt252, u32)` on-chain — game_token_id and entry_number — but
|
|
548
|
+
* `execute()` surfaces only the tx hash. Callers can fetch the receipt
|
|
549
|
+
* and parse events if they need the values.
|
|
550
|
+
*
|
|
551
|
+
* Tournaments with a non-trivial entry_requirement (NFT-gated or
|
|
552
|
+
* extension-validator) need a real `QualificationProof` and shouldn't go
|
|
553
|
+
* through this entrypoint — route those via the budokan client UI or
|
|
554
|
+
* implement a qualification-proof builder.
|
|
555
|
+
*/
|
|
556
|
+
declare function buildEnterTournamentCall(budokanAddress: string, args: EnterTournamentArgs): Call;
|
|
557
|
+
/** `submit_score(tournament_id: u64, token_id: felt252, position: u32)` */
|
|
558
|
+
declare function buildSubmitScoreCall(budokanAddress: string, args: {
|
|
559
|
+
tournamentId: string;
|
|
560
|
+
tokenId: string;
|
|
561
|
+
position: number;
|
|
562
|
+
}): Call;
|
|
563
|
+
/** `claim_reward(tournament_id: u64, reward_type: RewardType)` */
|
|
564
|
+
declare function buildClaimRewardCall(budokanAddress: string, args: {
|
|
565
|
+
tournamentId: string;
|
|
566
|
+
reward: RewardType;
|
|
567
|
+
}): Call;
|
|
568
|
+
/**
|
|
569
|
+
* `create_tournament(creator_rewards_address, metadata, schedule,
|
|
570
|
+
* game_config, entry_fee, entry_requirement,
|
|
571
|
+
* leaderboard_config, salt, metadata_value)`
|
|
572
|
+
*
|
|
573
|
+
* Schedule fields are durations (`registration_end_delay`,
|
|
574
|
+
* `game_end_delay` measured from their respective starts) — *not*
|
|
575
|
+
* absolute offsets from creation. Callers are responsible for the
|
|
576
|
+
* arithmetic; the contract validates min/max bounds itself.
|
|
577
|
+
*
|
|
578
|
+
* Pass `entryFee` / `entryRequirement` as `undefined` for free / open
|
|
579
|
+
* tournaments. Both fields are wrapped in `CairoOption` so
|
|
580
|
+
* `CallData.compile` emits the correct variant tag.
|
|
581
|
+
*/
|
|
582
|
+
declare function buildCreateTournamentCall(budokanAddress: string, args: CreateTournamentArgs): Call;
|
|
583
|
+
/**
|
|
584
|
+
* `add_prize(tournament_id: u64, prize: Prize, position: Option<u32>) -> u64`
|
|
585
|
+
*
|
|
586
|
+
* The `Prize` sum type discriminates between the built-in
|
|
587
|
+
* (ERC20/ERC721) flow and an external `IPrizeExtension` integration —
|
|
588
|
+
* see `PrizeSpec` for the variants.
|
|
589
|
+
*
|
|
590
|
+
* The on-chain entrypoint returns the minted `prize_id` (u64); callers
|
|
591
|
+
* wanting the full payload should subscribe to the `PrizeAdded` event.
|
|
592
|
+
*/
|
|
593
|
+
declare function buildAddPrizeCall(budokanAddress: string, args: AddPrizeArgs): Call;
|
|
594
|
+
/**
|
|
595
|
+
* Minimal receipt shape — `events: Array<{ from_address, keys, ... }>`
|
|
596
|
+
* is all `parseTournamentIdFromReceipt` needs and matches what every
|
|
597
|
+
* Starknet RPC / starknet.js `waitForTransaction` returns.
|
|
598
|
+
*/
|
|
599
|
+
interface ReceiptWithEvents {
|
|
600
|
+
events?: Array<{
|
|
601
|
+
from_address?: string;
|
|
602
|
+
keys?: string[];
|
|
603
|
+
}>;
|
|
604
|
+
}
|
|
605
|
+
/**
|
|
606
|
+
* Extract the new tournament's id from a `create_tournament` tx receipt
|
|
607
|
+
* by scanning for the `TournamentCreated` event emitted by the budokan
|
|
608
|
+
* contract. The event has the tournament id in its first indexed key
|
|
609
|
+
* (`keys[1]` — `keys[0]` is the selector).
|
|
610
|
+
*
|
|
611
|
+
* Returns the id as a `bigint` (the on-chain type is `u64`, which exceeds
|
|
612
|
+
* JS `Number.MAX_SAFE_INTEGER`, so a lossless type is required — callers
|
|
613
|
+
* deep-linking to a tournament page should `.toString()` it). Returns
|
|
614
|
+
* `undefined` if no matching event is found (e.g. the receipt came from a
|
|
615
|
+
* different call, or the budokan address didn't match).
|
|
616
|
+
*
|
|
617
|
+
* Caller is responsible for fetching the receipt — typically via
|
|
618
|
+
* `account.waitForTransaction(hash)` or `provider.waitForTransaction(hash)`.
|
|
619
|
+
*/
|
|
620
|
+
declare function parseTournamentIdFromReceipt(receipt: ReceiptWithEvents, budokanAddress: string): bigint | undefined;
|
|
621
|
+
|
|
622
|
+
/**
|
|
623
|
+
* Entry-requirement validator extensions.
|
|
624
|
+
*
|
|
625
|
+
* Thin wrappers on top of @provable-games/metagame-sdk for the four
|
|
626
|
+
* validator presets we recommend for chat / bot integrations:
|
|
627
|
+
*
|
|
628
|
+
* - merkle — Allowlist of addresses via a pre-built merkle tree
|
|
629
|
+
* - erc20Balance — Player must hold ≥ X of some ERC-20
|
|
630
|
+
* - opusTroves — Player must have borrowed ≥ $X CASH on Opus
|
|
631
|
+
* - tournament — Player must have entered / placed in a prior tournament
|
|
632
|
+
*
|
|
633
|
+
* Each `buildXxxConfig` function emits the `Span<felt252>` config array
|
|
634
|
+
* the on-chain validator's `add_config` expects. Pair the array with the
|
|
635
|
+
* validator address (via `extensionAddressFor`) when building an
|
|
636
|
+
* `EntryRequirementArgs` of kind `"extension"`.
|
|
637
|
+
*
|
|
638
|
+
* Authoritative on-chain layouts:
|
|
639
|
+
* metagame-extensions/packages/presets/src/entry_requirement/*.cairo
|
|
640
|
+
*
|
|
641
|
+
* u256 values (ERC-20 balance thresholds) are split into low/high felt
|
|
642
|
+
* pairs to match those layouts. CASH amounts for Opus are passed as
|
|
643
|
+
* single felts because they're u128-range in practice.
|
|
644
|
+
*/
|
|
645
|
+
|
|
646
|
+
type ExtensionPresetKind = "merkle" | "erc20Balance" | "opusTroves" | "tournament";
|
|
647
|
+
/**
|
|
648
|
+
* Lookup the deployed validator address for a given preset on a given
|
|
649
|
+
* chain. Throws if the metagame-sdk address table doesn't have one — the
|
|
650
|
+
* preset isn't usable on that chain.
|
|
651
|
+
*/
|
|
652
|
+
declare function extensionAddressFor(chain: WhitelistChain, kind: ExtensionPresetKind): string;
|
|
653
|
+
/** Split a u256 (as bigint) into [low_128, high_128] felt strings. */
|
|
654
|
+
declare function u256ToLowHigh(value: bigint): [string, string];
|
|
655
|
+
interface Erc20BalanceConfig {
|
|
656
|
+
tokenAddress: string;
|
|
657
|
+
/** Raw u256, smallest units. */
|
|
658
|
+
minThreshold: bigint;
|
|
659
|
+
/** Raw u256, smallest units; 0 = no max. */
|
|
660
|
+
maxThreshold: bigint;
|
|
661
|
+
/** Raw u256, smallest units; 0 = single entry, regardless of balance. */
|
|
662
|
+
valuePerEntry: bigint;
|
|
663
|
+
/** 0 = unlimited (only meaningful when valuePerEntry > 0). */
|
|
664
|
+
maxEntries: number;
|
|
665
|
+
bannable: boolean;
|
|
666
|
+
}
|
|
667
|
+
/**
|
|
668
|
+
* Build the felt-string config array.
|
|
669
|
+
*
|
|
670
|
+
* Layout (from erc20_balance_validator.cairo):
|
|
671
|
+
* [token, min_low, min_high, max_low, max_high, vpe_low, vpe_high,
|
|
672
|
+
* max_entries, bannable]
|
|
673
|
+
*/
|
|
674
|
+
declare function buildErc20BalanceConfig(cfg: Erc20BalanceConfig): string[];
|
|
675
|
+
interface OpusTrovesConfig {
|
|
676
|
+
/** Specific collateral filters; empty = wildcard (any trove qualifies). */
|
|
677
|
+
assetAddresses: string[];
|
|
678
|
+
/** Min CASH borrowed (raw, 18 decimals). CASH is 1:1 USD. */
|
|
679
|
+
threshold: bigint;
|
|
680
|
+
/** CASH per additional entry; 0 = single entry per qualifying trove. */
|
|
681
|
+
valuePerEntry: bigint;
|
|
682
|
+
/** 0 = unlimited (only meaningful with proportional valuePerEntry > 0). */
|
|
683
|
+
maxEntries: number;
|
|
684
|
+
bannable: boolean;
|
|
685
|
+
}
|
|
686
|
+
/**
|
|
687
|
+
* Layout (from opus_troves_validator):
|
|
688
|
+
* [asset_count, ...asset_addresses, threshold, value_per_entry,
|
|
689
|
+
* max_entries, bannable]
|
|
690
|
+
*
|
|
691
|
+
* threshold / value_per_entry are CASH amounts (18 decimals, ≤ u128 range
|
|
692
|
+
* for any reasonable USD value) — passed as single felts, not low/high
|
|
693
|
+
* pairs. This matches the validator's parse (parseOpusTrovesValidatorConfig
|
|
694
|
+
* in metagame-sdk reads them as bigints directly).
|
|
695
|
+
*/
|
|
696
|
+
declare function buildOpusTrovesConfig(cfg: OpusTrovesConfig): string[];
|
|
697
|
+
interface MerkleConfig {
|
|
698
|
+
/** On-chain tree ID from the merkle-validator's create_tree. */
|
|
699
|
+
treeId: number;
|
|
700
|
+
}
|
|
701
|
+
/** Layout: [tree_id]. */
|
|
702
|
+
declare function buildMerkleConfig(cfg: MerkleConfig): string[];
|
|
703
|
+
/** 0 = participated (any entry counts), 1 = won (placed in top N). */
|
|
704
|
+
type TournamentRequirementType = "participated" | "won";
|
|
705
|
+
/**
|
|
706
|
+
* How to combine multiple qualifying tournaments. Matches QualifyingMode
|
|
707
|
+
* in metagame-sdk: 0=AtLeastOne, 1=CumulativePerTournament, 2=All,
|
|
708
|
+
* 3=CumulativePerEntry, 4=AllParticipateAnyWin, 5=AllWithCumulative.
|
|
709
|
+
*/
|
|
710
|
+
interface TournamentValidatorConfig {
|
|
711
|
+
requirement: TournamentRequirementType;
|
|
712
|
+
/** Tournament IDs whose history qualifies. */
|
|
713
|
+
tournamentIds: string[];
|
|
714
|
+
/** Top N positions that count (only used when requirement = "won"). */
|
|
715
|
+
topPositions: number;
|
|
716
|
+
/** Default 0 (= AtLeastOne). */
|
|
717
|
+
qualifyingMode?: number;
|
|
718
|
+
}
|
|
719
|
+
/**
|
|
720
|
+
* Layout (from tournament_validator):
|
|
721
|
+
* [qualifier_type, qualifying_mode, top_positions, ...tournament_ids]
|
|
722
|
+
* - qualifier_type: 0 = participated, 1 = won
|
|
723
|
+
* - qualifying_mode: 0–5 enum
|
|
724
|
+
* - top_positions: 0 for "all positions" (used with participated)
|
|
725
|
+
*/
|
|
726
|
+
declare function buildTournamentValidatorConfig(cfg: TournamentValidatorConfig): string[];
|
|
192
727
|
|
|
193
|
-
export { BudokanApiError, BudokanConnectionError, BudokanError, BudokanTimeoutError, CHAINS, type ChainConfig, DataSourceError, PaginatedResult, PlatformStats, Prize, PrizeAggregation, PrizeStats, QualificationEntry, Registration, RewardClaim, RewardClaimSummary, RpcError, Tournament, TournamentListParams, TournamentNotFoundError, WSEventHandler, WSManager, WSSubscribeOptions, camelToSnake, getActivityStats, getChainConfig, getGameStats, getGameTournaments, getPrizeStats, getTournament, getTournamentPrizeAggregation, getTournamentPrizes, getTournamentQualifications, getTournamentRegistrations, getTournamentRewardClaims, getTournamentRewardClaimsSummary, getTournaments, normalizeAddress, snakeToCamel, withRetry };
|
|
728
|
+
export { type AddPrizeArgs, BudokanApiError, BudokanConnectionError, BudokanError, BudokanTimeoutError, CHAINS, type Call, type ChainConfig, type CreateTournamentArgs, DataSourceError, type DistributionSpec, type EnterTournamentArgs, type EntryFeeArgs, type EntryRequirementArgs, type EntryRequirementSpec, type Erc20BalanceConfig, type ExtensionPresetKind, type GameDefaults, type MerkleConfig, type OpusTrovesConfig, PaginatedResult, PlatformStats, Prize, PrizeAggregation, type PrizeSpec, PrizeStats, QualificationEntry, type ReceiptWithEvents, Registration, RewardClaim, RewardClaimSummary, type RewardType, RpcError, type TokenTypeSpec, Tournament, TournamentListParams, TournamentNotFoundError, type TournamentRequirementType, type TournamentValidatorConfig, WSEventHandler, WSManager, WSSubscribeOptions, type WhitelistChain, type WhitelistedGame, buildAddPrizeCall, buildClaimRewardCall, buildCreateTournamentCall, buildEnterTournamentCall, buildErc20ApproveCall, buildErc20BalanceConfig, buildMerkleConfig, buildOpusTrovesConfig, buildSubmitScoreCall, buildTournamentValidatorConfig, camelToSnake, explorerAddressUrl, explorerBaseUrl, explorerTxUrl, extensionAddressFor, findWhitelistedGame, getActivityStats, getChainConfig, getGameDefaults, getGameStats, getGameTournaments, getPrizeStats, getTournament, getTournamentPrizeAggregation, getTournamentPrizes, getTournamentQualifications, getTournamentRegistrations, getTournamentRewardClaims, getTournamentRewardClaimsSummary, getTournaments, getWhitelistedGames, isGameWhitelisted, normalizeAddress, parseTournamentIdFromReceipt, snakeToCamel, tournamentPageUrl, u256ToLowHigh, withRetry };
|