Skip to content

Commit

Permalink
fix panoptic positions
Browse files Browse the repository at this point in the history
  • Loading branch information
kyscott18 committed Oct 3, 2023
1 parent 7fe75b0 commit 8003826
Show file tree
Hide file tree
Showing 22 changed files with 490 additions and 192 deletions.
2 changes: 2 additions & 0 deletions packages/panoptic-sdk/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ Typescript SDK for Panoptic
- [x] `createPanopticPool`
- [x] `createPanopticCollateral`
- [x] `createPanopticPosition`
- [x] `createPanopticSemiFungiblePosition`
- [x] `calculatePanopticTokenID`
- [x] `calculatePanopticPositionKey`
- [ ] `calculatePanopticDeployNewPool`
Expand All @@ -47,6 +48,7 @@ Typescript SDK for Panoptic
- [x] `getPanopticCollateralPositionData`
- [x] `getPanoptionLegData`
- [x] `getPanopticPositionData`
- [x] `getPanopticSemiFungiblePositionData`
- [x] `simulatePanopticDeployNewPool`
- [x] `simulatePanopticMintOptions`
- [x] `simulatePanopticBurnOptions`
Expand Down
1 change: 1 addition & 0 deletions packages/panoptic-sdk/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ export { getPanopticCollateralData } from "./publicActions/getPanopticCollateral
export { getPanopticCollateralPositionData } from "./publicActions/getPanopticCollateralPositionData.js";
export { getPanoptionLegData } from "./publicActions/getPanoptionLegData.js";
export { getPanopticPositionData } from "./publicActions/getPanopticPositionData.js";
export { getPanopticSemiFungiblePositionData } from "./publicActions/getPanopticSemiFungiblePositionData.js";

export { simulatePanopticCollateralDeposit } from "./publicActions/simulatePanopticCollateralDeposit.js";
export { simulatePanopticCollateralWithdraw } from "./publicActions/simulatePanopticCollateralWithdraw.js";
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
import { createAmountFromString } from "reverse-mirage";
import { createUniswapV3Tick } from "uniswap-v3-sdk";
import { type Hex } from "viem";
import { simulateContract, writeContract } from "viem/actions";
import { beforeEach, expect, test } from "vitest";
import { ALICE } from "../_test/constants.js";
import {
deployPool,
publicClient,
testClient,
walletClient,
} from "../_test/utils.js";
import { mockErc20ABI } from "../generated.js";
import type { PanopticPool } from "../types/PanopticPool.js";
import type { PanopticPosition } from "../types/PanopticPosition.js";
import { createPanopticPosition } from "../utils/createPanopticPosition.js";
import { getPanopticPositionData } from "./getPanopticPositionData.js";
import { simulatePanopticCollateralDeposit } from "./simulatePanopticCollateralDeposit.js";
import { simulatePanopticMintOptions } from "./simulatePanopticMintOptions.js";
import { simulatePanopticSFPMInitializeAMMPool } from "./simulatePanopticSFPMInitializeAMMPool.js";

let id: Hex | undefined = undefined;

let pool: PanopticPool;

let position: PanopticPosition;

