@kehtus/proportion-sdk 0.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/SDK_IMPROVEMENT_PLAN.md +197 -0
- package/arch.md +448 -0
- package/dist/__tests__/account.test.d.ts +1 -0
- package/dist/__tests__/account.test.js +36 -0
- package/dist/__tests__/indexer.test.d.ts +1 -0
- package/dist/__tests__/indexer.test.js +230 -0
- package/dist/__tests__/lifecycle.test.d.ts +1 -0
- package/dist/__tests__/lifecycle.test.js +186 -0
- package/dist/__tests__/reads.test.d.ts +1 -0
- package/dist/__tests__/reads.test.js +185 -0
- package/dist/__tests__/utils.test.d.ts +1 -0
- package/dist/__tests__/utils.test.js +185 -0
- package/dist/abi/factory.d.ts +308 -0
- package/dist/abi/factory.js +399 -0
- package/dist/abi/fundedAccount.d.ts +1074 -0
- package/dist/abi/fundedAccount.js +1373 -0
- package/dist/abi/mainVault.d.ts +1448 -0
- package/dist/abi/mainVault.js +1865 -0
- package/dist/account.d.ts +55 -0
- package/dist/account.js +290 -0
- package/dist/constants.d.ts +48 -0
- package/dist/constants.js +42 -0
- package/dist/factory.d.ts +23 -0
- package/dist/factory.js +139 -0
- package/dist/index.d.ts +11 -0
- package/dist/index.js +14 -0
- package/dist/indexer.d.ts +57 -0
- package/dist/indexer.js +540 -0
- package/dist/sdk.d.ts +22 -0
- package/dist/sdk.js +89 -0
- package/dist/types.d.ts +384 -0
- package/dist/types.js +11 -0
- package/dist/utils.d.ts +21 -0
- package/dist/utils.js +89 -0
- package/dist/vault.d.ts +60 -0
- package/dist/vault.js +429 -0
- package/package.json +32 -0
- package/src/__tests__/account.test.ts +40 -0
- package/src/__tests__/indexer.test.ts +255 -0
- package/src/__tests__/lifecycle.test.ts +231 -0
- package/src/__tests__/reads.test.ts +209 -0
- package/src/__tests__/utils.test.ts +245 -0
- package/src/abi/factory.ts +399 -0
- package/src/abi/fundedAccount.ts +1373 -0
- package/src/abi/mainVault.ts +1865 -0
- package/src/account.ts +339 -0
- package/src/constants.ts +50 -0
- package/src/factory.ts +157 -0
- package/src/index.ts +16 -0
- package/src/indexer.ts +636 -0
- package/src/sdk.ts +93 -0
- package/src/types.ts +426 -0
- package/src/utils.ts +143 -0
- package/src/vault.ts +479 -0
- package/tsconfig.json +19 -0
- package/vitest.config.ts +8 -0
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import type { Address, Chain, Hash, PublicClient, WalletClient } from "viem";
|
|
2
|
+
import { AccountState, type AccountDetails } from "./types.js";
|
|
3
|
+
type RawCheckpoint = {
|
|
4
|
+
accountValue: bigint | number;
|
|
5
|
+
timestamp: bigint | number;
|
|
6
|
+
profitable: boolean;
|
|
7
|
+
};
|
|
8
|
+
export declare function normalizeCheckpoints(rawCheckpoints: readonly RawCheckpoint[], totalCheckpoints: number, checkpointIndex: number): Array<{
|
|
9
|
+
accountValue: bigint;
|
|
10
|
+
timestamp: number;
|
|
11
|
+
profitable: boolean;
|
|
12
|
+
}>;
|
|
13
|
+
export declare class AccountModule {
|
|
14
|
+
private publicClient;
|
|
15
|
+
private walletClient;
|
|
16
|
+
private chain;
|
|
17
|
+
constructor(publicClient: PublicClient, walletClient: WalletClient | undefined, chain: Chain);
|
|
18
|
+
getDetails(account: Address): Promise<AccountDetails>;
|
|
19
|
+
getState(account: Address): Promise<AccountState>;
|
|
20
|
+
getTrailingFloor(account: Address): Promise<bigint>;
|
|
21
|
+
getDailyFloor(account: Address): Promise<bigint>;
|
|
22
|
+
canWithdrawProfit(account: Address): Promise<boolean>;
|
|
23
|
+
isSubscriptionActive(account: Address): Promise<boolean>;
|
|
24
|
+
getCheckpoints(account: Address): Promise<Array<{
|
|
25
|
+
accountValue: bigint;
|
|
26
|
+
timestamp: number;
|
|
27
|
+
profitable: boolean;
|
|
28
|
+
}>>;
|
|
29
|
+
getPendingWithdrawal(account: Address): Promise<{
|
|
30
|
+
profit: bigint;
|
|
31
|
+
requestedAt: number;
|
|
32
|
+
}>;
|
|
33
|
+
getAccountConfig(account: Address): Promise<{
|
|
34
|
+
usdc: Address;
|
|
35
|
+
vault: Address;
|
|
36
|
+
subscriptionFeeMultiplier: number;
|
|
37
|
+
}>;
|
|
38
|
+
private requireWallet;
|
|
39
|
+
private write;
|
|
40
|
+
setApiWallet(account: Address, wallet: Address): Promise<Hash>;
|
|
41
|
+
requestWithdrawProfit(account: Address): Promise<Hash>;
|
|
42
|
+
cancelSubscription(account: Address): Promise<Hash>;
|
|
43
|
+
cancelStuckWithdrawal(account: Address): Promise<Hash>;
|
|
44
|
+
checkpoint(account: Address): Promise<Hash>;
|
|
45
|
+
initiateClose(account: Address): Promise<Hash>;
|
|
46
|
+
initiateCloseForPerp(account: Address, perpIndex: number): Promise<Hash>;
|
|
47
|
+
initiateCloseAdmin(account: Address): Promise<Hash>;
|
|
48
|
+
closeAndReturn(account: Address): Promise<Hash>;
|
|
49
|
+
finalizeReturn(account: Address): Promise<Hash>;
|
|
50
|
+
claimWithdrawal(account: Address): Promise<Hash>;
|
|
51
|
+
claimSubscriptionFee(account: Address): Promise<Hash>;
|
|
52
|
+
rescueStuckFunds(account: Address): Promise<Hash>;
|
|
53
|
+
setRiskEngineWallet(account: Address, wallet: Address): Promise<Hash>;
|
|
54
|
+
}
|
|
55
|
+
export {};
|
package/dist/account.js
ADDED
|
@@ -0,0 +1,290 @@
|
|
|
1
|
+
import { fundedAccountAbi } from "./abi/fundedAccount.js";
|
|
2
|
+
export function normalizeCheckpoints(rawCheckpoints, totalCheckpoints, checkpointIndex) {
|
|
3
|
+
if (totalCheckpoints <= 0)
|
|
4
|
+
return [];
|
|
5
|
+
const count = Math.min(totalCheckpoints, rawCheckpoints.length);
|
|
6
|
+
const start = count === rawCheckpoints.length ? checkpointIndex % count : 0;
|
|
7
|
+
return Array.from({ length: count }, (_, offset) => rawCheckpoints[(start + offset) % count]).map((cp) => ({
|
|
8
|
+
accountValue: BigInt(cp.accountValue),
|
|
9
|
+
timestamp: Number(cp.timestamp),
|
|
10
|
+
profitable: cp.profitable,
|
|
11
|
+
}));
|
|
12
|
+
}
|
|
13
|
+
export class AccountModule {
|
|
14
|
+
publicClient;
|
|
15
|
+
walletClient;
|
|
16
|
+
chain;
|
|
17
|
+
constructor(publicClient, walletClient, chain) {
|
|
18
|
+
this.publicClient = publicClient;
|
|
19
|
+
this.walletClient = walletClient;
|
|
20
|
+
this.chain = chain;
|
|
21
|
+
}
|
|
22
|
+
// ── READS ───────────────────────────────────────────
|
|
23
|
+
async getDetails(account) {
|
|
24
|
+
const contract = { address: account, abi: fundedAccountAbi };
|
|
25
|
+
const results = await this.publicClient.multicall({
|
|
26
|
+
contracts: [
|
|
27
|
+
{ ...contract, functionName: "state" },
|
|
28
|
+
{ ...contract, functionName: "owner" },
|
|
29
|
+
{ ...contract, functionName: "builder" },
|
|
30
|
+
{ ...contract, functionName: "accountSize" },
|
|
31
|
+
{ ...contract, functionName: "drawdownBps" },
|
|
32
|
+
{ ...contract, functionName: "dailyDrawdownEnabled" },
|
|
33
|
+
{ ...contract, functionName: "subscriptionFeeMultiplier" },
|
|
34
|
+
{ ...contract, functionName: "highWaterMark" },
|
|
35
|
+
{ ...contract, functionName: "dayStartValue" },
|
|
36
|
+
{ ...contract, functionName: "activatedAt" },
|
|
37
|
+
{ ...contract, functionName: "subscriptionPaidUntil" },
|
|
38
|
+
{ ...contract, functionName: "subscriptionCancelled" },
|
|
39
|
+
{ ...contract, functionName: "pendingSubscriptionFee" },
|
|
40
|
+
{ ...contract, functionName: "apiWallet" },
|
|
41
|
+
{ ...contract, functionName: "riskEngineWallet" },
|
|
42
|
+
{ ...contract, functionName: "builderRiskEngineWallet" },
|
|
43
|
+
{ ...contract, functionName: "checkpointIndex" },
|
|
44
|
+
{ ...contract, functionName: "profitableDaysCount" },
|
|
45
|
+
{ ...contract, functionName: "totalCheckpoints" },
|
|
46
|
+
{ ...contract, functionName: "lastCheckpointDay" },
|
|
47
|
+
{ ...contract, functionName: "closingInitiatedAt" },
|
|
48
|
+
{ ...contract, functionName: "returnInitiatedAt" },
|
|
49
|
+
{ ...contract, functionName: "pendingWithdrawal" },
|
|
50
|
+
{ ...contract, functionName: "getTrailingFloor" },
|
|
51
|
+
{ ...contract, functionName: "getDailyFloor" },
|
|
52
|
+
{ ...contract, functionName: "getSubscriptionFee" },
|
|
53
|
+
{ ...contract, functionName: "isSubscriptionActive" },
|
|
54
|
+
{ ...contract, functionName: "canWithdrawProfit" },
|
|
55
|
+
{ ...contract, functionName: "getAllCheckpoints" },
|
|
56
|
+
],
|
|
57
|
+
});
|
|
58
|
+
const checkpointIndex = results[16].result;
|
|
59
|
+
const totalCp = results[18].result;
|
|
60
|
+
const [profit, requestedAt] = results[22].result;
|
|
61
|
+
const rawCheckpoints = results[28].result;
|
|
62
|
+
const checkpoints = normalizeCheckpoints(rawCheckpoints, totalCp, checkpointIndex);
|
|
63
|
+
return {
|
|
64
|
+
address: account,
|
|
65
|
+
state: results[0].result,
|
|
66
|
+
owner: results[1].result,
|
|
67
|
+
builder: results[2].result,
|
|
68
|
+
accountSize: results[3].result,
|
|
69
|
+
drawdownBps: results[4].result,
|
|
70
|
+
dailyDrawdownEnabled: results[5].result,
|
|
71
|
+
subscriptionFeeMultiplier: results[6].result,
|
|
72
|
+
highWaterMark: results[7].result,
|
|
73
|
+
dayStartValue: results[8].result,
|
|
74
|
+
activatedAt: results[9].result,
|
|
75
|
+
subscriptionPaidUntil: results[10].result,
|
|
76
|
+
subscriptionCancelled: results[11].result,
|
|
77
|
+
pendingSubscriptionFee: results[12].result,
|
|
78
|
+
apiWallet: results[13].result,
|
|
79
|
+
riskEngineWallet: results[14].result,
|
|
80
|
+
builderRiskEngineWallet: results[15].result,
|
|
81
|
+
checkpointIndex,
|
|
82
|
+
profitableDaysCount: results[17].result,
|
|
83
|
+
totalCheckpoints: totalCp,
|
|
84
|
+
lastCheckpointDay: results[19].result,
|
|
85
|
+
closingInitiatedAt: Number(results[20].result),
|
|
86
|
+
returnInitiatedAt: Number(results[21].result),
|
|
87
|
+
pendingWithdrawal: { profit, requestedAt: Number(requestedAt) },
|
|
88
|
+
trailingFloor: results[23].result,
|
|
89
|
+
dailyFloor: results[24].result,
|
|
90
|
+
subscriptionFee: results[25].result,
|
|
91
|
+
isSubscriptionActive: results[26].result,
|
|
92
|
+
canWithdrawProfit: results[27].result,
|
|
93
|
+
checkpoints,
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
async getState(account) {
|
|
97
|
+
const raw = await this.publicClient.readContract({
|
|
98
|
+
address: account,
|
|
99
|
+
abi: fundedAccountAbi,
|
|
100
|
+
functionName: "state",
|
|
101
|
+
});
|
|
102
|
+
return raw;
|
|
103
|
+
}
|
|
104
|
+
async getTrailingFloor(account) {
|
|
105
|
+
return this.publicClient.readContract({
|
|
106
|
+
address: account,
|
|
107
|
+
abi: fundedAccountAbi,
|
|
108
|
+
functionName: "getTrailingFloor",
|
|
109
|
+
});
|
|
110
|
+
}
|
|
111
|
+
async getDailyFloor(account) {
|
|
112
|
+
return this.publicClient.readContract({
|
|
113
|
+
address: account,
|
|
114
|
+
abi: fundedAccountAbi,
|
|
115
|
+
functionName: "getDailyFloor",
|
|
116
|
+
});
|
|
117
|
+
}
|
|
118
|
+
async canWithdrawProfit(account) {
|
|
119
|
+
return this.publicClient.readContract({
|
|
120
|
+
address: account,
|
|
121
|
+
abi: fundedAccountAbi,
|
|
122
|
+
functionName: "canWithdrawProfit",
|
|
123
|
+
});
|
|
124
|
+
}
|
|
125
|
+
async isSubscriptionActive(account) {
|
|
126
|
+
return this.publicClient.readContract({
|
|
127
|
+
address: account,
|
|
128
|
+
abi: fundedAccountAbi,
|
|
129
|
+
functionName: "isSubscriptionActive",
|
|
130
|
+
});
|
|
131
|
+
}
|
|
132
|
+
async getCheckpoints(account) {
|
|
133
|
+
const [all, total, checkpointIndex] = await Promise.all([
|
|
134
|
+
this.publicClient.readContract({
|
|
135
|
+
address: account,
|
|
136
|
+
abi: fundedAccountAbi,
|
|
137
|
+
functionName: "getAllCheckpoints",
|
|
138
|
+
}),
|
|
139
|
+
this.publicClient.readContract({
|
|
140
|
+
address: account,
|
|
141
|
+
abi: fundedAccountAbi,
|
|
142
|
+
functionName: "totalCheckpoints",
|
|
143
|
+
}),
|
|
144
|
+
this.publicClient.readContract({
|
|
145
|
+
address: account,
|
|
146
|
+
abi: fundedAccountAbi,
|
|
147
|
+
functionName: "checkpointIndex",
|
|
148
|
+
}),
|
|
149
|
+
]);
|
|
150
|
+
return normalizeCheckpoints(all, Number(total), Number(checkpointIndex));
|
|
151
|
+
}
|
|
152
|
+
async getPendingWithdrawal(account) {
|
|
153
|
+
const result = await this.publicClient.readContract({
|
|
154
|
+
address: account,
|
|
155
|
+
abi: fundedAccountAbi,
|
|
156
|
+
functionName: "pendingWithdrawal",
|
|
157
|
+
});
|
|
158
|
+
return { profit: result[0], requestedAt: Number(result[1]) };
|
|
159
|
+
}
|
|
160
|
+
async getAccountConfig(account) {
|
|
161
|
+
const contract = { address: account, abi: fundedAccountAbi };
|
|
162
|
+
const results = await this.publicClient.multicall({
|
|
163
|
+
contracts: [
|
|
164
|
+
{ ...contract, functionName: "usdc" },
|
|
165
|
+
{ ...contract, functionName: "vault" },
|
|
166
|
+
{ ...contract, functionName: "subscriptionFeeMultiplier" },
|
|
167
|
+
],
|
|
168
|
+
});
|
|
169
|
+
return {
|
|
170
|
+
usdc: results[0].result,
|
|
171
|
+
vault: results[1].result,
|
|
172
|
+
subscriptionFeeMultiplier: results[2].result,
|
|
173
|
+
};
|
|
174
|
+
}
|
|
175
|
+
// ── WRITES ──────────────────────────────────────────
|
|
176
|
+
requireWallet() {
|
|
177
|
+
if (!this.walletClient)
|
|
178
|
+
throw new Error("WalletClient required for write operations");
|
|
179
|
+
return this.walletClient;
|
|
180
|
+
}
|
|
181
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
182
|
+
async write(params) {
|
|
183
|
+
const wallet = this.requireWallet();
|
|
184
|
+
return wallet.writeContract({ chain: this.chain, ...params });
|
|
185
|
+
}
|
|
186
|
+
// ── OWNER WRITES ────────────────────────────────────
|
|
187
|
+
async setApiWallet(account, wallet) {
|
|
188
|
+
return this.write({
|
|
189
|
+
address: account,
|
|
190
|
+
abi: fundedAccountAbi,
|
|
191
|
+
functionName: "setApiWallet",
|
|
192
|
+
args: [wallet],
|
|
193
|
+
});
|
|
194
|
+
}
|
|
195
|
+
async requestWithdrawProfit(account) {
|
|
196
|
+
return this.write({
|
|
197
|
+
address: account,
|
|
198
|
+
abi: fundedAccountAbi,
|
|
199
|
+
functionName: "requestWithdrawProfit",
|
|
200
|
+
});
|
|
201
|
+
}
|
|
202
|
+
async cancelSubscription(account) {
|
|
203
|
+
return this.write({
|
|
204
|
+
address: account,
|
|
205
|
+
abi: fundedAccountAbi,
|
|
206
|
+
functionName: "cancelSubscription",
|
|
207
|
+
});
|
|
208
|
+
}
|
|
209
|
+
async cancelStuckWithdrawal(account) {
|
|
210
|
+
return this.write({
|
|
211
|
+
address: account,
|
|
212
|
+
abi: fundedAccountAbi,
|
|
213
|
+
functionName: "cancelStuckWithdrawal",
|
|
214
|
+
});
|
|
215
|
+
}
|
|
216
|
+
// ── PERMISSIONLESS WRITES ───────────────────────────
|
|
217
|
+
async checkpoint(account) {
|
|
218
|
+
return this.write({
|
|
219
|
+
address: account,
|
|
220
|
+
abi: fundedAccountAbi,
|
|
221
|
+
functionName: "checkpoint",
|
|
222
|
+
});
|
|
223
|
+
}
|
|
224
|
+
async initiateClose(account) {
|
|
225
|
+
return this.write({
|
|
226
|
+
address: account,
|
|
227
|
+
abi: fundedAccountAbi,
|
|
228
|
+
functionName: "initiateClose",
|
|
229
|
+
});
|
|
230
|
+
}
|
|
231
|
+
async initiateCloseForPerp(account, perpIndex) {
|
|
232
|
+
return this.write({
|
|
233
|
+
address: account,
|
|
234
|
+
abi: fundedAccountAbi,
|
|
235
|
+
functionName: "initiateClose",
|
|
236
|
+
args: [perpIndex],
|
|
237
|
+
});
|
|
238
|
+
}
|
|
239
|
+
async initiateCloseAdmin(account) {
|
|
240
|
+
return this.write({
|
|
241
|
+
address: account,
|
|
242
|
+
abi: fundedAccountAbi,
|
|
243
|
+
functionName: "initiateCloseAdmin",
|
|
244
|
+
});
|
|
245
|
+
}
|
|
246
|
+
async closeAndReturn(account) {
|
|
247
|
+
return this.write({
|
|
248
|
+
address: account,
|
|
249
|
+
abi: fundedAccountAbi,
|
|
250
|
+
functionName: "closeAndReturn",
|
|
251
|
+
});
|
|
252
|
+
}
|
|
253
|
+
async finalizeReturn(account) {
|
|
254
|
+
return this.write({
|
|
255
|
+
address: account,
|
|
256
|
+
abi: fundedAccountAbi,
|
|
257
|
+
functionName: "finalizeReturn",
|
|
258
|
+
});
|
|
259
|
+
}
|
|
260
|
+
async claimWithdrawal(account) {
|
|
261
|
+
return this.write({
|
|
262
|
+
address: account,
|
|
263
|
+
abi: fundedAccountAbi,
|
|
264
|
+
functionName: "claimWithdrawal",
|
|
265
|
+
});
|
|
266
|
+
}
|
|
267
|
+
async claimSubscriptionFee(account) {
|
|
268
|
+
return this.write({
|
|
269
|
+
address: account,
|
|
270
|
+
abi: fundedAccountAbi,
|
|
271
|
+
functionName: "claimSubscriptionFee",
|
|
272
|
+
});
|
|
273
|
+
}
|
|
274
|
+
async rescueStuckFunds(account) {
|
|
275
|
+
return this.write({
|
|
276
|
+
address: account,
|
|
277
|
+
abi: fundedAccountAbi,
|
|
278
|
+
functionName: "rescueStuckFunds",
|
|
279
|
+
});
|
|
280
|
+
}
|
|
281
|
+
// ── RISK ENGINE WRITES ──────────────────────────────
|
|
282
|
+
async setRiskEngineWallet(account, wallet) {
|
|
283
|
+
return this.write({
|
|
284
|
+
address: account,
|
|
285
|
+
abi: fundedAccountAbi,
|
|
286
|
+
functionName: "setRiskEngineWallet",
|
|
287
|
+
args: [wallet],
|
|
288
|
+
});
|
|
289
|
+
}
|
|
290
|
+
}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
export declare const CHAIN_ID = 999;
|
|
2
|
+
export declare const hyperEvm: {
|
|
3
|
+
readonly id: 999;
|
|
4
|
+
readonly name: "HyperEVM";
|
|
5
|
+
readonly nativeCurrency: {
|
|
6
|
+
readonly name: "HYPE";
|
|
7
|
+
readonly symbol: "HYPE";
|
|
8
|
+
readonly decimals: 18;
|
|
9
|
+
};
|
|
10
|
+
readonly rpcUrls: {
|
|
11
|
+
readonly default: {
|
|
12
|
+
readonly http: readonly ["https://rpc.hyperliquid.xyz/evm"];
|
|
13
|
+
};
|
|
14
|
+
};
|
|
15
|
+
readonly contracts: {
|
|
16
|
+
readonly multicall3: {
|
|
17
|
+
readonly address: "0xcA11bde05977b3631167028862bE2a173976CA11";
|
|
18
|
+
};
|
|
19
|
+
};
|
|
20
|
+
};
|
|
21
|
+
export declare const ADDRESSES: {
|
|
22
|
+
readonly MAIN_VAULT: "0x4478888dA8d22E275344C1A24BDEbcf2bfE2dc45";
|
|
23
|
+
readonly FACTORY: "0xb7cE604a000CCFCe7c7DAfFBaefD26c33C86CE7A";
|
|
24
|
+
readonly USDC: "0xb88339CB7199b77E23DB6E890353E22632Ba630f";
|
|
25
|
+
};
|
|
26
|
+
export declare const BPS = 10000n;
|
|
27
|
+
export declare const MIN_DRAWDOWN_BPS = 500;
|
|
28
|
+
export declare const MAX_DRAWDOWN_BPS = 2500;
|
|
29
|
+
export declare const DAILY_DD_DISCOUNT_BPS = 2000n;
|
|
30
|
+
export declare const PROTOCOL_FEE_BPS = 1000n;
|
|
31
|
+
export declare const OWNER_PROFIT_BPS = 8000n;
|
|
32
|
+
export declare const PROTOCOL_PROFIT_BPS = 700n;
|
|
33
|
+
export declare const BUILDER_LEVERAGE = 10n;
|
|
34
|
+
export declare const MAX_UTILIZATION_BPS = 8000n;
|
|
35
|
+
export declare const MAX_SINGLE_ACCOUNT_BPS = 1000n;
|
|
36
|
+
export declare const HYPE_FOR_GAS = 1000000000000000n;
|
|
37
|
+
export declare const USDC_DECIMALS = 6;
|
|
38
|
+
export declare const ACCOUNT_VALUE_DECIMALS = 8;
|
|
39
|
+
export declare const DECIMALS_MULTIPLIER = 100n;
|
|
40
|
+
export declare const SUBSCRIPTION_PERIOD: number;
|
|
41
|
+
export declare const WITHDRAWAL_TIMEOUT: number;
|
|
42
|
+
export declare const BRIDGE_DELAY = 30;
|
|
43
|
+
export declare const CLOSING_TIMEOUT: number;
|
|
44
|
+
export declare const CHECKPOINT_INTERVAL = 86400;
|
|
45
|
+
export declare const TRADING_DAYS_REQUIRED = 7;
|
|
46
|
+
export declare const PROFITABLE_DAYS_REQUIRED = 3;
|
|
47
|
+
export declare const MIN_PROFIT_BPS = 50;
|
|
48
|
+
export declare const MAX_LEVERAGE = 5;
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
export const CHAIN_ID = 999;
|
|
2
|
+
export const hyperEvm = {
|
|
3
|
+
id: 999,
|
|
4
|
+
name: "HyperEVM",
|
|
5
|
+
nativeCurrency: { name: "HYPE", symbol: "HYPE", decimals: 18 },
|
|
6
|
+
rpcUrls: { default: { http: ["https://rpc.hyperliquid.xyz/evm"] } },
|
|
7
|
+
contracts: {
|
|
8
|
+
multicall3: { address: "0xcA11bde05977b3631167028862bE2a173976CA11" },
|
|
9
|
+
},
|
|
10
|
+
};
|
|
11
|
+
export const ADDRESSES = {
|
|
12
|
+
MAIN_VAULT: "0x4478888dA8d22E275344C1A24BDEbcf2bfE2dc45",
|
|
13
|
+
FACTORY: "0xb7cE604a000CCFCe7c7DAfFBaefD26c33C86CE7A",
|
|
14
|
+
USDC: "0xb88339CB7199b77E23DB6E890353E22632Ba630f",
|
|
15
|
+
};
|
|
16
|
+
// BPS
|
|
17
|
+
export const BPS = 10000n;
|
|
18
|
+
export const MIN_DRAWDOWN_BPS = 500;
|
|
19
|
+
export const MAX_DRAWDOWN_BPS = 2500;
|
|
20
|
+
export const DAILY_DD_DISCOUNT_BPS = 2000n;
|
|
21
|
+
export const PROTOCOL_FEE_BPS = 1000n;
|
|
22
|
+
export const OWNER_PROFIT_BPS = 8000n;
|
|
23
|
+
export const PROTOCOL_PROFIT_BPS = 700n;
|
|
24
|
+
export const BUILDER_LEVERAGE = 10n;
|
|
25
|
+
export const MAX_UTILIZATION_BPS = 8000n;
|
|
26
|
+
export const MAX_SINGLE_ACCOUNT_BPS = 1000n;
|
|
27
|
+
export const HYPE_FOR_GAS = 1000000000000000n; // 0.001 ether
|
|
28
|
+
// Decimals
|
|
29
|
+
export const USDC_DECIMALS = 6;
|
|
30
|
+
export const ACCOUNT_VALUE_DECIMALS = 8;
|
|
31
|
+
export const DECIMALS_MULTIPLIER = 100n; // 6→8 dec
|
|
32
|
+
// Time (seconds)
|
|
33
|
+
export const SUBSCRIPTION_PERIOD = 30 * 86400;
|
|
34
|
+
export const WITHDRAWAL_TIMEOUT = 7 * 86400;
|
|
35
|
+
export const BRIDGE_DELAY = 30;
|
|
36
|
+
export const CLOSING_TIMEOUT = 3 * 86400;
|
|
37
|
+
export const CHECKPOINT_INTERVAL = 86400;
|
|
38
|
+
// Trading rules
|
|
39
|
+
export const TRADING_DAYS_REQUIRED = 7;
|
|
40
|
+
export const PROFITABLE_DAYS_REQUIRED = 3;
|
|
41
|
+
export const MIN_PROFIT_BPS = 50;
|
|
42
|
+
export const MAX_LEVERAGE = 5;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { Address, PublicClient } from "viem";
|
|
2
|
+
export declare class FactoryModule {
|
|
3
|
+
private publicClient;
|
|
4
|
+
private factoryAddress;
|
|
5
|
+
constructor(publicClient: PublicClient, factoryAddress: Address);
|
|
6
|
+
private isOutOfBoundsError;
|
|
7
|
+
private accountExistsAt;
|
|
8
|
+
predictAddress(owner: Address, builder: Address): Promise<Address>;
|
|
9
|
+
getAccountAt(index: bigint): Promise<Address>;
|
|
10
|
+
getAccountIndex(account: Address): Promise<bigint>;
|
|
11
|
+
hasAccount(account: Address): Promise<boolean>;
|
|
12
|
+
findAccountIndex(account: Address): Promise<bigint | null>;
|
|
13
|
+
getTraderBuilderNonce(owner: Address, builder: Address): Promise<bigint>;
|
|
14
|
+
getAccountsCount(maxScan?: bigint): Promise<bigint>;
|
|
15
|
+
getAccounts(offset: bigint, limit: bigint): Promise<Address[]>;
|
|
16
|
+
getConfig(): Promise<{
|
|
17
|
+
implementation: Address;
|
|
18
|
+
owner: Address;
|
|
19
|
+
pendingOwner: Address;
|
|
20
|
+
usdc: Address;
|
|
21
|
+
vault: Address;
|
|
22
|
+
}>;
|
|
23
|
+
}
|
package/dist/factory.js
ADDED
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
import { factoryAbi } from "./abi/factory.js";
|
|
2
|
+
export class FactoryModule {
|
|
3
|
+
publicClient;
|
|
4
|
+
factoryAddress;
|
|
5
|
+
constructor(publicClient, factoryAddress) {
|
|
6
|
+
this.publicClient = publicClient;
|
|
7
|
+
this.factoryAddress = factoryAddress;
|
|
8
|
+
}
|
|
9
|
+
isOutOfBoundsError(error) {
|
|
10
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
11
|
+
return /out of bounds|execution reverted|returned no data|position out of bounds/i.test(message);
|
|
12
|
+
}
|
|
13
|
+
async accountExistsAt(index) {
|
|
14
|
+
try {
|
|
15
|
+
await this.getAccountAt(index);
|
|
16
|
+
return true;
|
|
17
|
+
}
|
|
18
|
+
catch (error) {
|
|
19
|
+
if (this.isOutOfBoundsError(error))
|
|
20
|
+
return false;
|
|
21
|
+
throw error;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
async predictAddress(owner, builder) {
|
|
25
|
+
return this.publicClient.readContract({
|
|
26
|
+
address: this.factoryAddress,
|
|
27
|
+
abi: factoryAbi,
|
|
28
|
+
functionName: "predictFundedAccountAddress",
|
|
29
|
+
args: [owner, builder],
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
async getAccountAt(index) {
|
|
33
|
+
return this.publicClient.readContract({
|
|
34
|
+
address: this.factoryAddress,
|
|
35
|
+
abi: factoryAbi,
|
|
36
|
+
functionName: "allAccounts",
|
|
37
|
+
args: [index],
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
async getAccountIndex(account) {
|
|
41
|
+
return this.publicClient.readContract({
|
|
42
|
+
address: this.factoryAddress,
|
|
43
|
+
abi: factoryAbi,
|
|
44
|
+
functionName: "allAccountsIndex",
|
|
45
|
+
args: [account],
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
async hasAccount(account) {
|
|
49
|
+
try {
|
|
50
|
+
const index = await this.getAccountIndex(account);
|
|
51
|
+
const candidate = await this.getAccountAt(index);
|
|
52
|
+
return candidate.toLowerCase() === account.toLowerCase();
|
|
53
|
+
}
|
|
54
|
+
catch {
|
|
55
|
+
return false;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
async findAccountIndex(account) {
|
|
59
|
+
const index = await this.getAccountIndex(account);
|
|
60
|
+
const candidate = await this.getAccountAt(index).catch(() => null);
|
|
61
|
+
if (!candidate || candidate.toLowerCase() !== account.toLowerCase())
|
|
62
|
+
return null;
|
|
63
|
+
return index;
|
|
64
|
+
}
|
|
65
|
+
async getTraderBuilderNonce(owner, builder) {
|
|
66
|
+
return this.publicClient.readContract({
|
|
67
|
+
address: this.factoryAddress,
|
|
68
|
+
abi: factoryAbi,
|
|
69
|
+
functionName: "traderBuilderNonce",
|
|
70
|
+
args: [owner, builder],
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
async getAccountsCount(maxScan = 10000n) {
|
|
74
|
+
if (!(await this.accountExistsAt(0n)))
|
|
75
|
+
return 0n;
|
|
76
|
+
let lo = 0n;
|
|
77
|
+
let hi = 1n;
|
|
78
|
+
while (hi < maxScan && await this.accountExistsAt(hi)) {
|
|
79
|
+
lo = hi;
|
|
80
|
+
hi *= 2n;
|
|
81
|
+
}
|
|
82
|
+
if (hi >= maxScan && await this.accountExistsAt(hi)) {
|
|
83
|
+
throw new Error(`Factory account count exceeds scan limit ${maxScan}`);
|
|
84
|
+
}
|
|
85
|
+
while (lo + 1n < hi) {
|
|
86
|
+
const mid = (lo + hi) / 2n;
|
|
87
|
+
if (await this.accountExistsAt(mid)) {
|
|
88
|
+
lo = mid;
|
|
89
|
+
}
|
|
90
|
+
else {
|
|
91
|
+
hi = mid;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
return lo + 1n;
|
|
95
|
+
}
|
|
96
|
+
async getAccounts(offset, limit) {
|
|
97
|
+
if (limit <= 0n)
|
|
98
|
+
return [];
|
|
99
|
+
const contracts = [];
|
|
100
|
+
for (let i = 0n; i < limit; i++) {
|
|
101
|
+
contracts.push({
|
|
102
|
+
address: this.factoryAddress,
|
|
103
|
+
abi: factoryAbi,
|
|
104
|
+
functionName: "allAccounts",
|
|
105
|
+
args: [offset + i],
|
|
106
|
+
});
|
|
107
|
+
}
|
|
108
|
+
const results = await this.publicClient.multicall({
|
|
109
|
+
contracts,
|
|
110
|
+
allowFailure: true,
|
|
111
|
+
});
|
|
112
|
+
const accounts = [];
|
|
113
|
+
for (const result of results) {
|
|
114
|
+
if (result.status !== "success")
|
|
115
|
+
break;
|
|
116
|
+
accounts.push(result.result);
|
|
117
|
+
}
|
|
118
|
+
return accounts;
|
|
119
|
+
}
|
|
120
|
+
async getConfig() {
|
|
121
|
+
const contract = { address: this.factoryAddress, abi: factoryAbi };
|
|
122
|
+
const results = await this.publicClient.multicall({
|
|
123
|
+
contracts: [
|
|
124
|
+
{ ...contract, functionName: "implementation" },
|
|
125
|
+
{ ...contract, functionName: "owner" },
|
|
126
|
+
{ ...contract, functionName: "pendingOwner" },
|
|
127
|
+
{ ...contract, functionName: "usdc" },
|
|
128
|
+
{ ...contract, functionName: "vault" },
|
|
129
|
+
],
|
|
130
|
+
});
|
|
131
|
+
return {
|
|
132
|
+
implementation: results[0].result,
|
|
133
|
+
owner: results[1].result,
|
|
134
|
+
pendingOwner: results[2].result,
|
|
135
|
+
usdc: results[3].result,
|
|
136
|
+
vault: results[4].result,
|
|
137
|
+
};
|
|
138
|
+
}
|
|
139
|
+
}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export { ProportionSDK } from "./sdk.js";
|
|
2
|
+
export { VaultModule } from "./vault.js";
|
|
3
|
+
export { AccountModule } from "./account.js";
|
|
4
|
+
export { FactoryModule } from "./factory.js";
|
|
5
|
+
export { IndexerModule } from "./indexer.js";
|
|
6
|
+
export * from "./types.js";
|
|
7
|
+
export * from "./constants.js";
|
|
8
|
+
export * from "./utils.js";
|
|
9
|
+
export { mainVaultAbi } from "./abi/mainVault.js";
|
|
10
|
+
export { fundedAccountAbi } from "./abi/fundedAccount.js";
|
|
11
|
+
export { factoryAbi } from "./abi/factory.js";
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
// Main
|
|
2
|
+
export { ProportionSDK } from "./sdk.js";
|
|
3
|
+
// Modules
|
|
4
|
+
export { VaultModule } from "./vault.js";
|
|
5
|
+
export { AccountModule } from "./account.js";
|
|
6
|
+
export { FactoryModule } from "./factory.js";
|
|
7
|
+
export { IndexerModule } from "./indexer.js";
|
|
8
|
+
// Core
|
|
9
|
+
export * from "./types.js";
|
|
10
|
+
export * from "./constants.js";
|
|
11
|
+
export * from "./utils.js";
|
|
12
|
+
export { mainVaultAbi } from "./abi/mainVault.js";
|
|
13
|
+
export { fundedAccountAbi } from "./abi/fundedAccount.js";
|
|
14
|
+
export { factoryAbi } from "./abi/factory.js";
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import type { GqlAccount, GqlAccountEvent, GqlAllowedPerp, GqlBuilder, GqlCheckpoint, GqlConfigChange, GqlFactoryConfig, GqlDelegate, GqlDeposit, GqlLiquidityProviderDayData, GqlLP, GqlMainVaultConfig, GqlProfitWithdrawal, GqlProtocolConfig, GqlSubscriptionPayment, GqlVault, GqlVaultDayData, GqlWithdrawal, ConfigChangeFilters, IndexerAccountStateLabel, Pagination, Unsubscribe, WebSocketConstructor } from "./types.js";
|
|
2
|
+
export declare class IndexerModule {
|
|
3
|
+
private graphqlUrl;
|
|
4
|
+
private graphqlWsUrl?;
|
|
5
|
+
private transports;
|
|
6
|
+
private ws;
|
|
7
|
+
private wsId;
|
|
8
|
+
private subscriptions;
|
|
9
|
+
private reconnectTimer;
|
|
10
|
+
private reconnectDelay;
|
|
11
|
+
constructor(graphqlUrl: string, graphqlWsUrl?: string | undefined, transports?: {
|
|
12
|
+
fetchFn?: typeof fetch;
|
|
13
|
+
webSocketCtor?: WebSocketConstructor;
|
|
14
|
+
});
|
|
15
|
+
private static readonly PAGE_SIZE;
|
|
16
|
+
private static readonly VAULT_FIELDS;
|
|
17
|
+
private static readonly ACCOUNT_FIELDS;
|
|
18
|
+
private static readonly MAIN_VAULT_CONFIG_FIELDS;
|
|
19
|
+
private static readonly FACTORY_CONFIG_FIELDS;
|
|
20
|
+
private static readonly CONFIG_CHANGE_FIELDS;
|
|
21
|
+
private static readonly VAULT_DAY_DATA_FIELDS;
|
|
22
|
+
private static readonly LP_DAY_DATA_FIELDS;
|
|
23
|
+
private resolveVaultAddress;
|
|
24
|
+
private resolveFactoryAddress;
|
|
25
|
+
private query;
|
|
26
|
+
getVault(vaultAddress?: string): Promise<GqlVault | null>;
|
|
27
|
+
getLP(address: string): Promise<GqlLP | null>;
|
|
28
|
+
getLPDeposits(address: string, p?: Pagination): Promise<GqlDeposit[]>;
|
|
29
|
+
getLPWithdrawals(address: string, p?: Pagination): Promise<GqlWithdrawal[]>;
|
|
30
|
+
getBuilder(address: string, vaultAddress?: string): Promise<GqlBuilder | null>;
|
|
31
|
+
getDelegates(builder: string, vaultAddress?: string): Promise<GqlDelegate[]>;
|
|
32
|
+
getAccount(address: string): Promise<GqlAccount | null>;
|
|
33
|
+
getAccountsByOwner(owner: string): Promise<GqlAccount[]>;
|
|
34
|
+
getAccountsByBuilder(builder: string, vaultAddress?: string): Promise<GqlAccount[]>;
|
|
35
|
+
getAccountsByState(state: IndexerAccountStateLabel): Promise<GqlAccount[]>;
|
|
36
|
+
getAccountsByStates(states: IndexerAccountStateLabel[]): Promise<GqlAccount[]>;
|
|
37
|
+
getAccountsUpdatedSince(since: string): Promise<GqlAccount[]>;
|
|
38
|
+
getCheckpoints(account: string, p?: Pagination): Promise<GqlCheckpoint[]>;
|
|
39
|
+
getWithdrawals(account: string, p?: Pagination): Promise<GqlProfitWithdrawal[]>;
|
|
40
|
+
getSubscriptionPayments(account: string, p?: Pagination): Promise<GqlSubscriptionPayment[]>;
|
|
41
|
+
getEvents(account: string, p?: Pagination): Promise<GqlAccountEvent[]>;
|
|
42
|
+
getEventsByType(type: string, limit?: number): Promise<GqlAccountEvent[]>;
|
|
43
|
+
getProtocolConfig(): Promise<GqlProtocolConfig | null>;
|
|
44
|
+
getMainVaultConfig(vaultAddress?: string): Promise<GqlMainVaultConfig | null>;
|
|
45
|
+
getFactoryConfig(factoryAddress?: string): Promise<GqlFactoryConfig | null>;
|
|
46
|
+
getConfigChanges(filters?: ConfigChangeFilters): Promise<GqlConfigChange[]>;
|
|
47
|
+
getVaultDayData(vaultAddress?: string, p?: Pagination): Promise<GqlVaultDayData[]>;
|
|
48
|
+
getLPDayData(address: string, p?: Pagination): Promise<GqlLiquidityProviderDayData[]>;
|
|
49
|
+
getAllowedPerps(vaultAddress?: string): Promise<GqlAllowedPerp[]>;
|
|
50
|
+
private ensureWs;
|
|
51
|
+
private subscribe;
|
|
52
|
+
subscribeActiveAccounts(cb: (accounts: GqlAccount[]) => void): Unsubscribe;
|
|
53
|
+
subscribeAccount(address: string, cb: (account: GqlAccount) => void): Unsubscribe;
|
|
54
|
+
subscribeAccountEvents(address: string, cb: (events: GqlAccountEvent[]) => void): Unsubscribe;
|
|
55
|
+
subscribeStateChanges(cb: (accounts: GqlAccount[]) => void): Unsubscribe;
|
|
56
|
+
disconnect(): void;
|
|
57
|
+
}
|