From 2b6862462f2f4c58d38d641bf169f4da827ff625 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Antoni=20Gal=C3=AD?= Date: Mon, 2 Feb 2026 13:54:02 +0100 Subject: [PATCH 01/10] feat: add passkey support and recovery method options - Updated package dependencies to include `react-native-passkeys`. - Introduced `NativePasskeyHandler` for handling passkey operations. - Added support for passkey recovery method in wallet configuration. - Implemented hooks for detecting passkey support. - Enhanced message handling in WebView for passkey key normalization. - Updated types to accommodate new recovery options. --- package.json | 8 +- pnpm-lock.yaml | 26 +- src/core/provider.tsx | 34 ++- src/hooks/core/index.ts | 3 + src/hooks/core/usePasskeySupport.ts | 43 ++++ src/hooks/wallet/utils.ts | 29 ++- src/native/index.ts | 4 +- src/native/passkey.ts | 380 ++++++++++++++++++++++++++++ src/native/webview.tsx | 39 ++- src/types/wallet.ts | 16 ++ 10 files changed, 562 insertions(+), 20 deletions(-) create mode 100644 src/hooks/core/usePasskeySupport.ts create mode 100644 src/native/passkey.ts diff --git a/package.json b/package.json index d289aaa..46a556c 100644 --- a/package.json +++ b/package.json @@ -40,7 +40,8 @@ } }, "dependencies": { - "@openfort/openfort-js": "^1.1.3" + "@openfort/openfort-js": "https://pkg.pr.new/@openfort/openfort-js@f589f41", + "react-native-passkeys": "0.4.0" }, "peerDependencies": { "expo-apple-authentication": "*", @@ -94,7 +95,10 @@ "size-limit": [ { "path": "dist/index.js", - "limit": "250 KB" + "limit": "250 KB", + "ignore": [ + "expo-modules-core" + ] } ], "pnpm": { diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index b665b4d..8fcb06d 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -13,8 +13,11 @@ importers: .: dependencies: '@openfort/openfort-js': - specifier: ^1.1.3 - version: 1.1.3 + specifier: https://pkg.pr.new/@openfort/openfort-js@f589f41 + version: https://pkg.pr.new/@openfort/openfort-js@f589f41 + react-native-passkeys: + specifier: 0.4.0 + version: 0.4.0(react-native@0.77.1(@babel/core@7.28.6)(@types/react@18.3.27)(react@18.3.1))(react@18.3.1) devDependencies: '@biomejs/biome': specifier: ^2.2.4 @@ -1009,8 +1012,9 @@ packages: resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} engines: {node: '>= 8'} - '@openfort/openfort-js@1.1.3': - resolution: {integrity: sha512-KFbDBT+Tp2ZMEe+1qOLjpi7JtRp6qsyq2VjBm5p5oNVrEyUYJN9DjaPfdu0PHURtyzqNIA/aMBoBCOKlu0Zlog==} + '@openfort/openfort-js@https://pkg.pr.new/@openfort/openfort-js@f589f41': + resolution: {tarball: https://pkg.pr.new/@openfort/openfort-js@f589f41} + version: 1.1.4 '@openfort/shield-js@0.1.34': resolution: {integrity: sha512-bJxQc0zk0VPxk7CWSE5NZp5Bv8nYnStwG5GKXrS2A6hxEt0vf4BMu9db4IUiHxmgGaFWrdAnbSCSZ5AU1gwyew==} @@ -2585,6 +2589,13 @@ packages: react-is@18.3.1: resolution: {integrity: sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==} + react-native-passkeys@0.4.0: + resolution: {integrity: sha512-WX0jw60tDyZ3SwhnKvAdddwC27efT4CWWcq/j8O+RyGU/wIidQXeaAtX0kX1CMGNsXnoDDgbMAhUbIG+Ia786Q==} + peerDependencies: + expo: '>=48.0.0' + react: '*' + react-native: '>=0.71.0' + react-native-webview@13.16.0: resolution: {integrity: sha512-Nh13xKZWW35C0dbOskD7OX01nQQavOzHbCw9XoZmar4eXCo7AvrYJ0jlUfRVVIJzqINxHlpECYLdmAdFsl9xDA==} peerDependencies: @@ -4306,7 +4317,7 @@ snapshots: '@nodelib/fs.scandir': 2.1.5 fastq: 1.20.1 - '@openfort/openfort-js@1.1.3': + '@openfort/openfort-js@https://pkg.pr.new/@openfort/openfort-js@f589f41': dependencies: '@ethersproject/abi': 5.8.0 '@ethersproject/bytes': 5.8.0 @@ -6100,6 +6111,11 @@ snapshots: react-is@18.3.1: {} + react-native-passkeys@0.4.0(react-native@0.77.1(@babel/core@7.28.6)(@types/react@18.3.27)(react@18.3.1))(react@18.3.1): + dependencies: + react: 18.3.1 + react-native: 0.77.1(@babel/core@7.28.6)(@types/react@18.3.27)(react@18.3.1) + react-native-webview@13.16.0(react-native@0.77.1(@babel/core@7.28.6)(@types/react@18.3.27)(react@18.3.1))(react@18.3.1): dependencies: escape-string-regexp: 4.0.0 diff --git a/src/core/provider.tsx b/src/core/provider.tsx index 07f8cdc..33e0e3a 100644 --- a/src/core/provider.tsx +++ b/src/core/provider.tsx @@ -10,7 +10,7 @@ import { import React, { useCallback, useEffect, useMemo, useState } from 'react' import { validateEnvironment } from '../lib/environmentValidation' import { getEmbeddedStateName, logger } from '../lib/logger' -import { EmbeddedWalletWebView, WebViewUtils } from '../native' +import { EmbeddedWalletWebView, NativePasskeyHandler, WebViewUtils } from '../native' import type { OAuthFlowState, PasswordFlowState, RecoveryFlowState, SiweFlowState } from '../types' import { createOpenfortClient, setDefaultClient } from './client' import { OpenfortContext, type OpenfortContextValue } from './context' @@ -24,8 +24,12 @@ export type CommonEmbeddedWalletConfiguration = { ethereumProviderPolicyId?: PolicyConfig accountType?: AccountTypeEnum debug?: boolean - /** Recovery method for the embedded wallet: 'automatic' or 'password' */ - recoveryMethod?: 'automatic' | 'password' + /** Recovery method for the embedded wallet: 'automatic', 'password', or 'passkey' */ + recoveryMethod?: 'automatic' | 'password' | 'passkey' + /** Passkey Relying Party ID (domain) for passkey-based recovery */ + passkeyRpId?: string + /** Passkey Relying Party Name for passkey-based recovery */ + passkeyRpName?: string } /** @@ -248,7 +252,19 @@ export const OpenfortProvider = ({ logger.setVerbose(verbose) }, [verbose]) - // Create or use provided client + // Create passkey handler if passkey recovery is configured (single instance for SDK and WebView) + const passkeyHandler = useMemo(() => { + if (walletConfig?.passkeyRpId) { + return new NativePasskeyHandler({ + rpId: walletConfig.passkeyRpId, + rpName: walletConfig.passkeyRpName, + extractableKey: true, + }) + } + return undefined + }, [walletConfig?.passkeyRpId, walletConfig?.passkeyRpName]) + + // Create client with passkeyHandler in overrides when configured const client = useMemo(() => { const newClient = createOpenfortClient({ baseConfiguration: { @@ -258,15 +274,19 @@ export const OpenfortProvider = ({ ? new ShieldConfiguration({ shieldPublishableKey: walletConfig.shieldPublishableKey, shieldDebug: walletConfig.debug, + passkeyRpId: walletConfig.passkeyRpId, + passkeyRpName: walletConfig.passkeyRpName, }) : undefined, - overrides, + overrides: { + ...overrides, + ...(passkeyHandler && { passkeyHandler }), + }, thirdPartyAuth, }) - setDefaultClient(newClient) return newClient - }, [publishableKey, walletConfig, overrides]) + }, [publishableKey, walletConfig, overrides, thirdPartyAuth, passkeyHandler]) // Embedded state const [embeddedState, setEmbeddedState] = useState(EmbeddedState.NONE) diff --git a/src/hooks/core/index.ts b/src/hooks/core/index.ts index 8db6794..f9880e7 100644 --- a/src/hooks/core/index.ts +++ b/src/hooks/core/index.ts @@ -9,4 +9,7 @@ export { useOpenfort } from './useOpenfort' export { useOpenfortClient } from './useOpenfortClient' +export type { UsePasskeySupportOptions } from './usePasskeySupport' +export { usePasskeySupport } from './usePasskeySupport' + export { useUser } from './useUser' diff --git a/src/hooks/core/usePasskeySupport.ts b/src/hooks/core/usePasskeySupport.ts new file mode 100644 index 0000000..0e62330 --- /dev/null +++ b/src/hooks/core/usePasskeySupport.ts @@ -0,0 +1,43 @@ +import { useEffect, useState } from 'react' +import { isPasskeySupported } from '../../native/passkey' + +export type UsePasskeySupportOptions = { + /** Reserved for future use (e.g. RP config). Passkey support uses the library's isSupported() only. */ + rpId?: string + rpName?: string +} + +/** + * Hook to detect if the platform supports passkeys (WebAuthn). + * Uses the library's isSupported() only — no credential creation. + * + * @returns Object containing passkey support (isSupported, isPRFSupported set from the same check) + */ +export function usePasskeySupport(_options?: UsePasskeySupportOptions) { + const [isSupported, setIsSupported] = useState(false) + const [isPRFSupported, setIsPRFSupported] = useState(false) + const [isLoading, setIsLoading] = useState(true) + + useEffect(() => { + async function checkSupport() { + try { + const available = await isPasskeySupported() + setIsSupported(available) + setIsPRFSupported(available) + } catch { + setIsSupported(false) + setIsPRFSupported(false) + } finally { + setIsLoading(false) + } + } + + checkSupport() + }, []) + + return { + isSupported, + isPRFSupported, + isLoading, + } +} diff --git a/src/hooks/wallet/utils.ts b/src/hooks/wallet/utils.ts index 80f230d..e0a143e 100644 --- a/src/hooks/wallet/utils.ts +++ b/src/hooks/wallet/utils.ts @@ -81,9 +81,35 @@ async function resolveEncryptionSession( * @internal */ export async function buildRecoveryParams( - options: { recoveryPassword?: string; otpCode?: string; userId?: string } | undefined, + options: + | { + recoveryPassword?: string + otpCode?: string + userId?: string + recoveryMethod?: 'automatic' | 'password' | 'passkey' + passkeyId?: string + } + | undefined, walletConfig?: EmbeddedWalletConfiguration ): Promise { + // If passkey recovery method is explicitly requested + if (options?.recoveryMethod === 'passkey') { + // If passkeyId is provided, use it for recovery + if (options.passkeyId) { + return { + recoveryMethod: RecoveryMethod.PASSKEY, + passkeyInfo: { + passkeyId: options.passkeyId, + }, + } + } + // If no passkeyId, this is a creation request - SDK will create the passkey + return { + recoveryMethod: RecoveryMethod.PASSKEY, + } + } + + // If password is provided, use password recovery if (options?.recoveryPassword) { return { recoveryMethod: RecoveryMethod.PASSWORD, @@ -91,6 +117,7 @@ export async function buildRecoveryParams( } } + // Default to automatic recovery return { recoveryMethod: RecoveryMethod.AUTOMATIC, encryptionSession: await resolveEncryptionSession(walletConfig, options?.otpCode, options?.userId), diff --git a/src/native/index.ts b/src/native/index.ts index 25122f4..be12869 100644 --- a/src/native/index.ts +++ b/src/native/index.ts @@ -1,5 +1,4 @@ // WebView integration - export type { AppleAuthResult, OAuthResult, @@ -14,6 +13,9 @@ export { openOAuthSession, parseOAuthUrl, } from './oauth' +export type { NativePasskeyHandlerConfig, PasskeysAPI } from './passkey' +// Passkey handler and support checks +export { isPasskeySupported, NativePasskeyHandler } from './passkey' export type { SecureStorageMessage, SecureStorageResponse, diff --git a/src/native/passkey.ts b/src/native/passkey.ts new file mode 100644 index 0000000..a1b790e --- /dev/null +++ b/src/native/passkey.ts @@ -0,0 +1,380 @@ +import type { IPasskeyHandler } from '@openfort/openfort-js' + +/** Resolved API from react-native-passkeys (module.Passkeys ?? module). Library may export sync or async isSupported. */ +export type PasskeysAPI = { + create?: (options: any) => Promise + get?: (options: any) => Promise + /** Sync on native (iOS/Android), sync on web; may be function or boolean. */ + isSupported?: (() => boolean) | (() => Promise) | boolean +} + +let passkeysModule: (PasskeysAPI & { Passkeys?: PasskeysAPI }) | null = null +let passkeysLoadAttempted = false +let passkeysLoadError: Error | null = null + +/** + * Returns the passkeys API (create, get, isSupported). Resolves module.Passkeys ?? module once. + * Returns null if the module failed to load. + */ +function getPasskeysAPI(): PasskeysAPI | null { + if (passkeysLoadAttempted) { + return passkeysLoadError ? null : passkeysModule ? (passkeysModule.Passkeys ?? passkeysModule) : null + } + passkeysLoadAttempted = true + try { + passkeysModule = require('react-native-passkeys') + return passkeysModule ? (passkeysModule.Passkeys ?? passkeysModule) : null + } catch (error) { + passkeysLoadError = error instanceof Error ? error : new Error(String(error)) + return null + } +} + +/** + * Checks if the device supports passkeys (WebAuthn). Uses the library's isSupported() only — no credential creation. + * Normalizes sync/async and function/boolean from react-native-passkeys. + */ +export async function isPasskeySupported(): Promise { + const api = getPasskeysAPI() + if (!api || api.isSupported == null) { + return false + } + const supported = api.isSupported + if (typeof supported === 'boolean') { + return supported + } + if (typeof supported === 'function') { + const result = supported() + return result instanceof Promise ? result : Promise.resolve(result) + } + return false +} + +export interface NativePasskeyHandlerConfig { + rpId?: string + rpName?: string + timeoutMillis?: number + derivedKeyLengthBytes?: number + extractableKey?: boolean +} + +// Type definitions for react-native-passkeys +interface PublicKeyCredentialCreationOptions { + challenge: string + rp: { id: string; name: string } + user: { id: string; name: string; displayName: string } + pubKeyCredParams: Array<{ type: string; alg: number }> + authenticatorSelection: { + authenticatorAttachment?: string + residentKey?: string + requireResidentKey?: boolean + userVerification?: string + } + excludeCredentials?: Array<{ id: string; type: string }> // Iteration 14: Android might require this explicitly + extensions?: { prf?: { eval?: { first: string } } } + timeout?: number + attestation?: string +} + +interface PublicKeyCredentialRequestOptions { + challenge: string + rpId: string + allowCredentials: Array<{ id: string; type: string }> + userVerification: string + extensions?: { prf?: { eval?: { first: string } } } +} + +/** + * NativePasskeyHandler implements IPasskeyHandler using react-native-passkeys (create/get) + * as the native equivalent of navigator.credentials.create/get. Same contract as openfort-js + * PasskeyHandler; key is returned to the SDK/Shield like on web. + */ +export class NativePasskeyHandler implements IPasskeyHandler { + private readonly iValidByteLengths: number[] = [16, 24, 32] + private readonly rpId?: string + private readonly rpName?: string + private readonly timeoutMillis: number + private readonly derivedKeyLengthBytes: number + private readonly extractableKey: boolean + + constructor(config: NativePasskeyHandlerConfig) { + this.rpId = config.rpId + this.rpName = config.rpName + this.timeoutMillis = config.timeoutMillis ?? 60_000 + this.derivedKeyLengthBytes = config.derivedKeyLengthBytes ?? 32 + this.extractableKey = config.extractableKey ?? true + + if (!this.iValidByteLengths.includes(this.derivedKeyLengthBytes)) { + throw new Error(`Invalid key byte length ${this.derivedKeyLengthBytes}`) + } + } + + private getChallengeBytes(): Uint8Array { + return crypto.getRandomValues(new Uint8Array(32)) as Uint8Array + } + + private base64ToArrayBuffer(base64: string): ArrayBuffer { + // Handle both base64 and base64url (WebAuthn uses base64url) + const base64url = base64.replace(/-/g, '+').replace(/_/g, '/') + const binary = atob(base64url) + const bytes = new Uint8Array(binary.length) + for (let i = 0; i < binary.length; i++) { + bytes[i] = binary.charCodeAt(i) + } + return bytes.buffer + } + + /** + * Normalizes prf.results.first from the native module to Uint8Array. + * On Android, the bridge may return base64 string or array of numbers; crypto.subtle.importKey + * requires a BufferSource (e.g. Uint8Array) and some React Native polyfills reject plain ArrayBuffer. + */ + private normalizePRFResultFirst(first: unknown): Uint8Array { + if (typeof first === 'string') { + const buffer = this.base64ToArrayBuffer(first) + const out = new Uint8Array(buffer) + return out + } + if (first instanceof ArrayBuffer) { + const out = new Uint8Array(first) + return out + } + if (ArrayBuffer.isView(first)) { + const out = new Uint8Array(first.buffer, first.byteOffset, first.byteLength) + return out + } + if (Array.isArray(first) || (typeof first === 'object' && first !== null && 'length' in first)) { + const out = new Uint8Array(first as ArrayLike) + return out + } + throw new Error('PRF result first: expected base64 string, ArrayBuffer, TypedArray, or array of numbers') + } + + /** + * Converts ArrayBuffer to base64url (URL-safe base64) as required by WebAuthn spec + */ + private arrayBufferToBase64URL(buffer: ArrayBuffer | ArrayBufferLike): string { + const bytes = new Uint8Array(buffer) + const base64 = btoa(String.fromCharCode(...bytes)) + // Convert to base64url: replace + with -, / with _, and remove padding = + return base64.replace(/\+/g, '-').replace(/\//g, '_').replace(/=/g, '') + } + + /** + * Converts standard base64 to base64url (for credential id from openfort when passed to react-native-passkeys) + */ + private base64ToBase64URL(base64: string): string { + return base64.replace(/\+/g, '-').replace(/\//g, '_').replace(/=/g, '') + } + + /** + * Returns true when Web Crypto subtle API is available (e.g. browser). + * In React Native, crypto.subtle is typically undefined. + */ + private hasSubtle(): boolean { + return typeof globalThis.crypto !== 'undefined' && typeof globalThis.crypto.subtle !== 'undefined' + } + + /** + * Produces raw key bytes from PRF result when crypto.subtle is unavailable (React Native). + * Truncates to derivedKeyLengthBytes or pads with zeros if shorter. + */ + private getRawKeyBytes(prfResult: ArrayBuffer | Uint8Array): Uint8Array { + const bytes = prfResult instanceof Uint8Array ? prfResult : new Uint8Array(prfResult) + if (bytes.length >= this.derivedKeyLengthBytes) { + return bytes.slice(0, this.derivedKeyLengthBytes) + } + const key = new Uint8Array(this.derivedKeyLengthBytes) + key.set(bytes) + return key + } + + /** + * Derives a CryptoKey from PRF result (from normalizePRFResultFirst). Key data is a standalone Uint8Array + * accepted by crypto.subtle.importKey. + */ + private async deriveFromPRFResult(prfResult: Uint8Array): Promise { + const keyBytes = this.getRawKeyBytes(prfResult) + const keyData = new Uint8Array(this.derivedKeyLengthBytes) + keyData.set(keyBytes.subarray(0, this.derivedKeyLengthBytes)) + const algo = { name: 'AES-CBC', length: this.derivedKeyLengthBytes * 8 } + const usages: KeyUsage[] = ['encrypt', 'decrypt'] + return crypto.subtle.importKey('raw', keyData, algo, this.extractableKey, usages) + } + + async createPasskey(config: { + id: string + displayName: string + seed: string + }): Promise<{ id: string; displayName?: string; key?: Uint8Array }> { + if (!this.rpId || !this.rpName) { + throw new Error('rpId and rpName must be configured') + } + + const challenge = this.getChallengeBytes() + // Android Credentials API requires base64url for challenge + const challengeBase64URL = this.arrayBufferToBase64URL(challenge.buffer) + const userIdBytes = new TextEncoder().encode(config.id) + // Android Credentials API requires base64url for user.id + const userIdBase64URL = this.arrayBufferToBase64URL(userIdBytes.buffer) + + const publicKey: PublicKeyCredentialCreationOptions = { + challenge: challengeBase64URL, // base64url for Android + rp: { id: this.rpId, name: this.rpName }, + user: { + id: userIdBase64URL, // base64url for Android + name: config.id, + displayName: config.displayName, + }, + pubKeyCredParams: [ + { type: 'public-key', alg: -7 }, + { type: 'public-key', alg: -257 }, + ], + authenticatorSelection: { + residentKey: 'required', + userVerification: 'required', + }, + excludeCredentials: [], // Empty array for new passkey creation + // PRF extension: react-native-passkeys expects all inputs as base64url (challenge, user.id, prf.eval.first) + extensions: { + prf: { + eval: { + first: this.arrayBufferToBase64URL(new TextEncoder().encode(config.seed).buffer), + }, + }, + }, + timeout: this.timeoutMillis, + attestation: 'none', // Iteration 13: Using "none" per Android docs examples + } + + const api = getPasskeysAPI() + if (!api?.create || typeof api.create !== 'function') { + throw new Error('react-native-passkeys module not available or create not available') + } + const credential = await api.create(publicKey as any) + if (!credential) { + throw new Error('could not create passkey') + } + + const prfResults = credential.clientExtensionResults?.prf + if (!prfResults || !prfResults.results?.first) { + throw new Error('PRF extension not supported or missing results') + } + + const prfResultBytes = this.normalizePRFResultFirst(prfResults.results.first) + + let key: Uint8Array | undefined + if (this.hasSubtle()) { + const derivedKey = await this.deriveFromPRFResult(prfResultBytes) + if (this.extractableKey) { + key = new Uint8Array(await crypto.subtle.exportKey('raw', derivedKey)) + } + } else { + if (this.extractableKey) { + key = this.getRawKeyBytes(prfResultBytes) + } + } + // RN→WebView uses JSON.stringify. Return plain array cast to Uint8Array for interface; JSON sends [n,n,...]. + // Shield (iframe) must convert received key to Uint8Array before crypto.subtle.importKey (e.g. new Uint8Array(key)). + return { + id: credential.id, + displayName: config.displayName, + key: key != null ? new Uint8Array(key) : undefined, + } + } + + async deriveKey(config: { id: string; seed: string }): Promise { + if (!this.rpId) { + throw new Error('rpId must be configured') + } + + const challenge = this.getChallengeBytes() + const challengeBase64URL = this.arrayBufferToBase64URL(challenge.buffer) + // openfort may store credential id as standard base64; react-native-passkeys expects base64url + const credentialId = + config.id.includes('+') || config.id.includes('/') ? this.base64ToBase64URL(config.id) : config.id + + const publicKey: PublicKeyCredentialRequestOptions = { + challenge: challengeBase64URL, + rpId: this.rpId, + allowCredentials: [{ id: credentialId, type: 'public-key' }], + userVerification: 'required', + extensions: { + prf: { + eval: { + first: this.arrayBufferToBase64URL(new TextEncoder().encode(config.seed).buffer), + }, + }, + }, + } + + const api = getPasskeysAPI() + if (!api?.get || typeof api.get !== 'function') { + throw new Error('react-native-passkeys is not available. Please ensure it is installed and the app is rebuilt.') + } + const assertion = await api.get(publicKey as any) + if (!assertion) { + throw new Error('could not get passkey assertion') + } + + const prfResults = assertion.clientExtensionResults?.prf + if (!prfResults || !prfResults.results?.first) { + throw new Error('PRF extension not supported or missing results') + } + + const prfResultBytes = this.normalizePRFResultFirst(prfResults.results.first) + if (this.hasSubtle()) { + return this.deriveFromPRFResult(prfResultBytes) + } + throw new Error('deriveKey (CryptoKey) is not supported in React Native; passkey recovery uses deriveAndExportKey.') + } + + async deriveAndExportKey(config: { id: string; seed: string }): Promise { + if (!this.extractableKey) { + throw new Error('Derived keys cannot be exported if extractableKey is not set to true') + } + if (this.hasSubtle()) { + const derivedKey = await this.deriveKey(config) + const key = new Uint8Array(await crypto.subtle.exportKey('raw', derivedKey)) + // Return as plain array so it survives JSON when sent to the Shield iframe (RN→WebView). + return Array.from(key) as unknown as Uint8Array + } + // React Native path: get assertion and use raw PRF bytes (same flow as deriveKey up to buffer) + if (!this.rpId) { + throw new Error('rpId must be configured') + } + const challenge = this.getChallengeBytes() + const challengeBase64URL = this.arrayBufferToBase64URL(challenge.buffer) + const credentialId = + config.id.includes('+') || config.id.includes('/') ? this.base64ToBase64URL(config.id) : config.id + const publicKey: PublicKeyCredentialRequestOptions = { + challenge: challengeBase64URL, + rpId: this.rpId, + allowCredentials: [{ id: credentialId, type: 'public-key' }], + userVerification: 'required', + extensions: { + prf: { + eval: { + first: this.arrayBufferToBase64URL(new TextEncoder().encode(config.seed).buffer), + }, + }, + }, + } + const api = getPasskeysAPI() + if (!api?.get || typeof api.get !== 'function') { + throw new Error('react-native-passkeys is not available. Please ensure it is installed and the app is rebuilt.') + } + const assertion = await api.get(publicKey as any) + if (!assertion) { + throw new Error('could not get passkey assertion') + } + const prfResults = assertion.clientExtensionResults?.prf + if (!prfResults || !prfResults.results?.first) { + throw new Error('PRF extension not supported or missing results') + } + const prfResultBytes = this.normalizePRFResultFirst(prfResults.results.first) + const key = this.getRawKeyBytes(prfResultBytes) + // Return as plain array so it survives JSON when sent to the Shield iframe (RN→WebView). + return new Uint8Array(key) + } +} diff --git a/src/native/webview.tsx b/src/native/webview.tsx index 92818de..ad110f8 100644 --- a/src/native/webview.tsx +++ b/src/native/webview.tsx @@ -9,6 +9,33 @@ import WebView from 'react-native-webview' import { logger } from '../lib/logger' import { handleSecureStorageMessage, isSecureStorageMessage } from './storage' +/** + * Normalizes passkey key from serialized Uint8Array format {0:n, 1:n, ...} to number[] + * This handles JSON.stringify behavior in React Native where Uint8Array becomes an object + */ +function normalizePasskeyKey(key: unknown): number[] | unknown { + if (key && typeof key === 'object' && !Array.isArray(key)) { + return Object.values(key as Record) + } + return key +} + +/** + * Transforms outgoing message to normalize passkey.key format for iframe compatibility + */ +function transformMessage(message: string): string { + try { + const parsed = JSON.parse(message) + if (parsed?.args?.[0]?.passkey?.key) { + parsed.args[0].passkey.key = normalizePasskeyKey(parsed.args[0].passkey.key) + return JSON.stringify(parsed) + } + } catch { + /* keep original message */ + } + return message +} + /** * Props for the EmbeddedWalletWebView component */ @@ -68,10 +95,10 @@ export const EmbeddedWalletWebView: React.FC = ({ // Set up WebView reference with client immediately when both are available useEffect(() => { if (webViewRef.current) { - // Message poster with Uint8Array preprocessing for React Native + // Message poster with passkey key normalization for React Native const messagePoster = { postMessage: (message: string) => { - webViewRef.current?.postMessage(message) + webViewRef.current?.postMessage(transformMessage(message)) }, } client.embeddedWallet.setMessagePoster(messagePoster) @@ -110,7 +137,7 @@ export const EmbeddedWalletWebView: React.FC = ({ if (ref) { const messagePoster = { postMessage: (message: string) => { - ref.postMessage(message) + ref.postMessage(transformMessage(message)) }, } client.embeddedWallet.setMessagePoster(messagePoster) @@ -196,7 +223,11 @@ export const WebViewUtils = { * @param message - JSON string message to validate * @returns Validation result with parsed data or error information */ - validateMessage(message: string): { isValid: boolean; data?: any; error?: string } { + validateMessage(message: string): { + isValid: boolean + data?: any + error?: string + } { try { const parsed = JSON.parse(message) diff --git a/src/types/wallet.ts b/src/types/wallet.ts index a3d3dca..2e1c307 100644 --- a/src/types/wallet.ts +++ b/src/types/wallet.ts @@ -163,6 +163,10 @@ export type CreateEthereumWalletOptions = { otpCode?: string accountType?: AccountTypeEnum policyId?: string + /** Recovery method to use: 'automatic', 'password', or 'passkey' */ + recoveryMethod?: 'automatic' | 'password' | 'passkey' + /** Passkey ID for passkey recovery (required when recoveryMethod is 'passkey' for recovery) */ + passkeyId?: string } & OpenfortHookOptions /** @@ -183,6 +187,10 @@ export type SetActiveEthereumWalletOptions = { recoveryPassword?: string /** OTP code for Shield verification when using automatic recovery */ otpCode?: string + /** Recovery method to use: 'automatic', 'password', or 'passkey' */ + recoveryMethod?: 'automatic' | 'password' | 'passkey' + /** Passkey ID for passkey recovery (required when recoveryMethod is 'passkey' for recovery) */ + passkeyId?: string } & OpenfortHookOptions /** @@ -221,6 +229,10 @@ export type CreateSolanaEmbeddedWalletOpts = { * Create additional wallet if one already exists */ createAdditional?: boolean + /** Recovery method to use: 'automatic', 'password', or 'passkey' */ + recoveryMethod?: 'automatic' | 'password' | 'passkey' + /** Passkey ID for passkey recovery (required when recoveryMethod is 'passkey' for recovery) */ + passkeyId?: string } /** @@ -254,6 +266,10 @@ export type SetActiveSolanaWalletOptions = { recoveryPassword?: string /** OTP code for Shield verification when using automatic recovery */ otpCode?: string + /** Recovery method to use: 'automatic', 'password', or 'passkey' */ + recoveryMethod?: 'automatic' | 'password' | 'passkey' + /** Passkey ID for passkey recovery (required when recoveryMethod is 'passkey' for recovery) */ + passkeyId?: string } & OpenfortHookOptions // ============================================================================ From 396f0e1224b26bdfa94ea3a0199306b81366429b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Antoni=20Gal=C3=AD?= Date: Mon, 2 Feb 2026 16:31:41 +0100 Subject: [PATCH 02/10] chore: update @openfort/openfort-js dependency and refactor passkey handling - Updated the @openfort/openfort-js dependency to a new version. - Refactored passkey handling in NativePasskeyHandler to utilize PasskeyUtils for validation and conversion. - Removed obsolete normalization functions in webview handling. --- package.json | 2 +- pnpm-lock.yaml | 10 +-- src/native/passkey.ts | 162 ++++++++++++++++++++--------------------- src/native/webview.tsx | 40 +--------- 4 files changed, 88 insertions(+), 126 deletions(-) diff --git a/package.json b/package.json index 46a556c..7a706e3 100644 --- a/package.json +++ b/package.json @@ -40,7 +40,7 @@ } }, "dependencies": { - "@openfort/openfort-js": "https://pkg.pr.new/@openfort/openfort-js@f589f41", + "@openfort/openfort-js": "https://pkg.pr.new/@openfort/openfort-js@e6f2ed0", "react-native-passkeys": "0.4.0" }, "peerDependencies": { diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 8fcb06d..6d5cda7 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -13,8 +13,8 @@ importers: .: dependencies: '@openfort/openfort-js': - specifier: https://pkg.pr.new/@openfort/openfort-js@f589f41 - version: https://pkg.pr.new/@openfort/openfort-js@f589f41 + specifier: https://pkg.pr.new/@openfort/openfort-js@e6f2ed0 + version: https://pkg.pr.new/@openfort/openfort-js@e6f2ed0 react-native-passkeys: specifier: 0.4.0 version: 0.4.0(react-native@0.77.1(@babel/core@7.28.6)(@types/react@18.3.27)(react@18.3.1))(react@18.3.1) @@ -1012,8 +1012,8 @@ packages: resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} engines: {node: '>= 8'} - '@openfort/openfort-js@https://pkg.pr.new/@openfort/openfort-js@f589f41': - resolution: {tarball: https://pkg.pr.new/@openfort/openfort-js@f589f41} + '@openfort/openfort-js@https://pkg.pr.new/@openfort/openfort-js@e6f2ed0': + resolution: {tarball: https://pkg.pr.new/@openfort/openfort-js@e6f2ed0} version: 1.1.4 '@openfort/shield-js@0.1.34': @@ -4317,7 +4317,7 @@ snapshots: '@nodelib/fs.scandir': 2.1.5 fastq: 1.20.1 - '@openfort/openfort-js@https://pkg.pr.new/@openfort/openfort-js@f589f41': + '@openfort/openfort-js@https://pkg.pr.new/@openfort/openfort-js@e6f2ed0': dependencies: '@ethersproject/abi': 5.8.0 '@ethersproject/bytes': 5.8.0 diff --git a/src/native/passkey.ts b/src/native/passkey.ts index a1b790e..adc0514 100644 --- a/src/native/passkey.ts +++ b/src/native/passkey.ts @@ -1,4 +1,4 @@ -import type { IPasskeyHandler } from '@openfort/openfort-js' +import { type IPasskeyHandler, PasskeyUtils } from '@openfort/openfort-js' /** Resolved API from react-native-passkeys (module.Passkeys ?? module). Library may export sync or async isSupported. */ export type PasskeysAPI = { @@ -90,7 +90,6 @@ interface PublicKeyCredentialRequestOptions { * PasskeyHandler; key is returned to the SDK/Shield like on web. */ export class NativePasskeyHandler implements IPasskeyHandler { - private readonly iValidByteLengths: number[] = [16, 24, 32] private readonly rpId?: string private readonly rpName?: string private readonly timeoutMillis: number @@ -104,24 +103,7 @@ export class NativePasskeyHandler implements IPasskeyHandler { this.derivedKeyLengthBytes = config.derivedKeyLengthBytes ?? 32 this.extractableKey = config.extractableKey ?? true - if (!this.iValidByteLengths.includes(this.derivedKeyLengthBytes)) { - throw new Error(`Invalid key byte length ${this.derivedKeyLengthBytes}`) - } - } - - private getChallengeBytes(): Uint8Array { - return crypto.getRandomValues(new Uint8Array(32)) as Uint8Array - } - - private base64ToArrayBuffer(base64: string): ArrayBuffer { - // Handle both base64 and base64url (WebAuthn uses base64url) - const base64url = base64.replace(/-/g, '+').replace(/_/g, '/') - const binary = atob(base64url) - const bytes = new Uint8Array(binary.length) - for (let i = 0; i < binary.length; i++) { - bytes[i] = binary.charCodeAt(i) - } - return bytes.buffer + PasskeyUtils.validateKeyByteLength(this.derivedKeyLengthBytes) } /** @@ -131,42 +113,20 @@ export class NativePasskeyHandler implements IPasskeyHandler { */ private normalizePRFResultFirst(first: unknown): Uint8Array { if (typeof first === 'string') { - const buffer = this.base64ToArrayBuffer(first) - const out = new Uint8Array(buffer) - return out + return PasskeyUtils.base64URLToUint8Array(first) } if (first instanceof ArrayBuffer) { - const out = new Uint8Array(first) - return out + return new Uint8Array(first) } if (ArrayBuffer.isView(first)) { - const out = new Uint8Array(first.buffer, first.byteOffset, first.byteLength) - return out + return new Uint8Array(first.buffer, first.byteOffset, first.byteLength) } if (Array.isArray(first) || (typeof first === 'object' && first !== null && 'length' in first)) { - const out = new Uint8Array(first as ArrayLike) - return out + return new Uint8Array(first as ArrayLike) } throw new Error('PRF result first: expected base64 string, ArrayBuffer, TypedArray, or array of numbers') } - /** - * Converts ArrayBuffer to base64url (URL-safe base64) as required by WebAuthn spec - */ - private arrayBufferToBase64URL(buffer: ArrayBuffer | ArrayBufferLike): string { - const bytes = new Uint8Array(buffer) - const base64 = btoa(String.fromCharCode(...bytes)) - // Convert to base64url: replace + with -, / with _, and remove padding = - return base64.replace(/\+/g, '-').replace(/\//g, '_').replace(/=/g, '') - } - - /** - * Converts standard base64 to base64url (for credential id from openfort when passed to react-native-passkeys) - */ - private base64ToBase64URL(base64: string): string { - return base64.replace(/\+/g, '-').replace(/\//g, '_').replace(/=/g, '') - } - /** * Returns true when Web Crypto subtle API is available (e.g. browser). * In React Native, crypto.subtle is typically undefined. @@ -180,13 +140,7 @@ export class NativePasskeyHandler implements IPasskeyHandler { * Truncates to derivedKeyLengthBytes or pads with zeros if shorter. */ private getRawKeyBytes(prfResult: ArrayBuffer | Uint8Array): Uint8Array { - const bytes = prfResult instanceof Uint8Array ? prfResult : new Uint8Array(prfResult) - if (bytes.length >= this.derivedKeyLengthBytes) { - return bytes.slice(0, this.derivedKeyLengthBytes) - } - const key = new Uint8Array(this.derivedKeyLengthBytes) - key.set(bytes) - return key + return PasskeyUtils.extractRawKeyBytes(prfResult, this.derivedKeyLengthBytes) } /** @@ -202,21 +156,25 @@ export class NativePasskeyHandler implements IPasskeyHandler { return crypto.subtle.importKey('raw', keyData, algo, this.extractableKey, usages) } - async createPasskey(config: { + /** + * Creates a passkey and returns the key as base64url string (JSON-friendly for React Native WebView). + * This is the preferred method for React Native. + */ + async createNativePasskey(config: { id: string displayName: string seed: string - }): Promise<{ id: string; displayName?: string; key?: Uint8Array }> { + }): Promise<{ id: string; displayName?: string; key?: string }> { if (!this.rpId || !this.rpName) { throw new Error('rpId and rpName must be configured') } - const challenge = this.getChallengeBytes() + const challenge = PasskeyUtils.generateChallenge() // Android Credentials API requires base64url for challenge - const challengeBase64URL = this.arrayBufferToBase64URL(challenge.buffer) + const challengeBase64URL = PasskeyUtils.arrayBufferToBase64URL(challenge) const userIdBytes = new TextEncoder().encode(config.id) // Android Credentials API requires base64url for user.id - const userIdBase64URL = this.arrayBufferToBase64URL(userIdBytes.buffer) + const userIdBase64URL = PasskeyUtils.arrayBufferToBase64URL(userIdBytes) const publicKey: PublicKeyCredentialCreationOptions = { challenge: challengeBase64URL, // base64url for Android @@ -239,7 +197,7 @@ export class NativePasskeyHandler implements IPasskeyHandler { extensions: { prf: { eval: { - first: this.arrayBufferToBase64URL(new TextEncoder().encode(config.seed).buffer), + first: PasskeyUtils.arrayBufferToBase64URL(new TextEncoder().encode(config.seed)), }, }, }, @@ -263,23 +221,41 @@ export class NativePasskeyHandler implements IPasskeyHandler { const prfResultBytes = this.normalizePRFResultFirst(prfResults.results.first) - let key: Uint8Array | undefined + let keyBase64URL: string | undefined if (this.hasSubtle()) { const derivedKey = await this.deriveFromPRFResult(prfResultBytes) if (this.extractableKey) { - key = new Uint8Array(await crypto.subtle.exportKey('raw', derivedKey)) + const keyBytes = new Uint8Array(await crypto.subtle.exportKey('raw', derivedKey)) + keyBase64URL = PasskeyUtils.arrayBufferToBase64URL(keyBytes) } } else { if (this.extractableKey) { - key = this.getRawKeyBytes(prfResultBytes) + const keyBytes = this.getRawKeyBytes(prfResultBytes) + keyBase64URL = PasskeyUtils.arrayBufferToBase64URL(keyBytes) } } - // RN→WebView uses JSON.stringify. Return plain array cast to Uint8Array for interface; JSON sends [n,n,...]. - // Shield (iframe) must convert received key to Uint8Array before crypto.subtle.importKey (e.g. new Uint8Array(key)). + return { id: credential.id, displayName: config.displayName, - key: key != null ? new Uint8Array(key) : undefined, + key: keyBase64URL, + } + } + + /** + * Creates a passkey and returns the key as Uint8Array (for interface compliance). + * Note: The SDK prefers createNativePasskey() which returns base64url for better JSON serialization. + */ + async createPasskey(config: { + id: string + displayName: string + seed: string + }): Promise<{ id: string; displayName?: string; key?: Uint8Array }> { + const result = await this.createNativePasskey(config) + return { + id: result.id, + displayName: result.displayName, + key: result.key ? PasskeyUtils.base64URLToUint8Array(result.key) : undefined, } } @@ -288,11 +264,11 @@ export class NativePasskeyHandler implements IPasskeyHandler { throw new Error('rpId must be configured') } - const challenge = this.getChallengeBytes() - const challengeBase64URL = this.arrayBufferToBase64URL(challenge.buffer) + const challenge = PasskeyUtils.generateChallenge() + const challengeBase64URL = PasskeyUtils.arrayBufferToBase64URL(challenge) // openfort may store credential id as standard base64; react-native-passkeys expects base64url const credentialId = - config.id.includes('+') || config.id.includes('/') ? this.base64ToBase64URL(config.id) : config.id + config.id.includes('+') || config.id.includes('/') ? PasskeyUtils.base64ToBase64URL(config.id) : config.id const publicKey: PublicKeyCredentialRequestOptions = { challenge: challengeBase64URL, @@ -302,7 +278,7 @@ export class NativePasskeyHandler implements IPasskeyHandler { extensions: { prf: { eval: { - first: this.arrayBufferToBase64URL(new TextEncoder().encode(config.seed).buffer), + first: PasskeyUtils.arrayBufferToBase64URL(new TextEncoder().encode(config.seed)), }, }, }, @@ -329,24 +305,23 @@ export class NativePasskeyHandler implements IPasskeyHandler { throw new Error('deriveKey (CryptoKey) is not supported in React Native; passkey recovery uses deriveAndExportKey.') } - async deriveAndExportKey(config: { id: string; seed: string }): Promise { + /** + * Derives and exports a key as base64url string (JSON-friendly for React Native WebView). + * This is the preferred method for React Native. + */ + async deriveAndExportNativeKey(config: { id: string; seed: string }): Promise { if (!this.extractableKey) { throw new Error('Derived keys cannot be exported if extractableKey is not set to true') } - if (this.hasSubtle()) { - const derivedKey = await this.deriveKey(config) - const key = new Uint8Array(await crypto.subtle.exportKey('raw', derivedKey)) - // Return as plain array so it survives JSON when sent to the Shield iframe (RN→WebView). - return Array.from(key) as unknown as Uint8Array - } - // React Native path: get assertion and use raw PRF bytes (same flow as deriveKey up to buffer) if (!this.rpId) { throw new Error('rpId must be configured') } - const challenge = this.getChallengeBytes() - const challengeBase64URL = this.arrayBufferToBase64URL(challenge.buffer) + + const challenge = PasskeyUtils.generateChallenge() + const challengeBase64URL = PasskeyUtils.arrayBufferToBase64URL(challenge) const credentialId = - config.id.includes('+') || config.id.includes('/') ? this.base64ToBase64URL(config.id) : config.id + config.id.includes('+') || config.id.includes('/') ? PasskeyUtils.base64ToBase64URL(config.id) : config.id + const publicKey: PublicKeyCredentialRequestOptions = { challenge: challengeBase64URL, rpId: this.rpId, @@ -355,11 +330,12 @@ export class NativePasskeyHandler implements IPasskeyHandler { extensions: { prf: { eval: { - first: this.arrayBufferToBase64URL(new TextEncoder().encode(config.seed).buffer), + first: PasskeyUtils.arrayBufferToBase64URL(new TextEncoder().encode(config.seed)), }, }, }, } + const api = getPasskeysAPI() if (!api?.get || typeof api.get !== 'function') { throw new Error('react-native-passkeys is not available. Please ensure it is installed and the app is rebuilt.') @@ -368,13 +344,31 @@ export class NativePasskeyHandler implements IPasskeyHandler { if (!assertion) { throw new Error('could not get passkey assertion') } + const prfResults = assertion.clientExtensionResults?.prf if (!prfResults || !prfResults.results?.first) { throw new Error('PRF extension not supported or missing results') } + const prfResultBytes = this.normalizePRFResultFirst(prfResults.results.first) - const key = this.getRawKeyBytes(prfResultBytes) - // Return as plain array so it survives JSON when sent to the Shield iframe (RN→WebView). - return new Uint8Array(key) + + let keyBytes: Uint8Array + if (this.hasSubtle()) { + const derivedKey = await this.deriveFromPRFResult(prfResultBytes) + keyBytes = new Uint8Array(await crypto.subtle.exportKey('raw', derivedKey)) + } else { + keyBytes = this.getRawKeyBytes(prfResultBytes) + } + + return PasskeyUtils.arrayBufferToBase64URL(keyBytes) + } + + /** + * Derives and exports a key as Uint8Array (for interface compliance). + * Note: The SDK prefers deriveAndExportNativeKey() which returns base64url for better JSON serialization. + */ + async deriveAndExportKey(config: { id: string; seed: string }): Promise { + const keyBase64URL = await this.deriveAndExportNativeKey(config) + return PasskeyUtils.base64URLToUint8Array(keyBase64URL) } } diff --git a/src/native/webview.tsx b/src/native/webview.tsx index ad110f8..29dff14 100644 --- a/src/native/webview.tsx +++ b/src/native/webview.tsx @@ -9,33 +9,6 @@ import WebView from 'react-native-webview' import { logger } from '../lib/logger' import { handleSecureStorageMessage, isSecureStorageMessage } from './storage' -/** - * Normalizes passkey key from serialized Uint8Array format {0:n, 1:n, ...} to number[] - * This handles JSON.stringify behavior in React Native where Uint8Array becomes an object - */ -function normalizePasskeyKey(key: unknown): number[] | unknown { - if (key && typeof key === 'object' && !Array.isArray(key)) { - return Object.values(key as Record) - } - return key -} - -/** - * Transforms outgoing message to normalize passkey.key format for iframe compatibility - */ -function transformMessage(message: string): string { - try { - const parsed = JSON.parse(message) - if (parsed?.args?.[0]?.passkey?.key) { - parsed.args[0].passkey.key = normalizePasskeyKey(parsed.args[0].passkey.key) - return JSON.stringify(parsed) - } - } catch { - /* keep original message */ - } - return message -} - /** * Props for the EmbeddedWalletWebView component */ @@ -55,11 +28,7 @@ interface EmbeddedWalletWebViewProps { * * @param props - Component props, see {@link EmbeddedWalletWebViewProps} */ -export const EmbeddedWalletWebView: React.FC = ({ - client, - isClientReady, - onProxyStatusChange, -}) => { +export const EmbeddedWalletWebView: React.FC = ({ client, onProxyStatusChange }) => { const webViewRef = useRef(null) // Handle app state changes to monitor WebView health @@ -95,15 +64,14 @@ export const EmbeddedWalletWebView: React.FC = ({ // Set up WebView reference with client immediately when both are available useEffect(() => { if (webViewRef.current) { - // Message poster with passkey key normalization for React Native const messagePoster = { postMessage: (message: string) => { - webViewRef.current?.postMessage(transformMessage(message)) + webViewRef.current?.postMessage(message) }, } client.embeddedWallet.setMessagePoster(messagePoster) } - }, [client, isClientReady]) + }, [client]) // Clean message handler using the new penpal bridge const handleMessage = useCallback( @@ -137,7 +105,7 @@ export const EmbeddedWalletWebView: React.FC = ({ if (ref) { const messagePoster = { postMessage: (message: string) => { - ref.postMessage(transformMessage(message)) + ref.postMessage(message) }, } client.embeddedWallet.setMessagePoster(messagePoster) From 6f3d87527aa2bfdedbac1e1c41ff242582fb0e0e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Antoni=20Gal=C3=AD?= Date: Mon, 2 Feb 2026 17:09:24 +0100 Subject: [PATCH 03/10] refactor: improve wallet recovery method handling and code formatting - Enhanced recovery method detection for embedded wallets by auto-detecting from account details. - Improved code formatting for better readability in both Ethereum and Solana wallet hooks. - Updated recovery parameters to include effective recovery method and passkey ID where applicable. --- src/hooks/wallet/useEmbeddedEthereumWallet.ts | 62 ++++++++++++++++--- src/hooks/wallet/useEmbeddedSolanaWallet.ts | 55 ++++++++++++++-- 2 files changed, 104 insertions(+), 13 deletions(-) diff --git a/src/hooks/wallet/useEmbeddedEthereumWallet.ts b/src/hooks/wallet/useEmbeddedEthereumWallet.ts index 7ec5f87..711b28b 100644 --- a/src/hooks/wallet/useEmbeddedEthereumWallet.ts +++ b/src/hooks/wallet/useEmbeddedEthereumWallet.ts @@ -1,4 +1,10 @@ -import { AccountTypeEnum, ChainTypeEnum, type EmbeddedAccount, EmbeddedState } from '@openfort/openfort-js' +import { + AccountTypeEnum, + ChainTypeEnum, + type EmbeddedAccount, + EmbeddedState, + RecoveryMethod, +} from '@openfort/openfort-js' import { useCallback, useEffect, useMemo, useRef, useState } from 'react' import { useOpenfortContext } from '../../core/context' import { onError, onSuccess } from '../../lib/hookConsistency' @@ -215,7 +221,10 @@ export function useEmbeddedEthereumWallet(options: UseEmbeddedEthereumWalletOpti return policy } - return await client.embeddedWallet.getEthereumProvider({ announceProvider: false, policy: resolvePolicy() }) + return await client.embeddedWallet.getEthereumProvider({ + announceProvider: false, + policy: resolvePolicy(), + }) }, [client.embeddedWallet, walletConfig, options.chainId]) // Initialize provider when recovering an active wallet on mount @@ -346,7 +355,10 @@ export function useEmbeddedEthereumWallet(options: UseEmbeddedEthereumWalletOpti }) if (createOptions?.onSuccess) { - createOptions.onSuccess({ account: embeddedAccount, provider: ethProvider }) + createOptions.onSuccess({ + account: embeddedAccount, + provider: ethProvider, + }) } if (options.onCreateSuccess) { options.onCreateSuccess(embeddedAccount, ethProvider) @@ -449,8 +461,31 @@ export function useEmbeddedEthereumWallet(options: UseEmbeddedEthereumWalletOpti throw new OpenfortError(errorMsg, OpenfortErrorType.WALLET_ERROR) } + // Auto-detect recovery method from account if not explicitly provided + let effectiveRecoveryMethod = setActiveOptions.recoveryMethod + let effectivePasskeyId = setActiveOptions.passkeyId + + if (!effectiveRecoveryMethod && embeddedAccountToRecover.recoveryMethod) { + if (embeddedAccountToRecover.recoveryMethod === RecoveryMethod.PASSKEY) { + effectiveRecoveryMethod = 'passkey' + if (!effectivePasskeyId) { + effectivePasskeyId = embeddedAccountToRecover.recoveryMethodDetails?.passkeyId + } + } else if (embeddedAccountToRecover.recoveryMethod === RecoveryMethod.PASSWORD) { + effectiveRecoveryMethod = 'password' + } + } + // Build recovery params - const recoveryParams = await buildRecoveryParams({ ...setActiveOptions, userId: user?.id }, walletConfig) + const recoveryParams = await buildRecoveryParams( + { + ...setActiveOptions, + userId: user?.id, + recoveryMethod: effectiveRecoveryMethod, + passkeyId: effectivePasskeyId, + }, + walletConfig + ) // Recover the embedded wallet const embeddedAccount = await client.embeddedWallet.recover({ @@ -610,11 +645,20 @@ export function useEmbeddedEthereumWallet(options: UseEmbeddedEthereumWalletOpti } if (status.status === 'connecting' || status.status === 'reconnecting' || status.status === 'loading') { - return { ...baseActions, status: 'connecting', activeWallet: activeWallet! } + return { + ...baseActions, + status: 'connecting', + activeWallet: activeWallet!, + } } if (status.status === 'error') { - return { ...baseActions, status: 'error', activeWallet, error: status.error?.message || 'Unknown error' } + return { + ...baseActions, + status: 'error', + activeWallet, + error: status.error?.message || 'Unknown error', + } } // Priority 2: Check authentication state from context @@ -631,7 +675,11 @@ export function useEmbeddedEthereumWallet(options: UseEmbeddedEthereumWalletOpti if (activeAccount && !provider) { // Have wallet but provider not initialized yet (mount recovery in progress) - return { ...baseActions, status: 'connecting', activeWallet: activeWallet! } + return { + ...baseActions, + status: 'connecting', + activeWallet: activeWallet!, + } } // Default: disconnected (authenticated but no wallet selected) diff --git a/src/hooks/wallet/useEmbeddedSolanaWallet.ts b/src/hooks/wallet/useEmbeddedSolanaWallet.ts index b21e83a..cf47999 100644 --- a/src/hooks/wallet/useEmbeddedSolanaWallet.ts +++ b/src/hooks/wallet/useEmbeddedSolanaWallet.ts @@ -1,4 +1,10 @@ -import { AccountTypeEnum, ChainTypeEnum, type EmbeddedAccount, EmbeddedState } from '@openfort/openfort-js' +import { + AccountTypeEnum, + ChainTypeEnum, + type EmbeddedAccount, + EmbeddedState, + RecoveryMethod, +} from '@openfort/openfort-js' import { useCallback, useEffect, useMemo, useRef, useState } from 'react' import { useOpenfortContext } from '../../core/context' import { onError, onSuccess } from '../../lib/hookConsistency' @@ -261,7 +267,9 @@ export function useEmbeddedSolanaWallet(options: UseEmbeddedSolanaWalletOptions }, signMessage: async (message: string): Promise => { // Sign message using openfort-js (with hashMessage: false for Solana) - const result = await client.embeddedWallet.signMessage(message, { hashMessage: false }) + const result = await client.embeddedWallet.signMessage(message, { + hashMessage: false, + }) return result }, }) @@ -331,7 +339,11 @@ export function useEmbeddedSolanaWallet(options: UseEmbeddedSolanaWalletOptions // Build recovery params (only use recoveryPassword, otpCode, and userId, ignore createAdditional) const recoveryParams = await buildRecoveryParams( createOptions?.recoveryPassword || createOptions?.otpCode || user?.id - ? { recoveryPassword: createOptions?.recoveryPassword, otpCode: createOptions?.otpCode, userId: user?.id } + ? { + recoveryPassword: createOptions?.recoveryPassword, + otpCode: createOptions?.otpCode, + userId: user?.id, + } : undefined, walletConfig ) @@ -364,7 +376,10 @@ export function useEmbeddedSolanaWallet(options: UseEmbeddedSolanaWalletOptions }) if (createOptions?.onSuccess) { - createOptions.onSuccess({ account: embeddedAccount, provider: solProvider }) + createOptions.onSuccess({ + account: embeddedAccount, + provider: solProvider, + }) } if (options.onCreateSuccess) { options.onCreateSuccess(embeddedAccount, solProvider) @@ -439,8 +454,31 @@ export function useEmbeddedSolanaWallet(options: UseEmbeddedSolanaWalletOptions ) } + // Auto-detect recovery method from account if not explicitly provided + let effectiveRecoveryMethod = setActiveOptions.recoveryMethod + let effectivePasskeyId = setActiveOptions.passkeyId + + if (!effectiveRecoveryMethod && embeddedAccountToRecover.recoveryMethod) { + if (embeddedAccountToRecover.recoveryMethod === RecoveryMethod.PASSKEY) { + effectiveRecoveryMethod = 'passkey' + if (!effectivePasskeyId) { + effectivePasskeyId = embeddedAccountToRecover.recoveryMethodDetails?.passkeyId + } + } else if (embeddedAccountToRecover.recoveryMethod === RecoveryMethod.PASSWORD) { + effectiveRecoveryMethod = 'password' + } + } + // Build recovery params - const recoveryParams = await buildRecoveryParams({ ...setActiveOptions, userId: user?.id }, walletConfig) + const recoveryParams = await buildRecoveryParams( + { + ...setActiveOptions, + userId: user?.id, + recoveryMethod: effectiveRecoveryMethod, + passkeyId: effectivePasskeyId, + }, + walletConfig + ) // Recover the embedded wallet const embeddedAccount = await client.embeddedWallet.recover({ @@ -551,7 +589,12 @@ export function useEmbeddedSolanaWallet(options: UseEmbeddedSolanaWalletOptions } if (status.status === 'error') { - return { ...baseActions, status: 'error', activeWallet, error: status.error?.message || 'Unknown error' } + return { + ...baseActions, + status: 'error', + activeWallet, + error: status.error?.message || 'Unknown error', + } } // Priority 2: Check authentication state from context From 1562a2d3b84ccf371a33a158de5ffdf20619060d Mon Sep 17 00:00:00 2001 From: Jaume Alavedra Date: Thu, 5 Feb 2026 11:27:21 +0100 Subject: [PATCH 04/10] chore: update lock --- package.json | 2 +- pnpm-lock.yaml | 1192 ++++++++++++++++++++--------------------- src/core/provider.tsx | 1 - src/native/passkey.ts | 189 ++----- 4 files changed, 631 insertions(+), 753 deletions(-) diff --git a/package.json b/package.json index 7a706e3..66e1b96 100644 --- a/package.json +++ b/package.json @@ -40,7 +40,7 @@ } }, "dependencies": { - "@openfort/openfort-js": "https://pkg.pr.new/@openfort/openfort-js@e6f2ed0", + "@openfort/openfort-js": "https://pkg.pr.new/@openfort/openfort-js@224", "react-native-passkeys": "0.4.0" }, "peerDependencies": { diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 6d5cda7..a7e0ce3 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -13,21 +13,21 @@ importers: .: dependencies: '@openfort/openfort-js': - specifier: https://pkg.pr.new/@openfort/openfort-js@e6f2ed0 - version: https://pkg.pr.new/@openfort/openfort-js@e6f2ed0 + specifier: https://pkg.pr.new/@openfort/openfort-js@224 + version: https://pkg.pr.new/@openfort/openfort-js@224 react-native-passkeys: specifier: 0.4.0 - version: 0.4.0(react-native@0.77.1(@babel/core@7.28.6)(@types/react@18.3.27)(react@18.3.1))(react@18.3.1) + version: 0.4.0(react-native@0.77.1(@babel/core@7.29.0)(@types/react@18.3.27)(react@18.3.1))(react@18.3.1) devDependencies: '@biomejs/biome': specifier: ^2.2.4 - version: 2.3.11 + version: 2.3.14 '@changesets/changelog-github': specifier: ^0.5.1 version: 0.5.2 '@changesets/cli': specifier: ^2.29.7 - version: 2.29.8(@types/node@25.0.9) + version: 2.29.8(@types/node@25.2.0) '@size-limit/preset-small-lib': specifier: ^11.2.0 version: 11.2.0(size-limit@11.2.0) @@ -39,7 +39,7 @@ importers: version: 5.7.1 expo-apple-authentication: specifier: ^7.2.4 - version: 7.2.4(react-native@0.77.1(@babel/core@7.28.6)(@types/react@18.3.27)(react@18.3.1)) + version: 7.2.4(react-native@0.77.1(@babel/core@7.29.0)(@types/react@18.3.27)(react@18.3.1)) expo-application: specifier: ^6.1.4 version: 6.1.5 @@ -48,25 +48,25 @@ importers: version: 14.0.2 expo-linking: specifier: ^7.1.5 - version: 7.1.7(react-native@0.77.1(@babel/core@7.28.6)(@types/react@18.3.27)(react@18.3.1))(react@18.3.1) + version: 7.1.7(react-native@0.77.1(@babel/core@7.29.0)(@types/react@18.3.27)(react@18.3.1))(react@18.3.1) expo-secure-store: specifier: ^14.2.3 version: 14.2.4 expo-web-browser: specifier: ^14.1.6 - version: 14.2.0(react-native@0.77.1(@babel/core@7.28.6)(@types/react@18.3.27)(react@18.3.1)) + version: 14.2.0(react-native@0.77.1(@babel/core@7.29.0)(@types/react@18.3.27)(react@18.3.1)) knip: specifier: ^5.69.1 - version: 5.82.1(@types/node@25.0.9)(typescript@5.9.3) + version: 5.83.0(@types/node@25.2.0)(typescript@5.9.3) react: specifier: ^18.3.1 version: 18.3.1 react-native: specifier: 0.77.1 - version: 0.77.1(@babel/core@7.28.6)(@types/react@18.3.27)(react@18.3.1) + version: 0.77.1(@babel/core@7.29.0)(@types/react@18.3.27)(react@18.3.1) react-native-webview: specifier: ^13.15.0 - version: 13.16.0(react-native@0.77.1(@babel/core@7.28.6)(@types/react@18.3.27)(react@18.3.1))(react@18.3.1) + version: 13.16.0(react-native@0.77.1(@babel/core@7.29.0)(@types/react@18.3.27)(react@18.3.1))(react@18.3.1) size-limit: specifier: ^11.2.0 version: 11.2.0 @@ -82,20 +82,20 @@ packages: '@babel/code-frame@7.10.4': resolution: {integrity: sha512-vG6SvB6oYEhvgisZNFRmRCUkLz11c7rp+tbNTynGqc6mS1d5ATd/sGyV6W0KZZnXRKMTzZDRgQT3Ou9jhpAfUg==} - '@babel/code-frame@7.28.6': - resolution: {integrity: sha512-JYgintcMjRiCvS8mMECzaEn+m3PfoQiyqukOMCCVQtoJGYJw8j/8LBJEiqkHLkfwCcs74E3pbAUFNg7d9VNJ+Q==} + '@babel/code-frame@7.29.0': + resolution: {integrity: sha512-9NhCeYjq9+3uxgdtp20LSiJXJvN0FeCtNGpJxuMFZ1Kv3cWUNb6DOhJwUvcVCzKGR66cw4njwM6hrJLqgOwbcw==} engines: {node: '>=6.9.0'} - '@babel/compat-data@7.28.6': - resolution: {integrity: sha512-2lfu57JtzctfIrcGMz992hyLlByuzgIk58+hhGCxjKZ3rWI82NnVLjXcaTqkI2NvlcvOskZaiZ5kjUALo3Lpxg==} + '@babel/compat-data@7.29.0': + resolution: {integrity: sha512-T1NCJqT/j9+cn8fvkt7jtwbLBfLC/1y1c7NtCeXFRgzGTsafi68MRv8yzkYSapBnFA6L3U2VSc02ciDzoAJhJg==} engines: {node: '>=6.9.0'} - '@babel/core@7.28.6': - resolution: {integrity: sha512-H3mcG6ZDLTlYfaSNi0iOKkigqMFvkTKlGUYlD8GW7nNOYRrevuA46iTypPyv+06V3fEmvvazfntkBU34L0azAw==} + '@babel/core@7.29.0': + resolution: {integrity: sha512-CGOfOJqWjg2qW/Mb6zNsDm+u5vFQ8DxXfbM09z69p5Z6+mE1ikP2jUXw+j42Pf1XTYED2Rni5f95npYeuwMDQA==} engines: {node: '>=6.9.0'} - '@babel/generator@7.28.6': - resolution: {integrity: sha512-lOoVRwADj8hjf7al89tvQ2a1lf53Z+7tiXMgpZJL3maQPDxh0DgLMN62B2MKUOFcoodBHLMbDM6WAbKgNy5Suw==} + '@babel/generator@7.29.0': + resolution: {integrity: sha512-vSH118/wwM/pLR38g/Sgk05sNtro6TlTJKuiMXDaZqPUfjTFcudpCOt00IhOfj+1BFAX+UFAlzCU+6WXr3GLFQ==} engines: {node: '>=6.9.0'} '@babel/helper-annotate-as-pure@7.27.3': @@ -118,8 +118,8 @@ packages: peerDependencies: '@babel/core': ^7.0.0 - '@babel/helper-define-polyfill-provider@0.6.5': - resolution: {integrity: sha512-uJnGFcPsWQK8fvjgGP5LZUZZsYGIoPeRjSF5PGwrelYgq7Q15/Ft9NGFp1zglwgIv//W0uG4BevRuSJRyylZPg==} + '@babel/helper-define-polyfill-provider@0.6.6': + resolution: {integrity: sha512-mOAsxeeKkUKayvZR3HeTYD/fICpCPLJrU5ZjelT/PA6WHtNDBOE436YiaEUvHN454bRM3CebhDsIpieCc4texA==} peerDependencies: '@babel/core': ^7.4.0 || ^8.0.0-0 <8.0.0 @@ -189,8 +189,8 @@ packages: resolution: {integrity: sha512-llL88JShoCsth8fF8R4SJnIn+WLvR6ccFxu1H3FlMhDontdcmZWf2HgIZ7AIqV3Xcck1idlohrN4EUBQz6klbw==} engines: {node: '>=6.9.0'} - '@babel/parser@7.28.6': - resolution: {integrity: sha512-TeR9zWR18BvbfPmGbLampPMW+uW1NZnJlRuuHso8i87QZNq2JRF9i6RgxRqtEq+wQGsS19NNTWr2duhnE49mfQ==} + '@babel/parser@7.29.0': + resolution: {integrity: sha512-IyDgFV5GeDUVX4YdF/3CPULtVGSXXMLh1xVIgdCgxApktqnQV0r7/8Nqthg+8YLGaAtdyIlo2qIdZrbCv4+7ww==} engines: {node: '>=6.0.0'} hasBin: true @@ -314,8 +314,8 @@ packages: peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-async-generator-functions@7.28.6': - resolution: {integrity: sha512-9knsChgsMzBV5Yh3kkhrZNxH3oCYAfMBkNNaVN4cP2RVlFPe8wYdwwcnOsAbkdDoV9UjFtOXWrWB52M8W4jNeA==} + '@babel/plugin-transform-async-generator-functions@7.29.0': + resolution: {integrity: sha512-va0VdWro4zlBr2JsXC+ofCPB2iG12wPtVGTWFx2WLDOM3nYQZZIGP82qku2eW/JR83sD+k2k+CsNtyEbUqhU6w==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 @@ -392,8 +392,8 @@ packages: peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-named-capturing-groups-regex@7.27.1': - resolution: {integrity: sha512-SstR5JYy8ddZvD6MhV0tM/j16Qds4mIpJTOd1Yu9J9pJjH93bxHECF7pgtc28XvkzTD6Pxcm/0Z73Hvk7kb3Ng==} + '@babel/plugin-transform-named-capturing-groups-regex@7.29.0': + resolution: {integrity: sha512-1CZQA5KNAD6ZYQLPw7oi5ewtDNxH/2vuCh+6SmvgDfhumForvs8a1o9n0UrEoBD8HU4djO2yWngTQlXl1NDVEQ==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0 @@ -470,14 +470,14 @@ packages: peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-regenerator@7.28.6': - resolution: {integrity: sha512-eZhoEZHYQLL5uc1gS5e9/oTknS0sSSAtd5TkKMUp3J+S/CaUjagc0kOUPsEbDmMeva0nC3WWl4SxVY6+OBuxfw==} + '@babel/plugin-transform-regenerator@7.29.0': + resolution: {integrity: sha512-FijqlqMA7DmRdg/aINBSs04y8XNTYw/lr1gJ2WsmBnnaNw1iS43EPkJW+zK7z65auG3AWRFXWj+NcTQwYptUog==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-runtime@7.28.5': - resolution: {integrity: sha512-20NUVgOrinudkIBzQ2bNxP08YpKprUkRTiRSd2/Z5GOdPImJGkoN4Z7IQe1T5AdyKI1i5L6RBmluqdSzvaq9/w==} + '@babel/plugin-transform-runtime@7.29.0': + resolution: {integrity: sha512-jlaRT5dJtMaMCV6fAuLbsQMSwz/QkvaHOHOSXRitGGwSpR1blCY4KUKoyP2tYO8vJcqYe8cEj96cqSztv3uF9w==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 @@ -538,67 +538,67 @@ packages: resolution: {integrity: sha512-YA6Ma2KsCdGb+WC6UpBVFJGXL58MDA6oyONbjyF/+5sBgxY/dwkhLogbMT2GXXyU84/IhRw/2D1Os1B/giz+BQ==} engines: {node: '>=6.9.0'} - '@babel/traverse@7.28.6': - resolution: {integrity: sha512-fgWX62k02qtjqdSNTAGxmKYY/7FSL9WAS1o2Hu5+I5m9T0yxZzr4cnrfXQ/MX0rIifthCSs6FKTlzYbJcPtMNg==} + '@babel/traverse@7.29.0': + resolution: {integrity: sha512-4HPiQr0X7+waHfyXPZpWPfWL/J7dcN1mx9gL6WdQVMbPnF3+ZhSMs8tCxN7oHddJE9fhNE7+lxdnlyemKfJRuA==} engines: {node: '>=6.9.0'} - '@babel/types@7.28.6': - resolution: {integrity: sha512-0ZrskXVEHSWIqZM/sQZ4EV3jZJXRkio/WCxaqKZP1g//CEWEPSfeZFcms4XeKBCHU0ZKnIkdJeU/kF+eRp5lBg==} + '@babel/types@7.29.0': + resolution: {integrity: sha512-LwdZHpScM4Qz8Xw2iKSzS+cfglZzJGvofQICy7W7v4caru4EaAmyUuO6BGrbyQ2mYV11W0U8j5mBhd14dd3B0A==} engines: {node: '>=6.9.0'} - '@biomejs/biome@2.3.11': - resolution: {integrity: sha512-/zt+6qazBWguPG6+eWmiELqO+9jRsMZ/DBU3lfuU2ngtIQYzymocHhKiZRyrbra4aCOoyTg/BmY+6WH5mv9xmQ==} + '@biomejs/biome@2.3.14': + resolution: {integrity: sha512-QMT6QviX0WqXJCaiqVMiBUCr5WRQ1iFSjvOLoTk6auKukJMvnMzWucXpwZB0e8F00/1/BsS9DzcKgWH+CLqVuA==} engines: {node: '>=14.21.3'} hasBin: true - '@biomejs/cli-darwin-arm64@2.3.11': - resolution: {integrity: sha512-/uXXkBcPKVQY7rc9Ys2CrlirBJYbpESEDme7RKiBD6MmqR2w3j0+ZZXRIL2xiaNPsIMMNhP1YnA+jRRxoOAFrA==} + '@biomejs/cli-darwin-arm64@2.3.14': + resolution: {integrity: sha512-UJGPpvWJMkLxSRtpCAKfKh41Q4JJXisvxZL8ChN1eNW3m/WlPFJ6EFDCE7YfUb4XS8ZFi3C1dFpxUJ0Ety5n+A==} engines: {node: '>=14.21.3'} cpu: [arm64] os: [darwin] - '@biomejs/cli-darwin-x64@2.3.11': - resolution: {integrity: sha512-fh7nnvbweDPm2xEmFjfmq7zSUiox88plgdHF9OIW4i99WnXrAC3o2P3ag9judoUMv8FCSUnlwJCM1B64nO5Fbg==} + '@biomejs/cli-darwin-x64@2.3.14': + resolution: {integrity: sha512-PNkLNQG6RLo8lG7QoWe/hhnMxJIt1tEimoXpGQjwS/dkdNiKBLPv4RpeQl8o3s1OKI3ZOR5XPiYtmbGGHAOnLA==} engines: {node: '>=14.21.3'} cpu: [x64] os: [darwin] - '@biomejs/cli-linux-arm64-musl@2.3.11': - resolution: {integrity: sha512-XPSQ+XIPZMLaZ6zveQdwNjbX+QdROEd1zPgMwD47zvHV+tCGB88VH+aynyGxAHdzL+Tm/+DtKST5SECs4iwCLg==} + '@biomejs/cli-linux-arm64-musl@2.3.14': + resolution: {integrity: sha512-LInRbXhYujtL3sH2TMCH/UBwJZsoGwfQjBrMfl84CD4hL/41C/EU5mldqf1yoFpsI0iPWuU83U+nB2TUUypWeg==} engines: {node: '>=14.21.3'} cpu: [arm64] os: [linux] libc: [musl] - '@biomejs/cli-linux-arm64@2.3.11': - resolution: {integrity: sha512-l4xkGa9E7Uc0/05qU2lMYfN1H+fzzkHgaJoy98wO+b/7Gl78srbCRRgwYSW+BTLixTBrM6Ede5NSBwt7rd/i6g==} + '@biomejs/cli-linux-arm64@2.3.14': + resolution: {integrity: sha512-KT67FKfzIw6DNnUNdYlBg+eU24Go3n75GWK6NwU4+yJmDYFe9i/MjiI+U/iEzKvo0g7G7MZqoyrhIYuND2w8QQ==} engines: {node: '>=14.21.3'} cpu: [arm64] os: [linux] libc: [glibc] - '@biomejs/cli-linux-x64-musl@2.3.11': - resolution: {integrity: sha512-vU7a8wLs5C9yJ4CB8a44r12aXYb8yYgBn+WeyzbMjaCMklzCv1oXr8x+VEyWodgJt9bDmhiaW/I0RHbn7rsNmw==} + '@biomejs/cli-linux-x64-musl@2.3.14': + resolution: {integrity: sha512-KQU7EkbBBuHPW3/rAcoiVmhlPtDSGOGRPv9js7qJVpYTzjQmVR+C9Rfcz+ti8YCH+zT1J52tuBybtP4IodjxZQ==} engines: {node: '>=14.21.3'} cpu: [x64] os: [linux] libc: [musl] - '@biomejs/cli-linux-x64@2.3.11': - resolution: {integrity: sha512-/1s9V/H3cSe0r0Mv/Z8JryF5x9ywRxywomqZVLHAoa/uN0eY7F8gEngWKNS5vbbN/BsfpCG5yeBT5ENh50Frxg==} + '@biomejs/cli-linux-x64@2.3.14': + resolution: {integrity: sha512-ZsZzQsl9U+wxFrGGS4f6UxREUlgHwmEfu1IrXlgNFrNnd5Th6lIJr8KmSzu/+meSa9f4rzFrbEW9LBBA6ScoMA==} engines: {node: '>=14.21.3'} cpu: [x64] os: [linux] libc: [glibc] - '@biomejs/cli-win32-arm64@2.3.11': - resolution: {integrity: sha512-PZQ6ElCOnkYapSsysiTy0+fYX+agXPlWugh6+eQ6uPKI3vKAqNp6TnMhoM3oY2NltSB89hz59o8xIfOdyhi9Iw==} + '@biomejs/cli-win32-arm64@2.3.14': + resolution: {integrity: sha512-+IKYkj/pUBbnRf1G1+RlyA3LWiDgra1xpS7H2g4BuOzzRbRB+hmlw0yFsLprHhbbt7jUzbzAbAjK/Pn0FDnh1A==} engines: {node: '>=14.21.3'} cpu: [arm64] os: [win32] - '@biomejs/cli-win32-x64@2.3.11': - resolution: {integrity: sha512-43VrG813EW+b5+YbDbz31uUsheX+qFKCpXeY9kfdAx+ww3naKxeVkTD9zLIWxUPfJquANMHrmW3wbe/037G0Qg==} + '@biomejs/cli-win32-x64@2.3.14': + resolution: {integrity: sha512-oizCjdyQ3WJEswpb3Chdngeat56rIdSYK12JI3iI11Mt5T5EXcZ7WLuowzEaFPNJ3zmOQFliMN8QY1Pi+qsfdQ==} engines: {node: '>=14.21.3'} cpu: [x64] os: [win32] @@ -916,8 +916,8 @@ packages: '@expo/sdk-runtime-versions@1.0.0': resolution: {integrity: sha512-Doz2bfiPndXYFPMRwPyGa1k5QaKDVpY806UJj570epIiMzWaYyCtobasyfC++qfIXVb5Ocy7r3tP9d62hAQ7IQ==} - '@gerrit0/mini-shiki@3.21.0': - resolution: {integrity: sha512-9PrsT5DjZA+w3lur/aOIx3FlDeHdyCEFlv9U+fmsVyjPZh61G5SYURQ/1ebe2U63KbDmI2V8IhIUegWb8hjOyg==} + '@gerrit0/mini-shiki@3.22.0': + resolution: {integrity: sha512-jMpciqEVUBKE1QwU64S4saNMzpsSza6diNCk4MWAeCxO2+LFi2FIFmL2S0VDLzEJCxuvCbU783xi8Hp/gkM5CQ==} '@inquirer/external-editor@1.0.3': resolution: {integrity: sha512-RWbSrDiYmO4LbejWY7ttpxczuwQyZLBUyygsA9Nsv95hpzUWwnNTVQmAq3xuh7vNwCp07UTmE5i11XAEExx4RA==} @@ -932,8 +932,8 @@ packages: resolution: {integrity: sha512-yzMTt9lEb8Gv7zRioUilSglI0c0smZ9k5D65677DLWLtWJaXIS3CqcGyUFByYKlnUj6TkjLVs54fBl6+TiGQDQ==} engines: {node: 20 || >=22} - '@isaacs/brace-expansion@5.0.0': - resolution: {integrity: sha512-ZT55BDLV0yv0RBm2czMiZ+SqCGO7AvmOM3G/w2xhVPH+te0aKgFjmBvGlL1dH+ql2tgGO3MVrbb3jCKyvpgnxA==} + '@isaacs/brace-expansion@5.0.1': + resolution: {integrity: sha512-WMz71T1JS624nWj2n2fnYAuPovhv7EUhk69R6i9dsVyzxt5eM3bjwvgk9L+APE1TRscGysAVMANkB0jh0LQZrQ==} engines: {node: 20 || >=22} '@isaacs/ttlcache@1.4.1': @@ -1012,118 +1012,118 @@ packages: resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} engines: {node: '>= 8'} - '@openfort/openfort-js@https://pkg.pr.new/@openfort/openfort-js@e6f2ed0': - resolution: {tarball: https://pkg.pr.new/@openfort/openfort-js@e6f2ed0} + '@openfort/openfort-js@https://pkg.pr.new/@openfort/openfort-js@224': + resolution: {tarball: https://pkg.pr.new/@openfort/openfort-js@224} version: 1.1.4 '@openfort/shield-js@0.1.34': resolution: {integrity: sha512-bJxQc0zk0VPxk7CWSE5NZp5Bv8nYnStwG5GKXrS2A6hxEt0vf4BMu9db4IUiHxmgGaFWrdAnbSCSZ5AU1gwyew==} - '@oxc-resolver/binding-android-arm-eabi@11.16.3': - resolution: {integrity: sha512-CVyWHu6ACDqDcJxR4nmGiG8vDF4TISJHqRNzac5z/gPQycs/QrP/1pDsJBy0MD7jSw8nVq2E5WqeHQKabBG/Jg==} + '@oxc-resolver/binding-android-arm-eabi@11.17.0': + resolution: {integrity: sha512-kVnY21v0GyZ/+LG6EIO48wK3mE79BUuakHUYLIqobO/Qqq4mJsjuYXMSn3JtLcKZpN1HDVit4UHpGJHef1lrlw==} cpu: [arm] os: [android] - '@oxc-resolver/binding-android-arm64@11.16.3': - resolution: {integrity: sha512-tTIoB7plLeh2o6Ay7NnV5CJb6QUXdxI7Shnsp2ECrLSV81k+oVE3WXYrQSh4ltWL75i0OgU5Bj3bsuyg5SMepw==} + '@oxc-resolver/binding-android-arm64@11.17.0': + resolution: {integrity: sha512-Pf8e3XcsK9a8RHInoAtEcrwf2vp7V9bSturyUUYxw9syW6E7cGi7z9+6ADXxm+8KAevVfLA7pfBg8NXTvz/HOw==} cpu: [arm64] os: [android] - '@oxc-resolver/binding-darwin-arm64@11.16.3': - resolution: {integrity: sha512-OXKVH7uwYd3Rbw1s2yJZd6/w+6b01iaokZubYhDAq4tOYArr+YCS+lr81q1hsTPPRZeIsWE+rJLulmf1qHdYZA==} + '@oxc-resolver/binding-darwin-arm64@11.17.0': + resolution: {integrity: sha512-lVSgKt3biecofXVr8e1hnfX0IYMd4A6VCxmvOmHsFt5Zbmt0lkO4S2ap2bvQwYDYh5ghUNamC7M2L8K6vishhQ==} cpu: [arm64] os: [darwin] - '@oxc-resolver/binding-darwin-x64@11.16.3': - resolution: {integrity: sha512-WwjQ4WdnCxVYZYd3e3oY5XbV3JeLy9pPMK+eQQ2m8DtqUtbxnvPpAYC2Knv/2bS6q5JiktqOVJ2Hfia3OSo0/A==} + '@oxc-resolver/binding-darwin-x64@11.17.0': + resolution: {integrity: sha512-+/raxVJE1bo7R4fA9Yp0wm3slaCOofTEeUzM01YqEGcRDLHB92WRGjRhagMG2wGlvqFuSiTp81DwSbBVo/g6AQ==} cpu: [x64] os: [darwin] - '@oxc-resolver/binding-freebsd-x64@11.16.3': - resolution: {integrity: sha512-4OHKFGJBBfOnuJnelbCS4eBorI6cj54FUxcZJwEXPeoLc8yzORBoJ2w+fQbwjlQcUUZLEg92uGhKCRiUoqznjg==} + '@oxc-resolver/binding-freebsd-x64@11.17.0': + resolution: {integrity: sha512-x9Ks56n+n8h0TLhzA6sJXa2tGh3uvMGpBppg6PWf8oF0s5S/3p/J6k1vJJ9lIUtTmenfCQEGKnFokpRP4fLTLg==} cpu: [x64] os: [freebsd] - '@oxc-resolver/binding-linux-arm-gnueabihf@11.16.3': - resolution: {integrity: sha512-OM3W0NLt9u7uKwG/yZbeXABansZC0oZeDF1nKgvcZoRw4/Yak6/l4S0onBfDFeYMY94eYeAt2bl60e30lgsb5A==} + '@oxc-resolver/binding-linux-arm-gnueabihf@11.17.0': + resolution: {integrity: sha512-Wf3w07Ow9kXVJrS0zmsaFHKOGhXKXE8j1tNyy+qIYDsQWQ4UQZVx5SjlDTcqBnFerlp3Z3Is0RjmVzgoLG3qkA==} cpu: [arm] os: [linux] - '@oxc-resolver/binding-linux-arm-musleabihf@11.16.3': - resolution: {integrity: sha512-MRs7D7i1t7ACsAdTuP81gLZES918EpBmiUyEl8fu302yQB+4L7L7z0Ui8BWnthUTQd3nAU9dXvENLK/SqRVH8A==} + '@oxc-resolver/binding-linux-arm-musleabihf@11.17.0': + resolution: {integrity: sha512-N0OKA1al1gQ5Gm7Fui1RWlXaHRNZlwMoBLn3TVtSXX+WbnlZoVyDqqOqFL8+pVEHhhxEA2LR8kmM0JO6FAk6dg==} cpu: [arm] os: [linux] - '@oxc-resolver/binding-linux-arm64-gnu@11.16.3': - resolution: {integrity: sha512-0eVYZxSceNqGADzhlV4ZRqkHF0fjWxRXQOB7Qwl5y1gN/XYUDvMfip+ngtzj4dM7zQT4U97hUhJ7PUKSy/JIGQ==} + '@oxc-resolver/binding-linux-arm64-gnu@11.17.0': + resolution: {integrity: sha512-wdcQ7Niad9JpjZIGEeqKJnTvczVunqlZ/C06QzR5zOQNeLVRScQ9S5IesKWUAPsJQDizV+teQX53nTK+Z5Iy+g==} cpu: [arm64] os: [linux] libc: [glibc] - '@oxc-resolver/binding-linux-arm64-musl@11.16.3': - resolution: {integrity: sha512-B1BvLeZbgDdVN0FvU40l5Q7lej8310WlabCBaouk8jY7H7xbI8phtomTtk3Efmevgfy5hImaQJu6++OmcFb2NQ==} + '@oxc-resolver/binding-linux-arm64-musl@11.17.0': + resolution: {integrity: sha512-65B2/t39HQN5AEhkLsC+9yBD1iRUkKOIhfmJEJ7g6wQ9kylra7JRmNmALFjbsj0VJsoSQkpM8K07kUZuNJ9Kxw==} cpu: [arm64] os: [linux] libc: [musl] - '@oxc-resolver/binding-linux-ppc64-gnu@11.16.3': - resolution: {integrity: sha512-q7khglic3Jqak7uDgA3MFnjDeI7krQT595GDZpvFq785fmFYSx8rlTkoHzmhQtUisYtl4XG7WUscwsoidFUI4w==} + '@oxc-resolver/binding-linux-ppc64-gnu@11.17.0': + resolution: {integrity: sha512-kExgm3TLK21dNMmcH+xiYGbc6BUWvT03PUZ2aYn8mUzGPeeORklBhg3iYcaBI3ZQHB25412X1Z6LLYNjt4aIaA==} cpu: [ppc64] os: [linux] libc: [glibc] - '@oxc-resolver/binding-linux-riscv64-gnu@11.16.3': - resolution: {integrity: sha512-aFRNmQNPzDgQEbw2s3c8yJYRimacSDI+u9df8rn5nSKzTVitHmbEpZqfxpwNLCKIuLSNmozHR1z1OT+oZVeYqg==} + '@oxc-resolver/binding-linux-riscv64-gnu@11.17.0': + resolution: {integrity: sha512-1utUJC714/ydykZQE8c7QhpEyM4SaslMfRXxN9G61KYazr6ndt85LaubK3EZCSD50vVEfF4PVwFysCSO7LN9uA==} cpu: [riscv64] os: [linux] libc: [glibc] - '@oxc-resolver/binding-linux-riscv64-musl@11.16.3': - resolution: {integrity: sha512-vZI85SvSMADcEL9G1TIrV0Rlkc1fY5Mup0DdlVC5EHPysZB4hXXHpr+h09pjlK5y+5om5foIzDRxE1baUCaWOA==} + '@oxc-resolver/binding-linux-riscv64-musl@11.17.0': + resolution: {integrity: sha512-mayiYOl3LMmtO2CLn4I5lhanfxEo0LAqlT/EQyFbu1ZN3RS+Xa7Q3JEM0wBpVIyfO/pqFrjvC5LXw/mHNDEL7A==} cpu: [riscv64] os: [linux] libc: [musl] - '@oxc-resolver/binding-linux-s390x-gnu@11.16.3': - resolution: {integrity: sha512-xiLBnaUlddFEzRHiHiSGEMbkg8EwZY6VD8F+3GfnFsiK3xg/4boaUV2bwXd+nUzl3UDQOMW1QcZJ4jJSb0qiJA==} + '@oxc-resolver/binding-linux-s390x-gnu@11.17.0': + resolution: {integrity: sha512-Ow/yI+CrUHxIIhn/Y1sP/xoRKbCC3x9O1giKr3G/pjMe+TCJ5ZmfqVWU61JWwh1naC8X5Xa7uyLnbzyYqPsHfg==} cpu: [s390x] os: [linux] libc: [glibc] - '@oxc-resolver/binding-linux-x64-gnu@11.16.3': - resolution: {integrity: sha512-6y0b05wIazJJgwu7yU/AYGFswzQQudYJBOb/otDhiDacp1+6ye8egoxx63iVo9lSpDbipL++54AJQFlcOHCB+g==} + '@oxc-resolver/binding-linux-x64-gnu@11.17.0': + resolution: {integrity: sha512-Z4J7XlPMQOLPANyu6y3B3V417Md4LKH5bV6bhqgaG99qLHmU5LV2k9ErV14fSqoRc/GU/qOpqMdotxiJqN/YWg==} cpu: [x64] os: [linux] libc: [glibc] - '@oxc-resolver/binding-linux-x64-musl@11.16.3': - resolution: {integrity: sha512-RmMgwuMa42c9logS7Pjprf5KCp8J1a1bFiuBFtG9/+yMu0BhY2t+0VR/um7pwtkNFvIQqAVh6gDOg/PnoKRcdQ==} + '@oxc-resolver/binding-linux-x64-musl@11.17.0': + resolution: {integrity: sha512-0effK+8lhzXsgsh0Ny2ngdnTPF30v6QQzVFApJ1Ctk315YgpGkghkelvrLYYgtgeFJFrzwmOJ2nDvCrUFKsS2Q==} cpu: [x64] os: [linux] libc: [musl] - '@oxc-resolver/binding-openharmony-arm64@11.16.3': - resolution: {integrity: sha512-/7AYRkjjW7xu1nrHgWUFy99Duj4/ydOBVaHtODie9/M6fFngo+8uQDFFnzmr4q//sd/cchIerISp/8CQ5TsqIA==} + '@oxc-resolver/binding-openharmony-arm64@11.17.0': + resolution: {integrity: sha512-kFB48dRUW6RovAICZaxHKdtZe+e94fSTNA2OedXokzMctoU54NPZcv0vUX5PMqyikLIKJBIlW7laQidnAzNrDA==} cpu: [arm64] os: [openharmony] - '@oxc-resolver/binding-wasm32-wasi@11.16.3': - resolution: {integrity: sha512-urM6aIPbi5di4BSlnpd/TWtDJgG6RD06HvLBuNM+qOYuFtY1/xPbzQ2LanBI2ycpqIoIZwsChyplALwAMdyfCQ==} + '@oxc-resolver/binding-wasm32-wasi@11.17.0': + resolution: {integrity: sha512-a3elKSBLPT0OoRPxTkCIIc+4xnOELolEBkPyvdj01a6PSdSmyJ1NExWjWLaXnT6wBMblvKde5RmSwEi3j+jZpg==} engines: {node: '>=14.0.0'} cpu: [wasm32] - '@oxc-resolver/binding-win32-arm64-msvc@11.16.3': - resolution: {integrity: sha512-QuvLqGKf7frxWHQ5TnrcY0C/hJpANsaez99Q4dAk1hen7lDTD4FBPtBzPnntLFXeaVG3PnSmnVjlv0vMILwU7Q==} + '@oxc-resolver/binding-win32-arm64-msvc@11.17.0': + resolution: {integrity: sha512-4eszUsSDb9YVx0RtYkPWkxxtSZIOgfeiX//nG5cwRRArg178w4RCqEF1kbKPud9HPrp1rXh7gE4x911OhvTnPg==} cpu: [arm64] os: [win32] - '@oxc-resolver/binding-win32-ia32-msvc@11.16.3': - resolution: {integrity: sha512-QR/witXK6BmYTlEP8CCjC5fxeG5U9A6a50pNpC1nLnhAcJjtzFG8KcQ5etVy/XvCLiDc7fReaAWRNWtCaIhM8Q==} + '@oxc-resolver/binding-win32-ia32-msvc@11.17.0': + resolution: {integrity: sha512-t946xTXMmR7yGH0KAe9rB055/X4EPIu93JUvjchl2cizR5QbuwkUV7vLS2BS6x6sfvDoQb6rWYnV1HCci6tBSg==} cpu: [ia32] os: [win32] - '@oxc-resolver/binding-win32-x64-msvc@11.16.3': - resolution: {integrity: sha512-bFuJRKOscsDAEZ/a8BezcTMAe2BQ/OBRfuMLFUuINfTR5qGVcm4a3xBIrQVepBaPxFj16SJdRjGe05vDiwZmFw==} + '@oxc-resolver/binding-win32-x64-msvc@11.17.0': + resolution: {integrity: sha512-pX6s2kMXLQg+hlqKk5UqOW09iLLxnTkvn8ohpYp2Mhsm2yzDPCx9dyOHiB/CQixLzTkLQgWWJykN4Z3UfRKW4Q==} cpu: [x64] os: [win32] @@ -1212,23 +1212,23 @@ packages: resolution: {integrity: sha512-KX62+qIt4xgy8eHKHiikfhz2p5fOciXd0Cl+dNzhgPFq8klq4MGMNaf148GB3M/vBqP4nw/eFvRMAayFCgdRQw==} engines: {node: '>=18'} - '@shikijs/engine-oniguruma@3.21.0': - resolution: {integrity: sha512-OYknTCct6qiwpQDqDdf3iedRdzj6hFlOPv5hMvI+hkWfCKs5mlJ4TXziBG9nyabLwGulrUjHiCq3xCspSzErYQ==} + '@shikijs/engine-oniguruma@3.22.0': + resolution: {integrity: sha512-DyXsOG0vGtNtl7ygvabHd7Mt5EY8gCNqR9Y7Lpbbd/PbJvgWrqaKzH1JW6H6qFkuUa8aCxoiYVv8/YfFljiQxA==} - '@shikijs/langs@3.21.0': - resolution: {integrity: sha512-g6mn5m+Y6GBJ4wxmBYqalK9Sp0CFkUqfNzUy2pJglUginz6ZpWbaWjDB4fbQ/8SHzFjYbtU6Ddlp1pc+PPNDVA==} + '@shikijs/langs@3.22.0': + resolution: {integrity: sha512-x/42TfhWmp6H00T6uwVrdTJGKgNdFbrEdhaDwSR5fd5zhQ1Q46bHq9EO61SCEWJR0HY7z2HNDMaBZp8JRmKiIA==} - '@shikijs/themes@3.21.0': - resolution: {integrity: sha512-BAE4cr9EDiZyYzwIHEk7JTBJ9CzlPuM4PchfcA5ao1dWXb25nv6hYsoDiBq2aZK9E3dlt3WB78uI96UESD+8Mw==} + '@shikijs/themes@3.22.0': + resolution: {integrity: sha512-o+tlOKqsr6FE4+mYJG08tfCFDS+3CG20HbldXeVoyP+cYSUxDhrFf3GPjE60U55iOkkjbpY2uC3It/eeja35/g==} - '@shikijs/types@3.21.0': - resolution: {integrity: sha512-zGrWOxZ0/+0ovPY7PvBU2gIS9tmhSUUt30jAcNV0Bq0gb2S98gwfjIs1vxlmH5zM7/4YxLamT6ChlqqAJmPPjA==} + '@shikijs/types@3.22.0': + resolution: {integrity: sha512-491iAekgKDBFE67z70Ok5a8KBMsQ2IJwOWw3us/7ffQkIBCyOQfm/aNwVMBUriP02QshIfgHCBSIYAl3u2eWjg==} '@shikijs/vscode-textmate@10.0.2': resolution: {integrity: sha512-83yeghZ2xxin3Nj8z1NMd/NCuca+gsYXswywDy5bHvwlWL8tpTQmzGeUuHd9FC3E/SBEMvzJRwWEOz5gGes9Qg==} - '@sinclair/typebox@0.27.8': - resolution: {integrity: sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==} + '@sinclair/typebox@0.27.10': + resolution: {integrity: sha512-MTBk/3jGLNB2tVxv6uLlFh1iu64iYOQ2PbdOSK3NW8JZsmlaOh2q6sdtKowBhfw8QFLmYNzTW4/oK4uATIi6ZA==} '@sinonjs/commons@3.0.1': resolution: {integrity: sha512-K3mCHKQ9sVh8o1C9cxkwxaOmXoAMlDxC1mYyHrjqOWEcBjYr76t96zL2zlj5dUGZ3HSw240X1qgH3Mjf1yJWpQ==} @@ -1289,8 +1289,8 @@ packages: '@types/node@12.20.55': resolution: {integrity: sha512-J8xLz7q2OFulZ2cyGTLE1TbbZcjpno7FaN6zdJNrgAdrJ+DZzh/uFR6YrTb4C+nXakvud8Q4+rbhoIWlYQbUFQ==} - '@types/node@25.0.9': - resolution: {integrity: sha512-/rpCXHlCWeqClNBwUhDcusJxXYDjZTyE8v5oTO7WbL8eij2nKhUeU89/6xgjU7N4/Vh3He0BtyhJdQbDyhiXAw==} + '@types/node@25.2.0': + resolution: {integrity: sha512-DZ8VwRFUNzuqJ5khrvwMXHmvPe+zGayJhr2CDNiKB1WBE1ST8Djl00D0IC4vvNmHMdj6DlbYRIaFE7WHjlDl5w==} '@types/prop-types@15.7.15': resolution: {integrity: sha512-F6bEyamV9jKGAFBEmlQnesRPGOQqS2+Uwi0Em15xenOxHaf2hv6L8YCVn3rPdPJOiJfPiCnLIRyvwVaqMY3MIw==} @@ -1388,8 +1388,8 @@ packages: axios@1.12.2: resolution: {integrity: sha512-vMJzPewAlRyOgxV2dU0Cuz2O8zzzx9VYtbJOaBgXFeLc4IV/Eg50n4LowmehOOR61S8ZMpc2K5Sa7g6A4jfkUw==} - axios@1.13.2: - resolution: {integrity: sha512-VPk9ebNqPcy5lRGuSlKx752IlDatOjT9paPlm8A7yOuW2Fbvp4X3JznJtT4f0GzGLLiWE9W8onz51SqLYwzGaA==} + axios@1.13.4: + resolution: {integrity: sha512-1wVkUaAO6WyaYtCkcYCOx12ZgpGf9Zif+qXa4n+oYzK558YryKqiL6UWwd5DqiH3VRW0GYhTZQ/vlgJrCoNQlg==} babel-jest@29.7.0: resolution: {integrity: sha512-BrvGY3xZSwEcCzKvKsCi2GgHqDqsYkOP4/by5xCgIwGXQxIEh+8ew3gmrE1y7XRR6LHZIj6yLYnUi/mm2KXKBg==} @@ -1405,8 +1405,8 @@ packages: resolution: {integrity: sha512-ESAc/RJvGTFEzRwOTT4+lNDk/GNHMkKbNzsvT0qKRfDyyYTskxB5rnU2njIDYVxXCBHHEI1c0YwHob3WaYujOg==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - babel-plugin-polyfill-corejs2@0.4.14: - resolution: {integrity: sha512-Co2Y9wX854ts6U8gAAPXfn0GmAyctHuK8n0Yhfjd6t30g7yvKjspvvOo9yG+z52PZRgFErt7Ka2pYnXCjLKEpg==} + babel-plugin-polyfill-corejs2@0.4.15: + resolution: {integrity: sha512-hR3GwrRwHUfYwGfrisXPIDP3JcYfBrW7wKE7+Au6wDYl7fm/ka1NEII6kORzxNU556JjfidZeBsO10kYvtV1aw==} peerDependencies: '@babel/core': ^7.4.0 || ^8.0.0-0 <8.0.0 @@ -1415,8 +1415,8 @@ packages: peerDependencies: '@babel/core': ^7.4.0 || ^8.0.0-0 <8.0.0 - babel-plugin-polyfill-regenerator@0.6.5: - resolution: {integrity: sha512-ISqQ2frbiNU9vIJkzg7dlPpznPZ4jOiUQ1uSmB0fEHeowtN3COYRsXr/xexn64NpU13P06jc/L5TgiJXOgrbEg==} + babel-plugin-polyfill-regenerator@0.6.6: + resolution: {integrity: sha512-hYm+XLYRMvupxiQzrvXUj7YyvFFVfv5gI0R71AJzudg1g2AI2vyCPPIFEBjk162/wFzti3inBHo7isWFuEVS/A==} peerDependencies: '@babel/core': ^7.4.0 || ^8.0.0-0 <8.0.0 @@ -1443,8 +1443,8 @@ packages: base64-js@1.5.1: resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==} - baseline-browser-mapping@2.9.16: - resolution: {integrity: sha512-KeUZdBuxngy825i8xvzaK1Ncnkx0tBmb3k8DkEuqjKRkmtvNTjey2ZsNeh8Dw4lfKvbCOu9oeNx2TKm2vHqcRw==} + baseline-browser-mapping@2.9.19: + resolution: {integrity: sha512-ipDqC8FrAl/76p2SSWKSI+H9tFwm7vYqXQrItCuiVPt26Km0jS+NzSsBWAaBusvSbQcfJG+JitdMm+wZAgTYqg==} hasBin: true bech32@1.1.4: @@ -1526,8 +1526,8 @@ packages: resolution: {integrity: sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==} engines: {node: '>=10'} - caniuse-lite@1.0.30001765: - resolution: {integrity: sha512-LWcNtSyZrakjECqmpP4qdg0MMGdN368D7X8XvvAqOcqMv0RxnlqVKZl2V6/mBR68oYMxOZPLw/gO7DuisMHUvQ==} + caniuse-lite@1.0.30001767: + resolution: {integrity: sha512-34+zUAMhSH+r+9eKmYG+k2Rpt8XttfE4yXAjoZvkAPs15xcYQhyBYdalJ65BzivAvGRMViEjy6oKr/S91loekQ==} chalk@2.4.2: resolution: {integrity: sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==} @@ -1608,8 +1608,8 @@ packages: convert-source-map@2.0.0: resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==} - core-js-compat@3.47.0: - resolution: {integrity: sha512-IGfuznZ/n7Kp9+nypamBhvwdwLsW6KC8IOaURw2doAK5e98AG3acVLdh0woOnEqCfUtS+Vu882JE4k/DAm3ItQ==} + core-js-compat@3.48.0: + resolution: {integrity: sha512-OM4cAF3D6VtH/WkLtWvyNC56EZVXsZdU3iqaMG2B4WvYrlqU831pc4UtG5yp0sE9z8Y02wVN7PjW5Zf9Gt0f1Q==} cosmiconfig@5.2.1: resolution: {integrity: sha512-H65gsXo1SKjf8zmrJ67eJk8aIRKV5ff2D4uKZIBZShbhGSpEmsQOPW/SKMKYhSTrqR7ufy6RP69rPogdaPh/kA==} @@ -1685,8 +1685,8 @@ packages: ee-first@1.1.1: resolution: {integrity: sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==} - electron-to-chromium@1.5.267: - resolution: {integrity: sha512-0Drusm6MVRXSOJpGbaSVgcQsuB4hEkMpHXaVstcPmhu5LIedxs1xNK/nIxmQIU/RPC0+1/o0AVZfBTkTNJOdUw==} + electron-to-chromium@1.5.286: + resolution: {integrity: sha512-9tfDXhJ4RKFNerfjdCcZfufu49vg620741MNs26a9+bhLThdB+plgMeou98CAaHu/WATj2iHOOHTp1hWtABj2A==} elliptic@6.6.1: resolution: {integrity: sha512-RaddvvMatK2LJHqFJ+YA4WysVN5Ita9E35botqIYspQ4TkRAlCicdzKOjlyv/1Za5RyTNn7di//eEV0uTAfe3g==} @@ -1865,8 +1865,8 @@ packages: flow-enums-runtime@0.0.6: resolution: {integrity: sha512-3PYnM29RFXwvAN6Pc/scUfkI7RwhQ/xqyLUyPNlXUp9S40zI8nup9tUSrTLSVnWGBN38FNiGWbwZOB6uR4OGdw==} - flow-parser@0.297.0: - resolution: {integrity: sha512-51kjVLwebsDNCrBrm+VLBJ1rEZffrWzsEPjfbdhf/0lxQkX01zFoiojwEW7l6902p1ZQI/ju/QmLGowwne23lg==} + flow-parser@0.299.0: + resolution: {integrity: sha512-phGMRoNt6SNglPHGRbCyWm9/pxfe6t/t4++EIYPaBGWT6e0lphLBgUMrvpL62NbRo9R549o3oqrbKHq82kANCw==} engines: {node: '>=0.4.0'} follow-redirects@1.15.11: @@ -1938,13 +1938,13 @@ packages: resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} engines: {node: '>= 6'} - glob@13.0.0: - resolution: {integrity: sha512-tvZgpqk6fz4BaNZ66ZsRaZnbHvP/jG3uKJvAZOwEVUL4RTA5nJeeLYfyN9/VA8NX/V3IBG+hkeuGpKjvELkVhA==} + glob@13.0.1: + resolution: {integrity: sha512-B7U/vJpE3DkJ5WXTgTpTRN63uV42DseiXXKMwG14LQBXmsdeIoHAPbU/MEo6II0k5ED74uc2ZGTC6MwHFQhF6w==} engines: {node: 20 || >=22} glob@7.2.3: resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==} - deprecated: Glob versions prior to v9 are no longer supported + deprecated: Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me globby@11.1.0: resolution: {integrity: sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==} @@ -2188,8 +2188,8 @@ packages: resolution: {integrity: sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==} engines: {node: '>=0.10.0'} - knip@5.82.1: - resolution: {integrity: sha512-1nQk+5AcnkqL40kGQXfouzAEXkTR+eSrgo/8m1d0BMei4eAzFwghoXC4gOKbACgBiCof7hE8wkBVDsEvznf85w==} + knip@5.83.0: + resolution: {integrity: sha512-FfmaHMntpZB13B1oJQMSs1hTOZxd0TOn+FYB3oWEI02XlxTW3RH4H7d8z5Us3g0ziHCYyl7z0B1xi8ENP3QEKA==} engines: {node: '>=18.18.0'} hasBin: true peerDependencies: @@ -2234,8 +2234,8 @@ packages: resolution: {integrity: sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==} hasBin: true - lru-cache@11.2.4: - resolution: {integrity: sha512-B5Y16Jr9LB9dHVkh6ZevG+vAbOsNOYCX+sXvFWFu7B3Iz5mijW3zdbMyhsh8ANd2mSWBYdJgnqi+mL7/LrOPYg==} + lru-cache@11.2.5: + resolution: {integrity: sha512-vFrFJkWtJvJnD5hg+hJvVE8Lh/TcMzKnTgCWmtBipwI5yLX/iX+5UB2tfuyODF5E7k9xEzMdYgGqaSb1c0c5Yw==} engines: {node: 20 || >=22} lru-cache@5.1.1: @@ -2356,8 +2356,8 @@ packages: minimalistic-crypto-utils@1.0.1: resolution: {integrity: sha512-JIYlbt6g8i5jKfJ3xz7rF0LXmv2TkDxBLUkiBeZ7bAx4GnnNMr8xFpGnOxn6GhTEHx3SjRrZEoU+j04prX1ktg==} - minimatch@10.1.1: - resolution: {integrity: sha512-enIvLvRAFZYXJzkCYG5RKmPfrFArdLv+R+lbQ53BmIMLIry74bjKzX6iHAm8WYamJkhSSEabrWN5D97XnKObjQ==} + minimatch@10.1.2: + resolution: {integrity: sha512-fu656aJ0n2kcXwsnwnv9g24tkU5uSmOlTjd6WyyaKm2Z+h1qmY6bAjrcaIxF/BslFqbZ8UBtbJi7KgQOZD2PTw==} engines: {node: 20 || >=22} minimatch@3.1.2: @@ -2459,8 +2459,8 @@ packages: outdent@0.5.0: resolution: {integrity: sha512-/jHxFIzoMXdqPzTaCpFzAAWhpkSjZPF4Vsn6jAfNpmbH/ymsmd7Qc6VE9BGn0L6YMj6uwpQLxCECpus4ukKS9Q==} - oxc-resolver@11.16.3: - resolution: {integrity: sha512-goLOJH3x69VouGWGp5CgCIHyksmOZzXr36lsRmQz1APg3SPFORrvV2q7nsUHMzLVa6ZJgNwkgUSJFsbCpAWkCA==} + oxc-resolver@11.17.0: + resolution: {integrity: sha512-R5P2Tw6th+nQJdNcZGfuppBS/sM0x1EukqYffmlfX2xXLgLGCCPwu4ruEr9Sx29mrpkHgITc130Qps2JR90NdQ==} p-filter@2.1.0: resolution: {integrity: sha512-ZBxxZ5sL2HghephhpGAQdoskxplTwr7ICaehZwLIlfL6acuVgZPm8yBNuRAFBGEqtD/hmUeq9eqLg2ys9Xr/yw==} @@ -3083,8 +3083,8 @@ packages: resolution: {integrity: sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==} engines: {node: '>=12'} - zod@4.3.5: - resolution: {integrity: sha512-k7Nwx6vuWx1IJ9Bjuf4Zt1PEllcwe7cls3VNzm4CQ1/hgtFUK2bRNG3rvnpPUhFjmqJKAKtjV576KnUkHocg/g==} + zod@4.3.6: + resolution: {integrity: sha512-rftlrkhHZOcjDwkGlnUtZZkvaPHCsDATp4pGpuOOMDaTdDDXF91wuVDJoWoPsKX/3YPQ5fHuF3STjcYyKr+Qhg==} snapshots: @@ -3092,25 +3092,25 @@ snapshots: dependencies: '@babel/highlight': 7.25.9 - '@babel/code-frame@7.28.6': + '@babel/code-frame@7.29.0': dependencies: '@babel/helper-validator-identifier': 7.28.5 js-tokens: 4.0.0 picocolors: 1.1.1 - '@babel/compat-data@7.28.6': {} + '@babel/compat-data@7.29.0': {} - '@babel/core@7.28.6': + '@babel/core@7.29.0': dependencies: - '@babel/code-frame': 7.28.6 - '@babel/generator': 7.28.6 + '@babel/code-frame': 7.29.0 + '@babel/generator': 7.29.0 '@babel/helper-compilation-targets': 7.28.6 - '@babel/helper-module-transforms': 7.28.6(@babel/core@7.28.6) + '@babel/helper-module-transforms': 7.28.6(@babel/core@7.29.0) '@babel/helpers': 7.28.6 - '@babel/parser': 7.28.6 + '@babel/parser': 7.29.0 '@babel/template': 7.28.6 - '@babel/traverse': 7.28.6 - '@babel/types': 7.28.6 + '@babel/traverse': 7.29.0 + '@babel/types': 7.29.0 '@jridgewell/remapping': 2.3.5 convert-source-map: 2.0.0 debug: 4.4.3 @@ -3120,49 +3120,49 @@ snapshots: transitivePeerDependencies: - supports-color - '@babel/generator@7.28.6': + '@babel/generator@7.29.0': dependencies: - '@babel/parser': 7.28.6 - '@babel/types': 7.28.6 + '@babel/parser': 7.29.0 + '@babel/types': 7.29.0 '@jridgewell/gen-mapping': 0.3.13 '@jridgewell/trace-mapping': 0.3.31 jsesc: 3.1.0 '@babel/helper-annotate-as-pure@7.27.3': dependencies: - '@babel/types': 7.28.6 + '@babel/types': 7.29.0 '@babel/helper-compilation-targets@7.28.6': dependencies: - '@babel/compat-data': 7.28.6 + '@babel/compat-data': 7.29.0 '@babel/helper-validator-option': 7.27.1 browserslist: 4.28.1 lru-cache: 5.1.1 semver: 6.3.1 - '@babel/helper-create-class-features-plugin@7.28.6(@babel/core@7.28.6)': + '@babel/helper-create-class-features-plugin@7.28.6(@babel/core@7.29.0)': dependencies: - '@babel/core': 7.28.6 + '@babel/core': 7.29.0 '@babel/helper-annotate-as-pure': 7.27.3 '@babel/helper-member-expression-to-functions': 7.28.5 '@babel/helper-optimise-call-expression': 7.27.1 - '@babel/helper-replace-supers': 7.28.6(@babel/core@7.28.6) + '@babel/helper-replace-supers': 7.28.6(@babel/core@7.29.0) '@babel/helper-skip-transparent-expression-wrappers': 7.27.1 - '@babel/traverse': 7.28.6 + '@babel/traverse': 7.29.0 semver: 6.3.1 transitivePeerDependencies: - supports-color - '@babel/helper-create-regexp-features-plugin@7.28.5(@babel/core@7.28.6)': + '@babel/helper-create-regexp-features-plugin@7.28.5(@babel/core@7.29.0)': dependencies: - '@babel/core': 7.28.6 + '@babel/core': 7.29.0 '@babel/helper-annotate-as-pure': 7.27.3 regexpu-core: 6.4.0 semver: 6.3.1 - '@babel/helper-define-polyfill-provider@0.6.5(@babel/core@7.28.6)': + '@babel/helper-define-polyfill-provider@0.6.6(@babel/core@7.29.0)': dependencies: - '@babel/core': 7.28.6 + '@babel/core': 7.29.0 '@babel/helper-compilation-targets': 7.28.6 '@babel/helper-plugin-utils': 7.28.6 debug: 4.4.3 @@ -3175,55 +3175,55 @@ snapshots: '@babel/helper-member-expression-to-functions@7.28.5': dependencies: - '@babel/traverse': 7.28.6 - '@babel/types': 7.28.6 + '@babel/traverse': 7.29.0 + '@babel/types': 7.29.0 transitivePeerDependencies: - supports-color '@babel/helper-module-imports@7.28.6': dependencies: - '@babel/traverse': 7.28.6 - '@babel/types': 7.28.6 + '@babel/traverse': 7.29.0 + '@babel/types': 7.29.0 transitivePeerDependencies: - supports-color - '@babel/helper-module-transforms@7.28.6(@babel/core@7.28.6)': + '@babel/helper-module-transforms@7.28.6(@babel/core@7.29.0)': dependencies: - '@babel/core': 7.28.6 + '@babel/core': 7.29.0 '@babel/helper-module-imports': 7.28.6 '@babel/helper-validator-identifier': 7.28.5 - '@babel/traverse': 7.28.6 + '@babel/traverse': 7.29.0 transitivePeerDependencies: - supports-color '@babel/helper-optimise-call-expression@7.27.1': dependencies: - '@babel/types': 7.28.6 + '@babel/types': 7.29.0 '@babel/helper-plugin-utils@7.28.6': {} - '@babel/helper-remap-async-to-generator@7.27.1(@babel/core@7.28.6)': + '@babel/helper-remap-async-to-generator@7.27.1(@babel/core@7.29.0)': dependencies: - '@babel/core': 7.28.6 + '@babel/core': 7.29.0 '@babel/helper-annotate-as-pure': 7.27.3 '@babel/helper-wrap-function': 7.28.6 - '@babel/traverse': 7.28.6 + '@babel/traverse': 7.29.0 transitivePeerDependencies: - supports-color - '@babel/helper-replace-supers@7.28.6(@babel/core@7.28.6)': + '@babel/helper-replace-supers@7.28.6(@babel/core@7.29.0)': dependencies: - '@babel/core': 7.28.6 + '@babel/core': 7.29.0 '@babel/helper-member-expression-to-functions': 7.28.5 '@babel/helper-optimise-call-expression': 7.27.1 - '@babel/traverse': 7.28.6 + '@babel/traverse': 7.29.0 transitivePeerDependencies: - supports-color '@babel/helper-skip-transparent-expression-wrappers@7.27.1': dependencies: - '@babel/traverse': 7.28.6 - '@babel/types': 7.28.6 + '@babel/traverse': 7.29.0 + '@babel/types': 7.29.0 transitivePeerDependencies: - supports-color @@ -3236,15 +3236,15 @@ snapshots: '@babel/helper-wrap-function@7.28.6': dependencies: '@babel/template': 7.28.6 - '@babel/traverse': 7.28.6 - '@babel/types': 7.28.6 + '@babel/traverse': 7.29.0 + '@babel/types': 7.29.0 transitivePeerDependencies: - supports-color '@babel/helpers@7.28.6': dependencies: '@babel/template': 7.28.6 - '@babel/types': 7.28.6 + '@babel/types': 7.29.0 '@babel/highlight@7.25.9': dependencies: @@ -3253,379 +3253,379 @@ snapshots: js-tokens: 4.0.0 picocolors: 1.1.1 - '@babel/parser@7.28.6': + '@babel/parser@7.29.0': dependencies: - '@babel/types': 7.28.6 + '@babel/types': 7.29.0 - '@babel/plugin-proposal-export-default-from@7.27.1(@babel/core@7.28.6)': + '@babel/plugin-proposal-export-default-from@7.27.1(@babel/core@7.29.0)': dependencies: - '@babel/core': 7.28.6 + '@babel/core': 7.29.0 '@babel/helper-plugin-utils': 7.28.6 - '@babel/plugin-syntax-async-generators@7.8.4(@babel/core@7.28.6)': + '@babel/plugin-syntax-async-generators@7.8.4(@babel/core@7.29.0)': dependencies: - '@babel/core': 7.28.6 + '@babel/core': 7.29.0 '@babel/helper-plugin-utils': 7.28.6 - '@babel/plugin-syntax-bigint@7.8.3(@babel/core@7.28.6)': + '@babel/plugin-syntax-bigint@7.8.3(@babel/core@7.29.0)': dependencies: - '@babel/core': 7.28.6 + '@babel/core': 7.29.0 '@babel/helper-plugin-utils': 7.28.6 - '@babel/plugin-syntax-class-properties@7.12.13(@babel/core@7.28.6)': + '@babel/plugin-syntax-class-properties@7.12.13(@babel/core@7.29.0)': dependencies: - '@babel/core': 7.28.6 + '@babel/core': 7.29.0 '@babel/helper-plugin-utils': 7.28.6 - '@babel/plugin-syntax-class-static-block@7.14.5(@babel/core@7.28.6)': + '@babel/plugin-syntax-class-static-block@7.14.5(@babel/core@7.29.0)': dependencies: - '@babel/core': 7.28.6 + '@babel/core': 7.29.0 '@babel/helper-plugin-utils': 7.28.6 - '@babel/plugin-syntax-dynamic-import@7.8.3(@babel/core@7.28.6)': + '@babel/plugin-syntax-dynamic-import@7.8.3(@babel/core@7.29.0)': dependencies: - '@babel/core': 7.28.6 + '@babel/core': 7.29.0 '@babel/helper-plugin-utils': 7.28.6 - '@babel/plugin-syntax-export-default-from@7.28.6(@babel/core@7.28.6)': + '@babel/plugin-syntax-export-default-from@7.28.6(@babel/core@7.29.0)': dependencies: - '@babel/core': 7.28.6 + '@babel/core': 7.29.0 '@babel/helper-plugin-utils': 7.28.6 - '@babel/plugin-syntax-flow@7.28.6(@babel/core@7.28.6)': + '@babel/plugin-syntax-flow@7.28.6(@babel/core@7.29.0)': dependencies: - '@babel/core': 7.28.6 + '@babel/core': 7.29.0 '@babel/helper-plugin-utils': 7.28.6 - '@babel/plugin-syntax-import-attributes@7.28.6(@babel/core@7.28.6)': + '@babel/plugin-syntax-import-attributes@7.28.6(@babel/core@7.29.0)': dependencies: - '@babel/core': 7.28.6 + '@babel/core': 7.29.0 '@babel/helper-plugin-utils': 7.28.6 - '@babel/plugin-syntax-import-meta@7.10.4(@babel/core@7.28.6)': + '@babel/plugin-syntax-import-meta@7.10.4(@babel/core@7.29.0)': dependencies: - '@babel/core': 7.28.6 + '@babel/core': 7.29.0 '@babel/helper-plugin-utils': 7.28.6 - '@babel/plugin-syntax-json-strings@7.8.3(@babel/core@7.28.6)': + '@babel/plugin-syntax-json-strings@7.8.3(@babel/core@7.29.0)': dependencies: - '@babel/core': 7.28.6 + '@babel/core': 7.29.0 '@babel/helper-plugin-utils': 7.28.6 - '@babel/plugin-syntax-jsx@7.28.6(@babel/core@7.28.6)': + '@babel/plugin-syntax-jsx@7.28.6(@babel/core@7.29.0)': dependencies: - '@babel/core': 7.28.6 + '@babel/core': 7.29.0 '@babel/helper-plugin-utils': 7.28.6 - '@babel/plugin-syntax-logical-assignment-operators@7.10.4(@babel/core@7.28.6)': + '@babel/plugin-syntax-logical-assignment-operators@7.10.4(@babel/core@7.29.0)': dependencies: - '@babel/core': 7.28.6 + '@babel/core': 7.29.0 '@babel/helper-plugin-utils': 7.28.6 - '@babel/plugin-syntax-nullish-coalescing-operator@7.8.3(@babel/core@7.28.6)': + '@babel/plugin-syntax-nullish-coalescing-operator@7.8.3(@babel/core@7.29.0)': dependencies: - '@babel/core': 7.28.6 + '@babel/core': 7.29.0 '@babel/helper-plugin-utils': 7.28.6 - '@babel/plugin-syntax-numeric-separator@7.10.4(@babel/core@7.28.6)': + '@babel/plugin-syntax-numeric-separator@7.10.4(@babel/core@7.29.0)': dependencies: - '@babel/core': 7.28.6 + '@babel/core': 7.29.0 '@babel/helper-plugin-utils': 7.28.6 - '@babel/plugin-syntax-object-rest-spread@7.8.3(@babel/core@7.28.6)': + '@babel/plugin-syntax-object-rest-spread@7.8.3(@babel/core@7.29.0)': dependencies: - '@babel/core': 7.28.6 + '@babel/core': 7.29.0 '@babel/helper-plugin-utils': 7.28.6 - '@babel/plugin-syntax-optional-catch-binding@7.8.3(@babel/core@7.28.6)': + '@babel/plugin-syntax-optional-catch-binding@7.8.3(@babel/core@7.29.0)': dependencies: - '@babel/core': 7.28.6 + '@babel/core': 7.29.0 '@babel/helper-plugin-utils': 7.28.6 - '@babel/plugin-syntax-optional-chaining@7.8.3(@babel/core@7.28.6)': + '@babel/plugin-syntax-optional-chaining@7.8.3(@babel/core@7.29.0)': dependencies: - '@babel/core': 7.28.6 + '@babel/core': 7.29.0 '@babel/helper-plugin-utils': 7.28.6 - '@babel/plugin-syntax-private-property-in-object@7.14.5(@babel/core@7.28.6)': + '@babel/plugin-syntax-private-property-in-object@7.14.5(@babel/core@7.29.0)': dependencies: - '@babel/core': 7.28.6 + '@babel/core': 7.29.0 '@babel/helper-plugin-utils': 7.28.6 - '@babel/plugin-syntax-top-level-await@7.14.5(@babel/core@7.28.6)': + '@babel/plugin-syntax-top-level-await@7.14.5(@babel/core@7.29.0)': dependencies: - '@babel/core': 7.28.6 + '@babel/core': 7.29.0 '@babel/helper-plugin-utils': 7.28.6 - '@babel/plugin-syntax-typescript@7.28.6(@babel/core@7.28.6)': + '@babel/plugin-syntax-typescript@7.28.6(@babel/core@7.29.0)': dependencies: - '@babel/core': 7.28.6 + '@babel/core': 7.29.0 '@babel/helper-plugin-utils': 7.28.6 - '@babel/plugin-transform-arrow-functions@7.27.1(@babel/core@7.28.6)': + '@babel/plugin-transform-arrow-functions@7.27.1(@babel/core@7.29.0)': dependencies: - '@babel/core': 7.28.6 + '@babel/core': 7.29.0 '@babel/helper-plugin-utils': 7.28.6 - '@babel/plugin-transform-async-generator-functions@7.28.6(@babel/core@7.28.6)': + '@babel/plugin-transform-async-generator-functions@7.29.0(@babel/core@7.29.0)': dependencies: - '@babel/core': 7.28.6 + '@babel/core': 7.29.0 '@babel/helper-plugin-utils': 7.28.6 - '@babel/helper-remap-async-to-generator': 7.27.1(@babel/core@7.28.6) - '@babel/traverse': 7.28.6 + '@babel/helper-remap-async-to-generator': 7.27.1(@babel/core@7.29.0) + '@babel/traverse': 7.29.0 transitivePeerDependencies: - supports-color - '@babel/plugin-transform-async-to-generator@7.28.6(@babel/core@7.28.6)': + '@babel/plugin-transform-async-to-generator@7.28.6(@babel/core@7.29.0)': dependencies: - '@babel/core': 7.28.6 + '@babel/core': 7.29.0 '@babel/helper-module-imports': 7.28.6 '@babel/helper-plugin-utils': 7.28.6 - '@babel/helper-remap-async-to-generator': 7.27.1(@babel/core@7.28.6) + '@babel/helper-remap-async-to-generator': 7.27.1(@babel/core@7.29.0) transitivePeerDependencies: - supports-color - '@babel/plugin-transform-block-scoping@7.28.6(@babel/core@7.28.6)': + '@babel/plugin-transform-block-scoping@7.28.6(@babel/core@7.29.0)': dependencies: - '@babel/core': 7.28.6 + '@babel/core': 7.29.0 '@babel/helper-plugin-utils': 7.28.6 - '@babel/plugin-transform-class-properties@7.28.6(@babel/core@7.28.6)': + '@babel/plugin-transform-class-properties@7.28.6(@babel/core@7.29.0)': dependencies: - '@babel/core': 7.28.6 - '@babel/helper-create-class-features-plugin': 7.28.6(@babel/core@7.28.6) + '@babel/core': 7.29.0 + '@babel/helper-create-class-features-plugin': 7.28.6(@babel/core@7.29.0) '@babel/helper-plugin-utils': 7.28.6 transitivePeerDependencies: - supports-color - '@babel/plugin-transform-classes@7.28.6(@babel/core@7.28.6)': + '@babel/plugin-transform-classes@7.28.6(@babel/core@7.29.0)': dependencies: - '@babel/core': 7.28.6 + '@babel/core': 7.29.0 '@babel/helper-annotate-as-pure': 7.27.3 '@babel/helper-compilation-targets': 7.28.6 '@babel/helper-globals': 7.28.0 '@babel/helper-plugin-utils': 7.28.6 - '@babel/helper-replace-supers': 7.28.6(@babel/core@7.28.6) - '@babel/traverse': 7.28.6 + '@babel/helper-replace-supers': 7.28.6(@babel/core@7.29.0) + '@babel/traverse': 7.29.0 transitivePeerDependencies: - supports-color - '@babel/plugin-transform-computed-properties@7.28.6(@babel/core@7.28.6)': + '@babel/plugin-transform-computed-properties@7.28.6(@babel/core@7.29.0)': dependencies: - '@babel/core': 7.28.6 + '@babel/core': 7.29.0 '@babel/helper-plugin-utils': 7.28.6 '@babel/template': 7.28.6 - '@babel/plugin-transform-destructuring@7.28.5(@babel/core@7.28.6)': + '@babel/plugin-transform-destructuring@7.28.5(@babel/core@7.29.0)': dependencies: - '@babel/core': 7.28.6 + '@babel/core': 7.29.0 '@babel/helper-plugin-utils': 7.28.6 - '@babel/traverse': 7.28.6 + '@babel/traverse': 7.29.0 transitivePeerDependencies: - supports-color - '@babel/plugin-transform-flow-strip-types@7.27.1(@babel/core@7.28.6)': + '@babel/plugin-transform-flow-strip-types@7.27.1(@babel/core@7.29.0)': dependencies: - '@babel/core': 7.28.6 + '@babel/core': 7.29.0 '@babel/helper-plugin-utils': 7.28.6 - '@babel/plugin-syntax-flow': 7.28.6(@babel/core@7.28.6) + '@babel/plugin-syntax-flow': 7.28.6(@babel/core@7.29.0) - '@babel/plugin-transform-for-of@7.27.1(@babel/core@7.28.6)': + '@babel/plugin-transform-for-of@7.27.1(@babel/core@7.29.0)': dependencies: - '@babel/core': 7.28.6 + '@babel/core': 7.29.0 '@babel/helper-plugin-utils': 7.28.6 '@babel/helper-skip-transparent-expression-wrappers': 7.27.1 transitivePeerDependencies: - supports-color - '@babel/plugin-transform-function-name@7.27.1(@babel/core@7.28.6)': + '@babel/plugin-transform-function-name@7.27.1(@babel/core@7.29.0)': dependencies: - '@babel/core': 7.28.6 + '@babel/core': 7.29.0 '@babel/helper-compilation-targets': 7.28.6 '@babel/helper-plugin-utils': 7.28.6 - '@babel/traverse': 7.28.6 + '@babel/traverse': 7.29.0 transitivePeerDependencies: - supports-color - '@babel/plugin-transform-literals@7.27.1(@babel/core@7.28.6)': + '@babel/plugin-transform-literals@7.27.1(@babel/core@7.29.0)': dependencies: - '@babel/core': 7.28.6 + '@babel/core': 7.29.0 '@babel/helper-plugin-utils': 7.28.6 - '@babel/plugin-transform-logical-assignment-operators@7.28.6(@babel/core@7.28.6)': + '@babel/plugin-transform-logical-assignment-operators@7.28.6(@babel/core@7.29.0)': dependencies: - '@babel/core': 7.28.6 + '@babel/core': 7.29.0 '@babel/helper-plugin-utils': 7.28.6 - '@babel/plugin-transform-modules-commonjs@7.28.6(@babel/core@7.28.6)': + '@babel/plugin-transform-modules-commonjs@7.28.6(@babel/core@7.29.0)': dependencies: - '@babel/core': 7.28.6 - '@babel/helper-module-transforms': 7.28.6(@babel/core@7.28.6) + '@babel/core': 7.29.0 + '@babel/helper-module-transforms': 7.28.6(@babel/core@7.29.0) '@babel/helper-plugin-utils': 7.28.6 transitivePeerDependencies: - supports-color - '@babel/plugin-transform-named-capturing-groups-regex@7.27.1(@babel/core@7.28.6)': + '@babel/plugin-transform-named-capturing-groups-regex@7.29.0(@babel/core@7.29.0)': dependencies: - '@babel/core': 7.28.6 - '@babel/helper-create-regexp-features-plugin': 7.28.5(@babel/core@7.28.6) + '@babel/core': 7.29.0 + '@babel/helper-create-regexp-features-plugin': 7.28.5(@babel/core@7.29.0) '@babel/helper-plugin-utils': 7.28.6 - '@babel/plugin-transform-nullish-coalescing-operator@7.28.6(@babel/core@7.28.6)': + '@babel/plugin-transform-nullish-coalescing-operator@7.28.6(@babel/core@7.29.0)': dependencies: - '@babel/core': 7.28.6 + '@babel/core': 7.29.0 '@babel/helper-plugin-utils': 7.28.6 - '@babel/plugin-transform-numeric-separator@7.28.6(@babel/core@7.28.6)': + '@babel/plugin-transform-numeric-separator@7.28.6(@babel/core@7.29.0)': dependencies: - '@babel/core': 7.28.6 + '@babel/core': 7.29.0 '@babel/helper-plugin-utils': 7.28.6 - '@babel/plugin-transform-object-rest-spread@7.28.6(@babel/core@7.28.6)': + '@babel/plugin-transform-object-rest-spread@7.28.6(@babel/core@7.29.0)': dependencies: - '@babel/core': 7.28.6 + '@babel/core': 7.29.0 '@babel/helper-compilation-targets': 7.28.6 '@babel/helper-plugin-utils': 7.28.6 - '@babel/plugin-transform-destructuring': 7.28.5(@babel/core@7.28.6) - '@babel/plugin-transform-parameters': 7.27.7(@babel/core@7.28.6) - '@babel/traverse': 7.28.6 + '@babel/plugin-transform-destructuring': 7.28.5(@babel/core@7.29.0) + '@babel/plugin-transform-parameters': 7.27.7(@babel/core@7.29.0) + '@babel/traverse': 7.29.0 transitivePeerDependencies: - supports-color - '@babel/plugin-transform-optional-catch-binding@7.28.6(@babel/core@7.28.6)': + '@babel/plugin-transform-optional-catch-binding@7.28.6(@babel/core@7.29.0)': dependencies: - '@babel/core': 7.28.6 + '@babel/core': 7.29.0 '@babel/helper-plugin-utils': 7.28.6 - '@babel/plugin-transform-optional-chaining@7.28.6(@babel/core@7.28.6)': + '@babel/plugin-transform-optional-chaining@7.28.6(@babel/core@7.29.0)': dependencies: - '@babel/core': 7.28.6 + '@babel/core': 7.29.0 '@babel/helper-plugin-utils': 7.28.6 '@babel/helper-skip-transparent-expression-wrappers': 7.27.1 transitivePeerDependencies: - supports-color - '@babel/plugin-transform-parameters@7.27.7(@babel/core@7.28.6)': + '@babel/plugin-transform-parameters@7.27.7(@babel/core@7.29.0)': dependencies: - '@babel/core': 7.28.6 + '@babel/core': 7.29.0 '@babel/helper-plugin-utils': 7.28.6 - '@babel/plugin-transform-private-methods@7.28.6(@babel/core@7.28.6)': + '@babel/plugin-transform-private-methods@7.28.6(@babel/core@7.29.0)': dependencies: - '@babel/core': 7.28.6 - '@babel/helper-create-class-features-plugin': 7.28.6(@babel/core@7.28.6) + '@babel/core': 7.29.0 + '@babel/helper-create-class-features-plugin': 7.28.6(@babel/core@7.29.0) '@babel/helper-plugin-utils': 7.28.6 transitivePeerDependencies: - supports-color - '@babel/plugin-transform-private-property-in-object@7.28.6(@babel/core@7.28.6)': + '@babel/plugin-transform-private-property-in-object@7.28.6(@babel/core@7.29.0)': dependencies: - '@babel/core': 7.28.6 + '@babel/core': 7.29.0 '@babel/helper-annotate-as-pure': 7.27.3 - '@babel/helper-create-class-features-plugin': 7.28.6(@babel/core@7.28.6) + '@babel/helper-create-class-features-plugin': 7.28.6(@babel/core@7.29.0) '@babel/helper-plugin-utils': 7.28.6 transitivePeerDependencies: - supports-color - '@babel/plugin-transform-react-display-name@7.28.0(@babel/core@7.28.6)': + '@babel/plugin-transform-react-display-name@7.28.0(@babel/core@7.29.0)': dependencies: - '@babel/core': 7.28.6 + '@babel/core': 7.29.0 '@babel/helper-plugin-utils': 7.28.6 - '@babel/plugin-transform-react-jsx-self@7.27.1(@babel/core@7.28.6)': + '@babel/plugin-transform-react-jsx-self@7.27.1(@babel/core@7.29.0)': dependencies: - '@babel/core': 7.28.6 + '@babel/core': 7.29.0 '@babel/helper-plugin-utils': 7.28.6 - '@babel/plugin-transform-react-jsx-source@7.27.1(@babel/core@7.28.6)': + '@babel/plugin-transform-react-jsx-source@7.27.1(@babel/core@7.29.0)': dependencies: - '@babel/core': 7.28.6 + '@babel/core': 7.29.0 '@babel/helper-plugin-utils': 7.28.6 - '@babel/plugin-transform-react-jsx@7.28.6(@babel/core@7.28.6)': + '@babel/plugin-transform-react-jsx@7.28.6(@babel/core@7.29.0)': dependencies: - '@babel/core': 7.28.6 + '@babel/core': 7.29.0 '@babel/helper-annotate-as-pure': 7.27.3 '@babel/helper-module-imports': 7.28.6 '@babel/helper-plugin-utils': 7.28.6 - '@babel/plugin-syntax-jsx': 7.28.6(@babel/core@7.28.6) - '@babel/types': 7.28.6 + '@babel/plugin-syntax-jsx': 7.28.6(@babel/core@7.29.0) + '@babel/types': 7.29.0 transitivePeerDependencies: - supports-color - '@babel/plugin-transform-regenerator@7.28.6(@babel/core@7.28.6)': + '@babel/plugin-transform-regenerator@7.29.0(@babel/core@7.29.0)': dependencies: - '@babel/core': 7.28.6 + '@babel/core': 7.29.0 '@babel/helper-plugin-utils': 7.28.6 - '@babel/plugin-transform-runtime@7.28.5(@babel/core@7.28.6)': + '@babel/plugin-transform-runtime@7.29.0(@babel/core@7.29.0)': dependencies: - '@babel/core': 7.28.6 + '@babel/core': 7.29.0 '@babel/helper-module-imports': 7.28.6 '@babel/helper-plugin-utils': 7.28.6 - babel-plugin-polyfill-corejs2: 0.4.14(@babel/core@7.28.6) - babel-plugin-polyfill-corejs3: 0.13.0(@babel/core@7.28.6) - babel-plugin-polyfill-regenerator: 0.6.5(@babel/core@7.28.6) + babel-plugin-polyfill-corejs2: 0.4.15(@babel/core@7.29.0) + babel-plugin-polyfill-corejs3: 0.13.0(@babel/core@7.29.0) + babel-plugin-polyfill-regenerator: 0.6.6(@babel/core@7.29.0) semver: 6.3.1 transitivePeerDependencies: - supports-color - '@babel/plugin-transform-shorthand-properties@7.27.1(@babel/core@7.28.6)': + '@babel/plugin-transform-shorthand-properties@7.27.1(@babel/core@7.29.0)': dependencies: - '@babel/core': 7.28.6 + '@babel/core': 7.29.0 '@babel/helper-plugin-utils': 7.28.6 - '@babel/plugin-transform-spread@7.28.6(@babel/core@7.28.6)': + '@babel/plugin-transform-spread@7.28.6(@babel/core@7.29.0)': dependencies: - '@babel/core': 7.28.6 + '@babel/core': 7.29.0 '@babel/helper-plugin-utils': 7.28.6 '@babel/helper-skip-transparent-expression-wrappers': 7.27.1 transitivePeerDependencies: - supports-color - '@babel/plugin-transform-sticky-regex@7.27.1(@babel/core@7.28.6)': + '@babel/plugin-transform-sticky-regex@7.27.1(@babel/core@7.29.0)': dependencies: - '@babel/core': 7.28.6 + '@babel/core': 7.29.0 '@babel/helper-plugin-utils': 7.28.6 - '@babel/plugin-transform-typescript@7.28.6(@babel/core@7.28.6)': + '@babel/plugin-transform-typescript@7.28.6(@babel/core@7.29.0)': dependencies: - '@babel/core': 7.28.6 + '@babel/core': 7.29.0 '@babel/helper-annotate-as-pure': 7.27.3 - '@babel/helper-create-class-features-plugin': 7.28.6(@babel/core@7.28.6) + '@babel/helper-create-class-features-plugin': 7.28.6(@babel/core@7.29.0) '@babel/helper-plugin-utils': 7.28.6 '@babel/helper-skip-transparent-expression-wrappers': 7.27.1 - '@babel/plugin-syntax-typescript': 7.28.6(@babel/core@7.28.6) + '@babel/plugin-syntax-typescript': 7.28.6(@babel/core@7.29.0) transitivePeerDependencies: - supports-color - '@babel/plugin-transform-unicode-regex@7.27.1(@babel/core@7.28.6)': + '@babel/plugin-transform-unicode-regex@7.27.1(@babel/core@7.29.0)': dependencies: - '@babel/core': 7.28.6 - '@babel/helper-create-regexp-features-plugin': 7.28.5(@babel/core@7.28.6) + '@babel/core': 7.29.0 + '@babel/helper-create-regexp-features-plugin': 7.28.5(@babel/core@7.29.0) '@babel/helper-plugin-utils': 7.28.6 - '@babel/preset-flow@7.27.1(@babel/core@7.28.6)': + '@babel/preset-flow@7.27.1(@babel/core@7.29.0)': dependencies: - '@babel/core': 7.28.6 + '@babel/core': 7.29.0 '@babel/helper-plugin-utils': 7.28.6 '@babel/helper-validator-option': 7.27.1 - '@babel/plugin-transform-flow-strip-types': 7.27.1(@babel/core@7.28.6) + '@babel/plugin-transform-flow-strip-types': 7.27.1(@babel/core@7.29.0) - '@babel/preset-typescript@7.28.5(@babel/core@7.28.6)': + '@babel/preset-typescript@7.28.5(@babel/core@7.29.0)': dependencies: - '@babel/core': 7.28.6 + '@babel/core': 7.29.0 '@babel/helper-plugin-utils': 7.28.6 '@babel/helper-validator-option': 7.27.1 - '@babel/plugin-syntax-jsx': 7.28.6(@babel/core@7.28.6) - '@babel/plugin-transform-modules-commonjs': 7.28.6(@babel/core@7.28.6) - '@babel/plugin-transform-typescript': 7.28.6(@babel/core@7.28.6) + '@babel/plugin-syntax-jsx': 7.28.6(@babel/core@7.29.0) + '@babel/plugin-transform-modules-commonjs': 7.28.6(@babel/core@7.29.0) + '@babel/plugin-transform-typescript': 7.28.6(@babel/core@7.29.0) transitivePeerDependencies: - supports-color - '@babel/register@7.28.6(@babel/core@7.28.6)': + '@babel/register@7.28.6(@babel/core@7.29.0)': dependencies: - '@babel/core': 7.28.6 + '@babel/core': 7.29.0 clone-deep: 4.0.1 find-cache-dir: 2.1.0 make-dir: 2.1.0 @@ -3636,60 +3636,60 @@ snapshots: '@babel/template@7.28.6': dependencies: - '@babel/code-frame': 7.28.6 - '@babel/parser': 7.28.6 - '@babel/types': 7.28.6 + '@babel/code-frame': 7.29.0 + '@babel/parser': 7.29.0 + '@babel/types': 7.29.0 - '@babel/traverse@7.28.6': + '@babel/traverse@7.29.0': dependencies: - '@babel/code-frame': 7.28.6 - '@babel/generator': 7.28.6 + '@babel/code-frame': 7.29.0 + '@babel/generator': 7.29.0 '@babel/helper-globals': 7.28.0 - '@babel/parser': 7.28.6 + '@babel/parser': 7.29.0 '@babel/template': 7.28.6 - '@babel/types': 7.28.6 + '@babel/types': 7.29.0 debug: 4.4.3 transitivePeerDependencies: - supports-color - '@babel/types@7.28.6': + '@babel/types@7.29.0': dependencies: '@babel/helper-string-parser': 7.27.1 '@babel/helper-validator-identifier': 7.28.5 - '@biomejs/biome@2.3.11': + '@biomejs/biome@2.3.14': optionalDependencies: - '@biomejs/cli-darwin-arm64': 2.3.11 - '@biomejs/cli-darwin-x64': 2.3.11 - '@biomejs/cli-linux-arm64': 2.3.11 - '@biomejs/cli-linux-arm64-musl': 2.3.11 - '@biomejs/cli-linux-x64': 2.3.11 - '@biomejs/cli-linux-x64-musl': 2.3.11 - '@biomejs/cli-win32-arm64': 2.3.11 - '@biomejs/cli-win32-x64': 2.3.11 - - '@biomejs/cli-darwin-arm64@2.3.11': + '@biomejs/cli-darwin-arm64': 2.3.14 + '@biomejs/cli-darwin-x64': 2.3.14 + '@biomejs/cli-linux-arm64': 2.3.14 + '@biomejs/cli-linux-arm64-musl': 2.3.14 + '@biomejs/cli-linux-x64': 2.3.14 + '@biomejs/cli-linux-x64-musl': 2.3.14 + '@biomejs/cli-win32-arm64': 2.3.14 + '@biomejs/cli-win32-x64': 2.3.14 + + '@biomejs/cli-darwin-arm64@2.3.14': optional: true - '@biomejs/cli-darwin-x64@2.3.11': + '@biomejs/cli-darwin-x64@2.3.14': optional: true - '@biomejs/cli-linux-arm64-musl@2.3.11': + '@biomejs/cli-linux-arm64-musl@2.3.14': optional: true - '@biomejs/cli-linux-arm64@2.3.11': + '@biomejs/cli-linux-arm64@2.3.14': optional: true - '@biomejs/cli-linux-x64-musl@2.3.11': + '@biomejs/cli-linux-x64-musl@2.3.14': optional: true - '@biomejs/cli-linux-x64@2.3.11': + '@biomejs/cli-linux-x64@2.3.14': optional: true - '@biomejs/cli-win32-arm64@2.3.11': + '@biomejs/cli-win32-arm64@2.3.14': optional: true - '@biomejs/cli-win32-x64@2.3.11': + '@biomejs/cli-win32-x64@2.3.14': optional: true '@changesets/apply-release-plan@7.0.14': @@ -3729,7 +3729,7 @@ snapshots: transitivePeerDependencies: - encoding - '@changesets/cli@2.29.8(@types/node@25.0.9)': + '@changesets/cli@2.29.8(@types/node@25.2.0)': dependencies: '@changesets/apply-release-plan': 7.0.14 '@changesets/assemble-release-plan': 6.0.9 @@ -3745,7 +3745,7 @@ snapshots: '@changesets/should-skip-package': 0.1.2 '@changesets/types': 6.1.0 '@changesets/write': 0.4.0 - '@inquirer/external-editor': 1.0.3(@types/node@25.0.9) + '@inquirer/external-editor': 1.0.3(@types/node@25.2.0) '@manypkg/get-packages': 1.1.3 ansi-colors: 4.1.3 ci-info: 3.9.0 @@ -4119,7 +4119,7 @@ snapshots: chalk: 4.1.2 debug: 4.4.3 getenv: 2.0.0 - glob: 13.0.0 + glob: 13.0.1 resolve-from: 5.0.0 semver: 7.7.3 slash: 3.0.0 @@ -4139,7 +4139,7 @@ snapshots: '@expo/json-file': 9.1.5 deepmerge: 4.3.1 getenv: 2.0.0 - glob: 13.0.0 + glob: 13.0.1 require-from-string: 2.0.2 resolve-from: 5.0.0 resolve-workspace-root: 2.0.1 @@ -4172,24 +4172,24 @@ snapshots: '@expo/sdk-runtime-versions@1.0.0': {} - '@gerrit0/mini-shiki@3.21.0': + '@gerrit0/mini-shiki@3.22.0': dependencies: - '@shikijs/engine-oniguruma': 3.21.0 - '@shikijs/langs': 3.21.0 - '@shikijs/themes': 3.21.0 - '@shikijs/types': 3.21.0 + '@shikijs/engine-oniguruma': 3.22.0 + '@shikijs/langs': 3.22.0 + '@shikijs/themes': 3.22.0 + '@shikijs/types': 3.22.0 '@shikijs/vscode-textmate': 10.0.2 - '@inquirer/external-editor@1.0.3(@types/node@25.0.9)': + '@inquirer/external-editor@1.0.3(@types/node@25.2.0)': dependencies: chardet: 2.1.1 iconv-lite: 0.7.2 optionalDependencies: - '@types/node': 25.0.9 + '@types/node': 25.2.0 '@isaacs/balanced-match@4.0.1': {} - '@isaacs/brace-expansion@5.0.0': + '@isaacs/brace-expansion@5.0.1': dependencies: '@isaacs/balanced-match': 4.0.1 @@ -4213,25 +4213,25 @@ snapshots: dependencies: '@jest/fake-timers': 29.7.0 '@jest/types': 29.6.3 - '@types/node': 25.0.9 + '@types/node': 25.2.0 jest-mock: 29.7.0 '@jest/fake-timers@29.7.0': dependencies: '@jest/types': 29.6.3 '@sinonjs/fake-timers': 10.3.0 - '@types/node': 25.0.9 + '@types/node': 25.2.0 jest-message-util: 29.7.0 jest-mock: 29.7.0 jest-util: 29.7.0 '@jest/schemas@29.6.3': dependencies: - '@sinclair/typebox': 0.27.8 + '@sinclair/typebox': 0.27.10 '@jest/transform@29.7.0': dependencies: - '@babel/core': 7.28.6 + '@babel/core': 7.29.0 '@jest/types': 29.6.3 '@jridgewell/trace-mapping': 0.3.31 babel-plugin-istanbul: 6.1.1 @@ -4254,7 +4254,7 @@ snapshots: '@jest/schemas': 29.6.3 '@types/istanbul-lib-coverage': 2.0.6 '@types/istanbul-reports': 3.0.4 - '@types/node': 25.0.9 + '@types/node': 25.2.0 '@types/yargs': 17.0.35 chalk: 4.1.2 @@ -4317,7 +4317,7 @@ snapshots: '@nodelib/fs.scandir': 2.1.5 fastq: 1.20.1 - '@openfort/openfort-js@https://pkg.pr.new/@openfort/openfort-js@e6f2ed0': + '@openfort/openfort-js@https://pkg.pr.new/@openfort/openfort-js@224': dependencies: '@ethersproject/abi': 5.8.0 '@ethersproject/bytes': 5.8.0 @@ -4328,8 +4328,8 @@ snapshots: '@openfort/shield-js': 0.1.34 '@sentry/browser': 9.47.1 '@sentry/core': 9.47.1 - axios: 1.13.2 - axios-retry: 4.5.0(axios@1.13.2) + axios: 1.13.4 + axios-retry: 4.5.0(axios@1.13.4) eventemitter3: 5.0.1 human-id: 4.1.3 transitivePeerDependencies: @@ -4344,73 +4344,73 @@ snapshots: transitivePeerDependencies: - debug - '@oxc-resolver/binding-android-arm-eabi@11.16.3': + '@oxc-resolver/binding-android-arm-eabi@11.17.0': optional: true - '@oxc-resolver/binding-android-arm64@11.16.3': + '@oxc-resolver/binding-android-arm64@11.17.0': optional: true - '@oxc-resolver/binding-darwin-arm64@11.16.3': + '@oxc-resolver/binding-darwin-arm64@11.17.0': optional: true - '@oxc-resolver/binding-darwin-x64@11.16.3': + '@oxc-resolver/binding-darwin-x64@11.17.0': optional: true - '@oxc-resolver/binding-freebsd-x64@11.16.3': + '@oxc-resolver/binding-freebsd-x64@11.17.0': optional: true - '@oxc-resolver/binding-linux-arm-gnueabihf@11.16.3': + '@oxc-resolver/binding-linux-arm-gnueabihf@11.17.0': optional: true - '@oxc-resolver/binding-linux-arm-musleabihf@11.16.3': + '@oxc-resolver/binding-linux-arm-musleabihf@11.17.0': optional: true - '@oxc-resolver/binding-linux-arm64-gnu@11.16.3': + '@oxc-resolver/binding-linux-arm64-gnu@11.17.0': optional: true - '@oxc-resolver/binding-linux-arm64-musl@11.16.3': + '@oxc-resolver/binding-linux-arm64-musl@11.17.0': optional: true - '@oxc-resolver/binding-linux-ppc64-gnu@11.16.3': + '@oxc-resolver/binding-linux-ppc64-gnu@11.17.0': optional: true - '@oxc-resolver/binding-linux-riscv64-gnu@11.16.3': + '@oxc-resolver/binding-linux-riscv64-gnu@11.17.0': optional: true - '@oxc-resolver/binding-linux-riscv64-musl@11.16.3': + '@oxc-resolver/binding-linux-riscv64-musl@11.17.0': optional: true - '@oxc-resolver/binding-linux-s390x-gnu@11.16.3': + '@oxc-resolver/binding-linux-s390x-gnu@11.17.0': optional: true - '@oxc-resolver/binding-linux-x64-gnu@11.16.3': + '@oxc-resolver/binding-linux-x64-gnu@11.17.0': optional: true - '@oxc-resolver/binding-linux-x64-musl@11.16.3': + '@oxc-resolver/binding-linux-x64-musl@11.17.0': optional: true - '@oxc-resolver/binding-openharmony-arm64@11.16.3': + '@oxc-resolver/binding-openharmony-arm64@11.17.0': optional: true - '@oxc-resolver/binding-wasm32-wasi@11.16.3': + '@oxc-resolver/binding-wasm32-wasi@11.17.0': dependencies: '@napi-rs/wasm-runtime': 1.1.1 optional: true - '@oxc-resolver/binding-win32-arm64-msvc@11.16.3': + '@oxc-resolver/binding-win32-arm64-msvc@11.17.0': optional: true - '@oxc-resolver/binding-win32-ia32-msvc@11.16.3': + '@oxc-resolver/binding-win32-ia32-msvc@11.17.0': optional: true - '@oxc-resolver/binding-win32-x64-msvc@11.16.3': + '@oxc-resolver/binding-win32-x64-msvc@11.17.0': optional: true '@react-native/assets-registry@0.77.1': {} '@react-native/babel-plugin-codegen@0.77.1': dependencies: - '@babel/traverse': 7.28.6 + '@babel/traverse': 7.29.0 '@react-native/codegen': 0.77.1 transitivePeerDependencies: - '@babel/preset-env' @@ -4418,50 +4418,50 @@ snapshots: '@react-native/babel-preset@0.77.1': dependencies: - '@babel/core': 7.28.6 - '@babel/plugin-proposal-export-default-from': 7.27.1(@babel/core@7.28.6) - '@babel/plugin-syntax-dynamic-import': 7.8.3(@babel/core@7.28.6) - '@babel/plugin-syntax-export-default-from': 7.28.6(@babel/core@7.28.6) - '@babel/plugin-syntax-nullish-coalescing-operator': 7.8.3(@babel/core@7.28.6) - '@babel/plugin-syntax-optional-chaining': 7.8.3(@babel/core@7.28.6) - '@babel/plugin-transform-arrow-functions': 7.27.1(@babel/core@7.28.6) - '@babel/plugin-transform-async-generator-functions': 7.28.6(@babel/core@7.28.6) - '@babel/plugin-transform-async-to-generator': 7.28.6(@babel/core@7.28.6) - '@babel/plugin-transform-block-scoping': 7.28.6(@babel/core@7.28.6) - '@babel/plugin-transform-class-properties': 7.28.6(@babel/core@7.28.6) - '@babel/plugin-transform-classes': 7.28.6(@babel/core@7.28.6) - '@babel/plugin-transform-computed-properties': 7.28.6(@babel/core@7.28.6) - '@babel/plugin-transform-destructuring': 7.28.5(@babel/core@7.28.6) - '@babel/plugin-transform-flow-strip-types': 7.27.1(@babel/core@7.28.6) - '@babel/plugin-transform-for-of': 7.27.1(@babel/core@7.28.6) - '@babel/plugin-transform-function-name': 7.27.1(@babel/core@7.28.6) - '@babel/plugin-transform-literals': 7.27.1(@babel/core@7.28.6) - '@babel/plugin-transform-logical-assignment-operators': 7.28.6(@babel/core@7.28.6) - '@babel/plugin-transform-modules-commonjs': 7.28.6(@babel/core@7.28.6) - '@babel/plugin-transform-named-capturing-groups-regex': 7.27.1(@babel/core@7.28.6) - '@babel/plugin-transform-nullish-coalescing-operator': 7.28.6(@babel/core@7.28.6) - '@babel/plugin-transform-numeric-separator': 7.28.6(@babel/core@7.28.6) - '@babel/plugin-transform-object-rest-spread': 7.28.6(@babel/core@7.28.6) - '@babel/plugin-transform-optional-catch-binding': 7.28.6(@babel/core@7.28.6) - '@babel/plugin-transform-optional-chaining': 7.28.6(@babel/core@7.28.6) - '@babel/plugin-transform-parameters': 7.27.7(@babel/core@7.28.6) - '@babel/plugin-transform-private-methods': 7.28.6(@babel/core@7.28.6) - '@babel/plugin-transform-private-property-in-object': 7.28.6(@babel/core@7.28.6) - '@babel/plugin-transform-react-display-name': 7.28.0(@babel/core@7.28.6) - '@babel/plugin-transform-react-jsx': 7.28.6(@babel/core@7.28.6) - '@babel/plugin-transform-react-jsx-self': 7.27.1(@babel/core@7.28.6) - '@babel/plugin-transform-react-jsx-source': 7.27.1(@babel/core@7.28.6) - '@babel/plugin-transform-regenerator': 7.28.6(@babel/core@7.28.6) - '@babel/plugin-transform-runtime': 7.28.5(@babel/core@7.28.6) - '@babel/plugin-transform-shorthand-properties': 7.27.1(@babel/core@7.28.6) - '@babel/plugin-transform-spread': 7.28.6(@babel/core@7.28.6) - '@babel/plugin-transform-sticky-regex': 7.27.1(@babel/core@7.28.6) - '@babel/plugin-transform-typescript': 7.28.6(@babel/core@7.28.6) - '@babel/plugin-transform-unicode-regex': 7.27.1(@babel/core@7.28.6) + '@babel/core': 7.29.0 + '@babel/plugin-proposal-export-default-from': 7.27.1(@babel/core@7.29.0) + '@babel/plugin-syntax-dynamic-import': 7.8.3(@babel/core@7.29.0) + '@babel/plugin-syntax-export-default-from': 7.28.6(@babel/core@7.29.0) + '@babel/plugin-syntax-nullish-coalescing-operator': 7.8.3(@babel/core@7.29.0) + '@babel/plugin-syntax-optional-chaining': 7.8.3(@babel/core@7.29.0) + '@babel/plugin-transform-arrow-functions': 7.27.1(@babel/core@7.29.0) + '@babel/plugin-transform-async-generator-functions': 7.29.0(@babel/core@7.29.0) + '@babel/plugin-transform-async-to-generator': 7.28.6(@babel/core@7.29.0) + '@babel/plugin-transform-block-scoping': 7.28.6(@babel/core@7.29.0) + '@babel/plugin-transform-class-properties': 7.28.6(@babel/core@7.29.0) + '@babel/plugin-transform-classes': 7.28.6(@babel/core@7.29.0) + '@babel/plugin-transform-computed-properties': 7.28.6(@babel/core@7.29.0) + '@babel/plugin-transform-destructuring': 7.28.5(@babel/core@7.29.0) + '@babel/plugin-transform-flow-strip-types': 7.27.1(@babel/core@7.29.0) + '@babel/plugin-transform-for-of': 7.27.1(@babel/core@7.29.0) + '@babel/plugin-transform-function-name': 7.27.1(@babel/core@7.29.0) + '@babel/plugin-transform-literals': 7.27.1(@babel/core@7.29.0) + '@babel/plugin-transform-logical-assignment-operators': 7.28.6(@babel/core@7.29.0) + '@babel/plugin-transform-modules-commonjs': 7.28.6(@babel/core@7.29.0) + '@babel/plugin-transform-named-capturing-groups-regex': 7.29.0(@babel/core@7.29.0) + '@babel/plugin-transform-nullish-coalescing-operator': 7.28.6(@babel/core@7.29.0) + '@babel/plugin-transform-numeric-separator': 7.28.6(@babel/core@7.29.0) + '@babel/plugin-transform-object-rest-spread': 7.28.6(@babel/core@7.29.0) + '@babel/plugin-transform-optional-catch-binding': 7.28.6(@babel/core@7.29.0) + '@babel/plugin-transform-optional-chaining': 7.28.6(@babel/core@7.29.0) + '@babel/plugin-transform-parameters': 7.27.7(@babel/core@7.29.0) + '@babel/plugin-transform-private-methods': 7.28.6(@babel/core@7.29.0) + '@babel/plugin-transform-private-property-in-object': 7.28.6(@babel/core@7.29.0) + '@babel/plugin-transform-react-display-name': 7.28.0(@babel/core@7.29.0) + '@babel/plugin-transform-react-jsx': 7.28.6(@babel/core@7.29.0) + '@babel/plugin-transform-react-jsx-self': 7.27.1(@babel/core@7.29.0) + '@babel/plugin-transform-react-jsx-source': 7.27.1(@babel/core@7.29.0) + '@babel/plugin-transform-regenerator': 7.29.0(@babel/core@7.29.0) + '@babel/plugin-transform-runtime': 7.29.0(@babel/core@7.29.0) + '@babel/plugin-transform-shorthand-properties': 7.27.1(@babel/core@7.29.0) + '@babel/plugin-transform-spread': 7.28.6(@babel/core@7.29.0) + '@babel/plugin-transform-sticky-regex': 7.27.1(@babel/core@7.29.0) + '@babel/plugin-transform-typescript': 7.28.6(@babel/core@7.29.0) + '@babel/plugin-transform-unicode-regex': 7.27.1(@babel/core@7.29.0) '@babel/template': 7.28.6 '@react-native/babel-plugin-codegen': 0.77.1 babel-plugin-syntax-hermes-parser: 0.25.1 - babel-plugin-transform-flow-enums: 0.0.2(@babel/core@7.28.6) + babel-plugin-transform-flow-enums: 0.0.2(@babel/core@7.29.0) react-refresh: 0.14.2 transitivePeerDependencies: - '@babel/preset-env' @@ -4469,7 +4469,7 @@ snapshots: '@react-native/codegen@0.77.1': dependencies: - '@babel/parser': 7.28.6 + '@babel/parser': 7.29.0 glob: 7.2.3 hermes-parser: 0.25.1 invariant: 2.2.4 @@ -4524,7 +4524,7 @@ snapshots: '@react-native/metro-babel-transformer@0.77.1': dependencies: - '@babel/core': 7.28.6 + '@babel/core': 7.29.0 '@react-native/babel-preset': 0.77.1 hermes-parser: 0.25.1 nullthrows: 1.1.1 @@ -4534,12 +4534,12 @@ snapshots: '@react-native/normalize-colors@0.77.1': {} - '@react-native/virtualized-lists@0.77.1(@types/react@18.3.27)(react-native@0.77.1(@babel/core@7.28.6)(@types/react@18.3.27)(react@18.3.1))(react@18.3.1)': + '@react-native/virtualized-lists@0.77.1(@types/react@18.3.27)(react-native@0.77.1(@babel/core@7.29.0)(@types/react@18.3.27)(react@18.3.1))(react@18.3.1)': dependencies: invariant: 2.2.4 nullthrows: 1.1.1 react: 18.3.1 - react-native: 0.77.1(@babel/core@7.28.6)(@types/react@18.3.27)(react@18.3.1) + react-native: 0.77.1(@babel/core@7.29.0)(@types/react@18.3.27)(react@18.3.1) optionalDependencies: '@types/react': 18.3.27 @@ -4571,27 +4571,27 @@ snapshots: '@sentry/core@9.47.1': {} - '@shikijs/engine-oniguruma@3.21.0': + '@shikijs/engine-oniguruma@3.22.0': dependencies: - '@shikijs/types': 3.21.0 + '@shikijs/types': 3.22.0 '@shikijs/vscode-textmate': 10.0.2 - '@shikijs/langs@3.21.0': + '@shikijs/langs@3.22.0': dependencies: - '@shikijs/types': 3.21.0 + '@shikijs/types': 3.22.0 - '@shikijs/themes@3.21.0': + '@shikijs/themes@3.22.0': dependencies: - '@shikijs/types': 3.21.0 + '@shikijs/types': 3.22.0 - '@shikijs/types@3.21.0': + '@shikijs/types@3.22.0': dependencies: '@shikijs/vscode-textmate': 10.0.2 '@types/hast': 3.0.4 '@shikijs/vscode-textmate@10.0.2': {} - '@sinclair/typebox@0.27.8': {} + '@sinclair/typebox@0.27.10': {} '@sinonjs/commons@3.0.1': dependencies: @@ -4624,28 +4624,28 @@ snapshots: '@types/babel__core@7.20.5': dependencies: - '@babel/parser': 7.28.6 - '@babel/types': 7.28.6 + '@babel/parser': 7.29.0 + '@babel/types': 7.29.0 '@types/babel__generator': 7.27.0 '@types/babel__template': 7.4.4 '@types/babel__traverse': 7.28.0 '@types/babel__generator@7.27.0': dependencies: - '@babel/types': 7.28.6 + '@babel/types': 7.29.0 '@types/babel__template@7.4.4': dependencies: - '@babel/parser': 7.28.6 - '@babel/types': 7.28.6 + '@babel/parser': 7.29.0 + '@babel/types': 7.29.0 '@types/babel__traverse@7.28.0': dependencies: - '@babel/types': 7.28.6 + '@babel/types': 7.29.0 '@types/graceful-fs@4.1.9': dependencies: - '@types/node': 25.0.9 + '@types/node': 25.2.0 '@types/hast@3.0.4': dependencies: @@ -4663,11 +4663,11 @@ snapshots: '@types/node-forge@1.3.14': dependencies: - '@types/node': 25.0.9 + '@types/node': 25.2.0 '@types/node@12.20.55': {} - '@types/node@25.0.9': + '@types/node@25.2.0': dependencies: undici-types: 7.16.0 @@ -4747,9 +4747,9 @@ snapshots: axios: 1.12.2 is-retry-allowed: 2.2.0 - axios-retry@4.5.0(axios@1.13.2): + axios-retry@4.5.0(axios@1.13.4): dependencies: - axios: 1.13.2 + axios: 1.13.4 is-retry-allowed: 2.2.0 axios@1.12.2: @@ -4760,7 +4760,7 @@ snapshots: transitivePeerDependencies: - debug - axios@1.13.2: + axios@1.13.4: dependencies: follow-redirects: 1.15.11 form-data: 4.0.5 @@ -4768,13 +4768,13 @@ snapshots: transitivePeerDependencies: - debug - babel-jest@29.7.0(@babel/core@7.28.6): + babel-jest@29.7.0(@babel/core@7.29.0): dependencies: - '@babel/core': 7.28.6 + '@babel/core': 7.29.0 '@jest/transform': 29.7.0 '@types/babel__core': 7.20.5 babel-plugin-istanbul: 6.1.1 - babel-preset-jest: 29.6.3(@babel/core@7.28.6) + babel-preset-jest: 29.6.3(@babel/core@7.29.0) chalk: 4.1.2 graceful-fs: 4.2.11 slash: 3.0.0 @@ -4794,31 +4794,31 @@ snapshots: babel-plugin-jest-hoist@29.6.3: dependencies: '@babel/template': 7.28.6 - '@babel/types': 7.28.6 + '@babel/types': 7.29.0 '@types/babel__core': 7.20.5 '@types/babel__traverse': 7.28.0 - babel-plugin-polyfill-corejs2@0.4.14(@babel/core@7.28.6): + babel-plugin-polyfill-corejs2@0.4.15(@babel/core@7.29.0): dependencies: - '@babel/compat-data': 7.28.6 - '@babel/core': 7.28.6 - '@babel/helper-define-polyfill-provider': 0.6.5(@babel/core@7.28.6) + '@babel/compat-data': 7.29.0 + '@babel/core': 7.29.0 + '@babel/helper-define-polyfill-provider': 0.6.6(@babel/core@7.29.0) semver: 6.3.1 transitivePeerDependencies: - supports-color - babel-plugin-polyfill-corejs3@0.13.0(@babel/core@7.28.6): + babel-plugin-polyfill-corejs3@0.13.0(@babel/core@7.29.0): dependencies: - '@babel/core': 7.28.6 - '@babel/helper-define-polyfill-provider': 0.6.5(@babel/core@7.28.6) - core-js-compat: 3.47.0 + '@babel/core': 7.29.0 + '@babel/helper-define-polyfill-provider': 0.6.6(@babel/core@7.29.0) + core-js-compat: 3.48.0 transitivePeerDependencies: - supports-color - babel-plugin-polyfill-regenerator@0.6.5(@babel/core@7.28.6): + babel-plugin-polyfill-regenerator@0.6.6(@babel/core@7.29.0): dependencies: - '@babel/core': 7.28.6 - '@babel/helper-define-polyfill-provider': 0.6.5(@babel/core@7.28.6) + '@babel/core': 7.29.0 + '@babel/helper-define-polyfill-provider': 0.6.6(@babel/core@7.29.0) transitivePeerDependencies: - supports-color @@ -4826,42 +4826,42 @@ snapshots: dependencies: hermes-parser: 0.25.1 - babel-plugin-transform-flow-enums@0.0.2(@babel/core@7.28.6): + babel-plugin-transform-flow-enums@0.0.2(@babel/core@7.29.0): dependencies: - '@babel/plugin-syntax-flow': 7.28.6(@babel/core@7.28.6) + '@babel/plugin-syntax-flow': 7.28.6(@babel/core@7.29.0) transitivePeerDependencies: - '@babel/core' - babel-preset-current-node-syntax@1.2.0(@babel/core@7.28.6): - dependencies: - '@babel/core': 7.28.6 - '@babel/plugin-syntax-async-generators': 7.8.4(@babel/core@7.28.6) - '@babel/plugin-syntax-bigint': 7.8.3(@babel/core@7.28.6) - '@babel/plugin-syntax-class-properties': 7.12.13(@babel/core@7.28.6) - '@babel/plugin-syntax-class-static-block': 7.14.5(@babel/core@7.28.6) - '@babel/plugin-syntax-import-attributes': 7.28.6(@babel/core@7.28.6) - '@babel/plugin-syntax-import-meta': 7.10.4(@babel/core@7.28.6) - '@babel/plugin-syntax-json-strings': 7.8.3(@babel/core@7.28.6) - '@babel/plugin-syntax-logical-assignment-operators': 7.10.4(@babel/core@7.28.6) - '@babel/plugin-syntax-nullish-coalescing-operator': 7.8.3(@babel/core@7.28.6) - '@babel/plugin-syntax-numeric-separator': 7.10.4(@babel/core@7.28.6) - '@babel/plugin-syntax-object-rest-spread': 7.8.3(@babel/core@7.28.6) - '@babel/plugin-syntax-optional-catch-binding': 7.8.3(@babel/core@7.28.6) - '@babel/plugin-syntax-optional-chaining': 7.8.3(@babel/core@7.28.6) - '@babel/plugin-syntax-private-property-in-object': 7.14.5(@babel/core@7.28.6) - '@babel/plugin-syntax-top-level-await': 7.14.5(@babel/core@7.28.6) - - babel-preset-jest@29.6.3(@babel/core@7.28.6): - dependencies: - '@babel/core': 7.28.6 + babel-preset-current-node-syntax@1.2.0(@babel/core@7.29.0): + dependencies: + '@babel/core': 7.29.0 + '@babel/plugin-syntax-async-generators': 7.8.4(@babel/core@7.29.0) + '@babel/plugin-syntax-bigint': 7.8.3(@babel/core@7.29.0) + '@babel/plugin-syntax-class-properties': 7.12.13(@babel/core@7.29.0) + '@babel/plugin-syntax-class-static-block': 7.14.5(@babel/core@7.29.0) + '@babel/plugin-syntax-import-attributes': 7.28.6(@babel/core@7.29.0) + '@babel/plugin-syntax-import-meta': 7.10.4(@babel/core@7.29.0) + '@babel/plugin-syntax-json-strings': 7.8.3(@babel/core@7.29.0) + '@babel/plugin-syntax-logical-assignment-operators': 7.10.4(@babel/core@7.29.0) + '@babel/plugin-syntax-nullish-coalescing-operator': 7.8.3(@babel/core@7.29.0) + '@babel/plugin-syntax-numeric-separator': 7.10.4(@babel/core@7.29.0) + '@babel/plugin-syntax-object-rest-spread': 7.8.3(@babel/core@7.29.0) + '@babel/plugin-syntax-optional-catch-binding': 7.8.3(@babel/core@7.29.0) + '@babel/plugin-syntax-optional-chaining': 7.8.3(@babel/core@7.29.0) + '@babel/plugin-syntax-private-property-in-object': 7.14.5(@babel/core@7.29.0) + '@babel/plugin-syntax-top-level-await': 7.14.5(@babel/core@7.29.0) + + babel-preset-jest@29.6.3(@babel/core@7.29.0): + dependencies: + '@babel/core': 7.29.0 babel-plugin-jest-hoist: 29.6.3 - babel-preset-current-node-syntax: 1.2.0(@babel/core@7.28.6) + babel-preset-current-node-syntax: 1.2.0(@babel/core@7.29.0) balanced-match@1.0.2: {} base64-js@1.5.1: {} - baseline-browser-mapping@2.9.16: {} + baseline-browser-mapping@2.9.19: {} bech32@1.1.4: {} @@ -4900,9 +4900,9 @@ snapshots: browserslist@4.28.1: dependencies: - baseline-browser-mapping: 2.9.16 - caniuse-lite: 1.0.30001765 - electron-to-chromium: 1.5.267 + baseline-browser-mapping: 2.9.19 + caniuse-lite: 1.0.30001767 + electron-to-chromium: 1.5.286 node-releases: 2.0.27 update-browserslist-db: 1.2.3(browserslist@4.28.1) @@ -4938,7 +4938,7 @@ snapshots: camelcase@6.3.0: {} - caniuse-lite@1.0.30001765: {} + caniuse-lite@1.0.30001767: {} chalk@2.4.2: dependencies: @@ -4959,7 +4959,7 @@ snapshots: chrome-launcher@0.15.2: dependencies: - '@types/node': 25.0.9 + '@types/node': 25.2.0 escape-string-regexp: 4.0.0 is-wsl: 2.2.0 lighthouse-logger: 1.4.2 @@ -4968,7 +4968,7 @@ snapshots: chromium-edge-launcher@0.2.0: dependencies: - '@types/node': 25.0.9 + '@types/node': 25.2.0 escape-string-regexp: 4.0.0 is-wsl: 2.2.0 lighthouse-logger: 1.4.2 @@ -5030,7 +5030,7 @@ snapshots: convert-source-map@2.0.0: {} - core-js-compat@3.47.0: + core-js-compat@3.48.0: dependencies: browserslist: 4.28.1 @@ -5089,7 +5089,7 @@ snapshots: ee-first@1.1.1: {} - electron-to-chromium@1.5.267: {} + electron-to-chromium@1.5.286: {} elliptic@6.6.1: dependencies: @@ -5184,17 +5184,17 @@ snapshots: eventemitter3@5.0.1: {} - expo-apple-authentication@7.2.4(react-native@0.77.1(@babel/core@7.28.6)(@types/react@18.3.27)(react@18.3.1)): + expo-apple-authentication@7.2.4(react-native@0.77.1(@babel/core@7.29.0)(@types/react@18.3.27)(react@18.3.1)): dependencies: - react-native: 0.77.1(@babel/core@7.28.6)(@types/react@18.3.27)(react@18.3.1) + react-native: 0.77.1(@babel/core@7.29.0)(@types/react@18.3.27)(react@18.3.1) expo-application@6.1.5: {} - expo-constants@17.1.8(react-native@0.77.1(@babel/core@7.28.6)(@types/react@18.3.27)(react@18.3.1)): + expo-constants@17.1.8(react-native@0.77.1(@babel/core@7.29.0)(@types/react@18.3.27)(react@18.3.1)): dependencies: '@expo/config': 11.0.13 '@expo/env': 1.0.7 - react-native: 0.77.1(@babel/core@7.28.6)(@types/react@18.3.27)(react@18.3.1) + react-native: 0.77.1(@babel/core@7.29.0)(@types/react@18.3.27)(react@18.3.1) transitivePeerDependencies: - supports-color @@ -5202,21 +5202,21 @@ snapshots: dependencies: base64-js: 1.5.1 - expo-linking@7.1.7(react-native@0.77.1(@babel/core@7.28.6)(@types/react@18.3.27)(react@18.3.1))(react@18.3.1): + expo-linking@7.1.7(react-native@0.77.1(@babel/core@7.29.0)(@types/react@18.3.27)(react@18.3.1))(react@18.3.1): dependencies: - expo-constants: 17.1.8(react-native@0.77.1(@babel/core@7.28.6)(@types/react@18.3.27)(react@18.3.1)) + expo-constants: 17.1.8(react-native@0.77.1(@babel/core@7.29.0)(@types/react@18.3.27)(react@18.3.1)) invariant: 2.2.4 react: 18.3.1 - react-native: 0.77.1(@babel/core@7.28.6)(@types/react@18.3.27)(react@18.3.1) + react-native: 0.77.1(@babel/core@7.29.0)(@types/react@18.3.27)(react@18.3.1) transitivePeerDependencies: - expo - supports-color expo-secure-store@14.2.4: {} - expo-web-browser@14.2.0(react-native@0.77.1(@babel/core@7.28.6)(@types/react@18.3.27)(react@18.3.1)): + expo-web-browser@14.2.0(react-native@0.77.1(@babel/core@7.29.0)(@types/react@18.3.27)(react@18.3.1)): dependencies: - react-native: 0.77.1(@babel/core@7.28.6)(@types/react@18.3.27)(react@18.3.1) + react-native: 0.77.1(@babel/core@7.29.0)(@types/react@18.3.27)(react@18.3.1) exponential-backoff@3.1.3: {} @@ -5281,7 +5281,7 @@ snapshots: flow-enums-runtime@0.0.6: {} - flow-parser@0.297.0: {} + flow-parser@0.299.0: {} follow-redirects@1.15.11: {} @@ -5348,9 +5348,9 @@ snapshots: dependencies: is-glob: 4.0.3 - glob@13.0.0: + glob@13.0.1: dependencies: - minimatch: 10.1.1 + minimatch: 10.1.2 minipass: 7.1.2 path-scurry: 2.0.1 @@ -5491,8 +5491,8 @@ snapshots: istanbul-lib-instrument@5.2.1: dependencies: - '@babel/core': 7.28.6 - '@babel/parser': 7.28.6 + '@babel/core': 7.29.0 + '@babel/parser': 7.29.0 '@istanbuljs/schema': 0.1.3 istanbul-lib-coverage: 3.2.2 semver: 6.3.1 @@ -5504,7 +5504,7 @@ snapshots: '@jest/environment': 29.7.0 '@jest/fake-timers': 29.7.0 '@jest/types': 29.6.3 - '@types/node': 25.0.9 + '@types/node': 25.2.0 jest-mock: 29.7.0 jest-util: 29.7.0 @@ -5514,7 +5514,7 @@ snapshots: dependencies: '@jest/types': 29.6.3 '@types/graceful-fs': 4.1.9 - '@types/node': 25.0.9 + '@types/node': 25.2.0 anymatch: 3.1.3 fb-watchman: 2.0.2 graceful-fs: 4.2.11 @@ -5528,7 +5528,7 @@ snapshots: jest-message-util@29.7.0: dependencies: - '@babel/code-frame': 7.28.6 + '@babel/code-frame': 7.29.0 '@jest/types': 29.6.3 '@types/stack-utils': 2.0.3 chalk: 4.1.2 @@ -5541,7 +5541,7 @@ snapshots: jest-mock@29.7.0: dependencies: '@jest/types': 29.6.3 - '@types/node': 25.0.9 + '@types/node': 25.2.0 jest-util: 29.7.0 jest-regex-util@29.6.3: {} @@ -5549,7 +5549,7 @@ snapshots: jest-util@29.7.0: dependencies: '@jest/types': 29.6.3 - '@types/node': 25.0.9 + '@types/node': 25.2.0 chalk: 4.1.2 ci-info: 3.9.0 graceful-fs: 4.2.11 @@ -5566,7 +5566,7 @@ snapshots: jest-worker@29.7.0: dependencies: - '@types/node': 25.0.9 + '@types/node': 25.2.0 jest-util: 29.7.0 merge-stream: 2.0.0 supports-color: 8.1.1 @@ -5592,17 +5592,17 @@ snapshots: jscodeshift@17.3.0: dependencies: - '@babel/core': 7.28.6 - '@babel/parser': 7.28.6 - '@babel/plugin-transform-class-properties': 7.28.6(@babel/core@7.28.6) - '@babel/plugin-transform-modules-commonjs': 7.28.6(@babel/core@7.28.6) - '@babel/plugin-transform-nullish-coalescing-operator': 7.28.6(@babel/core@7.28.6) - '@babel/plugin-transform-optional-chaining': 7.28.6(@babel/core@7.28.6) - '@babel/plugin-transform-private-methods': 7.28.6(@babel/core@7.28.6) - '@babel/preset-flow': 7.27.1(@babel/core@7.28.6) - '@babel/preset-typescript': 7.28.5(@babel/core@7.28.6) - '@babel/register': 7.28.6(@babel/core@7.28.6) - flow-parser: 0.297.0 + '@babel/core': 7.29.0 + '@babel/parser': 7.29.0 + '@babel/plugin-transform-class-properties': 7.28.6(@babel/core@7.29.0) + '@babel/plugin-transform-modules-commonjs': 7.28.6(@babel/core@7.29.0) + '@babel/plugin-transform-nullish-coalescing-operator': 7.28.6(@babel/core@7.29.0) + '@babel/plugin-transform-optional-chaining': 7.28.6(@babel/core@7.29.0) + '@babel/plugin-transform-private-methods': 7.28.6(@babel/core@7.29.0) + '@babel/preset-flow': 7.27.1(@babel/core@7.29.0) + '@babel/preset-typescript': 7.28.5(@babel/core@7.29.0) + '@babel/register': 7.28.6(@babel/core@7.29.0) + flow-parser: 0.299.0 graceful-fs: 4.2.11 micromatch: 4.0.8 neo-async: 2.6.2 @@ -5625,22 +5625,22 @@ snapshots: kind-of@6.0.3: {} - knip@5.82.1(@types/node@25.0.9)(typescript@5.9.3): + knip@5.83.0(@types/node@25.2.0)(typescript@5.9.3): dependencies: '@nodelib/fs.walk': 1.2.8 - '@types/node': 25.0.9 + '@types/node': 25.2.0 fast-glob: 3.3.3 formatly: 0.3.0 jiti: 2.6.1 js-yaml: 4.1.1 minimist: 1.2.8 - oxc-resolver: 11.16.3 + oxc-resolver: 11.17.0 picocolors: 1.1.1 picomatch: 4.0.3 smol-toml: 1.6.0 strip-json-comments: 5.0.3 typescript: 5.9.3 - zod: 4.3.5 + zod: 4.3.6 leven@3.1.0: {} @@ -5678,7 +5678,7 @@ snapshots: dependencies: js-tokens: 4.0.0 - lru-cache@11.2.4: {} + lru-cache@11.2.5: {} lru-cache@5.1.1: dependencies: @@ -5718,7 +5718,7 @@ snapshots: metro-babel-transformer@0.81.5: dependencies: - '@babel/core': 7.28.6 + '@babel/core': 7.29.0 flow-enums-runtime: 0.0.6 hermes-parser: 0.25.1 nullthrows: 1.1.1 @@ -5786,9 +5786,9 @@ snapshots: metro-source-map@0.81.5: dependencies: - '@babel/traverse': 7.28.6 - '@babel/traverse--for-generate-function-map': '@babel/traverse@7.28.6' - '@babel/types': 7.28.6 + '@babel/traverse': 7.29.0 + '@babel/traverse--for-generate-function-map': '@babel/traverse@7.29.0' + '@babel/types': 7.29.0 flow-enums-runtime: 0.0.6 invariant: 2.2.4 metro-symbolicate: 0.81.5 @@ -5812,10 +5812,10 @@ snapshots: metro-transform-plugins@0.81.5: dependencies: - '@babel/core': 7.28.6 - '@babel/generator': 7.28.6 + '@babel/core': 7.29.0 + '@babel/generator': 7.29.0 '@babel/template': 7.28.6 - '@babel/traverse': 7.28.6 + '@babel/traverse': 7.29.0 flow-enums-runtime: 0.0.6 nullthrows: 1.1.1 transitivePeerDependencies: @@ -5823,10 +5823,10 @@ snapshots: metro-transform-worker@0.81.5: dependencies: - '@babel/core': 7.28.6 - '@babel/generator': 7.28.6 - '@babel/parser': 7.28.6 - '@babel/types': 7.28.6 + '@babel/core': 7.29.0 + '@babel/generator': 7.29.0 + '@babel/parser': 7.29.0 + '@babel/types': 7.29.0 flow-enums-runtime: 0.0.6 metro: 0.81.5 metro-babel-transformer: 0.81.5 @@ -5843,13 +5843,13 @@ snapshots: metro@0.81.5: dependencies: - '@babel/code-frame': 7.28.6 - '@babel/core': 7.28.6 - '@babel/generator': 7.28.6 - '@babel/parser': 7.28.6 + '@babel/code-frame': 7.29.0 + '@babel/core': 7.29.0 + '@babel/generator': 7.29.0 + '@babel/parser': 7.29.0 '@babel/template': 7.28.6 - '@babel/traverse': 7.28.6 - '@babel/types': 7.28.6 + '@babel/traverse': 7.29.0 + '@babel/types': 7.29.0 accepts: 1.3.8 chalk: 4.1.2 ci-info: 2.0.0 @@ -5905,9 +5905,9 @@ snapshots: minimalistic-crypto-utils@1.0.1: {} - minimatch@10.1.1: + minimatch@10.1.2: dependencies: - '@isaacs/brace-expansion': 5.0.0 + '@isaacs/brace-expansion': 5.0.1 minimatch@3.1.2: dependencies: @@ -5984,28 +5984,28 @@ snapshots: outdent@0.5.0: {} - oxc-resolver@11.16.3: + oxc-resolver@11.17.0: optionalDependencies: - '@oxc-resolver/binding-android-arm-eabi': 11.16.3 - '@oxc-resolver/binding-android-arm64': 11.16.3 - '@oxc-resolver/binding-darwin-arm64': 11.16.3 - '@oxc-resolver/binding-darwin-x64': 11.16.3 - '@oxc-resolver/binding-freebsd-x64': 11.16.3 - '@oxc-resolver/binding-linux-arm-gnueabihf': 11.16.3 - '@oxc-resolver/binding-linux-arm-musleabihf': 11.16.3 - '@oxc-resolver/binding-linux-arm64-gnu': 11.16.3 - '@oxc-resolver/binding-linux-arm64-musl': 11.16.3 - '@oxc-resolver/binding-linux-ppc64-gnu': 11.16.3 - '@oxc-resolver/binding-linux-riscv64-gnu': 11.16.3 - '@oxc-resolver/binding-linux-riscv64-musl': 11.16.3 - '@oxc-resolver/binding-linux-s390x-gnu': 11.16.3 - '@oxc-resolver/binding-linux-x64-gnu': 11.16.3 - '@oxc-resolver/binding-linux-x64-musl': 11.16.3 - '@oxc-resolver/binding-openharmony-arm64': 11.16.3 - '@oxc-resolver/binding-wasm32-wasi': 11.16.3 - '@oxc-resolver/binding-win32-arm64-msvc': 11.16.3 - '@oxc-resolver/binding-win32-ia32-msvc': 11.16.3 - '@oxc-resolver/binding-win32-x64-msvc': 11.16.3 + '@oxc-resolver/binding-android-arm-eabi': 11.17.0 + '@oxc-resolver/binding-android-arm64': 11.17.0 + '@oxc-resolver/binding-darwin-arm64': 11.17.0 + '@oxc-resolver/binding-darwin-x64': 11.17.0 + '@oxc-resolver/binding-freebsd-x64': 11.17.0 + '@oxc-resolver/binding-linux-arm-gnueabihf': 11.17.0 + '@oxc-resolver/binding-linux-arm-musleabihf': 11.17.0 + '@oxc-resolver/binding-linux-arm64-gnu': 11.17.0 + '@oxc-resolver/binding-linux-arm64-musl': 11.17.0 + '@oxc-resolver/binding-linux-ppc64-gnu': 11.17.0 + '@oxc-resolver/binding-linux-riscv64-gnu': 11.17.0 + '@oxc-resolver/binding-linux-riscv64-musl': 11.17.0 + '@oxc-resolver/binding-linux-s390x-gnu': 11.17.0 + '@oxc-resolver/binding-linux-x64-gnu': 11.17.0 + '@oxc-resolver/binding-linux-x64-musl': 11.17.0 + '@oxc-resolver/binding-openharmony-arm64': 11.17.0 + '@oxc-resolver/binding-wasm32-wasi': 11.17.0 + '@oxc-resolver/binding-win32-arm64-msvc': 11.17.0 + '@oxc-resolver/binding-win32-ia32-msvc': 11.17.0 + '@oxc-resolver/binding-win32-x64-msvc': 11.17.0 p-filter@2.1.0: dependencies: @@ -6050,7 +6050,7 @@ snapshots: path-scurry@2.0.1: dependencies: - lru-cache: 11.2.4 + lru-cache: 11.2.5 minipass: 7.1.2 path-type@4.0.0: {} @@ -6111,19 +6111,19 @@ snapshots: react-is@18.3.1: {} - react-native-passkeys@0.4.0(react-native@0.77.1(@babel/core@7.28.6)(@types/react@18.3.27)(react@18.3.1))(react@18.3.1): + react-native-passkeys@0.4.0(react-native@0.77.1(@babel/core@7.29.0)(@types/react@18.3.27)(react@18.3.1))(react@18.3.1): dependencies: react: 18.3.1 - react-native: 0.77.1(@babel/core@7.28.6)(@types/react@18.3.27)(react@18.3.1) + react-native: 0.77.1(@babel/core@7.29.0)(@types/react@18.3.27)(react@18.3.1) - react-native-webview@13.16.0(react-native@0.77.1(@babel/core@7.28.6)(@types/react@18.3.27)(react@18.3.1))(react@18.3.1): + react-native-webview@13.16.0(react-native@0.77.1(@babel/core@7.29.0)(@types/react@18.3.27)(react@18.3.1))(react@18.3.1): dependencies: escape-string-regexp: 4.0.0 invariant: 2.2.4 react: 18.3.1 - react-native: 0.77.1(@babel/core@7.28.6)(@types/react@18.3.27)(react@18.3.1) + react-native: 0.77.1(@babel/core@7.29.0)(@types/react@18.3.27)(react@18.3.1) - react-native@0.77.1(@babel/core@7.28.6)(@types/react@18.3.27)(react@18.3.1): + react-native@0.77.1(@babel/core@7.29.0)(@types/react@18.3.27)(react@18.3.1): dependencies: '@jest/create-cache-key-function': 29.7.0 '@react-native/assets-registry': 0.77.1 @@ -6132,11 +6132,11 @@ snapshots: '@react-native/gradle-plugin': 0.77.1 '@react-native/js-polyfills': 0.77.1 '@react-native/normalize-colors': 0.77.1 - '@react-native/virtualized-lists': 0.77.1(@types/react@18.3.27)(react-native@0.77.1(@babel/core@7.28.6)(@types/react@18.3.27)(react@18.3.1))(react@18.3.1) + '@react-native/virtualized-lists': 0.77.1(@types/react@18.3.27)(react-native@0.77.1(@babel/core@7.29.0)(@types/react@18.3.27)(react@18.3.1))(react@18.3.1) abort-controller: 3.0.0 anser: 1.4.10 ansi-regex: 5.0.1 - babel-jest: 29.7.0(@babel/core@7.28.6) + babel-jest: 29.7.0(@babel/core@7.29.0) babel-plugin-syntax-hermes-parser: 0.25.1 base64-js: 1.5.1 chalk: 4.1.2 @@ -6385,7 +6385,7 @@ snapshots: dependencies: '@jridgewell/gen-mapping': 0.3.13 commander: 4.1.1 - glob: 13.0.0 + glob: 13.0.1 lines-and-columns: 1.2.4 mz: 2.7.0 pirates: 4.0.7 @@ -6459,7 +6459,7 @@ snapshots: typedoc@0.28.16(typescript@5.9.3): dependencies: - '@gerrit0/mini-shiki': 3.21.0 + '@gerrit0/mini-shiki': 3.22.0 lunr: 2.3.9 markdown-it: 14.1.0 minimatch: 9.0.5 @@ -6576,4 +6576,4 @@ snapshots: y18n: 5.0.8 yargs-parser: 21.1.1 - zod@4.3.5: {} + zod@4.3.6: {} diff --git a/src/core/provider.tsx b/src/core/provider.tsx index 33e0e3a..611fd37 100644 --- a/src/core/provider.tsx +++ b/src/core/provider.tsx @@ -258,7 +258,6 @@ export const OpenfortProvider = ({ return new NativePasskeyHandler({ rpId: walletConfig.passkeyRpId, rpName: walletConfig.passkeyRpName, - extractableKey: true, }) } return undefined diff --git a/src/native/passkey.ts b/src/native/passkey.ts index adc0514..c018518 100644 --- a/src/native/passkey.ts +++ b/src/native/passkey.ts @@ -53,9 +53,8 @@ export async function isPasskeySupported(): Promise { export interface NativePasskeyHandlerConfig { rpId?: string rpName?: string - timeoutMillis?: number + timeout?: number derivedKeyLengthBytes?: number - extractableKey?: boolean } // Type definitions for react-native-passkeys @@ -70,7 +69,7 @@ interface PublicKeyCredentialCreationOptions { requireResidentKey?: boolean userVerification?: string } - excludeCredentials?: Array<{ id: string; type: string }> // Iteration 14: Android might require this explicitly + excludeCredentials?: Array<{ id: string; type: string }> extensions?: { prf?: { eval?: { first: string } } } timeout?: number attestation?: string @@ -92,26 +91,23 @@ interface PublicKeyCredentialRequestOptions { export class NativePasskeyHandler implements IPasskeyHandler { private readonly rpId?: string private readonly rpName?: string - private readonly timeoutMillis: number + private readonly timeout: number private readonly derivedKeyLengthBytes: number - private readonly extractableKey: boolean constructor(config: NativePasskeyHandlerConfig) { this.rpId = config.rpId this.rpName = config.rpName - this.timeoutMillis = config.timeoutMillis ?? 60_000 + this.timeout = config.timeout ?? 60_000 this.derivedKeyLengthBytes = config.derivedKeyLengthBytes ?? 32 - this.extractableKey = config.extractableKey ?? true PasskeyUtils.validateKeyByteLength(this.derivedKeyLengthBytes) } /** * Normalizes prf.results.first from the native module to Uint8Array. - * On Android, the bridge may return base64 string or array of numbers; crypto.subtle.importKey - * requires a BufferSource (e.g. Uint8Array) and some React Native polyfills reject plain ArrayBuffer. + * On Android, the bridge may return base64 string or array of numbers. */ - private normalizePRFResultFirst(first: unknown): Uint8Array { + private normalizePRFResult(first: unknown): Uint8Array { if (typeof first === 'string') { return PasskeyUtils.base64URLToUint8Array(first) } @@ -124,43 +120,21 @@ export class NativePasskeyHandler implements IPasskeyHandler { if (Array.isArray(first) || (typeof first === 'object' && first !== null && 'length' in first)) { return new Uint8Array(first as ArrayLike) } - throw new Error('PRF result first: expected base64 string, ArrayBuffer, TypedArray, or array of numbers') - } - - /** - * Returns true when Web Crypto subtle API is available (e.g. browser). - * In React Native, crypto.subtle is typically undefined. - */ - private hasSubtle(): boolean { - return typeof globalThis.crypto !== 'undefined' && typeof globalThis.crypto.subtle !== 'undefined' - } - - /** - * Produces raw key bytes from PRF result when crypto.subtle is unavailable (React Native). - * Truncates to derivedKeyLengthBytes or pads with zeros if shorter. - */ - private getRawKeyBytes(prfResult: ArrayBuffer | Uint8Array): Uint8Array { - return PasskeyUtils.extractRawKeyBytes(prfResult, this.derivedKeyLengthBytes) + throw new Error('PRF result: expected base64 string, ArrayBuffer, TypedArray, or array of numbers') } /** - * Derives a CryptoKey from PRF result (from normalizePRFResultFirst). Key data is a standalone Uint8Array - * accepted by crypto.subtle.importKey. + * Extracts key bytes from PRF result and returns as base64url string. */ - private async deriveFromPRFResult(prfResult: Uint8Array): Promise { - const keyBytes = this.getRawKeyBytes(prfResult) - const keyData = new Uint8Array(this.derivedKeyLengthBytes) - keyData.set(keyBytes.subarray(0, this.derivedKeyLengthBytes)) - const algo = { name: 'AES-CBC', length: this.derivedKeyLengthBytes * 8 } - const usages: KeyUsage[] = ['encrypt', 'decrypt'] - return crypto.subtle.importKey('raw', keyData, algo, this.extractableKey, usages) + private extractKeyBytes(prfResultBytes: Uint8Array): string { + const keyBytes = PasskeyUtils.extractRawKeyBytes(prfResultBytes, this.derivedKeyLengthBytes) + return PasskeyUtils.arrayBufferToBase64URL(keyBytes) } /** - * Creates a passkey and returns the key as base64url string (JSON-friendly for React Native WebView). - * This is the preferred method for React Native. + * Creates a passkey and derives a key using the PRF extension. */ - async createNativePasskey(config: { + async createPasskey(config: { id: string displayName: string seed: string @@ -177,10 +151,10 @@ export class NativePasskeyHandler implements IPasskeyHandler { const userIdBase64URL = PasskeyUtils.arrayBufferToBase64URL(userIdBytes) const publicKey: PublicKeyCredentialCreationOptions = { - challenge: challengeBase64URL, // base64url for Android + challenge: challengeBase64URL, rp: { id: this.rpId, name: this.rpName }, user: { - id: userIdBase64URL, // base64url for Android + id: userIdBase64URL, name: config.id, displayName: config.displayName, }, @@ -192,8 +166,8 @@ export class NativePasskeyHandler implements IPasskeyHandler { residentKey: 'required', userVerification: 'required', }, - excludeCredentials: [], // Empty array for new passkey creation - // PRF extension: react-native-passkeys expects all inputs as base64url (challenge, user.id, prf.eval.first) + excludeCredentials: [], + // PRF extension: react-native-passkeys expects all inputs as base64url extensions: { prf: { eval: { @@ -201,72 +175,46 @@ export class NativePasskeyHandler implements IPasskeyHandler { }, }, }, - timeout: this.timeoutMillis, - attestation: 'none', // Iteration 13: Using "none" per Android docs examples + timeout: this.timeout, + attestation: 'none', } const api = getPasskeysAPI() if (!api?.create || typeof api.create !== 'function') { - throw new Error('react-native-passkeys module not available or create not available') + throw new Error('react-native-passkeys module not available') } + const credential = await api.create(publicKey as any) if (!credential) { - throw new Error('could not create passkey') + throw new Error('Could not create passkey') } const prfResults = credential.clientExtensionResults?.prf - if (!prfResults || !prfResults.results?.first) { + if (!prfResults?.results?.first) { throw new Error('PRF extension not supported or missing results') } - const prfResultBytes = this.normalizePRFResultFirst(prfResults.results.first) - - let keyBase64URL: string | undefined - if (this.hasSubtle()) { - const derivedKey = await this.deriveFromPRFResult(prfResultBytes) - if (this.extractableKey) { - const keyBytes = new Uint8Array(await crypto.subtle.exportKey('raw', derivedKey)) - keyBase64URL = PasskeyUtils.arrayBufferToBase64URL(keyBytes) - } - } else { - if (this.extractableKey) { - const keyBytes = this.getRawKeyBytes(prfResultBytes) - keyBase64URL = PasskeyUtils.arrayBufferToBase64URL(keyBytes) - } - } + const prfResultBytes = this.normalizePRFResult(prfResults.results.first) + const key = this.extractKeyBytes(prfResultBytes) return { id: credential.id, displayName: config.displayName, - key: keyBase64URL, + key, } } /** - * Creates a passkey and returns the key as Uint8Array (for interface compliance). - * Note: The SDK prefers createNativePasskey() which returns base64url for better JSON serialization. + * Derives and exports key material from an existing passkey as base64url string. */ - async createPasskey(config: { - id: string - displayName: string - seed: string - }): Promise<{ id: string; displayName?: string; key?: Uint8Array }> { - const result = await this.createNativePasskey(config) - return { - id: result.id, - displayName: result.displayName, - key: result.key ? PasskeyUtils.base64URLToUint8Array(result.key) : undefined, - } - } - - async deriveKey(config: { id: string; seed: string }): Promise { + async deriveAndExportKey(config: { id: string; seed: string }): Promise { if (!this.rpId) { throw new Error('rpId must be configured') } const challenge = PasskeyUtils.generateChallenge() const challengeBase64URL = PasskeyUtils.arrayBufferToBase64URL(challenge) - // openfort may store credential id as standard base64; react-native-passkeys expects base64url + // Openfort may store credential id as standard base64; react-native-passkeys expects base64url const credentialId = config.id.includes('+') || config.id.includes('/') ? PasskeyUtils.base64ToBase64URL(config.id) : config.id @@ -286,89 +234,20 @@ export class NativePasskeyHandler implements IPasskeyHandler { const api = getPasskeysAPI() if (!api?.get || typeof api.get !== 'function') { - throw new Error('react-native-passkeys is not available. Please ensure it is installed and the app is rebuilt.') - } - const assertion = await api.get(publicKey as any) - if (!assertion) { - throw new Error('could not get passkey assertion') - } - - const prfResults = assertion.clientExtensionResults?.prf - if (!prfResults || !prfResults.results?.first) { - throw new Error('PRF extension not supported or missing results') - } - - const prfResultBytes = this.normalizePRFResultFirst(prfResults.results.first) - if (this.hasSubtle()) { - return this.deriveFromPRFResult(prfResultBytes) - } - throw new Error('deriveKey (CryptoKey) is not supported in React Native; passkey recovery uses deriveAndExportKey.') - } - - /** - * Derives and exports a key as base64url string (JSON-friendly for React Native WebView). - * This is the preferred method for React Native. - */ - async deriveAndExportNativeKey(config: { id: string; seed: string }): Promise { - if (!this.extractableKey) { - throw new Error('Derived keys cannot be exported if extractableKey is not set to true') - } - if (!this.rpId) { - throw new Error('rpId must be configured') + throw new Error('react-native-passkeys module not available') } - const challenge = PasskeyUtils.generateChallenge() - const challengeBase64URL = PasskeyUtils.arrayBufferToBase64URL(challenge) - const credentialId = - config.id.includes('+') || config.id.includes('/') ? PasskeyUtils.base64ToBase64URL(config.id) : config.id - - const publicKey: PublicKeyCredentialRequestOptions = { - challenge: challengeBase64URL, - rpId: this.rpId, - allowCredentials: [{ id: credentialId, type: 'public-key' }], - userVerification: 'required', - extensions: { - prf: { - eval: { - first: PasskeyUtils.arrayBufferToBase64URL(new TextEncoder().encode(config.seed)), - }, - }, - }, - } - - const api = getPasskeysAPI() - if (!api?.get || typeof api.get !== 'function') { - throw new Error('react-native-passkeys is not available. Please ensure it is installed and the app is rebuilt.') - } const assertion = await api.get(publicKey as any) if (!assertion) { - throw new Error('could not get passkey assertion') + throw new Error('Could not get passkey assertion') } const prfResults = assertion.clientExtensionResults?.prf - if (!prfResults || !prfResults.results?.first) { + if (!prfResults?.results?.first) { throw new Error('PRF extension not supported or missing results') } - const prfResultBytes = this.normalizePRFResultFirst(prfResults.results.first) - - let keyBytes: Uint8Array - if (this.hasSubtle()) { - const derivedKey = await this.deriveFromPRFResult(prfResultBytes) - keyBytes = new Uint8Array(await crypto.subtle.exportKey('raw', derivedKey)) - } else { - keyBytes = this.getRawKeyBytes(prfResultBytes) - } - - return PasskeyUtils.arrayBufferToBase64URL(keyBytes) - } - - /** - * Derives and exports a key as Uint8Array (for interface compliance). - * Note: The SDK prefers deriveAndExportNativeKey() which returns base64url for better JSON serialization. - */ - async deriveAndExportKey(config: { id: string; seed: string }): Promise { - const keyBase64URL = await this.deriveAndExportNativeKey(config) - return PasskeyUtils.base64URLToUint8Array(keyBase64URL) + const prfResultBytes = this.normalizePRFResult(prfResults.results.first) + return this.extractKeyBytes(prfResultBytes) } } From 8b32cf9b6277ad230296290f4fba70626d1057e0 Mon Sep 17 00:00:00 2001 From: Jaume Alavedra Date: Thu, 5 Feb 2026 16:53:22 +0100 Subject: [PATCH 05/10] chore: improve passkey --- package.json | 2 +- pnpm-lock.yaml | 1193 +++++++++-------- src/core/provider.tsx | 6 +- src/hooks/wallet/useEmbeddedEthereumWallet.ts | 5 +- src/hooks/wallet/useEmbeddedSolanaWallet.ts | 9 +- src/native/index.ts | 2 +- src/native/passkey.ts | 216 ++- src/native/webview.tsx | 7 +- src/types/index.ts | 10 + 9 files changed, 833 insertions(+), 617 deletions(-) diff --git a/package.json b/package.json index dd9941b..2e499e6 100644 --- a/package.json +++ b/package.json @@ -40,7 +40,7 @@ } }, "dependencies": { - "@openfort/openfort-js": "file:../openfort-core-js/sdk", + "@openfort/openfort-js": "https://pkg.pr.new/@openfort/openfort-js@cc06c35", "react-native-passkeys": "0.4.0" }, "peerDependencies": { diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 12a072c..608180b 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -13,21 +13,21 @@ importers: .: dependencies: '@openfort/openfort-js': - specifier: file:../openfort-core-js/sdk - version: file:../openfort-core-js/sdk + specifier: https://pkg.pr.new/@openfort/openfort-js@cc06c35 + version: https://pkg.pr.new/@openfort/openfort-js@cc06c35 react-native-passkeys: specifier: 0.4.0 - version: 0.4.0(react-native@0.77.1(@babel/core@7.28.6)(@types/react@18.3.27)(react@18.3.1))(react@18.3.1) + version: 0.4.0(react-native@0.77.1(@babel/core@7.29.0)(@types/react@18.3.27)(react@18.3.1))(react@18.3.1) devDependencies: '@biomejs/biome': specifier: ^2.2.4 - version: 2.3.11 + version: 2.3.14 '@changesets/changelog-github': specifier: ^0.5.1 version: 0.5.2 '@changesets/cli': specifier: ^2.29.7 - version: 2.29.8(@types/node@25.0.9) + version: 2.29.8(@types/node@25.2.0) '@size-limit/preset-small-lib': specifier: ^11.2.0 version: 11.2.0(size-limit@11.2.0) @@ -39,7 +39,7 @@ importers: version: 5.7.1 expo-apple-authentication: specifier: ^7.2.4 - version: 7.2.4(react-native@0.77.1(@babel/core@7.28.6)(@types/react@18.3.27)(react@18.3.1)) + version: 7.2.4(react-native@0.77.1(@babel/core@7.29.0)(@types/react@18.3.27)(react@18.3.1)) expo-application: specifier: ^6.1.4 version: 6.1.5 @@ -48,25 +48,25 @@ importers: version: 14.0.2 expo-linking: specifier: ^7.1.5 - version: 7.1.7(react-native@0.77.1(@babel/core@7.28.6)(@types/react@18.3.27)(react@18.3.1))(react@18.3.1) + version: 7.1.7(react-native@0.77.1(@babel/core@7.29.0)(@types/react@18.3.27)(react@18.3.1))(react@18.3.1) expo-secure-store: specifier: ^14.2.3 version: 14.2.4 expo-web-browser: specifier: ^14.1.6 - version: 14.2.0(react-native@0.77.1(@babel/core@7.28.6)(@types/react@18.3.27)(react@18.3.1)) + version: 14.2.0(react-native@0.77.1(@babel/core@7.29.0)(@types/react@18.3.27)(react@18.3.1)) knip: specifier: ^5.69.1 - version: 5.82.1(@types/node@25.0.9)(typescript@5.9.3) + version: 5.83.0(@types/node@25.2.0)(typescript@5.9.3) react: specifier: ^18.3.1 version: 18.3.1 react-native: specifier: 0.77.1 - version: 0.77.1(@babel/core@7.28.6)(@types/react@18.3.27)(react@18.3.1) + version: 0.77.1(@babel/core@7.29.0)(@types/react@18.3.27)(react@18.3.1) react-native-webview: specifier: ^13.15.0 - version: 13.16.0(react-native@0.77.1(@babel/core@7.28.6)(@types/react@18.3.27)(react@18.3.1))(react@18.3.1) + version: 13.16.0(react-native@0.77.1(@babel/core@7.29.0)(@types/react@18.3.27)(react@18.3.1))(react@18.3.1) size-limit: specifier: ^11.2.0 version: 11.2.0 @@ -82,20 +82,20 @@ packages: '@babel/code-frame@7.10.4': resolution: {integrity: sha512-vG6SvB6oYEhvgisZNFRmRCUkLz11c7rp+tbNTynGqc6mS1d5ATd/sGyV6W0KZZnXRKMTzZDRgQT3Ou9jhpAfUg==} - '@babel/code-frame@7.28.6': - resolution: {integrity: sha512-JYgintcMjRiCvS8mMECzaEn+m3PfoQiyqukOMCCVQtoJGYJw8j/8LBJEiqkHLkfwCcs74E3pbAUFNg7d9VNJ+Q==} + '@babel/code-frame@7.29.0': + resolution: {integrity: sha512-9NhCeYjq9+3uxgdtp20LSiJXJvN0FeCtNGpJxuMFZ1Kv3cWUNb6DOhJwUvcVCzKGR66cw4njwM6hrJLqgOwbcw==} engines: {node: '>=6.9.0'} - '@babel/compat-data@7.28.6': - resolution: {integrity: sha512-2lfu57JtzctfIrcGMz992hyLlByuzgIk58+hhGCxjKZ3rWI82NnVLjXcaTqkI2NvlcvOskZaiZ5kjUALo3Lpxg==} + '@babel/compat-data@7.29.0': + resolution: {integrity: sha512-T1NCJqT/j9+cn8fvkt7jtwbLBfLC/1y1c7NtCeXFRgzGTsafi68MRv8yzkYSapBnFA6L3U2VSc02ciDzoAJhJg==} engines: {node: '>=6.9.0'} - '@babel/core@7.28.6': - resolution: {integrity: sha512-H3mcG6ZDLTlYfaSNi0iOKkigqMFvkTKlGUYlD8GW7nNOYRrevuA46iTypPyv+06V3fEmvvazfntkBU34L0azAw==} + '@babel/core@7.29.0': + resolution: {integrity: sha512-CGOfOJqWjg2qW/Mb6zNsDm+u5vFQ8DxXfbM09z69p5Z6+mE1ikP2jUXw+j42Pf1XTYED2Rni5f95npYeuwMDQA==} engines: {node: '>=6.9.0'} - '@babel/generator@7.28.6': - resolution: {integrity: sha512-lOoVRwADj8hjf7al89tvQ2a1lf53Z+7tiXMgpZJL3maQPDxh0DgLMN62B2MKUOFcoodBHLMbDM6WAbKgNy5Suw==} + '@babel/generator@7.29.1': + resolution: {integrity: sha512-qsaF+9Qcm2Qv8SRIMMscAvG4O3lJ0F1GuMo5HR/Bp02LopNgnZBC/EkbevHFeGs4ls/oPz9v+Bsmzbkbe+0dUw==} engines: {node: '>=6.9.0'} '@babel/helper-annotate-as-pure@7.27.3': @@ -118,8 +118,8 @@ packages: peerDependencies: '@babel/core': ^7.0.0 - '@babel/helper-define-polyfill-provider@0.6.5': - resolution: {integrity: sha512-uJnGFcPsWQK8fvjgGP5LZUZZsYGIoPeRjSF5PGwrelYgq7Q15/Ft9NGFp1zglwgIv//W0uG4BevRuSJRyylZPg==} + '@babel/helper-define-polyfill-provider@0.6.6': + resolution: {integrity: sha512-mOAsxeeKkUKayvZR3HeTYD/fICpCPLJrU5ZjelT/PA6WHtNDBOE436YiaEUvHN454bRM3CebhDsIpieCc4texA==} peerDependencies: '@babel/core': ^7.4.0 || ^8.0.0-0 <8.0.0 @@ -189,8 +189,8 @@ packages: resolution: {integrity: sha512-llL88JShoCsth8fF8R4SJnIn+WLvR6ccFxu1H3FlMhDontdcmZWf2HgIZ7AIqV3Xcck1idlohrN4EUBQz6klbw==} engines: {node: '>=6.9.0'} - '@babel/parser@7.28.6': - resolution: {integrity: sha512-TeR9zWR18BvbfPmGbLampPMW+uW1NZnJlRuuHso8i87QZNq2JRF9i6RgxRqtEq+wQGsS19NNTWr2duhnE49mfQ==} + '@babel/parser@7.29.0': + resolution: {integrity: sha512-IyDgFV5GeDUVX4YdF/3CPULtVGSXXMLh1xVIgdCgxApktqnQV0r7/8Nqthg+8YLGaAtdyIlo2qIdZrbCv4+7ww==} engines: {node: '>=6.0.0'} hasBin: true @@ -314,8 +314,8 @@ packages: peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-async-generator-functions@7.28.6': - resolution: {integrity: sha512-9knsChgsMzBV5Yh3kkhrZNxH3oCYAfMBkNNaVN4cP2RVlFPe8wYdwwcnOsAbkdDoV9UjFtOXWrWB52M8W4jNeA==} + '@babel/plugin-transform-async-generator-functions@7.29.0': + resolution: {integrity: sha512-va0VdWro4zlBr2JsXC+ofCPB2iG12wPtVGTWFx2WLDOM3nYQZZIGP82qku2eW/JR83sD+k2k+CsNtyEbUqhU6w==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 @@ -392,8 +392,8 @@ packages: peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-named-capturing-groups-regex@7.27.1': - resolution: {integrity: sha512-SstR5JYy8ddZvD6MhV0tM/j16Qds4mIpJTOd1Yu9J9pJjH93bxHECF7pgtc28XvkzTD6Pxcm/0Z73Hvk7kb3Ng==} + '@babel/plugin-transform-named-capturing-groups-regex@7.29.0': + resolution: {integrity: sha512-1CZQA5KNAD6ZYQLPw7oi5ewtDNxH/2vuCh+6SmvgDfhumForvs8a1o9n0UrEoBD8HU4djO2yWngTQlXl1NDVEQ==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0 @@ -470,14 +470,14 @@ packages: peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-regenerator@7.28.6': - resolution: {integrity: sha512-eZhoEZHYQLL5uc1gS5e9/oTknS0sSSAtd5TkKMUp3J+S/CaUjagc0kOUPsEbDmMeva0nC3WWl4SxVY6+OBuxfw==} + '@babel/plugin-transform-regenerator@7.29.0': + resolution: {integrity: sha512-FijqlqMA7DmRdg/aINBSs04y8XNTYw/lr1gJ2WsmBnnaNw1iS43EPkJW+zK7z65auG3AWRFXWj+NcTQwYptUog==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-runtime@7.28.5': - resolution: {integrity: sha512-20NUVgOrinudkIBzQ2bNxP08YpKprUkRTiRSd2/Z5GOdPImJGkoN4Z7IQe1T5AdyKI1i5L6RBmluqdSzvaq9/w==} + '@babel/plugin-transform-runtime@7.29.0': + resolution: {integrity: sha512-jlaRT5dJtMaMCV6fAuLbsQMSwz/QkvaHOHOSXRitGGwSpR1blCY4KUKoyP2tYO8vJcqYe8cEj96cqSztv3uF9w==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 @@ -538,67 +538,67 @@ packages: resolution: {integrity: sha512-YA6Ma2KsCdGb+WC6UpBVFJGXL58MDA6oyONbjyF/+5sBgxY/dwkhLogbMT2GXXyU84/IhRw/2D1Os1B/giz+BQ==} engines: {node: '>=6.9.0'} - '@babel/traverse@7.28.6': - resolution: {integrity: sha512-fgWX62k02qtjqdSNTAGxmKYY/7FSL9WAS1o2Hu5+I5m9T0yxZzr4cnrfXQ/MX0rIifthCSs6FKTlzYbJcPtMNg==} + '@babel/traverse@7.29.0': + resolution: {integrity: sha512-4HPiQr0X7+waHfyXPZpWPfWL/J7dcN1mx9gL6WdQVMbPnF3+ZhSMs8tCxN7oHddJE9fhNE7+lxdnlyemKfJRuA==} engines: {node: '>=6.9.0'} - '@babel/types@7.28.6': - resolution: {integrity: sha512-0ZrskXVEHSWIqZM/sQZ4EV3jZJXRkio/WCxaqKZP1g//CEWEPSfeZFcms4XeKBCHU0ZKnIkdJeU/kF+eRp5lBg==} + '@babel/types@7.29.0': + resolution: {integrity: sha512-LwdZHpScM4Qz8Xw2iKSzS+cfglZzJGvofQICy7W7v4caru4EaAmyUuO6BGrbyQ2mYV11W0U8j5mBhd14dd3B0A==} engines: {node: '>=6.9.0'} - '@biomejs/biome@2.3.11': - resolution: {integrity: sha512-/zt+6qazBWguPG6+eWmiELqO+9jRsMZ/DBU3lfuU2ngtIQYzymocHhKiZRyrbra4aCOoyTg/BmY+6WH5mv9xmQ==} + '@biomejs/biome@2.3.14': + resolution: {integrity: sha512-QMT6QviX0WqXJCaiqVMiBUCr5WRQ1iFSjvOLoTk6auKukJMvnMzWucXpwZB0e8F00/1/BsS9DzcKgWH+CLqVuA==} engines: {node: '>=14.21.3'} hasBin: true - '@biomejs/cli-darwin-arm64@2.3.11': - resolution: {integrity: sha512-/uXXkBcPKVQY7rc9Ys2CrlirBJYbpESEDme7RKiBD6MmqR2w3j0+ZZXRIL2xiaNPsIMMNhP1YnA+jRRxoOAFrA==} + '@biomejs/cli-darwin-arm64@2.3.14': + resolution: {integrity: sha512-UJGPpvWJMkLxSRtpCAKfKh41Q4JJXisvxZL8ChN1eNW3m/WlPFJ6EFDCE7YfUb4XS8ZFi3C1dFpxUJ0Ety5n+A==} engines: {node: '>=14.21.3'} cpu: [arm64] os: [darwin] - '@biomejs/cli-darwin-x64@2.3.11': - resolution: {integrity: sha512-fh7nnvbweDPm2xEmFjfmq7zSUiox88plgdHF9OIW4i99WnXrAC3o2P3ag9judoUMv8FCSUnlwJCM1B64nO5Fbg==} + '@biomejs/cli-darwin-x64@2.3.14': + resolution: {integrity: sha512-PNkLNQG6RLo8lG7QoWe/hhnMxJIt1tEimoXpGQjwS/dkdNiKBLPv4RpeQl8o3s1OKI3ZOR5XPiYtmbGGHAOnLA==} engines: {node: '>=14.21.3'} cpu: [x64] os: [darwin] - '@biomejs/cli-linux-arm64-musl@2.3.11': - resolution: {integrity: sha512-XPSQ+XIPZMLaZ6zveQdwNjbX+QdROEd1zPgMwD47zvHV+tCGB88VH+aynyGxAHdzL+Tm/+DtKST5SECs4iwCLg==} + '@biomejs/cli-linux-arm64-musl@2.3.14': + resolution: {integrity: sha512-LInRbXhYujtL3sH2TMCH/UBwJZsoGwfQjBrMfl84CD4hL/41C/EU5mldqf1yoFpsI0iPWuU83U+nB2TUUypWeg==} engines: {node: '>=14.21.3'} cpu: [arm64] os: [linux] libc: [musl] - '@biomejs/cli-linux-arm64@2.3.11': - resolution: {integrity: sha512-l4xkGa9E7Uc0/05qU2lMYfN1H+fzzkHgaJoy98wO+b/7Gl78srbCRRgwYSW+BTLixTBrM6Ede5NSBwt7rd/i6g==} + '@biomejs/cli-linux-arm64@2.3.14': + resolution: {integrity: sha512-KT67FKfzIw6DNnUNdYlBg+eU24Go3n75GWK6NwU4+yJmDYFe9i/MjiI+U/iEzKvo0g7G7MZqoyrhIYuND2w8QQ==} engines: {node: '>=14.21.3'} cpu: [arm64] os: [linux] libc: [glibc] - '@biomejs/cli-linux-x64-musl@2.3.11': - resolution: {integrity: sha512-vU7a8wLs5C9yJ4CB8a44r12aXYb8yYgBn+WeyzbMjaCMklzCv1oXr8x+VEyWodgJt9bDmhiaW/I0RHbn7rsNmw==} + '@biomejs/cli-linux-x64-musl@2.3.14': + resolution: {integrity: sha512-KQU7EkbBBuHPW3/rAcoiVmhlPtDSGOGRPv9js7qJVpYTzjQmVR+C9Rfcz+ti8YCH+zT1J52tuBybtP4IodjxZQ==} engines: {node: '>=14.21.3'} cpu: [x64] os: [linux] libc: [musl] - '@biomejs/cli-linux-x64@2.3.11': - resolution: {integrity: sha512-/1s9V/H3cSe0r0Mv/Z8JryF5x9ywRxywomqZVLHAoa/uN0eY7F8gEngWKNS5vbbN/BsfpCG5yeBT5ENh50Frxg==} + '@biomejs/cli-linux-x64@2.3.14': + resolution: {integrity: sha512-ZsZzQsl9U+wxFrGGS4f6UxREUlgHwmEfu1IrXlgNFrNnd5Th6lIJr8KmSzu/+meSa9f4rzFrbEW9LBBA6ScoMA==} engines: {node: '>=14.21.3'} cpu: [x64] os: [linux] libc: [glibc] - '@biomejs/cli-win32-arm64@2.3.11': - resolution: {integrity: sha512-PZQ6ElCOnkYapSsysiTy0+fYX+agXPlWugh6+eQ6uPKI3vKAqNp6TnMhoM3oY2NltSB89hz59o8xIfOdyhi9Iw==} + '@biomejs/cli-win32-arm64@2.3.14': + resolution: {integrity: sha512-+IKYkj/pUBbnRf1G1+RlyA3LWiDgra1xpS7H2g4BuOzzRbRB+hmlw0yFsLprHhbbt7jUzbzAbAjK/Pn0FDnh1A==} engines: {node: '>=14.21.3'} cpu: [arm64] os: [win32] - '@biomejs/cli-win32-x64@2.3.11': - resolution: {integrity: sha512-43VrG813EW+b5+YbDbz31uUsheX+qFKCpXeY9kfdAx+ww3naKxeVkTD9zLIWxUPfJquANMHrmW3wbe/037G0Qg==} + '@biomejs/cli-win32-x64@2.3.14': + resolution: {integrity: sha512-oizCjdyQ3WJEswpb3Chdngeat56rIdSYK12JI3iI11Mt5T5EXcZ7WLuowzEaFPNJ3zmOQFliMN8QY1Pi+qsfdQ==} engines: {node: '>=14.21.3'} cpu: [x64] os: [win32] @@ -916,8 +916,8 @@ packages: '@expo/sdk-runtime-versions@1.0.0': resolution: {integrity: sha512-Doz2bfiPndXYFPMRwPyGa1k5QaKDVpY806UJj570epIiMzWaYyCtobasyfC++qfIXVb5Ocy7r3tP9d62hAQ7IQ==} - '@gerrit0/mini-shiki@3.21.0': - resolution: {integrity: sha512-9PrsT5DjZA+w3lur/aOIx3FlDeHdyCEFlv9U+fmsVyjPZh61G5SYURQ/1ebe2U63KbDmI2V8IhIUegWb8hjOyg==} + '@gerrit0/mini-shiki@3.22.0': + resolution: {integrity: sha512-jMpciqEVUBKE1QwU64S4saNMzpsSza6diNCk4MWAeCxO2+LFi2FIFmL2S0VDLzEJCxuvCbU783xi8Hp/gkM5CQ==} '@inquirer/external-editor@1.0.3': resolution: {integrity: sha512-RWbSrDiYmO4LbejWY7ttpxczuwQyZLBUyygsA9Nsv95hpzUWwnNTVQmAq3xuh7vNwCp07UTmE5i11XAEExx4RA==} @@ -932,8 +932,8 @@ packages: resolution: {integrity: sha512-yzMTt9lEb8Gv7zRioUilSglI0c0smZ9k5D65677DLWLtWJaXIS3CqcGyUFByYKlnUj6TkjLVs54fBl6+TiGQDQ==} engines: {node: 20 || >=22} - '@isaacs/brace-expansion@5.0.0': - resolution: {integrity: sha512-ZT55BDLV0yv0RBm2czMiZ+SqCGO7AvmOM3G/w2xhVPH+te0aKgFjmBvGlL1dH+ql2tgGO3MVrbb3jCKyvpgnxA==} + '@isaacs/brace-expansion@5.0.1': + resolution: {integrity: sha512-WMz71T1JS624nWj2n2fnYAuPovhv7EUhk69R6i9dsVyzxt5eM3bjwvgk9L+APE1TRscGysAVMANkB0jh0LQZrQ==} engines: {node: 20 || >=22} '@isaacs/ttlcache@1.4.1': @@ -1012,117 +1012,118 @@ packages: resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} engines: {node: '>= 8'} - '@openfort/openfort-js@file:../openfort-core-js/sdk': - resolution: {directory: ../openfort-core-js/sdk, type: directory} + '@openfort/openfort-js@https://pkg.pr.new/@openfort/openfort-js@cc06c35': + resolution: {tarball: https://pkg.pr.new/@openfort/openfort-js@cc06c35} + version: 1.1.4 '@openfort/shield-js@0.1.34': resolution: {integrity: sha512-bJxQc0zk0VPxk7CWSE5NZp5Bv8nYnStwG5GKXrS2A6hxEt0vf4BMu9db4IUiHxmgGaFWrdAnbSCSZ5AU1gwyew==} - '@oxc-resolver/binding-android-arm-eabi@11.16.3': - resolution: {integrity: sha512-CVyWHu6ACDqDcJxR4nmGiG8vDF4TISJHqRNzac5z/gPQycs/QrP/1pDsJBy0MD7jSw8nVq2E5WqeHQKabBG/Jg==} + '@oxc-resolver/binding-android-arm-eabi@11.17.0': + resolution: {integrity: sha512-kVnY21v0GyZ/+LG6EIO48wK3mE79BUuakHUYLIqobO/Qqq4mJsjuYXMSn3JtLcKZpN1HDVit4UHpGJHef1lrlw==} cpu: [arm] os: [android] - '@oxc-resolver/binding-android-arm64@11.16.3': - resolution: {integrity: sha512-tTIoB7plLeh2o6Ay7NnV5CJb6QUXdxI7Shnsp2ECrLSV81k+oVE3WXYrQSh4ltWL75i0OgU5Bj3bsuyg5SMepw==} + '@oxc-resolver/binding-android-arm64@11.17.0': + resolution: {integrity: sha512-Pf8e3XcsK9a8RHInoAtEcrwf2vp7V9bSturyUUYxw9syW6E7cGi7z9+6ADXxm+8KAevVfLA7pfBg8NXTvz/HOw==} cpu: [arm64] os: [android] - '@oxc-resolver/binding-darwin-arm64@11.16.3': - resolution: {integrity: sha512-OXKVH7uwYd3Rbw1s2yJZd6/w+6b01iaokZubYhDAq4tOYArr+YCS+lr81q1hsTPPRZeIsWE+rJLulmf1qHdYZA==} + '@oxc-resolver/binding-darwin-arm64@11.17.0': + resolution: {integrity: sha512-lVSgKt3biecofXVr8e1hnfX0IYMd4A6VCxmvOmHsFt5Zbmt0lkO4S2ap2bvQwYDYh5ghUNamC7M2L8K6vishhQ==} cpu: [arm64] os: [darwin] - '@oxc-resolver/binding-darwin-x64@11.16.3': - resolution: {integrity: sha512-WwjQ4WdnCxVYZYd3e3oY5XbV3JeLy9pPMK+eQQ2m8DtqUtbxnvPpAYC2Knv/2bS6q5JiktqOVJ2Hfia3OSo0/A==} + '@oxc-resolver/binding-darwin-x64@11.17.0': + resolution: {integrity: sha512-+/raxVJE1bo7R4fA9Yp0wm3slaCOofTEeUzM01YqEGcRDLHB92WRGjRhagMG2wGlvqFuSiTp81DwSbBVo/g6AQ==} cpu: [x64] os: [darwin] - '@oxc-resolver/binding-freebsd-x64@11.16.3': - resolution: {integrity: sha512-4OHKFGJBBfOnuJnelbCS4eBorI6cj54FUxcZJwEXPeoLc8yzORBoJ2w+fQbwjlQcUUZLEg92uGhKCRiUoqznjg==} + '@oxc-resolver/binding-freebsd-x64@11.17.0': + resolution: {integrity: sha512-x9Ks56n+n8h0TLhzA6sJXa2tGh3uvMGpBppg6PWf8oF0s5S/3p/J6k1vJJ9lIUtTmenfCQEGKnFokpRP4fLTLg==} cpu: [x64] os: [freebsd] - '@oxc-resolver/binding-linux-arm-gnueabihf@11.16.3': - resolution: {integrity: sha512-OM3W0NLt9u7uKwG/yZbeXABansZC0oZeDF1nKgvcZoRw4/Yak6/l4S0onBfDFeYMY94eYeAt2bl60e30lgsb5A==} + '@oxc-resolver/binding-linux-arm-gnueabihf@11.17.0': + resolution: {integrity: sha512-Wf3w07Ow9kXVJrS0zmsaFHKOGhXKXE8j1tNyy+qIYDsQWQ4UQZVx5SjlDTcqBnFerlp3Z3Is0RjmVzgoLG3qkA==} cpu: [arm] os: [linux] - '@oxc-resolver/binding-linux-arm-musleabihf@11.16.3': - resolution: {integrity: sha512-MRs7D7i1t7ACsAdTuP81gLZES918EpBmiUyEl8fu302yQB+4L7L7z0Ui8BWnthUTQd3nAU9dXvENLK/SqRVH8A==} + '@oxc-resolver/binding-linux-arm-musleabihf@11.17.0': + resolution: {integrity: sha512-N0OKA1al1gQ5Gm7Fui1RWlXaHRNZlwMoBLn3TVtSXX+WbnlZoVyDqqOqFL8+pVEHhhxEA2LR8kmM0JO6FAk6dg==} cpu: [arm] os: [linux] - '@oxc-resolver/binding-linux-arm64-gnu@11.16.3': - resolution: {integrity: sha512-0eVYZxSceNqGADzhlV4ZRqkHF0fjWxRXQOB7Qwl5y1gN/XYUDvMfip+ngtzj4dM7zQT4U97hUhJ7PUKSy/JIGQ==} + '@oxc-resolver/binding-linux-arm64-gnu@11.17.0': + resolution: {integrity: sha512-wdcQ7Niad9JpjZIGEeqKJnTvczVunqlZ/C06QzR5zOQNeLVRScQ9S5IesKWUAPsJQDizV+teQX53nTK+Z5Iy+g==} cpu: [arm64] os: [linux] libc: [glibc] - '@oxc-resolver/binding-linux-arm64-musl@11.16.3': - resolution: {integrity: sha512-B1BvLeZbgDdVN0FvU40l5Q7lej8310WlabCBaouk8jY7H7xbI8phtomTtk3Efmevgfy5hImaQJu6++OmcFb2NQ==} + '@oxc-resolver/binding-linux-arm64-musl@11.17.0': + resolution: {integrity: sha512-65B2/t39HQN5AEhkLsC+9yBD1iRUkKOIhfmJEJ7g6wQ9kylra7JRmNmALFjbsj0VJsoSQkpM8K07kUZuNJ9Kxw==} cpu: [arm64] os: [linux] libc: [musl] - '@oxc-resolver/binding-linux-ppc64-gnu@11.16.3': - resolution: {integrity: sha512-q7khglic3Jqak7uDgA3MFnjDeI7krQT595GDZpvFq785fmFYSx8rlTkoHzmhQtUisYtl4XG7WUscwsoidFUI4w==} + '@oxc-resolver/binding-linux-ppc64-gnu@11.17.0': + resolution: {integrity: sha512-kExgm3TLK21dNMmcH+xiYGbc6BUWvT03PUZ2aYn8mUzGPeeORklBhg3iYcaBI3ZQHB25412X1Z6LLYNjt4aIaA==} cpu: [ppc64] os: [linux] libc: [glibc] - '@oxc-resolver/binding-linux-riscv64-gnu@11.16.3': - resolution: {integrity: sha512-aFRNmQNPzDgQEbw2s3c8yJYRimacSDI+u9df8rn5nSKzTVitHmbEpZqfxpwNLCKIuLSNmozHR1z1OT+oZVeYqg==} + '@oxc-resolver/binding-linux-riscv64-gnu@11.17.0': + resolution: {integrity: sha512-1utUJC714/ydykZQE8c7QhpEyM4SaslMfRXxN9G61KYazr6ndt85LaubK3EZCSD50vVEfF4PVwFysCSO7LN9uA==} cpu: [riscv64] os: [linux] libc: [glibc] - '@oxc-resolver/binding-linux-riscv64-musl@11.16.3': - resolution: {integrity: sha512-vZI85SvSMADcEL9G1TIrV0Rlkc1fY5Mup0DdlVC5EHPysZB4hXXHpr+h09pjlK5y+5om5foIzDRxE1baUCaWOA==} + '@oxc-resolver/binding-linux-riscv64-musl@11.17.0': + resolution: {integrity: sha512-mayiYOl3LMmtO2CLn4I5lhanfxEo0LAqlT/EQyFbu1ZN3RS+Xa7Q3JEM0wBpVIyfO/pqFrjvC5LXw/mHNDEL7A==} cpu: [riscv64] os: [linux] libc: [musl] - '@oxc-resolver/binding-linux-s390x-gnu@11.16.3': - resolution: {integrity: sha512-xiLBnaUlddFEzRHiHiSGEMbkg8EwZY6VD8F+3GfnFsiK3xg/4boaUV2bwXd+nUzl3UDQOMW1QcZJ4jJSb0qiJA==} + '@oxc-resolver/binding-linux-s390x-gnu@11.17.0': + resolution: {integrity: sha512-Ow/yI+CrUHxIIhn/Y1sP/xoRKbCC3x9O1giKr3G/pjMe+TCJ5ZmfqVWU61JWwh1naC8X5Xa7uyLnbzyYqPsHfg==} cpu: [s390x] os: [linux] libc: [glibc] - '@oxc-resolver/binding-linux-x64-gnu@11.16.3': - resolution: {integrity: sha512-6y0b05wIazJJgwu7yU/AYGFswzQQudYJBOb/otDhiDacp1+6ye8egoxx63iVo9lSpDbipL++54AJQFlcOHCB+g==} + '@oxc-resolver/binding-linux-x64-gnu@11.17.0': + resolution: {integrity: sha512-Z4J7XlPMQOLPANyu6y3B3V417Md4LKH5bV6bhqgaG99qLHmU5LV2k9ErV14fSqoRc/GU/qOpqMdotxiJqN/YWg==} cpu: [x64] os: [linux] libc: [glibc] - '@oxc-resolver/binding-linux-x64-musl@11.16.3': - resolution: {integrity: sha512-RmMgwuMa42c9logS7Pjprf5KCp8J1a1bFiuBFtG9/+yMu0BhY2t+0VR/um7pwtkNFvIQqAVh6gDOg/PnoKRcdQ==} + '@oxc-resolver/binding-linux-x64-musl@11.17.0': + resolution: {integrity: sha512-0effK+8lhzXsgsh0Ny2ngdnTPF30v6QQzVFApJ1Ctk315YgpGkghkelvrLYYgtgeFJFrzwmOJ2nDvCrUFKsS2Q==} cpu: [x64] os: [linux] libc: [musl] - '@oxc-resolver/binding-openharmony-arm64@11.16.3': - resolution: {integrity: sha512-/7AYRkjjW7xu1nrHgWUFy99Duj4/ydOBVaHtODie9/M6fFngo+8uQDFFnzmr4q//sd/cchIerISp/8CQ5TsqIA==} + '@oxc-resolver/binding-openharmony-arm64@11.17.0': + resolution: {integrity: sha512-kFB48dRUW6RovAICZaxHKdtZe+e94fSTNA2OedXokzMctoU54NPZcv0vUX5PMqyikLIKJBIlW7laQidnAzNrDA==} cpu: [arm64] os: [openharmony] - '@oxc-resolver/binding-wasm32-wasi@11.16.3': - resolution: {integrity: sha512-urM6aIPbi5di4BSlnpd/TWtDJgG6RD06HvLBuNM+qOYuFtY1/xPbzQ2LanBI2ycpqIoIZwsChyplALwAMdyfCQ==} + '@oxc-resolver/binding-wasm32-wasi@11.17.0': + resolution: {integrity: sha512-a3elKSBLPT0OoRPxTkCIIc+4xnOELolEBkPyvdj01a6PSdSmyJ1NExWjWLaXnT6wBMblvKde5RmSwEi3j+jZpg==} engines: {node: '>=14.0.0'} cpu: [wasm32] - '@oxc-resolver/binding-win32-arm64-msvc@11.16.3': - resolution: {integrity: sha512-QuvLqGKf7frxWHQ5TnrcY0C/hJpANsaez99Q4dAk1hen7lDTD4FBPtBzPnntLFXeaVG3PnSmnVjlv0vMILwU7Q==} + '@oxc-resolver/binding-win32-arm64-msvc@11.17.0': + resolution: {integrity: sha512-4eszUsSDb9YVx0RtYkPWkxxtSZIOgfeiX//nG5cwRRArg178w4RCqEF1kbKPud9HPrp1rXh7gE4x911OhvTnPg==} cpu: [arm64] os: [win32] - '@oxc-resolver/binding-win32-ia32-msvc@11.16.3': - resolution: {integrity: sha512-QR/witXK6BmYTlEP8CCjC5fxeG5U9A6a50pNpC1nLnhAcJjtzFG8KcQ5etVy/XvCLiDc7fReaAWRNWtCaIhM8Q==} + '@oxc-resolver/binding-win32-ia32-msvc@11.17.0': + resolution: {integrity: sha512-t946xTXMmR7yGH0KAe9rB055/X4EPIu93JUvjchl2cizR5QbuwkUV7vLS2BS6x6sfvDoQb6rWYnV1HCci6tBSg==} cpu: [ia32] os: [win32] - '@oxc-resolver/binding-win32-x64-msvc@11.16.3': - resolution: {integrity: sha512-bFuJRKOscsDAEZ/a8BezcTMAe2BQ/OBRfuMLFUuINfTR5qGVcm4a3xBIrQVepBaPxFj16SJdRjGe05vDiwZmFw==} + '@oxc-resolver/binding-win32-x64-msvc@11.17.0': + resolution: {integrity: sha512-pX6s2kMXLQg+hlqKk5UqOW09iLLxnTkvn8ohpYp2Mhsm2yzDPCx9dyOHiB/CQixLzTkLQgWWJykN4Z3UfRKW4Q==} cpu: [x64] os: [win32] @@ -1211,23 +1212,23 @@ packages: resolution: {integrity: sha512-KX62+qIt4xgy8eHKHiikfhz2p5fOciXd0Cl+dNzhgPFq8klq4MGMNaf148GB3M/vBqP4nw/eFvRMAayFCgdRQw==} engines: {node: '>=18'} - '@shikijs/engine-oniguruma@3.21.0': - resolution: {integrity: sha512-OYknTCct6qiwpQDqDdf3iedRdzj6hFlOPv5hMvI+hkWfCKs5mlJ4TXziBG9nyabLwGulrUjHiCq3xCspSzErYQ==} + '@shikijs/engine-oniguruma@3.22.0': + resolution: {integrity: sha512-DyXsOG0vGtNtl7ygvabHd7Mt5EY8gCNqR9Y7Lpbbd/PbJvgWrqaKzH1JW6H6qFkuUa8aCxoiYVv8/YfFljiQxA==} - '@shikijs/langs@3.21.0': - resolution: {integrity: sha512-g6mn5m+Y6GBJ4wxmBYqalK9Sp0CFkUqfNzUy2pJglUginz6ZpWbaWjDB4fbQ/8SHzFjYbtU6Ddlp1pc+PPNDVA==} + '@shikijs/langs@3.22.0': + resolution: {integrity: sha512-x/42TfhWmp6H00T6uwVrdTJGKgNdFbrEdhaDwSR5fd5zhQ1Q46bHq9EO61SCEWJR0HY7z2HNDMaBZp8JRmKiIA==} - '@shikijs/themes@3.21.0': - resolution: {integrity: sha512-BAE4cr9EDiZyYzwIHEk7JTBJ9CzlPuM4PchfcA5ao1dWXb25nv6hYsoDiBq2aZK9E3dlt3WB78uI96UESD+8Mw==} + '@shikijs/themes@3.22.0': + resolution: {integrity: sha512-o+tlOKqsr6FE4+mYJG08tfCFDS+3CG20HbldXeVoyP+cYSUxDhrFf3GPjE60U55iOkkjbpY2uC3It/eeja35/g==} - '@shikijs/types@3.21.0': - resolution: {integrity: sha512-zGrWOxZ0/+0ovPY7PvBU2gIS9tmhSUUt30jAcNV0Bq0gb2S98gwfjIs1vxlmH5zM7/4YxLamT6ChlqqAJmPPjA==} + '@shikijs/types@3.22.0': + resolution: {integrity: sha512-491iAekgKDBFE67z70Ok5a8KBMsQ2IJwOWw3us/7ffQkIBCyOQfm/aNwVMBUriP02QshIfgHCBSIYAl3u2eWjg==} '@shikijs/vscode-textmate@10.0.2': resolution: {integrity: sha512-83yeghZ2xxin3Nj8z1NMd/NCuca+gsYXswywDy5bHvwlWL8tpTQmzGeUuHd9FC3E/SBEMvzJRwWEOz5gGes9Qg==} - '@sinclair/typebox@0.27.8': - resolution: {integrity: sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==} + '@sinclair/typebox@0.27.10': + resolution: {integrity: sha512-MTBk/3jGLNB2tVxv6uLlFh1iu64iYOQ2PbdOSK3NW8JZsmlaOh2q6sdtKowBhfw8QFLmYNzTW4/oK4uATIi6ZA==} '@sinonjs/commons@3.0.1': resolution: {integrity: sha512-K3mCHKQ9sVh8o1C9cxkwxaOmXoAMlDxC1mYyHrjqOWEcBjYr76t96zL2zlj5dUGZ3HSw240X1qgH3Mjf1yJWpQ==} @@ -1288,8 +1289,8 @@ packages: '@types/node@12.20.55': resolution: {integrity: sha512-J8xLz7q2OFulZ2cyGTLE1TbbZcjpno7FaN6zdJNrgAdrJ+DZzh/uFR6YrTb4C+nXakvud8Q4+rbhoIWlYQbUFQ==} - '@types/node@25.0.9': - resolution: {integrity: sha512-/rpCXHlCWeqClNBwUhDcusJxXYDjZTyE8v5oTO7WbL8eij2nKhUeU89/6xgjU7N4/Vh3He0BtyhJdQbDyhiXAw==} + '@types/node@25.2.0': + resolution: {integrity: sha512-DZ8VwRFUNzuqJ5khrvwMXHmvPe+zGayJhr2CDNiKB1WBE1ST8Djl00D0IC4vvNmHMdj6DlbYRIaFE7WHjlDl5w==} '@types/prop-types@15.7.15': resolution: {integrity: sha512-F6bEyamV9jKGAFBEmlQnesRPGOQqS2+Uwi0Em15xenOxHaf2hv6L8YCVn3rPdPJOiJfPiCnLIRyvwVaqMY3MIw==} @@ -1387,8 +1388,8 @@ packages: axios@1.12.2: resolution: {integrity: sha512-vMJzPewAlRyOgxV2dU0Cuz2O8zzzx9VYtbJOaBgXFeLc4IV/Eg50n4LowmehOOR61S8ZMpc2K5Sa7g6A4jfkUw==} - axios@1.13.2: - resolution: {integrity: sha512-VPk9ebNqPcy5lRGuSlKx752IlDatOjT9paPlm8A7yOuW2Fbvp4X3JznJtT4f0GzGLLiWE9W8onz51SqLYwzGaA==} + axios@1.13.4: + resolution: {integrity: sha512-1wVkUaAO6WyaYtCkcYCOx12ZgpGf9Zif+qXa4n+oYzK558YryKqiL6UWwd5DqiH3VRW0GYhTZQ/vlgJrCoNQlg==} babel-jest@29.7.0: resolution: {integrity: sha512-BrvGY3xZSwEcCzKvKsCi2GgHqDqsYkOP4/by5xCgIwGXQxIEh+8ew3gmrE1y7XRR6LHZIj6yLYnUi/mm2KXKBg==} @@ -1404,8 +1405,8 @@ packages: resolution: {integrity: sha512-ESAc/RJvGTFEzRwOTT4+lNDk/GNHMkKbNzsvT0qKRfDyyYTskxB5rnU2njIDYVxXCBHHEI1c0YwHob3WaYujOg==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - babel-plugin-polyfill-corejs2@0.4.14: - resolution: {integrity: sha512-Co2Y9wX854ts6U8gAAPXfn0GmAyctHuK8n0Yhfjd6t30g7yvKjspvvOo9yG+z52PZRgFErt7Ka2pYnXCjLKEpg==} + babel-plugin-polyfill-corejs2@0.4.15: + resolution: {integrity: sha512-hR3GwrRwHUfYwGfrisXPIDP3JcYfBrW7wKE7+Au6wDYl7fm/ka1NEII6kORzxNU556JjfidZeBsO10kYvtV1aw==} peerDependencies: '@babel/core': ^7.4.0 || ^8.0.0-0 <8.0.0 @@ -1414,8 +1415,8 @@ packages: peerDependencies: '@babel/core': ^7.4.0 || ^8.0.0-0 <8.0.0 - babel-plugin-polyfill-regenerator@0.6.5: - resolution: {integrity: sha512-ISqQ2frbiNU9vIJkzg7dlPpznPZ4jOiUQ1uSmB0fEHeowtN3COYRsXr/xexn64NpU13P06jc/L5TgiJXOgrbEg==} + babel-plugin-polyfill-regenerator@0.6.6: + resolution: {integrity: sha512-hYm+XLYRMvupxiQzrvXUj7YyvFFVfv5gI0R71AJzudg1g2AI2vyCPPIFEBjk162/wFzti3inBHo7isWFuEVS/A==} peerDependencies: '@babel/core': ^7.4.0 || ^8.0.0-0 <8.0.0 @@ -1442,8 +1443,8 @@ packages: base64-js@1.5.1: resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==} - baseline-browser-mapping@2.9.16: - resolution: {integrity: sha512-KeUZdBuxngy825i8xvzaK1Ncnkx0tBmb3k8DkEuqjKRkmtvNTjey2ZsNeh8Dw4lfKvbCOu9oeNx2TKm2vHqcRw==} + baseline-browser-mapping@2.9.19: + resolution: {integrity: sha512-ipDqC8FrAl/76p2SSWKSI+H9tFwm7vYqXQrItCuiVPt26Km0jS+NzSsBWAaBusvSbQcfJG+JitdMm+wZAgTYqg==} hasBin: true bech32@1.1.4: @@ -1525,8 +1526,8 @@ packages: resolution: {integrity: sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==} engines: {node: '>=10'} - caniuse-lite@1.0.30001765: - resolution: {integrity: sha512-LWcNtSyZrakjECqmpP4qdg0MMGdN368D7X8XvvAqOcqMv0RxnlqVKZl2V6/mBR68oYMxOZPLw/gO7DuisMHUvQ==} + caniuse-lite@1.0.30001767: + resolution: {integrity: sha512-34+zUAMhSH+r+9eKmYG+k2Rpt8XttfE4yXAjoZvkAPs15xcYQhyBYdalJ65BzivAvGRMViEjy6oKr/S91loekQ==} chalk@2.4.2: resolution: {integrity: sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==} @@ -1607,8 +1608,8 @@ packages: convert-source-map@2.0.0: resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==} - core-js-compat@3.47.0: - resolution: {integrity: sha512-IGfuznZ/n7Kp9+nypamBhvwdwLsW6KC8IOaURw2doAK5e98AG3acVLdh0woOnEqCfUtS+Vu882JE4k/DAm3ItQ==} + core-js-compat@3.48.0: + resolution: {integrity: sha512-OM4cAF3D6VtH/WkLtWvyNC56EZVXsZdU3iqaMG2B4WvYrlqU831pc4UtG5yp0sE9z8Y02wVN7PjW5Zf9Gt0f1Q==} cosmiconfig@5.2.1: resolution: {integrity: sha512-H65gsXo1SKjf8zmrJ67eJk8aIRKV5ff2D4uKZIBZShbhGSpEmsQOPW/SKMKYhSTrqR7ufy6RP69rPogdaPh/kA==} @@ -1684,8 +1685,8 @@ packages: ee-first@1.1.1: resolution: {integrity: sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==} - electron-to-chromium@1.5.267: - resolution: {integrity: sha512-0Drusm6MVRXSOJpGbaSVgcQsuB4hEkMpHXaVstcPmhu5LIedxs1xNK/nIxmQIU/RPC0+1/o0AVZfBTkTNJOdUw==} + electron-to-chromium@1.5.286: + resolution: {integrity: sha512-9tfDXhJ4RKFNerfjdCcZfufu49vg620741MNs26a9+bhLThdB+plgMeou98CAaHu/WATj2iHOOHTp1hWtABj2A==} elliptic@6.6.1: resolution: {integrity: sha512-RaddvvMatK2LJHqFJ+YA4WysVN5Ita9E35botqIYspQ4TkRAlCicdzKOjlyv/1Za5RyTNn7di//eEV0uTAfe3g==} @@ -1864,8 +1865,8 @@ packages: flow-enums-runtime@0.0.6: resolution: {integrity: sha512-3PYnM29RFXwvAN6Pc/scUfkI7RwhQ/xqyLUyPNlXUp9S40zI8nup9tUSrTLSVnWGBN38FNiGWbwZOB6uR4OGdw==} - flow-parser@0.297.0: - resolution: {integrity: sha512-51kjVLwebsDNCrBrm+VLBJ1rEZffrWzsEPjfbdhf/0lxQkX01zFoiojwEW7l6902p1ZQI/ju/QmLGowwne23lg==} + flow-parser@0.299.0: + resolution: {integrity: sha512-phGMRoNt6SNglPHGRbCyWm9/pxfe6t/t4++EIYPaBGWT6e0lphLBgUMrvpL62NbRo9R549o3oqrbKHq82kANCw==} engines: {node: '>=0.4.0'} follow-redirects@1.15.11: @@ -1937,13 +1938,13 @@ packages: resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} engines: {node: '>= 6'} - glob@13.0.0: - resolution: {integrity: sha512-tvZgpqk6fz4BaNZ66ZsRaZnbHvP/jG3uKJvAZOwEVUL4RTA5nJeeLYfyN9/VA8NX/V3IBG+hkeuGpKjvELkVhA==} + glob@13.0.1: + resolution: {integrity: sha512-B7U/vJpE3DkJ5WXTgTpTRN63uV42DseiXXKMwG14LQBXmsdeIoHAPbU/MEo6II0k5ED74uc2ZGTC6MwHFQhF6w==} engines: {node: 20 || >=22} glob@7.2.3: resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==} - deprecated: Glob versions prior to v9 are no longer supported + deprecated: Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me globby@11.1.0: resolution: {integrity: sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==} @@ -2187,8 +2188,8 @@ packages: resolution: {integrity: sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==} engines: {node: '>=0.10.0'} - knip@5.82.1: - resolution: {integrity: sha512-1nQk+5AcnkqL40kGQXfouzAEXkTR+eSrgo/8m1d0BMei4eAzFwghoXC4gOKbACgBiCof7hE8wkBVDsEvznf85w==} + knip@5.83.0: + resolution: {integrity: sha512-FfmaHMntpZB13B1oJQMSs1hTOZxd0TOn+FYB3oWEI02XlxTW3RH4H7d8z5Us3g0ziHCYyl7z0B1xi8ENP3QEKA==} engines: {node: '>=18.18.0'} hasBin: true peerDependencies: @@ -2233,8 +2234,8 @@ packages: resolution: {integrity: sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==} hasBin: true - lru-cache@11.2.4: - resolution: {integrity: sha512-B5Y16Jr9LB9dHVkh6ZevG+vAbOsNOYCX+sXvFWFu7B3Iz5mijW3zdbMyhsh8ANd2mSWBYdJgnqi+mL7/LrOPYg==} + lru-cache@11.2.5: + resolution: {integrity: sha512-vFrFJkWtJvJnD5hg+hJvVE8Lh/TcMzKnTgCWmtBipwI5yLX/iX+5UB2tfuyODF5E7k9xEzMdYgGqaSb1c0c5Yw==} engines: {node: 20 || >=22} lru-cache@5.1.1: @@ -2355,8 +2356,8 @@ packages: minimalistic-crypto-utils@1.0.1: resolution: {integrity: sha512-JIYlbt6g8i5jKfJ3xz7rF0LXmv2TkDxBLUkiBeZ7bAx4GnnNMr8xFpGnOxn6GhTEHx3SjRrZEoU+j04prX1ktg==} - minimatch@10.1.1: - resolution: {integrity: sha512-enIvLvRAFZYXJzkCYG5RKmPfrFArdLv+R+lbQ53BmIMLIry74bjKzX6iHAm8WYamJkhSSEabrWN5D97XnKObjQ==} + minimatch@10.1.2: + resolution: {integrity: sha512-fu656aJ0n2kcXwsnwnv9g24tkU5uSmOlTjd6WyyaKm2Z+h1qmY6bAjrcaIxF/BslFqbZ8UBtbJi7KgQOZD2PTw==} engines: {node: 20 || >=22} minimatch@3.1.2: @@ -2458,8 +2459,8 @@ packages: outdent@0.5.0: resolution: {integrity: sha512-/jHxFIzoMXdqPzTaCpFzAAWhpkSjZPF4Vsn6jAfNpmbH/ymsmd7Qc6VE9BGn0L6YMj6uwpQLxCECpus4ukKS9Q==} - oxc-resolver@11.16.3: - resolution: {integrity: sha512-goLOJH3x69VouGWGp5CgCIHyksmOZzXr36lsRmQz1APg3SPFORrvV2q7nsUHMzLVa6ZJgNwkgUSJFsbCpAWkCA==} + oxc-resolver@11.17.0: + resolution: {integrity: sha512-R5P2Tw6th+nQJdNcZGfuppBS/sM0x1EukqYffmlfX2xXLgLGCCPwu4ruEr9Sx29mrpkHgITc130Qps2JR90NdQ==} p-filter@2.1.0: resolution: {integrity: sha512-ZBxxZ5sL2HghephhpGAQdoskxplTwr7ICaehZwLIlfL6acuVgZPm8yBNuRAFBGEqtD/hmUeq9eqLg2ys9Xr/yw==} @@ -3082,8 +3083,8 @@ packages: resolution: {integrity: sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==} engines: {node: '>=12'} - zod@4.3.5: - resolution: {integrity: sha512-k7Nwx6vuWx1IJ9Bjuf4Zt1PEllcwe7cls3VNzm4CQ1/hgtFUK2bRNG3rvnpPUhFjmqJKAKtjV576KnUkHocg/g==} + zod@4.3.6: + resolution: {integrity: sha512-rftlrkhHZOcjDwkGlnUtZZkvaPHCsDATp4pGpuOOMDaTdDDXF91wuVDJoWoPsKX/3YPQ5fHuF3STjcYyKr+Qhg==} snapshots: @@ -3091,25 +3092,25 @@ snapshots: dependencies: '@babel/highlight': 7.25.9 - '@babel/code-frame@7.28.6': + '@babel/code-frame@7.29.0': dependencies: '@babel/helper-validator-identifier': 7.28.5 js-tokens: 4.0.0 picocolors: 1.1.1 - '@babel/compat-data@7.28.6': {} + '@babel/compat-data@7.29.0': {} - '@babel/core@7.28.6': + '@babel/core@7.29.0': dependencies: - '@babel/code-frame': 7.28.6 - '@babel/generator': 7.28.6 + '@babel/code-frame': 7.29.0 + '@babel/generator': 7.29.1 '@babel/helper-compilation-targets': 7.28.6 - '@babel/helper-module-transforms': 7.28.6(@babel/core@7.28.6) + '@babel/helper-module-transforms': 7.28.6(@babel/core@7.29.0) '@babel/helpers': 7.28.6 - '@babel/parser': 7.28.6 + '@babel/parser': 7.29.0 '@babel/template': 7.28.6 - '@babel/traverse': 7.28.6 - '@babel/types': 7.28.6 + '@babel/traverse': 7.29.0 + '@babel/types': 7.29.0 '@jridgewell/remapping': 2.3.5 convert-source-map: 2.0.0 debug: 4.4.3 @@ -3119,49 +3120,49 @@ snapshots: transitivePeerDependencies: - supports-color - '@babel/generator@7.28.6': + '@babel/generator@7.29.1': dependencies: - '@babel/parser': 7.28.6 - '@babel/types': 7.28.6 + '@babel/parser': 7.29.0 + '@babel/types': 7.29.0 '@jridgewell/gen-mapping': 0.3.13 '@jridgewell/trace-mapping': 0.3.31 jsesc: 3.1.0 '@babel/helper-annotate-as-pure@7.27.3': dependencies: - '@babel/types': 7.28.6 + '@babel/types': 7.29.0 '@babel/helper-compilation-targets@7.28.6': dependencies: - '@babel/compat-data': 7.28.6 + '@babel/compat-data': 7.29.0 '@babel/helper-validator-option': 7.27.1 browserslist: 4.28.1 lru-cache: 5.1.1 semver: 6.3.1 - '@babel/helper-create-class-features-plugin@7.28.6(@babel/core@7.28.6)': + '@babel/helper-create-class-features-plugin@7.28.6(@babel/core@7.29.0)': dependencies: - '@babel/core': 7.28.6 + '@babel/core': 7.29.0 '@babel/helper-annotate-as-pure': 7.27.3 '@babel/helper-member-expression-to-functions': 7.28.5 '@babel/helper-optimise-call-expression': 7.27.1 - '@babel/helper-replace-supers': 7.28.6(@babel/core@7.28.6) + '@babel/helper-replace-supers': 7.28.6(@babel/core@7.29.0) '@babel/helper-skip-transparent-expression-wrappers': 7.27.1 - '@babel/traverse': 7.28.6 + '@babel/traverse': 7.29.0 semver: 6.3.1 transitivePeerDependencies: - supports-color - '@babel/helper-create-regexp-features-plugin@7.28.5(@babel/core@7.28.6)': + '@babel/helper-create-regexp-features-plugin@7.28.5(@babel/core@7.29.0)': dependencies: - '@babel/core': 7.28.6 + '@babel/core': 7.29.0 '@babel/helper-annotate-as-pure': 7.27.3 regexpu-core: 6.4.0 semver: 6.3.1 - '@babel/helper-define-polyfill-provider@0.6.5(@babel/core@7.28.6)': + '@babel/helper-define-polyfill-provider@0.6.6(@babel/core@7.29.0)': dependencies: - '@babel/core': 7.28.6 + '@babel/core': 7.29.0 '@babel/helper-compilation-targets': 7.28.6 '@babel/helper-plugin-utils': 7.28.6 debug: 4.4.3 @@ -3174,55 +3175,55 @@ snapshots: '@babel/helper-member-expression-to-functions@7.28.5': dependencies: - '@babel/traverse': 7.28.6 - '@babel/types': 7.28.6 + '@babel/traverse': 7.29.0 + '@babel/types': 7.29.0 transitivePeerDependencies: - supports-color '@babel/helper-module-imports@7.28.6': dependencies: - '@babel/traverse': 7.28.6 - '@babel/types': 7.28.6 + '@babel/traverse': 7.29.0 + '@babel/types': 7.29.0 transitivePeerDependencies: - supports-color - '@babel/helper-module-transforms@7.28.6(@babel/core@7.28.6)': + '@babel/helper-module-transforms@7.28.6(@babel/core@7.29.0)': dependencies: - '@babel/core': 7.28.6 + '@babel/core': 7.29.0 '@babel/helper-module-imports': 7.28.6 '@babel/helper-validator-identifier': 7.28.5 - '@babel/traverse': 7.28.6 + '@babel/traverse': 7.29.0 transitivePeerDependencies: - supports-color '@babel/helper-optimise-call-expression@7.27.1': dependencies: - '@babel/types': 7.28.6 + '@babel/types': 7.29.0 '@babel/helper-plugin-utils@7.28.6': {} - '@babel/helper-remap-async-to-generator@7.27.1(@babel/core@7.28.6)': + '@babel/helper-remap-async-to-generator@7.27.1(@babel/core@7.29.0)': dependencies: - '@babel/core': 7.28.6 + '@babel/core': 7.29.0 '@babel/helper-annotate-as-pure': 7.27.3 '@babel/helper-wrap-function': 7.28.6 - '@babel/traverse': 7.28.6 + '@babel/traverse': 7.29.0 transitivePeerDependencies: - supports-color - '@babel/helper-replace-supers@7.28.6(@babel/core@7.28.6)': + '@babel/helper-replace-supers@7.28.6(@babel/core@7.29.0)': dependencies: - '@babel/core': 7.28.6 + '@babel/core': 7.29.0 '@babel/helper-member-expression-to-functions': 7.28.5 '@babel/helper-optimise-call-expression': 7.27.1 - '@babel/traverse': 7.28.6 + '@babel/traverse': 7.29.0 transitivePeerDependencies: - supports-color '@babel/helper-skip-transparent-expression-wrappers@7.27.1': dependencies: - '@babel/traverse': 7.28.6 - '@babel/types': 7.28.6 + '@babel/traverse': 7.29.0 + '@babel/types': 7.29.0 transitivePeerDependencies: - supports-color @@ -3235,15 +3236,15 @@ snapshots: '@babel/helper-wrap-function@7.28.6': dependencies: '@babel/template': 7.28.6 - '@babel/traverse': 7.28.6 - '@babel/types': 7.28.6 + '@babel/traverse': 7.29.0 + '@babel/types': 7.29.0 transitivePeerDependencies: - supports-color '@babel/helpers@7.28.6': dependencies: '@babel/template': 7.28.6 - '@babel/types': 7.28.6 + '@babel/types': 7.29.0 '@babel/highlight@7.25.9': dependencies: @@ -3252,379 +3253,379 @@ snapshots: js-tokens: 4.0.0 picocolors: 1.1.1 - '@babel/parser@7.28.6': + '@babel/parser@7.29.0': dependencies: - '@babel/types': 7.28.6 + '@babel/types': 7.29.0 - '@babel/plugin-proposal-export-default-from@7.27.1(@babel/core@7.28.6)': + '@babel/plugin-proposal-export-default-from@7.27.1(@babel/core@7.29.0)': dependencies: - '@babel/core': 7.28.6 + '@babel/core': 7.29.0 '@babel/helper-plugin-utils': 7.28.6 - '@babel/plugin-syntax-async-generators@7.8.4(@babel/core@7.28.6)': + '@babel/plugin-syntax-async-generators@7.8.4(@babel/core@7.29.0)': dependencies: - '@babel/core': 7.28.6 + '@babel/core': 7.29.0 '@babel/helper-plugin-utils': 7.28.6 - '@babel/plugin-syntax-bigint@7.8.3(@babel/core@7.28.6)': + '@babel/plugin-syntax-bigint@7.8.3(@babel/core@7.29.0)': dependencies: - '@babel/core': 7.28.6 + '@babel/core': 7.29.0 '@babel/helper-plugin-utils': 7.28.6 - '@babel/plugin-syntax-class-properties@7.12.13(@babel/core@7.28.6)': + '@babel/plugin-syntax-class-properties@7.12.13(@babel/core@7.29.0)': dependencies: - '@babel/core': 7.28.6 + '@babel/core': 7.29.0 '@babel/helper-plugin-utils': 7.28.6 - '@babel/plugin-syntax-class-static-block@7.14.5(@babel/core@7.28.6)': + '@babel/plugin-syntax-class-static-block@7.14.5(@babel/core@7.29.0)': dependencies: - '@babel/core': 7.28.6 + '@babel/core': 7.29.0 '@babel/helper-plugin-utils': 7.28.6 - '@babel/plugin-syntax-dynamic-import@7.8.3(@babel/core@7.28.6)': + '@babel/plugin-syntax-dynamic-import@7.8.3(@babel/core@7.29.0)': dependencies: - '@babel/core': 7.28.6 + '@babel/core': 7.29.0 '@babel/helper-plugin-utils': 7.28.6 - '@babel/plugin-syntax-export-default-from@7.28.6(@babel/core@7.28.6)': + '@babel/plugin-syntax-export-default-from@7.28.6(@babel/core@7.29.0)': dependencies: - '@babel/core': 7.28.6 + '@babel/core': 7.29.0 '@babel/helper-plugin-utils': 7.28.6 - '@babel/plugin-syntax-flow@7.28.6(@babel/core@7.28.6)': + '@babel/plugin-syntax-flow@7.28.6(@babel/core@7.29.0)': dependencies: - '@babel/core': 7.28.6 + '@babel/core': 7.29.0 '@babel/helper-plugin-utils': 7.28.6 - '@babel/plugin-syntax-import-attributes@7.28.6(@babel/core@7.28.6)': + '@babel/plugin-syntax-import-attributes@7.28.6(@babel/core@7.29.0)': dependencies: - '@babel/core': 7.28.6 + '@babel/core': 7.29.0 '@babel/helper-plugin-utils': 7.28.6 - '@babel/plugin-syntax-import-meta@7.10.4(@babel/core@7.28.6)': + '@babel/plugin-syntax-import-meta@7.10.4(@babel/core@7.29.0)': dependencies: - '@babel/core': 7.28.6 + '@babel/core': 7.29.0 '@babel/helper-plugin-utils': 7.28.6 - '@babel/plugin-syntax-json-strings@7.8.3(@babel/core@7.28.6)': + '@babel/plugin-syntax-json-strings@7.8.3(@babel/core@7.29.0)': dependencies: - '@babel/core': 7.28.6 + '@babel/core': 7.29.0 '@babel/helper-plugin-utils': 7.28.6 - '@babel/plugin-syntax-jsx@7.28.6(@babel/core@7.28.6)': + '@babel/plugin-syntax-jsx@7.28.6(@babel/core@7.29.0)': dependencies: - '@babel/core': 7.28.6 + '@babel/core': 7.29.0 '@babel/helper-plugin-utils': 7.28.6 - '@babel/plugin-syntax-logical-assignment-operators@7.10.4(@babel/core@7.28.6)': + '@babel/plugin-syntax-logical-assignment-operators@7.10.4(@babel/core@7.29.0)': dependencies: - '@babel/core': 7.28.6 + '@babel/core': 7.29.0 '@babel/helper-plugin-utils': 7.28.6 - '@babel/plugin-syntax-nullish-coalescing-operator@7.8.3(@babel/core@7.28.6)': + '@babel/plugin-syntax-nullish-coalescing-operator@7.8.3(@babel/core@7.29.0)': dependencies: - '@babel/core': 7.28.6 + '@babel/core': 7.29.0 '@babel/helper-plugin-utils': 7.28.6 - '@babel/plugin-syntax-numeric-separator@7.10.4(@babel/core@7.28.6)': + '@babel/plugin-syntax-numeric-separator@7.10.4(@babel/core@7.29.0)': dependencies: - '@babel/core': 7.28.6 + '@babel/core': 7.29.0 '@babel/helper-plugin-utils': 7.28.6 - '@babel/plugin-syntax-object-rest-spread@7.8.3(@babel/core@7.28.6)': + '@babel/plugin-syntax-object-rest-spread@7.8.3(@babel/core@7.29.0)': dependencies: - '@babel/core': 7.28.6 + '@babel/core': 7.29.0 '@babel/helper-plugin-utils': 7.28.6 - '@babel/plugin-syntax-optional-catch-binding@7.8.3(@babel/core@7.28.6)': + '@babel/plugin-syntax-optional-catch-binding@7.8.3(@babel/core@7.29.0)': dependencies: - '@babel/core': 7.28.6 + '@babel/core': 7.29.0 '@babel/helper-plugin-utils': 7.28.6 - '@babel/plugin-syntax-optional-chaining@7.8.3(@babel/core@7.28.6)': + '@babel/plugin-syntax-optional-chaining@7.8.3(@babel/core@7.29.0)': dependencies: - '@babel/core': 7.28.6 + '@babel/core': 7.29.0 '@babel/helper-plugin-utils': 7.28.6 - '@babel/plugin-syntax-private-property-in-object@7.14.5(@babel/core@7.28.6)': + '@babel/plugin-syntax-private-property-in-object@7.14.5(@babel/core@7.29.0)': dependencies: - '@babel/core': 7.28.6 + '@babel/core': 7.29.0 '@babel/helper-plugin-utils': 7.28.6 - '@babel/plugin-syntax-top-level-await@7.14.5(@babel/core@7.28.6)': + '@babel/plugin-syntax-top-level-await@7.14.5(@babel/core@7.29.0)': dependencies: - '@babel/core': 7.28.6 + '@babel/core': 7.29.0 '@babel/helper-plugin-utils': 7.28.6 - '@babel/plugin-syntax-typescript@7.28.6(@babel/core@7.28.6)': + '@babel/plugin-syntax-typescript@7.28.6(@babel/core@7.29.0)': dependencies: - '@babel/core': 7.28.6 + '@babel/core': 7.29.0 '@babel/helper-plugin-utils': 7.28.6 - '@babel/plugin-transform-arrow-functions@7.27.1(@babel/core@7.28.6)': + '@babel/plugin-transform-arrow-functions@7.27.1(@babel/core@7.29.0)': dependencies: - '@babel/core': 7.28.6 + '@babel/core': 7.29.0 '@babel/helper-plugin-utils': 7.28.6 - '@babel/plugin-transform-async-generator-functions@7.28.6(@babel/core@7.28.6)': + '@babel/plugin-transform-async-generator-functions@7.29.0(@babel/core@7.29.0)': dependencies: - '@babel/core': 7.28.6 + '@babel/core': 7.29.0 '@babel/helper-plugin-utils': 7.28.6 - '@babel/helper-remap-async-to-generator': 7.27.1(@babel/core@7.28.6) - '@babel/traverse': 7.28.6 + '@babel/helper-remap-async-to-generator': 7.27.1(@babel/core@7.29.0) + '@babel/traverse': 7.29.0 transitivePeerDependencies: - supports-color - '@babel/plugin-transform-async-to-generator@7.28.6(@babel/core@7.28.6)': + '@babel/plugin-transform-async-to-generator@7.28.6(@babel/core@7.29.0)': dependencies: - '@babel/core': 7.28.6 + '@babel/core': 7.29.0 '@babel/helper-module-imports': 7.28.6 '@babel/helper-plugin-utils': 7.28.6 - '@babel/helper-remap-async-to-generator': 7.27.1(@babel/core@7.28.6) + '@babel/helper-remap-async-to-generator': 7.27.1(@babel/core@7.29.0) transitivePeerDependencies: - supports-color - '@babel/plugin-transform-block-scoping@7.28.6(@babel/core@7.28.6)': + '@babel/plugin-transform-block-scoping@7.28.6(@babel/core@7.29.0)': dependencies: - '@babel/core': 7.28.6 + '@babel/core': 7.29.0 '@babel/helper-plugin-utils': 7.28.6 - '@babel/plugin-transform-class-properties@7.28.6(@babel/core@7.28.6)': + '@babel/plugin-transform-class-properties@7.28.6(@babel/core@7.29.0)': dependencies: - '@babel/core': 7.28.6 - '@babel/helper-create-class-features-plugin': 7.28.6(@babel/core@7.28.6) + '@babel/core': 7.29.0 + '@babel/helper-create-class-features-plugin': 7.28.6(@babel/core@7.29.0) '@babel/helper-plugin-utils': 7.28.6 transitivePeerDependencies: - supports-color - '@babel/plugin-transform-classes@7.28.6(@babel/core@7.28.6)': + '@babel/plugin-transform-classes@7.28.6(@babel/core@7.29.0)': dependencies: - '@babel/core': 7.28.6 + '@babel/core': 7.29.0 '@babel/helper-annotate-as-pure': 7.27.3 '@babel/helper-compilation-targets': 7.28.6 '@babel/helper-globals': 7.28.0 '@babel/helper-plugin-utils': 7.28.6 - '@babel/helper-replace-supers': 7.28.6(@babel/core@7.28.6) - '@babel/traverse': 7.28.6 + '@babel/helper-replace-supers': 7.28.6(@babel/core@7.29.0) + '@babel/traverse': 7.29.0 transitivePeerDependencies: - supports-color - '@babel/plugin-transform-computed-properties@7.28.6(@babel/core@7.28.6)': + '@babel/plugin-transform-computed-properties@7.28.6(@babel/core@7.29.0)': dependencies: - '@babel/core': 7.28.6 + '@babel/core': 7.29.0 '@babel/helper-plugin-utils': 7.28.6 '@babel/template': 7.28.6 - '@babel/plugin-transform-destructuring@7.28.5(@babel/core@7.28.6)': + '@babel/plugin-transform-destructuring@7.28.5(@babel/core@7.29.0)': dependencies: - '@babel/core': 7.28.6 + '@babel/core': 7.29.0 '@babel/helper-plugin-utils': 7.28.6 - '@babel/traverse': 7.28.6 + '@babel/traverse': 7.29.0 transitivePeerDependencies: - supports-color - '@babel/plugin-transform-flow-strip-types@7.27.1(@babel/core@7.28.6)': + '@babel/plugin-transform-flow-strip-types@7.27.1(@babel/core@7.29.0)': dependencies: - '@babel/core': 7.28.6 + '@babel/core': 7.29.0 '@babel/helper-plugin-utils': 7.28.6 - '@babel/plugin-syntax-flow': 7.28.6(@babel/core@7.28.6) + '@babel/plugin-syntax-flow': 7.28.6(@babel/core@7.29.0) - '@babel/plugin-transform-for-of@7.27.1(@babel/core@7.28.6)': + '@babel/plugin-transform-for-of@7.27.1(@babel/core@7.29.0)': dependencies: - '@babel/core': 7.28.6 + '@babel/core': 7.29.0 '@babel/helper-plugin-utils': 7.28.6 '@babel/helper-skip-transparent-expression-wrappers': 7.27.1 transitivePeerDependencies: - supports-color - '@babel/plugin-transform-function-name@7.27.1(@babel/core@7.28.6)': + '@babel/plugin-transform-function-name@7.27.1(@babel/core@7.29.0)': dependencies: - '@babel/core': 7.28.6 + '@babel/core': 7.29.0 '@babel/helper-compilation-targets': 7.28.6 '@babel/helper-plugin-utils': 7.28.6 - '@babel/traverse': 7.28.6 + '@babel/traverse': 7.29.0 transitivePeerDependencies: - supports-color - '@babel/plugin-transform-literals@7.27.1(@babel/core@7.28.6)': + '@babel/plugin-transform-literals@7.27.1(@babel/core@7.29.0)': dependencies: - '@babel/core': 7.28.6 + '@babel/core': 7.29.0 '@babel/helper-plugin-utils': 7.28.6 - '@babel/plugin-transform-logical-assignment-operators@7.28.6(@babel/core@7.28.6)': + '@babel/plugin-transform-logical-assignment-operators@7.28.6(@babel/core@7.29.0)': dependencies: - '@babel/core': 7.28.6 + '@babel/core': 7.29.0 '@babel/helper-plugin-utils': 7.28.6 - '@babel/plugin-transform-modules-commonjs@7.28.6(@babel/core@7.28.6)': + '@babel/plugin-transform-modules-commonjs@7.28.6(@babel/core@7.29.0)': dependencies: - '@babel/core': 7.28.6 - '@babel/helper-module-transforms': 7.28.6(@babel/core@7.28.6) + '@babel/core': 7.29.0 + '@babel/helper-module-transforms': 7.28.6(@babel/core@7.29.0) '@babel/helper-plugin-utils': 7.28.6 transitivePeerDependencies: - supports-color - '@babel/plugin-transform-named-capturing-groups-regex@7.27.1(@babel/core@7.28.6)': + '@babel/plugin-transform-named-capturing-groups-regex@7.29.0(@babel/core@7.29.0)': dependencies: - '@babel/core': 7.28.6 - '@babel/helper-create-regexp-features-plugin': 7.28.5(@babel/core@7.28.6) + '@babel/core': 7.29.0 + '@babel/helper-create-regexp-features-plugin': 7.28.5(@babel/core@7.29.0) '@babel/helper-plugin-utils': 7.28.6 - '@babel/plugin-transform-nullish-coalescing-operator@7.28.6(@babel/core@7.28.6)': + '@babel/plugin-transform-nullish-coalescing-operator@7.28.6(@babel/core@7.29.0)': dependencies: - '@babel/core': 7.28.6 + '@babel/core': 7.29.0 '@babel/helper-plugin-utils': 7.28.6 - '@babel/plugin-transform-numeric-separator@7.28.6(@babel/core@7.28.6)': + '@babel/plugin-transform-numeric-separator@7.28.6(@babel/core@7.29.0)': dependencies: - '@babel/core': 7.28.6 + '@babel/core': 7.29.0 '@babel/helper-plugin-utils': 7.28.6 - '@babel/plugin-transform-object-rest-spread@7.28.6(@babel/core@7.28.6)': + '@babel/plugin-transform-object-rest-spread@7.28.6(@babel/core@7.29.0)': dependencies: - '@babel/core': 7.28.6 + '@babel/core': 7.29.0 '@babel/helper-compilation-targets': 7.28.6 '@babel/helper-plugin-utils': 7.28.6 - '@babel/plugin-transform-destructuring': 7.28.5(@babel/core@7.28.6) - '@babel/plugin-transform-parameters': 7.27.7(@babel/core@7.28.6) - '@babel/traverse': 7.28.6 + '@babel/plugin-transform-destructuring': 7.28.5(@babel/core@7.29.0) + '@babel/plugin-transform-parameters': 7.27.7(@babel/core@7.29.0) + '@babel/traverse': 7.29.0 transitivePeerDependencies: - supports-color - '@babel/plugin-transform-optional-catch-binding@7.28.6(@babel/core@7.28.6)': + '@babel/plugin-transform-optional-catch-binding@7.28.6(@babel/core@7.29.0)': dependencies: - '@babel/core': 7.28.6 + '@babel/core': 7.29.0 '@babel/helper-plugin-utils': 7.28.6 - '@babel/plugin-transform-optional-chaining@7.28.6(@babel/core@7.28.6)': + '@babel/plugin-transform-optional-chaining@7.28.6(@babel/core@7.29.0)': dependencies: - '@babel/core': 7.28.6 + '@babel/core': 7.29.0 '@babel/helper-plugin-utils': 7.28.6 '@babel/helper-skip-transparent-expression-wrappers': 7.27.1 transitivePeerDependencies: - supports-color - '@babel/plugin-transform-parameters@7.27.7(@babel/core@7.28.6)': + '@babel/plugin-transform-parameters@7.27.7(@babel/core@7.29.0)': dependencies: - '@babel/core': 7.28.6 + '@babel/core': 7.29.0 '@babel/helper-plugin-utils': 7.28.6 - '@babel/plugin-transform-private-methods@7.28.6(@babel/core@7.28.6)': + '@babel/plugin-transform-private-methods@7.28.6(@babel/core@7.29.0)': dependencies: - '@babel/core': 7.28.6 - '@babel/helper-create-class-features-plugin': 7.28.6(@babel/core@7.28.6) + '@babel/core': 7.29.0 + '@babel/helper-create-class-features-plugin': 7.28.6(@babel/core@7.29.0) '@babel/helper-plugin-utils': 7.28.6 transitivePeerDependencies: - supports-color - '@babel/plugin-transform-private-property-in-object@7.28.6(@babel/core@7.28.6)': + '@babel/plugin-transform-private-property-in-object@7.28.6(@babel/core@7.29.0)': dependencies: - '@babel/core': 7.28.6 + '@babel/core': 7.29.0 '@babel/helper-annotate-as-pure': 7.27.3 - '@babel/helper-create-class-features-plugin': 7.28.6(@babel/core@7.28.6) + '@babel/helper-create-class-features-plugin': 7.28.6(@babel/core@7.29.0) '@babel/helper-plugin-utils': 7.28.6 transitivePeerDependencies: - supports-color - '@babel/plugin-transform-react-display-name@7.28.0(@babel/core@7.28.6)': + '@babel/plugin-transform-react-display-name@7.28.0(@babel/core@7.29.0)': dependencies: - '@babel/core': 7.28.6 + '@babel/core': 7.29.0 '@babel/helper-plugin-utils': 7.28.6 - '@babel/plugin-transform-react-jsx-self@7.27.1(@babel/core@7.28.6)': + '@babel/plugin-transform-react-jsx-self@7.27.1(@babel/core@7.29.0)': dependencies: - '@babel/core': 7.28.6 + '@babel/core': 7.29.0 '@babel/helper-plugin-utils': 7.28.6 - '@babel/plugin-transform-react-jsx-source@7.27.1(@babel/core@7.28.6)': + '@babel/plugin-transform-react-jsx-source@7.27.1(@babel/core@7.29.0)': dependencies: - '@babel/core': 7.28.6 + '@babel/core': 7.29.0 '@babel/helper-plugin-utils': 7.28.6 - '@babel/plugin-transform-react-jsx@7.28.6(@babel/core@7.28.6)': + '@babel/plugin-transform-react-jsx@7.28.6(@babel/core@7.29.0)': dependencies: - '@babel/core': 7.28.6 + '@babel/core': 7.29.0 '@babel/helper-annotate-as-pure': 7.27.3 '@babel/helper-module-imports': 7.28.6 '@babel/helper-plugin-utils': 7.28.6 - '@babel/plugin-syntax-jsx': 7.28.6(@babel/core@7.28.6) - '@babel/types': 7.28.6 + '@babel/plugin-syntax-jsx': 7.28.6(@babel/core@7.29.0) + '@babel/types': 7.29.0 transitivePeerDependencies: - supports-color - '@babel/plugin-transform-regenerator@7.28.6(@babel/core@7.28.6)': + '@babel/plugin-transform-regenerator@7.29.0(@babel/core@7.29.0)': dependencies: - '@babel/core': 7.28.6 + '@babel/core': 7.29.0 '@babel/helper-plugin-utils': 7.28.6 - '@babel/plugin-transform-runtime@7.28.5(@babel/core@7.28.6)': + '@babel/plugin-transform-runtime@7.29.0(@babel/core@7.29.0)': dependencies: - '@babel/core': 7.28.6 + '@babel/core': 7.29.0 '@babel/helper-module-imports': 7.28.6 '@babel/helper-plugin-utils': 7.28.6 - babel-plugin-polyfill-corejs2: 0.4.14(@babel/core@7.28.6) - babel-plugin-polyfill-corejs3: 0.13.0(@babel/core@7.28.6) - babel-plugin-polyfill-regenerator: 0.6.5(@babel/core@7.28.6) + babel-plugin-polyfill-corejs2: 0.4.15(@babel/core@7.29.0) + babel-plugin-polyfill-corejs3: 0.13.0(@babel/core@7.29.0) + babel-plugin-polyfill-regenerator: 0.6.6(@babel/core@7.29.0) semver: 6.3.1 transitivePeerDependencies: - supports-color - '@babel/plugin-transform-shorthand-properties@7.27.1(@babel/core@7.28.6)': + '@babel/plugin-transform-shorthand-properties@7.27.1(@babel/core@7.29.0)': dependencies: - '@babel/core': 7.28.6 + '@babel/core': 7.29.0 '@babel/helper-plugin-utils': 7.28.6 - '@babel/plugin-transform-spread@7.28.6(@babel/core@7.28.6)': + '@babel/plugin-transform-spread@7.28.6(@babel/core@7.29.0)': dependencies: - '@babel/core': 7.28.6 + '@babel/core': 7.29.0 '@babel/helper-plugin-utils': 7.28.6 '@babel/helper-skip-transparent-expression-wrappers': 7.27.1 transitivePeerDependencies: - supports-color - '@babel/plugin-transform-sticky-regex@7.27.1(@babel/core@7.28.6)': + '@babel/plugin-transform-sticky-regex@7.27.1(@babel/core@7.29.0)': dependencies: - '@babel/core': 7.28.6 + '@babel/core': 7.29.0 '@babel/helper-plugin-utils': 7.28.6 - '@babel/plugin-transform-typescript@7.28.6(@babel/core@7.28.6)': + '@babel/plugin-transform-typescript@7.28.6(@babel/core@7.29.0)': dependencies: - '@babel/core': 7.28.6 + '@babel/core': 7.29.0 '@babel/helper-annotate-as-pure': 7.27.3 - '@babel/helper-create-class-features-plugin': 7.28.6(@babel/core@7.28.6) + '@babel/helper-create-class-features-plugin': 7.28.6(@babel/core@7.29.0) '@babel/helper-plugin-utils': 7.28.6 '@babel/helper-skip-transparent-expression-wrappers': 7.27.1 - '@babel/plugin-syntax-typescript': 7.28.6(@babel/core@7.28.6) + '@babel/plugin-syntax-typescript': 7.28.6(@babel/core@7.29.0) transitivePeerDependencies: - supports-color - '@babel/plugin-transform-unicode-regex@7.27.1(@babel/core@7.28.6)': + '@babel/plugin-transform-unicode-regex@7.27.1(@babel/core@7.29.0)': dependencies: - '@babel/core': 7.28.6 - '@babel/helper-create-regexp-features-plugin': 7.28.5(@babel/core@7.28.6) + '@babel/core': 7.29.0 + '@babel/helper-create-regexp-features-plugin': 7.28.5(@babel/core@7.29.0) '@babel/helper-plugin-utils': 7.28.6 - '@babel/preset-flow@7.27.1(@babel/core@7.28.6)': + '@babel/preset-flow@7.27.1(@babel/core@7.29.0)': dependencies: - '@babel/core': 7.28.6 + '@babel/core': 7.29.0 '@babel/helper-plugin-utils': 7.28.6 '@babel/helper-validator-option': 7.27.1 - '@babel/plugin-transform-flow-strip-types': 7.27.1(@babel/core@7.28.6) + '@babel/plugin-transform-flow-strip-types': 7.27.1(@babel/core@7.29.0) - '@babel/preset-typescript@7.28.5(@babel/core@7.28.6)': + '@babel/preset-typescript@7.28.5(@babel/core@7.29.0)': dependencies: - '@babel/core': 7.28.6 + '@babel/core': 7.29.0 '@babel/helper-plugin-utils': 7.28.6 '@babel/helper-validator-option': 7.27.1 - '@babel/plugin-syntax-jsx': 7.28.6(@babel/core@7.28.6) - '@babel/plugin-transform-modules-commonjs': 7.28.6(@babel/core@7.28.6) - '@babel/plugin-transform-typescript': 7.28.6(@babel/core@7.28.6) + '@babel/plugin-syntax-jsx': 7.28.6(@babel/core@7.29.0) + '@babel/plugin-transform-modules-commonjs': 7.28.6(@babel/core@7.29.0) + '@babel/plugin-transform-typescript': 7.28.6(@babel/core@7.29.0) transitivePeerDependencies: - supports-color - '@babel/register@7.28.6(@babel/core@7.28.6)': + '@babel/register@7.28.6(@babel/core@7.29.0)': dependencies: - '@babel/core': 7.28.6 + '@babel/core': 7.29.0 clone-deep: 4.0.1 find-cache-dir: 2.1.0 make-dir: 2.1.0 @@ -3635,60 +3636,60 @@ snapshots: '@babel/template@7.28.6': dependencies: - '@babel/code-frame': 7.28.6 - '@babel/parser': 7.28.6 - '@babel/types': 7.28.6 + '@babel/code-frame': 7.29.0 + '@babel/parser': 7.29.0 + '@babel/types': 7.29.0 - '@babel/traverse@7.28.6': + '@babel/traverse@7.29.0': dependencies: - '@babel/code-frame': 7.28.6 - '@babel/generator': 7.28.6 + '@babel/code-frame': 7.29.0 + '@babel/generator': 7.29.1 '@babel/helper-globals': 7.28.0 - '@babel/parser': 7.28.6 + '@babel/parser': 7.29.0 '@babel/template': 7.28.6 - '@babel/types': 7.28.6 + '@babel/types': 7.29.0 debug: 4.4.3 transitivePeerDependencies: - supports-color - '@babel/types@7.28.6': + '@babel/types@7.29.0': dependencies: '@babel/helper-string-parser': 7.27.1 '@babel/helper-validator-identifier': 7.28.5 - '@biomejs/biome@2.3.11': + '@biomejs/biome@2.3.14': optionalDependencies: - '@biomejs/cli-darwin-arm64': 2.3.11 - '@biomejs/cli-darwin-x64': 2.3.11 - '@biomejs/cli-linux-arm64': 2.3.11 - '@biomejs/cli-linux-arm64-musl': 2.3.11 - '@biomejs/cli-linux-x64': 2.3.11 - '@biomejs/cli-linux-x64-musl': 2.3.11 - '@biomejs/cli-win32-arm64': 2.3.11 - '@biomejs/cli-win32-x64': 2.3.11 - - '@biomejs/cli-darwin-arm64@2.3.11': + '@biomejs/cli-darwin-arm64': 2.3.14 + '@biomejs/cli-darwin-x64': 2.3.14 + '@biomejs/cli-linux-arm64': 2.3.14 + '@biomejs/cli-linux-arm64-musl': 2.3.14 + '@biomejs/cli-linux-x64': 2.3.14 + '@biomejs/cli-linux-x64-musl': 2.3.14 + '@biomejs/cli-win32-arm64': 2.3.14 + '@biomejs/cli-win32-x64': 2.3.14 + + '@biomejs/cli-darwin-arm64@2.3.14': optional: true - '@biomejs/cli-darwin-x64@2.3.11': + '@biomejs/cli-darwin-x64@2.3.14': optional: true - '@biomejs/cli-linux-arm64-musl@2.3.11': + '@biomejs/cli-linux-arm64-musl@2.3.14': optional: true - '@biomejs/cli-linux-arm64@2.3.11': + '@biomejs/cli-linux-arm64@2.3.14': optional: true - '@biomejs/cli-linux-x64-musl@2.3.11': + '@biomejs/cli-linux-x64-musl@2.3.14': optional: true - '@biomejs/cli-linux-x64@2.3.11': + '@biomejs/cli-linux-x64@2.3.14': optional: true - '@biomejs/cli-win32-arm64@2.3.11': + '@biomejs/cli-win32-arm64@2.3.14': optional: true - '@biomejs/cli-win32-x64@2.3.11': + '@biomejs/cli-win32-x64@2.3.14': optional: true '@changesets/apply-release-plan@7.0.14': @@ -3728,7 +3729,7 @@ snapshots: transitivePeerDependencies: - encoding - '@changesets/cli@2.29.8(@types/node@25.0.9)': + '@changesets/cli@2.29.8(@types/node@25.2.0)': dependencies: '@changesets/apply-release-plan': 7.0.14 '@changesets/assemble-release-plan': 6.0.9 @@ -3744,7 +3745,7 @@ snapshots: '@changesets/should-skip-package': 0.1.2 '@changesets/types': 6.1.0 '@changesets/write': 0.4.0 - '@inquirer/external-editor': 1.0.3(@types/node@25.0.9) + '@inquirer/external-editor': 1.0.3(@types/node@25.2.0) '@manypkg/get-packages': 1.1.3 ansi-colors: 4.1.3 ci-info: 3.9.0 @@ -4118,7 +4119,7 @@ snapshots: chalk: 4.1.2 debug: 4.4.3 getenv: 2.0.0 - glob: 13.0.0 + glob: 13.0.1 resolve-from: 5.0.0 semver: 7.7.3 slash: 3.0.0 @@ -4138,7 +4139,7 @@ snapshots: '@expo/json-file': 9.1.5 deepmerge: 4.3.1 getenv: 2.0.0 - glob: 13.0.0 + glob: 13.0.1 require-from-string: 2.0.2 resolve-from: 5.0.0 resolve-workspace-root: 2.0.1 @@ -4171,24 +4172,24 @@ snapshots: '@expo/sdk-runtime-versions@1.0.0': {} - '@gerrit0/mini-shiki@3.21.0': + '@gerrit0/mini-shiki@3.22.0': dependencies: - '@shikijs/engine-oniguruma': 3.21.0 - '@shikijs/langs': 3.21.0 - '@shikijs/themes': 3.21.0 - '@shikijs/types': 3.21.0 + '@shikijs/engine-oniguruma': 3.22.0 + '@shikijs/langs': 3.22.0 + '@shikijs/themes': 3.22.0 + '@shikijs/types': 3.22.0 '@shikijs/vscode-textmate': 10.0.2 - '@inquirer/external-editor@1.0.3(@types/node@25.0.9)': + '@inquirer/external-editor@1.0.3(@types/node@25.2.0)': dependencies: chardet: 2.1.1 iconv-lite: 0.7.2 optionalDependencies: - '@types/node': 25.0.9 + '@types/node': 25.2.0 '@isaacs/balanced-match@4.0.1': {} - '@isaacs/brace-expansion@5.0.0': + '@isaacs/brace-expansion@5.0.1': dependencies: '@isaacs/balanced-match': 4.0.1 @@ -4212,25 +4213,25 @@ snapshots: dependencies: '@jest/fake-timers': 29.7.0 '@jest/types': 29.6.3 - '@types/node': 25.0.9 + '@types/node': 25.2.0 jest-mock: 29.7.0 '@jest/fake-timers@29.7.0': dependencies: '@jest/types': 29.6.3 '@sinonjs/fake-timers': 10.3.0 - '@types/node': 25.0.9 + '@types/node': 25.2.0 jest-message-util: 29.7.0 jest-mock: 29.7.0 jest-util: 29.7.0 '@jest/schemas@29.6.3': dependencies: - '@sinclair/typebox': 0.27.8 + '@sinclair/typebox': 0.27.10 '@jest/transform@29.7.0': dependencies: - '@babel/core': 7.28.6 + '@babel/core': 7.29.0 '@jest/types': 29.6.3 '@jridgewell/trace-mapping': 0.3.31 babel-plugin-istanbul: 6.1.1 @@ -4253,7 +4254,7 @@ snapshots: '@jest/schemas': 29.6.3 '@types/istanbul-lib-coverage': 2.0.6 '@types/istanbul-reports': 3.0.4 - '@types/node': 25.0.9 + '@types/node': 25.2.0 '@types/yargs': 17.0.35 chalk: 4.1.2 @@ -4316,7 +4317,7 @@ snapshots: '@nodelib/fs.scandir': 2.1.5 fastq: 1.20.1 - '@openfort/openfort-js@file:../openfort-core-js/sdk': + '@openfort/openfort-js@https://pkg.pr.new/@openfort/openfort-js@cc06c35': dependencies: '@ethersproject/abi': 5.8.0 '@ethersproject/bytes': 5.8.0 @@ -4327,8 +4328,8 @@ snapshots: '@openfort/shield-js': 0.1.34 '@sentry/browser': 9.47.1 '@sentry/core': 9.47.1 - axios: 1.13.2 - axios-retry: 4.5.0(axios@1.13.2) + axios: 1.13.4 + axios-retry: 4.5.0(axios@1.13.4) eventemitter3: 5.0.1 human-id: 4.1.3 transitivePeerDependencies: @@ -4343,73 +4344,73 @@ snapshots: transitivePeerDependencies: - debug - '@oxc-resolver/binding-android-arm-eabi@11.16.3': + '@oxc-resolver/binding-android-arm-eabi@11.17.0': optional: true - '@oxc-resolver/binding-android-arm64@11.16.3': + '@oxc-resolver/binding-android-arm64@11.17.0': optional: true - '@oxc-resolver/binding-darwin-arm64@11.16.3': + '@oxc-resolver/binding-darwin-arm64@11.17.0': optional: true - '@oxc-resolver/binding-darwin-x64@11.16.3': + '@oxc-resolver/binding-darwin-x64@11.17.0': optional: true - '@oxc-resolver/binding-freebsd-x64@11.16.3': + '@oxc-resolver/binding-freebsd-x64@11.17.0': optional: true - '@oxc-resolver/binding-linux-arm-gnueabihf@11.16.3': + '@oxc-resolver/binding-linux-arm-gnueabihf@11.17.0': optional: true - '@oxc-resolver/binding-linux-arm-musleabihf@11.16.3': + '@oxc-resolver/binding-linux-arm-musleabihf@11.17.0': optional: true - '@oxc-resolver/binding-linux-arm64-gnu@11.16.3': + '@oxc-resolver/binding-linux-arm64-gnu@11.17.0': optional: true - '@oxc-resolver/binding-linux-arm64-musl@11.16.3': + '@oxc-resolver/binding-linux-arm64-musl@11.17.0': optional: true - '@oxc-resolver/binding-linux-ppc64-gnu@11.16.3': + '@oxc-resolver/binding-linux-ppc64-gnu@11.17.0': optional: true - '@oxc-resolver/binding-linux-riscv64-gnu@11.16.3': + '@oxc-resolver/binding-linux-riscv64-gnu@11.17.0': optional: true - '@oxc-resolver/binding-linux-riscv64-musl@11.16.3': + '@oxc-resolver/binding-linux-riscv64-musl@11.17.0': optional: true - '@oxc-resolver/binding-linux-s390x-gnu@11.16.3': + '@oxc-resolver/binding-linux-s390x-gnu@11.17.0': optional: true - '@oxc-resolver/binding-linux-x64-gnu@11.16.3': + '@oxc-resolver/binding-linux-x64-gnu@11.17.0': optional: true - '@oxc-resolver/binding-linux-x64-musl@11.16.3': + '@oxc-resolver/binding-linux-x64-musl@11.17.0': optional: true - '@oxc-resolver/binding-openharmony-arm64@11.16.3': + '@oxc-resolver/binding-openharmony-arm64@11.17.0': optional: true - '@oxc-resolver/binding-wasm32-wasi@11.16.3': + '@oxc-resolver/binding-wasm32-wasi@11.17.0': dependencies: '@napi-rs/wasm-runtime': 1.1.1 optional: true - '@oxc-resolver/binding-win32-arm64-msvc@11.16.3': + '@oxc-resolver/binding-win32-arm64-msvc@11.17.0': optional: true - '@oxc-resolver/binding-win32-ia32-msvc@11.16.3': + '@oxc-resolver/binding-win32-ia32-msvc@11.17.0': optional: true - '@oxc-resolver/binding-win32-x64-msvc@11.16.3': + '@oxc-resolver/binding-win32-x64-msvc@11.17.0': optional: true '@react-native/assets-registry@0.77.1': {} '@react-native/babel-plugin-codegen@0.77.1': dependencies: - '@babel/traverse': 7.28.6 + '@babel/traverse': 7.29.0 '@react-native/codegen': 0.77.1 transitivePeerDependencies: - '@babel/preset-env' @@ -4417,50 +4418,50 @@ snapshots: '@react-native/babel-preset@0.77.1': dependencies: - '@babel/core': 7.28.6 - '@babel/plugin-proposal-export-default-from': 7.27.1(@babel/core@7.28.6) - '@babel/plugin-syntax-dynamic-import': 7.8.3(@babel/core@7.28.6) - '@babel/plugin-syntax-export-default-from': 7.28.6(@babel/core@7.28.6) - '@babel/plugin-syntax-nullish-coalescing-operator': 7.8.3(@babel/core@7.28.6) - '@babel/plugin-syntax-optional-chaining': 7.8.3(@babel/core@7.28.6) - '@babel/plugin-transform-arrow-functions': 7.27.1(@babel/core@7.28.6) - '@babel/plugin-transform-async-generator-functions': 7.28.6(@babel/core@7.28.6) - '@babel/plugin-transform-async-to-generator': 7.28.6(@babel/core@7.28.6) - '@babel/plugin-transform-block-scoping': 7.28.6(@babel/core@7.28.6) - '@babel/plugin-transform-class-properties': 7.28.6(@babel/core@7.28.6) - '@babel/plugin-transform-classes': 7.28.6(@babel/core@7.28.6) - '@babel/plugin-transform-computed-properties': 7.28.6(@babel/core@7.28.6) - '@babel/plugin-transform-destructuring': 7.28.5(@babel/core@7.28.6) - '@babel/plugin-transform-flow-strip-types': 7.27.1(@babel/core@7.28.6) - '@babel/plugin-transform-for-of': 7.27.1(@babel/core@7.28.6) - '@babel/plugin-transform-function-name': 7.27.1(@babel/core@7.28.6) - '@babel/plugin-transform-literals': 7.27.1(@babel/core@7.28.6) - '@babel/plugin-transform-logical-assignment-operators': 7.28.6(@babel/core@7.28.6) - '@babel/plugin-transform-modules-commonjs': 7.28.6(@babel/core@7.28.6) - '@babel/plugin-transform-named-capturing-groups-regex': 7.27.1(@babel/core@7.28.6) - '@babel/plugin-transform-nullish-coalescing-operator': 7.28.6(@babel/core@7.28.6) - '@babel/plugin-transform-numeric-separator': 7.28.6(@babel/core@7.28.6) - '@babel/plugin-transform-object-rest-spread': 7.28.6(@babel/core@7.28.6) - '@babel/plugin-transform-optional-catch-binding': 7.28.6(@babel/core@7.28.6) - '@babel/plugin-transform-optional-chaining': 7.28.6(@babel/core@7.28.6) - '@babel/plugin-transform-parameters': 7.27.7(@babel/core@7.28.6) - '@babel/plugin-transform-private-methods': 7.28.6(@babel/core@7.28.6) - '@babel/plugin-transform-private-property-in-object': 7.28.6(@babel/core@7.28.6) - '@babel/plugin-transform-react-display-name': 7.28.0(@babel/core@7.28.6) - '@babel/plugin-transform-react-jsx': 7.28.6(@babel/core@7.28.6) - '@babel/plugin-transform-react-jsx-self': 7.27.1(@babel/core@7.28.6) - '@babel/plugin-transform-react-jsx-source': 7.27.1(@babel/core@7.28.6) - '@babel/plugin-transform-regenerator': 7.28.6(@babel/core@7.28.6) - '@babel/plugin-transform-runtime': 7.28.5(@babel/core@7.28.6) - '@babel/plugin-transform-shorthand-properties': 7.27.1(@babel/core@7.28.6) - '@babel/plugin-transform-spread': 7.28.6(@babel/core@7.28.6) - '@babel/plugin-transform-sticky-regex': 7.27.1(@babel/core@7.28.6) - '@babel/plugin-transform-typescript': 7.28.6(@babel/core@7.28.6) - '@babel/plugin-transform-unicode-regex': 7.27.1(@babel/core@7.28.6) + '@babel/core': 7.29.0 + '@babel/plugin-proposal-export-default-from': 7.27.1(@babel/core@7.29.0) + '@babel/plugin-syntax-dynamic-import': 7.8.3(@babel/core@7.29.0) + '@babel/plugin-syntax-export-default-from': 7.28.6(@babel/core@7.29.0) + '@babel/plugin-syntax-nullish-coalescing-operator': 7.8.3(@babel/core@7.29.0) + '@babel/plugin-syntax-optional-chaining': 7.8.3(@babel/core@7.29.0) + '@babel/plugin-transform-arrow-functions': 7.27.1(@babel/core@7.29.0) + '@babel/plugin-transform-async-generator-functions': 7.29.0(@babel/core@7.29.0) + '@babel/plugin-transform-async-to-generator': 7.28.6(@babel/core@7.29.0) + '@babel/plugin-transform-block-scoping': 7.28.6(@babel/core@7.29.0) + '@babel/plugin-transform-class-properties': 7.28.6(@babel/core@7.29.0) + '@babel/plugin-transform-classes': 7.28.6(@babel/core@7.29.0) + '@babel/plugin-transform-computed-properties': 7.28.6(@babel/core@7.29.0) + '@babel/plugin-transform-destructuring': 7.28.5(@babel/core@7.29.0) + '@babel/plugin-transform-flow-strip-types': 7.27.1(@babel/core@7.29.0) + '@babel/plugin-transform-for-of': 7.27.1(@babel/core@7.29.0) + '@babel/plugin-transform-function-name': 7.27.1(@babel/core@7.29.0) + '@babel/plugin-transform-literals': 7.27.1(@babel/core@7.29.0) + '@babel/plugin-transform-logical-assignment-operators': 7.28.6(@babel/core@7.29.0) + '@babel/plugin-transform-modules-commonjs': 7.28.6(@babel/core@7.29.0) + '@babel/plugin-transform-named-capturing-groups-regex': 7.29.0(@babel/core@7.29.0) + '@babel/plugin-transform-nullish-coalescing-operator': 7.28.6(@babel/core@7.29.0) + '@babel/plugin-transform-numeric-separator': 7.28.6(@babel/core@7.29.0) + '@babel/plugin-transform-object-rest-spread': 7.28.6(@babel/core@7.29.0) + '@babel/plugin-transform-optional-catch-binding': 7.28.6(@babel/core@7.29.0) + '@babel/plugin-transform-optional-chaining': 7.28.6(@babel/core@7.29.0) + '@babel/plugin-transform-parameters': 7.27.7(@babel/core@7.29.0) + '@babel/plugin-transform-private-methods': 7.28.6(@babel/core@7.29.0) + '@babel/plugin-transform-private-property-in-object': 7.28.6(@babel/core@7.29.0) + '@babel/plugin-transform-react-display-name': 7.28.0(@babel/core@7.29.0) + '@babel/plugin-transform-react-jsx': 7.28.6(@babel/core@7.29.0) + '@babel/plugin-transform-react-jsx-self': 7.27.1(@babel/core@7.29.0) + '@babel/plugin-transform-react-jsx-source': 7.27.1(@babel/core@7.29.0) + '@babel/plugin-transform-regenerator': 7.29.0(@babel/core@7.29.0) + '@babel/plugin-transform-runtime': 7.29.0(@babel/core@7.29.0) + '@babel/plugin-transform-shorthand-properties': 7.27.1(@babel/core@7.29.0) + '@babel/plugin-transform-spread': 7.28.6(@babel/core@7.29.0) + '@babel/plugin-transform-sticky-regex': 7.27.1(@babel/core@7.29.0) + '@babel/plugin-transform-typescript': 7.28.6(@babel/core@7.29.0) + '@babel/plugin-transform-unicode-regex': 7.27.1(@babel/core@7.29.0) '@babel/template': 7.28.6 '@react-native/babel-plugin-codegen': 0.77.1 babel-plugin-syntax-hermes-parser: 0.25.1 - babel-plugin-transform-flow-enums: 0.0.2(@babel/core@7.28.6) + babel-plugin-transform-flow-enums: 0.0.2(@babel/core@7.29.0) react-refresh: 0.14.2 transitivePeerDependencies: - '@babel/preset-env' @@ -4468,7 +4469,7 @@ snapshots: '@react-native/codegen@0.77.1': dependencies: - '@babel/parser': 7.28.6 + '@babel/parser': 7.29.0 glob: 7.2.3 hermes-parser: 0.25.1 invariant: 2.2.4 @@ -4523,7 +4524,7 @@ snapshots: '@react-native/metro-babel-transformer@0.77.1': dependencies: - '@babel/core': 7.28.6 + '@babel/core': 7.29.0 '@react-native/babel-preset': 0.77.1 hermes-parser: 0.25.1 nullthrows: 1.1.1 @@ -4533,12 +4534,12 @@ snapshots: '@react-native/normalize-colors@0.77.1': {} - '@react-native/virtualized-lists@0.77.1(@types/react@18.3.27)(react-native@0.77.1(@babel/core@7.28.6)(@types/react@18.3.27)(react@18.3.1))(react@18.3.1)': + '@react-native/virtualized-lists@0.77.1(@types/react@18.3.27)(react-native@0.77.1(@babel/core@7.29.0)(@types/react@18.3.27)(react@18.3.1))(react@18.3.1)': dependencies: invariant: 2.2.4 nullthrows: 1.1.1 react: 18.3.1 - react-native: 0.77.1(@babel/core@7.28.6)(@types/react@18.3.27)(react@18.3.1) + react-native: 0.77.1(@babel/core@7.29.0)(@types/react@18.3.27)(react@18.3.1) optionalDependencies: '@types/react': 18.3.27 @@ -4570,27 +4571,27 @@ snapshots: '@sentry/core@9.47.1': {} - '@shikijs/engine-oniguruma@3.21.0': + '@shikijs/engine-oniguruma@3.22.0': dependencies: - '@shikijs/types': 3.21.0 + '@shikijs/types': 3.22.0 '@shikijs/vscode-textmate': 10.0.2 - '@shikijs/langs@3.21.0': + '@shikijs/langs@3.22.0': dependencies: - '@shikijs/types': 3.21.0 + '@shikijs/types': 3.22.0 - '@shikijs/themes@3.21.0': + '@shikijs/themes@3.22.0': dependencies: - '@shikijs/types': 3.21.0 + '@shikijs/types': 3.22.0 - '@shikijs/types@3.21.0': + '@shikijs/types@3.22.0': dependencies: '@shikijs/vscode-textmate': 10.0.2 '@types/hast': 3.0.4 '@shikijs/vscode-textmate@10.0.2': {} - '@sinclair/typebox@0.27.8': {} + '@sinclair/typebox@0.27.10': {} '@sinonjs/commons@3.0.1': dependencies: @@ -4623,28 +4624,28 @@ snapshots: '@types/babel__core@7.20.5': dependencies: - '@babel/parser': 7.28.6 - '@babel/types': 7.28.6 + '@babel/parser': 7.29.0 + '@babel/types': 7.29.0 '@types/babel__generator': 7.27.0 '@types/babel__template': 7.4.4 '@types/babel__traverse': 7.28.0 '@types/babel__generator@7.27.0': dependencies: - '@babel/types': 7.28.6 + '@babel/types': 7.29.0 '@types/babel__template@7.4.4': dependencies: - '@babel/parser': 7.28.6 - '@babel/types': 7.28.6 + '@babel/parser': 7.29.0 + '@babel/types': 7.29.0 '@types/babel__traverse@7.28.0': dependencies: - '@babel/types': 7.28.6 + '@babel/types': 7.29.0 '@types/graceful-fs@4.1.9': dependencies: - '@types/node': 25.0.9 + '@types/node': 25.2.0 '@types/hast@3.0.4': dependencies: @@ -4662,11 +4663,11 @@ snapshots: '@types/node-forge@1.3.14': dependencies: - '@types/node': 25.0.9 + '@types/node': 25.2.0 '@types/node@12.20.55': {} - '@types/node@25.0.9': + '@types/node@25.2.0': dependencies: undici-types: 7.16.0 @@ -4746,9 +4747,9 @@ snapshots: axios: 1.12.2 is-retry-allowed: 2.2.0 - axios-retry@4.5.0(axios@1.13.2): + axios-retry@4.5.0(axios@1.13.4): dependencies: - axios: 1.13.2 + axios: 1.13.4 is-retry-allowed: 2.2.0 axios@1.12.2: @@ -4759,7 +4760,7 @@ snapshots: transitivePeerDependencies: - debug - axios@1.13.2: + axios@1.13.4: dependencies: follow-redirects: 1.15.11 form-data: 4.0.5 @@ -4767,13 +4768,13 @@ snapshots: transitivePeerDependencies: - debug - babel-jest@29.7.0(@babel/core@7.28.6): + babel-jest@29.7.0(@babel/core@7.29.0): dependencies: - '@babel/core': 7.28.6 + '@babel/core': 7.29.0 '@jest/transform': 29.7.0 '@types/babel__core': 7.20.5 babel-plugin-istanbul: 6.1.1 - babel-preset-jest: 29.6.3(@babel/core@7.28.6) + babel-preset-jest: 29.6.3(@babel/core@7.29.0) chalk: 4.1.2 graceful-fs: 4.2.11 slash: 3.0.0 @@ -4793,31 +4794,31 @@ snapshots: babel-plugin-jest-hoist@29.6.3: dependencies: '@babel/template': 7.28.6 - '@babel/types': 7.28.6 + '@babel/types': 7.29.0 '@types/babel__core': 7.20.5 '@types/babel__traverse': 7.28.0 - babel-plugin-polyfill-corejs2@0.4.14(@babel/core@7.28.6): + babel-plugin-polyfill-corejs2@0.4.15(@babel/core@7.29.0): dependencies: - '@babel/compat-data': 7.28.6 - '@babel/core': 7.28.6 - '@babel/helper-define-polyfill-provider': 0.6.5(@babel/core@7.28.6) + '@babel/compat-data': 7.29.0 + '@babel/core': 7.29.0 + '@babel/helper-define-polyfill-provider': 0.6.6(@babel/core@7.29.0) semver: 6.3.1 transitivePeerDependencies: - supports-color - babel-plugin-polyfill-corejs3@0.13.0(@babel/core@7.28.6): + babel-plugin-polyfill-corejs3@0.13.0(@babel/core@7.29.0): dependencies: - '@babel/core': 7.28.6 - '@babel/helper-define-polyfill-provider': 0.6.5(@babel/core@7.28.6) - core-js-compat: 3.47.0 + '@babel/core': 7.29.0 + '@babel/helper-define-polyfill-provider': 0.6.6(@babel/core@7.29.0) + core-js-compat: 3.48.0 transitivePeerDependencies: - supports-color - babel-plugin-polyfill-regenerator@0.6.5(@babel/core@7.28.6): + babel-plugin-polyfill-regenerator@0.6.6(@babel/core@7.29.0): dependencies: - '@babel/core': 7.28.6 - '@babel/helper-define-polyfill-provider': 0.6.5(@babel/core@7.28.6) + '@babel/core': 7.29.0 + '@babel/helper-define-polyfill-provider': 0.6.6(@babel/core@7.29.0) transitivePeerDependencies: - supports-color @@ -4825,42 +4826,42 @@ snapshots: dependencies: hermes-parser: 0.25.1 - babel-plugin-transform-flow-enums@0.0.2(@babel/core@7.28.6): + babel-plugin-transform-flow-enums@0.0.2(@babel/core@7.29.0): dependencies: - '@babel/plugin-syntax-flow': 7.28.6(@babel/core@7.28.6) + '@babel/plugin-syntax-flow': 7.28.6(@babel/core@7.29.0) transitivePeerDependencies: - '@babel/core' - babel-preset-current-node-syntax@1.2.0(@babel/core@7.28.6): - dependencies: - '@babel/core': 7.28.6 - '@babel/plugin-syntax-async-generators': 7.8.4(@babel/core@7.28.6) - '@babel/plugin-syntax-bigint': 7.8.3(@babel/core@7.28.6) - '@babel/plugin-syntax-class-properties': 7.12.13(@babel/core@7.28.6) - '@babel/plugin-syntax-class-static-block': 7.14.5(@babel/core@7.28.6) - '@babel/plugin-syntax-import-attributes': 7.28.6(@babel/core@7.28.6) - '@babel/plugin-syntax-import-meta': 7.10.4(@babel/core@7.28.6) - '@babel/plugin-syntax-json-strings': 7.8.3(@babel/core@7.28.6) - '@babel/plugin-syntax-logical-assignment-operators': 7.10.4(@babel/core@7.28.6) - '@babel/plugin-syntax-nullish-coalescing-operator': 7.8.3(@babel/core@7.28.6) - '@babel/plugin-syntax-numeric-separator': 7.10.4(@babel/core@7.28.6) - '@babel/plugin-syntax-object-rest-spread': 7.8.3(@babel/core@7.28.6) - '@babel/plugin-syntax-optional-catch-binding': 7.8.3(@babel/core@7.28.6) - '@babel/plugin-syntax-optional-chaining': 7.8.3(@babel/core@7.28.6) - '@babel/plugin-syntax-private-property-in-object': 7.14.5(@babel/core@7.28.6) - '@babel/plugin-syntax-top-level-await': 7.14.5(@babel/core@7.28.6) - - babel-preset-jest@29.6.3(@babel/core@7.28.6): - dependencies: - '@babel/core': 7.28.6 + babel-preset-current-node-syntax@1.2.0(@babel/core@7.29.0): + dependencies: + '@babel/core': 7.29.0 + '@babel/plugin-syntax-async-generators': 7.8.4(@babel/core@7.29.0) + '@babel/plugin-syntax-bigint': 7.8.3(@babel/core@7.29.0) + '@babel/plugin-syntax-class-properties': 7.12.13(@babel/core@7.29.0) + '@babel/plugin-syntax-class-static-block': 7.14.5(@babel/core@7.29.0) + '@babel/plugin-syntax-import-attributes': 7.28.6(@babel/core@7.29.0) + '@babel/plugin-syntax-import-meta': 7.10.4(@babel/core@7.29.0) + '@babel/plugin-syntax-json-strings': 7.8.3(@babel/core@7.29.0) + '@babel/plugin-syntax-logical-assignment-operators': 7.10.4(@babel/core@7.29.0) + '@babel/plugin-syntax-nullish-coalescing-operator': 7.8.3(@babel/core@7.29.0) + '@babel/plugin-syntax-numeric-separator': 7.10.4(@babel/core@7.29.0) + '@babel/plugin-syntax-object-rest-spread': 7.8.3(@babel/core@7.29.0) + '@babel/plugin-syntax-optional-catch-binding': 7.8.3(@babel/core@7.29.0) + '@babel/plugin-syntax-optional-chaining': 7.8.3(@babel/core@7.29.0) + '@babel/plugin-syntax-private-property-in-object': 7.14.5(@babel/core@7.29.0) + '@babel/plugin-syntax-top-level-await': 7.14.5(@babel/core@7.29.0) + + babel-preset-jest@29.6.3(@babel/core@7.29.0): + dependencies: + '@babel/core': 7.29.0 babel-plugin-jest-hoist: 29.6.3 - babel-preset-current-node-syntax: 1.2.0(@babel/core@7.28.6) + babel-preset-current-node-syntax: 1.2.0(@babel/core@7.29.0) balanced-match@1.0.2: {} base64-js@1.5.1: {} - baseline-browser-mapping@2.9.16: {} + baseline-browser-mapping@2.9.19: {} bech32@1.1.4: {} @@ -4899,9 +4900,9 @@ snapshots: browserslist@4.28.1: dependencies: - baseline-browser-mapping: 2.9.16 - caniuse-lite: 1.0.30001765 - electron-to-chromium: 1.5.267 + baseline-browser-mapping: 2.9.19 + caniuse-lite: 1.0.30001767 + electron-to-chromium: 1.5.286 node-releases: 2.0.27 update-browserslist-db: 1.2.3(browserslist@4.28.1) @@ -4937,7 +4938,7 @@ snapshots: camelcase@6.3.0: {} - caniuse-lite@1.0.30001765: {} + caniuse-lite@1.0.30001767: {} chalk@2.4.2: dependencies: @@ -4958,7 +4959,7 @@ snapshots: chrome-launcher@0.15.2: dependencies: - '@types/node': 25.0.9 + '@types/node': 25.2.0 escape-string-regexp: 4.0.0 is-wsl: 2.2.0 lighthouse-logger: 1.4.2 @@ -4967,7 +4968,7 @@ snapshots: chromium-edge-launcher@0.2.0: dependencies: - '@types/node': 25.0.9 + '@types/node': 25.2.0 escape-string-regexp: 4.0.0 is-wsl: 2.2.0 lighthouse-logger: 1.4.2 @@ -5029,7 +5030,7 @@ snapshots: convert-source-map@2.0.0: {} - core-js-compat@3.47.0: + core-js-compat@3.48.0: dependencies: browserslist: 4.28.1 @@ -5088,7 +5089,7 @@ snapshots: ee-first@1.1.1: {} - electron-to-chromium@1.5.267: {} + electron-to-chromium@1.5.286: {} elliptic@6.6.1: dependencies: @@ -5183,17 +5184,17 @@ snapshots: eventemitter3@5.0.1: {} - expo-apple-authentication@7.2.4(react-native@0.77.1(@babel/core@7.28.6)(@types/react@18.3.27)(react@18.3.1)): + expo-apple-authentication@7.2.4(react-native@0.77.1(@babel/core@7.29.0)(@types/react@18.3.27)(react@18.3.1)): dependencies: - react-native: 0.77.1(@babel/core@7.28.6)(@types/react@18.3.27)(react@18.3.1) + react-native: 0.77.1(@babel/core@7.29.0)(@types/react@18.3.27)(react@18.3.1) expo-application@6.1.5: {} - expo-constants@17.1.8(react-native@0.77.1(@babel/core@7.28.6)(@types/react@18.3.27)(react@18.3.1)): + expo-constants@17.1.8(react-native@0.77.1(@babel/core@7.29.0)(@types/react@18.3.27)(react@18.3.1)): dependencies: '@expo/config': 11.0.13 '@expo/env': 1.0.7 - react-native: 0.77.1(@babel/core@7.28.6)(@types/react@18.3.27)(react@18.3.1) + react-native: 0.77.1(@babel/core@7.29.0)(@types/react@18.3.27)(react@18.3.1) transitivePeerDependencies: - supports-color @@ -5201,21 +5202,21 @@ snapshots: dependencies: base64-js: 1.5.1 - expo-linking@7.1.7(react-native@0.77.1(@babel/core@7.28.6)(@types/react@18.3.27)(react@18.3.1))(react@18.3.1): + expo-linking@7.1.7(react-native@0.77.1(@babel/core@7.29.0)(@types/react@18.3.27)(react@18.3.1))(react@18.3.1): dependencies: - expo-constants: 17.1.8(react-native@0.77.1(@babel/core@7.28.6)(@types/react@18.3.27)(react@18.3.1)) + expo-constants: 17.1.8(react-native@0.77.1(@babel/core@7.29.0)(@types/react@18.3.27)(react@18.3.1)) invariant: 2.2.4 react: 18.3.1 - react-native: 0.77.1(@babel/core@7.28.6)(@types/react@18.3.27)(react@18.3.1) + react-native: 0.77.1(@babel/core@7.29.0)(@types/react@18.3.27)(react@18.3.1) transitivePeerDependencies: - expo - supports-color expo-secure-store@14.2.4: {} - expo-web-browser@14.2.0(react-native@0.77.1(@babel/core@7.28.6)(@types/react@18.3.27)(react@18.3.1)): + expo-web-browser@14.2.0(react-native@0.77.1(@babel/core@7.29.0)(@types/react@18.3.27)(react@18.3.1)): dependencies: - react-native: 0.77.1(@babel/core@7.28.6)(@types/react@18.3.27)(react@18.3.1) + react-native: 0.77.1(@babel/core@7.29.0)(@types/react@18.3.27)(react@18.3.1) exponential-backoff@3.1.3: {} @@ -5280,7 +5281,7 @@ snapshots: flow-enums-runtime@0.0.6: {} - flow-parser@0.297.0: {} + flow-parser@0.299.0: {} follow-redirects@1.15.11: {} @@ -5347,9 +5348,9 @@ snapshots: dependencies: is-glob: 4.0.3 - glob@13.0.0: + glob@13.0.1: dependencies: - minimatch: 10.1.1 + minimatch: 10.1.2 minipass: 7.1.2 path-scurry: 2.0.1 @@ -5490,8 +5491,8 @@ snapshots: istanbul-lib-instrument@5.2.1: dependencies: - '@babel/core': 7.28.6 - '@babel/parser': 7.28.6 + '@babel/core': 7.29.0 + '@babel/parser': 7.29.0 '@istanbuljs/schema': 0.1.3 istanbul-lib-coverage: 3.2.2 semver: 6.3.1 @@ -5503,7 +5504,7 @@ snapshots: '@jest/environment': 29.7.0 '@jest/fake-timers': 29.7.0 '@jest/types': 29.6.3 - '@types/node': 25.0.9 + '@types/node': 25.2.0 jest-mock: 29.7.0 jest-util: 29.7.0 @@ -5513,7 +5514,7 @@ snapshots: dependencies: '@jest/types': 29.6.3 '@types/graceful-fs': 4.1.9 - '@types/node': 25.0.9 + '@types/node': 25.2.0 anymatch: 3.1.3 fb-watchman: 2.0.2 graceful-fs: 4.2.11 @@ -5527,7 +5528,7 @@ snapshots: jest-message-util@29.7.0: dependencies: - '@babel/code-frame': 7.28.6 + '@babel/code-frame': 7.29.0 '@jest/types': 29.6.3 '@types/stack-utils': 2.0.3 chalk: 4.1.2 @@ -5540,7 +5541,7 @@ snapshots: jest-mock@29.7.0: dependencies: '@jest/types': 29.6.3 - '@types/node': 25.0.9 + '@types/node': 25.2.0 jest-util: 29.7.0 jest-regex-util@29.6.3: {} @@ -5548,7 +5549,7 @@ snapshots: jest-util@29.7.0: dependencies: '@jest/types': 29.6.3 - '@types/node': 25.0.9 + '@types/node': 25.2.0 chalk: 4.1.2 ci-info: 3.9.0 graceful-fs: 4.2.11 @@ -5565,7 +5566,7 @@ snapshots: jest-worker@29.7.0: dependencies: - '@types/node': 25.0.9 + '@types/node': 25.2.0 jest-util: 29.7.0 merge-stream: 2.0.0 supports-color: 8.1.1 @@ -5591,17 +5592,17 @@ snapshots: jscodeshift@17.3.0: dependencies: - '@babel/core': 7.28.6 - '@babel/parser': 7.28.6 - '@babel/plugin-transform-class-properties': 7.28.6(@babel/core@7.28.6) - '@babel/plugin-transform-modules-commonjs': 7.28.6(@babel/core@7.28.6) - '@babel/plugin-transform-nullish-coalescing-operator': 7.28.6(@babel/core@7.28.6) - '@babel/plugin-transform-optional-chaining': 7.28.6(@babel/core@7.28.6) - '@babel/plugin-transform-private-methods': 7.28.6(@babel/core@7.28.6) - '@babel/preset-flow': 7.27.1(@babel/core@7.28.6) - '@babel/preset-typescript': 7.28.5(@babel/core@7.28.6) - '@babel/register': 7.28.6(@babel/core@7.28.6) - flow-parser: 0.297.0 + '@babel/core': 7.29.0 + '@babel/parser': 7.29.0 + '@babel/plugin-transform-class-properties': 7.28.6(@babel/core@7.29.0) + '@babel/plugin-transform-modules-commonjs': 7.28.6(@babel/core@7.29.0) + '@babel/plugin-transform-nullish-coalescing-operator': 7.28.6(@babel/core@7.29.0) + '@babel/plugin-transform-optional-chaining': 7.28.6(@babel/core@7.29.0) + '@babel/plugin-transform-private-methods': 7.28.6(@babel/core@7.29.0) + '@babel/preset-flow': 7.27.1(@babel/core@7.29.0) + '@babel/preset-typescript': 7.28.5(@babel/core@7.29.0) + '@babel/register': 7.28.6(@babel/core@7.29.0) + flow-parser: 0.299.0 graceful-fs: 4.2.11 micromatch: 4.0.8 neo-async: 2.6.2 @@ -5624,22 +5625,22 @@ snapshots: kind-of@6.0.3: {} - knip@5.82.1(@types/node@25.0.9)(typescript@5.9.3): + knip@5.83.0(@types/node@25.2.0)(typescript@5.9.3): dependencies: '@nodelib/fs.walk': 1.2.8 - '@types/node': 25.0.9 + '@types/node': 25.2.0 fast-glob: 3.3.3 formatly: 0.3.0 jiti: 2.6.1 js-yaml: 4.1.1 minimist: 1.2.8 - oxc-resolver: 11.16.3 + oxc-resolver: 11.17.0 picocolors: 1.1.1 picomatch: 4.0.3 smol-toml: 1.6.0 strip-json-comments: 5.0.3 typescript: 5.9.3 - zod: 4.3.5 + zod: 4.3.6 leven@3.1.0: {} @@ -5677,7 +5678,7 @@ snapshots: dependencies: js-tokens: 4.0.0 - lru-cache@11.2.4: {} + lru-cache@11.2.5: {} lru-cache@5.1.1: dependencies: @@ -5717,7 +5718,7 @@ snapshots: metro-babel-transformer@0.81.5: dependencies: - '@babel/core': 7.28.6 + '@babel/core': 7.29.0 flow-enums-runtime: 0.0.6 hermes-parser: 0.25.1 nullthrows: 1.1.1 @@ -5785,9 +5786,9 @@ snapshots: metro-source-map@0.81.5: dependencies: - '@babel/traverse': 7.28.6 - '@babel/traverse--for-generate-function-map': '@babel/traverse@7.28.6' - '@babel/types': 7.28.6 + '@babel/traverse': 7.29.0 + '@babel/traverse--for-generate-function-map': '@babel/traverse@7.29.0' + '@babel/types': 7.29.0 flow-enums-runtime: 0.0.6 invariant: 2.2.4 metro-symbolicate: 0.81.5 @@ -5811,10 +5812,10 @@ snapshots: metro-transform-plugins@0.81.5: dependencies: - '@babel/core': 7.28.6 - '@babel/generator': 7.28.6 + '@babel/core': 7.29.0 + '@babel/generator': 7.29.1 '@babel/template': 7.28.6 - '@babel/traverse': 7.28.6 + '@babel/traverse': 7.29.0 flow-enums-runtime: 0.0.6 nullthrows: 1.1.1 transitivePeerDependencies: @@ -5822,10 +5823,10 @@ snapshots: metro-transform-worker@0.81.5: dependencies: - '@babel/core': 7.28.6 - '@babel/generator': 7.28.6 - '@babel/parser': 7.28.6 - '@babel/types': 7.28.6 + '@babel/core': 7.29.0 + '@babel/generator': 7.29.1 + '@babel/parser': 7.29.0 + '@babel/types': 7.29.0 flow-enums-runtime: 0.0.6 metro: 0.81.5 metro-babel-transformer: 0.81.5 @@ -5842,13 +5843,13 @@ snapshots: metro@0.81.5: dependencies: - '@babel/code-frame': 7.28.6 - '@babel/core': 7.28.6 - '@babel/generator': 7.28.6 - '@babel/parser': 7.28.6 + '@babel/code-frame': 7.29.0 + '@babel/core': 7.29.0 + '@babel/generator': 7.29.1 + '@babel/parser': 7.29.0 '@babel/template': 7.28.6 - '@babel/traverse': 7.28.6 - '@babel/types': 7.28.6 + '@babel/traverse': 7.29.0 + '@babel/types': 7.29.0 accepts: 1.3.8 chalk: 4.1.2 ci-info: 2.0.0 @@ -5904,9 +5905,9 @@ snapshots: minimalistic-crypto-utils@1.0.1: {} - minimatch@10.1.1: + minimatch@10.1.2: dependencies: - '@isaacs/brace-expansion': 5.0.0 + '@isaacs/brace-expansion': 5.0.1 minimatch@3.1.2: dependencies: @@ -5983,28 +5984,28 @@ snapshots: outdent@0.5.0: {} - oxc-resolver@11.16.3: + oxc-resolver@11.17.0: optionalDependencies: - '@oxc-resolver/binding-android-arm-eabi': 11.16.3 - '@oxc-resolver/binding-android-arm64': 11.16.3 - '@oxc-resolver/binding-darwin-arm64': 11.16.3 - '@oxc-resolver/binding-darwin-x64': 11.16.3 - '@oxc-resolver/binding-freebsd-x64': 11.16.3 - '@oxc-resolver/binding-linux-arm-gnueabihf': 11.16.3 - '@oxc-resolver/binding-linux-arm-musleabihf': 11.16.3 - '@oxc-resolver/binding-linux-arm64-gnu': 11.16.3 - '@oxc-resolver/binding-linux-arm64-musl': 11.16.3 - '@oxc-resolver/binding-linux-ppc64-gnu': 11.16.3 - '@oxc-resolver/binding-linux-riscv64-gnu': 11.16.3 - '@oxc-resolver/binding-linux-riscv64-musl': 11.16.3 - '@oxc-resolver/binding-linux-s390x-gnu': 11.16.3 - '@oxc-resolver/binding-linux-x64-gnu': 11.16.3 - '@oxc-resolver/binding-linux-x64-musl': 11.16.3 - '@oxc-resolver/binding-openharmony-arm64': 11.16.3 - '@oxc-resolver/binding-wasm32-wasi': 11.16.3 - '@oxc-resolver/binding-win32-arm64-msvc': 11.16.3 - '@oxc-resolver/binding-win32-ia32-msvc': 11.16.3 - '@oxc-resolver/binding-win32-x64-msvc': 11.16.3 + '@oxc-resolver/binding-android-arm-eabi': 11.17.0 + '@oxc-resolver/binding-android-arm64': 11.17.0 + '@oxc-resolver/binding-darwin-arm64': 11.17.0 + '@oxc-resolver/binding-darwin-x64': 11.17.0 + '@oxc-resolver/binding-freebsd-x64': 11.17.0 + '@oxc-resolver/binding-linux-arm-gnueabihf': 11.17.0 + '@oxc-resolver/binding-linux-arm-musleabihf': 11.17.0 + '@oxc-resolver/binding-linux-arm64-gnu': 11.17.0 + '@oxc-resolver/binding-linux-arm64-musl': 11.17.0 + '@oxc-resolver/binding-linux-ppc64-gnu': 11.17.0 + '@oxc-resolver/binding-linux-riscv64-gnu': 11.17.0 + '@oxc-resolver/binding-linux-riscv64-musl': 11.17.0 + '@oxc-resolver/binding-linux-s390x-gnu': 11.17.0 + '@oxc-resolver/binding-linux-x64-gnu': 11.17.0 + '@oxc-resolver/binding-linux-x64-musl': 11.17.0 + '@oxc-resolver/binding-openharmony-arm64': 11.17.0 + '@oxc-resolver/binding-wasm32-wasi': 11.17.0 + '@oxc-resolver/binding-win32-arm64-msvc': 11.17.0 + '@oxc-resolver/binding-win32-ia32-msvc': 11.17.0 + '@oxc-resolver/binding-win32-x64-msvc': 11.17.0 p-filter@2.1.0: dependencies: @@ -6049,7 +6050,7 @@ snapshots: path-scurry@2.0.1: dependencies: - lru-cache: 11.2.4 + lru-cache: 11.2.5 minipass: 7.1.2 path-type@4.0.0: {} @@ -6110,19 +6111,19 @@ snapshots: react-is@18.3.1: {} - react-native-passkeys@0.4.0(react-native@0.77.1(@babel/core@7.28.6)(@types/react@18.3.27)(react@18.3.1))(react@18.3.1): + react-native-passkeys@0.4.0(react-native@0.77.1(@babel/core@7.29.0)(@types/react@18.3.27)(react@18.3.1))(react@18.3.1): dependencies: react: 18.3.1 - react-native: 0.77.1(@babel/core@7.28.6)(@types/react@18.3.27)(react@18.3.1) + react-native: 0.77.1(@babel/core@7.29.0)(@types/react@18.3.27)(react@18.3.1) - react-native-webview@13.16.0(react-native@0.77.1(@babel/core@7.28.6)(@types/react@18.3.27)(react@18.3.1))(react@18.3.1): + react-native-webview@13.16.0(react-native@0.77.1(@babel/core@7.29.0)(@types/react@18.3.27)(react@18.3.1))(react@18.3.1): dependencies: escape-string-regexp: 4.0.0 invariant: 2.2.4 react: 18.3.1 - react-native: 0.77.1(@babel/core@7.28.6)(@types/react@18.3.27)(react@18.3.1) + react-native: 0.77.1(@babel/core@7.29.0)(@types/react@18.3.27)(react@18.3.1) - react-native@0.77.1(@babel/core@7.28.6)(@types/react@18.3.27)(react@18.3.1): + react-native@0.77.1(@babel/core@7.29.0)(@types/react@18.3.27)(react@18.3.1): dependencies: '@jest/create-cache-key-function': 29.7.0 '@react-native/assets-registry': 0.77.1 @@ -6131,11 +6132,11 @@ snapshots: '@react-native/gradle-plugin': 0.77.1 '@react-native/js-polyfills': 0.77.1 '@react-native/normalize-colors': 0.77.1 - '@react-native/virtualized-lists': 0.77.1(@types/react@18.3.27)(react-native@0.77.1(@babel/core@7.28.6)(@types/react@18.3.27)(react@18.3.1))(react@18.3.1) + '@react-native/virtualized-lists': 0.77.1(@types/react@18.3.27)(react-native@0.77.1(@babel/core@7.29.0)(@types/react@18.3.27)(react@18.3.1))(react@18.3.1) abort-controller: 3.0.0 anser: 1.4.10 ansi-regex: 5.0.1 - babel-jest: 29.7.0(@babel/core@7.28.6) + babel-jest: 29.7.0(@babel/core@7.29.0) babel-plugin-syntax-hermes-parser: 0.25.1 base64-js: 1.5.1 chalk: 4.1.2 @@ -6384,7 +6385,7 @@ snapshots: dependencies: '@jridgewell/gen-mapping': 0.3.13 commander: 4.1.1 - glob: 13.0.0 + glob: 13.0.1 lines-and-columns: 1.2.4 mz: 2.7.0 pirates: 4.0.7 @@ -6458,7 +6459,7 @@ snapshots: typedoc@0.28.16(typescript@5.9.3): dependencies: - '@gerrit0/mini-shiki': 3.21.0 + '@gerrit0/mini-shiki': 3.22.0 lunr: 2.3.9 markdown-it: 14.1.0 minimatch: 9.0.5 @@ -6575,4 +6576,4 @@ snapshots: y18n: 5.0.8 yargs-parser: 21.1.1 - zod@4.3.5: {} + zod@4.3.6: {} diff --git a/src/core/provider.tsx b/src/core/provider.tsx index 611fd37..037b923 100644 --- a/src/core/provider.tsx +++ b/src/core/provider.tsx @@ -255,9 +255,12 @@ export const OpenfortProvider = ({ // Create passkey handler if passkey recovery is configured (single instance for SDK and WebView) const passkeyHandler = useMemo(() => { if (walletConfig?.passkeyRpId) { + if (!walletConfig.passkeyRpName) { + logger.warn('passkeyRpName is required when passkeyRpId is provided for passkey recovery') + } return new NativePasskeyHandler({ rpId: walletConfig.passkeyRpId, - rpName: walletConfig.passkeyRpName, + rpName: walletConfig.passkeyRpName ?? walletConfig.passkeyRpId, }) } return undefined @@ -483,6 +486,7 @@ export const OpenfortProvider = ({ { // Handle WebView status changes for debugging if (verbose) { diff --git a/src/hooks/wallet/useEmbeddedEthereumWallet.ts b/src/hooks/wallet/useEmbeddedEthereumWallet.ts index a28eabd..db2b0f9 100644 --- a/src/hooks/wallet/useEmbeddedEthereumWallet.ts +++ b/src/hooks/wallet/useEmbeddedEthereumWallet.ts @@ -485,7 +485,10 @@ export function useEmbeddedEthereumWallet(options: UseEmbeddedEthereumWalletOpti if (embeddedAccountToRecover.recoveryMethod === RecoveryMethod.PASSKEY) { effectiveRecoveryMethod = 'passkey' if (!effectivePasskeyId) { - effectivePasskeyId = embeddedAccountToRecover.recoveryMethodDetails?.passkeyId + const details = embeddedAccountToRecover.recoveryMethodDetails + if (details && 'passkeyId' in details && typeof details.passkeyId === 'string') { + effectivePasskeyId = details.passkeyId + } } } else if (embeddedAccountToRecover.recoveryMethod === RecoveryMethod.PASSWORD) { effectiveRecoveryMethod = 'password' diff --git a/src/hooks/wallet/useEmbeddedSolanaWallet.ts b/src/hooks/wallet/useEmbeddedSolanaWallet.ts index cf47999..de996e5 100644 --- a/src/hooks/wallet/useEmbeddedSolanaWallet.ts +++ b/src/hooks/wallet/useEmbeddedSolanaWallet.ts @@ -462,7 +462,10 @@ export function useEmbeddedSolanaWallet(options: UseEmbeddedSolanaWalletOptions if (embeddedAccountToRecover.recoveryMethod === RecoveryMethod.PASSKEY) { effectiveRecoveryMethod = 'passkey' if (!effectivePasskeyId) { - effectivePasskeyId = embeddedAccountToRecover.recoveryMethodDetails?.passkeyId + const details = embeddedAccountToRecover.recoveryMethodDetails + if (details && 'passkeyId' in details && typeof details.passkeyId === 'string') { + effectivePasskeyId = details.passkeyId + } } } else if (embeddedAccountToRecover.recoveryMethod === RecoveryMethod.PASSWORD) { effectiveRecoveryMethod = 'password' @@ -585,7 +588,7 @@ export function useEmbeddedSolanaWallet(options: UseEmbeddedSolanaWalletOptions } if (status.status === 'connecting' || status.status === 'reconnecting' || status.status === 'loading') { - return { ...baseActions, status: 'connecting' } + return { ...baseActions, status: 'connecting', activeWallet } } if (status.status === 'error') { @@ -611,7 +614,7 @@ export function useEmbeddedSolanaWallet(options: UseEmbeddedSolanaWalletOptions if (activeAccount && !provider) { // Have wallet but provider not initialized yet (mount recovery in progress) - return { ...baseActions, status: 'connecting' } + return { ...baseActions, status: 'connecting', activeWallet } } // Default: disconnected (authenticated but no wallet selected) diff --git a/src/native/index.ts b/src/native/index.ts index be12869..964d6f0 100644 --- a/src/native/index.ts +++ b/src/native/index.ts @@ -15,7 +15,7 @@ export { } from './oauth' export type { NativePasskeyHandlerConfig, PasskeysAPI } from './passkey' // Passkey handler and support checks -export { isPasskeySupported, NativePasskeyHandler } from './passkey' +export { getPasskeyDiagnostics, isPasskeySupported, NativePasskeyHandler } from './passkey' export type { SecureStorageMessage, SecureStorageResponse, diff --git a/src/native/passkey.ts b/src/native/passkey.ts index c018518..c1e625a 100644 --- a/src/native/passkey.ts +++ b/src/native/passkey.ts @@ -1,9 +1,134 @@ -import { type IPasskeyHandler, PasskeyUtils } from '@openfort/openfort-js' +import { + type IPasskeyHandler, + PasskeyAssertionFailedError, + PasskeyCreationFailedError, + PasskeyPRFNotSupportedError, + PasskeySeedInvalidError, + PasskeyUserCancelledError, +} from '@openfort/openfort-js' +import { logger } from '../lib/logger' + +/** + * Utility functions for passkey operations in React Native. + * Handles base64/base64url encoding, key extraction, and challenge generation. + */ +const PasskeyUtils = { + /** Valid byte lengths for derived keys (AES-128, AES-192, AES-256) */ + validByteLengths: [16, 24, 32], + + /** + * Validates that the key byte length is valid for AES encryption. + * @throws Error if length is not 16, 24, or 32 + */ + validateKeyByteLength(length: number): void { + if (!this.validByteLengths.includes(length)) { + throw new Error(`Invalid key byte length ${length}. Must be 16, 24, or 32.`) + } + }, + + /** + * Generates a random 32-byte challenge for WebAuthn operations. + */ + generateChallenge(): Uint8Array { + const challenge = new Uint8Array(32) + if (typeof crypto !== 'undefined' && crypto.getRandomValues) { + crypto.getRandomValues(challenge) + } else { + // Fallback for environments without crypto.getRandomValues + for (let i = 0; i < 32; i++) { + challenge[i] = Math.floor(Math.random() * 256) + } + } + return challenge + }, + + /** + * Converts ArrayBuffer or Uint8Array to base64url string. + * Base64URL uses '-' and '_' instead of '+' and '/', and omits padding '='. + */ + arrayBufferToBase64URL(buffer: ArrayBuffer | Uint8Array): string { + const bytes = buffer instanceof Uint8Array ? buffer : new Uint8Array(buffer) + let binary = '' + for (const byte of bytes) { + binary += String.fromCharCode(byte) + } + const base64 = btoa(binary) + return base64.replace(/\+/g, '-').replace(/\//g, '_').replace(/=/g, '') + }, + + /** + * Converts base64url string to Uint8Array. + */ + base64URLToUint8Array(base64url: string): Uint8Array { + // Convert base64url to base64 + let base64 = base64url.replace(/-/g, '+').replace(/_/g, '/') + // Add padding if needed + while (base64.length % 4) { + base64 += '=' + } + const binary = atob(base64) + const bytes = new Uint8Array(binary.length) + for (let i = 0; i < binary.length; i++) { + bytes[i] = binary.charCodeAt(i) + } + return bytes + }, + + /** + * Converts standard base64 to base64url format. + * This is idempotent - safe to call on strings already in base64url format. + */ + base64ToBase64URL(base64: string): string { + return base64.replace(/\+/g, '-').replace(/\//g, '_').replace(/=/g, '') + }, + + /** + * Extracts the first N bytes from a PRF result for use as key material. + */ + extractRawKeyBytes(prfResult: Uint8Array, length: number): Uint8Array { + return prfResult.slice(0, length) + }, +} + +/** + * Result from passkey credential creation. + */ +interface PasskeyCredentialResult { + id: string + rawId?: string + type: string + clientExtensionResults?: { + prf?: { + results?: { + first?: unknown // Can be string, ArrayBuffer, or number[] + } + } + } + response?: { + attestationObject?: string + clientDataJSON?: string + } +} + +/** + * Result from passkey assertion (get). + */ +interface PasskeyAssertionResult { + id: string + type: string + clientExtensionResults?: { + prf?: { + results?: { + first?: unknown + } + } + } +} /** Resolved API from react-native-passkeys (module.Passkeys ?? module). Library may export sync or async isSupported. */ export type PasskeysAPI = { - create?: (options: any) => Promise - get?: (options: any) => Promise + create?: (options: PublicKeyCredentialCreationOptions) => Promise + get?: (options: PublicKeyCredentialRequestOptions) => Promise /** Sync on native (iOS/Android), sync on web; may be function or boolean. */ isSupported?: (() => boolean) | (() => Promise) | boolean } @@ -30,6 +155,23 @@ function getPasskeysAPI(): PasskeysAPI | null { } } +/** + * Returns diagnostic information about passkey support. + * Useful for debugging why passkeys may not be available. + */ +export function getPasskeyDiagnostics(): { + isSupported: boolean + loadError: Error | null + moduleLoaded: boolean +} { + const api = getPasskeysAPI() + return { + isSupported: api !== null && api.isSupported !== undefined, + loadError: passkeysLoadError, + moduleLoaded: passkeysLoadAttempted && passkeysLoadError === null, + } +} + /** * Checks if the device supports passkeys (WebAuthn). Uses the library's isSupported() only — no credential creation. * Normalizes sync/async and function/boolean from react-native-passkeys. @@ -81,6 +223,7 @@ interface PublicKeyCredentialRequestOptions { allowCredentials: Array<{ id: string; type: string }> userVerification: string extensions?: { prf?: { eval?: { first: string } } } + timeout?: number } /** @@ -125,8 +268,15 @@ export class NativePasskeyHandler implements IPasskeyHandler { /** * Extracts key bytes from PRF result and returns as base64url string. + * Validates that the PRF result has sufficient entropy for the requested key length. */ private extractKeyBytes(prfResultBytes: Uint8Array): string { + // Validate PRF result has sufficient entropy + if (prfResultBytes.length < this.derivedKeyLengthBytes) { + throw new Error( + `PRF result too short: got ${prfResultBytes.length} bytes, need at least ${this.derivedKeyLengthBytes} bytes` + ) + } const keyBytes = PasskeyUtils.extractRawKeyBytes(prfResultBytes, this.derivedKeyLengthBytes) return PasskeyUtils.arrayBufferToBase64URL(keyBytes) } @@ -143,6 +293,11 @@ export class NativePasskeyHandler implements IPasskeyHandler { throw new Error('rpId and rpName must be configured') } + // Validate seed is non-empty for PRF entropy + if (!config.seed || config.seed.trim().length === 0) { + throw new PasskeySeedInvalidError() + } + const challenge = PasskeyUtils.generateChallenge() // Android Credentials API requires base64url for challenge const challengeBase64URL = PasskeyUtils.arrayBufferToBase64URL(challenge) @@ -184,14 +339,33 @@ export class NativePasskeyHandler implements IPasskeyHandler { throw new Error('react-native-passkeys module not available') } - const credential = await api.create(publicKey as any) + let credential: PasskeyCredentialResult | null + try { + credential = await api.create(publicKey) + } catch (e) { + // Re-throw known error types + if (e instanceof PasskeyUserCancelledError) throw e + if (e instanceof PasskeySeedInvalidError) throw e + throw new PasskeyCreationFailedError( + e instanceof Error ? e.message : 'Unknown error', + e instanceof Error ? e : undefined + ) + } + if (!credential) { - throw new Error('Could not create passkey') + // Null result typically indicates user cancellation + throw new PasskeyUserCancelledError() } const prfResults = credential.clientExtensionResults?.prf if (!prfResults?.results?.first) { - throw new Error('PRF extension not supported or missing results') + // Log warning about orphaned passkey credential + logger.warn( + 'Passkey created but PRF extension failed. ' + + 'A passkey credential may exist on the device that cannot be used for wallet recovery. ' + + `Credential ID: ${credential.id}` + ) + throw new PasskeyPRFNotSupportedError() } const prfResultBytes = this.normalizePRFResult(prfResults.results.first) @@ -212,11 +386,15 @@ export class NativePasskeyHandler implements IPasskeyHandler { throw new Error('rpId must be configured') } + // Validate seed is non-empty for PRF entropy + if (!config.seed || config.seed.trim().length === 0) { + throw new PasskeySeedInvalidError() + } + const challenge = PasskeyUtils.generateChallenge() const challengeBase64URL = PasskeyUtils.arrayBufferToBase64URL(challenge) - // Openfort may store credential id as standard base64; react-native-passkeys expects base64url - const credentialId = - config.id.includes('+') || config.id.includes('/') ? PasskeyUtils.base64ToBase64URL(config.id) : config.id + // Always normalize to base64url - this is idempotent for strings already in base64url format + const credentialId = PasskeyUtils.base64ToBase64URL(config.id) const publicKey: PublicKeyCredentialRequestOptions = { challenge: challengeBase64URL, @@ -230,6 +408,7 @@ export class NativePasskeyHandler implements IPasskeyHandler { }, }, }, + timeout: this.timeout, } const api = getPasskeysAPI() @@ -237,14 +416,27 @@ export class NativePasskeyHandler implements IPasskeyHandler { throw new Error('react-native-passkeys module not available') } - const assertion = await api.get(publicKey as any) + let assertion: PasskeyAssertionResult | null + try { + assertion = await api.get(publicKey) + } catch (e) { + // Re-throw known error types + if (e instanceof PasskeyUserCancelledError) throw e + if (e instanceof PasskeySeedInvalidError) throw e + throw new PasskeyAssertionFailedError( + e instanceof Error ? e.message : 'Unknown error', + e instanceof Error ? e : undefined + ) + } + if (!assertion) { - throw new Error('Could not get passkey assertion') + // Null result typically indicates user cancellation + throw new PasskeyUserCancelledError() } const prfResults = assertion.clientExtensionResults?.prf if (!prfResults?.results?.first) { - throw new Error('PRF extension not supported or missing results') + throw new PasskeyPRFNotSupportedError() } const prfResultBytes = this.normalizePRFResult(prfResults.results.first) diff --git a/src/native/webview.tsx b/src/native/webview.tsx index 29dff14..d3a98c1 100644 --- a/src/native/webview.tsx +++ b/src/native/webview.tsx @@ -19,6 +19,8 @@ interface EmbeddedWalletWebViewProps { isClientReady: boolean /** Callback when WebView proxy status changes */ onProxyStatusChange?: (status: 'loading' | 'loaded' | 'reloading') => void + /** Enable WebView debugging (allows inspection via Safari/Chrome dev tools) */ + debug?: boolean } /** @@ -28,7 +30,7 @@ interface EmbeddedWalletWebViewProps { * * @param props - Component props, see {@link EmbeddedWalletWebViewProps} */ -export const EmbeddedWalletWebView: React.FC = ({ client, onProxyStatusChange }) => { +export const EmbeddedWalletWebView: React.FC = ({ client, onProxyStatusChange, debug }) => { const webViewRef = useRef(null) // Handle app state changes to monitor WebView health @@ -121,7 +123,8 @@ export const EmbeddedWalletWebView: React.FC = ({ cl source={{ uri: client.embeddedWallet.getURL(), }} - webviewDebuggingEnabled={true} + // Enable debugging when explicitly enabled via walletConfig.debug + webviewDebuggingEnabled={debug} cacheEnabled={false} injectedJavaScriptObject={{ shouldUseAppBackedStorage: true }} cacheMode="LOAD_NO_CACHE" diff --git a/src/types/index.ts b/src/types/index.ts index 3404f87..908e7db 100644 --- a/src/types/index.ts +++ b/src/types/index.ts @@ -7,6 +7,16 @@ export interface UseOpenfort { error: Error | null } +// Passkey error types (re-exported from @openfort/openfort-js) +export { + PASSKEY_ERROR_CODES, + PasskeyAssertionFailedError, + PasskeyCreationFailedError, + type PasskeyErrorCode, + PasskeyPRFNotSupportedError, + PasskeySeedInvalidError, + PasskeyUserCancelledError, +} from '@openfort/openfort-js' // Authentication types export type { AuthSuccessCallback, From 7fec94eea4343ab65a3e40235899c12e27082803 Mon Sep 17 00:00:00 2001 From: Jaume Alavedra Date: Thu, 5 Feb 2026 16:56:49 +0100 Subject: [PATCH 06/10] feat: add passkey suport --- .changeset/polite-experts-punch.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/polite-experts-punch.md diff --git a/.changeset/polite-experts-punch.md b/.changeset/polite-experts-punch.md new file mode 100644 index 0000000..d8c1482 --- /dev/null +++ b/.changeset/polite-experts-punch.md @@ -0,0 +1,5 @@ +--- +"@openfort/react-native": patch +--- + +add passkey support From 9370e2a8df8682aa559ea751b4de125ea988d31c Mon Sep 17 00:00:00 2001 From: Jaume Alavedra Date: Thu, 5 Feb 2026 17:40:14 +0100 Subject: [PATCH 07/10] chore: fix issupportedhook --- src/hooks/core/index.ts | 1 - src/hooks/core/usePasskeySupport.ts | 19 ++++++------------- 2 files changed, 6 insertions(+), 14 deletions(-) diff --git a/src/hooks/core/index.ts b/src/hooks/core/index.ts index f9880e7..be489ef 100644 --- a/src/hooks/core/index.ts +++ b/src/hooks/core/index.ts @@ -9,7 +9,6 @@ export { useOpenfort } from './useOpenfort' export { useOpenfortClient } from './useOpenfortClient' -export type { UsePasskeySupportOptions } from './usePasskeySupport' export { usePasskeySupport } from './usePasskeySupport' export { useUser } from './useUser' diff --git a/src/hooks/core/usePasskeySupport.ts b/src/hooks/core/usePasskeySupport.ts index 0e62330..6f946e4 100644 --- a/src/hooks/core/usePasskeySupport.ts +++ b/src/hooks/core/usePasskeySupport.ts @@ -1,21 +1,17 @@ import { useEffect, useState } from 'react' import { isPasskeySupported } from '../../native/passkey' -export type UsePasskeySupportOptions = { - /** Reserved for future use (e.g. RP config). Passkey support uses the library's isSupported() only. */ - rpId?: string - rpName?: string -} - /** * Hook to detect if the platform supports passkeys (WebAuthn). - * Uses the library's isSupported() only — no credential creation. * - * @returns Object containing passkey support (isSupported, isPRFSupported set from the same check) + * Note: This only checks basic passkey support, not PRF extension support. + * PRF support can only be determined during passkey creation via the + * `clientExtensionResults.prf.enabled` field in the response. + * + * @returns Object with `isSupported` boolean and `isLoading` state */ -export function usePasskeySupport(_options?: UsePasskeySupportOptions) { +export function usePasskeySupport() { const [isSupported, setIsSupported] = useState(false) - const [isPRFSupported, setIsPRFSupported] = useState(false) const [isLoading, setIsLoading] = useState(true) useEffect(() => { @@ -23,10 +19,8 @@ export function usePasskeySupport(_options?: UsePasskeySupportOptions) { try { const available = await isPasskeySupported() setIsSupported(available) - setIsPRFSupported(available) } catch { setIsSupported(false) - setIsPRFSupported(false) } finally { setIsLoading(false) } @@ -37,7 +31,6 @@ export function usePasskeySupport(_options?: UsePasskeySupportOptions) { return { isSupported, - isPRFSupported, isLoading, } } From 9f0117c446b04db99a1742079bd47b9c113e8406 Mon Sep 17 00:00:00 2001 From: Jaume Alavedra Date: Thu, 5 Feb 2026 18:01:41 +0100 Subject: [PATCH 08/10] chore: versino --- package.json | 2 +- pnpm-lock.yaml | 11 +++++------ 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/package.json b/package.json index 2e499e6..d68e5ca 100644 --- a/package.json +++ b/package.json @@ -40,7 +40,7 @@ } }, "dependencies": { - "@openfort/openfort-js": "https://pkg.pr.new/@openfort/openfort-js@cc06c35", + "@openfort/openfort-js": "^1.1.5", "react-native-passkeys": "0.4.0" }, "peerDependencies": { diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 608180b..5335f7d 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -13,8 +13,8 @@ importers: .: dependencies: '@openfort/openfort-js': - specifier: https://pkg.pr.new/@openfort/openfort-js@cc06c35 - version: https://pkg.pr.new/@openfort/openfort-js@cc06c35 + specifier: ^1.1.5 + version: 1.1.5 react-native-passkeys: specifier: 0.4.0 version: 0.4.0(react-native@0.77.1(@babel/core@7.29.0)(@types/react@18.3.27)(react@18.3.1))(react@18.3.1) @@ -1012,9 +1012,8 @@ packages: resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} engines: {node: '>= 8'} - '@openfort/openfort-js@https://pkg.pr.new/@openfort/openfort-js@cc06c35': - resolution: {tarball: https://pkg.pr.new/@openfort/openfort-js@cc06c35} - version: 1.1.4 + '@openfort/openfort-js@1.1.5': + resolution: {integrity: sha512-Cx1f/H+/QSL12+deiv9piScSsjM8qVShMr33AdipdoEieKhW3ADpXiZrvKWKFfL5O2PWBN5Tcz7oWwpHEwSCbg==} '@openfort/shield-js@0.1.34': resolution: {integrity: sha512-bJxQc0zk0VPxk7CWSE5NZp5Bv8nYnStwG5GKXrS2A6hxEt0vf4BMu9db4IUiHxmgGaFWrdAnbSCSZ5AU1gwyew==} @@ -4317,7 +4316,7 @@ snapshots: '@nodelib/fs.scandir': 2.1.5 fastq: 1.20.1 - '@openfort/openfort-js@https://pkg.pr.new/@openfort/openfort-js@cc06c35': + '@openfort/openfort-js@1.1.5': dependencies: '@ethersproject/abi': 5.8.0 '@ethersproject/bytes': 5.8.0 From c4335c1902ca57ce0f17658fe1050d6d646aad09 Mon Sep 17 00:00:00 2001 From: Jaume Alavedra Date: Thu, 5 Feb 2026 18:30:11 +0100 Subject: [PATCH 09/10] fix: exoprt wallet --- src/hooks/wallet/useEmbeddedEthereumWallet.ts | 33 ++++++++++-- src/hooks/wallet/useEmbeddedSolanaWallet.ts | 12 +++++ src/index.ts | 3 +- src/types/wallet.ts | 52 ++++++++++++++++++- 4 files changed, 94 insertions(+), 6 deletions(-) diff --git a/src/hooks/wallet/useEmbeddedEthereumWallet.ts b/src/hooks/wallet/useEmbeddedEthereumWallet.ts index db2b0f9..24750e4 100644 --- a/src/hooks/wallet/useEmbeddedEthereumWallet.ts +++ b/src/hooks/wallet/useEmbeddedEthereumWallet.ts @@ -305,10 +305,19 @@ export function useEmbeddedEthereumWallet(options: UseEmbeddedEthereumWalletOpti }, [] as EmbeddedAccount[]) return deduplicatedAccounts.map((account, index) => ({ + id: account.id, address: account.address, + chainType: ChainTypeEnum.EVM, + chainId: account.chainId, ownerAddress: account.ownerAddress, + factoryAddress: account.factoryAddress, + salt: account.salt, + accountType: account.accountType, + implementationAddress: account.implementationAddress, + createdAt: account.createdAt, implementationType: account.implementationType, - chainType: ChainTypeEnum.EVM, + recoveryMethod: account.recoveryMethod, + recoveryMethodDetails: account.recoveryMethodDetails, walletIndex: index, getProvider: async () => await getEthereumProvider(), })) @@ -524,10 +533,19 @@ export function useEmbeddedEthereumWallet(options: UseEmbeddedEthereumWalletOpti ) const wallet: ConnectedEmbeddedEthereumWallet = { + id: embeddedAccount.id, address: embeddedAccount.address, + chainType: ChainTypeEnum.EVM, + chainId: embeddedAccount.chainId, ownerAddress: embeddedAccount.ownerAddress, + factoryAddress: embeddedAccount.factoryAddress, + salt: embeddedAccount.salt, + accountType: embeddedAccount.accountType, + implementationAddress: embeddedAccount.implementationAddress, + createdAt: embeddedAccount.createdAt, implementationType: embeddedAccount.implementationType, - chainType: ChainTypeEnum.EVM, + recoveryMethod: embeddedAccount.recoveryMethod, + recoveryMethodDetails: embeddedAccount.recoveryMethodDetails, walletIndex: walletIndex >= 0 ? walletIndex : 0, getProvider: async () => ethProvider, } @@ -635,10 +653,19 @@ export function useEmbeddedEthereumWallet(options: UseEmbeddedEthereumWalletOpti const accountIndex = embeddedAccounts.findIndex((acc) => acc.id === activeWalletId) return { + id: activeAccount.id, address: activeAccount.address, + chainType: ChainTypeEnum.EVM, + chainId: activeAccount.chainId, ownerAddress: activeAccount.ownerAddress, + factoryAddress: activeAccount.factoryAddress, + salt: activeAccount.salt, + accountType: activeAccount.accountType, + implementationAddress: activeAccount.implementationAddress, + createdAt: activeAccount.createdAt, implementationType: activeAccount.implementationType, - chainType: ChainTypeEnum.EVM, + recoveryMethod: activeAccount.recoveryMethod, + recoveryMethodDetails: activeAccount.recoveryMethodDetails, walletIndex: accountIndex >= 0 ? accountIndex : 0, getProvider: async () => await getEthereumProvider(), } diff --git a/src/hooks/wallet/useEmbeddedSolanaWallet.ts b/src/hooks/wallet/useEmbeddedSolanaWallet.ts index de996e5..781e904 100644 --- a/src/hooks/wallet/useEmbeddedSolanaWallet.ts +++ b/src/hooks/wallet/useEmbeddedSolanaWallet.ts @@ -322,8 +322,12 @@ export function useEmbeddedSolanaWallet(options: UseEmbeddedSolanaWalletOptions // Build wallets list (simple deduplication by address) const wallets: ConnectedEmbeddedSolanaWallet[] = useMemo(() => { return embeddedAccounts.map((account, index) => ({ + id: account.id, address: account.address, chainType: ChainTypeEnum.SVM, + createdAt: account.createdAt, + recoveryMethod: account.recoveryMethod, + recoveryMethodDetails: account.recoveryMethodDetails, walletIndex: index, getProvider: async () => await getSolanaProvider(account), })) @@ -499,8 +503,12 @@ export function useEmbeddedSolanaWallet(options: UseEmbeddedSolanaWalletOptions ) const wallet: ConnectedEmbeddedSolanaWallet = { + id: embeddedAccount.id, address: embeddedAccount.address, chainType: ChainTypeEnum.SVM, + createdAt: embeddedAccount.createdAt, + recoveryMethod: embeddedAccount.recoveryMethod, + recoveryMethodDetails: embeddedAccount.recoveryMethodDetails, walletIndex: walletIndex >= 0 ? walletIndex : 0, getProvider: async () => solProvider, } @@ -563,8 +571,12 @@ export function useEmbeddedSolanaWallet(options: UseEmbeddedSolanaWalletOptions const accountIndex = embeddedAccounts.findIndex((acc) => acc.id === activeWalletId) return { + id: activeAccount.id, address: activeAccount.address, chainType: ChainTypeEnum.SVM, + createdAt: activeAccount.createdAt, + recoveryMethod: activeAccount.recoveryMethod, + recoveryMethodDetails: activeAccount.recoveryMethodDetails, walletIndex: accountIndex >= 0 ? accountIndex : 0, getProvider: async () => await getSolanaProvider(activeAccount), } diff --git a/src/index.ts b/src/index.ts index 0f67472..f745c7e 100644 --- a/src/index.ts +++ b/src/index.ts @@ -42,8 +42,9 @@ export * from './constants' export * from './core' // Re-export all hooks export * from './hooks' - // Re-export native functionality export * from './native' // Re-export all types from the main types module export * from './types' +// Re-export RecoveryMethodDetails extracted from EmbeddedAccount (not directly exported from @openfort/openfort-js) +export type { RecoveryMethodDetails } from './types/wallet' diff --git a/src/types/wallet.ts b/src/types/wallet.ts index 2e1c307..3700f58 100644 --- a/src/types/wallet.ts +++ b/src/types/wallet.ts @@ -1,4 +1,16 @@ -import type { AccountTypeEnum, ChainTypeEnum, EmbeddedAccount, RecoveryParams } from '@openfort/openfort-js' +import type { + AccountTypeEnum, + ChainTypeEnum, + EmbeddedAccount, + RecoveryMethod, + RecoveryParams, +} from '@openfort/openfort-js' + +/** + * Recovery method details extracted from EmbeddedAccount + */ +export type RecoveryMethodDetails = EmbeddedAccount['recoveryMethodDetails'] + import type { Hex } from './hex' import type { OpenfortHookOptions } from './hookOption' import type { OpenfortError } from './openfortError' @@ -122,11 +134,35 @@ export interface OpenfortEmbeddedSolanaWalletProvider { * Connected Ethereum wallet */ export type ConnectedEmbeddedEthereumWallet = { + /** Account ID */ + id: string + /** Account address */ address: string + /** Chain type (always EVM) */ + chainType: ChainTypeEnum.EVM + /** Chain ID */ + chainId?: number + /** Owner address (for smart accounts) */ ownerAddress?: string + /** Factory address (for smart accounts) */ + factoryAddress?: string + /** Salt (for smart accounts) */ + salt?: string + /** Account type (EOA, Smart Account, Delegated) */ + accountType: AccountTypeEnum + /** Implementation address (for smart accounts) */ + implementationAddress?: string + /** Creation timestamp */ + createdAt?: number + /** Implementation type */ implementationType?: string - chainType: ChainTypeEnum.EVM + /** Recovery method used for this wallet */ + recoveryMethod?: RecoveryMethod + /** Recovery method details (e.g., passkey info) */ + recoveryMethodDetails?: RecoveryMethodDetails + /** Index in the wallets array */ walletIndex: number + /** Get the EIP-1193 provider for this wallet */ getProvider: () => Promise } @@ -134,9 +170,21 @@ export type ConnectedEmbeddedEthereumWallet = { * Connected Solana wallet */ export type ConnectedEmbeddedSolanaWallet = { + /** Account ID */ + id: string + /** Account address (public key) */ address: string + /** Chain type (always SVM) */ chainType: ChainTypeEnum.SVM + /** Creation timestamp */ + createdAt?: number + /** Recovery method used for this wallet */ + recoveryMethod?: RecoveryMethod + /** Recovery method details (e.g., passkey info) */ + recoveryMethodDetails?: RecoveryMethodDetails + /** Index in the wallets array */ walletIndex: number + /** Get the Solana provider for this wallet */ getProvider: () => Promise } From 6032190cdbe6abb82fc3e8e74398965af35f028c Mon Sep 17 00:00:00 2001 From: Jaume Alavedra Date: Thu, 5 Feb 2026 19:10:39 +0100 Subject: [PATCH 10/10] fix: add missing error --- src/hooks/wallet/utils.ts | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/hooks/wallet/utils.ts b/src/hooks/wallet/utils.ts index e0a143e..be428bb 100644 --- a/src/hooks/wallet/utils.ts +++ b/src/hooks/wallet/utils.ts @@ -109,8 +109,14 @@ export async function buildRecoveryParams( } } - // If password is provided, use password recovery - if (options?.recoveryPassword) { + // If password recovery method is explicitly requested or password is provided + if (options?.recoveryMethod === 'password' || options?.recoveryPassword) { + if (!options?.recoveryPassword) { + throw new OpenfortError( + 'Recovery password is required when using password recovery method', + OpenfortErrorType.WALLET_ERROR + ) + } return { recoveryMethod: RecoveryMethod.PASSWORD, password: options.recoveryPassword,