beforeEach(async () => {
if (id === undefined) {
pool = await deployPool();
const { request: initializeRequest } =
await simulatePanopticSFPMInitializeAMMPool(publicClient, {
args: {
pool: pool.uniswapPool,
sfpm: pool.factory.semiFungiblePositionManager,
},
});

const initializeHash = await walletClient.writeContract(initializeRequest);
await publicClient.waitForTransactionReceipt({ hash: initializeHash });

const { request: approveRequest } = await simulateContract(publicClient, {
address: pool.collateralTracker0.underlyingToken.address,
abi: mockErc20ABI,
functionName: "approve",
args: [pool.collateralTracker0.address, 10n ** 18n],
account: ALICE,
});

const approveHash = await writeContract(walletClient, approveRequest);
await publicClient.waitForTransactionReceipt({ hash: approveHash });

const { request: depositRequest } = await simulatePanopticCollateralDeposit(
publicClient,
{
args: {
collateral: pool.collateralTracker0,
amount: createAmountFromString(
pool.collateralTracker0.underlyingToken,
"1",
),
to: ALICE,
},
account: ALICE,
},
);

const depositHash = await writeContract(walletClient, depositRequest);
await publicClient.waitForTransactionReceipt({ hash: depositHash });

position = createPanopticPosition(ALICE, pool, [
{
asset: "token0",
optionRatio: 1,
position: "short",
tokenType: "token0",
riskPartnerIndex: 0,
tickLower: createUniswapV3Tick(0),
tickUpper: createUniswapV3Tick(10),
},
undefined,
undefined,
undefined,
]);

const { request } = await simulatePanopticMintOptions(publicClient, {
args: {
position,
amount: 5n * 10n ** 17n,
},
account: ALICE,
});
const hash = await walletClient.writeContract(request);
await publicClient.waitForTransactionReceipt({ hash });
} else {
await testClient.revert({ id });
}
id = await testClient.snapshot();
}, 100_000);

test("get position data", async () => {
const positionData = await getPanopticPositionData(publicClient, {
position,
});

expect(positionData.position).toStrictEqual(position);
expect(positionData.amount).toBe(5n * 10n ** 17n);
});
61 changes: 15 additions & 46 deletions packages/panoptic-sdk/src/publicActions/getPanopticPositionData.ts
Original file line number Diff line number Diff line change
@@ -1,77 +1,46 @@
import { createFraction } from "reverse-mirage";
import type { UniswapV3Tick } from "uniswap-v3-sdk";
import type { Chain, Client, ReadContractParameters, Transport } from "viem";
import { readContract } from "viem/actions";
import { panopticPoolABI } from "../generated.js";
import type {
PanopticPosition,
PanopticPositionData,
} from "../types/PanopticPosition.js";
import { getPanoptionLegData } from "./getPanoptionLegData.js";

export type GetPanopticPositionDataParameters = Omit<
ReadContractParameters<typeof panopticPoolABI, "totalSupply">,
"address" | "abi" | "functionName" | "args"
> & {
panopticPosition: PanopticPosition;
tick: UniswapV3Tick;
position: PanopticPosition;
};

export type GetPanopticPositionDataReturnType = PanopticPositionData;

