rain-sdk-v2 1.0.5 → 1.0.7

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
@@ -192,17 +192,19 @@ const txsRain = await rain.buildCreateMarketTx({
192
192
 
193
193
  ### Trading
194
194
 
195
- #### `buildEnterOptionTx(params: EnterOptionTxParams): RawTransaction`
195
+ #### `buildEnterOptionTx(params): Promise<RawTransaction[]>`
196
196
 
197
- Buy shares of an option (AMM trade).
197
+ Buy shares of an option (AMM trade). Automatically reads the market's base token, checks allowance, and includes approval TX if needed.
198
198
 
199
199
  ```typescript
200
- const tx = rain.buildEnterOptionTx({
200
+ const txs = await rain.buildEnterOptionTx({
201
201
  marketContractAddress: '0x...',
202
202
  selectedOption: 1n, // 1-based option index
203
203
  optionSide: OptionSide.Yes, // Yes = 1, No = 2
204
- buyAmountInWei: parseUnits('5', 6), // 5 USDT
204
+ buyAmountInWei: parseUnits('5', 6), // 5 USDT (or parseUnits('5', 18) for RAIN)
205
+ walletAddress: '0x...', // user's wallet address
205
206
  });
207
+ // Returns [approveTx?, enterOptionTx]
206
208
  ```
207
209
 
208
210
  | Parameter | Type | Description |
@@ -211,26 +213,29 @@ const tx = rain.buildEnterOptionTx({
211
213
  | `selectedOption` | `bigint` | Option index (1-based) |
212
214
  | `optionSide` | `OptionSide` | `Yes (1)` or `No (2)` |
213
215
  | `buyAmountInWei` | `bigint` | Amount in base token wei |
216
+ | `walletAddress` | `0x${string}` | User's wallet address (for allowance check) |
214
217
 
215
- > **Note:** Requires prior ERC20 approval to the market contract.
218
+ > **Note:** Approval is handled automatically. The SDK reads `baseToken` from the market contract and checks allowance before building transactions.
216
219
 
217
220
  ---
218
221
 
219
222
  ### Split & Merge
220
223
 
221
- #### `buildSplitTx(params: SplitTxParams): RawTransaction`
224
+ #### `buildSplitTx(params): Promise<RawTransaction[]>`
222
225
 
223
- Split base tokens into equal Yes + No shares for an option.
226
+ Split base tokens into equal Yes + No shares for an option. Automatically checks allowance and includes approval TX if needed.
224
227
 
225
228
  ```typescript
226
- const tx = rain.buildSplitTx({
229
+ const txs = await rain.buildSplitTx({
227
230
  marketContractAddress: '0x...',
228
231
  option: 1n,
229
232
  amount: parseUnits('5', 6), // 5 USDT -> 5 Yes shares + 5 No shares
233
+ walletAddress: '0x...', // user's wallet address
230
234
  });
235
+ // Returns [approveTx?, splitTx]
231
236
  ```
232
237
 
233
- > **Note:** Requires prior ERC20 approval to the market contract.
238
+ > **Note:** Approval is handled automatically.
234
239
 
235
240
  #### `buildMergeTx(params: MergeTxParams): RawTransaction`
236
241
 
@@ -250,19 +255,21 @@ const tx = rain.buildMergeTx({
250
255
 
251
256
  ### Liquidity
252
257
 
253
- #### `buildAddLiquidityTx(params: AddLiquidityTxParams): RawTransaction`
258
+ #### `buildAddLiquidityTx(params): Promise<RawTransaction[]>`
254
259
 
255
- Add liquidity to a specific option.
260
+ Add liquidity to a specific option. Automatically checks allowance and includes approval TX if needed.
256
261
 
257
262
  ```typescript
258
- const tx = rain.buildAddLiquidityTx({
263
+ const txs = await rain.buildAddLiquidityTx({
259
264
  marketContractAddress: '0x...',
260
265
  option: 1n,
261
266
  totalAmountInWei: parseUnits('10', 6), // 10 USDT
267
+ walletAddress: '0x...', // user's wallet address
262
268
  });
269
+ // Returns [approveTx?, addLiquidityTx]
263
270
  ```
264
271
 
265
- > **Note:** Requires prior ERC20 approval to the market contract.
272
+ > **Note:** Approval is handled automatically.
266
273
 
267
274
  #### `buildRemoveLiquidityTx(params: RemoveLiquidityTxParams): RawTransaction`
268
275
 
@@ -286,21 +293,23 @@ const tx = rain.buildRemoveLiquidityTx({
286
293
 
287
294
  ### Order Book
288
295
 
289
- #### `buildPlaceBuyOrderTx(params: PlaceBuyOrderTxParams): RawTransaction`
296
+ #### `buildPlaceBuyOrderTx(params): Promise<RawTransaction[]>`
290
297
 
291
- Place a limit buy order.
298
+ Place a limit buy order. Automatically checks allowance and includes approval TX if needed.
292
299
 
293
300
  ```typescript
294
- const tx = rain.buildPlaceBuyOrderTx({
301
+ const txs = await rain.buildPlaceBuyOrderTx({
295
302
  marketContractAddress: '0x...',
296
303
  option: 1n,
297
304
  optionSide: OptionSide.Yes,
298
305
  price: parseEther('0.5'), // 50% price in 1e18 scale
299
306
  amount: parseUnits('10', 6), // 10 USDT
307
+ walletAddress: '0x...', // user's wallet address
300
308
  });
309
+ // Returns [approveTx?, placeBuyOrderTx]
301
310
  ```
302
311
 
303
- > **Note:** Requires prior ERC20 approval to the market contract. Available when AMM pool is closed.
312
+ > **Note:** Approval is handled automatically. Available when AMM pool is closed.
304
313
 
305
314
  #### `buildPlaceSellOrderTx(params: PlaceSellOrderTxParams): RawTransaction`
306
315
 
@@ -912,7 +921,11 @@ await rain.markNotificationAsRead({ notificationId: '...' }, accessToken);
912
921
 
913
922
  ```typescript
914
923
  // Get price data for a pool
915
- const prices = await rain.getPriceData({ poolId: '...', interval: '1h' });
924
+ const prices = await rain.getPriceData({
925
+ contractAddress: '0x...', // market contract address
926
+ side: 1, // 1 = YES, 2 = NO
927
+ filter: '1D', // '1H' | '6H' | '1D' | '1W' | '1M' | 'ALL'
928
+ });
916
929
  ```
917
930
 
918
931
  ### Pool Reviews
package/dist/Rain.d.ts CHANGED
@@ -16,8 +16,12 @@ export declare class Rain {
16
16
  getTokenConfig(tokenAddress: `0x${string}`): import("./config/environments.js").TokenConfig | null;
17
17
  buildApprovalTx(params: ApproveTxParams): RawTransaction;
18
18
  buildCreateMarketTx(params: CreateMarketTxParams): Promise<RawTransaction[]>;
19
- buildEnterOptionTx(params: EnterOptionTxParams): RawTransaction;
20
- buildAddLiquidityTx(params: AddLiquidityTxParams): RawTransaction;
19
+ buildEnterOptionTx(params: EnterOptionTxParams & {
20
+ walletAddress: `0x${string}`;
21
+ }): Promise<RawTransaction[]>;
22
+ buildAddLiquidityTx(params: AddLiquidityTxParams & {
23
+ walletAddress: `0x${string}`;
24
+ }): Promise<RawTransaction[]>;
21
25
  buildRemoveLiquidityTx(params: RemoveLiquidityTxParams): RawTransaction;
22
26
  getUserOptionLPShares(params: {
23
27
  marketContractAddress: `0x${string}`;
@@ -30,12 +34,16 @@ export declare class Rain {
30
34
  optionSide: number;
31
35
  userAddress: `0x${string}`;
32
36
  }): Promise<bigint>;
33
- buildSplitTx(params: SplitTxParams): RawTransaction;
37
+ buildSplitTx(params: SplitTxParams & {
38
+ walletAddress: `0x${string}`;
39
+ }): Promise<RawTransaction[]>;
34
40
  buildMergeTx(params: MergeTxParams): RawTransaction;
35
41
  buildClosePoolAITx(params: ClosePoolAITxParams): Promise<RawTransaction[]>;
36
42
  buildClosePoolManualTx(params: ClosePoolManualTxParams): Promise<RawTransaction[]>;
37
43
  buildChooseWinnerTx(params: ChooseWinnerTxParams): RawTransaction;
38
- buildPlaceBuyOrderTx(params: PlaceBuyOrderTxParams): RawTransaction;
44
+ buildPlaceBuyOrderTx(params: PlaceBuyOrderTxParams & {
45
+ walletAddress: `0x${string}`;
46
+ }): Promise<RawTransaction[]>;
39
47
  buildPlaceSellOrderTx(params: PlaceSellOrderTxParams): RawTransaction;
40
48
  buildOpenDisputeTx(params: OpenDisputeTxParams): Promise<RawTransaction[]>;
41
49
  buildCalculateWinnerTx(params: CalculateWinnerTxParams): Promise<RawTransaction>;
package/dist/Rain.js CHANGED
@@ -74,11 +74,11 @@ export class Rain {
74
74
  const tokenDecimals = params.tokenDecimals ?? tokenConfig?.decimals ?? 6;
75
75
  return buildCreateMarketRawTx({ ...params, tokenDecimals, factoryContractAddress: this.marketFactory, apiUrl: this.apiUrl, rpcUrl: this.rpcUrl, disputeTimer: this.distute_initial_timer, oracleFixedFeePerOption });
76
76
  }
77
- buildEnterOptionTx(params) {
78
- return buildEnterOptionRawTx(params);
77
+ async buildEnterOptionTx(params) {
78
+ return buildEnterOptionRawTx({ ...params, rpcUrl: this.rpcUrl });
79
79
  }
80
- buildAddLiquidityTx(params) {
81
- return buildAddLiquidityRawTx(params);
80
+ async buildAddLiquidityTx(params) {
81
+ return buildAddLiquidityRawTx({ ...params, rpcUrl: this.rpcUrl });
82
82
  }
83
83
  buildRemoveLiquidityTx(params) {
84
84
  return buildRemoveLiquidityRawTx(params);
@@ -89,8 +89,8 @@ export class Rain {
89
89
  async getUserOptionShares(params) {
90
90
  return getUserOptionShares({ ...params, rpcUrl: this.rpcUrl });
91
91
  }
92
- buildSplitTx(params) {
93
- return buildSplitRawTx(params);
92
+ async buildSplitTx(params) {
93
+ return buildSplitRawTx({ ...params, rpcUrl: this.rpcUrl });
94
94
  }
95
95
  buildMergeTx(params) {
96
96
  return buildMergeRawTx(params);
@@ -104,8 +104,8 @@ export class Rain {
104
104
  buildChooseWinnerTx(params) {
105
105
  return buildChooseWinnerRawTx(params);
106
106
  }
107
- buildPlaceBuyOrderTx(params) {
108
- return buildPlaceBuyOrderRawTx(params);
107
+ async buildPlaceBuyOrderTx(params) {
108
+ return buildPlaceBuyOrderRawTx({ ...params, rpcUrl: this.rpcUrl });
109
109
  }
110
110
  buildPlaceSellOrderTx(params) {
111
111
  return buildPlaceSellOrderRawTx(params);
@@ -1,6 +1,6 @@
1
1
  import { buildHeaders, buildQuery, handleResponse } from './helpers.js';
2
2
  export async function getPriceData(params, config) {
3
- const qs = buildQuery({ subPool: params.subPool, side: params.side, filter: params.filter });
3
+ const qs = buildQuery({ contractAddress: params.contractAddress, side: params.side, filter: params.filter });
4
4
  const res = await fetch(`${config.apiUrl}/price-data/get-price-data${qs}`, {
5
5
  method: 'GET',
6
6
  headers: buildHeaders(config),
@@ -193,7 +193,7 @@ export interface PnlByPoolIdParams {
193
193
  poolId: string;
194
194
  }
195
195
  export interface PriceDataParams {
196
- subPool: string;
196
+ contractAddress: string;
197
197
  side: 1 | 2;
198
198
  filter?: '1H' | '6H' | '1D' | '1W' | '1M' | 'ALL';
199
199
  }
@@ -1,2 +1,5 @@
1
1
  import { AddLiquidityTxParams, RawTransaction } from "./types.js";
2
- export declare function buildAddLiquidityRawTx(params: AddLiquidityTxParams): RawTransaction;
2
+ export declare function buildAddLiquidityRawTx(params: AddLiquidityTxParams & {
3
+ walletAddress: `0x${string}`;
4
+ rpcUrl: string;
5
+ }): Promise<RawTransaction[]>;
@@ -1,8 +1,10 @@
1
1
  import { encodeFunctionData } from "viem";
2
2
  import { MarketsAbi } from "../abi/MarketsAbi.js";
3
3
  import { ENTER_LIQUIDITY } from "../constants/contractmethods.js";
4
- export function buildAddLiquidityRawTx(params) {
5
- const { marketContractAddress, option, totalAmountInWei } = params;
4
+ import { checkMarketTokenAllowance } from "../utils/helpers.js";
5
+ import { buildApproveRawTx } from "./buildApprovalRawTx.js";
6
+ export async function buildAddLiquidityRawTx(params) {
7
+ const { marketContractAddress, option, totalAmountInWei, walletAddress, rpcUrl } = params;
6
8
  if (!marketContractAddress)
7
9
  throw new Error("marketContractAddress is required");
8
10
  if (option === undefined || option === null)
@@ -11,7 +13,12 @@ export function buildAddLiquidityRawTx(params) {
11
13
  throw new Error("totalAmountInWei is required");
12
14
  if (totalAmountInWei <= 0n)
13
15
  throw new Error("totalAmountInWei must be greater than 0");
14
- return {
16
+ const { allowance, baseToken } = await checkMarketTokenAllowance({ marketContractAddress, owner: walletAddress, rpcUrl });
17
+ const txs = [];
18
+ if (allowance < totalAmountInWei) {
19
+ txs.push(buildApproveRawTx({ tokenAddress: baseToken, spender: marketContractAddress, amount: totalAmountInWei }));
20
+ }
21
+ txs.push({
15
22
  to: marketContractAddress,
16
23
  data: encodeFunctionData({
17
24
  abi: MarketsAbi,
@@ -19,5 +26,6 @@ export function buildAddLiquidityRawTx(params) {
19
26
  args: [option, totalAmountInWei],
20
27
  }),
21
28
  value: 0n,
22
- };
29
+ });
30
+ return txs;
23
31
  }
@@ -1,2 +1,5 @@
1
1
  import { EnterOptionTxParams, RawTransaction } from "./types.js";
2
- export declare function buildEnterOptionRawTx(params: EnterOptionTxParams): RawTransaction;
2
+ export declare function buildEnterOptionRawTx(params: EnterOptionTxParams & {
3
+ walletAddress: `0x${string}`;
4
+ rpcUrl: string;
5
+ }): Promise<RawTransaction[]>;
@@ -1,8 +1,10 @@
1
1
  import { encodeFunctionData } from "viem";
2
2
  import { MarketsAbi } from "../abi/MarketsAbi.js";
3
3
  import { ENTER_OPTION } from "../constants/contractmethods.js";
4
- export function buildEnterOptionRawTx(params) {
5
- const { marketContractAddress, selectedOption, optionSide, buyAmountInWei } = params;
4
+ import { checkMarketTokenAllowance } from "../utils/helpers.js";
5
+ import { buildApproveRawTx } from "./buildApprovalRawTx.js";
6
+ export async function buildEnterOptionRawTx(params) {
7
+ const { marketContractAddress, selectedOption, optionSide, buyAmountInWei, walletAddress, rpcUrl } = params;
6
8
  if (!marketContractAddress)
7
9
  throw new Error("marketContractAddress is required");
8
10
  if (selectedOption === undefined || selectedOption === null)
@@ -13,7 +15,12 @@ export function buildEnterOptionRawTx(params) {
13
15
  throw new Error("buyAmountInWei is required");
14
16
  if (buyAmountInWei <= 0n)
15
17
  throw new Error("buyAmountInWei must be greater than 0");
16
- return {
18
+ const { allowance, baseToken } = await checkMarketTokenAllowance({ marketContractAddress, owner: walletAddress, rpcUrl });
19
+ const txs = [];
20
+ if (allowance < buyAmountInWei) {
21
+ txs.push(buildApproveRawTx({ tokenAddress: baseToken, spender: marketContractAddress, amount: buyAmountInWei }));
22
+ }
23
+ txs.push({
17
24
  to: marketContractAddress,
18
25
  data: encodeFunctionData({
19
26
  abi: MarketsAbi,
@@ -21,5 +28,6 @@ export function buildEnterOptionRawTx(params) {
21
28
  args: [selectedOption, optionSide, buyAmountInWei],
22
29
  }),
23
30
  value: 0n,
24
- };
31
+ });
32
+ return txs;
25
33
  }
@@ -1,3 +1,6 @@
1
1
  import { PlaceBuyOrderTxParams, PlaceSellOrderTxParams, RawTransaction } from "./types.js";
2
- export declare function buildPlaceBuyOrderRawTx(params: PlaceBuyOrderTxParams): RawTransaction;
2
+ export declare function buildPlaceBuyOrderRawTx(params: PlaceBuyOrderTxParams & {
3
+ walletAddress: `0x${string}`;
4
+ rpcUrl: string;
5
+ }): Promise<RawTransaction[]>;
3
6
  export declare function buildPlaceSellOrderRawTx(params: PlaceSellOrderTxParams): RawTransaction;
@@ -1,8 +1,10 @@
1
1
  import { encodeFunctionData } from "viem";
2
2
  import { MarketsAbi } from "../abi/MarketsAbi.js";
3
3
  import { PLACE_BUY_ORDER, PLACE_SELL_ORDER } from "../constants/contractmethods.js";
4
- export function buildPlaceBuyOrderRawTx(params) {
5
- const { marketContractAddress, option, optionSide, price, amount } = params;
4
+ import { checkMarketTokenAllowance } from "../utils/helpers.js";
5
+ import { buildApproveRawTx } from "./buildApprovalRawTx.js";
6
+ export async function buildPlaceBuyOrderRawTx(params) {
7
+ const { marketContractAddress, option, optionSide, price, amount, walletAddress, rpcUrl } = params;
6
8
  if (!marketContractAddress)
7
9
  throw new Error("marketContractAddress is required");
8
10
  if (option === undefined || option === null)
@@ -13,7 +15,12 @@ export function buildPlaceBuyOrderRawTx(params) {
13
15
  throw new Error("price must be greater than 0");
14
16
  if (!amount || amount <= 0n)
15
17
  throw new Error("amount must be greater than 0");
16
- return {
18
+ const { allowance, baseToken } = await checkMarketTokenAllowance({ marketContractAddress, owner: walletAddress, rpcUrl });
19
+ const txs = [];
20
+ if (allowance < amount) {
21
+ txs.push(buildApproveRawTx({ tokenAddress: baseToken, spender: marketContractAddress, amount }));
22
+ }
23
+ txs.push({
17
24
  to: marketContractAddress,
18
25
  data: encodeFunctionData({
19
26
  abi: MarketsAbi,
@@ -21,7 +28,8 @@ export function buildPlaceBuyOrderRawTx(params) {
21
28
  args: [option, optionSide, price, amount],
22
29
  }),
23
30
  value: 0n,
24
- };
31
+ });
32
+ return txs;
25
33
  }
26
34
  export function buildPlaceSellOrderRawTx(params) {
27
35
  const { marketContractAddress, option, optionSide, price, shares } = params;
@@ -1,2 +1,5 @@
1
1
  import { SplitTxParams, RawTransaction } from "./types.js";
2
- export declare function buildSplitRawTx(params: SplitTxParams): RawTransaction;
2
+ export declare function buildSplitRawTx(params: SplitTxParams & {
3
+ walletAddress: `0x${string}`;
4
+ rpcUrl: string;
5
+ }): Promise<RawTransaction[]>;
@@ -1,15 +1,22 @@
1
1
  import { encodeFunctionData } from "viem";
2
2
  import { MarketsAbi } from "../abi/MarketsAbi.js";
3
3
  import { SPLIT } from "../constants/contractmethods.js";
4
- export function buildSplitRawTx(params) {
5
- const { marketContractAddress, option, amount } = params;
4
+ import { checkMarketTokenAllowance } from "../utils/helpers.js";
5
+ import { buildApproveRawTx } from "./buildApprovalRawTx.js";
6
+ export async function buildSplitRawTx(params) {
7
+ const { marketContractAddress, option, amount, walletAddress, rpcUrl } = params;
6
8
  if (!marketContractAddress)
7
9
  throw new Error("marketContractAddress is required");
8
10
  if (option === undefined || option === null)
9
11
  throw new Error("option is required");
10
12
  if (!amount || amount <= 0n)
11
13
  throw new Error("amount must be greater than 0");
12
- return {
14
+ const { allowance, baseToken } = await checkMarketTokenAllowance({ marketContractAddress, owner: walletAddress, rpcUrl });
15
+ const txs = [];
16
+ if (allowance < amount) {
17
+ txs.push(buildApproveRawTx({ tokenAddress: baseToken, spender: marketContractAddress, amount }));
18
+ }
19
+ txs.push({
13
20
  to: marketContractAddress,
14
21
  data: encodeFunctionData({
15
22
  abi: MarketsAbi,
@@ -17,5 +24,6 @@ export function buildSplitRawTx(params) {
17
24
  args: [option, amount],
18
25
  }),
19
26
  value: 0n,
20
- };
27
+ });
28
+ return txs;
21
29
  }
@@ -2,3 +2,17 @@ import { CreateMarketTxParams } from "../tx/types.js";
2
2
  export declare const convertToWeiEthers: (value: string | bigint, decimals: number) => bigint;
3
3
  export declare function isRpcValid(rpcUrl: string | undefined): Promise<boolean>;
4
4
  export declare function getUserAllowance(params: CreateMarketTxParams): Promise<number>;
5
+ /**
6
+ * Checks allowance for a market's base token.
7
+ * Reads baseToken from the market contract, then checks the ERC20 allowance.
8
+ * Also returns the token decimals by reading from the ERC20 contract.
9
+ */
10
+ export declare function checkMarketTokenAllowance(params: {
11
+ marketContractAddress: `0x${string}`;
12
+ owner: `0x${string}`;
13
+ rpcUrl: string;
14
+ }): Promise<{
15
+ allowance: bigint;
16
+ baseToken: `0x${string}`;
17
+ decimals: number;
18
+ }>;
@@ -1,5 +1,6 @@
1
1
  import { ethers, JsonRpcProvider, Contract } from "ethers";
2
2
  import { ERC20Abi } from "../abi/ERC20Abi.js";
3
+ import { getMarketBaseToken } from "../markets/getResolverBondAmount.js";
3
4
  export const convertToWeiEthers = (value, decimals) => {
4
5
  return ethers.parseUnits(value.toString(), decimals);
5
6
  };
@@ -26,3 +27,27 @@ export async function getUserAllowance(params) {
26
27
  const userAllowance = await ERC20ApprovalContract.allowance(creator, factoryContractAddress);
27
28
  return userAllowance;
28
29
  }
30
+ /**
31
+ * Checks allowance for a market's base token.
32
+ * Reads baseToken from the market contract, then checks the ERC20 allowance.
33
+ * Also returns the token decimals by reading from the ERC20 contract.
34
+ */
35
+ export async function checkMarketTokenAllowance(params) {
36
+ const { marketContractAddress, owner, rpcUrl } = params;
37
+ const isRpcWorking = await isRpcValid(rpcUrl);
38
+ if (!rpcUrl || !isRpcWorking) {
39
+ throw new Error("Provided RPC URL is not valid or not working");
40
+ }
41
+ const baseToken = await getMarketBaseToken({ marketContractAddress, rpcUrl });
42
+ const provider = new JsonRpcProvider(rpcUrl);
43
+ const tokenContract = new Contract(baseToken, ERC20Abi, provider);
44
+ const [userAllowance, tokenDecimals] = await Promise.all([
45
+ tokenContract.allowance(owner, marketContractAddress),
46
+ tokenContract.decimals(),
47
+ ]);
48
+ return {
49
+ allowance: BigInt(userAllowance),
50
+ baseToken,
51
+ decimals: Number(tokenDecimals),
52
+ };
53
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "rain-sdk-v2",
3
- "version": "1.0.5",
3
+ "version": "1.0.7",
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",