@provablehq/shield-swap-cli 0.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,352 @@
1
+ import {
2
+ confirmed,
3
+ done,
4
+ fail,
5
+ flags,
6
+ output,
7
+ run,
8
+ step,
9
+ warn
10
+ } from "./chunk-IBVZHLUT.js";
11
+ import "./chunk-IHYFMX5A.js";
12
+ import {
13
+ formatAmount,
14
+ loadSession,
15
+ namedAmounts,
16
+ pollUntil
17
+ } from "./chunk-2OT6LZPW.js";
18
+
19
+ // src/commands/liquidity.ts
20
+ import {
21
+ amountsForLiquidity,
22
+ getSqrtPriceAtTickX128,
23
+ liquidityForAmounts,
24
+ liquidityForAmount
25
+ } from "@provablehq/shield-swap-sdk";
26
+ var USAGE = `shield-swap liquidity \u2014 add to or withdraw from an open position
27
+
28
+ --position <id> position token id (required)
29
+ --increase commit more of both tokens
30
+ --decrease remove liquidity, booking it as owed
31
+ --amount <symbol>:<decimal> how much of one named token, e.g. USDCx:0.5.
32
+ Repeatable, once per side. Prefer this \u2014 it does
33
+ not depend on knowing the pool's token order
34
+ --amount0 <decimal> token0 to add, or to withdraw, in human units
35
+ --amount1 <decimal> token1 to add, or to withdraw
36
+ --percent <n> --increase: n% of the private balance of both
37
+ sides; --decrease: n% of the position's liquidity
38
+ --network <testnet|mainnet> default testnet
39
+ --execute actually submit
40
+ --json machine-readable output
41
+
42
+ List positions with \`shield-swap positions\`. A decrease books what it removes as
43
+ owed to the position \u2014 run \`shield-swap collect\` to take it out.
44
+
45
+ --amount0/--amount1 follow the pool's own token order; the line this script
46
+ prints for the position names both symbols.`;
47
+ async function main(argv) {
48
+ const args = flags(
49
+ {
50
+ position: { type: "string" },
51
+ increase: { type: "boolean" },
52
+ decrease: { type: "boolean" },
53
+ amount: { type: "string", multiple: true },
54
+ amount0: { type: "string" },
55
+ amount1: { type: "string" },
56
+ percent: { type: "string" }
57
+ },
58
+ USAGE,
59
+ argv
60
+ );
61
+ const bySymbol = args.amount ?? [];
62
+ const anyAmount = bySymbol.length > 0 || !!args.amount0 || !!args.amount1;
63
+ if (!args.position) fail(`--position is required.
64
+
65
+ ${USAGE}`);
66
+ if (!!args.increase === !!args.decrease) fail(`pass exactly one of --increase or --decrease.
67
+
68
+ ${USAGE}`);
69
+ if (!args.percent && !anyAmount) {
70
+ fail(`--percent, --amount, --amount0, or --amount1 is required.
71
+
72
+ ${USAGE}`);
73
+ }
74
+ if (args.percent && anyAmount) {
75
+ fail(`--percent and the amount flags are alternatives, not both.
76
+
77
+ ${USAGE}`);
78
+ }
79
+ const positionTokenId = args.position;
80
+ const percent = args.percent ? Number(args.percent) : void 0;
81
+ if (percent !== void 0 && (!(percent > 0) || percent > 100)) {
82
+ fail(`--percent must be greater than 0 and at most 100, got ${args.percent}`);
83
+ }
84
+ const share = (total, pct) => total * BigInt(Math.round(pct * 100)) / 10000n;
85
+ const amountsFor = (token0, token1) => namedAmounts({
86
+ entries: bySymbol,
87
+ indexed: [args.amount0, args.amount1],
88
+ tokens: [token0, token1]
89
+ });
90
+ await run(async () => {
91
+ const { client, network } = await loadSession({ network: args.network });
92
+ done(`session on ${network}`);
93
+ step("reading the position from chain");
94
+ const position = await client.getOwnedPosition({ positionTokenId });
95
+ if (!position) {
96
+ throw new Error(
97
+ `this account holds no position record for ${positionTokenId} on ${network}. List what it does hold with \`shield-swap positions\`.`
98
+ );
99
+ }
100
+ if (position.frozen) {
101
+ throw new Error(
102
+ `position ${positionTokenId} is frozen: every liquidity operation on it reverts until an admin unfreezes it.`
103
+ );
104
+ }
105
+ const state = position.state;
106
+ if (!state) {
107
+ throw new Error(
108
+ `position ${positionTokenId} has no entry in the positions mapping. Either its mint has not finalized yet \u2014 wait a few seconds and retry \u2014 or it was already burned and the record scanner is still serving the spent record, which it can do for minutes. Neither can be operated on.`
109
+ );
110
+ }
111
+ const tokens = await client.listTokens();
112
+ const infoOf = (id) => tokens.find((token) => token.id === id);
113
+ const token0 = infoOf(position.token0Id);
114
+ const token1 = infoOf(position.token1Id);
115
+ if (!token0 || !token1) throw new Error(`the registry does not describe both tokens of pool ${position.poolKey}.`);
116
+ const pair = `${token0.symbol}/${token1.symbol}`;
117
+ done(`${pair} position over ticks ${position.tickLower}\u2026${position.tickUpper}, liquidity ${state.liquidity}`);
118
+ const waitForLiquidity = async (predicate, verb) => {
119
+ let settled2;
120
+ const caught = await pollUntil(
121
+ async () => {
122
+ const onchain = await client.getPosition({ positionTokenId });
123
+ if (onchain && predicate(onchain.liquidity)) settled2 = onchain.liquidity;
124
+ return settled2 !== void 0;
125
+ },
126
+ 10,
127
+ 3e3
128
+ );
129
+ if (!caught) {
130
+ warn(
131
+ `the position's liquidity did not ${verb} within 30s of the transaction landing \u2014 the mapping may still be catching up; check \`shield-swap positions\``
132
+ );
133
+ }
134
+ return settled2;
135
+ };
136
+ if (args.increase) {
137
+ const balances = await client.getBalances({ tokens: [token0.id, token1.id] });
138
+ const held0 = balances[token0.id]?.private ?? 0n;
139
+ const held1 = balances[token1.id]?.private ?? 0n;
140
+ const { amount0: named0, amount1: named1 } = amountsFor(token0, token1);
141
+ let budget0 = percent ? share(held0, percent) : named0 ?? held0;
142
+ let budget1 = percent ? share(held1, percent) : named1 ?? held1;
143
+ if (!percent && named0 === void 0 !== (named1 === void 0)) {
144
+ const side = named0 === void 0 ? 1 : 0;
145
+ const named = named0 ?? named1;
146
+ const slot2 = await client.getSlot({ poolKey: position.poolKey });
147
+ if (!slot2) throw new Error(`pool ${position.poolKey} has no slot on chain`);
148
+ const range = {
149
+ sqrtPriceX128: slot2.sqrt_price,
150
+ sqrtLowerX128: getSqrtPriceAtTickX128(position.tickLower),
151
+ sqrtUpperX128: getSqrtPriceAtTickX128(position.tickUpper)
152
+ };
153
+ const liquidity = liquidityForAmount({ ...range, side, amount: named });
154
+ if (liquidity === 0n) {
155
+ const other = side === 0 ? token1 : token0;
156
+ const unused = side === 0 ? slot2.tick >= position.tickUpper : slot2.tick < position.tickLower;
157
+ throw new Error(
158
+ unused ? `at tick ${slot2.tick} this position holds only ${other.symbol}, so ${side === 0 ? token0.symbol : token1.symbol} cannot fund it \u2014 name --amount${other === token1 ? "1" : "0"} instead.` : `${formatAmount(named, side === 0 ? token0.decimals : token1.decimals, side === 0 ? token0.symbol : token1.symbol)} adds no liquidity over ticks ${position.tickLower}\u2026${position.tickUpper} \u2014 commit more.`
159
+ );
160
+ }
161
+ const required = amountsForLiquidity({ ...range, liquidity, roundUp: true });
162
+ budget0 = required.amount0;
163
+ budget1 = required.amount1;
164
+ const derived = side === 0 ? token1 : token0;
165
+ const amount = side === 0 ? required.amount1 : required.amount0;
166
+ done(`${derived.symbol} derived: ${formatAmount(amount, derived.decimals, derived.symbol)} needed alongside`);
167
+ }
168
+ step("pricing the addition against the pool\u2019s live price");
169
+ const preview = await client.previewMint({
170
+ poolKey: position.poolKey,
171
+ amount0Desired: budget0,
172
+ amount1Desired: budget1,
173
+ tickLower: position.tickLower,
174
+ tickUpper: position.tickUpper
175
+ });
176
+ if (preview.liquidity === 0n) {
177
+ throw new Error(
178
+ `that budget adds no liquidity over ticks ${position.tickLower}\u2026${position.tickUpper} \u2014 commit more. An increase would cost a fee and add nothing.`
179
+ );
180
+ }
181
+ for (const side of [
182
+ { info: token0, needed: preview.amount0, held: held0 },
183
+ { info: token1, needed: preview.amount1, held: held1 }
184
+ ]) {
185
+ if (side.needed > side.held) {
186
+ throw new Error(
187
+ `the addition needs ${formatAmount(side.needed, side.info.decimals, side.info.symbol)} but only ${formatAmount(side.held, side.info.decimals, side.info.symbol)} is held privately.`
188
+ );
189
+ }
190
+ }
191
+ const planLines2 = [
192
+ ["position", positionTokenId],
193
+ ["pool", `${pair} ticks ${position.tickLower}\u2026${position.tickUpper}`],
194
+ ["add", formatAmount(preview.amount0, token0.decimals, token0.symbol)],
195
+ // Empty label: the second side of the same deposit, not a separate step.
196
+ ["", formatAmount(preview.amount1, token1.decimals, token1.symbol)],
197
+ ["liquidity", `${state.liquidity} \u2192 about ${state.liquidity + preview.liquidity}`]
198
+ ];
199
+ if (!confirmed({ execute: args.execute, network, plan: planLines2 })) {
200
+ output({ network, submitted: false, action: "increase", positionTokenId, preview }, () => {
201
+ });
202
+ return;
203
+ }
204
+ const imports = await client.resolveDexImports({
205
+ tokenPrograms: [token0.ammTokenProgram, token1.ammTokenProgram].filter(
206
+ (program) => !!program
207
+ )
208
+ });
209
+ step("proving and submitting the increase \u2014 this takes a minute or two");
210
+ const result2 = await client.increaseLiquidity({
211
+ positionTokenId,
212
+ poolKey: position.poolKey,
213
+ amount0Desired: preview.amount0,
214
+ amount1Desired: preview.amount1,
215
+ imports
216
+ });
217
+ done(`increase landed: tx ${result2.transactionId}`);
218
+ const settled2 = await waitForLiquidity((liquidity) => liquidity > state.liquidity, "grow");
219
+ output(
220
+ {
221
+ network,
222
+ submitted: true,
223
+ action: "increase",
224
+ positionTokenId,
225
+ transactionId: result2.transactionId,
226
+ added0: preview.amount0,
227
+ added1: preview.amount1,
228
+ liquidityBefore: state.liquidity,
229
+ liquidityAfter: settled2 ?? null
230
+ },
231
+ (data) => {
232
+ console.log(
233
+ `
234
+ Added ${formatAmount(data.added0, token0.decimals, token0.symbol)} and ${formatAmount(data.added1, token1.decimals, token1.symbol)} to position ${data.positionTokenId}.`
235
+ );
236
+ console.log(`Liquidity ${data.liquidityBefore} \u2192 ${data.liquidityAfter ?? "still settling"}.`);
237
+ }
238
+ );
239
+ return;
240
+ }
241
+ if (state.liquidity === 0n) {
242
+ throw new Error(
243
+ `position ${positionTokenId} holds no liquidity to remove. Collect what it is owed with \`shield-swap collect --position <id> --close\`.`
244
+ );
245
+ }
246
+ const slot = await client.getSlot({ poolKey: position.poolKey });
247
+ if (!slot) throw new Error(`pool ${position.poolKey} has no slot state, so it cannot be operated on.`);
248
+ const sqrtLower = getSqrtPriceAtTickX128(position.tickLower);
249
+ const sqrtUpper = getSqrtPriceAtTickX128(position.tickUpper);
250
+ let liquidityToRemove;
251
+ if (percent) {
252
+ liquidityToRemove = percent === 100 ? state.liquidity : share(state.liquidity, percent);
253
+ } else {
254
+ const named = amountsFor(token0, token1);
255
+ const want0 = named.amount0 ?? null;
256
+ const want1 = named.amount1 ?? null;
257
+ for (const side of [
258
+ { want: want0, backing: state.amount0, info: token0 },
259
+ { want: want1, backing: state.amount1, info: token1 }
260
+ ]) {
261
+ if (side.want !== null && side.want > side.backing) {
262
+ throw new Error(
263
+ `asked to withdraw ${formatAmount(side.want, side.info.decimals, side.info.symbol)} but the position backs ${formatAmount(side.backing, side.info.decimals, side.info.symbol)} at the pool's current price.`
264
+ );
265
+ }
266
+ }
267
+ const requested = liquidityForAmounts({
268
+ sqrtPriceX128: slot.sqrt_price,
269
+ sqrtLowerX128: sqrtLower,
270
+ sqrtUpperX128: sqrtUpper,
271
+ amount0: want0 ?? state.amount0,
272
+ amount1: want1 ?? state.amount1
273
+ });
274
+ liquidityToRemove = requested > state.liquidity ? state.liquidity : requested;
275
+ }
276
+ if (liquidityToRemove === 0n) {
277
+ throw new Error(
278
+ "that amount converts to zero liquidity for this range \u2014 ask for more, or use --percent to remove a share of the position instead."
279
+ );
280
+ }
281
+ const booked = amountsForLiquidity({
282
+ sqrtPriceX128: slot.sqrt_price,
283
+ sqrtLowerX128: sqrtLower,
284
+ sqrtUpperX128: sqrtUpper,
285
+ liquidity: liquidityToRemove,
286
+ roundUp: false
287
+ });
288
+ const planLines = [
289
+ ["position", positionTokenId],
290
+ ["pool", `${pair} ticks ${position.tickLower}\u2026${position.tickUpper}`],
291
+ ["remove", `${liquidityToRemove} of ${state.liquidity} liquidity`],
292
+ ["books", `about ${formatAmount(booked.amount0, token0.decimals, token0.symbol)}`],
293
+ // Empty label: the second side of the same booking.
294
+ ["", `about ${formatAmount(booked.amount1, token1.decimals, token1.symbol)}`],
295
+ ["payout", "none \u2014 this books the amounts as owed; `shield-swap collect` pays them out"]
296
+ ];
297
+ if (!confirmed({ execute: args.execute, network, plan: planLines })) {
298
+ output(
299
+ {
300
+ network,
301
+ submitted: false,
302
+ action: "decrease",
303
+ positionTokenId,
304
+ liquidityToRemove,
305
+ booked0: booked.amount0,
306
+ booked1: booked.amount1
307
+ },
308
+ () => {
309
+ }
310
+ );
311
+ return;
312
+ }
313
+ step("proving and submitting the decrease \u2014 this takes a minute or two");
314
+ const result = await client.decreaseLiquidity({
315
+ positionTokenId,
316
+ poolKey: position.poolKey,
317
+ liquidityToRemove
318
+ });
319
+ done(`decrease landed: tx ${result.transactionId}`);
320
+ const settled = await waitForLiquidity((liquidity) => liquidity < state.liquidity, "shrink");
321
+ const owed = await client.getPosition({ positionTokenId });
322
+ output(
323
+ {
324
+ network,
325
+ submitted: true,
326
+ action: "decrease",
327
+ positionTokenId,
328
+ transactionId: result.transactionId,
329
+ liquidityRemoved: liquidityToRemove,
330
+ liquidityBefore: state.liquidity,
331
+ liquidityAfter: settled ?? null,
332
+ owed0: owed?.tokens_owed0 ?? null,
333
+ owed1: owed?.tokens_owed1 ?? null
334
+ },
335
+ (data) => {
336
+ console.log(`
337
+ Removed ${data.liquidityRemoved} liquidity from position ${data.positionTokenId}.`);
338
+ console.log(`Liquidity ${data.liquidityBefore} \u2192 ${data.liquidityAfter ?? "still settling"}.`);
339
+ if (data.owed0 !== null && data.owed1 !== null) {
340
+ console.log(
341
+ `Owed to the position: ${formatAmount(data.owed0, token0.decimals, token0.symbol)} and ${formatAmount(data.owed1, token1.decimals, token1.symbol)}.`
342
+ );
343
+ }
344
+ console.log("Take it out with `shield-swap collect --position <id>`.");
345
+ }
346
+ );
347
+ });
348
+ }
349
+ export {
350
+ main
351
+ };
352
+ //# sourceMappingURL=liquidity-RB5MKGPA.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/commands/liquidity.ts"],"sourcesContent":["/**\n * Liquidity — deepen an open position, or take part of it back out.\n *\n * The range is fixed at mint, so neither direction changes it: `--increase`\n * commits more of both tokens over the same bounds, `--decrease` removes\n * liquidity and books the proceeds as owed to the position. Withdrawing does not\n * pay out — `shield-swap collect` is what turns an owed balance into records the account\n * holds.\n *\n * The position is read from chain first. Two states block every liquidity\n * operation and are worth catching before spending a fee: a frozen position (an\n * admin froze it) and one with no entry in the positions mapping (a mint still\n * finalizing, or one already burned whose record the scanner still serves).\n *\n * SPENDS REAL FUNDS with --execute. Without it, prints the plan and stops.\n *\n * Usage:\n * shield-swap liquidity --position <id> --increase --percent 1\n * shield-swap liquidity --position <id> --increase --percent 1 --execute\n * shield-swap liquidity --position <id> --increase --amount0 0.5 --execute\n * shield-swap liquidity --position <id> --decrease --percent 50 --execute\n * shield-swap liquidity --position <id> --decrease --amount1 0.25 --execute\n */\nimport type { TokenInfo } from '@provablehq/shield-swap-sdk'\nimport {\n amountsForLiquidity,\n getSqrtPriceAtTickX128,\n liquidityForAmounts,\n liquidityForAmount,\n} from '@provablehq/shield-swap-sdk'\nimport { loadSession, formatAmount, namedAmounts, pollUntil } from '../session.js'\nimport { flags, step, done, warn, output, confirmed, run, fail } from '../shared.js'\n\nconst USAGE = `shield-swap liquidity — add to or withdraw from an open position\n\n --position <id> position token id (required)\n --increase commit more of both tokens\n --decrease remove liquidity, booking it as owed\n --amount <symbol>:<decimal> how much of one named token, e.g. USDCx:0.5.\n Repeatable, once per side. Prefer this — it does\n not depend on knowing the pool's token order\n --amount0 <decimal> token0 to add, or to withdraw, in human units\n --amount1 <decimal> token1 to add, or to withdraw\n --percent <n> --increase: n% of the private balance of both\n sides; --decrease: n% of the position's liquidity\n --network <testnet|mainnet> default testnet\n --execute actually submit\n --json machine-readable output\n\nList positions with \\`shield-swap positions\\`. A decrease books what it removes as\nowed to the position — run \\`shield-swap collect\\` to take it out.\n\n--amount0/--amount1 follow the pool's own token order; the line this script\nprints for the position names both symbols.`\n\n/**\n * Runs the `liquidity` subcommand.\n *\n * @param argv Arguments after the subcommand name, as the dispatcher supplies them.\n */\nexport async function main(argv: string[]): Promise<void> {\n const args = flags(\n {\n position: { type: 'string' },\n increase: { type: 'boolean' },\n decrease: { type: 'boolean' },\n amount: { type: 'string', multiple: true },\n amount0: { type: 'string' },\n amount1: { type: 'string' },\n percent: { type: 'string' },\n },\n USAGE,\n argv,\n )\n\n const bySymbol = (args.amount as string[] | undefined) ?? []\n const anyAmount = bySymbol.length > 0 || !!args.amount0 || !!args.amount1\n\n if (!args.position) fail(`--position is required.\\n\\n${USAGE}`)\n if (!!args.increase === !!args.decrease) fail(`pass exactly one of --increase or --decrease.\\n\\n${USAGE}`)\n if (!args.percent && !anyAmount) {\n fail(`--percent, --amount, --amount0, or --amount1 is required.\\n\\n${USAGE}`)\n }\n if (args.percent && anyAmount) {\n fail(`--percent and the amount flags are alternatives, not both.\\n\\n${USAGE}`)\n }\n\n const positionTokenId = args.position as string\n const percent = args.percent ? Number(args.percent) : undefined\n if (percent !== undefined && (!(percent > 0) || percent > 100)) {\n fail(`--percent must be greater than 0 and at most 100, got ${args.percent as string}`)\n }\n\n /** Basis points of a whole, so `--percent 12.5` is exact rather than rounded to 12. */\n const share = (total: bigint, pct: number) => (total * BigInt(Math.round(pct * 100))) / 10_000n\n\n /** This script's amount flags, placed into one pool's token order. */\n const amountsFor = (token0: TokenInfo, token1: TokenInfo) =>\n namedAmounts({\n entries: bySymbol,\n indexed: [args.amount0 as string | undefined, args.amount1 as string | undefined],\n tokens: [token0, token1],\n })\n\n await run(async () => {\n const { client, network } = await loadSession({ network: args.network as string | undefined })\n done(`session on ${network}`)\n\n step('reading the position from chain')\n const position = await client.getOwnedPosition({ positionTokenId })\n if (!position) {\n throw new Error(\n `this account holds no position record for ${positionTokenId} on ${network}. ` +\n 'List what it does hold with `shield-swap positions`.',\n )\n }\n if (position.frozen) {\n throw new Error(\n `position ${positionTokenId} is frozen: every liquidity operation on it reverts until an admin unfreezes it.`,\n )\n }\n // Pulled out of the position so the checked value is what the rest of the\n // script reads, rather than a property that has to be re-checked.\n const state = position.state\n if (!state) {\n throw new Error(\n `position ${positionTokenId} has no entry in the positions mapping. Either its mint has not ` +\n 'finalized yet — wait a few seconds and retry — or it was already burned and the record scanner ' +\n 'is still serving the spent record, which it can do for minutes. Neither can be operated on.',\n )\n }\n\n const tokens = await client.listTokens()\n const infoOf = (id: string) => tokens.find((token) => token.id === id)\n const token0 = infoOf(position.token0Id)\n const token1 = infoOf(position.token1Id)\n if (!token0 || !token1) throw new Error(`the registry does not describe both tokens of pool ${position.poolKey}.`)\n const pair = `${token0.symbol}/${token1.symbol}`\n done(`${pair} position over ticks ${position.tickLower}…${position.tickUpper}, liquidity ${state.liquidity}`)\n\n /**\n * Polls the positions mapping until the liquidity satisfies `predicate`.\n *\n * Mapping writes propagate to reads asynchronously, so the first read after a\n * confirmed transaction can still show the previous value.\n *\n * @param predicate What the settled liquidity must satisfy.\n * @param verb Completes \"liquidity did not … within 30s\" in the warning.\n * @returns The settled liquidity, or `undefined` when the read never caught up.\n */\n const waitForLiquidity = async (predicate: (liquidity: bigint) => boolean, verb: string) => {\n let settled: bigint | undefined\n const caught = await pollUntil(\n async () => {\n const onchain = await client.getPosition({ positionTokenId })\n if (onchain && predicate(onchain.liquidity)) settled = onchain.liquidity\n return settled !== undefined\n },\n 10,\n 3_000,\n )\n if (!caught) {\n warn(\n `the position's liquidity did not ${verb} within 30s of the transaction landing — the mapping ` +\n 'may still be catching up; check `shield-swap positions`',\n )\n }\n return settled\n }\n\n if (args.increase) {\n // Private records fund a deposit; the public balance cannot be added.\n const balances = await client.getBalances({ tokens: [token0.id, token1.id] })\n const held0 = balances[token0.id]?.private ?? 0n\n const held1 = balances[token1.id]?.private ?? 0n\n const { amount0: named0, amount1: named1 } = amountsFor(token0, token1)\n\n // Naming exactly one side makes it authoritative: the other is derived as the\n // minimum that must come with it. Offering the unnamed side's whole balance as\n // a ceiling instead would let a short balance quietly govern, adding a\n // fraction of the liquidity that was asked for without saying so.\n let budget0 = percent ? share(held0, percent) : (named0 ?? held0)\n let budget1 = percent ? share(held1, percent) : (named1 ?? held1)\n if (!percent && (named0 === undefined) !== (named1 === undefined)) {\n const side = named0 === undefined ? 1 : 0\n const named = named0 ?? named1!\n const slot = await client.getSlot({ poolKey: position.poolKey })\n if (!slot) throw new Error(`pool ${position.poolKey} has no slot on chain`)\n const range = {\n sqrtPriceX128: slot.sqrt_price,\n sqrtLowerX128: getSqrtPriceAtTickX128(position.tickLower),\n sqrtUpperX128: getSqrtPriceAtTickX128(position.tickUpper),\n }\n const liquidity = liquidityForAmount({ ...range, side, amount: named })\n if (liquidity === 0n) {\n // Either the amount is dust over this width, or the price has left the\n // side that was named — a distinction worth making, since one is fixed by\n // depositing more and the other by naming the other token.\n const other = side === 0 ? token1 : token0\n const unused = side === 0 ? slot.tick >= position.tickUpper : slot.tick < position.tickLower\n throw new Error(\n unused\n ? `at tick ${slot.tick} this position holds only ${other.symbol}, so ` +\n `${side === 0 ? token0.symbol : token1.symbol} cannot fund it — name --amount${other === token1 ? '1' : '0'} instead.`\n : `${formatAmount(named, side === 0 ? token0.decimals : token1.decimals, side === 0 ? token0.symbol : token1.symbol)} ` +\n `adds no liquidity over ticks ${position.tickLower}…${position.tickUpper} — commit more.`,\n )\n }\n // Deposit-side rounding, so neither derived amount rounds below what the\n // finalize will require.\n const required = amountsForLiquidity({ ...range, liquidity, roundUp: true })\n budget0 = required.amount0\n budget1 = required.amount1\n const derived = side === 0 ? token1 : token0\n const amount = side === 0 ? required.amount1 : required.amount0\n done(`${derived.symbol} derived: ${formatAmount(amount, derived.decimals, derived.symbol)} needed alongside`)\n }\n\n // Priced over the position's own bounds, which are already spacing-aligned,\n // so the preview reports purely what the deposit buys and what it consumes.\n step('pricing the addition against the pool’s live price')\n const preview = await client.previewMint({\n poolKey: position.poolKey,\n amount0Desired: budget0,\n amount1Desired: budget1,\n tickLower: position.tickLower,\n tickUpper: position.tickUpper,\n })\n if (preview.liquidity === 0n) {\n throw new Error(\n `that budget adds no liquidity over ticks ${position.tickLower}…${position.tickUpper} — commit ` +\n 'more. An increase would cost a fee and add nothing.',\n )\n }\n for (const side of [\n { info: token0, needed: preview.amount0, held: held0 },\n { info: token1, needed: preview.amount1, held: held1 },\n ]) {\n // One record funds each side, not the sum of several, so a balance large\n // enough in total can still be too fragmented to spend.\n if (side.needed > side.held) {\n throw new Error(\n `the addition needs ${formatAmount(side.needed, side.info.decimals, side.info.symbol)} but only ` +\n `${formatAmount(side.held, side.info.decimals, side.info.symbol)} is held privately.`,\n )\n }\n }\n\n const planLines: Array<readonly [string, string]> = [\n ['position', positionTokenId],\n ['pool', `${pair} ticks ${position.tickLower}…${position.tickUpper}`],\n ['add', formatAmount(preview.amount0, token0.decimals, token0.symbol)],\n // Empty label: the second side of the same deposit, not a separate step.\n ['', formatAmount(preview.amount1, token1.decimals, token1.symbol)],\n ['liquidity', `${state.liquidity} → about ${state.liquidity + preview.liquidity}`],\n ]\n if (!confirmed({ execute: args.execute as boolean | undefined, network, plan: planLines })) {\n output({ network, submitted: false, action: 'increase', positionTokenId, preview }, () => {})\n return\n }\n\n // Both token programs' sources: the prover cannot discover the dynamically\n // dispatched IARC20 callees on its own.\n const imports = await client.resolveDexImports({\n tokenPrograms: [token0.ammTokenProgram, token1.ammTokenProgram].filter(\n (program): program is string => !!program,\n ),\n })\n step('proving and submitting the increase — this takes a minute or two')\n const result = await client.increaseLiquidity({\n positionTokenId,\n poolKey: position.poolKey,\n amount0Desired: preview.amount0,\n amount1Desired: preview.amount1,\n imports,\n })\n done(`increase landed: tx ${result.transactionId}`)\n\n const settled = await waitForLiquidity((liquidity) => liquidity > state.liquidity, 'grow')\n output(\n {\n network,\n submitted: true,\n action: 'increase',\n positionTokenId,\n transactionId: result.transactionId,\n added0: preview.amount0,\n added1: preview.amount1,\n liquidityBefore: state.liquidity,\n liquidityAfter: settled ?? null,\n },\n (data) => {\n console.log(\n `\\nAdded ${formatAmount(data.added0, token0.decimals, token0.symbol)} and ` +\n `${formatAmount(data.added1, token1.decimals, token1.symbol)} to position ${data.positionTokenId}.`,\n )\n console.log(`Liquidity ${data.liquidityBefore} → ${data.liquidityAfter ?? 'still settling'}.`)\n },\n )\n return\n }\n\n // --decrease from here down.\n if (state.liquidity === 0n) {\n throw new Error(\n `position ${positionTokenId} holds no liquidity to remove. Collect what it is owed with ` +\n '`shield-swap collect --position <id> --close`.',\n )\n }\n const slot = await client.getSlot({ poolKey: position.poolKey })\n if (!slot) throw new Error(`pool ${position.poolKey} has no slot state, so it cannot be operated on.`)\n const sqrtLower = getSqrtPriceAtTickX128(position.tickLower)\n const sqrtUpper = getSqrtPriceAtTickX128(position.tickUpper)\n\n let liquidityToRemove: bigint\n if (percent) {\n // 100% removes exactly what the position holds rather than a rounded share:\n // a base unit left behind blocks the burn.\n liquidityToRemove = percent === 100 ? state.liquidity : share(state.liquidity, percent)\n } else {\n // The contract takes liquidity, not amounts, so a named amount is converted\n // through the same math a deposit uses. An unnamed side offers everything the\n // position backs — a zero there would floor the conversion to nothing.\n const named = amountsFor(token0, token1)\n const want0 = named.amount0 ?? null\n const want1 = named.amount1 ?? null\n for (const side of [\n { want: want0, backing: state.amount0, info: token0 },\n { want: want1, backing: state.amount1, info: token1 },\n ]) {\n // Asking for more than the range holds is a misunderstanding rather than a\n // rounding matter, and the cap below would quietly turn it into \"all of it\".\n if (side.want !== null && side.want > side.backing) {\n throw new Error(\n `asked to withdraw ${formatAmount(side.want, side.info.decimals, side.info.symbol)} but the ` +\n `position backs ${formatAmount(side.backing, side.info.decimals, side.info.symbol)} at the ` +\n \"pool's current price.\",\n )\n }\n }\n const requested = liquidityForAmounts({\n sqrtPriceX128: slot.sqrt_price,\n sqrtLowerX128: sqrtLower,\n sqrtUpperX128: sqrtUpper,\n amount0: want0 ?? state.amount0,\n amount1: want1 ?? state.amount1,\n })\n // Capped rather than rejected: the conversion can ask for a unit more than\n // the position holds, and removing all of it is the intent either way.\n liquidityToRemove = requested > state.liquidity ? state.liquidity : requested\n }\n if (liquidityToRemove === 0n) {\n throw new Error(\n 'that amount converts to zero liquidity for this range — ask for more, or use --percent to remove ' +\n 'a share of the position instead.',\n )\n }\n\n // Withdrawal-side rounding (`false`): what the contract books as owed, not what\n // a deposit of the same size would cost.\n const booked = amountsForLiquidity({\n sqrtPriceX128: slot.sqrt_price,\n sqrtLowerX128: sqrtLower,\n sqrtUpperX128: sqrtUpper,\n liquidity: liquidityToRemove,\n roundUp: false,\n })\n\n const planLines: Array<readonly [string, string]> = [\n ['position', positionTokenId],\n ['pool', `${pair} ticks ${position.tickLower}…${position.tickUpper}`],\n ['remove', `${liquidityToRemove} of ${state.liquidity} liquidity`],\n ['books', `about ${formatAmount(booked.amount0, token0.decimals, token0.symbol)}`],\n // Empty label: the second side of the same booking.\n ['', `about ${formatAmount(booked.amount1, token1.decimals, token1.symbol)}`],\n ['payout', 'none — this books the amounts as owed; `shield-swap collect` pays them out'],\n ]\n if (!confirmed({ execute: args.execute as boolean | undefined, network, plan: planLines })) {\n output(\n {\n network,\n submitted: false,\n action: 'decrease',\n positionTokenId,\n liquidityToRemove,\n booked0: booked.amount0,\n booked1: booked.amount1,\n },\n () => {},\n )\n return\n }\n\n // No imports: a decrease moves no tokens, so there is no dynamically dispatched\n // IARC20 call for the prover to resolve.\n step('proving and submitting the decrease — this takes a minute or two')\n const result = await client.decreaseLiquidity({\n positionTokenId,\n poolKey: position.poolKey,\n liquidityToRemove,\n })\n done(`decrease landed: tx ${result.transactionId}`)\n\n const settled = await waitForLiquidity((liquidity) => liquidity < state.liquidity, 'shrink')\n const owed = await client.getPosition({ positionTokenId })\n output(\n {\n network,\n submitted: true,\n action: 'decrease',\n positionTokenId,\n transactionId: result.transactionId,\n liquidityRemoved: liquidityToRemove,\n liquidityBefore: state.liquidity,\n liquidityAfter: settled ?? null,\n owed0: owed?.tokens_owed0 ?? null,\n owed1: owed?.tokens_owed1 ?? null,\n },\n (data) => {\n console.log(`\\nRemoved ${data.liquidityRemoved} liquidity from position ${data.positionTokenId}.`)\n console.log(`Liquidity ${data.liquidityBefore} → ${data.liquidityAfter ?? 'still settling'}.`)\n if (data.owed0 !== null && data.owed1 !== null) {\n console.log(\n `Owed to the position: ${formatAmount(data.owed0, token0.decimals, token0.symbol)} and ` +\n `${formatAmount(data.owed1, token1.decimals, token1.symbol)}.`,\n )\n }\n console.log('Take it out with `shield-swap collect --position <id>`.')\n },\n )\n })\n}\n"],"mappings":"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","names":["settled","slot","planLines","result"]}