rain-sdk-v2 2.2.0 → 2.4.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 +60 -0
- package/README.md +71 -8
- package/dist/Rain.d.ts +28 -2
- package/dist/Rain.js +39 -1
- package/dist/RainAA.d.ts +7 -0
- package/dist/RainAA.js +11 -0
- package/dist/api/pools.d.ts +3 -3
- package/dist/api/pools.js +2 -2
- package/dist/api/types.d.ts +47 -0
- package/dist/auth/login.js +16 -1
- package/dist/auth/types.d.ts +2 -0
- package/dist/config/environments.d.ts +0 -1
- package/dist/config/environments.js +0 -4
- package/dist/index.d.ts +3 -1
- package/dist/index.js +2 -1
- package/dist/socket/RainSocket.d.ts +79 -40
- package/dist/socket/RainSocket.js +38 -0
- package/dist/tx/execute.d.ts +30 -0
- package/dist/tx/execute.js +25 -0
- package/dist/utils/helpers.d.ts +2 -1
- package/dist/utils/helpers.js +22 -20
- package/package.json +6 -3
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,66 @@
|
|
|
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.4.0] - Production readiness
|
|
13
|
+
|
|
14
|
+
No breaking changes to the public API.
|
|
15
|
+
|
|
16
|
+
### Fixed
|
|
17
|
+
- **Docs correctness:** the `deadline` examples and parameter tables in the README
|
|
18
|
+
no longer show `deadline: 600n` (a duration), which the builders reject since
|
|
19
|
+
2.2.0. They now show an absolute unix timestamp and note the default 10-min window.
|
|
20
|
+
|
|
21
|
+
### Changed
|
|
22
|
+
- **viem-only (dropped `ethers`):** `utils/helpers.ts` (allowance + decimals reads,
|
|
23
|
+
`parseUnits`, RPC liveness) is ported to viem. `ethers` is removed from
|
|
24
|
+
dependencies — one web3 stack, smaller install/bundle. The redundant
|
|
25
|
+
per-call `getNetwork()` RPC round-trip before allowance checks is gone.
|
|
26
|
+
- **`RainAA` browser-only, documented + guarded:** session methods now throw a
|
|
27
|
+
clear error when `indexedDB` is unavailable (Node/SSR) instead of a cryptic
|
|
28
|
+
`ReferenceError`. Documented in the README and class JSDoc. Use `Rain` for
|
|
29
|
+
server-side flows.
|
|
30
|
+
|
|
31
|
+
### Added
|
|
32
|
+
- **Test suite (vitest):** unit tests for the validators and encoders, plus a
|
|
33
|
+
gated Arbitrum integration test (`npm run test:integration`) exercising the
|
|
34
|
+
on-chain read path. Scripts: `test`, `test:watch`, `test:integration`.
|
|
35
|
+
- **CI:** GitHub Actions — build + test on push/PR, and publish-on-release
|
|
36
|
+
(`.github/workflows/`).
|
|
37
|
+
|
|
38
|
+
### Removed
|
|
39
|
+
- Dead `getRandomRpc` export (superseded by `getDefaultRpc` in 2.3.0).
|
|
40
|
+
- Committed `*.tgz` tarball removed from the repo and gitignored.
|
|
41
|
+
|
|
42
|
+
## [2.3.0] - Developer experience
|
|
43
|
+
|
|
44
|
+
Additive, non-breaking. Fills in the untyped core data model and adds the
|
|
45
|
+
convenience helpers the docs previously pushed onto the caller.
|
|
46
|
+
|
|
47
|
+
### Added
|
|
48
|
+
- **Typed pool DTOs (F-05):** exported `Pool`, `SubPool`, `PaginatedPools`, and
|
|
49
|
+
`TradingModelName`. `getPublicPools` / `getPrivatePools` now return
|
|
50
|
+
`ApiResponse<PaginatedPools>` instead of `unknown`. Socket `*EventData`
|
|
51
|
+
payloads now type their `pool` / `subPool` / `subMarkets` fields as
|
|
52
|
+
`Pool` / `SubPool`. Interfaces carry an index signature, so they are a safe
|
|
53
|
+
superset of the wire (dynamic field access still works).
|
|
54
|
+
- **`rain.execute(txs, executor)` (F-07):** sequences the `[approval, main]`
|
|
55
|
+
arrays the builders return — sends each tx and awaits its receipt before the
|
|
56
|
+
next. Pluggable `TxExecutor` (`{ send, wait? }`) adapts to viem, ethers, or
|
|
57
|
+
RainAA. Also exported as the standalone `executeTxs`.
|
|
58
|
+
- **`rain.parseAmount` / `rain.formatAmount` (F-14):** convert between
|
|
59
|
+
human-readable amounts and base units using the token's configured decimals
|
|
60
|
+
(no more hand-tracking that USDT is 6 and RAIN is 18).
|
|
61
|
+
- **`RAIN_SOCKET_EVENTS` (F-16):** correctly-spelled camelCase aliases for the
|
|
62
|
+
raw wire event names (including the upstream-misspelled `dispute-time-extented`).
|
|
63
|
+
- **Token expiry (F-13):** `LoginResult.expiresAt` exposes the decoded JWT `exp`
|
|
64
|
+
(unix seconds) so apps can renew proactively.
|
|
65
|
+
|
|
6
66
|
## [2.2.0] - Guardrails
|
|
7
67
|
|
|
8
68
|
Adds fail-fast validation and structured errors. These surface mistakes
|
package/README.md
CHANGED
|
@@ -71,6 +71,8 @@ const rain = new Rain(config?: RainCoreConfig);
|
|
|
71
71
|
|
|
72
72
|
Stateful class for smart account (Account Abstraction) management with Alchemy gas sponsorship.
|
|
73
73
|
|
|
74
|
+
> ⚠️ **Browser-only.** `RainAA` persists session keys in `indexedDB`, so it is **not supported in Node.js or SSR** — session methods throw a descriptive error in those environments. For server-side flows use the stateless `Rain` class (transaction building and on-chain reads), which runs anywhere.
|
|
75
|
+
|
|
74
76
|
#### Constructor
|
|
75
77
|
|
|
76
78
|
```typescript
|
|
@@ -213,7 +215,7 @@ const txs = await rain.buildEnterOptionTx({
|
|
|
213
215
|
buyAmountInWei: parseUnits('5', 6), // 5 USDT (or parseUnits('5', 18) for RAIN)
|
|
214
216
|
walletAddress: '0x...', // user's wallet address
|
|
215
217
|
slippageTolerance: 5n, // optional, default 5% — percentage tolerance for minSharesOut
|
|
216
|
-
deadline:
|
|
218
|
+
deadline: BigInt(Math.floor(Date.now() / 1000) + 600), // optional — absolute unix timestamp; omit for a default 10-min window
|
|
217
219
|
});
|
|
218
220
|
// Returns [approveTx?, enterOptionTx]
|
|
219
221
|
```
|
|
@@ -227,7 +229,7 @@ const txs = await rain.buildEnterOptionTx({
|
|
|
227
229
|
| `walletAddress` | `0x${string}` | User's wallet address (for allowance check) |
|
|
228
230
|
| `minSharesOut` | `bigint` | *(Optional)* Minimum shares to receive. Auto-calculated from `getEntryShares` with slippage if not set |
|
|
229
231
|
| `slippageTolerance` | `bigint` | *(Optional)* Slippage percentage (e.g. `5n` = 5%). Default: 5% |
|
|
230
|
-
| `deadline` | `bigint` | *(Optional)*
|
|
232
|
+
| `deadline` | `bigint` | *(Optional)* Absolute unix timestamp in seconds, e.g. `BigInt(Math.floor(Date.now()/1000) + 600)`. Omit for a default 10-min window. A small duration like `600n` is **rejected** (`RainValidationError`). |
|
|
231
233
|
|
|
232
234
|
> **Note:** Approval is handled automatically. The SDK reads `baseToken` from the market contract and checks allowance before building transactions. Slippage protection is auto-calculated: the SDK calls `getEntryShares` on-chain to get expected shares, then applies the slippage tolerance.
|
|
233
235
|
|
|
@@ -244,7 +246,7 @@ const tx = await rain.buildSellOptionTx({
|
|
|
244
246
|
optionSide: OptionSide.Yes, // Yes = 1, No = 2
|
|
245
247
|
sharesAmount: parseUnits('10', 6), // shares to sell
|
|
246
248
|
slippageTolerance: 5n, // optional, default 5%
|
|
247
|
-
deadline:
|
|
249
|
+
deadline: BigInt(Math.floor(Date.now() / 1000) + 600), // optional — absolute unix timestamp; omit for a default 10-min window
|
|
248
250
|
});
|
|
249
251
|
// Returns a single RawTransaction (no approval needed)
|
|
250
252
|
```
|
|
@@ -257,7 +259,7 @@ const tx = await rain.buildSellOptionTx({
|
|
|
257
259
|
| `sharesAmount` | `bigint` | Number of shares to sell |
|
|
258
260
|
| `minAmountOut` | `bigint` | *(Optional)* Minimum base tokens to receive. Auto-calculated from `getCurrentPrice` with slippage if not set |
|
|
259
261
|
| `slippageTolerance` | `bigint` | *(Optional)* Slippage percentage (e.g. `5n` = 5%). Default: 5% |
|
|
260
|
-
| `deadline` | `bigint` | *(Optional)*
|
|
262
|
+
| `deadline` | `bigint` | *(Optional)* Absolute unix timestamp in seconds, e.g. `BigInt(Math.floor(Date.now()/1000) + 600)`. Omit for a default 10-min window. A small duration like `600n` is **rejected** (`RainValidationError`). |
|
|
261
263
|
|
|
262
264
|
---
|
|
263
265
|
|
|
@@ -308,7 +310,7 @@ const txs = await rain.buildAddLiquidityTx({
|
|
|
308
310
|
totalAmountInWei: parseUnits('10', 6), // 10 USDT
|
|
309
311
|
walletAddress: '0x...', // user's wallet address
|
|
310
312
|
slippageTolerance: 5n, // optional, default 5%
|
|
311
|
-
deadline:
|
|
313
|
+
deadline: BigInt(Math.floor(Date.now() / 1000) + 600), // optional — absolute unix timestamp; omit for a default 10-min window
|
|
312
314
|
});
|
|
313
315
|
// Returns [approveTx?, addLiquidityTx]
|
|
314
316
|
```
|
|
@@ -322,7 +324,7 @@ const txs = await rain.buildAddLiquidityTx({
|
|
|
322
324
|
| `minYesToDeposit` | `bigint` | *(Optional)* Min yes tokens to deposit. Auto-calculated from reserves if not set |
|
|
323
325
|
| `minNoToDeposit` | `bigint` | *(Optional)* Min no tokens to deposit. Auto-calculated from reserves if not set |
|
|
324
326
|
| `slippageTolerance` | `bigint` | *(Optional)* Slippage percentage (e.g. `5n` = 5%). Default: 5% |
|
|
325
|
-
| `deadline` | `bigint` | *(Optional)*
|
|
327
|
+
| `deadline` | `bigint` | *(Optional)* Absolute unix timestamp in seconds, e.g. `BigInt(Math.floor(Date.now()/1000) + 600)`. Omit for a default 10-min window. A small duration like `600n` is **rejected** (`RainValidationError`). |
|
|
326
328
|
|
|
327
329
|
> **Note:** Approval is handled automatically. Slippage protection is auto-calculated from `ammYesReserve`/`ammNoReserve` proportionally.
|
|
328
330
|
|
|
@@ -342,7 +344,7 @@ const tx = await rain.buildRemoveLiquidityTx({
|
|
|
342
344
|
option: 1n,
|
|
343
345
|
lpShares, // raw LP shares amount
|
|
344
346
|
slippageTolerance: 5n, // optional, default 5%
|
|
345
|
-
deadline:
|
|
347
|
+
deadline: BigInt(Math.floor(Date.now() / 1000) + 600), // optional — absolute unix timestamp; omit for a default 10-min window
|
|
346
348
|
});
|
|
347
349
|
```
|
|
348
350
|
|
|
@@ -354,7 +356,7 @@ const tx = await rain.buildRemoveLiquidityTx({
|
|
|
354
356
|
| `minYesOut` | `bigint` | *(Optional)* Min yes tokens to receive. Auto-calculated from `getRemovedLiquidity` if not set |
|
|
355
357
|
| `minNoOut` | `bigint` | *(Optional)* Min no tokens to receive. Auto-calculated if not set |
|
|
356
358
|
| `slippageTolerance` | `bigint` | *(Optional)* Slippage percentage (e.g. `5n` = 5%). Default: 5% |
|
|
357
|
-
| `deadline` | `bigint` | *(Optional)*
|
|
359
|
+
| `deadline` | `bigint` | *(Optional)* Absolute unix timestamp in seconds, e.g. `BigInt(Math.floor(Date.now()/1000) + 600)`. Omit for a default 10-min window. A small duration like `600n` is **rejected** (`RainValidationError`). |
|
|
358
360
|
|
|
359
361
|
---
|
|
360
362
|
|
|
@@ -1544,6 +1546,67 @@ socket.disconnect();
|
|
|
1544
1546
|
|
|
1545
1547
|
---
|
|
1546
1548
|
|
|
1549
|
+
## Helpers & Execution
|
|
1550
|
+
|
|
1551
|
+
### Executing transactions
|
|
1552
|
+
|
|
1553
|
+
Builders return unsigned `RawTransaction[]` where index 0 may be an ERC-20
|
|
1554
|
+
approval. `rain.execute()` sends them in order and waits for each receipt before
|
|
1555
|
+
the next — so the main transaction never front-runs its approval:
|
|
1556
|
+
|
|
1557
|
+
```typescript
|
|
1558
|
+
const txs = await rain.buildEnterOptionTx({ /* ... */ });
|
|
1559
|
+
|
|
1560
|
+
await rain.execute(txs, {
|
|
1561
|
+
send: (tx) => walletClient.sendTransaction({ to: tx.to, data: tx.data, value: tx.value ?? 0n }),
|
|
1562
|
+
wait: (hash) => publicClient.waitForTransactionReceipt({ hash }),
|
|
1563
|
+
});
|
|
1564
|
+
```
|
|
1565
|
+
|
|
1566
|
+
The executor is pluggable — adapt `{ send, wait? }` to viem, ethers, RainAA, or
|
|
1567
|
+
your own KMS. Also available as the standalone `executeTxs(txs, executor)`.
|
|
1568
|
+
|
|
1569
|
+
### Amount conversion
|
|
1570
|
+
|
|
1571
|
+
Convert between human-readable amounts and base units using the token's
|
|
1572
|
+
configured decimals — no need to track that USDT is 6 and RAIN is 18:
|
|
1573
|
+
|
|
1574
|
+
```typescript
|
|
1575
|
+
rain.parseAmount('5', usdtAddress); // 5_000_000n
|
|
1576
|
+
rain.formatAmount(5_000_000n, usdtAddress); // '5'
|
|
1577
|
+
```
|
|
1578
|
+
|
|
1579
|
+
### Typed pool data
|
|
1580
|
+
|
|
1581
|
+
`getPublicPools` / `getPrivatePools` return `ApiResponse<PaginatedPools>`, and
|
|
1582
|
+
socket event payloads type their `pool` / `subPool` fields as `Pool` / `SubPool`.
|
|
1583
|
+
Import the DTOs to annotate your own code:
|
|
1584
|
+
|
|
1585
|
+
```typescript
|
|
1586
|
+
import type { Pool, SubPool, PaginatedPools } from 'rain-sdk-v2';
|
|
1587
|
+
```
|
|
1588
|
+
|
|
1589
|
+
### Socket event names
|
|
1590
|
+
|
|
1591
|
+
Use `RAIN_SOCKET_EVENTS` for correctly-spelled event identifiers with the
|
|
1592
|
+
low-level `.on()` API (some raw wire names are misspelled upstream):
|
|
1593
|
+
|
|
1594
|
+
```typescript
|
|
1595
|
+
import { RAIN_SOCKET_EVENTS } from 'rain-sdk-v2';
|
|
1596
|
+
socket.on(RAIN_SOCKET_EVENTS.disputeTimeExtended, poolId, handler);
|
|
1597
|
+
```
|
|
1598
|
+
|
|
1599
|
+
### Token expiry
|
|
1600
|
+
|
|
1601
|
+
`login()` returns `expiresAt` (unix seconds, decoded from the JWT) so you can
|
|
1602
|
+
renew before it lapses:
|
|
1603
|
+
|
|
1604
|
+
```typescript
|
|
1605
|
+
const { accessToken, expiresAt } = await rain.login({ /* ... */ });
|
|
1606
|
+
```
|
|
1607
|
+
|
|
1608
|
+
---
|
|
1609
|
+
|
|
1547
1610
|
## Error Handling & Validation
|
|
1548
1611
|
|
|
1549
1612
|
### 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<
|
|
237
|
-
getPrivatePools(params: PrivatePoolsParams, accessToken?: string): Promise<import("./api/types.js").ApiResponse<
|
|
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 {
|
|
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([
|
package/dist/RainAA.d.ts
CHANGED
|
@@ -1,5 +1,12 @@
|
|
|
1
1
|
import { RainConfig } from './types.js';
|
|
2
2
|
import { RawTransaction } from './tx/types.js';
|
|
3
|
+
/**
|
|
4
|
+
* Smart-account (Account Abstraction) manager with Alchemy gas sponsorship.
|
|
5
|
+
*
|
|
6
|
+
* ⚠️ **Browser-only.** Session persistence uses `indexedDB`, so `RainAA` is not
|
|
7
|
+
* supported in Node.js or SSR — session methods throw a descriptive error there.
|
|
8
|
+
* The stateless `Rain` class works in any environment; use it for server-side flows.
|
|
9
|
+
*/
|
|
3
10
|
export declare class RainAA {
|
|
4
11
|
private config;
|
|
5
12
|
private _client;
|
package/dist/RainAA.js
CHANGED
|
@@ -3,6 +3,10 @@ const SESSION_DURATION_SEC = 60 * 60 * 24; // 24 hours
|
|
|
3
3
|
const DB_NAME = 'RainSDKV2';
|
|
4
4
|
const STORE_NAME = 'sessions';
|
|
5
5
|
function openSessionDB() {
|
|
6
|
+
if (typeof indexedDB === 'undefined') {
|
|
7
|
+
return Promise.reject(new Error('RainAA requires a browser environment: session persistence uses indexedDB, ' +
|
|
8
|
+
'which is unavailable in Node.js/SSR. RainAA is browser-only.'));
|
|
9
|
+
}
|
|
6
10
|
return new Promise((resolve, reject) => {
|
|
7
11
|
const req = indexedDB.open(DB_NAME, 1);
|
|
8
12
|
req.onupgradeneeded = () => {
|
|
@@ -42,6 +46,13 @@ async function deleteSession(key) {
|
|
|
42
46
|
tx.onerror = () => reject(tx.error);
|
|
43
47
|
});
|
|
44
48
|
}
|
|
49
|
+
/**
|
|
50
|
+
* Smart-account (Account Abstraction) manager with Alchemy gas sponsorship.
|
|
51
|
+
*
|
|
52
|
+
* ⚠️ **Browser-only.** Session persistence uses `indexedDB`, so `RainAA` is not
|
|
53
|
+
* supported in Node.js or SSR — session methods throw a descriptive error there.
|
|
54
|
+
* The stateless `Rain` class works in any environment; use it for server-side flows.
|
|
55
|
+
*/
|
|
45
56
|
export class RainAA {
|
|
46
57
|
config;
|
|
47
58
|
_client = null; // EOA-signed client (for grantPermissions)
|
package/dist/api/pools.d.ts
CHANGED
|
@@ -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)}`, {
|
package/dist/api/types.d.ts
CHANGED
|
@@ -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;
|
package/dist/auth/login.js
CHANGED
|
@@ -1,3 +1,18 @@
|
|
|
1
|
+
/** Decode the `exp` (unix seconds) claim from a JWT without verifying it. Uses `atob` (browser + Node 18+). */
|
|
2
|
+
function decodeJwtExp(token) {
|
|
3
|
+
try {
|
|
4
|
+
const part = token.split('.')[1];
|
|
5
|
+
if (!part || typeof atob !== 'function')
|
|
6
|
+
return undefined;
|
|
7
|
+
const b64 = part.replace(/-/g, '+').replace(/_/g, '/');
|
|
8
|
+
const padded = b64 + '='.repeat((4 - (b64.length % 4)) % 4);
|
|
9
|
+
const payload = JSON.parse(atob(padded));
|
|
10
|
+
return typeof payload?.exp === 'number' ? payload.exp : undefined;
|
|
11
|
+
}
|
|
12
|
+
catch {
|
|
13
|
+
return undefined;
|
|
14
|
+
}
|
|
15
|
+
}
|
|
1
16
|
export async function loginUser(params) {
|
|
2
17
|
const { signature, walletAddress, smartWalletAddress, referredBy, apiUrl } = params;
|
|
3
18
|
// Plain-EOA integrations may omit smartWalletAddress; fall back to the EOA.
|
|
@@ -25,5 +40,5 @@ export async function loginUser(params) {
|
|
|
25
40
|
if (!accessToken || !userId) {
|
|
26
41
|
throw new Error('Login response missing token or user id');
|
|
27
42
|
}
|
|
28
|
-
return { accessToken, userId };
|
|
43
|
+
return { accessToken, userId, expiresAt: decodeJwtExp(accessToken) };
|
|
29
44
|
}
|
package/dist/auth/types.d.ts
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
export declare const ALLOWED_ENVIRONMENTS: readonly ["development", "stage", "production"];
|
|
2
2
|
export declare const DEFAULT_RPCS: string[];
|
|
3
|
-
export declare function getRandomRpc(): string;
|
|
4
3
|
/** Deterministic default RPC — every instance resolves to the same endpoint. */
|
|
5
4
|
export declare function getDefaultRpc(): string;
|
|
6
5
|
export declare const USDT_SYMBOL_DEV = "USDTm";
|
|
@@ -4,10 +4,6 @@ export const DEFAULT_RPCS = [
|
|
|
4
4
|
"https://arbitrum-one.publicnode.com",
|
|
5
5
|
"https://rpc.sentio.xyz/arbitrum-one"
|
|
6
6
|
];
|
|
7
|
-
export function getRandomRpc() {
|
|
8
|
-
const index = Math.floor(Math.random() * DEFAULT_RPCS.length);
|
|
9
|
-
return DEFAULT_RPCS[index];
|
|
10
|
-
}
|
|
11
7
|
/** Deterministic default RPC — every instance resolves to the same endpoint. */
|
|
12
8
|
export function getDefaultRpc() {
|
|
13
9
|
return DEFAULT_RPCS[0];
|
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:
|
|
5
|
-
subPool:
|
|
43
|
+
pool: Pool;
|
|
44
|
+
subPool: SubPool;
|
|
6
45
|
}
|
|
7
46
|
export interface ExitOptionEventData {
|
|
8
47
|
exitOption: Record<string, any>;
|
|
9
|
-
pool:
|
|
10
|
-
subPool:
|
|
48
|
+
pool: Pool;
|
|
49
|
+
subPool: SubPool;
|
|
11
50
|
}
|
|
12
51
|
export interface LiquidityEventData {
|
|
13
52
|
enterLiquidity: Record<string, any>;
|
|
14
|
-
pool:
|
|
15
|
-
subPool:
|
|
53
|
+
pool: Pool;
|
|
54
|
+
subPool: SubPool;
|
|
16
55
|
}
|
|
17
56
|
export interface SplitEventData {
|
|
18
57
|
split: Record<string, any>;
|
|
19
|
-
pool:
|
|
20
|
-
subPool:
|
|
58
|
+
pool: Pool;
|
|
59
|
+
subPool: SubPool;
|
|
21
60
|
}
|
|
22
61
|
export interface MergeEventData {
|
|
23
62
|
merge: Record<string, any>;
|
|
24
|
-
pool:
|
|
25
|
-
subPool:
|
|
63
|
+
pool: Pool;
|
|
64
|
+
subPool: SubPool;
|
|
26
65
|
}
|
|
27
66
|
export interface RemoveLiquidityEventData {
|
|
28
67
|
removeLiquidity: Record<string, any>;
|
|
29
|
-
pool:
|
|
30
|
-
subPool:
|
|
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:
|
|
40
|
-
subPool:
|
|
78
|
+
pool: Pool;
|
|
79
|
+
subPool: SubPool;
|
|
41
80
|
}
|
|
42
81
|
export interface OrderCreatedEventData {
|
|
43
82
|
order: Record<string, any>;
|
|
44
|
-
pool:
|
|
45
|
-
subPool:
|
|
83
|
+
pool: Pool;
|
|
84
|
+
subPool: SubPool;
|
|
46
85
|
}
|
|
47
86
|
export interface OrderCancelledEventData {
|
|
48
87
|
order: Record<string, any>;
|
|
49
|
-
pool:
|
|
50
|
-
subPool:
|
|
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:
|
|
56
|
-
subPool:
|
|
94
|
+
pool: Pool;
|
|
95
|
+
subPool: SubPool;
|
|
57
96
|
}
|
|
58
97
|
export interface PoolClosedEventData {
|
|
59
|
-
pool:
|
|
60
|
-
subPool?:
|
|
98
|
+
pool: Pool;
|
|
99
|
+
subPool?: SubPool;
|
|
61
100
|
}
|
|
62
101
|
export interface PoolEventData {
|
|
63
|
-
pool:
|
|
64
|
-
subMarkets?:
|
|
102
|
+
pool: Pool;
|
|
103
|
+
subMarkets?: SubPool[];
|
|
65
104
|
}
|
|
66
105
|
export interface WinnerEventData {
|
|
67
|
-
pool:
|
|
68
|
-
subPool:
|
|
106
|
+
pool: Pool;
|
|
107
|
+
subPool: SubPool;
|
|
69
108
|
}
|
|
70
109
|
export interface DisputeOpenedEventData {
|
|
71
|
-
subPool:
|
|
110
|
+
subPool: SubPool;
|
|
72
111
|
eventType: string;
|
|
73
112
|
}
|
|
74
113
|
export interface OracleCreatedEventData {
|
|
75
|
-
pool:
|
|
76
|
-
subPool:
|
|
114
|
+
pool: Pool;
|
|
115
|
+
subPool: SubPool;
|
|
77
116
|
}
|
|
78
117
|
export interface AppealOpenedEventData {
|
|
79
|
-
pool:
|
|
80
|
-
subPool:
|
|
118
|
+
pool: Pool;
|
|
119
|
+
subPool: SubPool;
|
|
81
120
|
}
|
|
82
121
|
export interface DisputeWinnerEventData {
|
|
83
|
-
subPool:
|
|
122
|
+
subPool: SubPool;
|
|
84
123
|
eventType: string;
|
|
85
124
|
}
|
|
86
125
|
export interface AppealWinnerEventData {
|
|
87
|
-
subPool:
|
|
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:
|
|
94
|
-
subPool:
|
|
132
|
+
pool: Pool;
|
|
133
|
+
subPool: SubPool;
|
|
95
134
|
}
|
|
96
135
|
export interface DisputeRefundEventData {
|
|
97
136
|
claimReward: Record<string, any>;
|
|
98
|
-
pool:
|
|
99
|
-
subPool:
|
|
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:
|
|
157
|
-
subPool:
|
|
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:
|
|
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/dist/utils/helpers.d.ts
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { CreateMarketTxParams } from "../tx/types.js";
|
|
2
2
|
export declare const convertToWeiEthers: (value: string | bigint, decimals: number) => bigint;
|
|
3
|
+
/** Lightweight RPC liveness check via viem `getChainId`. Kept for callers that want a pre-flight probe. */
|
|
3
4
|
export declare function isRpcValid(rpcUrl: string | undefined): Promise<boolean>;
|
|
4
|
-
export declare function getUserAllowance(params: CreateMarketTxParams): Promise<
|
|
5
|
+
export declare function getUserAllowance(params: CreateMarketTxParams): Promise<bigint>;
|
|
5
6
|
/**
|
|
6
7
|
* Checks allowance for a market's base token.
|
|
7
8
|
* Reads baseToken from the market contract, then checks the ERC20 allowance.
|
package/dist/utils/helpers.js
CHANGED
|
@@ -1,31 +1,36 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { parseUnits, createPublicClient, http } from "viem";
|
|
2
|
+
import { arbitrum } from "viem/chains";
|
|
2
3
|
import { ERC20Abi } from "../abi/ERC20Abi.js";
|
|
3
4
|
import { getMarketBaseToken } from "../markets/getResolverBondAmount.js";
|
|
5
|
+
const erc20Abi = ERC20Abi;
|
|
4
6
|
export const convertToWeiEthers = (value, decimals) => {
|
|
5
|
-
return
|
|
7
|
+
return parseUnits(value.toString(), decimals);
|
|
6
8
|
};
|
|
9
|
+
/** Lightweight RPC liveness check via viem `getChainId`. Kept for callers that want a pre-flight probe. */
|
|
7
10
|
export async function isRpcValid(rpcUrl) {
|
|
8
11
|
if (!rpcUrl)
|
|
9
12
|
return false;
|
|
10
|
-
const provider = new JsonRpcProvider(rpcUrl);
|
|
11
13
|
try {
|
|
12
|
-
|
|
14
|
+
const client = createPublicClient({ chain: arbitrum, transport: http(rpcUrl) });
|
|
15
|
+
await client.getChainId();
|
|
13
16
|
return true;
|
|
14
17
|
}
|
|
15
|
-
catch
|
|
18
|
+
catch {
|
|
16
19
|
return false;
|
|
17
20
|
}
|
|
18
21
|
}
|
|
19
22
|
export async function getUserAllowance(params) {
|
|
20
23
|
const { factoryContractAddress, baseToken, creator, rpcUrl } = params;
|
|
21
|
-
|
|
22
|
-
if (!rpcUrl || !isRpcWorking) {
|
|
24
|
+
if (!rpcUrl)
|
|
23
25
|
throw new Error("Provided RPC URL is not valid or not working");
|
|
24
|
-
}
|
|
25
|
-
const
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
26
|
+
const client = createPublicClient({ chain: arbitrum, transport: http(rpcUrl) });
|
|
27
|
+
const allowance = await client.readContract({
|
|
28
|
+
address: baseToken,
|
|
29
|
+
abi: erc20Abi,
|
|
30
|
+
functionName: 'allowance',
|
|
31
|
+
args: [creator, factoryContractAddress],
|
|
32
|
+
});
|
|
33
|
+
return allowance;
|
|
29
34
|
}
|
|
30
35
|
/**
|
|
31
36
|
* Checks allowance for a market's base token.
|
|
@@ -34,19 +39,16 @@ export async function getUserAllowance(params) {
|
|
|
34
39
|
*/
|
|
35
40
|
export async function checkMarketTokenAllowance(params) {
|
|
36
41
|
const { marketContractAddress, owner, rpcUrl } = params;
|
|
37
|
-
|
|
38
|
-
if (!rpcUrl || !isRpcWorking) {
|
|
42
|
+
if (!rpcUrl)
|
|
39
43
|
throw new Error("Provided RPC URL is not valid or not working");
|
|
40
|
-
}
|
|
41
44
|
const baseToken = await getMarketBaseToken({ marketContractAddress, rpcUrl });
|
|
42
|
-
const
|
|
43
|
-
const tokenContract = new Contract(baseToken, ERC20Abi, provider);
|
|
45
|
+
const client = createPublicClient({ chain: arbitrum, transport: http(rpcUrl) });
|
|
44
46
|
const [userAllowance, tokenDecimals] = await Promise.all([
|
|
45
|
-
|
|
46
|
-
|
|
47
|
+
client.readContract({ address: baseToken, abi: erc20Abi, functionName: 'allowance', args: [owner, marketContractAddress] }),
|
|
48
|
+
client.readContract({ address: baseToken, abi: erc20Abi, functionName: 'decimals' }),
|
|
47
49
|
]);
|
|
48
50
|
return {
|
|
49
|
-
allowance:
|
|
51
|
+
allowance: userAllowance,
|
|
50
52
|
baseToken,
|
|
51
53
|
decimals: Number(tokenDecimals),
|
|
52
54
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "rain-sdk-v2",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.4.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",
|
|
@@ -19,6 +19,9 @@
|
|
|
19
19
|
"scripts": {
|
|
20
20
|
"build": "tsc",
|
|
21
21
|
"dev": "tsc -w",
|
|
22
|
+
"test": "vitest run",
|
|
23
|
+
"test:watch": "vitest",
|
|
24
|
+
"test:integration": "RUN_INTEGRATION=1 vitest run test/integration.test.ts",
|
|
22
25
|
"prepublishOnly": "npm run build"
|
|
23
26
|
},
|
|
24
27
|
"repository": {
|
|
@@ -57,11 +60,11 @@
|
|
|
57
60
|
}
|
|
58
61
|
},
|
|
59
62
|
"dependencies": {
|
|
60
|
-
"ethers": "^6.16.0",
|
|
61
63
|
"socket.io-client": "^4.8.3"
|
|
62
64
|
},
|
|
63
65
|
"devDependencies": {
|
|
64
66
|
"typescript": "^5.9.3",
|
|
65
|
-
"viem": "^2.48.8"
|
|
67
|
+
"viem": "^2.48.8",
|
|
68
|
+
"vitest": "^5.0.1"
|
|
66
69
|
}
|
|
67
70
|
}
|