@pear-protocol/core-sdk 1.20.1 → 2.0.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/core/index.d.ts +346 -153
- package/dist/core/index.js +32 -3
- package/dist/index.d.ts +1 -0
- package/dist/index.js +60 -11
- package/dist/types.d.ts +27 -6
- package/package.json +3 -3
package/dist/core/index.d.ts
CHANGED
|
@@ -3471,16 +3471,19 @@ declare class Core {
|
|
|
3471
3471
|
}[];
|
|
3472
3472
|
}>;
|
|
3473
3473
|
/**
|
|
3474
|
-
* Closed-
|
|
3474
|
+
* Closed-position history, newest close first, composed server-side.
|
|
3475
3475
|
*
|
|
3476
|
-
* A page may hold fewer than `limit`
|
|
3476
|
+
* A page may hold fewer than `limit` positions and still return a `nextCursor` —
|
|
3477
3477
|
* page until `nextCursor` is absent, never until a page comes back short.
|
|
3478
|
+
* `includeSteps` is accepted only together with `positionId`: the timeline is
|
|
3479
|
+
* unbounded per row, so it is served one position at a time.
|
|
3478
3480
|
*/
|
|
3479
3481
|
closed: (query?: HttpTypes.ClosedPositionListParamsInput, headers?: ClientHeaders) => Promise<{
|
|
3480
3482
|
limit: number;
|
|
3481
|
-
|
|
3483
|
+
positions: {
|
|
3482
3484
|
positionId: string;
|
|
3483
3485
|
connector: "hyperliquid" | "binance" | "bybit" | "okx" | "lighter";
|
|
3486
|
+
status: "CLOSED";
|
|
3484
3487
|
openedAt: string;
|
|
3485
3488
|
closedAt: string;
|
|
3486
3489
|
origin: "PARTIAL" | "PEAR" | "EXTERNAL";
|
|
@@ -3547,180 +3550,369 @@ declare class Core {
|
|
|
3547
3550
|
}[];
|
|
3548
3551
|
nextCursor?: string | undefined;
|
|
3549
3552
|
}>;
|
|
3553
|
+
/**
|
|
3554
|
+
* Open-position history: the realized part of every open position, newest
|
|
3555
|
+
* opened first, composed server-side. Every open position yields exactly
|
|
3556
|
+
* one row — one whose fills are not visible yet comes back as an explicit
|
|
3557
|
+
* zero-state row.
|
|
3558
|
+
*
|
|
3559
|
+
* Page until `nextCursor` is absent, never until a page comes back short.
|
|
3560
|
+
*/
|
|
3561
|
+
open: (query?: HttpTypes.OpenPositionListParamsInput, headers?: ClientHeaders) => Promise<{
|
|
3562
|
+
limit: number;
|
|
3563
|
+
positions: {
|
|
3564
|
+
positionId: string;
|
|
3565
|
+
connector: "hyperliquid" | "binance" | "bybit" | "okx" | "lighter";
|
|
3566
|
+
status: "OPEN";
|
|
3567
|
+
openedAt: string;
|
|
3568
|
+
updatedAt: string;
|
|
3569
|
+
origin: "PARTIAL" | "PEAR" | "EXTERNAL";
|
|
3570
|
+
realizedGrossPnl: `-${string}` | `+${string}`;
|
|
3571
|
+
netCashflow: `-${string}` | `+${string}`;
|
|
3572
|
+
totalFees: `-${string}` | `+${string}`;
|
|
3573
|
+
tradeFees: `-${string}` | `+${string}`;
|
|
3574
|
+
pearFees: `-${string}` | `+${string}`;
|
|
3575
|
+
totalFunding: `-${string}` | `+${string}`;
|
|
3576
|
+
initialExposureUSD: Record<string, `-${string}` | `+${string}`>;
|
|
3577
|
+
hasSyntheticFills: boolean;
|
|
3578
|
+
hasProvisionalFills: boolean;
|
|
3579
|
+
unstableHistoricalData: boolean;
|
|
3580
|
+
legs: {
|
|
3581
|
+
asset: string;
|
|
3582
|
+
side: "LONG" | "SHORT";
|
|
3583
|
+
realized: {
|
|
3584
|
+
quantity: string;
|
|
3585
|
+
unpricedQuantity: string;
|
|
3586
|
+
grossPnl: `-${string}` | `+${string}`;
|
|
3587
|
+
netPnl: `-${string}` | `+${string}`;
|
|
3588
|
+
exitVwap?: string | undefined;
|
|
3589
|
+
};
|
|
3590
|
+
remaining: {
|
|
3591
|
+
quantity: `-${string}` | `+${string}`;
|
|
3592
|
+
entryVwap?: string | undefined;
|
|
3593
|
+
};
|
|
3594
|
+
totalFees: `-${string}` | `+${string}`;
|
|
3595
|
+
tradeFees: `-${string}` | `+${string}`;
|
|
3596
|
+
pearFees: `-${string}` | `+${string}`;
|
|
3597
|
+
funding: `-${string}` | `+${string}`;
|
|
3598
|
+
}[];
|
|
3599
|
+
steps?: {
|
|
3600
|
+
at: string;
|
|
3601
|
+
grossPnl: `-${string}` | `+${string}`;
|
|
3602
|
+
legs: ({
|
|
3603
|
+
kind: "INCREASE";
|
|
3604
|
+
asset: string;
|
|
3605
|
+
side: "BUY" | "SELL";
|
|
3606
|
+
quantity: string;
|
|
3607
|
+
price: string;
|
|
3608
|
+
tradeFee: `-${string}` | `+${string}`;
|
|
3609
|
+
pearFee: `-${string}` | `+${string}`;
|
|
3610
|
+
} | {
|
|
3611
|
+
kind: "REDUCE";
|
|
3612
|
+
asset: string;
|
|
3613
|
+
side: "BUY" | "SELL";
|
|
3614
|
+
quantity: string;
|
|
3615
|
+
price: string;
|
|
3616
|
+
entryBasis: string;
|
|
3617
|
+
grossPnl: `-${string}` | `+${string}`;
|
|
3618
|
+
tradeFee: `-${string}` | `+${string}`;
|
|
3619
|
+
pearFee: `-${string}` | `+${string}`;
|
|
3620
|
+
} | {
|
|
3621
|
+
kind: "REDUCE_UNPRICED";
|
|
3622
|
+
asset: string;
|
|
3623
|
+
side: "BUY" | "SELL";
|
|
3624
|
+
quantity: string;
|
|
3625
|
+
tradeFee: `-${string}` | `+${string}`;
|
|
3626
|
+
pearFee: `-${string}` | `+${string}`;
|
|
3627
|
+
})[];
|
|
3628
|
+
executionId?: string | undefined;
|
|
3629
|
+
}[] | undefined;
|
|
3630
|
+
}[];
|
|
3631
|
+
nextCursor?: string | undefined;
|
|
3632
|
+
}>;
|
|
3633
|
+
};
|
|
3634
|
+
/** Fill-level history; basket commands live under the singular `trade` namespace. */
|
|
3635
|
+
trades: {
|
|
3636
|
+
/** List fill-level trades grouped by execution with compound cursor pagination. */
|
|
3637
|
+
list: (query?: HttpTypes.TradeListParamsInput, headers?: ClientHeaders) => Promise<{
|
|
3638
|
+
limit: number;
|
|
3639
|
+
groups: {
|
|
3640
|
+
id: string;
|
|
3641
|
+
connector: "hyperliquid" | "binance" | "bybit" | "okx" | "lighter";
|
|
3642
|
+
at: string;
|
|
3643
|
+
netCashflow: `-${string}` | `+${string}`;
|
|
3644
|
+
trades: {
|
|
3645
|
+
id: string;
|
|
3646
|
+
positionId: string;
|
|
3647
|
+
symbol: string;
|
|
3648
|
+
connector: "hyperliquid" | "binance" | "bybit" | "okx" | "lighter";
|
|
3649
|
+
side: "BUY" | "SELL";
|
|
3650
|
+
quantity: string;
|
|
3651
|
+
price: string;
|
|
3652
|
+
timestamp: string;
|
|
3653
|
+
settlement: "PROVISIONAL" | "CONFIRMED";
|
|
3654
|
+
positionEffect: {
|
|
3655
|
+
kind: "OPEN";
|
|
3656
|
+
openedQuantity: string;
|
|
3657
|
+
} | {
|
|
3658
|
+
kind: "INCREASE";
|
|
3659
|
+
increasedQuantity: string;
|
|
3660
|
+
} | {
|
|
3661
|
+
kind: "REDUCE";
|
|
3662
|
+
reducedQuantity: string;
|
|
3663
|
+
realization: {
|
|
3664
|
+
kind: "PRICED";
|
|
3665
|
+
quantity: string;
|
|
3666
|
+
entryPrice: string;
|
|
3667
|
+
exitPrice: string;
|
|
3668
|
+
grossPnl: `-${string}` | `+${string}`;
|
|
3669
|
+
} | {
|
|
3670
|
+
kind: "UNPRICED";
|
|
3671
|
+
quantity: string;
|
|
3672
|
+
};
|
|
3673
|
+
} | {
|
|
3674
|
+
kind: "CLOSE";
|
|
3675
|
+
reducedQuantity: string;
|
|
3676
|
+
realization: {
|
|
3677
|
+
kind: "PRICED";
|
|
3678
|
+
quantity: string;
|
|
3679
|
+
entryPrice: string;
|
|
3680
|
+
exitPrice: string;
|
|
3681
|
+
grossPnl: `-${string}` | `+${string}`;
|
|
3682
|
+
} | {
|
|
3683
|
+
kind: "UNPRICED";
|
|
3684
|
+
quantity: string;
|
|
3685
|
+
};
|
|
3686
|
+
} | {
|
|
3687
|
+
kind: "FLIP";
|
|
3688
|
+
reducedQuantity: string;
|
|
3689
|
+
openedQuantity: string;
|
|
3690
|
+
realization: {
|
|
3691
|
+
kind: "PRICED";
|
|
3692
|
+
quantity: string;
|
|
3693
|
+
entryPrice: string;
|
|
3694
|
+
exitPrice: string;
|
|
3695
|
+
grossPnl: `-${string}` | `+${string}`;
|
|
3696
|
+
} | {
|
|
3697
|
+
kind: "UNPRICED";
|
|
3698
|
+
quantity: string;
|
|
3699
|
+
};
|
|
3700
|
+
};
|
|
3701
|
+
basisBefore: {
|
|
3702
|
+
signedQuantity: `-${string}` | `+${string}`;
|
|
3703
|
+
basis: {
|
|
3704
|
+
kind: "FLAT";
|
|
3705
|
+
} | {
|
|
3706
|
+
kind: "PRICED";
|
|
3707
|
+
entryPrice: string;
|
|
3708
|
+
} | {
|
|
3709
|
+
kind: "UNPRICED";
|
|
3710
|
+
};
|
|
3711
|
+
};
|
|
3712
|
+
basisAfter: {
|
|
3713
|
+
signedQuantity: `-${string}` | `+${string}`;
|
|
3714
|
+
basis: {
|
|
3715
|
+
kind: "FLAT";
|
|
3716
|
+
} | {
|
|
3717
|
+
kind: "PRICED";
|
|
3718
|
+
entryPrice: string;
|
|
3719
|
+
} | {
|
|
3720
|
+
kind: "UNPRICED";
|
|
3721
|
+
};
|
|
3722
|
+
};
|
|
3723
|
+
tradeFee?: `-${string}` | `+${string}` | undefined;
|
|
3724
|
+
pearFee?: `-${string}` | `+${string}` | undefined;
|
|
3725
|
+
executionId?: string | undefined;
|
|
3726
|
+
}[];
|
|
3727
|
+
executionId?: string | undefined;
|
|
3728
|
+
scheduleId?: string | undefined;
|
|
3729
|
+
triggerId?: string | undefined;
|
|
3730
|
+
}[];
|
|
3731
|
+
nextCursor?: string | undefined;
|
|
3732
|
+
}>;
|
|
3550
3733
|
};
|
|
3551
3734
|
portfolio: {
|
|
3552
3735
|
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
|
-
|
|
3736
|
+
realizedCashflow: {
|
|
3737
|
+
grossPnl: number;
|
|
3738
|
+
tradeFees: number;
|
|
3739
|
+
pearFees: number;
|
|
3740
|
+
netCashflow: number;
|
|
3741
|
+
funding: number;
|
|
3742
|
+
netCashflowWithFunding: number;
|
|
3743
|
+
undeterminedQuantityByAsset: Record<string, number>;
|
|
3744
|
+
fundingSynced: boolean;
|
|
3745
|
+
intervals?: {
|
|
3746
|
+
oneDay: {
|
|
3747
|
+
grossPnl: number;
|
|
3748
|
+
tradeFees: number;
|
|
3749
|
+
pearFees: number;
|
|
3750
|
+
netCashflow: number;
|
|
3751
|
+
funding: number;
|
|
3752
|
+
netCashflowWithFunding: number;
|
|
3753
|
+
undeterminedQuantityByAsset: Record<string, number>;
|
|
3754
|
+
periodStart: string;
|
|
3755
|
+
periodEnd: string;
|
|
3756
|
+
}[];
|
|
3757
|
+
oneWeek: {
|
|
3758
|
+
grossPnl: number;
|
|
3759
|
+
tradeFees: number;
|
|
3760
|
+
pearFees: number;
|
|
3761
|
+
netCashflow: number;
|
|
3762
|
+
funding: number;
|
|
3763
|
+
netCashflowWithFunding: number;
|
|
3764
|
+
undeterminedQuantityByAsset: Record<string, number>;
|
|
3765
|
+
periodStart: string;
|
|
3766
|
+
periodEnd: string;
|
|
3767
|
+
}[];
|
|
3768
|
+
oneMonth: {
|
|
3769
|
+
grossPnl: number;
|
|
3770
|
+
tradeFees: number;
|
|
3771
|
+
pearFees: number;
|
|
3772
|
+
netCashflow: number;
|
|
3773
|
+
funding: number;
|
|
3774
|
+
netCashflowWithFunding: number;
|
|
3775
|
+
undeterminedQuantityByAsset: Record<string, number>;
|
|
3776
|
+
periodStart: string;
|
|
3777
|
+
periodEnd: string;
|
|
3778
|
+
}[];
|
|
3779
|
+
oneYear: {
|
|
3780
|
+
grossPnl: number;
|
|
3781
|
+
tradeFees: number;
|
|
3782
|
+
pearFees: number;
|
|
3783
|
+
netCashflow: number;
|
|
3784
|
+
funding: number;
|
|
3785
|
+
netCashflowWithFunding: number;
|
|
3786
|
+
undeterminedQuantityByAsset: Record<string, number>;
|
|
3787
|
+
periodStart: string;
|
|
3788
|
+
periodEnd: string;
|
|
3789
|
+
}[];
|
|
3790
|
+
all: {
|
|
3791
|
+
grossPnl: number;
|
|
3792
|
+
tradeFees: number;
|
|
3793
|
+
pearFees: number;
|
|
3794
|
+
netCashflow: number;
|
|
3795
|
+
funding: number;
|
|
3796
|
+
netCashflowWithFunding: number;
|
|
3797
|
+
undeterminedQuantityByAsset: Record<string, number>;
|
|
3798
|
+
periodStart: string;
|
|
3799
|
+
periodEnd: string;
|
|
3800
|
+
}[];
|
|
3801
|
+
} | undefined;
|
|
3802
|
+
};
|
|
3803
|
+
closedPositionStats: {
|
|
3804
|
+
totalPositions: number;
|
|
3805
|
+
wins: number;
|
|
3806
|
+
losses: number;
|
|
3807
|
+
hitRate: number | null;
|
|
3808
|
+
profitFactor: number | null;
|
|
3809
|
+
avgWinSize: number | null;
|
|
3810
|
+
avgLossSize: number | null;
|
|
3811
|
+
netPnl: number;
|
|
3812
|
+
positionPnls: number[];
|
|
3813
|
+
positionReturns: number[];
|
|
3814
|
+
};
|
|
3815
|
+
openSnapshot: {
|
|
3816
|
+
openInterest: number;
|
|
3612
3817
|
unrealizedPnl: number;
|
|
3613
|
-
|
|
3614
|
-
|
|
3615
|
-
|
|
3818
|
+
};
|
|
3819
|
+
volume: {
|
|
3820
|
+
total: number;
|
|
3821
|
+
intervals?: {
|
|
3822
|
+
oneDay: {
|
|
3823
|
+
periodStart: string;
|
|
3824
|
+
periodEnd: string;
|
|
3825
|
+
volume: number;
|
|
3826
|
+
}[];
|
|
3827
|
+
oneWeek: {
|
|
3828
|
+
periodStart: string;
|
|
3829
|
+
periodEnd: string;
|
|
3830
|
+
volume: number;
|
|
3831
|
+
}[];
|
|
3832
|
+
oneMonth: {
|
|
3833
|
+
periodStart: string;
|
|
3834
|
+
periodEnd: string;
|
|
3835
|
+
volume: number;
|
|
3836
|
+
}[];
|
|
3837
|
+
oneYear: {
|
|
3838
|
+
periodStart: string;
|
|
3839
|
+
periodEnd: string;
|
|
3840
|
+
volume: number;
|
|
3841
|
+
}[];
|
|
3842
|
+
all: {
|
|
3843
|
+
periodStart: string;
|
|
3844
|
+
periodEnd: string;
|
|
3845
|
+
volume: number;
|
|
3846
|
+
}[];
|
|
3847
|
+
} | undefined;
|
|
3616
3848
|
};
|
|
3617
3849
|
}>;
|
|
3618
3850
|
analytics: (query?: HttpTypes.PortfolioAnalyticsQueryInput, headers?: ClientHeaders) => Promise<{
|
|
3619
3851
|
config: {
|
|
3620
|
-
rollingWindowDays: number;
|
|
3621
3852
|
startDate: string;
|
|
3622
3853
|
endDate: string;
|
|
3854
|
+
};
|
|
3855
|
+
realizedCashflow: {
|
|
3856
|
+
grossPnl: number;
|
|
3857
|
+
tradeFees: number;
|
|
3858
|
+
pearFees: number;
|
|
3859
|
+
netCashflow: number;
|
|
3860
|
+
funding: number;
|
|
3861
|
+
netCashflowWithFunding: number;
|
|
3862
|
+
undeterminedQuantityByAsset: Record<string, number>;
|
|
3623
3863
|
fundingSynced: boolean;
|
|
3864
|
+
series?: {
|
|
3865
|
+
grossPnl: number;
|
|
3866
|
+
tradeFees: number;
|
|
3867
|
+
pearFees: number;
|
|
3868
|
+
netCashflow: number;
|
|
3869
|
+
funding: number;
|
|
3870
|
+
netCashflowWithFunding: number;
|
|
3871
|
+
undeterminedQuantityByAsset: Record<string, number>;
|
|
3872
|
+
periodStart: string;
|
|
3873
|
+
periodEnd: string;
|
|
3874
|
+
}[] | undefined;
|
|
3624
3875
|
};
|
|
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;
|
|
3876
|
+
closedPositionStats: {
|
|
3877
|
+
totalPositions: number;
|
|
3878
|
+
wins: number;
|
|
3879
|
+
losses: number;
|
|
3880
|
+
hitRate: number | null;
|
|
3653
3881
|
profitFactor: number | null;
|
|
3654
3882
|
avgWinSize: number | null;
|
|
3655
3883
|
avgLossSize: number | null;
|
|
3656
|
-
|
|
3657
|
-
|
|
3884
|
+
netPnl: number;
|
|
3885
|
+
positionPnls: number[];
|
|
3886
|
+
positionReturns: number[];
|
|
3658
3887
|
};
|
|
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: {
|
|
3888
|
+
pairBreakdown: {
|
|
3690
3889
|
key: string;
|
|
3691
3890
|
longAssets: string[];
|
|
3692
3891
|
shortAssets: string[];
|
|
3693
|
-
|
|
3892
|
+
positions: number;
|
|
3694
3893
|
wins: number;
|
|
3695
3894
|
losses: number;
|
|
3696
3895
|
hitRate: number | null;
|
|
3697
|
-
|
|
3698
|
-
|
|
3699
|
-
|
|
3700
|
-
|
|
3896
|
+
profitFactor: number | null;
|
|
3897
|
+
expectancy: number;
|
|
3898
|
+
grossPnl: number;
|
|
3899
|
+
tradeFees: number;
|
|
3900
|
+
pearFees: number;
|
|
3901
|
+
netPnl: number;
|
|
3701
3902
|
bookPercent: number | null;
|
|
3702
3903
|
}[];
|
|
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;
|
|
3904
|
+
openSnapshot: {
|
|
3905
|
+
openInterest: number;
|
|
3906
|
+
unrealizedPnl: number;
|
|
3907
|
+
};
|
|
3908
|
+
volume: {
|
|
3909
|
+
total: number;
|
|
3910
|
+
series?: {
|
|
3911
|
+
periodStart: string;
|
|
3912
|
+
periodEnd: string;
|
|
3913
|
+
volume: number;
|
|
3914
|
+
}[] | undefined;
|
|
3915
|
+
};
|
|
3724
3916
|
}>;
|
|
3725
3917
|
};
|
|
3726
3918
|
prices: {
|
|
@@ -4170,6 +4362,7 @@ declare class Core {
|
|
|
4170
4362
|
createBulk: (body: HttpTypes.CreateFundingPaymentsRequest, headers?: ClientHeaders) => Promise<Record<string, never>>;
|
|
4171
4363
|
};
|
|
4172
4364
|
};
|
|
4365
|
+
/** Basket commands; executed-fill history lives under the plural `trades` namespace. */
|
|
4173
4366
|
trade: {
|
|
4174
4367
|
open: (body: HttpTypes.CreateTradeOpen, headers?: ClientHeaders) => Promise<{
|
|
4175
4368
|
execution: {
|
package/dist/core/index.js
CHANGED
|
@@ -309,10 +309,12 @@ class Core {
|
|
|
309
309
|
});
|
|
310
310
|
}, "openLite"),
|
|
311
311
|
/**
|
|
312
|
-
* Closed-
|
|
312
|
+
* Closed-position history, newest close first, composed server-side.
|
|
313
313
|
*
|
|
314
|
-
* A page may hold fewer than `limit`
|
|
314
|
+
* A page may hold fewer than `limit` positions and still return a `nextCursor` —
|
|
315
315
|
* page until `nextCursor` is absent, never until a page comes back short.
|
|
316
|
+
* `includeSteps` is accepted only together with `positionId`: the timeline is
|
|
317
|
+
* unbounded per row, so it is served one position at a time.
|
|
316
318
|
*/
|
|
317
319
|
closed: /* @__PURE__ */ __name(async (query, headers) => {
|
|
318
320
|
return await this.client.fetch(`/positions/closed`, {
|
|
@@ -320,7 +322,33 @@ class Core {
|
|
|
320
322
|
headers,
|
|
321
323
|
query
|
|
322
324
|
});
|
|
323
|
-
}, "closed")
|
|
325
|
+
}, "closed"),
|
|
326
|
+
/**
|
|
327
|
+
* Open-position history: the realized part of every open position, newest
|
|
328
|
+
* opened first, composed server-side. Every open position yields exactly
|
|
329
|
+
* one row — one whose fills are not visible yet comes back as an explicit
|
|
330
|
+
* zero-state row.
|
|
331
|
+
*
|
|
332
|
+
* Page until `nextCursor` is absent, never until a page comes back short.
|
|
333
|
+
*/
|
|
334
|
+
open: /* @__PURE__ */ __name(async (query, headers) => {
|
|
335
|
+
return await this.client.fetch(`/positions/open`, {
|
|
336
|
+
method: "GET",
|
|
337
|
+
headers,
|
|
338
|
+
query
|
|
339
|
+
});
|
|
340
|
+
}, "open")
|
|
341
|
+
};
|
|
342
|
+
/** Fill-level history; basket commands live under the singular `trade` namespace. */
|
|
343
|
+
trades = {
|
|
344
|
+
/** List fill-level trades grouped by execution with compound cursor pagination. */
|
|
345
|
+
list: /* @__PURE__ */ __name(async (query, headers) => {
|
|
346
|
+
return await this.client.fetch(`/trades`, {
|
|
347
|
+
method: "GET",
|
|
348
|
+
headers,
|
|
349
|
+
query
|
|
350
|
+
});
|
|
351
|
+
}, "list")
|
|
324
352
|
};
|
|
325
353
|
portfolio = {
|
|
326
354
|
overview: /* @__PURE__ */ __name(async (query, headers) => {
|
|
@@ -560,6 +588,7 @@ class Core {
|
|
|
560
588
|
}, "createBulk")
|
|
561
589
|
}
|
|
562
590
|
};
|
|
591
|
+
/** Basket commands; executed-fill history lives under the plural `trades` namespace. */
|
|
563
592
|
trade = {
|
|
564
593
|
open: /* @__PURE__ */ __name(async (body, headers) => {
|
|
565
594
|
return await this.client.fetch(`/trade/open`, {
|
package/dist/index.d.ts
CHANGED
|
@@ -2,6 +2,7 @@ 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';
|
package/dist/index.js
CHANGED
|
@@ -91,13 +91,47 @@ class PearSDK {
|
|
|
91
91
|
});
|
|
92
92
|
if (config.onAuthError) {
|
|
93
93
|
const onAuthError = config.onAuthError;
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
94
|
+
const replayed = /* @__PURE__ */ new WeakSet();
|
|
95
|
+
const recoveries = /* @__PURE__ */ new Map();
|
|
96
|
+
const recover = /* @__PURE__ */ __name((request, failedCredential) => {
|
|
97
|
+
const inFlight = recoveries.get(failedCredential);
|
|
98
|
+
if (inFlight) {
|
|
99
|
+
logger.debug("[bearer-auth] Recovery already in flight for this credential, waiting...");
|
|
100
|
+
return inFlight;
|
|
101
|
+
}
|
|
102
|
+
const context = {
|
|
103
|
+
request: request.clone(),
|
|
104
|
+
failedCredential
|
|
105
|
+
};
|
|
106
|
+
const recovery = (async () => onAuthError(context))().finally(() => {
|
|
107
|
+
if (recoveries.get(failedCredential) === recovery) {
|
|
108
|
+
recoveries.delete(failedCredential);
|
|
109
|
+
}
|
|
110
|
+
});
|
|
111
|
+
recoveries.set(failedCredential, recovery);
|
|
112
|
+
return recovery;
|
|
113
|
+
}, "recover");
|
|
114
|
+
const bearerAuthMiddleware = /* @__PURE__ */ __name(async (response, retry, request) => {
|
|
115
|
+
if (response.status !== 401) {
|
|
116
|
+
return response;
|
|
117
|
+
}
|
|
118
|
+
if (replayed.has(request)) {
|
|
119
|
+
logger.error("[bearer-auth] Replay after recovery returned 401 again, giving up");
|
|
97
120
|
throw new FetchError("Unauthorized. Token may be expired or revoked.", "Unauthorized", 401);
|
|
98
121
|
}
|
|
99
|
-
|
|
100
|
-
|
|
122
|
+
const failedCredential = readBearerCredential(request);
|
|
123
|
+
logger.warn(`[bearer-auth] 401 received for ${request.method} ${request.url}`);
|
|
124
|
+
replayed.add(request);
|
|
125
|
+
try {
|
|
126
|
+
await recover(request, failedCredential);
|
|
127
|
+
} catch (err) {
|
|
128
|
+
logger.error("[bearer-auth] Recovery rejected, not replaying:", String(err));
|
|
129
|
+
throw new FetchError("Unauthorized. Token may be expired or revoked.", "Unauthorized", 401);
|
|
130
|
+
}
|
|
131
|
+
logger.info(`[bearer-auth] Replaying ${request.method} ${request.url}`);
|
|
132
|
+
return retry();
|
|
133
|
+
}, "bearerAuthMiddleware");
|
|
134
|
+
client.useResponse(bearerAuthMiddleware);
|
|
101
135
|
}
|
|
102
136
|
}
|
|
103
137
|
if (authMode === "apikey" && config.auth?.key) {
|
|
@@ -111,13 +145,20 @@ class PearSDK {
|
|
|
111
145
|
});
|
|
112
146
|
if (config.onAuthError) {
|
|
113
147
|
const onAuthError = config.onAuthError;
|
|
114
|
-
|
|
115
|
-
if (response.status
|
|
116
|
-
|
|
117
|
-
throw new FetchError("Unauthorized. API key may be expired or revoked.", "Unauthorized", 401);
|
|
148
|
+
const apiKeyAuthMiddleware = /* @__PURE__ */ __name(async (response, _retry, request) => {
|
|
149
|
+
if (response.status !== 401) {
|
|
150
|
+
return response;
|
|
118
151
|
}
|
|
119
|
-
|
|
120
|
-
|
|
152
|
+
const notified = onAuthError({
|
|
153
|
+
request: request.clone(),
|
|
154
|
+
failedCredential: request.headers.get("x-api-key")
|
|
155
|
+
});
|
|
156
|
+
void Promise.resolve(notified).catch((err) => {
|
|
157
|
+
logger.error("[apikey-auth] onAuthError callback rejected:", String(err));
|
|
158
|
+
});
|
|
159
|
+
throw new FetchError("Unauthorized. API key may be expired or revoked.", "Unauthorized", 401);
|
|
160
|
+
}, "apiKeyAuthMiddleware");
|
|
161
|
+
client.useResponse(apiKeyAuthMiddleware);
|
|
121
162
|
}
|
|
122
163
|
}
|
|
123
164
|
if (config.getTradeAccountId) {
|
|
@@ -142,5 +183,13 @@ function isSessionRefreshRequest(url) {
|
|
|
142
183
|
return pathname.endsWith("/auth/session/refresh") || pathname.endsWith("/auth/session/refresh/token");
|
|
143
184
|
}
|
|
144
185
|
__name(isSessionRefreshRequest, "isSessionRefreshRequest");
|
|
186
|
+
function readBearerCredential(request) {
|
|
187
|
+
const header = request.headers.get("authorization");
|
|
188
|
+
if (!header) {
|
|
189
|
+
return null;
|
|
190
|
+
}
|
|
191
|
+
return header.replace(/^Bearer\s+/i, "");
|
|
192
|
+
}
|
|
193
|
+
__name(readBearerCredential, "readBearerCredential");
|
|
145
194
|
|
|
146
195
|
export { 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.
|
|
@@ -58,14 +72,21 @@ type SDKConfig = {
|
|
|
58
72
|
*/
|
|
59
73
|
clientId?: string | null;
|
|
60
74
|
/**
|
|
61
|
-
* Called when server returns 401 (bearer / apikey mode).
|
|
75
|
+
* Called when the server returns 401 (bearer / apikey mode). The context carries the
|
|
76
|
+
* request and credential that actually received the 401, not the getter's current value.
|
|
77
|
+
*
|
|
78
|
+
* Bearer mode awaits the callback, then replays the original request exactly once with
|
|
79
|
+
* the token the getter returns afterward; reject to refuse the replay (e.g. after an
|
|
80
|
+
* identity switch). A second 401 ends the request without calling back. Refresh through
|
|
81
|
+
* a separate transport — calling this SDK instance from the callback deadlocks. Apikey
|
|
82
|
+
* mode stays notify-only: no await, no replay.
|
|
62
83
|
*
|
|
63
|
-
* Example: () => {
|
|
64
|
-
*
|
|
65
|
-
*
|
|
84
|
+
* Example: async ({ failedCredential }) => {
|
|
85
|
+
* if (failedCredential !== activeToken()) throw new Error('identity changed');
|
|
86
|
+
* await refreshTokenViaSeparateTransport();
|
|
66
87
|
* }
|
|
67
88
|
*/
|
|
68
|
-
onAuthError?: () => void
|
|
89
|
+
onAuthError?: (context: AuthErrorContext) => void | Promise<void>;
|
|
69
90
|
/**
|
|
70
91
|
* Called when the session cannot be recovered (session mode only).
|
|
71
92
|
* Fires after a 401 when the subsequent `POST /auth/refresh` also fails.
|
|
@@ -132,4 +153,4 @@ type RequestMiddleware = (request: Request, next: () => Promise<Response>) => Pr
|
|
|
132
153
|
type ResponseMiddleware = (response: Response, retry: () => Promise<Response>, request: Request) => Promise<Response>;
|
|
133
154
|
type ClientIdBody = HttpTypes.RebalanceManual | HttpTypes.CreateSchedule | HttpTypes.CreateTradeOpen | HttpTypes.CreateTradeAdjust | HttpTypes.CreateTradeClose | HttpTypes.CreateTradeCloseAll | HttpTypes.CreateTriggerOpen | HttpTypes.CreateTriggerClose;
|
|
134
155
|
|
|
135
|
-
export type { AuthMode, ClientHeaders, ClientIdBody, FetchArgs, FetchInput, FetchParams, Logger, RequestMiddleware, ResponseMiddleware, SDKConfig };
|
|
156
|
+
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": "
|
|
3
|
+
"version": "2.0.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": "^
|
|
30
|
-
"@pear-protocol/utils": "^0.
|
|
29
|
+
"@pear-protocol/types": "^2.0.0",
|
|
30
|
+
"@pear-protocol/utils": "^1.0.0",
|
|
31
31
|
"qs": "^6.14.0"
|
|
32
32
|
},
|
|
33
33
|
"devDependencies": {
|