@kehtus/proportion-sdk 0.1.2 → 0.1.3

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.
Files changed (89) hide show
  1. package/LICENSE +21 -0
  2. package/dist/abi/factory.d.ts +1 -0
  3. package/dist/abi/factory.d.ts.map +1 -0
  4. package/dist/abi/factory.js +1 -0
  5. package/dist/abi/factory.js.map +1 -0
  6. package/dist/abi/forwarder.d.ts +1 -0
  7. package/dist/abi/forwarder.d.ts.map +1 -0
  8. package/dist/abi/forwarder.js +1 -0
  9. package/dist/abi/forwarder.js.map +1 -0
  10. package/dist/abi/fundedAccount.d.ts +1 -0
  11. package/dist/abi/fundedAccount.d.ts.map +1 -0
  12. package/dist/abi/fundedAccount.js +1 -0
  13. package/dist/abi/fundedAccount.js.map +1 -0
  14. package/dist/abi/mainVault.d.ts +198 -16
  15. package/dist/abi/mainVault.d.ts.map +1 -0
  16. package/dist/abi/mainVault.js +253 -19
  17. package/dist/abi/mainVault.js.map +1 -0
  18. package/dist/account.d.ts +3 -2
  19. package/dist/account.d.ts.map +1 -0
  20. package/dist/account.js +46 -43
  21. package/dist/account.js.map +1 -0
  22. package/dist/base.d.ts +9 -0
  23. package/dist/base.d.ts.map +1 -0
  24. package/dist/base.js +19 -0
  25. package/dist/base.js.map +1 -0
  26. package/dist/constants.d.ts +5 -4
  27. package/dist/constants.d.ts.map +1 -0
  28. package/dist/constants.js +5 -4
  29. package/dist/constants.js.map +1 -0
  30. package/dist/factory.d.ts +1 -0
  31. package/dist/factory.d.ts.map +1 -0
  32. package/dist/factory.js +56 -10
  33. package/dist/factory.js.map +1 -0
  34. package/dist/index.d.ts +1 -0
  35. package/dist/index.d.ts.map +1 -0
  36. package/dist/index.js +1 -0
  37. package/dist/index.js.map +1 -0
  38. package/dist/indexer.d.ts +8 -3
  39. package/dist/indexer.d.ts.map +1 -0
  40. package/dist/indexer.js +81 -136
  41. package/dist/indexer.js.map +1 -0
  42. package/dist/sdk.d.ts +1 -0
  43. package/dist/sdk.d.ts.map +1 -0
  44. package/dist/sdk.js +1 -0
  45. package/dist/sdk.js.map +1 -0
  46. package/dist/types.d.ts +5 -0
  47. package/dist/types.d.ts.map +1 -0
  48. package/dist/types.js +1 -0
  49. package/dist/types.js.map +1 -0
  50. package/dist/utils.d.ts +8 -0
  51. package/dist/utils.d.ts.map +1 -0
  52. package/dist/utils.js +10 -0
  53. package/dist/utils.js.map +1 -0
  54. package/dist/vault.d.ts +7 -4
  55. package/dist/vault.d.ts.map +1 -0
  56. package/dist/vault.js +76 -51
  57. package/dist/vault.js.map +1 -0
  58. package/package.json +12 -1
  59. package/arch.md +0 -455
  60. package/dist/__tests__/account.test.d.ts +0 -1
  61. package/dist/__tests__/account.test.js +0 -36
  62. package/dist/__tests__/indexer.test.d.ts +0 -1
  63. package/dist/__tests__/indexer.test.js +0 -230
  64. package/dist/__tests__/lifecycle.test.d.ts +0 -1
  65. package/dist/__tests__/lifecycle.test.js +0 -186
  66. package/dist/__tests__/reads.test.d.ts +0 -1
  67. package/dist/__tests__/reads.test.js +0 -184
  68. package/dist/__tests__/utils.test.d.ts +0 -1
  69. package/dist/__tests__/utils.test.js +0 -185
  70. package/src/__tests__/account.test.ts +0 -40
  71. package/src/__tests__/indexer.test.ts +0 -255
  72. package/src/__tests__/lifecycle.test.ts +0 -231
  73. package/src/__tests__/reads.test.ts +0 -208
  74. package/src/__tests__/utils.test.ts +0 -245
  75. package/src/abi/factory.ts +0 -417
  76. package/src/abi/forwarder.ts +0 -373
  77. package/src/abi/fundedAccount.ts +0 -1296
  78. package/src/abi/mainVault.ts +0 -1852
  79. package/src/account.ts +0 -325
  80. package/src/constants.ts +0 -51
  81. package/src/factory.ts +0 -157
  82. package/src/index.ts +0 -16
  83. package/src/indexer.ts +0 -636
  84. package/src/sdk.ts +0 -93
  85. package/src/types.ts +0 -421
  86. package/src/utils.ts +0 -143
  87. package/src/vault.ts +0 -479
  88. package/tsconfig.json +0 -19
  89. package/vitest.config.ts +0 -8
