@strobelabs/perpcity-sdk 0.2.0 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.mjs CHANGED
@@ -1,7 +1,5 @@
1
1
  // src/context.ts
2
- import { GraphQLClient } from "graphql-request";
3
2
  import { publicActions, formatUnits } from "viem";
4
- import { parse } from "graphql";
5
3
 
6
4
  // src/utils/constants.ts
7
5
  var NUMBER_1E6 = 1e6;
@@ -66,24 +64,218 @@ async function approveUsdc(context, amount, confirmations = DEFAULT_CONFIRMATION
66
64
  });
67
65
  }
68
66
 
67
+ // src/utils/liquidity.ts
68
+ async function estimateLiquidity(context, tickLower, tickUpper, usdScaled) {
69
+ const Q962 = 1n << 96n;
70
+ const sqrtPriceLowerX96 = getSqrtRatioAtTick(tickLower);
71
+ const sqrtPriceUpperX96 = getSqrtRatioAtTick(tickUpper);
72
+ const sqrtPriceDiff = sqrtPriceUpperX96 - sqrtPriceLowerX96;
73
+ const liquidity = usdScaled * Q962 / sqrtPriceDiff;
74
+ return liquidity;
75
+ }
76
+ function getSqrtRatioAtTick(tick) {
77
+ const absTick = Math.abs(tick);
78
+ let ratio = 0xfffcb933bd6fad37aa2d162d1a594001n;
79
+ if (absTick & 1) ratio = ratio * 0xfff97272373d413259a46990580e213an >> 128n;
80
+ if (absTick & 2) ratio = ratio * 0xfff2e50f5f656932ef12357cf3c7fdccn >> 128n;
81
+ if (absTick & 4) ratio = ratio * 0xffe5caca7e10e4e61c3624eaa0941cd0n >> 128n;
82
+ if (absTick & 8) ratio = ratio * 0xffcb9843d60f6159c9db58835c926644n >> 128n;
83
+ if (absTick & 16) ratio = ratio * 0xff973b41fa98c081472e6896dfb254c0n >> 128n;
84
+ if (absTick & 32) ratio = ratio * 0xff2ea16466c96a3843ec78b326b52861n >> 128n;
85
+ if (absTick & 64) ratio = ratio * 0xfe5dee046a99a2a811c461f1969c3053n >> 128n;
86
+ if (absTick & 128) ratio = ratio * 0xfcbe86c7900a88aedcffc83b479aa3a4n >> 128n;
87
+ if (absTick & 256) ratio = ratio * 0xf987a7253ac413176f2b074cf7815e54n >> 128n;
88
+ if (absTick & 512) ratio = ratio * 0xf3392b0822b70005940c7a398e4b70f3n >> 128n;
89
+ if (absTick & 1024) ratio = ratio * 0xe7159475a2c29b7443b29c7fa6e889d9n >> 128n;
90
+ if (absTick & 2048) ratio = ratio * 0xd097f3bdfd2022b8845ad8f792aa5825n >> 128n;
91
+ if (absTick & 4096) ratio = ratio * 0xa9f746462d870fdf8a65dc1f90e061e5n >> 128n;
92
+ if (absTick & 8192) ratio = ratio * 0x70d869a156d2a1b890bb3df62baf32f7n >> 128n;
93
+ if (absTick & 16384) ratio = ratio * 0x31be135f97d08fd981231505542fcfa6n >> 128n;
94
+ if (absTick & 32768) ratio = ratio * 0x9aa508b5b7a84e1c677de54f3e99bc9n >> 128n;
95
+ if (absTick & 65536) ratio = ratio * 0x5d6af8dedb81196699c329225ee604n >> 128n;
96
+ if (absTick & 131072) ratio = ratio * 0x2216e584f5fa1ea926041bedfe98n >> 128n;
97
+ if (absTick & 262144) ratio = ratio * 0x48a170391f7dc42444e8fa2n >> 128n;
98
+ if (tick > 0) ratio = 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffn / ratio;
99
+ return ratio % (1n << 32n) > 0n ? (ratio >> 32n) + 1n : ratio >> 32n;
100
+ }
101
+
102
+ // src/utils/errors.ts
103
+ import { BaseError, ContractFunctionRevertedError } from "viem";
104
+ var PerpCityError = class extends Error {
105
+ constructor(message, cause) {
106
+ super(message);
107
+ this.cause = cause;
108
+ this.name = "PerpCityError";
109
+ }
110
+ };
111
+ var ContractError = class extends PerpCityError {
112
+ constructor(message, errorName, args, cause) {
113
+ super(message, cause);
114
+ this.errorName = errorName;
115
+ this.args = args;
116
+ this.name = "ContractError";
117
+ }
118
+ };
119
+ var TransactionRejectedError = class extends PerpCityError {
120
+ constructor(message = "Transaction rejected by user", cause) {
121
+ super(message, cause);
122
+ this.name = "TransactionRejectedError";
123
+ }
124
+ };
125
+ var InsufficientFundsError = class extends PerpCityError {
126
+ constructor(message = "Insufficient funds for transaction", cause) {
127
+ super(message, cause);
128
+ this.name = "InsufficientFundsError";
129
+ }
130
+ };
131
+ var RPCError = class extends PerpCityError {
132
+ constructor(message, cause) {
133
+ super(message, cause);
134
+ this.name = "RPCError";
135
+ }
136
+ };
137
+ var ValidationError = class extends PerpCityError {
138
+ constructor(message, cause) {
139
+ super(message, cause);
140
+ this.name = "ValidationError";
141
+ }
142
+ };
143
+ function parseContractError(error) {
144
+ if (error instanceof PerpCityError) {
145
+ return error;
146
+ }
147
+ if (error instanceof BaseError) {
148
+ const revertError = error.walk((err) => err instanceof ContractFunctionRevertedError);
149
+ if (revertError instanceof ContractFunctionRevertedError) {
150
+ const errorName = revertError.data?.errorName ?? "Unknown";
151
+ const args = revertError.data?.args ?? [];
152
+ const message = formatContractError(errorName, args);
153
+ return new ContractError(message, errorName, args, error);
154
+ }
155
+ if (error.message?.includes("User rejected") || error.code === 4001) {
156
+ return new TransactionRejectedError(error.message, error);
157
+ }
158
+ if (error.message?.includes("insufficient funds")) {
159
+ return new InsufficientFundsError(error.message, error);
160
+ }
161
+ return new PerpCityError(error.shortMessage || error.message, error);
162
+ }
163
+ if (error instanceof Error) {
164
+ return new PerpCityError(error.message, error);
165
+ }
166
+ return new PerpCityError(String(error));
167
+ }
168
+ function formatContractError(errorName, args) {
169
+ switch (errorName) {
170
+ case "InvalidBeaconAddress":
171
+ return `Invalid beacon address: ${args[0]}`;
172
+ case "InvalidTradingFeeSplits":
173
+ return `Invalid trading fee splits. Insurance split: ${args[0]}, Creator split: ${args[1]}`;
174
+ case "InvalidMaxOpeningLev":
175
+ return `Invalid maximum opening leverage: ${args[0]}`;
176
+ case "InvalidLiquidationLev":
177
+ return `Invalid liquidation leverage: ${args[0]}. Must be less than max opening leverage: ${args[1]}`;
178
+ case "InvalidLiquidationFee":
179
+ return `Invalid liquidation fee: ${args[0]}`;
180
+ case "InvalidLiquidatorFeeSplit":
181
+ return `Invalid liquidator fee split: ${args[0]}`;
182
+ case "InvalidClose":
183
+ return `Cannot close position. Caller: ${args[0]}, Holder: ${args[1]}, Is Liquidated: ${args[2]}`;
184
+ case "InvalidCaller":
185
+ return `Invalid caller. Expected: ${args[1]}, Got: ${args[0]}`;
186
+ case "InvalidLiquidity":
187
+ return `Invalid liquidity amount: ${args[0]}`;
188
+ case "InvalidMargin":
189
+ return `Invalid margin amount: ${args[0]}`;
190
+ case "InvalidLevX96":
191
+ return `Invalid leverage: ${args[0]}. Maximum allowed: ${args[1]}`;
192
+ case "MakerPositionLocked":
193
+ return `Maker position is locked until ${new Date(Number(args[1]) * 1e3).toISOString()}. Current time: ${new Date(Number(args[0]) * 1e3).toISOString()}`;
194
+ case "MaximumAmountExceeded":
195
+ return `Maximum amount exceeded. Maximum: ${args[0]}, Requested: ${args[1]}`;
196
+ case "MinimumAmountInsufficient":
197
+ return `Minimum amount not met. Required: ${args[0]}, Received: ${args[1]}`;
198
+ case "PriceImpactTooHigh":
199
+ return `Price impact too high. Current price: ${args[0]}, Min acceptable: ${args[1]}, Max acceptable: ${args[2]}`;
200
+ case "SwapReverted":
201
+ return "Swap failed. This may be due to insufficient liquidity or slippage tolerance.";
202
+ case "ZeroSizePosition":
203
+ return `Cannot create zero-size position. Perp delta: ${args[0]}, USD delta: ${args[1]}`;
204
+ case "InvalidFundingInterval":
205
+ return `Invalid funding interval: ${args[0]}`;
206
+ case "InvalidPriceImpactBand":
207
+ return `Invalid price impact band: ${args[0]}`;
208
+ case "InvalidMarketDeathThreshold":
209
+ return `Invalid market death threshold: ${args[0]}`;
210
+ case "InvalidTickRange":
211
+ return `Invalid tick range. Lower: ${args[0]}, Upper: ${args[1]}`;
212
+ case "MarketNotKillable":
213
+ return `Market health (${args[0]}) is above death threshold (${args[1]}). Market cannot be killed yet.`;
214
+ case "InvalidStartingSqrtPriceX96":
215
+ return `Invalid starting sqrt price: ${args[0]}`;
216
+ default:
217
+ return `Contract error: ${errorName}${args.length > 0 ? ` (${args.join(", ")})` : ""}`;
218
+ }
219
+ }
220
+ async function withErrorHandling(fn, context) {
221
+ try {
222
+ return await fn();
223
+ } catch (error) {
224
+ const parsedError = parseContractError(error);
225
+ parsedError.message = `${context}: ${parsedError.message}`;
226
+ throw parsedError;
227
+ }
228
+ }
229
+
230
+ // src/utils/rpc.ts
231
+ function getRpcUrl(config = {}) {
232
+ const rpcUrl = config.url ?? process.env.RPC_URL;
233
+ if (!rpcUrl) {
234
+ throw new Error(
235
+ "RPC_URL is required. Please set the RPC_URL environment variable with your full RPC endpoint URL.\nExample URLs (use your own provider and API key):\n https://base-sepolia.g.alchemy.com/v2/YOUR_API_KEY\n https://base-sepolia.infura.io/v3/YOUR_API_KEY\n https://sepolia.base.org"
236
+ );
237
+ }
238
+ return rpcUrl;
239
+ }
240
+
69
241
  // src/abis/perp-manager.ts
