rain-sdk-v2 2.2.0 → 2.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -3,6 +3,36 @@
3
3
  All notable changes to `rain-sdk-v2` are documented here. This project follows
4
4
  [Semantic Versioning](https://semver.org/).
5
5
 
6
+ ## Deprecation policy
7
+
8
+ APIs slated for removal are marked `@deprecated` in the type declarations for at
9
+ least one minor release before they are removed, with the replacement named in
10
+ the deprecation notice. Breaking removals land only in a major version.
11
+
12
+ ## [2.3.0] - Developer experience
13
+
14
+ Additive, non-breaking. Fills in the untyped core data model and adds the
15
+ convenience helpers the docs previously pushed onto the caller.
16
+
17
+ ### Added
18
+ - **Typed pool DTOs (F-05):** exported `Pool`, `SubPool`, `PaginatedPools`, and
19
+ `TradingModelName`. `getPublicPools` / `getPrivatePools` now return
20
+ `ApiResponse<PaginatedPools>` instead of `unknown`. Socket `*EventData`
21
+ payloads now type their `pool` / `subPool` / `subMarkets` fields as
22
+ `Pool` / `SubPool`. Interfaces carry an index signature, so they are a safe
23
+ superset of the wire (dynamic field access still works).
24
+ - **`rain.execute(txs, executor)` (F-07):** sequences the `[approval, main]`
25
+ arrays the builders return — sends each tx and awaits its receipt before the
26
+ next. Pluggable `TxExecutor` (`{ send, wait? }`) adapts to viem, ethers, or
27
+ RainAA. Also exported as the standalone `executeTxs`.
28
+ - **`rain.parseAmount` / `rain.formatAmount` (F-14):** convert between
29
+ human-readable amounts and base units using the token's configured decimals
30
+ (no more hand-tracking that USDT is 6 and RAIN is 18).
31
+ - **`RAIN_SOCKET_EVENTS` (F-16):** correctly-spelled camelCase aliases for the
32
+ raw wire event names (including the upstream-misspelled `dispute-time-extented`).
33
+ - **Token expiry (F-13):** `LoginResult.expiresAt` exposes the decoded JWT `exp`
34
+ (unix seconds) so apps can renew proactively.
35
+
6
36
  ## [2.2.0] - Guardrails
7
37
 
8
38
  Adds fail-fast validation and structured errors. These surface mistakes
package/README.md CHANGED
@@ -1544,6 +1544,67 @@ socket.disconnect();
1544
1544
 
1545
1545
  ---
1546
1546
 
1547
+ ## Helpers & Execution
1548
+
1549
+ ### Executing transactions
1550
+
1551
+ Builders return unsigned `RawTransaction[]` where index 0 may be an ERC-20
1552
+ approval. `rain.execute()` sends them in order and waits for each receipt before
1553
+ the next — so the main transaction never front-runs its approval:
1554
+
1555
+ ```typescript
1556
+ const txs = await rain.buildEnterOptionTx({ /* ... */ });
1557
+
1558
+ await rain.execute(txs, {
1559
+ send: (tx) => walletClient.sendTransaction({ to: tx.to, data: tx.data, value: tx.value ?? 0n }),
1560
+ wait: (hash) => publicClient.waitForTransactionReceipt({ hash }),
1561
+ });
1562
+ ```
1563
+
1564
+ The executor is pluggable — adapt `{ send, wait? }` to viem, ethers, RainAA, or
1565
+ your own KMS. Also available as the standalone `executeTxs(txs, executor)`.
1566
+
1567
+ ### Amount conversion
1568
+
1569
+ Convert between human-readable amounts and base units using the token's
1570
+ configured decimals — no need to track that USDT is 6 and RAIN is 18:
1571
+
1572
+ ```typescript
1573
+ rain.parseAmount('5', usdtAddress); // 5_000_000n
1574
+ rain.formatAmount(5_000_000n, usdtAddress); // '5'
1575
+ ```
1576
+
1577
+ ### Typed pool data
1578
+
1579
+ `getPublicPools` / `getPrivatePools` return `ApiResponse<PaginatedPools>`, and
1580
+ socket event payloads type their `pool` / `subPool` fields as `Pool` / `SubPool`.
1581
+ Import the DTOs to annotate your own code:
1582
+
1583
+ ```typescript
1584
+ import type { Pool, SubPool, PaginatedPools } from 'rain-sdk-v2';
1585
+ ```
1586
+
1587
+ ### Socket event names
1588
+
1589
+ Use `RAIN_SOCKET_EVENTS` for correctly-spelled event identifiers with the
1590
+ low-level `.on()` API (some raw wire names are misspelled upstream):
1591
+
1592
+ ```typescript
1593
+ import { RAIN_SOCKET_EVENTS } from 'rain-sdk-v2';
1594
+ socket.on(RAIN_SOCKET_EVENTS.disputeTimeExtended, poolId, handler);
1595
+ ```
1596
+
1597
+ ### Token expiry
1598
+
1599
+ `login()` returns `expiresAt` (unix seconds, decoded from the JWT) so you can
1600
+ renew before it lapses:
1601
+
1602
+ ```typescript
1603
+ const { accessToken, expiresAt } = await rain.login({ /* ... */ });
1604
+ ```
1605
+
1606
+ ---
1607
+
1547
1608
  ## Error Handling & Validation
1548
1609
 
1549
1610
  ### Build-time validation
package/dist/Rain.d.ts CHANGED
@@ -6,6 +6,7 @@ import { LoginParams, LoginResult } from './auth/types.js';
6
6
  import { SellProceedsResult } from './markets/getSellProceeds.js';
7
7
  import { OptionDisputeInfo, OptionAppealInfo } from './markets/getDisputeState.js';
8
8
  import { EntrySharesResult } from './markets/getEntryShares.js';
9
+ import { TxExecutor } from './tx/execute.js';
9
10
  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';
10
11
  export declare class Rain {
11
12
  readonly environment: RainEnvironment;
@@ -19,6 +20,31 @@ export declare class Rain {
19
20
  */
20
21
  getTokenConfig(tokenAddress: `0x${string}`): import("./config/environments.js").TokenConfig | null;
21
22
  buildApprovalTx(params: ApproveTxParams): RawTransaction;
23
+ /**
24
+ * Sequences an ordered list of raw transactions through a pluggable executor,
25
+ * awaiting each receipt before the next send. Use this for the `[approval, main]`
26
+ * arrays the builders return so the main tx never front-runs its approval.
27
+ *
28
+ * @example
29
+ * const txs = await rain.buildEnterOptionTx({ ... });
30
+ * await rain.execute(txs, {
31
+ * send: (tx) => walletClient.sendTransaction({ to: tx.to, data: tx.data, value: tx.value ?? 0n }),
32
+ * wait: (hash) => publicClient.waitForTransactionReceipt({ hash }),
33
+ * });
34
+ */
35
+ execute(txs: RawTransaction[], executor: TxExecutor): Promise<`0x${string}`[]>;
36
+ /**
37
+ * Convert a human-readable amount to base units (wei) using the token's
38
+ * configured decimals. Throws if the token is not in the environment config.
39
+ * @example rain.parseAmount('5', usdtAddress) // 5_000_000n for 6-decimal USDT
40
+ */
41
+ parseAmount(value: string | number, tokenAddress: `0x${string}`): bigint;
42
+ /**
43
+ * Convert a base-unit (wei) amount to a human-readable string using the
44
+ * token's configured decimals. Throws if the token is not in the config.
45
+ * @example rain.formatAmount(5_000_000n, usdtAddress) // '5' for 6-decimal USDT
46
+ */
47
+ formatAmount(amount: bigint, tokenAddress: `0x${string}`): string;
22
48
  getCreateMarketFees(tokenAddress: `0x${string}`, inputAmountWei: bigint): Promise<{
23
49
  oracleFeePerOption: bigint;
24
50
  liquidityFee: bigint;
@@ -233,8 +259,8 @@ export declare class Rain {
233
259
  poolId: string;
234
260
  accessCode: string;
235
261
  }, accessToken?: string): Promise<import("./api/types.js").ApiResponse<unknown>>;
236
- getPublicPools(params: PublicPoolsParams, accessToken?: string): Promise<import("./api/types.js").ApiResponse<unknown>>;
237
- getPrivatePools(params: PrivatePoolsParams, accessToken?: string): Promise<import("./api/types.js").ApiResponse<unknown>>;
262
+ getPublicPools(params: PublicPoolsParams, accessToken?: string): Promise<import("./api/types.js").ApiResponse<import("./api/types.js").PaginatedPools>>;
263
+ getPrivatePools(params: PrivatePoolsParams, accessToken?: string): Promise<import("./api/types.js").ApiResponse<import("./api/types.js").PaginatedPools>>;
238
264
  getPoolById(params: {
239
265
  id: string;
240
266
  }, accessToken?: string): Promise<import("./api/types.js").ApiResponse<unknown>>;
package/dist/Rain.js CHANGED
@@ -28,7 +28,8 @@ import { getResolverBondAmount } from './markets/getResolverBondAmount.js';
28
28
  import { getDisputeAppealFee } from './markets/getDisputeFee.js';
29
29
  import { optionResolverBond, optionResolutionProposer, isOptionDisputed, isOptionAppealed, optionDispute, optionAppeal } from './markets/getDisputeState.js';
30
30
  import { getEntryShares } from './markets/getEntryShares.js';
31
- import { createPublicClient, http, parseAbi } from 'viem';
31
+ import { executeTxs } from './tx/execute.js';
32
+ import { createPublicClient, http, parseAbi, parseUnits, formatUnits } from 'viem';
32
33
  import { arbitrum } from 'viem/chains';
33
34
  import * as usersApi from './api/users.js';
34
35
  import * as commentsApi from './api/comments.js';
@@ -98,6 +99,43 @@ export class Rain {
98
99
  buildApprovalTx(params) {
99
100
  return buildApproveRawTx(params);
100
101
  }
102
+ /**
103
+ * Sequences an ordered list of raw transactions through a pluggable executor,
104
+ * awaiting each receipt before the next send. Use this for the `[approval, main]`
105
+ * arrays the builders return so the main tx never front-runs its approval.
106
+ *
107
+ * @example
108
+ * const txs = await rain.buildEnterOptionTx({ ... });
109
+ * await rain.execute(txs, {
110
+ * send: (tx) => walletClient.sendTransaction({ to: tx.to, data: tx.data, value: tx.value ?? 0n }),
111
+ * wait: (hash) => publicClient.waitForTransactionReceipt({ hash }),
112
+ * });
113
+ */
114
+ async execute(txs, executor) {
115
+ return executeTxs(txs, executor);
116
+ }
117
+ /**
118
+ * Convert a human-readable amount to base units (wei) using the token's
119
+ * configured decimals. Throws if the token is not in the environment config.
120
+ * @example rain.parseAmount('5', usdtAddress) // 5_000_000n for 6-decimal USDT
121
+ */
122
+ parseAmount(value, tokenAddress) {
123
+ const cfg = this.getTokenConfig(tokenAddress);
124
+ if (!cfg)
125
+ throw new Error(`Unknown token ${tokenAddress}; not in the ${this.environment} environment config`);
126
+ return parseUnits(String(value), cfg.decimals);
127
+ }
128
+ /**
129
+ * Convert a base-unit (wei) amount to a human-readable string using the
130
+ * token's configured decimals. Throws if the token is not in the config.
131
+ * @example rain.formatAmount(5_000_000n, usdtAddress) // '5' for 6-decimal USDT
132
+ */
133
+ formatAmount(amount, tokenAddress) {
134
+ const cfg = this.getTokenConfig(tokenAddress);
135
+ if (!cfg)
136
+ throw new Error(`Unknown token ${tokenAddress}; not in the ${this.environment} environment config`);
137
+ return formatUnits(amount, cfg.decimals);
138
+ }
101
139
  async getCreateMarketFees(tokenAddress, inputAmountWei) {
102
140
  const pc = createPublicClient({ chain: arbitrum, transport: http(this.rpcUrl) });
103
141
  const [oracleFeeRaw, liquidityFee, factoryBaseToken] = await Promise.all([
@@ -1,10 +1,10 @@
1
- import { ApiConfig, ApiResponse, PublicPoolsParams, PrivatePoolsParams, PoolListingByCreatorParams, VerifyAccessCodeParams, PoolTotalParticipantsParams, SearchPoolParams, RelatedPoolsParams, UpdateStreamingParams, UpdatePoolResolutionTimeParams, FindPoolFallbackParams, SignOraclesExtendTimeParams, TrendingTagsParams } from './types.js';
1
+ import { ApiConfig, ApiResponse, PublicPoolsParams, PrivatePoolsParams, PoolListingByCreatorParams, VerifyAccessCodeParams, PoolTotalParticipantsParams, SearchPoolParams, RelatedPoolsParams, UpdateStreamingParams, UpdatePoolResolutionTimeParams, FindPoolFallbackParams, SignOraclesExtendTimeParams, TrendingTagsParams, PaginatedPools } from './types.js';
2
2
  export declare function accessPool(params: {
3
3
  poolId: string;
4
4
  accessCode: string;
5
5
  }, config: ApiConfig): Promise<ApiResponse>;
6
- export declare function getPublicPools(params: PublicPoolsParams, config: ApiConfig): Promise<ApiResponse>;
7
- export declare function getPrivatePools(params: PrivatePoolsParams, config: ApiConfig): Promise<ApiResponse>;
6
+ export declare function getPublicPools(params: PublicPoolsParams, config: ApiConfig): Promise<ApiResponse<PaginatedPools>>;
7
+ export declare function getPrivatePools(params: PrivatePoolsParams, config: ApiConfig): Promise<ApiResponse<PaginatedPools>>;
8
8
  export declare function getPoolById(params: {
9
9
  id: string;
10
10
  }, config: ApiConfig): Promise<ApiResponse>;
package/dist/api/pools.js CHANGED
@@ -9,7 +9,7 @@ export async function getPublicPools(params, config) {
9
9
  method: 'GET',
10
10
  headers: buildHeaders(config),
11
11
  });
12
- return handleResponse(res);
12
+ return handleResponse(res, '/pools/public-pools');
13
13
  }
14
14
  export async function getPrivatePools(params, config) {
15
15
  const qs = buildQuery({ limit: params.limit, offset: params.offset, tag: params.tag, status: params.status });
@@ -17,7 +17,7 @@ export async function getPrivatePools(params, config) {
17
17
  method: 'GET',
18
18
  headers: buildHeaders(config),
19
19
  });
20
- return handleResponse(res);
20
+ return handleResponse(res, '/pools/pools-private');
21
21
  }
22
22
  export async function getPoolById(params, config) {
23
23
  const res = await fetch(`${config.apiUrl}/pools/pool/${encodeURIComponent(params.id)}`, {
@@ -87,6 +87,53 @@ export interface PoolToken {
87
87
  tokenLogo?: string;
88
88
  }
89
89
  export type PoolStatus = 'New' | 'Live' | 'Closing_Soon' | 'Pending_Finalization' | 'Waiting_for_Result' | 'Dispute_Window_Open' | 'Under_Dispute' | 'Appeal_Window_Open' | 'Under_Appeal' | 'Closed';
90
+ export type TradingModelName = 'AMM' | 'OrderBook';
91
+ /**
92
+ * A sub-market (option group) within a Pool. Known fields are typed; the
93
+ * `[key: string]: any` index signature preserves access to the long tail of
94
+ * server fields not yet enumerated here, so this is a safe superset — never a
95
+ * contradiction of the wire.
96
+ */
97
+ export interface SubPool {
98
+ _id?: string;
99
+ subPoolIndex?: number;
100
+ question?: string;
101
+ options?: PoolOption[];
102
+ contractAddress?: string;
103
+ [key: string]: any;
104
+ }
105
+ /**
106
+ * The central pool data model. Known fields are typed; the index signature keeps
107
+ * additional server fields accessible without a cast.
108
+ */
109
+ export interface Pool {
110
+ _id: string;
111
+ contractAddress?: string;
112
+ question?: string;
113
+ status?: PoolStatus;
114
+ tradingModel?: TradingModelName;
115
+ token?: PoolToken;
116
+ tags?: string[];
117
+ options?: PoolOption[];
118
+ subPools?: SubPool[];
119
+ isPrivate?: boolean;
120
+ startDate?: string;
121
+ endDate?: string;
122
+ createdAt?: string;
123
+ updatedAt?: string;
124
+ [key: string]: any;
125
+ }
126
+ /** Paginated pool listing returned by `getPublicPools` / `getPrivatePools`. */
127
+ export interface PaginatedPools {
128
+ pools: Pool[];
129
+ pagination?: {
130
+ total: number;
131
+ offset: number;
132
+ limit: number;
133
+ totalPages: number;
134
+ };
135
+ [key: string]: any;
136
+ }
90
137
  export interface CreatePoolParams {
91
138
  question: string;
92
139
  isPrivate: boolean;
@@ -1,3 +1,21 @@
1
+ /** Decode the `exp` (unix seconds) claim from a JWT without verifying it. Cross-environment (browser + Node). */
2
+ function decodeJwtExp(token) {
3
+ try {
4
+ const part = token.split('.')[1];
5
+ if (!part)
6
+ return undefined;
7
+ const b64 = part.replace(/-/g, '+').replace(/_/g, '/');
8
+ const padded = b64 + '='.repeat((4 - (b64.length % 4)) % 4);
9
+ const json = typeof atob === 'function'
10
+ ? atob(padded)
11
+ : Buffer.from(padded, 'base64').toString('binary');
12
+ const payload = JSON.parse(json);
13
+ return typeof payload?.exp === 'number' ? payload.exp : undefined;
14
+ }
15
+ catch {
16
+ return undefined;
17
+ }
18
+ }
1
19
  export async function loginUser(params) {
2
20
  const { signature, walletAddress, smartWalletAddress, referredBy, apiUrl } = params;
3
21
  // Plain-EOA integrations may omit smartWalletAddress; fall back to the EOA.
@@ -25,5 +43,5 @@ export async function loginUser(params) {
25
43
  if (!accessToken || !userId) {
26
44
  throw new Error('Login response missing token or user id');
27
45
  }
28
- return { accessToken, userId };
46
+ return { accessToken, userId, expiresAt: decodeJwtExp(accessToken) };
29
47
  }
@@ -13,4 +13,6 @@ export interface LoginResult {
13
13
  accessToken: string;
14
14
  /** Backend user ID */
15
15
  userId: string;
16
+ /** Token expiry as a unix timestamp (seconds), decoded from the JWT `exp` claim. Undefined if the token has no `exp`. */
17
+ expiresAt?: number;
16
18
  }
package/dist/index.d.ts CHANGED
@@ -7,6 +7,8 @@ export type { EntrySharesResult } from './markets/getEntryShares.js';
7
7
  export type { SellProceedsResult } from './markets/getSellProceeds.js';
8
8
  export type { OrderLevelInfo } from './markets/getOrderInfo.js';
9
9
  export { RainValidationError, assertDeadline, assertSlippage, assertOption } from './tx/validation.js';
10
+ export { executeTxs } from './tx/execute.js';
11
+ export type { TxExecutor } from './tx/execute.js';
10
12
  export type { LoginParams, LoginResult } from './auth/types.js';
11
13
  export { signLoginMessage } from './auth/signMessage.js';
12
14
  export type { ExtendTimeTxParams } from './tx/buildExtendTimeRawTx.js';
@@ -15,5 +17,5 @@ export type { TokenConfig } from './config/environments.js';
15
17
  export type { OptionDisputeInfo, OptionAppealInfo } from './markets/getDisputeState.js';
16
18
  export { USDRAbi } from './abi/USDRAbi.js';
17
19
  export * from './api/index.js';
18
- export { RainSocket } from './socket/RainSocket.js';
20
+ export { RainSocket, RAIN_SOCKET_EVENTS } from './socket/RainSocket.js';
19
21
  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';
package/dist/index.js CHANGED
@@ -3,7 +3,8 @@ export { RainAA } from './RainAA.js';
3
3
  export * from './types.js';
4
4
  export { TradingModel, OptionSide } from './tx/types.js';
5
5
  export { RainValidationError, assertDeadline, assertSlippage, assertOption } from './tx/validation.js';
6
+ export { executeTxs } from './tx/execute.js';
6
7
  export { signLoginMessage } from './auth/signMessage.js';
7
8
  export { USDRAbi } from './abi/USDRAbi.js';
8
9
  export * from './api/index.js';
9
- export { RainSocket } from './socket/RainSocket.js';
10
+ export { RainSocket, RAIN_SOCKET_EVENTS } from './socket/RainSocket.js';
@@ -1,33 +1,72 @@
1
+ import type { Pool, SubPool } from '../api/types.js';
1
2
  export type RainSocketEvent = 'enter-option' | 'exit-option' | 'liquidity' | 'split' | 'merge' | 'remove-liquidity' | 'sync-price' | 'order-created' | 'order-cancelled' | 'order-filled' | 'pool-closed' | 'pool-reverted' | 'pool-token-set' | 'streamingStatusChanged' | 'winner' | 'winner-proposer' | 'reveal-winner-available' | 'dispute-opened' | 'oracle-created' | 'dispute-time-extented' | 'appeal-opened' | 'appeal-winner-calculated' | 'dispute-winner' | 'appeal-winner' | 'claim-reward' | 'dispute-refund' | 'appeal-refund' | 'resolution-refund' | 'resolver-reward' | 'notifications' | 'pool';
3
+ /**
4
+ * Correctly-spelled, camelCase aliases for the raw wire event names — use these
5
+ * with the low-level `.on()` API instead of hand-typing the wire strings (some
6
+ * of which are misspelled upstream, e.g. `dispute-time-extented`).
7
+ */
8
+ export declare const RAIN_SOCKET_EVENTS: {
9
+ readonly enterOption: "enter-option";
10
+ readonly exitOption: "exit-option";
11
+ readonly liquidity: "liquidity";
12
+ readonly split: "split";
13
+ readonly merge: "merge";
14
+ readonly removeLiquidity: "remove-liquidity";
15
+ readonly syncPrice: "sync-price";
16
+ readonly orderCreated: "order-created";
17
+ readonly orderCancelled: "order-cancelled";
18
+ readonly orderFilled: "order-filled";
19
+ readonly poolClosed: "pool-closed";
20
+ readonly poolReverted: "pool-reverted";
21
+ readonly poolTokenSet: "pool-token-set";
22
+ readonly streamingStatusChanged: "streamingStatusChanged";
23
+ readonly winner: "winner";
24
+ readonly winnerProposer: "winner-proposer";
25
+ readonly revealWinnerAvailable: "reveal-winner-available";
26
+ readonly disputeOpened: "dispute-opened";
27
+ readonly oracleCreated: "oracle-created";
28
+ readonly disputeTimeExtended: "dispute-time-extented";
29
+ readonly appealOpened: "appeal-opened";
30
+ readonly appealWinnerCalculated: "appeal-winner-calculated";
31
+ readonly disputeWinner: "dispute-winner";
32
+ readonly appealWinner: "appeal-winner";
33
+ readonly claimReward: "claim-reward";
34
+ readonly disputeRefund: "dispute-refund";
35
+ readonly appealRefund: "appeal-refund";
36
+ readonly resolutionRefund: "resolution-refund";
37
+ readonly resolverReward: "resolver-reward";
38
+ readonly notifications: "notifications";
39
+ readonly pool: "pool";
40
+ };
2
41
  export interface EnterOptionEventData {
3
42
  enterOption: Record<string, any>;
4
- pool: Record<string, any>;
5
- subPool: Record<string, any>;
43
+ pool: Pool;
44
+ subPool: SubPool;
6
45
  }
7
46
  export interface ExitOptionEventData {
8
47
  exitOption: Record<string, any>;
9
- pool: Record<string, any>;
10
- subPool: Record<string, any>;
48
+ pool: Pool;
49
+ subPool: SubPool;
11
50
  }
12
51
  export interface LiquidityEventData {
13
52
  enterLiquidity: Record<string, any>;
14
- pool: Record<string, any>;
15
- subPool: Record<string, any>;
53
+ pool: Pool;
54
+ subPool: SubPool;
16
55
  }
17
56
  export interface SplitEventData {
18
57
  split: Record<string, any>;
19
- pool: Record<string, any>;
20
- subPool: Record<string, any>;
58
+ pool: Pool;
59
+ subPool: SubPool;
21
60
  }
22
61
  export interface MergeEventData {
23
62
  merge: Record<string, any>;
24
- pool: Record<string, any>;
25
- subPool: Record<string, any>;
63
+ pool: Pool;
64
+ subPool: SubPool;
26
65
  }
27
66
  export interface RemoveLiquidityEventData {
28
67
  removeLiquidity: Record<string, any>;
29
- pool: Record<string, any>;
30
- subPool: Record<string, any>;
68
+ pool: Pool;
69
+ subPool: SubPool;
31
70
  }
32
71
  export interface SyncPriceEventData {
33
72
  prices: Array<{
@@ -36,67 +75,67 @@ export interface SyncPriceEventData {
36
75
  percentage: number;
37
76
  subPoolIndex: number;
38
77
  }>;
39
- pool: Record<string, any>;
40
- subPool: Record<string, any>;
78
+ pool: Pool;
79
+ subPool: SubPool;
41
80
  }
42
81
  export interface OrderCreatedEventData {
43
82
  order: Record<string, any>;
44
- pool: Record<string, any>;
45
- subPool: Record<string, any>;
83
+ pool: Pool;
84
+ subPool: SubPool;
46
85
  }
47
86
  export interface OrderCancelledEventData {
48
87
  order: Record<string, any>;
49
- pool: Record<string, any>;
50
- subPool: Record<string, any>;
88
+ pool: Pool;
89
+ subPool: SubPool;
51
90
  }
52
91
  export interface OrderFilledEventData {
53
92
  filledOrder: Record<string, any>;
54
93
  pendingOrder?: Record<string, any>;
55
- pool: Record<string, any>;
56
- subPool: Record<string, any>;
94
+ pool: Pool;
95
+ subPool: SubPool;
57
96
  }
58
97
  export interface PoolClosedEventData {
59
- pool: Record<string, any>;
60
- subPool?: Record<string, any>;
98
+ pool: Pool;
99
+ subPool?: SubPool;
61
100
  }
62
101
  export interface PoolEventData {
63
- pool: Record<string, any>;
64
- subMarkets?: Record<string, any>[];
102
+ pool: Pool;
103
+ subMarkets?: SubPool[];
65
104
  }
66
105
  export interface WinnerEventData {
67
- pool: Record<string, any>;
68
- subPool: Record<string, any>;
106
+ pool: Pool;
107
+ subPool: SubPool;
69
108
  }
70
109
  export interface DisputeOpenedEventData {
71
- subPool: Record<string, any>;
110
+ subPool: SubPool;
72
111
  eventType: string;
73
112
  }
74
113
  export interface OracleCreatedEventData {
75
- pool: Record<string, any>;
76
- subPool: Record<string, any>;
114
+ pool: Pool;
115
+ subPool: SubPool;
77
116
  }
78
117
  export interface AppealOpenedEventData {
79
- pool: Record<string, any>;
80
- subPool: Record<string, any>;
118
+ pool: Pool;
119
+ subPool: SubPool;
81
120
  }
82
121
  export interface DisputeWinnerEventData {
83
- subPool: Record<string, any>;
122
+ subPool: SubPool;
84
123
  eventType: string;
85
124
  }
86
125
  export interface AppealWinnerEventData {
87
- subPool: Record<string, any>;
126
+ subPool: SubPool;
88
127
  eventType: string;
89
128
  winnerFinalized: boolean;
90
129
  }
91
130
  export interface ClaimRewardEventData {
92
131
  claimReward: Record<string, any>;
93
- pool: Record<string, any>;
94
- subPool: Record<string, any>;
132
+ pool: Pool;
133
+ subPool: SubPool;
95
134
  }
96
135
  export interface DisputeRefundEventData {
97
136
  claimReward: Record<string, any>;
98
- pool: Record<string, any>;
99
- subPool: Record<string, any>;
137
+ pool: Pool;
138
+ subPool: SubPool;
100
139
  }
101
140
  export declare class RainSocket {
102
141
  private socket;
@@ -153,12 +192,12 @@ export declare class RainSocket {
153
192
  onDisputeOpened(poolId: string, callback: (data: DisputeOpenedEventData) => void): () => void;
154
193
  onOracleCreated(poolId: string, callback: (data: OracleCreatedEventData) => void): () => void;
155
194
  onDisputeTimeExtended(poolId: string, callback: (data: {
156
- pool: Record<string, any>;
157
- subPool: Record<string, any>;
195
+ pool: Pool;
196
+ subPool: SubPool;
158
197
  }) => void): () => void;
159
198
  onAppealOpened(poolId: string, callback: (data: AppealOpenedEventData) => void): () => void;
160
199
  onAppealWinnerCalculated(poolId: string, callback: (data: {
161
- subPool: Record<string, any>;
200
+ subPool: SubPool;
162
201
  }) => void): () => void;
163
202
  onDisputeWinner(poolId: string, callback: (data: DisputeWinnerEventData) => void): () => void;
164
203
  onAppealWinner(poolId: string, callback: (data: AppealWinnerEventData) => void): () => void;
@@ -1,4 +1,42 @@
1
1
  import { io } from 'socket.io-client';
2
+ /**
3
+ * Correctly-spelled, camelCase aliases for the raw wire event names — use these
4
+ * with the low-level `.on()` API instead of hand-typing the wire strings (some
5
+ * of which are misspelled upstream, e.g. `dispute-time-extented`).
6
+ */
7
+ export const RAIN_SOCKET_EVENTS = {
8
+ enterOption: 'enter-option',
9
+ exitOption: 'exit-option',
10
+ liquidity: 'liquidity',
11
+ split: 'split',
12
+ merge: 'merge',
13
+ removeLiquidity: 'remove-liquidity',
14
+ syncPrice: 'sync-price',
15
+ orderCreated: 'order-created',
16
+ orderCancelled: 'order-cancelled',
17
+ orderFilled: 'order-filled',
18
+ poolClosed: 'pool-closed',
19
+ poolReverted: 'pool-reverted',
20
+ poolTokenSet: 'pool-token-set',
21
+ streamingStatusChanged: 'streamingStatusChanged',
22
+ winner: 'winner',
23
+ winnerProposer: 'winner-proposer',
24
+ revealWinnerAvailable: 'reveal-winner-available',
25
+ disputeOpened: 'dispute-opened',
26
+ oracleCreated: 'oracle-created',
27
+ disputeTimeExtended: 'dispute-time-extented',
28
+ appealOpened: 'appeal-opened',
29
+ appealWinnerCalculated: 'appeal-winner-calculated',
30
+ disputeWinner: 'dispute-winner',
31
+ appealWinner: 'appeal-winner',
32
+ claimReward: 'claim-reward',
33
+ disputeRefund: 'dispute-refund',
34
+ appealRefund: 'appeal-refund',
35
+ resolutionRefund: 'resolution-refund',
36
+ resolverReward: 'resolver-reward',
37
+ notifications: 'notifications',
38
+ pool: 'pool',
39
+ };
2
40
  export class RainSocket {
3
41
  socket = null;
4
42
  url;
@@ -0,0 +1,30 @@
1
+ import { RawTransaction } from "./types.js";
2
+ /**
3
+ * Pluggable executor for sending the raw transactions the builders produce.
4
+ * Adapt it to viem, ethers, RainAA, or your own KMS — the SDK stays key-agnostic.
5
+ *
6
+ * @example viem
7
+ * const executor = {
8
+ * send: (tx) => walletClient.sendTransaction({ to: tx.to, data: tx.data, value: tx.value ?? 0n }),
9
+ * wait: (hash) => publicClient.waitForTransactionReceipt({ hash }),
10
+ * };
11
+ *
12
+ * @example RainAA (session key)
13
+ * const executor = { send: (tx) => rainAA.sendTransaction(tx) };
14
+ */
15
+ export interface TxExecutor {
16
+ /** Broadcast one transaction and resolve with its hash. */
17
+ send: (tx: RawTransaction) => Promise<`0x${string}`>;
18
+ /** Optional: wait for a hash to be mined before the next send. Strongly recommended for approval→main sequences. */
19
+ wait?: (hash: `0x${string}`) => Promise<unknown>;
20
+ }
21
+ /**
22
+ * Sequences an ordered list of raw transactions through an executor, awaiting
23
+ * each receipt (when `wait` is provided) before sending the next. This is the
24
+ * correct way to handle the `[approval, main]` arrays the builders return —
25
+ * sending the main tx before the approval lands is the most common integration
26
+ * bug.
27
+ *
28
+ * @returns the transaction hashes, in order.
29
+ */
30
+ export declare function executeTxs(txs: RawTransaction[], executor: TxExecutor): Promise<`0x${string}`[]>;
@@ -0,0 +1,25 @@
1
+ /**
2
+ * Sequences an ordered list of raw transactions through an executor, awaiting
3
+ * each receipt (when `wait` is provided) before sending the next. This is the
4
+ * correct way to handle the `[approval, main]` arrays the builders return —
5
+ * sending the main tx before the approval lands is the most common integration
6
+ * bug.
7
+ *
8
+ * @returns the transaction hashes, in order.
9
+ */
10
+ export async function executeTxs(txs, executor) {
11
+ if (!txs || txs.length === 0)
12
+ return [];
13
+ if (typeof executor?.send !== 'function') {
14
+ throw new Error("executor.send is required");
15
+ }
16
+ const hashes = [];
17
+ for (const tx of txs) {
18
+ const hash = await executor.send(tx);
19
+ hashes.push(hash);
20
+ if (executor.wait) {
21
+ await executor.wait(hash);
22
+ }
23
+ }
24
+ return hashes;
25
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "rain-sdk-v2",
3
- "version": "2.2.0",
3
+ "version": "2.3.0",
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",