package/src/sdk.ts DELETED
@@ -1,93 +0,0 @@
1
- import { createPublicClient, http, type Address } from "viem";
2
- import { ADDRESSES, hyperEvm } from "./constants.js";
3
- import { VaultModule } from "./vault.js";
4
- import { AccountModule } from "./account.js";
5
- import { FactoryModule } from "./factory.js";
6
- import { IndexerModule } from "./indexer.js";
7
- import { mainVaultAbi } from "./abi/mainVault.js";
8
- import type { SDKConfig } from "./types.js";
9
-
10
- export class ProportionSDK {
11
- readonly vault: VaultModule;
12
- readonly account: AccountModule;
13
- readonly factory: FactoryModule;
14
- readonly indexer: IndexerModule;
15
-
16
- /**
17
- * Async factory: resolves addresses from explicit config > ENV > ProtocolConfig > hardcoded constants.
18
- *
19
- * ProtocolConfig is only a convenience fallback from the indexer. It is not the source of truth
20
- * for protocol configuration and should not replace explicit deployment config in applications.
21
- *
22
- * ENV vars: PROPORTION_VAULT_ADDRESS, PROPORTION_FACTORY_ADDRESS, PROPORTION_USDC_ADDRESS
23
- */
24
- static async create(config: SDKConfig): Promise<ProportionSDK> {
25
- const resolved: Record<string, string> = { ...config.addresses };
26
-
27
- // ENV fallbacks (Node; safely ignored in browsers)
28
- const env = typeof process !== "undefined" ? process.env : undefined;
29
- if (!resolved.MAIN_VAULT && env?.PROPORTION_VAULT_ADDRESS) resolved.MAIN_VAULT = env.PROPORTION_VAULT_ADDRESS;
30
- if (!resolved.FACTORY && env?.PROPORTION_FACTORY_ADDRESS) resolved.FACTORY = env.PROPORTION_FACTORY_ADDRESS;
31
- if (!resolved.USDC && env?.PROPORTION_USDC_ADDRESS) resolved.USDC = env.PROPORTION_USDC_ADDRESS;
32
-
33
- // Fetch missing addresses from the indexer only as a convenience fallback.
34
- // Primary address sources remain explicit config.addresses and ENV.
35
- if (!resolved.MAIN_VAULT || !resolved.FACTORY) {
36
- try {
37
- const indexer = new IndexerModule(config.graphqlUrl, undefined, {
38
- fetchFn: config.fetchFn,
39
- webSocketCtor: config.webSocketCtor,
40
- });
41
- const protocol = await indexer.getProtocolConfig();
42
- if (protocol) {
43
- if (!resolved.MAIN_VAULT && protocol.vaultAddress) resolved.MAIN_VAULT = protocol.vaultAddress;
44
- if (!resolved.FACTORY && protocol.factoryAddress) resolved.FACTORY = protocol.factoryAddress;
45
- }
46
- } catch { /* fall back to hardcoded constants */ }
47
- }
48
-
49
- if (resolved.MAIN_VAULT && !resolved.USDC) {
50
- try {
51
- const publicClient = createPublicClient({
52
- chain: hyperEvm,
53
- transport: http(config.rpcUrl ?? hyperEvm.rpcUrls.default.http[0]),
54
- });
55
- resolved.USDC = await publicClient.readContract({
56
- address: resolved.MAIN_VAULT as Address,
57
- abi: mainVaultAbi,
58
- functionName: "usdc",
59
- });
60
- } catch { /* fall back to hardcoded constants */ }
61
- }
62
-
63
- return new ProportionSDK({ ...config, addresses: resolved });
64
- }
65
-
66
- constructor(config: SDKConfig) {
67
- const addresses = {
68
- vault: (config.addresses?.MAIN_VAULT ?? ADDRESSES.MAIN_VAULT) as Address,
69
- usdc: (config.addresses?.USDC ?? ADDRESSES.USDC) as Address,
70
- factory: (config.addresses?.FACTORY ?? ADDRESSES.FACTORY) as Address,
71
- };
72
-
73
- const publicClient = createPublicClient({
74
- chain: hyperEvm,
75
- transport: http(config.rpcUrl ?? hyperEvm.rpcUrls.default.http[0]),
76
- });
77
-
78
- this.vault = new VaultModule(publicClient, config.walletClient, hyperEvm, {
79
- vault: addresses.vault,
80
- usdc: addresses.usdc,
81
- });
82
- this.account = new AccountModule(publicClient, config.walletClient, hyperEvm);
83
- this.factory = new FactoryModule(publicClient, addresses.factory);
84
- this.indexer = new IndexerModule(config.graphqlUrl, config.graphqlWsUrl, {
85
- fetchFn: config.fetchFn,
86
- webSocketCtor: config.webSocketCtor,
87
- });
88
- }
89
-
90
- disconnect(): void {
91
- this.indexer.disconnect();
92
- }
93
- }
package/src/types.ts DELETED
@@ -1,421 +0,0 @@
1
- import type { Address, WalletClient } from "viem";
2
- import type { ADDRESSES } from "./constants.js";
3
-
4
- // ── Config ──────────────────────────────────────────
5
- export interface SDKConfig {
6
- rpcUrl?: string;
7
- graphqlUrl: string;
8
- graphqlWsUrl?: string;
9
- walletClient?: WalletClient;
10
- fetchFn?: typeof fetch;
11
- webSocketCtor?: WebSocketConstructor;
12
- addresses?: Partial<typeof ADDRESSES>;
13
- }
14
-
15
- export interface WebSocketLike {
16
- readyState: number;
17
- send(data: string): void;
18
- close(): void;
19
- onopen: ((this: unknown, ...args: unknown[]) => unknown) | null;
20
- onmessage: ((this: unknown, event: { data: unknown }, ...args: unknown[]) => unknown) | null;
21
- onclose: ((this: unknown, ...args: unknown[]) => unknown) | null;
22
- onerror: ((this: unknown, ...args: unknown[]) => unknown) | null;
23
- }
24
-
25
- export interface WebSocketConstructor {
26
- new (url: string, protocols?: string | string[]): WebSocketLike;
27
- readonly OPEN: number;
28
- }
29
-
30
- // ── Enums ───────────────────────────────────────────
31
- export enum AccountState {
32
- Uninitialized,
33
- Initialized,
34
- Active,
35
- WithdrawalPending,
36
- Closing,
37
- Returning,
38
- Closed,
39
- }
40
-
41
- export type AccountStateLabel =
42
- | "UNINITIALIZED"
43
- | "INITIALIZED"
44
- | "ACTIVE"
45
- | "WITHDRAWAL_PENDING"
46
- | "CLOSING"
47
- | "RETURNING"
48
- | "CLOSED";
49
-
50
- export type IndexerAccountStateLabel =
51
- | "INITIALIZED"
52
- | "ACTIVE"
53
- | "WITHDRAWAL_PENDING"
54
- | "CLOSING"
55
- | "RETURNING"
56
- | "CLOSED";
57
-
58
- export type BreachType =
59
- | "TRAILING_DRAWDOWN"
60
- | "DAILY_DRAWDOWN"
61
- | "POSITION_LEVERAGE"
62
- | "UNAUTHORIZED_ASSET"
63
- | "SUBSCRIPTION_EXPIRED";
64
-
65
- // ── On-chain return types ───────────────────────────
66
- export interface VaultStats {
67
- totalAssets: bigint;
68
- sharePrice: bigint;
69
- utilizationBps: bigint;
70
- availableForAllocation: bigint;
71
- maxAccountSize: bigint;
72
- remainingCap: bigint;
73
- paused: boolean;
74
- feeMultiplier: number;
75
- subscriptionFeeMultiplier: number;
76
- totalShares: bigint;
77
- totalAllocated: bigint;
78
- owner: Address;
79
- pendingOwner: Address;
80
- relayer: Address;
81
- protocolFeeReceiver: Address;
82
- maxCap: bigint;
83
- hypeForSpot: bigint;
84
- factory: Address;
85
- minBuilderShares: bigint;
86
- builderLeverage: bigint;
87
- protocolFeeBps: bigint;
88
- minAccountSize: bigint;
89
- maxAccountSizeLimit: bigint;
90
- minDrawdownBps: number;
91
- maxDrawdownBps: number;
92
- maxUtilizationBps: bigint;
93
- maxSingleAccountBps: bigint;
94
- dailyDdDiscountBps: number;
95
- }
96
-
97
- export interface LPPosition {
98
- shares: bigint;
99
- sharesValue: bigint;
100
- withdrawableShares: bigint;
101
- }
102
-
103
- export interface BuilderInfo {
104
- active: boolean;
105
- activeFunded: bigint;
106
- availableFunded: bigint;
107
- }
108
-
109
- export interface AccountDetails {
110
- address: Address;
111
- state: AccountState;
112
- owner: Address;
113
- builder: Address;
114
- accountSize: bigint;
115
- drawdownBps: number;
116
- dailyDrawdownEnabled: boolean;
117
- subscriptionFeeMultiplier: number;
118
- highWaterMark: bigint;
119
- dayStartValue: bigint;
120
- activatedAt: bigint;
121
- subscriptionPaidUntil: bigint;
122
- subscriptionCancelled: boolean;
123
- pendingSubscriptionFee: bigint;
124
- apiWallet: Address;
125
- checkpointIndex: number;
126
- totalCheckpoints: number;
127
- profitableDaysCount: number;
128
- lastCheckpointDay: bigint;
129
- closingInitiatedAt: number;
130
- returnInitiatedAt: number;
131
- pendingWithdrawal: { profit: bigint };
132
- trailingFloor: bigint;
133
- dailyFloor: bigint;
134
- subscriptionFee: bigint;
135
- isSubscriptionActive: boolean;
136
- canWithdrawProfit: boolean;
137
- checkpoints: Array<{
138
- accountValue: bigint;
139
- timestamp: number;
140
- profitable: boolean;
141
- }>;
142
- }
143
-
144
- // ── GraphQL entity types ────────────────────────────
145
- export interface GqlVault {
146
- id: string;
147
- address: string;
148
- totalDeposits: string;
149
- totalWithdrawals: string;
150
- totalActivationFees: string;
151
- cumulativeActivationFeesToVault: string;
152
- totalAllocated: string;
153
- totalShares: string;
154
- cumulativeProfitShares: string;
155
- cumulativeCancelledProfit: string;
156
- cumulativeSubscriptionFees: string;
157
- cumulativeProtocolFeesRouted: string;
158
- cumulativeHypercoreFees: string;
159
- cumulativeAccountGains: string;
160
- cumulativeAccountLosses: string;
161
- cumulativeRescuedFunds: string;
162
- totalAccountsActivated: number;
163
- totalAccountsActive: number;
164
- totalAccountsClosed: number;
165
- paused: boolean;
166
- subscriptionFeeMultiplier: number;
167
- protocolFeeBps: number;
168
- protocolFeeReceiver: string | null;
169
- updatedAt: string;
170
- }
171
-
172
- export interface GqlLP {
173
- id: string;
174
- totalDeposited: string;
175
- totalWithdrawn: string;
176
- depositCount: number;
177
- withdrawCount: number;
178
- lastActionAt: string;
179
- }
180
-
181
- export interface GqlBuilder {
182
- id: string;
183
- address: string;
184
- vaultAddress: string;
185
- active: boolean;
186
- totalAccountsActivated: number;
187
- totalAccountsClosed: number;
188
- activeAccounts: number;
189
- registeredAt: string;
190
- deactivatedAt: string | null;
191
- }
192
-
193
- export interface GqlAccount {
194
- id: string;
195
- owner: string;
196
- builder: { id: string; address: string; vaultAddress: string };
197
- vaultAddress: string;
198
- factoryAddress: string;
199
- state: IndexerAccountStateLabel;
200
- accountSize: string;
201
- drawdownBps: number;
202
- dailyDrawdownEnabled: boolean;
203
- activationFee: string;
204
- highWaterMark: string;
205
- profitableDaysCount: number;
206
- lastCheckpointDay: string;
207
- totalCheckpoints: number;
208
- subscriptionPaidUntil: string;
209
- subscriptionCancelled: boolean;
210
- pendingSubscriptionFee: string;
211
- subscriptionFeeMultiplier: number;
212
- dayStartValue: string;
213
- apiWallet: string | null;
214
- createdAt: string;
215
- activatedAt: string | null;
216
- closingInitiatedAt: string | null;
217
- returnInitiatedAt: string | null;
218
- closedAt: string | null;
219
- returnedAmount: string | null;
220
- breachType: BreachType | null;
221
- breachValue: string | null;
222
- breachFloor: string | null;
223
- closePendingSubFee: string | null;
224
- closePendingProfit: string | null;
225
- lastWithdrawalId: string | null;
226
- updatedAt: string;
227
- }
228
-
229
- export interface GqlCheckpoint {
230
- id: string;
231
- dayNumber: string;
232
- accountValue: string;
233
- previousValue: string;
234
- profitable: boolean;
235
- profitableDaysCount: number;
236
- timestamp: string;
237
- }
238
-
239
- export interface GqlProfitWithdrawal {
240
- id: string;
241
- profit: string;
242
- ownerAmount: string;
243
- vaultAmount: string;
244
- protocolAmount: string;
245
- status: "REQUESTED" | "CLAIMED" | "CANCELLED";
246
- requestedAt: string;
247
- claimedAt: string | null;
248
- cancelledAt: string | null;
249
- }
250
-
251
- export interface GqlSubscriptionPayment {
252
- id: string;
253
- amount: string;
254
- paidUntil: string;
255
- timestamp: string;
256
- }
257
-
258
- export interface GqlDeposit {
259
- id: string;
260
- lp: { id: string };
261
- amount: string;
262
- sharesReceived: string;
263
- timestamp: string;
264
- blockNumber?: number;
265
- txHash: string;
266
- }
267
-
268
- export interface GqlWithdrawal {
269
- id: string;
270
- lp: { id: string };
271
- amount: string;
272
- sharesBurned: string;
273
- timestamp: string;
274
- blockNumber?: number;
275
- txHash: string;
276
- }
277
-
278
- export interface GqlAccountEvent {
279
- id: string;
280
- eventType: string;
281
- data: string;
282
- timestamp: string;
283
- blockNumber: number;
284
- txHash: string;
285
- }
286
-
287
- export interface GqlAllowedPerp {
288
- id: string;
289
- vaultAddress: string;
290
- perpIndex: number;
291
- allowed: boolean;
292
- }
293
-
294
- export interface GqlDelegate {
295
- id: string;
296
- vaultAddress: string;
297
- delegateAddress: string;
298
- builderAddress: string;
299
- }
300
-
301
- export interface GqlProtocolConfig {
302
- id: string;
303
- vaultAddress: string;
304
- factoryAddress: string;
305
- updatedAt: string;
306
- }
307
-
308
- export type GqlConfigContractType = "MainVault" | "FundedAccountFactory";
309
-
310
- export interface GqlMainVaultConfig {
311
- id: string;
312
- vaultAddress: string;
313
- factoryAddress: string;
314
- owner: string;
315
- pendingOwner: string;
316
- relayer: string;
317
- paused: boolean;
318
- protocolFeeReceiver: string;
319
- feeMultiplier: number;
320
- subscriptionFeeMultiplier: number;
321
- dailyDdDiscountBps: number;
322
- minBuilderShares: string;
323
- builderLeverage: string;
324
- protocolFeeBps: number;
325
- minAccountSize: string;
326
- maxAccountSize: string;
327
- minDrawdownBps: number;
328
- maxDrawdownBps: number;
329
- maxUtilizationBps: number;
330
- maxSingleAccountBps: number;
331
- hypeForSpot: string;
332
- maxCap: string;
333
- createdAt: string;
334
- updatedAt: string;
335
- }
336
-
337
- export interface GqlFactoryConfig {
338
- id: string;
339
- factoryAddress: string;
340
- vaultAddress: string;
341
- owner: string;
342
- pendingOwner: string;
343
- createdAt: string;
344
- updatedAt: string;
345
- }
346
-
347
- export interface GqlConfigChange {
348
- id: string;
349
- contractAddress: string;
350
- contractType: GqlConfigContractType;
351
- field: string;
352
- oldValue: string;
353
- newValue: string;
354
- blockNumber: number;
355
- timestamp: string;
356
- txHash: string;
357
- }
358
-
359
- export interface GqlVaultDayData {
360
- id: string;
361
- date: number;
362
- dayNumber: number;
363
- evmBalance: string;
364
- totalAllocated: string;
365
- totalAssets: string;
366
- totalShares: string;
367
- sharePrice: string;
368
- dailyDeposits: string;
369
- dailyWithdrawals: string;
370
- dailyNetLpFlow: string;
371
- dailyActivationFees: string;
372
- dailyActivationFeesToVault: string;
373
- dailyProfitShares: string;
374
- dailyCancelledProfit: string;
375
- dailySubscriptionFees: string;
376
- dailyProtocolFeesRouted: string;
377
- dailyHypercoreFees: string;
378
- dailyRescuedFunds: string;
379
- dailyAccountReturnAmount: string;
380
- dailyAccountPrincipalReturned: string;
381
- dailyAccountGains: string;
382
- dailyAccountLosses: string;
383
- dailyPerformancePnl: string;
384
- totalAccountsActivated: number;
385
- totalAccountsActive: number;
386
- totalAccountsClosed: number;
387
- accountsActivatedToday: number;
388
- accountsClosedToday: number;
389
- navChange24h: string;
390
- sharePriceChange24h: string;
391
- return24hBps: number;
392
- paused: boolean;
393
- updatedAt: string;
394
- }
395
-
396
- export interface GqlLiquidityProviderDayData {
397
- id: string;
398
- lp: { id: string };
399
- date: number;
400
- dayNumber: number;
401
- shares: string;
402
- sharesValue: string;
403
- dailyDeposits: string;
404
- dailyWithdrawals: string;
405
- depositCount: number;
406
- withdrawCount: number;
407
- }
408
-
409
- // ── Helpers ─────────────────────────────────────────
410
- export interface Pagination {
411
- limit?: number;
412
- offset?: number;
413
- }
414
-
415
- export interface ConfigChangeFilters extends Pagination {
416
- contractAddress?: string;
417
- contractType?: GqlConfigContractType;
418
- field?: string;
419
- }
420
-
421
- export type Unsubscribe = () => void;
package/src/utils.ts DELETED
@@ -1,143 +0,0 @@
1
- import {
2
- BPS,
3
- DAILY_DD_DISCOUNT_BPS,
4
- DECIMALS_MULTIPLIER,
5
- OWNER_PROFIT_BPS,
6
- PROTOCOL_PROFIT_BPS,
7
- USDC_DECIMALS,
8
- } from "./constants.js";
9
- import { AccountState, type AccountStateLabel } from "./types.js";
10
-
11
- // ── Decimals ────────────────────────────────────────
12
-
13
- export function fromUsdc(amount: bigint): number {
14
- return Number(amount) / 10 ** USDC_DECIMALS;
15
- }
16
-
17
- export function toUsdc(amount: number): bigint {
18
- return BigInt(Math.round(amount * 10 ** USDC_DECIMALS));
19
- }
20
-
21
- export function from8Dec(value: bigint): number {
22
- return Number(value) / 1e8;
23
- }
24
-
25
- export function toUsdc6(value8dec: bigint): bigint {
26
- return value8dec / DECIMALS_MULTIPLIER;
27
- }
28
-
29
- export function to8Dec(value6dec: bigint): bigint {
30
- return value6dec * DECIMALS_MULTIPLIER;
31
- }
32
-
33
- export function formatUsd(amount: bigint, dec: number = USDC_DECIMALS): string {
34
- const num = Number(amount) / 10 ** dec;
35
- return "$" + num.toLocaleString("en-US", { minimumFractionDigits: 2, maximumFractionDigits: 2 });
36
- }
37
-
38
- // ── Drawdown (all values in 6dec — matching on-chain HWM/dayStartValue) ──
39
-
40
- export function trailingFloor(hwm: bigint, drawdownBps: number): bigint {
41
- return hwm - (hwm * BigInt(drawdownBps)) / BPS;
42
- }
43
-
44
- export function dailyFloor(dayStartValue: bigint, drawdownBps: number): bigint {
45
- const dailyBps = BigInt(drawdownBps) / 2n;
46
- return dayStartValue - (dayStartValue * dailyBps) / BPS;
47
- }
48
-
49
- export function isTrailingBreached(value: bigint, hwm: bigint, bps: number): boolean {
50
- return value < trailingFloor(hwm, bps);
51
- }
52
-
53
- export function isDailyBreached(value: bigint, dsv: bigint, bps: number): boolean {
54
- return value < dailyFloor(dsv, bps);
55
- }
56
-
57
- // ── Fees ────────────────────────────────────────────
58
-
59
- const FEE_DIVISOR = 1_000_000n;
60
- const USDC_UNIT = 1_000_000n;
61
-
62
- function roundUpUsdc(fee: bigint): bigint {
63
- return ((fee + USDC_UNIT - 1n) / USDC_UNIT) * USDC_UNIT;
64
- }
65
-
66
- function applyDailyDiscount(fee: bigint, discountBps: bigint): bigint {
67
- return (fee * (BPS - discountBps)) / BPS;
68
- }
69
-
70
- export function activationFee(
71
- accountSize: bigint,
72
- drawdownBps: number,
73
- dailyDD: boolean,
74
- feeMultiplier: number = 120,
75
- dailyDdDiscountBps: number = Number(DAILY_DD_DISCOUNT_BPS),
76
- ): bigint {
77
- let fee = (accountSize * BigInt(drawdownBps) * BigInt(feeMultiplier)) / FEE_DIVISOR;
78
- if (dailyDD) {
79
- fee = applyDailyDiscount(fee, BigInt(dailyDdDiscountBps));
80
- }
81
- return roundUpUsdc(fee);
82
- }
83
-
84
- export function subscriptionFee(accountSize: bigint, subFeeMultiplier: number): bigint;
85
- export function subscriptionFee(
86
- accountSize: bigint,
87
- _drawdownBps: number,
88
- _dailyDD: boolean,
89
- subFeeMultiplier: number,
90
- ): bigint;
91
- export function subscriptionFee(
92
- accountSize: bigint,
93
- a: number,
94
- _b?: boolean,
95
- c?: number,
96
- ): bigint {
97
- const subFeeMultiplier = c ?? a;
98
- const fee = (accountSize * BigInt(subFeeMultiplier)) / BPS;
99
- return roundUpUsdc(fee);
100
- }
101
-
102
- // ── Profit split ────────────────────────────────────
103
-
104
- export function splitProfit(profit: bigint): {
105
- owner: bigint;
106
- vault: bigint;
107
- protocol: bigint;
108
- } {
109
- const owner = (profit * OWNER_PROFIT_BPS) / BPS;
110
- const protocol = (profit * PROTOCOL_PROFIT_BPS) / BPS;
111
- const vault = profit - owner - protocol;
112
- return { owner, vault, protocol };
113
- }
114
-
115
- // ── Enum mapping ────────────────────────────────────
116
-
117
- const stateLabels: Record<AccountState, AccountStateLabel> = {
118
- [AccountState.Uninitialized]: "UNINITIALIZED",
119
- [AccountState.Initialized]: "INITIALIZED",
120
- [AccountState.Active]: "ACTIVE",
121
- [AccountState.WithdrawalPending]: "WITHDRAWAL_PENDING",
122
- [AccountState.Closing]: "CLOSING",
123
- [AccountState.Returning]: "RETURNING",
124
- [AccountState.Closed]: "CLOSED",
125
- };
126
-
127
- const labelStates: Record<AccountStateLabel, AccountState> = {
128
- UNINITIALIZED: AccountState.Uninitialized,
129
- INITIALIZED: AccountState.Initialized,
130
- ACTIVE: AccountState.Active,
131
- WITHDRAWAL_PENDING: AccountState.WithdrawalPending,
132
- CLOSING: AccountState.Closing,
133
- RETURNING: AccountState.Returning,
134
- CLOSED: AccountState.Closed,
135
- };
136
-
137
- export function stateToLabel(state: AccountState): AccountStateLabel {
138
- return stateLabels[state];
139
- }
140
-
141
- export function labelToState(label: AccountStateLabel): AccountState {
142
- return labelStates[label];
143
- }