@provablehq/shield-swap-cli 0.7.1 → 0.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js
CHANGED
|
@@ -36,7 +36,7 @@ var COMMANDS = {
|
|
|
36
36
|
},
|
|
37
37
|
history: {
|
|
38
38
|
summary: "Swap history and status of swaps.",
|
|
39
|
-
load: () => import("./swap-history-
|
|
39
|
+
load: () => import("./swap-history-43E4JZUO.js")
|
|
40
40
|
},
|
|
41
41
|
mint: {
|
|
42
42
|
summary: "Open a liquidity position over a tick range.",
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/commands/swap-history.ts"],"sourcesContent":["/**\n * Swap status — what is owed, what settled, and claiming what is still waiting.\n *\n * A private swap takes two transactions: the request, then a claim that collects\n * the output. Between them the proceeds sit in `swap_outputs` under a blinded\n * identity only this account can prove ownership of, and the handle needed to\n * claim them lives in the identity store the session configures.\n *\n * This is the sweep. It reads the chain rather than the store's own statuses, so\n * an entry appears exactly when a claim would succeed.\n *\n * --reconcile walk `claim_swap_output` / `claim_swap_output_no_refund` history\n * to recover a store that lost track of a swap. Expensive; run it\n * after losing a store, not routinely.\n * --claim claim what is owed (requires --execute).\n *\n * Usage:\n * shield-swap history # what is owed\n * shield-swap history --claim --execute # claim everything claimable\n * shield-swap history --claim --swap-id <id> --execute # claim one\n * shield-swap history --reconcile # rebuild from chain history\n * shield-swap history --json\n */\nimport {\n SwapOutputNotFinalizedError,\n deriveBlindedAddress,\n deriveBlindingFactor,\n viewKeyToScalar,\n} from '@provablehq/shield-swap-sdk'\nimport type { BlindedIdentityRecord, BlindedIdentityStore } from '@provablehq/shield-swap-sdk'\nimport { loadSession, formatAmount } from '../session.js'\nimport { flags, step, done, warn, output, confirmed, run, table } from '../shared.js'\nimport { dim, green, yellow } from '../color.js'\n\nconst USAGE = `shield-swap history — unclaimed swap outputs, reconciliation, and claiming\n\n --network <testnet|mainnet> default testnet\n --claim claim everything claimable\n --swap-id <id> with --claim, claim just this swap\n --reconcile force a full re-search even when the local history\n looks complete (discovery runs either way)\n --no-search never walk history, however incomplete it looks\n --window <n> identities to probe past the last known swap id,\n default 16\n --pages <n> bound the history walk; default is the whole\n history, which ends when the history does\n --execute actually submit claims\n --json machine-readable output`\n\n/**\n * Populates the store with identities this account has already consumed.\n *\n * A blinded identity is derived, not recorded: nothing on chain lists an\n * account's identities, and the account cannot enumerate its own. So a store that\n * starts empty — a first run, or a lost file — knows nothing, and\n * `reconcileSwapHistory` has no addresses to match history against.\n *\n * The only way back is to re-derive. Counters are sequential from 0, so this\n * walks forward from the store's tip deriving each address and asking\n * `used_blinded_addresses` whether this account has spent it. A window of hits\n * extends the search, because gaps are normal — a reverted or dropped swap burns\n * a counter without consuming its address.\n *\n * Recorded as `swapped` with no swap id, which is what they are: consumed on\n * chain, with their proceeds unlocatable until `reconcileSwapHistory` finds the\n * claim that names them.\n *\n * @param client A composed client with a local account.\n * @param viewKey The account's view key, for derivation.\n * @param signer The account address the identities are scoped to.\n * @param store The store to populate.\n * @param window Counters to probe past the last hit. Default 16.\n * @returns The identities discovered, in counter order.\n */\nexport async function discoverIdentities(\n client: Awaited<ReturnType<typeof loadSession>>['client'],\n viewKey: string,\n signer: string,\n store: BlindedIdentityStore,\n window = 16,\n): Promise<BlindedIdentityRecord[]> {\n const existing = await store.load()\n const known = new Set(existing.map((record) => record.counter))\n const viewKeyScalar = await viewKeyToScalar(viewKey)\n const tip = existing.length ? Math.max(...existing.map((record) => record.counter)) : -1\n\n const found: BlindedIdentityRecord[] = []\n let counter = tip + 1\n let sinceHit = 0\n // Bounded so a wrong view key or program cannot walk forever.\n const CEILING = 4096\n\n while (sinceHit < window && counter < CEILING) {\n if (known.has(counter)) {\n counter++\n continue\n }\n const blindingFactor = await deriveBlindingFactor(viewKeyScalar, counter)\n const blindedAddress = await deriveBlindedAddress(blindingFactor, signer)\n if (await client.isBlindedAddressUsed({ address: blindedAddress })) {\n step(`counter ${counter} was used by this account`)\n found.push({ counter, blindingFactor, blindedAddress, status: 'swapped' })\n sinceHit = 0\n } else {\n sinceHit++\n }\n counter++\n }\n\n if (found.length) await store.save([...existing, ...found])\n return found\n}\n\n/**\n * Runs the `history` 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 claim: { type: 'boolean' },\n 'swap-id': { type: 'string' },\n reconcile: { type: 'boolean' },\n 'no-search': { type: 'boolean' },\n pages: { type: 'string' },\n window: { type: 'string' },\n },\n USAGE,\n argv,\n )\n // Boolean rather than an optional value: `--claim --execute` is ambiguous to\n // parseArgs, which reads the next flag as the value.\n const claimOne = typeof args['swap-id'] === 'string' ? (args['swap-id'] as string) : undefined\n const wantsClaim = !!args.claim || !!claimOne\n\n await run(async () => {\n const { client, account, network, blindedIdentities } = await loadSession({\n network: args.network as string | undefined,\n })\n if (!account.viewKey) throw new Error('this script needs a local account — a wallet tracks its own identities')\n done(`session on ${network}`)\n\n // Whether the advice below can honestly say \"look further back\".\n let walkedEverything = false\n\n // Discovery is cheap and always worth doing: it is a handful of derivations and\n // mapping reads, and without it a new or lost store has nothing to reconcile.\n {\n const window = args.window ? Number(args.window) : 16\n step(`probing for used identities, ${window} past the last known swap id`)\n const discovered = await discoverIdentities(\n client,\n account.viewKey!,\n account.address,\n blindedIdentities,\n window,\n )\n done(\n discovered.length\n ? `discovered ${discovered.length} identity(ies) this account has used`\n : 'no unrecorded identities found',\n )\n }\n\n // The walk is the expensive part, so it runs only when the local history is\n // actually missing something. A record marked `claimSearched` has already been\n // looked for across the whole history and was not there — searching again would\n // cost the same and find the same nothing.\n const stored = await blindedIdentities.load()\n const missing = stored.filter(\n (record) => !record.swapId && record.status !== 'reserved' && !record.claimSearched,\n )\n if (args['no-search']) {\n if (missing.length) warn(`${missing.length} identity(ies) lack a swap id; --no-search skipped the lookup`)\n } else if (missing.length || args.reconcile) {\n step(\n missing.length\n ? `${missing.length} identity(ies) have no swap id — searching claim history`\n : 're-searching claim history because --reconcile was passed',\n )\n step(\n args.pages\n ? `walking up to ${args.pages} pages of claim history`\n : 'walking the whole claim history — it ends when the history does',\n )\n const result = await client.reconcileSwapHistory(args.pages ? { maxPages: Number(args.pages) } : {})\n walkedEverything = result.complete\n done(\n `scanned ${result.callsScanned} calls over ${result.pagesScanned} page(s); ` +\n `recovered ${result.claims.length} claim(s) and ${result.requests.length} request(s)`,\n )\n const claimable = result.requests.filter((request) => request.handle).length\n if (claimable) {\n done(`${claimable} abandoned swap(s) rebuilt with a claimable handle — see --claim`)\n }\n if (!result.complete) {\n warn('the walk stopped before the history ended — raise or drop --pages to finish it')\n }\n } else {\n // Nothing to look for: every consumed identity either has its swap id or has\n // already been searched for across the whole history.\n walkedEverything = true\n done('local history is complete — no need to search chain')\n }\n\n // Counted here rather than at startup: --reconcile populates the store, and a\n // count taken before that would report \"nothing tracked\" in the same run that\n // reports what it found.\n const records = await blindedIdentities.load()\n const tracked = records.length\n step(`reading swap_outputs for ${tracked} tracked identity(ies)`)\n const owed = await client.getUnclaimedSwaps()\n const tokens = await client.listTokens()\n const infoOf = (id: string) => tokens.find((token) => token.id === id)\n\n const rows = owed.swaps.map((swap) => {\n const out = infoOf(swap.output.token_out)\n const back = infoOf(swap.output.token_in)\n return {\n swapId: swap.swapId,\n blindedAddress: swap.blindedAddress,\n claimable: swap.claimable,\n tokenOut: out?.symbol ?? swap.output.token_out,\n amountOut: swap.output.amount_out,\n decimalsOut: out?.decimals ?? 0,\n tokenIn: back?.symbol ?? swap.output.token_in,\n amountRemaining: swap.output.amount_remaining,\n decimalsIn: back?.decimals ?? 0,\n }\n })\n\n const target = claimOne ? rows.filter((row) => row.swapId === claimOne) : rows\n if (claimOne && !target.length) {\n throw new Error(`swap ${claimOne} is not owed anything — it may already be claimed.`)\n }\n\n const claimed: Array<{ swapId: string; transactionId: string; amountOut: string }> = []\n if (wantsClaim) {\n const claimable = target.filter((row) => row.claimable)\n if (!claimable.length) {\n warn('nothing claimable: no stored handle for the owed swaps (try --reconcile)')\n } else if (\n confirmed({\n execute: args.execute as boolean | undefined,\n network,\n plan: claimable.map(\n (row) =>\n [\n `claim ${formatAmount(row.amountOut, row.decimalsOut, row.tokenOut)}`,\n `from swap ${row.swapId.slice(0, 16)}…`,\n ] as const,\n ),\n })\n ) {\n for (const row of claimable) {\n const swap = owed.swaps.find((entry) => entry.swapId === row.swapId)!\n const pIn = infoOf(swap.output.token_in)?.ammTokenProgram\n const pOut = infoOf(swap.output.token_out)?.ammTokenProgram\n if (!pIn || !pOut) {\n warn(`skipping ${row.swapId}: no wrapper program for one of its tokens`)\n continue\n }\n const imports = await client.resolveDexImports({ tokenPrograms: [pIn, pOut] })\n\n // The output becomes claimable a few blocks after the swap confirms, so\n // an early attempt is expected to fail rather than exceptional.\n for (let attempt = 0; attempt < 10; attempt++) {\n try {\n step(`claiming ${row.swapId.slice(0, 16)}… (attempt ${attempt + 1})`)\n const result = await client.claimSwapOutput({ handle: swap.handle!, imports })\n done(\n `claimed ${formatAmount(result.amountOut, row.decimalsOut, row.tokenOut)} (tx ${result.transactionId})`,\n )\n claimed.push({\n swapId: row.swapId,\n transactionId: result.transactionId,\n amountOut: result.amountOut.toString(),\n })\n break\n } catch (error) {\n if (!(error instanceof SwapOutputNotFinalizedError)) throw error\n step('not finalized yet — waiting 15s')\n await new Promise((resolve) => setTimeout(resolve, 15_000))\n }\n }\n }\n }\n }\n\n // The history is the point of the script, so it prints whatever else happened —\n // a failed claim or an exhausted page budget still leaves a picture worth\n // seeing, and a caller hunting for funds needs the whole ledger, not a summary.\n const symbolOf = (tokenId: string) => infoOf(tokenId)?.symbol ?? `${tokenId.slice(0, 8)}…`\n const decimalsOf = (tokenId: string) => infoOf(tokenId)?.decimals ?? 0\n\n const history = [...records]\n .sort((a, b) => a.counter - b.counter)\n .map((record) => {\n // The handle knows what was sold; the claim knows what came back. Either can\n // be absent — a recovered identity has neither — so both are nullable rather\n // than defaulted to zero, which would read as \"sold nothing\".\n const handle = record.handle\n const claim = record.claim\n const tokenIn = claim?.tokenIn ?? handle?.tokenInId ?? null\n const tokenOut = claim?.tokenOut ?? handle?.tokenOutId ?? null\n return {\n counter: record.counter,\n status: record.status,\n swapId: record.swapId ?? null,\n pair: tokenIn && tokenOut ? `${symbolOf(tokenIn)}→${symbolOf(tokenOut)}` : null,\n // The handle when it survived, else the request's public `amount_in`,\n // which the history walk recovers for a store that lost its handles.\n sold:\n handle || (record.soldAmountIn && tokenIn)\n ? {\n amount: BigInt(handle?.amountIn ?? record.soldAmountIn!),\n decimals: decimalsOf(handle?.tokenInId ?? tokenIn!),\n symbol: symbolOf(handle?.tokenInId ?? tokenIn!),\n }\n : null,\n received: claim ? { amount: BigInt(claim.amountOut), decimals: decimalsOf(claim.tokenOut), symbol: symbolOf(claim.tokenOut) } : null,\n refunded:\n claim && BigInt(claim.amountRemaining) > 0n\n ? { amount: BigInt(claim.amountRemaining), decimals: decimalsOf(claim.tokenIn), symbol: symbolOf(claim.tokenIn) }\n : null,\n block: claim?.blockNumber ?? null,\n hasHandle: !!handle,\n claimSearched: !!record.claimSearched,\n blindedAddress: record.blindedAddress,\n }\n })\n\n // Collated from the persisted claims rather than a fresh walk: the claim\n // deleted its `swap_outputs` entry, so what a swap moved is only knowable from\n // the record reconcile wrote.\n const settled = records.filter((record) => record.claim)\n const received: Record<string, bigint> = {}\n const refunded: Record<string, bigint> = {}\n const pairs: Record<string, number> = {}\n for (const record of settled) {\n const claim = record.claim!\n received[claim.tokenOut] = (received[claim.tokenOut] ?? 0n) + BigInt(claim.amountOut)\n if (BigInt(claim.amountRemaining) > 0n) {\n refunded[claim.tokenIn] = (refunded[claim.tokenIn] ?? 0n) + BigInt(claim.amountRemaining)\n }\n const inSymbol = infoOf(claim.tokenIn)?.symbol ?? claim.tokenIn.slice(0, 10)\n const outSymbol = infoOf(claim.tokenOut)?.symbol ?? claim.tokenOut.slice(0, 10)\n const pair = `${inSymbol}→${outSymbol}`\n pairs[pair] = (pairs[pair] ?? 0) + 1\n }\n\n output(\n {\n network,\n tracked,\n walkedEverything,\n summary: {\n settled: settled.length,\n unrecorded: records.filter((record) => !record.claim && record.status !== 'reserved').length,\n pairs,\n received,\n refunded,\n },\n history,\n owed: rows,\n totals: owed.totals,\n unresolvable: owed.unresolvable.length,\n claimed,\n },\n (data) => {\n if (data.history.length) {\n console.log(`\\nswaps so far on ${data.network}:\\n`)\n const header = ['#', 'pair', 'sold', 'received', 'block', 'status', 'note']\n const rows = data.history.map((entry) => [\n String(entry.counter),\n entry.pair ?? '—',\n entry.sold ? formatAmount(entry.sold.amount, entry.sold.decimals, entry.sold.symbol) : '—',\n entry.received\n ? formatAmount(entry.received.amount, entry.received.decimals, entry.received.symbol) +\n (entry.refunded\n ? ` (+${formatAmount(entry.refunded.amount, entry.refunded.decimals, entry.refunded.symbol)} back)`\n : '')\n : '—',\n entry.block === null ? '—' : String(entry.block),\n // Named for what the row means to a reader, not for the store's\n // lifecycle word. `swapped` is the state where money settled and is\n // sitting unclaimed, which is the only row that wants acting on.\n // `reserved` is NOT pending a claim: nothing was ever spent on it, so\n // calling it that would assert funds are waiting when none are.\n entry.status === 'claimed'\n ? green('claimed')\n : entry.status === 'swapped'\n ? yellow('pending claim')\n : dim(entry.status),\n // The handle is what makes an unclaimed swap claimable, so its absence\n // belongs beside the row rather than in a footnote.\n entry.status === 'swapped' && !entry.hasHandle\n ? entry.claimSearched\n ? yellow('never claimed')\n : dim('no handle')\n : '',\n ])\n // The shared renderer, which measures columns without their styling —\n // padding the raw string would indent everything right of a coloured\n // status cell by the width of its escape codes.\n table(header, rows, ['right', 'left', 'right', 'right', 'right', 'left', 'left'])\n }\n if (!data.owed.length) {\n if (data.tracked === 0) {\n console.log(\n '\\nThis store tracks no identities yet, so there is nothing to look for. A swap made ' +\n 'through these scripts records itself; for an account with history, ' +\n '`--reconcile` rebuilds the store from chain.',\n )\n } else if (data.unresolvable) {\n // Not \"all settled\": these were used but cannot be looked up, so whether\n // they hold proceeds is unknown rather than answered.\n console.log(\n `\\nNothing claimable across ${data.tracked} tracked identity(ies), but ` +\n `${data.unresolvable} of them cannot be checked — see below.`,\n )\n } else {\n console.log(`\\nNothing owed across ${data.tracked} tracked identity(ies) — all settled.`)\n }\n } else {\n console.log(`\\n${data.owed.length} unclaimed swap(s) on ${data.network}:\\n`)\n for (const row of data.owed) {\n const mark = row.claimable ? ' ' : '×'\n console.log(\n `${mark} ${formatAmount(row.amountOut, row.decimalsOut, row.tokenOut).padStart(24)}` +\n (row.amountRemaining > 0n\n ? ` + ${formatAmount(row.amountRemaining, row.decimalsIn, row.tokenIn)} refund`\n : ''),\n )\n console.log(` swap ${row.swapId}`)\n }\n const blocked = data.owed.filter((row) => !row.claimable).length\n if (blocked) {\n console.log(`\\n× ${blocked} owed but not claimable here: no stored handle. Try --reconcile.`)\n }\n }\n if (data.unresolvable) {\n warn(\n `${data.unresolvable} identity(ies) were used by this account but have no swap id on file, so ` +\n 'their swap cannot be looked up: it is unknown whether those swaps were already claimed or ' +\n 'still hold proceeds.',\n )\n if (data.walkedEverything) {\n // The whole history was searched and no claim names them, so they were\n // never claimed. Their proceeds may still be sitting in `swap_outputs`,\n // and a claim needs the whole handle — which chain history does not carry.\n warn(\n 'The entire claim history was searched and none of them appear in it, so those swaps were ' +\n 'never claimed. Their output may still be waiting on chain, but it cannot be claimed ' +\n 'without the handle, which only the process that made the swap held.',\n )\n } else {\n warn(\n 'Only part of the history was searched. Run `--reconcile` without --pages to walk all of it ' +\n 'before concluding anything about these.',\n )\n }\n }\n if (!wantsClaim && data.owed.some((row) => row.claimable)) {\n console.log('\\nRun with --claim --execute to collect.')\n }\n\n const { summary } = data\n console.log(`\\nswaps settled: ${summary.settled}`)\n if (summary.settled) {\n for (const [pair, count] of Object.entries(summary.pairs).sort((a, b) => b[1] - a[1])) {\n console.log(` ${String(count).padStart(4)} × ${pair}`)\n }\n console.log('\\nreceived in total:')\n for (const [tokenId, amount] of Object.entries(summary.received)) {\n const info = infoOf(tokenId)\n console.log(` ${formatAmount(amount, info?.decimals ?? 0, info?.symbol ?? tokenId.slice(0, 10))}`)\n }\n for (const [tokenId, amount] of Object.entries(summary.refunded)) {\n const info = infoOf(tokenId)\n console.log(\n ` ${formatAmount(amount, info?.decimals ?? 0, info?.symbol ?? tokenId.slice(0, 10))} refunded unfilled`,\n )\n }\n }\n if (summary.unrecorded) {\n // Totals cover the swaps whose claim was found. Saying so keeps the figures\n // from reading as a complete account of the account's trading.\n console.log(\n `\\nThese totals cover ${summary.settled} settled swap(s). ${summary.unrecorded} more were used ` +\n 'on chain without a recorded claim, so their amounts are not included.',\n )\n }\n },\n )\n })\n}\n"],"mappings":"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","names":["rows"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@provablehq/shield-swap-cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.8.0",
|
|
4
4
|
"description": "Command line trader for the Shield Swap AMM DEX on Aleo.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -29,8 +29,8 @@
|
|
|
29
29
|
"access": "public"
|
|
30
30
|
},
|
|
31
31
|
"dependencies": {
|
|
32
|
-
"@provablehq/
|
|
33
|
-
"@provablehq/
|
|
32
|
+
"@provablehq/veil-aleo-sdk": "^0.8.0",
|
|
33
|
+
"@provablehq/shield-swap-sdk": "^0.8.0"
|
|
34
34
|
},
|
|
35
35
|
"scripts": {
|
|
36
36
|
"build": "tsup",
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/commands/swap-history.ts"],"sourcesContent":["/**\n * Swap status — what is owed, what settled, and claiming what is still waiting.\n *\n * A private swap takes two transactions: the request, then a claim that collects\n * the output. Between them the proceeds sit in `swap_outputs` under a blinded\n * identity only this account can prove ownership of, and the handle needed to\n * claim them lives in the identity store the session configures.\n *\n * This is the sweep. It reads the chain rather than the store's own statuses, so\n * an entry appears exactly when a claim would succeed.\n *\n * --reconcile walk `claim_swap_output` history to recover a store that lost\n * track of a swap. Expensive; run it after losing a store, not\n * routinely.\n * --claim claim what is owed (requires --execute).\n *\n * Usage:\n * shield-swap history # what is owed\n * shield-swap history --claim --execute # claim everything claimable\n * shield-swap history --claim --swap-id <id> --execute # claim one\n * shield-swap history --reconcile # rebuild from chain history\n * shield-swap history --json\n */\nimport {\n SwapOutputNotFinalizedError,\n deriveBlindedAddress,\n deriveBlindingFactor,\n viewKeyToScalar,\n} from '@provablehq/shield-swap-sdk'\nimport type { BlindedIdentityRecord, BlindedIdentityStore } from '@provablehq/shield-swap-sdk'\nimport { loadSession, formatAmount } from '../session.js'\nimport { flags, step, done, warn, output, confirmed, run, table } from '../shared.js'\nimport { dim, green, yellow } from '../color.js'\n\nconst USAGE = `shield-swap history — unclaimed swap outputs, reconciliation, and claiming\n\n --network <testnet|mainnet> default testnet\n --claim claim everything claimable\n --swap-id <id> with --claim, claim just this swap\n --reconcile force a full re-search even when the local history\n looks complete (discovery runs either way)\n --no-search never walk history, however incomplete it looks\n --window <n> identities to probe past the last known swap id,\n default 16\n --pages <n> bound the history walk; default is the whole\n history, which ends when the history does\n --execute actually submit claims\n --json machine-readable output`\n\n/**\n * Populates the store with identities this account has already consumed.\n *\n * A blinded identity is derived, not recorded: nothing on chain lists an\n * account's identities, and the account cannot enumerate its own. So a store that\n * starts empty — a first run, or a lost file — knows nothing, and\n * `reconcileSwapHistory` has no addresses to match history against.\n *\n * The only way back is to re-derive. Counters are sequential from 0, so this\n * walks forward from the store's tip deriving each address and asking\n * `used_blinded_addresses` whether this account has spent it. A window of hits\n * extends the search, because gaps are normal — a reverted or dropped swap burns\n * a counter without consuming its address.\n *\n * Recorded as `swapped` with no swap id, which is what they are: consumed on\n * chain, with their proceeds unlocatable until `reconcileSwapHistory` finds the\n * claim that names them.\n *\n * @param client A composed client with a local account.\n * @param viewKey The account's view key, for derivation.\n * @param signer The account address the identities are scoped to.\n * @param store The store to populate.\n * @param window Counters to probe past the last hit. Default 16.\n * @returns The identities discovered, in counter order.\n */\nexport async function discoverIdentities(\n client: Awaited<ReturnType<typeof loadSession>>['client'],\n viewKey: string,\n signer: string,\n store: BlindedIdentityStore,\n window = 16,\n): Promise<BlindedIdentityRecord[]> {\n const existing = await store.load()\n const known = new Set(existing.map((record) => record.counter))\n const viewKeyScalar = await viewKeyToScalar(viewKey)\n const tip = existing.length ? Math.max(...existing.map((record) => record.counter)) : -1\n\n const found: BlindedIdentityRecord[] = []\n let counter = tip + 1\n let sinceHit = 0\n // Bounded so a wrong view key or program cannot walk forever.\n const CEILING = 4096\n\n while (sinceHit < window && counter < CEILING) {\n if (known.has(counter)) {\n counter++\n continue\n }\n const blindingFactor = await deriveBlindingFactor(viewKeyScalar, counter)\n const blindedAddress = await deriveBlindedAddress(blindingFactor, signer)\n if (await client.isBlindedAddressUsed({ address: blindedAddress })) {\n step(`counter ${counter} was used by this account`)\n found.push({ counter, blindingFactor, blindedAddress, status: 'swapped' })\n sinceHit = 0\n } else {\n sinceHit++\n }\n counter++\n }\n\n if (found.length) await store.save([...existing, ...found])\n return found\n}\n\n/**\n * Runs the `history` 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 claim: { type: 'boolean' },\n 'swap-id': { type: 'string' },\n reconcile: { type: 'boolean' },\n 'no-search': { type: 'boolean' },\n pages: { type: 'string' },\n window: { type: 'string' },\n },\n USAGE,\n argv,\n )\n // Boolean rather than an optional value: `--claim --execute` is ambiguous to\n // parseArgs, which reads the next flag as the value.\n const claimOne = typeof args['swap-id'] === 'string' ? (args['swap-id'] as string) : undefined\n const wantsClaim = !!args.claim || !!claimOne\n\n await run(async () => {\n const { client, account, network, blindedIdentities } = await loadSession({\n network: args.network as string | undefined,\n })\n if (!account.viewKey) throw new Error('this script needs a local account — a wallet tracks its own identities')\n done(`session on ${network}`)\n\n // Whether the advice below can honestly say \"look further back\".\n let walkedEverything = false\n\n // Discovery is cheap and always worth doing: it is a handful of derivations and\n // mapping reads, and without it a new or lost store has nothing to reconcile.\n {\n const window = args.window ? Number(args.window) : 16\n step(`probing for used identities, ${window} past the last known swap id`)\n const discovered = await discoverIdentities(\n client,\n account.viewKey!,\n account.address,\n blindedIdentities,\n window,\n )\n done(\n discovered.length\n ? `discovered ${discovered.length} identity(ies) this account has used`\n : 'no unrecorded identities found',\n )\n }\n\n // The walk is the expensive part, so it runs only when the local history is\n // actually missing something. A record marked `claimSearched` has already been\n // looked for across the whole history and was not there — searching again would\n // cost the same and find the same nothing.\n const stored = await blindedIdentities.load()\n const missing = stored.filter(\n (record) => !record.swapId && record.status !== 'reserved' && !record.claimSearched,\n )\n if (args['no-search']) {\n if (missing.length) warn(`${missing.length} identity(ies) lack a swap id; --no-search skipped the lookup`)\n } else if (missing.length || args.reconcile) {\n step(\n missing.length\n ? `${missing.length} identity(ies) have no swap id — searching claim history`\n : 're-searching claim history because --reconcile was passed',\n )\n step(\n args.pages\n ? `walking up to ${args.pages} pages of claim history`\n : 'walking the whole claim history — it ends when the history does',\n )\n const result = await client.reconcileSwapHistory(args.pages ? { maxPages: Number(args.pages) } : {})\n walkedEverything = result.complete\n done(\n `scanned ${result.callsScanned} calls over ${result.pagesScanned} page(s); ` +\n `recovered ${result.claims.length} claim(s) and ${result.requests.length} request(s)`,\n )\n const claimable = result.requests.filter((request) => request.handle).length\n if (claimable) {\n done(`${claimable} abandoned swap(s) rebuilt with a claimable handle — see --claim`)\n }\n if (!result.complete) {\n warn('the walk stopped before the history ended — raise or drop --pages to finish it')\n }\n } else {\n // Nothing to look for: every consumed identity either has its swap id or has\n // already been searched for across the whole history.\n walkedEverything = true\n done('local history is complete — no need to search chain')\n }\n\n // Counted here rather than at startup: --reconcile populates the store, and a\n // count taken before that would report \"nothing tracked\" in the same run that\n // reports what it found.\n const records = await blindedIdentities.load()\n const tracked = records.length\n step(`reading swap_outputs for ${tracked} tracked identity(ies)`)\n const owed = await client.getUnclaimedSwaps()\n const tokens = await client.listTokens()\n const infoOf = (id: string) => tokens.find((token) => token.id === id)\n\n const rows = owed.swaps.map((swap) => {\n const out = infoOf(swap.output.token_out)\n const back = infoOf(swap.output.token_in)\n return {\n swapId: swap.swapId,\n blindedAddress: swap.blindedAddress,\n claimable: swap.claimable,\n tokenOut: out?.symbol ?? swap.output.token_out,\n amountOut: swap.output.amount_out,\n decimalsOut: out?.decimals ?? 0,\n tokenIn: back?.symbol ?? swap.output.token_in,\n amountRemaining: swap.output.amount_remaining,\n decimalsIn: back?.decimals ?? 0,\n }\n })\n\n const target = claimOne ? rows.filter((row) => row.swapId === claimOne) : rows\n if (claimOne && !target.length) {\n throw new Error(`swap ${claimOne} is not owed anything — it may already be claimed.`)\n }\n\n const claimed: Array<{ swapId: string; transactionId: string; amountOut: string }> = []\n if (wantsClaim) {\n const claimable = target.filter((row) => row.claimable)\n if (!claimable.length) {\n warn('nothing claimable: no stored handle for the owed swaps (try --reconcile)')\n } else if (\n confirmed({\n execute: args.execute as boolean | undefined,\n network,\n plan: claimable.map(\n (row) =>\n [\n `claim ${formatAmount(row.amountOut, row.decimalsOut, row.tokenOut)}`,\n `from swap ${row.swapId.slice(0, 16)}…`,\n ] as const,\n ),\n })\n ) {\n for (const row of claimable) {\n const swap = owed.swaps.find((entry) => entry.swapId === row.swapId)!\n const pIn = infoOf(swap.output.token_in)?.ammTokenProgram\n const pOut = infoOf(swap.output.token_out)?.ammTokenProgram\n if (!pIn || !pOut) {\n warn(`skipping ${row.swapId}: no wrapper program for one of its tokens`)\n continue\n }\n const imports = await client.resolveDexImports({ tokenPrograms: [pIn, pOut] })\n\n // The output becomes claimable a few blocks after the swap confirms, so\n // an early attempt is expected to fail rather than exceptional.\n for (let attempt = 0; attempt < 10; attempt++) {\n try {\n step(`claiming ${row.swapId.slice(0, 16)}… (attempt ${attempt + 1})`)\n const result = await client.claimSwapOutput({ handle: swap.handle!, imports })\n done(\n `claimed ${formatAmount(result.amountOut, row.decimalsOut, row.tokenOut)} (tx ${result.transactionId})`,\n )\n claimed.push({\n swapId: row.swapId,\n transactionId: result.transactionId,\n amountOut: result.amountOut.toString(),\n })\n break\n } catch (error) {\n if (!(error instanceof SwapOutputNotFinalizedError)) throw error\n step('not finalized yet — waiting 15s')\n await new Promise((resolve) => setTimeout(resolve, 15_000))\n }\n }\n }\n }\n }\n\n // The history is the point of the script, so it prints whatever else happened —\n // a failed claim or an exhausted page budget still leaves a picture worth\n // seeing, and a caller hunting for funds needs the whole ledger, not a summary.\n const symbolOf = (tokenId: string) => infoOf(tokenId)?.symbol ?? `${tokenId.slice(0, 8)}…`\n const decimalsOf = (tokenId: string) => infoOf(tokenId)?.decimals ?? 0\n\n const history = [...records]\n .sort((a, b) => a.counter - b.counter)\n .map((record) => {\n // The handle knows what was sold; the claim knows what came back. Either can\n // be absent — a recovered identity has neither — so both are nullable rather\n // than defaulted to zero, which would read as \"sold nothing\".\n const handle = record.handle\n const claim = record.claim\n const tokenIn = claim?.tokenIn ?? handle?.tokenInId ?? null\n const tokenOut = claim?.tokenOut ?? handle?.tokenOutId ?? null\n return {\n counter: record.counter,\n status: record.status,\n swapId: record.swapId ?? null,\n pair: tokenIn && tokenOut ? `${symbolOf(tokenIn)}→${symbolOf(tokenOut)}` : null,\n // The handle when it survived, else the request's public `amount_in`,\n // which the history walk recovers for a store that lost its handles.\n sold:\n handle || (record.soldAmountIn && tokenIn)\n ? {\n amount: BigInt(handle?.amountIn ?? record.soldAmountIn!),\n decimals: decimalsOf(handle?.tokenInId ?? tokenIn!),\n symbol: symbolOf(handle?.tokenInId ?? tokenIn!),\n }\n : null,\n received: claim ? { amount: BigInt(claim.amountOut), decimals: decimalsOf(claim.tokenOut), symbol: symbolOf(claim.tokenOut) } : null,\n refunded:\n claim && BigInt(claim.amountRemaining) > 0n\n ? { amount: BigInt(claim.amountRemaining), decimals: decimalsOf(claim.tokenIn), symbol: symbolOf(claim.tokenIn) }\n : null,\n block: claim?.blockNumber ?? null,\n hasHandle: !!handle,\n claimSearched: !!record.claimSearched,\n blindedAddress: record.blindedAddress,\n }\n })\n\n // Collated from the persisted claims rather than a fresh walk: the claim\n // deleted its `swap_outputs` entry, so what a swap moved is only knowable from\n // the record reconcile wrote.\n const settled = records.filter((record) => record.claim)\n const received: Record<string, bigint> = {}\n const refunded: Record<string, bigint> = {}\n const pairs: Record<string, number> = {}\n for (const record of settled) {\n const claim = record.claim!\n received[claim.tokenOut] = (received[claim.tokenOut] ?? 0n) + BigInt(claim.amountOut)\n if (BigInt(claim.amountRemaining) > 0n) {\n refunded[claim.tokenIn] = (refunded[claim.tokenIn] ?? 0n) + BigInt(claim.amountRemaining)\n }\n const inSymbol = infoOf(claim.tokenIn)?.symbol ?? claim.tokenIn.slice(0, 10)\n const outSymbol = infoOf(claim.tokenOut)?.symbol ?? claim.tokenOut.slice(0, 10)\n const pair = `${inSymbol}→${outSymbol}`\n pairs[pair] = (pairs[pair] ?? 0) + 1\n }\n\n output(\n {\n network,\n tracked,\n walkedEverything,\n summary: {\n settled: settled.length,\n unrecorded: records.filter((record) => !record.claim && record.status !== 'reserved').length,\n pairs,\n received,\n refunded,\n },\n history,\n owed: rows,\n totals: owed.totals,\n unresolvable: owed.unresolvable.length,\n claimed,\n },\n (data) => {\n if (data.history.length) {\n console.log(`\\nswaps so far on ${data.network}:\\n`)\n const header = ['#', 'pair', 'sold', 'received', 'block', 'status', 'note']\n const rows = data.history.map((entry) => [\n String(entry.counter),\n entry.pair ?? '—',\n entry.sold ? formatAmount(entry.sold.amount, entry.sold.decimals, entry.sold.symbol) : '—',\n entry.received\n ? formatAmount(entry.received.amount, entry.received.decimals, entry.received.symbol) +\n (entry.refunded\n ? ` (+${formatAmount(entry.refunded.amount, entry.refunded.decimals, entry.refunded.symbol)} back)`\n : '')\n : '—',\n entry.block === null ? '—' : String(entry.block),\n // Named for what the row means to a reader, not for the store's\n // lifecycle word. `swapped` is the state where money settled and is\n // sitting unclaimed, which is the only row that wants acting on.\n // `reserved` is NOT pending a claim: nothing was ever spent on it, so\n // calling it that would assert funds are waiting when none are.\n entry.status === 'claimed'\n ? green('claimed')\n : entry.status === 'swapped'\n ? yellow('pending claim')\n : dim(entry.status),\n // The handle is what makes an unclaimed swap claimable, so its absence\n // belongs beside the row rather than in a footnote.\n entry.status === 'swapped' && !entry.hasHandle\n ? entry.claimSearched\n ? yellow('never claimed')\n : dim('no handle')\n : '',\n ])\n // The shared renderer, which measures columns without their styling —\n // padding the raw string would indent everything right of a coloured\n // status cell by the width of its escape codes.\n table(header, rows, ['right', 'left', 'right', 'right', 'right', 'left', 'left'])\n }\n if (!data.owed.length) {\n if (data.tracked === 0) {\n console.log(\n '\\nThis store tracks no identities yet, so there is nothing to look for. A swap made ' +\n 'through these scripts records itself; for an account with history, ' +\n '`--reconcile` rebuilds the store from chain.',\n )\n } else if (data.unresolvable) {\n // Not \"all settled\": these were used but cannot be looked up, so whether\n // they hold proceeds is unknown rather than answered.\n console.log(\n `\\nNothing claimable across ${data.tracked} tracked identity(ies), but ` +\n `${data.unresolvable} of them cannot be checked — see below.`,\n )\n } else {\n console.log(`\\nNothing owed across ${data.tracked} tracked identity(ies) — all settled.`)\n }\n } else {\n console.log(`\\n${data.owed.length} unclaimed swap(s) on ${data.network}:\\n`)\n for (const row of data.owed) {\n const mark = row.claimable ? ' ' : '×'\n console.log(\n `${mark} ${formatAmount(row.amountOut, row.decimalsOut, row.tokenOut).padStart(24)}` +\n (row.amountRemaining > 0n\n ? ` + ${formatAmount(row.amountRemaining, row.decimalsIn, row.tokenIn)} refund`\n : ''),\n )\n console.log(` swap ${row.swapId}`)\n }\n const blocked = data.owed.filter((row) => !row.claimable).length\n if (blocked) {\n console.log(`\\n× ${blocked} owed but not claimable here: no stored handle. Try --reconcile.`)\n }\n }\n if (data.unresolvable) {\n warn(\n `${data.unresolvable} identity(ies) were used by this account but have no swap id on file, so ` +\n 'their swap cannot be looked up: it is unknown whether those swaps were already claimed or ' +\n 'still hold proceeds.',\n )\n if (data.walkedEverything) {\n // The whole history was searched and no claim names them, so they were\n // never claimed. Their proceeds may still be sitting in `swap_outputs`,\n // and a claim needs the whole handle — which chain history does not carry.\n warn(\n 'The entire claim history was searched and none of them appear in it, so those swaps were ' +\n 'never claimed. Their output may still be waiting on chain, but it cannot be claimed ' +\n 'without the handle, which only the process that made the swap held.',\n )\n } else {\n warn(\n 'Only part of the history was searched. Run `--reconcile` without --pages to walk all of it ' +\n 'before concluding anything about these.',\n )\n }\n }\n if (!wantsClaim && data.owed.some((row) => row.claimable)) {\n console.log('\\nRun with --claim --execute to collect.')\n }\n\n const { summary } = data\n console.log(`\\nswaps settled: ${summary.settled}`)\n if (summary.settled) {\n for (const [pair, count] of Object.entries(summary.pairs).sort((a, b) => b[1] - a[1])) {\n console.log(` ${String(count).padStart(4)} × ${pair}`)\n }\n console.log('\\nreceived in total:')\n for (const [tokenId, amount] of Object.entries(summary.received)) {\n const info = infoOf(tokenId)\n console.log(` ${formatAmount(amount, info?.decimals ?? 0, info?.symbol ?? tokenId.slice(0, 10))}`)\n }\n for (const [tokenId, amount] of Object.entries(summary.refunded)) {\n const info = infoOf(tokenId)\n console.log(\n ` ${formatAmount(amount, info?.decimals ?? 0, info?.symbol ?? tokenId.slice(0, 10))} refunded unfilled`,\n )\n }\n }\n if (summary.unrecorded) {\n // Totals cover the swaps whose claim was found. Saying so keeps the figures\n // from reading as a complete account of the account's trading.\n console.log(\n `\\nThese totals cover ${summary.settled} settled swap(s). ${summary.unrecorded} more were used ` +\n 'on chain without a recorded claim, so their amounts are not included.',\n )\n }\n },\n )\n })\n}\n"],"mappings":"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","names":["rows"]}
|