From 69896dd32aeb44fefcaf30f975ecd8a29bf44b7f Mon Sep 17 00:00:00 2001 From: Andreas Wiermann Date: Thu, 13 Aug 2026 13:16:35 -0300 Subject: [PATCH] chore: add bare-react-native flow example The committed pnpm-lock.yaml resolved every @dynamic-labs* package against the internal fbinfra555artifactory.jfrog.io proxy, which is unreachable outside Fireblocks' network. A public clone running `pnpm install --frozen-lockfile` in this example would fail. Rewrote all 191 tarball resolution URLs to the equivalent public registry.npmjs.org path for the same package/version. Verified byte-for-byte equivalence by installing once via the internal proxy to populate the local pnpm store, then re-running `pnpm install --frozen-lockfile --offline` against the rewritten lockfile -- it resolved entirely from the local content-addressed store with zero network calls, confirming the integrity hashes match. No package.json changes. --- .../.bundle/config | 2 + .../.env.example | 23 + .../.eslintignore | 20 + .../.eslintrc.js | 4 + .../.gitignore | 81 + .../.prettierrc.js | 5 + .../.watchmanconfig | 1 + .../Gemfile | 22 + .../Gemfile.lock | 173 + .../README.md | 242 ++ .../android/app/build.gradle | 119 + .../android/app/debug.keystore | Bin 0 -> 2257 bytes .../android/app/proguard-rules.pro | 10 + .../android/app/src/main/AndroidManifest.xml | 55 + .../bareflowmetamaskdemo/MainActivity.kt | 33 + .../bareflowmetamaskdemo/MainApplication.kt | 38 + .../res/drawable/rn_edit_text_material.xml | 37 + .../src/main/res/mipmap-hdpi/ic_launcher.png | Bin 0 -> 3056 bytes .../res/mipmap-hdpi/ic_launcher_round.png | Bin 0 -> 5024 bytes .../src/main/res/mipmap-mdpi/ic_launcher.png | Bin 0 -> 2096 bytes .../res/mipmap-mdpi/ic_launcher_round.png | Bin 0 -> 2858 bytes .../src/main/res/mipmap-xhdpi/ic_launcher.png | Bin 0 -> 4569 bytes .../res/mipmap-xhdpi/ic_launcher_round.png | Bin 0 -> 7098 bytes .../main/res/mipmap-xxhdpi/ic_launcher.png | Bin 0 -> 6464 bytes .../res/mipmap-xxhdpi/ic_launcher_round.png | Bin 0 -> 10676 bytes .../main/res/mipmap-xxxhdpi/ic_launcher.png | Bin 0 -> 9250 bytes .../res/mipmap-xxxhdpi/ic_launcher_round.png | Bin 0 -> 15523 bytes .../app/src/main/res/values/strings.xml | 3 + .../app/src/main/res/values/styles.xml | 9 + .../android/build.gradle | 21 + .../android/gradle.properties | 44 + .../android/gradle/wrapper/gradle-wrapper.jar | Bin 0 -> 43764 bytes .../gradle/wrapper/gradle-wrapper.properties | 7 + .../android/gradlew | 251 ++ .../android/gradlew.bat | 99 + .../android/settings.gradle | 23 + .../app.json | 4 + .../babel.config.js | 20 + .../dynamicClient.ts | 72 + .../index.js | 13 + .../ios/.xcode.env | 11 + .../project.pbxproj | 478 +++ .../xcschemes/BareFlowMetaMaskDemo.xcscheme | 88 + .../contents.xcworkspacedata | 10 + .../BareFlowMetaMaskDemo/AppDelegate.swift | 61 + .../AppIcon.appiconset/Contents.json | 53 + .../Images.xcassets/Contents.json | 6 + .../ios/BareFlowMetaMaskDemo/Info.plist | 68 + .../LaunchScreen.storyboard | 47 + .../PrivacyInfo.xcprivacy | 37 + .../ios/Podfile | 108 + .../ios/Podfile.lock | 3050 +++++++++++++++++ .../metro.config.js | 33 + .../package.json | 63 + .../@react-native__codegen@0.81.4.patch | 36 + .../pnpm-workspace.yaml | 2 + .../polyfills.ts | 127 + .../shims/ws.js | 25 + .../src/App.tsx | 25 + .../src/components/CopyButton.tsx | 43 + .../src/components/ErrorText.tsx | 28 + .../src/components/Header.tsx | 87 + .../src/components/LinkButton.tsx | 69 + .../src/components/ListRow.tsx | 109 + .../src/components/PrimaryButton.tsx | 77 + .../src/components/Screen.tsx | 87 + .../src/components/SecondaryButton.tsx | 70 + .../src/components/Skeleton.tsx | 62 + .../src/components/icons.tsx | 147 + .../src/consts/config.ts | 44 + .../src/consts/flow.ts | 61 + .../src/consts/theme.ts | 111 + .../src/navigation.tsx | 136 + .../src/routes/AccountRoute.tsx | 37 + .../src/routes/ConnectWalletRoute.tsx | 102 + .../src/routes/DepositRoute.tsx | 130 + .../src/routes/FlowStatusRoute.tsx | 261 ++ .../src/routes/FundGasRoute.tsx | 138 + .../src/routes/HomeRoute.tsx | 73 + .../src/routes/LoginRoute.tsx | 38 + .../src/routes/OtpRoute.tsx | 86 + .../src/routes/ProvisioningRoute.tsx | 69 + .../src/routes/WithdrawAmountRoute.tsx | 199 ++ .../src/routes/WithdrawRoute.tsx | 194 ++ .../src/utils/connectCatalogWallet.ts | 50 + .../src/utils/connectEphemeralWallet.ts | 49 + .../src/utils/connectMetaMask.ts | 26 + .../src/utils/createDepositFlow.ts | 60 + .../src/utils/createWithdrawFlow.ts | 62 + .../src/utils/getNativeBalance.ts | 23 + .../src/utils/getUsdcBalance.ts | 43 + .../src/utils/isValidAmount.ts | 15 + .../src/utils/normalizeAmount.ts | 9 + .../src/utils/resolveWalletAccounts.ts | 23 + .../src/utils/shortAddress.ts | 4 + .../src/utils/vault.ts | 25 + .../src/views/AccountView.tsx | 74 + .../src/views/AmountView.tsx | 175 + .../src/views/FlowStatusView.tsx | 657 ++++ .../src/views/FundGasView.tsx | 76 + .../src/views/HomeView.tsx | 275 ++ .../src/views/LoginView.tsx | 119 + .../src/views/OtpView.tsx | 148 + .../src/views/ProvisioningView.tsx | 97 + .../src/views/SplashView.tsx | 71 + .../src/views/WalletPickerView.tsx | 83 + .../tsconfig.json | 11 + examples/rn-moneygram-ramp/pnpm-lock.yaml | 382 +-- 108 files changed, 10583 insertions(+), 191 deletions(-) create mode 100644 examples/bare-react-native-with-js-sdk-and-flow/.bundle/config create mode 100644 examples/bare-react-native-with-js-sdk-and-flow/.env.example create mode 100644 examples/bare-react-native-with-js-sdk-and-flow/.eslintignore create mode 100644 examples/bare-react-native-with-js-sdk-and-flow/.eslintrc.js create mode 100644 examples/bare-react-native-with-js-sdk-and-flow/.gitignore create mode 100644 examples/bare-react-native-with-js-sdk-and-flow/.prettierrc.js create mode 100644 examples/bare-react-native-with-js-sdk-and-flow/.watchmanconfig create mode 100644 examples/bare-react-native-with-js-sdk-and-flow/Gemfile create mode 100644 examples/bare-react-native-with-js-sdk-and-flow/Gemfile.lock create mode 100644 examples/bare-react-native-with-js-sdk-and-flow/README.md create mode 100644 examples/bare-react-native-with-js-sdk-and-flow/android/app/build.gradle create mode 100644 examples/bare-react-native-with-js-sdk-and-flow/android/app/debug.keystore create mode 100644 examples/bare-react-native-with-js-sdk-and-flow/android/app/proguard-rules.pro create mode 100644 examples/bare-react-native-with-js-sdk-and-flow/android/app/src/main/AndroidManifest.xml create mode 100644 examples/bare-react-native-with-js-sdk-and-flow/android/app/src/main/java/com/dynamiclabs/examples/bareflowmetamaskdemo/MainActivity.kt create mode 100644 examples/bare-react-native-with-js-sdk-and-flow/android/app/src/main/java/com/dynamiclabs/examples/bareflowmetamaskdemo/MainApplication.kt create mode 100644 examples/bare-react-native-with-js-sdk-and-flow/android/app/src/main/res/drawable/rn_edit_text_material.xml create mode 100644 examples/bare-react-native-with-js-sdk-and-flow/android/app/src/main/res/mipmap-hdpi/ic_launcher.png create mode 100644 examples/bare-react-native-with-js-sdk-and-flow/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png create mode 100644 examples/bare-react-native-with-js-sdk-and-flow/android/app/src/main/res/mipmap-mdpi/ic_launcher.png create mode 100644 examples/bare-react-native-with-js-sdk-and-flow/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png create mode 100644 examples/bare-react-native-with-js-sdk-and-flow/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png create mode 100644 examples/bare-react-native-with-js-sdk-and-flow/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png create mode 100644 examples/bare-react-native-with-js-sdk-and-flow/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png create mode 100644 examples/bare-react-native-with-js-sdk-and-flow/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png create mode 100644 examples/bare-react-native-with-js-sdk-and-flow/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png create mode 100644 examples/bare-react-native-with-js-sdk-and-flow/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png create mode 100644 examples/bare-react-native-with-js-sdk-and-flow/android/app/src/main/res/values/strings.xml create mode 100644 examples/bare-react-native-with-js-sdk-and-flow/android/app/src/main/res/values/styles.xml create mode 100644 examples/bare-react-native-with-js-sdk-and-flow/android/build.gradle create mode 100644 examples/bare-react-native-with-js-sdk-and-flow/android/gradle.properties create mode 100644 examples/bare-react-native-with-js-sdk-and-flow/android/gradle/wrapper/gradle-wrapper.jar create mode 100644 examples/bare-react-native-with-js-sdk-and-flow/android/gradle/wrapper/gradle-wrapper.properties create mode 100755 examples/bare-react-native-with-js-sdk-and-flow/android/gradlew create mode 100644 examples/bare-react-native-with-js-sdk-and-flow/android/gradlew.bat create mode 100644 examples/bare-react-native-with-js-sdk-and-flow/android/settings.gradle create mode 100644 examples/bare-react-native-with-js-sdk-and-flow/app.json create mode 100644 examples/bare-react-native-with-js-sdk-and-flow/babel.config.js create mode 100644 examples/bare-react-native-with-js-sdk-and-flow/dynamicClient.ts create mode 100644 examples/bare-react-native-with-js-sdk-and-flow/index.js create mode 100644 examples/bare-react-native-with-js-sdk-and-flow/ios/.xcode.env create mode 100644 examples/bare-react-native-with-js-sdk-and-flow/ios/BareFlowMetaMaskDemo.xcodeproj/project.pbxproj create mode 100644 examples/bare-react-native-with-js-sdk-and-flow/ios/BareFlowMetaMaskDemo.xcodeproj/xcshareddata/xcschemes/BareFlowMetaMaskDemo.xcscheme create mode 100644 examples/bare-react-native-with-js-sdk-and-flow/ios/BareFlowMetaMaskDemo.xcworkspace/contents.xcworkspacedata create mode 100644 examples/bare-react-native-with-js-sdk-and-flow/ios/BareFlowMetaMaskDemo/AppDelegate.swift create mode 100644 examples/bare-react-native-with-js-sdk-and-flow/ios/BareFlowMetaMaskDemo/Images.xcassets/AppIcon.appiconset/Contents.json create mode 100644 examples/bare-react-native-with-js-sdk-and-flow/ios/BareFlowMetaMaskDemo/Images.xcassets/Contents.json create mode 100644 examples/bare-react-native-with-js-sdk-and-flow/ios/BareFlowMetaMaskDemo/Info.plist create mode 100644 examples/bare-react-native-with-js-sdk-and-flow/ios/BareFlowMetaMaskDemo/LaunchScreen.storyboard create mode 100644 examples/bare-react-native-with-js-sdk-and-flow/ios/BareFlowMetaMaskDemo/PrivacyInfo.xcprivacy create mode 100644 examples/bare-react-native-with-js-sdk-and-flow/ios/Podfile create mode 100644 examples/bare-react-native-with-js-sdk-and-flow/ios/Podfile.lock create mode 100644 examples/bare-react-native-with-js-sdk-and-flow/metro.config.js create mode 100644 examples/bare-react-native-with-js-sdk-and-flow/package.json create mode 100644 examples/bare-react-native-with-js-sdk-and-flow/patches/@react-native__codegen@0.81.4.patch create mode 100644 examples/bare-react-native-with-js-sdk-and-flow/pnpm-workspace.yaml create mode 100644 examples/bare-react-native-with-js-sdk-and-flow/polyfills.ts create mode 100644 examples/bare-react-native-with-js-sdk-and-flow/shims/ws.js create mode 100644 examples/bare-react-native-with-js-sdk-and-flow/src/App.tsx create mode 100644 examples/bare-react-native-with-js-sdk-and-flow/src/components/CopyButton.tsx create mode 100644 examples/bare-react-native-with-js-sdk-and-flow/src/components/ErrorText.tsx create mode 100644 examples/bare-react-native-with-js-sdk-and-flow/src/components/Header.tsx create mode 100644 examples/bare-react-native-with-js-sdk-and-flow/src/components/LinkButton.tsx create mode 100644 examples/bare-react-native-with-js-sdk-and-flow/src/components/ListRow.tsx create mode 100644 examples/bare-react-native-with-js-sdk-and-flow/src/components/PrimaryButton.tsx create mode 100644 examples/bare-react-native-with-js-sdk-and-flow/src/components/Screen.tsx create mode 100644 examples/bare-react-native-with-js-sdk-and-flow/src/components/SecondaryButton.tsx create mode 100644 examples/bare-react-native-with-js-sdk-and-flow/src/components/Skeleton.tsx create mode 100644 examples/bare-react-native-with-js-sdk-and-flow/src/components/icons.tsx create mode 100644 examples/bare-react-native-with-js-sdk-and-flow/src/consts/config.ts create mode 100644 examples/bare-react-native-with-js-sdk-and-flow/src/consts/flow.ts create mode 100644 examples/bare-react-native-with-js-sdk-and-flow/src/consts/theme.ts create mode 100644 examples/bare-react-native-with-js-sdk-and-flow/src/navigation.tsx create mode 100644 examples/bare-react-native-with-js-sdk-and-flow/src/routes/AccountRoute.tsx create mode 100644 examples/bare-react-native-with-js-sdk-and-flow/src/routes/ConnectWalletRoute.tsx create mode 100644 examples/bare-react-native-with-js-sdk-and-flow/src/routes/DepositRoute.tsx create mode 100644 examples/bare-react-native-with-js-sdk-and-flow/src/routes/FlowStatusRoute.tsx create mode 100644 examples/bare-react-native-with-js-sdk-and-flow/src/routes/FundGasRoute.tsx create mode 100644 examples/bare-react-native-with-js-sdk-and-flow/src/routes/HomeRoute.tsx create mode 100644 examples/bare-react-native-with-js-sdk-and-flow/src/routes/LoginRoute.tsx create mode 100644 examples/bare-react-native-with-js-sdk-and-flow/src/routes/OtpRoute.tsx create mode 100644 examples/bare-react-native-with-js-sdk-and-flow/src/routes/ProvisioningRoute.tsx create mode 100644 examples/bare-react-native-with-js-sdk-and-flow/src/routes/WithdrawAmountRoute.tsx create mode 100644 examples/bare-react-native-with-js-sdk-and-flow/src/routes/WithdrawRoute.tsx create mode 100644 examples/bare-react-native-with-js-sdk-and-flow/src/utils/connectCatalogWallet.ts create mode 100644 examples/bare-react-native-with-js-sdk-and-flow/src/utils/connectEphemeralWallet.ts create mode 100644 examples/bare-react-native-with-js-sdk-and-flow/src/utils/connectMetaMask.ts create mode 100644 examples/bare-react-native-with-js-sdk-and-flow/src/utils/createDepositFlow.ts create mode 100644 examples/bare-react-native-with-js-sdk-and-flow/src/utils/createWithdrawFlow.ts create mode 100644 examples/bare-react-native-with-js-sdk-and-flow/src/utils/getNativeBalance.ts create mode 100644 examples/bare-react-native-with-js-sdk-and-flow/src/utils/getUsdcBalance.ts create mode 100644 examples/bare-react-native-with-js-sdk-and-flow/src/utils/isValidAmount.ts create mode 100644 examples/bare-react-native-with-js-sdk-and-flow/src/utils/normalizeAmount.ts create mode 100644 examples/bare-react-native-with-js-sdk-and-flow/src/utils/resolveWalletAccounts.ts create mode 100644 examples/bare-react-native-with-js-sdk-and-flow/src/utils/shortAddress.ts create mode 100644 examples/bare-react-native-with-js-sdk-and-flow/src/utils/vault.ts create mode 100644 examples/bare-react-native-with-js-sdk-and-flow/src/views/AccountView.tsx create mode 100644 examples/bare-react-native-with-js-sdk-and-flow/src/views/AmountView.tsx create mode 100644 examples/bare-react-native-with-js-sdk-and-flow/src/views/FlowStatusView.tsx create mode 100644 examples/bare-react-native-with-js-sdk-and-flow/src/views/FundGasView.tsx create mode 100644 examples/bare-react-native-with-js-sdk-and-flow/src/views/HomeView.tsx create mode 100644 examples/bare-react-native-with-js-sdk-and-flow/src/views/LoginView.tsx create mode 100644 examples/bare-react-native-with-js-sdk-and-flow/src/views/OtpView.tsx create mode 100644 examples/bare-react-native-with-js-sdk-and-flow/src/views/ProvisioningView.tsx create mode 100644 examples/bare-react-native-with-js-sdk-and-flow/src/views/SplashView.tsx create mode 100644 examples/bare-react-native-with-js-sdk-and-flow/src/views/WalletPickerView.tsx create mode 100644 examples/bare-react-native-with-js-sdk-and-flow/tsconfig.json diff --git a/examples/bare-react-native-with-js-sdk-and-flow/.bundle/config b/examples/bare-react-native-with-js-sdk-and-flow/.bundle/config new file mode 100644 index 0000000..848943b --- /dev/null +++ b/examples/bare-react-native-with-js-sdk-and-flow/.bundle/config @@ -0,0 +1,2 @@ +BUNDLE_PATH: "vendor/bundle" +BUNDLE_FORCE_RUBY_PLATFORM: 1 diff --git a/examples/bare-react-native-with-js-sdk-and-flow/.env.example b/examples/bare-react-native-with-js-sdk-and-flow/.env.example new file mode 100644 index 0000000..48d6bcc --- /dev/null +++ b/examples/bare-react-native-with-js-sdk-and-flow/.env.example @@ -0,0 +1,23 @@ +# Required — your Dynamic environment ID. +# Get one at https://app.dynamic.xyz/dashboard/developer/api (use a Sandbox +# key while developing, never a Live/production key in a local .env file). +DYNAMIC_ENVIRONMENT_ID= + +# Required — a Dynamic API key with the `flow.write` scope +# (Dashboard → Developers → API Keys), used to call the Flow create +# endpoint directly from this app (see src/utils/createDepositFlow.ts and +# src/utils/createWithdrawFlow.ts). +# +# SANDBOX-ONLY. Dynamic's own reference implementation only ever calls the +# Flow create endpoint from a server, because it takes a real API secret — +# this demo calls it straight from the client instead, for simplicity, which +# means this key ends up inside the compiled app bundle at runtime (anyone +# with the .ipa/.apk can extract it). That's an acceptable tradeoff for a +# sandbox-only demo key with no real funds behind it, but NEVER put a +# production key here, and don't reuse this key for anything else. +DYNAMIC_API_KEY= + +# Optional — override the Dynamic client's API base URL. Leave empty to let +# the JS SDK use its own built-in default (production). +DYNAMIC_API_BASE_URL= + diff --git a/examples/bare-react-native-with-js-sdk-and-flow/.eslintignore b/examples/bare-react-native-with-js-sdk-and-flow/.eslintignore new file mode 100644 index 0000000..8e446f9 --- /dev/null +++ b/examples/bare-react-native-with-js-sdk-and-flow/.eslintignore @@ -0,0 +1,20 @@ +# ios/ and android/ hold native project files, not this app's JS/TS source +# -- `eslint .` (package.json's "lint" script) should never need to walk +# them. This became load-bearing (not just tidy) once ios/Podfile started +# forcing Hermes to build from source: ios/Pods/hermes-engine now contains +# Hermes's own GitHub checkout, including its full JS test suite (esprima +# test fixtures, flow-parser tests, etc.) -- real .js/.jsx files that `eslint +# .` will otherwise happily try to lint and can crash on (a JSX test +# fixture in hermes-engine/external/esprima/test_fixtures previously threw +# "node.name.name.toLowerCase is not a function" inside +# eslint-plugin-react-native, since those fixtures aren't real React Native +# code). Before the from-source Hermes change, ios/Pods only ever held +# prebuilt binaries and headers, so this never came up. +# +# Anchored to the repo root (leading `/`) rather than bare `ios/`/`android/` +# -- unanchored gitignore-style patterns match at any depth, so without the +# anchor, a future source folder literally named e.g. `src/ios/` would be +# silently skipped by ESLint too, with no warning. Root-only is what's +# actually intended here. +/ios/ +/android/ diff --git a/examples/bare-react-native-with-js-sdk-and-flow/.eslintrc.js b/examples/bare-react-native-with-js-sdk-and-flow/.eslintrc.js new file mode 100644 index 0000000..187894b --- /dev/null +++ b/examples/bare-react-native-with-js-sdk-and-flow/.eslintrc.js @@ -0,0 +1,4 @@ +module.exports = { + root: true, + extends: '@react-native', +}; diff --git a/examples/bare-react-native-with-js-sdk-and-flow/.gitignore b/examples/bare-react-native-with-js-sdk-and-flow/.gitignore new file mode 100644 index 0000000..4793cfd --- /dev/null +++ b/examples/bare-react-native-with-js-sdk-and-flow/.gitignore @@ -0,0 +1,81 @@ +# OSX +# +.DS_Store + +# Xcode +# +build/ +*.pbxuser +!default.pbxuser +*.mode1v3 +!default.mode1v3 +*.mode2v3 +!default.mode2v3 +*.perspectivev3 +!default.perspectivev3 +xcuserdata +*.xccheckout +*.moved-aside +DerivedData +*.hmap +*.ipa +*.xcuserstate +**/.xcode.env.local + +# Android/IntelliJ +# +build/ +.idea +.gradle +local.properties +*.iml +*.hprof +.cxx/ +*.keystore +!debug.keystore +.kotlin/ + +# node.js +# +node_modules/ +npm-debug.log +yarn-error.log + +# fastlane +# +# It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the +# screenshots whenever they are needed. +# For more information about the recommended setup visit: +# https://docs.fastlane.tools/best-practices/source-control/ + +**/fastlane/report.xml +**/fastlane/Preview.html +**/fastlane/screenshots +**/fastlane/test_output + +# Bundle artifact +*.jsbundle + +# Ruby / CocoaPods +**/Pods/ +/vendor/bundle/ + +# Temporary files created by Metro to check the health of the file watcher +.metro-health-check* + +# testing +/coverage + +# Environment variables — never commit real secrets, only .env.example +.env +.env.local + +# Yarn +.yarn/* +!.yarn/patches +!.yarn/plugins +!.yarn/releases +!.yarn/sdks +!.yarn/versions + +pnpm-lock.yaml diff --git a/examples/bare-react-native-with-js-sdk-and-flow/.prettierrc.js b/examples/bare-react-native-with-js-sdk-and-flow/.prettierrc.js new file mode 100644 index 0000000..06860c8 --- /dev/null +++ b/examples/bare-react-native-with-js-sdk-and-flow/.prettierrc.js @@ -0,0 +1,5 @@ +module.exports = { + arrowParens: 'avoid', + singleQuote: true, + trailingComma: 'all', +}; diff --git a/examples/bare-react-native-with-js-sdk-and-flow/.watchmanconfig b/examples/bare-react-native-with-js-sdk-and-flow/.watchmanconfig new file mode 100644 index 0000000..0967ef4 --- /dev/null +++ b/examples/bare-react-native-with-js-sdk-and-flow/.watchmanconfig @@ -0,0 +1 @@ +{} diff --git a/examples/bare-react-native-with-js-sdk-and-flow/Gemfile b/examples/bare-react-native-with-js-sdk-and-flow/Gemfile new file mode 100644 index 0000000..cc897bb --- /dev/null +++ b/examples/bare-react-native-with-js-sdk-and-flow/Gemfile @@ -0,0 +1,22 @@ +source 'https://rubygems.org' + +# You may use http://rbenv.org/ or https://rvm.io/ to install and use this version +ruby ">= 2.6.10" + +# Exclude problematic versions of cocoapods and activesupport that causes build failures. +gem 'cocoapods', '>= 1.13', '!= 1.15.0', '!= 1.15.1' +gem 'activesupport', '>= 6.1.7.5', '!= 7.1.0' +gem 'xcodeproj', '< 1.26.0' +gem 'concurrent-ruby', '< 1.3.4' + +# Ruby 3.4.0 has removed some libraries from the standard library. +gem 'bigdecimal' +gem 'logger' +gem 'benchmark' +gem 'mutex_m' + +# Ruby 3.4/4.0 also dropped these two — CFPropertyList (a CocoaPods +# dependency) still calls Kconv, and molinillo (also a CocoaPods dependency) +# still calls tsort, both of which used to ship in the standard library. +gem 'nkf' +gem 'tsort' diff --git a/examples/bare-react-native-with-js-sdk-and-flow/Gemfile.lock b/examples/bare-react-native-with-js-sdk-and-flow/Gemfile.lock new file mode 100644 index 0000000..40db245 --- /dev/null +++ b/examples/bare-react-native-with-js-sdk-and-flow/Gemfile.lock @@ -0,0 +1,173 @@ +GEM + remote: https://rubygems.org/ + specs: + CFPropertyList (3.0.8) + activesupport (7.2.3.2) + base64 + benchmark (>= 0.3) + bigdecimal + concurrent-ruby (~> 1.0, >= 1.3.1) + connection_pool (>= 2.2.5) + drb + i18n (>= 1.6, < 2) + logger (>= 1.4.2) + minitest (>= 5.1, < 6) + securerandom (>= 0.3) + tzinfo (~> 2.0, >= 2.0.5) + addressable (2.9.0) + public_suffix (>= 2.0.2, < 8.0) + algoliasearch (1.27.5) + httpclient (~> 2.8, >= 2.8.3) + json (>= 1.5.1) + atomos (0.1.3) + base64 (0.3.0) + benchmark (0.5.0) + bigdecimal (4.1.2) + claide (1.1.0) + cocoapods (1.15.2) + addressable (~> 2.8) + claide (>= 1.0.2, < 2.0) + cocoapods-core (= 1.15.2) + cocoapods-deintegrate (>= 1.0.3, < 2.0) + cocoapods-downloader (>= 2.1, < 3.0) + cocoapods-plugins (>= 1.0.0, < 2.0) + cocoapods-search (>= 1.0.0, < 2.0) + cocoapods-trunk (>= 1.6.0, < 2.0) + cocoapods-try (>= 1.1.0, < 2.0) + colored2 (~> 3.1) + escape (~> 0.0.4) + fourflusher (>= 2.3.0, < 3.0) + gh_inspector (~> 1.0) + molinillo (~> 0.8.0) + nap (~> 1.0) + ruby-macho (>= 2.3.0, < 3.0) + xcodeproj (>= 1.23.0, < 2.0) + cocoapods-core (1.15.2) + activesupport (>= 5.0, < 8) + addressable (~> 2.8) + algoliasearch (~> 1.0) + concurrent-ruby (~> 1.1) + fuzzy_match (~> 2.0.4) + nap (~> 1.0) + netrc (~> 0.11) + public_suffix (~> 4.0) + typhoeus (~> 1.0) + cocoapods-deintegrate (1.0.5) + cocoapods-downloader (2.1) + cocoapods-plugins (1.0.0) + nap + cocoapods-search (1.0.1) + cocoapods-trunk (1.6.0) + nap (>= 0.8, < 2.0) + netrc (~> 0.11) + cocoapods-try (1.2.0) + colored2 (3.1.2) + concurrent-ruby (1.3.3) + connection_pool (3.0.2) + drb (2.2.3) + escape (0.0.4) + ethon (0.18.0) + ffi (>= 1.15.0) + logger + ffi (1.17.4) + fourflusher (2.3.1) + fuzzy_match (2.0.4) + gh_inspector (1.1.3) + httpclient (2.9.0) + mutex_m + i18n (1.15.2) + concurrent-ruby (~> 1.0) + json (2.21.2) + logger (1.7.0) + minitest (5.27.0) + molinillo (0.8.0) + mutex_m (0.3.0) + nanaimo (0.3.0) + nap (1.1.0) + netrc (0.11.0) + nkf (0.3.0) + public_suffix (4.0.7) + rexml (3.4.4) + ruby-macho (2.5.1) + securerandom (0.4.1) + tsort (0.2.0) + typhoeus (1.6.0) + ethon (>= 0.18.0) + tzinfo (2.0.6) + concurrent-ruby (~> 1.0) + xcodeproj (1.25.1) + CFPropertyList (>= 2.3.3, < 4.0) + atomos (~> 0.1.3) + claide (>= 1.0.2, < 2.0) + colored2 (~> 3.1) + nanaimo (~> 0.3.0) + rexml (>= 3.3.6, < 4.0) + +PLATFORMS + ruby + +DEPENDENCIES + activesupport (>= 6.1.7.5, != 7.1.0) + benchmark + bigdecimal + cocoapods (>= 1.13, != 1.15.1, != 1.15.0) + concurrent-ruby (< 1.3.4) + logger + mutex_m + nkf + tsort + xcodeproj (< 1.26.0) + +CHECKSUMS + CFPropertyList (3.0.8) sha256=2c99d0d980536d3d7ab252f7bd59ac8be50fbdd1ff487c98c949bb66bb114261 + activesupport (7.2.3.2) sha256=ddc90d11dd88086d78ace03407fe3c2a3f5c8853c3c3046313db5ed823ef3312 + addressable (2.9.0) sha256=7fdf6ac3660f7f4e867a0838be3f6cf722ace541dd97767fa42bc6cfa980c7af + algoliasearch (1.27.5) sha256=26c1cddf3c2ec4bd60c148389e42702c98fdac862881dc6b07a4c0b89ffec853 + atomos (0.1.3) sha256=7d43b22f2454a36bace5532d30785b06de3711399cb1c6bf932573eda536789f + base64 (0.3.0) sha256=27337aeabad6ffae05c265c450490628ef3ebd4b67be58257393227588f5a97b + benchmark (0.5.0) sha256=465df122341aedcb81a2a24b4d3bd19b6c67c1530713fd533f3ff034e419236c + bigdecimal (4.1.2) sha256=53d217666027eab4280346fba98e7d5b66baaae1b9c3c1c0ffe89d48188a3fbd + claide (1.1.0) sha256=6d3c5c089dde904d96aa30e73306d0d4bd444b1accb9b3125ce14a3c0183f82e + cocoapods (1.15.2) sha256=f0f5153de8d028d133b96f423e04f37fb97a1da0d11dda581a9f46c0cba4090a + cocoapods-core (1.15.2) sha256=322650d97fe1ad4c0831a09669764b888bd91c6d79d0f6bb07281a17667a2136 + cocoapods-deintegrate (1.0.5) sha256=517c2a448ef563afe99b6e7668704c27f5de9e02715a88ee9de6974dc1b3f6a2 + cocoapods-downloader (2.1) sha256=bb6ebe1b3966dc4055de54f7a28b773485ac724fdf575d9bee2212d235e7b6d1 + cocoapods-plugins (1.0.0) sha256=725d17ce90b52f862e73476623fd91441b4430b742d8a071000831efb440ca9a + cocoapods-search (1.0.1) sha256=1b133b0e6719ed439bd840e84a1828cca46425ab73a11eff5e096c3b2df05589 + cocoapods-trunk (1.6.0) sha256=5f5bda8c172afead48fa2d43a718cf534b1313c367ba1194cebdeb9bfee9ed31 + cocoapods-try (1.2.0) sha256=145b946c6e7747ed0301d975165157951153d27469e6b2763c83e25c84b9defe + colored2 (3.1.2) sha256=b13c2bd7eeae2cf7356a62501d398e72fde78780bd26aec6a979578293c28b4a + concurrent-ruby (1.3.3) sha256=4f9cd28965c4dcf83ffd3ea7304f9323277be8525819cb18a3b61edcb56a7c6a + connection_pool (3.0.2) sha256=33fff5ba71a12d2aa26cb72b1db8bba2a1a01823559fb01d29eb74c286e62e0a + drb (2.2.3) sha256=0b00d6fdb50995fe4a45dea13663493c841112e4068656854646f418fda13373 + escape (0.0.4) sha256=e49f44ae2b4f47c6a3abd544ae77fe4157802794e32f19b8e773cbc4dcec4169 + ethon (0.18.0) sha256=b598afc9f30448cb068b850714b7d6948e941476095d04f90a4ac65b8d6efcb2 + ffi (1.17.4) sha256=bcd1642e06f0d16fc9e09ac6d49c3a7298b9789bcb58127302f934e437d60acf + fourflusher (2.3.1) sha256=1b3de61c7c791b6a4e64f31e3719eb25203d151746bb519a0292bff1065ccaa9 + fuzzy_match (2.0.4) sha256=b5de4f95816589c5b5c3ad13770c0af539b75131c158135b3f3bbba75d0cfca5 + gh_inspector (1.1.3) sha256=04cca7171b87164e053aa43147971d3b7f500fcb58177698886b48a9fc4a1939 + httpclient (2.9.0) sha256=4b645958e494b2f86c2f8a2f304c959baa273a310e77a2931ddb986d83e498c8 + i18n (1.15.2) sha256=00f9eb62412fe593b2a65a97daa75300d37abb8f7202ec748e94b6d46a9dd1b5 + json (2.21.2) sha256=1f1d3b7cf2b3ba1a69beca0bb6db13d5438b80bff3cd54cdaaa620b9b07c1c6a + logger (1.7.0) sha256=196edec7cc44b66cfb40f9755ce11b392f21f7967696af15d274dde7edff0203 + minitest (5.27.0) sha256=2d3b17f8a36fe7801c1adcffdbc38233b938eb0b4966e97a6739055a45fa77d5 + molinillo (0.8.0) sha256=efbff2716324e2a30bccd3eba1ff3a735f4d5d53ffddbc6a2f32c0ca9433045d + mutex_m (0.3.0) sha256=cfcb04ac16b69c4813777022fdceda24e9f798e48092a2b817eb4c0a782b0751 + nanaimo (0.3.0) sha256=aaaedc60497070b864a7e220f7c4b4cad3a0daddda2c30055ba8dae306342376 + nap (1.1.0) sha256=949691660f9d041d75be611bb2a8d2fd559c467537deac241f4097d9b5eea576 + netrc (0.11.0) sha256=de1ce33da8c99ab1d97871726cba75151113f117146becbe45aa85cb3dabee3f + nkf (0.3.0) sha256=357a8dbeba38b727b75930f665146546076a394a1c243faf634ff176e3588895 + public_suffix (4.0.7) sha256=8be161e2421f8d45b0098c042c06486789731ea93dc3a896d30554ee38b573b8 + rexml (3.4.4) sha256=19e0a2c3425dfbf2d4fc1189747bdb2f849b6c5e74180401b15734bc97b5d142 + ruby-macho (2.5.1) sha256=9075e52e0f9270b552a90b24fcc6219ad149b0d15eae1bc364ecd0ac8984f5c9 + securerandom (0.4.1) sha256=cc5193d414a4341b6e225f0cb4446aceca8e50d5e1888743fac16987638ea0b1 + tsort (0.2.0) sha256=9650a793f6859a43b6641671278f79cfead60ac714148aabe4e3f0060480089f + typhoeus (1.6.0) sha256=bacc41c23e379547e29801dc235cd1699b70b955a1ba3d32b2b877aa844c331d + tzinfo (2.0.6) sha256=8daf828cc77bcf7d63b0e3bdb6caa47e2272dcfaf4fbfe46f8c3a9df087a829b + xcodeproj (1.25.1) sha256=9a2310dccf6d717076e86f602b17c640046b6f1dfe64480044596f6f2f13dc84 + +RUBY VERSION + ruby 4.0.6 + +BUNDLED WITH + 4.0.16 diff --git a/examples/bare-react-native-with-js-sdk-and-flow/README.md b/examples/bare-react-native-with-js-sdk-and-flow/README.md new file mode 100644 index 0000000..b6b3005 --- /dev/null +++ b/examples/bare-react-native-with-js-sdk-and-flow/README.md @@ -0,0 +1,242 @@ +# bare-react-native-with-js-sdk-and-flow + +A **bare React Native** (no Expo) example that logs a user in with Dynamic's +**email one-time-passcode** flow, provisions a Dynamic **embedded EVM wallet +as a "vault"**, and moves USDC on Base between an external wallet and the +vault in either direction using a real +[Fireblocks Flow](https://www.dynamic.xyz/docs/overview/fireblocks-flow-api): +create → attach source → quote → submit → (sign, either in the external +wallet app or silently via the embedded wallet) → display settlement status. + +Deposit and Withdraw each connect an external wallet ad hoc, per operation — +MetaMask or a curated WalletConnect-catalog wallet, picked fresh every time +and never persisted or signature-verified. Both directions settle **real +USDC on Base mainnet** — no testnet fallback — capped at $5 per transfer +(`src/consts/flow.ts`'s `MAX_AMOUNT_USD`) as a guardrail against a typo +turning into an expensive mistake. + +## Project structure + +| Folder | Responsible for | +| -------------------- | ------------------------------------------------------------------------------------------------------------------- | +| `src/components/` | Small, dumb presentational pieces (buttons, headers, icons) with no SDK/business logic. | +| `src/views/` | Dumb, prop-driven screens composed from components — no SDK or navigation calls, just render what they're given. | +| `src/routes/` | The smart layer: one file per screen, owns SDK/react-query hooks and navigation, feeds a view's props. | +| `src/utils/` | Standalone helper functions (Flow API calls, wallet connect, small pure helpers) — one top-level function per file. | +| `src/consts/` | Fixed config and constants (chain/token addresses, theme tokens, demo amount caps). | +| `src/navigation.tsx` | The React Navigation stack + the one-time cold-boot session check that picks the initial screen. | +| `src/App.tsx` | Top-level providers only (safe area, react-query, Dynamic) wrapping ``. | + +## Flow & wallet connections + +The files below do the actual work of talking to the Flow API and +connecting external wallets — start here to see how it's wired: + +- [`src/utils/createDepositFlow.ts`](./src/utils/createDepositFlow.ts) — hand-rolled REST call creating a deposit flow: external wallet pays ETH, vault settles in USDC (Flow's create step is server-only, no client SDK function exists for it). +- [`src/utils/createWithdrawFlow.ts`](./src/utils/createWithdrawFlow.ts) — same, but for a withdrawal: vault pays USDC, destination wallet settles in native ETH. +- [`src/routes/DepositRoute.tsx`](./src/routes/DepositRoute.tsx) — create → attach → quote → submit, external wallet → vault, external wallet signs. +- [`src/routes/WithdrawAmountRoute.tsx`](./src/routes/WithdrawAmountRoute.tsx) — same sequence, vault → external wallet, the vault signs directly. +- [`src/routes/FundGasRoute.tsx`](./src/routes/FundGasRoute.tsx) — funding the vault's own withdrawal gas: balance preflight, network switch, `transferAmount`/`confirmTransaction`. +- [`src/routes/FlowStatusRoute.tsx`](./src/routes/FlowStatusRoute.tsx) — polls a flow to a terminal state and derives its step-by-step status. +- [`src/utils/connectMetaMask.ts`](./src/utils/connectMetaMask.ts) — ephemeral MetaMask connect via Dynamic's own MetaMask SDK wrapper. +- [`src/utils/connectCatalogWallet.ts`](./src/utils/connectCatalogWallet.ts) — ephemeral connect to any wallet in Dynamic's WalletConnect catalog (Trust Wallet, Rainbow, …). +- [`src/utils/getNativeBalance.ts`](./src/utils/getNativeBalance.ts) — raw ETH balance read used to gate Withdraw on the vault having enough gas. + +## Prerequisites + +- Node 20+ +- Xcode + CocoaPods (iOS) and/or Android Studio (Android) +- pnpm (`npm i -g pnpm`) — this repo prefers pnpm, though the RN CLI itself + defaults to npm +- A [Dynamic](https://app.dynamic.xyz) account with a **Sandbox** environment + ID (Settings → Developers → API Keys) — never use a Live/production key + for local development + +## Requirements + +- **EVM embedded wallets (WaaS) must be enabled for this environment** in + the Dynamic dashboard, or `ProvisioningRoute.tsx`'s + `createWaasWalletAccounts` call will fail (surfaced inline as "Embedded + wallets aren't enabled for this Dynamic environment yet…" — + `NoWalletProviderFoundError`/`NotWaasWalletProviderError`). This is a + separate toggle from the Sandbox environment ID/API key setup above; + check your project's embedded-wallet settings before running the vault + flow end to end. +- **Email OTP must be enabled for this environment** in the Dynamic + dashboard (Settings → Login methods) — `LoginRoute.tsx`'s + `sendEmailOTP` call fails otherwise. + +## Setup + +```bash +cd examples/bare-react-native-with-js-sdk-and-flow + +# 1. Install dependencies +pnpm install + +# 2. Copy and fill in env vars +cp .env.example .env +# Edit .env + +# 3. iOS: install native pods +cd ios && bundle install && bundle exec pod install && cd .. +``` + +## Running a Release build on a physical device + +`pnpm ios` (step 4 above) launches a **Debug** build on the Simulator — +fine for most of the app, but neither MetaMask nor Trust Wallet can be +installed on the Simulator (see Troubleshooting), so exercising either +connect button for real means a **Release** build on an actual +iPhone/iPad, which means dealing with code signing. + +`ios/BareFlowMetaMaskDemo.xcodeproj/project.pbxproj` deliberately ships +with **no `DEVELOPMENT_TEAM` set**. It's a tracked, committed file shared +by everyone who clones this example — baking in one person's or company's +Apple Developer Team ID as a "default" would leak that identifier into a +public repo's git history for no real benefit (every other clone would +just have to overwrite it with their own anyway), and it's easy to commit +by accident the moment anyone picks a team from Xcode's Signing & +Capabilities UI, since that UI writes straight into this same tracked +file. Set your team at build time instead, via the React Native CLI's +`--extra-params`, which passes through to `xcodebuild` without writing +anything to disk: + +```bash +# Find your team ID (the 10-char code in the OU field of any of your valid +# signing certs): +security find-certificate -a -c "Apple Development" -p \ + | openssl x509 -noout -subject + +# Find your device's UDID in the *classic* format react-native-cli expects — +# NOT the CoreDevice identifier `xcrun devicectl list devices` prints; those +# are two different ID formats for the same physical device: +xcrun xctrace list devices + +# Build, sign, and install a Release build straight onto the device: +npx react-native run-ios \ + --mode Release \ + --udid \ + --extra-params "DEVELOPMENT_TEAM= CODE_SIGN_STYLE=Automatic" +``` + +> First launch with a fresh signing team/profile may prompt "Untrusted +> Developer" on the device — trust it under **Settings → General → VPN & +> Device Management** before the app will open. + +> If Xcode shows a red "Failed to load container for document" error when +> you open the workspace, that's unrelated to signing — running +> `pod install` from a sandboxed/scripted shell can leave +> `project.pbxproj`/`Pods/Pods.xcodeproj/project.pbxproj` with `600` +> permissions instead of the normal `644`, which Xcode's own helper +> processes can't read. `chmod 644` both files and reopen the workspace. + +If you do open the workspace in Xcode and pick a team from its Signing & +Capabilities UI instead of using `--extra-params`, check `git status`/`git +diff` in `ios/` before committing anything else — that UI writes +`DEVELOPMENT_TEAM` directly into the tracked `project.pbxproj`, and +`git checkout -- ios/BareFlowMetaMaskDemo.xcodeproj/project.pbxproj` reverts +it if you don't want it in history. + +### Android + +Same reasoning applies on Android: `pnpm android` runs a **Debug** build, +but MetaMask/Trust Wallet connect flows need a **Release** build on a +physical device. Unlike iOS, this needs no code-signing setup — a debug +keystore is enough to install locally — so it's just: + +```bash +# Find your device's ID (the value under "List of devices attached"): +adb devices + +# Build and install a Release build straight onto the device: +npx react-native run-android --device --mode release +``` + +> Make sure USB debugging is enabled on the device (**Settings → Developer +> options → USB debugging**) and that you've accepted the "Allow USB +> debugging" prompt on the device itself, or `adb devices` will list it as +> `unauthorized` instead of showing an ID you can use. + +## Environment variables + +| Variable | Required | Description | +| ------------------------ | -------- | ---------------------------------------------------------------------------------------------------------------------------- | +| `DYNAMIC_ENVIRONMENT_ID` | Yes | Your Dynamic environment ID. Use a Sandbox key. | +| `DYNAMIC_API_BASE_URL` | No | Overrides the SDK's API base URL. Leave empty to use the SDK's built-in production default. | +| `DYNAMIC_API_KEY` | Yes | Sandbox-only Dynamic API key (`flow.write` scope), used directly from the client for simplicity. **Never a production key.** | + +Bare React Native has no Expo-style `EXPO_PUBLIC_*` build-time substitution, +so env vars are inlined into the bundle via +[`babel-plugin-transform-inline-environment-variables`](https://www.npmjs.com/package/babel-plugin-transform-inline-environment-variables) +(loaded from `.env` via `dotenv` in `babel.config.js`) — see `src/consts/config.ts` +for where they're read. Missing required variables throw at startup instead +of failing silently. + +> **Heads up:** because `DYNAMIC_API_KEY` is called directly from the app, +> it's visible in plaintext in any request-inspector tooling (React Native's +> dev menu network inspector, Flipper, etc.) while the app is running in +> debug mode. Don't screen-record or screenshot that tooling while your key +> is loaded, and treat a sandbox key as "rotate if you suspect it leaked." + +**No env var for WalletConnect.** Unlike MetaMask, `connectWithWalletConnectEvm()` +(used for Trust Wallet/Rainbow) needs a WalletConnect Project ID to work at +all — but it's not app-supplied. The SDK reads it from your Dynamic +project's own settings (Dashboard → project settings → WalletConnect), +fetched at runtime via the client, not from `.env`. If it's missing there, +connecting throws a clear `Please configure a project ID for WalletConnect +in dashboard` error instead of a confusing connection failure. + +## Why MetaMask connection needs no Expo + +Dynamic's [bare React Native setup guide](https://www.dynamic.xyz/docs/javascript/react-native/bare-react-native) +covers exactly this: a handful of manual polyfills (`react-native-get-random-values`, +a `Buffer` global, a `crypto.randomUUID` shim, and a minimal `window.location` +shim for the embedded-wallet WebView — see `polyfills.ts`) and two Babel +plugins (`@babel/plugin-transform-export-namespace-from`, +`@babel/plugin-transform-class-static-block` — the SDK ships modern syntax +the stock RN Babel preset doesn't transform on its own). None of it is +Expo-specific; this example intentionally scaffolds with the RN CLI directly +to keep that dependency surface visible instead of hidden behind Expo +tooling. + +Trust Wallet/Rainbow's connection needs real RN-specific setup beyond the +above, per [Dynamic's WalletConnect integration guide](https://www.dynamic.xyz/docs/javascript/reference/wallets/walletconnect-integration#react-native): +`@walletconnect/react-native-compat` (imported as the very first line of +`polyfills.ts`, before even the random-values shim — it provides +crypto/encoding support Hermes lacks that WalletConnect needs unconditionally +at startup) and `@react-native-community/netinfo` (a peer dependency, so +WalletConnect sessions reconnect reliably after a network change). Android +also needs a JitPack Maven repository for one of the compat shim's native +dependencies (`android/settings.gradle`'s `dependencyResolutionManagement` +block). Without the compat shim, `addWalletConnectEvmExtension` crashes on +every app launch with `Cannot read property 'prototype' of undefined`. + +`addWalletConnectEvmExtension(dynamicClient)` (`dynamicClient.ts`) is called +once at startup, mirroring `addEvmExtension`, primarily so an +already-paired WalletConnect session survives an app relaunch. +`src/utils/connectCatalogWallet.ts` resolves a WalletConnect catalog +wallet's deep link, falling back to the raw pairing URI if the catalog +lookup ever fails. + +## Troubleshooting + +- **`pod install` fails with `cannot load such file -- kconv` (from CFPropertyList) or a `tsort` load error (from molinillo), or a spurious `pathname contains null byte` CocoaPods crash.** Ruby 3.4+ dropped `kconv` and `tsort` from the standard library; CocoaPods' own dependencies (`CFPropertyList`, `molinillo`) still call into them. Already worked around in the `Gemfile` (`gem 'nkf'`, `gem 'tsort'`); if you still hit this, run `bundle install` again and confirm your Ruby version isn't newer than what's been tested here. +- **iOS build fails inside `hermes-engine` with `make: \*** No rule to make target 'libhermes'`, or crashes on a physical Release build with `EXC_BAD_ACCESS`/`SIGSEGV`inside Hermes's debugger/inspector setup.** This project's`ios/Podfile` forces Hermes to build from source for everyone (`ENV['RCT_BUILD_HERMES_FROM_SOURCE'] ||= 'true'`) to avoid a C++ ABI mismatch between React Native's prebuilt Hermes binary and a newer Xcode. If you still hit a Hermes build failure, check GitHub connectivity — building from source clones Hermes from `https://github.com/facebook/hermes.git`. +- **A truly from-scratch `pnpm install` + `pod install` causes a native module to fail compiling with `no type or protocol named 'NativeSpec'`.** An upstream `@react-native/codegen` bug: its file-discovery uses `fs.lstatSync`, which doesn't follow symlinks, and every pnpm-managed `node_modules/` entry is a symlink — Codegen silently skips scanning pnpm-linked packages. Patched via `pnpm patch` (`patches/@react-native__codegen@0.81.4.patch`); applies automatically on `pnpm install`. If you bump `react-native`/`@react-native/codegen`, see the patch file's own header for how to regenerate it. +- **iOS build fails with `call to consteval function ... is not a constant expression` in `fmt`.** Already worked around in `ios/Podfile`'s `post_install` for Xcode 26+; if you still see it, delete `ios/Pods` and re-run `pod install`. +- **`pod install` fails with an `Invalid \`Podfile\``error wrapping a Codegen error about`setToolbarMenuElementOptions`.** `react-native-screens` is intentionally pinned below 4.25.0 (currently `4.24.0`) in `package.json` — 4.25.0+ ships an experimental Android-only native component whose codegen this pinned React Native version (0.81.4) can't parse. This app doesn't use that experimental API, so pinning loses nothing. +- **Metro fails to resolve `stream` from inside `ws`, or a Babel error like `Export namespace should be first transformed by...`.** Delete Metro's cache (`npx react-native start --reset-cache`) and confirm `metro.config.js`'s `resolver.resolveRequest` override and both `@babel/plugin-transform-*` plugins in `babel.config.js` are present. +- **Tapping "MetaMask" on the Connect Wallet screen (`ConnectWalletRoute.tsx`) shows a red screen: `Requiring unknown module ""`.** A currently-unresolved Metro dev-server issue deep in `@metamask/mobile-wallet-protocol-dapp-client`'s dependency chain — reproduces even after a full cache reset. Doesn't affect the app otherwise; a production/release bundle may not be affected (untested here). Needs a physical device with MetaMask installed either way (MetaMask can't be installed on the iOS Simulator). +- **Tapping "Connect with Trust Wallet"/"Rainbow" shows `Unable to open URL: ...`.** Expected on the iOS Simulator (or any device without the wallet app installed) — the deep-link resolution itself worked, `Linking.openURL` just has nothing installed to hand it to. Needs a physical device with the wallet installed to test past this point. +- **A withdrawal fails with an error mentioning balance, gas, or an insufficient-funds message.** The connected wallet needs enough native ETH on **Base mainnet** to cover both the withdrawal amount and gas — `submitFlowTransaction` checks this before submitting and surfaces a clear error rather than partially submitting. +- **Known limitation: no flow persistence.** `FlowStatusRoute.tsx`'s active `flowId` lives in plain React Navigation route params — there is no AsyncStorage record and no on-launch resume. If the app is killed while a deposit/withdraw is mid-flight, relaunching it loses track of that flow entirely — the underlying Flow keeps executing server-side regardless. +- **Known limitation: an app process killed mid wallet-approval loses the in-progress Deposit/Withdraw step.** The connected external wallet for that operation is held in-memory only, never persisted by design. Relaunching returns to Home; the operation must be restarted from scratch. + +## Learn more + +- [Dynamic JS SDK overview](https://www.dynamic.xyz/docs/javascript/overview) +- [React Native quickstart](https://www.dynamic.xyz/docs/javascript/reference/react-native-quickstart) +- [Bare React Native setup](https://www.dynamic.xyz/docs/javascript/react-native/bare-react-native) +- [Fireblocks Flow API](https://www.dynamic.xyz/docs/overview/fireblocks-flow-api) +- [Flow getting started (JS)](https://www.dynamic.xyz/docs/javascript/reference/flow-getting-started) diff --git a/examples/bare-react-native-with-js-sdk-and-flow/android/app/build.gradle b/examples/bare-react-native-with-js-sdk-and-flow/android/app/build.gradle new file mode 100644 index 0000000..b296e98 --- /dev/null +++ b/examples/bare-react-native-with-js-sdk-and-flow/android/app/build.gradle @@ -0,0 +1,119 @@ +apply plugin: "com.android.application" +apply plugin: "org.jetbrains.kotlin.android" +apply plugin: "com.facebook.react" + +/** + * This is the configuration block to customize your React Native Android app. + * By default you don't need to apply any configuration, just uncomment the lines you need. + */ +react { + /* Folders */ + // The root of your project, i.e. where "package.json" lives. Default is '../..' + // root = file("../../") + // The folder where the react-native NPM package is. Default is ../../node_modules/react-native + // reactNativeDir = file("../../node_modules/react-native") + // The folder where the react-native Codegen package is. Default is ../../node_modules/@react-native/codegen + // codegenDir = file("../../node_modules/@react-native/codegen") + // The cli.js file which is the React Native CLI entrypoint. Default is ../../node_modules/react-native/cli.js + // cliFile = file("../../node_modules/react-native/cli.js") + + /* Variants */ + // The list of variants to that are debuggable. For those we're going to + // skip the bundling of the JS bundle and the assets. By default is just 'debug'. + // If you add flavors like lite, prod, etc. you'll have to list your debuggableVariants. + // debuggableVariants = ["liteDebug", "prodDebug"] + + /* Bundling */ + // A list containing the node command and its flags. Default is just 'node'. + // nodeExecutableAndArgs = ["node"] + // + // The command to run when bundling. By default is 'bundle' + // bundleCommand = "ram-bundle" + // + // The path to the CLI configuration file. Default is empty. + // bundleConfig = file(../rn-cli.config.js) + // + // The name of the generated asset file containing your JS bundle + // bundleAssetName = "MyApplication.android.bundle" + // + // The entry file for bundle generation. Default is 'index.android.js' or 'index.js' + // entryFile = file("../js/MyApplication.android.js") + // + // A list of extra flags to pass to the 'bundle' commands. + // See https://github.com/react-native-community/cli/blob/main/docs/commands.md#bundle + // extraPackagerArgs = [] + + /* Hermes Commands */ + // The hermes compiler command to run. By default it is 'hermesc' + // hermesCommand = "$rootDir/my-custom-hermesc/bin/hermesc" + // + // The list of flags to pass to the Hermes compiler. By default is "-O", "-output-source-map" + // hermesFlags = ["-O", "-output-source-map"] + + /* Autolinking */ + autolinkLibrariesWithApp() +} + +/** + * Set this to true to Run Proguard on Release builds to minify the Java bytecode. + */ +def enableProguardInReleaseBuilds = false + +/** + * The preferred build flavor of JavaScriptCore (JSC) + * + * For example, to use the international variant, you can use: + * `def jscFlavor = io.github.react-native-community:jsc-android-intl:2026004.+` + * + * The international variant includes ICU i18n library and necessary data + * allowing to use e.g. `Date.toLocaleString` and `String.localeCompare` that + * give correct results when using with locales other than en-US. Note that + * this variant is about 6MiB larger per architecture than default. + */ +def jscFlavor = 'io.github.react-native-community:jsc-android:2026004.+' + +android { + ndkVersion rootProject.ext.ndkVersion + buildToolsVersion rootProject.ext.buildToolsVersion + compileSdk rootProject.ext.compileSdkVersion + + namespace "com.dynamiclabs.examples.bareflowmetamaskdemo" + defaultConfig { + applicationId "com.dynamiclabs.examples.bareflowmetamaskdemo" + minSdkVersion rootProject.ext.minSdkVersion + targetSdkVersion rootProject.ext.targetSdkVersion + versionCode 1 + versionName "1.0" + } + signingConfigs { + debug { + storeFile file('debug.keystore') + storePassword 'android' + keyAlias 'androiddebugkey' + keyPassword 'android' + } + } + buildTypes { + debug { + signingConfig signingConfigs.debug + } + release { + // Caution! In production, you need to generate your own keystore file. + // see https://reactnative.dev/docs/signed-apk-android. + signingConfig signingConfigs.debug + minifyEnabled enableProguardInReleaseBuilds + proguardFiles getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro" + } + } +} + +dependencies { + // The version of react-native is set by the React Native Gradle Plugin + implementation("com.facebook.react:react-android") + + if (hermesEnabled.toBoolean()) { + implementation("com.facebook.react:hermes-android") + } else { + implementation jscFlavor + } +} diff --git a/examples/bare-react-native-with-js-sdk-and-flow/android/app/debug.keystore b/examples/bare-react-native-with-js-sdk-and-flow/android/app/debug.keystore new file mode 100644 index 0000000000000000000000000000000000000000..364e105ed39fbfd62001429a68140672b06ec0de GIT binary patch literal 2257 zcmchYXEfYt8;7T1^dLH$VOTZ%2NOdOH5j5LYLtZ0q7x-V8_6gU5)#7dkq{HTmsfNq zB3ZqcAxeY^G10@?efK?Q&)M(qInVv!xjx+IKEL}p*K@LYvIzo#AZG>st5|P)KF1_Z;y){W{<7K{nl!CPuE z_^(!C(Ol0n8 zK13*rzAtW>(wULKPRYLd7G18F8#1P`V*9`(Poj26eOXYyBVZPno~Cvvhx7vPjAuZo zF?VD!zB~QG(!zbw#qsxT8%BSpqMZ4f70ZPn-3y$L8{EVbbN9$H`B&Z1quk9tgp5FM zuxp3pJ0b8u|3+#5bkJ4SRnCF2l7#DyLYXYY8*?OuAwK4E6J{0N=O3QNVzQ$L#FKkR zi-c@&!nDvezOV$i$Lr}iF$XEcwnybQ6WZrMKuw8gCL^U#D;q3t&HpTbqyD%vG=TeDlzCT~MXUPC|Leb-Uk+ z=vnMd(|>ld?Fh>V8poP;q;;nc@en$|rnP0ytzD&fFkCeUE^kG9Kx4wUh!!rpjwKDP zyw_e|a^x_w3E zP}}@$g>*LLJ4i0`Gx)qltL}@;mDv}D*xR^oeWcWdPkW@Uu)B^X&4W1$p6}ze!zudJ zyiLg@uggoMIArBr*27EZV7djDg@W1MaL+rcZ-lrANJQ%%>u8)ZMWU@R2qtnmG(acP z0d_^!t>}5W zpT`*2NR+0+SpTHb+6Js4b;%LJB;B_-ChhnU5py}iJtku*hm5F0!iql8Hrpcy1aYbT z1*dKC5ua6pMX@@iONI?Hpr%h;&YaXp9n!ND7-=a%BD7v&g zOO41M6EbE24mJ#S$Ui0-brR5ML%@|ndz^)YLMMV1atna{Fw<;TF@>d&F|!Z>8eg>>hkFrV)W+uv=`^F9^e zzzM2*oOjT9%gLoub%(R57p-`TXFe#oh1_{&N-YN z<}artH|m=d8TQuKSWE)Z%puU|g|^^NFwC#N=@dPhasyYjoy(fdEVfKR@cXKHZV-`06HsP`|Ftx;8(YD$fFXumLWbGnu$GMqRncXYY9mwz9$ap zQtfZB^_BeNYITh^hA7+(XNFox5WMeG_LtJ%*Q}$8VKDI_p8^pqX)}NMb`0e|wgF7D zuQACY_Ua<1ri{;Jwt@_1sW9zzdgnyh_O#8y+C;LcZq6=4e^cs6KvmK@$vVpKFGbQ= z$)Eux5C|Fx;Gtmv9^#Y-g@7Rt7*eLp5n!gJmn7&B_L$G?NCN`AP>cXQEz}%F%K;vUs{+l4Q{}eWW;ATe2 zqvXzxoIDy(u;F2q1JH7Sf;{jy_j})F+cKlIOmNfjBGHoG^CN zM|Ho&&X|L-36f}Q-obEACz`sI%2f&k>z5c$2TyTSj~vmO)BW~+N^kt`Jt@R|s!){H ze1_eCrlNaPkJQhL$WG&iRvF*YG=gXd1IyYQ9ew|iYn7r~g!wOnw;@n42>enAxBv*A zEmV*N#sxdicyNM=A4|yaOC5MByts}s_Hpfj|y<6G=o=!3S@eIFKDdpR7|FY>L&Wat&oW&cm&X~ z5Bt>Fcq(fgnvlvLSYg&o6>&fY`ODg4`V^lWWD=%oJ#Kbad2u~! zLECFS*??>|vDsNR&pH=Ze0Eo`sC_G`OjoEKVHY|wmwlX&(XBE<@sx3Hd^gtd-fNwUHsylg06p`U2y_={u}Bc + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/bare-react-native-with-js-sdk-and-flow/android/app/src/main/java/com/dynamiclabs/examples/bareflowmetamaskdemo/MainActivity.kt b/examples/bare-react-native-with-js-sdk-and-flow/android/app/src/main/java/com/dynamiclabs/examples/bareflowmetamaskdemo/MainActivity.kt new file mode 100644 index 0000000..d687d68 --- /dev/null +++ b/examples/bare-react-native-with-js-sdk-and-flow/android/app/src/main/java/com/dynamiclabs/examples/bareflowmetamaskdemo/MainActivity.kt @@ -0,0 +1,33 @@ +package com.dynamiclabs.examples.bareflowmetamaskdemo + +import android.content.Intent +import com.facebook.react.ReactActivity +import com.facebook.react.ReactActivityDelegate +import com.facebook.react.defaults.DefaultNewArchitectureEntryPoint.fabricEnabled +import com.facebook.react.defaults.DefaultReactActivityDelegate + +class MainActivity : ReactActivity() { + + /** + * Returns the name of the main component registered from JavaScript. This is used to schedule + * rendering of the component. + */ + override fun getMainComponentName(): String = "BareFlowMetaMaskDemo" + + /** + * Returns the instance of the [ReactActivityDelegate]. We use [DefaultReactActivityDelegate] + * which allows you to enable New Architecture with a single boolean flags [fabricEnabled] + */ + override fun createReactActivityDelegate(): ReactActivityDelegate = + DefaultReactActivityDelegate(this, mainComponentName, fabricEnabled) + + // Forwards incoming bareflowmetamaskdemo:// intents (see AndroidManifest.xml's + // intent-filter and dynamicClient.ts's metadata.nativeLink) to this already-running + // Activity — required because the manifest sets launchMode="singleTask", so a warm + // app receives the redirect here rather than via a fresh launch Intent. Without this, + // RN's Linking.getInitialURL()/'url' listeners never see it. + override fun onNewIntent(intent: Intent) { + super.onNewIntent(intent) + setIntent(intent) + } +} diff --git a/examples/bare-react-native-with-js-sdk-and-flow/android/app/src/main/java/com/dynamiclabs/examples/bareflowmetamaskdemo/MainApplication.kt b/examples/bare-react-native-with-js-sdk-and-flow/android/app/src/main/java/com/dynamiclabs/examples/bareflowmetamaskdemo/MainApplication.kt new file mode 100644 index 0000000..2a65b1f --- /dev/null +++ b/examples/bare-react-native-with-js-sdk-and-flow/android/app/src/main/java/com/dynamiclabs/examples/bareflowmetamaskdemo/MainApplication.kt @@ -0,0 +1,38 @@ +package com.dynamiclabs.examples.bareflowmetamaskdemo + +import android.app.Application +import com.facebook.react.PackageList +import com.facebook.react.ReactApplication +import com.facebook.react.ReactHost +import com.facebook.react.ReactNativeApplicationEntryPoint.loadReactNative +import com.facebook.react.ReactNativeHost +import com.facebook.react.ReactPackage +import com.facebook.react.defaults.DefaultReactHost.getDefaultReactHost +import com.facebook.react.defaults.DefaultReactNativeHost + +class MainApplication : Application(), ReactApplication { + + override val reactNativeHost: ReactNativeHost = + object : DefaultReactNativeHost(this) { + override fun getPackages(): List = + PackageList(this).packages.apply { + // Packages that cannot be autolinked yet can be added manually here, for example: + // add(MyReactNativePackage()) + } + + override fun getJSMainModuleName(): String = "index" + + override fun getUseDeveloperSupport(): Boolean = BuildConfig.DEBUG + + override val isNewArchEnabled: Boolean = BuildConfig.IS_NEW_ARCHITECTURE_ENABLED + override val isHermesEnabled: Boolean = BuildConfig.IS_HERMES_ENABLED + } + + override val reactHost: ReactHost + get() = getDefaultReactHost(applicationContext, reactNativeHost) + + override fun onCreate() { + super.onCreate() + loadReactNative(this) + } +} diff --git a/examples/bare-react-native-with-js-sdk-and-flow/android/app/src/main/res/drawable/rn_edit_text_material.xml b/examples/bare-react-native-with-js-sdk-and-flow/android/app/src/main/res/drawable/rn_edit_text_material.xml new file mode 100644 index 0000000..5c25e72 --- /dev/null +++ b/examples/bare-react-native-with-js-sdk-and-flow/android/app/src/main/res/drawable/rn_edit_text_material.xml @@ -0,0 +1,37 @@ + + + + + + + + + + + diff --git a/examples/bare-react-native-with-js-sdk-and-flow/android/app/src/main/res/mipmap-hdpi/ic_launcher.png b/examples/bare-react-native-with-js-sdk-and-flow/android/app/src/main/res/mipmap-hdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..a2f5908281d070150700378b64a84c7db1f97aa1 GIT binary patch literal 3056 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 axPAxe%7rDusX+w*00006jj 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⁣ zwiG+x#%j}{0gU~J8;<|!B1@-XaB@{KORFwrYg_8rOv({b0EO#DbeQRm;B6_9=mXGf z-x|VL{zd`)#@yN}HkCSJbjbNlE|zL3Wm9Q8HY`sV)}3%pgN>cL^67{Z;PPL(*wT8N zUjXU{@|*hvm}({wsAC=x0^ok0%UAz0;sogW{B!nDqk|JJ5x~4NfTDgP49^zeu`csl?5mY@JdQdISc zFs!E{^grmkLnUk9 zny~m)1vws@5BFI<-0Tuo2JWX(0v`W|t(wg;s--L47WTvTMz-8l#TL^=OJNRS2?_Qj z3AKT+gvbyBi#H*-tJ%tWD|>EV3wy|8qxfzS!5RW;Jpl5*zo&^UBU=fG#2}UvRyNkK zA06Dy9;K1ca@r2T>yThYgI!ont$(G{6q#2QT+00r_x0(b)gsE`lBB?2gr55gq^D3Fi&p%E(p9>U%bv zkg1Jco(RbyTX7FDHOnl7-O@ zI$AaIl?9NJKPm(WiBP`1-#CB1QzU>&hKm)fpa5DKE{2$X0hGz-0uZ?cyTk(YC!Y&| zL=1VrNERSA5NA2jq7FACfX4JfPyj5XXl1yv0>~s;eF7L2$>&oMqeTFT2m$y7FlkON z_yurD1yIOvA;5C6016pyxBznGUt0kJ&k5r#;&>Jow`r)sp9R~PmK~lz$3xH%LT*1U zJdOyABZ3!FvNoR*vN$5ykHS8f`jA4zV+|L}i1C4`B2c{R0;UdYxaU|H)2avz@ z=mEYc|2S<+(B2Tj+FkX+2D+yFI!k9lWMA61DJ{)e;lum$(;O87?vGJJe!KtK04+N_ zI*P~t@dUb>9Xh{dbyl{-ZQ(UMgz7$|QfL5XSPkskt^NgctYC#;4WcZB1@%@wy@2t3 z2z0DI7&%b$*Aw~abe?GxE`ez@+6hOh-6*8fHRV{1os$EL@}uUZeG4h1&Be`98q*7j z=3-v+lhIjfWVo12!<>%V^a6lTgW3+_#W6n|p*~==zOH7z$0{LSZk(Tpd7EaD04hnA zL;#fxS0aD{`5^&D`}>0Uq?byDD-l2=!wm_bLcUl4gc(% za1p|itVANvFF>hghAS07Im1;IK;|b*W)}VDyI;BIp2=K*yu2a)j?B|f<44NI$NbmJ z#dE0>jI$fMr&@>4kN8MLFb4&2O9fEKaQg%(QO$4_1rVQywG^CmBLh#}_7gKW3vd?| z2?1^&KWq8}8I^_S0|)MowU_pw$q@nl@Nkn$z>BQq_KA^9yaR`(R3u{{Ig;cwt z@AJ^{ODQCm^neroM9nKNUAXi9RCK`OsP_LuR0PUR(YZCCX5dNF6VzcoK&=b^r`W?ltt|*F zpkoae%ZT{C1h~EcFui~b7fF`vb<<~j_VquuUA$}QqIKYELPp#;{u?q8Dz}WAG-(3; zjrm$i%7UbyZMM(Y{>!uJ#vNB?R~B{6Htp=>e*<{fQQ5W7V(1coCWlOON!MzZxhum| ztZBQpGR z;~#ur^&PockKdV{Q6R>o`Pl{0x!DEbpZ7y9Y;*ZvE!*gU`V1W3znva{f=?WO5I&>B z&hw6}tjECtaghm5z|C#%M;Yf_*pI^};h}Vl=^r9EN=tVDj86D;C$jIJ?K7VP+00000NkvXXu0mjf D5i!M* literal 0 HcmV?d00001 diff --git a/examples/bare-react-native-with-js-sdk-and-flow/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png b/examples/bare-react-native-with-js-sdk-and-flow/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png new file mode 100644 index 0000000000000000000000000000000000000000..459ca609d3ae0d3943ab44cdc27feef9256dc6d7 GIT binary patch literal 7098 zcmV;r8%5-aP)U(QdAI7f)tS=AhH53iU?Q%B}x&gA$2B`o|*LCD1jhW zSQpS0{*?u3iXtkY?&2<)$@#zc%$?qDlF1T~d7k&lWaiv^&wbx>zVm(GIrof<%iY)A zm%|rhEg~Z$Te<*wd9Cb1SB{RkOI$-=MBtc%k*xtvYC~Uito}R@3fRUqJvco z|Bt2r9pSOcJocAEd)UN^Tz-82GUZlqsU;wb|2Q_1!4Rms&HO1Xyquft~#6lJoR z`$|}VSy@{k6U652FJ~bnD9(X%>CS6Wp6U>sn;f}te}%WL`rg)qE4Q=4OOhk^@ykw( ziKr^LHnAd4M?#&SQhw8zaC05q#Mc66K^mxY!dZ=W+#Bq1B}cQ6Y8FWd(n>#%{8Di_8$CHibtvP z-x#-g;~Q?y0vJA*8TW>ZxF?fAy1DuFy7%O1ylLF(t=ah7LjZ$=p!;8(ZLjXAhwEkCR{wF`L=hwm>|vLK2=gR&KM1ZEG9R~53yNCZdabQoQ%VsolX zS#WlesPcpJ)7XLo6>Ly$im38oxyiizP&&>***e@KqUk3q3y+LQN^-v?ZmO>9O{Oq@ z{{He$*Z=Kf_FPR>El3iB*FULYFMnLa#Fl^l&|bFg$Omlh{xVVJ7uHm=4WE6)NflH6 z=>z4w{GV&8#MNnEY3*B7pXU!$9v-tZvdjO}9O=9r{3Wxq2QB}(n%%YI$)pS~NEd}U z)n#nv-V)K}kz9M0$hogDLsa<(OS0Hf5^WUKO-%WbR1W1ID$NpAegxHH;em?U$Eyn1 zU{&J2@WqSUn0tav=jR&&taR9XbV+Izb*PwFn|?cv0mksBdOWeGxNb~oR;`~>#w3bp zrOrEQ+BiW_*f&GARyW|nE}~oh0R>>AOH^>NHNKe%%sXLgWRu1Sy3yW0Q#L{8Y6=3d zKd=By=Nb8?#W6|LrpZm>8Ro)`@cLmU;D`d64nKT~6Z!aLOS{m`@oYwD`9yily@}%yr0A>P!6O4G|ImNbBzI`LJ0@=TfLt^f`M07vw_PvXvN{nx%4 zD8vS>8*2N}`lD>M{`v?2!nYnf%+`GRK3`_i+yq#1a1Yx~_1o~-$2@{=r~q11r0oR* zqBhFFVZFx!U0!2CcItqLs)C;|hZ|9zt3k^(2g32!KB-|(RhKbq-vh|uT>jT@tX8dN zH`TT5iytrZT#&8u=9qt=oV`NjC)2gWl%KJ;n63WwAe%-)iz&bK{k`lTSAP`hr)H$Q`Yq8-A4PBBuP*-G#hSKrnmduy6}G zrc+mcVrrxM0WZ__Y#*1$mVa2y=2I`TQ%3Vhk&=y!-?<4~iq8`XxeRG!q?@l&cG8;X zQ(qH=@6{T$$qk~l?Z0@I4HGeTG?fWL67KN#-&&CWpW0fUm}{sBGUm)Xe#=*#W{h_i zohQ=S{=n3jDc1b{h6oTy=gI!(N%ni~O$!nBUig}9u1b^uI8SJ9GS7L#s!j;Xy*CO>N(o6z){ND5WTew%1lr? znp&*SAdJb5{L}y7q#NHbY;N_1vn!a^3TGRzCKjw?i_%$0d2%AR73CwHf z`h4QFmE-7G=psYnw)B!_Cw^{=!UNZeR{(s47|V$`3;-*gneX=;O+eN@+Efd_Zt=@H3T@v&o^%H z7QgDF8g>X~$4t9pv35G{a_8Io>#>uGRHV{2PSk#Ea~^V8!n@9C)ZH#87~ z#{~PUaRR~4K*m4*PI16)rvzdaP|7sE8SyMQYI6!t(%JNebR%?lc$={$s?VBI0Qk!A zvrE4|#asTZA|5tB{>!7BcxOezR?QIo4U_LU?&9Im-liGSc|TrJ>;1=;W?gG)0pQaw z|6o7&I&PH!*Z=c7pNPkp)1(4W`9Z01*QKv44FkvF^2Kdz3gDNpV=A6R;Q}~V-_sZY zB9DB)F8%iFEjK?Gf4$Cwu_hA$98&pkrJM!7{l+}osR_aU2PEx!1CRCKsS`0v$LlKq z{Pg#ZeoBMv@6BcmK$-*|S9nv50or*2&EV`L7PfW$2J7R1!9Q(1SSe42eSWZ5sYU?g z2v{_QB^^jfh$)L?+|M`u-E7D=Hb?7@9O89!bRUSI7uD?Mxh63j5!4e(v)Kc&TUEqy z8;f`#(hwrIeW);FA0CK%YHz6;(WfJz^<&W#y0N3O2&Qh_yxHu?*8z1y9Ua}rECL!5 z7L1AEXx83h^}+)cY*Ko{`^0g3GtTuMP>b$kq;Aqo+2d&+48mc#DP;Sv z*UL^nR*K7J968xR0_eTaZ`N`u_c#9bFUjTj-}0+_57(gtEJT|7PA12W=2Z>#_a z&Wg@_b=$d~wonN3h~?)gS`qxx<4J&`dI*rH9!mTSiQj(0rF-{YoNJRnOqd5IbP7p} ztDaPu$A;#osxf=z2zVe4>tpa(knS_Mp67nKcE<>Cj$G2orP(Z$Oc4;4DPwbXYZsS^ z;b>59s(LgYmx|tkRD?U{+9VZ$T}{S}L6>lQNR^a|&5joAFXtOrI07Do!vk(e$mu@Y zNdN!djB`Hq1*T8mrC@S)MLwZ`&8aM8YYtVj7i)IY{g&D1sJaY`3e=1DSFnjO+jEHH zj+|@r$$4RtpuJ!8=C`n5X;5BjU2slP9VV&m0gr+{O(I}9pYF32AMU?n$k$=x;X^E# zOb-x}p1_`@IOXAj3>HFxnmvBV9M^^9CfD7UlfuH*y^aOD?X6D82p_r*c>DF)m=9>o zgv_SDeSF6WkoVOI<_mX};FlW9rk3WgQP|vr-eVo8!wH!TiX)aiw+I|dBWJX=H6zxx z_tSI2$ChOM+?XlJwEz3!juYU6Z_b+vP-Y|m1!|ahw>Kpjrii-M_wmO@f@7;aK(I;p zqWgn+X^onc-*f)V9Vfu?AHLHHK!p2|M`R&@4H0x4hD5#l1##Plb8KsgqGZ{`d+1Ns zQ7N(V#t49wYIm9drzw`;WSa|+W+VW8Zbbx*Z+aXHSoa!c!@3F_yVww58NPH2->~Ls z2++`lSrKF(rBZLZ5_ts6_LbZG-W-3fDq^qI>|rzbc@21?)H>!?7O*!D?dKlL z6J@yulp7;Yk6Bdytq*J1JaR1!pXZz4aXQ{qfLu0;TyPWebr3|*EzCk5%ImpjUI4cP z7A$bJvo4(n2km-2JTfRKBjI9$mnJG@)LjjE9dnG&O=S;fC)@nq9K&eUHAL%yAPX7OFuD$pb_H9nhd{iE0OiI4#F-);A|&YT z|A3tvFLfR`5NYUkE?Rfr&PyUeFX-VHzcss2i*w06vn4{k1R%1_1+Ygx2oFt*HwfT> zd=PFdfFtrP1+YRs0AVr{YVp4Bnw2HQX-|P$M^9&P7pY6XSC-8;O2Ia4c{=t{NRD=z z0DeYUO3n;p%k zNEmBntbNac&5o#&fkY1QSYA4tKqBb=w~c6yktzjyk_Po)A|?nn8>HdA31amaOf7jX z2qillM8t8V#qv5>19Cg_X`mlU*O5|C#X-kfAXAHAD*q%6+z%IK(*H6olm-N4%Ic)5 zL`?wQgXfD&qQRxWskoO^Ylb>`jelq;*~ZIwKw|#BQjOSLkgc2uy7|oFEVhC?pcnU+ z^7qz}Z2%F!WOp%JO3y*&_7t;uRfU>)drR1q)c7lX?;A1-TuLTR zyr(`7O19`eW{ev;L%`;BvOzh?m|)Rh?W8&I$KVvUTo?@f@K!du&vf=o6kKb?hA z%e6$T0jWS7doVkN%^_k3QOksfV?aC$Ge$a)z(!C@UVs*@qzDw*OFd*JfX#>5LCXjE z_vfUrLF7D`K$U2Ld#OCnh9U!;r7%GlKo$e__Il-oba06ER{H&f#J&W@x^^5j;y$0` zs2`m6pf+{UiDb{Mjsb$rH+MCM6G_wX92so96`ODFYKD>!Xz^0y@U7Tc1uON4L<>2f-oPe%FRPEZ@S#-yd7Md-i?v z)$Kgtq;%4g@>Kap3Nl2I&jnCIfGmRmcF4CXfF1H}3SfhLg8=!a0ucGaUk&c3*Ykgl z2X_L84cs+FD#cjf-nMJkVDH%XzOoh5!X-Q$K5VZx-hGF7MQ=XKBjhZZQ@1Sh zO^vY`WQ`zi21z-+01na%<^niMFIWm-n|!?hm4X2HEHkba4YS|+HRoIR=`#Xck@PFXaPjnP z=hC4A*0lumS+gpK=TUN!G;{WqICbMz-V=-lTP^@a#C|E!qH;T00SZh7u#?+?08g0< zV1s%-U-`T@8wGh!3pO^`zUIY{nAED7kBqg!qi&GfOp>57f2PGTV19m z0qU@1PYkf%4z_%;Sq4IY94rS+ie~pwT@O3+tg?#k_=5PIk6tV@< zwLoqM0wBVLkI#`|1w=eYMnc^aRR!t?lnUng>WekR#X!!9mYXL3g^gC7`)S7mmo{y} z9*N!d$s32Nu{cZp#O|UxEZK7eY<7hGcI=lc;HrSVL|HA|S$rhhu_DBT&l+`75d`Sj3LaM~H)P zZuk2&jor6yipafklSsPL-vMo?0yAYXpH3=LveBhkno-3{4VLWL16I-@!RM$Po>&}} zm&PX3-$i>$*yx-THZmvK2q`8Qm7B`(NMR;>VSgoGw}W|G6Xd6v04Zf;HIZ0DZU?@- z39vPe0N8w(9kl$2?eG4T?tLgY5V&aFl%~g;2)aSpi!dl?{hDgsz|3<-M(gPtwP_!n z2aB4tV?d0k+>X`+(HMYfK@qtfDK|mIJeg+A<_i-n+5wkrexFs#V0N&~+{+qJ(wggC*52o2daaRwcu7r;S!!KwguB3!Ei7?IEY ze4V$m{8B4Q^(VK4~Ea!V@@}Gs0HGbR5 zy~WI*21hZuoiK`=O$2a|Uce-Zi2%A*pB|?{gv)n8+_B+i&u8Ys)ePY+UwhBDlzbC& z+N00*-?a8DTC26*(3pKgeMO`fOau^-+c6Qqq}3-dpTsEEH}ds! zT^}8XAWO>c5%+qF%#M8#x_0gC+N%q8h6-%w;qidS%gai<T)vpfYuCHXRx6O-TbC|fnj87X zBESvn(9XlXFMj6%{&BaNQ&;xixaKP)+jJ|%u&?HXvYficY}{%hf?0rNDS-X-0_Jcr zjfj~n?T;~RL#sd4ZED2Jf{*Vj+*1eP9-H+~8X^#Jb?HHabLY)EH{QD@Yh-$M`XXt@3_f-L8nBo~*C?L4~n6M92PCuzX=KFgM*j!B66er$F! z+*M(Wkk`UI@uhrL#IUz-C{K@@xtd&n-PQz%kc}7YeE{{&$?}-*yW$eG*E4jp>B_U!2`2oZuvvitN& z%RN>tE$+Yhtqb1q+xQHbp=W4uKSiIj_LZppR0=hEiVj>P0^Vcr^hu2+#Hqum+}zzo znqZ|M4oD|qd=y&JX-qob`=uqt?o%FJPIVY2w0M7BH>#sx>s#OM#9JF1(3LxMAe-vi ztJeU*G)aksP`5sP9_%|~>Pp{NmMMcay>&D+cI%H}$uSx{Su(yz$)2e$*pS%*+!Zo>DNp(P7 zI%w^D2ceEFUGCtQPKfsKr`x%^dy;Rh>lMKuhA^btz=071W=vV`_xz&m;cvd0`|!3+ z2M6uga6CNvy)%Pjw_X}5+xf###jc+?=>6chZI{BMH=haH^7ipT>(?9{weF3apk<4; z_nZFsi`@oFBXCZE^k9B1x+cH2)~9d(MnfEm;GJxG*IB zU@ly{cOTWk*K1ryX+T7m!6A>VwB-*qfH;b>`AUP19lLSA9HbfppW!={L0K)??SymOCA^V>=tOBLn2c5e ksm9QK-qMKdW>5J419kFO%DdQj-T(jq07*qoM6N<$f+5oB`~Uy| literal 0 HcmV?d00001 diff --git a/examples/bare-react-native-with-js-sdk-and-flow/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/examples/bare-react-native-with-js-sdk-and-flow/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..8ca12fe024be86e868d14e91120a6902f8e88ac6 GIT binary patch literal 6464 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 B0*L?s literal 0 HcmV?d00001 diff --git a/examples/bare-react-native-with-js-sdk-and-flow/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png b/examples/bare-react-native-with-js-sdk-and-flow/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png new file mode 100644 index 0000000000000000000000000000000000000000..8e19b410a1b15ff180f3dacac19395fe3046cdec GIT binary patch literal 10676 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 literal 0 HcmV?d00001 diff --git a/examples/bare-react-native-with-js-sdk-and-flow/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png b/examples/bare-react-native-with-js-sdk-and-flow/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png new file mode 100644 index 0000000000000000000000000000000000000000..4c19a13c239cb67b8a2134ddd5f325db1d2d5bee GIT binary patch literal 15523 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 BIP(Ai literal 0 HcmV?d00001 diff --git a/examples/bare-react-native-with-js-sdk-and-flow/android/app/src/main/res/values/strings.xml b/examples/bare-react-native-with-js-sdk-and-flow/android/app/src/main/res/values/strings.xml new file mode 100644 index 0000000..aff847e --- /dev/null +++ b/examples/bare-react-native-with-js-sdk-and-flow/android/app/src/main/res/values/strings.xml @@ -0,0 +1,3 @@ + + BareFlowMetaMaskDemo + diff --git a/examples/bare-react-native-with-js-sdk-and-flow/android/app/src/main/res/values/styles.xml b/examples/bare-react-native-with-js-sdk-and-flow/android/app/src/main/res/values/styles.xml new file mode 100644 index 0000000..7ba83a2 --- /dev/null +++ b/examples/bare-react-native-with-js-sdk-and-flow/android/app/src/main/res/values/styles.xml @@ -0,0 +1,9 @@ + + + + + + diff --git a/examples/bare-react-native-with-js-sdk-and-flow/android/build.gradle b/examples/bare-react-native-with-js-sdk-and-flow/android/build.gradle new file mode 100644 index 0000000..dad99b0 --- /dev/null +++ b/examples/bare-react-native-with-js-sdk-and-flow/android/build.gradle @@ -0,0 +1,21 @@ +buildscript { + ext { + buildToolsVersion = "36.0.0" + minSdkVersion = 24 + compileSdkVersion = 36 + targetSdkVersion = 36 + ndkVersion = "27.1.12297006" + kotlinVersion = "2.1.20" + } + repositories { + google() + mavenCentral() + } + dependencies { + classpath("com.android.tools.build:gradle") + classpath("com.facebook.react:react-native-gradle-plugin") + classpath("org.jetbrains.kotlin:kotlin-gradle-plugin") + } +} + +apply plugin: "com.facebook.react.rootproject" diff --git a/examples/bare-react-native-with-js-sdk-and-flow/android/gradle.properties b/examples/bare-react-native-with-js-sdk-and-flow/android/gradle.properties new file mode 100644 index 0000000..9afe615 --- /dev/null +++ b/examples/bare-react-native-with-js-sdk-and-flow/android/gradle.properties @@ -0,0 +1,44 @@ +# Project-wide Gradle settings. + +# IDE (e.g. Android Studio) users: +# Gradle settings configured through the IDE *will override* +# any settings specified in this file. + +# For more details on how to configure your build environment visit +# http://www.gradle.org/docs/current/userguide/build_environment.html + +# Specifies the JVM arguments used for the daemon process. +# The setting is particularly useful for tweaking memory settings. +# Default value: -Xmx512m -XX:MaxMetaspaceSize=256m +org.gradle.jvmargs=-Xmx2048m -XX:MaxMetaspaceSize=512m + +# When configured, Gradle will run in incubating parallel mode. +# This option should only be used with decoupled projects. More details, visit +# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects +# org.gradle.parallel=true + +# AndroidX package structure to make it clearer which packages are bundled with the +# Android operating system, and which are packaged with your app's APK +# https://developer.android.com/topic/libraries/support-library/androidx-rn +android.useAndroidX=true + +# Use this property to specify which architecture you want to build. +# You can also override it from the CLI using +# ./gradlew -PreactNativeArchitectures=x86_64 +reactNativeArchitectures=armeabi-v7a,arm64-v8a,x86,x86_64 + +# Use this property to enable support to the new architecture. +# This will allow you to use TurboModules and the Fabric render in +# your application. You should enable this flag either if you want +# to write custom TurboModules/Fabric components OR use libraries that +# are providing them. +newArchEnabled=true + +# Use this property to enable or disable the Hermes JS engine. +# If set to false, you will be using JSC instead. +hermesEnabled=true + +# Use this property to enable edge-to-edge display support. +# This allows your app to draw behind system bars for an immersive UI. +# Note: Only works with ReactActivity and should not be used with custom Activity. +edgeToEdgeEnabled=false diff --git a/examples/bare-react-native-with-js-sdk-and-flow/android/gradle/wrapper/gradle-wrapper.jar b/examples/bare-react-native-with-js-sdk-and-flow/android/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 0000000000000000000000000000000000000000..1b33c55baabb587c669f562ae36f953de2481846 GIT binary patch literal 43764 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 '} + case $link in #( + /*) app_path=$link ;; #( + *) app_path=$APP_HOME$link ;; + esac +done + +# This is normally unused +# shellcheck disable=SC2034 +APP_BASE_NAME=${0##*/} +# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) +APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s\n' "$PWD" ) || exit + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD=maximum + +warn () { + echo "$*" +} >&2 + +die () { + echo + echo "$*" + echo + exit 1 +} >&2 + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +nonstop=false +case "$( uname )" in #( + CYGWIN* ) cygwin=true ;; #( + Darwin* ) darwin=true ;; #( + MSYS* | MINGW* ) msys=true ;; #( + NONSTOP* ) nonstop=true ;; +esac + +CLASSPATH="\\\"\\\"" + + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD=$JAVA_HOME/jre/sh/java + else + JAVACMD=$JAVA_HOME/bin/java + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD=java + if ! command -v java >/dev/null 2>&1 + then + die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +fi + +# Increase the maximum file descriptors if we can. +if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then + case $MAX_FD in #( + max*) + # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC2039,SC3045 + MAX_FD=$( ulimit -H -n ) || + warn "Could not query maximum file descriptor limit" + esac + case $MAX_FD in #( + '' | soft) :;; #( + *) + # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC2039,SC3045 + ulimit -n "$MAX_FD" || + warn "Could not set maximum file descriptor limit to $MAX_FD" + esac +fi + +# Collect all arguments for the java command, stacking in reverse order: +# * args from the command line +# * the main class name +# * -classpath +# * -D...appname settings +# * --module-path (only if needed) +# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. + +# For Cygwin or MSYS, switch paths to Windows format before running java +if "$cygwin" || "$msys" ; then + APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) + CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) + + JAVACMD=$( cygpath --unix "$JAVACMD" ) + + # Now convert the arguments - kludge to limit ourselves to /bin/sh + for arg do + if + case $arg in #( + -*) false ;; # don't mess with options #( + /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath + [ -e "$t" ] ;; #( + *) false ;; + esac + then + arg=$( cygpath --path --ignore --mixed "$arg" ) + fi + # Roll the args list around exactly as many times as the number of + # args, so each arg winds up back in the position where it started, but + # possibly modified. + # + # NB: a `for` loop captures its iteration list before it begins, so + # changing the positional parameters here affects neither the number of + # iterations, nor the values presented in `arg`. + shift # remove old arg + set -- "$@" "$arg" # push replacement arg + done +fi + + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' + +# Collect all arguments for the java command: +# * DEFAULT_JVM_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, +# and any embedded shellness will be escaped. +# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be +# treated as '${Hostname}' itself on the command line. + +set -- \ + "-Dorg.gradle.appname=$APP_BASE_NAME" \ + -classpath "$CLASSPATH" \ + -jar "$APP_HOME/gradle/wrapper/gradle-wrapper.jar" \ + "$@" + +# Stop when "xargs" is not available. +if ! command -v xargs >/dev/null 2>&1 +then + die "xargs is not available" +fi + +# Use "xargs" to parse quoted args. +# +# With -n1 it outputs one arg per line, with the quotes and backslashes removed. +# +# In Bash we could simply go: +# +# readarray ARGS < <( xargs -n1 <<<"$var" ) && +# set -- "${ARGS[@]}" "$@" +# +# but POSIX shell has neither arrays nor command substitution, so instead we +# post-process each arg (as a line of input to sed) to backslash-escape any +# character that might be a shell metacharacter, then use eval to reverse +# that process (while maintaining the separation between arguments), and wrap +# the whole thing up as a single "set" statement. +# +# This will of course break if any of these variables contains a newline or +# an unmatched quote. +# + +eval "set -- $( + printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | + xargs -n1 | + sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | + tr '\n' ' ' + )" '"$@"' + +exec "$JAVACMD" "$@" diff --git a/examples/bare-react-native-with-js-sdk-and-flow/android/gradlew.bat b/examples/bare-react-native-with-js-sdk-and-flow/android/gradlew.bat new file mode 100644 index 0000000..11bf182 --- /dev/null +++ b/examples/bare-react-native-with-js-sdk-and-flow/android/gradlew.bat @@ -0,0 +1,99 @@ +@REM Copyright (c) Meta Platforms, Inc. and affiliates. +@REM +@REM This source code is licensed under the MIT license found in the +@REM LICENSE file in the root directory of this source tree. + +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem https://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem +@rem SPDX-License-Identifier: Apache-2.0 +@rem + +@if "%DEBUG%"=="" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%"=="" set DIRNAME=. +@rem This is normally unused +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Resolve any "." and ".." in APP_HOME to make it shorter. +for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if %ERRORLEVEL% equ 0 goto execute + +echo. 1>&2 +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto execute + +echo. 1>&2 +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 + +goto fail + +:execute +@rem Setup the command line + +set CLASSPATH= + + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %* + +:end +@rem End local scope for the variables with windows NT shell +if %ERRORLEVEL% equ 0 goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +set EXIT_CODE=%ERRORLEVEL% +if %EXIT_CODE% equ 0 set EXIT_CODE=1 +if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% +exit /b %EXIT_CODE% + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/examples/bare-react-native-with-js-sdk-and-flow/android/settings.gradle b/examples/bare-react-native-with-js-sdk-and-flow/android/settings.gradle new file mode 100644 index 0000000..2a4b419 --- /dev/null +++ b/examples/bare-react-native-with-js-sdk-and-flow/android/settings.gradle @@ -0,0 +1,23 @@ +pluginManagement { includeBuild("../node_modules/@react-native/gradle-plugin") } +plugins { id("com.facebook.react.settings") } +extensions.configure(com.facebook.react.ReactSettingsExtension){ ex -> ex.autolinkLibrariesFromCommand() } +rootProject.name = 'com.dynamiclabs.examples.bareflowmetamaskdemo' + +// JitPack hosts a native artifact @walletconnect/react-native-compat needs +// on Android — required for the Trust Wallet button (trustWalletConnect.ts) +// and addWalletConnectEvmExtension (dynamicClient.ts) to work at all. Per +// https://www.dynamic.xyz/docs/javascript/react-native/bare-react-native +// google()/mavenCentral() are kept alongside it (the doc snippet only shows +// jitpack.io) since this project had no explicit dependencyResolutionManagement +// block before this — omitting them risked losing every other dependency's +// default resolution rather than just adding the one this needs. +dependencyResolutionManagement { + repositories { + google() + mavenCentral() + maven { url = uri("https://jitpack.io") } + } +} + +include ':app' +includeBuild('../node_modules/@react-native/gradle-plugin') diff --git a/examples/bare-react-native-with-js-sdk-and-flow/app.json b/examples/bare-react-native-with-js-sdk-and-flow/app.json new file mode 100644 index 0000000..b4a65f7 --- /dev/null +++ b/examples/bare-react-native-with-js-sdk-and-flow/app.json @@ -0,0 +1,4 @@ +{ + "name": "BareFlowMetaMaskDemo", + "displayName": "BareFlowMetaMaskDemo" +} diff --git a/examples/bare-react-native-with-js-sdk-and-flow/babel.config.js b/examples/bare-react-native-with-js-sdk-and-flow/babel.config.js new file mode 100644 index 0000000..a8c9065 --- /dev/null +++ b/examples/bare-react-native-with-js-sdk-and-flow/babel.config.js @@ -0,0 +1,20 @@ +// Loads .env into process.env before babel runs, so the plugin below can +// inline the values into the bundle. Copy .env.example to .env and fill it +// in — see README.md. +require('dotenv').config(); + +module.exports = { + presets: ['module:@react-native/babel-preset'], + plugins: [ + // The Dynamic SDK ships modern JS syntax (`export * as ns from …`, + // static class blocks) that the stock RN Babel preset doesn't + // transform on its own — see + // https://www.dynamic.xyz/docs/javascript/react-native/bare-react-native + '@babel/plugin-transform-export-namespace-from', + '@babel/plugin-transform-class-static-block', + // Inlines process.env.* references at bundle time. This is a bare RN + // app, so there's no Expo-style EXPO_PUBLIC_* / Metro env substitution + // — this plugin is the equivalent mechanism. + 'transform-inline-environment-variables', + ], +}; diff --git a/examples/bare-react-native-with-js-sdk-and-flow/dynamicClient.ts b/examples/bare-react-native-with-js-sdk-and-flow/dynamicClient.ts new file mode 100644 index 0000000..d8c7f1a --- /dev/null +++ b/examples/bare-react-native-with-js-sdk-and-flow/dynamicClient.ts @@ -0,0 +1,72 @@ +/** + * Creates and configures the single Dynamic client instance for this app. + * + * Imported once, at app startup (see App.tsx) — creating more than one + * DynamicClient in the same app is unsupported by most SDK helpers, which + * default to whichever client was created first (see `addEvmExtension`'s + * docs: "Only required when using multiple Dynamic clients"). + */ +import { + createDynamicClient, + getWalletConnectCatalogWalletByWalletProviderKey, + onEvent, +} from '@dynamic-labs-sdk/client'; +import { addEvmExtension } from '@dynamic-labs-sdk/evm'; +import { addWalletConnectEvmExtension } from '@dynamic-labs-sdk/evm/wallet-connect'; +import { APP_ORIGIN, config } from './src/consts/config'; +import { Linking } from 'react-native'; + +if (!config.dynamic.environmentId) { + throw new Error( + 'DYNAMIC_ENVIRONMENT_ID is not set. Copy .env.example to .env, fill in ' + + 'your Dynamic Sandbox environment ID, and rebuild the app.', + ); +} + +if (!config.dynamic.apiKey) { + throw new Error( + 'DYNAMIC_API_KEY is not set. Copy .env.example to .env, fill in a ' + + 'sandbox API key with the flow.write scope, and rebuild the app.', + ); +} + +export const dynamicClient = createDynamicClient({ + environmentId: config.dynamic.environmentId, + ...(config.dynamic.apiBaseUrl + ? { coreConfig: { apiBaseUrl: config.dynamic.apiBaseUrl } } + : {}), + logLevel: 'debug', + metadata: { + // Also required by WalletConnect's createSignClient (asserted non-empty + // at connect time) — not just cosmetic for MetaMask. + name: 'Bare Flow MetaMask Demo', + // Reduced to its scheme (bareflowmetamaskdemo://) and embedded in the + // MetaMask/WalletConnect pairing URIs, so the wallet app can offer a + // "return to app" affordance once the user approves — registered as a + // URL scheme in ios/.../Info.plist (CFBundleURLTypes, forwarded to + // Linking via AppDelegate.swift) and android/.../AndroidManifest.xml + // (intent-filter, forwarded via MainActivity.kt's onNewIntent). Approval + // itself still resolves over each SDK's own relay/session either way; + // this only affects how smoothly the user gets back to this app. + nativeLink: 'bareflowmetamaskdemo://', + universalLink: APP_ORIGIN, + }, +}); + +addEvmExtension(dynamicClient); +addWalletConnectEvmExtension(dynamicClient); + +onEvent({ + event: 'walletConnectUserActionRequested', + listener: async ({ walletProviderKey }) => { + const wallet = await getWalletConnectCatalogWalletByWalletProviderKey({ + walletProviderKey, + }); + + const deepLink = wallet?.deeplinks?.native ?? wallet?.deeplinks?.universal; + + if (deepLink) { + Linking.openURL(deepLink); + } + }, +}); diff --git a/examples/bare-react-native-with-js-sdk-and-flow/index.js b/examples/bare-react-native-with-js-sdk-and-flow/index.js new file mode 100644 index 0000000..8d13444 --- /dev/null +++ b/examples/bare-react-native-with-js-sdk-and-flow/index.js @@ -0,0 +1,13 @@ +/** + * @format + */ + +// Must run before anything else touches crypto/URL/Buffer globals — see +// polyfills.ts for why. +import './polyfills'; + +import { AppRegistry } from 'react-native'; +import App from './src/App'; +import { name as appName } from './app.json'; + +AppRegistry.registerComponent(appName, () => App); diff --git a/examples/bare-react-native-with-js-sdk-and-flow/ios/.xcode.env b/examples/bare-react-native-with-js-sdk-and-flow/ios/.xcode.env new file mode 100644 index 0000000..3d5782c --- /dev/null +++ b/examples/bare-react-native-with-js-sdk-and-flow/ios/.xcode.env @@ -0,0 +1,11 @@ +# This `.xcode.env` file is versioned and is used to source the environment +# used when running script phases inside Xcode. +# To customize your local environment, you can create an `.xcode.env.local` +# file that is not versioned. + +# NODE_BINARY variable contains the PATH to the node executable. +# +# Customize the NODE_BINARY variable here. +# For example, to use nvm with brew, add the following line +# . "$(brew --prefix nvm)/nvm.sh" --no-use +export NODE_BINARY=$(command -v node) diff --git a/examples/bare-react-native-with-js-sdk-and-flow/ios/BareFlowMetaMaskDemo.xcodeproj/project.pbxproj b/examples/bare-react-native-with-js-sdk-and-flow/ios/BareFlowMetaMaskDemo.xcodeproj/project.pbxproj new file mode 100644 index 0000000..f0516d9 --- /dev/null +++ b/examples/bare-react-native-with-js-sdk-and-flow/ios/BareFlowMetaMaskDemo.xcodeproj/project.pbxproj @@ -0,0 +1,478 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 54; + objects = { + +/* Begin PBXBuildFile section */ + 0C80B921A6F3F58F76C31292 /* libPods-BareFlowMetaMaskDemo.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5DCACB8F33CDC322A6C60F78 /* libPods-BareFlowMetaMaskDemo.a */; }; + 13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB51A68108700A75B9A /* Images.xcassets */; }; + 5F560E0A65990150FC49F55A /* PrivacyInfo.xcprivacy in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB81A68108700A75B9A /* PrivacyInfo.xcprivacy */; }; + 761780ED2CA45674006654EE /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 761780EC2CA45674006654EE /* AppDelegate.swift */; }; + 81AB9BB82411601600AC10FF /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 81AB9BB72411601600AC10FF /* LaunchScreen.storyboard */; }; +/* End PBXBuildFile section */ + +/* Begin PBXFileReference section */ + 13B07F961A680F5B00A75B9A /* BareFlowMetaMaskDemo.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = BareFlowMetaMaskDemo.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 13B07FB51A68108700A75B9A /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Images.xcassets; path = BareFlowMetaMaskDemo/Images.xcassets; sourceTree = ""; }; + 13B07FB61A68108700A75B9A /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = Info.plist; path = BareFlowMetaMaskDemo/Info.plist; sourceTree = ""; }; + 13B07FB81A68108700A75B9A /* PrivacyInfo.xcprivacy */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = PrivacyInfo.xcprivacy; path = BareFlowMetaMaskDemo/PrivacyInfo.xcprivacy; sourceTree = ""; }; + 3B4392A12AC88292D35C810B /* Pods-BareFlowMetaMaskDemo.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-BareFlowMetaMaskDemo.debug.xcconfig"; path = "Target Support Files/Pods-BareFlowMetaMaskDemo/Pods-BareFlowMetaMaskDemo.debug.xcconfig"; sourceTree = ""; }; + 5709B34CF0A7D63546082F79 /* Pods-BareFlowMetaMaskDemo.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-BareFlowMetaMaskDemo.release.xcconfig"; path = "Target Support Files/Pods-BareFlowMetaMaskDemo/Pods-BareFlowMetaMaskDemo.release.xcconfig"; sourceTree = ""; }; + 5DCACB8F33CDC322A6C60F78 /* libPods-BareFlowMetaMaskDemo.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-BareFlowMetaMaskDemo.a"; sourceTree = BUILT_PRODUCTS_DIR; }; + 761780EC2CA45674006654EE /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = AppDelegate.swift; path = BareFlowMetaMaskDemo/AppDelegate.swift; sourceTree = ""; }; + 81AB9BB72411601600AC10FF /* LaunchScreen.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; name = LaunchScreen.storyboard; path = BareFlowMetaMaskDemo/LaunchScreen.storyboard; sourceTree = ""; }; + ED297162215061F000B7C4FE /* JavaScriptCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = JavaScriptCore.framework; path = System/Library/Frameworks/JavaScriptCore.framework; sourceTree = SDKROOT; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 13B07F8C1A680F5B00A75B9A /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 0C80B921A6F3F58F76C31292 /* libPods-BareFlowMetaMaskDemo.a in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 13B07FAE1A68108700A75B9A /* BareFlowMetaMaskDemo */ = { + isa = PBXGroup; + children = ( + 13B07FB51A68108700A75B9A /* Images.xcassets */, + 761780EC2CA45674006654EE /* AppDelegate.swift */, + 13B07FB61A68108700A75B9A /* Info.plist */, + 81AB9BB72411601600AC10FF /* LaunchScreen.storyboard */, + 13B07FB81A68108700A75B9A /* PrivacyInfo.xcprivacy */, + ); + name = BareFlowMetaMaskDemo; + sourceTree = ""; + }; + 2D16E6871FA4F8E400B85C8A /* Frameworks */ = { + isa = PBXGroup; + children = ( + ED297162215061F000B7C4FE /* JavaScriptCore.framework */, + 5DCACB8F33CDC322A6C60F78 /* libPods-BareFlowMetaMaskDemo.a */, + ); + name = Frameworks; + sourceTree = ""; + }; + 832341AE1AAA6A7D00B99B32 /* Libraries */ = { + isa = PBXGroup; + children = ( + ); + name = Libraries; + sourceTree = ""; + }; + 83CBB9F61A601CBA00E9B192 = { + isa = PBXGroup; + children = ( + 13B07FAE1A68108700A75B9A /* BareFlowMetaMaskDemo */, + 832341AE1AAA6A7D00B99B32 /* Libraries */, + 83CBBA001A601CBA00E9B192 /* Products */, + 2D16E6871FA4F8E400B85C8A /* Frameworks */, + BBD78D7AC51CEA395F1C20DB /* Pods */, + ); + indentWidth = 2; + sourceTree = ""; + tabWidth = 2; + usesTabs = 0; + }; + 83CBBA001A601CBA00E9B192 /* Products */ = { + isa = PBXGroup; + children = ( + 13B07F961A680F5B00A75B9A /* BareFlowMetaMaskDemo.app */, + ); + name = Products; + sourceTree = ""; + }; + BBD78D7AC51CEA395F1C20DB /* Pods */ = { + isa = PBXGroup; + children = ( + 3B4392A12AC88292D35C810B /* Pods-BareFlowMetaMaskDemo.debug.xcconfig */, + 5709B34CF0A7D63546082F79 /* Pods-BareFlowMetaMaskDemo.release.xcconfig */, + ); + path = Pods; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 13B07F861A680F5B00A75B9A /* BareFlowMetaMaskDemo */ = { + isa = PBXNativeTarget; + buildConfigurationList = 13B07F931A680F5B00A75B9A /* Build configuration list for PBXNativeTarget "BareFlowMetaMaskDemo" */; + buildPhases = ( + C38B50BA6285516D6DCD4F65 /* [CP] Check Pods Manifest.lock */, + 13B07F871A680F5B00A75B9A /* Sources */, + 13B07F8C1A680F5B00A75B9A /* Frameworks */, + 13B07F8E1A680F5B00A75B9A /* Resources */, + 00DD1BFF1BD5951E006B06BC /* Bundle React Native code and images */, + 00EEFC60759A1932668264C0 /* [CP] Embed Pods Frameworks */, + E235C05ADACE081382539298 /* [CP] Copy Pods Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = BareFlowMetaMaskDemo; + productName = BareFlowMetaMaskDemo; + productReference = 13B07F961A680F5B00A75B9A /* BareFlowMetaMaskDemo.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 83CBB9F71A601CBA00E9B192 /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 1210; + TargetAttributes = { + 13B07F861A680F5B00A75B9A = { + LastSwiftMigration = 1120; + }; + }; + }; + buildConfigurationList = 83CBB9FA1A601CBA00E9B192 /* Build configuration list for PBXProject "BareFlowMetaMaskDemo" */; + compatibilityVersion = "Xcode 12.0"; + developmentRegion = en; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 83CBB9F61A601CBA00E9B192; + productRefGroup = 83CBBA001A601CBA00E9B192 /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 13B07F861A680F5B00A75B9A /* BareFlowMetaMaskDemo */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 13B07F8E1A680F5B00A75B9A /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 81AB9BB82411601600AC10FF /* LaunchScreen.storyboard in Resources */, + 13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */, + 5F560E0A65990150FC49F55A /* PrivacyInfo.xcprivacy in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXShellScriptBuildPhase section */ + 00DD1BFF1BD5951E006B06BC /* Bundle React Native code and images */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + "$(SRCROOT)/.xcode.env.local", + "$(SRCROOT)/.xcode.env", + ); + name = "Bundle React Native code and images"; + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "set -e\n\nWITH_ENVIRONMENT=\"$REACT_NATIVE_PATH/scripts/xcode/with-environment.sh\"\nREACT_NATIVE_XCODE=\"$REACT_NATIVE_PATH/scripts/react-native-xcode.sh\"\n\n/bin/sh -c \"$WITH_ENVIRONMENT $REACT_NATIVE_XCODE\"\n"; + }; + 00EEFC60759A1932668264C0 /* [CP] Embed Pods Frameworks */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-BareFlowMetaMaskDemo/Pods-BareFlowMetaMaskDemo-frameworks-${CONFIGURATION}-input-files.xcfilelist", + ); + name = "[CP] Embed Pods Frameworks"; + outputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-BareFlowMetaMaskDemo/Pods-BareFlowMetaMaskDemo-frameworks-${CONFIGURATION}-output-files.xcfilelist", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-BareFlowMetaMaskDemo/Pods-BareFlowMetaMaskDemo-frameworks.sh\"\n"; + showEnvVarsInLog = 0; + }; + C38B50BA6285516D6DCD4F65 /* [CP] Check Pods Manifest.lock */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; + outputFileListPaths = ( + ); + outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-BareFlowMetaMaskDemo-checkManifestLockResult.txt", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; + showEnvVarsInLog = 0; + }; + E235C05ADACE081382539298 /* [CP] Copy Pods Resources */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-BareFlowMetaMaskDemo/Pods-BareFlowMetaMaskDemo-resources-${CONFIGURATION}-input-files.xcfilelist", + ); + name = "[CP] Copy Pods Resources"; + outputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-BareFlowMetaMaskDemo/Pods-BareFlowMetaMaskDemo-resources-${CONFIGURATION}-output-files.xcfilelist", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-BareFlowMetaMaskDemo/Pods-BareFlowMetaMaskDemo-resources.sh\"\n"; + showEnvVarsInLog = 0; + }; +/* End PBXShellScriptBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 13B07F871A680F5B00A75B9A /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 761780ED2CA45674006654EE /* AppDelegate.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin XCBuildConfiguration section */ + 13B07F941A680F5B00A75B9A /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 3B4392A12AC88292D35C810B /* Pods-BareFlowMetaMaskDemo.debug.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CURRENT_PROJECT_VERSION = 1; + ENABLE_BITCODE = NO; + INFOPLIST_FILE = BareFlowMetaMaskDemo/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 15.1; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + MARKETING_VERSION = 1.0; + OTHER_LDFLAGS = ( + "$(inherited)", + "-ObjC", + "-lc++", + ); + PRODUCT_BUNDLE_IDENTIFIER = com.dynamiclabs.examples.bareflowmetamaskdemo; + PRODUCT_NAME = BareFlowMetaMaskDemo; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 5.0; + VERSIONING_SYSTEM = "apple-generic"; + }; + name = Debug; + }; + 13B07F951A680F5B00A75B9A /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 5709B34CF0A7D63546082F79 /* Pods-BareFlowMetaMaskDemo.release.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CURRENT_PROJECT_VERSION = 1; + INFOPLIST_FILE = BareFlowMetaMaskDemo/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 15.1; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + MARKETING_VERSION = 1.0; + OTHER_LDFLAGS = ( + "$(inherited)", + "-ObjC", + "-lc++", + ); + PRODUCT_BUNDLE_IDENTIFIER = com.dynamiclabs.examples.bareflowmetamaskdemo; + PRODUCT_NAME = BareFlowMetaMaskDemo; + SWIFT_VERSION = 5.0; + VERSIONING_SYSTEM = "apple-generic"; + }; + name = Release; + }; + 83CBBA201A601CBA00E9B192 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; + CLANG_CXX_LANGUAGE_STANDARD = "c++20"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + "EXCLUDED_ARCHS[sdk=iphonesimulator*]" = ""; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_SYMBOLS_PRIVATE_EXTERN = NO; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 15.1; + LD_RUNPATH_SEARCH_PATHS = ( + /usr/lib/swift, + "$(inherited)", + ); + LIBRARY_SEARCH_PATHS = ( + "\"$(SDKROOT)/usr/lib/swift\"", + "\"$(TOOLCHAIN_DIR)/usr/lib/swift/$(PLATFORM_NAME)\"", + "\"$(inherited)\"", + ); + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + OTHER_CPLUSPLUSFLAGS = ( + "$(OTHER_CFLAGS)", + "-DFOLLY_NO_CONFIG", + "-DFOLLY_MOBILE=1", + "-DFOLLY_USE_LIBCPP=1", + "-DFOLLY_CFG_NO_COROUTINES=1", + "-DFOLLY_HAVE_CLOCK_GETTIME=1", + ); + REACT_NATIVE_PATH = "${PODS_ROOT}/../../node_modules/react-native"; + SDKROOT = iphoneos; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) DEBUG"; + USE_HERMES = true; + }; + name = Debug; + }; + 83CBBA211A601CBA00E9B192 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; + CLANG_CXX_LANGUAGE_STANDARD = "c++20"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = YES; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + "EXCLUDED_ARCHS[sdk=iphonesimulator*]" = ""; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 15.1; + LD_RUNPATH_SEARCH_PATHS = ( + /usr/lib/swift, + "$(inherited)", + ); + LIBRARY_SEARCH_PATHS = ( + "\"$(SDKROOT)/usr/lib/swift\"", + "\"$(TOOLCHAIN_DIR)/usr/lib/swift/$(PLATFORM_NAME)\"", + "\"$(inherited)\"", + ); + MTL_ENABLE_DEBUG_INFO = NO; + OTHER_CPLUSPLUSFLAGS = ( + "$(OTHER_CFLAGS)", + "-DFOLLY_NO_CONFIG", + "-DFOLLY_MOBILE=1", + "-DFOLLY_USE_LIBCPP=1", + "-DFOLLY_CFG_NO_COROUTINES=1", + "-DFOLLY_HAVE_CLOCK_GETTIME=1", + ); + REACT_NATIVE_PATH = "${PODS_ROOT}/../../node_modules/react-native"; + SDKROOT = iphoneos; + USE_HERMES = true; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 13B07F931A680F5B00A75B9A /* Build configuration list for PBXNativeTarget "BareFlowMetaMaskDemo" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 13B07F941A680F5B00A75B9A /* Debug */, + 13B07F951A680F5B00A75B9A /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 83CBB9FA1A601CBA00E9B192 /* Build configuration list for PBXProject "BareFlowMetaMaskDemo" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 83CBBA201A601CBA00E9B192 /* Debug */, + 83CBBA211A601CBA00E9B192 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 83CBB9F71A601CBA00E9B192 /* Project object */; +} diff --git a/examples/bare-react-native-with-js-sdk-and-flow/ios/BareFlowMetaMaskDemo.xcodeproj/xcshareddata/xcschemes/BareFlowMetaMaskDemo.xcscheme b/examples/bare-react-native-with-js-sdk-and-flow/ios/BareFlowMetaMaskDemo.xcodeproj/xcshareddata/xcschemes/BareFlowMetaMaskDemo.xcscheme new file mode 100644 index 0000000..ae8dba3 --- /dev/null +++ b/examples/bare-react-native-with-js-sdk-and-flow/ios/BareFlowMetaMaskDemo.xcodeproj/xcshareddata/xcschemes/BareFlowMetaMaskDemo.xcscheme @@ -0,0 +1,88 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/bare-react-native-with-js-sdk-and-flow/ios/BareFlowMetaMaskDemo.xcworkspace/contents.xcworkspacedata b/examples/bare-react-native-with-js-sdk-and-flow/ios/BareFlowMetaMaskDemo.xcworkspace/contents.xcworkspacedata new file mode 100644 index 0000000..7b0e87c --- /dev/null +++ b/examples/bare-react-native-with-js-sdk-and-flow/ios/BareFlowMetaMaskDemo.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,10 @@ + + + + + + + diff --git a/examples/bare-react-native-with-js-sdk-and-flow/ios/BareFlowMetaMaskDemo/AppDelegate.swift b/examples/bare-react-native-with-js-sdk-and-flow/ios/BareFlowMetaMaskDemo/AppDelegate.swift new file mode 100644 index 0000000..181976f --- /dev/null +++ b/examples/bare-react-native-with-js-sdk-and-flow/ios/BareFlowMetaMaskDemo/AppDelegate.swift @@ -0,0 +1,61 @@ +import UIKit +import React +import React_RCTAppDelegate +import ReactAppDependencyProvider + +@main +class AppDelegate: UIResponder, UIApplicationDelegate { + var window: UIWindow? + + var reactNativeDelegate: ReactNativeDelegate? + var reactNativeFactory: RCTReactNativeFactory? + + func application( + _ application: UIApplication, + didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? = nil + ) -> Bool { + let delegate = ReactNativeDelegate() + let factory = RCTReactNativeFactory(delegate: delegate) + delegate.dependencyProvider = RCTAppDependencyProvider() + + reactNativeDelegate = delegate + reactNativeFactory = factory + + window = UIWindow(frame: UIScreen.main.bounds) + + factory.startReactNative( + withModuleName: "BareFlowMetaMaskDemo", + in: window, + launchOptions: launchOptions + ) + + return true + } + + // Forwards incoming bareflowmetamaskdemo:// URLs (see Info.plist's + // CFBundleURLTypes and dynamicClient.ts's metadata.nativeLink) to RN's + // Linking module, so JS-level Linking.getInitialURL()/'url' listeners + // actually fire. The OS foregrounds the app on a registered scheme + // regardless of this method, but without it RN never finds out why. + func application( + _ app: UIApplication, + open url: URL, + options: [UIApplication.OpenURLOptionsKey: Any] = [:] + ) -> Bool { + return RCTLinkingManager.application(app, open: url, options: options) + } +} + +class ReactNativeDelegate: RCTDefaultReactNativeFactoryDelegate { + override func sourceURL(for bridge: RCTBridge) -> URL? { + self.bundleURL() + } + + override func bundleURL() -> URL? { +#if DEBUG + RCTBundleURLProvider.sharedSettings().jsBundleURL(forBundleRoot: "index") +#else + Bundle.main.url(forResource: "main", withExtension: "jsbundle") +#endif + } +} diff --git a/examples/bare-react-native-with-js-sdk-and-flow/ios/BareFlowMetaMaskDemo/Images.xcassets/AppIcon.appiconset/Contents.json b/examples/bare-react-native-with-js-sdk-and-flow/ios/BareFlowMetaMaskDemo/Images.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 0000000..8121323 --- /dev/null +++ b/examples/bare-react-native-with-js-sdk-and-flow/ios/BareFlowMetaMaskDemo/Images.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,53 @@ +{ + "images" : [ + { + "idiom" : "iphone", + "scale" : "2x", + "size" : "20x20" + }, + { + "idiom" : "iphone", + "scale" : "3x", + "size" : "20x20" + }, + { + "idiom" : "iphone", + "scale" : "2x", + "size" : "29x29" + }, + { + "idiom" : "iphone", + "scale" : "3x", + "size" : "29x29" + }, + { + "idiom" : "iphone", + "scale" : "2x", + "size" : "40x40" + }, + { + "idiom" : "iphone", + "scale" : "3x", + "size" : "40x40" + }, + { + "idiom" : "iphone", + "scale" : "2x", + "size" : "60x60" + }, + { + "idiom" : "iphone", + "scale" : "3x", + "size" : "60x60" + }, + { + "idiom" : "ios-marketing", + "scale" : "1x", + "size" : "1024x1024" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/examples/bare-react-native-with-js-sdk-and-flow/ios/BareFlowMetaMaskDemo/Images.xcassets/Contents.json b/examples/bare-react-native-with-js-sdk-and-flow/ios/BareFlowMetaMaskDemo/Images.xcassets/Contents.json new file mode 100644 index 0000000..2d92bd5 --- /dev/null +++ b/examples/bare-react-native-with-js-sdk-and-flow/ios/BareFlowMetaMaskDemo/Images.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "version" : 1, + "author" : "xcode" + } +} diff --git a/examples/bare-react-native-with-js-sdk-and-flow/ios/BareFlowMetaMaskDemo/Info.plist b/examples/bare-react-native-with-js-sdk-and-flow/ios/BareFlowMetaMaskDemo/Info.plist new file mode 100644 index 0000000..1590ab1 --- /dev/null +++ b/examples/bare-react-native-with-js-sdk-and-flow/ios/BareFlowMetaMaskDemo/Info.plist @@ -0,0 +1,68 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleDisplayName + BareFlowMetaMaskDemo + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + APPL + CFBundleShortVersionString + $(MARKETING_VERSION) + CFBundleSignature + ???? + CFBundleVersion + $(CURRENT_PROJECT_VERSION) + LSRequiresIPhoneOS + + CFBundleURLTypes + + + + CFBundleURLName + com.dynamiclabs.examples.bareflowmetamaskdemo + CFBundleURLSchemes + + bareflowmetamaskdemo + + + + NSAppTransportSecurity + + NSAllowsArbitraryLoads + + NSAllowsLocalNetworking + + + NSLocationWhenInUseUsageDescription + + RCTNewArchEnabled + + UILaunchStoryboardName + LaunchScreen + UIRequiredDeviceCapabilities + + arm64 + + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + + UIViewControllerBasedStatusBarAppearance + + + diff --git a/examples/bare-react-native-with-js-sdk-and-flow/ios/BareFlowMetaMaskDemo/LaunchScreen.storyboard b/examples/bare-react-native-with-js-sdk-and-flow/ios/BareFlowMetaMaskDemo/LaunchScreen.storyboard new file mode 100644 index 0000000..28c43ba --- /dev/null +++ b/examples/bare-react-native-with-js-sdk-and-flow/ios/BareFlowMetaMaskDemo/LaunchScreen.storyboard @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/bare-react-native-with-js-sdk-and-flow/ios/BareFlowMetaMaskDemo/PrivacyInfo.xcprivacy b/examples/bare-react-native-with-js-sdk-and-flow/ios/BareFlowMetaMaskDemo/PrivacyInfo.xcprivacy new file mode 100644 index 0000000..41b8317 --- /dev/null +++ b/examples/bare-react-native-with-js-sdk-and-flow/ios/BareFlowMetaMaskDemo/PrivacyInfo.xcprivacy @@ -0,0 +1,37 @@ + + + + + NSPrivacyAccessedAPITypes + + + NSPrivacyAccessedAPIType + NSPrivacyAccessedAPICategoryFileTimestamp + NSPrivacyAccessedAPITypeReasons + + C617.1 + + + + NSPrivacyAccessedAPIType + NSPrivacyAccessedAPICategoryUserDefaults + NSPrivacyAccessedAPITypeReasons + + CA92.1 + + + + NSPrivacyAccessedAPIType + NSPrivacyAccessedAPICategorySystemBootTime + NSPrivacyAccessedAPITypeReasons + + 35F9.1 + + + + NSPrivacyCollectedDataTypes + + NSPrivacyTracking + + + diff --git a/examples/bare-react-native-with-js-sdk-and-flow/ios/Podfile b/examples/bare-react-native-with-js-sdk-and-flow/ios/Podfile new file mode 100644 index 0000000..b1435f0 --- /dev/null +++ b/examples/bare-react-native-with-js-sdk-and-flow/ios/Podfile @@ -0,0 +1,108 @@ +# --- Why this line exists: NOT a required step for using Dynamic's SDK --- +# +# This works around a machine/toolchain-specific problem, not something +# wrong with this app's code or with Dynamic's SDK. If your own project +# builds fine with the default (prebuilt) Hermes, you almost certainly +# don't need this — most people won't. It's kept here because this +# example's own dev/CI environment hit it and the fix is a safe, harmless +# default for anyone else who might. +# +# The problem: React Native 0.81.4's hermes-engine pod defaults to a +# prebuilt XCFramework compiled by Meta with whatever Xcode was current +# at RN 0.81.4's release time. Building with a *much newer* Xcode (26+, +# here) than that prebuilt binary was compiled with is a C++ ABI mismatch +# waiting to happen — confirmed the hard way in this repo: physical +# Release builds crashed on every single launch with EXC_BAD_ACCESS/SIGSEGV +# inside HermesRuntimeImpl's debugger/inspector setup +# (ReactInstance::initializeRuntime's runtime-install callback), 100% +# reproducible, before any app JS ever ran. Debug-on-Simulator never showed +# it (Simulator + Debug wasn't exercising the prebuilt binary's actual ABI +# boundary the same way). If you're on an Xcode version released closer to +# when your pinned React Native version shipped, the prebuilt binary and +# your compiler are ABI-compatible and this mismatch simply doesn't occur. +# +# The fix: forcing Hermes to build from source instead compiles it with +# this project's own Xcode toolchain, eliminating the mismatch entirely — +# confirmed fixed on-device after this change. The tradeoff is a one-time +# (cached by DerivedData afterwards) extra native compile of Hermes itself +# on the next `pod install` + build (well under 10 minutes on this +# project's dev machine), which is why this isn't just always the React +# Native default upstream. This also shifts a dependency onto GitHub +# connectivity (cloning Hermes's source at a pinned tag) rather than Maven +# Central, for every configuration -- including Debug-on-Simulator builds +# that were never affected by the crash in the first place. We apply it +# project-wide rather than scoping it to just Release because CocoaPods +# resolves one Podspec graph for all configurations in a single +# `pod install` -- there's no clean way to make this Debug/Release- +# conditional at the Podfile level. +# +# Why a Podfile default and not an env var you pass by hand, or a wrapper +# script around `pod install`: this needs to apply automatically to every +# future `pod install`/`bundle exec pod install` — including CI, including +# anyone else who clones this repo — for every configuration (Debug and +# Release) and target (Simulator and device) — not just the +# Release-on-device combination that happened to surface it here. A +# command you have to remember to run is a command someone eventually +# forgets to run. `||=` still allows an explicit override (e.g. +# HERMES_ENGINE_TARBALL_PATH workflows) by whoever's running the install. +# See hermes-utils.rb in react-native's own scripts for the full +# source-selection logic this feeds into. +ENV['RCT_BUILD_HERMES_FROM_SOURCE'] ||= 'true' + +# Resolve react_native_pods.rb with node to allow for hoisting +require Pod::Executable.execute_command('node', ['-p', + 'require.resolve( + "react-native/scripts/react_native_pods.rb", + {paths: [process.argv[1]]}, + )', __dir__]).strip + +platform :ios, min_ios_version_supported +prepare_react_native_project! + +linkage = ENV['USE_FRAMEWORKS'] +if linkage != nil + Pod::UI.puts "Configuring Pod with #{linkage}ally linked Frameworks".green + use_frameworks! :linkage => linkage.to_sym +end + +target 'BareFlowMetaMaskDemo' do + config = use_native_modules! + + use_react_native!( + :path => config[:reactNativePath], + # An absolute path to your application root. + :app_path => "#{Pod::Config.instance.installation_root}/.." + ) + + post_install do |installer| + # https://github.com/facebook/react-native/blob/main/packages/react-native/scripts/react_native_pods.rb#L197-L202 + react_native_post_install( + installer, + config[:reactNativePath], + :mac_catalyst_enabled => false, + # :ccache_enabled => true + ) + + # Workaround: react-native 0.81.x vendors fmt 11.0.2, which mis-detects + # consteval support on very recent Clang toolchains (Xcode 26.x here), + # producing "call to consteval function ... is not a constant + # expression". This is a local build-only patch (not shipped as part of + # the app) that disables fmt's compile-time format-string validation -- + # a compile-time diagnostic only, with no runtime behavior change. + # Workaround for fmt compilation errors with Xcode 26+ (stricter consteval + # in Clang): fmt unconditionally sets FMT_USE_CONSTEVAL=1 when + # __cpp_consteval is defined, which Xcode 26's Clang rejects ("call to + # consteval function ... is not a constant expression"). Patches + # fmt/base.h to disable the consteval code path. `ios/Pods` is gitignored + # and regenerated by `pod install`, so this re-applies on every install. + fmt_base_header = File.join(__dir__, 'Pods', 'fmt', 'include', 'fmt', 'base.h') + if File.exist?(fmt_base_header) + content = File.read(fmt_base_header) + patched = content.gsub('define FMT_USE_CONSTEVAL 1', 'define FMT_USE_CONSTEVAL 0') + if patched != content + File.chmod(0644, fmt_base_header) + File.write(fmt_base_header, patched) + end + end + end +end diff --git a/examples/bare-react-native-with-js-sdk-and-flow/ios/Podfile.lock b/examples/bare-react-native-with-js-sdk-and-flow/ios/Podfile.lock new file mode 100644 index 0000000..aa0553b --- /dev/null +++ b/examples/bare-react-native-with-js-sdk-and-flow/ios/Podfile.lock @@ -0,0 +1,3050 @@ +PODS: + - boost (1.84.0) + - BVLinearGradient (2.8.3): + - React-Core + - DoubleConversion (1.1.6) + - dynamic-labs-sdk-client (1.28.0): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - RCTRequired + - RCTTypeSafety + - React-Core + - React-debug + - React-Fabric + - React-featureflags + - React-graphics + - React-ImageManager + - React-jsi + - React-NativeModulesApple + - React-RCTFabric + - React-renderercss + - React-rendererdebug + - React-utils + - ReactCodegen + - ReactCommon/turbomodule/bridging + - ReactCommon/turbomodule/core + - SocketRocket + - Yoga + - fast_float (8.0.0) + - FBLazyVector (0.81.4) + - fmt (11.0.2) + - glog (0.3.5) + - hermes-engine (0.81.4): + - hermes-engine/cdp (= 0.81.4) + - hermes-engine/Hermes (= 0.81.4) + - hermes-engine/inspector (= 0.81.4) + - hermes-engine/inspector_chrome (= 0.81.4) + - hermes-engine/Public (= 0.81.4) + - hermes-engine/cdp (0.81.4) + - hermes-engine/Hermes (0.81.4) + - hermes-engine/inspector (0.81.4) + - hermes-engine/inspector_chrome (0.81.4) + - hermes-engine/Public (0.81.4) + - RCT-Folly (2024.11.18.00): + - boost + - DoubleConversion + - fast_float (= 8.0.0) + - fmt (= 11.0.2) + - glog + - RCT-Folly/Default (= 2024.11.18.00) + - RCT-Folly/Default (2024.11.18.00): + - boost + - DoubleConversion + - fast_float (= 8.0.0) + - fmt (= 11.0.2) + - glog + - RCT-Folly/Fabric (2024.11.18.00): + - boost + - DoubleConversion + - fast_float (= 8.0.0) + - fmt (= 11.0.2) + - glog + - RCTDeprecation (0.81.4) + - RCTRequired (0.81.4) + - RCTTypeSafety (0.81.4): + - FBLazyVector (= 0.81.4) + - RCTRequired (= 0.81.4) + - React-Core (= 0.81.4) + - React (0.81.4): + - React-Core (= 0.81.4) + - React-Core/DevSupport (= 0.81.4) + - React-Core/RCTWebSocket (= 0.81.4) + - React-RCTActionSheet (= 0.81.4) + - React-RCTAnimation (= 0.81.4) + - React-RCTBlob (= 0.81.4) + - React-RCTImage (= 0.81.4) + - React-RCTLinking (= 0.81.4) + - React-RCTNetwork (= 0.81.4) + - React-RCTSettings (= 0.81.4) + - React-RCTText (= 0.81.4) + - React-RCTVibration (= 0.81.4) + - React-callinvoker (0.81.4) + - React-Core (0.81.4): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - RCTDeprecation + - React-Core/Default (= 0.81.4) + - React-cxxreact + - React-featureflags + - React-hermes + - React-jsi + - React-jsiexecutor + - React-jsinspector + - React-jsinspectorcdp + - React-jsitooling + - React-perflogger + - React-runtimeexecutor + - React-runtimescheduler + - React-utils + - SocketRocket + - Yoga + - React-Core/CoreModulesHeaders (0.81.4): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - RCTDeprecation + - React-Core/Default + - React-cxxreact + - React-featureflags + - React-hermes + - React-jsi + - React-jsiexecutor + - React-jsinspector + - React-jsinspectorcdp + - React-jsitooling + - React-perflogger + - React-runtimeexecutor + - React-runtimescheduler + - React-utils + - SocketRocket + - Yoga + - React-Core/Default (0.81.4): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - RCTDeprecation + - React-cxxreact + - React-featureflags + - React-hermes + - React-jsi + - React-jsiexecutor + - React-jsinspector + - React-jsinspectorcdp + - React-jsitooling + - React-perflogger + - React-runtimeexecutor + - React-runtimescheduler + - React-utils + - SocketRocket + - Yoga + - React-Core/DevSupport (0.81.4): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - RCTDeprecation + - React-Core/Default (= 0.81.4) + - React-Core/RCTWebSocket (= 0.81.4) + - React-cxxreact + - React-featureflags + - React-hermes + - React-jsi + - React-jsiexecutor + - React-jsinspector + - React-jsinspectorcdp + - React-jsitooling + - React-perflogger + - React-runtimeexecutor + - React-runtimescheduler + - React-utils + - SocketRocket + - Yoga + - React-Core/RCTActionSheetHeaders (0.81.4): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - RCTDeprecation + - React-Core/Default + - React-cxxreact + - React-featureflags + - React-hermes + - React-jsi + - React-jsiexecutor + - React-jsinspector + - React-jsinspectorcdp + - React-jsitooling + - React-perflogger + - React-runtimeexecutor + - React-runtimescheduler + - React-utils + - SocketRocket + - Yoga + - React-Core/RCTAnimationHeaders (0.81.4): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - RCTDeprecation + - React-Core/Default + - React-cxxreact + - React-featureflags + - React-hermes + - React-jsi + - React-jsiexecutor + - React-jsinspector + - React-jsinspectorcdp + - React-jsitooling + - React-perflogger + - React-runtimeexecutor + - React-runtimescheduler + - React-utils + - SocketRocket + - Yoga + - React-Core/RCTBlobHeaders (0.81.4): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - RCTDeprecation + - React-Core/Default + - React-cxxreact + - React-featureflags + - React-hermes + - React-jsi + - React-jsiexecutor + - React-jsinspector + - React-jsinspectorcdp + - React-jsitooling + - React-perflogger + - React-runtimeexecutor + - React-runtimescheduler + - React-utils + - SocketRocket + - Yoga + - React-Core/RCTImageHeaders (0.81.4): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - RCTDeprecation + - React-Core/Default + - React-cxxreact + - React-featureflags + - React-hermes + - React-jsi + - React-jsiexecutor + - React-jsinspector + - React-jsinspectorcdp + - React-jsitooling + - React-perflogger + - React-runtimeexecutor + - React-runtimescheduler + - React-utils + - SocketRocket + - Yoga + - React-Core/RCTLinkingHeaders (0.81.4): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - RCTDeprecation + - React-Core/Default + - React-cxxreact + - React-featureflags + - React-hermes + - React-jsi + - React-jsiexecutor + - React-jsinspector + - React-jsinspectorcdp + - React-jsitooling + - React-perflogger + - React-runtimeexecutor + - React-runtimescheduler + - React-utils + - SocketRocket + - Yoga + - React-Core/RCTNetworkHeaders (0.81.4): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - RCTDeprecation + - React-Core/Default + - React-cxxreact + - React-featureflags + - React-hermes + - React-jsi + - React-jsiexecutor + - React-jsinspector + - React-jsinspectorcdp + - React-jsitooling + - React-perflogger + - React-runtimeexecutor + - React-runtimescheduler + - React-utils + - SocketRocket + - Yoga + - React-Core/RCTSettingsHeaders (0.81.4): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - RCTDeprecation + - React-Core/Default + - React-cxxreact + - React-featureflags + - React-hermes + - React-jsi + - React-jsiexecutor + - React-jsinspector + - React-jsinspectorcdp + - React-jsitooling + - React-perflogger + - React-runtimeexecutor + - React-runtimescheduler + - React-utils + - SocketRocket + - Yoga + - React-Core/RCTTextHeaders (0.81.4): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - RCTDeprecation + - React-Core/Default + - React-cxxreact + - React-featureflags + - React-hermes + - React-jsi + - React-jsiexecutor + - React-jsinspector + - React-jsinspectorcdp + - React-jsitooling + - React-perflogger + - React-runtimeexecutor + - React-runtimescheduler + - React-utils + - SocketRocket + - Yoga + - React-Core/RCTVibrationHeaders (0.81.4): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - RCTDeprecation + - React-Core/Default + - React-cxxreact + - React-featureflags + - React-hermes + - React-jsi + - React-jsiexecutor + - React-jsinspector + - React-jsinspectorcdp + - React-jsitooling + - React-perflogger + - React-runtimeexecutor + - React-runtimescheduler + - React-utils + - SocketRocket + - Yoga + - React-Core/RCTWebSocket (0.81.4): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - RCTDeprecation + - React-Core/Default (= 0.81.4) + - React-cxxreact + - React-featureflags + - React-hermes + - React-jsi + - React-jsiexecutor + - React-jsinspector + - React-jsinspectorcdp + - React-jsitooling + - React-perflogger + - React-runtimeexecutor + - React-runtimescheduler + - React-utils + - SocketRocket + - Yoga + - React-CoreModules (0.81.4): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - RCT-Folly + - RCT-Folly/Fabric + - RCTTypeSafety (= 0.81.4) + - React-Core/CoreModulesHeaders (= 0.81.4) + - React-jsi (= 0.81.4) + - React-jsinspector + - React-jsinspectorcdp + - React-jsinspectortracing + - React-NativeModulesApple + - React-RCTBlob + - React-RCTFBReactNativeSpec + - React-RCTImage (= 0.81.4) + - React-runtimeexecutor + - ReactCommon + - SocketRocket + - React-cxxreact (0.81.4): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - React-callinvoker (= 0.81.4) + - React-debug (= 0.81.4) + - React-jsi (= 0.81.4) + - React-jsinspector + - React-jsinspectorcdp + - React-jsinspectortracing + - React-logger (= 0.81.4) + - React-perflogger (= 0.81.4) + - React-runtimeexecutor + - React-timing (= 0.81.4) + - SocketRocket + - React-debug (0.81.4) + - React-defaultsnativemodule (0.81.4): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - React-domnativemodule + - React-featureflagsnativemodule + - React-idlecallbacksnativemodule + - React-jsi + - React-jsiexecutor + - React-microtasksnativemodule + - React-RCTFBReactNativeSpec + - SocketRocket + - React-domnativemodule (0.81.4): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - React-Fabric + - React-Fabric/bridging + - React-FabricComponents + - React-graphics + - React-jsi + - React-jsiexecutor + - React-RCTFBReactNativeSpec + - React-runtimeexecutor + - ReactCommon/turbomodule/core + - SocketRocket + - Yoga + - React-Fabric (0.81.4): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - RCTRequired + - RCTTypeSafety + - React-Core + - React-cxxreact + - React-debug + - React-Fabric/animations (= 0.81.4) + - React-Fabric/attributedstring (= 0.81.4) + - React-Fabric/bridging (= 0.81.4) + - React-Fabric/componentregistry (= 0.81.4) + - React-Fabric/componentregistrynative (= 0.81.4) + - React-Fabric/components (= 0.81.4) + - React-Fabric/consistency (= 0.81.4) + - React-Fabric/core (= 0.81.4) + - React-Fabric/dom (= 0.81.4) + - React-Fabric/imagemanager (= 0.81.4) + - React-Fabric/leakchecker (= 0.81.4) + - React-Fabric/mounting (= 0.81.4) + - React-Fabric/observers (= 0.81.4) + - React-Fabric/scheduler (= 0.81.4) + - React-Fabric/telemetry (= 0.81.4) + - React-Fabric/templateprocessor (= 0.81.4) + - React-Fabric/uimanager (= 0.81.4) + - React-featureflags + - React-graphics + - React-jsi + - React-jsiexecutor + - React-logger + - React-rendererdebug + - React-runtimeexecutor + - React-runtimescheduler + - React-utils + - ReactCommon/turbomodule/core + - SocketRocket + - React-Fabric/animations (0.81.4): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - RCTRequired + - RCTTypeSafety + - React-Core + - React-cxxreact + - React-debug + - React-featureflags + - React-graphics + - React-jsi + - React-jsiexecutor + - React-logger + - React-rendererdebug + - React-runtimeexecutor + - React-runtimescheduler + - React-utils + - ReactCommon/turbomodule/core + - SocketRocket + - React-Fabric/attributedstring (0.81.4): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - RCTRequired + - RCTTypeSafety + - React-Core + - React-cxxreact + - React-debug + - React-featureflags + - React-graphics + - React-jsi + - React-jsiexecutor + - React-logger + - React-rendererdebug + - React-runtimeexecutor + - React-runtimescheduler + - React-utils + - ReactCommon/turbomodule/core + - SocketRocket + - React-Fabric/bridging (0.81.4): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - RCTRequired + - RCTTypeSafety + - React-Core + - React-cxxreact + - React-debug + - React-featureflags + - React-graphics + - React-jsi + - React-jsiexecutor + - React-logger + - React-rendererdebug + - React-runtimeexecutor + - React-runtimescheduler + - React-utils + - ReactCommon/turbomodule/core + - SocketRocket + - React-Fabric/componentregistry (0.81.4): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - RCTRequired + - RCTTypeSafety + - React-Core + - React-cxxreact + - React-debug + - React-featureflags + - React-graphics + - React-jsi + - React-jsiexecutor + - React-logger + - React-rendererdebug + - React-runtimeexecutor + - React-runtimescheduler + - React-utils + - ReactCommon/turbomodule/core + - SocketRocket + - React-Fabric/componentregistrynative (0.81.4): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - RCTRequired + - RCTTypeSafety + - React-Core + - React-cxxreact + - React-debug + - React-featureflags + - React-graphics + - React-jsi + - React-jsiexecutor + - React-logger + - React-rendererdebug + - React-runtimeexecutor + - React-runtimescheduler + - React-utils + - ReactCommon/turbomodule/core + - SocketRocket + - React-Fabric/components (0.81.4): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - RCTRequired + - RCTTypeSafety + - React-Core + - React-cxxreact + - React-debug + - React-Fabric/components/legacyviewmanagerinterop (= 0.81.4) + - React-Fabric/components/root (= 0.81.4) + - React-Fabric/components/scrollview (= 0.81.4) + - React-Fabric/components/view (= 0.81.4) + - React-featureflags + - React-graphics + - React-jsi + - React-jsiexecutor + - React-logger + - React-rendererdebug + - React-runtimeexecutor + - React-runtimescheduler + - React-utils + - ReactCommon/turbomodule/core + - SocketRocket + - React-Fabric/components/legacyviewmanagerinterop (0.81.4): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - RCTRequired + - RCTTypeSafety + - React-Core + - React-cxxreact + - React-debug + - React-featureflags + - React-graphics + - React-jsi + - React-jsiexecutor + - React-logger + - React-rendererdebug + - React-runtimeexecutor + - React-runtimescheduler + - React-utils + - ReactCommon/turbomodule/core + - SocketRocket + - React-Fabric/components/root (0.81.4): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - RCTRequired + - RCTTypeSafety + - React-Core + - React-cxxreact + - React-debug + - React-featureflags + - React-graphics + - React-jsi + - React-jsiexecutor + - React-logger + - React-rendererdebug + - React-runtimeexecutor + - React-runtimescheduler + - React-utils + - ReactCommon/turbomodule/core + - SocketRocket + - React-Fabric/components/scrollview (0.81.4): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - RCTRequired + - RCTTypeSafety + - React-Core + - React-cxxreact + - React-debug + - React-featureflags + - React-graphics + - React-jsi + - React-jsiexecutor + - React-logger + - React-rendererdebug + - React-runtimeexecutor + - React-runtimescheduler + - React-utils + - ReactCommon/turbomodule/core + - SocketRocket + - React-Fabric/components/view (0.81.4): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - RCTRequired + - RCTTypeSafety + - React-Core + - React-cxxreact + - React-debug + - React-featureflags + - React-graphics + - React-jsi + - React-jsiexecutor + - React-logger + - React-renderercss + - React-rendererdebug + - React-runtimeexecutor + - React-runtimescheduler + - React-utils + - ReactCommon/turbomodule/core + - SocketRocket + - Yoga + - React-Fabric/consistency (0.81.4): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - RCTRequired + - RCTTypeSafety + - React-Core + - React-cxxreact + - React-debug + - React-featureflags + - React-graphics + - React-jsi + - React-jsiexecutor + - React-logger + - React-rendererdebug + - React-runtimeexecutor + - React-runtimescheduler + - React-utils + - ReactCommon/turbomodule/core + - SocketRocket + - React-Fabric/core (0.81.4): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - RCTRequired + - RCTTypeSafety + - React-Core + - React-cxxreact + - React-debug + - React-featureflags + - React-graphics + - React-jsi + - React-jsiexecutor + - React-logger + - React-rendererdebug + - React-runtimeexecutor + - React-runtimescheduler + - React-utils + - ReactCommon/turbomodule/core + - SocketRocket + - React-Fabric/dom (0.81.4): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - RCTRequired + - RCTTypeSafety + - React-Core + - React-cxxreact + - React-debug + - React-featureflags + - React-graphics + - React-jsi + - React-jsiexecutor + - React-logger + - React-rendererdebug + - React-runtimeexecutor + - React-runtimescheduler + - React-utils + - ReactCommon/turbomodule/core + - SocketRocket + - React-Fabric/imagemanager (0.81.4): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - RCTRequired + - RCTTypeSafety + - React-Core + - React-cxxreact + - React-debug + - React-featureflags + - React-graphics + - React-jsi + - React-jsiexecutor + - React-logger + - React-rendererdebug + - React-runtimeexecutor + - React-runtimescheduler + - React-utils + - ReactCommon/turbomodule/core + - SocketRocket + - React-Fabric/leakchecker (0.81.4): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - RCTRequired + - RCTTypeSafety + - React-Core + - React-cxxreact + - React-debug + - React-featureflags + - React-graphics + - React-jsi + - React-jsiexecutor + - React-logger + - React-rendererdebug + - React-runtimeexecutor + - React-runtimescheduler + - React-utils + - ReactCommon/turbomodule/core + - SocketRocket + - React-Fabric/mounting (0.81.4): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - RCTRequired + - RCTTypeSafety + - React-Core + - React-cxxreact + - React-debug + - React-featureflags + - React-graphics + - React-jsi + - React-jsiexecutor + - React-logger + - React-rendererdebug + - React-runtimeexecutor + - React-runtimescheduler + - React-utils + - ReactCommon/turbomodule/core + - SocketRocket + - React-Fabric/observers (0.81.4): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - RCTRequired + - RCTTypeSafety + - React-Core + - React-cxxreact + - React-debug + - React-Fabric/observers/events (= 0.81.4) + - React-featureflags + - React-graphics + - React-jsi + - React-jsiexecutor + - React-logger + - React-rendererdebug + - React-runtimeexecutor + - React-runtimescheduler + - React-utils + - ReactCommon/turbomodule/core + - SocketRocket + - React-Fabric/observers/events (0.81.4): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - RCTRequired + - RCTTypeSafety + - React-Core + - React-cxxreact + - React-debug + - React-featureflags + - React-graphics + - React-jsi + - React-jsiexecutor + - React-logger + - React-rendererdebug + - React-runtimeexecutor + - React-runtimescheduler + - React-utils + - ReactCommon/turbomodule/core + - SocketRocket + - React-Fabric/scheduler (0.81.4): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - RCTRequired + - RCTTypeSafety + - React-Core + - React-cxxreact + - React-debug + - React-Fabric/observers/events + - React-featureflags + - React-graphics + - React-jsi + - React-jsiexecutor + - React-logger + - React-performancetimeline + - React-rendererdebug + - React-runtimeexecutor + - React-runtimescheduler + - React-utils + - ReactCommon/turbomodule/core + - SocketRocket + - React-Fabric/telemetry (0.81.4): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - RCTRequired + - RCTTypeSafety + - React-Core + - React-cxxreact + - React-debug + - React-featureflags + - React-graphics + - React-jsi + - React-jsiexecutor + - React-logger + - React-rendererdebug + - React-runtimeexecutor + - React-runtimescheduler + - React-utils + - ReactCommon/turbomodule/core + - SocketRocket + - React-Fabric/templateprocessor (0.81.4): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - RCTRequired + - RCTTypeSafety + - React-Core + - React-cxxreact + - React-debug + - React-featureflags + - React-graphics + - React-jsi + - React-jsiexecutor + - React-logger + - React-rendererdebug + - React-runtimeexecutor + - React-runtimescheduler + - React-utils + - ReactCommon/turbomodule/core + - SocketRocket + - React-Fabric/uimanager (0.81.4): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - RCTRequired + - RCTTypeSafety + - React-Core + - React-cxxreact + - React-debug + - React-Fabric/uimanager/consistency (= 0.81.4) + - React-featureflags + - React-graphics + - React-jsi + - React-jsiexecutor + - React-logger + - React-rendererconsistency + - React-rendererdebug + - React-runtimeexecutor + - React-runtimescheduler + - React-utils + - ReactCommon/turbomodule/core + - SocketRocket + - React-Fabric/uimanager/consistency (0.81.4): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - RCTRequired + - RCTTypeSafety + - React-Core + - React-cxxreact + - React-debug + - React-featureflags + - React-graphics + - React-jsi + - React-jsiexecutor + - React-logger + - React-rendererconsistency + - React-rendererdebug + - React-runtimeexecutor + - React-runtimescheduler + - React-utils + - ReactCommon/turbomodule/core + - SocketRocket + - React-FabricComponents (0.81.4): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - RCTRequired + - RCTTypeSafety + - React-Core + - React-cxxreact + - React-debug + - React-Fabric + - React-FabricComponents/components (= 0.81.4) + - React-FabricComponents/textlayoutmanager (= 0.81.4) + - React-featureflags + - React-graphics + - React-jsi + - React-jsiexecutor + - React-logger + - React-RCTFBReactNativeSpec + - React-rendererdebug + - React-runtimescheduler + - React-utils + - ReactCommon/turbomodule/core + - SocketRocket + - Yoga + - React-FabricComponents/components (0.81.4): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - RCTRequired + - RCTTypeSafety + - React-Core + - React-cxxreact + - React-debug + - React-Fabric + - React-FabricComponents/components/inputaccessory (= 0.81.4) + - React-FabricComponents/components/iostextinput (= 0.81.4) + - React-FabricComponents/components/modal (= 0.81.4) + - React-FabricComponents/components/rncore (= 0.81.4) + - React-FabricComponents/components/safeareaview (= 0.81.4) + - React-FabricComponents/components/scrollview (= 0.81.4) + - React-FabricComponents/components/switch (= 0.81.4) + - React-FabricComponents/components/text (= 0.81.4) + - React-FabricComponents/components/textinput (= 0.81.4) + - React-FabricComponents/components/unimplementedview (= 0.81.4) + - React-FabricComponents/components/virtualview (= 0.81.4) + - React-featureflags + - React-graphics + - React-jsi + - React-jsiexecutor + - React-logger + - React-RCTFBReactNativeSpec + - React-rendererdebug + - React-runtimescheduler + - React-utils + - ReactCommon/turbomodule/core + - SocketRocket + - Yoga + - React-FabricComponents/components/inputaccessory (0.81.4): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - RCTRequired + - RCTTypeSafety + - React-Core + - React-cxxreact + - React-debug + - React-Fabric + - React-featureflags + - React-graphics + - React-jsi + - React-jsiexecutor + - React-logger + - React-RCTFBReactNativeSpec + - React-rendererdebug + - React-runtimescheduler + - React-utils + - ReactCommon/turbomodule/core + - SocketRocket + - Yoga + - React-FabricComponents/components/iostextinput (0.81.4): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - RCTRequired + - RCTTypeSafety + - React-Core + - React-cxxreact + - React-debug + - React-Fabric + - React-featureflags + - React-graphics + - React-jsi + - React-jsiexecutor + - React-logger + - React-RCTFBReactNativeSpec + - React-rendererdebug + - React-runtimescheduler + - React-utils + - ReactCommon/turbomodule/core + - SocketRocket + - Yoga + - React-FabricComponents/components/modal (0.81.4): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - RCTRequired + - RCTTypeSafety + - React-Core + - React-cxxreact + - React-debug + - React-Fabric + - React-featureflags + - React-graphics + - React-jsi + - React-jsiexecutor + - React-logger + - React-RCTFBReactNativeSpec + - React-rendererdebug + - React-runtimescheduler + - React-utils + - ReactCommon/turbomodule/core + - SocketRocket + - Yoga + - React-FabricComponents/components/rncore (0.81.4): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - RCTRequired + - RCTTypeSafety + - React-Core + - React-cxxreact + - React-debug + - React-Fabric + - React-featureflags + - React-graphics + - React-jsi + - React-jsiexecutor + - React-logger + - React-RCTFBReactNativeSpec + - React-rendererdebug + - React-runtimescheduler + - React-utils + - ReactCommon/turbomodule/core + - SocketRocket + - Yoga + - React-FabricComponents/components/safeareaview (0.81.4): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - RCTRequired + - RCTTypeSafety + - React-Core + - React-cxxreact + - React-debug + - React-Fabric + - React-featureflags + - React-graphics + - React-jsi + - React-jsiexecutor + - React-logger + - React-RCTFBReactNativeSpec + - React-rendererdebug + - React-runtimescheduler + - React-utils + - ReactCommon/turbomodule/core + - SocketRocket + - Yoga + - React-FabricComponents/components/scrollview (0.81.4): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - RCTRequired + - RCTTypeSafety + - React-Core + - React-cxxreact + - React-debug + - React-Fabric + - React-featureflags + - React-graphics + - React-jsi + - React-jsiexecutor + - React-logger + - React-RCTFBReactNativeSpec + - React-rendererdebug + - React-runtimescheduler + - React-utils + - ReactCommon/turbomodule/core + - SocketRocket + - Yoga + - React-FabricComponents/components/switch (0.81.4): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - RCTRequired + - RCTTypeSafety + - React-Core + - React-cxxreact + - React-debug + - React-Fabric + - React-featureflags + - React-graphics + - React-jsi + - React-jsiexecutor + - React-logger + - React-RCTFBReactNativeSpec + - React-rendererdebug + - React-runtimescheduler + - React-utils + - ReactCommon/turbomodule/core + - SocketRocket + - Yoga + - React-FabricComponents/components/text (0.81.4): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - RCTRequired + - RCTTypeSafety + - React-Core + - React-cxxreact + - React-debug + - React-Fabric + - React-featureflags + - React-graphics + - React-jsi + - React-jsiexecutor + - React-logger + - React-RCTFBReactNativeSpec + - React-rendererdebug + - React-runtimescheduler + - React-utils + - ReactCommon/turbomodule/core + - SocketRocket + - Yoga + - React-FabricComponents/components/textinput (0.81.4): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - RCTRequired + - RCTTypeSafety + - React-Core + - React-cxxreact + - React-debug + - React-Fabric + - React-featureflags + - React-graphics + - React-jsi + - React-jsiexecutor + - React-logger + - React-RCTFBReactNativeSpec + - React-rendererdebug + - React-runtimescheduler + - React-utils + - ReactCommon/turbomodule/core + - SocketRocket + - Yoga + - React-FabricComponents/components/unimplementedview (0.81.4): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - RCTRequired + - RCTTypeSafety + - React-Core + - React-cxxreact + - React-debug + - React-Fabric + - React-featureflags + - React-graphics + - React-jsi + - React-jsiexecutor + - React-logger + - React-RCTFBReactNativeSpec + - React-rendererdebug + - React-runtimescheduler + - React-utils + - ReactCommon/turbomodule/core + - SocketRocket + - Yoga + - React-FabricComponents/components/virtualview (0.81.4): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - RCTRequired + - RCTTypeSafety + - React-Core + - React-cxxreact + - React-debug + - React-Fabric + - React-featureflags + - React-graphics + - React-jsi + - React-jsiexecutor + - React-logger + - React-RCTFBReactNativeSpec + - React-rendererdebug + - React-runtimescheduler + - React-utils + - ReactCommon/turbomodule/core + - SocketRocket + - Yoga + - React-FabricComponents/textlayoutmanager (0.81.4): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - RCTRequired + - RCTTypeSafety + - React-Core + - React-cxxreact + - React-debug + - React-Fabric + - React-featureflags + - React-graphics + - React-jsi + - React-jsiexecutor + - React-logger + - React-RCTFBReactNativeSpec + - React-rendererdebug + - React-runtimescheduler + - React-utils + - ReactCommon/turbomodule/core + - SocketRocket + - Yoga + - React-FabricImage (0.81.4): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - RCTRequired (= 0.81.4) + - RCTTypeSafety (= 0.81.4) + - React-Fabric + - React-featureflags + - React-graphics + - React-ImageManager + - React-jsi + - React-jsiexecutor (= 0.81.4) + - React-logger + - React-rendererdebug + - React-utils + - ReactCommon + - SocketRocket + - Yoga + - React-featureflags (0.81.4): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - RCT-Folly + - RCT-Folly/Fabric + - SocketRocket + - React-featureflagsnativemodule (0.81.4): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - React-featureflags + - React-jsi + - React-jsiexecutor + - React-RCTFBReactNativeSpec + - ReactCommon/turbomodule/core + - SocketRocket + - React-graphics (0.81.4): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - React-jsi + - React-jsiexecutor + - React-utils + - SocketRocket + - React-hermes (0.81.4): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - React-cxxreact (= 0.81.4) + - React-jsi + - React-jsiexecutor (= 0.81.4) + - React-jsinspector + - React-jsinspectorcdp + - React-jsinspectortracing + - React-perflogger (= 0.81.4) + - React-runtimeexecutor + - SocketRocket + - React-idlecallbacksnativemodule (0.81.4): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - React-jsi + - React-jsiexecutor + - React-RCTFBReactNativeSpec + - React-runtimeexecutor + - React-runtimescheduler + - ReactCommon/turbomodule/core + - SocketRocket + - React-ImageManager (0.81.4): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - RCT-Folly + - RCT-Folly/Fabric + - React-Core/Default + - React-debug + - React-Fabric + - React-graphics + - React-rendererdebug + - React-utils + - SocketRocket + - React-jserrorhandler (0.81.4): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - React-cxxreact + - React-debug + - React-featureflags + - React-jsi + - ReactCommon/turbomodule/bridging + - SocketRocket + - React-jsi (0.81.4): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - SocketRocket + - React-jsiexecutor (0.81.4): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - React-cxxreact (= 0.81.4) + - React-jsi (= 0.81.4) + - React-jsinspector + - React-jsinspectorcdp + - React-jsinspectortracing + - React-perflogger (= 0.81.4) + - React-runtimeexecutor + - SocketRocket + - React-jsinspector (0.81.4): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - React-featureflags + - React-jsi + - React-jsinspectorcdp + - React-jsinspectornetwork + - React-jsinspectortracing + - React-oscompat + - React-perflogger (= 0.81.4) + - React-runtimeexecutor + - SocketRocket + - React-jsinspectorcdp (0.81.4): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - RCT-Folly + - RCT-Folly/Fabric + - SocketRocket + - React-jsinspectornetwork (0.81.4): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - RCT-Folly + - RCT-Folly/Fabric + - React-featureflags + - React-jsinspectorcdp + - React-performancetimeline + - React-timing + - SocketRocket + - React-jsinspectortracing (0.81.4): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - RCT-Folly + - RCT-Folly/Fabric + - React-oscompat + - React-timing + - SocketRocket + - React-jsitooling (0.81.4): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - RCT-Folly + - RCT-Folly/Fabric + - React-cxxreact (= 0.81.4) + - React-jsi (= 0.81.4) + - React-jsinspector + - React-jsinspectorcdp + - React-jsinspectortracing + - React-runtimeexecutor + - SocketRocket + - React-jsitracing (0.81.4): + - React-jsi + - React-logger (0.81.4): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - RCT-Folly + - RCT-Folly/Fabric + - SocketRocket + - React-Mapbuffer (0.81.4): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - RCT-Folly + - RCT-Folly/Fabric + - React-debug + - SocketRocket + - React-microtasksnativemodule (0.81.4): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - React-jsi + - React-jsiexecutor + - React-RCTFBReactNativeSpec + - ReactCommon/turbomodule/core + - SocketRocket + - react-native-compat (2.21.8): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - RCTRequired + - RCTTypeSafety + - React-Core + - React-debug + - React-Fabric + - React-featureflags + - React-graphics + - React-ImageManager + - React-jsi + - React-NativeModulesApple + - React-RCTFabric + - React-renderercss + - React-rendererdebug + - React-utils + - ReactCodegen + - ReactCommon/turbomodule/bridging + - ReactCommon/turbomodule/core + - SocketRocket + - Yoga + - react-native-get-random-values (2.0.0): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - RCTRequired + - RCTTypeSafety + - React-Core + - React-debug + - React-Fabric + - React-featureflags + - React-graphics + - React-ImageManager + - React-jsi + - React-NativeModulesApple + - React-RCTFabric + - React-renderercss + - React-rendererdebug + - React-utils + - ReactCodegen + - ReactCommon/turbomodule/bridging + - ReactCommon/turbomodule/core + - SocketRocket + - Yoga + - react-native-netinfo (12.0.1): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - RCTRequired + - RCTTypeSafety + - React-Core + - React-debug + - React-Fabric + - React-featureflags + - React-graphics + - React-ImageManager + - React-jsi + - React-NativeModulesApple + - React-RCTFabric + - React-renderercss + - React-rendererdebug + - React-utils + - ReactCodegen + - ReactCommon/turbomodule/bridging + - ReactCommon/turbomodule/core + - SocketRocket + - Yoga + - react-native-passkey (3.5.0): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - RCTRequired + - RCTTypeSafety + - React-Core + - React-debug + - React-Fabric + - React-featureflags + - React-graphics + - React-ImageManager + - React-jsi + - React-NativeModulesApple + - React-RCTFabric + - React-renderercss + - React-rendererdebug + - React-utils + - ReactCodegen + - ReactCommon/turbomodule/bridging + - ReactCommon/turbomodule/core + - SocketRocket + - Yoga + - react-native-safe-area-context (5.5.2): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - RCTRequired + - RCTTypeSafety + - React-Core + - React-debug + - React-Fabric + - React-featureflags + - React-graphics + - React-ImageManager + - React-jsi + - react-native-safe-area-context/common (= 5.5.2) + - react-native-safe-area-context/fabric (= 5.5.2) + - React-NativeModulesApple + - React-RCTFabric + - React-renderercss + - React-rendererdebug + - React-utils + - ReactCodegen + - ReactCommon/turbomodule/bridging + - ReactCommon/turbomodule/core + - SocketRocket + - Yoga + - react-native-safe-area-context/common (5.5.2): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - RCTRequired + - RCTTypeSafety + - React-Core + - React-debug + - React-Fabric + - React-featureflags + - React-graphics + - React-ImageManager + - React-jsi + - React-NativeModulesApple + - React-RCTFabric + - React-renderercss + - React-rendererdebug + - React-utils + - ReactCodegen + - ReactCommon/turbomodule/bridging + - ReactCommon/turbomodule/core + - SocketRocket + - Yoga + - react-native-safe-area-context/fabric (5.5.2): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - RCTRequired + - RCTTypeSafety + - React-Core + - React-debug + - React-Fabric + - React-featureflags + - React-graphics + - React-ImageManager + - React-jsi + - react-native-safe-area-context/common + - React-NativeModulesApple + - React-RCTFabric + - React-renderercss + - React-rendererdebug + - React-utils + - ReactCodegen + - ReactCommon/turbomodule/bridging + - ReactCommon/turbomodule/core + - SocketRocket + - Yoga + - React-NativeModulesApple (0.81.4): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - React-callinvoker + - React-Core + - React-cxxreact + - React-featureflags + - React-jsi + - React-jsinspector + - React-jsinspectorcdp + - React-runtimeexecutor + - ReactCommon/turbomodule/bridging + - ReactCommon/turbomodule/core + - SocketRocket + - React-oscompat (0.81.4) + - React-perflogger (0.81.4): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - RCT-Folly + - RCT-Folly/Fabric + - SocketRocket + - React-performancetimeline (0.81.4): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - RCT-Folly + - RCT-Folly/Fabric + - React-featureflags + - React-jsinspectortracing + - React-perflogger + - React-timing + - SocketRocket + - React-RCTActionSheet (0.81.4): + - React-Core/RCTActionSheetHeaders (= 0.81.4) + - React-RCTAnimation (0.81.4): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - RCT-Folly + - RCT-Folly/Fabric + - RCTTypeSafety + - React-Core/RCTAnimationHeaders + - React-featureflags + - React-jsi + - React-NativeModulesApple + - React-RCTFBReactNativeSpec + - ReactCommon + - SocketRocket + - React-RCTAppDelegate (0.81.4): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - RCTRequired + - RCTTypeSafety + - React-Core + - React-CoreModules + - React-debug + - React-defaultsnativemodule + - React-Fabric + - React-featureflags + - React-graphics + - React-hermes + - React-jsitooling + - React-NativeModulesApple + - React-RCTFabric + - React-RCTFBReactNativeSpec + - React-RCTImage + - React-RCTNetwork + - React-RCTRuntime + - React-rendererdebug + - React-RuntimeApple + - React-RuntimeCore + - React-runtimeexecutor + - React-runtimescheduler + - React-utils + - ReactCommon + - SocketRocket + - React-RCTBlob (0.81.4): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - React-Core/RCTBlobHeaders + - React-Core/RCTWebSocket + - React-jsi + - React-jsinspector + - React-jsinspectorcdp + - React-NativeModulesApple + - React-RCTFBReactNativeSpec + - React-RCTNetwork + - ReactCommon + - SocketRocket + - React-RCTFabric (0.81.4): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - React-Core + - React-debug + - React-Fabric + - React-FabricComponents + - React-FabricImage + - React-featureflags + - React-graphics + - React-ImageManager + - React-jsi + - React-jsinspector + - React-jsinspectorcdp + - React-jsinspectornetwork + - React-jsinspectortracing + - React-performancetimeline + - React-RCTAnimation + - React-RCTFBReactNativeSpec + - React-RCTImage + - React-RCTText + - React-rendererconsistency + - React-renderercss + - React-rendererdebug + - React-runtimeexecutor + - React-runtimescheduler + - React-utils + - SocketRocket + - Yoga + - React-RCTFBReactNativeSpec (0.81.4): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - RCTRequired + - RCTTypeSafety + - React-Core + - React-jsi + - React-NativeModulesApple + - React-RCTFBReactNativeSpec/components (= 0.81.4) + - ReactCommon + - SocketRocket + - React-RCTFBReactNativeSpec/components (0.81.4): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - RCTRequired + - RCTTypeSafety + - React-Core + - React-debug + - React-Fabric + - React-featureflags + - React-graphics + - React-jsi + - React-NativeModulesApple + - React-rendererdebug + - React-utils + - ReactCommon + - SocketRocket + - Yoga + - React-RCTImage (0.81.4): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - RCT-Folly + - RCT-Folly/Fabric + - RCTTypeSafety + - React-Core/RCTImageHeaders + - React-jsi + - React-NativeModulesApple + - React-RCTFBReactNativeSpec + - React-RCTNetwork + - ReactCommon + - SocketRocket + - React-RCTLinking (0.81.4): + - React-Core/RCTLinkingHeaders (= 0.81.4) + - React-jsi (= 0.81.4) + - React-NativeModulesApple + - React-RCTFBReactNativeSpec + - ReactCommon + - ReactCommon/turbomodule/core (= 0.81.4) + - React-RCTNetwork (0.81.4): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - RCT-Folly + - RCT-Folly/Fabric + - RCTTypeSafety + - React-Core/RCTNetworkHeaders + - React-featureflags + - React-jsi + - React-jsinspectorcdp + - React-jsinspectornetwork + - React-NativeModulesApple + - React-RCTFBReactNativeSpec + - ReactCommon + - SocketRocket + - React-RCTRuntime (0.81.4): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - React-Core + - React-jsi + - React-jsinspector + - React-jsinspectorcdp + - React-jsinspectortracing + - React-jsitooling + - React-RuntimeApple + - React-RuntimeCore + - React-runtimeexecutor + - React-RuntimeHermes + - SocketRocket + - React-RCTSettings (0.81.4): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - RCT-Folly + - RCT-Folly/Fabric + - RCTTypeSafety + - React-Core/RCTSettingsHeaders + - React-jsi + - React-NativeModulesApple + - React-RCTFBReactNativeSpec + - ReactCommon + - SocketRocket + - React-RCTText (0.81.4): + - React-Core/RCTTextHeaders (= 0.81.4) + - Yoga + - React-RCTVibration (0.81.4): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - RCT-Folly + - RCT-Folly/Fabric + - React-Core/RCTVibrationHeaders + - React-jsi + - React-NativeModulesApple + - React-RCTFBReactNativeSpec + - ReactCommon + - SocketRocket + - React-rendererconsistency (0.81.4) + - React-renderercss (0.81.4): + - React-debug + - React-utils + - React-rendererdebug (0.81.4): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - RCT-Folly + - RCT-Folly/Fabric + - React-debug + - SocketRocket + - React-RuntimeApple (0.81.4): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - React-callinvoker + - React-Core/Default + - React-CoreModules + - React-cxxreact + - React-featureflags + - React-jserrorhandler + - React-jsi + - React-jsiexecutor + - React-jsinspector + - React-jsitooling + - React-Mapbuffer + - React-NativeModulesApple + - React-RCTFabric + - React-RCTFBReactNativeSpec + - React-RuntimeCore + - React-runtimeexecutor + - React-RuntimeHermes + - React-runtimescheduler + - React-utils + - SocketRocket + - React-RuntimeCore (0.81.4): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - React-cxxreact + - React-Fabric + - React-featureflags + - React-jserrorhandler + - React-jsi + - React-jsiexecutor + - React-jsinspector + - React-jsitooling + - React-performancetimeline + - React-runtimeexecutor + - React-runtimescheduler + - React-utils + - SocketRocket + - React-runtimeexecutor (0.81.4): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - RCT-Folly + - RCT-Folly/Fabric + - React-debug + - React-featureflags + - React-jsi (= 0.81.4) + - React-utils + - SocketRocket + - React-RuntimeHermes (0.81.4): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - React-featureflags + - React-hermes + - React-jsi + - React-jsinspector + - React-jsinspectorcdp + - React-jsinspectortracing + - React-jsitooling + - React-jsitracing + - React-RuntimeCore + - React-runtimeexecutor + - React-utils + - SocketRocket + - React-runtimescheduler (0.81.4): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - React-callinvoker + - React-cxxreact + - React-debug + - React-featureflags + - React-jsi + - React-jsinspectortracing + - React-performancetimeline + - React-rendererconsistency + - React-rendererdebug + - React-runtimeexecutor + - React-timing + - React-utils + - SocketRocket + - React-timing (0.81.4): + - React-debug + - React-utils (0.81.4): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - React-debug + - React-jsi (= 0.81.4) + - SocketRocket + - ReactAppDependencyProvider (0.81.4): + - ReactCodegen + - ReactCodegen (0.81.4): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - RCTRequired + - RCTTypeSafety + - React-Core + - React-debug + - React-Fabric + - React-FabricImage + - React-featureflags + - React-graphics + - React-jsi + - React-jsiexecutor + - React-NativeModulesApple + - React-RCTAppDelegate + - React-rendererdebug + - React-utils + - ReactCommon/turbomodule/bridging + - ReactCommon/turbomodule/core + - SocketRocket + - ReactCommon (0.81.4): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - RCT-Folly + - RCT-Folly/Fabric + - ReactCommon/turbomodule (= 0.81.4) + - SocketRocket + - ReactCommon/turbomodule (0.81.4): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - React-callinvoker (= 0.81.4) + - React-cxxreact (= 0.81.4) + - React-jsi (= 0.81.4) + - React-logger (= 0.81.4) + - React-perflogger (= 0.81.4) + - ReactCommon/turbomodule/bridging (= 0.81.4) + - ReactCommon/turbomodule/core (= 0.81.4) + - SocketRocket + - ReactCommon/turbomodule/bridging (0.81.4): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - React-callinvoker (= 0.81.4) + - React-cxxreact (= 0.81.4) + - React-jsi (= 0.81.4) + - React-logger (= 0.81.4) + - React-perflogger (= 0.81.4) + - SocketRocket + - ReactCommon/turbomodule/core (0.81.4): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - React-callinvoker (= 0.81.4) + - React-cxxreact (= 0.81.4) + - React-debug (= 0.81.4) + - React-featureflags (= 0.81.4) + - React-jsi (= 0.81.4) + - React-logger (= 0.81.4) + - React-perflogger (= 0.81.4) + - React-utils (= 0.81.4) + - SocketRocket + - RNCAsyncStorage (2.2.0): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - RCTRequired + - RCTTypeSafety + - React-Core + - React-debug + - React-Fabric + - React-featureflags + - React-graphics + - React-ImageManager + - React-jsi + - React-NativeModulesApple + - React-RCTFabric + - React-renderercss + - React-rendererdebug + - React-utils + - ReactCodegen + - ReactCommon/turbomodule/bridging + - ReactCommon/turbomodule/core + - SocketRocket + - Yoga + - RNCClipboard (1.16.3): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - RCTRequired + - RCTTypeSafety + - React-Core + - React-debug + - React-Fabric + - React-featureflags + - React-graphics + - React-ImageManager + - React-jsi + - React-NativeModulesApple + - React-RCTFabric + - React-renderercss + - React-rendererdebug + - React-utils + - ReactCodegen + - ReactCommon/turbomodule/bridging + - ReactCommon/turbomodule/core + - SocketRocket + - Yoga + - RNInAppBrowser (3.7.1): + - React-Core + - RNKeychain (10.0.0): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - RCTRequired + - RCTTypeSafety + - React-Core + - React-debug + - React-Fabric + - React-featureflags + - React-graphics + - React-ImageManager + - React-jsi + - React-NativeModulesApple + - React-RCTFabric + - React-renderercss + - React-rendererdebug + - React-utils + - ReactCodegen + - ReactCommon/turbomodule/bridging + - ReactCommon/turbomodule/core + - SocketRocket + - Yoga + - RNScreens (4.24.0): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - RCTRequired + - RCTTypeSafety + - React-Core + - React-debug + - React-Fabric + - React-featureflags + - React-graphics + - React-ImageManager + - React-jsi + - React-NativeModulesApple + - React-RCTFabric + - React-RCTImage + - React-renderercss + - React-rendererdebug + - React-utils + - ReactCodegen + - ReactCommon/turbomodule/bridging + - ReactCommon/turbomodule/core + - RNScreens/common (= 4.24.0) + - SocketRocket + - Yoga + - RNScreens/common (4.24.0): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - RCTRequired + - RCTTypeSafety + - React-Core + - React-debug + - React-Fabric + - React-featureflags + - React-graphics + - React-ImageManager + - React-jsi + - React-NativeModulesApple + - React-RCTFabric + - React-RCTImage + - React-renderercss + - React-rendererdebug + - React-utils + - ReactCodegen + - ReactCommon/turbomodule/bridging + - ReactCommon/turbomodule/core + - SocketRocket + - Yoga + - RNSVG (15.15.5): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - RCTRequired + - RCTTypeSafety + - React-Core + - React-debug + - React-Fabric + - React-featureflags + - React-graphics + - React-ImageManager + - React-jsi + - React-NativeModulesApple + - React-RCTFabric + - React-renderercss + - React-rendererdebug + - React-utils + - ReactCodegen + - ReactCommon/turbomodule/bridging + - ReactCommon/turbomodule/core + - RNSVG/common (= 15.15.5) + - SocketRocket + - Yoga + - RNSVG/common (15.15.5): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - RCTRequired + - RCTTypeSafety + - React-Core + - React-debug + - React-Fabric + - React-featureflags + - React-graphics + - React-ImageManager + - React-jsi + - React-NativeModulesApple + - React-RCTFabric + - React-renderercss + - React-rendererdebug + - React-utils + - ReactCodegen + - ReactCommon/turbomodule/bridging + - ReactCommon/turbomodule/core + - SocketRocket + - Yoga + - SocketRocket (0.7.1) + - Yoga (0.0.0) + +DEPENDENCIES: + - boost (from `../node_modules/react-native/third-party-podspecs/boost.podspec`) + - BVLinearGradient (from `../node_modules/react-native-linear-gradient`) + - DoubleConversion (from `../node_modules/react-native/third-party-podspecs/DoubleConversion.podspec`) + - "dynamic-labs-sdk-client (from `../node_modules/@dynamic-labs-sdk/client`)" + - fast_float (from `../node_modules/react-native/third-party-podspecs/fast_float.podspec`) + - FBLazyVector (from `../node_modules/react-native/Libraries/FBLazyVector`) + - fmt (from `../node_modules/react-native/third-party-podspecs/fmt.podspec`) + - glog (from `../node_modules/react-native/third-party-podspecs/glog.podspec`) + - hermes-engine (from `../node_modules/react-native/sdks/hermes-engine/hermes-engine.podspec`) + - RCT-Folly (from `../node_modules/react-native/third-party-podspecs/RCT-Folly.podspec`) + - RCTDeprecation (from `../node_modules/react-native/ReactApple/Libraries/RCTFoundation/RCTDeprecation`) + - RCTRequired (from `../node_modules/react-native/Libraries/Required`) + - RCTTypeSafety (from `../node_modules/react-native/Libraries/TypeSafety`) + - React (from `../node_modules/react-native/`) + - React-callinvoker (from `../node_modules/react-native/ReactCommon/callinvoker`) + - React-Core (from `../node_modules/react-native/`) + - React-Core/RCTWebSocket (from `../node_modules/react-native/`) + - React-CoreModules (from `../node_modules/react-native/React/CoreModules`) + - React-cxxreact (from `../node_modules/react-native/ReactCommon/cxxreact`) + - React-debug (from `../node_modules/react-native/ReactCommon/react/debug`) + - React-defaultsnativemodule (from `../node_modules/react-native/ReactCommon/react/nativemodule/defaults`) + - React-domnativemodule (from `../node_modules/react-native/ReactCommon/react/nativemodule/dom`) + - React-Fabric (from `../node_modules/react-native/ReactCommon`) + - React-FabricComponents (from `../node_modules/react-native/ReactCommon`) + - React-FabricImage (from `../node_modules/react-native/ReactCommon`) + - React-featureflags (from `../node_modules/react-native/ReactCommon/react/featureflags`) + - React-featureflagsnativemodule (from `../node_modules/react-native/ReactCommon/react/nativemodule/featureflags`) + - React-graphics (from `../node_modules/react-native/ReactCommon/react/renderer/graphics`) + - React-hermes (from `../node_modules/react-native/ReactCommon/hermes`) + - React-idlecallbacksnativemodule (from `../node_modules/react-native/ReactCommon/react/nativemodule/idlecallbacks`) + - React-ImageManager (from `../node_modules/react-native/ReactCommon/react/renderer/imagemanager/platform/ios`) + - React-jserrorhandler (from `../node_modules/react-native/ReactCommon/jserrorhandler`) + - React-jsi (from `../node_modules/react-native/ReactCommon/jsi`) + - React-jsiexecutor (from `../node_modules/react-native/ReactCommon/jsiexecutor`) + - React-jsinspector (from `../node_modules/react-native/ReactCommon/jsinspector-modern`) + - React-jsinspectorcdp (from `../node_modules/react-native/ReactCommon/jsinspector-modern/cdp`) + - React-jsinspectornetwork (from `../node_modules/react-native/ReactCommon/jsinspector-modern/network`) + - React-jsinspectortracing (from `../node_modules/react-native/ReactCommon/jsinspector-modern/tracing`) + - React-jsitooling (from `../node_modules/react-native/ReactCommon/jsitooling`) + - React-jsitracing (from `../node_modules/react-native/ReactCommon/hermes/executor/`) + - React-logger (from `../node_modules/react-native/ReactCommon/logger`) + - React-Mapbuffer (from `../node_modules/react-native/ReactCommon`) + - React-microtasksnativemodule (from `../node_modules/react-native/ReactCommon/react/nativemodule/microtasks`) + - "react-native-compat (from `../node_modules/@walletconnect/react-native-compat`)" + - react-native-get-random-values (from `../node_modules/react-native-get-random-values`) + - "react-native-netinfo (from `../node_modules/@react-native-community/netinfo`)" + - react-native-passkey (from `../node_modules/react-native-passkey`) + - react-native-safe-area-context (from `../node_modules/react-native-safe-area-context`) + - React-NativeModulesApple (from `../node_modules/react-native/ReactCommon/react/nativemodule/core/platform/ios`) + - React-oscompat (from `../node_modules/react-native/ReactCommon/oscompat`) + - React-perflogger (from `../node_modules/react-native/ReactCommon/reactperflogger`) + - React-performancetimeline (from `../node_modules/react-native/ReactCommon/react/performance/timeline`) + - React-RCTActionSheet (from `../node_modules/react-native/Libraries/ActionSheetIOS`) + - React-RCTAnimation (from `../node_modules/react-native/Libraries/NativeAnimation`) + - React-RCTAppDelegate (from `../node_modules/react-native/Libraries/AppDelegate`) + - React-RCTBlob (from `../node_modules/react-native/Libraries/Blob`) + - React-RCTFabric (from `../node_modules/react-native/React`) + - React-RCTFBReactNativeSpec (from `../node_modules/react-native/React`) + - React-RCTImage (from `../node_modules/react-native/Libraries/Image`) + - React-RCTLinking (from `../node_modules/react-native/Libraries/LinkingIOS`) + - React-RCTNetwork (from `../node_modules/react-native/Libraries/Network`) + - React-RCTRuntime (from `../node_modules/react-native/React/Runtime`) + - React-RCTSettings (from `../node_modules/react-native/Libraries/Settings`) + - React-RCTText (from `../node_modules/react-native/Libraries/Text`) + - React-RCTVibration (from `../node_modules/react-native/Libraries/Vibration`) + - React-rendererconsistency (from `../node_modules/react-native/ReactCommon/react/renderer/consistency`) + - React-renderercss (from `../node_modules/react-native/ReactCommon/react/renderer/css`) + - React-rendererdebug (from `../node_modules/react-native/ReactCommon/react/renderer/debug`) + - React-RuntimeApple (from `../node_modules/react-native/ReactCommon/react/runtime/platform/ios`) + - React-RuntimeCore (from `../node_modules/react-native/ReactCommon/react/runtime`) + - React-runtimeexecutor (from `../node_modules/react-native/ReactCommon/runtimeexecutor`) + - React-RuntimeHermes (from `../node_modules/react-native/ReactCommon/react/runtime`) + - React-runtimescheduler (from `../node_modules/react-native/ReactCommon/react/renderer/runtimescheduler`) + - React-timing (from `../node_modules/react-native/ReactCommon/react/timing`) + - React-utils (from `../node_modules/react-native/ReactCommon/react/utils`) + - ReactAppDependencyProvider (from `build/generated/ios`) + - ReactCodegen (from `build/generated/ios`) + - ReactCommon/turbomodule/core (from `../node_modules/react-native/ReactCommon`) + - "RNCAsyncStorage (from `../node_modules/@react-native-async-storage/async-storage`)" + - "RNCClipboard (from `../node_modules/@react-native-clipboard/clipboard`)" + - RNInAppBrowser (from `../node_modules/react-native-inappbrowser-reborn`) + - RNKeychain (from `../node_modules/react-native-keychain`) + - RNScreens (from `../node_modules/react-native-screens`) + - RNSVG (from `../node_modules/react-native-svg`) + - SocketRocket (~> 0.7.1) + - Yoga (from `../node_modules/react-native/ReactCommon/yoga`) + +SPEC REPOS: + trunk: + - SocketRocket + +EXTERNAL SOURCES: + boost: + :podspec: "../node_modules/react-native/third-party-podspecs/boost.podspec" + BVLinearGradient: + :path: "../node_modules/react-native-linear-gradient" + DoubleConversion: + :podspec: "../node_modules/react-native/third-party-podspecs/DoubleConversion.podspec" + dynamic-labs-sdk-client: + :path: "../node_modules/@dynamic-labs-sdk/client" + fast_float: + :podspec: "../node_modules/react-native/third-party-podspecs/fast_float.podspec" + FBLazyVector: + :path: "../node_modules/react-native/Libraries/FBLazyVector" + fmt: + :podspec: "../node_modules/react-native/third-party-podspecs/fmt.podspec" + glog: + :podspec: "../node_modules/react-native/third-party-podspecs/glog.podspec" + hermes-engine: + :podspec: "../node_modules/react-native/sdks/hermes-engine/hermes-engine.podspec" + :tag: hermes-2025-07-07-RNv0.81.0-e0fc67142ec0763c6b6153ca2bf96df815539782 + RCT-Folly: + :podspec: "../node_modules/react-native/third-party-podspecs/RCT-Folly.podspec" + RCTDeprecation: + :path: "../node_modules/react-native/ReactApple/Libraries/RCTFoundation/RCTDeprecation" + RCTRequired: + :path: "../node_modules/react-native/Libraries/Required" + RCTTypeSafety: + :path: "../node_modules/react-native/Libraries/TypeSafety" + React: + :path: "../node_modules/react-native/" + React-callinvoker: + :path: "../node_modules/react-native/ReactCommon/callinvoker" + React-Core: + :path: "../node_modules/react-native/" + React-CoreModules: + :path: "../node_modules/react-native/React/CoreModules" + React-cxxreact: + :path: "../node_modules/react-native/ReactCommon/cxxreact" + React-debug: + :path: "../node_modules/react-native/ReactCommon/react/debug" + React-defaultsnativemodule: + :path: "../node_modules/react-native/ReactCommon/react/nativemodule/defaults" + React-domnativemodule: + :path: "../node_modules/react-native/ReactCommon/react/nativemodule/dom" + React-Fabric: + :path: "../node_modules/react-native/ReactCommon" + React-FabricComponents: + :path: "../node_modules/react-native/ReactCommon" + React-FabricImage: + :path: "../node_modules/react-native/ReactCommon" + React-featureflags: + :path: "../node_modules/react-native/ReactCommon/react/featureflags" + React-featureflagsnativemodule: + :path: "../node_modules/react-native/ReactCommon/react/nativemodule/featureflags" + React-graphics: + :path: "../node_modules/react-native/ReactCommon/react/renderer/graphics" + React-hermes: + :path: "../node_modules/react-native/ReactCommon/hermes" + React-idlecallbacksnativemodule: + :path: "../node_modules/react-native/ReactCommon/react/nativemodule/idlecallbacks" + React-ImageManager: + :path: "../node_modules/react-native/ReactCommon/react/renderer/imagemanager/platform/ios" + React-jserrorhandler: + :path: "../node_modules/react-native/ReactCommon/jserrorhandler" + React-jsi: + :path: "../node_modules/react-native/ReactCommon/jsi" + React-jsiexecutor: + :path: "../node_modules/react-native/ReactCommon/jsiexecutor" + React-jsinspector: + :path: "../node_modules/react-native/ReactCommon/jsinspector-modern" + React-jsinspectorcdp: + :path: "../node_modules/react-native/ReactCommon/jsinspector-modern/cdp" + React-jsinspectornetwork: + :path: "../node_modules/react-native/ReactCommon/jsinspector-modern/network" + React-jsinspectortracing: + :path: "../node_modules/react-native/ReactCommon/jsinspector-modern/tracing" + React-jsitooling: + :path: "../node_modules/react-native/ReactCommon/jsitooling" + React-jsitracing: + :path: "../node_modules/react-native/ReactCommon/hermes/executor/" + React-logger: + :path: "../node_modules/react-native/ReactCommon/logger" + React-Mapbuffer: + :path: "../node_modules/react-native/ReactCommon" + React-microtasksnativemodule: + :path: "../node_modules/react-native/ReactCommon/react/nativemodule/microtasks" + react-native-compat: + :path: "../node_modules/@walletconnect/react-native-compat" + react-native-get-random-values: + :path: "../node_modules/react-native-get-random-values" + react-native-netinfo: + :path: "../node_modules/@react-native-community/netinfo" + react-native-passkey: + :path: "../node_modules/react-native-passkey" + react-native-safe-area-context: + :path: "../node_modules/react-native-safe-area-context" + React-NativeModulesApple: + :path: "../node_modules/react-native/ReactCommon/react/nativemodule/core/platform/ios" + React-oscompat: + :path: "../node_modules/react-native/ReactCommon/oscompat" + React-perflogger: + :path: "../node_modules/react-native/ReactCommon/reactperflogger" + React-performancetimeline: + :path: "../node_modules/react-native/ReactCommon/react/performance/timeline" + React-RCTActionSheet: + :path: "../node_modules/react-native/Libraries/ActionSheetIOS" + React-RCTAnimation: + :path: "../node_modules/react-native/Libraries/NativeAnimation" + React-RCTAppDelegate: + :path: "../node_modules/react-native/Libraries/AppDelegate" + React-RCTBlob: + :path: "../node_modules/react-native/Libraries/Blob" + React-RCTFabric: + :path: "../node_modules/react-native/React" + React-RCTFBReactNativeSpec: + :path: "../node_modules/react-native/React" + React-RCTImage: + :path: "../node_modules/react-native/Libraries/Image" + React-RCTLinking: + :path: "../node_modules/react-native/Libraries/LinkingIOS" + React-RCTNetwork: + :path: "../node_modules/react-native/Libraries/Network" + React-RCTRuntime: + :path: "../node_modules/react-native/React/Runtime" + React-RCTSettings: + :path: "../node_modules/react-native/Libraries/Settings" + React-RCTText: + :path: "../node_modules/react-native/Libraries/Text" + React-RCTVibration: + :path: "../node_modules/react-native/Libraries/Vibration" + React-rendererconsistency: + :path: "../node_modules/react-native/ReactCommon/react/renderer/consistency" + React-renderercss: + :path: "../node_modules/react-native/ReactCommon/react/renderer/css" + React-rendererdebug: + :path: "../node_modules/react-native/ReactCommon/react/renderer/debug" + React-RuntimeApple: + :path: "../node_modules/react-native/ReactCommon/react/runtime/platform/ios" + React-RuntimeCore: + :path: "../node_modules/react-native/ReactCommon/react/runtime" + React-runtimeexecutor: + :path: "../node_modules/react-native/ReactCommon/runtimeexecutor" + React-RuntimeHermes: + :path: "../node_modules/react-native/ReactCommon/react/runtime" + React-runtimescheduler: + :path: "../node_modules/react-native/ReactCommon/react/renderer/runtimescheduler" + React-timing: + :path: "../node_modules/react-native/ReactCommon/react/timing" + React-utils: + :path: "../node_modules/react-native/ReactCommon/react/utils" + ReactAppDependencyProvider: + :path: build/generated/ios + ReactCodegen: + :path: build/generated/ios + ReactCommon: + :path: "../node_modules/react-native/ReactCommon" + RNCAsyncStorage: + :path: "../node_modules/@react-native-async-storage/async-storage" + RNCClipboard: + :path: "../node_modules/@react-native-clipboard/clipboard" + RNInAppBrowser: + :path: "../node_modules/react-native-inappbrowser-reborn" + RNKeychain: + :path: "../node_modules/react-native-keychain" + RNScreens: + :path: "../node_modules/react-native-screens" + RNSVG: + :path: "../node_modules/react-native-svg" + Yoga: + :path: "../node_modules/react-native/ReactCommon/yoga" + +SPEC CHECKSUMS: + boost: 7e761d76ca2ce687f7cc98e698152abd03a18f90 + BVLinearGradient: cb006ba232a1f3e4f341bb62c42d1098c284da70 + DoubleConversion: cb417026b2400c8f53ae97020b2be961b59470cb + dynamic-labs-sdk-client: 5fee4611d6c82001c86cc6a760603197eefea0b4 + fast_float: b32c788ed9c6a8c584d114d0047beda9664e7cc6 + FBLazyVector: 941bef1c8eeabd9fe1f501e30a5220beee913886 + fmt: a40bb5bd0294ea969aaaba240a927bd33d878cdd + glog: 5683914934d5b6e4240e497e0f4a3b42d1854183 + hermes-engine: 228692ee4d4390de83b99d1756f67b1502d9fbc6 + RCT-Folly: 846fda9475e61ec7bcbf8a3fe81edfcaeb090669 + RCTDeprecation: c0ed3249a97243002615517dff789bf4666cf585 + RCTRequired: 58719f5124f9267b5f9649c08bf23d9aea845b23 + RCTTypeSafety: 4aefa8328ab1f86da273f08517f1f6b343f6c2cc + React: 2073376f47c71b7e9a0af7535986a77522ce1049 + React-callinvoker: 751b6f2c83347a0486391c3f266f291f0f53b27e + React-Core: dff5d29973349b11dd6631c9498456d75f846d5e + React-CoreModules: c0ae04452e4c5d30e06f8e94692a49107657f537 + React-cxxreact: 376fd672c95dfb64ad5cc246e6a1e9edb78dec4c + React-debug: 7b56a0a7da432353287d2eedac727903e35278f5 + React-defaultsnativemodule: 393b81aaa6211408f50a6ef00a277847256dd881 + React-domnativemodule: 5fb5829baa7a7a0f217019cbad1eb226d94f7062 + React-Fabric: a17c4ae35503673b57b91c2d1388429e7cbee452 + React-FabricComponents: a76572ddeba78ebe4ec58615291e9db4a55cd46a + React-FabricImage: d806eb2695d7ef355ec28d1a21f5a14ac26b1cae + React-featureflags: 1690ec3c453920b6308e23a4e24eb9c3632f9c75 + React-featureflagsnativemodule: 7b7e8483fc671c5a33aefd699b7c7a3c0bdfdfec + React-graphics: ea146ee799dc816524a3a0922fc7be0b5a52dcc1 + React-hermes: fcbdc45ecf38259fe3b12642bd0757c52270a107 + React-idlecallbacksnativemodule: a353f9162eaa7ad787e68aba9f52a1cfa8154098 + React-ImageManager: ec5cf55ce9cc81719eb5f1f51d23d04db851c86c + React-jserrorhandler: 594c593f3d60f527be081e2cace7710c2bd9f524 + React-jsi: 59ec3190dd364cca86a58869e7755477d2468948 + React-jsiexecutor: b87d78a2e8dd7a6f56e9cdac038da45de98c944f + React-jsinspector: b9204adf1af622c98e78af96ec1bca615c2ce2bd + React-jsinspectorcdp: 4a356fa69e412d35d3a38c44d4a6cc555c5931e8 + React-jsinspectornetwork: 7820056773178f321cbf18689e1ffcd38276a878 + React-jsinspectortracing: b341c5ef6e031a33e0bd462d67fd397e8e9cd612 + React-jsitooling: 401655e05cb966b0081225c5201d90734a567cb9 + React-jsitracing: 67eff6dea0cb58a1e7bd8b49243012d88c0f511e + React-logger: a3cb5b29c32b8e447b5a96919340e89334062b48 + React-Mapbuffer: 9d2434a42701d6144ca18f0ca1c4507808ca7696 + React-microtasksnativemodule: 75b6604b667d297292345302cc5bfb6b6aeccc1b + react-native-compat: 4127e158ee4fa2d2752e398096178ef7afb09cf4 + react-native-get-random-values: e2acf4070fe4b7325705a05af047449637a27a21 + react-native-netinfo: a0be8c77f8420a60ddf07eb87be1a36f02a1bd65 + react-native-passkey: eaf2e620c220e12a37ba7c96a9934580ecf24cb2 + react-native-safe-area-context: 84a754cad3fbb25117482cde6b8defca6c6f6a53 + React-NativeModulesApple: 879fbdc5dcff7136abceb7880fe8a2022a1bd7c3 + React-oscompat: 93b5535ea7f7dff46aaee4f78309a70979bdde9d + React-perflogger: 5536d2df3d18fe0920263466f7b46a56351c0510 + React-performancetimeline: 9041c53efa07f537164dcfe7670a36642352f4c2 + React-RCTActionSheet: 42195ae666e6d79b4af2346770f765b7c29435b9 + React-RCTAnimation: fa103ccc3503b1ed8dedca7e62e7823937748843 + React-RCTAppDelegate: 665d4baf19424cef08276e9ac0d8771eec4519f9 + React-RCTBlob: 0fa9530c255644db095f2c4fd8d89738d9d9ecc0 + React-RCTFabric: 1fcd8af6e25f92532f56b4ba092e58662c14d156 + React-RCTFBReactNativeSpec: db171247585774f9f0a30f75109cc51568686213 + React-RCTImage: ba824e61ce2e920a239a65d130b83c3a1d426dff + React-RCTLinking: d2dc199c37e71e6f505d9eca3e5c33be930014d4 + React-RCTNetwork: 87137d4b9bd77e5068f854dd5c1f30d4b072faf6 + React-RCTRuntime: 137fafaa808a8b7e76a510e8be45f9f827899daa + React-RCTSettings: 71f5c7fd7b5f4e725a4e2114a4b4373d0e46048f + React-RCTText: b94d4699b49285bee22b8ebf768924d607eccee3 + React-RCTVibration: 6e3993c4f6c36a3899059f9a9ead560ddaf5a7d7 + React-rendererconsistency: b4785e5ed837dc7c242bbc5fdd464b33ef5bfae7 + React-renderercss: e6fb0ba387b389c595ffa86b8b628716d31f58dc + React-rendererdebug: 60a03de5c7ea59bf2d39791eb43c4c0f5d8b24e3 + React-RuntimeApple: 3df6788cd9b938bb8cb28298d80b5fbd98a4d852 + React-RuntimeCore: fad8adb4172c414c00ff6980250caf35601a0f5d + React-runtimeexecutor: d2db7e72d97751855ea0bf5273d2ac84e5ea390c + React-RuntimeHermes: 04faa4cf9a285136a6d73738787fe36020170613 + React-runtimescheduler: f6a1c9555e7131b4a8b64cce01489ad0405f6e8d + React-timing: 1e6a8acb66e2b7ac9d418956617fd1fdb19322fd + React-utils: 52bbb03f130319ef82e4c3bc7a85eaacdb1fec87 + ReactAppDependencyProvider: 433ddfb4536948630aadd5bd925aff8a632d2fe3 + ReactCodegen: bda01baeea463f2bb10d9166da70e1a4e4eded6d + ReactCommon: 394c6b92765cf6d211c2c3f7f6bc601dffb316a6 + RNCAsyncStorage: 29f0230e1a25f36c20b05f65e2eb8958d6526e82 + RNCClipboard: 4b58c780f63676367640f23c8e114e9bd0cf86ac + RNInAppBrowser: 904d24dc75e8e6c6c98a3160329192608946f9df + RNKeychain: a2c134ab796272c3d605e035ab727591000b30f3 + RNScreens: 7f643ee0fd1407dc5085c7795460bd93da113b8f + RNSVG: 4dd2d79b3cb224bcb3ae666a2adda2ede9d3772f + SocketRocket: d4aabe649be1e368d1318fdf28a022d714d65748 + Yoga: a3ed390a19db0459bd6839823a6ac6d9c6db198d + +PODFILE CHECKSUM: 9777ce28208699bc64da6eb7b341c67ee5c3ada0 + +COCOAPODS: 1.15.2 diff --git a/examples/bare-react-native-with-js-sdk-and-flow/metro.config.js b/examples/bare-react-native-with-js-sdk-and-flow/metro.config.js new file mode 100644 index 0000000..50bd22b --- /dev/null +++ b/examples/bare-react-native-with-js-sdk-and-flow/metro.config.js @@ -0,0 +1,33 @@ +const path = require('path'); +const { getDefaultConfig, mergeConfig } = require('@react-native/metro-config'); + +/** + * Metro configuration + * https://reactnative.dev/docs/metro + * + * @type {import('@react-native/metro-config').MetroConfig} + */ +const config = { + resolver: { + // `extraNodeModules` is only consulted as a *fallback*, once normal + // resolution fails to find a module — it can't override a package + // that's actually installed, which `ws` is (as a transitive + // dependency). `resolveRequest` intercepts every resolution up front, + // so it can redirect a real package too. + resolveRequest: (context, moduleName, platform) => { + if (moduleName === 'ws') { + // `ws` is a Node-only WebSocket client that WalletConnect + // internals pull in transitively (via @dynamic-labs-sdk/evm's + // wallet-connect dependency, even for MetaMask-only usage) — see + // shims/ws.js. + return { + type: 'sourceFile', + filePath: path.resolve(__dirname, 'shims/ws.js'), + }; + } + return context.resolveRequest(context, moduleName, platform); + }, + }, +}; + +module.exports = mergeConfig(getDefaultConfig(__dirname), config); diff --git a/examples/bare-react-native-with-js-sdk-and-flow/package.json b/examples/bare-react-native-with-js-sdk-and-flow/package.json new file mode 100644 index 0000000..ea30a54 --- /dev/null +++ b/examples/bare-react-native-with-js-sdk-and-flow/package.json @@ -0,0 +1,63 @@ +{ + "name": "bare-react-native-with-js-sdk-and-flow", + "version": "0.0.1", + "private": true, + "scripts": { + "android": "react-native run-android", + "ios": "react-native run-ios", + "lint": "eslint .", + "start": "react-native start" + }, + "dependencies": { + "@dynamic-labs-sdk/client": "1.28.0", + "@dynamic-labs-sdk/evm": "1.28.0", + "@dynamic-labs-sdk/react-hooks": "1.28.0", + "@react-native-async-storage/async-storage": "2.2.0", + "@react-native-clipboard/clipboard": "1.16.3", + "@react-native-community/netinfo": "12.0.1", + "@react-native/new-app-screen": "0.81.4", + "@react-navigation/native": "7.3.14", + "@react-navigation/native-stack": "7.18.6", + "@tanstack/react-query": "5.101.4", + "@walletconnect/react-native-compat": "2.21.8", + "buffer": "6.0.3", + "react": "19.1.0", + "react-native": "0.81.4", + "react-native-get-random-values": "2.0.0", + "react-native-inappbrowser-reborn": "3.7.1", + "react-native-keychain": "10.0.0", + "react-native-linear-gradient": "2.8.3", + "react-native-passkey": "3.5.0", + "react-native-safe-area-context": "5.5.2", + "react-native-screens": "4.24.0", + "react-native-svg": "15.15.5", + "viem": "2.55.8" + }, + "devDependencies": { + "@babel/core": "7.25.2", + "@babel/plugin-transform-class-static-block": "7.29.7", + "@babel/plugin-transform-export-namespace-from": "7.29.7", + "@babel/preset-env": "7.25.3", + "@babel/runtime": "7.25.0", + "@react-native-community/cli": "20.0.0", + "@react-native-community/cli-platform-android": "20.0.0", + "@react-native-community/cli-platform-ios": "20.0.0", + "@react-native/babel-preset": "0.81.4", + "@react-native/codegen": "0.81.4", + "@react-native/eslint-config": "0.81.4", + "@react-native/gradle-plugin": "0.81.4", + "@react-native/metro-config": "0.81.4", + "@react-native/typescript-config": "0.81.4", + "@types/react": "19.1.0", + "babel-plugin-transform-inline-environment-variables": "0.4.4", + "dotenv": "17.4.2", + "eslint": "8.57.1", + "eslint-plugin-jest": "27.9.0", + "prettier": "2.8.8", + "typescript": "5.8.3" + }, + "engines": { + "node": ">=20" + }, + "packageManager": "pnpm@10.30.3+sha512.c961d1e0a2d8e354ecaa5166b822516668b7f44cb5bd95122d590dd81922f606f5473b6d23ec4a5be05e7fcd18e8488d47d978bbe981872f1145d06e9a740017" +} diff --git a/examples/bare-react-native-with-js-sdk-and-flow/patches/@react-native__codegen@0.81.4.patch b/examples/bare-react-native-with-js-sdk-and-flow/patches/@react-native__codegen@0.81.4.patch new file mode 100644 index 0000000..72da76c --- /dev/null +++ b/examples/bare-react-native-with-js-sdk-and-flow/patches/@react-native__codegen@0.81.4.patch @@ -0,0 +1,36 @@ +diff --git a/lib/cli/combine/combine-js-to-schema.js b/lib/cli/combine/combine-js-to-schema.js +index 9c2fb5f4248f965b8d1c30540d35ad1549b3c937..06d9deea5f74c4a7777c80a8cc59ab0ade815033 100644 +--- a/lib/cli/combine/combine-js-to-schema.js ++++ b/lib/cli/combine/combine-js-to-schema.js +@@ -52,7 +52,30 @@ function combineSchemas(files, libraryName) { + function expandDirectoriesIntoFiles(fileList, platform, exclude) { + return fileList + .flatMap(file => { +- if (!fs.lstatSync(file).isDirectory()) { ++ // --- pnpm compatibility fix, not a machine-specific workaround --- ++ // Unlike the Hermes-from-source setting in this project's ios/Podfile ++ // (which only matters on an unusually new Xcode), THIS fix is needed ++ // by anyone using pnpm with this pinned React Native/codegen version ++ // -- it has nothing to do with what computer you're on. ++ // ++ // Upstream uses lstatSync here, which does NOT follow symlinks. Every ++ // pnpm-managed node_modules/ entry IS a symlink (into ++ // .pnpm/@version/node_modules/), so lstatSync reports every ++ // such package root as "not a directory" and this silently skips ++ // scanning it for Native*.ts specs entirely -- producing an empty ++ // codegen schema for every pnpm-linked TurboModule (any of them, not ++ // just @walletconnect/react-native-compat -- react-native-keychain's ++ // generated header is equally empty, it just happens not to be ++ // referenced by keychain's own native code, so nothing ever notices). ++ // The only symptom upstream gives you is a generic "No modules to ++ // process" log line during `pod install`, easy to miss. statSync ++ // follows symlinks and correctly identifies these as directories, ++ // which is all this one-line fix does. ++ // ++ // If this project ever switches off pnpm (npm/Yarn's node_modules ++ // aren't symlinked the same way), this patch becomes a no-op you can ++ // safely drop -- but with pnpm, every consumer of this repo needs it. ++ if (!fs.statSync(file).isDirectory()) { + return [file]; + } + const filePattern = path.sep === '\\' ? file.replace(/\\/g, '/') : file; diff --git a/examples/bare-react-native-with-js-sdk-and-flow/pnpm-workspace.yaml b/examples/bare-react-native-with-js-sdk-and-flow/pnpm-workspace.yaml new file mode 100644 index 0000000..025abba --- /dev/null +++ b/examples/bare-react-native-with-js-sdk-and-flow/pnpm-workspace.yaml @@ -0,0 +1,2 @@ +patchedDependencies: + '@react-native/codegen@0.81.4': patches/@react-native__codegen@0.81.4.patch diff --git a/examples/bare-react-native-with-js-sdk-and-flow/polyfills.ts b/examples/bare-react-native-with-js-sdk-and-flow/polyfills.ts new file mode 100644 index 0000000..78c139a --- /dev/null +++ b/examples/bare-react-native-with-js-sdk-and-flow/polyfills.ts @@ -0,0 +1,127 @@ +/** + * Bare React Native has none of the browser/Node globals the Dynamic SDK + * (and the libraries it pulls in) assume exist. Expo's managed workflow + * sets most of these up automatically; a bare RN CLI app has to do it + * explicitly, once, before anything else runs — see index.js, which + * imports this file first. + * + * This mirrors Dynamic's own bare React Native setup guide: + * https://www.dynamic.xyz/docs/javascript/react-native/bare-react-native + */ + +/** + * WalletConnect's own React Native shim (native crypto/TextEncoder-Decoder + * support WalletConnect needs that Hermes doesn't provide) — per Dynamic's + * WalletConnect integration guide, this must be the very first import in + * this file, ahead of the random-values shim below: + * https://www.dynamic.xyz/docs/javascript/reference/wallets/walletconnect-integration + * Needed for the Trust Wallet button (trustWalletConnect.ts) and for + * addWalletConnectEvmExtension (dynamicClient.ts) to work at all — without + * it, addWalletConnectEvmExtension crashes on startup. + */ +import '@walletconnect/react-native-compat'; + +/** + * Random values polyfill (crypto.getRandomValues). Provides the secure + * native RNG the SDK relies on. Must load before anything that generates + * random values. + */ +import 'react-native-get-random-values'; + +import { APP_ORIGIN } from './src/consts/config'; + +/** + * Buffer polyfill for various cryptographic operations in this dependency + * tree (viem, wallet connectors). + */ +import { Buffer as BufferPolyfill } from 'buffer'; + +(globalThis as typeof globalThis & { Buffer: typeof BufferPolyfill }).Buffer = + BufferPolyfill; + +/** + * crypto.randomUUID polyfill. Hermes doesn't implement crypto.randomUUID, + * so we generate a v4 UUID from crypto.getRandomValues (polyfilled above). + */ +type CryptoLike = { + getRandomValues?: (array: Uint8Array) => Uint8Array; + randomUUID?: () => string; +}; + +const globalWithCrypto = globalThis as unknown as { + crypto?: CryptoLike; +}; + +if (!globalWithCrypto.crypto) { + globalWithCrypto.crypto = {}; +} + +const cryptoRef = globalWithCrypto.crypto; + +if (typeof cryptoRef.randomUUID !== 'function') { + cryptoRef.randomUUID = () => { + const bytes = new Uint8Array(16); + // getRandomValues is guaranteed by the react-native-get-random-values + // import above. + cryptoRef.getRandomValues!(bytes); + // Set the version (4) and variant bits required by RFC 4122. + /* eslint-disable no-bitwise */ + bytes[6] = (bytes[6] & 0x0f) | 0x40; + bytes[8] = (bytes[8] & 0x3f) | 0x80; + /* eslint-enable no-bitwise */ + const hex = [...bytes] + .map(b => b.toString(16).padStart(2, '0')) + .join(''); + return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}-${hex.slice(16, 20)}-${hex.slice(20)}`; + }; +} + +/** + * window.location polyfill for Dynamic's embedded wallet support. + * React Native has no window.location; addEvmExtension() (see + * dynamicClient.ts) wires up Dynamic's embedded/WaaS wallet extension too + * (it's bundled into the same call as standard wallet support), and that + * client reads window.location.origin when loading the embedded wallet's + * page inside the SDK's native WebView — it throws without this shim, even + * though this demo only ever connects external wallets (MetaMask/Trust + * Wallet). Uses config.ts's APP_ORIGIN — the same value passed as + * metadata.universalLink (see dynamicClient.ts) — so the embedded wallet + * loads with a consistent origin. + */ +type MinimalLocation = { + origin: string; + href: string; + protocol: string; + host: string; + hostname: string; + port: string; + pathname: string; + search: string; + hash: string; +}; + +const globalWithLocation = globalThis as typeof globalThis & { + location?: MinimalLocation; +}; + +// React Native's TypeScript config has no DOM lib, so the URL global +// (provided at runtime by React Native) needs an explicit type here. +const globalWithUrl = globalThis as typeof globalThis & { + URL: new (url: string) => MinimalLocation; +}; + +if (!globalWithLocation.location) { + const appOriginUrl = new globalWithUrl.URL(APP_ORIGIN); + + globalWithLocation.location = { + origin: appOriginUrl.origin, + href: appOriginUrl.href, + protocol: appOriginUrl.protocol, + host: appOriginUrl.host, + hostname: appOriginUrl.hostname, + port: appOriginUrl.port, + pathname: appOriginUrl.pathname, + search: appOriginUrl.search, + hash: appOriginUrl.hash, + }; +} diff --git a/examples/bare-react-native-with-js-sdk-and-flow/shims/ws.js b/examples/bare-react-native-with-js-sdk-and-flow/shims/ws.js new file mode 100644 index 0000000..8304417 --- /dev/null +++ b/examples/bare-react-native-with-js-sdk-and-flow/shims/ws.js @@ -0,0 +1,25 @@ +/** + * Metro shim for the `ws` package. + * + * `ws` is a Node-only WebSocket client (its real implementation needs + * Node's `stream`/`net` built-ins, unavailable in Hermes/React Native). + * Something in this dependency tree resolves it transitively — WalletConnect + * internals pulled in by @dynamic-labs-sdk/evm's wallet-connect dependency, + * even when only MetaMask's own connector is used directly — so Metro tries + * to bundle `ws`'s real source and fails on the Node built-ins it needs. + * + * This just re-exports React Native's global `WebSocket`. That's only + * actually safe because the real consumers here (`isows`, pulled in by + * viem, and @walletconnect/jsonrpc-ws-connection) both check for a global + * `WebSocket` FIRST and prefer it over whatever `require('ws')` returns — + * they never call this shim's exports directly, so its exact shape doesn't + * matter much in practice today. It is NOT a faithful `ws` polyfill (no + * `.on('message', ...)`-style EventEmitter API, only the browser-style + * `WebSocket` shape) — if a future dependency in this tree calls `ws` + * directly without that same defensive check, this will need a real + * implementation instead, aliased in via metro.config.js's + * resolver.resolveRequest. + */ +module.exports = global.WebSocket; +module.exports.WebSocket = global.WebSocket; +module.exports.default = global.WebSocket; diff --git a/examples/bare-react-native-with-js-sdk-and-flow/src/App.tsx b/examples/bare-react-native-with-js-sdk-and-flow/src/App.tsx new file mode 100644 index 0000000..db42244 --- /dev/null +++ b/examples/bare-react-native-with-js-sdk-and-flow/src/App.tsx @@ -0,0 +1,25 @@ +import { DynamicProvider } from '@dynamic-labs-sdk/react-hooks'; +import { QueryClient, QueryClientProvider } from '@tanstack/react-query'; +import { StatusBar } from 'react-native'; +import { SafeAreaProvider } from 'react-native-safe-area-context'; +import { dynamicClient } from '../dynamicClient'; +import { colors } from './consts/theme'; +import { Navigation } from './navigation'; + +const queryClient = new QueryClient(); + +export default function App() { + return ( + + + + + + + + + ); +} diff --git a/examples/bare-react-native-with-js-sdk-and-flow/src/components/CopyButton.tsx b/examples/bare-react-native-with-js-sdk-and-flow/src/components/CopyButton.tsx new file mode 100644 index 0000000..0eb21db --- /dev/null +++ b/examples/bare-react-native-with-js-sdk-and-flow/src/components/CopyButton.tsx @@ -0,0 +1,43 @@ +import React from 'react'; +import { Pressable, StyleSheet, Text } from 'react-native'; +import { colors, radii, spacing } from '../consts/theme'; + +type CopyButtonProps = { + title: string; + onPress: () => void; +}; + +/** + * Small bordered chip button, purely presentational — FlowStatusScreen's + * CopyRow owns the actual clipboard write + "Copied!" label swap and just + * passes the current label down. + */ +export function CopyButton({ title, onPress }: CopyButtonProps) { + return ( + [styles.button, pressed && styles.buttonPressed]} + onPress={onPress} + > + {title} + + ); +} + +const styles = StyleSheet.create({ + button: { + borderWidth: 1, + borderColor: colors.border, + borderRadius: radii.sm, + paddingHorizontal: spacing.md, + paddingVertical: spacing.xs, + }, + buttonPressed: { + backgroundColor: colors.divider, + }, + buttonText: { + fontSize: 12, + fontWeight: '600', + color: colors.accent, + }, +}); diff --git a/examples/bare-react-native-with-js-sdk-and-flow/src/components/ErrorText.tsx b/examples/bare-react-native-with-js-sdk-and-flow/src/components/ErrorText.tsx new file mode 100644 index 0000000..881fa8f --- /dev/null +++ b/examples/bare-react-native-with-js-sdk-and-flow/src/components/ErrorText.tsx @@ -0,0 +1,28 @@ +import React from 'react'; +import { StyleProp, StyleSheet, Text, TextStyle } from 'react-native'; +import { colors, spacing } from '../consts/theme'; + +type ErrorTextProps = { + children: React.ReactNode; + style?: StyleProp; +}; + +/** + * Inline error message shown under a failed mutation/query. Extracted from + * the `color: colors.error, fontSize: 13, marginTop: spacing.sm` Text that + * had drifted into near-identical copies across App.tsx, + * WithdrawalForm.tsx, and FlowStatusScreen.tsx — the latter also added an + * extra marginBottom before its Retry button, so that stays available as a + * style override rather than baked into the default. + */ +export function ErrorText({ children, style }: ErrorTextProps) { + return {children}; +} + +const styles = StyleSheet.create({ + text: { + color: colors.error, + fontSize: 13, + marginTop: spacing.sm, + }, +}); diff --git a/examples/bare-react-native-with-js-sdk-and-flow/src/components/Header.tsx b/examples/bare-react-native-with-js-sdk-and-flow/src/components/Header.tsx new file mode 100644 index 0000000..a51555c --- /dev/null +++ b/examples/bare-react-native-with-js-sdk-and-flow/src/components/Header.tsx @@ -0,0 +1,87 @@ +import React from 'react'; +import { Pressable, StyleSheet, Text, View } from 'react-native'; +import { colors, spacing, typography } from '../consts/theme'; +import { ChevronLeftIcon } from './icons'; + +type HeaderProps = { + title: string; + /** Renders a back chevron + "Back" that calls this when tapped. Omit on + * screens with nothing to go back to (Splash, the first screen of a + * stack). */ + onBack?: () => void; + /** A single trailing affordance, e.g. Home's account icon button. Kept to + * one slot, not a generic children/icon-row API — every screen in this + * app needs at most one. */ + right?: React.ReactNode; +}; + +/** + * Every full-bleed screen renders its own Header rather than relying on + * native-stack's built-in one (navigation.tsx sets `headerShown: false`) — + * this app's redesign wants full control over the header's look (no native + * chrome/back-button styling to fight), and a single shared component here + * keeps that consistent across ~10 screens instead of each reinventing it. + */ +export function Header({ title, onBack, right }: HeaderProps) { + return ( + + + {onBack ? ( + [ + styles.backButton, + pressed && styles.backButtonPressed, + ]} + onPress={onBack} + hitSlop={8} + > + + Back + + ) : null} + + + {title} + + {right} + + ); +} + +const styles = StyleSheet.create({ + row: { + flexDirection: 'row', + alignItems: 'center', + paddingHorizontal: spacing.lg, + paddingVertical: spacing.md, + }, + // Equal-width side slots keep `title` visually centered regardless of + // whether onBack/right are present — a plain 3-cell flex row without this + // would shift the title left/right depending on which slots are filled. + side: { + minWidth: 56, + }, + rightSide: { + alignItems: 'flex-end', + }, + backButton: { + flexDirection: 'row', + alignItems: 'center', + gap: 2, + alignSelf: 'flex-start', + }, + backButtonPressed: { + opacity: 0.6, + }, + backText: { + color: colors.accent, + ...typography.bodyMedium, + }, + title: { + flex: 1, + textAlign: 'center', + color: colors.foreground, + ...typography.headline, + }, +}); diff --git a/examples/bare-react-native-with-js-sdk-and-flow/src/components/LinkButton.tsx b/examples/bare-react-native-with-js-sdk-and-flow/src/components/LinkButton.tsx new file mode 100644 index 0000000..5f92b99 --- /dev/null +++ b/examples/bare-react-native-with-js-sdk-and-flow/src/components/LinkButton.tsx @@ -0,0 +1,69 @@ +import React from 'react'; +import { Pressable, StyleSheet, Text } from 'react-native'; +import { colors } from '../consts/theme'; + +type LinkButtonProps = { + title: string; + onPress: () => void; + disabled?: boolean; + /** + * 'accent' for a plain link (e.g. the keyboard accessory's "Done"), + * 'danger' for a destructive action (e.g. "Disconnect"). + */ + tone?: 'accent' | 'danger'; + hitSlop?: number; +}; + +/** + * Bare text button with no fill or border — a tap target that's just a + * Text with a pressed-opacity feedback. Consolidates App.tsx's "Disconnect" + * (danger) and WithdrawalForm.tsx's keyboard-accessory "Done" (accent), + * which had drifted to the point that "Done" had no pressed feedback at + * all. + */ +export function LinkButton({ + title, + onPress, + disabled = false, + tone = 'accent', + hitSlop, +}: LinkButtonProps) { + return ( + + {({ pressed }) => ( + + {title} + + )} + + ); +} + +const styles = StyleSheet.create({ + text: { + fontSize: 13, + fontWeight: '600', + }, + accentText: { + color: colors.accent, + fontSize: 16, + }, + dangerText: { + color: colors.error, + }, + textPressed: { + opacity: 0.6, + }, +}); diff --git a/examples/bare-react-native-with-js-sdk-and-flow/src/components/ListRow.tsx b/examples/bare-react-native-with-js-sdk-and-flow/src/components/ListRow.tsx new file mode 100644 index 0000000..326d390 --- /dev/null +++ b/examples/bare-react-native-with-js-sdk-and-flow/src/components/ListRow.tsx @@ -0,0 +1,109 @@ +import React from 'react'; +import { + ActivityIndicator, + Image, + Pressable, + StyleSheet, + Text, + View, +} from 'react-native'; +import { colors, radii, spacing, typography } from '../consts/theme'; +import { ChevronRightIcon } from './icons'; + +type ListRowProps = { + label: string; + /** Wallet/provider icon, e.g. a WalletConnect catalog entry's spriteUrl. + * Falls back to a plain circle with the label's first letter when absent + * (not every provider in the catalog ships an icon). */ + iconUri?: string; + onPress: () => void; + /** Replaces the trailing chevron with a spinner — the row currently being + * connected to, in WalletPickerView. */ + isLoading?: boolean; + disabled?: boolean; +}; + +/** + * A single tappable row: leading icon, label, trailing chevron/spinner. + * Built for WalletPickerView's wallet list (MetaMask + WalletConnect catalog + * entries), kept generic enough that any future "pick one of these" screen + * in this app can reuse it instead of hand-rolling another Pressable row. + */ +export function ListRow({ + label, + iconUri, + onPress, + isLoading = false, + disabled = false, +}: ListRowProps) { + const isDisabled = disabled || isLoading; + + return ( + [ + styles.row, + pressed && !isDisabled && styles.rowPressed, + isDisabled && !isLoading && styles.rowDisabled, + ]} + > + {iconUri ? ( + + ) : ( + + + {label.charAt(0).toUpperCase()} + + + )} + + {label} + + {isLoading ? ( + + ) : ( + + )} + + ); +} + +const styles = StyleSheet.create({ + row: { + flexDirection: 'row', + alignItems: 'center', + paddingVertical: spacing.md, + gap: spacing.md, + }, + rowPressed: { + opacity: 0.6, + }, + rowDisabled: { + opacity: 0.4, + }, + icon: { + width: 32, + height: 32, + borderRadius: radii.full, + }, + iconFallback: { + width: 32, + height: 32, + borderRadius: radii.full, + backgroundColor: colors.divider, + alignItems: 'center', + justifyContent: 'center', + }, + iconFallbackText: { + color: colors.foregroundSecondary, + ...typography.label, + }, + label: { + flex: 1, + color: colors.foreground, + ...typography.body, + }, +}); diff --git a/examples/bare-react-native-with-js-sdk-and-flow/src/components/PrimaryButton.tsx b/examples/bare-react-native-with-js-sdk-and-flow/src/components/PrimaryButton.tsx new file mode 100644 index 0000000..2e2aa79 --- /dev/null +++ b/examples/bare-react-native-with-js-sdk-and-flow/src/components/PrimaryButton.tsx @@ -0,0 +1,77 @@ +import React from 'react'; +import { + ActivityIndicator, + Pressable, + StyleProp, + StyleSheet, + Text, + ViewStyle, +} from 'react-native'; +import { colors, radii, spacing } from '../consts/theme'; + +type PrimaryButtonProps = { + title: string; + onPress: () => void; + /** Shows a spinner in place of the label and implicitly disables the button. */ + loading?: boolean; + disabled?: boolean; + style?: StyleProp; +}; + +/** + * The filled accent CTA used throughout the app (e.g. "Connect with + * MetaMask", "Send withdrawal", "Retry", "Start a new withdrawal"). + * Extracted from the near-identical Pressable blocks duplicated across + * App.tsx, WithdrawalForm.tsx, and FlowStatusScreen.tsx. + */ +export function PrimaryButton({ + title, + onPress, + loading = false, + disabled = false, + style, +}: PrimaryButtonProps) { + const isDisabled = disabled || loading; + + return ( + [ + styles.button, + pressed && !isDisabled && styles.buttonPressed, + isDisabled && styles.buttonDisabled, + style, + ]} + onPress={onPress} + disabled={isDisabled} + > + {loading ? ( + + ) : ( + {title} + )} + + ); +} + +const styles = StyleSheet.create({ + button: { + backgroundColor: colors.accent, + borderRadius: radii.md, + paddingVertical: spacing.md, + alignItems: 'center', + justifyContent: 'center', + }, + buttonPressed: { + backgroundColor: colors.accentHover, + }, + buttonDisabled: { + opacity: 0.7, + }, + buttonText: { + color: colors.onAccent, + fontSize: 16, + fontWeight: '600', + }, +}); diff --git a/examples/bare-react-native-with-js-sdk-and-flow/src/components/Screen.tsx b/examples/bare-react-native-with-js-sdk-and-flow/src/components/Screen.tsx new file mode 100644 index 0000000..71a00e3 --- /dev/null +++ b/examples/bare-react-native-with-js-sdk-and-flow/src/components/Screen.tsx @@ -0,0 +1,87 @@ +import React from 'react'; +import { + Keyboard, + KeyboardAvoidingView, + Platform, + ScrollView, + StyleSheet, + TouchableWithoutFeedback, + View, +} from 'react-native'; +import { useSafeAreaInsets } from 'react-native-safe-area-context'; +import { colors, spacing } from '../consts/theme'; + +type ScreenProps = { + children: React.ReactNode; + /** + * Wraps content in a ScrollView + keyboard-dismiss-on-tap-outside, for + * screens with a text input that can end up behind the keyboard (Login, + * Otp, AmountView). Screens with no input (Splash, Provisioning, + * FlowStatus) don't need this. + */ + scrollsWithKeyboard?: boolean; +}; + +/** + * Every full-bleed route renders its content inside this instead of a bare + * View — it owns safe-area insets and (optionally) the keyboard-avoidance/ + * dismiss-on-tap behavior that used to live once in App.tsx (see its + * pre-redesign AppContent, which wrapped its single screen in + * KeyboardAvoidingView + ScrollView + TouchableWithoutFeedback). Now that + * each screen is its own route instead of one component swapping content, + * that behavior has to be available per-screen rather than once at the top. + */ +export function Screen({ children, scrollsWithKeyboard = false }: ScreenProps) { + const insets = useSafeAreaInsets(); + const paddedContent = ( + + {children} + + ); + + if (!scrollsWithKeyboard) { + return {paddedContent}; + } + + return ( + + + + {paddedContent} + + + + ); +} + +const styles = StyleSheet.create({ + flexOne: { + flex: 1, + }, + screen: { + flex: 1, + backgroundColor: colors.pageBackground, + }, + scrollContent: { + flexGrow: 1, + }, + content: { + flex: 1, + paddingHorizontal: spacing.lg, + }, +}); diff --git a/examples/bare-react-native-with-js-sdk-and-flow/src/components/SecondaryButton.tsx b/examples/bare-react-native-with-js-sdk-and-flow/src/components/SecondaryButton.tsx new file mode 100644 index 0000000..be74a82 --- /dev/null +++ b/examples/bare-react-native-with-js-sdk-and-flow/src/components/SecondaryButton.tsx @@ -0,0 +1,70 @@ +import React from 'react'; +import { + Pressable, + StyleProp, + StyleSheet, + Text, + ViewStyle, +} from 'react-native'; +import { colors, radii, spacing } from '../consts/theme'; + +type SecondaryButtonProps = { + title: string; + onPress: () => void; + disabled?: boolean; + style?: StyleProp; +}; + +/** + * Outline CTA for the lower-emphasis option next to a PrimaryButton (e.g. + * "Give up and start a new withdrawal"). Extracted from + * FlowStatusScreen.tsx, which was the only place this visual actually + * existed — App.tsx's "secondary" connect button is styled identically to + * its primary button, so it stays a PrimaryButton. + */ +export function SecondaryButton({ + title, + onPress, + disabled = false, + style, +}: SecondaryButtonProps) { + return ( + [ + styles.button, + pressed && !disabled && styles.buttonPressed, + disabled && styles.buttonDisabled, + style, + ]} + onPress={onPress} + disabled={disabled} + > + {title} + + ); +} + +const styles = StyleSheet.create({ + button: { + backgroundColor: colors.surface, + borderWidth: 1, + borderColor: colors.border, + borderRadius: radii.md, + paddingVertical: spacing.md, + alignItems: 'center', + justifyContent: 'center', + }, + buttonPressed: { + backgroundColor: colors.divider, + }, + buttonDisabled: { + opacity: 0.7, + }, + buttonText: { + color: colors.foregroundSecondary, + fontSize: 14, + fontWeight: '600', + }, +}); diff --git a/examples/bare-react-native-with-js-sdk-and-flow/src/components/Skeleton.tsx b/examples/bare-react-native-with-js-sdk-and-flow/src/components/Skeleton.tsx new file mode 100644 index 0000000..86f417a --- /dev/null +++ b/examples/bare-react-native-with-js-sdk-and-flow/src/components/Skeleton.tsx @@ -0,0 +1,62 @@ +import React, { useEffect, useRef } from 'react'; +import { Animated, StyleProp, ViewStyle } from 'react-native'; +import { colors, radii } from '../consts/theme'; + +type SkeletonProps = { + width: number | `${number}%`; + height: number; + borderRadius?: number; + style?: StyleProp; +}; + +/** + * A pulsing placeholder block for content that's still loading (e.g. Home's + * vault balance before the first balance query resolves). Opacity-pulses + * rather than the more common left-to-right shimmer sweep — a fixed-size + * Animated.View pulsing in place needs no gradient/mask setup, which keeps + * this dependency-free for a demo app that already has react-native-svg and + * react-native-linear-gradient available if a future pass wants the fancier + * version. + */ +export function Skeleton({ + width, + height, + borderRadius = radii.sm, + style, +}: SkeletonProps) { + const opacity = useRef(new Animated.Value(0.4)).current; + + useEffect(() => { + const pulse = Animated.loop( + Animated.sequence([ + Animated.timing(opacity, { + toValue: 1, + duration: 700, + useNativeDriver: true, + }), + Animated.timing(opacity, { + toValue: 0.4, + duration: 700, + useNativeDriver: true, + }), + ]), + ); + pulse.start(); + return () => pulse.stop(); + }, [opacity]); + + return ( + + ); +} diff --git a/examples/bare-react-native-with-js-sdk-and-flow/src/components/icons.tsx b/examples/bare-react-native-with-js-sdk-and-flow/src/components/icons.tsx new file mode 100644 index 0000000..4857133 --- /dev/null +++ b/examples/bare-react-native-with-js-sdk-and-flow/src/components/icons.tsx @@ -0,0 +1,147 @@ +/** + * Small glyph icons shared across the vault screen (VaultBalanceCard.tsx) + * and the flow status screen (FlowStatusScreen.tsx) — deposit/withdraw + * arrows, refresh, and two filled step-state glyphs (check/alert). Kept to + * this handful rather than porting demo-dashboard's full hand-drawn + * scenario illustrations (BalanceIllustration/WithdrawIllustration) — this + * is a single mobile card plus a status list, not a set of per-scenario + * landing pages, so the simpler "dashboard tier" of that reference app's + * icon set is the better fit. All paths use `currentColor` via the `color` + * prop so callers can theme them with existing theme.ts tokens instead of + * hardcoding hex here. + */ +import Svg, { Circle, Path } from 'react-native-svg'; + +type IconProps = { + size?: number; + color: string; +}; + +export function DepositIcon({ size = 18, color }: IconProps) { + return ( + + + + ); +} + +export function WithdrawIcon({ size = 18, color }: IconProps) { + return ( + + + + ); +} + +export function RefreshIcon({ size = 16, color }: IconProps) { + return ( + + + + ); +} + +/** + * Filled circle + white checkmark — a "this step is done" glyph for + * FlowStatusScreen's step list. Unlike the outline icons above, `color` + * fills the circle rather than strokes a path, since the glyph inside is + * always white for contrast regardless of what's underneath. + */ +export function CheckCircleIcon({ size = 22, color }: IconProps) { + return ( + + + + + ); +} + +/** Filled circle + white exclamation mark — a "this step failed" glyph. */ +export function AlertCircleIcon({ size = 22, color }: IconProps) { + return ( + + + + + + ); +} + +/** Back-navigation chevron - Header.tsx's back button, in place of relying + * on native-stack's own header (this app renders its own Header per screen + * instead, for full control over the full-bleed redesign's look). */ +export function ChevronLeftIcon({ size = 20, color }: IconProps) { + return ( + + + + ); +} + +/** Right-pointing chevron - ListRow.tsx's default trailing affordance for a + * tappable row (e.g. a wallet option in WalletPickerView). */ +export function ChevronRightIcon({ size = 18, color }: IconProps) { + return ( + + + + ); +} + +/** Person-in-circle glyph - Home's header button that opens AccountRoute + * (email + Log out), now that there's no persistent external-wallet chip to + * attach account controls to (see HomeView.tsx). */ +export function PersonIcon({ size = 20, color }: IconProps) { + return ( + + + + + ); +} diff --git a/examples/bare-react-native-with-js-sdk-and-flow/src/consts/config.ts b/examples/bare-react-native-with-js-sdk-and-flow/src/consts/config.ts new file mode 100644 index 0000000..a5df959 --- /dev/null +++ b/examples/bare-react-native-with-js-sdk-and-flow/src/consts/config.ts @@ -0,0 +1,44 @@ +/** + * Centralized env var reads. Values are inlined into the JS bundle at build + * time by babel-plugin-transform-inline-environment-variables (see + * babel.config.js) — there's no Expo-style EXPO_PUBLIC_* substitution in a + * bare React Native app, so this is the equivalent mechanism. + * + * Copy .env.example to .env and fill it in before running the app. + */ +/** + * Placeholder — this demo has no real hosted domain. Used both as the + * origin for Dynamic's embedded-wallet WebView (polyfills.ts's + * window.location shim) and as `metadata.universalLink` (dynamicClient.ts). + * Shared here so the two stay in sync automatically; replace with your + * app's actual domain in production. + */ +export const APP_ORIGIN = 'https://example.com'; +const BASE_CHAIN_ID = '8453'; +const BASE_USDC_ADDRESS = '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913'; + +export const config = { + dynamic: { + /** Required. https://app.dynamic.xyz/dashboard/developer/api */ + environmentId: process.env.DYNAMIC_ENVIRONMENT_ID, + /** Optional. Empty/undefined lets the SDK use its own default (production). */ + apiBaseUrl: process.env.DYNAMIC_API_BASE_URL || undefined, + /** + * Sandbox-only Dynamic API key (flow.write scope) — see .env.example. + * Used directly by src/utils/createDepositFlow.ts and + * src/utils/createWithdrawFlow.ts to create Flows server-side. + */ + apiKey: process.env.DYNAMIC_API_KEY, + }, + /** String form — what Flow's own params (fromChainId/chainId) expect. */ + chainId: BASE_CHAIN_ID, + /** + * Numeric form of the same chain ID — what `getTokenBalances`'s + * `networkId` param expects (see VaultBalanceCard.tsx/WithdrawForm.tsx). + * Kept as a single derived constant rather than each call site writing + * its own `Number(config.chainId)`, so there's one place to get this + * right instead of two-plus copies that can drift out of sync. + */ + chainIdNumber: Number(BASE_CHAIN_ID), + usdcAddress: BASE_USDC_ADDRESS, +} as const; diff --git a/examples/bare-react-native-with-js-sdk-and-flow/src/consts/flow.ts b/examples/bare-react-native-with-js-sdk-and-flow/src/consts/flow.ts new file mode 100644 index 0000000..bf57394 --- /dev/null +++ b/examples/bare-react-native-with-js-sdk-and-flow/src/consts/flow.ts @@ -0,0 +1,61 @@ +/** + * This settles real USDC on Base mainnet (see WithdrawalForm.tsx's original + * comment, now shared by DepositForm.tsx and WithdrawForm.tsx) — there's no + * testnet fallback, so a demo-appropriate cap is the only thing standing + * between a typo (e.g. "100" instead of "1.00") and an expensive mistake. + * Shared by both directions rather than given each its own limit: the same + * USDC/Base rail carries both, so there's no reason for one direction to be + * riskier than the other. Raise this if you actually need to test a larger + * amount. + */ +export const MAX_AMOUNT_USD = 5; + +/** + * Fixed, conservative ETH amount treated as "enough gas for one Flow + * withdrawal transaction" on Base mainnet — deliberately not a computed + * estimate. Flow doesn't expose a way to estimate the withdrawal + * transaction's actual gas before attachFlowSource/getFlowQuote/ + * submitFlowTransaction run (see WithdrawForm.tsx), so there's nothing to + * estimate against pre-submit; this is headroom instead. + * + * Anchored to a real measured data point, not theory: submitFlowTransaction + * asserts sufficient balance server-side by default + * (assertBalanceForGasCost), and a real withdrawal attempt against this + * threshold's first value (0.00002 ETH) was rejected with a stated + * requirement of 0.0000576 ETH — ~2.9x higher. That gap means the + * withdrawal transaction isn't just a plain ~65,000-gas ERC-20 transfer (the + * assumption the first value was sized against); it evidently costs more, + * likely from additional contract calls Flow makes as part of settlement. + * Set to ~1.7x that measured value for margin against gas price movement + * between checks — not sized from BaseScan's gas tracker/generic Base-cost + * math again, since that math was tried once already and undershot by 3x. + * This is the balance *threshold* below which Withdraw is blocked — see + * VAULT_GAS_TOPUP_ETH below for why the top-up button sends more than this. + */ +export const MIN_VAULT_GAS_ETH = '0.0001'; + +/** + * ETH amount WithdrawForm's "Send ETH to vault" button actually sends — + * deliberately higher than MIN_VAULT_GAS_ETH, not equal to it. The most + * common trigger for that button is a vault at ~0 ETH, so funding it to + * exactly the pass/fail threshold would leave zero margin for the very + * withdrawal it's meant to unblock (e.g. if the real gas cost ever lands + * marginally above the fixed estimate). Set to 2x MIN_VAULT_GAS_ETH — good + * for roughly two withdrawals per top-up at the measured real cost (see + * MIN_VAULT_GAS_ETH's comment), not a much larger, unnecessary reserve. + */ +export const VAULT_GAS_TOPUP_ETH = '0.0002'; + +/** + * Fixed, conservative ETH amount assumed sufficient for the *external* + * wallet's own gas to broadcast the "Send ETH to vault" transfer itself — + * checked against that wallet's balance before attempting the transfer, on + * top of VAULT_GAS_TOPUP_ETH, so a wallet with just enough for the transfer + * amount but nothing left for its own gas fails fast with a clear message + * instead of surfacing a raw "insufficient funds" error from the wallet + * provider (see WithdrawForm.tsx). Smaller than MIN_VAULT_GAS_ETH: this + * transfer is a plain native ETH send (~21,000 gas), simpler than whatever + * the withdrawal transaction itself does — see MIN_VAULT_GAS_ETH's comment + * for why that turned out to cost more than a plain transfer. + */ +export const EXTERNAL_WALLET_GAS_BUFFER_ETH = '0.00003'; diff --git a/examples/bare-react-native-with-js-sdk-and-flow/src/consts/theme.ts b/examples/bare-react-native-with-js-sdk-and-flow/src/consts/theme.ts new file mode 100644 index 0000000..07761ca --- /dev/null +++ b/examples/bare-react-native-with-js-sdk-and-flow/src/consts/theme.ts @@ -0,0 +1,111 @@ +/** + * Colors/spacing lifted from flow.dynamic.dev's marketing pages (its + * `--brand-*` CSS custom properties and DM Sans typography) so this demo's + * UI reads as visually related to Dynamic's own Flow demo site. + * + * Caveat: flow.dynamic.dev's actual wallet-connect/quote/status widget is + * rendered client-side after the page hydrates, so its exact screens + * weren't inspectable — this is a best-effort approximation built from the + * site's marketing-page CSS and layout, not a pixel-exact clone. We also use + * the system sans-serif font rather than DM Sans itself: bare React Native + * needs the font file linked as a native asset to use a custom font, which + * felt like unnecessary weight for a demo app. + */ +export const colors = { + pageBackground: '#F4F5F7', + surface: '#FFFFFF', + foreground: '#0E121B', + foregroundSecondary: '#525866', + muted: '#99A0AE', + border: '#E1E4EA', + divider: '#F2F3F5', + accent: '#4779FF', + accentHover: '#2F61E8', + success: '#16A34A', + error: '#DC2626', + warning: '#F59E0B', + onAccent: '#FFFFFF', + /** + * Gradient stops for the vault balance card (VaultBalanceCard.tsx). + * Deliberately darker than accent/accentHover, not just a saturated + * version of them: white text/icons need to stay readable at *every* + * point along the gradient, including its lightest corner, and + * accent (#4779FF) alone only gives ~3.9:1 contrast against white — + * under WCAG AA's 4.5:1 for normal-size text. vaultGradientStart's + * luminance keeps that corner at ~6:1. + */ + vaultGradientStart: '#3A5CC4', + vaultGradientEnd: '#131E52', + /** Translucent overlays for controls placed on the vault gradient, where + * the flat surface/border tokens above would be invisible or too dark. */ + onVaultOverlay: 'rgba(255, 255, 255, 0.14)', + onVaultOverlayPressed: 'rgba(255, 255, 255, 0.24)', + onVaultMuted: 'rgba(255, 255, 255, 0.7)', +} as const; + +export const spacing = { + xs: 4, + sm: 8, + md: 16, + lg: 24, + xl: 32, +} as const; + +export const radii = { + sm: 8, + md: 12, + lg: 16, + full: 999, +} as const; + +/** + * Font sizes/weights, extracted from what was already inlined per-component + * across the pre-redesign widgets rather than invented from scratch — + * existing screens migrating to these tokens should be a like-for-like swap, + * not a visual change. Precedents: `title` is the old App.tsx title + * (28/700), `label` is the form-label size used across Deposit/Withdraw + * (13/600), and `displayLarge` is VaultBalanceCard's balance text (40/700) — + * that one's a size coincidence, not a shared identity: `displayLarge` is + * meant as this redesign's general "big number/hero text" size, of which the + * vault balance is the first user, not the only one it's reserved for. + */ +export const typography = { + displayLarge: { fontSize: 40, fontWeight: '700' }, + title: { fontSize: 28, fontWeight: '700' }, + headline: { fontSize: 20, fontWeight: '700' }, + body: { fontSize: 15, fontWeight: '400' }, + bodyMedium: { fontSize: 15, fontWeight: '600' }, + label: { fontSize: 13, fontWeight: '600' }, + caption: { fontSize: 12, fontWeight: '400' }, +} as const; + +/** + * iOS shadow + Android elevation for surfaces that need to visually lift off + * pageBackground on the new full-bleed screens (e.g. a card floating over the + * page rather than being the entire page, as it was pre-redesign). RN doesn't + * unify the two platforms' shadow APIs, so each tier bundles both sets of + * properties — spread the whole tier into a style object on either platform. + */ +export const shadows = { + sm: { + shadowColor: '#0E121B', + shadowOffset: { width: 0, height: 1 }, + shadowOpacity: 0.06, + shadowRadius: 2, + elevation: 1, + }, + md: { + shadowColor: '#0E121B', + shadowOffset: { width: 0, height: 4 }, + shadowOpacity: 0.08, + shadowRadius: 12, + elevation: 4, + }, + lg: { + shadowColor: '#0E121B', + shadowOffset: { width: 0, height: 12 }, + shadowOpacity: 0.12, + shadowRadius: 24, + elevation: 8, + }, +} as const; diff --git a/examples/bare-react-native-with-js-sdk-and-flow/src/navigation.tsx b/examples/bare-react-native-with-js-sdk-and-flow/src/navigation.tsx new file mode 100644 index 0000000..f577fe9 --- /dev/null +++ b/examples/bare-react-native-with-js-sdk-and-flow/src/navigation.tsx @@ -0,0 +1,136 @@ +/** + * Owns the app's screen-to-screen navigation via React Navigation's + * native-stack, replacing the old App.tsx's single-component state machine + * (see git history for AppContent's pre-redesign derived-state render + * branching). Every screen renders its own Header (see components/Header.tsx) + * instead of native-stack's built-in one, hence `headerShown: false` below. + * + * Before the stack even mounts, this also owns the one-time "is there a + * session, and if so how far along is the user" check that used to be + * implicit in AppContent's hook calls — now made explicit because it decides + * which screen to land on first, not just what to render inline. Three + * independent facts feed that decision: + * 1. `useInitStatus()` — has the Dynamic client finished initializing at all? + * 2. `useUser()` — is there a signed-in user (persisted session)? + * 3. `useGetWalletAccounts()` — does that user already have a vault (WaaS + * embedded wallet)? + * Until all three have resolved, SplashView is rendered directly (not as a + * registered screen — there's nothing to navigate to yet). + */ +import { + useGetWalletAccounts, + useInitStatus, + useUser, +} from '@dynamic-labs-sdk/react-hooks'; +import { NavigationContainer } from '@react-navigation/native'; +import { + createNativeStackNavigator, + type NativeStackScreenProps, +} from '@react-navigation/native-stack'; +import { useMemo } from 'react'; +import type { EvmWalletAccount } from '@dynamic-labs-sdk/evm'; +import { SplashView } from './views/SplashView'; +import { hasVault } from './utils/vault'; +import { LoginRoute } from './routes/LoginRoute'; +import { OtpRoute } from './routes/OtpRoute'; +import { ProvisioningRoute } from './routes/ProvisioningRoute'; +import { HomeRoute } from './routes/HomeRoute'; +import { AccountRoute } from './routes/AccountRoute'; +import { ConnectWalletRoute } from './routes/ConnectWalletRoute'; +import { DepositRoute } from './routes/DepositRoute'; +import { FlowStatusRoute } from './routes/FlowStatusRoute'; +import { FundGasRoute } from './routes/FundGasRoute'; +import { WithdrawRoute } from './routes/WithdrawRoute'; +import { WithdrawAmountRoute } from './routes/WithdrawAmountRoute'; +import type { OTPVerification } from '@dynamic-labs-sdk/client'; + +export type RootStackParamList = { + Login: undefined; + Otp: { email: string; otpVerification: OTPVerification }; + Provisioning: undefined; + Home: undefined; + Account: undefined; + /** Shared across every ephemeral-connect call site — deposit, funding the + * vault's withdrawal gas, and picking a withdrawal destination — see + * ConnectWalletRoute.tsx and utils/connectEphemeralWallet.ts. */ + ConnectWallet: { purpose: 'deposit' | 'fund-gas' | 'withdraw-destination' }; + Deposit: { externalAccount: EvmWalletAccount }; + FlowStatus: { flowId: string; direction: 'deposit' | 'withdraw' }; + /** `reusableExternalAccount` carries the wallet connected for a gas + * top-up forward, so this screen can offer to reuse it as the withdrawal + * destination instead of forcing a fresh connect — see WithdrawRoute.tsx. + * Absent on the first visit (from Home). */ + Withdraw: { reusableExternalAccount?: EvmWalletAccount } | undefined; + FundGas: { vaultAddress: string; externalAccount: EvmWalletAccount }; + WithdrawAmount: { + vaultAccount: EvmWalletAccount; + externalAccount: EvmWalletAccount; + }; +}; + +export type RouteProps = + NativeStackScreenProps; + +const Stack = createNativeStackNavigator(); + +export function Navigation() { + const { data: initStatus, error: initError } = useInitStatus(); + const { data: user, isLoading: isUserLoading } = useUser(); + const walletAccountsQuery = useGetWalletAccounts(); + + const isReady = + initStatus === 'finished' && + !isUserLoading && + !walletAccountsQuery.isLoading; + + // Computed once ready, not on every render of an already-mounted + // Navigator: initialRouteName is only consulted the first time the + // Navigator mounts, so recomputing it after that would do nothing anyway + // — but memoizing keeps the intent explicit and avoids re-deriving + // hasVault() (a fresh array filter/some) on unrelated re-renders. + const initialRouteName = useMemo(() => { + if (!user) { + return 'Login'; + } + return hasVault() ? 'Home' : 'Provisioning'; + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [isReady, user, walletAccountsQuery.data]); + + // A distinct, unrecoverable-from-here state, checked after (not instead + // of) every hook above runs — without this, a failed init (bad/ + // unreachable environment config, offline cold boot) leaves `isReady` + // false forever and the app stuck on the loading spinner indefinitely, + // since nothing else ever flips `initStatus` away from 'failed'. + if (initStatus === 'failed') { + return ( + + ); + } + + if (!isReady) { + return ; + } + + return ( + + + + + + + + + + + + + + + + ); +} diff --git a/examples/bare-react-native-with-js-sdk-and-flow/src/routes/AccountRoute.tsx b/examples/bare-react-native-with-js-sdk-and-flow/src/routes/AccountRoute.tsx new file mode 100644 index 0000000..6c26bc1 --- /dev/null +++ b/examples/bare-react-native-with-js-sdk-and-flow/src/routes/AccountRoute.tsx @@ -0,0 +1,37 @@ +/** + * Account screen: signed-in email + Log out. Reached from Home's header + * icon button (see HomeView.tsx) — this is where session control lives now + * that there's no persistent external-wallet chip to attach a Logout link + * to (the old ConnectedWallet.tsx; see git history). + */ +import { useLogout, useUser } from '@dynamic-labs-sdk/react-hooks'; +import { AccountView } from '../views/AccountView'; +import type { RouteProps } from '../navigation'; + +export function AccountRoute({ navigation }: RouteProps<'Account'>) { + const { data: user } = useUser(); + + const { + mutate: logOut, + isPending: isLoggingOut, + error, + } = useLogout({ + mutateParams: { + // navigation.reset, not goBack: once logged out, Home/Account have + // nothing left to show — send the user back to a fresh Login with no + // way to swipe/back into the now-dead session's screens. + onSuccess: () => + navigation.reset({ index: 0, routes: [{ name: 'Login' }] }), + }, + }); + + return ( + logOut()} + onBack={() => navigation.goBack()} + isLoggingOut={isLoggingOut} + error={error?.message} + /> + ); +} diff --git a/examples/bare-react-native-with-js-sdk-and-flow/src/routes/ConnectWalletRoute.tsx b/examples/bare-react-native-with-js-sdk-and-flow/src/routes/ConnectWalletRoute.tsx new file mode 100644 index 0000000..afadf40 --- /dev/null +++ b/examples/bare-react-native-with-js-sdk-and-flow/src/routes/ConnectWalletRoute.tsx @@ -0,0 +1,102 @@ +/** + * Shared "connect a wallet" screen for every ephemeral-connect call site in + * the app: deposit, funding the vault's withdrawal gas, and picking a + * withdrawal destination. `purpose` picks the screen's copy and, on a + * successful connect, which screen to hand the freshly-connected account + * off to — via `navigation.replace`, not a callback threaded through route + * params: this screen has nothing useful left to show once connected, and + * `replace` keeps it out of the back stack instead of leaving a dead + * "Connect a wallet" screen a user could swipe back into. + */ +import { useState } from 'react'; +import { + connectEphemeralWallet, + EPHEMERAL_WALLET_OPTIONS, + type EphemeralWalletProviderKey, +} from '../utils/connectEphemeralWallet'; +import { WalletPickerView } from '../views/WalletPickerView'; +import { findVaultAccount } from '../utils/vault'; +import type { RouteProps } from '../navigation'; + +type Purpose = RouteProps<'ConnectWallet'>['route']['params']['purpose']; + +const SUBTITLES: Record = { + deposit: 'Connect a wallet to deposit USDC into your vault.', + 'fund-gas': "Connect a wallet to fund your vault's gas.", + 'withdraw-destination': 'Connect a wallet to receive your withdrawal.', +}; + +/** Forces a compile error if `purpose` ever grows a case this switch + * doesn't handle — see handleSelect below. Without this, extending + * `Purpose` to a union in a later PR without adding a matching branch would + * compile cleanly and just silently hang (spinner never clears, no + * navigation) the moment that case is actually hit. */ +function assertUnreachable(value: never): never { + throw new Error(`Unhandled ConnectWallet purpose: ${String(value)}`); +} + +export function ConnectWalletRoute({ + navigation, + route, +}: RouteProps<'ConnectWallet'>) { + const { purpose } = route.params; + const [connectingKey, setConnectingKey] = useState(); + const [error, setError] = useState(); + + async function handleSelect(key: string) { + setConnectingKey(key); + setError(undefined); + try { + const externalAccount = await connectEphemeralWallet( + key as EphemeralWalletProviderKey, + ); + switch (purpose) { + case 'deposit': + navigation.replace('Deposit', { externalAccount }); + break; + case 'fund-gas': { + const vaultAccount = findVaultAccount(); + if (!vaultAccount) { + // Unreachable in practice — every ConnectWallet purpose is only + // ever reached from a screen navigation.tsx's own invariant + // already guarantees a vault exists for. + throw new Error("Couldn't find your vault."); + } + navigation.replace('FundGas', { + vaultAddress: vaultAccount.address, + externalAccount, + }); + break; + } + case 'withdraw-destination': { + const vaultAccount = findVaultAccount(); + if (!vaultAccount) { + throw new Error("Couldn't find your vault."); + } + navigation.replace('WithdrawAmount', { + vaultAccount, + externalAccount, + }); + break; + } + default: + assertUnreachable(purpose); + } + } catch (e) { + setError(e instanceof Error ? e.message : 'Failed to connect wallet.'); + setConnectingKey(undefined); + } + } + + return ( + navigation.goBack()} + /> + ); +} diff --git a/examples/bare-react-native-with-js-sdk-and-flow/src/routes/DepositRoute.tsx b/examples/bare-react-native-with-js-sdk-and-flow/src/routes/DepositRoute.tsx new file mode 100644 index 0000000..33799f4 --- /dev/null +++ b/examples/bare-react-native-with-js-sdk-and-flow/src/routes/DepositRoute.tsx @@ -0,0 +1,130 @@ +/** + * Amount-only deposit: the just-connected external wallet (route.params, + * see ConnectWalletRoute.tsx) -> vault. Drives the same create -> attach + * source -> quote -> submit sequence the pre-redesign DepositForm.tsx did — + * ported here as the "smart" half, with AmountView as the dumb one. + */ +import { + attachFlowSource, + getFlowQuote, + submitFlowTransaction, +} from '@dynamic-labs-sdk/client'; +import { useMutation } from '@tanstack/react-query'; +import { useState } from 'react'; +import { AmountView } from '../views/AmountView'; +import { config } from '../consts/config'; +import { MAX_AMOUNT_USD } from '../consts/flow'; +import { createDepositFlow } from '../utils/createDepositFlow'; +import { findVaultAccount } from '../utils/vault'; +import { normalizeAmount } from '../utils/normalizeAmount'; +import { isValidAmount } from '../utils/isValidAmount'; +import type { RouteProps } from '../navigation'; + +type Step = + | 'idle' + | 'creating' + | 'attaching' + | 'quoting' + | 'awaiting-approval' + | 'error'; + +const BUSY_STEPS: ReadonlySet = new Set([ + 'creating', + 'attaching', + 'quoting', + 'awaiting-approval', +]); + +const STEP_LABELS: Partial> = { + creating: 'Creating deposit…', + attaching: 'Attaching your wallet…', + quoting: 'Getting a quote…', + 'awaiting-approval': 'Check your wallet to approve the transaction…', +}; + +export function DepositRoute({ navigation, route }: RouteProps<'Deposit'>) { + const { externalAccount } = route.params; + const [amount, setAmount] = useState(''); + const [step, setStep] = useState('idle'); + const [submitStepLabel, setSubmitStepLabel] = useState(null); + const isBusy = BUSY_STEPS.has(step); + const canSubmit = !isBusy && isValidAmount(amount, MAX_AMOUNT_USD); + const vaultAddress = findVaultAccount()?.address; + + const { + mutate: handleSubmit, + isPending: isSubmitting, + error, + } = useMutation({ + mutationFn: async ({ amount: submittedAmount }: { amount: string }) => { + if (!vaultAddress) { + // Unreachable in practice — this screen is only ever reached from + // Home, which (per navigation.tsx's own invariant) never renders + // without a vault existing. + throw new Error("Couldn't find your vault."); + } + + setSubmitStepLabel(null); + setStep('creating'); + + const normalizedAmount = normalizeAmount(submittedAmount); + + const flowId = await createDepositFlow({ + amount: normalizedAmount, + destinationAddress: vaultAddress, + }); + + setStep('attaching'); + + await attachFlowSource({ + flowId, + sourceType: 'wallet', + fromAddress: externalAccount.address, + fromChainId: config.chainId, + fromChainName: 'EVM', + }); + + setStep('quoting'); + + await getFlowQuote({ flowId }); + + setStep('awaiting-approval'); + + await submitFlowTransaction({ + flowId, + walletAccount: externalAccount, + onStepChange: submitStep => { + if (submitStep === 'approval') { + setSubmitStepLabel('Check your wallet to approve the transaction…'); + } else if (submitStep === 'transaction') { + setSubmitStepLabel('Broadcasting transaction…'); + } + }, + }); + + navigation.replace('FlowStatus', { flowId, direction: 'deposit' }); + }, + onError: () => { + setStep('error'); + setSubmitStepLabel(null); + }, + }); + + return ( + handleSubmit({ amount })} + submitLabel="Deposit" + isSubmitting={isSubmitting} + canSubmit={canSubmit} + stepLabel={ + isSubmitting ? submitStepLabel ?? STEP_LABELS[step] : undefined + } + error={error?.message} + onBack={() => navigation.goBack()} + /> + ); +} diff --git a/examples/bare-react-native-with-js-sdk-and-flow/src/routes/FlowStatusRoute.tsx b/examples/bare-react-native-with-js-sdk-and-flow/src/routes/FlowStatusRoute.tsx new file mode 100644 index 0000000..bfa4cac --- /dev/null +++ b/examples/bare-react-native-with-js-sdk-and-flow/src/routes/FlowStatusRoute.tsx @@ -0,0 +1,261 @@ +/** + * Tracks a submitted Flow from broadcast through settlement — the "smart" + * half of the pre-redesign FlowStatusScreen.tsx, porting its polling/ + * derived-state logic (buildSteps, the execution/settlement/risk label + * maps, the isFailure-before-isComplete resolution order) to feed + * FlowStatusView's props instead of rendering its own markup. See + * FlowStatusView.tsx's own top-of-file comment for the full rationale + * behind each of these — this file only recomputes the *data*, not the + * reasoning; that lives with the view now. + */ +import type { + Flow, + FlowExecutionState, + FlowSettlementState, +} from '@dynamic-labs-sdk/client'; +import { useCancelFlow, useGetFlow } from '@dynamic-labs-sdk/react-hooks'; +import { FlowStatusView, type Step } from '../views/FlowStatusView'; +import type { RouteProps } from '../navigation'; + +const EXECUTION_ORDER: FlowExecutionState[] = [ + 'initiated', + 'source_attached', + 'quoted', + 'signing', + 'broadcasted', + 'source_confirmed', +]; + +const PRE_BROADCAST_STATES: FlowExecutionState[] = [ + 'initiated', + 'source_attached', + 'quoted', + 'signing', +]; + +const EXECUTION_LABELS: Record = { + initiated: 'Initiated', + source_attached: 'Wallet attached', + quoted: 'Quote received', + signing: 'Awaiting your signature', + broadcasted: 'Broadcast to Base', + source_confirmed: 'Source transaction confirmed', + cancelled: 'Cancelled', + expired: 'Expired', + failed: 'Failed', +}; + +const SETTLEMENT_LABELS: Record = { + none: 'Not started', + routing: 'Routing', + bridging: 'Bridging', + swapping: 'Swapping assets', + settling: 'Settling', + completed: 'Completed', + failed: 'Failed', +}; + +const RISK_LABELS: Record = { + unknown: 'Unknown', + pending: 'Screening in progress', + cleared: 'Cleared', + blocked: 'Blocked', + review: 'Under review', +}; + +const SETTLEMENT_STEP_DESCRIPTIONS: Record = { + none: 'Preparing to route your funds to the destination.', + routing: 'Routing your funds to the destination.', + bridging: 'Bridging your funds across chains.', + swapping: 'Swapping assets.', + settling: 'Finalizing the transfer.', + completed: 'Funds have landed.', + failed: 'Settlement failed.', +}; + +function buildSteps(flow: Flow, direction: 'deposit' | 'withdraw'): Step[] { + const execIndex = EXECUTION_ORDER.indexOf(flow.executionState); + const isBroadcasted = execIndex >= EXECUTION_ORDER.indexOf('broadcasted'); + const isSourceConfirmed = + execIndex >= EXECUTION_ORDER.indexOf('source_confirmed'); + const isSettlementStarted = flow.settlementState !== 'none'; + const isSettled = flow.settlementState === 'completed'; + + return [ + { + key: 'broadcast', + title: 'Broadcast to Base', + description: isBroadcasted + ? 'Sent to the Base network.' + : flow.executionState === 'signing' + ? 'Waiting for you to confirm in your wallet.' + : 'Preparing your transaction.', + status: isBroadcasted ? 'completed' : 'active', + }, + { + key: 'confirm', + title: 'Confirm on Base', + description: 'Waiting for the network to confirm your transaction.', + status: isSourceConfirmed + ? 'completed' + : isBroadcasted + ? 'active' + : 'pending', + }, + { + key: 'settle', + title: 'Convert & route', + description: SETTLEMENT_STEP_DESCRIPTIONS[flow.settlementState], + status: isSettled + ? 'completed' + : isSourceConfirmed || isSettlementStarted + ? 'active' + : 'pending', + }, + { + key: 'complete', + title: + direction === 'deposit' ? 'Deposit complete' : 'Withdrawal complete', + description: + direction === 'deposit' + ? 'USDC has landed in your vault.' + : 'ETH has landed in your wallet.', + status: isSettled ? 'completed' : 'pending', + }, + ]; +} + +export function FlowStatusRoute({ + navigation, + route, +}: RouteProps<'FlowStatus'>) { + const { flowId, direction } = route.params; + const noun = direction === 'deposit' ? 'Deposit' : 'Withdrawal'; + + const { + data: flow, + isPending, + isError, + refetch, + error, + } = useGetFlow({ + flowId, + // Simple fixed 3s poll — this keeps polling even once the flow reaches + // a terminal state, unlike the previous refetchInterval callback that + // stopped polling there. Simplicity was chosen over that optimization + // here; a few extra background polls a terminal flow doesn't move on + // from is a fine trade-off for a demo app. + queryParams: { refetchInterval: 3000 }, + }); + + const { + mutate: cancelFlowMutate, + isPending: isCancelling, + error: cancelError, + } = useCancelFlow({ mutateParams: { onSuccess: () => refetch() } }); + + const onDone = () => + navigation.reset({ index: 0, routes: [{ name: 'Home' }] }); + + if (isPending) { + return ( + refetch()} + onGiveUp={onDone} + onDone={onDone} + /> + ); + } + + // Gated on `!flow`, not just `isError` — see FlowStatusView.tsx's + // top-of-file comment on why a transient background-poll error shouldn't + // blow away a perfectly healthy cached step list. + if (isError && !flow) { + const message = + error instanceof Error + ? error.message + : `Failed to load ${noun.toLowerCase()} status.`; + return ( + refetch()} + onGiveUp={onDone} + onDone={onDone} + /> + ); + } + + if (!flow) { + return null; + } + + const isFailure = + flow.executionState === 'cancelled' || + flow.executionState === 'expired' || + flow.executionState === 'failed' || + flow.settlementState === 'failed'; + const isComplete = !isFailure && flow.settlementState === 'completed'; + const isCancellable = PRE_BROADCAST_STATES.includes(flow.executionState); + + const failureTitle = + flow.executionState === 'cancelled' + ? `${noun} cancelled` + : flow.executionState === 'expired' + ? `${noun} expired` + : `${noun} failed`; + const isMutedFailure = + flow.executionState === 'cancelled' || flow.executionState === 'expired'; + const failureDescription = + flow.executionState === 'cancelled' + ? `You cancelled this ${noun.toLowerCase()} before it was broadcast.` + : flow.executionState === 'expired' + ? `This ${noun.toLowerCase()} timed out before it was broadcast. Start a new one from the vault.` + : flow.failure?.message ?? + `Something went wrong processing this ${noun.toLowerCase()}.`; + const failureHint = + !isMutedFailure && flow.failure?.retryable + ? `This step can be retried — start a new ${noun.toLowerCase()} from the vault.` + : undefined; + + return ( + refetch()} + onGiveUp={onDone} + riskState={flow.riskState} + isStale={isError} + isComplete={isComplete} + isFailure={isFailure} + failureTitle={failureTitle} + failureDescription={failureDescription} + failureHint={failureHint} + isMutedFailure={isMutedFailure} + steps={isComplete || isFailure ? undefined : buildSteps(flow, direction)} + isCancellable={isCancellable} + isCancelling={isCancelling} + cancelError={cancelError?.message} + onCancel={() => cancelFlowMutate({ flowId })} + details={{ + executionLabel: EXECUTION_LABELS[flow.executionState], + settlementLabel: SETTLEMENT_LABELS[flow.settlementState], + screeningLabel: RISK_LABELS[flow.riskState], + quoteLabel: flow.quote + ? `${flow.quote.fromAmount} → ${flow.quote.toAmount}${ + flow.quote.fees?.totalFeeUsd + ? ` (~$${flow.quote.fees.totalFeeUsd} fee)` + : '' + }` + : undefined, + flowId: flow.id, + sourceTxHash: flow.txHash ?? undefined, + destinationTxHash: flow.settlementTxHash ?? undefined, + }} + onDone={onDone} + /> + ); +} diff --git a/examples/bare-react-native-with-js-sdk-and-flow/src/routes/FundGasRoute.tsx b/examples/bare-react-native-with-js-sdk-and-flow/src/routes/FundGasRoute.tsx new file mode 100644 index 0000000..f2bf10f --- /dev/null +++ b/examples/bare-react-native-with-js-sdk-and-flow/src/routes/FundGasRoute.tsx @@ -0,0 +1,138 @@ +/** + * Sends a small, fixed ETH top-up from the just-connected external wallet + * (route.params, see ConnectWalletRoute.tsx) to the vault, so it can pay for + * a withdrawal's own gas on Base. Port of the pre-redesign + * FundVaultGasForm.tsx's mutation, driving FundGasView instead of its own + * markup. + * + * On success, hands the connected wallet back to WithdrawRoute via + * `navigation.popTo` (not `navigate` or `goBack`) — this is how WithdrawRoute + * learns a wallet is available to reuse as the withdrawal destination + * without forcing a second connect. `popTo(name, params, {merge: true})` is + * React Navigation v7's dedicated API for "pop back to an existing screen + * further down the stack and merge in new params" — confirmed against + * @react-navigation/routers' actual StackRouter source, not assumed: a plain + * `navigate('Withdraw', ...)` here does NOT pop back to the existing + * Withdraw instance (that implicit v6 behavior was replaced by `popTo` in + * v7); it pushes a second, independent Withdraw screen, stranding this + * already-used FundGas screen (and the first, now-stale Withdraw instance) + * permanently in the back-stack. Caught by adversarial review before this + * ever shipped, not discovered live — MetaMask/WalletConnect can't be + * installed on the iOS Simulator to exercise this path end-to-end here. + */ +import { + confirmTransaction, + getActiveNetworkId, + isProgrammaticNetworkSwitchAvailable, + switchActiveNetwork, + transferAmount, +} from '@dynamic-labs-sdk/client'; +import { useMutation } from '@tanstack/react-query'; +import { useState } from 'react'; +import { formatEther, parseEther } from 'viem'; +import { FundGasView } from '../views/FundGasView'; +import { config } from '../consts/config'; +import { + EXTERNAL_WALLET_GAS_BUFFER_ETH, + VAULT_GAS_TOPUP_ETH, +} from '../consts/flow'; +import { getNativeBalance } from '../utils/getNativeBalance'; +import type { RouteProps } from '../navigation'; + +export function FundGasRoute({ navigation, route }: RouteProps<'FundGas'>) { + const { vaultAddress, externalAccount } = route.params; + const [stepLabel, setStepLabel] = useState(null); + + const { + mutate: fundGas, + isPending, + error, + } = useMutation({ + mutationFn: async () => { + setStepLabel('Checking your wallet…'); + + // Preflight: transferAmount below would otherwise fail inside the + // wallet provider with a raw "insufficient funds" message that gives + // no hint it's the *external* wallet (not the vault) that's short. + const externalBalance = await getNativeBalance(externalAccount.address); + const requiredExternalBalance = + parseEther(VAULT_GAS_TOPUP_ETH) + + parseEther(EXTERNAL_WALLET_GAS_BUFFER_ETH); + if (externalBalance < requiredExternalBalance) { + throw new Error( + `Your connected wallet needs at least ${formatEther( + requiredExternalBalance, + )} ETH on Base (for the top-up plus its own gas) to fund your vault.`, + ); + } + + const { networkId: activeNetworkId } = await getActiveNetworkId({ + walletAccount: externalAccount, + }); + + // transferAmount/confirmTransaction have no networkId param at all — + // they resolve chain from whatever network the external wallet is + // currently "active" on. Must switch it to Base first if it isn't + // already, or this ETH send could land on (and be paid from) the + // wrong chain entirely. + if (activeNetworkId !== config.chainId) { + const canSwitch = isProgrammaticNetworkSwitchAvailable({ + walletAccount: externalAccount, + }); + if (!canSwitch) { + throw new Error( + 'Your connected wallet is on a different network and can’t be switched automatically. Switch it to Base mainnet yourself, then tap "Send ETH to vault" again.', + ); + } + + setStepLabel('Switching your wallet to Base…'); + await switchActiveNetwork({ + networkId: config.chainId, + walletAccount: externalAccount, + }); + + const { networkId: verifiedNetworkId } = await getActiveNetworkId({ + walletAccount: externalAccount, + }); + if (verifiedNetworkId !== config.chainId) { + throw new Error( + "Couldn't confirm your wallet switched to Base mainnet. Switch it manually and try again.", + ); + } + } + + setStepLabel('Check your wallet to approve sending ETH…'); + + const { transactionHash } = await transferAmount({ + walletAccount: externalAccount, + amount: VAULT_GAS_TOPUP_ETH, + recipient: vaultAddress, + }); + + setStepLabel('Confirming…'); + + await confirmTransaction({ + walletAccount: externalAccount, + transactionHash, + }); + + navigation.popTo( + 'Withdraw', + { reusableExternalAccount: externalAccount }, + { merge: true }, + ); + }, + onError: () => setStepLabel(null), + }); + + return ( + fundGas()} + isPending={isPending} + stepLabel={stepLabel ?? undefined} + error={error?.message} + onBack={() => navigation.goBack()} + /> + ); +} diff --git a/examples/bare-react-native-with-js-sdk-and-flow/src/routes/HomeRoute.tsx b/examples/bare-react-native-with-js-sdk-and-flow/src/routes/HomeRoute.tsx new file mode 100644 index 0000000..4915ea2 --- /dev/null +++ b/examples/bare-react-native-with-js-sdk-and-flow/src/routes/HomeRoute.tsx @@ -0,0 +1,73 @@ +/** + * Vault dashboard: balance + Deposit/Withdraw entry points + an account menu + * button. Owns the vault (WaaS wallet) lookup and its USDC balance polling — + * HomeView itself is purely prop-driven (see its own file for why the + * gradient-card JSX is a near-verbatim port of the old VaultBalanceCard.tsx). + * + * Both onDeposit and onWithdraw are wired for real — Withdraw's own + * gas-check/fund-gas/destination-reuse sub-flow lives in WithdrawRoute.tsx. + */ +import { useGetWalletAccounts } from '@dynamic-labs-sdk/react-hooks'; +import { useQuery } from '@tanstack/react-query'; +import { useMemo } from 'react'; +import { formatUnits } from 'viem'; +import { HomeView } from '../views/HomeView'; +import { getUsdcBalance } from '../utils/getUsdcBalance'; +import { findVaultAccount } from '../utils/vault'; +import type { RouteProps } from '../navigation'; + +export function HomeRoute({ navigation }: RouteProps<'Home'>) { + const walletAccountsQuery = useGetWalletAccounts(); + + // Navigation.tsx's own initialRouteName check already guarantees this + // screen is never reached without a vault existing, so `vaultAccount` + // being undefined here would mean that invariant broke, not a normal + // loading state. Re-derived via useMemo (not just findVaultAccount() + // called plain) so this component still re-renders reactively when + // walletAccountsQuery's data changes, even though findVaultAccount() + // itself reads a synchronous, always-current snapshot either way. + const vaultAccount = useMemo(() => { + return findVaultAccount(); + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [walletAccountsQuery.data]); + + // Reads the vault's USDC balance directly on-chain rather than through + // useGetTokenBalances — that hook is backed by Dynamic's own balances API + // (an indexer), which can lag a very recent transfer by several minutes + // even with forceRefresh: true. A direct balanceOf call has no such lag: + // it's always exactly what's on-chain right now. See getUsdcBalance.ts. + const { + data: usdcBalanceRaw, + isPending: isBalancePending, + isFetching: isBalanceFetching, + refetch: refetchBalance, + } = useQuery({ + queryKey: ['vault-usdc-balance', vaultAccount?.address], + queryFn: () => getUsdcBalance(vaultAccount!.address), + enabled: !!vaultAccount, + refetchInterval: 3000, + }); + + const usdcBalance = Number(formatUnits(usdcBalanceRaw ?? 0n, 6)); + + if (!vaultAccount) { + // Unreachable in practice (see the comment on `vaultAccount` above) — + // keeps this component exhaustively typed rather than passing a + // possibly-undefined address into HomeView's non-optional prop. + return null; + } + + return ( + + navigation.navigate('ConnectWallet', { purpose: 'deposit' }) + } + onWithdraw={() => navigation.navigate('Withdraw', {})} + onOpenAccount={() => navigation.navigate('Account')} + onRefresh={() => refetchBalance()} + isRefreshing={isBalanceFetching} + /> + ); +} diff --git a/examples/bare-react-native-with-js-sdk-and-flow/src/routes/LoginRoute.tsx b/examples/bare-react-native-with-js-sdk-and-flow/src/routes/LoginRoute.tsx new file mode 100644 index 0000000..a4c8793 --- /dev/null +++ b/examples/bare-react-native-with-js-sdk-and-flow/src/routes/LoginRoute.tsx @@ -0,0 +1,38 @@ +/** + * First screen: email-OTP login, replacing the old connect-external-wallet- + * and-verify-it entry point entirely (see git history for ConnectWallet.tsx/ + * VerifyWallet.tsx) — this app's session is now a Dynamic email/OTP session, + * not tied to any wallet at all. External wallets only ever get connected + * ephemerally, per Deposit/Withdraw operation (see routes built in later + * PRs of this stack). + */ +import { useSendEmailOTP } from '@dynamic-labs-sdk/react-hooks'; +import { useState } from 'react'; +import { LoginView } from '../views/LoginView'; +import type { RouteProps } from '../navigation'; + +export function LoginRoute({ navigation }: RouteProps<'Login'>) { + const [email, setEmail] = useState(''); + + const { + mutate: sendEmailOTP, + isPending, + error, + } = useSendEmailOTP({ + mutateParams: { + onSuccess: otpVerification => { + navigation.navigate('Otp', { email, otpVerification }); + }, + }, + }); + + return ( + sendEmailOTP({ email })} + isSubmitting={isPending} + error={error?.message} + /> + ); +} diff --git a/examples/bare-react-native-with-js-sdk-and-flow/src/routes/OtpRoute.tsx b/examples/bare-react-native-with-js-sdk-and-flow/src/routes/OtpRoute.tsx new file mode 100644 index 0000000..370a565 --- /dev/null +++ b/examples/bare-react-native-with-js-sdk-and-flow/src/routes/OtpRoute.tsx @@ -0,0 +1,86 @@ +/** + * Second (and last) auth screen: verifies the code sent by LoginRoute. + * Once verified, this becomes an *authenticated* session — the same "does + * this user have a vault yet" check Navigation.tsx uses to pick an initial + * route on cold boot decides where this screen sends a freshly-logged-in + * user, via `navigation.reset` rather than `navigate` so Login/Otp aren't + * left sitting in the back-stack behind a real session. + */ +import { useSendEmailOTP, useVerifyOTP } from '@dynamic-labs-sdk/react-hooks'; +import { useEffect, useRef, useState } from 'react'; +import { OtpView } from '../views/OtpView'; +import { hasVault } from '../utils/vault'; +import type { RouteProps } from '../navigation'; + +const RESEND_COOLDOWN_SECONDS = 30; + +export function OtpRoute({ navigation, route }: RouteProps<'Otp'>) { + const { email } = route.params; + const [otpVerification, setOtpVerification] = useState( + route.params.otpVerification, + ); + const [code, setCode] = useState(''); + const [cooldown, setCooldown] = useState(RESEND_COOLDOWN_SECONDS); + const cooldownIntervalRef = useRef | null>( + null, + ); + + useEffect(() => { + cooldownIntervalRef.current = setInterval(() => { + setCooldown(seconds => Math.max(0, seconds - 1)); + }, 1000); + return () => { + if (cooldownIntervalRef.current) { + clearInterval(cooldownIntervalRef.current); + } + }; + }, []); + + const { + mutate: verifyOTP, + isPending: isVerifying, + error: verifyError, + } = useVerifyOTP({ + mutateParams: { + onSuccess: () => { + // navigation.reset (not navigate): once verified this is a real + // session, and Login/Otp have nothing left to offer a back-gesture + // into — same route Navigation.tsx's own cold-boot check would send + // a returning, already-provisioned user to. + navigation.reset({ + index: 0, + routes: [{ name: hasVault() ? 'Home' : 'Provisioning' }], + }); + }, + }, + }); + + const { + mutate: resendEmailOTP, + isPending: isResending, + error: resendError, + } = useSendEmailOTP({ + mutateParams: { + onSuccess: freshOtpVerification => { + setOtpVerification(freshOtpVerification); + setCode(''); + setCooldown(RESEND_COOLDOWN_SECONDS); + }, + }, + }); + + return ( + verifyOTP({ otpVerification, verificationToken: code })} + onResend={() => resendEmailOTP({ email })} + onBack={() => navigation.goBack()} + isSubmitting={isVerifying} + isResending={isResending} + error={verifyError?.message ?? resendError?.message} + resendCooldownSeconds={cooldown} + /> + ); +} diff --git a/examples/bare-react-native-with-js-sdk-and-flow/src/routes/ProvisioningRoute.tsx b/examples/bare-react-native-with-js-sdk-and-flow/src/routes/ProvisioningRoute.tsx new file mode 100644 index 0000000..7b0b18d --- /dev/null +++ b/examples/bare-react-native-with-js-sdk-and-flow/src/routes/ProvisioningRoute.tsx @@ -0,0 +1,69 @@ +/** + * Reached right after OTP success (or on cold boot, for an authenticated + * user with no vault yet) — silently provisions the embedded EVM wallet + * ("vault") and hands off to Home the moment it exists. Port of the old + * VaultProvisioning.tsx's auto-trigger-once + describeError logic, now + * driving ProvisioningView instead of rendering its own markup, and + * navigating to Home explicitly instead of relying on a parent re-render. + */ +import { NotWaasWalletProviderError } from '@dynamic-labs-sdk/client/waas'; +import { NoWalletProviderFoundError } from '@dynamic-labs-sdk/client/core'; +import { + WaasLoadFailedError, + WaasOnboardingIncompleteError, +} from '@dynamic-labs-sdk/client'; +import { useCreateWaasWalletAccounts } from '@dynamic-labs-sdk/react-hooks'; +import { useEffect, useRef } from 'react'; +import { ProvisioningView } from '../views/ProvisioningView'; +import type { RouteProps } from '../navigation'; + +function describeError(error: Error): string { + if (error instanceof NoWalletProviderFoundError) { + return "Embedded wallets aren't enabled for this Dynamic environment yet — enable EVM embedded wallets in the dashboard, then retry."; + } + if (error instanceof NotWaasWalletProviderError) { + return "This Dynamic environment's EVM wallet provider isn't configured for embedded wallets — check the dashboard config, then retry."; + } + if (error instanceof WaasOnboardingIncompleteError) { + return 'Your account needs to finish onboarding (e.g. MFA/recovery setup) before a vault can be created.'; + } + if (error instanceof WaasLoadFailedError) { + return 'The embedded-wallet service failed to load — this is usually transient.'; + } + return error.message; +} + +export function ProvisioningRoute({ navigation }: RouteProps<'Provisioning'>) { + const { + mutate: createVault, + isPending, + isError, + error, + } = useCreateWaasWalletAccounts({ + mutateParams: { + onSuccess: () => + navigation.reset({ index: 0, routes: [{ name: 'Home' }] }), + }, + }); + + // Fires exactly once per mount — a ref (not a state flag) so it survives + // React's dev-mode double-effect without double-firing the mutation, and + // so Retry (below) doesn't need to reset anything; it calls createVault + // directly, bypassing this guard. + const hasTriggeredRef = useRef(false); + + useEffect(() => { + if (!hasTriggeredRef.current) { + hasTriggeredRef.current = true; + createVault({ chains: ['EVM'] }); + } + }, [createVault]); + + return ( + createVault({ chains: ['EVM'] })} + /> + ); +} diff --git a/examples/bare-react-native-with-js-sdk-and-flow/src/routes/WithdrawAmountRoute.tsx b/examples/bare-react-native-with-js-sdk-and-flow/src/routes/WithdrawAmountRoute.tsx new file mode 100644 index 0000000..95440b6 --- /dev/null +++ b/examples/bare-react-native-with-js-sdk-and-flow/src/routes/WithdrawAmountRoute.tsx @@ -0,0 +1,199 @@ +/** + * Amount-only withdrawal: vault -> the destination wallet chosen in + * WithdrawRoute.tsx (route.params). Paid in USDC from the vault, settled as + * native ETH to the destination — the reverse of DepositRoute.tsx's + * ETH-in/USDC-out. Same create -> attach source -> quote -> submit sequence, + * with source/destination swapped and the vault signing directly (no + * external-wallet-app hand-off, unlike Deposit). + * + * The `footer` slot (see AmountView.tsx) shows the chosen destination + * address with a "Change" link back into wallet selection — this view has + * no idea what a destination wallet even is, which is the point of that + * slot existing at all. + */ +import { + attachFlowSource, + getFlowQuote, + submitFlowTransaction, +} from '@dynamic-labs-sdk/client'; +import { useGetTokenBalances } from '@dynamic-labs-sdk/react-hooks'; +import { useMutation } from '@tanstack/react-query'; +import { useState } from 'react'; +import { StyleSheet, Text, View } from 'react-native'; +import { AmountView } from '../views/AmountView'; +import { LinkButton } from '../components/LinkButton'; +import { config } from '../consts/config'; +import { MAX_AMOUNT_USD } from '../consts/flow'; +import { colors, radii, spacing, typography } from '../consts/theme'; +import { createWithdrawFlow } from '../utils/createWithdrawFlow'; +import { normalizeAmount } from '../utils/normalizeAmount'; +import { isValidAmount } from '../utils/isValidAmount'; +import { shortAddress } from '../utils/shortAddress'; +import type { RouteProps } from '../navigation'; + +type Step = + | 'idle' + | 'creating' + | 'attaching' + | 'quoting' + | 'awaiting-approval' + | 'error'; + +const BUSY_STEPS: ReadonlySet = new Set([ + 'creating', + 'attaching', + 'quoting', + 'awaiting-approval', +]); + +const STEP_LABELS: Partial> = { + creating: 'Creating withdrawal…', + attaching: 'Attaching your vault…', + quoting: 'Getting a quote…', + 'awaiting-approval': 'Signing with your vault…', +}; + +export function WithdrawAmountRoute({ + navigation, + route, +}: RouteProps<'WithdrawAmount'>) { + const { vaultAccount, externalAccount } = route.params; + const [amount, setAmount] = useState(''); + const [step, setStep] = useState('idle'); + const [submitStepLabel, setSubmitStepLabel] = useState(null); + const isBusy = BUSY_STEPS.has(step); + + const { data: tokenBalances } = useGetTokenBalances({ + walletAccount: vaultAccount, + networkId: config.chainIdNumber, + whitelistedContracts: [config.usdcAddress], + }); + const vaultBalance = + tokenBalances?.find( + token => token.address.toLowerCase() === config.usdcAddress.toLowerCase(), + )?.balance ?? 0; + + const amountExceedsBalance = + amount.length > 0 && Number(normalizeAmount(amount)) > vaultBalance; + const canSubmit = + !isBusy && isValidAmount(amount, Math.min(MAX_AMOUNT_USD, vaultBalance)); + + const { + mutate: handleSubmit, + isPending: isSubmitting, + error, + } = useMutation({ + mutationFn: async ({ amount: submittedAmount }: { amount: string }) => { + setSubmitStepLabel(null); + setStep('creating'); + + const normalizedAmount = normalizeAmount(submittedAmount); + + const flowId = await createWithdrawFlow({ + amount: normalizedAmount, + destinationAddress: externalAccount.address, + }); + + setStep('attaching'); + + await attachFlowSource({ + flowId, + sourceType: 'wallet', + fromAddress: vaultAccount.address, + fromChainId: config.chainId, + fromChainName: 'EVM', + }); + + setStep('quoting'); + + // fromTokenAddress is what actually picks the vault's paying asset — + // attachFlowSource's wallet-source params have no token field at all, + // so without this, getFlowQuote defaults to the chain's native token + // (ETH) regardless of what the vault holds. This is the one place + // that makes the vault actually spend its USDC instead of its ETH + // gas float — confirmed against Dynamic's own demo-dashboard + // reference (github.com/dynamic-labs-oss/demo-dashboard), whose + // withdraw flow passes this same param for exactly this reason. + await getFlowQuote({ flowId, fromTokenAddress: config.usdcAddress }); + + setStep('awaiting-approval'); + + await submitFlowTransaction({ + flowId, + walletAccount: vaultAccount, + onStepChange: submitStep => { + if (submitStep === 'approval') { + setSubmitStepLabel('Signing with your vault…'); + } else if (submitStep === 'transaction') { + setSubmitStepLabel('Broadcasting transaction…'); + } + }, + }); + + navigation.replace('FlowStatus', { flowId, direction: 'withdraw' }); + }, + onError: () => { + setStep('error'); + setSubmitStepLabel(null); + }, + }); + + return ( + handleSubmit({ amount })} + submitLabel="Withdraw" + isSubmitting={isSubmitting} + canSubmit={canSubmit} + amountErrorText={ + amountExceedsBalance + ? "Amount exceeds your vault's balance." + : undefined + } + stepLabel={ + isSubmitting ? submitStepLabel ?? STEP_LABELS[step] : undefined + } + error={error?.message} + footer={ + + + Sending to {shortAddress(externalAccount.address)} + + {!isBusy ? ( + + navigation.navigate('ConnectWallet', { + purpose: 'withdraw-destination', + }) + } + /> + ) : null} + + } + onBack={() => navigation.goBack()} + /> + ); +} + +const styles = StyleSheet.create({ + destinationRow: { + flexDirection: 'row', + justifyContent: 'space-between', + alignItems: 'center', + backgroundColor: colors.divider, + borderRadius: radii.md, + paddingHorizontal: spacing.md, + paddingVertical: spacing.sm, + marginBottom: spacing.md, + }, + destinationText: { + ...typography.body, + color: colors.foregroundSecondary, + }, +}); diff --git a/examples/bare-react-native-with-js-sdk-and-flow/src/routes/WithdrawRoute.tsx b/examples/bare-react-native-with-js-sdk-and-flow/src/routes/WithdrawRoute.tsx new file mode 100644 index 0000000..740be6b --- /dev/null +++ b/examples/bare-react-native-with-js-sdk-and-flow/src/routes/WithdrawRoute.tsx @@ -0,0 +1,194 @@ +/** + * Withdraw entry point: checks the vault's native ETH balance (it pays its + * own withdrawal gas — this app doesn't sponsor gas, a paymaster/smart- + * account rabbit hole out of scope here) before ever showing an amount + * field. Mirrors the pre-redesign WithdrawForm.tsx's gas-check-first design, + * now as the stateful hub for a small multi-screen sub-flow instead of one + * component switching between inline views: + * + * insufficient gas -> ConnectWallet(fund-gas) -> FundGas -> back here + * (now with reusableExternalAccount) -> offer to reuse it or connect a + * new one for the withdrawal destination -> WithdrawAmount + * + * The five states below (checking / error / insufficient gas / choose + * destination with a reuse option / connect fresh) are simple enough, and + * specific enough to this one route, that they're rendered with a small + * local `Prompt` helper composed from existing dumb components rather than + * five separate views/*.tsx files — none of them has any reuse beyond this + * screen. + */ +import { useQuery } from '@tanstack/react-query'; +import React, { useEffect } from 'react'; +import { ActivityIndicator, StyleSheet, Text, View } from 'react-native'; +import { parseEther } from 'viem'; +import { ErrorText } from '../components/ErrorText'; +import { Header } from '../components/Header'; +import { PrimaryButton } from '../components/PrimaryButton'; +import { Screen } from '../components/Screen'; +import { SecondaryButton } from '../components/SecondaryButton'; +import { MIN_VAULT_GAS_ETH } from '../consts/flow'; +import { colors, spacing, typography } from '../consts/theme'; +import { getNativeBalance } from '../utils/getNativeBalance'; +import { findVaultAccount } from '../utils/vault'; +import { shortAddress } from '../utils/shortAddress'; +import type { RouteProps } from '../navigation'; + +type PromptProps = { + children: React.ReactNode; + onBack: () => void; +}; + +/** Shared "Withdraw" header + centered body used by every state below. */ +function Prompt({ children, onBack }: PromptProps) { + return ( + +
+ {children} + + ); +} + +export function WithdrawRoute({ navigation, route }: RouteProps<'Withdraw'>) { + const reusableExternalAccount = route.params?.reusableExternalAccount; + const vaultAccount = findVaultAccount(); + + const vaultGasQuery = useQuery({ + queryKey: ['vault-native-balance', vaultAccount?.address], + queryFn: () => getNativeBalance(vaultAccount!.address), + enabled: !!vaultAccount, + }); + const hasEnoughGas = + vaultGasQuery.data !== undefined && + vaultGasQuery.data >= parseEther(MIN_VAULT_GAS_ETH); + + // FundGasRoute lands back here via `popTo(..., {merge: true})` — the + // *existing* WithdrawRoute instance, not a fresh mount — specifically so + // the back-stack doesn't accumulate a duplicate Withdraw screen (see + // FundGasRoute.tsx's own comment). The cost of reusing the instance + // instead of remounting: react-query has no reason to refetch + // `vaultGasQuery` on its own just because `route.params` changed — its + // queryKey is keyed on the vault's address, which never changes. Without + // this effect, a user who just funded their vault would land back here + // still looking at the stale pre-top-up "insufficient gas" result. + // `reusableExternalAccount` only ever newly appears right after a + // successful top-up, so it's the right signal to force this one refetch. + useEffect(() => { + if (reusableExternalAccount) { + vaultGasQuery.refetch(); + } + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [reusableExternalAccount]); + + const onBack = () => navigation.goBack(); + + if (!vaultAccount) { + // Unreachable in practice — same invariant as HomeRoute/DepositRoute. + return null; + } + + if (vaultGasQuery.isPending) { + return ( + + + Checking your vault's ETH balance… + + ); + } + + if (vaultGasQuery.isError) { + return ( + + + Couldn't check your vault's ETH balance. Check your connection and try + again. + + vaultGasQuery.refetch()} /> + + ); + } + + if (!hasEnoughGas) { + return ( + + + Your vault doesn't have enough ETH to pay for a withdrawal's gas on + Base. Connect a wallet to send a small top-up. + + + navigation.navigate('ConnectWallet', { purpose: 'fund-gas' }) + } + /> + + ); + } + + if (reusableExternalAccount) { + return ( + + + Choose which wallet should receive your withdrawal. + + + navigation.replace('WithdrawAmount', { + vaultAccount, + externalAccount: reusableExternalAccount, + }) + } + /> + + navigation.navigate('ConnectWallet', { + purpose: 'withdraw-destination', + }) + } + /> + + ); + } + + return ( + + + Connect a wallet to receive your withdrawal. + + + navigation.navigate('ConnectWallet', { + purpose: 'withdraw-destination', + }) + } + /> + + ); +} + +const styles = StyleSheet.create({ + body: { + alignItems: 'center', + paddingTop: spacing.xl, + }, + text: { + ...typography.body, + color: colors.foregroundSecondary, + textAlign: 'center', + marginTop: spacing.sm, + }, + errorSpaced: { + textAlign: 'center', + marginBottom: spacing.md, + }, + actionSpacing: { + marginTop: spacing.lg, + alignSelf: 'stretch', + }, +}); diff --git a/examples/bare-react-native-with-js-sdk-and-flow/src/utils/connectCatalogWallet.ts b/examples/bare-react-native-with-js-sdk-and-flow/src/utils/connectCatalogWallet.ts new file mode 100644 index 0000000..9483925 --- /dev/null +++ b/examples/bare-react-native-with-js-sdk-and-flow/src/utils/connectCatalogWallet.ts @@ -0,0 +1,50 @@ +/** + * Connects a wallet from Dynamic's WalletConnect catalog (Trust Wallet, + * Rainbow, …) for exactly one operation — never persisted + * (`addToDynamicWalletAccounts: false`), see connectEphemeralWallet.ts's + * file-level comment for the full rationale. + */ +import { + appendConnectionUriToDeeplink, + getWalletConnectCatalog, +} from '@dynamic-labs-sdk/client'; +import { connectWithWalletConnectEvm } from '@dynamic-labs-sdk/evm/wallet-connect'; +import type { EvmWalletAccount } from '@dynamic-labs-sdk/evm'; +import { Linking } from 'react-native'; +import { resolveWalletAccounts } from './resolveWalletAccounts'; + +export async function connectCatalogWallet( + catalogKey: string, +): Promise { + const { uri, approval } = await connectWithWalletConnectEvm({ + addToDynamicWalletAccounts: false, + }); + + // Explicitly caught, not left to propagate: getWalletConnectCatalog's own + // underlying fetchLegacyWalletBook throws if both the CDN fetch and the + // local cache fail — mirrors the pre-redesign trustWalletConnect.ts's + // established try/catch-around-the-catalog-call pattern for exactly that + // failure mode, rather than only handling "fetched fine but this + // key/deep link is missing" below. + const wallet = await getWalletConnectCatalog() + .then(catalog => catalog.wallets[catalogKey]) + .catch(() => undefined); + const deeplinkBase = + wallet?.deeplinks?.native ?? wallet?.deeplinks?.universal; + + if (deeplinkBase) { + const deeplink = appendConnectionUriToDeeplink({ + deeplinkUrl: deeplinkBase, + connectionUri: uri, + }); + Linking.openURL(deeplink); + } else { + // Falls back to the raw wc: pairing URI rather than silently doing + // nothing — the wallet app (if installed) can still often handle a + // bare wc: link — whether the catalog fetch itself failed, or it + // succeeded but this key/deep link was missing. + Linking.openURL(uri); + } + + return resolveWalletAccounts(approval); +} diff --git a/examples/bare-react-native-with-js-sdk-and-flow/src/utils/connectEphemeralWallet.ts b/examples/bare-react-native-with-js-sdk-and-flow/src/utils/connectEphemeralWallet.ts new file mode 100644 index 0000000..13ef070 --- /dev/null +++ b/examples/bare-react-native-with-js-sdk-and-flow/src/utils/connectEphemeralWallet.ts @@ -0,0 +1,49 @@ +/** + * Connects an external wallet for exactly one operation (a deposit, a + * gas top-up, a withdrawal destination) — never persisted to Dynamic's + * wallet-account list, never signature-verified. This is the redesign's + * whole point: "always let the user connect to the wallet they want for + * the operation they want, then discard it — we don't care about it + * afterward" (see README's top-of-file Status note). + * + * `addToDynamicWalletAccounts: false` on every connect call (see + * connectMetaMask.ts/connectCatalogWallet.ts) is what makes that true at + * the Dynamic-bookkeeping level — the connected account never appears in + * getWalletAccounts(). Actually *closing* the underlying provider session + * afterward is a separate concern this SDK version has no public API for + * (see this app's git history for `discardEphemeralWallet.ts`, removed + * since it was a no-op — `disconnectWalletAccount` isn't re-exported from + * any public barrel in the installed `@dynamic-labs-sdk/client` version). + */ +import { connectMetaMask } from './connectMetaMask'; +import { connectCatalogWallet } from './connectCatalogWallet'; +import type { EvmWalletAccount } from '@dynamic-labs-sdk/evm'; + +/** + * The wallets offered in WalletPickerView for every ephemeral-connect + * purpose in this app. MetaMask connects via its own SDK/deep-link flow + * (not the generic WalletConnect catalog); the rest are resolved by key + * from getWalletConnectCatalog() — a small curated set rather than the + * catalog's full wallet list, which is large enough that surfacing all of + * it would need a search/filter UI beyond this demo's scope. + */ +export const EPHEMERAL_WALLET_OPTIONS = [ + { key: 'metamask', label: 'MetaMask' }, + { key: 'trust', label: 'Trust Wallet' }, + { key: 'rainbow', label: 'Rainbow' }, +] as const; + +export type EphemeralWalletProviderKey = + (typeof EPHEMERAL_WALLET_OPTIONS)[number]['key']; + +/** Connects the wallet identified by `key`, ephemerally (see file-level + * comment). Opens the appropriate deep link and resolves once the user + * approves in their wallet app. */ +export async function connectEphemeralWallet( + key: EphemeralWalletProviderKey, +): Promise { + if (key === 'metamask') { + return connectMetaMask(); + } + return connectCatalogWallet(key); +} diff --git a/examples/bare-react-native-with-js-sdk-and-flow/src/utils/connectMetaMask.ts b/examples/bare-react-native-with-js-sdk-and-flow/src/utils/connectMetaMask.ts new file mode 100644 index 0000000..acccb71 --- /dev/null +++ b/examples/bare-react-native-with-js-sdk-and-flow/src/utils/connectMetaMask.ts @@ -0,0 +1,26 @@ +/** + * Connects MetaMask for exactly one operation — never persisted to + * Dynamic's wallet-account list (`addToDynamicWalletAccounts: false`), see + * connectEphemeralWallet.ts's file-level comment for the full rationale. + * Uses Dynamic's own MetaMask SDK wrapper (a deep link, not the generic + * WalletConnect catalog — see connectCatalogWallet.ts for the rest). + */ +import { appendConnectionUriToDeeplink } from '@dynamic-labs-sdk/client'; +import { connectWithMetaMaskUriEvm } from '@dynamic-labs-sdk/evm/metamask'; +import type { EvmWalletAccount } from '@dynamic-labs-sdk/evm'; +import { Linking } from 'react-native'; +import { resolveWalletAccounts } from './resolveWalletAccounts'; + +const METAMASK_DEEPLINK = 'https://metamask.app.link/wc'; + +export async function connectMetaMask(): Promise { + const { uri, approval } = await connectWithMetaMaskUriEvm({ + addToDynamicWalletAccounts: false, + }); + const deeplink = appendConnectionUriToDeeplink({ + connectionUri: uri, + deeplinkUrl: METAMASK_DEEPLINK, + }); + Linking.openURL(deeplink); + return resolveWalletAccounts(approval); +} diff --git a/examples/bare-react-native-with-js-sdk-and-flow/src/utils/createDepositFlow.ts b/examples/bare-react-native-with-js-sdk-and-flow/src/utils/createDepositFlow.ts new file mode 100644 index 0000000..be04291 --- /dev/null +++ b/examples/bare-react-native-with-js-sdk-and-flow/src/utils/createDepositFlow.ts @@ -0,0 +1,60 @@ +import { config } from '../consts/config'; + +type CreateDepositFlowParams = { + /** Settlement amount in USD, e.g. "0.10". */ + amount: string; + /** The vault's address — receives USDC. */ + destinationAddress: string; +}; + +/** + * Creates a Flow deposit: the connected external wallet pays in ETH on Base + * mainnet, settled as USDC into the vault (`destinationAddress`). + * + * The process of creating your flow should be done from the backend so the + * Dynamic API token is not exposed to the client. This is just an example of + * how to do it from the client side. + */ +export const createDepositFlow = async ({ + amount, + destinationAddress, +}: CreateDepositFlowParams) => { + const res = await fetch( + `${config.dynamic.apiBaseUrl}/server/${config.dynamic.environmentId}/flow/deposit`, + { + method: 'POST', + headers: { + Authorization: `Bearer ${config.dynamic.apiKey}`, + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ + amount, + currency: 'USD', + settlementConfig: { + strategy: 'cheapest', + settlements: [ + { + chainName: 'EVM', + chainId: config.chainId, + symbol: 'USDC', + tokenAddress: config.usdcAddress, + tokenDecimals: 6, + }, + ], + }, + destinationConfig: { + destinations: [ + { + chainName: 'EVM', + type: 'address', + identifier: destinationAddress, + }, + ], + }, + }), + }, + ); + const { flow } = (await res.json()) as { flow: { id: string } }; + + return flow.id; +}; diff --git a/examples/bare-react-native-with-js-sdk-and-flow/src/utils/createWithdrawFlow.ts b/examples/bare-react-native-with-js-sdk-and-flow/src/utils/createWithdrawFlow.ts new file mode 100644 index 0000000..b32a213 --- /dev/null +++ b/examples/bare-react-native-with-js-sdk-and-flow/src/utils/createWithdrawFlow.ts @@ -0,0 +1,62 @@ +import { config } from '../consts/config'; + +type CreateWithdrawFlowParams = { + /** Settlement amount in USD, e.g. "0.10". */ + amount: string; + /** The destination wallet's address — receives native ETH. */ + destinationAddress: string; +}; + +/** + * Creates a Flow withdrawal: the vault pays in USDC, settled as native ETH + * on Base mainnet to the destination wallet (`destinationAddress`) — the + * reverse of createDepositFlow's ETH-in/USDC-out. + * + * The process of creating your flow should be done from the backend so the + * Dynamic API token is not exposed to the client. This is just an example of + * how to do it from the client side. + */ +export const createWithdrawFlow = async ({ + amount, + destinationAddress, +}: CreateWithdrawFlowParams) => { + const res = await fetch( + `${config.dynamic.apiBaseUrl}/server/${config.dynamic.environmentId}/flow/withdraw`, + { + method: 'POST', + headers: { + Authorization: `Bearer ${config.dynamic.apiKey}`, + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ + amount, + currency: 'USD', + settlementConfig: { + strategy: 'cheapest', + settlements: [ + { + chainName: 'EVM', + chainId: config.chainId, + symbol: 'ETH', + tokenAddress: '0x0000000000000000000000000000000000000000', + tokenDecimals: 18, + isNative: true, + }, + ], + }, + destinationConfig: { + destinations: [ + { + chainName: 'EVM', + type: 'address', + identifier: destinationAddress, + }, + ], + }, + }), + }, + ); + const { flow } = (await res.json()) as { flow: { id: string } }; + + return flow.id; +}; diff --git a/examples/bare-react-native-with-js-sdk-and-flow/src/utils/getNativeBalance.ts b/examples/bare-react-native-with-js-sdk-and-flow/src/utils/getNativeBalance.ts new file mode 100644 index 0000000..be23410 --- /dev/null +++ b/examples/bare-react-native-with-js-sdk-and-flow/src/utils/getNativeBalance.ts @@ -0,0 +1,23 @@ +/** + * Reads a wallet's native ETH balance on Base mainnet via a plain, public + * viem client — deliberately NOT `useGetTokenBalances` (that SDK hook only + * returns ERC-20/whitelisted token balances, e.g. USDC). Used to detect + * whether the vault has enough ETH to pay for a withdrawal's gas before + * letting the user submit one (see WithdrawRoute.tsx). + * + * A raw RPC balance read needs no wallet connection, so this sidesteps any + * "which network is the connected wallet active on" ambiguity entirely — + * Base is hardcoded here via viem's own `base` chain descriptor, not + * derived from whatever network a connected wallet happens to be on. + */ +import { createPublicClient, http, type Address } from 'viem'; +import { base } from 'viem/chains'; + +const client = createPublicClient({ + chain: base, + transport: http(), +}); + +export function getNativeBalance(address: string): Promise { + return client.getBalance({ address: address as Address }); +} diff --git a/examples/bare-react-native-with-js-sdk-and-flow/src/utils/getUsdcBalance.ts b/examples/bare-react-native-with-js-sdk-and-flow/src/utils/getUsdcBalance.ts new file mode 100644 index 0000000..ab2fcaf --- /dev/null +++ b/examples/bare-react-native-with-js-sdk-and-flow/src/utils/getUsdcBalance.ts @@ -0,0 +1,43 @@ +/** + * Reads a wallet's USDC balance on Base mainnet via a direct on-chain + * `balanceOf` call — deliberately NOT `useGetTokenBalances` (that SDK hook + * reads from Dynamic's own balances API, which is indexer-backed and can lag + * a very recent on-chain transfer by several minutes even with + * `forceRefresh: true`; that lag is what made a real, already-landed deposit + * look "missing" on the Home screen). + * + * Mirrors getNativeBalance.ts's "sidestep the ambiguity, read the chain + * directly" approach, but built from the SDK's own + * createPublicClientFromNetworkData instead of a bare viem client pointed at + * viem/chains' `base` descriptor — this app has no reason to special-case + * Base's RPC URL by hand when the SDK already exposes the project's + * configured network data (including RPC URLs) for exactly this purpose. + */ +import { getNetworksData } from '@dynamic-labs-sdk/client'; +import { createPublicClientFromNetworkData } from '@dynamic-labs-sdk/evm/viem'; +import { erc20Abi, type Address } from 'viem'; +import { config } from '../consts/config'; + +function getBaseNetworkData() { + const networkData = getNetworksData().find( + network => network.networkId === config.chainId, + ); + if (!networkData) { + throw new Error( + `No configured network data found for chain ${config.chainId} — check the Dynamic dashboard's enabled networks.`, + ); + } + return networkData; +} + +export async function getUsdcBalance(address: string): Promise { + const client = createPublicClientFromNetworkData({ + networkData: getBaseNetworkData(), + }); + return client.readContract({ + address: config.usdcAddress as Address, + abi: erc20Abi, + functionName: 'balanceOf', + args: [address as Address], + }); +} diff --git a/examples/bare-react-native-with-js-sdk-and-flow/src/utils/isValidAmount.ts b/examples/bare-react-native-with-js-sdk-and-flow/src/utils/isValidAmount.ts new file mode 100644 index 0000000..60a1388 --- /dev/null +++ b/examples/bare-react-native-with-js-sdk-and-flow/src/utils/isValidAmount.ts @@ -0,0 +1,15 @@ +/** + * Shared by DepositRoute (max = MAX_AMOUNT_USD) and WithdrawAmountRoute + * (max = min(MAX_AMOUNT_USD, the vault's current balance)) — `maxAmount` is + * the caller's job to derive, this just validates the string against it. + */ +import { normalizeAmount } from './normalizeAmount'; + +export function isValidAmount(value: string, maxAmount: number): boolean { + const normalized = normalizeAmount(value); + return ( + /^\d+(\.\d{1,2})?$/.test(normalized) && + Number(normalized) > 0 && + Number(normalized) <= maxAmount + ); +} diff --git a/examples/bare-react-native-with-js-sdk-and-flow/src/utils/normalizeAmount.ts b/examples/bare-react-native-with-js-sdk-and-flow/src/utils/normalizeAmount.ts new file mode 100644 index 0000000..669f074 --- /dev/null +++ b/examples/bare-react-native-with-js-sdk-and-flow/src/utils/normalizeAmount.ts @@ -0,0 +1,9 @@ +/** + * `decimal-pad` renders whatever decimal separator the device's region uses + * (comma vs. period) — this normalizes either input to what `isValidAmount` + * and `Number()` expect. Ported verbatim from the pre-redesign + * DepositForm.tsx. + */ +export function normalizeAmount(value: string): string { + return value.replace(',', '.'); +} diff --git a/examples/bare-react-native-with-js-sdk-and-flow/src/utils/resolveWalletAccounts.ts b/examples/bare-react-native-with-js-sdk-and-flow/src/utils/resolveWalletAccounts.ts new file mode 100644 index 0000000..88c5463 --- /dev/null +++ b/examples/bare-react-native-with-js-sdk-and-flow/src/utils/resolveWalletAccounts.ts @@ -0,0 +1,23 @@ +/** + * Shared by connectMetaMask/connectCatalogWallet: both connect flows resolve + * to the exact same shape (`approval()` resolving `{ walletAccounts }`) — + * a real, typed guarantee from the SDK + * (`WalletProviderUriConnectionResult`/`WalletConnectConnectionResult`), not + * a coincidence this relies on informally. + */ +import { + isEvmWalletAccount, + type EvmWalletAccount, +} from '@dynamic-labs-sdk/evm'; +import type { WalletAccount } from '@dynamic-labs-sdk/client'; + +export async function resolveWalletAccounts( + approval: () => Promise<{ walletAccounts: WalletAccount[] }>, +): Promise { + const { walletAccounts } = await approval(); + const account = walletAccounts[0]; + if (!account || !isEvmWalletAccount(account)) { + throw new Error('Wallet connected, but no EVM account was returned.'); + } + return account; +} diff --git a/examples/bare-react-native-with-js-sdk-and-flow/src/utils/shortAddress.ts b/examples/bare-react-native-with-js-sdk-and-flow/src/utils/shortAddress.ts new file mode 100644 index 0000000..a2bebea --- /dev/null +++ b/examples/bare-react-native-with-js-sdk-and-flow/src/utils/shortAddress.ts @@ -0,0 +1,4 @@ +/** `0x1234…abcd` — used anywhere a full address would be too wide to show. */ +export function shortAddress(address: string): string { + return `${address.slice(0, 6)}…${address.slice(-4)}`; +} diff --git a/examples/bare-react-native-with-js-sdk-and-flow/src/utils/vault.ts b/examples/bare-react-native-with-js-sdk-and-flow/src/utils/vault.ts new file mode 100644 index 0000000..175e849 --- /dev/null +++ b/examples/bare-react-native-with-js-sdk-and-flow/src/utils/vault.ts @@ -0,0 +1,25 @@ +/** + * The vault (WaaS wallet), the same way App.tsx's old AppContent derived it + * — distinct from any external wallet. Ephemeral, per-operation external + * wallets (the redesign's whole point) never persist to this list at all, + * so this stays exactly this simple even with Deposit/Withdraw connecting + * wallets ad hoc. Shared by every route that needs "the vault" (Home, + * Deposit, ConnectWallet, Withdraw, FundGas, WithdrawAmount) instead of each + * re-deriving its own copy of this filter/find. + */ +import { getWalletAccounts } from '@dynamic-labs-sdk/client'; +import { isWaasWalletAccount } from '@dynamic-labs-sdk/client/waas'; +import { + isEvmWalletAccount, + type EvmWalletAccount, +} from '@dynamic-labs-sdk/evm'; + +export function findVaultAccount(): EvmWalletAccount | undefined { + return getWalletAccounts() + .filter(wallet => isEvmWalletAccount(wallet)) + .find(wallet => isWaasWalletAccount({ walletAccount: wallet })); +} + +export function hasVault(): boolean { + return !!findVaultAccount(); +} diff --git a/examples/bare-react-native-with-js-sdk-and-flow/src/views/AccountView.tsx b/examples/bare-react-native-with-js-sdk-and-flow/src/views/AccountView.tsx new file mode 100644 index 0000000..80b4b9c --- /dev/null +++ b/examples/bare-react-native-with-js-sdk-and-flow/src/views/AccountView.tsx @@ -0,0 +1,74 @@ +/** + * Account screen: the signed-in email plus a Log out action. Purely + * prop-driven — AccountRoute owns the useLogout mutation and passes down its + * isPending/error state instead of this view calling the SDK itself. + * + * The Log out action reuses LinkButton with tone="danger", matching the + * destructive-action styling ConnectedWallet.tsx already established for its + * own Logout button — a single visual language for "sign the user out" + * across both the old chip-based header and this screen. + */ +import React from 'react'; +import { StyleSheet, Text, View } from 'react-native'; +import { Screen } from '../components/Screen'; +import { Header } from '../components/Header'; +import { ErrorText } from '../components/ErrorText'; +import { LinkButton } from '../components/LinkButton'; +import { colors, spacing, typography } from '../consts/theme'; + +type AccountViewProps = { + email: string; + onLogout: () => void; + onBack: () => void; + isLoggingOut: boolean; + error?: string; +}; + +export function AccountView({ + email, + onLogout, + onBack, + isLoggingOut, + error, +}: AccountViewProps) { + return ( + +
+ + + Signed in as + {email} + + + + + + + {error ? {error} : null} + + ); +} + +const styles = StyleSheet.create({ + row: { + marginTop: spacing.lg, + }, + label: { + color: colors.foregroundSecondary, + ...typography.label, + }, + value: { + color: colors.foreground, + marginTop: spacing.xs, + ...typography.body, + }, + logoutRow: { + marginTop: spacing.lg, + alignItems: 'flex-start', + }, +}); diff --git a/examples/bare-react-native-with-js-sdk-and-flow/src/views/AmountView.tsx b/examples/bare-react-native-with-js-sdk-and-flow/src/views/AmountView.tsx new file mode 100644 index 0000000..db0861f --- /dev/null +++ b/examples/bare-react-native-with-js-sdk-and-flow/src/views/AmountView.tsx @@ -0,0 +1,175 @@ +/** + * Dumb, prop-driven amount entry view — shared shape for Deposit and + * Withdraw, which differ only in copy (title/hint/submitLabel) and in + * whether there's a destination-wallet row to show below the hint (see + * `footer`). All amount-flow mechanics (create -> attach source -> quote -> + * submit, validation, busy state) stay in the route/widget that renders this + * — this component only knows about the amount TextInput, the hint/error + * text, and the submit button, exactly like DepositForm.tsx/ + * WithdrawAmountForm.tsx's shared layout below their inputs. + */ +import React from 'react'; +import { + InputAccessoryView, + Keyboard, + Platform, + StyleSheet, + Text, + TextInput, + View, +} from 'react-native'; +import { ErrorText } from '../components/ErrorText'; +import { Header } from '../components/Header'; +import { LinkButton } from '../components/LinkButton'; +import { PrimaryButton } from '../components/PrimaryButton'; +import { Screen } from '../components/Screen'; +import { colors, radii, spacing, typography } from '../consts/theme'; + +type Props = { + title: string; + hint: string; + amount: string; + onChangeAmount: (value: string) => void; + onSubmit: () => void; + submitLabel: string; + isSubmitting: boolean; + canSubmit: boolean; + stepLabel?: string; + error?: string; + amountErrorText?: string; + onBack: () => void; + /** Composable slot rendered between the hint and the submit button — e.g. + * a "Sending to 0x123…abcd [Change]" row that WithdrawAmountRoute injects + * for the withdraw case but DepositRoute doesn't use at all. This view + * has no idea what a "destination wallet" is — that's the whole point of + * this slot. */ + footer?: React.ReactNode; +}; + +// decimal-pad/number-pad have no return key on iOS to hit "Done" with, so +// this pairs the amount field with its own accessory toolbar above the +// keyboard as the way to dismiss it — same pattern as DepositForm.tsx/ +// WithdrawAmountForm.tsx, just under this view's own nativeID so the two +// don't collide if both ever mount at once. +const AMOUNT_INPUT_ACCESSORY_ID = 'amount-view-done'; + +export function AmountView({ + title, + hint, + amount, + onChangeAmount, + onSubmit, + submitLabel, + isSubmitting, + canSubmit, + stepLabel, + error, + amountErrorText, + onBack, + footer, +}: Props) { + return ( + + {/* onBack is withheld while submitting rather than just hiding a + * second Back affordance below the button (which is what this used + * to be, back when DepositForm.tsx/WithdrawAmountForm.tsx had no + * Header at all) — the Header's Back is now the only way out of this + * screen, so it has to carry that same "can't leave mid-submit" rule + * itself instead of a redundant link duplicating it further down. */} +
+ + Amount (USD) + + {Platform.OS === 'ios' ? ( + + + + + + ) : null} + + {hint} + + {amountErrorText ? ( + + {amountErrorText} + + ) : null} + + {footer} + + + + {isSubmitting && stepLabel ? ( + {stepLabel} + ) : null} + {error ? {error} : null} + + ); +} + +const styles = StyleSheet.create({ + label: { + ...typography.label, + color: colors.foregroundSecondary, + marginBottom: spacing.xs, + }, + input: { + ...typography.body, + borderWidth: 1, + borderColor: colors.border, + borderRadius: radii.md, + paddingHorizontal: spacing.md, + paddingVertical: spacing.sm, + color: colors.foreground, + marginBottom: spacing.md, + }, + hint: { + ...typography.caption, + color: colors.foregroundSecondary, + lineHeight: 17, + marginBottom: spacing.md, + }, + amountErrorSpaced: { + marginTop: -spacing.sm, + marginBottom: spacing.md, + }, + stepLabel: { + ...typography.caption, + color: colors.foregroundSecondary, + marginTop: spacing.sm, + textAlign: 'center', + }, + accessoryBar: { + flexDirection: 'row', + justifyContent: 'flex-end', + backgroundColor: colors.surface, + borderTopWidth: 1, + borderTopColor: colors.border, + paddingHorizontal: spacing.lg, + paddingVertical: spacing.sm, + }, +}); diff --git a/examples/bare-react-native-with-js-sdk-and-flow/src/views/FlowStatusView.tsx b/examples/bare-react-native-with-js-sdk-and-flow/src/views/FlowStatusView.tsx new file mode 100644 index 0000000..d1f38c3 --- /dev/null +++ b/examples/bare-react-native-with-js-sdk-and-flow/src/views/FlowStatusView.tsx @@ -0,0 +1,657 @@ +/** + * Dumb, prop-driven port of FlowStatusScreen.tsx's presentational half — the + * step list, risk banner, complete/failure summaries, and collapsible + * technical-details block, with every place that used to read `flow` + * directly (or react-query's isPending/isError/error/isCancelling/ + * cancelError) now reading the equivalent value from props instead. The + * route/widget that renders this owns useGetFlow/useCancelFlow and all the + * derived-state computation (buildSteps, isFailure/isComplete resolution, + * the failure title/description/hint strings, the technical-details label + * strings) — this view has no @dynamic-labs-sdk/react-hooks or react-query + * import at all, only a type-only import of FlowRiskState for prop typing. + * + * `showDetails` is the one exception to "props are the only state": it's + * pure UI toggle state with no bearing on any business logic, so — exactly + * like the original FlowStatusScreen.tsx — it stays a local useState here + * rather than being lifted to the caller. + * + * Branch order mirrors the original exactly: isLoading -> loadError (full + * takeover, only when there's truly nothing cached) -> isFailure -> isComplete + * -> otherwise (in-progress step list). See FlowStatusScreen.tsx's top-of-file + * comment for why isFailure is resolved before isComplete, and why the + * loadError takeover is gated on "nothing to show" rather than plain isError. + */ +import type { FlowRiskState } from '@dynamic-labs-sdk/client'; +import Clipboard from '@react-native-clipboard/clipboard'; +import React, { useEffect, useRef, useState } from 'react'; +import { ActivityIndicator, StyleSheet, Text, View } from 'react-native'; +import { CopyButton } from '../components/CopyButton'; +import { ErrorText } from '../components/ErrorText'; +import { Header } from '../components/Header'; +import { AlertCircleIcon, CheckCircleIcon } from '../components/icons'; +import { LinkButton } from '../components/LinkButton'; +import { PrimaryButton } from '../components/PrimaryButton'; +import { Screen } from '../components/Screen'; +import { SecondaryButton } from '../components/SecondaryButton'; +import { colors, radii, spacing, typography } from '../consts/theme'; + +export type StepStatus = 'completed' | 'active' | 'pending'; + +export type Step = { + key: string; + title: string; + description: string; + status: StepStatus; +}; + +export type Details = { + executionLabel: string; + settlementLabel: string; + screeningLabel: string; + quoteLabel?: string; + flowId: string; + sourceTxHash?: string; + destinationTxHash?: string; +}; + +type Props = { + direction: 'deposit' | 'withdraw'; + /** Mirrors FlowStatusScreen.tsx's `isPending` (react-query's initial-load + * state, not a mutation's). */ + isLoading: boolean; + /** Set ONLY when there's truly nothing cached to show (mirrors + * FlowStatusScreen.tsx's `isError && !flow` branch) — the full-page error + * takeover. */ + loadError?: string; + onRetryLoad: () => void; + onGiveUp: () => void; + + // The rest are present once loaded (isLoading === false && !loadError): + riskState?: FlowRiskState; + /** Mirrors the `isError` (but WITH a cached flow present) inline "stale" + * notice. */ + isStale?: boolean; + isComplete?: boolean; + isFailure?: boolean; + failureTitle?: string; + failureDescription?: string; + failureHint?: string; + isMutedFailure?: boolean; + /** Only meaningful when !isComplete && !isFailure — the in-progress step + * list. */ + steps?: Step[]; + isCancellable?: boolean; + isCancelling?: boolean; + cancelError?: string; + onCancel?: () => void; + details?: Details; + onDone: () => void; +}; + +function shortHash(hash: string): string { + return `${hash.slice(0, 8)}…${hash.slice(-6)}`; +} + +function StepIcon({ status }: { status: StepStatus }) { + if (status === 'completed') { + return ; + } + if (status === 'active') { + return ( + + + + ); + } + return ; +} + +function StepRow({ step, isLast }: { step: Step; isLast: boolean }) { + return ( + + + + {!isLast ? ( + + ) : null} + + + + {step.title} + + {step.description} + + + ); +} + +function RiskBanner({ riskState }: { riskState?: FlowRiskState }) { + if (riskState !== 'blocked' && riskState !== 'review') { + return null; + } + const isBlocked = riskState === 'blocked'; + return ( + + + {isBlocked + ? 'This transfer was blocked during compliance screening. Contact support for help.' + : 'This transfer is under manual compliance review — this can take longer than usual.'} + + + ); +} + +/** Small "Copy" button with transient "Copied!" feedback. */ +function CopyRow({ label, value }: { label: string; value: string }) { + const [justCopied, setJustCopied] = useState(false); + const timeoutRef = useRef | null>(null); + + useEffect(() => { + return () => { + if (timeoutRef.current) { + clearTimeout(timeoutRef.current); + } + }; + }, []); + + return ( + + + {label} + + {value.length > 20 ? shortHash(value) : value} + + + { + Clipboard.setString(value); + setJustCopied(true); + if (timeoutRef.current) { + clearTimeout(timeoutRef.current); + } + timeoutRef.current = setTimeout(() => setJustCopied(false), 1500); + }} + /> + + ); +} + +function TechnicalDetails({ details }: { details: Details }) { + return ( + + + + Execution + {details.executionLabel} + + + Settlement + {details.settlementLabel} + + + Screening + {details.screeningLabel} + + {details.quoteLabel ? ( + + Quote + {details.quoteLabel} + + ) : null} + + + {details.sourceTxHash ? ( + + ) : null} + {details.destinationTxHash ? ( + + ) : null} + + ); +} + +function DetailsToggle({ + expanded, + onToggle, +}: { + expanded: boolean; + onToggle: () => void; +}) { + return ( + + + + ); +} + +function CompleteSummary({ + direction, + onDone, +}: { + direction: 'deposit' | 'withdraw'; + onDone: () => void; +}) { + const noun = direction === 'deposit' ? 'Deposit' : 'Withdrawal'; + return ( + + + {`${noun} complete`} + + {direction === 'deposit' + ? 'USDC has landed in your vault.' + : 'ETH has landed in your wallet.'} + + + + ); +} + +function FailureSummary({ + title, + description, + hint, + isMuted, + onDone, +}: { + title: string; + description: string; + hint?: string; + isMuted: boolean; + onDone: () => void; +}) { + return ( + + + + {title} + + {description} + {!isMuted && hint ? {hint} : null} + + + ); +} + +export function FlowStatusView({ + direction, + isLoading, + loadError, + onRetryLoad, + onGiveUp, + riskState, + isStale, + isComplete, + isFailure, + failureTitle, + failureDescription, + failureHint, + isMutedFailure, + steps, + isCancellable, + isCancelling, + cancelError, + onCancel, + details, + onDone, +}: Props) { + const [showDetails, setShowDetails] = useState(false); + const noun = direction === 'deposit' ? 'Deposit' : 'Withdrawal'; + + // No onBack on any branch below: mid-flight this isn't cancelable via a + // header back button (matches the original's behavior of no navigation + // away at all while in-progress) — the in-progress branch's own Cancel + // link and the terminal branches' "Back to vault" button are the only + // ways off this screen, same as before this Header existed. + const headerTitle = `${noun} status`; + + if (isLoading) { + return ( + +
+ + + Loading {noun.toLowerCase()} status… + + + ); + } + + if (loadError) { + return ( + +
+ Couldn't load status + {loadError} + + + + ); + } + + if (isFailure) { + return ( + +
+ + + setShowDetails(v => !v)} + /> + {showDetails && details ? : null} + + ); + } + + if (isComplete) { + return ( + +
+ + + setShowDetails(v => !v)} + /> + {showDetails && details ? : null} + + ); + } + + const inProgressSteps = steps ?? []; + + return ( + +
+ + {isStale ? ( + + + Couldn't refresh the latest status — showing the last known state. + + + ) : null} + {`${noun} in progress`} + + + {inProgressSteps.map((step, index) => ( + + ))} + + + {isCancellable ? ( + + {cancelError ? ( + {cancelError} + ) : null} + onCancel?.()} + /> + + ) : null} + + setShowDetails(v => !v)} + /> + {showDetails && details ? : null} + + + This updates automatically every few seconds — you can leave and come + back to this app while it's in progress. + + + ); +} + +const styles = StyleSheet.create({ + centered: { + alignItems: 'center', + paddingVertical: spacing.lg, + }, + title: { + fontSize: 18, + fontWeight: '700', + color: colors.foreground, + marginBottom: spacing.md, + }, + stepsBlock: { + marginBottom: spacing.sm, + }, + stepRow: { + flexDirection: 'row', + }, + stepIconColumn: { + width: 24, + alignItems: 'center', + }, + stepConnector: { + width: 2, + flex: 1, + minHeight: 20, + marginTop: spacing.xs, + backgroundColor: colors.border, + }, + stepConnectorActive: { + backgroundColor: colors.success, + }, + activeIconWrap: { + width: 24, + height: 24, + alignItems: 'center', + justifyContent: 'center', + }, + pendingDot: { + width: 12, + height: 12, + borderRadius: radii.full, + marginTop: 6, + backgroundColor: colors.divider, + borderWidth: 2, + borderColor: colors.border, + }, + stepTextColumn: { + flex: 1, + marginLeft: spacing.md, + paddingBottom: spacing.lg, + }, + stepTitle: { + ...typography.bodyMedium, + color: colors.foreground, + }, + stepTitleMuted: { + color: colors.foregroundSecondary, + }, + stepDescription: { + fontSize: 13, + color: colors.foregroundSecondary, + marginTop: 2, + }, + riskBanner: { + borderRadius: radii.md, + borderWidth: 1, + padding: spacing.md, + marginBottom: spacing.md, + }, + riskBannerBlocked: { + backgroundColor: 'rgba(220, 38, 38, 0.08)', + borderColor: colors.error, + }, + riskBannerReview: { + backgroundColor: 'rgba(245, 158, 11, 0.1)', + borderColor: colors.warning, + }, + riskBannerText: { + ...typography.label, + color: colors.foreground, + }, + staleNotice: { + borderRadius: radii.md, + borderWidth: 1, + borderColor: colors.border, + backgroundColor: colors.divider, + padding: spacing.sm, + marginBottom: spacing.md, + }, + staleNoticeText: { + fontSize: 12, + color: colors.foregroundSecondary, + }, + cancelRow: { + marginBottom: spacing.md, + }, + detailsToggleRow: { + marginTop: spacing.sm, + marginBottom: spacing.xs, + }, + detailsBlock: { + marginTop: spacing.xs, + }, + divider: { + height: 1, + backgroundColor: colors.divider, + marginBottom: spacing.md, + }, + detailRow: { + flexDirection: 'row', + justifyContent: 'space-between', + paddingVertical: spacing.xs, + }, + detailLabel: { + fontSize: 13, + color: colors.foregroundSecondary, + }, + detailValue: { + ...typography.label, + color: colors.foreground, + flexShrink: 1, + textAlign: 'right', + marginLeft: spacing.md, + }, + copyRow: { + flexDirection: 'row', + alignItems: 'center', + justifyContent: 'space-between', + marginTop: spacing.sm, + }, + copyRowText: { + flex: 1, + marginRight: spacing.sm, + }, + copyRowLabel: { + fontSize: 12, + color: colors.foregroundSecondary, + }, + copyRowValue: { + fontSize: 14, + fontWeight: '600', + color: colors.foreground, + }, + summaryCentered: { + alignItems: 'center', + paddingVertical: spacing.lg, + }, + summaryTitle: { + fontSize: 18, + fontWeight: '700', + color: colors.foreground, + marginTop: spacing.md, + }, + summaryTitleMuted: { + color: colors.foregroundSecondary, + }, + summaryDescription: { + fontSize: 14, + color: colors.foregroundSecondary, + textAlign: 'center', + marginTop: spacing.xs, + paddingHorizontal: spacing.md, + }, + summaryHint: { + fontSize: 12, + color: colors.foregroundSecondary, + textAlign: 'center', + marginTop: spacing.sm, + paddingHorizontal: spacing.md, + }, + summaryButton: { + marginTop: spacing.lg, + alignSelf: 'stretch', + }, + hint: { + fontSize: 12, + color: colors.foregroundSecondary, + lineHeight: 17, + marginTop: spacing.md, + }, + doneButton: { + marginTop: spacing.md, + }, + errorTitle: { + fontSize: 16, + fontWeight: '700', + color: colors.error, + marginBottom: spacing.xs, + }, + errorTextSpaced: { + marginBottom: spacing.md, + }, +}); diff --git a/examples/bare-react-native-with-js-sdk-and-flow/src/views/FundGasView.tsx b/examples/bare-react-native-with-js-sdk-and-flow/src/views/FundGasView.tsx new file mode 100644 index 0000000..af81f25 --- /dev/null +++ b/examples/bare-react-native-with-js-sdk-and-flow/src/views/FundGasView.tsx @@ -0,0 +1,76 @@ +/** + * Dumb, prop-driven "fund your vault's gas" view — the presentational half + * of FundVaultGasForm.tsx's screen. All the actual top-up mechanics + * (external-wallet balance preflight, network switch, transferAmount, + * confirmTransaction, the vault-gas-balance refetch) stay in the route/ + * widget that renders this; this view only knows about the hint copy, the + * "Send N ETH to vault" button, and the busy/step-label/error layout below + * it — ported verbatim from FundVaultGasForm.tsx's render. + */ +import React from 'react'; +import { StyleSheet, Text } from 'react-native'; +import { ErrorText } from '../components/ErrorText'; +import { Header } from '../components/Header'; +import { PrimaryButton } from '../components/PrimaryButton'; +import { Screen } from '../components/Screen'; +import { colors, spacing, typography } from '../consts/theme'; + +type Props = { + topupAmountEth: string; + onFund: () => void; + isPending: boolean; + stepLabel?: string; + error?: string; + onBack: () => void; +}; + +export function FundGasView({ + topupAmountEth, + onFund, + isPending, + stepLabel, + error, + onBack, +}: Props) { + return ( + + {/* onBack withheld while pending, same as AmountView.tsx — the + * Header's Back is the only way out of this screen now, so it carries + * the "can't leave mid-transfer" rule itself instead of a second, + * redundant link duplicating it below the button (which is what this + * used to be, back when FundVaultGasForm.tsx had no Header at all). */} +
+ + + Your vault doesn't have enough ETH to pay for a withdrawal's gas on + Base. Send a small top-up from your connected wallet to continue. + + + + + {isPending && stepLabel ? ( + {stepLabel} + ) : null} + {error ? {error} : null} + + ); +} + +const styles = StyleSheet.create({ + hint: { + ...typography.caption, + color: colors.foregroundSecondary, + lineHeight: 17, + marginBottom: spacing.md, + }, + stepLabel: { + ...typography.caption, + color: colors.foregroundSecondary, + marginTop: spacing.sm, + textAlign: 'center', + }, +}); diff --git a/examples/bare-react-native-with-js-sdk-and-flow/src/views/HomeView.tsx b/examples/bare-react-native-with-js-sdk-and-flow/src/views/HomeView.tsx new file mode 100644 index 0000000..9f6ff3b --- /dev/null +++ b/examples/bare-react-native-with-js-sdk-and-flow/src/views/HomeView.tsx @@ -0,0 +1,275 @@ +/** + * Home screen: a header with an account-icon button plus the vault balance + * card (gradient hero) with Deposit/Withdraw entry points. Purely + * prop-driven — HomeRoute owns the useGetTokenBalances polling and passes + * the resolved balanceUsd/vaultAddress down here, along with the + * Deposit/Withdraw/Refresh/Account callbacks. + * + * The gradient card below is ported near-verbatim from the pre-redesign + * VaultBalanceCard.tsx (see that file's own comment for why the 3-layer + * shadowWrapper/card/gradient structure exists, and why its styling is its + * own translucent button/copy-chip look rather than PrimaryButton/ + * SecondaryButton). The only real differences here: data and callbacks come + * from props instead of a useGetTokenBalances call, and there's no internal + * 15s poll — HomeRoute owns that now. + */ +import React, { useEffect, useRef, useState } from 'react'; +import { Pressable, StyleSheet, Text, View } from 'react-native'; +import LinearGradient from 'react-native-linear-gradient'; +import Clipboard from '@react-native-clipboard/clipboard'; +import { Screen } from '../components/Screen'; +import { Header } from '../components/Header'; +import { Skeleton } from '../components/Skeleton'; +import { + DepositIcon, + PersonIcon, + RefreshIcon, + WithdrawIcon, +} from '../components/icons'; +import { colors, radii, spacing, typography } from '../consts/theme'; +import { shortAddress } from '../utils/shortAddress'; + +type HomeViewProps = { + /** undefined = still loading (renders '—', matching VaultBalanceCard's + * isPending state). */ + balanceUsd: number | undefined; + vaultAddress: string; + onDeposit: () => void; + onWithdraw: () => void; + onOpenAccount: () => void; + onRefresh: () => void; + isRefreshing: boolean; +}; + +export function HomeView({ + balanceUsd, + vaultAddress, + onDeposit, + onWithdraw, + onOpenAccount, + onRefresh, + isRefreshing, +}: HomeViewProps) { + const [justCopied, setJustCopied] = useState(false); + const copyTimeoutRef = useRef | null>(null); + + // Matches FlowStatusView.tsx's CopyRow, which implements the same + // "Copied!" transient-flag pattern and clears its timeout on unmount — + // without this, navigating away within the 1500ms window still fires + // setJustCopied on an unmounted component (harmless in React 18, but an + // avoidable inconsistency between two copies of the same pattern). + useEffect(() => { + return () => { + if (copyTimeoutRef.current) { + clearTimeout(copyTimeoutRef.current); + } + }; + }, []); + + return ( + +
+ + + } + /> + + + + + + + + Vault + + [ + styles.refreshButton, + pressed && styles.overlayPressed, + ]} + disabled={isRefreshing} + onPress={onRefresh} + > + + + + + {balanceUsd === undefined ? ( + + ) : ( + {`$${balanceUsd.toFixed(2)}`} + )} + USDC · Base + + [ + styles.addressChip, + pressed && styles.overlayPressed, + ]} + onPress={() => { + Clipboard.setString(vaultAddress); + setJustCopied(true); + if (copyTimeoutRef.current) { + clearTimeout(copyTimeoutRef.current); + } + copyTimeoutRef.current = setTimeout( + () => setJustCopied(false), + 1500, + ); + }} + > + + {shortAddress(vaultAddress)} + + + {justCopied ? 'Copied!' : 'Copy'} + + + + + [ + styles.actionButton, + pressed && styles.overlayPressed, + ]} + onPress={onDeposit} + > + + Deposit + + [ + styles.actionButton, + pressed && styles.overlayPressed, + ]} + onPress={onWithdraw} + > + + Withdraw + + + + + + + ); +} + +const styles = StyleSheet.create({ + shadowWrapper: { + borderRadius: radii.lg, + // Lifts the card off the page background. Must NOT also have + // overflow: 'hidden' (see `card` below) or the shadow disappears. + shadowColor: colors.vaultGradientEnd, + shadowOffset: { width: 0, height: 8 }, + shadowOpacity: 0.25, + shadowRadius: 16, + elevation: 6, + }, + card: { + borderRadius: radii.lg, + overflow: 'hidden', + }, + content: { + padding: spacing.lg, + }, + headerRow: { + flexDirection: 'row', + alignItems: 'center', + justifyContent: 'space-between', + }, + eyebrow: { + fontSize: 12, + fontWeight: '700', + textTransform: 'uppercase', + letterSpacing: 0.6, + color: colors.onVaultMuted, + }, + refreshButton: { + width: 32, + height: 32, + borderRadius: radii.full, + backgroundColor: colors.onVaultOverlay, + alignItems: 'center', + justifyContent: 'center', + }, + balance: { + ...typography.displayLarge, + color: colors.onAccent, + marginTop: spacing.md, + fontVariant: ['tabular-nums'], + }, + balanceSkeleton: { + marginTop: spacing.md, + backgroundColor: colors.onVaultOverlay, + }, + balanceHint: { + fontSize: 13, + color: colors.onVaultMuted, + marginTop: spacing.xs, + }, + addressChip: { + flexDirection: 'row', + alignItems: 'center', + alignSelf: 'flex-start', + justifyContent: 'space-between', + gap: spacing.sm, + backgroundColor: colors.onVaultOverlay, + borderRadius: radii.full, + paddingVertical: spacing.sm, + paddingHorizontal: spacing.md, + marginTop: spacing.lg, + }, + addressValue: { + ...typography.label, + color: colors.onAccent, + }, + addressAction: { + fontSize: 12, + fontWeight: '600', + color: colors.onVaultMuted, + }, + actionRow: { + flexDirection: 'row', + gap: spacing.sm, + marginTop: spacing.lg, + }, + actionButton: { + flex: 1, + flexDirection: 'row', + alignItems: 'center', + justifyContent: 'center', + gap: spacing.xs, + backgroundColor: colors.onVaultOverlay, + borderRadius: radii.md, + paddingVertical: spacing.md, + }, + actionLabel: { + ...typography.bodyMedium, + color: colors.onAccent, + }, + overlayPressed: { + backgroundColor: colors.onVaultOverlayPressed, + }, +}); diff --git a/examples/bare-react-native-with-js-sdk-and-flow/src/views/LoginView.tsx b/examples/bare-react-native-with-js-sdk-and-flow/src/views/LoginView.tsx new file mode 100644 index 0000000..db3335f --- /dev/null +++ b/examples/bare-react-native-with-js-sdk-and-flow/src/views/LoginView.tsx @@ -0,0 +1,119 @@ +import React from 'react'; +import { + InputAccessoryView, + Keyboard, + Platform, + StyleSheet, + Text, + TextInput, + View, +} from 'react-native'; +import { ErrorText } from '../components/ErrorText'; +import { LinkButton } from '../components/LinkButton'; +import { PrimaryButton } from '../components/PrimaryButton'; +import { Screen } from '../components/Screen'; +import { colors, radii, spacing, typography } from '../consts/theme'; + +type Props = { + email: string; + onChangeEmail: (value: string) => void; + onSubmit: () => void; + isSubmitting: boolean; + error?: string; +}; + +// number-pad/email keyboards don't reliably surface a "Done" key on iOS, so +// this pairs the field with its own accessory toolbar above the keyboard — +// same convention as DepositForm.tsx's amount field, with its own unique +// nativeID so this screen's accessory view doesn't collide with OtpView's. +const EMAIL_INPUT_ACCESSORY_ID = 'login-email-done'; + +/** + * First screen of the app — no Header, since it's the first thing rendered + * once a session is known not to exist and there's nothing to go back to. + * Purely prop-driven: the caller owns the email field's state, the + * send-code mutation, and any navigation to OtpView once a code has gone + * out. + */ +export function LoginView({ + email, + onChangeEmail, + onSubmit, + isSubmitting, + error, +}: Props) { + return ( + + Log in + + Enter your email to get a one-time code. + + + + {Platform.OS === 'ios' ? ( + + + + + + ) : null} + + + + {error ? {error} : null} + + ); +} + +const styles = StyleSheet.create({ + title: { + color: colors.foreground, + marginBottom: spacing.xs, + ...typography.title, + }, + subtitle: { + color: colors.foregroundSecondary, + marginBottom: spacing.lg, + ...typography.body, + }, + input: { + borderWidth: 1, + borderColor: colors.border, + borderRadius: radii.md, + paddingHorizontal: spacing.md, + paddingVertical: spacing.sm, + color: colors.foreground, + marginBottom: spacing.md, + ...typography.body, + }, + accessoryBar: { + flexDirection: 'row', + justifyContent: 'flex-end', + backgroundColor: colors.surface, + borderTopWidth: 1, + borderTopColor: colors.border, + paddingHorizontal: spacing.lg, + paddingVertical: spacing.sm, + }, +}); diff --git a/examples/bare-react-native-with-js-sdk-and-flow/src/views/OtpView.tsx b/examples/bare-react-native-with-js-sdk-and-flow/src/views/OtpView.tsx new file mode 100644 index 0000000..c79e1fc --- /dev/null +++ b/examples/bare-react-native-with-js-sdk-and-flow/src/views/OtpView.tsx @@ -0,0 +1,148 @@ +import React from 'react'; +import { + InputAccessoryView, + Keyboard, + Platform, + StyleSheet, + Text, + TextInput, + View, +} from 'react-native'; +import { ErrorText } from '../components/ErrorText'; +import { Header } from '../components/Header'; +import { LinkButton } from '../components/LinkButton'; +import { PrimaryButton } from '../components/PrimaryButton'; +import { Screen } from '../components/Screen'; +import { colors, radii, spacing, typography } from '../consts/theme'; + +type Props = { + email: string; + code: string; + onChangeCode: (value: string) => void; + onSubmit: () => void; + onResend: () => void; + onBack: () => void; + isSubmitting: boolean; + isResending: boolean; + error?: string; + /** > 0 disables/labels the Resend link as a countdown instead of "Resend code". */ + resendCooldownSeconds?: number; +}; + +// number-pad has no "Done" key on iOS, so this pairs the code field with its +// own accessory toolbar above the keyboard — same convention as +// DepositForm.tsx's amount field, with its own unique nativeID so this +// screen's accessory view doesn't collide with LoginView's. +const CODE_INPUT_ACCESSORY_ID = 'otp-code-done'; + +/** + * Second screen of the login flow — reachable only from LoginView, so it's + * the one screen of these four with a Header/back button (back returns to + * Login, per the caller's onBack). Purely prop-driven: the caller owns the + * code field's state, the verify/resend mutations, and any cooldown timer + * behind resendCooldownSeconds. + */ +export function OtpView({ + email, + code, + onChangeCode, + onSubmit, + onResend, + onBack, + isSubmitting, + isResending, + error, + resendCooldownSeconds, +}: Props) { + const isOnCooldown = !!resendCooldownSeconds && resendCooldownSeconds > 0; + + return ( + +
+ + {`We sent a code to ${email}.`} + + + {Platform.OS === 'ios' ? ( + + + + + + ) : null} + + + + + {isOnCooldown ? ( + + ) : ( + + )} + + + {error ? {error} : null} + + ); +} + +const styles = StyleSheet.create({ + subtitle: { + color: colors.foregroundSecondary, + marginBottom: spacing.lg, + ...typography.body, + }, + input: { + borderWidth: 1, + borderColor: colors.border, + borderRadius: radii.md, + paddingHorizontal: spacing.md, + paddingVertical: spacing.sm, + color: colors.foreground, + marginBottom: spacing.md, + fontSize: 24, + fontWeight: '700', + letterSpacing: 8, + textAlign: 'center', + }, + accessoryBar: { + flexDirection: 'row', + justifyContent: 'flex-end', + backgroundColor: colors.surface, + borderTopWidth: 1, + borderTopColor: colors.border, + paddingHorizontal: spacing.lg, + paddingVertical: spacing.sm, + }, + resendRow: { + alignSelf: 'center', + marginTop: spacing.md, + }, +}); diff --git a/examples/bare-react-native-with-js-sdk-and-flow/src/views/ProvisioningView.tsx b/examples/bare-react-native-with-js-sdk-and-flow/src/views/ProvisioningView.tsx new file mode 100644 index 0000000..690f73f --- /dev/null +++ b/examples/bare-react-native-with-js-sdk-and-flow/src/views/ProvisioningView.tsx @@ -0,0 +1,97 @@ +import React from 'react'; +import { ActivityIndicator, StyleSheet, Text, View } from 'react-native'; +import { ErrorText } from '../components/ErrorText'; +import { AlertCircleIcon } from '../components/icons'; +import { PrimaryButton } from '../components/PrimaryButton'; +import { Screen } from '../components/Screen'; +import { colors, spacing, typography } from '../consts/theme'; + +type Props = { + /** Defaults to "Setting up your vault…" if omitted. */ + message?: string; + error?: string; + /** Only rendered when `error` is set — there's no Cancel/Back on this + * screen (see below), so Retry is the only way forward. */ + onRetry?: () => void; + /** Disables/spins the Retry button while a retry is in flight — without + * this, a double-tap can fire two concurrent vault-creation calls, which + * the original VaultProvisioning.tsx explicitly guarded against via its + * own `loading={isPending}`. */ + isRetrying?: boolean; +}; + +const DEFAULT_MESSAGE = 'Setting up your vault…'; + +/** + * Reached automatically right after OTP success, while the embedded wallet + * ("vault") is being created — no Header, since this screen isn't reachable + * via back navigation and, unlike the other three views, has nothing + * meaningful to go back *to*: the vault is required to use the rest of the + * app at all. If provisioning fails, the only action is Retry — no Cancel, + * for the same reason. Error copy (e.g. "embedded wallets aren't enabled + * for this Dynamic environment") is the caller's responsibility to supply + * via `error`, mirroring the real failure modes in VaultProvisioning.tsx. + */ +export function ProvisioningView({ + message, + error, + onRetry, + isRetrying = false, +}: Props) { + if (error) { + return ( + + + + Couldn't set up your vault + {error} + {onRetry ? ( + + ) : null} + + + ); + } + + return ( + + + + {message ?? DEFAULT_MESSAGE} + + + ); +} + +const styles = StyleSheet.create({ + centered: { + flex: 1, + alignItems: 'center', + justifyContent: 'center', + paddingHorizontal: spacing.md, + }, + message: { + color: colors.foregroundSecondary, + marginTop: spacing.md, + ...typography.body, + }, + errorTitle: { + color: colors.foreground, + marginTop: spacing.md, + textAlign: 'center', + ...typography.headline, + }, + errorText: { + textAlign: 'center', + marginTop: spacing.xs, + }, + retryButton: { + marginTop: spacing.lg, + alignSelf: 'stretch', + }, +}); diff --git a/examples/bare-react-native-with-js-sdk-and-flow/src/views/SplashView.tsx b/examples/bare-react-native-with-js-sdk-and-flow/src/views/SplashView.tsx new file mode 100644 index 0000000..e0c2073 --- /dev/null +++ b/examples/bare-react-native-with-js-sdk-and-flow/src/views/SplashView.tsx @@ -0,0 +1,71 @@ +import React from 'react'; +import { ActivityIndicator, StyleSheet, Text, View } from 'react-native'; +import { Screen } from '../components/Screen'; +import { ErrorText } from '../components/ErrorText'; +import { AlertCircleIcon } from '../components/icons'; +import { colors, spacing, typography } from '../consts/theme'; + +type Props = { + /** e.g. "Checking your session…" — optional, a bare spinner is fine + * without it. Ignored once `error` is set. */ + message?: string; + /** Set when the Dynamic client itself failed to initialize (bad/ + * unreachable environment config, offline cold boot) — a distinct, + * unrecoverable-from-here state, not just "still loading." There's no + * SDK-exposed way to retry initialization itself (it runs once at client + * creation), so this has no Retry button — telling the user plainly what + * happened, rather than offering a button with nothing real to call, is + * the more honest failure mode. */ + error?: string; +}; + +/** + * The very first thing the app can render, before it's even known whether + * there's a session to resume — deliberately minimal: no Header, no back + * button, no cancel action, since there's nothing yet to go back to or + * cancel out of. + */ +export function SplashView({ message, error }: Props) { + return ( + + + {error ? ( + <> + + Couldn't start the app + {error} + + ) : ( + <> + + {message ? {message} : null} + + )} + + + ); +} + +const styles = StyleSheet.create({ + centered: { + flex: 1, + alignItems: 'center', + justifyContent: 'center', + paddingHorizontal: spacing.md, + }, + message: { + color: colors.foregroundSecondary, + marginTop: spacing.md, + ...typography.body, + }, + errorTitle: { + color: colors.foreground, + marginTop: spacing.md, + textAlign: 'center', + ...typography.headline, + }, + errorText: { + textAlign: 'center', + marginTop: spacing.xs, + }, +}); diff --git a/examples/bare-react-native-with-js-sdk-and-flow/src/views/WalletPickerView.tsx b/examples/bare-react-native-with-js-sdk-and-flow/src/views/WalletPickerView.tsx new file mode 100644 index 0000000..4cede75 --- /dev/null +++ b/examples/bare-react-native-with-js-sdk-and-flow/src/views/WalletPickerView.tsx @@ -0,0 +1,83 @@ +/** + * Wallet picker screen: a call-site-supplied subtitle plus a vertical list + * of connectable wallets, each rendered as a ListRow. Purely prop-driven — + * this view has no notion of *why* it's being shown (deposit / fund-gas / + * withdraw-destination all reuse it with a different screenSubtitle and + * wallets list from their own route). + * + * No divider between rows: ListRow's own icon+label+chevron row already + * carries enough visual weight (padding, pressed/disabled states) that a + * hairline between entries would be redundant rather than clarifying. + */ +import React from 'react'; +import { StyleSheet, Text, View } from 'react-native'; +import { Screen } from '../components/Screen'; +import { Header } from '../components/Header'; +import { ListRow } from '../components/ListRow'; +import { ErrorText } from '../components/ErrorText'; +import { colors, spacing, typography } from '../consts/theme'; + +export type WalletOption = { + key: string; + label: string; + iconUri?: string; +}; + +type WalletPickerViewProps = { + /** e.g. "Connect a wallet to fund your vault's gas" — varies per call + * site, passed in fully-formed. */ + screenSubtitle: string; + wallets: WalletOption[]; + onSelect: (key: string) => void; + /** Which wallet's ListRow shows isLoading. */ + connectingKey?: string; + /** True whenever any connect is in flight — disables all rows besides + * connectingKey. */ + isConnecting: boolean; + error?: string; + onBack: () => void; +}; + +export function WalletPickerView({ + screenSubtitle, + wallets, + onSelect, + connectingKey, + isConnecting, + error, + onBack, +}: WalletPickerViewProps) { + return ( + +
+ + {screenSubtitle} + + + {wallets.map(wallet => ( + onSelect(wallet.key)} + /> + ))} + + + {error ? {error} : null} + + ); +} + +const styles = StyleSheet.create({ + subtitle: { + color: colors.foregroundSecondary, + marginTop: spacing.sm, + ...typography.body, + }, + list: { + marginTop: spacing.lg, + }, +}); diff --git a/examples/bare-react-native-with-js-sdk-and-flow/tsconfig.json b/examples/bare-react-native-with-js-sdk-and-flow/tsconfig.json new file mode 100644 index 0000000..b39e658 --- /dev/null +++ b/examples/bare-react-native-with-js-sdk-and-flow/tsconfig.json @@ -0,0 +1,11 @@ +{ + "extends": "@react-native/typescript-config", + "compilerOptions": { + // @react-native/typescript-config hardcodes ["jest"] here — this app + // has no tests, so the jest package (and its ambient types) aren't + // installed at all. + "types": [] + }, + "include": ["**/*.ts", "**/*.tsx"], + "exclude": ["**/node_modules", "**/Pods"] +} diff --git a/examples/rn-moneygram-ramp/pnpm-lock.yaml b/examples/rn-moneygram-ramp/pnpm-lock.yaml index a7cacc5..f5613ea 100644 --- a/examples/rn-moneygram-ramp/pnpm-lock.yaml +++ b/examples/rn-moneygram-ramp/pnpm-lock.yaml @@ -593,16 +593,16 @@ packages: engines: {node: '>=6.9.0'} '@dynamic-labs-sdk/assert-package-version@0.26.9': - resolution: {integrity: sha512-hB9VvQOhE9j2EHAQfv7LCoLH8+DQXzYveHbsEK5dlU3BB4FoZTdJEU2SEH34q+g7Hyz3Nb+ioc5//jrr/tb39w==, tarball: https://fbinfra555artifactory.jfrog.io/artifactory/api/npm/fireblocks-npm/@dynamic-labs-sdk/assert-package-version/-/assert-package-version-0.26.9.tgz} + resolution: {integrity: sha512-hB9VvQOhE9j2EHAQfv7LCoLH8+DQXzYveHbsEK5dlU3BB4FoZTdJEU2SEH34q+g7Hyz3Nb+ioc5//jrr/tb39w==, tarball: https://registry.npmjs.org/@dynamic-labs-sdk/assert-package-version/-/assert-package-version-0.26.9.tgz} '@dynamic-labs-sdk/client@0.26.9': - resolution: {integrity: sha512-ubdqCkyiER9Ruc63E4IomvsOMMzSjGbFNeGnn3hIipzamPslrlAO9YTcU50qJEFioMneA2iJ00kbSBx+1VWHmw==, tarball: https://fbinfra555artifactory.jfrog.io/artifactory/api/npm/fireblocks-npm/@dynamic-labs-sdk/client/-/client-0.26.9.tgz} + resolution: {integrity: sha512-ubdqCkyiER9Ruc63E4IomvsOMMzSjGbFNeGnn3hIipzamPslrlAO9YTcU50qJEFioMneA2iJ00kbSBx+1VWHmw==, tarball: https://registry.npmjs.org/@dynamic-labs-sdk/client/-/client-0.26.9.tgz} '@dynamic-labs-wallet/browser-wallet-client@0.0.325': - resolution: {integrity: sha512-niU6U2OPNg0aPMpQ+yqoTFYayKoRpLSxQg56mKHWM9RmbilGH5jHWXH3mEAVGS7u5YEAuZDnnCavBdWYSBsK5Q==, tarball: https://fbinfra555artifactory.jfrog.io/artifactory/api/npm/fireblocks-npm/@dynamic-labs-wallet/browser-wallet-client/-/browser-wallet-client-0.0.325.tgz} + resolution: {integrity: sha512-niU6U2OPNg0aPMpQ+yqoTFYayKoRpLSxQg56mKHWM9RmbilGH5jHWXH3mEAVGS7u5YEAuZDnnCavBdWYSBsK5Q==, tarball: https://registry.npmjs.org/@dynamic-labs-wallet/browser-wallet-client/-/browser-wallet-client-0.0.325.tgz} '@dynamic-labs-wallet/browser-wallet-client@0.0.337': - resolution: {integrity: sha512-0fZyXUfiZf/mPvvWl+kI4NqUAddWT18dWPRoM08xDUMZ8wGJmyWgD0MeqyJjHV92CV2by2cV+TRcEK3gnaf1sQ==, tarball: https://fbinfra555artifactory.jfrog.io/artifactory/api/npm/fireblocks-npm/@dynamic-labs-wallet/browser-wallet-client/-/browser-wallet-client-0.0.337.tgz} + resolution: {integrity: sha512-0fZyXUfiZf/mPvvWl+kI4NqUAddWT18dWPRoM08xDUMZ8wGJmyWgD0MeqyJjHV92CV2by2cV+TRcEK3gnaf1sQ==, tarball: https://registry.npmjs.org/@dynamic-labs-wallet/browser-wallet-client/-/browser-wallet-client-0.0.337.tgz} '@dynamic-labs-wallet/browser@0.0.167': resolution: {integrity: sha512-HDmUetnJ1iz6kGd5PB1kJzeLI7ZJmwxlJ1QGtUqSQHDdBkhLwaDPlccB2IviC5iPfU5PR/IQ1BYEqpoTWx2sBA==} @@ -611,7 +611,7 @@ packages: resolution: {integrity: sha512-Vwi4CFMjSiLsPF4VUlYV4F87xaQrgnmUVUVx3b5F0I5DbFsGLafiSl2T/dlsOeNuRAhbpDMU4MEB4oOxzR0kYQ==} '@dynamic-labs-wallet/browser@0.0.259': - resolution: {integrity: sha512-wvsfzFDFiXx+LnELExFkbakzyewreZl9VvpaXrwTpzDrDFQHQE081CwyMHLHxZetFzE10L23fyKOrjSAaJuQuw==, tarball: https://fbinfra555artifactory.jfrog.io/artifactory/api/npm/dynamic-npm/@dynamic-labs-wallet/browser/-/@dynamic-labs-wallet/browser-0.0.259.tgz} + resolution: {integrity: sha512-wvsfzFDFiXx+LnELExFkbakzyewreZl9VvpaXrwTpzDrDFQHQE081CwyMHLHxZetFzE10L23fyKOrjSAaJuQuw==, tarball: https://registry.npmjs.org/@dynamic-labs-wallet/browser/-/@dynamic-labs-wallet/browser-0.0.259.tgz} '@dynamic-labs-wallet/core@0.0.167': resolution: {integrity: sha512-jEHD/mDfnqx2/ML/MezY725uPPrKGsGoR3BaS1JNITGIitai1gPEgaEMqbXIhzId/m+Xieb8ZrLDiaYYJcXcyQ==} @@ -620,80 +620,80 @@ packages: resolution: {integrity: sha512-1ykOANTDCPPaIpajpKqRxfISGYrmiMs7WMZQzdzRkTLftpnatgycYjdZrX9adhE1kY9BMrPdhfYaaE5B9wbFbQ==} '@dynamic-labs-wallet/core@0.0.259': - resolution: {integrity: sha512-q9QhQ30CU1IwJgSQ4jvoX3ltWBnvoomsPIjn8K3+vhW/Js6zIeTB0mQ0M0m/NQSbms3E16XstzSnAkiXcSTvow==, tarball: https://fbinfra555artifactory.jfrog.io/artifactory/api/npm/dynamic-npm/@dynamic-labs-wallet/core/-/@dynamic-labs-wallet/core-0.0.259.tgz} + resolution: {integrity: sha512-q9QhQ30CU1IwJgSQ4jvoX3ltWBnvoomsPIjn8K3+vhW/Js6zIeTB0mQ0M0m/NQSbms3E16XstzSnAkiXcSTvow==, tarball: https://registry.npmjs.org/@dynamic-labs-wallet/core/-/@dynamic-labs-wallet/core-0.0.259.tgz} '@dynamic-labs-wallet/core@0.0.325': - resolution: {integrity: sha512-kWlCPMjHVBwiKyWUYrQrsgfTL2Mszsk1acjxJqfsWJucfgOxp432uO5XHGivosu3T1hfGNBNyKK6bChy3gL9Nw==, tarball: https://fbinfra555artifactory.jfrog.io/artifactory/api/npm/dynamic-npm/@dynamic-labs-wallet/core/-/@dynamic-labs-wallet/core-0.0.325.tgz} + resolution: {integrity: sha512-kWlCPMjHVBwiKyWUYrQrsgfTL2Mszsk1acjxJqfsWJucfgOxp432uO5XHGivosu3T1hfGNBNyKK6bChy3gL9Nw==, tarball: https://registry.npmjs.org/@dynamic-labs-wallet/core/-/@dynamic-labs-wallet/core-0.0.325.tgz} peerDependencies: '@dynamic-labs-wallet/forward-mpc-client': 0.5.5 '@dynamic-labs-wallet/core@0.0.337': - resolution: {integrity: sha512-csS/Xqx9kERTYLzt7BXHkaIBX8WIfUIDC3R0Yv6fweWdRL+6KX0A6lRUN1lajAF9/7d6XhxVzS/C3umS0qd7JQ==, tarball: https://fbinfra555artifactory.jfrog.io/artifactory/api/npm/dynamic-npm/@dynamic-labs-wallet/core/-/@dynamic-labs-wallet/core-0.0.337.tgz} + resolution: {integrity: sha512-csS/Xqx9kERTYLzt7BXHkaIBX8WIfUIDC3R0Yv6fweWdRL+6KX0A6lRUN1lajAF9/7d6XhxVzS/C3umS0qd7JQ==, tarball: https://registry.npmjs.org/@dynamic-labs-wallet/core/-/@dynamic-labs-wallet/core-0.0.337.tgz} peerDependencies: '@dynamic-labs-wallet/forward-mpc-client': 0.9.0 '@dynamic-labs-wallet/forward-mpc-client@0.1.3': - resolution: {integrity: sha512-riZesfU41fMvetaxJ3bO48/9P8ikRPgoVJgWh8m8i0oRyYN7uUz+Iesp+52U12DCtcvSTXljxrKtrV3yqNAYRw==, tarball: https://fbinfra555artifactory.jfrog.io/artifactory/api/npm/fireblocks-npm/@dynamic-labs-wallet/forward-mpc-client/-/forward-mpc-client-0.1.3.tgz} + resolution: {integrity: sha512-riZesfU41fMvetaxJ3bO48/9P8ikRPgoVJgWh8m8i0oRyYN7uUz+Iesp+52U12DCtcvSTXljxrKtrV3yqNAYRw==, tarball: https://registry.npmjs.org/@dynamic-labs-wallet/forward-mpc-client/-/forward-mpc-client-0.1.3.tgz} '@dynamic-labs-wallet/forward-mpc-client@0.2.0': - resolution: {integrity: sha512-zkn5eYPPkjOFRi8POHXM+rl2lW+0AKjqiKPdNYmJieegI8PuXqq9Q0UzVWISwzpqmMX4/nQmK+9cqbPDW9Lu6A==, tarball: https://fbinfra555artifactory.jfrog.io/artifactory/api/npm/fireblocks-npm/@dynamic-labs-wallet/forward-mpc-client/-/forward-mpc-client-0.2.0.tgz} + resolution: {integrity: sha512-zkn5eYPPkjOFRi8POHXM+rl2lW+0AKjqiKPdNYmJieegI8PuXqq9Q0UzVWISwzpqmMX4/nQmK+9cqbPDW9Lu6A==, tarball: https://registry.npmjs.org/@dynamic-labs-wallet/forward-mpc-client/-/forward-mpc-client-0.2.0.tgz} '@dynamic-labs-wallet/forward-mpc-client@0.5.5': - resolution: {integrity: sha512-O2qu7C6dLyImsEsuKtypXw6sTQ6Z5JoDle0sSDjEtcrUmlyJZBq0Bbf4gveNFkvB9Ra6dKG5V4RpK2V6vi0oKw==, tarball: https://fbinfra555artifactory.jfrog.io/artifactory/api/npm/fireblocks-npm/@dynamic-labs-wallet/forward-mpc-client/-/forward-mpc-client-0.5.5.tgz} + resolution: {integrity: sha512-O2qu7C6dLyImsEsuKtypXw6sTQ6Z5JoDle0sSDjEtcrUmlyJZBq0Bbf4gveNFkvB9Ra6dKG5V4RpK2V6vi0oKw==, tarball: https://registry.npmjs.org/@dynamic-labs-wallet/forward-mpc-client/-/forward-mpc-client-0.5.5.tgz} '@dynamic-labs-wallet/forward-mpc-client@0.9.0': - resolution: {integrity: sha512-gotV/RnPTJmjosddbZU6L9Rgs6WEJRwNX/VO7v+0JKyyuzIZPvjA2wJLto9EVEiNMCKMES2a+VY39rEqcGNHCg==, tarball: https://fbinfra555artifactory.jfrog.io/artifactory/api/npm/fireblocks-npm/@dynamic-labs-wallet/forward-mpc-client/-/forward-mpc-client-0.9.0.tgz} + resolution: {integrity: sha512-gotV/RnPTJmjosddbZU6L9Rgs6WEJRwNX/VO7v+0JKyyuzIZPvjA2wJLto9EVEiNMCKMES2a+VY39rEqcGNHCg==, tarball: https://registry.npmjs.org/@dynamic-labs-wallet/forward-mpc-client/-/forward-mpc-client-0.9.0.tgz} peerDependencies: '@dynamic-labs-wallet/primitives': '>=0.0.336 || 0.0.1' '@dynamic-labs-wallet/forward-mpc-shared@0.1.0': - resolution: {integrity: sha512-xRpMri4+ZuClonwf04RcnT/BCG8oA36ononD7s0MA5wSqd8kOuHjzNTSoM6lWnPiCmlpECyPARJ1CEO02Sfq9Q==, tarball: https://fbinfra555artifactory.jfrog.io/artifactory/api/npm/fireblocks-npm/@dynamic-labs-wallet/forward-mpc-shared/-/forward-mpc-shared-0.1.0.tgz} + resolution: {integrity: sha512-xRpMri4+ZuClonwf04RcnT/BCG8oA36ononD7s0MA5wSqd8kOuHjzNTSoM6lWnPiCmlpECyPARJ1CEO02Sfq9Q==, tarball: https://registry.npmjs.org/@dynamic-labs-wallet/forward-mpc-shared/-/forward-mpc-shared-0.1.0.tgz} '@dynamic-labs-wallet/forward-mpc-shared@0.2.0': - resolution: {integrity: sha512-2I8NoCBVT9/09o4+M78S2wyY9jVXAb6RKt5Bnh1fhvikuB11NBeswtfZLns3wAFQxayApe31Jhamd4D2GR+mtw==, tarball: https://fbinfra555artifactory.jfrog.io/artifactory/api/npm/fireblocks-npm/@dynamic-labs-wallet/forward-mpc-shared/-/forward-mpc-shared-0.2.0.tgz} + resolution: {integrity: sha512-2I8NoCBVT9/09o4+M78S2wyY9jVXAb6RKt5Bnh1fhvikuB11NBeswtfZLns3wAFQxayApe31Jhamd4D2GR+mtw==, tarball: https://registry.npmjs.org/@dynamic-labs-wallet/forward-mpc-shared/-/forward-mpc-shared-0.2.0.tgz} '@dynamic-labs-wallet/forward-mpc-shared@0.5.1': - resolution: {integrity: sha512-ekfuJV7Q861ElqeeOCKO1kNGE+32+xM9azka7BxOLr3XeBPQz3H/wjcEX8YWqOUqeAcYMRc4QbBKR7ouTgsFSQ==, tarball: https://fbinfra555artifactory.jfrog.io/artifactory/api/npm/fireblocks-npm/@dynamic-labs-wallet/forward-mpc-shared/-/forward-mpc-shared-0.5.1.tgz} + resolution: {integrity: sha512-ekfuJV7Q861ElqeeOCKO1kNGE+32+xM9azka7BxOLr3XeBPQz3H/wjcEX8YWqOUqeAcYMRc4QbBKR7ouTgsFSQ==, tarball: https://registry.npmjs.org/@dynamic-labs-wallet/forward-mpc-shared/-/forward-mpc-shared-0.5.1.tgz} '@dynamic-labs-wallet/forward-mpc-shared@0.7.0': - resolution: {integrity: sha512-mN6zT5J8JbZxkOJxEjgGrjURybVn/t9DD+pWW5U4DRZH6Qakn5n1LIB4Lg4Y7OW9WwrlMH2IJ9RNgBW35RaF1A==, tarball: https://fbinfra555artifactory.jfrog.io/artifactory/api/npm/fireblocks-npm/@dynamic-labs-wallet/forward-mpc-shared/-/forward-mpc-shared-0.7.0.tgz} + resolution: {integrity: sha512-mN6zT5J8JbZxkOJxEjgGrjURybVn/t9DD+pWW5U4DRZH6Qakn5n1LIB4Lg4Y7OW9WwrlMH2IJ9RNgBW35RaF1A==, tarball: https://registry.npmjs.org/@dynamic-labs-wallet/forward-mpc-shared/-/forward-mpc-shared-0.7.0.tgz} peerDependencies: '@dynamic-labs-wallet/primitives': '>=0.0.336 || 0.0.1' '@dynamic-labs-wallet/primitives@0.0.337': - resolution: {integrity: sha512-HZHohGUedboP4Bwe6cS0Plftq6GATGnt4PnqVC3IY2mD+W8w7IAK+NVSSbe9kllXJyfaYeK+hJxpE/SC/gc6bw==, tarball: https://fbinfra555artifactory.jfrog.io/artifactory/api/npm/dynamic-npm/@dynamic-labs-wallet/primitives/-/@dynamic-labs-wallet/primitives-0.0.337.tgz} + resolution: {integrity: sha512-HZHohGUedboP4Bwe6cS0Plftq6GATGnt4PnqVC3IY2mD+W8w7IAK+NVSSbe9kllXJyfaYeK+hJxpE/SC/gc6bw==, tarball: https://registry.npmjs.org/@dynamic-labs-wallet/primitives/-/@dynamic-labs-wallet/primitives-0.0.337.tgz} '@dynamic-labs/assert-package-version@4.83.1': - resolution: {integrity: sha512-wSpNfNxoaUVGGYQWGnvyiEuwoNr5YA9dTQZizvnEyCvI/HfipVsQRJjp63ysbPFmqLUFHvwYEDjcHE/+5/V62w==, tarball: https://fbinfra555artifactory.jfrog.io/artifactory/api/npm/fireblocks-npm/@dynamic-labs/assert-package-version/-/assert-package-version-4.83.1.tgz} + resolution: {integrity: sha512-wSpNfNxoaUVGGYQWGnvyiEuwoNr5YA9dTQZizvnEyCvI/HfipVsQRJjp63ysbPFmqLUFHvwYEDjcHE/+5/V62w==, tarball: https://registry.npmjs.org/@dynamic-labs/assert-package-version/-/assert-package-version-4.83.1.tgz} '@dynamic-labs/client@4.83.1': - resolution: {integrity: sha512-Y3UE9pprtTK54+gsj3FOCSDemWwj3UeGdBnwBShdnBO1Rgig0h5vxQfkPlYXUZNTT7YS62dTjyjjANfc1PP1Rg==, tarball: https://fbinfra555artifactory.jfrog.io/artifactory/api/npm/fireblocks-npm/@dynamic-labs/client/-/client-4.83.1.tgz} + resolution: {integrity: sha512-Y3UE9pprtTK54+gsj3FOCSDemWwj3UeGdBnwBShdnBO1Rgig0h5vxQfkPlYXUZNTT7YS62dTjyjjANfc1PP1Rg==, tarball: https://registry.npmjs.org/@dynamic-labs/client/-/client-4.83.1.tgz} '@dynamic-labs/iconic@4.83.1': - resolution: {integrity: sha512-tYU1XYsI426LRnRp1ID1MybyXTitBXNTOZ+SKOWrNzqSnC503li6d4dm7pjuWAT0OZlpMlGw2bL0ZpV66Uojqw==, tarball: https://fbinfra555artifactory.jfrog.io/artifactory/api/npm/fireblocks-npm/@dynamic-labs/iconic/-/iconic-4.83.1.tgz} + resolution: {integrity: sha512-tYU1XYsI426LRnRp1ID1MybyXTitBXNTOZ+SKOWrNzqSnC503li6d4dm7pjuWAT0OZlpMlGw2bL0ZpV66Uojqw==, tarball: https://registry.npmjs.org/@dynamic-labs/iconic/-/iconic-4.83.1.tgz} peerDependencies: react: '>=18.0.0 <20.0.0' react-dom: '>=18.0.0 <20.0.0' '@dynamic-labs/locale@4.83.1': - resolution: {integrity: sha512-QlVqKyc9tVhisocfuPAlwKxfEebEfitE1F1j1TUGCsVrs4BukT7ZMhXvwE73z6umQAHILABXepwS0xjURRhLeg==, tarball: https://fbinfra555artifactory.jfrog.io/artifactory/api/npm/fireblocks-npm/@dynamic-labs/locale/-/locale-4.83.1.tgz} + resolution: {integrity: sha512-QlVqKyc9tVhisocfuPAlwKxfEebEfitE1F1j1TUGCsVrs4BukT7ZMhXvwE73z6umQAHILABXepwS0xjURRhLeg==, tarball: https://registry.npmjs.org/@dynamic-labs/locale/-/locale-4.83.1.tgz} '@dynamic-labs/logger@4.83.1': - resolution: {integrity: sha512-rT8Wsx2EJbnPosbTVIgUWHxHfQ5x8mOnBmcGmVwB3jhPa809sJDJ/+QrvTj0Fsoz80XvmseoHoTKSgIv6XpWVg==, tarball: https://fbinfra555artifactory.jfrog.io/artifactory/api/npm/dynamic-npm/@dynamic-labs/logger/-/@dynamic-labs/logger-4.83.1.tgz} + resolution: {integrity: sha512-rT8Wsx2EJbnPosbTVIgUWHxHfQ5x8mOnBmcGmVwB3jhPa809sJDJ/+QrvTj0Fsoz80XvmseoHoTKSgIv6XpWVg==, tarball: https://registry.npmjs.org/@dynamic-labs/logger/-/@dynamic-labs/logger-4.83.1.tgz} '@dynamic-labs/logger@4.84.1': - resolution: {integrity: sha512-0/QnGlA4UUOlqKl0fIrefQ+kXvFVAUgHkExnESIbdlJYH3BTEX61LTb/Sx7lYRho55QkR6XVjEjeZzHY8ngGoA==, tarball: https://fbinfra555artifactory.jfrog.io/artifactory/api/npm/dynamic-npm/@dynamic-labs/logger/-/@dynamic-labs/logger-4.84.1.tgz} + resolution: {integrity: sha512-0/QnGlA4UUOlqKl0fIrefQ+kXvFVAUgHkExnESIbdlJYH3BTEX61LTb/Sx7lYRho55QkR6XVjEjeZzHY8ngGoA==, tarball: https://registry.npmjs.org/@dynamic-labs/logger/-/@dynamic-labs/logger-4.84.1.tgz} '@dynamic-labs/message-transport@4.83.1': - resolution: {integrity: sha512-NlJSIZmOjf0ZP9U3wmyUKs20rBsigyNwcDacd+WBqaQlMtuiGLkz6exK6MSxAC4ej/CgWZpnGaKBnBDu9RIRkA==, tarball: https://fbinfra555artifactory.jfrog.io/artifactory/api/npm/fireblocks-npm/@dynamic-labs/message-transport/-/message-transport-4.83.1.tgz} + resolution: {integrity: sha512-NlJSIZmOjf0ZP9U3wmyUKs20rBsigyNwcDacd+WBqaQlMtuiGLkz6exK6MSxAC4ej/CgWZpnGaKBnBDu9RIRkA==, tarball: https://registry.npmjs.org/@dynamic-labs/message-transport/-/message-transport-4.83.1.tgz} '@dynamic-labs/react-hooks@4.83.1': - resolution: {integrity: sha512-WHrM4JLty5Tr4FclFCvK1ISfks3Jwxny1nyv2+VXNLUxk7ihYWnFHB3VWAW2o9Zlm8RkLUYcNbbTPt2DSsMWdg==, tarball: https://fbinfra555artifactory.jfrog.io/artifactory/api/npm/fireblocks-npm/@dynamic-labs/react-hooks/-/react-hooks-4.83.1.tgz} + resolution: {integrity: sha512-WHrM4JLty5Tr4FclFCvK1ISfks3Jwxny1nyv2+VXNLUxk7ihYWnFHB3VWAW2o9Zlm8RkLUYcNbbTPt2DSsMWdg==, tarball: https://registry.npmjs.org/@dynamic-labs/react-hooks/-/react-hooks-4.83.1.tgz} peerDependencies: react: '>=18.0.0 <20.0.0' '@dynamic-labs/react-native-extension@4.83.1': - resolution: {integrity: sha512-LlTBuVNIqkfI7hD80xvZQG0NzkWzaJKIkN0l9YZ2yWd0E1aJVH3YkPbOu+GfWw/8p2CG1mnFm3G1qlmhMZWCpg==, tarball: https://fbinfra555artifactory.jfrog.io/artifactory/api/npm/fireblocks-npm/@dynamic-labs/react-native-extension/-/react-native-extension-4.83.1.tgz} + resolution: {integrity: sha512-LlTBuVNIqkfI7hD80xvZQG0NzkWzaJKIkN0l9YZ2yWd0E1aJVH3YkPbOu+GfWw/8p2CG1mnFm3G1qlmhMZWCpg==, tarball: https://registry.npmjs.org/@dynamic-labs/react-native-extension/-/react-native-extension-4.83.1.tgz} peerDependencies: expo-linking: '>=6.2.2' expo-modules-core: '>=2.0.0' @@ -704,7 +704,7 @@ packages: react-native-webview: ^13.6.4 '@dynamic-labs/rpc-providers@4.83.1': - resolution: {integrity: sha512-KghsNAHBwoRoKN/FPuUfT1yQ+Kf7KhxuHcsH+XINfA90/zMLQrOKIsKeUyBboWWwCJrqCcGsG+lqUmxbCrBasw==, tarball: https://fbinfra555artifactory.jfrog.io/artifactory/api/npm/fireblocks-npm/@dynamic-labs/rpc-providers/-/rpc-providers-4.83.1.tgz} + resolution: {integrity: sha512-KghsNAHBwoRoKN/FPuUfT1yQ+Kf7KhxuHcsH+XINfA90/zMLQrOKIsKeUyBboWWwCJrqCcGsG+lqUmxbCrBasw==, tarball: https://registry.npmjs.org/@dynamic-labs/rpc-providers/-/rpc-providers-4.83.1.tgz} '@dynamic-labs/sdk-api-core@0.0.764': resolution: {integrity: sha512-79JptJTTClLc9qhioThtwMuzTHJ+mrj8sTEglb7Mcx3lJub9YbXqNdzS9mLRxZsr2et3aqqpzymXdUBzSEaMng==} @@ -716,42 +716,42 @@ packages: resolution: {integrity: sha512-XChDKxbbJtZgFsJ1g9N35ALE2O/CCmT+tB50LpbnbXWkt1gRjYoPNB+UVzNQeDXD4skwJUy6i849WmTUPRNReg==} '@dynamic-labs/sdk-api-core@0.0.900': - resolution: {integrity: sha512-4kb6IY75fFbTLwW24hN8ziVuxEeGAtsQpvXlKXA/XYrPKFFtJU6VQnuiKrKAerekIltdfMXEIqBJpcdPsmbszg==, tarball: https://fbinfra555artifactory.jfrog.io/artifactory/api/npm/dynamic-npm/@dynamic-labs/sdk-api-core/-/@dynamic-labs/sdk-api-core-0.0.900.tgz} + resolution: {integrity: sha512-4kb6IY75fFbTLwW24hN8ziVuxEeGAtsQpvXlKXA/XYrPKFFtJU6VQnuiKrKAerekIltdfMXEIqBJpcdPsmbszg==, tarball: https://registry.npmjs.org/@dynamic-labs/sdk-api-core/-/@dynamic-labs/sdk-api-core-0.0.900.tgz} '@dynamic-labs/sdk-api-core@0.0.958': - resolution: {integrity: sha512-jbDSjxWi69Nb5ZRmMrt+tV1gqGoPflvZnw7Qlpmbxbfguqx8KBzvDdDphMJ5jW2YCEmD8dRw2qizOrnN1gjIxw==, tarball: https://fbinfra555artifactory.jfrog.io/artifactory/api/npm/dynamic-npm/@dynamic-labs/sdk-api-core/-/@dynamic-labs/sdk-api-core-0.0.958.tgz} + resolution: {integrity: sha512-jbDSjxWi69Nb5ZRmMrt+tV1gqGoPflvZnw7Qlpmbxbfguqx8KBzvDdDphMJ5jW2YCEmD8dRw2qizOrnN1gjIxw==, tarball: https://registry.npmjs.org/@dynamic-labs/sdk-api-core/-/@dynamic-labs/sdk-api-core-0.0.958.tgz} '@dynamic-labs/sdk-api-core@0.0.964': - resolution: {integrity: sha512-U7PdyUQXdvToWCoysBIURYDMy+3XTnGZsdruv1Bl1LKwXHNbR8jGwIt6ibf0vbp1lQga6fc4DPnlAjbtUHaPIA==, tarball: https://fbinfra555artifactory.jfrog.io/artifactory/api/npm/dynamic-npm/@dynamic-labs/sdk-api-core/-/@dynamic-labs/sdk-api-core-0.0.964.tgz} + resolution: {integrity: sha512-U7PdyUQXdvToWCoysBIURYDMy+3XTnGZsdruv1Bl1LKwXHNbR8jGwIt6ibf0vbp1lQga6fc4DPnlAjbtUHaPIA==, tarball: https://registry.npmjs.org/@dynamic-labs/sdk-api-core/-/@dynamic-labs/sdk-api-core-0.0.964.tgz} '@dynamic-labs/solana-core@4.83.1': - resolution: {integrity: sha512-j2Upn13oq8z/biAQWAeLocrKqaVeA1yVFWnxSzB0DKPsyKs944LgdFXo2IOVwycegvhejMfGezMVloaO5AgVkg==, tarball: https://fbinfra555artifactory.jfrog.io/artifactory/api/npm/fireblocks-npm/@dynamic-labs/solana-core/-/solana-core-4.83.1.tgz} + resolution: {integrity: sha512-j2Upn13oq8z/biAQWAeLocrKqaVeA1yVFWnxSzB0DKPsyKs944LgdFXo2IOVwycegvhejMfGezMVloaO5AgVkg==, tarball: https://registry.npmjs.org/@dynamic-labs/solana-core/-/solana-core-4.83.1.tgz} '@dynamic-labs/solana-extension@4.83.1': - resolution: {integrity: sha512-j97Cx260psg2BjK+33EJzmVS4SKxFntPoDDkp8n+LKJGrAYSgBQiLtCMTAfHoP+TJDnW99BQGlfUBN7DGpyLTQ==, tarball: https://fbinfra555artifactory.jfrog.io/artifactory/api/npm/fireblocks-npm/@dynamic-labs/solana-extension/-/solana-extension-4.83.1.tgz} + resolution: {integrity: sha512-j97Cx260psg2BjK+33EJzmVS4SKxFntPoDDkp8n+LKJGrAYSgBQiLtCMTAfHoP+TJDnW99BQGlfUBN7DGpyLTQ==, tarball: https://registry.npmjs.org/@dynamic-labs/solana-extension/-/solana-extension-4.83.1.tgz} peerDependencies: '@solana/web3.js': 1.98.1 '@dynamic-labs/types@4.83.1': - resolution: {integrity: sha512-lwNz57iJLk/bySkGVxeYIbWZvmb18s9yD2QbXQguyChu6V4/PdoRH4DGBr9xxOMY06zzSVSN3g2ctrsepv4atg==, tarball: https://fbinfra555artifactory.jfrog.io/artifactory/api/npm/fireblocks-npm/@dynamic-labs/types/-/types-4.83.1.tgz} + resolution: {integrity: sha512-lwNz57iJLk/bySkGVxeYIbWZvmb18s9yD2QbXQguyChu6V4/PdoRH4DGBr9xxOMY06zzSVSN3g2ctrsepv4atg==, tarball: https://registry.npmjs.org/@dynamic-labs/types/-/types-4.83.1.tgz} '@dynamic-labs/utils@4.83.1': - resolution: {integrity: sha512-6PgT0Xr8IQUn4xx3fBn2XEcyA9NAnR/BSVEsOb/+KgFRhx7bmKkwC3Bh1ooCXpr9P/osutT9Yy+Eb/3rg182CA==, tarball: https://fbinfra555artifactory.jfrog.io/artifactory/api/npm/fireblocks-npm/@dynamic-labs/utils/-/utils-4.83.1.tgz} + resolution: {integrity: sha512-6PgT0Xr8IQUn4xx3fBn2XEcyA9NAnR/BSVEsOb/+KgFRhx7bmKkwC3Bh1ooCXpr9P/osutT9Yy+Eb/3rg182CA==, tarball: https://registry.npmjs.org/@dynamic-labs/utils/-/utils-4.83.1.tgz} '@dynamic-labs/wallet-book@4.83.1': - resolution: {integrity: sha512-FNCQsS8U1l2SgvbZAESJcBcVcVJ7EeQrazNiEIKze4gcAwlJXDMoa/ThbN/dUOGaY1smM0A8TOKiBER96+t7OA==, tarball: https://fbinfra555artifactory.jfrog.io/artifactory/api/npm/fireblocks-npm/@dynamic-labs/wallet-book/-/wallet-book-4.83.1.tgz} + resolution: {integrity: sha512-FNCQsS8U1l2SgvbZAESJcBcVcVJ7EeQrazNiEIKze4gcAwlJXDMoa/ThbN/dUOGaY1smM0A8TOKiBER96+t7OA==, tarball: https://registry.npmjs.org/@dynamic-labs/wallet-book/-/wallet-book-4.83.1.tgz} peerDependencies: react: '>=18.0.0 <20.0.0' react-dom: '>=18.0.0 <20.0.0' '@dynamic-labs/wallet-connector-core@4.83.1': - resolution: {integrity: sha512-lYAuLgMB8aKqT+M+vftUslIy5YlArs4LxcwCHZgQNoly1UB9CEjGSJFQBQmZQIrmz7TB+8H8V11uHhGu/Ow3IQ==, tarball: https://fbinfra555artifactory.jfrog.io/artifactory/api/npm/fireblocks-npm/@dynamic-labs/wallet-connector-core/-/wallet-connector-core-4.83.1.tgz} + resolution: {integrity: sha512-lYAuLgMB8aKqT+M+vftUslIy5YlArs4LxcwCHZgQNoly1UB9CEjGSJFQBQmZQIrmz7TB+8H8V11uHhGu/Ow3IQ==, tarball: https://registry.npmjs.org/@dynamic-labs/wallet-connector-core/-/wallet-connector-core-4.83.1.tgz} '@dynamic-labs/webauthn@4.83.1': - resolution: {integrity: sha512-8d4OQK4D/7Hdn4x2cAWC5uiXW1j1ZFmDsm5Hg3QkXhuBOGO7zqleT2VhPfm0RXcdG7p6Po0RtuFFWmv6jTvWgw==, tarball: https://fbinfra555artifactory.jfrog.io/artifactory/api/npm/fireblocks-npm/@dynamic-labs/webauthn/-/webauthn-4.83.1.tgz} + resolution: {integrity: sha512-8d4OQK4D/7Hdn4x2cAWC5uiXW1j1ZFmDsm5Hg3QkXhuBOGO7zqleT2VhPfm0RXcdG7p6Po0RtuFFWmv6jTvWgw==, tarball: https://registry.npmjs.org/@dynamic-labs/webauthn/-/webauthn-4.83.1.tgz} '@dynamic-labs/webview-messages@4.83.1': - resolution: {integrity: sha512-V/sRqfG6FcnbynQQxqF+Pkrdi/2vUjgHyWCS7K1GmUhIcxJcqFLt5OqgaGlr5nxGEsjZVYPBSm34e4omq6g9cQ==, tarball: https://fbinfra555artifactory.jfrog.io/artifactory/api/npm/fireblocks-npm/@dynamic-labs/webview-messages/-/webview-messages-4.83.1.tgz} + resolution: {integrity: sha512-V/sRqfG6FcnbynQQxqF+Pkrdi/2vUjgHyWCS7K1GmUhIcxJcqFLt5OqgaGlr5nxGEsjZVYPBSm34e4omq6g9cQ==, tarball: https://registry.npmjs.org/@dynamic-labs/webview-messages/-/webview-messages-4.83.1.tgz} '@emnapi/runtime@1.10.0': resolution: {integrity: sha512-ewvYlk86xUoGI0zQRNq/mC+16R1QeDlKQy21Ki3oSYXNgLb45GV1P6A0M+/s6nyCuNDqe5VpaY84BzXGwVbwFA==} @@ -760,7 +760,7 @@ packages: resolution: {integrity: sha512-pJsbax/pEPdRXSnFKahzGZeq2CNTZ0skAPWpnEZK/8vdcvlan7LE7wMSOVr+Z+MqTBnVEnS7O80TKpXKU5Rsbw==} '@expo/cli@54.0.24': - resolution: {integrity: sha512-5xse1bEgnVUBhOrtttc6xTNJVvjyTRavpzuF0/0nuj+312vfSbk7EiRbG+xJ2pW/iZxnhLPJkFCrPYG0nmheAQ==, tarball: https://fbinfra555artifactory.jfrog.io/artifactory/api/npm/fireblocks-npm/@expo/cli/-/cli-54.0.24.tgz} + resolution: {integrity: sha512-5xse1bEgnVUBhOrtttc6xTNJVvjyTRavpzuF0/0nuj+312vfSbk7EiRbG+xJ2pW/iZxnhLPJkFCrPYG0nmheAQ==, tarball: https://registry.npmjs.org/@expo/cli/-/cli-54.0.24.tgz} hasBin: true peerDependencies: expo: '*' @@ -788,7 +788,7 @@ packages: resolution: {integrity: sha512-qC4eaxmKMTmJC2ahwyui6ud8f3W60Ss7pMkpBq40Hu3zyiAaugPXnZ24145U7K36qO9UHdZUVxsCvIpz2RYYCA==} '@expo/devtools@0.1.8': - resolution: {integrity: sha512-SVLxbuanDjJPgc0sy3EfXUMLb/tXzp6XIHkhtPVmTWJAp+FOr6+5SeiCfJrCzZFet0Ifyke2vX3sFcKwEvCXwQ==, tarball: https://fbinfra555artifactory.jfrog.io/artifactory/api/npm/fireblocks-npm/@expo/devtools/-/devtools-0.1.8.tgz} + resolution: {integrity: sha512-SVLxbuanDjJPgc0sy3EfXUMLb/tXzp6XIHkhtPVmTWJAp+FOr6+5SeiCfJrCzZFet0Ifyke2vX3sFcKwEvCXwQ==, tarball: https://registry.npmjs.org/@expo/devtools/-/devtools-0.1.8.tgz} peerDependencies: react: '*' react-native: '*' @@ -802,7 +802,7 @@ packages: resolution: {integrity: sha512-xV+ps6YCW7XIPVUwFVCRN2nox09dnRwy8uIjwHWTODu0zFw4kp4omnVkl0OOjuu2XOe7tdgAHxikrkJt9xB/7Q==} '@expo/fingerprint@0.15.5': - resolution: {integrity: sha512-mdVoAMcux1WlM6kd1RoWiHRNqKqS+J6mKmWQ/BKgeh937S/fcW58EE68O6nc4KDXtWi3PBeNHskOFcgyIuD4hw==, tarball: https://fbinfra555artifactory.jfrog.io/artifactory/api/npm/fireblocks-npm/@expo/fingerprint/-/fingerprint-0.15.5.tgz} + resolution: {integrity: sha512-mdVoAMcux1WlM6kd1RoWiHRNqKqS+J6mKmWQ/BKgeh937S/fcW58EE68O6nc4KDXtWi3PBeNHskOFcgyIuD4hw==, tarball: https://registry.npmjs.org/@expo/fingerprint/-/fingerprint-0.15.5.tgz} hasBin: true '@expo/image-utils@0.8.14': @@ -815,7 +815,7 @@ packages: resolution: {integrity: sha512-rmkjHrYLdfhGGW1TINHwJ/TIcKgtd+1iV+uTycEB74RWSax6U2klRiXXGgudKH6j2OrDSCm3edYTPukSVZtsIQ==} '@expo/metro-config@54.0.15': - resolution: {integrity: sha512-SqIya4VZ9KHM1S9g+xR0A+QKw1Tfs7Gacx6bQNJ98vs4+O7I5+QP5mHZIB0QSZLUV8opiXebHYTiTu+0OAsIUw==, tarball: https://fbinfra555artifactory.jfrog.io/artifactory/api/npm/fireblocks-npm/@expo/metro-config/-/metro-config-54.0.15.tgz} + resolution: {integrity: sha512-SqIya4VZ9KHM1S9g+xR0A+QKw1Tfs7Gacx6bQNJ98vs4+O7I5+QP5mHZIB0QSZLUV8opiXebHYTiTu+0OAsIUw==, tarball: https://registry.npmjs.org/@expo/metro-config/-/metro-config-54.0.15.tgz} peerDependencies: expo: '*' peerDependenciesMeta: @@ -823,7 +823,7 @@ packages: optional: true '@expo/metro-runtime@6.1.2': - resolution: {integrity: sha512-nvM+Qv45QH7pmYvP8JB1G8JpScrWND3KrMA6ZKe62cwwNiX/BjHU28Ear0v/4bQWXlOY0mv6B8CDIm8JxXde9g==, tarball: https://fbinfra555artifactory.jfrog.io/artifactory/api/npm/fireblocks-npm/@expo/metro-runtime/-/metro-runtime-6.1.2.tgz} + resolution: {integrity: sha512-nvM+Qv45QH7pmYvP8JB1G8JpScrWND3KrMA6ZKe62cwwNiX/BjHU28Ear0v/4bQWXlOY0mv6B8CDIm8JxXde9g==, tarball: https://registry.npmjs.org/@expo/metro-runtime/-/metro-runtime-6.1.2.tgz} peerDependencies: expo: '*' react: '*' @@ -887,118 +887,118 @@ packages: hasBin: true '@img/sharp-darwin-arm64@0.33.5': - resolution: {integrity: sha512-UT4p+iz/2H4twwAoLCqfA9UH5pI6DggwKEGuaPy7nCVQ8ZsiY5PIcrRvD1DzuY3qYL07NtIQcWnBSY/heikIFQ==, tarball: https://fbinfra555artifactory.jfrog.io/artifactory/api/npm/fireblocks-npm/@img/sharp-darwin-arm64/-/sharp-darwin-arm64-0.33.5.tgz} + resolution: {integrity: sha512-UT4p+iz/2H4twwAoLCqfA9UH5pI6DggwKEGuaPy7nCVQ8ZsiY5PIcrRvD1DzuY3qYL07NtIQcWnBSY/heikIFQ==, tarball: https://registry.npmjs.org/@img/sharp-darwin-arm64/-/sharp-darwin-arm64-0.33.5.tgz} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} cpu: [arm64] os: [darwin] '@img/sharp-darwin-x64@0.33.5': - resolution: {integrity: sha512-fyHac4jIc1ANYGRDxtiqelIbdWkIuQaI84Mv45KvGRRxSAa7o7d1ZKAOBaYbnepLC1WqxfpimdeWfvqqSGwR2Q==, tarball: https://fbinfra555artifactory.jfrog.io/artifactory/api/npm/fireblocks-npm/@img/sharp-darwin-x64/-/sharp-darwin-x64-0.33.5.tgz} + resolution: {integrity: sha512-fyHac4jIc1ANYGRDxtiqelIbdWkIuQaI84Mv45KvGRRxSAa7o7d1ZKAOBaYbnepLC1WqxfpimdeWfvqqSGwR2Q==, tarball: https://registry.npmjs.org/@img/sharp-darwin-x64/-/sharp-darwin-x64-0.33.5.tgz} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} cpu: [x64] os: [darwin] '@img/sharp-libvips-darwin-arm64@1.0.4': - resolution: {integrity: sha512-XblONe153h0O2zuFfTAbQYAX2JhYmDHeWikp1LM9Hul9gVPjFY427k6dFEcOL72O01QxQsWi761svJ/ev9xEDg==, tarball: https://fbinfra555artifactory.jfrog.io/artifactory/api/npm/fireblocks-npm/@img/sharp-libvips-darwin-arm64/-/sharp-libvips-darwin-arm64-1.0.4.tgz} + resolution: {integrity: sha512-XblONe153h0O2zuFfTAbQYAX2JhYmDHeWikp1LM9Hul9gVPjFY427k6dFEcOL72O01QxQsWi761svJ/ev9xEDg==, tarball: https://registry.npmjs.org/@img/sharp-libvips-darwin-arm64/-/sharp-libvips-darwin-arm64-1.0.4.tgz} cpu: [arm64] os: [darwin] '@img/sharp-libvips-darwin-x64@1.0.4': - resolution: {integrity: sha512-xnGR8YuZYfJGmWPvmlunFaWJsb9T/AO2ykoP3Fz/0X5XV2aoYBPkX6xqCQvUTKKiLddarLaxpzNe+b1hjeWHAQ==, tarball: https://fbinfra555artifactory.jfrog.io/artifactory/api/npm/fireblocks-npm/@img/sharp-libvips-darwin-x64/-/sharp-libvips-darwin-x64-1.0.4.tgz} + resolution: {integrity: sha512-xnGR8YuZYfJGmWPvmlunFaWJsb9T/AO2ykoP3Fz/0X5XV2aoYBPkX6xqCQvUTKKiLddarLaxpzNe+b1hjeWHAQ==, tarball: https://registry.npmjs.org/@img/sharp-libvips-darwin-x64/-/sharp-libvips-darwin-x64-1.0.4.tgz} cpu: [x64] os: [darwin] '@img/sharp-libvips-linux-arm64@1.0.4': - resolution: {integrity: sha512-9B+taZ8DlyyqzZQnoeIvDVR/2F4EbMepXMc/NdVbkzsJbzkUjhXv/70GQJ7tdLA4YJgNP25zukcxpX2/SueNrA==, tarball: https://fbinfra555artifactory.jfrog.io/artifactory/api/npm/fireblocks-npm/@img/sharp-libvips-linux-arm64/-/sharp-libvips-linux-arm64-1.0.4.tgz} + resolution: {integrity: sha512-9B+taZ8DlyyqzZQnoeIvDVR/2F4EbMepXMc/NdVbkzsJbzkUjhXv/70GQJ7tdLA4YJgNP25zukcxpX2/SueNrA==, tarball: https://registry.npmjs.org/@img/sharp-libvips-linux-arm64/-/sharp-libvips-linux-arm64-1.0.4.tgz} cpu: [arm64] os: [linux] libc: [glibc] '@img/sharp-libvips-linux-arm@1.0.5': - resolution: {integrity: sha512-gvcC4ACAOPRNATg/ov8/MnbxFDJqf/pDePbBnuBDcjsI8PssmjoKMAz4LtLaVi+OnSb5FK/yIOamqDwGmXW32g==, tarball: https://fbinfra555artifactory.jfrog.io/artifactory/api/npm/fireblocks-npm/@img/sharp-libvips-linux-arm/-/sharp-libvips-linux-arm-1.0.5.tgz} + resolution: {integrity: sha512-gvcC4ACAOPRNATg/ov8/MnbxFDJqf/pDePbBnuBDcjsI8PssmjoKMAz4LtLaVi+OnSb5FK/yIOamqDwGmXW32g==, tarball: https://registry.npmjs.org/@img/sharp-libvips-linux-arm/-/sharp-libvips-linux-arm-1.0.5.tgz} cpu: [arm] os: [linux] libc: [glibc] '@img/sharp-libvips-linux-s390x@1.0.4': - resolution: {integrity: sha512-u7Wz6ntiSSgGSGcjZ55im6uvTrOxSIS8/dgoVMoiGE9I6JAfU50yH5BoDlYA1tcuGS7g/QNtetJnxA6QEsCVTA==, tarball: https://fbinfra555artifactory.jfrog.io/artifactory/api/npm/fireblocks-npm/@img/sharp-libvips-linux-s390x/-/sharp-libvips-linux-s390x-1.0.4.tgz} + resolution: {integrity: sha512-u7Wz6ntiSSgGSGcjZ55im6uvTrOxSIS8/dgoVMoiGE9I6JAfU50yH5BoDlYA1tcuGS7g/QNtetJnxA6QEsCVTA==, tarball: https://registry.npmjs.org/@img/sharp-libvips-linux-s390x/-/sharp-libvips-linux-s390x-1.0.4.tgz} cpu: [s390x] os: [linux] libc: [glibc] '@img/sharp-libvips-linux-x64@1.0.4': - resolution: {integrity: sha512-MmWmQ3iPFZr0Iev+BAgVMb3ZyC4KeFc3jFxnNbEPas60e1cIfevbtuyf9nDGIzOaW9PdnDciJm+wFFaTlj5xYw==, tarball: https://fbinfra555artifactory.jfrog.io/artifactory/api/npm/fireblocks-npm/@img/sharp-libvips-linux-x64/-/sharp-libvips-linux-x64-1.0.4.tgz} + resolution: {integrity: sha512-MmWmQ3iPFZr0Iev+BAgVMb3ZyC4KeFc3jFxnNbEPas60e1cIfevbtuyf9nDGIzOaW9PdnDciJm+wFFaTlj5xYw==, tarball: https://registry.npmjs.org/@img/sharp-libvips-linux-x64/-/sharp-libvips-linux-x64-1.0.4.tgz} cpu: [x64] os: [linux] libc: [glibc] '@img/sharp-libvips-linuxmusl-arm64@1.0.4': - resolution: {integrity: sha512-9Ti+BbTYDcsbp4wfYib8Ctm1ilkugkA/uscUn6UXK1ldpC1JjiXbLfFZtRlBhjPZ5o1NCLiDbg8fhUPKStHoTA==, tarball: https://fbinfra555artifactory.jfrog.io/artifactory/api/npm/fireblocks-npm/@img/sharp-libvips-linuxmusl-arm64/-/sharp-libvips-linuxmusl-arm64-1.0.4.tgz} + resolution: {integrity: sha512-9Ti+BbTYDcsbp4wfYib8Ctm1ilkugkA/uscUn6UXK1ldpC1JjiXbLfFZtRlBhjPZ5o1NCLiDbg8fhUPKStHoTA==, tarball: https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-arm64/-/sharp-libvips-linuxmusl-arm64-1.0.4.tgz} cpu: [arm64] os: [linux] libc: [musl] '@img/sharp-libvips-linuxmusl-x64@1.0.4': - resolution: {integrity: sha512-viYN1KX9m+/hGkJtvYYp+CCLgnJXwiQB39damAO7WMdKWlIhmYTfHjwSbQeUK/20vY154mwezd9HflVFM1wVSw==, tarball: https://fbinfra555artifactory.jfrog.io/artifactory/api/npm/fireblocks-npm/@img/sharp-libvips-linuxmusl-x64/-/sharp-libvips-linuxmusl-x64-1.0.4.tgz} + resolution: {integrity: sha512-viYN1KX9m+/hGkJtvYYp+CCLgnJXwiQB39damAO7WMdKWlIhmYTfHjwSbQeUK/20vY154mwezd9HflVFM1wVSw==, tarball: https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-x64/-/sharp-libvips-linuxmusl-x64-1.0.4.tgz} cpu: [x64] os: [linux] libc: [musl] '@img/sharp-linux-arm64@0.33.5': - resolution: {integrity: sha512-JMVv+AMRyGOHtO1RFBiJy/MBsgz0x4AWrT6QoEVVTyh1E39TrCUpTRI7mx9VksGX4awWASxqCYLCV4wBZHAYxA==, tarball: https://fbinfra555artifactory.jfrog.io/artifactory/api/npm/fireblocks-npm/@img/sharp-linux-arm64/-/sharp-linux-arm64-0.33.5.tgz} + resolution: {integrity: sha512-JMVv+AMRyGOHtO1RFBiJy/MBsgz0x4AWrT6QoEVVTyh1E39TrCUpTRI7mx9VksGX4awWASxqCYLCV4wBZHAYxA==, tarball: https://registry.npmjs.org/@img/sharp-linux-arm64/-/sharp-linux-arm64-0.33.5.tgz} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} cpu: [arm64] os: [linux] libc: [glibc] '@img/sharp-linux-arm@0.33.5': - resolution: {integrity: sha512-JTS1eldqZbJxjvKaAkxhZmBqPRGmxgu+qFKSInv8moZ2AmT5Yib3EQ1c6gp493HvrvV8QgdOXdyaIBrhvFhBMQ==, tarball: https://fbinfra555artifactory.jfrog.io/artifactory/api/npm/fireblocks-npm/@img/sharp-linux-arm/-/sharp-linux-arm-0.33.5.tgz} + resolution: {integrity: sha512-JTS1eldqZbJxjvKaAkxhZmBqPRGmxgu+qFKSInv8moZ2AmT5Yib3EQ1c6gp493HvrvV8QgdOXdyaIBrhvFhBMQ==, tarball: https://registry.npmjs.org/@img/sharp-linux-arm/-/sharp-linux-arm-0.33.5.tgz} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} cpu: [arm] os: [linux] libc: [glibc] '@img/sharp-linux-s390x@0.33.5': - resolution: {integrity: sha512-y/5PCd+mP4CA/sPDKl2961b+C9d+vPAveS33s6Z3zfASk2j5upL6fXVPZi7ztePZ5CuH+1kW8JtvxgbuXHRa4Q==, tarball: https://fbinfra555artifactory.jfrog.io/artifactory/api/npm/fireblocks-npm/@img/sharp-linux-s390x/-/sharp-linux-s390x-0.33.5.tgz} + resolution: {integrity: sha512-y/5PCd+mP4CA/sPDKl2961b+C9d+vPAveS33s6Z3zfASk2j5upL6fXVPZi7ztePZ5CuH+1kW8JtvxgbuXHRa4Q==, tarball: https://registry.npmjs.org/@img/sharp-linux-s390x/-/sharp-linux-s390x-0.33.5.tgz} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} cpu: [s390x] os: [linux] libc: [glibc] '@img/sharp-linux-x64@0.33.5': - resolution: {integrity: sha512-opC+Ok5pRNAzuvq1AG0ar+1owsu842/Ab+4qvU879ippJBHvyY5n2mxF1izXqkPYlGuP/M556uh53jRLJmzTWA==, tarball: https://fbinfra555artifactory.jfrog.io/artifactory/api/npm/fireblocks-npm/@img/sharp-linux-x64/-/sharp-linux-x64-0.33.5.tgz} + resolution: {integrity: sha512-opC+Ok5pRNAzuvq1AG0ar+1owsu842/Ab+4qvU879ippJBHvyY5n2mxF1izXqkPYlGuP/M556uh53jRLJmzTWA==, tarball: https://registry.npmjs.org/@img/sharp-linux-x64/-/sharp-linux-x64-0.33.5.tgz} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} cpu: [x64] os: [linux] libc: [glibc] '@img/sharp-linuxmusl-arm64@0.33.5': - resolution: {integrity: sha512-XrHMZwGQGvJg2V/oRSUfSAfjfPxO+4DkiRh6p2AFjLQztWUuY/o8Mq0eMQVIY7HJ1CDQUJlxGGZRw1a5bqmd1g==, tarball: https://fbinfra555artifactory.jfrog.io/artifactory/api/npm/fireblocks-npm/@img/sharp-linuxmusl-arm64/-/sharp-linuxmusl-arm64-0.33.5.tgz} + resolution: {integrity: sha512-XrHMZwGQGvJg2V/oRSUfSAfjfPxO+4DkiRh6p2AFjLQztWUuY/o8Mq0eMQVIY7HJ1CDQUJlxGGZRw1a5bqmd1g==, tarball: https://registry.npmjs.org/@img/sharp-linuxmusl-arm64/-/sharp-linuxmusl-arm64-0.33.5.tgz} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} cpu: [arm64] os: [linux] libc: [musl] '@img/sharp-linuxmusl-x64@0.33.5': - resolution: {integrity: sha512-WT+d/cgqKkkKySYmqoZ8y3pxx7lx9vVejxW/W4DOFMYVSkErR+w7mf2u8m/y4+xHe7yY9DAXQMWQhpnMuFfScw==, tarball: https://fbinfra555artifactory.jfrog.io/artifactory/api/npm/fireblocks-npm/@img/sharp-linuxmusl-x64/-/sharp-linuxmusl-x64-0.33.5.tgz} + resolution: {integrity: sha512-WT+d/cgqKkkKySYmqoZ8y3pxx7lx9vVejxW/W4DOFMYVSkErR+w7mf2u8m/y4+xHe7yY9DAXQMWQhpnMuFfScw==, tarball: https://registry.npmjs.org/@img/sharp-linuxmusl-x64/-/sharp-linuxmusl-x64-0.33.5.tgz} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} cpu: [x64] os: [linux] libc: [musl] '@img/sharp-wasm32@0.33.5': - resolution: {integrity: sha512-ykUW4LVGaMcU9lu9thv85CbRMAwfeadCJHRsg2GmeRa/cJxsVY9Rbd57JcMxBkKHag5U/x7TSBpScF4U8ElVzg==, tarball: https://fbinfra555artifactory.jfrog.io/artifactory/api/npm/fireblocks-npm/@img/sharp-wasm32/-/sharp-wasm32-0.33.5.tgz} + resolution: {integrity: sha512-ykUW4LVGaMcU9lu9thv85CbRMAwfeadCJHRsg2GmeRa/cJxsVY9Rbd57JcMxBkKHag5U/x7TSBpScF4U8ElVzg==, tarball: https://registry.npmjs.org/@img/sharp-wasm32/-/sharp-wasm32-0.33.5.tgz} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} cpu: [wasm32] '@img/sharp-win32-ia32@0.33.5': - resolution: {integrity: sha512-T36PblLaTwuVJ/zw/LaH0PdZkRz5rd3SmMHX8GSmR7vtNSP5Z6bQkExdSK7xGWyxLw4sUknBuugTelgw2faBbQ==, tarball: https://fbinfra555artifactory.jfrog.io/artifactory/api/npm/fireblocks-npm/@img/sharp-win32-ia32/-/sharp-win32-ia32-0.33.5.tgz} + resolution: {integrity: sha512-T36PblLaTwuVJ/zw/LaH0PdZkRz5rd3SmMHX8GSmR7vtNSP5Z6bQkExdSK7xGWyxLw4sUknBuugTelgw2faBbQ==, tarball: https://registry.npmjs.org/@img/sharp-win32-ia32/-/sharp-win32-ia32-0.33.5.tgz} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} cpu: [ia32] os: [win32] '@img/sharp-win32-x64@0.33.5': - resolution: {integrity: sha512-MpY/o8/8kj+EcnxwvrP4aTJSWw/aZ7JIGR4aBeZkZw5B7/Jn+tY9/VNwtcoGmdT7GfggGIU4kygOMSbYnOrAbg==, tarball: https://fbinfra555artifactory.jfrog.io/artifactory/api/npm/fireblocks-npm/@img/sharp-win32-x64/-/sharp-win32-x64-0.33.5.tgz} + resolution: {integrity: sha512-MpY/o8/8kj+EcnxwvrP4aTJSWw/aZ7JIGR4aBeZkZw5B7/Jn+tY9/VNwtcoGmdT7GfggGIU4kygOMSbYnOrAbg==, tarball: https://registry.npmjs.org/@img/sharp-win32-x64/-/sharp-win32-x64-0.33.5.tgz} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} cpu: [x64] os: [win32] @@ -1138,10 +1138,10 @@ packages: resolution: {integrity: sha512-+Mzq+W7cNEKfkNZzyLl6A6ffqc3r21HGZUezgfKxpZrkORfOqgRXnS80Zu0IV6a9Ue9QBJeKD7kN0iWfc3bhRQ==} '@radix-ui/primitive@1.1.3': - resolution: {integrity: sha512-JTF99U/6XIjCBo0wqkU5sK10glYe27MRRsfwoiq5zzOEZLHU3A3KCMa5X/azekYRCJ0HlwI0crAXS/5dEHTzDg==, tarball: https://fbinfra555artifactory.jfrog.io/artifactory/api/npm/fireblocks-npm/@radix-ui/primitive/-/primitive-1.1.3.tgz} + resolution: {integrity: sha512-JTF99U/6XIjCBo0wqkU5sK10glYe27MRRsfwoiq5zzOEZLHU3A3KCMa5X/azekYRCJ0HlwI0crAXS/5dEHTzDg==, tarball: https://registry.npmjs.org/@radix-ui/primitive/-/primitive-1.1.3.tgz} '@radix-ui/react-collection@1.1.7': - resolution: {integrity: sha512-Fh9rGN0MoI4ZFUNyfFVNU4y9LUz93u9/0K+yLgA2bwRojxM8JU1DyvvMBabnZPBgMWREAJvU2jjVzq+LrFUglw==, tarball: https://fbinfra555artifactory.jfrog.io/artifactory/api/npm/fireblocks-npm/@radix-ui/react-collection/-/react-collection-1.1.7.tgz} + resolution: {integrity: sha512-Fh9rGN0MoI4ZFUNyfFVNU4y9LUz93u9/0K+yLgA2bwRojxM8JU1DyvvMBabnZPBgMWREAJvU2jjVzq+LrFUglw==, tarball: https://registry.npmjs.org/@radix-ui/react-collection/-/react-collection-1.1.7.tgz} peerDependencies: '@types/react': '*' '@types/react-dom': '*' @@ -1154,7 +1154,7 @@ packages: optional: true '@radix-ui/react-compose-refs@1.1.2': - resolution: {integrity: sha512-z4eqJvfiNnFMHIIvXP3CY57y2WJs5g2v3X0zm9mEJkrkNv4rDxu+sg9Jh8EkXyeqBkB7SOcboo9dMVqhyrACIg==, tarball: https://fbinfra555artifactory.jfrog.io/artifactory/api/npm/fireblocks-npm/@radix-ui/react-compose-refs/-/react-compose-refs-1.1.2.tgz} + resolution: {integrity: sha512-z4eqJvfiNnFMHIIvXP3CY57y2WJs5g2v3X0zm9mEJkrkNv4rDxu+sg9Jh8EkXyeqBkB7SOcboo9dMVqhyrACIg==, tarball: https://registry.npmjs.org/@radix-ui/react-compose-refs/-/react-compose-refs-1.1.2.tgz} peerDependencies: '@types/react': '*' react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc @@ -1163,7 +1163,7 @@ packages: optional: true '@radix-ui/react-context@1.1.2': - resolution: {integrity: sha512-jCi/QKUM2r1Ju5a3J64TH2A5SpKAgh0LpknyqdQ4m6DCV0xJ2HG1xARRwNGPQfi1SLdLWZ1OJz6F4OMBBNiGJA==, tarball: https://fbinfra555artifactory.jfrog.io/artifactory/api/npm/fireblocks-npm/@radix-ui/react-context/-/react-context-1.1.2.tgz} + resolution: {integrity: sha512-jCi/QKUM2r1Ju5a3J64TH2A5SpKAgh0LpknyqdQ4m6DCV0xJ2HG1xARRwNGPQfi1SLdLWZ1OJz6F4OMBBNiGJA==, tarball: https://registry.npmjs.org/@radix-ui/react-context/-/react-context-1.1.2.tgz} peerDependencies: '@types/react': '*' react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc @@ -1185,7 +1185,7 @@ packages: optional: true '@radix-ui/react-direction@1.1.1': - resolution: {integrity: sha512-1UEWRX6jnOA2y4H5WczZ44gOOjTEmlqv1uNW4GAJEO5+bauCBhv8snY65Iw5/VOS/ghKN9gr2KjnLKxrsvoMVw==, tarball: https://fbinfra555artifactory.jfrog.io/artifactory/api/npm/fireblocks-npm/@radix-ui/react-direction/-/react-direction-1.1.1.tgz} + resolution: {integrity: sha512-1UEWRX6jnOA2y4H5WczZ44gOOjTEmlqv1uNW4GAJEO5+bauCBhv8snY65Iw5/VOS/ghKN9gr2KjnLKxrsvoMVw==, tarball: https://registry.npmjs.org/@radix-ui/react-direction/-/react-direction-1.1.1.tgz} peerDependencies: '@types/react': '*' react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc @@ -1194,7 +1194,7 @@ packages: optional: true '@radix-ui/react-dismissable-layer@1.1.11': - resolution: {integrity: sha512-Nqcp+t5cTB8BinFkZgXiMJniQH0PsUt2k51FUhbdfeKvc4ACcG2uQniY/8+h1Yv6Kza4Q7lD7PQV0z0oicE0Mg==, tarball: https://fbinfra555artifactory.jfrog.io/artifactory/api/npm/fireblocks-npm/@radix-ui/react-dismissable-layer/-/react-dismissable-layer-1.1.11.tgz} + resolution: {integrity: sha512-Nqcp+t5cTB8BinFkZgXiMJniQH0PsUt2k51FUhbdfeKvc4ACcG2uQniY/8+h1Yv6Kza4Q7lD7PQV0z0oicE0Mg==, tarball: https://registry.npmjs.org/@radix-ui/react-dismissable-layer/-/react-dismissable-layer-1.1.11.tgz} peerDependencies: '@types/react': '*' '@types/react-dom': '*' @@ -1207,7 +1207,7 @@ packages: optional: true '@radix-ui/react-focus-guards@1.1.3': - resolution: {integrity: sha512-0rFg/Rj2Q62NCm62jZw0QX7a3sz6QCQU0LpZdNrJX8byRGaGVTqbrW9jAoIAHyMQqsNpeZ81YgSizOt5WXq0Pw==, tarball: https://fbinfra555artifactory.jfrog.io/artifactory/api/npm/fireblocks-npm/@radix-ui/react-focus-guards/-/react-focus-guards-1.1.3.tgz} + resolution: {integrity: sha512-0rFg/Rj2Q62NCm62jZw0QX7a3sz6QCQU0LpZdNrJX8byRGaGVTqbrW9jAoIAHyMQqsNpeZ81YgSizOt5WXq0Pw==, tarball: https://registry.npmjs.org/@radix-ui/react-focus-guards/-/react-focus-guards-1.1.3.tgz} peerDependencies: '@types/react': '*' react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc @@ -1216,7 +1216,7 @@ packages: optional: true '@radix-ui/react-focus-scope@1.1.7': - resolution: {integrity: sha512-t2ODlkXBQyn7jkl6TNaw/MtVEVvIGelJDCG41Okq/KwUsJBwQ4XVZsHAVUkK4mBv3ewiAS3PGuUWuY2BoK4ZUw==, tarball: https://fbinfra555artifactory.jfrog.io/artifactory/api/npm/fireblocks-npm/@radix-ui/react-focus-scope/-/react-focus-scope-1.1.7.tgz} + resolution: {integrity: sha512-t2ODlkXBQyn7jkl6TNaw/MtVEVvIGelJDCG41Okq/KwUsJBwQ4XVZsHAVUkK4mBv3ewiAS3PGuUWuY2BoK4ZUw==, tarball: https://registry.npmjs.org/@radix-ui/react-focus-scope/-/react-focus-scope-1.1.7.tgz} peerDependencies: '@types/react': '*' '@types/react-dom': '*' @@ -1229,7 +1229,7 @@ packages: optional: true '@radix-ui/react-id@1.1.1': - resolution: {integrity: sha512-kGkGegYIdQsOb4XjsfM97rXsiHaBwco+hFI66oO4s9LU+PLAC5oJ7khdOVFxkhsmlbpUqDAvXw11CluXP+jkHg==, tarball: https://fbinfra555artifactory.jfrog.io/artifactory/api/npm/fireblocks-npm/@radix-ui/react-id/-/react-id-1.1.1.tgz} + resolution: {integrity: sha512-kGkGegYIdQsOb4XjsfM97rXsiHaBwco+hFI66oO4s9LU+PLAC5oJ7khdOVFxkhsmlbpUqDAvXw11CluXP+jkHg==, tarball: https://registry.npmjs.org/@radix-ui/react-id/-/react-id-1.1.1.tgz} peerDependencies: '@types/react': '*' react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc @@ -1238,7 +1238,7 @@ packages: optional: true '@radix-ui/react-portal@1.1.9': - resolution: {integrity: sha512-bpIxvq03if6UNwXZ+HTK71JLh4APvnXntDc6XOX8UVq4XQOVl7lwok0AvIl+b8zgCw3fSaVTZMpAPPagXbKmHQ==, tarball: https://fbinfra555artifactory.jfrog.io/artifactory/api/npm/fireblocks-npm/@radix-ui/react-portal/-/react-portal-1.1.9.tgz} + resolution: {integrity: sha512-bpIxvq03if6UNwXZ+HTK71JLh4APvnXntDc6XOX8UVq4XQOVl7lwok0AvIl+b8zgCw3fSaVTZMpAPPagXbKmHQ==, tarball: https://registry.npmjs.org/@radix-ui/react-portal/-/react-portal-1.1.9.tgz} peerDependencies: '@types/react': '*' '@types/react-dom': '*' @@ -1251,7 +1251,7 @@ packages: optional: true '@radix-ui/react-presence@1.1.5': - resolution: {integrity: sha512-/jfEwNDdQVBCNvjkGit4h6pMOzq8bHkopq458dPt2lMjx+eBQUohZNG9A7DtO/O5ukSbxuaNGXMjHicgwy6rQQ==, tarball: https://fbinfra555artifactory.jfrog.io/artifactory/api/npm/fireblocks-npm/@radix-ui/react-presence/-/react-presence-1.1.5.tgz} + resolution: {integrity: sha512-/jfEwNDdQVBCNvjkGit4h6pMOzq8bHkopq458dPt2lMjx+eBQUohZNG9A7DtO/O5ukSbxuaNGXMjHicgwy6rQQ==, tarball: https://registry.npmjs.org/@radix-ui/react-presence/-/react-presence-1.1.5.tgz} peerDependencies: '@types/react': '*' '@types/react-dom': '*' @@ -1264,7 +1264,7 @@ packages: optional: true '@radix-ui/react-primitive@2.1.3': - resolution: {integrity: sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ==, tarball: https://fbinfra555artifactory.jfrog.io/artifactory/api/npm/fireblocks-npm/@radix-ui/react-primitive/-/react-primitive-2.1.3.tgz} + resolution: {integrity: sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ==, tarball: https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.1.3.tgz} peerDependencies: '@types/react': '*' '@types/react-dom': '*' @@ -1277,7 +1277,7 @@ packages: optional: true '@radix-ui/react-roving-focus@1.1.11': - resolution: {integrity: sha512-7A6S9jSgm/S+7MdtNDSb+IU859vQqJ/QAtcYQcfFC6W8RS4IxIZDldLR0xqCFZ6DCyrQLjLPsxtTNch5jVA4lA==, tarball: https://fbinfra555artifactory.jfrog.io/artifactory/api/npm/fireblocks-npm/@radix-ui/react-roving-focus/-/react-roving-focus-1.1.11.tgz} + resolution: {integrity: sha512-7A6S9jSgm/S+7MdtNDSb+IU859vQqJ/QAtcYQcfFC6W8RS4IxIZDldLR0xqCFZ6DCyrQLjLPsxtTNch5jVA4lA==, tarball: https://registry.npmjs.org/@radix-ui/react-roving-focus/-/react-roving-focus-1.1.11.tgz} peerDependencies: '@types/react': '*' '@types/react-dom': '*' @@ -1290,7 +1290,7 @@ packages: optional: true '@radix-ui/react-slot@1.2.0': - resolution: {integrity: sha512-ujc+V6r0HNDviYqIK3rW4ffgYiZ8g5DEHrGJVk4x7kTlLXRDILnKX9vAUYeIsLOoDpDJ0ujpqMkjH4w2ofuo6w==, tarball: https://fbinfra555artifactory.jfrog.io/artifactory/api/npm/fireblocks-npm/@radix-ui/react-slot/-/react-slot-1.2.0.tgz} + resolution: {integrity: sha512-ujc+V6r0HNDviYqIK3rW4ffgYiZ8g5DEHrGJVk4x7kTlLXRDILnKX9vAUYeIsLOoDpDJ0ujpqMkjH4w2ofuo6w==, tarball: https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.2.0.tgz} peerDependencies: '@types/react': '*' react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc @@ -1299,7 +1299,7 @@ packages: optional: true '@radix-ui/react-slot@1.2.3': - resolution: {integrity: sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A==, tarball: https://fbinfra555artifactory.jfrog.io/artifactory/api/npm/fireblocks-npm/@radix-ui/react-slot/-/react-slot-1.2.3.tgz} + resolution: {integrity: sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A==, tarball: https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.2.3.tgz} peerDependencies: '@types/react': '*' react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc @@ -1321,7 +1321,7 @@ packages: optional: true '@radix-ui/react-use-callback-ref@1.1.1': - resolution: {integrity: sha512-FkBMwD+qbGQeMu1cOHnuGB6x4yzPjho8ap5WtbEJ26umhgqVXbhekKUQO+hZEL1vU92a3wHwdp0HAcqAUF5iDg==, tarball: https://fbinfra555artifactory.jfrog.io/artifactory/api/npm/fireblocks-npm/@radix-ui/react-use-callback-ref/-/react-use-callback-ref-1.1.1.tgz} + resolution: {integrity: sha512-FkBMwD+qbGQeMu1cOHnuGB6x4yzPjho8ap5WtbEJ26umhgqVXbhekKUQO+hZEL1vU92a3wHwdp0HAcqAUF5iDg==, tarball: https://registry.npmjs.org/@radix-ui/react-use-callback-ref/-/react-use-callback-ref-1.1.1.tgz} peerDependencies: '@types/react': '*' react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc @@ -1330,7 +1330,7 @@ packages: optional: true '@radix-ui/react-use-controllable-state@1.2.2': - resolution: {integrity: sha512-BjasUjixPFdS+NKkypcyyN5Pmg83Olst0+c6vGov0diwTEo6mgdqVR6hxcEgFuh4QrAs7Rc+9KuGJ9TVCj0Zzg==, tarball: https://fbinfra555artifactory.jfrog.io/artifactory/api/npm/fireblocks-npm/@radix-ui/react-use-controllable-state/-/react-use-controllable-state-1.2.2.tgz} + resolution: {integrity: sha512-BjasUjixPFdS+NKkypcyyN5Pmg83Olst0+c6vGov0diwTEo6mgdqVR6hxcEgFuh4QrAs7Rc+9KuGJ9TVCj0Zzg==, tarball: https://registry.npmjs.org/@radix-ui/react-use-controllable-state/-/react-use-controllable-state-1.2.2.tgz} peerDependencies: '@types/react': '*' react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc @@ -1339,7 +1339,7 @@ packages: optional: true '@radix-ui/react-use-effect-event@0.0.2': - resolution: {integrity: sha512-Qp8WbZOBe+blgpuUT+lw2xheLP8q0oatc9UpmiemEICxGvFLYmHm9QowVZGHtJlGbS6A6yJ3iViad/2cVjnOiA==, tarball: https://fbinfra555artifactory.jfrog.io/artifactory/api/npm/fireblocks-npm/@radix-ui/react-use-effect-event/-/react-use-effect-event-0.0.2.tgz} + resolution: {integrity: sha512-Qp8WbZOBe+blgpuUT+lw2xheLP8q0oatc9UpmiemEICxGvFLYmHm9QowVZGHtJlGbS6A6yJ3iViad/2cVjnOiA==, tarball: https://registry.npmjs.org/@radix-ui/react-use-effect-event/-/react-use-effect-event-0.0.2.tgz} peerDependencies: '@types/react': '*' react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc @@ -1348,7 +1348,7 @@ packages: optional: true '@radix-ui/react-use-escape-keydown@1.1.1': - resolution: {integrity: sha512-Il0+boE7w/XebUHyBjroE+DbByORGR9KKmITzbR7MyQ4akpORYP/ZmbhAr0DG7RmmBqoOnZdy2QlvajJ2QA59g==, tarball: https://fbinfra555artifactory.jfrog.io/artifactory/api/npm/fireblocks-npm/@radix-ui/react-use-escape-keydown/-/react-use-escape-keydown-1.1.1.tgz} + resolution: {integrity: sha512-Il0+boE7w/XebUHyBjroE+DbByORGR9KKmITzbR7MyQ4akpORYP/ZmbhAr0DG7RmmBqoOnZdy2QlvajJ2QA59g==, tarball: https://registry.npmjs.org/@radix-ui/react-use-escape-keydown/-/react-use-escape-keydown-1.1.1.tgz} peerDependencies: '@types/react': '*' react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc @@ -1357,7 +1357,7 @@ packages: optional: true '@radix-ui/react-use-layout-effect@1.1.1': - resolution: {integrity: sha512-RbJRS4UWQFkzHTTwVymMTUv8EqYhOp8dOOviLj2ugtTiXRaRQS7GLGxZTLL1jWhMeoSCf5zmcZkqTl9IiYfXcQ==, tarball: https://fbinfra555artifactory.jfrog.io/artifactory/api/npm/fireblocks-npm/@radix-ui/react-use-layout-effect/-/react-use-layout-effect-1.1.1.tgz} + resolution: {integrity: sha512-RbJRS4UWQFkzHTTwVymMTUv8EqYhOp8dOOviLj2ugtTiXRaRQS7GLGxZTLL1jWhMeoSCf5zmcZkqTl9IiYfXcQ==, tarball: https://registry.npmjs.org/@radix-ui/react-use-layout-effect/-/react-use-layout-effect-1.1.1.tgz} peerDependencies: '@types/react': '*' react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc @@ -1366,7 +1366,7 @@ packages: optional: true '@react-native-async-storage/async-storage@2.2.0': - resolution: {integrity: sha512-gvRvjR5JAaUZF8tv2Kcq/Gbt3JHwbKFYfmb445rhOj6NUMx3qPLixmDx5pZAyb9at1bYvJ4/eTUipU5aki45xw==, tarball: https://fbinfra555artifactory.jfrog.io/artifactory/api/npm/fireblocks-npm/@react-native-async-storage/async-storage/-/async-storage-2.2.0.tgz} + resolution: {integrity: sha512-gvRvjR5JAaUZF8tv2Kcq/Gbt3JHwbKFYfmb445rhOj6NUMx3qPLixmDx5pZAyb9at1bYvJ4/eTUipU5aki45xw==, tarball: https://registry.npmjs.org/@react-native-async-storage/async-storage/-/async-storage-2.2.0.tgz} peerDependencies: react-native: ^0.0.0-0 || >=0.65 <1.0 @@ -1377,33 +1377,33 @@ packages: react-native: '>=0.79.0' '@react-native/assets-registry@0.81.4': - resolution: {integrity: sha512-AMcDadefBIjD10BRqkWw+W/VdvXEomR6aEZ0fhQRAv7igrBzb4PTn4vHKYg+sUK0e3wa74kcMy2DLc/HtnGcMA==, tarball: https://fbinfra555artifactory.jfrog.io/artifactory/api/npm/fireblocks-npm/@react-native/assets-registry/-/assets-registry-0.81.4.tgz} + resolution: {integrity: sha512-AMcDadefBIjD10BRqkWw+W/VdvXEomR6aEZ0fhQRAv7igrBzb4PTn4vHKYg+sUK0e3wa74kcMy2DLc/HtnGcMA==, tarball: https://registry.npmjs.org/@react-native/assets-registry/-/assets-registry-0.81.4.tgz} engines: {node: '>= 20.19.4'} '@react-native/babel-plugin-codegen@0.81.5': - resolution: {integrity: sha512-oF71cIH6je3fSLi6VPjjC3Sgyyn57JLHXs+mHWc9MoCiJJcM4nqsS5J38zv1XQ8d3zOW2JtHro+LF0tagj2bfQ==, tarball: https://fbinfra555artifactory.jfrog.io/artifactory/api/npm/fireblocks-npm/@react-native/babel-plugin-codegen/-/babel-plugin-codegen-0.81.5.tgz} + resolution: {integrity: sha512-oF71cIH6je3fSLi6VPjjC3Sgyyn57JLHXs+mHWc9MoCiJJcM4nqsS5J38zv1XQ8d3zOW2JtHro+LF0tagj2bfQ==, tarball: https://registry.npmjs.org/@react-native/babel-plugin-codegen/-/babel-plugin-codegen-0.81.5.tgz} engines: {node: '>= 20.19.4'} '@react-native/babel-preset@0.81.5': - resolution: {integrity: sha512-UoI/x/5tCmi+pZ3c1+Ypr1DaRMDLI3y+Q70pVLLVgrnC3DHsHRIbHcCHIeG/IJvoeFqFM2sTdhSOLJrf8lOPrA==, tarball: https://fbinfra555artifactory.jfrog.io/artifactory/api/npm/fireblocks-npm/@react-native/babel-preset/-/babel-preset-0.81.5.tgz} + resolution: {integrity: sha512-UoI/x/5tCmi+pZ3c1+Ypr1DaRMDLI3y+Q70pVLLVgrnC3DHsHRIbHcCHIeG/IJvoeFqFM2sTdhSOLJrf8lOPrA==, tarball: https://registry.npmjs.org/@react-native/babel-preset/-/babel-preset-0.81.5.tgz} engines: {node: '>= 20.19.4'} peerDependencies: '@babel/core': '*' '@react-native/codegen@0.81.4': - resolution: {integrity: sha512-LWTGUTzFu+qOQnvkzBP52B90Ym3stZT8IFCzzUrppz8Iwglg83FCtDZAR4yLHI29VY/x/+pkcWAMCl3739XHdw==, tarball: https://fbinfra555artifactory.jfrog.io/artifactory/api/npm/fireblocks-npm/@react-native/codegen/-/codegen-0.81.4.tgz} + resolution: {integrity: sha512-LWTGUTzFu+qOQnvkzBP52B90Ym3stZT8IFCzzUrppz8Iwglg83FCtDZAR4yLHI29VY/x/+pkcWAMCl3739XHdw==, tarball: https://registry.npmjs.org/@react-native/codegen/-/codegen-0.81.4.tgz} engines: {node: '>= 20.19.4'} peerDependencies: '@babel/core': '*' '@react-native/codegen@0.81.5': - resolution: {integrity: sha512-a2TDA03Up8lpSa9sh5VRGCQDXgCTOyDOFH+aqyinxp1HChG8uk89/G+nkJ9FPd0rqgi25eCTR16TWdS3b+fA6g==, tarball: https://fbinfra555artifactory.jfrog.io/artifactory/api/npm/fireblocks-npm/@react-native/codegen/-/codegen-0.81.5.tgz} + resolution: {integrity: sha512-a2TDA03Up8lpSa9sh5VRGCQDXgCTOyDOFH+aqyinxp1HChG8uk89/G+nkJ9FPd0rqgi25eCTR16TWdS3b+fA6g==, tarball: https://registry.npmjs.org/@react-native/codegen/-/codegen-0.81.5.tgz} engines: {node: '>= 20.19.4'} peerDependencies: '@babel/core': '*' '@react-native/community-cli-plugin@0.81.4': - resolution: {integrity: sha512-8mpnvfcLcnVh+t1ok6V9eozWo8Ut+TZhz8ylJ6gF9d6q9EGDQX6s8jenan5Yv/pzN4vQEKI4ib2pTf/FELw+SA==, tarball: https://fbinfra555artifactory.jfrog.io/artifactory/api/npm/fireblocks-npm/@react-native/community-cli-plugin/-/community-cli-plugin-0.81.4.tgz} + resolution: {integrity: sha512-8mpnvfcLcnVh+t1ok6V9eozWo8Ut+TZhz8ylJ6gF9d6q9EGDQX6s8jenan5Yv/pzN4vQEKI4ib2pTf/FELw+SA==, tarball: https://registry.npmjs.org/@react-native/community-cli-plugin/-/community-cli-plugin-0.81.4.tgz} engines: {node: '>= 20.19.4'} peerDependencies: '@react-native-community/cli': '*' @@ -1415,37 +1415,37 @@ packages: optional: true '@react-native/debugger-frontend@0.81.4': - resolution: {integrity: sha512-SU05w1wD0nKdQFcuNC9D6De0ITnINCi8MEnx9RsTD2e4wN83ukoC7FpXaPCYyP6+VjFt5tUKDPgP1O7iaNXCqg==, tarball: https://fbinfra555artifactory.jfrog.io/artifactory/api/npm/fireblocks-npm/@react-native/debugger-frontend/-/debugger-frontend-0.81.4.tgz} + resolution: {integrity: sha512-SU05w1wD0nKdQFcuNC9D6De0ITnINCi8MEnx9RsTD2e4wN83ukoC7FpXaPCYyP6+VjFt5tUKDPgP1O7iaNXCqg==, tarball: https://registry.npmjs.org/@react-native/debugger-frontend/-/debugger-frontend-0.81.4.tgz} engines: {node: '>= 20.19.4'} '@react-native/debugger-frontend@0.81.5': - resolution: {integrity: sha512-bnd9FSdWKx2ncklOetCgrlwqSGhMHP2zOxObJbOWXoj7GHEmih4MKarBo5/a8gX8EfA1EwRATdfNBQ81DY+h+w==, tarball: https://fbinfra555artifactory.jfrog.io/artifactory/api/npm/fireblocks-npm/@react-native/debugger-frontend/-/debugger-frontend-0.81.5.tgz} + resolution: {integrity: sha512-bnd9FSdWKx2ncklOetCgrlwqSGhMHP2zOxObJbOWXoj7GHEmih4MKarBo5/a8gX8EfA1EwRATdfNBQ81DY+h+w==, tarball: https://registry.npmjs.org/@react-native/debugger-frontend/-/debugger-frontend-0.81.5.tgz} engines: {node: '>= 20.19.4'} '@react-native/dev-middleware@0.81.4': - resolution: {integrity: sha512-hu1Wu5R28FT7nHXs2wWXvQ++7W7zq5GPY83llajgPlYKznyPLAY/7bArc5rAzNB7b0kwnlaoPQKlvD/VP9LZug==, tarball: https://fbinfra555artifactory.jfrog.io/artifactory/api/npm/fireblocks-npm/@react-native/dev-middleware/-/dev-middleware-0.81.4.tgz} + resolution: {integrity: sha512-hu1Wu5R28FT7nHXs2wWXvQ++7W7zq5GPY83llajgPlYKznyPLAY/7bArc5rAzNB7b0kwnlaoPQKlvD/VP9LZug==, tarball: https://registry.npmjs.org/@react-native/dev-middleware/-/dev-middleware-0.81.4.tgz} engines: {node: '>= 20.19.4'} '@react-native/dev-middleware@0.81.5': - resolution: {integrity: sha512-WfPfZzboYgo/TUtysuD5xyANzzfka8Ebni6RIb2wDxhb56ERi7qDrE4xGhtPsjCL4pQBXSVxyIlCy0d8I6EgGA==, tarball: https://fbinfra555artifactory.jfrog.io/artifactory/api/npm/fireblocks-npm/@react-native/dev-middleware/-/dev-middleware-0.81.5.tgz} + resolution: {integrity: sha512-WfPfZzboYgo/TUtysuD5xyANzzfka8Ebni6RIb2wDxhb56ERi7qDrE4xGhtPsjCL4pQBXSVxyIlCy0d8I6EgGA==, tarball: https://registry.npmjs.org/@react-native/dev-middleware/-/dev-middleware-0.81.5.tgz} engines: {node: '>= 20.19.4'} '@react-native/gradle-plugin@0.81.4': - resolution: {integrity: sha512-T7fPcQvDDCSusZFVSg6H1oVDKb/NnVYLnsqkcHsAF2C2KGXyo3J7slH/tJAwNfj/7EOA2OgcWxfC1frgn9TQvw==, tarball: https://fbinfra555artifactory.jfrog.io/artifactory/api/npm/fireblocks-npm/@react-native/gradle-plugin/-/gradle-plugin-0.81.4.tgz} + resolution: {integrity: sha512-T7fPcQvDDCSusZFVSg6H1oVDKb/NnVYLnsqkcHsAF2C2KGXyo3J7slH/tJAwNfj/7EOA2OgcWxfC1frgn9TQvw==, tarball: https://registry.npmjs.org/@react-native/gradle-plugin/-/gradle-plugin-0.81.4.tgz} engines: {node: '>= 20.19.4'} '@react-native/js-polyfills@0.81.4': - resolution: {integrity: sha512-sr42FaypKXJHMVHhgSbu2f/ZJfrLzgaoQ+HdpRvKEiEh2mhFf6XzZwecyLBvWqf2pMPZa+CpPfNPiejXjKEy8w==, tarball: https://fbinfra555artifactory.jfrog.io/artifactory/api/npm/fireblocks-npm/@react-native/js-polyfills/-/js-polyfills-0.81.4.tgz} + resolution: {integrity: sha512-sr42FaypKXJHMVHhgSbu2f/ZJfrLzgaoQ+HdpRvKEiEh2mhFf6XzZwecyLBvWqf2pMPZa+CpPfNPiejXjKEy8w==, tarball: https://registry.npmjs.org/@react-native/js-polyfills/-/js-polyfills-0.81.4.tgz} engines: {node: '>= 20.19.4'} '@react-native/normalize-colors@0.81.4': - resolution: {integrity: sha512-9nRRHO1H+tcFqjb9gAM105Urtgcanbta2tuqCVY0NATHeFPDEAB7gPyiLxCHKMi1NbhP6TH0kxgSWXKZl1cyRg==, tarball: https://fbinfra555artifactory.jfrog.io/artifactory/api/npm/fireblocks-npm/@react-native/normalize-colors/-/normalize-colors-0.81.4.tgz} + resolution: {integrity: sha512-9nRRHO1H+tcFqjb9gAM105Urtgcanbta2tuqCVY0NATHeFPDEAB7gPyiLxCHKMi1NbhP6TH0kxgSWXKZl1cyRg==, tarball: https://registry.npmjs.org/@react-native/normalize-colors/-/normalize-colors-0.81.4.tgz} '@react-native/normalize-colors@0.81.5': - resolution: {integrity: sha512-0HuJ8YtqlTVRXGZuGeBejLE04wSQsibpTI+RGOyVqxZvgtlLLC/Ssw0UmbHhT4lYMp2fhdtvKZSs5emWB1zR/g==, tarball: https://fbinfra555artifactory.jfrog.io/artifactory/api/npm/fireblocks-npm/@react-native/normalize-colors/-/normalize-colors-0.81.5.tgz} + resolution: {integrity: sha512-0HuJ8YtqlTVRXGZuGeBejLE04wSQsibpTI+RGOyVqxZvgtlLLC/Ssw0UmbHhT4lYMp2fhdtvKZSs5emWB1zR/g==, tarball: https://registry.npmjs.org/@react-native/normalize-colors/-/normalize-colors-0.81.5.tgz} '@react-native/virtualized-lists@0.81.4': - resolution: {integrity: sha512-hBM+rMyL6Wm1Q4f/WpqGsaCojKSNUBqAXLABNGoWm1vabZ7cSnARMxBvA/2vo3hLcoR4v7zDK8tkKm9+O0LjVA==, tarball: https://fbinfra555artifactory.jfrog.io/artifactory/api/npm/fireblocks-npm/@react-native/virtualized-lists/-/virtualized-lists-0.81.4.tgz} + resolution: {integrity: sha512-hBM+rMyL6Wm1Q4f/WpqGsaCojKSNUBqAXLABNGoWm1vabZ7cSnARMxBvA/2vo3hLcoR4v7zDK8tkKm9+O0LjVA==, tarball: https://registry.npmjs.org/@react-native/virtualized-lists/-/virtualized-lists-0.81.4.tgz} engines: {node: '>= 20.19.4'} peerDependencies: '@types/react': ^19.1.0 @@ -1500,10 +1500,10 @@ packages: resolution: {integrity: sha512-9/hhMte12Kgu+pMnLfA4EWJ0OQmIEAMVMX06FPH2yGkEQSQ3JhhCN/GkcRikzQhtEi97VYYQA15umptBUShcOQ==} '@simplewebauthn/browser@13.1.0': - resolution: {integrity: sha512-WuHZ/PYvyPJ9nxSzgHtOEjogBhwJfC8xzYkPC+rR/+8chl/ft4ngjiK8kSU5HtRJfczupyOh33b25TjYbvwAcg==, tarball: https://fbinfra555artifactory.jfrog.io/artifactory/api/npm/fireblocks-npm/@simplewebauthn/browser/-/browser-13.1.0.tgz} + resolution: {integrity: sha512-WuHZ/PYvyPJ9nxSzgHtOEjogBhwJfC8xzYkPC+rR/+8chl/ft4ngjiK8kSU5HtRJfczupyOh33b25TjYbvwAcg==, tarball: https://registry.npmjs.org/@simplewebauthn/browser/-/browser-13.1.0.tgz} '@simplewebauthn/types@12.0.0': - resolution: {integrity: sha512-q6y8MkoV8V8jB4zzp18Uyj2I7oFp2/ONL8c3j8uT06AOWu3cIChc1au71QYHrP2b+xDapkGTiv+9lX7xkTlAsA==, tarball: https://fbinfra555artifactory.jfrog.io/artifactory/api/npm/fireblocks-npm/@simplewebauthn/types/-/types-12.0.0.tgz} + resolution: {integrity: sha512-q6y8MkoV8V8jB4zzp18Uyj2I7oFp2/ONL8c3j8uT06AOWu3cIChc1au71QYHrP2b+xDapkGTiv+9lX7xkTlAsA==, tarball: https://registry.npmjs.org/@simplewebauthn/types/-/types-12.0.0.tgz} deprecated: Package no longer supported. Contact Support at https://www.npmjs.com/support for more info. '@sinclair/typebox@0.27.10': @@ -1528,18 +1528,18 @@ packages: engines: {node: '>=5.10'} '@solana/codecs-core@2.0.0-rc.1': - resolution: {integrity: sha512-bauxqMfSs8EHD0JKESaNmNuNvkvHSuN3bbWAF5RjOfDu2PugxHrvRebmYauvSumZ3cTfQ4HJJX6PG5rN852qyQ==, tarball: https://fbinfra555artifactory.jfrog.io/artifactory/api/npm/fireblocks-npm/@solana/codecs-core/-/codecs-core-2.0.0-rc.1.tgz} + resolution: {integrity: sha512-bauxqMfSs8EHD0JKESaNmNuNvkvHSuN3bbWAF5RjOfDu2PugxHrvRebmYauvSumZ3cTfQ4HJJX6PG5rN852qyQ==, tarball: https://registry.npmjs.org/@solana/codecs-core/-/codecs-core-2.0.0-rc.1.tgz} peerDependencies: typescript: '>=5' '@solana/codecs-core@2.3.0': - resolution: {integrity: sha512-oG+VZzN6YhBHIoSKgS5ESM9VIGzhWjEHEGNPSibiDTxFhsFWxNaz8LbMDPjBUE69r9wmdGLkrQ+wVPbnJcZPvw==, tarball: https://fbinfra555artifactory.jfrog.io/artifactory/api/npm/fireblocks-npm/@solana/codecs-core/-/codecs-core-2.3.0.tgz} + resolution: {integrity: sha512-oG+VZzN6YhBHIoSKgS5ESM9VIGzhWjEHEGNPSibiDTxFhsFWxNaz8LbMDPjBUE69r9wmdGLkrQ+wVPbnJcZPvw==, tarball: https://registry.npmjs.org/@solana/codecs-core/-/codecs-core-2.3.0.tgz} engines: {node: '>=20.18.0'} peerDependencies: typescript: '>=5.3.3' '@solana/codecs-data-structures@2.0.0-rc.1': - resolution: {integrity: sha512-rinCv0RrAVJ9rE/rmaibWJQxMwC5lSaORSZuwjopSUE6T0nb/MVg6Z1siNCXhh/HFTOg0l8bNvZHgBcN/yvXog==, tarball: https://fbinfra555artifactory.jfrog.io/artifactory/api/npm/fireblocks-npm/@solana/codecs-data-structures/-/codecs-data-structures-2.0.0-rc.1.tgz} + resolution: {integrity: sha512-rinCv0RrAVJ9rE/rmaibWJQxMwC5lSaORSZuwjopSUE6T0nb/MVg6Z1siNCXhh/HFTOg0l8bNvZHgBcN/yvXog==, tarball: https://registry.npmjs.org/@solana/codecs-data-structures/-/codecs-data-structures-2.0.0-rc.1.tgz} peerDependencies: typescript: '>=5' @@ -1555,31 +1555,31 @@ packages: typescript: '>=5.3.3' '@solana/codecs-strings@2.0.0-rc.1': - resolution: {integrity: sha512-9/wPhw8TbGRTt6mHC4Zz1RqOnuPTqq1Nb4EyuvpZ39GW6O2t2Q7Q0XxiB3+BdoEjwA2XgPw6e2iRfvYgqty44g==, tarball: https://fbinfra555artifactory.jfrog.io/artifactory/api/npm/fireblocks-npm/@solana/codecs-strings/-/codecs-strings-2.0.0-rc.1.tgz} + resolution: {integrity: sha512-9/wPhw8TbGRTt6mHC4Zz1RqOnuPTqq1Nb4EyuvpZ39GW6O2t2Q7Q0XxiB3+BdoEjwA2XgPw6e2iRfvYgqty44g==, tarball: https://registry.npmjs.org/@solana/codecs-strings/-/codecs-strings-2.0.0-rc.1.tgz} peerDependencies: fastestsmallesttextencoderdecoder: ^1.0.22 typescript: '>=5' '@solana/codecs@2.0.0-rc.1': - resolution: {integrity: sha512-qxoR7VybNJixV51L0G1RD2boZTcxmwUWnKCaJJExQ5qNKwbpSyDdWfFJfM5JhGyKe9DnPVOZB+JHWXnpbZBqrQ==, tarball: https://fbinfra555artifactory.jfrog.io/artifactory/api/npm/fireblocks-npm/@solana/codecs/-/codecs-2.0.0-rc.1.tgz} + resolution: {integrity: sha512-qxoR7VybNJixV51L0G1RD2boZTcxmwUWnKCaJJExQ5qNKwbpSyDdWfFJfM5JhGyKe9DnPVOZB+JHWXnpbZBqrQ==, tarball: https://registry.npmjs.org/@solana/codecs/-/codecs-2.0.0-rc.1.tgz} peerDependencies: typescript: '>=5' '@solana/errors@2.0.0-rc.1': - resolution: {integrity: sha512-ejNvQ2oJ7+bcFAYWj225lyRkHnixuAeb7RQCixm+5mH4n1IA4Qya/9Bmfy5RAAHQzxK43clu3kZmL5eF9VGtYQ==, tarball: https://fbinfra555artifactory.jfrog.io/artifactory/api/npm/fireblocks-npm/@solana/errors/-/errors-2.0.0-rc.1.tgz} + resolution: {integrity: sha512-ejNvQ2oJ7+bcFAYWj225lyRkHnixuAeb7RQCixm+5mH4n1IA4Qya/9Bmfy5RAAHQzxK43clu3kZmL5eF9VGtYQ==, tarball: https://registry.npmjs.org/@solana/errors/-/errors-2.0.0-rc.1.tgz} hasBin: true peerDependencies: typescript: '>=5' '@solana/errors@2.3.0': - resolution: {integrity: sha512-66RI9MAbwYV0UtP7kGcTBVLxJgUxoZGm8Fbc0ah+lGiAw17Gugco6+9GrJCV83VyF2mDWyYnYM9qdI3yjgpnaQ==, tarball: https://fbinfra555artifactory.jfrog.io/artifactory/api/npm/fireblocks-npm/@solana/errors/-/errors-2.3.0.tgz} + resolution: {integrity: sha512-66RI9MAbwYV0UtP7kGcTBVLxJgUxoZGm8Fbc0ah+lGiAw17Gugco6+9GrJCV83VyF2mDWyYnYM9qdI3yjgpnaQ==, tarball: https://registry.npmjs.org/@solana/errors/-/errors-2.3.0.tgz} engines: {node: '>=20.18.0'} hasBin: true peerDependencies: typescript: '>=5.3.3' '@solana/options@2.0.0-rc.1': - resolution: {integrity: sha512-mLUcR9mZ3qfHlmMnREdIFPf9dpMc/Bl66tLSOOWxw4ml5xMT2ohFn7WGqoKcu/UHkT9CrC6+amEdqCNvUqI7AA==, tarball: https://fbinfra555artifactory.jfrog.io/artifactory/api/npm/fireblocks-npm/@solana/options/-/options-2.0.0-rc.1.tgz} + resolution: {integrity: sha512-mLUcR9mZ3qfHlmMnREdIFPf9dpMc/Bl66tLSOOWxw4ml5xMT2ohFn7WGqoKcu/UHkT9CrC6+amEdqCNvUqI7AA==, tarball: https://registry.npmjs.org/@solana/options/-/options-2.0.0-rc.1.tgz} peerDependencies: typescript: '>=5' @@ -1596,13 +1596,13 @@ packages: '@solana/web3.js': ^1.95.3 '@solana/spl-token@0.4.13': - resolution: {integrity: sha512-cite/pYWQZZVvLbg5lsodSovbetK/eA24gaR0eeUeMuBAMNrT8XFCwaygKy0N2WSg3gSyjjNpIeAGBAKZaY/1w==, tarball: https://fbinfra555artifactory.jfrog.io/artifactory/api/npm/fireblocks-npm/@solana/spl-token/-/spl-token-0.4.13.tgz} + resolution: {integrity: sha512-cite/pYWQZZVvLbg5lsodSovbetK/eA24gaR0eeUeMuBAMNrT8XFCwaygKy0N2WSg3gSyjjNpIeAGBAKZaY/1w==, tarball: https://registry.npmjs.org/@solana/spl-token/-/spl-token-0.4.13.tgz} engines: {node: '>=16'} peerDependencies: '@solana/web3.js': ^1.95.5 '@solana/spl-token@0.4.14': - resolution: {integrity: sha512-u09zr96UBpX4U685MnvQsNzlvw9TiY005hk1vJmJr7gMJldoPG1eYU5/wNEyOA5lkMLiR/gOi9SFD4MefOYEsA==, tarball: https://fbinfra555artifactory.jfrog.io/artifactory/api/npm/fireblocks-npm/@solana/spl-token/-/spl-token-0.4.14.tgz} + resolution: {integrity: sha512-u09zr96UBpX4U685MnvQsNzlvw9TiY005hk1vJmJr7gMJldoPG1eYU5/wNEyOA5lkMLiR/gOi9SFD4MefOYEsA==, tarball: https://registry.npmjs.org/@solana/spl-token/-/spl-token-0.4.14.tgz} engines: {node: '>=16'} peerDependencies: '@solana/web3.js': ^1.95.5 @@ -1626,7 +1626,7 @@ packages: engines: {node: '>=18.0.0'} '@turnkey/encoding@0.6.0': - resolution: {integrity: sha512-IC8qXvy36+iGAeiaVIuJvB35uU2Ld/RAWI/DRTKS+ttBej0GXhOn48Ouu5mlca4jt8ZEuwXmDVv74A8uBQclsA==, tarball: https://fbinfra555artifactory.jfrog.io/artifactory/api/npm/fireblocks-npm/@turnkey/encoding/-/encoding-0.6.0.tgz} + resolution: {integrity: sha512-IC8qXvy36+iGAeiaVIuJvB35uU2Ld/RAWI/DRTKS+ttBej0GXhOn48Ouu5mlca4jt8ZEuwXmDVv74A8uBQclsA==, tarball: https://registry.npmjs.org/@turnkey/encoding/-/encoding-0.6.0.tgz} engines: {node: '>=18.0.0'} '@turnkey/http@3.16.1': @@ -1634,7 +1634,7 @@ packages: engines: {node: '>=18.0.0'} '@turnkey/react-native-passkey-stamper@1.2.7': - resolution: {integrity: sha512-w8Ka8EO+Tu1o2qI/y4NNuhfhGWEF9Bc7vNQAgpJ5RPkEjFYTqA6SQsRNToFpf/AQjvyNDRlBq5k83XHqm2oVdQ==, tarball: https://fbinfra555artifactory.jfrog.io/artifactory/api/npm/fireblocks-npm/@turnkey/react-native-passkey-stamper/-/react-native-passkey-stamper-1.2.7.tgz} + resolution: {integrity: sha512-w8Ka8EO+Tu1o2qI/y4NNuhfhGWEF9Bc7vNQAgpJ5RPkEjFYTqA6SQsRNToFpf/AQjvyNDRlBq5k83XHqm2oVdQ==, tarball: https://registry.npmjs.org/@turnkey/react-native-passkey-stamper/-/react-native-passkey-stamper-1.2.7.tgz} engines: {node: '>=18.0.0'} '@turnkey/sdk-types@0.11.1': @@ -1642,7 +1642,7 @@ packages: engines: {node: '>=18.0.0'} '@turnkey/webauthn-stamper@0.6.0': - resolution: {integrity: sha512-jdN17QEnn7RBykEOhtKIialWmDjnDAH8DzbyITwn8jsKcwT1TBNYge89hTUTjbdsDLBAqQw8cHujPdy0RaAqvw==, tarball: https://fbinfra555artifactory.jfrog.io/artifactory/api/npm/fireblocks-npm/@turnkey/webauthn-stamper/-/webauthn-stamper-0.6.0.tgz} + resolution: {integrity: sha512-jdN17QEnn7RBykEOhtKIialWmDjnDAH8DzbyITwn8jsKcwT1TBNYge89hTUTjbdsDLBAqQw8cHujPdy0RaAqvw==, tarball: https://registry.npmjs.org/@turnkey/webauthn-stamper/-/webauthn-stamper-0.6.0.tgz} engines: {node: '>=18.0.0'} '@types/babel__core@7.20.5': @@ -1726,7 +1726,7 @@ packages: resolution: {integrity: sha512-y9XDjCEuBp+98k+UL5dbYkh57AHU4o6cxZedOPXw3bmrZZYLQsVHguGurq7hVrPCSrQtrnz1f9dssyFr+dMXfQ==} '@vue/shared@3.5.34': - resolution: {integrity: sha512-24uqU4OIiX29ryC3MeWid/Xf2fa2EFRUVLb77nRhk+UrTVrh/XiGtFAFmJBAtBRbjwNdsPRP+jj/OL27Eg1NDA==, tarball: https://fbinfra555artifactory.jfrog.io/artifactory/api/npm/fireblocks-npm/@vue/shared/-/shared-3.5.34.tgz} + resolution: {integrity: sha512-24uqU4OIiX29ryC3MeWid/Xf2fa2EFRUVLb77nRhk+UrTVrh/XiGtFAFmJBAtBRbjwNdsPRP+jj/OL27Eg1NDA==, tarball: https://registry.npmjs.org/@vue/shared/-/shared-3.5.34.tgz} '@xmldom/xmldom@0.8.13': resolution: {integrity: sha512-KRYzxepc14G/CEpEGc3Yn+JKaAeT63smlDr+vjB8jRfgTBBI9wRj/nkQEO+ucV8p8I9bfKLWp37uHgFrbntPvw==} @@ -1737,7 +1737,7 @@ packages: engines: {node: '>=14.6'} ably@2.17.1: - resolution: {integrity: sha512-70yfXHoM7JtJD/8FCtPD1gkWW0f+AJqbJp0PsqDAqiyxFB8cPFY+FuKHgNTYb8eRHKXq8hT1xiDphUcY0+GHnA==, tarball: https://fbinfra555artifactory.jfrog.io/artifactory/api/npm/fireblocks-npm/ably/-/ably-2.17.1.tgz} + resolution: {integrity: sha512-70yfXHoM7JtJD/8FCtPD1gkWW0f+AJqbJp0PsqDAqiyxFB8cPFY+FuKHgNTYb8eRHKXq8hT1xiDphUcY0+GHnA==, tarball: https://registry.npmjs.org/ably/-/ably-2.17.1.tgz} engines: {node: '>=16'} peerDependencies: react: '>=16.8.0' @@ -1811,7 +1811,7 @@ packages: resolution: {integrity: sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==} argon2id@1.0.1: - resolution: {integrity: sha512-rsiD3lX+0L0CsiZARp3bf9EGxprtuWAT7PpiJd+Fk53URV0/USOQkBIP1dLTV8t6aui0ECbymQ9W9YCcTd6XgA==, tarball: https://fbinfra555artifactory.jfrog.io/artifactory/api/npm/fireblocks-npm/argon2id/-/argon2id-1.0.1.tgz} + resolution: {integrity: sha512-rsiD3lX+0L0CsiZARp3bf9EGxprtuWAT7PpiJd+Fk53URV0/USOQkBIP1dLTV8t6aui0ECbymQ9W9YCcTd6XgA==, tarball: https://registry.npmjs.org/argon2id/-/argon2id-1.0.1.tgz} argparse@1.0.10: resolution: {integrity: sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==} @@ -1841,16 +1841,16 @@ packages: engines: {node: '>= 0.4'} axios@1.13.2: - resolution: {integrity: sha512-VPk9ebNqPcy5lRGuSlKx752IlDatOjT9paPlm8A7yOuW2Fbvp4X3JznJtT4f0GzGLLiWE9W8onz51SqLYwzGaA==, tarball: https://fbinfra555artifactory.jfrog.io/artifactory/api/npm/fireblocks-npm/axios/-/axios-1.13.2.tgz} + resolution: {integrity: sha512-VPk9ebNqPcy5lRGuSlKx752IlDatOjT9paPlm8A7yOuW2Fbvp4X3JznJtT4f0GzGLLiWE9W8onz51SqLYwzGaA==, tarball: https://registry.npmjs.org/axios/-/axios-1.13.2.tgz} axios@1.15.0: - resolution: {integrity: sha512-wWyJDlAatxk30ZJer+GeCWS209sA42X+N5jU2jy6oHTp7ufw8uzUTVFBX9+wTfAlhiJXGS0Bq7X6efruWjuK9Q==, tarball: https://fbinfra555artifactory.jfrog.io/artifactory/api/npm/fireblocks-npm/axios/-/axios-1.15.0.tgz} + resolution: {integrity: sha512-wWyJDlAatxk30ZJer+GeCWS209sA42X+N5jU2jy6oHTp7ufw8uzUTVFBX9+wTfAlhiJXGS0Bq7X6efruWjuK9Q==, tarball: https://registry.npmjs.org/axios/-/axios-1.15.0.tgz} axios@1.15.2: - resolution: {integrity: sha512-wLrXxPtcrPTsNlJmKjkPnNPK2Ihe0hn0wGSaTEiHRPxwjvJwT3hKmXF4dpqxmPO9SoNb2FsYXj/xEo0gHN+D5A==, tarball: https://fbinfra555artifactory.jfrog.io/artifactory/api/npm/fireblocks-npm/axios/-/axios-1.15.2.tgz} + resolution: {integrity: sha512-wLrXxPtcrPTsNlJmKjkPnNPK2Ihe0hn0wGSaTEiHRPxwjvJwT3hKmXF4dpqxmPO9SoNb2FsYXj/xEo0gHN+D5A==, tarball: https://registry.npmjs.org/axios/-/axios-1.15.2.tgz} axios@1.9.0: - resolution: {integrity: sha512-re4CqKTJaURpzbLHtIi6XpDv20/CnpXOtjRY5/CU32L8gU8ek9UIivcfvSWvmKEngmVbrUtPpdDwWDWL7DNHvg==, tarball: https://fbinfra555artifactory.jfrog.io/artifactory/api/npm/fireblocks-npm/axios/-/axios-1.9.0.tgz} + resolution: {integrity: sha512-re4CqKTJaURpzbLHtIi6XpDv20/CnpXOtjRY5/CU32L8gU8ek9UIivcfvSWvmKEngmVbrUtPpdDwWDWL7DNHvg==, tarball: https://registry.npmjs.org/axios/-/axios-1.9.0.tgz} babel-jest@29.7.0: resolution: {integrity: sha512-BrvGY3xZSwEcCzKvKsCi2GgHqDqsYkOP4/by5xCgIwGXQxIEh+8ew3gmrE1y7XRR6LHZIj6yLYnUi/mm2KXKBg==} @@ -1888,7 +1888,7 @@ packages: resolution: {integrity: sha512-SPD0J6qjJn8231i0HZhlAGH6NORe+QvRSQM2mwQEzJ2Fb3E4ruWTiiicPlHjmeWShDXLcvoorOCXjeR7k/lyWA==} babel-plugin-syntax-hermes-parser@0.29.1: - resolution: {integrity: sha512-2WFYnoWGdmih1I1J5eIqxATOeycOqRwYxAQBu3cUu/rhwInwHUg7k60AFNbuGjSDL8tje5GDrAnxzRLcu2pYcA==, tarball: https://fbinfra555artifactory.jfrog.io/artifactory/api/npm/fireblocks-npm/babel-plugin-syntax-hermes-parser/-/babel-plugin-syntax-hermes-parser-0.29.1.tgz} + resolution: {integrity: sha512-2WFYnoWGdmih1I1J5eIqxATOeycOqRwYxAQBu3cUu/rhwInwHUg7k60AFNbuGjSDL8tje5GDrAnxzRLcu2pYcA==, tarball: https://registry.npmjs.org/babel-plugin-syntax-hermes-parser/-/babel-plugin-syntax-hermes-parser-0.29.1.tgz} babel-plugin-transform-flow-enums@0.0.2: resolution: {integrity: sha512-g4aaCrDDOsWjbm0PUUeVnkcVd6AKJsVc/MbnPhEotEpkeJQP6b8nzewohQi7+QS8UyPehOhGWn0nOwjvWpmMvQ==} @@ -1975,7 +1975,7 @@ packages: resolution: {integrity: sha512-kc9+BgR3zz9+cjbwM8ODoUB4fs3X3I5A/HtX7LZKxCLaMrEeDFoBpnhZY//DTS1VZBSs6S5v46RZRbZjRFspEg==} bplist-creator@0.1.0: - resolution: {integrity: sha512-sXaHZicyEEmY86WyueLTQesbeoH/mquvarJaQNbjuOQO+7gbFcDEWqKmcWA4cOTLzFlfgvkiVxolk1k5bBIpmg==, tarball: https://fbinfra555artifactory.jfrog.io/artifactory/api/npm/fireblocks-npm/bplist-creator/-/bplist-creator-0.1.0.tgz} + resolution: {integrity: sha512-sXaHZicyEEmY86WyueLTQesbeoH/mquvarJaQNbjuOQO+7gbFcDEWqKmcWA4cOTLzFlfgvkiVxolk1k5bBIpmg==, tarball: https://registry.npmjs.org/bplist-creator/-/bplist-creator-0.1.0.tgz} bplist-parser@0.3.1: resolution: {integrity: sha512-PyJxiNtA5T2PlLIeBot4lbp7rj4OadzjnMZD/G5zuBNt8ei/yCU7+wW0h2bag9vr8c+/WuRWmSxbqAl9hL1rBA==} @@ -2011,10 +2011,10 @@ packages: resolution: {integrity: sha512-PD0wEnEYg6ijszw/u8s+iI3H17cTymlrwkKhDhPZq+Sokl3AU4htyBFTjAeNAlCCmg0f53g6ih3jATyCKftTfw==} bs58check@4.0.0: - resolution: {integrity: sha512-FsGDOnFg9aVI9erdriULkd/JjEWONV/lQE5aYziB5PoBsXRind56lh8doIZIc9X4HoxT5x4bLjMWN1/NB8Zp5g==, tarball: https://fbinfra555artifactory.jfrog.io/artifactory/api/npm/fireblocks-npm/bs58check/-/bs58check-4.0.0.tgz} + resolution: {integrity: sha512-FsGDOnFg9aVI9erdriULkd/JjEWONV/lQE5aYziB5PoBsXRind56lh8doIZIc9X4HoxT5x4bLjMWN1/NB8Zp5g==, tarball: https://registry.npmjs.org/bs58check/-/bs58check-4.0.0.tgz} bser@2.1.1: - resolution: {integrity: sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==, tarball: https://fbinfra555artifactory.jfrog.io/artifactory/api/npm/fireblocks-npm/bser/-/bser-2.1.1.tgz} + resolution: {integrity: sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==, tarball: https://registry.npmjs.org/bser/-/bser-2.1.1.tgz} buffer-from@1.1.2: resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==} @@ -2030,7 +2030,7 @@ packages: engines: {node: '>=6.14.2'} bytes@3.1.2: - resolution: {integrity: sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==, tarball: https://fbinfra555artifactory.jfrog.io/artifactory/api/npm/fireblocks-npm/bytes/-/bytes-3.1.2.tgz} + resolution: {integrity: sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==, tarball: https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz} engines: {node: '>= 0.8'} cacheable-lookup@5.0.4: @@ -2172,7 +2172,7 @@ packages: engines: {node: '>= 0.8.0'} concat-map@0.0.1: - resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==, tarball: https://fbinfra555artifactory.jfrog.io/artifactory/api/npm/fireblocks-npm/concat-map/-/concat-map-0.0.1.tgz} + resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==, tarball: https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz} connect@3.7.0: resolution: {integrity: sha512-ZqRXc+tZukToSNmh5C2iWMSoV3X1YUcPbqEM4DkEG5tNQXrQUZCNVGGv3IuicnkMtPfGf3Xtp8WCXs295iQ1pQ==} @@ -2259,7 +2259,7 @@ packages: engines: {node: '>=0.4.0'} depd@2.0.0: - resolution: {integrity: sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==, tarball: https://fbinfra555artifactory.jfrog.io/artifactory/api/npm/fireblocks-npm/depd/-/depd-2.0.0.tgz} + resolution: {integrity: sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==, tarball: https://registry.npmjs.org/depd/-/depd-2.0.0.tgz} engines: {node: '>= 0.8'} dequal@2.0.3: @@ -2267,7 +2267,7 @@ packages: engines: {node: '>=6'} destroy@1.2.0: - resolution: {integrity: sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==, tarball: https://fbinfra555artifactory.jfrog.io/artifactory/api/npm/fireblocks-npm/destroy/-/destroy-1.2.0.tgz} + resolution: {integrity: sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==, tarball: https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz} engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16} detect-libc@2.1.2: @@ -2290,7 +2290,7 @@ packages: engines: {node: '>= 0.4'} ee-first@1.1.1: - resolution: {integrity: sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==, tarball: https://fbinfra555artifactory.jfrog.io/artifactory/api/npm/fireblocks-npm/ee-first/-/ee-first-1.1.1.tgz} + resolution: {integrity: sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==, tarball: https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz} electron-to-chromium@1.5.353: resolution: {integrity: sha512-kOrWphBi8TOZyiJZqsgqIle0lw+tzmnQK83pV9dZUd01Nm2POECSyFQMAuarzZdYqQW7FH9RaYOuaRo3h+bQ3w==} @@ -2422,11 +2422,11 @@ packages: react-native: '*' expo-modules-autolinking@3.0.25: - resolution: {integrity: sha512-YmHWctJlwvOuLZccg3cOXvSiXVJrPMKl7g2YR0YHWoGL9v2RvcmgaPJWPSLVW+voNEgEPsbo5UmUrAqbnYcBeg==, tarball: https://fbinfra555artifactory.jfrog.io/artifactory/api/npm/fireblocks-npm/expo-modules-autolinking/-/expo-modules-autolinking-3.0.25.tgz} + resolution: {integrity: sha512-YmHWctJlwvOuLZccg3cOXvSiXVJrPMKl7g2YR0YHWoGL9v2RvcmgaPJWPSLVW+voNEgEPsbo5UmUrAqbnYcBeg==, tarball: https://registry.npmjs.org/expo-modules-autolinking/-/expo-modules-autolinking-3.0.25.tgz} hasBin: true expo-modules-core@3.0.30: - resolution: {integrity: sha512-a6IrpAn/Jbmwxi9L+hMmXKpNqnkUpoF7WHOpn02rVLyax2J0gB1vvCVE5rNydplEnt41Q6WxQwvcOjZaIkcSUg==, tarball: https://fbinfra555artifactory.jfrog.io/artifactory/api/npm/fireblocks-npm/expo-modules-core/-/expo-modules-core-3.0.30.tgz} + resolution: {integrity: sha512-a6IrpAn/Jbmwxi9L+hMmXKpNqnkUpoF7WHOpn02rVLyax2J0gB1vvCVE5rNydplEnt41Q6WxQwvcOjZaIkcSUg==, tarball: https://registry.npmjs.org/expo-modules-core/-/expo-modules-core-3.0.30.tgz} peerDependencies: react: '*' react-native: '*' @@ -2543,7 +2543,7 @@ packages: optional: true file-uri-to-path@1.0.0: - resolution: {integrity: sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==, tarball: https://fbinfra555artifactory.jfrog.io/artifactory/api/npm/fireblocks-npm/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz} + resolution: {integrity: sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==, tarball: https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz} fill-range@7.1.1: resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==} @@ -2554,7 +2554,7 @@ packages: engines: {node: '>=0.10.0'} finalhandler@1.1.2: - resolution: {integrity: sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==, tarball: https://fbinfra555artifactory.jfrog.io/artifactory/api/npm/fireblocks-npm/finalhandler/-/finalhandler-1.1.2.tgz} + resolution: {integrity: sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==, tarball: https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz} engines: {node: '>= 0.8'} find-up@4.1.0: @@ -2685,13 +2685,13 @@ packages: engines: {node: '>= 0.4'} hermes-estree@0.29.1: - resolution: {integrity: sha512-jl+x31n4/w+wEqm0I2r4CMimukLbLQEYpisys5oCre611CI5fc9TxhqkBBCJ1edDG4Kza0f7CgNz8xVMLZQOmQ==, tarball: https://fbinfra555artifactory.jfrog.io/artifactory/api/npm/fireblocks-npm/hermes-estree/-/hermes-estree-0.29.1.tgz} + resolution: {integrity: sha512-jl+x31n4/w+wEqm0I2r4CMimukLbLQEYpisys5oCre611CI5fc9TxhqkBBCJ1edDG4Kza0f7CgNz8xVMLZQOmQ==, tarball: https://registry.npmjs.org/hermes-estree/-/hermes-estree-0.29.1.tgz} hermes-estree@0.32.0: - resolution: {integrity: sha512-KWn3BqnlDOl97Xe1Yviur6NbgIZ+IP+UVSpshlZWkq+EtoHg6/cwiDj/osP9PCEgFE15KBm1O55JRwbMEm5ejQ==, tarball: https://fbinfra555artifactory.jfrog.io/artifactory/api/npm/fireblocks-npm/hermes-estree/-/hermes-estree-0.32.0.tgz} + resolution: {integrity: sha512-KWn3BqnlDOl97Xe1Yviur6NbgIZ+IP+UVSpshlZWkq+EtoHg6/cwiDj/osP9PCEgFE15KBm1O55JRwbMEm5ejQ==, tarball: https://registry.npmjs.org/hermes-estree/-/hermes-estree-0.32.0.tgz} hermes-estree@0.35.0: - resolution: {integrity: sha512-xVx5Opwy8Oo1I5yGpVRhCvWL/iV3M+ylksSKVNlxxD90cpDpR/AR1jLYqK8HWihm065a6UI3HeyAmYzwS8NOOg==, tarball: https://fbinfra555artifactory.jfrog.io/artifactory/api/npm/fireblocks-npm/hermes-estree/-/hermes-estree-0.35.0.tgz} + resolution: {integrity: sha512-xVx5Opwy8Oo1I5yGpVRhCvWL/iV3M+ylksSKVNlxxD90cpDpR/AR1jLYqK8HWihm065a6UI3HeyAmYzwS8NOOg==, tarball: https://registry.npmjs.org/hermes-estree/-/hermes-estree-0.35.0.tgz} hermes-parser@0.29.1: resolution: {integrity: sha512-xBHWmUtRC5e/UL0tI7Ivt2riA/YBq9+SiYFU7C1oBa/j2jYGlIF9043oak1F47ihuDIxQ5nbsKueYJDRY02UgA==} @@ -2732,7 +2732,7 @@ packages: resolution: {integrity: sha512-Fl70vYtsAFb/C06PTS9dZBo7ihau+Tu/DNCk/OyHhea07S+aeMWpFFkUaXRa8fI+ScZbEI8dfSxwY7gxZ9SAVQ==} i18next@23.4.6: - resolution: {integrity: sha512-jBE8bui969Ygv7TVYp0pwDZB7+he0qsU+nz7EcfdqSh+QvKjEfl9YPRQd/KrGiMhTYFGkeuPaeITenKK/bSFDg==, tarball: https://fbinfra555artifactory.jfrog.io/artifactory/api/npm/fireblocks-npm/i18next/-/i18next-23.4.6.tgz} + resolution: {integrity: sha512-jBE8bui969Ygv7TVYp0pwDZB7+he0qsU+nz7EcfdqSh+QvKjEfl9YPRQd/KrGiMhTYFGkeuPaeITenKK/bSFDg==, tarball: https://registry.npmjs.org/i18next/-/i18next-23.4.6.tgz} ieee754@1.2.1: resolution: {integrity: sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==} @@ -2879,7 +2879,7 @@ packages: engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} jimp-compact@0.16.1: - resolution: {integrity: sha512-dZ6Ra7u1G8c4Letq/B5EzAxj4tLFHL+cGtdpR+PVm4yzPDj+lCk+AbivWt1eOM+ikzkowtyV7qSqX6qr3t71Ww==, tarball: https://fbinfra555artifactory.jfrog.io/artifactory/api/npm/fireblocks-npm/jimp-compact/-/jimp-compact-0.16.1.tgz} + resolution: {integrity: sha512-dZ6Ra7u1G8c4Letq/B5EzAxj4tLFHL+cGtdpR+PVm4yzPDj+lCk+AbivWt1eOM+ikzkowtyV7qSqX6qr3t71Ww==, tarball: https://registry.npmjs.org/jimp-compact/-/jimp-compact-0.16.1.tgz} js-tokens@4.0.0: resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} @@ -2901,7 +2901,7 @@ packages: hasBin: true json-buffer@3.0.1: - resolution: {integrity: sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==, tarball: https://fbinfra555artifactory.jfrog.io/artifactory/api/npm/fireblocks-npm/json-buffer/-/json-buffer-3.0.1.tgz} + resolution: {integrity: sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==, tarball: https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz} json-stringify-safe@5.0.1: resolution: {integrity: sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==} @@ -2930,71 +2930,71 @@ packages: resolution: {integrity: sha512-gPWxznF6TKmUHrOQjlVo2UbaL2EJ71mb2CCeRs/2qBpi4L/g4LUVc9+3lKQ6DTUZwJswfM7ainGrLO1+fOqa2g==} lightningcss-android-arm64@1.32.0: - resolution: {integrity: sha512-YK7/ClTt4kAK0vo6w3X+Pnm0D2cf2vPHbhOXdoNti1Ga0al1P4TBZhwjATvjNwLEBCnKvjJc2jQgHXH0NEwlAg==, tarball: https://fbinfra555artifactory.jfrog.io/artifactory/api/npm/fireblocks-npm/lightningcss-android-arm64/-/lightningcss-android-arm64-1.32.0.tgz} + resolution: {integrity: sha512-YK7/ClTt4kAK0vo6w3X+Pnm0D2cf2vPHbhOXdoNti1Ga0al1P4TBZhwjATvjNwLEBCnKvjJc2jQgHXH0NEwlAg==, tarball: https://registry.npmjs.org/lightningcss-android-arm64/-/lightningcss-android-arm64-1.32.0.tgz} engines: {node: '>= 12.0.0'} cpu: [arm64] os: [android] lightningcss-darwin-arm64@1.32.0: - resolution: {integrity: sha512-RzeG9Ju5bag2Bv1/lwlVJvBE3q6TtXskdZLLCyfg5pt+HLz9BqlICO7LZM7VHNTTn/5PRhHFBSjk5lc4cmscPQ==, tarball: https://fbinfra555artifactory.jfrog.io/artifactory/api/npm/fireblocks-npm/lightningcss-darwin-arm64/-/lightningcss-darwin-arm64-1.32.0.tgz} + resolution: {integrity: sha512-RzeG9Ju5bag2Bv1/lwlVJvBE3q6TtXskdZLLCyfg5pt+HLz9BqlICO7LZM7VHNTTn/5PRhHFBSjk5lc4cmscPQ==, tarball: https://registry.npmjs.org/lightningcss-darwin-arm64/-/lightningcss-darwin-arm64-1.32.0.tgz} engines: {node: '>= 12.0.0'} cpu: [arm64] os: [darwin] lightningcss-darwin-x64@1.32.0: - resolution: {integrity: sha512-U+QsBp2m/s2wqpUYT/6wnlagdZbtZdndSmut/NJqlCcMLTWp5muCrID+K5UJ6jqD2BFshejCYXniPDbNh73V8w==, tarball: https://fbinfra555artifactory.jfrog.io/artifactory/api/npm/fireblocks-npm/lightningcss-darwin-x64/-/lightningcss-darwin-x64-1.32.0.tgz} + resolution: {integrity: sha512-U+QsBp2m/s2wqpUYT/6wnlagdZbtZdndSmut/NJqlCcMLTWp5muCrID+K5UJ6jqD2BFshejCYXniPDbNh73V8w==, tarball: https://registry.npmjs.org/lightningcss-darwin-x64/-/lightningcss-darwin-x64-1.32.0.tgz} engines: {node: '>= 12.0.0'} cpu: [x64] os: [darwin] lightningcss-freebsd-x64@1.32.0: - resolution: {integrity: sha512-JCTigedEksZk3tHTTthnMdVfGf61Fky8Ji2E4YjUTEQX14xiy/lTzXnu1vwiZe3bYe0q+SpsSH/CTeDXK6WHig==, tarball: https://fbinfra555artifactory.jfrog.io/artifactory/api/npm/fireblocks-npm/lightningcss-freebsd-x64/-/lightningcss-freebsd-x64-1.32.0.tgz} + resolution: {integrity: sha512-JCTigedEksZk3tHTTthnMdVfGf61Fky8Ji2E4YjUTEQX14xiy/lTzXnu1vwiZe3bYe0q+SpsSH/CTeDXK6WHig==, tarball: https://registry.npmjs.org/lightningcss-freebsd-x64/-/lightningcss-freebsd-x64-1.32.0.tgz} engines: {node: '>= 12.0.0'} cpu: [x64] os: [freebsd] lightningcss-linux-arm-gnueabihf@1.32.0: - resolution: {integrity: sha512-x6rnnpRa2GL0zQOkt6rts3YDPzduLpWvwAF6EMhXFVZXD4tPrBkEFqzGowzCsIWsPjqSK+tyNEODUBXeeVHSkw==, tarball: https://fbinfra555artifactory.jfrog.io/artifactory/api/npm/fireblocks-npm/lightningcss-linux-arm-gnueabihf/-/lightningcss-linux-arm-gnueabihf-1.32.0.tgz} + resolution: {integrity: sha512-x6rnnpRa2GL0zQOkt6rts3YDPzduLpWvwAF6EMhXFVZXD4tPrBkEFqzGowzCsIWsPjqSK+tyNEODUBXeeVHSkw==, tarball: https://registry.npmjs.org/lightningcss-linux-arm-gnueabihf/-/lightningcss-linux-arm-gnueabihf-1.32.0.tgz} engines: {node: '>= 12.0.0'} cpu: [arm] os: [linux] lightningcss-linux-arm64-gnu@1.32.0: - resolution: {integrity: sha512-0nnMyoyOLRJXfbMOilaSRcLH3Jw5z9HDNGfT/gwCPgaDjnx0i8w7vBzFLFR1f6CMLKF8gVbebmkUN3fa/kQJpQ==, tarball: https://fbinfra555artifactory.jfrog.io/artifactory/api/npm/fireblocks-npm/lightningcss-linux-arm64-gnu/-/lightningcss-linux-arm64-gnu-1.32.0.tgz} + resolution: {integrity: sha512-0nnMyoyOLRJXfbMOilaSRcLH3Jw5z9HDNGfT/gwCPgaDjnx0i8w7vBzFLFR1f6CMLKF8gVbebmkUN3fa/kQJpQ==, tarball: https://registry.npmjs.org/lightningcss-linux-arm64-gnu/-/lightningcss-linux-arm64-gnu-1.32.0.tgz} engines: {node: '>= 12.0.0'} cpu: [arm64] os: [linux] libc: [glibc] lightningcss-linux-arm64-musl@1.32.0: - resolution: {integrity: sha512-UpQkoenr4UJEzgVIYpI80lDFvRmPVg6oqboNHfoH4CQIfNA+HOrZ7Mo7KZP02dC6LjghPQJeBsvXhJod/wnIBg==, tarball: https://fbinfra555artifactory.jfrog.io/artifactory/api/npm/fireblocks-npm/lightningcss-linux-arm64-musl/-/lightningcss-linux-arm64-musl-1.32.0.tgz} + resolution: {integrity: sha512-UpQkoenr4UJEzgVIYpI80lDFvRmPVg6oqboNHfoH4CQIfNA+HOrZ7Mo7KZP02dC6LjghPQJeBsvXhJod/wnIBg==, tarball: https://registry.npmjs.org/lightningcss-linux-arm64-musl/-/lightningcss-linux-arm64-musl-1.32.0.tgz} engines: {node: '>= 12.0.0'} cpu: [arm64] os: [linux] libc: [musl] lightningcss-linux-x64-gnu@1.32.0: - resolution: {integrity: sha512-V7Qr52IhZmdKPVr+Vtw8o+WLsQJYCTd8loIfpDaMRWGUZfBOYEJeyJIkqGIDMZPwPx24pUMfwSxxI8phr/MbOA==, tarball: https://fbinfra555artifactory.jfrog.io/artifactory/api/npm/fireblocks-npm/lightningcss-linux-x64-gnu/-/lightningcss-linux-x64-gnu-1.32.0.tgz} + resolution: {integrity: sha512-V7Qr52IhZmdKPVr+Vtw8o+WLsQJYCTd8loIfpDaMRWGUZfBOYEJeyJIkqGIDMZPwPx24pUMfwSxxI8phr/MbOA==, tarball: https://registry.npmjs.org/lightningcss-linux-x64-gnu/-/lightningcss-linux-x64-gnu-1.32.0.tgz} engines: {node: '>= 12.0.0'} cpu: [x64] os: [linux] libc: [glibc] lightningcss-linux-x64-musl@1.32.0: - resolution: {integrity: sha512-bYcLp+Vb0awsiXg/80uCRezCYHNg1/l3mt0gzHnWV9XP1W5sKa5/TCdGWaR/zBM2PeF/HbsQv/j2URNOiVuxWg==, tarball: https://fbinfra555artifactory.jfrog.io/artifactory/api/npm/fireblocks-npm/lightningcss-linux-x64-musl/-/lightningcss-linux-x64-musl-1.32.0.tgz} + resolution: {integrity: sha512-bYcLp+Vb0awsiXg/80uCRezCYHNg1/l3mt0gzHnWV9XP1W5sKa5/TCdGWaR/zBM2PeF/HbsQv/j2URNOiVuxWg==, tarball: https://registry.npmjs.org/lightningcss-linux-x64-musl/-/lightningcss-linux-x64-musl-1.32.0.tgz} engines: {node: '>= 12.0.0'} cpu: [x64] os: [linux] libc: [musl] lightningcss-win32-arm64-msvc@1.32.0: - resolution: {integrity: sha512-8SbC8BR40pS6baCM8sbtYDSwEVQd4JlFTOlaD3gWGHfThTcABnNDBda6eTZeqbofalIJhFx0qKzgHJmcPTnGdw==, tarball: https://fbinfra555artifactory.jfrog.io/artifactory/api/npm/fireblocks-npm/lightningcss-win32-arm64-msvc/-/lightningcss-win32-arm64-msvc-1.32.0.tgz} + resolution: {integrity: sha512-8SbC8BR40pS6baCM8sbtYDSwEVQd4JlFTOlaD3gWGHfThTcABnNDBda6eTZeqbofalIJhFx0qKzgHJmcPTnGdw==, tarball: https://registry.npmjs.org/lightningcss-win32-arm64-msvc/-/lightningcss-win32-arm64-msvc-1.32.0.tgz} engines: {node: '>= 12.0.0'} cpu: [arm64] os: [win32] lightningcss-win32-x64-msvc@1.32.0: - resolution: {integrity: sha512-Amq9B/SoZYdDi1kFrojnoqPLxYhQ4Wo5XiL8EVJrVsB8ARoC1PWW6VGtT0WKCemjy8aC+louJnjS7U18x3b06Q==, tarball: https://fbinfra555artifactory.jfrog.io/artifactory/api/npm/fireblocks-npm/lightningcss-win32-x64-msvc/-/lightningcss-win32-x64-msvc-1.32.0.tgz} + resolution: {integrity: sha512-Amq9B/SoZYdDi1kFrojnoqPLxYhQ4Wo5XiL8EVJrVsB8ARoC1PWW6VGtT0WKCemjy8aC+louJnjS7U18x3b06Q==, tarball: https://registry.npmjs.org/lightningcss-win32-x64-msvc/-/lightningcss-win32-x64-msvc-1.32.0.tgz} engines: {node: '>= 12.0.0'} cpu: [x64] os: [win32] @@ -3039,7 +3039,7 @@ packages: resolution: {integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==} makeerror@1.0.12: - resolution: {integrity: sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==, tarball: https://fbinfra555artifactory.jfrog.io/artifactory/api/npm/fireblocks-npm/makeerror/-/makeerror-1.0.12.tgz} + resolution: {integrity: sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==, tarball: https://registry.npmjs.org/makeerror/-/makeerror-1.0.12.tgz} marky@1.3.0: resolution: {integrity: sha512-ocnPZQLNpvbedwTy9kNrQEsknEfgvcLMvOtz3sFeWApDq1MXH1TqkCIx58xlpESsfwQOnuBO9beyQuNGzVvuhQ==} @@ -3059,7 +3059,7 @@ packages: resolution: {integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==} metro-babel-transformer@0.83.3: - resolution: {integrity: sha512-1vxlvj2yY24ES1O5RsSIvg4a4WeL7PFXgKOHvXTXiW0deLvQr28ExXj6LjwCCDZ4YZLhq6HddLpZnX4dEdSq5g==, tarball: https://fbinfra555artifactory.jfrog.io/artifactory/api/npm/fireblocks-npm/metro-babel-transformer/-/metro-babel-transformer-0.83.3.tgz} + resolution: {integrity: sha512-1vxlvj2yY24ES1O5RsSIvg4a4WeL7PFXgKOHvXTXiW0deLvQr28ExXj6LjwCCDZ4YZLhq6HddLpZnX4dEdSq5g==, tarball: https://registry.npmjs.org/metro-babel-transformer/-/metro-babel-transformer-0.83.3.tgz} engines: {node: '>=20.19.4'} metro-babel-transformer@0.83.7: @@ -3067,7 +3067,7 @@ packages: engines: {node: '>=20.19.4'} metro-cache-key@0.83.3: - resolution: {integrity: sha512-59ZO049jKzSmvBmG/B5bZ6/dztP0ilp0o988nc6dpaDsU05Cl1c/lRf+yx8m9WW/JVgbmfO5MziBU559XjI5Zw==, tarball: https://fbinfra555artifactory.jfrog.io/artifactory/api/npm/fireblocks-npm/metro-cache-key/-/metro-cache-key-0.83.3.tgz} + resolution: {integrity: sha512-59ZO049jKzSmvBmG/B5bZ6/dztP0ilp0o988nc6dpaDsU05Cl1c/lRf+yx8m9WW/JVgbmfO5MziBU559XjI5Zw==, tarball: https://registry.npmjs.org/metro-cache-key/-/metro-cache-key-0.83.3.tgz} engines: {node: '>=20.19.4'} metro-cache-key@0.83.7: @@ -3075,7 +3075,7 @@ packages: engines: {node: '>=20.19.4'} metro-cache@0.83.3: - resolution: {integrity: sha512-3jo65X515mQJvKqK3vWRblxDEcgY55Sk3w4xa6LlfEXgQ9g1WgMh9m4qVZVwgcHoLy0a2HENTPCCX4Pk6s8c8Q==, tarball: https://fbinfra555artifactory.jfrog.io/artifactory/api/npm/fireblocks-npm/metro-cache/-/metro-cache-0.83.3.tgz} + resolution: {integrity: sha512-3jo65X515mQJvKqK3vWRblxDEcgY55Sk3w4xa6LlfEXgQ9g1WgMh9m4qVZVwgcHoLy0a2HENTPCCX4Pk6s8c8Q==, tarball: https://registry.npmjs.org/metro-cache/-/metro-cache-0.83.3.tgz} engines: {node: '>=20.19.4'} metro-cache@0.83.7: @@ -3083,7 +3083,7 @@ packages: engines: {node: '>=20.19.4'} metro-config@0.83.3: - resolution: {integrity: sha512-mTel7ipT0yNjKILIan04bkJkuCzUUkm2SeEaTads8VfEecCh+ltXchdq6DovXJqzQAXuR2P9cxZB47Lg4klriA==, tarball: https://fbinfra555artifactory.jfrog.io/artifactory/api/npm/fireblocks-npm/metro-config/-/metro-config-0.83.3.tgz} + resolution: {integrity: sha512-mTel7ipT0yNjKILIan04bkJkuCzUUkm2SeEaTads8VfEecCh+ltXchdq6DovXJqzQAXuR2P9cxZB47Lg4klriA==, tarball: https://registry.npmjs.org/metro-config/-/metro-config-0.83.3.tgz} engines: {node: '>=20.19.4'} metro-config@0.83.7: @@ -3091,7 +3091,7 @@ packages: engines: {node: '>=20.19.4'} metro-core@0.83.3: - resolution: {integrity: sha512-M+X59lm7oBmJZamc96usuF1kusd5YimqG/q97g4Ac7slnJ3YiGglW5CsOlicTR5EWf8MQFxxjDoB6ytTqRe8Hw==, tarball: https://fbinfra555artifactory.jfrog.io/artifactory/api/npm/fireblocks-npm/metro-core/-/metro-core-0.83.3.tgz} + resolution: {integrity: sha512-M+X59lm7oBmJZamc96usuF1kusd5YimqG/q97g4Ac7slnJ3YiGglW5CsOlicTR5EWf8MQFxxjDoB6ytTqRe8Hw==, tarball: https://registry.npmjs.org/metro-core/-/metro-core-0.83.3.tgz} engines: {node: '>=20.19.4'} metro-core@0.83.7: @@ -3099,7 +3099,7 @@ packages: engines: {node: '>=20.19.4'} metro-file-map@0.83.3: - resolution: {integrity: sha512-jg5AcyE0Q9Xbbu/4NAwwZkmQn7doJCKGW0SLeSJmzNB9Z24jBe0AL2PHNMy4eu0JiKtNWHz9IiONGZWq7hjVTA==, tarball: https://fbinfra555artifactory.jfrog.io/artifactory/api/npm/fireblocks-npm/metro-file-map/-/metro-file-map-0.83.3.tgz} + resolution: {integrity: sha512-jg5AcyE0Q9Xbbu/4NAwwZkmQn7doJCKGW0SLeSJmzNB9Z24jBe0AL2PHNMy4eu0JiKtNWHz9IiONGZWq7hjVTA==, tarball: https://registry.npmjs.org/metro-file-map/-/metro-file-map-0.83.3.tgz} engines: {node: '>=20.19.4'} metro-file-map@0.83.7: @@ -3107,7 +3107,7 @@ packages: engines: {node: '>=20.19.4'} metro-minify-terser@0.83.3: - resolution: {integrity: sha512-O2BmfWj6FSfzBLrNCXt/rr2VYZdX5i6444QJU0fFoc7Ljg+Q+iqebwE3K0eTvkI6TRjELsXk1cjU+fXwAR4OjQ==, tarball: https://fbinfra555artifactory.jfrog.io/artifactory/api/npm/fireblocks-npm/metro-minify-terser/-/metro-minify-terser-0.83.3.tgz} + resolution: {integrity: sha512-O2BmfWj6FSfzBLrNCXt/rr2VYZdX5i6444QJU0fFoc7Ljg+Q+iqebwE3K0eTvkI6TRjELsXk1cjU+fXwAR4OjQ==, tarball: https://registry.npmjs.org/metro-minify-terser/-/metro-minify-terser-0.83.3.tgz} engines: {node: '>=20.19.4'} metro-minify-terser@0.83.7: @@ -3115,7 +3115,7 @@ packages: engines: {node: '>=20.19.4'} metro-resolver@0.83.3: - resolution: {integrity: sha512-0js+zwI5flFxb1ktmR///bxHYg7OLpRpWZlBBruYG8OKYxeMP7SV0xQ/o/hUelrEMdK4LJzqVtHAhBm25LVfAQ==, tarball: https://fbinfra555artifactory.jfrog.io/artifactory/api/npm/fireblocks-npm/metro-resolver/-/metro-resolver-0.83.3.tgz} + resolution: {integrity: sha512-0js+zwI5flFxb1ktmR///bxHYg7OLpRpWZlBBruYG8OKYxeMP7SV0xQ/o/hUelrEMdK4LJzqVtHAhBm25LVfAQ==, tarball: https://registry.npmjs.org/metro-resolver/-/metro-resolver-0.83.3.tgz} engines: {node: '>=20.19.4'} metro-resolver@0.83.7: @@ -3139,7 +3139,7 @@ packages: engines: {node: '>=20.19.4'} metro-symbolicate@0.83.3: - resolution: {integrity: sha512-F/YChgKd6KbFK3eUR5HdUsfBqVsanf5lNTwFd4Ca7uuxnHgBC3kR/Hba/RGkenR3pZaGNp5Bu9ZqqP52Wyhomw==, tarball: https://fbinfra555artifactory.jfrog.io/artifactory/api/npm/fireblocks-npm/metro-symbolicate/-/metro-symbolicate-0.83.3.tgz} + resolution: {integrity: sha512-F/YChgKd6KbFK3eUR5HdUsfBqVsanf5lNTwFd4Ca7uuxnHgBC3kR/Hba/RGkenR3pZaGNp5Bu9ZqqP52Wyhomw==, tarball: https://registry.npmjs.org/metro-symbolicate/-/metro-symbolicate-0.83.3.tgz} engines: {node: '>=20.19.4'} hasBin: true @@ -3149,7 +3149,7 @@ packages: hasBin: true metro-transform-plugins@0.83.3: - resolution: {integrity: sha512-eRGoKJU6jmqOakBMH5kUB7VitEWiNrDzBHpYbkBXW7C5fUGeOd2CyqrosEzbMK5VMiZYyOcNFEphvxk3OXey2A==, tarball: https://fbinfra555artifactory.jfrog.io/artifactory/api/npm/fireblocks-npm/metro-transform-plugins/-/metro-transform-plugins-0.83.3.tgz} + resolution: {integrity: sha512-eRGoKJU6jmqOakBMH5kUB7VitEWiNrDzBHpYbkBXW7C5fUGeOd2CyqrosEzbMK5VMiZYyOcNFEphvxk3OXey2A==, tarball: https://registry.npmjs.org/metro-transform-plugins/-/metro-transform-plugins-0.83.3.tgz} engines: {node: '>=20.19.4'} metro-transform-plugins@0.83.7: @@ -3157,7 +3157,7 @@ packages: engines: {node: '>=20.19.4'} metro-transform-worker@0.83.3: - resolution: {integrity: sha512-Ztekew9t/gOIMZX1tvJOgX7KlSLL5kWykl0Iwu2cL2vKMKVALRl1hysyhUw0vjpAvLFx+Kfq9VLjnHIkW32fPA==, tarball: https://fbinfra555artifactory.jfrog.io/artifactory/api/npm/fireblocks-npm/metro-transform-worker/-/metro-transform-worker-0.83.3.tgz} + resolution: {integrity: sha512-Ztekew9t/gOIMZX1tvJOgX7KlSLL5kWykl0Iwu2cL2vKMKVALRl1hysyhUw0vjpAvLFx+Kfq9VLjnHIkW32fPA==, tarball: https://registry.npmjs.org/metro-transform-worker/-/metro-transform-worker-0.83.3.tgz} engines: {node: '>=20.19.4'} metro-transform-worker@0.83.7: @@ -3165,7 +3165,7 @@ packages: engines: {node: '>=20.19.4'} metro@0.83.3: - resolution: {integrity: sha512-+rP+/GieOzkt97hSJ0MrPOuAH/jpaS21ZDvL9DJ35QYRDlQcwzcvUlGUf79AnQxq/2NPiS/AULhhM4TKutIt8Q==, tarball: https://fbinfra555artifactory.jfrog.io/artifactory/api/npm/fireblocks-npm/metro/-/metro-0.83.3.tgz} + resolution: {integrity: sha512-+rP+/GieOzkt97hSJ0MrPOuAH/jpaS21ZDvL9DJ35QYRDlQcwzcvUlGUf79AnQxq/2NPiS/AULhhM4TKutIt8Q==, tarball: https://registry.npmjs.org/metro/-/metro-0.83.3.tgz} engines: {node: '>=20.19.4'} hasBin: true @@ -3179,7 +3179,7 @@ packages: engines: {node: '>=8.6'} mime-db@1.52.0: - resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==, tarball: https://fbinfra555artifactory.jfrog.io/artifactory/api/npm/fireblocks-npm/mime-db/-/mime-db-1.52.0.tgz} + resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==, tarball: https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz} engines: {node: '>= 0.6'} mime-db@1.54.0: @@ -3195,7 +3195,7 @@ packages: engines: {node: '>=18'} mime@1.6.0: - resolution: {integrity: sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==, tarball: https://fbinfra555artifactory.jfrog.io/artifactory/api/npm/fireblocks-npm/mime/-/mime-1.6.0.tgz} + resolution: {integrity: sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==, tarball: https://registry.npmjs.org/mime/-/mime-1.6.0.tgz} engines: {node: '>=4'} hasBin: true @@ -3253,7 +3253,7 @@ packages: hasBin: true negotiator@0.6.3: - resolution: {integrity: sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==, tarball: https://fbinfra555artifactory.jfrog.io/artifactory/api/npm/fireblocks-npm/negotiator/-/negotiator-0.6.3.tgz} + resolution: {integrity: sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==, tarball: https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz} engines: {node: '>= 0.6'} negotiator@0.6.4: @@ -3365,7 +3365,7 @@ packages: engines: {node: '>=8'} p-queue@9.1.0: - resolution: {integrity: sha512-O/ZPaXuQV29uSLbxWBGGZO1mCQXV2BLIwUr59JUU9SoH76mnYvtms7aafH/isNSNGwuEfP6W/4xD0/TJXxrizw==, tarball: https://fbinfra555artifactory.jfrog.io/artifactory/api/npm/fireblocks-npm/p-queue/-/p-queue-9.1.0.tgz} + resolution: {integrity: sha512-O/ZPaXuQV29uSLbxWBGGZO1mCQXV2BLIwUr59JUU9SoH76mnYvtms7aafH/isNSNGwuEfP6W/4xD0/TJXxrizw==, tarball: https://registry.npmjs.org/p-queue/-/p-queue-9.1.0.tgz} engines: {node: '>=20'} p-timeout@7.0.1: @@ -3468,7 +3468,7 @@ packages: resolution: {integrity: sha512-VS7sjc6KR7e1ukRFhQSY5LM2uBWAUPiOPa/A3mkKmiMwSmRFUITt0xuj+/lesgnCv+dPIEYlkzrcyXgquIHMcA==} punycode@1.3.2: - resolution: {integrity: sha512-RofWgt/7fL5wP1Y7fxE7/EmTLzQVnB0ycyibJ0OOHIlJqTNzglYFxVwETOcIoJqJmpDXJ9xImDv+Fq34F/d4Dw==, tarball: https://fbinfra555artifactory.jfrog.io/artifactory/api/npm/fireblocks-npm/punycode/-/punycode-1.3.2.tgz} + resolution: {integrity: sha512-RofWgt/7fL5wP1Y7fxE7/EmTLzQVnB0ycyibJ0OOHIlJqTNzglYFxVwETOcIoJqJmpDXJ9xImDv+Fq34F/d4Dw==, tarball: https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz} punycode@2.3.1: resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==} @@ -3482,7 +3482,7 @@ packages: engines: {node: '>=16.0.0'} qrcode-terminal@0.11.0: - resolution: {integrity: sha512-Uu7ii+FQy4Qf82G4xu7ShHhjhGahEpCWc3x8UavY3CTcWV+ufmmCtwkr7ZKsX42jdL0kr1B5FKUeqJvAn51jzQ==, tarball: https://fbinfra555artifactory.jfrog.io/artifactory/api/npm/fireblocks-npm/qrcode-terminal/-/qrcode-terminal-0.11.0.tgz} + resolution: {integrity: sha512-Uu7ii+FQy4Qf82G4xu7ShHhjhGahEpCWc3x8UavY3CTcWV+ufmmCtwkr7ZKsX42jdL0kr1B5FKUeqJvAn51jzQ==, tarball: https://registry.npmjs.org/qrcode-terminal/-/qrcode-terminal-0.11.0.tgz} hasBin: true query-string@7.1.3: @@ -3490,12 +3490,12 @@ packages: engines: {node: '>=6'} querystring@0.2.0: - resolution: {integrity: sha512-X/xY82scca2tau62i9mDyU9K+I+djTMUsvwf7xnUX5GLvVzgJybOJf4Y6o9Zx3oJK/LSXg5tTZBjwzqVPaPO2g==, tarball: https://fbinfra555artifactory.jfrog.io/artifactory/api/npm/fireblocks-npm/querystring/-/querystring-0.2.0.tgz} + resolution: {integrity: sha512-X/xY82scca2tau62i9mDyU9K+I+djTMUsvwf7xnUX5GLvVzgJybOJf4Y6o9Zx3oJK/LSXg5tTZBjwzqVPaPO2g==, tarball: https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz} engines: {node: '>=0.4.x'} deprecated: The querystring API is considered Legacy. new code should use the URLSearchParams API instead. queue@6.0.2: - resolution: {integrity: sha512-iHZWu+q3IdFZFX36ro/lKBkSvfkztY5Y7HMiPlOUjhupPcG2JMfst2KKEpu5XndviX/3UhFbRngUPNKtgvtZiA==, tarball: https://fbinfra555artifactory.jfrog.io/artifactory/api/npm/fireblocks-npm/queue/-/queue-6.0.2.tgz} + resolution: {integrity: sha512-iHZWu+q3IdFZFX36ro/lKBkSvfkztY5Y7HMiPlOUjhupPcG2JMfst2KKEpu5XndviX/3UhFbRngUPNKtgvtZiA==, tarball: https://registry.npmjs.org/queue/-/queue-6.0.2.tgz} quick-lru@5.1.1: resolution: {integrity: sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==} @@ -3513,7 +3513,7 @@ packages: resolution: {integrity: sha512-ePrwPfxAnB+7hgnEr8vpKxL9cmnp7F322t8oqcPshbIQQhDKgFDW4tjhF2wjVbdXF9O/nyuy3sQWd9JGpiLPvA==} react-dom@19.2.5: - resolution: {integrity: sha512-J5bAZz+DXMMwW/wV3xzKke59Af6CHY7G4uYLN1OvBcKEsWOs4pQExj86BBKamxl/Ik5bx9whOrvBlSDfWzgSag==, tarball: https://fbinfra555artifactory.jfrog.io/artifactory/api/npm/fireblocks-npm/react-dom/-/react-dom-19.2.5.tgz} + resolution: {integrity: sha512-J5bAZz+DXMMwW/wV3xzKke59Af6CHY7G4uYLN1OvBcKEsWOs4pQExj86BBKamxl/Ik5bx9whOrvBlSDfWzgSag==, tarball: https://registry.npmjs.org/react-dom/-/react-dom-19.2.5.tgz} peerDependencies: react: ^19.2.5 @@ -3527,7 +3527,7 @@ packages: react: '>=17.0.0' react-i18next@13.5.0: - resolution: {integrity: sha512-CFJ5NDGJ2MUyBohEHxljOq/39NQ972rh1ajnadG9BjTk+UXbHLq4z5DKEbEQBDoIhUmmbuS/fIMJKo6VOax1HA==, tarball: https://fbinfra555artifactory.jfrog.io/artifactory/api/npm/fireblocks-npm/react-i18next/-/react-i18next-13.5.0.tgz} + resolution: {integrity: sha512-CFJ5NDGJ2MUyBohEHxljOq/39NQ972rh1ajnadG9BjTk+UXbHLq4z5DKEbEQBDoIhUmmbuS/fIMJKo6VOax1HA==, tarball: https://registry.npmjs.org/react-i18next/-/react-i18next-13.5.0.tgz} peerDependencies: i18next: '>= 23.2.3' react: '>= 16.8.0' @@ -3566,7 +3566,7 @@ packages: react-native: '*' react-native-passkey@3.3.2: - resolution: {integrity: sha512-YgXERrBlgVHAYkxGPpncB0zoiRQfZyMMMlWfNTYMyKvOS6muFMlhzk6w5lG4FyEEVrvXHGV4AS6twbmt2Rv8GA==, tarball: https://fbinfra555artifactory.jfrog.io/artifactory/api/npm/fireblocks-npm/react-native-passkey/-/react-native-passkey-3.3.2.tgz} + resolution: {integrity: sha512-YgXERrBlgVHAYkxGPpncB0zoiRQfZyMMMlWfNTYMyKvOS6muFMlhzk6w5lG4FyEEVrvXHGV4AS6twbmt2Rv8GA==, tarball: https://registry.npmjs.org/react-native-passkey/-/react-native-passkey-3.3.2.tgz} peerDependencies: react: '*' react-native: '*' @@ -3584,13 +3584,13 @@ packages: react-native: '*' react-native-webview@13.15.0: - resolution: {integrity: sha512-Vzjgy8mmxa/JO6l5KZrsTC7YemSdq+qB01diA0FqjUTaWGAGwuykpJ73MDj3+mzBSlaDxAEugHzTtkUQkQEQeQ==, tarball: https://fbinfra555artifactory.jfrog.io/artifactory/api/npm/fireblocks-npm/react-native-webview/-/react-native-webview-13.15.0.tgz} + resolution: {integrity: sha512-Vzjgy8mmxa/JO6l5KZrsTC7YemSdq+qB01diA0FqjUTaWGAGwuykpJ73MDj3+mzBSlaDxAEugHzTtkUQkQEQeQ==, tarball: https://registry.npmjs.org/react-native-webview/-/react-native-webview-13.15.0.tgz} peerDependencies: react: '*' react-native: '*' react-native@0.81.4: - resolution: {integrity: sha512-bt5bz3A/+Cv46KcjV0VQa+fo7MKxs17RCcpzjftINlen4ZDUl0I6Ut+brQ2FToa5oD0IB0xvQHfmsg2EDqsZdQ==, tarball: https://fbinfra555artifactory.jfrog.io/artifactory/api/npm/fireblocks-npm/react-native/-/react-native-0.81.4.tgz} + resolution: {integrity: sha512-bt5bz3A/+Cv46KcjV0VQa+fo7MKxs17RCcpzjftINlen4ZDUl0I6Ut+brQ2FToa5oD0IB0xvQHfmsg2EDqsZdQ==, tarball: https://registry.npmjs.org/react-native/-/react-native-0.81.4.tgz} engines: {node: '>= 20.19.4'} hasBin: true peerDependencies: @@ -3635,7 +3635,7 @@ packages: optional: true react@19.1.0: - resolution: {integrity: sha512-FS+XFBNvn3GTAWq26joslQgWNoFu08F4kl0J4CgdNKADkdSGXQyTCnKteIAJy96Br6YbpEU1LSzV5dYtjMkMDg==, tarball: https://fbinfra555artifactory.jfrog.io/artifactory/api/npm/fireblocks-npm/react/-/react-19.1.0.tgz} + resolution: {integrity: sha512-FS+XFBNvn3GTAWq26joslQgWNoFu08F4kl0J4CgdNKADkdSGXQyTCnKteIAJy96Br6YbpEU1LSzV5dYtjMkMDg==, tarball: https://registry.npmjs.org/react/-/react-19.1.0.tgz} engines: {node: '>=0.10.0'} reflect-metadata@0.2.2: @@ -3723,7 +3723,7 @@ packages: engines: {node: '>=11.0.0'} scheduler@0.26.0: - resolution: {integrity: sha512-NlHwttCI/l5gCPR3D1nNXtWABUmBwvZpEQiD4IXSbIDq8BzLIK/7Ir5gTFSGZDUu37K5cMNp0hFtzO38sC7gWA==, tarball: https://fbinfra555artifactory.jfrog.io/artifactory/api/npm/fireblocks-npm/scheduler/-/scheduler-0.26.0.tgz} + resolution: {integrity: sha512-NlHwttCI/l5gCPR3D1nNXtWABUmBwvZpEQiD4IXSbIDq8BzLIK/7Ir5gTFSGZDUu37K5cMNp0hFtzO38sC7gWA==, tarball: https://registry.npmjs.org/scheduler/-/scheduler-0.26.0.tgz} scheduler@0.27.0: resolution: {integrity: sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q==} @@ -3775,7 +3775,7 @@ packages: resolution: {integrity: sha512-y0m1JoUZSlPAjXVtPPW70aZWfIL/dSP7AFkRnniLCrK/8MDKog3TySTBmckD+RObVxH0v4Tox67+F14PdED2oQ==} sharp@0.33.5: - resolution: {integrity: sha512-haPVm1EkS9pgvHrQ/F3Xy+hgcuMV0Wm9vfIBSiwZ05k+xgb0PkBQpGsAA/oWdDobNaZTH5ppvHtzCFbnSEwHVw==, tarball: https://fbinfra555artifactory.jfrog.io/artifactory/api/npm/fireblocks-npm/sharp/-/sharp-0.33.5.tgz} + resolution: {integrity: sha512-haPVm1EkS9pgvHrQ/F3Xy+hgcuMV0Wm9vfIBSiwZ05k+xgb0PkBQpGsAA/oWdDobNaZTH5ppvHtzCFbnSEwHVw==, tarball: https://registry.npmjs.org/sharp/-/sharp-0.33.5.tgz} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} shebang-command@2.0.0: @@ -3955,18 +3955,18 @@ packages: resolution: {integrity: sha512-Je6p7pkk+KMzMv2XXKmAE3McmolOQFdxkKw0R8EYNr7sELW46JqnNeTX8ybPiQgvg1ymCoF8LXs5fzFaZvJPTA==} tldts@6.0.16: - resolution: {integrity: sha512-TkEq38COU640mzOKPk4D1oH3FFVvwEtMaKIfw/+F/umVsy7ONWu8PPQH0c11qJ/Jq/zbcQGprXGsT8GcaDSmJg==, tarball: https://fbinfra555artifactory.jfrog.io/artifactory/api/npm/fireblocks-npm/tldts/-/tldts-6.0.16.tgz} + resolution: {integrity: sha512-TkEq38COU640mzOKPk4D1oH3FFVvwEtMaKIfw/+F/umVsy7ONWu8PPQH0c11qJ/Jq/zbcQGprXGsT8GcaDSmJg==, tarball: https://registry.npmjs.org/tldts/-/tldts-6.0.16.tgz} hasBin: true tmpl@1.0.5: - resolution: {integrity: sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==, tarball: https://fbinfra555artifactory.jfrog.io/artifactory/api/npm/fireblocks-npm/tmpl/-/tmpl-1.0.5.tgz} + resolution: {integrity: sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==, tarball: https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz} to-regex-range@5.0.1: resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} engines: {node: '>=8.0'} to-utf8@0.0.1: - resolution: {integrity: sha512-zks18/TWT1iHO3v0vFp5qLKOG27m67ycq/Y7a7cTiRuUNlc4gf3HGnkRgMv0NyhnfTamtkYBJl+YeD1/j07gBQ==, tarball: https://fbinfra555artifactory.jfrog.io/artifactory/api/npm/fireblocks-npm/to-utf8/-/to-utf8-0.0.1.tgz} + resolution: {integrity: sha512-zks18/TWT1iHO3v0vFp5qLKOG27m67ycq/Y7a7cTiRuUNlc4gf3HGnkRgMv0NyhnfTamtkYBJl+YeD1/j07gBQ==, tarball: https://registry.npmjs.org/to-utf8/-/to-utf8-0.0.1.tgz} toidentifier@1.0.1: resolution: {integrity: sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==} @@ -3979,7 +3979,7 @@ packages: resolution: {integrity: sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==} tsl-apple-cloudkit@0.2.34: - resolution: {integrity: sha512-A49Oflo4/Edb9GUN9hzjm7akpY3S+uivrPUxgvp6LPN+PGQsnruiCadSED029Wnh7HVZDU/I7dqWtG9VkPAbVA==, tarball: https://fbinfra555artifactory.jfrog.io/artifactory/api/npm/fireblocks-npm/tsl-apple-cloudkit/-/tsl-apple-cloudkit-0.2.34.tgz} + resolution: {integrity: sha512-A49Oflo4/Edb9GUN9hzjm7akpY3S+uivrPUxgvp6LPN+PGQsnruiCadSED029Wnh7HVZDU/I7dqWtG9VkPAbVA==, tarball: https://registry.npmjs.org/tsl-apple-cloudkit/-/tsl-apple-cloudkit-0.2.34.tgz} engines: {node: '>=16.0.0'} peerDependencies: typescript: '>=3.0.0' @@ -3995,7 +3995,7 @@ packages: engines: {node: '>= 6.0.0'} type-detect@4.0.8: - resolution: {integrity: sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==, tarball: https://fbinfra555artifactory.jfrog.io/artifactory/api/npm/fireblocks-npm/type-detect/-/type-detect-4.0.8.tgz} + resolution: {integrity: sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==, tarball: https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz} engines: {node: '>=4'} type-fest@0.21.3: @@ -4049,7 +4049,7 @@ packages: browserslist: '>= 4.21.0' url@0.11.0: - resolution: {integrity: sha512-kbailJa29QrtXnxgq+DdCEGlbTeYM2eJUxsz6vjZavrCYPMIFHMKQmSKYAIuUK2i7hgPm28a8piX5NTUtM/LKQ==, tarball: https://fbinfra555artifactory.jfrog.io/artifactory/api/npm/fireblocks-npm/url/-/url-0.11.0.tgz} + resolution: {integrity: sha512-kbailJa29QrtXnxgq+DdCEGlbTeYM2eJUxsz6vjZavrCYPMIFHMKQmSKYAIuUK2i7hgPm28a8piX5NTUtM/LKQ==, tarball: https://registry.npmjs.org/url/-/url-0.11.0.tgz} use-callback-ref@1.3.3: resolution: {integrity: sha512-jQL3lRnocaFtu3V00JToYz/4QkNWswxijDaCVNZRiRTO3HQDLsdu1ZtmIUvV4yPp+rvWm5j0y0TG/S61cuijTg==} @@ -4089,10 +4089,10 @@ packages: resolution: {integrity: sha512-E8VjFIQ/TyQgp+TZfS6l8yp/xWppSAHzidGiRrqe4bK4XP9pTRyKFgGJpO3SN7zdX4DeomTrwaseCHovfpFcqQ==} util@0.12.5: - resolution: {integrity: sha512-kZf/K6hEIrWHI6XqOFUiiMa+79wE/D8Q+NCNAWclkyg3b4d2k7s0QGepNjiABc+aR3N1PAyHL7p6UcLY6LmrnA==, tarball: https://fbinfra555artifactory.jfrog.io/artifactory/api/npm/fireblocks-npm/util/-/util-0.12.5.tgz} + resolution: {integrity: sha512-kZf/K6hEIrWHI6XqOFUiiMa+79wE/D8Q+NCNAWclkyg3b4d2k7s0QGepNjiABc+aR3N1PAyHL7p6UcLY6LmrnA==, tarball: https://registry.npmjs.org/util/-/util-0.12.5.tgz} utils-merge@1.0.1: - resolution: {integrity: sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==, tarball: https://fbinfra555artifactory.jfrog.io/artifactory/api/npm/fireblocks-npm/utils-merge/-/utils-merge-1.0.1.tgz} + resolution: {integrity: sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==, tarball: https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz} engines: {node: '>= 0.4.0'} uuid@11.1.0: @@ -4131,7 +4131,7 @@ packages: resolution: {integrity: sha512-gQpnTgkubC6hQgdIcRdYGDSDc+SaujOdyesZQMv6JlfQee/9Mp0Qhnys6WxDWvQnL5WZdT7o2Ul187aSt0Rq+w==} void-elements@3.1.0: - resolution: {integrity: sha512-Dhxzh5HZuiHQhbvTW9AMetFfBHDMYpo23Uo9btPXgdYP+3T5S+p+jgNy7spra+veYhBP2dCSgxR/i2Y02h5/6w==, tarball: https://fbinfra555artifactory.jfrog.io/artifactory/api/npm/fireblocks-npm/void-elements/-/void-elements-3.1.0.tgz} + resolution: {integrity: sha512-Dhxzh5HZuiHQhbvTW9AMetFfBHDMYpo23Uo9btPXgdYP+3T5S+p+jgNy7spra+veYhBP2dCSgxR/i2Y02h5/6w==, tarball: https://registry.npmjs.org/void-elements/-/void-elements-3.1.0.tgz} engines: {node: '>=0.10.0'} walker@1.0.8: @@ -4154,7 +4154,7 @@ packages: resolution: {integrity: sha512-EqhiFU6daOA8kpjOWTL0olhVOF3i7OrFzSYiGsEMB8GcXS+RrzauAERX65xMeNWVqxA6HXH2m69Z9LaKKdisfg==} whatwg-url-without-unicode@8.0.0-3: - resolution: {integrity: sha512-HoKuzZrUlgpz35YO27XgD28uh/WJH4B0+3ttFqRo//lmq+9T/mIOJ6kqmINI9HpUpz1imRC/nR/lxKpJiv0uig==, tarball: https://fbinfra555artifactory.jfrog.io/artifactory/api/npm/fireblocks-npm/whatwg-url-without-unicode/-/whatwg-url-without-unicode-8.0.0-3.tgz} + resolution: {integrity: sha512-HoKuzZrUlgpz35YO27XgD28uh/WJH4B0+3ttFqRo//lmq+9T/mIOJ6kqmINI9HpUpz1imRC/nR/lxKpJiv0uig==, tarball: https://registry.npmjs.org/whatwg-url-without-unicode/-/whatwg-url-without-unicode-8.0.0-3.tgz} engines: {node: '>=10'} whatwg-url@5.0.0: @@ -4223,7 +4223,7 @@ packages: engines: {node: '>=10.0.0'} xml2js@0.6.0: - resolution: {integrity: sha512-eLTh0kA8uHceqesPqSE+VvO1CDDJWMwlQfB6LuN6T8w6MaDJ8Txm8P7s5cHD0miF0V+GGTZrDQfxPZQVsur33w==, tarball: https://fbinfra555artifactory.jfrog.io/artifactory/api/npm/fireblocks-npm/xml2js/-/xml2js-0.6.0.tgz} + resolution: {integrity: sha512-eLTh0kA8uHceqesPqSE+VvO1CDDJWMwlQfB6LuN6T8w6MaDJ8Txm8P7s5cHD0miF0V+GGTZrDQfxPZQVsur33w==, tarball: https://registry.npmjs.org/xml2js/-/xml2js-0.6.0.tgz} engines: {node: '>=4.0.0'} xmlbuilder@11.0.1: @@ -4263,7 +4263,7 @@ packages: engines: {node: '>=10'} zod@4.0.5: - resolution: {integrity: sha512-/5UuuRPStvHXu7RS+gmvRf4NXrNxpSllGwDnCBcJZtQsKrviYXm54yDGV2KYNLT5kq0lHGcl7lqWJLgSaG+tgA==, tarball: https://fbinfra555artifactory.jfrog.io/artifactory/api/npm/fireblocks-npm/zod/-/zod-4.0.5.tgz} + resolution: {integrity: sha512-/5UuuRPStvHXu7RS+gmvRf4NXrNxpSllGwDnCBcJZtQsKrviYXm54yDGV2KYNLT5kq0lHGcl7lqWJLgSaG+tgA==, tarball: https://registry.npmjs.org/zod/-/zod-4.0.5.tgz} snapshots: