From e2e14e414de25904d791b503d2852c68b3ac9415 Mon Sep 17 00:00:00 2001 From: polwex Date: Wed, 16 Jul 2025 07:55:57 +0700 Subject: m --- .env | 4 + actions/passkey.ts | 8 ++ actions/render-info.tsx | 8 ++ app.json | 5 +- app/(tabs)/login.tsx | 136 ++++++++++++++++++++++++++++ assets/UrbitWalletIcon.png | Bin 0 -> 1053 bytes assets/adaptive-icon.png | Bin 0 -> 17547 bytes assets/clock-icon-active-dark.png | Bin 0 -> 721 bytes assets/clock-icon-active-light.png | Bin 0 -> 707 bytes assets/clock-icon-inactive-dark.png | Bin 0 -> 1016 bytes assets/clock-icon-inactive-light.png | Bin 0 -> 994 bytes assets/eth-logo.png | Bin 0 -> 338608 bytes assets/favicon.png | Bin 0 -> 1466 bytes assets/icon.png | Bin 0 -> 22380 bytes assets/link-logo.png | Bin 0 -> 167995 bytes assets/splash-icon.png | Bin 0 -> 17547 bytes assets/urbit-logo-dark.png | Bin 0 -> 4634 bytes assets/urbit-logo-light.png | Bin 0 -> 4711 bytes assets/usdc-logo.png | Bin 0 -> 221850 bytes assets/wallet-icon-active-dark.png | Bin 0 -> 756 bytes assets/wallet-icon-active-light.png | Bin 0 -> 695 bytes assets/wallet-icon-inactive-dark.png | Bin 0 -> 800 bytes assets/wallet-icon-inactive-light.png | Bin 0 -> 837 bytes bun.lock | 162 +++++++++++++++++++++++++++++++++- components/PrimaryButton.tsx | 102 +++++++++++++++++++++ components/ScreenWrapper.tsx | 31 +++++++ components/auth/Auth.tsx | 149 +++++++++++++++++++++++++++++++ constants/colors.ts | 51 +++++++++++ constants/config.ts | 67 ++++++++++++++ constants/constants.ts | 24 +++++ constants/contracts.ts | 109 +++++++++++++++++++++++ constants/index.ts | 5 ++ constants/routes.ts | 11 +++ lib/passkey.ts | 131 +++++++++++++++++++++++++++ package.json | 4 +- 35 files changed, 1000 insertions(+), 7 deletions(-) create mode 100644 .env create mode 100644 actions/passkey.ts create mode 100644 actions/render-info.tsx create mode 100644 app/(tabs)/login.tsx create mode 100644 assets/UrbitWalletIcon.png create mode 100644 assets/adaptive-icon.png create mode 100644 assets/clock-icon-active-dark.png create mode 100644 assets/clock-icon-active-light.png create mode 100644 assets/clock-icon-inactive-dark.png create mode 100644 assets/clock-icon-inactive-light.png create mode 100644 assets/eth-logo.png create mode 100644 assets/favicon.png create mode 100644 assets/icon.png create mode 100644 assets/link-logo.png create mode 100644 assets/splash-icon.png create mode 100644 assets/urbit-logo-dark.png create mode 100644 assets/urbit-logo-light.png create mode 100644 assets/usdc-logo.png create mode 100644 assets/wallet-icon-active-dark.png create mode 100644 assets/wallet-icon-active-light.png create mode 100644 assets/wallet-icon-inactive-dark.png create mode 100644 assets/wallet-icon-inactive-light.png create mode 100644 components/PrimaryButton.tsx create mode 100644 components/ScreenWrapper.tsx create mode 100644 components/auth/Auth.tsx create mode 100644 constants/colors.ts create mode 100644 constants/config.ts create mode 100644 constants/constants.ts create mode 100644 constants/contracts.ts create mode 100644 constants/index.ts create mode 100644 constants/routes.ts create mode 100644 lib/passkey.ts diff --git a/.env b/.env new file mode 100644 index 0000000..cb41bef --- /dev/null +++ b/.env @@ -0,0 +1,4 @@ +EXPO_PUBLIC_NETWORK="mainnet" +EXPO_PUBLIC_INFURA_API="mainnet" +EXPO_PUBLIC_INFURA_API_SECRET_KEY="mainnet" +EXPO_PUBLIC_ETHERSCAN_API_KEY="mainnet" diff --git a/actions/passkey.ts b/actions/passkey.ts new file mode 100644 index 0000000..1428337 --- /dev/null +++ b/actions/passkey.ts @@ -0,0 +1,8 @@ +"use server"; + +import { Text } from "react-native"; + +export default async function renderInfo({ name }) { + // Securely fetch data from an API, and read environment variables... + return Hello, {name}!; +} diff --git a/actions/render-info.tsx b/actions/render-info.tsx new file mode 100644 index 0000000..1428337 --- /dev/null +++ b/actions/render-info.tsx @@ -0,0 +1,8 @@ +"use server"; + +import { Text } from "react-native"; + +export default async function renderInfo({ name }) { + // Securely fetch data from an API, and read environment variables... + return Hello, {name}!; +} diff --git a/app.json b/app.json index bbbd9fe..b4c63ed 100644 --- a/app.json +++ b/app.json @@ -20,7 +20,7 @@ }, "web": { "bundler": "metro", - "output": "static", + "output": "single", "favicon": "./assets/images/favicon.png" }, "plugins": [ @@ -36,7 +36,8 @@ ] ], "experiments": { - "typedRoutes": true + "typedRoutes": true, + "reactServerFunctions": true } } } diff --git a/app/(tabs)/login.tsx b/app/(tabs)/login.tsx new file mode 100644 index 0000000..d09e613 --- /dev/null +++ b/app/(tabs)/login.tsx @@ -0,0 +1,136 @@ +import React, { useState } from "react"; +import { + View, + Text, + StyleSheet, + Image, + KeyboardAvoidingView, + Platform, + Alert, +} from "react-native"; +import PrimaryButton from "../../components/PrimaryButton"; +import ScreenWrapper from "../../components/ScreenWrapper"; +import { useThemeColors, ColorScheme } from "../../constants"; +import { ROUTES } from "../../constants/routes"; +import { Passkee } from "@/components/auth/Auth"; + +// import { useSettingsStore } from "../store/useSettingsStore"; +// import useAuthStore from "../store/useAuthStore"; +// import { createPasskey, isPasskeySupported } from "../lib/passkey"; +// import { navigationRef } from "../lib/navigationRef"; + +const PasskeySetupScreen = () => { + const [isLoading, setIsLoading] = useState(false); + // const isDarkMode = useSettingsStore((s) => s.isDarkMode); + const isDarkMode = false; + const colors = useThemeColors(); + const styles = getStyles(colors); + // const { setHasPasskey, setHasSeenPasskeyPrompt } = useAuthStore(); + + const logoSource = isDarkMode + ? require("../../assets/urbit-logo-dark.png") + : require("../../assets/urbit-logo-light.png"); + + const handleCreatePasskey = async () => { + console.log("creaing psskey"); + setIsLoading(true); + + try { + // const res = await startRegistration({}) + } catch (error) { + console.error("Passkey creation error:", error); + Alert.alert("Error", "An error occurred while creating the passkey."); + } finally { + setIsLoading(false); + } + }; + + const handleSkip = () => { + // setHasSeenPasskeyPrompt(true); + // navigationRef.current?.navigate(ROUTES.LOGIN as never); + }; + + return ( + + + + + Secure Your Wallet + + Create a passkey for easy and secure access to your Urbit wallet + + + + + + + + + You can always set up a passkey later in settings + + + + + ); +}; + +export const getStyles = (colors: ColorScheme) => + StyleSheet.create({ + container: { + flex: 1, + backgroundColor: colors.background, + justifyContent: "space-between", + padding: 20, + }, + topSection: { + flex: 1, + justifyContent: "center", + alignItems: "center", + }, + walletIcon: { + width: 64, + height: 64, + marginBottom: 24, + }, + title: { + fontSize: 24, + color: colors.text, + fontWeight: "600", + marginBottom: 12, + textAlign: "center", + }, + subtitle: { + fontSize: 16, + color: colors.secondary, + textAlign: "center", + paddingHorizontal: 20, + lineHeight: 24, + }, + bottomSection: { + marginBottom: 40, + }, + infoText: { + color: colors.secondary, + fontSize: 14, + textAlign: "center", + marginTop: 16, + }, + }); + +export default PasskeySetupScreen; diff --git a/assets/UrbitWalletIcon.png b/assets/UrbitWalletIcon.png new file mode 100644 index 0000000..1f34694 Binary files /dev/null and b/assets/UrbitWalletIcon.png differ diff --git a/assets/adaptive-icon.png b/assets/adaptive-icon.png new file mode 100644 index 0000000..03d6f6b Binary files /dev/null and b/assets/adaptive-icon.png differ diff --git a/assets/clock-icon-active-dark.png b/assets/clock-icon-active-dark.png new file mode 100644 index 0000000..c9de50c Binary files /dev/null and b/assets/clock-icon-active-dark.png differ diff --git a/assets/clock-icon-active-light.png b/assets/clock-icon-active-light.png new file mode 100644 index 0000000..c8b7230 Binary files /dev/null and b/assets/clock-icon-active-light.png differ diff --git a/assets/clock-icon-inactive-dark.png b/assets/clock-icon-inactive-dark.png new file mode 100644 index 0000000..4f00950 Binary files /dev/null and b/assets/clock-icon-inactive-dark.png differ diff --git a/assets/clock-icon-inactive-light.png b/assets/clock-icon-inactive-light.png new file mode 100644 index 0000000..6407c4a Binary files /dev/null and b/assets/clock-icon-inactive-light.png differ diff --git a/assets/eth-logo.png b/assets/eth-logo.png new file mode 100644 index 0000000..9ba012c Binary files /dev/null and b/assets/eth-logo.png differ diff --git a/assets/favicon.png b/assets/favicon.png new file mode 100644 index 0000000..e75f697 Binary files /dev/null and b/assets/favicon.png differ diff --git a/assets/icon.png b/assets/icon.png new file mode 100644 index 0000000..a0b1526 Binary files /dev/null and b/assets/icon.png differ diff --git a/assets/link-logo.png b/assets/link-logo.png new file mode 100644 index 0000000..ac1dea7 Binary files /dev/null and b/assets/link-logo.png differ diff --git a/assets/splash-icon.png b/assets/splash-icon.png new file mode 100644 index 0000000..03d6f6b Binary files /dev/null and b/assets/splash-icon.png differ diff --git a/assets/urbit-logo-dark.png b/assets/urbit-logo-dark.png new file mode 100644 index 0000000..8f198ae Binary files /dev/null and b/assets/urbit-logo-dark.png differ diff --git a/assets/urbit-logo-light.png b/assets/urbit-logo-light.png new file mode 100644 index 0000000..771aab9 Binary files /dev/null and b/assets/urbit-logo-light.png differ diff --git a/assets/usdc-logo.png b/assets/usdc-logo.png new file mode 100644 index 0000000..36a9f90 Binary files /dev/null and b/assets/usdc-logo.png differ diff --git a/assets/wallet-icon-active-dark.png b/assets/wallet-icon-active-dark.png new file mode 100644 index 0000000..dbda9a6 Binary files /dev/null and b/assets/wallet-icon-active-dark.png differ diff --git a/assets/wallet-icon-active-light.png b/assets/wallet-icon-active-light.png new file mode 100644 index 0000000..dcef651 Binary files /dev/null and b/assets/wallet-icon-active-light.png differ diff --git a/assets/wallet-icon-inactive-dark.png b/assets/wallet-icon-inactive-dark.png new file mode 100644 index 0000000..4baba74 Binary files /dev/null and b/assets/wallet-icon-inactive-dark.png differ diff --git a/assets/wallet-icon-inactive-light.png b/assets/wallet-icon-inactive-light.png new file mode 100644 index 0000000..8523a39 Binary files /dev/null and b/assets/wallet-icon-inactive-light.png differ diff --git a/bun.lock b/bun.lock index b984a45..b2dd270 100644 --- a/bun.lock +++ b/bun.lock @@ -8,6 +8,7 @@ "@react-navigation/bottom-tabs": "^7.3.10", "@react-navigation/elements": "^2.3.8", "@react-navigation/native": "^7.1.6", + "ethers": "^6.15.0", "expo": "~53.0.17", "expo-blur": "~14.1.5", "expo-constants": "~17.1.7", @@ -30,6 +31,7 @@ "react-native-screens": "~4.11.1", "react-native-web": "~0.20.0", "react-native-webview": "13.13.5", + "react-server-dom-webpack": "^19.1.0", }, "devDependencies": { "@babel/core": "^7.25.2", @@ -43,6 +45,8 @@ "packages": { "@0no-co/graphql.web": ["@0no-co/graphql.web@1.1.2", "", { "peerDependencies": { "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0" }, "optionalPeers": ["graphql"] }, "sha512-N2NGsU5FLBhT8NZ+3l2YrzZSHITjNXNuDhC4iDiikv0IujaJ0Xc6xIxQZ/Ek3Cb+rgPjnLHYyJm11tInuJn+cw=="], + "@adraffy/ens-normalize": ["@adraffy/ens-normalize@1.10.1", "", {}, "sha512-96Z2IP3mYmF1Xg2cDm8f1gWGf/HUVedQ3FMifV4kG/PQ4yEP51xDtRAEfhVNt5f/uzpNkZHwWQuUcu6D6K+Ekw=="], + "@ampproject/remapping": ["@ampproject/remapping@2.3.0", "", { "dependencies": { "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.24" } }, "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw=="], "@babel/code-frame": ["@babel/code-frame@7.27.1", "", { "dependencies": { "@babel/helper-validator-identifier": "^7.27.1", "js-tokens": "^4.0.0", "picocolors": "^1.1.1" } }, "sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg=="], @@ -345,6 +349,10 @@ "@napi-rs/wasm-runtime": ["@napi-rs/wasm-runtime@0.2.12", "", { "dependencies": { "@emnapi/core": "^1.4.3", "@emnapi/runtime": "^1.4.3", "@tybys/wasm-util": "^0.10.0" } }, "sha512-ZVWUcfwY4E/yPitQJl481FjFo3K22D6qF0DuFH6Y/nbnE11GY5uguDxZMGXPQ8WQ0128MXQD7TnfHyK4oWoIJQ=="], + "@noble/curves": ["@noble/curves@1.2.0", "", { "dependencies": { "@noble/hashes": "1.3.2" } }, "sha512-oYclrNgRaM9SsBUBVbb8M6DTV7ZHRTKugureoYEncY5c65HOmRzvSiTE3y5CYaPYJA/GVkrhXEoF0M3Ya9PMnw=="], + + "@noble/hashes": ["@noble/hashes@1.3.2", "", {}, "sha512-MVC8EAQp7MvEcm30KWENFjgR+Mkmf+D189XJTkFIlwohU5hcBbn1ZkKq7KVTi2Hme3PMGF390DaL52beVrIihQ=="], + "@nodelib/fs.scandir": ["@nodelib/fs.scandir@2.1.5", "", { "dependencies": { "@nodelib/fs.stat": "2.0.5", "run-parallel": "^1.1.9" } }, "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g=="], "@nodelib/fs.stat": ["@nodelib/fs.stat@2.0.5", "", {}, "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A=="], @@ -411,6 +419,10 @@ "@types/babel__traverse": ["@types/babel__traverse@7.20.7", "", { "dependencies": { "@babel/types": "^7.20.7" } }, "sha512-dkO5fhS7+/oos4ciWxyEyjWe48zmG6wbCheo/G2ZnHx4fs3EU6YC6UM8rk56gAjNJ9P3MTH2jo5jb92/K6wbng=="], + "@types/eslint": ["@types/eslint@9.6.1", "", { "dependencies": { "@types/estree": "*", "@types/json-schema": "*" } }, "sha512-FXx2pKgId/WyYo2jXw63kk7/+TY7u7AziEJxJAnSFzHlqTAS3Ync6SvgYAN/k4/PQpnnVuzoMuVnByKK2qp0ag=="], + + "@types/eslint-scope": ["@types/eslint-scope@3.7.7", "", { "dependencies": { "@types/eslint": "*", "@types/estree": "*" } }, "sha512-MzMFlSLBqNF2gcHWO0G1vP/YQyfvrxZ0bF+u7mzUdZ1/xK4A4sru+nraZz5i3iEIk1l1uyicaDVTB4QbbEkAYg=="], + "@types/estree": ["@types/estree@1.0.8", "", {}, "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w=="], "@types/graceful-fs": ["@types/graceful-fs@4.1.9", "", { "dependencies": { "@types/node": "*" } }, "sha512-olP3sd1qOEe5dXTSaFvQG+02VdRXcdytWLAZsAq1PecU8uqQAhkrnbli7DagjtXKW/Bl7YJbUsa8MPcuc8LHEQ=="], @@ -427,7 +439,7 @@ "@types/json5": ["@types/json5@0.0.29", "", {}, "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ=="], - "@types/node": ["@types/node@24.0.14", "", { "dependencies": { "undici-types": "~7.8.0" } }, "sha512-4zXMWD91vBLGRtHK3YbIoFMia+1nqEz72coM42C5ETjnNCa/heoj7NT1G67iAfOqMmcfhuCZ4uNpyz8EjlAejw=="], + "@types/node": ["@types/node@22.7.5", "", { "dependencies": { "undici-types": "~6.19.2" } }, "sha512-jML7s2NAzMWc//QSJ1a3prpk78cOPchGvXJsC3C6R6PSMoooztvRVQEz89gmBTBY1SPMaqo5teB4uNHPdetShQ=="], "@types/react": ["@types/react@19.0.14", "", { "dependencies": { "csstype": "^3.0.2" } }, "sha512-ixLZ7zG7j1fM0DijL9hDArwhwcCb4vqmePgwtV0GfnkHRSCUEv4LvzarcTdhoqgyMznUx/EhoTUv31CKZzkQlw=="], @@ -499,16 +511,56 @@ "@urql/exchange-retry": ["@urql/exchange-retry@1.3.2", "", { "dependencies": { "@urql/core": "^5.1.2", "wonka": "^6.3.2" } }, "sha512-TQMCz2pFJMfpNxmSfX1VSfTjwUIFx/mL+p1bnfM1xjjdla7Z+KnGMW/EhFbpckp3LyWAH4PgOsMwOMnIN+MBFg=="], + "@webassemblyjs/ast": ["@webassemblyjs/ast@1.14.1", "", { "dependencies": { "@webassemblyjs/helper-numbers": "1.13.2", "@webassemblyjs/helper-wasm-bytecode": "1.13.2" } }, "sha512-nuBEDgQfm1ccRp/8bCQrx1frohyufl4JlbMMZ4P1wpeOfDhF6FQkxZJ1b/e+PLwr6X1Nhw6OLme5usuBWYBvuQ=="], + + "@webassemblyjs/floating-point-hex-parser": ["@webassemblyjs/floating-point-hex-parser@1.13.2", "", {}, "sha512-6oXyTOzbKxGH4steLbLNOu71Oj+C8Lg34n6CqRvqfS2O71BxY6ByfMDRhBytzknj9yGUPVJ1qIKhRlAwO1AovA=="], + + "@webassemblyjs/helper-api-error": ["@webassemblyjs/helper-api-error@1.13.2", "", {}, "sha512-U56GMYxy4ZQCbDZd6JuvvNV/WFildOjsaWD3Tzzvmw/mas3cXzRJPMjP83JqEsgSbyrmaGjBfDtV7KDXV9UzFQ=="], + + "@webassemblyjs/helper-buffer": ["@webassemblyjs/helper-buffer@1.14.1", "", {}, "sha512-jyH7wtcHiKssDtFPRB+iQdxlDf96m0E39yb0k5uJVhFGleZFoNw1c4aeIcVUPPbXUVJ94wwnMOAqUHyzoEPVMA=="], + + "@webassemblyjs/helper-numbers": ["@webassemblyjs/helper-numbers@1.13.2", "", { "dependencies": { "@webassemblyjs/floating-point-hex-parser": "1.13.2", "@webassemblyjs/helper-api-error": "1.13.2", "@xtuc/long": "4.2.2" } }, "sha512-FE8aCmS5Q6eQYcV3gI35O4J789wlQA+7JrqTTpJqn5emA4U2hvwJmvFRC0HODS+3Ye6WioDklgd6scJ3+PLnEA=="], + + "@webassemblyjs/helper-wasm-bytecode": ["@webassemblyjs/helper-wasm-bytecode@1.13.2", "", {}, "sha512-3QbLKy93F0EAIXLh0ogEVR6rOubA9AoZ+WRYhNbFyuB70j3dRdwH9g+qXhLAO0kiYGlg3TxDV+I4rQTr/YNXkA=="], + + "@webassemblyjs/helper-wasm-section": ["@webassemblyjs/helper-wasm-section@1.14.1", "", { "dependencies": { "@webassemblyjs/ast": "1.14.1", "@webassemblyjs/helper-buffer": "1.14.1", "@webassemblyjs/helper-wasm-bytecode": "1.13.2", "@webassemblyjs/wasm-gen": "1.14.1" } }, "sha512-ds5mXEqTJ6oxRoqjhWDU83OgzAYjwsCV8Lo/N+oRsNDmx/ZDpqalmrtgOMkHwxsG0iI//3BwWAErYRHtgn0dZw=="], + + "@webassemblyjs/ieee754": ["@webassemblyjs/ieee754@1.13.2", "", { "dependencies": { "@xtuc/ieee754": "^1.2.0" } }, "sha512-4LtOzh58S/5lX4ITKxnAK2USuNEvpdVV9AlgGQb8rJDHaLeHciwG4zlGr0j/SNWlr7x3vO1lDEsuePvtcDNCkw=="], + + "@webassemblyjs/leb128": ["@webassemblyjs/leb128@1.13.2", "", { "dependencies": { "@xtuc/long": "4.2.2" } }, "sha512-Lde1oNoIdzVzdkNEAWZ1dZ5orIbff80YPdHx20mrHwHrVNNTjNr8E3xz9BdpcGqRQbAEa+fkrCb+fRFTl/6sQw=="], + + "@webassemblyjs/utf8": ["@webassemblyjs/utf8@1.13.2", "", {}, "sha512-3NQWGjKTASY1xV5m7Hr0iPeXD9+RDobLll3T9d2AO+g3my8xy5peVyjSag4I50mR1bBSN/Ct12lo+R9tJk0NZQ=="], + + "@webassemblyjs/wasm-edit": ["@webassemblyjs/wasm-edit@1.14.1", "", { "dependencies": { "@webassemblyjs/ast": "1.14.1", "@webassemblyjs/helper-buffer": "1.14.1", "@webassemblyjs/helper-wasm-bytecode": "1.13.2", "@webassemblyjs/helper-wasm-section": "1.14.1", "@webassemblyjs/wasm-gen": "1.14.1", "@webassemblyjs/wasm-opt": "1.14.1", "@webassemblyjs/wasm-parser": "1.14.1", "@webassemblyjs/wast-printer": "1.14.1" } }, "sha512-RNJUIQH/J8iA/1NzlE4N7KtyZNHi3w7at7hDjvRNm5rcUXa00z1vRz3glZoULfJ5mpvYhLybmVcwcjGrC1pRrQ=="], + + "@webassemblyjs/wasm-gen": ["@webassemblyjs/wasm-gen@1.14.1", "", { "dependencies": { "@webassemblyjs/ast": "1.14.1", "@webassemblyjs/helper-wasm-bytecode": "1.13.2", "@webassemblyjs/ieee754": "1.13.2", "@webassemblyjs/leb128": "1.13.2", "@webassemblyjs/utf8": "1.13.2" } }, "sha512-AmomSIjP8ZbfGQhumkNvgC33AY7qtMCXnN6bL2u2Js4gVCg8fp735aEiMSBbDR7UQIj90n4wKAFUSEd0QN2Ukg=="], + + "@webassemblyjs/wasm-opt": ["@webassemblyjs/wasm-opt@1.14.1", "", { "dependencies": { "@webassemblyjs/ast": "1.14.1", "@webassemblyjs/helper-buffer": "1.14.1", "@webassemblyjs/wasm-gen": "1.14.1", "@webassemblyjs/wasm-parser": "1.14.1" } }, "sha512-PTcKLUNvBqnY2U6E5bdOQcSM+oVP/PmrDY9NzowJjislEjwP/C4an2303MCVS2Mg9d3AJpIGdUFIQQWbPds0Sw=="], + + "@webassemblyjs/wasm-parser": ["@webassemblyjs/wasm-parser@1.14.1", "", { "dependencies": { "@webassemblyjs/ast": "1.14.1", "@webassemblyjs/helper-api-error": "1.13.2", "@webassemblyjs/helper-wasm-bytecode": "1.13.2", "@webassemblyjs/ieee754": "1.13.2", "@webassemblyjs/leb128": "1.13.2", "@webassemblyjs/utf8": "1.13.2" } }, "sha512-JLBl+KZ0R5qB7mCnud/yyX08jWFw5MsoalJ1pQ4EdFlgj9VdXKGuENGsiCIjegI1W7p91rUlcB/LB5yRJKNTcQ=="], + + "@webassemblyjs/wast-printer": ["@webassemblyjs/wast-printer@1.14.1", "", { "dependencies": { "@webassemblyjs/ast": "1.14.1", "@xtuc/long": "4.2.2" } }, "sha512-kPSSXE6De1XOR820C90RIo2ogvZG+c3KiHzqUoO/F34Y2shGzesfqv7o57xrxovZJH/MetF5UjroJ/R/3isoiw=="], + "@xmldom/xmldom": ["@xmldom/xmldom@0.8.10", "", {}, "sha512-2WALfTl4xo2SkGCYRt6rDTFfk9R1czmBvUQy12gK2KuRKIpWEhcbbzy8EZXtz/jkRqHX8bFEc6FC1HjX4TUWYw=="], + "@xtuc/ieee754": ["@xtuc/ieee754@1.2.0", "", {}, "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA=="], + + "@xtuc/long": ["@xtuc/long@4.2.2", "", {}, "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ=="], + "abort-controller": ["abort-controller@3.0.0", "", { "dependencies": { "event-target-shim": "^5.0.0" } }, "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg=="], "accepts": ["accepts@1.3.8", "", { "dependencies": { "mime-types": "~2.1.34", "negotiator": "0.6.3" } }, "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw=="], "acorn": ["acorn@8.15.0", "", { "bin": { "acorn": "bin/acorn" } }, "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg=="], + "acorn-import-phases": ["acorn-import-phases@1.0.4", "", { "peerDependencies": { "acorn": "^8.14.0" } }, "sha512-wKmbr/DDiIXzEOiWrTTUcDm24kQ2vGfZQvM2fwg2vXqR5uW6aapr7ObPtj1th32b9u90/Pf4AItvdTh42fBmVQ=="], + "acorn-jsx": ["acorn-jsx@5.3.2", "", { "peerDependencies": { "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" } }, "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ=="], + "acorn-loose": ["acorn-loose@8.5.2", "", { "dependencies": { "acorn": "^8.15.0" } }, "sha512-PPvV6g8UGMGgjrMu+n/f9E/tCSkNQ2Y97eFvuVdJfG11+xdIeDcLyNdC8SHcrHbRqkfwLASdplyR6B6sKM1U4A=="], + + "aes-js": ["aes-js@4.0.0-beta.5", "", {}, "sha512-G965FqalsNyrPqgEGON7nIx1e/OVENSgiEIzyC63haUMuvNnwIgIjMs52hlTCKhkBny7A2ORNlfY9Zu+jmGk1Q=="], + "agent-base": ["agent-base@7.1.4", "", {}, "sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ=="], "ajv": ["ajv@6.12.6", "", { "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", "json-schema-traverse": "^0.4.1", "uri-js": "^4.2.2" } }, "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g=="], @@ -629,6 +681,8 @@ "chrome-launcher": ["chrome-launcher@0.15.2", "", { "dependencies": { "@types/node": "*", "escape-string-regexp": "^4.0.0", "is-wsl": "^2.2.0", "lighthouse-logger": "^1.0.0" }, "bin": { "print-chrome-path": "bin/print-chrome-path.js" } }, "sha512-zdLEwNo3aUVzIhKhTtXfxhdvZhUghrnmkvcAq2NoDd+LeOHKf03H5jwZ8T/STsAlzyALkBVK552iaG1fGf1xVQ=="], + "chrome-trace-event": ["chrome-trace-event@1.0.4", "", {}, "sha512-rNjApaLzuwaOTjCiT8lSDdGN1APCiqkChLMJxJPWLunPAt5fy8xgU9/jNOchV84wfIxrA0lRQB7oCT8jrn/wrQ=="], + "chromium-edge-launcher": ["chromium-edge-launcher@0.2.0", "", { "dependencies": { "@types/node": "*", "escape-string-regexp": "^4.0.0", "is-wsl": "^2.2.0", "lighthouse-logger": "^1.0.0", "mkdirp": "^1.0.4", "rimraf": "^3.0.2" } }, "sha512-JfJjUnq25y9yg4FABRRVPmBGWPZZi+AQXT4mxupb67766/0UlhG8PAZCz6xzEMXTbW3CsSoE8PcCWA49n35mKg=="], "ci-info": ["ci-info@3.9.0", "", {}, "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ=="], @@ -725,6 +779,8 @@ "encodeurl": ["encodeurl@2.0.0", "", {}, "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg=="], + "enhanced-resolve": ["enhanced-resolve@5.18.2", "", { "dependencies": { "graceful-fs": "^4.2.4", "tapable": "^2.2.0" } }, "sha512-6Jw4sE1maoRJo3q8MsSIn2onJFbLTOjY9hlx4DZXmOKvLRd1Ok2kXmAGXaafL2+ijsJZ1ClYbl/pmqr9+k4iUQ=="], + "env-editor": ["env-editor@0.4.2", "", {}, "sha512-ObFo8v4rQJAE59M69QzwloxPZtd33TpYEIjtKD1rrFDcM1Gd7IkDxEBU+HriziN6HSHQnBJi8Dmy+JWkav5HKA=="], "error-ex": ["error-ex@1.3.2", "", { "dependencies": { "is-arrayish": "^0.2.1" } }, "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g=="], @@ -739,6 +795,8 @@ "es-iterator-helpers": ["es-iterator-helpers@1.2.1", "", { "dependencies": { "call-bind": "^1.0.8", "call-bound": "^1.0.3", "define-properties": "^1.2.1", "es-abstract": "^1.23.6", "es-errors": "^1.3.0", "es-set-tostringtag": "^2.0.3", "function-bind": "^1.1.2", "get-intrinsic": "^1.2.6", "globalthis": "^1.0.4", "gopd": "^1.2.0", "has-property-descriptors": "^1.0.2", "has-proto": "^1.2.0", "has-symbols": "^1.1.0", "internal-slot": "^1.1.0", "iterator.prototype": "^1.1.4", "safe-array-concat": "^1.1.3" } }, "sha512-uDn+FE1yrDzyC0pCo961B2IHbdM8y/ACZsKD4dG6WqrjV53BADjwa7D+1aom2rsNVfLyDgU/eigvlJGJ08OQ4w=="], + "es-module-lexer": ["es-module-lexer@1.7.0", "", {}, "sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA=="], + "es-object-atoms": ["es-object-atoms@1.1.1", "", { "dependencies": { "es-errors": "^1.3.0" } }, "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA=="], "es-set-tostringtag": ["es-set-tostringtag@2.1.0", "", { "dependencies": { "es-errors": "^1.3.0", "get-intrinsic": "^1.2.6", "has-tostringtag": "^1.0.2", "hasown": "^2.0.2" } }, "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA=="], @@ -789,8 +847,12 @@ "etag": ["etag@1.8.1", "", {}, "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg=="], + "ethers": ["ethers@6.15.0", "", { "dependencies": { "@adraffy/ens-normalize": "1.10.1", "@noble/curves": "1.2.0", "@noble/hashes": "1.3.2", "@types/node": "22.7.5", "aes-js": "4.0.0-beta.5", "tslib": "2.7.0", "ws": "8.17.1" } }, "sha512-Kf/3ZW54L4UT0pZtsY/rf+EkBU7Qi5nnhonjUb8yTXcxH3cdcWrV2cRyk0Xk/4jK6OoHhxxZHriyhje20If2hQ=="], + "event-target-shim": ["event-target-shim@5.0.1", "", {}, "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ=="], + "events": ["events@3.3.0", "", {}, "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q=="], + "exec-async": ["exec-async@2.2.0", "", {}, "sha512-87OpwcEiMia/DeiKFzaQNBNFeN3XkkpYIh9FyOqq5mS2oKv3CBE67PXoEKcr6nodWdXNogTiQ0jE2NGuoffXPw=="], "expo": ["expo@53.0.19", "", { "dependencies": { "@babel/runtime": "^7.20.0", "@expo/cli": "0.24.20", "@expo/config": "~11.0.13", "@expo/config-plugins": "~10.1.2", "@expo/fingerprint": "0.13.4", "@expo/metro-config": "0.20.17", "@expo/vector-icons": "^14.0.0", "babel-preset-expo": "~13.2.3", "expo-asset": "~11.1.7", "expo-constants": "~17.1.7", "expo-file-system": "~18.1.11", "expo-font": "~13.3.2", "expo-keep-awake": "~14.1.4", "expo-modules-autolinking": "2.1.14", "expo-modules-core": "2.4.2", "react-native-edge-to-edge": "1.6.0", "whatwg-url-without-unicode": "8.0.0-3" }, "peerDependencies": { "@expo/dom-webview": "*", "@expo/metro-runtime": "*", "react": "*", "react-native": "*", "react-native-webview": "*" }, "optionalPeers": ["@expo/dom-webview", "@expo/metro-runtime", "react-native-webview"], "bin": { "expo": "bin/cli", "fingerprint": "bin/fingerprint", "expo-modules-autolinking": "bin/autolinking" } }, "sha512-hZWEKw6h5dlfKy6+c3f2exx5x3Loio8p0b2s/Pk1eQfTffqpkQRVVlOzcTWU1RSuMfc47ZMpr97pUJWQczOGsQ=="], @@ -907,6 +969,8 @@ "glob-parent": ["glob-parent@6.0.2", "", { "dependencies": { "is-glob": "^4.0.3" } }, "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A=="], + "glob-to-regexp": ["glob-to-regexp@0.4.1", "", {}, "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw=="], + "globals": ["globals@16.3.0", "", {}, "sha512-bqWEnJ1Nt3neqx2q5SFfGS8r/ahumIakg3HcwtNlrVlwXIeNumWn/c7Pn/wKzGhf6SaW6H6uWXLqC30STCMchQ=="], "globalthis": ["globalthis@1.0.4", "", { "dependencies": { "define-properties": "^1.2.1", "gopd": "^1.0.1" } }, "sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ=="], @@ -1073,6 +1137,8 @@ "json-parse-better-errors": ["json-parse-better-errors@1.0.2", "", {}, "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw=="], + "json-parse-even-better-errors": ["json-parse-even-better-errors@2.3.1", "", {}, "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w=="], + "json-schema-traverse": ["json-schema-traverse@0.4.1", "", {}, "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg=="], "json-stable-stringify-without-jsonify": ["json-stable-stringify-without-jsonify@1.0.1", "", {}, "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw=="], @@ -1117,6 +1183,8 @@ "lines-and-columns": ["lines-and-columns@1.2.4", "", {}, "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg=="], + "loader-runner": ["loader-runner@4.3.0", "", {}, "sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg=="], + "locate-path": ["locate-path@6.0.0", "", { "dependencies": { "p-locate": "^5.0.0" } }, "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw=="], "lodash.debounce": ["lodash.debounce@4.0.8", "", {}, "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow=="], @@ -1203,6 +1271,8 @@ "negotiator": ["negotiator@0.6.3", "", {}, "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg=="], + "neo-async": ["neo-async@2.6.2", "", {}, "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw=="], + "nested-error-stacks": ["nested-error-stacks@2.0.1", "", {}, "sha512-SrQrok4CATudVzBS7coSz26QRSmlK9TzzoFbeKfcPBUFPjcQM9Rqvr/DlJkOrwI/0KcgvMub1n1g5Jt9EgRn4A=="], "node-fetch": ["node-fetch@2.7.0", "", { "dependencies": { "whatwg-url": "^5.0.0" }, "peerDependencies": { "encoding": "^0.1.0" }, "optionalPeers": ["encoding"] }, "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A=="], @@ -1321,6 +1391,8 @@ "queue-microtask": ["queue-microtask@1.2.3", "", {}, "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A=="], + "randombytes": ["randombytes@2.1.0", "", { "dependencies": { "safe-buffer": "^5.1.0" } }, "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ=="], + "range-parser": ["range-parser@1.2.1", "", {}, "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg=="], "rc": ["rc@1.2.8", "", { "dependencies": { "deep-extend": "^0.6.0", "ini": "~1.3.0", "minimist": "^1.2.0", "strip-json-comments": "~2.0.1" }, "bin": { "rc": "./cli.js" } }, "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw=="], @@ -1357,6 +1429,8 @@ "react-refresh": ["react-refresh@0.14.2", "", {}, "sha512-jCvmsr+1IUSMUyzOkRcvnVbX3ZYC6g9TDrDbFuFmRDq7PD4yaGbLKNQL6k2jnArV8hjYxh7hVhAZB6s9HDGpZA=="], + "react-server-dom-webpack": ["react-server-dom-webpack@19.1.0", "", { "dependencies": { "acorn-loose": "^8.3.0", "neo-async": "^2.6.1", "webpack-sources": "^3.2.0" }, "peerDependencies": { "react": "^19.1.0", "react-dom": "^19.1.0", "webpack": "^5.59.0" } }, "sha512-GUbawkNSN0oj8GnuNhMzsvyIHpXqqpAmyOY5NRqNNQ/M8wvUUN8YBoGjDUj9lbmBrmAHS65BByp6325CcWA0eg=="], + "reflect.getprototypeof": ["reflect.getprototypeof@1.0.10", "", { "dependencies": { "call-bind": "^1.0.8", "define-properties": "^1.2.1", "es-abstract": "^1.23.9", "es-errors": "^1.3.0", "es-object-atoms": "^1.0.0", "get-intrinsic": "^1.2.7", "get-proto": "^1.0.1", "which-builtin-type": "^1.2.1" } }, "sha512-00o4I+DVrefhv+nX0ulyi3biSHCPDe+yLv5o/p6d/UVlirijB8E16FtfwSAi4g3tcqrQ4lRAqQSoFEZJehYEcw=="], "regenerate": ["regenerate@1.4.2", "", {}, "sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A=="], @@ -1417,6 +1491,8 @@ "serialize-error": ["serialize-error@2.1.0", "", {}, "sha512-ghgmKt5o4Tly5yEG/UJp8qTd0AN7Xalw4XBtDEKP655B699qMEtra1WlXeE6WIvdEG481JvRxULKsInq/iNysw=="], + "serialize-javascript": ["serialize-javascript@6.0.2", "", { "dependencies": { "randombytes": "^2.1.0" } }, "sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g=="], + "serve-static": ["serve-static@1.16.2", "", { "dependencies": { "encodeurl": "~2.0.0", "escape-html": "~1.0.3", "parseurl": "~1.3.3", "send": "0.19.0" } }, "sha512-VqpjJZKadQB/PEbEwvFdO43Ax5dFBZ2UECszz8bQ7pi7wt//PWe1P6MN7eCnjsatYtBT6EuiClbjSWP2WrIoTw=="], "server-only": ["server-only@0.0.1", "", {}, "sha512-qepMx2JxAa5jjfzxG79yPPq+8BuFToHd1hm7kI+Z4zAq1ftQiP7HcxMhDDItrbtwVeLg/cY2JnKnrcFkmiswNA=="], @@ -1521,6 +1597,8 @@ "supports-preserve-symlinks-flag": ["supports-preserve-symlinks-flag@1.0.0", "", {}, "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w=="], + "tapable": ["tapable@2.2.2", "", {}, "sha512-Re10+NauLTMCudc7T5WLFLAwDhQ0JWdrMK+9B2M8zR5hRExKmsRDCBA7/aV/pNJFltmBFO5BAMlQFi/vq3nKOg=="], + "tar": ["tar@7.4.3", "", { "dependencies": { "@isaacs/fs-minipass": "^4.0.0", "chownr": "^3.0.0", "minipass": "^7.1.2", "minizlib": "^3.0.1", "mkdirp": "^3.0.1", "yallist": "^5.0.0" } }, "sha512-5S7Va8hKfV7W5U6g3aYxXmlPoZVAwUMy9AOKyF2fVuZa2UD3qZjg578OrLRt8PcNN1PleVaL/5/yYATNL0ICUw=="], "temp-dir": ["temp-dir@2.0.0", "", {}, "sha512-aoBAniQmmwtcKp/7BzsH8Cxzv8OL736p7v1ihGb5e9DJ9kTwGWHrQrVB5+lfVDzfGrdRzXch+ig7LHaY1JTOrg=="], @@ -1529,6 +1607,8 @@ "terser": ["terser@5.43.1", "", { "dependencies": { "@jridgewell/source-map": "^0.3.3", "acorn": "^8.14.0", "commander": "^2.20.0", "source-map-support": "~0.5.20" }, "bin": { "terser": "bin/terser" } }, "sha512-+6erLbBm0+LROX2sPXlUYx/ux5PyE9K/a92Wrt6oA+WDAoFTdpHE5tCYCI5PNzq2y8df4rA+QgHLJuR4jNymsg=="], + "terser-webpack-plugin": ["terser-webpack-plugin@5.3.14", "", { "dependencies": { "@jridgewell/trace-mapping": "^0.3.25", "jest-worker": "^27.4.5", "schema-utils": "^4.3.0", "serialize-javascript": "^6.0.2", "terser": "^5.31.1" }, "peerDependencies": { "webpack": "^5.1.0" } }, "sha512-vkZjpUjb6OMS7dhV+tILUW6BhpDR7P2L/aQSAv+Uwk+m8KATX9EccViHTJR2qDtACKPIYndLGCyl3FMo+r2LMw=="], + "test-exclude": ["test-exclude@6.0.0", "", { "dependencies": { "@istanbuljs/schema": "^0.1.2", "glob": "^7.1.4", "minimatch": "^3.0.4" } }, "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w=="], "thenify": ["thenify@3.3.1", "", { "dependencies": { "any-promise": "^1.0.0" } }, "sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw=="], @@ -1553,7 +1633,7 @@ "tsconfig-paths": ["tsconfig-paths@3.15.0", "", { "dependencies": { "@types/json5": "^0.0.29", "json5": "^1.0.2", "minimist": "^1.2.6", "strip-bom": "^3.0.0" } }, "sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg=="], - "tslib": ["tslib@2.8.1", "", {}, "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="], + "tslib": ["tslib@2.7.0", "", {}, "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA=="], "type-check": ["type-check@0.4.0", "", { "dependencies": { "prelude-ls": "^1.2.1" } }, "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew=="], @@ -1577,7 +1657,7 @@ "undici": ["undici@6.21.3", "", {}, "sha512-gBLkYIlEnSp8pFbT64yFgGE6UIB9tAkhukC23PmMDCe5Nd+cRqKxSjw5y54MK2AZMgZfJWMaNE4nYUHgi1XEOw=="], - "undici-types": ["undici-types@7.8.0", "", {}, "sha512-9UJ2xGDvQ43tYyVMpuHlsgApydB8ZKfVYTsLDhXkFL/6gfkp+U8xTGdh8pMJv1SpZna0zxG1DwsKZsreLbXBxw=="], + "undici-types": ["undici-types@6.19.8", "", {}, "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw=="], "unicode-canonical-property-names-ecmascript": ["unicode-canonical-property-names-ecmascript@2.0.1", "", {}, "sha512-dA8WbNeb2a6oQzAQ55YlT5vQAWGV9WXOsi3SskE3bcCdM0P4SDd+24zS/OCacdRq5BkdsRj9q3Pg6YyQoxIGqg=="], @@ -1615,10 +1695,16 @@ "warn-once": ["warn-once@0.1.1", "", {}, "sha512-VkQZJbO8zVImzYFteBXvBOZEl1qL175WH8VmZcxF2fZAoudNhNDvHi+doCaAEdU2l2vtcIwa2zn0QK5+I1HQ3Q=="], + "watchpack": ["watchpack@2.4.4", "", { "dependencies": { "glob-to-regexp": "^0.4.1", "graceful-fs": "^4.1.2" } }, "sha512-c5EGNOiyxxV5qmTtAB7rbiXxi1ooX1pQKMLX/MIabJjRA0SJBQOjKF+KSVfHkr9U1cADPon0mRiVe/riyaiDUA=="], + "wcwidth": ["wcwidth@1.0.1", "", { "dependencies": { "defaults": "^1.0.3" } }, "sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg=="], "webidl-conversions": ["webidl-conversions@5.0.0", "", {}, "sha512-VlZwKPCkYKxQgeSbH5EyngOmRp7Ww7I9rQLERETtf5ofd9pGeswWiOtogpEO850jziPRarreGxn5QIiTqpb2wA=="], + "webpack": ["webpack@5.100.2", "", { "dependencies": { "@types/eslint-scope": "^3.7.7", "@types/estree": "^1.0.8", "@types/json-schema": "^7.0.15", "@webassemblyjs/ast": "^1.14.1", "@webassemblyjs/wasm-edit": "^1.14.1", "@webassemblyjs/wasm-parser": "^1.14.1", "acorn": "^8.15.0", "acorn-import-phases": "^1.0.3", "browserslist": "^4.24.0", "chrome-trace-event": "^1.0.2", "enhanced-resolve": "^5.17.2", "es-module-lexer": "^1.2.1", "eslint-scope": "5.1.1", "events": "^3.2.0", "glob-to-regexp": "^0.4.1", "graceful-fs": "^4.2.11", "json-parse-even-better-errors": "^2.3.1", "loader-runner": "^4.2.0", "mime-types": "^2.1.27", "neo-async": "^2.6.2", "schema-utils": "^4.3.2", "tapable": "^2.1.1", "terser-webpack-plugin": "^5.3.11", "watchpack": "^2.4.1", "webpack-sources": "^3.3.3" }, "bin": { "webpack": "bin/webpack.js" } }, "sha512-QaNKAvGCDRh3wW1dsDjeMdDXwZm2vqq3zn6Pvq4rHOEOGSaUMgOOjG2Y9ZbIGzpfkJk9ZYTHpDqgDfeBDcnLaw=="], + + "webpack-sources": ["webpack-sources@3.3.3", "", {}, "sha512-yd1RBzSGanHkitROoPFd6qsrxt+oFhg/129YzheDGqeustzX0vTZJZsSsQjVQC4yzBQ56K55XU8gaNCtIzOnTg=="], + "whatwg-fetch": ["whatwg-fetch@3.6.20", "", {}, "sha512-EqhiFU6daOA8kpjOWTL0olhVOF3i7OrFzSYiGsEMB8GcXS+RrzauAERX65xMeNWVqxA6HXH2m69Z9LaKKdisfg=="], "whatwg-url": ["whatwg-url@5.0.0", "", { "dependencies": { "tr46": "~0.0.3", "webidl-conversions": "^3.0.0" } }, "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw=="], @@ -1647,7 +1733,7 @@ "write-file-atomic": ["write-file-atomic@4.0.2", "", { "dependencies": { "imurmurhash": "^0.1.4", "signal-exit": "^3.0.7" } }, "sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg=="], - "ws": ["ws@6.2.3", "", { "dependencies": { "async-limiter": "~1.0.0" } }, "sha512-jmTjYU0j60B+vHey6TfR3Z7RD61z/hmxBS3VMSGIrroOWXQEneK1zNuotOUrGyBHQj0yrpsLHPWtigEFd13ndA=="], + "ws": ["ws@8.17.1", "", { "peerDependencies": { "bufferutil": "^4.0.1", "utf-8-validate": ">=5.0.2" }, "optionalPeers": ["bufferutil", "utf-8-validate"] }, "sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ=="], "xcode": ["xcode@3.0.1", "", { "dependencies": { "simple-plist": "^1.1.0", "uuid": "^7.0.3" } }, "sha512-kCz5k7J7XbJtjABOvkc5lJmkiDh8VhjVCGNiqdKCscmVpdVUpEAyXv1xmCLkQJ5dsHqx3IPO4XW+NTDhU/fatA=="], @@ -1669,6 +1755,12 @@ "@babel/highlight/chalk": ["chalk@2.4.2", "", { "dependencies": { "ansi-styles": "^3.2.1", "escape-string-regexp": "^1.0.5", "supports-color": "^5.3.0" } }, "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ=="], + "@emnapi/core/tslib": ["tslib@2.8.1", "", {}, "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="], + + "@emnapi/runtime/tslib": ["tslib@2.8.1", "", {}, "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="], + + "@emnapi/wasi-threads/tslib": ["tslib@2.8.1", "", {}, "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="], + "@eslint-community/eslint-utils/eslint-visitor-keys": ["eslint-visitor-keys@3.4.3", "", {}, "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag=="], "@eslint/eslintrc/globals": ["globals@14.0.0", "", {}, "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ=="], @@ -1729,12 +1821,24 @@ "@istanbuljs/load-nyc-config/js-yaml": ["js-yaml@3.14.1", "", { "dependencies": { "argparse": "^1.0.7", "esprima": "^4.0.0" }, "bin": { "js-yaml": "bin/js-yaml.js" } }, "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g=="], + "@jest/environment/@types/node": ["@types/node@24.0.14", "", { "dependencies": { "undici-types": "~7.8.0" } }, "sha512-4zXMWD91vBLGRtHK3YbIoFMia+1nqEz72coM42C5ETjnNCa/heoj7NT1G67iAfOqMmcfhuCZ4uNpyz8EjlAejw=="], + + "@jest/fake-timers/@types/node": ["@types/node@24.0.14", "", { "dependencies": { "undici-types": "~7.8.0" } }, "sha512-4zXMWD91vBLGRtHK3YbIoFMia+1nqEz72coM42C5ETjnNCa/heoj7NT1G67iAfOqMmcfhuCZ4uNpyz8EjlAejw=="], + + "@jest/types/@types/node": ["@types/node@24.0.14", "", { "dependencies": { "undici-types": "~7.8.0" } }, "sha512-4zXMWD91vBLGRtHK3YbIoFMia+1nqEz72coM42C5ETjnNCa/heoj7NT1G67iAfOqMmcfhuCZ4uNpyz8EjlAejw=="], + "@react-native/community-cli-plugin/debug": ["debug@2.6.9", "", { "dependencies": { "ms": "2.0.0" } }, "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA=="], "@react-native/community-cli-plugin/semver": ["semver@7.6.3", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A=="], "@react-native/dev-middleware/debug": ["debug@2.6.9", "", { "dependencies": { "ms": "2.0.0" } }, "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA=="], + "@react-native/dev-middleware/ws": ["ws@6.2.3", "", { "dependencies": { "async-limiter": "~1.0.0" } }, "sha512-jmTjYU0j60B+vHey6TfR3Z7RD61z/hmxBS3VMSGIrroOWXQEneK1zNuotOUrGyBHQj0yrpsLHPWtigEFd13ndA=="], + + "@tybys/wasm-util/tslib": ["tslib@2.8.1", "", {}, "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="], + + "@types/graceful-fs/@types/node": ["@types/node@24.0.14", "", { "dependencies": { "undici-types": "~7.8.0" } }, "sha512-4zXMWD91vBLGRtHK3YbIoFMia+1nqEz72coM42C5ETjnNCa/heoj7NT1G67iAfOqMmcfhuCZ4uNpyz8EjlAejw=="], + "@typescript-eslint/eslint-plugin/ignore": ["ignore@7.0.5", "", {}, "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg=="], "@typescript-eslint/typescript-estree/minimatch": ["minimatch@9.0.5", "", { "dependencies": { "brace-expansion": "^2.0.1" } }, "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow=="], @@ -1753,6 +1857,10 @@ "caller-callsite/callsites": ["callsites@2.0.0", "", {}, "sha512-ksWePWBloaWPxJYQ8TL0JHvtci6G5QTKwQ95RcWAa/lzoAKuAOflGdAK92hpHXjkwb8zLxoLNUoNYZgVsaJzvQ=="], + "chrome-launcher/@types/node": ["@types/node@24.0.14", "", { "dependencies": { "undici-types": "~7.8.0" } }, "sha512-4zXMWD91vBLGRtHK3YbIoFMia+1nqEz72coM42C5ETjnNCa/heoj7NT1G67iAfOqMmcfhuCZ4uNpyz8EjlAejw=="], + + "chromium-edge-launcher/@types/node": ["@types/node@24.0.14", "", { "dependencies": { "undici-types": "~7.8.0" } }, "sha512-4zXMWD91vBLGRtHK3YbIoFMia+1nqEz72coM42C5ETjnNCa/heoj7NT1G67iAfOqMmcfhuCZ4uNpyz8EjlAejw=="], + "chromium-edge-launcher/mkdirp": ["mkdirp@1.0.4", "", { "bin": { "mkdirp": "bin/cmd.js" } }, "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw=="], "cliui/strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="], @@ -1803,8 +1911,18 @@ "is-bun-module/semver": ["semver@7.7.2", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA=="], + "jest-environment-node/@types/node": ["@types/node@24.0.14", "", { "dependencies": { "undici-types": "~7.8.0" } }, "sha512-4zXMWD91vBLGRtHK3YbIoFMia+1nqEz72coM42C5ETjnNCa/heoj7NT1G67iAfOqMmcfhuCZ4uNpyz8EjlAejw=="], + + "jest-haste-map/@types/node": ["@types/node@24.0.14", "", { "dependencies": { "undici-types": "~7.8.0" } }, "sha512-4zXMWD91vBLGRtHK3YbIoFMia+1nqEz72coM42C5ETjnNCa/heoj7NT1G67iAfOqMmcfhuCZ4uNpyz8EjlAejw=="], + + "jest-mock/@types/node": ["@types/node@24.0.14", "", { "dependencies": { "undici-types": "~7.8.0" } }, "sha512-4zXMWD91vBLGRtHK3YbIoFMia+1nqEz72coM42C5ETjnNCa/heoj7NT1G67iAfOqMmcfhuCZ4uNpyz8EjlAejw=="], + + "jest-util/@types/node": ["@types/node@24.0.14", "", { "dependencies": { "undici-types": "~7.8.0" } }, "sha512-4zXMWD91vBLGRtHK3YbIoFMia+1nqEz72coM42C5ETjnNCa/heoj7NT1G67iAfOqMmcfhuCZ4uNpyz8EjlAejw=="], + "jest-util/picomatch": ["picomatch@2.3.1", "", {}, "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA=="], + "jest-worker/@types/node": ["@types/node@24.0.14", "", { "dependencies": { "undici-types": "~7.8.0" } }, "sha512-4zXMWD91vBLGRtHK3YbIoFMia+1nqEz72coM42C5ETjnNCa/heoj7NT1G67iAfOqMmcfhuCZ4uNpyz8EjlAejw=="], + "jest-worker/supports-color": ["supports-color@8.1.1", "", { "dependencies": { "has-flag": "^4.0.0" } }, "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q=="], "lighthouse-logger/debug": ["debug@2.6.9", "", { "dependencies": { "ms": "2.0.0" } }, "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA=="], @@ -1839,6 +1957,8 @@ "react-native/semver": ["semver@7.6.3", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A=="], + "react-native/ws": ["ws@6.2.3", "", { "dependencies": { "async-limiter": "~1.0.0" } }, "sha512-jmTjYU0j60B+vHey6TfR3Z7RD61z/hmxBS3VMSGIrroOWXQEneK1zNuotOUrGyBHQj0yrpsLHPWtigEFd13ndA=="], + "react-native-reanimated/react-native-is-edge-to-edge": ["react-native-is-edge-to-edge@1.1.7", "", { "peerDependencies": { "react": "*", "react-native": "*" } }, "sha512-EH6i7E8epJGIcu7KpfXYXiV2JFIYITtq+rVS8uEb+92naMRBdxhTuS8Wn2Q7j9sqyO0B+Xbaaf9VdipIAmGW4w=="], "react-native-web/@react-native/normalize-colors": ["@react-native/normalize-colors@0.74.89", "", {}, "sha512-qoMMXddVKVhZ8PA1AbUCk83trpd6N+1nF2A6k1i6LsQObyS92fELuk8kU/lQs6M7BsMHwqyLCpQJ1uFgNvIQXg=="], @@ -1877,10 +1997,14 @@ "terser/commander": ["commander@2.20.3", "", {}, "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ=="], + "terser-webpack-plugin/jest-worker": ["jest-worker@27.5.1", "", { "dependencies": { "@types/node": "*", "merge-stream": "^2.0.0", "supports-color": "^8.0.0" } }, "sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg=="], + "tinyglobby/picomatch": ["picomatch@4.0.2", "", {}, "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg=="], "tsconfig-paths/json5": ["json5@1.0.2", "", { "dependencies": { "minimist": "^1.2.0" }, "bin": { "json5": "lib/cli.js" } }, "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA=="], + "webpack/eslint-scope": ["eslint-scope@5.1.1", "", { "dependencies": { "esrecurse": "^4.3.0", "estraverse": "^4.1.1" } }, "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw=="], + "whatwg-url/webidl-conversions": ["webidl-conversions@3.0.1", "", {}, "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ=="], "wrap-ansi/strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="], @@ -1919,16 +2043,28 @@ "@istanbuljs/load-nyc-config/js-yaml/argparse": ["argparse@1.0.10", "", { "dependencies": { "sprintf-js": "~1.0.2" } }, "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg=="], + "@jest/environment/@types/node/undici-types": ["undici-types@7.8.0", "", {}, "sha512-9UJ2xGDvQ43tYyVMpuHlsgApydB8ZKfVYTsLDhXkFL/6gfkp+U8xTGdh8pMJv1SpZna0zxG1DwsKZsreLbXBxw=="], + + "@jest/fake-timers/@types/node/undici-types": ["undici-types@7.8.0", "", {}, "sha512-9UJ2xGDvQ43tYyVMpuHlsgApydB8ZKfVYTsLDhXkFL/6gfkp+U8xTGdh8pMJv1SpZna0zxG1DwsKZsreLbXBxw=="], + + "@jest/types/@types/node/undici-types": ["undici-types@7.8.0", "", {}, "sha512-9UJ2xGDvQ43tYyVMpuHlsgApydB8ZKfVYTsLDhXkFL/6gfkp+U8xTGdh8pMJv1SpZna0zxG1DwsKZsreLbXBxw=="], + "@react-native/community-cli-plugin/debug/ms": ["ms@2.0.0", "", {}, "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="], "@react-native/dev-middleware/debug/ms": ["ms@2.0.0", "", {}, "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="], + "@types/graceful-fs/@types/node/undici-types": ["undici-types@7.8.0", "", {}, "sha512-9UJ2xGDvQ43tYyVMpuHlsgApydB8ZKfVYTsLDhXkFL/6gfkp+U8xTGdh8pMJv1SpZna0zxG1DwsKZsreLbXBxw=="], + "@typescript-eslint/typescript-estree/minimatch/brace-expansion": ["brace-expansion@2.0.2", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ=="], "ajv-formats/ajv/json-schema-traverse": ["json-schema-traverse@1.0.0", "", {}, "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug=="], "ajv-keywords/ajv/json-schema-traverse": ["json-schema-traverse@1.0.0", "", {}, "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug=="], + "chrome-launcher/@types/node/undici-types": ["undici-types@7.8.0", "", {}, "sha512-9UJ2xGDvQ43tYyVMpuHlsgApydB8ZKfVYTsLDhXkFL/6gfkp+U8xTGdh8pMJv1SpZna0zxG1DwsKZsreLbXBxw=="], + + "chromium-edge-launcher/@types/node/undici-types": ["undici-types@7.8.0", "", {}, "sha512-9UJ2xGDvQ43tYyVMpuHlsgApydB8ZKfVYTsLDhXkFL/6gfkp+U8xTGdh8pMJv1SpZna0zxG1DwsKZsreLbXBxw=="], + "compression/debug/ms": ["ms@2.0.0", "", {}, "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="], "connect/debug/ms": ["ms@2.0.0", "", {}, "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="], @@ -1941,6 +2077,16 @@ "finalhandler/debug/ms": ["ms@2.0.0", "", {}, "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="], + "jest-environment-node/@types/node/undici-types": ["undici-types@7.8.0", "", {}, "sha512-9UJ2xGDvQ43tYyVMpuHlsgApydB8ZKfVYTsLDhXkFL/6gfkp+U8xTGdh8pMJv1SpZna0zxG1DwsKZsreLbXBxw=="], + + "jest-haste-map/@types/node/undici-types": ["undici-types@7.8.0", "", {}, "sha512-9UJ2xGDvQ43tYyVMpuHlsgApydB8ZKfVYTsLDhXkFL/6gfkp+U8xTGdh8pMJv1SpZna0zxG1DwsKZsreLbXBxw=="], + + "jest-mock/@types/node/undici-types": ["undici-types@7.8.0", "", {}, "sha512-9UJ2xGDvQ43tYyVMpuHlsgApydB8ZKfVYTsLDhXkFL/6gfkp+U8xTGdh8pMJv1SpZna0zxG1DwsKZsreLbXBxw=="], + + "jest-util/@types/node/undici-types": ["undici-types@7.8.0", "", {}, "sha512-9UJ2xGDvQ43tYyVMpuHlsgApydB8ZKfVYTsLDhXkFL/6gfkp+U8xTGdh8pMJv1SpZna0zxG1DwsKZsreLbXBxw=="], + + "jest-worker/@types/node/undici-types": ["undici-types@7.8.0", "", {}, "sha512-9UJ2xGDvQ43tYyVMpuHlsgApydB8ZKfVYTsLDhXkFL/6gfkp+U8xTGdh8pMJv1SpZna0zxG1DwsKZsreLbXBxw=="], + "lighthouse-logger/debug/ms": ["ms@2.0.0", "", {}, "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="], "log-symbols/chalk/ansi-styles": ["ansi-styles@3.2.1", "", { "dependencies": { "color-convert": "^1.9.0" } }, "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA=="], @@ -1969,6 +2115,12 @@ "sucrase/glob/minimatch": ["minimatch@9.0.5", "", { "dependencies": { "brace-expansion": "^2.0.1" } }, "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow=="], + "terser-webpack-plugin/jest-worker/@types/node": ["@types/node@24.0.14", "", { "dependencies": { "undici-types": "~7.8.0" } }, "sha512-4zXMWD91vBLGRtHK3YbIoFMia+1nqEz72coM42C5ETjnNCa/heoj7NT1G67iAfOqMmcfhuCZ4uNpyz8EjlAejw=="], + + "terser-webpack-plugin/jest-worker/supports-color": ["supports-color@8.1.1", "", { "dependencies": { "has-flag": "^4.0.0" } }, "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q=="], + + "webpack/eslint-scope/estraverse": ["estraverse@4.3.0", "", {}, "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw=="], + "@babel/highlight/chalk/ansi-styles/color-convert": ["color-convert@1.9.3", "", { "dependencies": { "color-name": "1.1.3" } }, "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg=="], "@babel/highlight/chalk/supports-color/has-flag": ["has-flag@3.0.0", "", {}, "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw=="], @@ -1995,6 +2147,8 @@ "sucrase/glob/minimatch/brace-expansion": ["brace-expansion@2.0.2", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ=="], + "terser-webpack-plugin/jest-worker/@types/node/undici-types": ["undici-types@7.8.0", "", {}, "sha512-9UJ2xGDvQ43tYyVMpuHlsgApydB8ZKfVYTsLDhXkFL/6gfkp+U8xTGdh8pMJv1SpZna0zxG1DwsKZsreLbXBxw=="], + "@babel/highlight/chalk/ansi-styles/color-convert/color-name": ["color-name@1.1.3", "", {}, "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw=="], "@istanbuljs/load-nyc-config/find-up/locate-path/p-locate/p-limit": ["p-limit@2.3.0", "", { "dependencies": { "p-try": "^2.0.0" } }, "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w=="], diff --git a/components/PrimaryButton.tsx b/components/PrimaryButton.tsx new file mode 100644 index 0000000..94bd8ce --- /dev/null +++ b/components/PrimaryButton.tsx @@ -0,0 +1,102 @@ +import React from "react"; +import { + TouchableOpacity, + Text, + StyleSheet, + ActivityIndicator, + ViewStyle, + View, + TextStyle, +} from "react-native"; +import { Feather } from "@expo/vector-icons"; +import { useThemeColors, ColorScheme } from "../constants"; + +interface SendButtonProps { + onPress: () => void; + isLoading?: boolean; + disabled?: boolean; + label?: string; + style?: ViewStyle; + textStyle?: TextStyle; +} + +const SendButton: React.FC = ({ + onPress, + isLoading = false, + disabled = false, + label = "Send", + style, +}) => { + const isButtonDisabled = isLoading || disabled; + const colors = useThemeColors(); + + return ( + + {isLoading ? ( + + + + ) : ( + <> + + {label} + + + + )} + + ); +}; + +const styles = StyleSheet.create({ + sendButton: { + // paddingVertical: 10, + paddingHorizontal: 16, + borderRadius: 8, + flexDirection: "row", + justifyContent: "flex-start", + alignItems: "center", + gap: 8, + height: 48, + }, + sendText: { + fontSize: 16, + fontWeight: 600, + flex: 1, + }, + disabledButton: { + backgroundColor: "#4B5563", + }, + disabledText: { + color: "#eee", + }, +}); + +export default SendButton; diff --git a/components/ScreenWrapper.tsx b/components/ScreenWrapper.tsx new file mode 100644 index 0000000..49c698f --- /dev/null +++ b/components/ScreenWrapper.tsx @@ -0,0 +1,31 @@ +import React from "react"; +import { View, StyleSheet, Platform } from "react-native"; + +type Props = { + children: React.ReactNode; + style?: object; +}; + +const ScreenWrapper = ({ children, style }: Props) => { + return ( + + {children} + + ); +}; + +const styles = StyleSheet.create({ + outer: { + flex: 1, + alignItems: "center", + justifyContent: "flex-start", + }, + inner: { + width: "100%", + + maxWidth: Platform.OS === "web" ? 420 : "100%", + flexGrow: 1, + }, +}); + +export default ScreenWrapper; diff --git a/components/auth/Auth.tsx b/components/auth/Auth.tsx new file mode 100644 index 0000000..40512ca --- /dev/null +++ b/components/auth/Auth.tsx @@ -0,0 +1,149 @@ +"use client"; + +import PrimaryButton from "../PrimaryButton"; +import { SymbolView, SymbolViewProps, SymbolWeight } from "expo-symbols"; +import { useState } from "react"; +import { Platform, StyleProp, ViewStyle } from "react-native"; + +const PASSKEY_CREDENTIAL_ID_KEY = "urbit_wallet_passkey_id"; +const RELYING_PARTY_ID = "wallet.urbit.org"; // Change this to your domain +const RELYING_PARTY_NAME = "Urbit Wallet"; + +export function Passkee() { + const [isLoading, setIsLoading] = useState(false); + async function handleCreatePasskey() { + const pkok = + await window.PublicKeyCredential.isUserVerifyingPlatformAuthenticatorAvailable(); + console.log({ pkok }); + + // if (Platform.OS !== "web") { + // return false; + // } + console.log("creating passkey"); + + try { + // Generate a random user ID + const userId = new Uint8Array(16); + crypto.getRandomValues(userId); + + // Generate a random challenge + const challenge = new Uint8Array(32); + crypto.getRandomValues(challenge); + + const createCredentialOptions: CredentialCreationOptions = { + publicKey: { + // REQUIRED: Random challenge to prevent replay attacks + // Must be at least 16 bytes, we use 32 for extra security + challenge, + + // REQUIRED: Relying Party (your website/app) + rp: { + // REQUIRED: Human-readable name shown in UI prompts + name: RELYING_PARTY_NAME, + + // OPTIONAL: Domain that owns this credential + // If omitted, defaults to current domain + // Must match or be a registrable suffix of the current domain + id: + window.location.hostname === "localhost" + ? "localhost" + : RELYING_PARTY_ID, + }, + + // REQUIRED: User information + user: { + // REQUIRED: Unique user ID (must not contain PII) + // Used by authenticator to distinguish between accounts + id: userId, + + // REQUIRED: Unique username/identifier for this RP + // Shown in some UI contexts, should be recognizable to user + name: "urbit-user", + + // REQUIRED: Human-readable name for display + // Shown in account selectors and prompts + displayName: "Urbit Wallet User", + }, + + // REQUIRED: List of acceptable public key algorithms + // Order matters - authenticator will use first supported algorithm + pubKeyCredParams: [ + { alg: -7, type: "public-key" }, // ES256 (ECDSA with SHA-256) - most common + { alg: -257, type: "public-key" }, // RS256 (RSASSA-PKCS1-v1_5) - fallback + ], + + // OPTIONAL: Criteria for authenticator selection + authenticatorSelection: { + // OPTIONAL: "platform" (built-in like Touch ID) or "cross-platform" (USB key) + // Omitting allows both types + // authenticatorAttachment: "platform", + + // OPTIONAL: User verification requirement + // "required" - must verify user (biometric/PIN) + // "preferred" - verify if possible, continue if not (default) + // "discouraged" - don't verify unless required by RP + userVerification: "preferred", + + // OPTIONAL: Whether to create a discoverable credential (passkey) + // "required" - must create discoverable credential + // "preferred" - create if possible (default) + // "discouraged" - don't create discoverable credential + residentKey: "preferred", + + // DEPRECATED: Use residentKey instead + // Kept for backwards compatibility with older authenticators + requireResidentKey: false, + }, + + // OPTIONAL: Time limit in milliseconds (default varies by browser) + // 60 seconds is reasonable for user interaction + timeout: 60000, + + // OPTIONAL: Attestation preference (proof of authenticator legitimacy) + // "none" - no attestation needed (default, best for privacy) + // "indirect" - RP prefers attestation but allows anonymization + // "direct" - RP needs attestation from authenticator + // "enterprise" - RP needs attestation and device info (requires permission) + attestation: "none", + + // OPTIONAL: List of credentials to exclude (prevent duplicates) + // excludeCredentials: [ + // { id: existingCredentialId, type: "public-key" } + // ], + + // OPTIONAL: Extensions for additional features + // extensions: { + // credProps: true, // Request additional credential properties + // hmacCreateSecret: true, // For symmetric key operations + // }, + }, + }; + + const credential = (await navigator.credentials.create( + createCredentialOptions, + )) as PublicKeyCredential; + console.log({ credential }); + + if (credential) { + // Store the credential ID for later use + // await SecureStore.setItemAsync(PASSKEY_CREDENTIAL_ID_KEY, credential.id); + + console.log("Passkey created successfully", credential.id); + return true; + } + + return false; + } catch (error) { + console.error("Error creating passkey:", error); + return false; + } + } + return ( + + ); +} diff --git a/constants/colors.ts b/constants/colors.ts new file mode 100644 index 0000000..6f07a2c --- /dev/null +++ b/constants/colors.ts @@ -0,0 +1,51 @@ +// import { useSettingsStore } from "../store/useSettingsStore"; + +export type ColorScheme = typeof lightColors; + +export const useThemeColors = (): ColorScheme => { + // const isDarkMode = useSettingsStore((s) => s.isDarkMode); + // return isDarkMode ? darkColors : lightColors; + return lightColors; +}; + +export const lightColors = { + background: "#F7F7F7", + text: "#171717", + card: "#FFFFFF", + border: "#E5E5E5", + primary: "#1997FC", + secondary: "#737373", //"#4B5563", + toastBackground: "#171717", + toastText: "#FFFFFF", + toastSuccess: "#12BA03", + toastError: "#EF4444", + skeletonBase: "#ebebeb", + skeletonHighlight: "#f5f5f5", + button: "#171717", + buttonText: "#F7F7F7", + iconBorder: "#D4D4D4", + navBorder: "#D4D4D4", + switchBackground: "#E5E5E5", + switchThumb: "#FFFFFF", +}; + +export const darkColors = { + background: "#121212", + text: "#F3F3F3", + card: "#1F1F1F", + border: "#323232", //"#2A2A2A", + primary: "#1997FC", + secondary: "#9CA3AF", + toastBackground: "#F3F3F3", + toastText: "#121212", + toastSuccess: "#22C55E", + toastError: "#EF4444", + skeletonBase: "#374151", + skeletonHighlight: "#4B5563", + button: "#F7F7F7", + buttonText: "#171717", + iconBorder: "#FAFAFA", + navBorder: "#323232", + switchBackground: "#E5E5E5", + switchThumb: "#1F1F1F", +}; diff --git a/constants/config.ts b/constants/config.ts new file mode 100644 index 0000000..6fa09b6 --- /dev/null +++ b/constants/config.ts @@ -0,0 +1,67 @@ +import { JsonRpcProvider, WebSocketProvider } from "ethers"; +import { ETHEREUM_NETWORK } from "../constants"; + +const isLocal = false; + +const INFURA_API = process.env.EXPO_PUBLIC_INFURA_API!; +const INFURA_API_SECRET_KEY = process.env.EXPO_PUBLIC_INFURA_API_SECRET_KEY!; +const NETWORK = process.env.EXPO_PUBLIC_NETWORK!; +const ETHERSCAN_API_KEY = process.env.EXPO_PUBLIC_ETHERSCAN_API_KEY!; +const requiredVars = [ + INFURA_API, + INFURA_API_SECRET_KEY, + NETWORK, + ETHERSCAN_API_KEY, +]; + +const missingVar = requiredVars.find((v) => !v); + +if (missingVar) { + throw new Error( + "Missing required environment variables. Check your .env file.", + ); +} + +export const WEBSOCKET_URL = `wss://${NETWORK}.infura.io/ws/v3/${INFURA_API}`; + +export const PROVIDER_URL = isLocal + ? "http://localhost:8545" + : `https://${NETWORK}.infura.io/v3/${INFURA_API}`; + +export const MAINNET_PROVIDER_URL = `https://mainnet.infura.io/v3/${INFURA_API}`; + +export const getEtherscanBaseUrl = () => { + console.log("NETWORK", NETWORK); + return NETWORK === ETHEREUM_NETWORK.MAINNET + ? "https://api.etherscan.io/api" + : `https://api-${NETWORK}.etherscan.io/api`; +}; + +export const httpProvider = new JsonRpcProvider( + `https://${NETWORK}.infura.io/v3/${INFURA_API}`, +); +export const wsProvider = new WebSocketProvider(WEBSOCKET_URL); + +export const getEthTxUrl = ( + walletAddress: string, + page: number = 1, + pageSize: number = 20, +) => + `${getEtherscanBaseUrl()}?module=account&action=txlist&address=${walletAddress}&startblock=0&endblock=99999999&page=${page}&offset=${pageSize}&sort=desc&apikey=${ETHERSCAN_API_KEY}`; + +export const getTokenTxUrl = ( + walletAddress: string, + page: number = 1, + pageSize: number = 20, +) => + `${getEtherscanBaseUrl()}?module=account&action=tokentx&address=${walletAddress}&startblock=0&endblock=99999999&page=${page}&offset=${pageSize}&sort=desc&apikey=${ETHERSCAN_API_KEY}`; + +export const getTokenIcon = (address: string) => + `https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/${address}/logo.png`; + +export const getInternalTxUrl = ( + walletAddress: string, + page: number = 1, + pageSize: number = 20, +) => + `${getEtherscanBaseUrl()}?module=account&action=txlistinternal&address=${walletAddress}&startblock=0&endblock=99999999&page=${page}&offset=${pageSize}&sort=desc&apikey=${ETHERSCAN_API_KEY}`; diff --git a/constants/constants.ts b/constants/constants.ts new file mode 100644 index 0000000..477a2e7 --- /dev/null +++ b/constants/constants.ts @@ -0,0 +1,24 @@ +import { ImageSourcePropType } from "react-native"; +import EthLogo from "../assets/eth-logo.png"; +import UsdcLogo from "../assets/usdc-logo.png"; +import linkLogo from "../assets/link-logo.png"; + +export const ETHEREUM_NETWORK = { + MAINNET: "mainnet", + SEPOLIA: "sepolia", + LOCAL: "local", +} as const; + +export const DEFAULT_HD_PATH = "m/44'/60'/0'/0/0"; + +export const ETH_PRICE_URL = + "https://api.coingecko.com/api/v3/simple/price?ids=ethereum&vs_currencies=usd"; + +export const TOKEN_ICONS: Record = { + ETH: EthLogo, + USDC: UsdcLogo, + // USDT: "https://assets.coingecko.com/coins/images/325/thumb/Tether.png?1696501661", + // DAI: "https://assets.coingecko.com/coins/images/9956/thumb/Badge_Dai.png?1696509996", //"https://cryptologos.cc/logos/multi-collateral-dai-dai-logo.png", + LINK: linkLogo, //"https://assets.coingecko.com/coins/images/877/thumb/chainlink-new-logo.png?1696502009", //"https://cryptologos.cc/logos/chainlink-link-logo.png", + // default: "https://via.placeholder.com/36", +}; diff --git a/constants/contracts.ts b/constants/contracts.ts new file mode 100644 index 0000000..9c02a4a --- /dev/null +++ b/constants/contracts.ts @@ -0,0 +1,109 @@ +import { ETHEREUM_NETWORK } from "../constants"; + +type ContractAddresses = Record; +type NetworkKey = keyof typeof ETHEREUM_NETWORK; + +export const ERC20_ABI = [ + { + type: "function", + name: "balanceOf", + inputs: [{ name: "owner", type: "address" }], + outputs: [{ name: "", type: "uint256" }], + stateMutability: "view", + }, + { + type: "function", + name: "decimals", + inputs: [], + outputs: [{ name: "", type: "uint8" }], + stateMutability: "view", + }, + { + type: "function", + name: "transfer", + inputs: [ + { name: "to", type: "address" }, + { name: "value", type: "uint256" }, + ], + outputs: [{ name: "", type: "bool" }], + stateMutability: "nonpayable", + }, + { + type: "event", + name: "Transfer", + inputs: [ + { name: "from", type: "address", indexed: true }, + { name: "to", type: "address", indexed: true }, + { name: "value", type: "uint256", indexed: false }, + ], + anonymous: false, + }, +]; + +export const AZIMUTH_ABI = [ + "function getOwner(uint32 _point) view returns (address)", + "function getOwnedPoints(address _whose) view returns (uint32[])", +]; + +const CONTRACT_ADDRESSES: Record = { + MAINNET: { + azimuth: "0x223c067f8cf28ae173ee5cafea60ca44c335fecb", + ecliptic: "0x33EeCbf908478C10614626A9D304bfe18B78DD73", + polls: "0x0", + claims: "0x0", + linearStarRelease: "0x86cd9cd0992f04231751e3761de45cecea5d1801", + conditionalStarRelease: "0x8c241098c3d3498fe1261421633fd57986d74aea", + urbit_L2: "0x1111111111111111111111111111111111111111", + usdc: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606EB48", + usdt: "0xdac17f958d2ee523a2206206994597c13d831ec7", + dai: "0x6b175474e89094c44da98b954eedeac495271d0f", + link: "0x514910771af9ca656af840dff83e8264ecf986ca", // ? + }, + SEPOLIA: { + azimuth: "0xF07cD672D61453c29138c8db5b44fC9FA84811B5", + ecliptic: "0x2E35a61198C383212CeF06C22f1E81B6b097135C", + polls: "0x3A3a06199Dc537FB56A6975A8B12A8eD7fCbf897", + claims: "0xdB164DBEF321e7DE938809fE35A5A8A928c4F4df", + linearStarRelease: "0x0", + conditionalStarRelease: "0x0", + urbit_L2: "0x0", + usdc: "0x1c7D4B196Cb0C7B01d743Fbc6116a902379C7238", + usdt: "0xaa8e23fb1079ea71e0a56f48a2aa51851d8433d0", + dai: "0x776b6fc2ed15d6bb5fc32e0c89de68683118c62a", + link: "0x779877A7B0D9E8603169DdbD7836e478b4624789", + }, + LOCAL: { + azimuth: "0x0", + ecliptic: "0x0", + polls: "0x0", + claims: "0x0", + linearStarRelease: "0x0", + conditionalStarRelease: "0x0", + urbit_L2: "0x0", + usdc: "0x0", + usdt: "0x0", + dai: "0x0", + link: "0x0", + }, +}; + +const mapNetworkStringToKey = (network: string): NetworkKey => { + switch (network) { + case "mainnet": + return "MAINNET"; + case "sepolia": + return "SEPOLIA"; + case "local": + return "LOCAL"; + default: + return "SEPOLIA"; + } +}; + +const currentNetworkKey = mapNetworkStringToKey( + process.env.EXPO_PUBLIC_NETWORK!, +); + +console.log("currentNetworkKey", currentNetworkKey); + +export const CONTRACT = CONTRACT_ADDRESSES[currentNetworkKey]; diff --git a/constants/index.ts b/constants/index.ts new file mode 100644 index 0000000..ad2c758 --- /dev/null +++ b/constants/index.ts @@ -0,0 +1,5 @@ +export * from "./contracts"; +export * from "./constants"; +export * from "./colors"; +export * from "./config"; +export * from "./routes"; diff --git a/constants/routes.ts b/constants/routes.ts new file mode 100644 index 0000000..697f4fc --- /dev/null +++ b/constants/routes.ts @@ -0,0 +1,11 @@ +export const ROUTES = { + PASSKEY_SETUP: "PasskeySetup", + LOGIN: "Login", + HOME: "Home", + SEND: "Send", + RECEIVE: "Receive", + HISTORY: "TransactionHistory", + MAIN_TABS: "MainTabs", + AUTH: "Auth", + APP: "App", +} as const; diff --git a/lib/passkey.ts b/lib/passkey.ts new file mode 100644 index 0000000..573c62b --- /dev/null +++ b/lib/passkey.ts @@ -0,0 +1,131 @@ +const PASSKEY_CREDENTIAL_ID_KEY = "urbit_wallet_passkey_id"; +const RELYING_PARTY_ID = "wallet.urbit.org"; // Change this to your domain +const RELYING_PARTY_NAME = "Urbit Wallet"; + +async function createPasskey() { + const pkok = + await window.PublicKeyCredential.isUserVerifyingPlatformAuthenticatorAvailable(); + console.log({ pkok }); + + // if (Platform.OS !== "web") { + // return false; + // } + console.log("creating passkey"); + + try { + // Generate a random user ID + const userId = new Uint8Array(16); + crypto.getRandomValues(userId); + + // Generate a random challenge + const challenge = new Uint8Array(32); + crypto.getRandomValues(challenge); + + const createCredentialOptions: CredentialCreationOptions = { + publicKey: { + // REQUIRED: Random challenge to prevent replay attacks + // Must be at least 16 bytes, we use 32 for extra security + challenge, + + // REQUIRED: Relying Party (your website/app) + rp: { + // REQUIRED: Human-readable name shown in UI prompts + name: RELYING_PARTY_NAME, + + // OPTIONAL: Domain that owns this credential + // If omitted, defaults to current domain + // Must match or be a registrable suffix of the current domain + id: + window.location.hostname === "localhost" + ? "localhost" + : RELYING_PARTY_ID, + }, + + // REQUIRED: User information + user: { + // REQUIRED: Unique user ID (must not contain PII) + // Used by authenticator to distinguish between accounts + id: userId, + + // REQUIRED: Unique username/identifier for this RP + // Shown in some UI contexts, should be recognizable to user + name: "urbit-user", + + // REQUIRED: Human-readable name for display + // Shown in account selectors and prompts + displayName: "Urbit Wallet User", + }, + + // REQUIRED: List of acceptable public key algorithms + // Order matters - authenticator will use first supported algorithm + pubKeyCredParams: [ + { alg: -7, type: "public-key" }, // ES256 (ECDSA with SHA-256) - most common + { alg: -257, type: "public-key" }, // RS256 (RSASSA-PKCS1-v1_5) - fallback + ], + + // OPTIONAL: Criteria for authenticator selection + authenticatorSelection: { + // OPTIONAL: "platform" (built-in like Touch ID) or "cross-platform" (USB key) + // Omitting allows both types + // authenticatorAttachment: "platform", + + // OPTIONAL: User verification requirement + // "required" - must verify user (biometric/PIN) + // "preferred" - verify if possible, continue if not (default) + // "discouraged" - don't verify unless required by RP + userVerification: "preferred", + + // OPTIONAL: Whether to create a discoverable credential (passkey) + // "required" - must create discoverable credential + // "preferred" - create if possible (default) + // "discouraged" - don't create discoverable credential + residentKey: "preferred", + + // DEPRECATED: Use residentKey instead + // Kept for backwards compatibility with older authenticators + requireResidentKey: false, + }, + + // OPTIONAL: Time limit in milliseconds (default varies by browser) + // 60 seconds is reasonable for user interaction + timeout: 60000, + + // OPTIONAL: Attestation preference (proof of authenticator legitimacy) + // "none" - no attestation needed (default, best for privacy) + // "indirect" - RP prefers attestation but allows anonymization + // "direct" - RP needs attestation from authenticator + // "enterprise" - RP needs attestation and device info (requires permission) + attestation: "none", + + // OPTIONAL: List of credentials to exclude (prevent duplicates) + // excludeCredentials: [ + // { id: existingCredentialId, type: "public-key" } + // ], + + // OPTIONAL: Extensions for additional features + // extensions: { + // credProps: true, // Request additional credential properties + // hmacCreateSecret: true, // For symmetric key operations + // }, + }, + }; + + const credential = (await navigator.credentials.create( + createCredentialOptions, + )) as PublicKeyCredential; + console.log({ credential }); + + if (credential) { + // Store the credential ID for later use + // await SecureStore.setItemAsync(PASSKEY_CREDENTIAL_ID_KEY, credential.id); + + console.log("Passkey created successfully", credential.id); + return true; + } + + return false; + } catch (error) { + console.error("Error creating passkey:", error); + return false; + } +} diff --git a/package.json b/package.json index 48f24aa..5fed9f5 100644 --- a/package.json +++ b/package.json @@ -15,6 +15,7 @@ "@react-navigation/bottom-tabs": "^7.3.10", "@react-navigation/elements": "^2.3.8", "@react-navigation/native": "^7.1.6", + "ethers": "^6.15.0", "expo": "~53.0.17", "expo-blur": "~14.1.5", "expo-constants": "~17.1.7", @@ -36,7 +37,8 @@ "react-native-safe-area-context": "5.4.0", "react-native-screens": "~4.11.1", "react-native-web": "~0.20.0", - "react-native-webview": "13.13.5" + "react-native-webview": "13.13.5", + "react-server-dom-webpack": "^19.1.0" }, "devDependencies": { "@babel/core": "^7.25.2", -- cgit v1.2.3