Skip to content

Commit 757b2b3

Browse files
committed
Implements lockPosition test code
1 parent f4d44f8 commit 757b2b3

File tree

1 file changed

+154
-0
lines changed

1 file changed

+154
-0
lines changed
Lines changed: 154 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,154 @@
1+
import { describe, it, beforeAll } from "vitest";
2+
import type { Address } from "@solana/kit";
3+
import { rpc, sendTransaction, signer } from "./utils/mockRpc";
4+
import assert from "assert";
5+
import { setupAta, setupMint } from "./utils/token";
6+
import {
7+
setupAtaTE,
8+
setupMintTE,
9+
setupMintTEFee,
10+
} from "./utils/tokenExtensions";
11+
import {
12+
setupPosition,
13+
setupTEPosition,
14+
setupWhirlpool,
15+
} from "./utils/program";
16+
import {
17+
fetchLockConfig,
18+
getPositionAddress,
19+
LockType,
20+
} from "@orca-so/whirlpools-client";
21+
import { lockPositionInstructions } from "../src/lockPosition";
22+
import { getLockConfigAddress } from "../../client/src/pda/lockConfig";
23+
import {
24+
fetchMaybeMint,
25+
findAssociatedTokenPda,
26+
} from "@solana-program/token-2022";
27+
28+
const mintTypes = new Map([
29+
["A", setupMint],
30+
["B", setupMint],
31+
["TEA", setupMintTE],
32+
["TEB", setupMintTE],
33+
["TEFee", setupMintTEFee],
34+
]);
35+
36+
const ataTypes = new Map([
37+
["A", setupAta],
38+
["B", setupAta],
39+
["TEA", setupAtaTE],
40+
["TEB", setupAtaTE],
41+
["TEFee", setupAtaTE],
42+
]);
43+
44+
const poolTypes = new Map([
45+
["A-B", setupWhirlpool],
46+
["A-TEA", setupWhirlpool],
47+
["TEA-TEB", setupWhirlpool],
48+
["A-TEFee", setupWhirlpool],
49+
]);
50+
51+
const positionTypes = new Map([
52+
["equally centered", { tickLower: -100, tickUpper: 100 }],
53+
["one sided A", { tickLower: -100, tickUpper: -1 }],
54+
["one sided B", { tickLower: 1, tickUpper: 100 }],
55+
]);
56+
57+
describe("LockPosition instructions", () => {
58+
const tickSpacing = 64;
59+
const tokenBalance = 1_000_000n;
60+
const initialLiquidity = 100_000n;
61+
const mints: Map<string, Address> = new Map();
62+
const atas: Map<string, Address> = new Map();
63+
const pools: Map<string, Address> = new Map();
64+
const positions: Map<string, Address> = new Map();
65+
66+
beforeAll(async () => {
67+
for (const [name, setup] of mintTypes) {
68+
mints.set(name, await setup());
69+
}
70+
71+
for (const [name, setup] of ataTypes) {
72+
const mint = mints.get(name)!;
73+
atas.set(name, await setup(mint, { amount: tokenBalance }));
74+
}
75+
76+
for (const [name, setup] of poolTypes) {
77+
const [mintAKey, mintBKey] = name.split("-");
78+
const mintA = mints.get(mintAKey)!;
79+
const mintB = mints.get(mintBKey)!;
80+
pools.set(name, await setup(mintA, mintB, tickSpacing));
81+
}
82+
83+
for (const [poolName, poolAddress] of pools) {
84+
for (const [positionTypeName, tickRange] of positionTypes) {
85+
const position = await setupPosition(poolAddress, {
86+
...tickRange,
87+
liquidity: initialLiquidity,
88+
});
89+
positions.set(`${poolName} ${positionTypeName}`, position);
90+
91+
const positionTE = await setupTEPosition(poolAddress, {
92+
...tickRange,
93+
liquidity: initialLiquidity,
94+
});
95+
positions.set(`TE ${poolName} ${positionTypeName}`, positionTE);
96+
}
97+
}
98+
});
99+
100+
const testlockPosition = async (poolName: string, positionName: string) => {
101+
const positionMintAddress = positions.get(positionName)!;
102+
const [positionAddress] = await getPositionAddress(positionMintAddress);
103+
const [lockConfigAddress] = await getLockConfigAddress(positionAddress);
104+
const positionMint = await fetchMaybeMint(rpc, positionMintAddress);
105+
106+
assert(positionMint.exists, "Position mint not found");
107+
108+
const [positionTokenAccountAddress] = await findAssociatedTokenPda({
109+
owner: signer.address,
110+
mint: positionMintAddress,
111+
tokenProgram: positionMint.programAddress,
112+
});
113+
const lockPositionInstruction = await lockPositionInstructions({
114+
lockType: LockType.Permanent,
115+
funder: signer,
116+
positionAuthority: signer,
117+
position: positionAddress,
118+
positionMint: positionMintAddress,
119+
positionTokenAccount: positionTokenAccountAddress,
120+
lockConfigPda: lockConfigAddress,
121+
whirlpool: pools.get(poolName)!,
122+
});
123+
124+
await sendTransaction(lockPositionInstruction.instructions);
125+
126+
// Verify lock config
127+
const lockConfig = await fetchLockConfig(rpc, lockConfigAddress);
128+
assert(
129+
lockConfig.data.lockType.toFixed() == LockType.Permanent.toFixed(),
130+
"Lock config lock type is not permanent",
131+
);
132+
assert(
133+
lockConfig.data.lockedTimestamp > 0,
134+
"Lock config locked timestamp is not set",
135+
);
136+
assert(
137+
lockConfig.data.position == positionAddress,
138+
"Lock config position is not the same as the position",
139+
);
140+
assert(
141+
lockConfig.data.positionOwner === signer.address,
142+
"Lock config position owner is not the same as the signer",
143+
);
144+
};
145+
146+
for (const poolName of poolTypes.keys()) {
147+
for (const positionTypeName of positionTypes.keys()) {
148+
const positionNameTE = `TE ${poolName} ${positionTypeName}`;
149+
it(`Should be able to lock position for ${positionNameTE}`, async () => {
150+
await testlockPosition(poolName, positionNameTE);
151+
});
152+
}
153+
}
154+
});

0 commit comments

Comments
 (0)