@carrot-protocol/boost-http-client 0.3.3 → 0.4.0-stub-position-endpoints-dev-666335f
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/api/index.d.ts +14 -0
- package/dist/api/index.js +44 -0
- package/dist/api/types.d.ts +6 -0
- package/dist/api/types.js +2 -0
- package/dist/charting/bank/index.d.ts +11 -0
- package/dist/charting/bank/index.js +26 -0
- package/dist/charting/bank/types.d.ts +5 -0
- package/dist/charting/bank/types.js +2 -0
- package/dist/charting/group/index.d.ts +11 -0
- package/dist/charting/group/index.js +27 -0
- package/dist/charting/group/types.d.ts +6 -0
- package/dist/charting/group/types.js +2 -0
- package/dist/charting/position/index.d.ts +19 -0
- package/dist/charting/position/index.js +60 -0
- package/dist/charting/position/types.d.ts +19 -0
- package/dist/charting/position/types.js +2 -0
- package/dist/charting/wallet/index.d.ts +11 -0
- package/dist/charting/wallet/index.js +27 -0
- package/dist/charting/wallet/types.d.ts +6 -0
- package/dist/charting/wallet/types.js +2 -0
- package/dist/index.d.ts +9 -5
- package/dist/index.js +56 -39
- package/dist/types.d.ts +6 -0
- package/package.json +4 -4
- package/src/api/index.ts +46 -0
- package/src/api/types.ts +6 -0
- package/src/charting/bank/index.ts +35 -0
- package/src/charting/bank/types.ts +5 -0
- package/src/charting/group/index.ts +41 -0
- package/src/charting/group/types.ts +6 -0
- package/src/charting/position/index.ts +101 -0
- package/src/charting/position/types.ts +21 -0
- package/src/charting/wallet/index.ts +41 -0
- package/src/charting/wallet/types.ts +6 -0
- package/src/index.ts +69 -62
- package/src/types.ts +16 -0
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { AxiosInstance, AxiosResponse } from "axios";
|
|
2
|
+
/**
|
|
3
|
+
* Base API Client
|
|
4
|
+
*/
|
|
5
|
+
export declare class ApiClient {
|
|
6
|
+
protected readonly baseUrl: string;
|
|
7
|
+
protected readonly http: AxiosInstance;
|
|
8
|
+
/**
|
|
9
|
+
* Create a new API client
|
|
10
|
+
* @param baseUrl Base URL for the API
|
|
11
|
+
*/
|
|
12
|
+
constructor(baseUrl: string);
|
|
13
|
+
protected handleApiCall<T>(call: () => Promise<AxiosResponse<T>>): Promise<string>;
|
|
14
|
+
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.ApiClient = void 0;
|
|
7
|
+
const axios_1 = __importDefault(require("axios"));
|
|
8
|
+
/**
|
|
9
|
+
* Base API Client
|
|
10
|
+
*/
|
|
11
|
+
class ApiClient {
|
|
12
|
+
/**
|
|
13
|
+
* Create a new API client
|
|
14
|
+
* @param baseUrl Base URL for the API
|
|
15
|
+
*/
|
|
16
|
+
constructor(baseUrl) {
|
|
17
|
+
this.baseUrl = new URL(baseUrl).toString();
|
|
18
|
+
this.http = axios_1.default.create({
|
|
19
|
+
baseURL: this.baseUrl,
|
|
20
|
+
headers: {
|
|
21
|
+
"Content-Type": "application/json",
|
|
22
|
+
},
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
// Helper function to handle API calls
|
|
26
|
+
async handleApiCall(call) {
|
|
27
|
+
try {
|
|
28
|
+
const { data } = await call();
|
|
29
|
+
return JSON.stringify(data);
|
|
30
|
+
}
|
|
31
|
+
catch (e) {
|
|
32
|
+
if (axios_1.default.isAxiosError(e)) {
|
|
33
|
+
const res = e.response;
|
|
34
|
+
if (res && typeof res.data === "object") {
|
|
35
|
+
const payload = res.data;
|
|
36
|
+
throw new Error(`${payload.error}${payload.details ? ` ${payload.details}` : ""}`);
|
|
37
|
+
}
|
|
38
|
+
throw new Error(`${e.message}`);
|
|
39
|
+
}
|
|
40
|
+
throw e;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
exports.ApiClient = ApiClient;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { web3 } from "@coral-xyz/anchor";
|
|
2
|
+
import { ApyResponse } from "./types";
|
|
3
|
+
import { ApiClient } from "../../api";
|
|
4
|
+
export declare class BankChartingExtension extends ApiClient {
|
|
5
|
+
private readonly bank;
|
|
6
|
+
constructor(baseUrl: string, bank: web3.PublicKey);
|
|
7
|
+
getApy(options?: {
|
|
8
|
+
fromTime?: Date;
|
|
9
|
+
toTime?: Date;
|
|
10
|
+
}): Promise<ApyResponse[]>;
|
|
11
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.BankChartingExtension = void 0;
|
|
4
|
+
const api_1 = require("../../api");
|
|
5
|
+
class BankChartingExtension extends api_1.ApiClient {
|
|
6
|
+
constructor(baseUrl, bank) {
|
|
7
|
+
super(baseUrl);
|
|
8
|
+
this.bank = bank;
|
|
9
|
+
}
|
|
10
|
+
async getApy(options = {}) {
|
|
11
|
+
const body = await this.handleApiCall(() => this.http.get(`/bank/apys`, {
|
|
12
|
+
params: {
|
|
13
|
+
bank: this.bank.toString(),
|
|
14
|
+
fromTime: options.fromTime?.toISOString(),
|
|
15
|
+
toTime: options.toTime?.toISOString(),
|
|
16
|
+
},
|
|
17
|
+
}));
|
|
18
|
+
const response = JSON.parse(body).map((apy) => ({
|
|
19
|
+
time: new Date(apy.time),
|
|
20
|
+
assetApy: Number(apy.supply_apy),
|
|
21
|
+
liabilityApy: Number(apy.borrow_apy),
|
|
22
|
+
}));
|
|
23
|
+
return response;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
exports.BankChartingExtension = BankChartingExtension;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { web3 } from "@coral-xyz/anchor";
|
|
2
|
+
import { PerformanceResponse } from "./types";
|
|
3
|
+
import { ApiClient } from "../../api";
|
|
4
|
+
export declare class GroupChartingExtension extends ApiClient {
|
|
5
|
+
private readonly group;
|
|
6
|
+
constructor(baseUrl: string, group: web3.PublicKey);
|
|
7
|
+
getPerformance(options?: {
|
|
8
|
+
fromTime?: Date;
|
|
9
|
+
toTime?: Date;
|
|
10
|
+
}): Promise<PerformanceResponse[]>;
|
|
11
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.GroupChartingExtension = void 0;
|
|
4
|
+
const api_1 = require("../../api");
|
|
5
|
+
class GroupChartingExtension extends api_1.ApiClient {
|
|
6
|
+
constructor(baseUrl, group) {
|
|
7
|
+
super(baseUrl);
|
|
8
|
+
this.group = group;
|
|
9
|
+
}
|
|
10
|
+
async getPerformance(options = {}) {
|
|
11
|
+
const body = await this.handleApiCall(() => this.http.get(`/group/pnls`, {
|
|
12
|
+
params: {
|
|
13
|
+
group: this.group.toString(),
|
|
14
|
+
fromTime: options.fromTime?.toISOString(),
|
|
15
|
+
toTime: options.toTime?.toISOString(),
|
|
16
|
+
},
|
|
17
|
+
}));
|
|
18
|
+
const response = JSON.parse(body).map((performance) => ({
|
|
19
|
+
time: new Date(performance.time),
|
|
20
|
+
costBasis: Number(performance.cost_basis),
|
|
21
|
+
netValueValue: Number(performance.net_value_value),
|
|
22
|
+
pnlValue: Number(performance.pnl_value),
|
|
23
|
+
}));
|
|
24
|
+
return response;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
exports.GroupChartingExtension = GroupChartingExtension;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { web3 } from "@coral-xyz/anchor";
|
|
2
|
+
import { ApyResponse, LoanBalanceResponse, PerformanceResponse } from "./types";
|
|
3
|
+
import { ApiClient } from "../../api";
|
|
4
|
+
export declare class PositionChartingExtension extends ApiClient {
|
|
5
|
+
private readonly clendAccount;
|
|
6
|
+
constructor(baseUrl: string, clendAccount: web3.PublicKey);
|
|
7
|
+
getLoanBalance(options?: {
|
|
8
|
+
fromTime?: Date;
|
|
9
|
+
toTime?: Date;
|
|
10
|
+
}): Promise<LoanBalanceResponse[]>;
|
|
11
|
+
getPerformance(options?: {
|
|
12
|
+
fromTime?: Date;
|
|
13
|
+
toTime?: Date;
|
|
14
|
+
}): Promise<PerformanceResponse[]>;
|
|
15
|
+
getApy(options?: {
|
|
16
|
+
fromTime?: Date;
|
|
17
|
+
toTime?: Date;
|
|
18
|
+
}): Promise<ApyResponse[]>;
|
|
19
|
+
}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.PositionChartingExtension = void 0;
|
|
4
|
+
const api_1 = require("../../api");
|
|
5
|
+
class PositionChartingExtension extends api_1.ApiClient {
|
|
6
|
+
constructor(baseUrl, clendAccount) {
|
|
7
|
+
super(baseUrl);
|
|
8
|
+
this.clendAccount = clendAccount;
|
|
9
|
+
}
|
|
10
|
+
async getLoanBalance(options = {}) {
|
|
11
|
+
const body = await this.handleApiCall(() => this.http.get(`/account/balances`, {
|
|
12
|
+
params: {
|
|
13
|
+
account: this.clendAccount.toString(),
|
|
14
|
+
fromTime: options.fromTime?.toISOString(),
|
|
15
|
+
toTime: options.toTime?.toISOString(),
|
|
16
|
+
},
|
|
17
|
+
}));
|
|
18
|
+
const response = JSON.parse(body).map((balance) => ({
|
|
19
|
+
time: new Date(balance.time),
|
|
20
|
+
netAssetBalanceValue: Number(balance.net_asset_balance_value),
|
|
21
|
+
netLiabilityBalanceValue: Number(balance.net_liability_balance_value),
|
|
22
|
+
netValueValue: Number(balance.net_value_value),
|
|
23
|
+
notionalLeverage: Number(balance.notional_leverage),
|
|
24
|
+
}));
|
|
25
|
+
return response;
|
|
26
|
+
}
|
|
27
|
+
async getPerformance(options = {}) {
|
|
28
|
+
const body = await this.handleApiCall(() => this.http.get(`/account/performance`, {
|
|
29
|
+
params: {
|
|
30
|
+
account: this.clendAccount.toString(),
|
|
31
|
+
fromTime: options.fromTime?.toISOString(),
|
|
32
|
+
toTime: options.toTime?.toISOString(),
|
|
33
|
+
},
|
|
34
|
+
}));
|
|
35
|
+
const response = JSON.parse(body).map((performance) => ({
|
|
36
|
+
time: new Date(performance.time),
|
|
37
|
+
costBasis: Number(performance.cost_basis),
|
|
38
|
+
netValueValue: Number(performance.net_value_value),
|
|
39
|
+
pnlValue: Number(performance.pnl_value),
|
|
40
|
+
}));
|
|
41
|
+
return response;
|
|
42
|
+
}
|
|
43
|
+
async getApy(options = {}) {
|
|
44
|
+
const body = await this.handleApiCall(() => this.http.get(`/account/apys`, {
|
|
45
|
+
params: {
|
|
46
|
+
account: this.clendAccount.toString(),
|
|
47
|
+
fromTime: options.fromTime?.toISOString(),
|
|
48
|
+
toTime: options.toTime?.toISOString(),
|
|
49
|
+
},
|
|
50
|
+
}));
|
|
51
|
+
const response = JSON.parse(body).map((apy) => ({
|
|
52
|
+
time: new Date(apy.time),
|
|
53
|
+
assetApy: Number(apy.asset_apy),
|
|
54
|
+
liabilityApy: Number(apy.liability_apy),
|
|
55
|
+
netApy: Number(apy.net_apy),
|
|
56
|
+
}));
|
|
57
|
+
return response;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
exports.PositionChartingExtension = PositionChartingExtension;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
export interface LoanBalanceResponse {
|
|
2
|
+
time: Date;
|
|
3
|
+
netAssetBalanceValue: number;
|
|
4
|
+
netLiabilityBalanceValue: number;
|
|
5
|
+
netValueValue: number;
|
|
6
|
+
notionalLeverage: number;
|
|
7
|
+
}
|
|
8
|
+
export interface PerformanceResponse {
|
|
9
|
+
time: Date;
|
|
10
|
+
costBasis: number;
|
|
11
|
+
netValueValue: number;
|
|
12
|
+
pnlValue: number;
|
|
13
|
+
}
|
|
14
|
+
export interface ApyResponse {
|
|
15
|
+
time: Date;
|
|
16
|
+
assetApy: number;
|
|
17
|
+
liabilityApy: number;
|
|
18
|
+
netApy: number;
|
|
19
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { web3 } from "@coral-xyz/anchor";
|
|
2
|
+
import { PerformanceResponse } from "./types";
|
|
3
|
+
import { ApiClient } from "../../api";
|
|
4
|
+
export declare class WalletChartingExtension extends ApiClient {
|
|
5
|
+
private readonly address;
|
|
6
|
+
constructor(baseUrl: string, address: web3.PublicKey);
|
|
7
|
+
getPerformance(options?: {
|
|
8
|
+
fromTime?: Date;
|
|
9
|
+
toTime?: Date;
|
|
10
|
+
}): Promise<PerformanceResponse[]>;
|
|
11
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.WalletChartingExtension = void 0;
|
|
4
|
+
const api_1 = require("../../api");
|
|
5
|
+
class WalletChartingExtension extends api_1.ApiClient {
|
|
6
|
+
constructor(baseUrl, address) {
|
|
7
|
+
super(baseUrl);
|
|
8
|
+
this.address = address;
|
|
9
|
+
}
|
|
10
|
+
async getPerformance(options = {}) {
|
|
11
|
+
const body = await this.handleApiCall(() => this.http.get(`/user/pnls`, {
|
|
12
|
+
params: {
|
|
13
|
+
authority: this.address.toString(),
|
|
14
|
+
fromTime: options.fromTime?.toISOString(),
|
|
15
|
+
toTime: options.toTime?.toISOString(),
|
|
16
|
+
},
|
|
17
|
+
}));
|
|
18
|
+
const response = JSON.parse(body).map((performance) => ({
|
|
19
|
+
time: new Date(performance.time),
|
|
20
|
+
costBasis: Number(performance.cost_basis),
|
|
21
|
+
netValueValue: Number(performance.net_value_value),
|
|
22
|
+
pnlValue: Number(performance.pnl_value),
|
|
23
|
+
}));
|
|
24
|
+
return response;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
exports.WalletChartingExtension = WalletChartingExtension;
|
package/dist/index.d.ts
CHANGED
|
@@ -1,14 +1,17 @@
|
|
|
1
1
|
import { AnchorProvider, web3 } from "@coral-xyz/anchor";
|
|
2
|
-
import { GetBankResponse, GetUserResponse, GetGroupResponse, GetGroupsResponse, GetAccountResponse, GetAccountRequest } from "./types";
|
|
2
|
+
import { GetBankResponse, GetUserResponse, GetGroupResponse, GetUserRequest, GetGroupsResponse, GetAccountResponse, GetAccountRequest, ExtensionKey } from "./types";
|
|
3
|
+
import { ApiClient } from "./api";
|
|
4
|
+
import { PositionChartingExtension } from "./charting/position";
|
|
5
|
+
import { BankChartingExtension } from "./charting/bank";
|
|
6
|
+
import { WalletChartingExtension } from "./charting/wallet";
|
|
7
|
+
import { GroupChartingExtension } from "./charting/group";
|
|
3
8
|
export * from "./types";
|
|
4
9
|
export * from "./utils";
|
|
5
10
|
export * as Common from "@carrot-protocol/clend-common";
|
|
6
11
|
/**
|
|
7
12
|
* HTTP Client for Carrot Boost API
|
|
8
13
|
*/
|
|
9
|
-
export declare class Client {
|
|
10
|
-
private readonly baseUrl;
|
|
11
|
-
private readonly http;
|
|
14
|
+
export declare class Client extends ApiClient {
|
|
12
15
|
private readonly provider;
|
|
13
16
|
private readonly dryRun;
|
|
14
17
|
/**
|
|
@@ -32,7 +35,7 @@ export declare class Client {
|
|
|
32
35
|
*/
|
|
33
36
|
private parseClendAccountSummary;
|
|
34
37
|
private parseClendAccountWithSummary;
|
|
35
|
-
getUser(user:
|
|
38
|
+
getUser(user: GetUserRequest["user"], groups: GetUserRequest["groups"], getClendAccountSummary: GetUserRequest["getClendAccountSummary"]): Promise<GetUserResponse>;
|
|
36
39
|
/**
|
|
37
40
|
* Get all groups
|
|
38
41
|
* @param includeBankData Whether to include bank data in the response, if not strictly necessary keep false
|
|
@@ -76,4 +79,5 @@ export declare class Client {
|
|
|
76
79
|
* @returns Withdraw emissions operation result
|
|
77
80
|
*/
|
|
78
81
|
withdrawEmissions(clendAccount: web3.PublicKey): Promise<string>;
|
|
82
|
+
getExtension(extension: ExtensionKey): Promise<((clendAccount: web3.PublicKey) => PositionChartingExtension) | ((group: web3.PublicKey) => GroupChartingExtension) | ((address?: web3.PublicKey) => WalletChartingExtension) | ((bank: web3.PublicKey) => BankChartingExtension)>;
|
|
79
83
|
}
|
package/dist/index.js
CHANGED
|
@@ -40,9 +40,13 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
40
40
|
};
|
|
41
41
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
42
42
|
exports.Client = exports.Common = void 0;
|
|
43
|
-
const axios_1 = __importDefault(require("axios"));
|
|
44
43
|
const anchor_1 = require("@coral-xyz/anchor");
|
|
45
44
|
const bs58_1 = __importDefault(require("bs58"));
|
|
45
|
+
const api_1 = require("./api");
|
|
46
|
+
const position_1 = require("./charting/position");
|
|
47
|
+
const bank_1 = require("./charting/bank");
|
|
48
|
+
const wallet_1 = require("./charting/wallet");
|
|
49
|
+
const group_1 = require("./charting/group");
|
|
46
50
|
// Re-export types
|
|
47
51
|
__exportStar(require("./types"), exports);
|
|
48
52
|
__exportStar(require("./utils"), exports);
|
|
@@ -51,19 +55,13 @@ exports.Common = __importStar(require("@carrot-protocol/clend-common"));
|
|
|
51
55
|
/**
|
|
52
56
|
* HTTP Client for Carrot Boost API
|
|
53
57
|
*/
|
|
54
|
-
class Client {
|
|
58
|
+
class Client extends api_1.ApiClient {
|
|
55
59
|
/**
|
|
56
60
|
* Create a new Carrot Boost API client
|
|
57
61
|
* @param baseUrl Base URL for the API
|
|
58
62
|
*/
|
|
59
63
|
constructor(baseUrl, provider, dryRun) {
|
|
60
|
-
|
|
61
|
-
this.http = axios_1.default.create({
|
|
62
|
-
baseURL: this.baseUrl,
|
|
63
|
-
headers: {
|
|
64
|
-
"Content-Type": "application/json",
|
|
65
|
-
},
|
|
66
|
-
});
|
|
64
|
+
super(baseUrl);
|
|
67
65
|
if (!provider) {
|
|
68
66
|
provider = getDummyProvider();
|
|
69
67
|
}
|
|
@@ -95,7 +93,7 @@ class Client {
|
|
|
95
93
|
txns: [encodedAndSignedTx],
|
|
96
94
|
};
|
|
97
95
|
// send to api
|
|
98
|
-
await handleApiCall(() => this.http.post(`send`, sendRequest));
|
|
96
|
+
await this.handleApiCall(() => this.http.post(`send`, sendRequest));
|
|
99
97
|
// return txsig
|
|
100
98
|
return bs58_1.default.encode(txSig);
|
|
101
99
|
}
|
|
@@ -104,13 +102,18 @@ class Client {
|
|
|
104
102
|
* @returns Index details
|
|
105
103
|
*/
|
|
106
104
|
async index() {
|
|
107
|
-
return handleApiCall(() => this.http.get(""));
|
|
105
|
+
return this.handleApiCall(() => this.http.get(""));
|
|
108
106
|
}
|
|
109
107
|
/**
|
|
110
108
|
* Fetch and parse a single clend account by pubkey
|
|
111
109
|
*/
|
|
112
110
|
async getAccount(account, getClendAccountSummary) {
|
|
113
|
-
const body = await handleApiCall(() => this.http.get(`/account
|
|
111
|
+
const body = await this.handleApiCall(() => this.http.get(`/account`, {
|
|
112
|
+
params: {
|
|
113
|
+
account: account.toString(),
|
|
114
|
+
getClendAccountSummary,
|
|
115
|
+
},
|
|
116
|
+
}));
|
|
114
117
|
const jsonRawResponse = JSON.parse(body);
|
|
115
118
|
return this.parseClendAccountWithSummary(jsonRawResponse, getClendAccountSummary);
|
|
116
119
|
}
|
|
@@ -222,7 +225,13 @@ class Client {
|
|
|
222
225
|
}
|
|
223
226
|
async getUser(user, groups, getClendAccountSummary) {
|
|
224
227
|
// Make the API call to fetch the raw user data as a string.
|
|
225
|
-
const body = await handleApiCall(() => this.http.get(`/user
|
|
228
|
+
const body = await this.handleApiCall(() => this.http.get(`/user`, {
|
|
229
|
+
params: {
|
|
230
|
+
user: user.toString(),
|
|
231
|
+
groups: groups.map((g) => g.toString()).join(","),
|
|
232
|
+
getClendAccountSummary,
|
|
233
|
+
},
|
|
234
|
+
}));
|
|
226
235
|
// Parse the raw string body into a JSON object.
|
|
227
236
|
const jsonRawResponse = JSON.parse(body);
|
|
228
237
|
// 1. Parse Wallet Balances
|
|
@@ -251,7 +260,11 @@ class Client {
|
|
|
251
260
|
* @returns All groups
|
|
252
261
|
*/
|
|
253
262
|
async getGroups(includeBankData) {
|
|
254
|
-
const body = await handleApiCall(() => this.http.get(`/groups
|
|
263
|
+
const body = await this.handleApiCall(() => this.http.get(`/groups`, {
|
|
264
|
+
params: {
|
|
265
|
+
includeBankData,
|
|
266
|
+
},
|
|
267
|
+
}));
|
|
255
268
|
const marketJson = JSON.parse(body);
|
|
256
269
|
const groups = [];
|
|
257
270
|
for (const groupJson of marketJson.groups) {
|
|
@@ -275,7 +288,11 @@ class Client {
|
|
|
275
288
|
* @returns Group Details, which is really just all the bank data for that group
|
|
276
289
|
*/
|
|
277
290
|
async getGroup(groupAddress) {
|
|
278
|
-
const body = await handleApiCall(() => this.http.get(`/group
|
|
291
|
+
const body = await this.handleApiCall(() => this.http.get(`/group`, {
|
|
292
|
+
params: {
|
|
293
|
+
group: groupAddress.toString(),
|
|
294
|
+
},
|
|
295
|
+
}));
|
|
279
296
|
const marketJson = JSON.parse(body);
|
|
280
297
|
const group = {
|
|
281
298
|
group: new anchor_1.web3.PublicKey(marketJson.group.group),
|
|
@@ -297,7 +314,11 @@ class Client {
|
|
|
297
314
|
* @returns Bank details
|
|
298
315
|
*/
|
|
299
316
|
async getBank(bankAddress) {
|
|
300
|
-
const body = await handleApiCall(() => this.http.get(`/bank
|
|
317
|
+
const body = await this.handleApiCall(() => this.http.get(`/bank`, {
|
|
318
|
+
params: {
|
|
319
|
+
bank: bankAddress.toString(),
|
|
320
|
+
},
|
|
321
|
+
}));
|
|
301
322
|
const bankJson = JSON.parse(body);
|
|
302
323
|
const bank = parseBank(bankJson.bank);
|
|
303
324
|
const response = {
|
|
@@ -313,7 +334,7 @@ class Client {
|
|
|
313
334
|
inputTokenMint,
|
|
314
335
|
depositAmountUi: uiAmount,
|
|
315
336
|
};
|
|
316
|
-
const body = await handleApiCall(() => this.http.post("deposit", JSON.stringify(req)));
|
|
337
|
+
const body = await this.handleApiCall(() => this.http.post("deposit", JSON.stringify(req)));
|
|
317
338
|
const depositResponse = JSON.parse(body);
|
|
318
339
|
const txSig = await this.send(depositResponse.unsignedBase64Tx, depositResponse.userRequestId);
|
|
319
340
|
return txSig;
|
|
@@ -325,7 +346,7 @@ class Client {
|
|
|
325
346
|
withdrawAmountUi: uiAmount,
|
|
326
347
|
withdrawAll,
|
|
327
348
|
};
|
|
328
|
-
const body = await handleApiCall(() => this.http.post("withdraw", JSON.stringify(req)));
|
|
349
|
+
const body = await this.handleApiCall(() => this.http.post("withdraw", JSON.stringify(req)));
|
|
329
350
|
const withdrawResponse = JSON.parse(body);
|
|
330
351
|
const txSig = await this.send(withdrawResponse.unsignedBase64Tx, withdrawResponse.userRequestId);
|
|
331
352
|
return txSig;
|
|
@@ -351,7 +372,7 @@ class Client {
|
|
|
351
372
|
leverage,
|
|
352
373
|
slippageBps,
|
|
353
374
|
};
|
|
354
|
-
const body = await handleApiCall(() => this.http.post("leverage/deposit", JSON.stringify(req)));
|
|
375
|
+
const body = await this.handleApiCall(() => this.http.post("leverage/deposit", JSON.stringify(req)));
|
|
355
376
|
const depositLeverageResponse = JSON.parse(body);
|
|
356
377
|
const txSig = await this.send(depositLeverageResponse.unsignedBase64Tx, depositLeverageResponse.userRequestId);
|
|
357
378
|
return txSig;
|
|
@@ -369,7 +390,7 @@ class Client {
|
|
|
369
390
|
leverage,
|
|
370
391
|
slippageBps,
|
|
371
392
|
};
|
|
372
|
-
const body = await handleApiCall(() => this.http.post("leverage/adjust", JSON.stringify(req)));
|
|
393
|
+
const body = await this.handleApiCall(() => this.http.post("leverage/adjust", JSON.stringify(req)));
|
|
373
394
|
const adjustLeverageResponse = JSON.parse(body);
|
|
374
395
|
const txSig = await this.send(adjustLeverageResponse.unsignedBase64Tx, adjustLeverageResponse.userRequestId);
|
|
375
396
|
return txSig;
|
|
@@ -389,7 +410,7 @@ class Client {
|
|
|
389
410
|
slippageBps,
|
|
390
411
|
withdrawAll,
|
|
391
412
|
};
|
|
392
|
-
const body = await handleApiCall(() => this.http.post("leverage/withdraw", JSON.stringify(req)));
|
|
413
|
+
const body = await this.handleApiCall(() => this.http.post("leverage/withdraw", JSON.stringify(req)));
|
|
393
414
|
const withdrawLeverageResponse = JSON.parse(body);
|
|
394
415
|
const txSig = await this.send(withdrawLeverageResponse.unsignedBase64Tx, withdrawLeverageResponse.userRequestId);
|
|
395
416
|
return txSig;
|
|
@@ -402,31 +423,27 @@ class Client {
|
|
|
402
423
|
const req = {
|
|
403
424
|
clendAccount,
|
|
404
425
|
};
|
|
405
|
-
const body = await handleApiCall(() => this.http.post("emissions/withdraw", JSON.stringify(req)));
|
|
426
|
+
const body = await this.handleApiCall(() => this.http.post("emissions/withdraw", JSON.stringify(req)));
|
|
406
427
|
const withdrawEmissionsResponse = JSON.parse(body);
|
|
407
428
|
const txSig = await this.send(withdrawEmissionsResponse.unsignedBase64Tx, withdrawEmissionsResponse.userRequestId);
|
|
408
429
|
return txSig;
|
|
409
430
|
}
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
const payload = res.data;
|
|
423
|
-
throw new Error(`${payload.error}${payload.details ? ` ${payload.details}` : ""}`);
|
|
424
|
-
}
|
|
425
|
-
throw new Error(`${e.message}`);
|
|
431
|
+
async getExtension(extension) {
|
|
432
|
+
switch (extension) {
|
|
433
|
+
case "positionCharting":
|
|
434
|
+
return (clendAccount) => new position_1.PositionChartingExtension(this.baseUrl, clendAccount);
|
|
435
|
+
case "groupCharting":
|
|
436
|
+
return (group) => new group_1.GroupChartingExtension(this.baseUrl, group);
|
|
437
|
+
case "walletCharting":
|
|
438
|
+
return (address) => new wallet_1.WalletChartingExtension(this.baseUrl, address ?? this.address());
|
|
439
|
+
case "bankCharting":
|
|
440
|
+
return (bank) => new bank_1.BankChartingExtension(this.baseUrl, bank);
|
|
441
|
+
default:
|
|
442
|
+
throw new Error(`Unknown extension: ${extension}`);
|
|
426
443
|
}
|
|
427
|
-
throw e;
|
|
428
444
|
}
|
|
429
445
|
}
|
|
446
|
+
exports.Client = Client;
|
|
430
447
|
function getDummyProvider() {
|
|
431
448
|
return new anchor_1.AnchorProvider(new anchor_1.web3.Connection("http://localhost:8899"), new anchor_1.Wallet(anchor_1.web3.Keypair.generate()), {
|
|
432
449
|
skipPreflight: true,
|
package/dist/types.d.ts
CHANGED
|
@@ -1,4 +1,8 @@
|
|
|
1
1
|
import { BN, web3 } from "@coral-xyz/anchor";
|
|
2
|
+
import { PositionChartingExtension } from "./charting/position";
|
|
3
|
+
import { BankChartingExtension } from "./charting/bank";
|
|
4
|
+
import { WalletChartingExtension } from "./charting/wallet";
|
|
5
|
+
import { GroupChartingExtension } from "./charting/group";
|
|
2
6
|
export interface SendRequest {
|
|
3
7
|
userRequestId: string;
|
|
4
8
|
txns: string[];
|
|
@@ -247,3 +251,5 @@ export interface UserRequest {
|
|
|
247
251
|
openPosition: boolean | null;
|
|
248
252
|
closePosition: boolean | null;
|
|
249
253
|
}
|
|
254
|
+
export type ExtensionKey = "positionCharting" | "groupCharting" | "walletCharting" | "bankCharting";
|
|
255
|
+
export type Extension = InstanceType<typeof PositionChartingExtension> | InstanceType<typeof GroupChartingExtension> | InstanceType<typeof WalletChartingExtension> | InstanceType<typeof BankChartingExtension>;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@carrot-protocol/boost-http-client",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.0-stub-position-endpoints-dev-666335f",
|
|
4
4
|
"description": "HTTP client for Carrot Boost",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -13,8 +13,8 @@
|
|
|
13
13
|
"version-check": "current_version=$(node -p -e \"require('./package.json').version\") && if npm view @carrot-protocol/boost-http-client@$current_version > /dev/null 2>&1; then echo \"Version $current_version already exists. Please bump it in package.json\"; exit 1; fi"
|
|
14
14
|
},
|
|
15
15
|
"dependencies": {
|
|
16
|
+
"@carrot-protocol/clend-common": "^0.1.0",
|
|
16
17
|
"@coral-xyz/anchor": "^0.29.0",
|
|
17
|
-
"@carrot-protocol/clend-common": "0.1.8-group-refactor1-dev-19efede",
|
|
18
18
|
"axios": "^1.8.3",
|
|
19
19
|
"bs58": "^6.0.0",
|
|
20
20
|
"decimal.js": "^10.5.0"
|
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
"typescript": "^5.3.3"
|
|
26
26
|
},
|
|
27
27
|
"peerDependencies": {
|
|
28
|
-
"@
|
|
29
|
-
"@
|
|
28
|
+
"@carrot-protocol/clend-common": "^0.1.0",
|
|
29
|
+
"@coral-xyz/anchor": "^0.29.0"
|
|
30
30
|
}
|
|
31
31
|
}
|
package/src/api/index.ts
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import axios, { AxiosInstance, AxiosResponse } from "axios";
|
|
2
|
+
import { ApiErrorPayload } from "./types";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Base API Client
|
|
6
|
+
*/
|
|
7
|
+
export class ApiClient {
|
|
8
|
+
protected readonly baseUrl: string;
|
|
9
|
+
protected readonly http: AxiosInstance;
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Create a new API client
|
|
13
|
+
* @param baseUrl Base URL for the API
|
|
14
|
+
*/
|
|
15
|
+
constructor(baseUrl: string) {
|
|
16
|
+
this.baseUrl = new URL(baseUrl).toString();
|
|
17
|
+
this.http = axios.create({
|
|
18
|
+
baseURL: this.baseUrl,
|
|
19
|
+
headers: {
|
|
20
|
+
"Content-Type": "application/json",
|
|
21
|
+
},
|
|
22
|
+
});
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
// Helper function to handle API calls
|
|
26
|
+
protected async handleApiCall<T>(
|
|
27
|
+
call: () => Promise<AxiosResponse<T>>,
|
|
28
|
+
): Promise<string> {
|
|
29
|
+
try {
|
|
30
|
+
const { data } = await call();
|
|
31
|
+
return JSON.stringify(data);
|
|
32
|
+
} catch (e) {
|
|
33
|
+
if (axios.isAxiosError(e)) {
|
|
34
|
+
const res = e.response;
|
|
35
|
+
if (res && typeof res.data === "object") {
|
|
36
|
+
const payload = res.data as ApiErrorPayload;
|
|
37
|
+
throw new Error(
|
|
38
|
+
`${payload.error}${payload.details ? ` ${payload.details}` : ""}`,
|
|
39
|
+
);
|
|
40
|
+
}
|
|
41
|
+
throw new Error(`${e.message}`);
|
|
42
|
+
}
|
|
43
|
+
throw e;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
}
|
package/src/api/types.ts
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { web3 } from "@coral-xyz/anchor";
|
|
2
|
+
import { ApyResponse } from "./types";
|
|
3
|
+
import { ApiClient } from "../../api";
|
|
4
|
+
|
|
5
|
+
export class BankChartingExtension extends ApiClient {
|
|
6
|
+
private readonly bank: web3.PublicKey;
|
|
7
|
+
|
|
8
|
+
constructor(baseUrl: string, bank: web3.PublicKey) {
|
|
9
|
+
super(baseUrl);
|
|
10
|
+
this.bank = bank;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
public async getApy(
|
|
14
|
+
options: { fromTime?: Date; toTime?: Date } = {},
|
|
15
|
+
): Promise<ApyResponse[]> {
|
|
16
|
+
const body = await this.handleApiCall(() =>
|
|
17
|
+
this.http.get(`/bank/apys`, {
|
|
18
|
+
params: {
|
|
19
|
+
bank: this.bank.toString(),
|
|
20
|
+
fromTime: options.fromTime?.toISOString(),
|
|
21
|
+
toTime: options.toTime?.toISOString(),
|
|
22
|
+
},
|
|
23
|
+
}),
|
|
24
|
+
);
|
|
25
|
+
|
|
26
|
+
const response: ApyResponse[] = JSON.parse(body).map(
|
|
27
|
+
(apy: { time: string; supply_apy: string; borrow_apy: string }) => ({
|
|
28
|
+
time: new Date(apy.time),
|
|
29
|
+
assetApy: Number(apy.supply_apy),
|
|
30
|
+
liabilityApy: Number(apy.borrow_apy),
|
|
31
|
+
}),
|
|
32
|
+
);
|
|
33
|
+
return response;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { web3 } from "@coral-xyz/anchor";
|
|
2
|
+
import { PerformanceResponse } from "./types";
|
|
3
|
+
import { ApiClient } from "../../api";
|
|
4
|
+
|
|
5
|
+
export class GroupChartingExtension extends ApiClient {
|
|
6
|
+
private readonly group: web3.PublicKey;
|
|
7
|
+
|
|
8
|
+
constructor(baseUrl: string, group: web3.PublicKey) {
|
|
9
|
+
super(baseUrl);
|
|
10
|
+
this.group = group;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
public async getPerformance(
|
|
14
|
+
options: { fromTime?: Date; toTime?: Date } = {},
|
|
15
|
+
): Promise<PerformanceResponse[]> {
|
|
16
|
+
const body = await this.handleApiCall(() =>
|
|
17
|
+
this.http.get(`/group/pnls`, {
|
|
18
|
+
params: {
|
|
19
|
+
group: this.group.toString(),
|
|
20
|
+
fromTime: options.fromTime?.toISOString(),
|
|
21
|
+
toTime: options.toTime?.toISOString(),
|
|
22
|
+
},
|
|
23
|
+
}),
|
|
24
|
+
);
|
|
25
|
+
|
|
26
|
+
const response: PerformanceResponse[] = JSON.parse(body).map(
|
|
27
|
+
(performance: {
|
|
28
|
+
time: string;
|
|
29
|
+
cost_basis: string;
|
|
30
|
+
net_value_value: string;
|
|
31
|
+
pnl_value: string;
|
|
32
|
+
}) => ({
|
|
33
|
+
time: new Date(performance.time),
|
|
34
|
+
costBasis: Number(performance.cost_basis),
|
|
35
|
+
netValueValue: Number(performance.net_value_value),
|
|
36
|
+
pnlValue: Number(performance.pnl_value),
|
|
37
|
+
}),
|
|
38
|
+
);
|
|
39
|
+
return response;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import { web3 } from "@coral-xyz/anchor";
|
|
2
|
+
import { ApyResponse, LoanBalanceResponse, PerformanceResponse } from "./types";
|
|
3
|
+
import { ApiClient } from "../../api";
|
|
4
|
+
|
|
5
|
+
export class PositionChartingExtension extends ApiClient {
|
|
6
|
+
private readonly clendAccount: web3.PublicKey;
|
|
7
|
+
|
|
8
|
+
constructor(baseUrl: string, clendAccount: web3.PublicKey) {
|
|
9
|
+
super(baseUrl);
|
|
10
|
+
this.clendAccount = clendAccount;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
public async getLoanBalance(
|
|
14
|
+
options: { fromTime?: Date; toTime?: Date } = {},
|
|
15
|
+
): Promise<LoanBalanceResponse[]> {
|
|
16
|
+
const body = await this.handleApiCall(() =>
|
|
17
|
+
this.http.get(`/account/balances`, {
|
|
18
|
+
params: {
|
|
19
|
+
account: this.clendAccount.toString(),
|
|
20
|
+
fromTime: options.fromTime?.toISOString(),
|
|
21
|
+
toTime: options.toTime?.toISOString(),
|
|
22
|
+
},
|
|
23
|
+
}),
|
|
24
|
+
);
|
|
25
|
+
|
|
26
|
+
const response: LoanBalanceResponse[] = JSON.parse(body).map(
|
|
27
|
+
(balance: {
|
|
28
|
+
time: string;
|
|
29
|
+
net_asset_balance_value: string;
|
|
30
|
+
net_liability_balance_value: string;
|
|
31
|
+
net_value_value: string;
|
|
32
|
+
notional_leverage: string;
|
|
33
|
+
}) => ({
|
|
34
|
+
time: new Date(balance.time),
|
|
35
|
+
netAssetBalanceValue: Number(balance.net_asset_balance_value),
|
|
36
|
+
netLiabilityBalanceValue: Number(balance.net_liability_balance_value),
|
|
37
|
+
netValueValue: Number(balance.net_value_value),
|
|
38
|
+
notionalLeverage: Number(balance.notional_leverage),
|
|
39
|
+
}),
|
|
40
|
+
);
|
|
41
|
+
return response;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
public async getPerformance(
|
|
45
|
+
options: { fromTime?: Date; toTime?: Date } = {},
|
|
46
|
+
): Promise<PerformanceResponse[]> {
|
|
47
|
+
const body = await this.handleApiCall(() =>
|
|
48
|
+
this.http.get(`/account/performance`, {
|
|
49
|
+
params: {
|
|
50
|
+
account: this.clendAccount.toString(),
|
|
51
|
+
fromTime: options.fromTime?.toISOString(),
|
|
52
|
+
toTime: options.toTime?.toISOString(),
|
|
53
|
+
},
|
|
54
|
+
}),
|
|
55
|
+
);
|
|
56
|
+
|
|
57
|
+
const response: PerformanceResponse[] = JSON.parse(body).map(
|
|
58
|
+
(performance: {
|
|
59
|
+
time: string;
|
|
60
|
+
cost_basis: string;
|
|
61
|
+
net_value_value: string;
|
|
62
|
+
pnl_value: string;
|
|
63
|
+
}) => ({
|
|
64
|
+
time: new Date(performance.time),
|
|
65
|
+
costBasis: Number(performance.cost_basis),
|
|
66
|
+
netValueValue: Number(performance.net_value_value),
|
|
67
|
+
pnlValue: Number(performance.pnl_value),
|
|
68
|
+
}),
|
|
69
|
+
);
|
|
70
|
+
return response;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
public async getApy(
|
|
74
|
+
options: { fromTime?: Date; toTime?: Date } = {},
|
|
75
|
+
): Promise<ApyResponse[]> {
|
|
76
|
+
const body = await this.handleApiCall(() =>
|
|
77
|
+
this.http.get(`/account/apys`, {
|
|
78
|
+
params: {
|
|
79
|
+
account: this.clendAccount.toString(),
|
|
80
|
+
fromTime: options.fromTime?.toISOString(),
|
|
81
|
+
toTime: options.toTime?.toISOString(),
|
|
82
|
+
},
|
|
83
|
+
}),
|
|
84
|
+
);
|
|
85
|
+
|
|
86
|
+
const response: ApyResponse[] = JSON.parse(body).map(
|
|
87
|
+
(apy: {
|
|
88
|
+
time: string;
|
|
89
|
+
asset_apy: string;
|
|
90
|
+
liability_apy: string;
|
|
91
|
+
net_apy: string;
|
|
92
|
+
}) => ({
|
|
93
|
+
time: new Date(apy.time),
|
|
94
|
+
assetApy: Number(apy.asset_apy),
|
|
95
|
+
liabilityApy: Number(apy.liability_apy),
|
|
96
|
+
netApy: Number(apy.net_apy),
|
|
97
|
+
}),
|
|
98
|
+
);
|
|
99
|
+
return response;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
export interface LoanBalanceResponse {
|
|
2
|
+
time: Date;
|
|
3
|
+
netAssetBalanceValue: number;
|
|
4
|
+
netLiabilityBalanceValue: number;
|
|
5
|
+
netValueValue: number;
|
|
6
|
+
notionalLeverage: number;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export interface PerformanceResponse {
|
|
10
|
+
time: Date;
|
|
11
|
+
costBasis: number;
|
|
12
|
+
netValueValue: number;
|
|
13
|
+
pnlValue: number;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export interface ApyResponse {
|
|
17
|
+
time: Date;
|
|
18
|
+
assetApy: number;
|
|
19
|
+
liabilityApy: number;
|
|
20
|
+
netApy: number;
|
|
21
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { web3 } from "@coral-xyz/anchor";
|
|
2
|
+
import { PerformanceResponse } from "./types";
|
|
3
|
+
import { ApiClient } from "../../api";
|
|
4
|
+
|
|
5
|
+
export class WalletChartingExtension extends ApiClient {
|
|
6
|
+
private readonly address: web3.PublicKey;
|
|
7
|
+
|
|
8
|
+
constructor(baseUrl: string, address: web3.PublicKey) {
|
|
9
|
+
super(baseUrl);
|
|
10
|
+
this.address = address;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
public async getPerformance(
|
|
14
|
+
options: { fromTime?: Date; toTime?: Date } = {},
|
|
15
|
+
): Promise<PerformanceResponse[]> {
|
|
16
|
+
const body = await this.handleApiCall(() =>
|
|
17
|
+
this.http.get(`/user/pnls`, {
|
|
18
|
+
params: {
|
|
19
|
+
authority: this.address.toString(),
|
|
20
|
+
fromTime: options.fromTime?.toISOString(),
|
|
21
|
+
toTime: options.toTime?.toISOString(),
|
|
22
|
+
},
|
|
23
|
+
}),
|
|
24
|
+
);
|
|
25
|
+
|
|
26
|
+
const response: PerformanceResponse[] = JSON.parse(body).map(
|
|
27
|
+
(performance: {
|
|
28
|
+
time: string;
|
|
29
|
+
cost_basis: string;
|
|
30
|
+
net_value_value: string;
|
|
31
|
+
pnl_value: string;
|
|
32
|
+
}) => ({
|
|
33
|
+
time: new Date(performance.time),
|
|
34
|
+
costBasis: Number(performance.cost_basis),
|
|
35
|
+
netValueValue: Number(performance.net_value_value),
|
|
36
|
+
pnlValue: Number(performance.pnl_value),
|
|
37
|
+
}),
|
|
38
|
+
);
|
|
39
|
+
return response;
|
|
40
|
+
}
|
|
41
|
+
}
|
package/src/index.ts
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import axios, { AxiosInstance, AxiosError, AxiosResponse } from "axios";
|
|
2
1
|
import { AnchorProvider, BN, Wallet, web3 } from "@coral-xyz/anchor";
|
|
3
2
|
import {
|
|
4
3
|
DepositLeverageRequest,
|
|
@@ -33,8 +32,15 @@ import {
|
|
|
33
32
|
WithdrawResponse,
|
|
34
33
|
GetAccountResponse,
|
|
35
34
|
GetAccountRequest,
|
|
35
|
+
ExtensionKey,
|
|
36
|
+
Extension,
|
|
36
37
|
} from "./types";
|
|
37
38
|
import encode from "bs58";
|
|
39
|
+
import { ApiClient } from "./api";
|
|
40
|
+
import { PositionChartingExtension } from "./charting/position";
|
|
41
|
+
import { BankChartingExtension } from "./charting/bank";
|
|
42
|
+
import { WalletChartingExtension } from "./charting/wallet";
|
|
43
|
+
import { GroupChartingExtension } from "./charting/group";
|
|
38
44
|
|
|
39
45
|
// Re-export types
|
|
40
46
|
export * from "./types";
|
|
@@ -46,9 +52,7 @@ export * as Common from "@carrot-protocol/clend-common";
|
|
|
46
52
|
/**
|
|
47
53
|
* HTTP Client for Carrot Boost API
|
|
48
54
|
*/
|
|
49
|
-
export class Client {
|
|
50
|
-
private readonly baseUrl: string;
|
|
51
|
-
private readonly http: AxiosInstance;
|
|
55
|
+
export class Client extends ApiClient {
|
|
52
56
|
private readonly provider: AnchorProvider;
|
|
53
57
|
private readonly dryRun: boolean;
|
|
54
58
|
|
|
@@ -57,13 +61,7 @@ export class Client {
|
|
|
57
61
|
* @param baseUrl Base URL for the API
|
|
58
62
|
*/
|
|
59
63
|
constructor(baseUrl: string, provider?: AnchorProvider, dryRun?: boolean) {
|
|
60
|
-
|
|
61
|
-
this.http = axios.create({
|
|
62
|
-
baseURL: this.baseUrl,
|
|
63
|
-
headers: {
|
|
64
|
-
"Content-Type": "application/json",
|
|
65
|
-
},
|
|
66
|
-
});
|
|
64
|
+
super(baseUrl);
|
|
67
65
|
if (!provider) {
|
|
68
66
|
provider = getDummyProvider();
|
|
69
67
|
}
|
|
@@ -107,7 +105,7 @@ export class Client {
|
|
|
107
105
|
};
|
|
108
106
|
|
|
109
107
|
// send to api
|
|
110
|
-
await handleApiCall(() => this.http.post(`send`, sendRequest));
|
|
108
|
+
await this.handleApiCall(() => this.http.post(`send`, sendRequest));
|
|
111
109
|
|
|
112
110
|
// return txsig
|
|
113
111
|
return encode.encode(txSig);
|
|
@@ -118,7 +116,7 @@ export class Client {
|
|
|
118
116
|
* @returns Index details
|
|
119
117
|
*/
|
|
120
118
|
async index(): Promise<any> {
|
|
121
|
-
return handleApiCall(() => this.http.get(""));
|
|
119
|
+
return this.handleApiCall(() => this.http.get(""));
|
|
122
120
|
}
|
|
123
121
|
|
|
124
122
|
/**
|
|
@@ -128,10 +126,13 @@ export class Client {
|
|
|
128
126
|
account: GetAccountRequest["account"],
|
|
129
127
|
getClendAccountSummary: GetAccountRequest["getClendAccountSummary"],
|
|
130
128
|
): Promise<GetAccountResponse> {
|
|
131
|
-
const body = await handleApiCall(() =>
|
|
132
|
-
this.http.get(
|
|
133
|
-
|
|
134
|
-
|
|
129
|
+
const body = await this.handleApiCall(() =>
|
|
130
|
+
this.http.get(`/account`, {
|
|
131
|
+
params: {
|
|
132
|
+
account: account.toString(),
|
|
133
|
+
getClendAccountSummary,
|
|
134
|
+
},
|
|
135
|
+
}),
|
|
135
136
|
);
|
|
136
137
|
const jsonRawResponse: any = JSON.parse(body);
|
|
137
138
|
return this.parseClendAccountWithSummary(
|
|
@@ -271,15 +272,19 @@ export class Client {
|
|
|
271
272
|
}
|
|
272
273
|
|
|
273
274
|
async getUser(
|
|
274
|
-
user:
|
|
275
|
-
groups:
|
|
276
|
-
getClendAccountSummary:
|
|
275
|
+
user: GetUserRequest["user"],
|
|
276
|
+
groups: GetUserRequest["groups"],
|
|
277
|
+
getClendAccountSummary: GetUserRequest["getClendAccountSummary"],
|
|
277
278
|
): Promise<GetUserResponse> {
|
|
278
279
|
// Make the API call to fetch the raw user data as a string.
|
|
279
|
-
const body = await handleApiCall(() =>
|
|
280
|
-
this.http.get(
|
|
281
|
-
|
|
282
|
-
|
|
280
|
+
const body = await this.handleApiCall(() =>
|
|
281
|
+
this.http.get(`/user`, {
|
|
282
|
+
params: {
|
|
283
|
+
user: user.toString(),
|
|
284
|
+
groups: groups.map((g) => g.toString()).join(","),
|
|
285
|
+
getClendAccountSummary,
|
|
286
|
+
},
|
|
287
|
+
}),
|
|
283
288
|
);
|
|
284
289
|
|
|
285
290
|
// Parse the raw string body into a JSON object.
|
|
@@ -319,8 +324,12 @@ export class Client {
|
|
|
319
324
|
* @returns All groups
|
|
320
325
|
*/
|
|
321
326
|
async getGroups(includeBankData: boolean): Promise<GetGroupsResponse> {
|
|
322
|
-
const body = await handleApiCall(() =>
|
|
323
|
-
this.http.get(`/groups
|
|
327
|
+
const body = await this.handleApiCall(() =>
|
|
328
|
+
this.http.get(`/groups`, {
|
|
329
|
+
params: {
|
|
330
|
+
includeBankData,
|
|
331
|
+
},
|
|
332
|
+
}),
|
|
324
333
|
);
|
|
325
334
|
|
|
326
335
|
const marketJson: any = JSON.parse(body);
|
|
@@ -349,8 +358,12 @@ export class Client {
|
|
|
349
358
|
* @returns Group Details, which is really just all the bank data for that group
|
|
350
359
|
*/
|
|
351
360
|
async getGroup(groupAddress: web3.PublicKey): Promise<GetGroupResponse> {
|
|
352
|
-
const body = await handleApiCall(() =>
|
|
353
|
-
this.http.get(`/group
|
|
361
|
+
const body = await this.handleApiCall(() =>
|
|
362
|
+
this.http.get(`/group`, {
|
|
363
|
+
params: {
|
|
364
|
+
group: groupAddress.toString(),
|
|
365
|
+
},
|
|
366
|
+
}),
|
|
354
367
|
);
|
|
355
368
|
|
|
356
369
|
const marketJson: any = JSON.parse(body);
|
|
@@ -377,8 +390,12 @@ export class Client {
|
|
|
377
390
|
* @returns Bank details
|
|
378
391
|
*/
|
|
379
392
|
async getBank(bankAddress: web3.PublicKey): Promise<GetBankResponse> {
|
|
380
|
-
const body = await handleApiCall(() =>
|
|
381
|
-
this.http.get(`/bank
|
|
393
|
+
const body = await this.handleApiCall(() =>
|
|
394
|
+
this.http.get(`/bank`, {
|
|
395
|
+
params: {
|
|
396
|
+
bank: bankAddress.toString(),
|
|
397
|
+
},
|
|
398
|
+
}),
|
|
382
399
|
);
|
|
383
400
|
|
|
384
401
|
const bankJson: any = JSON.parse(body);
|
|
@@ -405,7 +422,7 @@ export class Client {
|
|
|
405
422
|
depositAmountUi: uiAmount,
|
|
406
423
|
};
|
|
407
424
|
|
|
408
|
-
const body = await handleApiCall(() =>
|
|
425
|
+
const body = await this.handleApiCall(() =>
|
|
409
426
|
this.http.post("deposit", JSON.stringify(req)),
|
|
410
427
|
);
|
|
411
428
|
|
|
@@ -432,7 +449,7 @@ export class Client {
|
|
|
432
449
|
withdrawAll,
|
|
433
450
|
};
|
|
434
451
|
|
|
435
|
-
const body = await handleApiCall(() =>
|
|
452
|
+
const body = await this.handleApiCall(() =>
|
|
436
453
|
this.http.post("withdraw", JSON.stringify(req)),
|
|
437
454
|
);
|
|
438
455
|
|
|
@@ -481,7 +498,7 @@ export class Client {
|
|
|
481
498
|
leverage,
|
|
482
499
|
slippageBps,
|
|
483
500
|
};
|
|
484
|
-
const body = await handleApiCall(() =>
|
|
501
|
+
const body = await this.handleApiCall(() =>
|
|
485
502
|
this.http.post("leverage/deposit", JSON.stringify(req)),
|
|
486
503
|
);
|
|
487
504
|
|
|
@@ -514,7 +531,7 @@ export class Client {
|
|
|
514
531
|
leverage,
|
|
515
532
|
slippageBps,
|
|
516
533
|
};
|
|
517
|
-
const body = await handleApiCall(() =>
|
|
534
|
+
const body = await this.handleApiCall(() =>
|
|
518
535
|
this.http.post("leverage/adjust", JSON.stringify(req)),
|
|
519
536
|
);
|
|
520
537
|
|
|
@@ -551,7 +568,7 @@ export class Client {
|
|
|
551
568
|
slippageBps,
|
|
552
569
|
withdrawAll,
|
|
553
570
|
};
|
|
554
|
-
const body = await handleApiCall(() =>
|
|
571
|
+
const body = await this.handleApiCall(() =>
|
|
555
572
|
this.http.post("leverage/withdraw", JSON.stringify(req)),
|
|
556
573
|
);
|
|
557
574
|
|
|
@@ -574,7 +591,7 @@ export class Client {
|
|
|
574
591
|
clendAccount,
|
|
575
592
|
};
|
|
576
593
|
|
|
577
|
-
const body = await handleApiCall(() =>
|
|
594
|
+
const body = await this.handleApiCall(() =>
|
|
578
595
|
this.http.post("emissions/withdraw", JSON.stringify(req)),
|
|
579
596
|
);
|
|
580
597
|
|
|
@@ -588,34 +605,24 @@ export class Client {
|
|
|
588
605
|
|
|
589
606
|
return txSig;
|
|
590
607
|
}
|
|
591
|
-
}
|
|
592
608
|
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
const res = e.response;
|
|
610
|
-
if (res && typeof res.data === "object") {
|
|
611
|
-
const payload = res.data as ApiErrorPayload;
|
|
612
|
-
throw new Error(
|
|
613
|
-
`${payload.error}${payload.details ? ` ${payload.details}` : ""}`,
|
|
614
|
-
);
|
|
615
|
-
}
|
|
616
|
-
throw new Error(`${e.message}`);
|
|
609
|
+
public async getExtension(extension: ExtensionKey) {
|
|
610
|
+
switch (extension) {
|
|
611
|
+
case "positionCharting":
|
|
612
|
+
return (clendAccount: web3.PublicKey) =>
|
|
613
|
+
new PositionChartingExtension(this.baseUrl, clendAccount);
|
|
614
|
+
case "groupCharting":
|
|
615
|
+
return (group: web3.PublicKey) =>
|
|
616
|
+
new GroupChartingExtension(this.baseUrl, group);
|
|
617
|
+
case "walletCharting":
|
|
618
|
+
return (address?: web3.PublicKey) =>
|
|
619
|
+
new WalletChartingExtension(this.baseUrl, address ?? this.address());
|
|
620
|
+
case "bankCharting":
|
|
621
|
+
return (bank: web3.PublicKey) =>
|
|
622
|
+
new BankChartingExtension(this.baseUrl, bank);
|
|
623
|
+
default:
|
|
624
|
+
throw new Error(`Unknown extension: ${extension}`);
|
|
617
625
|
}
|
|
618
|
-
throw e;
|
|
619
626
|
}
|
|
620
627
|
}
|
|
621
628
|
|
package/src/types.ts
CHANGED
|
@@ -1,4 +1,8 @@
|
|
|
1
1
|
import { BN, web3 } from "@coral-xyz/anchor";
|
|
2
|
+
import { PositionChartingExtension } from "./charting/position";
|
|
3
|
+
import { BankChartingExtension } from "./charting/bank";
|
|
4
|
+
import { WalletChartingExtension } from "./charting/wallet";
|
|
5
|
+
import { GroupChartingExtension } from "./charting/group";
|
|
2
6
|
|
|
3
7
|
// Send a tx
|
|
4
8
|
export interface SendRequest {
|
|
@@ -283,3 +287,15 @@ export interface UserRequest {
|
|
|
283
287
|
openPosition: boolean | null;
|
|
284
288
|
closePosition: boolean | null;
|
|
285
289
|
}
|
|
290
|
+
|
|
291
|
+
export type ExtensionKey =
|
|
292
|
+
| "positionCharting"
|
|
293
|
+
| "groupCharting"
|
|
294
|
+
| "walletCharting"
|
|
295
|
+
| "bankCharting";
|
|
296
|
+
|
|
297
|
+
export type Extension =
|
|
298
|
+
| InstanceType<typeof PositionChartingExtension>
|
|
299
|
+
| InstanceType<typeof GroupChartingExtension>
|
|
300
|
+
| InstanceType<typeof WalletChartingExtension>
|
|
301
|
+
| InstanceType<typeof BankChartingExtension>;
|