@rainprotocolsdk/sdk 2.1.2 → 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/README.md CHANGED
@@ -1,932 +1,952 @@
1
- # Rain SDK Documentation
1
+ # Rain Builders — SDK Guide
2
2
 
3
- ## Overview
3
+ Build complete prediction markets, trading applications, and custom integrations powered by Rain's automated protocol.
4
4
 
5
- Rain SDK is designed as a **clean, modular, and extensible TypeScript SDK** for interacting with Rain markets and preparing on-chain transactions.
5
+ The Rain SDK provides the TypeScript tools you need to interact with our protocol on Arbitrum One. You can use it to build, sign, and send transactions for everything from creating new markets to trading options and claiming winnings.
6
6
 
7
- The SDK is intentionally split into two layers:
7
+ Whether you're building a custom frontend, routing trades for your users, or launching specialized pools, the SDK handles the technical execution. By integrating Rain, you plug directly into our automated market maker (AMM) liquidity for logic-based forecasts.
8
8
 
9
- * **Rain** Stateless, public-facing utilities (data fetching, raw transaction builders)
10
- * **RainAA** → Stateful Account Abstraction layer (smart accounts)
9
+ If you're building high-speed applications, you can tap into our **RNG Layer**. This system uses verifiable randomness through Chainlink VRF to power mathematically-driven risk scenarios. Instead of using the individual pools required for standard prediction markets, the RNG Layer draws from a single shared liquidity pool. This gives your users instant settlement for fast-paced, random markets across any application built on this layer.
11
10
 
12
- ---
11
+ You can also give your users a simpler trading experience. The SDK includes an **account abstraction module**. This lets you manage smart accounts and sponsor gas fees, so your users can trade without worrying about network costs.
13
12
 
14
- ## Installation
13
+ Our Builder Program supports platforms that drive volume or create unique markets. You bring the users and the ideas, and the SDK provides the on-chain infrastructure.
15
14
 
16
- ```bash
17
- npm install @rainprotocolsdk/sdk
18
- ```
15
+ ---
19
16
 
20
- or
17
+ ## What You Can Build
21
18
 
22
- ```bash
23
- yarn add @rainprotocolsdk/sdk
24
- ```
19
+ The SDK gives you direct access to the protocol's core functions. Here is what you can do right away.
25
20
 
26
- ---
21
+ - **Permissionless Market Creation** — Launch public or private markets on any verifiable event. You define the options, set the resolution rules, and provide the initial liquidity in a single transaction. Rain is open for anyone to build on, so you never need our approval to start a new pool.
22
+ - **Trading** — Construct interfaces for your users to buy and sell outcome shares against the AMM with market and limit orders.
23
+ - **Gas-Sponsored Execution** — Route transactions through the `RainAA` module. We use Alchemy smart accounts to cover gas costs. Your users can trade and interact with the protocol without needing to hold native ETH in their wallets.
24
+ - **Live Data Streams** — Connect to our WebSockets via `RainSocket` to receive real-time trade events, order activity, dispute updates, and market resolution notifications directly in your front end.
27
25
 
28
- ### Initialization
26
+ ---
29
27
 
30
- ```ts
31
- import { Rain } from "@rainprotocolsdk/sdk";
28
+ ## SDK Architecture: The Two Pillars
32
29
 
33
- const rain = new Rain();
34
- ```
30
+ The SDK is split into two independent classes. This structure separates the logical transaction building from the actual execution.
35
31
 
36
- ### Constructor Parameters
32
+ | Module | Role | Core Functions | Wallet Required |
33
+ | ------------------- | ---------------------- | ------------------------------------------------------------------- | --------------- |
34
+ | `Rain` (Stateless) | Defines **what** to do | Market queries, transaction builders | No |
35
+ | `RainAA` (Stateful) | Defines **how** to execute | Smart account creation, gas-sponsored execution, session management | Yes |
37
36
 
38
- ```ts
39
- interface RainCoreConfig {
40
- environment?: "development" | "stage" | "production"; // default: "development"
41
- rpcUrl?: string; // optional custom RPC URL
42
- }
43
- ```
37
+ ### The Execution Flow
44
38
 
45
- ---
39
+ 1. **Your Application** — The user interacts with your custom frontend.
40
+ 2. **The `Rain` Class** — Your application calls a method here to build an action. All transaction builders return an unsigned `RawTransaction` containing the `to`, `data`, and optional `value` fields.
41
+ 3. **The `RainAA` Class** — You pass that `RawTransaction` into this module. It manages the Alchemy smart accounts and signs the transaction via account abstraction, covering the network fees.
42
+ 4. **Arbitrum One** — The transaction settles on-chain, interacting with our Diamond Proxy pools and the specific AMM for that option.
46
43
 
47
- ## login
44
+ ### The `Rain` Class (Stateless)
48
45
 
49
- Authenticates a user against the Rain backend using a wallet signature and returns a JWT access token.
46
+ `Rain` operates without state. It fetches data and builds unsigned transactions. It does not require a connected wallet.
50
47
 
51
- The caller is responsible for signing the message pass the resulting signature along with the wallet addresses.
48
+ You use this class to query the protocol and construct actions. Because it returns a standard `RawTransaction`, you retain the freedom to decide how to execute it — whether you use `RainAA`, `wagmi`, `ethers`, or another custom provider.
52
49
 
53
- ### Method Signature
50
+ ### The `RainAA` Class (Stateful Execution)
54
51
 
55
- ```ts
56
- login(params: LoginParams): Promise<LoginResult>
57
- ```
52
+ `RainAA` maintains state. It handles the mechanics of account abstraction.
58
53
 
59
- ### Parameters
54
+ Once your stateless class generates the transaction data, you pass it here. This module takes care of the execution. It sponsors gas costs so your users do not need native ETH to trade.
60
55
 
61
- ```ts
62
- interface LoginParams {
63
- signature: string; // personal_sign of the lowercased wallet address
64
- walletAddress: string; // EOA wallet address
65
- smartWalletAddress: string; // Smart account / AA wallet address
66
- referredBy?: string; // Optional referral code
67
- }
68
- ```
56
+ ---
69
57
 
70
- ### Return Type
58
+ ## Quick Start
71
59
 
72
- ```ts
73
- interface LoginResult {
74
- accessToken: string; // JWT token for authenticated API calls
75
- userId: string; // Backend user ID
76
- }
77
- ```
60
+ The Rain SDK is designed to get you reading data and building transactions as quickly as possible. Because the core `Rain` class is stateless, you can start fetching markets and building trade payloads without requiring users to connect a wallet upfront.
78
61
 
79
- ### Example
62
+ ### Installation
80
63
 
81
- ```ts
82
- // 1. Sign the message with your wallet provider
83
- const signature = await walletClient.signMessage({
84
- message: walletAddress.toLowerCase(),
85
- });
64
+ First, install the SDK into your project using your preferred package manager.
86
65
 
87
- // 2. Login
88
- const { accessToken, userId } = await rain.login({
89
- signature,
90
- walletAddress: "0x996ea23940f4a01610181D04bdB6F862719b63f0",
91
- smartWalletAddress: "0xSmartAccountAddress...",
92
- referredBy: "REFCODE123", // optional
93
- });
66
+ ```bash
67
+ npm install @rainprotocolsdk/sdk
68
+ npm install viem@^2.0.0 # Required peer dependency
94
69
  ```
95
70
 
96
- ---
71
+ ### Your First Trade Flow
97
72
 
98
- ## getPublicMarkets
73
+ Here is a complete example of how you initialize the client, read active markets from the protocol, build a transaction to buy shares, and execute it.
99
74
 
100
- Fetches public market data from the Rain backend.
75
+ **1. Initialize (stateless no wallet needed)**
101
76
 
102
- ### Method Signature
77
+ You set up the `Rain` class by pointing it to the development environment. This automatically configures the correct factory addresses and API endpoints.
103
78
 
104
79
  ```ts
105
- getPublicMarkets(params: GetMarketsParams): Promise<Market[]>;
80
+ const rain = new Rain({ environment: 'development' });
106
81
  ```
107
82
 
108
- ### Parameters
109
-
110
- ```ts
111
- interface GetMarketsParams {
112
- limit?: number;
113
- offset?: number;
114
- sortBy?: "Liquidity" | "Volumn" | "latest";
115
- status?: 'Live' | 'New' | 'WaitingForResult' | 'UnderDispute' | 'UnderAppeal' | 'ClosingSoon' | 'InReview' | 'InEvaluation' | 'Closed' | 'Trading';
116
- }
117
- ```
83
+ **2. Fetch Markets**
118
84
 
119
- ### Example
85
+ You query the protocol for a list of active markets. This pulls data directly from the Rain API.
120
86
 
121
87
  ```ts