70
242
  var PERP_MANAGER_ABI = [
71
243
  {
72
244
  "inputs": [
73
- {
74
- "internalType": "contract IPoolManager",
75
- "name": "poolManager",
76
- "type": "address"
77
- },
78
245
  {
79
246
  "internalType": "address",
80
- "name": "usdc",
247
+ "name": "owner",
81
248
  "type": "address"
82
249
  }
83
250
  ],
84
251
  "stateMutability": "nonpayable",
85
252
  "type": "constructor"
86
253
  },
254
+ {
255
+ "inputs": [],
256
+ "name": "AccountBalanceOverflow",
257
+ "type": "error"
258
+ },
259
+ {
260
+ "inputs": [],
261
+ "name": "AlreadyInitialized",
262
+ "type": "error"
263
+ },
264
+ {
265
+ "inputs": [],
266
+ "name": "BalanceQueryForZeroAddress",
267
+ "type": "error"
268
+ },
269
+ {
270
+ "inputs": [],
271
+ "name": "FeeTooLarge",
272
+ "type": "error"
273
+ },
274
+ {
275
+ "inputs": [],
276
+ "name": "FeesNotRegistered",
277
+ "type": "error"
278
+ },
87
279
  {
88
280
  "inputs": [
89
281
  {
@@ -96,42 +288,10 @@ var PERP_MANAGER_ABI = [
96
288
  "type": "error"
97
289
  },
98
290
  {
99
- "inputs": [
100
- {
101
- "internalType": "address",
102
- "name": "caller",
103
- "type": "address"
104
- },
105
- {
106
- "internalType": "address",
107
- "name": "expectedCaller",
108
- "type": "address"
109
- }
110
- ],
291
+ "inputs": [],
111
292
  "name": "InvalidCaller",
112
293
  "type": "error"
113
294
  },
114
- {
115
- "inputs": [
116
- {
117
- "internalType": "address",
118
- "name": "caller",
119
- "type": "address"
120
- },
121
- {
122
- "internalType": "address",
123
- "name": "holder",
124
- "type": "address"
125
- },
126
- {
127
- "internalType": "bool",
128
- "name": "isLiquidated",
129
- "type": "bool"
130
- }
131
- ],
132
- "name": "InvalidClose",
133
- "type": "error"
134
- },
135
295
  {
136
296
  "inputs": [
137
297
  {
@@ -144,13 +304,7 @@ var PERP_MANAGER_ABI = [
144
304
  "type": "error"
145
305
  },
146
306
  {
147
- "inputs": [
148
- {
149
- "internalType": "uint256",
150
- "name": "margin",
151
- "type": "uint256"
152
- }
153
- ],
307
+ "inputs": [],
154
308
  "name": "InvalidMargin",
155
309
  "type": "error"
156
310
  },
@@ -158,16 +312,26 @@ var PERP_MANAGER_ABI = [
158
312
  "inputs": [
159
313
  {
160
314
  "internalType": "uint256",
161
- "name": "currentTimestamp",
162
- "type": "uint256"
163
- },
164
- {
165
- "internalType": "uint256",
166
- "name": "lockupPeriodEnd",
315
+ "name": "marginRatio",
167
316
  "type": "uint256"
168
317
  }
169
318
  ],
170
- "name": "MakerPositionLocked",
319
+ "name": "InvalidMarginRatio",
320
+ "type": "error"
321
+ },
322
+ {
323
+ "inputs": [],
324
+ "name": "LockupPeriodNotRegistered",
325
+ "type": "error"
326
+ },
327
+ {
328
+ "inputs": [],
329
+ "name": "MakerNotAllowed",
330
+ "type": "error"
331
+ },
332
+ {
333
+ "inputs": [],
334
+ "name": "MarginRatiosNotRegistered",
171
335
  "type": "error"
172
336
  },
173
337
  {
@@ -202,47 +366,161 @@ var PERP_MANAGER_ABI = [
202
366
  "name": "MinimumAmountInsufficient",
203
367
  "type": "error"
204
368
  },
369
+ {
370
+ "inputs": [],
371
+ "name": "ModuleAlreadyRegistered",
372
+ "type": "error"
373
+ },
374
+ {
375
+ "inputs": [],
376
+ "name": "NewOwnerIsZeroAddress",
377
+ "type": "error"
378
+ },
379
+ {
380
+ "inputs": [],
381
+ "name": "NoHandoverRequest",
382
+ "type": "error"
383
+ },
384
+ {
385
+ "inputs": [],
386
+ "name": "NotOwnerNorApproved",
387
+ "type": "error"
388
+ },
205
389
  {
206
390
  "inputs": [],
207
391
  "name": "NotPoolManager",
208
392
  "type": "error"
209
393
  },
210
394
  {
211
- "inputs": [
212
- {
213
- "internalType": "bytes",
214
- "name": "reason",
215
- "type": "bytes"
216
- }
217
- ],
218
- "name": "UnexpectedRevertBytes",
395
+ "inputs": [],
396
+ "name": "PositionLocked",
219
397
  "type": "error"
220
398
  },
221
399
  {
222
- "inputs": [
223
- {
224
- "internalType": "int256",
225
- "name": "perpDelta",
226
- "type": "int256"
227
- },
228
- {
229
- "internalType": "int256",
230
- "name": "usdDelta",
231
- "type": "int256"
232
- }
233
- ],
234
- "name": "ZeroSizePosition",
400
+ "inputs": [],
401
+ "name": "SqrtPriceImpactLimitNotRegistered",
235
402
  "type": "error"
236
403
  },
237
404
  {
238
- "anonymous": false,
239
- "inputs": [
240
- {
241
- "indexed": false,
242
- "internalType": "PoolId",
243
- "name": "perpId",
244
- "type": "bytes32"
245
- },
405
+ "inputs": [],
406
+ "name": "TokenAlreadyExists",
407
+ "type": "error"
408
+ },
409
+ {
410
+ "inputs": [],
411
+ "name": "TokenDoesNotExist",
412
+ "type": "error"
413
+ },
414
+ {
415
+ "inputs": [],
416
+ "name": "TransferFromIncorrectOwner",
417
+ "type": "error"
418
+ },
419
+ {
420
+ "inputs": [],
421
+ "name": "TransferToNonERC721ReceiverImplementer",
422
+ "type": "error"
423
+ },
424
+ {
425
+ "inputs": [],
426
+ "name": "TransferToZeroAddress",
427
+ "type": "error"
428
+ },
429
+ {
430
+ "inputs": [],
431
+ "name": "Unauthorized",
432
+ "type": "error"
433
+ },
434
+ {
435
+ "inputs": [],
436
+ "name": "ZeroDelta",
437
+ "type": "error"
438
+ },
439
+ {
440
+ "anonymous": false,
441
+ "inputs": [
442
+ {
443
+ "indexed": true,
444
+ "internalType": "address",
445
+ "name": "owner",
446
+ "type": "address"
447
+ },
448
+ {
449
+ "indexed": true,
450
+ "internalType": "address",
451
+ "name": "account",
452
+ "type": "address"
453
+ },
454
+ {
455
+ "indexed": true,
456
+ "internalType": "uint256",
457
+ "name": "id",
458
+ "type": "uint256"
459
+ }
460
+ ],
461
+ "name": "Approval",
462
+ "type": "event"
463
+ },
464
+ {
465
+ "anonymous": false,
466
+ "inputs": [
467
+ {
468
+ "indexed": true,
469
+ "internalType": "address",
470
+ "name": "owner",
471
+ "type": "address"
472
+ },
473
+ {
474
+ "indexed": true,
475
+ "internalType": "address",
476
+ "name": "operator",
477
+ "type": "address"
478
+ },
479
+ {
480
+ "indexed": false,
481
+ "internalType": "bool",
482
+ "name": "isApproved",
483
+ "type": "bool"
484
+ }
485
+ ],
486
+ "name": "ApprovalForAll",
487
+ "type": "event"
488
+ },
489
+ {
490
+ "anonymous": false,
491
+ "inputs": [
492
+ {
493
+ "indexed": false,
494
+ "internalType": "contract IFees",
495
+ "name": "feesModule",
496
+ "type": "address"
497
+ }
498
+ ],
499
+ "name": "FeesModuleRegistered",
500
+ "type": "event"
501
+ },
502
+ {
503
+ "anonymous": false,
504
+ "inputs": [
505
+ {
506
+ "indexed": false,
507
+ "internalType": "contract ILockupPeriod",
508
+ "name": "lockupPeriodModule",
509
+ "type": "address"
510
+ }
511
+ ],
512
+ "name": "LockupPeriodModuleRegistered",
513
+ "type": "event"
514
+ },
515
+ {
516
+ "anonymous": false,
517
+ "inputs": [
518
+ {
519
+ "indexed": false,
520
+ "internalType": "PoolId",
521
+ "name": "perpId",
522
+ "type": "bytes32"
523
+ },
246
524
  {
247
525
  "indexed": false,
248
526
  "internalType": "uint256",
@@ -256,7 +534,108 @@ var PERP_MANAGER_ABI = [
256
534
  "type": "uint256"
257
535
  }
258
536
  ],
259
- "name": "MarginAdded",
537
+ "name": "MarginAdjusted",
538
+ "type": "event"
539
+ },
540
+ {
541
+ "anonymous": false,
542
+ "inputs": [
543
+ {
544
+ "indexed": false,
545
+ "internalType": "contract IMarginRatios",
546
+ "name": "marginRatiosModule",
547
+ "type": "address"
548
+ }
549
+ ],
550
+ "name": "MarginRatiosModuleRegistered",
551
+ "type": "event"
552
+ },
553
+ {
554
+ "anonymous": false,
555
+ "inputs": [
556
+ {
557
+ "indexed": false,
558
+ "internalType": "PoolId",
559
+ "name": "perpId",
560
+ "type": "bytes32"
561
+ },
562
+ {
563
+ "indexed": false,
564
+ "internalType": "uint256",
565
+ "name": "sqrtPriceX96",
566
+ "type": "uint256"
567
+ },
568
+ {
569
+ "indexed": false,
570
+ "internalType": "uint256",
571
+ "name": "longOI",
572
+ "type": "uint256"
573
+ },
574
+ {
575
+ "indexed": false,
576
+ "internalType": "uint256",
577
+ "name": "shortOI",
578
+ "type": "uint256"
579
+ },
580
+ {
581
+ "indexed": false,
582
+ "internalType": "uint256",
583
+ "name": "posId",
584
+ "type": "uint256"
585
+ },
586
+ {
587
+ "indexed": false,
588
+ "internalType": "int256",
589
+ "name": "newPerpDelta",
590
+ "type": "int256"
591
+ }
592
+ ],
593
+ "name": "NotionalAdjusted",
594
+ "type": "event"
595
+ },
596
+ {
597
+ "anonymous": false,
598
+ "inputs": [
599
+ {
600
+ "indexed": true,
601
+ "internalType": "address",
602
+ "name": "pendingOwner",
603
+ "type": "address"
604
+ }
605
+ ],
606
+ "name": "OwnershipHandoverCanceled",
607
+ "type": "event"
608
+ },
609
+ {
610
+ "anonymous": false,
611
+ "inputs": [
612
+ {
613
+ "indexed": true,
614
+ "internalType": "address",
615
+ "name": "pendingOwner",
616
+ "type": "address"
617
+ }
618
+ ],
619
+ "name": "OwnershipHandoverRequested",
620
+ "type": "event"
621
+ },
622
+ {
623
+ "anonymous": false,
624
+ "inputs": [
625
+ {
626
+ "indexed": true,
627
+ "internalType": "address",
628
+ "name": "oldOwner",
629
+ "type": "address"
630
+ },
631
+ {
632
+ "indexed": true,
633
+ "internalType": "address",
634
+ "name": "newOwner",
635
+ "type": "address"
636
+ }
637
+ ],
638
+ "name": "OwnershipTransferred",
260
639
  "type": "event"
261
640
  },
262
641
  {
@@ -277,7 +656,7 @@ var PERP_MANAGER_ABI = [
277
656
  {
278
657
  "indexed": false,
279
658
  "internalType": "uint256",
280
- "name": "startingSqrtPriceX96",
659
+ "name": "sqrtPriceX96",
281
660
  "type": "uint256"
282
661
  },
283
662
  {
@@ -302,32 +681,26 @@ var PERP_MANAGER_ABI = [
302
681
  {
303
682
  "indexed": false,
304
683
  "internalType": "uint256",
305
- "name": "posId",
684
+ "name": "sqrtPriceX96",
306
685
  "type": "uint256"
307
686
  },
308
687
  {
309
688
  "indexed": false,
310
- "internalType": "address",
311
- "name": "holder",
312
- "type": "address"
313
- },
314
- {
315
- "indexed": false,
316
- "internalType": "bool",
317
- "name": "wasMaker",
318
- "type": "bool"
689
+ "internalType": "uint256",
690
+ "name": "longOI",
691
+ "type": "uint256"
319
692
  },
320
693
  {
321
694
  "indexed": false,
322
- "internalType": "int256",
323
- "name": "perpDelta",
324
- "type": "int256"
695
+ "internalType": "uint256",
696
+ "name": "shortOI",
697
+ "type": "uint256"
325
698
  },
326
699
  {
327
700
  "indexed": false,
328
- "internalType": "int256",
329
- "name": "pnl",
330
- "type": "int256"
701
+ "internalType": "uint256",
702
+ "name": "posId",
703
+ "type": "uint256"
331
704
  },
332
705
  {
333
706
  "indexed": false,
@@ -337,15 +710,9 @@ var PERP_MANAGER_ABI = [
337
710
  },
338
711
  {
339
712
  "indexed": false,
340
- "internalType": "uint256",
341
- "name": "sqrtPriceX96",
342
- "type": "uint256"
343
- },
344
- {
345
- "indexed": false,
346
- "internalType": "int256",
347
- "name": "fundingPremiumPerSecX96",
348
- "type": "int256"
713
+ "internalType": "bool",
714
+ "name": "wasPartialClose",
715
+ "type": "bool"
349
716
  }
350
717
  ],
351
718
  "name": "PositionClosed",
@@ -363,37 +730,37 @@ var PERP_MANAGER_ABI = [
363
730
  {
364
731
  "indexed": false,
365
732
  "internalType": "uint256",
366
- "name": "posId",
733
+ "name": "sqrtPriceX96",
367
734
  "type": "uint256"
368
735
  },
369
736
  {
370
737
  "indexed": false,
371
- "internalType": "address",
372
- "name": "holder",
373
- "type": "address"
738
+ "internalType": "uint256",
739
+ "name": "longOI",
740
+ "type": "uint256"
374
741
  },
375
742
  {
376
743
  "indexed": false,
377
- "internalType": "bool",
378
- "name": "isMaker",
379
- "type": "bool"
744
+ "internalType": "uint256",
745
+ "name": "shortOI",
746
+ "type": "uint256"
380
747
  },
381
748
  {
382
749
  "indexed": false,
383
- "internalType": "int256",
384
- "name": "perpDelta",
385
- "type": "int256"
750
+ "internalType": "uint256",
751
+ "name": "posId",
752
+ "type": "uint256"
386
753
  },
387
754
  {
388
755
  "indexed": false,
389
- "internalType": "uint256",
390
- "name": "sqrtPriceX96",
391
- "type": "uint256"
756
+ "internalType": "bool",
757
+ "name": "isMaker",
758
+ "type": "bool"
392
759
  },
393
760
  {
394
761
  "indexed": false,
395
762
  "internalType": "int256",
396
- "name": "fundingPremiumPerSecX96",
763
+ "name": "entryPerpDelta",
397
764
  "type": "int256"
398
765
  }
399
766
  ],
@@ -401,74 +768,283 @@ var PERP_MANAGER_ABI = [
401
768
  "type": "event"
402
769
  },
403
770
  {
404
- "inputs": [],
405
- "name": "POOL_MANAGER",
406
- "outputs": [
771
+ "anonymous": false,
772
+ "inputs": [
407
773
  {
408
- "internalType": "contract IPoolManager",
409
- "name": "",
774
+ "indexed": false,
775
+ "internalType": "contract ISqrtPriceImpactLimit",
776
+ "name": "sqrtPriceImpactLimitModule",
410
777
  "type": "address"
411
778
  }
412
779
  ],
413
- "stateMutability": "view",
414
- "type": "function"
780
+ "name": "SqrtPriceImpactLimitModuleRegistered",
781
+ "type": "event"
415
782
  },
416
783
  {
417
- "inputs": [],
418
- "name": "USDC",
419
- "outputs": [
784
+ "anonymous": false,
785
+ "inputs": [
420
786
  {
787
+ "indexed": true,
421
788
  "internalType": "address",
422
- "name": "",
789
+ "name": "from",
790
+ "type": "address"
791
+ },
792
+ {
793
+ "indexed": true,
794
+ "internalType": "address",
795
+ "name": "to",
423
796
  "type": "address"
797
+ },
798
+ {
799
+ "indexed": true,
800
+ "internalType": "uint256",
801
+ "name": "id",
802
+ "type": "uint256"
424
803
  }
425
804
  ],
426
- "stateMutability": "view",
427
- "type": "function"
805
+ "name": "Transfer",
806
+ "type": "event"
428
807
  },
429
808
  {
430
- "inputs": [
809
+ "inputs": [],
810
+ "name": "ERC721_NAME",
811
+ "outputs": [
431
812
  {
432
- "internalType": "PoolId",
433
- "name": "perpId",
434
- "type": "bytes32"
435
- },
813
+ "internalType": "string",
814
+ "name": "",
815
+ "type": "string"
816
+ }
817
+ ],
818
+ "stateMutability": "view",
819
+ "type": "function"
820
+ },
821
+ {
822
+ "inputs": [],
823
+ "name": "ERC721_SYMBOL",
824
+ "outputs": [
825
+ {
826
+ "internalType": "string",
827
+ "name": "",
828
+ "type": "string"
829
+ }
830
+ ],
831
+ "stateMutability": "view",
832
+ "type": "function"
833
+ },
834
+ {
835
+ "inputs": [],
836
+ "name": "ERC721_URI",
837
+ "outputs": [
838
+ {
839
+ "internalType": "string",
840
+ "name": "",
841
+ "type": "string"
842
+ }
843
+ ],
844
+ "stateMutability": "view",
845
+ "type": "function"
846
+ },
847
+ {
848
+ "inputs": [],
849
+ "name": "MAX_PROTOCOL_FEE",
850
+ "outputs": [
851
+ {
852
+ "internalType": "uint24",
853
+ "name": "",
854
+ "type": "uint24"
855
+ }
856
+ ],
857
+ "stateMutability": "view",
858
+ "type": "function"
859
+ },
860
+ {
861
+ "inputs": [
436
862
  {
437
863
  "components": [
438
864
  {
439
- "internalType": "uint128",
865
+ "internalType": "uint256",
440
866
  "name": "posId",
441
- "type": "uint128"
867
+ "type": "uint256"
442
868
  },
869
+ {
870
+ "internalType": "int256",
871
+ "name": "marginDelta",
872
+ "type": "int256"
873
+ }
874
+ ],
875
+ "internalType": "struct IPerpManager.AdjustMarginParams",
876
+ "name": "params",
877
+ "type": "tuple"
878
+ }
879
+ ],
880
+ "name": "adjustMargin",
881
+ "outputs": [],
882
+ "stateMutability": "nonpayable",
883
+ "type": "function"
884
+ },
885
+ {
886
+ "inputs": [
887
+ {
888
+ "components": [
443
889
  {
444
890
  "internalType": "uint256",
445
- "name": "margin",
891
+ "name": "posId",
446
892
  "type": "uint256"
893
+ },
894
+ {
895
+ "internalType": "int256",
896
+ "name": "perpDelta",
897
+ "type": "int256"
898
+ },
899
+ {
900
+ "internalType": "uint128",
901
+ "name": "usdLimit",
902
+ "type": "uint128"
447
903
  }
448
904
  ],
449
- "internalType": "struct IPerpManager.AddMarginParams",
905
+ "internalType": "struct IPerpManager.AdjustNotionalParams",
450
906
  "name": "params",
451
907
  "type": "tuple"
452
908
  }
453
909
  ],
454
- "name": "addMargin",
910
+ "name": "adjustNotional",
455
911
  "outputs": [],
456
912
  "stateMutability": "nonpayable",
457
913
  "type": "function"
458
914
  },
915
+ {
916
+ "inputs": [
917
+ {
918
+ "internalType": "address",
919
+ "name": "account",
920
+ "type": "address"
921
+ },
922
+ {
923
+ "internalType": "uint256",
924
+ "name": "id",
925
+ "type": "uint256"
926
+ }
927
+ ],
928
+ "name": "approve",
929
+ "outputs": [],
930
+ "stateMutability": "payable",
931
+ "type": "function"
932
+ },
933
+ {
934
+ "inputs": [
935
+ {
936
+ "internalType": "address",
937
+ "name": "owner",
938
+ "type": "address"
939
+ }
940
+ ],
941
+ "name": "balanceOf",
942
+ "outputs": [
943
+ {
944
+ "internalType": "uint256",
945
+ "name": "result",
946
+ "type": "uint256"
947
+ }
948
+ ],
949
+ "stateMutability": "view",
950
+ "type": "function"
951
+ },
952
+ {
953
+ "inputs": [],
954
+ "name": "cancelOwnershipHandover",
955
+ "outputs": [],
956
+ "stateMutability": "payable",
957
+ "type": "function"
958
+ },
459
959
  {
460
960
  "inputs": [
461
961
  {
462
962
  "internalType": "PoolId",
463
- "name": "perpId",
963
+ "name": "",
464
964
  "type": "bytes32"
965
+ }
966
+ ],
967
+ "name": "cfgs",
968
+ "outputs": [
969
+ {
970
+ "components": [
971
+ {
972
+ "internalType": "Currency",
973
+ "name": "currency0",
974
+ "type": "address"
975
+ },
976
+ {
977
+ "internalType": "Currency",
978
+ "name": "currency1",
979
+ "type": "address"
980
+ },
981
+ {
982
+ "internalType": "uint24",
983
+ "name": "fee",
984
+ "type": "uint24"
985
+ },
986
+ {
987
+ "internalType": "int24",
988
+ "name": "tickSpacing",
989
+ "type": "int24"
990
+ },
991
+ {
992
+ "internalType": "contract IHooks",
993
+ "name": "hooks",
994
+ "type": "address"
995
+ }
996
+ ],
997
+ "internalType": "struct PoolKey",
998
+ "name": "key",
999
+ "type": "tuple"
1000
+ },
1001
+ {
1002
+ "internalType": "address",
1003
+ "name": "creator",
1004
+ "type": "address"
1005
+ },
1006
+ {
1007
+ "internalType": "address",
1008
+ "name": "vault",
1009
+ "type": "address"
1010
+ },
1011
+ {
1012
+ "internalType": "address",
1013
+ "name": "beacon",
1014
+ "type": "address"
1015
+ },
1016
+ {
1017
+ "internalType": "contract IFees",
1018
+ "name": "fees",
1019
+ "type": "address"
1020
+ },
1021
+ {
1022
+ "internalType": "contract IMarginRatios",
1023
+ "name": "marginRatios",
1024
+ "type": "address"
465
1025
  },
1026
+ {
1027
+ "internalType": "contract ILockupPeriod",
1028
+ "name": "lockupPeriod",
1029
+ "type": "address"
1030
+ },
1031
+ {
1032
+ "internalType": "contract ISqrtPriceImpactLimit",
1033
+ "name": "sqrtPriceImpactLimit",
1034
+ "type": "address"
1035
+ }
1036
+ ],
1037
+ "stateMutability": "view",
1038
+ "type": "function"
1039
+ },
1040
+ {
1041
+ "inputs": [
466
1042
  {
467
1043
  "components": [
468
1044
  {
469
- "internalType": "uint128",
1045
+ "internalType": "uint256",
470
1046
  "name": "posId",
471
- "type": "uint128"
1047
+ "type": "uint256"
472
1048
  },
473
1049
  {
474
1050
  "internalType": "uint128",
@@ -492,29 +1068,69 @@ var PERP_MANAGER_ABI = [
492
1068
  }
493
1069
  ],
494
1070
  "name": "closePosition",
495
- "outputs": [
1071
+ "outputs": [],
1072
+ "stateMutability": "nonpayable",
1073
+ "type": "function"
1074
+ },
1075
+ {
1076
+ "inputs": [
496
1077
  {
497
- "internalType": "uint128",
498
- "name": "posId",
499
- "type": "uint128"
1078
+ "internalType": "address",
1079
+ "name": "recipient",
1080
+ "type": "address"
500
1081
  }
501
1082
  ],
1083
+ "name": "collectProtocolFees",
1084
+ "outputs": [],
502
1085
  "stateMutability": "nonpayable",
503
1086
  "type": "function"
504
1087
  },
1088
+ {
1089
+ "inputs": [
1090
+ {
1091
+ "internalType": "address",
1092
+ "name": "pendingOwner",
1093
+ "type": "address"
1094
+ }
1095
+ ],
1096
+ "name": "completeOwnershipHandover",
1097
+ "outputs": [],
1098
+ "stateMutability": "payable",
1099
+ "type": "function"
1100
+ },
505
1101
  {
506
1102
  "inputs": [
507
1103
  {
508
1104
  "components": [
509
- {
510
- "internalType": "uint160",
511
- "name": "startingSqrtPriceX96",
512
- "type": "uint160"
513
- },
514
1105
  {
515
1106
  "internalType": "address",
516
1107
  "name": "beacon",
517
1108
  "type": "address"
1109
+ },
1110
+ {
1111
+ "internalType": "contract IFees",
1112
+ "name": "fees",
1113
+ "type": "address"
1114
+ },
1115
+ {
1116
+ "internalType": "contract IMarginRatios",
1117
+ "name": "marginRatios",
1118
+ "type": "address"
1119
+ },
1120
+ {
1121
+ "internalType": "contract ILockupPeriod",
1122
+ "name": "lockupPeriod",
1123
+ "type": "address"
1124
+ },
1125
+ {
1126
+ "internalType": "contract ISqrtPriceImpactLimit",
1127
+ "name": "sqrtPriceImpactLimit",
1128
+ "type": "address"
1129
+ },
1130
+ {
1131
+ "internalType": "uint160",
1132
+ "name": "startingSqrtPriceX96",
1133
+ "type": "uint160"
518
1134
  }
519
1135
  ],
520
1136
  "internalType": "struct IPerpManager.CreatePerpParams",
@@ -535,31 +1151,21 @@ var PERP_MANAGER_ABI = [
535
1151
  },
536
1152
  {
537
1153
  "inputs": [
538
- {
539
- "internalType": "int24",
540
- "name": "tickA",
541
- "type": "int24"
542
- },
543
- {
544
- "internalType": "int24",
545
- "name": "tickB",
546
- "type": "int24"
547
- },
548
1154
  {
549
1155
  "internalType": "uint256",
550
- "name": "amount1",
1156
+ "name": "id",
551
1157
  "type": "uint256"
552
1158
  }
553
1159
  ],
554
- "name": "estimateLiquidityForAmount1",
1160
+ "name": "getApproved",
555
1161
  "outputs": [
556
1162
  {
557
- "internalType": "uint128",
558
- "name": "liquidity",
559
- "type": "uint128"
1163
+ "internalType": "address",
1164
+ "name": "result",
1165
+ "type": "address"
560
1166
  }
561
1167
  ],
562
- "stateMutability": "pure",
1168
+ "stateMutability": "view",
563
1169
  "type": "function"
564
1170
  },
565
1171
  {
@@ -568,29 +1174,37 @@ var PERP_MANAGER_ABI = [
568
1174
  "internalType": "PoolId",
569
1175
  "name": "perpId",
570
1176
  "type": "bytes32"
1177
+ },
1178
+ {
1179
+ "internalType": "uint16",
1180
+ "name": "cardinalityCap",
1181
+ "type": "uint16"
571
1182
  }
572
1183
  ],
573
- "name": "fees",
574
- "outputs": [
1184
+ "name": "increaseCardinalityCap",
1185
+ "outputs": [],
1186
+ "stateMutability": "nonpayable",
1187
+ "type": "function"
1188
+ },
1189
+ {
1190
+ "inputs": [
575
1191
  {
576
- "internalType": "uint24",
577
- "name": "creatorFee",
578
- "type": "uint24"
579
- },
580
- {
581
- "internalType": "uint24",
582
- "name": "insurnaceFee",
583
- "type": "uint24"
1192
+ "internalType": "address",
1193
+ "name": "owner",
1194
+ "type": "address"
584
1195
  },
585
1196
  {
586
- "internalType": "uint24",
587
- "name": "lpFee",
588
- "type": "uint24"
589
- },
1197
+ "internalType": "address",
1198
+ "name": "operator",
1199
+ "type": "address"
1200
+ }
1201
+ ],
1202
+ "name": "isApprovedForAll",
1203
+ "outputs": [
590
1204
  {
591
- "internalType": "uint24",
592
- "name": "liquidationFee",
593
- "type": "uint24"
1205
+ "internalType": "bool",
1206
+ "name": "result",
1207
+ "type": "bool"
594
1208
  }
595
1209
  ],
596
1210
  "stateMutability": "view",
@@ -599,91 +1213,17 @@ var PERP_MANAGER_ABI = [
599
1213
  {
600
1214
  "inputs": [
601
1215
  {
602
- "internalType": "PoolId",
603
- "name": "perpId",
604
- "type": "bytes32"
605
- },
606
- {
607
- "internalType": "uint128",
608
- "name": "posId",
609
- "type": "uint128"
1216
+ "internalType": "contract IFees",
1217
+ "name": "",
1218
+ "type": "address"
610
1219
  }
611
1220
  ],
612
- "name": "getPosition",
1221
+ "name": "isFeesRegistered",
613
1222
  "outputs": [
614
1223
  {
615
- "components": [
616
- {
617
- "internalType": "address",
618
- "name": "holder",
619
- "type": "address"
620
- },
621
- {
622
- "internalType": "uint256",
623
- "name": "margin",
624
- "type": "uint256"
625
- },
626
- {
627
- "internalType": "int256",
628
- "name": "perpDelta",
629
- "type": "int256"
630
- },
631
- {
632
- "internalType": "int256",
633
- "name": "usdDelta",
634
- "type": "int256"
635
- },
636
- {
637
- "internalType": "int256",
638
- "name": "entryTwPremiumX96",
639
- "type": "int256"
640
- },
641
- {
642
- "components": [
643
- {
644
- "internalType": "uint32",
645
- "name": "entryTimestamp",
646
- "type": "uint32"
647
- },
648
- {
649
- "internalType": "int24",
650
- "name": "tickLower",
651
- "type": "int24"
652
- },
653
- {
654
- "internalType": "int24",
655
- "name": "tickUpper",
656
- "type": "int24"
657
- },
658
- {
659
- "internalType": "uint128",
660
- "name": "liquidity",
661
- "type": "uint128"
662
- },
663
- {
664
- "internalType": "int256",
665
- "name": "entryTwPremiumGrowthInsideX96",
666
- "type": "int256"
667
- },
668
- {
669
- "internalType": "int256",
670
- "name": "entryTwPremiumDivBySqrtPriceGrowthInsideX96",
671
- "type": "int256"
672
- },
673
- {
674
- "internalType": "int256",
675
- "name": "entryTwPremiumGrowthBelowX96",
676
- "type": "int256"
677
- }
678
- ],
679
- "internalType": "struct IPerpManager.MakerDetails",
680
- "name": "makerDetails",
681
- "type": "tuple"
682
- }
683
- ],
684
- "internalType": "struct IPerpManager.Position",
1224
+ "internalType": "bool",
685
1225
  "name": "",
686
- "type": "tuple"
1226
+ "type": "bool"
687
1227
  }
688
1228
  ],
689
1229
  "stateMutability": "view",
@@ -692,22 +1232,17 @@ var PERP_MANAGER_ABI = [
692
1232
  {
693
1233
  "inputs": [
694
1234
  {
695
- "internalType": "PoolId",
696
- "name": "perpId",
697
- "type": "bytes32"
698
- },
699
- {
700
- "internalType": "uint32",
701
- "name": "secondsAgo",
702
- "type": "uint32"
1235
+ "internalType": "contract ILockupPeriod",
1236
+ "name": "",
1237
+ "type": "address"
703
1238
  }
704
1239
  ],
705
- "name": "getTimeWeightedAvg",
1240
+ "name": "isLockupPeriodRegistered",
706
1241
  "outputs": [
707
1242
  {
708
- "internalType": "uint256",
1243
+ "internalType": "bool",
709
1244
  "name": "",
710
- "type": "uint256"
1245
+ "type": "bool"
711
1246
  }
712
1247
  ],
713
1248
  "stateMutability": "view",
@@ -716,63 +1251,65 @@ var PERP_MANAGER_ABI = [
716
1251
  {
717
1252
  "inputs": [
718
1253
  {
719
- "internalType": "PoolId",
720
- "name": "perpId",
721
- "type": "bytes32"
722
- },
1254
+ "internalType": "contract IMarginRatios",
1255
+ "name": "",
1256
+ "type": "address"
1257
+ }
1258
+ ],
1259
+ "name": "isMarginRatiosRegistered",
1260
+ "outputs": [
723
1261
  {
724
- "internalType": "uint32",
725
- "name": "cardinalityNext",
726
- "type": "uint32"
1262
+ "internalType": "bool",
1263
+ "name": "",
1264
+ "type": "bool"
727
1265
  }
728
1266
  ],
729
- "name": "increaseCardinalityNext",
730
- "outputs": [],
731
- "stateMutability": "nonpayable",
1267
+ "stateMutability": "view",
732
1268
  "type": "function"
733
1269
  },
734
1270
  {
735
1271
  "inputs": [
736
1272
  {
737
- "internalType": "PoolId",
738
- "name": "perpId",
739
- "type": "bytes32"
740
- },
741
- {
742
- "internalType": "uint128",
743
- "name": "posId",
744
- "type": "uint128"
1273
+ "internalType": "contract ISqrtPriceImpactLimit",
1274
+ "name": "",
1275
+ "type": "address"
745
1276
  }
746
1277
  ],
747
- "name": "livePositionDetails",
1278
+ "name": "isSqrtPriceImpactLimitRegistered",
748
1279
  "outputs": [
749
- {
750
- "internalType": "int256",
751
- "name": "pnl",
752
- "type": "int256"
753
- },
754
- {
755
- "internalType": "int256",
756
- "name": "fundingPayment",
757
- "type": "int256"
758
- },
759
- {
760
- "internalType": "int256",
761
- "name": "effectiveMargin",
762
- "type": "int256"
763
- },
764
1280
  {
765
1281
  "internalType": "bool",
766
- "name": "isLiquidatable",
1282
+ "name": "",
767
1283
  "type": "bool"
768
- },
1284
+ }
1285
+ ],
1286
+ "stateMutability": "view",
1287
+ "type": "function"
1288
+ },
1289
+ {
1290
+ "inputs": [],
1291
+ "name": "name",
1292
+ "outputs": [
1293
+ {
1294
+ "internalType": "string",
1295
+ "name": "",
1296
+ "type": "string"
1297
+ }
1298
+ ],
1299
+ "stateMutability": "pure",
1300
+ "type": "function"
1301
+ },
1302
+ {
1303
+ "inputs": [],
1304
+ "name": "nextPosId",
1305
+ "outputs": [
769
1306
  {
770
1307
  "internalType": "uint256",
771
- "name": "newPriceX96",
1308
+ "name": "",
772
1309
  "type": "uint256"
773
1310
  }
774
1311
  ],
775
- "stateMutability": "nonpayable",
1312
+ "stateMutability": "view",
776
1313
  "type": "function"
777
1314
  },
778
1315
  {
@@ -784,6 +1321,11 @@ var PERP_MANAGER_ABI = [
784
1321
  },
785
1322
  {
786
1323
  "components": [
1324
+ {
1325
+ "internalType": "address",
1326
+ "name": "holder",
1327
+ "type": "address"
1328
+ },
787
1329
  {
788
1330
  "internalType": "uint256",
789
1331
  "name": "margin",
@@ -820,12 +1362,12 @@ var PERP_MANAGER_ABI = [
820
1362
  "type": "tuple"
821
1363
  }
822
1364
  ],
823
- "name": "openMakerPosition",
1365
+ "name": "openMakerPos",
824
1366
  "outputs": [
825
1367
  {
826
- "internalType": "uint128",
827
- "name": "makerPosId",
828
- "type": "uint128"
1368
+ "internalType": "uint256",
1369
+ "name": "posId",
1370
+ "type": "uint256"
829
1371
  }
830
1372
  ],
831
1373
  "stateMutability": "nonpayable",
@@ -840,6 +1382,11 @@ var PERP_MANAGER_ABI = [
840
1382
  },
841
1383
  {
842
1384
  "components": [
1385
+ {
1386
+ "internalType": "address",
1387
+ "name": "holder",
1388
+ "type": "address"
1389
+ },
843
1390
  {
844
1391
  "internalType": "bool",
845
1392
  "name": "isLong",
@@ -866,264 +1413,233 @@ var PERP_MANAGER_ABI = [
866
1413
  "type": "tuple"
867
1414
  }
868
1415
  ],
869
- "name": "openTakerPosition",
1416
+ "name": "openTakerPos",
870
1417
  "outputs": [
871
1418
  {
872
- "internalType": "uint128",
873
- "name": "takerPosId",
874
- "type": "uint128"
1419
+ "internalType": "uint256",
1420
+ "name": "posId",
1421
+ "type": "uint256"
875
1422
  }
876
1423
  ],
877
1424
  "stateMutability": "nonpayable",
878
1425
  "type": "function"
879
1426
  },
1427
+ {
1428
+ "inputs": [],
1429
+ "name": "owner",
1430
+ "outputs": [
1431
+ {
1432
+ "internalType": "address",
1433
+ "name": "result",
1434
+ "type": "address"
1435
+ }
1436
+ ],
1437
+ "stateMutability": "view",
1438
+ "type": "function"
1439
+ },
880
1440
  {
881
1441
  "inputs": [
882
1442
  {
883
- "internalType": "PoolId",
884
- "name": "",
885
- "type": "bytes32"
1443
+ "internalType": "uint256",
1444
+ "name": "id",
1445
+ "type": "uint256"
886
1446
  }
887
1447
  ],
888
- "name": "perps",
1448
+ "name": "ownerOf",
889
1449
  "outputs": [
890
1450
  {
891
1451
  "internalType": "address",
892
- "name": "vault",
893
- "type": "address"
894
- },
895
- {
896
- "internalType": "address",
897
- "name": "beacon",
1452
+ "name": "result",
898
1453
  "type": "address"
899
- },
1454
+ }
1455
+ ],
1456
+ "stateMutability": "view",
1457
+ "type": "function"
1458
+ },
1459
+ {
1460
+ "inputs": [
900
1461
  {
901
1462
  "internalType": "address",
902
- "name": "creator",
1463
+ "name": "pendingOwner",
903
1464
  "type": "address"
904
- },
905
- {
906
- "internalType": "uint32",
907
- "name": "creationTimestamp",
908
- "type": "uint32"
909
- },
910
- {
911
- "internalType": "uint32",
912
- "name": "makerLockupPeriod",
913
- "type": "uint32"
914
- },
1465
+ }
1466
+ ],
1467
+ "name": "ownershipHandoverExpiresAt",
1468
+ "outputs": [
915
1469
  {
916
- "internalType": "uint32",
917
- "name": "twapWindow",
918
- "type": "uint32"
919
- },
1470
+ "internalType": "uint256",
1471
+ "name": "result",
1472
+ "type": "uint256"
1473
+ }
1474
+ ],
1475
+ "stateMutability": "view",
1476
+ "type": "function"
1477
+ },
1478
+ {
1479
+ "inputs": [
920
1480
  {
921
- "internalType": "uint32",
922
- "name": "lastTwPremiumsUpdate",
923
- "type": "uint32"
924
- },
1481
+ "internalType": "uint256",
1482
+ "name": "",
1483
+ "type": "uint256"
1484
+ }
1485
+ ],
1486
+ "name": "positions",
1487
+ "outputs": [
925
1488
  {
926
- "internalType": "uint24",
927
- "name": "creatorFee",
928
- "type": "uint24"
1489
+ "internalType": "PoolId",
1490
+ "name": "perpId",
1491
+ "type": "bytes32"
929
1492
  },
930
1493
  {
931
- "internalType": "uint24",
932
- "name": "insuranceFee",
933
- "type": "uint24"
1494
+ "internalType": "uint256",
1495
+ "name": "margin",
1496
+ "type": "uint256"
934
1497
  },
935
1498
  {
936
- "internalType": "uint24",
937
- "name": "liquidationFee",
938
- "type": "uint24"
1499
+ "internalType": "int256",
1500
+ "name": "entryPerpDelta",
1501
+ "type": "int256"
939
1502
  },
940
1503
  {
941
- "internalType": "uint24",
942
- "name": "liquidatorFeeSplit",
943
- "type": "uint24"
1504
+ "internalType": "int256",
1505
+ "name": "entryUsdDelta",
1506
+ "type": "int256"
944
1507
  },
945
1508
  {
946
- "internalType": "uint128",
947
- "name": "nextPosId",
948
- "type": "uint128"
1509
+ "internalType": "int256",
1510
+ "name": "entryCumlFundingX96",
1511
+ "type": "int256"
949
1512
  },
950
1513
  {
951
1514
  "internalType": "uint256",
952
- "name": "sqrtPriceLowerMultiX96",
1515
+ "name": "entryCumlBadDebtX96",
953
1516
  "type": "uint256"
954
1517
  },
955
1518
  {
956
1519
  "internalType": "uint256",
957
- "name": "sqrtPriceUpperMultiX96",
1520
+ "name": "entryCumlUtilizationX96",
958
1521
  "type": "uint256"
959
1522
  },
960
- {
961
- "internalType": "uint24",
962
- "name": "minOpeningMargin",
963
- "type": "uint24"
964
- },
965
- {
966
- "internalType": "uint24",
967
- "name": "minMakerOpeningMarginRatio",
968
- "type": "uint24"
969
- },
970
- {
971
- "internalType": "uint24",
972
- "name": "maxMakerOpeningMarginRatio",
973
- "type": "uint24"
974
- },
975
- {
976
- "internalType": "uint24",
977
- "name": "makerLiquidationMarginRatio",
978
- "type": "uint24"
979
- },
980
- {
981
- "internalType": "uint24",
982
- "name": "minTakerOpeningMarginRatio",
983
- "type": "uint24"
984
- },
985
- {
986
- "internalType": "uint24",
987
- "name": "maxTakerOpeningMarginRatio",
988
- "type": "uint24"
989
- },
990
- {
991
- "internalType": "uint24",
992
- "name": "takerLiquidationMarginRatio",
993
- "type": "uint24"
994
- },
995
- {
996
- "internalType": "int256",
997
- "name": "twPremiumX96",
998
- "type": "int256"
999
- },
1000
- {
1001
- "internalType": "int256",
1002
- "name": "twPremiumDivBySqrtPriceX96",
1003
- "type": "int256"
1004
- },
1005
- {
1006
- "internalType": "int256",
1007
- "name": "premiumPerSecondX96",
1008
- "type": "int256"
1009
- },
1010
1523
  {
1011
1524
  "components": [
1012
- {
1013
- "internalType": "Currency",
1014
- "name": "currency0",
1015
- "type": "address"
1016
- },
1017
- {
1018
- "internalType": "Currency",
1019
- "name": "currency1",
1020
- "type": "address"
1021
- },
1022
1525
  {
1023
1526
  "internalType": "uint24",
1024
- "name": "fee",
1527
+ "name": "min",
1025
1528
  "type": "uint24"
1026
1529
  },
1027
1530
  {
1028
- "internalType": "int24",
1029
- "name": "tickSpacing",
1030
- "type": "int24"
1531
+ "internalType": "uint24",
1532
+ "name": "max",
1533
+ "type": "uint24"
1031
1534
  },
1032
1535
  {
1033
- "internalType": "contract IHooks",
1034
- "name": "hooks",
1035
- "type": "address"
1536
+ "internalType": "uint24",
1537
+ "name": "liq",
1538
+ "type": "uint24"
1036
1539
  }
1037
1540
  ],
1038
- "internalType": "struct PoolKey",
1039
- "name": "key",
1541
+ "internalType": "struct IMarginRatios.MarginRatios",
1542
+ "name": "marginRatios",
1040
1543
  "type": "tuple"
1041
1544
  },
1042
1545
  {
1043
1546
  "components": [
1044
1547
  {
1045
- "internalType": "uint128",
1046
- "name": "baseFeeX96",
1047
- "type": "uint128"
1048
- },
1049
- {
1050
- "internalType": "uint128",
1051
- "name": "startFeeX96",
1052
- "type": "uint128"
1053
- },
1054
- {
1055
- "internalType": "uint128",
1056
- "name": "targetFeeX96",
1057
- "type": "uint128"
1548
+ "internalType": "uint32",
1549
+ "name": "unlockTimestamp",
1550
+ "type": "uint32"
1058
1551
  },
1059
1552
  {
1060
- "internalType": "uint128",
1061
- "name": "decay",
1062
- "type": "uint128"
1553
+ "internalType": "int24",
1554
+ "name": "tickLower",
1555
+ "type": "int24"
1063
1556
  },
1064
1557
  {
1065
- "internalType": "uint128",
1066
- "name": "volatilityScalerX96",
1067
- "type": "uint128"
1558
+ "internalType": "int24",
1559
+ "name": "tickUpper",
1560
+ "type": "int24"
1068
1561
  },
1069
1562
  {
1070
1563
  "internalType": "uint128",
1071
- "name": "maxFeeMultiplierX96",
1564
+ "name": "liquidity",
1072
1565
  "type": "uint128"
1073
- }
1074
- ],
1075
- "internalType": "struct TradingFee.Config",
1076
- "name": "tradingFeeConfig",
1077
- "type": "tuple"
1078
- },
1079
- {
1080
- "components": [
1081
- {
1082
- "internalType": "uint32",
1083
- "name": "index",
1084
- "type": "uint32"
1085
1566
  },
1086
1567
  {
1087
- "internalType": "uint32",
1088
- "name": "cardinality",
1089
- "type": "uint32"
1568
+ "internalType": "int256",
1569
+ "name": "entryCumlFundingBelowX96",
1570
+ "type": "int256"
1090
1571
  },
1091
1572
  {
1092
- "internalType": "uint32",
1093
- "name": "cardinalityNext",
1094
- "type": "uint32"
1573
+ "internalType": "int256",
1574
+ "name": "entryCumlFundingWithinX96",
1575
+ "type": "int256"
1095
1576
  },
1096
1577
  {
1097
- "components": [
1098
- {
1099
- "internalType": "uint32",
1100
- "name": "blockTimestamp",
1101
- "type": "uint32"
1102
- },
1103
- {
1104
- "internalType": "uint216",
1105
- "name": "cumulativeValue",
1106
- "type": "uint216"
1107
- },
1108
- {
1109
- "internalType": "bool",
1110
- "name": "initialized",
1111
- "type": "bool"
1112
- }
1113
- ],
1114
- "internalType": "struct TimeWeightedAvg.Observation[65535]",
1115
- "name": "observations",
1116
- "type": "tuple[65535]"
1578
+ "internalType": "int256",
1579
+ "name": "entryCumlFundingDivSqrtPWithinX96",
1580
+ "type": "int256"
1117
1581
  }
1118
1582
  ],
1119
- "internalType": "struct TimeWeightedAvg.State",
1120
- "name": "twapState",
1583
+ "internalType": "struct IPerpManager.MakerDetails",
1584
+ "name": "makerDetails",
1121
1585
  "type": "tuple"
1122
1586
  }
1123
1587
  ],
1124
1588
  "stateMutability": "view",
1125
1589
  "type": "function"
1126
1590
  },
1591
+ {
1592
+ "inputs": [],
1593
+ "name": "protocolFee",
1594
+ "outputs": [
1595
+ {
1596
+ "internalType": "uint24",
1597
+ "name": "",
1598
+ "type": "uint24"
1599
+ }
1600
+ ],
1601
+ "stateMutability": "view",
1602
+ "type": "function"
1603
+ },
1604
+ {
1605
+ "inputs": [
1606
+ {
1607
+ "internalType": "uint256",
1608
+ "name": "posId",
1609
+ "type": "uint256"
1610
+ }
1611
+ ],
1612
+ "name": "quoteClosePosition",
1613
+ "outputs": [
1614
+ {
1615
+ "internalType": "bool",
1616
+ "name": "success",
1617
+ "type": "bool"
1618
+ },
1619
+ {
1620
+ "internalType": "int256",
1621
+ "name": "pnl",
1622
+ "type": "int256"
1623
+ },
1624
+ {
1625
+ "internalType": "int256",
1626
+ "name": "funding",
1627
+ "type": "int256"
1628
+ },
1629
+ {
1630
+ "internalType": "uint256",
1631
+ "name": "netMargin",
1632
+ "type": "uint256"
1633
+ },
1634
+ {
1635
+ "internalType": "bool",
1636
+ "name": "wasLiquidated",
1637
+ "type": "bool"
1638
+ }
1639
+ ],
1640
+ "stateMutability": "nonpayable",
1641
+ "type": "function"
1642
+ },
1127
1643
  {
1128
1644
  "inputs": [
1129
1645
  {
@@ -1133,6 +1649,11 @@ var PERP_MANAGER_ABI = [
1133
1649
  },
1134
1650
  {
1135
1651
  "components": [
1652
+ {
1653
+ "internalType": "address",
1654
+ "name": "holder",
1655
+ "type": "address"
1656
+ },
1136
1657
  {
1137
1658
  "internalType": "uint256",
1138
1659
  "name": "margin",
@@ -1169,7 +1690,7 @@ var PERP_MANAGER_ABI = [
1169
1690
  "type": "tuple"
1170
1691
  }
1171
1692
  ],
1172
- "name": "quoteMakerPosition",
1693
+ "name": "quoteOpenMakerPosition",
1173
1694
  "outputs": [
1174
1695
  {
1175
1696
  "internalType": "bool",
@@ -1185,21 +1706,6 @@ var PERP_MANAGER_ABI = [
1185
1706
  "internalType": "int256",
1186
1707
  "name": "usdDelta",
1187
1708
  "type": "int256"
1188
- },
1189
- {
1190
- "internalType": "uint256",
1191
- "name": "creatorFeeAmt",
1192
- "type": "uint256"
1193
- },
1194
- {
1195
- "internalType": "uint256",
1196
- "name": "insuranceFeeAmt",
1197
- "type": "uint256"
1198
- },
1199
- {
1200
- "internalType": "uint256",
1201
- "name": "lpFeeAmt",
1202
- "type": "uint256"
1203
1709
  }
1204
1710
  ],
1205
1711
  "stateMutability": "nonpayable",
@@ -1214,6 +1720,11 @@ var PERP_MANAGER_ABI = [
1214
1720
  },
1215
1721
  {
1216
1722
  "components": [
1723
+ {
1724
+ "internalType": "address",
1725
+ "name": "holder",
1726
+ "type": "address"
1727
+ },
1217
1728
  {
1218
1729
  "internalType": "bool",
1219
1730
  "name": "isLong",
@@ -1240,7 +1751,7 @@ var PERP_MANAGER_ABI = [
1240
1751
  "type": "tuple"
1241
1752
  }
1242
1753
  ],
1243
- "name": "quoteTakerPosition",
1754
+ "name": "quoteOpenTakerPosition",
1244
1755
  "outputs": [
1245
1756
  {
1246
1757
  "internalType": "bool",
@@ -1256,21 +1767,6 @@ var PERP_MANAGER_ABI = [
1256
1767
  "internalType": "int256",
1257
1768
  "name": "usdDelta",
1258
1769
  "type": "int256"
1259
- },
1260
- {
1261
- "internalType": "uint256",
1262
- "name": "creatorFeeAmt",
1263
- "type": "uint256"
1264
- },
1265
- {
1266
- "internalType": "uint256",
1267
- "name": "insuranceFeeAmt",
1268
- "type": "uint256"
1269
- },
1270
- {
1271
- "internalType": "uint256",
1272
- "name": "lpFeeAmt",
1273
- "type": "uint256"
1274
1770
  }
1275
1771
  ],
1276
1772
  "stateMutability": "nonpayable",
@@ -1279,268 +1775,314 @@ var PERP_MANAGER_ABI = [
1279
1775
  {
1280
1776
  "inputs": [
1281
1777
  {
1282
- "internalType": "PoolId",
1283
- "name": "perpId",
1284
- "type": "bytes32"
1778
+ "internalType": "contract IFees",
1779
+ "name": "feesModule",
1780
+ "type": "address"
1285
1781
  }
1286
1782
  ],
1287
- "name": "sqrtPriceX96",
1288
- "outputs": [
1783
+ "name": "registerFeesModule",
1784
+ "outputs": [],
1785
+ "stateMutability": "nonpayable",
1786
+ "type": "function"
1787
+ },
1788
+ {
1789
+ "inputs": [
1289
1790
  {
1290
- "internalType": "uint160",
1291
- "name": "sqrtPrice",
1292
- "type": "uint160"
1791
+ "internalType": "contract ILockupPeriod",
1792
+ "name": "lockupPeriodModule",
1793
+ "type": "address"
1293
1794
  }
1294
1795
  ],
1295
- "stateMutability": "view",
1796
+ "name": "registerLockupPeriodModule",
1797
+ "outputs": [],
1798
+ "stateMutability": "nonpayable",
1296
1799
  "type": "function"
1297
1800
  },
1298
1801
  {
1299
1802
  "inputs": [
1300
1803
  {
1301
- "internalType": "PoolId",
1302
- "name": "perpId",
1303
- "type": "bytes32"
1804
+ "internalType": "contract IMarginRatios",
1805
+ "name": "marginRatiosModule",
1806
+ "type": "address"
1304
1807
  }
1305
1808
  ],
1306
- "name": "tickSpacing",
1307
- "outputs": [
1809
+ "name": "registerMarginRatiosModule",
1810
+ "outputs": [],
1811
+ "stateMutability": "nonpayable",
1812
+ "type": "function"
1813
+ },
1814
+ {
1815
+ "inputs": [
1308
1816
  {
1309
- "internalType": "int24",
1310
- "name": "",
1311
- "type": "int24"
1817
+ "internalType": "contract ISqrtPriceImpactLimit",
1818
+ "name": "sqrtPriceImpactLimitModule",
1819
+ "type": "address"
1312
1820
  }
1313
1821
  ],
1314
- "stateMutability": "view",
1822
+ "name": "registerSqrtPriceImpactLimitModule",
1823
+ "outputs": [],
1824
+ "stateMutability": "nonpayable",
1825
+ "type": "function"
1826
+ },
1827
+ {
1828
+ "inputs": [],
1829
+ "name": "renounceOwnership",
1830
+ "outputs": [],
1831
+ "stateMutability": "payable",
1832
+ "type": "function"
1833
+ },
1834
+ {
1835
+ "inputs": [],
1836
+ "name": "requestOwnershipHandover",
1837
+ "outputs": [],
1838
+ "stateMutability": "payable",
1315
1839
  "type": "function"
1316
1840
  },
1317
1841
  {
1318
1842
  "inputs": [
1319
1843
  {
1320
- "internalType": "PoolId",
1321
- "name": "perpId",
1322
- "type": "bytes32"
1844
+ "internalType": "address",
1845
+ "name": "from",
1846
+ "type": "address"
1847
+ },
1848
+ {
1849
+ "internalType": "address",
1850
+ "name": "to",
1851
+ "type": "address"
1852
+ },
1853
+ {
1854
+ "internalType": "uint256",
1855
+ "name": "id",
1856
+ "type": "uint256"
1323
1857
  }
1324
1858
  ],
1325
- "name": "tradingBounds",
1326
- "outputs": [
1859
+ "name": "safeTransferFrom",
1860
+ "outputs": [],
1861
+ "stateMutability": "payable",
1862
+ "type": "function"
1863
+ },
1864
+ {
1865
+ "inputs": [
1327
1866
  {
1328
- "internalType": "uint24",
1329
- "name": "minOpeningMargin",
1330
- "type": "uint24"
1867
+ "internalType": "address",
1868
+ "name": "from",
1869
+ "type": "address"
1331
1870
  },
1332
1871
  {
1333
- "internalType": "uint24",
1334
- "name": "minMakerMarginRatio",
1335
- "type": "uint24"
1872
+ "internalType": "address",
1873
+ "name": "to",
1874
+ "type": "address"
1336
1875
  },
1337
1876
  {
1338
- "internalType": "uint24",
1339
- "name": "maxMakerMarginRatio",
1340
- "type": "uint24"
1877
+ "internalType": "uint256",
1878
+ "name": "id",
1879
+ "type": "uint256"
1341
1880
  },
1342
1881
  {
1343
- "internalType": "uint24",
1344
- "name": "makerLiquidationMarginRatio",
1345
- "type": "uint24"
1346
- },
1882
+ "internalType": "bytes",
1883
+ "name": "data",
1884
+ "type": "bytes"
1885
+ }
1886
+ ],
1887
+ "name": "safeTransferFrom",
1888
+ "outputs": [],
1889
+ "stateMutability": "payable",
1890
+ "type": "function"
1891
+ },
1892
+ {
1893
+ "inputs": [
1347
1894
  {
1348
- "internalType": "uint24",
1349
- "name": "minTakerMarginRatio",
1350
- "type": "uint24"
1895
+ "internalType": "address",
1896
+ "name": "operator",
1897
+ "type": "address"
1351
1898
  },
1352
1899
  {
1353
- "internalType": "uint24",
1354
- "name": "maxTakerMarginRatio",
1355
- "type": "uint24"
1356
- },
1900
+ "internalType": "bool",
1901
+ "name": "isApproved",
1902
+ "type": "bool"
1903
+ }
1904
+ ],
1905
+ "name": "setApprovalForAll",
1906
+ "outputs": [],
1907
+ "stateMutability": "nonpayable",
1908
+ "type": "function"
1909
+ },
1910
+ {
1911
+ "inputs": [
1357
1912
  {
1358
1913
  "internalType": "uint24",
1359
- "name": "takerLiquidationMarginRatio",
1914
+ "name": "newProtocolFee",
1360
1915
  "type": "uint24"
1361
1916
  }
1362
1917
  ],
1363
- "stateMutability": "view",
1918
+ "name": "setProtocolFee",
1919
+ "outputs": [],
1920
+ "stateMutability": "nonpayable",
1364
1921
  "type": "function"
1365
1922
  },
1366
1923
  {
1367
1924
  "inputs": [
1368
1925
  {
1369
- "internalType": "bytes",
1370
- "name": "data",
1371
- "type": "bytes"
1926
+ "internalType": "bytes4",
1927
+ "name": "interfaceId",
1928
+ "type": "bytes4"
1372
1929
  }
1373
1930
  ],
1374
- "name": "unlockCallback",
1931
+ "name": "supportsInterface",
1375
1932
  "outputs": [
1376
1933
  {
1377
- "internalType": "bytes",
1378
- "name": "encodedDelta",
1379
- "type": "bytes"
1934
+ "internalType": "bool",
1935
+ "name": "result",
1936
+ "type": "bool"
1380
1937
  }
1381
1938
  ],
1382
- "stateMutability": "nonpayable",
1939
+ "stateMutability": "view",
1940
+ "type": "function"
1941
+ },
1942
+ {
1943
+ "inputs": [],
1944
+ "name": "symbol",
1945
+ "outputs": [
1946
+ {
1947
+ "internalType": "string",
1948
+ "name": "",
1949
+ "type": "string"
1950
+ }
1951
+ ],
1952
+ "stateMutability": "pure",
1953
+ "type": "function"
1954
+ },
1955
+ {
1956
+ "inputs": [
1957
+ {
1958
+ "internalType": "PoolId",
1959
+ "name": "perpId",
1960
+ "type": "bytes32"
1961
+ }
1962
+ ],
1963
+ "name": "takerOpenInterest",
1964
+ "outputs": [
1965
+ {
1966
+ "internalType": "uint128",
1967
+ "name": "longOI",
1968
+ "type": "uint128"
1969
+ },
1970
+ {
1971
+ "internalType": "uint128",
1972
+ "name": "shortOI",
1973
+ "type": "uint128"
1974
+ }
1975
+ ],
1976
+ "stateMutability": "view",
1977
+ "type": "function"
1978
+ },
1979
+ {
1980
+ "inputs": [
1981
+ {
1982
+ "internalType": "PoolId",
1983
+ "name": "perpId",
1984
+ "type": "bytes32"
1985
+ },
1986
+ {
1987
+ "internalType": "uint32",
1988
+ "name": "lookbackWindow",
1989
+ "type": "uint32"
1990
+ }
1991
+ ],
1992
+ "name": "timeWeightedAvgSqrtPriceX96",
1993
+ "outputs": [
1994
+ {
1995
+ "internalType": "uint256",
1996
+ "name": "twAvg",
1997
+ "type": "uint256"
1998
+ }
1999
+ ],
2000
+ "stateMutability": "view",
2001
+ "type": "function"
2002
+ },
2003
+ {
2004
+ "inputs": [
2005
+ {
2006
+ "internalType": "uint256",
2007
+ "name": "posId",
2008
+ "type": "uint256"
2009
+ }
2010
+ ],
2011
+ "name": "tokenURI",
2012
+ "outputs": [
2013
+ {
2014
+ "internalType": "string",
2015
+ "name": "",
2016
+ "type": "string"
2017
+ }
2018
+ ],
2019
+ "stateMutability": "pure",
2020
+ "type": "function"
2021
+ },
2022
+ {
2023
+ "inputs": [
2024
+ {
2025
+ "internalType": "address",
2026
+ "name": "from",
2027
+ "type": "address"
2028
+ },
2029
+ {
2030
+ "internalType": "address",
2031
+ "name": "to",
2032
+ "type": "address"
2033
+ },
2034
+ {
2035
+ "internalType": "uint256",
2036
+ "name": "id",
2037
+ "type": "uint256"
2038
+ }
2039
+ ],
2040
+ "name": "transferFrom",
2041
+ "outputs": [],
2042
+ "stateMutability": "payable",
2043
+ "type": "function"
2044
+ },
2045
+ {
2046
+ "inputs": [
2047
+ {
2048
+ "internalType": "address",
2049
+ "name": "newOwner",
2050
+ "type": "address"
2051
+ }
2052
+ ],
2053
+ "name": "transferOwnership",
2054
+ "outputs": [],
2055
+ "stateMutability": "payable",
2056
+ "type": "function"
2057
+ },
2058
+ {
2059
+ "inputs": [
2060
+ {
2061
+ "internalType": "bytes",
2062
+ "name": "data",
2063
+ "type": "bytes"
2064
+ }
2065
+ ],
2066
+ "name": "unlockCallback",
2067
+ "outputs": [
2068
+ {
2069
+ "internalType": "bytes",
2070
+ "name": "encodedDelta",
2071
+ "type": "bytes"
2072
+ }
2073
+ ],
2074
+ "stateMutability": "nonpayable",
1383
2075
  "type": "function"
1384
2076
  }
1385
- ];
1386
-
1387
- // src/utils/liquidity.ts
1388
- async function estimateLiquidity(context, tickLower, tickUpper, usdScaled) {
1389
- return await context.walletClient.readContract({
1390
- address: context.deployments().perpManager,
1391
- abi: PERP_MANAGER_ABI,
1392
- functionName: "estimateLiquidityForAmount1",
1393
- args: [tickLower, tickUpper, usdScaled]
1394
- });
1395
- }
1396
-
1397
- // src/utils/errors.ts
1398
- import { BaseError, ContractFunctionRevertedError } from "viem";
1399
- var PerpCityError = class extends Error {
1400
- constructor(message, cause) {
1401
- super(message);
1402
- this.cause = cause;
1403
- this.name = "PerpCityError";
1404
- }
1405
- };
1406
- var ContractError = class extends PerpCityError {
1407
- constructor(message, errorName, args, cause) {
1408
- super(message, cause);
1409
- this.errorName = errorName;
1410
- this.args = args;
1411
- this.name = "ContractError";
1412
- }
1413
- };
1414
- var TransactionRejectedError = class extends PerpCityError {
1415
- constructor(message = "Transaction rejected by user", cause) {
1416
- super(message, cause);
1417
- this.name = "TransactionRejectedError";
1418
- }
1419
- };
1420
- var InsufficientFundsError = class extends PerpCityError {
1421
- constructor(message = "Insufficient funds for transaction", cause) {
1422
- super(message, cause);
1423
- this.name = "InsufficientFundsError";
1424
- }
1425
- };
1426
- var GraphQLError = class extends PerpCityError {
1427
- constructor(message, cause) {
1428
- super(message, cause);
1429
- this.name = "GraphQLError";
1430
- }
1431
- };
1432
- var RPCError = class extends PerpCityError {
1433
- constructor(message, cause) {
1434
- super(message, cause);
1435
- this.name = "RPCError";
1436
- }
1437
- };
1438
- var ValidationError = class extends PerpCityError {
1439
- constructor(message, cause) {
1440
- super(message, cause);
1441
- this.name = "ValidationError";
1442
- }
1443
- };
1444
- function parseContractError(error) {
1445
- if (error instanceof PerpCityError) {
1446
- return error;
1447
- }
1448
- if (error instanceof BaseError) {
1449
- const revertError = error.walk((err) => err instanceof ContractFunctionRevertedError);
1450
- if (revertError instanceof ContractFunctionRevertedError) {
1451
- const errorName = revertError.data?.errorName ?? "Unknown";
1452
- const args = revertError.data?.args ?? [];
1453
- const message = formatContractError(errorName, args);
1454
- return new ContractError(message, errorName, args, error);
1455
- }
1456
- if (error.message?.includes("User rejected") || error.code === 4001) {
1457
- return new TransactionRejectedError(error.message, error);
1458
- }
1459
- if (error.message?.includes("insufficient funds")) {
1460
- return new InsufficientFundsError(error.message, error);
1461
- }
1462
- return new PerpCityError(error.shortMessage || error.message, error);
1463
- }
1464
- if (error instanceof Error) {
1465
- return new PerpCityError(error.message, error);
1466
- }
1467
- return new PerpCityError(String(error));
1468
- }
1469
- function formatContractError(errorName, args) {
1470
- switch (errorName) {
1471
- case "InvalidBeaconAddress":
1472
- return `Invalid beacon address: ${args[0]}`;
1473
- case "InvalidTradingFeeSplits":
1474
- return `Invalid trading fee splits. Insurance split: ${args[0]}, Creator split: ${args[1]}`;
1475
- case "InvalidMaxOpeningLev":
1476
- return `Invalid maximum opening leverage: ${args[0]}`;
1477
- case "InvalidLiquidationLev":
1478
- return `Invalid liquidation leverage: ${args[0]}. Must be less than max opening leverage: ${args[1]}`;
1479
- case "InvalidLiquidationFee":
1480
- return `Invalid liquidation fee: ${args[0]}`;
1481
- case "InvalidLiquidatorFeeSplit":
1482
- return `Invalid liquidator fee split: ${args[0]}`;
1483
- case "InvalidClose":
1484
- return `Cannot close position. Caller: ${args[0]}, Holder: ${args[1]}, Is Liquidated: ${args[2]}`;
1485
- case "InvalidCaller":
1486
- return `Invalid caller. Expected: ${args[1]}, Got: ${args[0]}`;
1487
- case "InvalidLiquidity":
1488
- return `Invalid liquidity amount: ${args[0]}`;
1489
- case "InvalidMargin":
1490
- return `Invalid margin amount: ${args[0]}`;
1491
- case "InvalidLevX96":
1492
- return `Invalid leverage: ${args[0]}. Maximum allowed: ${args[1]}`;
1493
- case "MakerPositionLocked":
1494
- return `Maker position is locked until ${new Date(Number(args[1]) * 1e3).toISOString()}. Current time: ${new Date(Number(args[0]) * 1e3).toISOString()}`;
1495
- case "MaximumAmountExceeded":
1496
- return `Maximum amount exceeded. Maximum: ${args[0]}, Requested: ${args[1]}`;
1497
- case "MinimumAmountInsufficient":
1498
- return `Minimum amount not met. Required: ${args[0]}, Received: ${args[1]}`;
1499
- case "PriceImpactTooHigh":
1500
- return `Price impact too high. Current price: ${args[0]}, Min acceptable: ${args[1]}, Max acceptable: ${args[2]}`;
1501
- case "SwapReverted":
1502
- return "Swap failed. This may be due to insufficient liquidity or slippage tolerance.";
1503
- case "ZeroSizePosition":
1504
- return `Cannot create zero-size position. Perp delta: ${args[0]}, USD delta: ${args[1]}`;
1505
- case "InvalidFundingInterval":
1506
- return `Invalid funding interval: ${args[0]}`;
1507
- case "InvalidPriceImpactBand":
1508
- return `Invalid price impact band: ${args[0]}`;
1509
- case "InvalidMarketDeathThreshold":
1510
- return `Invalid market death threshold: ${args[0]}`;
1511
- case "InvalidTickRange":
1512
- return `Invalid tick range. Lower: ${args[0]}, Upper: ${args[1]}`;
1513
- case "MarketNotKillable":
1514
- return `Market health (${args[0]}) is above death threshold (${args[1]}). Market cannot be killed yet.`;
1515
- case "InvalidStartingSqrtPriceX96":
1516
- return `Invalid starting sqrt price: ${args[0]}`;
1517
- default:
1518
- return `Contract error: ${errorName}${args.length > 0 ? ` (${args.join(", ")})` : ""}`;
1519
- }
1520
- }
1521
- async function withErrorHandling(fn, context) {
1522
- try {
1523
- return await fn();
1524
- } catch (error) {
1525
- const parsedError = parseContractError(error);
1526
- parsedError.message = `${context}: ${parsedError.message}`;
1527
- throw parsedError;
1528
- }
1529
- }
2077
+ ];
1530
2078
 
1531
2079
  // src/context.ts
1532
2080
  import { erc20Abi as erc20Abi2 } from "viem";
1533
2081
  var PerpCityContext = class {
1534
2082
  constructor(config) {
2083
+ this.configCache = /* @__PURE__ */ new Map();
1535
2084
  this.walletClient = config.walletClient.extend(publicActions);
1536
2085
  this._deployments = config.deployments;
1537
- const headers = {};
1538
- if (config.goldskyBearerToken) {
1539
- headers.authorization = `Bearer ${config.goldskyBearerToken}`;
1540
- }
1541
- this.goldskyClient = new GraphQLClient(config.goldskyEndpoint, {
1542
- headers
1543
- });
1544
2086
  }
1545
2087
  deployments() {
1546
2088
  return this._deployments;
@@ -1548,154 +2090,68 @@ var PerpCityContext = class {
1548
2090
  // Optimized batch data fetching methods
1549
2091
  async fetchPerpData(perpId) {
1550
2092
  return withErrorHandling(async () => {
1551
- const perpQuery = parse(`
1552
- query ($perpId: Bytes!) {
1553
- perp(id: $perpId) {
1554
- beacon { id }
1555
- }
1556
- perpSnapshots(
1557
- orderBy: timestamp
1558
- orderDirection: asc
1559
- where: { perp: $perpId }
1560
- ) {
1561
- timestamp
1562
- markPrice
1563
- takerLongNotional
1564
- takerShortNotional
1565
- fundingRate
1566
- }
1567
- }
1568
- `);
1569
- const beaconQuery = parse(`
1570
- query ($beaconAddr: Bytes!) {
1571
- beaconSnapshots(
1572
- orderBy: timestamp
1573
- orderDirection: asc
1574
- where: { beacon: $beaconAddr }
1575
- ) {
1576
- timestamp
1577
- indexPrice
1578
- }
1579
- }
1580
- `);
1581
- let perpResponse;
1582
- try {
1583
- perpResponse = await this.goldskyClient.request(perpQuery, { perpId });
1584
- } catch (error) {
1585
- throw new GraphQLError(`Failed to fetch perp data for ${perpId}: ${error instanceof Error ? error.message : String(error)}`, error instanceof Error ? error : void 0);
1586
- }
1587
- if (!perpResponse.perp || !perpResponse.perp.beacon) {
1588
- throw new GraphQLError(`Perp ${perpId} not found or has no beacon`);
1589
- }
1590
- let beaconResponse;
1591
- let contractData;
1592
- try {
1593
- [beaconResponse, contractData] = await Promise.all([
1594
- this.goldskyClient.request(beaconQuery, { beaconAddr: perpResponse.perp.beacon.id }),
1595
- this.fetchPerpContractData(perpId)
1596
- ]);
1597
- } catch (error) {
1598
- if (error instanceof GraphQLError || error instanceof RPCError) {
1599
- throw error;
1600
- }
1601
- throw new GraphQLError(`Failed to fetch beacon or contract data: ${error instanceof Error ? error.message : String(error)}`, error instanceof Error ? error : void 0);
1602
- }
1603
- if (perpResponse.perpSnapshots.length === 0) {
1604
- throw new GraphQLError(`No perpSnapshots found for perp ${perpId}. This perp may be newly created with no trading activity yet.`);
1605
- }
1606
- if (beaconResponse.beaconSnapshots.length === 0) {
1607
- throw new GraphQLError(`No beaconSnapshots found for perp ${perpId} beacon ${perpResponse.perp.beacon.id}. The beacon may not have any price updates yet.`);
1608
- }
1609
- const markTimeSeries = perpResponse.perpSnapshots.map((snapshot) => ({
1610
- timestamp: Number(snapshot.timestamp),
1611
- value: Number(formatUnits(BigInt(snapshot.markPrice), 6))
1612
- }));
1613
- const indexTimeSeries = beaconResponse.beaconSnapshots.map((snapshot) => ({
1614
- timestamp: Number(snapshot.timestamp),
1615
- value: Number(formatUnits(BigInt(snapshot.indexPrice), 6))
1616
- }));
1617
- const openInterestTimeSeries = perpResponse.perpSnapshots.map((snapshot) => ({
1618
- timestamp: Number(snapshot.timestamp),
1619
- value: {
1620
- takerLongNotional: Number(formatUnits(BigInt(snapshot.takerLongNotional), 6)),
1621
- takerShortNotional: Number(formatUnits(BigInt(snapshot.takerShortNotional), 6))
1622
- }
1623
- }));
1624
- const fundingRateTimeSeries = perpResponse.perpSnapshots.map((snapshot) => ({
1625
- timestamp: Number(snapshot.timestamp),
1626
- value: Number(formatUnits(BigInt(snapshot.fundingRate), 6))
1627
- }));
1628
- const latestSnapshot = perpResponse.perpSnapshots[perpResponse.perpSnapshots.length - 1];
1629
- const latestBeaconSnapshot = beaconResponse.beaconSnapshots[beaconResponse.beaconSnapshots.length - 1];
2093
+ const contractData = await this.fetchPerpContractData(perpId);
2094
+ const config = await this.getPerpConfig(perpId);
1630
2095
  const perpData = {
1631
2096
  id: perpId,
1632
2097
  tickSpacing: contractData.tickSpacing,
1633
2098
  mark: sqrtPriceX96ToPrice(contractData.sqrtPriceX96),
1634
- index: Number(formatUnits(BigInt(latestBeaconSnapshot.indexPrice), 6)),
1635
- beacon: perpResponse.perp.beacon.id,
1636
- lastIndexUpdate: Number(latestBeaconSnapshot.timestamp),
1637
- openInterest: {
1638
- takerLongNotional: Number(formatUnits(BigInt(latestSnapshot.takerLongNotional), 6)),
1639
- takerShortNotional: Number(formatUnits(BigInt(latestSnapshot.takerShortNotional), 6))
1640
- },
1641
- markTimeSeries,
1642
- indexTimeSeries,
1643
- fundingRate: Number(formatUnits(BigInt(latestSnapshot.fundingRate), 6)),
2099
+ beacon: config.beacon,
1644
2100
  bounds: contractData.bounds,
1645
- fees: contractData.fees,
1646
- openInterestTimeSeries,
1647
- fundingRateTimeSeries,
1648
- totalOpenMakerPnl: 0,
1649
- // These will be calculated by functions
1650
- totalOpenTakerPnl: 0
1651
- // These will be calculated by functions
2101
+ fees: contractData.fees
1652
2102
  };
1653
2103
  return perpData;
1654
2104
  }, `fetchPerpData for perp ${perpId}`);
1655
2105
  }
1656
- async fetchPerpContractData(perpId) {
2106
+ /**
2107
+ * Fetches and caches the config for a perpId
2108
+ * The config includes module addresses (fees, marginRatios, etc.) and pool settings
2109
+ */
2110
+ async getPerpConfig(perpId) {
2111
+ const cached = this.configCache.get(perpId);
2112
+ if (cached) {
2113
+ return cached;
2114
+ }
2115
+ const cfg = await this.walletClient.readContract({
2116
+ address: this.deployments().perpManager,
2117
+ abi: PERP_MANAGER_ABI,
2118
+ functionName: "cfgs",
2119
+ args: [perpId]
2120
+ });
2121
+ this.configCache.set(perpId, cfg);
2122
+ return cfg;
2123
+ }
2124
+ async fetchPerpContractData(perpId, markPrice) {
1657
2125
  return withErrorHandling(async () => {
1658
- const [tickSpacing, sqrtPriceX96, boundsRaw, feesRaw] = await Promise.all([
1659
- this.walletClient.readContract({
1660
- address: this.deployments().perpManager,
1661
- abi: PERP_MANAGER_ABI,
1662
- functionName: "tickSpacing",
1663
- args: [perpId]
1664
- }),
1665
- this.walletClient.readContract({
1666
- address: this.deployments().perpManager,
1667
- abi: PERP_MANAGER_ABI,
1668
- functionName: "sqrtPriceX96",
1669
- args: [perpId]
1670
- }),
1671
- this.walletClient.readContract({
1672
- address: this.deployments().perpManager,
1673
- abi: PERP_MANAGER_ABI,
1674
- functionName: "tradingBounds",
1675
- args: [perpId]
1676
- }),
1677
- this.walletClient.readContract({
2126
+ const cfg = await this.getPerpConfig(perpId);
2127
+ const tickSpacing = Number(cfg.key.tickSpacing);
2128
+ let sqrtPriceX96;
2129
+ if (markPrice) {
2130
+ const sqrtPrice = Math.sqrt(markPrice);
2131
+ sqrtPriceX96 = BigInt(Math.floor(sqrtPrice * 2 ** 96));
2132
+ } else {
2133
+ sqrtPriceX96 = await this.walletClient.readContract({
1678
2134
  address: this.deployments().perpManager,
1679
2135
  abi: PERP_MANAGER_ABI,
1680
- functionName: "fees",
1681
- args: [perpId]
1682
- })
1683
- ]);
1684
- const bounds = boundsRaw;
1685
- const fees = feesRaw;
2136
+ functionName: "timeWeightedAvgSqrtPriceX96",
2137
+ args: [perpId, 1]
2138
+ });
2139
+ }
1686
2140
  return {
1687
- tickSpacing: Number(tickSpacing),
2141
+ tickSpacing,
1688
2142
  sqrtPriceX96,
1689
2143
  bounds: {
1690
- minMargin: Number(formatUnits(bounds[0], 6)),
1691
- minTakerLeverage: marginRatioToLeverage(Number(formatUnits(bounds[4], 6))),
1692
- maxTakerLeverage: marginRatioToLeverage(Number(formatUnits(bounds[5], 6)))
2144
+ minMargin: 10,
2145
+ // Placeholder - would need to call cfg.marginRatios contract
2146
+ minTakerLeverage: 1.1,
2147
+ maxTakerLeverage: 20
1693
2148
  },
1694
2149
  fees: {
1695
- creatorFee: Number(formatUnits(fees[0], 6)),
1696
- insuranceFee: Number(formatUnits(fees[1], 6)),
1697
- lpFee: Number(formatUnits(fees[2], 6)),
1698
- liquidationFee: Number(formatUnits(fees[3], 6))
2150
+ creatorFee: 1e-4,
2151
+ // Placeholder - would need to call cfg.fees contract
2152
+ insuranceFee: 1e-4,
2153
+ lpFee: 3e-4,
2154
+ liquidationFee: 0.01
1699
2155
  }
1700
2156
  };
1701
2157
  }, `fetchPerpContractData for perp ${perpId}`);
@@ -1706,283 +2162,73 @@ var PerpCityContext = class {
1706
2162
  async getPerpData(perpId) {
1707
2163
  return this.fetchPerpData(perpId);
1708
2164
  }
1709
- /**
1710
- * Fetch data for multiple perps efficiently with true batching
1711
- * This fetches all perps in just 2 Goldsky requests total (not 2N!)
1712
- */
1713
- async getMultiplePerpData(perpIds) {
1714
- if (perpIds.length === 0) {
1715
- return /* @__PURE__ */ new Map();
1716
- }
1717
- if (perpIds.length === 1) {
1718
- const data = await this.fetchPerpData(perpIds[0]);
1719
- return /* @__PURE__ */ new Map([[perpIds[0], data]]);
1720
- }
1721
- const batchPerpQuery = parse(`
1722
- query ($perpIds: [Bytes!]!) {
1723
- perps(where: { id_in: $perpIds }) {
1724
- id
1725
- beacon { id }
1726
- }
1727
- perpSnapshots(
1728
- orderBy: timestamp
1729
- orderDirection: asc
1730
- where: { perp_in: $perpIds }
1731
- ) {
1732
- perp { id }
1733
- timestamp
1734
- markPrice
1735
- takerLongNotional
1736
- takerShortNotional
1737
- fundingRate
1738
- }
1739
- }
1740
- `);
1741
- const perpResponse = await this.goldskyClient.request(batchPerpQuery, { perpIds });
1742
- const beaconIds = [...new Set(perpResponse.perps.map((p) => p.beacon.id))];
1743
- const batchBeaconQuery = parse(`
1744
- query ($beaconIds: [Bytes!]!) {
1745
- beaconSnapshots(
1746
- orderBy: timestamp
1747
- orderDirection: asc
1748
- where: { beacon_in: $beaconIds }
1749
- ) {
1750
- beacon { id }
1751
- timestamp
1752
- indexPrice
1753
- }
1754
- }
1755
- `);
1756
- const [beaconResponse, contractDataMap] = await Promise.all([
1757
- this.goldskyClient.request(batchBeaconQuery, { beaconIds }),
1758
- this.fetchMultiplePerpContractData(perpIds)
1759
- ]);
1760
- const snapshotsByPerp = /* @__PURE__ */ new Map();
1761
- perpResponse.perpSnapshots.forEach((snapshot) => {
1762
- const perpId = snapshot.perp.id;
1763
- if (!snapshotsByPerp.has(perpId)) {
1764
- snapshotsByPerp.set(perpId, []);
1765
- }
1766
- snapshotsByPerp.get(perpId).push(snapshot);
1767
- });
1768
- const snapshotsByBeacon = /* @__PURE__ */ new Map();
1769
- beaconResponse.beaconSnapshots.forEach((snapshot) => {
1770
- const beaconId = snapshot.beacon.id;
1771
- if (!snapshotsByBeacon.has(beaconId)) {
1772
- snapshotsByBeacon.set(beaconId, []);
1773
- }
1774
- snapshotsByBeacon.get(beaconId).push(snapshot);
2165
+ async fetchUserData(userAddress, positions) {
2166
+ const usdcBalance = await this.walletClient.readContract({
2167
+ address: this.deployments().usdc,
2168
+ abi: erc20Abi2,
2169
+ functionName: "balanceOf",
2170
+ args: [userAddress]
1775
2171
  });
1776
- const perpLookup = new Map(
1777
- perpResponse.perps.map((p) => [
1778
- p.id,
1779
- p
1780
- ])
1781
- );
1782
- const resultMap = /* @__PURE__ */ new Map();
1783
- for (const perpId of perpIds) {
1784
- const perp = perpLookup.get(perpId);
1785
- if (!perp) {
1786
- throw new Error(`Perp ${perpId} not found`);
1787
- }
1788
- const beaconId = perp.beacon.id;
1789
- const snapshots = snapshotsByPerp.get(perpId) || [];
1790
- const beaconSnapshots = snapshotsByBeacon.get(beaconId) || [];
1791
- const contractData = contractDataMap.get(perpId);
1792
- if (!contractData) {
1793
- throw new Error(`Contract data for perp ${perpId} not found`);
1794
- }
1795
- if (snapshots.length === 0) {
1796
- throw new Error(`No snapshots found for perp ${perpId}`);
1797
- }
1798
- if (beaconSnapshots.length === 0) {
1799
- throw new Error(`No beacon snapshots found for perp ${perpId}`);
1800
- }
1801
- const markTimeSeries = snapshots.map((snapshot) => ({
1802
- timestamp: Number(snapshot.timestamp),
1803
- value: Number(formatUnits(BigInt(snapshot.markPrice), 6))
1804
- }));
1805
- const indexTimeSeries = beaconSnapshots.map((snapshot) => ({
1806
- timestamp: Number(snapshot.timestamp),
1807
- value: Number(formatUnits(BigInt(snapshot.indexPrice), 6))
1808
- }));
1809
- const openInterestTimeSeries = snapshots.map((snapshot) => ({
1810
- timestamp: Number(snapshot.timestamp),
1811
- value: {
1812
- takerLongNotional: Number(formatUnits(BigInt(snapshot.takerLongNotional), 6)),
1813
- takerShortNotional: Number(formatUnits(BigInt(snapshot.takerShortNotional), 6))
1814
- }
1815
- }));
1816
- const fundingRateTimeSeries = snapshots.map((snapshot) => ({
1817
- timestamp: Number(snapshot.timestamp),
1818
- value: Number(formatUnits(BigInt(snapshot.fundingRate), 6))
1819
- }));
1820
- const latestSnapshot = snapshots[snapshots.length - 1];
1821
- const latestBeaconSnapshot = beaconSnapshots[beaconSnapshots.length - 1];
1822
- const perpData = {
1823
- id: perpId,
1824
- tickSpacing: contractData.tickSpacing,
1825
- mark: sqrtPriceX96ToPrice(contractData.sqrtPriceX96),
1826
- index: Number(formatUnits(BigInt(latestBeaconSnapshot.indexPrice), 6)),
1827
- beacon: beaconId,
1828
- lastIndexUpdate: Number(latestBeaconSnapshot.timestamp),
1829
- openInterest: {
1830
- takerLongNotional: Number(formatUnits(BigInt(latestSnapshot.takerLongNotional), 6)),
1831
- takerShortNotional: Number(formatUnits(BigInt(latestSnapshot.takerShortNotional), 6))
1832
- },
1833
- markTimeSeries,
1834
- indexTimeSeries,
1835
- fundingRate: Number(formatUnits(BigInt(latestSnapshot.fundingRate), 6)),
1836
- bounds: contractData.bounds,
1837
- fees: contractData.fees,
1838
- openInterestTimeSeries,
1839
- fundingRateTimeSeries,
1840
- totalOpenMakerPnl: 0,
1841
- totalOpenTakerPnl: 0
1842
- };
1843
- resultMap.set(perpId, perpData);
1844
- }
1845
- return resultMap;
1846
- }
1847
- async fetchMultiplePerpContractData(perpIds) {
1848
- const results = await Promise.all(
1849
- perpIds.map(async (perpId) => ({
1850
- perpId,
1851
- data: await this.fetchPerpContractData(perpId)
1852
- }))
1853
- );
1854
- return new Map(results.map(({ perpId, data }) => [perpId, data]));
1855
- }
1856
- async fetchUserData(userAddress) {
1857
- const [usdcBalance, openPositionsData, closedPositionsData] = await Promise.all([
1858
- this.walletClient.readContract({
1859
- address: this.deployments().usdc,
1860
- abi: erc20Abi2,
1861
- functionName: "balanceOf",
1862
- args: [userAddress]
1863
- }),
1864
- this.fetchUserOpenPositions(userAddress),
1865
- this.fetchUserClosedPositions(userAddress)
1866
- ]);
1867
- const realizedPnl = closedPositionsData.reduce((acc, position) => acc + position.pnlAtClose, 0);
1868
- const unrealizedPnl = openPositionsData.reduce(
1869
- (acc, position) => acc + position.liveDetails.pnl - position.liveDetails.fundingPayment,
1870
- 0
1871
- );
1872
- return {
1873
- walletAddress: userAddress,
1874
- usdcBalance: Number(formatUnits(usdcBalance, 6)),
1875
- openPositions: openPositionsData,
1876
- closedPositions: closedPositionsData,
1877
- realizedPnl,
1878
- unrealizedPnl
1879
- };
1880
- }
1881
- async fetchUserOpenPositions(userAddress) {
1882
- const query = parse(`
1883
- query ($holder: Bytes!) {
1884
- openPositions(
1885
- where: { holder: $holder }
1886
- ) {
1887
- perp { id }
1888
- inContractPosId
1889
- isLong
1890
- isMaker
1891
- }
1892
- }
1893
- `);
1894
- const response = await this.goldskyClient.request(query, { holder: userAddress });
1895
- const positionsWithDetails = await Promise.all(
1896
- response.openPositions.map(async (position) => {
1897
- const positionId = typeof position.inContractPosId === "bigint" ? position.inContractPosId : BigInt(position.inContractPosId);
1898
- const liveDetails = await this.fetchPositionLiveDetailsFromContract(
1899
- position.perp.id,
1900
- positionId
1901
- );
2172
+ const openPositionsData = await Promise.all(
2173
+ positions.map(async ({ perpId, positionId, isLong, isMaker }) => {
2174
+ const liveDetails = await this.fetchPositionLiveDetailsFromContract(perpId, positionId);
1902
2175
  return {
1903
- perpId: position.perp.id,
2176
+ perpId,
1904
2177
  positionId,
1905
- isLong: position.isLong,
1906
- isMaker: position.isMaker,
2178
+ isLong,
2179
+ isMaker,
1907
2180
  liveDetails
1908
2181
  };
1909
2182
  })
1910
2183
  );
1911
- return positionsWithDetails;
1912
- }
1913
- async fetchUserClosedPositions(userAddress) {
1914
- const query = parse(`
1915
- query ($holder: Bytes!) {
1916
- closedPositions(
1917
- where: { holder: $holder }
1918
- ) {
1919
- perp { id }
1920
- wasMaker
1921
- wasLong
1922
- pnlAtClose
1923
- }
1924
- }
1925
- `);
1926
- const response = await this.goldskyClient.request(query, { holder: userAddress });
1927
- return response.closedPositions.map((position) => ({
1928
- perpId: position.perp.id,
1929
- wasMaker: position.wasMaker,
1930
- wasLong: position.wasLong,
1931
- pnlAtClose: Number(formatUnits(BigInt(position.pnlAtClose), 6))
1932
- }));
2184
+ return {
2185
+ walletAddress: userAddress,
2186
+ usdcBalance: Number(formatUnits(usdcBalance, 6)),
2187
+ openPositions: openPositionsData
2188
+ };
1933
2189
  }
1934
2190
  async fetchPositionLiveDetailsFromContract(perpId, positionId) {
1935
2191
  return withErrorHandling(async () => {
1936
2192
  const result = await this.walletClient.readContract({
1937
2193
  address: this.deployments().perpManager,
1938
2194
  abi: PERP_MANAGER_ABI,
1939
- functionName: "livePositionDetails",
1940
- args: [perpId, positionId]
2195
+ functionName: "quoteClosePosition",
2196
+ args: [positionId]
1941
2197
  });
2198
+ const [success, pnl, funding, netMargin, wasLiquidated] = result;
2199
+ if (!success) {
2200
+ throw new Error(`Failed to quote position ${positionId} - position may be invalid or already closed`);
2201
+ }
1942
2202
  return {
1943
- pnl: Number(formatUnits(result[0], 6)),
1944
- fundingPayment: Number(formatUnits(result[1], 6)),
1945
- effectiveMargin: Number(formatUnits(result[2], 6)),
1946
- isLiquidatable: result[3]
2203
+ pnl: Number(formatUnits(pnl, 6)),
2204
+ fundingPayment: Number(formatUnits(funding, 6)),
2205
+ effectiveMargin: Number(formatUnits(netMargin, 6)),
2206
+ isLiquidatable: wasLiquidated
1947
2207
  };
1948
2208
  }, `fetchPositionLiveDetailsFromContract for position ${positionId}`);
1949
2209
  }
1950
2210
  /**
1951
- * Fetch comprehensive user data with all positions in a single batched request
2211
+ * Fetch comprehensive user data with live details for all positions
2212
+ * @param userAddress - The user's wallet address
2213
+ * @param positions - Array of position metadata (perpId, positionId, isLong, isMaker) tracked from transaction receipts
1952
2214
  */
1953
- async getUserData(userAddress) {
1954
- return this.fetchUserData(userAddress);
2215
+ async getUserData(userAddress, positions) {
2216
+ return this.fetchUserData(userAddress, positions);
1955
2217
  }
1956
2218
  /**
1957
2219
  * Fetch open position data with live details
2220
+ * @param perpId - The perpetual market ID
2221
+ * @param positionId - The position ID
2222
+ * @param isLong - Whether the position is long (true) or short (false)
2223
+ * @param isMaker - Whether the position is a maker (LP) position
1958
2224
  */
1959
- async getOpenPositionData(perpId, positionId) {
1960
- const query = parse(`
1961
- query ($perpId: Bytes!, $posId: BigInt!) {
1962
- openPositions(
1963
- where: { perp: $perpId, inContractPosId: $posId }
1964
- first: 1
1965
- ) {
1966
- isLong
1967
- isMaker
1968
- }
1969
- }
1970
- `);
1971
- const [positionResponse, liveDetails] = await Promise.all([
1972
- this.goldskyClient.request(query, { perpId, posId: positionId.toString() }),
1973
- this.fetchPositionLiveDetailsFromContract(perpId, positionId)
1974
- ]);
1975
- const position = positionResponse.openPositions[0];
1976
- if (!position) {
1977
- throw new Error(
1978
- `Position not found in GraphQL: perpId=${perpId}, positionId=${positionId}. The position may not exist or may have been closed.`
1979
- );
1980
- }
2225
+ async getOpenPositionData(perpId, positionId, isLong, isMaker) {
2226
+ const liveDetails = await this.fetchPositionLiveDetailsFromContract(perpId, positionId);
1981
2227
  return {
1982
2228
  perpId,
1983
2229
  positionId,
1984
- isLong: position.isLong,
1985
- isMaker: position.isMaker,
2230
+ isLong,
2231
+ isMaker,
1986
2232
  liveDetails
1987
2233
  };
1988
2234
  }
@@ -2244,6 +2490,26 @@ var BEACON_ABI = [
2244
2490
  }
2245
2491
  ];
2246
2492
 
2493
+ // src/functions/perp.ts
2494
+ function getPerpMark(perpData) {
2495
+ return perpData.mark;
2496
+ }
2497
+ function getPerpBeacon(perpData) {
2498
+ return perpData.beacon;
2499
+ }
2500
+ function getPerpBounds(perpData) {
2501
+ return perpData.bounds;
2502
+ }
2503
+ function getPerpFees(perpData) {
2504
+ return perpData.fees;
2505
+ }
2506
+ function getPerpTickSpacing(perpData) {
2507
+ return perpData.tickSpacing;
2508
+ }
2509
+
2510
+ // src/functions/perp-manager.ts
2511
+ import { publicActions as publicActions3, decodeEventLog as decodeEventLog2 } from "viem";
2512
+
2247
2513
  // src/functions/open-position.ts
2248
2514
  import { publicActions as publicActions2, formatUnits as formatUnits2, decodeEventLog } from "viem";
2249
2515
  var OpenPosition = class _OpenPosition {
@@ -2262,11 +2528,11 @@ var OpenPosition = class _OpenPosition {
2262
2528
  minAmt1Out: scale6Decimals(params.minAmt1Out),
2263
2529
  maxAmt1In: scale6Decimals(params.maxAmt1In)
2264
2530
  };
2265
- const { result, request } = await this.context.walletClient.extend(publicActions2).simulateContract({
2531
+ const { request } = await this.context.walletClient.extend(publicActions2).simulateContract({
2266
2532
  address: this.context.deployments().perpManager,
2267
2533
  abi: PERP_MANAGER_ABI,
2268
2534
  functionName: "closePosition",
2269
- args: [this.perpId, contractParams],
2535
+ args: [contractParams],
2270
2536
  account: this.context.walletClient.account
2271
2537
  });
2272
2538
  const txHash = await this.context.walletClient.writeContract(request);
@@ -2275,21 +2541,35 @@ var OpenPosition = class _OpenPosition {
2275
2541
  if (receipt.status === "reverted") {
2276
2542
  throw new Error(`Transaction reverted. Hash: ${txHash}`);
2277
2543
  }
2278
- let newPositionId = result && result !== 0n ? result : null;
2544
+ let newPositionId = null;
2545
+ let wasFullyClosed = false;
2279
2546
  for (const log of receipt.logs) {
2280
2547
  try {
2281
- const closedDecoded = decodeEventLog({
2548
+ const openedDecoded = decodeEventLog({
2282
2549
  abi: PERP_MANAGER_ABI,
2283
2550
  data: log.data,
2284
2551
  topics: log.topics,
2285
- eventName: "PositionClosed"
2552
+ eventName: "PositionOpened"
2286
2553
  });
2287
- if (closedDecoded.args.perpId === this.perpId && closedDecoded.args.posId === this.positionId) {
2288
- newPositionId = null;
2554
+ if (openedDecoded.args.perpId === this.perpId) {
2555
+ newPositionId = openedDecoded.args.posId;
2289
2556
  break;
2290
2557
  }
2291
2558
  } catch (e) {
2292
- continue;
2559
+ try {
2560
+ const closedDecoded = decodeEventLog({
2561
+ abi: PERP_MANAGER_ABI,
2562
+ data: log.data,
2563
+ topics: log.topics,
2564
+ eventName: "PositionClosed"
2565
+ });
2566
+ if (closedDecoded.args.perpId === this.perpId && closedDecoded.args.posId === this.positionId) {
2567
+ wasFullyClosed = true;
2568
+ break;
2569
+ }
2570
+ } catch (e2) {
2571
+ continue;
2572
+ }
2293
2573
  }
2294
2574
  }
2295
2575
  if (!newPositionId) {
@@ -2303,141 +2583,42 @@ var OpenPosition = class _OpenPosition {
2303
2583
  const result = await this.context.walletClient.readContract({
2304
2584
  address: this.context.deployments().perpManager,
2305
2585
  abi: PERP_MANAGER_ABI,
2306
- functionName: "livePositionDetails",
2307
- args: [this.perpId, this.positionId]
2586
+ functionName: "quoteClosePosition",
2587
+ args: [this.positionId]
2308
2588
  });
2589
+ const [success, pnl, funding, netMargin, wasLiquidated] = result;
2590
+ if (!success) {
2591
+ throw new Error(`Failed to quote position ${this.positionId} - position may be invalid or already closed`);
2592
+ }
2309
2593
  return {
2310
- pnl: Number(formatUnits2(result[0], 6)),
2311
- fundingPayment: Number(formatUnits2(result[1], 6)),
2312
- effectiveMargin: Number(formatUnits2(result[2], 6)),
2313
- isLiquidatable: result[3]
2594
+ pnl: Number(formatUnits2(pnl, 6)),
2595
+ fundingPayment: Number(formatUnits2(funding, 6)),
2596
+ effectiveMargin: Number(formatUnits2(netMargin, 6)),
2597
+ isLiquidatable: wasLiquidated
2314
2598
  };
2315
2599
  }, `liveDetails for position ${this.positionId}`);
2316
2600
  }
2317
2601
  };
2318
2602
 
2319
- // src/functions/perp.ts
2320
- function getPerpMark(perpData) {
2321
- return perpData.mark;
2322
- }
2323
- function getPerpIndex(perpData) {
2324
- return perpData.index;
2325
- }
2326
- function getPerpBeacon(perpData) {
2327
- return perpData.beacon;
2328
- }
2329
- function getPerpLastIndexUpdate(perpData) {
2330
- return perpData.lastIndexUpdate;
2331
- }
2332
- function getPerpOpenInterest(perpData) {
2333
- return perpData.openInterest;
2334
- }
2335
- function getPerpMarkTimeSeries(perpData) {
2336
- return perpData.markTimeSeries;
2337
- }
2338
- function getPerpIndexTimeSeries(perpData) {
2339
- return perpData.indexTimeSeries;
2340
- }
2341
- function getPerpFundingRate(perpData) {
2342
- return perpData.fundingRate;
2343
- }
2344
- function getPerpBounds(perpData) {
2345
- return perpData.bounds;
2346
- }
2347
- function getPerpFees(perpData) {
2348
- return perpData.fees;
2349
- }
2350
- function getPerpOpenInterestTimeSeries(perpData) {
2351
- return perpData.openInterestTimeSeries;
2352
- }
2353
- function getPerpFundingRateTimeSeries(perpData) {
2354
- return perpData.fundingRateTimeSeries;
2355
- }
2356
- function getPerpTickSpacing(perpData) {
2357
- return perpData.tickSpacing;
2358
- }
2359
- async function getAllMakerPositions(context, perpId) {
2360
- const query = `
2361
- query ($perpId: Bytes!) {
2362
- openPositions(
2363
- where: { perp: $perpId, isMaker: true }
2364
- ) {
2365
- perp { id }
2366
- inContractPosId
2367
- isLong
2368
- isMaker
2369
- }
2370
- }
2371
- `;
2372
- const response = await context.goldskyClient.request(query, { perpId });
2373
- return response.openPositions.map(
2374
- (position) => new OpenPosition(
2375
- context,
2376
- position.perp.id,
2377
- BigInt(position.inContractPosId),
2378
- position.isLong,
2379
- position.isMaker
2380
- )
2381
- );
2382
- }
2383
- async function getAllTakerPositions(context, perpId) {
2384
- const query = `
2385
- query ($perpId: Bytes!) {
2386
- openPositions(
2387
- where: { perp: $perpId, isMaker: false }
2388
- ) {
2389
- perp { id }
2390
- inContractPosId
2391
- isLong
2392
- isMaker
2393
- }
2394
- }
2395
- `;
2396
- const response = await context.goldskyClient.request(query, { perpId });
2397
- return response.openPositions.map(
2398
- (position) => new OpenPosition(
2399
- context,
2400
- position.perp.id,
2401
- BigInt(position.inContractPosId),
2402
- position.isLong,
2403
- position.isMaker
2404
- )
2405
- );
2406
- }
2407
- async function getTotalOpenMakerPnl(context, perpId) {
2408
- const positions = await getAllMakerPositions(context, perpId);
2409
- const liveDetails = await Promise.all(positions.map((position) => position.liveDetails()));
2410
- return liveDetails.reduce((acc, detail) => acc + detail.pnl - detail.fundingPayment, 0);
2411
- }
2412
- async function getTotalOpenTakerPnl(context, perpId) {
2413
- const positions = await getAllTakerPositions(context, perpId);
2414
- const liveDetails = await Promise.all(positions.map((position) => position.liveDetails()));
2415
- return liveDetails.reduce((acc, detail) => acc + detail.pnl - detail.fundingPayment, 0);
2416
- }
2417
-
2418
2603
  // src/functions/perp-manager.ts
2419
- import { publicActions as publicActions3, decodeEventLog as decodeEventLog2 } from "viem";
2420
- import { gql } from "graphql-request";
2421
- import { parse as parse2 } from "graphql";
2422
- async function getPerps(context) {
2423
- return withErrorHandling(async () => {
2424
- const query = parse2(gql`
2425
- {
2426
- perps {
2427
- id
2428
- }
2429
- }
2430
- `);
2431
- const response = await context.goldskyClient.request(query);
2432
- return response.perps.map((perpData) => perpData.id);
2433
- }, "getPerps");
2434
- }
2435
2604
  async function createPerp(context, params) {
2436
2605
  return withErrorHandling(async () => {
2437
2606
  const sqrtPriceX96 = priceToSqrtPriceX96(params.startingPrice);
2607
+ const deployments = context.deployments();
2608
+ const fees = params.fees ?? deployments.feesModule;
2609
+ const marginRatios = params.marginRatios ?? deployments.marginRatiosModule;
2610
+ const lockupPeriod = params.lockupPeriod ?? deployments.lockupPeriodModule;
2611
+ const sqrtPriceImpactLimit = params.sqrtPriceImpactLimit ?? deployments.sqrtPriceImpactLimitModule;
2612
+ if (!fees || !marginRatios || !lockupPeriod || !sqrtPriceImpactLimit) {
2613
+ throw new Error("Module addresses must be provided either in params or deployment config");
2614
+ }
2438
2615
  const contractParams = {
2439
- startingSqrtPriceX96: sqrtPriceX96,
2440
- beacon: params.beacon
2616
+ beacon: params.beacon,
2617
+ fees,
2618
+ marginRatios,
2619
+ lockupPeriod,
2620
+ sqrtPriceImpactLimit,
2621
+ startingSqrtPriceX96: sqrtPriceX96
2441
2622
  };
2442
2623
  const { request } = await context.walletClient.simulateContract({
2443
2624
  address: context.deployments().perpManager,
@@ -2474,6 +2655,7 @@ async function openTakerPosition(context, perpId, params) {
2474
2655
  await approveUsdc(context, marginScaled);
2475
2656
  const levX96 = scaleToX96(params.leverage);
2476
2657
  const contractParams = {
2658
+ holder: context.walletClient.account.address,
2477
2659
  isLong: params.isLong,
2478
2660
  margin: marginScaled,
2479
2661
  levX96,
@@ -2482,7 +2664,7 @@ async function openTakerPosition(context, perpId, params) {
2482
2664
  const { request } = await context.walletClient.simulateContract({
2483
2665
  address: context.deployments().perpManager,
2484
2666
  abi: PERP_MANAGER_ABI,
2485
- functionName: "openTakerPosition",
2667
+ functionName: "openTakerPos",
2486
2668
  args: [perpId, contractParams],
2487
2669
  account: context.walletClient.account
2488
2670
  });
@@ -2526,6 +2708,7 @@ async function openMakerPosition(context, perpId, params) {
2526
2708
  const alignedTickLower = Math.floor(tickLower / tickSpacing) * tickSpacing;
2527
2709
  const alignedTickUpper = Math.ceil(tickUpper / tickSpacing) * tickSpacing;
2528
2710
  const contractParams = {
2711
+ holder: context.walletClient.account.address,
2529
2712
  margin: marginScaled,
2530
2713
  liquidity: params.liquidity,
2531
2714
  tickLower: alignedTickLower,
@@ -2536,7 +2719,7 @@ async function openMakerPosition(context, perpId, params) {
2536
2719
  const { request } = await context.walletClient.simulateContract({
2537
2720
  address: context.deployments().perpManager,
2538
2721
  abi: PERP_MANAGER_ABI,
2539
- functionName: "openMakerPosition",
2722
+ functionName: "openMakerPos",
2540
2723
  args: [perpId, contractParams],
2541
2724
  account: context.walletClient.account
2542
2725
  });
@@ -2577,15 +2760,6 @@ function getUserUsdcBalance(userData) {
2577
2760
  function getUserOpenPositions(userData) {
2578
2761
  return userData.openPositions;
2579
2762
  }
2580
- function getUserClosedPositions(userData) {
2581
- return userData.closedPositions;
2582
- }
2583
- function getUserRealizedPnl(userData) {
2584
- return userData.realizedPnl;
2585
- }
2586
- function getUserUnrealizedPnl(userData) {
2587
- return userData.unrealizedPnl;
2588
- }
2589
2763
  function getUserWalletAddress(userData) {
2590
2764
  return userData.walletAddress;
2591
2765
  }
@@ -2632,7 +2806,7 @@ async function closePosition(context, perpId, positionId, params) {
2632
2806
  address: context.deployments().perpManager,
2633
2807
  abi: PERP_MANAGER_ABI,
2634
2808
  functionName: "closePosition",
2635
- args: [perpId, contractParams],
2809
+ args: [contractParams],
2636
2810
  account: context.walletClient.account
2637
2811
  });
2638
2812
  const txHash = await context.walletClient.writeContract(request);
@@ -2673,14 +2847,18 @@ async function getPositionLiveDetailsFromContract(context, perpId, positionId) {
2673
2847
  const result = await context.walletClient.readContract({
2674
2848
  address: context.deployments().perpManager,
2675
2849
  abi: PERP_MANAGER_ABI,
2676
- functionName: "livePositionDetails",
2677
- args: [perpId, positionId]
2850
+ functionName: "quoteClosePosition",
2851
+ args: [positionId]
2678
2852
  });
2853
+ const [success, pnl, funding, netMargin, wasLiquidated] = result;
2854
+ if (!success) {
2855
+ throw new Error(`Failed to quote position ${positionId} - position may be invalid or already closed`);
2856
+ }
2679
2857
  return {
2680
- pnl: Number(formatUnits3(result[0], 6)),
2681
- fundingPayment: Number(formatUnits3(result[1], 6)),
2682
- effectiveMargin: Number(formatUnits3(result[2], 6)),
2683
- isLiquidatable: result[3]
2858
+ pnl: Number(formatUnits3(pnl, 6)),
2859
+ fundingPayment: Number(formatUnits3(funding, 6)),
2860
+ effectiveMargin: Number(formatUnits3(netMargin, 6)),
2861
+ isLiquidatable: wasLiquidated
2684
2862
  };
2685
2863
  }, `getPositionLiveDetailsFromContract for position ${positionId}`);
2686
2864
  }
@@ -2688,7 +2866,6 @@ export {
2688
2866
  BEACON_ABI,
2689
2867
  BIGINT_1E6,
2690
2868
  ContractError,
2691
- GraphQLError,
2692
2869
  InsufficientFundsError,
2693
2870
  NUMBER_1E6,
2694
2871
  OpenPosition,
@@ -2703,22 +2880,11 @@ export {
2703
2880
  closePosition,
2704
2881
  createPerp,
2705
2882
  estimateLiquidity,
2706
- getAllMakerPositions,
2707
- getAllTakerPositions,
2708
2883
  getPerpBeacon,
2709
2884
  getPerpBounds,
2710
2885
  getPerpFees,
2711
- getPerpFundingRate,
2712
- getPerpFundingRateTimeSeries,
2713
- getPerpIndex,
2714
- getPerpIndexTimeSeries,
2715
- getPerpLastIndexUpdate,
2716
2886
  getPerpMark,
2717
- getPerpMarkTimeSeries,
2718
- getPerpOpenInterest,
2719
- getPerpOpenInterestTimeSeries,
2720
2887
  getPerpTickSpacing,
2721
- getPerps,
2722
2888
  getPositionEffectiveMargin,
2723
2889
  getPositionFundingPayment,
2724
2890
  getPositionId,
@@ -2729,12 +2895,8 @@ export {
2729
2895
  getPositionLiveDetailsFromContract,
2730
2896
  getPositionPerpId,
2731
2897
  getPositionPnl,
2732
- getTotalOpenMakerPnl,
2733
- getTotalOpenTakerPnl,
2734
- getUserClosedPositions,
2898
+ getRpcUrl,
2735
2899
  getUserOpenPositions,
2736
- getUserRealizedPnl,
2737
- getUserUnrealizedPnl,
2738
2900
  getUserUsdcBalance,
2739
2901
  getUserWalletAddress,
2740
2902
  marginRatioToLeverage,