[
  {
    "path": ".gitignore",
    "content": "# Learn more https://docs.github.com/en/get-started/getting-started-with-git/ignoring-files\n\n# dependencies\nnode_modules/\n\n# Expo\n.expo/\ndist/\nweb-build/\nexpo-env.d.ts\n/android/\n/ios/\n\n# Native\n.kotlin/\n*.orig.*\n*.jks\n*.p8\n*.p12\n*.key\n*.mobileprovision\n\n# Metro\n.metro-health-check*\n\n# debug\nnpm-debug.*\nyarn-debug.*\nyarn-error.*\n\n# macOS\n.DS_Store\n*.pem\n\n# local env files\n.env*.local\n\n# typescript\n*.tsbuildinfo\n"
  },
  {
    "path": ".prettierignore",
    "content": "# Dependencies\nnode_modules\n\n# Build outputs\ndist\nbuild\n.expo\n\n# Native builds\nandroid\nios\n\n# Lock files\npackage-lock.json\nyarn.lock\npnpm-lock.yaml\n\n# Coverage\ncoverage\n\n# Generated files\n*.generated.*\n.expo-shared\n\n# Misc\n.git\n*.log\n"
  },
  {
    "path": ".prettierrc",
    "content": "{\n  \"semi\": true,\n  \"singleQuote\": false,\n  \"tabWidth\": 2,\n  \"useTabs\": false,\n  \"trailingComma\": \"all\",\n  \"bracketSpacing\": true,\n  \"arrowParens\": \"always\",\n  \"printWidth\": 100,\n  \"jsxSingleQuote\": false\n}\n"
  },
  {
    "path": "AGENTS.md",
    "content": "# AGENTS.md — eNuts\n\n## Overview\n\n- Expo + React Native app written in TypeScript.\n- `strict` TypeScript enabled in `tsconfig.json`.\n- Entry is `index.ts`; app config in `app.json`.\n- Source lives in `src/` with components, screens, services, context, storage, util.\n- Styling uses `react-native-size-matters` and shared `@styles` theme helpers.\n- i18n uses `react-i18next` with translations in `assets/translations`.\n\n## Commands\n\n### Install\n\n- `npm install`\n\n### Run (Expo)\n\n- `npm run start` (Expo dev server)\n- `npm run android` (run Android device/emulator)\n- `npm run ios` (run iOS simulator)\n\n### Formatting\n\n- `npm run format` (Prettier, repo-wide)\n\n### Build (EAS)\n\n- `npx eas build --profile development`\n- `npx eas build --profile preview`\n- `npx eas build --profile production`\n- Profiles are defined in `eas.json`; requires EAS auth.\n\n### Linting\n\n- No lint script configured in `package.json`.\n- If adding lint, keep it opt-in and align with Prettier.\n\n### Tests\n\n- No test runner configured in `package.json`.\n- No single-test command available yet.\n- If you introduce Jest later, use `npx jest path/to/test -t \"name\"` (convention only).\n\n## Project layout\n\n- `src/components/` reusable UI components and hooks.\n- `src/screens/` screen-level components and flows.\n- `src/context/` React context providers and hooks.\n- `src/services/` app services (seed, NFC, exchange rates).\n- `src/storage/` persistence and database helpers.\n- `src/styles/` theme colors and globals.\n- `src/util/` shared utilities.\n- `assets/` images, lottie, translations.\n\n## Imports and modules\n\n- Prefer path aliases from `tsconfig.json` (`@src`, `@comps`, `@styles`, `@model`, etc.).\n- Keep alias imports grouped together at the top.\n- Follow with external packages, then relative imports.\n- Use `import type` for type-only imports.\n- Avoid unused imports; rely on TypeScript to catch issues.\n\n## Formatting and structure\n\n- Prettier settings: semicolons, double quotes, `printWidth: 100`, trailing commas.\n- Indentation is 2 spaces; no tabs.\n- Keep JSX props each on new line when long.\n- Keep objects and arrays trailing commas for easier diffs.\n- Prefer `const` and `function` declarations over `let`.\n- Avoid inline comments unless requested.\n\n## Types and naming\n\n- Use TypeScript everywhere; avoid `any` unless unavoidable.\n- Prefer `interface` for props and object shapes; prefix with `I` (e.g., `IButtonProps`).\n- Use `type` for unions/utility types; prefix with `T` for nav props (e.g., `TDisplaySettingsPageProps`).\n- Component names are `PascalCase`; hooks are `useCamelCase`.\n- Constants are `SCREAMING_SNAKE_CASE` in `consts/`.\n- File names are `PascalCase` for components, `camelCase` for utilities.\n\n## Components and styling\n\n- Components generally use `export default function ComponentName(...)`.\n- Use `useThemeContext` for theme colors and highlight selection.\n- Prefer `globals(...)` and `@styles` helpers over hard-coded values.\n- Size spacing with `s()` / `ScaledSheet` from `react-native-size-matters`.\n- Use `TouchableOpacity` with `accessibilityRole=\"button\"` where appropriate.\n- Include `testID` attributes when there is an existing pattern.\n\n## State and context\n\n- Context providers live in `src/context/` and are exported as hooks.\n- Keep derived values memoized (`useMemo`) when depending on theme or context.\n- Persist preferences via `@src/storage` helpers.\n- Avoid side effects in render; use `useEffect`.\n\n## Error handling and logging\n\n- Use `try/catch` for async boundaries; log errors via `l` from `@log`.\n- Return `null`/fallback values when a feature can gracefully degrade.\n- Throw errors in services only for unrecoverable state (e.g., missing mnemonic).\n- Avoid swallowing errors without logging.\n\n## i18n and strings\n\n- Use `useTranslation` and `NS` namespaces for UI strings.\n- Add translations to `assets/translations/*.json` when new keys are introduced.\n- Keep user-visible strings out of services/utilities where possible.\n\n## Data and storage\n\n- Sensitive data uses `expo-secure-store` abstractions in `src/storage`.\n- Keep data models in `src/model/` and re-export via `@model`.\n- Prefer typed storage accessors over raw `SecureStore` calls.\n\n## Networking\n\n- Use `fetch` with typed responses where possible.\n- Validate input strings before network calls (e.g., LNURL parsing).\n- Handle `.onion` domains via `http` when required.\n\n## Navigation\n\n- Navigation types live in `src/model/nav.ts` and `src/nav/navTypes.ts`.\n- Screen components should accept typed nav props.\n\n## Testing notes\n\n- There are currently no test files or test scripts.\n- If you add tests, keep them colocated with features or in a `__tests__` folder.\n- Prefer deterministic tests and avoid network calls; mock where needed.\n\n## Formatting quick check\n\n- Run `npm run format` before submitting changes.\n- If format changes are large, scope to touched files when possible.\n\n## Cursor/Copilot rules\n\n- No `.cursor/rules/`, `.cursorrules`, or `.github/copilot-instructions.md` found.\n- If added later, follow them as higher priority.\n\n## PR hygiene (if contributing)\n\n- Keep commits focused and small.\n- Avoid unrelated refactors during feature work.\n- Note any missing tests in PR description.\n\n## Common pitfalls\n\n- Don’t hard-code colors; use theme helpers.\n- Don’t bypass `SecureStore` for secrets.\n- Ensure `await` is used for async storage calls.\n- Avoid using `any` to silence type errors.\n\n## File references\n\n- `package.json` for scripts.\n- `.prettierrc` for formatting.\n- `tsconfig.json` for path aliases and strict mode.\n- `app.json` and `eas.json` for Expo/EAS config.\n\n## Notes for agents\n\n- Respect existing patterns and naming.\n- Keep changes minimal and localized.\n- Ask before adding new dependencies.\n- Avoid writing new docs unless requested.\n- Use `edit` tool for modifications.\n- Re-run formatting after structural refactors.\n- Update translation files for any new UI string.\n- Ensure navigation types stay in sync.\n- Keep sample data localized to dev builds.\n"
  },
  {
    "path": "TODO.md",
    "content": "# TODO\n\n## Typecheck cleanup\n\nThese are the best next targets because they block `npx tsc --noEmit` from being useful as a regression check.\n\n- [x] Remove stale `selectMintToSwapTo` route.\n  - Removed the unreachable route registration, route type, screen prop type, and screen file.\n\n- [ ] Fix stale route types in `src/components/Empty.tsx`.\n  - Current type references old routes: `\"nostrReceive\"` and `\"qr scan\"`.\n  - Replace with a generic `NativeStackNavigationProp<RootStackParamList>` or a narrower current route type.\n\n- [ ] Clean up payment overview residue in `src/screens/Payment/Send/CoinSelection.tsx`.\n  - Remove the missing `_testmintUrl` import from `@consts`.\n  - Check whether `url`, `scanned`, and `trustMintRef` are still needed.\n\n- [ ] Fix utility module type errors in `src/util/index.ts`.\n  - Import or remove the `IContact` dependency used by `uniqByIContacts`.\n  - Fix `decodeLnInvoice`, which currently calls `decodeInvoice` without an import/provider.\n\n- [ ] Fix environment typing in `src/consts/env.ts`.\n  - TypeScript cannot resolve the `expo-constants` import from the root dependency graph.\n  - Add declarations or remove direct global references for `__TEST__` and `jest`.\n\n- [ ] Fix i18n key typing errors.\n  - `src/components/MintSelectionSheet.tsx` has a union key call for `\"selectMint\" | \"selectMints\"` that does not satisfy the typed `t` overload.\n  - `src/screens/Payment/Processing.tsx` has a similar dynamic key issue for processing status strings.\n\n## Parser/payment follow-ups\n\n- [ ] Add a QR chooser for unified requests with multiple supported candidates.\n  - Current QR policy chooses by priority.\n  - A chooser is better when a unified request contains both a Cashu payment request and a Lightning invoice.\n\n- [ ] Implement Cashu payment request execution from QR.\n  - QR currently recognizes `cashuPaymentRequest` candidates but shows an unsupported prompt.\n  - NFC already extracts and executes Cashu payment requests through `manager.paymentRequests`.\n\n- [ ] Add focused parser coverage once a test runner exists.\n  - Direct Cashu token.\n  - Direct Lightning invoice.\n  - Lightning address.\n  - LNURL.\n  - Direct `creq...`.\n  - `bitcoin:` with address plus `lightning=...`.\n  - `bitcoin:` with `creq=...`.\n  - `bitcoin:` with multiple supported fallbacks.\n\n## Lower-priority cleanup\n\n- [ ] Reduce noisy debug logging in `src/shim.ts`.\n  - It logs crypto polyfill setup details on startup.\n\n- [ ] Review `src/screens/Payment/MeltInput.tsx` for extraction opportunities.\n  - The file is large and still owns request parsing, LNURL amount flow, mint selection, operation preparation, confirmation, cancellation, and success routing.\n  - Do this after typecheck is cleaner, so behavior changes are easier to validate.\n\n- [ ] Review broad `any` and modal backdrop types.\n  - Several bottom-sheet components type backdrop props as `any`.\n  - This is lower priority than the current typecheck blockers.\n"
  },
  {
    "path": "app.json",
    "content": "{\n  \"expo\": {\n    \"name\": \"eNuts\",\n    \"slug\": \"enuts\",\n    \"version\": \"1.0.0\",\n    \"orientation\": \"portrait\",\n    \"icon\": \"./assets/app-icon-all.png\",\n    \"userInterfaceStyle\": \"automatic\",\n    \"newArchEnabled\": true,\n    \"splash\": {\n      \"image\": \"./assets/splash.png\",\n      \"resizeMode\": \"contain\",\n      \"backgroundColor\": \"#5DB075\"\n    },\n    \"ios\": {\n      \"supportsTablet\": true,\n      \"bundleIdentifier\": \"com.cypherbase.eNuts\",\n      \"entitlements\": {\n        \"com.apple.developer.nfc.readersession.formats\": [\"TAG\"]\n      },\n      \"infoPlist\": {\n        \"ITSAppUsesNonExemptEncryption\": false\n      }\n    },\n    \"android\": {\n      \"adaptiveIcon\": {\n        \"foregroundImage\": \"./assets/app-icon-android-adaptive-foreground.png\",\n        \"backgroundImage\": \"./assets/app-icon-android-adaptive-background.png\",\n        \"backgroundColor\": \"#ffffff\"\n      },\n      \"edgeToEdgeEnabled\": true,\n      \"permissions\": [\"android.permission.CAMERA\", \"android.permission.NFC\"],\n      \"package\": \"com.cypherbase.eNuts\"\n    },\n    \"plugins\": [\n      \"expo-sqlite\",\n      \"expo-secure-store\",\n      \"expo-localization\",\n      [\n        \"expo-camera\",\n        {\n          \"cameraPermission\": \"Allow $(PRODUCT_NAME) to access your camera to scan QR codes\",\n          \"microphonePermission\": \"Allow $(PRODUCT_NAME) to access your microphone for video recording\",\n          \"recordAudioAndroid\": false\n        }\n      ],\n      [\n        \"react-native-nfc-manager\",\n        {\n          \"selectIdentifiers\": [\"D2760000850101\", \"D2760000850100\"],\n          \"includeNdefEntitlement\": false\n        }\n      ]\n    ],\n    \"extra\": {\n      \"eas\": {\n        \"projectId\": \"3cc1ef51-5bef-42a4-8b6b-a1bb802d46a4\"\n      }\n    },\n    \"owner\": \"egge\"\n  }\n}\n"
  },
  {
    "path": "assets/lottie/confetti.json",
    "content": "{\n  \"v\": \"5.5.6\",\n  \"fr\": 60,\n  \"ip\": 0,\n  \"op\": 300,\n  \"w\": 609,\n  \"h\": 812,\n  \"nm\": \"lottie (mobile)\",\n  \"ddd\": 0,\n  \"assets\": [\n    {\n      \"id\": \"comp_0\",\n      \"layers\": [\n        {\n          \"ddd\": 0,\n          \"ind\": 1,\n          \"ty\": 0,\n          \"nm\": \"_small-side\",\n          \"refId\": \"comp_1\",\n          \"sr\": 1,\n          \"ks\": {\n            \"o\": {\n              \"a\": 0,\n              \"k\": 100,\n              \"ix\": 11\n            },\n            \"r\": {\n              \"a\": 0,\n              \"k\": 0,\n              \"ix\": 10\n            },\n            \"p\": {\n              \"a\": 0,\n              \"k\": [218, 320, 0],\n              \"ix\": 2\n            },\n            \"a\": {\n              \"a\": 0,\n              \"k\": [400, 400, 0],\n              \"ix\": 1\n            },\n            \"s\": {\n              \"a\": 0,\n              \"k\": [-100, 100, 100],\n              \"ix\": 6\n            }\n          },\n          \"ao\": 0,\n          \"w\": 800,\n          \"h\": 800,\n          \"ip\": 15,\n          \"op\": 234,\n          \"st\": 15,\n          \"bm\": 0\n        }\n      ]\n    },\n    {\n      \"id\": \"comp_1\",\n      \"layers\": [\n        {\n          \"ddd\": 0,\n          \"ind\": 1,\n          \"ty\": 4,\n          \"nm\": \"streamer b\",\n          \"sr\": 1,\n          \"ks\": {\n            \"o\": {\n              \"a\": 0,\n              \"k\": 100,\n              \"ix\": 11\n            },\n            \"r\": {\n              \"a\": 0,\n              \"k\": 166,\n              \"ix\": 10\n            },\n            \"p\": {\n              \"a\": 0,\n              \"k\": [554, 664, 0],\n              \"ix\": 2\n            },\n            \"a\": {\n              \"a\": 0,\n              \"k\": [-157, -245, 0],\n              \"ix\": 1\n            },\n            \"s\": {\n              \"a\": 0,\n              \"k\": [100, 100, 100],\n              \"ix\": 6\n            }\n          },\n          \"ao\": 0,\n          \"shapes\": [\n            {\n              \"ty\": \"gr\",\n              \"it\": [\n                {\n                  \"ind\": 0,\n                  \"ty\": \"sh\",\n                  \"ix\": 1,\n                  \"ks\": {\n                    \"a\": 0,\n                    \"k\": {\n                      \"i\": [\n                        [0, 0],\n                        [-1.685, -13.314],\n                        [0, -14.907],\n                        [0, -15.206],\n                        [0, -14.907],\n                        [0, -14.907],\n                        [0, -15.206],\n                        [1.754, -14.206],\n                        [-3.934, -9.465]\n                      ],\n                      \"o\": [\n                        [-3.895, 8.562],\n                        [1.872, 14.789],\n                        [0, 15.206],\n                        [0, 14.907],\n                        [0, 14.907],\n                        [0, 15.206],\n                        [0, 14.314],\n                        [-1.803, 14.605],\n                        [0, 0]\n                      ],\n                      \"v\": [\n                        [-156.5, -406],\n                        [-166.5, -367],\n                        [-146.5, -327],\n                        [-166.5, -286],\n                        [-146.5, -246],\n                        [-166.5, -206],\n                        [-146.5, -165],\n                        [-166.5, -127],\n                        [-156.5, -84]\n                      ],\n                      \"c\": false\n                    },\n                    \"ix\": 2\n                  },\n                  \"nm\": \"Path 1\",\n                  \"mn\": \"ADBE Vector Shape - Group\",\n                  \"hd\": false\n                },\n                {\n                  \"ty\": \"st\",\n                  \"c\": {\n                    \"a\": 0,\n                    \"k\": [1, 0.2627450980392157, 0.2, 1],\n                    \"ix\": 3\n                  },\n                  \"o\": {\n                    \"a\": 0,\n                    \"k\": 100,\n                    \"ix\": 4\n                  },\n                  \"w\": {\n                    \"a\": 1,\n                    \"k\": [\n                      {\n                        \"i\": {\n                          \"x\": [0.833],\n                          \"y\": [0.833]\n                        },\n                        \"o\": {\n                          \"x\": [0.167],\n                          \"y\": [0.167]\n                        },\n                        \"t\": 9,\n                        \"s\": [4]\n                      },\n                      {\n                        \"t\": 57,\n                        \"s\": [0.5]\n                      }\n                    ],\n                    \"ix\": 5\n                  },\n                  \"lc\": 2,\n                  \"lj\": 2,\n                  \"bm\": 0,\n                  \"nm\": \"Stroke 1\",\n                  \"mn\": \"ADBE Vector Graphic - Stroke\",\n                  \"hd\": false\n                },\n                {\n                  \"ty\": \"tr\",\n                  \"p\": {\n                    \"a\": 0,\n                    \"k\": [0, 0],\n                    \"ix\": 2\n                  },\n                  \"a\": {\n                    \"a\": 0,\n                    \"k\": [0, 0],\n                    \"ix\": 1\n                  },\n                  \"s\": {\n                    \"a\": 0,\n                    \"k\": [100, 100],\n                    \"ix\": 3\n                  },\n                  \"r\": {\n                    \"a\": 0,\n                    \"k\": 0,\n                    \"ix\": 6\n                  },\n                  \"o\": {\n                    \"a\": 0,\n                    \"k\": 100,\n                    \"ix\": 7\n                  },\n                  \"sk\": {\n                    \"a\": 0,\n                    \"k\": 0,\n                    \"ix\": 4\n                  },\n                  \"sa\": {\n                    \"a\": 0,\n                    \"k\": 0,\n                    \"ix\": 5\n                  },\n                  \"nm\": \"Transform\"\n                }\n              ],\n              \"nm\": \"Shape 1\",\n              \"np\": 2,\n              \"cix\": 2,\n              \"bm\": 0,\n              \"ix\": 1,\n              \"mn\": \"ADBE Vector Group\",\n              \"hd\": false\n            },\n            {\n              \"ty\": \"tm\",\n              \"s\": {\n                \"a\": 1,\n                \"k\": [\n                  {\n                    \"i\": {\n                      \"x\": [0.667],\n                      \"y\": [1]\n                    },\n                    \"o\": {\n                      \"x\": [0.167],\n                      \"y\": [0.167]\n                    },\n                    \"t\": 14,\n                    \"s\": [0]\n                  },\n                  {\n                    \"t\": 57,\n                    \"s\": [100]\n                  }\n                ],\n                \"ix\": 1\n              },\n              \"e\": {\n                \"a\": 1,\n                \"k\": [\n                  {\n                    \"i\": {\n                      \"x\": [0.833],\n                      \"y\": [0.833]\n                    },\n                    \"o\": {\n                      \"x\": [0.167],\n                      \"y\": [0.167]\n                    },\n                    \"t\": 9,\n                    \"s\": [0]\n                  },\n                  {\n                    \"i\": {\n                      \"x\": [0.667],\n                      \"y\": [1]\n                    },\n                    \"o\": {\n                      \"x\": [0.167],\n                      \"y\": [0.167]\n                    },\n                    \"t\": 14,\n                    \"s\": [35]\n                  },\n                  {\n                    \"t\": 57,\n                    \"s\": [100]\n                  }\n                ],\n                \"ix\": 2\n              },\n              \"o\": {\n                \"a\": 0,\n                \"k\": 0,\n                \"ix\": 3\n              },\n              \"m\": 1,\n              \"ix\": 2,\n              \"nm\": \"Trim Paths 1\",\n              \"mn\": \"ADBE Vector Filter - Trim\",\n              \"hd\": false\n            }\n          ],\n          \"ip\": 9,\n          \"op\": 58,\n          \"st\": 9,\n          \"bm\": 0\n        },\n        {\n          \"ddd\": 0,\n          \"ind\": 2,\n          \"ty\": 4,\n          \"nm\": \"streamer a\",\n          \"sr\": 1,\n          \"ks\": {\n            \"o\": {\n              \"a\": 0,\n              \"k\": 100,\n              \"ix\": 11\n            },\n            \"r\": {\n              \"a\": 0,\n              \"k\": 167,\n              \"ix\": 10\n            },\n            \"p\": {\n              \"a\": 0,\n              \"k\": [532, 582, 0],\n              \"ix\": 2\n            },\n            \"a\": {\n              \"a\": 0,\n              \"k\": [-157, -245, 0],\n              \"ix\": 1\n            },\n            \"s\": {\n              \"a\": 0,\n              \"k\": [-100, 100, 100],\n              \"ix\": 6\n            }\n          },\n          \"ao\": 0,\n          \"shapes\": [\n            {\n              \"ty\": \"gr\",\n              \"it\": [\n                {\n                  \"ind\": 0,\n                  \"ty\": \"sh\",\n                  \"ix\": 1,\n                  \"ks\": {\n                    \"a\": 0,\n                    \"k\": {\n                      \"i\": [\n                        [0, 0],\n                        [-1.685, -13.314],\n                        [0, -14.907],\n                        [0, -15.206],\n                        [0, -14.907],\n                        [0, -14.907],\n                        [0, -15.206],\n                        [1.754, -14.206],\n                        [-3.934, -9.465]\n                      ],\n                      \"o\": [\n                        [-3.895, 8.562],\n                        [1.872, 14.789],\n                        [0, 15.206],\n                        [0, 14.907],\n                        [0, 14.907],\n                        [0, 15.206],\n                        [0, 14.314],\n                        [-1.803, 14.605],\n                        [0, 0]\n                      ],\n                      \"v\": [\n                        [-156.5, -406],\n                        [-166.5, -367],\n                        [-146.5, -327],\n                        [-166.5, -286],\n                        [-146.5, -246],\n                        [-166.5, -206],\n                        [-146.5, -165],\n                        [-166.5, -127],\n                        [-156.5, -84]\n                      ],\n                      \"c\": false\n                    },\n                    \"ix\": 2\n                  },\n                  \"nm\": \"Path 1\",\n                  \"mn\": \"ADBE Vector Shape - Group\",\n                  \"hd\": false\n                },\n                {\n                  \"ty\": \"st\",\n                  \"c\": {\n                    \"a\": 0,\n                    \"k\": [1, 0.12156862745098039, 0.5647058823529412, 1],\n                    \"ix\": 3\n                  },\n                  \"o\": {\n                    \"a\": 0,\n                    \"k\": 100,\n                    \"ix\": 4\n                  },\n                  \"w\": {\n                    \"a\": 1,\n                    \"k\": [\n                      {\n                        \"i\": {\n                          \"x\": [0.833],\n                          \"y\": [0.833]\n                        },\n                        \"o\": {\n                          \"x\": [0.167],\n                          \"y\": [0.167]\n                        },\n                        \"t\": 5,\n                        \"s\": [4]\n                      },\n                      {\n                        \"t\": 48,\n                        \"s\": [0.5]\n                      }\n                    ],\n                    \"ix\": 5\n                  },\n                  \"lc\": 2,\n                  \"lj\": 2,\n                  \"bm\": 0,\n                  \"nm\": \"Stroke 1\",\n                  \"mn\": \"ADBE Vector Graphic - Stroke\",\n                  \"hd\": false\n                },\n                {\n                  \"ty\": \"tr\",\n                  \"p\": {\n                    \"a\": 0,\n                    \"k\": [0, 0],\n                    \"ix\": 2\n                  },\n                  \"a\": {\n                    \"a\": 0,\n                    \"k\": [0, 0],\n                    \"ix\": 1\n                  },\n                  \"s\": {\n                    \"a\": 0,\n                    \"k\": [100, 100],\n                    \"ix\": 3\n                  },\n                  \"r\": {\n                    \"a\": 0,\n                    \"k\": 0,\n                    \"ix\": 6\n                  },\n                  \"o\": {\n                    \"a\": 0,\n                    \"k\": 100,\n                    \"ix\": 7\n                  },\n                  \"sk\": {\n                    \"a\": 0,\n                    \"k\": 0,\n                    \"ix\": 4\n                  },\n                  \"sa\": {\n                    \"a\": 0,\n                    \"k\": 0,\n                    \"ix\": 5\n                  },\n                  \"nm\": \"Transform\"\n                }\n              ],\n              \"nm\": \"Shape 1\",\n              \"np\": 2,\n              \"cix\": 2,\n              \"bm\": 0,\n              \"ix\": 1,\n              \"mn\": \"ADBE Vector Group\",\n              \"hd\": false\n            },\n            {\n              \"ty\": \"tm\",\n              \"s\": {\n                \"a\": 1,\n                \"k\": [\n                  {\n                    \"i\": {\n                      \"x\": [0.667],\n                      \"y\": [1]\n                    },\n                    \"o\": {\n                      \"x\": [0.167],\n                      \"y\": [0.167]\n                    },\n                    \"t\": 10,\n                    \"s\": [0]\n                  },\n                  {\n                    \"t\": 48,\n                    \"s\": [100]\n                  }\n                ],\n                \"ix\": 1\n              },\n              \"e\": {\n                \"a\": 1,\n                \"k\": [\n                  {\n                    \"i\": {\n                      \"x\": [0.833],\n                      \"y\": [0.833]\n                    },\n                    \"o\": {\n                      \"x\": [0.167],\n                      \"y\": [0.167]\n                    },\n                    \"t\": 5,\n                    \"s\": [0]\n                  },\n                  {\n                    \"i\": {\n                      \"x\": [0.667],\n                      \"y\": [1]\n                    },\n                    \"o\": {\n                      \"x\": [0.167],\n                      \"y\": [0.167]\n                    },\n                    \"t\": 10,\n                    \"s\": [35]\n                  },\n                  {\n                    \"t\": 48,\n                    \"s\": [100]\n                  }\n                ],\n                \"ix\": 2\n              },\n              \"o\": {\n                \"a\": 0,\n                \"k\": 0,\n                \"ix\": 3\n              },\n              \"m\": 1,\n              \"ix\": 2,\n              \"nm\": \"Trim Paths 1\",\n              \"mn\": \"ADBE Vector Filter - Trim\",\n              \"hd\": false\n            }\n          ],\n          \"ip\": 5,\n          \"op\": 49,\n          \"st\": 5,\n          \"bm\": 0\n        },\n        {\n          \"ddd\": 0,\n          \"ind\": 3,\n          \"ty\": 4,\n          \"nm\": \"circle a\",\n          \"sr\": 1,\n          \"ks\": {\n            \"o\": {\n              \"a\": 0,\n              \"k\": 100,\n              \"ix\": 11\n            },\n            \"r\": {\n              \"a\": 1,\n              \"k\": [\n                {\n                  \"i\": {\n                    \"x\": [0.667],\n                    \"y\": [1]\n                  },\n                  \"o\": {\n                    \"x\": [0.167],\n                    \"y\": [0.167]\n                  },\n                  \"t\": 1,\n                  \"s\": [0]\n                },\n                {\n                  \"i\": {\n                    \"x\": [0.833],\n                    \"y\": [0.833]\n                  },\n                  \"o\": {\n                    \"x\": [0.333],\n                    \"y\": [0]\n                  },\n                  \"t\": 29,\n                  \"s\": [321.019]\n                },\n                {\n                  \"t\": 158,\n                  \"s\": [1800]\n                }\n              ],\n              \"ix\": 10\n            },\n            \"p\": {\n              \"a\": 1,\n              \"k\": [\n                {\n                  \"i\": {\n                    \"x\": 0.667,\n                    \"y\": 1\n                  },\n                  \"o\": {\n                    \"x\": 0.167,\n                    \"y\": 0.167\n                  },\n                  \"t\": 1,\n                  \"s\": [599.5, 838, 0],\n                  \"to\": [-30, -106.667, 0],\n                  \"ti\": [46.667, 0, 0]\n                },\n                {\n                  \"i\": {\n                    \"x\": 0.833,\n                    \"y\": 0.833\n                  },\n                  \"o\": {\n                    \"x\": 0.333,\n                    \"y\": 0\n                  },\n                  \"t\": 29,\n                  \"s\": [419.5, 198, 0],\n                  \"to\": [-46.667, 0, 0],\n                  \"ti\": [0, 0, 0]\n                },\n                {\n                  \"t\": 158,\n                  \"s\": [319.5, 838, 0]\n                }\n              ],\n              \"ix\": 2\n            },\n            \"a\": {\n              \"a\": 0,\n              \"k\": [0, 0, 0],\n              \"ix\": 1\n            },\n            \"s\": {\n              \"a\": 1,\n              \"k\": [\n                {\n                  \"i\": {\n                    \"x\": [0.667, 0.667, 0.667],\n                    \"y\": [1, 1, 1]\n                  },\n                  \"o\": {\n                    \"x\": [0.167, 0.167, 0.167],\n                    \"y\": [0.167, 0, 0]\n                  },\n                  \"t\": 1,\n                  \"s\": [50, 100, 100]\n                },\n                {\n                  \"i\": {\n                    \"x\": [0.833, 0.833, 0.833],\n                    \"y\": [1, 0.833, 1]\n                  },\n                  \"o\": {\n                    \"x\": [0.333, 0.333, 0.333],\n                    \"y\": [0, 0, 0]\n                  },\n                  \"t\": 29,\n                  \"s\": [100, 100, 100]\n                },\n                {\n                  \"t\": 128,\n                  \"s\": [100, 50, 100]\n                }\n              ],\n              \"ix\": 6\n            }\n          },\n          \"ao\": 0,\n          \"shapes\": [\n            {\n              \"ty\": \"gr\",\n              \"it\": [\n                {\n                  \"d\": 1,\n                  \"ty\": \"el\",\n                  \"s\": {\n                    \"a\": 0,\n                    \"k\": [16, 16],\n                    \"ix\": 2\n                  },\n                  \"p\": {\n                    \"a\": 0,\n                    \"k\": [0, 0],\n                    \"ix\": 3\n                  },\n                  \"nm\": \"Ellipse Path 1\",\n                  \"mn\": \"ADBE Vector Shape - Ellipse\",\n                  \"hd\": false\n                },\n                {\n                  \"ty\": \"fl\",\n                  \"c\": {\n                    \"a\": 0,\n                    \"k\": [0.12156862745098039, 0.8431372549019608, 1, 1],\n                    \"ix\": 4\n                  },\n                  \"o\": {\n                    \"a\": 0,\n                    \"k\": 100,\n                    \"ix\": 5\n                  },\n                  \"r\": 1,\n                  \"bm\": 0,\n                  \"nm\": \"Fill 1\",\n                  \"mn\": \"ADBE Vector Graphic - Fill\",\n                  \"hd\": false\n                },\n                {\n                  \"ty\": \"tr\",\n                  \"p\": {\n                    \"a\": 0,\n                    \"k\": [0, 0],\n                    \"ix\": 2\n                  },\n                  \"a\": {\n                    \"a\": 0,\n                    \"k\": [0, 0],\n                    \"ix\": 1\n                  },\n                  \"s\": {\n                    \"a\": 0,\n                    \"k\": [100, 100],\n                    \"ix\": 3\n                  },\n                  \"r\": {\n                    \"a\": 0,\n                    \"k\": 0,\n                    \"ix\": 6\n                  },\n                  \"o\": {\n                    \"a\": 0,\n                    \"k\": 100,\n                    \"ix\": 7\n                  },\n                  \"sk\": {\n                    \"a\": 0,\n                    \"k\": 0,\n                    \"ix\": 4\n                  },\n                  \"sa\": {\n                    \"a\": 0,\n                    \"k\": 0,\n                    \"ix\": 5\n                  },\n                  \"nm\": \"Transform\"\n                }\n              ],\n              \"nm\": \"Ellipse 1\",\n              \"np\": 2,\n              \"cix\": 2,\n              \"bm\": 0,\n              \"ix\": 1,\n              \"mn\": \"ADBE Vector Group\",\n              \"hd\": false\n            }\n          ],\n          \"ip\": 1,\n          \"op\": 159,\n          \"st\": 1,\n          \"bm\": 0\n        },\n        {\n          \"ddd\": 0,\n          \"ind\": 4,\n          \"ty\": 4,\n          \"nm\": \"circle b\",\n          \"sr\": 1,\n          \"ks\": {\n            \"o\": {\n              \"a\": 0,\n              \"k\": 50,\n              \"ix\": 11\n            },\n            \"r\": {\n              \"a\": 1,\n              \"k\": [\n                {\n                  \"i\": {\n                    \"x\": [0.833],\n                    \"y\": [0.833]\n                  },\n                  \"o\": {\n                    \"x\": [0.167],\n                    \"y\": [0.167]\n                  },\n                  \"t\": 3,\n                  \"s\": [0]\n                },\n                {\n                  \"t\": 128,\n                  \"s\": [1440]\n                }\n              ],\n              \"ix\": 10\n            },\n            \"p\": {\n              \"a\": 1,\n              \"k\": [\n                {\n                  \"i\": {\n                    \"x\": 0.667,\n                    \"y\": 1\n                  },\n                  \"o\": {\n                    \"x\": 0.167,\n                    \"y\": 0.167\n                  },\n                  \"t\": 3,\n                  \"s\": [599.5, 838, 0],\n                  \"to\": [-26.667, -93.333, 0],\n                  \"ti\": [66.667, 0, 0]\n                },\n                {\n                  \"i\": {\n                    \"x\": 0.833,\n                    \"y\": 0.833\n                  },\n                  \"o\": {\n                    \"x\": 0.333,\n                    \"y\": 0\n                  },\n                  \"t\": 21,\n                  \"s\": [439.5, 278, 0],\n                  \"to\": [-66.667, 0, 0],\n                  \"ti\": [0, 0, 0]\n                },\n                {\n                  \"t\": 128,\n                  \"s\": [199.5, 838, 0]\n                }\n              ],\n              \"ix\": 2\n            },\n            \"a\": {\n              \"a\": 0,\n              \"k\": [0, 0, 0],\n              \"ix\": 1\n            },\n            \"s\": {\n              \"a\": 1,\n              \"k\": [\n                {\n                  \"i\": {\n                    \"x\": [0.667, 0.667, 0.667],\n                    \"y\": [1, 1, 1]\n                  },\n                  \"o\": {\n                    \"x\": [0.167, 0.167, 0.167],\n                    \"y\": [0.167, 0, 0]\n                  },\n                  \"t\": 3,\n                  \"s\": [50, 100, 100]\n                },\n                {\n                  \"i\": {\n                    \"x\": [0.833, 0.833, 0.833],\n                    \"y\": [1, 0.833, 1]\n                  },\n                  \"o\": {\n                    \"x\": [0.333, 0.333, 0.333],\n                    \"y\": [0, 0, 0]\n                  },\n                  \"t\": 21,\n                  \"s\": [100, 100, 100]\n                },\n                {\n                  \"t\": 98,\n                  \"s\": [100, 50, 100]\n                }\n              ],\n              \"ix\": 6\n            }\n          },\n          \"ao\": 0,\n          \"shapes\": [\n            {\n              \"ty\": \"gr\",\n              \"it\": [\n                {\n                  \"d\": 1,\n                  \"ty\": \"el\",\n                  \"s\": {\n                    \"a\": 0,\n                    \"k\": [16, 16],\n                    \"ix\": 2\n                  },\n                  \"p\": {\n                    \"a\": 0,\n                    \"k\": [0, 0],\n                    \"ix\": 3\n                  },\n                  \"nm\": \"Ellipse Path 1\",\n                  \"mn\": \"ADBE Vector Shape - Ellipse\",\n                  \"hd\": false\n                },\n                {\n                  \"ty\": \"fl\",\n                  \"c\": {\n                    \"a\": 0,\n                    \"k\": [1, 0.12156862745098039, 0.5647058823529412, 1],\n                    \"ix\": 4\n                  },\n                  \"o\": {\n                    \"a\": 0,\n                    \"k\": 100,\n                    \"ix\": 5\n                  },\n                  \"r\": 1,\n                  \"bm\": 0,\n                  \"nm\": \"Fill 1\",\n                  \"mn\": \"ADBE Vector Graphic - Fill\",\n                  \"hd\": false\n                },\n                {\n                  \"ty\": \"tr\",\n                  \"p\": {\n                    \"a\": 0,\n                    \"k\": [0, 0],\n                    \"ix\": 2\n                  },\n                  \"a\": {\n                    \"a\": 0,\n                    \"k\": [0, 0],\n                    \"ix\": 1\n                  },\n                  \"s\": {\n                    \"a\": 0,\n                    \"k\": [100, 100],\n                    \"ix\": 3\n                  },\n                  \"r\": {\n                    \"a\": 0,\n                    \"k\": 0,\n                    \"ix\": 6\n                  },\n                  \"o\": {\n                    \"a\": 0,\n                    \"k\": 100,\n                    \"ix\": 7\n                  },\n                  \"sk\": {\n                    \"a\": 0,\n                    \"k\": 0,\n                    \"ix\": 4\n                  },\n                  \"sa\": {\n                    \"a\": 0,\n                    \"k\": 0,\n                    \"ix\": 5\n                  },\n                  \"nm\": \"Transform\"\n                }\n              ],\n              \"nm\": \"Ellipse 1\",\n              \"np\": 2,\n              \"cix\": 2,\n              \"bm\": 0,\n              \"ix\": 1,\n              \"mn\": \"ADBE Vector Group\",\n              \"hd\": false\n            }\n          ],\n          \"ip\": 3,\n          \"op\": 129,\n          \"st\": 3,\n          \"bm\": 0\n        },\n        {\n          \"ddd\": 0,\n          \"ind\": 5,\n          \"ty\": 4,\n          \"nm\": \"star a\",\n          \"sr\": 1,\n          \"ks\": {\n            \"o\": {\n              \"a\": 0,\n              \"k\": 100,\n              \"ix\": 11\n            },\n            \"r\": {\n              \"a\": 1,\n              \"k\": [\n                {\n                  \"i\": {\n                    \"x\": [0.667],\n                    \"y\": [1]\n                  },\n                  \"o\": {\n                    \"x\": [0.167],\n                    \"y\": [0.167]\n                  },\n                  \"t\": 1,\n                  \"s\": [0]\n                },\n                {\n                  \"i\": {\n                    \"x\": [0.833],\n                    \"y\": [0.833]\n                  },\n                  \"o\": {\n                    \"x\": [0.333],\n                    \"y\": [0]\n                  },\n                  \"t\": 31,\n                  \"s\": [343.949]\n                },\n                {\n                  \"t\": 158,\n                  \"s\": [1800]\n                }\n              ],\n              \"ix\": 10\n            },\n            \"p\": {\n              \"a\": 1,\n              \"k\": [\n                {\n                  \"i\": {\n                    \"x\": 0.667,\n                    \"y\": 1\n                  },\n                  \"o\": {\n                    \"x\": 0.167,\n                    \"y\": 0.167\n                  },\n                  \"t\": 1,\n                  \"s\": [596.087, 836.292, 0],\n                  \"to\": [-36.098, -100, 0],\n                  \"ti\": [52.765, 0, 0]\n                },\n                {\n                  \"i\": {\n                    \"x\": 0.833,\n                    \"y\": 0.833\n                  },\n                  \"o\": {\n                    \"x\": 0.333,\n                    \"y\": 0\n                  },\n                  \"t\": 31,\n                  \"s\": [379.5, 236.292, 0],\n                  \"to\": [-52.765, 0, 0],\n                  \"ti\": [0, 0, 0]\n                },\n                {\n                  \"t\": 158,\n                  \"s\": [279.5, 836.292, 0]\n                }\n              ],\n              \"ix\": 2\n            },\n            \"a\": {\n              \"a\": 0,\n              \"k\": [0, 0, 0],\n              \"ix\": 1\n            },\n            \"s\": {\n              \"a\": 1,\n              \"k\": [\n                {\n                  \"i\": {\n                    \"x\": [0.667, 0.667, 0.667],\n                    \"y\": [1, 1, 1]\n                  },\n                  \"o\": {\n                    \"x\": [0.167, 0.167, 0.167],\n                    \"y\": [0.167, 0, 0]\n                  },\n                  \"t\": 1,\n                  \"s\": [50, 100, 100]\n                },\n                {\n                  \"i\": {\n                    \"x\": [0.833, 0.833, 0.833],\n                    \"y\": [1, 0.833, 1]\n                  },\n                  \"o\": {\n                    \"x\": [0.333, 0.333, 0.333],\n                    \"y\": [0, 0, 0]\n                  },\n                  \"t\": 31,\n                  \"s\": [100, 100, 100]\n                },\n                {\n                  \"t\": 128,\n                  \"s\": [100, 50, 100]\n                }\n              ],\n              \"ix\": 6\n            }\n          },\n          \"ao\": 0,\n          \"shapes\": [\n            {\n              \"ty\": \"gr\",\n              \"it\": [\n                {\n                  \"ty\": \"sr\",\n                  \"sy\": 1,\n                  \"d\": 1,\n                  \"pt\": {\n                    \"a\": 0,\n                    \"k\": 5,\n                    \"ix\": 3\n                  },\n                  \"p\": {\n                    \"a\": 0,\n                    \"k\": [0, 0],\n                    \"ix\": 4\n                  },\n                  \"r\": {\n                    \"a\": 0,\n                    \"k\": 0,\n                    \"ix\": 5\n                  },\n                  \"ir\": {\n                    \"a\": 0,\n                    \"k\": 5,\n                    \"ix\": 6\n                  },\n                  \"is\": {\n                    \"a\": 0,\n                    \"k\": 0,\n                    \"ix\": 8\n                  },\n                  \"or\": {\n                    \"a\": 0,\n                    \"k\": 12,\n                    \"ix\": 7\n                  },\n                  \"os\": {\n                    \"a\": 0,\n                    \"k\": 0,\n                    \"ix\": 9\n                  },\n                  \"ix\": 1,\n                  \"nm\": \"Polystar Path 1\",\n                  \"mn\": \"ADBE Vector Shape - Star\",\n                  \"hd\": false\n                },\n                {\n                  \"ty\": \"fl\",\n                  \"c\": {\n                    \"a\": 0,\n                    \"k\": [1, 0.2627450980392157, 0.2, 1],\n                    \"ix\": 4\n                  },\n                  \"o\": {\n                    \"a\": 0,\n                    \"k\": 100,\n                    \"ix\": 5\n                  },\n                  \"r\": 1,\n                  \"bm\": 0,\n                  \"nm\": \"Fill 1\",\n                  \"mn\": \"ADBE Vector Graphic - Fill\",\n                  \"hd\": false\n                },\n                {\n                  \"ty\": \"tr\",\n                  \"p\": {\n                    \"a\": 0,\n                    \"k\": [0, 0],\n                    \"ix\": 2\n                  },\n                  \"a\": {\n                    \"a\": 0,\n                    \"k\": [0, 0],\n                    \"ix\": 1\n                  },\n                  \"s\": {\n                    \"a\": 0,\n                    \"k\": [100, 100],\n                    \"ix\": 3\n                  },\n                  \"r\": {\n                    \"a\": 0,\n                    \"k\": 0,\n                    \"ix\": 6\n                  },\n                  \"o\": {\n                    \"a\": 0,\n                    \"k\": 100,\n                    \"ix\": 7\n                  },\n                  \"sk\": {\n                    \"a\": 0,\n                    \"k\": 0,\n                    \"ix\": 4\n                  },\n                  \"sa\": {\n                    \"a\": 0,\n                    \"k\": 0,\n                    \"ix\": 5\n                  },\n                  \"nm\": \"Transform\"\n                }\n              ],\n              \"nm\": \"Polystar 1\",\n              \"np\": 2,\n              \"cix\": 2,\n              \"bm\": 0,\n              \"ix\": 1,\n              \"mn\": \"ADBE Vector Group\",\n              \"hd\": false\n            }\n          ],\n          \"ip\": 1,\n          \"op\": 159,\n          \"st\": 1,\n          \"bm\": 0\n        },\n        {\n          \"ddd\": 0,\n          \"ind\": 6,\n          \"ty\": 4,\n          \"nm\": \"star b\",\n          \"sr\": 1,\n          \"ks\": {\n            \"o\": {\n              \"a\": 0,\n              \"k\": 50,\n              \"ix\": 11\n            },\n            \"r\": {\n              \"a\": 1,\n              \"k\": [\n                {\n                  \"i\": {\n                    \"x\": [0.667],\n                    \"y\": [1]\n                  },\n                  \"o\": {\n                    \"x\": [0.167],\n                    \"y\": [0.167]\n                  },\n                  \"t\": 3,\n                  \"s\": [0]\n                },\n                {\n                  \"i\": {\n                    \"x\": [0.833],\n                    \"y\": [0.833]\n                  },\n                  \"o\": {\n                    \"x\": [0.333],\n                    \"y\": [0]\n                  },\n                  \"t\": 23,\n                  \"s\": [288]\n                },\n                {\n                  \"t\": 128,\n                  \"s\": [1800]\n                }\n              ],\n              \"ix\": 10\n            },\n            \"p\": {\n              \"a\": 1,\n              \"k\": [\n                {\n                  \"i\": {\n                    \"x\": 0.667,\n                    \"y\": 1\n                  },\n                  \"o\": {\n                    \"x\": 0.167,\n                    \"y\": 0.167\n                  },\n                  \"t\": 3,\n                  \"s\": [596.087, 836.292, 0],\n                  \"to\": [-39.431, -113.333, 0],\n                  \"ti\": [66.098, 1.667, 0]\n                },\n                {\n                  \"i\": {\n                    \"x\": 0.833,\n                    \"y\": 0.833\n                  },\n                  \"o\": {\n                    \"x\": 0.333,\n                    \"y\": 0\n                  },\n                  \"t\": 23,\n                  \"s\": [359.5, 156.292, 0],\n                  \"to\": [-66.098, -1.667, 0],\n                  \"ti\": [0, 0, 0]\n                },\n                {\n                  \"t\": 128,\n                  \"s\": [199.5, 826.292, 0]\n                }\n              ],\n              \"ix\": 2\n            },\n            \"a\": {\n              \"a\": 0,\n              \"k\": [0, 0, 0],\n              \"ix\": 1\n            },\n            \"s\": {\n              \"a\": 1,\n              \"k\": [\n                {\n                  \"i\": {\n                    \"x\": [0.667, 0.667, 0.667],\n                    \"y\": [1, 1, 1]\n                  },\n                  \"o\": {\n                    \"x\": [0.167, 0.167, 0.167],\n                    \"y\": [0.167, 0, 0]\n                  },\n                  \"t\": 3,\n                  \"s\": [50, 100, 100]\n                },\n                {\n                  \"i\": {\n                    \"x\": [0.833, 0.833, 0.833],\n                    \"y\": [1, 0.833, 1]\n                  },\n                  \"o\": {\n                    \"x\": [0.333, 0.333, 0.333],\n                    \"y\": [0, 0, 0]\n                  },\n                  \"t\": 23,\n                  \"s\": [100, 100, 100]\n                },\n                {\n                  \"t\": 98,\n                  \"s\": [100, 50, 100]\n                }\n              ],\n              \"ix\": 6\n            }\n          },\n          \"ao\": 0,\n          \"shapes\": [\n            {\n              \"ty\": \"gr\",\n              \"it\": [\n                {\n                  \"ty\": \"sr\",\n                  \"sy\": 1,\n                  \"d\": 1,\n                  \"pt\": {\n                    \"a\": 0,\n                    \"k\": 5,\n                    \"ix\": 3\n                  },\n                  \"p\": {\n                    \"a\": 0,\n                    \"k\": [0, 0],\n                    \"ix\": 4\n                  },\n                  \"r\": {\n                    \"a\": 0,\n                    \"k\": 0,\n                    \"ix\": 5\n                  },\n                  \"ir\": {\n                    \"a\": 0,\n                    \"k\": 5,\n                    \"ix\": 6\n                  },\n                  \"is\": {\n                    \"a\": 0,\n                    \"k\": 0,\n                    \"ix\": 8\n                  },\n                  \"or\": {\n                    \"a\": 0,\n                    \"k\": 12,\n                    \"ix\": 7\n                  },\n                  \"os\": {\n                    \"a\": 0,\n                    \"k\": 0,\n                    \"ix\": 9\n                  },\n                  \"ix\": 1,\n                  \"nm\": \"Polystar Path 1\",\n                  \"mn\": \"ADBE Vector Shape - Star\",\n                  \"hd\": false\n                },\n                {\n                  \"ty\": \"fl\",\n                  \"c\": {\n                    \"a\": 0,\n                    \"k\": [0, 0.5215686274509804, 0.27058823529411763, 1],\n                    \"ix\": 4\n                  },\n                  \"o\": {\n                    \"a\": 0,\n                    \"k\": 100,\n                    \"ix\": 5\n                  },\n                  \"r\": 1,\n                  \"bm\": 0,\n                  \"nm\": \"Fill 1\",\n                  \"mn\": \"ADBE Vector Graphic - Fill\",\n                  \"hd\": false\n                },\n                {\n                  \"ty\": \"tr\",\n                  \"p\": {\n                    \"a\": 0,\n                    \"k\": [0, 0],\n                    \"ix\": 2\n                  },\n                  \"a\": {\n                    \"a\": 0,\n                    \"k\": [0, 0],\n                    \"ix\": 1\n                  },\n                  \"s\": {\n                    \"a\": 0,\n                    \"k\": [100, 100],\n                    \"ix\": 3\n                  },\n                  \"r\": {\n                    \"a\": 0,\n                    \"k\": 0,\n                    \"ix\": 6\n                  },\n                  \"o\": {\n                    \"a\": 0,\n                    \"k\": 100,\n                    \"ix\": 7\n                  },\n                  \"sk\": {\n                    \"a\": 0,\n                    \"k\": 0,\n                    \"ix\": 4\n                  },\n                  \"sa\": {\n                    \"a\": 0,\n                    \"k\": 0,\n                    \"ix\": 5\n                  },\n                  \"nm\": \"Transform\"\n                }\n              ],\n              \"nm\": \"Polystar 1\",\n              \"np\": 2,\n              \"cix\": 2,\n              \"bm\": 0,\n              \"ix\": 1,\n              \"mn\": \"ADBE Vector Group\",\n              \"hd\": false\n            }\n          ],\n          \"ip\": 3,\n          \"op\": 129,\n          \"st\": 3,\n          \"bm\": 0\n        },\n        {\n          \"ddd\": 0,\n          \"ind\": 7,\n          \"ty\": 4,\n          \"nm\": \"rec a\",\n          \"sr\": 1,\n          \"ks\": {\n            \"o\": {\n              \"a\": 0,\n              \"k\": 100,\n              \"ix\": 11\n            },\n            \"r\": {\n              \"a\": 1,\n              \"k\": [\n                {\n                  \"i\": {\n                    \"x\": [0.667],\n                    \"y\": [1]\n                  },\n                  \"o\": {\n                    \"x\": [0.167],\n                    \"y\": [0.167]\n                  },\n                  \"t\": 0,\n                  \"s\": [0]\n                },\n                {\n                  \"i\": {\n                    \"x\": [0.833],\n                    \"y\": [0.833]\n                  },\n                  \"o\": {\n                    \"x\": [0.333],\n                    \"y\": [0]\n                  },\n                  \"t\": 33,\n                  \"s\": [381.468]\n                },\n                {\n                  \"t\": 218,\n                  \"s\": [2520]\n                }\n              ],\n              \"ix\": 10\n            },\n            \"p\": {\n              \"a\": 1,\n              \"k\": [\n                {\n                  \"i\": {\n                    \"x\": 0.667,\n                    \"y\": 1\n                  },\n                  \"o\": {\n                    \"x\": 0.167,\n                    \"y\": 0.167\n                  },\n                  \"t\": 0,\n                  \"s\": [599.5, 842, 0],\n                  \"to\": [-23.333, -100, 0],\n                  \"ti\": [41.333, 1.333, 0]\n                },\n                {\n                  \"i\": {\n                    \"x\": 0.833,\n                    \"y\": 0.833\n                  },\n                  \"o\": {\n                    \"x\": 0.333,\n                    \"y\": 0\n                  },\n                  \"t\": 33,\n                  \"s\": [459.5, 242, 0],\n                  \"to\": [-41.333, -1.333, 0],\n                  \"ti\": [0, 0, 0]\n                },\n                {\n                  \"t\": 218,\n                  \"s\": [351.5, 834, 0]\n                }\n              ],\n              \"ix\": 2\n            },\n            \"a\": {\n              \"a\": 0,\n              \"k\": [0, 0, 0],\n              \"ix\": 1\n            },\n            \"s\": {\n              \"a\": 1,\n              \"k\": [\n                {\n                  \"i\": {\n                    \"x\": [0.667, 0.667, 0.667],\n                    \"y\": [1, 1, 1]\n                  },\n                  \"o\": {\n                    \"x\": [0.167, 0.167, 0.167],\n                    \"y\": [0.167, 0, 0]\n                  },\n                  \"t\": 0,\n                  \"s\": [50, 100, 100]\n                },\n                {\n                  \"i\": {\n                    \"x\": [0.833, 0.833, 0.833],\n                    \"y\": [1, 0.833, 1]\n                  },\n                  \"o\": {\n                    \"x\": [0.333, 0.333, 0.333],\n                    \"y\": [0, 0, 0]\n                  },\n                  \"t\": 33,\n                  \"s\": [100, 100, 100]\n                },\n                {\n                  \"t\": 188,\n                  \"s\": [100, 50, 100]\n                }\n              ],\n              \"ix\": 6\n            }\n          },\n          \"ao\": 0,\n          \"shapes\": [\n            {\n              \"ty\": \"gr\",\n              \"it\": [\n                {\n                  \"ty\": \"rc\",\n                  \"d\": 1,\n                  \"s\": {\n                    \"a\": 0,\n                    \"k\": [16, 8],\n                    \"ix\": 2\n                  },\n                  \"p\": {\n                    \"a\": 0,\n                    \"k\": [0, 0],\n                    \"ix\": 3\n                  },\n                  \"r\": {\n                    \"a\": 0,\n                    \"k\": 0,\n                    \"ix\": 4\n                  },\n                  \"nm\": \"Rectangle Path 1\",\n                  \"mn\": \"ADBE Vector Shape - Rect\",\n                  \"hd\": false\n                },\n                {\n                  \"ty\": \"fl\",\n                  \"c\": {\n                    \"a\": 0,\n                    \"k\": [0.12156862745098039, 0.8431372549019608, 1, 1],\n                    \"ix\": 4\n                  },\n                  \"o\": {\n                    \"a\": 0,\n                    \"k\": 100,\n                    \"ix\": 5\n                  },\n                  \"r\": 1,\n                  \"bm\": 0,\n                  \"nm\": \"Fill 1\",\n                  \"mn\": \"ADBE Vector Graphic - Fill\",\n                  \"hd\": false\n                },\n                {\n                  \"ty\": \"tr\",\n                  \"p\": {\n                    \"a\": 0,\n                    \"k\": [0, 0],\n                    \"ix\": 2\n                  },\n                  \"a\": {\n                    \"a\": 0,\n                    \"k\": [0, 0],\n                    \"ix\": 1\n                  },\n                  \"s\": {\n                    \"a\": 0,\n                    \"k\": [100, 100],\n                    \"ix\": 3\n                  },\n                  \"r\": {\n                    \"a\": 0,\n                    \"k\": 0,\n                    \"ix\": 6\n                  },\n                  \"o\": {\n                    \"a\": 0,\n                    \"k\": 100,\n                    \"ix\": 7\n                  },\n                  \"sk\": {\n                    \"a\": 0,\n                    \"k\": 0,\n                    \"ix\": 4\n                  },\n                  \"sa\": {\n                    \"a\": 0,\n                    \"k\": 0,\n                    \"ix\": 5\n                  },\n                  \"nm\": \"Transform\"\n                }\n              ],\n              \"nm\": \"Rectangle 1\",\n              \"np\": 2,\n              \"cix\": 2,\n              \"bm\": 0,\n              \"ix\": 1,\n              \"mn\": \"ADBE Vector Group\",\n              \"hd\": false\n            }\n          ],\n          \"ip\": 0,\n          \"op\": 219,\n          \"st\": 0,\n          \"bm\": 0\n        },\n        {\n          \"ddd\": 0,\n          \"ind\": 8,\n          \"ty\": 4,\n          \"nm\": \"rec b\",\n          \"sr\": 1,\n          \"ks\": {\n            \"o\": {\n              \"a\": 0,\n              \"k\": 50,\n              \"ix\": 11\n            },\n            \"r\": {\n              \"a\": 1,\n              \"k\": [\n                {\n                  \"i\": {\n                    \"x\": [0.667],\n                    \"y\": [1]\n                  },\n                  \"o\": {\n                    \"x\": [0.167],\n                    \"y\": [0.167]\n                  },\n                  \"t\": 2,\n                  \"s\": [0]\n                },\n                {\n                  \"i\": {\n                    \"x\": [0.833],\n                    \"y\": [0.833]\n                  },\n                  \"o\": {\n                    \"x\": [0.333],\n                    \"y\": [0]\n                  },\n                  \"t\": 25,\n                  \"s\": [262.857]\n                },\n                {\n                  \"t\": 191,\n                  \"s\": [2160]\n                }\n              ],\n              \"ix\": 10\n            },\n            \"p\": {\n              \"a\": 1,\n              \"k\": [\n                {\n                  \"i\": {\n                    \"x\": 0.667,\n                    \"y\": 1\n                  },\n                  \"o\": {\n                    \"x\": 0.167,\n                    \"y\": 0.167\n                  },\n                  \"t\": 2,\n                  \"s\": [599.5, 842, 0],\n                  \"to\": [-23.333, -113.333, 0],\n                  \"ti\": [74, 5, 0]\n                },\n                {\n                  \"i\": {\n                    \"x\": 0.833,\n                    \"y\": 0.833\n                  },\n                  \"o\": {\n                    \"x\": 0.333,\n                    \"y\": 0\n                  },\n                  \"t\": 25,\n                  \"s\": [459.5, 162, 0],\n                  \"to\": [-74, -5, 0],\n                  \"ti\": [0, 0, 0]\n                },\n                {\n                  \"t\": 191,\n                  \"s\": [155.5, 812, 0]\n                }\n              ],\n              \"ix\": 2\n            },\n            \"a\": {\n              \"a\": 0,\n              \"k\": [0, 0, 0],\n              \"ix\": 1\n            },\n            \"s\": {\n              \"a\": 1,\n              \"k\": [\n                {\n                  \"i\": {\n                    \"x\": [0.667, 0.667, 0.667],\n                    \"y\": [1, 1, 1]\n                  },\n                  \"o\": {\n                    \"x\": [0.167, 0.167, 0.167],\n                    \"y\": [0.167, 0, 0]\n                  },\n                  \"t\": 2,\n                  \"s\": [50, 100, 100]\n                },\n                {\n                  \"i\": {\n                    \"x\": [0.833, 0.833, 0.833],\n                    \"y\": [1, 0.833, 1]\n                  },\n                  \"o\": {\n                    \"x\": [0.333, 0.333, 0.333],\n                    \"y\": [0, 0, 0]\n                  },\n                  \"t\": 25,\n                  \"s\": [100, 100, 100]\n                },\n                {\n                  \"t\": 161,\n                  \"s\": [100, 50, 100]\n                }\n              ],\n              \"ix\": 6\n            }\n          },\n          \"ao\": 0,\n          \"shapes\": [\n            {\n              \"ty\": \"gr\",\n              \"it\": [\n                {\n                  \"ty\": \"rc\",\n                  \"d\": 1,\n                  \"s\": {\n                    \"a\": 0,\n                    \"k\": [16, 8],\n                    \"ix\": 2\n                  },\n                  \"p\": {\n                    \"a\": 0,\n                    \"k\": [0, 0],\n                    \"ix\": 3\n                  },\n                  \"r\": {\n                    \"a\": 0,\n                    \"k\": 0,\n                    \"ix\": 4\n                  },\n                  \"nm\": \"Rectangle Path 1\",\n                  \"mn\": \"ADBE Vector Shape - Rect\",\n                  \"hd\": false\n                },\n                {\n                  \"ty\": \"fl\",\n                  \"c\": {\n                    \"a\": 0,\n                    \"k\": [1, 0.12156862745098039, 0.5647058823529412, 1],\n                    \"ix\": 4\n                  },\n                  \"o\": {\n                    \"a\": 0,\n                    \"k\": 100,\n                    \"ix\": 5\n                  },\n                  \"r\": 1,\n                  \"bm\": 0,\n                  \"nm\": \"Fill 1\",\n                  \"mn\": \"ADBE Vector Graphic - Fill\",\n                  \"hd\": false\n                },\n                {\n                  \"ty\": \"tr\",\n                  \"p\": {\n                    \"a\": 0,\n                    \"k\": [0, 0],\n                    \"ix\": 2\n                  },\n                  \"a\": {\n                    \"a\": 0,\n                    \"k\": [0, 0],\n                    \"ix\": 1\n                  },\n                  \"s\": {\n                    \"a\": 0,\n                    \"k\": [100, 100],\n                    \"ix\": 3\n                  },\n                  \"r\": {\n                    \"a\": 0,\n                    \"k\": 0,\n                    \"ix\": 6\n                  },\n                  \"o\": {\n                    \"a\": 0,\n                    \"k\": 100,\n                    \"ix\": 7\n                  },\n                  \"sk\": {\n                    \"a\": 0,\n                    \"k\": 0,\n                    \"ix\": 4\n                  },\n                  \"sa\": {\n                    \"a\": 0,\n                    \"k\": 0,\n                    \"ix\": 5\n                  },\n                  \"nm\": \"Transform\"\n                }\n              ],\n              \"nm\": \"Rectangle 1\",\n              \"np\": 2,\n              \"cix\": 2,\n              \"bm\": 0,\n              \"ix\": 1,\n              \"mn\": \"ADBE Vector Group\",\n              \"hd\": false\n            }\n          ],\n          \"ip\": 2,\n          \"op\": 192,\n          \"st\": 2,\n          \"bm\": 0\n        },\n        {\n          \"ddd\": 0,\n          \"ind\": 9,\n          \"ty\": 4,\n          \"nm\": \"square a\",\n          \"sr\": 1,\n          \"ks\": {\n            \"o\": {\n              \"a\": 0,\n              \"k\": 100,\n              \"ix\": 11\n            },\n            \"r\": {\n              \"a\": 1,\n              \"k\": [\n                {\n                  \"i\": {\n                    \"x\": [0.667],\n                    \"y\": [1]\n                  },\n                  \"o\": {\n                    \"x\": [0.167],\n                    \"y\": [0.167]\n                  },\n                  \"t\": 0,\n                  \"s\": [0]\n                },\n                {\n                  \"i\": {\n                    \"x\": [0.833],\n                    \"y\": [0.833]\n                  },\n                  \"o\": {\n                    \"x\": [0.333],\n                    \"y\": [0]\n                  },\n                  \"t\": 35,\n                  \"s\": [462.385]\n                },\n                {\n                  \"t\": 218,\n                  \"s\": [2880]\n                }\n              ],\n              \"ix\": 10\n            },\n            \"p\": {\n              \"a\": 1,\n              \"k\": [\n                {\n                  \"i\": {\n                    \"x\": 0.667,\n                    \"y\": 1\n                  },\n                  \"o\": {\n                    \"x\": 0.167,\n                    \"y\": 0.167\n                  },\n                  \"t\": 0,\n                  \"s\": [599.5, 838, 0],\n                  \"to\": [-43.333, -123.333, 0],\n                  \"ti\": [60, 0, 0]\n                },\n                {\n                  \"i\": {\n                    \"x\": 0.833,\n                    \"y\": 0.833\n                  },\n                  \"o\": {\n                    \"x\": 0.333,\n                    \"y\": 0\n                  },\n                  \"t\": 35,\n                  \"s\": [339.5, 98, 0],\n                  \"to\": [-60, 0, 0],\n                  \"ti\": [0, 0, 0]\n                },\n                {\n                  \"t\": 218,\n                  \"s\": [239.5, 838, 0]\n                }\n              ],\n              \"ix\": 2\n            },\n            \"a\": {\n              \"a\": 0,\n              \"k\": [0, 0, 0],\n              \"ix\": 1\n            },\n            \"s\": {\n              \"a\": 1,\n              \"k\": [\n                {\n                  \"i\": {\n                    \"x\": [0.667, 0.667, 0.667],\n                    \"y\": [1, 1, 1]\n                  },\n                  \"o\": {\n                    \"x\": [0.167, 0.167, 0.167],\n                    \"y\": [0.167, 0, 0]\n                  },\n                  \"t\": 0,\n                  \"s\": [50, 100, 100]\n                },\n                {\n                  \"i\": {\n                    \"x\": [0.833, 0.833, 0.833],\n                    \"y\": [1, 0.833, 1]\n                  },\n                  \"o\": {\n                    \"x\": [0.333, 0.333, 0.333],\n                    \"y\": [0, 0, 0]\n                  },\n                  \"t\": 35,\n                  \"s\": [100, 100, 100]\n                },\n                {\n                  \"t\": 188,\n                  \"s\": [100, 50, 100]\n                }\n              ],\n              \"ix\": 6\n            }\n          },\n          \"ao\": 0,\n          \"shapes\": [\n            {\n              \"ty\": \"gr\",\n              \"it\": [\n                {\n                  \"ty\": \"rc\",\n                  \"d\": 1,\n                  \"s\": {\n                    \"a\": 0,\n                    \"k\": [16, 16],\n                    \"ix\": 2\n                  },\n                  \"p\": {\n                    \"a\": 0,\n                    \"k\": [0, 0],\n                    \"ix\": 3\n                  },\n                  \"r\": {\n                    \"a\": 0,\n                    \"k\": 0,\n                    \"ix\": 4\n                  },\n                  \"nm\": \"Rectangle Path 1\",\n                  \"mn\": \"ADBE Vector Shape - Rect\",\n                  \"hd\": false\n                },\n                {\n                  \"ty\": \"fl\",\n                  \"c\": {\n                    \"a\": 0,\n                    \"k\": [1, 0.2627450980392157, 0.2, 1],\n                    \"ix\": 4\n                  },\n                  \"o\": {\n                    \"a\": 0,\n                    \"k\": 100,\n                    \"ix\": 5\n                  },\n                  \"r\": 1,\n                  \"bm\": 0,\n                  \"nm\": \"Fill 1\",\n                  \"mn\": \"ADBE Vector Graphic - Fill\",\n                  \"hd\": false\n                },\n                {\n                  \"ty\": \"tr\",\n                  \"p\": {\n                    \"a\": 0,\n                    \"k\": [0, 0],\n                    \"ix\": 2\n                  },\n                  \"a\": {\n                    \"a\": 0,\n                    \"k\": [0, 0],\n                    \"ix\": 1\n                  },\n                  \"s\": {\n                    \"a\": 0,\n                    \"k\": [100, 100],\n                    \"ix\": 3\n                  },\n                  \"r\": {\n                    \"a\": 0,\n                    \"k\": 0,\n                    \"ix\": 6\n                  },\n                  \"o\": {\n                    \"a\": 0,\n                    \"k\": 100,\n                    \"ix\": 7\n                  },\n                  \"sk\": {\n                    \"a\": 0,\n                    \"k\": 0,\n                    \"ix\": 4\n                  },\n                  \"sa\": {\n                    \"a\": 0,\n                    \"k\": 0,\n                    \"ix\": 5\n                  },\n                  \"nm\": \"Transform\"\n                }\n              ],\n              \"nm\": \"Rectangle 1\",\n              \"np\": 2,\n              \"cix\": 2,\n              \"bm\": 0,\n              \"ix\": 1,\n              \"mn\": \"ADBE Vector Group\",\n              \"hd\": false\n            }\n          ],\n          \"ip\": 0,\n          \"op\": 219,\n          \"st\": 0,\n          \"bm\": 0\n        },\n        {\n          \"ddd\": 0,\n          \"ind\": 10,\n          \"ty\": 4,\n          \"nm\": \"square b\",\n          \"sr\": 1,\n          \"ks\": {\n            \"o\": {\n              \"a\": 0,\n              \"k\": 50,\n              \"ix\": 11\n            },\n            \"r\": {\n              \"a\": 1,\n              \"k\": [\n                {\n                  \"i\": {\n                    \"x\": [0.667],\n                    \"y\": [1]\n                  },\n                  \"o\": {\n                    \"x\": [0.167],\n                    \"y\": [0.167]\n                  },\n                  \"t\": 2,\n                  \"s\": [0]\n                },\n                {\n                  \"i\": {\n                    \"x\": [0.833],\n                    \"y\": [0.833]\n                  },\n                  \"o\": {\n                    \"x\": [0.333],\n                    \"y\": [0]\n                  },\n                  \"t\": 27,\n                  \"s\": [285.714]\n                },\n                {\n                  \"t\": 191,\n                  \"s\": [2160]\n                }\n              ],\n              \"ix\": 10\n            },\n            \"p\": {\n              \"a\": 1,\n              \"k\": [\n                {\n                  \"i\": {\n                    \"x\": 0.667,\n                    \"y\": 1\n                  },\n                  \"o\": {\n                    \"x\": 0.167,\n                    \"y\": 0.167\n                  },\n                  \"t\": 2,\n                  \"s\": [599.5, 838, 0],\n                  \"to\": [-30, -120, 0],\n                  \"ti\": [75, 3.333, 0]\n                },\n                {\n                  \"i\": {\n                    \"x\": 0.833,\n                    \"y\": 0.833\n                  },\n                  \"o\": {\n                    \"x\": 0.333,\n                    \"y\": 0\n                  },\n                  \"t\": 27,\n                  \"s\": [419.5, 118, 0],\n                  \"to\": [-75, -3.333, 0],\n                  \"ti\": [0, 0, 0]\n                },\n                {\n                  \"t\": 191,\n                  \"s\": [149.5, 818, 0]\n                }\n              ],\n              \"ix\": 2\n            },\n            \"a\": {\n              \"a\": 0,\n              \"k\": [0, 0, 0],\n              \"ix\": 1\n            },\n            \"s\": {\n              \"a\": 1,\n              \"k\": [\n                {\n                  \"i\": {\n                    \"x\": [0.667, 0.667, 0.667],\n                    \"y\": [1, 1, 1]\n                  },\n                  \"o\": {\n                    \"x\": [0.167, 0.167, 0.167],\n                    \"y\": [0.167, 0, 0]\n                  },\n                  \"t\": 2,\n                  \"s\": [50, 100, 100]\n                },\n                {\n                  \"i\": {\n                    \"x\": [0.833, 0.833, 0.833],\n                    \"y\": [1, 0.833, 1]\n                  },\n                  \"o\": {\n                    \"x\": [0.333, 0.333, 0.333],\n                    \"y\": [0, 0, 0]\n                  },\n                  \"t\": 27,\n                  \"s\": [100, 100, 100]\n                },\n                {\n                  \"t\": 161,\n                  \"s\": [100, 50, 100]\n                }\n              ],\n              \"ix\": 6\n            }\n          },\n          \"ao\": 0,\n          \"shapes\": [\n            {\n              \"ty\": \"gr\",\n              \"it\": [\n                {\n                  \"ty\": \"rc\",\n                  \"d\": 1,\n                  \"s\": {\n                    \"a\": 0,\n                    \"k\": [16, 16],\n                    \"ix\": 2\n                  },\n                  \"p\": {\n                    \"a\": 0,\n                    \"k\": [0, 0],\n                    \"ix\": 3\n                  },\n                  \"r\": {\n                    \"a\": 0,\n                    \"k\": 0,\n                    \"ix\": 4\n                  },\n                  \"nm\": \"Rectangle Path 1\",\n                  \"mn\": \"ADBE Vector Shape - Rect\",\n                  \"hd\": false\n                },\n                {\n                  \"ty\": \"fl\",\n                  \"c\": {\n                    \"a\": 0,\n                    \"k\": [1, 0.12156862745098039, 0.5647058823529412, 1],\n                    \"ix\": 4\n                  },\n                  \"o\": {\n                    \"a\": 0,\n                    \"k\": 100,\n                    \"ix\": 5\n                  },\n                  \"r\": 1,\n                  \"bm\": 0,\n                  \"nm\": \"Fill 1\",\n                  \"mn\": \"ADBE Vector Graphic - Fill\",\n                  \"hd\": false\n                },\n                {\n                  \"ty\": \"tr\",\n                  \"p\": {\n                    \"a\": 0,\n                    \"k\": [0, 0],\n                    \"ix\": 2\n                  },\n                  \"a\": {\n                    \"a\": 0,\n                    \"k\": [0, 0],\n                    \"ix\": 1\n                  },\n                  \"s\": {\n                    \"a\": 0,\n                    \"k\": [100, 100],\n                    \"ix\": 3\n                  },\n                  \"r\": {\n                    \"a\": 0,\n                    \"k\": 0,\n                    \"ix\": 6\n                  },\n                  \"o\": {\n                    \"a\": 0,\n                    \"k\": 100,\n                    \"ix\": 7\n                  },\n                  \"sk\": {\n                    \"a\": 0,\n                    \"k\": 0,\n                    \"ix\": 4\n                  },\n                  \"sa\": {\n                    \"a\": 0,\n                    \"k\": 0,\n                    \"ix\": 5\n                  },\n                  \"nm\": \"Transform\"\n                }\n              ],\n              \"nm\": \"Rectangle 1\",\n              \"np\": 2,\n              \"cix\": 2,\n              \"bm\": 0,\n              \"ix\": 1,\n              \"mn\": \"ADBE Vector Group\",\n              \"hd\": false\n            }\n          ],\n          \"ip\": 2,\n          \"op\": 192,\n          \"st\": 2,\n          \"bm\": 0\n        },\n        {\n          \"ddd\": 0,\n          \"ind\": 11,\n          \"ty\": 4,\n          \"nm\": \"streamer b 2\",\n          \"sr\": 1,\n          \"ks\": {\n            \"o\": {\n              \"a\": 0,\n              \"k\": 100,\n              \"ix\": 11\n            },\n            \"r\": {\n              \"a\": 0,\n              \"k\": 171,\n              \"ix\": 10\n            },\n            \"p\": {\n              \"a\": 0,\n              \"k\": [543, 427, 0],\n              \"ix\": 2\n            },\n            \"a\": {\n              \"a\": 0,\n              \"k\": [-157, -245, 0],\n              \"ix\": 1\n            },\n            \"s\": {\n              \"a\": 0,\n              \"k\": [100, 100, 100],\n              \"ix\": 6\n            }\n          },\n          \"ao\": 0,\n          \"shapes\": [\n            {\n              \"ty\": \"gr\",\n              \"it\": [\n                {\n                  \"ind\": 0,\n                  \"ty\": \"sh\",\n                  \"ix\": 1,\n                  \"ks\": {\n                    \"a\": 0,\n                    \"k\": {\n                      \"i\": [\n                        [0, 0],\n                        [-1.685, -13.314],\n                        [0, -14.907],\n                        [0, -15.206],\n                        [0, -14.907],\n                        [0, -14.907],\n                        [0, -15.206],\n                        [1.754, -14.206],\n                        [-3.934, -9.465]\n                      ],\n                      \"o\": [\n                        [-3.895, 8.562],\n                        [1.872, 14.789],\n                        [0, 15.206],\n                        [0, 14.907],\n                        [0, 14.907],\n                        [0, 15.206],\n                        [0, 14.314],\n                        [-1.803, 14.605],\n                        [0, 0]\n                      ],\n                      \"v\": [\n                        [-156.5, -406],\n                        [-166.5, -367],\n                        [-146.5, -327],\n                        [-166.5, -286],\n                        [-146.5, -246],\n                        [-166.5, -206],\n                        [-146.5, -165],\n                        [-166.5, -127],\n                        [-156.5, -84]\n                      ],\n                      \"c\": false\n                    },\n                    \"ix\": 2\n                  },\n                  \"nm\": \"Path 1\",\n                  \"mn\": \"ADBE Vector Shape - Group\",\n                  \"hd\": false\n                },\n                {\n                  \"ty\": \"st\",\n                  \"c\": {\n                    \"a\": 0,\n                    \"k\": [0.12156862745098039, 0.8431372549019608, 1, 1],\n                    \"ix\": 3\n                  },\n                  \"o\": {\n                    \"a\": 0,\n                    \"k\": 100,\n                    \"ix\": 4\n                  },\n                  \"w\": {\n                    \"a\": 1,\n                    \"k\": [\n                      {\n                        \"i\": {\n                          \"x\": [0.833],\n                          \"y\": [0.833]\n                        },\n                        \"o\": {\n                          \"x\": [0.167],\n                          \"y\": [0.167]\n                        },\n                        \"t\": 13,\n                        \"s\": [4]\n                      },\n                      {\n                        \"t\": 61,\n                        \"s\": [0.5]\n                      }\n                    ],\n                    \"ix\": 5\n                  },\n                  \"lc\": 2,\n                  \"lj\": 2,\n                  \"bm\": 0,\n                  \"nm\": \"Stroke 1\",\n                  \"mn\": \"ADBE Vector Graphic - Stroke\",\n                  \"hd\": false\n                },\n                {\n                  \"ty\": \"tr\",\n                  \"p\": {\n                    \"a\": 0,\n                    \"k\": [0, 0],\n                    \"ix\": 2\n                  },\n                  \"a\": {\n                    \"a\": 0,\n                    \"k\": [0, 0],\n                    \"ix\": 1\n                  },\n                  \"s\": {\n                    \"a\": 0,\n                    \"k\": [100, 100],\n                    \"ix\": 3\n                  },\n                  \"r\": {\n                    \"a\": 0,\n                    \"k\": 0,\n                    \"ix\": 6\n                  },\n                  \"o\": {\n                    \"a\": 0,\n                    \"k\": 100,\n                    \"ix\": 7\n                  },\n                  \"sk\": {\n                    \"a\": 0,\n                    \"k\": 0,\n                    \"ix\": 4\n                  },\n                  \"sa\": {\n                    \"a\": 0,\n                    \"k\": 0,\n                    \"ix\": 5\n                  },\n                  \"nm\": \"Transform\"\n                }\n              ],\n              \"nm\": \"Shape 1\",\n              \"np\": 2,\n              \"cix\": 2,\n              \"bm\": 0,\n              \"ix\": 1,\n              \"mn\": \"ADBE Vector Group\",\n              \"hd\": false\n            },\n            {\n              \"ty\": \"tm\",\n              \"s\": {\n                \"a\": 1,\n                \"k\": [\n                  {\n                    \"i\": {\n                      \"x\": [0.667],\n                      \"y\": [1]\n                    },\n                    \"o\": {\n                      \"x\": [0.167],\n                      \"y\": [0.167]\n                    },\n                    \"t\": 18,\n                    \"s\": [0]\n                  },\n                  {\n                    \"t\": 61,\n                    \"s\": [100]\n                  }\n                ],\n                \"ix\": 1\n              },\n              \"e\": {\n                \"a\": 1,\n                \"k\": [\n                  {\n                    \"i\": {\n                      \"x\": [0.833],\n                      \"y\": [0.833]\n                    },\n                    \"o\": {\n                      \"x\": [0.167],\n                      \"y\": [0.167]\n                    },\n                    \"t\": 13,\n                    \"s\": [0]\n                  },\n                  {\n                    \"i\": {\n                      \"x\": [0.667],\n                      \"y\": [1]\n                    },\n                    \"o\": {\n                      \"x\": [0.167],\n                      \"y\": [0.167]\n                    },\n                    \"t\": 18,\n                    \"s\": [35]\n                  },\n                  {\n                    \"t\": 61,\n                    \"s\": [100]\n                  }\n                ],\n                \"ix\": 2\n              },\n              \"o\": {\n                \"a\": 0,\n                \"k\": 0,\n                \"ix\": 3\n              },\n              \"m\": 1,\n              \"ix\": 2,\n              \"nm\": \"Trim Paths 1\",\n              \"mn\": \"ADBE Vector Filter - Trim\",\n              \"hd\": false\n            }\n          ],\n          \"ip\": 13,\n          \"op\": 62,\n          \"st\": 13,\n          \"bm\": 0\n        },\n        {\n          \"ddd\": 0,\n          \"ind\": 12,\n          \"ty\": 4,\n          \"nm\": \"streamer a 2\",\n          \"sr\": 1,\n          \"ks\": {\n            \"o\": {\n              \"a\": 0,\n              \"k\": 100,\n              \"ix\": 11\n            },\n            \"r\": {\n              \"a\": 0,\n              \"k\": 151,\n              \"ix\": 10\n            },\n            \"p\": {\n              \"a\": 0,\n              \"k\": [454, 444, 0],\n              \"ix\": 2\n            },\n            \"a\": {\n              \"a\": 0,\n              \"k\": [-157, -245, 0],\n              \"ix\": 1\n            },\n            \"s\": {\n              \"a\": 0,\n              \"k\": [-100, 100, 100],\n              \"ix\": 6\n            }\n          },\n          \"ao\": 0,\n          \"shapes\": [\n            {\n              \"ty\": \"gr\",\n              \"it\": [\n                {\n                  \"ind\": 0,\n                  \"ty\": \"sh\",\n                  \"ix\": 1,\n                  \"ks\": {\n                    \"a\": 0,\n                    \"k\": {\n                      \"i\": [\n                        [0, 0],\n                        [-1.685, -13.314],\n                        [0, -14.907],\n                        [0, -15.206],\n                        [0, -14.907],\n                        [0, -14.907],\n                        [0, -15.206],\n                        [1.754, -14.206],\n                        [-3.934, -9.465]\n                      ],\n                      \"o\": [\n                        [-3.895, 8.562],\n                        [1.872, 14.789],\n                        [0, 15.206],\n                        [0, 14.907],\n                        [0, 14.907],\n                        [0, 15.206],\n                        [0, 14.314],\n                        [-1.803, 14.605],\n                        [0, 0]\n                      ],\n                      \"v\": [\n                        [-156.5, -406],\n                        [-166.5, -367],\n                        [-146.5, -327],\n                        [-166.5, -286],\n                        [-146.5, -246],\n                        [-166.5, -206],\n                        [-146.5, -165],\n                        [-166.5, -127],\n                        [-156.5, -84]\n                      ],\n                      \"c\": false\n                    },\n                    \"ix\": 2\n                  },\n                  \"nm\": \"Path 1\",\n                  \"mn\": \"ADBE Vector Shape - Group\",\n                  \"hd\": false\n                },\n                {\n                  \"ty\": \"st\",\n                  \"c\": {\n                    \"a\": 0,\n                    \"k\": [1, 0.2627450980392157, 0.2, 1],\n                    \"ix\": 3\n                  },\n                  \"o\": {\n                    \"a\": 0,\n                    \"k\": 100,\n                    \"ix\": 4\n                  },\n                  \"w\": {\n                    \"a\": 1,\n                    \"k\": [\n                      {\n                        \"i\": {\n                          \"x\": [0.833],\n                          \"y\": [0.833]\n                        },\n                        \"o\": {\n                          \"x\": [0.167],\n                          \"y\": [0.167]\n                        },\n                        \"t\": 10,\n                        \"s\": [4]\n                      },\n                      {\n                        \"t\": 53,\n                        \"s\": [0.5]\n                      }\n                    ],\n                    \"ix\": 5\n                  },\n                  \"lc\": 2,\n                  \"lj\": 2,\n                  \"bm\": 0,\n                  \"nm\": \"Stroke 1\",\n                  \"mn\": \"ADBE Vector Graphic - Stroke\",\n                  \"hd\": false\n                },\n                {\n                  \"ty\": \"tr\",\n                  \"p\": {\n                    \"a\": 0,\n                    \"k\": [0, 0],\n                    \"ix\": 2\n                  },\n                  \"a\": {\n                    \"a\": 0,\n                    \"k\": [0, 0],\n                    \"ix\": 1\n                  },\n                  \"s\": {\n                    \"a\": 0,\n                    \"k\": [100, 100],\n                    \"ix\": 3\n                  },\n                  \"r\": {\n                    \"a\": 0,\n                    \"k\": 0,\n                    \"ix\": 6\n                  },\n                  \"o\": {\n                    \"a\": 0,\n                    \"k\": 100,\n                    \"ix\": 7\n                  },\n                  \"sk\": {\n                    \"a\": 0,\n                    \"k\": 0,\n                    \"ix\": 4\n                  },\n                  \"sa\": {\n                    \"a\": 0,\n                    \"k\": 0,\n                    \"ix\": 5\n                  },\n                  \"nm\": \"Transform\"\n                }\n              ],\n              \"nm\": \"Shape 1\",\n              \"np\": 2,\n              \"cix\": 2,\n              \"bm\": 0,\n              \"ix\": 1,\n              \"mn\": \"ADBE Vector Group\",\n              \"hd\": false\n            },\n            {\n              \"ty\": \"tm\",\n              \"s\": {\n                \"a\": 1,\n                \"k\": [\n                  {\n                    \"i\": {\n                      \"x\": [0.667],\n                      \"y\": [1]\n                    },\n                    \"o\": {\n                      \"x\": [0.167],\n                      \"y\": [0.167]\n                    },\n                    \"t\": 15,\n                    \"s\": [0]\n                  },\n                  {\n                    \"t\": 53,\n                    \"s\": [100]\n                  }\n                ],\n                \"ix\": 1\n              },\n              \"e\": {\n                \"a\": 1,\n                \"k\": [\n                  {\n                    \"i\": {\n                      \"x\": [0.833],\n                      \"y\": [0.833]\n                    },\n                    \"o\": {\n                      \"x\": [0.167],\n                      \"y\": [0.167]\n                    },\n                    \"t\": 10,\n                    \"s\": [0]\n                  },\n                  {\n                    \"i\": {\n                      \"x\": [0.667],\n                      \"y\": [1]\n                    },\n                    \"o\": {\n                      \"x\": [0.167],\n                      \"y\": [0.167]\n                    },\n                    \"t\": 15,\n                    \"s\": [35]\n                  },\n                  {\n                    \"t\": 53,\n                    \"s\": [100]\n                  }\n                ],\n                \"ix\": 2\n              },\n              \"o\": {\n                \"a\": 0,\n                \"k\": 0,\n                \"ix\": 3\n              },\n              \"m\": 1,\n              \"ix\": 2,\n              \"nm\": \"Trim Paths 1\",\n              \"mn\": \"ADBE Vector Filter - Trim\",\n              \"hd\": false\n            }\n          ],\n          \"ip\": 10,\n          \"op\": 54,\n          \"st\": 10,\n          \"bm\": 0\n        },\n        {\n          \"ddd\": 0,\n          \"ind\": 13,\n          \"ty\": 4,\n          \"nm\": \"circle a 2\",\n          \"sr\": 1,\n          \"ks\": {\n            \"o\": {\n              \"a\": 0,\n              \"k\": 100,\n              \"ix\": 11\n            },\n            \"r\": {\n              \"a\": 1,\n              \"k\": [\n                {\n                  \"i\": {\n                    \"x\": [0.667],\n                    \"y\": [1]\n                  },\n                  \"o\": {\n                    \"x\": [0.167],\n                    \"y\": [0.167]\n                  },\n                  \"t\": 1,\n                  \"s\": [0]\n                },\n                {\n                  \"i\": {\n                    \"x\": [0.833],\n                    \"y\": [0.833]\n                  },\n                  \"o\": {\n                    \"x\": [0.333],\n                    \"y\": [0]\n                  },\n                  \"t\": 29,\n                  \"s\": [-371.368]\n                },\n                {\n                  \"t\": 191,\n                  \"s\": [-2520]\n                }\n              ],\n              \"ix\": 10\n            },\n            \"p\": {\n              \"a\": 1,\n              \"k\": [\n                {\n                  \"i\": {\n                    \"x\": 0.667,\n                    \"y\": 1\n                  },\n                  \"o\": {\n                    \"x\": 0.167,\n                    \"y\": 0.167\n                  },\n                  \"t\": 1,\n                  \"s\": [599.5, 838, 0],\n                  \"to\": [-53.333, -113.333, 0],\n                  \"ti\": [56.667, -3.333, 0]\n                },\n                {\n                  \"i\": {\n                    \"x\": 0.833,\n                    \"y\": 0.833\n                  },\n                  \"o\": {\n                    \"x\": 0.333,\n                    \"y\": 0\n                  },\n                  \"t\": 29,\n                  \"s\": [279.5, 158, 0],\n                  \"to\": [-56.667, 3.333, 0],\n                  \"ti\": [0, 0, 0]\n                },\n                {\n                  \"t\": 191,\n                  \"s\": [259.5, 858, 0]\n                }\n              ],\n              \"ix\": 2\n            },\n            \"a\": {\n              \"a\": 0,\n              \"k\": [0, 0, 0],\n              \"ix\": 1\n            },\n            \"s\": {\n              \"a\": 1,\n              \"k\": [\n                {\n                  \"i\": {\n                    \"x\": [0.667, 0.667, 0.667],\n                    \"y\": [1, 1, 1]\n                  },\n                  \"o\": {\n                    \"x\": [0.167, 0.167, 0.167],\n                    \"y\": [0, 0.167, 0]\n                  },\n                  \"t\": 1,\n                  \"s\": [100, 50, 100]\n                },\n                {\n                  \"i\": {\n                    \"x\": [0.833, 0.833, 0.833],\n                    \"y\": [0.833, 1, 1]\n                  },\n                  \"o\": {\n                    \"x\": [0.333, 0.333, 0.333],\n                    \"y\": [0, 0, 0]\n                  },\n                  \"t\": 29,\n                  \"s\": [100, 100, 100]\n                },\n                {\n                  \"t\": 161,\n                  \"s\": [50, 100, 100]\n                }\n              ],\n              \"ix\": 6\n            }\n          },\n          \"ao\": 0,\n          \"shapes\": [\n            {\n              \"ty\": \"gr\",\n              \"it\": [\n                {\n                  \"d\": 1,\n                  \"ty\": \"el\",\n                  \"s\": {\n                    \"a\": 0,\n                    \"k\": [16, 16],\n                    \"ix\": 2\n                  },\n                  \"p\": {\n                    \"a\": 0,\n                    \"k\": [0, 0],\n                    \"ix\": 3\n                  },\n                  \"nm\": \"Ellipse Path 1\",\n                  \"mn\": \"ADBE Vector Shape - Ellipse\",\n                  \"hd\": false\n                },\n                {\n                  \"ty\": \"fl\",\n                  \"c\": {\n                    \"a\": 0,\n                    \"k\": [0.12156862745098039, 0.8431372549019608, 1, 1],\n                    \"ix\": 4\n                  },\n                  \"o\": {\n                    \"a\": 0,\n                    \"k\": 100,\n                    \"ix\": 5\n                  },\n                  \"r\": 1,\n                  \"bm\": 0,\n                  \"nm\": \"Fill 1\",\n                  \"mn\": \"ADBE Vector Graphic - Fill\",\n                  \"hd\": false\n                },\n                {\n                  \"ty\": \"tr\",\n                  \"p\": {\n                    \"a\": 0,\n                    \"k\": [0, 0],\n                    \"ix\": 2\n                  },\n                  \"a\": {\n                    \"a\": 0,\n                    \"k\": [0, 0],\n                    \"ix\": 1\n                  },\n                  \"s\": {\n                    \"a\": 0,\n                    \"k\": [100, 100],\n                    \"ix\": 3\n                  },\n                  \"r\": {\n                    \"a\": 0,\n                    \"k\": 0,\n                    \"ix\": 6\n                  },\n                  \"o\": {\n                    \"a\": 0,\n                    \"k\": 100,\n                    \"ix\": 7\n                  },\n                  \"sk\": {\n                    \"a\": 0,\n                    \"k\": 0,\n                    \"ix\": 4\n                  },\n                  \"sa\": {\n                    \"a\": 0,\n                    \"k\": 0,\n                    \"ix\": 5\n                  },\n                  \"nm\": \"Transform\"\n                }\n              ],\n              \"nm\": \"Ellipse 1\",\n              \"np\": 2,\n              \"cix\": 2,\n              \"bm\": 0,\n              \"ix\": 1,\n              \"mn\": \"ADBE Vector Group\",\n              \"hd\": false\n            }\n          ],\n          \"ip\": 1,\n          \"op\": 192,\n          \"st\": 1,\n          \"bm\": 0\n        },\n        {\n          \"ddd\": 0,\n          \"ind\": 14,\n          \"ty\": 4,\n          \"nm\": \"circle b 2\",\n          \"sr\": 1,\n          \"ks\": {\n            \"o\": {\n              \"a\": 0,\n              \"k\": 50,\n              \"ix\": 11\n            },\n            \"r\": {\n              \"a\": 1,\n              \"k\": [\n                {\n                  \"i\": {\n                    \"x\": [0.667],\n                    \"y\": [1]\n                  },\n                  \"o\": {\n                    \"x\": [0.167],\n                    \"y\": [0.167]\n                  },\n                  \"t\": 3,\n                  \"s\": [0]\n                },\n                {\n                  \"i\": {\n                    \"x\": [0.833],\n                    \"y\": [0.833]\n                  },\n                  \"o\": {\n                    \"x\": [0.333],\n                    \"y\": [0]\n                  },\n                  \"t\": 21,\n                  \"s\": [-250.839]\n                },\n                {\n                  \"t\": 158,\n                  \"s\": [-2160]\n                }\n              ],\n              \"ix\": 10\n            },\n            \"p\": {\n              \"a\": 1,\n              \"k\": [\n                {\n                  \"i\": {\n                    \"x\": 0.667,\n                    \"y\": 1\n                  },\n                  \"o\": {\n                    \"x\": 0.167,\n                    \"y\": 0.167\n                  },\n                  \"t\": 3,\n                  \"s\": [599.5, 838, 0],\n                  \"to\": [-53.333, -100, 0],\n                  \"ti\": [63, -7, 0]\n                },\n                {\n                  \"i\": {\n                    \"x\": 0.833,\n                    \"y\": 0.833\n                  },\n                  \"o\": {\n                    \"x\": 0.333,\n                    \"y\": 0\n                  },\n                  \"t\": 21,\n                  \"s\": [279.5, 238, 0],\n                  \"to\": [-63, 7, 0],\n                  \"ti\": [0, 0, 0]\n                },\n                {\n                  \"t\": 158,\n                  \"s\": [221.5, 880, 0]\n                }\n              ],\n              \"ix\": 2\n            },\n            \"a\": {\n              \"a\": 0,\n              \"k\": [0, 0, 0],\n              \"ix\": 1\n            },\n            \"s\": {\n              \"a\": 1,\n              \"k\": [\n                {\n                  \"i\": {\n                    \"x\": [0.667, 0.667, 0.667],\n                    \"y\": [1, 1, 1]\n                  },\n                  \"o\": {\n                    \"x\": [0.167, 0.167, 0.167],\n                    \"y\": [0, 0.167, 0]\n                  },\n                  \"t\": 3,\n                  \"s\": [100, 50, 100]\n                },\n                {\n                  \"i\": {\n                    \"x\": [0.833, 0.833, 0.833],\n                    \"y\": [0.833, 1, 1]\n                  },\n                  \"o\": {\n                    \"x\": [0.333, 0.333, 0.333],\n                    \"y\": [0, 0, 0]\n                  },\n                  \"t\": 21,\n                  \"s\": [100, 100, 100]\n                },\n                {\n                  \"t\": 128,\n                  \"s\": [50, 100, 100]\n                }\n              ],\n              \"ix\": 6\n            }\n          },\n          \"ao\": 0,\n          \"shapes\": [\n            {\n              \"ty\": \"gr\",\n              \"it\": [\n                {\n                  \"d\": 1,\n                  \"ty\": \"el\",\n                  \"s\": {\n                    \"a\": 0,\n                    \"k\": [16, 16],\n                    \"ix\": 2\n                  },\n                  \"p\": {\n                    \"a\": 0,\n                    \"k\": [0, 0],\n                    \"ix\": 3\n                  },\n                  \"nm\": \"Ellipse Path 1\",\n                  \"mn\": \"ADBE Vector Shape - Ellipse\",\n                  \"hd\": false\n                },\n                {\n                  \"ty\": \"fl\",\n                  \"c\": {\n                    \"a\": 0,\n                    \"k\": [0, 0.5215686274509804, 0.27058823529411763, 1],\n                    \"ix\": 4\n                  },\n                  \"o\": {\n                    \"a\": 0,\n                    \"k\": 100,\n                    \"ix\": 5\n                  },\n                  \"r\": 1,\n                  \"bm\": 0,\n                  \"nm\": \"Fill 1\",\n                  \"mn\": \"ADBE Vector Graphic - Fill\",\n                  \"hd\": false\n                },\n                {\n                  \"ty\": \"tr\",\n                  \"p\": {\n                    \"a\": 0,\n                    \"k\": [0, 0],\n                    \"ix\": 2\n                  },\n                  \"a\": {\n                    \"a\": 0,\n                    \"k\": [0, 0],\n                    \"ix\": 1\n                  },\n                  \"s\": {\n                    \"a\": 0,\n                    \"k\": [100, 100],\n                    \"ix\": 3\n                  },\n                  \"r\": {\n                    \"a\": 0,\n                    \"k\": 0,\n                    \"ix\": 6\n                  },\n                  \"o\": {\n                    \"a\": 0,\n                    \"k\": 100,\n                    \"ix\": 7\n                  },\n                  \"sk\": {\n                    \"a\": 0,\n                    \"k\": 0,\n                    \"ix\": 4\n                  },\n                  \"sa\": {\n                    \"a\": 0,\n                    \"k\": 0,\n                    \"ix\": 5\n                  },\n                  \"nm\": \"Transform\"\n                }\n              ],\n              \"nm\": \"Ellipse 1\",\n              \"np\": 2,\n              \"cix\": 2,\n              \"bm\": 0,\n              \"ix\": 1,\n              \"mn\": \"ADBE Vector Group\",\n              \"hd\": false\n            }\n          ],\n          \"ip\": 3,\n          \"op\": 159,\n          \"st\": 3,\n          \"bm\": 0\n        },\n        {\n          \"ddd\": 0,\n          \"ind\": 15,\n          \"ty\": 4,\n          \"nm\": \"star a 2\",\n          \"sr\": 1,\n          \"ks\": {\n            \"o\": {\n              \"a\": 0,\n              \"k\": 100,\n              \"ix\": 11\n            },\n            \"r\": {\n              \"a\": 1,\n              \"k\": [\n                {\n                  \"i\": {\n                    \"x\": [0.667],\n                    \"y\": [1]\n                  },\n                  \"o\": {\n                    \"x\": [0.167],\n                    \"y\": [0.167]\n                  },\n                  \"t\": 1,\n                  \"s\": [0]\n                },\n                {\n                  \"i\": {\n                    \"x\": [0.833],\n                    \"y\": [0.833]\n                  },\n                  \"o\": {\n                    \"x\": [0.333],\n                    \"y\": [0]\n                  },\n                  \"t\": 31,\n                  \"s\": [-397.895]\n                },\n                {\n                  \"t\": 191,\n                  \"s\": [-2520]\n                }\n              ],\n              \"ix\": 10\n            },\n            \"p\": {\n              \"a\": 1,\n              \"k\": [\n                {\n                  \"i\": {\n                    \"x\": 0.667,\n                    \"y\": 1\n                  },\n                  \"o\": {\n                    \"x\": 0.167,\n                    \"y\": 0.167\n                  },\n                  \"t\": 1,\n                  \"s\": [596.087, 836.292, 0],\n                  \"to\": [-9.431, -113.333, 0],\n                  \"ti\": [42.765, -3.333, 0]\n                },\n                {\n                  \"i\": {\n                    \"x\": 0.833,\n                    \"y\": 0.833\n                  },\n                  \"o\": {\n                    \"x\": 0.333,\n                    \"y\": 0\n                  },\n                  \"t\": 31,\n                  \"s\": [539.5, 156.292, 0],\n                  \"to\": [-42.765, 3.333, 0],\n                  \"ti\": [0, 0, 0]\n                },\n                {\n                  \"t\": 191,\n                  \"s\": [339.5, 856.292, 0]\n                }\n              ],\n              \"ix\": 2\n            },\n            \"a\": {\n              \"a\": 0,\n              \"k\": [0, 0, 0],\n              \"ix\": 1\n            },\n            \"s\": {\n              \"a\": 1,\n              \"k\": [\n                {\n                  \"i\": {\n                    \"x\": [0.667, 0.667, 0.667],\n                    \"y\": [1, 1, 1]\n                  },\n                  \"o\": {\n                    \"x\": [0.167, 0.167, 0.167],\n                    \"y\": [0, 0.167, 0]\n                  },\n                  \"t\": 1,\n                  \"s\": [100, 50, 100]\n                },\n                {\n                  \"i\": {\n                    \"x\": [0.833, 0.833, 0.833],\n                    \"y\": [0.833, 1, 1]\n                  },\n                  \"o\": {\n                    \"x\": [0.333, 0.333, 0.333],\n                    \"y\": [0, 0, 0]\n                  },\n                  \"t\": 31,\n                  \"s\": [100, 100, 100]\n                },\n                {\n                  \"t\": 161,\n                  \"s\": [50, 100, 100]\n                }\n              ],\n              \"ix\": 6\n            }\n          },\n          \"ao\": 0,\n          \"shapes\": [\n            {\n              \"ty\": \"gr\",\n              \"it\": [\n                {\n                  \"ty\": \"sr\",\n                  \"sy\": 1,\n                  \"d\": 1,\n                  \"pt\": {\n                    \"a\": 0,\n                    \"k\": 5,\n                    \"ix\": 3\n                  },\n                  \"p\": {\n                    \"a\": 0,\n                    \"k\": [0, 0],\n                    \"ix\": 4\n                  },\n                  \"r\": {\n                    \"a\": 0,\n                    \"k\": 0,\n                    \"ix\": 5\n                  },\n                  \"ir\": {\n                    \"a\": 0,\n                    \"k\": 5,\n                    \"ix\": 6\n                  },\n                  \"is\": {\n                    \"a\": 0,\n                    \"k\": 0,\n                    \"ix\": 8\n                  },\n                  \"or\": {\n                    \"a\": 0,\n                    \"k\": 12,\n                    \"ix\": 7\n                  },\n                  \"os\": {\n                    \"a\": 0,\n                    \"k\": 0,\n                    \"ix\": 9\n                  },\n                  \"ix\": 1,\n                  \"nm\": \"Polystar Path 1\",\n                  \"mn\": \"ADBE Vector Shape - Star\",\n                  \"hd\": false\n                },\n                {\n                  \"ty\": \"fl\",\n                  \"c\": {\n                    \"a\": 0,\n                    \"k\": [1, 0.2627450980392157, 0.2, 1],\n                    \"ix\": 4\n                  },\n                  \"o\": {\n                    \"a\": 0,\n                    \"k\": 100,\n                    \"ix\": 5\n                  },\n                  \"r\": 1,\n                  \"bm\": 0,\n                  \"nm\": \"Fill 1\",\n                  \"mn\": \"ADBE Vector Graphic - Fill\",\n                  \"hd\": false\n                },\n                {\n                  \"ty\": \"tr\",\n                  \"p\": {\n                    \"a\": 0,\n                    \"k\": [0, 0],\n                    \"ix\": 2\n                  },\n                  \"a\": {\n                    \"a\": 0,\n                    \"k\": [0, 0],\n                    \"ix\": 1\n                  },\n                  \"s\": {\n                    \"a\": 0,\n                    \"k\": [100, 100],\n                    \"ix\": 3\n                  },\n                  \"r\": {\n                    \"a\": 0,\n                    \"k\": 0,\n                    \"ix\": 6\n                  },\n                  \"o\": {\n                    \"a\": 0,\n                    \"k\": 100,\n                    \"ix\": 7\n                  },\n                  \"sk\": {\n                    \"a\": 0,\n                    \"k\": 0,\n                    \"ix\": 4\n                  },\n                  \"sa\": {\n                    \"a\": 0,\n                    \"k\": 0,\n                    \"ix\": 5\n                  },\n                  \"nm\": \"Transform\"\n                }\n              ],\n              \"nm\": \"Polystar 1\",\n              \"np\": 2,\n              \"cix\": 2,\n              \"bm\": 0,\n              \"ix\": 1,\n              \"mn\": \"ADBE Vector Group\",\n              \"hd\": false\n            }\n          ],\n          \"ip\": 1,\n          \"op\": 192,\n          \"st\": 1,\n          \"bm\": 0\n        },\n        {\n          \"ddd\": 0,\n          \"ind\": 16,\n          \"ty\": 4,\n          \"nm\": \"star b 2\",\n          \"sr\": 1,\n          \"ks\": {\n            \"o\": {\n              \"a\": 0,\n              \"k\": 50,\n              \"ix\": 11\n            },\n            \"r\": {\n              \"a\": 1,\n              \"k\": [\n                {\n                  \"i\": {\n                    \"x\": [0.667],\n                    \"y\": [1]\n                  },\n                  \"o\": {\n                    \"x\": [0.167],\n                    \"y\": [0.167]\n                  },\n                  \"t\": 3,\n                  \"s\": [0]\n                },\n                {\n                  \"i\": {\n                    \"x\": [0.833],\n                    \"y\": [0.833]\n                  },\n                  \"o\": {\n                    \"x\": [0.333],\n                    \"y\": [0]\n                  },\n                  \"t\": 23,\n                  \"s\": [-278.71]\n                },\n                {\n                  \"t\": 158,\n                  \"s\": [-2160]\n                }\n              ],\n              \"ix\": 10\n            },\n            \"p\": {\n              \"a\": 1,\n              \"k\": [\n                {\n                  \"i\": {\n                    \"x\": 0.667,\n                    \"y\": 1\n                  },\n                  \"o\": {\n                    \"x\": 0.167,\n                    \"y\": 0.167\n                  },\n                  \"t\": 3,\n                  \"s\": [596.087, 836.292, 0],\n                  \"to\": [-12.765, -96.667, 0],\n                  \"ti\": [52.765, -3.333, 0]\n                },\n                {\n                  \"i\": {\n                    \"x\": 0.833,\n                    \"y\": 0.833\n                  },\n                  \"o\": {\n                    \"x\": 0.333,\n                    \"y\": 0\n                  },\n                  \"t\": 23,\n                  \"s\": [519.5, 256.292, 0],\n                  \"to\": [-52.765, 3.333, 0],\n                  \"ti\": [0, 0, 0]\n                },\n                {\n                  \"t\": 158,\n                  \"s\": [279.5, 856.292, 0]\n                }\n              ],\n              \"ix\": 2\n            },\n            \"a\": {\n              \"a\": 0,\n              \"k\": [0, 0, 0],\n              \"ix\": 1\n            },\n            \"s\": {\n              \"a\": 1,\n              \"k\": [\n                {\n                  \"i\": {\n                    \"x\": [0.667, 0.667, 0.667],\n                    \"y\": [1, 1, 1]\n                  },\n                  \"o\": {\n                    \"x\": [0.167, 0.167, 0.167],\n                    \"y\": [0, 0.167, 0]\n                  },\n                  \"t\": 3,\n                  \"s\": [100, 50, 100]\n                },\n                {\n                  \"i\": {\n                    \"x\": [0.833, 0.833, 0.833],\n                    \"y\": [0.833, 1, 1]\n                  },\n                  \"o\": {\n                    \"x\": [0.333, 0.333, 0.333],\n                    \"y\": [0, 0, 0]\n                  },\n                  \"t\": 23,\n                  \"s\": [100, 100, 100]\n                },\n                {\n                  \"t\": 128,\n                  \"s\": [50, 100, 100]\n                }\n              ],\n              \"ix\": 6\n            }\n          },\n          \"ao\": 0,\n          \"shapes\": [\n            {\n              \"ty\": \"gr\",\n              \"it\": [\n                {\n                  \"ty\": \"sr\",\n                  \"sy\": 1,\n                  \"d\": 1,\n                  \"pt\": {\n                    \"a\": 0,\n                    \"k\": 5,\n                    \"ix\": 3\n                  },\n                  \"p\": {\n                    \"a\": 0,\n                    \"k\": [0, 0],\n                    \"ix\": 4\n                  },\n                  \"r\": {\n                    \"a\": 0,\n                    \"k\": 0,\n                    \"ix\": 5\n                  },\n                  \"ir\": {\n                    \"a\": 0,\n                    \"k\": 5,\n                    \"ix\": 6\n                  },\n                  \"is\": {\n                    \"a\": 0,\n                    \"k\": 0,\n                    \"ix\": 8\n                  },\n                  \"or\": {\n                    \"a\": 0,\n                    \"k\": 12,\n                    \"ix\": 7\n                  },\n                  \"os\": {\n                    \"a\": 0,\n                    \"k\": 0,\n                    \"ix\": 9\n                  },\n                  \"ix\": 1,\n                  \"nm\": \"Polystar Path 1\",\n                  \"mn\": \"ADBE Vector Shape - Star\",\n                  \"hd\": false\n                },\n                {\n                  \"ty\": \"fl\",\n                  \"c\": {\n                    \"a\": 0,\n                    \"k\": [1, 0.12156862745098039, 0.5647058823529412, 1],\n                    \"ix\": 4\n                  },\n                  \"o\": {\n                    \"a\": 0,\n                    \"k\": 100,\n                    \"ix\": 5\n                  },\n                  \"r\": 1,\n                  \"bm\": 0,\n                  \"nm\": \"Fill 1\",\n                  \"mn\": \"ADBE Vector Graphic - Fill\",\n                  \"hd\": false\n                },\n                {\n                  \"ty\": \"tr\",\n                  \"p\": {\n                    \"a\": 0,\n                    \"k\": [0, 0],\n                    \"ix\": 2\n                  },\n                  \"a\": {\n                    \"a\": 0,\n                    \"k\": [0, 0],\n                    \"ix\": 1\n                  },\n                  \"s\": {\n                    \"a\": 0,\n                    \"k\": [100, 100],\n                    \"ix\": 3\n                  },\n                  \"r\": {\n                    \"a\": 0,\n                    \"k\": 0,\n                    \"ix\": 6\n                  },\n                  \"o\": {\n                    \"a\": 0,\n                    \"k\": 100,\n                    \"ix\": 7\n                  },\n                  \"sk\": {\n                    \"a\": 0,\n                    \"k\": 0,\n                    \"ix\": 4\n                  },\n                  \"sa\": {\n                    \"a\": 0,\n                    \"k\": 0,\n                    \"ix\": 5\n                  },\n                  \"nm\": \"Transform\"\n                }\n              ],\n              \"nm\": \"Polystar 1\",\n              \"np\": 2,\n              \"cix\": 2,\n              \"bm\": 0,\n              \"ix\": 1,\n              \"mn\": \"ADBE Vector Group\",\n              \"hd\": false\n            }\n          ],\n          \"ip\": 3,\n          \"op\": 159,\n          \"st\": 3,\n          \"bm\": 0\n        },\n        {\n          \"ddd\": 0,\n          \"ind\": 17,\n          \"ty\": 4,\n          \"nm\": \"rec a 2\",\n          \"sr\": 1,\n          \"ks\": {\n            \"o\": {\n              \"a\": 0,\n              \"k\": 100,\n              \"ix\": 11\n            },\n            \"r\": {\n              \"a\": 1,\n              \"k\": [\n                {\n                  \"i\": {\n                    \"x\": [0.667],\n                    \"y\": [1]\n                  },\n                  \"o\": {\n                    \"x\": [0.167],\n                    \"y\": [0.167]\n                  },\n                  \"t\": 0,\n                  \"s\": [0]\n                },\n                {\n                  \"i\": {\n                    \"x\": [0.833],\n                    \"y\": [0.833]\n                  },\n                  \"o\": {\n                    \"x\": [0.333],\n                    \"y\": [0]\n                  },\n                  \"t\": 33,\n                  \"s\": [-556.875]\n                },\n                {\n                  \"t\": 128,\n                  \"s\": [-2160]\n                }\n              ],\n              \"ix\": 10\n            },\n            \"p\": {\n              \"a\": 1,\n              \"k\": [\n                {\n                  \"i\": {\n                    \"x\": 0.667,\n                    \"y\": 1\n                  },\n                  \"o\": {\n                    \"x\": 0.167,\n                    \"y\": 0.167\n                  },\n                  \"t\": 0,\n                  \"s\": [599.5, 842, 0],\n                  \"to\": [-16.667, -120, 0],\n                  \"ti\": [66.667, 0, 0]\n                },\n                {\n                  \"i\": {\n                    \"x\": 0.833,\n                    \"y\": 0.833\n                  },\n                  \"o\": {\n                    \"x\": 0.333,\n                    \"y\": 0\n                  },\n                  \"t\": 33,\n                  \"s\": [499.5, 122, 0],\n                  \"to\": [-66.667, 0, 0],\n                  \"ti\": [0, 0, 0]\n                },\n                {\n                  \"t\": 128,\n                  \"s\": [199.5, 842, 0]\n                }\n              ],\n              \"ix\": 2\n            },\n            \"a\": {\n              \"a\": 0,\n              \"k\": [0, 0, 0],\n              \"ix\": 1\n            },\n            \"s\": {\n              \"a\": 1,\n              \"k\": [\n                {\n                  \"i\": {\n                    \"x\": [0.667, 0.667, 0.667],\n                    \"y\": [1, 1, 1]\n                  },\n                  \"o\": {\n                    \"x\": [0.167, 0.167, 0.167],\n                    \"y\": [0, 0.167, 0]\n                  },\n                  \"t\": 0,\n                  \"s\": [100, 50, 100]\n                },\n                {\n                  \"i\": {\n                    \"x\": [0.833, 0.833, 0.833],\n                    \"y\": [1, 0.833, 1]\n                  },\n                  \"o\": {\n                    \"x\": [0.333, 0.333, 0.333],\n                    \"y\": [0, 0, 0]\n                  },\n                  \"t\": 33,\n                  \"s\": [100, 100, 100]\n                },\n                {\n                  \"t\": 98,\n                  \"s\": [100, 50, 100]\n                }\n              ],\n              \"ix\": 6\n            }\n          },\n          \"ao\": 0,\n          \"shapes\": [\n            {\n              \"ty\": \"gr\",\n              \"it\": [\n                {\n                  \"ty\": \"rc\",\n                  \"d\": 1,\n                  \"s\": {\n                    \"a\": 0,\n                    \"k\": [16, 8],\n                    \"ix\": 2\n                  },\n                  \"p\": {\n                    \"a\": 0,\n                    \"k\": [0, 0],\n                    \"ix\": 3\n                  },\n                  \"r\": {\n                    \"a\": 0,\n                    \"k\": 0,\n                    \"ix\": 4\n                  },\n                  \"nm\": \"Rectangle Path 1\",\n                  \"mn\": \"ADBE Vector Shape - Rect\",\n                  \"hd\": false\n                },\n                {\n                  \"ty\": \"fl\",\n                  \"c\": {\n                    \"a\": 0,\n                    \"k\": [1, 0.2627450980392157, 0.2, 1],\n                    \"ix\": 4\n                  },\n                  \"o\": {\n                    \"a\": 0,\n                    \"k\": 100,\n                    \"ix\": 5\n                  },\n                  \"r\": 1,\n                  \"bm\": 0,\n                  \"nm\": \"Fill 1\",\n                  \"mn\": \"ADBE Vector Graphic - Fill\",\n                  \"hd\": false\n                },\n                {\n                  \"ty\": \"tr\",\n                  \"p\": {\n                    \"a\": 0,\n                    \"k\": [0, 0],\n                    \"ix\": 2\n                  },\n                  \"a\": {\n                    \"a\": 0,\n                    \"k\": [0, 0],\n                    \"ix\": 1\n                  },\n                  \"s\": {\n                    \"a\": 0,\n                    \"k\": [100, 100],\n                    \"ix\": 3\n                  },\n                  \"r\": {\n                    \"a\": 0,\n                    \"k\": 0,\n                    \"ix\": 6\n                  },\n                  \"o\": {\n                    \"a\": 0,\n                    \"k\": 100,\n                    \"ix\": 7\n                  },\n                  \"sk\": {\n                    \"a\": 0,\n                    \"k\": 0,\n                    \"ix\": 4\n                  },\n                  \"sa\": {\n                    \"a\": 0,\n                    \"k\": 0,\n                    \"ix\": 5\n                  },\n                  \"nm\": \"Transform\"\n                }\n              ],\n              \"nm\": \"Rectangle 1\",\n              \"np\": 2,\n              \"cix\": 2,\n              \"bm\": 0,\n              \"ix\": 1,\n              \"mn\": \"ADBE Vector Group\",\n              \"hd\": false\n            }\n          ],\n          \"ip\": 0,\n          \"op\": 129,\n          \"st\": 0,\n          \"bm\": 0\n        },\n        {\n          \"ddd\": 0,\n          \"ind\": 18,\n          \"ty\": 4,\n          \"nm\": \"rec b 2\",\n          \"sr\": 1,\n          \"ks\": {\n            \"o\": {\n              \"a\": 0,\n              \"k\": 50,\n              \"ix\": 11\n            },\n            \"r\": {\n              \"a\": 1,\n              \"k\": [\n                {\n                  \"i\": {\n                    \"x\": [0.667],\n                    \"y\": [1]\n                  },\n                  \"o\": {\n                    \"x\": [0.167],\n                    \"y\": [0.167]\n                  },\n                  \"t\": 2,\n                  \"s\": [0]\n                },\n                {\n                  \"i\": {\n                    \"x\": [0.833],\n                    \"y\": [0.833]\n                  },\n                  \"o\": {\n                    \"x\": [0.333],\n                    \"y\": [0]\n                  },\n                  \"t\": 25,\n                  \"s\": [-306.667]\n                },\n                {\n                  \"t\": 218,\n                  \"s\": [-2880]\n                }\n              ],\n              \"ix\": 10\n            },\n            \"p\": {\n              \"a\": 1,\n              \"k\": [\n                {\n                  \"i\": {\n                    \"x\": 0.667,\n                    \"y\": 1\n                  },\n                  \"o\": {\n                    \"x\": 0.167,\n                    \"y\": 0.167\n                  },\n                  \"t\": 2,\n                  \"s\": [599.5, 842, 0],\n                  \"to\": [-22.62, -109.87, 0],\n                  \"ti\": [2.877, -2.055, 0]\n                },\n                {\n                  \"i\": {\n                    \"x\": 0.833,\n                    \"y\": 0.833\n                  },\n                  \"o\": {\n                    \"x\": 0.333,\n                    \"y\": 0\n                  },\n                  \"t\": 25,\n                  \"s\": [339.5, 262, 0],\n                  \"to\": [-51.333, 36.667, 0],\n                  \"ti\": [0, 0, 0]\n                },\n                {\n                  \"t\": 218,\n                  \"s\": [219.5, 862, 0]\n                }\n              ],\n              \"ix\": 2\n            },\n            \"a\": {\n              \"a\": 0,\n              \"k\": [0, 0, 0],\n              \"ix\": 1\n            },\n            \"s\": {\n              \"a\": 1,\n              \"k\": [\n                {\n                  \"i\": {\n                    \"x\": [0.667, 0.667, 0.667],\n                    \"y\": [1, 1, 1]\n                  },\n                  \"o\": {\n                    \"x\": [0.167, 0.167, 0.167],\n                    \"y\": [0, 0.167, 0]\n                  },\n                  \"t\": 2,\n                  \"s\": [100, 50, 100]\n                },\n                {\n                  \"i\": {\n                    \"x\": [0.833, 0.833, 0.833],\n                    \"y\": [0.833, 1, 1]\n                  },\n                  \"o\": {\n                    \"x\": [0.333, 0.333, 0.333],\n                    \"y\": [0, 0, 0]\n                  },\n                  \"t\": 25,\n                  \"s\": [100, 100, 100]\n                },\n                {\n                  \"t\": 188,\n                  \"s\": [50, 100, 100]\n                }\n              ],\n              \"ix\": 6\n            }\n          },\n          \"ao\": 0,\n          \"shapes\": [\n            {\n              \"ty\": \"gr\",\n              \"it\": [\n                {\n                  \"ty\": \"rc\",\n                  \"d\": 1,\n                  \"s\": {\n                    \"a\": 0,\n                    \"k\": [16, 8],\n                    \"ix\": 2\n                  },\n                  \"p\": {\n                    \"a\": 0,\n                    \"k\": [0, 0],\n                    \"ix\": 3\n                  },\n                  \"r\": {\n                    \"a\": 0,\n                    \"k\": 0,\n                    \"ix\": 4\n                  },\n                  \"nm\": \"Rectangle Path 1\",\n                  \"mn\": \"ADBE Vector Shape - Rect\",\n                  \"hd\": false\n                },\n                {\n                  \"ty\": \"fl\",\n                  \"c\": {\n                    \"a\": 0,\n                    \"k\": [0.12156862745098039, 0.8431372549019608, 1, 1],\n                    \"ix\": 4\n                  },\n                  \"o\": {\n                    \"a\": 0,\n                    \"k\": 100,\n                    \"ix\": 5\n                  },\n                  \"r\": 1,\n                  \"bm\": 0,\n                  \"nm\": \"Fill 1\",\n                  \"mn\": \"ADBE Vector Graphic - Fill\",\n                  \"hd\": false\n                },\n                {\n                  \"ty\": \"tr\",\n                  \"p\": {\n                    \"a\": 0,\n                    \"k\": [0, 0],\n                    \"ix\": 2\n                  },\n                  \"a\": {\n                    \"a\": 0,\n                    \"k\": [0, 0],\n                    \"ix\": 1\n                  },\n                  \"s\": {\n                    \"a\": 0,\n                    \"k\": [100, 100],\n                    \"ix\": 3\n                  },\n                  \"r\": {\n                    \"a\": 0,\n                    \"k\": 0,\n                    \"ix\": 6\n                  },\n                  \"o\": {\n                    \"a\": 0,\n                    \"k\": 100,\n                    \"ix\": 7\n                  },\n                  \"sk\": {\n                    \"a\": 0,\n                    \"k\": 0,\n                    \"ix\": 4\n                  },\n                  \"sa\": {\n                    \"a\": 0,\n                    \"k\": 0,\n                    \"ix\": 5\n                  },\n                  \"nm\": \"Transform\"\n                }\n              ],\n              \"nm\": \"Rectangle 1\",\n              \"np\": 2,\n              \"cix\": 2,\n              \"bm\": 0,\n              \"ix\": 1,\n              \"mn\": \"ADBE Vector Group\",\n              \"hd\": false\n            }\n          ],\n          \"ip\": 2,\n          \"op\": 219,\n          \"st\": 2,\n          \"bm\": 0\n        },\n        {\n          \"ddd\": 0,\n          \"ind\": 19,\n          \"ty\": 4,\n          \"nm\": \"square a 2\",\n          \"sr\": 1,\n          \"ks\": {\n            \"o\": {\n              \"a\": 0,\n              \"k\": 100,\n              \"ix\": 11\n            },\n            \"r\": {\n              \"a\": 1,\n              \"k\": [\n                {\n                  \"i\": {\n                    \"x\": [0.667],\n                    \"y\": [1]\n                  },\n                  \"o\": {\n                    \"x\": [0.167],\n                    \"y\": [0.167]\n                  },\n                  \"t\": 0,\n                  \"s\": [0]\n                },\n                {\n                  \"i\": {\n                    \"x\": [0.833],\n                    \"y\": [0.833]\n                  },\n                  \"o\": {\n                    \"x\": [0.333],\n                    \"y\": [0]\n                  },\n                  \"t\": 35,\n                  \"s\": [-590.625]\n                },\n                {\n                  \"t\": 128,\n                  \"s\": [-2160]\n                }\n              ],\n              \"ix\": 10\n            },\n            \"p\": {\n              \"a\": 1,\n              \"k\": [\n                {\n                  \"i\": {\n                    \"x\": 0.667,\n                    \"y\": 1\n                  },\n                  \"o\": {\n                    \"x\": 0.167,\n                    \"y\": 0.167\n                  },\n                  \"t\": 0,\n                  \"s\": [599.5, 838, 0],\n                  \"to\": [-20, -90, 0],\n                  \"ti\": [36.667, 0, 0]\n                },\n                {\n                  \"i\": {\n                    \"x\": 0.833,\n                    \"y\": 0.833\n                  },\n                  \"o\": {\n                    \"x\": 0.333,\n                    \"y\": 0\n                  },\n                  \"t\": 35,\n                  \"s\": [479.5, 298, 0],\n                  \"to\": [-36.667, 0, 0],\n                  \"ti\": [0, 0, 0]\n                },\n                {\n                  \"t\": 128,\n                  \"s\": [379.5, 838, 0]\n                }\n              ],\n              \"ix\": 2\n            },\n            \"a\": {\n              \"a\": 0,\n              \"k\": [0, 0, 0],\n              \"ix\": 1\n            },\n            \"s\": {\n              \"a\": 1,\n              \"k\": [\n                {\n                  \"i\": {\n                    \"x\": [0.667, 0.667, 0.667],\n                    \"y\": [1, 1, 1]\n                  },\n                  \"o\": {\n                    \"x\": [0.167, 0.167, 0.167],\n                    \"y\": [0, 0.167, 0]\n                  },\n                  \"t\": 0,\n                  \"s\": [100, 50, 100]\n                },\n                {\n                  \"i\": {\n                    \"x\": [0.833, 0.833, 0.833],\n                    \"y\": [0.833, 1, 1]\n                  },\n                  \"o\": {\n                    \"x\": [0.333, 0.333, 0.333],\n                    \"y\": [0, 0, 0]\n                  },\n                  \"t\": 35,\n                  \"s\": [100, 100, 100]\n                },\n                {\n                  \"t\": 98,\n                  \"s\": [50, 100, 100]\n                }\n              ],\n              \"ix\": 6\n            }\n          },\n          \"ao\": 0,\n          \"shapes\": [\n            {\n              \"ty\": \"gr\",\n              \"it\": [\n                {\n                  \"ty\": \"rc\",\n                  \"d\": 1,\n                  \"s\": {\n                    \"a\": 0,\n                    \"k\": [16, 16],\n                    \"ix\": 2\n                  },\n                  \"p\": {\n                    \"a\": 0,\n                    \"k\": [0, 0],\n                    \"ix\": 3\n                  },\n                  \"r\": {\n                    \"a\": 0,\n                    \"k\": 0,\n                    \"ix\": 4\n                  },\n                  \"nm\": \"Rectangle Path 1\",\n                  \"mn\": \"ADBE Vector Shape - Rect\",\n                  \"hd\": false\n                },\n                {\n                  \"ty\": \"fl\",\n                  \"c\": {\n                    \"a\": 0,\n                    \"k\": [0.12156862745098039, 0.8431372549019608, 1, 1],\n                    \"ix\": 4\n                  },\n                  \"o\": {\n                    \"a\": 0,\n                    \"k\": 100,\n                    \"ix\": 5\n                  },\n                  \"r\": 1,\n                  \"bm\": 0,\n                  \"nm\": \"Fill 1\",\n                  \"mn\": \"ADBE Vector Graphic - Fill\",\n                  \"hd\": false\n                },\n                {\n                  \"ty\": \"tr\",\n                  \"p\": {\n                    \"a\": 0,\n                    \"k\": [0, 0],\n                    \"ix\": 2\n                  },\n                  \"a\": {\n                    \"a\": 0,\n                    \"k\": [0, 0],\n                    \"ix\": 1\n                  },\n                  \"s\": {\n                    \"a\": 0,\n                    \"k\": [100, 100],\n                    \"ix\": 3\n                  },\n                  \"r\": {\n                    \"a\": 0,\n                    \"k\": 0,\n                    \"ix\": 6\n                  },\n                  \"o\": {\n                    \"a\": 0,\n                    \"k\": 100,\n                    \"ix\": 7\n                  },\n                  \"sk\": {\n                    \"a\": 0,\n                    \"k\": 0,\n                    \"ix\": 4\n                  },\n                  \"sa\": {\n                    \"a\": 0,\n                    \"k\": 0,\n                    \"ix\": 5\n                  },\n                  \"nm\": \"Transform\"\n                }\n              ],\n              \"nm\": \"Rectangle 1\",\n              \"np\": 2,\n              \"cix\": 2,\n              \"bm\": 0,\n              \"ix\": 1,\n              \"mn\": \"ADBE Vector Group\",\n              \"hd\": false\n            }\n          ],\n          \"ip\": 0,\n          \"op\": 129,\n          \"st\": 0,\n          \"bm\": 0\n        },\n        {\n          \"ddd\": 0,\n          \"ind\": 20,\n          \"ty\": 4,\n          \"nm\": \"square b 2\",\n          \"sr\": 1,\n          \"ks\": {\n            \"o\": {\n              \"a\": 0,\n              \"k\": 50,\n              \"ix\": 11\n            },\n            \"r\": {\n              \"a\": 1,\n              \"k\": [\n                {\n                  \"i\": {\n                    \"x\": [0.667],\n                    \"y\": [1]\n                  },\n                  \"o\": {\n                    \"x\": [0.167],\n                    \"y\": [0.167]\n                  },\n                  \"t\": 2,\n                  \"s\": [0]\n                },\n                {\n                  \"i\": {\n                    \"x\": [0.833],\n                    \"y\": [0.833]\n                  },\n                  \"o\": {\n                    \"x\": [0.333],\n                    \"y\": [0]\n                  },\n                  \"t\": 27,\n                  \"s\": [-333.333]\n                },\n                {\n                  \"t\": 218,\n                  \"s\": [-2880]\n                }\n              ],\n              \"ix\": 10\n            },\n            \"p\": {\n              \"a\": 1,\n              \"k\": [\n                {\n                  \"i\": {\n                    \"x\": 0.667,\n                    \"y\": 1\n                  },\n                  \"o\": {\n                    \"x\": 0.167,\n                    \"y\": 0.167\n                  },\n                  \"t\": 2,\n                  \"s\": [599.5, 838, 0],\n                  \"to\": [-10, -103.333, 0],\n                  \"ti\": [50, 0, 0]\n                },\n                {\n                  \"i\": {\n                    \"x\": 0.833,\n                    \"y\": 0.833\n                  },\n                  \"o\": {\n                    \"x\": 0.333,\n                    \"y\": 0\n                  },\n                  \"t\": 27,\n                  \"s\": [539.5, 218, 0],\n                  \"to\": [-50, 0, 0],\n                  \"ti\": [0, 0, 0]\n                },\n                {\n                  \"t\": 218,\n                  \"s\": [299.5, 838, 0]\n                }\n              ],\n              \"ix\": 2\n            },\n            \"a\": {\n              \"a\": 0,\n              \"k\": [0, 0, 0],\n              \"ix\": 1\n            },\n            \"s\": {\n              \"a\": 1,\n              \"k\": [\n                {\n                  \"i\": {\n                    \"x\": [0.667, 0.667, 0.667],\n                    \"y\": [1, 1, 1]\n                  },\n                  \"o\": {\n                    \"x\": [0.167, 0.167, 0.167],\n                    \"y\": [0, 0.167, 0]\n                  },\n                  \"t\": 2,\n                  \"s\": [100, 50, 100]\n                },\n                {\n                  \"i\": {\n                    \"x\": [0.833, 0.833, 0.833],\n                    \"y\": [0.833, 1, 1]\n                  },\n                  \"o\": {\n                    \"x\": [0.333, 0.333, 0.333],\n                    \"y\": [0, 0, 0]\n                  },\n                  \"t\": 27,\n                  \"s\": [100, 100, 100]\n                },\n                {\n                  \"t\": 188,\n                  \"s\": [50, 100, 100]\n                }\n              ],\n              \"ix\": 6\n            }\n          },\n          \"ao\": 0,\n          \"shapes\": [\n            {\n              \"ty\": \"gr\",\n              \"it\": [\n                {\n                  \"ty\": \"rc\",\n                  \"d\": 1,\n                  \"s\": {\n                    \"a\": 0,\n                    \"k\": [16, 16],\n                    \"ix\": 2\n                  },\n                  \"p\": {\n                    \"a\": 0,\n                    \"k\": [0, 0],\n                    \"ix\": 3\n                  },\n                  \"r\": {\n                    \"a\": 0,\n                    \"k\": 0,\n                    \"ix\": 4\n                  },\n                  \"nm\": \"Rectangle Path 1\",\n                  \"mn\": \"ADBE Vector Shape - Rect\",\n                  \"hd\": false\n                },\n                {\n                  \"ty\": \"fl\",\n                  \"c\": {\n                    \"a\": 0,\n                    \"k\": [1, 0.12156862745098039, 0.5647058823529412, 1],\n                    \"ix\": 4\n                  },\n                  \"o\": {\n                    \"a\": 0,\n                    \"k\": 100,\n                    \"ix\": 5\n                  },\n                  \"r\": 1,\n                  \"bm\": 0,\n                  \"nm\": \"Fill 1\",\n                  \"mn\": \"ADBE Vector Graphic - Fill\",\n                  \"hd\": false\n                },\n                {\n                  \"ty\": \"tr\",\n                  \"p\": {\n                    \"a\": 0,\n                    \"k\": [0, 0],\n                    \"ix\": 2\n                  },\n                  \"a\": {\n                    \"a\": 0,\n                    \"k\": [0, 0],\n                    \"ix\": 1\n                  },\n                  \"s\": {\n                    \"a\": 0,\n                    \"k\": [100, 100],\n                    \"ix\": 3\n                  },\n                  \"r\": {\n                    \"a\": 0,\n                    \"k\": 0,\n                    \"ix\": 6\n                  },\n                  \"o\": {\n                    \"a\": 0,\n                    \"k\": 100,\n                    \"ix\": 7\n                  },\n                  \"sk\": {\n                    \"a\": 0,\n                    \"k\": 0,\n                    \"ix\": 4\n                  },\n                  \"sa\": {\n                    \"a\": 0,\n                    \"k\": 0,\n                    \"ix\": 5\n                  },\n                  \"nm\": \"Transform\"\n                }\n              ],\n              \"nm\": \"Rectangle 1\",\n              \"np\": 2,\n              \"cix\": 2,\n              \"bm\": 0,\n              \"ix\": 1,\n              \"mn\": \"ADBE Vector Group\",\n              \"hd\": false\n            }\n          ],\n          \"ip\": 2,\n          \"op\": 219,\n          \"st\": 2,\n          \"bm\": 0\n        }\n      ]\n    },\n    {\n      \"id\": \"comp_2\",\n      \"layers\": [\n        {\n          \"ddd\": 0,\n          \"ind\": 1,\n          \"ty\": 0,\n          \"nm\": \"_small-side\",\n          \"refId\": \"comp_1\",\n          \"sr\": 1,\n          \"ks\": {\n            \"o\": {\n              \"a\": 0,\n              \"k\": 100,\n              \"ix\": 11\n            },\n            \"r\": {\n              \"a\": 0,\n              \"k\": 0,\n              \"ix\": 10\n            },\n            \"p\": {\n              \"a\": 0,\n              \"k\": [260, 320, 0],\n              \"ix\": 2\n            },\n            \"a\": {\n              \"a\": 0,\n              \"k\": [400, 400, 0],\n              \"ix\": 1\n            },\n            \"s\": {\n              \"a\": 0,\n              \"k\": [100, 100, 100],\n              \"ix\": 6\n            }\n          },\n          \"ao\": 0,\n          \"w\": 800,\n          \"h\": 800,\n          \"ip\": 0,\n          \"op\": 219,\n          \"st\": 0,\n          \"bm\": 0\n        }\n      ]\n    },\n    {\n      \"id\": \"comp_3\",\n      \"layers\": [\n        {\n          \"ddd\": 0,\n          \"ind\": 1,\n          \"ty\": 0,\n          \"nm\": \"left\",\n          \"refId\": \"comp_4\",\n          \"sr\": 1,\n          \"ks\": {\n            \"o\": {\n              \"a\": 0,\n              \"k\": 100,\n              \"ix\": 11\n            },\n            \"r\": {\n              \"a\": 0,\n              \"k\": 0,\n              \"ix\": 10\n            },\n            \"p\": {\n              \"a\": 0,\n              \"k\": [400, 400, 0],\n              \"ix\": 2\n            },\n            \"a\": {\n              \"a\": 0,\n              \"k\": [400, 400, 0],\n              \"ix\": 1\n            },\n            \"s\": {\n              \"a\": 0,\n              \"k\": [100, 100, 100],\n              \"ix\": 6\n            }\n          },\n          \"ao\": 0,\n          \"w\": 800,\n          \"h\": 800,\n          \"ip\": 13,\n          \"op\": 313,\n          \"st\": 13,\n          \"bm\": 0\n        },\n        {\n          \"ddd\": 0,\n          \"ind\": 2,\n          \"ty\": 0,\n          \"nm\": \"right\",\n          \"refId\": \"comp_4\",\n          \"sr\": 1,\n          \"ks\": {\n            \"o\": {\n              \"a\": 0,\n              \"k\": 100,\n              \"ix\": 11\n            },\n            \"r\": {\n              \"a\": 0,\n              \"k\": 0,\n              \"ix\": 10\n            },\n            \"p\": {\n              \"a\": 0,\n              \"k\": [400, 400, 0],\n              \"ix\": 2\n            },\n            \"a\": {\n              \"a\": 0,\n              \"k\": [400, 400, 0],\n              \"ix\": 1\n            },\n            \"s\": {\n              \"a\": 0,\n              \"k\": [-100, 100, 100],\n              \"ix\": 6\n            }\n          },\n          \"ao\": 0,\n          \"w\": 800,\n          \"h\": 800,\n          \"ip\": 30,\n          \"op\": 330,\n          \"st\": 30,\n          \"bm\": 0\n        }\n      ]\n    },\n    {\n      \"id\": \"comp_4\",\n      \"layers\": [\n        {\n          \"ddd\": 0,\n          \"ind\": 1,\n          \"ty\": 4,\n          \"nm\": \"streamer a 4\",\n          \"sr\": 1,\n          \"ks\": {\n            \"o\": {\n              \"a\": 0,\n              \"k\": 100,\n              \"ix\": 11\n            },\n            \"r\": {\n              \"a\": 0,\n              \"k\": 14,\n              \"ix\": 10\n            },\n            \"p\": {\n              \"a\": 1,\n              \"k\": [\n                {\n                  \"i\": {\n                    \"x\": 0.833,\n                    \"y\": 0.833\n                  },\n                  \"o\": {\n                    \"x\": 0.167,\n                    \"y\": 0.167\n                  },\n                  \"t\": 13,\n                  \"s\": [219.178, -190.096, 0],\n                  \"to\": [-95.333, 426.667, 0],\n                  \"ti\": [167.333, -560.667, 0]\n                },\n                {\n                  \"t\": 173,\n                  \"s\": [179.178, 989.904, 0]\n                }\n              ],\n              \"ix\": 2\n            },\n            \"a\": {\n              \"a\": 0,\n              \"k\": [-157, -245, 0],\n              \"ix\": 1\n            },\n            \"s\": {\n              \"a\": 0,\n              \"k\": [-100, 100, 100],\n              \"ix\": 6\n            }\n          },\n          \"ao\": 0,\n          \"shapes\": [\n            {\n              \"ty\": \"gr\",\n              \"it\": [\n                {\n                  \"ind\": 0,\n                  \"ty\": \"sh\",\n                  \"ix\": 1,\n                  \"ks\": {\n                    \"a\": 0,\n                    \"k\": {\n                      \"i\": [\n                        [0, 0],\n                        [-1.685, -13.314],\n                        [0, -14.907],\n                        [0, -15.206],\n                        [0, -14.907],\n                        [0, -14.907],\n                        [0, -15.206],\n                        [1.754, -14.206],\n                        [-3.934, -9.465]\n                      ],\n                      \"o\": [\n                        [-3.895, 8.562],\n                        [1.872, 14.789],\n                        [0, 15.206],\n                        [0, 14.907],\n                        [0, 14.907],\n                        [0, 15.206],\n                        [0, 14.314],\n                        [-1.803, 14.605],\n                        [0, 0]\n                      ],\n                      \"v\": [\n                        [-156.5, -406],\n                        [-166.5, -367],\n                        [-146.5, -327],\n                        [-166.5, -286],\n                        [-146.5, -246],\n                        [-166.5, -206],\n                        [-146.5, -165],\n                        [-166.5, -127],\n                        [-156.5, -84]\n                      ],\n                      \"c\": false\n                    },\n                    \"ix\": 2\n                  },\n                  \"nm\": \"Path 1\",\n                  \"mn\": \"ADBE Vector Shape - Group\",\n                  \"hd\": false\n                },\n                {\n                  \"ty\": \"st\",\n                  \"c\": {\n                    \"a\": 0,\n                    \"k\": [1, 0.12156862745098039, 0.5647058823529412, 1],\n                    \"ix\": 3\n                  },\n                  \"o\": {\n                    \"a\": 0,\n                    \"k\": 100,\n                    \"ix\": 4\n                  },\n                  \"w\": {\n                    \"a\": 1,\n                    \"k\": [\n                      {\n                        \"i\": {\n                          \"x\": [0.833],\n                          \"y\": [0.833]\n                        },\n                        \"o\": {\n                          \"x\": [0.167],\n                          \"y\": [0.167]\n                        },\n                        \"t\": 13,\n                        \"s\": [4]\n                      },\n                      {\n                        \"t\": 176,\n                        \"s\": [0.5]\n                      }\n                    ],\n                    \"ix\": 5\n                  },\n                  \"lc\": 1,\n                  \"lj\": 1,\n                  \"ml\": 4,\n                  \"bm\": 0,\n                  \"nm\": \"Stroke 1\",\n                  \"mn\": \"ADBE Vector Graphic - Stroke\",\n                  \"hd\": false\n                },\n                {\n                  \"ty\": \"tr\",\n                  \"p\": {\n                    \"a\": 0,\n                    \"k\": [0, 0],\n                    \"ix\": 2\n                  },\n                  \"a\": {\n                    \"a\": 0,\n                    \"k\": [0, 0],\n                    \"ix\": 1\n                  },\n                  \"s\": {\n                    \"a\": 0,\n                    \"k\": [100, 100],\n                    \"ix\": 3\n                  },\n                  \"r\": {\n                    \"a\": 0,\n                    \"k\": 0,\n                    \"ix\": 6\n                  },\n                  \"o\": {\n                    \"a\": 0,\n                    \"k\": 100,\n                    \"ix\": 7\n                  },\n                  \"sk\": {\n                    \"a\": 0,\n                    \"k\": 0,\n                    \"ix\": 4\n                  },\n                  \"sa\": {\n                    \"a\": 0,\n                    \"k\": 0,\n                    \"ix\": 5\n                  },\n                  \"nm\": \"Transform\"\n                }\n              ],\n              \"nm\": \"Shape 1\",\n              \"np\": 2,\n              \"cix\": 2,\n              \"bm\": 0,\n              \"ix\": 1,\n              \"mn\": \"ADBE Vector Group\",\n              \"hd\": false\n            },\n            {\n              \"ty\": \"tm\",\n              \"s\": {\n                \"a\": 1,\n                \"k\": [\n                  {\n                    \"i\": {\n                      \"x\": [0.833],\n                      \"y\": [0.833]\n                    },\n                    \"o\": {\n                      \"x\": [0.167],\n                      \"y\": [0.167]\n                    },\n                    \"t\": 18,\n                    \"s\": [0]\n                  },\n                  {\n                    \"t\": 176,\n                    \"s\": [100]\n                  }\n                ],\n                \"ix\": 1\n              },\n              \"e\": {\n                \"a\": 1,\n                \"k\": [\n                  {\n                    \"i\": {\n                      \"x\": [0.833],\n                      \"y\": [0.833]\n                    },\n                    \"o\": {\n                      \"x\": [0.167],\n                      \"y\": [0.167]\n                    },\n                    \"t\": 13,\n                    \"s\": [0]\n                  },\n                  {\n                    \"i\": {\n                      \"x\": [0.833],\n                      \"y\": [0.833]\n                    },\n                    \"o\": {\n                      \"x\": [0.167],\n                      \"y\": [0.167]\n                    },\n                    \"t\": 18,\n                    \"s\": [40]\n                  },\n                  {\n                    \"t\": 176,\n                    \"s\": [100]\n                  }\n                ],\n                \"ix\": 2\n              },\n              \"o\": {\n                \"a\": 0,\n                \"k\": 0,\n                \"ix\": 3\n              },\n              \"m\": 1,\n              \"ix\": 2,\n              \"nm\": \"Trim Paths 1\",\n              \"mn\": \"ADBE Vector Filter - Trim\",\n              \"hd\": false\n            }\n          ],\n          \"ip\": 13,\n          \"op\": 174,\n          \"st\": 13,\n          \"bm\": 0\n        },\n        {\n          \"ddd\": 0,\n          \"ind\": 2,\n          \"ty\": 4,\n          \"nm\": \"streamer b 4\",\n          \"sr\": 1,\n          \"ks\": {\n            \"o\": {\n              \"a\": 0,\n              \"k\": 100,\n              \"ix\": 11\n            },\n            \"r\": {\n              \"a\": 0,\n              \"k\": -1.458,\n              \"ix\": 10\n            },\n            \"p\": {\n              \"a\": 1,\n              \"k\": [\n                {\n                  \"i\": {\n                    \"x\": 0.833,\n                    \"y\": 0.833\n                  },\n                  \"o\": {\n                    \"x\": 0.167,\n                    \"y\": 0.167\n                  },\n                  \"t\": 5,\n                  \"s\": [269.863, -175.455, 0],\n                  \"to\": [-110, 415.333, 0],\n                  \"ti\": [216, -599.333, 0]\n                },\n                {\n                  \"t\": 173,\n                  \"s\": [69.863, 984.545, 0]\n                }\n              ],\n              \"ix\": 2\n            },\n            \"a\": {\n              \"a\": 0,\n              \"k\": [-157, -245, 0],\n              \"ix\": 1\n            },\n            \"s\": {\n              \"a\": 0,\n              \"k\": [100, 100, 100],\n              \"ix\": 6\n            }\n          },\n          \"ao\": 0,\n          \"shapes\": [\n            {\n              \"ty\": \"gr\",\n              \"it\": [\n                {\n                  \"ind\": 0,\n                  \"ty\": \"sh\",\n                  \"ix\": 1,\n                  \"ks\": {\n                    \"a\": 0,\n                    \"k\": {\n                      \"i\": [\n                        [0, 0],\n                        [-1.685, -13.314],\n                        [0, -14.907],\n                        [0, -15.206],\n                        [0, -14.907],\n                        [0, -14.907],\n                        [0, -15.206],\n                        [1.754, -14.206],\n                        [-3.934, -9.465]\n                      ],\n                      \"o\": [\n                        [-3.895, 8.562],\n                        [1.872, 14.789],\n                        [0, 15.206],\n                        [0, 14.907],\n                        [0, 14.907],\n                        [0, 15.206],\n                        [0, 14.314],\n                        [-1.803, 14.605],\n                        [0, 0]\n                      ],\n                      \"v\": [\n                        [-156.5, -406],\n                        [-166.5, -367],\n                        [-146.5, -327],\n                        [-166.5, -286],\n                        [-146.5, -246],\n                        [-166.5, -206],\n                        [-146.5, -165],\n                        [-166.5, -127],\n                        [-156.5, -84]\n                      ],\n                      \"c\": false\n                    },\n                    \"ix\": 2\n                  },\n                  \"nm\": \"Path 1\",\n                  \"mn\": \"ADBE Vector Shape - Group\",\n                  \"hd\": false\n                },\n                {\n                  \"ty\": \"st\",\n                  \"c\": {\n                    \"a\": 0,\n                    \"k\": [1, 0.2627450980392157, 0.2, 1],\n                    \"ix\": 3\n                  },\n                  \"o\": {\n                    \"a\": 0,\n                    \"k\": 100,\n                    \"ix\": 4\n                  },\n                  \"w\": {\n                    \"a\": 1,\n                    \"k\": [\n                      {\n                        \"i\": {\n                          \"x\": [0.833],\n                          \"y\": [0.833]\n                        },\n                        \"o\": {\n                          \"x\": [0.167],\n                          \"y\": [0.167]\n                        },\n                        \"t\": 5,\n                        \"s\": [4]\n                      },\n                      {\n                        \"t\": 173,\n                        \"s\": [0.5]\n                      }\n                    ],\n                    \"ix\": 5\n                  },\n                  \"lc\": 1,\n                  \"lj\": 1,\n                  \"ml\": 4,\n                  \"bm\": 0,\n                  \"nm\": \"Stroke 1\",\n                  \"mn\": \"ADBE Vector Graphic - Stroke\",\n                  \"hd\": false\n                },\n                {\n                  \"ty\": \"tr\",\n                  \"p\": {\n                    \"a\": 0,\n                    \"k\": [0, 0],\n                    \"ix\": 2\n                  },\n                  \"a\": {\n                    \"a\": 0,\n                    \"k\": [0, 0],\n                    \"ix\": 1\n                  },\n                  \"s\": {\n                    \"a\": 0,\n                    \"k\": [100, 100],\n                    \"ix\": 3\n                  },\n                  \"r\": {\n                    \"a\": 0,\n                    \"k\": 0,\n                    \"ix\": 6\n                  },\n                  \"o\": {\n                    \"a\": 0,\n                    \"k\": 100,\n                    \"ix\": 7\n                  },\n                  \"sk\": {\n                    \"a\": 0,\n                    \"k\": 0,\n                    \"ix\": 4\n                  },\n                  \"sa\": {\n                    \"a\": 0,\n                    \"k\": 0,\n                    \"ix\": 5\n                  },\n                  \"nm\": \"Transform\"\n                }\n              ],\n              \"nm\": \"Shape 1\",\n              \"np\": 2,\n              \"cix\": 2,\n              \"bm\": 0,\n              \"ix\": 1,\n              \"mn\": \"ADBE Vector Group\",\n              \"hd\": false\n            },\n            {\n              \"ty\": \"tm\",\n              \"s\": {\n                \"a\": 1,\n                \"k\": [\n                  {\n                    \"i\": {\n                      \"x\": [0.833],\n                      \"y\": [0.833]\n                    },\n                    \"o\": {\n                      \"x\": [0.167],\n                      \"y\": [0.167]\n                    },\n                    \"t\": 10,\n                    \"s\": [0]\n                  },\n                  {\n                    \"t\": 173,\n                    \"s\": [100]\n                  }\n                ],\n                \"ix\": 1\n              },\n              \"e\": {\n                \"a\": 1,\n                \"k\": [\n                  {\n                    \"i\": {\n                      \"x\": [0.833],\n                      \"y\": [0.833]\n                    },\n                    \"o\": {\n                      \"x\": [0.167],\n                      \"y\": [0.167]\n                    },\n                    \"t\": 5,\n                    \"s\": [0]\n                  },\n                  {\n                    \"i\": {\n                      \"x\": [0.833],\n                      \"y\": [0.833]\n                    },\n                    \"o\": {\n                      \"x\": [0.167],\n                      \"y\": [0.167]\n                    },\n                    \"t\": 10,\n                    \"s\": [40]\n                  },\n                  {\n                    \"t\": 173,\n                    \"s\": [100]\n                  }\n                ],\n                \"ix\": 2\n              },\n              \"o\": {\n                \"a\": 0,\n                \"k\": 0,\n                \"ix\": 3\n              },\n              \"m\": 1,\n              \"ix\": 2,\n              \"nm\": \"Trim Paths 1\",\n              \"mn\": \"ADBE Vector Filter - Trim\",\n              \"hd\": false\n            }\n          ],\n          \"ip\": 5,\n          \"op\": 174,\n          \"st\": 5,\n          \"bm\": 0\n        },\n        {\n          \"ddd\": 0,\n          \"ind\": 3,\n          \"ty\": 4,\n          \"nm\": \"circle a 4\",\n          \"sr\": 1,\n          \"ks\": {\n            \"o\": {\n              \"a\": 0,\n              \"k\": 100,\n              \"ix\": 11\n            },\n            \"r\": {\n              \"a\": 1,\n              \"k\": [\n                {\n                  \"i\": {\n                    \"x\": [0.833],\n                    \"y\": [0.833]\n                  },\n                  \"o\": {\n                    \"x\": [0.167],\n                    \"y\": [0.167]\n                  },\n                  \"t\": 8,\n                  \"s\": [0]\n                },\n                {\n                  \"t\": 155,\n                  \"s\": [1800]\n                }\n              ],\n              \"ix\": 10\n            },\n            \"p\": {\n              \"a\": 1,\n              \"k\": [\n                {\n                  \"i\": {\n                    \"x\": 0.833,\n                    \"y\": 0.833\n                  },\n                  \"o\": {\n                    \"x\": 0.167,\n                    \"y\": 0.167\n                  },\n                  \"t\": 8,\n                  \"s\": [325.643, -26.292, 0],\n                  \"to\": [-101.333, 75.667, 0],\n                  \"ti\": [15.333, -507.667, 0]\n                },\n                {\n                  \"t\": 155,\n                  \"s\": [125.643, 835.708, 0]\n                }\n              ],\n              \"ix\": 2\n            },\n            \"a\": {\n              \"a\": 0,\n              \"k\": [0, 0, 0],\n              \"ix\": 1\n            },\n            \"s\": {\n              \"a\": 1,\n              \"k\": [\n                {\n                  \"i\": {\n                    \"x\": [0.833, 0.833, 0.833],\n                    \"y\": [0.833, 0.833, 0.833]\n                  },\n                  \"o\": {\n                    \"x\": [0.167, 0.167, 0.167],\n                    \"y\": [0.167, 0.167, 0.167]\n                  },\n                  \"t\": 8,\n                  \"s\": [50, 100, 100]\n                },\n                {\n                  \"t\": 155,\n                  \"s\": [100, 50, 100]\n                }\n              ],\n              \"ix\": 6\n            }\n          },\n          \"ao\": 0,\n          \"shapes\": [\n            {\n              \"ty\": \"gr\",\n              \"it\": [\n                {\n                  \"d\": 1,\n                  \"ty\": \"el\",\n                  \"s\": {\n                    \"a\": 0,\n                    \"k\": [16, 16],\n                    \"ix\": 2\n                  },\n                  \"p\": {\n                    \"a\": 0,\n                    \"k\": [0, 0],\n                    \"ix\": 3\n                  },\n                  \"nm\": \"Ellipse Path 1\",\n                  \"mn\": \"ADBE Vector Shape - Ellipse\",\n                  \"hd\": false\n                },\n                {\n                  \"ty\": \"fl\",\n                  \"c\": {\n                    \"a\": 0,\n                    \"k\": [0.12156862745098039, 0.8431372549019608, 1, 1],\n                    \"ix\": 4\n                  },\n                  \"o\": {\n                    \"a\": 0,\n                    \"k\": 100,\n                    \"ix\": 5\n                  },\n                  \"r\": 1,\n                  \"bm\": 0,\n                  \"nm\": \"Fill 1\",\n                  \"mn\": \"ADBE Vector Graphic - Fill\",\n                  \"hd\": false\n                },\n                {\n                  \"ty\": \"tr\",\n                  \"p\": {\n                    \"a\": 0,\n                    \"k\": [0, 0],\n                    \"ix\": 2\n                  },\n                  \"a\": {\n                    \"a\": 0,\n                    \"k\": [0, 0],\n                    \"ix\": 1\n                  },\n                  \"s\": {\n                    \"a\": 0,\n                    \"k\": [100, 100],\n                    \"ix\": 3\n                  },\n                  \"r\": {\n                    \"a\": 0,\n                    \"k\": 0,\n                    \"ix\": 6\n                  },\n                  \"o\": {\n                    \"a\": 0,\n                    \"k\": 100,\n                    \"ix\": 7\n                  },\n                  \"sk\": {\n                    \"a\": 0,\n                    \"k\": 0,\n                    \"ix\": 4\n                  },\n                  \"sa\": {\n                    \"a\": 0,\n                    \"k\": 0,\n                    \"ix\": 5\n                  },\n                  \"nm\": \"Transform\"\n                }\n              ],\n              \"nm\": \"Ellipse 1\",\n              \"np\": 2,\n              \"cix\": 2,\n              \"bm\": 0,\n              \"ix\": 1,\n              \"mn\": \"ADBE Vector Group\",\n              \"hd\": false\n            }\n          ],\n          \"ip\": 8,\n          \"op\": 156,\n          \"st\": -7,\n          \"bm\": 0\n        },\n        {\n          \"ddd\": 0,\n          \"ind\": 4,\n          \"ty\": 4,\n          \"nm\": \"circle b 4\",\n          \"sr\": 1,\n          \"ks\": {\n            \"o\": {\n              \"a\": 0,\n              \"k\": 50,\n              \"ix\": 11\n            },\n            \"r\": {\n              \"a\": 1,\n              \"k\": [\n                {\n                  \"i\": {\n                    \"x\": [0.833],\n                    \"y\": [0.833]\n                  },\n                  \"o\": {\n                    \"x\": [0.167],\n                    \"y\": [0.167]\n                  },\n                  \"t\": 2,\n                  \"s\": [0]\n                },\n                {\n                  \"t\": 215,\n                  \"s\": [2520]\n                }\n              ],\n              \"ix\": 10\n            },\n            \"p\": {\n              \"a\": 1,\n              \"k\": [\n                {\n                  \"i\": {\n                    \"x\": 0.833,\n                    \"y\": 0.833\n                  },\n                  \"o\": {\n                    \"x\": 0.167,\n                    \"y\": 0.167\n                  },\n                  \"t\": 2,\n                  \"s\": [619.5, -26.292, 0],\n                  \"to\": [-138, 77.667, 0],\n                  \"ti\": [-2, -497.667, 0]\n                },\n                {\n                  \"t\": 215,\n                  \"s\": [259.5, 835.708, 0]\n                }\n              ],\n              \"ix\": 2\n            },\n            \"a\": {\n              \"a\": 0,\n              \"k\": [0, 0, 0],\n              \"ix\": 1\n            },\n            \"s\": {\n              \"a\": 1,\n              \"k\": [\n                {\n                  \"i\": {\n                    \"x\": [0.833, 0.833, 0.833],\n                    \"y\": [0.833, 0.833, 0.833]\n                  },\n                  \"o\": {\n                    \"x\": [0.167, 0.167, 0.167],\n                    \"y\": [0.167, 0.167, 0.167]\n                  },\n                  \"t\": 2,\n                  \"s\": [50, 100, 100]\n                },\n                {\n                  \"t\": 215,\n                  \"s\": [100, 50, 100]\n                }\n              ],\n              \"ix\": 6\n            }\n          },\n          \"ao\": 0,\n          \"shapes\": [\n            {\n              \"ty\": \"gr\",\n              \"it\": [\n                {\n                  \"d\": 1,\n                  \"ty\": \"el\",\n                  \"s\": {\n                    \"a\": 0,\n                    \"k\": [16, 16],\n                    \"ix\": 2\n                  },\n                  \"p\": {\n                    \"a\": 0,\n                    \"k\": [0, 0],\n                    \"ix\": 3\n                  },\n                  \"nm\": \"Ellipse Path 1\",\n                  \"mn\": \"ADBE Vector Shape - Ellipse\",\n                  \"hd\": false\n                },\n                {\n                  \"ty\": \"fl\",\n                  \"c\": {\n                    \"a\": 0,\n                    \"k\": [1, 0.12156862745098039, 0.5647058823529412, 1],\n                    \"ix\": 4\n                  },\n                  \"o\": {\n                    \"a\": 0,\n                    \"k\": 100,\n                    \"ix\": 5\n                  },\n                  \"r\": 1,\n                  \"bm\": 0,\n                  \"nm\": \"Fill 1\",\n                  \"mn\": \"ADBE Vector Graphic - Fill\",\n                  \"hd\": false\n                },\n                {\n                  \"ty\": \"tr\",\n                  \"p\": {\n                    \"a\": 0,\n                    \"k\": [0, 0],\n                    \"ix\": 2\n                  },\n                  \"a\": {\n                    \"a\": 0,\n                    \"k\": [0, 0],\n                    \"ix\": 1\n                  },\n                  \"s\": {\n                    \"a\": 0,\n                    \"k\": [100, 100],\n                    \"ix\": 3\n                  },\n                  \"r\": {\n                    \"a\": 0,\n                    \"k\": 0,\n                    \"ix\": 6\n                  },\n                  \"o\": {\n                    \"a\": 0,\n                    \"k\": 100,\n                    \"ix\": 7\n                  },\n                  \"sk\": {\n                    \"a\": 0,\n                    \"k\": 0,\n                    \"ix\": 4\n                  },\n                  \"sa\": {\n                    \"a\": 0,\n                    \"k\": 0,\n                    \"ix\": 5\n                  },\n                  \"nm\": \"Transform\"\n                }\n              ],\n              \"nm\": \"Ellipse 1\",\n              \"np\": 2,\n              \"cix\": 2,\n              \"bm\": 0,\n              \"ix\": 1,\n              \"mn\": \"ADBE Vector Group\",\n              \"hd\": false\n            }\n          ],\n          \"ip\": 2,\n          \"op\": 216,\n          \"st\": -13,\n          \"bm\": 0\n        },\n        {\n          \"ddd\": 0,\n          \"ind\": 5,\n          \"ty\": 4,\n          \"nm\": \"star a 4\",\n          \"sr\": 1,\n          \"ks\": {\n            \"o\": {\n              \"a\": 0,\n              \"k\": 100,\n              \"ix\": 11\n            },\n            \"r\": {\n              \"a\": 1,\n              \"k\": [\n                {\n                  \"i\": {\n                    \"x\": [0.833],\n                    \"y\": [0.833]\n                  },\n                  \"o\": {\n                    \"x\": [0.167],\n                    \"y\": [0.167]\n                  },\n                  \"t\": 6,\n                  \"s\": [0]\n                },\n                {\n                  \"t\": 245,\n                  \"s\": [2880]\n                }\n              ],\n              \"ix\": 10\n            },\n            \"p\": {\n              \"a\": 1,\n              \"k\": [\n                {\n                  \"i\": {\n                    \"x\": 0.833,\n                    \"y\": 0.833\n                  },\n                  \"o\": {\n                    \"x\": 0.167,\n                    \"y\": 0.167\n                  },\n                  \"t\": 6,\n                  \"s\": [376.929, -28, 0],\n                  \"to\": [-213.333, 157.667, 0],\n                  \"ti\": [173.333, -127.667, 0]\n                },\n                {\n                  \"t\": 245,\n                  \"s\": [116.929, 834, 0]\n                }\n              ],\n              \"ix\": 2\n            },\n            \"a\": {\n              \"a\": 0,\n              \"k\": [0, 0, 0],\n              \"ix\": 1\n            },\n            \"s\": {\n              \"a\": 1,\n              \"k\": [\n                {\n                  \"i\": {\n                    \"x\": [0.833, 0.833, 0.833],\n                    \"y\": [0.833, 0.833, 0.833]\n                  },\n                  \"o\": {\n                    \"x\": [0.167, 0.167, 0.167],\n                    \"y\": [0.167, 0.167, 0.167]\n                  },\n                  \"t\": 6,\n                  \"s\": [50, 100, 100]\n                },\n                {\n                  \"t\": 245,\n                  \"s\": [100, 50, 100]\n                }\n              ],\n              \"ix\": 6\n            }\n          },\n          \"ao\": 0,\n          \"shapes\": [\n            {\n              \"ty\": \"gr\",\n              \"it\": [\n                {\n                  \"ty\": \"sr\",\n                  \"sy\": 1,\n                  \"d\": 1,\n                  \"pt\": {\n                    \"a\": 0,\n                    \"k\": 5,\n                    \"ix\": 3\n                  },\n                  \"p\": {\n                    \"a\": 0,\n                    \"k\": [0, 0],\n                    \"ix\": 4\n                  },\n                  \"r\": {\n                    \"a\": 0,\n                    \"k\": 0,\n                    \"ix\": 5\n                  },\n                  \"ir\": {\n                    \"a\": 0,\n                    \"k\": 5,\n                    \"ix\": 6\n                  },\n                  \"is\": {\n                    \"a\": 0,\n                    \"k\": 0,\n                    \"ix\": 8\n                  },\n                  \"or\": {\n                    \"a\": 0,\n                    \"k\": 12,\n                    \"ix\": 7\n                  },\n                  \"os\": {\n                    \"a\": 0,\n                    \"k\": 0,\n                    \"ix\": 9\n                  },\n                  \"ix\": 1,\n                  \"nm\": \"Polystar Path 1\",\n                  \"mn\": \"ADBE Vector Shape - Star\",\n                  \"hd\": false\n                },\n                {\n                  \"ty\": \"fl\",\n                  \"c\": {\n                    \"a\": 0,\n                    \"k\": [1, 0.2627450980392157, 0.2, 1],\n                    \"ix\": 4\n                  },\n                  \"o\": {\n                    \"a\": 0,\n                    \"k\": 100,\n                    \"ix\": 5\n                  },\n                  \"r\": 1,\n                  \"bm\": 0,\n                  \"nm\": \"Fill 1\",\n                  \"mn\": \"ADBE Vector Graphic - Fill\",\n                  \"hd\": false\n                },\n                {\n                  \"ty\": \"tr\",\n                  \"p\": {\n                    \"a\": 0,\n                    \"k\": [0, 0],\n                    \"ix\": 2\n                  },\n                  \"a\": {\n                    \"a\": 0,\n                    \"k\": [0, 0],\n                    \"ix\": 1\n                  },\n                  \"s\": {\n                    \"a\": 0,\n                    \"k\": [100, 100],\n                    \"ix\": 3\n                  },\n                  \"r\": {\n                    \"a\": 0,\n                    \"k\": 0,\n                    \"ix\": 6\n                  },\n                  \"o\": {\n                    \"a\": 0,\n                    \"k\": 100,\n                    \"ix\": 7\n                  },\n                  \"sk\": {\n                    \"a\": 0,\n                    \"k\": 0,\n                    \"ix\": 4\n                  },\n                  \"sa\": {\n                    \"a\": 0,\n                    \"k\": 0,\n                    \"ix\": 5\n                  },\n                  \"nm\": \"Transform\"\n                }\n              ],\n              \"nm\": \"Polystar 1\",\n              \"np\": 2,\n              \"cix\": 2,\n              \"bm\": 0,\n              \"ix\": 1,\n              \"mn\": \"ADBE Vector Group\",\n              \"hd\": false\n            }\n          ],\n          \"ip\": 6,\n          \"op\": 246,\n          \"st\": -9,\n          \"bm\": 0\n        },\n        {\n          \"ddd\": 0,\n          \"ind\": 6,\n          \"ty\": 4,\n          \"nm\": \"star b 4\",\n          \"sr\": 1,\n          \"ks\": {\n            \"o\": {\n              \"a\": 0,\n              \"k\": 50,\n              \"ix\": 11\n            },\n            \"r\": {\n              \"a\": 1,\n              \"k\": [\n                {\n                  \"i\": {\n                    \"x\": [0.833],\n                    \"y\": [0.833]\n                  },\n                  \"o\": {\n                    \"x\": [0.167],\n                    \"y\": [0.167]\n                  },\n                  \"t\": 2,\n                  \"s\": [0]\n                },\n                {\n                  \"t\": 125,\n                  \"s\": [1800]\n                }\n              ],\n              \"ix\": 10\n            },\n            \"p\": {\n              \"a\": 1,\n              \"k\": [\n                {\n                  \"i\": {\n                    \"x\": 0.833,\n                    \"y\": 0.833\n                  },\n                  \"o\": {\n                    \"x\": 0.167,\n                    \"y\": 0.167\n                  },\n                  \"t\": 2,\n                  \"s\": [171.786, -28, 0],\n                  \"to\": [0, 0, 0],\n                  \"ti\": [-161.333, -275.667, 0]\n                },\n                {\n                  \"t\": 125,\n                  \"s\": [251.786, 834, 0]\n                }\n              ],\n              \"ix\": 2\n            },\n            \"a\": {\n              \"a\": 0,\n              \"k\": [0, 0, 0],\n              \"ix\": 1\n            },\n            \"s\": {\n              \"a\": 1,\n              \"k\": [\n                {\n                  \"i\": {\n                    \"x\": [0.833, 0.833, 0.833],\n                    \"y\": [0.833, 0.833, 0.833]\n                  },\n                  \"o\": {\n                    \"x\": [0.167, 0.167, 0.167],\n                    \"y\": [0.167, 0.167, 0.167]\n                  },\n                  \"t\": 2,\n                  \"s\": [50, 100, 100]\n                },\n                {\n                  \"t\": 125,\n                  \"s\": [100, 50, 100]\n                }\n              ],\n              \"ix\": 6\n            }\n          },\n          \"ao\": 0,\n          \"shapes\": [\n            {\n              \"ty\": \"gr\",\n              \"it\": [\n                {\n                  \"ty\": \"sr\",\n                  \"sy\": 1,\n                  \"d\": 1,\n                  \"pt\": {\n                    \"a\": 0,\n                    \"k\": 5,\n                    \"ix\": 3\n                  },\n                  \"p\": {\n                    \"a\": 0,\n                    \"k\": [0, 0],\n                    \"ix\": 4\n                  },\n                  \"r\": {\n                    \"a\": 0,\n                    \"k\": 0,\n                    \"ix\": 5\n                  },\n                  \"ir\": {\n                    \"a\": 0,\n                    \"k\": 5,\n                    \"ix\": 6\n                  },\n                  \"is\": {\n                    \"a\": 0,\n                    \"k\": 0,\n                    \"ix\": 8\n                  },\n                  \"or\": {\n                    \"a\": 0,\n                    \"k\": 12,\n                    \"ix\": 7\n                  },\n                  \"os\": {\n                    \"a\": 0,\n                    \"k\": 0,\n                    \"ix\": 9\n                  },\n                  \"ix\": 1,\n                  \"nm\": \"Polystar Path 1\",\n                  \"mn\": \"ADBE Vector Shape - Star\",\n                  \"hd\": false\n                },\n                {\n                  \"ty\": \"fl\",\n                  \"c\": {\n                    \"a\": 0,\n                    \"k\": [0, 0.5215686274509804, 0.27058823529411763, 1],\n                    \"ix\": 4\n                  },\n                  \"o\": {\n                    \"a\": 0,\n                    \"k\": 100,\n                    \"ix\": 5\n                  },\n                  \"r\": 1,\n                  \"bm\": 0,\n                  \"nm\": \"Fill 1\",\n                  \"mn\": \"ADBE Vector Graphic - Fill\",\n                  \"hd\": false\n                },\n                {\n                  \"ty\": \"tr\",\n                  \"p\": {\n                    \"a\": 0,\n                    \"k\": [0, 0],\n                    \"ix\": 2\n                  },\n                  \"a\": {\n                    \"a\": 0,\n                    \"k\": [0, 0],\n                    \"ix\": 1\n                  },\n                  \"s\": {\n                    \"a\": 0,\n                    \"k\": [100, 100],\n                    \"ix\": 3\n                  },\n                  \"r\": {\n                    \"a\": 0,\n                    \"k\": 0,\n                    \"ix\": 6\n                  },\n                  \"o\": {\n                    \"a\": 0,\n                    \"k\": 100,\n                    \"ix\": 7\n                  },\n                  \"sk\": {\n                    \"a\": 0,\n                    \"k\": 0,\n                    \"ix\": 4\n                  },\n                  \"sa\": {\n                    \"a\": 0,\n                    \"k\": 0,\n                    \"ix\": 5\n                  },\n                  \"nm\": \"Transform\"\n                }\n              ],\n              \"nm\": \"Polystar 1\",\n              \"np\": 2,\n              \"cix\": 2,\n              \"bm\": 0,\n              \"ix\": 1,\n              \"mn\": \"ADBE Vector Group\",\n              \"hd\": false\n            }\n          ],\n          \"ip\": 2,\n          \"op\": 126,\n          \"st\": -13,\n          \"bm\": 0\n        },\n        {\n          \"ddd\": 0,\n          \"ind\": 7,\n          \"ty\": 4,\n          \"nm\": \"rec a 4\",\n          \"sr\": 1,\n          \"ks\": {\n            \"o\": {\n              \"a\": 0,\n              \"k\": 100,\n              \"ix\": 11\n            },\n            \"r\": {\n              \"a\": 1,\n              \"k\": [\n                {\n                  \"i\": {\n                    \"x\": [0.833],\n                    \"y\": [0.833]\n                  },\n                  \"o\": {\n                    \"x\": [0.167],\n                    \"y\": [0.167]\n                  },\n                  \"t\": 4,\n                  \"s\": [0]\n                },\n                {\n                  \"t\": 185,\n                  \"s\": [2520]\n                }\n              ],\n              \"ix\": 10\n            },\n            \"p\": {\n              \"a\": 1,\n              \"k\": [\n                {\n                  \"i\": {\n                    \"x\": 0.833,\n                    \"y\": 0.833\n                  },\n                  \"o\": {\n                    \"x\": 0.167,\n                    \"y\": 0.167\n                  },\n                  \"t\": 4,\n                  \"s\": [428.214, -22.292, 0],\n                  \"to\": [-167.333, 119.667, 0],\n                  \"ti\": [-130.667, -315.667, 0]\n                },\n                {\n                  \"t\": 185,\n                  \"s\": [228.214, 839.708, 0]\n                }\n              ],\n              \"ix\": 2\n            },\n            \"a\": {\n              \"a\": 0,\n              \"k\": [0, 0, 0],\n              \"ix\": 1\n            },\n            \"s\": {\n              \"a\": 1,\n              \"k\": [\n                {\n                  \"i\": {\n                    \"x\": [0.833, 0.833, 0.833],\n                    \"y\": [0.833, 0.833, 0.833]\n                  },\n                  \"o\": {\n                    \"x\": [0.167, 0.167, 0.167],\n                    \"y\": [0.167, 0.167, 0.167]\n                  },\n                  \"t\": 4,\n                  \"s\": [50, 100, 100]\n                },\n                {\n                  \"t\": 185,\n                  \"s\": [100, 50, 100]\n                }\n              ],\n              \"ix\": 6\n            }\n          },\n          \"ao\": 0,\n          \"shapes\": [\n            {\n              \"ty\": \"gr\",\n              \"it\": [\n                {\n                  \"ty\": \"rc\",\n                  \"d\": 1,\n                  \"s\": {\n                    \"a\": 0,\n                    \"k\": [16, 8],\n                    \"ix\": 2\n                  },\n                  \"p\": {\n                    \"a\": 0,\n                    \"k\": [0, 0],\n                    \"ix\": 3\n                  },\n                  \"r\": {\n                    \"a\": 0,\n                    \"k\": 0,\n                    \"ix\": 4\n                  },\n                  \"nm\": \"Rectangle Path 1\",\n                  \"mn\": \"ADBE Vector Shape - Rect\",\n                  \"hd\": false\n                },\n                {\n                  \"ty\": \"fl\",\n                  \"c\": {\n                    \"a\": 0,\n                    \"k\": [0.12156862745098039, 0.8431372549019608, 1, 1],\n                    \"ix\": 4\n                  },\n                  \"o\": {\n                    \"a\": 0,\n                    \"k\": 100,\n                    \"ix\": 5\n                  },\n                  \"r\": 1,\n                  \"bm\": 0,\n                  \"nm\": \"Fill 1\",\n                  \"mn\": \"ADBE Vector Graphic - Fill\",\n                  \"hd\": false\n                },\n                {\n                  \"ty\": \"tr\",\n                  \"p\": {\n                    \"a\": 0,\n                    \"k\": [0, 0],\n                    \"ix\": 2\n                  },\n                  \"a\": {\n                    \"a\": 0,\n                    \"k\": [0, 0],\n                    \"ix\": 1\n                  },\n                  \"s\": {\n                    \"a\": 0,\n                    \"k\": [100, 100],\n                    \"ix\": 3\n                  },\n                  \"r\": {\n                    \"a\": 0,\n                    \"k\": 0,\n                    \"ix\": 6\n                  },\n                  \"o\": {\n                    \"a\": 0,\n                    \"k\": 100,\n                    \"ix\": 7\n                  },\n                  \"sk\": {\n                    \"a\": 0,\n                    \"k\": 0,\n                    \"ix\": 4\n                  },\n                  \"sa\": {\n                    \"a\": 0,\n                    \"k\": 0,\n                    \"ix\": 5\n                  },\n                  \"nm\": \"Transform\"\n                }\n              ],\n              \"nm\": \"Rectangle 1\",\n              \"np\": 2,\n              \"cix\": 2,\n              \"bm\": 0,\n              \"ix\": 1,\n              \"mn\": \"ADBE Vector Group\",\n              \"hd\": false\n            }\n          ],\n          \"ip\": 4,\n          \"op\": 186,\n          \"st\": -11,\n          \"bm\": 0\n        },\n        {\n          \"ddd\": 0,\n          \"ind\": 8,\n          \"ty\": 4,\n          \"nm\": \"rec b 4\",\n          \"sr\": 1,\n          \"ks\": {\n            \"o\": {\n              \"a\": 0,\n              \"k\": 50,\n              \"ix\": 11\n            },\n            \"r\": {\n              \"a\": 1,\n              \"k\": [\n                {\n                  \"i\": {\n                    \"x\": [0.833],\n                    \"y\": [0.833]\n                  },\n                  \"o\": {\n                    \"x\": [0.167],\n                    \"y\": [0.167]\n                  },\n                  \"t\": 6,\n                  \"s\": [0]\n                },\n                {\n                  \"t\": 245,\n                  \"s\": [2880]\n                }\n              ],\n              \"ix\": 10\n            },\n            \"p\": {\n              \"a\": 1,\n              \"k\": [\n                {\n                  \"i\": {\n                    \"x\": 0.833,\n                    \"y\": 0.833\n                  },\n                  \"o\": {\n                    \"x\": 0.167,\n                    \"y\": 0.167\n                  },\n                  \"t\": 6,\n                  \"s\": [223.071, -22.292, 0],\n                  \"to\": [0, 0, 0],\n                  \"ti\": [-92.571, -383.708, 0]\n                },\n                {\n                  \"t\": 245,\n                  \"s\": [223.071, 839.708, 0]\n                }\n              ],\n              \"ix\": 2\n            },\n            \"a\": {\n              \"a\": 0,\n              \"k\": [0, 0, 0],\n              \"ix\": 1\n            },\n            \"s\": {\n              \"a\": 1,\n              \"k\": [\n                {\n                  \"i\": {\n                    \"x\": [0.833, 0.833, 0.833],\n                    \"y\": [0.833, 0.833, 0.833]\n                  },\n                  \"o\": {\n                    \"x\": [0.167, 0.167, 0.167],\n                    \"y\": [0.167, 0.167, 0.167]\n                  },\n                  \"t\": 6,\n                  \"s\": [50, 100, 100]\n                },\n                {\n                  \"t\": 245,\n                  \"s\": [100, 50, 100]\n                }\n              ],\n              \"ix\": 6\n            }\n          },\n          \"ao\": 0,\n          \"shapes\": [\n            {\n              \"ty\": \"gr\",\n              \"it\": [\n                {\n                  \"ty\": \"rc\",\n                  \"d\": 1,\n                  \"s\": {\n                    \"a\": 0,\n                    \"k\": [16, 8],\n                    \"ix\": 2\n                  },\n                  \"p\": {\n                    \"a\": 0,\n                    \"k\": [0, 0],\n                    \"ix\": 3\n                  },\n                  \"r\": {\n                    \"a\": 0,\n                    \"k\": 0,\n                    \"ix\": 4\n                  },\n                  \"nm\": \"Rectangle Path 1\",\n                  \"mn\": \"ADBE Vector Shape - Rect\",\n                  \"hd\": false\n                },\n                {\n                  \"ty\": \"fl\",\n                  \"c\": {\n                    \"a\": 0,\n                    \"k\": [1, 0.12156862745098039, 0.5647058823529412, 1],\n                    \"ix\": 4\n                  },\n                  \"o\": {\n                    \"a\": 0,\n                    \"k\": 100,\n                    \"ix\": 5\n                  },\n                  \"r\": 1,\n                  \"bm\": 0,\n                  \"nm\": \"Fill 1\",\n                  \"mn\": \"ADBE Vector Graphic - Fill\",\n                  \"hd\": false\n                },\n                {\n                  \"ty\": \"tr\",\n                  \"p\": {\n                    \"a\": 0,\n                    \"k\": [0, 0],\n                    \"ix\": 2\n                  },\n                  \"a\": {\n                    \"a\": 0,\n                    \"k\": [0, 0],\n                    \"ix\": 1\n                  },\n                  \"s\": {\n                    \"a\": 0,\n                    \"k\": [100, 100],\n                    \"ix\": 3\n                  },\n                  \"r\": {\n                    \"a\": 0,\n                    \"k\": 0,\n                    \"ix\": 6\n                  },\n                  \"o\": {\n                    \"a\": 0,\n                    \"k\": 100,\n                    \"ix\": 7\n                  },\n                  \"sk\": {\n                    \"a\": 0,\n                    \"k\": 0,\n                    \"ix\": 4\n                  },\n                  \"sa\": {\n                    \"a\": 0,\n                    \"k\": 0,\n                    \"ix\": 5\n                  },\n                  \"nm\": \"Transform\"\n                }\n              ],\n              \"nm\": \"Rectangle 1\",\n              \"np\": 2,\n              \"cix\": 2,\n              \"bm\": 0,\n              \"ix\": 1,\n              \"mn\": \"ADBE Vector Group\",\n              \"hd\": false\n            }\n          ],\n          \"ip\": 6,\n          \"op\": 246,\n          \"st\": -9,\n          \"bm\": 0\n        },\n        {\n          \"ddd\": 0,\n          \"ind\": 9,\n          \"ty\": 4,\n          \"nm\": \"square a 4\",\n          \"sr\": 1,\n          \"ks\": {\n            \"o\": {\n              \"a\": 0,\n              \"k\": 100,\n              \"ix\": 11\n            },\n            \"r\": {\n              \"a\": 1,\n              \"k\": [\n                {\n                  \"i\": {\n                    \"x\": [0.833],\n                    \"y\": [0.833]\n                  },\n                  \"o\": {\n                    \"x\": [0.167],\n                    \"y\": [0.167]\n                  },\n                  \"t\": 4,\n                  \"s\": [0]\n                },\n                {\n                  \"t\": 217,\n                  \"s\": [2520]\n                }\n              ],\n              \"ix\": 10\n            },\n            \"p\": {\n              \"a\": 1,\n              \"k\": [\n                {\n                  \"i\": {\n                    \"x\": 0.833,\n                    \"y\": 0.833\n                  },\n                  \"o\": {\n                    \"x\": 0.167,\n                    \"y\": 0.167\n                  },\n                  \"t\": 4,\n                  \"s\": [120.5, -26.292, 0],\n                  \"to\": [13, 430.305, 0],\n                  \"ti\": [52.221, -418.892, 0]\n                },\n                {\n                  \"t\": 217,\n                  \"s\": [198.5, 833.708, 0]\n                }\n              ],\n              \"ix\": 2\n            },\n            \"a\": {\n              \"a\": 0,\n              \"k\": [0, 0, 0],\n              \"ix\": 1\n            },\n            \"s\": {\n              \"a\": 1,\n              \"k\": [\n                {\n                  \"i\": {\n                    \"x\": [0.833, 0.833, 0.833],\n                    \"y\": [0.833, 0.833, 0.833]\n                  },\n                  \"o\": {\n                    \"x\": [0.167, 0.167, 0.167],\n                    \"y\": [0.167, 0.167, 0.167]\n                  },\n                  \"t\": 4,\n                  \"s\": [50, 100, 100]\n                },\n                {\n                  \"t\": 217,\n                  \"s\": [100, 50, 100]\n                }\n              ],\n              \"ix\": 6\n            }\n          },\n          \"ao\": 0,\n          \"shapes\": [\n            {\n              \"ty\": \"gr\",\n              \"it\": [\n                {\n                  \"ty\": \"rc\",\n                  \"d\": 1,\n                  \"s\": {\n                    \"a\": 0,\n                    \"k\": [16, 16],\n                    \"ix\": 2\n                  },\n                  \"p\": {\n                    \"a\": 0,\n                    \"k\": [0, 0],\n                    \"ix\": 3\n                  },\n                  \"r\": {\n                    \"a\": 0,\n                    \"k\": 0,\n                    \"ix\": 4\n                  },\n                  \"nm\": \"Rectangle Path 1\",\n                  \"mn\": \"ADBE Vector Shape - Rect\",\n                  \"hd\": false\n                },\n                {\n                  \"ty\": \"fl\",\n                  \"c\": {\n                    \"a\": 0,\n                    \"k\": [1, 0.2627450980392157, 0.2, 1],\n                    \"ix\": 4\n                  },\n                  \"o\": {\n                    \"a\": 0,\n                    \"k\": 100,\n                    \"ix\": 5\n                  },\n                  \"r\": 1,\n                  \"bm\": 0,\n                  \"nm\": \"Fill 1\",\n                  \"mn\": \"ADBE Vector Graphic - Fill\",\n                  \"hd\": false\n                },\n                {\n                  \"ty\": \"tr\",\n                  \"p\": {\n                    \"a\": 0,\n                    \"k\": [0, 0],\n                    \"ix\": 2\n                  },\n                  \"a\": {\n                    \"a\": 0,\n                    \"k\": [0, 0],\n                    \"ix\": 1\n                  },\n                  \"s\": {\n                    \"a\": 0,\n                    \"k\": [100, 100],\n                    \"ix\": 3\n                  },\n                  \"r\": {\n                    \"a\": 0,\n                    \"k\": 0,\n                    \"ix\": 6\n                  },\n                  \"o\": {\n                    \"a\": 0,\n                    \"k\": 100,\n                    \"ix\": 7\n                  },\n                  \"sk\": {\n                    \"a\": 0,\n                    \"k\": 0,\n                    \"ix\": 4\n                  },\n                  \"sa\": {\n                    \"a\": 0,\n                    \"k\": 0,\n                    \"ix\": 5\n                  },\n                  \"nm\": \"Transform\"\n                }\n              ],\n              \"nm\": \"Rectangle 1\",\n              \"np\": 2,\n              \"cix\": 2,\n              \"bm\": 0,\n              \"ix\": 1,\n              \"mn\": \"ADBE Vector Group\",\n              \"hd\": false\n            }\n          ],\n          \"ip\": 4,\n          \"op\": 218,\n          \"st\": -11,\n          \"bm\": 0\n        },\n        {\n          \"ddd\": 0,\n          \"ind\": 10,\n          \"ty\": 4,\n          \"nm\": \"square b 4\",\n          \"sr\": 1,\n          \"ks\": {\n            \"o\": {\n              \"a\": 0,\n              \"k\": 50,\n              \"ix\": 11\n            },\n            \"r\": {\n              \"a\": 1,\n              \"k\": [\n                {\n                  \"i\": {\n                    \"x\": [0.833],\n                    \"y\": [0.833]\n                  },\n                  \"o\": {\n                    \"x\": [0.167],\n                    \"y\": [0.167]\n                  },\n                  \"t\": 8,\n                  \"s\": [0]\n                },\n                {\n                  \"t\": 215,\n                  \"s\": [2520]\n                }\n              ],\n              \"ix\": 10\n            },\n            \"p\": {\n              \"a\": 1,\n              \"k\": [\n                {\n                  \"i\": {\n                    \"x\": 0.833,\n                    \"y\": 0.833\n                  },\n                  \"o\": {\n                    \"x\": 0.167,\n                    \"y\": 0.167\n                  },\n                  \"t\": 8,\n                  \"s\": [274.357, -26.292, 0],\n                  \"to\": [157.333, 415.667, 0],\n                  \"ti\": [22.667, -253.667, 0]\n                },\n                {\n                  \"t\": 215,\n                  \"s\": [114.357, 835.708, 0]\n                }\n              ],\n              \"ix\": 2\n            },\n            \"a\": {\n              \"a\": 0,\n              \"k\": [0, 0, 0],\n              \"ix\": 1\n            },\n            \"s\": {\n              \"a\": 1,\n              \"k\": [\n                {\n                  \"i\": {\n                    \"x\": [0.833, 0.833, 0.833],\n                    \"y\": [0.833, 0.833, 0.833]\n                  },\n                  \"o\": {\n                    \"x\": [0.167, 0.167, 0.167],\n                    \"y\": [0.167, 0.167, 0.167]\n                  },\n                  \"t\": 8,\n                  \"s\": [50, 100, 100]\n                },\n                {\n                  \"t\": 215,\n                  \"s\": [100, 50, 100]\n                }\n              ],\n              \"ix\": 6\n            }\n          },\n          \"ao\": 0,\n          \"shapes\": [\n            {\n              \"ty\": \"gr\",\n              \"it\": [\n                {\n                  \"ty\": \"rc\",\n                  \"d\": 1,\n                  \"s\": {\n                    \"a\": 0,\n                    \"k\": [16, 16],\n                    \"ix\": 2\n                  },\n                  \"p\": {\n                    \"a\": 0,\n                    \"k\": [0, 0],\n                    \"ix\": 3\n                  },\n                  \"r\": {\n                    \"a\": 0,\n                    \"k\": 0,\n                    \"ix\": 4\n                  },\n                  \"nm\": \"Rectangle Path 1\",\n                  \"mn\": \"ADBE Vector Shape - Rect\",\n                  \"hd\": false\n                },\n                {\n                  \"ty\": \"fl\",\n                  \"c\": {\n                    \"a\": 0,\n                    \"k\": [1, 0.2627450980392157, 0.2, 1],\n                    \"ix\": 4\n                  },\n                  \"o\": {\n                    \"a\": 0,\n                    \"k\": 100,\n                    \"ix\": 5\n                  },\n                  \"r\": 1,\n                  \"bm\": 0,\n                  \"nm\": \"Fill 1\",\n                  \"mn\": \"ADBE Vector Graphic - Fill\",\n                  \"hd\": false\n                },\n                {\n                  \"ty\": \"tr\",\n                  \"p\": {\n                    \"a\": 0,\n                    \"k\": [0, 0],\n                    \"ix\": 2\n                  },\n                  \"a\": {\n                    \"a\": 0,\n                    \"k\": [0, 0],\n                    \"ix\": 1\n                  },\n                  \"s\": {\n                    \"a\": 0,\n                    \"k\": [100, 100],\n                    \"ix\": 3\n                  },\n                  \"r\": {\n                    \"a\": 0,\n                    \"k\": 0,\n                    \"ix\": 6\n                  },\n                  \"o\": {\n                    \"a\": 0,\n                    \"k\": 100,\n                    \"ix\": 7\n                  },\n                  \"sk\": {\n                    \"a\": 0,\n                    \"k\": 0,\n                    \"ix\": 4\n                  },\n                  \"sa\": {\n                    \"a\": 0,\n                    \"k\": 0,\n                    \"ix\": 5\n                  },\n                  \"nm\": \"Transform\"\n                }\n              ],\n              \"nm\": \"Rectangle 1\",\n              \"np\": 2,\n              \"cix\": 2,\n              \"bm\": 0,\n              \"ix\": 1,\n              \"mn\": \"ADBE Vector Group\",\n              \"hd\": false\n            }\n          ],\n          \"ip\": 8,\n          \"op\": 216,\n          \"st\": -7,\n          \"bm\": 0\n        },\n        {\n          \"ddd\": 0,\n          \"ind\": 11,\n          \"ty\": 4,\n          \"nm\": \"streamer a 3\",\n          \"sr\": 1,\n          \"ks\": {\n            \"o\": {\n              \"a\": 0,\n              \"k\": 100,\n              \"ix\": 11\n            },\n            \"r\": {\n              \"a\": 0,\n              \"k\": 3,\n              \"ix\": 10\n            },\n            \"p\": {\n              \"a\": 1,\n              \"k\": [\n                {\n                  \"i\": {\n                    \"x\": 0.833,\n                    \"y\": 0.833\n                  },\n                  \"o\": {\n                    \"x\": 0.167,\n                    \"y\": 0.167\n                  },\n                  \"t\": 0,\n                  \"s\": [275.178, -173.096, 0],\n                  \"to\": [-87.333, 413.333, 0],\n                  \"ti\": [177.333, -643.333, 0]\n                },\n                {\n                  \"t\": 185,\n                  \"s\": [219.178, 974.904, 0]\n                }\n              ],\n              \"ix\": 2\n            },\n            \"a\": {\n              \"a\": 0,\n              \"k\": [-157, -245, 0],\n              \"ix\": 1\n            },\n            \"s\": {\n              \"a\": 0,\n              \"k\": [-100, 100, 100],\n              \"ix\": 6\n            }\n          },\n          \"ao\": 0,\n          \"shapes\": [\n            {\n              \"ty\": \"gr\",\n              \"it\": [\n                {\n                  \"ind\": 0,\n                  \"ty\": \"sh\",\n                  \"ix\": 1,\n                  \"ks\": {\n                    \"a\": 0,\n                    \"k\": {\n                      \"i\": [\n                        [0, 0],\n                        [-1.685, -13.314],\n                        [0, -14.907],\n                        [0, -15.206],\n                        [0, -14.907],\n                        [0, -14.907],\n                        [0, -15.206],\n                        [1.754, -14.206],\n                        [-3.934, -9.465]\n                      ],\n                      \"o\": [\n                        [-3.895, 8.562],\n                        [1.872, 14.789],\n                        [0, 15.206],\n                        [0, 14.907],\n                        [0, 14.907],\n                        [0, 15.206],\n                        [0, 14.314],\n                        [-1.803, 14.605],\n                        [0, 0]\n                      ],\n                      \"v\": [\n                        [-156.5, -406],\n                        [-166.5, -367],\n                        [-146.5, -327],\n                        [-166.5, -286],\n                        [-146.5, -246],\n                        [-166.5, -206],\n                        [-146.5, -165],\n                        [-166.5, -127],\n                        [-156.5, -84]\n                      ],\n                      \"c\": false\n                    },\n                    \"ix\": 2\n                  },\n                  \"nm\": \"Path 1\",\n                  \"mn\": \"ADBE Vector Shape - Group\",\n                  \"hd\": false\n                },\n                {\n                  \"ty\": \"st\",\n                  \"c\": {\n                    \"a\": 0,\n                    \"k\": [1, 0.2627450980392157, 0.2, 1],\n                    \"ix\": 3\n                  },\n                  \"o\": {\n                    \"a\": 0,\n                    \"k\": 100,\n                    \"ix\": 4\n                  },\n                  \"w\": {\n                    \"a\": 1,\n                    \"k\": [\n                      {\n                        \"i\": {\n                          \"x\": [0.833],\n                          \"y\": [0.833]\n                        },\n                        \"o\": {\n                          \"x\": [0.167],\n                          \"y\": [0.167]\n                        },\n                        \"t\": 0,\n                        \"s\": [4]\n                      },\n                      {\n                        \"t\": 177,\n                        \"s\": [0.5]\n                      }\n                    ],\n                    \"ix\": 5\n                  },\n                  \"lc\": 2,\n                  \"lj\": 2,\n                  \"bm\": 0,\n                  \"nm\": \"Stroke 1\",\n                  \"mn\": \"ADBE Vector Graphic - Stroke\",\n                  \"hd\": false\n                },\n                {\n                  \"ty\": \"tr\",\n                  \"p\": {\n                    \"a\": 0,\n                    \"k\": [0, 0],\n                    \"ix\": 2\n                  },\n                  \"a\": {\n                    \"a\": 0,\n                    \"k\": [0, 0],\n                    \"ix\": 1\n                  },\n                  \"s\": {\n                    \"a\": 0,\n                    \"k\": [100, 100],\n                    \"ix\": 3\n                  },\n                  \"r\": {\n                    \"a\": 0,\n                    \"k\": 0,\n                    \"ix\": 6\n                  },\n                  \"o\": {\n                    \"a\": 0,\n                    \"k\": 100,\n                    \"ix\": 7\n                  },\n                  \"sk\": {\n                    \"a\": 0,\n                    \"k\": 0,\n                    \"ix\": 4\n                  },\n                  \"sa\": {\n                    \"a\": 0,\n                    \"k\": 0,\n                    \"ix\": 5\n                  },\n                  \"nm\": \"Transform\"\n                }\n              ],\n              \"nm\": \"Shape 1\",\n              \"np\": 2,\n              \"cix\": 2,\n              \"bm\": 0,\n              \"ix\": 1,\n              \"mn\": \"ADBE Vector Group\",\n              \"hd\": false\n            },\n            {\n              \"ty\": \"tm\",\n              \"s\": {\n                \"a\": 1,\n                \"k\": [\n                  {\n                    \"i\": {\n                      \"x\": [0.833],\n                      \"y\": [0.833]\n                    },\n                    \"o\": {\n                      \"x\": [0.167],\n                      \"y\": [0.167]\n                    },\n                    \"t\": 5,\n                    \"s\": [0]\n                  },\n                  {\n                    \"t\": 177,\n                    \"s\": [100]\n                  }\n                ],\n                \"ix\": 1\n              },\n              \"e\": {\n                \"a\": 1,\n                \"k\": [\n                  {\n                    \"i\": {\n                      \"x\": [0.833],\n                      \"y\": [0.833]\n                    },\n                    \"o\": {\n                      \"x\": [0.167],\n                      \"y\": [0.167]\n                    },\n                    \"t\": 0,\n                    \"s\": [0]\n                  },\n                  {\n                    \"i\": {\n                      \"x\": [0.833],\n                      \"y\": [0.833]\n                    },\n                    \"o\": {\n                      \"x\": [0.167],\n                      \"y\": [0.167]\n                    },\n                    \"t\": 5,\n                    \"s\": [40]\n                  },\n                  {\n                    \"t\": 177,\n                    \"s\": [100]\n                  }\n                ],\n                \"ix\": 2\n              },\n              \"o\": {\n                \"a\": 0,\n                \"k\": 0,\n                \"ix\": 3\n              },\n              \"m\": 1,\n              \"ix\": 2,\n              \"nm\": \"Trim Paths 1\",\n              \"mn\": \"ADBE Vector Filter - Trim\",\n              \"hd\": false\n            }\n          ],\n          \"ip\": 0,\n          \"op\": 186,\n          \"st\": 0,\n          \"bm\": 0\n        },\n        {\n          \"ddd\": 0,\n          \"ind\": 12,\n          \"ty\": 4,\n          \"nm\": \"streamer b 3\",\n          \"sr\": 1,\n          \"ks\": {\n            \"o\": {\n              \"a\": 0,\n              \"k\": 100,\n              \"ix\": 11\n            },\n            \"r\": {\n              \"a\": 0,\n              \"k\": 9,\n              \"ix\": 10\n            },\n            \"p\": {\n              \"a\": 1,\n              \"k\": [\n                {\n                  \"i\": {\n                    \"x\": 0.833,\n                    \"y\": 0.833\n                  },\n                  \"o\": {\n                    \"x\": 0.167,\n                    \"y\": 0.167\n                  },\n                  \"t\": 11,\n                  \"s\": [199.863, 74.545, 0],\n                  \"to\": [-13.363, 405.455, 0],\n                  \"ti\": [179.333, -430.667, 0]\n                },\n                {\n                  \"t\": 217,\n                  \"s\": [139.863, 834.545, 0]\n                }\n              ],\n              \"ix\": 2\n            },\n            \"a\": {\n              \"a\": 0,\n              \"k\": [-157, -245, 0],\n              \"ix\": 1\n            },\n            \"s\": {\n              \"a\": 0,\n              \"k\": [100, 100, 100],\n              \"ix\": 6\n            }\n          },\n          \"ao\": 0,\n          \"shapes\": [\n            {\n              \"ty\": \"gr\",\n              \"it\": [\n                {\n                  \"ind\": 0,\n                  \"ty\": \"sh\",\n                  \"ix\": 1,\n                  \"ks\": {\n                    \"a\": 0,\n                    \"k\": {\n                      \"i\": [\n                        [0, 0],\n                        [-1.685, -13.314],\n                        [0, -14.907],\n                        [0, -15.206],\n                        [0, -14.907],\n                        [0, -14.907],\n                        [0, -15.206],\n                        [1.754, -14.206],\n                        [-3.934, -9.465]\n                      ],\n                      \"o\": [\n                        [-3.895, 8.562],\n                        [1.872, 14.789],\n                        [0, 15.206],\n                        [0, 14.907],\n                        [0, 14.907],\n                        [0, 15.206],\n                        [0, 14.314],\n                        [-1.803, 14.605],\n                        [0, 0]\n                      ],\n                      \"v\": [\n                        [-156.5, -406],\n                        [-166.5, -367],\n                        [-146.5, -327],\n                        [-166.5, -286],\n                        [-146.5, -246],\n                        [-166.5, -206],\n                        [-146.5, -165],\n                        [-166.5, -127],\n                        [-156.5, -84]\n                      ],\n                      \"c\": false\n                    },\n                    \"ix\": 2\n                  },\n                  \"nm\": \"Path 1\",\n                  \"mn\": \"ADBE Vector Shape - Group\",\n                  \"hd\": false\n                },\n                {\n                  \"ty\": \"st\",\n                  \"c\": {\n                    \"a\": 0,\n                    \"k\": [0.12156862745098039, 0.8431372549019608, 1, 1],\n                    \"ix\": 3\n                  },\n                  \"o\": {\n                    \"a\": 0,\n                    \"k\": 100,\n                    \"ix\": 4\n                  },\n                  \"w\": {\n                    \"a\": 1,\n                    \"k\": [\n                      {\n                        \"i\": {\n                          \"x\": [0.833],\n                          \"y\": [0.833]\n                        },\n                        \"o\": {\n                          \"x\": [0.167],\n                          \"y\": [0.167]\n                        },\n                        \"t\": 11,\n                        \"s\": [4]\n                      },\n                      {\n                        \"t\": 199,\n                        \"s\": [0.5]\n                      }\n                    ],\n                    \"ix\": 5\n                  },\n                  \"lc\": 2,\n                  \"lj\": 2,\n                  \"bm\": 0,\n                  \"nm\": \"Stroke 1\",\n                  \"mn\": \"ADBE Vector Graphic - Stroke\",\n                  \"hd\": false\n                },\n                {\n                  \"ty\": \"tr\",\n                  \"p\": {\n                    \"a\": 0,\n                    \"k\": [0, 0],\n                    \"ix\": 2\n                  },\n                  \"a\": {\n                    \"a\": 0,\n                    \"k\": [0, 0],\n                    \"ix\": 1\n                  },\n                  \"s\": {\n                    \"a\": 0,\n                    \"k\": [100, 100],\n                    \"ix\": 3\n                  },\n                  \"r\": {\n                    \"a\": 0,\n                    \"k\": 0,\n                    \"ix\": 6\n                  },\n                  \"o\": {\n                    \"a\": 0,\n                    \"k\": 100,\n                    \"ix\": 7\n                  },\n                  \"sk\": {\n                    \"a\": 0,\n                    \"k\": 0,\n                    \"ix\": 4\n                  },\n                  \"sa\": {\n                    \"a\": 0,\n                    \"k\": 0,\n                    \"ix\": 5\n                  },\n                  \"nm\": \"Transform\"\n                }\n              ],\n              \"nm\": \"Shape 1\",\n              \"np\": 2,\n              \"cix\": 2,\n              \"bm\": 0,\n              \"ix\": 1,\n              \"mn\": \"ADBE Vector Group\",\n              \"hd\": false\n            },\n            {\n              \"ty\": \"tm\",\n              \"s\": {\n                \"a\": 1,\n                \"k\": [\n                  {\n                    \"i\": {\n                      \"x\": [0.833],\n                      \"y\": [0.833]\n                    },\n                    \"o\": {\n                      \"x\": [0.167],\n                      \"y\": [0.167]\n                    },\n                    \"t\": 16,\n                    \"s\": [0]\n                  },\n                  {\n                    \"t\": 199,\n                    \"s\": [100]\n                  }\n                ],\n                \"ix\": 1\n              },\n              \"e\": {\n                \"a\": 1,\n                \"k\": [\n                  {\n                    \"i\": {\n                      \"x\": [0.833],\n                      \"y\": [0.833]\n                    },\n                    \"o\": {\n                      \"x\": [0.167],\n                      \"y\": [0.167]\n                    },\n                    \"t\": 11,\n                    \"s\": [0]\n                  },\n                  {\n                    \"i\": {\n                      \"x\": [0.833],\n                      \"y\": [0.833]\n                    },\n                    \"o\": {\n                      \"x\": [0.167],\n                      \"y\": [0.167]\n                    },\n                    \"t\": 16,\n                    \"s\": [40]\n                  },\n                  {\n                    \"t\": 199,\n                    \"s\": [100]\n                  }\n                ],\n                \"ix\": 2\n              },\n              \"o\": {\n                \"a\": 0,\n                \"k\": 0,\n                \"ix\": 3\n              },\n              \"m\": 1,\n              \"ix\": 2,\n              \"nm\": \"Trim Paths 1\",\n              \"mn\": \"ADBE Vector Filter - Trim\",\n              \"hd\": false\n            }\n          ],\n          \"ip\": 11,\n          \"op\": 218,\n          \"st\": 11,\n          \"bm\": 0\n        },\n        {\n          \"ddd\": 0,\n          \"ind\": 13,\n          \"ty\": 4,\n          \"nm\": \"circle a 3\",\n          \"sr\": 1,\n          \"ks\": {\n            \"o\": {\n              \"a\": 0,\n              \"k\": 100,\n              \"ix\": 11\n            },\n            \"r\": {\n              \"a\": 1,\n              \"k\": [\n                {\n                  \"i\": {\n                    \"x\": [0.833],\n                    \"y\": [0.833]\n                  },\n                  \"o\": {\n                    \"x\": [0.167],\n                    \"y\": [0.167]\n                  },\n                  \"t\": 2,\n                  \"s\": [0]\n                },\n                {\n                  \"t\": 125,\n                  \"s\": [-1800]\n                }\n              ],\n              \"ix\": 10\n            },\n            \"p\": {\n              \"a\": 1,\n              \"k\": [\n                {\n                  \"i\": {\n                    \"x\": 0.833,\n                    \"y\": 0.833\n                  },\n                  \"o\": {\n                    \"x\": 0.167,\n                    \"y\": 0.167\n                  },\n                  \"t\": 2,\n                  \"s\": [365.643, -26.292, 0],\n                  \"to\": [-101.333, 75.667, 0],\n                  \"ti\": [15.333, -507.667, 0]\n                },\n                {\n                  \"t\": 125,\n                  \"s\": [165.643, 835.708, 0]\n                }\n              ],\n              \"ix\": 2\n            },\n            \"a\": {\n              \"a\": 0,\n              \"k\": [0, 0, 0],\n              \"ix\": 1\n            },\n            \"s\": {\n              \"a\": 1,\n              \"k\": [\n                {\n                  \"i\": {\n                    \"x\": [0.833, 0.833, 0.833],\n                    \"y\": [0.833, 0.833, 0.833]\n                  },\n                  \"o\": {\n                    \"x\": [0.167, 0.167, 0.167],\n                    \"y\": [0.167, 0.167, 0.167]\n                  },\n                  \"t\": 2,\n                  \"s\": [100, 50, 100]\n                },\n                {\n                  \"t\": 125,\n                  \"s\": [50, 100, 100]\n                }\n              ],\n              \"ix\": 6\n            }\n          },\n          \"ao\": 0,\n          \"shapes\": [\n            {\n              \"ty\": \"gr\",\n              \"it\": [\n                {\n                  \"d\": 1,\n                  \"ty\": \"el\",\n                  \"s\": {\n                    \"a\": 0,\n                    \"k\": [16, 16],\n                    \"ix\": 2\n                  },\n                  \"p\": {\n                    \"a\": 0,\n                    \"k\": [0, 0],\n                    \"ix\": 3\n                  },\n                  \"nm\": \"Ellipse Path 1\",\n                  \"mn\": \"ADBE Vector Shape - Ellipse\",\n                  \"hd\": false\n                },\n                {\n                  \"ty\": \"fl\",\n                  \"c\": {\n                    \"a\": 0,\n                    \"k\": [0.12156862745098039, 0.8431372549019608, 1, 1],\n                    \"ix\": 4\n                  },\n                  \"o\": {\n                    \"a\": 0,\n                    \"k\": 100,\n                    \"ix\": 5\n                  },\n                  \"r\": 1,\n                  \"bm\": 0,\n                  \"nm\": \"Fill 1\",\n                  \"mn\": \"ADBE Vector Graphic - Fill\",\n                  \"hd\": false\n                },\n                {\n                  \"ty\": \"tr\",\n                  \"p\": {\n                    \"a\": 0,\n                    \"k\": [0, 0],\n                    \"ix\": 2\n                  },\n                  \"a\": {\n                    \"a\": 0,\n                    \"k\": [0, 0],\n                    \"ix\": 1\n                  },\n                  \"s\": {\n                    \"a\": 0,\n                    \"k\": [100, 100],\n                    \"ix\": 3\n                  },\n                  \"r\": {\n                    \"a\": 0,\n                    \"k\": 0,\n                    \"ix\": 6\n                  },\n                  \"o\": {\n                    \"a\": 0,\n                    \"k\": 100,\n                    \"ix\": 7\n                  },\n                  \"sk\": {\n                    \"a\": 0,\n                    \"k\": 0,\n                    \"ix\": 4\n                  },\n                  \"sa\": {\n                    \"a\": 0,\n                    \"k\": 0,\n                    \"ix\": 5\n                  },\n                  \"nm\": \"Transform\"\n                }\n              ],\n              \"nm\": \"Ellipse 1\",\n              \"np\": 2,\n              \"cix\": 2,\n              \"bm\": 0,\n              \"ix\": 1,\n              \"mn\": \"ADBE Vector Group\",\n              \"hd\": false\n            }\n          ],\n          \"ip\": 2,\n          \"op\": 126,\n          \"st\": -13,\n          \"bm\": 0\n        },\n        {\n          \"ddd\": 0,\n          \"ind\": 14,\n          \"ty\": 4,\n          \"nm\": \"circle b 3\",\n          \"sr\": 1,\n          \"ks\": {\n            \"o\": {\n              \"a\": 0,\n              \"k\": 50,\n              \"ix\": 11\n            },\n            \"r\": {\n              \"a\": 1,\n              \"k\": [\n                {\n                  \"i\": {\n                    \"x\": [0.833],\n                    \"y\": [0.833]\n                  },\n                  \"o\": {\n                    \"x\": [0.167],\n                    \"y\": [0.167]\n                  },\n                  \"t\": 8,\n                  \"s\": [0]\n                },\n                {\n                  \"t\": 245,\n                  \"s\": [-2880]\n                }\n              ],\n              \"ix\": 10\n            },\n            \"p\": {\n              \"a\": 1,\n              \"k\": [\n                {\n                  \"i\": {\n                    \"x\": 0.833,\n                    \"y\": 0.833\n                  },\n                  \"o\": {\n                    \"x\": 0.167,\n                    \"y\": 0.167\n                  },\n                  \"t\": 8,\n                  \"s\": [519.5, -26.292, 0],\n                  \"to\": [-138, 77.667, 0],\n                  \"ti\": [-2, -497.667, 0]\n                },\n                {\n                  \"t\": 245,\n                  \"s\": [159.5, 835.708, 0]\n                }\n              ],\n              \"ix\": 2\n            },\n            \"a\": {\n              \"a\": 0,\n              \"k\": [0, 0, 0],\n              \"ix\": 1\n            },\n            \"s\": {\n              \"a\": 1,\n              \"k\": [\n                {\n                  \"i\": {\n                    \"x\": [0.833, 0.833, 0.833],\n                    \"y\": [0.833, 0.833, 0.833]\n                  },\n                  \"o\": {\n                    \"x\": [0.167, 0.167, 0.167],\n                    \"y\": [0.167, 0.167, 0.167]\n                  },\n                  \"t\": 8,\n                  \"s\": [100, 50, 100]\n                },\n                {\n                  \"t\": 245,\n                  \"s\": [50, 100, 100]\n                }\n              ],\n              \"ix\": 6\n            }\n          },\n          \"ao\": 0,\n          \"shapes\": [\n            {\n              \"ty\": \"gr\",\n              \"it\": [\n                {\n                  \"d\": 1,\n                  \"ty\": \"el\",\n                  \"s\": {\n                    \"a\": 0,\n                    \"k\": [16, 16],\n                    \"ix\": 2\n                  },\n                  \"p\": {\n                    \"a\": 0,\n                    \"k\": [0, 0],\n                    \"ix\": 3\n                  },\n                  \"nm\": \"Ellipse Path 1\",\n                  \"mn\": \"ADBE Vector Shape - Ellipse\",\n                  \"hd\": false\n                },\n                {\n                  \"ty\": \"fl\",\n                  \"c\": {\n                    \"a\": 0,\n                    \"k\": [0, 0.5215686274509804, 0.27058823529411763, 1],\n                    \"ix\": 4\n                  },\n                  \"o\": {\n                    \"a\": 0,\n                    \"k\": 100,\n                    \"ix\": 5\n                  },\n                  \"r\": 1,\n                  \"bm\": 0,\n                  \"nm\": \"Fill 1\",\n                  \"mn\": \"ADBE Vector Graphic - Fill\",\n                  \"hd\": false\n                },\n                {\n                  \"ty\": \"tr\",\n                  \"p\": {\n                    \"a\": 0,\n                    \"k\": [0, 0],\n                    \"ix\": 2\n                  },\n                  \"a\": {\n                    \"a\": 0,\n                    \"k\": [0, 0],\n                    \"ix\": 1\n                  },\n                  \"s\": {\n                    \"a\": 0,\n                    \"k\": [100, 100],\n                    \"ix\": 3\n                  },\n                  \"r\": {\n                    \"a\": 0,\n                    \"k\": 0,\n                    \"ix\": 6\n                  },\n                  \"o\": {\n                    \"a\": 0,\n                    \"k\": 100,\n                    \"ix\": 7\n                  },\n                  \"sk\": {\n                    \"a\": 0,\n                    \"k\": 0,\n                    \"ix\": 4\n                  },\n                  \"sa\": {\n                    \"a\": 0,\n                    \"k\": 0,\n                    \"ix\": 5\n                  },\n                  \"nm\": \"Transform\"\n                }\n              ],\n              \"nm\": \"Ellipse 1\",\n              \"np\": 2,\n              \"cix\": 2,\n              \"bm\": 0,\n              \"ix\": 1,\n              \"mn\": \"ADBE Vector Group\",\n              \"hd\": false\n            }\n          ],\n          \"ip\": 8,\n          \"op\": 246,\n          \"st\": -7,\n          \"bm\": 0\n        },\n        {\n          \"ddd\": 0,\n          \"ind\": 15,\n          \"ty\": 4,\n          \"nm\": \"star a 3\",\n          \"sr\": 1,\n          \"ks\": {\n            \"o\": {\n              \"a\": 0,\n              \"k\": 100,\n              \"ix\": 11\n            },\n            \"r\": {\n              \"a\": 1,\n              \"k\": [\n                {\n                  \"i\": {\n                    \"x\": [0.833],\n                    \"y\": [0.833]\n                  },\n                  \"o\": {\n                    \"x\": [0.167],\n                    \"y\": [0.167]\n                  },\n                  \"t\": 6,\n                  \"s\": [0]\n                },\n                {\n                  \"t\": 245,\n                  \"s\": [-2880]\n                }\n              ],\n              \"ix\": 10\n            },\n            \"p\": {\n              \"a\": 1,\n              \"k\": [\n                {\n                  \"i\": {\n                    \"x\": 0.833,\n                    \"y\": 0.833\n                  },\n                  \"o\": {\n                    \"x\": 0.167,\n                    \"y\": 0.167\n                  },\n                  \"t\": 6,\n                  \"s\": [416.929, -28, 0],\n                  \"to\": [-213.333, 157.667, 0],\n                  \"ti\": [173.333, -127.667, 0]\n                },\n                {\n                  \"t\": 245,\n                  \"s\": [156.929, 834, 0]\n                }\n              ],\n              \"ix\": 2\n            },\n            \"a\": {\n              \"a\": 0,\n              \"k\": [0, 0, 0],\n              \"ix\": 1\n            },\n            \"s\": {\n              \"a\": 1,\n              \"k\": [\n                {\n                  \"i\": {\n                    \"x\": [0.833, 0.833, 0.833],\n                    \"y\": [0.833, 0.833, 0.833]\n                  },\n                  \"o\": {\n                    \"x\": [0.167, 0.167, 0.167],\n                    \"y\": [0.167, 0.167, 0.167]\n                  },\n                  \"t\": 6,\n                  \"s\": [100, 50, 100]\n                },\n                {\n                  \"t\": 245,\n                  \"s\": [50, 100, 100]\n                }\n              ],\n              \"ix\": 6\n            }\n          },\n          \"ao\": 0,\n          \"shapes\": [\n            {\n              \"ty\": \"gr\",\n              \"it\": [\n                {\n                  \"ty\": \"sr\",\n                  \"sy\": 1,\n                  \"d\": 1,\n                  \"pt\": {\n                    \"a\": 0,\n                    \"k\": 5,\n                    \"ix\": 3\n                  },\n                  \"p\": {\n                    \"a\": 0,\n                    \"k\": [0, 0],\n                    \"ix\": 4\n                  },\n                  \"r\": {\n                    \"a\": 0,\n                    \"k\": 0,\n                    \"ix\": 5\n                  },\n                  \"ir\": {\n                    \"a\": 0,\n                    \"k\": 5,\n                    \"ix\": 6\n                  },\n                  \"is\": {\n                    \"a\": 0,\n                    \"k\": 0,\n                    \"ix\": 8\n                  },\n                  \"or\": {\n                    \"a\": 0,\n                    \"k\": 12,\n                    \"ix\": 7\n                  },\n                  \"os\": {\n                    \"a\": 0,\n                    \"k\": 0,\n                    \"ix\": 9\n                  },\n                  \"ix\": 1,\n                  \"nm\": \"Polystar Path 1\",\n                  \"mn\": \"ADBE Vector Shape - Star\",\n                  \"hd\": false\n                },\n                {\n                  \"ty\": \"fl\",\n                  \"c\": {\n                    \"a\": 0,\n                    \"k\": [1, 0.2627450980392157, 0.2, 1],\n                    \"ix\": 4\n                  },\n                  \"o\": {\n                    \"a\": 0,\n                    \"k\": 100,\n                    \"ix\": 5\n                  },\n                  \"r\": 1,\n                  \"bm\": 0,\n                  \"nm\": \"Fill 1\",\n                  \"mn\": \"ADBE Vector Graphic - Fill\",\n                  \"hd\": false\n                },\n                {\n                  \"ty\": \"tr\",\n                  \"p\": {\n                    \"a\": 0,\n                    \"k\": [0, 0],\n                    \"ix\": 2\n                  },\n                  \"a\": {\n                    \"a\": 0,\n                    \"k\": [0, 0],\n                    \"ix\": 1\n                  },\n                  \"s\": {\n                    \"a\": 0,\n                    \"k\": [100, 100],\n                    \"ix\": 3\n                  },\n                  \"r\": {\n                    \"a\": 0,\n                    \"k\": 0,\n                    \"ix\": 6\n                  },\n                  \"o\": {\n                    \"a\": 0,\n                    \"k\": 100,\n                    \"ix\": 7\n                  },\n                  \"sk\": {\n                    \"a\": 0,\n                    \"k\": 0,\n                    \"ix\": 4\n                  },\n                  \"sa\": {\n                    \"a\": 0,\n                    \"k\": 0,\n                    \"ix\": 5\n                  },\n                  \"nm\": \"Transform\"\n                }\n              ],\n              \"nm\": \"Polystar 1\",\n              \"np\": 2,\n              \"cix\": 2,\n              \"bm\": 0,\n              \"ix\": 1,\n              \"mn\": \"ADBE Vector Group\",\n              \"hd\": false\n            }\n          ],\n          \"ip\": 6,\n          \"op\": 246,\n          \"st\": -9,\n          \"bm\": 0\n        },\n        {\n          \"ddd\": 0,\n          \"ind\": 16,\n          \"ty\": 4,\n          \"nm\": \"star b 3\",\n          \"sr\": 1,\n          \"ks\": {\n            \"o\": {\n              \"a\": 0,\n              \"k\": 50,\n              \"ix\": 11\n            },\n            \"r\": {\n              \"a\": 1,\n              \"k\": [\n                {\n                  \"i\": {\n                    \"x\": [0.833],\n                    \"y\": [0.833]\n                  },\n                  \"o\": {\n                    \"x\": [0.167],\n                    \"y\": [0.167]\n                  },\n                  \"t\": 8,\n                  \"s\": [0]\n                },\n                {\n                  \"t\": 155,\n                  \"s\": [-2160]\n                }\n              ],\n              \"ix\": 10\n            },\n            \"p\": {\n              \"a\": 1,\n              \"k\": [\n                {\n                  \"i\": {\n                    \"x\": 0.833,\n                    \"y\": 0.833\n                  },\n                  \"o\": {\n                    \"x\": 0.167,\n                    \"y\": 0.167\n                  },\n                  \"t\": 8,\n                  \"s\": [211.786, -28, 0],\n                  \"to\": [0, 0, 0],\n                  \"ti\": [-161.333, -275.667, 0]\n                },\n                {\n                  \"t\": 155,\n                  \"s\": [291.786, 834, 0]\n                }\n              ],\n              \"ix\": 2\n            },\n            \"a\": {\n              \"a\": 0,\n              \"k\": [0, 0, 0],\n              \"ix\": 1\n            },\n            \"s\": {\n              \"a\": 1,\n              \"k\": [\n                {\n                  \"i\": {\n                    \"x\": [0.833, 0.833, 0.833],\n                    \"y\": [0.833, 0.833, 0.833]\n                  },\n                  \"o\": {\n                    \"x\": [0.167, 0.167, 0.167],\n                    \"y\": [0.167, 0.167, 0.167]\n                  },\n                  \"t\": 8,\n                  \"s\": [100, 50, 100]\n                },\n                {\n                  \"t\": 155,\n                  \"s\": [50, 100, 100]\n                }\n              ],\n              \"ix\": 6\n            }\n          },\n          \"ao\": 0,\n          \"shapes\": [\n            {\n              \"ty\": \"gr\",\n              \"it\": [\n                {\n                  \"ty\": \"sr\",\n                  \"sy\": 1,\n                  \"d\": 1,\n                  \"pt\": {\n                    \"a\": 0,\n                    \"k\": 5,\n                    \"ix\": 3\n                  },\n                  \"p\": {\n                    \"a\": 0,\n                    \"k\": [0, 0],\n                    \"ix\": 4\n                  },\n                  \"r\": {\n                    \"a\": 0,\n                    \"k\": 0,\n                    \"ix\": 5\n                  },\n                  \"ir\": {\n                    \"a\": 0,\n                    \"k\": 5,\n                    \"ix\": 6\n                  },\n                  \"is\": {\n                    \"a\": 0,\n                    \"k\": 0,\n                    \"ix\": 8\n                  },\n                  \"or\": {\n                    \"a\": 0,\n                    \"k\": 12,\n                    \"ix\": 7\n                  },\n                  \"os\": {\n                    \"a\": 0,\n                    \"k\": 0,\n                    \"ix\": 9\n                  },\n                  \"ix\": 1,\n                  \"nm\": \"Polystar Path 1\",\n                  \"mn\": \"ADBE Vector Shape - Star\",\n                  \"hd\": false\n                },\n                {\n                  \"ty\": \"fl\",\n                  \"c\": {\n                    \"a\": 0,\n                    \"k\": [1, 0.12156862745098039, 0.5647058823529412, 1],\n                    \"ix\": 4\n                  },\n                  \"o\": {\n                    \"a\": 0,\n                    \"k\": 100,\n                    \"ix\": 5\n                  },\n                  \"r\": 1,\n                  \"bm\": 0,\n                  \"nm\": \"Fill 1\",\n                  \"mn\": \"ADBE Vector Graphic - Fill\",\n                  \"hd\": false\n                },\n                {\n                  \"ty\": \"tr\",\n                  \"p\": {\n                    \"a\": 0,\n                    \"k\": [0, 0],\n                    \"ix\": 2\n                  },\n                  \"a\": {\n                    \"a\": 0,\n                    \"k\": [0, 0],\n                    \"ix\": 1\n                  },\n                  \"s\": {\n                    \"a\": 0,\n                    \"k\": [100, 100],\n                    \"ix\": 3\n                  },\n                  \"r\": {\n                    \"a\": 0,\n                    \"k\": 0,\n                    \"ix\": 6\n                  },\n                  \"o\": {\n                    \"a\": 0,\n                    \"k\": 100,\n                    \"ix\": 7\n                  },\n                  \"sk\": {\n                    \"a\": 0,\n                    \"k\": 0,\n                    \"ix\": 4\n                  },\n                  \"sa\": {\n                    \"a\": 0,\n                    \"k\": 0,\n                    \"ix\": 5\n                  },\n                  \"nm\": \"Transform\"\n                }\n              ],\n              \"nm\": \"Polystar 1\",\n              \"np\": 2,\n              \"cix\": 2,\n              \"bm\": 0,\n              \"ix\": 1,\n              \"mn\": \"ADBE Vector Group\",\n              \"hd\": false\n            }\n          ],\n          \"ip\": 8,\n          \"op\": 156,\n          \"st\": -7,\n          \"bm\": 0\n        },\n        {\n          \"ddd\": 0,\n          \"ind\": 17,\n          \"ty\": 4,\n          \"nm\": \"rec a 3\",\n          \"sr\": 1,\n          \"ks\": {\n            \"o\": {\n              \"a\": 0,\n              \"k\": 100,\n              \"ix\": 11\n            },\n            \"r\": {\n              \"a\": 1,\n              \"k\": [\n                {\n                  \"i\": {\n                    \"x\": [0.833],\n                    \"y\": [0.833]\n                  },\n                  \"o\": {\n                    \"x\": [0.167],\n                    \"y\": [0.167]\n                  },\n                  \"t\": 4,\n                  \"s\": [0]\n                },\n                {\n                  \"t\": 185,\n                  \"s\": [-2160]\n                }\n              ],\n              \"ix\": 10\n            },\n            \"p\": {\n              \"a\": 1,\n              \"k\": [\n                {\n                  \"i\": {\n                    \"x\": 0.833,\n                    \"y\": 0.833\n                  },\n                  \"o\": {\n                    \"x\": 0.167,\n                    \"y\": 0.167\n                  },\n                  \"t\": 4,\n                  \"s\": [468.214, -22.292, 0],\n                  \"to\": [-167.333, 119.667, 0],\n                  \"ti\": [-130.667, -315.667, 0]\n                },\n                {\n                  \"t\": 185,\n                  \"s\": [268.214, 839.708, 0]\n                }\n              ],\n              \"ix\": 2\n            },\n            \"a\": {\n              \"a\": 0,\n              \"k\": [0, 0, 0],\n              \"ix\": 1\n            },\n            \"s\": {\n              \"a\": 1,\n              \"k\": [\n                {\n                  \"i\": {\n                    \"x\": [0.833, 0.833, 0.833],\n                    \"y\": [0.833, 0.833, 0.833]\n                  },\n                  \"o\": {\n                    \"x\": [0.167, 0.167, 0.167],\n                    \"y\": [0.167, 0.167, 0.167]\n                  },\n                  \"t\": 4,\n                  \"s\": [100, 50, 100]\n                },\n                {\n                  \"t\": 185,\n                  \"s\": [50, 100, 100]\n                }\n              ],\n              \"ix\": 6\n            }\n          },\n          \"ao\": 0,\n          \"shapes\": [\n            {\n              \"ty\": \"gr\",\n              \"it\": [\n                {\n                  \"ty\": \"rc\",\n                  \"d\": 1,\n                  \"s\": {\n                    \"a\": 0,\n                    \"k\": [16, 8],\n                    \"ix\": 2\n                  },\n                  \"p\": {\n                    \"a\": 0,\n                    \"k\": [0, 0],\n                    \"ix\": 3\n                  },\n                  \"r\": {\n                    \"a\": 0,\n                    \"k\": 0,\n                    \"ix\": 4\n                  },\n                  \"nm\": \"Rectangle Path 1\",\n                  \"mn\": \"ADBE Vector Shape - Rect\",\n                  \"hd\": false\n                },\n                {\n                  \"ty\": \"fl\",\n                  \"c\": {\n                    \"a\": 0,\n                    \"k\": [1, 0.2627450980392157, 0.2, 1],\n                    \"ix\": 4\n                  },\n                  \"o\": {\n                    \"a\": 0,\n                    \"k\": 100,\n                    \"ix\": 5\n                  },\n                  \"r\": 1,\n                  \"bm\": 0,\n                  \"nm\": \"Fill 1\",\n                  \"mn\": \"ADBE Vector Graphic - Fill\",\n                  \"hd\": false\n                },\n                {\n                  \"ty\": \"tr\",\n                  \"p\": {\n                    \"a\": 0,\n                    \"k\": [0, 0],\n                    \"ix\": 2\n                  },\n                  \"a\": {\n                    \"a\": 0,\n                    \"k\": [0, 0],\n                    \"ix\": 1\n                  },\n                  \"s\": {\n                    \"a\": 0,\n                    \"k\": [100, 100],\n                    \"ix\": 3\n                  },\n                  \"r\": {\n                    \"a\": 0,\n                    \"k\": 0,\n                    \"ix\": 6\n                  },\n                  \"o\": {\n                    \"a\": 0,\n                    \"k\": 100,\n                    \"ix\": 7\n                  },\n                  \"sk\": {\n                    \"a\": 0,\n                    \"k\": 0,\n                    \"ix\": 4\n                  },\n                  \"sa\": {\n                    \"a\": 0,\n                    \"k\": 0,\n                    \"ix\": 5\n                  },\n                  \"nm\": \"Transform\"\n                }\n              ],\n              \"nm\": \"Rectangle 1\",\n              \"np\": 2,\n              \"cix\": 2,\n              \"bm\": 0,\n              \"ix\": 1,\n              \"mn\": \"ADBE Vector Group\",\n              \"hd\": false\n            }\n          ],\n          \"ip\": 4,\n          \"op\": 186,\n          \"st\": -11,\n          \"bm\": 0\n        },\n        {\n          \"ddd\": 0,\n          \"ind\": 18,\n          \"ty\": 4,\n          \"nm\": \"rec b 3\",\n          \"sr\": 1,\n          \"ks\": {\n            \"o\": {\n              \"a\": 0,\n              \"k\": 50,\n              \"ix\": 11\n            },\n            \"r\": {\n              \"a\": 1,\n              \"k\": [\n                {\n                  \"i\": {\n                    \"x\": [0.833],\n                    \"y\": [0.833]\n                  },\n                  \"o\": {\n                    \"x\": [0.167],\n                    \"y\": [0.167]\n                  },\n                  \"t\": 6,\n                  \"s\": [0]\n                },\n                {\n                  \"t\": 245,\n                  \"s\": [-2880]\n                }\n              ],\n              \"ix\": 10\n            },\n            \"p\": {\n              \"a\": 1,\n              \"k\": [\n                {\n                  \"i\": {\n                    \"x\": 0.833,\n                    \"y\": 0.833\n                  },\n                  \"o\": {\n                    \"x\": 0.167,\n                    \"y\": 0.167\n                  },\n                  \"t\": 6,\n                  \"s\": [263.071, -22.292, 0],\n                  \"to\": [0, 143.667, 0],\n                  \"ti\": [-114.571, -267.708, 0]\n                },\n                {\n                  \"t\": 245,\n                  \"s\": [263.071, 839.708, 0]\n                }\n              ],\n              \"ix\": 2\n            },\n            \"a\": {\n              \"a\": 0,\n              \"k\": [0, 0, 0],\n              \"ix\": 1\n            },\n            \"s\": {\n              \"a\": 1,\n              \"k\": [\n                {\n                  \"i\": {\n                    \"x\": [0.833, 0.833, 0.833],\n                    \"y\": [0.833, 0.833, 0.833]\n                  },\n                  \"o\": {\n                    \"x\": [0.167, 0.167, 0.167],\n                    \"y\": [0.167, 0.167, 0.167]\n                  },\n                  \"t\": 6,\n                  \"s\": [100, 50, 100]\n                },\n                {\n                  \"t\": 245,\n                  \"s\": [50, 100, 100]\n                }\n              ],\n              \"ix\": 6\n            }\n          },\n          \"ao\": 0,\n          \"shapes\": [\n            {\n              \"ty\": \"gr\",\n              \"it\": [\n                {\n                  \"ty\": \"rc\",\n                  \"d\": 1,\n                  \"s\": {\n                    \"a\": 0,\n                    \"k\": [16, 8],\n                    \"ix\": 2\n                  },\n                  \"p\": {\n                    \"a\": 0,\n                    \"k\": [0, 0],\n                    \"ix\": 3\n                  },\n                  \"r\": {\n                    \"a\": 0,\n                    \"k\": 0,\n                    \"ix\": 4\n                  },\n                  \"nm\": \"Rectangle Path 1\",\n                  \"mn\": \"ADBE Vector Shape - Rect\",\n                  \"hd\": false\n                },\n                {\n                  \"ty\": \"fl\",\n                  \"c\": {\n                    \"a\": 0,\n                    \"k\": [0.12156862745098039, 0.8431372549019608, 1, 1],\n                    \"ix\": 4\n                  },\n                  \"o\": {\n                    \"a\": 0,\n                    \"k\": 100,\n                    \"ix\": 5\n                  },\n                  \"r\": 1,\n                  \"bm\": 0,\n                  \"nm\": \"Fill 1\",\n                  \"mn\": \"ADBE Vector Graphic - Fill\",\n                  \"hd\": false\n                },\n                {\n                  \"ty\": \"tr\",\n                  \"p\": {\n                    \"a\": 0,\n                    \"k\": [0, 0],\n                    \"ix\": 2\n                  },\n                  \"a\": {\n                    \"a\": 0,\n                    \"k\": [0, 0],\n                    \"ix\": 1\n                  },\n                  \"s\": {\n                    \"a\": 0,\n                    \"k\": [100, 100],\n                    \"ix\": 3\n                  },\n                  \"r\": {\n                    \"a\": 0,\n                    \"k\": 0,\n                    \"ix\": 6\n                  },\n                  \"o\": {\n                    \"a\": 0,\n                    \"k\": 100,\n                    \"ix\": 7\n                  },\n                  \"sk\": {\n                    \"a\": 0,\n                    \"k\": 0,\n                    \"ix\": 4\n                  },\n                  \"sa\": {\n                    \"a\": 0,\n                    \"k\": 0,\n                    \"ix\": 5\n                  },\n                  \"nm\": \"Transform\"\n                }\n              ],\n              \"nm\": \"Rectangle 1\",\n              \"np\": 2,\n              \"cix\": 2,\n              \"bm\": 0,\n              \"ix\": 1,\n              \"mn\": \"ADBE Vector Group\",\n              \"hd\": false\n            }\n          ],\n          \"ip\": 6,\n          \"op\": 246,\n          \"st\": -9,\n          \"bm\": 0\n        },\n        {\n          \"ddd\": 0,\n          \"ind\": 19,\n          \"ty\": 4,\n          \"nm\": \"square a 3\",\n          \"sr\": 1,\n          \"ks\": {\n            \"o\": {\n              \"a\": 0,\n              \"k\": 100,\n              \"ix\": 11\n            },\n            \"r\": {\n              \"a\": 1,\n              \"k\": [\n                {\n                  \"i\": {\n                    \"x\": [0.833],\n                    \"y\": [0.833]\n                  },\n                  \"o\": {\n                    \"x\": [0.167],\n                    \"y\": [0.167]\n                  },\n                  \"t\": 2,\n                  \"s\": [0]\n                },\n                {\n                  \"t\": 217,\n                  \"s\": [-2520]\n                }\n              ],\n              \"ix\": 10\n            },\n            \"p\": {\n              \"a\": 1,\n              \"k\": [\n                {\n                  \"i\": {\n                    \"x\": 0.833,\n                    \"y\": 0.833\n                  },\n                  \"o\": {\n                    \"x\": 0.167,\n                    \"y\": 0.167\n                  },\n                  \"t\": 2,\n                  \"s\": [160.5, -26.292, 0],\n                  \"to\": [13, 430.305, 0],\n                  \"ti\": [52.221, -418.892, 0]\n                },\n                {\n                  \"t\": 217,\n                  \"s\": [238.5, 833.708, 0]\n                }\n              ],\n              \"ix\": 2\n            },\n            \"a\": {\n              \"a\": 0,\n              \"k\": [0, 0, 0],\n              \"ix\": 1\n            },\n            \"s\": {\n              \"a\": 1,\n              \"k\": [\n                {\n                  \"i\": {\n                    \"x\": [0.833, 0.833, 0.833],\n                    \"y\": [0.833, 0.833, 0.833]\n                  },\n                  \"o\": {\n                    \"x\": [0.167, 0.167, 0.167],\n                    \"y\": [0.167, 0.167, 0.167]\n                  },\n                  \"t\": 2,\n                  \"s\": [100, 50, 100]\n                },\n                {\n                  \"t\": 217,\n                  \"s\": [50, 100, 100]\n                }\n              ],\n              \"ix\": 6\n            }\n          },\n          \"ao\": 0,\n          \"shapes\": [\n            {\n              \"ty\": \"gr\",\n              \"it\": [\n                {\n                  \"ty\": \"rc\",\n                  \"d\": 1,\n                  \"s\": {\n                    \"a\": 0,\n                    \"k\": [16, 16],\n                    \"ix\": 2\n                  },\n                  \"p\": {\n                    \"a\": 0,\n                    \"k\": [0, 0],\n                    \"ix\": 3\n                  },\n                  \"r\": {\n                    \"a\": 0,\n                    \"k\": 0,\n                    \"ix\": 4\n                  },\n                  \"nm\": \"Rectangle Path 1\",\n                  \"mn\": \"ADBE Vector Shape - Rect\",\n                  \"hd\": false\n                },\n                {\n                  \"ty\": \"fl\",\n                  \"c\": {\n                    \"a\": 0,\n                    \"k\": [0.12156862745098039, 0.8431372549019608, 1, 1],\n                    \"ix\": 4\n                  },\n                  \"o\": {\n                    \"a\": 0,\n                    \"k\": 100,\n                    \"ix\": 5\n                  },\n                  \"r\": 1,\n                  \"bm\": 0,\n                  \"nm\": \"Fill 1\",\n                  \"mn\": \"ADBE Vector Graphic - Fill\",\n                  \"hd\": false\n                },\n                {\n                  \"ty\": \"tr\",\n                  \"p\": {\n                    \"a\": 0,\n                    \"k\": [0, 0],\n                    \"ix\": 2\n                  },\n                  \"a\": {\n                    \"a\": 0,\n                    \"k\": [0, 0],\n                    \"ix\": 1\n                  },\n                  \"s\": {\n                    \"a\": 0,\n                    \"k\": [100, 100],\n                    \"ix\": 3\n                  },\n                  \"r\": {\n                    \"a\": 0,\n                    \"k\": 0,\n                    \"ix\": 6\n                  },\n                  \"o\": {\n                    \"a\": 0,\n                    \"k\": 100,\n                    \"ix\": 7\n                  },\n                  \"sk\": {\n                    \"a\": 0,\n                    \"k\": 0,\n                    \"ix\": 4\n                  },\n                  \"sa\": {\n                    \"a\": 0,\n                    \"k\": 0,\n                    \"ix\": 5\n                  },\n                  \"nm\": \"Transform\"\n                }\n              ],\n              \"nm\": \"Rectangle 1\",\n              \"np\": 2,\n              \"cix\": 2,\n              \"bm\": 0,\n              \"ix\": 1,\n              \"mn\": \"ADBE Vector Group\",\n              \"hd\": false\n            }\n          ],\n          \"ip\": 2,\n          \"op\": 218,\n          \"st\": -13,\n          \"bm\": 0\n        },\n        {\n          \"ddd\": 0,\n          \"ind\": 20,\n          \"ty\": 4,\n          \"nm\": \"square b 3\",\n          \"sr\": 1,\n          \"ks\": {\n            \"o\": {\n              \"a\": 0,\n              \"k\": 50,\n              \"ix\": 11\n            },\n            \"r\": {\n              \"a\": 1,\n              \"k\": [\n                {\n                  \"i\": {\n                    \"x\": [0.833],\n                    \"y\": [0.833]\n                  },\n                  \"o\": {\n                    \"x\": [0.167],\n                    \"y\": [0.167]\n                  },\n                  \"t\": 4,\n                  \"s\": [0]\n                },\n                {\n                  \"t\": 185,\n                  \"s\": [-2160]\n                }\n              ],\n              \"ix\": 10\n            },\n            \"p\": {\n              \"a\": 1,\n              \"k\": [\n                {\n                  \"i\": {\n                    \"x\": 0.833,\n                    \"y\": 0.833\n                  },\n                  \"o\": {\n                    \"x\": 0.167,\n                    \"y\": 0.167\n                  },\n                  \"t\": 4,\n                  \"s\": [314.357, -26.292, 0],\n                  \"to\": [157.333, 415.667, 0],\n                  \"ti\": [22.667, -253.667, 0]\n                },\n                {\n                  \"t\": 185,\n                  \"s\": [154.357, 835.708, 0]\n                }\n              ],\n              \"ix\": 2\n            },\n            \"a\": {\n              \"a\": 0,\n              \"k\": [0, 0, 0],\n              \"ix\": 1\n            },\n            \"s\": {\n              \"a\": 1,\n              \"k\": [\n                {\n                  \"i\": {\n                    \"x\": [0.833, 0.833, 0.833],\n                    \"y\": [0.833, 0.833, 0.833]\n                  },\n                  \"o\": {\n                    \"x\": [0.167, 0.167, 0.167],\n                    \"y\": [0.167, 0.167, 0.167]\n                  },\n                  \"t\": 4,\n                  \"s\": [100, 50, 100]\n                },\n                {\n                  \"t\": 185,\n                  \"s\": [50, 100, 100]\n                }\n              ],\n              \"ix\": 6\n            }\n          },\n          \"ao\": 0,\n          \"shapes\": [\n            {\n              \"ty\": \"gr\",\n              \"it\": [\n                {\n                  \"ty\": \"rc\",\n                  \"d\": 1,\n                  \"s\": {\n                    \"a\": 0,\n                    \"k\": [16, 16],\n                    \"ix\": 2\n                  },\n                  \"p\": {\n                    \"a\": 0,\n                    \"k\": [0, 0],\n                    \"ix\": 3\n                  },\n                  \"r\": {\n                    \"a\": 0,\n                    \"k\": 0,\n                    \"ix\": 4\n                  },\n                  \"nm\": \"Rectangle Path 1\",\n                  \"mn\": \"ADBE Vector Shape - Rect\",\n                  \"hd\": false\n                },\n                {\n                  \"ty\": \"fl\",\n                  \"c\": {\n                    \"a\": 0,\n                    \"k\": [1, 0.12156862745098039, 0.5647058823529412, 1],\n                    \"ix\": 4\n                  },\n                  \"o\": {\n                    \"a\": 0,\n                    \"k\": 100,\n                    \"ix\": 5\n                  },\n                  \"r\": 1,\n                  \"bm\": 0,\n                  \"nm\": \"Fill 1\",\n                  \"mn\": \"ADBE Vector Graphic - Fill\",\n                  \"hd\": false\n                },\n                {\n                  \"ty\": \"tr\",\n                  \"p\": {\n                    \"a\": 0,\n                    \"k\": [0, 0],\n                    \"ix\": 2\n                  },\n                  \"a\": {\n                    \"a\": 0,\n                    \"k\": [0, 0],\n                    \"ix\": 1\n                  },\n                  \"s\": {\n                    \"a\": 0,\n                    \"k\": [100, 100],\n                    \"ix\": 3\n                  },\n                  \"r\": {\n                    \"a\": 0,\n                    \"k\": 0,\n                    \"ix\": 6\n                  },\n                  \"o\": {\n                    \"a\": 0,\n                    \"k\": 100,\n                    \"ix\": 7\n                  },\n                  \"sk\": {\n                    \"a\": 0,\n                    \"k\": 0,\n                    \"ix\": 4\n                  },\n                  \"sa\": {\n                    \"a\": 0,\n                    \"k\": 0,\n                    \"ix\": 5\n                  },\n                  \"nm\": \"Transform\"\n                }\n              ],\n              \"nm\": \"Rectangle 1\",\n              \"np\": 2,\n              \"cix\": 2,\n              \"bm\": 0,\n              \"ix\": 1,\n              \"mn\": \"ADBE Vector Group\",\n              \"hd\": false\n            }\n          ],\n          \"ip\": 4,\n          \"op\": 186,\n          \"st\": -11,\n          \"bm\": 0\n        }\n      ]\n    }\n  ],\n  \"layers\": [\n    {\n      \"ddd\": 0,\n      \"ind\": 1,\n      \"ty\": 0,\n      \"nm\": \"cannon (small - left)\",\n      \"refId\": \"comp_0\",\n      \"sr\": 1,\n      \"ks\": {\n        \"o\": {\n          \"a\": 0,\n          \"k\": 100,\n          \"ix\": 11\n        },\n        \"r\": {\n          \"a\": 0,\n          \"k\": 0,\n          \"ix\": 10\n        },\n        \"p\": {\n          \"a\": 0,\n          \"k\": [76, 451.99999999999994, 0],\n          \"ix\": 2\n        },\n        \"a\": {\n          \"a\": 0,\n          \"k\": [0, 360, 0],\n          \"ix\": 1\n        },\n        \"s\": {\n          \"a\": 0,\n          \"k\": [100, 100, 100],\n          \"ix\": 6\n        }\n      },\n      \"ao\": 0,\n      \"w\": 480,\n      \"h\": 720,\n      \"ip\": 0,\n      \"op\": 300,\n      \"st\": 0,\n      \"bm\": 0\n    },\n    {\n      \"ddd\": 0,\n      \"ind\": 2,\n      \"ty\": 0,\n      \"nm\": \"cannon (small - right)\",\n      \"refId\": \"comp_2\",\n      \"sr\": 1,\n      \"ks\": {\n        \"o\": {\n          \"a\": 0,\n          \"k\": 100,\n          \"ix\": 11\n        },\n        \"r\": {\n          \"a\": 0,\n          \"k\": 0,\n          \"ix\": 10\n        },\n        \"p\": {\n          \"a\": 0,\n          \"k\": [533, 451.99999999999994, 0],\n          \"ix\": 2\n        },\n        \"a\": {\n          \"a\": 0,\n          \"k\": [479.994, 360, 0],\n          \"ix\": 1\n        },\n        \"s\": {\n          \"a\": 0,\n          \"k\": [100, 100, 100],\n          \"ix\": 6\n        }\n      },\n      \"ao\": 0,\n      \"w\": 480,\n      \"h\": 720,\n      \"ip\": 0,\n      \"op\": 300,\n      \"st\": 0,\n      \"bm\": 0\n    },\n    {\n      \"ddd\": 0,\n      \"ind\": 3,\n      \"ty\": 0,\n      \"nm\": \"cannon (small - top)\",\n      \"refId\": \"comp_3\",\n      \"sr\": 1,\n      \"ks\": {\n        \"o\": {\n          \"a\": 0,\n          \"k\": 100,\n          \"ix\": 11\n        },\n        \"r\": {\n          \"a\": 0,\n          \"k\": 0,\n          \"ix\": 10\n        },\n        \"p\": {\n          \"a\": 0,\n          \"k\": [304, 408, 0],\n          \"ix\": 2\n        },\n        \"a\": {\n          \"a\": 0,\n          \"k\": [400, 400, 0],\n          \"ix\": 1\n        },\n        \"s\": {\n          \"a\": 0,\n          \"k\": [102, 102, 100],\n          \"ix\": 6\n        }\n      },\n      \"ao\": 0,\n      \"w\": 800,\n      \"h\": 800,\n      \"ip\": 0,\n      \"op\": 300,\n      \"st\": 0,\n      \"bm\": 0\n    }\n  ],\n  \"markers\": []\n}\n"
  },
  {
    "path": "assets/lottie/success.json",
    "content": "{\n  \"v\": \"5.7.1\",\n  \"fr\": 30,\n  \"ip\": 0,\n  \"op\": 60,\n  \"w\": 300,\n  \"h\": 300,\n  \"nm\": \"Comp 1\",\n  \"ddd\": 0,\n  \"assets\": [],\n  \"layers\": [\n    {\n      \"ddd\": 0,\n      \"ind\": 1,\n      \"ty\": 4,\n      \"nm\": \"4\",\n      \"sr\": 1,\n      \"ks\": {\n        \"o\": {\n          \"a\": 0,\n          \"k\": 100,\n          \"ix\": 11\n        },\n        \"r\": {\n          \"a\": 0,\n          \"k\": 0,\n          \"ix\": 10\n        },\n        \"p\": {\n          \"a\": 0,\n          \"k\": [151, 151, 0],\n          \"ix\": 2\n        },\n        \"a\": {\n          \"a\": 0,\n          \"k\": [0, 0, 0],\n          \"ix\": 1\n        },\n        \"s\": {\n          \"a\": 0,\n          \"k\": [100, 100, 100],\n          \"ix\": 6\n        }\n      },\n      \"ao\": 0,\n      \"shapes\": [\n        {\n          \"ty\": \"gr\",\n          \"it\": [\n            {\n              \"ind\": 0,\n              \"ty\": \"sh\",\n              \"ix\": 1,\n              \"ks\": {\n                \"a\": 0,\n                \"k\": {\n                  \"i\": [\n                    [0, 0],\n                    [-22.5, -7.5],\n                    [0, 0]\n                  ],\n                  \"o\": [\n                    [0, 0],\n                    [22.5, 7.5],\n                    [0, 0]\n                  ],\n                  \"v\": [\n                    [61, 78.5],\n                    [78, 100.5],\n                    [94, 115.5]\n                  ],\n                  \"c\": false\n                },\n                \"ix\": 2\n              },\n              \"nm\": \"Path 1\",\n              \"mn\": \"ADBE Vector Shape - Group\",\n              \"hd\": false\n            },\n            {\n              \"ty\": \"st\",\n              \"c\": {\n                \"a\": 0,\n                \"k\": [0.12941176470588237, 0.19607843137254902, 0.3843137254901961, 1],\n                \"ix\": 3\n              },\n              \"o\": {\n                \"a\": 0,\n                \"k\": 100,\n                \"ix\": 4\n              },\n              \"w\": {\n                \"a\": 0,\n                \"k\": 5,\n                \"ix\": 5\n              },\n              \"lc\": 2,\n              \"lj\": 1,\n              \"ml\": 4,\n              \"bm\": 0,\n              \"nm\": \"Stroke 1\",\n              \"mn\": \"ADBE Vector Graphic - Stroke\",\n              \"hd\": false\n            },\n            {\n              \"ty\": \"tr\",\n              \"p\": {\n                \"a\": 0,\n                \"k\": [0, 0],\n                \"ix\": 2\n              },\n              \"a\": {\n                \"a\": 0,\n                \"k\": [0, 0],\n                \"ix\": 1\n              },\n              \"s\": {\n                \"a\": 0,\n                \"k\": [100, 100],\n                \"ix\": 3\n              },\n              \"r\": {\n                \"a\": 0,\n                \"k\": 0,\n                \"ix\": 6\n              },\n              \"o\": {\n                \"a\": 0,\n                \"k\": 100,\n                \"ix\": 7\n              },\n              \"sk\": {\n                \"a\": 0,\n                \"k\": 0,\n                \"ix\": 4\n              },\n              \"sa\": {\n                \"a\": 0,\n                \"k\": 0,\n                \"ix\": 5\n              },\n              \"nm\": \"Transform\"\n            }\n          ],\n          \"nm\": \"Shape 1\",\n          \"np\": 3,\n          \"cix\": 2,\n          \"bm\": 0,\n          \"ix\": 1,\n          \"mn\": \"ADBE Vector Group\",\n          \"hd\": false\n        },\n        {\n          \"ty\": \"tm\",\n          \"s\": {\n            \"a\": 1,\n            \"k\": [\n              {\n                \"i\": {\n                  \"x\": [0.667],\n                  \"y\": [1]\n                },\n                \"o\": {\n                  \"x\": [0.333],\n                  \"y\": [0]\n                },\n                \"t\": 28.254,\n                \"s\": [0]\n              },\n              {\n                \"t\": 51,\n                \"s\": [100]\n              }\n            ],\n            \"ix\": 1\n          },\n          \"e\": {\n            \"a\": 1,\n            \"k\": [\n              {\n                \"i\": {\n                  \"x\": [0.667],\n                  \"y\": [1]\n                },\n                \"o\": {\n                  \"x\": [0.333],\n                  \"y\": [0]\n                },\n                \"t\": 17,\n                \"s\": [0]\n              },\n              {\n                \"t\": 46.2109375,\n                \"s\": [100]\n              }\n            ],\n            \"ix\": 2\n          },\n          \"o\": {\n            \"a\": 0,\n            \"k\": 0,\n            \"ix\": 3\n          },\n          \"m\": 1,\n          \"ix\": 2,\n          \"nm\": \"Trim Paths 1\",\n          \"mn\": \"ADBE Vector Filter - Trim\",\n          \"hd\": false\n        }\n      ],\n      \"ip\": 17,\n      \"op\": 617,\n      \"st\": 17,\n      \"bm\": 0\n    },\n    {\n      \"ddd\": 0,\n      \"ind\": 2,\n      \"ty\": 4,\n      \"nm\": \"3\",\n      \"sr\": 1,\n      \"ks\": {\n        \"o\": {\n          \"a\": 0,\n          \"k\": 100,\n          \"ix\": 11\n        },\n        \"r\": {\n          \"a\": 0,\n          \"k\": 203,\n          \"ix\": 10\n        },\n        \"p\": {\n          \"a\": 0,\n          \"k\": [251.408, 59.449, 0],\n          \"ix\": 2\n        },\n        \"a\": {\n          \"a\": 0,\n          \"k\": [-103.936, 89.696, 0],\n          \"ix\": 1\n        },\n        \"s\": {\n          \"a\": 0,\n          \"k\": [91.456, 89.381, 100],\n          \"ix\": 6\n        }\n      },\n      \"ao\": 0,\n      \"shapes\": [\n        {\n          \"ty\": \"gr\",\n          \"it\": [\n            {\n              \"ind\": 0,\n              \"ty\": \"sh\",\n              \"ix\": 1,\n              \"ks\": {\n                \"a\": 0,\n                \"k\": {\n                  \"i\": [\n                    [0, 0],\n                    [29.459, 25.084],\n                    [5, -25.75],\n                    [5.75, -0.75]\n                  ],\n                  \"o\": [\n                    [0, 0],\n                    [-25.25, -21.5],\n                    [-5.515, 28.405],\n                    [-5.75, 0.75]\n                  ],\n                  \"v\": [\n                    [-75, 68.75],\n                    [-107.25, 86.5],\n                    [-94, 84],\n                    [-128.75, 113]\n                  ],\n                  \"c\": false\n                },\n                \"ix\": 2\n              },\n              \"nm\": \"Path 1\",\n              \"mn\": \"ADBE Vector Shape - Group\",\n              \"hd\": false\n            },\n            {\n              \"ty\": \"st\",\n              \"c\": {\n                \"a\": 0,\n                \"k\": [1, 0.713725490196, 0.211764720842, 1],\n                \"ix\": 3\n              },\n              \"o\": {\n                \"a\": 0,\n                \"k\": 100,\n                \"ix\": 4\n              },\n              \"w\": {\n                \"a\": 0,\n                \"k\": 5,\n                \"ix\": 5\n              },\n              \"lc\": 2,\n              \"lj\": 1,\n              \"ml\": 4,\n              \"bm\": 0,\n              \"nm\": \"Stroke 1\",\n              \"mn\": \"ADBE Vector Graphic - Stroke\",\n              \"hd\": false\n            },\n            {\n              \"ty\": \"tr\",\n              \"p\": {\n                \"a\": 0,\n                \"k\": [0, 0],\n                \"ix\": 2\n              },\n              \"a\": {\n                \"a\": 0,\n                \"k\": [0, 0],\n                \"ix\": 1\n              },\n              \"s\": {\n                \"a\": 0,\n                \"k\": [100, 100],\n                \"ix\": 3\n              },\n              \"r\": {\n                \"a\": 0,\n                \"k\": 0,\n                \"ix\": 6\n              },\n              \"o\": {\n                \"a\": 0,\n                \"k\": 100,\n                \"ix\": 7\n              },\n              \"sk\": {\n                \"a\": 0,\n                \"k\": 0,\n                \"ix\": 4\n              },\n              \"sa\": {\n                \"a\": 0,\n                \"k\": 0,\n                \"ix\": 5\n              },\n              \"nm\": \"Transform\"\n            }\n          ],\n          \"nm\": \"Shape 1\",\n          \"np\": 3,\n          \"cix\": 2,\n          \"bm\": 0,\n          \"ix\": 1,\n          \"mn\": \"ADBE Vector Group\",\n          \"hd\": false\n        },\n        {\n          \"ty\": \"tm\",\n          \"s\": {\n            \"a\": 1,\n            \"k\": [\n              {\n                \"i\": {\n                  \"x\": [0.667],\n                  \"y\": [1]\n                },\n                \"o\": {\n                  \"x\": [0.333],\n                  \"y\": [0]\n                },\n                \"t\": 28.254,\n                \"s\": [0]\n              },\n              {\n                \"t\": 51,\n                \"s\": [100]\n              }\n            ],\n            \"ix\": 1\n          },\n          \"e\": {\n            \"a\": 1,\n            \"k\": [\n              {\n                \"i\": {\n                  \"x\": [0.667],\n                  \"y\": [1]\n                },\n                \"o\": {\n                  \"x\": [0.333],\n                  \"y\": [0]\n                },\n                \"t\": 17,\n                \"s\": [0]\n              },\n              {\n                \"t\": 46.2109375,\n                \"s\": [100]\n              }\n            ],\n            \"ix\": 2\n          },\n          \"o\": {\n            \"a\": 0,\n            \"k\": 0,\n            \"ix\": 3\n          },\n          \"m\": 1,\n          \"ix\": 2,\n          \"nm\": \"Trim Paths 1\",\n          \"mn\": \"ADBE Vector Filter - Trim\",\n          \"hd\": false\n        }\n      ],\n      \"ip\": 17,\n      \"op\": 617,\n      \"st\": 17,\n      \"bm\": 0\n    },\n    {\n      \"ddd\": 0,\n      \"ind\": 3,\n      \"ty\": 4,\n      \"nm\": \"2\",\n      \"sr\": 1,\n      \"ks\": {\n        \"o\": {\n          \"a\": 0,\n          \"k\": 100,\n          \"ix\": 11\n        },\n        \"r\": {\n          \"a\": 0,\n          \"k\": 0,\n          \"ix\": 10\n        },\n        \"p\": {\n          \"a\": 0,\n          \"k\": [-21, 347, 0],\n          \"ix\": 2\n        },\n        \"a\": {\n          \"a\": 0,\n          \"k\": [0, 0, 0],\n          \"ix\": 1\n        },\n        \"s\": {\n          \"a\": 0,\n          \"k\": [100, 100, 100],\n          \"ix\": 6\n        }\n      },\n      \"ao\": 0,\n      \"shapes\": [\n        {\n          \"ty\": \"gr\",\n          \"it\": [\n            {\n              \"ind\": 0,\n              \"ty\": \"sh\",\n              \"ix\": 1,\n              \"ks\": {\n                \"a\": 0,\n                \"k\": {\n                  \"i\": [\n                    [0, 0],\n                    [20.5, 4.5],\n                    [0, 0],\n                    [18.25, 9.25],\n                    [3.5, -3.25]\n                  ],\n                  \"o\": [\n                    [0, 0],\n                    [-20.5, -4.5],\n                    [0, 0],\n                    [-18.25, -9.25],\n                    [-3.5, 3.25]\n                  ],\n                  \"v\": [\n                    [90.75, -122.25],\n                    [83.5, -110.5],\n                    [81.25, -97.25],\n                    [69.75, -93.25],\n                    [61, -75.75]\n                  ],\n                  \"c\": false\n                },\n                \"ix\": 2\n              },\n              \"nm\": \"Path 1\",\n              \"mn\": \"ADBE Vector Shape - Group\",\n              \"hd\": false\n            },\n            {\n              \"ty\": \"st\",\n              \"c\": {\n                \"a\": 0,\n                \"k\": [0.745098039216, 0.643137254902, 1, 1],\n                \"ix\": 3\n              },\n              \"o\": {\n                \"a\": 0,\n                \"k\": 100,\n                \"ix\": 4\n              },\n              \"w\": {\n                \"a\": 0,\n                \"k\": 5,\n                \"ix\": 5\n              },\n              \"lc\": 2,\n              \"lj\": 1,\n              \"ml\": 4,\n              \"bm\": 0,\n              \"nm\": \"Stroke 1\",\n              \"mn\": \"ADBE Vector Graphic - Stroke\",\n              \"hd\": false\n            },\n            {\n              \"ty\": \"tr\",\n              \"p\": {\n                \"a\": 0,\n                \"k\": [0, 0],\n                \"ix\": 2\n              },\n              \"a\": {\n                \"a\": 0,\n                \"k\": [0, 0],\n                \"ix\": 1\n              },\n              \"s\": {\n                \"a\": 0,\n                \"k\": [100, 100],\n                \"ix\": 3\n              },\n              \"r\": {\n                \"a\": 0,\n                \"k\": 0,\n                \"ix\": 6\n              },\n              \"o\": {\n                \"a\": 0,\n                \"k\": 100,\n                \"ix\": 7\n              },\n              \"sk\": {\n                \"a\": 0,\n                \"k\": 0,\n                \"ix\": 4\n              },\n              \"sa\": {\n                \"a\": 0,\n                \"k\": 0,\n                \"ix\": 5\n              },\n              \"nm\": \"Transform\"\n            }\n          ],\n          \"nm\": \"Shape 1\",\n          \"np\": 3,\n          \"cix\": 2,\n          \"bm\": 0,\n          \"ix\": 1,\n          \"mn\": \"ADBE Vector Group\",\n          \"hd\": false\n        },\n        {\n          \"ty\": \"tm\",\n          \"s\": {\n            \"a\": 1,\n            \"k\": [\n              {\n                \"i\": {\n                  \"x\": [0.667],\n                  \"y\": [1]\n                },\n                \"o\": {\n                  \"x\": [0.333],\n                  \"y\": [0]\n                },\n                \"t\": 28.254,\n                \"s\": [0]\n              },\n              {\n                \"t\": 51,\n                \"s\": [100]\n              }\n            ],\n            \"ix\": 1\n          },\n          \"e\": {\n            \"a\": 1,\n            \"k\": [\n              {\n                \"i\": {\n                  \"x\": [0.667],\n                  \"y\": [1]\n                },\n                \"o\": {\n                  \"x\": [0.333],\n                  \"y\": [0]\n                },\n                \"t\": 17,\n                \"s\": [0]\n              },\n              {\n                \"t\": 46.2109375,\n                \"s\": [100]\n              }\n            ],\n            \"ix\": 2\n          },\n          \"o\": {\n            \"a\": 0,\n            \"k\": 0,\n            \"ix\": 3\n          },\n          \"m\": 1,\n          \"ix\": 2,\n          \"nm\": \"Trim Paths 1\",\n          \"mn\": \"ADBE Vector Filter - Trim\",\n          \"hd\": false\n        }\n      ],\n      \"ip\": 17,\n      \"op\": 617,\n      \"st\": 17,\n      \"bm\": 0\n    },\n    {\n      \"ddd\": 0,\n      \"ind\": 4,\n      \"ty\": 4,\n      \"nm\": \"1\",\n      \"sr\": 1,\n      \"ks\": {\n        \"o\": {\n          \"a\": 0,\n          \"k\": 100,\n          \"ix\": 11\n        },\n        \"r\": {\n          \"a\": 0,\n          \"k\": 0,\n          \"ix\": 10\n        },\n        \"p\": {\n          \"a\": 0,\n          \"k\": [147, 146, 0],\n          \"ix\": 2\n        },\n        \"a\": {\n          \"a\": 0,\n          \"k\": [0, 0, 0],\n          \"ix\": 1\n        },\n        \"s\": {\n          \"a\": 0,\n          \"k\": [109.756, 101.856, 100],\n          \"ix\": 6\n        }\n      },\n      \"ao\": 0,\n      \"shapes\": [\n        {\n          \"ty\": \"gr\",\n          \"it\": [\n            {\n              \"ind\": 0,\n              \"ty\": \"sh\",\n              \"ix\": 1,\n              \"ks\": {\n                \"a\": 0,\n                \"k\": {\n                  \"i\": [\n                    [0, 0],\n                    [33.75, 1]\n                  ],\n                  \"o\": [\n                    [0, 0],\n                    [-33.75, -1]\n                  ],\n                  \"v\": [\n                    [-57.75, -75.75],\n                    [-90.75, -107.5]\n                  ],\n                  \"c\": false\n                },\n                \"ix\": 2\n              },\n              \"nm\": \"Path 1\",\n              \"mn\": \"ADBE Vector Shape - Group\",\n              \"hd\": false\n            },\n            {\n              \"ty\": \"st\",\n              \"c\": {\n                \"a\": 0,\n                \"k\": [1, 0.431372578939, 0.513725490196, 1],\n                \"ix\": 3\n              },\n              \"o\": {\n                \"a\": 0,\n                \"k\": 100,\n                \"ix\": 4\n              },\n              \"w\": {\n                \"a\": 0,\n                \"k\": 5,\n                \"ix\": 5\n              },\n              \"lc\": 2,\n              \"lj\": 1,\n              \"ml\": 4,\n              \"bm\": 0,\n              \"nm\": \"Stroke 1\",\n              \"mn\": \"ADBE Vector Graphic - Stroke\",\n              \"hd\": false\n            },\n            {\n              \"ty\": \"tr\",\n              \"p\": {\n                \"a\": 0,\n                \"k\": [-1.5, -0.25],\n                \"ix\": 2\n              },\n              \"a\": {\n                \"a\": 0,\n                \"k\": [0, 0],\n                \"ix\": 1\n              },\n              \"s\": {\n                \"a\": 0,\n                \"k\": [100, 100],\n                \"ix\": 3\n              },\n              \"r\": {\n                \"a\": 0,\n                \"k\": 0,\n                \"ix\": 6\n              },\n              \"o\": {\n                \"a\": 0,\n                \"k\": 100,\n                \"ix\": 7\n              },\n              \"sk\": {\n                \"a\": 0,\n                \"k\": 0,\n                \"ix\": 4\n              },\n              \"sa\": {\n                \"a\": 0,\n                \"k\": 0,\n                \"ix\": 5\n              },\n              \"nm\": \"Transform\"\n            }\n          ],\n          \"nm\": \"Shape 1\",\n          \"np\": 3,\n          \"cix\": 2,\n          \"bm\": 0,\n          \"ix\": 1,\n          \"mn\": \"ADBE Vector Group\",\n          \"hd\": false\n        },\n        {\n          \"ty\": \"tm\",\n          \"s\": {\n            \"a\": 1,\n            \"k\": [\n              {\n                \"i\": {\n                  \"x\": [0.667],\n                  \"y\": [1]\n                },\n                \"o\": {\n                  \"x\": [0.333],\n                  \"y\": [0]\n                },\n                \"t\": 28.254,\n                \"s\": [0]\n              },\n              {\n                \"t\": 51,\n                \"s\": [100]\n              }\n            ],\n            \"ix\": 1\n          },\n          \"e\": {\n            \"a\": 1,\n            \"k\": [\n              {\n                \"i\": {\n                  \"x\": [0.667],\n                  \"y\": [1]\n                },\n                \"o\": {\n                  \"x\": [0.333],\n                  \"y\": [0]\n                },\n                \"t\": 17,\n                \"s\": [0]\n              },\n              {\n                \"t\": 46.2109375,\n                \"s\": [100]\n              }\n            ],\n            \"ix\": 2\n          },\n          \"o\": {\n            \"a\": 0,\n            \"k\": 0,\n            \"ix\": 3\n          },\n          \"m\": 1,\n          \"ix\": 2,\n          \"nm\": \"Trim Paths 1\",\n          \"mn\": \"ADBE Vector Filter - Trim\",\n          \"hd\": false\n        }\n      ],\n      \"ip\": 17,\n      \"op\": 617,\n      \"st\": 17,\n      \"bm\": 0\n    },\n    {\n      \"ddd\": 0,\n      \"ind\": 5,\n      \"ty\": 4,\n      \"nm\": \"checkmark/success Outlines\",\n      \"sr\": 1,\n      \"ks\": {\n        \"o\": {\n          \"a\": 0,\n          \"k\": 100,\n          \"ix\": 11\n        },\n        \"r\": {\n          \"a\": 0,\n          \"k\": 0,\n          \"ix\": 10\n        },\n        \"p\": {\n          \"a\": 0,\n          \"k\": [150.06, 150.061, 0],\n          \"ix\": 2\n        },\n        \"a\": {\n          \"a\": 0,\n          \"k\": [99, 99, 0],\n          \"ix\": 1\n        },\n        \"s\": {\n          \"a\": 1,\n          \"k\": [\n            {\n              \"i\": {\n                \"x\": [0.667, 0.667, 0.667],\n                \"y\": [1, 1, 1]\n              },\n              \"o\": {\n                \"x\": [0.333, 0.333, 0.333],\n                \"y\": [0, 0, 0]\n              },\n              \"t\": 0,\n              \"s\": [100, 100, 100]\n            },\n            {\n              \"i\": {\n                \"x\": [0.667, 0.667, 0.667],\n                \"y\": [1, 1, 1]\n              },\n              \"o\": {\n                \"x\": [0.333, 0.333, 0.333],\n                \"y\": [0, 0, 0]\n              },\n              \"t\": 12,\n              \"s\": [27, 27, 100]\n            },\n            {\n              \"t\": 21,\n              \"s\": [100, 100, 100]\n            }\n          ],\n          \"ix\": 6\n        }\n      },\n      \"ao\": 0,\n      \"shapes\": [\n        {\n          \"ty\": \"gr\",\n          \"it\": [\n            {\n              \"ind\": 0,\n              \"ty\": \"sh\",\n              \"ix\": 1,\n              \"ks\": {\n                \"a\": 0,\n                \"k\": {\n                  \"i\": [\n                    [0, 0],\n                    [0.831, 1.409],\n                    [0, 0],\n                    [-0.622, 2.004],\n                    [-1.844, 1.043],\n                    [-2.083, -0.474],\n                    [-1.215, -1.74],\n                    [0, 0],\n                    [-0.949, 0.537],\n                    [0, 0],\n                    [-2.041, -0.632],\n                    [-1.075, -1.826],\n                    [0.463, -2.047],\n                    [1.756, -1.181]\n                  ],\n                  \"o\": [\n                    [-1.424, 0.805],\n                    [0, 0],\n                    [-0.93, -1.899],\n                    [0.622, -2.006],\n                    [1.844, -1.042],\n                    [2.084, 0.474],\n                    [0, 0],\n                    [0.553, 0.939],\n                    [0, 0],\n                    [1.921, -0.899],\n                    [2.042, 0.631],\n                    [1.076, 1.823],\n                    [-0.463, 2.047],\n                    [0, 0]\n                  ],\n                  \"v\": [\n                    [-26.138, 30.587],\n                    [-30.199, 29.498],\n                    [-58.899, -19.189],\n                    [-59.378, -25.261],\n                    [-55.542, -30.001],\n                    [-49.433, -30.884],\n                    [-44.302, -27.441],\n                    [-23.618, 7.647],\n                    [-20.911, 8.371],\n                    [47.571, -30.344],\n                    [53.736, -30.76],\n                    [58.584, -26.94],\n                    [59.537, -20.918],\n                    [56.086, -15.898]\n                  ],\n                  \"c\": true\n                },\n                \"ix\": 2\n              },\n              \"nm\": \"Path 1\",\n              \"mn\": \"ADBE Vector Shape - Group\",\n              \"hd\": false\n            },\n            {\n              \"ty\": \"fl\",\n              \"c\": {\n                \"a\": 0,\n                \"k\": [1, 1, 1, 1],\n                \"ix\": 4\n              },\n              \"o\": {\n                \"a\": 0,\n                \"k\": 100,\n                \"ix\": 5\n              },\n              \"r\": 1,\n              \"bm\": 0,\n              \"nm\": \"Fill 1\",\n              \"mn\": \"ADBE Vector Graphic - Fill\",\n              \"hd\": false\n            },\n            {\n              \"ty\": \"tr\",\n              \"p\": {\n                \"a\": 0,\n                \"k\": [99.943, 103.024],\n                \"ix\": 2\n              },\n              \"a\": {\n                \"a\": 0,\n                \"k\": [0, 0],\n                \"ix\": 1\n              },\n              \"s\": {\n                \"a\": 0,\n                \"k\": [83.631, 83.631],\n                \"ix\": 3\n              },\n              \"r\": {\n                \"a\": 0,\n                \"k\": -12.6,\n                \"ix\": 6\n              },\n              \"o\": {\n                \"a\": 0,\n                \"k\": 100,\n                \"ix\": 7\n              },\n              \"sk\": {\n                \"a\": 0,\n                \"k\": 0,\n                \"ix\": 4\n              },\n              \"sa\": {\n                \"a\": 0,\n                \"k\": 0,\n                \"ix\": 5\n              },\n              \"nm\": \"Transform\"\n            }\n          ],\n          \"nm\": \"Group 1\",\n          \"np\": 2,\n          \"cix\": 2,\n          \"bm\": 0,\n          \"ix\": 1,\n          \"mn\": \"ADBE Vector Group\",\n          \"hd\": false\n        },\n        {\n          \"ty\": \"gr\",\n          \"it\": [\n            {\n              \"ind\": 0,\n              \"ty\": \"sh\",\n              \"ix\": 1,\n              \"ks\": {\n                \"a\": 0,\n                \"k\": {\n                  \"i\": [\n                    [-47.479, -12.722],\n                    [12.721, -47.478],\n                    [47.478, 12.722],\n                    [-12.723, 47.478]\n                  ],\n                  \"o\": [\n                    [47.479, 12.722],\n                    [-12.723, 47.479],\n                    [-47.478, -12.723],\n                    [12.721, -47.479]\n                  ],\n                  \"v\": [\n                    [23.036, -85.967],\n                    [85.969, 23.035],\n                    [-23.035, 85.967],\n                    [-85.966, -23.035]\n                  ],\n                  \"c\": true\n                },\n                \"ix\": 2\n              },\n              \"nm\": \"Path 1\",\n              \"mn\": \"ADBE Vector Shape - Group\",\n              \"hd\": false\n            },\n            {\n              \"ty\": \"fl\",\n              \"c\": {\n                \"a\": 1,\n                \"k\": [\n                  {\n                    \"i\": {\n                      \"x\": [0.833],\n                      \"y\": [0.833]\n                    },\n                    \"o\": {\n                      \"x\": [0.167],\n                      \"y\": [0.167]\n                    },\n                    \"t\": 0,\n                    \"s\": [0.901960790157, 0.901960790157, 0.901960790157, 1]\n                  },\n                  {\n                    \"i\": {\n                      \"x\": [0.833],\n                      \"y\": [0.833]\n                    },\n                    \"o\": {\n                      \"x\": [0.167],\n                      \"y\": [0.167]\n                    },\n                    \"t\": 10,\n                    \"s\": [0.901960790157, 0.901960790157, 0.901960790157, 1]\n                  },\n                  {\n                    \"t\": 29,\n                    \"s\": [0.262745112181, 0.823529422283, 0.588235318661, 1]\n                  }\n                ],\n                \"ix\": 4\n              },\n              \"o\": {\n                \"a\": 0,\n                \"k\": 100,\n                \"ix\": 5\n              },\n              \"r\": 1,\n              \"bm\": 0,\n              \"nm\": \"Fill 1\",\n              \"mn\": \"ADBE Vector Graphic - Fill\",\n              \"hd\": false\n            },\n            {\n              \"ty\": \"tr\",\n              \"p\": {\n                \"a\": 0,\n                \"k\": [98.939, 98.939],\n                \"ix\": 2\n              },\n              \"a\": {\n                \"a\": 0,\n                \"k\": [0, 0],\n                \"ix\": 1\n              },\n              \"s\": {\n                \"a\": 0,\n                \"k\": [100, 100],\n                \"ix\": 3\n              },\n              \"r\": {\n                \"a\": 0,\n                \"k\": 0,\n                \"ix\": 6\n              },\n              \"o\": {\n                \"a\": 0,\n                \"k\": 100,\n                \"ix\": 7\n              },\n              \"sk\": {\n                \"a\": 0,\n                \"k\": 0,\n                \"ix\": 4\n              },\n              \"sa\": {\n                \"a\": 0,\n                \"k\": 0,\n                \"ix\": 5\n              },\n              \"nm\": \"Transform\"\n            }\n          ],\n          \"nm\": \"Group 2\",\n          \"np\": 2,\n          \"cix\": 2,\n          \"bm\": 0,\n          \"ix\": 2,\n          \"mn\": \"ADBE Vector Group\",\n          \"hd\": false\n        }\n      ],\n      \"ip\": 0,\n      \"op\": 600,\n      \"st\": 0,\n      \"bm\": 0\n    },\n    {\n      \"ddd\": 0,\n      \"ind\": 6,\n      \"ty\": 4,\n      \"nm\": \"large-circles/success Outlines\",\n      \"sr\": 1,\n      \"ks\": {\n        \"o\": {\n          \"a\": 1,\n          \"k\": [\n            {\n              \"i\": {\n                \"x\": [0.833],\n                \"y\": [0.833]\n              },\n              \"o\": {\n                \"x\": [0.167],\n                \"y\": [0.167]\n              },\n              \"t\": 42,\n              \"s\": [100]\n            },\n            {\n              \"t\": 52,\n              \"s\": [2]\n            }\n          ],\n          \"ix\": 11\n        },\n        \"r\": {\n          \"a\": 0,\n          \"k\": 0,\n          \"ix\": 10\n        },\n        \"p\": {\n          \"a\": 0,\n          \"k\": [148, 146, 0],\n          \"ix\": 2\n        },\n        \"a\": {\n          \"a\": 0,\n          \"k\": [95.5, 98, 0],\n          \"ix\": 1\n        },\n        \"s\": {\n          \"a\": 1,\n          \"k\": [\n            {\n              \"i\": {\n                \"x\": [0.667, 0.667, 0.667],\n                \"y\": [1, 1, 1]\n              },\n              \"o\": {\n                \"x\": [0.009, 0.009, 0.333],\n                \"y\": [1.621, 1.621, 0]\n              },\n              \"t\": 17,\n              \"s\": [62, 62, 100]\n            },\n            {\n              \"t\": 50,\n              \"s\": [124, 124, 100]\n            }\n          ],\n          \"ix\": 6\n        }\n      },\n      \"ao\": 0,\n      \"shapes\": [\n        {\n          \"ty\": \"gr\",\n          \"it\": [\n            {\n              \"ind\": 0,\n              \"ty\": \"sh\",\n              \"ix\": 1,\n              \"ks\": {\n                \"a\": 0,\n                \"k\": {\n                  \"i\": [\n                    [-6.209, 1.338],\n                    [-1.337, -6.209],\n                    [6.209, -1.337],\n                    [1.338, 6.209]\n                  ],\n                  \"o\": [\n                    [6.208, -1.337],\n                    [1.338, 6.209],\n                    [-6.209, 1.338],\n                    [-1.337, -6.209]\n                  ],\n                  \"v\": [\n                    [-2.421, -11.243],\n                    [11.242, -2.422],\n                    [2.421, 11.241],\n                    [-11.243, 2.421]\n                  ],\n                  \"c\": true\n                },\n                \"ix\": 2\n              },\n              \"nm\": \"Path 1\",\n              \"mn\": \"ADBE Vector Shape - Group\",\n              \"hd\": false\n            },\n            {\n              \"ty\": \"fl\",\n              \"c\": {\n                \"a\": 0,\n                \"k\": [0.745000023935, 0.642999985639, 1, 1],\n                \"ix\": 4\n              },\n              \"o\": {\n                \"a\": 0,\n                \"k\": 100,\n                \"ix\": 5\n              },\n              \"r\": 1,\n              \"bm\": 0,\n              \"nm\": \"Fill 1\",\n              \"mn\": \"ADBE Vector Graphic - Fill\",\n              \"hd\": false\n            },\n            {\n              \"ty\": \"tr\",\n              \"p\": {\n                \"a\": 0,\n                \"k\": [173.998, 145.423],\n                \"ix\": 2\n              },\n              \"a\": {\n                \"a\": 0,\n                \"k\": [0, 0],\n                \"ix\": 1\n              },\n              \"s\": {\n                \"a\": 0,\n                \"k\": [71, 71],\n                \"ix\": 3\n              },\n              \"r\": {\n                \"a\": 0,\n                \"k\": 0,\n                \"ix\": 6\n              },\n              \"o\": {\n                \"a\": 0,\n                \"k\": 100,\n                \"ix\": 7\n              },\n              \"sk\": {\n                \"a\": 0,\n                \"k\": 0,\n                \"ix\": 4\n              },\n              \"sa\": {\n                \"a\": 0,\n                \"k\": 0,\n                \"ix\": 5\n              },\n              \"nm\": \"Transform\"\n            }\n          ],\n          \"nm\": \"Group 1\",\n          \"np\": 2,\n          \"cix\": 2,\n          \"bm\": 0,\n          \"ix\": 1,\n          \"mn\": \"ADBE Vector Group\",\n          \"hd\": false\n        },\n        {\n          \"ty\": \"gr\",\n          \"it\": [\n            {\n              \"ind\": 0,\n              \"ty\": \"sh\",\n              \"ix\": 1,\n              \"ks\": {\n                \"a\": 0,\n                \"k\": {\n                  \"i\": [\n                    [-6.209, 1.337],\n                    [-1.338, -6.209],\n                    [6.209, -1.338],\n                    [1.338, 6.209]\n                  ],\n                  \"o\": [\n                    [6.209, -1.338],\n                    [1.337, 6.209],\n                    [-6.209, 1.337],\n                    [-1.337, -6.208]\n                  ],\n                  \"v\": [\n                    [-2.421, -11.242],\n                    [11.242, -2.422],\n                    [2.422, 11.242],\n                    [-11.243, 2.422]\n                  ],\n                  \"c\": true\n                },\n                \"ix\": 2\n              },\n              \"nm\": \"Path 1\",\n              \"mn\": \"ADBE Vector Shape - Group\",\n              \"hd\": false\n            },\n            {\n              \"ty\": \"fl\",\n              \"c\": {\n                \"a\": 0,\n                \"k\": [0.011764705882352941, 0.45098039215686275, 0.8901960784313725, 1],\n                \"ix\": 4\n              },\n              \"o\": {\n                \"a\": 0,\n                \"k\": 100,\n                \"ix\": 5\n              },\n              \"r\": 1,\n              \"bm\": 0,\n              \"nm\": \"Fill 1\",\n              \"mn\": \"ADBE Vector Graphic - Fill\",\n              \"hd\": false\n            },\n            {\n              \"ty\": \"tr\",\n              \"p\": {\n                \"a\": 0,\n                \"k\": [63.997, 183.011],\n                \"ix\": 2\n              },\n              \"a\": {\n                \"a\": 0,\n                \"k\": [0, 0],\n                \"ix\": 1\n              },\n              \"s\": {\n                \"a\": 0,\n                \"k\": [70, 70],\n                \"ix\": 3\n              },\n              \"r\": {\n                \"a\": 0,\n                \"k\": 0,\n                \"ix\": 6\n              },\n              \"o\": {\n                \"a\": 0,\n                \"k\": 100,\n                \"ix\": 7\n              },\n              \"sk\": {\n                \"a\": 0,\n                \"k\": 0,\n                \"ix\": 4\n              },\n              \"sa\": {\n                \"a\": 0,\n                \"k\": 0,\n                \"ix\": 5\n              },\n              \"nm\": \"Transform\"\n            }\n          ],\n          \"nm\": \"Group 2\",\n          \"np\": 2,\n          \"cix\": 2,\n          \"bm\": 0,\n          \"ix\": 2,\n          \"mn\": \"ADBE Vector Group\",\n          \"hd\": false\n        },\n        {\n          \"ty\": \"gr\",\n          \"it\": [\n            {\n              \"ind\": 0,\n              \"ty\": \"sh\",\n              \"ix\": 1,\n              \"ks\": {\n                \"a\": 0,\n                \"k\": {\n                  \"i\": [\n                    [-6.209, 1.337],\n                    [-1.337, -6.208],\n                    [6.209, -1.337],\n                    [1.338, 6.209]\n                  ],\n                  \"o\": [\n                    [6.209, -1.337],\n                    [1.338, 6.209],\n                    [-6.209, 1.338],\n                    [-1.337, -6.209]\n                  ],\n                  \"v\": [\n                    [-2.421, -11.243],\n                    [11.242, -2.423],\n                    [2.421, 11.242],\n                    [-11.243, 2.421]\n                  ],\n                  \"c\": true\n                },\n                \"ix\": 2\n              },\n              \"nm\": \"Path 1\",\n              \"mn\": \"ADBE Vector Shape - Group\",\n              \"hd\": false\n            },\n            {\n              \"ty\": \"fl\",\n              \"c\": {\n                \"a\": 0,\n                \"k\": [1, 0.713999968884, 0.211999990426, 1],\n                \"ix\": 4\n              },\n              \"o\": {\n                \"a\": 0,\n                \"k\": 100,\n                \"ix\": 5\n              },\n              \"r\": 1,\n              \"bm\": 0,\n              \"nm\": \"Fill 1\",\n              \"mn\": \"ADBE Vector Graphic - Fill\",\n              \"hd\": false\n            },\n            {\n              \"ty\": \"tr\",\n              \"p\": {\n                \"a\": 0,\n                \"k\": [103.291, 12.83],\n                \"ix\": 2\n              },\n              \"a\": {\n                \"a\": 0,\n                \"k\": [0, 0],\n                \"ix\": 1\n              },\n              \"s\": {\n                \"a\": 0,\n                \"k\": [70, 70],\n                \"ix\": 3\n              },\n              \"r\": {\n                \"a\": 0,\n                \"k\": 0,\n                \"ix\": 6\n              },\n              \"o\": {\n                \"a\": 0,\n                \"k\": 100,\n                \"ix\": 7\n              },\n              \"sk\": {\n                \"a\": 0,\n                \"k\": 0,\n                \"ix\": 4\n              },\n              \"sa\": {\n                \"a\": 0,\n                \"k\": 0,\n                \"ix\": 5\n              },\n              \"nm\": \"Transform\"\n            }\n          ],\n          \"nm\": \"Group 3\",\n          \"np\": 2,\n          \"cix\": 2,\n          \"bm\": 0,\n          \"ix\": 3,\n          \"mn\": \"ADBE Vector Group\",\n          \"hd\": false\n        },\n        {\n          \"ty\": \"gr\",\n          \"it\": [\n            {\n              \"ind\": 0,\n              \"ty\": \"sh\",\n              \"ix\": 1,\n              \"ks\": {\n                \"a\": 0,\n                \"k\": {\n                  \"i\": [\n                    [-6.208, 1.337],\n                    [-1.337, -6.209],\n                    [6.209, -1.338],\n                    [1.338, 6.209]\n                  ],\n                  \"o\": [\n                    [6.209, -1.337],\n                    [1.338, 6.209],\n                    [-6.209, 1.337],\n                    [-1.337, -6.209]\n                  ],\n                  \"v\": [\n                    [-2.423, -11.242],\n                    [11.241, -2.422],\n                    [2.421, 11.242],\n                    [-11.243, 2.422]\n                  ],\n                  \"c\": true\n                },\n                \"ix\": 2\n              },\n              \"nm\": \"Path 1\",\n              \"mn\": \"ADBE Vector Shape - Group\",\n              \"hd\": false\n            },\n            {\n              \"ty\": \"fl\",\n              \"c\": {\n                \"a\": 0,\n                \"k\": [0.011764705882352941, 0.45098039215686275, 0.8901960784313725, 1],\n                \"ix\": 4\n              },\n              \"o\": {\n                \"a\": 0,\n                \"k\": 100,\n                \"ix\": 5\n              },\n              \"r\": 1,\n              \"bm\": 0,\n              \"nm\": \"Fill 1\",\n              \"mn\": \"ADBE Vector Graphic - Fill\",\n              \"hd\": false\n            },\n            {\n              \"ty\": \"tr\",\n              \"p\": {\n                \"a\": 0,\n                \"k\": [178.004, 59.795],\n                \"ix\": 2\n              },\n              \"a\": {\n                \"a\": 0,\n                \"k\": [0, 0],\n                \"ix\": 1\n              },\n              \"s\": {\n                \"a\": 0,\n                \"k\": [67, 67],\n                \"ix\": 3\n              },\n              \"r\": {\n                \"a\": 0,\n                \"k\": 0,\n                \"ix\": 6\n              },\n              \"o\": {\n                \"a\": 0,\n                \"k\": 100,\n                \"ix\": 7\n              },\n              \"sk\": {\n                \"a\": 0,\n                \"k\": 0,\n                \"ix\": 4\n              },\n              \"sa\": {\n                \"a\": 0,\n                \"k\": 0,\n                \"ix\": 5\n              },\n              \"nm\": \"Transform\"\n            }\n          ],\n          \"nm\": \"Group 4\",\n          \"np\": 2,\n          \"cix\": 2,\n          \"bm\": 0,\n          \"ix\": 4,\n          \"mn\": \"ADBE Vector Group\",\n          \"hd\": false\n        },\n        {\n          \"ty\": \"gr\",\n          \"it\": [\n            {\n              \"ind\": 0,\n              \"ty\": \"sh\",\n              \"ix\": 1,\n              \"ks\": {\n                \"a\": 0,\n                \"k\": {\n                  \"i\": [\n                    [-6.209, 1.337],\n                    [-1.338, -6.208],\n                    [6.209, -1.337],\n                    [1.338, 6.209]\n                  ],\n                  \"o\": [\n                    [6.209, -1.337],\n                    [1.337, 6.209],\n                    [-6.209, 1.338],\n                    [-1.337, -6.209]\n                  ],\n                  \"v\": [\n                    [-2.421, -11.243],\n                    [11.243, -2.423],\n                    [2.422, 11.242],\n                    [-11.243, 2.421]\n                  ],\n                  \"c\": true\n                },\n                \"ix\": 2\n              },\n              \"nm\": \"Path 1\",\n              \"mn\": \"ADBE Vector Shape - Group\",\n              \"hd\": false\n            },\n            {\n              \"ty\": \"fl\",\n              \"c\": {\n                \"a\": 0,\n                \"k\": [1, 0.430999995213, 0.513999968884, 1],\n                \"ix\": 4\n              },\n              \"o\": {\n                \"a\": 0,\n                \"k\": 100,\n                \"ix\": 5\n              },\n              \"r\": 1,\n              \"bm\": 0,\n              \"nm\": \"Fill 1\",\n              \"mn\": \"ADBE Vector Graphic - Fill\",\n              \"hd\": false\n            },\n            {\n              \"ty\": \"tr\",\n              \"p\": {\n                \"a\": 0,\n                \"k\": [12.829, 84.352],\n                \"ix\": 2\n              },\n              \"a\": {\n                \"a\": 0,\n                \"k\": [0, 0],\n                \"ix\": 1\n              },\n              \"s\": {\n                \"a\": 0,\n                \"k\": [68, 68],\n                \"ix\": 3\n              },\n              \"r\": {\n                \"a\": 0,\n                \"k\": 0,\n                \"ix\": 6\n              },\n              \"o\": {\n                \"a\": 0,\n                \"k\": 100,\n                \"ix\": 7\n              },\n              \"sk\": {\n                \"a\": 0,\n                \"k\": 0,\n                \"ix\": 4\n              },\n              \"sa\": {\n                \"a\": 0,\n                \"k\": 0,\n                \"ix\": 5\n              },\n              \"nm\": \"Transform\"\n            }\n          ],\n          \"nm\": \"Group 5\",\n          \"np\": 2,\n          \"cix\": 2,\n          \"bm\": 0,\n          \"ix\": 5,\n          \"mn\": \"ADBE Vector Group\",\n          \"hd\": false\n        }\n      ],\n      \"ip\": 17,\n      \"op\": 617,\n      \"st\": 17,\n      \"bm\": 0\n    },\n    {\n      \"ddd\": 0,\n      \"ind\": 7,\n      \"ty\": 4,\n      \"nm\": \"checkmark/success Outlines\",\n      \"sr\": 1,\n      \"ks\": {\n        \"o\": {\n          \"a\": 0,\n          \"k\": 100,\n          \"ix\": 11\n        },\n        \"r\": {\n          \"a\": 0,\n          \"k\": 0,\n          \"ix\": 10\n        },\n        \"p\": {\n          \"a\": 0,\n          \"k\": [150.073, 150.073, 0],\n          \"ix\": 2\n        },\n        \"a\": {\n          \"a\": 0,\n          \"k\": [99, 99, 0],\n          \"ix\": 1\n        },\n        \"s\": {\n          \"a\": 1,\n          \"k\": [\n            {\n              \"i\": {\n                \"x\": [0.203, 0.203, 0.667],\n                \"y\": [0.507, 0.507, 1]\n              },\n              \"o\": {\n                \"x\": [0.915, 0.915, 0.333],\n                \"y\": [0.651, 0.651, 0]\n              },\n              \"t\": 50,\n              \"s\": [93.357, 93.357, 100]\n            },\n            {\n              \"t\": 59,\n              \"s\": [121.357, 121.357, 100]\n            }\n          ],\n          \"ix\": 6\n        }\n      },\n      \"ao\": 0,\n      \"shapes\": [\n        {\n          \"ty\": \"gr\",\n          \"it\": [\n            {\n              \"ind\": 0,\n              \"ty\": \"sh\",\n              \"ix\": 1,\n              \"ks\": {\n                \"a\": 0,\n                \"k\": {\n                  \"i\": [\n                    [0, 0],\n                    [0.831, 1.409],\n                    [0, 0],\n                    [-0.622, 2.004],\n                    [-1.844, 1.043],\n                    [-2.083, -0.474],\n                    [-1.215, -1.74],\n                    [0, 0],\n                    [-0.949, 0.537],\n                    [0, 0],\n                    [-2.041, -0.632],\n                    [-1.075, -1.826],\n                    [0.463, -2.047],\n                    [1.756, -1.181]\n                  ],\n                  \"o\": [\n                    [-1.424, 0.805],\n                    [0, 0],\n                    [-0.93, -1.899],\n                    [0.622, -2.006],\n                    [1.844, -1.042],\n                    [2.084, 0.474],\n                    [0, 0],\n                    [0.553, 0.939],\n                    [0, 0],\n                    [1.921, -0.899],\n                    [2.042, 0.631],\n                    [1.076, 1.823],\n                    [-0.463, 2.047],\n                    [0, 0]\n                  ],\n                  \"v\": [\n                    [-26.138, 30.587],\n                    [-30.199, 29.498],\n                    [-58.899, -19.189],\n                    [-59.378, -25.261],\n                    [-55.542, -30.001],\n                    [-49.433, -30.884],\n                    [-44.302, -27.441],\n                    [-23.618, 7.647],\n                    [-20.911, 8.371],\n                    [47.571, -30.344],\n                    [53.736, -30.76],\n                    [58.584, -26.94],\n                    [59.537, -20.918],\n                    [56.086, -15.898]\n                  ],\n                  \"c\": true\n                },\n                \"ix\": 2\n              },\n              \"nm\": \"Path 1\",\n              \"mn\": \"ADBE Vector Shape - Group\",\n              \"hd\": false\n            },\n            {\n              \"ty\": \"fl\",\n              \"c\": {\n                \"a\": 0,\n                \"k\": [1, 1, 1, 1],\n                \"ix\": 4\n              },\n              \"o\": {\n                \"a\": 0,\n                \"k\": 100,\n                \"ix\": 5\n              },\n              \"r\": 1,\n              \"bm\": 0,\n              \"nm\": \"Fill 1\",\n              \"mn\": \"ADBE Vector Graphic - Fill\",\n              \"hd\": false\n            },\n            {\n              \"ty\": \"tr\",\n              \"p\": {\n                \"a\": 0,\n                \"k\": [98.943, 102.024],\n                \"ix\": 2\n              },\n              \"a\": {\n                \"a\": 0,\n                \"k\": [0, 0],\n                \"ix\": 1\n              },\n              \"s\": {\n                \"a\": 0,\n                \"k\": [100, 100],\n                \"ix\": 3\n              },\n              \"r\": {\n                \"a\": 0,\n                \"k\": 0,\n                \"ix\": 6\n              },\n              \"o\": {\n                \"a\": 0,\n                \"k\": 100,\n                \"ix\": 7\n              },\n              \"sk\": {\n                \"a\": 0,\n                \"k\": 0,\n                \"ix\": 4\n              },\n              \"sa\": {\n                \"a\": 0,\n                \"k\": 0,\n                \"ix\": 5\n              },\n              \"nm\": \"Transform\"\n            }\n          ],\n          \"nm\": \"Group 1\",\n          \"np\": 2,\n          \"cix\": 2,\n          \"bm\": 0,\n          \"ix\": 1,\n          \"mn\": \"ADBE Vector Group\",\n          \"hd\": false\n        },\n        {\n          \"ty\": \"gr\",\n          \"it\": [\n            {\n              \"ind\": 0,\n              \"ty\": \"sh\",\n              \"ix\": 1,\n              \"ks\": {\n                \"a\": 0,\n                \"k\": {\n                  \"i\": [\n                    [-47.479, -12.722],\n                    [12.721, -47.478],\n                    [47.478, 12.722],\n                    [-12.723, 47.478]\n                  ],\n                  \"o\": [\n                    [47.479, 12.722],\n                    [-12.723, 47.479],\n                    [-47.478, -12.723],\n                    [12.721, -47.479]\n                  ],\n                  \"v\": [\n                    [23.036, -85.967],\n                    [85.969, 23.035],\n                    [-23.035, 85.967],\n                    [-85.966, -23.035]\n                  ],\n                  \"c\": true\n                },\n                \"ix\": 2\n              },\n              \"nm\": \"Path 1\",\n              \"mn\": \"ADBE Vector Shape - Group\",\n              \"hd\": false\n            },\n            {\n              \"ty\": \"fl\",\n              \"c\": {\n                \"a\": 0,\n                \"k\": [0.2235294117647059, 0.7843137254901961, 0.32941176470588235, 1],\n                \"ix\": 4\n              },\n              \"o\": {\n                \"a\": 0,\n                \"k\": 100,\n                \"ix\": 5\n              },\n              \"r\": 1,\n              \"bm\": 0,\n              \"nm\": \"Fill 1\",\n              \"mn\": \"ADBE Vector Graphic - Fill\",\n              \"hd\": false\n            },\n            {\n              \"ty\": \"tr\",\n              \"p\": {\n                \"a\": 0,\n                \"k\": [98.939, 98.939],\n                \"ix\": 2\n              },\n              \"a\": {\n                \"a\": 0,\n                \"k\": [0, 0],\n                \"ix\": 1\n              },\n              \"s\": {\n                \"a\": 0,\n                \"k\": [100, 100],\n                \"ix\": 3\n              },\n              \"r\": {\n                \"a\": 0,\n                \"k\": 0,\n                \"ix\": 6\n              },\n              \"o\": {\n                \"a\": 0,\n                \"k\": 100,\n                \"ix\": 7\n              },\n              \"sk\": {\n                \"a\": 0,\n                \"k\": 0,\n                \"ix\": 4\n              },\n              \"sa\": {\n                \"a\": 0,\n                \"k\": 0,\n                \"ix\": 5\n              },\n              \"nm\": \"Transform\"\n            }\n          ],\n          \"nm\": \"Group 2\",\n          \"np\": 2,\n          \"cix\": 2,\n          \"bm\": 0,\n          \"ix\": 2,\n          \"mn\": \"ADBE Vector Group\",\n          \"hd\": false\n        }\n      ],\n      \"ip\": 50,\n      \"op\": 650,\n      \"st\": 50,\n      \"bm\": 0\n    }\n  ],\n  \"markers\": []\n}\n"
  },
  {
    "path": "assets/translations/de.json",
    "content": "{\n  \"addrBook\": {\n    \"addOwnNpub\": \"Füge dein NPUB hinzu\",\n    \"favorite\": \"Favorisieren\",\n    \"removeFav\": \"Favorit entfernen\",\n    \"copyNpub\": \"NPUB kopieren\",\n    \"npubCopied\": \"NPUB kopiert!\",\n    \"receiverNoLnurl\": \"Empfänger hat keine LNURL\",\n    \"noResults\": \"Keine Ergebnisse\"\n  },\n  \"auth\": {\n    \"confirmAction\": \"Bitte bestätigen Sie die Aktion.\",\n    \"createPin\": \"PIN erstellen\",\n    \"editPin\": \"PIN ändern\",\n    \"pinMismatch\": \"PIN inkorrekt!\",\n    \"pinSetup\": \"Sie können optional eine PIN erstellen um Ihre App zu schützen.\",\n    \"pleaseConfirm\": \"Bitte bestätigen Sie Ihre PIN.\",\n    \"pleaseConfirmNewPin\": \"Bitte bestätigen Sie Ihre neue PIN.\",\n    \"pleaseEnter\": \"Bitte geben Sie Ihre PIN ein.\",\n    \"pleaseNewPin\": \"Bitte geben Sie eine neue PIN ein.\",\n    \"removePin\": \"PIN löschen\",\n    \"welcome\": \"Willkommen\",\n    \"welcomeBack\": \"Willkommen zurück!\"\n  },\n  \"bottomNav\": {\n    \"wallet\": \"Wallet\",\n    \"contacts\": \"Kontakte\"\n  },\n  \"common\": {\n    \"confirmReset\": \"Wallet zurücksetzen\",\n    \"copy\": \"Kopieren\",\n    \"cycle\": \"Zyklus\",\n    \"findMint\": \"Eine Mint finden\",\n    \"manualCounterIncrease\": \"Zähler erhöhen\",\n    \"manualCounterIncreaseHint\": \"Die Zähler erhöhen sich automatisch nach jeder Transaktion, aber in seltenen Fällen kann dies fehlschlagen, was zu Fehlern während des Wiederherstellungsprozesses führt. Das manuelle Erhöhen der Zähler kann den Zustand beheben.\",\n    \"increaseCounterHint\": \"Sind Sie sicher, dass Sie die Zähler erhöhen möchten? Dies sollte nur geschehen, wenn Sie sicher sind, dass die Zähler nicht synchron sind.\",\n    \"noMintForCounter\": \"Sie haben keine Mints, für die Sie die Zähler erhöhen könnten.\",\n    \"counterIncreased\": \"Zähler um {{counterIncreased}} erhöht!\",\n    \"doneSafety\": \"Fast fertig... Sicherheitsüberprüfung\",\n    \"noProofsRestored\": \"Keine Beweise gefunden, um deine Wallet wiederherzustellen.\",\n    \"restoreErr\": \"Ein Fehler ist aufgetreten bei der Wiederherstellung Ihrer Wallet.\",\n    \"dontClose\": \"Bitte schließen Sie die App während des Vorgangs nicht.\",\n    \"recoveryHint\": \"Schreiben oder fügen Sie Ihren 12-Wort-Mnemonic in der richtigen Reihenfolge ein, getrennt durch Leerzeichen.\",\n    \"walletRecovery\": \"Wallet-Wiederherstellung\",\n    \"walletRecoveryHint\": \"Verwenden Sie ein Seed-Backup, um Ihre Wallet wiederherzustellen.\",\n    \"seedBackup\": \"Seed-Backup\",\n    \"12WordMnemonic\": \"12-Wort Mnemonic\",\n    \"secureWallet\": \"Sichere Wallet\",\n    \"secureWalletHint\": \"Generieren Sie und notieren Sie ein Seed-Backup, um Ihre Wallet zu sichern.\",\n    \"quickWallet\": \"Schnelle Wallet\",\n    \"quickWalletHint\": \"Erstellen Sie sofort eine neue Wallet. Der Seed-Backup kann später generiert werden.\",\n    \"skipSeedHint\": \"Sie können diesen Prozess überspringen und später ein Seed-Backup generieren.\",\n    \"mnemonicHint\": \"Die Seed-Phrase wird nie wieder angezeigt. Schreiben Sie sie auf und teilen Sie sie niemals mit jemandem.\",\n    \"confirmMnemonicErr\": \"Falsches Wort! Stellen Sie sicher, dass Sie Ihre Seed-Phrase korrekt und in der richtigen Reihenfolge aufschreiben.\",\n    \"selectRestoreMint\": \"Bitte wählen Sie die Mint aus, die zur Wiederherstellung Ihrer Mittel verwendet wird.\",\n    \"recoveringWallet\": \"Die Mint stellt Ihr Guthaben wieder her...\",\n    \"seedEnabled\": \"Seed-Wiederherstellung aktiviert!\",\n    \"confirmSeed\": \"Bestätigen Sie bitte Ihren Seed, indem Sie das richtige Wort eingeben.\",\n    \"about\": \"Über\",\n    \"aboutToLeaveTo\": \"Sie sind im Begriff die App zu verlassen\",\n    \"accept\": \"Annehmen\",\n    \"amount\": \"Betrag\",\n    \"back\": \"Zurück\",\n    \"backToDashboard\": \"Zurück zu Wallet\",\n    \"balance\": \"Guthaben\",\n    \"balanceAfterTX\": \"Mint Guthaben nach Zahlung\",\n    \"balTooLow\": \"Nicht genug Guthaben\",\n    \"bigQrMsg\": \"Die Datenmenge ist zu groß für einen QR-Code.\",\n    \"calculateFeeEst\": \"Gebühr wird geschätzt\",\n    \"cancel\": \"Abbrechen\",\n    \"cashOut\": \"Auszahlen\",\n    \"cashOutFromMint\": \"Mint Auszahlung\",\n    \"change\": \"Rückgeld\",\n    \"claimed\": \"beansprucht\",\n    \"restored\": \"wiederhergestellt\",\n    \"claimSuccess\": \"{{amount}} Sats erhalten:\\n{{mintUrl}}\\nMemo: {{memo}}\",\n    \"claimToken\": \"Token in Anspruch nehmen\",\n    \"clear\": \"Löschen\",\n    \"clipboardInvalid\": \"Deine Zwischenablage beinhaltet einen invaliden Cashu Token\",\n    \"coinSelection\": \"Coin-Auswahl\",\n    \"confirm\": \"Bestätigen\",\n    \"contact\": \"Kontakt\",\n    \"mintDelErr\": \"Eine Mint mit verbleibendem Guthaben zu entfernen ist nicht möglich\",\n    \"continue\": \"Fortfahren\",\n    \"copied\": \"Kopiert\",\n    \"shareInvoice\": \"Rechnung teilen\",\n    \"copyToken\": \"Token kopieren\",\n    \"createInvoice\": \"Rechnung erstellen\",\n    \"createToken\": \"Token Erstellen\",\n    \"createTokenErr\": \"Es konnte kein Cashu-Token erstellt werden. Bitte versuchen Sie es später noch einmal.\",\n    \"eventError\": \"Ein Fehler ist aufgetreten während dem veröffentlichen der Nachricht.\",\n    \"createViaLn\": \"Rechnung Erstellen\",\n    \"darkMode\": \"Dunkler Modus\",\n    \"lightMode\": \"Heller Modus\",\n    \"autoMode\": \"Automatischer Modus\",\n    \"dbErr\": \"Etwas ist schief gelaufen während der Initialisierung der Datenbank!\",\n    \"deepLinkErr\": \"Link konnte nicht geöffnet werden\",\n    \"default\": \"Standard\",\n    \"delHistory\": \"Verlauf löschen\",\n    \"factoryReset\": \"Wallet zurücksetzen\",\n    \"delHistoryErr\": \"Verlauf konnte nicht gelöscht werden\",\n    \"delHistoryQ\": \"Verlauf löschen?\",\n    \"resetQ\": \"Wallet zurücksetzen?\",\n    \"delHistoryTxt\": \"Die Daten können nachträglich nicht wiederhergestellt werden.\",\n    \"display\": \"Anzeige\",\n    \"disclaimer\": \"Haftungsausschluss\",\n    \"restoreBattery\": \"Mindestens 20% Batterie.\",\n    \"restoreBatteryHint\": \"Wir empfehlen, dass Sie mindestens 20% Batterie haben, bevor Sie den Wiederherstellungsprozess starten. Je nach Datenmenge kann der Prozess eine Weile dauern.\",\n    \"restoreWifi\": \"Verwenden Sie Wi-Fi.\",\n    \"restoreWifiHint\": \"Wir empfehlen, dass Sie für den Wiederherstellungsprozess eine stabile Wi-Fi-Verbindung verwenden, um Unterbrechungen zu vermeiden und eine schnelle und sichere Wiederherstellung zu gewährleisten.\",\n    \"restoreForeground\": \"Halten Sie die App im Vordergrund.\",\n    \"restoreForegroundHint\": \"Bitte halten Sie die App im Vordergrund und schließen Sie sie während des Wiederherstellungsprozesses nicht, um Unterbrechungen zu vermeiden.\",\n    \"seedMigrationHint\": \"Der Seed gilt für alle Mints, allerdings können diese nur einzeln wiederhergestellt werden, notieren Sie also häufig verwendete Mint-URLs. Wenn Sie bereits Guthaben haben, jedoch noch kein Seed, erstellen Sie nach dem Generieren eines neuen Seeds einen Token und beanspruchen Sie ihn selbst mit der gewünschten Mint. Wiederholen Sie diesen Vorgang für jede Mint, die Sie sichern möchten.\",\n    \"ecashPayment\": \"Ecash Zahlung\",\n    \"english\": \"Englisch\",\n    \"spanish\": \"Spanisch\",\n    \"swahili\": \"Suaheli\",\n    \"hungarian\": \"Ungarisch\",\n    \"italian\": \"Italienisch\",\n    \"russian\": \"Russisch\",\n    \"thai\": \"Thailändisch\",\n    \"chinese simplified\": \"Chinesisch (Vereinfacht)\",\n    \"chinese traditional\": \"Chinesisch (Traditionell)\",\n    \"enutsRandD\": \"eNuts Telegram\",\n    \"estimatedFees\": \"Geschätzte Gebühr\",\n    \"estimateFee\": \"Gebühren schätzen\",\n    \"expired\": \"Abgelaufen\",\n    \"fee\": \"Gebühr\",\n    \"swapFee\": \"Tauschgebühr\",\n    \"feeErr\": \"Gebühr kann nicht geschätzt werden. Ist \\\"{{input}}\\\" eine valide LNURL?\",\n    \"foundCashuClipboard\": \"Cashu-Token gefunden\",\n    \"french\": \"Französisch\",\n    \"from\": \"von\",\n    \"fromMint\": \"von folgende Mint\",\n    \"sendingFrom\": \"Senden von\",\n    \"german\": \"Deutsch\",\n    \"github\": \"GitHub\",\n    \"githubIssues\": \"Melden Sie Fehler auf Github\",\n    \"reportIssue\": \"Problem melden\",\n    \"shareOrReport\": \"Feedback teilen oder Fehler melden\",\n    \"historyDeleted\": \"Verlauf gelöscht\",\n    \"invalidInvoice\": \"Rechnung invalid\",\n    \"invalidOrSpent\": \"Invalider Token oder bereits ausgegeben\",\n    \"invalidToken\": \"Token invalid\",\n    \"invoice\": \"Rechnung\",\n    \"invoiceExpired\": \"Rechnung abgelaufen\",\n    \"invoiceInclFee\": \"Rechnung inkl. Gebühr\",\n    \"invoiceOrLnurl\": \"LN Rechnung oder LNURL\",\n    \"invoiceOrLnAddress\": \"Rechnung oder Adresse\",\n    \"keysetID\": \"Schlüsselsatz\",\n    \"language\": \"Sprache\",\n    \"currency\": \"Währung\",\n    \"currencyConversion\": \"Währungsumrechnung\",\n    \"showFiatBalance\": \"Fiat-Guthaben anzeigen\",\n    \"showFiatBalanceDesc\": \"Zeige dein Guthaben und Beträge in deiner gewählten Fiat-Währung an\",\n    \"selectCurrency\": \"Währung auswählen\",\n    \"lastUpdate\": \"Aktualisiert\",\n    \"loadingRates\": \"Wechselkurse werden geladen...\",\n    \"ratesUnavailable\": \"Wechselkurse nicht verfügbar\",\n    \"ratesUnavailableDesc\": \"Wechselkurse konnten nicht geladen werden. Bitte überprüfe deine Internetverbindung und versuche es erneut.\",\n    \"ratesRequiredForFiat\": \"Wechselkurse erforderlich um Fiat-Anzeige zu aktivieren\",\n    \"noCurrenciesAvailable\": \"Keine Währungen verfügbar. Bitte versuche die Wechselkurse erneut zu laden.\",\n    \"retry\": \"Erneut versuchen\",\n    \"lnInvoice\": \"Lightning Rechnung\",\n    \"lnPayment\": \"Lightning Zahlung\",\n    \"mint\": \"Mint\",\n    \"minted\": \"erhalten\",\n    \"multimintSwap\": \"Multimint-Tausch\",\n    \"n/a\": \"Nicht verfügbar\",\n    \"name\": \"Name\",\n    \"no\": \"Nein\",\n    \"noCamAccess\": \"Kein Zugriff auf die Kamera\",\n    \"noFunds\": \"Nicht genügend Guthaben\",\n    \"noFundsForFee\": \"Nicht genug Guthaben, bitte lassen Sie Platz für eventuelle Gebühren: ~{{fee}} Sats\",\n    \"noMint\": \"Keine Mint gefunden\",\n    \"notQrCode\": \"Kein QR-Code!\",\n    \"noTX\": \"Noch keine Transaktionen\",\n    \"activity\": \"Aktivität\",\n    \"allHistory\": \"Alle\",\n    \"optionalMemo\": \"Optionales Memo\",\n    \"paste\": \"Einfügen\",\n    \"paymentPending\": \"Zahlung ausstehend\",\n    \"paymentSuccess\": \"Zahlung erfolgreich!\",\n    \"nostrPaymentSuccess\": \"versendet!\",\n    \"paymentType\": \"Zahlungstyp\",\n    \"payWithLn\": \"Zahle mit deiner LN wallet\",\n    \"preferences\": \"Einstellungen\",\n    \"readme\": \"Lies mich\",\n    \"sender\": \"Absender\",\n    \"recipient\": \"Empfänger\",\n    \"reqTimeout\": \"Timeout für Netzwerkanfragen\",\n    \"restore\": \"Wiederherstellen\",\n    \"save\": \"Speichern\",\n    \"scanAgain\": \"Erneut scannen\",\n    \"scan\": \"Scannen\",\n    \"scanQR\": \"QR scannen\",\n    \"qrScanHint\": \"QR-Code im Rahmen ausrichten\",\n    \"qrScanFormats\": \"Cashu, Lightning, LNURL oder Bitcoin\",\n    \"qrScanReady\": \"Bereit zum Scannen\",\n    \"qrScanPaused\": \"Scan pausiert\",\n    \"animatedQrProgress\": \"Animierter QR-Fortschritt\",\n    \"receivingAnimatedQr\": \"Empfange animierten QR-Code\",\n    \"unsupportedFormat\": \"Nicht unterstütztes Format\",\n    \"cashuPaymentRequestQrUnsupported\": \"Cashu-Zahlungsanfragen werden per QR noch nicht unterstützt\",\n    \"bitcoinAddressPaymentsUnsupported\": \"Bitcoin-Adresszahlungen werden nicht unterstützt\",\n    \"cameraAccessRequired\": \"Kamerazugriff erforderlich\",\n    \"cameraAccessDenied\": \"Kamerazugriff verweigert\",\n    \"cameraAccessRequiredHint\": \"Wir benötigen Kamerazugriff, um QR-Codes für Zahlungen und Token zu scannen.\",\n    \"cameraAccessDeniedHint\": \"Aktiviere den Kamerazugriff in den Geräteeinstellungen, um QR-Codes zu scannen.\",\n    \"allowCameraAccess\": \"Kamerazugriff erlauben\",\n    \"openSettings\": \"Einstellungen öffnen\",\n    \"seconds\": \"Sekunden\",\n    \"selectAmount\": \"Betrag auswählen\",\n    \"selected\": \"Ausgewählt\",\n    \"selectMint\": \"Mint für Zahlung auswählen\",\n    \"selectMints\": \"Mints auswählen\",\n    \"sendEcash\": \"Ecash senden\",\n    \"share\": \"Teilen\",\n    \"submitPaymentReq\": \"Auszahlen\",\n    \"to\": \"bis\",\n    \"today\": \"Heute\",\n    \"tokenInfoErr\": \"Ein Fehler ist aufgetreten während der Token-Info-Abfrage\",\n    \"totalInclFee\": \"Gesamt inkl. Gebühr\",\n    \"reservedTotal\": \"Reservierte Summe\",\n    \"trustMint\": \"Mint vertrauen?\",\n    \"tryLater\": \"Bitte versuchen Sie es später noch einmal.\",\n    \"unknownType\": \"Unbekannter Code-Typ\",\n    \"version\": \"Version\",\n    \"viewMnemonic\": \"Mnemonic anzeigen\",\n    \"wallet\": \"Wallet\",\n    \"willDoLater\": \"Mache ich später\",\n    \"yes\": \"Ja\",\n    \"invalidPubKey\": \"Invalider öffentlicher Schlüssel!\",\n    \"walletLocked\": \"Wallet gesperrt\",\n    \"explainer1\": \"eNuts ist eine treuhänderische Lightning-Wallet, die private und sofortige Transaktionen mit dem Cashu-Protokoll ermöglicht. Ihre Gelder werden von Mints verwaltet, mit denen Sie interagieren, und Ecash wird lokal auf Ihrem Gerät gespeichert.\",\n    \"explainer2\": \"Cashu ist ein neues Ecash-Protokoll für treuhänderische Bitcoin-Apps, bei denen Mints nur Lightning-Knoten sind, die Bitcoin-Transaktionen durchführen und Ihnen Ecash zur Verfügung stellen. Seien Sie versichert, die Mints bleiben unwissend über Ihre Ecash-Zahlungen.\",\n    \"explainer3\": \"Fügen Sie einfach eine Mint über die URL hinzu und zahlen Sie eine Lightning-Rechnung, um Ecash zu erhalten. eNuts führt Sie, ermöglicht Ihnen sofortiges Empfangen von jedem und fügt automatisch verbundene Mints hinzu – mit Ihrer Zustimmung. Tauschen Sie Guthaben zwischen Mints aus und senden Sie Ecash, sobald Sie ein Guthaben haben.\",\n    \"send&receive\": \"Senden & Empfangen\",\n    \"contactsNostr\": \"Kontakte & Nostr\",\n    \"nostrExplainer\": \"Die Nostr-Implementierung ermöglicht eine reibungslose Synchronisierung Ihrer Kontakte, ohne dass Sie Ihren privaten Schlüssel eingeben müssen, da wir einen neuen für Sie generieren. Ihre Daten werden mithilfe des öffentlichen Schlüssels angezeigt, während der neue private Schlüssel Ihre Nachrichten verschlüsselt/entschlüsselt.\",\n    \"send\": \"Senden\",\n    \"sendEcashDashboard\": \"Erstellen Sie ein Cashu-Token und senden Sie es an jeden beliebigen.\",\n    \"payInvoiceDashboard\": \"Senden Sie Ihr Guthaben von einer Mint an eine Lightning-Node.\",\n    \"receiveEcashDashboard\": \"Fügen Sie ein Cashu-Token aus Ihrer Zwischenablage ein.\",\n    \"receiveEcashNostr\": \"Nostr Nachrichten\",\n    \"receiveEcashNostrHint\": \"Überprüfen Sie Ihre Nostr Nachrichten auf eingehende Cashu-Token.\",\n    \"createInvoiceDashboard\": \"Empfangen Sie Ecash von einer Mint, indem Sie eine Lightning-Rechnung bezahlen.\",\n    \"hideNuts\": \"Gesamtsaldo verbergen\",\n    \"checkingDms\": \"Ihre Nachrichten werden auf Ecash überprüft...\",\n    \"clearOverHere\": \"Sie sind auf dem neusten Stand!\",\n    \"totalDmsReceived\": \"Sie haben {{totalDms}} Cashu token erhalten.\",\n    \"swapNow\": \"Jetzt tauschen\",\n    \"swap\": \"Tausch\",\n    \"emptyMint\": \"Kein Guthaben vorhanden\",\n    \"zapSoon\": \"Zaps werden bald hinzugefügt...\",\n    \"enutsPub\": \"eNuts: \",\n    \"seeFullHistory\": \"Gesamter Transaktionsverlauf\",\n    \"next\": \"Weiter\",\n    \"skip\": \"Überspringen\",\n    \"donateLn\": \"Spenden\",\n    \"supportHint\": \"Jeder Beitrag, ganz gleich in welcher Höhe, hat eine bedeutende Auswirkung. Die Bestätigungsseite befindet sich in der Entwicklung.\",\n    \"newToken\": \"Neuer Cashu Token\",\n    \"disclaimerHint\": \"Dieser Haftungsausschluss sollte ernst genommen und nicht ignoriert oder unterschätzt werden. Wir schätzen Ihr Interesse an diesem Projekt und werden weiterhin daran arbeiten, es zu verbessern.\",\n    \"searchContacts\": \"Suchen oder NPUB eingeben\",\n    \"submit\": \"Hinzufügen\",\n    \"clearMetadataCache\": \"Metadata Cache bereinigen\",\n    \"clearMetadataCacheHint\": \"Metadatencache löschen?\",\n    \"clearImageCache\": \"Bilder Cache bereinigen\",\n    \"clearImageCacheHint\": \"Bildercache löschen?\",\n    \"pullRefresh\": \"Zum Aktualisieren ziehen\",\n    \"processTestPay\": \"Testzahlung wird ausgeführt...\",\n    \"confirmMint\": \"Mint bestätigen\",\n    \"confirmMintHint\": \"Sind Sie sicher, dass Sie diese Mint hinzufügen möchten?\",\n    \"npubAlreadyAdded\": \"NPUB bereits hinzugefügt\",\n    \"replaceNpub\": \"NPUB ersetzen\",\n    \"replaceNpubTxt\": \"Ein NPUB ist bereits vorhanden. Möchten Sie ihn ersetzen?\",\n    \"npubAdded\": \"NPUB hinzugefügt!\",\n    \"showContacts\": \"Kontakte ansehen\",\n    \"topUpNow\": \"Jetzt Ecash anfordern\",\n    \"scanAnother\": \"Weiteren QR-Code scannen\",\n    \"deleteNpub\": \"NPUB löschen?\",\n    \"delNpubHint\": \"Alle Kontakte und zugehörigen Daten werden gelöscht.\",\n    \"addNewNpub\": \"Neuen NPUB hinzufügen?\",\n    \"addNpubHint\": \"Dadurch werden alle Daten, die mit Ihrem aktuellen NPUB verbunden sind, gelöscht.\",\n    \"zap\": \"Zap\",\n    \"zapNow\": \"Zap\",\n    \"meltNostrProfileHint\": \"Senden Sie Ihr Guthaben zu der LN-Adresse, die mit Ihrem Nostr-Profil verknüpft ist.\",\n    \"nostrDmHint\": \"eNuts kann nicht auf Ihre Nostr-Nachrichten zugreifen, da es keinen Zugriff auf Ihren privaten Schlüssel hat. Stattdessen generiert es einen neuen Schlüssel zum Senden von Ecash. Wenn Sie Ecash über Nostr senden, erhält der Empfänger es mit Ihrem neuen öffentlichen eNuts-Schlüssel. Wenn der Empfänger auf die Nachricht mit einem Ecash-Token antwortet, wird es hier angezeigt. Wir arbeiten aktiv an einer sicheren Lösung für private Schlüssel.\",\n    \"nostrIssueHeader\": \"Nostr-Kontaktproblem\",\n    \"nostrIssueHint\": \"Wenn Sie Schwierigkeiten haben, Ihre Nostr-Kontakte zu öffnen, klicken Sie auf die Schaltfläche unten oder setzen Sie die Nostr-Daten zurück in \\\"Optionen > Kontakte > Daten zurücksetzen\\\", um das Problem zu lösen.\",\n    \"submitNostrIssue\": \"Daten zurücksetzen\",\n    \"nostrIssueSuccess\": \"Nostr-Daten erfolgreich zurückgesetzt!\",\n    \"createLnInvoice\": \"Lightning Rechnung erstellen\",\n    \"metadataCacheCleared\": \"Metadatencache gelöscht!\",\n    \"imageCacheCleared\": \"Bildercache gelöscht!\",\n    \"leaveGithubStar\": \"Mit GitHub-Stern unterstützen\",\n    \"alreadySpentHint\": \"Einige Beweise in Ihrem Guthaben wurden anderswo ausgegeben oder beansprucht. Beheben Sie dies, indem Sie sie die betroffenen Beweise unter 'Optionen' > 'Mint-Management' > 'Beweise überprüfen' löschen.\",\n    \"useNpub\": \"NPUB verwenden\",\n    \"autoSwapToDefaulMint\": \"Auto-Tausch zu Standard-Mint\",\n    \"trustMintOpt\": \"Mint vertrauen\",\n    \"swapHint\": \"Diese Option erfordert eine Lightning-Zahlung, bringt Gebühren mit sich und kann die unbekannte Mint dennoch zur Liste hinzufügen, wenn eine Gebühren-Rückzahlung erfolgt.\",\n    \"trustHint\": \"Die mit dem Token verbundene Mint wird zu Ihrer Vertrauensliste hinzugefügt.\",\n    \"noDefaultHint\": \"Sie müssen eine Standard-Mint einrichten, um einen automatischen Tausch durchzuführen.\",\n    \"autoSwapSuccess\": \"Tausch erfolgreich!\",\n    \"paidInvoice\": \"{{ count }} Rechnung wurde mit einem Gesamtbetrag von {{ total }} Sats bezahlt\",\n    \"paidInvoices\": \"{{ count }} Rechnungen wurden mit einem Gesamtbetrag von {{ total }} Sats bezahlt\",\n    \"checkPayment\": \"Zahlung überprüfen\",\n    \"lnPaymentSpamHint\": \"Bitte warten Sie {{ remainingSeconds }} Sekunden um die Mint zu entlasten.\",\n    \"supportUs\": \"Unterstütze uns\",\n    \"shareEnuts\": \"Teile eNuts mit jemandem\",\n    \"justNow\": \"Gerade eben\",\n    \"hoursAgo\": \"vor {{count}} Stunden\",\n    \"yesterday\": \"Gestern\",\n    \"awaitingPayment\": \"Warte auf Zahlung\",\n    \"receivedFromMint\": \"Von Mint erhalten\",\n    \"status\": \"Status\",\n    \"unit\": \"Einheit\",\n    \"quoteId\": \"Angebots-ID\",\n    \"nfcPaymentLimits\": \"Zahlungslimits\",\n    \"nfcPaymentLimitsDesc\": \"Standard- und benutzerdefinierte Beträge für NFC-Zahlungen festlegen\",\n    \"amountLimits\": \"Betragsgrenzwerte\",\n    \"amountLimitsDesc\": \"Tippen um Standard zu setzen, lange drücken zum Löschen\",\n    \"noLimit\": \"Kein Limit\",\n    \"noLimitDesc\": \"Jeden Betrag bestätigen\",\n    \"deleteAmount\": \"Betrag löschen\",\n    \"deleteAmountConfirm\": \"Möchten Sie {{amount}} Sats wirklich aus Ihren Schnellauswahlbeträgen entfernen?\",\n    \"delete\": \"Löschen\",\n    \"resetToDefaults\": \"Auf Standard zurücksetzen\"\n  },\n  \"error\": {\n    \"checkSpendableErr\": \"Fehler beim Überprüfen, ob der Token ausgegeben werden kann\",\n    \"claimTokenErr\": \"Fehler beim Beanspruchen des Tokens\",\n    \"sendTokenErr\": \"Fehler beim Senden des Tokens\",\n    \"header\": \"Ein Fehler ist aufgetreten\",\n    \"msg\": \"Es tut uns leid, dass dieses Problem bei Ihnen aufgetreten ist. Sie können uns helfen, die Software zu verbessern, indem Sie einen Screenshot machen und einen kurzen Fehlerbericht erstellen.\",\n    \"reportBug\": \"Fehler melden\",\n    \"requestMintErr\": \"Fehler beim Abrufen der Rechnung von der Mint.\",\n    \"stackNA\": \"Ursprung des Fehlers nicht verfügbar\",\n    \"generalMeltingErr\": \"Die Mint konnte keine geeignete Lightning-Zahlungsroute zu Ihrer Node finden.\",\n    \"invoiceFromLnurlError\": \"Es konnte keine Rechnung erstellt werden mit deiner LNURL.\",\n    \"invoiceScanError\": \"Die gescannte Rechnung konnte nicht bearbeitet werden.\"\n  },\n  \"history\": {\n    \"checkSpent\": \"Überprüfen ob Token ausgegeben wurde\",\n    \"isPending\": \"Token steht aus\",\n    \"isSpent\": \"Token wurde ausgegeben\",\n    \"justNow\": \"Gerade eben\",\n    \"hoursAgo\": \"vor {{count}} Stunden\",\n    \"yesterday\": \"Gestern\",\n    \"memo\": \"Memo\",\n    \"nHrsAgo\": \"Vor {{hrs}} Stunden\",\n    \"nMinsAgo\": \"Vor {{mins}} Minuten\",\n    \"noMemo\": \"Keine Memo\",\n    \"oneHrAgo\": \"Vor einer Stunde\",\n    \"oneMinAgo\": \"Vor 1 Minute\",\n    \"paymentHash\": \"Zahlungs-Hash\",\n    \"settleTime\": \"Zeitpunkt\",\n    \"showQr\": \"QR-Code anzeigen\",\n    \"receive\": \"Empfangen\",\n    \"send\": \"Senden\",\n    \"melt\": \"Schmelzen\",\n    \"receivedEcash\": \"Ecash empfangen\",\n    \"sentEcash\": \"Ecash gesendet\",\n    \"paidInvoice\": \"Rechnung bezahlt\",\n    \"details\": \"Details\",\n    \"date\": \"Datum\",\n    \"amount\": \"Betrag\",\n    \"token\": \"Token\"\n  },\n  \"mints\": {\n    \"addCustomName\": \"Benutzerdefinierten Namen hinzufügen\",\n    \"additionalInfo\": \"Zusätzliche Informationen\",\n    \"addMintBtn\": \"Mint hinzufügen\",\n    \"addNewMint\": \"Neue Mint hinzufügen\",\n    \"atLeast2Mints\": \"Sie brauchen mindestens 2 Mints um einen Multimint-Tausch auszuführen.\",\n    \"awaitingInvoice\": \"Rechnung ausstehend.\",\n    \"cashOutAmountHint\": \"Es können Lightning-Gebühren anfallen, daher wird eine geschätzte Gebühr hinzugefügt und eventuell zu viel gezahlte Gebühren werden erstattet.\",\n    \"checkProofs\": \"Beweise überprüfen\",\n    \"checkProofsQ\": \"Alle Beweise überprüfen?\",\n    \"checkProofsTxt\": \"Dadurch wird überprüft, ob Ihre Token ausgegeben werden können und werden andernfalls gelöscht.\",\n    \"chooseMeltMintHint\": \"Wählen Sie eine Mint aus, von der aus Sie Ihre Gelder abheben möchten.\",\n    \"chooseMintHint\": \"Wählen Sie eine Mint aus, von der Sie Ecash erhalten möchten. Die Mint wird zum Verwalter Ihrer Gelder.\",\n    \"chooseTarget\": \"Wählen Sie den Empfänger der Zahlung aus.\",\n    \"coinSelectionHint\": \"Ihr Ecash-Guthaben ist im Wesentlichen eine Sammlung von Coin-sets. Die Coin Auswahl ermöglicht es Ihnen, die Coins auszuwählen, die Sie ausgeben möchten. Coin-sets erhalten von der Mint eine Schlüsselsatz-ID, die sich im Laufe der Zeit ändern kann. Neu hinzugefügte Sets werden grün hervorgehoben. Es wird empfohlen, zuerst ältere Sets auszugeben.\",\n    \"creatingEcashToken\": \"Der Cashu-Token wird erstellt.\",\n    \"sendingEcashViaNostr\": \"Der Cashu-Token wird via Nostr versendet!\",\n    \"customName\": \"Benutzerdefinierter Name\",\n    \"cutomNameAdded\": \"Benutzerdefinierter Name hinzugefügt\",\n    \"dangerZone\": \"Gefahrenzone\",\n    \"deletedProofs\": \"{{proofsToDel}} Beweise gelöscht.\",\n    \"delMint\": \"Mint löschen\",\n    \"delMintSure\": \"Mint löschen?\",\n    \"ecashAmountHint\": \"Wählen Sie den Betrag an Ecash aus, den Sie senden möchten.\",\n    \"editMintName\": \"Mint Name bearbeiten\",\n    \"errDelProofs\": \"Etwas ist schief gelaufen während dem Löschen der Beweise.\",\n    \"funds\": \"Guthaben\",\n    \"general\": \"Allgemein\",\n    \"importantNotice\": \"Wichtiger Hinweis\",\n    \"inputField\": \"Lightning-Rechnung oder LNURL\",\n    \"invalidUrl\": \"URL invalid\",\n    \"invoiceAmountHint\": \"Wählen Sie den Betrag an Ecash aus, den Sie erhalten möchten. Die Mint wird eine Rechnung erstellen, die Sie mit einer Lightning-Wallet bezahlen müssen.\",\n    \"invoiceHint\": \"Das kann einige Sekunden dauern...\",\n    \"lowBal\": \"Kein Guthaben verfügbar\",\n    \"metadata\": \"Metadaten\",\n    \"meltAddressbookHint\": \"Wählen Sie Ihre eigene LNURL oder einen anderen Kontakt als Zahlungsempfänger aus.\",\n    \"meltInputHint\": \"Fügen Sie eine Lightning-Rechnung, LNURL oder Lightning Adresse ein.\",\n    \"meltScanQRHint\": \"Erstellen Sie eine Lightning-Rechnung mit einem anderen Gerät und scannen Sie sie einfach.\",\n    \"meltSwapHint\": \"Wählen Sie eine andere Mint aus Ihrer vertrauenswürdigen Liste als Zahlungsempfänger aus.\",\n    \"copyShareToken\": \"Kopieren & teilen\",\n    \"copyShareTokenHint\": \"Kopieren Sie den Ecash-Token und teilen Sie ihn über eine Messenger App.\",\n    \"sendNostr\": \"Senden via Nostr\",\n    \"sendNostrHint\": \"Senden Sie Ecash ohne Umwege an eins Ihrer Kontakte in Nostr.\",\n    \"meltToken\": \"Auszahlen\",\n    \"mintConnectionFail\": \"Verbindung zu Mint fehlgeschlagen\",\n    \"mintInfo\": \"Mint Info\",\n    \"mintNewTokens\": \"Erhalte Ecash\",\n    \"mintNoContact\": \"Diese Mint verfügt über keine Kontakt Informationen\",\n    \"mntAlreadyAdded\": \"Mint bereits vorhanden\",\n    \"noAdditional\": \"Diese Mint verfügt über keine zusätzlichen Informationen\",\n    \"noInfo\": \"Keine Informationen verfügbar\",\n    \"noProofs\": \"Diese Mint verfügt über keine Beweise.\",\n    \"paymentOverview\": \"Zahlungsübersicht\",\n    \"processingPaymentByMint\": \"Die Mint bearbeitet die Zahlung gemäß Ihrem Antrag\",\n    \"processingSwap\": \"Verarbeitung eines Multimint-Swaps gemäß Ihrem Antrag\",\n    \"pubKey\": \"Öffentlicher Schlüssel\",\n    \"removeDefault\": \"Standard zurücksetzen\",\n    \"scanQR\": \"QR-Code scannen\",\n    \"sendEcashHint\": \"Wählen Sie eine Mint aus, aus der Sie gerne einen Cashu-Token erstellen möchten.\",\n    \"setDefault\": \"Als Standard-Mint festlegen\",\n    \"supportedNuts\": \"Unterstütze NUTs\",\n    \"swapNotAllowed\": \"Multimint-Tausch von einer Test-Mint ist nicht möglich.\",\n    \"zapNotAllowed\": \"Zap von einer Test-Mint ist nicht möglich.\",\n    \"testMintHint\": \"Dies ist eine Test-Mint für Simulationszwecke. Trotzdem hinzufügen?\",\n    \"trustMintSure\": \"Mint vertrauen?\",\n    \"updatedDefault\": \"Änderungen gespeichert\",\n    \"newMintAdded\": \"Mint hinzugefügt!\",\n    \"newMintAddedQuestion\": \"Möchten Sie jetzt Ecash empfangen?\",\n    \"selectSwapReceiver\": \"Wählen Sie eine Mint als Zahlungsempfänger aus.\",\n    \"prepairZapData\": \"Transaktionsdaten werden vorbereitet...\",\n    \"lastUpdated\": \"Zuletzt aktualisiert\",\n    \"mintInfoUpdated\": \"Mint-Info aktualisiert!\",\n    \"mintInfoUpdateFailed\": \"Fehler beim Aktualisieren der Mint-Info\",\n    \"npcSettings\": \"Lightning address\",\n    \"npcDefaultAccount\": \"Default\",\n    \"npcTapToCopy\": \"Tap to copy\",\n    \"npcUsernameLabel\": \"Custom username\",\n    \"npcUsernamePlaceholder\": \"optional username\",\n    \"npcPurchaseUsername\": \"Save username\",\n    \"npcSetUsername\": \"Set Username\",\n    \"npcRequestUsername\": \"Request username\",\n    \"npcUsernameFeePrompt\": \"Do you want to set this username for a fee of {{amount}} sats?\",\n    \"npcReceiveTitle\": \"NPC Lightning addresses\",\n    \"npcReceiveHint\": \"Receive Lightning payments into your local Cashu wallet.\",\n    \"npcAccountsLabel\": \"Accounts\",\n    \"npcLocalBalance\": \"Local balance\",\n    \"npcReceiveAddress\": \"Receive address\",\n    \"npcSeedKey\": \"Seed key\",\n    \"npcImportedKey\": \"Imported key\",\n    \"npcActive\": \"Active\",\n    \"npcSyncing\": \"Syncing\",\n    \"npcPaused\": \"Paused\",\n    \"npcNpubFallback\": \"Using your npub until a username is saved\",\n    \"npcSyncAll\": \"Sync all\",\n    \"npcSynced\": \"NPC account synced\",\n    \"npcAccountAdded\": \"NPC account added\",\n    \"npcAccountRemoved\": \"NPC account removed\",\n    \"npcUsernameSaved\": \"Username saved\",\n    \"npcAddAccountTitle\": \"Add NPC account\",\n    \"npcAddAccountHint\": \"Import an existing Nostr key or derive a new key from your seed.\",\n    \"npcPrivateKeyLabel\": \"Private key\",\n    \"npcPrivateKeyPlaceholder\": \"nsec or hex\",\n    \"npcPrivateKeyHint\": \"Imported keys are stored in secure storage on this device.\",\n    \"npcPrivateKeyRequired\": \"Enter an nsec or hex private key.\",\n    \"npcImportPrivateKey\": \"Import private key\",\n    \"npcDeriveAccount\": \"Derive new key\"\n  },\n  \"topNav\": {\n    \"about\": \"Über uns\",\n    \"addressBook\": \"Adressbuch\",\n    \"advancedFunctions\": \"Erweiterte Funktionen\",\n    \"display\": \"Anzeige\",\n    \"history\": \"Transaktionsverlauf\",\n    \"language\": \"Sprache\",\n    \"currency\": \"Währung\",\n    \"mintSettings\": \"Mint Management\",\n    \"nfcSettings\": \"NFC Einstellungen\",\n    \"npcSettingsTitle\": \"Lightning address\",\n    \"security\": \"Sicherheit\",\n    \"settings\": \"Optionen\",\n    \"privacy\": \"Privatsphäre\",\n    \"general\": \"Allgemein\"\n  },\n  \"wallet\": {\n    \"cashuContent\": \"Die Autoren von Cashu und eNuts sind keine Kryptografen und das Cashu-Protokoll wird noch überprüft. Es bestehen Bedenken hinsichtlich möglicher schwerwiegender Mängel. Daher ist Cashu noch nicht für den produktiven Einsatz bereit.\",\n    \"cashuExperiment\": \"Cashu ist immer noch experimentell.\",\n    \"claiming\": \"Überprüft...\",\n    \"processingInvoice\": \"Rechnung wird verarbeitet...\",\n    \"nfcPayment\": \"NFC-Zahlung\",\n    \"nfcKeepNearTerminal\": \"Halten Sie Ihr Telefon in die Nähe des Terminals\",\n    \"nfcSelectMaxAmount\": \"Maximalbetrag auswählen\",\n    \"noLimit\": \"Kein Limit\",\n    \"custodialRisk\": \"Verwahrrisiko, Mints halten die Schlüssel.\",\n    \"custodialRiskContent\": \"Mit eNuts haben Sie nicht die Kontrolle über die Bitcoin-Schlüssel; die Mint fungiert als Verwahrer. Wenn Sie einer Mint nicht vertrauen, ist es ratsam, nicht mit ihr zu interagieren.\",\n    \"disclaimer\": \"Bitte beachten Sie, dass es sich hierbei um eine Beta-Version in einem frühen Stadium handelt und diese noch vor der offiziellen Veröffentlichung getestet wird. Die Software und alle darauf enthaltenen Inhalte werden als „wie besehen“ und „wie verfügbar“ bereitgestellt. Wir geben keine Garantien, ob ausdrücklich oder stillschweigend, hinsichtlich der Eignung oder Verwendbarkeit der Software oder deren Inhalte.\",\n    \"enutsDisclaimer\": \"eNuts ist unvollendete Beta-Software.\",\n    \"lossContent\": \"Cashu-Token sind Inhabertoken, was bedeutet, dass es derzeit keine Möglichkeit zur Wiederherstellung gibt, wenn Sie den Zugriff darauf verlieren. eNuts speichert Ihre Token auf Ihrem Gerät. Stellen Sie vor dem Löschen der App sicher, dass Sie Ihre Token gesichert haben.\",\n    \"lossOfTokens\": \"Verlust von Geldern.\",\n    \"enutsMint\": \"Die standardmäßige eNuts-Mint\",\n    \"mintDisclaimer\": \"Die Verwendung der standardmäßigen eNuts-Mint erfolgt vollständig auf eigenes Risiko. Wir empfehlen dringend, Vorsicht walten zu lassen und sie nur für experimentelle oder Bildungszwecke zu nutzen. Es gibt keine Garantien hinsichtlich ihrer Funktionalität, Sicherheit oder Verfügbarkeit, und sie kann ohne Vorankündigung verschwinden. Einlagen, die in diese Mint getätigt werden, sollten als Spenden betrachtet werden und können möglicherweise nicht zurückgegeben werden, sondern eventuell für die Weiterentwicklung verwendet werden. Seien Sie sich der mit Beta-Software verbundenen Risiken bewusst, und es liegt in Ihrer Verantwortung, Ihre Vermögenswerte beim Gebrauch dieser Mint zu schützen.\",\n    \"paidOut\": \"Ausbezahlt\",\n    \"pasteToken\": \"Ecash einlösen\",\n    \"payInvoice\": \"Rechnung bezahlen\",\n    \"payLNInvoice\": \"Lightning Rechnung bezahlen\",\n    \"receive\": \"Empfangen\",\n    \"send\": \"Senden\",\n    \"sent\": \"Ausgezahlt\",\n    \"proofs\": \"Beweise\",\n    \"swapped\": \"Getauscht\"\n  }\n}\n"
  },
  {
    "path": "assets/translations/en.json",
    "content": "{\n  \"addrBook\": {\n    \"addOwnNpub\": \"Add your NPUB\",\n    \"favorite\": \"Favorite\",\n    \"removeFav\": \"Remove favorite\",\n    \"copyNpub\": \"Copy NPUB\",\n    \"npubCopied\": \"NPUB copied!\",\n    \"receiverNoLnurl\": \"Recipient has no LNURL\",\n    \"noResults\": \"No results\"\n  },\n  \"auth\": {\n    \"confirmAction\": \"Please confirm the action.\",\n    \"createPin\": \"Create PIN\",\n    \"editPin\": \"Edit PIN\",\n    \"pinMismatch\": \"Incorrect PIN!\",\n    \"pinSetup\": \"You can optionally setup a PIN to secure your app.\",\n    \"pleaseConfirm\": \"Please confirm your PIN.\",\n    \"pleaseConfirmNewPin\": \"Please confirm your new PIN.\",\n    \"pleaseEnter\": \"Please enter your PIN now.\",\n    \"pleaseNewPin\": \"Please enter a new PIN now.\",\n    \"removePin\": \"Delete PIN\",\n    \"welcome\": \"Welcome\",\n    \"welcomeBack\": \"Welcome back!\"\n  },\n  \"bottomNav\": {\n    \"wallet\": \"Wallet\",\n    \"contacts\": \"Contacts\"\n  },\n  \"common\": {\n    \"confirmReset\": \"Reset wallet\",\n    \"copy\": \"Copy\",\n    \"cycle\": \"Cycle\",\n    \"findMint\": \"Find a mint\",\n    \"manualCounterIncrease\": \"Increase counters\",\n    \"manualCounterIncreaseHint\": \"The counters increment automatically after each transaction, but in rare cases, this may fail, leading to errors during the restoration process. Manually raising the counters can resolve the state.\",\n    \"increaseCounterHint\": \"Are you sure you want to increase the counters? This should only be done if you are sure that the counters are out of sync.\",\n    \"noMintForCounter\": \"You have no mints to increase the counters for.\",\n    \"counterIncreased\": \"Counters increased by {{counterIncreased}}!\",\n    \"doneSafety\": \"Almost done... Safety check\",\n    \"noProofsRestored\": \"Found no proofs to restore your wallet.\",\n    \"restoreErr\": \"Something went wrong while restoring your wallet.\",\n    \"dontClose\": \"Please do not close the app during the process.\",\n    \"recoveryHint\": \"Write or paste your 12-word mnemonic in the right order, separated by blank spaces.\",\n    \"walletRecovery\": \"Wallet Recovery\",\n    \"walletRecoveryHint\": \"Use a backup seed to restore your wallet.\",\n    \"seedBackup\": \"Seed Backup\",\n    \"12WordMnemonic\": \"12-word mnemonic\",\n    \"secureWallet\": \"Secure wallet\",\n    \"secureWalletHint\": \"Generate and write down a seed backup to secure your wallet.\",\n    \"quickWallet\": \"Quick wallet\",\n    \"quickWalletHint\": \"Create a new wallet instantly. Backup seed can be generated later.\",\n    \"skipSeedHint\": \"You can skip this process and generate a seed backup later.\",\n    \"mnemonicHint\": \"The seed phrase will never be shown again. Write it down and never share it with anyone.\",\n    \"confirmMnemonicErr\": \"Wrong word! Please make sure to write down your seed phrase correctly in the right order.\",\n    \"selectRestoreMint\": \"Please select the mint that will be used to restore your funds.\",\n    \"recoveringWallet\": \"The mint is restoring your funds...\",\n    \"seedEnabled\": \"Seed recovery enabled!\",\n    \"confirmSeed\": \"Please confirm your seed by typing the correct word.\",\n    \"about\": \"About\",\n    \"aboutToLeaveTo\": \"You are about to leave\",\n    \"accept\": \"Accept\",\n    \"amount\": \"Amount\",\n    \"back\": \"Back\",\n    \"backToDashboard\": \"Back to dashboard\",\n    \"balance\": \"Balance\",\n    \"balanceAfterTX\": \"Mint balance after TX\",\n    \"balTooLow\": \"Balance too low\",\n    \"bigQrMsg\": \"The amount of data is too big for a QR code.\",\n    \"calculateFeeEst\": \"Calculating fee\",\n    \"cancel\": \"Cancel\",\n    \"cashOut\": \"Cash out\",\n    \"cashOutFromMint\": \"Cash out from mint\",\n    \"change\": \"Change\",\n    \"claimed\": \"claimed\",\n    \"restored\": \"restored\",\n    \"claimSuccess\": \"Claimed {{amount}} Sats:\\n{{mintUrl}}\\nMemo: {{memo}}\",\n    \"claimToken\": \"Claim token\",\n    \"clear\": \"Clear\",\n    \"clipboardInvalid\": \"Your clipboard contains an invalid Cashu token!\",\n    \"coinSelection\": \"Coin selection\",\n    \"confirm\": \"Confirm\",\n    \"contact\": \"Contact\",\n    \"mintDelErr\": \"Unable to remove a mint with remaining balance\",\n    \"continue\": \"Continue\",\n    \"copied\": \"Copied\",\n    \"shareInvoice\": \"Share invoice\",\n    \"copyToken\": \"Copy token\",\n    \"createInvoice\": \"Create invoice\",\n    \"createToken\": \"Create Token\",\n    \"createTokenErr\": \"Could not create a cashu token. Please try again later.\",\n    \"eventError\": \"Something went wrong while publishing the event.\",\n    \"createViaLn\": \"Create Invoice\",\n    \"darkMode\": \"Dark mode\",\n    \"lightMode\": \"Light mode\",\n    \"autoMode\": \"Auto mode\",\n    \"dbErr\": \"Something went wrong while initializing the DB!\",\n    \"deepLinkErr\": \"Link could not be opened\",\n    \"default\": \"Default\",\n    \"delHistory\": \"Delete history\",\n    \"factoryReset\": \"Factory reset\",\n    \"delHistoryErr\": \"Could not delete the history.\",\n    \"delHistoryQ\": \"Delete history?\",\n    \"resetQ\": \"Reset your wallet?\",\n    \"delHistoryTxt\": \"The data can not be retrieved afterwards.\",\n    \"display\": \"Display\",\n    \"disclaimer\": \"Disclaimer\",\n    \"restoreBattery\": \"At least 20% battery.\",\n    \"restoreBatteryHint\": \"We recommend that you have at least 20% battery before starting the recovery process. Depending on the amount of data, the process may take a while.\",\n    \"restoreWifi\": \"Use Wi-Fi.\",\n    \"restoreWifiHint\": \"We recommend that you use a stable Wi-Fi connection for the recovery process to avoid any interruptions and to ensure a fast and secure recovery.\",\n    \"restoreForeground\": \"Keep the app in the foreground.\",\n    \"restoreForegroundHint\": \"Please keep the app in the foreground and do not close it during the recovery process to avoid any interruptions.\",\n    \"seedMigrationHint\": \"The seed applies to all mints, but each needs an individual restore, so note down frequently used mint URLs. If you have a balance but no seed yet, create a token from a desired mint and self-claim it after generating a new seed. Repeat for each mint you wish to backup.\",\n    \"ecashPayment\": \"Ecash payment\",\n    \"english\": \"English\",\n    \"swahili\": \"Swahili\",\n    \"spanish\": \"Spanish\",\n    \"hungarian\": \"Hungarian\",\n    \"italian\": \"Italian\",\n    \"russian\": \"Russian\",\n    \"thai\": \"Thai\",\n    \"chinese simplified\": \"Chinese (Simplified)\",\n    \"chinese traditional\": \"Chinese (Traditional)\",\n    \"enutsRandD\": \"eNuts Telegram\",\n    \"estimatedFees\": \"Estimated fees\",\n    \"estimateFee\": \"Estimate fee\",\n    \"expired\": \"Expired\",\n    \"fee\": \"Fee\",\n    \"swapFee\": \"Swap fee\",\n    \"feeErr\": \"Unable to estimate fee. Is \\\"{{input}}\\\" a valid LNURL?\",\n    \"foundCashuClipboard\": \"Cashu token detected\",\n    \"french\": \"French\",\n    \"from\": \"from\",\n    \"fromMint\": \"from the following mint\",\n    \"sendingFrom\": \"Sending from\",\n    \"german\": \"German\",\n    \"github\": \"GitHub\",\n    \"githubIssues\": \"Report bugs on Github\",\n    \"reportIssue\": \"Report an issue\",\n    \"shareOrReport\": \"Share feedback or report bugs\",\n    \"historyDeleted\": \"History deleted\",\n    \"invalidInvoice\": \"Invalid invoice\",\n    \"invalidOrSpent\": \"Token invalid or already claimed\",\n    \"invalidToken\": \"Invalid token\",\n    \"invoice\": \"Invoice\",\n    \"invoiceExpired\": \"Invoice expired\",\n    \"invoiceInclFee\": \"Invoice incl. fee\",\n    \"invoiceOrLnurl\": \"LN invoice or LNURL\",\n    \"invoiceOrLnAddress\": \"Invoice or Address\",\n    \"keysetID\": \"Keyset ID\",\n    \"language\": \"Language\",\n    \"currency\": \"Currency\",\n    \"currencyConversion\": \"Currency Conversion\",\n    \"showFiatBalance\": \"Show fiat balance\",\n    \"showFiatBalanceDesc\": \"Display your balance and amounts in your selected fiat currency\",\n    \"selectCurrency\": \"Select Currency\",\n    \"lastUpdate\": \"Updated\",\n    \"loadingRates\": \"Loading exchange rates...\",\n    \"ratesUnavailable\": \"Exchange rates unavailable\",\n    \"ratesUnavailableDesc\": \"Unable to load exchange rates. Please check your internet connection and try again.\",\n    \"ratesRequiredForFiat\": \"Exchange rates required to enable fiat display\",\n    \"noCurrenciesAvailable\": \"No currencies available. Please retry loading exchange rates.\",\n    \"retry\": \"Retry\",\n    \"lnInvoice\": \"Lightning invoice\",\n    \"lnPayment\": \"Lightning payment\",\n    \"mint\": \"Mint\",\n    \"minted\": \"minted\",\n    \"multimintSwap\": \"Multimint swap\",\n    \"n/a\": \"Not available\",\n    \"name\": \"Name\",\n    \"no\": \"No\",\n    \"noCamAccess\": \"No access to camera\",\n    \"noFunds\": \"Not enough funds\",\n    \"noFundsForFee\": \"Not enough funds, please leave room for potential fees: ~{{fee}} Sats\",\n    \"noMint\": \"Found no mint\",\n    \"notQrCode\": \"Not a QR code!\",\n    \"noTX\": \"No transactions yet\",\n    \"activity\": \"Activity\",\n    \"allHistory\": \"All\",\n    \"optionalMemo\": \"Optional memo\",\n    \"paste\": \"Paste\",\n    \"paymentPending\": \"Payment pending\",\n    \"paymentSuccess\": \"Payment successful!\",\n    \"nostrPaymentSuccess\": \"sent!\",\n    \"paymentType\": \"Payment type\",\n    \"payWithLn\": \"Pay with your LN wallet\",\n    \"preferences\": \"Preferences\",\n    \"readme\": \"Read me\",\n    \"sender\": \"Sender\",\n    \"recipient\": \"Recipient\",\n    \"reqTimeout\": \"Network request timeout\",\n    \"restore\": \"Restore\",\n    \"save\": \"Save\",\n    \"scanAgain\": \"Scan Again\",\n    \"scan\": \"Scan\",\n    \"scanQR\": \"Scan QR\",\n    \"qrScanHint\": \"Place the QR code inside the frame\",\n    \"qrScanFormats\": \"Cashu, Lightning, LNURL, or Bitcoin\",\n    \"qrScanReady\": \"Ready to scan\",\n    \"qrScanPaused\": \"Scan paused\",\n    \"animatedQrProgress\": \"Animated QR progress\",\n    \"receivingAnimatedQr\": \"Receiving animated QR\",\n    \"unsupportedFormat\": \"Unsupported format\",\n    \"cashuPaymentRequestQrUnsupported\": \"Cashu payment requests are not supported from QR yet\",\n    \"bitcoinAddressPaymentsUnsupported\": \"Bitcoin address payments are not supported\",\n    \"cameraAccessRequired\": \"Camera access required\",\n    \"cameraAccessDenied\": \"Camera access denied\",\n    \"cameraAccessRequiredHint\": \"We need camera access to scan QR codes for payments and tokens.\",\n    \"cameraAccessDeniedHint\": \"Enable camera access in your device settings to scan QR codes.\",\n    \"allowCameraAccess\": \"Allow camera access\",\n    \"openSettings\": \"Open settings\",\n    \"seconds\": \"seconds\",\n    \"selectAmount\": \"Select amount\",\n    \"selected\": \"Selected\",\n    \"selectMint\": \"Select a mint to send from\",\n    \"selectMints\": \"Select mints\",\n    \"noMintsWithBalance\": \"No mints with balance available\",\n    \"sendEcash\": \"Send Ecash\",\n    \"share\": \"Share\",\n    \"submitPaymentReq\": \"Cash out\",\n    \"to\": \"to\",\n    \"today\": \"Today\",\n    \"tokenInfoErr\": \"Error while getting token info\",\n    \"totalInclFee\": \"Total incl. fee\",\n    \"reservedTotal\": \"Reserved total\",\n    \"trustMint\": \"Trust this mint?\",\n    \"tryLater\": \"Please try again later.\",\n    \"unknownType\": \"Unknown data\",\n    \"version\": \"Version\",\n    \"viewMnemonic\": \"View Mnemonic\",\n    \"wallet\": \"Wallet\",\n    \"willDoLater\": \"Will do later\",\n    \"yes\": \"Yes\",\n    \"invalidPubKey\": \"Invalid public key!\",\n    \"walletLocked\": \"Wallet locked\",\n    \"explainer1\": \"eNuts is a custodial Lightning wallet, allowing private and instant transactions using the Cashu protocol. Your funds are held by mints you interact with, and Ecash is stored locally on your device.\",\n    \"explainer2\": \"Cashu is a new Ecash protocol for custodial Bitcoin apps, where mints are Lightning nodes performing Bitcoin transactions and offer you Ecash. Rest assured, the mint remains unaware of your Ecash payments.\",\n    \"explainer3\": \"Simply add a mint via URL and pay a Lightning invoice to get Ecash. eNuts guides you, lets you receive from anyone instantly and with your permission, automatically adds related mints. Swap funds between mints and send Ecash once you have a balance.\",\n    \"send&receive\": \"Send & receive\",\n    \"contactsNostr\": \"Contacts & Nostr\",\n    \"nostrExplainer\": \"The Nostr implementation enables seamless synchronization of your contacts without the need for you to enter your private key, as we generate a new one for you. Your data is displayed using the public key, while the new private key encrypts/decrypts your messages.\",\n    \"send\": \"Send\",\n    \"sendEcashDashboard\": \"Create a Cashu token and send it to anyone.\",\n    \"payInvoiceDashboard\": \"Send your funds to a Lightning node.\",\n    \"receiveEcashDashboard\": \"Paste & redeem a Cashu token from clipboard.\",\n    \"receiveEcashNostr\": \"Nostr messages\",\n    \"receiveEcashNostrHint\": \"Check your Nostr messages for Ecash.\",\n    \"createInvoiceDashboard\": \"Receive Ecash by paying a Lightning invoice.\",\n    \"hideNuts\": \"Hide balance\",\n    \"checkingDms\": \"Checking your DMs for Ecash...\",\n    \"clearOverHere\": \"Everything is clear over here!\",\n    \"totalDmsReceived\": \"You received {{totalDms}} Cashu token.\",\n    \"swapNow\": \"Swap now\",\n    \"swap\": \"Swap\",\n    \"emptyMint\": \"Mint has no funds\",\n    \"zapSoon\": \"Zaps will be added soon...\",\n    \"enutsPub\": \"eNuts public key: \",\n    \"seeFullHistory\": \"See full transaction history\",\n    \"next\": \"Next\",\n    \"skip\": \"Skip\",\n    \"donateLn\": \"Donate\",\n    \"supportHint\": \"Every contribution, no matter the size, makes a significant impact. Confirmation screen is under development.\",\n    \"newToken\": \"New Cashu token\",\n    \"disclaimerHint\": \"This disclaimer should be taken seriously and should not be ignored or underestimated. We appreciate your interest in this project and will continue to work on improving it.\",\n    \"searchContacts\": \"Search or type NPUB\",\n    \"submit\": \"Submit\",\n    \"clearMetadataCache\": \"Clear metadata cache\",\n    \"clearMetadataCacheHint\": \"Clear metadata cache?\",\n    \"clearImageCache\": \"Clear image cache\",\n    \"clearImageCacheHint\": \"Clear image cache?\",\n    \"pullRefresh\": \"Pull to refresh\",\n    \"processTestPay\": \"Processing test payment...\",\n    \"confirmMint\": \"Confirm new mint\",\n    \"confirmMintHint\": \"Are you sure that you want to add this mint?\",\n    \"npubAlreadyAdded\": \"NPUB already added\",\n    \"replaceNpub\": \"Replace NPUB\",\n    \"replaceNpubTxt\": \"Are you sure that you want to replace the current NPUB?\",\n    \"npubAdded\": \"NPUB added!\",\n    \"showContacts\": \"Show contacts\",\n    \"topUpNow\": \"Get Ecash now\",\n    \"scanAnother\": \"Scan another QR code\",\n    \"deleteNpub\": \"Delete NPUB?\",\n    \"delNpubHint\": \"All the contacts and related data will be deleted.\",\n    \"addNewNpub\": \"Add a new NPUB?\",\n    \"addNpubHint\": \"This will delete all the data associated with your current NPUB.\",\n    \"zap\": \"Zap\",\n    \"zapNow\": \"Zap now\",\n    \"meltNostrProfileHint\": \"Transfer funds to the LN address associated with your Nostr profile.\",\n    \"nostrDmHint\": \"eNuts can't access your Nostr account DMs due to its lack of access to your private key. Instead, it generates a new key for sending Ecash. When you send Ecash via Nostr, the recipient gets it using your new eNuts public key. If the recipient replies to the DM with an Ecash token, you can view it here. We're actively working on a secure private key solution.\",\n    \"nostrIssueHeader\": \"Nostr contacts issue\",\n    \"nostrIssueHint\": \"If you're having trouble opening your Nostr contacts, click the button below or reset the Nostr data in 'options' > 'contacts' > 'reset data now' to resolve the issue.\",\n    \"submitNostrIssue\": \"Reset data now\",\n    \"nostrIssueSuccess\": \"Nostr data reset successfully!\",\n    \"createLnInvoice\": \"Create Lightning invoice\",\n    \"metadataCacheCleared\": \"Metadata cache cleared!\",\n    \"imageCacheCleared\": \"Image cache cleared!\",\n    \"leaveGithubStar\": \"Support us with a Github star\",\n    \"alreadySpentHint\": \"Some proofs in your balance are spent or claimed elsewhere. Resolve by deleting them in 'Options' > 'Mint Management' > 'Check Proofs'.\",\n    \"useNpub\": \"Use NPUB\",\n    \"autoSwapToDefaulMint\": \"Auto-swap to default mint\",\n    \"trustMintOpt\": \"Trust mint\",\n    \"swapHint\": \"This option requires a Lightning payment, involves fees, and may still add the unknown mint to the list if a fee refund occurs.\",\n    \"trustHint\": \"The mint associated with the token will be added to your trusted list.\",\n    \"noDefaultHint\": \"You need to setup a default mint to perform an auto swap.\",\n    \"autoSwapSuccess\": \"Swap successful!\",\n    \"paidInvoice\": \"{{ count }} invoice has been paid with a total amount of {{ total }} Sats\",\n    \"paidInvoices\": \"{{ count }} invoices have been paid with a total amount of {{ total }} Sats\",\n    \"checkPayment\": \"Check payment\",\n    \"lnPaymentSpamHint\": \"Please wait {{ remainingSeconds }} seconds to avoid spamming the mint.\",\n    \"supportUs\": \"Support us\",\n    \"shareEnuts\": \"Share eNuts with someone\",\n    \"justNow\": \"Just now\",\n    \"hoursAgo\": \"{{count}} hours ago\",\n    \"yesterday\": \"Yesterday\",\n    \"awaitingPayment\": \"Awaiting payment\",\n    \"receivedFromMint\": \"Received from mint\",\n    \"status\": \"Status\",\n    \"unit\": \"Unit\",\n    \"quoteId\": \"Quote ID\",\n    \"nfcPaymentLimits\": \"Payment Limits\",\n    \"nfcPaymentLimitsDesc\": \"Set default and custom amount limits for NFC tap-to-pay\",\n    \"amountLimits\": \"Amount Limits\",\n    \"amountLimitsDesc\": \"Tap to set as default, long press to delete\",\n    \"noLimit\": \"No Limit\",\n    \"noLimitDesc\": \"Confirm any amount\",\n    \"deleteAmount\": \"Delete Amount\",\n    \"deleteAmountConfirm\": \"Are you sure you want to remove {{amount}} sats from your quick select amounts?\",\n    \"delete\": \"Delete\",\n    \"resetToDefaults\": \"Reset to Defaults\"\n  },\n  \"error\": {\n    \"checkSpendableErr\": \"Error while checking if token is spendable\",\n    \"claimTokenErr\": \"Error while claiming token\",\n    \"sendTokenErr\": \"Error while sending token\",\n    \"header\": \"An error occured\",\n    \"msg\": \"We are sorry that you encountered this problem. You can help us improve the software by taking a screenshot and creating a short bug report.\",\n    \"reportBug\": \"Report the bug\",\n    \"requestMintErr\": \"Error while requesting invoice from mint.\",\n    \"stackNA\": \"Error stack not available\",\n    \"generalMeltingErr\": \"The mint was not able to find a proper Lightning payment route to your node.\",\n    \"invoiceFromLnurlError\": \"Could not create an invoice using your LNURL.\",\n    \"invoiceScanError\": \"Could not use the invoice from the scanned QR code.\"\n  },\n  \"history\": {\n    \"checkSpent\": \"Check if token has been spent\",\n    \"isPending\": \"Token is pending\",\n    \"isSpent\": \"Token has been spent\",\n    \"justNow\": \"Just now\",\n    \"hoursAgo\": \"{{count}} hours ago\",\n    \"yesterday\": \"Yesterday\",\n    \"memo\": \"Memo\",\n    \"nHrsAgo\": \"{{hrs}} hours ago\",\n    \"nMinsAgo\": \"{{mins}} minutes ago\",\n    \"noMemo\": \"No memo\",\n    \"oneHrAgo\": \"1 hour ago\",\n    \"oneMinAgo\": \"1 minute ago\",\n    \"paymentHash\": \"Payment hash\",\n    \"settleTime\": \"Settle time\",\n    \"showQr\": \"Show QR code\",\n    \"receive\": \"Receive\",\n    \"send\": \"Send\",\n    \"melt\": \"Melt\",\n    \"receivedEcash\": \"Received Ecash\",\n    \"sentEcash\": \"Sent Ecash\",\n    \"paidInvoice\": \"Paid invoice\",\n    \"details\": \"Details\",\n    \"date\": \"Date\",\n    \"amount\": \"Amount\",\n    \"token\": \"Token\"\n  },\n  \"mints\": {\n    \"addCustomName\": \"Add a custom name\",\n    \"additionalInfo\": \"Additional information\",\n    \"addMintBtn\": \"Add mint\",\n    \"addNewMint\": \"Add a new mint\",\n    \"atLeast2Mints\": \"You need at least 2 mints to perform an multimint-swap.\",\n    \"awaitingInvoice\": \"Awaiting invoice\",\n    \"cashOutAmountHint\": \"Lightning fees may occur, so an estimated fee is added, and any overpaid fees will be refunded.\",\n    \"checkProofs\": \"Check proofs\",\n    \"checkProofsQ\": \"Check all the proofs?\",\n    \"checkProofsTxt\": \"This will check if your token are spendable and will otherwise delete them.\",\n    \"chooseMeltMintHint\": \"Choose a mint from which you would like to cash out your funds.\",\n    \"chooseMintHint\": \"Choose a mint from which you would like to receive Ecash. The mint becomes custodian of your funds.\",\n    \"chooseTarget\": \"Choose the receiver of the payment.\",\n    \"coinSelectionHint\": \"Your Ecash balance is essentially a collection of coin-sets. Coin selection allows you to choose the coins you want to spend. Coin-sets are assigned a keyset-ID by the mint, which may change over time. Newly added keysets are highlighted in green. It is advisable to spend older sets first.\",\n    \"creatingEcashToken\": \"Cashu token is being created\",\n    \"sendingEcashViaNostr\": \"Sending Cashu token via Nostr!\",\n    \"customName\": \"Custom name\",\n    \"cutomNameAdded\": \"Added a custom name\",\n    \"dangerZone\": \"Danger zone\",\n    \"deletedProofs\": \"Deleted {{proofsToDel}} proofs.\",\n    \"delMint\": \"Delete mint\",\n    \"delMintSure\": \"Remove this mint?\",\n    \"ecashAmountHint\": \"Select the amount of Ecash you would like to send.\",\n    \"editMintName\": \"Edit mint name\",\n    \"errDelProofs\": \"Something went wrong while deleting proofs.\",\n    \"funds\": \"Funds\",\n    \"general\": \"General\",\n    \"importantNotice\": \"Important notice\",\n    \"inputField\": \"LN invoice or LNURL\",\n    \"invalidUrl\": \"Invalid URL\",\n    \"invoiceAmountHint\": \"Select the amount of Ecash you would like to receive. The mint will then create an invoice which you will have to pay using a Lightning wallet.\",\n    \"invoiceHint\": \"This can take a few seconds...\",\n    \"lowBal\": \"Mint balance too low!\",\n    \"metadata\": \"Metadata\",\n    \"meltAddressbookHint\": \"Choose your own LNURL or any other contact as a payment receiver.\",\n    \"meltInputHint\": \"Paste Lightning invoice, LN-URL or Lightning address.\",\n    \"meltScanQRHint\": \"Create a Lightning invoice with another device and simply scan it.\",\n    \"meltSwapHint\": \"Pick another mint from your trusted list as the payment receiver.\",\n    \"copyShareToken\": \"Copy & quickshare\",\n    \"copyShareTokenHint\": \"Copy the generated token and share it via any messenger app.\",\n    \"sendNostr\": \"Send via Nostr\",\n    \"sendNostrHint\": \"Send Ecash directly to one of your Nostr contacts.\",\n    \"meltToken\": \"Cash out\",\n    \"mintConnectionFail\": \"Connection to mint failed\",\n    \"mintInfo\": \"Mint info\",\n    \"mintNewTokens\": \"Get Ecash\",\n    \"mintNoContact\": \"The mint has no contact info\",\n    \"mntAlreadyAdded\": \"Mint already added\",\n    \"noAdditional\": \"This mint has no additional info\",\n    \"noInfo\": \"Mint has no info\",\n    \"noProofs\": \"Found no proofs for this mint.\",\n    \"paymentOverview\": \"Payment overview\",\n    \"processingPaymentByMint\": \"The mint is processing the payment according to your request\",\n    \"processingSwap\": \"Processing multimint-swap according to your request\",\n    \"pubKey\": \"Public key\",\n    \"removeDefault\": \"Remove from default\",\n    \"scanQR\": \"Scan a QR code\",\n    \"sendEcashHint\": \"Choose a mint from which you would like to create a Cashu token.\",\n    \"setDefault\": \"Set as default mint\",\n    \"supportedNuts\": \"Supported NUTs\",\n    \"swapNotAllowed\": \"Swap out from a test mint is not possible.\",\n    \"zapNotAllowed\": \"Zap from a test mint is not possible.\",\n    \"testMintHint\": \"This is a test mint to play around with. Add it anyway?\",\n    \"trustMintSure\": \"Trust this mint?\",\n    \"updatedDefault\": \"Updated the default mint\",\n    \"newMintAdded\": \"Mint added!\",\n    \"newMintAddedQuestion\": \"Do you want to receive Ecash now?\",\n    \"selectSwapReceiver\": \"Select a mint as the payment receiver.\",\n    \"prepairZapData\": \"Preparing the transaction data...\",\n    \"lastUpdated\": \"Last updated\",\n    \"mintInfoUpdated\": \"Mint info updated!\",\n    \"mintInfoUpdateFailed\": \"Failed to update mint info\",\n    \"npcSettings\": \"Lightning address\",\n    \"npcDefaultAccount\": \"Default\",\n    \"npcTapToCopy\": \"Tap to copy\",\n    \"npcUsernameLabel\": \"Custom username\",\n    \"npcUsernamePlaceholder\": \"optional username\",\n    \"npcPurchaseUsername\": \"Save username\",\n    \"npcSetUsername\": \"Set Username\",\n    \"npcRequestUsername\": \"Request username\",\n    \"npcUsernameFeePrompt\": \"Do you want to set this username for a fee of {{amount}} sats?\",\n    \"npcReceiveTitle\": \"NPC Lightning addresses\",\n    \"npcReceiveHint\": \"Receive Lightning payments into your local Cashu wallet.\",\n    \"npcAccountsLabel\": \"Accounts\",\n    \"npcLocalBalance\": \"Local balance\",\n    \"npcReceiveAddress\": \"Receive address\",\n    \"npcSeedKey\": \"Seed key\",\n    \"npcImportedKey\": \"Imported key\",\n    \"npcActive\": \"Active\",\n    \"npcSyncing\": \"Syncing\",\n    \"npcPaused\": \"Paused\",\n    \"npcNpubFallback\": \"Using your npub until a username is saved\",\n    \"npcSyncAll\": \"Sync all\",\n    \"npcSynced\": \"NPC account synced\",\n    \"npcAccountAdded\": \"NPC account added\",\n    \"npcAccountRemoved\": \"NPC account removed\",\n    \"npcUsernameSaved\": \"Username saved\",\n    \"npcAddAccountTitle\": \"Add NPC account\",\n    \"npcAddAccountHint\": \"Import an existing Nostr key or derive a new key from your seed.\",\n    \"npcPrivateKeyLabel\": \"Private key\",\n    \"npcPrivateKeyPlaceholder\": \"nsec or hex\",\n    \"npcPrivateKeyHint\": \"Imported keys are stored in secure storage on this device.\",\n    \"npcPrivateKeyRequired\": \"Enter an nsec or hex private key.\",\n    \"npcImportPrivateKey\": \"Import private key\",\n    \"npcDeriveAccount\": \"Derive new key\"\n  },\n  \"topNav\": {\n    \"about\": \"About us\",\n    \"addressBook\": \"Address book\",\n    \"advancedFunctions\": \"Advanced functions\",\n    \"display\": \"Display\",\n    \"history\": \"Transaction history\",\n    \"language\": \"Language\",\n    \"currency\": \"Currency\",\n    \"mintSettings\": \"Mint management\",\n    \"nfcSettings\": \"NFC Settings\",\n    \"npcSettingsTitle\": \"Lightning address\",\n    \"security\": \"Security\",\n    \"settings\": \"Options\",\n    \"privacy\": \"Privacy\",\n    \"general\": \"General\"\n  },\n  \"wallet\": {\n    \"cashuContent\": \"The author of Cashu is not a cryptographer and the protocol is still under review. It raises concerns about the potential existence of fatal flaws. As a result, Cashu is not yet production-ready.\",\n    \"cashuExperiment\": \"Cashu is still experimental.\",\n    \"claiming\": \"Claiming...\",\n    \"processingInvoice\": \"Processing invoice...\",\n    \"nfcPayment\": \"NFC Payment\",\n    \"nfcKeepNearTerminal\": \"Keep your phone near the terminal\",\n    \"nfcSelectMaxAmount\": \"Select maximum amount\",\n    \"noLimit\": \"No limit\",\n    \"custodialRisk\": \"Custodial risk, mints hold the keys.\",\n    \"custodialRiskContent\": \"With eNuts, you don't hold the keys to the Bitcoin; the mint acts as the custodian. Therefore, if you lack trust in a mint, it's advisable to avoid interacting with it.\",\n    \"disclaimer\": \"Please note that this is beta version in its early stage and is still undergoing testing before its official release. The software and all content found on it are provided on an “as is” and “as available” basis. We do not give any warranties, whether express or implied, as to the suitability or usability of the software or any of its content.\",\n    \"enutsDisclaimer\": \"eNuts is unfinished beta software.\",\n    \"lossContent\": \"Cashu tokens are bearer tokens, implying that if you lose access to them, there is no recovery option implemented yet. eNuts stores your tokens in your device. Before deleting the app, ensure you back up your tokens.\",\n    \"lossOfTokens\": \"Loss of funds.\",\n    \"enutsMint\": \"The default eNuts mint\",\n    \"mintDisclaimer\": \"The usage of the default eNuts mint is entirely at your own risk. We strongly encourage you to exercise caution and only use it for experimental or educational purposes. There are no guarantees regarding its functionality, security, or availability, and it may vanish without notice. Deposits made to this mint should be considered as donations and may not be returned, potentially used for further development. Be aware of the risks associated with beta software, and it's your responsibility to safeguard your assets while using this mint.\",\n    \"paidOut\": \"Paid out\",\n    \"pasteToken\": \"Redeem Ecash\",\n    \"payInvoice\": \"Pay invoice\",\n    \"payLNInvoice\": \"Pay Lightning invoice\",\n    \"receive\": \"Receive\",\n    \"send\": \"Send\",\n    \"proofs\": \"Proofs\",\n    \"swapped\": \"Swapped\"\n  }\n}\n"
  },
  {
    "path": "assets/translations/es.json",
    "content": "{\n  \"addrBook\": {\n    \"addOwnNpub\": \"Añadir tu NPUB\",\n    \"favorite\": \"Favoritos\",\n    \"removeFav\": \"Quitar de favoritos\",\n    \"copyNpub\": \"Copiar NPUB\",\n    \"npubCopied\": \"¡NPUB copiada!\",\n    \"receiverNoLnurl\": \"El receptor no tiene LNURL\",\n    \"noResults\": \"Sin resultados\"\n  },\n  \"auth\": {\n    \"confirmAction\": \"Por favor, confirma esta acción.\",\n    \"createPin\": \"Crear PIN\",\n    \"editPin\": \"Editar PIN\",\n    \"pinMismatch\": \"¡PIN incorrecto!\",\n    \"pinSetup\": \"Puedes establecer un PIN para proteger la aplicación (opcional).\",\n    \"pleaseConfirm\": \"Por favor, confirma tu PIN.\",\n    \"pleaseConfirmNewPin\": \"Por favor, confirma tu nuevo PIN.\",\n    \"pleaseEnter\": \"Por favor, introduce tu PIN.\",\n    \"pleaseNewPin\": \"Por favor, introduce tu nuevo PIN.\",\n    \"removePin\": \"Eliminar PIN\",\n    \"welcome\": \"Bienvenido\",\n    \"welcomeBack\": \"¡Bienvenido de nuevo!\"\n  },\n  \"bottomNav\": {\n    \"wallet\": \"Cartera\",\n    \"contacts\": \"Contactos\"\n  },\n  \"common\": {\n    \"confirmReset\": \"Restablecer billetera\",\n    \"copy\": \"Copiar\",\n    \"cycle\": \"Ciclo\",\n    \"findMint\": \"Buscar ceca\",\n    \"manualCounterIncrease\": \"Incrementar contadores\",\n    \"manualCounterIncreaseHint\": \"Los contadores se incrementan automáticamente después de cada transacción, pero en casos raros, esto puede fallar, lo que lleva a errores durante el proceso de restauración. Elevar manualmente los contadores puede resolver el estado.\",\n    \"increaseCounterHint\": \"¿Estás seguro de que quieres incrementar los contadores? Esto solo debe hacerse si estás seguro de que los contadores no están sincronizados.\",\n    \"noMintForCounter\": \"No tienes cecas para incrementar los contadores.\",\n    \"counterIncreased\": \"¡Contadores incrementados en {{counterIncreased}}!\",\n    \"doneSafety\": \"Casi terminado... Verificación de seguridad\",\n    \"restoreErr\": \"Ocurrió un error al restaurar tu cartera.\",\n    \"noProofsRestored\": \"No se encontraron pruebas para restaurar la cartera.\",\n    \"dontClose\": \"Por favor, no cierre la aplicación durante el proceso.\",\n    \"recoveryHint\": \"Escribe o pega tu mnemotecnia de 12 palabras en el orden correcto, separadas por espacios en blanco.\",\n    \"walletRecovery\": \"Recuperación\",\n    \"walletRecoveryHint\": \"Utiliza una copia de seguridad de la semilla para restaurar tu cartera.\",\n    \"seedBackup\": \"Seguridad de la semilla\",\n    \"12WordMnemonic\": \"12 palabras\",\n    \"secureWallet\": \"Cartera segura\",\n    \"secureWalletHint\": \"Genera y anota una copia de seguridad de la semilla para asegurar tu cartera.\",\n    \"quickWallet\": \"Cartera rápida\",\n    \"quickWalletHint\": \"Crea una nueva cartera al instante. La copia de seguridad de la semilla se puede generar más tarde.\",\n    \"skipSeedHint\": \"Puedes omitir este proceso y generar una copia de seguridad de la semilla más tarde.\",\n    \"mnemonicHint\": \"La frase de semilla nunca se mostrará de nuevo. Escríbela y nunca la compartas con nadie.\",\n    \"confirmMnemonicErr\": \"¡Palabra incorrecta! Asegúrate de escribir correctamente tu frase de semilla en el orden correcto.\",\n    \"selectRestoreMint\": \"Por favor, seleccione la ceca que se utilizará para restaurar sus fondos.\",\n    \"recoveringWallet\": \"La ceca está restaurando sus fondos...\",\n    \"seedEnabled\": \"¡Recuperación de semilla habilitada!\",\n    \"confirmSeed\": \"Por favor, confirma tu semilla escribiendo la palabra correcta.\",\n    \"about\": \"Acerca de\",\n    \"aboutToLeaveTo\": \"Estás a punto de salir\",\n    \"accept\": \"Aceptar\",\n    \"amount\": \"Cantidad\",\n    \"back\": \"Volver\",\n    \"backToDashboard\": \"Volver al panel de control\",\n    \"balance\": \"Saldo\",\n    \"balanceAfterTX\": \"Mint saldo tras la transacción\",\n    \"balTooLow\": \"Saldo insuficiente\",\n    \"bigQrMsg\": \"La cantidad de datos es demasiado grande para un código QR.\",\n    \"calculateFeeEst\": \"Calculando comisión\",\n    \"cancel\": \"Cancelar\",\n    \"cashOut\": \"Retirar efectivo\",\n    \"cashOutFromMint\": \"Retirar efectivo de la ceca\",\n    \"change\": \"Cambiar\",\n    \"claimed\": \"reclamado\",\n    \"restored\": \"restaurado\",\n    \"claimSuccess\": \"Reclamado {{amount}} Sats:\\n{{mintUrl}}\\nNota: {{memo}}\",\n    \"claimToken\": \"Reclamar token\",\n    \"clear\": \"Limpiar\",\n    \"clipboardInvalid\": \"¡Hay un token Cashu inválido en el portapapeles!\",\n    \"coinSelection\": \"Selección de monedas\",\n    \"confirm\": \"Confirmar\",\n    \"contact\": \"Contactar\",\n    \"mintDelErr\": \"No se puede eliminar una ceca con saldo restante\",\n    \"continue\": \"Continuar\",\n    \"copied\": \"Copiado\",\n    \"shareInvoice\": \"Compartir recibo\",\n    \"copyToken\": \"Copiar token\",\n    \"createInvoice\": \"Crear recibo\",\n    \"createToken\": \"Crear token\",\n    \"createTokenErr\": \"No se pudo crear un token Cashu. Por favor, reinténtalo más tarde.\",\n    \"eventError\": \"Algo falló al publicar el evento.\",\n    \"createViaLn\": \"Crear recibo\",\n    \"darkMode\": \"Modo Noche\",\n    \"lightMode\": \"Modo Claro\",\n    \"autoMode\": \"Modo Automático\",\n    \"dbErr\": \"¡Algo falló al inicializar la base de datos!\",\n    \"deepLinkErr\": \"No se pudo abrir el link\",\n    \"default\": \"Por defecto\",\n    \"delHistory\": \"Eliminar historial\",\n    \"factoryReset\": \"Restablecer configuración de fábrica\",\n    \"delHistoryErr\": \"No se pudo eliminar el historial.\",\n    \"delHistoryQ\": \"¿Eliminar historial?\",\n    \"resetQ\": \"¿Restablecer la cartera?\",\n    \"delHistoryTxt\": \"Los datos no podrán recuperarse después.\",\n    \"display\": \"Pantalla\",\n    \"disclaimer\": \"Advertencia\",\n    \"restoreBattery\": \"Al menos 20% de batería.\",\n    \"restoreBatteryHint\": \"Recomendamos que tenga al menos un 20% de batería antes de iniciar el proceso de recuperación. Dependiendo de la cantidad de datos, el proceso puede llevar un tiempo.\",\n    \"restoreWifi\": \"Usa Wi-Fi.\",\n    \"restoreWifiHint\": \"Recomendamos que utilice una conexión Wi-Fi estable para el proceso de recuperación para evitar cualquier interrupción y garantizar una recuperación rápida y segura.\",\n    \"restoreForeground\": \"Mantén la aplicación en primer plano.\",\n    \"restoreForegroundHint\": \"Por favor, mantenga la aplicación en primer plano y no la cierre durante el proceso de recuperación para evitar cualquier interrupción.\",\n    \"seedMigrationHint\": \"La semilla se aplica a todas las acuñaciones con las que interactúas, así que anota las URL de las acuñaciones que usas con frecuencia. Si tienes saldo, crea y reclama un token con la acuñación deseada después de generar una semilla. Repite para cada acuñación que desees respaldar.\",\n    \"ecashPayment\": \"Pagar Ecash\",\n    \"english\": \"Inglés\",\n    \"spanish\": \"Español\",\n    \"swahili\": \"Suajili\",\n    \"hungarian\": \"Húngaro\",\n    \"italian\": \"Italiano\",\n    \"russian\": \"Ruso\",\n    \"thai\": \"Tailandés\",\n    \"chinese simplified\": \"Chino (Simplificado)\",\n    \"chinese traditional\": \"Chino (Tradicional)\",\n    \"enutsRandD\": \"Telegram eNuts\",\n    \"estimatedFees\": \"Comisión estimada\",\n    \"estimateFee\": \"Estimar comisión\",\n    \"expired\": \"Expirado\",\n    \"fee\": \"Comisión\",\n    \"swapFee\": \"Comisión de intercambio\",\n    \"feeErr\": \"No se pudo estimar la comisión. ¿Es \\\"{{input}}\\\" una LNURL valida?\",\n    \"foundCashuClipboard\": \"Token Cashu detectado\",\n    \"french\": \"Francés\",\n    \"from\": \"desde\",\n    \"fromMint\": \"desde la siguiente ceca\",\n    \"sendingFrom\": \"Enviando desde\",\n    \"german\": \"Alemán\",\n    \"github\": \"GitHub\",\n    \"githubIssues\": \"Reportar bugs en Github\",\n    \"reportIssue\": \"Reportar un problema\",\n    \"shareOrReport\": \"Compartir opiniones o reportar bugs\",\n    \"historyDeleted\": \"Historial eliminado\",\n    \"invalidInvoice\": \"Recibo inválido\",\n    \"invalidOrSpent\": \"Token inválido o reclamado\",\n    \"invalidToken\": \"Token inválido\",\n    \"invoice\": \"Recibo\",\n    \"invoiceExpired\": \"Recibo expirado\",\n    \"invoiceInclFee\": \"Recibo incl. comisión\",\n    \"invoiceOrLnurl\": \"Recibo LN o LNURL\",\n    \"invoiceOrLnAddress\": \"Factura o Dirección\",\n    \"keysetID\": \"Keyset ID\",\n    \"language\": \"Idioma\",\n    \"currency\": \"Moneda\",\n    \"currencyConversion\": \"Conversión de moneda\",\n    \"showFiatBalance\": \"Mostrar saldo en fiat\",\n    \"showFiatBalanceDesc\": \"Muestra tu saldo y cantidades en tu moneda fiat seleccionada\",\n    \"selectCurrency\": \"Seleccionar moneda\",\n    \"lastUpdate\": \"Actualizado\",\n    \"loadingRates\": \"Cargando tipos de cambio...\",\n    \"ratesUnavailable\": \"Tipos de cambio no disponibles\",\n    \"ratesUnavailableDesc\": \"No se pudieron cargar los tipos de cambio. Por favor, comprueba tu conexión a internet e inténtalo de nuevo.\",\n    \"ratesRequiredForFiat\": \"Se requieren tipos de cambio para habilitar la visualización en fiat\",\n    \"noCurrenciesAvailable\": \"No hay monedas disponibles. Por favor, reintenta cargar los tipos de cambio.\",\n    \"retry\": \"Reintentar\",\n    \"lnInvoice\": \"Recibo Lightning\",\n    \"lnPayment\": \"Pago Lightning\",\n    \"mint\": \"Ceca\",\n    \"minted\": \"acuñado\",\n    \"multimintSwap\": \"Intercambio multiceca\",\n    \"n/a\": \"No disponible\",\n    \"name\": \"Nombre\",\n    \"no\": \"No\",\n    \"noCamAccess\": \"Sin acceso a la cámara\",\n    \"noFunds\": \"No hay fondos suficientes\",\n    \"noFundsForFee\": \"No hay fondos suficientes. Por favor, deja margen para posibles comisiones: ~{{fee}} Sats\",\n    \"noMint\": \"No se encontró ninguna ceca\",\n    \"notQrCode\": \"¡No es un código QR!\",\n    \"noTX\": \"No hay transacciones todavía\",\n    \"activity\": \"Actividad\",\n    \"allHistory\": \"Todo\",\n    \"optionalMemo\": \"Nota opcional\",\n    \"paste\": \"Pegar\",\n    \"paymentPending\": \"Pago pendiente\",\n    \"paymentSuccess\": \"¡Pagado con éxito!\",\n    \"nostrPaymentSuccess\": \"¡Enviado!\",\n    \"paymentType\": \"Tipo de pago\",\n    \"payWithLn\": \"Pagar con tu cartera LN\",\n    \"preferences\": \"Preferencias\",\n    \"readme\": \"Léeme\",\n    \"sender\": \"Remitente\",\n    \"recipient\": \"Receptor\",\n    \"reqTimeout\": \"Tiempo de espera de la solicitud de red agotado\",\n    \"restore\": \"Restaurar\",\n    \"save\": \"Guardar\",\n    \"scanAgain\": \"Escanear de nuevo\",\n    \"scan\": \"Escanear\",\n    \"scanQR\": \"Escanear QR\",\n    \"qrScanHint\": \"Coloca el código QR dentro del marco\",\n    \"qrScanFormats\": \"Cashu, Lightning, LNURL o Bitcoin\",\n    \"qrScanReady\": \"Listo para escanear\",\n    \"qrScanPaused\": \"Escaneo en pausa\",\n    \"animatedQrProgress\": \"Progreso del QR animado\",\n    \"receivingAnimatedQr\": \"Recibiendo QR animado\",\n    \"unsupportedFormat\": \"Formato no compatible\",\n    \"cashuPaymentRequestQrUnsupported\": \"Las solicitudes de pago Cashu aún no son compatibles desde QR\",\n    \"bitcoinAddressPaymentsUnsupported\": \"Los pagos a direcciones Bitcoin no son compatibles\",\n    \"cameraAccessRequired\": \"Se requiere acceso a la cámara\",\n    \"cameraAccessDenied\": \"Acceso a la cámara denegado\",\n    \"cameraAccessRequiredHint\": \"Necesitamos acceso a la cámara para escanear códigos QR de pagos y tokens.\",\n    \"cameraAccessDeniedHint\": \"Activa el acceso a la cámara en los ajustes del dispositivo para escanear códigos QR.\",\n    \"allowCameraAccess\": \"Permitir acceso a la cámara\",\n    \"openSettings\": \"Abrir ajustes\",\n    \"seconds\": \"segundos\",\n    \"selectAmount\": \"Seleccionar cantidad\",\n    \"selected\": \"Seleccionado\",\n    \"selectMint\": \"Seleccionar una ceca desde la que enviar\",\n    \"selectMints\": \"Seleccionar cecas\",\n    \"sendEcash\": \"Enviar Ecash\",\n    \"share\": \"Compartir\",\n    \"submitPaymentReq\": \"Retirar efectivo\",\n    \"to\": \"para\",\n    \"today\": \"Hoy\",\n    \"tokenInfoErr\": \"Error al obtener la información del token\",\n    \"totalInclFee\": \"Total incl. comisiones\",\n    \"reservedTotal\": \"Total reservado\",\n    \"trustMint\": \"¿Quieres fiarte de esta ceca?\",\n    \"tryLater\": \"Por favor, reinténtalo más tarde.\",\n    \"unknownType\": \"Desconocido\",\n    \"version\": \"Versión\",\n    \"viewMnemonic\": \"Ver Mnemónico\",\n    \"wallet\": \"Cartera\",\n    \"willDoLater\": \"Dejar para después\",\n    \"yes\": \"Sí\",\n    \"invalidPubKey\": \"¡Clave pública inválida!\",\n    \"walletLocked\": \"Cartera bloqueada\",\n    \"explainer1\": \"eNuts es una cartera custodia de Lightning, permite hacer transacciones de forma privada e instantánea usando el protocolo Cashu. Tus fondos son custodiados por las cecas con las que interactúas, y el Ecash se almacena de manera local en tu dispositivo.\",\n    \"explainer2\": \"Cashu es un nuevo protocolo de Ecash para aplicaciones custodias de Bitcoin, donde las cecas son nodos Lightning que llevan a cabo transacciones de Bitcoin y te ofrecen Ecash. Estate tranquilo, las cecas no son conscientes de tus pagos en Ecash.\",\n    \"explainer3\": \"Simplemente añade una ceca vía URL y paga un recibo Lightning para obtener Ecash. eNuts te guía, te permite recibir desde cualquiera al instante y, con tu permiso, añade automáticamente cecas relacionadas. Intercambia fondos entre cecas y envía Ecash una vez tengas saldo.\",\n    \"send&receive\": \"Enviar y recibir\",\n    \"contactsNostr\": \"Contactos y Nostr\",\n    \"nostrExplainer\": \"La implementación Nostr permite la sincronización perfecta de tus contactos sin tener que ingresar tu clave privada, ya que generamos una nueva para tí. Tus datos se muestran usando tu clave pública, mientras que la nueva clave privada encripta/descifra tus mensajes.\",\n    \"send\": \"Enviar\",\n    \"sendEcashDashboard\": \"Crear un token Cashu y envíalo a quien quieras.\",\n    \"payInvoiceDashboard\": \"Envía tus fondos a un nodo Lightning.\",\n    \"receiveEcashDashboard\": \"Pega y redime un token Cashu desde el portapapeles.\",\n    \"receiveEcashNostr\": \"Mensajes en Nostr\",\n    \"receiveEcashNostrHint\": \"Busca Ecash en tus mensajes personales de Nostr.\",\n    \"createInvoiceDashboard\": \"Recibe Ecash pagando un recibo Lightning.\",\n    \"hideNuts\": \"Esconder saldo\",\n    \"checkingDms\": \"Buscando Ecash en tus mensajes personales...\",\n    \"clearOverHere\": \"¡Todo despejado por aquí!\",\n    \"totalDmsReceived\": \"Has recibido {{totalDms}} tokens Cashu.\",\n    \"swapNow\": \"Intercambiar ahora\",\n    \"swap\": \"Intercambiar\",\n    \"emptyMint\": \"La ceca no tiene fondos\",\n    \"zapSoon\": \"Zaps, disponibles próximamente...\",\n    \"enutsPub\": \"Clave pública eNuts: \",\n    \"seeFullHistory\": \"Ver el historial de transacciones completo\",\n    \"next\": \"Siguiente\",\n    \"skip\": \"Saltar\",\n    \"donateLn\": \"Donar\",\n    \"supportHint\": \"Cada contribución, no importa el tamaño, tiene un impacto significativo. La pantalla de confirmación está en desarrollo.\",\n    \"newToken\": \"Nuevo token Cashu\",\n    \"disclaimerHint\": \"Esta advertencia debe ser tomada en serio y no ser ignorada o subestimada. Apreciamos tu interés en este proyecto y continuaremos trabajando en mejorarlo.\",\n    \"searchContacts\": \"Busca o escribe una NPUB\",\n    \"submit\": \"Enviar\",\n    \"clearMetadataCache\": \"Limpiar caché de metadatos\",\n    \"clearMetadataCacheHint\": \"¿Limpiar caché de metadatos?\",\n    \"clearImageCache\": \"Limpiar caché de imágenes\",\n    \"clearImageCacheHint\": \"¿Limpiar caché de imágenes?\",\n    \"pullRefresh\": \"Desliza para actualizar\",\n    \"processTestPay\": \"Procesando pago de prueba...\",\n    \"confirmMint\": \"Confirmar nueva ceca\",\n    \"confirmMintHint\": \"¿Seguro que quieres añadir esta ceca?\",\n    \"npubAlreadyAdded\": \"La NPUB ya ha sido añadida\",\n    \"replaceNpub\": \"Reemplazar NPUB\",\n    \"replaceNpubTxt\": \"¿Seguro que quieres reemplazar la NPUB actual?\",\n    \"npubAdded\": \"¡NPUB añadida!\",\n    \"showContacts\": \"Mostrar contactos\",\n    \"topUpNow\": \"Obtener Ecash ahora\",\n    \"scanAnother\": \"Escanear otro código QR\",\n    \"deleteNpub\": \"¿Eliminar NPUB?\",\n    \"delNpubHint\": \"Todos los contactos y datos relacionados serán eliminados.\",\n    \"addNewNpub\": \"¿Añadir una nueva NPUB?\",\n    \"addNpubHint\": \"Esto eliminará todos los datos asociados con tu NPUB actual.\",\n    \"zap\": \"Zap\",\n    \"zapNow\": \"Enviar Zap\",\n    \"meltNostrProfileHint\": \"Transfiere fondos a la dirección LN asociada con tu perfil de Nostr.\",\n    \"nostrDmHint\": \"eNuts no puede acceder a los mensajes directos de tu cuenta de Nostr porque no tiene acceso a tu clave privada. En su lugar, genera una nueva clave para enviar el Ecash. Cuando envías Ecash vía Nostr, el receptor lo recibe con tu nueva clave pública de eNuts. Si el receptor responde al mensaje directo con un token Ecash, lo podrás ver aquí. Estamos trabajando activamente en una solución segura para la clave privada.\",\n    \"nostrIssueHeader\": \"Problema en los contactos de Nostr\",\n    \"nostrIssueHint\": \"Si estás teniendo problemas al abrir tus contactos de Nostr, haz click en el botón de abajo o restablece los datos de Nostr en \\\"opciones > contactos > restablecer datos ahora\\\" para resolver el problema.\",\n    \"submitNostrIssue\": \"Restablecer datos ahora\",\n    \"nostrIssueSuccess\": \"¡Éxito al restablecer los datos de Nostr!\",\n    \"createLnInvoice\": \"Crear un recibo Lightning\",\n    \"metadataCacheCleared\": \"Caché de metadatos limpiada\",\n    \"imageCacheCleared\": \"Caché de imágenes limpiada\",\n    \"leaveGithubStar\": \"Apóyenos con una estrella en Github\",\n    \"alreadySpentHint\": \"Algunas pruebas en su saldo han sido gastadas o reclamadas en otro lugar. Resuelva esto eliminando las pruebas en 'Opciones' > 'Gestión de ceca' > 'Comprobar pruebas'.\",\n    \"useNpub\": \"Usar NPUB\",\n    \"autoSwapToDefaulMint\": \"Cambiar a la ceca por defecto\",\n    \"trustMintOpt\": \"Confiar en la ceca\",\n    \"swapHint\": \"Esta opción requiere un pago Lightning, implica una tarifa y aún puede agregar la ceca desconocida a la lista si se produce un reembolso de tarifa.\",\n    \"trustHint\": \"La ceca asociada al token se añadirá a tu lista de confianza.\",\n    \"noDefaultHint\": \"Necesitas configurar una ceca predeterminada para realizar un intercambio automático.\",\n    \"autoSwapSuccess\": \"¡Intercambio exitoso!\",\n    \"paidInvoice\": \"Se ha pagado {{ count }} factura con un importe total de {{ total }} Sats\",\n    \"paidInvoices\": \"Se han pagado {{ count }} facturas con un importe total de {{ total }} Sats\",\n    \"checkPayment\": \"Comprobar pago\",\n    \"lnPaymentSpamHint\": \"Por favor, espere {{ remainingSeconds }} segundos para aliviar la Mint.\",\n    \"shareEnuts\": \"Comparte eNuts con alguien\",\n    \"supportUs\": \"Apóyanos\",\n    \"justNow\": \"Ahora mismo\",\n    \"hoursAgo\": \"hace {{count}} horas\",\n    \"yesterday\": \"Ayer\",\n    \"awaitingPayment\": \"Esperando pago\",\n    \"receivedFromMint\": \"Recibido de la ceca\",\n    \"status\": \"Estado\",\n    \"unit\": \"Unidad\",\n    \"quoteId\": \"ID de cotización\",\n    \"nfcPaymentLimits\": \"Límites de pago\",\n    \"nfcPaymentLimitsDesc\": \"Establecer límites de cantidad predeterminados y personalizados para pagos NFC\",\n    \"amountLimits\": \"Límites de cantidad\",\n    \"amountLimitsDesc\": \"Toca para establecer como predeterminado, mantén pulsado para eliminar\",\n    \"noLimit\": \"Sin límite\",\n    \"noLimitDesc\": \"Confirmar cualquier cantidad\",\n    \"deleteAmount\": \"Eliminar cantidad\",\n    \"deleteAmountConfirm\": \"¿Estás seguro de que quieres eliminar {{amount}} sats de tus cantidades de selección rápida?\",\n    \"delete\": \"Eliminar\",\n    \"resetToDefaults\": \"Restablecer valores predeterminados\"\n  },\n  \"error\": {\n    \"checkSpendableErr\": \"Error al comprobar si el token puede ser gastado\",\n    \"claimTokenErr\": \"Error al reclamar el token\",\n    \"sendTokenErr\": \"Error al enviar el token\",\n    \"header\": \"Ocurrió un error\",\n    \"msg\": \"Sentimos que hayas experimentado este problema. Puedes ayudarnos a mejorar el programa realizando una captura de pantalla y creando un pequeño informe de errores.\",\n    \"reportBug\": \"Reportar el bug\",\n    \"requestMintErr\": \"Error al solicitar el recibo a la ceca.\",\n    \"stackNA\": \"Error, proceso no disponible\",\n    \"generalMeltingErr\": \"La ceca no pudo encontrar una ruta de pago Lightning funcional hasta tu nodo.\",\n    \"invoiceFromLnurlError\": \"No se pudo crear un recibo utilizando tu LNURL.\",\n    \"invoiceScanError\": \"No se pudo usar el recibo del código QR escaneado.\"\n  },\n  \"history\": {\n    \"checkSpent\": \"Comprueba si el token ha sido gastado\",\n    \"isPending\": \"El token está pendiente\",\n    \"isSpent\": \"El token ha sido gastado\",\n    \"justNow\": \"Ahora mismo\",\n    \"hoursAgo\": \"hace {{count}} horas\",\n    \"yesterday\": \"Ayer\",\n    \"memo\": \"Nota\",\n    \"nHrsAgo\": \"Hace {{hrs}} horas\",\n    \"nMinsAgo\": \"Hace {{mins}} minutos\",\n    \"noMemo\": \"Sin nota\",\n    \"oneHrAgo\": \"Hace 1 hora\",\n    \"oneMinAgo\": \"Hace 1 minuto\",\n    \"paymentHash\": \"Hash del pago\",\n    \"settleTime\": \"Tiempo de resolución\",\n    \"showQr\": \"Mostrar código QR\",\n    \"receive\": \"Recibir\",\n    \"send\": \"Enviar\",\n    \"melt\": \"Fundir\",\n    \"receivedEcash\": \"Ecash recibido\",\n    \"sentEcash\": \"Ecash enviado\",\n    \"paidInvoice\": \"Factura pagada\",\n    \"details\": \"Detalles\",\n    \"date\": \"Fecha\",\n    \"amount\": \"Cantidad\",\n    \"token\": \"Token\"\n  },\n  \"mints\": {\n    \"addCustomName\": \"Añadir nombre personalizado\",\n    \"additionalInfo\": \"Información adicional\",\n    \"addMintBtn\": \"Añadir ceca\",\n    \"addNewMint\": \"Añadir nueva ceca\",\n    \"atLeast2Mints\": \"Necesitas al menos 2 cecas para realizar un intercambio multiceca.\",\n    \"awaitingInvoice\": \"Esperando recibo\",\n    \"cashOutAmountHint\": \"Puede acarrear comisiones Lightning, por lo que se añadirá una comisión estimada. Cualquier comisión pagada de más será reembolsada.\",\n    \"checkProofs\": \"Comprobar pruebas\",\n    \"checkProofsQ\": \"¿Comprobar todas las pruebas?\",\n    \"checkProofsTxt\": \"Esto comprobará si tus tokens pueden ser gastados y de lo contrario los eliminará.\",\n    \"chooseMeltMintHint\": \"Elige la ceca desde la que quieres retirar tus fondos.\",\n    \"chooseMintHint\": \"Elige la ceca desde la que quieres recibir Ecash. La ceca se convertirá en custodia de tus fondos.\",\n    \"chooseTarget\": \"Elige el receptor del pago.\",\n    \"coinSelectionHint\": \"Tu saldo de Ecash es esencialmente una colección de sets de monedas. La selección de monedas te permite elegir las monedas que quieres utilizar. Los sets de monedas tienen una keyset-ID asignada por la ceca, la cual puede cambiar con el tiempo. Los keysets añadidos recientemente están destacados en verde. Es aconsejable utilizar primero los sets más antiguos.\",\n    \"creatingEcashToken\": \"El token Cashu está siendo creado\",\n    \"sendingEcashViaNostr\": \"¡Enviando token Cashu vía Nostr!\",\n    \"customName\": \"Nombre personalizado\",\n    \"cutomNameAdded\": \"Se añadió un nombre personalizado\",\n    \"dangerZone\": \"Zona de Peligro\",\n    \"deletedProofs\": \"Eliminadas {{proofsToDel}} pruebas.\",\n    \"delMint\": \"Eliminar ceca\",\n    \"delMintSure\": \"¿Eliminar esta ceca?\",\n    \"ecashAmountHint\": \"Selecciona la cantidad de Ecash que quieres enviar.\",\n    \"editMintName\": \"Editar nombre de la ceca\",\n    \"errDelProofs\": \"Algo salió mal al eliminar las pruebas.\",\n    \"funds\": \"Fondos\",\n    \"general\": \"General\",\n    \"importantNotice\": \"Aviso importante\",\n    \"inputField\": \"Recibo LN o LNURL\",\n    \"invalidUrl\": \"URL inválida\",\n    \"invoiceAmountHint\": \"Selecciona la cantidad de Ecash que deseas recibir. A continuación la ceca creará un recibo que deberás pagar usando una cartera Lightning.\",\n    \"invoiceHint\": \"Esto puede llevar unos segundos...\",\n    \"lowBal\": \"¡Saldo de la ceca muy bajo!\",\n    \"metadata\": \"Metadatos\",\n    \"meltAddressbookHint\": \"Elige tu propia LNURL o cualquier otro contacto como receptor del pago.\",\n    \"meltInputHint\": \"Pega la factura de Lightning, la LN-URL o la dirección de Lightning.\",\n    \"meltScanQRHint\": \"Crea un recibo Lightning con otro dispositivo y simplemente escanéalo.\",\n    \"meltSwapHint\": \"Elige otra ceca de tu lista de confianza como receptora del pago.\",\n    \"copyShareToken\": \"Copiar y compartir rápido\",\n    \"copyShareTokenHint\": \"Copia el token generado y compártelo a través de cualquier aplicación de mensajería.\",\n    \"sendNostr\": \"Enviar vía Nostr\",\n    \"sendNostrHint\": \"Envía Ecash directamente a uno de tus contactos en Nostr.\",\n    \"meltToken\": \"Retirar efectivo\",\n    \"mintConnectionFail\": \"Falló la conexión a la ceca\",\n    \"mintInfo\": \"Información de la ceca\",\n    \"mintNewTokens\": \"Obterner Ecash\",\n    \"mintNoContact\": \"La ceca no dispone de información de contacto\",\n    \"mntAlreadyAdded\": \"La ceca ya ha sido añadida\",\n    \"noAdditional\": \"Esta ceca no dispone de información adicional\",\n    \"noInfo\": \"La ceca no dispone de información\",\n    \"noProofs\": \"No se encontraron pruebas para esta ceca.\",\n    \"paymentOverview\": \"Información general del pago\",\n    \"processingPaymentByMint\": \"La ceca está procesando el pago de acuerdo con tu solicitud\",\n    \"processingSwap\": \"Procesando intercambio multiceca de acuerdo con tu solicitud\",\n    \"pubKey\": \"Clave pública\",\n    \"removeDefault\": \"Quitar de por defecto\",\n    \"scanQR\": \"Escanear un código QR\",\n    \"sendEcashHint\": \"Elige una ceca desde la que te gustaría crear un token Cashu.\",\n    \"setDefault\": \"Establecer como ceca por defecto\",\n    \"supportedNuts\": \"NUTs compatibles\",\n    \"swapNotAllowed\": \"No es posible retirar de una ceca de prueba.\",\n    \"zapNotAllowed\": \"No es posible enviar Zaps desde una ceca de prueba.\",\n    \"testMintHint\": \"Esta es una ceca de prueba para jugar un poco. ¿Añadir igualmente?\",\n    \"trustMintSure\": \"¿Confiar en esta ceca?\",\n    \"updatedDefault\": \"Ceca por defecto actualizada\",\n    \"newMintAdded\": \"¡Ceca añadida!\",\n    \"newMintAddedQuestion\": \"¿Quieres recibir Ecash ahora?\",\n    \"selectSwapReceiver\": \"Selecciona una ceca como receptora del pago.\",\n    \"prepairZapData\": \"Preparando los datos de la transacción...\",\n    \"lastUpdated\": \"Última actualización\",\n    \"mintInfoUpdated\": \"¡Información de la ceca actualizada!\",\n    \"mintInfoUpdateFailed\": \"Error al actualizar la información de la ceca\",\n    \"npcSettings\": \"Lightning address\",\n    \"npcDefaultAccount\": \"Default\",\n    \"npcTapToCopy\": \"Tap to copy\",\n    \"npcUsernameLabel\": \"Custom username\",\n    \"npcUsernamePlaceholder\": \"optional username\",\n    \"npcPurchaseUsername\": \"Save username\",\n    \"npcSetUsername\": \"Set Username\",\n    \"npcRequestUsername\": \"Request username\",\n    \"npcUsernameFeePrompt\": \"Do you want to set this username for a fee of {{amount}} sats?\",\n    \"npcReceiveTitle\": \"NPC Lightning addresses\",\n    \"npcReceiveHint\": \"Receive Lightning payments into your local Cashu wallet.\",\n    \"npcAccountsLabel\": \"Accounts\",\n    \"npcLocalBalance\": \"Local balance\",\n    \"npcReceiveAddress\": \"Receive address\",\n    \"npcSeedKey\": \"Seed key\",\n    \"npcImportedKey\": \"Imported key\",\n    \"npcActive\": \"Active\",\n    \"npcSyncing\": \"Syncing\",\n    \"npcPaused\": \"Paused\",\n    \"npcNpubFallback\": \"Using your npub until a username is saved\",\n    \"npcSyncAll\": \"Sync all\",\n    \"npcSynced\": \"NPC account synced\",\n    \"npcAccountAdded\": \"NPC account added\",\n    \"npcAccountRemoved\": \"NPC account removed\",\n    \"npcUsernameSaved\": \"Username saved\",\n    \"npcAddAccountTitle\": \"Add NPC account\",\n    \"npcAddAccountHint\": \"Import an existing Nostr key or derive a new key from your seed.\",\n    \"npcPrivateKeyLabel\": \"Private key\",\n    \"npcPrivateKeyPlaceholder\": \"nsec or hex\",\n    \"npcPrivateKeyHint\": \"Imported keys are stored in secure storage on this device.\",\n    \"npcPrivateKeyRequired\": \"Enter an nsec or hex private key.\",\n    \"npcImportPrivateKey\": \"Import private key\",\n    \"npcDeriveAccount\": \"Derive new key\"\n  },\n  \"topNav\": {\n    \"about\": \"Sobre nosotros\",\n    \"addressBook\": \"Agenda de contactos\",\n    \"advancedFunctions\": \"Funciones avanzadas\",\n    \"display\": \"Visualización\",\n    \"history\": \"Historial de transacciones\",\n    \"language\": \"Idioma\",\n    \"currency\": \"Moneda\",\n    \"mintSettings\": \"Gestión de ceca\",\n    \"nfcSettings\": \"Configuración NFC\",\n    \"npcSettingsTitle\": \"Lightning address\",\n    \"security\": \"Seguridad\",\n    \"settings\": \"Opciones\",\n    \"privacy\": \"Privacidad\",\n    \"general\": \"General\"\n  },\n  \"wallet\": {\n    \"cashuContent\": \"El autor de Cashu no es un criptógrafo y el protocolo está todavía bajo revisión. Esto supone ciertas reservas sobre la posible existencia de fallos críticos. Como resultado, Cashu no está listo todavía para su uso en producción.\",\n    \"cashuExperiment\": \"Cashu está todavía en fase experimental.\",\n    \"claiming\": \"Reclamando...\",\n    \"processingInvoice\": \"Procesando recibo...\",\n    \"nfcPayment\": \"Pago NFC\",\n    \"nfcKeepNearTerminal\": \"Mantén tu teléfono cerca del terminal\",\n    \"nfcSelectMaxAmount\": \"Seleccionar cantidad máxima\",\n    \"noLimit\": \"Sin límite\",\n    \"custodialRisk\": \"Riesgos custodios, las cecas poseen las claves.\",\n    \"custodialRiskContent\": \"Con eNuts, no posees las claves de tus Bitcoins; las cecas actuan como custodias. Por lo tanto, si no confías en una ceca, lo más aconsejable es evitar interactuar con ella.\",\n    \"disclaimer\": \"Por favor, ten en cuenta que esto es una verión beta en sus primeros estadios de desarrollo y que todavía está bajo pruebas supervisadas antes de su lanzamiento oficial. El programa y todo su contenido se ofrecen de forma “como está” y “como disponible”. No ofrecemos garantías, ni implícitas ni explícitas, sobre la sostenibilidad o usabilidad del programa ni de ninguno de sus contenidos..\",\n    \"enutsDisclaimer\": \"eNuts es un programa en fase beta incompleta.\",\n    \"lossContent\": \"Los tokens Cashu son tokens al portador, lo que implica que si pierdes acceso a ellos, no existe posibilidad de recuperación implementada todavía. eNuts guarda tus tokens en tu dispositivo. Antes de eliminar la aplicación, asegúrate de realizar una copia de seguridad de tus tokens.\",\n    \"lossOfTokens\": \"Perdida de fondos.\",\n    \"enutsMint\": \"La ceca por defecto de eNuts\",\n    \"mintDisclaimer\": \"El uso de la ceca por defecto de eNuts es completamente a tu cuenta y riesgo. Recomendamos encarecidamente que ejercites la cautela y la uses únicamente con fines experimentales o educativos. No existen garantías sobre su funcionalidad, seguridad o disponibilidad, y puede desaparecer sin aviso previo. Los depósitos hechos a esta ceca deben ser considerados como donativos y es posible que no sean devueltos, y, potencialmente, sean usados para posterior desarrollo del programa. Sé consciente de los riesgos asociados con programas en fase beta, es tu responsabilidad garantizar la seguridad de tus activos al usar esta ceca.\",\n    \"paidOut\": \"Pagado\",\n    \"pasteToken\": \"Redimir Ecash\",\n    \"payInvoice\": \"Pagar recibo\",\n    \"payLNInvoice\": \"Pagar recibo Lightning\",\n    \"receive\": \"Recibir\",\n    \"send\": \"Enviar\",\n    \"proofs\": \"Pruebas\",\n    \"swapped\": \"Intercambiado\"\n  }\n}\n"
  },
  {
    "path": "assets/translations/it.json",
    "content": "{\n  \"addrBook\": {\n    \"addOwnNpub\": \"Aggiungi la tua NPUB\",\n    \"favorite\": \"Preferito\",\n    \"removeFav\": \"Rimuovi preferito\",\n    \"copyNpub\": \"Copia NPUB\",\n    \"npubCopied\": \"NPUB copiata!\",\n    \"receiverNoLnurl\": \"Il destinatario non ha un LNURL\",\n    \"noResults\": \"Nessun risultato\"\n  },\n  \"auth\": {\n    \"confirmAction\": \"Confermare l'azione.\",\n    \"createPin\": \"Creare PIN\",\n    \"editPin\": \"Modifica PIN\",\n    \"pinMismatch\": \"PIN non corretto!\",\n    \"pinSetup\": \"E' possibile impostare un PIN per mettere in sicurezza l'applicazione (opzionale).\",\n    \"pleaseConfirm\": \"Conferma PIN.\",\n    \"pleaseConfirmNewPin\": \"Conferma nuovo PIN.\",\n    \"pleaseEnter\": \"Inserisci PIN.\",\n    \"pleaseNewPin\": \"Inserisi nuovo PIN.\",\n    \"removePin\": \"Elimina PIN\",\n    \"welcome\": \"Benvenuto\",\n    \"welcomeBack\": \"Ben tornato!\"\n  },\n  \"bottomNav\": {\n    \"wallet\": \"Portafoglio\",\n    \"contacts\": \"Contatti\"\n  },\n  \"common\": {\n    \"confirmReset\": \"Ripristina portafoglio\",\n    \"copy\": \"Copia\",\n    \"cycle\": \"Cycle\",\n    \"findMint\": \"Trova una mint\",\n    \"manualCounterIncrease\": \"Incrementa contatori\",\n    \"manualCounterIncreaseHint\": \"I contatori aumentano progressivamente in automatico dopo ogni transazione, tuttavia ciò potrebbe fallire in rare occasioni, portando ad errori durante il processo di ripristino del portafoglio. Incrementare manualmente i contatori potrebbe risolvere eventuali errori.\",\n    \"increaseCounterHint\": \"Incrementare i contatori? L'incremento manuale dovrebbe essere fatto solo se i contatori non sono sincronizzati\",\n    \"noMintForCounter\": \"Non ci sono mint per cui incrementare i contatori.\",\n    \"counterIncreased\": \"Contatori incrementati di {{counterIncreased}}!\",\n    \"doneSafety\": \"Processo quasi terminato... controllo di sicurezza\",\n    \"noProofsRestored\": \"Non ci sono prove utili per ripristinare il portafoglio.\",\n    \"restoreErr\": \"Qualcosa è andato storto durante il processo di ripristino del portafoglio.\",\n    \"dontClose\": \"Non chiudere l'applicazione durante il processo.\",\n    \"recoveryHint\": \"Scrivere o incollare la mnemonica di 12 parole, separate da uno spazio bianco.\",\n    \"walletRecovery\": \"Ripristino del portafoglio\",\n    \"walletRecoveryHint\": \"Utilizzare la mnemonica di backup per ripristinare il portafoglio\",\n    \"seedBackup\": \"Backup della mnemonica\",\n    \"12WordMnemonic\": \"Mnemonica di 12 parole\",\n    \"secureWallet\": \"Proteggere il portafoglio\",\n    \"secureWalletHint\": \"Generare ed annotare un backup della mnemonica per proteggere il portafoglio.\",\n    \"quickWallet\": \"Generare portafoglio\",\n    \"quickWalletHint\": \"Creare istantaneamente un nuovo portafoglio. La mnemonica di backup può essere generata in un secondo momento.\",\n    \"skipSeedHint\": \"E' possibile saltare questi passaggi e generare la mnemonica di backup in un secondo momento.\",\n    \"mnemonicHint\": \"La mnemonica verrà rivelata solo una volta. Annotarla e non condividerla con nessuno.\",\n    \"confirmMnemonicErr\": \"Parola errata! Assicurarsi di aver annotato le parole corrette e nell'ordine giusto.\",\n    \"selectRestoreMint\": \"Selezionare la mint che verrà utilizzata per recuperare i fondi.\",\n    \"recoveringWallet\": \"La mint sta ripristinando i fondi....\",\n    \"seedEnabled\": \"Mnemonica di recupero abilitata!\",\n    \"confirmSeed\": \"Confermare la mnemonica inserendo la parola corretta.\",\n    \"about\": \"Informazioni\",\n    \"aboutToLeaveTo\": \"Uscita dall'applicazione\",\n    \"accept\": \"Accetta\",\n    \"amount\": \"Importo\",\n    \"back\": \"Indietro\",\n    \"backToDashboard\": \"Tornare alla dashboard\",\n    \"balance\": \"Saldo\",\n    \"balanceAfterTX\": \"Saldo della mint dopo la TX\",\n    \"balTooLow\": \"Saldo troppo basso\",\n    \"bigQrMsg\": \"Il quantitativo di dati è eccessivo per un codice QR.\",\n    \"calculateFeeEst\": \"Calcolo delle commissioni\",\n    \"cancel\": \"Cancella\",\n    \"cashOut\": \"Preleva fondi\",\n    \"cashOutFromMint\": \"Preleva dalla mint\",\n    \"change\": \"Resto\",\n    \"claimed\": \"riscattato\",\n    \"restored\": \"ripristinato\",\n    \"claimSuccess\": \"Riscattati {{amount}} Sats::\\n{{mintUrl}}\\nMemo: {{memo}}\",\n    \"claimToken\": \"Riscatta token\",\n    \"clear\": \"Cancella\",\n    \"clipboardInvalid\": \"Gli appunti del dispositivo contengono un token Cashu non valido!\",\n    \"coinSelection\": \"Selezione delle monete\",\n    \"confirm\": \"Conferma\",\n    \"contact\": \"Contatto\",\n    \"mintDelErr\": \"Non è possibile rimuovere una mint con salto residuo\",\n    \"continue\": \"Continua\",\n    \"copied\": \"Copiato\",\n    \"shareInvoice\": \"Condividi richiesta di pagamento\",\n    \"copyToken\": \"Copia token\",\n    \"createInvoice\": \"Crea richiesta di pagamento\",\n    \"createToken\": \"Crea Token\",\n    \"createTokenErr\": \"Non è stato possibile creare un token cashu. Per favore, riprovare più tardi.\",\n    \"eventError\": \"Qualcosa è andato storto durante la pubblicazione dell'evento.\",\n    \"createViaLn\": \"Crea richiesta di pagamento\",\n    \"darkMode\": \"Modalità notturna\",\n    \"lightMode\": \"Modalità chiara\",\n    \"autoMode\": \"Modalità automatica\",\n    \"dbErr\": \"Qualcosa è andato storto durante l'inizializzazione del DB!\",\n    \"deepLinkErr\": \"Non è stato possibile aprire il link\",\n    \"default\": \"Predefinito\",\n    \"delHistory\": \"Cancella lo storico\",\n    \"factoryReset\": \"Ripristino dati di fabbrica\",\n    \"delHistoryErr\": \"Non è stato possibile cancellare lo storico.\",\n    \"delHistoryQ\": \"Cancellare lo storico?\",\n    \"resetQ\": \"Azzerare il portafoglio?\",\n    \"delHistoryTxt\": \"I dati non potranno essere recuperati successivamente.\",\n    \"display\": \"Schermo\",\n    \"disclaimer\": \"Avviso\",\n    \"restoreBattery\": \"Almeno 20% di batteria.\",\n    \"restoreBatteryHint\": \"Si raccomanda di avere almeno il 20% della batteria carica prima di inizializzare il ripristino. Il processo potrebbe durare a lungo, in base alla quantità di dati \",\n    \"restoreWifi\": \"Usare il Wi-Fi.\",\n    \"restoreWifiHint\": \"Si raccomanda di utilizzare una connessione Wi-Fi stabile durante il ripristino, per evitare qualsiasi interruzione ed assicurare un recupero veloce e sicuro dei fondi.\",\n    \"restoreForeground\": \"Mantienere l'applicazione in primo piano.\",\n    \"restoreForegroundHint\": \"Per favore mantienere l'app in primo piano e non terminarla durante il processo di ripristino, così da evitare interruzioni.\",\n    \"seedMigrationHint\": \"La mnemonica si applica a tutte le mint, tuttavia ogni mint necessita di un ripristino ad-hoc, dunque è consigliato di annotare frequentemente gli URL delle mint in uso. Se si possiedono fondi ma non ancora una mnemonica, creare un token dalla mint desiredata e riscattarlo dopo aveer generato la nuova mnemonica. Ripetere il processo per ogni mint di cui si vuole fare il backup.\",\n    \"ecashPayment\": \"Pagamento ecash\",\n    \"english\": \"Inglese\",\n    \"swahili\": \"Swahili\",\n    \"spanish\": \"Spagnolo\",\n    \"hungarian\": \"Ungherese\",\n    \"italian\": \"Italiano\",\n    \"russian\": \"Russo\",\n    \"thai\": \"Tailandese\",\n    \"chinese simplified\": \"Cinese (Semplificato)\",\n    \"chinese traditional\": \"Cinese (Tradizionale)\",\n    \"enutsRandD\": \"eNuts Telegram\",\n    \"estimatedFees\": \"Commissioni stimate\",\n    \"estimateFee\": \"Stimare le commissioni\",\n    \"expired\": \"Scaduto\",\n    \"fee\": \"Commissioni\",\n    \"swapFee\": \"Commissione di swap\",\n    \"feeErr\": \"Non è stato possibile stimare le commissioni necessarie. \\\"{{input}}\\\" è un LNURL valido?\",\n    \"foundCashuClipboard\": \"Token cashu rilevato\",\n    \"french\": \"Francese\",\n    \"from\": \"da\",\n    \"fromMint\": \"dalla seguente mint\",\n    \"sendingFrom\": \"Invio da\",\n    \"german\": \"Tedesco\",\n    \"github\": \"GitHub\",\n    \"githubIssues\": \"Segnala bug su Github\",\n    \"reportIssue\": \"Segnala un problema\",\n    \"shareOrReport\": \"Condividi feedback o segnala bug\",\n    \"historyDeleted\": \"Storico eliminato\",\n    \"invalidInvoice\": \"richiesta di pagamento non valida\",\n    \"invalidOrSpent\": \"Token non valido o già riscattato\",\n    \"invalidToken\": \"Token non valido\",\n    \"invoice\": \"richiesta di pagamento\",\n    \"invoiceExpired\": \"richiesta di pagamento scaduta\",\n    \"invoiceInclFee\": \"richiesta di pagamento (commissioni incluse)\",\n    \"invoiceOrLnurl\": \"richiesta di pagamento LN o LNURL\",\n    \"invoiceOrLnAddress\": \"Fattura o Indirizzo\",\n    \"keysetID\": \"Keyset ID\",\n    \"language\": \"Lingua\",\n    \"currency\": \"Valuta\",\n    \"currencyConversion\": \"Conversione valuta\",\n    \"showFiatBalance\": \"Mostra saldo in fiat\",\n    \"showFiatBalanceDesc\": \"Mostra il saldo e gli importi nella valuta fiat selezionata\",\n    \"selectCurrency\": \"Seleziona valuta\",\n    \"lastUpdate\": \"Aggiornato\",\n    \"loadingRates\": \"Caricamento tassi di cambio...\",\n    \"ratesUnavailable\": \"Tassi di cambio non disponibili\",\n    \"ratesUnavailableDesc\": \"Impossibile caricare i tassi di cambio. Controlla la connessione internet e riprova.\",\n    \"ratesRequiredForFiat\": \"Tassi di cambio necessari per abilitare la visualizzazione in fiat\",\n    \"noCurrenciesAvailable\": \"Nessuna valuta disponibile. Riprova a caricare i tassi di cambio.\",\n    \"retry\": \"Riprova\",\n    \"lnInvoice\": \"richiesta di pagamento lightning\",\n    \"lnPayment\": \"Pagamento lightning\",\n    \"mint\": \"Mint\",\n    \"minted\": \"creato\",\n    \"multimintSwap\": \"Scambio tra mint\",\n    \"n/a\": \"Non disponibile\",\n    \"name\": \"Nome\",\n    \"no\": \"No\",\n    \"noCamAccess\": \"Nessun accesso alla fotocamera\",\n    \"noFunds\": \"Fondi insufficienti\",\n    \"noFundsForFee\": \"Fondi insufficienti, si prega di lasciare margine spazio per eventuali commissioni: ~{{fee}} sats.\",\n    \"noMint\": \"Nessuna mint trovata\",\n    \"notQrCode\": \"Non è un codice QR!\",\n    \"noTX\": \"Nessuna transazione\",\n    \"activity\": \"Attività\",\n    \"allHistory\": \"Tutto\",\n    \"optionalMemo\": \"Nota opzionale\",\n    \"paste\": \"Incolla\",\n    \"paymentPending\": \"Pagamento in sospeso\",\n    \"paymentSuccess\": \"Pagamento avvenuto con successo!\",\n    \"nostrPaymentSuccess\": \"inviato!\",\n    \"paymentType\": \"Modalità di pagamento\",\n    \"payWithLn\": \"Pagare con portafoglio LN\",\n    \"preferences\": \"Preferenze\",\n    \"readme\": \"Leggimi\",\n    \"sender\": \"Mittente\",\n    \"recipient\": \"Destinatario\",\n    \"reqTimeout\": \"Errore di timeout per la richiesta di rete\",\n    \"restore\": \"Ripristina\",\n    \"save\": \"Salva\",\n    \"scanAgain\": \"Scansiona ancora\",\n    \"scan\": \"Scansiona\",\n    \"scanQR\": \"Scansiona QR\",\n    \"qrScanHint\": \"Posiziona il codice QR nel riquadro\",\n    \"qrScanFormats\": \"Cashu, Lightning, LNURL o Bitcoin\",\n    \"qrScanReady\": \"Pronto per la scansione\",\n    \"qrScanPaused\": \"Scansione in pausa\",\n    \"animatedQrProgress\": \"Avanzamento QR animato\",\n    \"receivingAnimatedQr\": \"Ricezione QR animato\",\n    \"unsupportedFormat\": \"Formato non supportato\",\n    \"cashuPaymentRequestQrUnsupported\": \"Le richieste di pagamento Cashu da QR non sono ancora supportate\",\n    \"bitcoinAddressPaymentsUnsupported\": \"I pagamenti a indirizzi Bitcoin non sono supportati\",\n    \"cameraAccessRequired\": \"Accesso alla fotocamera richiesto\",\n    \"cameraAccessDenied\": \"Accesso alla fotocamera negato\",\n    \"cameraAccessRequiredHint\": \"Serve l'accesso alla fotocamera per scansionare codici QR di pagamenti e token.\",\n    \"cameraAccessDeniedHint\": \"Abilita l'accesso alla fotocamera nelle impostazioni del dispositivo per scansionare codici QR.\",\n    \"allowCameraAccess\": \"Consenti accesso fotocamera\",\n    \"openSettings\": \"Apri impostazioni\",\n    \"seconds\": \"secondi\",\n    \"selectAmount\": \"Seleziona importo\",\n    \"selected\": \"Selezionato\",\n    \"selectMint\": \"Selezionare una mint da cui inviare\",\n    \"selectMints\": \"Selezionare mint\",\n    \"sendEcash\": \"Invia ecash\",\n    \"share\": \"Condividi\",\n    \"submitPaymentReq\": \"Preleva\",\n    \"to\": \"a\",\n    \"today\": \"Oggi\",\n    \"tokenInfoErr\": \"Errore durante il recupero delle informazioni sul token\",\n    \"totalInclFee\": \"Totale (commissioni incluse)\",\n    \"reservedTotal\": \"Totale riservato\",\n    \"trustMint\": \"Affidarsi a questa mint?\",\n    \"tryLater\": \"Riprovare più tardi.\",\n    \"unknownType\": \"Dato sconosciuto\",\n    \"version\": \"Versione\",\n    \"viewMnemonic\": \"Visualizza Mnemonico\",\n    \"wallet\": \"Portafoglio\",\n    \"willDoLater\": \"Più tardi\",\n    \"yes\": \"Sì\",\n    \"invalidPubKey\": \"Chiave pubblica non valida!\",\n    \"walletLocked\": \"Portafoglio bloccato\",\n    \"explainer1\": \"eNuts è un portafoglio lightning custodial, che permette transazioni istantanee e private grazie al protocollo Cashu. I fondi sono detenuti dalle mint con cui l'utente interagisce, i token ecash sono conservati localmente nel dispositivo.\",\n    \"explainer2\": \"Cashu è un nuovo protocollo ecash per applicazioni custodial, dove le mint sono nodi lightning che eseguono transazioni bitcoin e forniscono ecash. La mint non è a conoscenza dei pagamenti ecash degli utenti.\",\n    \"explainer3\": \"Per ricevere ecash è necessario semplicemente inserire una mint tramite URL e pagare una richiesta di pagamento lightning. eNuts permette di reicevere pagamenti istantanei da chiunque aggiungendo le mint con il permesso dell'utente. Scambiare i fondi tra le mint ed inviare ecash non appena si ha un saldo all'interno del portafoglio.\",\n    \"send&receive\": \"Invia & ricevi\",\n    \"contactsNostr\": \"Contatti & Nostr\",\n    \"nostrExplainer\": \"L'integrazione con Nostr permette di sincronizzare i contatti senza la necessità di inserire la chiave privata, poichè eNuts ne genera una nuova. I dati sono mostrati utilizzando la chiave pubblica dell'utente, mentre la nuova chiave privata viene utilizzata per criptare/decriptare i messaggi.\",\n    \"send\": \"Invia\",\n    \"sendEcashDashboard\": \"Crea un token Cashu ed invialo a chi preferisci.\",\n    \"payInvoiceDashboard\": \"Invia i tuoi fondi ad un nodo lightning.\",\n    \"receiveEcashDashboard\": \"Incolla & riscatta un token Cashu dagli appunti.\",\n    \"receiveEcashNostr\": \"Messaggi Nostr\",\n    \"receiveEcashNostrHint\": \"Controlla i messaggi Nostr alla ricerca di ecash.\",\n    \"createInvoiceDashboard\": \"Ricevi ecash pagando un richiesta di pagamento lightning.\",\n    \"hideNuts\": \"Nascondere saldo\",\n    \"checkingDms\": \"Verificando eventuali token ecash tra i messaggi...\",\n    \"clearOverHere\": \"Niente di nuovo!\",\n    \"totalDmsReceived\": \"{{totalDms}} token Cashu ricevuti.\",\n    \"swapNow\": \"Scambiare adesso\",\n    \"swap\": \"Scambiare\",\n    \"emptyMint\": \"Mint senza fondi\",\n    \"zapSoon\": \"Gli zap verranno aggiunti a breve...\",\n    \"enutsPub\": \"Chiave pubblica di eNuts: \",\n    \"seeFullHistory\": \"Visualizzarere lo storico delle transazioni\",\n    \"next\": \"Prossimo\",\n    \"skip\": \"Salta\",\n    \"donateLn\": \"Dona\",\n    \"supportHint\": \"Ogni donazione, anche la più piccola, ha un impatto significativo. Grazie per il sostegno.\",\n    \"newToken\": \"Nuovo token Cashu\",\n    \"disclaimerHint\": \"Questo annuncio ha un'enorme importanza, non deve essere sottovalutato o ignorato. Apprezziamo il tuo interesse in questo progetto e continueremo a lavorare per migliorarlo.\",\n    \"searchContacts\": \"Cerca o inserisci NPUB\",\n    \"submit\": \"Invia\",\n    \"clearMetadataCache\": \"Elimina la cache dei metadati\",\n    \"clearMetadataCacheHint\": \"Eliminare la cache dei metadati?\",\n    \"clearImageCache\": \"Elimina la cache dell'immagine\",\n    \"clearImageCacheHint\": \"Eliminare la cache dell'immagine?\",\n    \"pullRefresh\": \"Trascina per aggiornare\",\n    \"processTestPay\": \"Processando il pagamento di test...\",\n    \"confirmMint\": \"Confermare nuova mint\",\n    \"confirmMintHint\": \"Sicuro di voler aggiungere questa mint?\",\n    \"npubAlreadyAdded\": \"NPUB già aggiunta\",\n    \"replaceNpub\": \"Sostituisci NPUB\",\n    \"replaceNpubTxt\": \"Sicuro di voler sostituire l'NPUB attuale?\",\n    \"npubAdded\": \"NPUB aggiunta!\",\n    \"showContacts\": \"Mostra contatti\",\n    \"topUpNow\": \"Ottieni Ecash ora\",\n    \"scanAnother\": \"Scannerizza un altro codice QR\",\n    \"deleteNpub\": \"Eliminare NPUB?\",\n    \"delNpubHint\": \"Tutti i contatti e i dati correlati verranno eliminati.\",\n    \"addNewNpub\": \"Aggiungere una nuova NPUB?\",\n    \"addNpubHint\": \"Questa procedura cancellerà tutti i dati associati alla NPUB attuale.\",\n    \"zap\": \"Zap\",\n    \"zapNow\": \"Invia zap\",\n    \"meltNostrProfileHint\": \"Trasferire fondi all'indirizzo LN associato al profilo Nostr.\",\n    \"nostrDmHint\": \"eNuts non può accedere ai messaggi Nostr poichè non ha accesso alla chiave privata. eNuts genera una nuova chiave per inviare Ecash: quando del Ecash è inviato su Nostr, il destinatario lo riceve tramite la nuova chiave pubblica generata da eNuts. Se il ricevente risponde al messaggio con un token Ecash, sarà possibile visualizzare il token qui. Stiamo lavorando attivamente ad una soluzione sicura per la gestione di chiavi private Nostr\",\n    \"nostrIssueHeader\": \"Si è verificato un errore riguardante i contatti Nostr\",\n    \"nostrIssueHint\": \"Se non è possibile aprire la lista di contatti Nostr, cliccare il pulsante sotto o eseguire un reset dei dati Nostr in 'opzioni' > 'contatti' > 'ripristina dati' per risolvere il problema.\",\n    \"submitNostrIssue\": \"Ripristina dati\",\n    \"nostrIssueSuccess\": \"Reset dei dati Nostr terminato con successo!\",\n    \"createLnInvoice\": \"Crea richiesta di pagamento Lightning\",\n    \"metadataCacheCleared\": \"Cache dei metadati eliminata!\",\n    \"imageCacheCleared\": \"Cache dell'immagine eliminata!\",\n    \"leaveGithubStar\": \"Supportaci con una stella su Github\",\n    \"alreadySpentHint\": \"Alcune prove che compongono il saldo sono state spese o riscattate altrove. Risolvere l'errore cancellando le prove in 'Opzioni' > 'Gestione mint' > 'Controlla prove'\",\n    \"useNpub\": \"Usare NPUB\",\n    \"autoSwapToDefaulMint\": \"Scambiare automaticamente con la mint di default\",\n    \"trustMintOpt\": \"Affidarsi alla mint\",\n    \"swapHint\": \"Questa opzione richiede un pagamento Lightning, un pagamento di commissioni e potrebbe aggiungere una mint sconosciuta alla lista mint.\",\n    \"trustHint\": \"La mint associata al token verrà aggiunta alla lista di mint affidabili\",\n    \"noDefaultHint\": \"Per eseguire un scambio automatico è necessario impostare una mint predefinita.\",\n    \"autoSwapSuccess\": \"Scambio eseguito con successo!\",\n    \"paidInvoice\": \"{{ count }} richiesta di pagamento pagata con un totale di {{ total }} Sat\",\n    \"paidInvoices\": \"{{ count }} richieste di pagamento pagate con un totale di {{ total }} Sat\",\n    \"checkPayment\": \"Controllare pagamento\",\n    \"lnPaymentSpamHint\": \"Attendere {{ remainingSeconds }} secondi per evitare di sovraccaricare la mint.\",\n    \"supportUs\": \"Supportaci\",\n    \"shareEnuts\": \"Condividi eNuts con qualcuno\",\n    \"justNow\": \"Adesso\",\n    \"hoursAgo\": \"{{count}} ore fa\",\n    \"yesterday\": \"Ieri\",\n    \"awaitingPayment\": \"In attesa del pagamento\",\n    \"receivedFromMint\": \"Ricevuto dalla mint\",\n    \"status\": \"Stato\",\n    \"unit\": \"Unità\",\n    \"quoteId\": \"ID preventivo\",\n    \"nfcPaymentLimits\": \"Limiti di pagamento\",\n    \"nfcPaymentLimitsDesc\": \"Imposta limiti di importo predefiniti e personalizzati per i pagamenti NFC\",\n    \"amountLimits\": \"Limiti di importo\",\n    \"amountLimitsDesc\": \"Tocca per impostare come predefinito, tieni premuto per eliminare\",\n    \"noLimit\": \"Nessun limite\",\n    \"noLimitDesc\": \"Conferma qualsiasi importo\",\n    \"deleteAmount\": \"Elimina importo\",\n    \"deleteAmountConfirm\": \"Sei sicuro di voler rimuovere {{amount}} sats dai tuoi importi di selezione rapida?\",\n    \"delete\": \"Elimina\",\n    \"resetToDefaults\": \"Ripristina predefiniti\"\n  },\n  \"error\": {\n    \"checkSpendableErr\": \"Errore di verifica del token\",\n    \"claimTokenErr\": \"Errore nel riscatto del token\",\n    \"sendTokenErr\": \"Errore durante l'invio del token\",\n    \"header\": \"Errore\",\n    \"msg\": \"Purtroppo si è verificato un errore. Puoi aiutarci a migliorare eNuts facendo uno screenshot e riportandoci il bug.\",\n    \"reportBug\": \"Segnalare il bug\",\n    \"requestMintErr\": \"Errore nel recuperare richiesta di pagamento dalla mint.\",\n    \"stackNA\": \"Stack di errore non disponibile\",\n    \"generalMeltingErr\": \"Non è stato possibile trovare un percorso di pagamento tra la mint e il nodo.\",\n    \"invoiceFromLnurlError\": \"Non è stato possibile creare una richiesta di pagamento utilizzando l'LNURL.\",\n    \"invoiceScanError\": \"Non è stato possibile utilizzare la richiesta di pagamento fornita dal codice QR.\"\n  },\n  \"history\": {\n    \"checkSpent\": \"Verificare se il token è stato speso\",\n    \"isPending\": \"Token in sospeso\",\n    \"isSpent\": \"Token speso\",\n    \"justNow\": \"Adesso\",\n    \"hoursAgo\": \"{{count}} ore fa\",\n    \"yesterday\": \"Ieri\",\n    \"memo\": \"Memo\",\n    \"nHrsAgo\": \"{{hrs}} ore fa\",\n    \"nMinsAgo\": \"{{mins}} minuti fa\",\n    \"noMemo\": \"Nessuna memo\",\n    \"oneHrAgo\": \"1 ora fa\",\n    \"oneMinAgo\": \"1 minuto fa\",\n    \"paymentHash\": \"Hash del pagamento\",\n    \"settleTime\": \"Tempo di transazione\",\n    \"showQr\": \"Mostra codice QR\",\n    \"receive\": \"Ricevi\",\n    \"send\": \"Invia\",\n    \"melt\": \"Fondi\",\n    \"receivedEcash\": \"Ecash ricevuto\",\n    \"sentEcash\": \"Ecash inviato\",\n    \"paidInvoice\": \"Fattura pagata\",\n    \"details\": \"Dettagli\",\n    \"date\": \"Data\",\n    \"amount\": \"Importo\",\n    \"token\": \"Token\"\n  },\n  \"mints\": {\n    \"addCustomName\": \"Aggiungi nome personalizzato\",\n    \"additionalInfo\": \"Informazioni aggiuntive\",\n    \"addMintBtn\": \"Aggiungere mint\",\n    \"addNewMint\": \"Aggiungere nuova mint\",\n    \"atLeast2Mints\": \"Sono necessarie almeno 2 mint per eseguire uno scambio multi-mint.\",\n    \"awaitingInvoice\": \"In attesa di richiesta di pagamento\",\n    \"cashOutAmountHint\": \"Un pagamento lightning potrebbe richiedere commissioni: al pagamento verrà aggiunta una fee stimata ed eventuali rimanenze verranno rimborsate.\",\n    \"checkProofs\": \"Controlla prove\",\n    \"checkProofsQ\": \"Controllare tutte le prove?\",\n    \"checkProofsTxt\": \"Questo processo controllerà se i token sono spendibili, altrimenti li cancellerà.\",\n    \"chooseMeltMintHint\": \"Scegliere una mint da cui prelevare i fondi.\",\n    \"chooseMintHint\": \"Scegliere una mint da cui ricevere ecash. La mint diventerà il custode dei fondi.\",\n    \"chooseTarget\": \"Scegliere destinatario del pagamento.\",\n    \"coinSelectionHint\": \"Il saldo ecash è essenzialmente una collezione di monete. La selezione delle monete permette di scegliere quali spendere. Ogni tranche di monete ha un keyset-ID definito dalla mint, il quale potrebbe cambiare nel tempo. Nuovi keyset sono evidenziati in verde. E' consigliabile spendere prima i keyset più vecchi.\",\n    \"creatingEcashToken\": \"Token Cashu creato\",\n    \"sendingEcashViaNostr\": \"Inviando token Cashu attraverso Nostr!\",\n    \"customName\": \"Nome personalizzato\",\n    \"cutomNameAdded\": \"Nome personalizzato aggiunto\",\n    \"dangerZone\": \"Zona di pericolo\",\n    \"deletedProofs\": \"{{proofsToDel}} prove cancellate.\",\n    \"delMint\": \"Cancellare mint\",\n    \"delMintSure\": \"Rimuovere questa mint?\",\n    \"ecashAmountHint\": \"Selezionare l'ammontare di Ecash da inviare.\",\n    \"editMintName\": \"Modificare il nome della mint\",\n    \"errDelProofs\": \"Qualcosa è andato storto nella cancellazione delle prove.\",\n    \"funds\": \"Fondi\",\n    \"general\": \"Generali\",\n    \"importantNotice\": \"Avviso importante\",\n    \"inputField\": \"richiesta di pagamento LN o LNURL\",\n    \"invalidUrl\": \"URL invalido\",\n    \"invoiceAmountHint\": \"Selezionare l'ammontare di Ecash da ricevere. La mint creerà una richiesta di pagamento da pagare utilizzando un portafoglio lightning.\",\n    \"invoiceHint\": \"Potrebbe richiedere alcuni secondi...\",\n    \"lowBal\": \"Saldo della mint troppo basso!\",\n    \"meltAddressbookHint\": \"Scegli LNURL o un altro contatto come destinatario del pagamento.\",\n    \"meltInputHint\": \"Incollare richiesta di pagamento lightning, LNURL o lightning address.\",\n    \"meltScanQRHint\": \"Creare richiesta di pagamento lightning con un altro dispositivo ed inquadrare il codice QR.\",\n    \"meltSwapHint\": \"Scegliere mint destinataria del pagamento.\",\n    \"copyShareToken\": \"Copia & condividi\",\n    \"copyShareTokenHint\": \"Copiare il token e condividerlo attraverso qualunque applicazione di messaggistica\",\n    \"sendNostr\": \"Inviare attraverso Nostr\",\n    \"sendNostrHint\": \"Inviare Ecash direttamente ad uno dei contatti Nostr.\",\n    \"meltToken\": \"Preleva\",\n    \"mintConnectionFail\": \"Connessione alla mint fallita\",\n    \"mintInfo\": \"Informazioni sulla mint\",\n    \"mintNewTokens\": \"Ottieni Ecash\",\n    \"mintNoContact\": \"La mint non ha informazioni di contatto\",\n    \"mntAlreadyAdded\": \"Mint già aggiunta\",\n    \"noAdditional\": \"Questa mint non ha informazioni aggiuntive\",\n    \"noInfo\": \"Questa mint non ha informazioni\",\n    \"noProofs\": \"Nessuna prova trovata per questa mint.\",\n    \"paymentOverview\": \"Riepilogo pagamento\",\n    \"processingPaymentByMint\": \"La mint sta processando il pagamento come richiesto\",\n    \"processingSwap\": \"Processando lo scambio tra mint come richiesto\",\n    \"pubKey\": \"Chiave pubblica\",\n    \"removeDefault\": \"Rimuovere predefinito\",\n    \"scanQR\": \"Scansionare codice QR\",\n    \"sendEcashHint\": \"Sceglere una mint da cui creare un token Cashu.\",\n    \"setDefault\": \"Impostare come mint predefinita\",\n    \"supportedNuts\": \"NUT supportate\",\n    \"swapNotAllowed\": \"Non è possibile effettuare uno scambio da una mint di test.\",\n    \"zapNotAllowed\": \"Non è possibile effettuare uno zap da una mint di test.\",\n    \"testMintHint\": \"Questa è una mint di test, aggiungere ugualmente?\",\n    \"trustMintSure\": \"Affidarsi a questa mint?\",\n    \"updatedDefault\": \"Mint predefinita aggiornata\",\n    \"newMintAdded\": \"Mint aggiunta!\",\n    \"newMintAddedQuestion\": \"Ricevere Ecash ora?\",\n    \"selectSwapReceiver\": \"Selezionare mint destinataria del pagamento.\",\n    \"prepairZapData\": \"Preparando i dati della transazione...\",\n    \"lastUpdated\": \"Ultimo aggiornamento\",\n    \"mintInfoUpdated\": \"Informazioni mint aggiornate!\",\n    \"mintInfoUpdateFailed\": \"Aggiornamento informazioni mint fallito\",\n    \"npcSettings\": \"Lightning address\",\n    \"npcDefaultAccount\": \"Default\",\n    \"npcTapToCopy\": \"Tap to copy\",\n    \"npcUsernameLabel\": \"Custom username\",\n    \"npcUsernamePlaceholder\": \"optional username\",\n    \"npcPurchaseUsername\": \"Save username\",\n    \"npcSetUsername\": \"Set Username\",\n    \"npcRequestUsername\": \"Request username\",\n    \"npcUsernameFeePrompt\": \"Do you want to set this username for a fee of {{amount}} sats?\",\n    \"npcReceiveTitle\": \"NPC Lightning addresses\",\n    \"npcReceiveHint\": \"Receive Lightning payments into your local Cashu wallet.\",\n    \"npcAccountsLabel\": \"Accounts\",\n    \"npcLocalBalance\": \"Local balance\",\n    \"npcReceiveAddress\": \"Receive address\",\n    \"npcSeedKey\": \"Seed key\",\n    \"npcImportedKey\": \"Imported key\",\n    \"npcActive\": \"Active\",\n    \"npcSyncing\": \"Syncing\",\n    \"npcPaused\": \"Paused\",\n    \"npcNpubFallback\": \"Using your npub until a username is saved\",\n    \"npcSyncAll\": \"Sync all\",\n    \"npcSynced\": \"NPC account synced\",\n    \"npcAccountAdded\": \"NPC account added\",\n    \"npcAccountRemoved\": \"NPC account removed\",\n    \"npcUsernameSaved\": \"Username saved\",\n    \"npcAddAccountTitle\": \"Add NPC account\",\n    \"npcAddAccountHint\": \"Import an existing Nostr key or derive a new key from your seed.\",\n    \"npcPrivateKeyLabel\": \"Private key\",\n    \"npcPrivateKeyPlaceholder\": \"nsec or hex\",\n    \"npcPrivateKeyHint\": \"Imported keys are stored in secure storage on this device.\",\n    \"npcPrivateKeyRequired\": \"Enter an nsec or hex private key.\",\n    \"npcImportPrivateKey\": \"Import private key\",\n    \"npcDeriveAccount\": \"Derive new key\"\n  },\n  \"topNav\": {\n    \"about\": \"Chi siamo\",\n    \"addressBook\": \"Rubrica\",\n    \"advancedFunctions\": \"Impostazioni avanzate\",\n    \"display\": \"Schermo\",\n    \"history\": \"Storico transazioni\",\n    \"language\": \"Lingua\",\n    \"currency\": \"Valuta\",\n    \"mintSettings\": \"Gestione mint\",\n    \"nfcSettings\": \"Impostazioni NFC\",\n    \"npcSettingsTitle\": \"Lightning address\",\n    \"security\": \"Sicurezza\",\n    \"settings\": \"Opzioni\",\n    \"privacy\": \"Privacy\",\n    \"general\": \"Generali\"\n  },\n  \"wallet\": {\n    \"cashuContent\": \"L'autore di Cashu non è un crittografo ed il protocollo è in fase di revisione. E' possibile che vi siano difetti fatali nell'architettura del protocollo, di conseguenza Cashu non è considerabile pronto per il rilascio in produzione.\",\n    \"cashuExperiment\": \"Cashu è un protocollo in fase sperimentale.\",\n    \"claiming\": \"Richiesta...\",\n    \"processingInvoice\": \"Processando la richiesta di pagamento...\",\n    \"nfcPayment\": \"Pagamento NFC\",\n    \"nfcKeepNearTerminal\": \"Tieni il telefono vicino al terminale\",\n    \"nfcSelectMaxAmount\": \"Seleziona importo massimo\",\n    \"noLimit\": \"Nessun limite\",\n    \"custodialRisk\": \"Rischio di custodia, la mint detiene le chiavi.\",\n    \"custodialRiskContent\": \"Con eNuts l'utente non possiede le chiavi di custodia dei bitcoin poichè la mint stessa agisce come custode. Di conseguenza, in caso di mancanza di fiducia in una mint, è consigliabile non interagire con essa.\",\n    \"disclaimer\": \"Si ricorda che eNuts è in beta ed ancora in fase di test prima del rilascio ufficiale. Il software e tutti i contenuti presenti su di esso sono forniti sulla base 'così come sono' e 'come disponibili'. Non si fornisce alcuna garanzia, sia espressa che implicita, sulla idoneità o utilizzabilità del software o di qualsiasi suo contenuto.\",\n    \"enutsDisclaimer\": \"eNuts è un software beta e non completo.\",\n    \"lossContent\": \"I token Cashu sono titoli al portatore, perdere l'accesso ad essi implica l'impossibilità nel recuperarli. eNuts conserva i token nel device. Prima di cancellare l'applicazione, assicurarsi di effettuare il backup dei token.\",\n    \"lossOfTokens\": \"Perdita di fondi.\",\n    \"enutsMint\": \"Mint di predefinita di eNuts\",\n    \"mintDisclaimer\": \"L'utilizzo della mint predefinita è interamente a proprio rischio. Si raccomanda cautela ed un utilizzo solo a scopo didattico e di sperimentazione. Non vi sono garanzie circa il suo funzionamento, sicurezza o disponibilità, poichè potrebbe diventare non disponibile senza alcun preavviso. I depositi effettuati presso questa mint si considerano donazioni e potrebbero non essere riscattabili. E' necessario essere consapevoli dei rischi associati all'utilizzo di software beta; la salvaguardia degli asset mentre questa mint è in uso è responsabilità dell'utente.\",\n    \"paidOut\": \"Pagato\",\n    \"pasteToken\": \"Riscatta Ecash\",\n    \"payInvoice\": \"Paga richiesta di pagamento\",\n    \"payLNInvoice\": \"Paga richiesta di pagamento lightning\",\n    \"receive\": \"Ricevi\",\n    \"send\": \"Invia\",\n    \"proofs\": \"Prova\",\n    \"swapped\": \"Scambiato\"\n  }\n}\n"
  },
  {
    "path": "assets/translations/ru.json",
    "content": "{\n  \"addrBook\": {\n    \"addOwnNpub\": \"Добавьте свой NPUB\",\n    \"favorite\": \"Добавить в избранное\",\n    \"removeFav\": \"Убрать из избранного\",\n    \"copyNpub\": \"Копировать NPUB\",\n    \"npubCopied\": \"NPUB скопирован!\",\n    \"receiverNoLnurl\": \"У получателя нет LNURL\",\n    \"noResults\": \"Безрезультатно\"\n  },\n  \"auth\": {\n    \"confirmAction\": \"Пожалуйста, подтвердите действие.\",\n    \"createPin\": \"Создать PIN-код\",\n    \"editPin\": \"Редактировать PIN-код\",\n    \"pinMismatch\": \"Неправильный PIN-код!\",\n    \"pinSetup\": \"При желании Вы можете установить PIN-код для защиты Вашего приложения.\",\n    \"pleaseConfirm\": \"Пожалуйста, подтвердите свой PIN-код.\",\n    \"pleaseConfirmNewPin\": \"Пожалуйста, подтвердите свой новый PIN-код.\",\n    \"pleaseEnter\": \"Пожалуйста, введите свой PIN-код.\",\n    \"pleaseNewPin\": \"Пожалуйста, введите новый PIN-код.\",\n    \"removePin\": \"Удалить PIN-код\",\n    \"welcome\": \"Добро пожаловать!\",\n    \"welcomeBack\": \"Добро пожаловать!\"\n  },\n  \"bottomNav\": {\n    \"wallet\": \"Кошелёк\",\n    \"contacts\": \"Контакты\"\n  },\n  \"common\": {\n    \"confirmReset\": \"Сбросить кошелёк\",\n    \"copy\": \"Копировать\",\n    \"cycle\": \"Цикл\",\n    \"findMint\": \"Найти монетный двор\",\n    \"manualCounterIncrease\": \"Обновление счётчиков\",\n    \"manualCounterIncreaseHint\": \"Счётчики обновляются автоматически после каждой транзакции, но в редких случаях может произойти сбой, что приведет к ошибкам в процессе восстановления. Обновление счётчиков вручную может помочь.\",\n    \"increaseCounterHint\": \"Вы уверены, что хотите обновить счётчики? Это следует делать только в том случае, если Вы уверены, что счётчики не синхронизированы.\",\n    \"noMintForCounter\": \"У вас нет монет для обновления счётчиков.\",\n    \"counterIncreased\": \"Счётчики обновлены на {{counterIncreased}}!\",\n    \"doneSafety\": \"Почти готово... Проверка безопасности\",\n    \"noProofsRestored\": \"Не найдено доказательств для восстановления вашего кошелька.\",\n    \"restoreErr\": \"Что-то пошло не так при восстановлении вашего кошелька.\",\n    \"dontClose\": \"Пожалуйста, не закрывайте приложение во время процесса.\",\n    \"recoveryHint\": \"Напишите или вставьте мнемонику из 12 слов в правильном порядке, разделив их пробелами.\",\n    \"walletRecovery\": \"Восстановление кошелька\",\n    \"walletRecoveryHint\": \"Используйте seed-фразу для восстановления Вашего кошелька.\",\n    \"seedBackup\": \"Восстановление с помощью seed-фразы\",\n    \"12WordMnemonic\": \"Seed-фраза из 12 слов\",\n    \"secureWallet\": \"Безопасность кошелька\",\n    \"secureWalletHint\": \"Создайте и перепишите seed-фразу, чтобы обезопасить свой кошелёк.\",\n    \"quickWallet\": \"Мгновенный кошелек\",\n    \"quickWalletHint\": \"Создайте новый кошелек мгновенно. Seed-фразу можно создать позже.\",\n    \"skipSeedHint\": \"Вы можете пропустить этот процесс и создать seed-фразу позже.\",\n    \"mnemonicHint\": \"Seed-фраза больше никогда не будет отображаться. Перепишите её и никогда никому её не показывайте.\",\n    \"confirmMnemonicErr\": \"Неверное слово! Пожалуйста, убедитесь, что записали seed-фразу правильно и в правильном порядке.\",\n    \"selectRestoreMint\": \"Пожалуйста, выберите монетный двор, который будет использоваться для восстановления ваших средств.\",\n    \"recoveringWallet\": \"Монетный двор восстанавливает ваши средства...\",\n    \"seedEnabled\": \"Восстановление включено!\",\n    \"confirmSeed\": \"Пожалуйста, подтвердите свою seed-фразу, введя правильное слово.\",\n    \"about\": \"О нас\",\n    \"aboutToLeaveTo\": \"Вы собираетесь уйти\",\n    \"accept\": \"Принять\",\n    \"amount\": \"Сумма\",\n    \"back\": \"Назад\",\n    \"backToDashboard\": \"На главную\",\n    \"balance\": \"Баланс\",\n    \"balanceAfterTX\": \"Баланс после транзакции\",\n    \"balTooLow\": \"Недостаточно средств\",\n    \"bigQrMsg\": \"Объем данных слишком велик для QR-кода.\",\n    \"calculateFeeEst\": \"Расчет комиссии\",\n    \"cancel\": \"Отмена\",\n    \"cashOut\": \"Вывод средств\",\n    \"cashOutFromMint\": \"Вывод денег из монетного двора\",\n    \"change\": \"Изменение\",\n    \"claimed\": \"поступили\",\n    \"restored\": \"восстановлен\",\n    \"claimSuccess\": \"Поступили {{amount}} Сат:\\n{{mintUrl}}\\nMemo: {{memo}}\",\n    \"claimToken\": \"Вернуть токен\",\n    \"clear\": \"Очистить\",\n    \"clipboardInvalid\": \"Ваш буфер обмена содержит недействительные монеты!\",\n    \"coinSelection\": \"Выбор монет\",\n    \"confirm\": \"Подтвердить\",\n    \"contact\": \"Контакт\",\n    \"mintDelErr\": \"Невозможно удалить монетный двор при оставшемся балансе\",\n    \"continue\": \"Продолжить\",\n    \"copied\": \"Скопировано\",\n    \"shareInvoice\": \"Поделиться счётом\",\n    \"copyToken\": \"Скопировать токен\",\n    \"createInvoice\": \"Создать счёт-фактуру\",\n    \"createToken\": \"Создать токен\",\n    \"createTokenErr\": \"Не удалось создать монеты. Пожалуйста, повторите попытку позже.\",\n    \"eventError\": \"Что-то пошло не так при публикации.\",\n    \"createViaLn\": \"Создать LN-счёт\",\n    \"darkMode\": \"Тёмный режим\",\n    \"lightMode\": \"Светлый режим\",\n    \"autoMode\": \"Автоматический режим\",\n    \"dbErr\": \"Что-то пошло не так при инициализации базы данных!\",\n    \"deepLinkErr\": \"Ссылку не удалось открыть\",\n    \"default\": \"По умолчанию\",\n    \"delHistory\": \"Удалить историю\",\n    \"factoryReset\": \"Сброс к заводским настройкам\",\n    \"delHistoryErr\": \"Не удалось удалить историю.\",\n    \"delHistoryQ\": \"Удалить историю?\",\n    \"resetQ\": \"Сбросить кошелек?\",\n    \"delHistoryTxt\": \"Данные не будут подлежать восстановлению.\",\n    \"display\": \"Дисплей\",\n    \"disclaimer\": \"Отказ от ответственности\",\n    \"restoreBattery\": \"Не менее 20% заряда батареи.\",\n    \"restoreBatteryHint\": \"Мы рекомендуем, чтобы у Вас было как минимум 20% заряда батареи перед началом процесса восстановления. В зависимости от объема данных процесс может занять некоторое время.\",\n    \"restoreWifi\": \"Используйте Wi-Fi.\",\n    \"restoreWifiHint\": \"Мы рекомендуем Вам использовать стабильное соединение Wi-Fi для процесса восстановления, чтобы избежать перебоев и обеспечить быстрое и безопасное восстановление.\",\n    \"restoreForeground\": \"Держите приложение на переднем плане.\",\n    \"restoreForegroundHint\": \"Пожалуйста, оставьте приложение на переднем плане и не закрывайте его во время процесса восстановления, чтобы избежать прерываний.\",\n    \"seedMigrationHint\": \"Seed-фраза применяется ко всем монетным дворам, но каждый из них требует индивидуального восстановления, поэтому запишите часто используемые URL-адреса монетных дворов. При восстановлении средств на монетных дворах, добавьте монетный двор и введите seed-фразу. Повторите эти действия для каждого монетного двора, который Вы хотите восстановить.\",\n    \"ecashPayment\": \"Оплата Ecash\",\n    \"english\": \"Английский\",\n    \"swahili\": \"Суахили\",\n    \"spanish\": \"Испанский\",\n    \"hungarian\": \"Венгерский\",\n    \"italian\": \"Итальянский\",\n    \"thai\": \"Тайский\",\n    \"russian\": \"Русский\",\n    \"chinese simplified\": \"Китайский (Упрощенный)\",\n    \"chinese traditional\": \"Китайский (Традиционный)\",\n    \"enutsRandD\": \"eNuts в Телеграм\",\n    \"estimatedFees\": \"Ориентировочная комиссия\",\n    \"estimateFee\": \"Попробовать оплатить\",\n    \"expired\": \"Истёкший\",\n    \"fee\": \"Комиссия\",\n    \"swapFee\": \"Комиссия обмена\",\n    \"feeErr\": \"Невозможно произвести оплату. Является ли \\\"{{input}}\\\" допустимым LNURL?\",\n    \"foundCashuClipboard\": \"Обнаружен токен Cashu\",\n    \"french\": \"Французский\",\n    \"from\": \"от\",\n    \"fromMint\": \"из монетного двора именуемого\",\n    \"sendingFrom\": \"Отправка из\",\n    \"german\": \"Немецкий\",\n    \"github\": \"GitHub\",\n    \"githubIssues\": \"Сообщайте об ошибках на Github\",\n    \"reportIssue\": \"Сообщить о проблеме\",\n    \"shareOrReport\": \"Напишите отзыв или сообщите об ошибках\",\n    \"historyDeleted\": \"История удалена\",\n    \"invalidInvoice\": \"Неверный счет\",\n    \"invalidOrSpent\": \"Токен недействителен или уже принят\",\n    \"invalidToken\": \"Неверный токен\",\n    \"invoice\": \"Счёт\",\n    \"invoiceExpired\": \"Срок действия счёта истёк\",\n    \"invoiceInclFee\": \"Счёт включая комиссию\",\n    \"invoiceOrLnurl\": \"LN инвойс или LNURL\",\n    \"invoiceOrLnAddress\": \"Счёт или Адрес\",\n    \"keysetID\": \"ID-набор ключей\",\n    \"language\": \"Язык\",\n    \"currency\": \"Валюта\",\n    \"currencyConversion\": \"Конвертация валюты\",\n    \"showFiatBalance\": \"Показывать баланс в фиате\",\n    \"showFiatBalanceDesc\": \"Отображать баланс и суммы в выбранной фиатной валюте\",\n    \"selectCurrency\": \"Выбрать валюту\",\n    \"lastUpdate\": \"Обновлено\",\n    \"loadingRates\": \"Загрузка курсов валют...\",\n    \"ratesUnavailable\": \"Курсы валют недоступны\",\n    \"ratesUnavailableDesc\": \"Не удалось загрузить курсы валют. Проверьте интернет-соединение и повторите попытку.\",\n    \"ratesRequiredForFiat\": \"Для отображения в фиате необходимы курсы валют\",\n    \"noCurrenciesAvailable\": \"Валюты недоступны. Пожалуйста, попробуйте загрузить курсы валют снова.\",\n    \"retry\": \"Повторить\",\n    \"lnInvoice\": \"Счёт за Lightning\",\n    \"lnPayment\": \"Оплата через Lightning\",\n    \"mint\": \"Монетный двор\",\n    \"minted\": \"отчеканен\",\n    \"multimintSwap\": \"Междворный экспорт\",\n    \"n/a\": \"Нет в наличии\",\n    \"name\": \"Название\",\n    \"no\": \"Нет\",\n    \"noCamAccess\": \"Нет доступа к камере\",\n    \"noFunds\": \"Недостаточно средств\",\n    \"noFundsForFee\": \"Недостаточно средств. Оставьте место для возможных комиссий.: ~{{fee}} Сат\",\n    \"noMint\": \"Монетный двор не найден\",\n    \"notQrCode\": \"Неподходящий QR-код!\",\n    \"noTX\": \"Транзакций пока нет\",\n    \"activity\": \"Активность\",\n    \"allHistory\": \"Все\",\n    \"optionalMemo\": \"Необязательная заметка\",\n    \"paste\": \"Вставить\",\n    \"paymentPending\": \"Ожидается платёж\",\n    \"paymentSuccess\": \"Успешеный платёж!\",\n    \"nostrPaymentSuccess\": \"Отправлено!\",\n    \"paymentType\": \"Способ оплаты\",\n    \"payWithLn\": \"Оплатите с помощью LN-кошелька\",\n    \"preferences\": \"Настройки\",\n    \"readme\": \"Прочитать\",\n    \"sender\": \"Отправитель\",\n    \"recipient\": \"Получатель\",\n    \"reqTimeout\": \"Таймаут запроса сети\",\n    \"restore\": \"Восстановить\",\n    \"save\": \"Сохранить\",\n    \"scanAgain\": \"Отсканируйте ещё раз\",\n    \"scan\": \"Скан.\",\n    \"scanQR\": \"Сканировать QR\",\n    \"qrScanHint\": \"Поместите QR-код в рамку\",\n    \"qrScanFormats\": \"Cashu, Lightning, LNURL или Bitcoin\",\n    \"qrScanReady\": \"Готово к сканированию\",\n    \"qrScanPaused\": \"Сканирование приостановлено\",\n    \"animatedQrProgress\": \"Прогресс анимированного QR\",\n    \"receivingAnimatedQr\": \"Получение анимированного QR\",\n    \"unsupportedFormat\": \"Формат не поддерживается\",\n    \"cashuPaymentRequestQrUnsupported\": \"Платёжные запросы Cashu из QR пока не поддерживаются\",\n    \"bitcoinAddressPaymentsUnsupported\": \"Платежи на Bitcoin-адреса не поддерживаются\",\n    \"cameraAccessRequired\": \"Требуется доступ к камере\",\n    \"cameraAccessDenied\": \"Доступ к камере запрещён\",\n    \"cameraAccessRequiredHint\": \"Нужен доступ к камере, чтобы сканировать QR-коды для платежей и токенов.\",\n    \"cameraAccessDeniedHint\": \"Разрешите доступ к камере в настройках устройства, чтобы сканировать QR-коды.\",\n    \"allowCameraAccess\": \"Разрешить доступ к камере\",\n    \"openSettings\": \"Открыть настройки\",\n    \"seconds\": \"секунд\",\n    \"selectAmount\": \"Выберите сумму\",\n    \"selected\": \"Выбрано\",\n    \"selectMint\": \"Выберите монетный двор для отправки\",\n    \"selectMints\": \"Выберите монетные дворы\",\n    \"sendEcash\": \"Отправить Ecash\",\n    \"share\": \"Поделиться\",\n    \"submitPaymentReq\": \"Обналичить\",\n    \"to\": \"до\",\n    \"today\": \"Сегодня\",\n    \"tokenInfoErr\": \"Ошибка при получении информации о токене\",\n    \"totalInclFee\": \"Всего в платеже\",\n    \"reservedTotal\": \"Зарезервировано всего\",\n    \"trustMint\": \"Доверять этому монетному двору?\",\n    \"tryLater\": \"Пожалуйста, повторите попытку позже.\",\n    \"unknownType\": \"Неизвестные данные\",\n    \"version\": \"Версия\",\n    \"viewMnemonic\": \"Просмотр мнемоники\",\n    \"wallet\": \"Кошелёк\",\n    \"willDoLater\": \"Позже\",\n    \"yes\": \"Да\",\n    \"invalidPubKey\": \"Неверный публичный ключ!\",\n    \"walletLocked\": \"Кошелек заблокирован\",\n    \"explainer1\": \"eNuts — это кастодиальный кошелёк Lightning, позволяющий осуществлять частные и мгновенные транзакции с использованием протокола Cashu. Ваши средства хранятся на монетных дворах, с которыми Вы взаимодействуете, а электронные деньги хранятся локально на Вашем устройстве.\",\n    \"explainer2\": \"Cashu — это новый протокол Ecash (электронных денег) для кастодиальных Биткойн-приложений, в котором монетные дворы — это узлы Lightning, выполняющие Биткойн-транзакции и предлагающие Вам электронные деньги. Будьте уверены, монетный двор не будет знать о Ваших платежах электронными деньгами.\",\n    \"explainer3\": \"Просто добавьте монетный двор через URL-адрес и оплатите счёт Lightning, чтобы получить Ecash. eNuts перенаправляет Вас, позволяя мгновенно получать платежи в электронных деньгах от кого угодно и с Вашего разрешения автоматически добавляя соответствующие монетные дворы. Обменивайте средства между монетными дворами и отправляйте электронные деньги, как только у Вас появится средства на балансе.\",\n    \"send&receive\": \"Отправить & получить\",\n    \"contactsNostr\": \"Контакты & Nostr\",\n    \"nostrExplainer\": \"Реализация Nostr обеспечивает синхронизацию с Вашими контактами без необходимости ввода закрытого ключа, поскольку мы создаем для Вас новый. Ваши данные отображаются с использованием открытого ключа, а новый закрытый ключ шифрует/расшифровывает ваши сообщения.\",\n    \"send\": \"Отправить\",\n    \"sendEcashDashboard\": \"Создать и отправить токен Cashu.\",\n    \"payInvoiceDashboard\": \"Отправить средства через Lightning.\",\n    \"receiveEcashDashboard\": \"Вставить & активировать токен Cashu из буфера обмена.\",\n    \"receiveEcashNostr\": \"Nostr сообщения\",\n    \"receiveEcashNostrHint\": \"Проверьте свои сообщения Nostr на наличие монет.\",\n    \"createInvoiceDashboard\": \"Получите Ecash, оплатив счёт Lightning.\",\n    \"hideNuts\": \"Скрыть баланс\",\n    \"checkingDms\": \"Проверка ваших личных сообщений на наличие Ecash...\",\n    \"clearOverHere\": \"Здесь всё ясно!\",\n    \"totalDmsReceived\": \"Вы получили {{totalDms}} монет.\",\n    \"swapNow\": \"Обменять сейчас\",\n    \"swap\": \"Обмен\",\n    \"emptyMint\": \"У монетного двора нет Ваших средств\",\n    \"zapSoon\": \"Запы будут добавлены в ближайшее время...\",\n    \"enutsPub\": \"Публичный ключ eNuts: \",\n    \"seeFullHistory\": \"Посмотреть полную историю транзакций\",\n    \"next\": \"Далее\",\n    \"skip\": \"Пропустить\",\n    \"donateLn\": \"Пожертвовать\",\n    \"supportHint\": \"Каждый вклад, независимо от его размера, ценен. Экран подтверждения находится в разработке.\",\n    \"newToken\": \"Новый токен Cashu\",\n    \"disclaimerHint\": \"К этому отказу от ответственности следует относиться серьёзно, его нельзя игнорировать или недооценивать. Мы ценим Ваш интерес к этому проекту и продолжим работать над его улучшением.\",\n    \"searchContacts\": \"Искать или ввести NPUB\",\n    \"submit\": \"Применить\",\n    \"clearMetadataCache\": \"Очистить кеш метаданных\",\n    \"clearMetadataCacheHint\": \"Очистить кеш метаданных?\",\n    \"clearImageCache\": \"Очистить кеш изображений\",\n    \"clearImageCacheHint\": \"Очистить кеш изображений?\",\n    \"pullRefresh\": \"Потяните, чтобы обновить\",\n    \"processTestPay\": \"Обработка тестового платежа...\",\n    \"confirmMint\": \"Подтвердить новый монетный двор\",\n    \"confirmMintHint\": \"Вы уверены, что хотите добавить этот монетный двор?\",\n    \"npubAlreadyAdded\": \"NPUB уже добавлен\",\n    \"replaceNpub\": \"Заменить NPUB\",\n    \"replaceNpubTxt\": \"Вы уверены, что хотите заменить текущий NPUB?\",\n    \"npubAdded\": \"NPUB добавлен!\",\n    \"showContacts\": \"Показать контакты\",\n    \"topUpNow\": \"Получите Ecash прямо сейчас\",\n    \"scanAnother\": \"Отсканируйте другой QR-код\",\n    \"deleteNpub\": \"Удалить NPUB?\",\n    \"delNpubHint\": \"Все контакты и связанные с ними данные будут удалены.\",\n    \"addNewNpub\": \"Добавить новый NPUB?\",\n    \"addNpubHint\": \"Это приведет к удалению всех данных, связанных с вашим текущим NPUB.\",\n    \"zap\": \"Зап\",\n    \"zapNow\": \"Зап сейчас\",\n    \"meltNostrProfileHint\": \"Переведите средства на LN-адрес, связанный с вашим профилем Nostr.\",\n    \"nostrDmHint\": \"eNuts не может получить доступ к личным сообщениям Вашей учётной записи Nostr из-за отсутствия доступа к Вашему приватному ключу. Вместо этого он генерирует новый ключ для отправки электронных денег (Ecash). Когда Вы отправляете электронные деньги через Nostr, получатель получает их используя Ваш новый публичный ключ eNuts. Если получатель отвечает в DM токеном Ecash, Вы можете просмотреть его здесь. Мы активно работаем над безопасным решением для приватных ключей.\",\n    \"nostrIssueHeader\": \"Проблема с контактами Nostr\",\n    \"nostrIssueHint\": \"Если у Вас возникли проблемы с открытием контактов Nostr, нажмите кнопку ниже или сбросьте данные Nostr в разделе 'Настройки' > 'Основное' > 'Контакты' > 'Сбросить данные', чтобы решить проблему.\",\n    \"submitNostrIssue\": \"Сбросить данные\",\n    \"nostrIssueSuccess\": \"Данные Nostr успешно сброшены!\",\n    \"createLnInvoice\": \"Создать счёт Lightning\",\n    \"metadataCacheCleared\": \"Кэш метаданных очищен!\",\n    \"imageCacheCleared\": \"Кэш изображений очищен!\",\n    \"leaveGithubStar\": \"Поддержите нас звездой на Github\",\n    \"alreadySpentHint\": \"Некоторые доказательства на Вашем балансе потрачены или востребованы в другом месте. Решите проблему, удалив их. 'Настройки' > 'Управление монетным двором' > выберите интересующий монетный двор > 'Проверить доказательства'.\",\n    \"useNpub\": \"Используйте NPUB\",\n    \"autoSwapToDefaulMint\": \"Перевод на монетный двор, который по умолчанию\",\n    \"trustMintOpt\": \"Довериться монетному двору\",\n    \"swapHint\": \"Этот вариант требует платежа Lightning, включает в себя комиссию и может по-прежнему добавлять неизвестный монетный двор в список, если произойдет возврат комиссии.\",\n    \"paidInvoice\": \"{{ count }} счет был оплачен на общую сумму {{ total }} Сатов\",\n    \"paidInvoices\": \"{{ count }} счетов было оплачено на общую сумму {{ total }} Сатов\",\n    \"checkPayment\": \"Проверить платеж\",\n    \"lnPaymentSpamHint\": \"Пожалуйста, подождите {{ remainingSeconds }} секунд, чтобы избежать спама монетой.\",\n    \"trustHint\": \"Монетный двор, связанный с принимаемым токеном, будет добавлен в Ваш список доверенных монетных дворов.\",\n    \"noDefaultHint\": \"Вам необходимо настроить монетный двор по умолчанию для выполнения автоматического перевода средств.\",\n    \"autoSwapSuccess\": \"Обмен прошёл успешно!\",\n    \"shareEnuts\": \"Поделитесь eNuts с кем-нибудь\",\n    \"supportUs\": \"Поддержите нас\",\n    \"justNow\": \"Прямо сейчас\",\n    \"hoursAgo\": \"{{count}} часов назад\",\n    \"yesterday\": \"Вчера\",\n    \"awaitingPayment\": \"Ожидание платежа\",\n    \"receivedFromMint\": \"Получено от монетного двора\",\n    \"status\": \"Статус\",\n    \"unit\": \"Единица\",\n    \"quoteId\": \"ID котировки\",\n    \"nfcPaymentLimits\": \"Лимиты платежей\",\n    \"nfcPaymentLimitsDesc\": \"Установите лимиты по умолчанию и пользовательские лимиты для NFC-платежей\",\n    \"amountLimits\": \"Лимиты суммы\",\n    \"amountLimitsDesc\": \"Нажмите, чтобы установить по умолчанию, удерживайте для удаления\",\n    \"noLimit\": \"Без лимита\",\n    \"noLimitDesc\": \"Подтвердить любую сумму\",\n    \"deleteAmount\": \"Удалить сумму\",\n    \"deleteAmountConfirm\": \"Вы уверены, что хотите удалить {{amount}} сатов из быстрого выбора?\",\n    \"delete\": \"Удалить\",\n    \"resetToDefaults\": \"Сбросить настройки\"\n  },\n  \"error\": {\n    \"checkSpendableErr\": \"Ошибка при проверке попытке потратить токен\",\n    \"claimTokenErr\": \"Ошибка при запросе токена\",\n    \"sendTokenErr\": \"Ошибка при отправке токена\",\n    \"header\": \"Произошла ошибка\",\n    \"msg\": \"Сожалеем, что вы столкнулись с этой проблемой. Вы можете помочь нам улучшить программное обеспечение, сделав снимок экрана и создав короткий отчет об ошибке.\",\n    \"reportBug\": \"Сообщить об ошибке\",\n    \"requestMintErr\": \"Ошибка при запросе счёта у монетного двора.\",\n    \"stackNA\": \"Стек ошибок недоступен\",\n    \"generalMeltingErr\": \"Монетному двору не удалось найти правильный маршрут платежа Lightning к Вашему узлу.\",\n    \"invoiceFromLnurlError\": \"Не удалось создать счёт с использованием вашего LNURL.\",\n    \"invoiceScanError\": \"Не удалось использовать счёт из отсканированного QR-кода.\"\n  },\n  \"history\": {\n    \"checkSpent\": \"Проверьте, потрачен ли токен\",\n    \"isPending\": \"Токен находится на рассмотрении\",\n    \"isSpent\": \"Токен был потрачен\",\n    \"justNow\": \"Прямо сейчас\",\n    \"hoursAgo\": \"{{count}} часов назад\",\n    \"yesterday\": \"Вчера\",\n    \"memo\": \"Заметка\",\n    \"nHrsAgo\": \"{{hrs}} часов назад\",\n    \"nMinsAgo\": \"{{mins}} минут назад\",\n    \"noMemo\": \"Заметки нет\",\n    \"oneHrAgo\": \"1 час назад\",\n    \"oneMinAgo\": \"1 минуту назад\",\n    \"paymentHash\": \"Хеш платежа\",\n    \"settleTime\": \"Время сделки\",\n    \"showQr\": \"Показать QR-код\",\n    \"receive\": \"Получить\",\n    \"send\": \"Отправить\",\n    \"melt\": \"Расплавить\",\n    \"receivedEcash\": \"Ecash получен\",\n    \"sentEcash\": \"Ecash отправлен\",\n    \"paidInvoice\": \"Счёт оплачен\",\n    \"details\": \"Детали\",\n    \"date\": \"Дата\",\n    \"amount\": \"Сумма\",\n    \"token\": \"Токен\"\n  },\n  \"mints\": {\n    \"addCustomName\": \"Добавить кастомное название\",\n    \"additionalInfo\": \"Дополнительная информация\",\n    \"addMintBtn\": \"Добавить монетный двор\",\n    \"addNewMint\": \"Добавить новый монетный двор\",\n    \"atLeast2Mints\": \"Вам нужно как минимум 2 монетных двора для выполнения междворного обмена.\",\n    \"awaitingInvoice\": \"Ожидание счёта\",\n    \"cashOutAmountHint\": \"Могут взиматься молниеносные сборы, поэтому добавляется предполагаемая комиссия, любые переплаченные сборы будут возвращены.\",\n    \"checkProofs\": \"Проверить доказательства\",\n    \"checkProofsQ\": \"Проверить все доказательства?\",\n    \"checkProofsTxt\": \"Осуществится проверка того, можно ли потратить Ваши токены, если нельзя - они будут удалены.\",\n    \"chooseMeltMintHint\": \"Выберите монетный двор, с которого вы хотите обналичить свои средства.\",\n    \"chooseMintHint\": \"Выберите монетный двор, от которого Вы хотите получить Ecash взамен Биткойнов отправленных через Lightning. Монетный двор становится хранителем Ваших средств.\",\n    \"chooseTarget\": \"Выберите получателя платежа.\",\n    \"coinSelectionHint\": \"Ваш баланс Ecash по сути представляет собой набор токенов. Вы можете выбрать токены (монеты), которые хотите потратить. Наборам токенов монетный двор присваивает ID-набор ключей, который постоянно меняется. Вновь добавленные наборы токенов выделены зеленым цветом. Желательно сначала потратить старые наборы токенов.\",\n    \"creatingEcashToken\": \"Создание токена Cashu\",\n    \"sendingEcashViaNostr\": \"Отправка токена Cashu через Nostr!\",\n    \"customName\": \"Кастомизировать название\",\n    \"cutomNameAdded\": \"Название кастомизировано\",\n    \"dangerZone\": \"Опасная зона\",\n    \"deletedProofs\": \"Удаление {{proofsToDel}} доказательств.\",\n    \"delMint\": \"Удалить монетный двор\",\n    \"delMintSure\": \"Удалить этот монетный двор?\",\n    \"ecashAmountHint\": \"Введите сумму Ecash, которую вы хотите отправить.\",\n    \"editMintName\": \"Изменить название монетного двора\",\n    \"errDelProofs\": \"Что-то пошло не так при удалении доказательств.\",\n    \"funds\": \"Резерв\",\n    \"general\": \"Основное\",\n    \"importantNotice\": \"Важное замечание\",\n    \"inputField\": \"Lightning счёт или LNURL\",\n    \"invalidUrl\": \"Неверный URL\",\n    \"invoiceAmountHint\": \"Введите сумму Ecash, которую Вы хотели бы получить. Затем монетный двор выставит счёт, который Вам придётся оплатить с помощью кошелька Lightning.\",\n    \"invoiceHint\": \"Это может занять несколько секунд...\",\n    \"lowBal\": \"Баланс монетного двора слишком низкий!\",\n    \"meltAddressbookHint\": \"Выберите свой LNURL или любой другой контакт в качестве получателя платежа.\",\n    \"meltInputHint\": \"Вставьте счёт Lightning, LN-URL или адрес Lightning.\",\n    \"meltScanQRHint\": \"Отсканировать Lightning счёт созданный на другом устройстве.\",\n    \"meltSwapHint\": \"Выберите другой монетный двор из списка доверенных в качестве получателя платежа.\",\n    \"copyShareToken\": \"Создать токен Cashu\",\n    \"copyShareTokenHint\": \"Введите сумму, создайте токен и скопируйте его, чтобы поделиться им через любое приложение для обмена сообщениями.\",\n    \"sendNostr\": \"Отправить через Nostr\",\n    \"sendNostrHint\": \"Отправьте Ecash напрямую одному из ваших контактов на Nostr.\",\n    \"meltToken\": \"Обналичить\",\n    \"mintConnectionFail\": \"Не удалось подключиться к монетному двору\",\n    \"mintInfo\": \"Информация о монетном дворе\",\n    \"mintNewTokens\": \"Пополнить Ecash\",\n    \"mintNoContact\": \"У монетного двора нет контактной информации\",\n    \"mntAlreadyAdded\": \"Монетный двор уже добавлен\",\n    \"noAdditional\": \"Этот монетный двор не имеет дополнительной информации\",\n    \"noInfo\": \"У монетного двора нет информации\",\n    \"noProofs\": \"Не найдено доказательств для этого монетного двора.\",\n    \"paymentOverview\": \"Обзор платежей\",\n    \"processingPaymentByMint\": \"Монетный двор обрабатывает платёж согласно Вашему запросу\",\n    \"processingSwap\": \"Обработка междворного обмена по Вашему запросу\",\n    \"pubKey\": \"Публичный ключ\",\n    \"removeDefault\": \"Перестать использовать по умолчанию\",\n    \"scanQR\": \"Отсканировать QR-код\",\n    \"sendEcashHint\": \"Выберите монетный двор, на котором вы хотите создать токен Cashu.\",\n    \"setDefault\": \"Установить монетный двор по умолчанию\",\n    \"supportedNuts\": \"Поддерживаемые NUTs\",\n    \"swapNotAllowed\": \"Обмен с тестового монетного двора невозможен.\",\n    \"zapNotAllowed\": \"Зап из тестового монетного двора невозможен.\",\n    \"testMintHint\": \"Это тестовый монетный двор, с которым можно поиграть. Всё равно добавить?\",\n    \"trustMintSure\": \"Доверять этому монетному двору?\",\n    \"updatedDefault\": \"Обновлён монетный двор по умолчанию\",\n    \"newMintAdded\": \"Добавлен монетный двор!\",\n    \"newMintAddedQuestion\": \"Хотите ли Вы получить Ecash сейчас?\",\n    \"selectSwapReceiver\": \"Выберите монетный двор в качестве получателя платежа.\",\n    \"prepairZapData\": \"Подготовка данных транзакции...\",\n    \"lastUpdated\": \"Последнее обновление\",\n    \"mintInfoUpdated\": \"Информация о монетном дворе обновлена!\",\n    \"mintInfoUpdateFailed\": \"Не удалось обновить информацию о монетном дворе\",\n    \"npcSettings\": \"Lightning address\",\n    \"npcDefaultAccount\": \"Default\",\n    \"npcTapToCopy\": \"Tap to copy\",\n    \"npcUsernameLabel\": \"Custom username\",\n    \"npcUsernamePlaceholder\": \"optional username\",\n    \"npcPurchaseUsername\": \"Save username\",\n    \"npcSetUsername\": \"Set Username\",\n    \"npcRequestUsername\": \"Request username\",\n    \"npcUsernameFeePrompt\": \"Do you want to set this username for a fee of {{amount}} sats?\",\n    \"npcReceiveTitle\": \"NPC Lightning addresses\",\n    \"npcReceiveHint\": \"Receive Lightning payments into your local Cashu wallet.\",\n    \"npcAccountsLabel\": \"Accounts\",\n    \"npcLocalBalance\": \"Local balance\",\n    \"npcReceiveAddress\": \"Receive address\",\n    \"npcSeedKey\": \"Seed key\",\n    \"npcImportedKey\": \"Imported key\",\n    \"npcActive\": \"Active\",\n    \"npcSyncing\": \"Syncing\",\n    \"npcPaused\": \"Paused\",\n    \"npcNpubFallback\": \"Using your npub until a username is saved\",\n    \"npcSyncAll\": \"Sync all\",\n    \"npcSynced\": \"NPC account synced\",\n    \"npcAccountAdded\": \"NPC account added\",\n    \"npcAccountRemoved\": \"NPC account removed\",\n    \"npcUsernameSaved\": \"Username saved\",\n    \"npcAddAccountTitle\": \"Add NPC account\",\n    \"npcAddAccountHint\": \"Import an existing Nostr key or derive a new key from your seed.\",\n    \"npcPrivateKeyLabel\": \"Private key\",\n    \"npcPrivateKeyPlaceholder\": \"nsec or hex\",\n    \"npcPrivateKeyHint\": \"Imported keys are stored in secure storage on this device.\",\n    \"npcPrivateKeyRequired\": \"Enter an nsec or hex private key.\",\n    \"npcImportPrivateKey\": \"Import private key\",\n    \"npcDeriveAccount\": \"Derive new key\"\n  },\n  \"topNav\": {\n    \"about\": \"О нас\",\n    \"addressBook\": \"Адресная книга\",\n    \"advancedFunctions\": \"Расширенные функции\",\n    \"display\": \"Дисплей\",\n    \"history\": \"История транзакций\",\n    \"language\": \"Язык\",\n    \"currency\": \"Валюта\",\n    \"mintSettings\": \"Управление монетным двором\",\n    \"nfcSettings\": \"Настройки NFC\",\n    \"npcSettingsTitle\": \"Lightning address\",\n    \"security\": \"Безопасность\",\n    \"settings\": \"Настройки\",\n    \"privacy\": \"Конфиденциальность\",\n    \"general\": \"Основное\"\n  },\n  \"wallet\": {\n    \"cashuContent\": \"Автор Cashu не является криптографом, и протокол всё еще находится в разработке. Есть риск существования недостатков в протоколе, которые способны привести к фатальным последствиям. Cashu нужно использовать осознавая риски.\",\n    \"cashuExperiment\": \"Cashu находится на стадии эксперимента.\",\n    \"claiming\": \"Заявление...\",\n    \"processingInvoice\": \"Обработка счёта-фактуры...\",\n    \"nfcPayment\": \"NFC-платёж\",\n    \"nfcKeepNearTerminal\": \"Держите телефон рядом с терминалом\",\n    \"nfcSelectMaxAmount\": \"Выберите максимальную сумму\",\n    \"noLimit\": \"Без лимита\",\n    \"custodialRisk\": \"Риск кастодиального кошелька, ключи у монетных дворов.\",\n    \"custodialRiskContent\": \"У eNuts нет ключей от Биткойна; средства хранятся на монетном дворе. Поэтому, если Вы не доверяете монетному двору, желательно избегать взаимодействия с ним.\",\n    \"disclaimer\": \"Пожалуйста, обратите внимание, что это бета-версия на ранней стадии, и программа всё ещё проходит тестирование до официального выпуска. Программное обеспечение и весь контент на нём, предоставляются на основе “как есть” и “как доступно”. Мы не даём никаких гарантий, прямо или косвенно, в отношении пригодности или удобства использования программного обеспечения или любого его содержимого.\",\n    \"enutsDisclaimer\": \"eNuts - это незавершенная, бета-версия программного обеспечения.\",\n    \"lossContent\": \"Токены Cashu являются токенами-носителями, что означает, что если Вы потеряете доступ к ним, не существует возможности восстановления. eNuts хранит Ваши токены в Вашем устройстве. Прежде чем удалить приложение, убедитесь, что Вы перенесли свои токены.\",\n    \"lossOfTokens\": \"Потеря средств.\",\n    \"enutsMint\": \"По умолчанию используется монетный двор eNuts\",\n    \"mintDisclaimer\": \"Использование стандартного монетного двора eNuts осуществляется исключительно на Ваш страх и риск. Мы настоятельно рекомендуем Вам проявлять осторожность и использовать его только в экспериментальных или образовательных целях. Нет никаких гарантий относительно его функциональности, безопасности или доступности, и он может исчезнуть без предварительного уведомления. Вклады, внесённые в этот монетный двор, следует рассматривать как пожертвования, которые могут быть невозвращены, и потенциально использованы для дальнейшего развития. Помните о рисках, связанных с бета-версией программного обеспечения, и о том, что именно Вы несёте ответственность за защиту своих активов при использовании этого монетного двора (стандартный монетный двор eNuts).\",\n    \"paidOut\": \"Выплачено\",\n    \"pasteToken\": \"Принять Ecash\",\n    \"payInvoice\": \"Оплатить счёт\",\n    \"payLNInvoice\": \"Оплатить счёт Lightning\",\n    \"receive\": \"Получить\",\n    \"send\": \"Отправить\",\n    \"proofs\": \"Доказательства\",\n    \"swapped\": \"Поменять местами\"\n  }\n}\n"
  },
  {
    "path": "assets/translations/th.json",
    "content": "{\n  \"addrBook\": {\n    \"addOwnNpub\": \"เพิ่ม NPUB ของท่าน\",\n    \"favorite\": \"รายการโปรด\",\n    \"removeFav\": \"ลบ รายการโปรด\",\n    \"copyNpub\": \"คัดลอก NPUB\",\n    \"npubCopied\": \"คัดลอก NPUB แล้ว!\",\n    \"receiverNoLnurl\": \"ผู้รับไม่มี LNURL\",\n    \"noResults\": \"ไม่พบข้อมูล\"\n  },\n  \"auth\": {\n    \"confirmAction\": \"โปรดยืนยันการทำรายการ\",\n    \"createPin\": \"สร้างรหัสพิน\",\n    \"editPin\": \"แก้ไขรหัสพิน\",\n    \"pinMismatch\": \"รหัสพินไม่ถูกต้อง!\",\n    \"pinSetup\": \"ท่านสามารถเลือกที่จะสร้างรหัสพินเพื่อล็อคแอป\",\n    \"pleaseConfirm\": \"โปรดยืนยันรหัสอีกครั้ง\",\n    \"pleaseConfirmNewPin\": \"โปรดยืนยันรหัสใหม่อีกครั้ง\",\n    \"pleaseEnter\": \"โปรดใส่รหัสพินของท่าน\",\n    \"pleaseNewPin\": \"โปรดใส่รหัสพินใหม่ของท่าน\",\n    \"removePin\": \"ลบรหัสพิน\",\n    \"welcome\": \"ยินดีตอนรับ\",\n    \"welcomeBack\": \"ยินดีตอนรับกลับมา!\"\n  },\n  \"bottomNav\": {\n    \"wallet\": \"กระเป๋า\",\n    \"contacts\": \"รายชื่อ\"\n  },\n  \"common\": {\n    \"confirmReset\": \"รีเซ็ตกระเป๋า\",\n    \"copy\": \"คัดลอก\",\n    \"cycle\": \"วงรอบ\",\n    \"findMint\": \"ค้นหา Mint\",\n    \"manualCounterIncrease\": \"เพิ่มเคาน์เตอร์\",\n    \"manualCounterIncreaseHint\": \"การเพิ่มขึ้นของเคาน์เตอร์ จะเพิ่มขึ้นโดยอัตรโนมัติในทุกธุรกรรม แต่บางครั้งมันอาจจะเกิดข้อผิดพลาดในขั้นตอนกู้คืนกระเป๋า การเพิ่มเคาน์เตอร์จะช่วยแก้ปัญหาเหล่านี้\",\n    \"increaseCounterHint\": \"แน่ใจนะว่าจะเพิ่มเคาน์เตอร์? ควรจะทำก็ต่อเมื่อแน่ใจว่าเคาน์เตอร์ไม่ถูกซิงค์ข้อมูล\",\n    \"noMintForCounter\": \"ไม่พบ mints จากการเพิ่มเคาน์เตอร์\",\n    \"counterIncreased\": \"Counters increased by {{counterIncreased}}!\",\n    \"doneSafety\": \"เกือบเสร็จละ... การตรวจสอบความปลอดภัย\",\n    \"noProofsRestored\": \"ไม่พบ proof เพื่อทำการกู้คืนกระเป๋าของคุณ\",\n    \"restoreErr\": \"เกิดข้อผิดพลาดบางอย่างขณะกู้คืนกระเป๋าของคุณ\",\n    \"dontClose\": \"กรุณาอย่าปิดแอปในระหว่างกระบวนการ\",\n    \"recoveryHint\": \"เขียนหรือวาง 12 คำตามลำดับที่ถูกต้อง โดยคั่นด้วยช่องว่าง\",\n    \"walletRecovery\": \"การกู้คืนกระเป๋า\",\n    \"walletRecoveryHint\": \"ใช้ seed backup เพื่อกู้คืนกระเป๋าของคุณ\",\n    \"seedBackup\": \"Seed Backup\",\n    \"12WordMnemonic\": \"12-word mnemonic\",\n    \"secureWallet\": \"Secure wallet\",\n    \"secureWalletHint\": \"สร้างและเขียน seed backup เพื่อป้องกันกระเป๋าของคุณ\",\n    \"quickWallet\": \"Quick wallet\",\n    \"quickWalletHint\": \"สร้างกระเป๋าใหม่ทันที สามารถสร้าง seed backup ได้ในภายหลัง\",\n    \"skipSeedHint\": \"คุณสามารถข้ามขั้นตอนนี้และสร้าง seed backup ภายหลังได้\",\n    \"mnemonicHint\": \"Seed phrase จะไม่แสดงอีกต่อไป กรุณาเขียนลงและไม่เผยแพร่ให้ใครทราบ\",\n    \"confirmMnemonicErr\": \"คำผิด! โปรดตรวจสอบให้แน่ใจว่าเขียน seed phrase ลงให้ถูกต้องตามลำดับ\",\n    \"selectRestoreMint\": \"โปรดเลือก mint ที่จะใช้กู้คืนเงินของคุณ\",\n    \"recoveringWallet\": \"Mint กำลังกู้คืนเงินของคุณ...\",\n    \"seedEnabled\": \"Seed recovery enabled!\",\n    \"confirmSeed\": \"โปรดยืนยัน seed ของคุณโดยพิมพ์คำตามลำดับที่ถูกต้อง\",\n    \"about\": \"เกี่ยวกับ\",\n    \"aboutToLeaveTo\": \"คุณกำลังจะออกจาก\",\n    \"accept\": \"ยอมรับ\",\n    \"amount\": \"จำนวน\",\n    \"back\": \"ย้อนกลับ\",\n    \"backToDashboard\": \"ย้อนกลับไปที่หน้าหลัก\",\n    \"balance\": \"ยอดคงเหลือ\",\n    \"balanceAfterTX\": \"ยอดเงินหลังจากการทำธุรกรรม\",\n    \"balTooLow\": \"ยอดเงินไม่เพียงพอ\",\n    \"bigQrMsg\": \"ขนาดข้อมูลมากเกินไปสำหรับการสร้างรหัส QR\",\n    \"calculateFeeEst\": \"กำลังคำนวณค่าธรรมเนียม\",\n    \"cancel\": \"ยกเลิก\",\n    \"cashOut\": \"ถอนเงิน\",\n    \"cashOutFromMint\": \"ถอนเงินจาก mint\",\n    \"change\": \"เปลี่ยน\",\n    \"claimed\": \"รับแล้ว\",\n    \"restored\": \"กู้คืนแล้ว\",\n    \"claimSuccess\": \"รับ {{amount}} Sats:\\n{{mintUrl}}\\nหมายเหตุ: {{memo}}\",\n    \"claimToken\": \"รับ Token\",\n    \"clear\": \"ล้าง\",\n    \"clipboardInvalid\": \"คลิปบอร์ดของคุณมี Cashu token ที่ไม่ถูกต้อง!\",\n    \"coinSelection\": \"เลือกเหรียญ\",\n    \"confirm\": \"ยืนยัน\",\n    \"contact\": \"ติดต่อ\",\n    \"mintDelErr\": \"ไม่สามารถลบ mint ที่เหลือยอดเงินได้\",\n    \"continue\": \"ต่อ\",\n    \"copied\": \"คัดลอกแล้ว\",\n    \"shareInvoice\": \"แชร์ใบแจ้งหนี้\",\n    \"copyToken\": \"คัดลอก token\",\n    \"createInvoice\": \"สร้างใบแจ้งหนี้\",\n    \"createToken\": \"สร้าง Token\",\n    \"createTokenErr\": \"ไม่สามารถสร้าง Cashu token ได้ โปรดลองอีกครั้งในภายหลัง\",\n    \"eventError\": \"มีบางอย่างผิดพลาดขณะเผยแพร่เหตุการณ์\",\n    \"createViaLn\": \"สร้างใบแจ้งหนี้ผ่าน Lightning\",\n    \"darkMode\": \"โหมดมืด\",\n    \"lightMode\": \"โหมดสว่าง\",\n    \"autoMode\": \"โหมดอัตโนมัติ\",\n    \"dbErr\": \"มีบางอย่างผิดพลาดขณะเริ่มต้นฐานข้อมูล!\",\n    \"deepLinkErr\": \"ไม่สามารถเปิดลิงก์ได้\",\n    \"default\": \"ค่าเริ่มต้น\",\n    \"delHistory\": \"ลบประวัติ\",\n    \"factoryReset\": \"รีเซ็ตโรงงาน\",\n    \"delHistoryErr\": \"ไม่สามารถลบประวัติได้\",\n    \"delHistoryQ\": \"ลบประวัติหรือไม่?\",\n    \"resetQ\": \"รีเซ็ตกระเป๋าของคุณหรือไม่?\",\n    \"delHistoryTxt\": \"ข้อมูลไม่สามารถกู้คืนได้หลังจากนี้\",\n    \"display\": \"หน้าจอ\",\n    \"disclaimer\": \"คำประกาศ\",\n    \"restoreBattery\": \"มีแบตเตอรี่อย่างน้อย 20%\",\n    \"restoreBatteryHint\": \"เราขอแนะนำให้คุณมีแบตเตอรี่อย่างน้อย 20% ก่อนเริ่มกระบวนการกู้คืน เนื่องจากขึ้นอยู่กับปริมาณข้อมูล กระบวนการอาจใช้เวลาสักครู่\",\n    \"restoreWifi\": \"ใช้ Wi-Fi\",\n    \"restoreWifiHint\": \"เราขอแนะนำให้คุณใช้การเชื่อมต่อ Wi-Fi ที่เสถียรสำหรับกระบวนการกู้คืนเพื่อป้องกันความต่อเนื่องและเพื่อให้กระบวนการกู้คืนเร็วและปลอดภัย\",\n    \"restoreForeground\": \"ให้แอปอยู่ใน foreground\",\n    \"restoreForegroundHint\": \"กรุณาให้แอปอยู่ใน foreground และอย่าปิดในระหว่างกระบวนการกู้คืนเพื่อป้องกันความต่อเนื่อง\",\n    \"seedMigrationHint\": \"Seed มีผลต่อทุก mint แต่ทุกตัวต้องการการกู้คืนแยกต่างหาก ดังนั้นโปรดทำเครื่องหมายบน mint URL ที่ใช้บ่อยๆ หากคุณมียอดคงเหลือแต่ยังไม่มี seed สร้าง token จาก mint ที่ต้องการและทำการสร้าง seed ใหม่ เมื่อสำเร็จให้ทำซ้ำสำหรับทุก mint ที่คุณต้องการสำรองข้อมูล\",\n    \"ecashPayment\": \"การชำระเงินด้วย Ecash\",\n    \"english\": \"อังกฤษ\",\n    \"swahili\": \"ภาษาสวาฮิลี\",\n    \"spanish\": \"สเปน\",\n    \"hungarian\": \"ฮังการี\",\n    \"italian\": \"อิตาลี\",\n    \"russian\": \"รัสเซีย\",\n    \"thai\": \"ไทย\",\n    \"chinese simplified\": \"จีน (ตัวย่อ)\",\n    \"chinese traditional\": \"จีน (ดั้งเดิม)\",\n    \"enutsRandD\": \"eNuts Telegram\",\n    \"estimatedFees\": \"ค่าธรรมเนียมโดยประมาณ\",\n    \"estimateFee\": \"ประมาณค่าธรรมเนียม\",\n    \"expired\": \"หมดอายุ\",\n    \"fee\": \"ค่าธรรมเนียม\",\n    \"swapFee\": \"ค่าธรรมเนียมการสลับ\",\n    \"feeErr\": \"ไม่สามารถประมาณค่าธรรมเนียมได้ \\\"{{input}}\\\" เป็น LNURL ที่ถูกต้องหรือไม่?\",\n    \"foundCashuClipboard\": \"ตรวจพบ Cashu token\",\n    \"french\": \"ฝรั่งเศส\",\n    \"from\": \"จาก\",\n    \"fromMint\": \"จาก mint ต่อไปนี้\",\n    \"sendingFrom\": \"ส่งจาก\",\n    \"german\": \"เยอรมัน\",\n    \"github\": \"GitHub\",\n    \"githubIssues\": \"รายงานข้อบกพร่องบน Github\",\n    \"reportIssue\": \"รายงานปัญหา\",\n    \"shareOrReport\": \"แบ่งปันข้อเสนอหรือรายงานข้อบกพร่อง\",\n    \"historyDeleted\": \"ประวัติถูกลบแล้ว\",\n    \"invalidInvoice\": \"ใบแจ้งหนี้ไม่ถูกต้อง\",\n    \"invalidOrSpent\": \"Token ไม่ถูกต้องหรือถูกใช้ไปแล้ว\",\n    \"invalidToken\": \"Token ไม่ถูกต้อง\",\n    \"invoice\": \"ใบแจ้งหนี้\",\n    \"invoiceExpired\": \"ใบแจ้งหนี้หมดอายุ\",\n    \"invoiceInclFee\": \"ใบแจ้งหนี้รวมค่าธรรมเนียม\",\n    \"invoiceOrLnurl\": \"ใบแจ้งหนี้ LN หรือ LNURL\",\n    \"invoiceOrLnAddress\": \"ใบแจ้งหนี้หรือที่อยู่\",\n    \"keysetID\": \"Keyset ID\",\n    \"language\": \"ภาษา\",\n    \"currency\": \"สกุลเงิน\",\n    \"currencyConversion\": \"การแปลงสกุลเงิน\",\n    \"showFiatBalance\": \"แสดงยอดคงเหลือเป็นเงินเฟียต\",\n    \"showFiatBalanceDesc\": \"แสดงยอดคงเหลือและจำนวนเงินในสกุลเงินเฟียตที่เลือก\",\n    \"selectCurrency\": \"เลือกสกุลเงิน\",\n    \"lastUpdate\": \"อัปเดตแล้ว\",\n    \"loadingRates\": \"กำลังโหลดอัตราแลกเปลี่ยน...\",\n    \"ratesUnavailable\": \"อัตราแลกเปลี่ยนไม่พร้อมใช้งาน\",\n    \"ratesUnavailableDesc\": \"ไม่สามารถโหลดอัตราแลกเปลี่ยนได้ โปรดตรวจสอบการเชื่อมต่ออินเทอร์เน็ตและลองอีกครั้ง\",\n    \"ratesRequiredForFiat\": \"ต้องการอัตราแลกเปลี่ยนเพื่อเปิดใช้งานการแสดงผลเป็นเงินเฟียต\",\n    \"noCurrenciesAvailable\": \"ไม่มีสกุลเงินที่ใช้ได้ โปรดลองโหลดอัตราแลกเปลี่ยนอีกครั้ง\",\n    \"retry\": \"ลองอีกครั้ง\",\n    \"lnInvoice\": \"ใบแจ้งหนี้ Lightning\",\n    \"lnPayment\": \"การชำระเงิน Lightning\",\n    \"mint\": \"Mint\",\n    \"minted\": \"Minted\",\n    \"multimintSwap\": \"การสลับ multimint\",\n    \"n/a\": \"ไม่มีข้อมูล\",\n    \"name\": \"ชื่อ\",\n    \"no\": \"ไม่\",\n    \"noCamAccess\": \"ไม่มีการเข้าถึงกล้อง\",\n    \"noFunds\": \"ยอดเงินไม่เพียงพอ\",\n    \"noFundsForFee\": \"ยอดเงินไม่เพียงพอ โปรดเตรียมพื้นที่สำหรับค่าธรรมเนียมโดยประมาณ: ~{{fee}} Sats\",\n    \"noMint\": \"ไม่พบ mint\",\n    \"notQrCode\": \"ไม่ใช่รหัส QR!\",\n    \"noTX\": \"ยังไม่มีธุรกรรม\",\n    \"activity\": \"กิจกรรม\",\n    \"allHistory\": \"ทั้งหมด\",\n    \"optionalMemo\": \"หมายเหตุที่ไม่บังคับ\",\n    \"paste\": \"วาง\",\n    \"paymentPending\": \"การชำระเงินรอดำเนินการ\",\n    \"paymentSuccess\": \"ชำระเงินสำเร็จแล้ว!\",\n    \"nostrPaymentSuccess\": \"ส่งแล้ว!\",\n    \"paymentType\": \"ประเภทการชำระเงิน\",\n    \"payWithLn\": \"จ่ายด้วยวอลเล็ต LN ของคุณ\",\n    \"preferences\": \"การตั้งค่า\",\n    \"readme\": \"อ่านฉัน\",\n    \"sender\": \"ผู้ส่ง\",\n    \"recipient\": \"ผู้รับ\",\n    \"reqTimeout\": \"หมดเวลาคำขอเครือข่าย\",\n    \"restore\": \"คืนค่า\",\n    \"save\": \"บันทึก\",\n    \"scanAgain\": \"สแกนอีกครั้ง\",\n    \"scan\": \"สแกน\",\n    \"scanQR\": \"สแกน QR\",\n    \"qrScanHint\": \"วาง QR code ให้อยู่ในกรอบ\",\n    \"qrScanFormats\": \"Cashu, Lightning, LNURL หรือ Bitcoin\",\n    \"qrScanReady\": \"พร้อมสแกน\",\n    \"qrScanPaused\": \"หยุดสแกนชั่วคราว\",\n    \"animatedQrProgress\": \"ความคืบหน้า QR แบบเคลื่อนไหว\",\n    \"receivingAnimatedQr\": \"กำลังรับ QR แบบเคลื่อนไหว\",\n    \"unsupportedFormat\": \"ไม่รองรับรูปแบบนี้\",\n    \"cashuPaymentRequestQrUnsupported\": \"ยังไม่รองรับคำขอชำระเงิน Cashu จาก QR\",\n    \"bitcoinAddressPaymentsUnsupported\": \"ไม่รองรับการชำระเงินไปยังที่อยู่ Bitcoin\",\n    \"cameraAccessRequired\": \"ต้องการสิทธิ์เข้าถึงกล้อง\",\n    \"cameraAccessDenied\": \"การเข้าถึงกล้องถูกปฏิเสธ\",\n    \"cameraAccessRequiredHint\": \"เราต้องใช้กล้องเพื่อสแกน QR code สำหรับการชำระเงินและ token\",\n    \"cameraAccessDeniedHint\": \"เปิดสิทธิ์เข้าถึงกล้องในการตั้งค่าอุปกรณ์เพื่อสแกน QR code\",\n    \"allowCameraAccess\": \"อนุญาตให้ใช้กล้อง\",\n    \"openSettings\": \"เปิดการตั้งค่า\",\n    \"seconds\": \"วินาที\",\n    \"selectAmount\": \"เลือกจำนวน\",\n    \"selected\": \"เลือกแล้ว\",\n    \"selectMint\": \"เลือก mint เพื่อส่งจาก\",\n    \"selectMints\": \"เลือก mint\",\n    \"sendEcash\": \"ส่ง Ecash\",\n    \"share\": \"แชร์\",\n    \"submitPaymentReq\": \"ถอนเงิน\",\n    \"to\": \"ถึง\",\n    \"today\": \"วันนี้\",\n    \"tokenInfoErr\": \"มีข้อผิดพลาดขณะรับข้อมูล token\",\n    \"totalInclFee\": \"รวมทั้งหมดรวมค่าธรรมเนียม\",\n    \"reservedTotal\": \"ยอดรวมที่กันไว้\",\n    \"trustMint\": \"เชื่อมั่นใน mint นี้?\",\n    \"tryLater\": \"กรุณาลองอีกครั้งในภายหลัง\",\n    \"unknownType\": \"ประเภทข้อมูลที่ไม่รู้จัก\",\n    \"version\": \"เวอร์ชัน\",\n    \"viewMnemonic\": \"ดู Mnemonic\",\n    \"wallet\": \"วอลเล็ต\",\n    \"willDoLater\": \"จะทำในภายหลัง\",\n    \"yes\": \"ใช่\",\n    \"invalidPubKey\": \"คีย์สาธารณะไม่ถูกต้อง!\",\n    \"walletLocked\": \"กระเป๋าถูกล็อก\",\n    \"explainer1\": \"eNuts เป็นกระเป๋าเงิน Lightning ที่มีความรับผิดชอบซึ่งช่วยให้สามารถทำธุรกรรมได้โดยเป็นส่วนตัวและรวดเร็วโดยใช้โปรโตคอล Cashu. ทุนของคุณถูกควบคุมโดยมิ้นต์ที่คุณโต้ตอบและ Ecash ถูกเก็บไว้ในอุปกรณ์ของคุณ\",\n    \"explainer2\": \"Cashu เป็นโปรโตคอล Ecash ใหม่สำหรับแอปพลิเคชัน Bitcoin แบบซึ่งมิ้นต์เป็นโหนด Lightning ที่ดำเนินการธุรกรรม Bitcoin และให้คุณ Ecash. สบายใจได้ว่ามิ้นต์ยังไม่ทราบเรื่องการชำระเงิน Ecash ของคุณ\",\n    \"explainer3\": \"เพียงเพิ่มมิ้นต์ผ่าน URL และชำระใบแจ้งหนี้ Lightning เพื่อรับ Ecash. eNuts แนะนำคุณ ช่วยให้คุณได้รับเงินจากใครก็ได้โดยทันทีและด้วยการยินยอมของคุณ โดยอัตโนมัติเพิ่มมิ้นต์ที่เกี่ยวข้อง สลับเงินระหว่างมิ้นต์และส่ง Ecash เมื่อคุณมียอดเงิน\",\n    \"send&receive\": \"ส่ง & รับ\",\n    \"contactsNostr\": \"รายชื่อ & Nostr\",\n    \"nostrExplainer\": \"การดำเนินการ Nostr ทำให้การประสานข้อมูลรายชื่อติดต่อของคุณเป็นไปอย่างราบรื่นโดยไม่ต้องใส่คีย์ส่วนตัวของคุณ เนื่องจากเราสร้างขึ้นใหม่ให้คุณ ข้อมูลของคุณแสดงด้วยคีย์สาธารณะ ในขณะที่คีย์ส่วนตัวใหม่เข้ารหัส / ถอดรหัสข้อความของคุณ\",\n    \"send\": \"ส่ง\",\n    \"sendEcashDashboard\": \"สร้าง Cashu token และส่งให้กับใครก็ได้\",\n    \"payInvoiceDashboard\": \"ส่งเงินของคุณไปยังโหนด Lightning\",\n    \"receiveEcashDashboard\": \"วางและแลกเปลี่ยน Cashu token จากคลิปบอร์ด\",\n    \"receiveEcashNostr\": \"ข้อความ Nostr\",\n    \"receiveEcashNostrHint\": \"ตรวจสอบข้อความ Nostr เพื่อ Ecash\",\n    \"createInvoiceDashboard\": \"รับ Ecash โดยการชำระใบแจ้งหนี้ Lightning\",\n    \"hideNuts\": \"ซ่อนยอดคงเหลือ\",\n    \"checkingDms\": \"กำลังตรวจสอบ DMs ของคุณสำหรับ Ecash...\",\n    \"clearOverHere\": \"ทุกอย่างในนี้ชัดเจนแล้ว!\",\n    \"totalDmsReceived\": \"คุณได้รับ {{totalDms}} Cashu token.\",\n    \"swapNow\": \"สลับทันที\",\n    \"swap\": \"สลับ\",\n    \"emptyMint\": \"มิ้นต์ไม่มีเงิน\",\n    \"zapSoon\": \"Zaps จะถูกเพิ่มเร็ว ๆ นี้...\",\n    \"enutsPub\": \"คีย์สาธารณะ eNuts: \",\n    \"seeFullHistory\": \"ดูประวัติการทำธุรกรรมทั้งหมด\",\n    \"next\": \"ถัดไป\",\n    \"skip\": \"ข้าม\",\n    \"donateLn\": \"บริจาค\",\n    \"supportHint\": \"การมีส่วนร่วมใด ๆ ไม่ว่าจะเล็กหรือใหญ่ก็มีผลกระทบมาก. หน้าจอยืนยันกำลังพัฒนาอยู่\",\n    \"newToken\": \"Cashu token ใหม่\",\n    \"disclaimerHint\": \"คำปฏิเสธนี้ควรถือเป็นสำคัญและไม่ควรถูกละเลยหรือประมาท. เราขอขอบคุณสำหรับความสนใจในโครงการนี้และจะดำเนินการพัฒนาต่อไป\",\n    \"searchContacts\": \"ค้นหาหรือพิมพ์ NPUB\",\n    \"submit\": \"ส่ง\",\n    \"clearMetadataCache\": \"ล้างแคชเมตาดาต้า\",\n    \"clearMetadataCacheHint\": \"ล้างแคชเมตาดาต้า?\",\n    \"clearImageCache\": \"ล้างแคชภาพ\",\n    \"clearImageCacheHint\": \"ล้างแคชภาพ?\",\n    \"pullRefresh\": \"ดึงเพื่อรีเฟรช\",\n    \"processTestPay\": \"กำลังประมวลผลการชำระเงินทดสอบ...\",\n    \"confirmMint\": \"ยืนยันมิ้นต์ใหม่\",\n    \"confirmMintHint\": \"คุณแน่ใจหรือไม่ว่าคุณต้องการเพิ่มมิ้นต์นี้?\",\n    \"npubAlreadyAdded\": \"NPUB ถูกเพิ่มแล้ว\",\n    \"replaceNpub\": \"แทนที่ NPUB\",\n    \"replaceNpubTxt\": \"คุณแน่ใจหรือไม่ว่าต้องการแทนที่ NPUB ปัจจุบัน?\",\n    \"npubAdded\": \"เพิ่ม NPUB เรียบร้อยแล้ว!\",\n    \"showContacts\": \"แสดงรายชื่อ\",\n    \"topUpNow\": \"รับ Ecash ทันที\",\n    \"scanAnother\": \"สแกนรหัส QR อื่น\",\n    \"deleteNpub\": \"ลบ NPUB?\",\n    \"delNpubHint\": \"ข้อมูลทั้งหมดเกี่ยวกับผู้ติดต่อและข้อมูลที่เกี่ยวข้องจะถูกลบ\",\n    \"addNewNpub\": \"เพิ่ม NPUB ใหม่?\",\n    \"addNpubHint\": \"สิ่งนี้จะลบข้อมูลทั้งหมดที่เกี่ยวข้องกับ NPUB ปัจจุบันของคุณ\",\n    \"zap\": \"Zap\",\n    \"zapNow\": \"Zap ทันที\",\n    \"meltNostrProfileHint\": \"โอนเงินไปยังที่อยู่ LN ที่เกี่ยวข้องกับโปรไฟล์ Nostr ของคุณ\",\n    \"nostrDmHint\": \"eNuts ไม่สามารถเข้าถึงข้อความ DM ของบัญชี Nostr ของคุณได้เนื่องจากขาดของการเข้าถึงคีย์ส่วนตัว แทนที่นั้นเราสร้างคีย์ใหม่ให้คุณสำหรับการส่ง Ecash เมื่อคุณส่ง Ecash ผ่าน Nostr ผู้รับจะได้รับ Ecash โดยใช้คีย์สาธารณะ eNuts ของคุณ หากผู้รับตอบกลับ DM ด้วยตั๋ว Ecash คุณสามารถดูได้ที่นี่ เรากำลังทำงานอย่างเต็มที่เพื่อหาวิธีคีย์ส่วนตัวที่ปลอดภัย\",\n    \"nostrIssueHeader\": \"ปัญหาติดต่อ Nostr\",\n    \"nostrIssueHint\": \"หากคุณพบปัญหาในการเปิดติดต่อ Nostr คลิกที่ปุ่มด้านล่างหรือรีเซ็ตข้อมูล Nostr ใน 'ตัวเลือก' > 'รายชื่อ' > 'รีเซ็ตข้อมูลเดี๋ยวนี้' เพื่อแก้ไขปัญหา\",\n    \"submitNostrIssue\": \"รีเซ็ตข้อมูลเดี๋ยวนี้\",\n    \"nostrIssueSuccess\": \"รีเซ็ตข้อมูล Nostr เรียบร้อยแล้ว!\",\n    \"createLnInvoice\": \"สร้างใบแจ้งหนี้ Lightning\",\n    \"metadataCacheCleared\": \"ล้างแคชเมตาดาต้าเรียบร้อยแล้ว!\",\n    \"imageCacheCleared\": \"ล้างแคชภาพเรียบร้อยแล้ว!\",\n    \"leaveGithubStar\": \"สนับสนุนเราด้วยดาว Github\",\n    \"alreadySpentHint\": \"บางพิสูจน์ในยอดคงเหลือของคุณถูกใช้หรือถูกเรียกเก็บที่อื่น แก้ไขโดยการลบทิ้งใน 'ตัวเลือก' > 'การจัดการมิ้นต์' > 'ตรวจสอบพิสูจน์'\",\n    \"useNpub\": \"ใช้ NPUB\",\n    \"autoSwapToDefaulMint\": \"สลับอัตโนมัติไปยังมิ้นต์เริ่มต้น\",\n    \"trustMintOpt\": \"เชื่อมั่นในมิ้นต์\",\n    \"swapHint\": \"ตัวเลือกนี้ต้องการการชำระเงินผ่าน Lightning เกี่ยวข้องกับค่าธรรมเนียมและอาจเพิ่มมิ้นต์ที่ไม่รู้จักเข้าไปในรายการหากมีการคืนค่าธรรมเนียม\",\n    \"trustHint\": \"มิ้นต์ที่เกี่ยวข้องกับโทเค็นจะถูกเพิ่มในรายการที่เชื่อถือได้ของคุณ\",\n    \"noDefaultHint\": \"คุณต้องตั้งค่ามิ้นต์เริ่มต้นเพื่อทำการสลับอัตโนมัติ\",\n    \"autoSwapSuccess\": \"สลับสำเร็จ!\",\n    \"paidInvoice\": \"{{ count }} ใบแจ้งหนี้ได้รับการชำระเงินด้วยจำนวนรวม {{ total }} Sats\",\n    \"paidInvoices\": \"{{ count }} ใบแจ้งหนี้ได้รับการชำระเงินด้วยจำนวนรวม {{ total }} Sats\",\n    \"checkPayment\": \"ตรวจสอบการชำระเงิน\",\n    \"lnPaymentSpamHint\": \"โปรดรอ {{ remainingSeconds }} วินาทีเพื่อหลีกเลี่ยงการสแปมมิ้นต์\",\n    \"shareEnuts\": \"แบ่งปัน eNuts กับใครสักคน\",\n    \"supportUs\": \"สนับสนุนเรา\",\n    \"justNow\": \"เมื่อสักครู่นี้\",\n    \"hoursAgo\": \"{{count}} ชั่วโมงที่แล้ว\",\n    \"yesterday\": \"เมื่อวาน\",\n    \"awaitingPayment\": \"รอการชำระเงิน\",\n    \"receivedFromMint\": \"ได้รับจากมิ้นต์\",\n    \"status\": \"สถานะ\",\n    \"unit\": \"หน่วย\",\n    \"quoteId\": \"รหัสใบเสนอราคา\",\n    \"nfcPaymentLimits\": \"ขีดจำกัดการชำระเงิน\",\n    \"nfcPaymentLimitsDesc\": \"ตั้งค่าขีดจำกัดจำนวนเงินเริ่มต้นและกำหนดเองสำหรับการชำระเงิน NFC\",\n    \"amountLimits\": \"ขีดจำกัดจำนวนเงิน\",\n    \"amountLimitsDesc\": \"แตะเพื่อตั้งเป็นค่าเริ่มต้น กดค้างเพื่อลบ\",\n    \"noLimit\": \"ไม่จำกัด\",\n    \"noLimitDesc\": \"ยืนยันจำนวนเงินใดก็ได้\",\n    \"deleteAmount\": \"ลบจำนวนเงิน\",\n    \"deleteAmountConfirm\": \"คุณแน่ใจหรือไม่ว่าต้องการลบ {{amount}} sats ออกจากจำนวนเงินที่เลือกอย่างรวดเร็ว?\",\n    \"delete\": \"ลบ\",\n    \"resetToDefaults\": \"รีเซ็ตเป็นค่าเริ่มต้น\"\n  },\n  \"error\": {\n    \"checkSpendableErr\": \"เกิดข้อผิดพลาดขณะตรวจสอบว่า Token สามารถใช้ได้\",\n    \"claimTokenErr\": \"เกิดข้อผิดพลาดขณะกำลังเรียกร้อง Token\",\n    \"sendTokenErr\": \"เกิดข้อผิดพลาดขณะกำลังส่ง Token\",\n    \"header\": \"เกิดข้อผิดพลาด\",\n    \"msg\": \"เราขอโทษในความไม่สะดวกที่คุณพบ เพื่อช่วยเราปรับปรุงซอฟต์แวร์โปรดถ่ายภาพหน้าจอและสร้างรายงานข้อผิดพลาดเล็กน้อย\",\n    \"reportBug\": \"รายงานข้อผิดพลาด\",\n    \"requestMintErr\": \"เกิดข้อผิดพลาดขณะขอใบแจ้งหนี้จาก Mint\",\n    \"stackNA\": \"ข้อผิดพลาดไม่สามารถแสดงได้\",\n    \"generalMeltingErr\": \"Mint ไม่สามารถค้นหาเส้นทางการชำระเงิน Lightning ที่เหมาะสมไปยังโหนดของคุณ\",\n    \"invoiceFromLnurlError\": \"ไม่สามารถสร้างใบแจ้งหนี้โดยใช้ LNURL ของคุณ\",\n    \"invoiceScanError\": \"ไม่สามารถใช้ใบแจ้งหนี้จากรหัส QR ที่สแกนได้\"\n  },\n  \"history\": {\n    \"checkSpent\": \"ตรวจสอบว่าโทเค็นถูกใช้ไปหรือยัง\",\n    \"isPending\": \"โทเค็นอยู่ระหว่างรอ\",\n    \"isSpent\": \"โทเค็นถูกใช้ไปแล้ว\",\n    \"justNow\": \"เมื่อสักครู่นี้\",\n    \"hoursAgo\": \"{{count}} ชั่วโมงที่แล้ว\",\n    \"yesterday\": \"เมื่อวาน\",\n    \"memo\": \"บันทึก\",\n    \"nHrsAgo\": \"{{hrs}} ชั่วโมงที่ผ่านมา\",\n    \"nMinsAgo\": \"{{mins}} นาทีที่ผ่านมา\",\n    \"noMemo\": \"ไม่มีบันทึก\",\n    \"oneHrAgo\": \"1 ชั่วโมงที่ผ่านมา\",\n    \"oneMinAgo\": \"1 นาทีที่ผ่านมา\",\n    \"paymentHash\": \"รหัสการชำระเงิน\",\n    \"settleTime\": \"เวลาตกลง\",\n    \"showQr\": \"แสดงรหัส QR\",\n    \"receive\": \"รับ\",\n    \"send\": \"ส่ง\",\n    \"melt\": \"หลอม\",\n    \"receivedEcash\": \"ได้รับ Ecash\",\n    \"sentEcash\": \"ส่ง Ecash แล้ว\",\n    \"paidInvoice\": \"ชำระใบแจ้งหนี้แล้ว\",\n    \"details\": \"รายละเอียด\",\n    \"date\": \"วันที่\",\n    \"amount\": \"จำนวน\",\n    \"token\": \"โทเค็น\"\n  },\n  \"mints\": {\n    \"addCustomName\": \"เพิ่มชื่อกำหนดเอง\",\n    \"additionalInfo\": \"ข้อมูลเพิ่มเติม\",\n    \"addMintBtn\": \"เพิ่มมิ้นต์\",\n    \"addNewMint\": \"เพิ่มมิ้นต์ใหม่\",\n    \"atLeast2Mints\": \"คุณต้องมีอย่างน้อย 2 มิ้นต์เพื่อทำการสลับระหว่างมาสินต์หลายแหล่ง\",\n    \"awaitingInvoice\": \"กำลังรอใบแจ้งหนี้\",\n    \"cashOutAmountHint\": \"อาจมีค่าธรรมเนียมการส่งแบบ Lightning ซึ่งจะถูกเพิ่มเข้าไป และค่าธรรมเนียมที่จ่ายเกินจะถูกคืน\",\n    \"checkProofs\": \"ตรวจสอบพิสูจน์\",\n    \"checkProofsQ\": \"ตรวจสอบพิสูจน์ทั้งหมดหรือไม่\",\n    \"checkProofsTxt\": \"การดำเนินการนี้จะตรวจสอบว่าโทเค็นของคุณสามารถใช้ได้หรือไม่ และมิฉะนั้นจะลบโทเค็นที่ไม่สามารถใช้ได้\",\n    \"chooseMeltMintHint\": \"เลือกมิ้นต์ที่คุณต้องการถอนเงิน\",\n    \"chooseMintHint\": \"เลือกมิ้นต์ที่คุณต้องการรับ Ecash มิ้นต์จะเป็นผู้เก็บเงินสำหรับคุณ\",\n    \"chooseTarget\": \"เลือกผู้รับการชำระเงิน\",\n    \"coinSelectionHint\": \"ยอดเงิน Ecash ของคุณเป็นสิ่งที่เรียบเรียงขึ้นจากชุดเหรียญ Coin selection ช่วยให้คุณเลือกเหรียญที่คุณต้องการใช้ Coin-sets ได้รับ ID ชุดหลักจากมิ้นต์ ซึ่งอาจเปลี่ยนไปตามเวลา การเพิ่มชุดใหม่จะเน้นด้วยสีเขียว เราขอแนะนำให้ใช้เหรียญเซ็ตเก่าก่อน\",\n    \"creatingEcashToken\": \"กำลังสร้างโทเค็น Cashu\",\n    \"sendingEcashViaNostr\": \"กำลังส่งโทเค็น Cashu ผ่านทาง Nostr\",\n    \"customName\": \"ชื่อกำหนดเอง\",\n    \"cutomNameAdded\": \"เพิ่มชื่อกำหนดเองแล้ว\",\n    \"dangerZone\": \"โซนเสี่ยง\",\n    \"deletedProofs\": \"ลบ {{proofsToDel}} พิสูจน์แล้ว\",\n    \"delMint\": \"ลบมิ้นต์\",\n    \"delMintSure\": \"คุณต้องการลบมิ้นต์นี้หรือไม่\",\n    \"ecashAmountHint\": \"เลือกจำนวน Ecash ที่คุณต้องการส่ง\",\n    \"editMintName\": \"แก้ไขชื่อมิ้นต์\",\n    \"errDelProofs\": \"เกิดข้อผิดพลาดขณะลบพิสูจน์\",\n    \"funds\": \"เงิน\",\n    \"general\": \"ทั่วไป\",\n    \"importantNotice\": \"ข้อความสำคัญ\",\n    \"inputField\": \"ใบแจ้งหนี้ Lightning หรือ LNURL\",\n    \"invalidUrl\": \"URL ไม่ถูกต้อง\",\n    \"invoiceAmountHint\": \"เลือกจำนวน Ecash ที่คุณต้องการรับ มิ้นต์จะสร้างใบแจ้งหนี้ซึ่งคุณจะต้องชำระโดยใช้กระเป๋าเงิน Lightning\",\n    \"invoiceHint\": \"กรุณารอสักครู่...\",\n    \"lowBal\": \"ยอดเงินของมิ้นต์ต่ำเกินไป!\",\n    \"meltAddressbookHint\": \"เลือก LNURL ของคุณเองหรือที่ติดต่ออื่น ๆ เพื่อเป็นผู้รับชำระเงิน\",\n    \"meltInputHint\": \"วางใบแจ้งหนี้ Lightning หรือ LN-URL หรือที่อยู่ Lightning\",\n    \"meltScanQRHint\": \"สร้างใบแจ้งหนี้ Lightning ด้วยอุปกรณ์อื่น ๆ แล้วสแกนเข้ามา\",\n    \"meltSwapHint\": \"เลือกมิ้นต์อื่นจากรายการที่ไว้วางใจของคุณให้เป็นผู้รับชำระเงิน\",\n    \"copyShareToken\": \"คัดลอกและแชร์อย่างรวดเร็ว\",\n    \"copyShareTokenHint\": \"คัดลอกโทเค็นที่สร้างแล้วและแชร์ผ่านแอปสารบรรณใดก็ได้\",\n    \"sendNostr\": \"ส่งผ่านทาง Nostr\",\n    \"sendNostrHint\": \"ส่ง Ecash โดยตรงไปยังหนึ่งในรายชื่อติดต่อของคุณใน Nostr\",\n    \"meltToken\": \"ถอนเงิน\",\n    \"mintConnectionFail\": \"การเชื่อมต่อกับมิ้นต์ล้มเหลว\",\n    \"mintInfo\": \"ข้อมูลมิ้นต์\",\n    \"mintNewTokens\": \"รับ Ecash\",\n    \"mintNoContact\": \"มิ้นต์ไม่มีข้อมูลการติดต่อ\",\n    \"mntAlreadyAdded\": \"มิ้นต์ถูกเพิ่มแล้ว\",\n    \"noAdditional\": \"มิ้นต์นี้ไม่มีข้อมูลเพิ่มเติม\",\n    \"noInfo\": \"มิ้นต์ไม่มีข้อมูล\",\n    \"noProofs\": \"ไม่พบพิสูจน์สำหรับมิ้นต์นี้\",\n    \"paymentOverview\": \"ภาพรวมการชำระเงิน\",\n    \"processingPaymentByMint\": \"มิ้นต์กำลังดำเนินการชำระเงินตามคำขอของคุณ\",\n    \"processingSwap\": \"กำลังดำเนินการสลับระหว่างมาสินต์หลายแหล่งตามคำขอของคุณ\",\n    \"pubKey\": \"คีย์สาธารณะ\",\n    \"removeDefault\": \"เอาออกจากค่าเริ่มต้น\",\n    \"scanQR\": \"สแกนรหัส QR\",\n    \"sendEcashHint\": \"เลือกมิ้นต์ที่คุณต้องการสร้างโทเค็น Cashu\",\n    \"setDefault\": \"ตั้งเป็นมิ้นต์เริ่มต้น\",\n    \"supportedNuts\": \"NUTs ที่รองรับ\",\n    \"swapNotAllowed\": \"ไม่สามารถสลับจากมิ้นต์ทดสอบได้\",\n    \"zapNotAllowed\": \"ไม่สามารถ Zap จากมิ้นต์ทดสอบได้\",\n    \"testMintHint\": \"นี่คือมิ้นต์ทดสอบเพื่อทดลอง คุณต้องการเพิ่มมันหรือไม่\",\n    \"trustMintSure\": \"คุณแน่ใจหรือว่าต้องการเชื่อมั่นมิ้นต์นี้\",\n    \"updatedDefault\": \"อัปเดตมิ้นต์เริ่มต้นแล้ว\",\n    \"newMintAdded\": \"เพิ่มมิ้นต์แล้ว!\",\n    \"newMintAddedQuestion\": \"คุณต้องการรับ Ecash ตอนนี้หรือไม่\",\n    \"selectSwapReceiver\": \"เลือกมิ้นต์เป็นผู้รับชำระเงิน\",\n    \"prepairZapData\": \"กำลังเตรียมข้อมูลธุรกรรม...\",\n    \"lastUpdated\": \"อัปเดตล่าสุด\",\n    \"mintInfoUpdated\": \"ข้อมูลมิ้นต์อัปเดตแล้ว!\",\n    \"mintInfoUpdateFailed\": \"ไม่สามารถอัปเดตข้อมูลมิ้นต์ได้\",\n    \"npcSettings\": \"Lightning address\",\n    \"npcDefaultAccount\": \"Default\",\n    \"npcTapToCopy\": \"Tap to copy\",\n    \"npcUsernameLabel\": \"Custom username\",\n    \"npcUsernamePlaceholder\": \"optional username\",\n    \"npcPurchaseUsername\": \"Save username\",\n    \"npcSetUsername\": \"Set Username\",\n    \"npcRequestUsername\": \"Request username\",\n    \"npcUsernameFeePrompt\": \"Do you want to set this username for a fee of {{amount}} sats?\",\n    \"npcReceiveTitle\": \"NPC Lightning addresses\",\n    \"npcReceiveHint\": \"Receive Lightning payments into your local Cashu wallet.\",\n    \"npcAccountsLabel\": \"Accounts\",\n    \"npcLocalBalance\": \"Local balance\",\n    \"npcReceiveAddress\": \"Receive address\",\n    \"npcSeedKey\": \"Seed key\",\n    \"npcImportedKey\": \"Imported key\",\n    \"npcActive\": \"Active\",\n    \"npcSyncing\": \"Syncing\",\n    \"npcPaused\": \"Paused\",\n    \"npcNpubFallback\": \"Using your npub until a username is saved\",\n    \"npcSyncAll\": \"Sync all\",\n    \"npcSynced\": \"NPC account synced\",\n    \"npcAccountAdded\": \"NPC account added\",\n    \"npcAccountRemoved\": \"NPC account removed\",\n    \"npcUsernameSaved\": \"Username saved\",\n    \"npcAddAccountTitle\": \"Add NPC account\",\n    \"npcAddAccountHint\": \"Import an existing Nostr key or derive a new key from your seed.\",\n    \"npcPrivateKeyLabel\": \"Private key\",\n    \"npcPrivateKeyPlaceholder\": \"nsec or hex\",\n    \"npcPrivateKeyHint\": \"Imported keys are stored in secure storage on this device.\",\n    \"npcPrivateKeyRequired\": \"Enter an nsec or hex private key.\",\n    \"npcImportPrivateKey\": \"Import private key\",\n    \"npcDeriveAccount\": \"Derive new key\"\n  },\n  \"topNav\": {\n    \"about\": \"เกี่ยวกับเรา\",\n    \"addressBook\": \"สมุดที่อยู่\",\n    \"advancedFunctions\": \"ฟังก์ชั่นขั้นสูง\",\n    \"display\": \"การแสดงผล\",\n    \"history\": \"ประวัติการทำธุรกรรม\",\n    \"language\": \"ภาษา\",\n    \"currency\": \"สกุลเงิน\",\n    \"mintSettings\": \"การตั้งค่าการสร้างมิ้นต์\",\n    \"nfcSettings\": \"การตั้งค่า NFC\",\n    \"npcSettingsTitle\": \"Lightning address\",\n    \"security\": \"ความปลอดภัย\",\n    \"settings\": \"ตัวเลือก\",\n    \"privacy\": \"ความเป็นส่วนตัว\",\n    \"general\": \"ทั่วไป\"\n  },\n  \"wallet\": {\n    \"cashuContent\": \"ผู้เขียนของ Cashu ไม่ใช่นักวิเคราะห์รหัสเชิงลึกและโปรโตคอลยังอยู่ระหว่างการตรวจทาน. มันยังมีข้อกังวลเกี่ยวกับการมีข้อบกพร่องที่อาจเป็นอันตราย. เนื่องจากนั้น Cashu ยังไม่พร้อมใช้ในการใช้งานจริง\",\n    \"cashuExperiment\": \"Cashu ยังเป็นการทดลอง\",\n    \"claiming\": \"กำลังขอเรียกร้อง...\",\n    \"processingInvoice\": \"กำลังประมวลผลใบแจ้งหนี้...\",\n    \"nfcPayment\": \"การชำระเงิน NFC\",\n    \"nfcKeepNearTerminal\": \"ถือโทรศัพท์ของคุณไว้ใกล้เครื่องเทอร์มินัล\",\n    \"nfcSelectMaxAmount\": \"เลือกจำนวนเงินสูงสุด\",\n    \"noLimit\": \"ไม่จำกัด\",\n    \"custodialRisk\": \"ความเสี่ยงในการใช้งานที่มีความรับผิดชอบ, มิ้นต์เก็บคีย์\",\n    \"custodialRiskContent\": \"ด้วย eNuts, คุณไม่ควบคุมคีย์ของ Bitcoin; มิ้นต์เป็นผู้รับผิดชอบ. ดังนั้นหากคุณไม่มั่นใจในมิ้นต์หนึ่ง ๆ ควรหลีกเลี่ยงการโต้ตอบกับมัน\",\n    \"disclaimer\": \"โปรดทราบว่านี่เป็นเบต้าเวอร์ชันในช่วงเริ่มต้นของมันและยังอยู่ในกระบวนการทดสอบก่อนการเผยแพร่อย่างเป็นทางการ. ซอฟต์แวร์และเนื้อหาทั้งหมดที่พบบนมันได้รับการให้บริการตามหลักเป็น \\\"ตามสภาพปัจจุบัน\\\" และ \\\"ตามที่มีอยู่\\\" เราไม่ให้ประกันใด ๆ ไม่ว่าจะเป็นแบบชัดแจ้งหรือนัยนั้น เกี่ยวกับความเหมาะสมหรือความสามารถในการใช้งานของซอฟต์แวร์หรือเนื้อหาใด ๆ ของมัน\",\n    \"enutsDisclaimer\": \"eNuts เป็นซอฟต์แวร์เบต้าที่ยังไม่เสร็จสมบูรณ์\",\n    \"lossContent\": \"Cashu tokens เป็นตั๋วที่เป็นเจ้าของ นั่นหมายความว่าหากคุณสูญเสียการเข้าถึงกับพวกเขา จะไม่มีตัวเลือกการกู้คืนที่นำเข้าใช้. eNuts เก็บตั๋วของคุณในอุปกรณ์ของคุณ. ก่อนลบแอปพลิเคชันให้แน่ใจว่าคุณมีการสำรองข้อมูลตั๋วของคุณ\",\n    \"lossOfTokens\": \"สูญเสียเงิน\",\n    \"enutsMint\": \"มิ้นต์ eNuts ค่าเริ่มต้น\",\n    \"mintDisclaimer\": \"การใช้มิ้นต์ eNuts ค่าเริ่มต้นเป็นที่เสี่ยงต่อความเสี่ยงของคุณเอง. เราขอแนะนำให้คุณระมัดระวังและใช้เฉพาะเพื่อวัตถุประสงค์ทดลองหรือการศึกษาเท่านั้น. ไม่มีการรับประกันใด ๆ เกี่ยวกับความสามารถในการทำงาน ความปลอดภัย หรือความพร้อมใช้งาน และมันอาจหายไปโดยไม่มีการแจ้งให้ทราบ. เงินฝากที่ทำไปยังมิ้นต์นี้ควรถือว่าเป็นบริจาคและอาจไม่ได้รับคืน อาจถูกใช้ในการพัฒนาต่อไป กรุณาทราบถึงความเสี่ยงที่เกี่ยวข้องกับซอฟต์แวร์เบต้า และมันเป็นความรับผิดชอบของคุณที่จะป้องกันสินทรัพย์ของคุณขณะใช้มิ้นต์นี้\",\n    \"paidOut\": \"จ่ายออก\",\n    \"pasteToken\": \"เข้ารหัสสลับแล้ว\",\n    \"payInvoice\": \"จ่ายใบแจ้งหนี้\",\n    \"payLNInvoice\": \"จ่ายใบแจ้งหนี้ผ่าน Lightning\",\n    \"receive\": \"รับ\",\n    \"send\": \"ส่ง\",\n    \"proofs\": \"พิสูจน์\",\n    \"swapped\": \"สลับแล้ว\"\n  }\n}\n"
  },
  {
    "path": "eas.json",
    "content": "{\n  \"cli\": {\n    \"version\": \">= 5.6.0\",\n    \"appVersionSource\": \"remote\"\n  },\n  \"build\": {\n    \"development\": {\n      \"developmentClient\": true,\n      \"distribution\": \"internal\",\n      \"android\": {\n        \"buildType\": \"apk\"\n      }\n    },\n    \"preview\": {\n      \"distribution\": \"internal\",\n      \"android\": {\n        \"buildType\": \"apk\"\n      }\n    },\n    \"production\": {\n      \"autoIncrement\": true,\n      \"android\": {\n        \"buildType\": \"apk\"\n      }\n    }\n  },\n  \"submit\": {\n    \"production\": {}\n  }\n}\n"
  },
  {
    "path": "expo-router-implementation-steps.md",
    "content": "# Expo Router Implementation Steps\n\nThis document is the working execution plan for the Expo Router refactor.\n\nUse it as the source of truth while implementing. Do not skip ahead unless the current step is complete or deliberately blocked.\n\nRelated documents:\n\n- `expo-router-migration-plan.md`\n- `expo-router-migration-issues.md`\n\n## Working Rules\n\n1. Keep each implementation slice small enough to verify before moving on.\n2. Prefer route wrappers in `src/app/**` over moving screen files immediately.\n3. Do not refactor unrelated business logic while changing navigation.\n4. Prefer serializable route params. If that is not possible, stop and introduce a small flow-state mechanism explicitly.\n5. Keep old navigation code in place until the replacement path is verified.\n6. After each step, confirm the app still boots and the touched flow still works.\n\n## Decision Baseline\n\nThese decisions are assumed unless changed later:\n\n1. Use Expo Router with thin wrappers in `src/app/**` first.\n2. Use direct route paths instead of nested `{ screen: ... }` navigation.\n3. Replace operation-object route params with `operationId` lookup.\n4. Leave broader payment-flow object cleanup until after the router shell is stable.\n\n## Step 0: Preflight\n\nRelated issues:\n`ER-09`, `ER-20`\n\nGoal:\nStart with a clean understanding of the live route surface before changing startup.\n\nTasks:\n\n1. Freeze the canonical route list from the current live navigator tree.\n2. Mark stale route names and dead callers as cleanup targets, not active requirements.\n3. Confirm the target route tree to implement under `src/app/**`.\n\nDeliverable:\nOne canonical route inventory for the migration.\n\nCheckpoint:\nThere is no ambiguity about which routes must keep working in the first Router pass.\n\n## Step 1: Install and wire Expo Router entry\n\nRelated issues:\n`ER-01`\n\nGoal:\nMake Expo Router own app startup without breaking the current polyfills.\n\nTasks:\n\n1. Add `expo-router` dependency.\n2. Create a custom app entry file.\n3. In that entry file, import:\n   - `src/shim`\n   - `message-port-polyfill`\n   - `expo-router/entry` last\n4. Update `package.json` `main` to the new entry file.\n5. Add the `expo-router` plugin to `app.json`.\n6. Add an app `scheme` to `app.json`.\n7. Enable `experiments.typedRoutes` in `app.json`.\n\nDeliverable:\nThe app boots through Expo Router entry instead of `registerRootComponent(App)`.\n\nCheckpoint:\nThe app starts successfully and polyfill-dependent code still initializes.\n\nStop condition:\nIf startup breaks before any routing changes, fix entry/config before continuing.\n\n## Step 2: Create the root Router layout and move bootstrap into it\n\nRelated issues:\n`ER-02`, `ER-05`\n\nGoal:\nMove the existing app shell into `src/app/_layout.tsx`.\n\nTasks:\n\n1. Create `src/app/_layout.tsx`.\n2. Move provider composition from `src/components/App.tsx` into the root layout.\n3. Move app initialization logic into the root layout or a shared helper used by it.\n4. Preserve:\n   - splash screen control\n   - manager initialization\n   - theme provider\n   - prompt, bottom sheet, keyboard, safe area, menu, and modal providers\n5. Replace the local `NavigationContainer` with Router-compatible theme wiring.\n6. Render a blank/loading state until initialization completes.\n\nDeliverable:\nThe app shell exists entirely under `src/app/_layout.tsx`.\n\nCheckpoint:\nThe app boots to a blank/loading placeholder, then renders successfully with all providers active.\n\nStop condition:\nIf initialization order changes break manager setup, fix that before any route work.\n\n## Step 3: Add root routes with wrappers only\n\nRelated issues:\n`ER-03`, `ER-04`\n\nGoal:\nRecreate the top-level app routes in Expo Router with minimal logic changes.\n\nTasks:\n\n1. Create root route files:\n   - `src/app/index.tsx`\n   - `src/app/onboarding.tsx`\n   - `src/app/dashboard.tsx`\n   - `src/app/qr-scanner.tsx`\n2. Make each route file a thin wrapper around the existing screen component.\n3. Implement `src/app/index.tsx` redirect logic using the existing onboarding decision.\n4. Update onboarding completion to Router navigation.\n\nDeliverable:\nThe app can reach onboarding, dashboard, and QR scanner through file-based routes.\n\nCheckpoint:\nFresh-install and returning-user entry behavior matches the current app.\n\nStop condition:\nIf the app can boot but cannot route to dashboard/onboarding reliably, fix that before adding nested layouts.\n\n## Step 4: Add nested folder layouts for stable sections\n\nRelated issues:\n`ER-03`, `ER-19`\n\nGoal:\nRecreate the nested stack structure in Router form for the low-risk sections first.\n\nTasks:\n\n1. Create layouts for:\n   - `src/app/settings/_layout.tsx`\n   - `src/app/mint/_layout.tsx`\n   - `src/app/history/_layout.tsx`\n   - `src/app/restore/_layout.tsx`\n   - `src/app/payment/_layout.tsx`\n2. Create route wrappers for each existing screen in those groups.\n3. Preserve screen options currently set in stack navigators.\n4. Keep screen files in `src/screens/**` for now.\n\nDeliverable:\nThe file-based route tree mirrors the current stack tree.\n\nCheckpoint:\nThe main sections open via Expo Router paths and render the current screens.\n\n## Step 5: Convert simple navigation calls first\n\nRelated issues:\n`ER-06`, `ER-19`\n\nGoal:\nReplace the easiest imperative navigation calls before touching param-heavy flows.\n\nTasks:\n\n1. Convert simple `goBack` calls to `router.back()` where possible.\n2. Convert simple route pushes/replaces that do not carry complex params.\n3. Replace nested navigator calls such as:\n   - `navigate(\"Settings\", { screen: ... })`\n   - `navigate(\"Mint\", { screen: ... })`\n   - `navigate(\"History\", { screen: ... })`\n     with direct route paths.\n4. Leave complex route params on the old screen prop model temporarily if necessary.\n\nSuggested targets first:\n\n- settings entry\n- dashboard to simple routes\n- mint home to mint add\n- history index open/close\n\nDeliverable:\nThe app uses Router navigation for the simplest paths first.\n\nCheckpoint:\nNo behavior change in simple route transitions.\n\n## Step 6: Keep low-level navigation hooks only where needed\n\nRelated issues:\n`ER-08`\n\nGoal:\nPreserve critical flow guards while removing unnecessary dependency on screen props.\n\nTasks:\n\n1. Identify screens that truly need `useNavigation()` for listeners.\n2. Leave `beforeRemove` listeners in place for now on:\n   - dashboard\n   - processing\n   - success\n   - successScreen\n   - recovering\n   - processingError\n3. Verify `useFocusEffect` behavior on:\n   - invoice\n   - QR scanner\n   - animated QR hook\n\nDeliverable:\nLifecycle-sensitive screens still work after route conversion.\n\nCheckpoint:\nBack-blocking and focus reset still behave correctly on touched flows.\n\n## Step 7: Implement the mint invoice `operationId` refactor\n\nRelated issues:\n`ER-13`\n\nGoal:\nRemove prepared mint operation objects from route params.\n\nTasks:\n\n1. Change the prepare-and-navigate flow in `MintSelectAmount` to pass only `operationId`.\n2. Update the route type and route wrapper for the invoice screen accordingly.\n3. Update `Invoice` to look up the prepared operation using the ID.\n4. Use the looked-up operation for:\n   - QR display\n   - amount display\n   - finalization event matching\n5. Add graceful fallback behavior if the operation cannot be found.\n\nDeliverable:\nThe mint invoice route only carries `operationId`.\n\nCheckpoint:\nCreating an invoice, waiting for it to finalize, and navigating to success still works.\n\nStop condition:\nIf there is no reliable operation lookup API, pause and introduce a tiny session map deliberately.\n\n## Step 8: Implement the melt confirmation `operationId` refactor\n\nRelated issues:\n`ER-14`\n\nGoal:\nRemove prepared melt operation objects from route params.\n\nTasks:\n\n1. Change both melt-entry callers to pass only `operationId`.\n2. Update the melt confirmation route type and route wrapper.\n3. Update `MeltConfirmation` to look up the prepared operation by ID.\n4. Use the looked-up operation for:\n   - amount display\n   - fee display\n   - execute call\n   - success payload construction\n5. Review whether `MeltLnAddress` still needs route metadata, and minimize it if possible.\n\nDeliverable:\nThe melt confirmation route only carries `operationId`.\n\nCheckpoint:\nThe LN payout flow still reaches confirmation and can execute successfully.\n\n## Step 9: Convert history details to stable-key routing\n\nRelated issues:\n`ER-11`\n\nGoal:\nStop passing full `HistoryEntry` objects through the route layer.\n\nTasks:\n\n1. Decide on the history detail key.\n2. Update the history list/detail navigation to route by key.\n3. Update the detail screen to rehydrate the entry from the key.\n4. Add a not-found fallback if the entry cannot be resolved.\n\nDeliverable:\nHistory detail navigation no longer depends on a full entry object in params.\n\nCheckpoint:\nOpening history details from dashboard and history screens still works.\n\n## Step 10: Fix the recovery flow handoff\n\nRelated issues:\n`ER-12`\n\nGoal:\nMake the recovery flow Router-safe and correct the current mint-selection handoff.\n\nTasks:\n\n1. Decide on the recovery flow state holder.\n2. Store selected mint URLs from `SelectRecoveryMint` in that holder.\n3. Store or derive the recovery seed outside the route params.\n4. Update `Recover` and `Recovering` to consume that state without passing `Uint8Array` in params.\n5. Verify the selected-mints choice actually reaches the recovery logic.\n\nDeliverable:\nRecovery state is not passed through route params and the user’s mint selection is preserved.\n\nCheckpoint:\nSelecting a subset of mints and completing recovery works as intended.\n\n## Step 11: Convert mint details routing to a safe URL form\n\nRelated issues:\n`ER-10`\n\nGoal:\nMake mint details routing safe for arbitrary mint URLs.\n\nTasks:\n\n1. Choose the route form:\n   - query param\n   - encoded path segment\n2. Update mint details navigation to use that form.\n3. Update the mint details screen to decode/read the route input.\n\nDeliverable:\nMint details routing works for any valid mint URL.\n\nCheckpoint:\nMints with normal HTTPS URLs and any trailing path content still open correctly.\n\n## Step 12: Refactor the encoded token route\n\nRelated issues:\n`ER-15`\n\nGoal:\nStop passing `Token` objects through route params.\n\nTasks:\n\n1. Decide whether the token can be serialized safely enough for a query param.\n2. If not, introduce a small flow-state holder keyed by ID.\n3. Update the send flow and encoded token screen to use the new route payload.\n\nDeliverable:\nThe encoded token route uses only simple route data.\n\nCheckpoint:\nCreating and viewing a sendable token still works.\n\n## Step 13: Refactor the broader payment flow objects\n\nRelated issues:\n`ER-16`, `ER-17`\n\nGoal:\nRemove the remaining rich objects from coin-selection, processing, and error routes.\n\nTasks:\n\n1. Identify the minimum state required across:\n   - select-mint-to-swap-to\n   - coin-selection\n   - processing\n   - processing-error\n2. Introduce a payment flow state holder if needed.\n3. Route by flow ID and small primitives only.\n4. Simplify `processingError` to minimal UI params.\n\nDeliverable:\nThe payment pipeline no longer depends on non-serializable route params.\n\nCheckpoint:\nSend, melt, and swap-related flows still work end to end.\n\n## Step 14: Consolidate success handling\n\nRelated issues:\n`ER-18`\n\nGoal:\nReduce the migration surface by choosing one success screen.\n\nTasks:\n\n1. Compare `Success.tsx` and `SuccessScreen.tsx` responsibilities.\n2. Choose the canonical screen.\n3. Move callers to that screen.\n4. Delete the duplicate route and dead param model.\n\nDeliverable:\nOne success route remains.\n\nCheckpoint:\nAll current success-entry points still land on the intended UI.\n\n## Step 15: Finish screen-level Router API migration\n\nRelated issues:\n`ER-06`\n\nGoal:\nReplace the remaining screen-prop route access with Router hooks.\n\nTasks:\n\n1. Convert remaining screens from `{ navigation, route }` props to Router hooks.\n2. Keep `useNavigation()` only where event listeners still require it.\n3. Remove route-prop dependency from reusable components where possible.\n\nDeliverable:\nLive screens access routing through Expo Router-first APIs.\n\nCheckpoint:\nNo touched screen still depends on old screen-prop typing unless explicitly deferred.\n\n## Step 16: Clean up route drift and dead paths\n\nRelated issues:\n`ER-09`, `ER-20`\n\nGoal:\nDelete dead route names and references after the live replacements exist.\n\nTasks:\n\n1. Remove stale route names from the nav type layer.\n2. Remove dead callers such as:\n   - `mintmanagement`\n   - `selectAmount`\n   - `nostrReceive`\n   - `qr scan`\n3. Normalize any remaining route names to the Router naming scheme.\n\nDeliverable:\nOnly live Router-backed route names remain.\n\nCheckpoint:\nSearches no longer show callers to removed routes.\n\n## Step 17: Remove the old nav type files\n\nRelated issues:\n`ER-21`\n\nGoal:\nDelete the obsolete React Navigation param-list model.\n\nTasks:\n\n1. Remove imports from `src/model/nav.ts` and `src/nav/navTypes.ts` as screens are converted.\n2. Delete those files once nothing live depends on them.\n3. Replace any remaining shared types with local interfaces or non-navigation domain types.\n\nDeliverable:\nThe old nav typing layer is gone.\n\nCheckpoint:\nNo live import path points at the old nav type files.\n\n## Step 18: Remove the old manual navigation layer\n\nRelated issues:\n`ER-22`\n\nGoal:\nDelete the old navigator implementation completely.\n\nTasks:\n\n1. Remove:\n   - `src/components/nav/Navigator.tsx`\n   - `src/nav/SettingsNavigator.tsx`\n   - `src/nav/MintNavigator.tsx`\n   - `src/nav/RestoreNavigator.tsx`\n   - `src/nav/HistoryNavigator.tsx`\n2. Remove any helper code that only existed for the manual stack layer.\n3. Keep only the minimum low-level navigation code still needed by Router-based listeners.\n\nDeliverable:\nThe app navigates entirely through Expo Router.\n\nCheckpoint:\nNo manual navigator file remains in live use.\n\n## Final Verification Pass\n\nRun through these flows after Step 18:\n\n1. cold start to onboarding and dashboard\n2. dashboard to settings, mint, history, restore, send, melt, scan\n3. mint add\n4. mint invoice creation and success transition\n5. melt input to confirmation to success\n6. QR scan to melt or claim paths\n7. history details\n8. recovery with selected mints\n9. success and processing back behavior\n10. deep-link intake behavior for payment payloads\n\n## If Blocked\n\nIf a step is blocked, do not keep patching around it blindly.\n\nInstead:\n\n1. write down the exact blocker\n2. decide whether it is a lookup problem, a route-shape problem, or a state-handoff problem\n3. add a targeted sub-step to this document or the issue list\n4. resume from the last verified checkpoint\n"
  },
  {
    "path": "expo-router-migration-issues.md",
    "content": "# Expo Router Migration Issues\n\nThis checklist breaks the migration into discrete issues that can be handled one by one.\n\nRecommended order:\n\n1. ER-01\n2. ER-02\n3. ER-03\n4. ER-04\n5. ER-05\n6. ER-06\n7. ER-07\n8. ER-08\n9. ER-09\n10. ER-10\n11. ER-11\n12. ER-12\n13. ER-13\n14. ER-14\n15. ER-15\n16. ER-16\n17. ER-17\n18. ER-18\n\n## ER-01: Add Expo Router entry and app config\n\n- [ ] Status: open\n\nWhy:\nThe app still boots through `index.ts` and `registerRootComponent`. Expo Router needs to own the entry point.\n\nFiles:\n`package.json`\n`index.ts`\n`app.json`\n\nCurrent problem:\n`package.json` uses `\"main\": \"index.ts\"`.\n`index.ts` imports shims and mounts `src/components/App`.\n`app.json` does not yet declare the Expo Router plugin, a `scheme`, or typed routes.\n\nSuggested fix:\nCreate a custom root entry file that preserves the current side effects:\n`src/shim`\n`message-port-polyfill`\nThen import `expo-router/entry` last.\nUpdate `package.json` to point `main` at that custom entry file.\nAdd the `expo-router` plugin to `app.json`.\nAdd an app `scheme`.\nEnable `experiments.typedRoutes`.\n\nDone when:\nThe app starts through Expo Router without losing the current polyfills.\n\n## ER-02: Move root bootstrap into `src/app/_layout.tsx`\n\n- [ ] Status: open\n\nWhy:\nThe current bootstrap logic lives in `src/components/App.tsx`, but Expo Router expects the root layout to be the top-level app shell.\n\nFiles:\n`src/components/App.tsx`\n`src/app/_layout.tsx`\n\nCurrent problem:\n`App.tsx` owns:\nprovider composition\nsplash screen coordination\ntheme wiring\nmanager initialization\nonboarding flag calculation\n\nSuggested fix:\nMove the root provider tree and initialization flow into `src/app/_layout.tsx`.\nKeep the current initialization order intact.\nRender a blank/loading placeholder until the manager is ready.\n\nDone when:\n`RootApp` and the old `App` shell are no longer responsible for navigation startup.\n\n## ER-03: Replace manual navigator files with file-based layouts\n\n- [ ] Status: open\n\nWhy:\nThe app currently depends on React Navigation stack files instead of file-based routes.\n\nFiles:\n`src/components/nav/Navigator.tsx`\n`src/nav/SettingsNavigator.tsx`\n`src/nav/MintNavigator.tsx`\n`src/nav/RestoreNavigator.tsx`\n`src/nav/HistoryNavigator.tsx`\n`src/app/**`\n\nCurrent problem:\nAll live routes are registered manually in stack components.\n\nSuggested fix:\nCreate the `src/app/**` route tree and corresponding `_layout.tsx` files.\nStart with thin route wrappers that re-export the current screens instead of moving screen files immediately.\nPreserve existing stack options in the new layouts.\n\nDone when:\nThe live route tree is represented in `src/app/**` and the old navigator files are unused.\n\n## ER-04: Recreate onboarding entry logic with router redirects\n\n- [ ] Status: open\n\nWhy:\nThe current initial route is chosen with `initialRouteName={shouldOnboard ? \"onboarding\" : \"dashboard\"}`.\n\nFiles:\n`src/components/nav/Navigator.tsx`\n`src/components/App.tsx`\n`src/screens/Onboarding.tsx`\n`src/app/index.tsx`\n\nCurrent problem:\nExpo Router does not use `initialRouteName` the same way for app startup.\n\nSuggested fix:\nUse `src/app/index.tsx` to redirect to `/onboarding` or `/dashboard` based on the existing `STORE_KEYS.explainer` check.\nUpdate onboarding completion to use `router.replace(\"/dashboard\")`.\n\nDone when:\nFresh installs land on onboarding and returning users land on dashboard.\n\n## ER-05: Replace `NavigationContainer` with router-compatible theme wiring\n\n- [ ] Status: open\n\nWhy:\nExpo Router manages the navigation container internally.\n\nFiles:\n`src/components/App.tsx`\n`src/styles/colors.ts`\n\nCurrent problem:\n`ThemedNavigationContainer` wraps the whole app in a manual `NavigationContainer`.\n\nSuggested fix:\nRemove the manual container.\nKeep the theme object only where still needed through Expo Router-compatible wiring.\nVerify there is no remaining dependency on `NavigationContainer` ownership.\n\nDone when:\nTheme behavior is preserved without a local `NavigationContainer`.\n\n## ER-06: Replace screen-prop navigation types with Router hooks\n\n- [ ] Status: open\n\nWhy:\nLarge parts of the app are typed against `RootStackParamList`, nested stack param lists, and `NativeStackScreenProps`.\n\nFiles:\n`src/model/nav.ts`\n`src/nav/navTypes.ts`\n`src/screens/**`\n`src/components/**`\n\nCurrent problem:\nRoute access is tightly coupled to React Navigation screen props.\n\nSuggested fix:\nConvert screens incrementally to:\n`useRouter()`\n`useLocalSearchParams()`\n`useNavigation()` only where low-level listeners are required\nDelete old param-list types as each area migrates.\n\nDone when:\nLive screens no longer require React Navigation screen prop injection.\n\n## ER-07: Audit custom deep-link intake alongside Expo Router\n\n- [ ] Status: open\n\nWhy:\nThe app already consumes incoming URLs for Cashu tokens and invoices through `Linking`, while Expo Router also uses deep linking.\n\nFiles:\n`src/context/Linking.tsx`\n`src/screens/Payment/Send/CoinSelection.tsx`\n`src/screens/Payment/Processing.tsx`\n`app.json`\n\nCurrent problem:\nThe app needs both:\nroute deep links for app navigation\nraw external URL intake for token/invoice handling\n\nSuggested fix:\nDecide which incoming URLs should be treated as Expo Router routes and which should be treated as raw payloads.\nPreserve the existing token/invoice capture behavior.\nVerify the chosen `scheme` does not break current payment flows.\n\nDone when:\nExpo Router deep linking and Cashu/LNURL intake can coexist predictably.\n\n## ER-08: Audit `beforeRemove` and focus-based navigation behavior\n\n- [ ] Status: open\n\nWhy:\nSeveral screens rely on navigation lifecycle hooks to block exits or restart focus-based behavior.\n\nFiles:\n`src/components/nav/utils.ts`\n`src/screens/Dashboard.tsx`\n`src/screens/Payment/Processing.tsx`\n`src/screens/Payment/ProcessingError.tsx`\n`src/screens/Payment/Success.tsx`\n`src/screens/Payment/SuccessScreen.tsx`\n`src/screens/Restore/Recovering.tsx`\n`src/screens/Payment/Receive/Invoice.tsx`\n`src/screens/QRScan/QrScannerScreen.tsx`\n`src/components/hooks/AnimatedQr.ts`\n\nCurrent problem:\nThe app depends on:\n`beforeRemove`\n`useFocusEffect`\nroute stack history inspection\n\nSuggested fix:\nKeep low-level navigation listeners only where they are still necessary.\nRe-test back behavior on dashboard, processing, success, and recovery flows.\nConfirm `useFocusEffect` still behaves correctly after migration.\n\nDone when:\nCritical flows still prevent accidental exits and focus-driven screens still reset correctly.\n\n## ER-09: Normalize route names and remove route inventory drift\n\n- [ ] Status: open\n\nWhy:\nThe current nav model includes live routes, stale routes, and mixed naming styles.\n\nFiles:\n`src/model/nav.ts`\n`src/nav/navTypes.ts`\n`src/components/nav/Navigator.tsx`\n`src/screens/Mints/components/MintItem.tsx`\n`src/components/Empty.tsx`\n`src/screens/Payment/Send/SelectMintToSwapTo.tsx`\n\nCurrent problem:\nThere is route drift between the type layer and the live navigator tree.\nExamples:\n`selectAmount`\n`selectMint`\n`selectTarget`\n`mintmanagement`\n`mint info`\n`mint proofs`\n`disclaimer`\n`Seed`\n`Mnemonic`\n`Advanced settings`\n`nostrReceive`\n`qr scan`\n\nSuggested fix:\nMake a definitive list of live routes.\nDelete stale route names and dead navigation code.\nNormalize live route names to lowercase kebab-case in Expo Router.\n\nDone when:\nThere is exactly one canonical route inventory.\n\n## ER-10: Make the Mint details route safe for Expo Router params\n\n- [ ] Status: open\n\nWhy:\nThe mint details screen is a good Router candidate, but its current param is a full `mintUrl`.\n\nFiles:\n`src/screens/Mints/MintHomeScreen.tsx`\n`src/screens/Mints/MintSettingsScreen.tsx`\n\nCurrent problem:\nA raw mint URL contains `://` and `/`, which is awkward as a path segment.\n\nSuggested fix:\nDo not use a plain `[mintUrl].tsx` segment with an unencoded URL.\nEither:\nuse a query param like `/mint/details?mintUrl=...`\nor encode/decode the value before routing.\n\nDone when:\nMint details routing works for any valid mint URL.\n\n## ER-11: Replace full `HistoryEntry` route params with a stable lookup key\n\n- [ ] Status: open\n\nWhy:\nHistory detail routing currently passes the entire history object through navigation.\n\nFiles:\n`src/screens/History/components/LatestHistoryWrapper.tsx`\n`src/screens/History/Details.tsx`\n`src/nav/navTypes.ts`\n\nCurrent problem:\n`HistoryEntryDetails` consumes `route.params.entry`, which is not Router-friendly.\n\nSuggested fix:\nIntroduce a stable history detail key.\nRoute to that key instead of passing the whole object.\nLook up the entry again from store, manager state, or a small session cache.\n\nDone when:\nHistory details can open without passing a full `HistoryEntry` through route params.\n\n## ER-12: Fix the recovery flow state handoff\n\n- [ ] Status: open\n\nWhy:\nThe recovery flow currently depends on non-serializable route state and also appears to drop the selected mint list.\n\nFiles:\n`src/screens/Restore/SelectRecoveryMint.tsx`\n`src/screens/Restore/Recover.tsx`\n`src/screens/Restore/Recovering.tsx`\n`src/nav/navTypes.ts`\n\nCurrent problem:\n`Recovering` expects `{ bip39seed: Uint8Array; mintUrls: string[] }`.\n`Recover` passes a `Uint8Array` through navigation.\n`SelectRecoveryMint` tracks `selectedMints` locally but does not forward them to `Recover`, and `Recover` later uses all known mints instead.\n\nSuggested fix:\nMove recovery state into a small ephemeral store or context.\nPersist the chosen mint URLs there.\nPersist the generated seed there as well.\nRoute to the next screen with a lightweight key or no payload at all.\n\nDone when:\nThe selected mint list is preserved and the recovery flow no longer depends on `Uint8Array` route params.\n\n## ER-13: Refactor the mint invoice flow to pass `operationId` instead of operation objects\n\n- [ ] Status: open\n\nWhy:\nThe receive flow passes a prepared mint operation object directly into the invoice screen.\n\nFiles:\n`src/screens/Payment/MintSelectAmount.tsx`\n`src/screens/Payment/Receive/Invoice.tsx`\n`src/model/nav.ts`\n\nCurrent problem:\n`MintSelectAmount` navigates with `{ mintUrl, operation }`.\n`Invoice` currently reads `operation.id`, `operation.amount`, and `operation.request` directly from route params.\n\nSuggested fix:\nAfter `manager.ops.mint.prepare(...)`, pass only `operationId` in navigation.\nUpdate `Invoice` to look up the operation by ID on the destination screen.\nUse that looked-up operation for:\ndisplaying the request QR\ndisplaying the amount\nmatching manager finalization events\n\nDone when:\nThe invoice route only carries `operationId`, and the destination screen resolves the operation from that ID.\n\n## ER-14: Refactor the melt confirmation flow to pass `operationId` instead of operation objects\n\n- [ ] Status: open\n\nWhy:\nThe LN payout flow currently passes prepared operations and metadata-rich payloads between screens.\n\nFiles:\n`src/screens/Payment/MeltInput.tsx`\n`src/screens/Payment/MeltLnAddress.tsx`\n`src/screens/Payment/MeltConfirmation.tsx`\n`src/model/nav.ts`\n\nCurrent problem:\n`MeltInput` and `MeltLnAddress` navigate with a prepared `operation` object.\n`MeltConfirmation` currently reads the full operation from route params.\n`MeltLnAddress` also passes metadata that should be reviewed separately.\n\nSuggested fix:\nAfter `manager.ops.melt.prepare(...)`, pass only `operationId` to `MeltConfirmation`.\nUpdate `MeltConfirmation` to look up the prepared operation by ID on the destination screen.\nUse the looked-up operation for:\ndisplaying amount and fee reserve\nexecuting the melt\nbuilding the success payload\nKeep metadata out of route params unless the destination screen truly needs it; if it does, prefer recomputing or separately serializing only the minimal fields needed.\n\nDone when:\nThe melt confirmation route only carries `operationId`, and the destination screen resolves the operation from that ID.\n\n## ER-15: Refactor the encoded token screen to stop passing `Token` objects in params\n\n- [ ] Status: open\n\nWhy:\nThe send flow currently passes a full Cashu `Token` object into the token display screen.\n\nFiles:\n`src/screens/Payment/SendSelectAmount.tsx`\n`src/screens/Payment/Send/EncodedToken.tsx`\n`src/model/nav.ts`\n\nCurrent problem:\n`SendSelectAmount` navigates with `{ token }`.\n\nSuggested fix:\nStore the generated token in ephemeral flow state.\nNavigate with a simple key.\nLoad the token again in `EncodedToken` from that key.\n\nDone when:\nThe encoded token route only requires a serializable identifier.\n\n## ER-16: Refactor the coin selection and processing flows to stop passing rich domain objects\n\n- [ ] Status: open\n\nWhy:\nThese routes currently pass domain objects that are not a good fit for Router params.\n\nFiles:\n`src/screens/Payment/Send/CoinSelection.tsx`\n`src/screens/Payment/Processing.tsx`\n`src/model/nav.ts`\n`src/screens/Payment/Send/SelectMintToSwapTo.tsx`\n\nCurrent problem:\nThe active param types include values like:\n`IMintUrl`\n`ITokenInfo`\n`IProofSelection[]`\n`targetMint`\n`remainingMints`\n\nSuggested fix:\nIntroduce a payment flow store keyed by flow ID.\nRoute between coin selection and processing using that ID.\nOnly keep small flags or IDs in the URL layer.\n\nDone when:\nThe payment pipeline no longer depends on rich domain objects in route params.\n\n## ER-17: Simplify `processingError` route params\n\n- [ ] Status: open\n\nWhy:\nThe error route is close to safe already, but its type model still includes more context than it should.\n\nFiles:\n`src/model/nav.ts`\n`src/screens/Payment/Processing.tsx`\n`src/screens/Payment/ProcessingError.tsx`\n\nCurrent problem:\n`processingError` still allows `mint?: IMintUrl` in the param model even though the screen mainly needs `errorMsg` and a little display context.\n\nSuggested fix:\nReduce the route payload to the minimum the screen really needs.\nPrefer simple primitives like:\n`errorMsg`\n`scan`\n`source`\n\nDone when:\nThe error route only carries simple UI state.\n\n## ER-18: Consolidate the duplicate success screens\n\n- [ ] Status: open\n\nWhy:\nThe app currently has both `success` and `successScreen`, with overlapping responsibilities.\n\nFiles:\n`src/components/nav/Navigator.tsx`\n`src/screens/Payment/Success.tsx`\n`src/screens/Payment/SuccessScreen.tsx`\ncallers in payment and scanner flows\n\nCurrent problem:\nTwo different success routes increase migration complexity and keep two param models alive.\n\nSuggested fix:\nChoose one canonical success route.\nMove all callers to it.\nDelete the other screen and its route type.\n\nDone when:\nThere is exactly one success screen and one success param model.\n\n## ER-19: Rewrite nested-stack route callers to direct Router paths\n\n- [ ] Status: open\n\nWhy:\nSeveral screens currently navigate into nested stacks by parent route name plus `{ screen: ... }` params.\n\nFiles:\n`src/screens/Dashboard.tsx`\n`src/screens/Settings/index.tsx`\n`src/components/Balance.tsx`\n`src/screens/History/components/LatestHistoryWrapper.tsx`\n`src/screens/Mints/MintHomeScreen.tsx`\n\nCurrent problem:\nCurrent calls include patterns like:\n`navigation.navigate(\"Settings\", { screen: \"SettingsMain\" })`\n`navigation.navigate(\"Mint\", { screen: \"MintHome\" })`\n`navigation.navigate(\"History\", { screen: \"HistoryEntryDetails\", params: ... })`\n\nSuggested fix:\nReplace each nested navigator jump with a direct route path.\nExamples:\n`/settings`\n`/mint`\n`/history`\n\nDone when:\nNo screen depends on nested-stack `{ screen: ... }` navigation patterns.\n\n## ER-20: Resolve dead or unreachable payment and mint routes before migration cleanup\n\n- [ ] Status: open\n\nWhy:\nSome screens and route types appear to reference routes that are not part of the live navigator tree.\n\nFiles:\n`src/model/nav.ts`\n`src/screens/Mints/components/MintItem.tsx`\n`src/screens/Payment/Send/SelectMintToSwapTo.tsx`\n`src/components/Empty.tsx`\n\nCurrent problem:\nExamples:\n`MintItem` navigates to `mintmanagement`\n`SelectMintToSwapTo` navigates to `selectAmount`\n`Empty` references `nostrReceive` and `qr scan`\n\nSuggested fix:\nConfirm which of these routes are dead code versus partially migrated code.\nDelete dead paths.\nRe-point any still-needed flows to live routes.\n\nDone when:\nThere are no remaining references to routes that do not exist in the live app.\n\n## ER-21: Remove the old nav type layer after migration\n\n- [ ] Status: open\n\nWhy:\nThe old nav model will become a maintenance trap once Expo Router is in place.\n\nFiles:\n`src/model/nav.ts`\n`src/nav/navTypes.ts`\nall imports from those files\n\nCurrent problem:\nMany screens and components import route prop types from the old stack model.\n\nSuggested fix:\nDelete these files only after all live screens have been converted.\nReplace them with local interfaces and Router-based param access.\n\nDone when:\n`src/model/nav.ts` and `src/nav/navTypes.ts` are gone or reduced to non-navigation domain types only.\n\n## ER-22: Delete the manual navigation layer and related helpers\n\n- [ ] Status: open\n\nWhy:\nOnce the Router migration is complete, the manual stack layer should disappear entirely.\n\nFiles:\n`src/components/nav/Navigator.tsx`\n`src/nav/SettingsNavigator.tsx`\n`src/nav/MintNavigator.tsx`\n`src/nav/RestoreNavigator.tsx`\n`src/nav/HistoryNavigator.tsx`\n`src/components/nav/utils.ts`\n\nCurrent problem:\nThe migration is not complete until the old nav layer is actually removed.\n\nSuggested fix:\nDelete the old navigator files and any helper code that only exists to support them.\nRetain only the minimal low-level navigation code still required by Expo Router.\n\nDone when:\nThe app navigates entirely through `src/app/**` and no manual navigator files remain.\n"
  },
  {
    "path": "expo-router-migration-plan.md",
    "content": "# Expo Router Migration Plan\n\n## Goal\n\nMigrate the app from manual React Navigation stacks to Expo Router with the smallest safe refactor first, then clean up the flows that currently depend on non-serializable navigation params.\n\n## Target Route Tree\n\n```text\nsrc/app/\n  _layout.tsx\n  index.tsx\n  onboarding.tsx\n  dashboard.tsx\n  qr-scanner.tsx\n\n  settings/\n    _layout.tsx\n    index.tsx\n    display.tsx\n    language.tsx\n    currency.tsx\n    nfc.tsx\n    view-mnemonic.tsx\n\n  mint/\n    _layout.tsx\n    index.tsx\n    add.tsx\n    [mintUrl].tsx\n\n  history/\n    _layout.tsx\n    index.tsx\n    [entryId].tsx\n\n  restore/\n    _layout.tsx\n    index.tsx\n    recover.tsx\n    recovering.tsx\n\n  payment/\n    _layout.tsx\n    send-select-amount.tsx\n    mint-select-amount.tsx\n    melt-input.tsx\n    melt-ln-address.tsx\n    melt-confirmation.tsx\n    processing.tsx\n    processing-error.tsx\n    mint-invoice.tsx\n    encoded-token.tsx\n    success.tsx\n    success-screen.tsx\n    select-mint-to-swap-to.tsx\n    coin-selection.tsx\n```\n\nNotes:\n\n- `index.tsx` should choose between onboarding and dashboard.\n- Nested stacks map naturally to folder `_layout.tsx` files.\n- Route names should be normalized to lowercase kebab-case.\n\n## Phase 1: Router Scaffolding\n\n1. Add Expo Router dependency and config.\n2. Change entry from `index.ts` / `src/components/App.tsx` to Expo Router entry.\n3. Add the `expo-router` plugin to `app.json`.\n4. Create `src/app/_layout.tsx`.\n5. Move root providers and app initialization from `src/components/App.tsx` into the root layout.\n6. Replace `NavigationContainer` usage with Router-managed navigation plus React Navigation `ThemeProvider`.\n\nExpected output:\n\n- The app boots through Expo Router.\n- No screen behavior changes yet beyond the routing shell.\n\n## Phase 2: Mechanical Route Migration\n\n1. Replace `Navigator.tsx` and nested stack components with folder layouts.\n2. Re-export or move existing screens into `src/app/**`.\n3. Preserve screen options in layout files:\n   - `headerShown: false`\n   - `animation`\n   - `gestureEnabled`\n   - `navigationBarColor`\n4. Preserve onboarding entry behavior with redirect logic in `src/app/index.tsx`.\n\nExpected output:\n\n- Existing screens are reachable through file-based routes.\n- Root and nested stacks behave roughly the same.\n\n## Phase 3: Navigation API Migration\n\n1. Replace screen props `{ navigation, route }` with Expo Router hooks where possible.\n2. Migrate imperative calls:\n   - `navigation.navigate(...)` to `router.navigate(...)` or `router.push(...)`\n   - `navigation.replace(...)` to `router.replace(...)`\n   - `navigation.goBack()` to `router.back()`\n3. For screens that still need low-level navigation events, keep `useNavigation()` from Expo Router.\n\nExpected output:\n\n- Screens stop depending on React Navigation screen prop injection.\n- Route typing starts shifting away from `RootStackParamList`.\n\n## Phase 4: Param Refactor Hotspots\n\nThis is the main migration risk.\n\nExpo Router works best when route params are simple serializable values. The current app passes rich in-memory objects between screens.\n\n### Current high-risk flows\n\n- `MintSelectAmount -> mintInvoice` passes `operation`\n- `MeltInput` / `MeltLnAddress -> MeltConfirmation` passes `operation` and metadata objects\n- `SendSelectAmount -> encodedToken` passes a token object\n- `Recover -> Recovering` passes `Uint8Array`\n- `History list -> details` passes a full `HistoryEntry`\n\n### Recommended refactor pattern\n\n- `history/[entryId].tsx`\n  Use a stable ID or re-query from store/context instead of passing the full `entry` object.\n- `mint/[mintUrl].tsx`\n  Keep this string-param based route; it already fits Expo Router well.\n- `restore/recovering.tsx`\n  Do not pass `Uint8Array` in route params. Persist temporary recovery input in context, store, or an ephemeral session map.\n- `payment/mint-invoice.tsx`\n  Do not pass prepared operation objects through the route. Either prepare on the destination screen or save the prepared operation in ephemeral state keyed by an ID.\n- `payment/melt-confirmation.tsx`\n  Same as above.\n- `payment/encoded-token.tsx`\n  Prefer storing the generated token in ephemeral state and navigating by an ID.\n\nExpected output:\n\n- Routes only use simple params like strings, numbers, and booleans.\n- Flow screens become Router-compatible and more deep-link-safe.\n\n## Phase 5: Type Migration\n\n1. Remove dependence on `src/model/nav.ts` and `src/nav/navTypes.ts`.\n2. Replace screen prop types with:\n   - `useLocalSearchParams`\n   - Router typed hrefs\n   - local prop interfaces for non-route props\n3. Keep a small temporary compatibility layer only if needed during migration, then delete it.\n\nExpected output:\n\n- Navigation typing becomes route-string based instead of stack-param-list based.\n- Dead route names disappear.\n\n## Phase 6: Back-Blocking And Flow Guards\n\nThe current app uses `beforeRemove` listeners in a few screens to block accidental exits, including:\n\n- dashboard\n- processing\n- success\n- recovering\n\nPlan:\n\n1. Audit each `beforeRemove` usage.\n2. Keep low-level `useNavigation().addListener(\"beforeRemove\", ...)` where still needed.\n3. Replace with simpler route structure or redirect logic where possible.\n\nExpected output:\n\n- No regression in protected or critical flows.\n- Back behavior stays intentional.\n\n## Phase 7: Cleanup\n\n1. Delete:\n   - `src/components/nav/Navigator.tsx`\n   - `src/nav/SettingsNavigator.tsx`\n   - `src/nav/MintNavigator.tsx`\n   - `src/nav/RestoreNavigator.tsx`\n   - `src/nav/HistoryNavigator.tsx`\n2. Remove unused React Navigation types and imports.\n3. Remove stale route names from `src/model/nav.ts` and `src/components/Empty.tsx`.\n4. Normalize route naming.\n\n## Risk List\n\n### Highest risk\n\n- Passing non-serializable objects in params\n- Recovery flow using `Uint8Array`\n- Operation-preparation flows that assume in-memory handoff between screens\n\n### Medium risk\n\n- `beforeRemove` behavior changes\n- onboarding redirect logic\n- theme/provider bootstrapping during root layout migration\n\n### Low risk\n\n- nested stack structure\n- settings, mint, history, and restore route mapping\n- mint details route keyed by `mintUrl`\n\n## Decisions To Make Early\n\n1. Choose a temporary state strategy for flow objects:\n   - context\n   - store\n   - small in-memory session map\n2. Decide whether to physically move screen files into `src/app` or keep screens in `src/screens` and create thin route wrappers.\n3. Decide whether to do a compatibility-first migration or a cleanup-first migration.\n\nRecommendation:\n\n1. Use thin `src/app/**` wrappers first.\n2. Use a small ephemeral flow-state store for non-serializable objects.\n3. Convert high-risk flows one by one after the router shell is live.\n\n## Recommended Execution Order\n\n1. Router install, config, and root layout.\n2. File-based stacks for dashboard, settings, mint, history, and restore.\n3. Simple string-param routes first.\n4. History details refactor.\n5. Recovery flow refactor.\n6. Mint and melt operation flow refactors.\n7. Success, processing, and back-blocking audit.\n8. Delete the old nav layer and old nav types.\n\n## Definition Of Done\n\n- App boots via Expo Router.\n- Onboarding and dashboard entry works.\n- All current screens are reachable.\n- No route depends on non-serializable params.\n- No remaining imports from old navigator files.\n- Critical back-blocked flows still behave correctly.\n\n## Next Step\n\nTurn this into a route-by-route issue list, starting with the non-serializable param flows.\n"
  },
  {
    "path": "index.ts",
    "content": "// Import shim first to set up crypto polyfill before any other modules\nimport \"./src/shim\";\n//TODO: Find a workaround for this polyfill. Maybe we should use NDK instead.\nimport \"message-port-polyfill\";\n\nimport { registerRootComponent } from \"expo\";\n\nimport App from \"./src/components/App\";\n\nregisterRootComponent(App);\n"
  },
  {
    "path": "package.json",
    "content": "{\n  \"name\": \"enuts\",\n  \"version\": \"1.0.0\",\n  \"main\": \"index.ts\",\n  \"scripts\": {\n    \"start\": \"expo start\",\n    \"android\": \"expo run:android\",\n    \"ios\": \"expo run:ios\",\n    \"format\": \"prettier --write .\"\n  },\n  \"dependencies\": {\n    \"@cashu/cashu-ts\": \"^3.6.4\",\n    \"@cashu/coco-core\": \"^1.0.0-rc.2\",\n    \"@cashu/coco-expo-sqlite\": \"^1.0.0-rc.2\",\n    \"@cashu/coco-react\": \"^1.0.0-rc.2\",\n    \"@expo/vector-icons\": \"^15.0.3\",\n    \"@gandlaf21/bc-ur\": \"^1.1.12\",\n    \"@lodev09/react-native-true-sheet\": \"^3.10.1\",\n    \"@react-navigation/native\": \"^7.1.14\",\n    \"@react-navigation/native-stack\": \"^7.3.21\",\n    \"@scure/bip39\": \"^2.0.0\",\n    \"@shopify/flash-list\": \"2.0.2\",\n    \"@tanstack/react-query\": \"^5.83.0\",\n    \"@types/react-native-onboarding-swiper\": \"^1.1.9\",\n    \"bech32\": \"^2.0.0\",\n    \"cashu-kym\": \"^0.4.1\",\n    \"coco-cashu-plugin-npc\": \"^3.0.0-rc.20260430.1.1.sha.211bc4c\",\n    \"crypto-js\": \"^4.2.0\",\n    \"expo\": \"~54.0.25\",\n    \"expo-application\": \"~7.0.7\",\n    \"expo-camera\": \"~17.0.9\",\n    \"expo-clipboard\": \"~8.0.7\",\n    \"expo-crypto\": \"~15.0.7\",\n    \"expo-dev-client\": \"~6.0.18\",\n    \"expo-drizzle-studio-plugin\": \"^0.2.1\",\n    \"expo-file-system\": \"~19.0.19\",\n    \"expo-image\": \"~3.0.10\",\n    \"expo-localization\": \"~17.0.7\",\n    \"expo-secure-store\": \"~15.0.7\",\n    \"expo-splash-screen\": \"~31.0.11\",\n    \"expo-sqlite\": \"~16.0.9\",\n    \"expo-status-bar\": \"~3.0.8\",\n    \"lottie-react-native\": \"~7.3.1\",\n    \"message-port-polyfill\": \"^0.2.0\",\n    \"nostr-tools\": \"^2.17.0\",\n    \"react\": \"19.1.0\",\n    \"react-i18next\": \"^15.6.0\",\n    \"react-native\": \"0.81.5\",\n    \"react-native-gesture-handler\": \"~2.28.0\",\n    \"react-native-keyboard-controller\": \"1.18.5\",\n    \"react-native-nfc-manager\": \"^4.0.0-beta.6\",\n    \"react-native-onboarding-swiper\": \"^1.3.0\",\n    \"react-native-popup-menu\": \"^0.18.0\",\n    \"react-native-qrcode-svg\": \"^6.3.15\",\n    \"react-native-reanimated\": \"^4.1.5\",\n    \"react-native-safe-area-context\": \"~5.6.0\",\n    \"react-native-screens\": \"~4.16.0\",\n    \"react-native-size-matters\": \"^0.4.2\",\n    \"react-native-svg\": \"15.12.1\",\n    \"react-native-worklets\": \"0.5.1\"\n  },\n  \"devDependencies\": {\n    \"@babel/core\": \"^7.25.2\",\n    \"@types/react\": \"~19.1.10\",\n    \"expo-mcp\": \"~0.2.1\",\n    \"prettier\": \"^3.7.4\",\n    \"typescript\": \"~5.9.2\"\n  },\n  \"private\": true\n}\n"
  },
  {
    "path": "src/components/ActionButtons.tsx",
    "content": "import { View } from \"react-native\";\nimport { useSafeAreaInsets } from \"react-native-safe-area-context\";\nimport { s, ScaledSheet } from \"react-native-size-matters\";\n\nimport Button from \"./Button\";\n\ninterface IActionBtnsProps {\n  topBtnTxt: string;\n  topBtnAction: () => void;\n  bottomBtnTxt: string;\n  bottomBtnAction: () => void;\n  ontopOfNav?: boolean;\n  absolutePos?: boolean;\n  loading?: boolean;\n  topIcon?: React.ReactNode;\n  bottomIcon?: React.ReactNode;\n}\n\nexport default function ActionButtons({\n  topBtnTxt,\n  topBtnAction,\n  bottomBtnTxt,\n  bottomBtnAction,\n  ontopOfNav,\n  absolutePos,\n  loading,\n  topIcon,\n  bottomIcon,\n}: IActionBtnsProps) {\n  const insets = useSafeAreaInsets();\n  return (\n    <View\n      style={[\n        styles.actionWrap,\n        ontopOfNav ? styles.ontopOfNav : {},\n        absolutePos\n          ? { position: \"absolute\", right: 0, left: 0, padding: s(20), bottom: insets.bottom }\n          : {},\n      ]}\n    >\n      <Button loading={loading} txt={topBtnTxt} onPress={topBtnAction} icon={topIcon} />\n      <View style={{ marginVertical: s(10) }} />\n      <Button txt={bottomBtnTxt} outlined onPress={bottomBtnAction} icon={bottomIcon} />\n    </View>\n  );\n}\n\nconst styles = ScaledSheet.create({\n  actionWrap: {\n    width: \"100%\",\n    alignItems: \"center\",\n  },\n  ontopOfNav: {\n    paddingLeft: \"20@s\",\n    paddingRight: \"20@s\",\n    marginBottom: \"60@s\",\n  },\n});\n"
  },
  {
    "path": "src/components/AmountInput.tsx",
    "content": "import { useShakeAnimation } from \"@comps/animation/Shake\";\nimport Txt from \"@comps/Txt\";\nimport { useThemeContext } from \"@src/context/Theme\";\nimport { useCurrencyContext } from \"@src/context/Currency\";\nimport { globals, highlight as hi, mainColors } from \"@styles\";\nimport { formatSatStr } from \"@util\";\nimport { getLanguageCode } from \"@util/localization\";\nimport { useEffect, useMemo, useRef, forwardRef, useState, useCallback } from \"react\";\nimport { Animated, TextInput, View, Pressable } from \"react-native\";\nimport { ScaledSheet } from \"react-native-size-matters\";\nimport { SwapCurrencyIcon } from \"@comps/Icons\";\n\ninterface AmountInputProps {\n  value: string;\n  onChange: (value: string) => void;\n  onSubmit?: () => void;\n  error?: boolean;\n  placeholder?: string;\n  maxLength?: number;\n  autoFocus?: boolean;\n  testID?: string;\n  compact?: boolean;\n}\n\n/**\n * Detect the decimal separator for the current locale\n */\nfunction getLocalDecimalSeparator(): string {\n  const lang = getLanguageCode();\n  const formatted = new Intl.NumberFormat(lang).format(1.1);\n  // The decimal separator is the character between 1 and 1\n  return formatted.charAt(1);\n}\n\n/**\n * Normalize a numeric string to use period as decimal separator\n * Handles both EU (comma) and US (period) formats intelligently\n */\nfunction normalizeDecimalInput(input: string): string {\n  // Remove all whitespace\n  let text = input.replace(/\\s/g, \"\");\n\n  // If empty, return empty\n  if (!text) return \"\";\n\n  // Count separators\n  const commas = (text.match(/,/g) || []).length;\n  const periods = (text.match(/\\./g) || []).length;\n\n  // Case: Both separators present - last one is the decimal\n  if (commas > 0 && periods > 0) {\n    const lastComma = text.lastIndexOf(\",\");\n    const lastPeriod = text.lastIndexOf(\".\");\n\n    if (lastComma > lastPeriod) {\n      // EU format: 1.000,50 -> 1000.50\n      text = text.replace(/\\./g, \"\").replace(\",\", \".\");\n    } else {\n      // US format: 1,000.50 -> 1000.50\n      text = text.replace(/,/g, \"\");\n    }\n  }\n  // Case: Single comma, no periods - treat as decimal\n  else if (commas === 1 && periods === 0) {\n    text = text.replace(\",\", \".\");\n  }\n  // Case: Multiple commas, no periods - thousand separators\n  else if (commas > 1) {\n    text = text.replace(/,/g, \"\");\n  }\n  // Case: Multiple periods - first ones are thousand separators, last is decimal\n  else if (periods > 1) {\n    const lastPeriodIdx = text.lastIndexOf(\".\");\n    text = text.slice(0, lastPeriodIdx).replace(/\\./g, \"\") + text.slice(lastPeriodIdx);\n  }\n  // Single period or no separators - already normalized\n\n  return text;\n}\n\n/**\n * Format a number for display using the user's locale\n */\nfunction formatFiatDisplay(value: number, decimals: number = 2): string {\n  const lang = getLanguageCode();\n  return value.toLocaleString(lang, {\n    minimumFractionDigits: 0,\n    maximumFractionDigits: decimals,\n    useGrouping: false, // Don't add thousand separators in input\n  });\n}\n\nconst AmountInput = forwardRef<TextInput, AmountInputProps>(\n  (\n    {\n      value,\n      onChange,\n      onSubmit,\n      error = false,\n      placeholder = \"0\",\n      maxLength = 8,\n      autoFocus = true,\n      testID = \"amount-input\",\n      compact = false,\n    },\n    ref,\n  ) => {\n    const { color, highlight } = useThemeContext();\n    const { formatBalance, setFormatBalance, convertFiatToSats, rates, selectedCurrency } =\n      useCurrencyContext();\n    const { anim } = useShakeAnimation();\n    const internalRef = useRef<TextInput>(null);\n\n    // Use the forwarded ref or fall back to internal ref\n    const inputRef = (ref as React.RefObject<TextInput>) || internalRef;\n\n    // Check if we're in fiat mode\n    const isFiatMode = formatBalance && rates && rates[selectedCurrency];\n\n    // Check if currency toggle is available (rates must be loaded)\n    const canToggleCurrency = rates && rates[selectedCurrency];\n\n    // Handle toggling between sats and fiat modes\n    const handleToggleCurrency = useCallback(() => {\n      if (!canToggleCurrency) return;\n      void setFormatBalance(!formatBalance);\n    }, [canToggleCurrency, formatBalance, setFormatBalance]);\n\n    // Store the displayed text independently to avoid cursor jumping\n    // This is the raw text shown in the input field\n    const [displayText, setDisplayText] = useState(\"\");\n\n    // Track if we need to sync display from external value change\n    const lastExternalValue = useRef<string>(\"\");\n\n    // Memoize style objects to prevent recreation\n    const globalStyles = useMemo(() => globals(), []);\n\n    // Get the locale decimal separator for this user\n    const localDecimalSep = useMemo(() => getLocalDecimalSeparator(), []);\n\n    // Derived numeric amount in sats (value prop is always in sats)\n    const amountInSats = useMemo(() => {\n      const parsed = parseInt(value || \"0\", 10);\n      return Number.isNaN(parsed) ? 0 : parsed;\n    }, [value]);\n\n    // Sync display text when external value changes (e.g., from parent reset)\n    // But only if it wasn't caused by our own onChange\n    useEffect(() => {\n      // Skip if value hasn't changed from what we set\n      if (value === lastExternalValue.current) {\n        return;\n      }\n\n      // External value changed - need to update display\n      if (!value || value === \"0\") {\n        setDisplayText(\"\");\n        lastExternalValue.current = value;\n        return;\n      }\n\n      // For sats mode, just show the value\n      if (!isFiatMode) {\n        setDisplayText(value);\n        lastExternalValue.current = value;\n        return;\n      }\n\n      // For fiat mode, convert sats to fiat for display\n      const rate = rates?.[selectedCurrency];\n      if (rate) {\n        const sats = parseInt(value, 10);\n        if (!isNaN(sats) && sats > 0) {\n          const btcAmount = sats / 100_000_000;\n          const fiatAmount = btcAmount * rate.last;\n          // Format with locale-appropriate decimal separator\n          const formatted = formatFiatDisplay(fiatAmount);\n          setDisplayText(formatted);\n        }\n      }\n      lastExternalValue.current = value;\n    }, [value, isFiatMode, rates, selectedCurrency]);\n\n    // Handle mode switches - reset display when switching between sats/fiat\n    const prevFiatMode = useRef(isFiatMode);\n    useEffect(() => {\n      if (prevFiatMode.current !== isFiatMode) {\n        // Mode changed - reset display text\n        if (!value || value === \"0\") {\n          setDisplayText(\"\");\n        } else if (!isFiatMode) {\n          // Switched to sats mode - show sats value\n          setDisplayText(value);\n        } else {\n          // Switched to fiat mode - convert sats to fiat\n          const rate = rates?.[selectedCurrency];\n          if (rate) {\n            const sats = parseInt(value, 10);\n            if (!isNaN(sats) && sats > 0) {\n              const btcAmount = sats / 100_000_000;\n              const fiatAmount = btcAmount * rate.last;\n              setDisplayText(formatFiatDisplay(fiatAmount));\n            }\n          }\n        }\n        prevFiatMode.current = isFiatMode;\n      }\n    }, [isFiatMode, value, rates, selectedCurrency]);\n\n    // Handle user input changes\n    const handleAmountChange = useCallback(\n      (text: string) => {\n        // Handle empty input\n        if (!text) {\n          setDisplayText(\"\");\n          lastExternalValue.current = \"0\";\n          onChange(\"0\");\n          return;\n        }\n\n        if (isFiatMode) {\n          // Fiat mode: allow decimals\n\n          // Only allow digits, commas, and periods\n          let cleaned = text.replace(/[^\\d.,]/g, \"\");\n\n          // Handle leading decimal separator\n          if (cleaned.startsWith(\".\") || cleaned.startsWith(\",\")) {\n            cleaned = \"0\" + cleaned;\n          }\n\n          // Prevent multiple decimal separators of the same type\n          // But allow typing either . or , as the decimal separator\n          const normalized = normalizeDecimalInput(cleaned);\n\n          // Check if the input is valid\n          const parts = normalized.split(\".\");\n          if (parts.length > 2) {\n            // Invalid: multiple decimal points after normalization\n            return;\n          }\n\n          // Limit decimal places to 2\n          if (parts.length === 2 && parts[1].length > 2) {\n            const truncatedDecimals = parts[1].substring(0, 2);\n            // Reconstruct the display text with user's separator\n            const userDecimalSep =\n              text.includes(\",\") && !text.includes(\".\") ? \",\" : localDecimalSep;\n            cleaned = parts[0] + userDecimalSep + truncatedDecimals;\n          }\n\n          // Update display immediately (no lag)\n          setDisplayText(cleaned);\n\n          // Convert to sats and notify parent\n          const fiatValue = parseFloat(normalized || \"0\");\n          if (!isNaN(fiatValue) && fiatValue >= 0) {\n            const sats = convertFiatToSats(fiatValue);\n            const satsStr = sats.toString();\n            lastExternalValue.current = satsStr;\n            onChange(satsStr);\n          } else {\n            lastExternalValue.current = \"0\";\n            onChange(\"0\");\n          }\n        } else {\n          // Sats mode: integers only\n          const cleaned = text.replace(/\\D/g, \"\");\n          // Remove leading zeros except for single \"0\"\n          const sanitized = cleaned.replace(/^0+/, \"\") || \"0\";\n\n          setDisplayText(sanitized === \"0\" ? \"\" : sanitized);\n          lastExternalValue.current = sanitized;\n          onChange(sanitized);\n        }\n      },\n      [isFiatMode, convertFiatToSats, onChange, localDecimalSep],\n    );\n\n    // Auto-focus keyboard if requested\n    useEffect(() => {\n      if (autoFocus) {\n        const t = setTimeout(() => {\n          inputRef.current?.focus();\n          clearTimeout(t);\n        }, 200);\n      }\n      // eslint-disable-next-line react-hooks/exhaustive-deps\n    }, []);\n\n    // Currency symbol for fiat mode\n    const currencySymbol = useMemo(() => {\n      if (isFiatMode && rates?.[selectedCurrency]) {\n        return rates[selectedCurrency].symbol || selectedCurrency;\n      }\n      return \"\";\n    }, [isFiatMode, rates, selectedCurrency]);\n\n    // Secondary label showing sats equivalent in fiat mode\n    const secondaryLabel = useMemo(() => {\n      if (!isFiatMode || amountInSats === 0) {\n        return \"\";\n      }\n      return formatSatStr(amountInSats, \"standard\", true);\n    }, [isFiatMode, amountInSats]);\n\n    // Keyboard type\n    const keyboardType = useMemo(() => (isFiatMode ? \"decimal-pad\" : \"numeric\"), [isFiatMode]);\n\n    // Max length - allow more for fiat to accommodate decimals\n    const effectiveMaxLength = useMemo(\n      () => (isFiatMode ? 12 : maxLength),\n      [isFiatMode, maxLength],\n    );\n\n    // Placeholder - show appropriate for mode\n    const displayPlaceholder = useMemo(() => {\n      if (isFiatMode) {\n        return `0${localDecimalSep}00`;\n      }\n      return placeholder;\n    }, [isFiatMode, placeholder, localDecimalSep]);\n\n    return (\n      <View style={[styles.container, compact ? styles.containerCompact : null]}>\n        <View style={styles.inputRow}>\n          {/* Currency symbol prefix for fiat */}\n          {currencySymbol && (\n            <Txt\n              txt={currencySymbol}\n              styles={[\n                compact ? styles.currencySymbolCompact : styles.currencySymbol,\n                {\n                  color: error ? mainColors.ERROR : hi[highlight],\n                },\n              ]}\n            />\n          )}\n          <Animated.View style={[styles.amountWrap, { transform: [{ translateX: anim.current }] }]}>\n            <TextInput\n              keyboardType={keyboardType}\n              ref={inputRef}\n              placeholder={displayPlaceholder}\n              autoFocus={autoFocus}\n              cursorColor={hi[highlight]}\n              placeholderTextColor={error ? mainColors.ERROR : hi[highlight]}\n              style={[\n                globalStyles.selectAmount,\n                compact ? styles.amountInputCompact : null,\n                { color: error ? mainColors.ERROR : hi[highlight] },\n              ]}\n              onChangeText={handleAmountChange}\n              onSubmitEditing={onSubmit}\n              value={displayText}\n              maxLength={effectiveMaxLength}\n              testID={testID}\n              autoCorrect={false}\n              autoCapitalize=\"none\"\n              spellCheck={false}\n              allowFontScaling={false}\n            />\n          </Animated.View>\n          {/* Show \"Sats\" suffix when not in fiat mode */}\n          {!isFiatMode && displayText && (\n            <Txt\n              txt=\"Sats\"\n              styles={[\n                compact ? styles.satsSuffixCompact : styles.satsSuffix,\n                {\n                  color: error ? mainColors.ERROR : hi[highlight],\n                },\n              ]}\n            />\n          )}\n          {/* Currency toggle button */}\n          {canToggleCurrency && (\n            <Pressable\n              onPress={handleToggleCurrency}\n              style={({ pressed }) => [\n                styles.toggleButton,\n                {\n                  backgroundColor: pressed ? color.INPUT_BG : \"transparent\",\n                },\n              ]}\n              hitSlop={{ top: 10, bottom: 10, left: 10, right: 10 }}\n              accessibilityLabel=\"Toggle currency\"\n              accessibilityHint=\"Switch between sats and fiat currency\"\n            >\n              <SwapCurrencyIcon width={20} height={20} color={hi[highlight]} />\n            </Pressable>\n          )}\n        </View>\n        {secondaryLabel && (\n          <Pressable onPress={handleToggleCurrency} disabled={!canToggleCurrency}>\n            <Txt\n              txt={secondaryLabel}\n              styles={[\n                compact ? styles.secondaryLabelCompact : styles.secondaryLabel,\n                { color: color.TEXT_SECONDARY },\n              ]}\n            />\n          </Pressable>\n        )}\n      </View>\n    );\n  },\n);\n\nAmountInput.displayName = \"AmountInput\";\n\nexport default AmountInput;\n\n// Export the shake function for parent components to use\nexport { useShakeAnimation };\n\nconst styles = ScaledSheet.create({\n  container: {\n    width: \"100%\",\n    alignItems: \"center\",\n    paddingVertical: \"20@vs\",\n  },\n  containerCompact: {\n    paddingVertical: \"8@vs\",\n  },\n  inputRow: {\n    flexDirection: \"row\",\n    alignItems: \"center\",\n    justifyContent: \"center\",\n  },\n  amountWrap: {\n    alignItems: \"center\",\n  },\n  currencySymbol: {\n    fontSize: \"32@s\",\n    fontWeight: \"600\",\n    marginRight: \"4@s\",\n  },\n  currencySymbolCompact: {\n    fontSize: \"24@s\",\n    fontWeight: \"600\",\n    marginRight: \"4@s\",\n  },\n  amountInputCompact: {\n    fontSize: \"36@vs\",\n    marginBottom: 0,\n  },\n  satsSuffix: {\n    fontSize: \"24@s\",\n    fontWeight: \"500\",\n    marginLeft: \"8@s\",\n    opacity: 0.8,\n  },\n  satsSuffixCompact: {\n    fontSize: \"18@s\",\n    fontWeight: \"500\",\n    marginLeft: \"6@s\",\n    opacity: 0.8,\n  },\n  toggleButton: {\n    marginLeft: \"12@s\",\n    padding: \"8@s\",\n    borderRadius: \"20@s\",\n  },\n  secondaryLabel: {\n    fontSize: \"14@vs\",\n    textAlign: \"center\",\n    marginTop: \"8@vs\",\n  },\n  secondaryLabelCompact: {\n    fontSize: \"12@vs\",\n    textAlign: \"center\",\n    marginTop: \"4@vs\",\n  },\n});\n"
  },
  {
    "path": "src/components/AnimatedSpinner.tsx",
    "content": "import { useEffect } from \"react\";\nimport { View } from \"react-native\";\nimport Animated, {\n  useAnimatedStyle,\n  useSharedValue,\n  withRepeat,\n  withTiming,\n  Easing,\n} from \"react-native-reanimated\";\nimport { s, ScaledSheet } from \"react-native-size-matters\";\n\ninterface IAnimatedSpinnerProps {\n  color: string;\n  size?: number;\n}\n\nexport default function AnimatedSpinner({ color, size = 24 }: IAnimatedSpinnerProps) {\n  const rotation = useSharedValue(0);\n\n  useEffect(() => {\n    rotation.value = withRepeat(\n      withTiming(360, {\n        duration: 1000,\n        easing: Easing.linear,\n      }),\n      -1, // infinite\n      false,\n    );\n  }, [rotation]);\n\n  const animatedStyle = useAnimatedStyle(() => {\n    return {\n      transform: [{ rotate: `${rotation.value}deg` }],\n    };\n  });\n\n  const dotSize = size / 5;\n  const radius = (size - dotSize) / 2;\n\n  // Create 8 dots around a circle with varying opacity\n  const dots = Array.from({ length: 8 }, (_, i) => {\n    const angle = (i * 360) / 8;\n    const radian = (angle * Math.PI) / 180;\n    const x = radius * Math.cos(radian);\n    const y = radius * Math.sin(radian);\n    const opacity = 0.2 + (i / 8) * 0.8; // Gradient effect\n\n    return (\n      <View\n        key={i}\n        style={[\n          styles.dot,\n          {\n            width: dotSize,\n            height: dotSize,\n            borderRadius: dotSize / 2,\n            backgroundColor: color,\n            opacity,\n            transform: [{ translateX: x }, { translateY: y }],\n          },\n        ]}\n      />\n    );\n  });\n\n  return (\n    <View style={[styles.container, { width: size, height: size }]}>\n      <Animated.View style={[styles.spinner, animatedStyle]}>{dots}</Animated.View>\n    </View>\n  );\n}\n\nconst styles = ScaledSheet.create({\n  container: {\n    justifyContent: \"center\",\n    alignItems: \"center\",\n  },\n  spinner: {\n    width: \"100%\",\n    height: \"100%\",\n    justifyContent: \"center\",\n    alignItems: \"center\",\n  },\n  dot: {\n    position: \"absolute\",\n  },\n});\n"
  },
  {
    "path": "src/components/App.tsx",
    "content": "// Import shim first to set up crypto polyfill before any other modules\nimport \"../shim\";\n\nimport { l } from \"@log\";\nimport Navigator from \"@nav/Navigator\";\nimport { NavigationContainer, useNavigationState } from \"@react-navigation/native\";\nimport { Manager, initializeCoco } from \"@cashu/coco-core\";\nimport { ExpoSqliteRepositories } from \"@cashu/coco-expo-sqlite\";\nimport { CocoCashuProvider } from \"@cashu/coco-react\";\nimport { CustomErrorBoundary } from \"@screens/ErrorScreen/ErrorBoundary\";\n// Balance is now provided by CocoCashuProvider\nimport { CurrencyProvider } from \"@src/context/Currency\";\nimport { NfcAmountLimitsProvider } from \"@src/context/NfcAmountLimits\";\nimport { NpcProvider } from \"@src/context/Npc\";\nimport { PrivacyProvider } from \"@src/context/Privacy\";\nimport { PromptProvider } from \"@src/context/Prompt\";\nimport { ThemeProvider, useThemeContext } from \"@src/context/Theme\";\nimport { NS } from \"@src/i18n\";\nimport { createNpcPlugin } from \"@src/services/NpcService\";\nimport { store } from \"@store\";\nimport { STORE_KEYS } from \"@store/consts\";\nimport { dark, light } from \"@styles\";\nimport { isErr } from \"@util\";\nimport { StatusBar } from \"expo-status-bar\";\nimport React, { useEffect, useMemo, useState } from \"react\";\nimport { useTranslation } from \"react-i18next\";\nimport { MenuProvider } from \"react-native-popup-menu\";\nimport { SafeAreaProvider } from \"react-native-safe-area-context\";\nimport { GestureHandlerRootView } from \"react-native-gesture-handler\";\nimport { TrustMintModalProvider } from \"@modal/TrustMintProvider\";\n\nimport Blank from \"./Blank\";\nimport Toaster from \"./Toaster\";\n\nimport * as SplashScreen from \"expo-splash-screen\";\nimport { dbProvider } from \"@src/storage/DbProvider\";\nimport { seedService } from \"@src/services/SeedService\";\nimport { KeyboardProvider } from \"react-native-keyboard-controller\";\nimport { appLogger } from \"@src/logger\";\nimport { AppState } from \"react-native\";\nimport NfcManager from \"react-native-nfc-manager\";\nimport { useDrizzleStudio } from \"expo-drizzle-studio-plugin\";\n\nvoid SplashScreen.preventAutoHideAsync();\n\nfunction App(_: { exp: Record<string, unknown> }) {\n  return (\n    <GestureHandlerRootView style={{ flex: 1 }}>\n      <SafeAreaProvider>\n        <CustomErrorBoundary catchErrors=\"always\">\n          <RootApp />\n        </CustomErrorBoundary>\n      </SafeAreaProvider>\n    </GestureHandlerRootView>\n  );\n}\nexport default App;\n\nfunction useAppInitialization() {\n  const [manager, setManager] = useState<Manager | null>(null);\n  const [shouldOnboard, setShouldOnboard] = useState(false);\n  const { i18n } = useTranslation([NS.common]);\n  const [isAppReady, setIsAppReady] = useState(false);\n\n  useEffect(() => {\n    let isMounted = true;\n\n    async function initializeApp() {\n      appLogger.info(\"Starting app...\");\n      // Check seed / database integrity\n\n      const seedFingerprint = await seedService.getFingerprint();\n      if (seedFingerprint) {\n        // App was initialized before\n        const dbFingerprint = dbProvider.getFingerprint();\n        if (!dbFingerprint) {\n          appLogger.info(\"Found missmatch in db and seed. Rerolling mnemonic\");\n          // Fresh database, but old seed. Reroll seed and persist new fingerprint\n          const { fingerprint: newFingerprint } = await seedService.createNewMnemonic();\n          dbProvider.setFingerprint(newFingerprint);\n        } else if (seedFingerprint !== dbFingerprint) {\n          // This state should never happen, if it does we need to display an error to the user\n          //TODO: Display an error to the user\n        }\n      }\n\n      // Initialise app\n\n      try {\n        // Initialize NFC manager (non-blocking, OK if device doesn't support NFC)\n        NfcManager.start().catch((err) => {\n          appLogger.warn(\"NFC initialization failed:\", err);\n        });\n\n        appLogger.debug(\"Loading languages...\");\n        const lang = await store.get(STORE_KEYS.lang);\n        if (lang?.length) {\n          await i18n.changeLanguage(lang);\n        }\n        await seedService.ensureMnemonicSet();\n        const onboard = await store.get(STORE_KEYS.explainer);\n        appLogger.debug(\"Onboarding already displayed: \", onboard === \"1\");\n        setShouldOnboard(onboard !== \"1\");\n        // Initialize auth, data, and manager in parallel\n        const db = dbProvider.getDatabase();\n        const repo = new ExpoSqliteRepositories({ database: db });\n        const mgr = await initializeCoco({\n          repo,\n          seedGetter: async () => seedService.getSeed(),\n          logger: appLogger.child({ name: \"Manager\" }),\n        });\n        mgr.use(createNpcPlugin());\n        // Handle app state changes for subscription management\n        AppState.addEventListener(\"change\", (state) => {\n          if (state === \"background\") {\n            mgr.pauseSubscriptions();\n          } else if (state === \"active\") {\n            mgr.resumeSubscriptions();\n          }\n        });\n        // Only update state if component is still mounted\n        if (isMounted) {\n          setManager(mgr);\n          setIsAppReady(true);\n          appLogger.info(\"App is ready!\");\n        }\n      } catch (error) {\n        l(isErr(error) ? error.message : \"Failed to initialize app\");\n        throw error;\n      }\n    }\n\n    void initializeApp();\n\n    // Cleanup function\n    return () => {\n      isMounted = false;\n    };\n    // eslint-disable-next-line react-hooks/exhaustive-deps\n  }, []);\n\n  return {\n    ready: isAppReady,\n    manager,\n    shouldOnboard,\n  };\n}\n\nfunction AppProviders({ children }: { children: React.ReactNode }) {\n  const db = useMemo(() => dbProvider.getDatabase(), []);\n  useDrizzleStudio(db);\n  return (\n    <ThemeProvider>\n      <CurrencyProvider>\n        <NfcAmountLimitsProvider>\n          <PrivacyProvider>\n            <MenuProvider>\n              <TrustMintModalProvider>\n                <ThemedNavigationContainer>\n                  <PromptProvider>\n                    <KeyboardProvider>{children}</KeyboardProvider>\n                  </PromptProvider>\n                </ThemedNavigationContainer>\n              </TrustMintModalProvider>\n            </MenuProvider>\n          </PrivacyProvider>\n        </NfcAmountLimitsProvider>\n      </CurrencyProvider>\n    </ThemeProvider>\n  );\n}\n\nfunction RootApp() {\n  const { ready, manager, shouldOnboard } = useAppInitialization();\n  useEffect(() => {\n    if (ready && manager) {\n      void SplashScreen.hide();\n    }\n  }, [ready, manager]);\n  if (!ready || !manager) {\n    return <Blank />;\n  }\n  return (\n    <CocoCashuProvider manager={manager}>\n      <NpcProvider>\n        <AppProviders>\n          <Navigator shouldOnboard={shouldOnboard} />\n          <ThemedStatusBar />\n          <Toaster />\n        </AppProviders>\n      </NpcProvider>\n    </CocoCashuProvider>\n  );\n}\n\nfunction ThemedNavigationContainer({ children }: { children: React.ReactNode }) {\n  const { activeTheme } = useThemeContext();\n  return (\n    <NavigationContainer theme={activeTheme === \"light\" ? light : dark}>\n      {children}\n    </NavigationContainer>\n  );\n}\n\nfunction ThemedStatusBar() {\n  const { activeTheme } = useThemeContext();\n  // StatusBar style is inverted: \"light\" style means light text (for dark backgrounds)\n  // and \"dark\" style means dark text (for light backgrounds)\n  return <StatusBar style={activeTheme === \"light\" ? \"dark\" : \"light\"} />;\n}\n"
  },
  {
    "path": "src/components/Balance.tsx",
    "content": "import { SwapCurrencyIcon } from \"@comps/Icons\";\nimport type { RootStackParamList } from \"@model/nav\";\nimport type { NativeStackNavigationProp } from \"@react-navigation/native-stack\";\nimport { usePaginatedHistory } from \"@cashu/coco-react\";\nimport { useBalanceContext } from \"@src/context/Balance\";\nimport { usePrivacyContext } from \"@src/context/Privacy\";\nimport { useThemeContext } from \"@src/context/Theme\";\nimport { NS } from \"@src/i18n\";\nimport { globals, highlight as hi } from \"@styles\";\nimport { getColor } from \"@styles/colors\";\nimport { useTranslation } from \"react-i18next\";\nimport { Text, TouchableOpacity, View } from \"react-native\";\nimport { s, ScaledSheet } from \"react-native-size-matters\";\n\nimport { TxtButton } from \"./Button\";\nimport Txt from \"./Txt\";\nimport { LatestHistory } from \"@screens/History/components/LatestHistory\";\nimport { useCurrencyContext } from \"@src/context/Currency\";\n\ninterface IBalanceProps {\n  nav?: NativeStackNavigationProp<RootStackParamList, \"dashboard\", \"MyStack\">;\n}\n\nexport default function Balance({ nav }: IBalanceProps) {\n  const { t } = useTranslation([NS.common]);\n  const { color, highlight } = useThemeContext();\n  const { hidden } = usePrivacyContext();\n  const { balances } = useBalanceContext();\n  const { history: latestHistory, hasMore } = usePaginatedHistory(3);\n  const { formatAmount, formatBalance, setFormatBalance } = useCurrencyContext();\n\n  const toggleBalanceFormat = () => {\n    void setFormatBalance(!formatBalance);\n  };\n\n  return (\n    <View style={[styles.board, { borderColor: color.BORDER, backgroundColor: hi[highlight] }]}>\n      <TouchableOpacity\n        style={styles.balanceWrap}\n        onPress={toggleBalanceFormat}\n        disabled={hidden.balance}\n      >\n        <Text\n          testID={`balance: ${balances.total.total}`}\n          style={[styles.balAmount, { color: getColor(highlight, color) }]}\n        >\n          {hidden.balance ? \"****\" : formatAmount(balances.total.total).formatted}\n        </Text>\n        <View style={styles.balAssetNameWrap}>\n          {!hidden.balance && (\n            <>\n              <Text style={[styles.balAssetName, { color: getColor(highlight, color) }]}>\n                {formatAmount(balances.total.total).symbol}\n              </Text>\n              <SwapCurrencyIcon width={s(20)} height={s(20)} color={getColor(highlight, color)} />\n            </>\n          )}\n        </View>\n      </TouchableOpacity>\n      {/* No transactions yet */}\n      {!latestHistory.length && (\n        <View style={styles.txOverview}>\n          <Txt\n            txt={t(\"noTX\")}\n            styles={[globals(color).pressTxt, { color: getColor(highlight, color) }]}\n          />\n        </View>\n      )}\n      {/* latest 3 history entries */}\n      <LatestHistory history={latestHistory} />\n      {hasMore && (\n        <TxtButton\n          txt={t(\"seeFullHistory\")}\n          onPress={() => nav?.navigate(\"History\", { screen: \"HistoryMain\" })}\n          txtColor={getColor(highlight, color)}\n          style={[{ paddingTop: s(15) }]}\n        />\n      )}\n    </View>\n  );\n}\n\nconst styles = ScaledSheet.create({\n  board: {\n    borderBottomLeftRadius: 50,\n    borderBottomRightRadius: 50,\n    paddingHorizontal: \"20@s\",\n    paddingBottom: \"50@s\",\n    minHeight: \"55%\",\n  },\n  balanceWrap: {\n    alignItems: \"center\",\n    marginHorizontal: \"-20@s\",\n    marginBottom: \"10@s\",\n  },\n  balAmount: {\n    alignItems: \"center\",\n    fontSize: \"42@s\",\n    fontWeight: \"600\",\n  },\n  balAssetNameWrap: {\n    flexDirection: \"row\",\n    alignItems: \"center\",\n    marginBottom: \"10@s\",\n    minHeight: \"20@s\",\n  },\n  balAssetName: {\n    fontSize: \"14@vs\",\n    marginRight: \"5@s\",\n  },\n  iconWrap: {\n    minWidth: \"40@s\",\n    paddingTop: \"3@s\",\n  },\n  entry: {\n    flexDirection: \"row\",\n    alignItems: \"center\",\n    justifyContent: \"space-between\",\n    paddingBottom: \"10@s\",\n  },\n  wrap: {\n    flexDirection: \"row\",\n    alignItems: \"center\",\n  },\n  txOverview: {\n    flex: 1,\n    alignItems: \"center\",\n    justifyContent: \"center\",\n  },\n});\n"
  },
  {
    "path": "src/components/Blank.tsx",
    "content": "import { highlight } from \"@styles\";\nimport { View } from \"react-native\";\n\nexport default function Blank() {\n  return <View style={{ flex: 1, backgroundColor: highlight[\"Default\"] }} />;\n}\n"
  },
  {
    "path": "src/components/Button.tsx",
    "content": "import { useThemeContext } from \"@src/context/Theme\";\nimport { globals, highlight as hi, mainColors } from \"@styles\";\nimport { getColor } from \"@styles/colors\";\nimport { View, type StyleProp, TouchableOpacity, type ViewStyle } from \"react-native\";\nimport { s, ScaledSheet } from \"react-native-size-matters\";\n\nimport Loading from \"./Loading\";\nimport Txt from \"./Txt\";\n\ninterface IButtonProps {\n  txt: string;\n  onPress: () => void;\n  border?: boolean;\n  outlined?: boolean;\n  filled?: boolean;\n  ghost?: boolean;\n  destructive?: boolean;\n  disabled?: boolean;\n  loading?: boolean;\n  icon?: React.ReactNode;\n  size?: \"small\" | \"medium\" | \"large\";\n}\n\nexport default function Button({\n  txt,\n  onPress,\n  border,\n  outlined,\n  filled,\n  ghost,\n  destructive,\n  disabled,\n  loading,\n  icon,\n  size = \"medium\",\n}: IButtonProps) {\n  const { color, highlight } = useThemeContext();\n\n  // Define size variants\n  const sizeStyles = {\n    small: {\n      paddingHorizontal: s(14),\n      paddingVertical: s(12),\n      fontSize: s(13),\n      spinnerSize: 16,\n    },\n    medium: {\n      paddingHorizontal: s(18),\n      paddingVertical: s(18),\n      fontSize: s(14),\n      spinnerSize: 18,\n    },\n    large: {\n      paddingHorizontal: s(22),\n      paddingVertical: s(20),\n      fontSize: s(16),\n      spinnerSize: 20,\n    },\n  };\n\n  const currentSize = sizeStyles[size];\n\n  // Automatically disable button when loading\n  const isDisabled = disabled || loading;\n\n  return (\n    <View style={styles.safeArea}>\n      <TouchableOpacity\n        accessibilityRole=\"button\"\n        testID={`${txt}-modal-button`}\n        activeOpacity={0.5}\n        disabled={isDisabled}\n        style={[\n          styles.touchableOpacity,\n          {\n            backgroundColor: hi[highlight],\n            paddingHorizontal: currentSize.paddingHorizontal,\n            paddingVertical: currentSize.paddingVertical,\n          },\n          border ? { borderWidth: 1, borderColor: mainColors.WHITE } : {},\n          filled ? { backgroundColor: mainColors.WHITE } : {},\n          destructive && !outlined && !ghost\n            ? {\n                backgroundColor: mainColors.ERROR,\n              }\n            : {},\n          outlined\n            ? {\n                backgroundColor: \"transparent\",\n                paddingHorizontal: currentSize.paddingHorizontal,\n                paddingVertical: currentSize.paddingVertical,\n                borderWidth: 1,\n                borderColor: destructive ? mainColors.ERROR : hi[highlight],\n              }\n            : {},\n          ghost\n            ? {\n                backgroundColor: \"transparent\",\n                paddingHorizontal: currentSize.paddingHorizontal,\n                paddingVertical: currentSize.paddingVertical,\n              }\n            : {},\n          isDisabled && !loading ? { opacity: 0.3 } : {},\n          loading ? { opacity: 0.7 } : {},\n        ]}\n        onPress={onPress}\n      >\n        {!loading && (\n          <Txt\n            txt={txt}\n            bold\n            center\n            styles={[\n              {\n                color: getColor(highlight, color),\n                fontSize: currentSize.fontSize,\n              },\n              filled || outlined || ghost ? { color: hi[highlight] } : {},\n              destructive && (outlined || ghost)\n                ? { color: mainColors.ERROR }\n                : destructive\n                  ? { color: mainColors.WHITE }\n                  : {},\n            ]}\n          />\n        )}\n        {loading && (\n          <View style={styles.loadingContainer}>\n            <Loading\n              size={currentSize.spinnerSize}\n              color={\n                filled || outlined || ghost\n                  ? hi[highlight]\n                  : destructive\n                    ? mainColors.WHITE\n                    : getColor(highlight, color)\n              }\n            />\n          </View>\n        )}\n        {!loading && icon && <View style={styles.iconContainer}>{icon}</View>}\n      </TouchableOpacity>\n    </View>\n  );\n}\n\ninterface IIconBtnProps {\n  icon: React.ReactNode;\n  onPress: () => void;\n  outlined?: boolean;\n  disabled?: boolean;\n  size?: number;\n  testId?: string;\n}\n\nexport function IconBtn({ icon, size, outlined, disabled, onPress, testId }: IIconBtnProps) {\n  const { color, highlight } = useThemeContext();\n  return (\n    <View>\n      <TouchableOpacity\n        accessibilityRole=\"button\"\n        activeOpacity={0.5}\n        style={[\n          styles.iconBtn,\n          {\n            width: size || s(60),\n            height: size || s(60),\n            borderRadius: (size || s(60)) / 2,\n            backgroundColor: outlined ? color.BACKGROUND : hi[highlight],\n            borderColor: hi[highlight],\n            // opacity: disabled ? .6 : 1\n          },\n        ]}\n        onPress={onPress}\n        disabled={disabled}\n        testID={testId}\n      >\n        {icon}\n      </TouchableOpacity>\n    </View>\n  );\n}\n\ninterface ITxtBtnProps {\n  txt: string;\n  onPress: () => void;\n  icon?: React.ReactNode;\n  disabled?: boolean;\n  style?: StyleProp<ViewStyle>[];\n  txtColor?: string;\n}\n\nexport function TxtButton({ txt, onPress, icon, disabled, style, txtColor }: ITxtBtnProps) {\n  const { color, highlight } = useThemeContext();\n  return (\n    <TouchableOpacity\n      style={[styles.copyTxt, ...(style || [])]}\n      onPress={onPress}\n      disabled={disabled}\n      testID={`${txt}-button`}\n    >\n      <Txt\n        txt={txt}\n        styles={[\n          globals(color).pressTxt,\n          { color: txtColor || hi[highlight], marginRight: icon ? s(10) : 0 },\n        ]}\n      />\n      {icon ? icon : null}\n    </TouchableOpacity>\n  );\n}\n\nconst styles = ScaledSheet.create({\n  safeArea: {\n    width: \"100%\",\n  },\n  touchableOpacity: {\n    display: \"flex\",\n    flexDirection: \"row\",\n    alignItems: \"center\",\n    justifyContent: \"center\",\n    borderRadius: 50,\n  },\n  loadingContainer: {\n    alignItems: \"center\",\n    justifyContent: \"center\",\n  },\n  iconContainer: {\n    position: \"absolute\",\n    right: \"18@s\",\n    alignItems: \"center\",\n    justifyContent: \"center\",\n  },\n  // icon button\n  iconBtn: {\n    borderWidth: 2,\n    alignItems: \"center\",\n    justifyContent: \"center\",\n  },\n  // txt button\n  copyTxt: {\n    paddingTop: \"30@s\",\n    paddingBottom: \"10@s\",\n    flexDirection: \"row\",\n    alignItems: \"center\",\n    justifyContent: \"center\",\n  },\n});\n"
  },
  {
    "path": "src/components/Card.tsx",
    "content": "import { useThemeContext } from \"@src/context/Theme\";\nimport { highlight as hi } from \"@styles\";\nimport type { ReactNode } from \"react\";\nimport { View, type ViewStyle, type StyleProp } from \"react-native\";\nimport { ScaledSheet, s, vs } from \"react-native-size-matters\";\n\ninterface ICardProps {\n  children: ReactNode;\n  variant?: \"base\" | \"accent\";\n  style?: StyleProp<ViewStyle>;\n}\n\nexport default function Card({ children, variant = \"base\", style }: ICardProps) {\n  const { color, highlight } = useThemeContext();\n\n  return (\n    <View\n      style={[\n        styles.card,\n        {\n          backgroundColor: color.DRAWER,\n          borderColor: variant === \"accent\" ? hi[highlight] : color.BORDER,\n        },\n        style,\n      ]}\n    >\n      {children}\n    </View>\n  );\n}\n\nconst styles = ScaledSheet.create({\n  card: {\n    borderRadius: 20,\n    borderWidth: 2,\n    padding: \"20@s\",\n  },\n});\n"
  },
  {
    "path": "src/components/Copy.tsx",
    "content": "import { useThemeContext } from \"@src/context/Theme\";\nimport { mainColors } from \"@styles\";\nimport { TouchableOpacity } from \"react-native\";\nimport { s, ScaledSheet } from \"react-native-size-matters\";\n\nimport useCopy from \"./hooks/Copy\";\nimport { CheckmarkIcon, CopyIcon } from \"./Icons\";\n\nexport default function Copy({ txt }: { txt: string }) {\n  const { color } = useThemeContext();\n  const { copied, copy } = useCopy();\n\n  return (\n    <TouchableOpacity style={styles.copyIconWrap} onPress={() => void copy(txt)} disabled={copied}>\n      {copied ? (\n        <CheckmarkIcon width={s(16)} height={s(16)} color={mainColors.VALID} />\n      ) : (\n        <CopyIcon width={s(18)} height={s(18)} color={color.TEXT_SECONDARY} />\n      )}\n    </TouchableOpacity>\n  );\n}\n\nconst styles = ScaledSheet.create({\n  copyIconWrap: {\n    paddingHorizontal: \"10@s\",\n    paddingVertical: \"5@vs\",\n  },\n});\n"
  },
  {
    "path": "src/components/DashboardTopBar.tsx",
    "content": "import { SettingsIcon } from \"@comps/Icons\";\nimport { usePrivacyContext } from \"@src/context/Privacy\";\nimport { useThemeContext } from \"@src/context/Theme\";\nimport { highlight as hi } from \"@styles\";\nimport { Image, TouchableOpacity, View } from \"react-native\";\nimport { useSafeAreaInsets } from \"react-native-safe-area-context\";\nimport { s, ScaledSheet, vs } from \"react-native-size-matters\";\n\ninterface IDashboardTopBarProps {\n  onSettingsPress: () => void;\n}\n\nexport default function DashboardTopBar({ onSettingsPress }: IDashboardTopBarProps) {\n  const { color, highlight, activeTheme } = useThemeContext();\n  const { handleLogoPress } = usePrivacyContext();\n  const insets = useSafeAreaInsets();\n  const iconColor = hi[highlight];\n\n  const logoSrc =\n    activeTheme === \"dark\" && (highlight === \"Zap\" || highlight === \"Azyre\" || highlight === \"Rosy\")\n      ? require(\"@assets/icon_transparent_dark.png\")\n      : require(\"@assets/icon_transparent.png\");\n\n  return (\n    <View\n      style={[\n        styles.topBar,\n        {\n          paddingTop: insets.top,\n          backgroundColor: color.BACKGROUND,\n        },\n      ]}\n    >\n      <View style={styles.topBarContent}>\n        <TouchableOpacity onPress={() => void handleLogoPress()} style={styles.controlBtn}>\n          <View style={[styles.logoMark, { backgroundColor: hi[highlight] }]}>\n            <Image source={logoSrc} style={styles.logoImage} resizeMode=\"contain\" />\n          </View>\n        </TouchableOpacity>\n        <TouchableOpacity onPress={onSettingsPress} style={styles.controlBtn}>\n          <SettingsIcon width={s(24)} height={s(24)} color={iconColor} />\n        </TouchableOpacity>\n      </View>\n    </View>\n  );\n}\n\nconst styles = ScaledSheet.create({\n  topBar: {\n    paddingHorizontal: \"20@s\",\n    paddingBottom: \"4@vs\",\n  },\n  topBarContent: {\n    flexDirection: \"row\",\n    alignItems: \"center\",\n    justifyContent: \"space-between\",\n    minHeight: \"50@s\",\n  },\n  controlBtn: {\n    width: \"48@s\",\n    height: \"48@s\",\n    alignItems: \"center\",\n    justifyContent: \"center\",\n  },\n  logoMark: {\n    width: \"36@s\",\n    height: \"36@s\",\n    borderRadius: \"18@s\",\n    alignItems: \"center\",\n    justifyContent: \"center\",\n  },\n  logoImage: {\n    width: \"27@s\",\n    height: \"27@s\",\n  },\n});\n"
  },
  {
    "path": "src/components/Empty.tsx",
    "content": "import type { RootStackParamList } from \"@model/nav\";\nimport type { NativeStackNavigationProp } from \"@react-navigation/native-stack\";\nimport { useThemeContext } from \"@src/context/Theme\";\nimport { Image } from \"expo-image\";\nimport { useTranslation } from \"react-i18next\";\nimport { View } from \"react-native\";\nimport { ScaledSheet, vs } from \"react-native-size-matters\";\n\nimport { TxtButton } from \"./Button\";\nimport Txt from \"./Txt\";\n\ninterface IEmptyProps {\n  txt: string;\n  hint?: string;\n  hintComponent?: React.ReactNode;\n  hasOk?: boolean;\n  pressable?: boolean;\n  onPress?: () => void;\n  nav?:\n    | NativeStackNavigationProp<RootStackParamList, \"nostrReceive\", \"MyStack\">\n    | NativeStackNavigationProp<RootStackParamList, \"qr scan\", \"MyStack\">;\n}\n\nexport default function Empty({\n  txt,\n  hint,\n  hintComponent,\n  hasOk,\n  pressable,\n  onPress,\n  nav,\n}: IEmptyProps) {\n  const { t } = useTranslation();\n  const { color } = useThemeContext();\n  return (\n    <View style={styles.container}>\n      <Image style={styles.img} source={require(\"@assets/mixed_forest.png\")} contentFit=\"contain\" />\n      {pressable && onPress ? (\n        <>\n          {hintComponent}\n          <TxtButton txt={txt} onPress={onPress} />\n        </>\n      ) : (\n        <>\n          <Txt\n            txt={txt}\n            bold\n            center\n            styles={[styles.emptyTxt, { color: color.TEXT, marginBottom: hasOk ? vs(10) : 0 }]}\n          />\n          {hint && hint.length > 0 && (\n            <Txt txt={hint} center styles={[{ color: color.TEXT_SECONDARY, fontSize: vs(12) }]} />\n          )}\n        </>\n      )}\n      {hasOk && <TxtButton txt={t(\"backToDashboard\")} onPress={() => nav?.navigate(\"dashboard\")} />}\n    </View>\n  );\n}\n\nconst styles = ScaledSheet.create({\n  container: {\n    paddingHorizontal: \"20@s\",\n    alignItems: \"center\",\n  },\n  img: {\n    width: \"300@s\",\n    height: \"300@vs\",\n    opacity: 0.4,\n  },\n  emptyTxt: {\n    fontSize: \"18@vs\",\n    opacity: 0.8,\n  },\n});\n"
  },
  {
    "path": "src/components/Icons.tsx",
    "content": "import { Image, StyleSheet } from \"react-native\";\nimport Svg, { ClipPath, Defs, G, Path, Rect } from \"react-native-svg\";\nimport MaterialIcons from \"@expo/vector-icons/MaterialIcons\";\n\n// SVG ICON SOURCE:\n// https://www.figma.com/community/file/1063385570268529014\n\ninterface TIconProps {\n  width?: number;\n  height?: number;\n  active?: boolean;\n  color: string;\n}\ninterface IExtendedIconProps extends TIconProps {\n  disabled?: boolean;\n}\n\nexport function NfcIcon({ width, height, color }: TIconProps) {\n  const size = width || height || 24;\n  return <MaterialIcons name=\"nfc\" size={size} color={color} />;\n}\n\nexport function HamburgerIcon({ width, height, color }: TIconProps) {\n  return (\n    <Svg width={width || 22} height={height || 22} viewBox=\"0 0 18 11\" fill=\"none\">\n      <Path\n        d=\"M0.5 1C0.223858 1 0 0.776142 0 0.5C0 0.223858 0.223858 0 0.5 0H17.5C17.7761 0 18 0.223858 18 0.5C18 0.776142 17.7761 1 17.5 1H0.5ZM0.5 6C0.223858 6 0 5.77614 0 5.5C0 5.22386 0.223858 5 0.5 5H17.5C17.7761 5 18 5.22386 18 5.5C18 5.77614 17.7761 6 17.5 6H0.5ZM0.5 11C0.223858 11 0 10.7761 0 10.5C0 10.2239 0.223858 10 0.5 10H17.5C17.7761 10 18 10.2239 18 10.5C18 10.7761 17.7761 11 17.5 11H0.5Z\"\n        fill={color}\n      />\n    </Svg>\n  );\n}\nexport function QRIcon({ width, height, color }: TIconProps) {\n  return (\n    <Svg width={width || 22} height={height || 22} viewBox=\"0 0 18 18\" fill=\"none\">\n      <Path\n        d=\"M2.21429 1C1.54365 1 1 1.54365 1 2.21429V3.78571C1 4.45635 1.54365 5 2.21429 5H3.78571C4.45635 5 5 4.45635 5 3.78571V2.21429C5 1.54365 4.45635 1 3.78571 1H2.21429ZM2.21429 0H3.78571C5.00863 0 6 0.99137 6 2.21429V3.78571C6 5.00863 5.00863 6 3.78571 6H2.21429C0.99137 6 0 5.00863 0 3.78571V2.21429C0 0.99137 0.99137 0 2.21429 0ZM2.21429 12H3.78571C5.00863 12 6 12.9914 6 14.2143V15.7857C6 17.0086 5.00863 18 3.78571 18H2.21429C0.99137 18 0 17.0086 0 15.7857V14.2143C0 12.9914 0.99137 12 2.21429 12ZM2.21429 13C1.54365 13 1 13.5437 1 14.2143V15.7857C1 16.4563 1.54365 17 2.21429 17H3.78571C4.45635 17 5 16.4563 5 15.7857V14.2143C5 13.5437 4.45635 13 3.78571 13H2.21429ZM14.2143 0H15.7857C17.0086 0 18 0.99137 18 2.21429V3.78571C18 5.00863 17.0086 6 15.7857 6H14.2143C12.9914 6 12 5.00863 12 3.78571V2.21429C12 0.99137 12.9914 0 14.2143 0ZM14.2143 1C13.5437 1 13 1.54365 13 2.21429V3.78571C13 4.45635 13.5437 5 14.2143 5H15.7857C16.4563 5 17 4.45635 17 3.78571V2.21429C17 1.54365 16.4563 1 15.7857 1H14.2143ZM10 17V16.5C10 16.2239 10.2239 16 10.5 16C10.7761 16 11 16.2239 11 16.5V17H11.5C11.7761 17 12 17.2239 12 17.5C12 17.7761 11.7761 18 11.5 18H9.5C9.22386 18 9 17.7761 9 17.5C9 17.2239 9.22386 17 9.5 17H10ZM10 8H11V7.5C11 7.22386 11.2239 7 11.5 7C11.7761 7 12 7.22386 12 7.5V8.5C12 8.77614 11.7761 9 11.5 9H8.5C8.22386 9 8 8.77614 8 8.5C8 8.22386 8.22386 8 8.5 8H9V7H8.5C8.22386 7 8 6.77614 8 6.5C8 6.22386 8.22386 6 8.5 6H9.5C9.77614 6 10 6.22386 10 6.5V8ZM16 9V9.5C16 9.77614 15.7761 10 15.5 10C15.2239 10 15 9.77614 15 9.5V7.5C15 7.22386 15.2239 7 15.5 7C15.7761 7 16 7.22386 16 7.5V8H17V7.5C17 7.22386 17.2239 7 17.5 7C17.7761 7 18 7.22386 18 7.5V8.5C18 8.77614 17.7761 9 17.5 9H16ZM10 11H8.5C8.22386 11 8 10.7761 8 10.5C8 10.2239 8.22386 10 8.5 10H10.5C10.7761 10 11 10.2239 11 10.5V12.5C11 12.7761 10.7761 13 10.5 13H7.5C7.22386 13 7 12.7761 7 12.5C7 12.2239 7.22386 12 7.5 12H10V11ZM2.5 2H3.5C3.77614 2 4 2.22386 4 2.5V3.5C4 3.77614 3.77614 4 3.5 4H2.5C2.22386 4 2 3.77614 2 3.5V2.5C2 2.22386 2.22386 2 2.5 2ZM2.5 14H3.5C3.77614 14 4 14.2239 4 14.5V15.5C4 15.7761 3.77614 16 3.5 16H2.5C2.22386 16 2 15.7761 2 15.5V14.5C2 14.2239 2.22386 14 2.5 14ZM14.5 2H15.5C15.7761 2 16 2.22386 16 2.5V3.5C16 3.77614 15.7761 4 15.5 4H14.5C14.2239 4 14 3.77614 14 3.5V2.5C14 2.22386 14.2239 2 14.5 2ZM10 2V1H8V2.5C8 2.77614 7.77614 3 7.5 3C7.22386 3 7 2.77614 7 2.5V0.5C7 0.223858 7.22386 0 7.5 0H10.5C10.7761 0 11 0.223858 11 0.5V2.5C11 2.77614 10.7761 3 10.5 3H9.5C9.22386 3 9 2.77614 9 2.5C9 2.22386 9.22386 2 9.5 2H10ZM7.5 5C7.22386 5 7 4.77614 7 4.5C7 4.22386 7.22386 4 7.5 4H10.5C10.7761 4 11 4.22386 11 4.5C11 4.77614 10.7761 5 10.5 5H7.5ZM8 15V17.5C8 17.7761 7.77614 18 7.5 18C7.22386 18 7 17.7761 7 17.5V14.5C7 14.2239 7.22386 14 7.5 14H10.5C10.7761 14 11 14.2239 11 14.5C11 14.7761 10.7761 15 10.5 15H8ZM6 9H6.5C6.77614 9 7 9.22386 7 9.5V10.5C7 10.7761 6.77614 11 6.5 11C6.22386 11 6 10.7761 6 10.5V10H5.5C5.22386 10 5 9.77614 5 9.5V7.5C5 7.22386 5.22386 7 5.5 7H6.5C6.77614 7 7 7.22386 7 7.5C7 7.77614 6.77614 8 6.5 8H6V9ZM3 8H2.5C2.22386 8 2 7.77614 2 7.5C2 7.22386 2.22386 7 2.5 7H3.5C3.77614 7 4 7.22386 4 7.5V10.5C4 10.7761 3.77614 11 3.5 11C3.22386 11 3 10.7761 3 10.5V8ZM13 7.5C13 7.22386 13.2239 7 13.5 7C13.7761 7 14 7.22386 14 7.5V9.5C14 9.77614 13.7761 10 13.5 10C13.2239 10 13 9.77614 13 9.5V7.5ZM17 11V10.5C17 10.2239 17.2239 10 17.5 10C17.7761 10 18 10.2239 18 10.5V11.5C18 11.7761 17.7761 12 17.5 12H14.5C14.2239 12 14 11.7761 14 11.5C14 11.2239 14.2239 11 14.5 11H17ZM13 13H15.5C15.7761 13 16 13.2239 16 13.5C16 13.7761 15.7761 14 15.5 14H12.5C12.2239 14 12 13.7761 12 13.5V11.5C12 11.2239 12.2239 11 12.5 11C12.7761 11 13 11.2239 13 11.5V13ZM17 17V13.5C17 13.2239 17.2239 13 17.5 13C17.7761 13 18 13.2239 18 13.5V17.5C18 17.7761 17.7761 18 17.5 18H13.5C13.2239 18 13 17.7761 13 17.5C13 17.2239 13.2239 17 13.5 17H17ZM12.5 16C12.2239 16 12 15.7761 12 15.5C12 15.2239 12.2239 15 12.5 15H15.5C15.7761 15 16 15.2239 16 15.5C16 15.7761 15.7761 16 15.5 16H12.5ZM1 10H1.5C1.77614 10 2 10.2239 2 10.5C2 10.7761 1.77614 11 1.5 11H0.5C0.223858 11 0 10.7761 0 10.5V7.5C0 7.22386 0.223858 7 0.5 7C0.776142 7 1 7.22386 1 7.5V10Z\"\n        fill={color}\n      />\n    </Svg>\n  );\n}\nexport function ZapIcon({ width, height, color }: TIconProps) {\n  return (\n    <Svg width={width || 24} height={height || 24} viewBox=\"0 0 30 30\" fill=\"none\">\n      <Path\n        d=\"M11.8595 14.0001H5.49991C5.09127 14.0001 4.85519 13.5365 5.09555 13.206L13.0955 2.20597C13.4188 1.76149 14.1183 2.08813 13.985 2.62132L12.1403 10.0001H18.4999C18.9086 10.0001 19.1446 10.4637 18.9043 10.7941L10.9043 21.7941C10.581 22.2386 9.88155 21.912 10.0148 21.3788L11.8595 14.0001ZM12.3907 4.87529L6.4818 13.0001H12.4999C12.8252 13.0001 13.0639 13.3057 12.985 13.6213L11.6091 19.1248L17.518 11.0001H11.4999C11.1746 11.0001 10.936 10.6944 11.0148 10.3788L12.3907 4.87529Z\"\n        fill={color}\n      />\n    </Svg>\n  );\n}\nexport function MintBoardIcon({ width, height, color }: TIconProps) {\n  return (\n    <Svg width={width || 24} height={height || 24} viewBox=\"0 0 24 24\" fill=\"none\">\n      <Path\n        fill-rule=\"evenodd\"\n        clip-rule=\"evenodd\"\n        d=\"M8.97749 2.5H15.0223L21.8223 8.5H2.17749L8.97749 2.5ZM9.3556 3.5L4.82226 7.5H19.1775L14.6442 3.5H9.3556Z\"\n        fill={color}\n      />\n      <Path d=\"M4.5 20.5H19.5V21.5H4.5V20.5Z\" fill={color} />\n      <Path d=\"M12.5 19.5V9.5H11.5V19.5H12.5Z\" fill={color} />\n      <Path d=\"M16.5 9.5V19.5H15.5V9.5H16.5Z\" fill={color} />\n      <Path d=\"M8.5 19.5V9.5H7.5V19.5H8.5Z\" fill={color} />\n    </Svg>\n  );\n}\nexport function BitcoinIcon({ width, height, color }: TIconProps) {\n  return (\n    <Svg width={width || 24} height={height || 24} viewBox=\"0 0 24 24\" fill=\"none\">\n      <Path\n        d=\"M8 17V12H6.5C6.22386 12 6 11.7761 6 11.5C6 11.2239 6.22386 11 6.5 11H8V7H6.5C6.22386 7 6 6.77614 6 6.5C6 6.22386 6.22386 6 6.5 6H8V4.5C8 4.22386 8.22386 4 8.5 4C8.77614 4 9 4.22386 9 4.5V6H11V4.5C11 4.22386 11.2239 4 11.5 4C11.7761 4 12 4.22386 12 4.5V6H13.0139C14.6707 6 16.0139 7.34315 16.0139 9C16.0139 9.79993 15.7008 10.5267 15.1905 11.0646C16.8017 11.3782 18.0178 12.7971 18.0178 14.5C18.0178 16.433 16.4508 18 14.5178 18H12V19.5C12 19.7761 11.7761 20 11.5 20C11.2239 20 11 19.7761 11 19.5V18H9V19.5083C9 19.7845 8.77614 20.0083 8.5 20.0083C8.22386 20.0083 8 19.7845 8 19.5083V18H6.5C6.22386 18 6 17.7762 6 17.5C6 17.2239 6.22386 17 6.5 17H8ZM9 17H11.4948L11.5 17L11.5052 17H14.5178C15.8985 17 17.0178 15.8807 17.0178 14.5C17.0178 13.1193 15.8985 12 14.5178 12H9V17ZM13.0139 11C14.1184 11 15.0139 10.1046 15.0139 9C15.0139 7.89543 14.1184 7 13.0139 7H9V11H13.0139Z\"\n        fill={color}\n      />\n    </Svg>\n  );\n}\nexport function PlusIcon({ width, height, color }: TIconProps) {\n  return (\n    <Svg width={width || 24} height={height || 24} viewBox=\"0 0 24 24\" fill=\"none\">\n      <Path\n        d=\"M13 12H18.5C18.7761 12 19 12.2239 19 12.5C19 12.7761 18.7761 13 18.5 13H13V18.5C13 18.7761 12.7761 19 12.5 19C12.2239 19 12 18.7761 12 18.5V13H6.5C6.22386 13 6 12.7761 6 12.5C6 12.2239 6.22386 12 6.5 12H12V6.5C12 6.22386 12.2239 6 12.5 6C12.7761 6 13 6.22386 13 6.5V12Z\"\n        fill={color}\n      />\n    </Svg>\n  );\n}\nexport function ChevronRightIcon({ width, height, color }: TIconProps) {\n  return (\n    <Svg width={width || 11} height={height || 18} viewBox=\"0 0 11 18\" fill=\"none\">\n      <Path\n        d=\"M1.99987 0.939331L0.939209 1.99999L7.93918 8.99997L0.939209 16L1.99987 17.0607L10.0605 8.99997L1.99987 0.939331Z\"\n        fill={color}\n      />\n    </Svg>\n  );\n}\nexport function CopyIcon({ width, height, color }: TIconProps) {\n  return (\n    <Svg width={width || 20} height={height || 20} viewBox=\"0 0 20 20\" fill=\"none\">\n      <G clip-path=\"url(#clip0_37_1722)\">\n        <Path\n          d=\"M14.1666 11.1667V13.6667C14.1666 17 12.8333 18.3333 9.49996 18.3333H6.33329C2.99996 18.3333 1.66663 17 1.66663 13.6667V10.5C1.66663 7.16668 2.99996 5.83334 6.33329 5.83334H8.83329\"\n          stroke={color}\n          stroke-width=\"1.5\"\n          stroke-linecap=\"round\"\n          stroke-linejoin=\"round\"\n        />\n        <Path\n          d=\"M14.1667 11.1667H11.5C9.50004 11.1667 8.83337 10.5 8.83337 8.50001V5.83334L14.1667 11.1667Z\"\n          stroke={color}\n          stroke-width=\"1.5\"\n          stroke-linecap=\"round\"\n          stroke-linejoin=\"round\"\n        />\n        <Path\n          d=\"M9.66663 1.66666H13\"\n          stroke={color}\n          stroke-width=\"1.5\"\n          stroke-linecap=\"round\"\n          stroke-linejoin=\"round\"\n        />\n        <Path\n          d=\"M5.83337 4.16666C5.83337 2.78332 6.95004 1.66666 8.33337 1.66666H10.5167\"\n          stroke={color}\n          stroke-width=\"1.5\"\n          stroke-linecap=\"round\"\n          stroke-linejoin=\"round\"\n        />\n        <Path\n          d=\"M18.3332 6.66666V11.825C18.3332 13.1167 17.2832 14.1667 15.9916 14.1667\"\n          stroke={color}\n          stroke-width=\"1.5\"\n          stroke-linecap=\"round\"\n          stroke-linejoin=\"round\"\n        />\n        <Path\n          d=\"M18.3334 6.66666H15.8334C13.9584 6.66666 13.3334 6.04166 13.3334 4.16666V1.66666L18.3334 6.66666Z\"\n          stroke={color}\n          stroke-width=\"1.5\"\n          stroke-linecap=\"round\"\n          stroke-linejoin=\"round\"\n        />\n      </G>\n      <Defs>\n        <ClipPath id=\"clip0_37_1722\">\n          <Rect width=\"20\" height=\"20\" fill=\"white\" />\n        </ClipPath>\n      </Defs>\n    </Svg>\n  );\n}\nexport function RefreshIcon({ width, height, color }: TIconProps) {\n  return (\n    <Svg width={width || 22} height={height || 16} viewBox=\"0 0 22 16\" fill=\"none\">\n      <Path\n        d=\"M8.83329 6.91667H5.69271L5.69379 6.90692C5.83525 6.21427 6.1121 5.55638 6.50846 4.971C7.09828 4.10197 7.92562 3.42092 8.89179 3.00908C9.21896 2.87042 9.56021 2.76425 9.90796 2.69383C10.6293 2.54758 11.3727 2.54758 12.0941 2.69383C13.1308 2.90627 14.0822 3.41903 14.8295 4.16825L16.3635 2.63858C15.6722 1.94703 14.8542 1.39496 13.9542 1.0125C13.4952 0.818182 13.018 0.670116 12.5296 0.5705C11.5219 0.365762 10.4834 0.365762 9.47571 0.5705C8.98696 0.670529 8.50939 0.818955 8.05004 1.01358C6.69645 1.58786 5.53772 2.54118 4.71338 3.75875C4.15859 4.57976 3.77062 5.50182 3.57154 6.4725C3.54121 6.61875 3.52496 6.76825 3.50329 6.91667H0.166626L4.49996 11.25L8.83329 6.91667ZM13.1666 9.08333H16.3072L16.3061 9.092C16.0231 10.4806 15.2046 11.7018 14.0279 12.4915C13.4427 12.8882 12.7847 13.1651 12.092 13.3062C11.3709 13.4524 10.6279 13.4524 9.90688 13.3062C9.21423 13.1647 8.55634 12.8879 7.97096 12.4915C7.68347 12.297 7.41504 12.0758 7.16929 11.8307L5.63746 13.3625C6.32918 14.0539 7.14754 14.6056 8.04788 14.9875C8.50721 15.1825 8.98713 15.3309 9.47246 15.4295C10.4798 15.6344 11.518 15.6344 12.5253 15.4295C14.4672 15.0265 16.1753 13.8819 17.2865 12.2391C17.8408 11.4187 18.2284 10.4974 18.4273 9.5275C18.4565 9.38125 18.4739 9.23175 18.4955 9.08333H21.8333L17.5 4.75L13.1666 9.08333Z\"\n        fill={color}\n      />\n    </Svg>\n  );\n}\nexport function SwapIcon({ width, height, color }: TIconProps) {\n  return (\n    <Svg width={width || 24} height={height || 24} viewBox=\"0 0 24 24\" fill=\"none\">\n      <Path\n        d=\"M9.29289 7L7.14645 4.85355C6.95118 4.65829 6.95118 4.34171 7.14645 4.14645C7.34171 3.95118 7.65829 3.95118 7.85355 4.14645L10.8536 7.14645C11.0488 7.34171 11.0488 7.65829 10.8536 7.85355L7.85355 10.8536C7.65829 11.0488 7.34171 11.0488 7.14645 10.8536C6.95118 10.6583 6.95118 10.3417 7.14645 10.1464L9.29289 8H5.5C4.67157 8 4 8.67157 4 9.5V15.5C4 16.3284 4.67157 17 5.5 17H10.5C10.7761 17 11 17.2239 11 17.5C11 17.7761 10.7761 18 10.5 18H5.5C4.11929 18 3 16.8807 3 15.5V9.5C3 8.11929 4.11929 7 5.5 7H9.29289ZM13.5 8C13.2239 8 13 7.77614 13 7.5C13 7.22386 13.2239 7 13.5 7H20.5C20.7761 7 21 7.22386 21 7.5C21 7.77614 20.7761 8 20.5 8H13.5ZM13.5 13C13.2239 13 13 12.7761 13 12.5C13 12.2239 13.2239 12 13.5 12H20.5C20.7761 12 21 12.2239 21 12.5C21 12.7761 20.7761 13 20.5 13H13.5ZM13.5 18C13.2239 18 13 17.7761 13 17.5C13 17.2239 13.2239 17 13.5 17H20.5C20.7761 17 21 17.2239 21 17.5C21 17.7761 20.7761 18 20.5 18H13.5Z\"\n        fill={color}\n      />\n    </Svg>\n  );\n}\nexport function TrashbinIcon({ width, height, color }: TIconProps) {\n  return (\n    <Svg width={width || 24} height={height || 24} viewBox=\"0 0 24 24\" fill=\"none\">\n      <Path\n        d=\"M19 6V18.5C19 19.8807 17.8807 21 16.5 21H7.5C6.11929 21 5 19.8807 5 18.5V6H4.5C4.22386 6 4 5.77614 4 5.5C4 5.22386 4.22386 5 4.5 5H9V4.5C9 3.67157 9.67157 3 10.5 3H13.5C14.3284 3 15 3.67157 15 4.5V5H19.5C19.7761 5 20 5.22386 20 5.5C20 5.77614 19.7761 6 19.5 6H19ZM6 6V18.5C6 19.3284 6.67157 20 7.5 20H16.5C17.3284 20 18 19.3284 18 18.5V6H6ZM14 5V4.5C14 4.22386 13.7761 4 13.5 4H10.5C10.2239 4 10 4.22386 10 4.5V5H14ZM14 9.5C14 9.22386 14.2239 9 14.5 9C14.7761 9 15 9.22386 15 9.5V16.5C15 16.7761 14.7761 17 14.5 17C14.2239 17 14 16.7761 14 16.5V9.5ZM9 9.5C9 9.22386 9.22386 9 9.5 9C9.77614 9 10 9.22386 10 9.5V16.5C10 16.7761 9.77614 17 9.5 17C9.22386 17 9 16.7761 9 16.5V9.5Z\"\n        fill={color}\n      />\n    </Svg>\n  );\n}\nexport function PenIcon({ width, height, color }: TIconProps) {\n  return (\n    <Svg width={width || 24} height={height || 24} viewBox=\"0 0 24 24\" fill=\"none\">\n      <Path\n        d=\"M7.77891 18.486L5.51398 16.2211C4.61303 17.2771 4.08311 18.6019 4.00899 19.991C5.39808 19.9169 6.72294 19.387 7.77891 18.486ZM6.20711 15.5L8.5 17.7929L19.7979 6.49499C20.0713 6.22162 20.0713 5.77841 19.7979 5.50504L18.495 4.2021C18.2216 3.92873 17.7784 3.92873 17.505 4.2021L6.20711 15.5ZM14.792 5.50095C14.0468 4.80901 12.8815 4.82557 12.1565 5.55062L8.85355 8.85357C8.65829 9.04883 8.34171 9.04883 8.14645 8.85357C7.95118 8.65831 7.95118 8.34172 8.14645 8.14646L11.4494 4.84352C12.565 3.72792 14.3634 3.71125 15.4994 4.79352L16.7979 3.49499C17.4618 2.8311 18.5382 2.8311 19.2021 3.49499L20.505 4.79793C21.1689 5.46182 21.1689 6.5382 20.505 7.2021L8.85355 18.8536C7.47921 20.2279 5.61519 21 3.67157 21H3.5C3.22386 21 3 20.7762 3 20.5V20.3284C3 18.3848 3.7721 16.5208 5.14645 15.1465L14.792 5.50095Z\"\n        fill={color}\n      />\n    </Svg>\n  );\n}\nexport function ExclamationIcon({ width, height, color }: TIconProps) {\n  return (\n    <Svg width={width || 24} height={height || 24} viewBox=\"0 0 24 24\" fill=\"none\">\n      <G clip-path=\"url(#clip0_2_7981)\">\n        <Path\n          d=\"M12 22.5C9.21523 22.5 6.54451 21.3938 4.57538 19.4246C2.60625 17.4555 1.5 14.7848 1.5 12C1.5 9.21523 2.60625 6.54451 4.57538 4.57538C6.54451 2.60625 9.21523 1.5 12 1.5C14.7848 1.5 17.4555 2.60625 19.4246 4.57538C21.3938 6.54451 22.5 9.21523 22.5 12C22.5 14.7848 21.3938 17.4555 19.4246 19.4246C17.4555 21.3938 14.7848 22.5 12 22.5ZM12 24C15.1826 24 18.2348 22.7357 20.4853 20.4853C22.7357 18.2348 24 15.1826 24 12C24 8.8174 22.7357 5.76516 20.4853 3.51472C18.2348 1.26428 15.1826 0 12 0C8.8174 0 5.76516 1.26428 3.51472 3.51472C1.26428 5.76516 0 8.8174 0 12C0 15.1826 1.26428 18.2348 3.51472 20.4853C5.76516 22.7357 8.8174 24 12 24Z\"\n          fill={color}\n        />\n        <Path\n          d=\"M11 16.5075C11 16.3105 11.0388 16.1155 11.1142 15.9335C11.1896 15.7515 11.3001 15.5861 11.4393 15.4468C11.5786 15.3076 11.744 15.1971 11.926 15.1217C12.108 15.0463 12.303 15.0075 12.5 15.0075C12.697 15.0075 12.892 15.0463 13.074 15.1217C13.256 15.1971 13.4214 15.3076 13.5607 15.4468C13.6999 15.5861 13.8104 15.7515 13.8858 15.9335C13.9612 16.1155 14 16.3105 14 16.5075C14 16.9053 13.842 17.2869 13.5607 17.5682C13.2794 17.8495 12.8978 18.0075 12.5 18.0075C12.1022 18.0075 11.7206 17.8495 11.4393 17.5682C11.158 17.2869 11 16.9053 11 16.5075ZM11.147 7.5C11.127 7.31076 11.1471 7.11944 11.2058 6.93844C11.2645 6.75745 11.3607 6.59082 11.488 6.44938C11.6153 6.30794 11.7709 6.19484 11.9447 6.11742C12.1185 6.04001 12.3067 6 12.497 6C12.6873 6 12.8755 6.04001 13.0493 6.11742C13.2231 6.19484 13.3787 6.30794 13.506 6.44938C13.6333 6.59082 13.7295 6.75745 13.7882 6.93844C13.8469 7.11944 13.867 7.31076 13.847 7.5L13.322 12.7605C13.3044 12.9672 13.2098 13.1597 13.057 13.3C12.9043 13.4402 12.7044 13.5181 12.497 13.5181C12.2896 13.5181 12.0897 13.4402 11.937 13.3C11.7842 13.1597 11.6896 12.9672 11.672 12.7605L11.147 7.5Z\"\n          fill={color}\n        />\n      </G>\n      <Defs>\n        <ClipPath id=\"clip0_2_7981\">\n          <Rect width=\"24\" height=\"24\" fill=\"white\" />\n        </ClipPath>\n      </Defs>\n    </Svg>\n  );\n}\nexport function CheckCircleIcon({ width, height, color }: TIconProps) {\n  return (\n    <Svg width={width || 24} height={height || 24} viewBox=\"0 0 24 24\" fill=\"none\">\n      <G clip-path=\"url(#clip0_2_8549)\">\n        <Path\n          d=\"M12 22.5C9.21523 22.5 6.54451 21.3938 4.57538 19.4246C2.60625 17.4555 1.5 14.7848 1.5 12C1.5 9.21523 2.60625 6.54451 4.57538 4.57538C6.54451 2.60625 9.21523 1.5 12 1.5C14.7848 1.5 17.4555 2.60625 19.4246 4.57538C21.3938 6.54451 22.5 9.21523 22.5 12C22.5 14.7848 21.3938 17.4555 19.4246 19.4246C17.4555 21.3938 14.7848 22.5 12 22.5ZM12 24C15.1826 24 18.2348 22.7357 20.4853 20.4853C22.7357 18.2348 24 15.1826 24 12C24 8.8174 22.7357 5.76516 20.4853 3.51472C18.2348 1.26428 15.1826 0 12 0C8.8174 0 5.76516 1.26428 3.51472 3.51472C1.26428 5.76516 0 8.8174 0 12C0 15.1826 1.26428 18.2348 3.51472 20.4853C5.76516 22.7357 8.8174 24 12 24Z\"\n          fill={color}\n        />\n        <Path\n          d=\"M16.2709 7.32603C16.2603 7.33638 16.2502 7.3474 16.2409 7.35903L11.0314 13.9965L7.89194 10.8555C7.67867 10.6568 7.39661 10.5486 7.10515 10.5538C6.8137 10.5589 6.53562 10.677 6.3295 10.8831C6.12339 11.0892 6.00532 11.3673 6.00018 11.6587C5.99503 11.9502 6.10322 12.2323 6.30194 12.4455L10.2709 16.416C10.3779 16.5228 10.5052 16.6069 10.6453 16.6633C10.7854 16.7198 10.9355 16.7474 11.0866 16.7446C11.2376 16.7418 11.3865 16.7086 11.5245 16.647C11.6624 16.5854 11.7865 16.4966 11.8894 16.386L17.8774 8.90103C18.0813 8.68702 18.1928 8.40137 18.1878 8.10583C18.1827 7.81029 18.0616 7.5286 17.8505 7.32167C17.6394 7.11474 17.3554 6.99919 17.0598 7C16.7642 7.00082 16.4809 7.11793 16.2709 7.32603Z\"\n          fill={color}\n        />\n      </G>\n      <Defs>\n        <ClipPath id=\"clip0_2_8549\">\n          <Rect width={height || 24} height={height || 24} fill=\"white\" />\n        </ClipPath>\n      </Defs>\n    </Svg>\n  );\n}\nexport function UserIcon({ width, height, color }: TIconProps) {\n  return (\n    <Svg width={width || 24} height={height || 24} viewBox=\"0 0 24 24\" fill=\"none\">\n      <Path\n        d=\"M12 12C14.7614 12 17 9.76142 17 7C17 4.23858 14.7614 2 12 2C9.23858 2 7 4.23858 7 7C7 9.76142 9.23858 12 12 12Z\"\n        stroke={color}\n        stroke-width=\"1.5\"\n        stroke-linecap=\"round\"\n        stroke-linejoin=\"round\"\n      />\n      <Path\n        d=\"M20.5901 22C20.5901 18.13 16.7401 15 12.0001 15C7.26016 15 3.41016 18.13 3.41016 22\"\n        stroke={color}\n        stroke-width=\"1.5\"\n        stroke-linecap=\"round\"\n        stroke-linejoin=\"round\"\n      />\n    </Svg>\n  );\n}\nexport function PaletteIcon({ width, height, color }: TIconProps) {\n  return (\n    <Svg width={width || 24} height={height || 24} viewBox=\"0 0 24 24\" fill=\"none\">\n      <Path\n        d=\"M12 3C7.02944 3 3 7.02944 3 12C3 16.9706 7.02944 21 12 21H12.5C12.8583 21 13.1706 20.7562 13.2575 20.4086C13.3833 19.9051 13.2686 19.4033 12.956 19.0282L11.1159 16.8201C10.8732 16.5289 11.0302 16.0841 11.4019 16.0097L17.4796 14.7942C19.5266 14.3848 21 12.5875 21 10.5C21 6.35786 17.6421 3 13.5 3H12ZM12.4221 16.8255L13.7242 18.388C14.2411 19.0083 14.4309 19.838 14.2351 20.6213C14.0294 21.4439 13.3171 22 12.5 22H12C6.47715 22 2 17.5228 2 12C2 6.47715 6.47715 2 12 2H13.5C18.1944 2 22 5.80558 22 10.5C22 13.0642 20.1901 15.2719 17.6757 15.7748L12.4221 16.8255ZM18 10C18.5523 10 19 9.55228 19 9C19 8.44772 18.5523 8 18 8C17.4477 8 17 8.44772 17 9C17 9.55228 17.4477 10 18 10ZM14 7C14.5523 7 15 6.55228 15 6C15 5.44772 14.5523 5 14 5C13.4477 5 13 5.44772 13 6C13 6.55228 13.4477 7 14 7ZM9 8C9.55228 8 10 7.55228 10 7C10 6.44772 9.55228 6 9 6C8.44772 6 8 6.44772 8 7C8 7.55228 8.44772 8 9 8ZM6 12C6.55228 12 7 11.5523 7 11C7 10.4477 6.55228 10 6 10C5.44772 10 5 10.4477 5 11C5 11.5523 5.44772 12 6 12Z\"\n        fill={color}\n      />\n    </Svg>\n  );\n}\nexport function SwapCurrencyIcon({ width, height, color }: TIconProps) {\n  return (\n    <Svg width={width || 24} height={height || 24} viewBox=\"0 0 24 24\" fill=\"none\">\n      <Path\n        d=\"M9.01141 21.2497C8.82141 21.2497 8.63141 21.1797 8.48141 21.0297L3.47141 16.0197C3.18141 15.7297 3.18141 15.2497 3.47141 14.9597C3.76141 14.6697 4.24141 14.6697 4.53141 14.9597L9.54141 19.9697C9.83141 20.2597 9.83141 20.7397 9.54141 21.0297C9.39141 21.1697 9.20141 21.2497 9.01141 21.2497Z\"\n        fill={color}\n      />\n      <Path\n        d=\"M9.01172 21.25C8.60172 21.25 8.26172 20.91 8.26172 20.5V3.5C8.26172 3.09 8.60172 2.75 9.01172 2.75C9.42172 2.75 9.76172 3.09 9.76172 3.5V20.5C9.76172 20.91 9.42172 21.25 9.01172 21.25Z\"\n        fill={color}\n      />\n      <Path\n        d=\"M20.0114 9.26141C19.8214 9.26141 19.6314 9.19141 19.4814 9.04141L14.4714 4.03141C14.1814 3.74141 14.1814 3.26141 14.4714 2.97141C14.7614 2.68141 15.2414 2.68141 15.5314 2.97141L20.5414 7.98141C20.8314 8.27141 20.8314 8.75141 20.5414 9.04141C20.3914 9.19141 20.2014 9.26141 20.0114 9.26141Z\"\n        fill={color}\n      />\n      <Path\n        d=\"M14.9883 21.25C14.5783 21.25 14.2383 20.91 14.2383 20.5V3.5C14.2383 3.09 14.5783 2.75 14.9883 2.75C15.3983 2.75 15.7383 3.09 15.7383 3.5V20.5C15.7383 20.91 15.4083 21.25 14.9883 21.25Z\"\n        fill={color}\n      />\n    </Svg>\n  );\n}\nexport function ArrowDownIcon({ width, height, color }: TIconProps) {\n  return (\n    <Svg width={width || 24} height={height || 24} viewBox=\"0 0 24 24\" fill=\"none\">\n      <Path\n        fill-rule=\"evenodd\"\n        clip-rule=\"evenodd\"\n        d=\"M1.5 12C1.5 14.7848 2.60625 17.4555 4.57538 19.4246C6.54451 21.3938 9.21523 22.5 12 22.5C14.7848 22.5 17.4555 21.3938 19.4246 19.4246C21.3938 17.4555 22.5 14.7848 22.5 12C22.5 9.21523 21.3938 6.54451 19.4246 4.57538C17.4555 2.60625 14.7848 1.5 12 1.5C9.21523 1.5 6.54451 2.60625 4.57538 4.57538C2.60625 6.54451 1.5 9.21523 1.5 12ZM24 12C24 15.1826 22.7357 18.2348 20.4853 20.4853C18.2348 22.7357 15.1826 24 12 24C8.8174 24 5.76516 22.7357 3.51472 20.4853C1.26428 18.2348 0 15.1826 0 12C0 8.8174 1.26428 5.76516 3.51472 3.51472C5.76516 1.26428 8.8174 0 12 0C15.1826 0 18.2348 1.26428 20.4853 3.51472C22.7357 5.76516 24 8.8174 24 12ZM12.75 6.75C12.75 6.55109 12.671 6.36032 12.5303 6.21967C12.3897 6.07902 12.1989 6 12 6C11.8011 6 11.6103 6.07902 11.4697 6.21967C11.329 6.36032 11.25 6.55109 11.25 6.75V15.4395L8.031 12.219C7.89017 12.0782 7.69916 11.9991 7.5 11.9991C7.30084 11.9991 7.10983 12.0782 6.969 12.219C6.82817 12.3598 6.74905 12.5508 6.74905 12.75C6.74905 12.9492 6.82817 13.1402 6.969 13.281L11.469 17.781C11.5387 17.8508 11.6214 17.9063 11.7125 17.9441C11.8037 17.9819 11.9013 18.0013 12 18.0013C12.0987 18.0013 12.1963 17.9819 12.2874 17.9441C12.3786 17.9063 12.4613 17.8508 12.531 17.781L17.031 13.281C17.1718 13.1402 17.2509 12.9492 17.2509 12.75C17.2509 12.5508 17.1718 12.3598 17.031 12.219C16.8902 12.0782 16.6992 11.9991 16.5 11.9991C16.3008 11.9991 16.1098 12.0782 15.969 12.219L12.75 15.4395V6.75Z\"\n        fill={color}\n      />\n    </Svg>\n  );\n}\nexport function InfoIcon({ width, height, color }: TIconProps) {\n  return (\n    <Svg width={width || 24} height={height || 24} viewBox=\"0 0 24 24\" fill=\"none\">\n      <Path\n        d=\"M11 7H13V9H11V7ZM11 11H13V17H11V11ZM12 2C6.48 2 2 6.48 2 12C2 17.52 6.48 22 12 22C17.52 22 22 17.52 22 12C22 6.48 17.52 2 12 2ZM12 20C7.59 20 4 16.41 4 12C4 7.59 7.59 4 12 4C16.41 4 20 7.59 20 12C20 16.41 16.41 20 12 20Z\"\n        fill={color}\n      />\n    </Svg>\n  );\n}\nexport function ValidateIcon({ width, height, color }: TIconProps) {\n  return (\n    <Svg width={width || 24} height={height || 24} viewBox=\"0 0 24 24\" fill=\"none\">\n      <Path\n        d=\"M8.59609 20.3032L6.5 18.2071L4.40391 20.3032C4.9882 20.7408 5.71383 21 6.5 21C7.28617 21 8.0118 20.7408 8.59609 20.3032ZM9.30319 19.5961C9.7408 19.0118 10 18.2862 10 17.5C10 16.7138 9.7408 15.9882 9.30319 15.4039L7.20711 17.5L9.30319 19.5961ZM3.69681 15.4039C3.2592 15.9882 3 16.7138 3 17.5C3 18.2862 3.2592 19.0118 3.69681 19.5961L5.79289 17.5L3.69681 15.4039ZM4.40391 14.6968L6.5 16.7929L8.59609 14.6968C8.0118 14.2592 7.28617 14 6.5 14C5.71383 14 4.9882 14.2592 4.40391 14.6968ZM6.5 11C4.01472 11 2 8.98528 2 6.5C2 4.01472 4.01472 2 6.5 2C8.98528 2 11 4.01472 11 6.5C11 8.98528 8.98528 11 6.5 11ZM6.5 10C8.433 10 10 8.433 10 6.5C10 4.567 8.433 3 6.5 3C4.567 3 3 4.567 3 6.5C3 8.433 4.567 10 6.5 10ZM7.60957 5.18765C7.78207 4.97202 8.09672 4.93706 8.31235 5.10957C8.52798 5.28207 8.56294 5.59672 8.39043 5.81235L6.39043 8.31235C6.20427 8.54505 5.85717 8.56428 5.64645 8.35355L4.64645 7.35355C4.45118 7.15829 4.45118 6.84171 4.64645 6.64645C4.84171 6.45118 5.15829 6.45118 5.35355 6.64645L5.95854 7.25143L7.60957 5.18765ZM13.5 6C13.2239 6 13 5.77614 13 5.5C13 5.22386 13.2239 5 13.5 5H21.5C21.7761 5 22 5.22386 22 5.5C22 5.77614 21.7761 6 21.5 6H13.5ZM13.5 8C13.2239 8 13 7.77614 13 7.5C13 7.22386 13.2239 7 13.5 7H19.5C19.7761 7 20 7.22386 20 7.5C20 7.77614 19.7761 8 19.5 8H13.5ZM6.5 22C4.01472 22 2 19.9853 2 17.5C2 15.0147 4.01472 13 6.5 13C8.98528 13 11 15.0147 11 17.5C11 19.9853 8.98528 22 6.5 22ZM13.5 17C13.2239 17 13 16.7761 13 16.5C13 16.2239 13.2239 16 13.5 16H21.5C21.7761 16 22 16.2239 22 16.5C22 16.7761 21.7761 17 21.5 17H13.5ZM13.5 19C13.2239 19 13 18.7761 13 18.5C13 18.2239 13.2239 18 13.5 18H19.5C19.7761 18 20 18.2239 20 18.5C20 18.7761 19.7761 19 19.5 19H13.5Z\"\n        fill={color}\n      />\n    </Svg>\n  );\n}\nexport function LockIcon({ width, height, color }: TIconProps) {\n  return (\n    <Svg width={width || 24} height={height || 24} viewBox=\"0 0 24 24\" fill=\"none\">\n      <Path\n        d=\"M6 10V8C6 4.69 7 2 12 2C17 2 18 4.69 18 8V10\"\n        stroke={color}\n        stroke-width=\"1.5\"\n        stroke-linecap=\"round\"\n        stroke-linejoin=\"round\"\n      />\n      <Path\n        d=\"M9.5 16C9.5 17.38 10.62 18.5 12 18.5C13.38 18.5 14.5 17.38 14.5 16C14.5 14.62 13.38 13.5 12 13.5\"\n        stroke={color}\n        stroke-width=\"1.5\"\n        stroke-linecap=\"round\"\n        stroke-linejoin=\"round\"\n      />\n      <Path\n        d=\"M22 17V15C22 11 21 10 17 10H7C3 10 2 11 2 15V17C2 21 3 22 7 22H17C18.76 22 19.94 21.81 20.71 21.25\"\n        stroke={color}\n        stroke-width=\"1.5\"\n        stroke-linecap=\"round\"\n        stroke-linejoin=\"round\"\n      />\n    </Svg>\n  );\n}\nexport function UnlockIcon({ width, height, color }: TIconProps) {\n  return (\n    <Svg width={width || 24} height={height || 24} viewBox=\"0 0 24 24\" fill=\"none\">\n      <Path\n        d=\"M9.5 16C9.5 17.38 10.62 18.5 12 18.5C13.38 18.5 14.5 17.38 14.5 16C14.5 14.62 13.38 13.5 12 13.5\"\n        stroke={color}\n        stroke-width=\"1.5\"\n        stroke-linecap=\"round\"\n        stroke-linejoin=\"round\"\n      />\n      <Path\n        d=\"M22 17V15C22 11 21 10 17 10H7C3 10 2 11 2 15V17C2 21 3 22 7 22H17C18.76 22 19.94 21.81 20.71 21.25\"\n        stroke={color}\n        stroke-width=\"1.5\"\n        stroke-linecap=\"round\"\n        stroke-linejoin=\"round\"\n      />\n      <Path\n        d=\"M6 10V8C6 4.69 7 2 12 2C16.5 2 18 4 18 7\"\n        stroke={color}\n        stroke-width=\"1.5\"\n        stroke-linecap=\"round\"\n        stroke-linejoin=\"round\"\n      />\n    </Svg>\n  );\n}\nexport function BackupIcon({ width, height, color }: TIconProps) {\n  return (\n    <Svg width={width || 24} height={height || 24} viewBox=\"0 0 24 24\" fill=\"none\">\n      <G clip-path=\"url(#clip0_105_711)\">\n        <Path\n          d=\"M14 12C14 10.9 13.1 10 12 10C10.9 10 10 10.9 10 12C10 13.1 10.9 14 12 14C13.1 14 14 13.1 14 12ZM12 3C7.03 3 3 7.03 3 12H0L4 16L8 12H5C5 8.13 8.13 5 12 5C15.87 5 19 8.13 19 12C19 15.87 15.87 19 12 19C10.49 19 9.09 18.51 7.94 17.7L6.52 19.14C8.04 20.3 9.94 21 12 21C16.97 21 21 16.97 21 12C21 7.03 16.97 3 12 3Z\"\n          fill={color}\n        />\n      </G>\n      <Defs>\n        <ClipPath id=\"clip0_105_711\">\n          <Rect width=\"24\" height=\"24\" fill=\"white\" />\n        </ClipPath>\n      </Defs>\n    </Svg>\n  );\n}\nexport function FlashlightOffIcon({ width, height, color }: TIconProps) {\n  return (\n    <Svg width={width || 24} height={height || 24} viewBox=\"0 0 24 24\" fill=\"none\">\n      <Path\n        d=\"M13.81 6.32501L17.675 10.19C18.009 10.1 18.317 9.92501 18.571 9.67201L20.692 7.55001L16.45 3.30801L14.328 5.42801C14.0798 5.67645 13.9011 5.98578 13.81 6.32501ZM15.743 11.085L12.914 8.25701L3.72205 17.45C3.53458 17.6375 3.42926 17.8918 3.42926 18.157C3.42926 18.4222 3.53458 18.6765 3.72205 18.864L5.13605 20.278C5.32357 20.4655 5.57788 20.5708 5.84305 20.5708C6.10821 20.5708 6.36252 20.4655 6.55005 20.278L15.743 11.086V11.085ZM12.914 4.01501L15.036 1.89301C15.4111 1.51806 15.9197 1.30743 16.45 1.30743C16.9804 1.30743 17.489 1.51806 17.864 1.89301L22.107 6.13601C22.482 6.51106 22.6926 7.01968 22.6926 7.55001C22.6926 8.08034 22.482 8.58895 22.107 8.96401L19.985 11.086C19.297 11.7762 18.3798 12.1903 17.407 12.25L7.96405 21.692C7.40146 22.2544 6.63854 22.5704 5.84305 22.5704C5.04755 22.5704 4.28463 22.2544 3.72205 21.692L2.30805 20.278C1.74563 19.7154 1.42969 18.9525 1.42969 18.157C1.42969 17.3615 1.74563 16.5986 2.30805 16.036L11.75 6.59301C11.8097 5.62025 12.2239 4.70309 12.914 4.01501ZM10.793 13.207C10.6056 13.0195 10.5003 12.7652 10.5003 12.5C10.5003 12.2348 10.6056 11.9805 10.793 11.793L12.207 10.379C12.2993 10.2835 12.4096 10.2073 12.5316 10.1549C12.6536 10.1025 12.7849 10.0749 12.9176 10.0738C13.0504 10.0726 13.1821 10.0979 13.305 10.1482C13.4279 10.1985 13.5395 10.2727 13.6334 10.3666C13.7273 10.4605 13.8016 10.5722 13.8519 10.6951C13.9021 10.8179 13.9275 10.9496 13.9263 11.0824C13.9251 11.2152 13.8976 11.3464 13.8451 11.4684C13.7927 11.5904 13.7166 11.7008 13.621 11.793L12.207 13.207C12.0195 13.3945 11.7652 13.4998 11.5 13.4998C11.2349 13.4998 10.9806 13.3945 10.793 13.207Z\"\n        fill={color}\n      />\n    </Svg>\n  );\n}\nexport function FlashlightOnIcon({ width, height, color }: TIconProps) {\n  return (\n    <Svg width={width || 24} height={height || 24} viewBox=\"0 0 24 24\" fill=\"none\">\n      <G clip-path=\"url(#clip0_104_39886)\">\n        <Path\n          d=\"M13.2399 13.12L13.6209 13.14C13.7615 13.1487 13.9024 13.1273 14.0341 13.0773C14.1659 13.0273 14.2854 12.9498 14.3849 12.85L16.5059 10.728L12.9709 7.19198L10.8489 9.31398C10.749 9.41322 10.6714 9.53259 10.6212 9.66415C10.5711 9.7957 10.5495 9.93643 10.5579 10.077L10.5789 10.457L13.2409 13.119L13.2399 13.12ZM11.5559 14.263L9.43488 12.143L2.36388 19.213C2.17641 19.4005 2.07109 19.6548 2.07109 19.92C2.07109 20.1851 2.17641 20.4395 2.36388 20.627L3.07088 21.335C3.25841 21.5224 3.51272 21.6278 3.77788 21.6278C4.04305 21.6278 4.29735 21.5224 4.48488 21.335L11.5559 14.263ZM9.43488 7.89998L11.5559 5.77998C11.7416 5.59418 11.9621 5.44678 12.2048 5.34622C12.4475 5.24566 12.7077 5.19391 12.9704 5.19391C13.2331 5.19391 13.4932 5.24566 13.7359 5.34622C13.9786 5.44678 14.1992 5.59418 14.3849 5.77998L17.9199 9.31498C18.2948 9.69003 18.5055 10.1986 18.5055 10.729C18.5055 11.2593 18.2948 11.7679 17.9199 12.143L15.7999 14.263C15.5018 14.5619 15.1438 14.7945 14.7495 14.9453C14.3552 15.0961 13.9334 15.1617 13.5119 15.138L5.89988 22.748C5.3373 23.3104 4.57437 23.6263 3.77888 23.6263C2.98339 23.6263 2.22046 23.3104 1.65788 22.748L0.950881 22.042C0.672251 21.7634 0.451227 21.4327 0.300432 21.0686C0.149636 20.7046 0.0720215 20.3145 0.0720215 19.9205C0.0720215 19.5265 0.149636 19.1363 0.300432 18.7723C0.451227 18.4083 0.672251 18.0776 0.950881 17.799L8.56188 10.188C8.53784 9.76637 8.60328 9.34445 8.75392 8.94994C8.90455 8.55544 9.13696 8.19727 9.43588 7.89898L9.43488 7.89998ZM17.9199 7.89998C17.7324 7.71245 17.6271 7.45814 17.6271 7.19298C17.6271 6.92781 17.7324 6.67351 17.9199 6.48598L20.0419 4.36498C20.1341 4.26947 20.2445 4.19329 20.3665 4.14088C20.4885 4.08847 20.6197 4.06088 20.7525 4.05973C20.8853 4.05857 21.0169 4.08388 21.1398 4.13416C21.2627 4.18444 21.3744 4.25869 21.4683 4.35258C21.5622 4.44648 21.6364 4.55813 21.6867 4.68102C21.737 4.80392 21.7623 4.9356 21.7611 5.06838C21.76 5.20116 21.7324 5.33238 21.68 5.45438C21.6276 5.57639 21.5514 5.68673 21.4559 5.77898L19.3349 7.89998C19.242 7.99296 19.1317 8.06671 19.0103 8.11704C18.8889 8.16736 18.7588 8.19326 18.6274 8.19326C18.496 8.19326 18.3658 8.16736 18.2444 8.11704C18.123 8.06671 18.0128 7.99296 17.9199 7.89998ZM19.7829 9.57398C19.7489 9.44712 19.7401 9.3148 19.7573 9.18458C19.7744 9.05436 19.817 8.92878 19.8826 8.81503C19.9483 8.70127 20.0357 8.60157 20.1399 8.5216C20.2441 8.44163 20.363 8.38298 20.4899 8.34898L22.4219 7.83098C22.549 7.79634 22.6816 7.78714 22.8123 7.80392C22.9429 7.8207 23.0689 7.86312 23.1831 7.92875C23.2973 7.99438 23.3975 8.08192 23.4777 8.18635C23.558 8.29077 23.6168 8.41003 23.6509 8.53727C23.6849 8.66451 23.6935 8.79722 23.6761 8.92778C23.6587 9.05834 23.6157 9.18418 23.5496 9.29807C23.4834 9.41197 23.3954 9.51167 23.2906 9.59145C23.1858 9.67123 23.0663 9.72952 22.9389 9.76298L21.0079 10.281C20.881 10.315 20.7487 10.3237 20.6185 10.3066C20.4883 10.2895 20.3627 10.2469 20.2489 10.1812C20.1352 10.1156 20.0355 10.0282 19.9555 9.92396C19.8755 9.81977 19.8169 9.70084 19.7829 9.57398ZM15.7989 5.77898C15.6114 5.59145 15.5061 5.33714 15.5061 5.07198C15.5061 4.80681 15.6114 4.55251 15.7989 4.36498L17.9199 2.24398C18.1074 2.05634 18.3618 1.95087 18.627 1.95078C18.8923 1.95068 19.1467 2.05597 19.3344 2.24348C19.522 2.43099 19.6275 2.68535 19.6276 2.95062C19.6277 3.21589 19.5224 3.47034 19.3349 3.65798L17.2129 5.77898C17.0254 5.96645 16.771 6.07176 16.5059 6.07176C16.2407 6.07176 15.9864 5.96645 15.7989 5.77898ZM14.1259 3.91698C13.999 3.88298 13.8801 3.82432 13.7759 3.74436C13.6717 3.66439 13.5843 3.56468 13.5186 3.45093C13.453 3.33717 13.4104 3.2116 13.3933 3.08138C13.3761 2.95115 13.3849 2.81884 13.4189 2.69198L13.9359 0.759978C13.9699 0.633121 14.0286 0.514206 14.1085 0.410021C14.1885 0.305837 14.2882 0.218424 14.402 0.152773C14.5157 0.0871216 14.6413 0.0445185 14.7715 0.0273958C14.9017 0.010273 15.034 0.018966 15.1609 0.0529784C15.2877 0.0869908 15.4067 0.145656 15.5108 0.225626C15.615 0.305595 15.7024 0.405302 15.7681 0.519054C15.8337 0.632806 15.8763 0.758375 15.8935 0.888591C15.9106 1.01881 15.9019 1.15112 15.8679 1.27798L15.3509 3.20998C15.3169 3.33684 15.2582 3.45577 15.1783 3.55996C15.0983 3.66415 14.9986 3.75157 14.8848 3.81723C14.7711 3.88288 14.6455 3.92548 14.5153 3.9426C14.3851 3.95971 14.2527 3.95101 14.1259 3.91698Z\"\n          fill={color}\n        />\n      </G>\n      <Defs>\n        <ClipPath id=\"clip0_104_39886\">\n          <Rect width=\"24\" height=\"24\" fill=\"white\" />\n        </ClipPath>\n      </Defs>\n    </Svg>\n  );\n}\nexport function CloseIcon({ width, height, color }: TIconProps) {\n  return (\n    <Svg width={width || 24} height={height || 24} viewBox=\"0 0 24 24\" fill=\"none\">\n      <G clip-path=\"url(#clip0_105_887)\">\n        <Path\n          d=\"M19 6.41L17.59 5L12 10.59L6.41 5L5 6.41L10.59 12L5 17.59L6.41 19L12 13.41L17.59 19L19 17.59L13.41 12L19 6.41Z\"\n          fill={color}\n        />\n      </G>\n      <Defs>\n        <ClipPath id=\"clip0_105_887\">\n          <Rect width=\"24\" height=\"24\" fill=\"white\" />\n        </ClipPath>\n      </Defs>\n    </Svg>\n  );\n}\nexport function HistoryIcon({ width, height, color }: TIconProps) {\n  return (\n    <Svg width={width || 24} height={height || 24} viewBox=\"0 0 24 24\" fill=\"none\">\n      <Path\n        d=\"M3 6C3 5.44772 3.44772 5 4 5H5C5.55228 5 6 5.44772 6 6V7C6 7.55228 5.55228 8 5 8H4C3.44772 8 3 7.55228 3 7V6ZM8.5 7C8.22386 7 8 6.77614 8 6.5C8 6.22386 8.22386 6 8.5 6H20.5C20.7761 6 21 6.22386 21 6.5C21 6.77614 20.7761 7 20.5 7H8.5ZM3 11C3 10.4477 3.44772 10 4 10H5C5.55228 10 6 10.4477 6 11V12C6 12.5523 5.55228 13 5 13H4C3.44772 13 3 12.5523 3 12V11ZM8.5 12C8.22386 12 8 11.7761 8 11.5C8 11.2239 8.22386 11 8.5 11H20.5C20.7761 11 21 11.2239 21 11.5C21 11.7761 20.7761 12 20.5 12H8.5ZM3 16C3 15.4477 3.44772 15 4 15H5C5.55228 15 6 15.4477 6 16V17C6 17.5523 5.55228 18 5 18H4C3.44772 18 3 17.5523 3 17V16ZM4 6V7H5V6H4ZM4 11V12H5V11H4ZM4 16V17H5V16H4ZM8.5 17C8.22386 17 8 16.7761 8 16.5C8 16.2239 8.22386 16 8.5 16H20.5C20.7761 16 21 16.2239 21 16.5C21 16.7761 20.7761 17 20.5 17H8.5Z\"\n        fill={color}\n      />\n    </Svg>\n  );\n}\nexport function IncomingArrowIcon({ width, height, color }: TIconProps) {\n  return (\n    <Svg width={width || 13} height={height || 13} viewBox=\"0 0 13 13\" fill=\"none\">\n      <Path\n        d=\"M1.70711 12H6.5C6.77614 12 7 12.2239 7 12.5C7 12.7761 6.77614 13 6.5 13H0.5C0.223858 13 0 12.7761 0 12.5V6.5C0 6.22386 0.223858 6 0.5 6C0.776142 6 1 6.22386 1 6.5V11.2929L12.1464 0.146447C12.3417 -0.0488155 12.6583 -0.0488155 12.8536 0.146447C13.0488 0.341709 13.0488 0.658291 12.8536 0.853553L1.70711 12Z\"\n        fill={color}\n      />\n    </Svg>\n  );\n}\nexport function OutgoingArrowIcon({ width, height, color }: TIconProps) {\n  return (\n    <Svg width={width || 13} height={height || 13} viewBox=\"0 0 12 12\" fill=\"none\">\n      <Path\n        d=\"M10.2929 1H5.5C5.22386 1 5 0.776142 5 0.5C5 0.223858 5.22386 0 5.5 0H11.5C11.7761 0 12 0.223858 12 0.5V6.5C12 6.77614 11.7761 7 11.5 7C11.2239 7 11 6.77614 11 6.5V1.70711L0.853553 11.8536C0.658291 12.0488 0.341709 12.0488 0.146447 11.8536C-0.0488155 11.6583 -0.0488155 11.3417 0.146447 11.1464L10.2929 1Z\"\n        fill={color}\n      />\n    </Svg>\n  );\n}\nexport function CheckmarkIcon({ width, height, color }: TIconProps) {\n  return (\n    <Svg width={width || 24} height={height || 24} viewBox=\"0 0 24 24\" fill=\"none\">\n      <Path\n        fill-rule=\"evenodd\"\n        clip-rule=\"evenodd\"\n        d=\"M20.187 7.22484L9.58039 17.8315L3.81421 12.0653L4.87487 11.0046L9.58039 15.7101L19.1263 6.16418L20.187 7.22484Z\"\n        fill={color}\n      />\n    </Svg>\n  );\n}\nexport function EyeIcon({ width, height, color }: TIconProps) {\n  return (\n    <Svg width={width || 24} height={height || 24} viewBox=\"0 0 24 24\" fill=\"none\">\n      <Path\n        d=\"M2.03382 11.8193C4.16809 6.31515 10.3603 3.58331 15.8644 5.71758C18.6654 6.80367 20.8801 9.01833 21.9662 11.8193C22.0113 11.9356 22.0113 12.0646 21.9662 12.1808C19.8319 17.685 13.6397 20.4169 8.13556 18.2826C5.33457 17.1965 3.11992 14.9818 2.03382 12.1808C1.98873 12.0646 1.98873 11.9356 2.03382 11.8193ZM8.49709 17.3502C13.4257 19.2613 18.9629 16.8681 20.9617 12.0001C19.9533 9.54674 17.9813 7.61095 15.5029 6.64994C10.5743 4.73885 5.03714 7.13206 3.03835 12C4.04671 14.4534 6.01868 16.3892 8.49709 17.3502ZM12 16.0001C9.79086 16.0001 8 14.2092 8 12.0001C8 9.79094 9.79086 8.00008 12 8.00008C14.2091 8.00008 16 9.79094 16 12.0001C16 14.2092 14.2091 16.0001 12 16.0001ZM12 15.0001C13.6569 15.0001 15 13.6569 15 12.0001C15 10.3432 13.6569 9.00008 12 9.00008C10.3431 9.00008 9 10.3432 9 12.0001C9 13.6569 10.3431 15.0001 12 15.0001Z\"\n        fill={color}\n      />\n    </Svg>\n  );\n}\nexport function LanguageIcon({ width, height, color }: TIconProps) {\n  return (\n    <Svg width={width || 24} height={height || 24} viewBox=\"0 0 24 24\" fill=\"none\">\n      <Path\n        fillRule=\"evenodd\"\n        clipRule=\"evenodd\"\n        d=\"M12 2.5C6.7533 2.5 2.5 6.7533 2.5 12C2.5 17.2461 6.75237 21.4991 11.9983 21.5H12.0017C17.2476 21.4991 21.5 17.2461 21.5 12C21.5 6.7533 17.2467 2.5 12 2.5ZM3.775 9.84717C3.59553 10.5347 3.5 11.2562 3.5 12C3.5 12.7438 3.59553 13.4653 3.775 14.1528V14H7.65292C7.55505 13.3561 7.5 12.6869 7.5 12C7.5 11.3131 7.55505 10.6439 7.65292 10H3.775V9.84717ZM4.04455 9H7.84245C8.1542 7.62781 8.64679 6.40035 9.18454 5.3994C9.55305 4.71349 9.94735 4.12531 10.3272 3.66455C7.43138 4.24248 5.06634 6.29177 4.04455 9ZM8.66535 10C8.5599 10.6425 8.5 11.3122 8.5 12C8.5 12.6878 8.5599 13.3575 8.66535 14H15.3347C15.4401 13.3575 15.5 12.6878 15.5 12C15.5 11.3122 15.4401 10.6425 15.3347 10H8.66535ZM15.1301 9H8.86995C9.16061 7.81473 9.59403 6.75016 10.0655 5.87267C10.4873 5.08752 10.9326 4.4652 11.3199 4.04705C11.5143 3.83725 11.6845 3.68915 11.8206 3.59736C11.9245 3.52729 11.9825 3.50758 12 3.50208C12.0175 3.50758 12.0755 3.52729 12.1794 3.59736C12.3155 3.68915 12.4857 3.83725 12.6801 4.04705C13.0674 4.4652 13.5127 5.08752 13.9345 5.87267C14.406 6.75016 14.8394 7.81473 15.1301 9ZM16.3471 10C16.445 10.6439 16.5 11.3131 16.5 12C16.5 12.6869 16.445 13.3561 16.3471 14H20.225V14.1528C20.4045 13.4653 20.5 12.7438 20.5 12C20.5 11.2562 20.4045 10.5347 20.225 9.84717V10H16.3471ZM19.9554 9H16.1575C15.8458 7.62781 15.3532 6.40035 14.8155 5.3994C14.447 4.71349 14.0526 4.12531 13.6728 3.66455C16.5686 4.24248 18.9337 6.29177 19.9554 9ZM10.3272 20.3355C7.43138 19.7575 5.06634 17.7082 4.04455 15H7.84245C8.1542 16.3722 8.64679 17.5997 9.18454 18.6006C9.55305 19.2865 9.94735 19.8747 10.3272 20.3355ZM10.0655 18.1273C9.59403 17.2498 9.16061 16.1853 8.86995 15H15.1301C14.8394 16.1853 14.406 17.2498 13.9345 18.1273C13.5127 18.9125 13.0674 19.5348 12.6801 19.953C12.4857 20.1627 12.3155 20.3108 12.1794 20.4026C12.0755 20.4727 12.0175 20.4924 12 20.4979C11.9825 20.4924 11.9245 20.4727 11.8206 20.4026C11.6845 20.3108 11.5143 20.1627 11.3199 19.953C10.9326 19.5348 10.4873 18.9125 10.0655 18.1273ZM14.8155 18.6006C15.3532 17.5997 15.8458 16.3722 16.1575 15H19.9554C18.9337 17.7082 16.5686 19.7575 13.6728 20.3355C14.0526 19.8747 14.447 19.2865 14.8155 18.6006Z\"\n        fill={color}\n      />\n    </Svg>\n  );\n}\nexport function AboutIcon({ width, height, color }: TIconProps) {\n  return (\n    <Svg width={width || 24} height={height || 24} viewBox=\"0 0 24 24\" fill=\"none\">\n      <Path\n        d=\"M13 16H14.5C14.7761 16 15 16.2239 15 16.5C15 16.7761 14.7761 17 14.5 17H10.5C10.2239 17 10 16.7761 10 16.5C10 16.2239 10.2239 16 10.5 16H12V11H10.5C10.2239 11 10 10.7761 10 10.5C10 10.2239 10.2239 10 10.5 10H12.5C12.7761 10 13 10.2239 13 10.5V16ZM12 22C6.47715 22 2 17.5228 2 12C2 6.47715 6.47715 2 12 2C17.5228 2 22 6.47715 22 12C22 17.5228 17.5228 22 12 22ZM12 21C16.9706 21 21 16.9706 21 12C21 7.02944 16.9706 3 12 3C7.02944 3 3 7.02944 3 12C3 16.9706 7.02944 21 12 21ZM11.5 7H12.5C12.7761 7 13 7.22386 13 7.5V8.5C13 8.77614 12.7761 9 12.5 9H11.5C11.2239 9 11 8.77614 11 8.5V7.5C11 7.22386 11.2239 7 11.5 7Z\"\n        fill={color}\n      />\n    </Svg>\n  );\n}\nexport function BackspaceIcon({ width, height, color }: TIconProps) {\n  return (\n    <Svg width={width || 24} height={height || 24} viewBox=\"0 0 24 24\" fill=\"none\">\n      <Path\n        d=\"M14.3855 12.0034L17.2139 14.8319L16.5068 15.539L13.6783 12.7105L10.8499 15.5389L10.1428 14.8318L12.9712 12.0034L10.1428 9.17505L10.85 8.46794L13.6783 11.2963L16.5068 8.4679L17.2139 9.175L14.3855 12.0034Z\"\n        fill={color}\n      />\n      <Path\n        fill-rule=\"evenodd\"\n        clip-rule=\"evenodd\"\n        d=\"M7.38559 4.5H21.4999V19.5H7.38559L1.87964 12L7.38559 4.5ZM7.89201 5.5L3.12018 12L7.892 18.5H20.4999V5.5H7.89201Z\"\n        fill={color}\n      />\n    </Svg>\n  );\n}\nexport function SandClockIcon({ width, height, color }: TIconProps) {\n  return (\n    <Svg width={width || 24} height={height || 24} viewBox=\"0 0 24 24\" fill=\"none\">\n      <Path\n        fill-rule=\"evenodd\"\n        clip-rule=\"evenodd\"\n        d=\"M4.25 2.25H19.75V6.34495L13.1524 12L19.75 17.655V21.75H4.25V17.655L10.8476 12L4.25 6.34495V2.25ZM12 11.0122L16.3892 7.25H7.61078L12 11.0122ZM18 5.75V5.86933L18.25 5.65505V3.75H5.75V5.65505L6 5.86933V5.75H18ZM6 18.1307L5.75 18.345V20.25H18.25V18.345L18 18.1307V18.25H6V18.1307ZM7.61078 16.75H16.3892L12 12.9878L7.61078 16.75Z\"\n        fill={color}\n      />\n    </Svg>\n  );\n}\nexport function SearchIcon({ width, height, color }: TIconProps) {\n  return (\n    <Svg width={width || 24} height={height || 24} viewBox=\"0 0 24 24\" fill=\"none\">\n      <Path\n        fill-rule=\"evenodd\"\n        clip-rule=\"evenodd\"\n        d=\"M11 2.25C6.16751 2.25 2.25 6.16751 2.25 11C2.25 15.8325 6.16751 19.75 11 19.75C13.1462 19.75 15.112 18.9773 16.6342 17.6949L21 22.0607L22.0607 21L17.6949 16.6342C18.9773 15.112 19.75 13.1462 19.75 11C19.75 6.16751 15.8325 2.25 11 2.25ZM3.75 11C3.75 6.99594 6.99594 3.75 11 3.75C15.0041 3.75 18.25 6.99594 18.25 11C18.25 15.0041 15.0041 18.25 11 18.25C6.99594 18.25 3.75 15.0041 3.75 11Z\"\n        fill={color}\n      />\n    </Svg>\n  );\n}\nexport function ReceiveIcon({ width, height, color }: TIconProps) {\n  return (\n    <Svg width={width || 24} height={height || 24} viewBox=\"0 0 24 24\" fill=\"none\">\n      <Path\n        d=\"M11 15.2929V4.5C11 4.22386 11.2239 4 11.5 4C11.7761 4 12 4.22386 12 4.5V15.2929L15.1464 12.1464C15.3417 11.9512 15.6583 11.9512 15.8536 12.1464C16.0488 12.3417 16.0488 12.6583 15.8536 12.8536L11.8536 16.8536C11.6583 17.0488 11.3417 17.0488 11.1464 16.8536L7.14645 12.8536C6.95118 12.6583 6.95118 12.3417 7.14645 12.1464C7.34171 11.9512 7.65829 11.9512 7.85355 12.1464L11 15.2929ZM4.5 20C4.22386 20 4 19.7761 4 19.5C4 19.2239 4.22386 19 4.5 19H18.5C18.7761 19 19 19.2239 19 19.5C19 19.7761 18.7761 20 18.5 20H4.5Z\"\n        fill={color}\n      />\n    </Svg>\n  );\n}\nexport function SendIcon({ width, height, color, disabled }: IExtendedIconProps) {\n  return (\n    <Svg\n      width={width || 24}\n      height={height || 24}\n      style={{ opacity: disabled ? 0.5 : 1 }}\n      viewBox=\"0 0 24 24\"\n      fill=\"none\"\n    >\n      <Path\n        d=\"M13 5.70711V16.5C13 16.7761 12.7761 17 12.5 17C12.2239 17 12 16.7761 12 16.5V5.70711L8.85355 8.85355C8.65829 9.04882 8.34171 9.04882 8.14645 8.85355C7.95118 8.65829 7.95118 8.34171 8.14645 8.14645L12.1464 4.14645C12.3417 3.95118 12.6583 3.95118 12.8536 4.14645L16.8536 8.14645C17.0488 8.34171 17.0488 8.65829 16.8536 8.85355C16.6583 9.04882 16.3417 9.04882 16.1464 8.85355L13 5.70711ZM4.5 20C4.22386 20 4 19.7761 4 19.5C4 19.2239 4.22386 19 4.5 19H20.5C20.7761 19 21 19.2239 21 19.5C21 19.7761 20.7761 20 20.5 20H4.5Z\"\n        fill={color}\n      />\n    </Svg>\n  );\n}\nexport function ShareIcon({ width, height, color }: TIconProps) {\n  return (\n    <Svg width={width || 24} height={height || 24} viewBox=\"0 0 24 24\" fill=\"none\">\n      <G clip-path=\"url(#clip0_105_3144)\">\n        <Path\n          d=\"M18 16.08C17.24 16.08 16.56 16.38 16.04 16.85L8.91 12.7C8.96 12.47 9 12.24 9 12C9 11.76 8.96 11.53 8.91 11.3L15.96 7.19C16.5 7.69 17.21 8 18 8C19.66 8 21 6.66 21 5C21 3.34 19.66 2 18 2C16.34 2 15 3.34 15 5C15 5.24 15.04 5.47 15.09 5.7L8.04 9.81C7.5 9.31 6.79 9 6 9C4.34 9 3 10.34 3 12C3 13.66 4.34 15 6 15C6.79 15 7.5 14.69 8.04 14.19L15.16 18.35C15.11 18.56 15.08 18.78 15.08 19C15.08 20.61 16.39 21.92 18 21.92C19.61 21.92 20.92 20.61 20.92 19C20.92 17.39 19.61 16.08 18 16.08ZM18 4C18.55 4 19 4.45 19 5C19 5.55 18.55 6 18 6C17.45 6 17 5.55 17 5C17 4.45 17.45 4 18 4ZM6 13C5.45 13 5 12.55 5 12C5 11.45 5.45 11 6 11C6.55 11 7 11.45 7 12C7 12.55 6.55 13 6 13ZM18 20.02C17.45 20.02 17 19.57 17 19.02C17 18.47 17.45 18.02 18 18.02C18.55 18.02 19 18.47 19 19.02C19 19.57 18.55 20.02 18 20.02Z\"\n          fill={color}\n        />\n      </G>\n      <Defs>\n        <ClipPath id=\"clip0_105_3144\">\n          <Rect width=\"24\" height=\"24\" fill=\"white\" />\n        </ClipPath>\n      </Defs>\n    </Svg>\n  );\n}\nexport function CoinIcon({ width, height, color }: TIconProps) {\n  return (\n    <Svg width={width || 24} height={height || 24} viewBox=\"0 0 24 24\" fill=\"none\">\n      <Path\n        d=\"M12 6C7.03 6 2 7.546 2 10.5V14.5C2 17.454 7.03 19 12 19C16.97 19 22 17.454 22 14.5V10.5C22 7.546 16.97 6 12 6ZM4 14.5V13.303C4.63334 13.6617 5.30399 13.9501 6 14.163V16.044C4.688 15.53 4 14.918 4 14.5ZM16 14.648V16.619C15.133 16.798 14.133 16.929 13 16.977V14.977C14.0064 14.9369 15.0088 14.827 16 14.648ZM11 16.978C9.99201 16.9394 8.98877 16.8197 8 16.62V14.649C8.959 14.823 9.972 14.936 11 14.979V16.978ZM18 16.044V14.163C18.6962 13.9505 19.3669 13.6621 20 13.303V14.5C20 14.918 19.313 15.53 18 16.044ZM12 13C6.823 13 4 11.349 4 10.5C4 9.651 6.823 8 12 8C17.177 8 20 9.651 20 10.5C20 11.349 17.177 13 12 13Z\"\n        fill={color}\n      />\n    </Svg>\n  );\n}\nexport function ScanQRIcon({ width, height, color }: TIconProps) {\n  return (\n    <Svg width={width || 24} height={height || 24} viewBox=\"0 0 24 24\" fill=\"none\">\n      <Path\n        d=\"M16.1667 6C16.0746 6 16 6.07462 16 6.16667V7.83333C16 7.92538 16.0746 8 16.1667 8H17.8333C17.9254 8 18 7.92538 18 7.83333V6.16667C18 6.07462 17.9254 6 17.8333 6H16.1667ZM16 18V17.5C16 17.2239 16.2239 17 16.5 17C16.7761 17 17 17.2239 17 17.5V18H18V17.5C18 17.2239 18.2239 17 18.5 17C18.7761 17 19 17.2239 19 17.5V18.5C19 18.7761 18.7761 19 18.5 19H14.5C14.2239 19 14 18.7761 14 18.5V17.5C14 17.2239 14.2239 17 14.5 17C14.7761 17 15 17.2239 15 17.5V18H16ZM13 11H13.5C13.7761 11 14 11.2239 14 11.5C14 11.7761 13.7761 12 13.5 12H11.5C11.2239 12 11 11.7761 11 11.5C11 11.2239 11.2239 11 11.5 11H12V10H10.5C10.2239 10 10 9.77614 10 9.5C10 9.22386 10.2239 9 10.5 9H13.5C13.7761 9 14 9.22386 14 9.5C14 9.77614 13.7761 10 13.5 10H13V11ZM18 12H17.5C17.2239 12 17 11.7761 17 11.5C17 11.2239 17.2239 11 17.5 11H18V10.5C18 10.2239 18.2239 10 18.5 10C18.7761 10 19 10.2239 19 10.5V12.5C19 12.7761 18.7761 13 18.5 13C18.2239 13 18 12.7761 18 12.5V12ZM13 14H12.5C12.2239 14 12 13.7761 12 13.5C12 13.2239 12.2239 13 12.5 13H13.5C13.7761 13 14 13.2239 14 13.5V15.5C14 15.7761 13.7761 16 13.5 16H10.5C10.2239 16 10 15.7761 10 15.5C10 15.2239 10.2239 15 10.5 15H13V14ZM16.1667 5H17.8333C18.4777 5 19 5.52233 19 6.16667V7.83333C19 8.47767 18.4777 9 17.8333 9H16.1667C15.5223 9 15 8.47767 15 7.83333V6.16667C15 5.52233 15.5223 5 16.1667 5ZM6.16667 5H7.83333C8.47767 5 9 5.52233 9 6.16667V7.83333C9 8.47767 8.47767 9 7.83333 9H6.16667C5.52233 9 5 8.47767 5 7.83333V6.16667C5 5.52233 5.52233 5 6.16667 5ZM6.16667 6C6.07462 6 6 6.07462 6 6.16667V7.83333C6 7.92538 6.07462 8 6.16667 8H7.83333C7.92538 8 8 7.92538 8 7.83333V6.16667C8 6.07462 7.92538 6 7.83333 6H6.16667ZM6.16667 15H7.83333C8.47767 15 9 15.5223 9 16.1667V17.8333C9 18.4777 8.47767 19 7.83333 19H6.16667C5.52233 19 5 18.4777 5 17.8333V16.1667C5 15.5223 5.52233 15 6.16667 15ZM6.16667 16C6.07462 16 6 16.0746 6 16.1667V17.8333C6 17.9254 6.07462 18 6.16667 18H7.83333C7.92538 18 8 17.9254 8 17.8333V16.1667C8 16.0746 7.92538 16 7.83333 16H6.16667ZM13 6H10.5C10.2239 6 10 5.77614 10 5.5C10 5.22386 10.2239 5 10.5 5H13.5C13.7761 5 14 5.22386 14 5.5V7.5C14 7.77614 13.7761 8 13.5 8C13.2239 8 13 7.77614 13 7.5V6ZM10.5 8C10.2239 8 10 7.77614 10 7.5C10 7.22386 10.2239 7 10.5 7H11.5C11.7761 7 12 7.22386 12 7.5C12 7.77614 11.7761 8 11.5 8H10.5ZM5.5 14C5.22386 14 5 13.7761 5 13.5C5 13.2239 5.22386 13 5.5 13H7.5C7.77614 13 8 13.2239 8 13.5C8 13.7761 7.77614 14 7.5 14H5.5ZM9.5 14C9.22386 14 9 13.7761 9 13.5C9 13.2239 9.22386 13 9.5 13H10.5C10.7761 13 11 13.2239 11 13.5C11 13.7761 10.7761 14 10.5 14H9.5ZM11 18V18.5C11 18.7761 10.7761 19 10.5 19C10.2239 19 10 18.7761 10 18.5V17.5C10 17.2239 10.2239 17 10.5 17H12.5C12.7761 17 13 17.2239 13 17.5C13 17.7761 12.7761 18 12.5 18H11ZM9 11H9.5C9.77614 11 10 11.2239 10 11.5C10 11.7761 9.77614 12 9.5 12H8.5C8.22386 12 8 11.7761 8 11.5V11H7.5C7.22386 11 7 10.7761 7 10.5C7 10.2239 7.22386 10 7.5 10H8.5C8.77614 10 9 10.2239 9 10.5V11ZM5 10.5C5 10.2239 5.22386 10 5.5 10C5.77614 10 6 10.2239 6 10.5V11.5C6 11.7761 5.77614 12 5.5 12C5.22386 12 5 11.7761 5 11.5V10.5ZM15 10.5C15 10.2239 15.2239 10 15.5 10C15.7761 10 16 10.2239 16 10.5V12.5C16 12.7761 15.7761 13 15.5 13C15.2239 13 15 12.7761 15 12.5V10.5ZM17 15V14.5C17 14.2239 17.2239 14 17.5 14H18.5C18.7761 14 19 14.2239 19 14.5C19 14.7761 18.7761 15 18.5 15H18V15.5C18 15.7761 17.7761 16 17.5 16H15.5C15.2239 16 15 15.7761 15 15.5V14.5C15 14.2239 15.2239 14 15.5 14C15.7761 14 16 14.2239 16 14.5V15H17ZM3 6.5C3 6.77614 2.77614 7 2.5 7C2.22386 7 2 6.77614 2 6.5V4.5C2 3.11929 3.11929 2 4.5 2H6.5C6.77614 2 7 2.22386 7 2.5C7 2.77614 6.77614 3 6.5 3H4.5C3.67157 3 3 3.67157 3 4.5V6.5ZM17.5 3C17.2239 3 17 2.77614 17 2.5C17 2.22386 17.2239 2 17.5 2H19.5C20.8807 2 22 3.11929 22 4.5V6.5C22 6.77614 21.7761 7 21.5 7C21.2239 7 21 6.77614 21 6.5V4.5C21 3.67157 20.3284 3 19.5 3H17.5ZM6.5 21C6.77614 21 7 21.2239 7 21.5C7 21.7761 6.77614 22 6.5 22H4.5C3.11929 22 2 20.8807 2 19.5V17.5C2 17.2239 2.22386 17 2.5 17C2.77614 17 3 17.2239 3 17.5V19.5C3 20.3284 3.67157 21 4.5 21H6.5ZM21 17.5C21 17.2239 21.2239 17 21.5 17C21.7761 17 22 17.2239 22 17.5V19.5C22 20.8807 20.8807 22 19.5 22H17.5C17.2239 22 17 21.7761 17 21.5C17 21.2239 17.2239 21 17.5 21H19.5C20.3284 21 21 20.3284 21 19.5V17.5Z\"\n        fill={color}\n      />\n    </Svg>\n  );\n}\nexport function BookIcon({ width, height, color }: TIconProps) {\n  return (\n    <Svg width={width || 24} height={height || 24} viewBox=\"0 0 24 24\" fill=\"none\">\n      <Path\n        d=\"M4 4.5C4 3.11929 5.11929 2 6.5 2H19.5C19.7761 2 20 2.22386 20 2.5C20 2.77614 19.7761 3 19.5 3H6.5C5.67157 3 5 3.67157 5 4.5C5 5.32843 5.67157 6 6.5 6H17.5C18.8807 6 20 7.11929 20 8.5V19.5C20 20.8807 18.8807 22 17.5 22H8.5C6.01472 22 4 19.9853 4 17.5V4.5ZM5 17.5C5 19.433 6.567 21 8.5 21H17.5C18.3284 21 19 20.3284 19 19.5V8.5C19 7.67157 18.3284 7 17.5 7H6.5C5.9372 7 5.41783 6.81403 5 6.50018V17.5ZM6.5 5C6.22386 5 6 4.77614 6 4.5C6 4.22386 6.22386 4 6.5 4H19.5C19.7761 4 20 4.22386 20 4.5C20 4.77614 19.7761 5 19.5 5H6.5ZM8 10.5C8 10.2239 8.22386 10 8.5 10H15.5C15.7761 10 16 10.2239 16 10.5V13.5C16 13.7761 15.7761 14 15.5 14H8.5C8.22386 14 8 13.7761 8 13.5V10.5ZM9 13H15V11H9V13ZM8.5 16C8.22386 16 8 15.7761 8 15.5C8 15.2239 8.22386 15 8.5 15H15.5C15.7761 15 16 15.2239 16 15.5C16 15.7761 15.7761 16 15.5 16H8.5ZM8.5 18C8.22386 18 8 17.7761 8 17.5C8 17.2239 8.22386 17 8.5 17H12.5C12.7761 17 13 17.2239 13 17.5C13 17.7761 12.7761 18 12.5 18H8.5Z\"\n        fill={color}\n      />\n    </Svg>\n  );\n}\nexport function FlagIcon({ width, height, color }: TIconProps) {\n  return (\n    <Svg width={width || 24} height={height || 24} viewBox=\"0 0 24 24\" fill=\"none\">\n      <Path\n        d=\"M13 5.00003H18.5C18.912 5.00003 19.1472 5.47041 18.9 5.80003L16.125 9.50003L18.9 13.2C19.1472 13.5296 18.912 14 18.5 14H13.5C12.6716 14 12 13.3285 12 12.5C12 12.2239 11.7761 12 11.5 12H6V20.5C6 20.7762 5.77614 21 5.5 21C5.22386 21 5 20.7762 5 20.5V4.49268C5 3.66425 5.67157 2.99268 6.5 2.99268H11.5C12.3284 2.99268 13 3.66425 13 4.49268V5.00003ZM13 6.00003V7.50003C13 7.77617 12.7761 8.00003 12.5 8.00003C12.2239 8.00003 12 7.77617 12 7.50003V5.50201C12 5.50135 12 5.50069 12 5.50003C12 5.49936 12 5.4987 12 5.49804V4.49268C12 4.21653 11.7761 3.99268 11.5 3.99268H6.5C6.22386 3.99268 6 4.21653 6 4.49268V11H11.5C12.3284 11 13 11.6716 13 12.5C13 12.7762 13.2239 13 13.5 13H17.5L15.1 9.80003C14.9667 9.62225 14.9667 9.3778 15.1 9.20003L17.5 6.00003H13Z\"\n        fill={color}\n      />\n    </Svg>\n  );\n}\nexport function VerifiedIcon({ width, height, color }: TIconProps) {\n  return (\n    <Svg width={width || 24} height={height || 24} viewBox=\"0 0 24 24\" fill=\"none\">\n      <Path\n        d=\"M21.5609 10.7386L20.2009 9.15859C19.9409 8.85859 19.7309 8.29859 19.7309 7.89859V6.19859C19.7309 5.13859 18.8609 4.26859 17.8009 4.26859H16.1009C15.7109 4.26859 15.1409 4.05859 14.8409 3.79859L13.2609 2.43859C12.5709 1.84859 11.4409 1.84859 10.7409 2.43859L9.17086 3.80859C8.87086 4.05859 8.30086 4.26859 7.91086 4.26859H6.18086C5.12086 4.26859 4.25086 5.13859 4.25086 6.19859V7.90859C4.25086 8.29859 4.04086 8.85859 3.79086 9.15859L2.44086 10.7486C1.86086 11.4386 1.86086 12.5586 2.44086 13.2486L3.79086 14.8386C4.04086 15.1386 4.25086 15.6986 4.25086 16.0886V17.7986C4.25086 18.8586 5.12086 19.7286 6.18086 19.7286H7.91086C8.30086 19.7286 8.87086 19.9386 9.17086 20.1986L10.7509 21.5586C11.4409 22.1486 12.5709 22.1486 13.2709 21.5586L14.8509 20.1986C15.1509 19.9386 15.7109 19.7286 16.1109 19.7286H17.8109C18.8709 19.7286 19.7409 18.8586 19.7409 17.7986V16.0986C19.7409 15.7086 19.9509 15.1386 20.2109 14.8386L21.5709 13.2586C22.1509 12.5686 22.1509 11.4286 21.5609 10.7386ZM16.1609 10.1086L11.3309 14.9386C11.1909 15.0786 11.0009 15.1586 10.8009 15.1586C10.6009 15.1586 10.4109 15.0786 10.2709 14.9386L7.85086 12.5186C7.56086 12.2286 7.56086 11.7486 7.85086 11.4586C8.14086 11.1686 8.62086 11.1686 8.91086 11.4586L10.8009 13.3486L15.1009 9.04859C15.3909 8.75859 15.8709 8.75859 16.1609 9.04859C16.4509 9.33859 16.4509 9.81859 16.1609 10.1086Z\"\n        fill={color}\n      />\n    </Svg>\n  );\n}\nexport function LinkIcon({ width, height, color }: TIconProps) {\n  return (\n    <Svg width={width || 24} height={height || 24} viewBox=\"0 0 24 24\" fill=\"none\">\n      <Path\n        d=\"M12.1505 11.8472C11.9558 11.6514 11.9566 11.3348 12.1524 11.1401C12.3482 10.9454 12.6648 10.9462 12.8595 11.142C14.1565 12.4461 14.1548 14.5535 12.8557 15.8554L10.6879 18.0279C9.39473 19.3238 7.29786 19.3326 5.99389 18.0475C4.69107 16.7632 4.67607 14.6665 5.96006 13.364L8.14351 11.149C8.33737 10.9524 8.65394 10.9501 8.8506 11.144C9.04725 11.3378 9.04952 11.6544 8.85566 11.8511L6.6722 14.066C5.77594 14.9752 5.78641 16.4388 6.6956 17.3351C7.60815 18.2344 9.07525 18.2283 9.98002 17.3215L12.1478 15.1491C13.0579 14.237 13.0591 12.7608 12.1505 11.8472ZM11.6874 12.153C11.8822 12.3488 11.8813 12.6654 11.6855 12.8601C11.4897 13.0549 11.1732 13.054 10.9784 12.8582C9.68118 11.5539 9.68151 9.44657 10.9792 8.14267L13.0678 6.04398C14.4149 4.69037 16.5977 4.66402 17.9771 5.98473C18.0227 6.02838 18.067 6.07334 18.11 6.11954C19.3451 7.44679 19.2705 9.52401 17.9432 10.7591L15.679 12.8662C15.4768 13.0543 15.1605 13.043 14.9723 12.8408C14.7842 12.6386 14.7956 12.3223 14.9977 12.1342L17.262 10.0271C18.1849 9.1682 18.2368 7.72373 17.378 6.80079C17.3481 6.76866 17.3172 6.73739 17.2855 6.70704C16.2996 5.76306 14.7395 5.7819 13.7766 6.74939L11.688 8.84807C10.7785 9.76193 10.7783 11.2389 11.6874 12.153Z\"\n        fill={color}\n      />\n    </Svg>\n  );\n}\nexport function EyeClosedIcon({ width, height, color }: TIconProps) {\n  return (\n    <Svg width={width || 24} height={height || 24} viewBox=\"0 0 24 24\" fill=\"none\">\n      <Path\n        fill-rule=\"evenodd\"\n        clip-rule=\"evenodd\"\n        d=\"M3.25008 3.79285L6.04259 6.58536C7.47037 5.40993 9.41385 4.49998 12.0001 4.49998C15.694 4.49998 18.0766 6.35627 19.5182 8.19106C20.2366 9.10539 20.7249 10.0174 21.0338 10.7002C21.1885 11.0422 21.299 11.3284 21.3714 11.5311C21.4076 11.6324 21.4343 11.713 21.4523 11.7694C21.4613 11.7976 21.4681 11.8198 21.4728 11.8354C21.4735 11.8379 21.4742 11.8402 21.4749 11.8423L21.4759 11.8457C21.4768 11.8489 21.4777 11.8517 21.4784 11.8541C21.479 11.8563 21.4796 11.8582 21.48 11.8596L21.4807 11.8621C21.4808 11.8624 21.4808 11.8626 21.0001 12C21.4808 12.1374 21.4808 12.1376 21.4807 12.1379L21.48 12.1404C21.4796 12.1418 21.479 12.1437 21.4784 12.146C21.4779 12.1477 21.4773 12.1496 21.4766 12.1517L21.4749 12.1576L21.4738 12.1614L21.4728 12.1646C21.4681 12.1802 21.4613 12.2024 21.4523 12.2306C21.4343 12.287 21.4076 12.3676 21.3714 12.469C21.299 12.6716 21.1885 12.9578 21.0338 13.2998C20.7249 13.9826 20.2366 14.8946 19.5182 15.8089C18.9473 16.5356 18.2287 17.2656 17.3396 17.8824L19.9572 20.5L19.2501 21.2071L16.4628 18.4198C16.4605 18.4211 16.4581 18.4223 16.4558 18.4236L15.7126 17.6804C15.715 17.6792 15.7174 17.678 15.7198 17.6768L6.00999 7.96697C6.0082 7.96878 6.00641 7.97059 6.00462 7.97239L5.29775 7.26552C5.29954 7.26371 5.30133 7.26191 5.30312 7.2601L2.54297 4.49995L3.25008 3.79285ZM18.7319 15.1911C18.1808 15.8925 17.4863 16.59 16.6198 17.1626L13.8549 14.3977L14.1571 14.085C14.6785 13.5457 15.0001 12.8099 15.0001 12C15.0001 10.3432 13.657 8.99998 12.0001 8.99998C11.1902 8.99998 10.4544 9.32158 9.91509 9.84298L9.60246 10.1453L6.75305 7.29582C8.02466 6.27298 9.73285 5.49998 12.0001 5.49998C15.3062 5.49998 17.4236 7.14368 18.7319 8.80889C19.3885 9.64456 19.8378 10.4826 20.1227 11.1123C20.2648 11.4266 20.3653 11.6872 20.4296 11.8674C20.4478 11.9183 20.463 11.9627 20.4756 12C20.463 12.0373 20.4478 12.0817 20.4296 12.1326C20.3653 12.3128 20.2648 12.5734 20.1227 12.8877C19.8378 13.5174 19.3885 14.3554 18.7319 15.1911ZM13.4382 13.39L13.1477 13.6905L10.3097 10.8525L10.6102 10.5619C10.9705 10.2136 11.4599 9.99997 12.0001 9.99997C13.1047 9.99997 14.0001 10.8954 14.0001 12C14.0001 12.5403 13.7866 13.0296 13.4382 13.39Z\"\n        fill={color}\n      />\n      <Path\n        d=\"M4.6275 8.00964C4.57791 8.07012 4.52936 8.13063 4.48183 8.19112C3.76343 9.10545 3.27519 10.0174 2.96631 10.7002C2.81159 11.0422 2.7011 11.3284 2.62873 11.5311C2.59252 11.6324 2.5658 11.713 2.54781 11.7694C2.53882 11.7976 2.532 11.8198 2.52727 11.8354C2.5249 11.8433 2.52306 11.8495 2.52172 11.8541C2.52105 11.8563 2.52051 11.8582 2.5201 11.8596L2.51957 11.8615L2.51937 11.8621C2.5193 11.8624 2.51923 11.8626 2.99999 12L2.51923 11.8626L2.47998 12L2.51923 12.1374L2.99999 12C2.51923 12.1374 2.5193 12.1376 2.51937 12.1379L2.51957 12.1386L2.5201 12.1404C2.52051 12.1418 2.52105 12.1437 2.52172 12.146C2.52306 12.1505 2.5249 12.1567 2.52727 12.1646C2.532 12.1802 2.53882 12.2024 2.54781 12.2306C2.5658 12.287 2.59252 12.3676 2.62873 12.469C2.7011 12.6716 2.81159 12.9578 2.96631 13.2998C3.27519 13.9826 3.76343 14.8946 4.48183 15.8089C5.92345 17.6437 8.30611 19.5 12 19.5C13.3257 19.5 14.4824 19.2609 15.4874 18.8696L14.7049 18.087C13.9068 18.347 13.0087 18.5 12 18.5C8.69387 18.5 6.57652 16.8563 5.26815 15.1911C4.61155 14.3554 4.16229 13.5174 3.87742 12.8877C3.73526 12.5734 3.63481 12.3128 3.57047 12.1326C3.5523 12.0817 3.53703 12.0373 3.52452 12C3.53703 11.9627 3.5523 11.9183 3.57047 11.8674C3.63481 11.6872 3.73526 11.4266 3.87742 11.1123C4.16229 10.4826 4.61155 9.64462 5.26815 8.80895C5.29131 8.77947 5.31473 8.75 5.3384 8.72054L4.6275 8.00964Z\"\n        fill={color}\n      />\n      <Path\n        d=\"M21 11.9999L21.4807 11.8625L21.52 11.9999L21.4807 12.1373L21 11.9999Z\"\n        fill={color}\n      />\n    </Svg>\n  );\n}\n\nexport function LeftArrow({ width, height, color }: TIconProps) {\n  return (\n    <Svg width={width || 24} height={height || 24} viewBox=\"0 0 24 24\" fill=\"none\">\n      <Path\n        d=\"M21.0001 11H6.41406L11.7071 5.70697L10.2931 4.29297L2.58606 12L10.2931 19.707L11.7071 18.293L6.41406 13H21.0001V11Z\"\n        fill={color}\n      />\n    </Svg>\n  );\n}\nexport function EcashIcon({ width, height, color }: TIconProps) {\n  return (\n    <Svg width={width || 24} height={height || 24} viewBox=\"0 0 24 24\" fill=\"none\">\n      <Path\n        d=\"M6.75 11.25C6.33579 11.25 6 11.5858 6 12C6 12.4142 6.33579 12.75 6.75 12.75C7.16421 12.75 7.5 12.4142 7.5 12C7.5 11.5858 7.16421 11.25 6.75 11.25Z\"\n        fill={color}\n      />\n      <Path\n        d=\"M16.5 12C16.5 11.5858 16.8358 11.25 17.25 11.25C17.6642 11.25 18 11.5858 18 12C18 12.4142 17.6642 12.75 17.25 12.75C16.8358 12.75 16.5 12.4142 16.5 12Z\"\n        fill={color}\n      />\n      <Path\n        fillRule=\"evenodd\"\n        clipRule=\"evenodd\"\n        d=\"M12 9.75C10.7574 9.75 9.75 10.7574 9.75 12C9.75 13.2426 10.7574 14.25 12 14.25C13.2426 14.25 14.25 13.2426 14.25 12C14.25 10.7574 13.2426 9.75 12 9.75ZM10.75 12C10.75 11.3096 11.3096 10.75 12 10.75C12.6904 10.75 13.25 11.3096 13.25 12C13.25 12.6904 12.6904 13.25 12 13.25C11.3096 13.25 10.75 12.6904 10.75 12Z\"\n        fill={color}\n      />\n      <Path\n        fillRule=\"evenodd\"\n        clipRule=\"evenodd\"\n        d=\"M21.5 6.5H2.5V17.5H21.5V6.5ZM3.5 16.5V7.5H20.5V16.5H3.5Z\"\n        fill={color}\n      />\n    </Svg>\n  );\n}\nexport function MenuDotsIcon({ width, height, color }: TIconProps) {\n  return (\n    <Svg width={width || 24} height={height || 24} viewBox=\"0 0 24 24\" fill=\"none\">\n      <Path\n        d=\"M11.5 5C11.2239 5 11 5.22386 11 5.5V6.5C11 6.77614 11.2239 7 11.5 7H12.5C12.7761 7 13 6.77614 13 6.5V5.5C13 5.22386 12.7761 5 12.5 5H11.5ZM11.5 4H12.5C13.3284 4 14 4.67157 14 5.5V6.5C14 7.32843 13.3284 8 12.5 8H11.5C10.6716 8 10 7.32843 10 6.5V5.5C10 4.67157 10.6716 4 11.5 4ZM11.5 11C11.2239 11 11 11.2239 11 11.5V12.5C11 12.7761 11.2239 13 11.5 13H12.5C12.7761 13 13 12.7761 13 12.5V11.5C13 11.2239 12.7761 11 12.5 11H11.5ZM11.5 10H12.5C13.3284 10 14 10.6716 14 11.5V12.5C14 13.3284 13.3284 14 12.5 14H11.5C10.6716 14 10 13.3284 10 12.5V11.5C10 10.6716 10.6716 10 11.5 10ZM11.5 17C11.2239 17 11 17.2239 11 17.5V18.5C11 18.7761 11.2239 19 11.5 19H12.5C12.7761 19 13 18.7761 13 18.5V17.5C13 17.2239 12.7761 17 12.5 17H11.5ZM11.5 16H12.5C13.3284 16 14 16.6716 14 17.5V18.5C14 19.3284 13.3284 20 12.5 20H11.5C10.6716 20 10 19.3284 10 18.5V17.5C10 16.6716 10.6716 16 11.5 16Z\"\n        fill={color}\n      />\n    </Svg>\n  );\n}\nexport function ListVerifiedIcon({ width, height }: { width?: number; height?: number }) {\n  return (\n    <Svg width={width || 12} height={height || 12} viewBox=\"0 0 12 12\" fill=\"none\">\n      <Path\n        d=\"M5.03404 6.71244C5.22931 6.90771 5.54589 6.90771 5.74115 6.71244L7.75805 4.69555C7.80198 4.65161 7.87321 4.65161 7.91715 4.69555C7.96108 4.73948 7.96108 4.81071 7.91715 4.85465L5.46715 7.30465C5.42321 7.34858 5.35198 7.34858 5.30805 7.30465L4.08305 6.07965C4.03911 6.03571 4.03911 5.96448 4.08305 5.92055C4.12698 5.87661 4.19821 5.87661 4.24215 5.92055L5.03404 6.71244ZM4.45788 1.1681C4.23722 1.35614 3.96287 1.46978 3.67387 1.49284C2.50996 1.58572 1.58572 2.50996 1.49284 3.67387C1.46978 3.96287 1.35614 4.23722 1.1681 4.45788C0.410765 5.34656 0.410765 6.65363 1.1681 7.54232C1.35614 7.76297 1.46978 8.03733 1.49284 8.32632C1.58572 9.49023 2.50996 10.4145 3.67387 10.5074C3.96286 10.5304 4.23722 10.6441 4.45788 10.8321C5.34656 11.5894 6.65363 11.5894 7.54232 10.8321C7.76297 10.6441 8.03733 10.5304 8.32632 10.5074C9.49023 10.4145 10.4145 9.49023 10.5074 8.32632C10.5304 8.03733 10.6441 7.76297 10.8321 7.54232C11.5894 6.65363 11.5894 5.34656 10.8321 4.45788C10.6441 4.23722 10.5304 3.96286 10.5074 3.67387C10.4145 2.50996 9.49023 1.58572 8.32632 1.49284C8.03733 1.46978 7.76297 1.35614 7.54232 1.1681C6.65363 0.410765 5.34656 0.410765 4.45788 1.1681Z\"\n        fill=\"#8E30EB\"\n        stroke=\"white\"\n        stroke-linecap=\"round\"\n        stroke-linejoin=\"round\"\n      />\n    </Svg>\n  );\n}\nexport function ListFavIcon({ width, height, color }: TIconProps) {\n  return (\n    <Svg width={width || 24} height={height || 24} viewBox=\"0 0 24 24\" fill=\"none\">\n      <G clip-path=\"url(#clip0_2_8414)\">\n        <Path\n          d=\"M5.41598 23.4152C4.83698 23.7122 4.17998 23.1917 4.29698 22.5272L5.54198 15.4323L0.25748 10.3983C-0.23602 9.92725 0.0204801 9.06625 0.68198 8.97325L8.02898 7.92925L11.305 1.43875C11.6005 0.85375 12.4 0.85375 12.6955 1.43875L15.9715 7.92925L23.3185 8.97325C23.98 9.06625 24.2365 9.92725 23.7415 10.3983L18.4585 15.4323L19.7035 22.5272C19.8205 23.1917 19.1635 23.7122 18.5845 23.4152L11.998 20.0312L5.41448 23.4152H5.41598Z\"\n          fill={color}\n          stroke=\"white\"\n          stroke-linecap=\"round\"\n          stroke-linejoin=\"round\"\n        />\n      </G>\n      <Defs>\n        <ClipPath id=\"clip0_2_8414\">\n          <Rect width={width || 24} height={height || 24} fill=\"white\" />\n        </ClipPath>\n      </Defs>\n    </Svg>\n  );\n}\nexport function OutlinedFavIcon({ width, height, color }: TIconProps) {\n  return (\n    <Svg\n      width={width || 24}\n      height={height || 24}\n      fill=\"none\"\n      viewBox=\"0 0 24 24\"\n      stroke-width=\"1.5\"\n      stroke={color}\n    >\n      <Path\n        stroke-linecap=\"round\"\n        stroke-linejoin=\"round\"\n        d=\"M11.48 3.499a.562.562 0 011.04 0l2.125 5.111a.563.563 0 00.475.345l5.518.442c.499.04.701.663.321.988l-4.204 3.602a.563.563 0 00-.182.557l1.285 5.385a.562.562 0 01-.84.61l-4.725-2.885a.563.563 0 00-.586 0L6.982 20.54a.562.562 0 01-.84-.61l1.285-5.386a.562.562 0 00-.182-.557l-4.204-3.602a.563.563 0 01.321-.988l5.518-.442a.563.563 0 00.475-.345L11.48 3.5z\"\n      />\n    </Svg>\n  );\n}\nexport function HeartIcon({ width, height, color }: TIconProps) {\n  return (\n    <Svg width={width || 24} height={height || 24} viewBox=\"0 0 24 24\" fill=\"none\">\n      <Path\n        d=\"M20 10C20 6.84016 18.2825 5 15.5 5C14.0165 5 13.026 5.56595 12.4472 6.72361C12.263 7.09213 11.737 7.09213 11.5528 6.72361C10.974 5.56595 9.98354 5 8.5 5C5.71748 5 4 6.84016 4 10C4 12.3991 6.64867 15.399 12 18.9034C17.3513 15.399 20 12.3991 20 10ZM15.5 4C18.8508 4 21 6.3027 21 10C21 12.894 18.0716 16.1668 12.2716 19.9198C12.1063 20.0267 11.8937 20.0267 11.7284 19.9198C5.92838 16.1668 3 12.894 3 10C3 6.3027 5.14919 4 8.5 4C10.0277 4 11.2097 4.52341 12 5.55573C12.7903 4.52341 13.9723 4 15.5 4Z\"\n        fill={color}\n      />\n    </Svg>\n  );\n}\nexport function GithubIcon({ width, height, color }: TIconProps) {\n  return (\n    <Svg width={width || 24} height={height || 24} viewBox=\"0 0 24 24\" fill=\"none\">\n      <Path\n        fill-rule=\"evenodd\"\n        clip-rule=\"evenodd\"\n        d=\"M12.026 2C6.517 2 2.052 6.465 2.052 11.974C2.052 16.38 4.909 20.119 8.873 21.439C9.372 21.529 9.552 21.222 9.552 20.958C9.552 20.721 9.544 20.093 9.541 19.262C6.766 19.864 6.18 17.924 6.18 17.924C5.728 16.772 5.073 16.465 5.073 16.465C4.168 15.846 5.142 15.86 5.142 15.86C6.144 15.93 6.669 16.888 6.669 16.888C7.559 18.412 9.005 17.972 9.571 17.717C9.662 17.072 9.922 16.632 10.206 16.383C7.992 16.132 5.664 15.276 5.664 11.453C5.664 10.366 6.053 9.474 6.688 8.778C6.587 8.525 6.242 7.51 6.787 6.138C6.787 6.138 7.624 5.869 9.529 7.159C10.3426 6.93767 11.1818 6.8247 12.025 6.823C12.8682 6.82437 13.7075 6.93735 14.521 7.159C16.427 5.868 17.263 6.138 17.263 6.138C17.808 7.51 17.466 8.525 17.362 8.778C18.002 9.474 18.386 10.365 18.386 11.453C18.386 15.286 16.056 16.128 13.834 16.375C14.189 16.683 14.509 17.291 14.509 18.221C14.509 19.555 14.497 20.631 14.497 20.958C14.497 21.225 14.675 21.535 15.184 21.437C19.146 20.115 22 16.379 22 11.974C22 6.465 17.535 2 12.026 2Z\"\n        fill={color}\n      />\n    </Svg>\n  );\n}\nexport function TelegramIcon({ width, height, color }: TIconProps) {\n  return (\n    <Svg width={width || 24} height={height || 24} viewBox=\"0 0 24 24\" fill=\"none\">\n      <Path\n        d=\"M20.665 3.71706L2.93497 10.5541C1.72497 11.0401 1.73197 11.7151 2.71297 12.0161L7.26497 13.4361L17.797 6.79106C18.295 6.48806 18.75 6.65106 18.376 6.98306L9.84297 14.6841H9.84097L9.84297 14.6851L9.52897 19.3771C9.98897 19.3771 10.192 19.1661 10.45 18.9171L12.661 16.7671L17.26 20.1641C18.108 20.6311 18.717 20.3911 18.928 19.3791L21.947 5.15106C22.256 3.91206 21.474 3.35106 20.665 3.71706Z\"\n        fill={color}\n      />\n    </Svg>\n  );\n}\nexport function ReadmeIcon({ width, height, color }: TIconProps) {\n  return (\n    <Svg width={width || 24} height={height || 24} viewBox=\"0 0 24 24\" fill=\"none\">\n      <Path\n        d=\"M19 14.5V5.5C19 4.67157 18.3284 4 17.5 4H6.5C5.67157 4 5 4.67157 5 5.5V18.5C5 19.3284 5.67157 20 6.5 20H13.5C14.3284 20 15 19.3284 15 18.5C15 17.1193 16.1193 16 17.5 16C18.3284 16 19 15.3284 19 14.5ZM18.5014 16.7913C18.1948 16.9255 17.8561 17 17.5 17C16.6716 17 16 17.6716 16 18.5C16 18.8561 15.9255 19.1948 15.7913 19.5014C16.9874 18.9526 17.9526 17.9874 18.5014 16.7913ZM4 5.5C4 4.11929 5.11929 3 6.5 3H17.5C18.8807 3 20 4.11929 20 5.5V14.5C20 18.0899 17.0899 21 13.5 21H6.5C5.11929 21 4 19.8807 4 18.5V5.5ZM8.5 9C8.22386 9 8 8.77614 8 8.5C8 8.22386 8.22386 8 8.5 8H15.5C15.7761 8 16 8.22386 16 8.5C16 8.77614 15.7761 9 15.5 9H8.5ZM8.5 12C8.22386 12 8 11.7761 8 11.5C8 11.2239 8.22386 11 8.5 11H15.5C15.7761 11 16 11.2239 16 11.5C16 11.7761 15.7761 12 15.5 12H8.5ZM8.5 15C8.22386 15 8 14.7761 8 14.5C8 14.2239 8.22386 14 8.5 14H13.5C13.7761 14 14 14.2239 14 14.5C14 14.7761 13.7761 15 13.5 15H8.5Z\"\n        fill={color}\n      />\n    </Svg>\n  );\n}\nexport function OptionsIcon({ width, height, color }: TIconProps) {\n  return (\n    <Svg width={width || 24} height={height || 24} viewBox=\"0 0 24 24\" fill=\"none\">\n      <Path\n        d=\"M18 11.05C19.1411 11.2816 20 12.2905 20 13.5C20 14.7095 19.1411 15.7184 18 15.95V20.5C18 20.7761 17.7761 21 17.5 21C17.2239 21 17 20.7761 17 20.5V15.95C15.8589 15.7184 15 14.7095 15 13.5C15 12.2905 15.8589 11.2816 17 11.05V3.5C17 3.22386 17.2239 3 17.5 3C17.7761 3 18 3.22386 18 3.5V11.05ZM13 5.05001C14.1411 5.28164 15 6.29052 15 7.5C15 8.70948 14.1411 9.71836 13 9.94999V20.5C13 20.7761 12.7761 21 12.5 21C12.2239 21 12 20.7761 12 20.5V9.94999C10.8589 9.71836 10 8.70948 10 7.5C10 6.29052 10.8589 5.28164 12 5.05001V3.5C12 3.22386 12.2239 3 12.5 3C12.7761 3 13 3.22386 13 3.5V5.05001ZM8 14.05C9.14112 14.2816 10 15.2905 10 16.5C10 17.7095 9.14112 18.7184 8 18.95V20.5C8 20.7761 7.77614 21 7.5 21C7.22386 21 7 20.7761 7 20.5V18.95C5.85888 18.7184 5 17.7095 5 16.5C5 15.2905 5.85888 14.2816 7 14.05V3.5C7 3.22386 7.22386 3 7.5 3C7.77614 3 8 3.22386 8 3.5V14.05ZM9 16.5C9 15.6716 8.32843 15 7.5 15C6.67157 15 6 15.6716 6 16.5C6 17.3284 6.67157 18 7.5 18C8.32843 18 9 17.3284 9 16.5ZM14 7.5C14 6.67157 13.3284 6 12.5 6C11.6716 6 11 6.67157 11 7.5C11 8.32843 11.6716 9 12.5 9C13.3284 9 14 8.32843 14 7.5ZM19 13.5C19 12.6716 18.3284 12 17.5 12C16.6716 12 16 12.6716 16 13.5C16 14.3284 16.6716 15 17.5 15C18.3284 15 19 14.3284 19 13.5Z\"\n        fill={color}\n      />\n    </Svg>\n  );\n}\nexport function KeyIcon({ width, height, color }: TIconProps) {\n  return (\n    <Svg width={width || 24} height={height || 24} viewBox=\"0 0 24 24\" fill=\"none\">\n      <Path\n        d=\"M6.17916 22.7519C6.07916 22.7519 5.96916 22.7419 5.87916 22.7319L3.70916 22.4319C2.66916 22.2919 1.72916 21.3619 1.56916 20.3019L1.26916 18.1119C1.16916 17.4119 1.46916 16.5019 1.96916 15.9919L6.35916 11.6019C5.64916 8.76188 6.46916 5.76188 8.55916 3.69188C11.7992 0.461875 17.0692 0.451875 20.3192 3.69188C21.8892 5.26188 22.7492 7.35188 22.7492 9.57188C22.7492 11.7919 21.8892 13.8819 20.3192 15.4519C18.2192 17.5319 15.2292 18.3519 12.4092 17.6319L8.00916 22.0219C7.58916 22.4619 6.83916 22.7519 6.17916 22.7519ZM14.4292 2.76188C12.6792 2.76188 10.9392 3.42188 9.60916 4.75188C7.80916 6.54188 7.15916 9.16188 7.90916 11.6019C7.98916 11.8719 7.91916 12.1519 7.71916 12.3519L3.01916 17.0519C2.84916 17.2219 2.70916 17.6619 2.73916 17.8919L3.03916 20.0819C3.09916 20.4619 3.50916 20.8919 3.88916 20.9419L6.06916 21.2419C6.30916 21.2819 6.74916 21.1419 6.91916 20.9719L11.6392 16.2619C11.8392 16.0619 12.1292 16.0019 12.3892 16.0819C14.7992 16.8419 17.4292 16.1919 19.2292 14.3919C20.5092 13.1119 21.2192 11.3919 21.2192 9.57188C21.2192 7.74188 20.5092 6.03188 19.2292 4.75188C17.9292 3.43188 16.1792 2.76188 14.4292 2.76188Z\"\n        fill={color}\n      />\n      <Path\n        d=\"M9.18811 20.5397C8.99811 20.5397 8.80812 20.4697 8.65812 20.3197L6.35813 18.0197C6.06813 17.7297 6.06813 17.2497 6.35813 16.9597C6.64812 16.6697 7.12811 16.6697 7.41811 16.9597L9.71813 19.2597C10.0081 19.5497 10.0081 20.0297 9.71813 20.3197C9.56813 20.4697 9.37811 20.5397 9.18811 20.5397Z\"\n        fill={color}\n      />\n      <Path\n        d=\"M14.5 11.75C13.26 11.75 12.25 10.74 12.25 9.5C12.25 8.26 13.26 7.25 14.5 7.25C15.74 7.25 16.75 8.26 16.75 9.5C16.75 10.74 15.74 11.75 14.5 11.75ZM14.5 8.75C14.09 8.75 13.75 9.09 13.75 9.5C13.75 9.91 14.09 10.25 14.5 10.25C14.91 10.25 15.25 9.91 15.25 9.5C15.25 9.09 14.91 8.75 14.5 8.75Z\"\n        fill={color}\n      />\n    </Svg>\n  );\n}\nexport function SendMsgIcon({ width, height, color }: TIconProps) {\n  return (\n    <Svg width={width || 24} height={height || 24} viewBox=\"0 0 24 24\" fill=\"none\">\n      <G clip-path=\"url(#clip0_2_8800)\">\n        <Path\n          d=\"M23.3389 0.21776C23.4427 0.321758 23.5137 0.453971 23.543 0.597976C23.5724 0.74198 23.5588 0.89143 23.5039 1.02776L14.7754 22.8483C14.6985 23.0404 14.57 23.2076 14.4042 23.3315C14.2383 23.4554 14.0416 23.5311 13.8355 23.5503C13.6294 23.5696 13.422 23.5316 13.2361 23.4405C13.0502 23.3494 12.893 23.2089 12.7819 23.0343L8.01488 15.5418L0.522381 10.7748C0.347358 10.6637 0.206408 10.5065 0.115086 10.3205C0.0237631 10.1344 -0.0143824 9.92671 0.00485835 9.72034C0.0240991 9.51397 0.099978 9.31692 0.224122 9.15095C0.348267 8.98497 0.51585 8.85652 0.708381 8.77976L22.5289 0.0542598C22.6652 -0.000621803 22.8147 -0.0142414 22.9587 0.0150929C23.1027 0.0444271 23.2349 0.115422 23.3389 0.21926V0.21776ZM9.51188 15.1038L13.6534 21.6108L20.7529 3.86276L9.51188 15.1038ZM19.6924 2.80226L1.94438 9.90176L8.45288 14.0418L19.6939 2.80226H19.6924Z\"\n          fill={color}\n        />\n      </G>\n      <Defs>\n        <ClipPath id=\"clip0_2_8800\">\n          <Rect width={width || 24} height={height || 24} fill=\"white\" />\n        </ClipPath>\n      </Defs>\n    </Svg>\n  );\n}\nexport function DatabaseIcon({ width, height, color }: TIconProps) {\n  return (\n    <Svg width={width || 24} height={height || 24} viewBox=\"0 0 24 24\" fill=\"none\">\n      <Path\n        d=\"M3 7.39095V10C3 10.3436 3.85363 10.8747 5.40973 11.2842C7.13505 11.7383 9.48657 12 12 12C14.5134 12 16.8649 11.7383 18.5903 11.2842C20.1464 10.8747 21 10.3436 21 10V7.39095C19.3864 8.40254 15.9832 9 12 9C8.01684 9 4.61364 8.40254 3 7.39095ZM2 6C2 4.16677 6.43371 3 12 3C17.5663 3 22 4.16677 22 6V18C22 19.8332 17.5663 21 12 21C6.43371 21 2 19.8332 2 18V6ZM21 11.3909C19.3864 12.4025 15.9832 13 12 13C8.01684 13 4.61364 12.4025 3 11.3909V14C3 14.3436 3.85363 14.8747 5.40973 15.2842C7.13505 15.7383 9.48657 16 12 16C14.5134 16 16.8649 15.7383 18.5903 15.2842C20.1464 14.8747 21 14.3436 21 14V11.3909ZM21 15.3909C19.3864 16.4025 15.9832 17 12 17C8.01684 17 4.61364 16.4025 3 15.3909V18C3 18.3436 3.85363 18.8747 5.40973 19.2842C7.13505 19.7383 9.48657 20 12 20C14.5134 20 16.8649 19.7383 18.5903 19.2842C20.1464 18.8747 21 18.3436 21 18V15.3909ZM12 8C14.5134 8 16.8649 7.73826 18.5903 7.28423C20.1464 6.87473 21 6.34362 21 6C21 5.65638 20.1464 5.12527 18.5903 4.71577C16.8649 4.26174 14.5134 4 12 4C9.48657 4 7.13505 4.26174 5.40973 4.71577C3.85363 5.12527 3 5.65638 3 6C3 6.34362 3.85363 6.87473 5.40973 7.28423C7.13505 7.73826 9.48657 8 12 8Z\"\n        fill={color}\n      />\n    </Svg>\n  );\n}\nexport function ImageIcon({ width, height, color }: TIconProps) {\n  return (\n    <Svg width={width || 24} height={height || 24} viewBox=\"0 0 24 24\" fill=\"none\">\n      <Path\n        d=\"M20 15.2929V5.5C20 4.67157 19.3284 4 18.5 4H5.5C4.67157 4 4 4.67157 4 5.5V12.2929L7.14645 9.14645C7.34171 8.95118 7.65829 8.95118 7.85355 9.14645L13.5 14.7929L16.1464 12.1464C16.3417 11.9512 16.6583 11.9512 16.8536 12.1464L20 15.2929ZM20 16.7071L16.5 13.2071L13.8536 15.8536C13.6583 16.0488 13.3417 16.0488 13.1464 15.8536L7.5 10.2071L4 13.7071V18.5C4 19.3284 4.67157 20 5.5 20H18.5C19.3284 20 20 19.3284 20 18.5V16.7071ZM3 5.5C3 4.11929 4.11929 3 5.5 3H18.5C19.8807 3 21 4.11929 21 5.5V18.5C21 19.8807 19.8807 21 18.5 21H5.5C4.11929 21 3 19.8807 3 18.5V5.5ZM15 6H17C17.5523 6 18 6.44772 18 7V9C18 9.55228 17.5523 10 17 10H15C14.4477 10 14 9.55228 14 9V7C14 6.44772 14.4477 6 15 6ZM15 7V9H17V7H15Z\"\n        fill={color}\n      />\n    </Svg>\n  );\n}\nexport function DownloadIcon({ width, height, color }: TIconProps) {\n  return (\n    <Svg width={width || 24} height={height || 24} viewBox=\"0 0 24 24\" fill=\"none\">\n      <Path\n        d=\"M11.375 3.5C9.03603 3.5 7.08074 5.14772 6.60867 7.3461L6.55282 7.60622L6.30587 7.70522C5.24663 8.12985 4.5 9.16584 4.5 10.375C4.5 11.9628 5.78718 13.25 7.375 13.25C7.92278 13.25 8.43337 13.0973 8.86823 12.8324L9.09569 12.6938L9.33758 12.8053C9.70275 12.9735 10.0924 13.098 10.5 13.1718V14.1852C10.0323 14.1153 9.58224 13.9902 9.15697 13.8167C8.62312 14.0936 8.01674 14.25 7.375 14.25C5.2349 14.25 3.5 12.5151 3.5 10.375C3.5 8.83769 4.39506 7.51051 5.69093 6.88423C6.3509 4.36158 8.64501 2.5 11.375 2.5C13.1366 2.5 14.7174 3.27587 15.7935 4.50286C18.4079 4.59165 20.5 6.739 20.5 9.375C20.5 12.0674 18.3174 14.25 15.625 14.25C14.9048 14.25 14.22 14.0935 13.6037 13.8124C13.5693 13.8265 13.5347 13.8403 13.5 13.8538V12.765L13.6287 12.706L13.8455 12.8182C14.3778 13.094 14.9825 13.25 15.625 13.25C17.7651 13.25 19.5 11.5151 19.5 9.375C19.5 7.2349 17.7651 5.5 15.625 5.5C15.6054 5.5 15.5859 5.50015 15.5663 5.50043L15.3229 5.50404L15.1699 5.31463C14.2755 4.20699 12.908 3.5 11.375 3.5Z\"\n        fill={color}\n      />\n      <Path\n        d=\"M12.5001 9.5V19.7928L14.6251 17.6679L15.3322 18.375L12.0001 21.7071L8.66797 18.375L9.37508 17.6679L11.5001 19.7929V9.5H12.5001Z\"\n        fill={color}\n      />\n    </Svg>\n  );\n}\nexport function AppleIcon({ width, height, color }: TIconProps) {\n  return (\n    <Svg width={width || 24} height={height || 24} viewBox=\"0 0 24 24\" fill=\"none\">\n      <Path\n        d=\"M15.5 21C16.189 21 17.383 19.542 18.87 16.639C17.635 15.604 17 14.384 17 13C17 11.644 17.609 10.445 18.797 9.424C17.963 8.464 17.037 8 16 8C14.906 8 14.059 8.149 13.459 8.437C12.82 8.744 12.081 8.765 11.425 8.495C10.629 8.167 9.654 8 8.5 8C6.434 8 5 10.086 5 13C5 15.711 7.833 21 9 21C9.429 21 9.918 20.842 10.466 20.514C11.652 19.804 13.14 19.836 14.294 20.595C14.71 20.868 15.109 21 15.5 21ZM19.8 16.1C19.993 16.245 20.056 16.508 19.947 16.724C18.187 20.246 16.783 22 15.5 22C14.903 22 14.316 21.807 13.744 21.431C12.911 20.882 11.836 20.859 10.98 21.371C10.287 21.786 9.627 22 9 22C7.113 22 4 16.189 4 13C4 9.596 5.785 7 8.5 7C9.777 7 10.88 7.188 11.806 7.57C12.199 7.732 12.643 7.72 13.026 7.536C13.778 7.175 14.769 7 16 7C17.502 7 18.811 7.748 19.9 9.2C20.065 9.421 20.021 9.734 19.8 9.9C18.585 10.811 18 11.835 18 13C18 14.165 18.585 15.189 19.8 16.1ZM12.4995 6C12.2235 6 11.9995 5.776 11.9995 5.5C11.9995 3.567 13.5675 2 15.4995 2C15.7765 2 15.9995 2.224 15.9995 2.5C15.9995 4.433 14.4325 6 12.4995 6ZM14.9365 3.064C14.0075 3.278 13.2775 4.008 13.0635 4.936C13.9925 4.722 14.7225 3.992 14.9365 3.064Z\"\n        fill={color}\n      />\n    </Svg>\n  );\n}\nexport function VerifiedFilledIcon({ width, height, color }: TIconProps) {\n  return (\n    <Svg width={width || 24} height={height || 24} viewBox=\"0 0 24 24\" fill=\"none\">\n      <Path\n        d=\"M19.965 8.521C19.988 8.347 20 8.173 20 8C20 5.621 17.857 3.712 15.479 4.035C14.786 2.802 13.466 2 12 2C10.534 2 9.214 2.802 8.521 4.035C6.138 3.712 4 5.621 4 8C4 8.173 4.012 8.347 4.035 8.521C2.802 9.215 2 10.535 2 12C2 13.465 2.802 14.785 4.035 15.479C4.01193 15.6517 4.00024 15.8258 4 16C4 18.379 6.138 20.283 8.521 19.965C9.214 21.198 10.534 22 12 22C13.466 22 14.786 21.198 15.479 19.965C17.857 20.283 20 18.379 20 16C20 15.827 19.988 15.653 19.965 15.479C21.198 14.785 22 13.465 22 12C22 10.535 21.198 9.215 19.965 8.521ZM10.955 16.416L7.288 12.702L8.712 11.298L10.969 13.584L15.296 9.29L16.704 10.71L10.955 16.416Z\"\n        fill={color}\n      />\n    </Svg>\n  );\n}\nexport function ReleaseTagIcon({ width, height, color }: TIconProps) {\n  return (\n    <Svg width={width || 24} height={height || 24} viewBox=\"0 0 24 24\" fill=\"none\">\n      <Path\n        d=\"M3 5.5C3 4.11929 4.11929 3 5.5 3H11.5C11.6326 3 11.7598 3.05268 11.8536 3.14645L20.1565 11.4494C21.289 12.5819 21.289 14.4181 20.1565 15.5506L15.5506 20.1565C14.4181 21.289 12.5819 21.289 11.4494 20.1565L3.14645 11.8536C3.05268 11.7598 3 11.6326 3 11.5V5.5ZM11.2929 4H5.5C4.67157 4 4 4.67157 4 5.5V11.2929L12.1565 19.4494C12.8985 20.1914 14.1015 20.1914 14.8435 19.4494L19.4494 14.8435C20.1914 14.1015 20.1914 12.8985 19.4494 12.1565L11.2929 4ZM8 7C7.44772 7 7 7.44772 7 8C7 8.55228 7.44772 9 8 9C8.55228 9 9 8.55228 9 8C9 7.44772 8.55228 7 8 7ZM8 6C9.10457 6 10 6.89543 10 8C10 9.10457 9.10457 10 8 10C6.89543 10 6 9.10457 6 8C6 6.89543 6.89543 6 8 6Z\"\n        fill={color}\n      />\n    </Svg>\n  );\n}\nexport function LeafIcon({ width, height, color }: TIconProps) {\n  return (\n    <Svg width={width || 24} height={height || 24} viewBox=\"0 0 24 24\" fill=\"none\">\n      <Path\n        d=\"M6.73689 16.747C5.97017 18.059 5.56636 19.5514 5.56689 21.071C5.56689 21.3362 5.46154 21.5906 5.274 21.7781C5.08646 21.9656 4.83211 22.071 4.56689 22.071C4.30168 22.071 4.04732 21.9656 3.85979 21.7781C3.67225 21.5906 3.56689 21.3362 3.56689 21.071C3.56689 18.948 4.20389 16.908 5.35189 15.192C4.60061 14.0389 4.20582 12.6899 4.21685 11.3137C4.22787 9.93742 4.64423 8.59494 5.41389 7.45399C6.85589 5.31699 11.5799 3.43299 19.5839 1.80099C19.3159 8.65199 18.4619 13.146 17.0209 15.283C16.4735 16.0946 15.762 16.7823 14.9323 17.3018C14.1026 17.8213 13.1732 18.161 12.204 18.299C11.2349 18.437 10.2476 18.3701 9.30588 18.1028C8.36417 17.8355 7.489 17.3736 6.73689 16.747ZM7.94289 15.147C8.47758 15.6103 9.1045 15.9548 9.78221 16.1578C10.4599 16.3608 11.173 16.4177 11.8743 16.3247C12.5756 16.2317 13.2492 15.9909 13.8506 15.6183C14.452 15.2456 14.9674 14.7496 15.3629 14.163C16.3669 12.675 17.0999 9.34799 17.4469 4.31299C11.5039 5.7 7.98389 7.22199 7.07189 8.57299C6.58249 9.29803 6.29195 10.1388 6.2293 11.0113C6.16666 11.8838 6.3341 12.7575 6.71489 13.545C7.14489 13.122 7.61189 12.734 8.11489 12.385L8.62289 12.033C8.8409 11.882 9.10998 11.8237 9.37094 11.8711C9.6319 11.9184 9.86335 12.0675 10.0144 12.2855C10.1654 12.5035 10.2237 12.7726 10.1763 13.0335C10.129 13.2945 9.9799 13.526 9.76189 13.677L9.25489 14.029C8.78103 14.3569 8.34147 14.7318 7.94289 15.148V15.147Z\"\n        fill={color}\n      />\n    </Svg>\n  );\n}\nexport function BoltIcon({ width, height, color }: TIconProps) {\n  return (\n    <Svg width={width || 24} height={height || 24} viewBox=\"0 0 24 24\" fill=\"none\">\n      <Path\n        fillRule=\"evenodd\"\n        clipRule=\"evenodd\"\n        d=\"M8.44558 2.25H14.375V9.25H19.9355L9.62497 22.1381V14.75H4.61035L8.44558 2.25ZM9.55437 3.75L6.6396 13.25H11.125V17.8619L16.8145 10.75H12.875V3.75H9.55437Z\"\n        fill={color}\n      />\n    </Svg>\n  );\n}\nexport function ExitIcon({ width, height, color }: TIconProps) {\n  return (\n    <Svg width={width || 24} height={height || 24} viewBox=\"0 0 24 24\" fill=\"none\">\n      <G clipPath=\"url(#clip0_105_2665)\">\n        <Path\n          d=\"M10.09 15.59L11.5 17L16.5 12L11.5 7L10.09 8.41L12.67 11H3V13H12.67L10.09 15.59ZM19 3H5C3.89 3 3 3.9 3 5V9H5V5H19V19H5V15H3V19C3 20.1 3.89 21 5 21H19C20.1 21 21 20.1 21 19V5C21 3.9 20.1 3 19 3Z\"\n          fill={color}\n        />\n      </G>\n      <Defs>\n        <ClipPath id=\"clip0_105_2665\">\n          <Rect width=\"24\" height=\"24\" fill=\"white\" />\n        </ClipPath>\n      </Defs>\n    </Svg>\n  );\n}\nexport function HomeWifiIcon({ width, height, color }: TIconProps) {\n  return (\n    <Svg width={width || 24} height={height || 24} viewBox=\"0 0 24 24\" fill=\"none\">\n      <Path\n        d=\"M17.5998 22.5609H6.39983C4.57983 22.5609 2.91983 21.1608 2.61983 19.3608L1.28984 11.4008C1.07984 10.1608 1.67985 8.57084 2.66985 7.78084L9.59984 2.23079C10.9398 1.15079 13.0498 1.1608 14.3998 2.2408L21.3298 7.78084C22.3098 8.57084 22.9098 10.1608 22.7098 11.4008L21.3798 19.3608C21.0798 21.1308 19.3898 22.5609 17.5998 22.5609ZM11.9898 2.94075C11.4598 2.94075 10.9298 3.10085 10.5398 3.41085L3.60982 8.96077C3.03982 9.42077 2.64982 10.4408 2.76982 11.1608L4.09984 19.1208C4.27984 20.1708 5.32983 21.0609 6.39983 21.0609H17.5998C18.6698 21.0609 19.7198 20.1708 19.8998 19.1108L21.2298 11.1508C21.3498 10.4308 20.9499 9.40076 20.3899 8.95076L13.4598 3.41085C13.0598 3.10085 12.5298 2.94075 11.9898 2.94075Z\"\n        fill={color}\n      />\n      <Path\n        d=\"M14.1205 15.1302C13.9305 15.1302 13.7505 15.0602 13.6005 14.9202C12.6305 13.9902 11.3706 13.9902 10.3906 14.9202C10.0906 15.2102 9.62052 15.2002 9.33052 14.9002C9.04052 14.6002 9.05054 14.1302 9.35054 13.8402C10.9005 12.3502 13.0705 12.3502 14.6305 13.8402C14.9305 14.1302 14.9405 14.6002 14.6505 14.9002C14.5205 15.0502 14.3205 15.1302 14.1205 15.1302Z\"\n        fill={color}\n      />\n      <Path\n        d=\"M16.2404 13.0118C16.0504 13.0118 15.8604 12.9418 15.7204 12.8018C15.2504 12.3418 14.7204 11.9717 14.1604 11.7017C12.7604 11.0317 11.2304 11.0317 9.84037 11.7017C9.28037 11.9717 8.76037 12.3418 8.28037 12.8018C7.99037 13.0918 7.51037 13.0918 7.22037 12.7918C6.93037 12.4918 6.94038 12.0217 7.23038 11.7317C7.82038 11.1517 8.48037 10.6917 9.19037 10.3517C11.0004 9.48172 13.0004 9.48172 14.8004 10.3517C15.5104 10.6917 16.1704 11.1517 16.7604 11.7317C17.0604 12.0217 17.0604 12.4918 16.7704 12.7918C16.6304 12.9318 16.4404 13.0118 16.2404 13.0118Z\"\n        fill={color}\n      />\n      <Path\n        d=\"M12.0005 17.5003C11.7405 17.5003 11.4905 17.4002 11.2905 17.2102C10.9005 16.8202 10.9005 16.1903 11.2905 15.8003C11.6805 15.4103 12.3205 15.4103 12.7105 15.8003C13.1005 16.1903 13.1005 16.8202 12.7105 17.2102C12.5105 17.4002 12.2605 17.5003 12.0005 17.5003Z\"\n        fill={color}\n      />\n    </Svg>\n  );\n}\nexport function BatteryChargingIcon({ width, height, color }: TIconProps) {\n  return (\n    <Svg width={width || 24} height={height || 24} viewBox=\"0 0 24 24\" fill=\"none\">\n      <Path\n        d=\"M14.1278 4.10323C14.2743 4.18856 14.3876 4.32104 14.4492 4.47904C14.5108 4.63704 14.517 4.81124 14.4668 4.97323L12.7658 10.4992H15.7508C15.8973 10.4992 16.0406 10.542 16.163 10.6225C16.2854 10.7029 16.3816 10.8174 16.4396 10.9519C16.4977 11.0864 16.5151 11.2349 16.4897 11.3792C16.4644 11.5235 16.3973 11.6571 16.2968 11.7637L8.2958 20.2642C8.17969 20.3877 8.02518 20.4682 7.85746 20.4926C7.68974 20.517 7.51869 20.4839 7.3722 20.3987C7.22571 20.3134 7.11242 20.1811 7.05078 20.0232C6.98915 19.8653 6.98281 19.6912 7.0328 19.5292L8.7353 14.0017H5.7503C5.60382 14.0018 5.46052 13.9589 5.33811 13.8785C5.21569 13.7981 5.11951 13.6835 5.06145 13.549C5.00338 13.4146 4.98596 13.266 5.01135 13.1217C5.03674 12.9775 5.10381 12.8438 5.2043 12.7372L13.2038 4.23673C13.3199 4.11307 13.4744 4.0324 13.6422 4.00788C13.81 3.98336 13.9812 4.01644 14.1278 4.10173V4.10323Z\"\n        fill={color}\n      />\n      <Path\n        d=\"M3 6H9.498L8.088 7.5H3C2.60217 7.5 2.22064 7.65804 1.93934 7.93934C1.65804 8.22064 1.5 8.60218 1.5 9V15C1.5 15.3978 1.65804 15.7794 1.93934 16.0607C2.22064 16.342 2.60217 16.5 3 16.5H6.57L6.108 18H3C2.20435 18 1.44129 17.6839 0.87868 17.1213C0.316071 16.5587 0 15.7956 0 15V9C0 8.20435 0.316071 7.44129 0.87868 6.87868C1.44129 6.31607 2.20435 6 3 6Z\"\n        fill={color}\n      />\n      <Path\n        d=\"M3 9H6.675L4.362 11.4585C4.1233 11.7122 3.94678 12.0179 3.84633 12.3514C3.74588 12.685 3.72425 13.0373 3.78314 13.3806C3.84204 13.724 3.97985 14.049 4.18572 14.33C4.39159 14.611 4.65989 14.8403 4.9695 15H3V9ZM15.8925 6L15.4305 7.5H18C18.3978 7.5 18.7794 7.65804 19.0607 7.93934C19.342 8.22064 19.5 8.60218 19.5 9V15C19.5 15.3978 19.342 15.7794 19.0607 16.0607C18.7794 16.342 18.3978 16.5 18 16.5H13.914L12.501 18H18C18.7956 18 19.5587 17.6839 20.1213 17.1213C20.6839 16.5587 21 15.7956 21 15V9C21 8.20435 20.6839 7.44129 20.1213 6.87868C19.5587 6.31607 18.7956 6 18 6H15.8925Z\"\n        fill={color}\n      />\n      <Path\n        d=\"M17.6745 15H15L17.313 12.5415C17.4585 12.387 17.58 12.2145 17.6745 12.0315V15ZM17.6745 9.969V9H16.7055C17.1214 9.21439 17.4601 9.5531 17.6745 9.969ZM23.6745 12C23.6745 12.5967 23.4374 13.169 23.0155 13.591C22.5935 14.0129 22.0212 14.25 21.4245 14.25V9.75C22.0212 9.75 22.5935 9.98705 23.0155 10.409C23.4374 10.831 23.6745 11.4033 23.6745 12Z\"\n        fill={color}\n      />\n    </Svg>\n  );\n}\n\nexport function ConnectionErrorIcon({ width, height, color }: TIconProps) {\n  return (\n    <Svg width={width || 24} height={height || 24} viewBox=\"0 0 24 24\" fill=\"none\">\n      <Path\n        d=\"M12 16V14.5C12 13.6716 12.6716 13 13.5 13H19.5C20.3284 13 21 13.6716 21 14.5V18.5C21 19.3284 20.3284 20 19.5 20H18.5C18.7761 20 19 20.2239 19 20.5C19 20.7761 18.7761 21 18.5 21H14.5C14.2239 21 14 20.7761 14 20.5C14 20.2239 14.2239 20 14.5 20H13.5C12.6716 20 12 19.3284 12 18.5V17H10.5C10.2239 17 10 16.7761 10 16.5C10 16.2239 10.2239 16 10.5 16H12ZM7 11H5.5C5.22386 11 5 10.7761 5 10.5C5 10.2239 5.22386 10 5.5 10H4.5C3.67157 10 3 9.32843 3 8.5V4.5C3 3.67157 3.67157 3 4.5 3H10.5C11.3284 3 12 3.67157 12 4.5V8.5C12 9.32843 11.3284 10 10.5 10H9.5C9.77614 10 10 10.2239 10 10.5C10 10.7761 9.77614 11 9.5 11H8V13.5C8 13.7761 7.77614 14 7.5 14C7.22386 14 7 13.7761 7 13.5V11ZM7.5 15.7929L9.14645 14.1464C9.34171 13.9512 9.65829 13.9512 9.85355 14.1464C10.0488 14.3417 10.0488 14.6583 9.85355 14.8536L8.20711 16.5L9.85355 18.1464C10.0488 18.3417 10.0488 18.6583 9.85355 18.8536C9.65829 19.0488 9.34171 19.0488 9.14645 18.8536L7.5 17.2071L5.85355 18.8536C5.65829 19.0488 5.34171 19.0488 5.14645 18.8536C4.95118 18.6583 4.95118 18.3417 5.14645 18.1464L6.79289 16.5L5.14645 14.8536C4.95118 14.6583 4.95118 14.3417 5.14645 14.1464C5.34171 13.9512 5.65829 13.9512 5.85355 14.1464L7.5 15.7929ZM4 4.5V8.5C4 8.77614 4.22386 9 4.5 9H10.5C10.7761 9 11 8.77614 11 8.5V4.5C11 4.22386 10.7761 4 10.5 4H4.5C4.22386 4 4 4.22386 4 4.5ZM13 14.5V18.5C13 18.7761 13.2239 19 13.5 19H19.5C19.7761 19 20 18.7761 20 18.5V14.5C20 14.2239 19.7761 14 19.5 14H13.5C13.2239 14 13 14.2239 13 14.5Z\"\n        fill={color}\n      />\n    </Svg>\n  );\n}\nexport function ClockIcon({ width, height, color }: TIconProps) {\n  return (\n    <Svg width={width || 24} height={height || 24} viewBox=\"0 0 24 24\" fill=\"none\">\n      <Path d=\"M12.5 11.5H16.5V12.5H11.5V7.5H12.5V11.5Z\" fill={color} />\n      <Path\n        fillRule=\"evenodd\"\n        clipRule=\"evenodd\"\n        d=\"M2.5 12C2.5 6.7533 6.7533 2.5 12 2.5C17.2467 2.5 21.5 6.7533 21.5 12C21.5 17.2467 17.2467 21.5 12 21.5C6.7533 21.5 2.5 17.2467 2.5 12ZM12 3.5C7.30558 3.5 3.5 7.30558 3.5 12C3.5 16.6944 7.30558 20.5 12 20.5C16.6944 20.5 20.5 16.6944 20.5 12C20.5 7.30558 16.6944 3.5 12 3.5Z\"\n        fill={color}\n      />\n    </Svg>\n  );\n}\nexport function CloseCircleIcon({ width, height, color }: TIconProps) {\n  return (\n    <Svg width={width || 24} height={height || 24} viewBox=\"0 0 24 24\" fill=\"none\">\n      <Path\n        d=\"M12.5 11.7929L15.1464 9.14645C15.3417 8.95118 15.6583 8.95118 15.8536 9.14645C16.0488 9.34171 16.0488 9.65829 15.8536 9.85355L13.2071 12.5L15.8536 15.1464C16.0488 15.3417 16.0488 15.6583 15.8536 15.8536C15.6583 16.0488 15.3417 16.0488 15.1464 15.8536L12.5 13.2071L9.85355 15.8536C9.65829 16.0488 9.34171 16.0488 9.14645 15.8536C8.95118 15.6583 8.95118 15.3417 9.14645 15.1464L11.7929 12.5L9.14645 9.85355C8.95118 9.65829 8.95118 9.34171 9.14645 9.14645C9.34171 8.95118 9.65829 8.95118 9.85355 9.14645L12.5 11.7929ZM12.5 23C6.70101 23 2 18.299 2 12.5C2 6.70101 6.70101 2 12.5 2C18.299 2 23 6.70101 23 12.5C23 18.299 18.299 23 12.5 23ZM12.5 22C17.7467 22 22 17.7467 22 12.5C22 7.25329 17.7467 3 12.5 3C7.25329 3 3 7.25329 3 12.5C3 17.7467 7.25329 22 12.5 22Z\"\n        fill={color}\n      />\n    </Svg>\n  );\n}\nexport function WalletIcon({ width, height, color, active }: TIconProps) {\n  return active ? (\n    <Svg width={width || 24} height={height || 24} viewBox=\"0 0 24 24\" fill=\"none\">\n      <Path\n        d=\"M22.0002 10.9692V13.0292C22.0002 13.5792 21.5602 14.0292 21.0002 14.0492H19.0402C17.9602 14.0492 16.9702 13.2592 16.8802 12.1792C16.8202 11.5492 17.0602 10.9592 17.4802 10.5492C17.8502 10.1692 18.3602 9.94922 18.9202 9.94922H21.0002C21.5602 9.96922 22.0002 10.4192 22.0002 10.9692Z\"\n        fill={color}\n      />\n      <Path\n        d=\"M20.47 15.55H19.04C17.14 15.55 15.54 14.12 15.38 12.3C15.29 11.26 15.67 10.22 16.43 9.48C17.07 8.82 17.96 8.45 18.92 8.45H20.47C20.76 8.45 21 8.21 20.97 7.92C20.75 5.49 19.14 3.83 16.75 3.55C16.51 3.51 16.26 3.5 16 3.5H7C6.72 3.5 6.45 3.52 6.19 3.56C3.64 3.88 2 5.78 2 8.5V15.5C2 18.26 4.24 20.5 7 20.5H16C18.8 20.5 20.73 18.75 20.97 16.08C21 15.79 20.76 15.55 20.47 15.55ZM13 9.75H7C6.59 9.75 6.25 9.41 6.25 9C6.25 8.59 6.59 8.25 7 8.25H13C13.41 8.25 13.75 8.59 13.75 9C13.75 9.41 13.41 9.75 13 9.75Z\"\n        fill={color}\n      />\n    </Svg>\n  ) : (\n    <Svg width={width || 24} height={height || 24} viewBox=\"0 0 24 24\" fill=\"none\">\n      <Path\n        d=\"M13 9H7\"\n        stroke=\"black\"\n        strokeWidth=\"1.5\"\n        strokeLinecap=\"round\"\n        strokeLinejoin=\"round\"\n      />\n      <Path\n        d=\"M22.0002 10.9699V13.03C22.0002 13.58 21.5602 14.0299 21.0002 14.0499H19.0401C17.9601 14.0499 16.9702 13.2599 16.8802 12.1799C16.8202 11.5499 17.0601 10.9599 17.4801 10.5499C17.8501 10.1699 18.3602 9.94995 18.9202 9.94995H21.0002C21.5602 9.96995 22.0002 10.4199 22.0002 10.9699Z\"\n        stroke={color}\n        strokeWidth=\"1.5\"\n        strokeLinecap=\"round\"\n        strokeLinejoin=\"round\"\n      />\n      <Path\n        d=\"M17.48 10.55C17.06 10.96 16.82 11.55 16.88 12.18C16.97 13.26 17.96 14.05 19.04 14.05H21V15.5C21 18.5 19 20.5 16 20.5H7C4 20.5 2 18.5 2 15.5V8.5C2 5.78 3.64 3.88 6.19 3.56C6.45 3.52 6.72 3.5 7 3.5H16C16.26 3.5 16.51 3.50999 16.75 3.54999C19.33 3.84999 21 5.76 21 8.5V9.95001H18.92C18.36 9.95001 17.85 10.17 17.48 10.55Z\"\n        stroke={color}\n        strokeWidth=\"1.5\"\n        strokeLinecap=\"round\"\n        strokeLinejoin=\"round\"\n      />\n    </Svg>\n  );\n}\nexport function BookIconNav({ width, height, color, active }: TIconProps) {\n  return active ? (\n    <Svg width={width || 24} height={height || 24} viewBox=\"0 0 24 24\" fill=\"none\">\n      <Path\n        d=\"M9 2C6.38 2 4.25 4.13 4.25 6.75C4.25 9.32 6.26 11.4 8.88 11.49C8.96 11.48 9.04 11.48 9.1 11.49C9.12 11.49 9.13 11.49 9.15 11.49C9.16 11.49 9.16 11.49 9.17 11.49C11.73 11.4 13.74 9.32 13.75 6.75C13.75 4.13 11.62 2 9 2Z\"\n        fill={color}\n      />\n      <Path\n        d=\"M14.0809 14.1489C11.2909 12.2889 6.74094 12.2889 3.93094 14.1489C2.66094 14.9989 1.96094 16.1489 1.96094 17.3789C1.96094 18.6089 2.66094 19.7489 3.92094 20.5889C5.32094 21.5289 7.16094 21.9989 9.00094 21.9989C10.8409 21.9989 12.6809 21.5289 14.0809 20.5889C15.3409 19.7389 16.0409 18.5989 16.0409 17.3589C16.0309 16.1289 15.3409 14.9889 14.0809 14.1489Z\"\n        fill={color}\n      />\n      <Path\n        d=\"M19.9894 7.33815C20.1494 9.27815 18.7694 10.9781 16.8594 11.2081C16.8494 11.2081 16.8494 11.2081 16.8394 11.2081H16.8094C16.7494 11.2081 16.6894 11.2081 16.6394 11.2281C15.6694 11.2781 14.7794 10.9681 14.1094 10.3981C15.1394 9.47815 15.7294 8.09815 15.6094 6.59815C15.5394 5.78815 15.2594 5.04815 14.8394 4.41815C15.2194 4.22815 15.6594 4.10815 16.1094 4.06815C18.0694 3.89815 19.8194 5.35815 19.9894 7.33815Z\"\n        fill={color}\n      />\n      <Path\n        d=\"M21.9883 16.5904C21.9083 17.5604 21.2883 18.4004 20.2483 18.9704C19.2483 19.5204 17.9883 19.7804 16.7383 19.7504C17.4583 19.1004 17.8783 18.2904 17.9583 17.4304C18.0583 16.1904 17.4683 15.0004 16.2883 14.0504C15.6183 13.5204 14.8383 13.1004 13.9883 12.7904C16.1983 12.1504 18.9783 12.5804 20.6883 13.9604C21.6083 14.7004 22.0783 15.6304 21.9883 16.5904Z\"\n        fill={color}\n      />\n    </Svg>\n  ) : (\n    <Svg width={width || 24} height={height || 24} viewBox=\"0 0 24 24\" fill=\"none\">\n      <Path\n        d=\"M9.16055 10.87C9.06055 10.86 8.94055 10.86 8.83055 10.87C6.45055 10.79 4.56055 8.84 4.56055 6.44C4.56055 3.99 6.54055 2 9.00055 2C11.4506 2 13.4406 3.99 13.4406 6.44C13.4306 8.84 11.5406 10.79 9.16055 10.87Z\"\n        stroke={color}\n        strokeWidth=\"1.5\"\n        strokeLinecap=\"round\"\n        strokeLinejoin=\"round\"\n      />\n      <Path\n        d=\"M16.4103 4C18.3503 4 19.9103 5.57 19.9103 7.5C19.9103 9.39 18.4103 10.93 16.5403 11C16.4603 10.99 16.3703 10.99 16.2803 11\"\n        stroke={color}\n        strokeWidth=\"1.5\"\n        strokeLinecap=\"round\"\n        strokeLinejoin=\"round\"\n      />\n      <Path\n        d=\"M4.15973 14.56C1.73973 16.18 1.73973 18.82 4.15973 20.43C6.90973 22.27 11.4198 22.27 14.1698 20.43C16.5898 18.81 16.5898 16.17 14.1698 14.56C11.4298 12.73 6.91973 12.73 4.15973 14.56Z\"\n        stroke={color}\n        strokeWidth=\"1.5\"\n        strokeLinecap=\"round\"\n        strokeLinejoin=\"round\"\n      />\n      <Path\n        d=\"M18.3398 20C19.0598 19.85 19.7398 19.56 20.2998 19.13C21.8598 17.96 21.8598 16.03 20.2998 14.86C19.7498 14.44 19.0798 14.16 18.3698 14\"\n        stroke={color}\n        strokeWidth=\"1.5\"\n        strokeLinecap=\"round\"\n        strokeLinejoin=\"round\"\n      />\n    </Svg>\n  );\n}\nexport function SettingsIcon({ width, height, color, active }: TIconProps) {\n  return active ? (\n    <Svg width={width || 24} height={height || 24} viewBox=\"0 0 24 24\" fill=\"none\">\n      <G clipPath=\"url(#clip0_2_7845)\">\n        <Path\n          d=\"M14.1075 1.575C13.488 -0.525 10.512 -0.525 9.8925 1.575L9.7425 2.085C9.64994 2.39939 9.48818 2.68908 9.26909 2.93282C9.05 3.17656 8.77913 3.36817 8.47634 3.4936C8.17356 3.61902 7.84654 3.67509 7.51927 3.65768C7.192 3.64028 6.87277 3.54984 6.585 3.393L6.12 3.138C4.1955 2.091 2.091 4.1955 3.1395 6.1185L3.393 6.585C4.062 7.815 3.4275 9.3465 2.085 9.7425L1.575 9.8925C-0.525 10.512 -0.525 13.488 1.575 14.1075L2.085 14.2575C2.39939 14.3501 2.68908 14.5118 2.93282 14.7309C3.17656 14.95 3.36817 15.2209 3.4936 15.5237C3.61902 15.8264 3.67509 16.1535 3.65768 16.4807C3.64028 16.808 3.54984 17.1272 3.393 17.415L3.138 17.88C2.091 19.8045 4.1955 21.909 6.1185 20.8605L6.585 20.607C6.87277 20.4502 7.192 20.3597 7.51927 20.3423C7.84654 20.3249 8.17356 20.381 8.47634 20.5064C8.77913 20.6318 9.05 20.8234 9.26909 21.0672C9.48818 21.3109 9.64994 21.6006 9.7425 21.915L9.8925 22.425C10.512 24.525 13.488 24.525 14.1075 22.425L14.2575 21.915C14.3501 21.6006 14.5118 21.3109 14.7309 21.0672C14.95 20.8234 15.2209 20.6318 15.5237 20.5064C15.8264 20.381 16.1535 20.3249 16.4807 20.3423C16.808 20.3597 17.1272 20.4502 17.415 20.607L17.88 20.862C19.8045 21.909 21.909 19.8045 20.8605 17.8815L20.607 17.415C20.4502 17.1272 20.3597 16.808 20.3423 16.4807C20.3249 16.1535 20.381 15.8264 20.5064 15.5237C20.6318 15.2209 20.8234 14.95 21.0672 14.7309C21.3109 14.5118 21.6006 14.3501 21.915 14.2575L22.425 14.1075C24.525 13.488 24.525 10.512 22.425 9.8925L21.915 9.7425C21.6006 9.64994 21.3109 9.48818 21.0672 9.26909C20.8234 9.05 20.6318 8.77913 20.5064 8.47634C20.381 8.17356 20.3249 7.84654 20.3423 7.51927C20.3597 7.192 20.4502 6.87277 20.607 6.585L20.862 6.12C21.909 4.1955 19.8045 2.091 17.8815 3.1395L17.415 3.393C17.1272 3.54984 16.808 3.64028 16.4807 3.65768C16.1535 3.67509 15.8264 3.61902 15.5237 3.4936C15.2209 3.36817 14.95 3.17656 14.7309 2.93282C14.5118 2.68908 14.3501 2.39939 14.2575 2.085L14.1075 1.575ZM12 16.395C10.8344 16.395 9.71649 15.932 8.89227 15.1077C8.06804 14.2835 7.605 13.1656 7.605 12C7.605 10.8344 8.06804 9.71649 8.89227 8.89227C9.71649 8.06804 10.8344 7.605 12 7.605C13.1652 7.605 14.2827 8.06789 15.1067 8.89183C15.9306 9.71577 16.3935 10.8333 16.3935 11.9985C16.3935 13.1637 15.9306 14.2812 15.1067 15.1052C14.2827 15.9291 13.1652 16.392 12 16.392V16.395Z\"\n          fill={color}\n        />\n      </G>\n      <Defs>\n        <ClipPath id=\"clip0_2_7845\">\n          <Rect width={width || 24} height={height || 24} fill=\"white\" />\n        </ClipPath>\n      </Defs>\n    </Svg>\n  ) : (\n    <Svg width={width || 24} height={height || 24} viewBox=\"0 0 24 24\" fill=\"none\">\n      <G clipPath=\"url(#clip0_2_7847)\">\n        <Path\n          d=\"M11.869 7C11.2296 7 10.5964 7.12594 10.0057 7.37063C9.41498 7.61532 8.87823 7.97397 8.4261 8.4261C7.97397 8.87823 7.61532 9.41498 7.37063 10.0057C7.12594 10.5964 7 11.2296 7 11.869C7 12.5084 7.12594 13.1416 7.37063 13.7323C7.61532 14.323 7.97397 14.8598 8.4261 15.3119C8.87823 15.764 9.41498 16.1227 10.0057 16.3674C10.5964 16.6121 11.2296 16.738 11.869 16.738C13.1603 16.738 14.3988 16.225 15.3119 15.3119C16.225 14.3988 16.738 13.1603 16.738 11.869C16.738 10.5777 16.225 9.33921 15.3119 8.4261C14.3988 7.51298 13.1603 7 11.869 7ZM8.5 11.869C8.5 10.9755 8.85495 10.1186 9.48676 9.48676C10.1186 8.85495 10.9755 8.5 11.869 8.5C12.7625 8.5 13.6194 8.85495 14.2512 9.48676C14.8831 10.1186 15.238 10.9755 15.238 11.869C15.238 12.7625 14.8831 13.6194 14.2512 14.2512C13.6194 14.8831 12.7625 15.238 11.869 15.238C10.9755 15.238 10.1186 14.8831 9.48676 14.2512C8.85495 13.6194 8.5 12.7625 8.5 11.869Z\"\n          fill={color}\n        />\n        <Path\n          d=\"M14.6937 2.01425C13.9032 -0.670746 10.0962 -0.670746 9.30574 2.01425L9.16474 2.49275C9.10953 2.68018 9.01308 2.85288 8.88246 2.99819C8.75184 3.1435 8.59036 3.25774 8.40985 3.33253C8.22934 3.40732 8.03439 3.44077 7.83927 3.43043C7.64415 3.42009 7.45383 3.36621 7.28224 3.27275L6.84424 3.03275C4.38424 1.69475 1.69474 4.38575 3.03424 6.84425L3.27274 7.28225C3.3662 7.45384 3.42007 7.64417 3.43041 7.83928C3.44076 8.0344 3.40731 8.22936 3.33252 8.40987C3.25772 8.59037 3.14349 8.75186 2.99818 8.88248C2.85287 9.0131 2.68017 9.10955 2.49274 9.16475L2.01424 9.30575C-0.670762 10.0963 -0.670762 13.9033 2.01424 14.6938L2.49274 14.8348C2.68017 14.89 2.85287 14.9864 2.99818 15.117C3.14349 15.2477 3.25772 15.4091 3.33252 15.5896C3.40731 15.7701 3.44076 15.9651 3.43041 16.1602C3.42007 16.3553 3.3662 16.5457 3.27274 16.7173L3.03274 17.1553C1.69474 19.6153 4.38424 22.3063 6.84424 20.9653L7.28224 20.7268C7.45383 20.6333 7.64415 20.5794 7.83927 20.5691C8.03439 20.5587 8.22934 20.5922 8.40985 20.667C8.59036 20.7418 8.75184 20.856 8.88246 21.0013C9.01308 21.1466 9.10953 21.3193 9.16474 21.5068L9.30574 21.9853C10.0962 24.6703 13.9032 24.6703 14.6937 21.9853L14.8347 21.5068C14.8899 21.3193 14.9864 21.1466 15.117 21.0013C15.2476 20.856 15.4091 20.7418 15.5896 20.667C15.7701 20.5922 15.9651 20.5587 16.1602 20.5691C16.3553 20.5794 16.5457 20.6333 16.7172 20.7268L17.1552 20.9668C19.6152 22.3063 22.3062 19.6138 20.9652 17.1553L20.7267 16.7173C20.6333 16.5457 20.5794 16.3553 20.5691 16.1602C20.5587 15.9651 20.5922 15.7701 20.667 15.5896C20.7418 15.4091 20.856 15.2477 21.0013 15.117C21.1466 14.9864 21.3193 14.89 21.5067 14.8348L21.9852 14.6938C24.6702 13.9033 24.6702 10.0963 21.9852 9.30575L21.5067 9.16475C21.3193 9.10955 21.1466 9.0131 21.0013 8.88248C20.856 8.75186 20.7418 8.59037 20.667 8.40987C20.5922 8.22936 20.5587 8.0344 20.5691 7.83928C20.5794 7.64417 20.6333 7.45384 20.7267 7.28225L20.9667 6.84425C22.3062 4.38425 19.6137 1.69475 17.1552 3.03425L16.7172 3.27275C16.5457 3.36621 16.3553 3.42009 16.1602 3.43043C15.9651 3.44077 15.7701 3.40732 15.5896 3.33253C15.4091 3.25774 15.2476 3.1435 15.117 2.99819C14.9864 2.85288 14.8899 2.68018 14.8347 2.49275L14.6937 2.01425ZM10.7442 2.43875C11.1132 1.18625 12.8862 1.18625 13.2552 2.43875L13.3962 2.91725C13.5148 3.31938 13.7218 3.68989 14.0021 4.0016C14.2825 4.31332 14.629 4.55835 15.0164 4.71872C15.4037 4.8791 15.822 4.95075 16.2407 4.92844C16.6593 4.90612 17.0676 4.7904 17.4357 4.58975L17.8722 4.34975C19.0182 3.72725 20.2722 4.97975 19.6482 6.12725L19.4097 6.56525C19.2094 6.93339 19.094 7.34169 19.0719 7.76024C19.0498 8.17878 19.1217 8.59696 19.2822 8.98413C19.4427 9.3713 19.6878 9.71766 19.9995 9.99782C20.3112 10.278 20.6817 10.4848 21.0837 10.6033L21.5607 10.7443C22.8132 11.1133 22.8132 12.8863 21.5607 13.2553L21.0822 13.3963C20.6801 13.5148 20.3096 13.7218 19.9979 14.0021C19.6862 14.2825 19.4411 14.629 19.2808 15.0164C19.1204 15.4037 19.0487 15.822 19.0711 16.2407C19.0934 16.6593 19.2091 17.0677 19.4097 17.4358L19.6497 17.8723C20.2722 19.0183 19.0197 20.2723 17.8722 19.6483L17.4357 19.4098C17.0675 19.2091 16.6591 19.0935 16.2404 19.0712C15.8217 19.049 15.4033 19.1208 15.0159 19.2813C14.6285 19.4419 14.282 19.6871 14.0018 19.9989C13.7215 20.3108 13.5146 20.6815 13.3962 21.0838L13.2552 21.5608C12.8862 22.8133 11.1132 22.8133 10.7442 21.5608L10.6032 21.0823C10.4847 20.6803 10.2777 20.31 9.99743 19.9985C9.7172 19.6869 9.37082 19.442 8.98367 19.2816C8.59652 19.1213 8.1784 19.0496 7.75994 19.0717C7.34148 19.0939 6.93328 19.2094 6.56524 19.4098L6.12724 19.6498C4.98124 20.2723 3.72724 19.0198 4.35124 17.8723L4.58974 17.4358C4.79067 17.0676 4.90661 16.6591 4.92908 16.2403C4.95154 15.8215 4.87995 15.403 4.71955 15.0154C4.55916 14.6279 4.31403 14.2812 4.00216 14.0007C3.69028 13.7203 3.31958 13.5132 2.91724 13.3948L2.43874 13.2538C1.18624 12.8848 1.18624 11.1118 2.43874 10.7428L2.91724 10.6018C3.31895 10.4831 3.68905 10.2762 4.00045 9.99604C4.31186 9.71591 4.55668 9.3697 4.71702 8.98274C4.87735 8.59578 4.94913 8.17786 4.92711 7.75958C4.90509 7.3413 4.78982 6.93324 4.58974 6.56525L4.34974 6.12725C3.72724 4.98125 4.97974 3.72725 6.12724 4.35125L6.56524 4.58975C6.93328 4.79012 7.34148 4.90561 7.75994 4.92778C8.1784 4.94995 8.59652 4.87823 8.98367 4.71788C9.37082 4.55752 9.7172 4.3126 9.99743 4.00103C10.2777 3.68947 10.4847 3.31917 10.6032 2.91725L10.7442 2.43875Z\"\n          fill={color}\n        />\n      </G>\n      <Defs>\n        <ClipPath id=\"clip0_2_7847\">\n          <Rect width={width || 24} height={height || 24} fill=\"white\" />\n        </ClipPath>\n      </Defs>\n    </Svg>\n  );\n}\nconst styles = StyleSheet.create({});\n"
  },
  {
    "path": "src/components/InputAndLabel.tsx",
    "content": "import { useThemeContext } from \"@src/context/Theme\";\nimport { useTranslation } from \"react-i18next\";\nimport { type KeyboardTypeOptions, View } from \"react-native\";\nimport { ScaledSheet } from \"react-native-size-matters\";\n\nimport { TxtButton } from \"./Button\";\nimport TxtInput from \"./TxtInput\";\n\ninterface IInputAndLabelProps {\n  keyboardType?: KeyboardTypeOptions;\n  placeholder: string;\n  setInput: (txt: string) => void;\n  value: string;\n  handleInput?: () => void;\n  handleLabel: () => void;\n  isEmptyInput?: boolean;\n}\n\nexport default function InputAndLabel({\n  keyboardType,\n  placeholder,\n  setInput,\n  value,\n  handleInput,\n  handleLabel,\n  isEmptyInput,\n}: IInputAndLabelProps) {\n  const { t } = useTranslation();\n  const { color } = useThemeContext();\n  return (\n    <View style={styles.wrap}>\n      <TxtInput\n        keyboardType={keyboardType}\n        placeholder={placeholder}\n        value={value}\n        onChangeText={setInput}\n        onSubmitEditing={handleInput}\n      />\n      {/* Paste / Clear Input */}\n      <TxtButton\n        txt={t(isEmptyInput ? \"paste\" : \"clear\")}\n        onPress={handleLabel}\n        style={[styles.pasteInputTxtWrap, { backgroundColor: color.INPUT_BG }]}\n      />\n    </View>\n  );\n}\n\nconst styles = ScaledSheet.create({\n  wrap: {\n    position: \"relative\",\n    width: \"100%\",\n  },\n  pasteInputTxtWrap: {\n    position: \"absolute\",\n    right: \"10@s\",\n    top: \"10@s\",\n    paddingTop: \"10@s\",\n    marginHorizontal: \"10@s\",\n  },\n});\n"
  },
  {
    "path": "src/components/Loading.tsx",
    "content": "import { useThemeContext } from \"@src/context/Theme\";\nimport { highlight as hi } from \"@styles\";\n\nimport AnimatedSpinner from \"./AnimatedSpinner\";\n\ninterface ILoadingProps {\n  color?: string;\n  size?: number | \"small\" | \"large\";\n}\n\nexport default function Loading({ color, size }: ILoadingProps) {\n  const { highlight } = useThemeContext();\n\n  // Convert size prop to number for AnimatedSpinner\n  const numericSize = typeof size === \"number\" ? size : size === \"large\" ? 36 : 24;\n\n  return <AnimatedSpinner color={color || hi[highlight]} size={numericSize} />;\n}\n"
  },
  {
    "path": "src/components/Logo.tsx",
    "content": "import { useThemeContext } from \"@src/context/Theme\";\nimport { Image, type ImageStyle, type StyleProp, StyleSheet, View } from \"react-native\";\n\ninterface ILogoProps {\n  size: number;\n  success?: boolean;\n  style?: StyleProp<ImageStyle>;\n}\n\nexport default function Logo({ size, success, style }: ILogoProps) {\n  const { highlight, activeTheme } = useThemeContext();\n\n  const src = success\n    ? require(\"@assets/icon_transparent_success.png\")\n    : activeTheme === \"dark\" &&\n        (highlight === \"Zap\" || highlight === \"Azyre\" || highlight === \"Rosy\")\n      ? require(\"@assets/icon_transparent_dark.png\")\n      : require(\"@assets/icon_transparent.png\");\n  return (\n    <View style={styles.imgWrap}>\n      <Image style={[styles.img, { height: size }, style]} source={src} />\n    </View>\n  );\n}\n\nconst styles = StyleSheet.create({\n  imgWrap: {\n    alignItems: \"center\",\n  },\n  img: {\n    resizeMode: \"contain\",\n  },\n});\n"
  },
  {
    "path": "src/components/MintBalance.tsx",
    "content": "import { usePrivacyContext } from \"@src/context/Privacy\";\nimport { useThemeContext } from \"@src/context/Theme\";\nimport { useCurrencyContext } from \"@src/context/Currency\";\nimport { highlight as hi } from \"@styles\";\nimport { View } from \"react-native\";\nimport { s, ScaledSheet, vs } from \"react-native-size-matters\";\n\nimport { MintBoardIcon } from \"./Icons\";\nimport Txt from \"./Txt\";\n\ninterface IMintBalanceProps {\n  balance: number;\n  txtColor: string;\n  disabled?: boolean;\n}\n\nexport default function MintBalance({ balance, txtColor, disabled }: IMintBalanceProps) {\n  const { color, highlight } = useThemeContext();\n  const { hidden } = usePrivacyContext();\n  const { formatAmount } = useCurrencyContext();\n\n  const { formatted, symbol } = formatAmount(balance);\n\n  return (\n    <View style={[styles.wrap, { borderColor: disabled ? color.TEXT_SECONDARY : hi[highlight] }]}>\n      <MintBoardIcon\n        width={s(16)}\n        height={s(16)}\n        color={disabled ? color.TEXT_SECONDARY : hi[highlight]}\n      />\n      <Txt\n        txt={hidden.balance ? \"****\" : `${formatted} ${symbol}`}\n        styles={[{ fontSize: vs(10), color: txtColor, marginLeft: s(5) }]}\n      />\n    </View>\n  );\n}\n\nconst styles = ScaledSheet.create({\n  wrap: {\n    flexDirection: \"row\",\n    alignItems: \"center\",\n    borderWidth: 1,\n    paddingVertical: \"4@vs\",\n    paddingHorizontal: \"6@s\",\n    borderRadius: 20,\n  },\n});\n"
  },
  {
    "path": "src/components/MintHeaderSelector.tsx",
    "content": "import { MintBoardIcon } from \"@comps/Icons\";\nimport MintSelectionSheet from \"@comps/MintSelectionSheet\";\nimport Txt from \"@comps/Txt\";\nimport { TrueSheet } from \"@lodev09/react-native-true-sheet\";\nimport { useCurrencyContext } from \"@src/context/Currency\";\nimport type { KnownMintWithBalance } from \"@src/context/KnownMints\";\nimport { usePrivacyContext } from \"@src/context/Privacy\";\nimport { useThemeContext } from \"@src/context/Theme\";\nimport { highlight as hi } from \"@styles\";\nimport { Image } from \"expo-image\";\nimport { useMemo, useRef } from \"react\";\nimport { TouchableOpacity, View } from \"react-native\";\nimport { ScaledSheet } from \"react-native-size-matters\";\n\ninterface IMintHeaderSelectorProps {\n  selectedMint: KnownMintWithBalance;\n  onMintSelect: (mint: KnownMintWithBalance) => void;\n  onOpen?: () => void;\n  multiSelect?: boolean;\n  showZeroBalanceMints?: boolean;\n}\n\nexport default function MintHeaderSelector({\n  selectedMint,\n  onMintSelect,\n  onOpen,\n  multiSelect = false,\n  showZeroBalanceMints = false,\n}: IMintHeaderSelectorProps) {\n  const { color, highlight } = useThemeContext();\n  const { formatAmount } = useCurrencyContext();\n  const { hidden } = usePrivacyContext();\n  const mintSelectionSheetRef = useRef<TrueSheet>(null);\n\n  const headerBalance = useMemo(() => {\n    if (hidden.balance) {\n      return \"****\";\n    }\n\n    const { formatted, symbol } = formatAmount(selectedMint.balance);\n    return `${formatted} ${symbol}`;\n  }, [formatAmount, hidden.balance, selectedMint.balance]);\n\n  const handleOpen = () => {\n    onOpen?.();\n    try {\n      mintSelectionSheetRef.current?.present();\n    } catch (error) {\n      /* ignore */\n    }\n  };\n\n  return (\n    <>\n      <TouchableOpacity\n        accessibilityRole=\"button\"\n        onPress={handleOpen}\n        activeOpacity={0.7}\n        style={[\n          styles.button,\n          {\n            backgroundColor: color.INPUT_BG,\n            borderColor: color.BORDER,\n          },\n        ]}\n      >\n        <View\n          style={[\n            styles.iconWrap,\n            {\n              backgroundColor: color.INPUT_BG,\n              borderColor: color.BORDER,\n            },\n          ]}\n        >\n          {selectedMint.mintInfo.icon_url ? (\n            <Image\n              source={{ uri: selectedMint.mintInfo.icon_url }}\n              style={styles.image}\n              contentFit=\"cover\"\n              transition={200}\n            />\n          ) : (\n            <MintBoardIcon width={18} height={18} color={hi[highlight]} />\n          )}\n        </View>\n        <Txt txt={headerBalance} bold styles={[styles.balance, { color: color.TEXT }]} />\n      </TouchableOpacity>\n\n      <MintSelectionSheet\n        ref={mintSelectionSheetRef}\n        selectedMint={selectedMint}\n        onMintSelect={onMintSelect}\n        multiSelect={multiSelect}\n        showZeroBalanceMints={showZeroBalanceMints}\n      />\n    </>\n  );\n}\n\nconst styles = ScaledSheet.create({\n  button: {\n    minWidth: \"40@s\",\n    height: \"40@s\",\n    borderRadius: \"20@s\",\n    borderWidth: 1,\n    flexDirection: \"row\",\n    alignItems: \"center\",\n    justifyContent: \"center\",\n    gap: \"8@s\",\n    paddingLeft: \"3@s\",\n    paddingRight: \"12@s\",\n    marginRight: \"12@s\",\n  },\n  iconWrap: {\n    width: \"32@s\",\n    height: \"32@s\",\n    borderRadius: \"16@s\",\n    borderWidth: 1,\n    alignItems: \"center\",\n    justifyContent: \"center\",\n    overflow: \"hidden\",\n  },\n  image: {\n    width: \"100%\",\n    height: \"100%\",\n  },\n  balance: {\n    fontSize: \"12@ms\",\n    maxWidth: \"92@s\",\n  },\n});\n"
  },
  {
    "path": "src/components/MintSelectionSheet.tsx",
    "content": "import Txt from \"@comps/Txt\";\nimport Button from \"@comps/Button\";\nimport { CheckmarkIcon } from \"@comps/Icons\";\nimport { TrueSheet } from \"@lodev09/react-native-true-sheet\";\nimport { useThemeContext } from \"@src/context/Theme\";\nimport { useCurrencyContext } from \"@src/context/Currency\";\nimport { useKnownMints, type KnownMintWithBalance } from \"@src/context/KnownMints\";\nimport { NS } from \"@src/i18n\";\nimport { mainColors } from \"@styles\";\nimport React, {\n  forwardRef,\n  useMemo,\n  useCallback,\n  memo,\n  useState,\n  useRef,\n  type MutableRefObject,\n} from \"react\";\nimport { useTranslation } from \"react-i18next\";\nimport { TouchableOpacity, View, ScrollView } from \"react-native\";\nimport { s, ScaledSheet, vs } from \"react-native-size-matters\";\nimport { useSafeAreaInsets } from \"react-native-safe-area-context\";\n\ninterface MintSelectionSheetProps {\n  selectedMint?: { mintUrl: string };\n  selectedMints?: { mintUrl: string }[];\n  onMintSelect: (mint: KnownMintWithBalance) => void;\n  onMultipleMintSelect?: (mints: KnownMintWithBalance[]) => void;\n  multiSelect?: boolean;\n  showZeroBalanceMints?: boolean;\n}\n\n// Memoize individual mint items to prevent re-renders\nconst MintItem = memo(\n  ({\n    mint,\n    isSelected,\n    onPress,\n    textColor,\n    secondaryTextColor,\n    inputBgColor,\n    multiSelect,\n    formattedBalance,\n  }: {\n    mint: KnownMintWithBalance;\n    isSelected: boolean;\n    onPress: (mint: KnownMintWithBalance) => void;\n    textColor: string;\n    secondaryTextColor: string;\n    inputBgColor: string;\n    multiSelect?: boolean;\n    formattedBalance: string;\n  }) => {\n    const handlePress = useCallback(() => onPress(mint), [onPress, mint]);\n\n    return (\n      <TouchableOpacity\n        style={[\n          styles.mintItem,\n          {\n            backgroundColor: inputBgColor,\n            borderColor: isSelected ? mainColors.VALID : \"transparent\",\n          },\n        ]}\n        onPress={handlePress}\n      >\n        <View style={styles.mintInfo}>\n          <Txt\n            txt={mint.name || new URL(mint.mintUrl).hostname}\n            styles={[styles.mintAlias, { color: textColor }]}\n          />\n          <Txt txt={mint.mintUrl} styles={[styles.mintUrl, { color: secondaryTextColor }]} />\n        </View>\n        <View style={styles.rightSection}>\n          <Txt txt={formattedBalance} styles={[styles.balance, { color: mainColors.VALID }]} />\n          {multiSelect && (\n            <View\n              style={[\n                styles.checkbox,\n                {\n                  backgroundColor: isSelected ? mainColors.VALID : \"transparent\",\n                  borderColor: isSelected ? mainColors.VALID : textColor,\n                },\n              ]}\n            >\n              {isSelected && <CheckmarkIcon color={mainColors.WHITE} width={14} height={14} />}\n            </View>\n          )}\n        </View>\n      </TouchableOpacity>\n    );\n  },\n);\n\nMintItem.displayName = \"MintItem\";\n\nconst MintSelectionSheet = forwardRef<TrueSheet, MintSelectionSheetProps>(\n  (\n    {\n      selectedMint,\n      selectedMints,\n      onMintSelect,\n      onMultipleMintSelect,\n      multiSelect = false,\n      showZeroBalanceMints = false,\n    },\n    ref,\n  ) => {\n    const { t } = useTranslation([NS.common]);\n    const { color } = useThemeContext();\n    const { formatAmount } = useCurrencyContext();\n    const { knownMints } = useKnownMints();\n    const insets = useSafeAreaInsets();\n    const sheetRef = useRef<TrueSheet>(null);\n\n    // Internal state for multi-select mode\n    const [internalSelectedMints, setInternalSelectedMints] = useState<KnownMintWithBalance[]>([]);\n\n    const setSheetRef = useCallback(\n      (sheet: TrueSheet | null) => {\n        sheetRef.current = sheet;\n\n        if (typeof ref === \"function\") {\n          ref(sheet);\n          return;\n        }\n\n        if (ref) {\n          (ref as MutableRefObject<TrueSheet | null>).current = sheet;\n        }\n      },\n      [ref],\n    );\n\n    // Determine which mints to display based on balance visibility setting\n    const displayMints = useMemo(\n      () => (showZeroBalanceMints ? knownMints : knownMints.filter((mint) => mint.balance > 0)),\n      [knownMints, showZeroBalanceMints],\n    );\n\n    // Initialize internal state when controlled selectedMints change\n    React.useEffect(() => {\n      if (multiSelect && selectedMints) {\n        const controlledSelectedMints = displayMints.filter((mint) =>\n          selectedMints.some((selected) => selected.mintUrl === mint.mintUrl),\n        );\n        setInternalSelectedMints(controlledSelectedMints);\n      }\n    }, [selectedMints, displayMints, multiSelect]);\n\n    // Determine selected mints based on mode\n    const currentSelectedMints = useMemo(() => {\n      if (multiSelect) {\n        return internalSelectedMints;\n      }\n      return selectedMint\n        ? [displayMints.find((m) => m.mintUrl === selectedMint.mintUrl)].filter(Boolean)\n        : [];\n    }, [multiSelect, internalSelectedMints, selectedMint, displayMints]);\n\n    const handleMintPress = useCallback(\n      (mint: KnownMintWithBalance) => {\n        if (multiSelect) {\n          setInternalSelectedMints((prev) => {\n            const isAlreadySelected = prev.some((selected) => selected.mintUrl === mint.mintUrl);\n            if (isAlreadySelected) {\n              return prev.filter((selected) => selected.mintUrl !== mint.mintUrl);\n            } else {\n              return [...prev, mint];\n            }\n          });\n        } else {\n          // Single select mode - close immediately\n          onMintSelect(mint);\n          void sheetRef.current?.dismiss();\n        }\n      },\n      [multiSelect, onMintSelect],\n    );\n\n    const handleConfirmMultiSelect = useCallback(() => {\n      if (onMultipleMintSelect) {\n        onMultipleMintSelect(internalSelectedMints);\n      }\n      void sheetRef.current?.dismiss();\n    }, [onMultipleMintSelect, internalSelectedMints]);\n\n    const isMintSelected = useCallback(\n      (mint: KnownMintWithBalance) => {\n        if (multiSelect) {\n          return internalSelectedMints.some((selected) => selected.mintUrl === mint.mintUrl);\n        }\n        return selectedMint?.mintUrl === mint.mintUrl;\n      },\n      [multiSelect, internalSelectedMints, selectedMint],\n    );\n\n    return (\n      <TrueSheet\n        ref={setSheetRef}\n        detents={[0.5, 1]}\n        backgroundColor={color.BACKGROUND}\n        cornerRadius={s(26)}\n        grabberOptions={{ color: color.TEXT_SECONDARY }}\n        scrollable\n        scrollableOptions={{\n          topScrollEdgeEffect: \"hidden\",\n          bottomScrollEdgeEffect: \"hidden\",\n        }}\n      >\n        <ScrollView\n          style={{ backgroundColor: color.BACKGROUND }}\n          contentContainerStyle={[styles.scrollContent, { paddingBottom: insets.bottom }]}\n          showsVerticalScrollIndicator={false}\n        >\n          <View\n            style={[\n              styles.header,\n              {\n                backgroundColor: color.BACKGROUND,\n                borderBottomColor: color.BORDER || \"rgba(0,0,0,0.1)\",\n              },\n            ]}\n          >\n            <Txt\n              txt={\n                multiSelect\n                  ? t(\"selectMints\", { ns: NS.common })\n                  : t(\"selectMint\", { ns: NS.common })\n              }\n              styles={[styles.headerText, { color: color.TEXT }]}\n            />\n          </View>\n\n          {displayMints.length === 0 ? (\n            <View style={styles.emptyState}>\n              <Txt\n                txt={t(\"noMintsWithBalance\", {\n                  ns: NS.common,\n                })}\n                styles={[{ color: color.TEXT_SECONDARY }]}\n              />\n            </View>\n          ) : (\n            <>\n              {displayMints.map((mint) => {\n                const { formatted, symbol } = formatAmount(mint.balance);\n                const formattedBalance = `${formatted} ${symbol}`;\n\n                return (\n                  <MintItem\n                    key={mint.mintUrl}\n                    mint={mint}\n                    isSelected={isMintSelected(mint)}\n                    onPress={handleMintPress}\n                    textColor={color.TEXT}\n                    secondaryTextColor={color.TEXT_SECONDARY}\n                    inputBgColor={color.INPUT_BG}\n                    multiSelect={multiSelect}\n                    formattedBalance={formattedBalance}\n                  />\n                );\n              })}\n\n              {multiSelect && (\n                <View style={[styles.buttonContainer, { paddingBottom: insets.bottom + vs(16) }]}>\n                  <Button\n                    txt={t(\"confirm\", { ns: NS.common })}\n                    onPress={handleConfirmMultiSelect}\n                    disabled={internalSelectedMints.length === 0}\n                  />\n                </View>\n              )}\n            </>\n          )}\n        </ScrollView>\n      </TrueSheet>\n    );\n  },\n);\n\nconst styles = ScaledSheet.create({\n  header: {\n    paddingVertical: \"10@vs\",\n    alignItems: \"center\",\n    borderBottomWidth: 1,\n    marginBottom: \"16@vs\",\n  },\n  headerText: {\n    fontSize: \"18@s\",\n    fontWeight: \"600\",\n  },\n  selectedCount: {\n    fontSize: \"12@s\",\n    marginTop: \"4@vs\",\n  },\n  scrollContent: {\n    paddingHorizontal: \"16@s\",\n    paddingTop: \"30@vs\",\n  },\n  emptyState: {\n    padding: \"20@s\",\n    alignItems: \"center\",\n  },\n  mintItem: {\n    flexDirection: \"row\",\n    alignItems: \"center\",\n    padding: \"16@s\",\n    marginBottom: \"12@vs\",\n    borderRadius: \"12@s\",\n    borderWidth: 2,\n    minHeight: \"70@vs\",\n  },\n  mintInfo: {\n    flex: 1,\n    marginRight: \"12@s\",\n  },\n  rightSection: {\n    alignItems: \"flex-end\",\n    justifyContent: \"center\",\n  },\n  mintAlias: {\n    fontSize: \"16@s\",\n    fontWeight: \"500\",\n    marginBottom: \"4@vs\",\n  },\n  mintUrl: {\n    fontSize: \"12@s\",\n  },\n  balance: {\n    fontSize: \"14@s\",\n    fontWeight: \"600\",\n    marginBottom: \"8@vs\",\n  },\n  checkbox: {\n    width: \"22@s\",\n    height: \"22@s\",\n    borderRadius: \"4@s\",\n    borderWidth: 1.5,\n    alignItems: \"center\",\n    justifyContent: \"center\",\n  },\n  buttonContainer: {\n    paddingHorizontal: \"16@s\",\n    paddingTop: \"20@vs\",\n  },\n});\n\nexport default MintSelectionSheet;\n"
  },
  {
    "path": "src/components/MintSelector.tsx",
    "content": "import { useThemeContext } from \"@src/context/Theme\";\nimport { usePrivacyContext } from \"@src/context/Privacy\";\nimport { useCurrencyContext } from \"@src/context/Currency\";\nimport { formatMintUrl } from \"@util\";\nimport { TouchableOpacity, View, type ViewStyle, type StyleProp } from \"react-native\";\nimport { s, ScaledSheet, vs } from \"react-native-size-matters\";\nimport type { KnownMintWithBalance } from \"@src/context/KnownMints\";\nimport { ChevronRightIcon } from \"./Icons\";\nimport Txt from \"./Txt\";\nimport Card from \"./Card\";\n\ninterface IMintSelectorProps {\n  mint: KnownMintWithBalance;\n  onPress: (mint: KnownMintWithBalance) => void;\n  variant?: \"base\" | \"accent\";\n  style?: StyleProp<ViewStyle>;\n  label?: string;\n}\n\nexport default function MintSelector({\n  mint,\n  onPress,\n  variant = \"base\",\n  style,\n  label,\n}: IMintSelectorProps) {\n  const { color } = useThemeContext();\n  const { hidden } = usePrivacyContext();\n  const { formatAmount } = useCurrencyContext();\n\n  const displayName = mint.mintInfo.name || formatMintUrl(mint.mintUrl);\n\n  const { formatted, symbol } = formatAmount(mint.balance);\n  const displayBalance = hidden.balance ? \"****\" : `${formatted} ${symbol}`;\n\n  return (\n    <TouchableOpacity onPress={() => onPress(mint)} activeOpacity={0.7} style={style}>\n      <Card variant={variant} style={styles.cardContent}>\n        {label && (\n          <Txt\n            txt={label}\n            styles={[\n              {\n                color: color.TEXT_SECONDARY,\n                fontSize: s(12),\n                marginBottom: vs(8),\n              },\n            ]}\n          />\n        )}\n        <View style={styles.container}>\n          {/* Mint name and balance container */}\n          <View style={styles.infoContainer}>\n            <Txt txt={displayName} bold styles={[{ color: color.TEXT }]} />\n            <Txt\n              txt={displayBalance}\n              styles={[\n                {\n                  color: color.TEXT_SECONDARY,\n                  fontSize: s(12),\n                },\n              ]}\n            />\n          </View>\n\n          {/* Chevron icon */}\n          <View style={styles.chevronContainer}>\n            <ChevronRightIcon color={color.TEXT} />\n          </View>\n        </View>\n      </Card>\n    </TouchableOpacity>\n  );\n}\n\nconst styles = ScaledSheet.create({\n  cardContent: {\n    padding: \"12@s\",\n  },\n  container: {\n    flexDirection: \"row\",\n    alignItems: \"center\",\n    gap: \"8@s\",\n  },\n  infoContainer: {\n    flex: 1,\n    flexDirection: \"row\",\n    alignItems: \"center\",\n    justifyContent: \"space-between\",\n  },\n  chevronContainer: {\n    marginLeft: \"8@s\",\n  },\n});\n"
  },
  {
    "path": "src/components/Option.tsx",
    "content": "import { useThemeContext } from \"@src/context/Theme\";\nimport { globals } from \"@styles\";\nimport { TouchableOpacity, View } from \"react-native\";\nimport { s, ScaledSheet } from \"react-native-size-matters\";\n\nimport { ChevronRightIcon } from \"./Icons\";\nimport Loading from \"./Loading\";\nimport Separator from \"./Separator\";\nimport Txt from \"./Txt\";\n\ninterface IOptionProps {\n  txt: string;\n  hint: string;\n  onPress: () => void;\n  icon?: React.ReactNode;\n  hasSeparator?: boolean;\n  loading?: boolean;\n  secondIcon?: React.ReactNode;\n}\n\nexport default function Option({\n  icon,\n  txt,\n  hint,\n  onPress,\n  hasSeparator,\n  loading,\n  secondIcon,\n}: IOptionProps) {\n  const { color } = useThemeContext();\n  return (\n    <>\n      <TouchableOpacity style={globals().wrapRow} onPress={onPress} testID={`send-option-${txt}`}>\n        <View style={styles.txtWrap}>\n          {icon ? <View style={{ minWidth: s(40) }}>{icon}</View> : null}\n          <View>\n            <Txt txt={txt} bold />\n            <Txt styles={[styles.targetHint, { color: color.TEXT_SECONDARY }]} txt={hint} />\n          </View>\n        </View>\n        {loading ? (\n          <Loading />\n        ) : secondIcon ? (\n          <View style={styles.iconWrap}>{secondIcon}</View>\n        ) : (\n          <ChevronRightIcon color={color.TEXT} />\n        )}\n      </TouchableOpacity>\n      {hasSeparator && <Separator />}\n    </>\n  );\n}\n\nconst styles = ScaledSheet.create({\n  targetHint: {\n    fontSize: \"10@vs\",\n  },\n  txtWrap: {\n    flexDirection: \"row\",\n    alignItems: \"center\",\n    maxWidth: \"80%\",\n  },\n  iconWrap: {\n    marginRight: \"-5@s\",\n  },\n});\n"
  },
  {
    "path": "src/components/OverviewRow.tsx",
    "content": "import Separator from \"@comps/Separator\";\nimport Txt from \"@comps/Txt\";\nimport { globalStyles as globals } from \"@src/styles/globals\";\nimport { View } from \"react-native\";\n\nexport function OverviewRow({ txt1, txt2 }: { txt1: string; txt2: string }) {\n  return (\n    <>\n      <View style={globals().wrapRow}>\n        <Txt txt={txt1} bold />\n        <Txt txt={txt2} />\n      </View>\n      <Separator />\n    </>\n  );\n}\n"
  },
  {
    "path": "src/components/Progress.tsx",
    "content": "import { useThemeContext } from \"@src/context/Theme\";\nimport { highlight as hi } from \"@styles\";\nimport { StyleSheet, View } from \"react-native\";\n\nimport Txt from \"./Txt\";\n\ninterface IProgressProps {\n  progress: number;\n  withIndicator?: boolean;\n  contactsCount?: number;\n  doneCount?: number;\n}\n\nexport default function Progress({\n  progress,\n  withIndicator,\n  contactsCount,\n  doneCount,\n}: IProgressProps) {\n  const { color, highlight } = useThemeContext();\n  return (\n    <>\n      <View style={[styles.progress, { backgroundColor: color.INPUT_BG }]}>\n        <View\n          style={[styles.bar, { width: `${progress * 100}%`, backgroundColor: hi[highlight] }]}\n        />\n      </View>\n      {withIndicator && (\n        <Txt\n          txt={`${progress * 100}% - ${doneCount}/${contactsCount}`}\n          styles={[styles.indicator]}\n        />\n      )}\n    </>\n  );\n}\n\nconst styles = StyleSheet.create({\n  progress: {\n    width: \"100%\",\n    height: 5,\n    marginBottom: 20,\n  },\n  bar: {\n    height: 5,\n  },\n  indicator: {\n    textAlign: \"center\",\n    marginBottom: 20,\n  },\n});\n"
  },
  {
    "path": "src/components/QR.tsx",
    "content": "import { useThemeContext } from \"@src/context/Theme\";\nimport { NS } from \"@src/i18n\";\nimport { mainColors } from \"@src/styles\";\nimport { useTranslation } from \"react-i18next\";\nimport { TouchableOpacity, View } from \"react-native\";\nimport QRCode from \"react-native-qrcode-svg\";\nimport { s, ScaledSheet } from \"react-native-size-matters\";\n\nimport useCopy from \"./hooks/Copy\";\nimport { CheckmarkIcon, CopyIcon } from \"./Icons\";\nimport Txt from \"./Txt\";\nimport { useAnimatedQr } from \"./hooks/AnimatedQr\";\n\nfunction truncateStr(str: string, len: number): string {\n  if (!str) return \"\";\n  if (str.length <= len) return str;\n  return str.slice(0, len) + \"...\";\n}\n\ninterface QRProps {\n  size: number;\n  value: string;\n  isInvoice?: boolean;\n  animate?: boolean;\n  truncateNum?: number;\n  onError: () => void;\n}\n\nexport default function QR({ size, value, animate, truncateNum, onError }: QRProps) {\n  const { t } = useTranslation([NS.common]);\n  const { color } = useThemeContext();\n  const { copied, copy } = useCopy();\n  const chunk = useAnimatedQr(value, { animate });\n  return (\n    <TouchableOpacity onPress={() => void copy(value)}>\n      <View style={styles.qrWrap}>\n        <QRCode\n          size={size}\n          value={chunk}\n          testID=\"qr-code\"\n          logoBorderRadius={10}\n          logoBackgroundColor={mainColors.WHITE}\n          logoMargin={s(6)}\n          onError={onError}\n        />\n      </View>\n      <View\n        style={[\n          styles.txtContainer,\n          {\n            borderColor: color.BORDER,\n            backgroundColor: color.INPUT_BG,\n          },\n        ]}\n      >\n        <View style={styles.iconCon}>\n          {copied ? <CheckmarkIcon color={mainColors.VALID} /> : <CopyIcon color={color.TEXT} />}\n        </View>\n        <Txt\n          txt={copied ? t(\"copied\") : truncateStr(value, truncateNum ?? 20)}\n          styles={[{ color: copied ? mainColors.VALID : color.TEXT }]}\n        />\n      </View>\n    </TouchableOpacity>\n  );\n}\n\nconst styles = ScaledSheet.create({\n  qrWrap: {\n    borderWidth: \"10@s\",\n    borderColor: mainColors.WHITE,\n    borderTopLeftRadius: 10,\n    borderTopRightRadius: 10,\n  },\n  txtContainer: {\n    flexDirection: \"row\",\n    alignItems: \"center\",\n    justifyContent: \"center\",\n    padding: \"15@s\",\n    borderWidth: 1,\n    borderBottomLeftRadius: 10,\n    borderBottomRightRadius: 10,\n  },\n  iconCon: {\n    minWidth: \"30@s\",\n  },\n});\n"
  },
  {
    "path": "src/components/RadioBtn.tsx",
    "content": "import { useThemeContext } from \"@src/context/Theme\";\nimport { globals, highlight as hi } from \"@styles\";\nimport { View } from \"react-native\";\n\nexport default function RadioBtn({ selected }: { selected?: boolean }) {\n  const { color, highlight } = useThemeContext();\n  return (\n    <View\n      style={[\n        globals(color, highlight).radioBtn,\n        { backgroundColor: selected ? hi[highlight] : \"transparent\" },\n      ]}\n    />\n  );\n}\n"
  },
  {
    "path": "src/components/Screen.tsx",
    "content": "import TopNav from \"@nav/TopNav\";\nimport { isIOS } from \"@consts\";\nimport { useThemeContext } from \"@src/context/Theme\";\nimport { globals } from \"@styles\";\nimport type { ReactNode } from \"react\";\nimport { View } from \"react-native\";\nimport { useSafeAreaInsets } from \"react-native-safe-area-context\";\nimport { KeyboardAvoidingView } from \"react-native-keyboard-controller\";\n\ninterface IContainerProps {\n  children: ReactNode;\n  screenName?: string;\n  withBackBtn?: boolean;\n  withCancelBtn?: boolean;\n  handlePress?: () => void;\n  handleCancel?: () => void;\n  rightAction?: ReactNode;\n  withPadding?: boolean;\n  withBottomInset?: boolean;\n  withKeyboard?: boolean;\n}\n\nexport default function Screen({\n  children,\n  screenName,\n  withBackBtn,\n  withCancelBtn,\n  handlePress,\n  handleCancel,\n  rightAction,\n  withPadding = true,\n  withBottomInset = true,\n  withKeyboard = false,\n}: IContainerProps) {\n  const { color } = useThemeContext();\n  const insets = useSafeAreaInsets();\n\n  const containerStyle = [\n    globals(color).container,\n    {\n      paddingTop: insets.top,\n      paddingBottom: withBottomInset ? insets.bottom : 0,\n    },\n  ];\n\n  const contentStyle = {\n    flex: 1,\n    padding: withPadding ? 8 : 0,\n  };\n\n  const content = withKeyboard ? (\n    <KeyboardAvoidingView\n      style={{ flex: 1 }}\n      behavior={isIOS ? \"padding\" : \"height\"}\n      keyboardVerticalOffset={0}\n    >\n      <View style={contentStyle}>{children}</View>\n    </KeyboardAvoidingView>\n  ) : (\n    <View style={contentStyle}>{children}</View>\n  );\n\n  return (\n    <View style={containerStyle}>\n      <TopNav\n        screenName={screenName || \"\"}\n        withBackBtn={withBackBtn}\n        cancel={withCancelBtn}\n        handleCancel={handleCancel}\n        handlePress={handlePress}\n        rightAction={rightAction}\n      />\n      {content}\n    </View>\n  );\n}\n\nexport function ScreenWithKeyboard(props: IContainerProps) {\n  return <Screen {...props} withKeyboard={true} />;\n}\n"
  },
  {
    "path": "src/components/Separator.tsx",
    "content": "import { useThemeContext } from \"@src/context/Theme\";\nimport { type StyleProp, View, type ViewStyle } from \"react-native\";\nimport { ScaledSheet, vs } from \"react-native-size-matters\";\n\ninterface ISeparatorProps {\n  style?: StyleProp<ViewStyle>;\n  noMargin?: boolean;\n}\n\nexport default function Separator({ style, noMargin }: ISeparatorProps) {\n  const { color } = useThemeContext();\n  return (\n    <View\n      style={[\n        styles.separator,\n        {\n          borderColor: color.DARK_BORDER,\n          marginBottom: noMargin ? 0 : vs(20),\n        },\n        style,\n      ]}\n    />\n  );\n}\n\nconst styles = ScaledSheet.create({\n  separator: {\n    borderBottomWidth: 1,\n  },\n});\n"
  },
  {
    "path": "src/components/SwipeButton.tsx",
    "content": "import { useThemeContext } from \"@src/context/Theme\";\nimport { highlight as hi, mainColors } from \"@styles\";\nimport { useEffect, useImperativeHandle, forwardRef } from \"react\";\nimport { View, useWindowDimensions } from \"react-native\";\nimport { Gesture, GestureDetector } from \"react-native-gesture-handler\";\nimport Animated, {\n  Extrapolation,\n  interpolate,\n  interpolateColor,\n  runOnJS,\n  useAnimatedStyle,\n  useSharedValue,\n  withSpring,\n} from \"react-native-reanimated\";\nimport { ScaledSheet } from \"react-native-size-matters\";\n\nimport { ChevronRightIcon } from \"./Icons\";\n\nconst BUTTON_PADDING = 10;\nconst BUTTON_HEIGHT = 72;\nconst HORIZONTAL_MARGIN = 20;\nconst SWIPEABLE_DIMENSIONS = BUTTON_HEIGHT - 2 * BUTTON_PADDING;\n\nconst SPRING_CONFIG = {\n  mass: 1,\n  damping: 75,\n  stiffness: 250,\n  overshootClamping: true,\n  restDisplacementThreshold: 0.01,\n  restSpeedThreshold: 2.8,\n};\nconst AnimatedView = Animated.createAnimatedComponent(View);\n\ninterface ISwipeButtonProps {\n  txt: string;\n  onToggle: (isToggled: boolean) => void;\n}\n\nexport interface SwipeButtonHandle {\n  reset: () => void;\n}\n\nfunction SwipeButton({ txt, onToggle }: ISwipeButtonProps, ref: React.Ref<SwipeButtonHandle>) {\n  const { color, highlight } = useThemeContext();\n  const { width: windowWidth } = useWindowDimensions();\n  const X = useSharedValue(0);\n  const toggled = useSharedValue(false);\n\n  const BUTTON_WIDTH = windowWidth - HORIZONTAL_MARGIN * 2;\n  const H_WAVE_RANGE = SWIPEABLE_DIMENSIONS + 2 * BUTTON_PADDING;\n  const H_SWIPE_RANGE = BUTTON_WIDTH - 2 * BUTTON_PADDING - SWIPEABLE_DIMENSIONS;\n  const SWIPE_THRESHOLD = H_SWIPE_RANGE / 2;\n\n  const handleComplete = (isToggled: boolean) => {\n    onToggle(isToggled);\n  };\n\n  const reset = () => {\n    X.value = withSpring(0, SPRING_CONFIG);\n    toggled.value = false;\n  };\n\n  useImperativeHandle(ref, () => ({\n    reset,\n  }));\n\n  useEffect(() => {\n    // Reset animation when window dimensions change\n    reset();\n  }, [windowWidth]);\n\n  const panGesture = Gesture.Pan()\n    .onStart(() => {\n      // Store the current toggle state at gesture start\n    })\n    .onUpdate((e) => {\n      let newValue;\n      if (toggled.value) {\n        newValue = H_SWIPE_RANGE + e.translationX;\n      } else {\n        newValue = e.translationX;\n      }\n      if (newValue >= 0 && newValue <= H_SWIPE_RANGE) {\n        X.value = newValue;\n      }\n    })\n    .onEnd(() => {\n      const wasToggled = toggled.value;\n      if (X.value < SWIPE_THRESHOLD) {\n        X.value = withSpring(0, SPRING_CONFIG);\n        toggled.value = false;\n      } else {\n        X.value = withSpring(H_SWIPE_RANGE, SPRING_CONFIG);\n        // Only trigger the callback if we weren't already toggled\n        // This means the user just completed the swipe for the first time\n        if (!wasToggled) {\n          toggled.value = true;\n          runOnJS(handleComplete)(true);\n        }\n      }\n    });\n\n  const InterpolateXInput = [0, H_SWIPE_RANGE];\n  const AnimatedStyles = {\n    colorWave: useAnimatedStyle(() => ({\n      width: H_WAVE_RANGE + X.value,\n      opacity: interpolate(X.value, InterpolateXInput, [0, 1]),\n    })),\n    swipeable: useAnimatedStyle(() => ({\n      backgroundColor: interpolateColor(\n        X.value,\n        [0, H_SWIPE_RANGE],\n        [hi[highlight], mainColors.WHITE],\n      ),\n      transform: [{ translateX: X.value }],\n    })),\n    swipeText: useAnimatedStyle(() => ({\n      opacity: interpolate(X.value, [0, H_SWIPE_RANGE / 2], [1, 0], Extrapolation.CLAMP),\n      transform: [\n        {\n          translateX: interpolate(\n            X.value,\n            InterpolateXInput,\n            [0, H_SWIPE_RANGE / 2],\n            Extrapolation.CLAMP,\n          ),\n        },\n      ],\n    })),\n    chevron: useAnimatedStyle(() => ({\n      opacity: interpolate(X.value, [0, H_SWIPE_RANGE], [1, 0], Extrapolation.CLAMP),\n    })),\n  };\n\n  return (\n    <View style={styles.container}>\n      <Animated.View\n        style={[styles.swipeCont, { backgroundColor: color.INPUT_BG, width: BUTTON_WIDTH }]}\n        accessible={true}\n        accessibilityRole=\"button\"\n        accessibilityLabel={txt}\n        accessibilityHint=\"Swipe right to confirm\"\n      >\n        <AnimatedView\n          style={[AnimatedStyles.colorWave, styles.colorWave, { backgroundColor: hi[highlight] }]}\n        />\n        <GestureDetector gesture={panGesture}>\n          <Animated.View\n            style={[styles.swipeable, AnimatedStyles.swipeable, { borderColor: color.INPUT_PH }]}\n            testID=\"swipe-confirm-button\"\n          >\n            <Animated.View style={AnimatedStyles.chevron}>\n              <ChevronRightIcon color={mainColors.WHITE} />\n            </Animated.View>\n          </Animated.View>\n        </GestureDetector>\n        <Animated.Text style={[styles.swipeText, AnimatedStyles.swipeText, { color: color.TEXT }]}>\n          {txt}\n        </Animated.Text>\n      </Animated.View>\n    </View>\n  );\n}\n\nexport default forwardRef(SwipeButton);\n\nconst styles = ScaledSheet.create({\n  container: {\n    paddingHorizontal: \"20@s\",\n    paddingTop: \"5@s\",\n  },\n  swipeCont: {\n    height: BUTTON_HEIGHT,\n    borderRadius: BUTTON_HEIGHT,\n    padding: BUTTON_PADDING,\n    display: \"flex\",\n    justifyContent: \"center\",\n    alignItems: \"center\",\n    flexDirection: \"row\",\n  },\n  colorWave: {\n    position: \"absolute\",\n    left: 0,\n    height: BUTTON_HEIGHT,\n    borderRadius: BUTTON_HEIGHT,\n  },\n  swipeable: {\n    position: \"absolute\",\n    left: BUTTON_PADDING,\n    height: SWIPEABLE_DIMENSIONS,\n    width: SWIPEABLE_DIMENSIONS,\n    borderRadius: SWIPEABLE_DIMENSIONS,\n    alignItems: \"center\",\n    justifyContent: \"center\",\n    zIndex: 3,\n    borderWidth: 5,\n  },\n  swipeText: {\n    alignSelf: \"center\",\n    fontSize: \"14@vs\",\n    fontWeight: \"500\",\n    zIndex: 2,\n  },\n});\n"
  },
  {
    "path": "src/components/Toaster.tsx",
    "content": "import { usePromptContext } from \"@src/context/Prompt\";\nimport { mainColors } from \"@src/styles\";\nimport { TouchableOpacity } from \"react-native\";\nimport Animated, { FadeInUp, FadeOutUp } from \"react-native-reanimated\";\nimport { useSafeAreaInsets } from \"react-native-safe-area-context\";\nimport { ScaledSheet, vs } from \"react-native-size-matters\";\n\nimport Txt from \"./Txt\";\n\nexport default function Toaster() {\n  const insets = useSafeAreaInsets();\n  const { prompt, closePrompt } = usePromptContext();\n  return (\n    prompt.open && (\n      <Animated.View\n        entering={FadeInUp}\n        exiting={FadeOutUp}\n        style={[\n          styles.container,\n          {\n            backgroundColor: prompt.success ? mainColors.VALID : mainColors.ERROR,\n            top: insets.top + vs(20),\n          },\n        ]}\n      >\n        <TouchableOpacity\n          onPress={closePrompt}\n          style={styles.txtWrap}\n          testID={`${prompt.success ? \"success\" : \"error\"}-toaster`}\n        >\n          <Txt center txt={prompt.msg} styles={[styles.txt]} />\n        </TouchableOpacity>\n      </Animated.View>\n    )\n  );\n}\n\nconst styles = ScaledSheet.create({\n  container: {\n    position: \"absolute\",\n    alignItems: \"center\",\n    left: \"20@s\",\n    right: \"20@s\",\n    borderRadius: 8,\n    shadowColor: \"#171717\",\n    shadowOffset: { width: 3, height: 3 },\n    shadowOpacity: 0.2,\n    shadowRadius: 3,\n    elevation: 20,\n  },\n  txtWrap: {\n    width: \"100%\",\n    padding: \"15@s\",\n    alignItems: \"center\",\n    justifyContent: \"center\",\n  },\n  txt: {\n    fontSize: \"16@vs\",\n    color: mainColors.WHITE,\n  },\n});\n"
  },
  {
    "path": "src/components/Toggle.tsx",
    "content": "import { isIOS } from \"@consts\";\nimport { useThemeContext } from \"@src/context/Theme\";\nimport { highlight as hi } from \"@styles\";\nimport { Switch } from \"react-native\";\nimport { ScaledSheet } from \"react-native-size-matters\";\n\ninterface IToggleProps {\n  value: boolean;\n  onChange: () => void;\n  disabled?: boolean;\n}\n\nexport default function Toggle({ value, onChange, disabled }: IToggleProps) {\n  const { color, highlight } = useThemeContext();\n  return (\n    <Switch\n      trackColor={{ false: color.BORDER, true: hi[highlight] }}\n      thumbColor={color.TEXT}\n      onValueChange={onChange}\n      value={value}\n      style={[styles.switch, disabled && styles.disabled]}\n      disabled={disabled}\n    />\n  );\n}\n\nconst styles = ScaledSheet.create({\n  switch: {\n    marginVertical: \"-10@vs\",\n    transform: [{ scaleX: isIOS ? 0.6 : 1 }, { scaleY: isIOS ? 0.6 : 1 }],\n  },\n  disabled: {\n    opacity: 0.5,\n  },\n});\n"
  },
  {
    "path": "src/components/Txt.tsx",
    "content": "import { useThemeContext } from \"@src/context/Theme\";\nimport { globals, mainColors } from \"@styles\";\nimport { type StyleProp, Text, type TextStyle } from \"react-native\";\n\ninterface ITxtProps {\n  txt: string;\n  bold?: boolean;\n  center?: boolean;\n  error?: boolean;\n  success?: boolean;\n  styles?: StyleProp<TextStyle>[];\n}\n\nexport default function Txt({ txt, bold, center, error, success, styles }: ITxtProps) {\n  const { color } = useThemeContext();\n  return (\n    <Text\n      style={[\n        bold ? globals(color).txtBold : globals(color).txt,\n        {\n          color: error ? mainColors.ERROR : success ? mainColors.VALID : color.TEXT,\n          textAlign: center ? \"center\" : \"left\",\n        },\n        ...(styles || []),\n      ]}\n      testID={`${txt}-txt`}\n    >\n      {txt}\n    </Text>\n  );\n}\n"
  },
  {
    "path": "src/components/TxtInput.tsx",
    "content": "import { useThemeContext } from \"@src/context/Theme\";\nimport { globals, highlight as hi } from \"@styles\";\nimport { createRef, type LegacyRef, useEffect } from \"react\";\nimport {\n  type KeyboardTypeOptions,\n  type NativeSyntheticEvent,\n  type StyleProp,\n  TextInput,\n  type TextInputSubmitEditingEventData,\n  type TextStyle,\n} from \"react-native\";\nimport { vs } from \"react-native-size-matters\";\n\ninterface ITxtInputProps {\n  autoCorrect?: boolean;\n  keyboardType?: KeyboardTypeOptions;\n  placeholder: string;\n  onChangeText: (text: string) => void;\n  onSubmitEditing?: (e: NativeSyntheticEvent<TextInputSubmitEditingEventData>) => void;\n  innerRef?: LegacyRef<TextInput>;\n  autoFocus?: boolean;\n  ms?: number;\n  maxLength?: number;\n  value?: string;\n  multiline?: boolean;\n  numberOfLines?: number;\n  style?: StyleProp<TextStyle>;\n  autoCapitalize?: \"none\" | \"sentences\" | \"words\" | \"characters\";\n}\n\nexport default function TxtInput({\n  keyboardType,\n  placeholder,\n  onChangeText,\n  onSubmitEditing,\n  innerRef,\n  autoFocus,\n  ms,\n  maxLength,\n  value,\n  multiline,\n  numberOfLines,\n  style,\n  autoCorrect,\n  autoCapitalize,\n}: ITxtInputProps) {\n  const { color, highlight } = useThemeContext();\n  const inputRef = createRef<TextInput>();\n  // auto-focus\n  useEffect(() => {\n    if (!autoFocus) {\n      return;\n    }\n    const t = setTimeout(() => {\n      inputRef.current?.focus();\n      clearTimeout(t);\n    }, ms || 200);\n    // eslint-disable-next-line react-hooks/exhaustive-deps\n  }, []);\n  return (\n    <TextInput\n      ref={innerRef || inputRef}\n      keyboardType={keyboardType || \"default\"}\n      placeholder={placeholder}\n      placeholderTextColor={color.INPUT_PH}\n      autoCorrect={autoCorrect}\n      selectionColor={hi[highlight]}\n      cursorColor={hi[highlight]}\n      onChangeText={onChangeText}\n      onSubmitEditing={onSubmitEditing}\n      maxLength={maxLength}\n      value={value}\n      multiline={multiline}\n      numberOfLines={numberOfLines}\n      style={[globals(color).input, style]}\n      testID={`${placeholder}-input`}\n      autoCapitalize={autoCapitalize}\n    />\n  );\n}\n"
  },
  {
    "path": "src/components/animation/Shake.ts",
    "content": "import { useCallback, useRef } from \"react\";\nimport { Animated } from \"react-native\";\n\nexport const useShakeAnimation = () => {\n  const anim = useRef(new Animated.Value(0));\n  const shake = useCallback(() => {\n    // makes the sequence loop\n    Animated.loop(\n      // runs the animation array in sequence\n      Animated.sequence([\n        // shift element to the left by 2 units\n        Animated.timing(anim.current, {\n          toValue: -2,\n          duration: 40,\n          useNativeDriver: true,\n        }),\n        // shift element to the right by 2 units\n        Animated.timing(anim.current, {\n          toValue: 2,\n          duration: 40,\n          useNativeDriver: true,\n        }),\n        // bring the element back to its original position\n        Animated.timing(anim.current, {\n          toValue: 0,\n          duration: 40,\n          useNativeDriver: true,\n        }),\n      ]),\n      // loops the above animation config 3 times\n      { iterations: 3 },\n    ).start();\n  }, []);\n  return { anim, shake };\n};\n"
  },
  {
    "path": "src/components/hooks/AnimatedQr.ts",
    "content": "import { useCallback, useState } from \"react\";\nimport { useFocusEffect } from \"@react-navigation/native\";\nimport { UR, UREncoder } from \"@gandlaf21/bc-ur\";\n\ntype AnimatedQrOptions = {\n  intervalMs?: number;\n  maxFragmentLen?: number;\n  startWithUr?: boolean;\n  animate?: boolean;\n  minLengthToAnimate?: number;\n};\n\nexport const useAnimatedQr = (payload: string, options: AnimatedQrOptions = {}): string => {\n  const {\n    intervalMs = 250,\n    maxFragmentLen = 200,\n    startWithUr = true,\n    animate = true,\n    minLengthToAnimate = 150,\n  } = options;\n\n  const [chunk, setChunk] = useState<string>(payload || \"\");\n\n  useFocusEffect(\n    useCallback(() => {\n      if (!payload) {\n        setChunk(\"\");\n        return;\n      }\n\n      const shouldAnimate = animate && payload.length >= minLengthToAnimate;\n      if (!shouldAnimate) {\n        setChunk(payload);\n        return;\n      }\n\n      try {\n        const messageBuffer =\n          typeof TextEncoder !== \"undefined\"\n            ? new TextEncoder().encode(payload)\n            : new Uint8Array([...payload].map((c) => c.charCodeAt(0)));\n\n        const ur = UR.from(messageBuffer);\n        const encoder = new UREncoder(ur, maxFragmentLen, 0);\n\n        setChunk(startWithUr ? encoder.nextPart() : payload);\n\n        const timer = setInterval(() => {\n          const nextChunk = encoder.nextPart();\n          setChunk(nextChunk);\n        }, intervalMs);\n\n        return () => {\n          console.log(\"clearing timer\");\n          clearInterval(timer);\n        };\n      } catch (error) {\n        // Fall back to original payload if UR encoding fails\n        // Guard dev-only logging to avoid noise in production\n        try {\n          // @ts-ignore - __DEV__ is provided by React Native envs\n          if (typeof __DEV__ !== \"undefined\" && __DEV__) {\n            // eslint-disable-next-line no-console\n            console.warn(\"UR encoding failed, using original payload:\", error);\n          }\n        } catch (_) {\n          // no-op\n        }\n        setChunk(payload);\n      }\n    }, [payload, intervalMs, maxFragmentLen, startWithUr, animate, minLengthToAnimate]),\n  );\n\n  return chunk || payload;\n};\n"
  },
  {
    "path": "src/components/hooks/Copy.tsx",
    "content": "import { copyStrToClipboard } from \"@src/util\";\nimport { useCallback, useRef, useState } from \"react\";\n\nexport default function useCopy() {\n  const timerId = useRef<NodeJS.Timeout | null>(null);\n  const [copied, setCopied] = useState(false);\n\n  const clearTimer = useCallback(() => {\n    if (timerId.current) {\n      clearTimeout(timerId.current);\n    }\n    timerId.current = null;\n  }, []);\n\n  const copy = useCallback(\n    async (s: string) => {\n      await copyStrToClipboard(s);\n      setCopied(true);\n      if (timerId.current) {\n        clearTimer();\n      }\n      timerId.current = setTimeout(() => {\n        setCopied(false);\n        clearTimer();\n      }, 3000);\n    },\n    [clearTimer],\n  );\n\n  return {\n    copied,\n    copy,\n  };\n}\n"
  },
  {
    "path": "src/components/hooks/Loading.tsx",
    "content": "import { useState } from \"react\";\n\nexport default function useLoading() {\n  const [loading, setLoading] = useState(false);\n  const startLoading = () => setLoading(true);\n  const stopLoading = () => setLoading(false);\n\n  return {\n    loading,\n    startLoading,\n    stopLoading,\n  };\n}\n"
  },
  {
    "path": "src/components/hooks/useCashuClaimFlow.ts",
    "content": "import { getDecodedToken, Token } from \"@cashu/cashu-ts\";\nimport { useReceiveOperation } from \"@cashu/coco-react\";\nimport { usePromptContext } from \"@src/context/Prompt\";\nimport { useManager } from \"@src/context/Manager\";\nimport { NS } from \"@src/i18n\";\nimport { useTrustMint } from \"@modal/TrustMintProvider\";\nimport { isErr } from \"@src/util\";\nimport { useTranslation } from \"react-i18next\";\n\nexport type ClaimResult = SuccessClaimResult | CancelledClaimResult | ErrorClaimResult;\ntype SuccessClaimResult = {\n  token: Token;\n  amount: number;\n  status: \"success\";\n};\ntype CancelledClaimResult = {\n  status: \"cancelled\";\n};\ntype ErrorClaimResult = {\n  status: \"error\";\n  error: string;\n};\n\nexport function useCashuClaimFlow() {\n  const { t } = useTranslation([NS.common, NS.error, NS.wallet]);\n  const { openPromptAutoClose } = usePromptContext();\n  const manager = useManager();\n  const { open: openTrustMint } = useTrustMint();\n  const { prepare, execute, isLoading: isReceiving } = useReceiveOperation();\n\n  const claimFromTokenString = async (tokenStr: string): Promise<ClaimResult> => {\n    try {\n      const decoded = getDecodedToken(tokenStr);\n      const amount = decoded.proofs.reduce(\n        (acc: number, proof: { amount: number }) => acc + proof.amount,\n        0,\n      );\n      const isKnown = await manager.mint.isTrustedMint(decoded.mint);\n      if (isKnown) {\n        await prepare({ token: decoded });\n        await execute();\n        return {\n          status: \"success\",\n          token: decoded,\n          amount,\n        };\n      }\n\n      const action = await openTrustMint(decoded);\n      if (action === \"trust\") {\n        await manager.mint.addMint(decoded.mint, { trusted: true });\n        await manager.wallet.receive(decoded);\n        return { status: \"success\", token: decoded, amount };\n      }\n      // If cancelled or any other action, just abort as per requirement\n      return { status: \"cancelled\" };\n    } catch (e) {\n      console.error(e);\n      openPromptAutoClose({\n        msg: isErr(e) ? e.message : t(\"claimTokenErr\", { ns: NS.error }),\n      });\n      return {\n        status: \"error\",\n        error: isErr(e) ? e.message : \"Something went wrong\",\n      };\n    }\n  };\n\n  return { claimFromTokenString, isReceiving };\n}\n"
  },
  {
    "path": "src/components/hooks/useDiscoverMints.ts",
    "content": "import { useState, useEffect, useMemo } from \"react\";\nimport { useMints } from \"@cashu/coco-react\";\nimport { appLogger } from \"@src/logger\";\nimport { normalizeMintUrl } from \"@util\";\n\ntype MintRecommendation = {\n  id: number;\n  url: string;\n  info: string;\n  name: string;\n  balance: number;\n  sum_donations: number;\n  updated_at: string;\n  next_update: string;\n  state: string;\n  n_errors: number;\n  n_mints: number;\n  n_melts: number;\n};\n\ninterface UseDiscoverMintsResult {\n  recommendations: MintRecommendation[];\n  isLoading: boolean;\n  isError: boolean;\n}\n\nexport default function useDiscoverMints(): UseDiscoverMintsResult {\n  const [allRecommendations, setAllRecommendations] = useState<MintRecommendation[]>([]);\n  const [isLoading, setIsLoading] = useState(true);\n  const [isError, setIsError] = useState(false);\n  const { mints } = useMints();\n\n  useEffect(() => {\n    async function fetchRecommendations() {\n      setIsLoading(true);\n      try {\n        const res = await fetch(\"https://api.audit.8333.space/mints\");\n        if (!res.ok) {\n          setIsError(true);\n          setIsLoading(false);\n          return;\n        }\n\n        const data: MintRecommendation[] = await res.json();\n        setAllRecommendations(data);\n        setIsLoading(false);\n      } catch (error) {\n        appLogger.error(\"useDiscoverMints:fetchRecommendations\", error);\n        setIsError(true);\n        setIsLoading(false);\n      }\n    }\n    fetchRecommendations();\n  }, []);\n\n  // Filter out mints that are already trusted\n  const recommendations = useMemo(() => {\n    const trustedMintUrls = new Set(\n      mints.filter((mint) => mint.trusted).map((mint) => normalizeMintUrl(mint.mintUrl)),\n    );\n\n    return allRecommendations.filter((recommendation) => {\n      const normalizedUrl = normalizeMintUrl(recommendation.url);\n      return !trustedMintUrls.has(normalizedUrl);\n    });\n  }, [allRecommendations, mints]);\n\n  return {\n    recommendations,\n    isLoading,\n    isError,\n  };\n}\n"
  },
  {
    "path": "src/components/hooks/useNfcPayment.ts",
    "content": "import { useState, useCallback } from \"react\";\nimport { useManager } from \"@cashu/coco-react\";\nimport { getEncodedToken } from \"@cashu/cashu-ts\";\nimport NfcCashuPayment, { NfcError } from \"@src/services/NFCService\";\nimport { appLogger } from \"@src/logger\";\nimport { parsePaymentString, type PaymentCandidateKind } from \"@util/paymentStringParser\";\n\nconst log = appLogger.child({ name: \"useNfcPayment\" });\n\ntype TNfcPaymentHandoffKind = Extract<\n  PaymentCandidateKind,\n  \"lightningInvoice\" | \"lightningAddress\" | \"lnurl\"\n>;\n\nconst NFC_CANDIDATE_PRIORITY: PaymentCandidateKind[] = [\n  \"cashuPaymentRequest\",\n  \"lightningInvoice\",\n  \"lightningAddress\",\n  \"lnurl\",\n];\n\nfunction selectNfcCandidate(request: string) {\n  const candidates = parsePaymentString(request);\n  return NFC_CANDIDATE_PRIORITY.map((kind) =>\n    candidates.find((candidate) => candidate.kind === kind),\n  ).find((candidate) => Boolean(candidate));\n}\n\nfunction isNfcPaymentHandoffKind(kind: PaymentCandidateKind): kind is TNfcPaymentHandoffKind {\n  return kind === \"lightningInvoice\" || kind === \"lightningAddress\" || kind === \"lnurl\";\n}\n\nexport interface NfcPaymentHandoff {\n  kind: TNfcPaymentHandoffKind;\n  value: string;\n}\n\nexport interface NfcPaymentResult {\n  success: boolean;\n  paymentRequest?: string;\n  amount?: number;\n  mint?: string;\n  error?: string;\n  errorCode?: string;\n  handoff?: NfcPaymentHandoff;\n}\n\nexport interface StartPaymentOptions {\n  /** Maximum amount in sats to allow. If the request exceeds this, payment is aborted. */\n  maxAmount?: number;\n}\n\n/**\n * Error thrown when a payment request exceeds the configured limit.\n * Contains all information needed to complete the payment after user confirmation.\n */\nexport class LimitExceededError extends Error {\n  code = \"LIMIT_EXCEEDED\";\n  paymentRequest: string;\n  amount: number;\n  mint: string;\n  maxAmount: number;\n\n  constructor(paymentRequest: string, amount: number, mint: string, maxAmount: number) {\n    super(`Amount ${amount} sats exceeds limit of ${maxAmount} sats`);\n    this.name = \"LimitExceededError\";\n    this.paymentRequest = paymentRequest;\n    this.amount = amount;\n    this.mint = mint;\n    this.maxAmount = maxAmount;\n  }\n}\n\nexport interface UseNfcPaymentOptions {\n  /** Called when payment starts */\n  onPaymentStart?: () => void;\n  /** Called when payment completes successfully */\n  onPaymentSuccess?: (result: NfcPaymentResult) => void;\n  /** Called when payment fails */\n  onPaymentError?: (result: NfcPaymentResult) => void;\n  /** Called when payment amount exceeds the configured limit */\n  onLimitExceeded?: (error: LimitExceededError) => void;\n  /** Called when the NFC payload should be handled by another payment flow */\n  onPaymentHandoff?: (handoff: NfcPaymentHandoff) => void;\n  /** Called when payment ends (success or failure) */\n  onPaymentEnd?: () => void;\n}\n\nexport interface UseNfcPaymentReturn {\n  /** Whether an NFC payment is currently in progress */\n  isActive: boolean;\n  /** Current status message for UI display */\n  statusMessage: string;\n  /** Initiate an NFC payment */\n  startPayment: (options?: StartPaymentOptions) => Promise<NfcPaymentResult>;\n  /** Complete a payment that exceeded the limit (after user confirmation) */\n  completeOverLimitPayment: (\n    paymentRequest: string,\n    amount: number,\n    mint: string,\n  ) => Promise<NfcPaymentResult>;\n  /** Cancel the current payment (if possible) */\n  cancel: () => void;\n}\n\n/**\n * Custom hook for handling NFC Cashu payments.\n *\n * @example\n * ```tsx\n * const { isActive, statusMessage, startPayment } = useNfcPayment({\n *   onPaymentSuccess: (result) => {\n *     console.log(`Paid ${result.amount} sats!`);\n *   },\n *   onPaymentError: (result) => {\n *     console.error(result.error);\n *   },\n * });\n *\n * // Pay with no limit\n * <Button onPress={() => startPayment()} title=\"Pay\" />\n *\n * // Pay with max 1000 sats limit\n * <Button onPress={() => startPayment({ maxAmount: 1000 })} title=\"Pay (max 1000 sats)\" />\n * ```\n */\nexport function useNfcPayment(options: UseNfcPaymentOptions = {}): UseNfcPaymentReturn {\n  const {\n    onPaymentStart,\n    onPaymentSuccess,\n    onPaymentError,\n    onLimitExceeded,\n    onPaymentHandoff,\n    onPaymentEnd,\n  } = options;\n  const manager = useManager();\n  const [isActive, setIsActive] = useState(false);\n  const [statusMessage, setStatusMessage] = useState(\"Ready\");\n\n  const startPayment = useCallback(\n    async (paymentOptions: StartPaymentOptions = {}): Promise<NfcPaymentResult> => {\n      const { maxAmount } = paymentOptions;\n\n      if (isActive) {\n        log.warn(\"Payment already in progress\");\n        return {\n          success: false,\n          error: \"Payment already in progress\",\n          errorCode: \"ALREADY_ACTIVE\",\n        };\n      }\n\n      setIsActive(true);\n      setStatusMessage(\"Hold near terminal...\");\n      onPaymentStart?.();\n\n      let paymentAmount: number | undefined;\n      let paymentMint: string | undefined;\n      let paymentRequest: string | undefined;\n      let paymentHandoff: NfcPaymentHandoff | undefined;\n\n      try {\n        const result = await NfcCashuPayment.performPayment(async (request) => {\n          const selectedCandidate = selectNfcCandidate(request);\n\n          if (!selectedCandidate) {\n            throw new Error(\"NFC payload does not contain a supported payment request\");\n          }\n\n          if (isNfcPaymentHandoffKind(selectedCandidate.kind)) {\n            paymentHandoff = {\n              kind: selectedCandidate.kind,\n              value: selectedCandidate.value,\n            };\n            setStatusMessage(\"Opening payment screen...\");\n            return { type: \"finish\" };\n          }\n\n          const cashuPaymentRequest = selectedCandidate.value;\n          paymentRequest = cashuPaymentRequest;\n          log.info(\"Payment request received\");\n          setStatusMessage(\"Processing payment...\");\n          const parsedPr = await manager.paymentRequests.parse(cashuPaymentRequest);\n          if (parsedPr.transport.type !== \"inband\") {\n            throw new Error(\"NFC payment request uses an unsupported payment transport\");\n          }\n          if (parsedPr.payableMints.length === 0) {\n            throw new Error(\"No matching mints found\");\n          }\n          if (!parsedPr.amount) {\n            throw new Error(\"Payment request has no amount specified\");\n          }\n          if (maxAmount !== undefined && parsedPr.amount > maxAmount) {\n            log.warn(`Payment amount ${parsedPr.amount} exceeds max allowed ${maxAmount}`);\n            throw new LimitExceededError(\n              cashuPaymentRequest,\n              parsedPr.amount,\n              parsedPr.payableMints[0],\n              maxAmount,\n            );\n          }\n          const preparedRequest = await manager.paymentRequests.prepare(parsedPr, {\n            mintUrl: parsedPr.payableMints[0],\n          });\n          paymentAmount = preparedRequest.sendOperation.amount;\n          paymentMint = preparedRequest.sendOperation.mintUrl;\n          log.info(`Creating token for ${parsedPr.amount} sats from ${parsedPr.payableMints[0]}`);\n          setStatusMessage(`Sending ${parsedPr.amount} sats...`);\n          const executionResult = await manager.paymentRequests.execute(preparedRequest);\n          if (executionResult.type !== \"inband\") {\n            throw new Error(\"Terminal returned an unsupported payment transport\");\n          }\n          const token = executionResult.token;\n\n          setStatusMessage(\"Writing to terminal...\");\n          return { type: \"writeText\", text: getEncodedToken(token) };\n        });\n\n        if (!result.wroteResponse && paymentHandoff) {\n          log.info(`NFC payment handoff received: ${paymentHandoff.kind}`);\n          setStatusMessage(\"Opening payment screen...\");\n          onPaymentHandoff?.(paymentHandoff);\n          return {\n            success: false,\n            paymentRequest: result.request,\n            handoff: paymentHandoff,\n          };\n        }\n\n        log.info(\"NFC payment completed successfully\");\n        setStatusMessage(\"Payment complete!\");\n\n        const successResult: NfcPaymentResult = {\n          success: true,\n          paymentRequest: result.request,\n          amount: paymentAmount,\n          mint: paymentMint,\n        };\n\n        onPaymentSuccess?.(successResult);\n        return successResult;\n      } catch (error) {\n        // Handle limit exceeded separately - don't treat as error\n        if (error instanceof LimitExceededError) {\n          log.info(\n            `Payment requires confirmation: ${error.amount} sats exceeds limit of ${error.maxAmount} sats`,\n          );\n          setStatusMessage(\"Confirmation required\");\n          onLimitExceeded?.(error);\n          // Return a result indicating limit exceeded (not a failure)\n          return {\n            success: false,\n            paymentRequest: error.paymentRequest,\n            amount: error.amount,\n            mint: error.mint,\n            error: error.message,\n            errorCode: error.code,\n          };\n        }\n\n        const errorMessage = error instanceof Error ? error.message : \"NFC payment failed\";\n        const errorCode = error instanceof NfcError ? error.code : \"UNKNOWN\";\n\n        log.error(\"NFC payment failed:\", errorMessage);\n        setStatusMessage(\"Payment failed\");\n\n        const errorResult: NfcPaymentResult = {\n          success: false,\n          paymentRequest,\n          amount: paymentAmount,\n          mint: paymentMint,\n          error: errorMessage,\n          errorCode,\n        };\n\n        onPaymentError?.(errorResult);\n        return errorResult;\n      } finally {\n        setIsActive(false);\n        setStatusMessage(\"Ready\");\n        onPaymentEnd?.();\n      }\n    },\n    [\n      isActive,\n      manager,\n      onPaymentStart,\n      onPaymentSuccess,\n      onPaymentError,\n      onLimitExceeded,\n      onPaymentHandoff,\n      onPaymentEnd,\n    ],\n  );\n\n  /**\n   * Complete a payment that exceeded the limit after user confirmation.\n   * This creates the token and writes it to the NFC tag in a new session.\n   */\n  const completeOverLimitPayment = useCallback(\n    async (paymentRequest: string, amount: number, mint: string): Promise<NfcPaymentResult> => {\n      if (isActive) {\n        log.warn(\"Payment already in progress\");\n        return {\n          success: false,\n          error: \"Payment already in progress\",\n          errorCode: \"ALREADY_ACTIVE\",\n        };\n      }\n\n      setIsActive(true);\n      onPaymentStart?.();\n\n      try {\n        // Create the token\n        log.info(`Creating token for confirmed payment: ${amount} sats from ${mint}`);\n        setStatusMessage(`Sending ${amount} sats...`);\n        const preparedSend = await manager.ops.send.prepare({ mintUrl: mint, amount });\n        const { token } = await manager.ops.send.execute(preparedSend.id);\n        const encodedToken = getEncodedToken(token);\n\n        // Write to NFC in a new session\n        log.info(\"Writing token to NFC...\");\n        setStatusMessage(\"Hold near terminal...\");\n        await NfcCashuPayment.writeCashuToken(encodedToken);\n\n        log.info(\"Over-limit payment completed successfully\");\n        setStatusMessage(\"Payment complete!\");\n\n        const successResult: NfcPaymentResult = {\n          success: true,\n          paymentRequest,\n          amount,\n          mint,\n        };\n\n        onPaymentSuccess?.(successResult);\n        return successResult;\n      } catch (error) {\n        const errorMessage = error instanceof Error ? error.message : \"NFC payment failed\";\n        const errorCode = error instanceof NfcError ? error.code : \"UNKNOWN\";\n\n        log.error(\"Over-limit payment failed:\", errorMessage);\n        setStatusMessage(\"Payment failed\");\n\n        const errorResult: NfcPaymentResult = {\n          success: false,\n          paymentRequest,\n          amount,\n          mint,\n          error: errorMessage,\n          errorCode,\n        };\n\n        onPaymentError?.(errorResult);\n        return errorResult;\n      } finally {\n        setIsActive(false);\n        setStatusMessage(\"Ready\");\n        onPaymentEnd?.();\n      }\n    },\n    [isActive, manager, onPaymentStart, onPaymentSuccess, onPaymentError, onPaymentEnd],\n  );\n\n  const cancel = useCallback(() => {\n    // Note: NFC operations can't be truly cancelled mid-flight,\n    // but we can reset the UI state\n    if (isActive) {\n      log.info(\"Payment cancelled by user\");\n      setIsActive(false);\n      setStatusMessage(\"Ready\");\n    }\n  }, [isActive]);\n\n  return {\n    isActive,\n    statusMessage,\n    startPayment,\n    completeOverLimitPayment,\n    cancel,\n  };\n}\n\nexport default useNfcPayment;\n"
  },
  {
    "path": "src/components/hooks/useUrDecoder.ts",
    "content": "import { useCallback, useMemo, useRef, useState } from \"react\";\nimport { UR, URDecoder } from \"@gandlaf21/bc-ur\";\n\ntype UseUrDecoderOptions = {\n  allowedTypes?: string[];\n};\n\ntype AddPartResult = {\n  accepted: boolean;\n  complete: boolean;\n  progress: number; // 0..1 based on received/expected\n  estimated: number; // 0..1 estimated percent complete including duplicates handling\n};\n\nexport function useUrDecoder(options: UseUrDecoderOptions = {}) {\n  const { allowedTypes = [\"bytes\"] } = options;\n\n  const decoderRef = useRef<URDecoder>(new URDecoder());\n  const [active, setActive] = useState(false);\n  const [complete, setComplete] = useState(false);\n  const [error, setError] = useState<string | undefined>(undefined);\n  const [progress, setProgress] = useState(0);\n  const [estimated, setEstimated] = useState(0);\n  const [expectedCount, setExpectedCount] = useState(0);\n  const [receivedCount, setReceivedCount] = useState(0);\n  const [lastIndexes, setLastIndexes] = useState<number[]>([]);\n  const [resultUr, setResultUr] = useState<UR | undefined>(undefined);\n  const [decodedString, setDecodedString] = useState<string | undefined>(undefined);\n\n  const reset = useCallback(() => {\n    decoderRef.current = new URDecoder();\n    setActive(false);\n    setComplete(false);\n    setError(undefined);\n    setProgress(0);\n    setEstimated(0);\n    setExpectedCount(0);\n    setReceivedCount(0);\n    setLastIndexes([]);\n    setResultUr(undefined);\n    setDecodedString(undefined);\n  }, []);\n\n  const addPart = useCallback(\n    (part: string): AddPartResult => {\n      // Accept only UR parts\n      const lower = part.trim().toLowerCase();\n      if (!lower.startsWith(\"ur:\")) {\n        return {\n          accepted: false,\n          complete: false,\n          progress: decoderRef.current.getProgress?.() ?? 0,\n          estimated: decoderRef.current.estimatedPercentComplete?.() ?? 0,\n        };\n      }\n\n      // Validate allowed types on the first part\n      try {\n        const [type] = URDecoder.parse(lower);\n        if (allowedTypes.length && !allowedTypes.includes(type)) {\n          return {\n            accepted: false,\n            complete: false,\n            progress,\n            estimated,\n          };\n        }\n      } catch (e) {\n        // Parse error: ignore silently\n        return {\n          accepted: false,\n          complete: false,\n          progress: decoderRef.current.getProgress?.() ?? 0,\n          estimated: decoderRef.current.estimatedPercentComplete?.() ?? 0,\n        };\n      }\n\n      setActive(true);\n\n      try {\n        decoderRef.current.receivePart(lower);\n\n        const isComplete = decoderRef.current.isComplete();\n        const newProgress = decoderRef.current.getProgress();\n        const newEstimated = decoderRef.current.estimatedPercentComplete();\n        const newExpected = decoderRef.current.expectedPartCount();\n        const newReceived = decoderRef.current.receivedPartIndexes().length;\n        const newLast = decoderRef.current.lastPartIndexes();\n\n        setProgress(newProgress);\n        setEstimated(newEstimated);\n        setExpectedCount(newExpected);\n        setReceivedCount(newReceived);\n        setLastIndexes(newLast);\n\n        if (decoderRef.current.isError()) {\n          setError(decoderRef.current.resultError());\n          setActive(false);\n        }\n\n        if (isComplete) {\n          const ur = decoderRef.current.resultUR();\n          setResultUr(ur);\n          try {\n            const decoded = ur.decodeCBOR();\n            // @ts-ignore RN Buffer polyfill supports toString\n            const asString: string = decoded.toString();\n            setDecodedString(asString);\n          } catch (e) {\n            // If decoding fails, leave decodedString undefined\n          }\n          setComplete(true);\n          setActive(false);\n        }\n\n        return {\n          accepted: true,\n          complete: isComplete,\n          progress: newProgress,\n          estimated: newEstimated,\n        };\n      } catch (e: any) {\n        setError(e?.message || \"Decode error\");\n        setActive(false);\n        return {\n          accepted: false,\n          complete: false,\n          progress: decoderRef.current.getProgress?.() ?? 0,\n          estimated: decoderRef.current.estimatedPercentComplete?.() ?? 0,\n        };\n      }\n    },\n    [allowedTypes],\n  );\n\n  return useMemo(\n    () => ({\n      addPart,\n      reset,\n      active,\n      complete,\n      error,\n      progress,\n      estimated,\n      expectedCount,\n      receivedCount,\n      lastIndexes,\n      resultUr,\n      decodedString,\n    }),\n    [\n      addPart,\n      reset,\n      active,\n      complete,\n      error,\n      progress,\n      estimated,\n      expectedCount,\n      receivedCount,\n      lastIndexes,\n      resultUr,\n      decodedString,\n    ],\n  );\n}\n"
  },
  {
    "path": "src/components/modal/ConfirmBottomSheet.tsx",
    "content": "import React, { forwardRef, useCallback, useImperativeHandle, useRef, useState } from \"react\";\nimport { TrueSheet } from \"@lodev09/react-native-true-sheet\";\nimport { ScrollView, Text, View } from \"react-native\";\nimport { s, ScaledSheet, vs } from \"react-native-size-matters\";\nimport { useSafeAreaInsets } from \"react-native-safe-area-context\";\nimport { useThemeContext } from \"@src/context/Theme\";\nimport { globals } from \"@styles\";\nimport Button from \"@comps/Button\";\n\nexport type ConfirmBottomSheetRef = {\n  open: (options: {\n    header: string;\n    txt: string;\n    confirmTxt: string;\n    cancelTxt: string;\n    onConfirm: () => void;\n    onCancel?: () => void;\n    destructive?: boolean;\n  }) => void;\n  close: () => void;\n};\n\ninterface SheetOptions {\n  header: string;\n  txt: string;\n  confirmTxt: string;\n  cancelTxt: string;\n  onConfirm: () => void;\n  onCancel?: () => void;\n  destructive?: boolean;\n}\n\nconst ConfirmBottomSheet = forwardRef<ConfirmBottomSheetRef>((_, ref) => {\n  const { color, highlight } = useThemeContext();\n  const insets = useSafeAreaInsets();\n  const sheetRef = useRef<TrueSheet>(null);\n  const notifyCancelOnDismissRef = useRef(false);\n  const [options, setOptions] = useState<SheetOptions | null>(null);\n\n  const close = useCallback((closeOptions?: { notifyCancel?: boolean }) => {\n    notifyCancelOnDismissRef.current = closeOptions?.notifyCancel ?? false;\n    void sheetRef.current?.dismiss();\n  }, []);\n\n  const open = useCallback((newOptions: SheetOptions) => {\n    setOptions(newOptions);\n    notifyCancelOnDismissRef.current = false;\n    setTimeout(() => {\n      try {\n        void sheetRef.current?.present();\n      } catch {\n        /* ignore */\n      }\n    }, 0);\n  }, []);\n\n  useImperativeHandle(ref, () => ({ open, close }), [open, close]);\n\n  const handleConfirm = useCallback(() => {\n    if (options?.onConfirm) {\n      options.onConfirm();\n    }\n    close();\n  }, [options, close]);\n\n  const handleCancel = useCallback(() => {\n    close({ notifyCancel: true });\n  }, [close]);\n\n  const handleDismiss = useCallback(() => {\n    const shouldNotifyCancel = notifyCancelOnDismissRef.current;\n    notifyCancelOnDismissRef.current = false;\n\n    if (shouldNotifyCancel && options?.onCancel) {\n      options.onCancel();\n    }\n  }, [options]);\n\n  return (\n    <TrueSheet\n      ref={sheetRef}\n      detents={[\"auto\"]}\n      dismissible={false}\n      draggable={false}\n      backgroundColor={color.BACKGROUND}\n      cornerRadius={s(26)}\n      grabberOptions={{ color: color.TEXT_SECONDARY }}\n      onDidDismiss={handleDismiss}\n    >\n      <ScrollView\n        style={{ backgroundColor: color.BACKGROUND }}\n        contentContainerStyle={[\n          styles.container,\n          { paddingBottom: Math.max(insets.bottom, vs(20)) },\n        ]}\n        showsVerticalScrollIndicator={false}\n      >\n        {options && (\n          <>\n            <Text style={[globals(color, highlight).modalHeader, { marginBottom: vs(15) }]}>\n              {options.header}\n            </Text>\n            <Text style={[styles.message, { color: color.TEXT }]}>{options.txt}</Text>\n            <View style={styles.buttonContainer}>\n              <Button\n                txt={options.confirmTxt}\n                onPress={handleConfirm}\n                outlined={!options.destructive}\n                destructive={options.destructive}\n              />\n              <Button txt={options.cancelTxt} onPress={handleCancel} outlined />\n            </View>\n          </>\n        )}\n      </ScrollView>\n    </TrueSheet>\n  );\n});\n\nConfirmBottomSheet.displayName = \"ConfirmBottomSheet\";\n\nconst styles = ScaledSheet.create({\n  container: {\n    paddingHorizontal: \"20@s\",\n    paddingTop: \"30@vs\",\n  },\n  message: {\n    fontSize: \"14@vs\",\n    marginBottom: \"20@vs\",\n    lineHeight: \"20@vs\",\n  },\n  buttonContainer: {\n    width: \"100%\",\n    gap: \"10@vs\",\n  },\n});\n\nexport default ConfirmBottomSheet;\n"
  },
  {
    "path": "src/components/modal/ConfirmationModal.tsx",
    "content": "import Button from \"@comps/Button\";\nimport Txt from \"@comps/Txt\";\nimport { TrueSheet } from \"@lodev09/react-native-true-sheet\";\nimport { useThemeContext } from \"@src/context/Theme\";\nimport { globals } from \"@styles\";\nimport React, { forwardRef, useCallback, useImperativeHandle, useRef, type ReactNode } from \"react\";\nimport { ScrollView, Text, useWindowDimensions, View } from \"react-native\";\nimport { useSafeAreaInsets } from \"react-native-safe-area-context\";\nimport { s, ScaledSheet, vs } from \"react-native-size-matters\";\n\nexport type ConfirmationModalRef = {\n  present: () => void;\n  close: (options?: { notifyCancel?: boolean }) => void;\n};\n\ninterface IConfirmationModalProps {\n  title: string;\n  subtitle?: string;\n  confirmText: string;\n  cancelText: string;\n  loading?: boolean;\n  confirmDisabled?: boolean;\n  onConfirm: () => void;\n  onCancel: () => void;\n  children: ReactNode;\n}\n\nconst ConfirmationModal = forwardRef<ConfirmationModalRef, IConfirmationModalProps>(\n  (\n    {\n      title,\n      subtitle,\n      confirmText,\n      cancelText,\n      loading = false,\n      confirmDisabled = false,\n      onConfirm,\n      onCancel,\n      children,\n    },\n    ref,\n  ) => {\n    const { color, highlight } = useThemeContext();\n    const insets = useSafeAreaInsets();\n    const { height } = useWindowDimensions();\n    const sheetRef = useRef<TrueSheet>(null);\n    const notifyCancelOnDismissRef = useRef(true);\n    const maxDynamicContentSize = Math.floor(height * 0.9);\n\n    const present = useCallback(() => {\n      notifyCancelOnDismissRef.current = true;\n      void sheetRef.current?.present();\n    }, []);\n\n    const close = useCallback((options?: { notifyCancel?: boolean }) => {\n      notifyCancelOnDismissRef.current = options?.notifyCancel ?? false;\n      void sheetRef.current?.dismiss();\n    }, []);\n\n    useImperativeHandle(ref, () => ({ present, close }), [present, close]);\n\n    const handleCancel = useCallback(() => {\n      close({ notifyCancel: true });\n    }, [close]);\n\n    const handleDismiss = useCallback(() => {\n      const shouldNotifyCancel = notifyCancelOnDismissRef.current;\n      notifyCancelOnDismissRef.current = true;\n\n      if (shouldNotifyCancel) {\n        onCancel();\n      }\n    }, [onCancel]);\n\n    return (\n      <TrueSheet\n        ref={sheetRef}\n        detents={[\"auto\"]}\n        maxContentHeight={maxDynamicContentSize}\n        dismissible={false}\n        draggable={false}\n        backgroundColor={color.BACKGROUND}\n        cornerRadius={s(26)}\n        grabberOptions={{ color: color.TEXT_SECONDARY }}\n        scrollable\n        onDidDismiss={handleDismiss}\n      >\n        <ScrollView\n          style={[styles.scrollContainer, { backgroundColor: color.BACKGROUND }]}\n          contentContainerStyle={[\n            styles.container,\n            { paddingBottom: Math.max(insets.bottom, vs(20)) },\n          ]}\n          showsVerticalScrollIndicator={false}\n        >\n          <View style={styles.headerWrap}>\n            <Text style={[globals(color, highlight).modalHeader, styles.headerTitle]}>{title}</Text>\n            {subtitle ? (\n              <Txt\n                txt={subtitle}\n                center\n                styles={[styles.subtitle, { color: color.TEXT_SECONDARY }]}\n              />\n            ) : null}\n          </View>\n\n          {children}\n\n          <View style={styles.buttonContainer}>\n            <Button\n              txt={confirmText}\n              onPress={onConfirm}\n              loading={loading}\n              disabled={confirmDisabled}\n            />\n            <Button txt={cancelText} onPress={handleCancel} outlined disabled={loading} />\n          </View>\n        </ScrollView>\n      </TrueSheet>\n    );\n  },\n);\n\nConfirmationModal.displayName = \"ConfirmationModal\";\n\nconst styles = ScaledSheet.create({\n  scrollContainer: {\n    flex: 1,\n  },\n  container: {\n    paddingHorizontal: \"20@s\",\n    paddingTop: \"30@vs\",\n  },\n  headerWrap: {\n    marginBottom: \"18@vs\",\n  },\n  headerTitle: {\n    marginBottom: \"6@vs\",\n  },\n  subtitle: {\n    fontSize: \"14@vs\",\n    lineHeight: \"20@vs\",\n  },\n  buttonContainer: {\n    width: \"100%\",\n    gap: \"10@vs\",\n    marginBottom: \"4@vs\",\n  },\n});\n\nexport default ConfirmationModal;\n"
  },
  {
    "path": "src/components/modal/MeltConfirmationModal.tsx",
    "content": "import Card from \"@comps/Card\";\nimport Copy from \"@comps/Copy\";\nimport ConfirmationModal, { type ConfirmationModalRef } from \"@modal/ConfirmationModal\";\nimport OperationMintPanel, { type IOperationMintPanelRow } from \"@modal/OperationMintPanel\";\nimport Separator from \"@comps/Separator\";\nimport Txt from \"@comps/Txt\";\nimport type { MeltOperation } from \"@cashu/coco-core\";\nimport { useCurrencyContext } from \"@src/context/Currency\";\nimport type { KnownMintWithBalance } from \"@src/context/KnownMints\";\nimport { usePrivacyContext } from \"@src/context/Privacy\";\nimport { useThemeContext } from \"@src/context/Theme\";\nimport { NS } from \"@src/i18n\";\nimport { mainColors } from \"@styles\";\nimport React, { forwardRef, useCallback, useMemo } from \"react\";\nimport { Text, View } from \"react-native\";\nimport { useTranslation } from \"react-i18next\";\nimport { ScaledSheet } from \"react-native-size-matters\";\n\nexport type MeltConfirmationModalRef = ConfirmationModalRef;\n\ninterface IMeltConfirmationModalProps {\n  operation: MeltOperation;\n  mint: KnownMintWithBalance | null;\n  loading?: boolean;\n  onConfirm: () => void;\n  onCancel: () => void;\n  onBackToDashboard: () => void;\n}\n\ntype TRowTone = \"default\" | \"success\" | \"danger\";\n\ninterface IDetailRow {\n  label: string;\n  value: string;\n  copyValue?: string;\n  monospace?: boolean;\n  tone?: TRowTone;\n}\n\nconst MeltConfirmationModal = forwardRef<MeltConfirmationModalRef, IMeltConfirmationModalProps>(\n  ({ operation, mint, loading = false, onConfirm, onCancel, onBackToDashboard }, ref) => {\n    const { t } = useTranslation([NS.common, NS.auth]);\n    const { color } = useThemeContext();\n    const { hidden } = usePrivacyContext();\n    const { formatAmount } = useCurrencyContext();\n    const isPending = operation.state === \"pending\";\n\n    const formatDisplayAmount = useCallback(\n      (amount: number) => {\n        const { formatted, symbol } = formatAmount(amount);\n        return `${formatted} ${symbol}`;\n      },\n      [formatAmount],\n    );\n\n    const summaryRows = useMemo<IDetailRow[]>(() => {\n      if (operation.state === \"init\") {\n        return [];\n      }\n\n      const swapFee = operation.needsSwap ? operation.swap_fee : 0;\n      const totalAmount = operation.amount + operation.fee_reserve + swapFee;\n\n      return [\n        {\n          label: t(\"estimatedFees\", { ns: NS.common }),\n          value: formatDisplayAmount(operation.fee_reserve),\n        },\n        ...(operation.needsSwap\n          ? [\n              {\n                label: t(\"swapFee\", { ns: NS.common }),\n                value: formatDisplayAmount(swapFee),\n              },\n            ]\n          : []),\n        {\n          label: t(\"totalInclFee\", { ns: NS.common }),\n          value: formatDisplayAmount(totalAmount),\n        },\n        ...(operation.inputAmount !== totalAmount\n          ? [\n              {\n                label: t(\"reservedTotal\", { ns: NS.common }),\n                value: formatDisplayAmount(operation.inputAmount),\n              },\n            ]\n          : []),\n      ];\n    }, [formatDisplayAmount, operation, t]);\n\n    const detailRows = useMemo<IDetailRow[]>(() => {\n      if (operation.state === \"init\") {\n        return [];\n      }\n\n      const invoice = \"invoice\" in operation.methodData ? operation.methodData.invoice : \"\";\n\n      return [\n        {\n          label: t(\"paymentType\", { ns: NS.common }),\n          value:\n            operation.method === \"bolt11\" ? t(\"lnInvoice\", { ns: NS.common }) : operation.method,\n        },\n        {\n          label: t(\"swap\", { ns: NS.common }),\n          value: t(operation.needsSwap ? \"yes\" : \"no\", { ns: NS.common }),\n        },\n        {\n          label: t(\"quoteId\", { ns: NS.common }),\n          value: truncateMiddle(operation.quoteId),\n          copyValue: operation.quoteId,\n          monospace: true,\n        },\n        ...(invoice\n          ? [\n              {\n                label: t(\"invoice\", { ns: NS.common }),\n                value: truncateMiddle(invoice, 20, 12),\n                copyValue: invoice,\n                monospace: true,\n              },\n            ]\n          : []),\n      ];\n    }, [operation, t]);\n\n    const balanceAfterTx = useMemo(() => {\n      if (!mint || operation.state === \"init\") {\n        return \"\";\n      }\n\n      if (hidden.balance) {\n        return \"****\";\n      }\n\n      const swapFee = operation.needsSwap ? operation.swap_fee : 0;\n      const totalAmount = operation.amount + operation.fee_reserve + swapFee;\n      return formatDisplayAmount(mint.balance - totalAmount);\n    }, [formatDisplayAmount, hidden.balance, mint, operation]);\n\n    const mintRows = useMemo<IOperationMintPanelRow[]>(() => {\n      if (!mint || !balanceAfterTx) {\n        return [];\n      }\n\n      return [\n        {\n          label: t(\"balanceAfterTX\", { ns: NS.common }),\n          value: balanceAfterTx,\n          tone: \"success\",\n        },\n      ];\n    }, [balanceAfterTx, mint, t]);\n\n    if (operation.state === \"init\") {\n      return null;\n    }\n\n    const cancelText = isPending\n      ? t(\"backToDashboard\", { ns: NS.common })\n      : t(\"cancel\", { ns: NS.common });\n\n    return (\n      <ConfirmationModal\n        ref={ref}\n        title={t(\"confirmAction\", { ns: NS.auth })}\n        subtitle={t(\"lnPayment\", { ns: NS.common })}\n        confirmText={t(\"confirm\", { ns: NS.common })}\n        cancelText={cancelText}\n        loading={loading}\n        confirmDisabled={isPending}\n        onConfirm={onConfirm}\n        onCancel={isPending ? onBackToDashboard : onCancel}\n      >\n        <Card style={styles.summaryCard}>\n          <Txt\n            txt={t(\"amount\", { ns: NS.common })}\n            center\n            styles={[styles.amountLabel, { color: color.TEXT_SECONDARY }]}\n          />\n          <Txt txt={formatDisplayAmount(operation.amount)} center bold styles={[styles.amount]} />\n          {isPending ? (\n            <Txt\n              txt={t(\"paymentPending\", { ns: NS.common }) + \".\"}\n              center\n              styles={[styles.pendingBadge, { color: color.TEXT_SECONDARY }]}\n            />\n          ) : null}\n          <View style={styles.rowsWrap}>\n            {summaryRows.map((row, index) => (\n              <View key={`${row.label}-${index}`}>\n                <DetailRow row={row} />\n                {index < summaryRows.length - 1 ? (\n                  <Separator noMargin style={styles.separator} />\n                ) : null}\n              </View>\n            ))}\n          </View>\n        </Card>\n\n        {mint ? (\n          <View style={styles.mintSection}>\n            <Txt\n              txt={t(\"mint\", { ns: NS.common })}\n              styles={[styles.sectionLabel, { color: color.TEXT_SECONDARY }]}\n            />\n            <OperationMintPanel mint={mint} rows={mintRows} />\n          </View>\n        ) : null}\n\n        <Card style={styles.detailsCard}>\n          <View style={styles.rowsWrap}>\n            {detailRows.map((row, index) => (\n              <View key={`${row.label}-${index}`}>\n                <DetailRow row={row} />\n                {index < detailRows.length - 1 ? (\n                  <Separator noMargin style={styles.separator} />\n                ) : null}\n              </View>\n            ))}\n          </View>\n        </Card>\n      </ConfirmationModal>\n    );\n  },\n);\n\nfunction DetailRow({ row }: { row: IDetailRow }) {\n  const { color } = useThemeContext();\n\n  const valueColor = useMemo(() => {\n    switch (row.tone) {\n      case \"success\":\n        return mainColors.VALID;\n      case \"danger\":\n        return mainColors.ERROR;\n      default:\n        return color.TEXT;\n    }\n  }, [color.TEXT, row.tone]);\n\n  return (\n    <View style={styles.detailRow}>\n      <Txt txt={row.label} styles={[styles.detailLabel, { color: color.TEXT_SECONDARY }]} />\n      <View style={styles.detailValueWrap}>\n        <Text\n          numberOfLines={1}\n          ellipsizeMode=\"middle\"\n          style={[\n            styles.detailValue,\n            row.monospace && styles.mono,\n            {\n              color: valueColor,\n            },\n          ]}\n        >\n          {row.value}\n        </Text>\n        {row.copyValue ? <Copy txt={row.copyValue} /> : null}\n      </View>\n    </View>\n  );\n}\n\nfunction truncateMiddle(value: string, start = 14, end = 10) {\n  if (value.length <= start + end + 3) {\n    return value;\n  }\n\n  return `${value.slice(0, start)}...${value.slice(-end)}`;\n}\n\nMeltConfirmationModal.displayName = \"MeltConfirmationModal\";\n\nconst styles = ScaledSheet.create({\n  summaryCard: {\n    marginBottom: \"12@vs\",\n    paddingHorizontal: \"20@s\",\n    paddingTop: \"18@vs\",\n    paddingBottom: \"16@vs\",\n  },\n  amountLabel: {\n    fontSize: \"12@vs\",\n    marginBottom: \"8@vs\",\n    letterSpacing: 0.3,\n  },\n  amount: {\n    fontSize: \"34@vs\",\n    lineHeight: \"40@vs\",\n    marginBottom: \"16@vs\",\n  },\n  pendingBadge: {\n    fontSize: \"13@vs\",\n    marginBottom: \"14@vs\",\n  },\n  rowsWrap: {\n    gap: \"2@vs\",\n  },\n  detailRow: {\n    flexDirection: \"row\",\n    alignItems: \"center\",\n    justifyContent: \"space-between\",\n    gap: \"12@s\",\n    paddingVertical: \"12@vs\",\n  },\n  detailLabel: {\n    flex: 1,\n    fontSize: \"14@vs\",\n  },\n  detailValueWrap: {\n    flex: 1.25,\n    flexDirection: \"row\",\n    alignItems: \"center\",\n    justifyContent: \"flex-end\",\n    gap: \"8@s\",\n  },\n  detailValue: {\n    flexShrink: 1,\n    textAlign: \"right\",\n    fontSize: \"14@vs\",\n    fontWeight: \"500\",\n  },\n  mono: {\n    fontFamily: \"monospace\",\n    fontSize: \"12@vs\",\n  },\n  separator: {\n    marginVertical: 0,\n  },\n  mintSection: {\n    marginBottom: \"12@vs\",\n  },\n  sectionLabel: {\n    fontSize: \"13@vs\",\n    marginBottom: \"8@vs\",\n    marginLeft: \"2@s\",\n  },\n  detailsCard: {\n    marginBottom: \"16@vs\",\n    paddingHorizontal: \"20@s\",\n    paddingVertical: \"4@vs\",\n  },\n});\n\nexport default MeltConfirmationModal;\n"
  },
  {
    "path": "src/components/modal/NfcPaymentModal.tsx",
    "content": "import React, { forwardRef, useCallback, useImperativeHandle, useRef, useState } from \"react\";\nimport { TrueSheet } from \"@lodev09/react-native-true-sheet\";\nimport { View, TouchableOpacity, Text } from \"react-native\";\nimport { s, ScaledSheet } from \"react-native-size-matters\";\nimport { useTranslation } from \"react-i18next\";\n\nimport { NfcIcon, ExclamationIcon } from \"@comps/Icons\";\nimport { useNfcAmountLimitsContext, NO_LIMIT } from \"@src/context/NfcAmountLimits\";\nimport {\n  useNfcPayment,\n  type NfcPaymentHandoff,\n  type NfcPaymentResult,\n  type LimitExceededError,\n} from \"@comps/hooks/useNfcPayment\";\nimport Separator from \"@comps/Separator\";\nimport Txt from \"@comps/Txt\";\nimport { useCurrencyContext } from \"@src/context/Currency\";\nimport { useThemeContext } from \"@src/context/Theme\";\nimport { NS } from \"@src/i18n\";\nimport { highlight as hi } from \"@styles\";\n\nexport interface NfcPaymentModalRef {\n  /** Open the modal and start NFC payment with the default limit */\n  open: () => void;\n  /** Close the modal */\n  close: () => void;\n}\n\ninterface INfcPaymentModalProps {\n  /** Called when payment completes successfully */\n  onSuccess?: (result: NfcPaymentResult) => void;\n  /** Called when payment fails */\n  onError?: (result: NfcPaymentResult) => void;\n  /** Called when the NFC payload should be handled by another payment flow */\n  onPaymentHandoff?: (handoff: NfcPaymentHandoff) => void;\n  /** Called when modal is closed/cancelled */\n  onClose?: () => void;\n}\n\n/** Info stored when a payment exceeds the configured limit and needs confirmation */\ninterface PendingConfirmation {\n  paymentRequest: string;\n  amount: number;\n  mint: string;\n  maxAmount: number;\n}\n\nconst NfcPaymentModal = forwardRef<NfcPaymentModalRef, INfcPaymentModalProps>(\n  ({ onSuccess, onError, onPaymentHandoff, onClose }, ref) => {\n    const { t } = useTranslation([NS.common]);\n    const { color, highlight } = useThemeContext();\n    const { formatBalance, formatSatsAsCurrency, rates, selectedCurrency } = useCurrencyContext();\n\n    const sheetRef = useRef<TrueSheet>(null);\n    const [pendingConfirmation, setPendingConfirmation] = useState<PendingConfirmation | null>(\n      null,\n    );\n\n    const { defaultMaxAmount } = useNfcAmountLimitsContext();\n    const currencySymbol = rates?.[selectedCurrency]?.symbol || selectedCurrency;\n\n    // NFC Payment logic\n    const { isActive, statusMessage, startPayment, completeOverLimitPayment } = useNfcPayment({\n      onPaymentSuccess: (result) => {\n        setPendingConfirmation(null);\n        void sheetRef.current?.dismiss();\n        onSuccess?.(result);\n      },\n      onPaymentError: (result) => {\n        setPendingConfirmation(null);\n        void sheetRef.current?.dismiss();\n        onError?.(result);\n      },\n      onPaymentHandoff: (handoff) => {\n        setPendingConfirmation(null);\n        void sheetRef.current?.dismiss();\n        onPaymentHandoff?.(handoff);\n      },\n      onLimitExceeded: (error: LimitExceededError) => {\n        // Store the payment details and show confirmation UI\n        setPendingConfirmation({\n          paymentRequest: error.paymentRequest,\n          amount: error.amount,\n          mint: error.mint,\n          maxAmount: error.maxAmount,\n        });\n      },\n    });\n\n    // Start payment with default limit\n    const startPaymentWithDefaultLimit = useCallback(() => {\n      const maxAmount = defaultMaxAmount === NO_LIMIT ? undefined : defaultMaxAmount;\n      void startPayment({ maxAmount });\n    }, [defaultMaxAmount, startPayment]);\n\n    // Handle confirmation of over-limit payment\n    const handleConfirmOverLimit = useCallback(() => {\n      if (!pendingConfirmation) return;\n      const { paymentRequest, amount, mint } = pendingConfirmation;\n      void completeOverLimitPayment(paymentRequest, amount, mint);\n    }, [pendingConfirmation, completeOverLimitPayment]);\n\n    // Handle declining the over-limit payment\n    const handleDeclineOverLimit = useCallback(() => {\n      setPendingConfirmation(null);\n      void sheetRef.current?.dismiss();\n      onClose?.();\n    }, [onClose]);\n\n    // Expose imperative API\n    useImperativeHandle(\n      ref,\n      () => ({\n        open: () => {\n          setPendingConfirmation(null);\n          void sheetRef.current?.present().then(startPaymentWithDefaultLimit);\n        },\n        close: () => {\n          setPendingConfirmation(null);\n          void sheetRef.current?.dismiss();\n        },\n      }),\n      [startPaymentWithDefaultLimit],\n    );\n\n    const showConfirmation = pendingConfirmation !== null && !isActive;\n    const showNfcWaiting = isActive || !pendingConfirmation;\n\n    // Format the pending amount for display\n    const pendingAmountFiat =\n      pendingConfirmation && formatBalance && rates\n        ? formatSatsAsCurrency(pendingConfirmation.amount)\n        : null;\n    const pendingLimitFiat =\n      pendingConfirmation && formatBalance && rates\n        ? formatSatsAsCurrency(pendingConfirmation.maxAmount)\n        : null;\n\n    // Header title\n    const headerTitle = showConfirmation\n      ? t(\"nfcConfirmPayment\", {\n          ns: NS.wallet,\n          defaultValue: \"Confirm Payment\",\n        })\n      : t(\"nfcPayment\", {\n          ns: NS.wallet,\n          defaultValue: \"NFC Payment\",\n        });\n\n    return (\n      <TrueSheet\n        ref={sheetRef}\n        detents={[\"auto\"]}\n        dismissible={!isActive}\n        draggable={!isActive}\n        backgroundColor={color.BACKGROUND}\n        cornerRadius={s(26)}\n        grabberOptions={{ color: color.TEXT_SECONDARY }}\n      >\n        <View style={[styles.container, { backgroundColor: color.BACKGROUND }]}>\n          <View style={styles.header}>\n            {showConfirmation ? (\n              <ExclamationIcon width={s(28)} color={hi[highlight]} />\n            ) : (\n              <NfcIcon width={s(28)} color={hi[highlight]} />\n            )}\n            <Txt txt={headerTitle} bold styles={[styles.title]} />\n          </View>\n\n          {showConfirmation && pendingConfirmation && (\n            <View style={styles.confirmationContainer}>\n              <Txt\n                txt={t(\"nfcAmountExceedsLimit\", {\n                  ns: NS.wallet,\n                  defaultValue: \"This payment exceeds your configured limit.\",\n                })}\n                styles={[styles.confirmationText, { color: color.TEXT_SECONDARY }]}\n              />\n\n              <View\n                style={[\n                  styles.confirmationBox,\n                  {\n                    backgroundColor: color.INPUT_BG,\n                    borderColor: color.BORDER,\n                  },\n                ]}\n              >\n                <View style={styles.confirmationRow}>\n                  <Txt\n                    txt={t(\"amount\", { ns: NS.common, defaultValue: \"Amount\" })}\n                    styles={[styles.confirmationLabel, { color: color.TEXT_SECONDARY }]}\n                  />\n                  <View style={styles.confirmationValue}>\n                    <Txt\n                      txt={`${pendingConfirmation.amount.toLocaleString()} sats`}\n                      bold\n                      styles={[{ color: color.TEXT }]}\n                    />\n                    {pendingAmountFiat && (\n                      <Txt\n                        txt={`≈ ${currencySymbol}${pendingAmountFiat}`}\n                        styles={[styles.confirmationFiat, { color: color.TEXT_SECONDARY }]}\n                      />\n                    )}\n                  </View>\n                </View>\n\n                <Separator style={styles.confirmationSeparator} />\n\n                <View style={styles.confirmationRow}>\n                  <Txt\n                    txt={t(\"yourLimit\", {\n                      ns: NS.wallet,\n                      defaultValue: \"Your limit\",\n                    })}\n                    styles={[styles.confirmationLabel, { color: color.TEXT_SECONDARY }]}\n                  />\n                  <View style={styles.confirmationValue}>\n                    <Txt\n                      txt={`${pendingConfirmation.maxAmount.toLocaleString()} sats`}\n                      styles={[{ color: color.TEXT }]}\n                    />\n                    {pendingLimitFiat && (\n                      <Txt\n                        txt={`≈ ${currencySymbol}${pendingLimitFiat}`}\n                        styles={[styles.confirmationFiat, { color: color.TEXT_SECONDARY }]}\n                      />\n                    )}\n                  </View>\n                </View>\n              </View>\n\n              <Txt\n                txt={t(\"nfcTapAgainAfterConfirm\", {\n                  ns: NS.wallet,\n                  defaultValue: \"You will need to tap the terminal again after confirming.\",\n                })}\n                styles={[styles.confirmationHint, { color: color.TEXT_SECONDARY }]}\n              />\n\n              <View style={styles.confirmationButtons}>\n                <TouchableOpacity\n                  style={[\n                    styles.confirmationButton,\n                    styles.declineButton,\n                    { borderColor: color.BORDER },\n                  ]}\n                  onPress={handleDeclineOverLimit}\n                  activeOpacity={0.7}\n                >\n                  <Text style={[styles.declineButtonText, { color: color.TEXT }]}>\n                    {t(\"cancel\", { ns: NS.common, defaultValue: \"Cancel\" })}\n                  </Text>\n                </TouchableOpacity>\n\n                <TouchableOpacity\n                  style={[\n                    styles.confirmationButton,\n                    styles.confirmButton,\n                    { backgroundColor: hi[highlight] },\n                  ]}\n                  onPress={handleConfirmOverLimit}\n                  activeOpacity={0.7}\n                >\n                  <Text style={styles.confirmButtonText}>\n                    {t(\"confirm\", { ns: NS.common, defaultValue: \"Confirm\" })}\n                  </Text>\n                </TouchableOpacity>\n              </View>\n            </View>\n          )}\n\n          {showNfcWaiting && (\n            <View style={styles.loading}>\n              <View style={[styles.pulse, { borderColor: hi[highlight] }]}>\n                <NfcIcon width={s(40)} color={hi[highlight]} />\n              </View>\n              <Txt txt={statusMessage} styles={[{ color: color.TEXT_SECONDARY }]} />\n            </View>\n          )}\n        </View>\n      </TrueSheet>\n    );\n  },\n);\n\nNfcPaymentModal.displayName = \"NfcPaymentModal\";\n\nconst styles = ScaledSheet.create({\n  container: {\n    paddingHorizontal: \"20@s\",\n    paddingTop: \"30@vs\",\n    paddingBottom: \"16@vs\",\n  },\n  header: {\n    flexDirection: \"row\",\n    alignItems: \"center\",\n    justifyContent: \"center\",\n    gap: \"10@s\",\n    marginBottom: \"16@vs\",\n    marginTop: \"4@vs\",\n  },\n  title: {\n    fontSize: \"18@vs\",\n  },\n  loading: {\n    alignItems: \"center\",\n    paddingVertical: \"32@vs\",\n  },\n  pulse: {\n    width: \"80@s\",\n    height: \"80@s\",\n    borderRadius: \"40@s\",\n    borderWidth: 2,\n    justifyContent: \"center\",\n    alignItems: \"center\",\n    marginBottom: \"16@vs\",\n  },\n  // Confirmation UI styles\n  confirmationContainer: {\n    paddingVertical: \"8@vs\",\n  },\n  confirmationText: {\n    fontSize: \"14@vs\",\n    textAlign: \"center\",\n    marginBottom: \"16@vs\",\n  },\n  confirmationBox: {\n    borderRadius: \"12@s\",\n    borderWidth: 1,\n    marginBottom: \"12@vs\",\n  },\n  confirmationRow: {\n    flexDirection: \"row\",\n    alignItems: \"center\",\n    justifyContent: \"space-between\",\n    paddingVertical: \"14@vs\",\n    paddingHorizontal: \"16@s\",\n  },\n  confirmationLabel: {\n    fontSize: \"14@vs\",\n  },\n  confirmationValue: {\n    alignItems: \"flex-end\",\n  },\n  confirmationFiat: {\n    fontSize: \"12@vs\",\n    marginTop: \"2@vs\",\n  },\n  confirmationSeparator: {\n    marginHorizontal: \"16@s\",\n  },\n  confirmationHint: {\n    fontSize: \"12@vs\",\n    textAlign: \"center\",\n    marginBottom: \"20@vs\",\n    fontStyle: \"italic\",\n  },\n  confirmationButtons: {\n    flexDirection: \"row\",\n    gap: \"12@s\",\n  },\n  confirmationButton: {\n    flex: 1,\n    paddingVertical: \"14@vs\",\n    borderRadius: \"12@s\",\n    alignItems: \"center\",\n    justifyContent: \"center\",\n  },\n  declineButton: {\n    borderWidth: 1,\n  },\n  confirmButton: {},\n  declineButtonText: {\n    fontSize: \"15@vs\",\n    fontWeight: \"600\",\n  },\n  confirmButtonText: {\n    fontSize: \"15@vs\",\n    fontWeight: \"600\",\n    color: \"#fff\",\n  },\n});\n\nexport default NfcPaymentModal;\n"
  },
  {
    "path": "src/components/modal/OperationMintPanel.tsx",
    "content": "import { MintBoardIcon } from \"@comps/Icons\";\nimport Txt from \"@comps/Txt\";\nimport { Image } from \"expo-image\";\nimport type { KnownMintWithBalance } from \"@src/context/KnownMints\";\nimport { useThemeContext } from \"@src/context/Theme\";\nimport { highlight as hi, mainColors } from \"@styles\";\nimport { formatMintUrl } from \"@util\";\nimport { useMemo } from \"react\";\nimport { View } from \"react-native\";\nimport { s, ScaledSheet } from \"react-native-size-matters\";\n\ntype TOperationMintPanelRowTone = \"default\" | \"success\" | \"danger\";\n\nexport interface IOperationMintPanelRow {\n  label: string;\n  value: string;\n  tone?: TOperationMintPanelRowTone;\n}\n\ninterface IOperationMintPanelProps {\n  mint: KnownMintWithBalance;\n  rows: IOperationMintPanelRow[];\n}\n\nexport default function OperationMintPanel({ mint, rows }: IOperationMintPanelProps) {\n  const { color, highlight } = useThemeContext();\n\n  const mintLabel = useMemo(() => {\n    return mint.mintInfo.name || mint.name || formatMintUrl(mint.mintUrl);\n  }, [mint]);\n\n  return (\n    <View\n      style={[\n        styles.panel,\n        {\n          backgroundColor: color.DRAWER,\n          borderColor: color.BORDER,\n        },\n      ]}\n    >\n      <View style={styles.headerRow}>\n        {mint.mintInfo.icon_url ? (\n          <View\n            style={[\n              styles.iconWrap,\n              {\n                backgroundColor: color.INPUT_BG,\n                borderColor: color.BORDER,\n              },\n            ]}\n          >\n            <Image\n              source={{ uri: mint.mintInfo.icon_url }}\n              style={styles.iconImage}\n              contentFit=\"cover\"\n              transition={200}\n            />\n          </View>\n        ) : (\n          <View\n            style={[\n              styles.iconWrap,\n              {\n                backgroundColor: color.INPUT_BG,\n                borderColor: color.BORDER,\n              },\n            ]}\n          >\n            <MintBoardIcon width={s(18)} height={s(18)} color={hi[highlight]} />\n          </View>\n        )}\n\n        <View style={styles.mintInfo}>\n          <Txt txt={mintLabel} bold styles={[styles.mintName]} />\n          <Txt\n            txt={formatMintUrl(mint.mintUrl)}\n            styles={[styles.mintUrl, { color: color.TEXT_SECONDARY }]}\n          />\n        </View>\n      </View>\n\n      {rows.length ? (\n        <View style={[styles.metaWrap, { borderTopColor: color.BORDER }]}>\n          {rows.map((row, index) => (\n            <View\n              key={`${row.label}-${index}`}\n              style={index < rows.length - 1 ? styles.metaRowSpacing : undefined}\n            >\n              <MetaRow row={row} />\n            </View>\n          ))}\n        </View>\n      ) : null}\n    </View>\n  );\n}\n\nfunction MetaRow({ row }: { row: IOperationMintPanelRow }) {\n  const { color } = useThemeContext();\n\n  const valueColor = useMemo(() => {\n    switch (row.tone) {\n      case \"success\":\n        return mainColors.VALID;\n      case \"danger\":\n        return mainColors.ERROR;\n      default:\n        return color.TEXT;\n    }\n  }, [color.TEXT, row.tone]);\n\n  return (\n    <View style={styles.metaRow}>\n      <Txt txt={row.label} styles={[styles.balanceLabel, { color: color.TEXT_SECONDARY }]} />\n      <Txt txt={row.value} bold styles={[styles.balanceValue, { color: valueColor }]} />\n    </View>\n  );\n}\n\nconst styles = ScaledSheet.create({\n  panel: {\n    borderRadius: 18,\n    borderWidth: 1,\n    paddingHorizontal: \"14@s\",\n    paddingVertical: \"12@vs\",\n  },\n  headerRow: {\n    flexDirection: \"row\",\n    alignItems: \"center\",\n    gap: \"12@s\",\n  },\n  iconWrap: {\n    width: \"40@s\",\n    height: \"40@s\",\n    borderRadius: \"20@s\",\n    borderWidth: 1,\n    alignItems: \"center\",\n    justifyContent: \"center\",\n    overflow: \"hidden\",\n  },\n  iconImage: {\n    width: \"100%\",\n    height: \"100%\",\n  },\n  mintInfo: {\n    flex: 1,\n  },\n  mintName: {\n    fontSize: \"14@vs\",\n    marginBottom: \"2@vs\",\n  },\n  mintUrl: {\n    fontSize: \"12@vs\",\n  },\n  metaWrap: {\n    marginTop: \"12@vs\",\n    paddingTop: \"12@vs\",\n    borderTopWidth: 1,\n  },\n  metaRow: {\n    flexDirection: \"row\",\n    alignItems: \"center\",\n    justifyContent: \"space-between\",\n    gap: \"12@s\",\n  },\n  metaRowSpacing: {\n    marginBottom: \"8@vs\",\n  },\n  balanceLabel: {\n    flex: 1,\n    fontSize: \"12@vs\",\n  },\n  balanceValue: {\n    fontSize: \"13@vs\",\n  },\n});\n"
  },
  {
    "path": "src/components/modal/SendConfirmationModal.tsx",
    "content": "import Card from \"@comps/Card\";\nimport ConfirmationModal, { type ConfirmationModalRef } from \"@modal/ConfirmationModal\";\nimport OperationMintPanel, { type IOperationMintPanelRow } from \"@modal/OperationMintPanel\";\nimport Separator from \"@comps/Separator\";\nimport Txt from \"@comps/Txt\";\nimport type { SendOperation } from \"@cashu/coco-core\";\nimport { useCurrencyContext } from \"@src/context/Currency\";\nimport type { KnownMintWithBalance } from \"@src/context/KnownMints\";\nimport { usePrivacyContext } from \"@src/context/Privacy\";\nimport { NS } from \"@src/i18n\";\nimport { useThemeContext } from \"@src/context/Theme\";\nimport { mainColors } from \"@styles\";\nimport React, { forwardRef, useCallback, useMemo } from \"react\";\nimport { View } from \"react-native\";\nimport { useTranslation } from \"react-i18next\";\nimport { ScaledSheet } from \"react-native-size-matters\";\n\nexport type SendConfirmationModalRef = ConfirmationModalRef;\ntype TPreparedOrLaterSendOperation = Exclude<SendOperation, { state: \"init\" }>;\n\ninterface ISendConfirmationModalProps {\n  operation: TPreparedOrLaterSendOperation | null;\n  mint: KnownMintWithBalance | null;\n  loading?: boolean;\n  onConfirm: () => void;\n  onCancel: () => void;\n}\n\ntype TRowTone = \"default\" | \"success\" | \"danger\";\n\ninterface IDetailRow {\n  label: string;\n  value: string;\n  tone?: TRowTone;\n}\n\nconst SendConfirmationModal = forwardRef<SendConfirmationModalRef, ISendConfirmationModalProps>(\n  ({ operation, mint, loading = false, onConfirm, onCancel }, ref) => {\n    const { t } = useTranslation([NS.common, NS.auth]);\n    const { color } = useThemeContext();\n    const { hidden } = usePrivacyContext();\n    const { formatAmount } = useCurrencyContext();\n\n    const formatDisplayAmount = useCallback(\n      (amount: number) => {\n        const { formatted, symbol } = formatAmount(amount);\n        return `${formatted} ${symbol}`;\n      },\n      [formatAmount],\n    );\n\n    const summaryRows = useMemo<IDetailRow[]>(() => {\n      if (!operation) {\n        return [];\n      }\n\n      const totalAmount = operation.amount + operation.fee;\n\n      return [\n        {\n          label: t(\"estimatedFees\", { ns: NS.common }),\n          value: formatDisplayAmount(operation.fee),\n        },\n        {\n          label: t(\"totalInclFee\", { ns: NS.common }),\n          value: formatDisplayAmount(totalAmount),\n        },\n        ...(operation.inputAmount !== totalAmount\n          ? [\n              {\n                label: t(\"reservedTotal\", { ns: NS.common }),\n                value: formatDisplayAmount(operation.inputAmount),\n              },\n            ]\n          : []),\n      ];\n    }, [formatDisplayAmount, operation, t]);\n\n    const balanceAfterTx = useMemo(() => {\n      if (!operation || !mint) {\n        return \"\";\n      }\n\n      const totalAmount = operation.amount + operation.fee;\n      const nextBalance = mint.balance - totalAmount;\n\n      if (hidden.balance) {\n        return \"****\";\n      }\n\n      return formatDisplayAmount(nextBalance);\n    }, [formatDisplayAmount, hidden.balance, mint, operation]);\n\n    const mintRows = useMemo<IOperationMintPanelRow[]>(() => {\n      if (!mint) {\n        return [];\n      }\n\n      return [\n        {\n          label: t(\"balanceAfterTX\", { ns: NS.common }),\n          value: balanceAfterTx,\n          tone: \"success\",\n        },\n      ];\n    }, [balanceAfterTx, mint, t]);\n\n    return (\n      <ConfirmationModal\n        ref={ref}\n        title={t(\"confirmAction\", { ns: NS.auth })}\n        subtitle={t(\"sendEcash\", { ns: NS.common })}\n        confirmText={t(\"confirm\", { ns: NS.common })}\n        cancelText={t(\"cancel\", { ns: NS.common })}\n        loading={loading}\n        onConfirm={onConfirm}\n        onCancel={onCancel}\n      >\n        {operation ? (\n          <>\n            <Card style={styles.summaryCard}>\n              <Txt\n                txt={t(\"amount\", { ns: NS.common })}\n                center\n                styles={[styles.amountLabel, { color: color.TEXT_SECONDARY }]}\n              />\n              <Txt\n                txt={formatDisplayAmount(operation.amount)}\n                center\n                bold\n                styles={[styles.amount]}\n              />\n              <View style={styles.rowsWrap}>\n                {summaryRows.map((row, index) => (\n                  <View key={`${row.label}-${index}`}>\n                    <DetailRow row={row} />\n                    {index < summaryRows.length - 1 ? (\n                      <Separator noMargin style={styles.separator} />\n                    ) : null}\n                  </View>\n                ))}\n              </View>\n            </Card>\n\n            {mint ? (\n              <View style={styles.mintSection}>\n                <Txt\n                  txt={t(\"sendingFrom\", { ns: NS.common, defaultValue: \"Sending from\" })}\n                  styles={[styles.sectionLabel, { color: color.TEXT_SECONDARY }]}\n                />\n                <OperationMintPanel mint={mint} rows={mintRows} />\n              </View>\n            ) : null}\n          </>\n        ) : (\n          <View />\n        )}\n      </ConfirmationModal>\n    );\n  },\n);\n\nfunction DetailRow({ row }: { row: IDetailRow }) {\n  const { color } = useThemeContext();\n\n  const valueColor = useMemo(() => {\n    switch (row.tone) {\n      case \"success\":\n        return mainColors.VALID;\n      case \"danger\":\n        return mainColors.ERROR;\n      default:\n        return color.TEXT;\n    }\n  }, [color.TEXT, row.tone]);\n\n  return (\n    <View style={styles.detailRow}>\n      <Txt txt={row.label} styles={[styles.detailLabel, { color: color.TEXT_SECONDARY }]} />\n      <Txt txt={row.value} bold styles={[styles.detailValue, { color: valueColor }]} />\n    </View>\n  );\n}\n\nSendConfirmationModal.displayName = \"SendConfirmationModal\";\n\nconst styles = ScaledSheet.create({\n  summaryCard: {\n    marginBottom: \"12@vs\",\n    paddingHorizontal: \"20@s\",\n    paddingTop: \"18@vs\",\n    paddingBottom: \"16@vs\",\n  },\n  amountLabel: {\n    fontSize: \"12@vs\",\n    marginBottom: \"8@vs\",\n    letterSpacing: 0.3,\n  },\n  amount: {\n    fontSize: \"34@vs\",\n    lineHeight: \"40@vs\",\n    marginBottom: \"20@vs\",\n  },\n  rowsWrap: {\n    gap: \"2@vs\",\n  },\n  detailRow: {\n    flexDirection: \"row\",\n    alignItems: \"center\",\n    justifyContent: \"space-between\",\n    gap: \"12@s\",\n    paddingVertical: \"12@vs\",\n  },\n  detailLabel: {\n    flex: 1,\n    fontSize: \"14@vs\",\n  },\n  detailValue: {\n    flexShrink: 1,\n    textAlign: \"right\",\n    fontSize: \"14@vs\",\n  },\n  separator: {\n    marginVertical: 0,\n  },\n  mintSection: {\n    marginBottom: \"16@vs\",\n  },\n  sectionLabel: {\n    fontSize: \"13@vs\",\n    marginBottom: \"8@vs\",\n    marginLeft: \"2@s\",\n  },\n});\n\nexport default SendConfirmationModal;\n"
  },
  {
    "path": "src/components/modal/TrustMintBottomSheet.tsx",
    "content": "import React, { forwardRef, useCallback, useImperativeHandle, useRef, useState } from \"react\";\nimport { TrueSheet } from \"@lodev09/react-native-true-sheet\";\nimport { TxtButton } from \"@comps/Button\";\nimport { ReceiveIcon } from \"@comps/Icons\";\nimport Loading from \"@comps/Loading\";\nimport Separator from \"@comps/Separator\";\nimport type { Token } from \"@cashu/cashu-ts\";\nimport type { ITokenInfo } from \"@model\";\nimport { useThemeContext } from \"@src/context/Theme\";\nimport { useCurrencyContext } from \"@src/context/Currency\";\nimport { NS } from \"@src/i18n\";\nimport { globals, mainColors } from \"@styles\";\nimport { formatMintUrl } from \"@util\";\nimport { useTranslation } from \"react-i18next\";\nimport { ScrollView, Text, TouchableOpacity, View } from \"react-native\";\nimport { useSafeAreaInsets } from \"react-native-safe-area-context\";\nimport { s, ScaledSheet, vs } from \"react-native-size-matters\";\n\nexport type TrustMintAction = \"trust\" | \"cancel\" | \"swap\";\n\nexport type TrustMintBottomSheetRef = {\n  open: (token: Token) => Promise<TrustMintAction>;\n  close: () => void;\n};\n\nconst TrustMintBottomSheet = forwardRef<TrustMintBottomSheetRef, { loading?: boolean }>(\n  (_props, ref) => {\n    const { t } = useTranslation([NS.common]);\n    const { color, highlight } = useThemeContext();\n    const { formatAmount } = useCurrencyContext();\n    const insets = useSafeAreaInsets();\n\n    const sheetRef = useRef<TrueSheet>(null);\n    const [loading, setLoading] = useState(false);\n    const [tokenInfo, setTokenInfo] = useState<ITokenInfo | undefined>(undefined);\n    const resolverRef = useRef<((action: TrustMintAction) => void) | null>(null);\n\n    const close = useCallback(() => {\n      void sheetRef.current?.dismiss();\n    }, []);\n\n    const open = useCallback((token: Token) => {\n      setLoading(false);\n      setTokenInfo({\n        mints: [token.mint],\n        value: token.proofs.reduce((r, c) => r + c.amount, 0),\n        decoded: token,\n      });\n      setTimeout(() => {\n        try {\n          void sheetRef.current?.present();\n        } catch {\n          /* ignore */\n        }\n      }, 0);\n      return new Promise<TrustMintAction>((resolve) => {\n        resolverRef.current = resolve;\n      });\n    }, []);\n\n    useImperativeHandle(ref, () => ({ open, close }), [open, close]);\n\n    const resolveAndClose = (action: TrustMintAction) => {\n      if (resolverRef.current) {\n        resolverRef.current(action);\n        resolverRef.current = null;\n      }\n      close();\n    };\n\n    const handleTrust = () => {\n      setLoading(true);\n      resolveAndClose(\"trust\");\n    };\n\n    const handleCancel = () => resolveAndClose(\"cancel\");\n\n    const handleDismiss = useCallback(() => {\n      if (resolverRef.current) {\n        resolverRef.current(\"cancel\");\n        resolverRef.current = null;\n      }\n    }, []);\n\n    return (\n      <TrueSheet\n        ref={sheetRef}\n        detents={[\"auto\"]}\n        backgroundColor={color.BACKGROUND}\n        cornerRadius={s(26)}\n        grabberOptions={{ color: color.TEXT_SECONDARY }}\n        onDidDismiss={handleDismiss}\n      >\n        <ScrollView\n          style={{ backgroundColor: color.BACKGROUND }}\n          contentContainerStyle={[\n            styles.container,\n            { paddingBottom: Math.max(insets.bottom, vs(20)) },\n          ]}\n          showsVerticalScrollIndicator={false}\n        >\n          <Text style={[globals(color, highlight).modalHeader, { marginBottom: vs(15) }]}>\n            {t(\"trustMint\")}\n          </Text>\n          {tokenInfo && (\n            <Text style={[styles.mintPrompt, { color: color.TEXT }]}>\n              {formatAmount(tokenInfo.value).formatted} {formatAmount(tokenInfo.value).symbol}{\" \"}\n              {t(\"from\")}:\n            </Text>\n          )}\n          <View style={styles.tokenMintsView}>\n            {tokenInfo?.mints.map((m) => (\n              <Text style={[styles.mintPrompt, { color: color.TEXT }]} key={m}>\n                {formatMintUrl(m)}\n              </Text>\n            ))}\n          </View>\n          <Separator style={[styles.separator]} />\n          <TouchableOpacity style={styles.row} onPress={handleTrust}>\n            <View style={styles.iconContainer}>\n              {loading ? (\n                <View>\n                  <Loading size=\"small\" color={mainColors.VALID} />\n                </View>\n              ) : (\n                <ReceiveIcon width={s(26)} height={s(26)} color={mainColors.VALID} />\n              )}\n            </View>\n            <View style={styles.txtWrap}>\n              <Text style={[styles.actionText, { color: color.TEXT }]}>\n                {loading ? t(\"claiming\", { ns: NS.wallet }) : t(\"trustMintOpt\")}\n              </Text>\n              <Text style={[styles.descriptionText, { color: color.TEXT_SECONDARY }]}>\n                {t(\"trustHint\")}\n              </Text>\n            </View>\n          </TouchableOpacity>\n          <TxtButton txt={t(\"cancel\")} onPress={handleCancel} style={[styles.TxtButton]} />\n        </ScrollView>\n      </TrueSheet>\n    );\n  },\n);\n\nTrustMintBottomSheet.displayName = \"TrustMintBottomSheet\";\n\nconst styles = ScaledSheet.create({\n  container: {\n    paddingHorizontal: \"20@s\",\n    paddingTop: \"30@vs\",\n  },\n  row: {\n    flexDirection: \"row\",\n    alignItems: \"center\",\n    width: \"100%\",\n  },\n  iconContainer: {\n    minWidth: \"11%\",\n  },\n  txtWrap: {\n    width: \"90%\",\n  },\n  actionText: {\n    fontSize: \"14@vs\",\n    fontWeight: \"500\",\n    marginBottom: \"4@vs\",\n  },\n  descriptionText: {\n    fontSize: \"12@vs\",\n  },\n  mintPrompt: {\n    fontSize: \"12@vs\",\n    marginBottom: \"5@vs\",\n  },\n  tokenMintsView: {\n    marginBottom: \"30@vs\",\n  },\n  TxtButton: {\n    paddingBottom: vs(15),\n    paddingTop: vs(25),\n  },\n  separator: {\n    width: \"100%\",\n    marginTop: \"10@vs\",\n    marginBottom: \"10@vs\",\n  },\n});\n\nexport default TrustMintBottomSheet;\n"
  },
  {
    "path": "src/components/modal/TrustMintProvider.tsx",
    "content": "import React, { createContext, useCallback, useContext, useMemo, useRef } from \"react\";\nimport TrustMintBottomSheet, { type TrustMintBottomSheetRef } from \"@modal/TrustMintBottomSheet\";\nimport type { Token } from \"@cashu/cashu-ts\";\n\ntype TrustMintContextValue = {\n  open: (token: Token) => Promise<\"trust\" | \"cancel\" | \"swap\">;\n};\n\nconst TrustMintContext = createContext<TrustMintContextValue | undefined>(undefined);\n\nexport function TrustMintModalProvider({ children }: { children: React.ReactNode }) {\n  const ref = useRef<TrustMintBottomSheetRef>(null);\n\n  const open = useCallback((token: Token) => {\n    return ref.current?.open(token) ?? Promise.resolve(\"cancel\");\n  }, []);\n\n  const value = useMemo(() => ({ open }), [open]);\n\n  return (\n    <TrustMintContext.Provider value={value}>\n      {children}\n      <TrustMintBottomSheet ref={ref} />\n    </TrustMintContext.Provider>\n  );\n}\n\nexport function useTrustMint() {\n  const ctx = useContext(TrustMintContext);\n  if (!ctx) {\n    throw new Error(\"useTrustMint must be used within TrustMintModalProvider\");\n  }\n  return ctx;\n}\n"
  },
  {
    "path": "src/components/modal/index.tsx",
    "content": "import { isIOS } from \"@consts\";\nimport { useThemeContext } from \"@src/context/Theme\";\nimport { highlight as hi, HighlightKey, mainColors, Theme } from \"@styles\";\nimport {\n  KeyboardAvoidingView,\n  Modal,\n  StyleSheet,\n  TouchableOpacity,\n  TouchableWithoutFeedback,\n  View,\n} from \"react-native\";\nimport { useSafeAreaInsets } from \"react-native-safe-area-context\";\n\ninterface IMyModalProps {\n  type: \"bottom\" | \"question\" | \"success\" | \"error\" | \"invoiceAmount\";\n  animation?: \"slide\" | \"fade\" | \"none\";\n  visible?: boolean;\n  success?: boolean;\n  hasNoPadding?: boolean;\n  close?: () => void;\n  // onBackdropPress?: () => void\n  children: React.ReactNode;\n}\n\nexport default function MyModal({\n  type,\n  animation,\n  visible,\n  success,\n  hasNoPadding,\n  close,\n  // onBackdropPress,\n  children,\n}: IMyModalProps) {\n  const { color, highlight } = useThemeContext();\n  const insets = useSafeAreaInsets();\n\n  const getCorrectStyle = () => {\n    if (type === \"bottom\") {\n      return styles(color, highlight).bottomView;\n    }\n    if (type === \"question\" || type === \"success\" || type === \"error\" || type === \"invoiceAmount\") {\n      return styles(color, highlight).centeredView;\n    }\n  };\n\n  const getViewStyle = () => {\n    if (type === \"bottom\") {\n      return {\n        ...styles(color, highlight).common,\n        ...styles(color, highlight).modalView,\n        paddingBottom: 20 + insets.bottom,\n      };\n    }\n    if (type === \"question\") {\n      return {\n        ...styles(color, highlight).common,\n        ...styles(color, highlight).centeredModalView,\n      };\n    }\n    if (type === \"success\") {\n      return {\n        ...styles(color, highlight).common,\n        ...styles(color, highlight).successModalView,\n      };\n    }\n    if (type === \"error\") {\n      return {\n        ...styles(color, highlight).common,\n        ...styles(color, highlight).promptModalView,\n      };\n    }\n    if (type === \"invoiceAmount\") {\n      let styling = {\n        ...styles(color, highlight).common,\n        ...styles(color, highlight).invoiceAmountModalView,\n      };\n      if (hasNoPadding) {\n        styling = { ...styling, ...styles(color, highlight).contactList };\n      }\n      return styling;\n    }\n  };\n\n  return visible ? (\n    <View style={styles(color, highlight).modalParent}>\n      <Modal\n        visible\n        transparent\n        animationType={animation}\n        onRequestClose={close}\n        testID=\"testCoinSelectionModal\"\n      >\n        <TouchableOpacity\n          style={styles(color, highlight).modalContainer}\n          activeOpacity={1}\n          onPressOut={close}\n        >\n          <KeyboardAvoidingView style={getCorrectStyle()} behavior={isIOS ? \"height\" : undefined}>\n            <TouchableWithoutFeedback>\n              <View style={[getViewStyle(), success ? { backgroundColor: hi[highlight] } : {}]}>\n                {children}\n              </View>\n            </TouchableWithoutFeedback>\n          </KeyboardAvoidingView>\n        </TouchableOpacity>\n      </Modal>\n    </View>\n  ) : null;\n}\n\nconst styles = (pref: Theme, h: HighlightKey) =>\n  StyleSheet.create({\n    modalParent: {\n      position: \"absolute\",\n      top: 0,\n      right: 0,\n      bottom: 0,\n      left: 0,\n      backgroundColor: \"rgba(0, 0, 0, .5)\",\n    },\n    modalContainer: {\n      flex: 1,\n    },\n    common: {\n      backgroundColor: pref.BACKGROUND,\n      alignItems: \"center\",\n      shadowColor: mainColors.BLACK,\n      shadowOffset: {\n        width: 0,\n        height: 2,\n      },\n      shadowOpacity: 0.25,\n      shadowRadius: 4,\n      elevation: 5,\n    },\n    // Bottom Modal\n    bottomView: {\n      flex: 1,\n      justifyContent: \"flex-end\",\n      alignItems: \"center\",\n    },\n    modalView: {\n      width: \"100%\",\n      borderTopLeftRadius: 20,\n      borderTopRightRadius: 20,\n      padding: 20,\n    },\n    // Centered Modal\n    centeredView: {\n      flex: 1,\n      justifyContent: \"center\",\n      alignItems: \"center\",\n    },\n    centeredModalView: {\n      width: \"90%\",\n      borderRadius: 20,\n      borderWidth: 3,\n      borderColor: hi[h],\n      paddingTop: 50,\n      paddingBottom: 50,\n      paddingRight: 20,\n      paddingLeft: 20,\n    },\n    // Success Modal\n    successModalView: {\n      width: \"90%\",\n      borderRadius: 20,\n    },\n    promptModalView: {\n      width: \"90%\",\n      borderRadius: 20,\n      borderWidth: 3,\n      borderColor: hi[h],\n      padding: 20,\n    },\n    invoiceAmountModalView: {\n      width: \"100%\",\n      height: \"100%\",\n      padding: 20,\n      justifyContent: \"space-between\",\n    },\n    contactList: {\n      paddingHorizontal: 0,\n    },\n  });\n"
  },
  {
    "path": "src/components/nav/Navigator.tsx",
    "content": "import type { INavigatorProps, RootStackParamList } from \"@model/nav\";\nimport { createNativeStackNavigator } from \"@react-navigation/native-stack\";\nimport Dashboard from \"@screens/Dashboard\";\nimport MintNavigator from \"@src/nav/MintNavigator\";\nimport OnboardingScreen from \"@screens/Onboarding\";\nimport ProcessingScreen from \"@screens/Payment/Processing\";\nimport ProcessingErrorScreen from \"@screens/Payment/ProcessingError\";\nimport InvoiceScreen from \"@screens/Payment/Receive/Invoice\";\nimport CoinSelectionScreen from \"@screens/Payment/Send/CoinSelection\";\nimport EncodedTokenPage from \"@screens/Payment/Send/EncodedToken\";\nimport SuccessPage from \"@screens/Payment/Success\";\nimport SuccessScreen from \"@screens/Payment/SuccessScreen\";\nimport QrScannerScreen from \"@screens/QRScan/QrScannerScreen\";\nimport RestoreNavigator from \"@src/nav/RestoreNavigator\";\nimport SettingsNavigator from \"@src/nav/SettingsNavigator\";\nimport { useThemeContext } from \"@src/context/Theme\";\nimport { View } from \"react-native\";\nimport SendSelectAmountScreen from \"@screens/Payment/SendSelectAmount\";\nimport MintSelectAmountScreen from \"@screens/Payment/MintSelectAmount\";\nimport MeltInputScreen from \"@screens/Payment/MeltInput\";\nimport HistoryNavigator from \"@src/nav/HistoryNavigator\";\n\nconst Stack = createNativeStackNavigator<RootStackParamList>();\n\nconst animationDuration = 250;\n\nexport default function Navigator({ shouldOnboard }: INavigatorProps) {\n  const { color } = useThemeContext();\n\n  return (\n    <View\n      style={{\n        position: \"absolute\",\n        height: \"100%\",\n        width: \"100%\",\n        backgroundColor: color.BACKGROUND,\n      }}\n    >\n      <Stack.Navigator\n        initialRouteName={shouldOnboard ? \"onboarding\" : \"dashboard\"}\n        screenOptions={{\n          headerShown: false,\n          animation: \"fade\",\n          animationDuration,\n          navigationBarColor: color.BACKGROUND,\n        }}\n      >\n        <Stack.Screen\n          name=\"onboarding\"\n          component={OnboardingScreen}\n          options={{\n            animation: \"default\",\n            animationDuration,\n          }}\n        />\n        <Stack.Screen\n          name=\"dashboard\"\n          component={Dashboard}\n          options={{\n            gestureEnabled: false,\n          }}\n        />\n        <Stack.Screen name=\"Settings\" component={SettingsNavigator} />\n        <Stack.Screen name=\"MeltInput\" component={MeltInputScreen} />\n        <Stack.Screen name=\"SendSelectAmount\" component={SendSelectAmountScreen} />\n        <Stack.Screen name=\"MintSelectAmount\" component={MintSelectAmountScreen} />\n        <Stack.Screen name=\"coinSelection\" component={CoinSelectionScreen} />\n        <Stack.Screen\n          name=\"processing\"\n          component={ProcessingScreen}\n          options={{ gestureEnabled: false }}\n        />\n        <Stack.Screen name=\"QRScanner\" component={QrScannerScreen} />\n        <Stack.Screen name=\"processingError\" component={ProcessingErrorScreen} />\n        <Stack.Screen name=\"mintInvoice\" component={InvoiceScreen} />\n        {/* sendable token created page */}\n        <Stack.Screen\n          name=\"encodedToken\"\n          component={EncodedTokenPage}\n          options={{\n            animation: \"slide_from_bottom\",\n            animationDuration,\n            gestureEnabled: false,\n          }}\n        />\n        <Stack.Screen name=\"success\" component={SuccessPage} options={{ gestureEnabled: false }} />\n        <Stack.Screen\n          name=\"successScreen\"\n          component={SuccessScreen}\n          options={{ gestureEnabled: false }}\n        />\n        <Stack.Screen name=\"Mint\" component={MintNavigator} />\n        <Stack.Screen name=\"Restore\" component={RestoreNavigator} />\n        <Stack.Screen name=\"History\" component={HistoryNavigator} />\n      </Stack.Navigator>\n    </View>\n  );\n}\n"
  },
  {
    "path": "src/components/nav/TopNav.tsx",
    "content": "import { LeftArrow } from \"@comps/Icons\";\nimport { useThemeContext } from \"@src/context/Theme\";\nimport { NS } from \"@src/i18n\";\nimport { globals, highlight as hi } from \"@styles\";\nimport type { ReactNode } from \"react\";\nimport { useTranslation } from \"react-i18next\";\nimport { Text, TouchableOpacity, View } from \"react-native\";\nimport { ScaledSheet } from \"react-native-size-matters\";\n\ninterface ITopNavProps {\n  screenName?: string;\n  withBackBtn?: boolean;\n  handlePress?: () => void;\n  cancel?: boolean;\n  handleCancel?: () => void;\n  rightAction?: ReactNode;\n}\n\nexport default function TopNav({\n  screenName,\n  withBackBtn,\n  handlePress,\n  cancel,\n  handleCancel,\n  rightAction,\n}: ITopNavProps) {\n  const { t } = useTranslation([NS.common]);\n  const { color, highlight } = useThemeContext();\n\n  return (\n    <View style={[styles.topNav, { backgroundColor: color.BACKGROUND }]}>\n      <View style={styles.leftSlot}>\n        {withBackBtn ? (\n          <TouchableOpacity\n            accessibilityRole=\"button\"\n            activeOpacity={0.7}\n            onPress={handlePress}\n            style={styles.backiconWrap}\n            testID=\"back-btn-top-nav\"\n          >\n            <LeftArrow color={hi[highlight]} />\n          </TouchableOpacity>\n        ) : null}\n      </View>\n\n      <View style={styles.titleSlot}>\n        {screenName ? (\n          <Text numberOfLines={1} style={[globals(color).navTxt, styles.title]}>\n            {screenName}\n          </Text>\n        ) : null}\n      </View>\n\n      <View style={styles.rightSlot}>\n        {rightAction}\n        {cancel ? (\n          <TouchableOpacity\n            accessibilityRole=\"button\"\n            activeOpacity={0.7}\n            style={styles.cancel}\n            onPress={handleCancel}\n          >\n            <Text style={globals(color, highlight).pressTxt}>{t(\"cancel\")}</Text>\n          </TouchableOpacity>\n        ) : null}\n      </View>\n    </View>\n  );\n}\n\nconst styles = ScaledSheet.create({\n  topNav: {\n    flexDirection: \"row\",\n    alignItems: \"center\",\n    minHeight: \"48@vs\",\n    paddingHorizontal: \"6@s\",\n  },\n  leftSlot: {\n    width: \"44@s\",\n    alignItems: \"flex-start\",\n    justifyContent: \"center\",\n  },\n  titleSlot: {\n    flex: 1,\n    justifyContent: \"center\",\n    paddingHorizontal: \"6@s\",\n  },\n  title: {\n    fontSize: \"17@ms\",\n    lineHeight: \"22@vs\",\n  },\n  rightSlot: {\n    flexDirection: \"row\",\n    alignItems: \"center\",\n    justifyContent: \"flex-end\",\n    minWidth: \"44@s\",\n  },\n  backiconWrap: {\n    width: \"44@s\",\n    height: \"44@s\",\n    alignItems: \"center\",\n    justifyContent: \"center\",\n  },\n  cancel: {\n    minHeight: \"44@vs\",\n    justifyContent: \"center\",\n    paddingHorizontal: \"10@s\",\n  },\n});\n"
  },
  {
    "path": "src/components/nav/utils.ts",
    "content": "import type { TBeforeRemoveEvent } from \"@model/nav\";\nimport { l } from \"@src/logger\";\n\nconst screens = [\"dashboard\", \"auth\", \"qr scan\", \"Address book\", \"Seed\"];\n\nexport function preventBack(e: TBeforeRemoveEvent, dispatch: (action: any) => void) {\n  e.preventDefault();\n  l({\n    payload: e.data.action.payload,\n    type: e.data.action.type,\n    source: e.data.action.source,\n    target: e.data.action.target,\n  });\n  for (let i = 0; i < screens.length; i++) {\n    const screen = screens[i];\n    if (\n      e.data.action.payload &&\n      \"name\" in e.data.action.payload &&\n      e.data.action.payload.name === screen\n    ) {\n      dispatch(e.data.action);\n    }\n  }\n}\n"
  },
  {
    "path": "src/config/config.base.ts",
    "content": "import { env } from \"@src/consts\";\nimport { NativeModules } from \"react-native\";\n\nfunction getDebugHost() {\n  try {\n    const raw = NativeModules?.SourceCode?.scriptURL as string | undefined;\n    if (!raw || typeof raw !== \"string\") {\n      return;\n    }\n    const url = new URL(raw);\n    return { hostname: url.hostname, port: url.port };\n    // eslint-disable-next-line no-console\n  } catch (e) {\n    console.log(\"[getDebugHost][Error]\", e);\n  }\n}\nexport interface ConfigBaseProps {\n  persistNavigation: \"always\" | \"dev\" | \"prod\" | \"never\";\n  catchErrors: \"always\" | \"dev\" | \"prod\" | \"never\";\n  exitRoutes: string[];\n  env: typeof env;\n  hostname?: string | undefined;\n  port?: string | undefined;\n}\n\nexport type PersistNavigationConfig = ConfigBaseProps[\"persistNavigation\"];\n\nconst BaseConfig = {\n  // This feature is particularly useful in development mode, but\n  // can be used in production as well if you prefer.\n  persistNavigation: \"dev\",\n\n  /**\n   * Only enable if we're catching errors in the right environment\n   */\n  catchErrors: \"always\",\n\n  /**\n   * This is a list of all the route names that will exit the app if the back button\n   * is pressed while in that screen. Only affects Android.\n   */\n  exitRoutes: [\"dashboard\"],\n  env,\n\n  ...(getDebugHost() ?? {}),\n} as const;\n\nexport default BaseConfig;\n"
  },
  {
    "path": "src/config/config.dev.ts",
    "content": "/**\n * These are configuration settings for the dev environment.\n *\n * Do not include API secrets in this file or anywhere in your JS.\n *\n * https://reactnative.dev/docs/security#storing-sensitive-info\n */\nexport default {\n  API_URL: \"https://api.rss2json.com/v1/\",\n  skipVerification: true,\n};\n"
  },
  {
    "path": "src/config/config.prod.ts",
    "content": "/**\n * These are configuration settings for the production environment.\n *\n * Do not include API secrets in this file or anywhere in your JS.\n *\n * https://reactnative.dev/docs/security#storing-sensitive-info\n */\nexport default {\n  API_URL: \"CHANGEME\",\n  skipVerification: false,\n};\n"
  },
  {
    "path": "src/config/index.ts",
    "content": "/**\n * This file imports configuration objects from either the config.dev.js file\n * or the config.prod.js file depending on whether we are in __DEV__ or not.\n *\n * Note that we do not gitignore these files. Unlike on web servers, just because\n * these are not checked into your repo doesn't mean that they are secure.\n * In fact, you're shipping a JavaScript bundle with every\n * config variable in plain text. Anyone who downloads your app can easily\n * extract them.\n *\n * If you doubt this, just bundle your app, and then go look at the bundle and\n * search it for one of your config variable values. You'll find it there.\n *\n * Read more here: https://reactnative.dev/docs/security#storing-sensitive-info\n */\nimport BaseConfig from \"./config.base\";\nimport DevConfig from \"./config.dev\";\nimport ProdConfig from \"./config.prod\";\n\nlet ExtraConfig = ProdConfig;\n\nif (__DEV__) {\n  ExtraConfig = DevConfig;\n}\n\nconst Config = { ...BaseConfig, ...ExtraConfig } as const;\n\nexport default Config;\n"
  },
  {
    "path": "src/consts/env.ts",
    "content": "import type { IExpoConfig } from \"@model\";\nimport { IEnv } from \"@model/env\";\nimport { default as Consts, ExecutionEnvironment as ExecEnv } from \"expo-constants\";\nimport { Platform } from \"react-native\";\n\nimport { version } from \"../../package.json\";\nimport { expo } from \"../../app.json\";\n\nconst { executionEnvironment: execEnv } = Consts;\n// `true` when running in Expo Go.\nconst isExpoDev = execEnv && ExecEnv?.StoreClient && execEnv === ExecEnv?.StoreClient;\n// `true` when running in preview/production mode.\nconst isExpoProd = execEnv && ExecEnv?.Standalone && execEnv === ExecEnv?.Standalone;\n// True if the app is running in an `expo build` app or if it's running in Expo Go.\nconst isExpo = isExpoDev || isExpoProd;\n\nconst isReactNativeDevMode = typeof __DEV__ === \"boolean\" && __DEV__;\n\nexport { isExpo, isExpoDev, isExpoProd, isReactNativeDevMode };\n\ntype AppVariant = \"preview\" | \"beta\" | \"prod\" | \"dev\" | undefined;\n\nconst typedEnv = process?.env as unknown as IEnv;\n\nfunction nodeEnvShort(): \"test\" | AppVariant {\n  if (!typedEnv?.NODE_ENV) {\n    typedEnv.NODE_ENV = \"development\";\n    return;\n  }\n  if (typedEnv?.NODE_ENV === \"production\") {\n    return \"prod\";\n  }\n  if (typedEnv?.NODE_ENV === \"development\") {\n    return \"dev\";\n  }\n  if (typedEnv?.NODE_ENV === \"test\") {\n    return \"test\";\n  }\n  if (typedEnv?.NODE_ENV === \"preview\") {\n    return \"preview\";\n  }\n  if (typedEnv?.NODE_ENV === \"beta\") {\n    return \"beta\";\n  }\n}\n\nfunction appVariant(): AppVariant {\n  if (!typedEnv?.APP_VARIANT) {\n    typedEnv.APP_VARIANT = \"dev\";\n    return;\n  }\n  if (typedEnv?.APP_VARIANT === \"prod\") {\n    return \"prod\";\n  }\n  if (typedEnv?.APP_VARIANT === \"dev\") {\n    return \"dev\";\n  }\n  if (typedEnv?.APP_VARIANT === \"preview\") {\n    return \"preview\";\n  }\n  if (typedEnv?.APP_VARIANT === \"beta\") {\n    return \"beta\";\n  }\n}\n\nconst config: Readonly<IExpoConfig | undefined | null> = Consts?.expoConfig;\n\nexport const env /* : Readonly<IExpoConfig['extra'] & { BUGSNAG_API_KEY?: string }> */ = {\n  DEBUG: typedEnv?.DEBUG || config?.extra?.DEBUG,\n\n  NODE_ENV: typedEnv?.NODE_ENV || config?.extra?.NODE_ENV,\n\n  NODE_ENV_SHORT:\n    typedEnv?.NODE_ENV_SHORT || config?.extra?.NODE_ENV_SHORT || nodeEnvShort() || appVariant(),\n\n  APP_VARIANT:\n    typedEnv?.APP_VARIANT || config?.extra?.APP_VARIANT || appVariant() || nodeEnvShort(),\n\n  SENTRY_DSN: typedEnv?.SENTRY_DSN || typedEnv?.SENTRY_DSN || config?.extra?.SENTRY_DSN,\n\n  isExpo,\n  isExpoDev,\n  isExpoBeta:\n    typedEnv?.APP_VARIANT === \"beta\" ||\n    config?.extra?.APP_VARIANT === \"beta\" ||\n    appVariant() === \"beta\",\n  isExpoProd,\n  isReactNativeDevMode,\n} as const;\n\nexport const isTestMode =\n  (typeof __TEST__ === \"boolean\" && __TEST__) ||\n  (typeof jest !== \"undefined\" && jest.isMockFunction(jest)) ||\n  env?.NODE_ENV_SHORT === \"test\" ||\n  env?.NODE_ENV === \"test\" ||\n  env?.APP_VARIANT === \"test\" ||\n  env?.NODE_ENV === \"test\" ||\n  (env?.NODE_ENV === \"test\" && env?.NODE_ENV_SHORT === \"test\") ||\n  typedEnv?.NODE_ENV === \"test\" ||\n  config?.extra?.NODE_ENV === \"test\";\n\nexport const isIOS = Platform.OS === \"ios\";\nexport const isNotIosStore = __DEV__ || env.isExpoBeta || !isIOS;\nexport const appVersion = `eNuts v${expo.version}${env.isExpoBeta ? \"-beta\" : \"\"}`;\n"
  },
  {
    "path": "src/consts/index.ts",
    "content": "export { env, isExpo, isExpoDev, isExpoProd, isIOS, isReactNativeDevMode, isTestMode } from \"./env\";\nexport { DayInMs, HourInMs, MinuteInMs, MonthInMs, SecondInMs, WeekInMs, YearInMs } from \"./time\";\n"
  },
  {
    "path": "src/consts/time.ts",
    "content": "export const Ten_seconds = 10_000; /*  */\nexport const MinuteInS = 60; /*  */\nexport const FiveMins = 5 * MinuteInS;\nexport const MinuteInMs = 60_000; /* 1_000 * 60 */\nexport const HourInMs = 3_600_000; /* MinuteInMs * 60 */\nexport const DayInMs = 86_400_000; /* HourInMs * 24 */\nexport const SecondInMs = 1_000; /* 1_000 */\nexport const WeekInMs = 604_800_000; /* DayInMs * 7 */\nexport const MonthInMs = 2_592_000_000; /* DayInMs * 30 */\nexport const YearInMs = 31_536_000_000; /* DayInMs * 365 */\n"
  },
  {
    "path": "src/consts/urls.ts",
    "content": "export const repoIssueUrl = \"https://github.com/cashubtc/eNuts/issues/new\";\nexport const reportIssueUrl = \"https://enuts.cash/report-issue\";\n"
  },
  {
    "path": "src/context/Balance.tsx",
    "content": "export { BalanceCtx, BalanceProvider, useBalanceContext } from \"@cashu/coco-react\";\nexport type { BalanceContextValue } from \"@cashu/coco-react\";\n"
  },
  {
    "path": "src/context/Currency.tsx",
    "content": "import { appLogger } from \"@src/logger\";\nimport type { IExchangeRates, IFormattedAmount, TCurrencyCode } from \"@model\";\nimport { store } from \"@store\";\nimport { STORE_KEYS } from \"@store/consts\";\nimport { exchangeRateService } from \"@src/services/ExchangeRateService\";\nimport { createContext, useContext, useEffect, useRef, useState } from \"react\";\nimport { AppState } from \"react-native\";\nimport { formatInt } from \"@util\";\n\nconst REFRESH_INTERVAL_MS = 5 * 60 * 1000; // 5 minutes\nconst DEFAULT_CURRENCY = \"USD\";\n\ninterface ICurrencyContext {\n  rates: IExchangeRates | null;\n  selectedCurrency: TCurrencyCode;\n  setSelectedCurrency: (currency: TCurrencyCode) => Promise<void>;\n  isLoading: boolean;\n  lastUpdate: number | null;\n  error: string | null;\n  refreshRates: () => Promise<void>;\n  formatSatsAsCurrency: (sats: number, currencyCode?: TCurrencyCode) => string;\n  formatBalance: boolean;\n  setFormatBalance: (value: boolean) => Promise<void>;\n  formatAmount: (sats: number) => IFormattedAmount;\n  convertFiatToSats: (fiatAmount: number, currencyCode?: TCurrencyCode) => number;\n}\n\nconst useCurrency = () => {\n  const [rates, setRates] = useState<IExchangeRates | null>(null);\n  const [selectedCurrency, setSelectedCurrencyState] = useState<TCurrencyCode>(DEFAULT_CURRENCY);\n  const [isLoading, setIsLoading] = useState<boolean>(true);\n  const [lastUpdate, setLastUpdate] = useState<number | null>(null);\n  const [error, setError] = useState<string | null>(null);\n  const [formatBalance, setFormatBalanceState] = useState<boolean>(false);\n  const [isInitialized, setIsInitialized] = useState(false);\n\n  const intervalRef = useRef<NodeJS.Timeout | null>(null);\n  const appStateRef = useRef(AppState.currentState);\n  // Ref to track current rates for use in async callbacks (avoids stale closures)\n  const ratesRef = useRef<IExchangeRates | null>(null);\n\n  /**\n   * Load cached rates and preferences from storage\n   */\n  const loadFromStorage = async () => {\n    try {\n      // Load cached exchange rates\n      const cachedRates = await store.get(STORE_KEYS.exchangeRates);\n      if (cachedRates) {\n        const parsedRates = JSON.parse(cachedRates) as IExchangeRates;\n        if (exchangeRateService.validateRates(parsedRates)) {\n          setRates(parsedRates);\n          appLogger.debug(\"Currency: Loaded cached exchange rates\");\n        }\n      }\n\n      // Load cached timestamp\n      const cachedTimestamp = await store.get(STORE_KEYS.exchangeRatesTimestamp);\n      if (cachedTimestamp) {\n        setLastUpdate(parseInt(cachedTimestamp, 10));\n      }\n\n      // Load selected currency preference\n      const savedCurrency = await store.get(STORE_KEYS.selectedCurrency);\n      if (savedCurrency) {\n        setSelectedCurrencyState(savedCurrency);\n        appLogger.debug(\"Currency: Loaded selected currency\", {\n          currency: savedCurrency,\n        });\n      }\n\n      // Load format balance preference\n      const savedFormatBalance = await store.get(STORE_KEYS.formatBalance);\n      if (savedFormatBalance !== null) {\n        setFormatBalanceState(savedFormatBalance === \"true\");\n        appLogger.debug(\"Currency: Loaded format balance preference\", {\n          formatBalance: savedFormatBalance,\n        });\n      }\n    } catch (err) {\n      appLogger.error(\"Currency: Failed to load from storage\", err);\n    }\n  };\n\n  // Keep ratesRef in sync with rates state\n  useEffect(() => {\n    ratesRef.current = rates;\n  }, [rates]);\n\n  /**\n   * Fetch fresh exchange rates from API\n   */\n  const fetchRates = async () => {\n    try {\n      setError(null);\n      const freshRates = await exchangeRateService.fetchRates();\n\n      if (exchangeRateService.validateRates(freshRates)) {\n        setRates(freshRates);\n        const now = Date.now();\n        setLastUpdate(now);\n\n        // Persist to storage\n        await store.set(STORE_KEYS.exchangeRates, JSON.stringify(freshRates));\n        await store.set(STORE_KEYS.exchangeRatesTimestamp, now.toString());\n\n        appLogger.info(\"Currency: Successfully updated exchange rates\");\n      } else {\n        throw new Error(\"Invalid rates format received from API\");\n      }\n    } catch (err) {\n      const errorMessage = err instanceof Error ? err.message : \"Unknown error\";\n      appLogger.error(\"Currency: Failed to fetch exchange rates\", err);\n      setError(errorMessage);\n\n      // If we have no cached rates, this is a critical error\n      // Use ref to avoid stale closure issue\n      if (!ratesRef.current) {\n        setError(\"Unable to load exchange rates. Please check your internet connection.\");\n      }\n    }\n  };\n\n  /**\n   * Initialize currency context\n   */\n  useEffect(() => {\n    async function initialize() {\n      setIsLoading(true);\n\n      // Load cached data first\n      await loadFromStorage();\n\n      // Then fetch fresh data\n      await fetchRates();\n\n      setIsLoading(false);\n      setIsInitialized(true);\n    }\n\n    void initialize();\n  }, []);\n\n  /**\n   * Set up periodic refresh interval\n   */\n  useEffect(() => {\n    if (!isInitialized) return;\n\n    // Clear any existing interval\n    if (intervalRef.current) {\n      clearInterval(intervalRef.current);\n    }\n\n    // Set up new interval\n    intervalRef.current = setInterval(() => {\n      appLogger.debug(\"Currency: Periodic refresh triggered\");\n      void fetchRates();\n    }, REFRESH_INTERVAL_MS);\n\n    // Cleanup on unmount\n    return () => {\n      if (intervalRef.current) {\n        clearInterval(intervalRef.current);\n        intervalRef.current = null;\n      }\n    };\n  }, [isInitialized]);\n\n  /**\n   * Handle app state changes (pause/resume)\n   */\n  useEffect(() => {\n    const subscription = AppState.addEventListener(\"change\", (nextAppState) => {\n      // App coming back to foreground\n      if (appStateRef.current.match(/inactive|background/) && nextAppState === \"active\") {\n        appLogger.debug(\"Currency: App resumed, fetching fresh rates\");\n        void fetchRates();\n      }\n\n      appStateRef.current = nextAppState;\n    });\n\n    return () => {\n      subscription.remove();\n    };\n  }, []);\n\n  /**\n   * Update selected currency and persist to storage\n   */\n  const setSelectedCurrency = async (currency: TCurrencyCode) => {\n    try {\n      // Validate currency exists in rates\n      if (rates && !rates[currency]) {\n        appLogger.warn(\"Currency: Attempted to select invalid currency\", {\n          currency,\n        });\n        return;\n      }\n\n      setSelectedCurrencyState(currency);\n      await store.set(STORE_KEYS.selectedCurrency, currency);\n      appLogger.info(\"Currency: Selected currency updated\", { currency });\n    } catch (err) {\n      appLogger.error(\"Currency: Failed to update selected currency\", err);\n    }\n  };\n\n  /**\n   * Manual refresh function exposed to consumers\n   */\n  const refreshRates = async () => {\n    appLogger.debug(\"Currency: Manual refresh requested\");\n    await fetchRates();\n  };\n\n  /**\n   * Update format balance preference and persist to storage\n   */\n  const setFormatBalance = async (value: boolean) => {\n    try {\n      setFormatBalanceState(value);\n      await store.set(STORE_KEYS.formatBalance, value.toString());\n      appLogger.info(\"Currency: Format balance preference updated\", { value });\n    } catch (err) {\n      appLogger.error(\"Currency: Failed to update format balance preference\", err);\n    }\n  };\n\n  /**\n   * Convert satoshis to formatted currency string\n   * @param sats - Amount in satoshis\n   * @param currencyCode - Optional currency code (defaults to selectedCurrency)\n   * @returns Formatted number (e.g., \"123.45\", \"0.11\") without currency symbol\n   */\n  const formatSatsAsCurrency = (sats: number, currencyCode?: TCurrencyCode): string => {\n    // Use provided currency or fall back to selected currency\n    const currency = currencyCode || selectedCurrency;\n\n    // Return empty string if no rates available\n    if (!rates || !rates[currency]) {\n      return \"\";\n    }\n\n    // Convert satoshis to BTC\n    const btcAmount = sats / 100_000_000;\n\n    // Get exchange rate\n    const rate = rates[currency];\n\n    // Calculate fiat amount\n    const fiatAmount = btcAmount * rate.last;\n\n    // Format the number with proper locale-specific decimal/thousand separators\n    // Currency symbol will be displayed separately in the UI\n    return fiatAmount.toLocaleString(undefined, {\n      minimumFractionDigits: 2,\n      maximumFractionDigits: 2,\n    });\n  };\n\n  /**\n   * Format amount with symbol based on formatBalance preference\n   * @param sats - Amount in satoshis\n   * @returns Object with formatted amount and symbol\n   */\n  const formatAmount = (sats: number): IFormattedAmount => {\n    // If formatBalance is false OR rates are unavailable, show satoshis\n    if (!formatBalance || !rates || !rates[selectedCurrency]) {\n      const formatted = formatInt(sats, \"standard\");\n      const symbol = Math.abs(sats) === 1 ? \"Sat\" : \"Sats\";\n      return { formatted, symbol };\n    }\n\n    // Otherwise show fiat currency\n    const formatted = formatSatsAsCurrency(sats);\n    const symbol = rates[selectedCurrency]?.symbol || selectedCurrency;\n    return { formatted, symbol };\n  };\n\n  /**\n   * Convert fiat currency amount to satoshis\n   * @param fiatAmount - Amount in fiat currency\n   * @param currencyCode - Optional currency code (defaults to selectedCurrency)\n   * @returns Amount in satoshis (rounded to whole number)\n   */\n  const convertFiatToSats = (fiatAmount: number, currencyCode?: TCurrencyCode): number => {\n    // Use provided currency or fall back to selected currency\n    const currency = currencyCode || selectedCurrency;\n\n    // Return 0 if no rates available or invalid input\n    if (!rates || !rates[currency] || !fiatAmount || fiatAmount <= 0) {\n      return 0;\n    }\n\n    // Get exchange rate\n    const rate = rates[currency];\n\n    // Convert fiat to BTC\n    const btcAmount = fiatAmount / rate.last;\n\n    // Convert BTC to satoshis and round to whole number (no decimals in sats)\n    const sats = Math.round(btcAmount * 100_000_000);\n\n    return sats;\n  };\n\n  return {\n    rates,\n    selectedCurrency,\n    setSelectedCurrency,\n    isLoading,\n    lastUpdate,\n    error,\n    refreshRates,\n    formatSatsAsCurrency,\n    formatBalance,\n    setFormatBalance,\n    formatAmount,\n    convertFiatToSats,\n  };\n};\n\ntype UseCurrencyType = ReturnType<typeof useCurrency>;\n\nconst CurrencyContext = createContext<UseCurrencyType>({\n  rates: null,\n  selectedCurrency: DEFAULT_CURRENCY,\n  setSelectedCurrency: async () => {},\n  isLoading: true,\n  lastUpdate: null,\n  error: null,\n  refreshRates: async () => {},\n  formatSatsAsCurrency: () => \"\",\n  formatBalance: false,\n  setFormatBalance: async () => {},\n  formatAmount: () => ({ formatted: \"\", symbol: \"\" }),\n  convertFiatToSats: () => 0,\n});\n\nexport const useCurrencyContext = () => useContext(CurrencyContext);\n\nexport const CurrencyProvider = ({ children }: { children: React.ReactNode }) => (\n  <CurrencyContext.Provider value={useCurrency()}>{children}</CurrencyContext.Provider>\n);\n\n// Export types for consumers\nexport type { ICurrencyContext };\n"
  },
  {
    "path": "src/context/KnownMints.tsx",
    "content": "import { useMemo } from \"react\";\nimport { Mint } from \"@cashu/coco-core\";\nimport { useMints, useBalanceContext } from \"@cashu/coco-react\";\n\nexport type KnownMintWithBalance = Mint & { balance: number };\n\nexport const useKnownMints = () => {\n  const { trustedMints } = useMints();\n  const { balances } = useBalanceContext();\n\n  const knownMints: KnownMintWithBalance[] = useMemo(\n    () =>\n      trustedMints.map((mint) => ({\n        ...mint,\n        balance: balances.byMint[mint.mintUrl]?.total || 0,\n      })),\n    [trustedMints, balances],\n  );\n\n  return { knownMints, loading: false };\n};\n"
  },
  {
    "path": "src/context/Linking.tsx",
    "content": "import { parsePaymentString, type PaymentStringCandidate } from \"@util\";\nimport { useCallback, useEffect, useState } from \"react\";\nimport type { EmitterSubscription } from \"react-native\";\nimport { Linking } from \"react-native\";\n\nexport interface EventType {\n  url: string;\n  nativeEvent?: MessageEvent;\n}\n/**\n * stolen from expo\n * Add a handler to `Linking` changes by listening to the `url` event type and providing the handler.\n * It is recommended to use the [`useURL()`](#useurl) hook instead.\n * @param type The only valid type is `'url'`.\n * @param handler An [`URLListener`](#urllistener) function that takes an `event` object of the type\n * [`EventType`](#eventype).\n * @return An EmitterSubscription that has the remove method from EventSubscription\n * @see [React Native Docs Linking page](https://reactnative.dev/docs/linking#addeventlistener).\n */\nexport function addEventListener(\n  type: \"url\",\n  handler: (event: EventType) => void,\n): EmitterSubscription {\n  return Linking.addEventListener(type, (e) => {\n    // alert('calling link event')\n    handler(e);\n  });\n}\n\nconst LINK_CANDIDATE_PRIORITY: PaymentStringCandidate[\"kind\"][] = [\n  \"cashuToken\",\n  \"lightningInvoice\",\n  \"lightningAddress\",\n  \"lnurl\",\n];\n\nfunction normalizePaymentLink(url: string) {\n  const candidates = parsePaymentString(url);\n  const selected = LINK_CANDIDATE_PRIORITY.map((kind) =>\n    candidates.find((candidate) => candidate.kind === kind),\n  ).find((candidate): candidate is PaymentStringCandidate => Boolean(candidate));\n\n  return selected?.value || \"\";\n}\n\nexport const useInitialURL = () => {\n  const [url, setUrl] = useState<string>(\"\");\n  const [processing, setProcessing] = useState(true);\n\n  function onChange(event: { url: string }) {\n    if (!event?.url) {\n      return setUrl(\"\");\n    }\n    return setUrl(normalizePaymentLink(event.url));\n  }\n\n  const clearUrl = useCallback(() => setUrl(\"\"), []);\n\n  useEffect(() => {\n    const getUrlAsync = async () => {\n      // Get the deep link used to open the app\n      let initialUrl = (await Linking.getInitialURL()) || \"\";\n      if (!initialUrl) {\n        return;\n      }\n      initialUrl = normalizePaymentLink(initialUrl);\n      setProcessing(false);\n      return setUrl(initialUrl);\n    };\n    void getUrlAsync();\n    const subscription = addEventListener(\"url\", onChange);\n    return () => subscription.remove();\n  }, []);\n\n  return { url, clearUrl, processing };\n};\n"
  },
  {
    "path": "src/context/Manager.tsx",
    "content": "import \"../shim\";\nexport {\n  ManagerCtx,\n  ManagerProvider,\n  ManagerGate,\n  useManager,\n  useManagerContext,\n} from \"@cashu/coco-react\";\nexport type { ManagerContextValue } from \"@cashu/coco-react\";\n"
  },
  {
    "path": "src/context/NfcAmountLimits.tsx",
    "content": "import { store } from \"@store\";\nimport { STORE_KEYS } from \"@store/consts\";\nimport { createContext, useCallback, useContext, useEffect, useState } from \"react\";\n\n// Special value for \"no limit\"\nexport const NO_LIMIT = -1;\n\n// Default limit in sats (50k sats)\nconst DEFAULT_LIMIT = 50_000;\n\ninterface INfcAmountLimitsContext {\n  /** The configured default max amount (-1 = no limit) */\n  defaultMaxAmount: number;\n  /** Whether settings are still loading */\n  isLoading: boolean;\n  /** Set the default max amount */\n  setDefaultMaxAmount: (amount: number) => Promise<void>;\n}\n\nconst useNfcAmountLimitsState = () => {\n  const [defaultMaxAmount, setDefaultMaxAmountState] = useState<number>(DEFAULT_LIMIT);\n  const [isLoading, setIsLoading] = useState(true);\n\n  // Load saved settings on mount\n  useEffect(() => {\n    async function loadSettings() {\n      try {\n        const savedMaxAmount = await store.get(STORE_KEYS.nfcDefaultMaxAmount);\n        if (savedMaxAmount !== null) {\n          setDefaultMaxAmountState(parseInt(savedMaxAmount, 10));\n        }\n      } catch (error) {\n        console.error(\"Failed to load NFC settings:\", error);\n      } finally {\n        setIsLoading(false);\n      }\n    }\n    void loadSettings();\n  }, []);\n\n  // Save default max amount\n  const setDefaultMaxAmount = useCallback(async (amount: number) => {\n    setDefaultMaxAmountState(amount);\n    await store.set(STORE_KEYS.nfcDefaultMaxAmount, amount.toString());\n  }, []);\n\n  return {\n    defaultMaxAmount,\n    isLoading,\n    setDefaultMaxAmount,\n  };\n};\n\nconst NfcAmountLimitsContext = createContext<INfcAmountLimitsContext>({\n  defaultMaxAmount: DEFAULT_LIMIT,\n  isLoading: true,\n  setDefaultMaxAmount: async () => {},\n});\n\nexport const useNfcAmountLimitsContext = () => useContext(NfcAmountLimitsContext);\n\nexport const NfcAmountLimitsProvider = ({ children }: { children: React.ReactNode }) => (\n  <NfcAmountLimitsContext.Provider value={useNfcAmountLimitsState()}>\n    {children}\n  </NfcAmountLimitsContext.Provider>\n);\n\nexport type { INfcAmountLimitsContext };\n"
  },
  {
    "path": "src/context/Npc.tsx",
    "content": "import type { Manager } from \"@cashu/coco-core\";\nimport { useManager } from \"@src/context/Manager\";\nimport {\n  createDefaultNpcAccount,\n  getNpcAccountInfo,\n  getNpcAddress,\n  getNpcExtension,\n  getNpcPrivateKeyStorageKey,\n  isValidNpcUsername,\n  type IStoredNpcAccount,\n  NPC_DEFAULT_ACCOUNT_ID,\n  normalizeNpcPrivateKey,\n  payNpcUsernameRequest,\n  registerNpcAccount,\n  removeNpcAccount,\n  requestNpcUsername,\n  syncNpcAccount,\n  type TNpcUsernameRequest,\n} from \"@src/services/NpcService\";\nimport { secureStore, store } from \"@store\";\nimport { STORE_KEYS } from \"@store/consts\";\nimport { createContext, useCallback, useContext, useEffect, useMemo, useState } from \"react\";\nimport type React from \"react\";\n\nexport type INpcAccount = IStoredNpcAccount & {\n  npub: string;\n  address: string;\n  isDefault: boolean;\n  isRunning: boolean;\n  isSyncing: boolean;\n};\n\nexport type TNpcUsernameAccountRequest = TNpcUsernameRequest & {\n  accountId: string;\n};\n\ninterface INpcContext {\n  accounts: INpcAccount[];\n  isLoading: boolean;\n  busyAccountId: string | null;\n  deriveAccount: () => Promise<void>;\n  importPrivateKeyAccount: (privateKey: string) => Promise<void>;\n  removeAccount: (accountId: string) => Promise<void>;\n  syncAccount: (accountId: string) => Promise<void>;\n  syncAll: () => Promise<void>;\n  requestUsername: (accountId: string, username: string) => Promise<TNpcUsernameAccountRequest>;\n  confirmUsername: (usernameRequest: TNpcUsernameAccountRequest) => Promise<void>;\n}\n\nconst NpcCtx = createContext<INpcContext | null>(null);\n\nfunction sortAccounts(accounts: IStoredNpcAccount[]) {\n  return [...accounts].sort((a, b) => {\n    if (a.id === NPC_DEFAULT_ACCOUNT_ID) return -1;\n    if (b.id === NPC_DEFAULT_ACCOUNT_ID) return 1;\n    if (a.source === \"seed\" && b.source === \"seed\") {\n      return a.accountIndex - b.accountIndex;\n    }\n    if (a.source === \"seed\") return -1;\n    if (b.source === \"seed\") return 1;\n    return a.id.localeCompare(b.id);\n  });\n}\n\nfunction parseAccounts(raw: string | null): IStoredNpcAccount[] {\n  if (!raw) {\n    return [createDefaultNpcAccount()];\n  }\n\n  try {\n    const parsed = JSON.parse(raw);\n    if (!Array.isArray(parsed)) {\n      return [createDefaultNpcAccount()];\n    }\n\n    const accounts = parsed\n      .map((account): IStoredNpcAccount | null => {\n        if (!account || typeof account.id !== \"string\" || typeof account.label !== \"string\") {\n          return null;\n        }\n\n        if (\n          (account.source === \"seed\" || account.source === undefined) &&\n          typeof account.accountIndex === \"number\"\n        ) {\n          return {\n            id: account.id,\n            source: \"seed\",\n            accountIndex: account.accountIndex,\n            label: account.label,\n            username: typeof account.username === \"string\" ? account.username : undefined,\n          };\n        }\n\n        if (account.source === \"privateKey\" && typeof account.privateKeyStorageKey === \"string\") {\n          return {\n            id: account.id,\n            source: \"privateKey\",\n            privateKeyStorageKey: account.privateKeyStorageKey,\n            label: account.label,\n            username: typeof account.username === \"string\" ? account.username : undefined,\n          };\n        }\n\n        return null;\n      })\n      .filter((account): account is IStoredNpcAccount => account !== null);\n\n    if (!accounts.some((account) => account.id === NPC_DEFAULT_ACCOUNT_ID)) {\n      accounts.unshift(createDefaultNpcAccount());\n    }\n\n    return sortAccounts(accounts.length ? accounts : [createDefaultNpcAccount()]);\n  } catch {\n    return [createDefaultNpcAccount()];\n  }\n}\n\nasync function loadStoredAccounts() {\n  const accounts = parseAccounts(await store.get(STORE_KEYS.npcAccounts));\n  await saveStoredAccounts(accounts);\n  return accounts;\n}\n\nasync function saveStoredAccounts(accounts: IStoredNpcAccount[]) {\n  await store.set(STORE_KEYS.npcAccounts, JSON.stringify(sortAccounts(accounts)));\n}\n\nasync function hydrateAccount(manager: Manager, account: IStoredNpcAccount): Promise<INpcAccount> {\n  const { api, identity } = await registerNpcAccount(manager, account);\n  let username = account.username;\n\n  try {\n    const info = await getNpcAccountInfo(api);\n    username = info.name || username;\n  } catch {\n    // Account metadata can be unavailable while offline; keep the local record.\n  }\n\n  const status = api.getStatus();\n\n  return {\n    ...account,\n    username,\n    npub: identity.npub,\n    address: getNpcAddress(username, identity.npub),\n    isDefault: account.id === NPC_DEFAULT_ACCOUNT_ID,\n    isRunning: status.isRunning,\n    isSyncing: status.isSyncing,\n  };\n}\n\nexport function NpcProvider({ children }: { children: React.ReactNode }) {\n  const manager = useManager();\n  const [storedAccounts, setStoredAccounts] = useState<IStoredNpcAccount[]>([]);\n  const [accounts, setAccounts] = useState<INpcAccount[]>([]);\n  const [isLoading, setIsLoading] = useState(true);\n  const [busyAccountId, setBusyAccountId] = useState<string | null>(null);\n\n  const reloadAccounts = useCallback(\n    async (nextAccounts?: IStoredNpcAccount[]) => {\n      const loaded = nextAccounts || (await loadStoredAccounts());\n      const hydrated = await Promise.all(loaded.map((account) => hydrateAccount(manager, account)));\n      setStoredAccounts(loaded);\n      setAccounts(hydrated);\n    },\n    [manager],\n  );\n\n  useEffect(() => {\n    let cancelled = false;\n\n    async function initializeAccounts() {\n      setIsLoading(true);\n      try {\n        const loaded = await loadStoredAccounts();\n        const hydrated = await Promise.all(\n          loaded.map((account) => hydrateAccount(manager, account)),\n        );\n\n        if (!cancelled) {\n          setStoredAccounts(loaded);\n          setAccounts(hydrated);\n        }\n      } finally {\n        if (!cancelled) {\n          setIsLoading(false);\n        }\n      }\n    }\n\n    void initializeAccounts();\n\n    return () => {\n      cancelled = true;\n    };\n  }, [manager]);\n\n  const deriveAccount = useCallback(async () => {\n    const nextIndex =\n      storedAccounts.reduce(\n        (max, account) => (account.source === \"seed\" ? Math.max(max, account.accountIndex) : max),\n        0,\n      ) + 1;\n    const nextAccount: IStoredNpcAccount = {\n      id: `npc-seed-${nextIndex}`,\n      source: \"seed\",\n      accountIndex: nextIndex,\n      label: `Account ${nextIndex + 1}`,\n    };\n    const nextAccounts = [...storedAccounts, nextAccount];\n    await saveStoredAccounts(nextAccounts);\n    await reloadAccounts(nextAccounts);\n  }, [reloadAccounts, storedAccounts]);\n\n  const importPrivateKeyAccount = useCallback(\n    async (privateKey: string) => {\n      const normalizedPrivateKey = normalizeNpcPrivateKey(privateKey);\n      const importedCount = storedAccounts.filter(\n        (account) => account.source === \"privateKey\",\n      ).length;\n      const accountId = `npc-key-${Date.now()}`;\n      const privateKeyStorageKey = getNpcPrivateKeyStorageKey(accountId);\n      const nextAccount: IStoredNpcAccount = {\n        id: accountId,\n        source: \"privateKey\",\n        privateKeyStorageKey,\n        label: `Imported account ${importedCount + 1}`,\n      };\n      const nextAccounts = [...storedAccounts, nextAccount];\n\n      await secureStore.set(privateKeyStorageKey, normalizedPrivateKey);\n      try {\n        await saveStoredAccounts(nextAccounts);\n      } catch (error) {\n        try {\n          await secureStore.delete(privateKeyStorageKey);\n        } catch {}\n        throw error;\n      }\n      await reloadAccounts(nextAccounts);\n    },\n    [reloadAccounts, storedAccounts],\n  );\n\n  const removeAccount = useCallback(\n    async (accountId: string) => {\n      if (accountId === NPC_DEFAULT_ACCOUNT_ID) {\n        throw new Error(\"The default account cannot be removed.\");\n      }\n\n      setBusyAccountId(accountId);\n      try {\n        const account = storedAccounts.find((item) => item.id === accountId);\n        await removeNpcAccount(manager, accountId);\n        if (account?.source === \"privateKey\") {\n          await secureStore.delete(account.privateKeyStorageKey);\n        }\n        const nextAccounts = storedAccounts.filter((account) => account.id !== accountId);\n        await saveStoredAccounts(nextAccounts);\n        await reloadAccounts(nextAccounts);\n      } finally {\n        setBusyAccountId(null);\n      }\n    },\n    [manager, reloadAccounts, storedAccounts],\n  );\n\n  const syncAccount = useCallback(\n    async (accountId: string) => {\n      setBusyAccountId(accountId);\n      try {\n        await syncNpcAccount(manager, accountId);\n        await reloadAccounts(storedAccounts);\n      } finally {\n        setBusyAccountId(null);\n      }\n    },\n    [manager, reloadAccounts, storedAccounts],\n  );\n\n  const syncAll = useCallback(async () => {\n    setBusyAccountId(\"all\");\n    try {\n      await getNpcExtension(manager).syncAll();\n      await reloadAccounts(storedAccounts);\n    } finally {\n      setBusyAccountId(null);\n    }\n  }, [manager, reloadAccounts, storedAccounts]);\n\n  const persistUsername = useCallback(\n    async (accountId: string, username: string) => {\n      const nextAccounts = storedAccounts.map((item) =>\n        item.id === accountId ? { ...item, username } : item,\n      );\n      await saveStoredAccounts(nextAccounts);\n      await reloadAccounts(nextAccounts);\n    },\n    [reloadAccounts, storedAccounts],\n  );\n\n  const requestUsername = useCallback(\n    async (accountId: string, username: string) => {\n      const trimmed = username.trim();\n      if (!isValidNpcUsername(trimmed) || trimmed.length === 0) {\n        throw new Error(\"Use 3-32 letters, numbers, dots, dashes, or underscores.\");\n      }\n\n      const account = storedAccounts.find((item) => item.id === accountId);\n      if (!account) {\n        throw new Error(\"NPC account not found.\");\n      }\n\n      setBusyAccountId(accountId);\n      try {\n        const usernameRequest = await requestNpcUsername(manager, account, trimmed);\n        if (usernameRequest.type === \"free\") {\n          await persistUsername(accountId, trimmed);\n        }\n\n        return {\n          ...usernameRequest,\n          accountId,\n        };\n      } finally {\n        setBusyAccountId(null);\n      }\n    },\n    [manager, persistUsername, storedAccounts],\n  );\n\n  const confirmUsername = useCallback(\n    async (usernameRequest: TNpcUsernameAccountRequest) => {\n      const account = storedAccounts.find((item) => item.id === usernameRequest.accountId);\n      if (!account) {\n        throw new Error(\"NPC account not found.\");\n      }\n\n      setBusyAccountId(usernameRequest.accountId);\n      try {\n        await payNpcUsernameRequest(manager, account, usernameRequest);\n        await persistUsername(usernameRequest.accountId, usernameRequest.username);\n      } finally {\n        setBusyAccountId(null);\n      }\n    },\n    [manager, persistUsername, storedAccounts],\n  );\n\n  const value = useMemo(\n    () => ({\n      accounts,\n      isLoading,\n      busyAccountId,\n      deriveAccount,\n      importPrivateKeyAccount,\n      removeAccount,\n      syncAccount,\n      syncAll,\n      requestUsername,\n      confirmUsername,\n    }),\n    [\n      accounts,\n      busyAccountId,\n      confirmUsername,\n      deriveAccount,\n      importPrivateKeyAccount,\n      isLoading,\n      removeAccount,\n      requestUsername,\n      syncAccount,\n      syncAll,\n    ],\n  );\n\n  return <NpcCtx.Provider value={value}>{children}</NpcCtx.Provider>;\n}\n\nexport function useNpcContext() {\n  const ctx = useContext(NpcCtx);\n  if (!ctx) {\n    throw new Error(\"useNpcContext must be used within NpcProvider\");\n  }\n  return ctx;\n}\n"
  },
  {
    "path": "src/context/Privacy.tsx",
    "content": "/* eslint-disable no-return-await */\n\nimport { l } from \"@log\";\nimport { store } from \"@store\";\nimport { STORE_KEYS } from \"@store/consts\";\nimport * as SplashScreen from \"expo-splash-screen\";\nimport { createContext, useContext, useEffect, useState } from \"react\";\n\nconst usePrivacy = () => {\n  const [hidden, setHidden] = useState({\n    balance: false,\n    txs: false,\n  });\n\n  const handleHiddenBalance = async () => {\n    setHidden({ balance: !hidden.balance, txs: hidden.txs });\n    if (hidden.balance) {\n      await store.delete(STORE_KEYS.hiddenBal);\n      return;\n    }\n    await store.set(STORE_KEYS.hiddenBal, \"1\");\n  };\n\n  const handleHiddenTxs = async () => {\n    setHidden({ balance: hidden.balance, txs: !hidden.txs });\n    if (hidden.txs) {\n      await store.delete(STORE_KEYS.hiddenTxs);\n      return;\n    }\n    await store.set(STORE_KEYS.hiddenTxs, \"1\");\n  };\n\n  const handleLogoPress = async () => {\n    // both hidden, show both\n    if (hidden.balance && hidden.txs) {\n      setHidden({ balance: false, txs: false });\n      await Promise.all([store.delete(STORE_KEYS.hiddenTxs), store.delete(STORE_KEYS.hiddenBal)]);\n      return;\n    }\n    setHidden({ balance: true, txs: true });\n    await Promise.all([store.set(STORE_KEYS.hiddenTxs, \"1\"), store.set(STORE_KEYS.hiddenBal, \"1\")]);\n  };\n\n  useEffect(() => {\n    void (async () => {\n      // init privacy preferences\n      const [isHiddenBal, isHiddenTxs] = await Promise.all([\n        store.get(STORE_KEYS.hiddenBal),\n        store.get(STORE_KEYS.hiddenTxs),\n      ]);\n      setHidden({\n        balance: !!isHiddenBal,\n        txs: !!isHiddenTxs,\n      });\n      await SplashScreen.hideAsync();\n    })();\n  }, []);\n\n  return {\n    hidden,\n    setHidden,\n    handleHiddenBalance,\n    handleHiddenTxs,\n    handleLogoPress,\n  };\n};\ntype usePrivacyType = ReturnType<typeof usePrivacy>;\nconst PrivacyContext = createContext<usePrivacyType>({\n  hidden: { balance: false, txs: false },\n  setHidden: () => l(\"\"),\n  handleHiddenBalance: async () => await l(\"\"),\n  handleHiddenTxs: async () => await l(\"\"),\n  handleLogoPress: async () => await l(\"\"),\n});\n\nexport const usePrivacyContext = () => useContext(PrivacyContext);\n\nexport const PrivacyProvider = ({ children }: { children: React.ReactNode }) => (\n  <PrivacyContext.Provider value={usePrivacy()}>{children}</PrivacyContext.Provider>\n);\n"
  },
  {
    "path": "src/context/Prompt.tsx",
    "content": "import { l } from \"@log\";\nimport type { IOpenPromptAutoCloseProps, IPromptState } from \"@model\";\nimport { createContext, useContext, useRef, useState } from \"react\";\n\nconst usePrompt = () => {\n  const timerId = useRef<ReturnType<typeof setTimeout>>();\n  const [prompt, setPrompt] = useState<IPromptState>({ open: false, msg: \"\" });\n\n  const startClosingTimer = (ms?: number) => {\n    timerId.current = setTimeout(() => {\n      closePrompt();\n      clearTimer();\n    }, ms ?? 2500);\n  };\n\n  const clearTimer = () => {\n    clearTimeout(timerId.current);\n    timerId.current = undefined;\n  };\n\n  const openPrompt = (msg: string, success?: boolean) => setPrompt({ open: true, success, msg });\n\n  const closePrompt = () => {\n    setPrompt({ open: false, msg: \"\" });\n    if (timerId.current) {\n      clearTimer();\n    }\n  };\n\n  const openPromptAutoClose = ({ msg, success, ms }: IOpenPromptAutoCloseProps) => {\n    openPrompt(msg, success);\n    if (timerId.current) {\n      clearTimer();\n    }\n    startClosingTimer(ms);\n  };\n\n  return {\n    prompt,\n    openPrompt,\n    closePrompt,\n    openPromptAutoClose,\n  };\n};\ntype usePromptType = ReturnType<typeof usePrompt>;\n/**\n * A state that indicates if a cashu token has been claimed from\n * clipboard after the app comes to the foreground.\n * It is used to re-render the total balance after claiming\n */\nconst PromptCtx = createContext<usePromptType>({\n  prompt: { open: false, msg: \"\" },\n  openPrompt: (msg: string) => l(msg),\n  closePrompt: () => l(\"\"),\n  openPromptAutoClose: ({ msg, success, ms }) => l(msg, success, ms),\n});\n\nexport const usePromptContext = () => useContext(PromptCtx);\n\nexport const PromptProvider = ({ children }: { children: React.ReactNode }) => (\n  <PromptCtx.Provider value={usePrompt()}>{children}</PromptCtx.Provider>\n);\n"
  },
  {
    "path": "src/context/Theme.tsx",
    "content": "import { getPreferences, setPreferences } from \"@src/storage/store/theme\";\nimport { l } from \"@log\";\nimport type { IPreferences } from \"@model\";\nimport { dark, HighlightKey, light, lightTheme } from \"@styles\";\nimport { createContext, useContext, useEffect, useMemo, useRef, useState } from \"react\";\nimport { useColorScheme } from \"react-native\";\n\ntype ThemeMode = \"dark\" | \"light\" | \"auto\";\n\nconst useTheme = () => {\n  // Single source of truth for preferences\n  const [pref, setPref] = useState<IPreferences>({\n    id: 1,\n    mode: \"auto\",\n    formatBalance: false,\n    theme: \"Default\",\n    hasPref: false,\n  });\n\n  // Track if we're initialized to avoid writing default values to DB\n  const isInitialized = useRef(false);\n\n  // Derive the actual theme to display based on mode and device theme\n  const deviceColorScheme = useColorScheme() || \"light\";\n  const activeTheme = pref.mode === \"auto\" ? deviceColorScheme : pref.mode;\n\n  // Memoize color object to avoid unnecessary re-renders\n  const color = useMemo(\n    () => (activeTheme === \"light\" ? light.custom : dark.custom),\n    [activeTheme],\n  );\n\n  // Initialize preferences from database\n  useEffect(() => {\n    try {\n      const prefsDB = getPreferences();\n      setPref(prefsDB);\n      isInitialized.current = true;\n    } catch (e) {\n      l(e);\n      // Keep default values, mark as initialized\n      isInitialized.current = true;\n    }\n  }, []);\n\n  // Update theme mode and persist to DB\n  const updateMode = (mode: ThemeMode) => {\n    if (!isInitialized.current) return;\n\n    const newPref = { ...pref, mode };\n    setPref(newPref);\n    void setPreferences(newPref);\n  };\n\n  // Update highlight color and persist to DB\n  const updateHighlight = (theme: HighlightKey) => {\n    if (!isInitialized.current) return;\n\n    const newPref = { ...pref, theme };\n    setPref(newPref);\n    void setPreferences(newPref);\n  };\n\n  return {\n    // Preferences\n    pref,\n    // Theme state (lowercase for consistency)\n    activeTheme,\n    mode: pref.mode,\n    updateMode,\n    // Colors\n    color,\n    // Highlight\n    highlight: pref.theme,\n    updateHighlight,\n  };\n};\n\ntype useThemeType = ReturnType<typeof useTheme>;\n\nconst ThemeContext = createContext<useThemeType>({\n  pref: {\n    id: 1,\n    mode: \"auto\",\n    formatBalance: false,\n    theme: \"Default\",\n    hasPref: false,\n  },\n  activeTheme: \"light\",\n  mode: \"auto\",\n  updateMode: () => l(\"\"),\n  color: lightTheme,\n  highlight: \"Default\",\n  updateHighlight: () => l(\"\"),\n});\n\nexport const useThemeContext = () => useContext(ThemeContext);\n\nexport const ThemeProvider = ({ children }: { children: React.ReactNode }) => (\n  <ThemeContext.Provider value={useTheme()}>{children}</ThemeContext.Provider>\n);\n"
  },
  {
    "path": "src/i18n.ts",
    "content": "import de from \"@assets/translations/de.json\";\nimport en from \"@assets/translations/en.json\";\nimport es from \"@assets/translations/es.json\";\nimport it from \"@assets/translations/it.json\";\nimport ru from \"@assets/translations/ru.json\";\nimport th from \"@assets/translations/th.json\";\nimport { l } from \"@log\";\nimport { isErr } from \"@util\";\nimport { getTranslationLangCode } from \"@util/localization\";\nimport i18n from \"i18next\";\nimport { initReactI18next } from \"react-i18next\";\n\n/**\n * Enumerates namespaces for usage in translations.\n */\nexport enum NS {\n  common = \"common\",\n  auth = \"auth\",\n  wallet = \"wallet\",\n  topNav = \"topNav\",\n  bottomNav = \"bottomNav\",\n  error = \"error\",\n  history = \"history\",\n  mints = \"mints\",\n  backup = \"backup\",\n  addrBook = \"addrBook\",\n}\n\nexport const defaultNS = NS.common;\nexport const resources = {\n  en,\n  de,\n  es,\n  it,\n  ru,\n  th,\n} as const;\n\n/**\n * Config and Init i18n library\n */\ni18n\n  .use(initReactI18next)\n  .init({\n    // compatibilityJSON: 'v3',\n    cleanCode: true,\n    fallbackLng: \"en\",\n    interpolation: {\n      escapeValue: false,\n    },\n    defaultNS,\n    ns: [\n      NS.common,\n      NS.auth,\n      NS.wallet,\n      NS.topNav,\n      NS.bottomNav,\n      NS.error,\n      NS.history,\n      NS.mints,\n      NS.backup,\n      NS.addrBook,\n    ],\n    lng: getTranslationLangCode(),\n    // debug,\n    // Consider external storing of translations and fetch needed language on demand\n    // https://www.i18next.com/how-to/backend-fallback\n    resources,\n  })\n  .catch((e) => {\n    l({\n      i18nextError: isErr(e) ? e.message : \"Error while initializing i18next\",\n    });\n  });\n\nexport default i18n;\n"
  },
  {
    "path": "src/i18next.d.ts",
    "content": "import { resources, defaultNS } from \"./i18n\";\n\ndeclare module \"i18next\" {\n  interface CustomTypeOptions {\n    defaultNS: typeof defaultNS;\n    resources: (typeof resources)[\"en\"];\n  }\n}\n"
  },
  {
    "path": "src/logger/AppLogger.ts",
    "content": "export type LogLevel = \"error\" | \"warn\" | \"info\" | \"debug\";\n\ntype LogBindings = Record<string, unknown>;\n\nexport interface LogTransport {\n  write(level: LogLevel, message: string, meta: unknown[], bindings?: LogBindings): void;\n}\n\nconst levelPriority: Record<LogLevel, number> = {\n  error: 0,\n  warn: 1,\n  info: 2,\n  debug: 3,\n};\n\nfunction isPlainObject(value: unknown): value is Record<string, unknown> {\n  return (\n    typeof value === \"object\" && value !== null && Object.getPrototypeOf(value) === Object.prototype\n  );\n}\n\nclass ConsoleTransport implements LogTransport {\n  write(level: LogLevel, message: string, meta: unknown[], bindings?: LogBindings) {\n    const ts = new Date().toISOString();\n    const prefixParts: string[] = [ts];\n    const name = typeof bindings?.name === \"string\" ? bindings?.name : undefined;\n    if (name) prefixParts.push(name);\n    const prefix = `[${prefixParts.join(\"] [\")}]`;\n\n    const payload = bindings && Object.keys(bindings).length > 0 ? [{ bindings }, ...meta] : meta;\n\n    switch (level) {\n      case \"error\":\n        // eslint-disable-next-line no-console\n        console.error(prefix, message, ...payload);\n        break;\n      case \"warn\":\n        // eslint-disable-next-line no-console\n        console.warn(prefix, message, ...payload);\n        break;\n      case \"info\":\n        // eslint-disable-next-line no-console\n        console.info(prefix, message, ...payload);\n        break;\n      case \"debug\":\n      default:\n        // eslint-disable-next-line no-console\n        console.log(prefix, message, ...payload);\n        break;\n    }\n  }\n}\n\nexport type AppLoggerOptions = {\n  level?: LogLevel;\n  name?: string;\n  bindings?: LogBindings;\n  transports?: LogTransport[];\n};\n\n/**\n * App-wide logger compatible with @cashu/coco-core and cashu-kym Logger interfaces.\n * - Level filtering\n * - Child loggers with inherited bindings\n * - Pluggable transports (console by default)\n */\nexport class AppLogger {\n  private readonly minLevel: LogLevel;\n  private readonly transports: LogTransport[];\n  private readonly bindings: LogBindings;\n\n  constructor(options?: AppLoggerOptions) {\n    this.minLevel = options?.level ?? \"info\";\n    this.bindings = {\n      ...(options?.bindings ?? {}),\n      ...(options?.name ? { name: options.name } : {}),\n    };\n    this.transports =\n      options?.transports && options.transports.length > 0\n        ? options.transports\n        : [new ConsoleTransport()];\n  }\n\n  private shouldLog(level: LogLevel): boolean {\n    return levelPriority[level] <= levelPriority[this.minLevel];\n  }\n\n  private write(level: LogLevel, message: string, meta: unknown[]) {\n    if (!this.shouldLog(level)) return;\n    for (const transport of this.transports) transport.write(level, message, meta, this.bindings);\n  }\n\n  // Overloads to satisfy both libraries\n  error(message: string, context?: Record<string, unknown>): void;\n  error(message: string, ...meta: unknown[]): void;\n  error(message: string, ...metaOrContext: unknown[]): void {\n    const meta =\n      metaOrContext.length === 1 && isPlainObject(metaOrContext[0])\n        ? [metaOrContext[0]]\n        : metaOrContext;\n    this.write(\"error\", message, meta);\n  }\n\n  warn(message: string, context?: Record<string, unknown>): void;\n  warn(message: string, ...meta: unknown[]): void;\n  warn(message: string, ...metaOrContext: unknown[]): void {\n    const meta =\n      metaOrContext.length === 1 && isPlainObject(metaOrContext[0])\n        ? [metaOrContext[0]]\n        : metaOrContext;\n    this.write(\"warn\", message, meta);\n  }\n\n  info(message: string, context?: Record<string, unknown>): void;\n  info(message: string, ...meta: unknown[]): void;\n  info(message: string, ...metaOrContext: unknown[]): void {\n    const meta =\n      metaOrContext.length === 1 && isPlainObject(metaOrContext[0])\n        ? [metaOrContext[0]]\n        : metaOrContext;\n    this.write(\"info\", message, meta);\n  }\n\n  debug(message: string, context?: Record<string, unknown>): void;\n  debug(message: string, ...meta: unknown[]): void;\n  debug(message: string, ...metaOrContext: unknown[]): void {\n    const meta =\n      metaOrContext.length === 1 && isPlainObject(metaOrContext[0])\n        ? [metaOrContext[0]]\n        : metaOrContext;\n    this.write(\"debug\", message, meta);\n  }\n\n  log(level: LogLevel, message: string, ...meta: unknown[]): void {\n    this.write(level, message, meta);\n  }\n\n  child(bindings: LogBindings): AppLogger {\n    return new AppLogger({\n      level: this.minLevel,\n      transports: this.transports,\n      bindings: { ...this.bindings, ...bindings },\n    });\n  }\n}\n"
  },
  {
    "path": "src/logger/index.ts",
    "content": "import { env, isTestMode } from \"@consts\";\nimport { AppLogger } from \"./AppLogger\";\n\n/* function _log(\n\twithTime: boolean,\n\twithCallerName: boolean,\n\twithPath: boolean,\n\tmsg?: unknown,\n\t...optionalParams: unknown[]\n) {\n\tlet prefix = ''\n\tif(withTime) { prefix += `[${new Date().toLocaleTimeString()}]` }\n\tif (withCallerName) { prefix += `[${callerInfo()?.name}]` }\n\tif (withPath) { prefix += `[${callerInfo()?.path}]` }\n\t// eslint-disable-next-line no-console\n\tconsole.log(prefix, msg, ...optionalParams)\n} */\nexport function l(msg?: unknown, ...optionalParams: unknown[]) {\n  if (\n    env?.NODE_ENV_SHORT === \"test\" ||\n    env?.NODE_ENV === \"test\" ||\n    env?.NODE_ENV_SHORT === \"prod\" ||\n    env?.NODE_ENV === \"prod\" ||\n    env?.NODE_ENV === \"production\" ||\n    env.NODE_ENV === \"production\" ||\n    isTestMode\n  ) {\n    return;\n  }\n  if (env.DEBUG === \"full\") {\n    return debug(msg, ...optionalParams);\n  }\n  let fnName = callerInfo()?.name;\n  if (!fnName || fnName === \"?anon_0_\") {\n    fnName = \"\";\n  }\n  if (fnName) {\n    fnName = `[${fnName}]`;\n  }\n  appLogger.debug(`${new Date().toLocaleTimeString()}${fnName}`, msg, ...optionalParams);\n}\n\nfunction debug(msg?: unknown, ...optionalParams: unknown[]) {\n  appLogger.debug(`[${callerInfo()?.name}]`, msg, ...optionalParams);\n}\n/* export function log(msg: unknown, ...args: unknown[]) {\n\t// eslint-disable-next-line no-console\n\tconsole.log(`[${new Date().toLocaleTimeString()}]`, msg, ...args)\n} */\n\nexport function warn(msg: unknown, ...args: unknown[]) {\n  appLogger.warn(`${new Date().toISOString()}`, msg, ...args);\n}\nexport function err(msg: unknown, ...args: unknown[]) {\n  appLogger.error(`${new Date().toISOString()}`, msg, ...args);\n}\nexport function callerInfo(skipOf = 3) {\n  skipOf = skipOf || 3;\n  let eStack;\n  try {\n    eStack = new Error().stack;\n  } catch {\n    l(\"[callerInfo] bad error\", undefined);\n  }\n  // const arr = eStack?.split('at ').map(x => x?.split(' (')[0]?.split(' ('))\n  // log( arr?.slice(1,5),eStack)\n  // console.log(eStack?.split('at '), '\\n', eStack?.split('at ')[skipOf])\n  let tmpv = eStack?.split(\"at \")[skipOf]?.split(\")\\n\")[0]?.split(\" (\");\n  if (!tmpv || !tmpv[1] || !tmpv[0]) {\n    tmpv = eStack?.split(\"at \")[skipOf + 1]?.split(\")\\n\")[0]?.split(\" (\");\n  }\n  /* const error = new Error('')\n\t// console.log(error.stack, '\\n', '\\n')\n\tif (error.stack) {\n\t\tconst cla = error.stack.split('\\n')\n\t\tlet idx = 1\n\t\tconsole.log(idx, '----------------', cla[idx])\n\t\twhile (idx < cla.length && cla[idx].includes('callerInfo')) { idx++ }\n\t\tif (idx < cla.length) {\n\t\t\ta = cla[idx].slice(cla[idx].indexOf('at ') + 3, cla[idx].length)\n\t\t}\n\t}\n\tif (!tmpv || !tmpv[1] || tmpv[1] === undefined) { console.log(eStack?.stack) }*/\n  if (tmpv) {\n    return {\n      name: tmpv[0].replace(\"Object.exports.\", \"\").replace(\"Object.\", \"\"),\n      path: tmpv[1],\n    };\n  }\n  return null;\n}\n\n// Application-wide structured logger instance compatible with @cashu/coco-core and cashu-kym\nexport const appLogger = new AppLogger({\n  level: env.DEBUG === \"full\" || env.isReactNativeDevMode ? \"debug\" : \"info\",\n  name: \"eNuts\",\n});\n\nexport type { AppLogger } from \"./AppLogger\";\n"
  },
  {
    "path": "src/model/env.ts",
    "content": "export interface IEnv {\n  NODE_ENV: string;\n  APP_VARIANT: string;\n  DEBUG: string;\n  NODE_ENV_SHORT: string;\n  SENTRY_DSN: string;\n}\n"
  },
  {
    "path": "src/model/i18n.ts",
    "content": "const _tlLangNames = [\n  \"english\",\n  \"german\",\n  \"french\",\n  \"swahili\",\n  \"spanish\",\n  \"hungarian\",\n  \"italian\",\n  \"russian\",\n  \"thai\",\n  \"chinese traditional\",\n  \"chinese simplified\",\n] as const;\nexport type TTlLangNames = (typeof _tlLangNames)[number];\n\nconst _translationLangCodes = [\n  \"de\",\n  \"en\",\n  \"fr\",\n  \"sw\",\n  \"es\",\n  \"hu\",\n  \"it\",\n  \"ru\",\n  \"th\",\n  \"zh-Hant-TW\",\n  \"zh-Hans-CN\",\n] as const;\nexport type TranslationLangCodes = (typeof _translationLangCodes)[number];\nexport const translationLangCodes: readonly string[] = [..._translationLangCodes];\n\nexport interface ILangsOpt {\n  name: TTlLangNames;\n  code: TranslationLangCodes;\n  flag: string;\n}\n"
  },
  {
    "path": "src/model/index.ts",
    "content": "import type { Proof, Token } from \"@cashu/cashu-ts\";\nimport type { HighlightKey } from \"@styles\";\nimport type { ExpoConfig } from \"expo/config\";\n\nexport interface IExpoConfig extends ExpoConfig {\n  extra?: {\n    DEBUG?: string; // | 'full'\n    NODE_ENV?: string; // | 'development' | 'production' | 'test' | 'preview'\n    NODE_ENV_SHORT?: string; // | 'prod' | 'dev' | 'test' | 'preview'\n    APP_VARIANT?: string; // | 'prod' | 'dev' | 'test' | 'preview'\n    SENTRY_DSN?: string;\n  };\n}\nexport interface IInitialProps {\n  expo?: IExpoConfig;\n  exp: {\n    notification?: any;\n    manifestString?: string;\n    [key: string]: any;\n  };\n  shell?: boolean;\n  shellManifestUrl?: string;\n  [key: string]: any;\n}\nexport interface ILnUrl {\n  tag: string;\n  minSendable: number;\n  maxSendable: number;\n  callback: string;\n  pr: string;\n}\n\n// TODO This interface is missing some properties?\nexport interface ILnUrlPayRequest {\n  tag: string;\n  cb: string;\n  minSendable: number;\n  maxSendable: number;\n  metadata: string;\n}\nexport interface IMint {\n  id: string;\n  mintUrl: string;\n  active?: boolean;\n  fee?: number;\n}\n\nexport interface IMintUrl {\n  mintUrl: string;\n  customName?: string;\n}\n\nexport interface IMintWithBalance {\n  mintUrl: string;\n  amount: number;\n}\n\nexport interface IMintBalWithName extends IMintWithBalance {\n  customName: string;\n}\n\nexport interface ITokenInfo {\n  mints: string[];\n  value: number;\n  decoded: Token;\n}\n\nexport interface IPreferencesResp {\n  id: 1;\n  formatBalance: string;\n  mode: string;\n  theme: HighlightKey;\n  hasPref: string;\n}\n\nexport interface IPreferences {\n  id: 1;\n  formatBalance: boolean;\n  mode: \"dark\" | \"light\" | \"auto\";\n  theme: HighlightKey;\n  hasPref: boolean;\n}\n\nexport interface IContactResp {\n  id?: number;\n  name: string;\n  ln: string;\n  isOwner: string;\n}\n\nexport interface IProofSelection extends Proof {\n  selected: boolean;\n}\n\nexport enum txType {\n  SEND_RECEIVE = 1,\n  LIGHTNING = 2,\n  SWAP = 3,\n  RESTORE = 4,\n}\n\nexport type TTXType = txType.SEND_RECEIVE | txType.LIGHTNING | txType.SWAP | txType.RESTORE;\n\n/**\n * type: 1 | 2 | 3\n * 1 = send/receive Ecash\n * 2 = LN invoice\n * 3 = multimint swap\n * 4 = restored from backup\n */\nexport interface IHistoryEntry {\n  amount: number;\n  type: TTXType;\n  timestamp: number;\n  value: string; // Lightning invoice or encoded Cashu token\n  mints: string[]; // mints involved\n  sender?: string; // sender (nostr username)\n  recipient?: string; // recipient (nostr username)\n  preImage?: string;\n  fee?: number;\n  isSpent?: boolean; // is token spendable\n  isPending?: boolean; // is LN invoice pending\n  isExpired?: boolean; // is LN invoice expired\n}\n\nexport interface IInvoice {\n  pr: string;\n  hash: string;\n  amount: number;\n  time: number;\n  mintUrl: string;\n}\n// export interface IOpenDBParams {\n// \tname: string,\n// \tversion?: string,\n// \tdescription?: string,\n// \tsize?: number,\n// \tcallback?: ((db: WebSQLDatabase) => void)\n// }\n// export interface IOpenDB {\n// \t(\n// \t\tname: string,\n// \t\tversion?: string,\n// \t\tdescription?: string,\n// \t\tsize?: number,\n// \t\tcallback?: ((db: WebSQLDatabase) => void)\n// \t): WebSQLDatabase\n// }\nexport type QueryArgs = (number | string | null)[];\n// export interface ITx<T = unknown> {\n// \tsql: string,\n// \targs?: QueryArgs,\n// \tcb?: SQLStmtCb<T>,\n// \terrorCb?: SQLStmtErrCb\n// }\nexport interface IKeyValuePair<T> {\n  key: string;\n  value: T;\n}\n\nexport interface IContact {\n  id?: number;\n  name: string;\n  ln: string;\n  isOwner: boolean;\n}\nexport interface IPromptState {\n  open: boolean;\n  success?: boolean;\n  msg: string;\n}\n\nexport interface IOpenPromptAutoCloseProps {\n  msg: string;\n  success?: boolean;\n  ms?: number;\n}\n\nexport type TPayLnInvoiceReturnType = Promise<{\n  result?: { success: boolean; [key: string]: any };\n  fee?: number;\n  realFee?: number;\n  error?: unknown;\n}>;\n\nexport type TRequestTokenReturnType = Promise<{\n  success: boolean;\n  invoice: IInvoice | null | undefined;\n}>;\n\nexport interface ISecret {\n  secret: string;\n}\n\nexport interface Query {\n  sql: string;\n  args: (number | string | null)[];\n}\n\n// Currency and exchange rate types\nexport interface IExchangeRate {\n  \"15m\": number;\n  last: number;\n  buy: number;\n  sell: number;\n  symbol: string;\n}\n\nexport type IExchangeRates = Record<string, IExchangeRate>;\n\nexport type TCurrencyCode = string; // e.g., \"USD\", \"EUR\", \"GBP\", etc.\n\nexport interface IFormattedAmount {\n  formatted: string;\n  symbol: string;\n}\n"
  },
  {
    "path": "src/model/nav.ts",
    "content": "import type { Manager } from \"@cashu/coco-core\";\nimport { Token } from \"@cashu/cashu-ts\";\nimport type { EventArg, NavigatorScreenParams } from \"@react-navigation/core\";\nimport type { CompositeScreenProps } from \"@react-navigation/native\";\nimport type { NativeStackScreenProps } from \"@react-navigation/native-stack\";\n\nimport type {\n  IHistoryEntry,\n  ILnUrlPayRequest,\n  IMintUrl,\n  IMintWithBalance,\n  IProofSelection,\n  ITokenInfo,\n} from \".\";\nimport type { HistoryStackParamList, MintStackParamList } from \"@src/nav/navTypes\";\nimport type { RestoreStackParamList } from \"@src/nav/navTypes\";\nimport type { SettingsStackParamList } from \"@src/nav/navTypes\";\n\ninterface ILnurlNavData {\n  userInput: string;\n  url?: string;\n  data?: ILnUrlPayRequest;\n}\n\ntype TMintInvoiceOperation = Awaited<ReturnType<Manager[\"ops\"][\"mint\"][\"prepare\"]>>;\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Success Screen Config Types (Tagged Union)\n// ─────────────────────────────────────────────────────────────────────────────\n\ninterface BaseSuccessConfig {\n  mint?: string;\n  memo?: string;\n}\n\n/** User paid a Lightning invoice */\nexport interface MeltSuccessConfig extends BaseSuccessConfig {\n  type: \"melt\";\n  amount: number;\n  fee: number;\n  change?: number;\n}\n\n/** Automatic mint-to-mint swap completed */\nexport interface AutoSwapSuccessConfig extends BaseSuccessConfig {\n  type: \"autoSwap\";\n  amount: number;\n  fee: number;\n  change?: number;\n}\n\n/** User claimed an ecash token */\ninterface ClaimSuccessConfig extends BaseSuccessConfig {\n  type: \"claim\";\n  amount: number;\n}\n\n/** User received funds via Lightning invoice */\ninterface ReceiveSuccessConfig extends BaseSuccessConfig {\n  type: \"receive\";\n  amount: number;\n}\n\n/** Nostr zap payment completed */\ninterface ZapSuccessConfig extends BaseSuccessConfig {\n  type: \"zap\";\n  amount: number;\n  fee?: number;\n}\n\n/** Wallet restoration completed */\ninterface RestoreSuccessConfig extends BaseSuccessConfig {\n  type: \"restore\";\n  amount: number;\n}\n\n/** User sent ecash to someone */\ninterface SendSuccessConfig extends BaseSuccessConfig {\n  type: \"send\";\n  amount: number;\n}\n\nexport type SuccessConfig =\n  | MeltSuccessConfig\n  | AutoSwapSuccessConfig\n  | ClaimSuccessConfig\n  | ReceiveSuccessConfig\n  | ZapSuccessConfig\n  | RestoreSuccessConfig\n  | SendSuccessConfig;\n/**\n * Stack Navigator\n */\n// eslint-disable-next-line @typescript-eslint/consistent-type-definitions\nexport type RootStackParamList = {\n  onboarding: undefined;\n  dashboard: undefined;\n  Settings: NavigatorScreenParams<SettingsStackParamList>;\n  disclaimer: undefined;\n  Restore: NavigatorScreenParams<RestoreStackParamList>;\n  selectMint: {\n    mints: IMintUrl[];\n    mintsWithBal: IMintWithBalance[];\n    isMelt?: boolean;\n    isSendEcash?: boolean;\n    balance?: number;\n    allMintsEmpty?: boolean;\n    invoice?: string;\n    invoiceAmount?: number;\n    estFee?: number;\n    lnurl?: ILnurlNavData;\n    scanned?: boolean;\n  };\n  selectTarget: {\n    mint: IMintUrl;\n    balance: number;\n    isMelt?: boolean;\n    isSendEcash?: boolean;\n    remainingMints?: IMintUrl[];\n  };\n  SendSelectAmount: undefined;\n  MintSelectAmount: undefined;\n  MeltInput: { invoice?: string };\n  History: NavigatorScreenParams<HistoryStackParamList>;\n  selectAmount: {\n    isMelt?: boolean;\n    isSendEcash?: boolean;\n    isSwap?: boolean;\n    lnurl?: ILnurlNavData;\n    targetMint?: IMintUrl;\n    scanned?: boolean;\n  };\n  coinSelection: {\n    mint: IMintUrl;\n    balance: number;\n    amount: number;\n    estFee: number;\n    isMelt?: boolean;\n    isSendEcash?: boolean;\n    isSwap?: boolean;\n    isZap?: boolean;\n    targetMint?: IMintUrl;\n    recipient?: string;\n    memo?: string;\n    scanned?: boolean;\n    aiPathfindingEnabled?: boolean;\n  };\n  QRScanner: undefined;\n  processing: {\n    mint: IMintUrl;\n    tokenInfo?: ITokenInfo;\n    amount: number;\n    estFee?: number;\n    isMelt?: boolean;\n    isSendEcash?: boolean;\n    isSwap?: boolean;\n    isAutoSwap?: boolean;\n    isZap?: boolean;\n    payZap?: boolean;\n    targetMint?: IMintUrl;\n    proofs?: IProofSelection[];\n    recipient?: string;\n    memo?: string;\n  };\n  \"mint confirm\": {\n    mintUrl: string;\n  };\n  \"scan success\": {\n    mintUrl?: string;\n    edited?: boolean;\n  };\n  processingError: {\n    mint?: IMintUrl;\n    amount?: number;\n    scan?: boolean;\n    comingFromOnboarding?: boolean;\n    errorMsg: string;\n  };\n  mintInvoice: {\n    mintUrl: string;\n    operation: TMintInvoiceOperation;\n  };\n  encodedToken: {\n    token: Token;\n  };\n  success: {\n    amount?: number;\n    fee?: number;\n    mint?: string;\n    memo?: string;\n    isClaim?: boolean;\n    isMelt?: boolean;\n    isAutoSwap?: boolean;\n    isZap?: boolean;\n    isScanned?: boolean;\n    isRestored?: boolean;\n    change?: number;\n    comingFromOnboarding?: boolean;\n  };\n  successScreen: SuccessConfig;\n  Mint: NavigatorScreenParams<MintStackParamList>;\n  mintmanagement: {\n    mint: IMintUrl;\n    amount: number;\n    remainingMints: IMintUrl[];\n  };\n  \"mint info\": {\n    mintUrl: string;\n  };\n  \"mint proofs\": {\n    mintUrl: string;\n  };\n};\n\nexport type TRouteString = \"dashboard\" | \"Settings\";\nexport type TOnboardingPageProps = NativeStackScreenProps<\n  RootStackParamList,\n  \"onboarding\",\n  \"MyStack\"\n>;\nexport type TSelectMintPageProps = NativeStackScreenProps<\n  RootStackParamList,\n  \"selectMint\",\n  \"MyStack\"\n>;\nexport type TSelectTargetPageProps = NativeStackScreenProps<\n  RootStackParamList,\n  \"selectTarget\",\n  \"MyStack\"\n>;\nexport type SendSelectAmountProps = NativeStackScreenProps<\n  RootStackParamList,\n  \"selectAmount\",\n  \"MyStack\"\n>;\nexport type TSelectAmountPageProps = NativeStackScreenProps<\n  RootStackParamList,\n  \"selectAmount\",\n  \"MyStack\"\n>;\nexport type TCoinSelectionPageProps = NativeStackScreenProps<\n  RootStackParamList,\n  \"coinSelection\",\n  \"MyStack\"\n>;\nexport type TProcessingPageProps = NativeStackScreenProps<\n  RootStackParamList,\n  \"processing\",\n  \"MyStack\"\n>;\nexport type TMintConfirmPageProps = NativeStackScreenProps<\n  RootStackParamList,\n  \"mint confirm\",\n  \"MyStack\"\n>;\nexport type TScanSuccessPageProps = NativeStackScreenProps<\n  RootStackParamList,\n  \"scan success\",\n  \"MyStack\"\n>;\nexport type TProcessingErrorPageProps = NativeStackScreenProps<\n  RootStackParamList,\n  \"processingError\",\n  \"MyStack\"\n>;\nexport type TMintInvoicePageProps = NativeStackScreenProps<\n  RootStackParamList,\n  \"mintInvoice\",\n  \"MyStack\"\n>;\nexport type TDashboardPageProps = NativeStackScreenProps<\n  RootStackParamList,\n  \"dashboard\",\n  \"MyStack\"\n>;\nexport type TDisclaimerPageProps = NativeStackScreenProps<\n  RootStackParamList,\n  \"disclaimer\",\n  \"MyStack\"\n>;\nexport type TEncodedTokenPageProps = NativeStackScreenProps<\n  RootStackParamList,\n  \"encodedToken\",\n  \"MyStack\"\n>;\nexport type TSuccessPageProps = NativeStackScreenProps<RootStackParamList, \"success\", \"MyStack\">;\nexport type TSuccessScreenProps = NativeStackScreenProps<\n  RootStackParamList,\n  \"successScreen\",\n  \"MyStack\"\n>;\nexport type TMintManagementPageProps = NativeStackScreenProps<\n  RootStackParamList,\n  \"mintmanagement\",\n  \"MyStack\"\n>;\nexport type TMintInfoPageProps = NativeStackScreenProps<RootStackParamList, \"mint info\", \"MyStack\">;\nexport type TMintProofsPageProps = NativeStackScreenProps<\n  RootStackParamList,\n  \"mint proofs\",\n  \"MyStack\"\n>;\nexport type TSettingsPageProps = CompositeScreenProps<\n  NativeStackScreenProps<SettingsStackParamList, \"SettingsMain\">,\n  NativeStackScreenProps<RootStackParamList>\n>;\nexport type TDisplaySettingsPageProps = CompositeScreenProps<\n  NativeStackScreenProps<SettingsStackParamList, \"Display settings\">,\n  NativeStackScreenProps<RootStackParamList>\n>;\nexport type TLanguageSettingsPageProps = CompositeScreenProps<\n  NativeStackScreenProps<SettingsStackParamList, \"Language settings\">,\n  NativeStackScreenProps<RootStackParamList>\n>;\nexport type TAdvancedSettingsPageProps = CompositeScreenProps<\n  NativeStackScreenProps<SettingsStackParamList, \"Advanced settings\">,\n  NativeStackScreenProps<RootStackParamList>\n>;\nexport type TCurrencySettingsPageProps = CompositeScreenProps<\n  NativeStackScreenProps<SettingsStackParamList, \"Currency settings\">,\n  NativeStackScreenProps<RootStackParamList>\n>;\nexport type TViewMnemonicPageProps = CompositeScreenProps<\n  NativeStackScreenProps<SettingsStackParamList, \"View mnemonic\">,\n  NativeStackScreenProps<RootStackParamList>\n>;\nexport type THistoryPageProps = CompositeScreenProps<\n  NativeStackScreenProps<HistoryStackParamList, \"HistoryMain\">,\n  NativeStackScreenProps<RootStackParamList>\n>;\nexport type THistoryEntryPageProps = CompositeScreenProps<\n  NativeStackScreenProps<HistoryStackParamList, \"HistoryEntryDetails\">,\n  NativeStackScreenProps<RootStackParamList>\n>;\ntype RestoreStackScreenProps<T extends keyof RestoreStackParamList> = NativeStackScreenProps<\n  RestoreStackParamList,\n  T\n>;\n\nexport type ISeedPageProps = CompositeScreenProps<\n  RestoreStackScreenProps<\"Seed\">,\n  NativeStackScreenProps<RootStackParamList>\n>;\nexport type IRecoverPageProps = CompositeScreenProps<\n  RestoreStackScreenProps<\"Recover\">,\n  NativeStackScreenProps<RootStackParamList>\n>;\nexport type IMnemonicPageProps = CompositeScreenProps<\n  RestoreStackScreenProps<\"Mnemonic\">,\n  NativeStackScreenProps<RootStackParamList>\n>;\nexport type IRecoveringPageProps = CompositeScreenProps<\n  RestoreStackScreenProps<\"Recovering\">,\n  NativeStackScreenProps<RootStackParamList>\n>;\nexport type TProofsDebugPageProps = THistoryPageProps;\nexport interface INavigatorProps {\n  shouldOnboard?: boolean;\n  hasSeed?: boolean;\n}\nexport type TBeforeRemoveEvent = EventArg<\n  \"beforeRemove\",\n  true,\n  {\n    action: Readonly<{\n      type: string;\n      payload?: object | undefined;\n      source?: string | undefined;\n      target?: string | undefined;\n    }>;\n  }\n>;\n"
  },
  {
    "path": "src/nav/HistoryNavigator.tsx",
    "content": "import { createNativeStackNavigator } from \"@react-navigation/native-stack\";\nimport HistoryPage from \"@screens/History\";\nimport HistoryEntryDetails from \"@screens/History/Details\";\nimport { useThemeContext } from \"@src/context/Theme\";\nimport type { HistoryStackParamList } from \"@src/nav/navTypes\";\n\nconst HistoryStack = createNativeStackNavigator<HistoryStackParamList>();\n\nconst animationDuration = 250;\n\nexport default function HistoryNavigator() {\n  const { color } = useThemeContext();\n\n  return (\n    <HistoryStack.Navigator\n      screenOptions={{\n        headerShown: false,\n        animation: \"fade\",\n        animationDuration,\n        navigationBarColor: color.BACKGROUND,\n      }}\n    >\n      <HistoryStack.Screen name=\"HistoryMain\" component={HistoryPage} />\n      <HistoryStack.Screen name=\"HistoryEntryDetails\" component={HistoryEntryDetails} />\n    </HistoryStack.Navigator>\n  );\n}\n"
  },
  {
    "path": "src/nav/MintNavigator.tsx",
    "content": "import { createNativeStackNavigator } from \"@react-navigation/native-stack\";\nimport { MintHomeScreen, AddMintScreen, MintSettingsScreen } from \"@screens/Mints\";\nimport { MintStackParamList } from \"@src/nav/navTypes\";\n\nconst MintStack = createNativeStackNavigator<MintStackParamList>();\n\nfunction MintNavigator() {\n  return (\n    <MintStack.Navigator screenOptions={{ headerShown: false, animation: \"fade\" }}>\n      <MintStack.Screen name=\"MintHome\" component={MintHomeScreen} />\n      <MintStack.Screen name=\"MintAdd\" component={AddMintScreen} />\n      <MintStack.Screen name=\"MintSettings\" component={MintSettingsScreen} />\n    </MintStack.Navigator>\n  );\n}\n\nexport default MintNavigator;\n"
  },
  {
    "path": "src/nav/RestoreNavigator.tsx",
    "content": "import { createNativeStackNavigator } from \"@react-navigation/native-stack\";\nimport SelectRecoveryMintScreen from \"@screens/Restore/SelectRecoveryMint\";\nimport RecoverScreen from \"@screens/Restore/Recover\";\nimport RecoveringScreen from \"@screens/Restore/Recovering\";\nimport { RestoreStackParamList } from \"@src/nav/navTypes\";\n\nconst RestoreStack = createNativeStackNavigator<RestoreStackParamList>();\n\nfunction RestoreNavigator() {\n  return (\n    <RestoreStack.Navigator screenOptions={{ headerShown: false, animation: \"fade\" }}>\n      <RestoreStack.Screen name=\"RecoverMints\" component={SelectRecoveryMintScreen} />\n      <RestoreStack.Screen name=\"Recover\" component={RecoverScreen} />\n      <RestoreStack.Screen name=\"Recovering\" component={RecoveringScreen} />\n    </RestoreStack.Navigator>\n  );\n}\n\nexport default RestoreNavigator;\n"
  },
  {
    "path": "src/nav/SettingsNavigator.tsx",
    "content": "import { createNativeStackNavigator } from \"@react-navigation/native-stack\";\nimport Settings from \"@screens/Settings\";\nimport DisplaySettings from \"@screens/Settings/Display\";\nimport LanguageSettings from \"@screens/Settings/Language\";\nimport CurrencySettings from \"@screens/Settings/Currency\";\nimport NfcSettings from \"@screens/Settings/NfcSettings\";\nimport NpcSettings from \"@screens/Settings/NpcSettings\";\nimport ViewMnemonic from \"@screens/Settings/ViewMnemonic\";\nimport { useThemeContext } from \"@src/context/Theme\";\nimport { SettingsStackParamList } from \"./navTypes\";\n\nconst SettingsStack = createNativeStackNavigator<SettingsStackParamList>();\n\nconst animationDuration = 250;\n\nexport default function SettingsNavigator() {\n  const { color } = useThemeContext();\n\n  return (\n    <SettingsStack.Navigator\n      screenOptions={{\n        headerShown: false,\n        animation: \"fade\",\n        animationDuration,\n        navigationBarColor: color.BACKGROUND,\n      }}\n    >\n      <SettingsStack.Screen name=\"SettingsMain\" component={Settings} />\n      <SettingsStack.Screen name=\"Display settings\" component={DisplaySettings} />\n      <SettingsStack.Screen name=\"Language settings\" component={LanguageSettings} />\n      <SettingsStack.Screen name=\"Currency settings\" component={CurrencySettings} />\n      <SettingsStack.Screen name=\"NFC settings\" component={NfcSettings} />\n      <SettingsStack.Screen name=\"NPC settings\" component={NpcSettings} />\n      <SettingsStack.Screen name=\"View mnemonic\" component={ViewMnemonic} />\n    </SettingsStack.Navigator>\n  );\n}\n"
  },
  {
    "path": "src/nav/navTypes.ts",
    "content": "import { HistoryEntry } from \"@cashu/coco-core\";\nimport { CompositeScreenProps, NavigatorScreenParams } from \"@react-navigation/native\";\nimport { NativeStackScreenProps } from \"@react-navigation/native-stack\";\nimport { RootStackParamList } from \"@src/model/nav\";\n\n// Settings Stack\n\nexport type SettingsStackParamList = {\n  SettingsMain: undefined;\n  \"Display settings\": undefined;\n  \"Language settings\": undefined;\n  \"Currency settings\": undefined;\n  \"NFC settings\": undefined;\n  \"NPC settings\": undefined;\n  \"Advanced settings\": undefined;\n  \"View mnemonic\": undefined;\n};\n\nexport type TNfcSettingsPageProps = NativeStackScreenProps<SettingsStackParamList, \"NFC settings\">;\nexport type TNpcSettingsPageProps = NativeStackScreenProps<SettingsStackParamList, \"NPC settings\">;\n\ntype SettingsStackScreenProps<T extends keyof SettingsStackParamList> = NativeStackScreenProps<\n  SettingsStackParamList,\n  T\n>;\n\n// Mint Screens\n\nexport type MintStackParamList = {\n  MintHome: undefined;\n  MintAdd: undefined;\n  MintSettings: { mintUrl: string };\n};\n\ntype MintStackScreenProps<T extends keyof MintStackParamList> = NativeStackScreenProps<\n  MintStackParamList,\n  T\n>;\n\nexport type HistoryStackParamList = {\n  HistoryMain: undefined;\n  HistoryEntryDetails: {\n    entry: HistoryEntry;\n  };\n};\n\n// Restore Screens\n\nexport type RestoreStackParamList = {\n  Seed:\n    | {\n        comingFromOnboarding?: boolean;\n        sawSeedUpdate?: boolean;\n        hasSeed?: boolean;\n      }\n    | undefined;\n  RecoverMints: { comingFromOnboarding?: boolean } | undefined;\n  Recover: undefined;\n  Mnemonic: { comingFromOnboarding?: boolean };\n  Recovering: { bip39seed: Uint8Array; mintUrls: string[] };\n};\n\ntype RestoreStackScreenProps<T extends keyof RestoreStackParamList> = NativeStackScreenProps<\n  RestoreStackParamList,\n  T\n>;\n\nexport type RecoverScreenProps = CompositeScreenProps<\n  RestoreStackScreenProps<\"Recover\">,\n  NativeStackScreenProps<RootStackParamList>\n>;\n\nexport type RecoverMintsScreenProps = CompositeScreenProps<\n  RestoreStackScreenProps<\"RecoverMints\">,\n  NativeStackScreenProps<RootStackParamList>\n>;\n\nexport type SendSelectAmountProps = NativeStackScreenProps<RootStackParamList, \"SendSelectAmount\">;\n\nexport type MintSelectAmountProps = NativeStackScreenProps<RootStackParamList, \"MintSelectAmount\">;\n\nexport type MeltInputProps = NativeStackScreenProps<RootStackParamList, \"MeltInput\">;\n\nexport type RestoreScreenProps = NativeStackScreenProps<RootStackParamList, \"Restore\">;\n\nexport type QRScannerScreenProps = NativeStackScreenProps<RootStackParamList, \"QRScanner\">;\n"
  },
  {
    "path": "src/screens/Dashboard.tsx",
    "content": "import DashboardTopBar from \"@comps/DashboardTopBar\";\nimport useLoading from \"@comps/hooks/Loading\";\nimport { useCashuClaimFlow } from \"@comps/hooks/useCashuClaimFlow\";\nimport {\n  CopyIcon,\n  NfcIcon,\n  PlusIcon,\n  ReceiveIcon,\n  ScanQRIcon,\n  SendIcon,\n  SendMsgIcon,\n  SwapCurrencyIcon,\n  ZapIcon,\n} from \"@comps/Icons\";\nimport Loading from \"@comps/Loading\";\nimport NfcPaymentModal, { type NfcPaymentModalRef } from \"@comps/modal/NfcPaymentModal\";\nimport Separator from \"@comps/Separator\";\nimport Txt from \"@comps/Txt\";\nimport type { HistoryEntry } from \"@cashu/coco-core\";\nimport { usePaginatedHistory } from \"@cashu/coco-react\";\nimport { TrueSheet } from \"@lodev09/react-native-true-sheet\";\nimport type { TBeforeRemoveEvent, TDashboardPageProps } from \"@model/nav\";\nimport { preventBack } from \"@nav/utils\";\nimport { useBalanceContext } from \"@src/context/Balance\";\nimport { useCurrencyContext } from \"@src/context/Currency\";\nimport { useKnownMints } from \"@src/context/KnownMints\";\nimport { usePrivacyContext } from \"@src/context/Privacy\";\nimport { usePromptContext } from \"@src/context/Prompt\";\nimport { useThemeContext } from \"@src/context/Theme\";\nimport { NS } from \"@src/i18n\";\nimport { globals, highlight as hi, mainColors } from \"@styles\";\nimport { getStrFromClipboard } from \"@util\";\nimport { useEffect, useRef, type ReactNode } from \"react\";\nimport { useTranslation } from \"react-i18next\";\nimport { ScrollView, Text, TouchableOpacity, View } from \"react-native\";\nimport { SafeAreaView } from \"react-native-safe-area-context\";\nimport { s, ScaledSheet } from \"react-native-size-matters\";\n\nimport { LatestHistoryMeltEntry } from \"./History/components/LatestHistoryMeltEntry\";\nimport { LatestHistoryMintEntry } from \"./History/components/LatestHistoryMintEntry\";\nimport { LatestHistoryReceiveEntry } from \"./History/components/LatestHistoryReceiveEntry\";\nimport { LatestHistorySendEntry } from \"./History/components/LatestHistorySendEntry\";\nimport DashboardActionSheet, { DashboardActionSheetOption } from \"./DashboardActionSheet\";\n\nexport default function Dashboard({ navigation }: TDashboardPageProps) {\n  const { t } = useTranslation([NS.common, NS.wallet]);\n  const { activeTheme, color, highlight } = useThemeContext();\n  const accentColor = hi[highlight];\n  const isDarkTheme = activeTheme === \"dark\";\n  const balanceTextColor = accentColor;\n  const balanceMetaColor = color.TEXT_SECONDARY;\n  const actionTextColor = color.TEXT;\n  const actionIconColor = accentColor;\n  const actionIconBackground = withAlpha(accentColor, isDarkTheme ? 0.14 : 0.12);\n  const actionIconBorderColor = withAlpha(accentColor, isDarkTheme ? 0.24 : 0.18);\n  const { loading, startLoading, stopLoading } = useLoading();\n  const { openPromptAutoClose } = usePromptContext();\n  const { knownMints } = useKnownMints();\n  const { hidden } = usePrivacyContext();\n  const { balances } = useBalanceContext();\n  const { formatAmount, formatBalance, setFormatBalance } = useCurrencyContext();\n  const { history: latestHistory, hasMore } = usePaginatedHistory(10);\n  const sendOptionsRef = useRef<TrueSheet>(null);\n  const receiveOptionsRef = useRef<TrueSheet>(null);\n  const nfcModalRef = useRef<NfcPaymentModalRef>(null);\n  const { claimFromTokenString, isReceiving } = useCashuClaimFlow();\n  const balanceAmount = formatAmount(balances.total.total);\n\n  const toggleBalanceFormat = () => {\n    void setFormatBalance(!formatBalance);\n  };\n\n  const handleClaimBtnPress = async () => {\n    if (loading) {\n      return;\n    }\n    startLoading();\n    const clipboard = await getStrFromClipboard();\n    try {\n      if (!clipboard) {\n        throw new Error(\"Clipboard is empty\");\n      }\n      await claimFromTokenString(clipboard);\n    } catch (e) {\n      openPromptAutoClose({ msg: t(\"clipboardInvalid\") });\n      stopLoading();\n      return;\n    }\n    stopLoading();\n  };\n\n  const handleNfcOptionPress = () => {\n    void sendOptionsRef.current?.dismiss();\n    setTimeout(() => {\n      nfcModalRef.current?.open();\n    }, 200);\n  };\n\n  useEffect(() => {\n    const backHandler = (e: TBeforeRemoveEvent) => preventBack(e, navigation.dispatch);\n    navigation.addListener(\"beforeRemove\", backHandler);\n    return () => navigation.removeListener(\"beforeRemove\", backHandler);\n  }, [navigation]);\n\n  return (\n    <SafeAreaView\n      style={[styles.safeArea, { backgroundColor: color.BACKGROUND }]}\n      edges={[\"bottom\"]}\n    >\n      <View style={styles.container}>\n        <DashboardTopBar\n          onSettingsPress={() => navigation.navigate(\"Settings\", { screen: \"SettingsMain\" })}\n        />\n        <View style={styles.content}>\n          <View style={styles.balanceSection}>\n            <TouchableOpacity\n              style={styles.balanceWrap}\n              onPress={toggleBalanceFormat}\n              disabled={hidden.balance}\n              accessibilityRole=\"button\"\n            >\n              <Text\n                testID={`balance: ${balances.total.total}`}\n                style={[styles.balanceAmount, { color: balanceTextColor }]}\n              >\n                {hidden.balance ? \"****\" : balanceAmount.formatted}\n              </Text>\n              <View style={styles.balanceMetaWrap}>\n                {!hidden.balance && (\n                  <>\n                    <Text style={[styles.balanceSymbol, { color: balanceMetaColor }]}>\n                      {balanceAmount.symbol}\n                    </Text>\n                    <SwapCurrencyIcon width={s(18)} height={s(18)} color={balanceMetaColor} />\n                  </>\n                )}\n              </View>\n              <View\n                style={[\n                  styles.balanceRule,\n                  { backgroundColor: withAlpha(accentColor, isDarkTheme ? 0.4 : 0.28) },\n                ]}\n              />\n            </TouchableOpacity>\n          </View>\n\n          <View style={styles.historySection}>\n            <View style={styles.sectionHeader}>\n              <Text style={[styles.sectionTitle, { color: color.TEXT }]} numberOfLines={1}>\n                {t(\"activity\")}\n              </Text>\n              {hasMore && (\n                <TouchableOpacity\n                  accessibilityRole=\"button\"\n                  onPress={() => navigation.navigate(\"History\", { screen: \"HistoryMain\" })}\n                  style={[\n                    styles.historyLink,\n                    {\n                      backgroundColor: withAlpha(accentColor, isDarkTheme ? 0.14 : 0.12),\n                      borderColor: withAlpha(accentColor, isDarkTheme ? 0.28 : 0.18),\n                    },\n                  ]}\n                  testID={`${t(\"allHistory\")}-button`}\n                >\n                  <Text numberOfLines={1} style={[styles.historyLinkTxt, { color: accentColor }]}>\n                    {t(\"allHistory\")}\n                  </Text>\n                </TouchableOpacity>\n              )}\n            </View>\n            {!latestHistory.length ? (\n              <View style={[styles.emptyHistory, { backgroundColor: color.DRAWER }]}>\n                <Txt txt={t(\"noTX\")} styles={[globals(color).txt, styles.emptyHistoryTxt]} />\n              </View>\n            ) : (\n              <ScrollView\n                style={[styles.historyList, { backgroundColor: color.DRAWER }]}\n                contentContainerStyle={styles.historyListContent}\n                showsVerticalScrollIndicator={false}\n              >\n                {latestHistory.slice(0, 10).map((entry, index) => (\n                  <View key={entry.id} style={styles.historyEntry}>\n                    {renderHistoryEntry(entry)}\n                    {index < latestHistory.length - 1 && index < 9 ? (\n                      <View\n                        style={[styles.historyDivider, { backgroundColor: color.DARK_BORDER }]}\n                      />\n                    ) : null}\n                  </View>\n                ))}\n              </ScrollView>\n            )}\n          </View>\n        </View>\n\n        <View style={styles.actionDockWrap}>\n          <View\n            style={[\n              styles.actionDock,\n              {\n                backgroundColor: color.DRAWER,\n                borderColor: isDarkTheme ? color.DARK_BORDER : color.BORDER,\n              },\n            ]}\n          >\n            {knownMints.length > 0 ? (\n              <ActionBtn\n                icon={<SendIcon width={s(26)} height={s(26)} color={actionIconColor} />}\n                txt={t(\"send\", { ns: NS.wallet })}\n                textColor={actionTextColor}\n                iconBackgroundColor={actionIconBackground}\n                iconBorderColor={actionIconBorderColor}\n                onPress={() => {\n                  void sendOptionsRef.current?.present();\n                }}\n              />\n            ) : (\n              <ActionBtn\n                icon={<PlusIcon width={s(28)} height={s(28)} color={actionIconColor} />}\n                txt={t(\"mint\")}\n                textColor={actionTextColor}\n                iconBackgroundColor={actionIconBackground}\n                iconBorderColor={actionIconBorderColor}\n                onPress={() => {\n                  navigation.navigate(\"Mint\", { screen: \"MintHome\" });\n                }}\n              />\n            )}\n            <ActionBtn\n              icon={<ScanQRIcon width={s(26)} height={s(26)} color={actionIconColor} />}\n              txt={t(\"scan\")}\n              textColor={actionTextColor}\n              iconBackgroundColor={actionIconBackground}\n              iconBorderColor={actionIconBorderColor}\n              onPress={() => navigation.navigate(\"QRScanner\")}\n            />\n            <ActionBtn\n              icon={<ReceiveIcon width={s(26)} height={s(26)} color={actionIconColor} />}\n              txt={t(\"receive\", { ns: NS.wallet })}\n              textColor={actionTextColor}\n              iconBackgroundColor={actionIconBackground}\n              iconBorderColor={actionIconBorderColor}\n              disabled={isReceiving}\n              onPress={() => {\n                void receiveOptionsRef.current?.present();\n              }}\n            />\n          </View>\n        </View>\n\n        <DashboardActionSheet\n          sheetRef={sendOptionsRef}\n          title={t(\"send\", { ns: NS.wallet })}\n          closeAccessibilityLabel={t(\"cancel\")}\n          backgroundColor={color.BACKGROUND}\n          closeIconColor={color.TEXT_SECONDARY}\n        >\n          <DashboardActionSheetOption\n            icon={<SendMsgIcon width={s(16)} height={s(16)} color={mainColors.VALID} />}\n            title={t(\"sendEcash\")}\n            description={t(\"sendEcashDashboard\")}\n            textColor={color.TEXT}\n            descriptionColor={color.TEXT_SECONDARY}\n            onPress={() => {\n              void sendOptionsRef.current?.dismiss();\n              navigation.navigate(\"SendSelectAmount\");\n            }}\n            testID=\"send-ecash-option\"\n          />\n\n          <Separator style={styles.sheetSeparator} />\n\n          <DashboardActionSheetOption\n            icon={<ZapIcon width={s(26)} height={s(26)} color={mainColors.ZAP} />}\n            title={t(\"payLNInvoice\", { ns: NS.wallet })}\n            description={t(\"payInvoiceDashboard\")}\n            textColor={color.TEXT}\n            descriptionColor={color.TEXT_SECONDARY}\n            onPress={() => {\n              void sendOptionsRef.current?.dismiss();\n              navigation.navigate(\"MeltInput\", {});\n            }}\n            testID=\"pay-invoice-option\"\n          />\n\n          <Separator style={styles.sheetSeparator} />\n\n          <DashboardActionSheetOption\n            icon={<NfcIcon width={s(20)} color={mainColors.VALID} />}\n            title={t(\"nfcPayment\", {\n              ns: NS.wallet,\n              defaultValue: \"NFC Payment\",\n            })}\n            description={t(\"nfcPaymentDescription\", {\n              ns: NS.wallet,\n              defaultValue: \"Tap to pay at a terminal\",\n            })}\n            textColor={color.TEXT}\n            descriptionColor={color.TEXT_SECONDARY}\n            onPress={handleNfcOptionPress}\n            testID=\"third-option\"\n          />\n        </DashboardActionSheet>\n\n        <NfcPaymentModal\n          ref={nfcModalRef}\n          onSuccess={(result) => {\n            openPromptAutoClose({\n              msg: result.amount\n                ? `Sent ${result.amount.toLocaleString()} sats via NFC!`\n                : \"NFC payment sent successfully!\",\n              success: true,\n            });\n          }}\n          onError={(result) => {\n            openPromptAutoClose({\n              msg: result.error || \"NFC payment failed\",\n              success: false,\n            });\n          }}\n          onPaymentHandoff={(handoff) => {\n            navigation.navigate(\"MeltInput\", { invoice: handoff.value });\n          }}\n        />\n\n        <DashboardActionSheet\n          sheetRef={receiveOptionsRef}\n          title={t(\"receive\", { ns: NS.wallet })}\n          closeAccessibilityLabel={t(\"cancel\")}\n          backgroundColor={color.BACKGROUND}\n          closeIconColor={color.TEXT_SECONDARY}\n        >\n          <DashboardActionSheetOption\n            icon={\n              loading ? (\n                <Loading size=\"small\" color={mainColors.VALID} />\n              ) : (\n                <CopyIcon color={mainColors.VALID} />\n              )\n            }\n            title={loading ? t(\"claiming\", { ns: NS.wallet }) : t(\"pasteToken\", { ns: NS.wallet })}\n            description={t(\"receiveEcashDashboard\")}\n            textColor={color.TEXT}\n            descriptionColor={color.TEXT_SECONDARY}\n            onPress={() => {\n              void handleClaimBtnPress();\n              void receiveOptionsRef.current?.dismiss();\n            }}\n            testID=\"send-ecash-option\"\n          />\n\n          <Separator style={styles.sheetSeparator} />\n\n          <DashboardActionSheetOption\n            icon={<ZapIcon width={s(26)} height={s(26)} color={mainColors.ZAP} />}\n            title={t(\"createLnInvoice\")}\n            description={t(\"createInvoiceDashboard\")}\n            textColor={color.TEXT}\n            descriptionColor={color.TEXT_SECONDARY}\n            onPress={() => {\n              void receiveOptionsRef.current?.dismiss();\n              navigation.navigate(\"MintSelectAmount\");\n            }}\n            testID=\"pay-invoice-option\"\n          />\n        </DashboardActionSheet>\n      </View>\n    </SafeAreaView>\n  );\n}\n\ninterface IActionBtnsProps {\n  icon: ReactNode;\n  txt: string;\n  onPress: () => void;\n  textColor: string;\n  iconBackgroundColor: string;\n  iconBorderColor: string;\n  disabled?: boolean;\n}\n\nfunction ActionBtn({\n  icon,\n  onPress,\n  txt,\n  textColor,\n  iconBackgroundColor,\n  iconBorderColor,\n  disabled,\n}: IActionBtnsProps) {\n  return (\n    <TouchableOpacity\n      accessibilityRole=\"button\"\n      activeOpacity={0.65}\n      style={[styles.actionBtn, { opacity: disabled ? 0.45 : 1 }]}\n      onPress={onPress}\n      disabled={disabled}\n      testID={`${txt}-btn`}\n    >\n      <View\n        style={[\n          styles.actionIcon,\n          { backgroundColor: iconBackgroundColor, borderColor: iconBorderColor },\n        ]}\n      >\n        {icon}\n      </View>\n      <Txt txt={txt} bold styles={[styles.actionTxt, { color: textColor }]} />\n    </TouchableOpacity>\n  );\n}\n\nfunction renderHistoryEntry(entry: HistoryEntry) {\n  switch (entry.type) {\n    case \"mint\":\n      return <LatestHistoryMintEntry history={entry} variant=\"standard\" />;\n    case \"send\":\n      return <LatestHistorySendEntry history={entry} variant=\"standard\" />;\n    case \"melt\":\n      return <LatestHistoryMeltEntry history={entry} variant=\"standard\" />;\n    case \"receive\":\n      return <LatestHistoryReceiveEntry history={entry} variant=\"standard\" />;\n    default:\n      return null;\n  }\n}\n\nfunction withAlpha(hex: string, alpha: number) {\n  const color = hex.replace(\"#\", \"\");\n  if (color.length !== 6) {\n    return hex;\n  }\n\n  const red = parseInt(color.slice(0, 2), 16);\n  const green = parseInt(color.slice(2, 4), 16);\n  const blue = parseInt(color.slice(4, 6), 16);\n  return `rgba(${red}, ${green}, ${blue}, ${alpha})`;\n}\n\nconst styles = ScaledSheet.create({\n  safeArea: {\n    flex: 1,\n  },\n  container: {\n    flex: 1,\n  },\n  content: {\n    flex: 1,\n    paddingHorizontal: \"20@s\",\n    paddingTop: \"2@vs\",\n  },\n  balanceSection: {\n    paddingTop: \"10@vs\",\n    paddingBottom: \"24@vs\",\n  },\n  balanceWrap: {\n    alignItems: \"center\",\n    paddingVertical: \"8@vs\",\n  },\n  balanceAmount: {\n    fontSize: \"64@s\",\n    fontWeight: \"700\",\n    lineHeight: \"74@s\",\n    textAlign: \"center\",\n  },\n  balanceMetaWrap: {\n    flexDirection: \"row\",\n    alignItems: \"center\",\n    minHeight: \"22@s\",\n    marginTop: \"-2@vs\",\n  },\n  balanceSymbol: {\n    fontSize: \"14@vs\",\n    fontWeight: \"500\",\n    marginRight: \"6@s\",\n  },\n  balanceRule: {\n    width: \"72@s\",\n    height: \"3@vs\",\n    borderRadius: \"2@vs\",\n    marginTop: \"12@vs\",\n  },\n  actionDockWrap: {\n    paddingHorizontal: \"20@s\",\n    paddingTop: \"8@vs\",\n    paddingBottom: \"10@vs\",\n    backgroundColor: \"transparent\",\n  },\n  actionDock: {\n    flexDirection: \"row\",\n    alignItems: \"center\",\n    justifyContent: \"space-between\",\n    borderRadius: \"26@s\",\n    borderWidth: 1,\n    paddingHorizontal: \"14@s\",\n    paddingVertical: \"10@vs\",\n  },\n  actionBtn: {\n    alignItems: \"center\",\n    justifyContent: \"center\",\n    width: \"82@s\",\n    minHeight: \"70@s\",\n  },\n  actionIcon: {\n    width: \"44@s\",\n    height: \"44@s\",\n    borderRadius: \"22@s\",\n    borderWidth: 1,\n    alignItems: \"center\",\n    justifyContent: \"center\",\n    marginBottom: \"7@vs\",\n  },\n  actionTxt: {\n    fontSize: \"12@vs\",\n    textAlign: \"center\",\n  },\n  sheetSeparator: {\n    width: \"100%\",\n    marginTop: \"10@vs\",\n    marginBottom: \"10@vs\",\n  },\n  historySection: {\n    flex: 1,\n  },\n  sectionHeader: {\n    minHeight: \"34@vs\",\n    flexDirection: \"row\",\n    alignItems: \"center\",\n    justifyContent: \"space-between\",\n    marginBottom: \"10@vs\",\n  },\n  sectionTitle: {\n    flex: 1,\n    fontSize: \"22@vs\",\n    fontWeight: \"600\",\n    marginRight: \"14@s\",\n  },\n  historyLink: {\n    minWidth: \"52@s\",\n    minHeight: \"30@vs\",\n    borderRadius: \"15@vs\",\n    borderWidth: 1,\n    paddingHorizontal: \"14@s\",\n    alignItems: \"center\",\n    justifyContent: \"center\",\n  },\n  historyLinkTxt: {\n    fontSize: \"13@vs\",\n    fontWeight: \"500\",\n    textAlign: \"right\",\n  },\n  historyList: {\n    flex: 1,\n    borderRadius: \"26@s\",\n    paddingHorizontal: \"16@s\",\n  },\n  historyListContent: {\n    paddingTop: \"12@vs\",\n    paddingBottom: \"2@vs\",\n  },\n  historyEntry: {\n    paddingTop: \"1@vs\",\n  },\n  historyDivider: {\n    height: 1,\n    marginTop: \"9@vs\",\n    marginBottom: \"9@vs\",\n  },\n  emptyHistory: {\n    minHeight: \"100@vs\",\n    borderRadius: \"26@s\",\n    alignItems: \"center\",\n    justifyContent: \"center\",\n    paddingHorizontal: \"20@s\",\n  },\n  emptyHistoryTxt: {\n    textAlign: \"center\",\n  },\n});\n"
  },
  {
    "path": "src/screens/DashboardActionSheet.tsx",
    "content": "import { CloseIcon } from \"@comps/Icons\";\nimport Txt from \"@comps/Txt\";\nimport { TrueSheet } from \"@lodev09/react-native-true-sheet\";\nimport type { ReactNode, RefObject } from \"react\";\nimport { Text, TouchableOpacity, View } from \"react-native\";\nimport { s, ScaledSheet } from \"react-native-size-matters\";\n\ninterface IDashboardActionSheetProps {\n  sheetRef: RefObject<TrueSheet | null>;\n  title: string;\n  closeAccessibilityLabel: string;\n  backgroundColor: string;\n  closeIconColor: string;\n  children: ReactNode;\n}\n\nexport default function DashboardActionSheet({\n  sheetRef,\n  title,\n  closeAccessibilityLabel,\n  backgroundColor,\n  closeIconColor,\n  children,\n}: IDashboardActionSheetProps) {\n  return (\n    <TrueSheet\n      ref={sheetRef}\n      detents={[\"auto\"]}\n      backgroundColor={backgroundColor}\n      cornerRadius={s(26)}\n      grabberOptions={{ color: closeIconColor }}\n    >\n      <View style={[styles.container, { backgroundColor }]}>\n        <View style={styles.header}>\n          <Txt txt={title} bold center styles={[styles.title]} />\n          <TouchableOpacity\n            activeOpacity={0.65}\n            accessibilityRole=\"button\"\n            accessibilityLabel={closeAccessibilityLabel}\n            style={styles.closeBtn}\n            onPress={() => {\n              void sheetRef.current?.dismiss();\n            }}\n          >\n            <CloseIcon width={s(18)} height={s(18)} color={closeIconColor} />\n          </TouchableOpacity>\n        </View>\n\n        {children}\n      </View>\n    </TrueSheet>\n  );\n}\n\ninterface IDashboardActionSheetOptionProps {\n  icon: ReactNode;\n  title: string;\n  description: string;\n  textColor: string;\n  descriptionColor: string;\n  onPress: () => void;\n  testID: string;\n}\n\nexport function DashboardActionSheetOption({\n  icon,\n  title,\n  description,\n  textColor,\n  descriptionColor,\n  onPress,\n  testID,\n}: IDashboardActionSheetOptionProps) {\n  return (\n    <TouchableOpacity\n      activeOpacity={0.7}\n      style={styles.optionContainer}\n      onPress={onPress}\n      testID={testID}\n      accessibilityRole=\"button\"\n    >\n      <View style={styles.iconContainer}>{icon}</View>\n      <View style={styles.txtWrap}>\n        <Text style={[styles.actionText, { color: textColor }]}>{title}</Text>\n        <Text style={[styles.descriptionText, { color: descriptionColor }]}>{description}</Text>\n      </View>\n    </TouchableOpacity>\n  );\n}\n\nconst styles = ScaledSheet.create({\n  container: {\n    paddingHorizontal: \"20@s\",\n    paddingTop: \"34@vs\",\n    paddingBottom: \"24@vs\",\n  },\n  header: {\n    minHeight: \"40@s\",\n    alignItems: \"center\",\n    justifyContent: \"center\",\n    marginBottom: \"18@vs\",\n  },\n  title: {\n    fontSize: \"20@vs\",\n    lineHeight: \"25@vs\",\n  },\n  closeBtn: {\n    position: \"absolute\",\n    right: 0,\n    top: 0,\n    width: \"40@s\",\n    height: \"40@s\",\n    alignItems: \"center\",\n    justifyContent: \"center\",\n  },\n  optionContainer: {\n    flexDirection: \"row\",\n    alignItems: \"center\",\n    width: \"100%\",\n  },\n  iconContainer: {\n    minWidth: \"11%\",\n  },\n  txtWrap: {\n    width: \"90%\",\n  },\n  actionText: {\n    fontSize: \"14@vs\",\n    fontWeight: \"500\",\n    marginBottom: \"4@vs\",\n  },\n  descriptionText: {\n    fontSize: \"12@vs\",\n  },\n});\n"
  },
  {
    "path": "src/screens/ErrorScreen/ErrorBoundary.tsx",
    "content": "import { isReactNativeDevMode } from \"@consts\";\nimport { err } from \"@log\";\nimport type { ErrorInfo, ReactNode } from \"react\";\nimport { Component } from \"react\";\n\nimport { ErrorDetails } from \"./ErrorDetails\";\n\ninterface IProps {\n  children: ReactNode;\n  catchErrors: \"always\" | \"dev\" | \"prod\" | \"never\";\n  fallbackComponent?: () => React.JSX.Element;\n}\n\ninterface IState {\n  error: Error | null;\n  errorInfo: ErrorInfo | null;\n}\n\n/**\n * This component handles whenever the user encounters a JS error in the\n * app. It follows the \"error boundary\" pattern in React. We're using a\n * class component because according to the documentation, only class\n * components can be error boundaries.\n *\n * - [Documentation and Examples](https://github.com/infinitered/ignite/blob/master/docs/Error-Boundary.md)\n * - [React Error Boundaries](https://reactjs.org/docs/error-boundaries.html)\n */\nexport class CustomErrorBoundary extends Component<IProps, IState> {\n  state = { error: null, errorInfo: null };\n\n  // If an error in a child is encountered, this will run\n  componentDidCatch(error: Error, errorInfo: ErrorInfo) {\n    // Catch errors in any components below and re-render with error message\n    this.setState({ error, errorInfo });\n    err(error, errorInfo);\n  }\n\n  // Reset the error back to null\n  resetError = () => {\n    this.setState({ error: null, errorInfo: null });\n  };\n\n  // To avoid unnecessary re-renders\n  shouldComponentUpdate(_nextProps: Readonly<IProps>, nextState: Readonly<IState>): boolean {\n    return nextState.error !== this.state.error;\n  }\n\n  // Only enable if we're catching errors in the right environment\n  isEnabled(): boolean {\n    return (\n      this.props.catchErrors === \"always\" ||\n      (this.props.catchErrors === \"dev\" && isReactNativeDevMode) ||\n      (this.props.catchErrors === \"prod\" && !isReactNativeDevMode)\n    );\n  }\n\n  // Render an error UI if there's an error; otherwise, render children\n  render() {\n    return this.isEnabled() && this.state.error ? (\n      <ErrorDetails\n        resetError={this.resetError}\n        error={this.state.error}\n        componentStack={this.state.errorInfo}\n        eventId={null}\n      />\n    ) : (\n      this.props.children\n    );\n  }\n}\n"
  },
  {
    "path": "src/screens/ErrorScreen/ErrorDetails.tsx",
    "content": "import Txt from \"@comps/Txt\";\nimport { repoIssueUrl } from \"@consts/urls\";\nimport { usePromptContext } from \"@src/context/Prompt\";\nimport { NS } from \"@src/i18n\";\nimport { mainColors } from \"@src/styles\";\nimport { isErr, openUrl } from \"@util\";\nimport { useTranslation } from \"react-i18next\";\nimport { ScrollView, TouchableOpacity, View } from \"react-native\";\nimport { s, ScaledSheet } from \"react-native-size-matters\";\n\nexport interface ErrorDetailsProps {\n  error: Error;\n  componentStack: string | null;\n  eventId: string | null;\n  resetError(): void;\n}\n\nexport function ErrorDetails(props: ErrorDetailsProps) {\n  const { t } = useTranslation([NS.error]);\n  const { openPromptAutoClose } = usePromptContext();\n  return (\n    <View style={styles.container}>\n      <Txt txt={t(\"header\")} bold styles={[styles.header]} />\n      <Txt txt={t(\"msg\")} styles={[{ marginBottom: s(20) }]} />\n      <ScrollView style={styles.scroll} showsVerticalScrollIndicator={false}>\n        <Txt txt={props.error.message} styles={[{ color: mainColors.ERROR }]} />\n        <Txt txt={props?.componentStack || t(\"stackNA\")} />\n      </ScrollView>\n      <TouchableOpacity\n        onPress={() =>\n          void openUrl(repoIssueUrl)?.catch((err: unknown) =>\n            openPromptAutoClose({\n              msg: isErr(err) ? err.message : t(\"deepLinkErr\", { ns: NS.common }),\n            }),\n          )\n        }\n        style={styles.bugReport}\n      >\n        <Txt txt={`${t(\"reportBug\")}  🐛`} center bold />\n      </TouchableOpacity>\n    </View>\n  );\n}\n\nconst styles = ScaledSheet.create({\n  container: {\n    flex: 1,\n    paddingHorizontal: \"20@s\",\n    paddingBottom: \"20@vs\",\n    paddingTop: \"80@vs\",\n  },\n  header: {\n    fontSize: \"22@vs\",\n    marginBottom: \"30@vs\",\n    textAlign: \"center\",\n  },\n  scroll: {\n    marginBottom: \"20@vs\",\n  },\n  bugReport: {\n    padding: \"20@vs\",\n  },\n});\n"
  },
  {
    "path": "src/screens/History/Details.tsx",
    "content": "import type { THistoryEntryPageProps } from \"@model/nav\";\nimport { SendHistoryDetails } from \"./components/SendHistoryDetails\";\nimport { MintHistoryDetails } from \"./components/MintHistoryDetails\";\nimport { MeltHistoryDetails } from \"./components/MeltHistoryDetails\";\nimport { ReceiveHistoryDetails } from \"./components/ReceiveHistoryDetails\";\n\nexport default function HistoryEntryDetails({ navigation, route }: THistoryEntryPageProps) {\n  const { entry } = route.params;\n  const goBack = () => navigation.goBack();\n\n  switch (entry.type) {\n    case \"send\":\n      return <SendHistoryDetails entry={entry} onGoBack={goBack} />;\n    case \"mint\":\n      return <MintHistoryDetails entry={entry} onGoBack={goBack} />;\n    case \"melt\":\n      return <MeltHistoryDetails entry={entry} onGoBack={goBack} />;\n    case \"receive\":\n      return <ReceiveHistoryDetails entry={entry} onGoBack={goBack} />;\n  }\n}\n"
  },
  {
    "path": "src/screens/History/components/DetailsSection.tsx",
    "content": "import Txt from \"@comps/Txt\";\nimport { useThemeContext } from \"@src/context/Theme\";\nimport { View } from \"react-native\";\nimport { ScaledSheet } from \"react-native-size-matters\";\nimport { ReactNode } from \"react\";\n\ntype DetailsSectionProps = {\n  children: ReactNode;\n};\n\nexport function DetailsSection({ children }: DetailsSectionProps) {\n  return <View style={styles.details}>{children}</View>;\n}\n\ntype DetailRowProps = {\n  label: string;\n  value: string;\n};\n\nexport function DetailRow({ label, value }: DetailRowProps) {\n  const { color } = useThemeContext();\n\n  return (\n    <View style={styles.detailRow}>\n      <Txt txt={label} styles={[styles.detailLabel, { color: color.TEXT_SECONDARY }]} />\n      <Txt txt={value} styles={[styles.detailValue, { color: color.TEXT }]} />\n    </View>\n  );\n}\n\nconst styles = ScaledSheet.create({\n  details: {\n    paddingHorizontal: \"15@s\",\n    paddingBottom: \"15@vs\",\n  },\n  detailRow: {\n    flexDirection: \"row\",\n    justifyContent: \"space-between\",\n    paddingVertical: \"10@vs\",\n  },\n  detailLabel: {\n    fontSize: \"14@vs\",\n  },\n  detailValue: {\n    fontSize: \"14@vs\",\n  },\n});\n"
  },
  {
    "path": "src/screens/History/components/HistoryDetailsScreen.tsx",
    "content": "import Screen from \"@comps/Screen\";\nimport { NS } from \"@src/i18n\";\nimport { useTranslation } from \"react-i18next\";\nimport { ScrollView } from \"react-native\";\nimport { ScaledSheet } from \"react-native-size-matters\";\nimport { ReactNode } from \"react\";\n\ntype HistoryDetailsScreenProps = {\n  onGoBack: () => void;\n  children: ReactNode;\n};\n\nexport function HistoryDetailsScreen({ onGoBack, children }: HistoryDetailsScreenProps) {\n  const { t } = useTranslation([NS.history]);\n\n  return (\n    <Screen screenName={t(\"details\")} withBackBtn handlePress={onGoBack}>\n      <ScrollView style={styles.scrollContainer}>{children}</ScrollView>\n    </Screen>\n  );\n}\n\nconst styles = ScaledSheet.create({\n  scrollContainer: {\n    flex: 1,\n  },\n});\n"
  },
  {
    "path": "src/screens/History/components/HistoryOverview.tsx",
    "content": "import Txt from \"@comps/Txt\";\nimport { useThemeContext } from \"@src/context/Theme\";\nimport { useCurrencyContext } from \"@src/context/Currency\";\nimport { View } from \"react-native\";\nimport { ScaledSheet } from \"react-native-size-matters\";\n\ntype HistoryOverviewProps = {\n  amount: number;\n  amountPrefix: \"+\" | \"-\";\n  amountColor: string;\n  typeLabel: string;\n  description: string;\n};\n\nexport function HistoryOverview({\n  amount,\n  amountPrefix,\n  amountColor,\n  typeLabel,\n  description,\n}: HistoryOverviewProps) {\n  const { color } = useThemeContext();\n  const { formatAmount } = useCurrencyContext();\n\n  const { formatted, symbol } = formatAmount(amount);\n  const amountDisplay = `${amountPrefix}${formatted} ${symbol}`;\n\n  return (\n    <View style={styles.overview}>\n      <Txt txt={amountDisplay} styles={[styles.amount, { color: amountColor }]} />\n      <Txt txt={typeLabel} styles={[styles.type, { color: color.TEXT_SECONDARY }]} />\n      <Txt txt={description} styles={[styles.description, { color: color.TEXT_SECONDARY }]} />\n    </View>\n  );\n}\n\nconst styles = ScaledSheet.create({\n  overview: {\n    alignItems: \"center\",\n    paddingVertical: \"20@vs\",\n    paddingHorizontal: \"15@s\",\n  },\n  amount: {\n    fontSize: \"40@vs\",\n    fontWeight: \"600\",\n  },\n  type: {\n    fontSize: \"14@vs\",\n    marginTop: \"5@vs\",\n  },\n  description: {\n    fontSize: \"14@vs\",\n    marginTop: \"5@vs\",\n    textAlign: \"center\",\n  },\n});\n"
  },
  {
    "path": "src/screens/History/components/LatestHistory.tsx",
    "content": "import { HistoryEntry } from \"@cashu/coco-core\";\nimport { View } from \"react-native\";\nimport { memo } from \"react\";\nimport { LatestHistoryMintEntry } from \"./LatestHistoryMintEntry\";\nimport { LatestHistorySendEntry } from \"./LatestHistorySendEntry\";\nimport { LatestHistoryMeltEntry } from \"./LatestHistoryMeltEntry\";\nimport { LatestHistoryReceiveEntry } from \"./LatestHistoryReceiveEntry\";\n\ntype LatestHistoryProps = {\n  history: ReadonlyArray<HistoryEntry>;\n};\n\nexport const LatestHistory = memo(function LatestHistory({ history }: LatestHistoryProps) {\n  return <View>{history.slice(0, 4).map((h) => renderHistoryEntry(h))}</View>;\n});\n\nfunction renderHistoryEntry(history: HistoryEntry) {\n  switch (history.type) {\n    case \"mint\":\n      return <LatestHistoryMintEntry history={history} key={history.id} />;\n    case \"send\":\n      return <LatestHistorySendEntry history={history} key={history.id} />;\n    case \"melt\":\n      return <LatestHistoryMeltEntry history={history} key={history.id} />;\n    case \"receive\":\n      return <LatestHistoryReceiveEntry history={history} key={history.id} />;\n    default:\n      return null;\n  }\n}\n"
  },
  {
    "path": "src/screens/History/components/LatestHistoryMeltEntry.tsx",
    "content": "import { ZapIcon, CheckmarkIcon } from \"@comps/Icons\";\nimport { LatestHistoryWrapper } from \"./LatestHistoryWrapper\";\nimport { useThemeContext } from \"@src/context/Theme\";\nimport { MeltHistoryEntry } from \"@cashu/coco-core\";\nimport { getColor } from \"@src/styles/colors\";\nimport { memo } from \"react\";\n\ntype LatestHistoryMeltEntryProps = {\n  history: MeltHistoryEntry;\n  variant?: \"highlight\" | \"standard\";\n};\n\nexport const LatestHistoryMeltEntry = memo(\n  function LatestHistoryMeltEntry({ history, variant = \"highlight\" }: LatestHistoryMeltEntryProps) {\n    const { color, highlight } = useThemeContext();\n    const iconColor = variant === \"highlight\" ? getColor(highlight, color) : color.TEXT;\n\n    let icon;\n    switch (history.state) {\n      case \"UNPAID\":\n        icon = <ZapIcon color={iconColor} />;\n        break;\n      case \"PAID\":\n        icon = <CheckmarkIcon color={iconColor} />;\n        break;\n      case \"PENDING\":\n        icon = <ZapIcon color={iconColor} />;\n        break;\n      default:\n        icon = <ZapIcon color={iconColor} />;\n    }\n    return (\n      <LatestHistoryWrapper\n        icon={icon}\n        name={history.type}\n        createdAt={history.createdAt}\n        amount={history.amount}\n        variant={variant}\n        entry={history}\n      />\n    );\n  },\n  (prev, next) =>\n    prev.history.id === next.history.id &&\n    prev.history.state === next.history.state &&\n    prev.history.amount === next.history.amount &&\n    prev.history.createdAt === next.history.createdAt,\n);\n"
  },
  {
    "path": "src/screens/History/components/LatestHistoryMintEntry.tsx",
    "content": "import { CheckmarkIcon, ClockIcon, EcashIcon } from \"@comps/Icons\";\nimport { LatestHistoryWrapper } from \"./LatestHistoryWrapper\";\nimport { useThemeContext } from \"@src/context/Theme\";\nimport { MintHistoryEntry } from \"@cashu/coco-core\";\nimport { getColor } from \"@src/styles/colors\";\nimport { memo } from \"react\";\n\ntype LatestHistoryMintEntryProps = {\n  history: MintHistoryEntry;\n  variant?: \"highlight\" | \"standard\";\n};\n\nexport const LatestHistoryMintEntry = memo(\n  function LatestHistoryMintEntry({ history, variant = \"highlight\" }: LatestHistoryMintEntryProps) {\n    const { color, highlight } = useThemeContext();\n    const iconColor = variant === \"highlight\" ? getColor(highlight, color) : color.TEXT;\n\n    let icon;\n    switch (history.state) {\n      case \"UNPAID\":\n        icon = <ClockIcon color={iconColor} />;\n        break;\n      case \"PAID\":\n        icon = <CheckmarkIcon color={iconColor} />;\n        break;\n      default:\n        icon = <EcashIcon color={iconColor} />;\n    }\n    return (\n      <LatestHistoryWrapper\n        icon={icon}\n        name={history.type}\n        createdAt={history.createdAt}\n        amount={history.amount}\n        variant={variant}\n        entry={history}\n      />\n    );\n  },\n  (prev, next) =>\n    prev.history.id === next.history.id &&\n    prev.history.state === next.history.state &&\n    prev.history.amount === next.history.amount &&\n    prev.history.createdAt === next.history.createdAt,\n);\n"
  },
  {
    "path": "src/screens/History/components/LatestHistoryReceiveEntry.tsx",
    "content": "import { ReceiveIcon } from \"@comps/Icons\";\nimport { LatestHistoryWrapper } from \"./LatestHistoryWrapper\";\nimport { useThemeContext } from \"@src/context/Theme\";\nimport { ReceiveHistoryEntry } from \"@cashu/coco-core\";\nimport { getColor } from \"@src/styles/colors\";\nimport { memo } from \"react\";\n\ntype LatestHistoryReceiveEntryProps = {\n  history: ReceiveHistoryEntry;\n  variant?: \"highlight\" | \"standard\";\n};\n\nexport const LatestHistoryReceiveEntry = memo(\n  function LatestHistoryReceiveEntry({\n    history,\n    variant = \"highlight\",\n  }: LatestHistoryReceiveEntryProps) {\n    const { color, highlight } = useThemeContext();\n    const iconColor = variant === \"highlight\" ? getColor(highlight, color) : color.TEXT;\n\n    return (\n      <LatestHistoryWrapper\n        icon={<ReceiveIcon color={iconColor} />}\n        name={history.type}\n        createdAt={history.createdAt}\n        amount={history.amount}\n        variant={variant}\n        entry={history}\n      />\n    );\n  },\n  (prev, next) =>\n    prev.history.id === next.history.id &&\n    prev.history.amount === next.history.amount &&\n    prev.history.createdAt === next.history.createdAt,\n);\n"
  },
  {
    "path": "src/screens/History/components/LatestHistorySendEntry.tsx",
    "content": "import { SendIcon, ClockIcon, CheckmarkIcon } from \"@comps/Icons\";\nimport { LatestHistoryWrapper } from \"./LatestHistoryWrapper\";\nimport { useThemeContext } from \"@src/context/Theme\";\nimport { SendHistoryEntry } from \"@cashu/coco-core\";\nimport { getColor } from \"@src/styles/colors\";\nimport { memo } from \"react\";\n\ntype LatestHistorySendEntryProps = {\n  history: SendHistoryEntry;\n  variant?: \"highlight\" | \"standard\";\n};\n\nexport const LatestHistorySendEntry = memo(\n  function LatestHistorySendEntry({ history, variant = \"highlight\" }: LatestHistorySendEntryProps) {\n    const { color, highlight } = useThemeContext();\n    const iconColor = variant === \"highlight\" ? getColor(highlight, color) : color.TEXT;\n\n    let icon;\n    switch (history.state) {\n      case \"prepared\":\n      case \"pending\":\n        icon = <ClockIcon color={iconColor} />;\n        break;\n      case \"finalized\":\n        icon = <CheckmarkIcon color={iconColor} />;\n        break;\n      case \"rolledBack\":\n      default:\n        icon = <SendIcon color={iconColor} />;\n    }\n\n    return (\n      <LatestHistoryWrapper\n        icon={icon}\n        name={history.type}\n        createdAt={history.createdAt}\n        amount={history.amount}\n        variant={variant}\n        entry={history}\n      />\n    );\n  },\n  (prev, next) =>\n    prev.history.id === next.history.id &&\n    prev.history.state === next.history.state &&\n    prev.history.amount === next.history.amount &&\n    prev.history.createdAt === next.history.createdAt,\n);\n"
  },
  {
    "path": "src/screens/History/components/LatestHistoryWrapper.tsx",
    "content": "import Txt from \"@comps/Txt\";\nimport { HistoryEntry } from \"@cashu/coco-core\";\nimport { usePrivacyContext } from \"@src/context/Privacy\";\nimport { useThemeContext } from \"@src/context/Theme\";\nimport { useCurrencyContext } from \"@src/context/Currency\";\nimport { getColor } from \"@src/styles/colors\";\nimport { useTranslation } from \"react-i18next\";\nimport { Text, TouchableOpacity, View } from \"react-native\";\nimport { s, ScaledSheet } from \"react-native-size-matters\";\nimport EntryTime from \"@screens/History/entryTime\";\nimport { NS } from \"@src/i18n\";\nimport { useNavigation } from \"@react-navigation/native\";\nimport type { NativeStackNavigationProp } from \"@react-navigation/native-stack\";\nimport { RootStackParamList } from \"@src/model/nav\";\n\ntype LatestHistoryWrapperProps = {\n  icon: React.ReactNode;\n  name: string;\n  createdAt: number;\n  amount: number;\n  variant?: \"highlight\" | \"standard\";\n  entry: HistoryEntry;\n};\n\nexport function LatestHistoryWrapper({\n  icon,\n  name,\n  createdAt,\n  amount,\n  variant = \"highlight\",\n  entry,\n}: LatestHistoryWrapperProps) {\n  const { color, highlight } = useThemeContext();\n  const { hidden } = usePrivacyContext();\n  const { formatAmount } = useCurrencyContext();\n  const { t } = useTranslation([NS.history, NS.common]);\n  const navigation = useNavigation<NativeStackNavigationProp<RootStackParamList, \"History\">>();\n\n  // Use white/background color for highlight mode (colored background)\n  // Use theme text colors for standard mode (white/drawer background)\n  const textColor = variant === \"highlight\" ? getColor(highlight, color) : color.TEXT;\n  const secondaryTextColor =\n    variant === \"highlight\" ? getColor(highlight, color) : color.TEXT_SECONDARY;\n\n  const handlePress = () => {\n    navigation.navigate(\"History\", {\n      screen: \"HistoryEntryDetails\",\n      params: { entry },\n    });\n  };\n\n  const { formatted, symbol } = formatAmount(amount);\n\n  return (\n    <TouchableOpacity style={styles.entry} onPress={handlePress}>\n      <View style={styles.wrap}>\n        <View style={styles.iconWrap}>{icon}</View>\n        <View>\n          <Txt\n            txt={name}\n            styles={[\n              {\n                color: textColor,\n                marginBottom: s(4),\n              },\n            ]}\n          />\n          <Text\n            style={{\n              color: secondaryTextColor,\n              fontSize: s(12),\n            }}\n          >\n            <EntryTime from={createdAt} fallback={t(\"justNow\")} />\n          </Text>\n        </View>\n      </View>\n      <Txt\n        txt={hidden.balance ? \"****\" : `${formatted} ${symbol}`}\n        styles={[{ color: textColor }]}\n      />\n    </TouchableOpacity>\n  );\n}\n\nconst styles = ScaledSheet.create({\n  board: {\n    borderBottomLeftRadius: 50,\n    borderBottomRightRadius: 50,\n    paddingHorizontal: \"20@s\",\n    paddingTop: \"40@s\",\n    paddingBottom: \"50@s\",\n    minHeight: \"55%\",\n  },\n  balanceWrap: {\n    alignItems: \"center\",\n    marginHorizontal: \"-20@s\",\n    marginBottom: \"10@s\",\n  },\n  balAmount: {\n    alignItems: \"center\",\n    fontSize: \"42@s\",\n    fontWeight: \"600\",\n  },\n  balAssetNameWrap: {\n    flexDirection: \"row\",\n    alignItems: \"center\",\n    marginBottom: \"10@s\",\n    minHeight: \"20@s\",\n  },\n  balAssetName: {\n    fontSize: \"14@vs\",\n    marginRight: \"5@s\",\n  },\n  iconWrap: {\n    minWidth: \"40@s\",\n    paddingTop: \"3@s\",\n  },\n  entry: {\n    flexDirection: \"row\",\n    alignItems: \"center\",\n    justifyContent: \"space-between\",\n    paddingBottom: \"10@s\",\n  },\n  wrap: {\n    flexDirection: \"row\",\n    alignItems: \"center\",\n  },\n  txOverview: {\n    flex: 1,\n    alignItems: \"center\",\n    justifyContent: \"center\",\n  },\n});\n"
  },
  {
    "path": "src/screens/History/components/MeltHistoryDetails.tsx",
    "content": "import Separator from \"@comps/Separator\";\nimport { MeltHistoryEntry } from \"@cashu/coco-core\";\nimport { NS } from \"@src/i18n\";\nimport { mainColors } from \"@styles\";\nimport { formatMintUrl } from \"@util\";\nimport { useTranslation } from \"react-i18next\";\nimport { HistoryDetailsScreen } from \"./HistoryDetailsScreen\";\nimport { HistoryOverview } from \"./HistoryOverview\";\nimport { DetailsSection, DetailRow } from \"./DetailsSection\";\n\nconst truncateStr = (str: string, maxLength: number) => {\n  if (str.length <= maxLength) return str;\n  return str.substring(0, maxLength) + \"...\";\n};\n\ntype MeltHistoryDetailsProps = {\n  entry: MeltHistoryEntry;\n  onGoBack: () => void;\n};\n\nexport function MeltHistoryDetails({ entry, onGoBack }: MeltHistoryDetailsProps) {\n  const { t } = useTranslation([NS.history, NS.common]);\n\n  const getDescription = () => {\n    switch (entry.state) {\n      case \"UNPAID\":\n        return t(\"awaitingPayment\", { ns: NS.common });\n      case \"PENDING\":\n        return t(\"paymentPending\", { ns: NS.common });\n      case \"PAID\":\n        return t(\"paidInvoice\");\n      default:\n        return t(\"paidInvoice\");\n    }\n  };\n\n  return (\n    <HistoryDetailsScreen onGoBack={onGoBack}>\n      <HistoryOverview\n        amount={entry.amount}\n        amountPrefix=\"-\"\n        amountColor={mainColors.ZAP}\n        typeLabel={t(\"melt\")}\n        description={getDescription()}\n      />\n      <Separator />\n      <DetailsSection>\n        <DetailRow label={t(\"date\")} value={new Date(entry.createdAt).toLocaleString()} />\n        <DetailRow label={t(\"status\", { ns: NS.common })} value={entry.state} />\n        <DetailRow label={t(\"mint\", { ns: NS.common })} value={formatMintUrl(entry.mintUrl)} />\n        {entry.unit && <DetailRow label={t(\"unit\", { ns: NS.common })} value={entry.unit} />}\n        <DetailRow label={t(\"quoteId\", { ns: NS.common })} value={truncateStr(entry.quoteId, 20)} />\n      </DetailsSection>\n    </HistoryDetailsScreen>\n  );\n}\n"
  },
  {
    "path": "src/screens/History/components/MintHistoryDetails.tsx",
    "content": "import Separator from \"@comps/Separator\";\nimport { MintHistoryEntry } from \"@cashu/coco-core\";\nimport { NS } from \"@src/i18n\";\nimport { mainColors } from \"@styles\";\nimport { formatMintUrl } from \"@util\";\nimport { useTranslation } from \"react-i18next\";\nimport { HistoryDetailsScreen } from \"./HistoryDetailsScreen\";\nimport { HistoryOverview } from \"./HistoryOverview\";\nimport { DetailsSection, DetailRow } from \"./DetailsSection\";\nimport { TokenSection } from \"./TokenSection\";\n\nconst truncateStr = (str: string, maxLength: number) => {\n  if (str.length <= maxLength) return str;\n  return str.substring(0, maxLength) + \"...\";\n};\n\ntype MintHistoryDetailsProps = {\n  entry: MintHistoryEntry;\n  onGoBack: () => void;\n};\n\nexport function MintHistoryDetails({ entry, onGoBack }: MintHistoryDetailsProps) {\n  const { t } = useTranslation([NS.history, NS.common]);\n\n  const getDescription = () => {\n    if (entry.state === \"UNPAID\") {\n      return t(\"awaitingPayment\", { ns: NS.common });\n    }\n    return t(\"receivedFromMint\", { ns: NS.common });\n  };\n\n  return (\n    <HistoryDetailsScreen onGoBack={onGoBack}>\n      <HistoryOverview\n        amount={entry.amount}\n        amountPrefix=\"+\"\n        amountColor={mainColors.VALID}\n        typeLabel={t(\"mint\", { ns: NS.common })}\n        description={getDescription()}\n      />\n      <Separator />\n      <DetailsSection>\n        <DetailRow label={t(\"date\")} value={new Date(entry.createdAt).toLocaleString()} />\n        <DetailRow label={t(\"status\", { ns: NS.common })} value={entry.state} />\n        <DetailRow label={t(\"mint\", { ns: NS.common })} value={formatMintUrl(entry.mintUrl)} />\n        {entry.unit && <DetailRow label={t(\"unit\", { ns: NS.common })} value={entry.unit} />}\n        <DetailRow label={t(\"quoteId\", { ns: NS.common })} value={truncateStr(entry.quoteId, 20)} />\n      </DetailsSection>\n\n      {entry.paymentRequest && (\n        <TokenSection label={t(\"invoice\", { ns: NS.common })} value={entry.paymentRequest} />\n      )}\n    </HistoryDetailsScreen>\n  );\n}\n"
  },
  {
    "path": "src/screens/History/components/ReceiveHistoryDetails.tsx",
    "content": "import Separator from \"@comps/Separator\";\nimport { ReceiveHistoryEntry } from \"@cashu/coco-core\";\nimport { NS } from \"@src/i18n\";\nimport { mainColors } from \"@styles\";\nimport { formatMintUrl } from \"@util\";\nimport { useTranslation } from \"react-i18next\";\nimport { HistoryDetailsScreen } from \"./HistoryDetailsScreen\";\nimport { HistoryOverview } from \"./HistoryOverview\";\nimport { DetailsSection, DetailRow } from \"./DetailsSection\";\n\ntype ReceiveHistoryDetailsProps = {\n  entry: ReceiveHistoryEntry;\n  onGoBack: () => void;\n};\n\nexport function ReceiveHistoryDetails({ entry, onGoBack }: ReceiveHistoryDetailsProps) {\n  const { t } = useTranslation([NS.history, NS.common]);\n\n  return (\n    <HistoryDetailsScreen onGoBack={onGoBack}>\n      <HistoryOverview\n        amount={entry.amount}\n        amountPrefix=\"+\"\n        amountColor={mainColors.VALID}\n        typeLabel={t(\"receive\")}\n        description={t(\"receivedEcash\")}\n      />\n      <Separator />\n      <DetailsSection>\n        <DetailRow label={t(\"date\")} value={new Date(entry.createdAt).toLocaleString()} />\n        <DetailRow label={t(\"mint\", { ns: NS.common })} value={formatMintUrl(entry.mintUrl)} />\n        {entry.unit && <DetailRow label={t(\"unit\", { ns: NS.common })} value={entry.unit} />}\n      </DetailsSection>\n    </HistoryDetailsScreen>\n  );\n}\n"
  },
  {
    "path": "src/screens/History/components/SendHistoryDetails.tsx",
    "content": "import Separator from \"@comps/Separator\";\nimport { SendHistoryEntry } from \"@cashu/coco-core\";\nimport { NS } from \"@src/i18n\";\nimport { mainColors } from \"@styles\";\nimport { formatMintUrl } from \"@util\";\nimport { useTranslation } from \"react-i18next\";\nimport { getEncodedToken } from \"@cashu/cashu-ts\";\nimport { HistoryDetailsScreen } from \"./HistoryDetailsScreen\";\nimport { HistoryOverview } from \"./HistoryOverview\";\nimport { DetailsSection, DetailRow } from \"./DetailsSection\";\nimport { TokenSection } from \"./TokenSection\";\nimport { useEffect, useState } from \"react\";\nimport Button from \"@comps/Button\";\nimport { useManager } from \"@cashu/coco-react\";\n\ntype SendHistoryDetailsProps = {\n  entry: SendHistoryEntry;\n  onGoBack: () => void;\n};\n\nexport function SendHistoryDetails({ entry, onGoBack }: SendHistoryDetailsProps) {\n  const { t } = useTranslation([NS.history, NS.common]);\n  const [reactiveEntry, setReactiveEntry] = useState(entry);\n  const manager = useManager();\n\n  useEffect(() => {\n    const unsub = manager.on(\"history:updated\", ({ entry: updatedEntry }) => {\n      if (updatedEntry.id === entry.id && updatedEntry.type === \"send\") {\n        setReactiveEntry(updatedEntry as SendHistoryEntry);\n      }\n    });\n    return () => unsub();\n  }, [entry.id, manager]);\n\n  const getDescription = () => {\n    switch (reactiveEntry.state) {\n      case \"prepared\":\n        return t(\"awaitingPayment\", { ns: NS.common });\n      case \"pending\":\n        return t(\"paymentPending\", { ns: NS.common });\n      case \"finalized\":\n        return t(\"sentEcash\");\n      case \"rolledBack\":\n        return reactiveEntry.state;\n      default:\n        return t(\"sentEcash\");\n    }\n  };\n\n  const tokenValue = reactiveEntry.token ? getEncodedToken(reactiveEntry.token) : null;\n\n  return (\n    <HistoryDetailsScreen onGoBack={onGoBack}>\n      <HistoryOverview\n        amount={reactiveEntry.amount}\n        amountPrefix=\"-\"\n        amountColor={mainColors.ERROR}\n        typeLabel={t(\"send\")}\n        description={getDescription()}\n      />\n      <Separator />\n      <DetailsSection>\n        <DetailRow label={t(\"date\")} value={new Date(reactiveEntry.createdAt).toLocaleString()} />\n        <DetailRow label={t(\"status\", { ns: NS.common })} value={reactiveEntry.state} />\n        <DetailRow\n          label={t(\"mint\", { ns: NS.common })}\n          value={formatMintUrl(reactiveEntry.mintUrl)}\n        />\n        {reactiveEntry.unit && (\n          <DetailRow label={t(\"unit\", { ns: NS.common })} value={reactiveEntry.unit} />\n        )}\n      </DetailsSection>\n\n      {tokenValue && <TokenSection label={t(\"token\")} value={tokenValue} />}\n      {reactiveEntry.state === \"pending\" && (\n        <Button\n          txt=\"Abort Send\"\n          onPress={async () => {\n            try {\n              await manager.ops.send.reclaim(reactiveEntry.operationId);\n            } catch (error) {\n              console.error(\"Error aborting send\", error);\n            }\n          }}\n        />\n      )}\n\n      {/* Future: Add action buttons for pending tokens */}\n      {/* {entry.state === \"pending\" && (\n        <ActionSection>\n          <Button onPress={handleShare}>Share Token</Button>\n          <Button onPress={handleRollback}>Cancel</Button>\n        </ActionSection>\n      )} */}\n    </HistoryDetailsScreen>\n  );\n}\n"
  },
  {
    "path": "src/screens/History/components/TokenSection.tsx",
    "content": "import Copy from \"@comps/Copy\";\nimport Txt from \"@comps/Txt\";\nimport Separator from \"@comps/Separator\";\nimport { useThemeContext } from \"@src/context/Theme\";\nimport { View } from \"react-native\";\nimport { ScaledSheet } from \"react-native-size-matters\";\n\nconst truncateStr = (str: string, maxLength: number) => {\n  if (str.length <= maxLength) return str;\n  return str.substring(0, maxLength) + \"...\";\n};\n\ntype TokenSectionProps = {\n  label: string;\n  value: string;\n};\n\nexport function TokenSection({ label, value }: TokenSectionProps) {\n  const { color } = useThemeContext();\n\n  return (\n    <>\n      <Separator style={styles.separator} />\n      <View style={styles.tokenSection}>\n        <View style={styles.tokenHeader}>\n          <Txt txt={label} styles={[styles.sectionTitle, { color: color.TEXT }]} />\n          <Copy txt={value} />\n        </View>\n        <View style={[styles.tokenContainer, { backgroundColor: color.INPUT_BG }]}>\n          <Txt\n            txt={truncateStr(value, 100)}\n            styles={[styles.tokenValue, { color: color.TEXT_SECONDARY }]}\n          />\n        </View>\n      </View>\n    </>\n  );\n}\n\nconst styles = ScaledSheet.create({\n  separator: {\n    marginVertical: \"10@vs\",\n  },\n  tokenSection: {\n    paddingHorizontal: \"15@s\",\n    paddingBottom: \"15@vs\",\n  },\n  tokenHeader: {\n    flexDirection: \"row\",\n    justifyContent: \"space-between\",\n    alignItems: \"center\",\n    marginBottom: \"10@vs\",\n  },\n  sectionTitle: {\n    fontSize: \"16@vs\",\n    fontWeight: \"600\",\n  },\n  tokenValue: {\n    fontSize: \"14@vs\",\n  },\n  tokenContainer: {\n    padding: \"10@s\",\n    borderRadius: \"8@s\",\n  },\n});\n"
  },
  {
    "path": "src/screens/History/entryTime.tsx",
    "content": "import { DayInMs, HourInMs, MinuteInMs } from \"@consts\";\nimport { NS } from \"@src/i18n\";\nimport { getShortDateStr } from \"@util\";\nimport { useEffect, useState } from \"react\";\nimport { useTranslation } from \"react-i18next\";\n\ninterface IEntryTimeProps {\n  from: number;\n  fallback?: string;\n}\n\nexport default function EntryTime({ from, fallback }: IEntryTimeProps) {\n  const { t } = useTranslation([NS.history]);\n  const [time, setTime] = useState<string>();\n  function calcTime() {\n    const fromDate = new Date(from);\n    const ago = new Date().getTime() - from;\n    const absAgo = Math.abs(ago);\n    if (absAgo > DayInMs) {\n      return getShortDateStr(fromDate);\n    } else if (absAgo > HourInMs) {\n      const hrs = Math.floor(absAgo / HourInMs);\n      return hrs > 1 ? t(\"nHrsAgo\", { hrs }) : t(\"oneHrAgo\"); // `${hrs} hour${hrs > 1 ? 's' : ''} ago`\n    } else if (absAgo < MinuteInMs) {\n      return fallback;\n    }\n    const mins = Math.floor(absAgo / MinuteInMs);\n    return mins > 1 ? t(\"nMinsAgo\", { mins }) : t(\"oneMinAgo\"); //`${mins} minute${mins > 1 ? 's' : ''} ago`\n  }\n\n  useEffect(() => {\n    setTime(calcTime());\n    const t = setInterval(() => {\n      setTime((s) => {\n        const newTime = calcTime();\n        if (newTime !== s) {\n          return newTime;\n        }\n        return s;\n      });\n    }, MinuteInMs);\n    return () => clearInterval(t);\n    // eslint-disable-next-line react-hooks/exhaustive-deps\n  }, [time]);\n\n  return <>{time}</>;\n}\n"
  },
  {
    "path": "src/screens/History/index.tsx",
    "content": "import Empty from \"@comps/Empty\";\nimport { isIOS } from \"@consts\";\nimport type { THistoryPageProps } from \"@model/nav\";\nimport Screen from \"@comps/Screen\";\nimport { HistoryEntry } from \"@cashu/coco-core\";\nimport { usePaginatedHistory } from \"@cashu/coco-react\";\nimport { FlashList } from \"@shopify/flash-list\";\nimport { useThemeContext } from \"@src/context/Theme\";\nimport { NS } from \"@src/i18n\";\nimport { globals } from \"@styles\";\nimport { useTranslation } from \"react-i18next\";\nimport { ActivityIndicator, View } from \"react-native\";\nimport { useSafeAreaInsets } from \"react-native-safe-area-context\";\nimport { ScaledSheet } from \"react-native-size-matters\";\n\nimport { LatestHistoryMintEntry } from \"./components/LatestHistoryMintEntry\";\nimport { LatestHistorySendEntry } from \"./components/LatestHistorySendEntry\";\nimport { LatestHistoryMeltEntry } from \"./components/LatestHistoryMeltEntry\";\nimport { LatestHistoryReceiveEntry } from \"./components/LatestHistoryReceiveEntry\";\n\nexport default function HistoryPage({ navigation }: THistoryPageProps) {\n  const insets = useSafeAreaInsets();\n  const { t } = useTranslation([NS.common]);\n  const { color } = useThemeContext();\n  const { history, loadMore, hasMore, isFetching, refresh } = usePaginatedHistory(5);\n\n  const renderHistoryEntry = (entry: HistoryEntry) => {\n    switch (entry.type) {\n      case \"mint\":\n        return <LatestHistoryMintEntry history={entry} variant=\"standard\" />;\n      case \"send\":\n        return <LatestHistorySendEntry history={entry} variant=\"standard\" />;\n      case \"melt\":\n        return <LatestHistoryMeltEntry history={entry} variant=\"standard\" />;\n      case \"receive\":\n        return <LatestHistoryReceiveEntry history={entry} variant=\"standard\" />;\n      default:\n        return null;\n    }\n  };\n\n  const handleLoadMore = () => {\n    if (!isFetching && hasMore) {\n      void loadMore();\n    }\n  };\n\n  return (\n    <Screen\n      screenName={t(\"history\", { ns: NS.topNav })}\n      withBackBtn\n      handlePress={() => navigation.goBack()}\n    >\n      <View style={styles.container}>\n        <View style={styles.listContainer}>\n          {/* History list with infinite scroll */}\n          <FlashList\n            data={history}\n            renderItem={({ item }) => (\n              <View style={[styles.entryCard, { backgroundColor: color.DRAWER }]}>\n                {renderHistoryEntry(item)}\n              </View>\n            )}\n            onEndReached={handleLoadMore}\n            onEndReachedThreshold={0.5}\n            ListEmptyComponent={<Empty txt={t(\"noTX\") + \"...\"} />}\n            ListFooterComponent={\n              isFetching && hasMore ? (\n                <View style={styles.loaderWrap}>\n                  <ActivityIndicator size=\"small\" color={color.TEXT} />\n                </View>\n              ) : null\n            }\n            onRefresh={() => void refresh()}\n            refreshing={isFetching && history.length === 0}\n          />\n        </View>\n      </View>\n    </Screen>\n  );\n}\n\nconst styles = ScaledSheet.create({\n  container: {\n    flex: 1,\n    alignItems: \"center\",\n  },\n  listContainer: {\n    flex: 1,\n    width: \"100%\",\n  },\n  entryCard: {\n    borderRadius: 20,\n    paddingHorizontal: \"20@s\",\n    paddingVertical: \"15@vs\",\n    marginBottom: \"6@vs\",\n  },\n  loaderWrap: {\n    paddingVertical: \"20@vs\",\n    alignItems: \"center\",\n    justifyContent: \"center\",\n  },\n});\n"
  },
  {
    "path": "src/screens/Mints/AddMintScreen.tsx",
    "content": "import Txt from \"@comps/Txt\";\nimport TxtInput from \"@comps/TxtInput\";\nimport { ChevronRightIcon, ZapIcon, PlusIcon } from \"@comps/Icons\";\nimport { IconBtn } from \"@comps/Button\";\nimport { useThemeContext } from \"@src/context/Theme\";\nimport { NativeStackScreenProps } from \"@react-navigation/native-stack\";\nimport { MintStackParamList } from \"@src/nav/navTypes\";\nimport { globals, highlight as hi } from \"@src/styles\";\nimport { formatMintUrl, isErr } from \"@util\";\nimport { useState } from \"react\";\nimport useDiscoverMints from \"@comps/hooks/useDiscoverMints\";\nimport { View, TouchableOpacity, Text, ActivityIndicator, ScrollView } from \"react-native\";\nimport { s, vs } from \"react-native-size-matters\";\nimport Screen from \"@comps/Screen\";\nimport { usePromptContext } from \"@src/context/Prompt\";\nimport { NS } from \"@src/i18n\";\nimport { useTranslation } from \"react-i18next\";\nimport { useManager } from \"@src/context/Manager\";\n\ninterface RecommendedMintItemProps {\n  mint: MintRecommendation;\n  onPress: (url: string) => void;\n  color: any;\n  highlight: string;\n}\n\ntype MintRecommendation = {\n  id: number;\n  url: string;\n  info: string;\n  name: string;\n  balance: number;\n  sum_donations: number;\n  updated_at: string;\n  next_update: string;\n  state: string;\n  n_errors: number;\n  n_mints: number;\n  n_melts: number;\n};\n\nfunction RecommendedMintItem({ mint, color, highlight, onPress }: RecommendedMintItemProps) {\n  const displayName = mint.name || formatMintUrl(mint.url);\n  return (\n    <TouchableOpacity\n      style={[\n        {\n          flexDirection: \"row\",\n          alignItems: \"center\",\n          paddingVertical: vs(12),\n          paddingHorizontal: s(16),\n          backgroundColor: color.INPUT_BG,\n          marginVertical: vs(4),\n          borderRadius: s(8),\n        },\n      ]}\n      onPress={() => onPress(mint.url)}\n    >\n      <View style={{ flex: 1 }}>\n        <View\n          style={{\n            flexDirection: \"row\",\n            alignItems: \"center\",\n            marginBottom: vs(4),\n          }}\n        >\n          <Txt txt={displayName} bold styles={[{ color: color.TEXT }]} />\n          <View\n            style={{\n              backgroundColor: hi[highlight as keyof typeof hi],\n              paddingHorizontal: s(6),\n              paddingVertical: vs(2),\n              borderRadius: s(4),\n              marginLeft: s(8),\n            }}\n          >\n            <Text\n              style={{\n                color: \"white\",\n                fontSize: s(10),\n                fontWeight: \"bold\",\n              }}\n            >\n              {mint.state}\n            </Text>\n          </View>\n        </View>\n        <Text\n          style={{\n            color: color.TEXT_SECONDARY,\n            fontSize: s(12),\n            marginBottom: vs(2),\n          }}\n        >\n          {mint.url}\n        </Text>\n      </View>\n      <ChevronRightIcon color={color.TEXT_SECONDARY} />\n    </TouchableOpacity>\n  );\n}\n\ntype MintAddScreenProps = NativeStackScreenProps<MintStackParamList, \"MintAdd\">;\n\nfunction AddMintScreen({ navigation, route }: MintAddScreenProps) {\n  const { t } = useTranslation([NS.common]);\n  const { color, highlight } = useThemeContext();\n  const [inputUrl, setInputUrl] = useState(\"\");\n  const { recommendations, isLoading, isError } = useDiscoverMints();\n  const { openPromptAutoClose } = usePromptContext();\n  const manager = useManager();\n\n  const handleMintSelect = (url: string) => {\n    setInputUrl(url);\n    // You might want to add navigation or other logic here\n    // For now, just populate the input field\n  };\n\n  const handleConfirmSelection = async () => {\n    const submitted = inputUrl.trim();\n    if (!submitted) {\n      return;\n    }\n    try {\n      await manager.mint.addMint(submitted, { trusted: true });\n      navigation.goBack();\n    } catch (e) {\n      openPromptAutoClose({\n        msg: isErr(e) ? e.message : t(\"mintConnectionFail\", { ns: NS.mints }),\n        ms: 2000,\n      });\n    }\n  };\n\n  return (\n    <Screen\n      screenName=\"Add Mint\"\n      withBackBtn\n      handlePress={() => navigation.goBack()}\n      withKeyboard={true}\n    >\n      <View\n        style={{\n          paddingHorizontal: s(16),\n          paddingBottom: vs(12),\n          backgroundColor: color.BACKGROUND,\n          borderBottomWidth: 1,\n          borderBottomColor: color.BORDER || color.INPUT_BG,\n        }}\n      >\n        <View\n          style={{\n            flexDirection: \"row\",\n            alignItems: \"center\",\n            gap: s(12),\n          }}\n        >\n          <View style={{ flex: 1 }}>\n            <TxtInput\n              onChangeText={setInputUrl}\n              autoCorrect={false}\n              value={inputUrl}\n              placeholder=\"Enter mint URL or select from recommendations below\"\n              autoCapitalize=\"none\"\n            />\n          </View>\n          <View>\n            <IconBtn\n              icon={<PlusIcon color=\"white\" width={s(20)} height={s(20)} />}\n              onPress={handleConfirmSelection}\n              disabled={!inputUrl.trim()}\n              size={s(48)}\n              testId=\"confirm-mint-button\"\n            />\n          </View>\n        </View>\n      </View>\n\n      <ScrollView\n        style={{ flex: 1 }}\n        contentContainerStyle={{\n          paddingHorizontal: s(16),\n          paddingTop: vs(16),\n          paddingBottom: vs(20),\n        }}\n        keyboardShouldPersistTaps=\"handled\"\n        showsVerticalScrollIndicator={false}\n      >\n        {isLoading && (\n          <View\n            style={{\n              flexDirection: \"row\",\n              alignItems: \"center\",\n              justifyContent: \"center\",\n              paddingVertical: vs(20),\n            }}\n          >\n            <ActivityIndicator size=\"small\" color={hi[highlight as keyof typeof hi]} />\n            <Txt\n              txt=\"Loading recommendations...\"\n              styles={[{ marginLeft: s(8), color: color.TEXT_SECONDARY }]}\n            />\n          </View>\n        )}\n\n        {isError && (\n          <View style={{ paddingVertical: vs(20), alignItems: \"center\" }}>\n            <Txt txt=\"Failed to load recommendations\" styles={[{ color: color.TEXT_SECONDARY }]} />\n            <Text\n              style={{\n                color: color.TEXT_SECONDARY,\n                fontSize: s(12),\n                textAlign: \"center\",\n                marginTop: vs(4),\n              }}\n            >\n              Something went wrong fetching recommendations\n            </Text>\n          </View>\n        )}\n\n        {!isLoading && recommendations.length > 0 && (\n          <View>\n            <Txt\n              txt=\"Recommended Mints\"\n              bold\n              styles={[\n                {\n                  color: color.TEXT,\n                  marginBottom: vs(12),\n                  fontSize: s(16),\n                },\n              ]}\n            />\n            {recommendations.map((mint) => (\n              <RecommendedMintItem\n                key={mint.id}\n                mint={mint}\n                onPress={handleMintSelect}\n                color={color}\n                highlight={highlight}\n              />\n            ))}\n          </View>\n        )}\n      </ScrollView>\n    </Screen>\n  );\n}\n\nexport default AddMintScreen;\n"
  },
  {
    "path": "src/screens/Mints/MintHomeScreen.tsx",
    "content": "import Button, { IconBtn, TxtButton } from \"@comps/Button\";\nimport Card from \"@comps/Card\";\nimport Empty from \"@comps/Empty\";\nimport { ChevronRightIcon, PlusIcon } from \"@comps/Icons\";\nimport Txt from \"@comps/Txt\";\nimport Screen from \"@comps/Screen\";\nimport { useKnownMints } from \"@src/context/KnownMints\";\nimport { usePrivacyContext } from \"@src/context/Privacy\";\nimport { useThemeContext } from \"@src/context/Theme\";\nimport { NS } from \"@src/i18n\";\nimport { globals, highlight as hi } from \"@styles\";\nimport { getColor } from \"@styles/colors\";\nimport { formatMintUrl } from \"@util\";\nimport { useCurrencyContext } from \"@src/context/Currency\";\nimport { Image } from \"expo-image\";\nimport { useTranslation } from \"react-i18next\";\nimport { ScrollView, TouchableOpacity, View } from \"react-native\";\nimport { useSafeAreaInsets } from \"react-native-safe-area-context\";\nimport { s, ScaledSheet, vs } from \"react-native-size-matters\";\n\nexport default function MintHomeScreen({ navigation }: any) {\n  const { t } = useTranslation([NS.common]);\n  const { knownMints } = useKnownMints();\n  const { color, highlight } = useThemeContext();\n  const { formatAmount } = useCurrencyContext();\n  const insets = useSafeAreaInsets();\n  const { hidden } = usePrivacyContext();\n\n  return (\n    <Screen\n      screenName=\"Mints\"\n      withBackBtn\n      handlePress={() => navigation.goBack()}\n      rightAction={\n        <TouchableOpacity\n          onPress={() => {\n            navigation.navigate(\"Mint\", { screen: \"MintAdd\" });\n          }}\n          style={{ flexDirection: \"row\", alignItems: \"center\" }}\n        >\n          <PlusIcon width={s(30)} height={s(30)} color={hi[highlight]} />\n        </TouchableOpacity>\n      }\n    >\n      <View style={styles.container}>\n        {knownMints.length > 0 ? (\n          <View style={[styles.topSection, { marginBottom: 75 + insets.bottom }]}>\n            {/* Mints list */}\n            <ScrollView alwaysBounceVertical={false}>\n              {knownMints.map((m, i) => {\n                const displayName = m.mintInfo.name || formatMintUrl(m.mintUrl);\n                const { formatted, symbol } = formatAmount(m.balance);\n                const displayBalance = hidden.balance ? \"****\" : `${formatted} ${symbol}`;\n\n                return (\n                  <TouchableOpacity\n                    key={m.mintUrl}\n                    onPress={() => {\n                      navigation.navigate(\"MintSettings\", {\n                        mintUrl: m.mintUrl,\n                      });\n                    }}\n                    activeOpacity={0.7}\n                    style={{\n                      marginBottom: i < knownMints.length - 1 ? s(12) : 0,\n                    }}\n                  >\n                    <Card variant=\"base\" style={styles.cardContent}>\n                      <View style={styles.mintContainer}>\n                        {/* Left side: Mint icon (if available) */}\n                        {m.mintInfo.icon_url && (\n                          <View style={styles.iconContainer}>\n                            <Image\n                              source={{ uri: m.mintInfo.icon_url }}\n                              style={styles.icon}\n                              contentFit=\"cover\"\n                              transition={200}\n                            />\n                          </View>\n                        )}\n\n                        {/* Center: Mint name and balance */}\n                        <View style={styles.infoContainer}>\n                          <Txt txt={displayName} bold styles={[{ color: color.TEXT }]} />\n                          <Txt\n                            txt={displayBalance}\n                            styles={[\n                              {\n                                color: color.TEXT_SECONDARY,\n                                fontSize: s(12),\n                                marginTop: vs(2),\n                              },\n                            ]}\n                          />\n                        </View>\n\n                        {/* Right side: Chevron icon */}\n                        <View style={styles.chevronContainer}>\n                          <ChevronRightIcon color={color.TEXT} />\n                        </View>\n                      </View>\n                    </Card>\n                  </TouchableOpacity>\n                );\n              })}\n            </ScrollView>\n          </View>\n        ) : (\n          <View style={styles.noMintContainer}>\n            <Empty txt={t(\"noMint\")} />\n          </View>\n        )}\n      </View>\n    </Screen>\n  );\n}\n\nconst styles = ScaledSheet.create({\n  container: {\n    alignItems: \"center\",\n    justifyContent: \"flex-start\",\n  },\n  noMintContainer: {\n    flex: 1,\n    width: \"100%\",\n    paddingHorizontal: \"20@s\",\n  },\n  noMintBottomSection: {\n    position: \"absolute\",\n    bottom: \"20@s\",\n    right: \"20@s\",\n    left: \"20@s\",\n    rowGap: \"20@s\",\n  },\n  topSection: {\n    width: \"100%\",\n  },\n  newMint: {\n    position: \"absolute\",\n    right: 20,\n    bottom: 20,\n  },\n  cardContent: {\n    padding: \"12@s\",\n  },\n  mintContainer: {\n    flexDirection: \"row\",\n    alignItems: \"center\",\n  },\n  iconContainer: {\n    marginRight: \"12@s\",\n  },\n  icon: {\n    width: \"40@s\",\n    height: \"40@s\",\n    borderRadius: \"20@s\",\n  },\n  infoContainer: {\n    flex: 1,\n    justifyContent: \"center\",\n  },\n  chevronContainer: {\n    marginLeft: \"8@s\",\n  },\n});\n"
  },
  {
    "path": "src/screens/Mints/MintSettingsScreen.tsx",
    "content": "import Txt from \"@comps/Txt\";\nimport Screen from \"@comps/Screen\";\nimport { useTrustedMints } from \"@cashu/coco-react\";\n\nimport { l } from \"@log\";\nimport ConfirmBottomSheet, { ConfirmBottomSheetRef } from \"@comps/modal/ConfirmBottomSheet\";\nimport { useKnownMints } from \"@src/context/KnownMints\";\nimport { usePromptContext } from \"@src/context/Prompt\";\nimport { useThemeContext } from \"@src/context/Theme\";\nimport { NS } from \"@src/i18n\";\n\nimport { mainColors } from \"@styles\";\nimport { formatMintUrl } from \"@util\";\nimport { useRef } from \"react\";\nimport { useTranslation } from \"react-i18next\";\nimport { ScrollView, View } from \"react-native\";\nimport { s, ScaledSheet } from \"react-native-size-matters\";\nimport { Image } from \"expo-image\";\nimport Button from \"@comps/Button\";\n\nexport default function MintSettingsScreen({ navigation, route }: any) {\n  const { t } = useTranslation([NS.common]);\n  const { untrustMint } = useTrustedMints();\n  const { openPromptAutoClose } = usePromptContext();\n  const { color } = useThemeContext();\n  const confirmSheetRef = useRef<ConfirmBottomSheetRef>(null);\n\n  const { knownMints } = useKnownMints();\n  const mint = knownMints.find((m) => m.mintUrl === route.params.mintUrl);\n\n  const handleMintDelete = () => {\n    void (async () => {\n      try {\n        await untrustMint(route.params.mintUrl);\n        navigation.goBack();\n      } catch (e) {\n        l(e);\n      }\n    })();\n  };\n\n  return (\n    <Screen\n      screenName={t(\"mintSettings\", { ns: NS.topNav })}\n      withBackBtn\n      handlePress={() => navigation.goBack()}\n    >\n      <ScrollView showsVerticalScrollIndicator={false}>\n        {/* Mint Header Card */}\n        <View style={[styles.headerCard, { backgroundColor: color.INPUT_BG }]}>\n          <View style={styles.headerContent}>\n            {mint?.mintInfo?.icon_url && (\n              <Image\n                source={{ uri: mint.mintInfo.icon_url }}\n                style={styles.mintIcon}\n                contentFit=\"cover\"\n                transition={200}\n              />\n            )}\n            <View style={styles.headerTextContainer}>\n              {mint?.mintInfo?.name && (\n                <Txt txt={mint.mintInfo.name} styles={[styles.mintName, { color: color.TEXT }]} />\n              )}\n              {mint?.mintInfo?.version && (\n                <Txt\n                  txt={`Version ${mint.mintInfo.version}`}\n                  styles={[styles.mintVersion, { color: color.TEXT_SECONDARY }]}\n                />\n              )}\n            </View>\n          </View>\n        </View>\n\n        {/* Mint URL Section */}\n        <View style={styles.section}>\n          <Txt\n            txt={t(\"general\", { ns: NS.mints })}\n            styles={[styles.sectionTitle, { color: color.TEXT_SECONDARY }]}\n          />\n          <View style={[styles.card, { backgroundColor: color.INPUT_BG }]}>\n            <Txt\n              txt={formatMintUrl(route.params.mintUrl)}\n              styles={[styles.urlText, { color: color.TEXT }]}\n            />\n          </View>\n        </View>\n\n        {/* Metadata Section */}\n        {mint?.mintInfo &&\n          (mint.mintInfo.description ||\n            mint.mintInfo.description_long ||\n            (mint.mintInfo.contact && mint.mintInfo.contact.length > 0) ||\n            mint.mintInfo.motd) && (\n            <View style={styles.section}>\n              <Txt\n                txt={t(\"metadata\", { ns: NS.mints })}\n                styles={[styles.sectionTitle, { color: color.TEXT_SECONDARY }]}\n              />\n              <View style={[styles.card, { backgroundColor: color.INPUT_BG }]}>\n                {mint.mintInfo.description && (\n                  <InfoRow\n                    label=\"Description\"\n                    value={mint.mintInfo.description}\n                    hasSeparator={\n                      !!mint.mintInfo.description_long ||\n                      !!(mint.mintInfo.contact && mint.mintInfo.contact.length > 0) ||\n                      !!mint.mintInfo.motd\n                    }\n                  />\n                )}\n                {mint.mintInfo.description_long && (\n                  <InfoRow\n                    label=\"Details\"\n                    value={mint.mintInfo.description_long}\n                    hasSeparator={\n                      !!(mint.mintInfo.contact && mint.mintInfo.contact.length > 0) ||\n                      !!mint.mintInfo.motd\n                    }\n                  />\n                )}\n                {mint.mintInfo.contact && mint.mintInfo.contact.length > 0 && (\n                  <>\n                    {mint.mintInfo.contact.map((contact, index) => {\n                      const isLast = index === mint.mintInfo.contact!.length - 1;\n                      const hasMotd = !!mint.mintInfo.motd;\n                      return (\n                        <InfoRow\n                          key={`${contact.method}-${index}`}\n                          label={contact.method}\n                          value={contact.info}\n                          hasSeparator={!isLast || hasMotd}\n                        />\n                      );\n                    })}\n                  </>\n                )}\n                {mint.mintInfo.motd && <InfoRow label=\"Message\" value={mint.mintInfo.motd} />}\n              </View>\n            </View>\n          )}\n\n        {/* Danger Zone */}\n        <View style={styles.section}>\n          <Txt\n            txt={t(\"dangerZone\", { ns: NS.mints })}\n            styles={[styles.sectionTitle, { color: mainColors.ERROR }]}\n          />\n          <Button\n            txt={t(\"delMint\", { ns: NS.mints })}\n            destructive={true}\n            onPress={() => {\n              confirmSheetRef.current?.open({\n                header: t(\"delMint\", { ns: NS.mints }),\n                txt: t(\"delMintSure\", { ns: NS.mints }),\n                confirmTxt: t(\"confirm\", { ns: NS.common }),\n                cancelTxt: t(\"cancel\", { ns: NS.common }),\n                onConfirm: handleMintDelete,\n                destructive: true,\n              });\n            }}\n          />\n        </View>\n      </ScrollView>\n      <ConfirmBottomSheet ref={confirmSheetRef} />\n    </Screen>\n  );\n}\n\ninterface IInfoRow {\n  label: string;\n  value: string;\n  hasSeparator?: boolean;\n}\n\nfunction InfoRow({ label, value, hasSeparator }: IInfoRow) {\n  const { color } = useThemeContext();\n  return (\n    <>\n      <View style={styles.infoRow}>\n        <Txt txt={label} styles={[styles.infoLabel, { color: color.TEXT_SECONDARY }]} />\n        <Txt txt={value} styles={[styles.infoValue, { color: color.TEXT }]} />\n      </View>\n      {hasSeparator && <View style={[styles.infoSeparator, { backgroundColor: color.BORDER }]} />}\n    </>\n  );\n}\n\nconst styles = ScaledSheet.create({\n  headerCard: {\n    borderRadius: \"16@s\",\n    padding: \"20@s\",\n    marginTop: \"16@vs\",\n    marginBottom: \"24@vs\",\n  },\n  headerContent: {\n    flexDirection: \"row\",\n    alignItems: \"center\",\n  },\n  mintIcon: {\n    width: \"48@s\",\n    height: \"48@s\",\n    borderRadius: \"12@s\",\n    backgroundColor: \"rgba(0,0,0,0.05)\",\n  },\n  headerTextContainer: {\n    flex: 1,\n    marginLeft: \"16@s\",\n  },\n  mintName: {\n    fontSize: \"20@vs\",\n    fontWeight: \"700\",\n    marginBottom: \"4@vs\",\n    letterSpacing: 0.3,\n  },\n  mintVersion: {\n    fontSize: \"13@vs\",\n    fontWeight: \"500\",\n    opacity: 0.7,\n  },\n  balanceContainer: {\n    flexDirection: \"row\",\n    alignItems: \"center\",\n    justifyContent: \"center\",\n    paddingVertical: \"12@vs\",\n    paddingHorizontal: \"16@s\",\n    borderRadius: \"12@s\",\n    gap: \"8@s\",\n  },\n  balanceText: {\n    fontSize: \"18@vs\",\n    fontWeight: \"600\",\n  },\n  section: {\n    marginBottom: \"24@vs\",\n  },\n  sectionTitle: {\n    fontSize: \"12@vs\",\n    fontWeight: \"700\",\n    textTransform: \"uppercase\",\n    letterSpacing: 1,\n    marginBottom: \"12@vs\",\n    paddingHorizontal: \"4@s\",\n  },\n  card: {\n    borderRadius: \"16@s\",\n    padding: \"20@s\",\n  },\n  urlText: {\n    fontSize: \"14@vs\",\n    fontWeight: \"500\",\n    lineHeight: \"20@vs\",\n  },\n  infoRow: {\n    paddingVertical: \"8@vs\",\n  },\n  infoLabel: {\n    fontSize: \"12@vs\",\n    fontWeight: \"600\",\n    textTransform: \"capitalize\",\n    marginBottom: \"6@vs\",\n  },\n  infoValue: {\n    fontSize: \"14@vs\",\n    fontWeight: \"400\",\n    lineHeight: \"20@vs\",\n  },\n  infoSeparator: {\n    height: 1,\n    marginVertical: \"12@vs\",\n    opacity: 0.2,\n  },\n  deleteButton: {\n    flexDirection: \"row\",\n    alignItems: \"center\",\n    justifyContent: \"center\",\n    borderRadius: \"16@s\",\n    padding: \"16@s\",\n    borderWidth: 1.5,\n    gap: \"10@s\",\n  },\n  deleteButtonText: {\n    fontSize: \"15@vs\",\n    fontWeight: \"600\",\n  },\n});\n"
  },
  {
    "path": "src/screens/Mints/components/MetadataItem.tsx",
    "content": "import React from \"react\";\nimport { View } from \"react-native\";\nimport { vs, ScaledSheet } from \"react-native-size-matters\";\nimport Separator from \"@comps/Separator\";\nimport Txt from \"@comps/Txt\";\nimport { useThemeContext } from \"@src/context/Theme\";\n\ninterface MetadataItemProps {\n  text: string;\n  hasSeparator?: boolean;\n}\n\nexport default function MetadataItem({ text, hasSeparator }: MetadataItemProps) {\n  const { color } = useThemeContext();\n  return (\n    <>\n      <View style={[styles.metadataItem, { paddingBottom: vs(15) }]}>\n        <Txt txt={text} styles={[styles.metadataText, { color: color.TEXT }]} />\n      </View>\n      {hasSeparator && <Separator style={[styles.separator]} />}\n    </>\n  );\n}\n\nconst styles = ScaledSheet.create({\n  metadataItem: {\n    paddingHorizontal: \"20@s\",\n    marginBottom: \"5@vs\",\n  },\n  metadataText: {\n    fontSize: \"14@vs\",\n    lineHeight: \"20@vs\",\n    flexWrap: \"wrap\",\n    flexShrink: 1,\n    opacity: 0.8,\n  },\n  separator: {\n    marginBottom: \"15@vs\",\n  },\n});\n"
  },
  {
    "path": "src/screens/Mints/components/MintItem.tsx",
    "content": "import { ChevronRightIcon, ZapIcon } from \"@comps/Icons\";\nimport Separator from \"@comps/Separator\";\nimport Txt from \"@comps/Txt\";\nimport { formatMintUrl } from \"@util\";\nimport { useCurrencyContext } from \"@src/context/Currency\";\nimport { Text, TouchableOpacity, View } from \"react-native\";\nimport { s } from \"react-native-size-matters\";\nimport { globals, highlight as hi } from \"@styles\";\nimport type { NavigationProp } from \"@react-navigation/native\";\nimport type { RootStackParamList } from \"@model/nav\";\n\ninterface MintItemProps {\n  mint: {\n    mintUrl: string;\n    name?: string;\n    balance: number;\n  };\n  navigation: NavigationProp<RootStackParamList>;\n  isLast: boolean;\n  color: any;\n  highlight: string;\n  hidden: { balance: boolean };\n  t: (key: string) => string;\n  formatAmount: (sats: number) => { formatted: string; symbol: string };\n}\n\nconst styles = {\n  mintNameWrap: {\n    flexDirection: \"column\" as const,\n    alignItems: \"flex-start\" as const,\n  },\n  mintBal: {\n    flexDirection: \"row\" as const,\n    alignItems: \"center\" as const,\n    marginTop: 10,\n  },\n};\n\nexport default function MintItem({\n  mint,\n  navigation,\n  isLast,\n  color,\n  highlight,\n  hidden,\n  t,\n  formatAmount,\n}: MintItemProps) {\n  const { formatted, symbol } = formatAmount(mint.balance);\n\n  return (\n    <View key={mint.mintUrl}>\n      <TouchableOpacity\n        style={[globals().wrapRow, { paddingBottom: s(15) }]}\n        onPress={() => {\n          navigation.navigate(\"mintmanagement\", {\n            mint: {\n              mintUrl: mint.mintUrl,\n              customName: mint.name,\n            },\n            amount: mint.balance,\n            remainingMints: [],\n          });\n        }}\n      >\n        <View style={styles.mintNameWrap}>\n          <View\n            style={{\n              flexDirection: \"row\",\n              alignItems: \"center\",\n            }}\n          >\n            <Txt txt={mint.name || formatMintUrl(mint.mintUrl)} bold />\n          </View>\n          <View style={styles.mintBal}>\n            {mint.balance > 0 && <ZapIcon color={hi[highlight as keyof typeof hi]} />}\n            <Text\n              style={{\n                color: mint.balance > 0 ? color.TEXT : color.TEXT_SECONDARY,\n                marginLeft: mint.balance > 0 ? 5 : 0,\n                marginBottom: 5,\n              }}\n            >\n              {hidden.balance\n                ? \"****\"\n                : mint.balance > 0\n                  ? `${formatted} ${symbol}`\n                  : t(\"emptyMint\")}\n            </Text>\n          </View>\n        </View>\n        <ChevronRightIcon color={color.TEXT} />\n      </TouchableOpacity>\n      {!isLast && <Separator style={[{ marginBottom: s(15) }]} />}\n    </View>\n  );\n}\n"
  },
  {
    "path": "src/screens/Mints/index.ts",
    "content": "import AddMintScreen from \"./AddMintScreen\";\nimport MintHomeScreen from \"./MintHomeScreen\";\nimport MintSettingsScreen from \"./MintSettingsScreen\";\n\nexport { AddMintScreen, MintHomeScreen, MintSettingsScreen };\n"
  },
  {
    "path": "src/screens/Onboarding.tsx",
    "content": "import Logo from \"@comps/Logo\";\nimport RadioBtn from \"@comps/RadioBtn\";\nimport Txt from \"@comps/Txt\";\nimport type { TOnboardingPageProps } from \"@model/nav\";\nimport { NS } from \"@src/i18n\";\nimport { store } from \"@src/storage/store\";\nimport { STORE_KEYS } from \"@src/storage/store/consts\";\nimport { H_Colors, mainColors } from \"@styles/colors\";\nimport { useState } from \"react\";\nimport { useTranslation } from \"react-i18next\";\nimport { Image, TouchableOpacity, View } from \"react-native\";\nimport Onboarding from \"react-native-onboarding-swiper\";\nimport { s, ScaledSheet } from \"react-native-size-matters\";\n\nexport default function OnboardingScreen({ navigation }: TOnboardingPageProps) {\n  const { t } = useTranslation([NS.common]);\n  const [accepted, setAccepted] = useState(false);\n  const handleDone = async () => {\n    await store.set(STORE_KEYS.explainer, \"1\");\n    navigation.replace(\"dashboard\");\n  };\n  return (\n    <Onboarding\n      onDone={() => void handleDone()}\n      showDone={accepted}\n      showSkip={accepted}\n      showNext={accepted}\n      pages={[\n        {\n          backgroundColor: \"black\",\n          image: <Logo size={s(130)} />,\n          title: \"Alpha Testing\",\n          subtitle: (\n            <View\n              style={{\n                padding: s(10),\n                flexDirection: \"column\",\n                alignItems: \"center\",\n              }}\n            >\n              <Txt\n                txt=\"eNuts is currently in alpha testing. Please use at your own risk.\"\n                styles={[{ paddingHorizontal: s(10), textAlign: \"center\" }]}\n              />\n              <TouchableOpacity\n                style={{\n                  flexDirection: \"row\",\n                  alignItems: \"center\",\n                  marginTop: s(24),\n                }}\n                onPress={() => setAccepted((acpt) => !acpt)}\n                activeOpacity={0.7}\n                testID=\"onboarding-accept-checkbox\"\n              >\n                <View\n                  style={{\n                    width: s(10),\n                    borderWidth: 1,\n                    borderColor: \"white\",\n                    height: s(10),\n                    backgroundColor: accepted ? \"white\" : \"transparent\",\n                  }}\n                />\n                <Txt txt=\"I understand\" styles={[{ marginLeft: s(10) }]} />\n              </TouchableOpacity>\n            </View>\n          ),\n        },\n        {\n          backgroundColor: H_Colors.Default,\n          image: <Logo size={s(130)} />,\n          title: \"eNuts & Ecash\",\n          subtitle: t(\"explainer1\"),\n        },\n        {\n          backgroundColor: \"#8038CA\",\n\n          image: <Image style={styles.cashuImg} source={require(\"@assets/cashu.png\")} />,\n          title: \"Cashu & Mints\",\n          subtitle: t(\"explainer2\"),\n        },\n        {\n          backgroundColor: H_Colors.Nuts,\n\n          image: (\n            <Image style={styles.sendReceiveImg} source={require(\"@assets/send_receive.png\")} />\n          ),\n          title: t(\"send&receive\"),\n          subtitle: t(\"explainer3\"),\n        },\n      ]}\n      transitionAnimationDuration={250}\n      titleStyles={styles.title}\n      subTitleStyles={styles.subTitle}\n      nextLabel={t(\"next\")}\n      skipLabel={t(\"skip\")}\n      onSkip={() => void handleDone()}\n      DoneButtonComponent={() => (\n        <TouchableOpacity\n          onPress={() => void handleDone()}\n          style={{ marginRight: s(20) }}\n          testID=\"onboarding-done\"\n        >\n          <Txt txt={t(\"next\")} styles={[{ color: mainColors.WHITE }]} />\n        </TouchableOpacity>\n      )}\n    />\n  );\n}\n\nconst styles = ScaledSheet.create({\n  title: { fontSize: \"28@vs\", fontWeight: \"500\" },\n  subTitle: { fontSize: \"16@vs\" },\n  cashuImg: {\n    width: \"130@s\",\n    height: \"130@vs\",\n    resizeMode: \"contain\",\n  },\n  sendReceiveImg: {\n    width: \"300@s\",\n    height: \"170@vs\",\n    resizeMode: \"contain\",\n  },\n});\n"
  },
  {
    "path": "src/screens/Payment/MeltInput.tsx",
    "content": "import Button from \"@comps/Button\";\nimport AmountInput, { useShakeAnimation } from \"@comps/AmountInput\";\nimport useLoading from \"@comps/hooks/Loading\";\nimport Loading from \"@comps/Loading\";\nimport MintHeaderSelector from \"@comps/MintHeaderSelector\";\nimport Txt from \"@comps/Txt\";\nimport TxtInput from \"@comps/TxtInput\";\nimport { BoltIcon, ChevronRightIcon, CopyIcon } from \"@comps/Icons\";\nimport type { MeltOperation } from \"@cashu/coco-core\";\nimport { usePromptContext } from \"@src/context/Prompt\";\nimport { useThemeContext } from \"@src/context/Theme\";\nimport { NS } from \"@src/i18n\";\nimport { highlight as hi, mainColors } from \"@styles\";\nimport { formatMintUrl, getStrFromClipboard, isErr, vib } from \"@util\";\nimport { isLightningAddress, isLnurl } from \"@util/lnurl\";\nimport { useEffect, useState, useRef, useCallback, useMemo } from \"react\";\nimport { useTranslation } from \"react-i18next\";\nimport {\n  Animated,\n  Easing,\n  Keyboard,\n  ScrollView,\n  TextInput,\n  TouchableOpacity,\n  View,\n} from \"react-native\";\nimport { ScaledSheet } from \"react-native-size-matters\";\nimport MeltConfirmationModal, { type MeltConfirmationModalRef } from \"@modal/MeltConfirmationModal\";\n\nimport { useKnownMints, KnownMintWithBalance } from \"@src/context/KnownMints\";\nimport type { TBeforeRemoveEvent } from \"@model/nav\";\nimport { MeltInputProps } from \"@src/nav/navTypes\";\nimport Screen from \"@comps/Screen\";\nimport {\n  getInvoiceFromLnAddress,\n  requestLnurlPayMetadata,\n  type LnAddressMetadata,\n} from \"@src/util/lud16\";\nimport { useMeltOperation } from \"@cashu/coco-react\";\n\ntype TFinalizedMeltOperation = Extract<MeltOperation, { state: \"finalized\" }>;\ntype TMeltInputStep = \"request\" | \"amount\";\n\nexport default function MeltInputScreen({ navigation, route }: MeltInputProps) {\n  const { invoice } = route.params || {};\n  const { knownMints } = useKnownMints();\n  const {\n    cancel,\n    currentOperation,\n    execute,\n    isLoading: operationLoading,\n    prepare,\n    reset,\n  } = useMeltOperation();\n\n  const { loading, startLoading, stopLoading } = useLoading();\n\n  const [selectedMint, setSelectedMint] = useState<KnownMintWithBalance | null>(\n    knownMints.length > 0 ? knownMints[0] : null,\n  );\n  const [preparedOperation, setPreparedOperation] = useState<MeltOperation | null>(null);\n  const [preparedMint, setPreparedMint] = useState<KnownMintWithBalance | null>(null);\n  const [amountInput, setAmountInput] = useState(\"\");\n  const [amountErr, setAmountErr] = useState(false);\n  const [inputStep, setInputStep] = useState<TMeltInputStep>(\"request\");\n  const [lnAddress, setLnAddress] = useState(\"\");\n  const [lnAddressMetadata, setLnAddressMetadata] = useState<LnAddressMetadata | null>(null);\n\n  // Use refs for better performance\n  const inputRef = useRef<TextInput>(null);\n  const amountInputRef = useRef<TextInput>(null);\n  const meltConfirmationRef = useRef<MeltConfirmationModalRef>(null);\n  const hasNavigatedRef = useRef(false);\n  const hasCancelledRef = useRef(false);\n  const lnAddressAnim = useRef(new Animated.Value(0)).current;\n\n  const { t } = useTranslation([NS.common]);\n  const { openPromptAutoClose } = usePromptContext();\n  const { color, highlight } = useThemeContext();\n  const { shake } = useShakeAnimation();\n  const [input, setInput] = useState(invoice || \"\");\n  const trimmedInput = input.trim();\n  const isAmountStep = inputStep === \"amount\";\n  const displayOperation = currentOperation || preparedOperation;\n  const canCancelPreparedOperation = displayOperation?.state === \"prepared\";\n  const isBusy = loading || operationLoading;\n\n  const amountValue = useMemo(() => {\n    const parsed = parseInt(amountInput || \"0\", 10);\n    return Number.isNaN(parsed) ? 0 : parsed;\n  }, [amountInput]);\n\n  const isAmountInvalid = useMemo(() => {\n    if (!isAmountStep) {\n      return false;\n    }\n\n    const amountInMsats = amountValue * 1000;\n    const isAmountTooLow = amountValue < 1;\n    const isBelowMin =\n      !!lnAddressMetadata?.minSendable && lnAddressMetadata.minSendable > amountInMsats;\n    const isAboveMax =\n      !!lnAddressMetadata?.maxSendable && lnAddressMetadata.maxSendable < amountInMsats;\n\n    return isAmountTooLow || isBelowMin || isAboveMax;\n  }, [amountValue, isAmountStep, lnAddressMetadata]);\n\n  const minSendable = lnAddressMetadata?.minSendable;\n  const maxSendable = lnAddressMetadata?.maxSendable;\n  const shouldShowAmountLimits = isAmountStep && (!!minSendable || !!maxSendable);\n  const isContinueLoading = isBusy;\n  const isContinueDisabled =\n    isBusy ||\n    (isAmountStep ? !lnAddressMetadata || !amountValue || isAmountInvalid : !trimmedInput.length);\n\n  // Check if we have mints available\n  const noMintsAvailable = useMemo(() => {\n    return !selectedMint || knownMints.length === 0;\n  }, [selectedMint, knownMints.length]);\n\n  const handleMintSelect = useCallback(\n    (mint: KnownMintWithBalance) => {\n      setSelectedMint(mint);\n    },\n    [setSelectedMint],\n  );\n\n  const handleMintSelectorOpen = useCallback(() => {\n    inputRef.current?.blur();\n    amountInputRef.current?.blur();\n  }, []);\n\n  // Paste from clipboard\n  const handlePaste = async () => {\n    if (isAmountStep) {\n      return;\n    }\n\n    const clipboard = await getStrFromClipboard();\n    if (!clipboard) {\n      return;\n    }\n    setInput(clipboard);\n  };\n\n  const triggerAmountError = useCallback(() => {\n    vib(400);\n    setAmountErr(true);\n    shake();\n    const timeout = setTimeout(() => {\n      setAmountErr(false);\n      clearTimeout(timeout);\n    }, 500);\n  }, [shake]);\n\n  const showError = useCallback(\n    (error: unknown) => {\n      if (isErr(error)) {\n        openPromptAutoClose({ msg: error.message || t(\"invalidInvoice\") });\n        return;\n      }\n\n      console.error(error);\n      openPromptAutoClose({ msg: t(\"invalidInvoice\") });\n    },\n    [openPromptAutoClose, t],\n  );\n\n  const presentMeltConfirmation = useCallback(() => {\n    inputRef.current?.blur();\n    amountInputRef.current?.blur();\n    Keyboard.dismiss();\n\n    setTimeout(() => {\n      meltConfirmationRef.current?.present();\n    }, 0);\n  }, []);\n\n  const navigateToSuccess = useCallback(\n    (finalizedOperation: TFinalizedMeltOperation) => {\n      if (hasNavigatedRef.current) {\n        return;\n      }\n\n      hasNavigatedRef.current = true;\n      meltConfirmationRef.current?.close({ notifyCancel: false });\n\n      const mintName =\n        preparedMint?.mintInfo.name ||\n        preparedMint?.name ||\n        formatMintUrl(preparedMint?.mintUrl || finalizedOperation.mintUrl);\n\n      setPreparedOperation(null);\n      setPreparedMint(null);\n\n      navigation.navigate(\"successScreen\", {\n        type: \"melt\",\n        mint: mintName,\n        amount: finalizedOperation.amount,\n        fee: finalizedOperation.effectiveFee ?? finalizedOperation.fee_reserve,\n        change: finalizedOperation.changeAmount,\n      });\n    },\n    [navigation, preparedMint],\n  );\n\n  const cancelPreparedOperation = useCallback(async () => {\n    if (!canCancelPreparedOperation || operationLoading || hasCancelledRef.current) {\n      return true;\n    }\n\n    try {\n      hasCancelledRef.current = true;\n      await cancel();\n      setPreparedOperation(null);\n      setPreparedMint(null);\n      reset();\n      return true;\n    } catch (error) {\n      hasCancelledRef.current = false;\n      showError(error);\n      return false;\n    }\n  }, [canCancelPreparedOperation, cancel, operationLoading, reset, showError]);\n\n  const handleOperationCancel = useCallback(async () => {\n    const didCancel = await cancelPreparedOperation();\n    if (!didCancel) {\n      presentMeltConfirmation();\n    }\n  }, [cancelPreparedOperation, presentMeltConfirmation]);\n\n  const handleBackToDashboard = useCallback(() => {\n    navigation.navigate(\"dashboard\");\n  }, [navigation]);\n\n  const handleCancelLnAddress = useCallback(() => {\n    amountInputRef.current?.blur();\n    Keyboard.dismiss();\n    setInputStep(\"request\");\n    setLnAddress(\"\");\n    setLnAddressMetadata(null);\n    setAmountInput(\"\");\n    setAmountErr(false);\n  }, []);\n\n  const handleBack = useCallback(() => {\n    if (displayOperation) {\n      meltConfirmationRef.current?.close({ notifyCancel: true });\n      return;\n    }\n\n    if (isAmountStep) {\n      handleCancelLnAddress();\n      return;\n    }\n\n    navigation.goBack();\n  }, [displayOperation, handleCancelLnAddress, isAmountStep, navigation]);\n\n  const handleOperationConfirm = useCallback(async () => {\n    if (!displayOperation) {\n      return;\n    }\n\n    try {\n      await execute();\n    } catch (error) {\n      showError(error);\n    }\n  }, [displayOperation, execute, showError]);\n\n  const prepareMelt = useCallback(\n    async (invoiceToPrepare: string, currentMint: KnownMintWithBalance) => {\n      const operation = await prepare({\n        mintUrl: currentMint.mintUrl,\n        method: \"bolt11\",\n        methodData: { invoice: invoiceToPrepare },\n      });\n\n      hasCancelledRef.current = false;\n      hasNavigatedRef.current = false;\n      setPreparedMint(currentMint);\n      setPreparedOperation(operation);\n      presentMeltConfirmation();\n    },\n    [prepare, presentMeltConfirmation],\n  );\n\n  const handleBtnPress = async () => {\n    const currentMint = selectedMint;\n    if (isBusy || !currentMint) {\n      return;\n    }\n\n    if (isAmountStep) {\n      if (!lnAddressMetadata || isAmountInvalid) {\n        triggerAmountError();\n        return;\n      }\n\n      startLoading();\n      try {\n        const invoiceToPrepare = await getInvoiceFromLnAddress(\n          lnAddressMetadata,\n          amountValue * 1000,\n        );\n        await prepareMelt(invoiceToPrepare, currentMint);\n      } catch (e) {\n        return openPromptAutoClose({ msg: t(\"invalidInvoice\") });\n      } finally {\n        stopLoading();\n      }\n      return;\n    }\n\n    // user pasted an encoded LNURL, we need to get the amount by the user\n    if (isLnurl(trimmedInput)) {\n      startLoading();\n      try {\n        const metadata = await requestLnurlPayMetadata(trimmedInput);\n        setLnAddress(trimmedInput);\n        setLnAddressMetadata(metadata);\n        setAmountInput(\"\");\n        setAmountErr(false);\n        setInputStep(\"amount\");\n        inputRef.current?.blur();\n      } catch (e) {\n        return openPromptAutoClose({ msg: t(\"invalidInvoice\") });\n      } finally {\n        stopLoading();\n      }\n\n      return;\n    }\n\n    if (isLightningAddress(trimmedInput)) {\n      startLoading();\n      try {\n        const metadata = await requestLnurlPayMetadata(trimmedInput);\n        setLnAddress(trimmedInput);\n        setLnAddressMetadata(metadata);\n        setAmountInput(\"\");\n        setAmountErr(false);\n        setInputStep(\"amount\");\n        inputRef.current?.blur();\n      } catch (e) {\n        return openPromptAutoClose({ msg: t(\"invalidInvoice\") });\n      } finally {\n        stopLoading();\n      }\n\n      return;\n    }\n\n    startLoading();\n    try {\n      await prepareMelt(trimmedInput, currentMint);\n    } catch (e) {\n      return openPromptAutoClose({ msg: t(\"invalidInvoice\") });\n    } finally {\n      stopLoading();\n    }\n  };\n\n  const lnAddressMotionStyle = {\n    opacity: lnAddressAnim,\n    transform: [\n      {\n        translateY: lnAddressAnim.interpolate({\n          inputRange: [0, 1],\n          outputRange: [10, 0],\n        }),\n      },\n    ],\n  };\n\n  useEffect(() => {\n    if (!isAmountStep) {\n      lnAddressAnim.setValue(0);\n      return;\n    }\n\n    Animated.timing(lnAddressAnim, {\n      toValue: 1,\n      duration: 180,\n      easing: Easing.out(Easing.cubic),\n      useNativeDriver: true,\n    }).start();\n  }, [isAmountStep, lnAddressAnim]);\n\n  useEffect(() => {\n    if (currentOperation?.state === \"finalized\") {\n      navigateToSuccess(currentOperation);\n    }\n  }, [currentOperation, navigateToSuccess]);\n\n  useEffect(() => {\n    const handleBeforeRemove = (e: TBeforeRemoveEvent) => {\n      if (!canCancelPreparedOperation || hasCancelledRef.current) {\n        return;\n      }\n\n      e.preventDefault();\n\n      if (operationLoading) {\n        return;\n      }\n\n      void cancelPreparedOperation().then((didCancel) => {\n        if (didCancel) {\n          navigation.dispatch(e.data.action);\n        }\n      });\n    };\n\n    return navigation.addListener(\"beforeRemove\", handleBeforeRemove);\n  }, [canCancelPreparedOperation, cancelPreparedOperation, navigation, operationLoading]);\n\n  // auto-focus keyboard\n  useEffect(() => {\n    const t = setTimeout(() => {\n      inputRef.current?.focus();\n      clearTimeout(t);\n    }, 200);\n    // eslint-disable-next-line react-hooks/exhaustive-deps\n  }, []);\n\n  // Early return if no mints available\n  if (noMintsAvailable) {\n    return (\n      <Screen\n        screenName={t(\"cashOut\")}\n        withBackBtn\n        handlePress={handleBack}\n        withCancelBtn\n        withPadding={true}\n      >\n        <View\n          style={{\n            flex: 1,\n            justifyContent: \"center\",\n            alignItems: \"center\",\n          }}\n        >\n          <Txt txt={t(\"noMintsWithBalance\", { ns: NS.common })} />\n        </View>\n      </Screen>\n    );\n  }\n\n  return (\n    <Screen\n      screenName={t(\"cashOut\")}\n      withBackBtn\n      handlePress={handleBack}\n      withPadding={true}\n      withBottomInset={false}\n      withKeyboard={true}\n      rightAction={\n        <MintHeaderSelector\n          selectedMint={selectedMint!}\n          onMintSelect={handleMintSelect}\n          onOpen={handleMintSelectorOpen}\n        />\n      }\n    >\n      <ScrollView\n        style={styles.formScroll}\n        contentContainerStyle={styles.contentContainer}\n        keyboardShouldPersistTaps=\"handled\"\n        showsVerticalScrollIndicator={false}\n      >\n        {!isAmountStep ? (\n          <View\n            key=\"request-input\"\n            style={[\n              styles.inputSurface,\n              {\n                backgroundColor: color.DRAWER,\n                borderColor: color.BORDER,\n              },\n            ]}\n          >\n            <View style={styles.inputRow}>\n              <TxtInput\n                innerRef={inputRef}\n                keyboardType=\"email-address\"\n                autoCapitalize=\"none\"\n                autoCorrect={false}\n                placeholder={t(\"invoiceOrLnAddress\")}\n                value={input}\n                onChangeText={(text) => {\n                  setInput(text);\n                }}\n                onSubmitEditing={() => void handleBtnPress()}\n                autoFocus\n                ms={200}\n                style={styles.inputField}\n              />\n              <TouchableOpacity\n                accessibilityRole=\"button\"\n                accessibilityLabel={t(\"paste\")}\n                activeOpacity={0.7}\n                onPress={() => void handlePaste()}\n                style={[\n                  styles.pasteButton,\n                  {\n                    backgroundColor: color.INPUT_BG,\n                    borderColor: color.BORDER,\n                  },\n                ]}\n              >\n                <CopyIcon width={18} height={18} color={hi[highlight]} />\n              </TouchableOpacity>\n            </View>\n          </View>\n        ) : (\n          <Animated.View\n            key=\"ln-address-amount\"\n            style={[\n              styles.lnAddressPanel,\n              {\n                backgroundColor: color.DRAWER,\n                borderColor: color.BORDER,\n              },\n              lnAddressMotionStyle,\n            ]}\n          >\n            <View style={styles.panelHeader}>\n              <View style={[styles.panelIcon, { backgroundColor: color.INPUT_BG }]}>\n                <BoltIcon width={18} height={18} color={hi[highlight]} />\n              </View>\n              <View style={styles.panelCopy}>\n                <Txt txt={t(\"amount\", { ns: NS.common })} bold styles={[styles.panelTitle]} />\n                <Txt\n                  txt={lnAddress}\n                  styles={[styles.addressText, { color: color.TEXT_SECONDARY }]}\n                />\n              </View>\n              <TouchableOpacity\n                accessibilityRole=\"button\"\n                accessibilityLabel={t(\"cancel\", { ns: NS.common })}\n                activeOpacity={0.7}\n                onPress={handleCancelLnAddress}\n                style={[\n                  styles.cancelButton,\n                  {\n                    backgroundColor: color.INPUT_BG,\n                    borderColor: color.BORDER,\n                  },\n                ]}\n              >\n                <Txt\n                  txt={t(\"cancel\", { ns: NS.common })}\n                  bold\n                  styles={[styles.cancelText, { color: hi[highlight] }]}\n                />\n              </TouchableOpacity>\n            </View>\n\n            <View style={styles.amountStage}>\n              <View style={[styles.amountDivider, { backgroundColor: color.DARK_BORDER }]} />\n              <AmountInput\n                ref={amountInputRef}\n                value={amountInput}\n                onChange={setAmountInput}\n                onSubmit={handleBtnPress}\n                error={amountErr}\n                autoFocus\n                compact\n                testID=\"melt-ln-address-amount-input\"\n              />\n            </View>\n\n            {shouldShowAmountLimits ? (\n              <View style={[styles.amountRangeSection, { borderTopColor: color.DARK_BORDER }]}>\n                <Txt\n                  txt={t(\"amountLimits\", { ns: NS.common })}\n                  bold\n                  styles={[styles.rangeTitle, { color: color.TEXT }]}\n                />\n                <View style={styles.rangeGrid}>\n                  {minSendable ? (\n                    <View style={[styles.rangeItem, { backgroundColor: color.INPUT_BG }]}>\n                      <Txt\n                        txt=\"Min\"\n                        styles={[styles.rangeLabel, { color: color.TEXT_SECONDARY }]}\n                      />\n                      <Txt\n                        txt={`${Math.floor(minSendable / 1000)} sats`}\n                        styles={[styles.rangeValue]}\n                      />\n                    </View>\n                  ) : null}\n                  {maxSendable ? (\n                    <View style={[styles.rangeItem, { backgroundColor: color.INPUT_BG }]}>\n                      <Txt\n                        txt=\"Max\"\n                        styles={[styles.rangeLabel, { color: color.TEXT_SECONDARY }]}\n                      />\n                      <Txt\n                        txt={`${Math.floor(maxSendable / 1000)} sats`}\n                        styles={[styles.rangeValue]}\n                      />\n                    </View>\n                  ) : null}\n                </View>\n              </View>\n            ) : null}\n          </Animated.View>\n        )}\n\n        <View style={styles.actionWrap}>\n          <Button\n            disabled={isContinueDisabled}\n            txt={t(\"continue\")}\n            onPress={() => void handleBtnPress()}\n            icon={\n              isContinueLoading ? (\n                <Loading size={20} />\n              ) : (\n                <ChevronRightIcon color={mainColors.WHITE} />\n              )\n            }\n          />\n        </View>\n      </ScrollView>\n\n      {displayOperation ? (\n        <MeltConfirmationModal\n          ref={meltConfirmationRef}\n          operation={displayOperation}\n          mint={preparedMint}\n          loading={operationLoading}\n          onConfirm={() => void handleOperationConfirm()}\n          onCancel={() => void handleOperationCancel()}\n          onBackToDashboard={handleBackToDashboard}\n        />\n      ) : null}\n    </Screen>\n  );\n}\n\nconst styles = ScaledSheet.create({\n  contentContainer: {\n    flexGrow: 1,\n    gap: \"12@vs\",\n    paddingTop: \"6@vs\",\n    paddingBottom: \"14@vs\",\n  },\n  formScroll: {\n    flex: 1,\n  },\n  inputSurface: {\n    borderRadius: \"28@s\",\n    borderWidth: 1,\n    paddingHorizontal: \"18@s\",\n    paddingVertical: \"18@vs\",\n  },\n  inputRow: {\n    flexDirection: \"row\",\n    alignItems: \"center\",\n    gap: \"12@s\",\n  },\n  inputField: {\n    flex: 1,\n    width: \"auto\",\n    backgroundColor: \"transparent\",\n    borderRadius: 0,\n    paddingHorizontal: 0,\n    paddingVertical: \"4@vs\",\n    fontSize: \"16@ms\",\n  },\n  pasteButton: {\n    width: \"42@s\",\n    height: \"42@s\",\n    borderRadius: \"21@s\",\n    borderWidth: 1,\n    alignItems: \"center\",\n    justifyContent: \"center\",\n  },\n  lnAddressPanel: {\n    borderRadius: \"24@s\",\n    borderWidth: 1,\n    paddingHorizontal: \"16@s\",\n    paddingVertical: \"14@vs\",\n  },\n  panelHeader: {\n    flexDirection: \"row\",\n    alignItems: \"center\",\n    gap: \"12@s\",\n  },\n  panelIcon: {\n    width: \"34@s\",\n    height: \"34@s\",\n    borderRadius: \"17@s\",\n    alignItems: \"center\",\n    justifyContent: \"center\",\n  },\n  panelCopy: {\n    flex: 1,\n    gap: \"3@vs\",\n  },\n  panelTitle: {\n    fontSize: \"14@ms\",\n  },\n  cancelButton: {\n    borderRadius: \"16@s\",\n    borderWidth: 1,\n    paddingHorizontal: \"10@s\",\n    paddingVertical: \"7@vs\",\n  },\n  cancelText: {\n    fontSize: \"11@ms\",\n  },\n  amountStage: {\n    width: \"100%\",\n    paddingTop: \"6@vs\",\n  },\n  amountDivider: {\n    height: 1,\n    width: \"100%\",\n    marginBottom: \"1@vs\",\n  },\n  addressText: {\n    fontSize: \"12@ms\",\n    lineHeight: \"17@vs\",\n    flexShrink: 1,\n  },\n  amountRangeSection: {\n    gap: \"8@vs\",\n    paddingTop: \"10@vs\",\n    borderTopWidth: 1,\n  },\n  rangeTitle: {\n    fontSize: \"12@ms\",\n  },\n  rangeGrid: {\n    flexDirection: \"row\",\n    gap: \"10@s\",\n  },\n  rangeItem: {\n    flex: 1,\n    gap: \"2@vs\",\n    borderRadius: \"14@s\",\n    paddingHorizontal: \"10@s\",\n    paddingVertical: \"8@vs\",\n  },\n  rangeLabel: {\n    fontSize: \"10@ms\",\n    textTransform: \"uppercase\",\n  },\n  rangeValue: {\n    fontSize: \"13@ms\",\n  },\n  actionWrap: {\n    width: \"100%\",\n    marginTop: \"auto\",\n    paddingTop: \"14@vs\",\n  },\n});\n"
  },
  {
    "path": "src/screens/Payment/MintSelectAmount.tsx",
    "content": "import AmountInput, { useShakeAnimation } from \"@comps/AmountInput\";\nimport Button from \"@comps/Button\";\nimport { ChevronRightIcon } from \"@comps/Icons\";\nimport MintHeaderSelector from \"@comps/MintHeaderSelector\";\nimport Screen from \"@comps/Screen\";\nimport Txt from \"@comps/Txt\";\nimport { useKnownMints } from \"@src/context/KnownMints\";\nimport type { KnownMintWithBalance } from \"@src/context/KnownMints\";\nimport { NS } from \"@src/i18n\";\nimport { mainColors } from \"@styles\";\nimport { vib } from \"@util\";\nimport { useCurrencyContext } from \"@src/context/Currency\";\nimport { useCallback, useEffect, useRef, useState, useMemo } from \"react\";\nimport { useTranslation } from \"react-i18next\";\nimport { Keyboard, TextInput, View } from \"react-native\";\nimport { ScaledSheet } from \"react-native-size-matters\";\nimport { useManager } from \"@src/context/Manager\";\nimport type { MintSelectAmountProps } from \"@src/nav/navTypes\";\nimport { useThemeContext } from \"@src/context/Theme\";\nimport useLoading from \"@comps/hooks/Loading\";\n\nexport default function MintSelectAmountScreen({ navigation }: MintSelectAmountProps) {\n  const { t } = useTranslation([NS.wallet, NS.common]);\n  const { shake } = useShakeAnimation();\n  const { knownMints } = useKnownMints();\n  const { loading, startLoading, stopLoading } = useLoading();\n  const manager = useManager();\n  const amountInputRef = useRef<TextInput>(null);\n\n  const [amountInput, setAmountInput] = useState(\"\");\n\n  const [selectedMint, setSelectedMint] = useState<KnownMintWithBalance | null>(\n    knownMints[0] ?? null,\n  );\n\n  useEffect(() => {\n    setSelectedMint((currentMint) => {\n      const updatedMint = currentMint\n        ? knownMints.find((mint) => mint.mintUrl === currentMint.mintUrl)\n        : null;\n\n      return updatedMint ?? knownMints[0] ?? null;\n    });\n  }, [knownMints]);\n\n  const noMintsAvailable = useMemo(() => {\n    return !selectedMint || knownMints.length === 0;\n  }, [selectedMint, knownMints.length]);\n\n  const [err, setErr] = useState(false);\n\n  const amountValue = useMemo(() => {\n    const parsed = parseInt(amountInput || \"0\", 10);\n    return Number.isNaN(parsed) ? 0 : parsed;\n  }, [amountInput]);\n\n  const screenName = \"createInvoice\";\n\n  const handleBack = useCallback(() => navigation.goBack(), [navigation]);\n\n  const handleMintSelect = useCallback(\n    (mint: KnownMintWithBalance) => {\n      setSelectedMint(mint);\n    },\n    [setSelectedMint],\n  );\n\n  const handleMintSelectorOpen = useCallback(() => {\n    amountInputRef.current?.blur();\n  }, []);\n\n  const triggerAmountError = useCallback(() => {\n    vib(400);\n    setErr(true);\n    shake();\n    const timeout = setTimeout(() => {\n      setErr(false);\n      clearTimeout(timeout);\n    }, 500);\n  }, [shake]);\n\n  const handleSubmit = useCallback(async () => {\n    if (loading || !selectedMint) {\n      return;\n    }\n\n    if (!amountValue || amountValue < 1) {\n      triggerAmountError();\n      return;\n    }\n\n    startLoading();\n    try {\n      const operation = await manager.ops.mint.prepare({\n        mintUrl: selectedMint.mintUrl,\n        amount: amountValue,\n        method: \"bolt11\",\n      });\n      amountInputRef.current?.blur();\n      Keyboard.dismiss();\n      return navigation.navigate(\"mintInvoice\", {\n        mintUrl: selectedMint.mintUrl,\n        operation,\n      });\n    } catch (error) {\n      console.error(error);\n    } finally {\n      stopLoading();\n    }\n  }, [\n    amountValue,\n    loading,\n    manager,\n    navigation,\n    selectedMint,\n    startLoading,\n    stopLoading,\n    triggerAmountError,\n  ]);\n\n  // Early return after all hooks\n  if (noMintsAvailable) {\n    return (\n      <Screen\n        screenName={t(\"selectAmount\", { ns: NS.common })}\n        withBackBtn\n        handlePress={handleBack}\n        withPadding={true}\n      >\n        <View\n          style={{\n            flex: 1,\n            justifyContent: \"center\",\n            alignItems: \"center\",\n          }}\n        >\n          <Txt txt={t(\"noMintsWithBalance\", { ns: NS.common })} />\n        </View>\n      </Screen>\n    );\n  }\n\n  return (\n    <Screen\n      screenName={t(screenName, { ns: NS.common })}\n      withBackBtn\n      handlePress={handleBack}\n      withPadding={false}\n      withBottomInset={false}\n      withKeyboard={true}\n      rightAction={\n        <MintHeaderSelector\n          selectedMint={selectedMint!}\n          onMintSelect={handleMintSelect}\n          onOpen={handleMintSelectorOpen}\n          showZeroBalanceMints\n        />\n      }\n    >\n      <AmountInput\n        ref={amountInputRef}\n        value={amountInput}\n        onChange={setAmountInput}\n        onSubmit={handleSubmit}\n        error={err}\n        autoFocus\n        testID=\"mint-amount-input\"\n      />\n\n      <View style={styles.actionWrap}>\n        <Button\n          txt={t(\"continue\", { ns: NS.common })}\n          onPress={handleSubmit}\n          icon={<ChevronRightIcon color={mainColors.WHITE} />}\n          loading={loading}\n        />\n      </View>\n    </Screen>\n  );\n}\n\ninterface IMeltOverviewProps {\n  amount: number;\n  shouldEstimate?: boolean;\n  balTooLow?: boolean;\n  isInvoice?: boolean;\n  fee: number;\n}\n\nexport function MeltOverview({\n  amount,\n  shouldEstimate,\n  balTooLow,\n  isInvoice,\n  fee,\n}: IMeltOverviewProps) {\n  const { t } = useTranslation([NS.common]);\n  const { color } = useThemeContext();\n  const { formatAmount } = useCurrencyContext();\n  const total = shouldEstimate ? 0 : amount + fee;\n  const { formatted, symbol } = formatAmount(total);\n\n  return (\n    <View style={styles.overview}>\n      <Txt\n        txt={\n          t(isInvoice ? \"invoiceInclFee\" : \"totalInclFee\", {\n            ns: NS.common,\n          }) + \"*\"\n        }\n        bold\n      />\n      <Txt\n        txt={`${formatted} ${symbol}`}\n        styles={[\n          {\n            color:\n              !shouldEstimate && balTooLow\n                ? mainColors.ERROR\n                : shouldEstimate\n                  ? color.TEXT\n                  : mainColors.VALID,\n          },\n        ]}\n      />\n    </View>\n  );\n}\n\nconst styles = ScaledSheet.create({\n  overview: {\n    flexDirection: \"row\",\n    alignItems: \"center\",\n    justifyContent: \"space-between\",\n  },\n  actionWrap: {\n    flex: 1,\n    width: \"100%\",\n    justifyContent: \"flex-end\",\n    paddingHorizontal: \"20@s\",\n    paddingBottom: \"10@vs\",\n  },\n});\n"
  },
  {
    "path": "src/screens/Payment/Processing.tsx",
    "content": "import { getDecodedToken } from \"@cashu/cashu-ts\";\nimport Loading from \"@comps/Loading\";\nimport Txt from \"@comps/Txt\";\nimport type { TBeforeRemoveEvent, TProcessingPageProps } from \"@model/nav\";\nimport { preventBack } from \"@nav/utils\";\nimport { useInitialURL } from \"@src/context/Linking\";\nimport { useThemeContext } from \"@src/context/Theme\";\nimport { NS } from \"@src/i18n\";\nimport { globals } from \"@styles\";\nimport { decodeLnInvoice, isErr } from \"@util\";\nimport { useEffect, useMemo } from \"react\";\nimport { useTranslation } from \"react-i18next\";\nimport { View } from \"react-native\";\nimport { s, ScaledSheet } from \"react-native-size-matters\";\n\ninterface IErrorProps {\n  e?: unknown;\n  customMsg?: \"requestMintErr\" | \"generalMeltingErr\" | \"invoiceFromLnurlError\";\n}\n\nexport default function ProcessingScreen({ navigation, route }: TProcessingPageProps) {\n  const { t } = useTranslation([NS.mints]);\n  const { color } = useThemeContext();\n  const { clearUrl } = useInitialURL();\n  const {\n    mint,\n    tokenInfo,\n    amount,\n    memo,\n    estFee,\n    isMelt,\n    isSendEcash,\n    isSwap,\n    isAutoSwap,\n    isZap,\n    payZap,\n    targetMint,\n    proofs,\n    recipient,\n  } = route.params;\n\n  const processingTxt = useMemo(() => {\n    if (isMelt) {\n      return payZap ? \"payingInvoice\" : \"meltingToken\";\n    }\n    if (isSwap || isAutoSwap) {\n      return \"swapping\";\n    }\n    if (isSendEcash) {\n      return \"sendingEcash\";\n    }\n    if (isZap) {\n      return \"payingInvoice\";\n    }\n    return \"claimingToken\";\n  }, [isMelt, isSwap, isZap, payZap, isSendEcash, isAutoSwap]);\n\n  const handleError = ({ e, customMsg }: IErrorProps) => {\n    clearUrl();\n    navigation.navigate(\"processingError\", {\n      errorMsg: customMsg\n        ? t(customMsg, { ns: NS.error })\n        : isErr(e)\n          ? e.message\n          : t(\"generalMeltingErr\", { ns: NS.error }),\n    });\n  };\n\n  // prevent back navigation - https://reactnavigation.org/docs/preventing-going-back/\n  useEffect(() => {\n    const backHandler = (e: TBeforeRemoveEvent) => preventBack(e, navigation.dispatch);\n    navigation.addListener(\"beforeRemove\", backHandler);\n    return () => navigation.removeListener(\"beforeRemove\", backHandler);\n  }, [navigation]);\n\n  return (\n    <View style={[globals(color).container, styles.container]}>\n      <Txt txt={t(processingTxt, { ns: NS.wallet })} styles={[{ color: color.TEXT }]} />\n      <Loading size={s(35)} />\n    </View>\n  );\n}\n\nconst styles = ScaledSheet.create({\n  container: {\n    paddingTop: 0,\n    alignItems: \"center\",\n    justifyContent: \"center\",\n    paddingHorizontal: \"20@s\",\n  },\n  descText: {\n    marginTop: \"20@vs\",\n    textAlign: \"center\",\n  },\n  hint: {\n    fontSize: \"12@vs\",\n    marginTop: \"10@vs\",\n  },\n});\n"
  },
  {
    "path": "src/screens/Payment/ProcessingError.tsx",
    "content": "import Button from \"@comps/Button\";\nimport { ExclamationIcon } from \"@comps/Icons\";\nimport Txt from \"@comps/Txt\";\nimport type { TBeforeRemoveEvent, TProcessingErrorPageProps } from \"@model/nav\";\nimport { preventBack } from \"@nav/utils\";\nimport { isIOS } from \"@src/consts\";\nimport { useThemeContext } from \"@src/context/Theme\";\nimport { NS } from \"@src/i18n\";\nimport TrustMintBottomSheet, { type TrustMintBottomSheetRef } from \"@modal/TrustMintBottomSheet\";\nimport { globals, mainColors } from \"@styles\";\nimport { useEffect, useRef } from \"react\";\nimport { useTranslation } from \"react-i18next\";\nimport { View } from \"react-native\";\nimport { s, ScaledSheet, vs } from \"react-native-size-matters\";\n\nconst alreadySpentErr = \"Token already spent.\";\n\nexport default function ProcessingErrorScreen({ navigation, route }: TProcessingErrorPageProps) {\n  const { scan, comingFromOnboarding, errorMsg } = route.params;\n\n  const { t } = useTranslation([NS.common]);\n  const { color } = useThemeContext();\n  const trustMintRef = useRef<TrustMintBottomSheetRef>(null);\n\n  // prevent back navigation - https://reactnavigation.org/docs/preventing-going-back/\n  useEffect(() => {\n    const backHandler = (e: TBeforeRemoveEvent) => preventBack(e, navigation.dispatch);\n    navigation.addListener(\"beforeRemove\", backHandler);\n    return () => navigation.removeListener(\"beforeRemove\", backHandler);\n  }, [navigation]);\n\n  return (\n    <View style={[globals(color).container, styles.container]}>\n      <View />\n      <View style={styles.section}>\n        <ExclamationIcon width={s(60)} height={s(60)} color={mainColors.ERROR} />\n        <Txt\n          txt={errorMsg}\n          bold\n          center\n          styles={[\n            {\n              color: mainColors.ERROR,\n              marginVertical: vs(15),\n              fontSize: vs(18),\n            },\n          ]}\n        />\n        {!scan && errorMsg !== alreadySpentErr && (\n          <Txt center styles={[styles.hint, { color: color.TEXT_SECONDARY }]} txt={t(\"tryLater\")} />\n        )}\n        {errorMsg === alreadySpentErr && (\n          <Txt\n            center\n            styles={[styles.hint, { color: color.TEXT_SECONDARY }]}\n            txt={t(\"alreadySpentHint\")}\n          />\n        )}\n      </View>\n      <View style={{ width: \"100%\" }}>\n        <Button\n          outlined={scan}\n          txt={t(\"backToDashboard\")}\n          onPress={() => {\n            navigation.navigate(\"dashboard\");\n          }}\n        />\n        <TrustMintBottomSheet ref={trustMintRef} />\n      </View>\n    </View>\n  );\n}\n\nconst styles = ScaledSheet.create({\n  container: {\n    paddingTop: 0,\n    alignItems: \"center\",\n    justifyContent: \"space-between\",\n    paddingHorizontal: \"20@s\",\n    paddingBottom: isIOS ? \"40@s\" : \"20@s\",\n  },\n  section: {\n    alignItems: \"center\",\n  },\n  errMsg: {\n    color: mainColors.ERROR,\n    marginVertical: \"15@vs\",\n    fontSize: \"18@vs\",\n  },\n  hint: {\n    fontSize: \"14@vs\",\n    marginTop: \"10@vs\",\n  },\n});\n"
  },
  {
    "path": "src/screens/Payment/Receive/Invoice.tsx",
    "content": "import Button from \"@comps/Button\";\nimport { ShareIcon } from \"@comps/Icons\";\nimport Loading from \"@comps/Loading\";\nimport QR from \"@comps/QR\";\nimport Txt from \"@comps/Txt\";\nimport { isIOS } from \"@consts\";\nimport { l } from \"@log\";\nimport type { TMintInvoicePageProps } from \"@model/nav\";\nimport Screen from \"@comps/Screen\";\nimport { useFocusEffect } from \"@react-navigation/native\";\nimport { useManager } from \"@src/context/Manager\";\nimport { useThemeContext } from \"@src/context/Theme\";\nimport { NS } from \"@src/i18n\";\nimport { globals } from \"@styles\";\nimport { getColor } from \"@styles/colors\";\nimport { formatMintUrl, share } from \"@util\";\nimport { useCallback } from \"react\";\nimport { useTranslation } from \"react-i18next\";\nimport { View } from \"react-native\";\nimport { s, ScaledSheet, vs } from \"react-native-size-matters\";\n\nexport default function InvoiceScreen({ navigation, route }: TMintInvoicePageProps) {\n  const { operation } = route.params;\n  const { t } = useTranslation([NS.common]);\n  const { color, highlight } = useThemeContext();\n  const manager = useManager();\n\n  useFocusEffect(\n    useCallback(() => {\n      const handlePaidInvoice = ({\n        operation: finalizedOperation,\n      }: {\n        operation: { id: string };\n      }) => {\n        if (finalizedOperation.id !== operation.id) {\n          return;\n        }\n\n        navigation.navigate(\"successScreen\", {\n          type: \"receive\",\n          amount: operation.amount,\n        });\n      };\n\n      manager.on(\"mint-op:finalized\", handlePaidInvoice);\n      return () => manager.off(\"mint-op:finalized\", handlePaidInvoice);\n    }, [manager, navigation, operation.amount, operation.id]),\n  );\n\n  return (\n    <Screen\n      screenName={t(\"payInvoice\", { ns: NS.wallet })}\n      withCancelBtn\n      handleCancel={() => {\n        console.log(\"handleCancel\");\n        navigation.navigate(\"dashboard\");\n      }}\n    >\n      <View style={styles.container}>\n        <View style={styles.content}>\n          <QR\n            size={vs(250)}\n            value={operation.request}\n            onError={() => l(\"Error while generating the LN QR code\")}\n            isInvoice\n            animate={false}\n          />\n          <View>\n            <View style={styles.awaitingWrap}>\n              <Txt\n                txt={t(\"paymentPending\") + \"...\"}\n                styles={[{ fontWeight: \"500\", marginRight: s(10) }]}\n              />\n              <Loading />\n            </View>\n          </View>\n          <Button\n            txt={t(\"shareInvoice\")}\n            onPress={() => void share(operation.request)}\n            icon={<ShareIcon color={getColor(highlight, color)} />}\n            outlined\n          />\n          {isIOS && <View style={styles.placeholder} />}\n        </View>\n      </View>\n    </Screen>\n  );\n}\n\nconst styles = ScaledSheet.create({\n  container: {\n    flex: 1,\n    paddingHorizontal: \"20@s\",\n    paddingBottom: \"20@s\",\n  },\n  content: {\n    flex: 1,\n    alignItems: \"center\",\n    justifyContent: \"space-between\",\n  },\n  lnExpiry: {\n    fontSize: \"34@vs\",\n    fontWeight: \"600\",\n    textAlign: \"center\",\n  },\n  awaitingWrap: {\n    flexDirection: \"row\",\n    alignItems: \"center\",\n    justifyContent: \"center\",\n    marginTop: \"5@vs\",\n  },\n  placeholder: {\n    height: \"20@vs\",\n  },\n});\n"
  },
  {
    "path": "src/screens/Payment/Send/CoinSelection.tsx",
    "content": "import Separator from \"@comps/Separator\";\nimport SwipeButton from \"@comps/SwipeButton\";\nimport Txt from \"@comps/Txt\";\nimport { _testmintUrl } from \"@consts\";\nimport type { IProofSelection } from \"@model\";\nimport type { TCoinSelectionPageProps } from \"@model/nav\";\nimport Screen from \"@comps/Screen\";\n// Helper functions to replace nostr utilities\nfunction truncateStr(str: string, len: number): string {\n  if (str.length <= len) return str;\n  return str.slice(0, len) + \"...\";\n}\nimport { useInitialURL } from \"@src/context/Linking\";\nimport { useThemeContext } from \"@src/context/Theme\";\nimport { useCurrencyContext } from \"@src/context/Currency\";\nimport { NS } from \"@src/i18n\";\nimport TrustMintBottomSheet, { type TrustMintBottomSheetRef } from \"@modal/TrustMintBottomSheet\";\nimport { globals } from \"@styles\";\nimport { formatMintUrl, getSelectedAmount, isNum } from \"@util\";\nimport { isLightningAddress } from \"@util/lnurl\";\nimport { useEffect, useRef, useState } from \"react\";\nimport { useTranslation } from \"react-i18next\";\nimport { ScrollView, View } from \"react-native\";\nimport { useSafeAreaInsets } from \"react-native-safe-area-context\";\nimport { s, ScaledSheet } from \"react-native-size-matters\";\nimport { OverviewRow } from \"@comps/OverviewRow\";\n\nexport default function CoinSelectionScreen({ navigation, route }: TCoinSelectionPageProps) {\n  const {\n    mint,\n    balance,\n    amount,\n    memo,\n    estFee,\n    recipient,\n    isMelt,\n    isZap,\n    isSendEcash,\n    isSwap,\n    targetMint,\n    scanned,\n  } = route.params;\n  const insets = useSafeAreaInsets();\n  const { t } = useTranslation([NS.common]);\n  const { color } = useThemeContext();\n  const { formatAmount } = useCurrencyContext();\n  const { url, clearUrl } = useInitialURL();\n  const trustMintRef = useRef<TrustMintBottomSheetRef>(null);\n\n  const getPaymentType = () => {\n    if (isZap) {\n      return \"zap\";\n    }\n    if (isMelt) {\n      return \"cashOutFromMint\";\n    }\n    if (isSwap) {\n      return \"multimintSwap\";\n    }\n    return \"sendEcash\";\n  };\n\n  const getBtnTxt = () => {\n    if (isZap) {\n      return \"zapNow\";\n    }\n    if (isMelt) {\n      return \"submitPaymentReq\";\n    }\n    if (isSwap) {\n      return \"swapNow\";\n    }\n    return \"createToken\";\n  };\n\n  const getRecipient = () => {\n    if (recipient) {\n      return !isLightningAddress(recipient) ? truncateStr(recipient, 16) : recipient;\n    }\n    return t(\"n/a\");\n  };\n\n  const submitPaymentReq = async () => {\n    //TODO: Add proofs\n    const proofs: IProofSelection[] = [];\n    navigation.navigate(\"processing\", {\n      mint,\n      amount,\n      memo,\n      estFee,\n      isMelt,\n      isSendEcash,\n      isSwap,\n      isZap,\n      payZap: true,\n      targetMint,\n      proofs: proofs.map((p) => ({ ...p, selected: true })),\n      recipient,\n    });\n  };\n\n  return (\n    <Screen\n      screenName={t(\"paymentOverview\", { ns: NS.mints })}\n      withCancelBtn\n      handlePress={() => {\n        const routes = navigation.getState()?.routes;\n        const prevRoute = routes[routes.length - 2];\n        // if user comes from processing screen, navigate back to dashboard\n        // @ts-expect-error navigation type is not complete\n        if (prevRoute?.name === \"processing\" && prevRoute.params?.isZap) {\n          // clear the deep link url if user cancels\n          clearUrl();\n          return navigation.navigate(\"dashboard\");\n        }\n        navigation.goBack();\n      }}\n      withBackBtn\n    >\n      <ScrollView alwaysBounceVertical={false} style={{ marginBottom: s(90) }}>\n        <View style={globals(color).wrapContainer}>\n          <OverviewRow txt1={t(\"paymentType\")} txt2={t(getPaymentType())} />\n          <OverviewRow txt1={t(\"mint\")} txt2={mint.customName || formatMintUrl(mint.mintUrl)} />\n          {recipient && <OverviewRow txt1={t(\"recipient\")} txt2={getRecipient()} />}\n          {isSwap && targetMint && (\n            <OverviewRow\n              txt1={t(\"recipient\")}\n              txt2={targetMint.customName || formatMintUrl(targetMint.mintUrl)}\n            />\n          )}\n          <OverviewRow\n            txt1={t(\"amount\")}\n            txt2={`${formatAmount(amount).formatted} ${formatAmount(amount).symbol}`}\n          />\n          {isNum(estFee) && !isSendEcash && (\n            <OverviewRow\n              txt1={t(\"estimatedFees\")}\n              txt2={`${formatAmount(estFee).formatted} ${formatAmount(estFee).symbol}`}\n            />\n          )}\n          <View>\n            <Txt txt={t(\"balanceAfterTX\")} styles={[{ fontWeight: \"500\", marginBottom: s(5) }]} />\n            <Txt\n              txt={\n                estFee > 0\n                  ? `${formatAmount(balance - amount - estFee).formatted} ${t(\n                      \"to\",\n                    )} ${formatAmount(balance - amount).formatted} ${formatAmount(balance - amount).symbol}`\n                  : `${formatAmount(balance - amount).formatted} ${formatAmount(balance - amount).symbol}`\n              }\n              styles={[{ color: color.TEXT_SECONDARY }]}\n            />\n          </View>\n          <Separator style={[{ marginTop: s(20) }]} />\n          {memo && memo.length > 0 && (\n            <OverviewRow txt1={t(\"memo\", { ns: NS.history })} txt2={memo} />\n          )}\n        </View>\n      </ScrollView>\n      <View\n        style={[\n          styles.swipeContainer,\n          {\n            backgroundColor: color.BACKGROUND,\n            bottom: insets.bottom,\n          },\n        ]}\n      >\n        <SwipeButton txt={t(getBtnTxt())} onToggle={submitPaymentReq} />\n      </View>\n      <TrustMintBottomSheet ref={trustMintRef} />\n    </Screen>\n  );\n}\n\nconst styles = ScaledSheet.create({\n  container: {\n    flexDirection: \"column\",\n    justifyContent: \"space-between\",\n  },\n  coinSelectionHint: {\n    fontSize: \"10@vs\",\n    maxWidth: \"88%\",\n  },\n  swipeContainer: {\n    position: \"absolute\",\n    width: \"100%\",\n  },\n});\n"
  },
  {
    "path": "src/screens/Payment/Send/EncodedToken.tsx",
    "content": "import { getEncodedToken } from \"@cashu/cashu-ts\";\nimport Button from \"@comps/Button\";\nimport useCopy from \"@comps/hooks/Copy\";\nimport { CopyIcon, ShareIcon } from \"@comps/Icons\";\nimport QR from \"@comps/QR\";\nimport Txt from \"@comps/Txt\";\nimport type { TBeforeRemoveEvent, TEncodedTokenPageProps } from \"@model/nav\";\nimport Screen from \"@comps/Screen\";\nimport { preventBack } from \"@nav/utils\";\nimport { useThemeContext } from \"@src/context/Theme\";\nimport { useCurrencyContext } from \"@src/context/Currency\";\nimport { NS } from \"@src/i18n\";\nimport { globals, highlight as hi, mainColors } from \"@styles\";\nimport { formatInt, formatSatStr, share } from \"@util\";\nimport LottieView from \"lottie-react-native\";\nimport { useEffect, useMemo, useState } from \"react\";\nimport { useTranslation } from \"react-i18next\";\nimport { Text, View } from \"react-native\";\nimport { s, ScaledSheet } from \"react-native-size-matters\";\nimport { useManager } from \"@src/context/Manager\";\n\n/**\n * The page that shows the created Cashu token that can be scanned, copied or shared\n */\nexport default function EncodedTokenPage({ navigation, route }: TEncodedTokenPageProps) {\n  const { token } = route.params || {};\n  const { t } = useTranslation([NS.common]);\n  const { color, highlight } = useThemeContext();\n  const { formatBalance, formatAmount } = useCurrencyContext();\n  const [error, setError] = useState({ msg: \"\", open: false });\n  const encodedToken = useMemo(() => getEncodedToken(token), [token]);\n  const tokenAmount = useMemo(() => token.proofs.reduce((r, c) => r + c.amount, 0), [token]);\n  const manager = useManager();\n\n  // For tokens, always show sats as primary (tokens ARE in sats)\n  // Show fiat equivalent as secondary info if user prefers fiat\n  const fiatEquivalent = formatBalance ? formatAmount(tokenAmount) : null;\n  //TODO: Add spent check\n  const spent = false;\n  const { copied, copy } = useCopy();\n\n  // prevent back navigation - https://reactnavigation.org/docs/preventing-going-back/\n  useEffect(() => {\n    const backHandler = (e: TBeforeRemoveEvent) => preventBack(e, navigation.dispatch);\n    navigation.addListener(\"beforeRemove\", backHandler);\n    return () => navigation.removeListener(\"beforeRemove\", backHandler);\n  }, [navigation]);\n\n  useEffect(() => {\n    const unsub = manager.on(\"send:finalized\", () => {\n      navigation.navigate(\"dashboard\");\n    });\n    return () => unsub();\n  }, []);\n\n  return (\n    <Screen\n      withBackBtn={!spent}\n      screenName={!spent ? `${t(\"newToken\")}  🥜🐿️` : undefined}\n      handlePress={() => navigation.navigate(\"dashboard\")}\n      withPadding={false}\n    >\n      <View style={styles.container}>\n        {spent ? (\n          <>\n            <View />\n            <View>\n              <Text style={[styles.successTxt, { color: color.TEXT }]}>\n                {t(\"isSpent\", { ns: NS.history })}\n              </Text>\n              <View style={styles.successAnim}>\n                <LottieView\n                  source={require(\"../../../../assets/lottie/success.json\")}\n                  autoPlay\n                  loop={false}\n                  style={styles.lottie}\n                  renderMode=\"HARDWARE\"\n                />\n              </View>\n            </View>\n            <Button txt={t(\"backToDashboard\")} onPress={() => navigation.navigate(\"dashboard\")} />\n          </>\n        ) : (\n          <>\n            {/* The amount of the created token */}\n            <View style={styles.qrWrap}>\n              <Txt\n                txt={formatInt(tokenAmount)}\n                styles={[styles.tokenAmount, { color: hi[highlight] }]}\n              />\n              <Txt\n                txt={formatSatStr(tokenAmount, \"standard\", false)}\n                styles={[styles.tokenFormat]}\n              />\n              {fiatEquivalent && (\n                <Txt\n                  txt={`≈ ${fiatEquivalent.symbol}${fiatEquivalent.formatted}`}\n                  styles={[styles.fiatEquivalent, { color: color.TEXT_SECONDARY }]}\n                />\n              )}\n              {/* The QR code */}\n              {error.open ? (\n                <Txt txt={error.msg} styles={[globals(color).navTxt, styles.errorMsg]} />\n              ) : (\n                <QR\n                  size={s(280)}\n                  value={encodedToken}\n                  onError={() =>\n                    setTimeout(\n                      () =>\n                        setError({\n                          msg: t(\"bigQrMsg\"),\n                          open: true,\n                        }),\n                      0,\n                    )\n                  }\n                />\n              )}\n            </View>\n            <View style={styles.fullWidth}>\n              {error.open && (\n                <>\n                  <Button\n                    txt={t(copied ? \"copied\" : \"copyToken\")}\n                    onPress={() => void copy(encodedToken)}\n                    icon={<CopyIcon width={s(18)} height={s(18)} color={mainColors.WHITE} />}\n                  />\n                  <View style={{ marginVertical: s(10) }} />\n                </>\n              )}\n              <Button\n                outlined\n                txt={t(\"share\")}\n                onPress={() => void share(encodedToken, `cashu://${encodedToken}`)}\n                icon={<ShareIcon width={s(18)} height={s(18)} color={hi[highlight]} />}\n              />\n            </View>\n          </>\n        )}\n      </View>\n    </Screen>\n  );\n}\n\nconst styles = ScaledSheet.create({\n  container: {\n    flex: 1,\n    alignItems: \"center\",\n    justifyContent: \"space-between\",\n    width: \"100%\",\n    padding: \"20@s\",\n  },\n  qrWrap: {\n    alignItems: \"center\",\n  },\n  tokenAmount: {\n    fontSize: \"40@vs\",\n    fontWeight: \"500\",\n    marginTop: \"20@vs\",\n  },\n  tokenFormat: {\n    marginBottom: \"5@vs\",\n  },\n  fiatEquivalent: {\n    fontSize: \"14@vs\",\n    marginBottom: \"15@vs\",\n  },\n  errorMsg: {\n    marginVertical: \"25@vs\",\n    textAlign: \"center\",\n  },\n  successTxt: {\n    fontSize: \"28@vs\",\n    fontWeight: \"800\",\n    textAlign: \"center\",\n    marginTop: \"30@vs\",\n  },\n  successAnim: {\n    justifyContent: \"center\",\n    alignItems: \"center\",\n    marginTop: \"20@vs\",\n  },\n  fullWidth: {\n    width: \"100%\",\n  },\n  lottie: {\n    width: \"100@s\",\n    height: \"100@s\",\n  },\n});\n"
  },
  {
    "path": "src/screens/Payment/SendSelectAmount.tsx",
    "content": "import AmountInput, { useShakeAnimation } from \"@comps/AmountInput\";\nimport Button from \"@comps/Button\";\nimport { ChevronRightIcon } from \"@comps/Icons\";\nimport MintHeaderSelector from \"@comps/MintHeaderSelector\";\nimport Screen from \"@comps/Screen\";\nimport Txt from \"@comps/Txt\";\nimport type { PreparedSendOperation, SendOperation } from \"@cashu/coco-core\";\nimport { useSendOperation } from \"@cashu/coco-react\";\nimport SendConfirmationModal, { type SendConfirmationModalRef } from \"@modal/SendConfirmationModal\";\nimport { useCurrencyContext } from \"@src/context/Currency\";\nimport { useKnownMints, KnownMintWithBalance } from \"@src/context/KnownMints\";\nimport { NS } from \"@src/i18n\";\nimport type { TBeforeRemoveEvent } from \"@model/nav\";\nimport { SendSelectAmountProps } from \"@src/nav/navTypes\";\nimport { usePromptContext } from \"@src/context/Prompt\";\nimport { useThemeContext } from \"@src/context/Theme\";\nimport { mainColors } from \"@styles\";\nimport { isErr, vib } from \"@util\";\nimport { useCallback, useEffect, useRef, useState, useMemo } from \"react\";\nimport { useTranslation } from \"react-i18next\";\nimport { Keyboard, TextInput, View } from \"react-native\";\nimport { ScaledSheet } from \"react-native-size-matters\";\n\ntype TPreparedOrLaterSendOperation = Exclude<SendOperation, { state: \"init\" }>;\n\nfunction isPreparedOrLaterSendOperation(\n  operation: SendOperation | null,\n): operation is TPreparedOrLaterSendOperation {\n  return !!operation && operation.state !== \"init\";\n}\n\nexport default function SendSelectAmountScreen({ navigation }: SendSelectAmountProps) {\n  const { t } = useTranslation([NS.wallet, NS.common, NS.error]);\n  const { shake } = useShakeAnimation();\n  const { knownMints } = useKnownMints();\n  const amountInputRef = useRef<TextInput>(null);\n  const sendConfirmationRef = useRef<SendConfirmationModalRef>(null);\n  const {\n    cancel,\n    currentOperation,\n    execute,\n    isLoading: isSending,\n    prepare,\n    reset,\n  } = useSendOperation();\n  const { openPromptAutoClose } = usePromptContext();\n\n  const [amountInput, setAmountInput] = useState(\"\");\n  const [preparedOperation, setPreparedOperation] = useState<PreparedSendOperation | null>(null);\n  const [preparedMint, setPreparedMint] = useState<KnownMintWithBalance | null>(null);\n  const hasCancelledRef = useRef(false);\n\n  const selectableMints = useMemo(() => {\n    return knownMints.filter((mint) => mint.balance > 0);\n  }, [knownMints]);\n\n  const [selectedMint, setSelectedMint] = useState<KnownMintWithBalance | null>(\n    selectableMints[0] ?? null,\n  );\n\n  useEffect(() => {\n    setSelectedMint((currentMint) => {\n      const updatedMint = currentMint\n        ? selectableMints.find((mint) => mint.mintUrl === currentMint.mintUrl)\n        : null;\n\n      return updatedMint ?? selectableMints[0] ?? null;\n    });\n  }, [selectableMints]);\n\n  const displayOperation = isPreparedOrLaterSendOperation(currentOperation)\n    ? currentOperation\n    : preparedOperation;\n  const canCancelPreparedOperation = displayOperation?.state === \"prepared\";\n\n  const noMintsAvailable = useMemo(() => {\n    return !selectedMint || selectableMints.length === 0;\n  }, [selectedMint, selectableMints.length]);\n\n  // Defer non-critical state initialization\n  const [err, setErr] = useState(false);\n\n  // Derived numeric amount and selected mint balance\n  const amountValue = useMemo(() => {\n    const parsed = parseInt(amountInput || \"0\", 10);\n    return Number.isNaN(parsed) ? 0 : parsed;\n  }, [amountInput]);\n  const selectedMintBalance = selectedMint?.balance || 0;\n\n  // Memoize screen name computation\n  const screenName = \"sendEcash\";\n\n  // Back navigation handler\n  const handleBack = useCallback(() => {\n    if (displayOperation) {\n      sendConfirmationRef.current?.close({ notifyCancel: true });\n      return;\n    }\n\n    navigation.goBack();\n  }, [displayOperation, navigation]);\n\n  const handleMintSelect = useCallback(\n    (mint: KnownMintWithBalance) => {\n      setSelectedMint(mint);\n    },\n    [setSelectedMint],\n  );\n\n  const handleMintSelectorOpen = useCallback(() => {\n    amountInputRef.current?.blur();\n  }, []);\n\n  const triggerAmountError = useCallback(() => {\n    vib(400);\n    setErr(true);\n    shake();\n    const timeout = setTimeout(() => {\n      setErr(false);\n      clearTimeout(timeout);\n    }, 500);\n  }, [shake]);\n\n  const showError = useCallback(\n    (error: unknown) => {\n      console.error(error);\n      openPromptAutoClose({\n        msg: isErr(error) ? error.message : t(\"sendTokenErr\", { ns: NS.error }),\n      });\n    },\n    [openPromptAutoClose, t],\n  );\n\n  const presentSendConfirmation = useCallback(() => {\n    amountInputRef.current?.blur();\n    Keyboard.dismiss();\n\n    setTimeout(() => {\n      sendConfirmationRef.current?.present();\n    }, 0);\n  }, []);\n\n  const handleAmountSubmit = useCallback(async () => {\n    if (isSending || !selectedMint) {\n      return;\n    }\n\n    if (!amountValue || amountValue < 1 || amountValue > selectedMintBalance) {\n      triggerAmountError();\n      return;\n    }\n\n    try {\n      const operation = await prepare({ mintUrl: selectedMint.mintUrl, amount: amountValue });\n      hasCancelledRef.current = false;\n      setPreparedMint(selectedMint);\n      setPreparedOperation(operation);\n      presentSendConfirmation();\n    } catch (e) {\n      showError(e);\n      shake();\n    }\n  }, [\n    amountValue,\n    isSending,\n    prepare,\n    presentSendConfirmation,\n    selectedMint,\n    selectedMintBalance,\n    shake,\n    showError,\n    triggerAmountError,\n  ]);\n\n  const handleOperationConfirm = useCallback(async () => {\n    if (!displayOperation) {\n      return;\n    }\n\n    try {\n      const { token } = await execute();\n      sendConfirmationRef.current?.close({ notifyCancel: false });\n      setPreparedOperation(null);\n      setPreparedMint(null);\n      navigation.navigate(\"encodedToken\", {\n        token,\n      });\n    } catch (e) {\n      showError(e);\n      shake();\n    }\n  }, [displayOperation, execute, navigation, shake, showError]);\n\n  const cancelPreparedOperation = useCallback(async () => {\n    if (!canCancelPreparedOperation || isSending || hasCancelledRef.current) {\n      return true;\n    }\n\n    try {\n      hasCancelledRef.current = true;\n      await cancel();\n      setPreparedOperation(null);\n      setPreparedMint(null);\n      reset();\n      return true;\n    } catch (error) {\n      hasCancelledRef.current = false;\n      showError(error);\n      return false;\n    }\n  }, [canCancelPreparedOperation, cancel, isSending, reset, showError]);\n\n  const handleOperationCancel = useCallback(async () => {\n    const didCancel = await cancelPreparedOperation();\n    if (!didCancel) {\n      presentSendConfirmation();\n    }\n  }, [cancelPreparedOperation, presentSendConfirmation]);\n\n  useEffect(() => {\n    const handleBeforeRemove = (e: TBeforeRemoveEvent) => {\n      if (!canCancelPreparedOperation || hasCancelledRef.current) {\n        return;\n      }\n\n      e.preventDefault();\n\n      if (isSending) {\n        return;\n      }\n\n      void cancelPreparedOperation().then((didCancel) => {\n        if (didCancel) {\n          navigation.dispatch(e.data.action);\n        }\n      });\n    };\n\n    return navigation.addListener(\"beforeRemove\", handleBeforeRemove);\n  }, [canCancelPreparedOperation, cancelPreparedOperation, isSending, navigation]);\n\n  // Early return after all hooks\n  if (noMintsAvailable) {\n    return (\n      <Screen\n        screenName={t(\"selectAmount\", { ns: NS.common })}\n        withBackBtn\n        handlePress={handleBack}\n      >\n        <View\n          style={{\n            flex: 1,\n            justifyContent: \"center\",\n            alignItems: \"center\",\n            padding: 20,\n          }}\n        >\n          <Txt txt={t(\"noMintsWithBalance\", { ns: NS.common })} />\n        </View>\n      </Screen>\n    );\n  }\n\n  return (\n    <Screen\n      screenName={t(screenName, { ns: NS.common })}\n      withBackBtn\n      handlePress={handleBack}\n      withPadding={false}\n      withBottomInset={false}\n      withKeyboard={true}\n      rightAction={\n        <MintHeaderSelector\n          selectedMint={selectedMint!}\n          onMintSelect={handleMintSelect}\n          onOpen={handleMintSelectorOpen}\n        />\n      }\n    >\n      <AmountInput\n        ref={amountInputRef}\n        value={amountInput}\n        onChange={setAmountInput}\n        onSubmit={handleAmountSubmit}\n        error={err}\n        autoFocus\n        testID=\"send-amount-input\"\n      />\n\n      <View style={styles.actionWrap}>\n        <Button\n          txt={t(\"continue\", { ns: NS.common })}\n          onPress={handleAmountSubmit}\n          icon={<ChevronRightIcon color={mainColors.WHITE} />}\n          loading={isSending}\n        />\n      </View>\n\n      <SendConfirmationModal\n        ref={sendConfirmationRef}\n        operation={displayOperation}\n        mint={preparedMint}\n        loading={isSending}\n        onConfirm={() => void handleOperationConfirm()}\n        onCancel={() => void handleOperationCancel()}\n      />\n    </Screen>\n  );\n}\n\ninterface IMeltOverviewProps {\n  amount: number;\n  shouldEstimate?: boolean;\n  balTooLow?: boolean;\n  isInvoice?: boolean;\n  fee: number;\n}\n\nexport function MeltOverview({\n  amount,\n  shouldEstimate,\n  balTooLow,\n  isInvoice,\n  fee,\n}: IMeltOverviewProps) {\n  const { t } = useTranslation([NS.common]);\n  const { color } = useThemeContext();\n  const { formatAmount } = useCurrencyContext();\n  const total = shouldEstimate ? 0 : amount + fee;\n  const { formatted, symbol } = formatAmount(total);\n\n  return (\n    <View style={styles.overview}>\n      <Txt\n        txt={\n          t(isInvoice ? \"invoiceInclFee\" : \"totalInclFee\", {\n            ns: NS.common,\n          }) + \"*\"\n        }\n        bold\n      />\n      <Txt\n        txt={`${formatted} ${symbol}`}\n        styles={[\n          {\n            color:\n              !shouldEstimate && balTooLow\n                ? mainColors.ERROR\n                : shouldEstimate\n                  ? color.TEXT\n                  : mainColors.VALID,\n          },\n        ]}\n      />\n    </View>\n  );\n}\n\nconst styles = ScaledSheet.create({\n  overview: {\n    flexDirection: \"row\",\n    alignItems: \"center\",\n    justifyContent: \"space-between\",\n  },\n  actionWrap: {\n    flex: 1,\n    width: \"100%\",\n    justifyContent: \"flex-end\",\n    paddingHorizontal: \"20@s\",\n    paddingBottom: \"10@vs\",\n  },\n});\n"
  },
  {
    "path": "src/screens/Payment/Success.tsx",
    "content": "import Button from \"@comps/Button\";\nimport Logo from \"@comps/Logo\";\nimport Txt from \"@comps/Txt\";\nimport { isIOS } from \"@consts\";\nimport type { TBeforeRemoveEvent, TSuccessPageProps } from \"@model/nav\";\nimport { preventBack } from \"@nav/utils\";\nimport { useBalanceContext } from \"@src/context/Balance\";\nimport { useThemeContext } from \"@src/context/Theme\";\nimport { useCurrencyContext } from \"@src/context/Currency\";\nimport { NS } from \"@src/i18n\";\nimport { isNum, vib } from \"@util\";\nimport LottieView from \"lottie-react-native\";\nimport { useEffect } from \"react\";\nimport { useTranslation } from \"react-i18next\";\nimport { Text, View } from \"react-native\";\nimport { useSafeAreaInsets } from \"react-native-safe-area-context\";\nimport { s, ScaledSheet, vs } from \"react-native-size-matters\";\n\nexport default function SuccessPage({ navigation, route }: TSuccessPageProps) {\n  const { amount, memo, fee, change, mint, isClaim, isMelt, isAutoSwap, isScanned } = route.params;\n  const { t } = useTranslation([NS.common]);\n  const { color } = useThemeContext();\n  const { formatAmount } = useCurrencyContext();\n  const insets = useSafeAreaInsets();\n\n  useEffect(() => {\n    vib(400);\n    // eslint-disable-next-line react-hooks/exhaustive-deps\n  }, []);\n\n  // prevent back navigation - https://reactnavigation.org/docs/preventing-going-back/\n  useEffect(() => {\n    const backHandler = (e: TBeforeRemoveEvent) => preventBack(e, navigation.dispatch);\n    navigation.addListener(\"beforeRemove\", backHandler);\n    return () => navigation.removeListener(\"beforeRemove\", backHandler);\n  }, [navigation]);\n\n  return (\n    <View style={[styles.container, { backgroundColor: color.BACKGROUND }]}>\n      <View pointerEvents=\"none\" style={styles.confetti}>\n        <LottieView\n          source={require(\"../../../assets/lottie/confetti.json\")}\n          autoPlay\n          loop={false}\n          style={{ width: \"100%\", height: \"100%\" }}\n        />\n      </View>\n      <View style={{ width: \"100%\" }}>\n        <Text testID={`amount: ${amount}`} style={[styles.successTxt, { color: color.TEXT }]}>\n          {(() => {\n            if (isMelt && !isAutoSwap) {\n              return t(\"paymentSuccess\");\n            }\n            if (isAutoSwap) {\n              return t(\"autoSwapSuccess\");\n            }\n            return null;\n          })()}\n        </Text>\n        {memo && <Text style={[styles.mints, { color: color.TEXT_SECONDARY }]}>{memo}</Text>}\n        {mint && mint.length > 0 && (\n          <Text testID={`mint: ${mint}`} style={[styles.mints, { color: color.TEXT_SECONDARY }]}>\n            {mint}\n          </Text>\n        )}\n        <View style={styles.successAnim}>\n          <LottieView\n            source={require(\"../../../assets/lottie/success.json\")}\n            autoPlay\n            loop={false}\n            style={styles.lottie}\n          />\n        </View>\n        {(isMelt || isAutoSwap) && amount && (\n          <View style={styles.meltWrap}>\n            <Details\n              txt={t(isAutoSwap ? \"swapped\" : \"paidOut\", {\n                ns: NS.wallet,\n              })}\n              value={`${formatAmount(amount).formatted} ${formatAmount(amount).symbol}`}\n            />\n            <Details\n              txt={t(\"fee\")}\n              value={`${formatAmount(fee || 0).formatted} ${formatAmount(fee || 0).symbol}`}\n            />\n            <Details\n              txt={t(\"totalInclFee\")}\n              value={`${formatAmount(amount + (fee || 0)).formatted} ${\n                formatAmount(amount + (fee || 0)).symbol\n              }`}\n            />\n            {isNum(change) && (\n              <Details\n                txt={t(\"change\")}\n                value={`${formatAmount(change).formatted} ${formatAmount(change).symbol}`}\n              />\n            )}\n          </View>\n        )}\n      </View>\n      <View style={[styles.btnWrap, { marginBottom: isIOS ? insets.bottom : 20 }]}>\n        <Button\n          txt={t(\"backToDashboard\")}\n          onPress={() => {\n            navigation.navigate(\"dashboard\");\n          }}\n        />\n      </View>\n    </View>\n  );\n}\n\nfunction Details({ txt, value }: { txt: string; value: string }) {\n  return (\n    <View style={styles.meltOverview}>\n      <Txt txt={txt} styles={[styles.meltTxt]} />\n      <Txt txt={value} styles={[styles.meltTxt]} />\n    </View>\n  );\n}\n\nconst styles = ScaledSheet.create({\n  container: {\n    flex: 1,\n    padding: \"20@s\",\n  },\n  img: {\n    marginTop: \"90@s\",\n    height: \"90@s\",\n    opacity: 0.8,\n  },\n  nostrImg: {\n    marginTop: \"90@vs\",\n    justifyContent: \"center\",\n    alignItems: \"center\",\n  },\n  successTxt: {\n    fontSize: \"28@vs\",\n    fontWeight: \"800\",\n    textAlign: \"center\",\n    marginTop: \"30@vs\",\n  },\n  meltWrap: {\n    width: \"100%\",\n    marginTop: \"20@vs\",\n  },\n  meltOverview: {\n    flexDirection: \"row\",\n    alignItems: \"center\",\n    justifyContent: \"space-between\",\n    marginBottom: \"10@vs\",\n  },\n  meltTxt: {\n    fontWeight: \"500\",\n  },\n  mints: {\n    marginTop: \"20@vs\",\n    fontSize: \"14@vs\",\n    textAlign: \"center\",\n    fontWeight: \"500\",\n  },\n  btnWrap: {\n    position: \"absolute\",\n    bottom: 0,\n    right: 0,\n    left: 0,\n    paddingHorizontal: \"20@s\",\n  },\n  confetti: {\n    position: \"absolute\",\n    top: 0,\n    right: 0,\n    bottom: 0,\n    left: 0,\n  },\n  successAnim: {\n    justifyContent: \"center\",\n    alignItems: \"center\",\n    marginTop: \"20@vs\",\n  },\n  lottie: {\n    width: \"100@s\",\n    height: \"100@s\",\n  },\n});\n"
  },
  {
    "path": "src/screens/Payment/SuccessScreen.tsx",
    "content": "import Button from \"@comps/Button\";\nimport Logo from \"@comps/Logo\";\nimport Txt from \"@comps/Txt\";\nimport Screen from \"@comps/Screen\";\nimport { isIOS } from \"@consts\";\nimport type {\n  TBeforeRemoveEvent,\n  TSuccessScreenProps,\n  SuccessConfig,\n  MeltSuccessConfig,\n  AutoSwapSuccessConfig,\n} from \"@model/nav\";\nimport { preventBack } from \"@nav/utils\";\nimport { useThemeContext } from \"@src/context/Theme\";\nimport { useCurrencyContext } from \"@src/context/Currency\";\nimport { NS } from \"@src/i18n\";\nimport { isNum, vib } from \"@util\";\nimport LottieView from \"lottie-react-native\";\nimport { useEffect } from \"react\";\nimport { useTranslation } from \"react-i18next\";\nimport { View } from \"react-native\";\nimport { useSafeAreaInsets } from \"react-native-safe-area-context\";\nimport { s, ScaledSheet, vs } from \"react-native-size-matters\";\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Helper Functions\n// ─────────────────────────────────────────────────────────────────────────────\n\nfunction hasPaymentDetails(\n  config: SuccessConfig,\n): config is MeltSuccessConfig | AutoSwapSuccessConfig {\n  return config.type === \"melt\" || config.type === \"autoSwap\";\n}\n\nfunction hasSimpleAmount(config: SuccessConfig): boolean {\n  return (\n    config.type === \"receive\" ||\n    config.type === \"claim\" ||\n    config.type === \"send\" ||\n    config.type === \"restore\" ||\n    config.type === \"zap\"\n  );\n}\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Components\n// ─────────────────────────────────────────────────────────────────────────────\n\nfunction DetailsRow({ label, value }: { label: string; value: string }) {\n  return (\n    <View style={styles.detailsRow}>\n      <Txt txt={label} styles={[styles.detailsTxt]} />\n      <Txt txt={value} styles={[styles.detailsTxt]} />\n    </View>\n  );\n}\n\ninterface PaymentDetailsProps {\n  config: MeltSuccessConfig | AutoSwapSuccessConfig;\n  formatAmount: ReturnType<typeof useCurrencyContext>[\"formatAmount\"];\n}\n\nfunction PaymentDetails({ config, formatAmount }: PaymentDetailsProps) {\n  const { t } = useTranslation([NS.common]);\n  const { amount, fee, change } = config;\n  const isSwap = config.type === \"autoSwap\";\n\n  return (\n    <View style={styles.detailsWrap}>\n      <DetailsRow\n        label={t(isSwap ? \"swapped\" : \"paidOut\", { ns: NS.wallet })}\n        value={`${formatAmount(amount).formatted} ${formatAmount(amount).symbol}`}\n      />\n      <DetailsRow\n        label={t(\"fee\")}\n        value={`${formatAmount(fee).formatted} ${formatAmount(fee).symbol}`}\n      />\n      <DetailsRow\n        label={t(\"totalInclFee\")}\n        value={`${formatAmount(amount + fee).formatted} ${formatAmount(amount + fee).symbol}`}\n      />\n      {isNum(change) && (\n        <DetailsRow\n          label={t(\"change\")}\n          value={`${formatAmount(change).formatted} ${formatAmount(change).symbol}`}\n        />\n      )}\n    </View>\n  );\n}\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Main Screen Component\n// ─────────────────────────────────────────────────────────────────────────────\n\nexport default function SuccessScreen({ navigation, route }: TSuccessScreenProps) {\n  const config = route.params;\n  const { t } = useTranslation([NS.common]);\n  const { color } = useThemeContext();\n  const { formatAmount } = useCurrencyContext();\n  const insets = useSafeAreaInsets();\n\n  const getSuccessTitle = (cfg: SuccessConfig): string => {\n    switch (cfg.type) {\n      case \"melt\":\n        return t(\"paymentSuccess\");\n      case \"autoSwap\":\n        return t(\"autoSwapSuccess\");\n      case \"claim\":\n        return t(\"receivedEcash\", { ns: NS.history });\n      case \"receive\":\n        return t(\"receivedFromMint\");\n      case \"zap\":\n        return t(\"paymentSuccess\");\n      case \"restore\":\n        return \"Wallet restored!\";\n      case \"send\":\n        return t(\"ecashCreated\", {\n          ns: NS.common,\n          defaultValue: \"Ecash created!\",\n        });\n    }\n  };\n\n  const title = getSuccessTitle(config);\n\n  // Vibrate on mount\n  useEffect(() => {\n    vib(400);\n  }, []);\n\n  // Prevent back navigation\n  useEffect(() => {\n    const backHandler = (e: TBeforeRemoveEvent) => preventBack(e, navigation.dispatch);\n    navigation.addListener(\"beforeRemove\", backHandler);\n    return () => navigation.removeListener(\"beforeRemove\", backHandler);\n  }, [navigation]);\n\n  return (\n    <Screen>\n      {/* Confetti Animation */}\n      <View pointerEvents=\"none\" style={styles.confetti}>\n        <LottieView\n          source={require(\"../../../assets/lottie/confetti.json\")}\n          autoPlay\n          loop={false}\n          style={{ width: \"100%\", height: \"100%\" }}\n        />\n      </View>\n\n      {/* Content */}\n      <View style={styles.content}>\n        {/* Title */}\n        <Txt txt={title} bold center styles={[styles.title]} />\n\n        {/* Memo */}\n        {config.memo && (\n          <Txt\n            txt={config.memo}\n            center\n            styles={[styles.subtitle, { color: color.TEXT_SECONDARY }]}\n          />\n        )}\n\n        {/* Mint */}\n        {config.mint && config.mint.length > 0 && (\n          <Txt\n            txt={config.mint}\n            center\n            styles={[styles.subtitle, { color: color.TEXT_SECONDARY }]}\n          />\n        )}\n\n        {/* Amount Display (for simple success types) */}\n        {hasSimpleAmount(config) && (\n          <View style={styles.amountWrap}>\n            <Txt txt={formatAmount(config.amount).formatted} bold center styles={[styles.amount]} />\n            <Txt\n              txt={formatAmount(config.amount).symbol}\n              center\n              styles={[styles.amountSymbol, { color: color.TEXT_SECONDARY }]}\n            />\n          </View>\n        )}\n\n        {/* Payment Details (for melt/autoSwap) */}\n        {hasPaymentDetails(config) && (\n          <PaymentDetails config={config} formatAmount={formatAmount} />\n        )}\n      </View>\n\n      {/* Back to Dashboard Button */}\n      <View style={[styles.btnWrap, { marginBottom: isIOS ? insets.bottom : 20 }]}>\n        <Button txt={t(\"backToDashboard\")} onPress={() => navigation.navigate(\"dashboard\")} />\n      </View>\n    </Screen>\n  );\n}\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Styles\n// ─────────────────────────────────────────────────────────────────────────────\n\nconst styles = ScaledSheet.create({\n  container: {\n    flex: 1,\n    padding: \"20@s\",\n  },\n  logo: {\n    marginTop: \"90@s\",\n    height: \"90@s\",\n    opacity: 0.8,\n  },\n  content: {\n    width: \"100%\",\n  },\n  title: {\n    fontSize: \"28@vs\",\n    marginTop: \"30@vs\",\n  },\n  amountWrap: {\n    alignItems: \"center\",\n    marginTop: \"20@vs\",\n  },\n  amount: {\n    fontSize: \"42@s\",\n  },\n  amountSymbol: {\n    fontSize: \"14@vs\",\n    marginTop: \"4@vs\",\n  },\n  subtitle: {\n    marginTop: \"20@vs\",\n    fontSize: \"14@vs\",\n    fontWeight: \"500\",\n  },\n  detailsWrap: {\n    width: \"100%\",\n    marginTop: \"20@vs\",\n  },\n  detailsRow: {\n    flexDirection: \"row\",\n    alignItems: \"center\",\n    justifyContent: \"space-between\",\n    marginBottom: \"10@vs\",\n  },\n  detailsTxt: {\n    fontWeight: \"500\",\n  },\n  btnWrap: {\n    position: \"absolute\",\n    bottom: 0,\n    right: 0,\n    left: 0,\n    paddingHorizontal: \"20@s\",\n  },\n  confetti: {\n    position: \"absolute\",\n    top: 0,\n    right: 0,\n    bottom: 0,\n    left: 0,\n  },\n  successAnim: {\n    justifyContent: \"center\",\n    alignItems: \"center\",\n    marginTop: \"20@vs\",\n  },\n  lottie: {\n    width: \"100@s\",\n    height: \"100@s\",\n  },\n});\n"
  },
  {
    "path": "src/screens/QRScan/QrScannerScreen.tsx",
    "content": "import Screen from \"@comps/Screen\";\nimport { NfcIcon } from \"@comps/Icons\";\nimport Loading from \"@comps/Loading\";\nimport NfcPaymentModal, { type NfcPaymentModalRef } from \"@comps/modal/NfcPaymentModal\";\nimport CameraPermission from \"@src/screens/QRScan/components/CameraPermission\";\nimport useScanResult from \"@src/screens/QRScan/hooks/useScanResult\";\nimport { useCashuClaimFlow } from \"@comps/hooks/useCashuClaimFlow\";\nimport { usePromptContext } from \"@src/context/Prompt\";\nimport { useThemeContext } from \"@src/context/Theme\";\nimport { NS } from \"@src/i18n\";\nimport type { QRScannerScreenProps } from \"@src/nav/navTypes\";\nimport { highlight as hi, mainColors } from \"@styles\";\nimport { getColor } from \"@styles/colors\";\nimport type { PaymentCandidateKind, PaymentStringCandidate } from \"@util/paymentStringParser\";\nimport MaterialIcons from \"@expo/vector-icons/MaterialIcons\";\nimport { useFocusEffect } from \"@react-navigation/native\";\nimport { CameraView, useCameraPermissions } from \"expo-camera\";\nimport type { ScanningResult } from \"expo-camera\";\nimport type { ComponentProps } from \"react\";\nimport { useCallback, useEffect, useRef, useState } from \"react\";\nimport { useTranslation } from \"react-i18next\";\nimport { Linking, StyleSheet, Text, TouchableOpacity, View } from \"react-native\";\nimport { ScaledSheet, s } from \"react-native-size-matters\";\n\nconst QR_CANDIDATE_PRIORITY: PaymentCandidateKind[] = [\n  \"cashuToken\",\n  \"lightningInvoice\",\n  \"lightningAddress\",\n  \"lnurl\",\n  \"cashuPaymentRequest\",\n  \"bitcoinAddress\",\n];\n\nfunction selectQrCandidate(candidates: PaymentStringCandidate[]) {\n  return QR_CANDIDATE_PRIORITY.map((kind) =>\n    candidates.find((candidate) => candidate.kind === kind),\n  ).find((candidate): candidate is PaymentStringCandidate => Boolean(candidate));\n}\n\nfunction QrScannerScreen({ navigation }: QRScannerScreenProps) {\n  const [permission, requestPermission] = useCameraPermissions();\n  const { t } = useTranslation([NS.common, NS.wallet]);\n  const { color, highlight } = useThemeContext();\n  const { openPromptAutoClose } = usePromptContext();\n  const [isScanningEnabled, setIsScanningEnabled] = useState(true);\n  const [isClaimingScannedToken, setIsClaimingScannedToken] = useState(false);\n  const isHandlingScanRef = useRef(false);\n  const isScreenActiveRef = useRef(false);\n  const nfcModalRef = useRef<NfcPaymentModalRef>(null);\n\n  const {\n    onScan,\n    reset,\n    active: urActive,\n    complete,\n    estimated,\n    expectedCount,\n    receivedCount,\n    error: urError,\n    candidates,\n  } = useScanResult();\n\n  const { claimFromTokenString, isReceiving } = useCashuClaimFlow();\n  const isClaimingToken = isClaimingScannedToken || isReceiving;\n\n  useFocusEffect(\n    useCallback(() => {\n      // on focus\n      isScreenActiveRef.current = true;\n      isHandlingScanRef.current = false;\n      setIsClaimingScannedToken(false);\n      setIsScanningEnabled(true);\n      reset();\n      return () => {\n        // on blur\n        isScreenActiveRef.current = false;\n        reset();\n        isHandlingScanRef.current = false;\n        setIsClaimingScannedToken(false);\n        setIsScanningEnabled(true);\n      };\n    }, [reset]),\n  );\n\n  useEffect(() => {\n    if (!complete || !candidates || isHandlingScanRef.current) return;\n    isHandlingScanRef.current = true;\n    setIsScanningEnabled(false);\n    const selectedCandidate = selectQrCandidate(candidates);\n    if (!selectedCandidate) {\n      openPromptAutoClose({ msg: t(\"unsupportedFormat\"), success: false });\n      return;\n    }\n\n    if (\n      selectedCandidate.kind === \"lightningInvoice\" ||\n      selectedCandidate.kind === \"lightningAddress\" ||\n      selectedCandidate.kind === \"lnurl\"\n    ) {\n      navigation.replace(\"MeltInput\", { invoice: selectedCandidate.value });\n      return;\n    }\n\n    if (selectedCandidate.kind === \"cashuToken\") {\n      setIsClaimingScannedToken(true);\n      (async () => {\n        try {\n          const result = await claimFromTokenString(selectedCandidate.value);\n          if (result.status === \"success\") {\n            navigation.replace(\"successScreen\", {\n              type: \"claim\",\n              mint: result.token.mint,\n              amount: result.amount,\n            });\n          }\n        } finally {\n          if (isScreenActiveRef.current) {\n            setIsClaimingScannedToken(false);\n          }\n        }\n      })();\n      return;\n    }\n\n    if (selectedCandidate.kind === \"cashuPaymentRequest\") {\n      openPromptAutoClose({\n        msg: t(\"cashuPaymentRequestQrUnsupported\"),\n        success: false,\n      });\n      return;\n    }\n\n    if (selectedCandidate.kind === \"bitcoinAddress\") {\n      openPromptAutoClose({ msg: t(\"bitcoinAddressPaymentsUnsupported\"), success: false });\n      return;\n    }\n  }, [complete, candidates, navigation, openPromptAutoClose, claimFromTokenString, t]);\n\n  const handleCodeScanned = (result: ScanningResult) => {\n    if (isHandlingScanRef.current) {\n      return;\n    }\n    onScan(result.data);\n  };\n\n  const handleRescan = () => {\n    isHandlingScanRef.current = false;\n    setIsScanningEnabled(true);\n    reset();\n  };\n\n  const handleNfcPress = () => {\n    nfcModalRef.current?.open();\n  };\n\n  const nfcHeaderAction = (\n    <TouchableOpacity\n      accessibilityLabel={t(\"nfcPayment\", {\n        ns: NS.wallet,\n        defaultValue: \"NFC Payment\",\n      })}\n      accessibilityRole=\"button\"\n      activeOpacity={0.7}\n      onPress={handleNfcPress}\n      style={[styles.headerAction, { borderColor: `${hi[highlight]}55` }]}\n      testID=\"nfc-btn-top-nav\"\n    >\n      <NfcIcon width={s(20)} color={hi[highlight]} />\n    </TouchableOpacity>\n  );\n\n  const nfcPaymentModal = (\n    <NfcPaymentModal\n      ref={nfcModalRef}\n      onSuccess={(result) => {\n        openPromptAutoClose({\n          msg: result.amount\n            ? `Sent ${result.amount.toLocaleString()} sats via NFC!`\n            : \"NFC payment sent successfully!\",\n          success: true,\n        });\n      }}\n      onError={(result) => {\n        openPromptAutoClose({\n          msg: result.error || \"NFC payment failed\",\n          success: false,\n        });\n      }}\n      onPaymentHandoff={(handoff) => {\n        navigation.navigate(\"MeltInput\", { invoice: handoff.value });\n      }}\n    />\n  );\n\n  if (!permission) {\n    // Camera permissions are still loading.\n    return <View />;\n  }\n\n  if (!permission.granted) {\n    // Camera permissions are not granted yet.\n    return (\n      <Screen\n        screenName={t(\"scanQR\")}\n        withBackBtn\n        handlePress={() => navigation.goBack()}\n        rightAction={nfcHeaderAction}\n        withBottomInset={false}\n      >\n        <>\n          <CameraPermission\n            canAskAgain={permission.canAskAgain}\n            onRequestPermission={requestPermission}\n            onOpenSettings={() => Linking.openSettings()}\n          />\n          {nfcPaymentModal}\n        </>\n      </Screen>\n    );\n  }\n\n  return (\n    <Screen\n      screenName={t(\"scanQR\")}\n      withBackBtn\n      handlePress={() => navigation.goBack()}\n      rightAction={nfcHeaderAction}\n      withPadding={false}\n      withBottomInset={false}\n    >\n      <View style={[styles.cameraContainer, { backgroundColor: color.BACKGROUND }]}>\n        <CameraView\n          style={styles.camera}\n          onBarcodeScanned={isScanningEnabled ? handleCodeScanned : undefined}\n        />\n        <View style={styles.scrim} />\n        <View style={styles.scanSurface}>\n          <View style={styles.headerCopy}>\n            <StatusPill\n              label={\n                isClaimingToken\n                  ? t(\"claiming\", { ns: NS.wallet })\n                  : urActive\n                    ? t(\"animatedQrProgress\")\n                    : isScanningEnabled\n                      ? t(\"qrScanReady\")\n                      : t(\"qrScanPaused\")\n              }\n              color={hi[highlight]}\n              iconName={\n                isClaimingToken\n                  ? \"hourglass-top\"\n                  : urActive\n                    ? \"qr-code-scanner\"\n                    : \"center-focus-strong\"\n              }\n            />\n            <Text style={styles.title}>{t(\"qrScanHint\")}</Text>\n            <Text style={styles.subtitle}>{t(\"qrScanFormats\")}</Text>\n          </View>\n\n          <View style={[styles.focusFrame, { borderColor: `${hi[highlight]}66` }]}>\n            <FrameCorner position=\"topLeft\" color={hi[highlight]} />\n            <FrameCorner position=\"topRight\" color={hi[highlight]} />\n            <FrameCorner position=\"bottomLeft\" color={hi[highlight]} />\n            <FrameCorner position=\"bottomRight\" color={hi[highlight]} />\n          </View>\n\n          <View style={styles.bottomDock}>\n            {isClaimingToken && (\n              <View style={styles.progressWrap}>\n                <View style={styles.loadingState}>\n                  <Loading size={s(24)} color={hi[highlight]} />\n                  <Text style={styles.progressTitle}>{t(\"claiming\", { ns: NS.wallet })}</Text>\n                </View>\n              </View>\n            )}\n            {!isClaimingToken && urActive && (\n              <View style={styles.progressWrap}>\n                <View style={styles.progressHeader}>\n                  <Text style={styles.progressTitle}>{t(\"receivingAnimatedQr\")}</Text>\n                  <Text style={[styles.progressCount, { color: hi[highlight] }]}>\n                    {receivedCount}/{expectedCount || \"-\"}\n                  </Text>\n                </View>\n                <View style={styles.progressTrack}>\n                  <View\n                    style={[\n                      styles.progressFill,\n                      { width: `${Math.min(estimated, 1) * 100}%`, backgroundColor: hi[highlight] },\n                    ]}\n                  />\n                </View>\n                {urError && <Text style={styles.errorText}>{urError}</Text>}\n              </View>\n            )}\n            {!isClaimingToken && !isScanningEnabled && (\n              <TouchableOpacity\n                accessibilityRole=\"button\"\n                style={[styles.rescanButton, { backgroundColor: hi[highlight] }]}\n                onPress={handleRescan}\n                activeOpacity={0.75}\n              >\n                <MaterialIcons name=\"refresh\" size={s(18)} color={getColor(highlight, color)} />\n                <Text style={[styles.rescanButtonText, { color: getColor(highlight, color) }]}>\n                  {t(\"scanAgain\")}\n                </Text>\n              </TouchableOpacity>\n            )}\n          </View>\n        </View>\n        {nfcPaymentModal}\n      </View>\n    </Screen>\n  );\n}\n\nexport default QrScannerScreen;\n\ninterface IStatusPillProps {\n  label: string;\n  color: string;\n  iconName: ComponentProps<typeof MaterialIcons>[\"name\"];\n}\n\nfunction StatusPill({ label, color, iconName }: IStatusPillProps) {\n  return (\n    <View style={[styles.statusPill, { borderColor: `${color}55` }]}>\n      <MaterialIcons name={iconName} size={s(16)} color={color} />\n      <Text style={styles.statusText}>{label}</Text>\n    </View>\n  );\n}\n\ntype TFrameCornerPosition = \"topLeft\" | \"topRight\" | \"bottomLeft\" | \"bottomRight\";\n\ninterface IFrameCornerProps {\n  position: TFrameCornerPosition;\n  color: string;\n}\n\nfunction FrameCorner({ position, color }: IFrameCornerProps) {\n  const positionStyle = {\n    topLeft: styles.cornerTopLeft,\n    topRight: styles.cornerTopRight,\n    bottomLeft: styles.cornerBottomLeft,\n    bottomRight: styles.cornerBottomRight,\n  }[position];\n\n  return (\n    <View style={[styles.corner, positionStyle]}>\n      <View style={[styles.cornerHorizontal, { backgroundColor: color }]} />\n      <View style={[styles.cornerVertical, { backgroundColor: color }]} />\n    </View>\n  );\n}\n\nconst styles = ScaledSheet.create({\n  camera: {\n    ...StyleSheet.absoluteFillObject,\n  },\n  cameraContainer: {\n    flex: 1,\n  },\n  scrim: {\n    ...StyleSheet.absoluteFillObject,\n    backgroundColor: \"rgba(0, 0, 0, 0.42)\",\n  },\n  scanSurface: {\n    flex: 1,\n    alignItems: \"center\",\n    justifyContent: \"space-between\",\n    paddingHorizontal: \"24@s\",\n    paddingTop: \"26@vs\",\n    paddingBottom: \"26@vs\",\n  },\n  headerCopy: {\n    width: \"100%\",\n    alignItems: \"center\",\n  },\n  headerAction: {\n    width: \"40@s\",\n    height: \"40@s\",\n    borderRadius: \"20@s\",\n    borderWidth: 1,\n    alignItems: \"center\",\n    justifyContent: \"center\",\n  },\n  statusPill: {\n    flexDirection: \"row\",\n    alignItems: \"center\",\n    columnGap: \"8@s\",\n    borderWidth: 1,\n    borderRadius: \"999@s\",\n    paddingHorizontal: \"12@s\",\n    paddingVertical: \"8@vs\",\n    backgroundColor: \"rgba(0, 0, 0, 0.36)\",\n    marginBottom: \"18@vs\",\n  },\n  statusText: {\n    color: mainColors.WHITE,\n    fontSize: \"12@vs\",\n    fontWeight: \"600\",\n  },\n  title: {\n    color: mainColors.WHITE,\n    fontSize: \"24@vs\",\n    lineHeight: \"30@vs\",\n    fontWeight: \"600\",\n    textAlign: \"center\",\n  },\n  subtitle: {\n    color: \"rgba(250, 250, 250, 0.72)\",\n    fontSize: \"13@vs\",\n    lineHeight: \"19@vs\",\n    textAlign: \"center\",\n    marginTop: \"8@vs\",\n  },\n  focusFrame: {\n    width: \"268@s\",\n    height: \"268@s\",\n    borderRadius: \"34@s\",\n    borderWidth: 1,\n    backgroundColor: \"rgba(255, 255, 255, 0.04)\",\n    overflow: \"hidden\",\n  },\n  corner: {\n    position: \"absolute\",\n    width: \"56@s\",\n    height: \"56@s\",\n  },\n  cornerTopLeft: {\n    top: \"12@s\",\n    left: \"12@s\",\n  },\n  cornerTopRight: {\n    top: \"12@s\",\n    right: \"12@s\",\n    transform: [{ rotate: \"90deg\" }],\n  },\n  cornerBottomLeft: {\n    bottom: \"12@s\",\n    left: \"12@s\",\n    transform: [{ rotate: \"-90deg\" }],\n  },\n  cornerBottomRight: {\n    right: \"12@s\",\n    bottom: \"12@s\",\n    transform: [{ rotate: \"180deg\" }],\n  },\n  cornerHorizontal: {\n    width: \"44@s\",\n    height: \"4@s\",\n    borderRadius: \"999@s\",\n  },\n  cornerVertical: {\n    width: \"4@s\",\n    height: \"44@s\",\n    borderRadius: \"999@s\",\n    marginTop: \"-4@s\",\n  },\n  bottomDock: {\n    width: \"100%\",\n    minHeight: \"92@vs\",\n    justifyContent: \"flex-end\",\n  },\n  progressWrap: {\n    width: \"100%\",\n    padding: \"18@s\",\n    borderRadius: \"24@s\",\n    backgroundColor: \"rgba(0, 0, 0, 0.58)\",\n    borderWidth: 1,\n    borderColor: \"rgba(255, 255, 255, 0.12)\",\n    marginBottom: \"12@vs\",\n  },\n  progressHeader: {\n    flexDirection: \"row\",\n    alignItems: \"center\",\n    justifyContent: \"space-between\",\n    marginBottom: \"12@vs\",\n  },\n  loadingState: {\n    flexDirection: \"row\",\n    alignItems: \"center\",\n    justifyContent: \"center\",\n    columnGap: \"12@s\",\n    minHeight: \"40@vs\",\n  },\n  progressTitle: {\n    color: mainColors.WHITE,\n    fontSize: \"14@vs\",\n    fontWeight: \"600\",\n  },\n  progressCount: {\n    fontSize: \"13@vs\",\n    fontWeight: \"700\",\n  },\n  progressTrack: {\n    width: \"100%\",\n    height: \"5@vs\",\n    borderRadius: \"999@s\",\n    backgroundColor: \"rgba(255, 255, 255, 0.16)\",\n    overflow: \"hidden\",\n  },\n  progressFill: {\n    height: \"100%\",\n    borderRadius: \"999@s\",\n  },\n  rescanButton: {\n    width: \"100%\",\n    minHeight: \"54@vs\",\n    borderRadius: \"999@s\",\n    flexDirection: \"row\",\n    alignItems: \"center\",\n    justifyContent: \"center\",\n    columnGap: \"8@s\",\n  },\n  rescanButtonText: {\n    color: mainColors.WHITE,\n    fontSize: \"15@vs\",\n    fontWeight: \"600\",\n  },\n  errorText: {\n    color: mainColors.ERROR,\n    marginTop: \"10@vs\",\n    textAlign: \"center\",\n    fontSize: \"12@vs\",\n  },\n});\n"
  },
  {
    "path": "src/screens/QRScan/components/CameraPermission.tsx",
    "content": "import Button from \"@comps/Button\";\nimport Txt from \"@comps/Txt\";\nimport { useThemeContext } from \"@src/context/Theme\";\nimport { NS } from \"@src/i18n\";\nimport { highlight as hi } from \"@styles\";\nimport MaterialIcons from \"@expo/vector-icons/MaterialIcons\";\nimport { useTranslation } from \"react-i18next\";\nimport { View } from \"react-native\";\nimport { ScaledSheet, s } from \"react-native-size-matters\";\n\ninterface ICameraPermissionProps {\n  canAskAgain: boolean;\n  onRequestPermission: () => void;\n  onOpenSettings: () => void;\n}\n\nexport default function CameraPermission({\n  canAskAgain,\n  onRequestPermission,\n  onOpenSettings,\n}: ICameraPermissionProps) {\n  const { color, highlight } = useThemeContext();\n  const { t } = useTranslation([NS.common]);\n\n  return (\n    <View style={styles.container}>\n      <View\n        style={[\n          styles.stage,\n          {\n            backgroundColor: color.DRAWER,\n            borderColor: color.DARK_BORDER,\n          },\n        ]}\n      >\n        <View style={[styles.iconContainer, { backgroundColor: `${hi[highlight]}18` }]}>\n          <MaterialIcons name=\"photo-camera\" size={s(36)} color={hi[highlight]} />\n        </View>\n        <View style={styles.framePreview}>\n          <View\n            style={[\n              styles.previewCorner,\n              styles.previewCornerTopLeft,\n              { borderColor: hi[highlight] },\n            ]}\n          />\n          <View\n            style={[\n              styles.previewCorner,\n              styles.previewCornerTopRight,\n              { borderColor: hi[highlight] },\n            ]}\n          />\n          <View\n            style={[\n              styles.previewCorner,\n              styles.previewCornerBottomLeft,\n              { borderColor: hi[highlight] },\n            ]}\n          />\n          <View\n            style={[\n              styles.previewCorner,\n              styles.previewCornerBottomRight,\n              { borderColor: hi[highlight] },\n            ]}\n          />\n        </View>\n      </View>\n      <Txt\n        txt={canAskAgain ? t(\"cameraAccessRequired\") : t(\"cameraAccessDenied\")}\n        bold\n        center\n        styles={[styles.title]}\n      />\n      <Txt\n        txt={canAskAgain ? t(\"cameraAccessRequiredHint\") : t(\"cameraAccessDeniedHint\")}\n        center\n        styles={[styles.description, { color: color.TEXT_SECONDARY }]}\n      />\n      <View style={styles.buttonContainer}>\n        <Button\n          txt={canAskAgain ? t(\"allowCameraAccess\") : t(\"openSettings\")}\n          onPress={canAskAgain ? onRequestPermission : onOpenSettings}\n        />\n      </View>\n    </View>\n  );\n}\n\nconst styles = ScaledSheet.create({\n  container: {\n    flex: 1,\n    alignItems: \"center\",\n    justifyContent: \"center\",\n    paddingHorizontal: \"24@s\",\n  },\n  stage: {\n    width: \"190@s\",\n    height: \"190@s\",\n    borderRadius: \"42@s\",\n    borderWidth: 1,\n    alignItems: \"center\",\n    justifyContent: \"center\",\n    marginBottom: \"28@vs\",\n  },\n  iconContainer: {\n    width: \"78@s\",\n    height: \"78@s\",\n    borderRadius: \"39@s\",\n    alignItems: \"center\",\n    justifyContent: \"center\",\n  },\n  framePreview: {\n    position: \"absolute\",\n    width: \"140@s\",\n    height: \"140@s\",\n  },\n  previewCorner: {\n    position: \"absolute\",\n    width: \"28@s\",\n    height: \"28@s\",\n    opacity: 0.48,\n  },\n  previewCornerTopLeft: {\n    top: 0,\n    left: 0,\n    borderTopWidth: \"3@s\",\n    borderLeftWidth: \"3@s\",\n    borderTopLeftRadius: \"14@s\",\n  },\n  previewCornerTopRight: {\n    top: 0,\n    right: 0,\n    borderTopWidth: \"3@s\",\n    borderRightWidth: \"3@s\",\n    borderTopRightRadius: \"14@s\",\n  },\n  previewCornerBottomLeft: {\n    bottom: 0,\n    left: 0,\n    borderBottomWidth: \"3@s\",\n    borderLeftWidth: \"3@s\",\n    borderBottomLeftRadius: \"14@s\",\n  },\n  previewCornerBottomRight: {\n    right: 0,\n    bottom: 0,\n    borderRightWidth: \"3@s\",\n    borderBottomWidth: \"3@s\",\n    borderBottomRightRadius: \"14@s\",\n  },\n  title: {\n    fontSize: \"24@vs\",\n    marginBottom: \"10@vs\",\n  },\n  description: {\n    fontSize: \"14@vs\",\n    lineHeight: \"20@vs\",\n    marginBottom: \"30@vs\",\n    paddingHorizontal: \"16@s\",\n  },\n  buttonContainer: {\n    width: \"100%\",\n    paddingHorizontal: \"20@s\",\n  },\n});\n"
  },
  {
    "path": "src/screens/QRScan/hooks/useScanResult.ts",
    "content": "import { useCallback, useEffect, useMemo, useRef, useState } from \"react\";\nimport { useUrDecoder } from \"@comps/hooks/useUrDecoder\";\nimport { parsePaymentString, type PaymentStringCandidate } from \"@util/paymentStringParser\";\n\nconst useScanResult = () => {\n  const {\n    addPart,\n    reset: resetUr,\n    active: urActive,\n    complete: urComplete,\n    estimated,\n    expectedCount,\n    receivedCount,\n    decodedString,\n    error: urError,\n  } = useUrDecoder({ allowedTypes: [\"bytes\"] });\n\n  const [candidates, setCandidates] = useState<PaymentStringCandidate[] | undefined>(undefined);\n  const handledRef = useRef(false);\n\n  const reset = useCallback(() => {\n    handledRef.current = false;\n    setCandidates(undefined);\n    resetUr();\n  }, [resetUr]);\n\n  // When UR completes, parse the decoded string\n  useEffect(() => {\n    if (!urComplete || !decodedString || handledRef.current) return;\n    setCandidates(parsePaymentString(decodedString));\n    handledRef.current = true;\n  }, [urComplete, decodedString]);\n\n  const onScan = useCallback(\n    (data: string) => {\n      if (handledRef.current) return;\n\n      const content = String(data || \"\");\n      const lower = content.trim().toLowerCase();\n\n      if (lower.startsWith(\"ur:\")) {\n        const { accepted } = addPart(content);\n        if (accepted) {\n          // Keep scanning to accumulate parts\n          return;\n        }\n        // Fall through to normal parsing if not accepted\n      }\n\n      setCandidates(parsePaymentString(content));\n      handledRef.current = true;\n    },\n    [addPart],\n  );\n\n  const complete = useMemo(() => Boolean(candidates), [candidates]);\n  const active = urActive;\n  const error = urError;\n\n  return {\n    onScan,\n    reset,\n    active,\n    complete,\n    estimated,\n    expectedCount,\n    receivedCount,\n    error,\n    candidates,\n  };\n};\n\nexport default useScanResult;\n"
  },
  {
    "path": "src/screens/Restore/Recover.tsx",
    "content": "import Button, { TxtButton } from \"@comps/Button\";\nimport useLoading from \"@comps/hooks/Loading\";\nimport Loading from \"@comps/Loading\";\nimport Screen from \"@comps/Screen\";\nimport Txt from \"@comps/Txt\";\nimport TxtInput from \"@comps/TxtInput\";\nimport type { RecoverScreenProps } from \"@src/nav/navTypes\";\nimport { NS } from \"@src/i18n\";\nimport { useKnownMints } from \"@src/context/KnownMints\";\nimport { seedService } from \"@src/services/SeedService\";\nimport { getStrFromClipboard } from \"@util\";\nimport { createRef, useEffect, useState } from \"react\";\nimport { useTranslation } from \"react-i18next\";\nimport { type TextInput, View } from \"react-native\";\nimport { s, ScaledSheet } from \"react-native-size-matters\";\n\nexport default function RecoverScreen({ navigation }: RecoverScreenProps) {\n  const { t } = useTranslation([NS.common]);\n  const [input, setInput] = useState(\"\");\n  const { loading } = useLoading();\n  const inputRef = createRef<TextInput>();\n  const { knownMints } = useKnownMints();\n\n  const handlePaste = async () => {\n    const clipboard = await getStrFromClipboard();\n    if (!clipboard) {\n      return;\n    }\n    setInput(clipboard);\n  };\n\n  const handleBtnPress = async () => {\n    if (loading || !input.length) {\n      return;\n    }\n    const seed = seedService.convertMnemonicToSeed(input);\n\n    navigation.navigate(\"Recovering\", {\n      bip39seed: seed,\n      mintUrls: knownMints.map((mint) => mint.mintUrl),\n    });\n  };\n\n  // auto-focus keyboard\n  useEffect(() => {\n    const t = setTimeout(() => {\n      inputRef.current?.focus();\n      clearTimeout(t);\n    }, 200);\n    // eslint-disable-next-line react-hooks/exhaustive-deps\n  }, []);\n\n  return (\n    <Screen\n      screenName={t(\"walletRecovery\")}\n      withBackBtn\n      handlePress={() => navigation.goBack()}\n      withKeyboard={true}\n    >\n      <View style={styles.container}>\n        <View style={{ paddingHorizontal: s(8) }}>\n          <Txt txt={t(\"recoveryHint\")} styles={[styles.hint]} bold />\n          <View style={styles.labelRow}>\n            <Txt txt={t(\"12WordMnemonic\")} styles={[styles.label]} />\n            <TxtButton\n              txt={t(\"paste\")}\n              onPress={() => void handlePaste()}\n              style={[styles.pasteBtn]}\n            />\n          </View>\n          <TxtInput\n            autoCapitalize=\"none\"\n            multiline\n            innerRef={inputRef}\n            placeholder=\"\"\n            onChangeText={(text) => setInput(text)}\n            onSubmitEditing={() => void handleBtnPress()}\n            autoFocus\n            ms={200}\n            style={[styles.multilineInput]}\n            value={input}\n          />\n        </View>\n        <View style={styles.actionWrap}>\n          <Button\n            disabled={!input.length}\n            txt={t(\"confirm\")}\n            onPress={() => void handleBtnPress()}\n            icon={loading ? <Loading size={20} /> : undefined}\n          />\n        </View>\n      </View>\n    </Screen>\n  );\n}\n\nconst styles = ScaledSheet.create({\n  container: {\n    flex: 1,\n    justifyContent: \"space-between\",\n  },\n  action: {\n    flexDirection: \"row\",\n    alignItems: \"center\",\n    width: \"100%\",\n  },\n  hint: {\n    marginBottom: \"20@vs\",\n  },\n  labelRow: {\n    flexDirection: \"row\",\n    justifyContent: \"space-between\",\n    alignItems: \"center\",\n    marginBottom: \"8@vs\",\n  },\n  label: {\n    flex: 1,\n  },\n  pasteBtn: {\n    paddingTop: 0,\n    paddingBottom: 0,\n  },\n  actionWrap: {\n    marginBottom: \"20@s\",\n  },\n  multilineInput: {\n    minHeight: \"80@s\",\n    borderRadius: 25,\n    padding: \"10@s\",\n  },\n});\n"
  },
  {
    "path": "src/screens/Restore/Recovering.tsx",
    "content": "import Button from \"@comps/Button\";\nimport Loading from \"@comps/Loading\";\nimport Logo from \"@comps/Logo\";\nimport Progress from \"@comps/Progress\";\nimport Txt from \"@comps/Txt\";\nimport type { IRecoveringPageProps, TBeforeRemoveEvent } from \"@model/nav\";\nimport { preventBack } from \"@nav/utils\";\nimport { useManager } from \"@src/context/Manager\";\nimport { useThemeContext } from \"@src/context/Theme\";\nimport { NS } from \"@src/i18n\";\nimport { appLogger } from \"@src/logger\";\nimport { vib } from \"@src/util\";\nimport { globals } from \"@styles\";\nimport LottieView from \"lottie-react-native\";\nimport { useEffect, useMemo, useState } from \"react\";\nimport { useTranslation } from \"react-i18next\";\nimport { Text, View } from \"react-native\";\nimport { useSafeAreaInsets } from \"react-native-safe-area-context\";\nimport { s, ScaledSheet, vs } from \"react-native-size-matters\";\n\n// TODO\n// show internet connection status\n// show different quotes messages during the process\n\nexport default function RecoveringScreen({ navigation, route }: IRecoveringPageProps) {\n  const manager = useManager();\n  const { t } = useTranslation([NS.common]);\n  const insets = useSafeAreaInsets();\n  const [current, setCurrent] = useState(0);\n  const [isDone, setIsDone] = useState(false);\n  const [error, setError] = useState<string | null>(null);\n  const { bip39seed, mintUrls } = route.params;\n\n  useEffect(() => {\n    const restore = async () => {\n      try {\n        for (let i = 0; i < mintUrls.length; i++) {\n          const mintUrl = mintUrls[i];\n          await manager.wallet.sweep(mintUrl, bip39seed);\n          setCurrent(i + 1);\n        }\n        setIsDone(true);\n        vib(300);\n      } catch (e) {\n        setError(\"Restore failed\");\n        appLogger.error(\"Restore failed\", { error: e });\n        setTimeout(() => {\n          navigation.navigate(\"dashboard\");\n        }, 3000);\n      }\n    };\n    restore();\n  }, []);\n\n  const { color } = useThemeContext();\n\n  useEffect(() => {\n    const backHandler = (e: TBeforeRemoveEvent) => preventBack(e, navigation.dispatch);\n    navigation.addListener(\"beforeRemove\", backHandler);\n    return () => navigation.removeListener(\"beforeRemove\", backHandler);\n  }, [navigation]);\n\n  const progress = useMemo(() => {\n    if (!mintUrls?.length) return 0;\n    return Math.min(1, current / mintUrls.length);\n  }, [current, mintUrls]);\n\n  if (isDone) {\n    return (\n      <View style={[styles.containerSuccess, { backgroundColor: color.BACKGROUND }]}>\n        <View pointerEvents=\"none\" style={styles.confetti}>\n          <LottieView\n            source={require(\"../../../assets/lottie/confetti.json\")}\n            autoPlay\n            loop={false}\n            style={{ width: \"100%\", height: \"100%\" }}\n          />\n        </View>\n        <Logo size={s(230)} style={styles.img} success />\n        <View style={{ width: \"100%\" }}>\n          <Text style={[styles.successTxt, { color: color.TEXT }]}>Wallet restored!</Text>\n          <View style={styles.successAnim}>\n            <LottieView\n              source={require(\"../../../assets/lottie/success.json\")}\n              autoPlay\n              loop={false}\n              style={styles.lottie}\n            />\n          </View>\n        </View>\n        <View style={[styles.btnWrap, { marginBottom: insets.bottom || 20 }]}>\n          <Button txt={t(\"backToDashboard\")} onPress={() => navigation.navigate(\"dashboard\")} />\n        </View>\n      </View>\n    );\n  }\n\n  return (\n    <View style={[globals(color).container, styles.container]}>\n      <Loading size={s(35)} />\n      <Txt styles={[styles.descText]} txt={t(\"recoveringWallet\")} />\n      <View style={{ width: \"100%\", paddingHorizontal: s(20) }}>\n        <Progress progress={progress} />\n        <Txt\n          center\n          styles={[styles.hint, { color: color.TEXT_SECONDARY }]}\n          txt={`${t(\"restored\")} ${current}/${mintUrls.length}`}\n        />\n        <Txt\n          center\n          styles={[styles.hint, { color: color.TEXT_SECONDARY, marginTop: vs(6) }]}\n          txt={t(\"dontClose\")}\n        />\n      </View>\n      {error && <Txt center styles={[styles.errorTxt]} txt={error} />}\n    </View>\n  );\n}\n\nconst styles = ScaledSheet.create({\n  container: {\n    paddingTop: 0,\n    alignItems: \"center\",\n    justifyContent: \"center\",\n    paddingHorizontal: \"20@s\",\n  },\n  descText: {\n    marginTop: \"20@s\",\n    marginBottom: \"30@s\",\n    textAlign: \"center\",\n    fontSize: \"20@s\",\n  },\n  hint: {\n    fontSize: \"12@s\",\n    marginTop: \"10@s\",\n  },\n  errorTxt: {\n    fontSize: \"12@s\",\n    marginTop: \"14@s\",\n    color: \"#ff5a5f\",\n  },\n  // Success styles\n  containerSuccess: {\n    flex: 1,\n    padding: \"20@s\",\n  },\n  img: {\n    marginTop: \"90@s\",\n    height: \"90@s\",\n    opacity: 0.8,\n  },\n  successTxt: {\n    fontSize: \"28@vs\",\n    fontWeight: \"800\",\n    textAlign: \"center\",\n    marginTop: \"30@vs\",\n  },\n  successAnim: {\n    justifyContent: \"center\",\n    alignItems: \"center\",\n    marginTop: \"20@vs\",\n  },\n  lottie: {\n    width: \"100@s\",\n    height: \"100@s\",\n  },\n  btnWrap: {\n    position: \"absolute\",\n    bottom: 0,\n    right: 0,\n    left: 0,\n    paddingHorizontal: \"20@s\",\n  },\n  confetti: {\n    position: \"absolute\",\n    top: 0,\n    right: 0,\n    bottom: 0,\n    left: 0,\n  },\n});\n"
  },
  {
    "path": "src/screens/Restore/SelectRecoveryMint.tsx",
    "content": "import Button from \"@comps/Button\";\nimport { highlight as hi } from \"@styles\";\nimport { CheckmarkIcon } from \"@comps/Icons\";\nimport { ScreenWithKeyboard } from \"@comps/Screen\";\nimport Txt from \"@comps/Txt\";\nimport { isIOS } from \"@consts\";\nimport type { RecoverMintsScreenProps } from \"@src/nav/navTypes\";\nimport { useKnownMints } from \"@src/context/KnownMints\";\nimport { useThemeContext } from \"@src/context/Theme\";\nimport { NS } from \"@src/i18n\";\nimport { globals } from \"@styles\";\nimport { useState } from \"react\";\nimport { useTranslation } from \"react-i18next\";\nimport { ScrollView, TouchableOpacity, View } from \"react-native\";\nimport { s, ScaledSheet } from \"react-native-size-matters\";\nimport { vs } from \"react-native-size-matters\";\n\nexport default function SelectRecoveryMintScreen({ navigation }: RecoverMintsScreenProps) {\n  const { t } = useTranslation([NS.common]);\n  const { highlight, color } = useThemeContext();\n\n  const { knownMints } = useKnownMints();\n  const [selectedMints, setSelectedMints] = useState<string[]>(\n    knownMints.map((mint) => mint.mintUrl),\n  );\n\n  const toggleMintSelection = (mintUrl: string) => {\n    setSelectedMints((prev) =>\n      prev.includes(mintUrl) ? prev.filter((m) => m !== mintUrl) : [...prev, mintUrl],\n    );\n  };\n\n  return (\n    <ScreenWithKeyboard\n      screenName={t(\"walletRecovery\")}\n      withBackBtn\n      handlePress={() => navigation.goBack()}\n    >\n      <View style={{ flex: 1, gap: s(10) }}>\n        <Txt txt={t(\"selectRestoreMint\")} styles={[styles.hint]} bold />\n        <ScrollView alwaysBounceVertical={false} style={{ flex: 1 }}>\n          {knownMints.length > 0 ? (\n            <View style={{ flex: 1, gap: s(4) }}>\n              {knownMints.map((mint) => {\n                const isSelected = selectedMints.includes(mint.mintUrl);\n                return (\n                  <TouchableOpacity\n                    key={mint.mintUrl}\n                    style={[\n                      styles.mintItem,\n                      isSelected && {\n                        backgroundColor: hi[highlight] + \"20\",\n                        borderColor: hi[highlight],\n                      },\n                    ]}\n                    onPress={() => toggleMintSelection(mint.mintUrl)}\n                    activeOpacity={0.7}\n                  >\n                    <View style={styles.mintContent}>\n                      <Txt txt={mint.mintUrl} styles={[{ flex: 1 }]} />\n                      {isSelected && (\n                        <CheckmarkIcon width={vs(14)} height={vs(14)} color={hi[highlight]} />\n                      )}\n                    </View>\n                  </TouchableOpacity>\n                );\n              })}\n            </View>\n          ) : (\n            <View style={styles.emptyContainer}>\n              <Txt txt={t(\"noMint\")} />\n            </View>\n          )}\n        </ScrollView>\n        <View style={styles.btnWrap}>\n          <Button\n            disabled={selectedMints.length === 0}\n            txt={t(\"confirm\")}\n            onPress={() => {\n              navigation.navigate(\"Recover\");\n            }}\n          />\n        </View>\n      </View>\n    </ScreenWithKeyboard>\n  );\n}\n\nconst styles = ScaledSheet.create({\n  hint: {\n    paddingHorizontal: \"20@s\",\n    marginBottom: \"20@vs\",\n  },\n  mintItem: {\n    padding: \"16@s\",\n    borderRadius: \"12@s\",\n    borderWidth: 2,\n    borderColor: \"transparent\",\n    marginBottom: \"8@s\",\n  },\n  mintContent: {\n    flexDirection: \"row\",\n    alignItems: \"center\",\n    gap: \"12@s\",\n  },\n  emptyContainer: {\n    padding: \"20@s\",\n    alignItems: \"center\",\n  },\n  btnWrap: {\n    marginHorizontal: \"20@s\",\n    marginTop: \"20@s\",\n    marginBottom: isIOS ? \"0@s\" : \"20@s\",\n  },\n});\n"
  },
  {
    "path": "src/screens/Settings/Currency.tsx",
    "content": "import Button from \"@comps/Button\";\nimport RadioBtn from \"@comps/RadioBtn\";\nimport Screen from \"@comps/Screen\";\nimport Separator from \"@comps/Separator\";\nimport Toggle from \"@comps/Toggle\";\nimport Txt from \"@comps/Txt\";\nimport type { TCurrencySettingsPageProps } from \"@model/nav\";\nimport { useCurrencyContext } from \"@src/context/Currency\";\nimport { useThemeContext } from \"@src/context/Theme\";\nimport { NS } from \"@src/i18n\";\nimport type { TCurrencyCode } from \"@model\";\nimport { globals, mainColors } from \"@styles\";\nimport { useTranslation } from \"react-i18next\";\nimport { ActivityIndicator, ScrollView, TouchableOpacity, View } from \"react-native\";\nimport { s, ScaledSheet, vs } from \"react-native-size-matters\";\n\n// Common currencies to display at the top\nconst COMMON_CURRENCIES: TCurrencyCode[] = [\"USD\", \"EUR\", \"GBP\", \"JPY\", \"CHF\", \"CAD\", \"AUD\", \"CNY\"];\n\nexport default function CurrencySettings({ navigation }: TCurrencySettingsPageProps) {\n  const { t } = useTranslation([NS.common]);\n  const { color } = useThemeContext();\n  const {\n    rates,\n    selectedCurrency,\n    setSelectedCurrency,\n    formatBalance,\n    setFormatBalance,\n    isLoading,\n    lastUpdate,\n    error,\n    refreshRates,\n  } = useCurrencyContext();\n\n  // Determine if rates are unavailable (error state)\n  const hasRatesError = !isLoading && !rates && !!error;\n  const ratesUnavailable = !rates;\n\n  // Sort currencies: common ones first, then alphabetically\n  const sortedCurrencies = rates\n    ? Object.keys(rates).sort((a, b) => {\n        const aIsCommon = COMMON_CURRENCIES.includes(a);\n        const bIsCommon = COMMON_CURRENCIES.includes(b);\n        if (aIsCommon && !bIsCommon) return -1;\n        if (!aIsCommon && bIsCommon) return 1;\n        if (aIsCommon && bIsCommon) {\n          return COMMON_CURRENCIES.indexOf(a) - COMMON_CURRENCIES.indexOf(b);\n        }\n        return a.localeCompare(b);\n      })\n    : [];\n\n  const handleCurrencySelect = async (currency: TCurrencyCode) => {\n    // Don't allow selection if rates are unavailable\n    if (ratesUnavailable) return;\n    await setSelectedCurrency(currency);\n  };\n\n  const handleToggleFormatBalance = async () => {\n    // Don't allow toggle if rates are unavailable\n    if (ratesUnavailable) return;\n    await setFormatBalance(!formatBalance);\n  };\n\n  const handleRetry = async () => {\n    await refreshRates();\n  };\n\n  const formatLastUpdate = () => {\n    if (!lastUpdate) return \"\";\n    const date = new Date(lastUpdate);\n    return date.toLocaleTimeString(undefined, {\n      hour: \"2-digit\",\n      minute: \"2-digit\",\n    });\n  };\n\n  return (\n    <Screen\n      screenName={t(\"currency\", { ns: NS.topNav })}\n      withBackBtn\n      handlePress={() => navigation.goBack()}\n    >\n      <ScrollView alwaysBounceVertical={false}>\n        {/* Error Banner */}\n        {hasRatesError && (\n          <View style={[styles.errorContainer, { backgroundColor: mainColors.ERROR }]}>\n            <Txt txt={t(\"ratesUnavailable\")} styles={[styles.errorText]} />\n            <Txt txt={t(\"ratesUnavailableDesc\")} styles={[styles.errorDescription]} />\n            <Button txt={t(\"retry\")} onPress={handleRetry} outlined loading={isLoading} />\n          </View>\n        )}\n\n        {/* Enable Currency Conversion Toggle */}\n        <Txt txt={t(\"currencyConversion\")} bold styles={[styles.subHeader]} />\n        <View style={globals(color).wrapContainer}>\n          <TouchableOpacity\n            style={styles.toggleRow}\n            onPress={handleToggleFormatBalance}\n            disabled={ratesUnavailable}\n          >\n            <View style={styles.toggleTextContainer}>\n              <Txt\n                txt={t(\"showFiatBalance\")}\n                styles={[\n                  {\n                    color: ratesUnavailable ? color.TEXT_SECONDARY : color.TEXT,\n                  },\n                ]}\n              />\n              <Txt\n                txt={ratesUnavailable ? t(\"ratesRequiredForFiat\") : t(\"showFiatBalanceDesc\")}\n                styles={[styles.description, { color: color.TEXT_SECONDARY }]}\n              />\n            </View>\n            <View style={styles.toggleContainer}>\n              <Toggle\n                value={formatBalance}\n                onChange={handleToggleFormatBalance}\n                disabled={ratesUnavailable}\n              />\n            </View>\n          </TouchableOpacity>\n        </View>\n\n        {/* Currency Selection */}\n        <View style={styles.currencyHeader}>\n          <Txt txt={t(\"selectCurrency\")} bold styles={[styles.subHeader]} />\n          {lastUpdate && (\n            <Txt\n              txt={`${t(\"lastUpdate\")}: ${formatLastUpdate()}`}\n              styles={[styles.lastUpdate, { color: color.TEXT_SECONDARY }]}\n            />\n          )}\n        </View>\n\n        {isLoading && !rates ? (\n          <View style={styles.loadingContainer}>\n            <ActivityIndicator size=\"large\" color={color.TEXT} />\n            <Txt\n              txt={t(\"loadingRates\")}\n              styles={[styles.loadingText, { color: color.TEXT_SECONDARY }]}\n            />\n          </View>\n        ) : hasRatesError ? (\n          <View style={[globals(color).wrapContainer, styles.emptyContainer]}>\n            <Txt\n              txt={t(\"noCurrenciesAvailable\")}\n              styles={[styles.emptyText, { color: color.TEXT_SECONDARY }]}\n            />\n          </View>\n        ) : (\n          <View style={[globals(color).wrapContainer, { marginBottom: s(80) }]}>\n            {sortedCurrencies.map((currency, i) => (\n              <CurrencySelection\n                key={currency}\n                code={currency}\n                symbol={rates?.[currency]?.symbol || currency}\n                selected={currency === selectedCurrency}\n                hasSeparator={i !== sortedCurrencies.length - 1}\n                onSelect={handleCurrencySelect}\n                disabled={!formatBalance || ratesUnavailable}\n              />\n            ))}\n          </View>\n        )}\n      </ScrollView>\n    </Screen>\n  );\n}\n\ninterface ICurrencySelectionProps {\n  code: TCurrencyCode;\n  symbol: string;\n  selected: boolean;\n  hasSeparator?: boolean;\n  onSelect: (code: TCurrencyCode) => void;\n  disabled?: boolean;\n}\n\nfunction CurrencySelection({\n  code,\n  symbol,\n  selected,\n  hasSeparator,\n  onSelect,\n  disabled,\n}: ICurrencySelectionProps) {\n  const { color } = useThemeContext();\n\n  return (\n    <>\n      <TouchableOpacity\n        style={[globals().wrapRow, { paddingBottom: vs(15) }]}\n        onPress={() => onSelect(code)}\n        disabled={disabled}\n      >\n        <View style={styles.currencyInfo}>\n          <Txt txt={code} bold styles={[{ color: disabled ? color.TEXT_SECONDARY : color.TEXT }]} />\n          <Txt\n            txt={symbol}\n            styles={[\n              styles.currencySymbol,\n              { color: disabled ? color.TEXT_SECONDARY : color.TEXT_SECONDARY },\n            ]}\n          />\n        </View>\n        <RadioBtn selected={selected} />\n      </TouchableOpacity>\n      {hasSeparator && <Separator style={[{ marginBottom: vs(15) }]} />}\n    </>\n  );\n}\n\nconst styles = ScaledSheet.create({\n  subHeader: {\n    paddingHorizontal: \"20@s\",\n    marginBottom: \"10@vs\",\n  },\n  toggleRow: {\n    flexDirection: \"row\",\n    alignItems: \"center\",\n    justifyContent: \"space-between\",\n    paddingBottom: \"15@vs\",\n  },\n  toggleTextContainer: {\n    flex: 1,\n    marginRight: \"16@s\",\n  },\n  toggleContainer: {\n    justifyContent: \"center\",\n    alignItems: \"center\",\n  },\n  description: {\n    fontSize: \"12@s\",\n    marginTop: \"4@vs\",\n  },\n  currencyHeader: {\n    flexDirection: \"row\",\n    justifyContent: \"space-between\",\n    alignItems: \"center\",\n    paddingRight: \"20@s\",\n  },\n  lastUpdate: {\n    fontSize: \"11@s\",\n  },\n  loadingContainer: {\n    padding: \"40@s\",\n    alignItems: \"center\",\n  },\n  loadingText: {\n    marginTop: \"12@vs\",\n  },\n  currencyInfo: {\n    flexDirection: \"row\",\n    alignItems: \"center\",\n  },\n  currencySymbol: {\n    marginLeft: \"12@s\",\n    fontSize: \"14@s\",\n  },\n  errorContainer: {\n    marginHorizontal: \"20@s\",\n    marginBottom: \"16@vs\",\n    padding: \"16@s\",\n    borderRadius: \"12@s\",\n    alignItems: \"center\",\n  },\n  errorText: {\n    color: \"#FFFFFF\",\n    fontWeight: \"600\",\n    fontSize: \"14@s\",\n    marginBottom: \"4@vs\",\n  },\n  errorDescription: {\n    color: \"#FFFFFF\",\n    fontSize: \"12@s\",\n    textAlign: \"center\",\n    marginBottom: \"12@vs\",\n    opacity: 0.9,\n  },\n  emptyContainer: {\n    padding: \"40@s\",\n    alignItems: \"center\",\n  },\n  emptyText: {\n    textAlign: \"center\",\n  },\n});\n"
  },
  {
    "path": "src/screens/Settings/Display.tsx",
    "content": "import RadioBtn from \"@comps/RadioBtn\";\nimport Screen from \"@comps/Screen\";\nimport Separator from \"@comps/Separator\";\nimport Toggle from \"@comps/Toggle\";\nimport Txt from \"@comps/Txt\";\nimport type { TDisplaySettingsPageProps } from \"@model/nav\";\nimport { useThemeContext } from \"@src/context/Theme\";\nimport { NS } from \"@src/i18n\";\nimport { globals, HighlightKey, themeColors } from \"@styles\";\nimport { useTranslation } from \"react-i18next\";\nimport { ScrollView, TouchableOpacity, View } from \"react-native\";\nimport { s, ScaledSheet } from \"react-native-size-matters\";\n\nexport default function DisplaySettings({ navigation }: TDisplaySettingsPageProps) {\n  const { t } = useTranslation([NS.common]);\n  const { updateMode, mode, color, highlight } = useThemeContext();\n  return (\n    <Screen\n      screenName={t(\"display\", { ns: NS.topNav })}\n      withBackBtn\n      handlePress={() => navigation.goBack()}\n    >\n      <ScrollView alwaysBounceVertical={false}>\n        <Txt txt=\"Theme\" bold styles={[styles.subHeader]} />\n        <View style={globals(color).wrapContainer}>\n          <TouchableOpacity style={[globals().wrapRow]} onPress={() => updateMode(\"dark\")}>\n            <Txt txt={t(\"darkMode\")} />\n            <RadioBtn selected={mode === \"dark\"} />\n          </TouchableOpacity>\n\n          <TouchableOpacity style={[globals().wrapRow]} onPress={() => updateMode(\"light\")}>\n            <Txt txt={t(\"lightMode\")} />\n            <RadioBtn selected={mode === \"light\"} />\n          </TouchableOpacity>\n          <TouchableOpacity style={[globals().wrapRow]} onPress={() => updateMode(\"auto\")}>\n            <Txt txt={t(\"autoMode\")} />\n            <RadioBtn selected={mode === \"auto\"} />\n          </TouchableOpacity>\n        </View>\n        <Txt txt=\"Highlight\" bold styles={[styles.subHeader]} />\n        <View style={[globals(color).wrapContainer, { marginBottom: s(80) }]}>\n          {themeColors.map((t, i) => (\n            <ThemeSelection\n              key={t}\n              name={t}\n              selected={t === highlight}\n              hasSeparator={i !== themeColors.length - 1}\n            />\n          ))}\n        </View>\n      </ScrollView>\n    </Screen>\n  );\n}\n\ninterface IThemeSelectionProps {\n  name: HighlightKey;\n  selected: boolean;\n  hasSeparator?: boolean;\n}\n\nfunction ThemeSelection({ name, selected, hasSeparator }: IThemeSelectionProps) {\n  const { t } = useTranslation([NS.common]);\n  const { updateHighlight } = useThemeContext();\n  return (\n    <>\n      <TouchableOpacity\n        style={[globals().wrapRow, { paddingBottom: s(15) }]}\n        onPress={() => updateHighlight(name)}\n      >\n        <Txt txt={name === \"Default\" ? t(\"default\") : name} />\n        <RadioBtn selected={selected} />\n      </TouchableOpacity>\n      {hasSeparator && <Separator style={[{ marginBottom: s(15) }]} />}\n    </>\n  );\n}\n\nconst styles = ScaledSheet.create({\n  subHeader: {\n    paddingHorizontal: \"20@s\",\n    marginBottom: \"10@vs\",\n  },\n});\n"
  },
  {
    "path": "src/screens/Settings/Language.tsx",
    "content": "import RadioBtn from \"@comps/RadioBtn\";\nimport Screen from \"@comps/Screen\";\nimport Separator from \"@comps/Separator\";\nimport Txt from \"@comps/Txt\";\nimport type { ILangsOpt, TranslationLangCodes, TTlLangNames } from \"@model/i18n\";\nimport type { TLanguageSettingsPageProps } from \"@model/nav\";\nimport { useThemeContext } from \"@src/context/Theme\";\nimport { NS } from \"@src/i18n\";\nimport { getFlagEmoji } from \"@src/util\";\nimport { store } from \"@store\";\nimport { STORE_KEYS } from \"@store/consts\";\nimport { globals } from \"@styles\";\nimport { useTranslation } from \"react-i18next\";\nimport { ScrollView, TouchableOpacity, View } from \"react-native\";\nimport { s, vs } from \"react-native-size-matters\";\n\nconst langs: ILangsOpt[] = [\n  { name: \"english\", code: \"en\", flag: \"us\" },\n  { name: \"german\", code: \"de\", flag: \"de\" },\n  { name: \"spanish\", code: \"es\", flag: \"es\" },\n  { name: \"italian\", code: \"it\", flag: \"it\" },\n  { name: \"russian\", code: \"ru\", flag: \"ru\" },\n  { name: \"thai\", code: \"th\", flag: \"th\" },\n];\n\nexport default function LanguageSettings({ navigation }: TLanguageSettingsPageProps) {\n  const { t, i18n } = useTranslation([NS.common]);\n  const { color } = useThemeContext();\n  return (\n    <Screen\n      screenName={t(\"language\", { ns: NS.topNav })}\n      withBackBtn\n      handlePress={() => navigation.goBack()}\n    >\n      <ScrollView alwaysBounceVertical={false}>\n        <View style={globals(color).wrapContainer}>\n          {langs.map((l, i) => (\n            <LangSelection\n              key={l.code}\n              code={l.code}\n              name={l.name}\n              flag={l.flag}\n              selected={l.code === i18n.language}\n              hasSeparator={i !== langs.length - 1}\n            />\n          ))}\n        </View>\n      </ScrollView>\n    </Screen>\n  );\n}\n\ninterface ILangSelectionProps {\n  code: TranslationLangCodes;\n  name: TTlLangNames;\n  flag: string;\n  selected: boolean;\n  hasSeparator?: boolean;\n}\n\nfunction LangSelection({ code, name, flag, selected, hasSeparator }: ILangSelectionProps) {\n  const { t, i18n } = useTranslation([NS.common]);\n  const handleLangChange = async () => {\n    await i18n.changeLanguage(code);\n    await store.set(STORE_KEYS.lang, code);\n  };\n  return (\n    <>\n      <TouchableOpacity\n        style={[globals().wrapRow, { paddingBottom: vs(15) }]}\n        onPress={() => void handleLangChange()}\n      >\n        <View style={{ flexDirection: \"row\", alignItems: \"center\" }}>\n          <View style={{ minWidth: s(40) }}>\n            <Txt txt={getFlagEmoji(flag)} styles={[{ fontSize: s(22) }]} />\n          </View>\n          <Txt txt={t(name)} />\n        </View>\n        <RadioBtn selected={selected} />\n      </TouchableOpacity>\n      {hasSeparator && <Separator style={[{ marginBottom: vs(15) }]} />}\n    </>\n  );\n}\n"
  },
  {
    "path": "src/screens/Settings/MenuItem.tsx",
    "content": "import Separator from \"@comps/Separator\";\nimport Txt from \"@comps/Txt\";\nimport { useThemeContext } from \"@src/context/Theme\";\nimport { globals, highlight as hi } from \"@styles\";\nimport { TouchableOpacity, View } from \"react-native\";\nimport { ScaledSheet, vs } from \"react-native-size-matters\";\n\ninterface IMenuItemProps {\n  header?: string;\n  txt: string;\n  onPress: () => void;\n  icon: React.ReactElement;\n  hasSeparator?: boolean;\n  disabled?: boolean;\n}\n\nexport default function SettingsMenuItem({\n  header,\n  txt,\n  icon,\n  onPress,\n  hasSeparator,\n  disabled,\n}: IMenuItemProps) {\n  const { color, highlight } = useThemeContext();\n  return (\n    <>\n      <View\n        style={[\n          globals().wrapRow,\n          { paddingBottom: vs(15), flexDirection: \"column\", alignItems: \"flex-start\" },\n        ]}\n      >\n        {header && (\n          <Txt\n            txt={header}\n            styles={[{ color: hi[highlight], fontWeight: \"bold\", marginBottom: vs(25) }]}\n          />\n        )}\n        <TouchableOpacity onPress={onPress} disabled={disabled} style={styles.setting}>\n          {icon}\n          <Txt\n            txt={txt}\n            styles={[styles.settingTxt, { color: disabled ? color.TEXT_SECONDARY : color.TEXT }]}\n          />\n        </TouchableOpacity>\n      </View>\n      {hasSeparator && <Separator style={[styles.separator]} />}\n    </>\n  );\n}\n\nconst styles = ScaledSheet.create({\n  setting: {\n    flexDirection: \"row\",\n    alignItems: \"center\",\n    width: \"100%\",\n  },\n  settingTxt: {\n    marginLeft: \"15@s\",\n  },\n  separator: {\n    marginBottom: \"15@vs\",\n    marginTop: \"3@vs\",\n  },\n});\n"
  },
  {
    "path": "src/screens/Settings/NfcSettings.tsx",
    "content": "import RadioBtn from \"@comps/RadioBtn\";\nimport Screen from \"@comps/Screen\";\nimport Separator from \"@comps/Separator\";\nimport Txt from \"@comps/Txt\";\nimport { useNfcAmountLimitsContext, NO_LIMIT } from \"@src/context/NfcAmountLimits\";\nimport type { TNfcSettingsPageProps } from \"@src/nav/navTypes\";\nimport { useCurrencyContext } from \"@src/context/Currency\";\nimport { useThemeContext } from \"@src/context/Theme\";\nimport { NS } from \"@src/i18n\";\nimport { globals, highlight as hi } from \"@styles\";\nimport { useCallback, useEffect, useRef, useState } from \"react\";\nimport { useTranslation } from \"react-i18next\";\nimport { ScrollView, TouchableOpacity, View, Text, TextInput } from \"react-native\";\nimport { s, ScaledSheet, vs } from \"react-native-size-matters\";\n\nexport default function NfcSettings({ navigation }: TNfcSettingsPageProps) {\n  const { t } = useTranslation([NS.common]);\n  const { color, highlight } = useThemeContext();\n  const { formatBalance, formatSatsAsCurrency, rates, selectedCurrency } = useCurrencyContext();\n\n  const { defaultMaxAmount, isLoading, setDefaultMaxAmount } = useNfcAmountLimitsContext();\n\n  const inputRef = useRef<TextInput>(null);\n  const [inputValue, setInputValue] = useState(\"\");\n  const hasNoLimit = defaultMaxAmount === NO_LIMIT;\n\n  const currencySymbol = rates?.[selectedCurrency]?.symbol || selectedCurrency;\n\n  // Sync local state with context when it loads\n  useEffect(() => {\n    if (!isLoading && defaultMaxAmount !== NO_LIMIT) {\n      setInputValue(defaultMaxAmount.toString());\n    }\n  }, [isLoading, defaultMaxAmount]);\n\n  // Get fiat value for display\n  const getFiatValue = useCallback(\n    (amount: number) => {\n      if (!formatBalance || !rates || amount <= 0) return null;\n      return formatSatsAsCurrency(amount);\n    },\n    [formatBalance, rates, formatSatsAsCurrency],\n  );\n\n  // Handle selecting \"No Limit\"\n  const handleSelectNoLimit = useCallback(async () => {\n    await setDefaultMaxAmount(NO_LIMIT);\n  }, [setDefaultMaxAmount]);\n\n  // Handle selecting \"Custom Limit\"\n  const handleSelectCustomLimit = useCallback(async () => {\n    const amount = parseInt(inputValue, 10);\n    if (!isNaN(amount) && amount > 0) {\n      await setDefaultMaxAmount(amount);\n    } else {\n      setInputValue(\"50000\");\n      await setDefaultMaxAmount(50_000);\n    }\n    // Focus the input when selecting custom limit\n    setTimeout(() => inputRef.current?.focus(), 100);\n  }, [inputValue, setDefaultMaxAmount]);\n\n  // Handle input change\n  const handleInputChange = useCallback(\n    (text: string) => {\n      const cleaned = text.replace(/[^0-9]/g, \"\");\n      setInputValue(cleaned);\n\n      if (!hasNoLimit) {\n        const amount = parseInt(cleaned, 10);\n        if (!isNaN(amount) && amount > 0) {\n          void setDefaultMaxAmount(amount);\n        }\n      }\n    },\n    [hasNoLimit, setDefaultMaxAmount],\n  );\n\n  const currentAmount = parseInt(inputValue, 10);\n  const fiatValue = !isNaN(currentAmount) ? getFiatValue(currentAmount) : null;\n\n  // Format display value with thousand separators\n  const displayValue = !isNaN(currentAmount) ? currentAmount.toLocaleString() : \"50,000\";\n\n  if (isLoading) {\n    return (\n      <Screen\n        screenName={t(\"nfcSettings\", {\n          ns: NS.topNav,\n          defaultValue: \"NFC Settings\",\n        })}\n        withBackBtn\n        handlePress={() => navigation.goBack()}\n      >\n        <View style={styles.loadingContainer}>\n          <Txt txt=\"Loading...\" />\n        </View>\n      </Screen>\n    );\n  }\n\n  return (\n    <Screen\n      screenName={t(\"nfcSettings\", {\n        ns: NS.topNav,\n        defaultValue: \"NFC Settings\",\n      })}\n      withBackBtn\n      handlePress={() => navigation.goBack()}\n    >\n      <ScrollView alwaysBounceVertical={false}>\n        <Txt\n          txt={t(\"paymentLimit\", { defaultValue: \"Payment Limit\" })}\n          bold\n          styles={[styles.subHeader]}\n        />\n\n        <View style={globals(color).wrapContainer}>\n          {/* No Limit option */}\n          <TouchableOpacity\n            style={[globals().wrapRow, { paddingBottom: s(15) }]}\n            onPress={handleSelectNoLimit}\n          >\n            <Txt txt={t(\"noLimit\", { defaultValue: \"No Limit\" })} />\n            <RadioBtn selected={hasNoLimit} />\n          </TouchableOpacity>\n\n          <Separator style={[{ marginBottom: s(15) }]} />\n\n          {/* Custom Limit option */}\n          <TouchableOpacity style={[globals().wrapRow]} onPress={handleSelectCustomLimit}>\n            <View style={styles.customLimitRow}>\n              <Txt txt={t(\"customLimit\", { defaultValue: \"Custom\" })} />\n              {!hasNoLimit && (\n                <View style={styles.valueContainer}>\n                  <TextInput\n                    ref={inputRef}\n                    value={inputValue}\n                    onChangeText={handleInputChange}\n                    keyboardType=\"number-pad\"\n                    style={[styles.inlineInput, { color: hi[highlight] }]}\n                    selectionColor={hi[highlight]}\n                    returnKeyType=\"done\"\n                  />\n                  <Text style={[styles.satsLabel, { color: color.TEXT_SECONDARY }]}>sats</Text>\n                </View>\n              )}\n            </View>\n            <RadioBtn selected={!hasNoLimit} />\n          </TouchableOpacity>\n\n          {/* Fiat value hint */}\n          {!hasNoLimit && fiatValue && (\n            <Text style={[styles.fiatHint, { color: color.TEXT_SECONDARY }]}>\n              ≈ {currencySymbol}\n              {fiatValue}\n            </Text>\n          )}\n        </View>\n      </ScrollView>\n    </Screen>\n  );\n}\n\nconst styles = ScaledSheet.create({\n  loadingContainer: {\n    flex: 1,\n    justifyContent: \"center\",\n    alignItems: \"center\",\n  },\n  subHeader: {\n    paddingHorizontal: \"20@s\",\n    marginBottom: \"10@vs\",\n  },\n  customLimitRow: {\n    flex: 1,\n    flexDirection: \"row\",\n    alignItems: \"center\",\n    gap: \"10@s\",\n  },\n  valueContainer: {\n    flexDirection: \"row\",\n    alignItems: \"center\",\n  },\n  inlineInput: {\n    fontSize: \"15@vs\",\n    fontWeight: \"500\",\n    padding: 0,\n    minWidth: \"60@s\",\n  },\n  satsLabel: {\n    fontSize: \"13@vs\",\n    marginLeft: \"4@s\",\n  },\n  fiatHint: {\n    fontSize: \"12@vs\",\n    marginTop: \"8@vs\",\n    marginLeft: \"70@s\",\n  },\n});\n"
  },
  {
    "path": "src/screens/Settings/NpcSettings.tsx",
    "content": "import Button from \"@comps/Button\";\nimport Loading from \"@comps/Loading\";\nimport Screen from \"@comps/Screen\";\nimport Txt from \"@comps/Txt\";\nimport TxtInput from \"@comps/TxtInput\";\nimport { CopyIcon, KeyIcon, PlusIcon, RefreshIcon, TrashbinIcon } from \"@comps/Icons\";\nimport type { TNpcSettingsPageProps } from \"@src/nav/navTypes\";\nimport { useBalanceContext } from \"@src/context/Balance\";\nimport { useCurrencyContext } from \"@src/context/Currency\";\nimport { useNpcContext, type INpcAccount, type TNpcUsernameAccountRequest } from \"@src/context/Npc\";\nimport { usePromptContext } from \"@src/context/Prompt\";\nimport { useThemeContext } from \"@src/context/Theme\";\nimport { NS } from \"@src/i18n\";\nimport { isErr } from \"@util\";\nimport { globals, highlight as hi, mainColors } from \"@styles\";\nimport { TrueSheet } from \"@lodev09/react-native-true-sheet\";\nimport * as Clipboard from \"expo-clipboard\";\nimport { useRef, useMemo, useState } from \"react\";\nimport { useTranslation } from \"react-i18next\";\nimport { ScrollView, TouchableOpacity, View } from \"react-native\";\nimport { useSafeAreaInsets } from \"react-native-safe-area-context\";\nimport { s, ScaledSheet } from \"react-native-size-matters\";\n\ninterface INpcAccountCardProps {\n  account: INpcAccount;\n  busy: boolean;\n  onCopy: (value: string) => void;\n  onRemove: (accountId: string) => void;\n  onSetUsername: (account: INpcAccount) => void;\n  onSync: (accountId: string) => void;\n}\n\nfunction NpcAccountCard({\n  account,\n  busy,\n  onCopy,\n  onRemove,\n  onSetUsername,\n  onSync,\n}: INpcAccountCardProps) {\n  const { t } = useTranslation([NS.common]);\n  const { color, highlight } = useThemeContext();\n\n  const accountSourceLabel =\n    account.source === \"privateKey\"\n      ? t(\"npcImportedKey\", { defaultValue: \"Imported key\" })\n      : t(\"npcSeedKey\", { defaultValue: \"Seed key\" });\n  const statusLabel = account.isSyncing\n    ? t(\"npcSyncing\", { defaultValue: \"Syncing\" })\n    : account.isRunning\n      ? t(\"npcActive\", { defaultValue: \"Active\" })\n      : t(\"npcPaused\", { defaultValue: \"Paused\" });\n\n  return (\n    <View style={[globals(color).wrapContainer, styles.accountCard]}>\n      <View style={styles.accountHeader}>\n        <View style={styles.accountTitleWrap}>\n          <Txt txt={account.label} bold styles={[styles.accountTitle]} />\n          <View style={styles.badgeRow}>\n            <View style={[styles.sourceBadge, { borderColor: color.BORDER }]}>\n              <Txt\n                txt={accountSourceLabel}\n                styles={[styles.sourceBadgeText, { color: color.TEXT_SECONDARY }]}\n              />\n            </View>\n            {account.isDefault && (\n              <View style={[styles.badge, { backgroundColor: hi[highlight] }]}>\n                <Txt\n                  txt={t(\"npcDefaultAccount\", { defaultValue: \"Default\" })}\n                  styles={[styles.badgeText, { color: color.BACKGROUND }]}\n                />\n              </View>\n            )}\n          </View>\n        </View>\n        <TouchableOpacity\n          accessibilityRole=\"button\"\n          onPress={() => onSync(account.id)}\n          disabled={busy}\n          style={[styles.iconButton, { borderColor: color.BORDER, opacity: busy ? 0.7 : 1 }]}\n        >\n          {busy ? <Loading size={s(16)} /> : <RefreshIcon width={s(18)} color={hi[highlight]} />}\n        </TouchableOpacity>\n      </View>\n\n      <View style={styles.statusRow}>\n        <View\n          style={[\n            styles.statusDot,\n            { backgroundColor: account.isRunning ? hi[highlight] : color.TEXT_SECONDARY },\n          ]}\n        />\n        <Txt txt={statusLabel} styles={[styles.statusText, { color: color.TEXT_SECONDARY }]} />\n      </View>\n\n      <TouchableOpacity\n        accessibilityRole=\"button\"\n        onPress={() => onCopy(account.address)}\n        style={[\n          styles.addressBox,\n          { borderColor: color.DARK_BORDER, backgroundColor: color.BACKGROUND },\n        ]}\n      >\n        <View style={styles.addressHeader}>\n          <Txt\n            txt={t(\"npcReceiveAddress\", { defaultValue: \"Receive address\" })}\n            styles={[styles.addressLabel, { color: color.TEXT_SECONDARY }]}\n          />\n          <View style={styles.copyHint}>\n            <Txt\n              txt={t(\"copy\", { defaultValue: \"Copy\" })}\n              styles={[styles.copyText, { color: hi[highlight] }]}\n            />\n            <CopyIcon width={s(16)} color={hi[highlight]} />\n          </View>\n        </View>\n        <Txt txt={account.address} bold styles={[styles.addressText, { color: hi[highlight] }]} />\n        <Txt\n          txt={\n            account.username\n              ? account.npub\n              : t(\"npcNpubFallback\", { defaultValue: \"Using your npub until a username is saved\" })\n          }\n          styles={[styles.mutedText, { color: color.TEXT_SECONDARY }]}\n        />\n      </TouchableOpacity>\n\n      <View style={styles.actions}>\n        <View style={styles.primaryAction}>\n          <Button\n            txt={t(\"npcSetUsername\", { defaultValue: \"Set Username\" })}\n            onPress={() => onSetUsername(account)}\n            disabled={busy}\n            loading={busy}\n            size=\"small\"\n          />\n        </View>\n        {!account.isDefault && (\n          <TouchableOpacity\n            accessibilityRole=\"button\"\n            onPress={() => onRemove(account.id)}\n            disabled={busy}\n            style={[\n              styles.removeButton,\n              { borderColor: mainColors.ERROR, opacity: busy ? 0.5 : 1 },\n            ]}\n          >\n            <TrashbinIcon width={s(16)} color={mainColors.ERROR} />\n            <Txt\n              txt={t(\"remove\", { defaultValue: \"Remove\" })}\n              styles={[styles.removeText, { color: mainColors.ERROR }]}\n            />\n          </TouchableOpacity>\n        )}\n      </View>\n    </View>\n  );\n}\n\nexport default function NpcSettings({ navigation }: TNpcSettingsPageProps) {\n  const { t } = useTranslation([NS.common]);\n  const { color, highlight } = useThemeContext();\n  const insets = useSafeAreaInsets();\n  const { openPromptAutoClose } = usePromptContext();\n  const { balances } = useBalanceContext();\n  const { formatAmount } = useCurrencyContext();\n  const addAccountSheetRef = useRef<TrueSheet>(null);\n  const usernameSheetRef = useRef<TrueSheet>(null);\n  const [privateKeyInput, setPrivateKeyInput] = useState(\"\");\n  const [selectedUsernameAccount, setSelectedUsernameAccount] = useState<INpcAccount | null>(null);\n  const [usernameInput, setUsernameInput] = useState(\"\");\n  const [usernameRequest, setUsernameRequest] = useState<TNpcUsernameAccountRequest | null>(null);\n  const [usernameBusy, setUsernameBusy] = useState(false);\n  const {\n    accounts,\n    busyAccountId,\n    confirmUsername,\n    deriveAccount,\n    importPrivateKeyAccount,\n    isLoading,\n    removeAccount,\n    requestUsername,\n    syncAccount,\n    syncAll,\n  } = useNpcContext();\n\n  const balance = useMemo(\n    () => formatAmount(balances.total.total),\n    [balances.total.total, formatAmount],\n  );\n  const accountCount = accounts.length.toString();\n\n  const runAction = (action: () => Promise<void>, success?: string) => {\n    void action()\n      .then(() => {\n        if (success) {\n          openPromptAutoClose({ msg: success });\n        }\n      })\n      .catch((err: unknown) => {\n        openPromptAutoClose({\n          msg: isErr(err) ? err.message : t(\"tryLater\"),\n        });\n      });\n  };\n\n  const handleCopy = (value: string) => {\n    void Clipboard.setStringAsync(value).then(() =>\n      openPromptAutoClose({\n        msg: t(\"copied\"),\n      }),\n    );\n  };\n\n  const handleOpenAddAccountSheet = () => {\n    setPrivateKeyInput(\"\");\n    void addAccountSheetRef.current?.present();\n  };\n\n  const handleDeriveAccount = () => {\n    void addAccountSheetRef.current?.dismiss();\n    runAction(\n      deriveAccount,\n      t(\"npcAccountAdded\", {\n        defaultValue: \"NPC account added\",\n      }),\n    );\n  };\n\n  const handleImportPrivateKey = () => {\n    const input = privateKeyInput.trim();\n    if (!input) {\n      openPromptAutoClose({\n        msg: t(\"npcPrivateKeyRequired\", {\n          defaultValue: \"Enter an nsec or hex private key.\",\n        }),\n      });\n      return;\n    }\n\n    setPrivateKeyInput(\"\");\n    void addAccountSheetRef.current?.dismiss();\n    runAction(\n      () => importPrivateKeyAccount(input),\n      t(\"npcAccountAdded\", {\n        defaultValue: \"NPC account added\",\n      }),\n    );\n  };\n\n  const handleOpenUsernameSheet = (account: INpcAccount) => {\n    setSelectedUsernameAccount(account);\n    setUsernameInput(account.username || \"\");\n    setUsernameRequest(null);\n    void usernameSheetRef.current?.present();\n  };\n\n  const handleCloseUsernameSheet = () => {\n    void usernameSheetRef.current?.dismiss();\n  };\n\n  const handleRequestUsername = () => {\n    const account = selectedUsernameAccount;\n    const username = usernameInput.trim();\n    if (!account) {\n      return;\n    }\n\n    setUsernameBusy(true);\n    void requestUsername(account.id, username)\n      .then((request) => {\n        if (request.type === \"free\") {\n          void usernameSheetRef.current?.dismiss();\n          openPromptAutoClose({\n            msg: t(\"npcUsernameSaved\", { defaultValue: \"Username saved\" }),\n          });\n          return;\n        }\n\n        setUsernameRequest(request);\n      })\n      .catch((err: unknown) => {\n        openPromptAutoClose({\n          msg: isErr(err) ? err.message : t(\"tryLater\"),\n        });\n      })\n      .finally(() => {\n        setUsernameBusy(false);\n      });\n  };\n\n  const handleConfirmUsername = () => {\n    if (!usernameRequest) {\n      return;\n    }\n\n    setUsernameBusy(true);\n    void confirmUsername(usernameRequest)\n      .then(() => {\n        void usernameSheetRef.current?.dismiss();\n        openPromptAutoClose({\n          msg: t(\"npcUsernameSaved\", { defaultValue: \"Username saved\" }),\n        });\n      })\n      .catch((err: unknown) => {\n        openPromptAutoClose({\n          msg: isErr(err) ? err.message : t(\"tryLater\"),\n        });\n      })\n      .finally(() => {\n        setUsernameBusy(false);\n      });\n  };\n\n  return (\n    <Screen\n      screenName={t(\"npcSettingsTitle\", {\n        ns: NS.topNav,\n        defaultValue: \"Lightning address\",\n      })}\n      withBackBtn\n      withPadding={false}\n      withBottomInset={false}\n      handlePress={() => navigation.goBack()}\n      rightAction={\n        <TouchableOpacity\n          accessibilityRole=\"button\"\n          onPress={handleOpenAddAccountSheet}\n          disabled={busyAccountId !== null}\n          style={[styles.headerAddAction, { opacity: busyAccountId !== null ? 0.5 : 1 }]}\n        >\n          <PlusIcon width={s(30)} height={s(30)} color={hi[highlight]} />\n        </TouchableOpacity>\n      }\n    >\n      {isLoading ? (\n        <View style={styles.loadingContainer}>\n          <Loading />\n        </View>\n      ) : (\n        <ScrollView\n          alwaysBounceVertical={false}\n          contentContainerStyle={{\n            paddingHorizontal: 8,\n            paddingTop: 8,\n            paddingBottom: Math.max(insets.bottom, s(18)),\n          }}\n        >\n          <View style={[globals(color).wrapContainer, styles.summaryCard]}>\n            <View style={styles.summaryHeader}>\n              <View style={styles.summaryText}>\n                <Txt\n                  txt={t(\"npcReceiveTitle\", { defaultValue: \"NPC Lightning addresses\" })}\n                  bold\n                  styles={[styles.summaryTitle]}\n                />\n                <Txt\n                  txt={t(\"npcReceiveHint\", {\n                    defaultValue: \"Receive Lightning payments into your local Cashu wallet.\",\n                  })}\n                  styles={[styles.mutedText, { color: color.TEXT_SECONDARY }]}\n                />\n              </View>\n            </View>\n            <View\n              style={[\n                styles.summaryStats,\n                { borderTopColor: color.DARK_BORDER, borderBottomColor: color.DARK_BORDER },\n              ]}\n            >\n              <View style={styles.summaryStat}>\n                <Txt\n                  txt={t(\"npcAccountsLabel\", { defaultValue: \"Accounts\" })}\n                  styles={[styles.statLabel, { color: color.TEXT_SECONDARY }]}\n                />\n                <Txt txt={accountCount} bold styles={[styles.statValue]} />\n              </View>\n              <View style={[styles.statDivider, { backgroundColor: color.DARK_BORDER }]} />\n              <View style={styles.summaryStat}>\n                <Txt\n                  txt={t(\"npcLocalBalance\", { defaultValue: \"Local balance\" })}\n                  styles={[styles.statLabel, { color: color.TEXT_SECONDARY }]}\n                />\n                <Txt\n                  txt={`${balance.formatted} ${balance.symbol}`}\n                  bold\n                  styles={[styles.statValue, { color: hi[highlight] }]}\n                />\n              </View>\n            </View>\n            <View style={styles.summaryActions}>\n              <View style={styles.summaryAction}>\n                <Button\n                  txt={t(\"npcSyncAll\", { defaultValue: \"Sync all\" })}\n                  onPress={() =>\n                    runAction(syncAll, t(\"npcSynced\", { defaultValue: \"NPC accounts synced\" }))\n                  }\n                  loading={busyAccountId === \"all\"}\n                  disabled={busyAccountId !== null && busyAccountId !== \"all\"}\n                  size=\"small\"\n                  outlined\n                />\n              </View>\n            </View>\n          </View>\n\n          {accounts.map((account) => (\n            <NpcAccountCard\n              key={account.id}\n              account={account}\n              busy={busyAccountId === account.id}\n              onCopy={handleCopy}\n              onRemove={(accountId) =>\n                runAction(\n                  () => removeAccount(accountId),\n                  t(\"npcAccountRemoved\", { defaultValue: \"NPC account removed\" }),\n                )\n              }\n              onSetUsername={handleOpenUsernameSheet}\n              onSync={(accountId) =>\n                runAction(\n                  () => syncAccount(accountId),\n                  t(\"npcSynced\", { defaultValue: \"NPC account synced\" }),\n                )\n              }\n            />\n          ))}\n        </ScrollView>\n      )}\n      <TrueSheet\n        ref={addAccountSheetRef}\n        detents={[\"auto\"]}\n        backgroundColor={color.BACKGROUND}\n        cornerRadius={s(26)}\n        grabberOptions={{ color: color.TEXT_SECONDARY }}\n        onDidDismiss={() => setPrivateKeyInput(\"\")}\n      >\n        <ScrollView\n          style={{ backgroundColor: color.BACKGROUND }}\n          contentContainerStyle={[\n            styles.sheetContainer,\n            { paddingBottom: Math.max(insets.bottom, s(22)) },\n          ]}\n          keyboardShouldPersistTaps=\"handled\"\n          showsVerticalScrollIndicator={false}\n        >\n          <View style={styles.sheetHeader}>\n            <View style={[styles.sheetIcon, { backgroundColor: hi[highlight] }]}>\n              <KeyIcon width={s(22)} color={color.BACKGROUND} />\n            </View>\n            <View style={styles.sheetTitleBlock}>\n              <Txt\n                txt={t(\"npcAddAccountTitle\", { defaultValue: \"Add NPC account\" })}\n                bold\n                styles={[styles.sheetTitle]}\n              />\n              <Txt\n                txt={t(\"npcAddAccountHint\", {\n                  defaultValue: \"Import an existing Nostr key or derive a new key from your seed.\",\n                })}\n                styles={[styles.mutedText, { color: color.TEXT_SECONDARY }]}\n              />\n            </View>\n          </View>\n\n          <View style={styles.fieldBlock}>\n            <Txt\n              txt={t(\"npcPrivateKeyLabel\", { defaultValue: \"Private key\" })}\n              styles={[styles.label, { color: color.TEXT_SECONDARY }]}\n            />\n            <TxtInput\n              placeholder={t(\"npcPrivateKeyPlaceholder\", { defaultValue: \"nsec or hex\" })}\n              value={privateKeyInput}\n              autoCapitalize=\"none\"\n              autoCorrect={false}\n              onChangeText={setPrivateKeyInput}\n            />\n            <Txt\n              txt={t(\"npcPrivateKeyHint\", {\n                defaultValue: \"Imported keys are stored in secure storage on this device.\",\n              })}\n              styles={[styles.mutedText, { color: color.TEXT_SECONDARY }]}\n            />\n          </View>\n\n          <View style={styles.sheetActions}>\n            <Button\n              txt={t(\"npcImportPrivateKey\", { defaultValue: \"Import private key\" })}\n              onPress={handleImportPrivateKey}\n              disabled={busyAccountId !== null}\n              size=\"small\"\n            />\n            <Button\n              txt={t(\"npcDeriveAccount\", { defaultValue: \"Derive new key\" })}\n              onPress={handleDeriveAccount}\n              disabled={busyAccountId !== null}\n              size=\"small\"\n              outlined\n            />\n          </View>\n        </ScrollView>\n      </TrueSheet>\n      <TrueSheet\n        ref={usernameSheetRef}\n        detents={[\"auto\"]}\n        backgroundColor={color.BACKGROUND}\n        cornerRadius={s(26)}\n        dismissible={!usernameBusy}\n        draggable={!usernameBusy}\n        grabberOptions={{ color: color.TEXT_SECONDARY }}\n        onDidDismiss={() => {\n          setSelectedUsernameAccount(null);\n          setUsernameInput(\"\");\n          setUsernameRequest(null);\n          setUsernameBusy(false);\n        }}\n      >\n        <ScrollView\n          style={{ backgroundColor: color.BACKGROUND }}\n          contentContainerStyle={[\n            styles.sheetContainer,\n            { paddingBottom: Math.max(insets.bottom, s(22)) },\n          ]}\n          keyboardShouldPersistTaps=\"handled\"\n          showsVerticalScrollIndicator={false}\n        >\n          <View style={styles.sheetHeader}>\n            <View style={[styles.sheetIcon, { backgroundColor: hi[highlight] }]}>\n              <KeyIcon width={s(22)} color={color.BACKGROUND} />\n            </View>\n            <View style={styles.sheetTitleBlock}>\n              <Txt\n                txt={t(\"npcSetUsername\", { defaultValue: \"Set Username\" })}\n                bold\n                styles={[styles.sheetTitle]}\n              />\n              <Txt\n                txt={selectedUsernameAccount?.address || \"\"}\n                styles={[styles.mutedText, { color: color.TEXT_SECONDARY }]}\n              />\n            </View>\n          </View>\n\n          {usernameRequest?.type === \"payment\" ? (\n            <View>\n              <View\n                style={[\n                  styles.usernamePreview,\n                  { backgroundColor: color.INPUT_BG, borderColor: color.DARK_BORDER },\n                ]}\n              >\n                <Txt\n                  txt={usernameRequest.username}\n                  bold\n                  center\n                  styles={[styles.usernamePreviewText, { color: hi[highlight] }]}\n                />\n              </View>\n              <Txt\n                txt={t(\"npcUsernameFeePrompt\", {\n                  defaultValue: \"Do you want to set this username for a fee of {{amount}} sats?\",\n                  amount: usernameRequest.amount.toLocaleString(),\n                })}\n                center\n                styles={[styles.usernamePrompt, { color: color.TEXT_SECONDARY }]}\n              />\n              <View style={styles.sheetActions}>\n                <Button\n                  txt={t(\"confirm\", { defaultValue: \"Confirm\" })}\n                  onPress={handleConfirmUsername}\n                  loading={usernameBusy}\n                  disabled={usernameBusy}\n                  size=\"small\"\n                />\n                <Button\n                  txt={t(\"cancel\", { defaultValue: \"Cancel\" })}\n                  onPress={handleCloseUsernameSheet}\n                  disabled={usernameBusy}\n                  size=\"small\"\n                  outlined\n                />\n              </View>\n            </View>\n          ) : (\n            <View>\n              <View style={styles.fieldBlock}>\n                <Txt\n                  txt={t(\"npcUsernameLabel\", { defaultValue: \"Custom username\" })}\n                  styles={[styles.label, { color: color.TEXT_SECONDARY }]}\n                />\n                <TxtInput\n                  placeholder={t(\"npcUsernamePlaceholder\", { defaultValue: \"optional username\" })}\n                  value={usernameInput}\n                  autoCapitalize=\"none\"\n                  autoCorrect={false}\n                  onChangeText={setUsernameInput}\n                />\n              </View>\n              <View style={styles.sheetActions}>\n                <Button\n                  txt={t(\"npcRequestUsername\", { defaultValue: \"Request username\" })}\n                  onPress={handleRequestUsername}\n                  loading={usernameBusy}\n                  disabled={usernameBusy}\n                  size=\"small\"\n                />\n                <Button\n                  txt={t(\"cancel\", { defaultValue: \"Cancel\" })}\n                  onPress={handleCloseUsernameSheet}\n                  disabled={usernameBusy}\n                  size=\"small\"\n                  outlined\n                />\n              </View>\n            </View>\n          )}\n        </ScrollView>\n      </TrueSheet>\n    </Screen>\n  );\n}\n\nconst styles = ScaledSheet.create({\n  loadingContainer: {\n    flex: 1,\n    alignItems: \"center\",\n    justifyContent: \"center\",\n  },\n  summaryCard: {\n    paddingBottom: \"20@vs\",\n  },\n  summaryHeader: {\n    flexDirection: \"row\",\n    justifyContent: \"space-between\",\n  },\n  summaryText: {\n    flex: 1,\n  },\n  summaryTitle: {\n    marginBottom: \"6@vs\",\n  },\n  summaryStats: {\n    borderTopWidth: 1,\n    borderBottomWidth: 1,\n    flexDirection: \"row\",\n    alignItems: \"center\",\n    marginTop: \"18@vs\",\n    paddingVertical: \"14@vs\",\n  },\n  summaryStat: {\n    flex: 1,\n    paddingHorizontal: \"14@s\",\n  },\n  statDivider: {\n    width: 1,\n    height: \"34@vs\",\n  },\n  statLabel: {\n    fontSize: \"11@vs\",\n    marginBottom: \"5@vs\",\n  },\n  statValue: {\n    fontSize: \"16@vs\",\n  },\n  summaryActions: {\n    flexDirection: \"row\",\n    alignItems: \"center\",\n    marginTop: \"18@vs\",\n    gap: \"12@s\",\n  },\n  summaryAction: {\n    flex: 1,\n  },\n  headerAddAction: {\n    flexDirection: \"row\",\n    alignItems: \"center\",\n    justifyContent: \"center\",\n  },\n  accountCard: {\n    paddingBottom: \"20@vs\",\n  },\n  accountHeader: {\n    flexDirection: \"row\",\n    alignItems: \"center\",\n    justifyContent: \"space-between\",\n    marginBottom: \"14@vs\",\n  },\n  accountTitleWrap: {\n    flex: 1,\n    paddingRight: \"12@s\",\n  },\n  accountTitle: {\n    fontSize: \"16@vs\",\n    marginBottom: \"8@vs\",\n  },\n  badgeRow: {\n    flexDirection: \"row\",\n    alignItems: \"center\",\n    gap: \"8@s\",\n  },\n  badge: {\n    borderRadius: \"12@s\",\n    paddingHorizontal: \"8@s\",\n    paddingVertical: \"3@vs\",\n  },\n  badgeText: {\n    fontSize: \"10@vs\",\n    fontWeight: \"600\",\n  },\n  sourceBadge: {\n    borderWidth: 1,\n    borderRadius: \"12@s\",\n    paddingHorizontal: \"8@s\",\n    paddingVertical: \"3@vs\",\n  },\n  sourceBadgeText: {\n    fontSize: \"10@vs\",\n    fontWeight: \"600\",\n  },\n  iconButton: {\n    width: \"36@s\",\n    height: \"36@s\",\n    borderRadius: \"18@s\",\n    borderWidth: 1,\n    alignItems: \"center\",\n    justifyContent: \"center\",\n  },\n  statusRow: {\n    flexDirection: \"row\",\n    alignItems: \"center\",\n    marginBottom: \"12@vs\",\n    gap: \"7@s\",\n  },\n  statusDot: {\n    width: \"7@s\",\n    height: \"7@s\",\n    borderRadius: \"4@s\",\n  },\n  statusText: {\n    fontSize: \"12@vs\",\n  },\n  addressBox: {\n    borderWidth: 1,\n    borderRadius: \"16@s\",\n    paddingHorizontal: \"14@s\",\n    paddingVertical: \"12@vs\",\n    marginBottom: \"16@vs\",\n  },\n  addressHeader: {\n    flexDirection: \"row\",\n    alignItems: \"center\",\n    justifyContent: \"space-between\",\n    marginBottom: \"8@vs\",\n    gap: \"12@s\",\n  },\n  copyHint: {\n    flexDirection: \"row\",\n    alignItems: \"center\",\n    gap: \"5@s\",\n  },\n  copyText: {\n    fontSize: \"12@vs\",\n    fontWeight: \"600\",\n  },\n  addressText: {\n    fontSize: \"14@vs\",\n    fontWeight: \"600\",\n  },\n  mutedText: {\n    fontSize: \"12@vs\",\n    marginTop: \"4@vs\",\n  },\n  fieldBlock: {\n    marginBottom: \"14@vs\",\n  },\n  label: {\n    fontSize: \"12@vs\",\n    marginBottom: \"7@vs\",\n  },\n  addressLabel: {\n    fontSize: \"12@vs\",\n  },\n  actions: {\n    flexDirection: \"row\",\n    alignItems: \"center\",\n    justifyContent: \"space-between\",\n    gap: \"12@s\",\n  },\n  primaryAction: {\n    flex: 1,\n  },\n  removeButton: {\n    minHeight: \"42@vs\",\n    borderWidth: 1,\n    borderRadius: \"22@s\",\n    paddingHorizontal: \"13@s\",\n    flexDirection: \"row\",\n    alignItems: \"center\",\n    justifyContent: \"center\",\n    gap: \"6@s\",\n  },\n  removeText: {\n    fontSize: \"13@vs\",\n    fontWeight: \"600\",\n  },\n  usernamePreview: {\n    borderWidth: 1,\n    borderRadius: \"18@s\",\n    paddingHorizontal: \"16@s\",\n    paddingVertical: \"18@vs\",\n    marginBottom: \"14@vs\",\n  },\n  usernamePreviewText: {\n    fontSize: \"20@vs\",\n  },\n  usernamePrompt: {\n    fontSize: \"14@vs\",\n    lineHeight: \"20@vs\",\n    marginBottom: \"18@vs\",\n  },\n  sheetContainer: {\n    paddingHorizontal: \"20@s\",\n    paddingTop: \"26@vs\",\n  },\n  sheetHeader: {\n    flexDirection: \"row\",\n    alignItems: \"center\",\n    gap: \"12@s\",\n    marginBottom: \"22@vs\",\n  },\n  sheetIcon: {\n    width: \"44@s\",\n    height: \"44@s\",\n    borderRadius: \"22@s\",\n    alignItems: \"center\",\n    justifyContent: \"center\",\n  },\n  sheetTitleBlock: {\n    flex: 1,\n  },\n  sheetTitle: {\n    fontSize: \"17@vs\",\n    marginBottom: \"4@vs\",\n  },\n  sheetActions: {\n    gap: \"10@vs\",\n  },\n});\n"
  },
  {
    "path": "src/screens/Settings/ViewMnemonic.tsx",
    "content": "import Screen from \"@comps/Screen\";\nimport Txt from \"@comps/Txt\";\nimport Loading from \"@comps/Loading\";\nimport Button from \"@comps/Button\";\nimport { isIOS } from \"@consts\";\nimport { useThemeContext } from \"@src/context/Theme\";\nimport { NS } from \"@src/i18n\";\nimport { seedService } from \"@src/services/SeedService\";\nimport { useEffect, useState } from \"react\";\nimport type { TViewMnemonicPageProps } from \"@model/nav\";\nimport { useTranslation } from \"react-i18next\";\nimport { FlatList, View } from \"react-native\";\nimport { s, ScaledSheet } from \"react-native-size-matters\";\nimport useCopy from \"@comps/hooks/Copy\";\nimport { CheckmarkIcon, CopyIcon } from \"@comps/Icons\";\nimport { mainColors } from \"@styles\";\n\nexport default function ViewMnemonic({ navigation }: TViewMnemonicPageProps) {\n  const { t } = useTranslation([NS.common]);\n  const { color } = useThemeContext();\n  const { copied, copy } = useCopy();\n  const [mnemonic, setMnemonic] = useState<string | null>(null);\n  const [loading, setLoading] = useState(true);\n\n  useEffect(() => {\n    const id = setTimeout(() => {\n      try {\n        const words = seedService.getMnemonic();\n        setMnemonic(words || null);\n      } finally {\n        setLoading(false);\n      }\n    }, 0);\n    return () => clearTimeout(id);\n  }, []);\n\n  return (\n    <Screen screenName={\"Mnemonic\"} withBackBtn handlePress={() => navigation.goBack()}>\n      <View style={styles.content}>\n        {loading ? (\n          <View style={[styles.warnContainer, { backgroundColor: color.DRAWER }]}>\n            <Loading size=\"large\" />\n          </View>\n        ) : !mnemonic ? (\n          <View style={[styles.warnContainer, { backgroundColor: color.DRAWER }]}>\n            <Txt txt={\"No mnemonic found\"} styles={[{ color: color.TEXT_SECONDARY }]} />\n          </View>\n        ) : (\n          <>\n            <FlatList\n              data={mnemonic.split(\" \")}\n              numColumns={2}\n              keyExtractor={(_item, index) => index.toString()}\n              renderItem={({ item, index }) => (\n                <View\n                  style={[\n                    styles.mnemonicWord,\n                    {\n                      backgroundColor: color.DRAWER,\n                      marginRight: index % 2 === 0 ? s(10) : 0,\n                    },\n                  ]}\n                >\n                  <Txt bold txt={`${index + 1}. `} />\n                  <Txt bold txt={item} />\n                </View>\n              )}\n            />\n            <View style={styles.copyButtonContainer}>\n              <Button\n                txt={copied ? \"Copied!\" : \"Copy Mnemonic\"}\n                onPress={() => void copy(mnemonic)}\n                disabled={copied}\n                icon={\n                  copied ? (\n                    <CheckmarkIcon width={s(18)} height={s(18)} color={mainColors.WHITE} />\n                  ) : (\n                    <CopyIcon width={s(18)} height={s(18)} color={mainColors.WHITE} />\n                  )\n                }\n              />\n            </View>\n          </>\n        )}\n      </View>\n    </Screen>\n  );\n}\n\nconst styles = ScaledSheet.create({\n  content: {\n    marginTop: `${isIOS ? 20 : 60}@s`,\n    paddingHorizontal: \"20@s\",\n  },\n  copyButtonContainer: {\n    marginTop: \"20@s\",\n  },\n  mnemonicWord: {\n    padding: \"10@s\",\n    marginBottom: \"10@s\",\n    borderRadius: \"10@s\",\n    width: \"48.5%\",\n    flexDirection: \"row\",\n    alignItems: \"center\",\n  },\n  warnContainer: {\n    alignItems: \"center\",\n    padding: \"20@s\",\n    rowGap: \"10@s\",\n    borderRadius: \"10@s\",\n    marginBottom: \"20@s\",\n  },\n});\n"
  },
  {
    "path": "src/screens/Settings/index.tsx",
    "content": "import {\n  GithubIcon,\n  HistoryIcon,\n  LanguageIcon,\n  KeyIcon,\n  LinkIcon,\n  LockIcon,\n  MintBoardIcon,\n  NfcIcon,\n  PaletteIcon,\n  SettingsIcon,\n  SwapCurrencyIcon,\n  ZapIcon,\n} from \"@comps/Icons\";\nimport type { TSettingsPageProps } from \"@model/nav\";\nimport Screen from \"@comps/Screen\";\nimport Txt from \"@comps/Txt\";\nimport { usePromptContext } from \"@src/context/Prompt\";\nimport { useThemeContext } from \"@src/context/Theme\";\nimport { NS } from \"@src/i18n\";\nimport { dropAllData } from \"@src/storage/dev\";\nimport { appVersion } from \"@src/consts/env\";\nimport { reportIssueUrl } from \"@src/consts/urls\";\nimport { isErr, openUrl } from \"@util\";\nimport { secureStore, store } from \"@store\";\nimport { SECURESTORE_KEY, STORE_KEYS } from \"@store/consts\";\nimport { globals } from \"@styles\";\nimport { useEffect, useRef, useState } from \"react\";\nimport { useTranslation } from \"react-i18next\";\nimport { ScrollView, Text, View } from \"react-native\";\nimport { s, vs } from \"react-native-size-matters\";\nimport ConfirmBottomSheet, { ConfirmBottomSheetRef } from \"@comps/modal/ConfirmBottomSheet\";\n\nimport MenuItem from \"./MenuItem\";\nimport Loading from \"@comps/Loading\";\n\nexport default function Settings({ navigation }: TSettingsPageProps) {\n  const { t } = useTranslation([NS.common]);\n  const { openPromptAutoClose } = usePromptContext();\n  const { color } = useThemeContext();\n  const confirmSheetRef = useRef<ConfirmBottomSheetRef>(null);\n\n  const handleReset = async () => {\n    try {\n      await dropAllData();\n    } catch {\n      /* ignore */\n    }\n  };\n\n  return (\n    <Screen\n      screenName={t(\"settings\", { ns: NS.topNav })}\n      withBackBtn\n      handlePress={() => navigation.goBack()}\n    >\n      <ScrollView alwaysBounceVertical={false}>\n        {/* MINT */}\n        <View style={[globals(color).wrapContainer, { marginBottom: vs(20) }]}>\n          <MenuItem\n            header={t(\"mint\")}\n            txt={t(\"mintSettings\", { ns: NS.topNav })}\n            icon={<MintBoardIcon color={color.TEXT} />}\n            onPress={() => navigation.navigate(\"Mint\", { screen: \"MintHome\" })}\n          />\n        </View>\n        {/* WALLET */}\n        <View style={[globals(color).wrapContainer, { marginBottom: vs(20) }]}>\n          <MenuItem\n            header={t(\"wallet\")}\n            txt={t(\"history\", { ns: NS.topNav })}\n            icon={<HistoryIcon color={color.TEXT} />}\n            onPress={() => navigation.navigate(\"History\", { screen: \"HistoryMain\" })}\n          />\n        </View>\n        {/* PREFERENCES */}\n        <View style={[globals(color).wrapContainer, { marginBottom: vs(20) }]}>\n          <MenuItem\n            header={t(\"preferences\")}\n            txt={t(\"display\")}\n            icon={<PaletteIcon color={color.TEXT} />}\n            onPress={() => navigation.navigate(\"Display settings\")}\n          />\n          <MenuItem\n            txt={t(\"language\")}\n            icon={<LanguageIcon color={color.TEXT} />}\n            onPress={() => navigation.navigate(\"Language settings\")}\n          />\n          <MenuItem\n            txt={t(\"currency\")}\n            icon={<SwapCurrencyIcon color={color.TEXT} />}\n            onPress={() => navigation.navigate(\"Currency settings\")}\n          />\n          <MenuItem\n            txt={t(\"nfcSettings\", { defaultValue: \"NFC Payments\" })}\n            icon={<NfcIcon width={s(18)} color={color.TEXT} />}\n            onPress={() => navigation.navigate(\"NFC settings\")}\n          />\n          <MenuItem\n            txt={t(\"npcSettings\", { defaultValue: \"Lightning address\" })}\n            icon={<ZapIcon width={s(18)} color={color.TEXT} />}\n            onPress={() => navigation.navigate(\"NPC settings\")}\n          />\n        </View>\n        {/* SECURITY */}\n        <View style={[globals(color).wrapContainer, { marginBottom: vs(20) }]}>\n          <MenuItem\n            header={t(\"restore\")}\n            txt={t(\"viewMnemonic\")}\n            icon={<KeyIcon color={color.TEXT} />}\n            onPress={() => navigation.navigate(\"View mnemonic\")}\n          />\n          <MenuItem\n            txt={t(\"restore\")}\n            icon={<LockIcon color={color.TEXT} />}\n            onPress={() => navigation.navigate(\"Restore\", { screen: \"RecoverMints\" })}\n          />\n        </View>\n        {/* ABOUT */}\n        <View style={[globals(color).wrapContainer, { marginBottom: vs(20) }]}>\n          <MenuItem\n            header={t(\"about\")}\n            txt={t(\"github\")}\n            icon={<GithubIcon color={color.TEXT} />}\n            onPress={() => {}}\n          />\n          <MenuItem\n            txt={t(\"reportIssue\", { defaultValue: \"Report an issue\" })}\n            icon={<LinkIcon color={color.TEXT} />}\n            onPress={() =>\n              void openUrl(reportIssueUrl)?.catch((err: unknown) =>\n                openPromptAutoClose({\n                  msg: isErr(err) ? err.message : t(\"deepLinkErr\", { ns: NS.common }),\n                }),\n              )\n            }\n          />\n        </View>\n        <View style={[globals(color).wrapContainer, { marginBottom: vs(20) }]}>\n          <MenuItem\n            header=\"DEV\"\n            txt={t(\"factoryReset\")}\n            icon={<Text>💥💥💥</Text>}\n            onPress={() =>\n              confirmSheetRef.current?.open({\n                header: t(\"resetQ\"),\n                txt: t(\"delHistoryTxt\"),\n                confirmTxt: t(\"confirmReset\"),\n                cancelTxt: t(\"back\"),\n                onConfirm: () => void handleReset(),\n                onCancel: () => {},\n                destructive: true,\n              })\n            }\n          />\n        </View>\n        <Txt txt={appVersion} bold center />\n      </ScrollView>\n      <ConfirmBottomSheet ref={confirmSheetRef} />\n    </Screen>\n  );\n}\n"
  },
  {
    "path": "src/services/ExchangeRateService.ts",
    "content": "import { appLogger } from \"@src/logger\";\nimport type { IExchangeRates } from \"@model\";\n\nconst BLOCKCHAIN_INFO_API = \"https://blockchain.info/ticker\";\n\nclass ExchangeRateService {\n  /**\n   * Fetches current exchange rates from blockchain.info API\n   * @returns Promise<IExchangeRates> - Object containing exchange rates for all currencies\n   * @throws Error if the fetch fails or response is invalid\n   */\n  async fetchRates(): Promise<IExchangeRates> {\n    try {\n      appLogger.debug(\"ExchangeRateService: Fetching exchange rates from blockchain.info\");\n\n      const response = await fetch(BLOCKCHAIN_INFO_API, {\n        method: \"GET\",\n        headers: {\n          Accept: \"application/json\",\n        },\n      });\n\n      if (!response.ok) {\n        throw new Error(`HTTP error! status: ${response.status}`);\n      }\n\n      const rates: IExchangeRates = await response.json();\n\n      appLogger.debug(\"ExchangeRateService: Successfully fetched exchange rates\", {\n        currencyCount: Object.keys(rates).length,\n      });\n\n      return rates;\n    } catch (error) {\n      appLogger.error(\"ExchangeRateService: Failed to fetch exchange rates\", error);\n      throw error;\n    }\n  }\n\n  /**\n   * Validates if the exchange rates object is valid\n   * @param rates - Exchange rates object to validate\n   * @returns boolean - True if valid, false otherwise\n   */\n  validateRates(rates: IExchangeRates): boolean {\n    if (!rates || typeof rates !== \"object\") {\n      return false;\n    }\n\n    // Check if at least one currency exists\n    const currencies = Object.keys(rates);\n    if (currencies.length === 0) {\n      return false;\n    }\n\n    // Validate structure of first currency\n    const firstCurrency = rates[currencies[0]];\n    if (!firstCurrency) {\n      return false;\n    }\n\n    // Check required fields\n    const hasRequiredFields =\n      typeof firstCurrency.last === \"number\" &&\n      typeof firstCurrency.buy === \"number\" &&\n      typeof firstCurrency.sell === \"number\" &&\n      typeof firstCurrency.symbol === \"string\";\n\n    return hasRequiredFields;\n  }\n}\n\nexport const exchangeRateService = new ExchangeRateService();\n"
  },
  {
    "path": "src/services/NFCService.ts",
    "content": "// NfcCashuPayment.ts\nimport NfcManager, { NfcTech } from \"react-native-nfc-manager\";\nimport { Buffer } from \"buffer/\";\nimport { appLogger } from \"@src/logger\";\n\nconst log = appLogger.child({ name: \"NFC\" });\n\n// ---------- CONSTANTS FROM SPEC ----------\nconst SELECT_AID = [0x00, 0xa4, 0x04, 0x00, 0x07, 0xd2, 0x76, 0x00, 0x00, 0x85, 0x01, 0x01, 0x00];\n\nconst SELECT_NDEF = [0x00, 0xa4, 0x00, 0x0c, 0x02, 0xe1, 0x04];\n\nconst READ_BINARY = (offset: number, len: number) => [\n  0x00,\n  0xb0,\n  (offset >> 8) & 0xff,\n  offset & 0xff,\n  len,\n];\n\nconst UPDATE_BINARY = (offset: number, bytes: number[]) => [\n  0x00,\n  0xd6,\n  (offset >> 8) & 0xff,\n  offset & 0xff,\n  bytes.length,\n  ...bytes,\n];\n\nconst STATUS_OK = \"9000\";\n\n// Status word meanings for better error messages\nconst STATUS_CODES: Record<string, string> = {\n  \"9000\": \"Success\",\n  \"6a82\": \"File not found / Not supported\",\n  \"6a86\": \"Incorrect P1-P2 parameters\",\n  \"6a87\": \"Lc inconsistent with TLV structure\",\n  \"6700\": \"Wrong length\",\n  \"6982\": \"Security status not satisfied\",\n  \"6985\": \"Conditions of use not satisfied\",\n  \"6d00\": \"INS not supported\",\n  \"6e00\": \"CLA not supported\",\n};\n\n// ------------------------------------------\n\nfunction hex(bytes: number[]): string {\n  return Buffer.from(bytes).toString(\"hex\").toUpperCase();\n}\n\nfunction toBytes(str: string): number[] {\n  return Array.from(Buffer.from(str, \"utf8\"));\n}\n\nfunction getStatusMessage(sw: string): string {\n  const swLower = sw.toLowerCase();\n  return STATUS_CODES[swLower] || `Unknown status: ${sw}`;\n}\n\n// Build an NDEF Text record (supports both Short Record and Normal Record)\nfunction buildTextNdef(text: string): number[] {\n  const lang = \"en\";\n  const langBytes = toBytes(lang);\n  const textBytes = toBytes(text);\n\n  const payload = [\n    langBytes.length, // status byte (bit 7=0 for UTF-8, lower 6 bits = lang length)\n    ...langBytes,\n    ...textBytes,\n  ];\n\n  let recordHeader: number[];\n\n  if (payload.length <= 255) {\n    // Short Record format (SR=1)\n    log.debug(`Building Short Record NDEF (payload: ${payload.length} bytes)`);\n    recordHeader = [\n      0xd1, // MB=1, ME=1, SR=1, TNF=1\n      0x01, // type length\n      payload.length, // payload length (1 byte)\n      0x54, // 'T'\n      ...payload,\n    ];\n  } else {\n    // Normal Record format (SR=0) for payloads > 255 bytes\n    log.debug(`Building Normal Record NDEF (payload: ${payload.length} bytes)`);\n    const len = payload.length;\n    recordHeader = [\n      0xc1, // MB=1, ME=1, SR=0, TNF=1\n      0x01, // type length\n      (len >> 24) & 0xff, // payload length (4 bytes, big-endian)\n      (len >> 16) & 0xff,\n      (len >> 8) & 0xff,\n      len & 0xff,\n      0x54, // 'T'\n      ...payload,\n    ];\n  }\n\n  const nlen = recordHeader.length;\n  log.debug(`NDEF message total size: ${nlen + 2} bytes (NLEN=${nlen})`);\n  return [(nlen >> 8) & 0xff, nlen & 0xff, ...recordHeader];\n}\n\ninterface ApduResponse {\n  ok: boolean;\n  raw: number[];\n  payload: number[];\n  sw: string;\n}\n\nasync function sendApdu(command: number[], label?: string): Promise<ApduResponse> {\n  const cmdHex = hex(command);\n  log.debug(`>> APDU${label ? ` [${label}]` : \"\"}: ${cmdHex}`);\n\n  try {\n    const response = await NfcManager.isoDepHandler.transceive(command);\n    const hexResp = hex(response);\n    const sw = hexResp.slice(-4);\n    const ok = sw.toLowerCase() === STATUS_OK.toLowerCase();\n\n    log.debug(`<< Response: ${hexResp} (SW: ${sw} - ${getStatusMessage(sw)})`);\n\n    return {\n      ok,\n      raw: response,\n      payload: response.slice(0, -2), // strip SW1 SW2\n      sw,\n    };\n  } catch (error) {\n    log.error(`APDU transceive failed:`, error);\n    throw new NfcError(\n      `APDU communication failed: ${error instanceof Error ? error.message : String(error)}`,\n      \"TRANSCEIVE_FAILED\",\n    );\n  }\n}\n\n// Custom error class for NFC operations\nexport class NfcError extends Error {\n  code: string;\n  sw?: string;\n\n  constructor(message: string, code: string, sw?: string) {\n    super(message);\n    this.name = \"NfcError\";\n    this.code = code;\n    this.sw = sw;\n  }\n}\n\n// ------------------ MAIN API ------------------\n\n/**\n * Result of reading a payment request\n */\nexport interface PaymentRequestResult {\n  /** The raw payment request string (e.g., \"creqA...\") */\n  request: string;\n  /** Whether a response was written back to the NFC tag */\n  wroteResponse: boolean;\n}\n\n/**\n * Callback to handle the text read from the NFC tag.\n * Return writeText to write a response back, or finish to close the session without writing.\n */\nexport type NfcTextExchangeAction =\n  | {\n      type: \"writeText\";\n      text: string;\n    }\n  | {\n      type: \"finish\";\n    };\n\nexport type NfcTextHandler = (request: string) => Promise<NfcTextExchangeAction>;\n\nexport default class NfcCashuPayment {\n  /**\n   * Check if NFC is supported and enabled on this device\n   */\n  static async isSupported(): Promise<boolean> {\n    try {\n      const supported = await NfcManager.isSupported();\n      log.debug(`NFC supported: ${supported}`);\n      return supported;\n    } catch (error) {\n      log.warn(\"Failed to check NFC support:\", error);\n      return false;\n    }\n  }\n\n  /**\n   * Check if NFC is currently enabled\n   */\n  static async isEnabled(): Promise<boolean> {\n    try {\n      const enabled = await NfcManager.isEnabled();\n      log.debug(`NFC enabled: ${enabled}`);\n      return enabled;\n    } catch (error) {\n      log.warn(\"Failed to check if NFC is enabled:\", error);\n      return false;\n    }\n  }\n\n  /**\n   * Perform a complete NFC Cashu payment flow:\n   * 1. Connect to the PoS terminal\n   * 2. Read the payment request\n   * 3. Call your callback to decide how to handle the request\n   * 4. Optionally write text back to the PoS\n   * 5. Close the connection\n   *\n   * This keeps the NFC session open throughout the entire flow.\n   *\n   * @param handleRequest Async callback that receives the payment request and returns the next action\n   * @returns The payment request that was read\n   *\n   * @example\n   * ```typescript\n   * await NfcCashuPayment.performPayment(async (paymentRequest) => {\n   *   const pr = PaymentRequest.fromEncodedRequest(paymentRequest);\n   *   const prepared = await manager.ops.send.prepare({ mintUrl: pr.mints![0]!, amount: pr.amount! });\n   *   const { token } = await manager.ops.send.execute(prepared.id);\n   *   return { type: \"writeText\", text: getEncodedToken(token) };\n   * });\n   * ```\n   */\n  static async performPayment(handleRequest: NfcTextHandler): Promise<PaymentRequestResult> {\n    log.info(\"Starting NFC payment flow...\");\n\n    // Pre-flight checks\n    const supported = await this.isSupported();\n    if (!supported) {\n      throw new NfcError(\"NFC is not supported on this device\", \"NOT_SUPPORTED\");\n    }\n\n    const enabled = await this.isEnabled();\n    if (!enabled) {\n      throw new NfcError(\n        \"NFC is disabled. Please enable NFC in your device settings.\",\n        \"NOT_ENABLED\",\n      );\n    }\n\n    log.debug(\"Requesting IsoDep technology...\");\n\n    try {\n      await NfcManager.requestTechnology(NfcTech.IsoDep);\n      log.info(\"IsoDep technology acquired, communicating with PoS...\");\n    } catch (error) {\n      log.error(\"Failed to acquire IsoDep technology:\", error);\n      throw new NfcError(\n        `Failed to connect to NFC tag: ${error instanceof Error ? error.message : String(error)}`,\n        \"TECHNOLOGY_REQUEST_FAILED\",\n      );\n    }\n\n    try {\n      // ===== PHASE 1: READ PAYMENT REQUEST =====\n      log.info(\"Phase 1: Reading payment request...\");\n\n      // 1) SELECT AID\n      log.debug(\"SELECT NDEF Tag Application AID\");\n      let r = await sendApdu(SELECT_AID, \"SELECT AID\");\n      if (!r.ok) {\n        throw new NfcError(\n          `AID not accepted by tag (${getStatusMessage(r.sw)})`,\n          \"AID_SELECT_FAILED\",\n          r.sw,\n        );\n      }\n\n      // 2) SELECT NDEF FILE\n      log.debug(\"SELECT NDEF File (E104)\");\n      r = await sendApdu(SELECT_NDEF, \"SELECT NDEF\");\n      if (!r.ok) {\n        throw new NfcError(\n          `NDEF file not accessible (${getStatusMessage(r.sw)})`,\n          \"NDEF_SELECT_FAILED\",\n          r.sw,\n        );\n      }\n\n      // 3) Read NLEN\n      r = await sendApdu(READ_BINARY(0, 2), \"READ NLEN\");\n      if (!r.ok) {\n        throw new NfcError(\n          `Failed reading NLEN (${getStatusMessage(r.sw)})`,\n          \"READ_NLEN_FAILED\",\n          r.sw,\n        );\n      }\n\n      const nlen = (r.payload[0] << 8) | r.payload[1];\n      log.debug(`NLEN = ${nlen} bytes`);\n\n      if (nlen === 0) {\n        throw new NfcError(\n          \"NDEF file is empty (NLEN=0). No payment request available.\",\n          \"EMPTY_NDEF\",\n        );\n      }\n\n      // 4) Read NDEF body\n      let ndefBytes: number[] = [];\n      const MAX_READ_SIZE = 250;\n\n      if (nlen <= MAX_READ_SIZE) {\n        r = await sendApdu(READ_BINARY(2, nlen), \"READ NDEF\");\n        if (!r.ok) {\n          throw new NfcError(\n            `Failed reading NDEF content (${getStatusMessage(r.sw)})`,\n            \"READ_NDEF_FAILED\",\n            r.sw,\n          );\n        }\n        ndefBytes = r.payload;\n      } else {\n        log.debug(`Large NDEF message, reading in chunks...`);\n        let offset = 2;\n        let remaining = nlen;\n\n        while (remaining > 0) {\n          const chunkSize = Math.min(remaining, MAX_READ_SIZE);\n          r = await sendApdu(READ_BINARY(offset, chunkSize), `READ chunk @${offset}`);\n          if (!r.ok) {\n            throw new NfcError(\n              `Failed reading NDEF chunk at offset ${offset}`,\n              \"READ_NDEF_CHUNK_FAILED\",\n              r.sw,\n            );\n          }\n          ndefBytes.push(...r.payload);\n          offset += chunkSize;\n          remaining -= chunkSize;\n        }\n      }\n\n      const paymentRequest = decodeTextRecord(ndefBytes);\n      log.info(`Read payment request (${paymentRequest.length} chars)`);\n      log.debug(`Payment request: ${paymentRequest.substring(0, 60)}...`);\n\n      // ===== PHASE 2: HANDLE REQUEST (user callback) =====\n      log.info(\"Phase 2: Handling payment request (calling user callback)...\");\n      let action: NfcTextExchangeAction;\n      try {\n        action = await handleRequest(paymentRequest);\n      } catch (error) {\n        log.error(\"Payment request handling failed:\", error);\n        // Re-throw the original error to preserve custom error types (e.g., LimitExceededError)\n        // The caller can handle these errors appropriately\n        throw error;\n      }\n\n      if (action.type === \"finish\") {\n        log.info(\"NFC exchange completed without writing a response\");\n        return { request: paymentRequest, wroteResponse: false };\n      }\n\n      const token = action.text;\n      if (!token || token.length === 0) {\n        throw new NfcError(\"NFC callback returned empty response text\", \"INVALID_RESPONSE_TEXT\");\n      }\n\n      log.info(`Response text created (${token.length} chars)`);\n      log.debug(`Response preview: ${token.substring(0, 50)}...`);\n\n      // ===== PHASE 3: WRITE RESPONSE BACK =====\n      log.info(\"Phase 3: Writing response back to PoS...\");\n\n      // Re-select NDEF file (may be needed after the callback took time)\n      log.debug(\"Re-SELECT NDEF File for writing\");\n      r = await sendApdu(SELECT_NDEF, \"SELECT NDEF (write)\");\n      if (!r.ok) {\n        throw new NfcError(\n          `NDEF file not accessible for write (${getStatusMessage(r.sw)})`,\n          \"NDEF_SELECT_FAILED\",\n          r.sw,\n        );\n      }\n\n      // Build NDEF message\n      const ndef = buildTextNdef(token);\n      const writeNlen = (ndef[0] << 8) | ndef[1];\n      log.debug(`NDEF message: NLEN=${writeNlen}, total=${ndef.length} bytes`);\n\n      // Write NLEN first (Pattern A)\n      r = await sendApdu(UPDATE_BINARY(0, [ndef[0], ndef[1]]), \"WRITE NLEN\");\n      if (!r.ok) {\n        throw new NfcError(\n          `Failed writing NLEN (${getStatusMessage(r.sw)})`,\n          \"WRITE_NLEN_FAILED\",\n          r.sw,\n        );\n      }\n\n      // Write body in chunks\n      const CHUNK_SIZE = 240;\n      let offset = 2;\n      const body = ndef.slice(2);\n      const totalChunks = Math.ceil(body.length / CHUNK_SIZE);\n      let chunkNum = 0;\n\n      while (offset - 2 < body.length) {\n        const chunk = body.slice(offset - 2, offset - 2 + CHUNK_SIZE);\n        chunkNum++;\n        log.debug(`Writing chunk ${chunkNum}/${totalChunks}: ${chunk.length} bytes`);\n\n        r = await sendApdu(UPDATE_BINARY(offset, chunk), `WRITE chunk ${chunkNum}`);\n        if (!r.ok) {\n          throw new NfcError(\n            `Failed writing chunk ${chunkNum} (${getStatusMessage(r.sw)})`,\n            \"WRITE_CHUNK_FAILED\",\n            r.sw,\n          );\n        }\n        offset += chunk.length;\n      }\n\n      log.info(\"✓ NFC payment completed successfully!\");\n      return { request: paymentRequest, wroteResponse: true };\n    } finally {\n      log.debug(\"Releasing NFC technology...\");\n      try {\n        await NfcManager.cancelTechnologyRequest();\n      } catch (cleanupError) {\n        log.warn(\"Failed to release NFC technology:\", cleanupError);\n      }\n    }\n  }\n\n  /**\n   * Write a Cashu token to an NFC tag (PoS terminal).\n   * Used for completing over-limit payments after user confirmation.\n   *\n   * @param token The Cashu token string (e.g., \"cashuA...\" or \"cashuB...\")\n   */\n  static async writeCashuToken(token: string): Promise<void> {\n    log.info(`Starting NFC token write (${token.length} chars)...`);\n    log.debug(`Token preview: ${token.substring(0, 50)}...`);\n\n    // Pre-flight checks\n    const supported = await this.isSupported();\n    if (!supported) {\n      throw new NfcError(\"NFC is not supported on this device\", \"NOT_SUPPORTED\");\n    }\n\n    const enabled = await this.isEnabled();\n    if (!enabled) {\n      throw new NfcError(\n        \"NFC is disabled. Please enable NFC in your device settings.\",\n        \"NOT_ENABLED\",\n      );\n    }\n\n    if (!token || token.length === 0) {\n      throw new NfcError(\"Token cannot be empty\", \"INVALID_TOKEN\");\n    }\n\n    log.debug(\"Requesting IsoDep technology...\");\n\n    try {\n      await NfcManager.requestTechnology(NfcTech.IsoDep);\n      log.info(\"IsoDep technology acquired, communicating with tag...\");\n    } catch (error) {\n      log.error(\"Failed to acquire IsoDep technology:\", error);\n      throw new NfcError(\n        `Failed to connect to NFC tag: ${error instanceof Error ? error.message : String(error)}`,\n        \"TECHNOLOGY_REQUEST_FAILED\",\n      );\n    }\n\n    try {\n      // 1) SELECT AID\n      log.debug(\"Step 1: SELECT NDEF Tag Application AID\");\n      let r = await sendApdu(SELECT_AID, \"SELECT AID\");\n      if (!r.ok) {\n        throw new NfcError(\n          `AID not accepted by tag (${getStatusMessage(r.sw)})`,\n          \"AID_SELECT_FAILED\",\n          r.sw,\n        );\n      }\n\n      // 2) SELECT NDEF FILE\n      log.debug(\"Step 2: SELECT NDEF File (E104)\");\n      r = await sendApdu(SELECT_NDEF, \"SELECT NDEF\");\n      if (!r.ok) {\n        throw new NfcError(\n          `NDEF file not accessible (${getStatusMessage(r.sw)})`,\n          \"NDEF_SELECT_FAILED\",\n          r.sw,\n        );\n      }\n\n      // 3) Build outgoing NDEF with token\n      log.debug(\"Step 3: Building NDEF Text record...\");\n      const ndef = buildTextNdef(token);\n      const nlen = (ndef[0] << 8) | ndef[1];\n      log.debug(`NDEF message built: NLEN=${nlen}, total=${ndef.length} bytes`);\n\n      // 4) Write NLEN first (Pattern A from spec)\n      log.debug(\"Step 4: UPDATE BINARY - Write NLEN at offset 0\");\n      r = await sendApdu(UPDATE_BINARY(0, [ndef[0], ndef[1]]), \"WRITE NLEN\");\n      if (!r.ok) {\n        throw new NfcError(\n          `Failed writing NLEN (${getStatusMessage(r.sw)})`,\n          \"WRITE_NLEN_FAILED\",\n          r.sw,\n        );\n      }\n\n      // 5) Write body in chunks <= 240 bytes (safe for most implementations)\n      const CHUNK_SIZE = 240;\n      let offset = 2;\n      const body = ndef.slice(2);\n      const totalChunks = Math.ceil(body.length / CHUNK_SIZE);\n      let chunkNum = 0;\n\n      log.debug(`Step 5: Writing ${body.length} bytes in ${totalChunks} chunk(s)...`);\n\n      while (offset - 2 < body.length) {\n        const chunk = body.slice(offset - 2, offset - 2 + CHUNK_SIZE);\n        chunkNum++;\n        log.debug(\n          `Writing chunk ${chunkNum}/${totalChunks}: ${chunk.length} bytes at offset ${offset}`,\n        );\n\n        r = await sendApdu(UPDATE_BINARY(offset, chunk), `WRITE chunk ${chunkNum}`);\n        if (!r.ok) {\n          throw new NfcError(\n            `Failed writing chunk ${chunkNum} at offset ${offset} (${getStatusMessage(r.sw)})`,\n            \"WRITE_CHUNK_FAILED\",\n            r.sw,\n          );\n        }\n        offset += chunk.length;\n      }\n\n      log.info(\"Successfully wrote Cashu token to NFC tag\");\n    } finally {\n      log.debug(\"Releasing NFC technology...\");\n      try {\n        await NfcManager.cancelTechnologyRequest();\n      } catch (cleanupError) {\n        log.warn(\"Failed to release NFC technology:\", cleanupError);\n      }\n    }\n  }\n}\n\n// --------- NDEF TEXT RECORD PARSER -------------\n// Supports both Short Record (SR=1) and Normal Record (SR=0) formats\nconst SHORT_RECORD_FLAG = 0x10;\n\nfunction decodeTextRecord(ndef: number[]): string {\n  if (!ndef || ndef.length < 4) {\n    throw new NfcError(\n      `Invalid NDEF data: too short (${ndef?.length || 0} bytes)`,\n      \"INVALID_NDEF_FORMAT\",\n    );\n  }\n\n  // ndef = [recordHeader...], no NLEN here (already removed)\n  const header = ndef[0];\n  const typeLen = ndef[1];\n  const isShortRecord = (header & SHORT_RECORD_FLAG) !== 0;\n\n  log.debug(\n    `Parsing NDEF: header=0x${header.toString(16)}, typeLen=${typeLen}, SR=${isShortRecord}`,\n  );\n\n  // Validate TNF (Type Name Format) - should be 0x01 (NFC Forum well-known type)\n  const tnf = header & 0x07;\n  if (tnf !== 0x01) {\n    log.warn(`Unexpected TNF: ${tnf} (expected 1 for well-known type)`);\n  }\n\n  let payloadLen: number;\n  let typeFieldStart: number;\n\n  if (isShortRecord) {\n    // SR format: 1-byte payload length at offset 2\n    payloadLen = ndef[2];\n    typeFieldStart = 3;\n  } else {\n    // Normal format: 4-byte big-endian payload length at offset 2-5\n    if (ndef.length < 7) {\n      throw new NfcError(\"Invalid NDEF: normal record header too short\", \"INVALID_NDEF_FORMAT\");\n    }\n    payloadLen = ((ndef[2] << 24) | (ndef[3] << 16) | (ndef[4] << 8) | ndef[5]) >>> 0;\n    typeFieldStart = 6;\n  }\n\n  log.debug(`Payload length: ${payloadLen}, type field starts at: ${typeFieldStart}`);\n\n  if (typeFieldStart >= ndef.length) {\n    throw new NfcError(\"Invalid NDEF: type field offset out of bounds\", \"INVALID_NDEF_FORMAT\");\n  }\n\n  const type = ndef[typeFieldStart];\n  if (type !== 0x54) {\n    // 0x54 = 'T' for Text\n    throw new NfcError(\n      `Not a Text record (type=0x${type.toString(16)}, expected 0x54 'T')`,\n      \"NOT_TEXT_RECORD\",\n    );\n  }\n\n  const payloadStart = typeFieldStart + typeLen;\n\n  if (payloadStart >= ndef.length) {\n    throw new NfcError(\"Invalid NDEF: payload start out of bounds\", \"INVALID_NDEF_FORMAT\");\n  }\n\n  const status = ndef[payloadStart];\n  const langLen = status & 0x3f;\n  const isUtf16 = (status & 0x80) !== 0;\n\n  log.debug(`Text record: status=0x${status.toString(16)}, langLen=${langLen}, UTF-16=${isUtf16}`);\n\n  if (isUtf16) {\n    log.warn(\"UTF-16 encoding detected - this implementation assumes UTF-8\");\n  }\n\n  const textStart = payloadStart + 1 + langLen;\n  const textLen = payloadLen - 1 - langLen;\n\n  if (textStart + textLen > ndef.length) {\n    throw new NfcError(\n      `Invalid NDEF: text data out of bounds (textStart=${textStart}, textLen=${textLen}, ndefLen=${ndef.length})`,\n      \"INVALID_NDEF_FORMAT\",\n    );\n  }\n\n  const textBytes = ndef.slice(textStart, textStart + textLen);\n  const text = Buffer.from(textBytes).toString(\"utf8\");\n\n  log.debug(`Decoded text: ${textLen} bytes -> ${text.length} chars`);\n\n  return text;\n}\n"
  },
  {
    "path": "src/services/NpcService.ts",
    "content": "import type { Manager, Plugin, ResolvedPaymentRequest } from \"@cashu/coco-core\";\nimport { getEncodedToken } from \"@cashu/coco-core\";\nimport {\n  NPCPlugin,\n  type NPCAccountApi,\n  type NPCPluginApi,\n  type SinceStore,\n  type Signer,\n} from \"coco-cashu-plugin-npc\";\nimport { JWTAuthProvider, NPCClient, PaymentRequiredError } from \"npubcash-sdk\";\nimport { accountFromSeedWords } from \"nostr-tools/nip06\";\nimport { finalizeEvent, getPublicKey } from \"nostr-tools/pure\";\nimport { decode, npubEncode } from \"nostr-tools/nip19\";\n\nimport { appLogger } from \"@src/logger\";\nimport { seedService } from \"@src/services/SeedService\";\nimport { secureStore, store } from \"@store\";\n\nexport const NPC_BASE_URL = \"https://npubx.cash\";\nexport const NPC_DOMAIN = new URL(NPC_BASE_URL).host;\nexport const NPC_SYNC_INTERVAL_MS = 25_000;\nexport const NPC_DEFAULT_ACCOUNT_ID = \"npc-seed-0\";\n\nexport type TNpcAccountSource = \"seed\" | \"privateKey\";\n\ninterface IBaseStoredNpcAccount {\n  id: string;\n  label: string;\n  username?: string;\n}\n\nexport interface ISeedNpcAccount extends IBaseStoredNpcAccount {\n  source: \"seed\";\n  accountIndex: number;\n}\n\nexport interface IPrivateKeyNpcAccount extends IBaseStoredNpcAccount {\n  source: \"privateKey\";\n  privateKeyStorageKey: string;\n}\n\nexport type IStoredNpcAccount = ISeedNpcAccount | IPrivateKeyNpcAccount;\n\nexport interface INpcIdentity {\n  signer: Signer;\n  publicKey: string;\n  npub: string;\n}\n\nexport type TNpcUsernameRequest =\n  | {\n      type: \"free\";\n      username: string;\n    }\n  | {\n      type: \"payment\";\n      username: string;\n      amount: number;\n      mintUrl: string;\n      request: ResolvedPaymentRequest;\n    };\n\ninterface INpcManager extends Manager {\n  ext: Manager[\"ext\"] & {\n    npc?: NPCPluginApi;\n  };\n}\n\nclass StoreSinceStore implements SinceStore {\n  constructor(private readonly key: string) {}\n\n  async get() {\n    const saved = await store.get(this.key);\n    const parsed = saved ? Number(saved) : 0;\n    return Number.isFinite(parsed) ? parsed : 0;\n  }\n\n  async set(since: number) {\n    await store.set(this.key, String(since));\n  }\n\n  async clear() {\n    await store.delete(this.key);\n  }\n}\n\nexport function createNpcPlugin(): Plugin {\n  return new NPCPlugin({\n    defaultBaseUrl: NPC_BASE_URL,\n    syncIntervalMs: NPC_SYNC_INTERVAL_MS,\n    useWebsocket: true,\n    logger: appLogger.child({ name: \"NPCPlugin\" }),\n  }) as unknown as Plugin;\n}\n\nexport function createDefaultNpcAccount(): IStoredNpcAccount {\n  return {\n    id: NPC_DEFAULT_ACCOUNT_ID,\n    source: \"seed\",\n    accountIndex: 0,\n    label: \"Main account\",\n  };\n}\n\nexport function isValidNpcUsername(username: string) {\n  const trimmed = username.trim();\n  return trimmed.length === 0 || /^[a-zA-Z0-9_.-]{3,32}$/.test(trimmed);\n}\n\nexport function getNpcAddress(username: string | undefined, npub: string) {\n  const localPart = username?.trim() || npub;\n  return `${localPart}@${NPC_DOMAIN}`;\n}\n\nexport function getNpcSinceStore(accountId: string) {\n  return new StoreSinceStore(`npc_since:${accountId}`);\n}\n\nexport function getNpcPrivateKeyStorageKey(accountId: string) {\n  return `npc_private_key:${accountId}`;\n}\n\nfunction bytesToHex(bytes: Uint8Array) {\n  return Array.from(bytes)\n    .map((byte) => byte.toString(16).padStart(2, \"0\"))\n    .join(\"\");\n}\n\nfunction normalizeHexPrivateKey(hex: string) {\n  const normalized = hex.trim().toLowerCase().replace(/^0x/, \"\");\n  if (!/^[0-9a-f]{64}$/.test(normalized)) {\n    throw new Error(\"Private key must be a 64-character hex key or nsec.\");\n  }\n  return normalized;\n}\n\nfunction hexToBytes(hex: string) {\n  const normalized = normalizeHexPrivateKey(hex);\n  const bytes = new Uint8Array(32);\n  for (let i = 0; i < bytes.length; i++) {\n    bytes[i] = parseInt(normalized.slice(i * 2, i * 2 + 2), 16);\n  }\n  return bytes;\n}\n\nexport function normalizeNpcPrivateKey(input: string) {\n  const trimmed = input.trim();\n  const normalized = trimmed.toLowerCase();\n  if (normalized.startsWith(\"nsec1\")) {\n    const decoded = decode(normalized);\n    if (decoded.type !== \"nsec\") {\n      throw new Error(\"Private key must be a valid nsec.\");\n    }\n    return bytesToHex(decoded.data);\n  }\n  return normalizeHexPrivateKey(trimmed);\n}\n\nasync function getSeedNpcIdentity(accountIndex: number): Promise<INpcIdentity> {\n  const mnemonic = await seedService.getMnemonic();\n  if (!mnemonic) {\n    throw new Error(\"No mnemonic found\");\n  }\n  const account = accountFromSeedWords(mnemonic, undefined, accountIndex);\n  const signer: Signer = async (template) => finalizeEvent(template, account.privateKey);\n\n  return {\n    signer,\n    publicKey: account.publicKey,\n    npub: npubEncode(account.publicKey),\n  };\n}\n\nasync function getPrivateKeyNpcIdentity(privateKeyStorageKey: string): Promise<INpcIdentity> {\n  const savedKey = await secureStore.get(privateKeyStorageKey);\n  if (!savedKey) {\n    throw new Error(\"NPC private key not found.\");\n  }\n\n  const privateKey = hexToBytes(savedKey);\n  const signer: Signer = async (template) => finalizeEvent(template, privateKey);\n  const publicKey = getPublicKey(privateKey);\n\n  return {\n    signer,\n    publicKey,\n    npub: npubEncode(publicKey),\n  };\n}\n\nexport async function getNpcIdentity(account: IStoredNpcAccount): Promise<INpcIdentity> {\n  if (account.source === \"privateKey\") {\n    return getPrivateKeyNpcIdentity(account.privateKeyStorageKey);\n  }\n  return getSeedNpcIdentity(account.accountIndex);\n}\n\nexport function getNpcExtension(manager: Manager) {\n  const npc = (manager as INpcManager).ext.npc;\n  if (!npc) {\n    throw new Error(\"NPC plugin is not registered\");\n  }\n  return npc;\n}\n\nexport async function registerNpcAccount(manager: Manager, account: IStoredNpcAccount) {\n  const npc = getNpcExtension(manager);\n  const identity = await getNpcIdentity(account);\n  const existing = npc.getAccount(account.id);\n\n  if (existing) {\n    return {\n      api: existing,\n      identity,\n    };\n  }\n\n  const api = await npc.addAccount({\n    id: account.id,\n    signer: identity.signer,\n    baseUrl: NPC_BASE_URL,\n    sinceStore: getNpcSinceStore(account.id),\n    syncIntervalMs: NPC_SYNC_INTERVAL_MS,\n    useWebsocket: true,\n    autoStart: true,\n  });\n\n  return {\n    api,\n    identity,\n  };\n}\n\nexport async function removeNpcAccount(manager: Manager, accountId: string) {\n  const npc = getNpcExtension(manager);\n  await npc.removeAccount(accountId);\n  await getNpcSinceStore(accountId).clear();\n}\n\nexport async function syncNpcAccount(manager: Manager, accountId: string) {\n  const npc = getNpcExtension(manager);\n  const account = npc.getAccount(accountId);\n  if (!account) {\n    throw new Error(\"NPC account is not registered\");\n  }\n  await account.sync();\n}\n\nexport async function getNpcAccountInfo(api: NPCAccountApi) {\n  return api.getInfo();\n}\n\nfunction createNpcClient(identity: INpcIdentity) {\n  return new NPCClient(NPC_BASE_URL, new JWTAuthProvider(NPC_BASE_URL, identity.signer));\n}\n\nexport async function requestNpcUsername(\n  manager: Manager,\n  account: IStoredNpcAccount,\n  username: string,\n): Promise<TNpcUsernameRequest> {\n  const identity = await getNpcIdentity(account);\n  const client = createNpcClient(identity);\n\n  try {\n    await client.setUsername(username);\n    return {\n      type: \"free\",\n      username,\n    };\n  } catch (error) {\n    if (!(error instanceof PaymentRequiredError)) {\n      throw error;\n    }\n\n    const encodedRequest = error.paymentRequest.toEncodedRequest();\n    const request = await manager.paymentRequests.parse(encodedRequest);\n\n    if (request.transport.type !== \"inband\") {\n      throw new Error(\"NPC username purchase uses an unsupported payment transport.\");\n    }\n\n    if (request.paymentRequest.unit && request.paymentRequest.unit !== \"sat\") {\n      throw new Error(\"NPC username purchase uses an unsupported payment unit.\");\n    }\n\n    const mintUrl = request.payableMints[0];\n\n    if (!mintUrl) {\n      throw new Error(\"No local mint can pay for this username.\");\n    }\n\n    if (!request.amount) {\n      throw new Error(\"NPC username purchase did not include a fee amount.\");\n    }\n\n    return {\n      type: \"payment\",\n      username,\n      amount: request.amount,\n      mintUrl,\n      request,\n    };\n  }\n}\n\nexport async function payNpcUsernameRequest(\n  manager: Manager,\n  account: IStoredNpcAccount,\n  usernameRequest: TNpcUsernameRequest,\n) {\n  if (usernameRequest.type === \"free\") {\n    return;\n  }\n\n  const identity = await getNpcIdentity(account);\n  const client = createNpcClient(identity);\n  const transaction = await manager.paymentRequests.prepare(usernameRequest.request, {\n    mintUrl: usernameRequest.mintUrl,\n    amount: usernameRequest.amount,\n  });\n  const result = await manager.paymentRequests.execute(transaction);\n\n  if (result.type !== \"inband\") {\n    throw new Error(\"NPC username purchase did not return an in-band token.\");\n  }\n\n  try {\n    await client.setUsername(usernameRequest.username, getEncodedToken(result.token));\n  } catch (error) {\n    if (error instanceof PaymentRequiredError) {\n      throw new Error(\"NPC username purchase was not accepted by the server.\");\n    }\n    throw error;\n  }\n}\n"
  },
  {
    "path": "src/services/SeedService.ts",
    "content": "import * as bip39 from \"@scure/bip39\";\nimport * as Crypto from \"expo-crypto\";\nimport { wordlist } from \"@scure/bip39/wordlists/english\";\nimport * as SecureStore from \"expo-secure-store\";\nimport { privateKeyFromSeedWords } from \"nostr-tools/nip06\";\n\nclass SeedService {\n  private _seed: Uint8Array | null = null;\n  async createNewMnemonic(): Promise<{\n    mnemonic: string;\n    fingerprint: string;\n  }> {\n    const mnemonic = bip39.generateMnemonic(wordlist);\n    SecureStore.setItem(\"mnemonic\", mnemonic);\n    const seed = bip39.mnemonicToSeedSync(mnemonic);\n    this._seed = seed;\n    const fingerprint = await Crypto.digestStringAsync(Crypto.CryptoDigestAlgorithm.MD5, mnemonic);\n    return { mnemonic, fingerprint };\n  }\n\n  async deleteMnemonic() {\n    return SecureStore.deleteItemAsync(\"mnemonic\");\n  }\n\n  setMnemonic(mnemonic: string) {\n    this._seed = bip39.mnemonicToSeedSync(mnemonic);\n  }\n\n  getMnemonic() {\n    return SecureStore.getItem(\"mnemonic\");\n  }\n\n  isMnemonicSet() {\n    return SecureStore.getItem(\"mnemonic\") !== null;\n  }\n\n  async getFingerprint() {\n    const mnemonic = this.getMnemonic();\n    if (!mnemonic) {\n      return null;\n    }\n    const fingerprint = await Crypto.digestStringAsync(Crypto.CryptoDigestAlgorithm.MD5, mnemonic);\n    return fingerprint;\n  }\n  async ensureMnemonicSet() {\n    const savedMnemonic = this.getMnemonic();\n    if (!savedMnemonic) {\n      await this.createNewMnemonic();\n    }\n  }\n\n  getSeed() {\n    if (this._seed) {\n      return this._seed;\n    }\n    const mnemonic = SecureStore.getItem(\"mnemonic\");\n    if (!mnemonic) {\n      throw new Error(\"No mnemonic found\");\n    }\n    const seed = bip39.mnemonicToSeedSync(mnemonic);\n    this._seed = seed;\n    return seed;\n  }\n\n  async getNostrSk() {\n    const mnemonic = await this.getMnemonic();\n    if (!mnemonic) {\n      throw new Error(\"No mnemonic found\");\n    }\n    const sk = privateKeyFromSeedWords(mnemonic);\n    return sk;\n  }\n  convertMnemonicToSeed(mnemonic: string) {\n    return bip39.mnemonicToSeedSync(mnemonic);\n  }\n}\n\nexport const seedService = new SeedService();\n"
  },
  {
    "path": "src/shim.ts",
    "content": "import * as c from \"expo-crypto\";\n\nconsole.log(\"shim.ts - starting crypto polyfill\");\n\n// Create a comprehensive crypto polyfill that handles all scenarios\nfunction setupCryptoPolyfill() {\n  // Create a wrapper for getRandomValues that matches Web Crypto API signature\n  const getRandomValuesWrapper = <T extends ArrayBufferView | null>(array: T): T => {\n    if (!array) {\n      throw new TypeError(\"getRandomValues called with null or undefined\");\n    }\n\n    // Check if it's a valid TypedArray for crypto operations\n    const validTypes = [\n      \"Int8Array\",\n      \"Uint8Array\",\n      \"Uint8ClampedArray\",\n      \"Int16Array\",\n      \"Uint16Array\",\n      \"Int32Array\",\n      \"Uint32Array\",\n      \"BigInt64Array\",\n      \"BigUint64Array\",\n    ];\n\n    const typeName = array.constructor.name;\n    if (!validTypes.includes(typeName)) {\n      throw new TypeError(`getRandomValues called with unsupported type: ${typeName}`);\n    }\n\n    // Cast to the expected type and call expo-crypto\n    const result = c.getRandomValues(array as any);\n    return result as T;\n  };\n\n  // Define a proper crypto object with all necessary methods\n  const cryptoPolyfill = {\n    getRandomValues: getRandomValuesWrapper,\n    randomUUID:\n      c.randomUUID ||\n      (() => {\n        // Fallback UUID generation if not available\n        return \"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx\".replace(/[xy]/g, function (c) {\n          const r = (Math.random() * 16) | 0;\n          const v = c == \"x\" ? r : (r & 0x3) | 0x8;\n          return v.toString(16);\n        });\n      }),\n    subtle: undefined, // Not needed for most cases\n    // Add other crypto methods from expo-crypto\n    digest: c.digest,\n    digestStringAsync: c.digestStringAsync,\n    getRandomBytes: c.getRandomBytes,\n    getRandomBytesAsync: c.getRandomBytesAsync,\n  };\n\n  // Set up global crypto object\n  if (typeof globalThis !== \"undefined\") {\n    if (!globalThis.crypto) {\n      // @ts-expect-error - polyfill assignment\n      globalThis.crypto = cryptoPolyfill;\n    } else if (!globalThis.crypto.getRandomValues) {\n      globalThis.crypto.getRandomValues = cryptoPolyfill.getRandomValues;\n    }\n  }\n\n  // Set up global.crypto\n  if (typeof global !== \"undefined\") {\n    if (!global.crypto) {\n      // @ts-expect-error - polyfill assignment\n      global.crypto = cryptoPolyfill;\n    } else if (!global.crypto.getRandomValues) {\n      global.crypto.getRandomValues = cryptoPolyfill.getRandomValues;\n    }\n  }\n\n  // Set up window.crypto if in browser environment\n  if (typeof window !== \"undefined\") {\n    if (!window.crypto) {\n      // @ts-expect-error - polyfill assignment\n      window.crypto = cryptoPolyfill;\n    } else if (!window.crypto.getRandomValues) {\n      window.crypto.getRandomValues = cryptoPolyfill.getRandomValues;\n    }\n  }\n\n  // Also set up self.crypto for web workers\n  if (typeof self !== \"undefined\" && self !== global) {\n    if (!self.crypto) {\n      // @ts-expect-error - polyfill assignment\n      self.crypto = cryptoPolyfill;\n    } else if (!self.crypto.getRandomValues) {\n      self.crypto.getRandomValues = cryptoPolyfill.getRandomValues;\n    }\n  }\n\n  console.log(\"shim.ts - crypto polyfill setup complete\");\n  console.log(\"Available crypto methods:\", Object.keys(global.crypto || {}));\n}\n\n// Run the polyfill immediately\nsetupCryptoPolyfill();\n\n// Also set up a fallback check that runs after a short delay\nsetTimeout(() => {\n  if (typeof global?.crypto?.getRandomValues === \"undefined\") {\n    console.log(\"shim.ts - crypto.getRandomValues still undefined, retrying...\");\n    setupCryptoPolyfill();\n  }\n}, 100);\n\n// Test the polyfill to make sure it works\ntry {\n  console.log(\"shim.ts - testing crypto.getRandomValues...\");\n  const testArray = new Uint8Array(10);\n  const result = global.crypto.getRandomValues(testArray);\n  console.log(\"shim.ts - crypto.getRandomValues test successful:\", result.length === 10);\n} catch (error) {\n  console.error(\"shim.ts - crypto.getRandomValues test failed:\", error);\n}\n\n/* if (typeof Buffer === 'undefined') {\n\t// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-var-requires\n\tglobal.Buffer = require('buffer/').Buffer as typeof import('buffer').Buffer\n}\nif (typeof __dirname === 'undefined') { global.__dirname = '/' }\nif (typeof __filename === 'undefined') { global.__filename = '' }\n*/\n"
  },
  {
    "path": "src/storage/DbProvider.ts",
    "content": "import * as SQLite from \"expo-sqlite\";\nimport Storage from \"expo-sqlite/kv-store\";\n\n/**\n * Provider for an Expo SQLite database.\n * - Lazily opens the database on first access\n * - Exposes methods to close and delete the database (useful for tests)\n */\nclass DbProvider {\n  private readonly dbName: string;\n  private database: SQLite.SQLiteDatabase | null = null;\n\n  constructor(dbName: string) {\n    this.dbName = dbName;\n  }\n\n  /**\n   * Returns the SQLite database, opening it if needed.\n   */\n  public getDatabase(): SQLite.SQLiteDatabase {\n    if (!this.database) {\n      this.database = SQLite.openDatabaseSync(this.dbName);\n    }\n    return this.database;\n  }\n\n  public getFingerprint(): string | null {\n    const fingerprint = Storage.getItemSync(\"coco_fingerprint\");\n    return fingerprint;\n  }\n\n  public setFingerprint(fingerprint: string): void {\n    Storage.setItemSync(\"coco_fingerprint\", fingerprint);\n  }\n\n  /**\n   * Whether the database is currently open.\n   */\n  public isOpen(): boolean {\n    return this.database != null;\n  }\n\n  /**\n   * Close the database if open.\n   */\n  public async close(): Promise<void> {\n    if (!this.database) return;\n    try {\n      await this.database.closeAsync();\n    } catch (e) {\n      console.log(e);\n      try {\n        this.database.closeSync?.();\n      } catch {\n        // ignore\n      }\n    } finally {\n      this.database = null;\n    }\n  }\n\n  /**\n   * Delete the database file. Ensures the database is closed first.\n   * Returns true on success.\n   */\n  public async delete(): Promise<void> {\n    await this.close();\n    try {\n      SQLite.deleteDatabaseSync(this.dbName);\n    } catch (e) {\n      console.log(e);\n      console.log(\"Error deleting database\", this.dbName);\n      // ignore\n    }\n  }\n}\nconst dbProvider = new DbProvider(\"coco.db\");\nexport { dbProvider };\nexport default dbProvider;\n"
  },
  {
    "path": "src/storage/dev.ts",
    "content": "import * as FileSystem from \"expo-file-system\";\nimport Storage from \"expo-sqlite/kv-store\";\n\nimport { secureStore, store } from \"./store\";\nimport { SECRET, SECURESTORE_KEY, STORE_KEYS } from \"./store/consts\";\nimport dbProvider from \"./DbProvider\";\nimport { seedService } from \"@src/services/SeedService\";\n\nexport async function dropAllData() {\n  await dbProvider.delete();\n  Storage.clear();\n  await store.clear();\n  await seedService.deleteMnemonic();\n  await secureStore.delete(SECRET);\n  await secureStore.delete(SECURESTORE_KEY);\n  await secureStore.delete(STORE_KEYS.seed);\n  const cacheDir = new FileSystem.Directory(FileSystem.Paths.cache);\n  const documentDir = new FileSystem.Directory(FileSystem.Paths.document);\n  documentDir.delete();\n  cacheDir.delete();\n}\n"
  },
  {
    "path": "src/storage/store/SecureStore.ts",
    "content": "import type { SecureStoreOptions } from \"expo-secure-store\";\nimport * as _SecureStore from \"expo-secure-store\";\n\n/**\n * SecureStore provides a way to encrypt and securely store\n * key–value pairs locally on the device.\n * Each Expo project has a separate storage system\n * and has no access to the storage of other Expo projects\n *\n * Size limit for a value is 2048 bytes. An attempt to store larger values may fail.\n * Currently, we print a warning when the limit is reached, however,\n * in a future SDK version an error might be thrown.\n * @export\n * @class SecureStore\n */\nexport class SecureStore {\n  #options?: SecureStoreOptions;\n  constructor(options?: SecureStoreOptions) {\n    this.#options = options;\n  }\n  public static set(key: string, value: string, options?: SecureStoreOptions): Promise<void> {\n    return _SecureStore.setItemAsync(key, value, options);\n  }\n  public set(key: string, value: string, options?: SecureStoreOptions): Promise<void> {\n    return SecureStore.set(key, value, options ? options : this.#options);\n  }\n  public static get(key: string, options?: SecureStoreOptions): Promise<string | null> {\n    return _SecureStore.getItemAsync(key, options);\n  }\n  public get(key: string, options?: SecureStoreOptions): Promise<string | null> {\n    return SecureStore.get(key, options ? options : this.#options);\n  }\n  public static delete(key: string, options?: SecureStoreOptions): Promise<void> {\n    return _SecureStore.deleteItemAsync(key, options);\n  }\n  public delete(key: string, options?: SecureStoreOptions): Promise<void> {\n    return SecureStore.delete(key, options ? options : this.#options);\n  }\n  public static isAvailable(): Promise<boolean> {\n    return _SecureStore.isAvailableAsync();\n  }\n  public isAvailable(): Promise<boolean> {\n    return SecureStore.isAvailable();\n  }\n}\n"
  },
  {
    "path": "src/storage/store/consts.ts",
    "content": "export const STORE_KEYS = {\n  explainer: \"init_skipped\",\n  theme: \"theme\",\n  // auth\n  pinSkipped: \"auth_skipped\",\n  lock: \"auth_lock\",\n  bgCounter: \"auth_bg\",\n  // preferences\n  reqTimeout: \"request_timeout\",\n  lang: \"settings_lang\",\n  defaultMint: \"MINT_STORE=|:|=default_mint\",\n  hiddenBal: \"privacy_balance\",\n  hiddenTxs: \"privacy_txs\",\n  latestHistory: \"history_latest\",\n  createdToken: \"createdToken\",\n  sawSeedUpdate: \"saw_seed_update\",\n  hasSeed: \"has_seed\",\n  // currency conversion\n  exchangeRates: \"exchange_rates\",\n  exchangeRatesTimestamp: \"exchange_rates_timestamp\",\n  selectedCurrency: \"selected_currency\",\n  formatBalance: \"format_balance\",\n  // NFC settings\n  nfcDefaultMaxAmount: \"nfc_default_max_amount\",\n  // NPC settings\n  npcAccounts: \"npc_accounts\",\n  // secure store keys\n  mnemonic: \"mnemonic\",\n  seed: \"seed\",\n};\n\nexport const SECURESTORE_KEY = \"auth_pin\";\nexport const SECRET = \"secret\";\n"
  },
  {
    "path": "src/storage/store/index.ts",
    "content": "import { SecureStore } from \"./SecureStore\";\nimport Storage from \"expo-sqlite/kv-store\";\n\nclass Store {\n  async set(key: string, value: string) {\n    await Storage.setItemAsync(key, value);\n  }\n  async get(key: string) {\n    return await Storage.getItemAsync(key);\n  }\n  async delete(key: string) {\n    await Storage.removeItemAsync(key);\n  }\n  async clear() {\n    await Storage.clearAsync();\n  }\n}\n\nconst store = new Store();\n\nconst secureStore = new SecureStore();\n\nexport { secureStore, store };\n"
  },
  {
    "path": "src/storage/store/theme.ts",
    "content": "import type { IPreferences, IPreferencesResp } from \"@model\";\nimport Storage from \"expo-sqlite/kv-store\";\n\nimport { STORE_KEYS } from \"../store/consts\";\n\nexport function getPreferences(): IPreferences {\n  const theme = Storage.getItemSync(STORE_KEYS.theme);\n  if (!theme) {\n    return {\n      id: 1,\n      mode: \"auto\",\n      theme: \"Default\",\n      formatBalance: false,\n      hasPref: false,\n    };\n  }\n  const parsed = JSON.parse(theme) as IPreferences;\n  return parsed;\n}\nexport function setPreferences(p: IPreferences) {\n  Storage.setItemSync(STORE_KEYS.theme, JSON.stringify(p));\n}\n"
  },
  {
    "path": "src/styles/colors.ts",
    "content": "import { DefaultTheme } from \"@react-navigation/native\";\n\n// Define ExtendedTheme type\ntype ExtendedTheme = typeof DefaultTheme & {\n  custom: Theme;\n  fonts: {\n    regular: { fontFamily: string; fontWeight: string };\n    medium: { fontFamily: string; fontWeight: string };\n    bold: { fontFamily: string; fontWeight: string };\n    heavy: { fontFamily: string; fontWeight: string };\n  };\n};\n\n// general theme related colors\nexport enum Colors {\n  // light theme\n  L_Background = \"#E7E8E9\",\n  L_Text = \"#656565\",\n  L_Text_Secondary = \"#ADADAD\",\n  L_Input_Bg = \"#F6F6F6\",\n  L_Border = \"#D8D8D8\",\n  L_DARK_Border = \"#E7E8E8\",\n  // dark theme\n  D_Background = \"#1C1C1E\",\n  D_Drawer = \"#252429\",\n  D_Text = \"#EBEBF0\",\n  D_Text_Secondary = \"#999DA2\",\n  D_Border = \"#5F6368\",\n  D_Dark_Border = \"rgba(59, 67, 84, .5)\",\n}\n\nexport type Theme = typeof lightTheme | typeof darkTheme;\n\n// light theme\nexport const lightTheme = {\n  BACKGROUND: Colors.L_Background,\n  DRAWER: Colors.L_Input_Bg,\n  TEXT: Colors.L_Text,\n  TEXT_SECONDARY: Colors.L_Text_Secondary,\n  INPUT_BG: Colors.L_Input_Bg,\n  INPUT_PH: Colors.L_Text,\n  BORDER: Colors.L_Border,\n  DARK_BORDER: Colors.L_DARK_Border,\n};\n\n// dark theme\nconst darkTheme = {\n  BACKGROUND: Colors.D_Background,\n  DRAWER: Colors.D_Drawer,\n  TEXT: Colors.D_Text,\n  TEXT_SECONDARY: Colors.D_Text_Secondary,\n  INPUT_BG: Colors.D_Drawer,\n  INPUT_PH: Colors.D_Border,\n  BORDER: Colors.D_Border,\n  DARK_BORDER: Colors.D_Dark_Border,\n};\n\nexport const light: ExtendedTheme = {\n  dark: false,\n  colors: { ...DefaultTheme.colors },\n  custom: lightTheme,\n  fonts: {\n    regular: { fontFamily: \"\", fontWeight: \"normal\" },\n    medium: { fontFamily: \"\", fontWeight: \"normal\" },\n    bold: { fontFamily: \"\", fontWeight: \"normal\" },\n    heavy: { fontFamily: \"\", fontWeight: \"normal\" },\n  },\n};\n\nexport const dark: ExtendedTheme = {\n  dark: true,\n  colors: { ...DefaultTheme.colors },\n  custom: darkTheme,\n  fonts: {\n    regular: { fontFamily: \"\", fontWeight: \"normal\" },\n    medium: { fontFamily: \"\", fontWeight: \"normal\" },\n    bold: { fontFamily: \"\", fontWeight: \"normal\" },\n    heavy: { fontFamily: \"\", fontWeight: \"normal\" },\n  },\n};\n\n// highlight theme colors\nexport enum H_Colors {\n  Default = \"#5DB075\",\n  Bitcoin = \"#FF9900\",\n  Nuts = \"#B37436\",\n\n  Sky = \"#027DFF\",\n  Azyre = \"#03DDFF\",\n  Rosy = \"#FC7ED0\",\n  Zap = \"#FFCC00\",\n}\n\nexport type HighlightKey = keyof typeof H_Colors;\n\n// Create the highlight object with specific color keys\nexport const highlight: { [key in HighlightKey]: H_Colors } = {\n  Default: H_Colors.Default,\n  Bitcoin: H_Colors.Bitcoin,\n  Nuts: H_Colors.Nuts,\n  Sky: H_Colors.Sky,\n  Azyre: H_Colors.Azyre,\n  Rosy: H_Colors.Rosy,\n  Zap: H_Colors.Zap,\n};\n\n// PIN buttons colors based on highlight theme\nconst pinpadBg = {\n  Default: \"#73BD88\",\n  Bitcoin: \"#FFB340\",\n  Nuts: \"#AB8763\",\n  Sky: \"#58A8FC\",\n  Azyre: \"#79EBFC\",\n  Rosy: \"#FCB3E3\",\n  Zap: \"#FFE16E\",\n};\n\n/**\n * Returns the theme-highlight-related PIN button background color\n */\nexport function getPinpadBg(highlight: keyof typeof pinpadBg) {\n  return pinpadBg[highlight];\n}\n\nexport enum mainColors {\n  // indicators\n  VALID = \"#5DB076\",\n  WARN = \"#FF9900\",\n  ERROR = \"#FF6666\",\n  // colors\n  BLACK = \"#000\",\n  WHITE = \"#FAFAFA\",\n  GREY = \"#999\",\n  BLUE = \"#027DFF\",\n  ZAP = H_Colors.Zap,\n  STAR = \"#E5BC50\",\n}\n\nexport const themeColors = Object.keys(highlight) as HighlightKey[];\n\nexport const getColor = (highlight: HighlightKey, color: Theme) => {\n  if (highlight === \"Azyre\" || highlight === \"Zap\" || highlight === \"Rosy\") {\n    return color.BACKGROUND;\n  }\n  return mainColors.WHITE;\n};\n"
  },
  {
    "path": "src/styles/globals.ts",
    "content": "import { ScaledSheet } from \"react-native-size-matters\";\n\nimport { highlight, type HighlightKey, mainColors, type Theme } from \"./colors\";\n\nexport const globalStyles = (color?: Theme, h?: HighlightKey) =>\n  ScaledSheet.create({\n    container: {\n      flex: 1,\n      backgroundColor: color?.BACKGROUND,\n    },\n    fullWidth: {\n      width: \"100%\",\n    },\n    txt: {\n      fontSize: \"14@vs\",\n      color: color?.TEXT,\n    },\n    txtBold: {\n      fontSize: \"14@vs\",\n      fontWeight: \"500\",\n      color: color?.TEXT,\n    },\n    pressTxt: {\n      fontSize: \"14@vs\",\n      fontWeight: \"500\",\n      textAlign: \"center\",\n      color: h ? highlight[h] : mainColors.BLACK,\n    },\n    navTxt: {\n      fontSize: \"18@vs\",\n      fontWeight: \"500\",\n      color: color?.TEXT,\n    },\n    input: {\n      color: color?.TEXT,\n      backgroundColor: color?.INPUT_BG,\n      paddingHorizontal: \"18@s\",\n      paddingVertical: \"18@vs\",\n      borderRadius: 50,\n      fontSize: \"14@vs\",\n      width: \"100%\",\n    },\n    modalHeader: {\n      fontSize: \"22@vs\",\n      fontWeight: \"500\",\n      marginBottom: \"30@vs\",\n      marginTop: \"10@vs\",\n      textAlign: \"center\",\n      color: color?.TEXT,\n    },\n    modalTxt: {\n      fontSize: \"14@vs\",\n      textAlign: \"center\",\n      color: color?.TEXT,\n      marginHorizontal: 20,\n      marginTop: -15,\n      marginBottom: \"30@vs\",\n    },\n    scrollContainer: {\n      flex: 1,\n      borderRadius: 20,\n      backgroundColor: color?.DRAWER,\n      padding: 0,\n    },\n    scrollRow: {\n      flexDirection: \"row\",\n      alignItems: \"center\",\n      justifyContent: \"space-between\",\n      paddingHorizontal: \"20@s\",\n      paddingVertical: \"20@vs\",\n    },\n    wrapContainer: {\n      borderRadius: 20,\n      backgroundColor: color?.DRAWER,\n      paddingHorizontal: \"20@s\",\n      paddingTop: \"20@vs\",\n      paddingBottom: \"5@vs\",\n      marginBottom: \"20@vs\",\n    },\n    wrapRow: {\n      flex: 1,\n      flexDirection: \"row\",\n      alignItems: \"center\",\n      justifyContent: \"space-between\",\n      paddingBottom: \"20@vs\",\n      // backgroundColor: '#fff'\n    },\n    radioBtn: {\n      borderWidth: 1,\n      width: \"20@s\",\n      height: \"20@s\",\n      borderRadius: \"10@s\",\n      borderColor: color?.BORDER,\n    },\n    bold: {\n      fontWeight: \"500\",\n    },\n    selectAmount: {\n      width: \"100%\",\n      fontSize: \"48@vs\",\n      marginBottom: \"5@vs\",\n      fontWeight: \"600\",\n      padding: 0,\n      textAlign: \"center\",\n    },\n  });\n"
  },
  {
    "path": "src/styles/index.ts",
    "content": "export type { HighlightKey, Theme } from \"./colors\";\nexport { dark, getPinpadBg, highlight, light, lightTheme, mainColors, themeColors } from \"./colors\";\nexport { globalStyles as globals } from \"./globals\";\n"
  },
  {
    "path": "src/util/index.ts",
    "content": "import { l } from \"@log\";\nimport type { IMintBalWithName, IProofSelection } from \"@model\";\nimport * as Clipboard from \"expo-clipboard\";\nimport { Linking, Share, Vibration } from \"react-native\";\n\nimport { isUrl } from \"./lnurl\";\nimport { getLanguageCode } from \"./localization\";\nimport { isArr, isStr } from \"./typeguards\";\n\nexport {\n  isArr,\n  isArrOf,\n  isArrOfNonNullable,\n  isArrOfNum,\n  isArrOfObj,\n  isArrOfStr,\n  isBool,\n  isBuf,\n  isErr,\n  isNonNullable,\n  isNull,\n  isNum,\n  isObj,\n  isStr,\n  isUndef,\n} from \"./typeguards\";\nexport * from \"./paymentStringParser\";\n\nexport function unixTimestamp() {\n  return Math.ceil(new Date().getTime() / 1000);\n}\n\n/**\n * Return the unique values found in the passed iterable\n */\nexport function uniq<T extends string | number | bigint | boolean | symbol>(iter: Iterable<T>) {\n  return [...new Set(iter)];\n}\n\nexport function uniqByIContacts(iter: Iterable<IContact>, key: keyof IContact) {\n  // l()\n  const o = [...iter].reduce<{ [k: string | number | symbol]: IContact }>((acc, cur) => {\n    const hex = cur?.[key];\n    if (!hex) {\n      return acc;\n    }\n    if (!acc[hex] || Object.keys(cur).length > Object.keys(acc[hex]).length) {\n      // l({ cur, hex, accItem: acc[hex] })\n      acc[hex] = cur;\n      return acc;\n    }\n    return acc;\n  }, {});\n  // l({o})\n  return Object.values(o);\n}\nexport function clearArr<T extends U[], U>(array: T) {\n  array.length = 0;\n}\n\nexport function sleep(ms: number) {\n  return new Promise<void>((resolve) => setTimeout(resolve, ms));\n}\n\nexport function formatBalance(bal: number) {\n  return (bal / 100_000_000).toFixed(8);\n}\n\n/**\n * format a number to a string with a given locale. Compact notation is not yet supported for all locales.\n *\n * if locale is not specified, the current locale is used\n *\n * @export\n * @param {number} val number to format\n * @param {('standard' | 'engineering' | 'scientific' | 'compact')} [notation='standard'] 'standard' | 'engineering' | 'scientific' | 'compact'\n * @param {string} [locale] optional defaults to the current locale\n * @returns {string}  formatted string representation of the number\n */\nexport function formatInt(\n  val: number,\n  notation: \"standard\" | \"engineering\" | \"scientific\" | \"compact\" = \"standard\",\n  locale?: string,\n): string {\n  try {\n    const lan = getLanguageCode();\n    // eslint-disable-next-line new-cap\n    const numberFormatter = Intl.NumberFormat(locale || lan, { notation });\n    return numberFormatter.format(val);\n  } catch (e) {\n    l(e);\n    return val.toLocaleString();\n  }\n}\n\n/**\n * Generates a short date string representation based on the provided date.\n *\n * @param date - The date for which the short date string is generated.\n * @returns A short date string representation f.E: \"Mo., 17. Aug. 23\"\n */\nexport function getShortDateStr(date: Date) {\n  return date.toLocaleDateString(getLanguageCode(), {\n    year: \"2-digit\",\n    month: \"short\",\n    day: \"2-digit\",\n    weekday: \"short\",\n  });\n}\n\nexport function isToday(someDate: Date) {\n  const today = new Date();\n  return (\n    someDate.getDate() === today.getDate() &&\n    someDate.getMonth() === today.getMonth() &&\n    someDate.getFullYear() === today.getFullYear()\n  );\n}\n\nexport function getHistoryGroupDate(date: Date) {\n  return isToday(date) ? \"Today\" : getShortDateStr(date);\n}\n\nexport function formatMintUrl(url: string) {\n  const clean = url.startsWith(\"http\") ? url.split(\"://\")[1] : url;\n  if (clean.length < 30) {\n    return clean;\n  }\n  const u = new URL(url);\n  return `${u.hostname.slice(0, 25)}...${u.pathname.slice(-10)}`;\n}\n\n/**\n * @param time a number in seconds\n * @returns the following format: 00:00\n */\nexport function formatSeconds(time: number) {\n  const minutes = Math.floor(time / 60);\n  const seconds = time % 60;\n  return `${minutes.toString().padStart(2, \"0\")}:${seconds.toString().padStart(2, \"0\")}`;\n}\n\nexport function getSelectedAmount(proofs: IProofSelection[]) {\n  return proofs.reduce((acc, p) => acc + (p.selected ? p.amount : 0), 0);\n}\n\nexport function vib(pattern?: number | number[]) {\n  Vibration.vibrate(pattern);\n}\n\nexport function hasTrustedMint(userMints: string[], tokenMints: string[]): boolean;\n\nexport function hasTrustedMint(userMints: { mintUrl: string }[], tokenMints: string[]): boolean;\n\nexport function hasTrustedMint(uMints: ({ mintUrl: string } | string)[], tMints: string[]) {\n  if (!uMints?.length || !isArr(uMints) || !tMints?.length || !isArr(tMints)) {\n    return false;\n  }\n  return uMints.some((m) => tMints.includes(isStr(m) ? m : m.mintUrl));\n}\n\nexport function extractStrFromURL(url?: string) {\n  try {\n    const u = new URL(url || \"\");\n    return u.hostname || u.pathname;\n  } catch {\n    return url;\n  }\n}\n\nexport function* arrToChunks<T extends T[number][]>(arr: T, n: number) {\n  for (let i = 0; i < arr.length; i += n) {\n    yield arr.slice(i, i + n);\n  }\n}\n\n/**\n * This function is used to show a few TX info in the history entry details page\n * @param invoice The LN invoice\n */\nexport function getLnInvoiceInfo(invoice: string) {\n  if (!invoice) {\n    return { hash: \"\", memo: \"Mint new tokens test\" };\n  }\n  const x = decodeLnInvoice(invoice);\n  return { ...x, hash: x.paymentHash, memo: x.memo };\n}\n\nexport function decodeLnInvoice(invoice: string) {\n  const x = decodeInvoice(invoice);\n  const amount = x.amountInMSats;\n  const timestamp = x.timestamp;\n  const expiry = x.expiry;\n  const memo = x.memo;\n  const paymentHash = x.paymentHash;\n  const timePassed = unixTimestamp() - timestamp;\n  const timeLeft = expiry - timePassed;\n  return {\n    decoded: x,\n    amount: amount / 1000,\n    timestamp,\n    expiry,\n    timeLeft,\n    memo,\n    paymentHash,\n  };\n}\n\nexport function cleanUpNumericStr(str: string) {\n  if (str.startsWith(\"0\")) {\n    return \"\";\n  }\n  return str.replace(/\\D/g, \"\");\n}\n\nexport function openUrl(url: string) {\n  if (!url?.trim() || !isUrl(url)) {\n    return;\n  }\n  return Linking.openURL(url);\n}\n\nexport async function copyStrToClipboard(str: string) {\n  await Clipboard.setStringAsync(str);\n}\n\nexport async function getStrFromClipboard() {\n  try {\n    const s = await Clipboard.getStringAsync();\n    if (!s) {\n      return null;\n    }\n    return s;\n  } catch (error) {\n    l(\"[getStrFromClipboard]\", error);\n  }\n  return null;\n}\n\nexport async function share(message: string, url?: string) {\n  try {\n    const res = await Share.share({ message, url });\n    if (res.action === Share.sharedAction) {\n      if (res.activityType) {\n        // shared with activity type of result.activityType\n        return l(\"shared with activity type of result.activityType\");\n      }\n      // shared\n      return l(\"shared\");\n    }\n    if (res.action === Share.dismissedAction) {\n      // dismissed\n      l(\"sharing dismissed\");\n    }\n  } catch (e) {\n    l(\"[quick-share error] \", e);\n  }\n}\n\nexport function normalizeMintUrl(url: string) {\n  const res = url.startsWith(\"https://\") ? url : `https://${url}`;\n  if (!isUrl(res)) {\n    return;\n  }\n  return res;\n}\n\nexport function sortMintsByDefault(mints: IMintBalWithName[], defaultMint: string) {\n  return mints.sort((a, b) => {\n    if (a.mintUrl === defaultMint) {\n      return -1;\n    }\n    if (b.mintUrl === defaultMint) {\n      return 1;\n    }\n    // if neither 'a' nor 'b' is the default mint, sort by amount (descending)\n    return b.amount - a.amount;\n  });\n}\n\nexport function debounce<T extends (...args: any[]) => void>(\n  func: T,\n  timeout = 300,\n): (...args: Parameters<T>) => void {\n  let timer: NodeJS.Timeout;\n\n  return function (this: ThisParameterType<T>, ...args: Parameters<T>): void {\n    clearTimeout(timer);\n    timer = setTimeout(() => {\n      func.apply(this, args);\n    }, timeout);\n  };\n}\n\nexport function formatSatStr(\n  amount: number,\n  notation: \"standard\" | \"engineering\" | \"scientific\" | \"compact\" = \"standard\",\n  showAmount = true,\n) {\n  return `${showAmount ? `${formatInt(amount, notation, \"en\")} ` : \" \"}${\n    amount < 2 && amount > -2 ? \"Sat\" : \"Sats\"\n  }`;\n}\n\nexport function getUnixTimestampFromDaysAgo(days: number) {\n  const oneDayInMs = 24 * 60 * 60 * 1000;\n  return Math.ceil(getUnixTimestamp() - days * oneDayInMs);\n}\n\nexport function getUnixTimestamp() {\n  return Math.ceil(new Date().getTime() / 1000);\n}\n\nexport function withTimeout<T>(promis: Promise<T>, ms: number) {\n  return Promise.race([promis, timeout<T>(ms)]);\n}\n\nexport async function timeout<T>(ms = 1000) {\n  if (ms < 0) {\n    return {} as unknown as T;\n  } // should never happen\n  await sleep(ms);\n  throw new Error(`promise was timed out in ${ms} ms, by withTimeout`);\n}\n\nexport function getFlagEmoji(code: string) {\n  const codePoints = Array.from(code.toUpperCase()).map((char) => 0x1f1a5 + char.charCodeAt(0));\n  return String.fromCodePoint(...codePoints);\n}\n"
  },
  {
    "path": "src/util/lnurl.ts",
    "content": "import type { ILnUrlPayRequest } from \"@model\";\nimport { bech32 } from \"bech32\";\nimport { Buffer } from \"buffer/\";\n\nconst LNURL_REGEX = /^(?:http.*[&?]lightning=|lightning:)?(lnurl[0-9]{1,}[02-9ac-hj-np-z]+)/;\n\nconst LN_ADDRESS_REGEX =\n  /^((?:[^<>()[\\]\\\\.,;:\\s@\"]+(?:\\.[^<>()[\\]\\\\.,;:\\s@\"]+)*)|(?:\".+\"))@((?:\\[[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\])|(?:(?:[a-zA-Z\\-0-9]+\\.)+[a-zA-Z]{2,}))$/;\n\nconst LNURLP_REGEX = /^lnurlp:\\/\\/([\\w-]+\\.)+[\\w-]+(:\\d{1,5})?(\\/[\\w-./?%&=]*)?$/;\n\nexport interface LightningAddress {\n  username: string;\n  domain: string;\n}\n\nexport function isUrl(url: string) {\n  try {\n    return !!new URL(url);\n  } catch {\n    /* ignore*/\n  }\n  return false;\n}\n\nexport function isLnurl(str: string) {\n  const bech32Url: string | null = parseLnUrl(str);\n  if (bech32Url) {\n    return true;\n  }\n  const lnurlp = parseLnurlp(str);\n  if (lnurlp) {\n    return true;\n  }\n  return false;\n}\n\n/**\n * Parse an url and return a bech32 encoded url (lnurl)\n * @method parseLnUrl\n * @param  url string to parse\n * @return  bech32 encoded url (lnurl) or null if is an invalid url\n */\nexport const parseLnUrl = (url: string): string | null => {\n  if (!url) {\n    return null;\n  }\n  const result = LNURL_REGEX.exec(url.toLowerCase());\n  return result ? result[1] : null;\n};\n\n/**\n * Verify if a string is a lightning adress\n * @method isLightningAddress\n * @param  address string to validate\n * @return  true if is a lightning address\n */\nexport const isLightningAddress = (address: string): boolean => {\n  if (!address) {\n    return false;\n  }\n  return LN_ADDRESS_REGEX.test(address);\n};\n\n/**\n * Parse an address and return username and domain\n * @method parseLightningAddress\n * @param  address string to parse\n * @return  LightningAddress { username, domain }\n */\nexport const parseLightningAddress = (address: string): LightningAddress | null => {\n  if (!address) {\n    return null;\n  }\n  const result = LN_ADDRESS_REGEX.exec(address);\n  return result ? { username: result[1], domain: result[2] } : null;\n};\n\n/**\n * Verify if a string is a lnurlp url\n * @method isLnurlp\n * @param  url string to validate\n * @return  true if is a lnurlp url\n */\nexport const isLnurlp = (url: string): boolean => {\n  if (!url) {\n    return false;\n  }\n  return LNURLP_REGEX.test(url);\n};\n\n/**\n * Parse a lnurlp url and return an url with the proper protocol\n * @method parseLnurlp\n * @param  url string to parse\n * @return  url (http or https) or null if is an invalid lnurlp\n */\nexport const parseLnurlp = (url: string): string | null => {\n  if (!url) {\n    return null;\n  }\n  const parsedUrl = url.toLowerCase();\n  if (!LNURLP_REGEX.test(parsedUrl)) {\n    return null;\n  }\n  const protocol = parsedUrl.includes(\".onion\") ? \"http://\" : \"https://\";\n  return parsedUrl.replace(\"lnurlp://\", protocol);\n};\n\nexport const decodeUrlOrAddress = (lnUrlOrAddress: string): string | null => {\n  const bech32Url = parseLnUrl(lnUrlOrAddress);\n  if (bech32Url) {\n    const decoded = bech32.decode(bech32Url, 20000);\n    return Buffer.from(bech32.fromWords(decoded.words)).toString();\n  }\n  const address = parseLightningAddress(lnUrlOrAddress);\n  if (address) {\n    const { username, domain } = address;\n    const protocol = domain.match(/\\.onion$/) ? \"http\" : \"https\";\n    return `${protocol}://${domain}/.well-known/lnurlp/${username}`;\n  }\n  return parseLnurlp(lnUrlOrAddress);\n};\n\nexport function getLnurlData(url?: string): Promise<ILnUrlPayRequest> | null {\n  if (!url) {\n    return null;\n  }\n  return fetch(url).then((res) => res.json());\n}\n\nexport function getLnurlIdentifierFromMetadata(metadata: string) {\n  try {\n    const parsed = JSON.parse(metadata) as string[][];\n    const identifier = parsed.find(([key]) => key === \"text/identifier\")?.[1];\n    return identifier ?? \"Identifier not found\";\n  } catch {\n    return \"Error: Identifier not found\";\n  }\n}\n"
  },
  {
    "path": "src/util/localization.ts",
    "content": "import { type TranslationLangCodes, translationLangCodes } from \"@model/i18n\";\nimport { getLocales } from \"expo-localization\";\n\n/**\n * Retrieves the primary language code from the current locale.\n */\nexport function getLanguageCode() {\n  const locales = getLocales();\n  return locales[0].languageCode?.split(\"-\")[0] ?? \"en\";\n}\n\n/**\n * Retrieves the translation language code based on the primary language code.\n * If the primary language code is not supported, 'en' (English) is returned as the default.\n */\nexport function getTranslationLangCode() {\n  const lang = getLanguageCode();\n  return (translationLangCodes.includes(lang) ? lang : \"en\") as TranslationLangCodes;\n}\n"
  },
  {
    "path": "src/util/lud16.ts",
    "content": "import { decodeUrlOrAddress } from \"@util/lnurl\";\n\nexport type LnAddressMetadata = {\n  tag: \"payRequest\";\n  callback: string;\n  minSendable: number;\n  maxSendable: number;\n  metadata: string;\n};\n\nfunction isLnurlPayMetadata(data: unknown): data is LnAddressMetadata {\n  if (!data || typeof data !== \"object\") {\n    return false;\n  }\n\n  const metadata = data as Partial<LnAddressMetadata>;\n  return (\n    metadata.tag === \"payRequest\" &&\n    typeof metadata.callback === \"string\" &&\n    metadata.callback.length > 0 &&\n    typeof metadata.minSendable === \"number\" &&\n    typeof metadata.maxSendable === \"number\" &&\n    typeof metadata.metadata === \"string\"\n  );\n}\n\nexport async function requestLnurlPayMetadata(lnUrlOrAddress: string): Promise<LnAddressMetadata> {\n  const url = decodeUrlOrAddress(lnUrlOrAddress);\n  if (!url) {\n    throw new Error(\"Invalid LNURL or Lightning address\");\n  }\n  const response = await fetch(url);\n  const data = (await response.json()) as unknown;\n  if (!isLnurlPayMetadata(data)) {\n    throw new Error(\"Invalid LNURL pay request\");\n  }\n  return data;\n}\n\nexport async function getInvoiceFromLnAddress(\n  data: LnAddressMetadata,\n  amountInMsats: number,\n): Promise<string> {\n  if (!data.callback) {\n    throw new Error(\"Callback URL is required\");\n  }\n  const res = await fetch(`${data.callback}?amount=${amountInMsats}`);\n  const { pr } = (await res.json()) as { pr: string };\n  if (!pr) {\n    throw new Error(\"No invoice found\");\n  }\n  return pr;\n}\n"
  },
  {
    "path": "src/util/paymentStringParser.ts",
    "content": "import { decodePaymentRequest, getDecodedToken } from \"@cashu/cashu-ts\";\n\nimport { isLightningAddress, isLnurl } from \"./lnurl\";\n\nexport type PaymentCandidateKind =\n  | \"cashuToken\"\n  | \"lightningInvoice\"\n  | \"lightningAddress\"\n  | \"lnurl\"\n  | \"cashuPaymentRequest\"\n  | \"bitcoinAddress\";\n\nexport type PaymentCandidateSource = \"direct\" | \"uri\" | \"bitcoin-uri-body\" | \"bitcoin-uri-param\";\n\ninterface IPaymentCandidateBase {\n  kind: PaymentCandidateKind;\n  value: string;\n  raw: string;\n  source: PaymentCandidateSource;\n  param?: string;\n  required?: boolean;\n  supported: boolean;\n}\n\nexport interface ICashuTokenCandidate extends IPaymentCandidateBase {\n  kind: \"cashuToken\";\n  supported: true;\n}\n\nexport interface ILightningInvoiceCandidate extends IPaymentCandidateBase {\n  kind: \"lightningInvoice\";\n  supported: true;\n}\n\nexport interface ILightningAddressCandidate extends IPaymentCandidateBase {\n  kind: \"lightningAddress\";\n  supported: true;\n}\n\nexport interface ILnurlCandidate extends IPaymentCandidateBase {\n  kind: \"lnurl\";\n  supported: true;\n}\n\nexport interface ICashuPaymentRequestCandidate extends IPaymentCandidateBase {\n  kind: \"cashuPaymentRequest\";\n  supported: true;\n}\n\nexport interface IBitcoinAddressCandidate extends IPaymentCandidateBase {\n  kind: \"bitcoinAddress\";\n  supported: false;\n}\n\nexport type PaymentStringCandidate =\n  | ICashuTokenCandidate\n  | ILightningInvoiceCandidate\n  | ILightningAddressCandidate\n  | ILnurlCandidate\n  | ICashuPaymentRequestCandidate\n  | IBitcoinAddressCandidate;\n\nconst CASHU_TOKEN_URI_PREFIXES = [\n  \"https://wallet.nutstash.app/#\",\n  \"https://wallet.cashu.me/?token=\",\n  \"web+cashu://\",\n  \"cashu://\",\n  \"cashu:\",\n];\n\nconst LIGHTNING_PREFIXES = [\"lightning://\", \"lightning:\", \"lightning=\"];\n\nconst LNURL_WRAPPER_PREFIXES = [\"lnurl://\", \"lnurl=\", \"lnurl:\"];\n\nconst CASHU_REQUEST_PARAM_KEYS = new Set([\n  \"cashu\",\n  \"cashu_pr\",\n  \"cashu_request\",\n  \"cashupaymentrequest\",\n  \"cashu_payment_request\",\n  \"creq\",\n  \"paymentrequest\",\n  \"payment_request\",\n]);\n\nconst CASHU_TOKEN_PARAM_KEYS = new Set([\"cashu_token\", \"cashutoken\", \"token\"]);\n\nconst BITCOIN_ADDRESS_PARAM_KEYS = new Set([\"bc\", \"tb\", \"bcrt\"]);\n\nfunction stripPrefix(value: string, prefixes: string[]) {\n  const lower = value.toLowerCase();\n  const prefix = prefixes.find((p) => lower.startsWith(p));\n  return prefix ? value.slice(prefix.length).trim() : value;\n}\n\nfunction stripCashuTokenUri(value: string) {\n  let normalized = value.trim();\n  const idx = normalized.indexOf(\"cashuA\");\n  if (idx !== -1) {\n    normalized = normalized.slice(idx);\n  }\n  return stripPrefix(normalized, CASHU_TOKEN_URI_PREFIXES);\n}\n\nfunction stripLightningUri(value: string) {\n  return stripPrefix(value.trim(), LIGHTNING_PREFIXES);\n}\n\nfunction isCashuTokenValue(value: string) {\n  try {\n    getDecodedToken(value);\n    return true;\n  } catch {\n    return false;\n  }\n}\n\nfunction isCashuPaymentRequestValue(value: string) {\n  try {\n    decodePaymentRequest(value);\n    return true;\n  } catch {\n    return false;\n  }\n}\n\nfunction isLightningInvoiceValue(value: string) {\n  const normalized = value.trim().toLowerCase();\n  return (\n    normalized.startsWith(\"lnbc\") ||\n    normalized.startsWith(\"lntb\") ||\n    normalized.startsWith(\"lnbcrt\") ||\n    normalized.startsWith(\"lnsb\") ||\n    normalized.startsWith(\"lntbs\")\n  );\n}\n\nfunction isBitcoinAddressValue(value: string) {\n  const normalized = value.trim();\n  return (\n    /^(bc1|tb1|bcrt1)[023456789acdefghjklmnpqrstuvwxyz]{10,}$/i.test(normalized) ||\n    /^[13mn2][a-km-zA-HJ-NP-Z1-9]{25,}$/.test(normalized)\n  );\n}\n\nfunction decodeUriComponent(value: string) {\n  try {\n    return decodeURIComponent(value);\n  } catch {\n    return value;\n  }\n}\n\nfunction addCandidate(candidates: PaymentStringCandidate[], candidate: PaymentStringCandidate) {\n  const exists = candidates.some(\n    (item) =>\n      item.kind === candidate.kind &&\n      item.value === candidate.value &&\n      item.param === candidate.param &&\n      item.source === candidate.source,\n  );\n\n  if (!exists) {\n    candidates.push(candidate);\n  }\n}\n\nfunction parseStandalonePaymentString(\n  input: string,\n  source: PaymentCandidateSource,\n  raw: string,\n  param?: string,\n  required?: boolean,\n) {\n  const candidates: PaymentStringCandidate[] = [];\n  const trimmed = input.trim();\n\n  if (!trimmed) {\n    return candidates;\n  }\n\n  const cashuPaymentRequest = stripPrefix(\n    stripPrefix(trimmed, [\"cashu-request://\", \"cashu-request:\"]),\n    CASHU_TOKEN_URI_PREFIXES,\n  );\n  if (isCashuPaymentRequestValue(cashuPaymentRequest)) {\n    addCandidate(candidates, {\n      kind: \"cashuPaymentRequest\",\n      value: cashuPaymentRequest,\n      raw,\n      source,\n      param,\n      required,\n      supported: true,\n    });\n  }\n\n  const cashuToken = stripCashuTokenUri(trimmed);\n  if (isCashuTokenValue(cashuToken)) {\n    addCandidate(candidates, {\n      kind: \"cashuToken\",\n      value: cashuToken,\n      raw,\n      source,\n      param,\n      required,\n      supported: true,\n    });\n  }\n\n  const lightningValue = stripLightningUri(trimmed);\n  if (isLightningInvoiceValue(lightningValue)) {\n    addCandidate(candidates, {\n      kind: \"lightningInvoice\",\n      value: lightningValue,\n      raw,\n      source,\n      param,\n      required,\n      supported: true,\n    });\n  }\n\n  const lnurlValue = isLnurl(lightningValue)\n    ? lightningValue\n    : stripPrefix(lightningValue, LNURL_WRAPPER_PREFIXES);\n  if (isLnurl(lnurlValue)) {\n    addCandidate(candidates, {\n      kind: \"lnurl\",\n      value: lnurlValue,\n      raw,\n      source,\n      param,\n      required,\n      supported: true,\n    });\n  }\n\n  if (isLightningAddress(lightningValue)) {\n    addCandidate(candidates, {\n      kind: \"lightningAddress\",\n      value: lightningValue,\n      raw,\n      source,\n      param,\n      required,\n      supported: true,\n    });\n  }\n\n  if (isBitcoinAddressValue(trimmed)) {\n    addCandidate(candidates, {\n      kind: \"bitcoinAddress\",\n      value: trimmed,\n      raw,\n      source,\n      param,\n      required,\n      supported: false,\n    });\n  }\n\n  return candidates;\n}\n\nfunction parseBitcoinUri(input: string) {\n  const candidates: PaymentStringCandidate[] = [];\n  const raw = input.trim();\n  const body = raw.slice(raw.indexOf(\":\") + 1);\n  const [addressPart = \"\", query = \"\"] = body.split(\"?\");\n  const address = decodeUriComponent(addressPart.replace(/^\\/\\//, \"\")).trim();\n\n  if (address && isBitcoinAddressValue(address)) {\n    addCandidate(candidates, {\n      kind: \"bitcoinAddress\",\n      value: address,\n      raw,\n      source: \"bitcoin-uri-body\",\n      supported: false,\n    });\n  }\n\n  const params = new URLSearchParams(query);\n\n  params.forEach((value, key) => {\n    const normalizedKey = key.toLowerCase();\n    const isRequired = normalizedKey.startsWith(\"req-\");\n    const unprefixedKey = isRequired ? normalizedKey.slice(4) : normalizedKey;\n\n    if (unprefixedKey === \"lightning\") {\n      parseStandalonePaymentString(value, \"bitcoin-uri-param\", raw, key, isRequired).forEach(\n        (candidate) => addCandidate(candidates, candidate),\n      );\n      return;\n    }\n\n    if (unprefixedKey === \"lnurl\" || unprefixedKey === \"lnurlp\") {\n      parseStandalonePaymentString(value, \"bitcoin-uri-param\", raw, key, isRequired).forEach(\n        (candidate) => addCandidate(candidates, candidate),\n      );\n      return;\n    }\n\n    if (CASHU_REQUEST_PARAM_KEYS.has(unprefixedKey) || CASHU_TOKEN_PARAM_KEYS.has(unprefixedKey)) {\n      parseStandalonePaymentString(value, \"bitcoin-uri-param\", raw, key, isRequired).forEach(\n        (candidate) => addCandidate(candidates, candidate),\n      );\n      return;\n    }\n\n    if (BITCOIN_ADDRESS_PARAM_KEYS.has(unprefixedKey) && isBitcoinAddressValue(value)) {\n      addCandidate(candidates, {\n        kind: \"bitcoinAddress\",\n        value,\n        raw,\n        source: \"bitcoin-uri-param\",\n        param: key,\n        required: isRequired,\n        supported: false,\n      });\n    }\n  });\n\n  return candidates;\n}\n\nexport function parsePaymentString(input: string): PaymentStringCandidate[] {\n  const trimmed = String(input || \"\").trim();\n  if (!trimmed) {\n    return [];\n  }\n\n  if (trimmed.toLowerCase().startsWith(\"bitcoin:\")) {\n    return parseBitcoinUri(trimmed);\n  }\n\n  return parseStandalonePaymentString(trimmed, trimmed.includes(\":\") ? \"uri\" : \"direct\", trimmed);\n}\n"
  },
  {
    "path": "src/util/typeguards.ts",
    "content": "import { Buffer } from \"buffer/\";\n\nexport function isStr(v: unknown): v is string {\n  return typeof v === \"string\";\n}\nexport function isNum(v: unknown): v is number {\n  return typeof v === \"number\";\n}\nexport function isObj(v: unknown): v is object {\n  return typeof v === \"object\";\n}\nexport function isBool(v: unknown): v is boolean {\n  return typeof v === \"boolean\";\n}\nexport function isUndef(v: unknown): v is undefined {\n  return typeof v === \"undefined\";\n}\nexport function isNull(v: unknown): v is null {\n  return v === null;\n}\nexport function isArr(v: unknown): v is unknown[] {\n  return Array.isArray(v);\n}\nexport function isErr(v: unknown): v is Error {\n  return v instanceof Error;\n}\nexport function isBuf(v: unknown): v is Buffer {\n  return Buffer.isBuffer(v);\n}\nexport function isNonNullable<T>(v: T): v is NonNullable<T> {\n  return !isNull(v) && !isUndef(v);\n}\nexport function isArrOf<T>(elemGuard: (x: unknown) => x is T) {\n  return (arr: unknown[]): arr is T[] => arr.every(elemGuard);\n}\nexport function isArrOfStr(arr: unknown): arr is string[] {\n  return isArr(arr) && arr.every(isStr);\n}\nexport function isArrOfNum(arr: unknown[]): arr is number[] {\n  return arr.every(isNum);\n}\nexport function isArrOfObj(arr: unknown[]): arr is object[] {\n  return arr.every(isObj);\n}\nexport function isArrOfNonNullable<T>(arr: unknown[]): arr is NonNullable<T>[] {\n  return arr.every(isNonNullable);\n}\n"
  },
  {
    "path": "tsconfig.json",
    "content": "{\n  \"extends\": \"expo/tsconfig.base\",\n  \"compilerOptions\": {\n    \"strict\": true,\n    \"baseUrl\": \".\",\n    \"paths\": {\n      \"@nav\": [\"src/components/nav\"],\n      \"@nav/*\": [\"src/components/nav/*\"],\n      \"@comps\": [\"src/components\"],\n      \"@comps/*\": [\"src/components/*\"],\n      \"@screens\": [\"src/screens\"],\n      \"@screens/*\": [\"src/screens/*\"],\n      \"@src\": [\"src\"],\n      \"@src/*\": [\"src/*\"],\n      \"@assets/*\": [\"assets/*\"],\n      \"@log\": [\"src/logger\"],\n      \"@log/*\": [\"src/logger/*\"],\n      \"@model/*\": [\"src/model/*\"],\n      \"@model\": [\"src/model\"],\n      \"@styles\": [\"src/styles\"],\n      \"@styles/*\": [\"src/styles/*\"],\n      \"@wallet\": [\"src/wallet\"],\n      \"@wallet/*\": [\"src/wallet/*\"],\n      \"@util\": [\"src/util\"],\n      \"@util/*\": [\"src/util/*\"],\n      \"@modal\": [\"src/components/modal\"],\n      \"@modal/*\": [\"src/components/modal/*\"],\n      \"@db\": [\"src/storage/db\"],\n      \"@db/*\": [\"src/storage/db/*\"],\n      \"@store\": [\"src/storage/store\"],\n      \"@store/*\": [\"src/storage/store/*\"],\n      \"@consts\": [\"src/consts\"],\n      \"@consts/*\": [\"src/consts/*\"]\n    }\n  }\n}\n"
  },
  {
    "path": "zapstore.yaml",
    "content": "repository: https://github.com/cashubtc/eNuts\nrelease_source: https://github.com/cashubtc/eNuts\ndescription: >-\n  Warning: This is an alpha-state release! Use at your own risk!\n  eNuts is a mobile Cashu wallet for Bitcoin ecash. Add a mint you trust,\n  receive or redeem Cashu tokens, pay Lightning invoices, and keep ecash\n  stored locally on your device. QR and NFC make\n  everyday payments quick.\nsummary: Private ecash payments with Cashu and Lightning\ntags:\n  - cashu,ecash,wallet,lightning,bitcoin,nfc\nlicense: MIT\nwebsite: https://enuts.cash\nmetadata_sources:\n  - github\npubkey: npub1mhcr4j594hsrnen594d7700n2t03n8gdx83zhxzculk6sh9nhwlq7uc226\n"
  }
]