rain-sdk-v2 2.1.3 → 2.1.5

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 CHANGED
@@ -661,6 +661,96 @@ const payouts = await rain.getDynamicPayout({
661
661
  // payouts = [yesPayoutWei, noPayoutWei]
662
662
  ```
663
663
 
664
+ ### `getResolverBondAmount(params): Promise<bigint>`
665
+
666
+ Get the bond amount (in base-token wei) a resolver must post to propose a resolution for an option.
667
+
668
+ ```typescript
669
+ const bond = await rain.getResolverBondAmount({
670
+ marketContractAddress: '0x...',
671
+ option: 1n, // 1-based option index
672
+ });
673
+ ```
674
+
675
+ ### `getDisputeAppealFee(params): Promise<bigint>`
676
+
677
+ Get the fee (in base-token wei) required to open a dispute or appeal on an option.
678
+
679
+ ```typescript
680
+ const fee = await rain.getDisputeAppealFee({
681
+ marketContractAddress: '0x...',
682
+ option: 1n,
683
+ });
684
+ ```
685
+
686
+ ### `optionResolverBond(params): Promise<bigint>`
687
+
688
+ Get the resolver bond currently posted on an option (0n if no resolution has been proposed).
689
+
690
+ ```typescript
691
+ const bond = await rain.optionResolverBond({
692
+ marketContractAddress: '0x...',
693
+ option: 1n,
694
+ });
695
+ ```
696
+
697
+ ### `optionResolutionProposer(params): Promise<`0x${string}`>`
698
+
699
+ Get the address that proposed the resolution for an option (zero address if none).
700
+
701
+ ```typescript
702
+ const proposer = await rain.optionResolutionProposer({
703
+ marketContractAddress: '0x...',
704
+ option: 1n,
705
+ });
706
+ ```
707
+
708
+ ### `isOptionDisputed(params): Promise<boolean>`
709
+
710
+ Check whether an option's resolution has been disputed.
711
+
712
+ ```typescript
713
+ const disputed = await rain.isOptionDisputed({
714
+ marketContractAddress: '0x...',
715
+ option: 1n,
716
+ });
717
+ ```
718
+
719
+ ### `isOptionAppealed(params): Promise<boolean>`
720
+
721
+ Check whether an option's dispute resolution has been appealed.
722
+
723
+ ```typescript
724
+ const appealed = await rain.isOptionAppealed({
725
+ marketContractAddress: '0x...',
726
+ option: 1n,
727
+ });
728
+ ```
729
+
730
+ ### `optionDispute(params): Promise<OptionDisputeInfo>`
731
+
732
+ Get the dispute details for an option: fee paid, the winner claimed by the disputer, the disputer address, and the dispute resolver.
733
+
734
+ ```typescript
735
+ const dispute = await rain.optionDispute({
736
+ marketContractAddress: '0x...',
737
+ option: 1n,
738
+ });
739
+ // { disputeFee: bigint, disputedWinner: bigint, disputer: '0x...', disputeResolver: '0x...' }
740
+ ```
741
+
742
+ ### `optionAppeal(params): Promise<OptionAppealInfo>`
743
+
744
+ Get the appeal details for an option: fee paid, the winner claimed by the appellant, the disputer address, and the appeal resolver.
745
+
746
+ ```typescript
747
+ const appeal = await rain.optionAppeal({
748
+ marketContractAddress: '0x...',
749
+ option: 1n,
750
+ });
751
+ // { disputeFee: bigint, disputedWinner: bigint, disputer: '0x...', appealResolver: '0x...' }
752
+ ```
753
+
664
754
  ### `getUserActiveBuyOrders(params): Promise<bigint>`
665
755
 
666
756
  Get count of user's active buy orders.
@@ -1237,6 +1327,64 @@ const priceData = await rain.getTokenPrice('0x...'); // token contract address
1237
1327
  // priceData.data = { price: 0.05 } — USD price per token
1238
1328
  ```
1239
1329
 
1330
+ ### Leaderboard
1331
+
1332
+ Public endpoints — no access token required. Boards are served from a materialized document rebuilt by a cron (~20 min), so changes appear after the next tick rather than on the next request.
1333
+
1334
+ ```typescript
1335
+ // Get a ranked leaderboard — one board per (board, window, category)
1336
+ const board = await rain.getLeaderboard({
1337
+ board: 'profit', // 'profit' (net realized PnL) or 'correct_calls' (sum of 1 − entryPrice over winning positions)
1338
+ window: 'all_time', // 'all_time' (default) or 'monthly' (current UTC calendar month)
1339
+ category: 'Crypto', // optional, case-insensitive; omit for the global board
1340
+ limit: 10, // up to the stored cap of 100 (default 10)
1341
+ });
1342
+ // board.data = { board, window, category, categoryLabel, period, limit, totalRanked, priceBasis, entries, lastUpdatedAt }
1343
+ // Each entry carries all four table columns — profit, correctCalls, winRate, trades —
1344
+ // whichever board is sorting, so switching the sorted column needs no second request.
1345
+
1346
+ // Search traders on a board — the leaderboard's trader search box
1347
+ const found = await rain.searchLeaderboard({
1348
+ q: '0x742d', // wallet address, address fragment (with/without 0x, prefix/middle/tail), or user id
1349
+ board: 'profit', // required — searches the stored board for this (board, window, category)
1350
+ window: 'all_time', // optional, default 'all_time'
1351
+ category: 'Crypto', // optional; omit for the global board
1352
+ limit: 10, // up to 50 (default 10)
1353
+ });
1354
+ // found.data = { board, window, category, period, query, matched, searchedTop, totalRanked, lastUpdatedAt, results }
1355
+ // `results` are the same entry objects getLeaderboard returns, in rank order.
1356
+ // Scoped to the stored board — a trader outside the top N is simply not found.
1357
+ // Empty `results` means "not on this board"; `searchedTop` + `totalRanked` let you
1358
+ // say "not in the top 100" precisely. Queries under 2 characters return empty, not a 400.
1359
+
1360
+ // Get a trader's most recent trades — the rows inside an expanded leaderboard row
1361
+ const recent = await rain.getTraderRecentTrades({
1362
+ userId: '...', // from a leaderboard entry's `userId`
1363
+ limit: 5, // rendered rows (a multi-side trade flattens into more lines), up to 25 (default 5)
1364
+ });
1365
+ // recent.data = { userId, limit, trades }
1366
+ // Each trade: { action ('Buy'|'Sell'), origin, transactionHash, tradedAt, poolId, question,
1367
+ // poolImage, subPoolId, subQuestion, side (1=YES, 2=NO), optionName, shares,
1368
+ // amountUSD, pricePerShare, priceCents, status ('open'|'pending'|'settled'),
1369
+ // pnlScope, pnlUSD }
1370
+ // Directional trades only (origin ∈ {enter, orderFill}), newest first — and unlike the
1371
+ // track-record endpoint, OPEN positions are included (status 'open').
1372
+ // `pnlUSD` is POSITION-level, not per-fill: several trades in the same market report the
1373
+ // same number. Null until settled; `amountUSD`/`pnlUSD` are dollars × 1e6.
1374
+
1375
+ // Get categories that currently have a ranked board (feeds the category filter)
1376
+ const categories = await rain.getLeaderboardCategories();
1377
+ // categories.data = [{ category: 'CRYPTO', label: 'Crypto' }, ...]
1378
+ // Pass `category` back as the `category` param of getLeaderboard.
1379
+ ```
1380
+
1381
+ **Notes:**
1382
+ - **Units:** every `*USD` number (including `profit` and `score` on the profit board) is **dollars × 1e6** — divide by 1,000,000 to display. E.g. `profit: 887505347` is **$887.51**.
1383
+ - **Monthly window** buckets on when PnL *settled*, not when the position was opened; `window: 'monthly'` always means the current UTC month (`period` reports it as `YYYY-MM`).
1384
+ - **Only positive scores are ranked.** An unknown `category` returns an empty board, not a 400.
1385
+ - **Top-N only** — there is no rank-of-user lookup. Empty `entries` with `lastUpdatedAt: null` means the cron hasn't built the board yet; empty with a timestamp means nobody qualifies.
1386
+ - The client can highlight the viewer's own row by matching `userId` in `entries`.
1387
+
1240
1388
  ---
1241
1389
 
1242
1390
  ## WebSocket Events (Socket.IO)
package/dist/Rain.d.ts CHANGED
@@ -4,8 +4,9 @@ import { ExtendTimeTxParams } from './tx/buildExtendTimeRawTx.js';
4
4
  import { RainCoreConfig, RainEnvironment } from './types.js';
5
5
  import { LoginParams, LoginResult } from './auth/types.js';
6
6
  import { SellProceedsResult } from './markets/getSellProceeds.js';
7
+ import { OptionDisputeInfo, OptionAppealInfo } from './markets/getDisputeState.js';
7
8
  import { EntrySharesResult } from './markets/getEntryShares.js';
8
- import type { UserProfileUpdateParams, UserHistoryParams, CreateCommentParams, CommentsListingParams, UpdateCommentParams, CommentCountParams, PublicPoolsParams, PrivatePoolsParams, PoolListingByCreatorParams, VerifyAccessCodeParams, PoolTotalParticipantsParams, SearchPoolParams, RelatedPoolsParams, UpdateStreamingParams, UpdatePoolResolutionTimeParams, FindPoolFallbackParams, SignOraclesExtendTimeParams, TrendingTagsParams, UserTotalInvestmentParams, OptionsTotalVolumeParams, PoolActivityParams, TopHoldersParams, UserInvestedPoolsParams, InvestmentVolumeGraphParams, UserPnlGraphParams, TopWinnersLosersParams, PnlByPoolIdParams, UserPositionsParams, OpenPositionsParams, UserSharePositionsParams, SearchInvestedPoolsParams, PriceDataParams, AddReviewParams, GetUserOrdersParams, OrderBookParams, GetUserOrderByPoolIdParams, OrdersListingByPoolParams, AddUserPointsParams, UserOnboardingParams, PointsGraphParams, GetNotificationsParams, MarkNotificationAsReadParams, CreateDisputeMessageParams, GetPoolDisputeConvoParams, FollowToggleParams, FollowCheckParams, FollowListParams, FollowStatsParams, RainBurnPerPoolParams, ToggleBookmarkParams, GetBookmarksParams, CheckBookmarkParams } from './api/types.js';
9
+ import type { UserProfileUpdateParams, UserHistoryParams, CreateCommentParams, CommentsListingParams, UpdateCommentParams, CommentCountParams, PublicPoolsParams, PrivatePoolsParams, PoolListingByCreatorParams, VerifyAccessCodeParams, PoolTotalParticipantsParams, SearchPoolParams, RelatedPoolsParams, UpdateStreamingParams, UpdatePoolResolutionTimeParams, FindPoolFallbackParams, SignOraclesExtendTimeParams, TrendingTagsParams, UserTotalInvestmentParams, OptionsTotalVolumeParams, PoolActivityParams, TopHoldersParams, UserInvestedPoolsParams, InvestmentVolumeGraphParams, UserPnlGraphParams, TopWinnersLosersParams, PnlByPoolIdParams, UserPositionsParams, OpenPositionsParams, UserSharePositionsParams, SearchInvestedPoolsParams, PriceDataParams, AddReviewParams, GetUserOrdersParams, OrderBookParams, GetUserOrderByPoolIdParams, OrdersListingByPoolParams, AddUserPointsParams, UserOnboardingParams, PointsGraphParams, GetNotificationsParams, MarkNotificationAsReadParams, CreateDisputeMessageParams, GetPoolDisputeConvoParams, FollowToggleParams, FollowCheckParams, FollowListParams, FollowStatsParams, RainBurnPerPoolParams, ToggleBookmarkParams, GetBookmarksParams, CheckBookmarkParams, LeaderboardParams, LeaderboardSearchParams, TraderRecentTradesParams } from './api/types.js';
9
10
  export declare class Rain {
10
11
  readonly environment: RainEnvironment;
11
12
  private readonly marketFactory;
@@ -58,6 +59,38 @@ export declare class Rain {
58
59
  getDisputeWindow(params: {
59
60
  marketContractAddress: `0x${string}`;
60
61
  }): Promise<bigint>;
62
+ getResolverBondAmount(params: {
63
+ marketContractAddress: `0x${string}`;
64
+ option: bigint;
65
+ }): Promise<bigint>;
66
+ getDisputeAppealFee(params: {
67
+ marketContractAddress: `0x${string}`;
68
+ option: bigint;
69
+ }): Promise<bigint>;
70
+ optionResolverBond(params: {
71
+ marketContractAddress: `0x${string}`;
72
+ option: bigint;
73
+ }): Promise<bigint>;
74
+ optionResolutionProposer(params: {
75
+ marketContractAddress: `0x${string}`;
76
+ option: bigint;
77
+ }): Promise<`0x${string}`>;
78
+ isOptionDisputed(params: {
79
+ marketContractAddress: `0x${string}`;
80
+ option: bigint;
81
+ }): Promise<boolean>;
82
+ isOptionAppealed(params: {
83
+ marketContractAddress: `0x${string}`;
84
+ option: bigint;
85
+ }): Promise<boolean>;
86
+ optionDispute(params: {
87
+ marketContractAddress: `0x${string}`;
88
+ option: bigint;
89
+ }): Promise<OptionDisputeInfo>;
90
+ optionAppeal(params: {
91
+ marketContractAddress: `0x${string}`;
92
+ option: bigint;
93
+ }): Promise<OptionAppealInfo>;
61
94
  getEntryShares(params: {
62
95
  marketContractAddress: `0x${string}`;
63
96
  option: bigint;
@@ -292,4 +325,8 @@ export declare class Rain {
292
325
  toggleBookmark(params: ToggleBookmarkParams, accessToken: string): Promise<import("./api/types.js").ApiResponse<unknown>>;
293
326
  getBookmarks(params: GetBookmarksParams, accessToken: string): Promise<import("./api/types.js").ApiResponse<unknown>>;
294
327
  checkBookmark(params: CheckBookmarkParams, accessToken: string): Promise<import("./api/types.js").ApiResponse<unknown>>;
328
+ getLeaderboard(params: LeaderboardParams): Promise<import("./api/types.js").ApiResponse<import("./api/types.js").LeaderboardData>>;
329
+ searchLeaderboard(params: LeaderboardSearchParams): Promise<import("./api/types.js").ApiResponse<import("./api/types.js").LeaderboardSearchData>>;
330
+ getTraderRecentTrades(params: TraderRecentTradesParams): Promise<import("./api/types.js").ApiResponse<import("./api/types.js").TraderRecentTradesData>>;
331
+ getLeaderboardCategories(): Promise<import("./api/types.js").ApiResponse<import("./api/types.js").LeaderboardCategory[]>>;
295
332
  }
package/dist/Rain.js CHANGED
@@ -24,6 +24,9 @@ import { getSellProceeds } from './markets/getSellProceeds.js';
24
24
  import { getUserSharesInEscrow } from './markets/getUserSharesInEscrow.js';
25
25
  import { getOptionClaimed } from './markets/getOptionClaimed.js';
26
26
  import { getDisputeWindow } from './markets/getDisputeWindow.js';
27
+ import { getResolverBondAmount } from './markets/getResolverBondAmount.js';
28
+ import { getDisputeAppealFee } from './markets/getDisputeFee.js';
29
+ import { optionResolverBond, optionResolutionProposer, isOptionDisputed, isOptionAppealed, optionDispute, optionAppeal } from './markets/getDisputeState.js';
27
30
  import { getEntryShares } from './markets/getEntryShares.js';
28
31
  import { createPublicClient, http, parseAbi } from 'viem';
29
32
  import { arbitrum } from 'viem/chains';
@@ -41,6 +44,7 @@ import * as disputeApi from './api/dispute.js';
41
44
  import * as followApi from './api/follow.js';
42
45
  import * as whitelistedTokensApi from './api/whitelistedTokens.js';
43
46
  import * as bookmarksApi from './api/bookmarks.js';
47
+ import * as leaderboardApi from './api/leaderboard.js';
44
48
  const erc20AllowanceAbi = parseAbi(['function allowance(address owner, address spender) view returns (uint256)']);
45
49
  const factoryViewAbi = parseAbi([
46
50
  'function oracleFixedFee() view returns (uint256)',
@@ -136,6 +140,30 @@ export class Rain {
136
140
  async getDisputeWindow(params) {
137
141
  return getDisputeWindow({ ...params, rpcUrl: this.rpcUrl });
138
142
  }
143
+ async getResolverBondAmount(params) {
144
+ return getResolverBondAmount({ ...params, rpcUrl: this.rpcUrl });
145
+ }
146
+ async getDisputeAppealFee(params) {
147
+ return getDisputeAppealFee({ ...params, rpcUrl: this.rpcUrl });
148
+ }
149
+ async optionResolverBond(params) {
150
+ return optionResolverBond({ ...params, rpcUrl: this.rpcUrl });
151
+ }
152
+ async optionResolutionProposer(params) {
153
+ return optionResolutionProposer({ ...params, rpcUrl: this.rpcUrl });
154
+ }
155
+ async isOptionDisputed(params) {
156
+ return isOptionDisputed({ ...params, rpcUrl: this.rpcUrl });
157
+ }
158
+ async isOptionAppealed(params) {
159
+ return isOptionAppealed({ ...params, rpcUrl: this.rpcUrl });
160
+ }
161
+ async optionDispute(params) {
162
+ return optionDispute({ ...params, rpcUrl: this.rpcUrl });
163
+ }
164
+ async optionAppeal(params) {
165
+ return optionAppeal({ ...params, rpcUrl: this.rpcUrl });
166
+ }
139
167
  async getEntryShares(params) {
140
168
  return getEntryShares({ ...params, rpcUrl: this.rpcUrl });
141
169
  }
@@ -503,4 +531,17 @@ export class Rain {
503
531
  async checkBookmark(params, accessToken) {
504
532
  return bookmarksApi.checkBookmark(params, this.cfg(accessToken));
505
533
  }
534
+ // ─── Leaderboard ────────────────────────────────────────────────────────────
535
+ async getLeaderboard(params) {
536
+ return leaderboardApi.getLeaderboard(params, this.cfg());
537
+ }
538
+ async searchLeaderboard(params) {
539
+ return leaderboardApi.searchLeaderboard(params, this.cfg());
540
+ }
541
+ async getTraderRecentTrades(params) {
542
+ return leaderboardApi.getTraderRecentTrades(params, this.cfg());
543
+ }
544
+ async getLeaderboardCategories() {
545
+ return leaderboardApi.getLeaderboardCategories(this.cfg());
546
+ }
506
547
  }
@@ -14,3 +14,4 @@ export * from './dispute.js';
14
14
  export * from './follow.js';
15
15
  export * from './whitelistedTokens.js';
16
16
  export * from './bookmarks.js';
17
+ export * from './leaderboard.js';
package/dist/api/index.js CHANGED
@@ -14,3 +14,4 @@ export * from './dispute.js';
14
14
  export * from './follow.js';
15
15
  export * from './whitelistedTokens.js';
16
16
  export * from './bookmarks.js';
17
+ export * from './leaderboard.js';
@@ -0,0 +1,5 @@
1
+ import { ApiConfig, ApiResponse, LeaderboardParams, LeaderboardData, LeaderboardCategory, LeaderboardSearchParams, LeaderboardSearchData, TraderRecentTradesParams, TraderRecentTradesData } from './types.js';
2
+ export declare function getLeaderboard(params: LeaderboardParams, config: ApiConfig): Promise<ApiResponse<LeaderboardData>>;
3
+ export declare function searchLeaderboard(params: LeaderboardSearchParams, config: ApiConfig): Promise<ApiResponse<LeaderboardSearchData>>;
4
+ export declare function getTraderRecentTrades(params: TraderRecentTradesParams, config: ApiConfig): Promise<ApiResponse<TraderRecentTradesData>>;
5
+ export declare function getLeaderboardCategories(config: ApiConfig): Promise<ApiResponse<LeaderboardCategory[]>>;
@@ -0,0 +1,32 @@
1
+ import { buildHeaders, buildQuery, handleResponse } from './helpers.js';
2
+ export async function getLeaderboard(params, config) {
3
+ const qs = buildQuery({ board: params.board, window: params.window, category: params.category, limit: params.limit });
4
+ const res = await fetch(`${config.apiUrl}/leaderboard${qs}`, {
5
+ method: 'GET',
6
+ headers: buildHeaders(config),
7
+ });
8
+ return handleResponse(res);
9
+ }
10
+ export async function searchLeaderboard(params, config) {
11
+ const qs = buildQuery({ q: params.q, board: params.board, window: params.window, category: params.category, limit: params.limit });
12
+ const res = await fetch(`${config.apiUrl}/leaderboard/search${qs}`, {
13
+ method: 'GET',
14
+ headers: buildHeaders(config),
15
+ });
16
+ return handleResponse(res);
17
+ }
18
+ export async function getTraderRecentTrades(params, config) {
19
+ const qs = buildQuery({ limit: params.limit });
20
+ const res = await fetch(`${config.apiUrl}/leaderboard/traders/${encodeURIComponent(params.userId)}/recent-trades${qs}`, {
21
+ method: 'GET',
22
+ headers: buildHeaders(config),
23
+ });
24
+ return handleResponse(res);
25
+ }
26
+ export async function getLeaderboardCategories(config) {
27
+ const res = await fetch(`${config.apiUrl}/leaderboard/categories`, {
28
+ method: 'GET',
29
+ headers: buildHeaders(config),
30
+ });
31
+ return handleResponse(res);
32
+ }
@@ -322,3 +322,141 @@ export interface GetBookmarksParams {
322
322
  export interface CheckBookmarkParams {
323
323
  poolId: string;
324
324
  }
325
+ export type LeaderboardBoard = 'profit' | 'correct_calls';
326
+ export type LeaderboardWindow = 'all_time' | 'monthly';
327
+ export interface LeaderboardParams {
328
+ /** Ranking to serve: net realized PnL, or the weighted correct-calls score. */
329
+ board: LeaderboardBoard;
330
+ /** `all_time` (default) or the current UTC calendar month. */
331
+ window?: LeaderboardWindow;
332
+ /** Market category (case-insensitive). Omit for the global board. Unknown categories return an empty board. */
333
+ category?: string;
334
+ /** Entries to return, up to the stored cap of 100. Default 10. */
335
+ limit?: number;
336
+ }
337
+ export interface LeaderboardEntry {
338
+ rank: number;
339
+ userId: string;
340
+ walletAddress: string | null;
341
+ eoaWalletAddress: string | null;
342
+ /** The ranking key. On `profit`, dollars × 1e6 (divide by 1,000,000 to display); on `correct_calls`, an unscaled weight. */
343
+ score: number;
344
+ positions: number;
345
+ /** Net realized PnL in dollars × 1e6. Present on both boards. */
346
+ profit: number;
347
+ /** Sum of `1 − entryPrice` over winning positions — a weight, not a count. Present on both boards. */
348
+ correctCalls: number;
349
+ /** Resolved directional positions — the denominator of `winRate`. */
350
+ trades: number;
351
+ wins: number;
352
+ /** `wins / trades`, a fraction in [0,1]. */
353
+ winRate: number;
354
+ badge: 'none' | 'blue' | 'gold';
355
+ /** Crowns held on this board and category — the row's crown indicator. */
356
+ categoryCrowns: number;
357
+ /** Newest crowned month in this bucket, `YYYY-MM` (UTC), or null. */
358
+ lastCrownPeriod: string | null;
359
+ /** Crowns held across all boards and categories. */
360
+ crownCount: number;
361
+ marketScore: number;
362
+ costScore: number;
363
+ }
364
+ export interface LeaderboardData {
365
+ board: LeaderboardBoard;
366
+ window: LeaderboardWindow;
367
+ /** Upper-cased matched key, or null for the global board. */
368
+ category: string | null;
369
+ /** Display spelling of the matched category, or null. */
370
+ categoryLabel: string | null;
371
+ /** `YYYY-MM` (UTC) on the monthly window; null on all-time. */
372
+ period: string | null;
373
+ limit: number;
374
+ /** Users ranked in total (before the stored cap). */
375
+ totalRanked: number;
376
+ /** Entry-price basis the correct-calls board was ranked on: `market` or `cost`. */
377
+ priceBasis: 'market' | 'cost';
378
+ entries: LeaderboardEntry[];
379
+ /** When the cron last rebuilt this board; null means never. */
380
+ lastUpdatedAt: string | null;
381
+ }
382
+ export interface LeaderboardCategory {
383
+ /** Upper-cased key — pass this back as `category`. */
384
+ category: string;
385
+ /** First-seen spelling, for display. */
386
+ label: string;
387
+ }
388
+ export interface LeaderboardSearchParams {
389
+ /** Wallet address, address fragment (with or without 0x, prefix/middle/tail), or user id. Case-insensitive substring match. */
390
+ q: string;
391
+ /** Board to search: `profit` or `correct_calls`. */
392
+ board: LeaderboardBoard;
393
+ /** `all_time` (default) or the current UTC calendar month. */
394
+ window?: LeaderboardWindow;
395
+ /** Market category (case-insensitive). Omit for the global board. */
396
+ category?: string;
397
+ /** Results to return, up to 50. Default 10. */
398
+ limit?: number;
399
+ }
400
+ export interface TraderRecentTradesParams {
401
+ /** The trader's user id, as returned in leaderboard entries. */
402
+ userId: string;
403
+ /** Rendered rows to return (a trade carrying more than one side flattens into more than one line), up to 25. Default 5. */
404
+ limit?: number;
405
+ }
406
+ export interface TraderRecentTrade {
407
+ /** Rendered form of `transactionType`: `Buy` or `Sell`. */
408
+ action: 'Buy' | 'Sell';
409
+ transactionType: string;
410
+ origin: 'enter' | 'orderFill';
411
+ transactionHash: string;
412
+ tradedAt: string;
413
+ poolId: string;
414
+ question: string | null;
415
+ poolImage: string | null;
416
+ subPoolId: string | null;
417
+ /** The sub-market — e.g. "Match winner". */
418
+ subQuestion: string | null;
419
+ /** 1 = YES, 2 = NO */
420
+ side: number;
421
+ optionName: string;
422
+ shares: number;
423
+ /** Collateral paid, in dollars × 1e6 (divide by 1,000,000 to display). */
424
+ amountUSD: number;
425
+ /** Collateral paid per share, in (0,1). Null when the recorded ratio is not a price (e.g. a 1:1 AMM entry). */
426
+ pricePerShare: number | null;
427
+ /** `pricePerShare` in cents, for the "9c" label. */
428
+ priceCents: number | null;
429
+ /** `open` = market not resolved; `pending` = won but unclaimed (no PnL yet, never booked as a loss); `settled` = realized. */
430
+ status: 'open' | 'pending' | 'settled';
431
+ /** Always `position` — PnL is per (pool, subPool), not per fill. */
432
+ pnlScope: string;
433
+ /** Realized PnL of the POSITION this trade belongs to, in dollars × 1e6. Null until settled. */
434
+ pnlUSD: number | null;
435
+ /** Resolved-but-unclaimed winnings of the position, in dollars × 1e6. */
436
+ pendingUSD?: number;
437
+ /** Whether the position won, once resolved. */
438
+ won?: boolean;
439
+ }
440
+ export interface TraderRecentTradesData {
441
+ userId: string;
442
+ limit: number;
443
+ /** Most recent directional trades, newest first. */
444
+ trades: TraderRecentTrade[];
445
+ }
446
+ export interface LeaderboardSearchData {
447
+ board: LeaderboardBoard;
448
+ window: LeaderboardWindow;
449
+ category: string | null;
450
+ /** `YYYY-MM` (UTC) on the monthly window; null on all-time. */
451
+ period: string | null;
452
+ query: string;
453
+ /** Board entries the term matched, before `limit`. */
454
+ matched: number;
455
+ /** Board rows searched — the stored depth. With `matched: 0`, lets a client say "not in the top N" rather than "no such trader". */
456
+ searchedTop: number;
457
+ /** Users ranked on this board in total. */
458
+ totalRanked: number;
459
+ lastUpdatedAt: string | null;
460
+ /** Matching board entries — the same objects `getLeaderboard` returns, in rank order. */
461
+ results: LeaderboardEntry[];
462
+ }
package/dist/index.d.ts CHANGED
@@ -8,6 +8,7 @@ export { signLoginMessage } from './auth/signMessage.js';
8
8
  export type { ExtendTimeTxParams } from './tx/buildExtendTimeRawTx.js';
9
9
  export type { CalculateWinnerTxParams } from './tx/buildCalculateWinnerRawTx.js';
10
10
  export type { TokenConfig } from './config/environments.js';
11
+ export type { OptionDisputeInfo, OptionAppealInfo } from './markets/getDisputeState.js';
11
12
  export * from './api/index.js';
12
13
  export { RainSocket } from './socket/RainSocket.js';
13
14
  export type { RainSocketEvent, EnterOptionEventData, ExitOptionEventData, LiquidityEventData, SplitEventData, MergeEventData, RemoveLiquidityEventData, SyncPriceEventData, OrderCreatedEventData, OrderCancelledEventData, OrderFilledEventData, PoolClosedEventData, PoolEventData, WinnerEventData, DisputeOpenedEventData, OracleCreatedEventData, AppealOpenedEventData, DisputeWinnerEventData, AppealWinnerEventData, ClaimRewardEventData, DisputeRefundEventData } from './socket/RainSocket.js';
@@ -0,0 +1,24 @@
1
+ export interface OptionDisputeInfo {
2
+ disputeFee: bigint;
3
+ disputedWinner: bigint;
4
+ disputer: `0x${string}`;
5
+ disputeResolver: `0x${string}`;
6
+ }
7
+ export interface OptionAppealInfo {
8
+ disputeFee: bigint;
9
+ disputedWinner: bigint;
10
+ disputer: `0x${string}`;
11
+ appealResolver: `0x${string}`;
12
+ }
13
+ interface OptionReadParams {
14
+ marketContractAddress: `0x${string}`;
15
+ option: bigint;
16
+ rpcUrl: string;
17
+ }
18
+ export declare function optionResolverBond(params: OptionReadParams): Promise<bigint>;
19
+ export declare function optionResolutionProposer(params: OptionReadParams): Promise<`0x${string}`>;
20
+ export declare function isOptionDisputed(params: OptionReadParams): Promise<boolean>;
21
+ export declare function isOptionAppealed(params: OptionReadParams): Promise<boolean>;
22
+ export declare function optionDispute(params: OptionReadParams): Promise<OptionDisputeInfo>;
23
+ export declare function optionAppeal(params: OptionReadParams): Promise<OptionAppealInfo>;
24
+ export {};
@@ -0,0 +1,69 @@
1
+ import { createPublicClient, http } from 'viem';
2
+ import { arbitrum } from 'viem/chains';
3
+ import { MarketsAbi } from '../abi/MarketsAbi.js';
4
+ function client(rpcUrl) {
5
+ return createPublicClient({
6
+ chain: arbitrum,
7
+ transport: http(rpcUrl),
8
+ });
9
+ }
10
+ export async function optionResolverBond(params) {
11
+ const { marketContractAddress, option, rpcUrl } = params;
12
+ const bond = await client(rpcUrl).readContract({
13
+ address: marketContractAddress,
14
+ abi: MarketsAbi,
15
+ functionName: 'optionResolverBond',
16
+ args: [option],
17
+ });
18
+ return bond;
19
+ }
20
+ export async function optionResolutionProposer(params) {
21
+ const { marketContractAddress, option, rpcUrl } = params;
22
+ const proposer = await client(rpcUrl).readContract({
23
+ address: marketContractAddress,
24
+ abi: MarketsAbi,
25
+ functionName: 'optionResolutionProposer',
26
+ args: [option],
27
+ });
28
+ return proposer;
29
+ }
30
+ export async function isOptionDisputed(params) {
31
+ const { marketContractAddress, option, rpcUrl } = params;
32
+ const disputed = await client(rpcUrl).readContract({
33
+ address: marketContractAddress,
34
+ abi: MarketsAbi,
35
+ functionName: 'isOptionDisputed',
36
+ args: [option],
37
+ });
38
+ return disputed;
39
+ }
40
+ export async function isOptionAppealed(params) {
41
+ const { marketContractAddress, option, rpcUrl } = params;
42
+ const appealed = await client(rpcUrl).readContract({
43
+ address: marketContractAddress,
44
+ abi: MarketsAbi,
45
+ functionName: 'isOptionAppealed',
46
+ args: [option],
47
+ });
48
+ return appealed;
49
+ }
50
+ export async function optionDispute(params) {
51
+ const { marketContractAddress, option, rpcUrl } = params;
52
+ const [disputeFee, disputedWinner, disputer, disputeResolver] = await client(rpcUrl).readContract({
53
+ address: marketContractAddress,
54
+ abi: MarketsAbi,
55
+ functionName: 'optionDispute',
56
+ args: [option],
57
+ });
58
+ return { disputeFee, disputedWinner, disputer, disputeResolver };
59
+ }
60
+ export async function optionAppeal(params) {
61
+ const { marketContractAddress, option, rpcUrl } = params;
62
+ const [disputeFee, disputedWinner, disputer, appealResolver] = await client(rpcUrl).readContract({
63
+ address: marketContractAddress,
64
+ abi: MarketsAbi,
65
+ functionName: 'optionAppeal',
66
+ args: [option],
67
+ });
68
+ return { disputeFee, disputedWinner, disputer, appealResolver };
69
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "rain-sdk-v2",
3
- "version": "2.1.3",
3
+ "version": "2.1.5",
4
4
  "type": "module",
5
5
  "description": "Rain SDK V2 — TypeScript SDK for Rain prediction markets on Arbitrum. Market creation, trading, liquidity, order book, split/merge, dispute, and smart account support.",
6
6
  "main": "dist/index.js",