export const getPanopticPositionData = <TChain extends Chain | undefined>(
client: Client<Transport, TChain>,
{ panopticPosition, tick, ...request }: GetPanopticPositionDataParameters,
{ position, ...request }: GetPanopticPositionDataParameters,
): Promise<GetPanopticPositionDataReturnType> =>
Promise.all([
readContract(client, {
abi: panopticPoolABI,
functionName: "optionPositionBalance",
address: panopticPosition.pool.address,
args: [panopticPosition.address, panopticPosition.id],
address: position.pool.address,
args: [position.owner, position.id],
...request,
}),
panopticPosition.legs[0]
? getPanoptionLegData(client, {
leg: panopticPosition.legs[0],
address: panopticPosition.address,
pool: panopticPosition.pool,
tick,
...request,
})
: undefined,
panopticPosition.legs[1]
? getPanoptionLegData(client, {
leg: panopticPosition.legs[1],
address: panopticPosition.address,
pool: panopticPosition.pool,
tick,
...request,
})
: undefined,
panopticPosition.legs[2]
? getPanoptionLegData(client, {
leg: panopticPosition.legs[2],
address: panopticPosition.address,
pool: panopticPosition.pool,
tick,
...request,
})
: undefined,
panopticPosition.legs[3]
? getPanoptionLegData(client, {
leg: panopticPosition.legs[3],
address: panopticPosition.address,
pool: panopticPosition.pool,
tick,
...request,
})
: undefined,
] as const).then(([optionsBalance, leg0, leg1, leg2, leg3]) => ({
readContract(client, {
abi: panopticPoolABI,
functionName: "calculateAccumulatedFeesBatch",
address: position.pool.address,
args: [position.owner, [position.id]],
...request,
}),
] as const).then(([optionsBalance, accumumlatedFees]) => ({
type: "panopticPositionData",
position,
amount: optionsBalance[0],
token0Utilization: createFraction(optionsBalance[1], 2n ** 64n),
token1Utilization: createFraction(optionsBalance[2], 2n ** 64n),
token: panopticPosition,
legData: [leg0, leg1, leg2, leg3],
premium0: accumumlatedFees[0],
premium1: accumumlatedFees[1],
}));
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
import { createUniswapV3Tick } from "uniswap-v3-sdk";
import { type Hex } from "viem";
import { simulateContract, writeContract } from "viem/actions";
import { sepolia } from "viem/chains";
import { beforeEach, expect, test } from "vitest";
import { ALICE } from "../_test/constants.js";
import {
deployPool,
publicClient,
testClient,
walletClient,
} from "../_test/utils.js";
import { mockErc20ABI } from "../generated.js";
import type { PanopticPool } from "../types/PanopticPool.js";
import type { PanopticSemiFungiblePosition } from "../types/PanopticSemiFungiblePositionManager.js";
import { createPanopticSemiFungiblePosition } from "../utils/createPanopticSemiFungiblePosition.js";
import { getPanopticSemiFungiblePositionData } from "./getPanopticSemiFungiblePositionData.js";
import { simulatePanopticSFPMInitializeAMMPool } from "./simulatePanopticSFPMInitializeAMMPool.js";
import { simulatePanopticSFPMMintTokenizedPosition } from "./simulatePanopticSFPMMintTokenizedPosition.js";

let id: Hex | undefined = undefined;

let pool: PanopticPool;

let position: PanopticSemiFungiblePosition;

beforeEach(async () => {
if (id === undefined) {
pool = await deployPool();
const { request: initializeRequest } =
await simulatePanopticSFPMInitializeAMMPool(publicClient, {
args: {
pool: pool.uniswapPool,
sfpm: pool.factory.semiFungiblePositionManager,
},
});

const initializeHash = await walletClient.writeContract(initializeRequest);
await publicClient.waitForTransactionReceipt({ hash: initializeHash });

const { request: approveRequest } = await simulateContract(publicClient, {
address: pool.collateralTracker0.underlyingToken.address,
abi: mockErc20ABI,
functionName: "approve",
args: [pool.factory.semiFungiblePositionManager.address, 10n ** 18n],
account: ALICE,
});

const approveHash = await writeContract(walletClient, approveRequest);
await publicClient.waitForTransactionReceipt({ hash: approveHash });

position = createPanopticSemiFungiblePosition(
ALICE,
pool.factory.semiFungiblePositionManager,
[
{
asset: "token0",
optionRatio: 1,
position: "short",
tokenType: "token0",
riskPartnerIndex: 0,
tickLower: createUniswapV3Tick(0),
tickUpper: createUniswapV3Tick(10),
},
undefined,
undefined,
undefined,
],
pool.uniswapPool,
sepolia.id,
);

const { request } = await simulatePanopticSFPMMintTokenizedPosition(
publicClient,
{
args: {
position,
amount: 10n ** 18n,
},
account: ALICE,
},
);
const hash = await walletClient.writeContract(request);
await publicClient.waitForTransactionReceipt({ hash });
} else {
await testClient.revert({ id });
}
id = await testClient.snapshot();
}, 100_000);

test("get sfpm position data", async () => {
const positionData = await getPanopticSemiFungiblePositionData(publicClient, {
position,
tick: createUniswapV3Tick(0),
});

expect(positionData.amount).toBe(10n ** 18n);
expect(positionData.token).toStrictEqual(position);
});
Loading

0 comments on commit 8003826

Please sign in to comment.