diff --git a/.gitignore b/.gitignore index 4e60f8f..0e7a796 100644 --- a/.gitignore +++ b/.gitignore @@ -5,6 +5,9 @@ **/typechain-types/ **/dist/ **/.next/ +**/*.tsbuildinfo +**/vite.config.d.ts +**/vite.config.js # Ignores development broadcast logs !/broadcast diff --git a/packages/safe-tx/package.json b/packages/safe-tx/package.json index deb21c0..884b58a 100644 --- a/packages/safe-tx/package.json +++ b/packages/safe-tx/package.json @@ -25,6 +25,11 @@ "dependencies": { "commander": "^12.0.0" }, + "optionalDependencies": { + "@ledgerhq/hw-app-eth": "^6.39.0", + "@ledgerhq/hw-transport-node-hid": "^6.29.5", + "@trezor/connect": "^9.4.0" + }, "peerDependencies": { "viem": "^2.0.0" }, diff --git a/packages/safe-tx/scripts/test-trezor.ts b/packages/safe-tx/scripts/test-trezor.ts new file mode 100644 index 0000000..7c86f1e --- /dev/null +++ b/packages/safe-tx/scripts/test-trezor.ts @@ -0,0 +1,101 @@ +#!/usr/bin/env bun +/** + * Graduated Trezor smoke test. Run with: + * + * bun packages/safe-tx/scripts/test-trezor.ts # Phase A only + * bun packages/safe-tx/scripts/test-trezor.ts --sign-harmless # Phase A + B + * bun packages/safe-tx/scripts/test-trezor.ts --sign-typed # Phase A + B + C + * + * Phases: + * A. Resolve address only — NO signature, no device prompt. + * Validates Trezor Bridge + @trezor/connect + USB connection. + * + * B. personal_sign of a fixed string — device shows the message, + * you press confirm. Signature is only valid for THAT exact + * string, cannot be replayed for anything dangerous. + * + * C. EIP-712 typed-data sign with a BOGUS verifyingContract + * (0x000…dEaD). Signature is bound to a non-existent contract, + * so even if leaked it's worthless on mainnet. + * + * Pre-flight: + * 1. Install Trezor Bridge: https://trezor.io/start + * 2. Plug + unlock your Trezor (any model). + * 3. bun add @trezor/connect (only needed for this test session) + */ + +import { trezorSigner } from '../src/signers/trezor.js' + +const args = process.argv.slice(2) +const wantHarmless = args.includes('--sign-harmless') || args.includes('--sign-typed') +const wantTyped = args.includes('--sign-typed') + +console.log('=== Phase A — Resolve address (no signature) ===') +console.log('Initializing Trezor Connect (may take ~30s on first run)…') +const signer = await trezorSigner() +console.log(`✅ Address: ${signer.address}`) +console.log(' This came from your device without any prompt.') +console.log(' If you see this, the integration works end-to-end.\n') + +if (!wantHarmless) { + console.log('Done. Re-run with --sign-harmless to test signature flow.') + process.exit(0) +} + +console.log('=== Phase B — personal_sign a harmless string ===') +const message = `safe-tx Trezor smoke test @ ${new Date().toISOString()}` +console.log(`Message: "${message}"`) +console.log('LOOK AT YOUR TREZOR — confirm the message displayed matches.\n') +const sigB = await signer.signMessage({ message }) +console.log(`✅ Signature: ${sigB}`) +console.log(' This signature is bound to that exact string only.') +console.log(' It cannot be replayed for any tx, transfer, or contract call.\n') + +if (!wantTyped) { + console.log('Done. Re-run with --sign-typed to test EIP-712 flow.') + process.exit(0) +} + +console.log('=== Phase C — EIP-712 sign with BOGUS verifyingContract ===') +const fakeSafe = '0x000000000000000000000000000000000000dEaD' as const +console.log(`verifyingContract: ${fakeSafe} (intentionally non-existent)`) +console.log('LOOK AT YOUR TREZOR — confirm the contract address shown is 0x000…dEaD.') +console.log('If it shows ANY OTHER address, REJECT the signature.\n') +const sigC = await signer.signTypedData({ + domain: { + chainId: 1155, + verifyingContract: fakeSafe, + }, + types: { + SafeTx: [ + { name: 'to', type: 'address' }, + { name: 'value', type: 'uint256' }, + { name: 'data', type: 'bytes' }, + { name: 'operation', type: 'uint8' }, + { name: 'safeTxGas', type: 'uint256' }, + { name: 'baseGas', type: 'uint256' }, + { name: 'gasPrice', type: 'uint256' }, + { name: 'gasToken', type: 'address' }, + { name: 'refundReceiver', type: 'address' }, + { name: 'nonce', type: 'uint256' }, + ], + }, + primaryType: 'SafeTx', + message: { + to: fakeSafe, + value: 0n, + data: '0x', + operation: 0, + safeTxGas: 0n, + baseGas: 0n, + gasPrice: 0n, + gasToken: '0x0000000000000000000000000000000000000000', + refundReceiver: '0x0000000000000000000000000000000000000000', + nonce: 0n, + }, +}) +console.log(`✅ Signature: ${sigC}`) +console.log(' Bound to a non-existent Safe — useless on mainnet.\n') + +console.log('All phases passed. Your Trezor signer is ready for real Safe ops.') +process.exit(0) diff --git a/packages/safe-tx/src/cli/commands/confirm.ts b/packages/safe-tx/src/cli/commands/confirm.ts index b66ad27..00a7404 100644 --- a/packages/safe-tx/src/cli/commands/confirm.ts +++ b/packages/safe-tx/src/cli/commands/confirm.ts @@ -13,7 +13,7 @@ export function buildConfirmCommand(): Command { .option('--network ', 'Target network', 'intuition-mainnet') .addOption( new Option('--signer ', 'Signer strategy') - .choices(['env', 'walletconnect', 'ledger']) + .choices(['env', 'walletconnect', 'ledger', 'trezor']) .default('env'), ) .action( diff --git a/packages/safe-tx/src/cli/commands/execute.ts b/packages/safe-tx/src/cli/commands/execute.ts index c9b65a1..a8ebc83 100644 --- a/packages/safe-tx/src/cli/commands/execute.ts +++ b/packages/safe-tx/src/cli/commands/execute.ts @@ -18,7 +18,7 @@ export function buildExecuteCommand(): Command { .option('--network ', 'Target network', 'intuition-mainnet') .addOption( new Option('--signer ', 'Signer strategy for the executor (does not need to be a Safe owner)') - .choices(['env', 'walletconnect', 'ledger']) + .choices(['env', 'walletconnect', 'ledger', 'trezor']) .default('env'), ) .action( diff --git a/packages/safe-tx/src/cli/commands/propose.ts b/packages/safe-tx/src/cli/commands/propose.ts index 93fca85..95f560b 100644 --- a/packages/safe-tx/src/cli/commands/propose.ts +++ b/packages/safe-tx/src/cli/commands/propose.ts @@ -24,7 +24,7 @@ function buildProposeCommand(op: OpRegistration): Command { cmd.option('--network ', 'Target network', 'intuition-mainnet') cmd.addOption( new Option('--signer ', 'Signer strategy') - .choices(['env', 'walletconnect', 'ledger']) + .choices(['env', 'walletconnect', 'ledger', 'trezor']) .default('env'), ) diff --git a/packages/safe-tx/src/ops/index.ts b/packages/safe-tx/src/ops/index.ts index aaa888b..d10d23a 100644 --- a/packages/safe-tx/src/ops/index.ts +++ b/packages/safe-tx/src/ops/index.ts @@ -1,3 +1,5 @@ export * as v2Admin from './v2-admin.js' export * as factory from './factory.js' export * as uups from './uups-upgrade.js' +export * as versionedProxy from './versioned-proxy.js' +export * as sponsored from './sponsored.js' diff --git a/packages/safe-tx/src/ops/sponsored.ts b/packages/safe-tx/src/ops/sponsored.ts new file mode 100644 index 0000000..76399b5 --- /dev/null +++ b/packages/safe-tx/src/ops/sponsored.ts @@ -0,0 +1,70 @@ +import { encodeFunctionData, type Address } from 'viem' +import type { AdminOp } from '../types.js' + +/** + * Admin operations specific to `IntuitionFeeProxyV2Sponsored` (the + * sponsor-pool-funded variant). All gated by `onlyWhitelistedAdmin`. + * + * Note: `fundPool` is `external payable` and NOT admin-gated — anyone + * can credit the sponsor pool — so it's not modelled as an AdminOp. + */ +const SPONSORED_ABI = [ + { + type: 'function', + name: 'setClaimLimits', + inputs: [ + { name: 'maxPerTx', type: 'uint256' }, + { name: 'maxPerWindow', type: 'uint256' }, + { name: 'maxVolumePerWindow', type: 'uint256' }, + { name: 'windowSec', type: 'uint256' }, + ], + outputs: [], + stateMutability: 'nonpayable', + }, + { + type: 'function', + name: 'reclaimFromPool', + inputs: [ + { name: 'amount', type: 'uint256' }, + { name: 'to', type: 'address' }, + ], + outputs: [], + stateMutability: 'nonpayable', + }, +] as const + +export function setClaimLimits( + proxy: Address, + maxPerTx: bigint, + maxPerWindow: bigint, + maxVolumePerWindow: bigint, + windowSec: bigint, +): AdminOp { + return { + to: proxy, + value: 0n, + data: encodeFunctionData({ + abi: SPONSORED_ABI, + functionName: 'setClaimLimits', + args: [maxPerTx, maxPerWindow, maxVolumePerWindow, windowSec], + }), + description: `setClaimLimits(maxPerTx=${maxPerTx}, maxPerWindow=${maxPerWindow}, maxVolumePerWindow=${maxVolumePerWindow}, windowSec=${windowSec}) on ${proxy}`, + } +} + +export function reclaimFromPool( + proxy: Address, + amount: bigint, + to: Address, +): AdminOp { + return { + to: proxy, + value: 0n, + data: encodeFunctionData({ + abi: SPONSORED_ABI, + functionName: 'reclaimFromPool', + args: [amount, to], + }), + description: `reclaimFromPool(${amount} wei -> ${to}) on ${proxy}`, + } +} diff --git a/packages/safe-tx/src/ops/versioned-proxy.ts b/packages/safe-tx/src/ops/versioned-proxy.ts new file mode 100644 index 0000000..1c56548 --- /dev/null +++ b/packages/safe-tx/src/ops/versioned-proxy.ts @@ -0,0 +1,99 @@ +import { encodeFunctionData, type Address, type Hex } from 'viem' +import type { AdminOp } from '../types.js' + +/** + * Role 1 (proxyAdmin) operations on `IntuitionVersionedFeeProxy`. + * + * `transferProxyAdmin` is 2-step: it sets `pendingProxyAdmin`, the + * target then has to call `acceptProxyAdmin` from their own wallet + * (or via their Safe propose flow if they're a Safe) to finalize. + */ +const VERSIONED_PROXY_ABI = [ + { + type: 'function', + name: 'transferProxyAdmin', + inputs: [{ name: 'newAdmin', type: 'address' }], + outputs: [], + stateMutability: 'nonpayable', + }, + { + type: 'function', + name: 'acceptProxyAdmin', + inputs: [], + outputs: [], + stateMutability: 'nonpayable', + }, + { + type: 'function', + name: 'registerVersion', + inputs: [ + { name: 'version', type: 'bytes32' }, + { name: 'implementation', type: 'address' }, + ], + outputs: [], + stateMutability: 'nonpayable', + }, + { + type: 'function', + name: 'setDefaultVersion', + inputs: [{ name: 'version', type: 'bytes32' }], + outputs: [], + stateMutability: 'nonpayable', + }, +] as const + +export function transferProxyAdmin(proxy: Address, newAdmin: Address): AdminOp { + return { + to: proxy, + value: 0n, + data: encodeFunctionData({ + abi: VERSIONED_PROXY_ABI, + functionName: 'transferProxyAdmin', + args: [newAdmin], + }), + description: `transferProxyAdmin(-> ${newAdmin}) on proxy ${proxy}`, + } +} + +export function acceptProxyAdmin(proxy: Address): AdminOp { + return { + to: proxy, + value: 0n, + data: encodeFunctionData({ + abi: VERSIONED_PROXY_ABI, + functionName: 'acceptProxyAdmin', + args: [], + }), + description: `acceptProxyAdmin() on proxy ${proxy}`, + } +} + +export function registerVersion( + proxy: Address, + version: Hex, + implementation: Address, +): AdminOp { + return { + to: proxy, + value: 0n, + data: encodeFunctionData({ + abi: VERSIONED_PROXY_ABI, + functionName: 'registerVersion', + args: [version, implementation], + }), + description: `registerVersion(${version}, ${implementation}) on proxy ${proxy}`, + } +} + +export function setDefaultVersion(proxy: Address, version: Hex): AdminOp { + return { + to: proxy, + value: 0n, + data: encodeFunctionData({ + abi: VERSIONED_PROXY_ABI, + functionName: 'setDefaultVersion', + args: [version], + }), + description: `setDefaultVersion(${version}) on proxy ${proxy}`, + } +} diff --git a/packages/safe-tx/src/signers/factory.ts b/packages/safe-tx/src/signers/factory.ts index 4d1e01e..b6c9d95 100644 --- a/packages/safe-tx/src/signers/factory.ts +++ b/packages/safe-tx/src/signers/factory.ts @@ -1,22 +1,24 @@ import { envSigner, type EnvSignerOptions } from './env.js' import { ledgerSigner, type LedgerSignerOptions } from './ledger.js' +import { trezorSigner, type TrezorSignerOptions } from './trezor.js' import { walletconnectSigner, type WalletConnectSignerOptions, } from './walletconnect.js' import type { Signer } from './types.js' -export type SignerStrategy = 'env' | 'walletconnect' | 'ledger' +export type SignerStrategy = 'env' | 'walletconnect' | 'ledger' | 'trezor' export type SignerOptions = { env?: EnvSignerOptions walletconnect?: WalletConnectSignerOptions ledger?: LedgerSignerOptions + trezor?: TrezorSignerOptions } /** * Resolve a Signer for the requested strategy. Async because some - * strategies (walletconnect, ledger) do I/O during initialization. + * strategies (walletconnect, ledger, trezor) do I/O during initialization. */ export async function getSigner( strategy: SignerStrategy, @@ -29,5 +31,7 @@ export async function getSigner( return walletconnectSigner(opts.walletconnect) case 'ledger': return ledgerSigner(opts.ledger) + case 'trezor': + return trezorSigner(opts.trezor) } } diff --git a/packages/safe-tx/src/signers/index.ts b/packages/safe-tx/src/signers/index.ts index 3b2699d..d3f90a6 100644 --- a/packages/safe-tx/src/signers/index.ts +++ b/packages/safe-tx/src/signers/index.ts @@ -1,5 +1,6 @@ export type { Signer } from './types.js' export { envSigner, type EnvSignerOptions } from './env.js' export { ledgerSigner, type LedgerSignerOptions } from './ledger.js' +export { trezorSigner, type TrezorSignerOptions } from './trezor.js' export { walletconnectSigner, type WalletConnectSignerOptions } from './walletconnect.js' export { getSigner, type SignerOptions, type SignerStrategy } from './factory.js' diff --git a/packages/safe-tx/src/signers/ledger.ts b/packages/safe-tx/src/signers/ledger.ts index 9e8b05e..99d3379 100644 --- a/packages/safe-tx/src/signers/ledger.ts +++ b/packages/safe-tx/src/signers/ledger.ts @@ -1,21 +1,117 @@ +import type { Hex } from 'viem' +import { toAccount } from 'viem/accounts' import type { Signer } from './types.js' export type LedgerSignerOptions = { /** BIP-44 path. Default: "44'/60'/0'/0/0" (first Ethereum account). */ derivationPath?: string + /** Max time to wait for USB transport open. Default: 3000ms. */ + transportTimeoutMs?: number } /** - * Stub. Hardware-wallet signing via @ledgerhq/hw-app-eth + - * @ledgerhq/hw-transport-node-hid. Recommended for production prod - * signers — key never leaves the device. + * Hardware-wallet signing via Ledger over USB. Uses dynamic imports of + * `@ledgerhq/hw-app-eth` + `@ledgerhq/hw-transport-node-hid` (declared + * as `optionalDependencies`) so the heavy native bindings only need to + * resolve when this signer is actually selected. * - * Implementation deferred until the CLI's mainnet path actually needs - * it. The stub keeps the strategy dispatched in the factory so - * downstream code can target the final API today. + * EIP-712 signing uses `signEIP712Message` (full struct on-device, + * requires Ledger Ethereum app v1.10+). For Intuition mainnet + * (chain id 1155, not in Ledger's pre-shipped chain list), the device's + * Ethereum app must have "Blind signing" enabled in Settings. + * + * Pre-flight: device unlocked, Ethereum app open, Ledger Live closed + * (Live grabs the USB transport and blocks other clients). */ -export async function ledgerSigner(_opts: LedgerSignerOptions = {}): Promise { - throw new Error( - 'safe-tx: ledger signer not yet implemented. Install @ledgerhq/hw-app-eth + @ledgerhq/hw-transport-node-hid and wire the implementation.', - ) +export async function ledgerSigner(opts: LedgerSignerOptions = {}): Promise { + const derivationPath = opts.derivationPath ?? "44'/60'/0'/0/0" + const transportTimeoutMs = opts.transportTimeoutMs ?? 3000 + + // Optional deps — typed `any` so typecheck doesn't depend on them + // being installed (the whole point of optionalDependencies). + // eslint-disable-next-line @typescript-eslint/no-explicit-any + let TransportNodeHid: any + // eslint-disable-next-line @typescript-eslint/no-explicit-any + let Eth: any + try { + const transportMod = await import(/* @vite-ignore */ '@ledgerhq/hw-transport-node-hid' as string) + const ethMod = await import(/* @vite-ignore */ '@ledgerhq/hw-app-eth' as string) + TransportNodeHid = transportMod.default + Eth = ethMod.default + } catch { + throw new Error( + 'safe-tx: ledger signer requires optional deps. Install: ' + + 'bun add @ledgerhq/hw-app-eth @ledgerhq/hw-transport-node-hid', + ) + } + + // TransportNodeHid.create() can hang indefinitely on machines with no + // Ledger plugged in (and on some Linux configs without udev rules). + // Race it with a timeout so we surface a usable error instead of a + // 30s freeze. + // eslint-disable-next-line @typescript-eslint/no-explicit-any + let transport: any + try { + transport = await Promise.race([ + TransportNodeHid.create(), + new Promise((_, reject) => + setTimeout( + () => + reject( + new Error(`USB transport open timed out after ${transportTimeoutMs}ms`), + ), + transportTimeoutMs, + ), + ), + ]) + } catch (err) { + const msg = err instanceof Error ? err.message : String(err) + throw new Error( + `safe-tx: cannot open USB transport to Ledger. Is the device connected, unlocked, and Ethereum app open? Close Ledger Live first. (${msg})`, + ) + } + + const eth = new Eth(transport) + const { address } = await eth.getAddress(derivationPath) + const account = address as `0x${string}` + + function packSig(r: string, s: string, v: number): Hex { + const vHex = v.toString(16).padStart(2, '0') + return (`0x${r}${s}${vHex}`) as Hex + } + + return toAccount({ + address: account, + + async signTypedData(typedData) { + // The Ledger SDK takes an EIP712Message *object* (not JSON string), + // and all numeric values must be decimal strings (no bigints). Round- + // trip through JSON to coerce bigints while preserving structure. + // eslint-disable-next-line @typescript-eslint/no-explicit-any + const eip712Message: any = JSON.parse( + JSON.stringify(typedData, (_k, v) => + typeof v === 'bigint' ? v.toString() : v, + ), + ) + const sig = await eth.signEIP712Message(derivationPath, eip712Message) + return packSig(sig.r, sig.s, sig.v) + }, + + async signMessage({ message }) { + const raw = + typeof message === 'string' + ? Buffer.from(message, 'utf-8').toString('hex') + : (message.raw as string).startsWith('0x') + ? (message.raw as string).slice(2) + : Buffer.from(message.raw as string, 'utf-8').toString('hex') + const sig = await eth.signPersonalMessage(derivationPath, raw) + return packSig(sig.r, sig.s, sig.v) + }, + + async signTransaction(_transaction) { + throw new Error( + 'safe-tx ledger signer: signTransaction not implemented. The Safe execution path uses signTypedData; if you need raw tx signing for a different flow, file an issue.', + ) + }, + }) } diff --git a/packages/safe-tx/src/signers/trezor.ts b/packages/safe-tx/src/signers/trezor.ts new file mode 100644 index 0000000..e20cb6f --- /dev/null +++ b/packages/safe-tx/src/signers/trezor.ts @@ -0,0 +1,140 @@ +import type { Hex } from 'viem' +import { toAccount } from 'viem/accounts' +import type { Signer } from './types.js' + +export type TrezorSignerOptions = { + /** BIP-44 path. Default: "m/44'/60'/0'/0/0" (first Ethereum account). */ + derivationPath?: string + /** + * App identity sent to Trezor Connect. The library requires it to be + * declared once per process — pick a stable email + url for your CLI. + */ + manifest?: { + email: string + appUrl: string + } + /** Max time to wait for Trezor Connect init. Default: 30000ms. */ + initTimeoutMs?: number +} + +/** + * Hardware-wallet signing via Trezor (Model One / Model T / Safe). + * Uses a dynamic import of `@trezor/connect` so the dep stays optional: + * + * bun add @trezor/connect + * + * Pre-flight: + * - Trezor Bridge installed and running (https://trezor.io/start) — + * Trezor Connect uses Bridge to talk to the device on Linux/Mac. + * - Device unlocked and on the home screen. + * - Confirm action prompts on the device when signing. + * + * EIP-712: uses `ethereumSignTypedData` with `metamask_v4_compat: true` + * which accepts a domain + types + message structure equivalent to what + * viem produces for Safe transactions. + */ +export async function trezorSigner(opts: TrezorSignerOptions = {}): Promise { + const derivationPath = opts.derivationPath ?? "m/44'/60'/0'/0/0" + const manifest = opts.manifest ?? { + email: 'safe-tx@intuition.box', + appUrl: 'https://github.com/intuition-box/intuition-fee-proxy-template', + } + const initTimeoutMs = opts.initTimeoutMs ?? 30_000 + + // Optional dep — typed `any` so the typecheck doesn't fail when + // @trezor/connect isn't installed in node_modules (the whole point of + // optionalDependencies). Runtime types are checked at the use sites + // through the SDK's response shape. + // eslint-disable-next-line @typescript-eslint/no-explicit-any + let TrezorConnect: any + try { + // @vite-ignore — optional dep, may not be installed in webapp builds. + const mod = await import(/* @vite-ignore */ '@trezor/connect' as string) + TrezorConnect = mod.default + } catch { + throw new Error( + 'safe-tx: trezor signer requires optional dep. Install: bun add @trezor/connect', + ) + } + + try { + await Promise.race([ + TrezorConnect.init({ manifest }), + new Promise((_, reject) => + setTimeout( + () => + reject( + new Error( + `Trezor Connect init timed out after ${initTimeoutMs}ms — is Trezor Bridge running? https://trezor.io/start`, + ), + ), + initTimeoutMs, + ), + ), + ]) + } catch (err) { + const msg = err instanceof Error ? err.message : String(err) + // init() throws if already initialized — that's fine, we proceed. + if (!/already/i.test(msg)) { + throw new Error(`safe-tx: trezor init failed. ${msg}`) + } + } + + const addrRes = await TrezorConnect.ethereumGetAddress({ + path: derivationPath, + showOnTrezor: false, + }) + if (!addrRes.success) { + throw new Error(`safe-tx: trezor getAddress failed. ${addrRes.payload.error}`) + } + const account = addrRes.payload.address as `0x${string}` + + return toAccount({ + address: account, + + async signTypedData(typedData) { + // Trezor's ethereumSignTypedData with metamask_v4_compat accepts + // the EIP-712 v4 structure. Need to coerce bigints to decimal + // strings so JSON-serializable. + // eslint-disable-next-line @typescript-eslint/no-explicit-any + const data: any = JSON.parse( + JSON.stringify(typedData, (_k, v) => + typeof v === 'bigint' ? v.toString() : v, + ), + ) + const res = await TrezorConnect.ethereumSignTypedData({ + path: derivationPath, + data, + metamask_v4_compat: true, + }) + if (!res.success) { + throw new Error(`safe-tx trezor signTypedData failed: ${res.payload.error}`) + } + return res.payload.signature as Hex + }, + + async signMessage({ message }) { + const messageString = + typeof message === 'string' + ? message + : (message.raw as string).startsWith('0x') + ? Buffer.from((message.raw as string).slice(2), 'hex').toString('utf-8') + : (message.raw as string) + const res = await TrezorConnect.ethereumSignMessage({ + path: derivationPath, + message: messageString, + hex: false, + }) + if (!res.success) { + throw new Error(`safe-tx trezor signMessage failed: ${res.payload.error}`) + } + return res.payload.signature as Hex + }, + + async signTransaction(_transaction) { + throw new Error( + 'safe-tx trezor signer: signTransaction not implemented. The Safe execution path uses signTypedData; if you need raw tx signing, file an issue.', + ) + }, + }) +} diff --git a/packages/safe-tx/test/integration/rotation-script.test.ts b/packages/safe-tx/test/integration/rotation-script.test.ts new file mode 100644 index 0000000..c895338 --- /dev/null +++ b/packages/safe-tx/test/integration/rotation-script.test.ts @@ -0,0 +1,90 @@ +import { spawnSync } from 'node:child_process' +import { resolve } from 'node:path' +import { describe, expect, it } from 'vitest' + +/** + * Smoke tests for the transferAdminToSafe.ts CLI script. We don't run + * the full rotation against a real proxy here (would require deploying + * a mock V2 proxy on Anvil fork, ~1-2h of plumbing). Instead we verify + * the script's process-level behavior: + * + * - --help prints usage and exits 0 + * - missing required flags surface clear errors + * - --dry-run can run without PROPOSER_PK env var set + * + * The on-chain rotation mechanics are covered by: + * - test/integration/direct-sign.test.ts (Safe execTransaction flow) + * - test/integration/api-kit.test.ts (STS propose flow) + * - test/unit/ops/v2-admin.test.ts (setWhitelistedAdmin builder) + */ + +const SCRIPT = resolve( + __dirname, + '..', + '..', + 'scripts', + 'transferAdminToSafe.ts', +) + +function runScript(args: string[], env: Record = {}): { + stdout: string + stderr: string + status: number | null +} { + const result = spawnSync('bun', [SCRIPT, ...args], { + encoding: 'utf-8', + env: { ...process.env, ...env }, + timeout: 30_000, + }) + return { + stdout: result.stdout ?? '', + stderr: result.stderr ?? '', + status: result.status, + } +} + +describe('transferAdminToSafe script — smoke', () => { + it('--help exits 0 and prints usage', () => { + const { stdout, status } = runScript(['--help']) + expect(status).toBe(0) + expect(stdout).toContain('transferAdminToSafe') + expect(stdout).toContain('--proxy') + expect(stdout).toContain('--safe') + expect(stdout).toContain('--eoa') + expect(stdout).toContain('--dry-run') + }) + + it('missing --proxy fails with a clear required-option error', () => { + const { stderr, status } = runScript([ + '--safe', + '0xf10D442D0fB934D4037DC30769a6EfCf2f54F7B6', + '--eoa', + '0xc634457aD68b037E2D5aA1C10c3930d7e4E2d551', + ]) + expect(status).not.toBe(0) + expect(stderr).toMatch(/required option/i) + expect(stderr).toContain('--proxy') + }) + + it('--dry-run does not require PROPOSER_PK env var', () => { + // Use a non-existent proxy address — the dry-run still hits the + // network to read whitelistedAdmins (which will revert because no + // contract). We expect a non-zero exit but NOT the missing-key error. + const { stderr, status } = runScript( + [ + '--proxy', + '0x000000000000000000000000000000000000dEaD', + '--safe', + '0xf10D442D0fB934D4037DC30769a6EfCf2f54F7B6', + '--eoa', + '0xc634457aD68b037E2D5aA1C10c3930d7e4E2d551', + '--dry-run', + ], + { PROPOSER_PK: '' }, + ) + // We don't care about the network outcome — only that the script + // didn't bail on the env-var check. + expect(status).not.toBe(0) + expect(stderr).not.toMatch(/PROPOSER_PK env var required/) + }, 30_000) +}) diff --git a/packages/safe-tx/test/unit/ops/sponsored.test.ts b/packages/safe-tx/test/unit/ops/sponsored.test.ts new file mode 100644 index 0000000..e966c1f --- /dev/null +++ b/packages/safe-tx/test/unit/ops/sponsored.test.ts @@ -0,0 +1,65 @@ +import { describe, expect, it } from 'vitest' +import { decodeFunctionData, getAddress, toFunctionSelector } from 'viem' +import * as sponsored from '../../../src/ops/sponsored.js' + +const PROXY = getAddress('0xf10D442D0fB934D4037DC30769a6EfCf2f54F7B6') +const RECIPIENT = getAddress('0xc634457aD68b037E2D5aA1C10c3930d7e4E2d551') + +const SELECTOR_SET_LIMITS = toFunctionSelector( + 'setClaimLimits(uint256,uint256,uint256,uint256)', +) +const SELECTOR_RECLAIM = toFunctionSelector('reclaimFromPool(uint256,address)') + +const ABI = [ + { + type: 'function', + name: 'setClaimLimits', + inputs: [ + { type: 'uint256' }, + { type: 'uint256' }, + { type: 'uint256' }, + { type: 'uint256' }, + ], + outputs: [], + stateMutability: 'nonpayable', + }, + { + type: 'function', + name: 'reclaimFromPool', + inputs: [{ type: 'uint256' }, { type: 'address' }], + outputs: [], + stateMutability: 'nonpayable', + }, +] as const + +describe('sponsored AdminOp builders', () => { + it('setClaimLimits encodes 4 uint256 args in order', () => { + const op = sponsored.setClaimLimits( + PROXY, + 10n ** 18n, // maxPerTx + 10n, // maxPerWindow + 10n ** 19n, // maxVolumePerWindow + 3600n, // windowSec + ) + expect(op.to).toBe(PROXY) + expect(op.value).toBe(0n) + expect(op.data.slice(0, 10)).toBe(SELECTOR_SET_LIMITS) + const decoded = decodeFunctionData({ abi: ABI, data: op.data }) + expect(decoded.functionName).toBe('setClaimLimits') + expect(decoded.args).toEqual([10n ** 18n, 10n, 10n ** 19n, 3600n]) + }) + + it('reclaimFromPool encodes (amount, to)', () => { + const op = sponsored.reclaimFromPool(PROXY, 5n * 10n ** 18n, RECIPIENT) + expect(op.data.slice(0, 10)).toBe(SELECTOR_RECLAIM) + const decoded = decodeFunctionData({ abi: ABI, data: op.data }) + expect(decoded.functionName).toBe('reclaimFromPool') + expect(decoded.args).toEqual([5n * 10n ** 18n, RECIPIENT]) + }) + + it('description includes recipient + amount for traceability', () => { + const op = sponsored.reclaimFromPool(PROXY, 1n, RECIPIENT) + expect(op.description).toContain(RECIPIENT) + expect(op.description).toContain('1 wei') + }) +}) diff --git a/packages/safe-tx/test/unit/ops/versioned-proxy.test.ts b/packages/safe-tx/test/unit/ops/versioned-proxy.test.ts new file mode 100644 index 0000000..fa236ad --- /dev/null +++ b/packages/safe-tx/test/unit/ops/versioned-proxy.test.ts @@ -0,0 +1,71 @@ +import { describe, expect, it } from 'vitest' +import { decodeFunctionData, getAddress, stringToHex, toFunctionSelector } from 'viem' +import * as vp from '../../../src/ops/versioned-proxy.js' + +const PROXY = getAddress('0xf10D442D0fB934D4037DC30769a6EfCf2f54F7B6') +const NEW_ADMIN = getAddress('0xc634457aD68b037E2D5aA1C10c3930d7e4E2d551') +const NEW_IMPL = getAddress('0x29fcB43b46531BcA003ddC8FCB67FFE91900C762') +const VERSION_BYTES32 = stringToHex('v3.0.0', { size: 32 }) + +const SELECTOR_TRANSFER = toFunctionSelector('transferProxyAdmin(address)') +const SELECTOR_ACCEPT = toFunctionSelector('acceptProxyAdmin()') +const SELECTOR_REGISTER = toFunctionSelector('registerVersion(bytes32,address)') +const SELECTOR_SET_DEFAULT = toFunctionSelector('setDefaultVersion(bytes32)') + +const ABI = [ + { type: 'function', name: 'transferProxyAdmin', inputs: [{ type: 'address' }], outputs: [], stateMutability: 'nonpayable' }, + { type: 'function', name: 'acceptProxyAdmin', inputs: [], outputs: [], stateMutability: 'nonpayable' }, + { type: 'function', name: 'registerVersion', inputs: [{ type: 'bytes32' }, { type: 'address' }], outputs: [], stateMutability: 'nonpayable' }, + { type: 'function', name: 'setDefaultVersion', inputs: [{ type: 'bytes32' }], outputs: [], stateMutability: 'nonpayable' }, +] as const + +describe('versioned-proxy AdminOp builders', () => { + it('transferProxyAdmin', () => { + const op = vp.transferProxyAdmin(PROXY, NEW_ADMIN) + expect(op.to).toBe(PROXY) + expect(op.value).toBe(0n) + expect(op.data.slice(0, 10)).toBe(SELECTOR_TRANSFER) + const decoded = decodeFunctionData({ abi: ABI, data: op.data }) + expect(decoded.functionName).toBe('transferProxyAdmin') + expect(decoded.args).toEqual([NEW_ADMIN]) + }) + + it('acceptProxyAdmin (no args, selector only)', () => { + const op = vp.acceptProxyAdmin(PROXY) + expect(op.data).toBe(SELECTOR_ACCEPT) + expect(op.data.length).toBe(10) + const decoded = decodeFunctionData({ abi: ABI, data: op.data }) + expect(decoded.functionName).toBe('acceptProxyAdmin') + expect(decoded.args ?? []).toEqual([]) + }) + + it('registerVersion', () => { + const op = vp.registerVersion(PROXY, VERSION_BYTES32, NEW_IMPL) + expect(op.data.slice(0, 10)).toBe(SELECTOR_REGISTER) + const decoded = decodeFunctionData({ abi: ABI, data: op.data }) + expect(decoded.functionName).toBe('registerVersion') + expect(decoded.args).toEqual([VERSION_BYTES32, NEW_IMPL]) + }) + + it('setDefaultVersion', () => { + const op = vp.setDefaultVersion(PROXY, VERSION_BYTES32) + expect(op.data.slice(0, 10)).toBe(SELECTOR_SET_DEFAULT) + const decoded = decodeFunctionData({ abi: ABI, data: op.data }) + expect(decoded.functionName).toBe('setDefaultVersion') + expect(decoded.args).toEqual([VERSION_BYTES32]) + }) + + it('all builders target the proxy address with value 0n', () => { + const ops = [ + vp.transferProxyAdmin(PROXY, NEW_ADMIN), + vp.acceptProxyAdmin(PROXY), + vp.registerVersion(PROXY, VERSION_BYTES32, NEW_IMPL), + vp.setDefaultVersion(PROXY, VERSION_BYTES32), + ] + for (const op of ops) { + expect(op.to).toBe(PROXY) + expect(op.value).toBe(0n) + expect(op.description.length).toBeGreaterThan(0) + } + }) +}) diff --git a/packages/safe-tx/test/unit/signers/factory.test.ts b/packages/safe-tx/test/unit/signers/factory.test.ts index c500162..414264d 100644 --- a/packages/safe-tx/test/unit/signers/factory.test.ts +++ b/packages/safe-tx/test/unit/signers/factory.test.ts @@ -11,9 +11,30 @@ describe('getSigner factory', () => { expect(signer.address).toBe(TEST_ADDR) }) - it('rejects with "not yet implemented" for ledger strategy', async () => { - await expect(getSigner('ledger')).rejects.toThrow(/ledger.*not yet implemented/i) - }) + it('rejects with an actionable error when ledger has no device + no deps', async () => { + // Two valid failure paths depending on whether @ledgerhq/* optional + // deps were installed by bun: + // - deps missing -> "ledger signer requires optional deps" + // - deps installed but no device plugged -> "cannot open USB transport" + // Both are user-actionable and resolve quickly thanks to the 3s + // transport open timeout in the signer. + await expect( + getSigner('ledger', { ledger: { transportTimeoutMs: 1500 } }), + ).rejects.toThrow( + /ledger signer requires optional deps|cannot open USB transport/i, + ) + }, 5000) + + it('rejects with an actionable error when trezor has no bridge + no deps', async () => { + // Same dual-path as ledger: + // - deps missing -> "trezor signer requires optional dep" + // - deps installed but no Trezor Bridge running -> init timeout + await expect( + getSigner('trezor', { trezor: { initTimeoutMs: 1500 } }), + ).rejects.toThrow( + /trezor signer requires optional dep|trezor init failed|trezor connect init timed out/i, + ) + }, 5000) it('rejects with "not yet implemented" for walletconnect strategy', async () => { await expect(getSigner('walletconnect')).rejects.toThrow(/walletconnect.*not yet implemented/i) diff --git a/packages/webapp/src/components/AdminsPanel.tsx b/packages/webapp/src/components/AdminsPanel.tsx index ad6ad2e..47b576b 100644 --- a/packages/webapp/src/components/AdminsPanel.tsx +++ b/packages/webapp/src/components/AdminsPanel.tsx @@ -2,13 +2,17 @@ import { useEffect, useState } from 'react' import { isAddress, type Address } from 'viem' import { useWaitForTransactionReceipt } from 'wagmi' +import { ops } from '@intuition-fee-proxy/safe-tx' import { useAdmins, useIsAdmin, useSetWhitelistedAdmin, } from '../hooks/useProxy' +import { useSafeAdmin } from '../hooks/useSafeAdmin' +import { useSafePropose } from '../hooks/useSafePropose' import AddressDisplay from './Address' import { SafeBadge } from './SafeBadge' +import { SafeProposeFeedback } from './SafeProposeFeedback' import { Spinner } from './Spinner' interface Props { @@ -28,18 +32,15 @@ export function AdminsPanel({ proxy, connectedAccount }: Props) { } = useSetWhitelistedAdmin(proxy) const receipt = useWaitForTransactionReceipt({ hash }) const [addDraft, setAddDraft] = useState('') - // Tracks which row (or 'ADD') owns the in-flight tx, so only that button - // shows "Signing…" / "Mining…" state. Other rows stay idle (but disabled). const [pendingTarget, setPendingTarget] = useState
( null, ) - // True between "receipt mined" and "admins list refetched" — bridges the - // gap where the tx is done but the event-log-derived list hasn't caught - // up yet. Drives the discrete title spinner + keeps the row button - // spinner alive so the UI never looks idle during that window. const [postTxRefreshing, setPostTxRefreshing] = useState(false) - const busy = isPending || receipt.isLoading || postTxRefreshing + const { safe } = useSafeAdmin(proxy) + const safePropose = useSafePropose({ safeAddress: safe }) + + const busy = isPending || receipt.isLoading || postTxRefreshing || safePropose.isProposing useEffect(() => { if (receipt.isSuccess) { @@ -50,7 +51,6 @@ export function AdminsPanel({ proxy, connectedAccount }: Props) { } }, [hash, receipt.isSuccess]) - // Release the spinner once the admins refetch settles. useEffect(() => { if (postTxRefreshing && !isLoading) { setPostTxRefreshing(false) @@ -58,8 +58,6 @@ export function AdminsPanel({ proxy, connectedAccount }: Props) { } }, [postTxRefreshing, isLoading]) - // If the write errored or the user rejected the signature, release the - // per-row pending marker so the buttons become clickable again. useEffect(() => { if ( !isPending && @@ -87,6 +85,18 @@ export function AdminsPanel({ proxy, connectedAccount }: Props) { } } + async function onProposeAdd() { + if (!addValid || !safe) return + safePropose.reset() + try { + await safePropose.propose( + ops.v2Admin.setWhitelistedAdmin(proxy, addDraft as Address, true), + ) + } catch (e) { + console.error(e) + } + } + async function onRevoke(addr: Address) { setPendingTarget(addr) try { @@ -97,6 +107,23 @@ export function AdminsPanel({ proxy, connectedAccount }: Props) { } } + async function onProposeRevoke(addr: Address) { + if (!safe) return + safePropose.reset() + try { + await safePropose.propose( + ops.v2Admin.setWhitelistedAdmin(proxy, addr, false), + ) + } catch (e) { + console.error(e) + } + } + + // The form is visible if the user can either direct-write (already an + // admin) or propose via Safe (a Safe is in the admin list — Safe owners + // who aren't direct admins can still propose). + const canInteract = connectedIsAdmin || Boolean(safe) + return (
@@ -116,10 +143,8 @@ export function AdminsPanel({ proxy, connectedAccount }: Props) {

- Controls money flow — withdraw accumulated fees, change fee settings, - add / revoke other fee admins, and on sponsored proxies fundPool / - reclaim / setClaimLimits. Cannot register new - implementation versions. List is reconstructed from on-chain events. + Controls fees, withdrawals and (sponsored) pool funding. Cannot + register new implementations.

{isLoading && admins.length === 0 && ( @@ -142,7 +167,8 @@ export function AdminsPanel({ proxy, connectedAccount }: Props) { connectedAccount && addr.toLowerCase() === connectedAccount.toLowerCase() const isLastAdmin = admins.length === 1 - const canRevoke = connectedIsAdmin && !(isSelf && isLastAdmin) + const canDirectRevoke = connectedIsAdmin && !(isSelf && isLastAdmin) + const canProposeRevoke = Boolean(safe) && !isLastAdmin return (
  • )} - {canRevoke && ( - - )} - {isSelf && isLastAdmin && ( - - Last admin — cannot self-revoke - - )} +
    + {canDirectRevoke && ( + + )} + {canProposeRevoke && ( + + )} + {isSelf && isLastAdmin && ( + + Last admin — cannot self-revoke + + )} +
  • ) })} )} - {connectedIsAdmin ? ( + {canInteract ? (
    -
    +
    Grant Role 2 to a new address
    -
    - Grants fee admin rights. Use a Safe or multisig address for - production deployments — granting to an EOA concentrates trust. +
    + Prefer a Safe — granting to an EOA concentrates trust
    @@ -204,19 +241,31 @@ export function AdminsPanel({ proxy, connectedAccount }: Props) { placeholder="0x…" className="input font-mono text-xs flex-1 min-w-[260px]" /> - + {connectedIsAdmin && ( + + )} + {safe && ( + + )}
    {addDraft && !isAddress(addDraft) && (

    Invalid address.

    @@ -232,9 +281,11 @@ export function AdminsPanel({ proxy, connectedAccount }: Props) {
    ) : (

    - Connect as a whitelisted admin to add or revoke admins. + Connect as a whitelisted admin (or as a Safe owner of a Safe in the admin list) to add or revoke admins.

    )} + +
    ) } diff --git a/packages/webapp/src/components/AdminsTab.tsx b/packages/webapp/src/components/AdminsTab.tsx index d5d4d1c..53352c7 100644 --- a/packages/webapp/src/components/AdminsTab.tsx +++ b/packages/webapp/src/components/AdminsTab.tsx @@ -28,10 +28,8 @@ export function AdminsTab({ return (

    - Two independent admin roles — disjoint by design so that a compromise - of one cannot be leveraged into the other. Most setups use a single - Safe for both; splitting is an option if your dev team and ops team - are distinct. + Two independent roles. A single Safe can hold both, or split them + between dev and ops.

    { if (current) { setMaxPerTx(formatEther(current.maxClaimPerTx)) @@ -85,6 +92,24 @@ export function ClaimLimitsPanel({ proxy, current, onDone }: Props) { } } + async function onProposeSetLimits() { + if (!allValid || !safe) return + safePropose.reset() + try { + await safePropose.propose( + ops.sponsored.setClaimLimits( + proxy, + parseEther(maxPerTx), + BigInt(maxPerWindow), + parseEther(maxVolume), + BigInt(windowSec), + ), + ) + } catch (e) { + console.error(e) + } + } + // Live recap values const recapTx = toNumberOrUndefined(maxPerTx) const recapCount = toNumberOrUndefined(maxPerWindow) @@ -285,14 +310,28 @@ export function ClaimLimitsPanel({ proxy, current, onDone }: Props) {

    - +
    + + {safe && ( + + )} +
    + + {error && (

    diff --git a/packages/webapp/src/components/FundPoolPanel.tsx b/packages/webapp/src/components/FundPoolPanel.tsx index 9d85781..3f2db35 100644 --- a/packages/webapp/src/components/FundPoolPanel.tsx +++ b/packages/webapp/src/components/FundPoolPanel.tsx @@ -34,13 +34,11 @@ export function FundPoolPanel({ proxy, onDone }: Props) { } return ( -

    +

    Fund the pool

    - Top up the shared sponsorship pool with TRUST from your wallet. - Any user interacting with this proxy will draw from the pool - transparently (bounded by the per-user rate limits). + Permissionless — anyone can top up the shared pool.

    @@ -57,20 +55,22 @@ export function FundPoolPanel({ proxy, onDone }: Props) { /> - +
    + - {error && ( -

    - {error.message.split('\n')[0]} -

    - )} + {error && ( +

    + {error.message.split('\n')[0]} +

    + )} +
    ) } diff --git a/packages/webapp/src/components/HistoryTab.tsx b/packages/webapp/src/components/HistoryTab.tsx index 76947b9..84be726 100644 --- a/packages/webapp/src/components/HistoryTab.tsx +++ b/packages/webapp/src/components/HistoryTab.tsx @@ -127,10 +127,7 @@ export function HistoryTab({ proxy, isAdmin, channel }: Props) {

    History

    Chronological log of every public event on this proxy — pool - contributions, refunds, and fee withdrawals. Reconstructed - client-side from on-chain events; everyone sees the same data. - Admins get a one-click Refund on top-ups (amount + donor - pre-filled from the event). + contributions, refunds, and fee withdrawals.

    {isSponsored && (
    diff --git a/packages/webapp/src/components/MetricsTab.tsx b/packages/webapp/src/components/MetricsTab.tsx index 2a5dadf..7e3bed6 100644 --- a/packages/webapp/src/components/MetricsTab.tsx +++ b/packages/webapp/src/components/MetricsTab.tsx @@ -67,12 +67,6 @@ export function MetricsTab({

    On-chain metrics

    -

    - Aggregate counters read from the proxy itself. Every write-path - call updates these and emits a{' '} - MetricsUpdated event — - single-source-of-truth for dashboards and off-chain indexers. -

    {unsupported && ( @@ -130,11 +124,6 @@ export function MetricsTab({

    Sponsored activity

    -

    - Subset of the metrics above that went through the sponsor pool - (fully or partially covered by{' '} - sponsorPool). -

    void } -export function ReclaimFromPoolPanel({ proxy, poolBalance, onDone }: Props) { +export function ReclaimFromPoolPanel({ proxy, onDone }: Props) { const [amount, setAmount] = useState('') const [to, setTo] = useState('') const { reclaim, hash, isPending, error, reset } = useReclaimFromPool(proxy) const receipt = useWaitForTransactionReceipt({ hash }) + const { safe } = useSafeAdmin(proxy) + const safePropose = useSafePropose({ safeAddress: safe }) + useEffect(() => { if (receipt.isSuccess) { onDone() @@ -36,16 +42,24 @@ export function ReclaimFromPoolPanel({ proxy, poolBalance, onDone }: Props) { } } + async function onProposeReclaim() { + if (!toValid || !amountValid || !safe) return + safePropose.reset() + try { + await safePropose.propose( + ops.sponsored.reclaimFromPool(proxy, parseEther(amount), to as Address), + ) + } catch (e) { + console.error(e) + } + } + return ( -
    +
    -
    - Counterpart to Fund pool -
    -

    Reclaim from pool

    -

    - Withdraw TRUST you previously funded but that users haven't - spent yet. +

    Reclaim from pool

    +

    + Withdraw unspent TRUST you previously funded.

    @@ -70,27 +84,38 @@ export function ReclaimFromPoolPanel({ proxy, poolBalance, onDone }: Props) { placeholder="1.0" className="input" /> - {poolBalance !== undefined && ( -
    - Pool balance: {formatEther(poolBalance)} TRUST -
    - )} - +
    +
    + + {safe && ( + + )} +
    - {error && ( -

    - {error.message.split('\n')[0]} -

    - )} + + + {error && ( +

    + {error.message.split('\n')[0]} +

    + )} +
    ) } diff --git a/packages/webapp/src/components/SafeProposeFeedback.tsx b/packages/webapp/src/components/SafeProposeFeedback.tsx new file mode 100644 index 0000000..3d95c16 --- /dev/null +++ b/packages/webapp/src/components/SafeProposeFeedback.tsx @@ -0,0 +1,41 @@ +import type { SafeProposeResult } from '../hooks/useSafePropose' + +interface Props { + proposed: SafeProposeResult | null + error: string | null +} + +/** + * Shared success / error feedback block for any panel that uses + * useSafePropose. Renders the safeTxHash + Den link on success, or + * a one-line error if propose failed. Renders nothing in idle state. + */ +export function SafeProposeFeedback({ proposed, error }: Props) { + return ( + <> + {proposed && ( +
    +
    + Proposed. safeTxHash:{' '} + {proposed.safeTxHash} +
    +
    + Owners can co-sign and execute in{' '} + + Den + + . +
    +
    + )} + {error && ( +

    Safe propose: {error}

    + )} + + ) +} diff --git a/packages/webapp/src/components/SetFeesPanel.tsx b/packages/webapp/src/components/SetFeesPanel.tsx index b853bb4..481467f 100644 --- a/packages/webapp/src/components/SetFeesPanel.tsx +++ b/packages/webapp/src/components/SetFeesPanel.tsx @@ -6,6 +6,7 @@ import { ops } from '@intuition-fee-proxy/safe-tx' import { useSetFees } from '../hooks/useProxy' import { useSafeAdmin } from '../hooks/useSafeAdmin' import { useSafePropose } from '../hooks/useSafePropose' +import { SafeProposeFeedback } from './SafeProposeFeedback' interface Props { proxy: Address @@ -146,32 +147,7 @@ export function SetFeesPanel({ proxy, currentFixed, currentPct, onDone }: Props)
    - {safePropose.proposed && ( -
    -
    - Proposed. safeTxHash:{' '} - {safePropose.proposed.safeTxHash} -
    -
    - Owners can co-sign and execute in{' '} - - Den - - . -
    -
    - )} - - {safePropose.error && ( -

    - Safe propose: {safePropose.error} -

    - )} + {error && (

    diff --git a/packages/webapp/src/components/SponsoringTab.tsx b/packages/webapp/src/components/SponsoringTab.tsx index c54980b..66e6973 100644 --- a/packages/webapp/src/components/SponsoringTab.tsx +++ b/packages/webapp/src/components/SponsoringTab.tsx @@ -4,13 +4,13 @@ import { useClaimLimits, usePoolBurnRate, useSponsorPool, + type ClaimLimits, } from '../hooks/useSponsoredProxy' import { formatWindow } from '../lib/format' import { ClaimLimitsPanel } from './ClaimLimitsPanel' import { FundPoolPanel } from './FundPoolPanel' import { PoolHealthBadge } from './PoolHealthBadge' import { ReclaimFromPoolPanel } from './ReclaimFromPoolPanel' -import { Stat } from './Stat' interface Props { proxy: Address @@ -29,50 +29,63 @@ export function SponsoringTab({ proxy, isAdmin }: Props) { } return ( -

    +
    -
    - - - - -
    - - {/* Permissionless — anyone can contribute to the pool. */} - + {isAdmin ? ( <> - + {/* Fund: permissionless. Reclaim: admin-only. Side-by-side, equal height. */} +
    + + +
    ) : ( -

    - Reclaiming pool balance and tuning claim limits is restricted to - whitelisted admins of this proxy. -

    + <> + +

    + Reclaiming pool balance and tuning claim limits is restricted to + whitelisted admins of this proxy. +

    + )}
    ) } + +function ClaimLimitsStrip({ limits }: { limits: ClaimLimits | undefined }) { + const items: { label: string; value: string }[] = [ + { + label: 'Max / tx', + value: limits ? `${formatEther(limits.maxClaimPerTx)} TRUST` : '—', + }, + { + label: 'Max calls / user', + value: limits ? limits.maxClaimsPerWindow.toString() : '—', + }, + { + label: 'Max TRUST / user', + value: limits ? `${formatEther(limits.maxClaimVolumePerWindow)} TRUST` : '—', + }, + { + label: 'Window', + value: limits ? formatWindow(limits.claimWindowSeconds) : '—', + }, + ] + return ( +
    + + Claim limits + + {items.map((it) => ( + + {it.label} + {it.value} + + ))} +
    + ) +} diff --git a/packages/webapp/src/components/UpgradeAuthorityPanel.tsx b/packages/webapp/src/components/UpgradeAuthorityPanel.tsx index dbdfcdb..472f3e8 100644 --- a/packages/webapp/src/components/UpgradeAuthorityPanel.tsx +++ b/packages/webapp/src/components/UpgradeAuthorityPanel.tsx @@ -2,15 +2,19 @@ import { useEffect, useState } from 'react' import { isAddress, type Address } from 'viem' import { useWaitForTransactionReceipt } from 'wagmi' +import { ops } from '@intuition-fee-proxy/safe-tx' import { useAcceptProxyAdmin, useTransferProxyAdmin, } from '../hooks/useVersionedProxy' +import { useSafePropose } from '../hooks/useSafePropose' +import { useSafeStatus } from '../hooks/useSafeStatus' import AddressDisplay from './Address' import { useProxyAdminRotation } from '../hooks/useProxyAdminRotation' import { usePostTxRefreshing } from '../hooks/usePostTxRefreshing' import { ProxyAdminSafeBanner } from './ProxyAdminSafeBanner' import { SafeBadge } from './SafeBadge' +import { SafeProposeFeedback } from './SafeProposeFeedback' import { Spinner } from './Spinner' const ZERO = '0x0000000000000000000000000000000000000000' @@ -49,6 +53,18 @@ export function UpgradeAuthorityPanel({ ) const hasBothRoles = isYou && isConnectedFeeAdmin + // Detect if proxyAdmin is itself a Safe — then we can propose + // transferProxyAdmin / acceptProxyAdmin via that Safe. + const proxyAdminStatus = useSafeStatus(proxyAdmin) + const proxyAdminSafe = proxyAdminStatus.kind === 'safe' ? proxyAdmin : undefined + // Same for the pending admin — useful when the new owner is a Safe + // and needs to acceptProxyAdmin via that Safe's quorum. + const pendingStatus = useSafeStatus(pendingProxyAdmin) + const pendingIsSafe = pendingStatus.kind === 'safe' + const safePropose = useSafePropose({ + safeAddress: proxyAdminSafe ?? (pendingIsSafe ? pendingProxyAdmin : undefined), + }) + // Standalone "Grant Role 1" — separate write instance from the rotation. const [newAdminInput, setNewAdminInput] = useState('') const { @@ -139,26 +155,17 @@ export function UpgradeAuthorityPanel({

    - Only one address can hold this role at a time. - For production, put a Gnosis Safe multisig here — - the Safe itself handles N signers / threshold / signer rotation - internally, so you get “multi-human proxyAdmin” - without the contract knowing anything about it. + Single slot. Controls implementation registration only — fees and + withdrawals are Role 2. Use a Safe for production.

    {acceptedFlash && ( -
    - - ✓ - +
    - You are now proxyAdmin — the transfer has been - finalised on-chain. + You are now proxyAdmin — transfer finalised + on-chain.
    )} @@ -199,10 +206,9 @@ export function UpgradeAuthorityPanel({ )}

    - A transfer has been initiated. The pending address must sign{' '} - acceptProxyAdmin() from - their wallet to finalise. Until then the current admin keeps all - powers and can overwrite the pending candidate. + Pending must call{' '} + acceptProxyAdmin() to + finalise. Current admin can still overwrite.

    {isPendingYou && ( + )} {acceptError && (

    {acceptError.message.split('\n')[0]} @@ -226,11 +249,16 @@ export function UpgradeAuthorityPanel({ )} - {isYou && ( -

    - + {(isYou || proxyAdminSafe) && ( +
    +
    + + + 2-step · target then signs acceptProxyAdmin() + +
    setNewAdminInput(e.target.value)} className="input flex-1 min-w-[18rem] font-mono text-xs" /> - + {isYou && ( + + )} + {proxyAdminSafe && ( + + )}
    {transferError && (

    {transferError.message.split('\n')[0]}

    )} -

    - Grants Role 1 only — the target must then call{' '} - acceptProxyAdmin(). - Fee admin rights (Role 2) are untouched. Use the combined grant - below if you hold both roles. -

    )} - {hasBothRoles && } + {hasBothRoles && ( +
    + + + + Advanced + + + Grant both roles to a single address + + + expand + collapse + +
    + +
    +
    + )} -

    - Role 1 controls which logic the proxy delegates to — - register new implementations, change default version, rename. It{' '} - cannot touch fees, withdrawals, or the sponsor - pool; those are Role 2 below. -

    +
    ) } @@ -305,23 +365,20 @@ function RotateBothRolesForm({ } })() + const stepDone = (s: 'grant' | 'transfer' | 'accept') => { + if (s === 'grant') + return rotation.grantConfirmed || rotation.stage === 'transfer' || rotation.stage === 'done' + if (s === 'transfer') return rotation.stage === 'done' + return false + } + return ( -
    -
    - - Convenience - - - Grant both roles to a single address - -
    +

    - You currently hold both roles. This runs{' '} - setWhitelistedAdmin(new, true){' '} - then transferProxyAdmin(new){' '} - back-to-back (2 signatures). After the new admin calls{' '} - acceptProxyAdmin(), they - can revoke you as fee admin from their wallet. + Two signatures: setWhitelistedAdmin{' '} + then transferProxyAdmin. The + new admin then calls{' '} + acceptProxyAdmin().

    {rotation.stage !== 'complete' && (
    @@ -345,38 +402,24 @@ function RotateBothRolesForm({
    )} {rotation.stage !== 'idle' && rotation.stage !== 'complete' && ( -
      -
    1. - {rotation.grantConfirmed ? '✓ ' : ''}Grant fee admin to new - address (immediate) +
        +
      1. + Grant fee admin (immediate)
      2. -
      3. - {rotation.stage === 'done' ? '✓ ' : ''}Initiate proxyAdmin - transfer (pending until accepted) +
      4. + Transfer proxyAdmin (pending)
      5. -
      6. +
      7. New admin calls{' '} - acceptProxyAdmin(){' '} - (auto-detected) -
      8. -
      9. - (optional) Revoke your old fee admin rights from the new - admin's wallet + acceptProxyAdmin()
      )} {rotation.stage === 'complete' && (
      -

      - ✓ Rotation complete — the new address is now proxyAdmin + fee - admin. You can optionally revoke yourself as fee admin from the - new admin's wallet. +

      + Rotation complete. Optionally revoke your fee admin rights from + the new admin's wallet.

    ) } @@ -301,19 +355,27 @@ export function VersionsPanel({ function VersionRow({ row, isProxyAdmin, + proxyAdminIsSafe, busy, busyLabel, anyBusy, + safeProposing, onPromote, onMakeDefault, + onProposePromote, + onProposeMakeDefault, }: { row: Row isProxyAdmin: boolean + proxyAdminIsSafe: boolean busy: boolean busyLabel: string anyBusy: boolean + safeProposing: boolean onPromote: () => void onMakeDefault: () => void + onProposePromote: () => void + onProposeMakeDefault: () => void }) { const impl = row.impl ?? '—' @@ -353,8 +415,8 @@ function VersionRow({ )} - {isProxyAdmin && ( -
    + {(isProxyAdmin || proxyAdminIsSafe) && ( +
    {row.status.kind === 'default' && ( )} - {row.status.kind === 'registered' && ( + {row.status.kind === 'registered' && isProxyAdmin && ( )} - {row.status.kind === 'available' && ( + {row.status.kind === 'registered' && proxyAdminIsSafe && ( + + )} + {row.status.kind === 'available' && isProxyAdmin && ( )} + {row.status.kind === 'available' && proxyAdminIsSafe && ( + + )}
    )} diff --git a/packages/webapp/src/components/WithdrawPanel.tsx b/packages/webapp/src/components/WithdrawPanel.tsx index b85ef94..82b7fd0 100644 --- a/packages/webapp/src/components/WithdrawPanel.tsx +++ b/packages/webapp/src/components/WithdrawPanel.tsx @@ -2,7 +2,11 @@ import { useEffect, useState } from 'react' import { formatEther, isAddress, parseEther, type Address } from 'viem' import { useAccount, useWaitForTransactionReceipt } from 'wagmi' +import { ops } from '@intuition-fee-proxy/safe-tx' import { useWithdraw } from '../hooks/useProxy' +import { useSafeAdmin } from '../hooks/useSafeAdmin' +import { useSafePropose } from '../hooks/useSafePropose' +import { SafeProposeFeedback } from './SafeProposeFeedback' interface Props { proxy: Address @@ -18,6 +22,9 @@ export function WithdrawPanel({ proxy, accumulated, onDone }: Props) { const { withdraw, hash, isPending, error } = useWithdraw(proxy) const receipt = useWaitForTransactionReceipt({ hash }) + const { safe } = useSafeAdmin(proxy) + const safePropose = useSafePropose({ safeAddress: safe }) + useEffect(() => { if (receipt.isSuccess) onDone() }, [hash, receipt.isSuccess]) @@ -34,12 +41,26 @@ export function WithdrawPanel({ proxy, accumulated, onDone }: Props) { } } + async function onProposeWithdraw() { + if (!toValid || !amountValid || !safe) return + safePropose.reset() + try { + await safePropose.propose( + ops.v2Admin.withdraw(proxy, to as Address, parseEther(amount)), + ) + } catch (e) { + console.error(e) + } + } + return (

    Withdraw fees

    - Pull accumulated fees to any address. Admin-only. + Pull accumulated fees to any address. Admin-only. Direct write + takes effect immediately. Safe propose opens a multisig + transaction for owners to co-sign in Den.

    @@ -88,17 +109,32 @@ export function WithdrawPanel({ proxy, accumulated, onDone }: Props) {
    - +
    + + {safe && ( + + )} +
    {isPending &&

    Confirm in wallet…

    } {receipt.isLoading &&

    Mining…

    } + + + {error && (

    {error.message.split('\n')[0]} diff --git a/packages/webapp/src/pages/Deploy.tsx b/packages/webapp/src/pages/Deploy.tsx index 673965d..b36bc42 100644 --- a/packages/webapp/src/pages/Deploy.tsx +++ b/packages/webapp/src/pages/Deploy.tsx @@ -175,32 +175,39 @@ export default function DeployPage() { const txExplorer = TX_EXPLORER_BY_CHAIN[chainId] const atomPortal = ATOM_PORTAL_BY_CHAIN[chainId] - return ( -

    -
    -

    - Deploy a fee proxy -

    -

    - Configure fees and admins. The proxy is upgradeable via version registry. -

    -
    - - {receipt.isSuccess && newProxyAddress && ( + const isDeploying = isPending || receipt.isLoading + const proxySucceeded = receipt.isSuccess && Boolean(newProxyAddress) + const showResultCard = isDeploying || proxySucceeded + + if (showResultCard) { + const proxyState: 'pending' | 'success' = proxySucceeded ? 'success' : 'pending' + const proxyLabel = proxySucceeded + ? 'Proxy deployed' + : isPending + ? 'Confirm deployment in wallet…' + : 'Mining proxy deployment…' + return ( +
    - {/* Step 1 — Proxy deployment (always green once we reach this card) */} + {/* Step 1 — Proxy deployment (progressive: signing → mining → success) */}
    - -
    - - {newProxyAddress} - - -
    + + {newProxyAddress ? ( +
    + + {newProxyAddress} + + +
    + ) : hash ? ( +
    + tx {hash} +
    + ) : null}
    - {/* Step 2 — Intuition atom (progressive: loading → success/error) */} - {caip10 && ( + {/* Step 2 — Intuition atom (renders only after the proxy lands) */} + {proxySucceeded && caip10 && (
    )} -
    - - Open detail → - - -
    + {proxySucceeded && newProxyAddress && ( +
    + + Open detail → + + +
    + )}
    - )} +
    + ) + } + + return ( +
    +
    +

    + Deploy a fee proxy +

    +

    + Configure fees and admins. The proxy is upgradeable via version registry. +

    +
    {!factory && (
    diff --git a/packages/webapp/src/pages/Docs.tsx b/packages/webapp/src/pages/Docs.tsx index d53a8e3..22b2085 100644 --- a/packages/webapp/src/pages/Docs.tsx +++ b/packages/webapp/src/pages/Docs.tsx @@ -1396,6 +1396,56 @@ await walletClient.writeContract({ value: parseEther('25'), })`} +

    Call deposit() with front-run protection

    +

    + V2's deposit(termId, receiver, amount, maxFeeBps, + maxFixedFee) takes two caller-supplied caps. If the + proxy admin bumps fees between the moment your user signs and + the moment the tx mines, the call reverts with{' '} + FeeExceedsCap instead of charging the inflated + fee. The SDK ships ergonomic helpers so you never have to + hard-code the bytecode MAX_FEE_PERCENTAGE /{' '} + MAX_FIXED_FEE (which would defeat the protection). +

    + {`import { parseEther } from 'viem' +import { + IntuitionFeeProxyV2ABI, + fetchLiveFees, + feeCapsExact, + feeCapsWithBuffer, +} from '@intuition-fee-proxy/sdk' + +// 1. Snapshot live fees just before signing +const live = await fetchLiveFees(client, yourProxyAddress) + +// 2. Pick a strategy: +// - exact = strict, any admin bump in the same block reverts +const caps = feeCapsExact(live) +// - buffer = tolerate small re-pricing (here +10% bumpsallowed) +// const caps = feeCapsWithBuffer(live, 1000n) + +// 3. Splice the caps into your deposit args +await walletClient.writeContract({ + abi: IntuitionFeeProxyV2ABI, + address: yourProxyAddress, + functionName: 'deposit', + args: [ + termId, + receiver, + amount, + caps.maxFeeBps, + caps.maxFixedFee, + ], + value: amount + (amount * caps.maxFeeBps) / 10000n + caps.maxFixedFee, +})`} + + Hard-coding the bytecode maxima is opting out of front-run + protection. The deposit will always succeed even if the admin + spikes fees from 0% to 10% between sign and execute. Use these + helpers (or compute equivalent caps yourself) on every + deposit path. + +

    Canonical versions

    This table is sourced directly from the SDK's{' '} diff --git a/packages/webapp/tsconfig.node.tsbuildinfo b/packages/webapp/tsconfig.node.tsbuildinfo deleted file mode 100644 index 085d3d8..0000000 --- a/packages/webapp/tsconfig.node.tsbuildinfo +++ /dev/null @@ -1 +0,0 @@ -{"fileNames":["../../node_modules/.bun/typescript@5.9.3/node_modules/typescript/lib/lib.d.ts","../../node_modules/.bun/typescript@5.9.3/node_modules/typescript/lib/lib.es5.d.ts","../../node_modules/.bun/typescript@5.9.3/node_modules/typescript/lib/lib.es2015.d.ts","../../node_modules/.bun/typescript@5.9.3/node_modules/typescript/lib/lib.es2016.d.ts","../../node_modules/.bun/typescript@5.9.3/node_modules/typescript/lib/lib.es2017.d.ts","../../node_modules/.bun/typescript@5.9.3/node_modules/typescript/lib/lib.es2018.d.ts","../../node_modules/.bun/typescript@5.9.3/node_modules/typescript/lib/lib.es2019.d.ts","../../node_modules/.bun/typescript@5.9.3/node_modules/typescript/lib/lib.es2020.d.ts","../../node_modules/.bun/typescript@5.9.3/node_modules/typescript/lib/lib.dom.d.ts","../../node_modules/.bun/typescript@5.9.3/node_modules/typescript/lib/lib.webworker.importscripts.d.ts","../../node_modules/.bun/typescript@5.9.3/node_modules/typescript/lib/lib.scripthost.d.ts","../../node_modules/.bun/typescript@5.9.3/node_modules/typescript/lib/lib.es2015.core.d.ts","../../node_modules/.bun/typescript@5.9.3/node_modules/typescript/lib/lib.es2015.collection.d.ts","../../node_modules/.bun/typescript@5.9.3/node_modules/typescript/lib/lib.es2015.generator.d.ts","../../node_modules/.bun/typescript@5.9.3/node_modules/typescript/lib/lib.es2015.iterable.d.ts","../../node_modules/.bun/typescript@5.9.3/node_modules/typescript/lib/lib.es2015.promise.d.ts","../../node_modules/.bun/typescript@5.9.3/node_modules/typescript/lib/lib.es2015.proxy.d.ts","../../node_modules/.bun/typescript@5.9.3/node_modules/typescript/lib/lib.es2015.reflect.d.ts","../../node_modules/.bun/typescript@5.9.3/node_modules/typescript/lib/lib.es2015.symbol.d.ts","../../node_modules/.bun/typescript@5.9.3/node_modules/typescript/lib/lib.es2015.symbol.wellknown.d.ts","../../node_modules/.bun/typescript@5.9.3/node_modules/typescript/lib/lib.es2016.array.include.d.ts","../../node_modules/.bun/typescript@5.9.3/node_modules/typescript/lib/lib.es2016.intl.d.ts","../../node_modules/.bun/typescript@5.9.3/node_modules/typescript/lib/lib.es2017.arraybuffer.d.ts","../../node_modules/.bun/typescript@5.9.3/node_modules/typescript/lib/lib.es2017.date.d.ts","../../node_modules/.bun/typescript@5.9.3/node_modules/typescript/lib/lib.es2017.object.d.ts","../../node_modules/.bun/typescript@5.9.3/node_modules/typescript/lib/lib.es2017.sharedmemory.d.ts","../../node_modules/.bun/typescript@5.9.3/node_modules/typescript/lib/lib.es2017.string.d.ts","../../node_modules/.bun/typescript@5.9.3/node_modules/typescript/lib/lib.es2017.intl.d.ts","../../node_modules/.bun/typescript@5.9.3/node_modules/typescript/lib/lib.es2017.typedarrays.d.ts","../../node_modules/.bun/typescript@5.9.3/node_modules/typescript/lib/lib.es2018.asyncgenerator.d.ts","../../node_modules/.bun/typescript@5.9.3/node_modules/typescript/lib/lib.es2018.asynciterable.d.ts","../../node_modules/.bun/typescript@5.9.3/node_modules/typescript/lib/lib.es2018.intl.d.ts","../../node_modules/.bun/typescript@5.9.3/node_modules/typescript/lib/lib.es2018.promise.d.ts","../../node_modules/.bun/typescript@5.9.3/node_modules/typescript/lib/lib.es2018.regexp.d.ts","../../node_modules/.bun/typescript@5.9.3/node_modules/typescript/lib/lib.es2019.array.d.ts","../../node_modules/.bun/typescript@5.9.3/node_modules/typescript/lib/lib.es2019.object.d.ts","../../node_modules/.bun/typescript@5.9.3/node_modules/typescript/lib/lib.es2019.string.d.ts","../../node_modules/.bun/typescript@5.9.3/node_modules/typescript/lib/lib.es2019.symbol.d.ts","../../node_modules/.bun/typescript@5.9.3/node_modules/typescript/lib/lib.es2019.intl.d.ts","../../node_modules/.bun/typescript@5.9.3/node_modules/typescript/lib/lib.es2020.bigint.d.ts","../../node_modules/.bun/typescript@5.9.3/node_modules/typescript/lib/lib.es2020.date.d.ts","../../node_modules/.bun/typescript@5.9.3/node_modules/typescript/lib/lib.es2020.promise.d.ts","../../node_modules/.bun/typescript@5.9.3/node_modules/typescript/lib/lib.es2020.sharedmemory.d.ts","../../node_modules/.bun/typescript@5.9.3/node_modules/typescript/lib/lib.es2020.string.d.ts","../../node_modules/.bun/typescript@5.9.3/node_modules/typescript/lib/lib.es2020.symbol.wellknown.d.ts","../../node_modules/.bun/typescript@5.9.3/node_modules/typescript/lib/lib.es2020.intl.d.ts","../../node_modules/.bun/typescript@5.9.3/node_modules/typescript/lib/lib.es2020.number.d.ts","../../node_modules/.bun/typescript@5.9.3/node_modules/typescript/lib/lib.decorators.d.ts","../../node_modules/.bun/typescript@5.9.3/node_modules/typescript/lib/lib.decorators.legacy.d.ts","../../node_modules/.bun/@types+node@20.19.39/node_modules/@types/node/compatibility/disposable.d.ts","../../node_modules/.bun/@types+node@20.19.39/node_modules/@types/node/compatibility/indexable.d.ts","../../node_modules/.bun/@types+node@20.19.39/node_modules/@types/node/compatibility/iterators.d.ts","../../node_modules/.bun/@types+node@20.19.39/node_modules/@types/node/compatibility/index.d.ts","../../node_modules/.bun/@types+node@20.19.39/node_modules/@types/node/globals.typedarray.d.ts","../../node_modules/.bun/@types+node@20.19.39/node_modules/@types/node/buffer.buffer.d.ts","../../node_modules/.bun/@types+node@20.19.39/node_modules/@types/node/globals.d.ts","../../node_modules/.bun/@types+node@20.19.39/node_modules/@types/node/web-globals/abortcontroller.d.ts","../../node_modules/.bun/@types+node@20.19.39/node_modules/@types/node/web-globals/domexception.d.ts","../../node_modules/.bun/@types+node@20.19.39/node_modules/@types/node/web-globals/events.d.ts","../../node_modules/.bun/undici-types@6.21.0/node_modules/undici-types/header.d.ts","../../node_modules/.bun/undici-types@6.21.0/node_modules/undici-types/readable.d.ts","../../node_modules/.bun/undici-types@6.21.0/node_modules/undici-types/file.d.ts","../../node_modules/.bun/undici-types@6.21.0/node_modules/undici-types/fetch.d.ts","../../node_modules/.bun/undici-types@6.21.0/node_modules/undici-types/formdata.d.ts","../../node_modules/.bun/undici-types@6.21.0/node_modules/undici-types/connector.d.ts","../../node_modules/.bun/undici-types@6.21.0/node_modules/undici-types/client.d.ts","../../node_modules/.bun/undici-types@6.21.0/node_modules/undici-types/errors.d.ts","../../node_modules/.bun/undici-types@6.21.0/node_modules/undici-types/dispatcher.d.ts","../../node_modules/.bun/undici-types@6.21.0/node_modules/undici-types/global-dispatcher.d.ts","../../node_modules/.bun/undici-types@6.21.0/node_modules/undici-types/global-origin.d.ts","../../node_modules/.bun/undici-types@6.21.0/node_modules/undici-types/pool-stats.d.ts","../../node_modules/.bun/undici-types@6.21.0/node_modules/undici-types/pool.d.ts","../../node_modules/.bun/undici-types@6.21.0/node_modules/undici-types/handlers.d.ts","../../node_modules/.bun/undici-types@6.21.0/node_modules/undici-types/balanced-pool.d.ts","../../node_modules/.bun/undici-types@6.21.0/node_modules/undici-types/agent.d.ts","../../node_modules/.bun/undici-types@6.21.0/node_modules/undici-types/mock-interceptor.d.ts","../../node_modules/.bun/undici-types@6.21.0/node_modules/undici-types/mock-agent.d.ts","../../node_modules/.bun/undici-types@6.21.0/node_modules/undici-types/mock-client.d.ts","../../node_modules/.bun/undici-types@6.21.0/node_modules/undici-types/mock-pool.d.ts","../../node_modules/.bun/undici-types@6.21.0/node_modules/undici-types/mock-errors.d.ts","../../node_modules/.bun/undici-types@6.21.0/node_modules/undici-types/proxy-agent.d.ts","../../node_modules/.bun/undici-types@6.21.0/node_modules/undici-types/env-http-proxy-agent.d.ts","../../node_modules/.bun/undici-types@6.21.0/node_modules/undici-types/retry-handler.d.ts","../../node_modules/.bun/undici-types@6.21.0/node_modules/undici-types/retry-agent.d.ts","../../node_modules/.bun/undici-types@6.21.0/node_modules/undici-types/api.d.ts","../../node_modules/.bun/undici-types@6.21.0/node_modules/undici-types/interceptors.d.ts","../../node_modules/.bun/undici-types@6.21.0/node_modules/undici-types/util.d.ts","../../node_modules/.bun/undici-types@6.21.0/node_modules/undici-types/cookies.d.ts","../../node_modules/.bun/undici-types@6.21.0/node_modules/undici-types/patch.d.ts","../../node_modules/.bun/undici-types@6.21.0/node_modules/undici-types/websocket.d.ts","../../node_modules/.bun/undici-types@6.21.0/node_modules/undici-types/eventsource.d.ts","../../node_modules/.bun/undici-types@6.21.0/node_modules/undici-types/filereader.d.ts","../../node_modules/.bun/undici-types@6.21.0/node_modules/undici-types/diagnostics-channel.d.ts","../../node_modules/.bun/undici-types@6.21.0/node_modules/undici-types/content-type.d.ts","../../node_modules/.bun/undici-types@6.21.0/node_modules/undici-types/cache.d.ts","../../node_modules/.bun/undici-types@6.21.0/node_modules/undici-types/index.d.ts","../../node_modules/.bun/@types+node@20.19.39/node_modules/@types/node/web-globals/fetch.d.ts","../../node_modules/.bun/@types+node@20.19.39/node_modules/@types/node/assert.d.ts","../../node_modules/.bun/@types+node@20.19.39/node_modules/@types/node/assert/strict.d.ts","../../node_modules/.bun/@types+node@20.19.39/node_modules/@types/node/async_hooks.d.ts","../../node_modules/.bun/@types+node@20.19.39/node_modules/@types/node/buffer.d.ts","../../node_modules/.bun/@types+node@20.19.39/node_modules/@types/node/child_process.d.ts","../../node_modules/.bun/@types+node@20.19.39/node_modules/@types/node/cluster.d.ts","../../node_modules/.bun/@types+node@20.19.39/node_modules/@types/node/console.d.ts","../../node_modules/.bun/@types+node@20.19.39/node_modules/@types/node/constants.d.ts","../../node_modules/.bun/@types+node@20.19.39/node_modules/@types/node/crypto.d.ts","../../node_modules/.bun/@types+node@20.19.39/node_modules/@types/node/dgram.d.ts","../../node_modules/.bun/@types+node@20.19.39/node_modules/@types/node/diagnostics_channel.d.ts","../../node_modules/.bun/@types+node@20.19.39/node_modules/@types/node/dns.d.ts","../../node_modules/.bun/@types+node@20.19.39/node_modules/@types/node/dns/promises.d.ts","../../node_modules/.bun/@types+node@20.19.39/node_modules/@types/node/domain.d.ts","../../node_modules/.bun/@types+node@20.19.39/node_modules/@types/node/events.d.ts","../../node_modules/.bun/@types+node@20.19.39/node_modules/@types/node/fs.d.ts","../../node_modules/.bun/@types+node@20.19.39/node_modules/@types/node/fs/promises.d.ts","../../node_modules/.bun/@types+node@20.19.39/node_modules/@types/node/http.d.ts","../../node_modules/.bun/@types+node@20.19.39/node_modules/@types/node/http2.d.ts","../../node_modules/.bun/@types+node@20.19.39/node_modules/@types/node/https.d.ts","../../node_modules/.bun/@types+node@20.19.39/node_modules/@types/node/inspector.generated.d.ts","../../node_modules/.bun/@types+node@20.19.39/node_modules/@types/node/module.d.ts","../../node_modules/.bun/@types+node@20.19.39/node_modules/@types/node/net.d.ts","../../node_modules/.bun/@types+node@20.19.39/node_modules/@types/node/os.d.ts","../../node_modules/.bun/@types+node@20.19.39/node_modules/@types/node/path.d.ts","../../node_modules/.bun/@types+node@20.19.39/node_modules/@types/node/perf_hooks.d.ts","../../node_modules/.bun/@types+node@20.19.39/node_modules/@types/node/process.d.ts","../../node_modules/.bun/@types+node@20.19.39/node_modules/@types/node/punycode.d.ts","../../node_modules/.bun/@types+node@20.19.39/node_modules/@types/node/querystring.d.ts","../../node_modules/.bun/@types+node@20.19.39/node_modules/@types/node/readline.d.ts","../../node_modules/.bun/@types+node@20.19.39/node_modules/@types/node/readline/promises.d.ts","../../node_modules/.bun/@types+node@20.19.39/node_modules/@types/node/repl.d.ts","../../node_modules/.bun/@types+node@20.19.39/node_modules/@types/node/sea.d.ts","../../node_modules/.bun/@types+node@20.19.39/node_modules/@types/node/stream.d.ts","../../node_modules/.bun/@types+node@20.19.39/node_modules/@types/node/stream/promises.d.ts","../../node_modules/.bun/@types+node@20.19.39/node_modules/@types/node/stream/consumers.d.ts","../../node_modules/.bun/@types+node@20.19.39/node_modules/@types/node/stream/web.d.ts","../../node_modules/.bun/@types+node@20.19.39/node_modules/@types/node/string_decoder.d.ts","../../node_modules/.bun/@types+node@20.19.39/node_modules/@types/node/test.d.ts","../../node_modules/.bun/@types+node@20.19.39/node_modules/@types/node/timers.d.ts","../../node_modules/.bun/@types+node@20.19.39/node_modules/@types/node/timers/promises.d.ts","../../node_modules/.bun/@types+node@20.19.39/node_modules/@types/node/tls.d.ts","../../node_modules/.bun/@types+node@20.19.39/node_modules/@types/node/trace_events.d.ts","../../node_modules/.bun/@types+node@20.19.39/node_modules/@types/node/tty.d.ts","../../node_modules/.bun/@types+node@20.19.39/node_modules/@types/node/url.d.ts","../../node_modules/.bun/@types+node@20.19.39/node_modules/@types/node/util.d.ts","../../node_modules/.bun/@types+node@20.19.39/node_modules/@types/node/v8.d.ts","../../node_modules/.bun/@types+node@20.19.39/node_modules/@types/node/vm.d.ts","../../node_modules/.bun/@types+node@20.19.39/node_modules/@types/node/wasi.d.ts","../../node_modules/.bun/@types+node@20.19.39/node_modules/@types/node/worker_threads.d.ts","../../node_modules/.bun/@types+node@20.19.39/node_modules/@types/node/zlib.d.ts","../../node_modules/.bun/@types+node@20.19.39/node_modules/@types/node/index.d.ts","../../node_modules/.bun/@types+estree@1.0.8/node_modules/@types/estree/index.d.ts","../../node_modules/.bun/rollup@4.60.1/node_modules/rollup/dist/rollup.d.ts","../../node_modules/.bun/rollup@4.60.1/node_modules/rollup/dist/parseAst.d.ts","../../node_modules/.bun/vite@5.4.21+f61fc156e9fb716d/node_modules/vite/types/hmrPayload.d.ts","../../node_modules/.bun/vite@5.4.21+f61fc156e9fb716d/node_modules/vite/types/customEvent.d.ts","../../node_modules/.bun/vite@5.4.21+f61fc156e9fb716d/node_modules/vite/types/hot.d.ts","../../node_modules/.bun/vite@5.4.21+f61fc156e9fb716d/node_modules/vite/dist/node/types.d-aGj9QkWt.d.ts","../../node_modules/.bun/esbuild@0.21.5/node_modules/esbuild/lib/main.d.ts","../../node_modules/.bun/source-map-js@1.2.1/node_modules/source-map-js/source-map.d.ts","../../node_modules/.bun/postcss@8.5.10/node_modules/postcss/lib/previous-map.d.ts","../../node_modules/.bun/postcss@8.5.10/node_modules/postcss/lib/input.d.ts","../../node_modules/.bun/postcss@8.5.10/node_modules/postcss/lib/css-syntax-error.d.ts","../../node_modules/.bun/postcss@8.5.10/node_modules/postcss/lib/declaration.d.ts","../../node_modules/.bun/postcss@8.5.10/node_modules/postcss/lib/root.d.ts","../../node_modules/.bun/postcss@8.5.10/node_modules/postcss/lib/warning.d.ts","../../node_modules/.bun/postcss@8.5.10/node_modules/postcss/lib/lazy-result.d.ts","../../node_modules/.bun/postcss@8.5.10/node_modules/postcss/lib/no-work-result.d.ts","../../node_modules/.bun/postcss@8.5.10/node_modules/postcss/lib/processor.d.ts","../../node_modules/.bun/postcss@8.5.10/node_modules/postcss/lib/result.d.ts","../../node_modules/.bun/postcss@8.5.10/node_modules/postcss/lib/document.d.ts","../../node_modules/.bun/postcss@8.5.10/node_modules/postcss/lib/rule.d.ts","../../node_modules/.bun/postcss@8.5.10/node_modules/postcss/lib/node.d.ts","../../node_modules/.bun/postcss@8.5.10/node_modules/postcss/lib/comment.d.ts","../../node_modules/.bun/postcss@8.5.10/node_modules/postcss/lib/container.d.ts","../../node_modules/.bun/postcss@8.5.10/node_modules/postcss/lib/at-rule.d.ts","../../node_modules/.bun/postcss@8.5.10/node_modules/postcss/lib/list.d.ts","../../node_modules/.bun/postcss@8.5.10/node_modules/postcss/lib/postcss.d.ts","../../node_modules/.bun/postcss@8.5.10/node_modules/postcss/lib/postcss.d.mts","../../node_modules/.bun/vite@5.4.21+f61fc156e9fb716d/node_modules/vite/dist/node/runtime.d.ts","../../node_modules/.bun/vite@5.4.21+f61fc156e9fb716d/node_modules/vite/types/importGlob.d.ts","../../node_modules/.bun/vite@5.4.21+f61fc156e9fb716d/node_modules/vite/types/metadata.d.ts","../../node_modules/.bun/vite@5.4.21+f61fc156e9fb716d/node_modules/vite/dist/node/index.d.ts","../../node_modules/.bun/@babel+types@7.29.0/node_modules/@babel/types/lib/index.d.ts","../../node_modules/.bun/@types+babel__generator@7.27.0/node_modules/@types/babel__generator/index.d.ts","../../node_modules/.bun/@babel+parser@7.29.2/node_modules/@babel/parser/typings/babel-parser.d.ts","../../node_modules/.bun/@types+babel__template@7.4.4/node_modules/@types/babel__template/index.d.ts","../../node_modules/.bun/@types+babel__traverse@7.28.0/node_modules/@types/babel__traverse/index.d.ts","../../node_modules/.bun/@types+babel__core@7.20.5/node_modules/@types/babel__core/index.d.ts","../../node_modules/.bun/@vitejs+plugin-react@4.7.0+885654ef1d50a9ee/node_modules/@vitejs/plugin-react/dist/index.d.ts","./vite.config.ts","../../node_modules/.bun/@types+react@18.3.28/node_modules/@types/react/global.d.ts","../../node_modules/.bun/csstype@3.2.3/node_modules/csstype/index.d.ts","../../node_modules/.bun/@types+prop-types@15.7.15/node_modules/@types/prop-types/index.d.ts","../../node_modules/.bun/@types+react@18.3.28/node_modules/@types/react/index.d.ts","../../node_modules/.bun/@types+react-dom@18.3.7+9b6d2b90343c6348/node_modules/@types/react-dom/index.d.ts","../../node_modules/.bun/@types+three@0.169.0/node_modules/@types/three/src/constants.d.ts","../../node_modules/.bun/@types+three@0.169.0/node_modules/@types/three/src/core/Layers.d.ts","../../node_modules/.bun/@types+three@0.169.0/node_modules/@types/three/src/math/Vector2.d.ts","../../node_modules/.bun/@types+three@0.169.0/node_modules/@types/three/src/math/Matrix3.d.ts","../../node_modules/.bun/@types+three@0.169.0/node_modules/@types/three/src/core/BufferAttribute.d.ts","../../node_modules/.bun/@types+three@0.169.0/node_modules/@types/three/src/core/InterleavedBuffer.d.ts","../../node_modules/.bun/@types+three@0.169.0/node_modules/@types/three/src/core/InterleavedBufferAttribute.d.ts","../../node_modules/.bun/@types+three@0.169.0/node_modules/@types/three/src/math/Quaternion.d.ts","../../node_modules/.bun/@types+three@0.169.0/node_modules/@types/three/src/math/Euler.d.ts","../../node_modules/.bun/@types+three@0.169.0/node_modules/@types/three/src/math/Matrix4.d.ts","../../node_modules/.bun/@types+three@0.169.0/node_modules/@types/three/src/math/Vector4.d.ts","../../node_modules/.bun/@types+three@0.169.0/node_modules/@types/three/src/cameras/Camera.d.ts","../../node_modules/.bun/@types+three@0.169.0/node_modules/@types/three/src/math/ColorManagement.d.ts","../../node_modules/.bun/@types+three@0.169.0/node_modules/@types/three/src/math/Color.d.ts","../../node_modules/.bun/@types+three@0.169.0/node_modules/@types/three/src/math/Cylindrical.d.ts","../../node_modules/.bun/@types+three@0.169.0/node_modules/@types/three/src/math/Spherical.d.ts","../../node_modules/.bun/@types+three@0.169.0/node_modules/@types/three/src/math/Vector3.d.ts","../../node_modules/.bun/@types+three@0.169.0/node_modules/@types/three/src/objects/Bone.d.ts","../../node_modules/.bun/@types+three@0.169.0/node_modules/@types/three/src/math/Interpolant.d.ts","../../node_modules/.bun/@types+three@0.169.0/node_modules/@types/three/src/math/interpolants/CubicInterpolant.d.ts","../../node_modules/.bun/@types+three@0.169.0/node_modules/@types/three/src/math/interpolants/DiscreteInterpolant.d.ts","../../node_modules/.bun/@types+three@0.169.0/node_modules/@types/three/src/math/interpolants/LinearInterpolant.d.ts","../../node_modules/.bun/@types+three@0.169.0/node_modules/@types/three/src/animation/KeyframeTrack.d.ts","../../node_modules/.bun/@types+three@0.169.0/node_modules/@types/three/src/animation/AnimationClip.d.ts","../../node_modules/.bun/@types+three@0.169.0/node_modules/@types/three/src/extras/core/Curve.d.ts","../../node_modules/.bun/@types+three@0.169.0/node_modules/@types/three/src/extras/core/CurvePath.d.ts","../../node_modules/.bun/@types+three@0.169.0/node_modules/@types/three/src/extras/core/Path.d.ts","../../node_modules/.bun/@types+three@0.169.0/node_modules/@types/three/src/extras/core/Shape.d.ts","../../node_modules/.bun/@types+three@0.169.0/node_modules/@types/three/src/math/Line3.d.ts","../../node_modules/.bun/@types+three@0.169.0/node_modules/@types/three/src/math/Sphere.d.ts","../../node_modules/.bun/@types+three@0.169.0/node_modules/@types/three/src/math/Plane.d.ts","../../node_modules/.bun/@types+three@0.169.0/node_modules/@types/three/src/math/Triangle.d.ts","../../node_modules/.bun/@types+three@0.169.0/node_modules/@types/three/src/math/Box3.d.ts","../../node_modules/.bun/@types+three@0.169.0/node_modules/@types/three/src/core/EventDispatcher.d.ts","../../node_modules/.bun/@types+three@0.169.0/node_modules/@types/three/src/core/GLBufferAttribute.d.ts","../../node_modules/.bun/@types+three@0.169.0/node_modules/@types/three/src/core/BufferGeometry.d.ts","../../node_modules/.bun/@types+three@0.169.0/node_modules/@types/three/src/objects/Group.d.ts","../../node_modules/.bun/@types+three@0.169.0/node_modules/@types/three/src/textures/CompressedTexture.d.ts","../../node_modules/.bun/@types+three@0.169.0/node_modules/@types/three/src/textures/CubeTexture.d.ts","../../node_modules/.bun/@types+three@0.169.0/node_modules/@types/three/src/textures/Source.d.ts","../../node_modules/.bun/@types+three@0.169.0/node_modules/@types/three/src/textures/Texture.d.ts","../../node_modules/.bun/@types+three@0.169.0/node_modules/@types/three/src/materials/LineBasicMaterial.d.ts","../../node_modules/.bun/@types+three@0.169.0/node_modules/@types/three/src/materials/LineDashedMaterial.d.ts","../../node_modules/.bun/@types+three@0.169.0/node_modules/@types/three/src/materials/MeshBasicMaterial.d.ts","../../node_modules/.bun/@types+three@0.169.0/node_modules/@types/three/src/materials/MeshDepthMaterial.d.ts","../../node_modules/.bun/@types+three@0.169.0/node_modules/@types/three/src/materials/MeshDistanceMaterial.d.ts","../../node_modules/.bun/@types+three@0.169.0/node_modules/@types/three/src/materials/MeshLambertMaterial.d.ts","../../node_modules/.bun/@types+three@0.169.0/node_modules/@types/three/src/materials/MeshMatcapMaterial.d.ts","../../node_modules/.bun/@types+three@0.169.0/node_modules/@types/three/src/materials/MeshNormalMaterial.d.ts","../../node_modules/.bun/@types+three@0.169.0/node_modules/@types/three/src/materials/MeshPhongMaterial.d.ts","../../node_modules/.bun/@types+three@0.169.0/node_modules/@types/three/src/materials/MeshStandardMaterial.d.ts","../../node_modules/.bun/@types+three@0.169.0/node_modules/@types/three/src/materials/MeshPhysicalMaterial.d.ts","../../node_modules/.bun/@types+three@0.169.0/node_modules/@types/three/src/materials/MeshToonMaterial.d.ts","../../node_modules/.bun/@types+three@0.169.0/node_modules/@types/three/src/materials/PointsMaterial.d.ts","../../node_modules/.bun/@types+three@0.169.0/node_modules/@types/three/src/core/Uniform.d.ts","../../node_modules/.bun/@types+three@0.169.0/node_modules/@types/three/src/core/UniformsGroup.d.ts","../../node_modules/.bun/@types+three@0.169.0/node_modules/@types/three/src/renderers/shaders/UniformsLib.d.ts","../../node_modules/.bun/@types+three@0.169.0/node_modules/@types/three/src/materials/ShaderMaterial.d.ts","../../node_modules/.bun/@types+three@0.169.0/node_modules/@types/three/src/materials/RawShaderMaterial.d.ts","../../node_modules/.bun/@types+three@0.169.0/node_modules/@types/three/src/materials/ShadowMaterial.d.ts","../../node_modules/.bun/@types+three@0.169.0/node_modules/@types/three/src/materials/SpriteMaterial.d.ts","../../node_modules/.bun/@types+three@0.169.0/node_modules/@types/three/src/materials/Materials.d.ts","../../node_modules/.bun/@types+three@0.169.0/node_modules/@types/three/src/objects/Sprite.d.ts","../../node_modules/.bun/@types+three@0.169.0/node_modules/@types/three/src/math/Frustum.d.ts","../../node_modules/.bun/@types+three@0.169.0/node_modules/@types/three/src/textures/DepthTexture.d.ts","../../node_modules/.bun/@types+three@0.169.0/node_modules/@types/three/src/core/RenderTarget.d.ts","../../node_modules/.bun/@types+three@0.169.0/node_modules/@types/three/src/renderers/WebGLRenderTarget.d.ts","../../node_modules/.bun/@types+three@0.169.0/node_modules/@types/three/src/lights/LightShadow.d.ts","../../node_modules/.bun/@types+three@0.169.0/node_modules/@types/three/src/lights/Light.d.ts","../../node_modules/.bun/@types+three@0.169.0/node_modules/@types/three/src/scenes/Fog.d.ts","../../node_modules/.bun/@types+three@0.169.0/node_modules/@types/three/src/scenes/FogExp2.d.ts","../../node_modules/.bun/@types+three@0.169.0/node_modules/@types/three/src/scenes/Scene.d.ts","../../node_modules/.bun/@types+three@0.169.0/node_modules/@types/three/src/math/Box2.d.ts","../../node_modules/.bun/@types+three@0.169.0/node_modules/@types/three/src/textures/types.d.ts","../../node_modules/.bun/@types+three@0.169.0/node_modules/@types/three/src/textures/Data3DTexture.d.ts","../../node_modules/.bun/@types+three@0.169.0/node_modules/@types/three/src/textures/DataArrayTexture.d.ts","../../node_modules/.bun/@types+three@0.169.0/node_modules/@types/three/src/renderers/webgl/WebGLCapabilities.d.ts","../../node_modules/.bun/@types+three@0.169.0/node_modules/@types/three/src/renderers/webgl/WebGLExtensions.d.ts","../../node_modules/.bun/@types+three@0.169.0/node_modules/@types/three/src/renderers/webgl/WebGLProperties.d.ts","../../node_modules/.bun/@types+three@0.169.0/node_modules/@types/three/src/renderers/webgl/WebGLState.d.ts","../../node_modules/.bun/@types+three@0.169.0/node_modules/@types/three/src/renderers/webgl/WebGLUtils.d.ts","../../node_modules/.bun/@types+three@0.169.0/node_modules/@types/three/src/renderers/webgl/WebGLTextures.d.ts","../../node_modules/.bun/@types+three@0.169.0/node_modules/@types/three/src/renderers/webgl/WebGLUniforms.d.ts","../../node_modules/.bun/@types+three@0.169.0/node_modules/@types/three/src/renderers/webgl/WebGLProgram.d.ts","../../node_modules/.bun/@types+three@0.169.0/node_modules/@types/three/src/renderers/webgl/WebGLInfo.d.ts","../../node_modules/.bun/@types+three@0.169.0/node_modules/@types/three/src/renderers/webgl/WebGLRenderLists.d.ts","../../node_modules/.bun/@types+three@0.169.0/node_modules/@types/three/src/renderers/webgl/WebGLObjects.d.ts","../../node_modules/.bun/@types+three@0.169.0/node_modules/@types/three/src/renderers/webgl/WebGLShadowMap.d.ts","../../node_modules/.bun/@types+webxr@0.5.24/node_modules/@types/webxr/index.d.ts","../../node_modules/.bun/@types+three@0.169.0/node_modules/@types/three/src/cameras/PerspectiveCamera.d.ts","../../node_modules/.bun/@types+three@0.169.0/node_modules/@types/three/src/cameras/ArrayCamera.d.ts","../../node_modules/.bun/@types+three@0.169.0/node_modules/@types/three/src/objects/Mesh.d.ts","../../node_modules/.bun/@types+three@0.169.0/node_modules/@types/three/src/renderers/webxr/WebXRController.d.ts","../../node_modules/.bun/@types+three@0.169.0/node_modules/@types/three/src/renderers/webxr/WebXRManager.d.ts","../../node_modules/.bun/@types+three@0.169.0/node_modules/@types/three/src/renderers/WebGLRenderer.d.ts","../../node_modules/.bun/@types+three@0.169.0/node_modules/@types/three/src/renderers/webgl/WebGLAttributes.d.ts","../../node_modules/.bun/@types+three@0.169.0/node_modules/@types/three/src/renderers/webgl/WebGLBindingStates.d.ts","../../node_modules/.bun/@types+three@0.169.0/node_modules/@types/three/src/renderers/webgl/WebGLClipping.d.ts","../../node_modules/.bun/@types+three@0.169.0/node_modules/@types/three/src/renderers/webgl/WebGLCubeMaps.d.ts","../../node_modules/.bun/@types+three@0.169.0/node_modules/@types/three/src/renderers/webgl/WebGLLights.d.ts","../../node_modules/.bun/@types+three@0.169.0/node_modules/@types/three/src/renderers/webgl/WebGLPrograms.d.ts","../../node_modules/.bun/@types+three@0.169.0/node_modules/@types/three/src/materials/Material.d.ts","../../node_modules/.bun/@types+three@0.169.0/node_modules/@types/three/src/textures/DataTexture.d.ts","../../node_modules/.bun/@types+three@0.169.0/node_modules/@types/three/src/objects/Skeleton.d.ts","../../node_modules/.bun/@types+three@0.169.0/node_modules/@types/three/src/math/Ray.d.ts","../../node_modules/.bun/@types+three@0.169.0/node_modules/@types/three/src/core/Raycaster.d.ts","../../node_modules/.bun/@types+three@0.169.0/node_modules/@types/three/src/core/Object3D.d.ts","../../node_modules/.bun/@types+three@0.169.0/node_modules/@types/three/src/animation/AnimationObjectGroup.d.ts","../../node_modules/.bun/@types+three@0.169.0/node_modules/@types/three/src/animation/AnimationMixer.d.ts","../../node_modules/.bun/@types+three@0.169.0/node_modules/@types/three/src/animation/AnimationAction.d.ts","../../node_modules/.bun/@types+three@0.169.0/node_modules/@types/three/src/animation/AnimationUtils.d.ts","../../node_modules/.bun/@types+three@0.169.0/node_modules/@types/three/src/animation/PropertyBinding.d.ts","../../node_modules/.bun/@types+three@0.169.0/node_modules/@types/three/src/animation/PropertyMixer.d.ts","../../node_modules/.bun/@types+three@0.169.0/node_modules/@types/three/src/animation/tracks/BooleanKeyframeTrack.d.ts","../../node_modules/.bun/@types+three@0.169.0/node_modules/@types/three/src/animation/tracks/ColorKeyframeTrack.d.ts","../../node_modules/.bun/@types+three@0.169.0/node_modules/@types/three/src/animation/tracks/NumberKeyframeTrack.d.ts","../../node_modules/.bun/@types+three@0.169.0/node_modules/@types/three/src/animation/tracks/QuaternionKeyframeTrack.d.ts","../../node_modules/.bun/@types+three@0.169.0/node_modules/@types/three/src/animation/tracks/StringKeyframeTrack.d.ts","../../node_modules/.bun/@types+three@0.169.0/node_modules/@types/three/src/animation/tracks/VectorKeyframeTrack.d.ts","../../node_modules/.bun/@types+three@0.169.0/node_modules/@types/three/src/audio/AudioContext.d.ts","../../node_modules/.bun/@types+three@0.169.0/node_modules/@types/three/src/audio/AudioListener.d.ts","../../node_modules/.bun/@types+three@0.169.0/node_modules/@types/three/src/audio/Audio.d.ts","../../node_modules/.bun/@types+three@0.169.0/node_modules/@types/three/src/audio/AudioAnalyser.d.ts","../../node_modules/.bun/@types+three@0.169.0/node_modules/@types/three/src/audio/PositionalAudio.d.ts","../../node_modules/.bun/@types+three@0.169.0/node_modules/@types/three/src/renderers/WebGLCubeRenderTarget.d.ts","../../node_modules/.bun/@types+three@0.169.0/node_modules/@types/three/src/cameras/CubeCamera.d.ts","../../node_modules/.bun/@types+three@0.169.0/node_modules/@types/three/src/cameras/OrthographicCamera.d.ts","../../node_modules/.bun/@types+three@0.169.0/node_modules/@types/three/src/cameras/StereoCamera.d.ts","../../node_modules/.bun/@types+three@0.169.0/node_modules/@types/three/src/core/Clock.d.ts","../../node_modules/.bun/@types+three@0.169.0/node_modules/@types/three/src/core/InstancedBufferAttribute.d.ts","../../node_modules/.bun/@types+three@0.169.0/node_modules/@types/three/src/core/InstancedBufferGeometry.d.ts","../../node_modules/.bun/@types+three@0.169.0/node_modules/@types/three/src/core/InstancedInterleavedBuffer.d.ts","../../node_modules/.bun/@types+three@0.169.0/node_modules/@types/three/src/extras/Controls.d.ts","../../node_modules/.bun/@types+three@0.169.0/node_modules/@types/three/src/extras/core/ShapePath.d.ts","../../node_modules/.bun/@types+three@0.169.0/node_modules/@types/three/src/extras/curves/EllipseCurve.d.ts","../../node_modules/.bun/@types+three@0.169.0/node_modules/@types/three/src/extras/curves/ArcCurve.d.ts","../../node_modules/.bun/@types+three@0.169.0/node_modules/@types/three/src/extras/curves/CatmullRomCurve3.d.ts","../../node_modules/.bun/@types+three@0.169.0/node_modules/@types/three/src/extras/curves/CubicBezierCurve.d.ts","../../node_modules/.bun/@types+three@0.169.0/node_modules/@types/three/src/extras/curves/CubicBezierCurve3.d.ts","../../node_modules/.bun/@types+three@0.169.0/node_modules/@types/three/src/extras/curves/LineCurve.d.ts","../../node_modules/.bun/@types+three@0.169.0/node_modules/@types/three/src/extras/curves/LineCurve3.d.ts","../../node_modules/.bun/@types+three@0.169.0/node_modules/@types/three/src/extras/curves/QuadraticBezierCurve.d.ts","../../node_modules/.bun/@types+three@0.169.0/node_modules/@types/three/src/extras/curves/QuadraticBezierCurve3.d.ts","../../node_modules/.bun/@types+three@0.169.0/node_modules/@types/three/src/extras/curves/SplineCurve.d.ts","../../node_modules/.bun/@types+three@0.169.0/node_modules/@types/three/src/extras/curves/Curves.d.ts","../../node_modules/.bun/@types+three@0.169.0/node_modules/@types/three/src/extras/DataUtils.d.ts","../../node_modules/.bun/@types+three@0.169.0/node_modules/@types/three/src/extras/ImageUtils.d.ts","../../node_modules/.bun/@types+three@0.169.0/node_modules/@types/three/src/extras/PMREMGenerator.d.ts","../../node_modules/.bun/@types+three@0.169.0/node_modules/@types/three/src/extras/ShapeUtils.d.ts","../../node_modules/.bun/@types+three@0.169.0/node_modules/@types/three/src/extras/TextureUtils.d.ts","../../node_modules/.bun/@types+three@0.169.0/node_modules/@types/three/src/geometries/BoxGeometry.d.ts","../../node_modules/.bun/@types+three@0.169.0/node_modules/@types/three/src/geometries/CapsuleGeometry.d.ts","../../node_modules/.bun/@types+three@0.169.0/node_modules/@types/three/src/geometries/CircleGeometry.d.ts","../../node_modules/.bun/@types+three@0.169.0/node_modules/@types/three/src/geometries/CylinderGeometry.d.ts","../../node_modules/.bun/@types+three@0.169.0/node_modules/@types/three/src/geometries/ConeGeometry.d.ts","../../node_modules/.bun/@types+three@0.169.0/node_modules/@types/three/src/geometries/PolyhedronGeometry.d.ts","../../node_modules/.bun/@types+three@0.169.0/node_modules/@types/three/src/geometries/DodecahedronGeometry.d.ts","../../node_modules/.bun/@types+three@0.169.0/node_modules/@types/three/src/geometries/EdgesGeometry.d.ts","../../node_modules/.bun/@types+three@0.169.0/node_modules/@types/three/src/geometries/ExtrudeGeometry.d.ts","../../node_modules/.bun/@types+three@0.169.0/node_modules/@types/three/src/geometries/IcosahedronGeometry.d.ts","../../node_modules/.bun/@types+three@0.169.0/node_modules/@types/three/src/geometries/LatheGeometry.d.ts","../../node_modules/.bun/@types+three@0.169.0/node_modules/@types/three/src/geometries/OctahedronGeometry.d.ts","../../node_modules/.bun/@types+three@0.169.0/node_modules/@types/three/src/geometries/PlaneGeometry.d.ts","../../node_modules/.bun/@types+three@0.169.0/node_modules/@types/three/src/geometries/RingGeometry.d.ts","../../node_modules/.bun/@types+three@0.169.0/node_modules/@types/three/src/geometries/ShapeGeometry.d.ts","../../node_modules/.bun/@types+three@0.169.0/node_modules/@types/three/src/geometries/SphereGeometry.d.ts","../../node_modules/.bun/@types+three@0.169.0/node_modules/@types/three/src/geometries/TetrahedronGeometry.d.ts","../../node_modules/.bun/@types+three@0.169.0/node_modules/@types/three/src/geometries/TorusGeometry.d.ts","../../node_modules/.bun/@types+three@0.169.0/node_modules/@types/three/src/geometries/TorusKnotGeometry.d.ts","../../node_modules/.bun/@types+three@0.169.0/node_modules/@types/three/src/geometries/TubeGeometry.d.ts","../../node_modules/.bun/@types+three@0.169.0/node_modules/@types/three/src/geometries/WireframeGeometry.d.ts","../../node_modules/.bun/@types+three@0.169.0/node_modules/@types/three/src/geometries/Geometries.d.ts","../../node_modules/.bun/@types+three@0.169.0/node_modules/@types/three/src/objects/Line.d.ts","../../node_modules/.bun/@types+three@0.169.0/node_modules/@types/three/src/helpers/ArrowHelper.d.ts","../../node_modules/.bun/@types+three@0.169.0/node_modules/@types/three/src/objects/LineSegments.d.ts","../../node_modules/.bun/@types+three@0.169.0/node_modules/@types/three/src/helpers/AxesHelper.d.ts","../../node_modules/.bun/@types+three@0.169.0/node_modules/@types/three/src/helpers/Box3Helper.d.ts","../../node_modules/.bun/@types+three@0.169.0/node_modules/@types/three/src/helpers/BoxHelper.d.ts","../../node_modules/.bun/@types+three@0.169.0/node_modules/@types/three/src/helpers/CameraHelper.d.ts","../../node_modules/.bun/@types+three@0.169.0/node_modules/@types/three/src/lights/DirectionalLightShadow.d.ts","../../node_modules/.bun/@types+three@0.169.0/node_modules/@types/three/src/lights/DirectionalLight.d.ts","../../node_modules/.bun/@types+three@0.169.0/node_modules/@types/three/src/helpers/DirectionalLightHelper.d.ts","../../node_modules/.bun/@types+three@0.169.0/node_modules/@types/three/src/helpers/GridHelper.d.ts","../../node_modules/.bun/@types+three@0.169.0/node_modules/@types/three/src/lights/HemisphereLight.d.ts","../../node_modules/.bun/@types+three@0.169.0/node_modules/@types/three/src/helpers/HemisphereLightHelper.d.ts","../../node_modules/.bun/@types+three@0.169.0/node_modules/@types/three/src/helpers/PlaneHelper.d.ts","../../node_modules/.bun/@types+three@0.169.0/node_modules/@types/three/src/lights/PointLightShadow.d.ts","../../node_modules/.bun/@types+three@0.169.0/node_modules/@types/three/src/lights/PointLight.d.ts","../../node_modules/.bun/@types+three@0.169.0/node_modules/@types/three/src/helpers/PointLightHelper.d.ts","../../node_modules/.bun/@types+three@0.169.0/node_modules/@types/three/src/helpers/PolarGridHelper.d.ts","../../node_modules/.bun/@types+three@0.169.0/node_modules/@types/three/src/objects/SkinnedMesh.d.ts","../../node_modules/.bun/@types+three@0.169.0/node_modules/@types/three/src/helpers/SkeletonHelper.d.ts","../../node_modules/.bun/@types+three@0.169.0/node_modules/@types/three/src/helpers/SpotLightHelper.d.ts","../../node_modules/.bun/@types+three@0.169.0/node_modules/@types/three/src/lights/AmbientLight.d.ts","../../node_modules/.bun/@types+three@0.169.0/node_modules/@types/three/src/math/SphericalHarmonics3.d.ts","../../node_modules/.bun/@types+three@0.169.0/node_modules/@types/three/src/lights/LightProbe.d.ts","../../node_modules/.bun/@types+three@0.169.0/node_modules/@types/three/src/lights/RectAreaLight.d.ts","../../node_modules/.bun/@types+three@0.169.0/node_modules/@types/three/src/lights/SpotLightShadow.d.ts","../../node_modules/.bun/@types+three@0.169.0/node_modules/@types/three/src/lights/SpotLight.d.ts","../../node_modules/.bun/@types+three@0.169.0/node_modules/@types/three/src/loaders/LoadingManager.d.ts","../../node_modules/.bun/@types+three@0.169.0/node_modules/@types/three/src/loaders/Loader.d.ts","../../node_modules/.bun/@types+three@0.169.0/node_modules/@types/three/src/loaders/AnimationLoader.d.ts","../../node_modules/.bun/@types+three@0.169.0/node_modules/@types/three/src/loaders/AudioLoader.d.ts","../../node_modules/.bun/@types+three@0.169.0/node_modules/@types/three/src/loaders/BufferGeometryLoader.d.ts","../../node_modules/.bun/@types+three@0.169.0/node_modules/@types/three/src/loaders/Cache.d.ts","../../node_modules/.bun/@types+three@0.169.0/node_modules/@types/three/src/loaders/CompressedTextureLoader.d.ts","../../node_modules/.bun/@types+three@0.169.0/node_modules/@types/three/src/loaders/CubeTextureLoader.d.ts","../../node_modules/.bun/@types+three@0.169.0/node_modules/@types/three/src/loaders/DataTextureLoader.d.ts","../../node_modules/.bun/@types+three@0.169.0/node_modules/@types/three/src/loaders/FileLoader.d.ts","../../node_modules/.bun/@types+three@0.169.0/node_modules/@types/three/src/loaders/ImageBitmapLoader.d.ts","../../node_modules/.bun/@types+three@0.169.0/node_modules/@types/three/src/loaders/ImageLoader.d.ts","../../node_modules/.bun/@types+three@0.169.0/node_modules/@types/three/src/loaders/LoaderUtils.d.ts","../../node_modules/.bun/@types+three@0.169.0/node_modules/@types/three/src/loaders/MaterialLoader.d.ts","../../node_modules/.bun/@types+three@0.169.0/node_modules/@types/three/src/loaders/ObjectLoader.d.ts","../../node_modules/.bun/@types+three@0.169.0/node_modules/@types/three/src/loaders/TextureLoader.d.ts","../../node_modules/.bun/@types+three@0.169.0/node_modules/@types/three/src/math/interpolants/QuaternionLinearInterpolant.d.ts","../../node_modules/.bun/@types+three@0.169.0/node_modules/@types/three/src/math/MathUtils.d.ts","../../node_modules/.bun/@types+three@0.169.0/node_modules/@types/three/src/math/Matrix2.d.ts","../../node_modules/.bun/@types+three@0.169.0/node_modules/@types/three/src/objects/BatchedMesh.d.ts","../../node_modules/.bun/@types+three@0.169.0/node_modules/@types/three/src/objects/InstancedMesh.d.ts","../../node_modules/.bun/@types+three@0.169.0/node_modules/@types/three/src/objects/LineLoop.d.ts","../../node_modules/.bun/@types+three@0.169.0/node_modules/@types/three/src/objects/LOD.d.ts","../../node_modules/.bun/@types+three@0.169.0/node_modules/@types/three/src/objects/Points.d.ts","../../node_modules/.bun/@types+three@0.169.0/node_modules/@types/three/src/renderers/shaders/ShaderChunk.d.ts","../../node_modules/.bun/@types+three@0.169.0/node_modules/@types/three/src/renderers/shaders/ShaderLib.d.ts","../../node_modules/.bun/@types+three@0.169.0/node_modules/@types/three/src/renderers/shaders/UniformsUtils.d.ts","../../node_modules/.bun/@types+three@0.169.0/node_modules/@types/three/src/renderers/webgl/WebGLBufferRenderer.d.ts","../../node_modules/.bun/@types+three@0.169.0/node_modules/@types/three/src/renderers/webgl/WebGLCubeUVMaps.d.ts","../../node_modules/.bun/@types+three@0.169.0/node_modules/@types/three/src/renderers/webgl/WebGLGeometries.d.ts","../../node_modules/.bun/@types+three@0.169.0/node_modules/@types/three/src/renderers/webgl/WebGLIndexedBufferRenderer.d.ts","../../node_modules/.bun/@types+three@0.169.0/node_modules/@types/three/src/renderers/webgl/WebGLShader.d.ts","../../node_modules/.bun/@types+three@0.169.0/node_modules/@types/three/src/renderers/WebGL3DRenderTarget.d.ts","../../node_modules/.bun/@types+three@0.169.0/node_modules/@types/three/src/renderers/WebGLArrayRenderTarget.d.ts","../../node_modules/.bun/@types+three@0.169.0/node_modules/@types/three/src/renderers/webxr/WebXRDepthSensing.d.ts","../../node_modules/.bun/@types+three@0.169.0/node_modules/@types/three/src/textures/CanvasTexture.d.ts","../../node_modules/.bun/@types+three@0.169.0/node_modules/@types/three/src/textures/CompressedArrayTexture.d.ts","../../node_modules/.bun/@types+three@0.169.0/node_modules/@types/three/src/textures/CompressedCubeTexture.d.ts","../../node_modules/.bun/@types+three@0.169.0/node_modules/@types/three/src/textures/FramebufferTexture.d.ts","../../node_modules/.bun/@types+three@0.169.0/node_modules/@types/three/src/textures/VideoTexture.d.ts","../../node_modules/.bun/@types+three@0.169.0/node_modules/@types/three/src/Three.Legacy.d.ts","../../node_modules/.bun/@types+three@0.169.0/node_modules/@types/three/src/utils.d.ts","../../node_modules/.bun/@types+three@0.169.0/node_modules/@types/three/src/Three.d.ts","../../node_modules/.bun/@types+three@0.169.0/node_modules/@types/three/index.d.ts"],"fileIdsList":[[55,101,182],[55,101],[55,101,182,183,184,185,186],[55,101,182,184],[55,98,101],[55,100,101],[101],[55,101,106,134],[55,101,102,107,112,120,131,142],[55,101,102,103,112,120],[50,51,52,55,101],[55,101,104,143],[55,101,105,106,113,121],[55,101,106,131,139],[55,101,107,109,112,120],[55,100,101,108],[55,101,109,110],[55,101,111,112],[55,100,101,112],[55,101,112,113,114,131,142],[55,101,112,113,114,127,131,134],[55,101,109,112,115,120,131,142],[55,101,112,113,115,116,120,131,139,142],[55,101,115,117,131,139,142],[53,54,55,56,57,58,59,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148],[55,101,112,118],[55,101,119,142,147],[55,101,109,112,120,131],[55,101,121],[55,101,122],[55,100,101,123],[55,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148],[55,101,125],[55,101,126],[55,101,112,127,128],[55,101,127,129,143,145],[55,101,112,131,132,134],[55,101,133,134],[55,101,131,132],[55,101,134],[55,101,135],[55,98,101,131,136],[55,101,112,137,138],[55,101,137,138],[55,101,106,120,131,139],[55,101,140],[55,101,120,141],[55,101,115,126,142],[55,101,106,143],[55,101,131,144],[55,101,119,145],[55,101,146],[55,96,101],[55,96,101,112,114,123,131,134,142,145,147],[55,101,131,148],[55,101,193],[55,101,190,191,192],[55,101,436],[55,101,235,260,261],[55,101,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,224,225,226,227,228,229,230,231,232,233,234,235,249,250,251,256,257,258,259,260,261,262,263,264,265,266,267,269,270,271,272,273,274,275,276,277,278,279,280,281,282,284,285,286,287,288,289,290,291,292,293,294,295,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,339,340,341,342,343,344,366,367,368,369,370,371,372,373,374,375,376,377,378,379,380,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,400,401,402,403,404,405,406,407,408,409,410,411,412,413,414,415,416,417,418,419,420,421,422,423,424,425,426,427,428,429,430,431,432,433,434,435],[55,101,195,218,301,303],[55,101,195,211,212,217],[55,101,195,218,228,301,302,304],[55,101,218],[55,101,195,213,214,215,216],[55,101,217],[55,101,195,217],[55,101,301,314,315],[55,101,316],[55,101,301,314],[55,101,315,316],[55,101,284],[55,101,195,196,204,205,211,301],[55,101,195,289,301,319],[55,101,206,301],[55,101,197,206,301],[55,101,206,284],[55,101,195,198,204],[55,101,197,199,201,202,204,211,224,227,228,229],[55,101,199],[55,101,230],[55,101,199,200],[55,101,195,199,201],[55,101,198,199,200,204],[55,101,196,198,202,203,204,206,211,218,222,228,230,231,234,235,266,289,296,298,300],[55,101,196,197,206,211,287,299,301],[55,101,195,205,228,235,259],[55,101,195,228,249],[55,101,228,301],[55,101,233,235,261,266,289],[55,101,197],[55,101,195,235],[55,101,197,211],[55,101,197,211,219],[55,101,197,220],[55,101,197,221],[55,101,197,208,221,222],[55,101,329],[55,101,211,219],[55,101,197,219],[55,101,329,330,331,332,333,334,335,336,337,338],[55,101,348],[55,101,350],[55,101,197,211,219,222,230],[55,101,345,346,347,348,349,350,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365],[55,101,197,230],[55,101,222,230],[55,101,211,219,230],[55,101,208,211,286,301,367],[55,101,208,369],[55,101,208,227,369],[55,101,208,230,236,301,369],[55,101,204,206,208,369],[55,101,204,208,301,367,375],[55,101,208,230,236,369],[55,101,204,208,238,301,378],[55,101,225,369],[55,101,204,208,301,382],[55,101,204,212,301,369,385],[55,101,204,208,263,301,369],[55,101,208,263],[55,101,208,211,263,301,374],[55,101,262,321],[55,101,208,211,263],[55,101,208,262,301],[55,101,263,389],[55,101,197,204,205,206,258,261,263,301],[55,101,208,263,381],[55,101,262,263,284],[55,101,208,211,235,263,301,392],[55,101,262,284],[55,101,218,394,395],[55,101,394,395],[55,101,230,325,394,395],[55,101,232,394,395],[55,101,233,394,395],[55,101,297,394,395],[55,101,394],[55,101,395],[55,101,235,296,394,395],[55,101,218,230,234,235,296,301,325,394,395],[55,101,235,394,395],[55,101,208,235,296],[55,101,236],[55,101,195,206,208,225,228,230,231,266,289,295,301,436],[55,101,236,237,238,239,240,241,242,243,244,245,246,247,248,252,253,254,255,296],[55,101,195,203,208,235,296],[55,101,195,235,296],[55,101,211,235,296],[55,101,195,197,203,208,235,296],[55,101,195,197,208,235,296],[55,101,195,197,235,296],[55,101,197,208,235,245],[55,101,252],[55,101,195,197,198,204,205,211,250,251,296,301],[55,101,208,296],[55,101,199,204,211,224,225,226,301],[55,101,195,198,199,201,207,211],[55,101,195,208,211],[55,101,211],[55,101,202,204,211],[55,101,195,204,211,224,225,227,257,301],[55,101,204,211],[55,101,202],[55,101,197,204,211],[55,101,195,198,202,203,211],[55,101,198,204,211,223,224,227],[55,101,199,201,203,204,211],[55,101,204,211,224,225,227],[55,101,204,211,225,227],[55,101,197,199,201,205,211,225,227],[55,101,198,199],[55,101,198,199,201,202,203,204,206,208,209,210],[55,101,199,202,204],[55,101,213],[55,101,204,206,208,224,227,230,286,296],[55,101,301],[55,101,199,204,208,224,227,230,286,296,297,301,324],[55,101,230,296,301],[55,101,230,296,301,367],[55,101,211,230,296,301],[55,101,204,212,297],[55,101,195,204,211,224,227,230,286,296,298,301],[55,101,197,230,256,301],[55,101,260,261,269],[55,101,260,261,270],[55,101,233,235,260,261,289],[55,101,235,260],[55,101,195,197,199,205,206,208,211,225,227,230,235,261,266,267,269,270,271,272,273,274,278,279,280,282,288,296,301],[55,101,251],[55,101,197,198,208],[55,101,250,251],[55,101,199,201,229],[55,101,199,230,278,290,296,301],[55,101,272,279],[55,101,195],[55,101,206,225,273,296],[55,101,289],[55,101,235,289],[55,101,199,230,279,290,301],[55,101,278],[55,101,272],[55,101,277,289],[55,101,195,251,263,266,271,272,278,289,291,292,293,294,296,301],[55,101,206,230,231,266,273,278,296,301],[55,101,195,206,263,266,271,281,289],[55,101,195,205,261,296],[55,101,271,272,273,274,275,279],[55,101,276,278],[55,101,195,272],[55,101,211,231,301],[55,101,235,286,288,289],[55,101,205,228,235,283,284,285,286,287,289],[55,101,208],[55,101,203,208,233,235,264,265,296,301],[55,101,195,232],[55,101,195,199,235],[55,101,195,235,268],[55,101,195,197,198,228,232,233,234],[55,101,181,187],[55,101,173],[55,101,171,173],[55,101,162,170,171,172,174,176],[55,101,160],[55,101,163,168,173,176],[55,101,159,176],[55,101,163,164,167,168,169,176],[55,101,163,164,165,167,168,176],[55,101,160,161,162,163,164,168,169,170,172,173,174,176],[55,101,176],[55,101,158,160,161,162,163,164,165,167,168,169,170,171,172,173,174,175],[55,101,158,176],[55,101,163,165,166,168,169,176],[55,101,167,176],[55,101,168,169,173,176],[55,101,161,171],[55,101,151,180],[55,101,150,151],[55,68,72,101,142],[55,68,101,131,142],[55,63,101],[55,65,68,101,139,142],[55,101,120,139],[55,101,149],[55,63,101,149],[55,65,68,101,120,142],[55,60,61,64,67,101,112,131,142],[55,68,75,101],[55,60,66,101],[55,68,89,90,101],[55,64,68,101,134,142,149],[55,89,101,149],[55,62,63,101,149],[55,68,101],[55,62,63,64,65,66,67,68,69,70,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,90,91,92,93,94,95,101],[55,68,83,101],[55,68,75,76,101],[55,66,68,76,77,101],[55,67,101],[55,60,63,68,101],[55,68,72,76,77,101],[55,72,101],[55,66,68,71,101,142],[55,60,65,68,75,101],[55,101,131],[55,63,68,89,101,147,149],[55,101,112,113,115,116,117,120,131,139,142,148,149,151,152,153,154,155,156,157,177,178,179,180],[55,101,153,154,155,156],[55,101,153,154,155],[55,101,153],[55,101,154],[55,101,151],[55,101,122,181,188]],"fileInfos":[{"version":"a7297ff837fcdf174a9524925966429eb8e5feecc2cc55cc06574e6b092c1eaa","impliedFormat":1},{"version":"c430d44666289dae81f30fa7b2edebf186ecc91a2d4c71266ea6ae76388792e1","affectsGlobalScope":true,"impliedFormat":1},{"version":"45b7ab580deca34ae9729e97c13cfd999df04416a79116c3bfb483804f85ded4","impliedFormat":1},{"version":"3facaf05f0c5fc569c5649dd359892c98a85557e3e0c847964caeb67076f4d75","impliedFormat":1},{"version":"e44bb8bbac7f10ecc786703fe0a6a4b952189f908707980ba8f3c8975a760962","impliedFormat":1},{"version":"5e1c4c362065a6b95ff952c0eab010f04dcd2c3494e813b493ecfd4fcb9fc0d8","impliedFormat":1},{"version":"68d73b4a11549f9c0b7d352d10e91e5dca8faa3322bfb77b661839c42b1ddec7","impliedFormat":1},{"version":"5efce4fc3c29ea84e8928f97adec086e3dc876365e0982cc8479a07954a3efd4","impliedFormat":1},{"version":"080941d9f9ff9307f7e27a83bcd888b7c8270716c39af943532438932ec1d0b9","affectsGlobalScope":true,"impliedFormat":1},{"version":"80e18897e5884b6723488d4f5652167e7bb5024f946743134ecc4aa4ee731f89","affectsGlobalScope":true,"impliedFormat":1},{"version":"cd034f499c6cdca722b60c04b5b1b78e058487a7085a8e0d6fb50809947ee573","affectsGlobalScope":true,"impliedFormat":1},{"version":"c57796738e7f83dbc4b8e65132f11a377649c00dd3eee333f672b8f0a6bea671","affectsGlobalScope":true,"impliedFormat":1},{"version":"dc2df20b1bcdc8c2d34af4926e2c3ab15ffe1160a63e58b7e09833f616efff44","affectsGlobalScope":true,"impliedFormat":1},{"version":"515d0b7b9bea2e31ea4ec968e9edd2c39d3eebf4a2d5cbd04e88639819ae3b71","affectsGlobalScope":true,"impliedFormat":1},{"version":"0559b1f683ac7505ae451f9a96ce4c3c92bdc71411651ca6ddb0e88baaaad6a3","affectsGlobalScope":true,"impliedFormat":1},{"version":"0dc1e7ceda9b8b9b455c3a2d67b0412feab00bd2f66656cd8850e8831b08b537","affectsGlobalScope":true,"impliedFormat":1},{"version":"ce691fb9e5c64efb9547083e4a34091bcbe5bdb41027e310ebba8f7d96a98671","affectsGlobalScope":true,"impliedFormat":1},{"version":"8d697a2a929a5fcb38b7a65594020fcef05ec1630804a33748829c5ff53640d0","affectsGlobalScope":true,"impliedFormat":1},{"version":"4ff2a353abf8a80ee399af572debb8faab2d33ad38c4b4474cff7f26e7653b8d","affectsGlobalScope":true,"impliedFormat":1},{"version":"fb0f136d372979348d59b3f5020b4cdb81b5504192b1cacff5d1fbba29378aa1","affectsGlobalScope":true,"impliedFormat":1},{"version":"d15bea3d62cbbdb9797079416b8ac375ae99162a7fba5de2c6c505446486ac0a","affectsGlobalScope":true,"impliedFormat":1},{"version":"68d18b664c9d32a7336a70235958b8997ebc1c3b8505f4f1ae2b7e7753b87618","affectsGlobalScope":true,"impliedFormat":1},{"version":"eb3d66c8327153d8fa7dd03f9c58d351107fe824c79e9b56b462935176cdf12a","affectsGlobalScope":true,"impliedFormat":1},{"version":"38f0219c9e23c915ef9790ab1d680440d95419ad264816fa15009a8851e79119","affectsGlobalScope":true,"impliedFormat":1},{"version":"69ab18c3b76cd9b1be3d188eaf8bba06112ebbe2f47f6c322b5105a6fbc45a2e","affectsGlobalScope":true,"impliedFormat":1},{"version":"a680117f487a4d2f30ea46f1b4b7f58bef1480456e18ba53ee85c2746eeca012","affectsGlobalScope":true,"impliedFormat":1},{"version":"2f11ff796926e0832f9ae148008138ad583bd181899ab7dd768a2666700b1893","affectsGlobalScope":true,"impliedFormat":1},{"version":"4de680d5bb41c17f7f68e0419412ca23c98d5749dcaaea1896172f06435891fc","affectsGlobalScope":true,"impliedFormat":1},{"version":"954296b30da6d508a104a3a0b5d96b76495c709785c1d11610908e63481ee667","affectsGlobalScope":true,"impliedFormat":1},{"version":"ac9538681b19688c8eae65811b329d3744af679e0bdfa5d842d0e32524c73e1c","affectsGlobalScope":true,"impliedFormat":1},{"version":"0a969edff4bd52585473d24995c5ef223f6652d6ef46193309b3921d65dd4376","affectsGlobalScope":true,"impliedFormat":1},{"version":"9e9fbd7030c440b33d021da145d3232984c8bb7916f277e8ffd3dc2e3eae2bdb","affectsGlobalScope":true,"impliedFormat":1},{"version":"811ec78f7fefcabbda4bfa93b3eb67d9ae166ef95f9bff989d964061cbf81a0c","affectsGlobalScope":true,"impliedFormat":1},{"version":"717937616a17072082152a2ef351cb51f98802fb4b2fdabd32399843875974ca","affectsGlobalScope":true,"impliedFormat":1},{"version":"d7e7d9b7b50e5f22c915b525acc5a49a7a6584cf8f62d0569e557c5cfc4b2ac2","affectsGlobalScope":true,"impliedFormat":1},{"version":"71c37f4c9543f31dfced6c7840e068c5a5aacb7b89111a4364b1d5276b852557","affectsGlobalScope":true,"impliedFormat":1},{"version":"576711e016cf4f1804676043e6a0a5414252560eb57de9faceee34d79798c850","affectsGlobalScope":true,"impliedFormat":1},{"version":"89c1b1281ba7b8a96efc676b11b264de7a8374c5ea1e6617f11880a13fc56dc6","affectsGlobalScope":true,"impliedFormat":1},{"version":"74f7fa2d027d5b33eb0471c8e82a6c87216223181ec31247c357a3e8e2fddc5b","affectsGlobalScope":true,"impliedFormat":1},{"version":"d6d7ae4d1f1f3772e2a3cde568ed08991a8ae34a080ff1151af28b7f798e22ca","affectsGlobalScope":true,"impliedFormat":1},{"version":"063600664504610fe3e99b717a1223f8b1900087fab0b4cad1496a114744f8df","affectsGlobalScope":true,"impliedFormat":1},{"version":"934019d7e3c81950f9a8426d093458b65d5aff2c7c1511233c0fd5b941e608ab","affectsGlobalScope":true,"impliedFormat":1},{"version":"52ada8e0b6e0482b728070b7639ee42e83a9b1c22d205992756fe020fd9f4a47","affectsGlobalScope":true,"impliedFormat":1},{"version":"3bdefe1bfd4d6dee0e26f928f93ccc128f1b64d5d501ff4a8cf3c6371200e5e6","affectsGlobalScope":true,"impliedFormat":1},{"version":"59fb2c069260b4ba00b5643b907ef5d5341b167e7d1dbf58dfd895658bda2867","affectsGlobalScope":true,"impliedFormat":1},{"version":"639e512c0dfc3fad96a84caad71b8834d66329a1f28dc95e3946c9b58176c73a","affectsGlobalScope":true,"impliedFormat":1},{"version":"368af93f74c9c932edd84c58883e736c9e3d53cec1fe24c0b0ff451f529ceab1","affectsGlobalScope":true,"impliedFormat":1},{"version":"8e7f8264d0fb4c5339605a15daadb037bf238c10b654bb3eee14208f860a32ea","affectsGlobalScope":true,"impliedFormat":1},{"version":"782dec38049b92d4e85c1585fbea5474a219c6984a35b004963b00beb1aab538","affectsGlobalScope":true,"impliedFormat":1},{"version":"70521b6ab0dcba37539e5303104f29b721bfb2940b2776da4cc818c07e1fefc1","affectsGlobalScope":true,"impliedFormat":1},{"version":"ab41ef1f2cdafb8df48be20cd969d875602483859dc194e9c97c8a576892c052","affectsGlobalScope":true,"impliedFormat":1},{"version":"d153a11543fd884b596587ccd97aebbeed950b26933ee000f94009f1ab142848","affectsGlobalScope":true,"impliedFormat":1},{"version":"21d819c173c0cf7cc3ce57c3276e77fd9a8a01d35a06ad87158781515c9a438a","impliedFormat":1},{"version":"98cffbf06d6bab333473c70a893770dbe990783904002c4f1a960447b4b53dca","affectsGlobalScope":true,"impliedFormat":1},{"version":"ba481bca06f37d3f2c137ce343c7d5937029b2468f8e26111f3c9d9963d6568d","affectsGlobalScope":true,"impliedFormat":1},{"version":"6d9ef24f9a22a88e3e9b3b3d8c40ab1ddb0853f1bfbd5c843c37800138437b61","affectsGlobalScope":true,"impliedFormat":1},{"version":"1db0b7dca579049ca4193d034d835f6bfe73096c73663e5ef9a0b5779939f3d0","affectsGlobalScope":true,"impliedFormat":1},{"version":"9798340ffb0d067d69b1ae5b32faa17ab31b82466a3fc00d8f2f2df0c8554aaa","affectsGlobalScope":true,"impliedFormat":1},{"version":"f26b11d8d8e4b8028f1c7d618b22274c892e4b0ef5b3678a8ccbad85419aef43","affectsGlobalScope":true,"impliedFormat":1},{"version":"5929864ce17fba74232584d90cb721a89b7ad277220627cc97054ba15a98ea8f","impliedFormat":1},{"version":"763fe0f42b3d79b440a9b6e51e9ba3f3f91352469c1e4b3b67bfa4ff6352f3f4","impliedFormat":1},{"version":"25c8056edf4314820382a5fdb4bb7816999acdcb929c8f75e3f39473b87e85bc","impliedFormat":1},{"version":"929b4c540b70efdaee3390e40d123889e3410c022d49edeb81b36acd54f28b4e","impliedFormat":1},{"version":"6401927b62c7d8e62eb9af3b2ac6f5597e31f185b2052a0e891f8b0b1f04eef9","impliedFormat":1},{"version":"c6fd2c5a395f2432786c9cb8deb870b9b0e8ff7e22c029954fabdd692bff6195","impliedFormat":1},{"version":"f8edab1fd539c4bc67932e1d0a37588528febc37ad8ee555d8a28aae30a7b770","impliedFormat":1},{"version":"62dbb9afbfbe0f14c68963c21034da7cd82fc752c8191f224dbbafaf470347e1","impliedFormat":1},{"version":"38ecaace40b2b571363e63992f1cb8e7973588df81b342c6f6ebf71fbffff906","impliedFormat":1},{"version":"383b91398f3ad5520d74661409ed1026e553a7ebc607028a8435385ddc8aa0e6","impliedFormat":1},{"version":"385aab901643aa54e1c36f5ef3107913b10d1b5bb8cbcd933d4263b80a0d7f20","impliedFormat":1},{"version":"eaa2e9af2d32f0586ef50ff5621d3ff94d1e0033639d6b8c84b687bbefbf065f","impliedFormat":1},{"version":"860e2841ceb976416594ea4b428fbfe94a31418f172e27df7926072029034ac3","impliedFormat":1},{"version":"3283decbf4f544bc802a865b08d4d720383bb6ce6e4ed60e013bb40c6bbb6b90","impliedFormat":1},{"version":"f2e47827db13f95a20139b9be29e58b728e8e18f3f86289fa1e99589313e96f5","impliedFormat":1},{"version":"bd8d46dc9e5cfff76b40e8b418ef1e55848366c0ded87cdc06b5a43a9f5e9199","impliedFormat":1},{"version":"55b3a57d0a4e8f6e04b96cb3b9040e3f1bedfba796e072b374110fc832ca706c","impliedFormat":1},{"version":"3a5edc4c3a85102031e36f88ac0149a3c1599c3acabd3a8d62abdc767c96d468","impliedFormat":1},{"version":"5fa0dc3c25e77dc8488194dde96c862fb6df566c6bfc747b4dc8328c8551dc4a","impliedFormat":1},{"version":"e00f958278e17b33bea65dc9954e67b8cab7c47894fbf04afd7465e56283ddb8","impliedFormat":1},{"version":"926b74b0bfae3c43ea8cb9110f4036bbb48c6937593a82a2a29af0d7b027a292","impliedFormat":1},{"version":"3655183a607c5605e52f9d2acb9afcefd8140cfcc21d25345608a038bb4dd93b","impliedFormat":1},{"version":"a32f3a86595a70182a2801759b9c0287c16e8887d9a1c3b3bd19845fe185aae1","impliedFormat":1},{"version":"f5defd0791f7cb141bcc82dcca4bf52f90fcfe43d318ce818bb0a05e21aa8e68","impliedFormat":1},{"version":"85b97ce0065e4c3bde88ef39bbd071e8d7c650cd4d1c1126263ff159c30367fb","impliedFormat":1},{"version":"a26b1facfea6b62ce9ec55106d84fefd1300bdda27ba5ee2bd5ebb676135f644","impliedFormat":1},{"version":"037b8a322e4d96a7b4e21bf1ccc695d3e5b8758dcccec2427d1fcbdbf9cb6791","impliedFormat":1},{"version":"bd0532fd6556073727d28da0edfd1736417a3f9f394877b6d5ef6ad88fba1d1a","impliedFormat":1},{"version":"55245877be1a89483a0e3dc347a17652c034f44b10c3018a62ac8766b7401918","impliedFormat":1},{"version":"615ba88d0128ed16bf83ef8ccbb6aff05c3ee2db1cc0f89ab50a4939bfc1943f","impliedFormat":1},{"version":"029d278301e67ff530caefca0992749bf220d0b3b61a7c604f06bdff3c014d85","impliedFormat":1},{"version":"efdb613729ff9021f37f591ac75def5696e56be59cc87224e94cd9240b85cde4","impliedFormat":1},{"version":"a721cceaeb9c8599a74b01fb3ed04e9f73db4f715e0e358996cce831f4992f30","impliedFormat":1},{"version":"6362d52572d95519061db0dfd4a4a570503e8e36ac0c4ac9502fa173f70fb9e8","impliedFormat":1},{"version":"2e85db9e6fd73cfa3d7f28e0ab6b55417ea18931423bd47b409a96e4a169e8e6","impliedFormat":1},{"version":"88f9f1cfe56e8e4102031351e9a475378348e65b1515f530fc0fa8e661363f07","impliedFormat":1},{"version":"f590da8ae6e0ce1cf67566380658f5495a8929ad55878b405734e5f211b876ba","impliedFormat":1},{"version":"b52476feb4a0cbcb25e5931b930fc73cb6643fb1a5060bf8a3dda0eeae5b4b68","affectsGlobalScope":true,"impliedFormat":1},{"version":"e2677634fe27e87348825bb041651e22d50a613e2fdf6a4a3ade971d71bac37e","impliedFormat":1},{"version":"7394959e5a741b185456e1ef5d64599c36c60a323207450991e7a42e08911419","impliedFormat":1},{"version":"8c0bcd6c6b67b4b503c11e91a1fb91522ed585900eab2ab1f61bba7d7caa9d6f","impliedFormat":1},{"version":"8cd19276b6590b3ebbeeb030ac271871b9ed0afc3074ac88a94ed2449174b776","affectsGlobalScope":true,"impliedFormat":1},{"version":"696eb8d28f5949b87d894b26dc97318ef944c794a9a4e4f62360cd1d1958014b","impliedFormat":1},{"version":"3f8fa3061bd7402970b399300880d55257953ee6d3cd408722cb9ac20126460c","impliedFormat":1},{"version":"35ec8b6760fd7138bbf5809b84551e31028fb2ba7b6dc91d95d098bf212ca8b4","affectsGlobalScope":true,"impliedFormat":1},{"version":"5524481e56c48ff486f42926778c0a3cce1cc85dc46683b92b1271865bcf015a","impliedFormat":1},{"version":"68bd56c92c2bd7d2339457eb84d63e7de3bd56a69b25f3576e1568d21a162398","affectsGlobalScope":true,"impliedFormat":1},{"version":"3e93b123f7c2944969d291b35fed2af79a6e9e27fdd5faa99748a51c07c02d28","impliedFormat":1},{"version":"9d19808c8c291a9010a6c788e8532a2da70f811adb431c97520803e0ec649991","impliedFormat":1},{"version":"87aad3dd9752067dc875cfaa466fc44246451c0c560b820796bdd528e29bef40","impliedFormat":1},{"version":"4aacb0dd020eeaef65426153686cc639a78ec2885dc72ad220be1d25f1a439df","impliedFormat":1},{"version":"f0bd7e6d931657b59605c44112eaf8b980ba7f957a5051ed21cb93d978cf2f45","impliedFormat":1},{"version":"8db0ae9cb14d9955b14c214f34dae1b9ef2baee2fe4ce794a4cd3ac2531e3255","affectsGlobalScope":true,"impliedFormat":1},{"version":"15fc6f7512c86810273af28f224251a5a879e4261b4d4c7e532abfbfc3983134","impliedFormat":1},{"version":"58adba1a8ab2d10b54dc1dced4e41f4e7c9772cbbac40939c0dc8ce2cdb1d442","impliedFormat":1},{"version":"641942a78f9063caa5d6b777c99304b7d1dc7328076038c6d94d8a0b81fc95c1","impliedFormat":1},{"version":"714435130b9015fae551788df2a88038471a5a11eb471f27c4ede86552842bc9","impliedFormat":1},{"version":"855cd5f7eb396f5f1ab1bc0f8580339bff77b68a770f84c6b254e319bbfd1ac7","impliedFormat":1},{"version":"5650cf3dace09e7c25d384e3e6b818b938f68f4e8de96f52d9c5a1b3db068e86","impliedFormat":1},{"version":"1354ca5c38bd3fd3836a68e0f7c9f91f172582ba30ab15bb8c075891b91502b7","affectsGlobalScope":true,"impliedFormat":1},{"version":"7e20d899c28ca26a2a7afc98beaa69e63ff7fba0a8bc47b4e3bf3ede5e09e424","impliedFormat":1},{"version":"2d2fcaab481b31a5882065c7951255703ddbe1c0e507af56ea42d79ac3911201","impliedFormat":1},{"version":"a192fe8ec33f75edbc8d8f3ed79f768dfae11ff5735e7fe52bfa69956e46d78d","impliedFormat":1},{"version":"ca867399f7db82df981d6915bcbb2d81131d7d1ef683bc782b59f71dda59bc85","affectsGlobalScope":true,"impliedFormat":1},{"version":"372413016d17d804e1d139418aca0c68e47a83fb6669490857f4b318de8cccb3","affectsGlobalScope":true,"impliedFormat":1},{"version":"9e043a1bc8fbf2a255bccf9bf27e0f1caf916c3b0518ea34aa72357c0afd42ec","impliedFormat":1},{"version":"b4f70ec656a11d570e1a9edce07d118cd58d9760239e2ece99306ee9dfe61d02","impliedFormat":1},{"version":"3bc2f1e2c95c04048212c569ed38e338873f6a8593930cf5a7ef24ffb38fc3b6","impliedFormat":1},{"version":"6e70e9570e98aae2b825b533aa6292b6abd542e8d9f6e9475e88e1d7ba17c866","impliedFormat":1},{"version":"f9d9d753d430ed050dc1bf2667a1bab711ccbb1c1507183d794cc195a5b085cc","impliedFormat":1},{"version":"9eece5e586312581ccd106d4853e861aaaa1a39f8e3ea672b8c3847eedd12f6e","impliedFormat":1},{"version":"085f552d005479e2e6a7311cdbbe5d8c55c497b4d19274285df161ee9684cd9c","impliedFormat":1},{"version":"37ba7b45141a45ce6e80e66f2a96c8a5ab1bcef0fc2d0f56bb58df96ec67e972","impliedFormat":1},{"version":"45650f47bfb376c8a8ed39d4bcda5902ab899a3150029684ee4c10676d9fbaee","impliedFormat":1},{"version":"007faacc9268357caa21d24169f3f3f2497af3e9241308df2d89f6e6d9bb3f2e","affectsGlobalScope":true,"impliedFormat":1},{"version":"74cf591a0f63db318651e0e04cb55f8791385f86e987a67fd4d2eaab8191f730","impliedFormat":1},{"version":"5eab9b3dc9b34f185417342436ec3f106898da5f4801992d8ff38ab3aff346b5","impliedFormat":1},{"version":"12ed4559eba17cd977aa0db658d25c4047067444b51acfdcbf38470630642b23","affectsGlobalScope":true,"impliedFormat":1},{"version":"f3ffabc95802521e1e4bcba4c88d8615176dc6e09111d920c7a213bdda6e1d65","impliedFormat":1},{"version":"809821b8a065e3234a55b3a9d7846231ed18d66dd749f2494c66288d890daf7f","impliedFormat":1},{"version":"ae56f65caf3be91108707bd8dfbccc2a57a91feb5daabf7165a06a945545ed26","impliedFormat":1},{"version":"a136d5de521da20f31631a0a96bf712370779d1c05b7015d7019a9b2a0446ca9","impliedFormat":1},{"version":"c3b41e74b9a84b88b1dca61ec39eee25c0dbc8e7d519ba11bb070918cfacf656","affectsGlobalScope":true,"impliedFormat":1},{"version":"4737a9dc24d0e68b734e6cfbcea0c15a2cfafeb493485e27905f7856988c6b29","affectsGlobalScope":true,"impliedFormat":1},{"version":"36d8d3e7506b631c9582c251a2c0b8a28855af3f76719b12b534c6edf952748d","impliedFormat":1},{"version":"1ca69210cc42729e7ca97d3a9ad48f2e9cb0042bada4075b588ae5387debd318","impliedFormat":1},{"version":"f5ebe66baaf7c552cfa59d75f2bfba679f329204847db3cec385acda245e574e","impliedFormat":1},{"version":"ed59add13139f84da271cafd32e2171876b0a0af2f798d0c663e8eeb867732cf","affectsGlobalScope":true,"impliedFormat":1},{"version":"b7c5e2ea4a9749097c347454805e933844ed207b6eefec6b7cfd418b5f5f7b28","impliedFormat":1},{"version":"b1810689b76fd473bd12cc9ee219f8e62f54a7d08019a235d07424afbf074d25","impliedFormat":1},{"version":"151ff381ef9ff8da2da9b9663ebf657eac35c4c9a19183420c05728f31a6761d","impliedFormat":1},{"version":"ee70b8037ecdf0de6c04f35277f253663a536d7e38f1539d270e4e916d225a3f","affectsGlobalScope":true,"impliedFormat":1},{"version":"a660aa95476042d3fdcc1343cf6bb8fdf24772d31712b1db321c5a4dcc325434","impliedFormat":1},{"version":"282f98006ed7fa9bb2cd9bdbe2524595cfc4bcd58a0bb3232e4519f2138df811","impliedFormat":1},{"version":"6222e987b58abfe92597e1273ad7233626285bc2d78409d4a7b113d81a83496b","impliedFormat":1},{"version":"cbe726263ae9a7bf32352380f7e8ab66ee25b3457137e316929269c19e18a2be","impliedFormat":1},{"version":"8b96046bf5fb0a815cba6b0880d9f97b7f3a93cf187e8dcfe8e2792e97f38f87","impliedFormat":99},{"version":"bacf2c84cf448b2cd02c717ad46c3d7fd530e0c91282888c923ad64810a4d511","affectsGlobalScope":true,"impliedFormat":1},{"version":"402e5c534fb2b85fa771170595db3ac0dd532112c8fa44fc23f233bc6967488b","impliedFormat":1},{"version":"52dcc257df5119fb66d864625112ce5033ac51a4c2afe376a0b299d2f7f76e4a","impliedFormat":1},{"version":"e5bab5f871ef708d52d47b3e5d0aa72a08ee7a152f33931d9a60809711a2a9a3","impliedFormat":1},{"version":"e16dc2a81595736024a206c7d5c8a39bfe2e6039208ef29981d0d95434ba8fcf","impliedFormat":1},{"version":"cc4a4903fb698ca1d961d4c10dce658aa3a479faf40509d526f122b044eaf6a4","impliedFormat":1},{"version":"19ee8416e6473ed6c7adb868fa796b5653cf0fa2a337658e677eaa0d134388c3","impliedFormat":1},{"version":"1328ab4e442614b28cdb3d4b414cf68325c0da0dca07287a338d0654b7a00261","impliedFormat":1},{"version":"a039dc21f045919f3cbee2ec13812cc6cc3eebc99dae4be00973230f468d19a6","impliedFormat":1},{"version":"3fbe57af01460e49dcd29df55d6931e1672bc6f1be0fb073d11410bc16f9037d","impliedFormat":1},{"version":"f760be449e8562ec5c09bb5187e8e1eabf3c113c0c58cddda53ef8c69f3e2131","impliedFormat":1},{"version":"44325ed13294fce6ab825b82947bbeed2611db7dad9d9135260192f375e5a189","impliedFormat":1},{"version":"e392e8fb5b514eafc585601c1d781485aa6dd6a320e75daf1064a4c6918a1b45","impliedFormat":1},{"version":"46e4a36e8ddbdfb4e7330e11c81c970dc8b218611df9183d39c41c5f8c653b55","impliedFormat":1},{"version":"370bde134aa8c2abc926d0e99d3a4d5d5dba65c6ee65459137e4f02670cbf841","impliedFormat":1},{"version":"6332f565867cf4a740a70e30f31cefba37ef7cebcf74f22eab8d744fde6d193e","impliedFormat":1},{"version":"2977b7884aedc895a1d0c9c210c7cf3272c29d6959a08a6fa3ff71e0aff08175","impliedFormat":1},{"version":"17f2922d41ddd032830a91371c948cd9ce903b35c95adca72271a54584f19b0b","impliedFormat":1},{"version":"3eed76ede2a1a14d7c9bb0a642041282dcc264811139d3dd275c9fe14efc9840","impliedFormat":1},{"version":"00cf4001e0d9c6e5e036bc545b9d73e2b8b84cddb02e61ad05bab3752b1d4522","impliedFormat":1},{"version":"8d369483f0c2b9ee388129cfdb6a43bc8112b377e86a41884bd06e19ce04f4c1","impliedFormat":99},{"version":"82e687ebd99518bc63ea04b0c3810fb6e50aa6942decd0ca6f7a56d9b9a212a6","impliedFormat":99},{"version":"7f698624bbbb060ece7c0e51b7236520ebada74b747d7523c7df376453ed6fea","impliedFormat":1},{"version":"8f07f2b6514744ac96e51d7cb8518c0f4de319471237ea10cf688b8d0e9d0225","impliedFormat":1},{"version":"257b83faa134d971c738a6b9e4c47e59bb7b23274719d92197580dd662bfafc3","impliedFormat":99},{"version":"556ccd493ec36c7d7cb130d51be66e147b91cc1415be383d71da0f1e49f742a9","impliedFormat":1},{"version":"b6d03c9cfe2cf0ba4c673c209fcd7c46c815b2619fd2aad59fc4229aaef2ed43","impliedFormat":1},{"version":"95aba78013d782537cc5e23868e736bec5d377b918990e28ed56110e3ae8b958","impliedFormat":1},{"version":"670a76db379b27c8ff42f1ba927828a22862e2ab0b0908e38b671f0e912cc5ed","impliedFormat":1},{"version":"13b77ab19ef7aadd86a1e54f2f08ea23a6d74e102909e3c00d31f231ed040f62","impliedFormat":1},{"version":"069bebfee29864e3955378107e243508b163e77ab10de6a5ee03ae06939f0bb9","impliedFormat":1},{"version":"26e0ffceb2198feb1ef460d5d14111c69ad07d44c5a67fd4bfeb74c969aa9afb","impliedFormat":99},{"version":"efa235fa23d71829de136935b91c4048f4741f33c3f5bcf5a90b01c29c2bd07c","signature":"4b96dd19fd2949d28ce80e913412b0026dc421e5bf6c31d87c7b5eb11b5753b4"},{"version":"eb5b19b86227ace1d29ea4cf81387279d04bb34051e944bc53df69f58914b788","affectsGlobalScope":true,"impliedFormat":1},{"version":"ac51dd7d31333793807a6abaa5ae168512b6131bd41d9c5b98477fc3b7800f9f","impliedFormat":1},{"version":"87d9d29dbc745f182683f63187bf3d53fd8673e5fca38ad5eaab69798ed29fbc","impliedFormat":1},{"version":"035312d4945d13efa134ae482f6dc56a1a9346f7ac3be7ccbad5741058ce87f3","affectsGlobalScope":true,"impliedFormat":1},{"version":"17ed71200119e86ccef2d96b73b02ce8854b76ad6bd21b5021d4269bec527b5f","impliedFormat":1},{"version":"889b2c3eb9e1589df4ed4d28ef37e25be191e1dc4f7dd82d600ce79811800ff3","impliedFormat":99},{"version":"ae046314c0651da4a01e9e48ddf370ce9d22ad21f48962f25a12c1c09de9b01a","impliedFormat":99},{"version":"d0e136d6bf3c38be7af296b7e01912b6e8944a428ba7fd1e415a10acd9e687e8","impliedFormat":99},{"version":"7a685305685db7f9d2195ae629df44ae5888c13371a032ebe629a615a177a45b","impliedFormat":99},{"version":"383653e7a2888455e907c0adbde5bf74f16d95f40b73c81ffe0cc982b21745d5","impliedFormat":99},{"version":"c95ddf25be5f33178641ca540ca1ec157f8bdceb1f3c430d0c7045af5af04404","impliedFormat":99},{"version":"c3aa1b9d09adac7ac5e49aba8e8fa7114c2c842d46c2c5f51da53ec889787bac","impliedFormat":99},{"version":"7cd8fbd00f9608795145d427ff641d7abc485cd485d833ea1d9a90222ee73778","impliedFormat":99},{"version":"0f4f54801406a0a67455a9ad950bed9f4d2921fd66a91682f83a985086d60082","impliedFormat":99},{"version":"23e2aa3fe97254db69a9ba8f6b62e9397a5c64fd080e2dbf70d9004f226a224a","impliedFormat":99},{"version":"77d9b19c200d3803c1b31a29dd65cb977983e9b81dd797fab892e70bbe6b9679","impliedFormat":99},{"version":"a189ede87046071ae9cd84e90d09327b3ab44b5e73947d38eaa56c2e839b0fc7","impliedFormat":99},{"version":"ed2d9201cc939621497a3d92ad39828a8823b7c7fe64f6c41d43792204e60f97","impliedFormat":99},{"version":"3f05e2ba96cd23e6a53cfea66bc100621c4703bf6d46515b841dd6892286b08e","impliedFormat":99},{"version":"6e5aa91099e2fe5d1d05f6f3100a90e5a5d9b8aea7b0ea6f4d05a0f192899a64","impliedFormat":99},{"version":"bd85cba544b37cd32e8d02b138c3a2a4075930d01146b3f5e33d713b39dafe77","impliedFormat":99},{"version":"04a7116aece3802e7ee128fed47d31cd18e5660825a62b42a62929f9508b936e","impliedFormat":99},{"version":"20ca05d62223bf6f117925ef8f9b9781e894cb146d30ac491e0763d34e53a5d0","impliedFormat":99},{"version":"4ba733d1a5ff0a0779b714468b13c9089f0d877e6fbd0147fac7c3af54c89fe0","impliedFormat":99},{"version":"697203f3f5a1fea90e40fe660360325090ab36e630dc9422a1909dd4faa2cacc","impliedFormat":99},{"version":"ad1226eba93a65cdccdb1b4f115d67c5469e12705dbe80139c2988d6b296d04d","impliedFormat":99},{"version":"4ea2c94c3a1c87029d10f11c209674d4c6a0c675a97503dc9668d2815ff6ea11","impliedFormat":99},{"version":"63ec0a7e0f0b1ac673102c02c00969d992d7dde30d7066d941f0c3e2c9e80610","impliedFormat":99},{"version":"31ace06421fa71c192f4b9de6ccf36dbe0ee3534a237ebafce0a2215bb9455f1","impliedFormat":99},{"version":"94cfe3be66e4a6a1d52eaff0eb03bea21b4cded83428272c28feedfa5f9a152a","impliedFormat":99},{"version":"c2cf5eb33fc641dd321afd12c726ac3e753a81ab1618270ce6cd508f927989c7","impliedFormat":99},{"version":"a7f2f38cd72a96e7678555a1166a4488771b94e5a9c799d1c8943974ada483bd","impliedFormat":99},{"version":"c519327110a82e5eeaad683dc64f36994f19d9893fe69c4ea2b19d41b7e3e45b","impliedFormat":99},{"version":"23af35a045f9117250e060abdb2789bd34519eb5a6308463f299975a205b2d8c","impliedFormat":99},{"version":"9eaaedc489e28c9f7ff513bc094fe82da02cf2c4a3b2b35fe025699fcc08be78","impliedFormat":99},{"version":"73c4f628937d4e4a94d5af1c04bf57008a9d2c5f94a8fe6d9da8d51783069e15","impliedFormat":99},{"version":"1a7bb0d5979c3081b835f51a7a54b50c50500a897792b66b26a4b8583162ce4f","impliedFormat":99},{"version":"4cd02f2d4d7feae05b035dc1c451070f7536601f4f060d0e944959f1036b3b18","impliedFormat":99},{"version":"75ad38105b8decc3c60ee068c8d76e3f546b4db1ca55255d0a509f45e4b52990","impliedFormat":99},{"version":"6e16ba58508a87f231264a5e01b0859669229a40d6edea4485ac2032ddf8a7c6","impliedFormat":99},{"version":"8a3576bf6a6c46ceaf02e1a8fb56146b9271c5194ff8bf171156d0467946565f","impliedFormat":99},{"version":"d45218d368df27abcfd0253d4b1287e1b954156f32ff263f31913bad81a80918","impliedFormat":99},{"version":"0df2fda4b69934223c08e3b8dc5ddb620e2c0636e973960e624f309a330229c0","impliedFormat":99},{"version":"8e67c31beb3a87366e5eaa2f0399078be858b5b05b6b8209e594be97b69b020e","impliedFormat":99},{"version":"49455da231ef295ce5fdc0baa019df7622f4b9dc136677109cda3bd20824e903","impliedFormat":99},{"version":"7e92bffc685fdc3d8e04df0218f616022fc571ee8c057e95922e653759576816","impliedFormat":99},{"version":"9f404e614b2c4cff62c24a47df9e91c72bf3ff160624deac897bb35552b43842","impliedFormat":99},{"version":"715a0154ce1359c3387d467981bc331da06822a9b999bbdf5c483696e28a4ceb","impliedFormat":99},{"version":"38c9d54cbcd3022f7b8bac65e76b05fc15c318f53a114a5bcc2d69c33a182adb","impliedFormat":99},{"version":"86c183d6201f35c841e31d97ede84989e4c02b690786f7c11efe025ec2f15c05","impliedFormat":99},{"version":"f0258631e56de39d236a0a34aed46b28859d376949ba040204513e61fb2dfb97","impliedFormat":99},{"version":"6b5db77219e73ae487db6ad94fb2048b0bb051b4fdce283600a763cf63b14e8e","impliedFormat":99},{"version":"de5d4a4fe9ab759003078db5588ff1d6b4727e164b6ad570859cfdf06a9bd47e","impliedFormat":99},{"version":"86ea856c59eb2c4d2090f22510d63631393af4793c98f0ad100f4545f0c9088e","impliedFormat":99},{"version":"5ef5bf461006cf3fe5bf50c5aed8d4fd5ba4aed06105428d4df3733136c9d9d7","impliedFormat":99},{"version":"6a074d0008571a6d1396fb1d86e54bf22bfb38fcd8a4df1e61cf4ca309817fac","impliedFormat":99},{"version":"bfedd3882083dc1f013092f079f76c17b6ea95594fba33a3e56c222ca984f263","impliedFormat":99},{"version":"7d89a609d9e50597111dde64263b0708343a68db2d53aee0bc2d3bcab7e745c3","impliedFormat":99},{"version":"0b840392f948eeb18059b0478c2073ac222a467829df29ef0eb1f15f55a3c77a","impliedFormat":99},{"version":"c91b058ab74323c57dda1cbda7eb8cee56272002249a642deebbbd977c4a0baa","impliedFormat":99},{"version":"cb7f489960477f1f432a3389f691dc243ca075e87f20032a2866321dab05bae2","impliedFormat":99},{"version":"ca885b971dc0c8217ef8aca9f3879c3c2d53415c4dfbe457748045160f6e5205","impliedFormat":99},{"version":"b8019033d2c520e44e54fb15b5865eca6b2939920ea8002b37e263d3187d5b71","impliedFormat":99},{"version":"a4e67e8eb5df4e6630588b1ce5c114d1fa5a533eb1f45c2ee4ecb4f48dab7788","impliedFormat":99},{"version":"3f8e1b42b7e6aa4756e00b26c972a64eac1b747600b2540120f95a92cb1684e4","impliedFormat":99},{"version":"93d5f2949aafca2e199761d2ded0b4870446685897b4d2214d0a9d9d581e0538","impliedFormat":99},{"version":"7c7a960997d3470573faaaa089e6effd21cd6233d97ba7245974b4adf46597fd","impliedFormat":99},{"version":"2bb814f26a57746ff80ff0dee91e834d00a5f40d60ee908c9c69265944c3a8b5","impliedFormat":99},{"version":"86e035d87d8f9827b055483b7dfdb86ecbb7d2ca74e9dce8adeaf6972756ac03","impliedFormat":99},{"version":"73ac47e45d90fb23336a6a01512ae421275cb1c818b7a5068ec84f58e94a5999","impliedFormat":99},{"version":"b5c081fa1ad246f75cd10b822eebdf35c3e1c510e9ad3a89570fbe4c575e0cb1","impliedFormat":99},{"version":"017907864b01ae728f5be6be99ea7632e68b2a35c2d7c9606bde20f85f10f838","impliedFormat":99},{"version":"a86a5d2ab15be86342869797f056d4861fd0b7cfae4cfa270121f18fe8521eab","impliedFormat":99},{"version":"22f98eae982b7f0d26d3dd7849210e033dc1992f594d87c6fe30075eb94b7a24","impliedFormat":99},{"version":"ec47b34311c3c799d1c90a3dcac1651ed23948c064aca4f0617fa253e648ab15","impliedFormat":99},{"version":"761efac4dfd849586e4fe49fc6cda2aba8e708fa8e4eb19ae85373084cba0d51","impliedFormat":99},{"version":"899ed4016a7a722a6224e78139286f1ab7d05f79be50af0a6492b95170e56fab","impliedFormat":99},{"version":"965bfde0433a808a389b80a8e45b717cd2d5a3a0cdf418707cfda3046e33fa5e","impliedFormat":99},{"version":"f5f69e449b4dc8e31cd0315860c59fde6358408f19747b76d98c90773ca62b19","impliedFormat":99},{"version":"6f623e7a3b9de6f69a0b2f81413d4dc357017ebbda86f12153346a52f1e2a739","impliedFormat":99},{"version":"e44950769f3c3b4ee2fa3b0a19c1cfd190c4e8378287ce8a2dabf821c7b9c2e3","impliedFormat":99},{"version":"9a9a3212ac108de497464fc14ab2178cfa037eb981a5b0f461e13362fdd3851a","impliedFormat":99},{"version":"b011f71b5d21579da9f868e56acf3887051fc4027cc7cde7317facb232ed3e95","impliedFormat":99},{"version":"7714308befeeb34cbc1d6715bb650d05e2b4e0516db9e58ef4c399e462d222b1","impliedFormat":99},{"version":"81e2b5cdeccd368e2eaaf33003fea50bd39740f8a8a71a1a487458435b7695dc","impliedFormat":99},{"version":"919b86dd53cd38daf8207cac48b67824ad2b8c9daffe559e1b0ec75f39d21ba8","impliedFormat":99},{"version":"aa7a83f4acf2686925511ecc32d148062c02984068d563c44f00835fee5b164f","impliedFormat":99},{"version":"d4632bbd2d2afbb1b75163dc7cabab5cc218c2fa933cb8f7d5b7089255faa6fd","impliedFormat":99},{"version":"0cf4827f19c749c5befed9585862c6196a4a5b3d889d20e0f5f4bdb6f734dcc7","impliedFormat":99},{"version":"14d3c7499d1759af5c78eec4f26a6f5b85bdd5b0e41ef3f5e6e813f1ae88c06a","impliedFormat":99},{"version":"0082935dc2cb31cd632eaa6bbdec17f1a9142652e38ede025c0ffab00c50bac4","impliedFormat":99},{"version":"0df7497ada3a4f6459420803ecf7e555f1ad1e7bd43c1e17bdafbc34e19d7162","impliedFormat":99},{"version":"5cccc8d1dd17c789bb6baba06a035e98e378a80d133da3071045c9901bee0094","impliedFormat":99},{"version":"c8a40bb3df60346af02e8d786473985ba53b716bc7caefd21ab838f025ec103b","affectsGlobalScope":true,"impliedFormat":1},{"version":"64da9a17f7cb5d84731607aed8493e4550a3e613cc7b880c87ce82b209d66b96","impliedFormat":99},{"version":"1e4bccd328de23aafb5a566317b3fa580aa2caa1a9146cc0b9effa792ba48ea9","impliedFormat":99},{"version":"156ac329be3116b9c1f55ae3cdf8e7586717561ac438ee6b193e7c15b2c87b1a","impliedFormat":99},{"version":"6d056661e4b636cc04e36c36b24a4eb692499b21fe0b18cb81f8bb655d7a3930","impliedFormat":99},{"version":"3481e087d798439d58148bb56c2320d555416010a93d5088888f33c1094fce0c","impliedFormat":99},{"version":"1601196196feb9bc15f41c1abe032669bb1687304cdc644f67e9ec8d99e1252d","impliedFormat":99},{"version":"1f957c8657bb868e8cb92e46eac8c8b1877a96708e962015a1ed47fd42c697f6","impliedFormat":99},{"version":"217800577a2c9a7232e5a9d1abd1c1836acbb004e7522a5261299aa867713f96","impliedFormat":99},{"version":"60981ae7c2a8926f7855d8068c42e05a3b1959f0bb795a8bb9773c912a9a6f16","impliedFormat":99},{"version":"4a6de5821d23f5e1781c567ab6550e5357b2c2ae3e8813a277062512f73d4a28","impliedFormat":99},{"version":"618b5aa1f8b9791938f8033f1855238774b555f9dd35f0b8a5443cc066721605","impliedFormat":99},{"version":"58bdc0c8212671d213ad6456b1851e4b4473fc0c63891e362a7513187fea1736","impliedFormat":99},{"version":"b4be747af2c3ceddb397190b4346be5612761526d4a8f5f9015c04e7aa73f1d6","impliedFormat":99},{"version":"2022dfa3df40a1f11d5f354bd729d0a2bb69d0d12b62767d3b237a29e6c62d4a","impliedFormat":99},{"version":"68617a52d0596e488c88549c000e964c5f6a241e5361095b2c6203586689b1f3","impliedFormat":99},{"version":"8d4a70e05b1f8450f5fb8997e5bfc336dd0baec3f2c8117f6f260d4eb68de0ac","impliedFormat":99},{"version":"01e6524f28e8d3fad9e13c43a27eaca96e88ca299f0a4f7da074143c251926e9","impliedFormat":99},{"version":"e61ce3bbfe37669692af8ac289869baa7b9d01b7e260e5cd0294095a4f6c29a2","impliedFormat":99},{"version":"0e6b3c7f300f6e2587c62783ebf78c74e61e7e85d37591e1e1ecf82cc15adc01","impliedFormat":99},{"version":"f78f6212fdebbc513a6656389ecf3c4bd9e77f79c0d2da2250de961b386a67a5","impliedFormat":99},{"version":"5de56154de88f7bbad618a1aac7dcfbf8234785cb8821b00c6902208587409f9","impliedFormat":99},{"version":"a4f4ecd42fc62ae32f9fa03100f821c61a2ca3d5fe2a9c0720baddbd67ad3174","impliedFormat":99},{"version":"b41dc4272747d7b9e3f5620815fd1aece9bc2c0c09e00c4101b429216599412e","impliedFormat":99},{"version":"4c136da3b1dce49c12eac152699c6b4bc64fa93d6c7224a43c816f7e51b00930","impliedFormat":99},{"version":"1093df5dbb38c416c10e41b3379033e952cb26cfa2a667bdf182f55dcca0d7e9","impliedFormat":99},{"version":"4d42746407b6732df92275e20f311f9717b57f1e3a90cf71730620077a7daf5d","impliedFormat":99},{"version":"72635b405f1d979eee2110b7d2921470748e13b19adbf42887c2680964af6f30","impliedFormat":99},{"version":"3a719c9c30a20a413b97a458f411679bbe56a4de8ddb2f3ae7cf2639e86d0e0f","impliedFormat":99},{"version":"ea37a7bc8718a01eeff979fef574318d7a5915fc786c74582c86cb553bee484b","impliedFormat":99},{"version":"6c61ff540eda59f07484aa863b753d7d6a8de0ac907e0e912ce2835f2e86e167","impliedFormat":99},{"version":"b90f14bca14cdbdd60dc83c451aca97e8df63c8eb8a158a9ed84de4bfb4cad76","impliedFormat":99},{"version":"bcdfa0b735dff249e6cafe7096d17d338c3942704c20b0cacf78c1d78a5a427f","impliedFormat":99},{"version":"daf3cb7fbb067540163df0a3421e791ebde6bd2e699aad4cdb13366871cb7196","impliedFormat":99},{"version":"98ba4768c426848773fb4a39203aac92e6baa545d93510665cdf207454d0811c","impliedFormat":99},{"version":"f65116ea54fd65813a0d9695249ceaa716487c932247e4aede3e2e3ad3d07316","impliedFormat":99},{"version":"99484c7a277c488a16c49ac1affe465e4fbb5e4d57b8c2190092c5d7b4fe6fca","impliedFormat":99},{"version":"c29f7f5c851ec3a781a17d7afb9280da6adfc9748535481b381daf5a67f439d0","impliedFormat":99},{"version":"0f1ea4f6570d745ee2dfa784baa306ae15c35ff7742566ac5ccc1a893af9a1ba","impliedFormat":99},{"version":"06e727ca4d41b4f549f875d7999d940a392058b1b579846441351ff011a63a31","impliedFormat":99},{"version":"6c7f1a4f3d43a47624bdf26e93be7be9fe29cda02de5b53b83f5c7559ae07745","impliedFormat":99},{"version":"d94acd15b4a3517523756dfeabcb7b4fb8ee853bba680d892ccfd3df4c81edc1","impliedFormat":99},{"version":"0f65f9b61383ffcfa1a409da90c35741cd81ece1a2dc6f2ebd094d81599bc5f6","impliedFormat":99},{"version":"9abd03a84d5473e66b038270dbeae266129ab97261d348a5fbd32ec876161a85","impliedFormat":99},{"version":"07af0693d07d8995441f333cc1fd578c8dc28500e1e43bbc3e1656b24bc19d03","impliedFormat":99},{"version":"b6024c6222886b95cb29ab236155a98f8e5dc41151233781815e81a83debf67b","impliedFormat":99},{"version":"94dab3752006a2cd2726462342f1775ef18ff4986404d016d317fe79a9d0a14c","impliedFormat":99},{"version":"727b3a462015bbed74b520861445761ebaecf94e09d95bbf59dfcf22afaccae9","impliedFormat":99},{"version":"2c0300921d8d04b21353c94a8f50a2b6c902feccd1303b6f136bedbb2cec5ed1","impliedFormat":99},{"version":"d496217c7f38f218fc162e8f3e6ed611343aa65615f730f82c494dee6c892bc0","impliedFormat":99},{"version":"282ed4ab5b5c4759d5c917c51a5b2f03ca1df4072275b6bccb936cf60078e973","impliedFormat":99},{"version":"2c96813e14e7edcd8e846f009b24fb1bd842b90e2dcd85481136e52588de7982","impliedFormat":99},{"version":"aa70da8072bb8b6e8fae35c7d394d543be8e5c946dad666225a3475010fd2bf0","impliedFormat":99},{"version":"d2c35cb9836cae1899ae9e7e114410dc128bcff4a79cc26318db285699e0223a","impliedFormat":99},{"version":"f89fbb50fd3736e09b418a2e66b98ff9a04820259856afe54bc67977e1acd05b","impliedFormat":99},{"version":"4c76aceec7002f299d9a57ec8e6623f3573bea208b1ea51cc5ea03bf140adad4","impliedFormat":99},{"version":"a0f217b01453d43058cea514325ac8bd3ac3a184265314429eec8059c62824b6","impliedFormat":99},{"version":"c73e552e79763809a52f967e48b7a96a0c164c672ef99de1fa8a7e9e02e3b177","impliedFormat":99},{"version":"3bb351642082a63b4565d8354455bb752daa8902451cd851d6235e04cfaff5a9","impliedFormat":99},{"version":"caa4ee2fefd75dd8bf98a9421e3f99f6c7e70c30b21e78384ed23903a04579e5","impliedFormat":99},{"version":"aecd83ca7059d21a33fb7ed01dfa06a36c545698dbe0017073dba45532a8487d","impliedFormat":99},{"version":"7fb874c17f3c769961d1b07b6bb0ef07b3ca3d49da344726d8b69608997ef190","impliedFormat":99},{"version":"979e969f86456425e505f6054f5d299f848223d70770a5283fa7c405020b47e1","impliedFormat":99},{"version":"7235f928c14f752f6ea3d6d034693c5d46154cce8757a053d9cd6856be2ab344","impliedFormat":99},{"version":"acd7f9268858029bcec5eba752515b9351d4435b21f1956461242c706dcc0cf9","impliedFormat":99},{"version":"53e2856f8644978742fae88b3c7f570ab509dc4d13288b3912a4446993fa3bc7","impliedFormat":99},{"version":"ea2b6112bfd326f1075896bf76c9108dfd08ccbae2482ba31f68ca43f0b59ca5","impliedFormat":99},{"version":"3f9368aa15d0cc227a3af7af3e3df431dadf0f7cd9897fcc54507f7eb68761cc","impliedFormat":99},{"version":"0f2d4be859066fc3ea8d04b583cd0774e1f9dce7f60b9890bcc0a10efb9fac33","impliedFormat":99},{"version":"ac09b9131c553c189311d9e94d3853b7942d0097925304fe043220a893701ce9","impliedFormat":99},{"version":"f1b34ea3d64f73fc79ce1f312589134db27aa78ef9e156a8f14f89f768e800ac","impliedFormat":99},{"version":"873da6c837a1ee62b5f9b286845be06dc887290a75c553bed7f431107d25a3b6","impliedFormat":99},{"version":"b2abee3c001c024d4e552c4a3319bf3fcc94a1f48bb0d21f5d300d9b4920bde9","impliedFormat":99},{"version":"f9740d044306830442cac761b593538117f46c5ea57a8dc6d61f0bee12e971b6","impliedFormat":99},{"version":"7cf786964e26f0e2c3a904f93f6e31609e2636723df8c1ce248d39b55055c89f","impliedFormat":99},{"version":"41c6aff52e4289763ea30f0849b712437aaeb420c8448aeb8047ee2eca4549f4","impliedFormat":99},{"version":"f5db101f7d90f614627bcab5f8d06d9ccd144a1735b475637940c54097786b67","impliedFormat":99},{"version":"8c575a8e1b6032e576577f28d74066f73aefa7a35d741d0015be36956bbc30aa","impliedFormat":99},{"version":"1989cb4fb2174c56b15f8b10d18ecb0c053e7b39f94582581d69767d7bfb9b32","impliedFormat":99},{"version":"cdac1d3e70d332d213295dc438bf78242c29b14534adf3ef404c3e255c66e642","impliedFormat":99},{"version":"47921880701610e8d8a5930d0c9ea03ee9c13773e6665f4ffc8378d5f8c8c168","impliedFormat":99},{"version":"41cbf6c58f2f4e1e5ee95a829b3f193f83952385fa303062f648040a314f939b","impliedFormat":99},{"version":"bb11cd0d046d21d4ae4a28fc4b0eb5d9336a728f9bd489807a6a313142903bc1","impliedFormat":99},{"version":"a96d6463ab2a5a4cf31b01946f1b0929dc3f8be9f28c7c43da29a9e6b7649db1","impliedFormat":99},{"version":"ec43d6b21fd1ed5a1afeb779ceba99e80fe010458bb0a67d9ef301426b1929e5","impliedFormat":99},{"version":"105bb5317c5212d56f82fd9730322b87f4ad8aea2927ef7684341afad050f49b","impliedFormat":99},{"version":"79ffce57ab318282b29bceb505812c490957124a3a96c7d280a342488b0859bf","impliedFormat":99},{"version":"06fd0e1204b7daf4164533fff32ab4e2c1723763c98794f51df417c21e0767f3","impliedFormat":99},{"version":"c4b46086b44bb8816d4a995654c00f64b3601eb50a163f2bba4dfe48ae6c6b91","impliedFormat":99},{"version":"32e670209322bd3692e8fc884c63002f6bd565e83f62f1fd23c46729aa335d1b","impliedFormat":99},{"version":"97717d35deb9f6a6127f3abff60c9af080ab0ccba60aa06a5a3486a374747573","impliedFormat":99},{"version":"4d70c89489fdef067b0819f22eec5fd0323a8b488d93075cb7953bbfc636e03e","impliedFormat":99},{"version":"233dc7f3ea55d2375b32c5c19034babec8e1496dc73784f9b091629a5287f2fe","impliedFormat":99},{"version":"e3fbf3f3e99083f8fc21bbde7677c3b1cad0c730fe231599a69911aa66487d01","impliedFormat":99},{"version":"59110c7d72a09bacde4a80f4ba95d9990b352911f0e4ea09bf766804f8d3e44b","impliedFormat":99},{"version":"3d827d1dd689311e57a98e476b3451445d39e573f4855ac265b7ec1747075c4f","impliedFormat":99},{"version":"e0669b0e7c953962035bb39e7fdfd5cc8fc3d9a666a8b167b78417355609be01","impliedFormat":99},{"version":"8495eef8be427c71a2d574e3ead06c537a9a6d437dd669e6786dab3df009f125","impliedFormat":99},{"version":"15741df16deef60b197560d3cfe45e6c1eff69fa7b85a861e3d8aa8a26683b83","impliedFormat":99},{"version":"802fd034cf22379b22a681e021d7ecc9073c01fccff1eb737f54ee2c6fe4395c","impliedFormat":99},{"version":"bb77b52bead9b75d7173bec685e5e2136f6c3f226cedae736db63a44f69db679","impliedFormat":99},{"version":"b3f7783d4977af919bdb8db798fe185908083c6f4bd3b07460967c8e093f7312","impliedFormat":99},{"version":"5a6bae49831f960e7f0bc66f49b2c40077b136d9573871f865507fde09580436","impliedFormat":99},{"version":"c9d03e6b230acfabb058a0b0391312dfb0e7001bb5955836333a14c7f9347f3e","impliedFormat":99},{"version":"e6295124f95b686a16233c1031d04cd971f9685e3416631f463bde75a5c86ce7","impliedFormat":99},{"version":"00c38bd1fe89fed8d4e8502db4f896aef7415b097ac061c2d65f2b539b6df6a7","impliedFormat":99},{"version":"94a2d7c15538d8e83415299f17fd00ab88c594b6a0a40be1e26c99febbab45f6","impliedFormat":99},{"version":"20bbd68ac2d2e7cdf9f60816ba9b378e13c07f0fdafccf9ae5833c876c6f51bc","impliedFormat":99},{"version":"df109d2490b693bd75105efaae08738ab84102bfdb2eee2372e9e3f369ec5fc2","impliedFormat":99},{"version":"0fabc5da6eb8454effc526d74f28b0abbe726eab0ed1296aa618b611da7d9462","impliedFormat":99},{"version":"d411ba0bcd6a51485be855a01cb95f79649fa90039b4f235ba8481dc68edae3e","impliedFormat":99},{"version":"b1991f24f264ab5e0d4de1a95b8483830ba659016dfe4b9e58b4076974c1966a","impliedFormat":99},{"version":"b8ba23b2e323342f2710619f6c1abf6731da764092cdca12f09b983ebf236d8a","impliedFormat":99},{"version":"6e688e8aeba98c268b195f80355a8d163d87ac135ad03c708ceda608e6e269b2","impliedFormat":99},{"version":"802a6978c1b38822934ce43a3505e13b555584848c50bc5db9deb2e896c0940e","impliedFormat":99},{"version":"f502c7d829f5774109007ec2262c23efc941dd1ce42acc140f293a7c5ccfd25b","impliedFormat":99},{"version":"af3444bd00030bae3bef81569f8703ecddc2e569cb6b728ec045f0d73d47572b","impliedFormat":99},{"version":"53102281f8a153bb051e0223a8dc51ff9c4cf92da127d91e3f60e74b4e8f41ca","impliedFormat":99},{"version":"e402e111fadcd36fa26ea1ad74f3defd6ef478f6d278a69c547e664b57770392","impliedFormat":99},{"version":"bf8f4b3b372e92a4e4942ce7f872b2b1e1bd1d3f8698af21627db2dee0dda813","impliedFormat":99},{"version":"ab8b67c1f76b6586467a8bf7a2e855e8c2eb4e386f1d264dec1d8d877de7210c","impliedFormat":99},{"version":"d6325d809c8396ecc90202ebfd2427e052a77d98cfd4e308f656346baf84106b","impliedFormat":99},{"version":"dad5c38d723d08fc0134279b90fac87441ee99b71b0d30814b86954e0111d504","impliedFormat":99},{"version":"a29375cdd094d8ea5180422fb278f6bcffdeade0280d86d24d77b017a6144833","impliedFormat":99},{"version":"cef653b7f2115c8e2a9b6558bf9a083dbcc37ce8fb6bae0e48cde3b92fdaacb2","impliedFormat":99},{"version":"bb544ec93eab70a6c769cd69c0912742da7c2a8bed7d570e79b8af046a9ca556","impliedFormat":99},{"version":"532bd533a1921eedb9b39fa3559594ab783233867021a7a911db00be5d42fe7a","impliedFormat":99},{"version":"ad48586787d5e217f4fcc229e3c3d8de8aa12979fdf1f186134e3684d56577ac","impliedFormat":99},{"version":"229d6bca5145c86846793cb3166c83abb256cfdb5c425f25ada8eee49c993e54","impliedFormat":99},{"version":"292856f47dad178fe1cb3401554428b3b0157369a8fa52792587fd2bd06fcbec","impliedFormat":99},{"version":"46d372c701338579665c25fb121c836a402409cba9a03d14c403f92a4d6c7852","impliedFormat":99},{"version":"5c390ba8a6920d8d9072b0646388e5a4fa455d6e02cef29164f1c0b917a16f41","impliedFormat":99},{"version":"b8562e5aefa86c069ec1c61dff56ef0492e9fbd731cbcdd4d7fce28a8644e9f6","impliedFormat":99},{"version":"d4df0b60e8672c34a487c685ff7bee9d56ff755c61695bd63d152c331f768cc9","impliedFormat":99},{"version":"dd6c7d6abb025e7494d02fa9f118af4a5ab0217e03ae54dd836f1160cb7a9201","impliedFormat":99},{"version":"82d76af0a89cd5eb4338771a2a5b27f3cbc689b22be0b840de75be4cfc61f864","impliedFormat":99},{"version":"24e856aec3b5c4228ffed866dcd8e7e692aa86eccaecc4fa8205fadd9737d1af","impliedFormat":99},{"version":"fe395a24df9ffd344cb825575d4b35c1cf69275208c0f99517c715bd7d08ff79","impliedFormat":99},{"version":"39e8edcbd5ac35c6cfdf2b1a794a9693a461a54efb2a475ab7fc08ab13504e26","impliedFormat":99},{"version":"12012b6c28d09a6f1d86b2a30213a92a9e92ad9ee573f94c92a8b237b6422bb7","impliedFormat":99},{"version":"8ee28204ddb2be7d6dfb68891493f654cbf10f5e1667bd33bd62920d9eb9e164","impliedFormat":99},{"version":"b09669391dd3312b8a52242af7823a3c44b50c7dcdc216db8da88b679af46574","impliedFormat":99},{"version":"b71e7f69e72d51d44ad171e6e93aedc2c33c339dab5fa2656e7b1ee5ba19b2ad","impliedFormat":99},{"version":"440c9aba92c41b63d718656bd3758f8f98619dbe827448e47601faa51e7a42fa","impliedFormat":99},{"version":"d9cf429fa9667112f53e9bb67bb7b32eeb3697f524d01b9781b65247f1733da4","impliedFormat":99},{"version":"763ee96bd4c739b679a8301b479458ea4fd8166892b2292efe237f2f023f44ca","impliedFormat":99},{"version":"9b10d76e4436eb4ac33c0a5540a02ec881a2fbcfcccfbb9883ebadff7f1d35ad","impliedFormat":99},{"version":"701e25008d343bdd67e02c0ccdce4c2ab41d56645bff646b5dc25e4145e77a3a","impliedFormat":99},{"version":"7a891af63bf06f2be51ed3a67fa974a324d7b917f7b1d10f323ed508a6662354","impliedFormat":99},{"version":"efa0e3dff0199f00eaeb36925776e62419538f7263ec77a56d5612ac5abe9ee2","impliedFormat":99},{"version":"ae6114539394eed7b6305a6d788cb6d2fd94e256d7582f5111a1972ee5a1c455","impliedFormat":99},{"version":"26e8e64bbad8cec5562ca764330c89d2cbe72a10fd7d9f320f16cc25bfe4a1e5","impliedFormat":99},{"version":"3563a343e025cb849b94da85e8455dd89064dee213bc97bbed559f83d74c98de","impliedFormat":99},{"version":"e247d08f342c95e3fd58574f875af23cf50ef53edc811ab8e2accc2f25441f8d","impliedFormat":99},{"version":"420845f2661ac73433cbdc45f36d1f7ca7ea4eca60c3cbd077adf3355387cb63","impliedFormat":99}],"root":[189],"options":{"allowSyntheticDefaultImports":true,"composite":true,"module":99,"skipLibCheck":true,"strict":true},"referencedMap":[[184,1],[182,2],[187,3],[183,1],[185,4],[186,1],[150,2],[98,5],[99,5],[100,6],[55,7],[101,8],[102,9],[103,10],[50,2],[53,11],[51,2],[52,2],[104,12],[105,13],[106,14],[107,15],[108,16],[109,17],[110,17],[111,18],[112,19],[113,20],[114,21],[56,2],[54,2],[115,22],[116,23],[117,24],[149,25],[118,26],[119,27],[120,28],[121,29],[122,30],[123,31],[124,32],[125,33],[126,34],[127,35],[128,35],[129,36],[130,2],[131,37],[133,38],[132,39],[134,40],[135,41],[136,42],[137,43],[138,44],[139,45],[140,46],[141,47],[142,48],[143,49],[144,50],[145,51],[146,52],[57,2],[58,2],[59,2],[97,53],[147,54],[148,55],[192,2],[194,56],[190,2],[193,57],[437,58],[434,59],[436,60],[304,61],[218,62],[303,63],[302,2],[305,64],[217,65],[306,2],[307,2],[308,66],[309,67],[310,67],[311,67],[312,66],[313,67],[316,68],[317,69],[314,2],[315,70],[318,71],[285,72],[206,73],[320,74],[321,75],[284,76],[322,77],[195,2],[199,78],[230,79],[323,2],[228,2],[229,2],[324,80],[325,81],[326,82],[200,83],[201,84],[196,2],[301,85],[300,86],[260,87],[249,2],[250,88],[327,89],[340,2],[341,2],[342,90],[343,91],[344,92],[219,93],[220,94],[221,95],[222,96],[328,97],[330,98],[331,99],[332,100],[333,99],[339,101],[329,100],[334,100],[335,99],[336,100],[337,99],[338,100],[345,81],[346,81],[347,81],[349,102],[348,81],[351,103],[352,81],[353,104],[366,105],[354,103],[355,106],[356,103],[357,81],[350,81],[358,81],[359,107],[360,81],[361,103],[362,81],[363,81],[364,108],[365,81],[368,109],[370,110],[371,111],[372,112],[373,113],[376,114],[377,115],[379,116],[380,117],[383,118],[384,110],[386,119],[387,120],[388,121],[375,122],[374,123],[378,124],[263,125],[390,126],[262,127],[382,128],[381,129],[391,121],[393,130],[392,131],[396,132],[397,133],[398,134],[399,2],[400,135],[401,136],[402,137],[403,133],[404,133],[405,133],[395,138],[406,2],[394,139],[407,140],[408,141],[409,142],[236,143],[237,144],[296,145],[256,146],[238,147],[239,148],[240,149],[241,150],[242,151],[243,152],[244,150],[246,153],[245,150],[247,151],[248,143],[253,154],[252,155],[254,156],[255,143],[267,91],[227,157],[208,158],[207,159],[209,160],[203,161],[258,162],[213,2],[223,163],[411,164],[412,2],[198,165],[204,166],[225,167],[202,168],[299,169],[224,170],[210,160],[389,160],[226,171],[197,172],[211,173],[205,174],[214,175],[215,175],[216,175],[410,175],[413,176],[212,177],[231,177],[414,178],[416,75],[367,179],[415,180],[369,180],[286,181],[417,179],[298,182],[385,183],[257,184],[426,185],[427,186],[319,187],[261,188],[289,189],[418,2],[419,190],[251,191],[420,192],[290,193],[291,194],[421,195],[271,196],[292,197],[293,198],[422,199],[272,2],[423,200],[424,2],[279,201],[294,202],[281,2],[278,203],[295,204],[273,2],[280,205],[425,2],[282,206],[274,207],[276,208],[277,209],[275,210],[287,211],[428,212],[288,213],[264,214],[265,214],[266,215],[429,92],[430,216],[431,216],[232,217],[233,92],[269,218],[270,218],[297,218],[259,92],[432,92],[234,2],[235,219],[433,92],[268,2],[435,2],[283,2],[188,220],[191,2],[157,2],[174,221],[172,222],[173,223],[161,224],[162,222],[169,225],[160,226],[165,227],[175,2],[166,228],[171,229],[177,230],[176,231],[159,232],[167,233],[168,234],[163,235],[170,221],[164,236],[152,237],[151,238],[158,2],[1,2],[48,2],[49,2],[9,2],[13,2],[12,2],[3,2],[14,2],[15,2],[16,2],[17,2],[18,2],[19,2],[20,2],[21,2],[4,2],[22,2],[23,2],[5,2],[24,2],[28,2],[25,2],[26,2],[27,2],[29,2],[30,2],[31,2],[6,2],[32,2],[33,2],[34,2],[35,2],[7,2],[39,2],[36,2],[37,2],[38,2],[40,2],[8,2],[41,2],[46,2],[47,2],[42,2],[43,2],[44,2],[45,2],[2,2],[11,2],[10,2],[75,239],[85,240],[74,239],[95,241],[66,242],[65,243],[94,244],[88,245],[93,246],[68,247],[82,248],[67,249],[91,250],[63,251],[62,244],[92,252],[64,253],[69,254],[70,2],[73,254],[60,2],[96,255],[86,256],[77,257],[78,258],[80,259],[76,260],[79,261],[89,244],[71,262],[72,263],[81,264],[61,265],[84,256],[83,254],[87,2],[90,266],[181,267],[178,268],[156,269],[154,270],[153,2],[155,271],[179,2],[180,272],[189,273]],"latestChangedDtsFile":"./vite.config.d.ts","version":"5.9.3"} \ No newline at end of file diff --git a/packages/webapp/tsconfig.tsbuildinfo b/packages/webapp/tsconfig.tsbuildinfo deleted file mode 100644 index 4f51030..0000000 --- a/packages/webapp/tsconfig.tsbuildinfo +++ /dev/null @@ -1 +0,0 @@ -{"root":["./src/App.tsx","./src/main.tsx","./src/types.ts","./src/vite-env.d.ts","./src/components/Address.tsx","./src/components/AdminsPanel.tsx","./src/components/AdminsTab.tsx","./src/components/ClaimLimitsPanel.tsx","./src/components/CopyInline.tsx","./src/components/EditableName.tsx","./src/components/FeeTab.tsx","./src/components/FundPoolPanel.tsx","./src/components/HistoryTab.tsx","./src/components/IntuitionAtomCard.tsx","./src/components/LaserFlow.tsx","./src/components/Layout.tsx","./src/components/Metric.tsx","./src/components/MetricsTab.tsx","./src/components/NewVersionBanner.tsx","./src/components/OverviewTab.tsx","./src/components/PoolHealthBadge.tsx","./src/components/ReclaimFromPoolPanel.tsx","./src/components/SafeAdminHealthBanner.tsx","./src/components/SafeBadge.tsx","./src/components/SetFeesPanel.tsx","./src/components/Spinner.tsx","./src/components/SponsoringTab.tsx","./src/components/Stat.tsx","./src/components/Tabs.tsx","./src/components/UpgradeAuthorityPanel.tsx","./src/components/VersionsPanel.tsx","./src/components/ViewerBanner.tsx","./src/components/WithdrawPanel.tsx","./src/hooks/useFactory.ts","./src/hooks/useIntuitionAtom.ts","./src/hooks/usePostTxRefreshing.ts","./src/hooks/useProxy.ts","./src/hooks/useProxyAdminRotation.ts","./src/hooks/useProxyRoles.ts","./src/hooks/useSafeStatus.ts","./src/hooks/useSponsoredProxy.ts","./src/hooks/useTabAutoSnap.ts","./src/hooks/useVersionedProxy.ts","./src/lib/addresses.ts","./src/lib/explorers.ts","./src/lib/format.ts","./src/lib/poolHealth.ts","./src/lib/safeDetection.ts","./src/lib/wagmi.ts","./src/pages/Deploy.tsx","./src/pages/Docs.tsx","./src/pages/Explore.tsx","./src/pages/Home.tsx","./src/pages/MyProxies.tsx","./src/pages/ProxyDetail.tsx"],"version":"5.9.3"} \ No newline at end of file