122
- const markets = await rain.getPublicMarkets({
123
- limit: 12,
124
- offset: 1,
125
- sortBy: "Liquidity",
126
- status: "Live",
127
- });
88
+ const markets = await rain.getPublicMarkets({ limit: 10 });
128
89
  ```
129
90
 
130
- ---
131
-
132
- ## getMarketById
133
-
134
- Fetches a single market by its ID from the Rain backend.
91
+ **3. Build a Buy Transaction**
135
92
 
136
- ### Method Signature
93
+ You define exactly what you want to do. In this case, you are building the raw transaction data to buy $10 worth of shares in Option 1.
137
94
 
138
95
  ```ts
139
- getMarketById(params: GetMarketByIdParams): Promise<Market>
96
+ const rawTx = rain.buildBuyOptionRawTx({
97
+ marketContractAddress: '0x...',
98
+ selectedOption: 1n,
99
+ buyAmountInWei: 10_000_000n, // 10 USDT (Arbitrum USDT uses 6 decimals)
100
+ });
140
101
  ```
141
102
 
142
- ### Parameters
103
+ **4. Execute**
104
+
105
+ The SDK hands you back an unsigned `RawTransaction` (`{ to, data, value }`). You then pass this payload to your user's standard wallet provider, or route it through the `RainAA` class for gasless execution.
143
106
 
144
107
  ```ts
145
- interface GetMarketByIdParams {
146
- marketId: string; // MongoDB _id of the market
147
- }
108
+ await yourProvider.sendTransaction(rawTx);
148
109
  ```
149
110
 
150
- ### Validations
111
+ ---
151
112
 
152
- | Parameter | Type | Required | Description |
153
- | ---------- | -------- | -------- | ---------------------- |
154
- | `marketId` | `string` | ✅ | Unique market `_id` |
113
+ ## Authentication
155
114
 
156
- ### Example
115
+ Before accessing protected endpoints, users must authenticate with the Rain API.
157
116
 
158
117
  ```ts
