@panoptic-eng/sdk 1.0.36 → 1.0.38
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/cow/index.d.ts +4 -5
- package/dist/cow/index.js +3 -3
- package/dist/cow/types.d.ts +3 -2
- package/dist/{cow-aX6of9TS.js → cow-DB8siv6M.js} +2 -2
- package/dist/{cow-aX6of9TS.js.map → cow-DB8siv6M.js.map} +1 -1
- package/dist/deployments.d.ts +3 -2
- package/dist/deployments.d.ts.map +1 -1
- package/dist/deployments.js +4 -0
- package/dist/deployments.js.map +1 -1
- package/dist/{position-C8rkkKhi.js → getTrackedPositionIds-zYPIs5dt.js} +1086 -34
- package/dist/getTrackedPositionIds-zYPIs5dt.js.map +1 -0
- package/dist/hypoVault/vaultDisplayNames.d.ts +2 -0
- package/dist/hypoVault/vaultDisplayNames.js +4 -0
- package/dist/{index-CURXeKNy.d.ts → index-BhEBx83X.d.ts} +405 -351
- package/dist/index-BhEBx83X.d.ts.map +1 -0
- package/dist/index-Bo9tHtD7.d.ts +1901 -0
- package/dist/index-Bo9tHtD7.d.ts.map +1 -0
- package/dist/{index-Cp-nCeV2.d.ts → index-CttjEZ-S.d.ts} +3 -4
- package/dist/index-CttjEZ-S.d.ts.map +1 -0
- package/dist/{index-Zvu-rJpV.d.ts → index-DktZq9Kb.d.ts} +2 -2
- package/dist/{index-Zvu-rJpV.d.ts.map → index-DktZq9Kb.d.ts.map} +1 -1
- package/dist/index.d.ts +159 -39
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +323 -70
- package/dist/index.js.map +1 -1
- package/dist/{irm-DnM96-X4.js → irm-ChkvYphK.js} +3 -318
- package/dist/irm-ChkvYphK.js.map +1 -0
- package/dist/{irm-CmgC1Mqi.d.ts → irm-D2WTHtuo.d.ts} +3 -30
- package/dist/{irm-CmgC1Mqi.d.ts.map → irm-D2WTHtuo.d.ts.map} +1 -1
- package/dist/irm-D5plRhpB.d.ts +32 -0
- package/dist/irm-D5plRhpB.d.ts.map +1 -0
- package/dist/panoptic/v2/greeks/index.d.ts +3 -2
- package/dist/panoptic/v2/index.d.ts +7 -8
- package/dist/panoptic/v2/index.js +7 -6
- package/dist/panoptic/v2/react-public.d.ts +29 -13
- package/dist/panoptic/v2/react-public.d.ts.map +1 -1
- package/dist/panoptic/v2/react-public.js +48 -8
- package/dist/panoptic/v2/react-public.js.map +1 -1
- package/dist/panoptic/v2/types/index.d.ts +3 -0
- package/dist/panoptic/v2/types/index.js +0 -0
- package/dist/quote-DeHNUR0Z.d.ts +52 -0
- package/dist/quote-DeHNUR0Z.d.ts.map +1 -0
- package/dist/{router-CS86ptMu.js → router-BCUJkY8j.js} +3 -3
- package/dist/{router-CS86ptMu.js.map → router-BCUJkY8j.js.map} +1 -1
- package/dist/{router-DcoU2KmV.js → router-tCRa0ekE.js} +2 -2
- package/dist/{router-DcoU2KmV.js.map → router-tCRa0ekE.js.map} +1 -1
- package/dist/src-CRAtPwWk.js +321 -0
- package/dist/src-CRAtPwWk.js.map +1 -0
- package/dist/test/index.d.ts +2 -2
- package/dist/test/index.d.ts.map +1 -1
- package/dist/transactionFees-CVi2TrJh.js +175 -0
- package/dist/transactionFees-CVi2TrJh.js.map +1 -0
- package/dist/transactionFees-DzDyt50k.d.ts +63 -0
- package/dist/transactionFees-DzDyt50k.d.ts.map +1 -0
- package/dist/{types-D_jcYss-.d.ts → types-Cad5m4Td.d.ts} +3 -5
- package/dist/types-Cad5m4Td.d.ts.map +1 -0
- package/dist/{types-BHdnurYr.d.ts → types-DM0nxlZr.d.ts} +2 -2
- package/dist/{types-BHdnurYr.d.ts.map → types-DM0nxlZr.d.ts.map} +1 -1
- package/dist/uniswap/index.d.ts +4 -5
- package/dist/uniswap/index.d.ts.map +1 -1
- package/dist/uniswap/index.js +4 -4
- package/dist/{v2-D0dEatKb.js → v2-BxtzpUnV.js} +3267 -2675
- package/dist/v2-BxtzpUnV.js.map +1 -0
- package/dist/vault-transaction-fees.d.ts +2 -0
- package/dist/vault-transaction-fees.js +3 -0
- package/dist/vaultDisplayNames-CKpz51Hu.js +0 -0
- package/dist/vaultDisplayNames-Q6htUcch.d.ts +2 -0
- package/dist/{writes-AupZCK4M.js → writes-D3bj1wth.js} +326 -1292
- package/dist/writes-D3bj1wth.js.map +1 -0
- package/package.json +5 -1
- package/dist/index-CURXeKNy.d.ts.map +0 -1
- package/dist/index-Cp-nCeV2.d.ts.map +0 -1
- package/dist/irm-DnM96-X4.js.map +0 -1
- package/dist/position-BqIgubs5.d.ts +0 -199
- package/dist/position-BqIgubs5.d.ts.map +0 -1
- package/dist/position-C8rkkKhi.js.map +0 -1
- package/dist/quote-BxQkPBRg.d.ts +0 -718
- package/dist/quote-BxQkPBRg.d.ts.map +0 -1
- package/dist/simulation-zM6-YUaw.d.ts +0 -258
- package/dist/simulation-zM6-YUaw.d.ts.map +0 -1
- package/dist/tx-CbDQ58Io.d.ts +0 -367
- package/dist/tx-CbDQ58Io.d.ts.map +0 -1
- package/dist/types-D_jcYss-.d.ts.map +0 -1
- package/dist/v2-D0dEatKb.js.map +0 -1
- package/dist/writes-AupZCK4M.js.map +0 -1
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { BatchValidationError$1 as BatchValidationError, DEFAULT_VEGOID$1 as DEFAULT_VEGOID, InputListFailError$1 as InputListFailError, InvalidTickLimitsError, InvalidTokenIdParameterError$1 as InvalidTokenIdParameterError, LEG_BITS$1 as LEG_BITS, LEG_LIMITS$1 as LEG_LIMITS, LEG_MASKS$1 as LEG_MASKS, LoanSlotExhaustedError$1 as LoanSlotExhaustedError, MaxRetriesExceededError$1 as MaxRetriesExceededError, MissingPositionIdsError$1 as MissingPositionIdsError, NoLoanPositionsError, OracleRateLimitedError$1 as OracleRateLimitedError, PanopticError
|
|
2
|
-
import { REORG_DEPTH,
|
|
3
|
-
import {
|
|
1
|
+
import { BatchValidationError$1 as BatchValidationError, DEFAULT_VEGOID$1 as DEFAULT_VEGOID, InputListFailError$1 as InputListFailError, InvalidTickLimitsError, InvalidTokenIdParameterError$1 as InvalidTokenIdParameterError, LEG_BITS$1 as LEG_BITS, LEG_LIMITS$1 as LEG_LIMITS, LEG_MASKS$1 as LEG_MASKS, LoanSlotExhaustedError$1 as LoanSlotExhaustedError, MaxRetriesExceededError$1 as MaxRetriesExceededError, MissingPositionIdsError$1 as MissingPositionIdsError, NoLoanPositionsError, OracleRateLimitedError$1 as OracleRateLimitedError, PanopticError$1 as PanopticError, PositionSnapshotNotFoundError$1 as PositionSnapshotNotFoundError, ProviderLagError$1 as ProviderLagError, STRIKE_CONVERSION_FACTOR, SwapTokenMismatchError$1 as SwapTokenMismatchError, SyncTimeoutError$1 as SyncTimeoutError, TOKEN_ID_BITS$1 as TOKEN_ID_BITS, collateralTrackerV2Abi, createTxResult, decodeLeftRightUnsigned$1 as decodeLeftRightUnsigned, decodeOracleTiming$1 as decodeOracleTiming, getBlockMeta$1 as getBlockMeta, getOpenPositionIds$1 as getOpenPositionIds, getPool$1 as getPool, getPoolMetaKey$1 as getPoolMetaKey, getPoolMetadata$1 as getPoolMetadata, getPositionMetaKey$1 as getPositionMetaKey, getPositions$1 as getPositions, getPositionsKey$1 as getPositionsKey, getSyncCheckpointKey$1 as getSyncCheckpointKey, getTrackedPositionIds$1 as getTrackedPositionIds, jsonSerializer$1 as jsonSerializer, oracleEpochAt$1 as oracleEpochAt, panopticErrorsAbi, panopticFactoryV3Abi, panopticFactoryV4Abi, panopticPoolV2Abi, parsePanopticError$1 as parsePanopticError, submitWrite } from "./getTrackedPositionIds-zYPIs5dt.js";
|
|
2
|
+
import { REORG_DEPTH, calculatePositionGreeks, tickLimits } from "./greeks-GysWXct-.js";
|
|
3
|
+
import { decodeFunctionResult, encodeFunctionData, erc20Abi, getAbiItem } from "viem";
|
|
4
4
|
|
|
5
5
|
//#region src/panoptic/v2/writes/broadcaster.ts
|
|
6
6
|
/**
|
|
@@ -341,822 +341,6 @@ async function redeemAndWait(params) {
|
|
|
341
341
|
return result.wait();
|
|
342
342
|
}
|
|
343
343
|
|
|
344
|
-
//#endregion
|
|
345
|
-
//#region src/panoptic/v2/storage/fileStorage.ts
|
|
346
|
-
/**
|
|
347
|
-
* Creates a file-based storage adapter for Node.js environments.
|
|
348
|
-
* Stores data as JSON files in the specified directory.
|
|
349
|
-
*
|
|
350
|
-
* The directory will be created if it doesn't exist.
|
|
351
|
-
*
|
|
352
|
-
* @param directory - Path to the storage directory
|
|
353
|
-
*
|
|
354
|
-
* @example
|
|
355
|
-
* ```typescript
|
|
356
|
-
* import { createFileStorage, createConfig } from 'panoptic-v2-sdk'
|
|
357
|
-
*
|
|
358
|
-
* // Node.js only
|
|
359
|
-
* const config = createConfig({
|
|
360
|
-
* chainId: 1n,
|
|
361
|
-
* transport: http('...'),
|
|
362
|
-
* poolAddress: '0x...',
|
|
363
|
-
* storage: createFileStorage('./panoptic-cache'),
|
|
364
|
-
* })
|
|
365
|
-
* ```
|
|
366
|
-
*/
|
|
367
|
-
function createFileStorage(directory) {
|
|
368
|
-
let fsPromises = null;
|
|
369
|
-
let pathModule = null;
|
|
370
|
-
let initialized = false;
|
|
371
|
-
const ensureInitialized = async () => {
|
|
372
|
-
if (initialized) return;
|
|
373
|
-
fsPromises = await import("node:fs/promises");
|
|
374
|
-
pathModule = await import("node:path");
|
|
375
|
-
await fsPromises.mkdir(directory, { recursive: true });
|
|
376
|
-
initialized = true;
|
|
377
|
-
};
|
|
378
|
-
const getFilePath = (key) => {
|
|
379
|
-
if (!pathModule) throw new Error("File storage not initialized");
|
|
380
|
-
const safeKey = Buffer.from(key).toString("base64url");
|
|
381
|
-
return pathModule.join(directory, `${safeKey}.json`);
|
|
382
|
-
};
|
|
383
|
-
return {
|
|
384
|
-
async get(key) {
|
|
385
|
-
await ensureInitialized();
|
|
386
|
-
if (!fsPromises) throw new Error("File storage not initialized");
|
|
387
|
-
try {
|
|
388
|
-
const filePath = getFilePath(key);
|
|
389
|
-
const content = await fsPromises.readFile(filePath, "utf-8");
|
|
390
|
-
return content;
|
|
391
|
-
} catch (error) {
|
|
392
|
-
if (error.code === "ENOENT") return null;
|
|
393
|
-
throw error;
|
|
394
|
-
}
|
|
395
|
-
},
|
|
396
|
-
async set(key, value) {
|
|
397
|
-
await ensureInitialized();
|
|
398
|
-
if (!fsPromises) throw new Error("File storage not initialized");
|
|
399
|
-
const filePath = getFilePath(key);
|
|
400
|
-
await fsPromises.writeFile(filePath, value, "utf-8");
|
|
401
|
-
},
|
|
402
|
-
async delete(key) {
|
|
403
|
-
await ensureInitialized();
|
|
404
|
-
if (!fsPromises) throw new Error("File storage not initialized");
|
|
405
|
-
try {
|
|
406
|
-
const filePath = getFilePath(key);
|
|
407
|
-
await fsPromises.unlink(filePath);
|
|
408
|
-
} catch (error) {
|
|
409
|
-
if (error.code !== "ENOENT") throw error;
|
|
410
|
-
}
|
|
411
|
-
},
|
|
412
|
-
async has(key) {
|
|
413
|
-
await ensureInitialized();
|
|
414
|
-
if (!fsPromises) throw new Error("File storage not initialized");
|
|
415
|
-
try {
|
|
416
|
-
const filePath = getFilePath(key);
|
|
417
|
-
await fsPromises.access(filePath);
|
|
418
|
-
return true;
|
|
419
|
-
} catch {
|
|
420
|
-
return false;
|
|
421
|
-
}
|
|
422
|
-
},
|
|
423
|
-
async keys(prefix) {
|
|
424
|
-
await ensureInitialized();
|
|
425
|
-
if (!fsPromises || !pathModule) throw new Error("File storage not initialized");
|
|
426
|
-
const result = [];
|
|
427
|
-
try {
|
|
428
|
-
const files = await fsPromises.readdir(directory);
|
|
429
|
-
for (const file of files) if (file.endsWith(".json")) {
|
|
430
|
-
const safeKey = file.slice(0, -5);
|
|
431
|
-
try {
|
|
432
|
-
const key = Buffer.from(safeKey, "base64url").toString();
|
|
433
|
-
if (key.startsWith(prefix)) result.push(key);
|
|
434
|
-
} catch {}
|
|
435
|
-
}
|
|
436
|
-
} catch (error) {
|
|
437
|
-
if (error.code !== "ENOENT") throw error;
|
|
438
|
-
}
|
|
439
|
-
return result;
|
|
440
|
-
},
|
|
441
|
-
async clear(prefix) {
|
|
442
|
-
await ensureInitialized();
|
|
443
|
-
if (!fsPromises) throw new Error("File storage not initialized");
|
|
444
|
-
const keysToDelete = await this.keys(prefix);
|
|
445
|
-
for (const key of keysToDelete) await this.delete(key);
|
|
446
|
-
}
|
|
447
|
-
};
|
|
448
|
-
}
|
|
449
|
-
|
|
450
|
-
//#endregion
|
|
451
|
-
//#region src/panoptic/v2/storage/keys.ts
|
|
452
|
-
/**
|
|
453
|
-
* Get the schema version key.
|
|
454
|
-
*/
|
|
455
|
-
function getSchemaVersionKey() {
|
|
456
|
-
return `${STORAGE_PREFIX}:schemaVersion`;
|
|
457
|
-
}
|
|
458
|
-
/**
|
|
459
|
-
* Get the base prefix for a specific pool.
|
|
460
|
-
*/
|
|
461
|
-
function getPoolPrefix(chainId, poolAddress) {
|
|
462
|
-
return `${STORAGE_PREFIX}:v${SCHEMA_VERSION}:chain${chainId}:pool${poolAddress.toLowerCase()}`;
|
|
463
|
-
}
|
|
464
|
-
/**
|
|
465
|
-
* Get the key for tracked position IDs.
|
|
466
|
-
*/
|
|
467
|
-
function getPositionsKey(chainId, poolAddress, account) {
|
|
468
|
-
return `${getPoolPrefix(chainId, poolAddress)}:positions:${account.toLowerCase()}`;
|
|
469
|
-
}
|
|
470
|
-
/**
|
|
471
|
-
* Get the key for position mint metadata.
|
|
472
|
-
*/
|
|
473
|
-
function getPositionMetaKey(chainId, poolAddress, tokenId) {
|
|
474
|
-
return `${getPoolPrefix(chainId, poolAddress)}:positionMeta:${tokenId.toString()}`;
|
|
475
|
-
}
|
|
476
|
-
/**
|
|
477
|
-
* Get the key for sync checkpoint.
|
|
478
|
-
*/
|
|
479
|
-
function getSyncCheckpointKey(chainId, poolAddress, account) {
|
|
480
|
-
return `${getPoolPrefix(chainId, poolAddress)}:sync:${account.toLowerCase()}`;
|
|
481
|
-
}
|
|
482
|
-
/**
|
|
483
|
-
* Get the key for closed positions.
|
|
484
|
-
*/
|
|
485
|
-
function getClosedPositionsKey(chainId, poolAddress, account) {
|
|
486
|
-
return `${getPoolPrefix(chainId, poolAddress)}:closed:${account.toLowerCase()}`;
|
|
487
|
-
}
|
|
488
|
-
/**
|
|
489
|
-
* Get the key for tracked chunks.
|
|
490
|
-
*/
|
|
491
|
-
function getTrackedChunksKey(chainId, poolAddress) {
|
|
492
|
-
return `${getPoolPrefix(chainId, poolAddress)}:chunks`;
|
|
493
|
-
}
|
|
494
|
-
/**
|
|
495
|
-
* Get the key for pending positions.
|
|
496
|
-
*/
|
|
497
|
-
function getPendingPositionsKey(chainId, poolAddress, account) {
|
|
498
|
-
return `${getPoolPrefix(chainId, poolAddress)}:pending:${account.toLowerCase()}`;
|
|
499
|
-
}
|
|
500
|
-
/**
|
|
501
|
-
* Get the key for pool metadata (tickSpacing, etc.).
|
|
502
|
-
*/
|
|
503
|
-
function getPoolMetaKey(chainId, poolAddress) {
|
|
504
|
-
return `${getPoolPrefix(chainId, poolAddress)}:poolMeta`;
|
|
505
|
-
}
|
|
506
|
-
|
|
507
|
-
//#endregion
|
|
508
|
-
//#region src/panoptic/v2/storage/memoryStorage.ts
|
|
509
|
-
/**
|
|
510
|
-
* Creates an in-memory storage adapter.
|
|
511
|
-
* Useful for testing and development.
|
|
512
|
-
*
|
|
513
|
-
* Data is lost when the process exits.
|
|
514
|
-
*
|
|
515
|
-
* @example
|
|
516
|
-
* ```typescript
|
|
517
|
-
* import { createMemoryStorage, createConfig } from 'panoptic-v2-sdk'
|
|
518
|
-
*
|
|
519
|
-
* const config = createConfig({
|
|
520
|
-
* chainId: 1n,
|
|
521
|
-
* transport: http('...'),
|
|
522
|
-
* poolAddress: '0x...',
|
|
523
|
-
* storage: createMemoryStorage(),
|
|
524
|
-
* })
|
|
525
|
-
* ```
|
|
526
|
-
*/
|
|
527
|
-
function createMemoryStorage() {
|
|
528
|
-
const store = new Map();
|
|
529
|
-
return {
|
|
530
|
-
async get(key) {
|
|
531
|
-
return store.get(key) ?? null;
|
|
532
|
-
},
|
|
533
|
-
async set(key, value) {
|
|
534
|
-
store.set(key, value);
|
|
535
|
-
},
|
|
536
|
-
async delete(key) {
|
|
537
|
-
store.delete(key);
|
|
538
|
-
},
|
|
539
|
-
async has(key) {
|
|
540
|
-
return store.has(key);
|
|
541
|
-
},
|
|
542
|
-
async keys(prefix) {
|
|
543
|
-
const result = [];
|
|
544
|
-
for (const key of store.keys()) if (key.startsWith(prefix)) result.push(key);
|
|
545
|
-
return result;
|
|
546
|
-
},
|
|
547
|
-
async clear(prefix) {
|
|
548
|
-
const keysToDelete = [];
|
|
549
|
-
for (const key of store.keys()) if (key.startsWith(prefix)) keysToDelete.push(key);
|
|
550
|
-
for (const key of keysToDelete) store.delete(key);
|
|
551
|
-
}
|
|
552
|
-
};
|
|
553
|
-
}
|
|
554
|
-
|
|
555
|
-
//#endregion
|
|
556
|
-
//#region src/panoptic/v2/storage/serializer.ts
|
|
557
|
-
/**
|
|
558
|
-
* Type guard to check if a value is a tagged BigInt.
|
|
559
|
-
*/
|
|
560
|
-
function isBigIntTagged(value) {
|
|
561
|
-
return value !== null && typeof value === "object" && "__type" in value && value.__type === "bigint" && "value" in value && typeof value.value === "string";
|
|
562
|
-
}
|
|
563
|
-
/**
|
|
564
|
-
* Replacer function for JSON.stringify that tags BigInt values.
|
|
565
|
-
*/
|
|
566
|
-
function replacer(_key, value) {
|
|
567
|
-
if (typeof value === "bigint") return {
|
|
568
|
-
__type: "bigint",
|
|
569
|
-
value: value.toString()
|
|
570
|
-
};
|
|
571
|
-
return value;
|
|
572
|
-
}
|
|
573
|
-
/**
|
|
574
|
-
* Reviver function for JSON.parse that restores tagged BigInt values.
|
|
575
|
-
*/
|
|
576
|
-
function reviver(_key, value) {
|
|
577
|
-
if (isBigIntTagged(value)) return BigInt(value.value);
|
|
578
|
-
return value;
|
|
579
|
-
}
|
|
580
|
-
/**
|
|
581
|
-
* BigInt-safe JSON serializer for the Panoptic v2 SDK.
|
|
582
|
-
*
|
|
583
|
-
* This serializer handles BigInt values by tagging them with a special format
|
|
584
|
-
* that can be restored on parse. The format is compatible with superjson
|
|
585
|
-
* patterns used in Next.js and Remix for SSR hydration.
|
|
586
|
-
*
|
|
587
|
-
* @example
|
|
588
|
-
* ```typescript
|
|
589
|
-
* import { jsonSerializer } from 'panoptic-v2-sdk'
|
|
590
|
-
*
|
|
591
|
-
* const data = { amount: 1000000000000000000n, nested: { value: 42n } }
|
|
592
|
-
*
|
|
593
|
-
* // Serialize to JSON string
|
|
594
|
-
* const json = jsonSerializer.stringify(data)
|
|
595
|
-
* // '{"amount":{"__type":"bigint","value":"1000000000000000000"},"nested":{"value":{"__type":"bigint","value":"42"}}}'
|
|
596
|
-
*
|
|
597
|
-
* // Parse back to original types
|
|
598
|
-
* const parsed = jsonSerializer.parse(json)
|
|
599
|
-
* // { amount: 1000000000000000000n, nested: { value: 42n } }
|
|
600
|
-
* ```
|
|
601
|
-
*/
|
|
602
|
-
const jsonSerializer = {
|
|
603
|
-
stringify(value, space) {
|
|
604
|
-
return JSON.stringify(value, replacer, space);
|
|
605
|
-
},
|
|
606
|
-
parse(text) {
|
|
607
|
-
return JSON.parse(text, reviver);
|
|
608
|
-
}
|
|
609
|
-
};
|
|
610
|
-
|
|
611
|
-
//#endregion
|
|
612
|
-
//#region src/panoptic/v2/sync/snapshotRecovery.ts
|
|
613
|
-
const LOG_SCAN_WINDOW = 10000n;
|
|
614
|
-
const rolesExecutionAbi = parseAbi(["function execTransactionWithRole(address to, uint256 value, bytes data, uint8 operation, bytes32 roleKey, bool shouldRevert)"]);
|
|
615
|
-
/**
|
|
616
|
-
* Recover position snapshot from the last dispatch transaction.
|
|
617
|
-
* This is the primary recovery method - it finds the most recent dispatch()
|
|
618
|
-
* call and extracts the finalPositionIdList from the calldata.
|
|
619
|
-
*
|
|
620
|
-
* @param params - Recovery parameters
|
|
621
|
-
* @returns Snapshot recovery result
|
|
622
|
-
*/
|
|
623
|
-
async function recoverSnapshot(params) {
|
|
624
|
-
const { client, poolAddress, account, toBlock } = params;
|
|
625
|
-
const latestBlock = toBlock ?? await client.getBlockNumber();
|
|
626
|
-
const searchFromBlock = params.fromBlock ?? 0n;
|
|
627
|
-
if (latestBlock < searchFromBlock) return null;
|
|
628
|
-
try {
|
|
629
|
-
const events = await getSnapshotEventsForWindow({
|
|
630
|
-
client,
|
|
631
|
-
poolAddress,
|
|
632
|
-
account,
|
|
633
|
-
fromBlock: searchFromBlock,
|
|
634
|
-
toBlock: latestBlock
|
|
635
|
-
});
|
|
636
|
-
return await recoverSnapshotFromEvents({
|
|
637
|
-
client,
|
|
638
|
-
account,
|
|
639
|
-
events
|
|
640
|
-
});
|
|
641
|
-
} catch (error) {
|
|
642
|
-
if (!isRangeLimitError(error)) throw error;
|
|
643
|
-
}
|
|
644
|
-
let windowToBlock = latestBlock;
|
|
645
|
-
while (true) {
|
|
646
|
-
const windowFromBlock = windowToBlock - searchFromBlock + 1n > LOG_SCAN_WINDOW ? windowToBlock - LOG_SCAN_WINDOW + 1n : searchFromBlock;
|
|
647
|
-
const events = await getSnapshotEventsForWindow({
|
|
648
|
-
client,
|
|
649
|
-
poolAddress,
|
|
650
|
-
account,
|
|
651
|
-
fromBlock: windowFromBlock,
|
|
652
|
-
toBlock: windowToBlock
|
|
653
|
-
});
|
|
654
|
-
const snapshot = await recoverSnapshotFromEvents({
|
|
655
|
-
client,
|
|
656
|
-
account,
|
|
657
|
-
events
|
|
658
|
-
});
|
|
659
|
-
if (snapshot) return snapshot;
|
|
660
|
-
if (windowFromBlock === searchFromBlock) break;
|
|
661
|
-
windowToBlock = windowFromBlock - 1n;
|
|
662
|
-
}
|
|
663
|
-
return null;
|
|
664
|
-
}
|
|
665
|
-
/**
|
|
666
|
-
* Detect provider errors that indicate the requested getLogs block range was
|
|
667
|
-
* too wide (so the caller should retry with smaller windows). Covers the common
|
|
668
|
-
* phrasings used by Alchemy, Infura, and other JSON-RPC providers.
|
|
669
|
-
*/
|
|
670
|
-
function isRangeLimitError(error) {
|
|
671
|
-
const parts = [];
|
|
672
|
-
let current = error;
|
|
673
|
-
let depth = 0;
|
|
674
|
-
while (current && typeof current === "object" && depth < 5) {
|
|
675
|
-
const obj = current;
|
|
676
|
-
if (typeof obj.message === "string") parts.push(obj.message);
|
|
677
|
-
if (typeof obj.details === "string") parts.push(obj.details);
|
|
678
|
-
current = obj.cause;
|
|
679
|
-
depth += 1;
|
|
680
|
-
}
|
|
681
|
-
if (typeof error === "string") parts.push(error);
|
|
682
|
-
const message = parts.join(" ").toLowerCase();
|
|
683
|
-
if (!message) return false;
|
|
684
|
-
return message.includes("block range") || message.includes("range is too large") || message.includes("range too large") || message.includes("query returned more than") || message.includes("too many results") || message.includes("log response size exceeded") || message.includes("exceeds the limit") || message.includes("range") && message.includes("limit");
|
|
685
|
-
}
|
|
686
|
-
async function getSnapshotEventsForWindow(params) {
|
|
687
|
-
const { client, poolAddress, account, fromBlock, toBlock } = params;
|
|
688
|
-
const [mintEvents, burnEvents, forceExerciseEvents, liquidationEvents] = await Promise.all([
|
|
689
|
-
client.getLogs({
|
|
690
|
-
address: poolAddress,
|
|
691
|
-
event: {
|
|
692
|
-
type: "event",
|
|
693
|
-
name: "OptionMinted",
|
|
694
|
-
inputs: [
|
|
695
|
-
{
|
|
696
|
-
type: "address",
|
|
697
|
-
name: "recipient",
|
|
698
|
-
indexed: true
|
|
699
|
-
},
|
|
700
|
-
{
|
|
701
|
-
type: "uint256",
|
|
702
|
-
name: "tokenId",
|
|
703
|
-
indexed: true
|
|
704
|
-
},
|
|
705
|
-
{
|
|
706
|
-
type: "uint256",
|
|
707
|
-
name: "balanceData",
|
|
708
|
-
indexed: false
|
|
709
|
-
}
|
|
710
|
-
]
|
|
711
|
-
},
|
|
712
|
-
args: { recipient: account },
|
|
713
|
-
fromBlock,
|
|
714
|
-
toBlock
|
|
715
|
-
}),
|
|
716
|
-
client.getLogs({
|
|
717
|
-
address: poolAddress,
|
|
718
|
-
event: {
|
|
719
|
-
type: "event",
|
|
720
|
-
name: "OptionBurnt",
|
|
721
|
-
inputs: [
|
|
722
|
-
{
|
|
723
|
-
type: "address",
|
|
724
|
-
name: "recipient",
|
|
725
|
-
indexed: true
|
|
726
|
-
},
|
|
727
|
-
{
|
|
728
|
-
type: "uint128",
|
|
729
|
-
name: "positionSize",
|
|
730
|
-
indexed: false
|
|
731
|
-
},
|
|
732
|
-
{
|
|
733
|
-
type: "uint256",
|
|
734
|
-
name: "tokenId",
|
|
735
|
-
indexed: true
|
|
736
|
-
},
|
|
737
|
-
{
|
|
738
|
-
type: "int256[4]",
|
|
739
|
-
name: "premiaByLeg",
|
|
740
|
-
indexed: false
|
|
741
|
-
}
|
|
742
|
-
]
|
|
743
|
-
},
|
|
744
|
-
args: { recipient: account },
|
|
745
|
-
fromBlock,
|
|
746
|
-
toBlock
|
|
747
|
-
}),
|
|
748
|
-
client.getLogs({
|
|
749
|
-
address: poolAddress,
|
|
750
|
-
event: {
|
|
751
|
-
type: "event",
|
|
752
|
-
name: "ForcedExercised",
|
|
753
|
-
inputs: [
|
|
754
|
-
{
|
|
755
|
-
type: "address",
|
|
756
|
-
name: "exercisor",
|
|
757
|
-
indexed: true
|
|
758
|
-
},
|
|
759
|
-
{
|
|
760
|
-
type: "address",
|
|
761
|
-
name: "user",
|
|
762
|
-
indexed: true
|
|
763
|
-
},
|
|
764
|
-
{
|
|
765
|
-
type: "uint256",
|
|
766
|
-
name: "tokenId",
|
|
767
|
-
indexed: true
|
|
768
|
-
},
|
|
769
|
-
{
|
|
770
|
-
type: "int256",
|
|
771
|
-
name: "exerciseFee",
|
|
772
|
-
indexed: false
|
|
773
|
-
}
|
|
774
|
-
]
|
|
775
|
-
},
|
|
776
|
-
args: { user: account },
|
|
777
|
-
fromBlock,
|
|
778
|
-
toBlock
|
|
779
|
-
}),
|
|
780
|
-
client.getLogs({
|
|
781
|
-
address: poolAddress,
|
|
782
|
-
event: {
|
|
783
|
-
type: "event",
|
|
784
|
-
name: "AccountLiquidated",
|
|
785
|
-
inputs: [
|
|
786
|
-
{
|
|
787
|
-
type: "address",
|
|
788
|
-
name: "liquidator",
|
|
789
|
-
indexed: true
|
|
790
|
-
},
|
|
791
|
-
{
|
|
792
|
-
type: "address",
|
|
793
|
-
name: "liquidatee",
|
|
794
|
-
indexed: true
|
|
795
|
-
},
|
|
796
|
-
{
|
|
797
|
-
type: "int256",
|
|
798
|
-
name: "bonusAmounts",
|
|
799
|
-
indexed: false
|
|
800
|
-
}
|
|
801
|
-
]
|
|
802
|
-
},
|
|
803
|
-
args: { liquidatee: account },
|
|
804
|
-
fromBlock,
|
|
805
|
-
toBlock
|
|
806
|
-
})
|
|
807
|
-
]);
|
|
808
|
-
return [
|
|
809
|
-
...mintEvents,
|
|
810
|
-
...burnEvents,
|
|
811
|
-
...forceExerciseEvents,
|
|
812
|
-
...liquidationEvents
|
|
813
|
-
];
|
|
814
|
-
}
|
|
815
|
-
async function recoverSnapshotFromEvents(params) {
|
|
816
|
-
const { client, account, events } = params;
|
|
817
|
-
const allEvents = events.filter(isSnapshotCandidateEvent).sort((a, b) => {
|
|
818
|
-
const blockDiff = Number(b.blockNumber - a.blockNumber);
|
|
819
|
-
if (blockDiff !== 0) return blockDiff;
|
|
820
|
-
return Number(b.logIndex - a.logIndex);
|
|
821
|
-
});
|
|
822
|
-
const seen = new Set();
|
|
823
|
-
const uniqueEvents = allEvents.filter((e) => {
|
|
824
|
-
if (seen.has(e.transactionHash)) return false;
|
|
825
|
-
seen.add(e.transactionHash);
|
|
826
|
-
return true;
|
|
827
|
-
});
|
|
828
|
-
for (const event of uniqueEvents) try {
|
|
829
|
-
const [tx, block] = await Promise.all([client.getTransaction({ hash: event.transactionHash }), client.getBlock({ blockNumber: event.blockNumber })]);
|
|
830
|
-
const candidates = decodeAllDispatchCalldata(tx.input);
|
|
831
|
-
const decoded = selectDispatchForAccount(candidates, account, tx.from) ?? selectDispatchProvenByAccountEvent(candidates);
|
|
832
|
-
if (!decoded) continue;
|
|
833
|
-
return {
|
|
834
|
-
success: true,
|
|
835
|
-
positionIds: decoded.positionIds,
|
|
836
|
-
blockNumber: event.blockNumber,
|
|
837
|
-
blockHash: block.hash,
|
|
838
|
-
transactionHash: event.transactionHash
|
|
839
|
-
};
|
|
840
|
-
} catch {}
|
|
841
|
-
return null;
|
|
842
|
-
}
|
|
843
|
-
function isSnapshotCandidateEvent(event) {
|
|
844
|
-
return event.transactionHash !== null && event.blockNumber !== null && event.logIndex !== null;
|
|
845
|
-
}
|
|
846
|
-
function decodeSnapshotTransaction(params) {
|
|
847
|
-
const { account, pool, rolesContext } = params;
|
|
848
|
-
let dispatchInput = params.input;
|
|
849
|
-
let dispatchSender = params.from;
|
|
850
|
-
if (rolesContext) {
|
|
851
|
-
if (params.to === null || getAddress(params.to) !== getAddress(rolesContext.modifier) || getAddress(params.from) !== getAddress(rolesContext.member)) return null;
|
|
852
|
-
try {
|
|
853
|
-
const decodedRoleCall = decodeFunctionData({
|
|
854
|
-
abi: rolesExecutionAbi,
|
|
855
|
-
data: params.input
|
|
856
|
-
});
|
|
857
|
-
const [target, value, data, operation, roleKey, shouldRevert] = decodedRoleCall.args;
|
|
858
|
-
if (!pool || getAddress(target) !== getAddress(pool) || value !== 0n || operation !== 0 || roleKey.toLowerCase() !== rolesContext.roleKey.toLowerCase() || !shouldRevert) return null;
|
|
859
|
-
dispatchInput = data;
|
|
860
|
-
if (!account) return null;
|
|
861
|
-
dispatchSender = account;
|
|
862
|
-
} catch {
|
|
863
|
-
return null;
|
|
864
|
-
}
|
|
865
|
-
} else if (pool && (params.to === null || getAddress(params.to) !== getAddress(pool))) return null;
|
|
866
|
-
const candidates = decodeAllDispatchCalldata(dispatchInput);
|
|
867
|
-
if (candidates.length === 0) return null;
|
|
868
|
-
return account ? selectDispatchForAccount(candidates, account, dispatchSender) : candidates[candidates.length - 1];
|
|
869
|
-
}
|
|
870
|
-
/**
|
|
871
|
-
* Recover position snapshot from a specific dispatch transaction hash.
|
|
872
|
-
*
|
|
873
|
-
* This is an O(1) alternative to {@link recoverSnapshot} when you already
|
|
874
|
-
* know the tx hash of the most recent dispatch. It fetches the transaction,
|
|
875
|
-
* decodes the `finalPositionIdList` from the calldata, and returns the result
|
|
876
|
-
* — no event scanning required.
|
|
877
|
-
*
|
|
878
|
-
* @param params - Recovery parameters including the transaction hash
|
|
879
|
-
* @returns Snapshot recovery result, or null if the tx is not a dispatch call
|
|
880
|
-
*
|
|
881
|
-
* @example
|
|
882
|
-
* ```typescript
|
|
883
|
-
* const snapshot = await recoverSnapshotFromTx({
|
|
884
|
-
* client,
|
|
885
|
-
* transactionHash: '0xabc...',
|
|
886
|
-
* })
|
|
887
|
-
* if (snapshot) {
|
|
888
|
-
* console.log('Open positions:', snapshot.positionIds)
|
|
889
|
-
* }
|
|
890
|
-
* ```
|
|
891
|
-
*/
|
|
892
|
-
async function recoverSnapshotFromTx(params) {
|
|
893
|
-
const { client, transactionHash, account, pool, rolesContext } = params;
|
|
894
|
-
const tx = await client.getTransaction({ hash: transactionHash });
|
|
895
|
-
if (tx.blockNumber == null) return null;
|
|
896
|
-
const decoded = decodeSnapshotTransaction({
|
|
897
|
-
input: tx.input,
|
|
898
|
-
from: tx.from,
|
|
899
|
-
to: tx.to,
|
|
900
|
-
account,
|
|
901
|
-
pool,
|
|
902
|
-
rolesContext
|
|
903
|
-
});
|
|
904
|
-
if (!decoded) return null;
|
|
905
|
-
const blockNumber = tx.blockNumber;
|
|
906
|
-
const block = await client.getBlock({ blockNumber });
|
|
907
|
-
return {
|
|
908
|
-
success: true,
|
|
909
|
-
positionIds: decoded.positionIds,
|
|
910
|
-
blockNumber,
|
|
911
|
-
blockHash: block.hash,
|
|
912
|
-
transactionHash
|
|
913
|
-
};
|
|
914
|
-
}
|
|
915
|
-
/**
|
|
916
|
-
* Decode position IDs from dispatch calldata.
|
|
917
|
-
*
|
|
918
|
-
* When the tx embeds multiple dispatch/dispatchFrom calls (e.g. a force-exercise
|
|
919
|
-
* multicall), this returns the last one — prefer {@link decodeAllDispatchCalldata}
|
|
920
|
-
* plus {@link selectDispatchForAccount} when the account context matters.
|
|
921
|
-
*
|
|
922
|
-
* @param input - Transaction input data
|
|
923
|
-
* @returns Decoded dispatch data or null if not a dispatch call
|
|
924
|
-
*/
|
|
925
|
-
function decodeDispatchCalldata(input) {
|
|
926
|
-
const all = decodeAllDispatchCalldata(input);
|
|
927
|
-
return all.length > 0 ? all[all.length - 1] : null;
|
|
928
|
-
}
|
|
929
|
-
/**
|
|
930
|
-
* Decode every dispatch/dispatchFrom call embedded in transaction calldata.
|
|
931
|
-
*
|
|
932
|
-
* A single tx can carry more than one such call — most importantly a force-exercise
|
|
933
|
-
* `multicall` that bundles the exercisor's own `dispatch` together with the victim's
|
|
934
|
-
* `dispatchFrom`. Returning all candidates lets the caller select the one attributable
|
|
935
|
-
* to the relevant account ({@link selectDispatchForAccount}).
|
|
936
|
-
*
|
|
937
|
-
* @param input - Transaction input data
|
|
938
|
-
* @returns All decoded dispatch calls, in calldata order (may be empty)
|
|
939
|
-
*/
|
|
940
|
-
function decodeAllDispatchCalldata(input) {
|
|
941
|
-
const direct = decodeDirectDispatch(input);
|
|
942
|
-
if (direct) return [direct];
|
|
943
|
-
return decodeWrappedDispatch(input);
|
|
944
|
-
}
|
|
945
|
-
/**
|
|
946
|
-
* Select the dispatch call attributable to `account` from a set of candidates.
|
|
947
|
-
*
|
|
948
|
-
* - `dispatchFrom`: matches when `targetAccount === account` (builder/exercisor acting
|
|
949
|
-
* on behalf of the account).
|
|
950
|
-
* - `dispatch` (no `targetAccount`): matches only when the tx sender is the account.
|
|
951
|
-
*
|
|
952
|
-
* Returns the LAST matching candidate (in calldata order), or null when none are
|
|
953
|
-
* attributable to `account`. The last dispatch reflects the final post-transaction
|
|
954
|
-
* state when a single tx contains multiple dispatches for the same account (e.g. a
|
|
955
|
-
* multicall). Matching also prevents accepting a third party's `dispatch` (e.g. the
|
|
956
|
-
* exercisor's own, bundled in a force-exercise multicall) as the account's snapshot.
|
|
957
|
-
*
|
|
958
|
-
* @param candidates - Decoded dispatch calls from a single tx, in calldata order
|
|
959
|
-
* @param account - Account whose position list we are recovering
|
|
960
|
-
* @param txFrom - The transaction sender (`tx.from`)
|
|
961
|
-
*/
|
|
962
|
-
function selectDispatchForAccount(candidates, account, txFrom) {
|
|
963
|
-
const acct = account.toLowerCase();
|
|
964
|
-
let match = null;
|
|
965
|
-
for (const candidate of candidates) if (candidate.targetAccount) {
|
|
966
|
-
if (candidate.targetAccount.toLowerCase() === acct) match = candidate;
|
|
967
|
-
} else if (txFrom.toLowerCase() === acct) match = candidate;
|
|
968
|
-
return match;
|
|
969
|
-
}
|
|
970
|
-
function selectDispatchProvenByAccountEvent(candidates) {
|
|
971
|
-
let match = null;
|
|
972
|
-
for (const candidate of candidates) if (candidate.targetAccount === void 0) match = candidate;
|
|
973
|
-
return match;
|
|
974
|
-
}
|
|
975
|
-
/**
|
|
976
|
-
* Try to decode input as a direct dispatch or dispatchFrom call.
|
|
977
|
-
*/
|
|
978
|
-
function decodeDirectDispatch(input) {
|
|
979
|
-
try {
|
|
980
|
-
const decoded = decodeFunctionData({
|
|
981
|
-
abi: panopticPoolV2Abi,
|
|
982
|
-
data: input
|
|
983
|
-
});
|
|
984
|
-
if (decoded.functionName === "dispatch") {
|
|
985
|
-
const args = decoded.args;
|
|
986
|
-
return { positionIds: [...args[1]] };
|
|
987
|
-
}
|
|
988
|
-
if (decoded.functionName === "dispatchFrom") {
|
|
989
|
-
const args = decoded.args;
|
|
990
|
-
return {
|
|
991
|
-
positionIds: [...args[3]],
|
|
992
|
-
targetAccount: args[1]
|
|
993
|
-
};
|
|
994
|
-
}
|
|
995
|
-
return null;
|
|
996
|
-
} catch {
|
|
997
|
-
return null;
|
|
998
|
-
}
|
|
999
|
-
}
|
|
1000
|
-
/**
|
|
1001
|
-
* 4-byte function selectors for dispatch/dispatchFrom, derived from the generated ABI.
|
|
1002
|
-
* Used for scanning raw calldata inside smart contract wallet wrappers.
|
|
1003
|
-
*/
|
|
1004
|
-
const DISPATCH_SELECTOR = toFunctionSelector(panopticPoolV2Abi.find((e) => e.type === "function" && e.name === "dispatch")).slice(2);
|
|
1005
|
-
const DISPATCH_FROM_SELECTOR = toFunctionSelector(panopticPoolV2Abi.find((e) => e.type === "function" && e.name === "dispatchFrom")).slice(2);
|
|
1006
|
-
/**
|
|
1007
|
-
* Scan raw transaction input for embedded dispatch calldata.
|
|
1008
|
-
*
|
|
1009
|
-
* Smart contract wallets (Safe, Turnkey, ERC-4337) and vault managers
|
|
1010
|
-
* wrap dispatch calls inside executeBatch → manage → dispatch chains.
|
|
1011
|
-
* Instead of decoding each wrapper layer, we scan the raw hex for the
|
|
1012
|
-
* dispatch function selector and attempt to decode from that offset.
|
|
1013
|
-
*
|
|
1014
|
-
* This handles arbitrary nesting depth without knowing wrapper ABIs.
|
|
1015
|
-
*/
|
|
1016
|
-
function decodeWrappedDispatch(input) {
|
|
1017
|
-
const hex = input.slice(2).toLowerCase();
|
|
1018
|
-
const selectors = [DISPATCH_SELECTOR, DISPATCH_FROM_SELECTOR];
|
|
1019
|
-
const results = [];
|
|
1020
|
-
let offset = 0;
|
|
1021
|
-
while (offset < hex.length) {
|
|
1022
|
-
let earliestIdx = -1;
|
|
1023
|
-
for (const selector of selectors) {
|
|
1024
|
-
const idx = hex.indexOf(selector, offset);
|
|
1025
|
-
if (idx !== -1 && (earliestIdx === -1 || idx < earliestIdx)) earliestIdx = idx;
|
|
1026
|
-
}
|
|
1027
|
-
if (earliestIdx === -1) break;
|
|
1028
|
-
const candidate = `0x${hex.slice(earliestIdx)}`;
|
|
1029
|
-
const result = decodeDirectDispatch(candidate);
|
|
1030
|
-
if (result) results.push(result);
|
|
1031
|
-
offset = earliestIdx + 8;
|
|
1032
|
-
}
|
|
1033
|
-
return results;
|
|
1034
|
-
}
|
|
1035
|
-
|
|
1036
|
-
//#endregion
|
|
1037
|
-
//#region src/panoptic/v2/sync/getTrackedPositionIds.ts
|
|
1038
|
-
/**
|
|
1039
|
-
* Verify that a recovered position-id list still matches the account's current
|
|
1040
|
-
* on-chain state. `getFullPositionsData` reverts when the list contains a
|
|
1041
|
-
* tokenId the account no longer holds, so a successful call is proof the list
|
|
1042
|
-
* is live. Returns `false` on revert so the caller can fall back to an
|
|
1043
|
-
* authoritative event scan instead of trusting a stale checkpoint.
|
|
1044
|
-
*/
|
|
1045
|
-
async function isPositionListLive(params) {
|
|
1046
|
-
const { client, poolAddress, account, positionIds, blockNumber } = params;
|
|
1047
|
-
if (positionIds.length === 0) return true;
|
|
1048
|
-
try {
|
|
1049
|
-
await client.readContract({
|
|
1050
|
-
address: poolAddress,
|
|
1051
|
-
abi: panopticPoolV2Abi,
|
|
1052
|
-
functionName: "getFullPositionsData",
|
|
1053
|
-
args: [
|
|
1054
|
-
account,
|
|
1055
|
-
false,
|
|
1056
|
-
positionIds
|
|
1057
|
-
],
|
|
1058
|
-
blockNumber
|
|
1059
|
-
});
|
|
1060
|
-
return true;
|
|
1061
|
-
} catch {
|
|
1062
|
-
return false;
|
|
1063
|
-
}
|
|
1064
|
-
}
|
|
1065
|
-
/**
|
|
1066
|
-
* Get all tracked position IDs for an account from local cache.
|
|
1067
|
-
*
|
|
1068
|
-
* This function reads from the storage adapter without making RPC calls.
|
|
1069
|
-
* The positions returned may include closed positions if the cache is stale.
|
|
1070
|
-
* Use `getPositions()` for authoritative on-chain data.
|
|
1071
|
-
*
|
|
1072
|
-
* @param params - Query parameters
|
|
1073
|
-
* @returns Array of position token IDs
|
|
1074
|
-
*/
|
|
1075
|
-
async function getTrackedPositionIds(params) {
|
|
1076
|
-
const { chainId, poolAddress, account, storage } = params;
|
|
1077
|
-
const key = getPositionsKey(chainId, poolAddress, account);
|
|
1078
|
-
const data = await storage.get(key);
|
|
1079
|
-
if (!data) return [];
|
|
1080
|
-
try {
|
|
1081
|
-
const positionIds = jsonSerializer.parse(data);
|
|
1082
|
-
return positionIds;
|
|
1083
|
-
} catch {
|
|
1084
|
-
return [];
|
|
1085
|
-
}
|
|
1086
|
-
}
|
|
1087
|
-
/**
|
|
1088
|
-
* Check if a specific position ID is tracked.
|
|
1089
|
-
*
|
|
1090
|
-
* @param params - Query parameters
|
|
1091
|
-
* @param tokenId - Token ID to check
|
|
1092
|
-
* @returns Whether the position is tracked
|
|
1093
|
-
*/
|
|
1094
|
-
async function isPositionTracked(params, tokenId) {
|
|
1095
|
-
const positionIds = await getTrackedPositionIds(params);
|
|
1096
|
-
return positionIds.some((id) => id === tokenId);
|
|
1097
|
-
}
|
|
1098
|
-
/**
|
|
1099
|
-
* Clear all tracked positions for an account.
|
|
1100
|
-
*
|
|
1101
|
-
* @param params - Query parameters
|
|
1102
|
-
*/
|
|
1103
|
-
async function clearTrackedPositions(params) {
|
|
1104
|
-
const { chainId, poolAddress, account, storage } = params;
|
|
1105
|
-
const key = getPositionsKey(chainId, poolAddress, account);
|
|
1106
|
-
await storage.delete(key);
|
|
1107
|
-
}
|
|
1108
|
-
/**
|
|
1109
|
-
* Get the authoritative list of open position IDs from the chain.
|
|
1110
|
-
*
|
|
1111
|
-
* Recovers the `finalPositionIdList` from the account's most recent
|
|
1112
|
-
* `dispatch()` transaction calldata. This is the on-chain–validated set of
|
|
1113
|
-
* open positions (verified against `s_positionsHash` by the contract) and
|
|
1114
|
-
* requires only a few RPC calls regardless of account history length.
|
|
1115
|
-
*
|
|
1116
|
-
* This is the recommended way to get position IDs for `existingPositionIds`
|
|
1117
|
-
* (openPosition) and `positionIdList` (closePosition).
|
|
1118
|
-
*
|
|
1119
|
-
* If `storage` is provided, the local cache is updated with the result.
|
|
1120
|
-
*
|
|
1121
|
-
* @param params - Query parameters
|
|
1122
|
-
* @returns Array of currently open position token IDs, or null if no snapshot was found
|
|
1123
|
-
*/
|
|
1124
|
-
async function getOpenPositionIds(params) {
|
|
1125
|
-
const { client, chainId, poolAddress, account, storage, lastDispatchTxHash, fromBlock, toBlock, rolesContext } = params;
|
|
1126
|
-
let snapshot = null;
|
|
1127
|
-
if (lastDispatchTxHash) try {
|
|
1128
|
-
const candidate = await recoverSnapshotFromTx({
|
|
1129
|
-
client,
|
|
1130
|
-
transactionHash: lastDispatchTxHash,
|
|
1131
|
-
account,
|
|
1132
|
-
pool: poolAddress,
|
|
1133
|
-
rolesContext
|
|
1134
|
-
});
|
|
1135
|
-
if (candidate && await isPositionListLive({
|
|
1136
|
-
client,
|
|
1137
|
-
poolAddress,
|
|
1138
|
-
account,
|
|
1139
|
-
positionIds: candidate.positionIds,
|
|
1140
|
-
blockNumber: toBlock
|
|
1141
|
-
})) snapshot = candidate;
|
|
1142
|
-
} catch {
|
|
1143
|
-
snapshot = null;
|
|
1144
|
-
}
|
|
1145
|
-
if (!snapshot) snapshot = await recoverSnapshot({
|
|
1146
|
-
client,
|
|
1147
|
-
poolAddress,
|
|
1148
|
-
account,
|
|
1149
|
-
fromBlock,
|
|
1150
|
-
toBlock
|
|
1151
|
-
});
|
|
1152
|
-
if (!snapshot) return null;
|
|
1153
|
-
if (storage) {
|
|
1154
|
-
const key = getPositionsKey(chainId, poolAddress, account);
|
|
1155
|
-
await storage.set(key, jsonSerializer.stringify(snapshot.positionIds));
|
|
1156
|
-
}
|
|
1157
|
-
return snapshot.positionIds;
|
|
1158
|
-
}
|
|
1159
|
-
|
|
1160
344
|
//#endregion
|
|
1161
345
|
//#region src/panoptic/v2/writes/position.ts
|
|
1162
346
|
/**
|
|
@@ -1694,231 +878,158 @@ async function liquidateAndWait(params) {
|
|
|
1694
878
|
}
|
|
1695
879
|
|
|
1696
880
|
//#endregion
|
|
1697
|
-
//#region src/panoptic/v2/
|
|
1698
|
-
/**
|
|
1699
|
-
*
|
|
1700
|
-
*
|
|
1701
|
-
*
|
|
1702
|
-
*
|
|
1703
|
-
* @param
|
|
1704
|
-
* @
|
|
1705
|
-
|
|
1706
|
-
|
|
1707
|
-
|
|
1708
|
-
|
|
1709
|
-
|
|
1710
|
-
|
|
1711
|
-
|
|
1712
|
-
|
|
1713
|
-
|
|
1714
|
-
|
|
1715
|
-
|
|
1716
|
-
|
|
1717
|
-
|
|
1718
|
-
|
|
1719
|
-
|
|
1720
|
-
|
|
1721
|
-
|
|
1722
|
-
|
|
1723
|
-
|
|
1724
|
-
|
|
1725
|
-
|
|
1726
|
-
|
|
1727
|
-
|
|
1728
|
-
|
|
1729
|
-
|
|
1730
|
-
|
|
1731
|
-
|
|
1732
|
-
|
|
1733
|
-
|
|
1734
|
-
|
|
1735
|
-
|
|
1736
|
-
|
|
1737
|
-
}
|
|
1738
|
-
|
|
1739
|
-
|
|
1740
|
-
|
|
1741
|
-
|
|
1742
|
-
|
|
1743
|
-
|
|
1744
|
-
|
|
1745
|
-
|
|
1746
|
-
|
|
1747
|
-
|
|
1748
|
-
|
|
1749
|
-
|
|
1750
|
-
|
|
1751
|
-
|
|
1752
|
-
|
|
1753
|
-
|
|
1754
|
-
|
|
1755
|
-
|
|
1756
|
-
|
|
1757
|
-
|
|
1758
|
-
|
|
1759
|
-
|
|
1760
|
-
|
|
1761
|
-
|
|
1762
|
-
|
|
1763
|
-
|
|
1764
|
-
* @throws SafeModeError if minting is not allowed
|
|
1765
|
-
*
|
|
1766
|
-
* @example
|
|
1767
|
-
* ```typescript
|
|
1768
|
-
* const safeMode = await getSafeMode({ client, poolAddress })
|
|
1769
|
-
* assertCanMint(safeMode)
|
|
1770
|
-
* await openPosition({ ... })
|
|
1771
|
-
* ```
|
|
1772
|
-
*/
|
|
1773
|
-
function assertCanMint(safeMode) {
|
|
1774
|
-
if (!safeMode.canMint) throw new SafeModeError(safeMode.mode, safeMode.reason ?? "Minting not allowed");
|
|
1775
|
-
}
|
|
1776
|
-
/**
|
|
1777
|
-
* Assert that burning is allowed.
|
|
1778
|
-
*
|
|
1779
|
-
* @param safeMode - SafeModeState from getSafeMode()
|
|
1780
|
-
* @throws SafeModeError if burning is not allowed
|
|
1781
|
-
*/
|
|
1782
|
-
function assertCanBurn(safeMode) {
|
|
1783
|
-
if (!safeMode.canBurn) throw new SafeModeError(safeMode.mode, safeMode.reason ?? "Burning not allowed");
|
|
1784
|
-
}
|
|
1785
|
-
/**
|
|
1786
|
-
* Assert that liquidations are allowed.
|
|
1787
|
-
*
|
|
1788
|
-
* @param safeMode - SafeModeState from getSafeMode()
|
|
1789
|
-
* @throws SafeModeError if liquidations are not allowed
|
|
1790
|
-
*/
|
|
1791
|
-
function assertCanLiquidate(safeMode) {
|
|
1792
|
-
if (!safeMode.canLiquidate) throw new SafeModeError(safeMode.mode, safeMode.reason ?? "Liquidations not allowed");
|
|
1793
|
-
}
|
|
1794
|
-
/**
|
|
1795
|
-
* Assert that force exercise is allowed.
|
|
1796
|
-
*
|
|
1797
|
-
* @param safeMode - SafeModeState from getSafeMode()
|
|
1798
|
-
* @throws SafeModeError if force exercise is not allowed
|
|
1799
|
-
*/
|
|
1800
|
-
function assertCanForceExercise(safeMode) {
|
|
1801
|
-
if (!safeMode.canForceExercise) throw new SafeModeError(safeMode.mode, safeMode.reason ?? "Force exercise not allowed");
|
|
1802
|
-
}
|
|
1803
|
-
/**
|
|
1804
|
-
* Common retryable RPC error codes.
|
|
1805
|
-
*/
|
|
1806
|
-
const RETRYABLE_RPC_CODES = new Set([
|
|
1807
|
-
-32e3,
|
|
1808
|
-
-32001,
|
|
1809
|
-
-32002,
|
|
1810
|
-
-32003,
|
|
1811
|
-
-32005,
|
|
1812
|
-
-32097,
|
|
1813
|
-
-32098,
|
|
1814
|
-
-32099
|
|
1815
|
-
]);
|
|
1816
|
-
/**
|
|
1817
|
-
* Common retryable error message patterns.
|
|
1818
|
-
*/
|
|
1819
|
-
const RETRYABLE_PATTERNS = [
|
|
1820
|
-
/timeout/i,
|
|
1821
|
-
/timed out/i,
|
|
1822
|
-
/rate limit/i,
|
|
1823
|
-
/too many requests/i,
|
|
1824
|
-
/429/i,
|
|
1825
|
-
/503/i,
|
|
1826
|
-
/504/i,
|
|
1827
|
-
/502/i,
|
|
1828
|
-
/connection refused/i,
|
|
1829
|
-
/connection reset/i,
|
|
1830
|
-
/network error/i,
|
|
1831
|
-
/econnreset/i,
|
|
1832
|
-
/econnrefused/i,
|
|
1833
|
-
/etimedout/i,
|
|
1834
|
-
/socket hang up/i,
|
|
1835
|
-
/temporarily unavailable/i,
|
|
1836
|
-
/service unavailable/i,
|
|
1837
|
-
/server error/i,
|
|
1838
|
-
/internal error/i,
|
|
1839
|
-
/nonce too low/i,
|
|
1840
|
-
/replacement transaction underpriced/i,
|
|
1841
|
-
/already known/i
|
|
1842
|
-
];
|
|
1843
|
-
/**
|
|
1844
|
-
* Check if an error is a retryable RPC error.
|
|
1845
|
-
*
|
|
1846
|
-
* Returns true for transient errors that may succeed on retry:
|
|
1847
|
-
* - Timeouts
|
|
1848
|
-
* - Rate limits
|
|
1849
|
-
* - Connection errors
|
|
1850
|
-
* - Server errors (5xx)
|
|
1851
|
-
* - Nonce errors (recoverable with correct nonce)
|
|
1852
|
-
*
|
|
1853
|
-
* @param error - The error to check
|
|
1854
|
-
* @returns True if the error is likely retryable
|
|
1855
|
-
*
|
|
1856
|
-
* @example
|
|
1857
|
-
* ```typescript
|
|
1858
|
-
* try {
|
|
1859
|
-
* await openPosition({ ... })
|
|
1860
|
-
* } catch (error) {
|
|
1861
|
-
* if (isRetryableRpcError(error)) {
|
|
1862
|
-
* // Wait and retry
|
|
1863
|
-
* await sleep(1000)
|
|
1864
|
-
* await openPosition({ ... })
|
|
1865
|
-
* } else {
|
|
1866
|
-
* throw error // Non-retryable, propagate
|
|
1867
|
-
* }
|
|
1868
|
-
* }
|
|
1869
|
-
* ```
|
|
1870
|
-
*/
|
|
1871
|
-
function isRetryableRpcError(error) {
|
|
1872
|
-
if (error === null || error === void 0) return false;
|
|
1873
|
-
if (typeof error === "object") {
|
|
1874
|
-
const errorObj = error;
|
|
1875
|
-
if (typeof errorObj.code === "number" && RETRYABLE_RPC_CODES.has(errorObj.code)) return true;
|
|
1876
|
-
if (errorObj.cause && isRetryableRpcError(errorObj.cause)) return true;
|
|
1877
|
-
if (errorObj.details && typeof errorObj.details === "object") {
|
|
1878
|
-
const details = errorObj.details;
|
|
1879
|
-
if (typeof details.code === "number" && RETRYABLE_RPC_CODES.has(details.code)) return true;
|
|
881
|
+
//#region src/panoptic/v2/sync/eventReconstruction.ts
|
|
882
|
+
/**
|
|
883
|
+
* Reconstruct position history from events.
|
|
884
|
+
* This is the fallback method when snapshot recovery fails.
|
|
885
|
+
* It scans all OptionMinted and OptionBurnt events to build the position set.
|
|
886
|
+
*
|
|
887
|
+
* @param params - Reconstruction parameters
|
|
888
|
+
* @returns Reconstruction result with open and closed positions
|
|
889
|
+
*/
|
|
890
|
+
async function reconstructFromEvents(params) {
|
|
891
|
+
const { client, poolAddress, account, fromBlock, toBlock, batchSize = 10000n, onProgress } = params;
|
|
892
|
+
const mintEvents = [];
|
|
893
|
+
const burnEvents = [];
|
|
894
|
+
const totalBlocks = toBlock - fromBlock + 1n;
|
|
895
|
+
const safeBatchSize = batchSize > 0n ? batchSize : 10000n;
|
|
896
|
+
const scanRange = async (rangeFromBlock, rangeToBlock) => {
|
|
897
|
+
const [mints, burns] = await Promise.all([client.getLogs({
|
|
898
|
+
address: poolAddress,
|
|
899
|
+
event: OPTION_MINTED_EVENT,
|
|
900
|
+
args: { recipient: account },
|
|
901
|
+
fromBlock: rangeFromBlock,
|
|
902
|
+
toBlock: rangeToBlock
|
|
903
|
+
}), client.getLogs({
|
|
904
|
+
address: poolAddress,
|
|
905
|
+
event: OPTION_BURNT_EVENT,
|
|
906
|
+
args: { recipient: account },
|
|
907
|
+
fromBlock: rangeFromBlock,
|
|
908
|
+
toBlock: rangeToBlock
|
|
909
|
+
})]);
|
|
910
|
+
for (const mint$1 of mints) {
|
|
911
|
+
const balanceData = mint$1.args.balanceData;
|
|
912
|
+
const positionSize = balanceData & (1n << 128n) - 1n;
|
|
913
|
+
mintEvents.push({
|
|
914
|
+
tokenId: mint$1.args.tokenId,
|
|
915
|
+
positionSize,
|
|
916
|
+
blockNumber: mint$1.blockNumber,
|
|
917
|
+
blockHash: mint$1.blockHash,
|
|
918
|
+
transactionHash: mint$1.transactionHash,
|
|
919
|
+
logIndex: mint$1.logIndex
|
|
920
|
+
});
|
|
921
|
+
}
|
|
922
|
+
for (const burn of burns) burnEvents.push({
|
|
923
|
+
tokenId: burn.args.tokenId,
|
|
924
|
+
positionSize: burn.args.positionSize,
|
|
925
|
+
blockNumber: burn.blockNumber,
|
|
926
|
+
blockHash: burn.blockHash,
|
|
927
|
+
transactionHash: burn.transactionHash,
|
|
928
|
+
logIndex: burn.logIndex
|
|
929
|
+
});
|
|
930
|
+
const blocksProcessed = rangeToBlock - fromBlock + 1n;
|
|
931
|
+
const progress = totalBlocks > 0n ? blocksProcessed * 100n / totalBlocks : 100n;
|
|
932
|
+
onProgress?.({
|
|
933
|
+
currentBlock: rangeToBlock,
|
|
934
|
+
targetBlock: toBlock,
|
|
935
|
+
positionsFound: BigInt(mintEvents.length),
|
|
936
|
+
progress: progress > 100n ? 100n : progress
|
|
937
|
+
});
|
|
938
|
+
};
|
|
939
|
+
try {
|
|
940
|
+
await scanRange(fromBlock, toBlock);
|
|
941
|
+
} catch (error) {
|
|
942
|
+
if (!isRangeLimitError(error)) throw error;
|
|
943
|
+
let currentBlock = fromBlock;
|
|
944
|
+
while (currentBlock <= toBlock) {
|
|
945
|
+
const endBlock = currentBlock + safeBatchSize - 1n > toBlock ? toBlock : currentBlock + safeBatchSize - 1n;
|
|
946
|
+
await scanRange(currentBlock, endBlock);
|
|
947
|
+
currentBlock = endBlock + 1n;
|
|
1880
948
|
}
|
|
1881
949
|
}
|
|
1882
|
-
const
|
|
1883
|
-
|
|
1884
|
-
|
|
950
|
+
const positionMap = new Map();
|
|
951
|
+
const allEvents = [...mintEvents.map((e) => ({
|
|
952
|
+
...e,
|
|
953
|
+
type: "mint"
|
|
954
|
+
})), ...burnEvents.map((e) => ({
|
|
955
|
+
...e,
|
|
956
|
+
type: "burn"
|
|
957
|
+
}))].sort((a, b) => {
|
|
958
|
+
const blockDiff = Number(a.blockNumber - b.blockNumber);
|
|
959
|
+
if (blockDiff !== 0) return blockDiff;
|
|
960
|
+
return a.logIndex - b.logIndex;
|
|
961
|
+
});
|
|
962
|
+
for (const event of allEvents) {
|
|
963
|
+
const current = positionMap.get(event.tokenId) ?? 0n;
|
|
964
|
+
if (event.type === "mint") positionMap.set(event.tokenId, current + event.positionSize);
|
|
965
|
+
else positionMap.set(event.tokenId, current - event.positionSize);
|
|
1885
966
|
}
|
|
1886
|
-
|
|
967
|
+
const openPositions = [];
|
|
968
|
+
const closedPositions = [];
|
|
969
|
+
for (const [tokenId, size] of positionMap) if (size > 0n) openPositions.push(tokenId);
|
|
970
|
+
else closedPositions.push(tokenId);
|
|
971
|
+
const lastBlock = await client.getBlock({ blockNumber: toBlock });
|
|
972
|
+
return {
|
|
973
|
+
openPositions,
|
|
974
|
+
closedPositions,
|
|
975
|
+
blocksScanned: toBlock - fromBlock + 1n,
|
|
976
|
+
lastBlock: toBlock,
|
|
977
|
+
lastBlockHash: lastBlock.hash
|
|
978
|
+
};
|
|
1887
979
|
}
|
|
1888
|
-
|
|
1889
|
-
|
|
1890
|
-
|
|
1891
|
-
|
|
1892
|
-
|
|
1893
|
-
|
|
1894
|
-
|
|
1895
|
-
|
|
1896
|
-
|
|
1897
|
-
|
|
980
|
+
const OPTION_MINTED_EVENT = getAbiItem({
|
|
981
|
+
abi: panopticPoolV2Abi,
|
|
982
|
+
name: "OptionMinted"
|
|
983
|
+
});
|
|
984
|
+
const OPTION_BURNT_EVENT = getAbiItem({
|
|
985
|
+
abi: panopticPoolV2Abi,
|
|
986
|
+
name: "OptionBurnt"
|
|
987
|
+
});
|
|
988
|
+
function isRangeLimitError(error) {
|
|
989
|
+
const messages = [];
|
|
990
|
+
let current = error;
|
|
991
|
+
for (let depth = 0; current && typeof current === "object" && depth < 5; depth += 1) {
|
|
992
|
+
if ("message" in current && typeof current.message === "string") messages.push(current.message);
|
|
993
|
+
if ("details" in current && typeof current.details === "string") messages.push(current.details);
|
|
994
|
+
current = "cause" in current ? current.cause : void 0;
|
|
1898
995
|
}
|
|
1899
|
-
|
|
1900
|
-
|
|
1901
|
-
|
|
1902
|
-
* Check if an error is a nonce-related error that can be recovered.
|
|
1903
|
-
*
|
|
1904
|
-
* @param error - The error to check
|
|
1905
|
-
* @returns True if this is a nonce error
|
|
1906
|
-
*/
|
|
1907
|
-
function isNonceError(error) {
|
|
1908
|
-
const message = getErrorMessage(error);
|
|
1909
|
-
if (!message) return false;
|
|
1910
|
-
return /nonce too low/i.test(message) || /nonce too high/i.test(message) || /already known/i.test(message);
|
|
996
|
+
if (typeof error === "string") messages.push(error);
|
|
997
|
+
const message = messages.join(" ").toLowerCase();
|
|
998
|
+
return message.includes("block range") || message.includes("range is too large") || message.includes("range too large") || message.includes("query returned more than") || message.includes("too many results") || message.includes("log response size exceeded") || message.includes("exceeds the limit") || message.includes("range") && message.includes("limit");
|
|
1911
999
|
}
|
|
1912
1000
|
/**
|
|
1913
|
-
*
|
|
1001
|
+
* Get the deployment block for a pool.
|
|
1002
|
+
* This searches for the first PoolInitialized event.
|
|
1914
1003
|
*
|
|
1915
|
-
* @param
|
|
1916
|
-
* @
|
|
1917
|
-
|
|
1918
|
-
|
|
1919
|
-
|
|
1920
|
-
|
|
1921
|
-
|
|
1004
|
+
* @param client - viem public client
|
|
1005
|
+
* @param poolAddress - Pool address
|
|
1006
|
+
* @returns Deployment block number or null if not found
|
|
1007
|
+
*/
|
|
1008
|
+
async function getPoolDeploymentBlock(client, poolAddress) {
|
|
1009
|
+
const currentBlock = await client.getBlockNumber();
|
|
1010
|
+
let low = 0n;
|
|
1011
|
+
let high = currentBlock;
|
|
1012
|
+
let foundBlock = null;
|
|
1013
|
+
const scanRange = 10000n;
|
|
1014
|
+
while (low <= high) {
|
|
1015
|
+
const mid = (low + high) / 2n;
|
|
1016
|
+
const rangeEnd = mid + scanRange > high ? high : mid + scanRange;
|
|
1017
|
+
try {
|
|
1018
|
+
const logs = await client.getLogs({
|
|
1019
|
+
address: poolAddress,
|
|
1020
|
+
fromBlock: mid,
|
|
1021
|
+
toBlock: rangeEnd
|
|
1022
|
+
});
|
|
1023
|
+
if (logs.length > 0) {
|
|
1024
|
+
const earliest = logs[0].blockNumber;
|
|
1025
|
+
if (foundBlock === null || earliest < foundBlock) foundBlock = earliest;
|
|
1026
|
+
high = earliest - 1n;
|
|
1027
|
+
} else low = rangeEnd + 1n;
|
|
1028
|
+
} catch {
|
|
1029
|
+
high = mid + (rangeEnd - mid) / 2n;
|
|
1030
|
+
}
|
|
1031
|
+
}
|
|
1032
|
+
return foundBlock;
|
|
1922
1033
|
}
|
|
1923
1034
|
|
|
1924
1035
|
//#endregion
|
|
@@ -2087,47 +1198,45 @@ async function syncPositions(params) {
|
|
|
2087
1198
|
fromBlock: checkpoint?.lastBlock ?? params.fromBlock
|
|
2088
1199
|
});
|
|
2089
1200
|
let positionIds;
|
|
2090
|
-
if (snapshotResult === null
|
|
2091
|
-
|
|
2092
|
-
|
|
2093
|
-
const
|
|
1201
|
+
if (snapshotResult === null) {
|
|
1202
|
+
const fromBlock = params.fromBlock ?? await getPoolDeploymentBlock(client, poolAddress);
|
|
1203
|
+
if (fromBlock === null) throw new PositionSnapshotNotFoundError(new Error("Pool deployment block not found"));
|
|
1204
|
+
const reconstruction = await reconstructFromEvents({
|
|
2094
1205
|
client,
|
|
2095
1206
|
poolAddress,
|
|
2096
1207
|
account,
|
|
2097
|
-
fromBlock
|
|
2098
|
-
toBlock
|
|
1208
|
+
fromBlock,
|
|
1209
|
+
toBlock,
|
|
1210
|
+
batchSize: params.maxLogsPerQuery,
|
|
1211
|
+
onProgress: (progress) => {
|
|
1212
|
+
checkTimeout();
|
|
1213
|
+
onUpdate?.({
|
|
1214
|
+
type: "progress",
|
|
1215
|
+
blockNumber: progress.currentBlock,
|
|
1216
|
+
progress: {
|
|
1217
|
+
current: progress.currentBlock,
|
|
1218
|
+
total: progress.targetBlock
|
|
1219
|
+
}
|
|
1220
|
+
});
|
|
1221
|
+
}
|
|
2099
1222
|
});
|
|
2100
|
-
|
|
2101
|
-
|
|
2102
|
-
|
|
2103
|
-
|
|
2104
|
-
|
|
2105
|
-
|
|
2106
|
-
|
|
2107
|
-
|
|
2108
|
-
|
|
2109
|
-
|
|
2110
|
-
|
|
2111
|
-
|
|
2112
|
-
|
|
2113
|
-
|
|
2114
|
-
|
|
2115
|
-
await storage.set(positionsKey$1, jsonSerializer.stringify([]));
|
|
2116
|
-
return {
|
|
2117
|
-
lastSyncedBlock: toBlock,
|
|
2118
|
-
lastSyncedBlockHash: finalBlock$1.hash,
|
|
2119
|
-
positionCount: 0n,
|
|
2120
|
-
positionIds: [],
|
|
2121
|
-
incremental: false,
|
|
2122
|
-
durationMs: BigInt(Date.now() - startTime)
|
|
2123
|
-
};
|
|
2124
|
-
}
|
|
1223
|
+
positionIds = reconstruction.openPositions;
|
|
1224
|
+
} else positionIds = snapshotResult;
|
|
1225
|
+
const finalBlock = await client.getBlock({ blockNumber: toBlock });
|
|
1226
|
+
if (positionIds.length === 0) {
|
|
1227
|
+
await persistPoolAndCheckpoint(params, toBlock, finalBlock.hash, []);
|
|
1228
|
+
const positionsKey$1 = getPositionsKey(chainId, poolAddress, account);
|
|
1229
|
+
await storage.set(positionsKey$1, jsonSerializer.stringify([]));
|
|
1230
|
+
return {
|
|
1231
|
+
lastSyncedBlock: toBlock,
|
|
1232
|
+
lastSyncedBlockHash: finalBlock.hash,
|
|
1233
|
+
positionCount: 0n,
|
|
1234
|
+
positionIds: [],
|
|
1235
|
+
incremental: !!checkpoint,
|
|
1236
|
+
durationMs: BigInt(Date.now() - startTime)
|
|
1237
|
+
};
|
|
2125
1238
|
}
|
|
2126
1239
|
checkTimeout();
|
|
2127
|
-
const finalBlock = await client.getBlock({ blockNumber: toBlock });
|
|
2128
|
-
const poolMetaKey = getPoolMetaKey(chainId, poolAddress);
|
|
2129
|
-
const existingPoolMeta = await storage.get(poolMetaKey);
|
|
2130
|
-
if (!existingPoolMeta) await fetchAndStorePoolMeta(client, poolAddress, poolMetaKey, storage);
|
|
2131
1240
|
if (positionIds.length > 0) {
|
|
2132
1241
|
const { positions } = await getPositions({
|
|
2133
1242
|
client,
|
|
@@ -2152,15 +1261,7 @@ async function syncPositions(params) {
|
|
|
2152
1261
|
await storage.set(positionMetaKey, jsonSerializer.stringify(storedData));
|
|
2153
1262
|
}
|
|
2154
1263
|
}
|
|
2155
|
-
await
|
|
2156
|
-
storage,
|
|
2157
|
-
chainId,
|
|
2158
|
-
poolAddress,
|
|
2159
|
-
account,
|
|
2160
|
-
lastBlock: toBlock,
|
|
2161
|
-
lastBlockHash: finalBlock.hash,
|
|
2162
|
-
positionIds
|
|
2163
|
-
});
|
|
1264
|
+
await persistPoolAndCheckpoint(params, toBlock, finalBlock.hash, positionIds);
|
|
2164
1265
|
const positionsKey = getPositionsKey(chainId, poolAddress, account);
|
|
2165
1266
|
await storage.set(positionsKey, jsonSerializer.stringify(positionIds));
|
|
2166
1267
|
return {
|
|
@@ -2172,143 +1273,20 @@ async function syncPositions(params) {
|
|
|
2172
1273
|
durationMs: BigInt(Date.now() - startTime)
|
|
2173
1274
|
};
|
|
2174
1275
|
}
|
|
2175
|
-
|
|
2176
|
-
|
|
2177
|
-
|
|
2178
|
-
|
|
2179
|
-
|
|
2180
|
-
|
|
2181
|
-
|
|
2182
|
-
|
|
2183
|
-
|
|
2184
|
-
|
|
2185
|
-
|
|
2186
|
-
|
|
2187
|
-
|
|
2188
|
-
|
|
2189
|
-
async function accountHasPositionEvents(params) {
|
|
2190
|
-
const { client, poolAddress, account, fromBlock = 0n, toBlock } = params;
|
|
2191
|
-
const [mintEvents, burnEvents, forceExerciseEvents, liquidationEvents] = await Promise.all([
|
|
2192
|
-
withRetry(() => client.getLogs({
|
|
2193
|
-
address: poolAddress,
|
|
2194
|
-
event: {
|
|
2195
|
-
type: "event",
|
|
2196
|
-
name: "OptionMinted",
|
|
2197
|
-
inputs: [
|
|
2198
|
-
{
|
|
2199
|
-
type: "address",
|
|
2200
|
-
name: "recipient",
|
|
2201
|
-
indexed: true
|
|
2202
|
-
},
|
|
2203
|
-
{
|
|
2204
|
-
type: "uint256",
|
|
2205
|
-
name: "tokenId",
|
|
2206
|
-
indexed: true
|
|
2207
|
-
},
|
|
2208
|
-
{
|
|
2209
|
-
type: "uint256",
|
|
2210
|
-
name: "balanceData",
|
|
2211
|
-
indexed: false
|
|
2212
|
-
}
|
|
2213
|
-
]
|
|
2214
|
-
},
|
|
2215
|
-
args: { recipient: account },
|
|
2216
|
-
fromBlock,
|
|
2217
|
-
toBlock
|
|
2218
|
-
})),
|
|
2219
|
-
withRetry(() => client.getLogs({
|
|
2220
|
-
address: poolAddress,
|
|
2221
|
-
event: {
|
|
2222
|
-
type: "event",
|
|
2223
|
-
name: "OptionBurnt",
|
|
2224
|
-
inputs: [
|
|
2225
|
-
{
|
|
2226
|
-
type: "address",
|
|
2227
|
-
name: "recipient",
|
|
2228
|
-
indexed: true
|
|
2229
|
-
},
|
|
2230
|
-
{
|
|
2231
|
-
type: "uint256",
|
|
2232
|
-
name: "tokenId",
|
|
2233
|
-
indexed: true
|
|
2234
|
-
},
|
|
2235
|
-
{
|
|
2236
|
-
type: "uint256",
|
|
2237
|
-
name: "positionSize",
|
|
2238
|
-
indexed: false
|
|
2239
|
-
},
|
|
2240
|
-
{
|
|
2241
|
-
type: "int256[4]",
|
|
2242
|
-
name: "premiaByLeg",
|
|
2243
|
-
indexed: false
|
|
2244
|
-
}
|
|
2245
|
-
]
|
|
2246
|
-
},
|
|
2247
|
-
args: { recipient: account },
|
|
2248
|
-
fromBlock,
|
|
2249
|
-
toBlock
|
|
2250
|
-
})),
|
|
2251
|
-
withRetry(() => client.getLogs({
|
|
2252
|
-
address: poolAddress,
|
|
2253
|
-
event: {
|
|
2254
|
-
type: "event",
|
|
2255
|
-
name: "ForcedExercised",
|
|
2256
|
-
inputs: [
|
|
2257
|
-
{
|
|
2258
|
-
type: "address",
|
|
2259
|
-
name: "exercisor",
|
|
2260
|
-
indexed: true
|
|
2261
|
-
},
|
|
2262
|
-
{
|
|
2263
|
-
type: "address",
|
|
2264
|
-
name: "user",
|
|
2265
|
-
indexed: true
|
|
2266
|
-
},
|
|
2267
|
-
{
|
|
2268
|
-
type: "uint256",
|
|
2269
|
-
name: "tokenId",
|
|
2270
|
-
indexed: true
|
|
2271
|
-
},
|
|
2272
|
-
{
|
|
2273
|
-
type: "int256",
|
|
2274
|
-
name: "exerciseFee",
|
|
2275
|
-
indexed: false
|
|
2276
|
-
}
|
|
2277
|
-
]
|
|
2278
|
-
},
|
|
2279
|
-
args: { user: account },
|
|
2280
|
-
fromBlock,
|
|
2281
|
-
toBlock
|
|
2282
|
-
})),
|
|
2283
|
-
withRetry(() => client.getLogs({
|
|
2284
|
-
address: poolAddress,
|
|
2285
|
-
event: {
|
|
2286
|
-
type: "event",
|
|
2287
|
-
name: "AccountLiquidated",
|
|
2288
|
-
inputs: [
|
|
2289
|
-
{
|
|
2290
|
-
type: "address",
|
|
2291
|
-
name: "liquidator",
|
|
2292
|
-
indexed: true
|
|
2293
|
-
},
|
|
2294
|
-
{
|
|
2295
|
-
type: "address",
|
|
2296
|
-
name: "liquidatee",
|
|
2297
|
-
indexed: true
|
|
2298
|
-
},
|
|
2299
|
-
{
|
|
2300
|
-
type: "int256",
|
|
2301
|
-
name: "bonusAmounts",
|
|
2302
|
-
indexed: false
|
|
2303
|
-
}
|
|
2304
|
-
]
|
|
2305
|
-
},
|
|
2306
|
-
args: { liquidatee: account },
|
|
2307
|
-
fromBlock,
|
|
2308
|
-
toBlock
|
|
2309
|
-
}))
|
|
2310
|
-
]);
|
|
2311
|
-
return mintEvents.length > 0 || burnEvents.length > 0 || forceExerciseEvents.length > 0 || liquidationEvents.length > 0;
|
|
1276
|
+
async function persistPoolAndCheckpoint(params, lastBlock, lastBlockHash, positionIds) {
|
|
1277
|
+
const { account, chainId, client, poolAddress, storage } = params;
|
|
1278
|
+
const poolMetaKey = getPoolMetaKey(chainId, poolAddress);
|
|
1279
|
+
const existingPoolMeta = await storage.get(poolMetaKey);
|
|
1280
|
+
if (!existingPoolMeta) await fetchAndStorePoolMeta(client, poolAddress, poolMetaKey, storage);
|
|
1281
|
+
await saveCheckpoint({
|
|
1282
|
+
storage,
|
|
1283
|
+
chainId,
|
|
1284
|
+
poolAddress,
|
|
1285
|
+
account,
|
|
1286
|
+
lastBlock,
|
|
1287
|
+
lastBlockHash,
|
|
1288
|
+
positionIds
|
|
1289
|
+
});
|
|
2312
1290
|
}
|
|
2313
1291
|
/**
|
|
2314
1292
|
* Fetch full pool metadata and store it.
|
|
@@ -2335,27 +1313,6 @@ async function fetchAndStorePoolMeta(client, poolAddress, poolMetaKey, storage)
|
|
|
2335
1313
|
};
|
|
2336
1314
|
await storage.set(poolMetaKey, jsonSerializer.stringify(poolMeta));
|
|
2337
1315
|
}
|
|
2338
|
-
/**
|
|
2339
|
-
* Retry helper with exponential backoff for transient RPC errors.
|
|
2340
|
-
*
|
|
2341
|
-
* @param fn - Async function to retry
|
|
2342
|
-
* @param maxRetries - Maximum number of retries (default: 3)
|
|
2343
|
-
* @returns The result of the function
|
|
2344
|
-
*/
|
|
2345
|
-
async function withRetry(fn, maxRetries = 3) {
|
|
2346
|
-
let lastError;
|
|
2347
|
-
for (let attempt = 0; attempt <= maxRetries; attempt++) try {
|
|
2348
|
-
return await fn();
|
|
2349
|
-
} catch (error) {
|
|
2350
|
-
lastError = error;
|
|
2351
|
-
if (attempt < maxRetries && isRetryableRpcError(error)) {
|
|
2352
|
-
await new Promise((resolve) => setTimeout(resolve, 1e3 * 2 ** attempt));
|
|
2353
|
-
continue;
|
|
2354
|
-
}
|
|
2355
|
-
throw error;
|
|
2356
|
-
}
|
|
2357
|
-
throw lastError;
|
|
2358
|
-
}
|
|
2359
1316
|
|
|
2360
1317
|
//#endregion
|
|
2361
1318
|
//#region src/panoptic/v2/writes/forceExercise.ts
|
|
@@ -2515,10 +1472,10 @@ async function pokeOracle(params) {
|
|
|
2515
1472
|
functionName: "getOracleTicks"
|
|
2516
1473
|
}), client.getBlock()]);
|
|
2517
1474
|
const oraclePack = oracleData[4];
|
|
2518
|
-
const epoch = oraclePack
|
|
2519
|
-
const currentEpoch = block.timestamp
|
|
2520
|
-
if (currentEpoch
|
|
2521
|
-
const lastUpdate = epoch
|
|
1475
|
+
const { epoch } = decodeOracleTiming(oraclePack, block.timestamp);
|
|
1476
|
+
const currentEpoch = oracleEpochAt(block.timestamp);
|
|
1477
|
+
if (currentEpoch === epoch) {
|
|
1478
|
+
const lastUpdate = epoch << 6n;
|
|
2522
1479
|
throw new OracleRateLimitedError(lastUpdate, block.timestamp);
|
|
2523
1480
|
}
|
|
2524
1481
|
}
|
|
@@ -3139,6 +2096,44 @@ function buildUniqueCredit(poolId, asset, tokenType, currentTick, tickSpacing, e
|
|
|
3139
2096
|
|
|
3140
2097
|
//#endregion
|
|
3141
2098
|
//#region src/panoptic/v2/writes/swap.ts
|
|
2099
|
+
/** Build an atomic credit mint/burn swap without fetching or sending anything. */
|
|
2100
|
+
function buildCreditSwapCall(params) {
|
|
2101
|
+
const amount = params.kind === "exactIn" ? params.amountIn : params.amountOut;
|
|
2102
|
+
if (amount <= 0n) throw new Error("credit swap amount must be positive");
|
|
2103
|
+
if (params.tokenIndex !== 0n && params.tokenIndex !== 1n) throw new Error("credit swap tokenIndex must be 0 or 1");
|
|
2104
|
+
const { low, high } = tickLimits(params.currentTick, params.slippageBps);
|
|
2105
|
+
const { tokenId: creditTokenId, adjustedSize } = buildUniqueCredit(params.poolId, params.tokenIndex, params.tokenIndex, params.currentTick, params.tickSpacing, params.existingPositionIds, amount);
|
|
2106
|
+
const ascending = [
|
|
2107
|
+
Number(low),
|
|
2108
|
+
Number(high),
|
|
2109
|
+
0
|
|
2110
|
+
];
|
|
2111
|
+
const descending = [
|
|
2112
|
+
Number(high),
|
|
2113
|
+
Number(low),
|
|
2114
|
+
0
|
|
2115
|
+
];
|
|
2116
|
+
const limits = params.kind === "exactIn" ? [ascending, descending] : [descending, ascending];
|
|
2117
|
+
const args = [
|
|
2118
|
+
[creditTokenId, creditTokenId],
|
|
2119
|
+
[...params.existingPositionIds],
|
|
2120
|
+
[adjustedSize, 0n],
|
|
2121
|
+
limits,
|
|
2122
|
+
false,
|
|
2123
|
+
params.builderCode ?? 0n
|
|
2124
|
+
];
|
|
2125
|
+
return {
|
|
2126
|
+
to: params.poolAddress,
|
|
2127
|
+
data: encodeFunctionData({
|
|
2128
|
+
abi: panopticPoolV2Abi,
|
|
2129
|
+
functionName: "dispatch",
|
|
2130
|
+
args
|
|
2131
|
+
}),
|
|
2132
|
+
creditTokenId,
|
|
2133
|
+
adjustedSize,
|
|
2134
|
+
args
|
|
2135
|
+
};
|
|
2136
|
+
}
|
|
3142
2137
|
/**
|
|
3143
2138
|
* Swap tokens using Panoptic's exact-output mechanism.
|
|
3144
2139
|
*
|
|
@@ -3172,22 +2167,18 @@ async function swapExactOut(params) {
|
|
|
3172
2167
|
const token0 = pool.collateralTracker0.token;
|
|
3173
2168
|
const token1 = pool.collateralTracker1.token;
|
|
3174
2169
|
const tokenOutIndex = resolveTokenIndex(tokenOut, token0, token1);
|
|
3175
|
-
const
|
|
3176
|
-
|
|
3177
|
-
|
|
3178
|
-
|
|
3179
|
-
|
|
3180
|
-
|
|
3181
|
-
|
|
3182
|
-
|
|
3183
|
-
|
|
3184
|
-
|
|
3185
|
-
|
|
3186
|
-
|
|
3187
|
-
];
|
|
3188
|
-
const positionIdList = [creditTokenId, creditTokenId];
|
|
3189
|
-
const finalPositionIdList = [...positionIds];
|
|
3190
|
-
const positionSizes = [adjustedSize, 0n];
|
|
2170
|
+
const call = buildCreditSwapCall({
|
|
2171
|
+
kind: "exactOut",
|
|
2172
|
+
poolAddress,
|
|
2173
|
+
poolId: pool.poolId,
|
|
2174
|
+
currentTick: pool.currentTick,
|
|
2175
|
+
tickSpacing: pool.tickSpacing,
|
|
2176
|
+
existingPositionIds: positionIds,
|
|
2177
|
+
tokenIndex: tokenOutIndex,
|
|
2178
|
+
amountOut,
|
|
2179
|
+
slippageBps,
|
|
2180
|
+
builderCode
|
|
2181
|
+
});
|
|
3191
2182
|
try {
|
|
3192
2183
|
return await submitWrite({
|
|
3193
2184
|
client,
|
|
@@ -3196,14 +2187,7 @@ async function swapExactOut(params) {
|
|
|
3196
2187
|
address: poolAddress,
|
|
3197
2188
|
abi: panopticPoolV2Abi,
|
|
3198
2189
|
functionName: "dispatch",
|
|
3199
|
-
args:
|
|
3200
|
-
positionIdList,
|
|
3201
|
-
finalPositionIdList,
|
|
3202
|
-
positionSizes,
|
|
3203
|
-
[mintTickLimits, burnTickLimits],
|
|
3204
|
-
false,
|
|
3205
|
-
builderCode
|
|
3206
|
-
],
|
|
2190
|
+
args: call.args,
|
|
3207
2191
|
txOverrides
|
|
3208
2192
|
});
|
|
3209
2193
|
} catch (error) {
|
|
@@ -3253,22 +2237,18 @@ async function swapExactIn(params) {
|
|
|
3253
2237
|
const token0 = pool.collateralTracker0.token;
|
|
3254
2238
|
const token1 = pool.collateralTracker1.token;
|
|
3255
2239
|
const tokenInIndex = resolveTokenIndex(tokenIn, token0, token1);
|
|
3256
|
-
const
|
|
3257
|
-
|
|
3258
|
-
|
|
3259
|
-
|
|
3260
|
-
|
|
3261
|
-
|
|
3262
|
-
|
|
3263
|
-
|
|
3264
|
-
|
|
3265
|
-
|
|
3266
|
-
|
|
3267
|
-
|
|
3268
|
-
];
|
|
3269
|
-
const positionIdList = [creditTokenId, creditTokenId];
|
|
3270
|
-
const finalPositionIdList = [...positionIds];
|
|
3271
|
-
const positionSizes = [adjustedSize, 0n];
|
|
2240
|
+
const call = buildCreditSwapCall({
|
|
2241
|
+
kind: "exactIn",
|
|
2242
|
+
poolAddress,
|
|
2243
|
+
poolId: pool.poolId,
|
|
2244
|
+
currentTick: pool.currentTick,
|
|
2245
|
+
tickSpacing: pool.tickSpacing,
|
|
2246
|
+
existingPositionIds: positionIds,
|
|
2247
|
+
tokenIndex: tokenInIndex,
|
|
2248
|
+
amountIn,
|
|
2249
|
+
slippageBps,
|
|
2250
|
+
builderCode
|
|
2251
|
+
});
|
|
3272
2252
|
try {
|
|
3273
2253
|
return await submitWrite({
|
|
3274
2254
|
client,
|
|
@@ -3277,14 +2257,7 @@ async function swapExactIn(params) {
|
|
|
3277
2257
|
address: poolAddress,
|
|
3278
2258
|
abi: panopticPoolV2Abi,
|
|
3279
2259
|
functionName: "dispatch",
|
|
3280
|
-
args:
|
|
3281
|
-
positionIdList,
|
|
3282
|
-
finalPositionIdList,
|
|
3283
|
-
positionSizes,
|
|
3284
|
-
[mintTickLimits, burnTickLimits],
|
|
3285
|
-
false,
|
|
3286
|
-
builderCode
|
|
3287
|
-
],
|
|
2260
|
+
args: call.args,
|
|
3288
2261
|
txOverrides
|
|
3289
2262
|
});
|
|
3290
2263
|
} catch (error) {
|
|
@@ -3873,6 +2846,67 @@ async function simulateWithTokenFlow(params) {
|
|
|
3873
2846
|
};
|
|
3874
2847
|
}
|
|
3875
2848
|
}
|
|
2849
|
+
/**
|
|
2850
|
+
* Get pool token addresses for reference.
|
|
2851
|
+
*
|
|
2852
|
+
* @param params - Parameters
|
|
2853
|
+
* @returns Pool token addresses
|
|
2854
|
+
*/
|
|
2855
|
+
async function getPoolTokensForSimulation(params) {
|
|
2856
|
+
const { client, poolAddress, blockNumber } = params;
|
|
2857
|
+
const poolAbi = [{
|
|
2858
|
+
type: "function",
|
|
2859
|
+
name: "collateralToken0",
|
|
2860
|
+
inputs: [],
|
|
2861
|
+
outputs: [{ type: "address" }],
|
|
2862
|
+
stateMutability: "view"
|
|
2863
|
+
}, {
|
|
2864
|
+
type: "function",
|
|
2865
|
+
name: "collateralToken1",
|
|
2866
|
+
inputs: [],
|
|
2867
|
+
outputs: [{ type: "address" }],
|
|
2868
|
+
stateMutability: "view"
|
|
2869
|
+
}];
|
|
2870
|
+
const collateralAbi = [{
|
|
2871
|
+
type: "function",
|
|
2872
|
+
name: "asset",
|
|
2873
|
+
inputs: [],
|
|
2874
|
+
outputs: [{ type: "address" }],
|
|
2875
|
+
stateMutability: "view"
|
|
2876
|
+
}];
|
|
2877
|
+
const [ct0, ct1] = await client.multicall({
|
|
2878
|
+
contracts: [{
|
|
2879
|
+
address: poolAddress,
|
|
2880
|
+
abi: poolAbi,
|
|
2881
|
+
functionName: "collateralToken0"
|
|
2882
|
+
}, {
|
|
2883
|
+
address: poolAddress,
|
|
2884
|
+
abi: poolAbi,
|
|
2885
|
+
functionName: "collateralToken1"
|
|
2886
|
+
}],
|
|
2887
|
+
blockNumber,
|
|
2888
|
+
allowFailure: false
|
|
2889
|
+
});
|
|
2890
|
+
const [token0, token1] = await client.multicall({
|
|
2891
|
+
contracts: [{
|
|
2892
|
+
address: ct0,
|
|
2893
|
+
abi: collateralAbi,
|
|
2894
|
+
functionName: "asset"
|
|
2895
|
+
}, {
|
|
2896
|
+
address: ct1,
|
|
2897
|
+
abi: collateralAbi,
|
|
2898
|
+
functionName: "asset"
|
|
2899
|
+
}],
|
|
2900
|
+
blockNumber,
|
|
2901
|
+
allowFailure: false
|
|
2902
|
+
});
|
|
2903
|
+
return {
|
|
2904
|
+
token0,
|
|
2905
|
+
token1,
|
|
2906
|
+
collateralTracker0: ct0,
|
|
2907
|
+
collateralTracker1: ct1
|
|
2908
|
+
};
|
|
2909
|
+
}
|
|
3876
2910
|
|
|
3877
2911
|
//#endregion
|
|
3878
2912
|
//#region src/panoptic/v2/simulations/simulateOpenPosition.ts
|
|
@@ -4572,5 +3606,5 @@ async function smartRepayAndWait(params) {
|
|
|
4572
3606
|
}
|
|
4573
3607
|
|
|
4574
3608
|
//#endregion
|
|
4575
|
-
export { addLegToTokenId as addLegToTokenId$1, approve as approve$1, approveAndWait as approveAndWait$1, approvePool as approvePool$1,
|
|
4576
|
-
//# sourceMappingURL=writes-
|
|
3609
|
+
export { addLegToTokenId as addLegToTokenId$1, approve as approve$1, approveAndWait as approveAndWait$1, approvePool as approvePool$1, borrow as borrow$1, borrowAndWait as borrowAndWait$1, buildBatchDispatchArgs as buildBatchDispatchArgs$1, buildCreditSwapCall as buildCreditSwapCall$1, buildOpenPositionCalldata as buildOpenPositionCalldata$1, buildUniqueCredit as buildUniqueCredit$1, buildUniqueLoan as buildUniqueLoan$1, buildUniqueWidthZeroLeg as buildUniqueWidthZeroLeg$1, calculateResyncBlock as calculateResyncBlock$1, cancelTransaction as cancelTransaction$1, checkApproval as checkApproval$1, clearCheckpoint as clearCheckpoint$1, closePosition as closePosition$1, closePositionAndWait as closePositionAndWait$1, countLegs as countLegs$1, createNonceManager as createNonceManager$1, createTokenIdBuilder as createTokenIdBuilder$1, decodeAllLegs as decodeAllLegs$1, decodeLeg as decodeLeg$1, decodePoolId as decodePoolId$1, decodeTickSpacing as decodeTickSpacing$2, decodeTokenId as decodeTokenId$1, decodeVegoid as decodeVegoid$1, deployNewPool as deployNewPool$1, deployNewPoolAndWait as deployNewPoolAndWait$1, deposit as deposit$1, depositAndWait as depositAndWait$1, detectReorg as detectReorg$1, dispatch as dispatch$1, dispatchAndWait as dispatchAndWait$1, encodeLeg as encodeLeg$1, encodePoolId as encodePoolId$1, encodeV4PoolId as encodeV4PoolId$1, executeBatchDispatch as executeBatchDispatch$1, executeBatchDispatchAndWait as executeBatchDispatchAndWait$1, forceExercise as forceExercise$1, forceExerciseAndWait as forceExerciseAndWait$1, getAssetIndex as getAssetIndex$1, getPoolDeploymentBlock as getPoolDeploymentBlock$1, getPoolTokensForSimulation, hasLoanOrCredit as hasLoanOrCredit$1, hasLongLeg as hasLongLeg$1, isCredit as isCredit$1, isCreditLeg as isCreditLeg$1, isInputListFailError as isInputListFailError$1, isLoan as isLoan$1, isLoanLeg as isLoanLeg$1, isShortOnly as isShortOnly$1, isSpread as isSpread$1, liquidate as liquidate$1, liquidateAndWait as liquidateAndWait$1, loadCheckpoint as loadCheckpoint$1, mint as mint$1, mintAndWait as mintAndWait$1, openPosition as openPosition$1, openPositionAndWait as openPositionAndWait$1, pokeOracle as pokeOracle$1, pokeOracleAndWait as pokeOracleAndWait$1, previewBorrow as previewBorrow$1, previewUnwrap as previewUnwrap$1, previewWrap as previewWrap$1, publicBroadcaster as publicBroadcaster$1, reconstructFromEvents as reconstructFromEvents$1, redeem as redeem$1, redeemAndWait as redeemAndWait$1, repay as repay$1, repayAndWait as repayAndWait$1, resolveTokenIndex as resolveTokenIndex$1, rollPosition as rollPosition$1, rollPositionAndWait as rollPositionAndWait$1, saveCheckpoint as saveCheckpoint$1, settleAccumulatedPremia as settleAccumulatedPremia$1, settleAccumulatedPremiaAndWait as settleAccumulatedPremiaAndWait$1, simulateOpenPosition as simulateOpenPosition$1, simulateWithTokenFlow as simulateWithTokenFlow$1, smartRepay as smartRepay$1, smartRepayAndWait as smartRepayAndWait$1, speedUpTransaction as speedUpTransaction$1, supply as supply$1, supplyAndWait as supplyAndWait$1, swapExactIn as swapExactIn$1, swapExactInAndWait as swapExactInAndWait$1, swapExactOut as swapExactOut$1, swapExactOutAndWait as swapExactOutAndWait$1, syncPositions as syncPositions$1, unsupply as unsupply$1, unsupplyAndWait as unsupplyAndWait$1, unwrapWeth as unwrapWeth$1, unwrapWethAndWait as unwrapWethAndWait$1, unwrapXstock as unwrapXstock$1, unwrapXstockAndWait as unwrapXstockAndWait$1, validateBatch as validateBatch$1, validatePoolId as validatePoolId$1, verifyBlockContinuity as verifyBlockContinuity$1, wethWrapAbi as wethWrapAbi$1, withdraw as withdraw$1, withdrawAndWait as withdrawAndWait$1, withdrawWithPositions as withdrawWithPositions$1, withdrawWithPositionsAndWait as withdrawWithPositionsAndWait$1, wrapEth as wrapEth$1, wrapEthAndWait as wrapEthAndWait$1, wrapXstock as wrapXstock$1, wrapXstockAndWait as wrapXstockAndWait$1, xstockWrapperAbi as xstockWrapperAbi$1 };
|
|
3610
|
+
//# sourceMappingURL=writes-D3bj1wth.js.map
|