@pulsepairs/sdk 0.5.1 → 0.6.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/DOCUMENTATION.md +1487 -0
- package/README.md +4 -0
- package/dist/http.d.ts +12 -0
- package/dist/http.js +24 -2
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/pnl.d.ts +18 -1
- package/dist/pnl.js +5 -1
- package/dist/types.d.ts +22 -0
- package/dist/types.js +11 -0
- package/package.json +3 -2
package/README.md
CHANGED
|
@@ -19,6 +19,10 @@ It gives you three things:
|
|
|
19
19
|
Alchemy smart-contract account (the SAME wallet rain.trade uses), plus
|
|
20
20
|
gasless onboarding / approve / withdraw.
|
|
21
21
|
|
|
22
|
+
> This README is the quickstart. For the exhaustive reference — every export,
|
|
23
|
+
> its units, its failure modes, the WS protocol, the full type surface and a
|
|
24
|
+
> troubleshooting table — see **[`DOCUMENTATION.md`](./DOCUMENTATION.md)**.
|
|
25
|
+
|
|
22
26
|
> **Live integration environment:** a public demo of the full stack (markets
|
|
23
27
|
> cycling 24/7 on Arbitrum One, mock oracle, mintable test USDT) runs at
|
|
24
28
|
> **https://demo-pulsepairs.rainwins.com** with the matcher API/WS at
|
package/dist/http.d.ts
CHANGED
|
@@ -18,6 +18,18 @@ export declare class UpDownHttpClient {
|
|
|
18
18
|
getOrderbook(marketAddress: string): Promise<OrderBookFull>;
|
|
19
19
|
getBalance(wallet: string): Promise<Balance>;
|
|
20
20
|
getPositions(wallet: string): Promise<Position[]>;
|
|
21
|
+
/**
|
|
22
|
+
* Open positions PLUS the wallet-level realized-from-sells scalar (atomic
|
|
23
|
+
* USDT, signed). Uses `?includeRealized=1`; `getPositions` keeps the plain
|
|
24
|
+
* bare-array response for callers that don't need the realized term.
|
|
25
|
+
*
|
|
26
|
+
* Tolerant of a backend that predates the envelope: if the body comes back a
|
|
27
|
+
* bare array, the realized term is simply reported as "0" rather than failing.
|
|
28
|
+
*/
|
|
29
|
+
getPositionsWithRealized(wallet: string): Promise<{
|
|
30
|
+
positions: Position[];
|
|
31
|
+
realizedFromSells: string;
|
|
32
|
+
}>;
|
|
21
33
|
getTrades(wallet: string, opts?: {
|
|
22
34
|
limit?: number;
|
|
23
35
|
offset?: number;
|
package/dist/http.js
CHANGED
|
@@ -69,6 +69,21 @@ export class UpDownHttpClient {
|
|
|
69
69
|
const res = await fetch(buildUrl(this.baseUrl, `/positions/${wallet}`));
|
|
70
70
|
return parseJson(res);
|
|
71
71
|
}
|
|
72
|
+
/**
|
|
73
|
+
* Open positions PLUS the wallet-level realized-from-sells scalar (atomic
|
|
74
|
+
* USDT, signed). Uses `?includeRealized=1`; `getPositions` keeps the plain
|
|
75
|
+
* bare-array response for callers that don't need the realized term.
|
|
76
|
+
*
|
|
77
|
+
* Tolerant of a backend that predates the envelope: if the body comes back a
|
|
78
|
+
* bare array, the realized term is simply reported as "0" rather than failing.
|
|
79
|
+
*/
|
|
80
|
+
async getPositionsWithRealized(wallet) {
|
|
81
|
+
const res = await fetch(buildUrl(this.baseUrl, `/positions/${wallet}`, { includeRealized: 1 }));
|
|
82
|
+
const body = await parseJson(res);
|
|
83
|
+
if (Array.isArray(body))
|
|
84
|
+
return { positions: body, realizedFromSells: "0" };
|
|
85
|
+
return { positions: body.positions ?? [], realizedFromSells: body.realizedFromSells ?? "0" };
|
|
86
|
+
}
|
|
72
87
|
async getTrades(wallet, opts) {
|
|
73
88
|
const res = await fetch(buildUrl(this.baseUrl, `/trades/${wallet}`, {
|
|
74
89
|
limit: opts?.limit,
|
|
@@ -91,9 +106,15 @@ export class UpDownHttpClient {
|
|
|
91
106
|
* @param opts.usdtDecimals display-float decimals (default 6).
|
|
92
107
|
*/
|
|
93
108
|
async getPnl(wallet, opts) {
|
|
94
|
-
|
|
109
|
+
// Fetch the realized-from-sells scalar alongside the positions so the
|
|
110
|
+
// rolled-up PnL carries realized (from manual sells) as well as unrealized.
|
|
111
|
+
// Backward-tolerant: an old backend yields "0" here, not an error.
|
|
112
|
+
const { positions, realizedFromSells } = await this.getPositionsWithRealized(wallet);
|
|
95
113
|
if (positions.length === 0) {
|
|
96
|
-
return computePortfolioPnl([], new Map(), {
|
|
114
|
+
return computePortfolioPnl([], new Map(), {
|
|
115
|
+
usdtDecimals: opts?.usdtDecimals,
|
|
116
|
+
realizedFromSells,
|
|
117
|
+
});
|
|
97
118
|
}
|
|
98
119
|
const marketKeys = Array.from(new Set(positions.map((p) => p.market)));
|
|
99
120
|
const details = await Promise.all(marketKeys.map((key) => this.getMarket(key).catch(() => null)));
|
|
@@ -111,6 +132,7 @@ export class UpDownHttpClient {
|
|
|
111
132
|
return computePortfolioPnl(positions, marketsByKey, {
|
|
112
133
|
fees,
|
|
113
134
|
usdtDecimals: opts?.usdtDecimals,
|
|
135
|
+
realizedFromSells,
|
|
114
136
|
});
|
|
115
137
|
}
|
|
116
138
|
async getOrders(wallet, opts) {
|
package/dist/index.d.ts
CHANGED
|
@@ -7,4 +7,4 @@ export { readOnChainHolderShares, reconcileFills, reportedFromPositions, type On
|
|
|
7
7
|
export { UpDownAccountKitSigner, bareErc1271Signer, stripErc6492Wrapper, isErc6492Signature, type UpDownAccountKitConfig, type Eip1193Provider, type GrantSessionResult, type RawTypedDataSigner, } from "./accountKit.js";
|
|
8
8
|
export { buildApproveSettlementTx, buildInstallOrderSessionTx, signWithOrderSession, type RawTransaction, type OrderSessionRecord, } from "./accountKit.js";
|
|
9
9
|
export { PRICE_BPS_SCALE, WIN_MARK_BPS, LOSE_MARK_BPS, DEFAULT_USDT_DECIMALS, atomicToUsdt, markValueAtomic, midBps, markForOption, isResolvedWinner, positionPnl, feesPaidByWallet, portfolioPnl, computePortfolioPnl, type MarkSource, type PositionPnl, type PortfolioPnl, type PositionPnlOptions, } from "./pnl.js";
|
|
10
|
-
export { OrderType, OrderSide, Option, type ApiConfig, type Balance, type CancelOrderBody, type Eip712Domain, type MarketDetail, type MarketListItem, type OptionValue, type OrderBookFull, type OrderBookLevel, type OrderBookSide, type OrderRow, type OrderSideKey, type OrderSideValue, type OrderStatus, type OrderTypeKey, type OrderTypeValue, type OrdersResponse, type PairConfig, type PairSymbol, type PostOrderBody, type Position, type Stats, type Trade, type Version, } from "./types.js";
|
|
10
|
+
export { OrderType, OrderSide, Option, takerPriceBps, type ApiConfig, type Balance, type CancelOrderBody, type Eip712Domain, type MarketDetail, type MarketListItem, type OptionValue, type OrderBookFull, type OrderBookLevel, type OrderBookSide, type OrderRow, type OrderSideKey, type OrderSideValue, type OrderStatus, type OrderTypeKey, type OrderTypeValue, type OrdersResponse, type PairConfig, type PairSymbol, type PostOrderBody, type Position, type Stats, type Trade, type Version, } from "./types.js";
|
package/dist/index.js
CHANGED
|
@@ -25,4 +25,4 @@ export { buildApproveSettlementTx, buildInstallOrderSessionTx, signWithOrderSess
|
|
|
25
25
|
// contract). `UpDownHttpClient.getPnl` is the batteries-included wrapper.
|
|
26
26
|
export { PRICE_BPS_SCALE, WIN_MARK_BPS, LOSE_MARK_BPS, DEFAULT_USDT_DECIMALS, atomicToUsdt, markValueAtomic, midBps, markForOption, isResolvedWinner, positionPnl, feesPaidByWallet, portfolioPnl, computePortfolioPnl, } from "./pnl.js";
|
|
27
27
|
// Types
|
|
28
|
-
export { OrderType, OrderSide, Option, } from "./types.js";
|
|
28
|
+
export { OrderType, OrderSide, Option, takerPriceBps, } from "./types.js";
|
package/dist/pnl.d.ts
CHANGED
|
@@ -82,6 +82,18 @@ export type PortfolioPnl = {
|
|
|
82
82
|
* (see `feesPaidByWallet`); "0" otherwise. Not netted into `unrealizedPnl`
|
|
83
83
|
* — cost basis is fee-exclusive, so fees stay a separate, explicit line. */
|
|
84
84
|
fees: string;
|
|
85
|
+
/**
|
|
86
|
+
* Atomic USDT (signed) realized P&L booked from manual market-SELLs, across
|
|
87
|
+
* ALL of the wallet's positions — including ones sold to zero net shares,
|
|
88
|
+
* which never appear in `positions`. "0" when the caller did not supply it
|
|
89
|
+
* (or the backend predates the `?includeRealized=1` envelope).
|
|
90
|
+
*
|
|
91
|
+
* Report it ALONGSIDE `unrealizedPnl`, which already carries settled
|
|
92
|
+
* survivors at full-face/zero (`resolved: true`); the two together are the
|
|
93
|
+
* wallet's complete realized+unrealized P&L. It is average-cost per sell, so
|
|
94
|
+
* only the combined figure is order-invariant — never surface it standalone.
|
|
95
|
+
*/
|
|
96
|
+
realizedFromSells: string;
|
|
85
97
|
};
|
|
86
98
|
/** Options controlling how one position is valued. */
|
|
87
99
|
export type PositionPnlOptions = {
|
|
@@ -130,9 +142,13 @@ export declare function positionPnl(position: Position, opts?: PositionPnlOption
|
|
|
130
142
|
* so treat it as an upper bound on the wallet's own fee drag. */
|
|
131
143
|
export declare function feesPaidByWallet(wallet: string, trades: Trade[]): string;
|
|
132
144
|
/** Roll individual position PnLs up into a portfolio total. Pass `fees` (from
|
|
133
|
-
* `feesPaidByWallet`) to carry a fee line through; it is reported, not netted.
|
|
145
|
+
* `feesPaidByWallet`) to carry a fee line through; it is reported, not netted.
|
|
146
|
+
* Pass `realizedFromSells` (atomic USDT string, from `GET
|
|
147
|
+
* /positions/:wallet?includeRealized=1`) to carry the manual-sell realized
|
|
148
|
+
* term; likewise reported, never netted into `unrealizedPnl`. */
|
|
134
149
|
export declare function portfolioPnl(items: PositionPnl[], opts?: {
|
|
135
150
|
fees?: string;
|
|
151
|
+
realizedFromSells?: string;
|
|
136
152
|
usdtDecimals?: number;
|
|
137
153
|
}): PortfolioPnl;
|
|
138
154
|
/**
|
|
@@ -146,5 +162,6 @@ export declare function portfolioPnl(items: PositionPnl[], opts?: {
|
|
|
146
162
|
*/
|
|
147
163
|
export declare function computePortfolioPnl(positions: Position[], marketsByKey: Map<string, Pick<MarketDetail, "winner" | "orderBook">>, opts?: {
|
|
148
164
|
fees?: string;
|
|
165
|
+
realizedFromSells?: string;
|
|
149
166
|
usdtDecimals?: number;
|
|
150
167
|
}): PortfolioPnl;
|
package/dist/pnl.js
CHANGED
|
@@ -113,7 +113,10 @@ export function feesPaidByWallet(wallet, trades) {
|
|
|
113
113
|
return total.toString();
|
|
114
114
|
}
|
|
115
115
|
/** Roll individual position PnLs up into a portfolio total. Pass `fees` (from
|
|
116
|
-
* `feesPaidByWallet`) to carry a fee line through; it is reported, not netted.
|
|
116
|
+
* `feesPaidByWallet`) to carry a fee line through; it is reported, not netted.
|
|
117
|
+
* Pass `realizedFromSells` (atomic USDT string, from `GET
|
|
118
|
+
* /positions/:wallet?includeRealized=1`) to carry the manual-sell realized
|
|
119
|
+
* term; likewise reported, never netted into `unrealizedPnl`. */
|
|
117
120
|
export function portfolioPnl(items, opts = {}) {
|
|
118
121
|
const decimals = opts.usdtDecimals ?? DEFAULT_USDT_DECIMALS;
|
|
119
122
|
let costBasis = 0n;
|
|
@@ -131,6 +134,7 @@ export function portfolioPnl(items, opts = {}) {
|
|
|
131
134
|
unrealizedPnlUsdt: atomicToUsdt(unrealizedPnl, decimals),
|
|
132
135
|
roiPct: pctOf(unrealizedPnl, costBasis),
|
|
133
136
|
fees: opts.fees ?? "0",
|
|
137
|
+
realizedFromSells: opts.realizedFromSells ?? "0",
|
|
134
138
|
};
|
|
135
139
|
}
|
|
136
140
|
/**
|
package/dist/types.d.ts
CHANGED
|
@@ -140,18 +140,40 @@ export type Position = {
|
|
|
140
140
|
export type Trade = {
|
|
141
141
|
tradeId: string;
|
|
142
142
|
market: string;
|
|
143
|
+
/** The TAKER leg's option (1=UP, 2=DOWN). On a MINT/MERGE the maker leg is
|
|
144
|
+
* the opposite option. */
|
|
143
145
|
option: number;
|
|
144
146
|
buyOrderId: string;
|
|
145
147
|
sellOrderId: string;
|
|
148
|
+
/** NORMAL: the buyer. MINT/MERGE: the aggressor (taker) — a buyer on MINT,
|
|
149
|
+
* a seller on MERGE. */
|
|
146
150
|
buyer: string;
|
|
151
|
+
/** NORMAL: the seller. MINT/MERGE: the resting maker, on the OPPOSITE option
|
|
152
|
+
* to `option`. */
|
|
147
153
|
seller: string;
|
|
154
|
+
/** Basis points — the resting MAKER's pegged execution price. On a
|
|
155
|
+
* complementary fill the taker executed at the complement; render taker
|
|
156
|
+
* fills with `takerPrice`, not this. */
|
|
148
157
|
price: number;
|
|
149
158
|
amount: string;
|
|
150
159
|
platformFee: string;
|
|
151
160
|
makerFee: string;
|
|
152
161
|
settlementStatus: string;
|
|
153
162
|
createdAt: string;
|
|
163
|
+
/** Match geometry. NORMAL = same-option fill. MINT/MERGE = complementary
|
|
164
|
+
* cross (opposite-option legs). Optional so a pre-2026-07-17 backend
|
|
165
|
+
* (field absent) degrades rather than breaking a consumer. */
|
|
166
|
+
matchType?: "NORMAL" | "MINT" | "MERGE";
|
|
167
|
+
/** Basis points the taker actually executed at: `price` on NORMAL,
|
|
168
|
+
* `10000 − price` on MINT/MERGE. Prefer this over `price` when rendering a
|
|
169
|
+
* wallet's own fills. Optional for the same back-compat reason. */
|
|
170
|
+
takerPrice?: number;
|
|
154
171
|
};
|
|
172
|
+
/** The price the AGGRESSOR paid/received per share, in bps. Mirrors the
|
|
173
|
+
* backend's `takerPriceBps`: the complement on a complementary fill, else the
|
|
174
|
+
* row price. Falls back to computing the complement if a row predates the
|
|
175
|
+
* `takerPrice` field. */
|
|
176
|
+
export declare function takerPriceBps(trade: Pick<Trade, "price" | "matchType" | "takerPrice">): number;
|
|
155
177
|
export type OrderStatus = "OPEN" | "PARTIALLY_FILLED" | "FILLED" | "CANCEL_PENDING" | "CANCELLED" | string;
|
|
156
178
|
export type OrderRow = {
|
|
157
179
|
orderId: string;
|
package/dist/types.js
CHANGED
|
@@ -18,3 +18,14 @@ export const Option = {
|
|
|
18
18
|
UP: 1,
|
|
19
19
|
DOWN: 2,
|
|
20
20
|
};
|
|
21
|
+
/** The price the AGGRESSOR paid/received per share, in bps. Mirrors the
|
|
22
|
+
* backend's `takerPriceBps`: the complement on a complementary fill, else the
|
|
23
|
+
* row price. Falls back to computing the complement if a row predates the
|
|
24
|
+
* `takerPrice` field. */
|
|
25
|
+
export function takerPriceBps(trade) {
|
|
26
|
+
if (typeof trade.takerPrice === "number")
|
|
27
|
+
return trade.takerPrice;
|
|
28
|
+
return trade.matchType === "MINT" || trade.matchType === "MERGE"
|
|
29
|
+
? 10000 - trade.price
|
|
30
|
+
: trade.price;
|
|
31
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pulsepairs/sdk",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.6.0",
|
|
4
4
|
"description": "Standalone SDK for the UpDown (PulsePairs) up/down prediction markets — matcher REST/WS client, EIP-712 order signing, trade-math, and Alchemy Account Kit (smart-account) order signing for rain.trade integration.",
|
|
5
5
|
"license": "UNLICENSED",
|
|
6
6
|
"type": "module",
|
|
@@ -27,7 +27,8 @@
|
|
|
27
27
|
},
|
|
28
28
|
"files": [
|
|
29
29
|
"dist",
|
|
30
|
-
"README.md"
|
|
30
|
+
"README.md",
|
|
31
|
+
"DOCUMENTATION.md"
|
|
31
32
|
],
|
|
32
33
|
"sideEffects": false,
|
|
33
34
|
"scripts": {
|