159
- const market = await rain.getMarketById({
160
- marketId: "698c8f116e985bbfacc7fc01",
118
+ const result = await rain.login({
119
+ walletAddress: '0x996ea23940f4a01610181D04bdB6F862719b63f0',
120
+ signature: '0x...', // Signed message from user's wallet
161
121
  });
122
+ // Returns: { accessToken, userId, ... }
162
123
  ```
163
124
 
125
+ The `accessToken` returned is required for methods that need user context, such as `getUserInvestments`, `buildClaimTx`, and `buildExtendTimeTx`.
126
+
164
127
  ---
165
128
 
166
- ## getUserInvestments
129
+ ## Creating a Market
167
130
 
168
- Fetches a user's invested markets from the Rain backend. Requires a valid access token.
131
+ Launch your own prediction markets on any verifiable event.
169
132
 
170
- ### Method Signature
133
+ One of the core features of building on Rain is permissionless market creation. You do not need approval to start a new pool. If an event has a verifiable outcome, you can build a market around it using the SDK.
171
134
 
172
- ```ts
173
- getUserInvestments(params: GetUserInvestmentsParams): Promise<UserInvestment[]>
174
- ```
135
+ When you create a market, you define the question, set the possible options, and provide the initial liquidity. This liquidity allows the Automated Market Maker (AMM) to start pricing shares immediately.
175
136
 
176
- ### Parameters
137
+ ### Public vs. Private Markets
177
138
 
178
- ```ts
179
- interface GetUserInvestmentsParams {
180
- walletAddress: string; // User's wallet address
181
- accessToken: string; // JWT from Rain auth (login)
182
- limit?: number;
183
- offset?: number;
184
- status?: 'Live' | 'New' | 'WaitingForResult' | 'UnderDispute' | 'UnderAppeal' | 'ClosingSoon' | 'InReview' | 'InEvaluation' | 'Closed' | 'Trading';
185
- }
186
- ```
139
+ Before writing the code, you need to decide what kind of market you are building using the `isPublic` parameter.
140
+
141
+ - **Public Markets** These are open to anyone and are great for topics like sports, politics, or global events. The market can be resolved either by a specialized AI oracle or by the market creator.
142
+ - **Private Markets** These are designed for specific groups or topics and require a secret access code to join. The person who creates the pool acts as the resolver and decides the outcome.
187
143
 
188
- ### Validations
144
+ ### Building the Transaction
189
145
 
190
- | Parameter | Type | Required | Description |
191
- | --------------- | ------------- | -------- | ------------------------------------ |
192
- | `walletAddress` | `string` | ✅ | The user's wallet address |
193
- | `accessToken` | `string` | ✅ | JWT returned from `login()` |
194
- | `limit` | `number` | ❌ | Number of results per page |
195
- | `offset` | `number` | ❌ | Pagination offset |
196
- | `status` | `MarketStatus`| ❌ | Filter by market status |
146
+ You use the stateless `Rain` class to construct the transaction. The `buildCreateMarketTx` method requires specific parameters to set the probabilities, dates, and token decimals.
197
147
 
198
- ### Example
148
+ Because creating a market usually requires approving the token spend first, this method returns an array of raw transactions that you must execute in order.
199
149
 
200
150
  ```ts
201
- const investments = await rain.getUserInvestments({
202
- walletAddress: "0x996ea23940f4a01610181D04bdB6F862719b63f0",
203
- accessToken: "eyJhbGciOi...",
204
- limit: 10,
205
- offset: 1,
206
- status: "Live",
151
+ import { Rain } from '@rainprotocolsdk/sdk';
152
+
153
+ const rain = new Rain({ environment: 'production' });
154
+
155
+ // buildCreateMarketTx returns an array: [approveTx, createTx] or just [createTx]
156
+ const txs = await rain.buildCreateMarketTx({
157
+ marketQuestion: 'Will BTC hit 100k?',
158
+ marketOptions: ['Yes', 'No', 'Maybe'],
159
+ marketTags: ['crypto', 'bitcoin'],
160
+ marketDescription: 'Prediction market for BTC price',
161
+ isPublic: true,
162
+ isPublicPoolResolverAi: false,
163
+ creator: '0x996ea23940f4a01610181D04bdB6F862719b63f0',
164
+ startTime: 1770836400n,
165
+ endTime: 1770922800n,
166
+ no_of_options: 3n,
167
+ inputAmountWei: 100_000_000n, // 100 USDT (min 10 tokens)
168
+ barValues: [34, 33, 33], // Initial probability distribution (%)
169
+ baseToken: '0xFd086bC7CD5C481DCC9C85ebE478A1C0b69FCbb9',
170
+ tokenDecimals: 6,
207
171
  });
172
+
173
+ // Execute sequentially
174
+ for (const tx of txs) {
175
+ await yourProvider.sendTransaction(tx);
176
+ }
208
177
  ```
209
178
 
179
+ ### Breaking Down the Parameters
180
+
181
+ - **Text Fields** — `marketQuestion`, `marketDescription`, and `marketTags` define how the market appears to users.
182
+ - **Options** — `marketOptions` is an array of the possible outcomes. `no_of_options` is the numerical count of those choices.
183
+ - **Permissions** — `isPublic` determines if the market is open or access-restricted. `isPublicPoolResolverAi` dictates if the AI oracle handles the resolution.
184
+ - **Timing** — `startTime` and `endTime` are Unix timestamps defining when the market is active.
185
+ - **Liquidity & Tokens** — `inputAmountWei` is your initial funding. The minimum requirement is $10 in the chosen token. `baseToken` is the contract address of the currency being used, and `tokenDecimals` ensures the math is calculated correctly.
186
+ - **Initial Odds** — `barValues` sets the starting probability distribution for the options as a percentage. All values must sum to 100.
187
+
188
+ ### Managing the Market Lifecycle
189
+
190
+ Creating the market is just the first step. To manage the conclusion of a market, the SDK provides these transaction builders:
191
+
192
+ - `buildCloseMarketTx(params)` — Builds a raw transaction to officially close the market and halt trading.
193
+ - `buildCreateDisputeTx(params)` — Builds a raw transaction to open a dispute on the market outcome.
194
+ - `buildCreateAppealTx(params)` — Builds a raw transaction to appeal a dispute decision.
195
+ - `buildExtendTimeTx(params)` — Builds a raw transaction to extend the dispute resolution window (re-submit appeal).
196
+
210
197
  ---
211
198
 
212
- ## buildApprovalTx
199
+ ## Trading & Positions
213
200
 
214
- Builds a raw ERC20 approval transaction if needed.
201
+ Build interfaces for buying shares, placing limit orders, and claiming winnings.
215
202
 
216
- This function prepares an unsigned `approve(spender, amount)` transaction and does not execute it.
203
+ Once a market is live, participants can start taking positions. The Rain SDK allows you to construct trading actions directly from the protocol.
217
204
 
218
- If `amount` is not provided, a default large allowance is approved.
205
+ Because trades happen against our Automated Market Maker (AMM), your users get instant execution. They do not have to wait for a counterparty to match their order.
219
206
 
220
- ### Return Type
207
+ ### Buying Options
221
208
 
222
- ```ts
223
- interface RawTransaction {
224
- to: `0x${string}`;
225
- data: `0x${string}`;
226
- }
227
- ```
209
+ When a user buys an option, they are purchasing shares of a specific outcome. The price of these shares is determined by the AMM based on the current pool ratios.
228
210
 
229
- ### Example
211
+ Here is how you build a standard market order to buy shares.
230
212
 
231
213
  ```ts
232
- const approvalTx = rain.buildApprovalTx({
233
- tokenAddress: "0xTokenAddress...", // ERC20 token address
234
- spender: "0xMarketContractAddress...", // Market contract address
235
- amount: 1000000000000000000n // optional
214
+ import { Rain } from '@rainprotocolsdk/sdk';
215
+
216
+ const rain = new Rain({ environment: 'production' });
217
+
218
+ // Build the raw buy transaction
219
+ const buyTx = rain.buildBuyOptionRawTx({
220
+ marketContractAddress: '0x...',
221
+ selectedOption: 1n, // The option index (e.g., 0 for Yes, 1 for No)
222
+ buyAmountInWei: 10_000_000n, // 10 USDT (Arbitrum USDT uses 6 decimals)
236
223
  });
237
224
  ```
238
225
 
239
- ---
240
-
241
- ## buildBuyOptionRawTx
226
+ If a user wants to set a specific entry target rather than taking the current AMM price, you can build a limit order instead.
242
227
 
243
- Builds a **raw EVM transaction** for entering a market option.
228
+ ```ts
229
+ // Build a limit buy transaction
230
+ const limitTx = rain.buildLimitBuyOptionTx({
231
+ marketContractAddress: '0x...',
232
+ selectedOption: 1,
233
+ pricePerShare: 500000000000000000n, // 0.50 represented in 1e18
234
+ buyAmountInWei: 10_000_000n,
235
+ tokenDecimals: 6,
236
+ });
237
+ ```
244
238
 
245
- This function **does not send the transaction** — it only prepares calldata.
239
+ ### Selling Options
246
240
 
247
- ### Method Signature
241
+ Users do not have to hold their shares until the market resolves. If the odds shift in their favor, they can sell their position early to lock in a profit.
248
242
 
249
243
  ```ts
250
- buildBuyOptionRawTx(params: EnterOptionTxParams): RawTransaction;
244
+ // Build a limit sell transaction
245
+ const sellTx = rain.buildLimitSellOptionTx({
246
+ marketContractAddress: '0x...',
247
+ selectedOption: 1,
248
+ pricePerShare: 500000000000000000n, // 0.50 represented in 1e18
249
+ shares: 5_000_000n, // The number of shares to sell
250
+ tokenDecimals: 6,
251
+ });
251
252
  ```
252
253
 
253
- ### Parameters
254
+ ### Canceling Orders
255
+
256
+ If a user places limit orders that have not been filled yet, they might want to cancel them. You can build a transaction to remove specific open orders by referencing their order IDs, or cancel all open orders at once.
254
257
 
255
258
  ```ts
256
- interface EnterOptionTxParams {
257
- marketContractAddress: `0x${string}`; // TradeMarket contract address
258
- selectedOption: bigint; // Option index
259
- buyAmountInWei: bigint; // Amount in wei
260
- }
259
+ // Build a transaction to cancel specific open orders
260
+ const cancelTx = rain.buildCancelOrdersTx({
261
+ marketContractAddress: '0x...',
262
+ orders: [
263
+ { option: 1, price: 0.5, orderID: 1n },
264
+ { option: 1, price: 0.6, orderID: 2n },
265
+ ],
266
+ });
267
+
268
+ // Build a transaction to cancel all open orders for a user
269
+ const cancelAllTx = await rain.buildCancelAllOpenOrdersTx({
270
+ marketContractAddress: '0x...',
271
+ walletAddress: '0x...',
272
+ accessToken: 'your-access-token',
273
+ });
261
274
  ```
262
275
 
263
- ### Return Type
276
+ ### Claiming Winnings
264
277
 
265
- ```ts
266
- interface RawTransaction {
267
- to: `0x${string}`;
268
- data: `0x${string}`;
269
- }
270
- ```
278
+ When a market concludes, it goes through a resolution phase and a short dispute window. Once that window closes, the market is officially settled.
271
279
 
272
- ### Example
280
+ Users who hold shares in the winning outcome can then claim their payout. The payout is drawn from the total pool of funds, after a platform fee is collected.
273
281
 
274
282
  ```ts
275
- const rawTx = rain.buildBuyOptionRawTx({
276
- marketContractAddress: "0xMarketContractAddress...",
277
- selectedOption: 1n,
278
- buyAmountInWei: 1000000n,
283
+ // Build the raw claim transaction
284
+ const claimTx = await rain.buildClaimTx({
285
+ marketId: '698c8f116e985bbfacc7fc01',
286
+ walletAddress: '0x996ea23940f4a01610181D04bdB6F862719b63f0',
279
287
  });
280
288
  ```
281
289
 
290
+ This single transaction sends the user's original stake plus their winnings directly to their wallet or smart account.
291
+
282
292
  ---
283
293
 
284
- ## buildLimitBuyOptionTx
294
+ ## Liquidity
285
295
 
286
- Builds a **raw EVM transaction** for placing a limit buy order on a Rain market.
296
+ Every market on Rain needs liquidity to function. Because trades execute against an Automated Market Maker (AMM), the pool requires an initial supply of funds to price shares and settle outcomes.
287
297
 
288
- This function **does not send the transaction** — it only prepares calldata.
298
+ ### Adding Liquidity
289
299
 
290
- ### Method Signature
300
+ Use `buildAddLiquidityTx` to let users supply funds to an existing market. The SDK reads the market's base token on-chain and only requests the approval needed — either USDT or RAIN, depending on the market.
291
301
 
292
302
  ```ts
293
- buildLimitBuyOptionTx(params: EnterLimitOptionTxParams): RawTransaction
294
- ```
295
-
296
- ### Parameters
303
+ const txs = await rain.buildAddLiquidityTx({
304
+ marketContractAddress: '0x...',
305
+ walletAddress: '0x...',
306
+ amount: 100, // human-readable amount — decimals auto-detected (6 for USDT, 18 for RAIN)
307
+ });
297
308
 
298
- ```ts
299
- interface EnterLimitOptionTxParams {
300
- marketContractAddress: `0x${string}`; // Market contract address
301
- selectedOption: number; // Option index
302
- pricePerShare: number; // Limit price per share (between 0 and 1)
303
- buyAmountInWei: bigint; // Total buy amount in token wei
304
- tokenDecimals?: number; // Token decimals (default: 6)
309
+ // Execute sequentially
310
+ for (const tx of txs) {
311
+ await yourProvider.sendTransaction(tx);
305
312
  }
306
313
  ```
307
314
 
308
- ### Validations
315
+ Returns `[approveTx, enterLiquidityTx]` if the allowance is insufficient, or `[enterLiquidityTx]` if already approved.
309
316
 
310
- | Field | Type | Required | Description |
311
- | ----------------------- | ------------- | -------- | ------------------------------------------------------ |
312
- | `marketContractAddress` | `0x${string}` | ✅ | Address of the market contract |
313
- | `selectedOption` | `number` | ✅ | Option index to place the buy order for |
314
- | `pricePerShare` | `number` | ✅ | Limit price per share (between `0` and `1`) |
315
- | `buyAmountInWei` | `bigint` | ✅ | Total amount to spend (already converted to token wei) |
316
- | `tokenDecimals` | `number` | ❌ | Token decimals (default: `6`) |
317
+ ### How LPs Earn Fees
317
318
 
318
- ### Return Type
319
+ Liquidity providers take on the other side of the trades. They fund the entire market rather than betting on "Yes" or "No". In return for taking on this risk, they earn a cut of the trading activity.
319
320
 
320
- ```ts
321
- interface RawTransaction {
322
- to: `0x${string}`;
323
- data: `0x${string}`;
324
- }
325
- ```
321
+ The protocol charges a 5% fee on transactions. From that total volume, 1.2% is automatically distributed back to the liquidity providers of that specific market.
326
322
 
327
- ### Example
323
+ For applications built on the RNG Layer, like Risk Markets, liquidity providers act as the "house". They still earn the 1.2% volume fee. Additionally, if players fail to exit their positions before a scenario terminates, their stakes remain in the pool, which increases the value of the LP shares.
328
324
 
329
- ```ts
330
- rain.buildLimitBuyOptionTx({
331
- marketContractAddress: "0xMarketContractAddress...",
332
- selectedOption: 1,
333
- pricePerShare: 0.6,
334
- buyAmountInWei: 1000000n,
335
- });
336
- ```
325
+ ### Withdrawing Liquidity
337
326
 
338
- ---
327
+ Liquidity is locked until the market reaches its resolution. There is no method to remove liquidity while the market is active.
339
328
 
340
- ## buildLimitSellOptionTx
329
+ Liquidity providers recover their initial supplied share, plus any accumulated fees, by using the standard `buildClaimTx` method after the market officially resolves and settles.
341
330
 
342
- Builds a **raw EVM transaction** for placing a limit sell order on a Rain market.
331
+ ---
343
332
 
344
- This function **does not send the transaction** — it only prepares calldata.
333
+ ## Disputes & Appeals
345
334
 
346
- ### Method Signature
335
+ When a market resolves, participants can challenge the outcome through the dispute and appeal system.
347
336
 
348
- ```ts
349
- buildLimitSellOptionTx(params: LimitSellOptionTxParams): RawTransaction
350
- ```
337
+ ### Opening a Dispute
351
338
 
352
- ### Parameters
339
+ If a participant believes the market outcome is incorrect, they can open a dispute.
353
340
 
354
341
  ```ts
355
- interface LimitSellOptionTxParams {
356
- marketContractAddress: `0x${string}`; // Market contract address
357
- selectedOption: number; // Option index
358
- pricePerShare: number; // Limit price per share (between 0 and 1)
359
- sharesAmountWei: bigint; // Number of shares to sell (in wei)
360
- tokenDecimals?: number; // Token decimals (default: 6)
342
+ const disputeTxs = await rain.buildCreateDisputeTx({
343
+ marketContractAddress: '0x...',
344
+ walletAddress: '0x...',
345
+ accessToken: 'your-access-token',
346
+ });
347
+
348
+ for (const tx of disputeTxs) {
349
+ await yourProvider.sendTransaction(tx);
361
350
  }
362
351
  ```
363
352
 
364
- ### Validations
365
-
366
- | Field | Type | Required | Description |
367
- | ----------------------- | ------------- | -------- | ------------------------------------------- |
368
- | `marketContractAddress` | `0x${string}` | ✅ | Address of the market contract |
369
- | `selectedOption` | `number` | ✅ | Option index to place the sell order for |
370
- | `pricePerShare` | `number` | ✅ | Limit price per share (between `0` and `1`) |
371
- | `sharesAmountWei` | `bigint` | ✅ | Number of shares to sell (must be `> 0`) |
372
- | `tokenDecimals` | `number` | ❌ | Token decimals (default: `6`) |
353
+ ### Filing an Appeal
373
354
 
374
- ### Return Type
355
+ If the dispute resolution is also contested, participants can escalate it through an appeal.
375
356
 
376
357
  ```ts
377
- interface RawTransaction {
378
- to: `0x${string}`;
379
- data: `0x${string}`;
358
+ const appealTxs = await rain.buildCreateAppealTx({
359
+ marketContractAddress: '0x...',
360
+ walletAddress: '0x...',
361
+ accessToken: 'your-access-token',
362
+ });
363
+
364
+ for (const tx of appealTxs) {
365
+ await yourProvider.sendTransaction(tx);
380
366
  }
381
367
  ```
382
368
 
383
- ### Example
369
+ ### Extending the Dispute Window
370
+
371
+ If more time is needed for resolution, the dispute window can be extended.
384
372
 
385
373
  ```ts
386
- rain.buildLimitSellOptionTx({
387
- marketContractAddress: "0xMarketContractAddress...",
388
- selectedOption: 0,
389
- pricePerShare: 0.4,
390
- sharesAmountWei: 500000n,
374
+ const extendTx = await rain.buildExtendTimeTx({
375
+ marketContractAddress: '0x...',
376
+ walletAddress: '0x...',
377
+ accessToken: 'your-access-token',
391
378
  });
379
+
380
+ await yourProvider.sendTransaction(extendTx);
392
381
  ```
393
382
 
394
383
  ---
395
384
 
396
- ## buildCancelOrdersTx
385
+ ## Account Abstraction
397
386
 
398
- Builds **raw EVM transactions** to cancel specific open orders on a Rain market.
387
+ Remove gas fees from your trading experience using stateful execution.
399
388
 
400
- Groups orders by type and returns up to two transactions one for sell orders (`cancelSellOrders`) and one for buy orders (`cancelBuyOrders`).
389
+ The SDK splits its functionality into two classes. While the `Rain` class is stateless and handles your queries and transaction building, it does not send transactions.
401
390
 
402
- This function **does not send the transaction** it only prepares calldata.
391
+ To execute trades without requiring users to hold native ETH for gas, you use the `RainAA` class. This stateful class manages Alchemy smart accounts with gas sponsorship.
403
392
 
404
- ### Method Signature
393
+ ### Setting Up the Execution Engine
405
394
 
406
- ```ts
407
- buildCancelOrdersTx(params: CancelOrdersTxParams): RawTransaction[]
408
- ```
409
-
410
- ### Parameters
395
+ To get started, you initialize the `RainAA` class with your standard viem wallet client and your Alchemy credentials.
411
396
 
412
397
  ```ts
413
- interface OrderToCancel {
414
- orderType: 'buy' | 'sell';
415
- option: bigint; // Option index (e.g. 0n for Yes, 1n for No)
416
- pricePerShare: bigint; // Price in 18-decimal wei
417
- orderId: bigint; // externalID from the open order
418
- }
398
+ import { RainAA } from '@rainprotocolsdk/sdk';
399
+ import { arbitrum } from 'viem/chains';
419
400
 
420
- interface CancelOrdersTxParams {
421
- marketContractAddress: `0x${string}`;
422
- orders: OrderToCancel[];
423
- }
401
+ const rainAA = new RainAA({
402
+ walletClient: yourWalletClient, // viem WalletClient
403
+ alchemyApiKey: 'your-alchemy-key',
404
+ paymasterPolicyId: 'your-policy-id',
405
+ chain: arbitrum,
406
+ rpcUrl: 'https://...', // Optional
407
+ });
424
408
  ```
425
409
 
426
- ### Validations
427
-
428
- | Field | Type | Required | Description |
429
- | ----------------------- | ---------------- | -------- | ------------------------------------- |
430
- | `marketContractAddress` | `0x${string}` | ✅ | Address of the market contract |
431
- | `orders` | `OrderToCancel[]`| ✅ | Non-empty array of orders to cancel |
432
-
433
- ### Return Type
410
+ Once initialized, you connect the client. This derives a smart account from the user's Externally Owned Account (EOA).
434
411
 
435
412
  ```ts
436
- RawTransaction[] // 1 tx if only buy or only sell; 2 txs if both
413
+ // Connect, derives smart account from EOA
414
+ const smartAccountAddress = await rainAA.connect();
415
+ console.log('Smart account:', smartAccountAddress);
437
416
  ```
438
417
 
439
- ### Example
418
+ ### Session Management
419
+
420
+ The `RainAA` class provides simple accessors to retrieve the connected smart account address and the underlying AA client. When the session is over, you can disconnect the user.
440
421
 
441
422
  ```ts
442
- const txs = rain.buildCancelOrdersTx({
443
- marketContractAddress: "0xMarketContractAddress...",
444
- orders: [
445
- {
446
- orderType: "buy",
447
- option: 0n,
448
- pricePerShare: 600000000000000000n, // 0.6 in 18 decimals
449
- orderId: 42n,
450
- },
451
- {
452
- orderType: "sell",
453
- option: 1n,
454
- pricePerShare: 400000000000000000n,
455
- orderId: 43n,
456
- },
457
- ],
458
- });
423
+ rainAA.address; // Smart account address (throws if not connected)
424
+ rainAA.client; // Underlying AA client (throws if not connected)
425
+
426
+ // Disconnect
427
+ rainAA.disconnect();
459
428
  ```
460
429
 
461
430
  ---
462
431
 
463
- ## buildCancelAllOpenOrdersTx
432
+ ## WebSockets & Live Data
464
433
 
465
- Fetches all open orders for a wallet on a given market from the Rain backend and builds the cancel transactions automatically.
434
+ Keep your application in sync with the protocol without constantly polling for updates.
466
435
 
467
- Returns an empty array if no open orders exist.
436
+ The `RainSocket` class provides a dedicated WebSocket client that connects to the Rain API and exposes typed event subscriptions. Each subscription method returns an unsubscribe function call it when the user navigates away to prevent memory leaks.
468
437
 
469
- ### Method Signature
438
+ ### Setting Up
470
439
 
471
440
  ```ts
472
- buildCancelAllOpenOrdersTx(params: CancelAllOpenOrdersTxParams): Promise<RawTransaction[]>
473
- ```
441
+ import { RainSocket } from '@rainprotocolsdk/sdk';
474
442
 
475
- ### Parameters
443
+ const rs = new RainSocket({ environment: 'production' });
476
444
 
477
- ```ts
478
- interface CancelAllOpenOrdersTxParams {
479
- marketId: string; // MongoDB _id of the market
480
- marketContractAddress: `0x${string}`; // Market contract address
481
- walletAddress: `0x${string}`; // User's wallet address
482
- accessToken: string; // JWT from Rain auth (login)
483
- }
445
+ rs.onConnect(() => console.log('Connected'));
446
+ rs.onDisconnect(() => console.log('Disconnected'));
484
447
  ```
485
448
 
486
- ### Validations
449
+ ### Trade Events
450
+
451
+ ```ts
452
+ // Fires when a user buys into a market option
453
+ const unsub = rs.onEnterOption(marketId, (data) => {
454
+ console.log(data.poolId, data.investments, data.totalInvestmentWei);
455
+ });
487
456
 
488
- | Field | Type | Required | Description |
489
- | ----------------------- | ------------- | -------- | ------------------------------------ |
490
- | `marketId` | `string` | ✅ | MongoDB `_id` from market data |
491
- | `marketContractAddress` | `0x${string}` | ✅ | Market contract address |
492
- | `walletAddress` | `0x${string}` | ✅ | Wallet address of the user |
493
- | `accessToken` | `string` | ✅ | JWT returned from `login()` |
457
+ // Fires when a new limit order is placed
458
+ const unsub = rs.onOrderCreated(marketId, (data) => {
459
+ console.log(data.poolId, data.order);
460
+ });
494
461
 
495
- ### Return Type
462
+ // Fires when an open order is cancelled
463
+ const unsub = rs.onOrderCancelled(marketId, (data) => {
464
+ console.log(data.poolId, data.order);
465
+ });
496
466
 
497
- ```ts
498
- RawTransaction[] // empty array if no open orders found
467
+ // Fires when a limit order is partially or fully filled
468
+ const unsub = rs.onOrderFilled(marketId, (data) => {
469
+ console.log(data.poolId, data.raw);
470
+ });
499
471
  ```
500
472
 
501
- ### Example
473
+ ### Dispute & Appeal Events
502
474
 
503
475
  ```ts
504
- const txs = await rain.buildCancelAllOpenOrdersTx({
505
- marketId: "698c8f116e985bbfacc7fc01",
506
- marketContractAddress: "0xMarketContractAddress...",
507
- walletAddress: "0x996ea23940f4a01610181D04bdB6F862719b63f0",
508
- accessToken: "eyJhbGciOi...",
476
+ // Fires when a dispute is opened on a market
477
+ const unsub = rs.onDisputeOpened(marketId, (data) => {
478
+ console.log(data.poolId, data.isDisputed, data.status);
509
479
  });
510
- ```
511
480
 
512
- ---
481
+ // Fires when an appeal is filed
482
+ const unsub = rs.onAppealOpened(marketId, (data) => {
483
+ console.log(data.poolId, data.isAppealed);
484
+ });
513
485
 
514
- ## buildCreateMarketTx
486
+ // Fires when the dispute window is extended
487
+ const unsub = rs.onDisputeTimeExtended(marketId, (data) => {
488
+ console.log(data.poolId, data.newEndTime);
489
+ });
490
+ ```
515
491
 
516
- Builds a **raw EVM transaction** for creating a market in Rain Protocol.
492
+ ### Resolution Events
517
493
 
518
- This function **does not send the transaction** — it only prepares calldata.
494
+ ```ts
495
+ // Fires when a dispute winner is decided
496
+ const unsub = rs.onDisputeWinner(marketId, (data) => {
497
+ console.log(data.poolId, data.winnerOption);
498
+ });
519
499
 
520
- ### Method Signature
500
+ // Fires when an appeal winner is finalized
501
+ const unsub = rs.onAppealWinner(marketId, (data) => {
502
+ console.log(data.poolId, data.winnerFinalized);
503
+ });
521
504
 
522
- ```ts
523
- buildCreateMarketTx(params: CreateMarketTxParams): Promise<RawTransaction[]>
505
+ // Fires when a user's reward claim is confirmed
506
+ // Note: requires both marketId and userId
507
+ const unsub = rs.onClaimReward(marketId, userId, (data) => {
508
+ console.log(data.poolId, data.userId);
509
+ });
524
510
  ```
525
511
 
526
- ### Parameters
512
+ ### Cleanup
527
513
 
528
514
  ```ts
529
- interface CreateMarketTxParams {
530
- marketQuestion: string;
531
- marketOptions: string[];
532
- marketTags: string[];
533
- marketDescription: string;
534
- isPublic: boolean;
535
- isPublicPoolResolverAi: boolean;
536
- creator: `0x${string}`;
537
- startTime: bigint; // Unix timestamp (seconds)
538
- endTime: bigint; // Must be > startTime
539
- no_of_options: bigint; // Number of options (>= 2)
540
- inputAmountWei: bigint; // Initial liquidity (token wei)
541
- barValues: number[]; // Token distribution per option in %
542
- baseToken: `0x${string}`; // ERC20 token address
543
- tokenDecimals?: number; // Optional (default: 6)
544
- }
515
+ // Stop a specific subscription
516
+ unsub();
517
+
518
+ // Disconnect the socket entirely
519
+ rs.disconnect();
545
520
  ```
546
521
 
547
- ### Validations
522
+ ---
548
523
 
549
- | Field | Type | Required | Description |
550
- | ------------------------ | ------------------ | -------- | ------------------------------------------ |
551
- | `marketQuestion` | `string` | ✅ | Market question (cannot be empty) |
552
- | `marketOptions` | `string[]` | ✅ | List of options (2 to 26) |
553
- | `marketTags` | `string[]` | ✅ | Tags related to the market (1 to 3) |
554
- | `marketDescription` | `string` | ✅ | Detailed market description |
555
- | `isPublic` | `boolean` | ✅ | Whether market is public |
556
- | `isPublicPoolResolverAi` | `boolean` | ✅ | AI resolver flag |
557
- | `creator` | `0x${string}` | ✅ | Market creator address |
558
- | `startTime` | `bigint` | ✅ | Market start timestamp |
559
- | `endTime` | `bigint` | ✅ | Must be greater than `startTime` |
560
- | `no_of_options` | `bigint` | ✅ | Number of market options (>= 2) |
561
- | `inputAmountWei` | `bigint` | ✅ | Initial liquidity (minimum 10 tokens) |
562
- | `barValues` | `number[]` | ✅ | Cannot be empty |
563
- | `baseToken` | `0x${string}` | ✅ | ERC20 base token address |
564
- | `tokenDecimals` | `number` | ❌ | Defaults to `6` |
524
+ ## Environments & Configuration
565
525
 
566
- ### Minimum Liquidity Rule
526
+ Set up your application for development, testing, or production.
567
527
 
568
- #### inputAmountWei >= 10 tokens
528
+ When initializing the Rain class, your configuration dictates which endpoints and contract addresses the SDK interacts with.
569
529
 
570
- ### Return Type
530
+ ### Environment Addresses
571
531
 
572
- ```ts
573
- RawTransaction[] // [approve, createMarket] or [createMarket] depending on allowance
574
- ```
532
+ The SDK automatically selects the correct Factory Address and API endpoint based on your chosen environment.
575
533
 
576
- ### Note
534
+ | Environment | API Endpoint | Factory Address |
535
+ | ----------- | ------------ | --------------- |
536
+ | development | dev-api.rain.one | 0x148DA7F2039B2B00633AC2ab566f59C8a4C86313 |
537
+ | stage | stg-api.rain.one | 0x6109c9f28FE3Ad84c51368f7Ef2d487ca020c561 |
538
+ | production | prod-api.rain.one | 0xccCB3C03D9355B01883779EF15C1Be09cf3623F1 |
577
539
 
578
- If the user has not approved the **Rain Factory contract**, the function will return two transactions **(approve + create market)**, but if approval already exists, it will return only one transaction **(create market)**.
540
+ You will also frequently interact with the standard base token, which is Arbitrum USDT (`0xFd086bC7CD5C481DCC9C85ebE478A1C0b69FCbb9`) using 6 decimals.
579
541
 
580
- ### Example
542
+ ### Full Configuration Options
581
543
 
582
544
  ```ts
583
- const txs = await rain.buildCreateMarketTx({
584
- marketQuestion: "Will BTC hit 100k?",
585
- marketOptions: ["Yes", "No"],
586
- marketTags: ["crypto", "bitcoin"],
587
- marketDescription: "Prediction market for BTC price",
588
- isPublic: true,
589
- isPublicPoolResolverAi: false,
590
- creator: "0x996ea23940f4a01610181D04bdB6F862719b63f0",
591
- startTime: 1770836400n,
592
- endTime: 1770922800n,
593
- no_of_options: 2n,
594
- inputAmountWei: 100000000n,
595
- barValues: [50, 50],
596
- baseToken: "0xCa4f77A38d8552Dd1D5E44e890173921B67725F4",
545
+ const rain = new Rain({
546
+ environment: 'development', // 'development' | 'stage' | 'production'
547
+ rpcUrl: 'https://...', // Optional, defaults to public Arbitrum RPCs
597
548
  });
598
549
  ```
599
550
 
600
551
  ---
601
552
 
602
- ## buildClaimTx
553
+ ## API Reference
603
554
 
604
- Builds a **raw EVM transaction** to claim funds from a resolved Rain market.
555
+ A comprehensive list of methods, parameters, and return types for the Rain SDK.
605
556
 
606
- This function **does not send the transaction** it only prepares calldata.
557
+ All transaction builders return an unsigned `RawTransaction` (`{ to, data, value? }`) that must be executed by a wallet or smart account.
607
558
 
608
- ### Method Signature
559
+ ---
609
560
 
610
- ```ts
611
- buildClaimTx(params: ClaimTxParams): Promise<RawTransaction>
612
- ```
561
+ ### Authentication
562
+
563
+ #### `login(params)`
613
564
 
614
- ### Parameters
565
+ Authenticate a user with the Rain API.
615
566
 
616
567
  ```ts
617
- interface ClaimTxParams {
618
- marketId: string;
619
- walletAddress: `0x${string}`;
620
- }
568
+ const result = await rain.login({
569
+ walletAddress: '0x...',
570
+ signature: '0x...',
571
+ });
572
+ // Returns: LoginResult
573
+ // { accessToken, userId, ... }
621
574
  ```
622
575
 
623
- ### Validations
624
-
625
- | Parameter | Type | Required | Description |
626
- | --------------- | ------------- | -------- | ---------------------------------- |
627
- | `marketId` | `string` | ✅ | Unique identifier of the market |
628
- | `walletAddress` | `0x${string}` | ✅ | Address of the user claiming funds |
576
+ ---
629
577
 
630
- ### Return Type
578
+ ### Market Queries
631
579
 
632
- ```ts
633
- interface RawTransaction {
634
- to: `0x${string}`;
635
- data: `0x${string}`;
636
- }
637
- ```
580
+ #### `getPublicMarkets(params)`
638
581
 
639
- ### Example
582
+ Browse markets based on specific filters.
640
583
 
641
584
  ```ts
642
- const tx = await rain.buildClaimTx({
643
- marketId: "698c8f116e985bbfacc7fc01",
644
- walletAddress: "0x996ea23940f4a01610181D04bdB6F862719b63f0",
585
+ const markets = await rain.getPublicMarkets({
586
+ limit: 12,
587
+ offset: 0,
588
+ sortBy: 'Liquidity', // 'Liquidity' | 'Volumn' | 'latest'
589
+ status: 'Live', // 'Live' | 'Trading' | 'Closed' | ...
590
+ creator: '0x...', // Optional — filter by creator
645
591
  });
592
+ // Returns: Market[]
593
+ // { id, title, totalVolume, status, contractAddress, poolOwnerWalletAddress }
646
594
  ```
647
595
 
648
- ---
649
-
650
- ## buildCloseMarketTx
651
-
652
- Builds **raw EVM transactions** to close a Rain market and submit the resolution outcome.
653
-
654
- Handles both V2 and V3 market contracts automatically. For V3 markets, checks token allowances and prepends an approval transaction if needed.
596
+ #### `getMarketById(params)`
655
597
 
656
- This function **does not send the transactions** — it only prepares calldata.
657
-
658
- ### Method Signature
598
+ Fetch a single market by its API ID.
659
599
 
660
600
  ```ts
661
- buildCloseMarketTx(params: CloseMarketTxParams): Promise<RawTransaction[]>
601
+ const market = await rain.getMarketById({
602
+ marketId: '698c8f116e985bbfacc7fc01',
603
+ accessToken: 'your-access-token', // Optional
604
+ });
605
+ // Returns: Market
662
606
  ```
663
607
 
664
- ### Parameters
608
+ #### `getUserInvestments(params)`
609
+
610
+ Fetch all active investments for a specific user.
665
611
 
666
612
  ```ts
667
- interface CloseMarketTxParams {
668
- marketId: string; // MongoDB _id of the market
669
- walletAddress: `0x${string}`; // Smart account address
670
- proposedOutcome?: number; // Winner option index (required for V2 and V3 manual resolver)
671
- usdtTokenAddress?: `0x${string}`; // Required for V3 USDT markets
672
- rainTokenAddress?: `0x${string}`; // Required for V3 RAIN markets
673
- usdtSymbol?: string; // USDT symbol for the environment (e.g. "USDTm")
674
- tokenDecimals?: number; // Defaults to 6
675
- }
613
+ const investments = await rain.getUserInvestments({
614
+ walletAddress: '0x...',
615
+ accessToken: 'your-access-token',
616
+ });
617
+ // Returns: UserInvestment[]
676
618
  ```
677
619
 
678
- ### Validations
620
+ ---
679
621
 
680
- | Field | Type | Required | Description |
681
- | -------------------- | ------------- | -------- | -------------------------------------------------------- |
682
- | `marketId` | `string` | ✅ | MongoDB `_id` of the market |
683
- | `walletAddress` | `0x${string}` | ✅ | Smart account used for allowance checks |
684
- | `proposedOutcome` | `number` | ⚠️ | Required for V2 markets and V3 manual resolver markets |
685
- | `usdtTokenAddress` | `0x${string}` | ⚠️ | Required for V3 USDT markets |
686
- | `rainTokenAddress` | `0x${string}` | ⚠️ | Required for V3 RAIN markets |
687
- | `usdtSymbol` | `string` | ❌ | Used to detect if market uses USDT as base token |
688
- | `tokenDecimals` | `number` | ❌ | Defaults to `6` |
622
+ ### Transaction Builders
689
623
 
690
- ### Return Type
624
+ #### Approvals
691
625
 
692
626
  ```ts
693
- RawTransaction[] // [approve?, closePool] for V3 or [closePool, chooseWinner] for V2
627
+ // buildApprovalTx(params) ERC20 approve
628
+ const tx = rain.buildApprovalTx({
629
+ tokenAddress: '0xFd086bC7CD5C481DCC9C85ebE478A1C0b69FCbb9', // USDT
630
+ spender: '0x...', // market contract address
631
+ amount: 100_000_000n, // Optional — defaults to max uint256
632
+ });
694
633
  ```
695
634
 
696
- ### Example
635
+ #### Creating a Market
697
636
 
698
- ```ts
699
- // V2 market
700
- const txs = await rain.buildCloseMarketTx({
701
- marketId: "698c8f116e985bbfacc7fc01",
702
- walletAddress: "0x996ea23940f4a01610181D04bdB6F862719b63f0",
703
- proposedOutcome: 0,
704
- });
637
+ Returns `[approveTx, createTx]` if approval is needed, or `[createTx]` if already approved.
705
638
 
706
- // V3 manual resolver with RAIN token
707
- const txs = await rain.buildCloseMarketTx({
708
- marketId: "698c8f116e985bbfacc7fc01",
709
- walletAddress: "0x996ea23940f4a01610181D04bdB6F862719b63f0",
710
- proposedOutcome: 1,
711
- rainTokenAddress: "0xRainTokenAddress...",
712
- usdtSymbol: "USDTm",
639
+ ```ts
640
+ const txs = await rain.buildCreateMarketTx({
641
+ marketQuestion: 'Will BTC hit 100k?',
642
+ marketOptions: ['Yes', 'No', 'Maybe'],
643
+ marketTags: ['crypto', 'bitcoin'],
644
+ marketDescription: 'Prediction market for BTC price',
645
+ isPublic: true,
646
+ isPublicPoolResolverAi: false,
647
+ creator: '0x996ea23940f4a01610181D04bdB6F862719b63f0',
648
+ startTime: 1770836400n,
649
+ endTime: 1770922800n,
650
+ no_of_options: 3n,
651
+ inputAmountWei: 100_000_000n,
652
+ barValues: [34, 33, 33],
653
+ baseToken: '0xFd086bC7CD5C481DCC9C85ebE478A1C0b69FCbb9',
654
+ tokenDecimals: 6,
713
655
  });
714
656
  ```
715
657
 
716
- ---
717
-
718
- ## buildCreateDisputeTx
658
+ #### Trading Options
719
659
 
720
- Builds **raw EVM transactions** to open a dispute on a Rain market.
660
+ ```ts
661
+ // buildBuyOptionRawTx(params) — Market buy
662
+ const tx = rain.buildBuyOptionRawTx({
663
+ marketContractAddress: '0x...',
664
+ selectedOption: 1n, // Option index (bigint)
665
+ buyAmountInWei: 10_000_000n, // 10 USDT
666
+ });
721
667
 
722
- Checks the user's token allowance against the dispute fee and prepends an approval transaction if needed.
668
+ // buildLimitBuyOptionTx(params) Limit buy order
669
+ const limitBuyTx = rain.buildLimitBuyOptionTx({
670
+ marketContractAddress: '0x...',
671
+ selectedOption: 1,
672
+ pricePerShare: 500000000000000000n, // 0.50 in 1e18
673
+ buyAmountInWei: 10_000_000n,
674
+ tokenDecimals: 6,
675
+ });
723
676
 
724
- This function **does not send the transactions** it only prepares calldata.
677
+ // buildLimitSellOptionTx(params)Limit sell order
678
+ const limitSellTx = rain.buildLimitSellOptionTx({
679
+ marketContractAddress: '0x...',
680
+ selectedOption: 1,
681
+ pricePerShare: 500000000000000000n, // 0.50 in 1e18
682
+ shares: 5_000_000n,
683
+ tokenDecimals: 6,
684
+ });
725
685
 
726
- ### Method Signature
686
+ // buildCancelOrdersTx(params) — Cancel specific open orders
687
+ const cancelTx = rain.buildCancelOrdersTx({
688
+ marketContractAddress: '0x...',
689
+ orders: [
690
+ { option: 1, price: 0.5, orderID: 1n },
691
+ { option: 1, price: 0.6, orderID: 2n },
692
+ ],
693
+ });
727
694
 
728
- ```ts
729
- buildCreateDisputeTx(params: CreateDisputeTxParams): Promise<RawTransaction[]>
695
+ // buildCancelAllOpenOrdersTx(params) — Cancel all open orders for a user
696
+ const cancelAllTx = await rain.buildCancelAllOpenOrdersTx({
697
+ marketContractAddress: '0x...',
698
+ walletAddress: '0x...',
699
+ accessToken: 'your-access-token',
700
+ });
730
701
  ```
731
702
 
732
- ### Parameters
703
+ #### Market Lifecycle
733
704
 
734
705
  ```ts
735
- interface CreateDisputeTxParams {
736
- marketId: string; // MongoDB _id of the market
737
- walletAddress: `0x${string}`; // User's wallet address
738
- usdtTokenAddress?: `0x${string}`; // Required for USDT markets
739
- rainTokenAddress?: `0x${string}`; // Required for RAIN markets
740
- usdtSymbol?: string; // Used to detect market token type
741
- }
742
- ```
706
+ // buildCloseMarketTx(params) — Close market and halt trading
707
+ const closeTx = await rain.buildCloseMarketTx({
708
+ marketContractAddress: '0x...',
709
+ walletAddress: '0x...',
710
+ accessToken: 'your-access-token',
711
+ });
743
712
 
744
- ### Validations
713
+ // buildAddLiquidityTx(params) — Add liquidity to a market
714
+ const addLiqTxs = await rain.buildAddLiquidityTx({
715
+ marketContractAddress: '0x...',
716
+ walletAddress: '0x...',
717
+ amount: 100, // human-readable — reads baseToken() on-chain, uses 6 decimals for USDT or 18 for RAIN
718
+ });
719
+ // Returns [approveTx, enterLiquidityTx] or [enterLiquidityTx] if already approved.
745
720
 
746
- | Field | Type | Required | Description |
747
- | ------------------- | ------------- | -------- | -------------------------------------------- |
748
- | `marketId` | `string` | ✅ | MongoDB `_id` of the market |
749
- | `walletAddress` | `0x${string}` | ✅ | Address of the user opening the dispute |
750
- | `usdtTokenAddress` | `0x${string}` | ⚠️ | Required if market uses USDT as base token |
751
- | `rainTokenAddress` | `0x${string}` | ⚠️ | Required if market uses RAIN as base token |
752
- | `usdtSymbol` | `string` | ❌ | Used to detect if market uses USDT |
721
+ // buildClaimTx(params) Claim winnings after market settles
722
+ const claimTx = await rain.buildClaimTx({
723
+ marketId: '698c8f116e985bbfacc7fc01',
724
+ walletAddress: '0x996ea23940f4a01610181D04bdB6F862719b63f0',
725
+ });
726
+ ```
753
727
 
754
- ### Return Type
728
+ #### Disputes & Appeals
755
729
 
756
730
  ```ts
757
- RawTransaction[] // [approve?, openDispute]
758
- ```
731
+ // buildCreateDisputeTx(params) — Open a dispute on market outcome
732
+ const disputeTxs = await rain.buildCreateDisputeTx({
733
+ marketContractAddress: '0x...',
734
+ walletAddress: '0x...',
735
+ accessToken: 'your-access-token',
736
+ });
759
737
 
760
- ### Example
738
+ // buildCreateAppealTx(params) — Appeal a dispute decision
739
+ const appealTxs = await rain.buildCreateAppealTx({
740
+ marketContractAddress: '0x...',
741
+ walletAddress: '0x...',
742
+ accessToken: 'your-access-token',
743
+ });
761
744
 
762
- ```ts
763
- const txs = await rain.buildCreateDisputeTx({
764
- marketId: "698c8f116e985bbfacc7fc01",
765
- walletAddress: "0x996ea23940f4a01610181D04bdB6F862719b63f0",
766
- rainTokenAddress: "0xRainTokenAddress...",
767
- usdtSymbol: "USDTm",
745
+ // buildExtendTimeTx(params) — Extend the dispute resolution window
746
+ const extendTx = await rain.buildExtendTimeTx({
747
+ marketContractAddress: '0x...',
748
+ walletAddress: '0x...',
749
+ accessToken: 'your-access-token',
768
750
  });
769
751
  ```
770
752
 
771
753
  ---
772
754
 
773
- ## buildCreateAppealTx
755
+ ### RainSocket — WebSocket Subscriptions
774
756
 
775
- Builds **raw EVM transactions** to appeal a dispute resolution on a Rain market.
776
-
777
- Identical flow to `buildCreateDisputeTx` — checks token allowance against the appeal fee and prepends an approval if needed.
778
-
779
- This function **does not send the transactions** — it only prepares calldata.
780
-
781
- ### Method Signature
757
+ All subscription methods return an unsubscribe function `() => void`.
782
758
 
783
759
  ```ts
784
- buildCreateAppealTx(params: CreateAppealTxParams): Promise<RawTransaction[]>
785
- ```
760
+ import { RainSocket } from '@rainprotocolsdk/sdk';
786
761
 
787
- ### Parameters
762
+ const rs = new RainSocket({ environment: 'production' });
788
763
 
789
- ```ts
790
- interface CreateAppealTxParams {
791
- marketId: string; // MongoDB _id of the market
792
- walletAddress: `0x${string}`; // User's wallet address
793
- usdtTokenAddress?: `0x${string}`; // Required for USDT markets
794
- rainTokenAddress?: `0x${string}`; // Required for RAIN markets
795
- usdtSymbol?: string; // Used to detect market token type
796
- }
797
- ```
764
+ // Connection lifecycle
765
+ rs.onConnect(callback)
766
+ rs.onDisconnect(callback)
798
767
 
799
- ### Validations
768
+ // Trade events
769
+ rs.onEnterOption(marketId, callback) // enter-option/{marketId}
770
+ rs.onOrderCreated(marketId, callback) // order-created/{marketId}
771
+ rs.onOrderCancelled(marketId, callback) // order-cancelled/{marketId}
772
+ rs.onOrderFilled(marketId, callback) // order-filled/{marketId}
800
773
 
801
- | Field | Type | Required | Description |
802
- | ------------------- | ------------- | -------- | -------------------------------------------- |
803
- | `marketId` | `string` | ✅ | MongoDB `_id` of the market |
804
- | `walletAddress` | `0x${string}` | ✅ | Address of the user filing the appeal |
805
- | `usdtTokenAddress` | `0x${string}` | ⚠️ | Required if market uses USDT as base token |
806
- | `rainTokenAddress` | `0x${string}` | ⚠️ | Required if market uses RAIN as base token |
807
- | `usdtSymbol` | `string` | ❌ | Used to detect if market uses USDT |
774
+ // Dispute & appeal events
775
+ rs.onDisputeOpened(marketId, callback) // dispute-opened/{marketId}
776
+ rs.onAppealOpened(marketId, callback) // appeal-opened/{marketId}
777
+ rs.onDisputeTimeExtended(marketId, callback) // dispute-time-extented/{marketId}
808
778
 
809
- ### Return Type
779
+ // Resolution events
780
+ rs.onDisputeWinner(marketId, callback) // dispute-winner/{marketId}
781
+ rs.onAppealWinner(marketId, callback) // appeal-winner/{marketId}
782
+ rs.onClaimReward(marketId, userId, callback) // claim-reward/{marketId}/{userId}
810
783
 
811
- ```ts
812
- RawTransaction[] // [approve?, openDispute]
813
- ```
814
-
815
- ### Example
816
-
817
- ```ts
818
- const txs = await rain.buildCreateAppealTx({
819
- marketId: "698c8f116e985bbfacc7fc01",
820
- walletAddress: "0x996ea23940f4a01610181D04bdB6F862719b63f0",
821
- rainTokenAddress: "0xRainTokenAddress...",
822
- usdtSymbol: "USDTm",
823
- });
784
+ // Disconnect
785
+ rs.disconnect()
824
786
  ```
825
787
 
826
788
  ---
827
789
 
828
- ## buildExtendTimeTx
790
+ ### RainAA — Account Abstraction
829
791
 
830
- Builds a **raw EVM transaction** to re-submit an appeal by extending the oracle voting timer on a disputed Rain market.
792
+ `RainAA` manages Alchemy smart accounts with gas sponsorship.
831
793
 
832
- Internally calls `resolver()` on the market contract to resolve the oracle address, then fetches a signed epoch from the Rain backend, and encodes the `extendTime(epoch, signature)` call targeting the oracle contract.
794
+ ```ts
795
+ import { RainAA } from '@rainprotocolsdk/sdk';
796
+ import { arbitrum } from 'viem/chains';
833
797
 
834
- This function **does not send the transaction** — it only prepares calldata.
798
+ const rainAA = new RainAA({
799
+ walletClient: yourWalletClient, // viem WalletClient
800
+ alchemyApiKey: 'your-alchemy-key',
801
+ paymasterPolicyId: 'your-policy-id',
802
+ chain: arbitrum,
803
+ rpcUrl: 'https://...', // Optional
804
+ });
835
805
 
836
- ### Method Signature
806
+ // Connect — derives smart account from EOA
807
+ const smartAccountAddress = await rainAA.connect();
837
808
 
838
- ```ts
839
- buildExtendTimeTx(params: ExtendTimeTxParams): Promise<RawTransaction>
840
- ```
809
+ // Accessors
810
+ rainAA.address; // Smart account address (throws if not connected)
811
+ rainAA.client; // Underlying AA client (throws if not connected)
841
812
 
842
- ### Parameters
843
-
844
- ```ts
845
- interface ExtendTimeTxParams {
846
- marketContractAddress: `0x${string}`; // TradeMarket contract address — resolver() is called on it
847
- walletAddress: `0x${string}`; // Smart account address
848
- accessToken: string; // JWT from Rain auth (login)
849
- }
813
+ // Disconnect
814
+ rainAA.disconnect();
850
815
  ```
851
816
 
852
- ### Validations
853
-
854
- | Field | Type | Required | Description |
855
- | ----------------------- | ------------- | -------- | ---------------------------------------------------- |
856
- | `marketContractAddress` | `0x${string}` | ✅ | Market contract — used to look up the oracle address |
857
- | `walletAddress` | `0x${string}` | ✅ | Smart account address of the caller |
858
- | `accessToken` | `string` | ✅ | JWT returned from `login()` |
817
+ ---
859
818
 
860
- ### Return Type
819
+ ### Key Types
861
820
 
862
821
  ```ts
822
+ // Core transaction type — returned by all builders
863
823
  interface RawTransaction {
864
- to: `0x${string}`; // oracle contract address (resolved on-chain)
824
+ to: `0x${string}`;
865
825
  data: `0x${string}`;
826
+ value?: bigint;
866
827
  }
867
- ```
868
828
 
869
- ### Example
829
+ // Market from listing endpoint
830
+ interface Market {
831
+ id: string;
832
+ title: string;
833
+ totalVolume: string;
834
+ status: MarketStatus;
835
+ contractAddress?: string;
836
+ poolOwnerWalletAddress?: string;
837
+ }
870
838
 
871
- ```ts
872
- const tx = await rain.buildExtendTimeTx({
873
- marketContractAddress: "0xMarketContractAddress...",
874
- walletAddress: "0x996ea23940f4a01610181D04bdB6F862719b63f0",
875
- accessToken: "eyJhbGciOi...",
876
- });
839
+ type MarketStatus = 'Live' | 'New' | 'WaitingForResult' | 'UnderDispute' |
840
+ 'UnderAppeal' | 'ClosingSoon' | 'InReview' | 'InEvaluation' | 'Closed' | 'Trading';
877
841
  ```
878
842
 
879
843
  ---
880
844
 
881
- ## RainAA Class (Account Abstraction)
845
+ ## Full Method Reference
846
+
847
+ A complete directory of all available methods in the Rain SDK.
848
+
849
+ ### Rain Class
850
+
851
+ | Method | Returns | Async |
852
+ | ------ | ------- | ----- |
853
+ | **Authentication** | | |
854
+ | `login(params)` | `LoginResult` | Yes |
855
+ | **Market Queries** | | |
856
+ | `getPublicMarkets(params)` | `Market[]` | Yes |
857
+ | `getMarketById(params)` | `Market` | Yes |
858
+ | `getUserInvestments(params)` | `UserInvestment[]` | Yes |
859
+ | **Transaction Builders** | | |
860
+ | `buildApprovalTx(params)` | `RawTransaction` | No |
861
+ | `buildCreateMarketTx(params)` | `RawTransaction[]` | Yes |
862
+ | `buildBuyOptionRawTx(params)` | `RawTransaction` | No |
863
+ | `buildLimitBuyOptionTx(params)` | `RawTransaction` | No |
864
+ | `buildLimitSellOptionTx(params)` | `RawTransaction` | No |
865
+ | `buildCancelOrdersTx(params)` | `RawTransaction[]` | No |
866
+ | `buildCancelAllOpenOrdersTx(params)` | `RawTransaction[]` | Yes |
867
+ | `buildAddLiquidityTx(params)` | `RawTransaction[]` | Yes |
868
+ | `buildClaimTx(params)` | `RawTransaction` | Yes |
869
+ | `buildCloseMarketTx(params)` | `RawTransaction[]` | Yes |
870
+ | `buildCreateDisputeTx(params)` | `RawTransaction[]` | Yes |
871
+ | `buildCreateAppealTx(params)` | `RawTransaction[]` | Yes |
872
+ | `buildExtendTimeTx(params)` | `RawTransaction` | Yes |
873
+
874
+ ### RainAA Class
875
+
876
+ | Method | Returns | Async |
877
+ | ------ | ------- | ----- |
878
+ | `connect()` | `` 0x${string} `` | Yes |
879
+ | `disconnect()` | `void` | No |
880
+ | `.address` | `` 0x${string} `` | — |
881
+ | `.client` | Smart wallet client | — |
882
+
883
+ ### RainSocket Class
884
+
885
+ | Method | Returns | Async |
886
+ | ------ | ------- | ----- |
887
+ | `onConnect(callback)` | `void` | No |
888
+ | `onDisconnect(callback)` | `void` | No |
889
+ | `onEnterOption(marketId, callback)` | `Unsubscribe` | No |
890
+ | `onOrderCreated(marketId, callback)` | `Unsubscribe` | No |
891
+ | `onOrderCancelled(marketId, callback)` | `Unsubscribe` | No |
892
+ | `onOrderFilled(marketId, callback)` | `Unsubscribe` | No |
893
+ | `onDisputeOpened(marketId, callback)` | `Unsubscribe` | No |
894
+ | `onAppealOpened(marketId, callback)` | `Unsubscribe` | No |
895
+ | `onDisputeTimeExtended(marketId, callback)` | `Unsubscribe` | No |
896
+ | `onDisputeWinner(marketId, callback)` | `Unsubscribe` | No |
897
+ | `onAppealWinner(marketId, callback)` | `Unsubscribe` | No |
898
+ | `onClaimReward(marketId, userId, callback)` | `Unsubscribe` | No |
899
+ | `disconnect()` | `void` | No |
882
900
 
883
- `RainAA` is responsible for:
901
+ ---
884
902
 
885
- * Smart account creation
886
- * Session management (coming soon)
887
- * Gas-sponsored execution (coming soon)
888
- * Transaction submission (coming soon)
903
+ ## Local Development
889
904
 
890
- > `RainAA` consumes raw transactions generated by `Rain`.
905
+ Instructions for building and testing the Rain SDK locally.
891
906
 
892
- ### Conceptual Flow
907
+ If you are looking to contribute to the SDK or run the test suite, follow these steps to set up your local development environment.
893
908
 
894
- ```ts
895
- Rain (WHAT to do)
896
-
897
- Raw Transaction
898
-
899
- RainAA (HOW to execute)
909
+ ### Installation
910
+
911
+ First, navigate to the rain-sdk directory and install the necessary dependencies:
912
+
913
+ ```bash
914
+ cd rain-sdk
915
+ npm install
900
916
  ```
901
917
 
902
- ---
918
+ ### Available Scripts
903
919
 
904
- ## Versioning Policy
920
+ The following commands are available for development and testing.
905
921
 
906
- Rain SDK follows **Semantic Versioning**:
922
+ #### Build the SDK
907
923
 
908
- * **Patch** (`1.0.x`) Bug fixes
909
- * **Minor** (`1.x.0`) → New features, backward compatible
910
- * **Major** (`x.0.0`) → Breaking API changes
924
+ Compiles the TypeScript source code into the final distribution files.
911
925
 
912
- ---
926
+ ```bash
927
+ npm run build
928
+ ```
913
929
 
914
- ## Recommended Usage Pattern
930
+ #### Development Mode
915
931
 
916
- ```ts
917
- // 1. Init SDK
918
- const rain = new Rain({ environment: "production" });
932
+ Runs the development environment in watch mode, automatically recompiling when files are changed.
919
933
 
920
- // 2. Login
921
- const { accessToken } = await rain.login({ signature, walletAddress, smartWalletAddress });
934
+ ```bash
935
+ npm run dev
936
+ ```
922
937
 
923
- // 3. Read data / build tx
924
- const rawTx = await rain.buildBuyOptionRawTx({ ... });
938
+ #### Run Tests
925
939
 
926
- // 4. Execute via your provider
927
- await yourProvider.sendTransaction(rawTx);
940
+ Executes the standard test suite to ensure everything is functioning correctly.
941
+
942
+ ```bash
943
+ npm test
928
944
  ```
929
945
 
930
- ---
946
+ #### Integration Tests
947
+
948
+ Runs tests that interact with external services or the blockchain to verify end-to-end functionality.
931
949
 
932
- **Rain SDK** is built to scale with both products and protocols.
950
+ ```bash
951
+ npm run test:integration
952
+ ```