@pear-protocol/core-sdk 1.20.1 → 2.1.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/dist/auth/index.d.ts +4 -4
- package/dist/core/index.d.ts +422 -154
- package/dist/core/index.js +61 -5
- package/dist/index.d.ts +4 -1
- package/dist/index.js +70 -14
- package/dist/types.d.ts +38 -6
- package/package.json +3 -3
package/dist/auth/index.d.ts
CHANGED
|
@@ -47,7 +47,7 @@ declare class Auth {
|
|
|
47
47
|
refreshToken: string;
|
|
48
48
|
user: {
|
|
49
49
|
id: string;
|
|
50
|
-
role: "basic" | "pro";
|
|
50
|
+
role: "basic" | "pro" | "vault";
|
|
51
51
|
providerId: string | null;
|
|
52
52
|
loginMethod: "email" | "evm_wallet" | "oauth" | "x";
|
|
53
53
|
};
|
|
@@ -77,7 +77,7 @@ declare class Auth {
|
|
|
77
77
|
refreshToken: string;
|
|
78
78
|
user: {
|
|
79
79
|
id: string;
|
|
80
|
-
role: "basic" | "pro";
|
|
80
|
+
role: "basic" | "pro" | "vault";
|
|
81
81
|
providerId: string | null;
|
|
82
82
|
loginMethod: "email" | "evm_wallet" | "oauth" | "x";
|
|
83
83
|
};
|
|
@@ -91,7 +91,7 @@ declare class Auth {
|
|
|
91
91
|
logout(headers?: ClientHeaders): Promise<void>;
|
|
92
92
|
me(headers?: ClientHeaders): Promise<{
|
|
93
93
|
id: string;
|
|
94
|
-
role: "basic" | "pro";
|
|
94
|
+
role: "basic" | "pro" | "vault";
|
|
95
95
|
providerId: string | null;
|
|
96
96
|
loginMethod: "email" | "evm_wallet" | "oauth" | "x";
|
|
97
97
|
identities: {
|
|
@@ -102,7 +102,7 @@ declare class Auth {
|
|
|
102
102
|
}>;
|
|
103
103
|
apiKeyMe(headers?: ClientHeaders): Promise<{
|
|
104
104
|
id: string;
|
|
105
|
-
role: "basic" | "pro";
|
|
105
|
+
role: "basic" | "pro" | "vault";
|
|
106
106
|
scope: "read" | "read_write";
|
|
107
107
|
authMethod: "api_key";
|
|
108
108
|
}>;
|
package/dist/core/index.d.ts
CHANGED
|
@@ -14,6 +14,7 @@ declare class Core {
|
|
|
14
14
|
id: string;
|
|
15
15
|
alias: string;
|
|
16
16
|
connector: "hyperliquid" | "binance" | "bybit" | "okx" | "lighter";
|
|
17
|
+
kind: "vault" | "eoa";
|
|
17
18
|
exchangeIdentifier: string;
|
|
18
19
|
createdAt: string;
|
|
19
20
|
updatedAt: string;
|
|
@@ -32,6 +33,7 @@ declare class Core {
|
|
|
32
33
|
id: string;
|
|
33
34
|
alias: string;
|
|
34
35
|
connector: "hyperliquid" | "binance" | "bybit" | "okx" | "lighter";
|
|
36
|
+
kind: "vault" | "eoa";
|
|
35
37
|
exchangeIdentifier: string;
|
|
36
38
|
createdAt: string;
|
|
37
39
|
updatedAt: string;
|
|
@@ -50,6 +52,7 @@ declare class Core {
|
|
|
50
52
|
id: string;
|
|
51
53
|
alias: string;
|
|
52
54
|
connector: "hyperliquid" | "binance" | "bybit" | "okx" | "lighter";
|
|
55
|
+
kind: "vault" | "eoa";
|
|
53
56
|
exchangeIdentifier: string;
|
|
54
57
|
createdAt: string;
|
|
55
58
|
updatedAt: string;
|
|
@@ -70,6 +73,7 @@ declare class Core {
|
|
|
70
73
|
id: string;
|
|
71
74
|
alias: string;
|
|
72
75
|
connector: "hyperliquid" | "binance" | "bybit" | "okx" | "lighter";
|
|
76
|
+
kind: "vault" | "eoa";
|
|
73
77
|
exchangeIdentifier: string;
|
|
74
78
|
createdAt: string;
|
|
75
79
|
updatedAt: string;
|
|
@@ -91,6 +95,7 @@ declare class Core {
|
|
|
91
95
|
id: string;
|
|
92
96
|
alias: string;
|
|
93
97
|
connector: "hyperliquid" | "binance" | "bybit" | "okx" | "lighter";
|
|
98
|
+
kind: "vault" | "eoa";
|
|
94
99
|
exchangeIdentifier: string;
|
|
95
100
|
createdAt: string;
|
|
96
101
|
updatedAt: string;
|
|
@@ -119,6 +124,7 @@ declare class Core {
|
|
|
119
124
|
id: string;
|
|
120
125
|
alias: string;
|
|
121
126
|
connector: "hyperliquid" | "binance" | "bybit" | "okx" | "lighter";
|
|
127
|
+
kind: "vault" | "eoa";
|
|
122
128
|
exchangeIdentifier: string;
|
|
123
129
|
createdAt: string;
|
|
124
130
|
updatedAt: string;
|
|
@@ -141,6 +147,7 @@ declare class Core {
|
|
|
141
147
|
id: string;
|
|
142
148
|
alias: string;
|
|
143
149
|
connector: "hyperliquid" | "binance" | "bybit" | "okx" | "lighter";
|
|
150
|
+
kind: "vault" | "eoa";
|
|
144
151
|
exchangeIdentifier: string;
|
|
145
152
|
createdAt: string;
|
|
146
153
|
updatedAt: string;
|
|
@@ -164,6 +171,7 @@ declare class Core {
|
|
|
164
171
|
id: string;
|
|
165
172
|
alias: string;
|
|
166
173
|
connector: "hyperliquid" | "binance" | "bybit" | "okx" | "lighter";
|
|
174
|
+
kind: "vault" | "eoa";
|
|
167
175
|
exchangeIdentifier: string;
|
|
168
176
|
createdAt: string;
|
|
169
177
|
updatedAt: string;
|
|
@@ -182,6 +190,69 @@ declare class Core {
|
|
|
182
190
|
};
|
|
183
191
|
}>;
|
|
184
192
|
restore: (id: string, headers?: ClientHeaders) => Promise<void>;
|
|
193
|
+
createVault: (body: HttpTypes.CreateVaultTradeAccountInput, headers?: ClientHeaders) => Promise<{
|
|
194
|
+
account: {
|
|
195
|
+
id: string;
|
|
196
|
+
alias: string;
|
|
197
|
+
connector: "hyperliquid" | "binance" | "bybit" | "okx" | "lighter";
|
|
198
|
+
kind: "vault" | "eoa";
|
|
199
|
+
exchangeIdentifier: string;
|
|
200
|
+
createdAt: string;
|
|
201
|
+
updatedAt: string;
|
|
202
|
+
metadata?: {
|
|
203
|
+
agentWalletAddress: string;
|
|
204
|
+
isSubaccount: boolean;
|
|
205
|
+
mainAccountAddress: string;
|
|
206
|
+
} | {
|
|
207
|
+
l1_address: string;
|
|
208
|
+
} | undefined;
|
|
209
|
+
deletedAt?: string | undefined;
|
|
210
|
+
};
|
|
211
|
+
}>;
|
|
212
|
+
getVaultStatus: (vaultAddress: string, headers?: ClientHeaders) => Promise<{
|
|
213
|
+
status: {
|
|
214
|
+
exists: false;
|
|
215
|
+
} | {
|
|
216
|
+
exists: true;
|
|
217
|
+
tradeAccountId: string;
|
|
218
|
+
account: {
|
|
219
|
+
id: string;
|
|
220
|
+
alias: string;
|
|
221
|
+
connector: "hyperliquid" | "binance" | "bybit" | "okx" | "lighter";
|
|
222
|
+
kind: "vault" | "eoa";
|
|
223
|
+
exchangeIdentifier: string;
|
|
224
|
+
createdAt: string;
|
|
225
|
+
updatedAt: string;
|
|
226
|
+
metadata?: {
|
|
227
|
+
agentWalletAddress: string;
|
|
228
|
+
isSubaccount: boolean;
|
|
229
|
+
mainAccountAddress: string;
|
|
230
|
+
} | {
|
|
231
|
+
l1_address: string;
|
|
232
|
+
} | undefined;
|
|
233
|
+
deletedAt?: string | undefined;
|
|
234
|
+
};
|
|
235
|
+
};
|
|
236
|
+
}>;
|
|
237
|
+
refreshVault: (vaultAddress: string, headers?: ClientHeaders) => Promise<{
|
|
238
|
+
account: {
|
|
239
|
+
id: string;
|
|
240
|
+
alias: string;
|
|
241
|
+
connector: "hyperliquid" | "binance" | "bybit" | "okx" | "lighter";
|
|
242
|
+
kind: "vault" | "eoa";
|
|
243
|
+
exchangeIdentifier: string;
|
|
244
|
+
createdAt: string;
|
|
245
|
+
updatedAt: string;
|
|
246
|
+
metadata?: {
|
|
247
|
+
agentWalletAddress: string;
|
|
248
|
+
isSubaccount: boolean;
|
|
249
|
+
mainAccountAddress: string;
|
|
250
|
+
} | {
|
|
251
|
+
l1_address: string;
|
|
252
|
+
} | undefined;
|
|
253
|
+
deletedAt?: string | undefined;
|
|
254
|
+
};
|
|
255
|
+
}>;
|
|
185
256
|
};
|
|
186
257
|
fee: {
|
|
187
258
|
get: (query?: HttpTypes.QuoteFeeParamsInput, headers?: ClientHeaders) => Promise<{
|
|
@@ -3471,16 +3542,19 @@ declare class Core {
|
|
|
3471
3542
|
}[];
|
|
3472
3543
|
}>;
|
|
3473
3544
|
/**
|
|
3474
|
-
* Closed-
|
|
3545
|
+
* Closed-position history, newest close first, composed server-side.
|
|
3475
3546
|
*
|
|
3476
|
-
* A page may hold fewer than `limit`
|
|
3547
|
+
* A page may hold fewer than `limit` positions and still return a `nextCursor` —
|
|
3477
3548
|
* page until `nextCursor` is absent, never until a page comes back short.
|
|
3549
|
+
* `includeSteps` is accepted only together with `positionId`: the timeline is
|
|
3550
|
+
* unbounded per row, so it is served one position at a time.
|
|
3478
3551
|
*/
|
|
3479
3552
|
closed: (query?: HttpTypes.ClosedPositionListParamsInput, headers?: ClientHeaders) => Promise<{
|
|
3480
3553
|
limit: number;
|
|
3481
|
-
|
|
3554
|
+
positions: {
|
|
3482
3555
|
positionId: string;
|
|
3483
3556
|
connector: "hyperliquid" | "binance" | "bybit" | "okx" | "lighter";
|
|
3557
|
+
status: "CLOSED";
|
|
3484
3558
|
openedAt: string;
|
|
3485
3559
|
closedAt: string;
|
|
3486
3560
|
origin: "PARTIAL" | "PEAR" | "EXTERNAL";
|
|
@@ -3547,180 +3621,369 @@ declare class Core {
|
|
|
3547
3621
|
}[];
|
|
3548
3622
|
nextCursor?: string | undefined;
|
|
3549
3623
|
}>;
|
|
3624
|
+
/**
|
|
3625
|
+
* Open-position history: the realized part of every open position, newest
|
|
3626
|
+
* opened first, composed server-side. Every open position yields exactly
|
|
3627
|
+
* one row — one whose fills are not visible yet comes back as an explicit
|
|
3628
|
+
* zero-state row.
|
|
3629
|
+
*
|
|
3630
|
+
* Page until `nextCursor` is absent, never until a page comes back short.
|
|
3631
|
+
*/
|
|
3632
|
+
open: (query?: HttpTypes.OpenPositionListParamsInput, headers?: ClientHeaders) => Promise<{
|
|
3633
|
+
limit: number;
|
|
3634
|
+
positions: {
|
|
3635
|
+
positionId: string;
|
|
3636
|
+
connector: "hyperliquid" | "binance" | "bybit" | "okx" | "lighter";
|
|
3637
|
+
status: "OPEN";
|
|
3638
|
+
openedAt: string;
|
|
3639
|
+
updatedAt: string;
|
|
3640
|
+
origin: "PARTIAL" | "PEAR" | "EXTERNAL";
|
|
3641
|
+
realizedGrossPnl: `-${string}` | `+${string}`;
|
|
3642
|
+
netCashflow: `-${string}` | `+${string}`;
|
|
3643
|
+
totalFees: `-${string}` | `+${string}`;
|
|
3644
|
+
tradeFees: `-${string}` | `+${string}`;
|
|
3645
|
+
pearFees: `-${string}` | `+${string}`;
|
|
3646
|
+
totalFunding: `-${string}` | `+${string}`;
|
|
3647
|
+
initialExposureUSD: Record<string, `-${string}` | `+${string}`>;
|
|
3648
|
+
hasSyntheticFills: boolean;
|
|
3649
|
+
hasProvisionalFills: boolean;
|
|
3650
|
+
unstableHistoricalData: boolean;
|
|
3651
|
+
legs: {
|
|
3652
|
+
asset: string;
|
|
3653
|
+
side: "LONG" | "SHORT";
|
|
3654
|
+
realized: {
|
|
3655
|
+
quantity: string;
|
|
3656
|
+
unpricedQuantity: string;
|
|
3657
|
+
grossPnl: `-${string}` | `+${string}`;
|
|
3658
|
+
netPnl: `-${string}` | `+${string}`;
|
|
3659
|
+
exitVwap?: string | undefined;
|
|
3660
|
+
};
|
|
3661
|
+
remaining: {
|
|
3662
|
+
quantity: `-${string}` | `+${string}`;
|
|
3663
|
+
entryVwap?: string | undefined;
|
|
3664
|
+
};
|
|
3665
|
+
totalFees: `-${string}` | `+${string}`;
|
|
3666
|
+
tradeFees: `-${string}` | `+${string}`;
|
|
3667
|
+
pearFees: `-${string}` | `+${string}`;
|
|
3668
|
+
funding: `-${string}` | `+${string}`;
|
|
3669
|
+
}[];
|
|
3670
|
+
steps?: {
|
|
3671
|
+
at: string;
|
|
3672
|
+
grossPnl: `-${string}` | `+${string}`;
|
|
3673
|
+
legs: ({
|
|
3674
|
+
kind: "INCREASE";
|
|
3675
|
+
asset: string;
|
|
3676
|
+
side: "BUY" | "SELL";
|
|
3677
|
+
quantity: string;
|
|
3678
|
+
price: string;
|
|
3679
|
+
tradeFee: `-${string}` | `+${string}`;
|
|
3680
|
+
pearFee: `-${string}` | `+${string}`;
|
|
3681
|
+
} | {
|
|
3682
|
+
kind: "REDUCE";
|
|
3683
|
+
asset: string;
|
|
3684
|
+
side: "BUY" | "SELL";
|
|
3685
|
+
quantity: string;
|
|
3686
|
+
price: string;
|
|
3687
|
+
entryBasis: string;
|
|
3688
|
+
grossPnl: `-${string}` | `+${string}`;
|
|
3689
|
+
tradeFee: `-${string}` | `+${string}`;
|
|
3690
|
+
pearFee: `-${string}` | `+${string}`;
|
|
3691
|
+
} | {
|
|
3692
|
+
kind: "REDUCE_UNPRICED";
|
|
3693
|
+
asset: string;
|
|
3694
|
+
side: "BUY" | "SELL";
|
|
3695
|
+
quantity: string;
|
|
3696
|
+
tradeFee: `-${string}` | `+${string}`;
|
|
3697
|
+
pearFee: `-${string}` | `+${string}`;
|
|
3698
|
+
})[];
|
|
3699
|
+
executionId?: string | undefined;
|
|
3700
|
+
}[] | undefined;
|
|
3701
|
+
}[];
|
|
3702
|
+
nextCursor?: string | undefined;
|
|
3703
|
+
}>;
|
|
3704
|
+
};
|
|
3705
|
+
/** Fill-level history; basket commands live under the singular `trade` namespace. */
|
|
3706
|
+
trades: {
|
|
3707
|
+
/** List fill-level trades grouped by execution with compound cursor pagination. */
|
|
3708
|
+
list: (query?: HttpTypes.TradeListParamsInput, headers?: ClientHeaders) => Promise<{
|
|
3709
|
+
limit: number;
|
|
3710
|
+
groups: {
|
|
3711
|
+
id: string;
|
|
3712
|
+
connector: "hyperliquid" | "binance" | "bybit" | "okx" | "lighter";
|
|
3713
|
+
at: string;
|
|
3714
|
+
netCashflow: `-${string}` | `+${string}`;
|
|
3715
|
+
trades: {
|
|
3716
|
+
id: string;
|
|
3717
|
+
positionId: string;
|
|
3718
|
+
symbol: string;
|
|
3719
|
+
connector: "hyperliquid" | "binance" | "bybit" | "okx" | "lighter";
|
|
3720
|
+
side: "BUY" | "SELL";
|
|
3721
|
+
quantity: string;
|
|
3722
|
+
price: string;
|
|
3723
|
+
timestamp: string;
|
|
3724
|
+
settlement: "PROVISIONAL" | "CONFIRMED";
|
|
3725
|
+
positionEffect: {
|
|
3726
|
+
kind: "OPEN";
|
|
3727
|
+
openedQuantity: string;
|
|
3728
|
+
} | {
|
|
3729
|
+
kind: "INCREASE";
|
|
3730
|
+
increasedQuantity: string;
|
|
3731
|
+
} | {
|
|
3732
|
+
kind: "REDUCE";
|
|
3733
|
+
reducedQuantity: string;
|
|
3734
|
+
realization: {
|
|
3735
|
+
kind: "PRICED";
|
|
3736
|
+
quantity: string;
|
|
3737
|
+
entryPrice: string;
|
|
3738
|
+
exitPrice: string;
|
|
3739
|
+
grossPnl: `-${string}` | `+${string}`;
|
|
3740
|
+
} | {
|
|
3741
|
+
kind: "UNPRICED";
|
|
3742
|
+
quantity: string;
|
|
3743
|
+
};
|
|
3744
|
+
} | {
|
|
3745
|
+
kind: "CLOSE";
|
|
3746
|
+
reducedQuantity: string;
|
|
3747
|
+
realization: {
|
|
3748
|
+
kind: "PRICED";
|
|
3749
|
+
quantity: string;
|
|
3750
|
+
entryPrice: string;
|
|
3751
|
+
exitPrice: string;
|
|
3752
|
+
grossPnl: `-${string}` | `+${string}`;
|
|
3753
|
+
} | {
|
|
3754
|
+
kind: "UNPRICED";
|
|
3755
|
+
quantity: string;
|
|
3756
|
+
};
|
|
3757
|
+
} | {
|
|
3758
|
+
kind: "FLIP";
|
|
3759
|
+
reducedQuantity: string;
|
|
3760
|
+
openedQuantity: string;
|
|
3761
|
+
realization: {
|
|
3762
|
+
kind: "PRICED";
|
|
3763
|
+
quantity: string;
|
|
3764
|
+
entryPrice: string;
|
|
3765
|
+
exitPrice: string;
|
|
3766
|
+
grossPnl: `-${string}` | `+${string}`;
|
|
3767
|
+
} | {
|
|
3768
|
+
kind: "UNPRICED";
|
|
3769
|
+
quantity: string;
|
|
3770
|
+
};
|
|
3771
|
+
};
|
|
3772
|
+
basisBefore: {
|
|
3773
|
+
signedQuantity: `-${string}` | `+${string}`;
|
|
3774
|
+
basis: {
|
|
3775
|
+
kind: "FLAT";
|
|
3776
|
+
} | {
|
|
3777
|
+
kind: "PRICED";
|
|
3778
|
+
entryPrice: string;
|
|
3779
|
+
} | {
|
|
3780
|
+
kind: "UNPRICED";
|
|
3781
|
+
};
|
|
3782
|
+
};
|
|
3783
|
+
basisAfter: {
|
|
3784
|
+
signedQuantity: `-${string}` | `+${string}`;
|
|
3785
|
+
basis: {
|
|
3786
|
+
kind: "FLAT";
|
|
3787
|
+
} | {
|
|
3788
|
+
kind: "PRICED";
|
|
3789
|
+
entryPrice: string;
|
|
3790
|
+
} | {
|
|
3791
|
+
kind: "UNPRICED";
|
|
3792
|
+
};
|
|
3793
|
+
};
|
|
3794
|
+
tradeFee?: `-${string}` | `+${string}` | undefined;
|
|
3795
|
+
pearFee?: `-${string}` | `+${string}` | undefined;
|
|
3796
|
+
executionId?: string | undefined;
|
|
3797
|
+
}[];
|
|
3798
|
+
executionId?: string | undefined;
|
|
3799
|
+
scheduleId?: string | undefined;
|
|
3800
|
+
triggerId?: string | undefined;
|
|
3801
|
+
}[];
|
|
3802
|
+
nextCursor?: string | undefined;
|
|
3803
|
+
}>;
|
|
3550
3804
|
};
|
|
3551
3805
|
portfolio: {
|
|
3552
3806
|
overview: (query?: HttpTypes.PortfolioQueryInput, headers?: ClientHeaders) => Promise<{
|
|
3553
|
-
|
|
3554
|
-
|
|
3555
|
-
|
|
3556
|
-
|
|
3557
|
-
|
|
3558
|
-
|
|
3559
|
-
|
|
3560
|
-
|
|
3561
|
-
|
|
3562
|
-
|
|
3563
|
-
|
|
3564
|
-
|
|
3565
|
-
|
|
3566
|
-
|
|
3567
|
-
|
|
3568
|
-
|
|
3569
|
-
|
|
3570
|
-
|
|
3571
|
-
|
|
3572
|
-
|
|
3573
|
-
|
|
3574
|
-
|
|
3575
|
-
|
|
3576
|
-
|
|
3577
|
-
|
|
3578
|
-
|
|
3579
|
-
|
|
3580
|
-
|
|
3581
|
-
|
|
3582
|
-
|
|
3583
|
-
|
|
3584
|
-
|
|
3585
|
-
|
|
3586
|
-
|
|
3587
|
-
|
|
3588
|
-
|
|
3589
|
-
|
|
3590
|
-
|
|
3591
|
-
|
|
3592
|
-
|
|
3593
|
-
|
|
3594
|
-
|
|
3595
|
-
|
|
3596
|
-
|
|
3597
|
-
|
|
3598
|
-
|
|
3599
|
-
|
|
3600
|
-
|
|
3601
|
-
|
|
3602
|
-
|
|
3603
|
-
|
|
3604
|
-
|
|
3605
|
-
|
|
3606
|
-
|
|
3607
|
-
|
|
3608
|
-
|
|
3609
|
-
|
|
3610
|
-
|
|
3611
|
-
|
|
3807
|
+
realizedCashflow: {
|
|
3808
|
+
grossPnl: number;
|
|
3809
|
+
tradeFees: number;
|
|
3810
|
+
pearFees: number;
|
|
3811
|
+
netCashflow: number;
|
|
3812
|
+
funding: number;
|
|
3813
|
+
netCashflowWithFunding: number;
|
|
3814
|
+
undeterminedQuantityByAsset: Record<string, number>;
|
|
3815
|
+
fundingSynced: boolean;
|
|
3816
|
+
intervals?: {
|
|
3817
|
+
oneDay: {
|
|
3818
|
+
grossPnl: number;
|
|
3819
|
+
tradeFees: number;
|
|
3820
|
+
pearFees: number;
|
|
3821
|
+
netCashflow: number;
|
|
3822
|
+
funding: number;
|
|
3823
|
+
netCashflowWithFunding: number;
|
|
3824
|
+
undeterminedQuantityByAsset: Record<string, number>;
|
|
3825
|
+
periodStart: string;
|
|
3826
|
+
periodEnd: string;
|
|
3827
|
+
}[];
|
|
3828
|
+
oneWeek: {
|
|
3829
|
+
grossPnl: number;
|
|
3830
|
+
tradeFees: number;
|
|
3831
|
+
pearFees: number;
|
|
3832
|
+
netCashflow: number;
|
|
3833
|
+
funding: number;
|
|
3834
|
+
netCashflowWithFunding: number;
|
|
3835
|
+
undeterminedQuantityByAsset: Record<string, number>;
|
|
3836
|
+
periodStart: string;
|
|
3837
|
+
periodEnd: string;
|
|
3838
|
+
}[];
|
|
3839
|
+
oneMonth: {
|
|
3840
|
+
grossPnl: number;
|
|
3841
|
+
tradeFees: number;
|
|
3842
|
+
pearFees: number;
|
|
3843
|
+
netCashflow: number;
|
|
3844
|
+
funding: number;
|
|
3845
|
+
netCashflowWithFunding: number;
|
|
3846
|
+
undeterminedQuantityByAsset: Record<string, number>;
|
|
3847
|
+
periodStart: string;
|
|
3848
|
+
periodEnd: string;
|
|
3849
|
+
}[];
|
|
3850
|
+
oneYear: {
|
|
3851
|
+
grossPnl: number;
|
|
3852
|
+
tradeFees: number;
|
|
3853
|
+
pearFees: number;
|
|
3854
|
+
netCashflow: number;
|
|
3855
|
+
funding: number;
|
|
3856
|
+
netCashflowWithFunding: number;
|
|
3857
|
+
undeterminedQuantityByAsset: Record<string, number>;
|
|
3858
|
+
periodStart: string;
|
|
3859
|
+
periodEnd: string;
|
|
3860
|
+
}[];
|
|
3861
|
+
all: {
|
|
3862
|
+
grossPnl: number;
|
|
3863
|
+
tradeFees: number;
|
|
3864
|
+
pearFees: number;
|
|
3865
|
+
netCashflow: number;
|
|
3866
|
+
funding: number;
|
|
3867
|
+
netCashflowWithFunding: number;
|
|
3868
|
+
undeterminedQuantityByAsset: Record<string, number>;
|
|
3869
|
+
periodStart: string;
|
|
3870
|
+
periodEnd: string;
|
|
3871
|
+
}[];
|
|
3872
|
+
} | undefined;
|
|
3873
|
+
};
|
|
3874
|
+
closedPositionStats: {
|
|
3875
|
+
totalPositions: number;
|
|
3876
|
+
wins: number;
|
|
3877
|
+
losses: number;
|
|
3878
|
+
hitRate: number | null;
|
|
3879
|
+
profitFactor: number | null;
|
|
3880
|
+
avgWinSize: number | null;
|
|
3881
|
+
avgLossSize: number | null;
|
|
3882
|
+
netPnl: number;
|
|
3883
|
+
positionPnls: number[];
|
|
3884
|
+
positionReturns: number[];
|
|
3885
|
+
};
|
|
3886
|
+
openSnapshot: {
|
|
3887
|
+
openInterest: number;
|
|
3612
3888
|
unrealizedPnl: number;
|
|
3613
|
-
|
|
3614
|
-
|
|
3615
|
-
|
|
3889
|
+
};
|
|
3890
|
+
volume: {
|
|
3891
|
+
total: number;
|
|
3892
|
+
intervals?: {
|
|
3893
|
+
oneDay: {
|
|
3894
|
+
periodStart: string;
|
|
3895
|
+
periodEnd: string;
|
|
3896
|
+
volume: number;
|
|
3897
|
+
}[];
|
|
3898
|
+
oneWeek: {
|
|
3899
|
+
periodStart: string;
|
|
3900
|
+
periodEnd: string;
|
|
3901
|
+
volume: number;
|
|
3902
|
+
}[];
|
|
3903
|
+
oneMonth: {
|
|
3904
|
+
periodStart: string;
|
|
3905
|
+
periodEnd: string;
|
|
3906
|
+
volume: number;
|
|
3907
|
+
}[];
|
|
3908
|
+
oneYear: {
|
|
3909
|
+
periodStart: string;
|
|
3910
|
+
periodEnd: string;
|
|
3911
|
+
volume: number;
|
|
3912
|
+
}[];
|
|
3913
|
+
all: {
|
|
3914
|
+
periodStart: string;
|
|
3915
|
+
periodEnd: string;
|
|
3916
|
+
volume: number;
|
|
3917
|
+
}[];
|
|
3918
|
+
} | undefined;
|
|
3616
3919
|
};
|
|
3617
3920
|
}>;
|
|
3618
3921
|
analytics: (query?: HttpTypes.PortfolioAnalyticsQueryInput, headers?: ClientHeaders) => Promise<{
|
|
3619
3922
|
config: {
|
|
3620
|
-
rollingWindowDays: number;
|
|
3621
3923
|
startDate: string;
|
|
3622
3924
|
endDate: string;
|
|
3925
|
+
};
|
|
3926
|
+
realizedCashflow: {
|
|
3927
|
+
grossPnl: number;
|
|
3928
|
+
tradeFees: number;
|
|
3929
|
+
pearFees: number;
|
|
3930
|
+
netCashflow: number;
|
|
3931
|
+
funding: number;
|
|
3932
|
+
netCashflowWithFunding: number;
|
|
3933
|
+
undeterminedQuantityByAsset: Record<string, number>;
|
|
3623
3934
|
fundingSynced: boolean;
|
|
3935
|
+
series?: {
|
|
3936
|
+
grossPnl: number;
|
|
3937
|
+
tradeFees: number;
|
|
3938
|
+
pearFees: number;
|
|
3939
|
+
netCashflow: number;
|
|
3940
|
+
funding: number;
|
|
3941
|
+
netCashflowWithFunding: number;
|
|
3942
|
+
undeterminedQuantityByAsset: Record<string, number>;
|
|
3943
|
+
periodStart: string;
|
|
3944
|
+
periodEnd: string;
|
|
3945
|
+
}[] | undefined;
|
|
3624
3946
|
};
|
|
3625
|
-
|
|
3626
|
-
|
|
3627
|
-
|
|
3628
|
-
|
|
3629
|
-
|
|
3630
|
-
profitFactor: number | null;
|
|
3631
|
-
avgWinSize: number | null;
|
|
3632
|
-
avgLossSize: number | null;
|
|
3633
|
-
avgReturnPerWin: number | null;
|
|
3634
|
-
avgReturnPerLoss: number | null;
|
|
3635
|
-
maxDrawdown: number | null;
|
|
3636
|
-
sharpeRatio: number | null;
|
|
3637
|
-
sortinoRatio: number | null;
|
|
3638
|
-
};
|
|
3639
|
-
realizedPlusUnrealized: {
|
|
3640
|
-
pnlAbsolute: number;
|
|
3641
|
-
pnlPercent: number | null;
|
|
3642
|
-
hitRate: number | null;
|
|
3643
|
-
profitFactor: number | null;
|
|
3644
|
-
avgWinSize: number | null;
|
|
3645
|
-
avgLossSize: number | null;
|
|
3646
|
-
avgReturnPerWin: number | null;
|
|
3647
|
-
avgReturnPerLoss: number | null;
|
|
3648
|
-
maxDrawdown: number | null;
|
|
3649
|
-
sharpeRatio: number | null;
|
|
3650
|
-
sortinoRatio: number | null;
|
|
3651
|
-
};
|
|
3652
|
-
realizedHitRate: number | null;
|
|
3947
|
+
closedPositionStats: {
|
|
3948
|
+
totalPositions: number;
|
|
3949
|
+
wins: number;
|
|
3950
|
+
losses: number;
|
|
3951
|
+
hitRate: number | null;
|
|
3653
3952
|
profitFactor: number | null;
|
|
3654
3953
|
avgWinSize: number | null;
|
|
3655
3954
|
avgLossSize: number | null;
|
|
3656
|
-
|
|
3657
|
-
|
|
3955
|
+
netPnl: number;
|
|
3956
|
+
positionPnls: number[];
|
|
3957
|
+
positionReturns: number[];
|
|
3658
3958
|
};
|
|
3659
|
-
|
|
3660
|
-
asset: string;
|
|
3661
|
-
realizedOnly: {
|
|
3662
|
-
pnlAbsolute: number;
|
|
3663
|
-
pnlPercent: number | null;
|
|
3664
|
-
hitRate: number | null;
|
|
3665
|
-
profitFactor: number | null;
|
|
3666
|
-
avgWinSize: number | null;
|
|
3667
|
-
avgLossSize: number | null;
|
|
3668
|
-
avgReturnPerWin: number | null;
|
|
3669
|
-
avgReturnPerLoss: number | null;
|
|
3670
|
-
maxDrawdown: number | null;
|
|
3671
|
-
sharpeRatio: number | null;
|
|
3672
|
-
sortinoRatio: number | null;
|
|
3673
|
-
};
|
|
3674
|
-
realizedPlusUnrealized: {
|
|
3675
|
-
pnlAbsolute: number;
|
|
3676
|
-
pnlPercent: number | null;
|
|
3677
|
-
hitRate: number | null;
|
|
3678
|
-
profitFactor: number | null;
|
|
3679
|
-
avgWinSize: number | null;
|
|
3680
|
-
avgLossSize: number | null;
|
|
3681
|
-
avgReturnPerWin: number | null;
|
|
3682
|
-
avgReturnPerLoss: number | null;
|
|
3683
|
-
maxDrawdown: number | null;
|
|
3684
|
-
sharpeRatio: number | null;
|
|
3685
|
-
sortinoRatio: number | null;
|
|
3686
|
-
};
|
|
3687
|
-
unrealizedReturnPerDay: number | null;
|
|
3688
|
-
}[];
|
|
3689
|
-
pairs: {
|
|
3959
|
+
pairBreakdown: {
|
|
3690
3960
|
key: string;
|
|
3691
3961
|
longAssets: string[];
|
|
3692
3962
|
shortAssets: string[];
|
|
3693
|
-
|
|
3963
|
+
positions: number;
|
|
3694
3964
|
wins: number;
|
|
3695
3965
|
losses: number;
|
|
3696
3966
|
hitRate: number | null;
|
|
3697
|
-
|
|
3698
|
-
|
|
3699
|
-
|
|
3700
|
-
|
|
3967
|
+
profitFactor: number | null;
|
|
3968
|
+
expectancy: number;
|
|
3969
|
+
grossPnl: number;
|
|
3970
|
+
tradeFees: number;
|
|
3971
|
+
pearFees: number;
|
|
3972
|
+
netPnl: number;
|
|
3701
3973
|
bookPercent: number | null;
|
|
3702
3974
|
}[];
|
|
3703
|
-
|
|
3704
|
-
|
|
3705
|
-
|
|
3706
|
-
|
|
3707
|
-
|
|
3708
|
-
|
|
3709
|
-
|
|
3710
|
-
|
|
3711
|
-
|
|
3712
|
-
|
|
3713
|
-
|
|
3714
|
-
|
|
3715
|
-
rollingWinLossRatio: number | null;
|
|
3716
|
-
dailyReturn: number | null;
|
|
3717
|
-
cumulativeReturn: number;
|
|
3718
|
-
equity: number;
|
|
3719
|
-
drawdown: number;
|
|
3720
|
-
rollingSharpe: number | null;
|
|
3721
|
-
rollingSortino: number | null;
|
|
3722
|
-
rollingVolatility: number | null;
|
|
3723
|
-
}[] | undefined;
|
|
3975
|
+
openSnapshot: {
|
|
3976
|
+
openInterest: number;
|
|
3977
|
+
unrealizedPnl: number;
|
|
3978
|
+
};
|
|
3979
|
+
volume: {
|
|
3980
|
+
total: number;
|
|
3981
|
+
series?: {
|
|
3982
|
+
periodStart: string;
|
|
3983
|
+
periodEnd: string;
|
|
3984
|
+
volume: number;
|
|
3985
|
+
}[] | undefined;
|
|
3986
|
+
};
|
|
3724
3987
|
}>;
|
|
3725
3988
|
};
|
|
3726
3989
|
prices: {
|
|
@@ -4170,6 +4433,7 @@ declare class Core {
|
|
|
4170
4433
|
createBulk: (body: HttpTypes.CreateFundingPaymentsRequest, headers?: ClientHeaders) => Promise<Record<string, never>>;
|
|
4171
4434
|
};
|
|
4172
4435
|
};
|
|
4436
|
+
/** Basket commands; executed-fill history lives under the plural `trades` namespace. */
|
|
4173
4437
|
trade: {
|
|
4174
4438
|
open: (body: HttpTypes.CreateTradeOpen, headers?: ClientHeaders) => Promise<{
|
|
4175
4439
|
execution: {
|
|
@@ -4917,6 +5181,10 @@ declare class Core {
|
|
|
4917
5181
|
})[];
|
|
4918
5182
|
}>;
|
|
4919
5183
|
setLeverage: (body: HttpTypes.SetLeverage, headers?: ClientHeaders) => Promise<Record<string, never>>;
|
|
5184
|
+
/** Add or remove margin from an isolated position without changing its size. */
|
|
5185
|
+
adjustIsolatedMargin: (body: HttpTypes.AdjustIsolatedMargin, headers?: ClientHeaders) => Promise<{
|
|
5186
|
+
adjustmentId: string;
|
|
5187
|
+
}>;
|
|
4920
5188
|
};
|
|
4921
5189
|
triggers: {
|
|
4922
5190
|
list: (query: HttpTypes.TriggerListParamsInput, headers?: ClientHeaders) => Promise<{
|
|
@@ -7195,7 +7463,7 @@ declare class Core {
|
|
|
7195
7463
|
profile: {
|
|
7196
7464
|
id: string;
|
|
7197
7465
|
displayName: string;
|
|
7198
|
-
role: "basic" | "pro";
|
|
7466
|
+
role: "basic" | "pro" | "vault";
|
|
7199
7467
|
address: string | null;
|
|
7200
7468
|
email: string | null;
|
|
7201
7469
|
emailVerified: boolean;
|
package/dist/core/index.js
CHANGED
|
@@ -61,7 +61,26 @@ class Core {
|
|
|
61
61
|
method: "POST",
|
|
62
62
|
headers
|
|
63
63
|
});
|
|
64
|
-
}, "restore")
|
|
64
|
+
}, "restore"),
|
|
65
|
+
createVault: /* @__PURE__ */ __name(async (body, headers) => {
|
|
66
|
+
return await this.client.fetch(`/trade-accounts/vault`, {
|
|
67
|
+
method: "POST",
|
|
68
|
+
headers,
|
|
69
|
+
body
|
|
70
|
+
});
|
|
71
|
+
}, "createVault"),
|
|
72
|
+
getVaultStatus: /* @__PURE__ */ __name(async (vaultAddress, headers) => {
|
|
73
|
+
return await this.client.fetch(`/trade-accounts/vault/${vaultAddress}`, {
|
|
74
|
+
method: "GET",
|
|
75
|
+
headers
|
|
76
|
+
});
|
|
77
|
+
}, "getVaultStatus"),
|
|
78
|
+
refreshVault: /* @__PURE__ */ __name(async (vaultAddress, headers) => {
|
|
79
|
+
return await this.client.fetch(`/trade-accounts/vault/${vaultAddress}/refresh`, {
|
|
80
|
+
method: "POST",
|
|
81
|
+
headers
|
|
82
|
+
});
|
|
83
|
+
}, "refreshVault")
|
|
65
84
|
};
|
|
66
85
|
fee = {
|
|
67
86
|
// Resolves the trading fee and connector fee recipient for the caller's selected trade account.
|
|
@@ -309,10 +328,12 @@ class Core {
|
|
|
309
328
|
});
|
|
310
329
|
}, "openLite"),
|
|
311
330
|
/**
|
|
312
|
-
* Closed-
|
|
331
|
+
* Closed-position history, newest close first, composed server-side.
|
|
313
332
|
*
|
|
314
|
-
* A page may hold fewer than `limit`
|
|
333
|
+
* A page may hold fewer than `limit` positions and still return a `nextCursor` —
|
|
315
334
|
* page until `nextCursor` is absent, never until a page comes back short.
|
|
335
|
+
* `includeSteps` is accepted only together with `positionId`: the timeline is
|
|
336
|
+
* unbounded per row, so it is served one position at a time.
|
|
316
337
|
*/
|
|
317
338
|
closed: /* @__PURE__ */ __name(async (query, headers) => {
|
|
318
339
|
return await this.client.fetch(`/positions/closed`, {
|
|
@@ -320,7 +341,33 @@ class Core {
|
|
|
320
341
|
headers,
|
|
321
342
|
query
|
|
322
343
|
});
|
|
323
|
-
}, "closed")
|
|
344
|
+
}, "closed"),
|
|
345
|
+
/**
|
|
346
|
+
* Open-position history: the realized part of every open position, newest
|
|
347
|
+
* opened first, composed server-side. Every open position yields exactly
|
|
348
|
+
* one row — one whose fills are not visible yet comes back as an explicit
|
|
349
|
+
* zero-state row.
|
|
350
|
+
*
|
|
351
|
+
* Page until `nextCursor` is absent, never until a page comes back short.
|
|
352
|
+
*/
|
|
353
|
+
open: /* @__PURE__ */ __name(async (query, headers) => {
|
|
354
|
+
return await this.client.fetch(`/positions/open`, {
|
|
355
|
+
method: "GET",
|
|
356
|
+
headers,
|
|
357
|
+
query
|
|
358
|
+
});
|
|
359
|
+
}, "open")
|
|
360
|
+
};
|
|
361
|
+
/** Fill-level history; basket commands live under the singular `trade` namespace. */
|
|
362
|
+
trades = {
|
|
363
|
+
/** List fill-level trades grouped by execution with compound cursor pagination. */
|
|
364
|
+
list: /* @__PURE__ */ __name(async (query, headers) => {
|
|
365
|
+
return await this.client.fetch(`/trades`, {
|
|
366
|
+
method: "GET",
|
|
367
|
+
headers,
|
|
368
|
+
query
|
|
369
|
+
});
|
|
370
|
+
}, "list")
|
|
324
371
|
};
|
|
325
372
|
portfolio = {
|
|
326
373
|
overview: /* @__PURE__ */ __name(async (query, headers) => {
|
|
@@ -560,6 +607,7 @@ class Core {
|
|
|
560
607
|
}, "createBulk")
|
|
561
608
|
}
|
|
562
609
|
};
|
|
610
|
+
/** Basket commands; executed-fill history lives under the plural `trades` namespace. */
|
|
563
611
|
trade = {
|
|
564
612
|
open: /* @__PURE__ */ __name(async (body, headers) => {
|
|
565
613
|
return await this.client.fetch(`/trade/open`, {
|
|
@@ -602,7 +650,15 @@ class Core {
|
|
|
602
650
|
headers,
|
|
603
651
|
body
|
|
604
652
|
});
|
|
605
|
-
}, "setLeverage")
|
|
653
|
+
}, "setLeverage"),
|
|
654
|
+
/** Add or remove margin from an isolated position without changing its size. */
|
|
655
|
+
adjustIsolatedMargin: /* @__PURE__ */ __name(async (body, headers) => {
|
|
656
|
+
return await this.client.fetch(`/margin`, {
|
|
657
|
+
method: "POST",
|
|
658
|
+
headers,
|
|
659
|
+
body
|
|
660
|
+
});
|
|
661
|
+
}, "adjustIsolatedMargin")
|
|
606
662
|
};
|
|
607
663
|
triggers = {
|
|
608
664
|
list: /* @__PURE__ */ __name(async (query, headers) => {
|
package/dist/index.d.ts
CHANGED
|
@@ -2,11 +2,14 @@ import { Auth } from './auth/index.js';
|
|
|
2
2
|
import { Core } from './core/index.js';
|
|
3
3
|
import { External } from './external/index.js';
|
|
4
4
|
import { SDKConfig } from './types.js';
|
|
5
|
+
export { AuthErrorContext } from './types.js';
|
|
5
6
|
export { ExternalTrigger, ExternalTriggerSource, HttpTypes, SearchTriggersParams, SearchTriggersResponse, TriggerOutcome } from '@pear-protocol/types';
|
|
6
7
|
export * from '@pear-protocol/utils';
|
|
7
8
|
export { FetchError } from './utils.js';
|
|
8
9
|
import './http.js';
|
|
9
10
|
|
|
11
|
+
/** Header that makes a request act as a Pear vault (see `SDKConfig.getVaultAddress`). */
|
|
12
|
+
declare const VAULT_ADDRESS_HEADER = "pear-vault-address";
|
|
10
13
|
declare class PearSDK {
|
|
11
14
|
auth: Auth;
|
|
12
15
|
core: Core;
|
|
@@ -14,4 +17,4 @@ declare class PearSDK {
|
|
|
14
17
|
constructor(config: SDKConfig);
|
|
15
18
|
}
|
|
16
19
|
|
|
17
|
-
export { External, PearSDK as default };
|
|
20
|
+
export { External, VAULT_ADDRESS_HEADER, PearSDK as default };
|
package/dist/index.js
CHANGED
|
@@ -10,6 +10,7 @@ export { FetchError } from './utils';
|
|
|
10
10
|
|
|
11
11
|
var __defProp = Object.defineProperty;
|
|
12
12
|
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
|
|
13
|
+
const VAULT_ADDRESS_HEADER = "pear-vault-address";
|
|
13
14
|
class PearSDK {
|
|
14
15
|
static {
|
|
15
16
|
__name(this, "PearSDK");
|
|
@@ -91,13 +92,47 @@ class PearSDK {
|
|
|
91
92
|
});
|
|
92
93
|
if (config.onAuthError) {
|
|
93
94
|
const onAuthError = config.onAuthError;
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
95
|
+
const replayed = /* @__PURE__ */ new WeakSet();
|
|
96
|
+
const recoveries = /* @__PURE__ */ new Map();
|
|
97
|
+
const recover = /* @__PURE__ */ __name((request, failedCredential) => {
|
|
98
|
+
const inFlight = recoveries.get(failedCredential);
|
|
99
|
+
if (inFlight) {
|
|
100
|
+
logger.debug("[bearer-auth] Recovery already in flight for this credential, waiting...");
|
|
101
|
+
return inFlight;
|
|
102
|
+
}
|
|
103
|
+
const context = {
|
|
104
|
+
request: request.clone(),
|
|
105
|
+
failedCredential
|
|
106
|
+
};
|
|
107
|
+
const recovery = (async () => onAuthError(context))().finally(() => {
|
|
108
|
+
if (recoveries.get(failedCredential) === recovery) {
|
|
109
|
+
recoveries.delete(failedCredential);
|
|
110
|
+
}
|
|
111
|
+
});
|
|
112
|
+
recoveries.set(failedCredential, recovery);
|
|
113
|
+
return recovery;
|
|
114
|
+
}, "recover");
|
|
115
|
+
const bearerAuthMiddleware = /* @__PURE__ */ __name(async (response, retry, request) => {
|
|
116
|
+
if (response.status !== 401) {
|
|
117
|
+
return response;
|
|
118
|
+
}
|
|
119
|
+
if (replayed.has(request)) {
|
|
120
|
+
logger.error("[bearer-auth] Replay after recovery returned 401 again, giving up");
|
|
97
121
|
throw new FetchError("Unauthorized. Token may be expired or revoked.", "Unauthorized", 401);
|
|
98
122
|
}
|
|
99
|
-
|
|
100
|
-
|
|
123
|
+
const failedCredential = readBearerCredential(request);
|
|
124
|
+
logger.warn(`[bearer-auth] 401 received for ${request.method} ${request.url}`);
|
|
125
|
+
replayed.add(request);
|
|
126
|
+
try {
|
|
127
|
+
await recover(request, failedCredential);
|
|
128
|
+
} catch (err) {
|
|
129
|
+
logger.error("[bearer-auth] Recovery rejected, not replaying:", String(err));
|
|
130
|
+
throw new FetchError("Unauthorized. Token may be expired or revoked.", "Unauthorized", 401);
|
|
131
|
+
}
|
|
132
|
+
logger.info(`[bearer-auth] Replaying ${request.method} ${request.url}`);
|
|
133
|
+
return retry();
|
|
134
|
+
}, "bearerAuthMiddleware");
|
|
135
|
+
client.useResponse(bearerAuthMiddleware);
|
|
101
136
|
}
|
|
102
137
|
}
|
|
103
138
|
if (authMode === "apikey" && config.auth?.key) {
|
|
@@ -111,19 +146,32 @@ class PearSDK {
|
|
|
111
146
|
});
|
|
112
147
|
if (config.onAuthError) {
|
|
113
148
|
const onAuthError = config.onAuthError;
|
|
114
|
-
|
|
115
|
-
if (response.status
|
|
116
|
-
|
|
117
|
-
throw new FetchError("Unauthorized. API key may be expired or revoked.", "Unauthorized", 401);
|
|
149
|
+
const apiKeyAuthMiddleware = /* @__PURE__ */ __name(async (response, _retry, request) => {
|
|
150
|
+
if (response.status !== 401) {
|
|
151
|
+
return response;
|
|
118
152
|
}
|
|
119
|
-
|
|
120
|
-
|
|
153
|
+
const notified = onAuthError({
|
|
154
|
+
request: request.clone(),
|
|
155
|
+
failedCredential: request.headers.get("x-api-key")
|
|
156
|
+
});
|
|
157
|
+
void Promise.resolve(notified).catch((err) => {
|
|
158
|
+
logger.error("[apikey-auth] onAuthError callback rejected:", String(err));
|
|
159
|
+
});
|
|
160
|
+
throw new FetchError("Unauthorized. API key may be expired or revoked.", "Unauthorized", 401);
|
|
161
|
+
}, "apiKeyAuthMiddleware");
|
|
162
|
+
client.useResponse(apiKeyAuthMiddleware);
|
|
121
163
|
}
|
|
122
164
|
}
|
|
123
|
-
if (config.getTradeAccountId) {
|
|
165
|
+
if (config.getTradeAccountId || config.getVaultAddress) {
|
|
124
166
|
const getTradeAccountId = config.getTradeAccountId;
|
|
167
|
+
const getVaultAddress = config.getVaultAddress;
|
|
125
168
|
client.useRequest(async (request, next) => {
|
|
126
|
-
const
|
|
169
|
+
const vaultAddress = getVaultAddress?.();
|
|
170
|
+
if (vaultAddress) {
|
|
171
|
+
request.headers.set(VAULT_ADDRESS_HEADER, vaultAddress);
|
|
172
|
+
return next();
|
|
173
|
+
}
|
|
174
|
+
const tradeAccountId = getTradeAccountId?.();
|
|
127
175
|
if (tradeAccountId) {
|
|
128
176
|
request.headers.set("x-trade-account-id", tradeAccountId);
|
|
129
177
|
}
|
|
@@ -142,5 +190,13 @@ function isSessionRefreshRequest(url) {
|
|
|
142
190
|
return pathname.endsWith("/auth/session/refresh") || pathname.endsWith("/auth/session/refresh/token");
|
|
143
191
|
}
|
|
144
192
|
__name(isSessionRefreshRequest, "isSessionRefreshRequest");
|
|
193
|
+
function readBearerCredential(request) {
|
|
194
|
+
const header = request.headers.get("authorization");
|
|
195
|
+
if (!header) {
|
|
196
|
+
return null;
|
|
197
|
+
}
|
|
198
|
+
return header.replace(/^Bearer\s+/i, "");
|
|
199
|
+
}
|
|
200
|
+
__name(readBearerCredential, "readBearerCredential");
|
|
145
201
|
|
|
146
|
-
export { PearSDK as default };
|
|
202
|
+
export { VAULT_ADDRESS_HEADER, PearSDK as default };
|
package/dist/types.d.ts
CHANGED
|
@@ -2,6 +2,20 @@ import { HttpTypes } from '@pear-protocol/types';
|
|
|
2
2
|
import { ProxyConfig } from '@pear-protocol/utils';
|
|
3
3
|
|
|
4
4
|
type AuthMode = 'session' | 'bearer' | 'apikey';
|
|
5
|
+
/** What received a 401, so `onAuthError` can tell whose request it was. */
|
|
6
|
+
type AuthErrorContext = {
|
|
7
|
+
/**
|
|
8
|
+
* A snapshot clone of the request that received the 401 — same method, URL, headers and
|
|
9
|
+
* body, but safe to consume: reading it never disturbs the underlying request, in
|
|
10
|
+
* bearer mode the very request the SDK is about to replay.
|
|
11
|
+
*/
|
|
12
|
+
request: Request;
|
|
13
|
+
/**
|
|
14
|
+
* The credential that request carried: the bearer token without its `Bearer ` prefix, or
|
|
15
|
+
* the `x-api-key` value. `null` when the getter supplied none.
|
|
16
|
+
*/
|
|
17
|
+
failedCredential: string | null;
|
|
18
|
+
};
|
|
5
19
|
type SDKConfig = {
|
|
6
20
|
/**
|
|
7
21
|
* API endpoint.
|
|
@@ -48,6 +62,17 @@ type SDKConfig = {
|
|
|
48
62
|
* Example: () => localStorage.getState().activeTradeAccountId
|
|
49
63
|
*/
|
|
50
64
|
getTradeAccountId?: () => string | null;
|
|
65
|
+
/**
|
|
66
|
+
* Pear vault address getter (used in both modes). When it returns an address the
|
|
67
|
+
* request carries the `pear-vault-address` header and acts as that vault: the
|
|
68
|
+
* backend authorizes the caller as the vault's owner/trader and resolves the
|
|
69
|
+
* vault's own trade account, so the trade-account header is not sent. For a
|
|
70
|
+
* one-off call without this hook, pass `{ [VAULT_ADDRESS_HEADER]: address }` as
|
|
71
|
+
* the call's headers.
|
|
72
|
+
*
|
|
73
|
+
* Example: () => useSessionStore.getState().activeVault?.address ?? null
|
|
74
|
+
*/
|
|
75
|
+
getVaultAddress?: () => string | null;
|
|
51
76
|
/**
|
|
52
77
|
* Default attribution client code (client_ids.code). When set, it is
|
|
53
78
|
* auto-added to the body of trade / trigger / schedule / rebalance requests
|
|
@@ -58,14 +83,21 @@ type SDKConfig = {
|
|
|
58
83
|
*/
|
|
59
84
|
clientId?: string | null;
|
|
60
85
|
/**
|
|
61
|
-
* Called when server returns 401 (bearer / apikey mode).
|
|
86
|
+
* Called when the server returns 401 (bearer / apikey mode). The context carries the
|
|
87
|
+
* request and credential that actually received the 401, not the getter's current value.
|
|
88
|
+
*
|
|
89
|
+
* Bearer mode awaits the callback, then replays the original request exactly once with
|
|
90
|
+
* the token the getter returns afterward; reject to refuse the replay (e.g. after an
|
|
91
|
+
* identity switch). A second 401 ends the request without calling back. Refresh through
|
|
92
|
+
* a separate transport — calling this SDK instance from the callback deadlocks. Apikey
|
|
93
|
+
* mode stays notify-only: no await, no replay.
|
|
62
94
|
*
|
|
63
|
-
* Example: () => {
|
|
64
|
-
*
|
|
65
|
-
*
|
|
95
|
+
* Example: async ({ failedCredential }) => {
|
|
96
|
+
* if (failedCredential !== activeToken()) throw new Error('identity changed');
|
|
97
|
+
* await refreshTokenViaSeparateTransport();
|
|
66
98
|
* }
|
|
67
99
|
*/
|
|
68
|
-
onAuthError?: () => void
|
|
100
|
+
onAuthError?: (context: AuthErrorContext) => void | Promise<void>;
|
|
69
101
|
/**
|
|
70
102
|
* Called when the session cannot be recovered (session mode only).
|
|
71
103
|
* Fires after a 401 when the subsequent `POST /auth/refresh` also fails.
|
|
@@ -132,4 +164,4 @@ type RequestMiddleware = (request: Request, next: () => Promise<Response>) => Pr
|
|
|
132
164
|
type ResponseMiddleware = (response: Response, retry: () => Promise<Response>, request: Request) => Promise<Response>;
|
|
133
165
|
type ClientIdBody = HttpTypes.RebalanceManual | HttpTypes.CreateSchedule | HttpTypes.CreateTradeOpen | HttpTypes.CreateTradeAdjust | HttpTypes.CreateTradeClose | HttpTypes.CreateTradeCloseAll | HttpTypes.CreateTriggerOpen | HttpTypes.CreateTriggerClose;
|
|
134
166
|
|
|
135
|
-
export type { AuthMode, ClientHeaders, ClientIdBody, FetchArgs, FetchInput, FetchParams, Logger, RequestMiddleware, ResponseMiddleware, SDKConfig };
|
|
167
|
+
export type { AuthErrorContext, AuthMode, ClientHeaders, ClientIdBody, FetchArgs, FetchInput, FetchParams, Logger, RequestMiddleware, ResponseMiddleware, SDKConfig };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pear-protocol/core-sdk",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "2.1.0",
|
|
4
4
|
"description": "Pear Protocol Core SDK",
|
|
5
5
|
"private": false,
|
|
6
6
|
"type": "module",
|
|
@@ -26,8 +26,8 @@
|
|
|
26
26
|
"typecheck": "tsc --noEmit"
|
|
27
27
|
},
|
|
28
28
|
"dependencies": {
|
|
29
|
-
"@pear-protocol/types": "^1.
|
|
30
|
-
"@pear-protocol/utils": "^0.
|
|
29
|
+
"@pear-protocol/types": "^2.1.0",
|
|
30
|
+
"@pear-protocol/utils": "^1.0.0",
|
|
31
31
|
"qs": "^6.14.0"
|
|
32
32
|
},
|
|
33
33
|
"devDependencies": {
|