diff --git a/wallets/rn_cli_wallet/android/app/build.gradle b/wallets/rn_cli_wallet/android/app/build.gradle index 48018df5..394e2298 100644 --- a/wallets/rn_cli_wallet/android/app/build.gradle +++ b/wallets/rn_cli_wallet/android/app/build.gradle @@ -89,7 +89,7 @@ android { applicationId "com.walletconnect.web3wallet.rnsample" minSdkVersion rootProject.ext.minSdkVersion targetSdkVersion rootProject.ext.targetSdkVersion - versionCode 54 + versionCode 55 versionName "1.0" resValue "string", "build_config_package", "com.walletconnect.web3wallet.rnsample" } diff --git a/wallets/rn_cli_wallet/index.js b/wallets/rn_cli_wallet/index.js index 9490b44c..f40149c3 100644 --- a/wallets/rn_cli_wallet/index.js +++ b/wallets/rn_cli_wallet/index.js @@ -1,6 +1,6 @@ import 'react-native-gesture-handler'; -import '@walletconnect/react-native-compat'; import {AppRegistry} from 'react-native'; +import '@walletconnect/react-native-compat'; import {name as appName} from './app.json'; import crypto from 'react-native-quick-crypto'; diff --git a/wallets/rn_cli_wallet/ios/Podfile.lock b/wallets/rn_cli_wallet/ios/Podfile.lock index 796b4544..132e9664 100644 --- a/wallets/rn_cli_wallet/ios/Podfile.lock +++ b/wallets/rn_cli_wallet/ios/Podfile.lock @@ -1,5 +1,7 @@ PODS: - boost (1.83.0) + - BVLinearGradient (2.8.3): + - React-Core - DoubleConversion (1.1.6) - FBLazyVector (0.74.3) - fmt (9.1.0) @@ -938,7 +940,7 @@ PODS: - React-Mapbuffer (0.74.3): - glog - React-debug - - react-native-compat (2.17.2): + - react-native-compat (2.18.1-canary-ca-5): - DoubleConversion - glog - hermes-engine @@ -959,6 +961,7 @@ PODS: - ReactCommon/turbomodule/bridging - ReactCommon/turbomodule/core - Yoga + - YttriumWrapper (= 0.8.35) - react-native-config (1.5.2): - react-native-config/App (= 1.5.2) - react-native-config/App (1.5.2): @@ -1246,7 +1249,7 @@ PODS: - React-Core - RNCAsyncStorage (1.24.0): - React-Core - - RNCClipboard (1.14.1): + - RNCClipboard (1.15.0): - React-Core - RNDeviceInfo (11.1.0): - React-Core @@ -1329,9 +1332,11 @@ PODS: - VisionCamera/React (4.5.0): - React-Core - Yoga (0.0.0) + - YttriumWrapper (0.8.35) 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`) - FBLazyVector (from `../node_modules/react-native/Libraries/FBLazyVector`) - fmt (from `../node_modules/react-native/third-party-podspecs/fmt.podspec`) @@ -1411,10 +1416,13 @@ SPEC REPOS: - OpenSSL-Universal - Sentry - SocketRocket + - YttriumWrapper 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" FBLazyVector: @@ -1561,6 +1569,7 @@ EXTERNAL SOURCES: SPEC CHECKSUMS: boost: d3f49c53809116a5d38da093a8aa78bf551aed09 + BVLinearGradient: 880f91a7854faff2df62518f0281afb1c60d49a3 DoubleConversion: 76ab83afb40bddeeee456813d9c04f67f78771b5 FBLazyVector: 7e977dd099937dc5458851233141583abba49ff2 fmt: 4c2741a687cc09f0634a2e2c72a838b99f1ff120 @@ -1592,7 +1601,7 @@ SPEC CHECKSUMS: React-jsitracing: 6b3c8c98313642140530f93c46f5a6ca4530b446 React-logger: fa92ba4d3a5d39ac450f59be2a3cec7b099f0304 React-Mapbuffer: 9f68550e7c6839d01411ac8896aea5c868eff63a - react-native-compat: 425ce849bdeb6dceeb1c003b254c3c2623a37ba1 + react-native-compat: 824fba7586ebff78f51477f6d0a30c261872b020 react-native-config: d7d8a0c65f7fa523197879f6b777997abbfc987e react-native-get-random-values: 21325b2244dfa6b58878f51f9aa42821e7ba3d06 react-native-netinfo: 076df4f9b07f6670acf4ce9a75aac8d34c2e2ccc @@ -1624,7 +1633,7 @@ SPEC CHECKSUMS: ReactCommon: f00e436b3925a7ae44dfa294b43ef360fbd8ccc4 RNBootSplash: e025d4ee98d942ee6c8b495a6fe66339a6b5f6dd RNCAsyncStorage: ec53e44dc3e75b44aa2a9f37618a49c3bc080a7a - RNCClipboard: 0a720adef5ec193aa0e3de24c3977222c7e52a37 + RNCClipboard: 69ab8e51324d5b351f6ba72bbdb72478087a2c64 RNDeviceInfo: b899ce37a403a4dea52b7cb85e16e49c04a5b88e RNGestureHandler: 8dbcccada4a7e702e7dec9338c251b1cf393c960 RNPermissions: 9fa74223844f437bc309e112994859dc47194829 @@ -1634,8 +1643,9 @@ SPEC CHECKSUMS: Sentry: 54d0fe6c0df448497c8ed4cce66ccf7027e1823e SocketRocket: abac6f5de4d4d62d24e11868d7a2f427e0ef940d VisionCamera: 412fec057156eb5fe84a44351e8ed71a072c1228 - Yoga: 04f1db30bb810187397fa4c37dd1868a27af229c + Yoga: 88480008ccacea6301ff7bf58726e27a72931c8d + YttriumWrapper: 31e937fe9fbe0f1314d2ca6be9ce9b379a059966 PODFILE CHECKSUM: c71b4a1de1dcccdf71d8f7f0d4d9b3c37106456c -COCOAPODS: 1.14.3 +COCOAPODS: 1.16.2 diff --git a/wallets/rn_cli_wallet/ios/RNWeb3Wallet.xcodeproj/project.pbxproj b/wallets/rn_cli_wallet/ios/RNWeb3Wallet.xcodeproj/project.pbxproj index b0c32c2f..9e2c6e95 100644 --- a/wallets/rn_cli_wallet/ios/RNWeb3Wallet.xcodeproj/project.pbxproj +++ b/wallets/rn_cli_wallet/ios/RNWeb3Wallet.xcodeproj/project.pbxproj @@ -827,7 +827,7 @@ "$(inherited)", ); INFOPLIST_FILE = RNWeb3WalletTests/Info.plist; - IPHONEOS_DEPLOYMENT_TARGET = 12.4; + IPHONEOS_DEPLOYMENT_TARGET = 15.6; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", @@ -853,7 +853,7 @@ BUNDLE_LOADER = "$(TEST_HOST)"; COPY_PHASE_STRIP = NO; INFOPLIST_FILE = RNWeb3WalletTests/Info.plist; - IPHONEOS_DEPLOYMENT_TARGET = 12.4; + IPHONEOS_DEPLOYMENT_TARGET = 15.6; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", @@ -937,6 +937,7 @@ ); INFOPLIST_FILE = RNWeb3Wallet/Info.plist; INFOPLIST_KEY_CFBundleDisplayName = "RN Wallet"; + IPHONEOS_DEPLOYMENT_TARGET = 15.6; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", @@ -1026,6 +1027,7 @@ ); INFOPLIST_FILE = RNWeb3Wallet/Info.plist; INFOPLIST_KEY_CFBundleDisplayName = "RN Wallet"; + IPHONEOS_DEPLOYMENT_TARGET = 15.6; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", @@ -1116,6 +1118,7 @@ ); INFOPLIST_FILE = "RNWeb3Wallet/Debug-Info.plist"; INFOPLIST_KEY_CFBundleDisplayName = "RN Wallet"; + IPHONEOS_DEPLOYMENT_TARGET = 15.6; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", @@ -1204,6 +1207,7 @@ ); INFOPLIST_FILE = "RNWeb3Wallet/Debug-Info.plist"; INFOPLIST_KEY_CFBundleDisplayName = "RN Wallet"; + IPHONEOS_DEPLOYMENT_TARGET = 15.6; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", @@ -1295,6 +1299,7 @@ ); INFOPLIST_FILE = "RNWeb3Wallet/Internal-Info.plist"; INFOPLIST_KEY_CFBundleDisplayName = "RN Wallet"; + IPHONEOS_DEPLOYMENT_TARGET = 15.6; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", @@ -1386,6 +1391,7 @@ ); INFOPLIST_FILE = "RNWeb3Wallet/Internal-Info.plist"; INFOPLIST_KEY_CFBundleDisplayName = "RN Wallet"; + IPHONEOS_DEPLOYMENT_TARGET = 15.6; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", @@ -1473,7 +1479,7 @@ "${PODS_CONFIGURATION_BUILD_DIR}/React-graphics/React_graphics.framework/Headers", "${PODS_CONFIGURATION_BUILD_DIR}/React-graphics/React_graphics.framework/Headers/react/renderer/graphics/platform/ios", ); - IPHONEOS_DEPLOYMENT_TARGET = 12.4; + IPHONEOS_DEPLOYMENT_TARGET = 16.6; LD = ""; LDPLUSPLUS = ""; LD_RUNPATH_SEARCH_PATHS = ( @@ -1557,7 +1563,7 @@ "${PODS_CONFIGURATION_BUILD_DIR}/React-graphics/React_graphics.framework/Headers", "${PODS_CONFIGURATION_BUILD_DIR}/React-graphics/React_graphics.framework/Headers/react/renderer/graphics/platform/ios", ); - IPHONEOS_DEPLOYMENT_TARGET = 12.4; + IPHONEOS_DEPLOYMENT_TARGET = 16.6; LD = ""; LDPLUSPLUS = ""; LD_RUNPATH_SEARCH_PATHS = ( diff --git a/wallets/rn_cli_wallet/package.json b/wallets/rn_cli_wallet/package.json index a6bc5bae..0d749c85 100644 --- a/wallets/rn_cli_wallet/package.json +++ b/wallets/rn_cli_wallet/package.json @@ -25,7 +25,7 @@ "@json-rpc-tools/utils": "1.7.6", "@kangfenmao/react-native-minimizer": "1.0.4", "@react-native-async-storage/async-storage": "1.24.0", - "@react-native-clipboard/clipboard": "1.14.1", + "@react-native-clipboard/clipboard": "1.15.0", "@react-native-community/netinfo": "11.3.2", "@react-navigation/bottom-tabs": "6.5.1", "@react-navigation/elements": "1.3.31", @@ -33,9 +33,9 @@ "@react-navigation/native-stack": "6.10.1", "@react-navigation/stack": "6.4.1", "@reown/appkit-ui-react-native": "1.0.1", - "@reown/walletkit": "1.1.1", + "@reown/walletkit": "1.1.2-canary-ca-6", "@sentry/react-native": "6.4.0", - "@walletconnect/react-native-compat": "2.17.2", + "@walletconnect/react-native-compat": "2.18.1-canary-ca-5", "dayjs": "1.11.11", "ethers": "5.7.2", "fast-xml-parser": "4.4.1", @@ -49,6 +49,7 @@ "react-native-dialog": "9.3.0", "react-native-gesture-handler": "2.17.1", "react-native-get-random-values": "1.11.0", + "react-native-linear-gradient": "^2.8.3", "react-native-modal": "13.0.1", "react-native-permissions": "4.1.5", "react-native-quick-base64": "2.1.2", diff --git a/wallets/rn_cli_wallet/src/assets/bridge.png b/wallets/rn_cli_wallet/src/assets/bridge.png new file mode 100644 index 00000000..218ea79b Binary files /dev/null and b/wallets/rn_cli_wallet/src/assets/bridge.png differ diff --git a/wallets/rn_cli_wallet/src/components/BridgeBadge.tsx b/wallets/rn_cli_wallet/src/components/BridgeBadge.tsx new file mode 100644 index 00000000..ed477947 --- /dev/null +++ b/wallets/rn_cli_wallet/src/components/BridgeBadge.tsx @@ -0,0 +1,27 @@ +import {Image, StyleSheet, View} from 'react-native'; +import Bridge from '@/assets/bridge.png'; + +export function BridgeBadge() { + return ( + + + + ); +} + +const styles = StyleSheet.create({ + container: { + width: 24, + height: 24, + borderRadius: 12, + backgroundColor: '#363636', + marginEnd: 8, + flexDirection: 'row', + justifyContent: 'space-evenly', + }, + image: { + width: 16, + height: 16, + top: 3, + }, +}); diff --git a/wallets/rn_cli_wallet/src/components/Loader.tsx b/wallets/rn_cli_wallet/src/components/Loader.tsx new file mode 100644 index 00000000..76fdd11c --- /dev/null +++ b/wallets/rn_cli_wallet/src/components/Loader.tsx @@ -0,0 +1,5 @@ +import {ActivityIndicator} from 'react-native'; + +export function Loader({loading}: {loading: boolean}) { + return loading ? : null; +} diff --git a/wallets/rn_cli_wallet/src/components/VerifiedDomain.tsx b/wallets/rn_cli_wallet/src/components/VerifiedDomain.tsx new file mode 100644 index 00000000..fbe04711 --- /dev/null +++ b/wallets/rn_cli_wallet/src/components/VerifiedDomain.tsx @@ -0,0 +1,15 @@ +import {Image, StyleSheet} from 'react-native'; +import VerifiedIcon from '@/assets/VerifiedDomain.png'; + +export function VerifiedDomain() { + return ; +} + +const styles = StyleSheet.create({ + icon: { + width: 10, + height: 10, + borderRadius: 5, + marginEnd: 5, + }, +}); diff --git a/wallets/rn_cli_wallet/src/hooks/useInitializeWalletKit.ts b/wallets/rn_cli_wallet/src/hooks/useInitializeWalletKit.ts index f9a25cc2..1f177542 100644 --- a/wallets/rn_cli_wallet/src/hooks/useInitializeWalletKit.ts +++ b/wallets/rn_cli_wallet/src/hooks/useInitializeWalletKit.ts @@ -1,6 +1,5 @@ import {useCallback, useEffect, useRef, useState} from 'react'; import {useSnapshot} from 'valtio'; - import SettingsStore from '@/store/SettingsStore'; import {createOrRestoreEIP155Wallet} from '@/utils/EIP155WalletUtil'; import {createWalletKit, walletKit} from '@/utils/WalletKitUtil'; @@ -29,7 +28,7 @@ export default function useInitializeWalletKit() { // restart transport if relayer region changes const onRelayerRegionChange = useCallback(() => { try { - walletKit.core.relayer.restartTransport(relayerRegionURL); + walletKit?.core.relayer.restartTransport(relayerRegionURL); prevRelayerURLValue.current = relayerRegionURL; } catch (err: unknown) { console.log(err); diff --git a/wallets/rn_cli_wallet/src/hooks/useWalletKitEventsManager.ts b/wallets/rn_cli_wallet/src/hooks/useWalletKitEventsManager.ts index 08b65aad..adceb927 100644 --- a/wallets/rn_cli_wallet/src/hooks/useWalletKitEventsManager.ts +++ b/wallets/rn_cli_wallet/src/hooks/useWalletKitEventsManager.ts @@ -14,7 +14,7 @@ export default function useWalletKitEventsManager(initialized: boolean) { *****************************************************************************/ const onSessionProposal = useCallback( (proposal: SignClientTypes.EventArguments['session_proposal']) => { - console.log('onSessionProposal', proposal); + console.log('onSessionProposal', JSON.stringify(proposal, null, 2)); // set the verify context so it can be displayed in the projectInfoCard SettingsStore.setCurrentRequestVerifyContext(proposal.verifyContext); @@ -41,7 +41,9 @@ export default function useWalletKitEventsManager(initialized: boolean) { console.log('onSessionRequest', requestEvent); const {topic, params, verifyContext} = requestEvent; const {request} = params; + console.log('request', JSON.stringify(requestEvent, null, 2)); const requestSession = walletKit.engine.signClient.session.get(topic); + console.log('requestSession', JSON.stringify(requestSession, null, 2)); // set the verify context so it can be displayed in the projectInfoCard SettingsStore.setCurrentRequestVerifyContext(verifyContext); @@ -97,7 +99,175 @@ export default function useWalletKitEventsManager(initialized: boolean) { * Set up WalletKit event listeners *****************************************************************************/ useEffect(() => { - if (initialized) { + if (initialized && walletKit) { + // ModalStore.open('SessionSendTransactionModal', { + // requestEvent: { + // id: 1734448264642458, + // topic: + // '0a9e4131a9b8cb1b72a33bc55a659c6f5ddca006972e34bd062da6e2558fb4a9', + // params: { + // request: { + // method: 'eth_sendTransaction', + // params: [ + // { + // data: '0xa9059cbb00000000000000000000000013a2ff792037aa2cd77fe1f4b522921ac59a9c5200000000000000000000000000000000000000000000000000000000004c4b40', + // from: '0x13A2Ff792037AA2cd77fE1f4B522921ac59a9C52', + // to: '0x0b2c639c533813f4aa9d7837caf62653d097ff85', + // }, + // ], + // expiryTimestamp: 1734448564, + // }, + // chainId: 'eip155:10', + // }, + // verifyContext: { + // verified: { + // verifyUrl: 'https://verify.walletconnect.org', + // validation: 'VALID', + // origin: 'https://appkit-lab.reown.com', + // isScam: null, + // }, + // }, + // }, + // requestSession: { + // relay: { + // protocol: 'irn', + // }, + // namespaces: { + // eip155: { + // chains: [ + // 'eip155:1', + // 'eip155:10', + // 'eip155:137', + // 'eip155:324', + // 'eip155:42161', + // 'eip155:8453', + // 'eip155:100', + // 'eip155:1313161554', + // ], + // methods: [ + // 'personal_sign', + // 'eth_sign', + // 'eth_signTransaction', + // 'eth_signTypedData', + // 'eth_signTypedData_v3', + // 'eth_signTypedData_v4', + // 'eth_sendRawTransaction', + // 'eth_sendTransaction', + // ], + // events: ['accountsChanged', 'chainChanged'], + // accounts: [ + // 'eip155:1:0x13A2Ff792037AA2cd77fE1f4B522921ac59a9C52', + // 'eip155:10:0x13A2Ff792037AA2cd77fE1f4B522921ac59a9C52', + // 'eip155:137:0x13A2Ff792037AA2cd77fE1f4B522921ac59a9C52', + // 'eip155:324:0x13A2Ff792037AA2cd77fE1f4B522921ac59a9C52', + // 'eip155:42161:0x13A2Ff792037AA2cd77fE1f4B522921ac59a9C52', + // 'eip155:8453:0x13A2Ff792037AA2cd77fE1f4B522921ac59a9C52', + // 'eip155:100:0x13A2Ff792037AA2cd77fE1f4B522921ac59a9C52', + // 'eip155:1313161554:0x13A2Ff792037AA2cd77fE1f4B522921ac59a9C52', + // ], + // }, + // }, + // controller: + // 'ea8f2172d22ace9801b2178a9f55b0053c9ac63d1f5a7d2bc4b79ec84d91244a', + // expiry: 1734080914, + // topic: + // 'f013d8008bf88c77d78f64548f4103d6ec677254f8a9ba89366d5368a79334b0', + // requiredNamespaces: {}, + // optionalNamespaces: { + // eip155: { + // methods: [ + // 'personal_sign', + // 'eth_sign', + // 'eth_signTransaction', + // 'eth_signTypedData', + // 'eth_signTypedData_v3', + // 'eth_signTypedData_v4', + // 'eth_sendRawTransaction', + // 'eth_sendTransaction', + // 'wallet_getCapabilities', + // 'wallet_sendCalls', + // 'wallet_showCallsStatus', + // 'wallet_getCallsStatus', + // 'wallet_grantPermissions', + // 'wallet_revokePermissions', + // 'wallet_switchEthereumChain', + // ], + // events: ['accountsChanged', 'chainChanged'], + // chains: [ + // 'eip155:1', + // 'eip155:10', + // 'eip155:137', + // 'eip155:324', + // 'eip155:42161', + // 'eip155:8453', + // 'eip155:84532', + // 'eip155:1301', + // 'eip155:11155111', + // 'eip155:100', + // 'eip155:295', + // 'eip155:1313161554', + // 'eip155:5000', + // ], + // rpcMap: { + // '1': 'https://rpc.walletconnect.org/v1/?chainId=eip155%3A1&projectId=702e2d45d9debca66795614cddb5c1ca', + // '10': 'https://rpc.walletconnect.org/v1/?chainId=eip155%3A10&projectId=702e2d45d9debca66795614cddb5c1ca', + // '100': + // 'https://rpc.walletconnect.org/v1/?chainId=eip155%3A100&projectId=702e2d45d9debca66795614cddb5c1ca', + // '137': + // 'https://rpc.walletconnect.org/v1/?chainId=eip155%3A137&projectId=702e2d45d9debca66795614cddb5c1ca', + // '295': 'https://mainnet.hashio.io/api', + // '324': + // 'https://rpc.walletconnect.org/v1/?chainId=eip155%3A324&projectId=702e2d45d9debca66795614cddb5c1ca', + // '1301': + // 'https://rpc.walletconnect.org/v1/?chainId=eip155%3A1301&projectId=702e2d45d9debca66795614cddb5c1ca', + // '5000': + // 'https://rpc.walletconnect.org/v1/?chainId=eip155%3A5000&projectId=702e2d45d9debca66795614cddb5c1ca', + // '8453': + // 'https://rpc.walletconnect.org/v1/?chainId=eip155%3A8453&projectId=702e2d45d9debca66795614cddb5c1ca', + // '42161': + // 'https://rpc.walletconnect.org/v1/?chainId=eip155%3A42161&projectId=702e2d45d9debca66795614cddb5c1ca', + // '84532': + // 'https://rpc.walletconnect.org/v1/?chainId=eip155%3A84532&projectId=702e2d45d9debca66795614cddb5c1ca', + // '11155111': + // 'https://rpc.walletconnect.org/v1/?chainId=eip155%3A11155111&projectId=702e2d45d9debca66795614cddb5c1ca', + // '1313161554': + // 'https://rpc.walletconnect.org/v1/?chainId=eip155%3A1313161554&projectId=702e2d45d9debca66795614cddb5c1ca', + // }, + // }, + // }, + // pairingTopic: + // 'c0d67be3a41ded5ffa144e8ed6281a057e1e8e9f23003a427c1a70d04a5939f6', + // acknowledged: true, + // self: { + // publicKey: + // 'ea8f2172d22ace9801b2178a9f55b0053c9ac63d1f5a7d2bc4b79ec84d91244a', + // metadata: { + // name: 'React Native Wallet Example', + // description: 'React Native WalletKit by Reown', + // url: 'https://reown.com/walletkit', + // icons: ['https://avatars.githubusercontent.com/u/179229932'], + // redirect: { + // native: 'rn-web3wallet://', + // universal: 'https://appkit-lab.reown.com/rn_walletkit', + // linkMode: true, + // }, + // }, + // }, + // peer: { + // publicKey: + // '9dc9524bd9f09fb0e387729354099c686086757701e417815f73a168c4f31565', + // metadata: { + // name: 'AppKit Lab', + // description: + // 'Explore the AppKit Lab to test the latest AppKit features.', + // url: 'https://appkit-lab.reown.com', + // icons: ['https://appkit-lab.reown.com/favicon.svg'], + // }, + // }, + // transportType: 'relay', + // }, + // }); + //sign walletKit.on('session_proposal', onSessionProposal); walletKit.on('session_request', onSessionRequest); diff --git a/wallets/rn_cli_wallet/src/lib/EIP155Lib.ts b/wallets/rn_cli_wallet/src/lib/EIP155Lib.ts index 45b00920..34f28a4d 100644 --- a/wallets/rn_cli_wallet/src/lib/EIP155Lib.ts +++ b/wallets/rn_cli_wallet/src/lib/EIP155Lib.ts @@ -1,10 +1,11 @@ -import {providers, Wallet} from 'ethers'; +import {ethers, providers, Wallet} from 'ethers'; /** * Types */ interface IInitArgs { mnemonic?: string; + privateKey?: string; } /** @@ -17,16 +18,21 @@ export default class EIP155Lib { this.wallet = wallet; } - static init({mnemonic}: IInitArgs) { - const wallet = mnemonic - ? Wallet.fromMnemonic(mnemonic) - : Wallet.createRandom(); + static init({mnemonic, privateKey}: IInitArgs) { + let wallet; + if (privateKey) { + wallet = new Wallet(privateKey); + } else if (mnemonic) { + wallet = Wallet.fromMnemonic(mnemonic); + } else { + wallet = Wallet.createRandom(); + } return new EIP155Lib(wallet); } getMnemonic() { - return this.wallet.mnemonic.phrase; + return this.wallet.mnemonic?.phrase || this.wallet.privateKey; } getAddress() { @@ -48,4 +54,9 @@ export default class EIP155Lib { signTransaction(transaction: providers.TransactionRequest) { return this.wallet.signTransaction(transaction); } + + signAny(data: any) { + const signature = this.wallet._signingKey().signDigest(data); + return ethers.utils.joinSignature(signature); + } } diff --git a/wallets/rn_cli_wallet/src/modals/RequestModalV2/ModalFooter.tsx b/wallets/rn_cli_wallet/src/modals/RequestModalV2/ModalFooter.tsx new file mode 100644 index 00000000..57bfd1b7 --- /dev/null +++ b/wallets/rn_cli_wallet/src/modals/RequestModalV2/ModalFooter.tsx @@ -0,0 +1,87 @@ +import {View, StyleSheet} from 'react-native'; +import {Verify} from '@walletconnect/types'; + +import {ActionButton} from '@/components/ActionButton'; +import VerifyInfoBox from '@/components/VerifyInfoBox'; +import {useTheme} from '@/hooks/useTheme'; + +export interface ModalFooterProps { + onApprove: () => void; + onReject: () => void; + approveLoader?: boolean; + rejectLoader?: boolean; + verifyContext?: Verify.Context; + disableApprove?: boolean; +} + +export function ModalFooter({ + onApprove, + onReject, + approveLoader, + rejectLoader, + verifyContext, + disableApprove, +}: ModalFooterProps) { + const Theme = useTheme(); + const validation = verifyContext?.verified.validation; + const isScam = verifyContext?.verified.isScam; + + const bgColor = + isScam || validation === 'INVALID' + ? Theme['verify-invalid'] + : validation === 'VALID' + ? Theme['accent-100'] + : Theme['verify-unknown']; + + return ( + + + + + Reject + + + Approve + + + + ); +} + +const styles = StyleSheet.create({ + container: { + alignItems: 'center', + marginHorizontal: 16, + paddingBottom: 32, + }, + buttonContainer: { + marginTop: 16, + flexDirection: 'row', + justifyContent: 'space-between', + width: '100%', + }, + button: { + width: '48%', + height: 48, + borderRadius: 100, + }, + rejectText: { + fontWeight: '500', + fontSize: 16, + }, + approveText: { + fontWeight: '600', + fontSize: 16, + }, +}); diff --git a/wallets/rn_cli_wallet/src/modals/RequestModalV2/ModalHeader.tsx b/wallets/rn_cli_wallet/src/modals/RequestModalV2/ModalHeader.tsx new file mode 100644 index 00000000..6a7af832 --- /dev/null +++ b/wallets/rn_cli_wallet/src/modals/RequestModalV2/ModalHeader.tsx @@ -0,0 +1,37 @@ +import {StyleSheet, Text, View} from 'react-native'; + +interface ModalHeaderProps { + heading: string; +} + +export function ModalHeader({heading}: ModalHeaderProps) { + return ( + + + {heading} + + + ); +} + +const styles = StyleSheet.create({ + container: { + justifyContent: 'center', + alignItems: 'center', + // marginHorizontal: 16, + padding: 10, + }, + heading: { + borderRadius: 20, + height: 25, + alignItems: 'center', + justifyContent: 'center', + alignSelf: 'center', + marginBottom: 12, + }, + headingText: { + fontSize: 14, + fontWeight: '500', + color: '#ffffff', + }, +}); diff --git a/wallets/rn_cli_wallet/src/modals/RequestModalV2/RequestModalV2.tsx b/wallets/rn_cli_wallet/src/modals/RequestModalV2/RequestModalV2.tsx new file mode 100644 index 00000000..e6b638f2 --- /dev/null +++ b/wallets/rn_cli_wallet/src/modals/RequestModalV2/RequestModalV2.tsx @@ -0,0 +1,217 @@ +import {ReactNode, useMemo} from 'react'; +import {StyleSheet, View} from 'react-native'; +import {LinearGradient} from 'react-native-linear-gradient'; +import {CoreTypes} from '@walletconnect/types'; + +import {ModalHeader} from './ModalHeader'; +import {useSnapshot} from 'valtio'; +import SettingsStore from '@/store/SettingsStore'; +import VerifyInfoBox from '@/components/VerifyInfoBox'; +import {ActionButton} from '@/components/ActionButton'; + +export interface RequestModalProps { + children: ReactNode; + metadata?: CoreTypes.Metadata; + heading: string; + onApprove: () => void; + onReject: () => void; + approveLoader?: boolean; + rejectLoader?: boolean; + intention?: string; + isLinkMode?: boolean; + disableApprove?: boolean; +} + +export function RequestModalV2({ + children, + heading, + onApprove, + onReject, + approveLoader, + rejectLoader, + disableApprove, +}: RequestModalProps) { + const {currentRequestVerifyContext} = useSnapshot(SettingsStore.state); + return ( + + + {children} + + + ); +} + +function ModalFooter({ + onApprove, + onReject, + approveLoader, + rejectLoader, + verifyContext, + disableApprove, +}: any) { + const validation = verifyContext?.verified.validation; + const isScam = verifyContext?.verified.isScam; + + const approveButtonColors = useMemo(() => { + let gradient; + let textColor; + if (disableApprove) { + gradient = ['transparent', 'transparent']; + textColor = '#9A9A9A'; + } else { + gradient = ['#732BCC', '#076CF1']; + textColor = 'white'; + } + return { + gradient, + textColor, + }; + }, [disableApprove]); + + return ( + + + + + Cancel + + + + Approve + + + + + ); +} + +const styles = StyleSheet.create({ + container: { + flexDirection: 'column', // Main container stacks rows vertically + padding: 10, + borderTopLeftRadius: 20, + borderTopRightRadius: 20, + width: 'auto', + backgroundColor: '#2A2A2A', + }, + section: { + width: '100%', + backgroundColor: '#252525', + borderRadius: 20, + display: 'flex', + padding: 5, + marginBottom: 10, + }, + innerSection: { + backgroundColor: '#2A2A2A', + borderRadius: 20, + }, + alignInCenter: { + flexDirection: 'row', + alignItems: 'center', + }, + row: { + flexDirection: 'row', // Each row splits into two columns + justifyContent: 'space-between', + alignItems: 'center', + height: 44, + paddingLeft: 20, + paddingEnd: 20, + }, + chainLogo: { + width: 12, + height: 12, + borderRadius: 6, + }, + column: { + alignItems: 'center', // Center content horizontally in the column + }, + iconColumn: { + flexDirection: 'row', + alignItems: 'center', + }, + textMuted: { + color: '#9A9A9A', + fontSize: 14, + fontWeight: 400, + lineHeight: 16, + textAlign: 'left', + }, + textMid: { + fontSize: 14, + lineHeight: 16, + }, + textSm: { + fontSize: 12, + lineHeight: 14, + }, + textMain: { + color: '#ffffff', + fontWeight: 500, + textAlign: 'right', + }, +}); + +const stylesFooter = StyleSheet.create({ + container: { + alignItems: 'center', + }, + buttonContainer: { + marginBottom: 10, + flexDirection: 'row', + justifyContent: 'space-between', + width: '100%', + }, + declineButton: { + backgroundColor: 'transparent', + }, + appoveButton: { + backgroundColor: 'transparent', + width: '100%', + }, + button: { + width: '48%', + height: 48, + borderRadius: 40, + borderWidth: 1, + borderColor: '#363636', + }, + rejectText: { + fontWeight: '500', + fontSize: 16, + color: '#ffff', + }, + approveText: { + fontWeight: '600', + fontSize: 16, + }, +}); diff --git a/wallets/rn_cli_wallet/src/modals/SessionSendTransactionModal.tsx b/wallets/rn_cli_wallet/src/modals/SessionSendTransactionModal.tsx index eee48450..d264d26c 100644 --- a/wallets/rn_cli_wallet/src/modals/SessionSendTransactionModal.tsx +++ b/wallets/rn_cli_wallet/src/modals/SessionSendTransactionModal.tsx @@ -1,10 +1,8 @@ import {useSnapshot} from 'valtio'; -import {useCallback, useState} from 'react'; -import {View, StyleSheet} from 'react-native'; +import {useCallback, useEffect, useMemo, useState} from 'react'; +import {View, StyleSheet, Image, Text, Alert} from 'react-native'; import {SignClientTypes} from '@walletconnect/types'; -import {Methods} from '@/components/Modal/Methods'; -import {Message} from '@/components/Modal/Message'; import { approveEIP155Request, rejectEIP155Request, @@ -12,14 +10,46 @@ import { import {walletKit} from '@/utils/WalletKitUtil'; import {handleRedirect} from '@/utils/LinkingUtils'; import ModalStore from '@/store/ModalStore'; -import {RequestModal} from '@/modals/RequestModal'; -import {Chains} from '@/components/Modal/Chains'; -import {PresetsUtil} from '@/utils/PresetsUtil'; +import {EIP155_CHAINS, PresetsUtil} from '@/utils/PresetsUtil'; +import {RequestModalV2} from './RequestModalV2/RequestModalV2'; +import {BridgeBadge} from '@/components/BridgeBadge'; +import { + calculateEip155Gas, + getNonce, + getTransferDetails, + wallet1, +} from '@/utils/EIP155WalletUtil'; +import {isVerified} from '@/utils/HelperUtil'; +import {VerifiedDomain} from '@/components/VerifiedDomain'; +import {Loader} from '@/components/Loader'; +import {ethers} from 'ethers'; +import {ChainAbstractionTypes} from '@reown/walletkit'; +import {FeeEstimatedTransaction} from '@reown/walletkit/dist/types/libs/yttrium'; +import {formatJsonRpcResult} from '@json-rpc-tools/utils'; export default function SessionSendTransactionModal() { const {data} = useSnapshot(ModalStore.state); - const [isLoadingApprove, setIsLoadingApprove] = useState(false); - const [isLoadingReject, setIsLoadingReject] = useState(false); + const [payingAmount, setPayingAmount] = useState(''); + const [fundingFrom, setFundingFrom] = useState< + { + symbol: string; + chainId: string; + amount: string; + tokenContract: string; + decimals: number; + }[] + >(); + const [networkFee, setNetworkFee] = useState(''); + const [rejectLoading, setRejectLoading] = useState(false); + const [approveLoading, setApproveLoading] = useState(false); + const [fetchingRoutes, setFetchingRoutes] = useState(false); + const [fetchingGas, setFetchingGas] = useState(false); + const [fetchingTransferAmount, setFetchingTransferAmount] = useState(false); + const [routingStatus, setRoutingStatus] = useState(''); + const [hasError, setHasError] = useState(false); + const [bridgeDetails, setBridgeDetails] = useState< + ChainAbstractionTypes.UiFields | undefined + >(); // Get request and wallet data from store const requestEvent = data?.requestEvent; @@ -27,21 +57,180 @@ export default function SessionSendTransactionModal() { const topic = requestEvent?.topic; const params = requestEvent?.params; - const chainId = params?.chainId; - const chain = PresetsUtil.getChainData(chainId?.split(':')[1] || ''); + const chainId = params?.chainId as string; const request = params?.request; - const transaction = request?.params[0]; - const method = requestEvent?.params?.request?.method!; + console.log('request tx', request?.params[0]); + const [transaction, setTransaction] = useState({ + ...request?.params[0], + input: request?.params[0].input || request?.params[0].data || '0x', + }); const isLinkMode = session?.transportType === 'link_mode'; - const peerMetadata = session?.peer?.metadata as SignClientTypes.Metadata; + const chainData = useMemo(() => { + if (!chainId) { + return; + } + const id = chainId.split(':')[1]; + const chain = PresetsUtil.getChainData(id); + const logoSource = PresetsUtil.getChainLogo(id); + return { + data: chain, + logo: logoSource ? ( + + ) : null, + }; + }, [chainId]); + + useEffect(() => { + const value = transaction.value; + if (value) { + setPayingAmount(`${calculateFundingAmount(value, 18)} ETH`); + return; + } + setFetchingTransferAmount(true); + getTransferDetails(transaction.input, transaction.to, chainId) + .then(details => { + console.log('details', details); + setPayingAmount(`${details?.amount} ${details?.symbol}`); + }) + .finally(() => { + setFetchingTransferAmount(false); + }); + // eslint-disable-next-line react-hooks/exhaustive-deps + }, []); + + const calculateInitialTxFees = async () => { + if (networkFee) { + console.log('fees already updated'); + return; + } + setFetchingGas(true); + console.log('calculating fees..'); + const fees = await calculateEip155Gas(transaction, chainId!); + console.log('fees', fees); + if (!fees) { + console.log('fees not available'); + return; + } + + setTransaction({ + from: transaction.from, + to: transaction.to, + input: transaction.input, + chainId: chainId, + nonce: (await getNonce(transaction.from!, chainId)) as `0x${string}`, + value: transaction.value || '0x', + maxFeePerGas: fees.maxFeePerGas as `0x${string}`, + maxPriorityFeePerGas: fees.maxPriorityFeePerGas as `0x${string}`, + gasLimit: fees.gasLimit as `0x${string}`, + }); + console.log('fees updated', fees); + setNetworkFee(`${ethers.utils.formatEther(fees.gasLimit)} ETH`); + setFetchingGas(false); + }; + + useMemo(async () => { + if (fundingFrom) { + return; + } + setFetchingRoutes(true); + setFetchingGas(true); + try { + console.log('fetching routes...', { + transaction: { + from: transaction.from, + to: transaction.to, + input: transaction.input, + chainId: chainId, + }, + }); + + const result = await walletKit.chainAbstraction.prepareDetailed({ + transaction: { + from: transaction.from as `0x${string}`, + to: transaction.to as `0x${string}`, + // @ts-ignore - cater for both input or data + input: transaction.input || (transaction.data as `0x${string}`), + chainId: chainId, + value: transaction.value || '0x', + }, + }); + + console.log('result', JSON.stringify(result, null, 2)); + + if ('success' in result) { + if ('notRequired' in result.success) { + console.log('no routing required'); + setRoutingStatus('no bridging required'); + await calculateInitialTxFees(); + } else if ('available' in result.success) { + const available = result.success.available; + + console.log('details --------', JSON.stringify(available, null, 2)); + + const transactions: any[] = []; + + for (const detail of available.route) { + transactions.push(detail.transactionHashToSign); + } + + setNetworkFee( + `${available.localTotal.formattedAlt} ${available.localTotal.symbol}`, + ); + + setTransaction(available.initial.transaction); + setFundingFrom(available.routeResponse.metadata.fundingFrom); + setBridgeDetails(available); + } + } + } catch (e) { + console.log('error', e); + const error = e as Error; + setRoutingStatus(error.message); + setHasError(true); + } + setFetchingRoutes(false); + setFetchingGas(false); + // eslint-disable-next-line react-hooks/exhaustive-deps + }, []); + + const execute = useCallback(async () => { + if (requestEvent && bridgeDetails) { + console.log('prepping executing...', {}); + const bridgeTxs = bridgeDetails.route.map(tx => tx.transactionHashToSign); + const signedBridgeTxs = bridgeTxs.map(tx => wallet1.signAny(tx)); + const signInitialTx = wallet1.signAny( + bridgeDetails.initial.transactionHashToSign, + ); + + console.log('executing...', { + signedBridgeTxs, + signInitialTx, + }); + + const result = await walletKit.chainAbstraction.execute({ + bridgeSignedTransactions: signedBridgeTxs, + initialSignedTransaction: signInitialTx, + orchestrationId: bridgeDetails.routeResponse.orchestrationId, + }); + + console.log('execute result', result); + + return formatJsonRpcResult(requestEvent.id, result); + } + }, [bridgeDetails, requestEvent]); // Handle approve action const onApprove = useCallback(async () => { if (requestEvent && topic) { - setIsLoadingApprove(true); + console.log('on Approve'); try { - const response = await approveEIP155Request(requestEvent); + setApproveLoading(true); + const bridgeResult = await execute(); + + const response = bridgeResult + ? bridgeResult + : await approveEIP155Request(requestEvent); await walletKit.respondSessionRequest({ topic, response, @@ -52,17 +241,20 @@ export default function SessionSendTransactionModal() { }); } catch (e) { console.log((e as Error).message, 'error'); + Alert.alert((e as Error).message); + setApproveLoading(false); return; } - setIsLoadingApprove(false); + + setApproveLoading(false); ModalStore.close(); } - }, [requestEvent, peerMetadata, topic, isLinkMode]); + }, [requestEvent, topic, execute, peerMetadata?.redirect, isLinkMode]); // Handle reject action const onReject = useCallback(async () => { if (requestEvent && topic) { - setIsLoadingReject(true); + setRejectLoading(true); const response = rejectEIP155Request(requestEvent); try { await walletKit.respondSessionRequest({ @@ -72,27 +264,177 @@ export default function SessionSendTransactionModal() { } catch (e) { console.log((e as Error).message, 'error'); return; + } finally { + setRejectLoading(false); } - setIsLoadingReject(false); ModalStore.close(); } }, [requestEvent, topic]); + const calculateFundingAmount = (amount: string, decimals: number = 6) => { + console.log( + 'amount', + amount, + parseInt(amount, 16), + parseInt(amount, 16) / 10 ** decimals, + ); + return parseInt(amount, 16) / 10 ** decimals; + }; + + const getChain = (chain: string) => { + const parsedChain = chain?.includes(':') ? chain.split(':')[1] : chain; + const logoSource = PresetsUtil.getChainLogo(parsedChain); + console.log('chain', EIP155_CHAINS[parsedChain]); + return { + data: EIP155_CHAINS[parsedChain], + logo: logoSource ? ( + + ) : null, + }; + }; + + const FundingFromUi = useMemo(() => { + if (!fundingFrom) { + return ( + + + + + Bridging + + + + + + {fetchingRoutes ? ( + + ) : ( + routingStatus + )} + + + + + ); + } + return fundingFrom?.map((funding, index) => { + const fundingChainDetails = getChain(funding.chainId); + return ( + + + + + Bridging + + + + + {calculateFundingAmount(funding.amount, funding.decimals).toFixed( + 5, + )}{' '} + {funding.symbol} + + + + From {fundingChainDetails?.data?.name}{' '} + + {fundingChainDetails?.logo} + + + + ); + }); + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [fetchingRoutes, fundingFrom]); + return ( - - - - - + onApprove={onApprove} + approveLoader={approveLoading} + rejectLoader={rejectLoading} + disableApprove={ + fetchingGas || fetchingRoutes || fetchingTransferAmount || hasError + }> + + + {/* Left Column in Row */} + + Paying + + {/* Right Column in Row */} + + + {payingAmount ? ( + payingAmount + ) : ( + + )} + + + + + + {/* Left Column in Row */} + + + Source of funds + + + {/* Right Column in Row */} + + + {FundingFromUi} + + + + + + {/* Left Column in Row */} + + App + + {/* Right Column in Row */} + + {isVerified(requestEvent?.verifyContext) ? ( + + ) : null} + + {peerMetadata?.url} + + + + + {/* Left Column in Row */} + + Network + + {/* Right Column in Row */} + + + {chainData?.logo} {chainData?.data.name} + + + + + + {/* Left Column in Row */} + + + Estimated Fees + + + {/* Right Column in Row */} + + + {networkFee ? networkFee : } + + + + - + ); } @@ -103,4 +445,60 @@ const styles = StyleSheet.create({ paddingHorizontal: 16, rowGap: 8, }, + section: { + width: '100%', + backgroundColor: '#252525', + borderRadius: 20, + display: 'flex', + padding: 5, + marginBottom: 10, + }, + innerSection: { + backgroundColor: '#2A2A2A', + borderRadius: 20, + }, + alignInCenter: { + flexDirection: 'row', + alignItems: 'center', + }, + row: { + flexDirection: 'row', + justifyContent: 'space-between', + alignItems: 'center', + height: 42, + paddingLeft: 20, + paddingEnd: 20, + }, + chainLogo: { + width: 12, + height: 12, + borderRadius: 6, + }, + column: { + alignItems: 'center', + }, + iconColumn: { + flexDirection: 'row', + alignItems: 'center', + }, + textMuted: { + color: '#9A9A9A', + fontSize: 14, + fontWeight: 400, + lineHeight: 16, + textAlign: 'left', + }, + textMid: { + fontSize: 14, + lineHeight: 16, + }, + textSm: { + fontSize: 12, + lineHeight: 14, + }, + textMain: { + color: '#ffffff', + fontWeight: 500, + textAlign: 'right', + }, }); diff --git a/wallets/rn_cli_wallet/src/screens/App.tsx b/wallets/rn_cli_wallet/src/screens/App.tsx index e1371cf6..07cc36b8 100644 --- a/wallets/rn_cli_wallet/src/screens/App.tsx +++ b/wallets/rn_cli_wallet/src/screens/App.tsx @@ -81,6 +81,7 @@ const App = () => { ({url}: {url: string}) => { const isLinkMode = url.includes('wc_ev'); SettingsStore.setIsLinkModeRequest(isLinkMode); + SettingsStore.setConnectionViaDeepLink(true); if (isLinkMode) { return; diff --git a/wallets/rn_cli_wallet/src/screens/Settings/index.tsx b/wallets/rn_cli_wallet/src/screens/Settings/index.tsx index 4fe15795..235aedad 100644 --- a/wallets/rn_cli_wallet/src/screens/Settings/index.tsx +++ b/wallets/rn_cli_wallet/src/screens/Settings/index.tsx @@ -1,16 +1,17 @@ import {useSnapshot} from 'valtio'; import {useEffect, useState} from 'react'; -import {Text, View, Alert, ScrollView} from 'react-native'; +import {Text, View, Alert, ScrollView, DevSettings} from 'react-native'; import AsyncStorage from '@react-native-async-storage/async-storage'; import Clipboard from '@react-native-clipboard/clipboard'; import {getVersion, getBuildNumber} from 'react-native-device-info'; -import {eip155Wallets} from '@/utils/EIP155WalletUtil'; +import {eip155Wallets, replaceMnemonic} from '@/utils/EIP155WalletUtil'; import SettingsStore from '@/store/SettingsStore'; import {Card} from '@/components/Card'; import {useTheme} from '@/hooks/useTheme'; import styles from './styles'; import {SettingsStackScreenProps} from '@/utils/TypesUtil'; +import {TextInput} from 'react-native-gesture-handler'; type Props = SettingsStackScreenProps<'Settings'>; @@ -18,7 +19,7 @@ export default function Settings({navigation}: Props) { const Theme = useTheme(); const {eip155Address, socketStatus} = useSnapshot(SettingsStore.state); const [clientId, setClientId] = useState(''); - + const [newMnemonic, setNewMnemonic] = useState(''); useEffect(() => { async function getAsyncData() { const _clientId = await AsyncStorage.getItem('WALLETCONNECT_CLIENT_ID'); @@ -34,6 +35,17 @@ export default function Settings({navigation}: Props) { Alert.alert('Value copied to clipboard'); }; + const onAddNewAccount = () => { + console.log('Add new account', newMnemonic); + replaceMnemonic(newMnemonic) + .then(() => { + Alert.alert('Success', 'Please restart the app!'); + }) + .catch(e => { + Alert.alert('Error', e.message); + }); + }; + return ( + + setNewMnemonic(value)} + /> + + Device diff --git a/wallets/rn_cli_wallet/src/store/SettingsStore.ts b/wallets/rn_cli_wallet/src/store/SettingsStore.ts index 46bec50c..58cd08a5 100644 --- a/wallets/rn_cli_wallet/src/store/SettingsStore.ts +++ b/wallets/rn_cli_wallet/src/store/SettingsStore.ts @@ -24,6 +24,7 @@ interface State { socketStatus: 'connected' | 'disconnected' | 'stalled' | 'unknown'; logs: string[]; isLinkModeRequest: boolean; + connectionViaDeepLink: boolean; } /** @@ -40,6 +41,7 @@ const state = proxy({ socketStatus: 'unknown', logs: [], isLinkModeRequest: false, + connectionViaDeepLink: false, }); /** @@ -98,6 +100,9 @@ const SettingsStore = { AsyncStorage.removeItem('TEST_NETS'); } }, + setConnectionViaDeepLink(value: State['connectionViaDeepLink']) { + state.connectionViaDeepLink = value; + }, }; export default SettingsStore; diff --git a/wallets/rn_cli_wallet/src/utils/EIP155RequestHandlerUtil.ts b/wallets/rn_cli_wallet/src/utils/EIP155RequestHandlerUtil.ts index bf767203..9b5f5439 100644 --- a/wallets/rn_cli_wallet/src/utils/EIP155RequestHandlerUtil.ts +++ b/wallets/rn_cli_wallet/src/utils/EIP155RequestHandlerUtil.ts @@ -10,11 +10,15 @@ import { getWalletAddressFromParams, } from '@/utils/HelperUtil'; import {EIP155_SIGNING_METHODS, PresetsUtil} from './PresetsUtil'; +import {parseChainId} from './HelperUtil'; type RequestEventArgs = Omit< SignClientTypes.EventArguments['session_request'], 'verifyContext' >; -export async function approveEIP155Request(requestEvent: RequestEventArgs) { +export async function approveEIP155Request( + requestEvent: RequestEventArgs, + additionalTransactions: any[] = [], +) { const {params, id} = requestEvent; const {chainId, request} = params; const wallet = @@ -57,19 +61,46 @@ export async function approveEIP155Request(requestEvent: RequestEventArgs) { } case EIP155_SIGNING_METHODS.ETH_SEND_TRANSACTION: - try { - const chainData = PresetsUtil.getChainData(chainId.split(':')[1]); + let hash = ''; + if (additionalTransactions.length > 0) { + console.log( + 'starting processing transactions: ', + additionalTransactions.length, + ); + const start = Date.now(); + for (const transaction of additionalTransactions) { + const chain = transaction.chainId + ? parseChainId(transaction.chainId) + : parseChainId(chainId); + const chainData = PresetsUtil.getChainData(chain); + const provider = new providers.JsonRpcProvider(chainData.rpcUrl); + const connectedWallet = wallet.connect(provider); + console.log('sending transaction...', transaction); + // await new Promise(resolve => setTimeout(resolve, 10_000)); + delete transaction.chainId; + const result = await connectedWallet.sendTransaction({ + ...transaction, + nonce: await provider.getTransactionCount(transaction.from), + }); + console.log('transaction sent - hash:', result.hash); + console.log('waiting for transaction to be mined...'); + const receipt = await waitForTransaction(result.hash, provider); + console.log('transaction mined:', receipt); + hash = result.hash; + console.log('tx done:', Date.now() - start); + } + console.log('all tx done:', Date.now() - start); + } else { + const chainData = PresetsUtil.getChainData(parseChainId(chainId)); const provider = new providers.JsonRpcProvider(chainData.rpcUrl); const sendTransaction = request.params[0]; const connectedWallet = wallet.connect(provider); - const {hash} = await connectedWallet.sendTransaction(sendTransaction); - return formatJsonRpcResult(id, hash); - } catch (error: any) { - console.error(error); - console.log(error.message); - return formatJsonRpcError(id, error.message); + const result = await connectedWallet.sendTransaction(sendTransaction); + hash = result.hash; } + return formatJsonRpcResult(id, hash); + case EIP155_SIGNING_METHODS.ETH_SIGN_TRANSACTION: try { const signTransaction = request.params[0]; @@ -91,3 +122,25 @@ export function rejectEIP155Request(request: RequestEventArgs) { return formatJsonRpcError(id, getSdkError('USER_REJECTED').message); } + +async function waitForTransaction( + txHash: string, + provider: providers.JsonRpcProvider, +) { + let receipt = null; + + // Loop until the transaction is mined (receipt is not null) + while (receipt === null) { + // Wait 2 seconds before checking again + await new Promise(resolve => setTimeout(resolve, 2000)); + + try { + // Get the receipt for the transaction hash + receipt = await provider.getTransactionReceipt(txHash); + } catch (error) { + console.error('Error fetching receipt:', error); + } + } + + return receipt; +} diff --git a/wallets/rn_cli_wallet/src/utils/EIP155WalletUtil.ts b/wallets/rn_cli_wallet/src/utils/EIP155WalletUtil.ts index 25b8b91c..a740ecca 100644 --- a/wallets/rn_cli_wallet/src/utils/EIP155WalletUtil.ts +++ b/wallets/rn_cli_wallet/src/utils/EIP155WalletUtil.ts @@ -1,5 +1,9 @@ import AsyncStorage from '@react-native-async-storage/async-storage'; import EIP155Lib from '../lib/EIP155Lib'; +import {ethers} from 'ethers'; +import {PresetsUtil} from '../utils/PresetsUtil'; +import {getAbiByPrefix, parseChainId} from './HelperUtil'; +import {TransactionType} from './TypesUtil'; export let wallet1: EIP155Lib; export let wallet2: EIP155Lib; @@ -13,27 +17,24 @@ let address2: string; * Utilities */ export async function createOrRestoreEIP155Wallet() { - const mnemonic1 = await AsyncStorage.getItem('EIP155_MNEMONIC_1'); - const mnemonic2 = await AsyncStorage.getItem('EIP155_MNEMONIC_2'); + const mnemonic1 = + (await AsyncStorage.getItem('EIP155_MNEMONIC_1')) || undefined; + const privateKey1 = + (await AsyncStorage.getItem('EIP155_PRIVATE_1')) || undefined; - if (mnemonic1 && mnemonic2) { - wallet1 = EIP155Lib.init({mnemonic: mnemonic1}); - wallet2 = EIP155Lib.init({mnemonic: mnemonic2}); + if (mnemonic1 || privateKey1) { + wallet1 = EIP155Lib.init({mnemonic: mnemonic1, privateKey: privateKey1}); } else { wallet1 = EIP155Lib.init({}); - wallet2 = EIP155Lib.init({}); - // Don't store mnemonic in local storage in a production project! AsyncStorage.setItem('EIP155_MNEMONIC_1', wallet1.getMnemonic()); - AsyncStorage.setItem('EIP155_MNEMONIC_2', wallet2.getMnemonic()); } address1 = wallet1.getAddress(); - address2 = wallet2.getAddress(); eip155Wallets = { [address1]: wallet1, - [address2]: wallet2, + [address2]: wallet1, }; eip155Addresses = Object.keys(eip155Wallets); @@ -42,3 +43,154 @@ export async function createOrRestoreEIP155Wallet() { eip155Addresses, }; } + +export async function replaceMnemonic(mnemonicOrPrivateKey: string) { + try { + let wallet; + if (mnemonicOrPrivateKey.includes(' ')) { + wallet = EIP155Lib.init({mnemonic: mnemonicOrPrivateKey}); + await AsyncStorage.setItem('EIP155_MNEMONIC_1', wallet.getMnemonic()); + } else { + wallet = EIP155Lib.init({privateKey: mnemonicOrPrivateKey}); + await AsyncStorage.setItem('EIP155_PRIVATE_1', wallet.wallet.privateKey); + } + } catch (error) { + throw new Error('Invalid mnemonic or private key'); + } +} + +export async function calculateEip155Gas( + transaction: TransactionType, + chainId: string, +) { + console.log('calculateEip155Gas:', chainId); + const chainData = PresetsUtil.getChainData(parseChainId(chainId)); + let provider = new ethers.providers.JsonRpcProvider(chainData.rpcUrl); + + // Fetch the latest block to get the base fee + const block = await provider.getBlock('latest'); + if (!block) { + return; + } + const baseFee = block.baseFeePerGas; + const fees = await fetchGasPrice(parseChainId(chainId)); + + // You can adjust the priority fee based on current network conditions + const maxPriorityFeePerGas = fees.normal.priority_price.toString(); + // console.log('fees:', fees); + // Calculate the max fee per gas (base fee + priority fee) + const maxFeePerGas = baseFee!.add(maxPriorityFeePerGas); + + let gasLimit; + try { + gasLimit = await provider.estimateGas({ + ...transaction, + chainId: chainData.id, + }); + console.log('Gas Limit estimated:', gasLimit.toString()); + } catch (error) { + console.error('Error estimating gas:', error); + gasLimit = ethers.BigNumber.from(0x05b6a8); + } + + // Log the details of the gas fees + console.log('Base Fee:', ethers.utils.formatUnits(baseFee!, 'gwei'), 'Gwei'); + console.log( + 'Max Priority Fee:', + ethers.utils.formatUnits(maxPriorityFeePerGas, 'gwei'), + 'Gwei', + ); + console.log( + 'Max Fee per Gas:', + ethers.utils.formatUnits(maxFeePerGas, 'gwei'), + 'Gwei', + ); + console.log('Estimated Gas Limit:', gasLimit.toString()); + + return { + maxFeePerGas: ethers.utils.formatUnits(maxFeePerGas, 'wei'), + maxPriorityFeePerGas: ethers.utils.formatUnits(maxPriorityFeePerGas, 'wei'), + gasLimit: ethers.utils.formatUnits(gasLimit, 'wei'), + }; +} + +const fetchGasPrice = async (chainId: string) => { + const result = await fetch( + `https://tokentool.bitbond.com/api/gas-price-20240116?chain_id=${parseChainId( + chainId, + )}×tamp=${Date.now()}`, + ); + const data = await result.json(); + console.log('fetchGasPrice:', data); + return data?.data; +}; + +export async function calculateGasLimit(tx: any, chainId: string) { + const chainData = PresetsUtil.getChainData(parseChainId(chainId)); + const provider = new ethers.providers.JsonRpcProvider(chainData.rpcUrl); + + const result = await provider.estimateGas(tx); + return result; +} + +export async function getNonce(address: string, chainId: string) { + const chainData = PresetsUtil.getChainData(parseChainId(chainId)); + const provider = new ethers.providers.JsonRpcProvider(chainData.rpcUrl); + + const nonce = await provider.getTransactionCount(address); + console.log('getNonce:', nonce); + return nonce.toString(); +} + +export async function getTransferDetails( + data: string, + contractAddress: string, + chainId: string, +) { + const prefix = data.slice(0, 10); + // Define the function ABI + const abi = getAbiByPrefix(prefix); + console.log('ABI:', abi); + // Create an Interface instance + const iabi = new ethers.utils.Interface(abi); + console.log('Interface data', data); + // Decode the transaction data + const decodedData = iabi.parseTransaction({ + data: data, + }); + + const chainData = PresetsUtil.getChainData(parseChainId(chainId)); + // Connect to the Ethereum network + const provider = new ethers.providers.JsonRpcProvider(chainData.rpcUrl); + + const ERC20_ABI = [ + 'function decimals() view returns (uint8)', + 'function symbol() view returns (string)', + ]; + + console.log('Token Address:', contractAddress); + // Create a contract instance + const tokenContract = new ethers.Contract( + contractAddress, + ERC20_ABI, + provider, + ); + + // Fetch decimals and symbol + try { + const decimals = await tokenContract.decimals(); + const symbol = await tokenContract.symbol(); + + const amount = + parseInt(decodedData.args[1].toString(), 10) / 10 ** decimals; + + console.log(`Token Symbol: ${symbol}`); + console.log(`Token Decimals: ${decimals}`); + console.log(`Total Amount: ${amount}`); + + return {symbol, decimals, amount}; + } catch (error) { + console.error('Error fetching token details:', error); + return null; + } +} diff --git a/wallets/rn_cli_wallet/src/utils/HelperUtil.ts b/wallets/rn_cli_wallet/src/utils/HelperUtil.ts index 643304d5..fcb6d139 100644 --- a/wallets/rn_cli_wallet/src/utils/HelperUtil.ts +++ b/wallets/rn_cli_wallet/src/utils/HelperUtil.ts @@ -128,3 +128,27 @@ export function getSupportedChains( .map(chain => PresetsUtil.getChainData(chain.split(':')[1])) .filter(chain => chain !== undefined); } + +export function getAbiByPrefix(prefix: string) { + console.log('matching prefix:', prefix); + if (prefix === '0xa9059cbb') { + return ['function transfer(address to, uint256 amount)']; + } + + if (prefix === '0x23b872dd') { + return ['function approve(address spender, uint256 amount)']; + } + + if (prefix === '0x095ea7b3') { + return ['function approve(address spender, uint256 amount)']; + } + throw new Error(`Unknown abi for prefix: ${prefix}`); +} + +export const parseChainId = (chainId: string) => { + return chainId.includes(':') ? chainId.split(':')[1] : chainId; +}; + +export const isVerified = (verifyContext: any) => { + return verifyContext?.verified?.validation === 'VALID'; +}; diff --git a/wallets/rn_cli_wallet/src/utils/LinkingUtils.ts b/wallets/rn_cli_wallet/src/utils/LinkingUtils.ts index 7a69a74c..195fb2da 100644 --- a/wallets/rn_cli_wallet/src/utils/LinkingUtils.ts +++ b/wallets/rn_cli_wallet/src/utils/LinkingUtils.ts @@ -1,6 +1,7 @@ import {Linking, Platform} from 'react-native'; import Toast from 'react-native-toast-message'; import Minimizer from '@kangfenmao/react-native-minimizer'; +import SettingsStore from '@/store/SettingsStore'; interface redirect { native?: string; @@ -18,9 +19,13 @@ const goBackOrToast = () => { Toast.show({ type: 'success', text1: 'Success!', - text2: 'Redirecting to the dapp', + text2: SettingsStore.state.connectionViaDeepLink + ? 'Redirecting to the dapp' + : 'Please go back to the dapp', }); - Minimizer.goBack(); + if (SettingsStore.state.connectionViaDeepLink) { + Minimizer.goBack(); + } } else { Toast.show({ type: 'success', diff --git a/wallets/rn_cli_wallet/src/utils/ThemeUtil.ts b/wallets/rn_cli_wallet/src/utils/ThemeUtil.ts index db498d27..b41189b8 100644 --- a/wallets/rn_cli_wallet/src/utils/ThemeUtil.ts +++ b/wallets/rn_cli_wallet/src/utils/ThemeUtil.ts @@ -21,6 +21,7 @@ export const LightTheme: {[key in ThemeKeys]: string} = { 'fg-250': '#8b9797', 'fg-275': '#95a0a0', 'fg-300': '#9ea9a9', + 'fg-secondary': '#6e7777', 'bg-100': '#ffffff', 'bg-125': '#ffffff', @@ -87,6 +88,7 @@ export const DarkTheme: {[key in ThemeKeys]: string} = { 'bg-250': '#313535', 'bg-275': '#363b3b', 'bg-300': '#3b4040', + 'fg-secondary': '#2A2A2A', 'inverse-100': '#ffffff', 'inverse-000': '#000000', diff --git a/wallets/rn_cli_wallet/src/utils/TypesUtil.ts b/wallets/rn_cli_wallet/src/utils/TypesUtil.ts index ed4ed1db..ba7316de 100644 --- a/wallets/rn_cli_wallet/src/utils/TypesUtil.ts +++ b/wallets/rn_cli_wallet/src/utils/TypesUtil.ts @@ -14,6 +14,7 @@ export type ThemeKeys = | 'accent-glass-010' | 'accent-glass-005' | 'accent-glass-002' + | 'fg-secondary' | 'fg-100' | 'fg-125' | 'fg-150' diff --git a/wallets/rn_cli_wallet/src/utils/WalletKitUtil.ts b/wallets/rn_cli_wallet/src/utils/WalletKitUtil.ts index b5634201..65b06613 100644 --- a/wallets/rn_cli_wallet/src/utils/WalletKitUtil.ts +++ b/wallets/rn_cli_wallet/src/utils/WalletKitUtil.ts @@ -8,14 +8,14 @@ export let walletKit: IWalletKit; export async function createWalletKit(relayerRegionURL: string) { const core = new Core({ - projectId: Config.ENV_PROJECT_ID, + projectId: '47a263e9e957d954353cb970f024e1d3', relayUrl: relayerRegionURL ?? Config.ENV_RELAY_URL, }); walletKit = await WalletKit.init({ core, metadata: getMetadata(), }); - + console.log('walletkit created'); try { const clientId = await walletKit.engine.signClient.core.crypto.getClientId(); diff --git a/wallets/rn_cli_wallet/tsconfig.json b/wallets/rn_cli_wallet/tsconfig.json index 461b9db4..4d8cd98e 100644 --- a/wallets/rn_cli_wallet/tsconfig.json +++ b/wallets/rn_cli_wallet/tsconfig.json @@ -1,6 +1,7 @@ { "extends": "@react-native/typescript-config/tsconfig.json", "compilerOptions": { + "jsx": "react-jsx", "baseUrl": ".", "paths": { "@/assets/*": ["./src/assets/*"], diff --git a/wallets/rn_cli_wallet/yarn.lock b/wallets/rn_cli_wallet/yarn.lock index 49c554a3..491795f5 100644 --- a/wallets/rn_cli_wallet/yarn.lock +++ b/wallets/rn_cli_wallet/yarn.lock @@ -2709,6 +2709,45 @@ __metadata: languageName: node linkType: hard +"@noble/ciphers@npm:1.2.1": + version: 1.2.1 + resolution: "@noble/ciphers@npm:1.2.1" + checksum: 843bd81a2b17cac7045c4ecc511c1e88f42e51f5df2635efdbd30fd318afe78d88c732772773a8412d5057560d23746a6aea6dd255af1a49fb17928ef23f6c22 + languageName: node + linkType: hard + +"@noble/curves@npm:1.8.0": + version: 1.8.0 + resolution: "@noble/curves@npm:1.8.0" + dependencies: + "@noble/hashes": 1.7.0 + checksum: 88198bc5b8049358dfcc6c5e121125744fb81c703299127800f38f868a41697bc26bef8f88dc38f1939f4e0133b8db5f24337164eca7421a6a9480ee711f5e1b + languageName: node + linkType: hard + +"@noble/curves@npm:1.8.1": + version: 1.8.1 + resolution: "@noble/curves@npm:1.8.1" + dependencies: + "@noble/hashes": 1.7.1 + checksum: 4143f1248ed57c1ae46dfef5c692a91383e5830420b9c72d3ff1061aa9ebbf8999297da6d2aed8a9716fef8e6b1f5a45737feeab02abf55ca2a4f514bf9339ec + languageName: node + linkType: hard + +"@noble/hashes@npm:1.7.0": + version: 1.7.0 + resolution: "@noble/hashes@npm:1.7.0" + checksum: c06949ead7f5771a74f6fc9a346c7519212b3484c5b7916c8cad6b1b0e5f5f6c997ac3a43c0884ef8b99cfc55fac89058eefb29b6aad1cb41f436c748b316a1c + languageName: node + linkType: hard + +"@noble/hashes@npm:1.7.1": + version: 1.7.1 + resolution: "@noble/hashes@npm:1.7.1" + checksum: 4f1b56428a10323feef17e4f437c9093556cb18db06f94d254043fadb69c3da8475f96eb3f8322d41e8670117d7486475a8875e68265c2839f60fd03edd6a616 + languageName: node + linkType: hard + "@nodelib/fs.scandir@npm:2.1.5": version: 2.1.5 resolution: "@nodelib/fs.scandir@npm:2.1.5" @@ -2928,15 +2967,20 @@ __metadata: languageName: node linkType: hard -"@react-native-clipboard/clipboard@npm:1.14.1": - version: 1.14.1 - resolution: "@react-native-clipboard/clipboard@npm:1.14.1" +"@react-native-clipboard/clipboard@npm:1.15.0": + version: 1.15.0 + resolution: "@react-native-clipboard/clipboard@npm:1.15.0" peerDependencies: - react: 16.9.0 || 16.11.0 || 16.13.1 || 17.0.1 || 17.0.2 || 18.0.0 || 18.1.0 || 18.2.0 - react-native: ^0.61.5 || ^0.62.3 || ^0.63.2 || ^0.64.2 || ^0.65.0 || ^0.66.0 || ^0.67.0 || ^0.68.0 || ^0.69.0 || ^0.70.0 || ^0.71.0 || ^0.72.0 || ^0.73.0 - react-native-macos: ^0.61.0 || ^0.62.0 || ^0.63.0 || ^0.64.0 || ^0.65.0 || ^0.66.0 || ^0.67.0 || ^0.68.0 || ^0.69.0 || ^0.70.0 || ^0.71.0 || ^0.72.0 || ^0.73.0 - react-native-windows: ^0.61.0 || ^0.62.0 || ^0.63.0 || ^0.64.0 || ^0.65.0 || ^0.66.0 || ^0.67.0 || ^0.68.0 || ^0.69.0 || ^0.70.0 || ^0.71.0 || ^0.72.0 || ^0.73.0 - checksum: 005ce2bee4d6e30b2a6b11be0d0ee169ab108d24f2a9b518b0ba8e5b96616c6dfb089c28644c1b5e3c1b9aa786c92cbf781e525223f56ab8589da1df79cae31f + react: ">= 16.9.0" + react-native: ">= 0.61.5" + react-native-macos: ">= 0.61.0" + react-native-windows: ">= 0.61.0" + peerDependenciesMeta: + react-native-macos: + optional: true + react-native-windows: + optional: true + checksum: b0c071368e46ce0676bbe68de2812c31ba67c477a85163b3f6392d04d13e4134c42040dc485361bfa059a7713baceb25afd4e15b77bfcaabe136fa499d9d5e19 languageName: node linkType: hard @@ -3489,18 +3533,19 @@ __metadata: languageName: node linkType: hard -"@reown/walletkit@npm:1.1.1": - version: 1.1.1 - resolution: "@reown/walletkit@npm:1.1.1" +"@reown/walletkit@npm:1.1.2-canary-ca-6": + version: 1.1.2-canary-ca-6 + resolution: "@reown/walletkit@npm:1.1.2-canary-ca-6" dependencies: - "@walletconnect/core": 2.17.1 + "@walletconnect/core": 2.18.1 "@walletconnect/jsonrpc-provider": 1.0.14 "@walletconnect/jsonrpc-utils": 1.0.8 "@walletconnect/logger": 2.1.2 - "@walletconnect/sign-client": 2.17.1 - "@walletconnect/types": 2.17.1 - "@walletconnect/utils": 2.17.1 - checksum: 30499034bd6b1a4e6fd357243f3395cda4c22211f90c86f783207485de33e953db36d938b32b25fb45f038376de4c2932e9026cc199016caab4fb8d7842a641d + "@walletconnect/sign-client": 2.18.1 + "@walletconnect/types": 2.18.1 + "@walletconnect/utils": 2.18.1 + brotli: ^1.3.3 + checksum: 219034f2c11685b351d250234fbccdd9b0c8ea04ef4076c75fc60278ab9bfb67ee3c8478078006591f0de57f8403db9d0b834c8899d78fbaec424e0849a71766 languageName: node linkType: hard @@ -3779,176 +3824,6 @@ __metadata: languageName: node linkType: hard -"@stablelib/aead@npm:^1.0.1": - version: 1.0.1 - resolution: "@stablelib/aead@npm:1.0.1" - checksum: 1a6f68d138f105d17dd65349751515bd252ab0498c77255b8555478d28415600dde493f909eb718245047a993f838dfae546071e1687566ffb7b8c3e10c918d9 - languageName: node - linkType: hard - -"@stablelib/binary@npm:^1.0.1": - version: 1.0.1 - resolution: "@stablelib/binary@npm:1.0.1" - dependencies: - "@stablelib/int": ^1.0.1 - checksum: dca9b98eb1f56a4002b5b9e7351fbc49f3d8616af87007c01e833bd763ac89214eb5f3b7e18673c91ce59d4a0e4856a2eb661ace33d39f17fb1ad267271fccd8 - languageName: node - linkType: hard - -"@stablelib/bytes@npm:^1.0.1": - version: 1.0.1 - resolution: "@stablelib/bytes@npm:1.0.1" - checksum: 456267e08c3384abcb71d3ad3e97a6f99185ad754bac016f501ebea4e4886f37900589143b57e33bdbbf513a92fc89368c15dd4517e0540d0bdc79ecdf9dd087 - languageName: node - linkType: hard - -"@stablelib/chacha20poly1305@npm:1.0.1": - version: 1.0.1 - resolution: "@stablelib/chacha20poly1305@npm:1.0.1" - dependencies: - "@stablelib/aead": ^1.0.1 - "@stablelib/binary": ^1.0.1 - "@stablelib/chacha": ^1.0.1 - "@stablelib/constant-time": ^1.0.1 - "@stablelib/poly1305": ^1.0.1 - "@stablelib/wipe": ^1.0.1 - checksum: 81f1a32330838d31e4dc3144d76eba7244b56d9ea38c1f604f2c34d93ed8e67e9a6167d2cfd72254c13cc46dfc1f5ce5157b37939a575295d69d9144abb4e4fb - languageName: node - linkType: hard - -"@stablelib/chacha@npm:^1.0.1": - version: 1.0.1 - resolution: "@stablelib/chacha@npm:1.0.1" - dependencies: - "@stablelib/binary": ^1.0.1 - "@stablelib/wipe": ^1.0.1 - checksum: f061f36c4ca4bf177dd7cac11e7c65ced164f141b6065885141ae5a55f32e16ba0209aefcdcc966aef013f1da616ce901a3a80653b4b6f833cf7e3397ae2d6bd - languageName: node - linkType: hard - -"@stablelib/constant-time@npm:^1.0.1": - version: 1.0.1 - resolution: "@stablelib/constant-time@npm:1.0.1" - checksum: dba4f4bf508de2ff15f7f0cbd875e70391aa3ba3698290fe1ed2feb151c243ba08a90fc6fb390ec2230e30fcc622318c591a7c0e35dcb8150afb50c797eac3d7 - languageName: node - linkType: hard - -"@stablelib/ed25519@npm:^1.0.2": - version: 1.0.3 - resolution: "@stablelib/ed25519@npm:1.0.3" - dependencies: - "@stablelib/random": ^1.0.2 - "@stablelib/sha512": ^1.0.1 - "@stablelib/wipe": ^1.0.1 - checksum: e18279de078edac67396ba07dbb862dce0fe89efa8141c21a5b04108a29914bd51636019522323ca5097ec596a90b3028ed64e88ee009b0ac7de7c1ab6499ccb - languageName: node - linkType: hard - -"@stablelib/hash@npm:^1.0.1": - version: 1.0.1 - resolution: "@stablelib/hash@npm:1.0.1" - checksum: 3ff1f12d1a4082aaf4b6cdf40c2010aabe5c4209d3b40b97b5bbb0d9abc0ee94abdc545e57de0614afaea807ca0212ac870e247ec8f66cdce91ec39ce82948cf - languageName: node - linkType: hard - -"@stablelib/hkdf@npm:1.0.1": - version: 1.0.1 - resolution: "@stablelib/hkdf@npm:1.0.1" - dependencies: - "@stablelib/hash": ^1.0.1 - "@stablelib/hmac": ^1.0.1 - "@stablelib/wipe": ^1.0.1 - checksum: 9d45e303715a1835c8612b78e6c1b9d2b7463699b484241d8681fb5c17e0f2bbde5ce211c882134b64616a402e09177baeba80426995ff227b3654a155ab225d - languageName: node - linkType: hard - -"@stablelib/hmac@npm:^1.0.1": - version: 1.0.1 - resolution: "@stablelib/hmac@npm:1.0.1" - dependencies: - "@stablelib/constant-time": ^1.0.1 - "@stablelib/hash": ^1.0.1 - "@stablelib/wipe": ^1.0.1 - checksum: e3b93f7144a5846a6e30213278f7570de6d3f9d09131b95ce76d5c5c8bf37bf5d1830f2ee8d847555707271dbfd6e2461221719fd4d8b27ff06b9dd689c0ec21 - languageName: node - linkType: hard - -"@stablelib/int@npm:^1.0.1": - version: 1.0.1 - resolution: "@stablelib/int@npm:1.0.1" - checksum: 65bfbf50a382eea70c68e05366bf379cfceff8fbc076f1c267ef2f2411d7aed64fd140c415cb6c29f19a3910d3b8b7805d4b32ad5721a5007a8e744a808c7ae3 - languageName: node - linkType: hard - -"@stablelib/keyagreement@npm:^1.0.1": - version: 1.0.1 - resolution: "@stablelib/keyagreement@npm:1.0.1" - dependencies: - "@stablelib/bytes": ^1.0.1 - checksum: 3c8ec904dd50f72f3162f5447a0fa8f1d9ca6e24cd272d3dbe84971267f3b47f9bd5dc4e4eeedf3fbac2fe01f2d9277053e57c8e60db8c5544bfb35c62d290dd - languageName: node - linkType: hard - -"@stablelib/poly1305@npm:^1.0.1": - version: 1.0.1 - resolution: "@stablelib/poly1305@npm:1.0.1" - dependencies: - "@stablelib/constant-time": ^1.0.1 - "@stablelib/wipe": ^1.0.1 - checksum: 70b845bb0481c66b7ba3f3865d01e4c67a4dffc9616fc6de1d23efc5e828ec09de25f8e3be4e1f15a23b8e87e3036ee3d949c2fd4785047e6f7028bbec0ead18 - languageName: node - linkType: hard - -"@stablelib/random@npm:1.0.2, @stablelib/random@npm:^1.0.1, @stablelib/random@npm:^1.0.2": - version: 1.0.2 - resolution: "@stablelib/random@npm:1.0.2" - dependencies: - "@stablelib/binary": ^1.0.1 - "@stablelib/wipe": ^1.0.1 - checksum: f5ace0a588dc4c21f01cb85837892d4c872e994ae77a58a8eb7dd61aa0b26fb1e9b46b0445e71af57d963ef7d9f5965c64258fc0d04df7b2947bc48f2d3560c5 - languageName: node - linkType: hard - -"@stablelib/sha256@npm:1.0.1": - version: 1.0.1 - resolution: "@stablelib/sha256@npm:1.0.1" - dependencies: - "@stablelib/binary": ^1.0.1 - "@stablelib/hash": ^1.0.1 - "@stablelib/wipe": ^1.0.1 - checksum: 38669871e1bda72eb537629ebceac1c72da8890273a9fbe088f81f6d14c1ec04e78be8c5b455380a06c67f8e62b2508e11e9063fcc257dbaa1b5c27ac756ba77 - languageName: node - linkType: hard - -"@stablelib/sha512@npm:^1.0.1": - version: 1.0.1 - resolution: "@stablelib/sha512@npm:1.0.1" - dependencies: - "@stablelib/binary": ^1.0.1 - "@stablelib/hash": ^1.0.1 - "@stablelib/wipe": ^1.0.1 - checksum: b7c82f7608a35948a2147a534c0c9afc80deab3fd5f72a2e27b2454e7c0c6944d39381be3abcb1b7fac5b824ba030ae3e98209d517a579c143d8ed63930b042f - languageName: node - linkType: hard - -"@stablelib/wipe@npm:^1.0.1": - version: 1.0.1 - resolution: "@stablelib/wipe@npm:1.0.1" - checksum: 287802eb146810a46ba72af70b82022caf83a8aeebde23605f5ee0decf64fe2b97a60c856e43b6617b5801287c30cfa863cfb0469e7fcde6f02d143cf0c6cbf4 - languageName: node - linkType: hard - -"@stablelib/x25519@npm:1.0.3": - version: 1.0.3 - resolution: "@stablelib/x25519@npm:1.0.3" - dependencies: - "@stablelib/keyagreement": ^1.0.1 - "@stablelib/random": ^1.0.2 - "@stablelib/wipe": ^1.0.1 - checksum: f8537066b542b6770c1b5b2ae5ad0688d1b986e4bf818067c152c123a5471531987bbf024224f75f387f481ccc5b628e391e49e92102b8b1a3e2d449d6105402 - languageName: node - linkType: hard - "@types/babel__core@npm:^7.1.14": version: 7.20.5 resolution: "@types/babel__core@npm:7.20.5" @@ -4334,28 +4209,28 @@ __metadata: languageName: node linkType: hard -"@walletconnect/core@npm:2.17.1": - version: 2.17.1 - resolution: "@walletconnect/core@npm:2.17.1" +"@walletconnect/core@npm:2.18.1": + version: 2.18.1 + resolution: "@walletconnect/core@npm:2.18.1" dependencies: "@walletconnect/heartbeat": 1.2.2 "@walletconnect/jsonrpc-provider": 1.0.14 "@walletconnect/jsonrpc-types": 1.0.4 "@walletconnect/jsonrpc-utils": 1.0.8 - "@walletconnect/jsonrpc-ws-connection": 1.0.14 + "@walletconnect/jsonrpc-ws-connection": 1.0.16 "@walletconnect/keyvaluestorage": 1.1.1 "@walletconnect/logger": 2.1.2 "@walletconnect/relay-api": 1.0.11 - "@walletconnect/relay-auth": 1.0.4 + "@walletconnect/relay-auth": 1.1.0 "@walletconnect/safe-json": 1.0.2 "@walletconnect/time": 1.0.2 - "@walletconnect/types": 2.17.1 - "@walletconnect/utils": 2.17.1 + "@walletconnect/types": 2.18.1 + "@walletconnect/utils": 2.18.1 "@walletconnect/window-getters": 1.0.1 events: 3.3.0 lodash.isequal: 4.5.0 uint8arrays: 3.1.0 - checksum: 41fae7cfe91e012881eae3e1214ab626ad119bfdf33866f97ee423011efca828d673bb9496dce5f5f9d71c0997ca46c4c2bc7c3c53ca1aa6580494de945743cb + checksum: 33eebe3e9ead0a74f18e0485b1c2a2c8bf4ce6abdc3aef18480e4e0b90c5aef8cf825c2a67fc8f41d7f8b79d1b3443cfcd4b1751a17b5c0cb12e92d0c6232cc6 languageName: node linkType: hard @@ -4421,15 +4296,15 @@ __metadata: languageName: node linkType: hard -"@walletconnect/jsonrpc-ws-connection@npm:1.0.14": - version: 1.0.14 - resolution: "@walletconnect/jsonrpc-ws-connection@npm:1.0.14" +"@walletconnect/jsonrpc-ws-connection@npm:1.0.16": + version: 1.0.16 + resolution: "@walletconnect/jsonrpc-ws-connection@npm:1.0.16" dependencies: "@walletconnect/jsonrpc-utils": ^1.0.6 "@walletconnect/safe-json": ^1.0.2 events: ^3.3.0 ws: ^7.5.1 - checksum: a401e60b19390098183ef1b2a7b3e15c4dd3c64f9ac87fd2bbc0ae1f7fb31539ba542374ca021193efc4a2ae59fa3b04e588aed98cdf5c364f50524403d50f9f + checksum: 8d1b551d69f8a5b27894d2b37cfd28d407634a95acc920db127daa4a20999676780ce157ba44614e3c048acfe8adc494592bd49f314c1601e6daf60e2bbae385 languageName: node linkType: hard @@ -4459,9 +4334,9 @@ __metadata: languageName: node linkType: hard -"@walletconnect/react-native-compat@npm:2.17.2": - version: 2.17.2 - resolution: "@walletconnect/react-native-compat@npm:2.17.2" +"@walletconnect/react-native-compat@npm:2.18.1-canary-ca-5": + version: 2.18.1-canary-ca-5 + resolution: "@walletconnect/react-native-compat@npm:2.18.1-canary-ca-5" dependencies: events: 3.3.0 fast-text-encoding: 1.0.6 @@ -4475,7 +4350,7 @@ __metadata: peerDependenciesMeta: expo-application: optional: true - checksum: a038f29cc4e77a4493b735e14c4227f7883728845ad49ba5583e0598f0b3aaddfe5cf2a1550869d478e138d9b089ec177a5e28952c320b9c2f7e7fd84987d8cb + checksum: ee8804bd997572c903131cd86d3a754ca36133c425d72291f230d548aecb6c47152bc48e52b0d57e7f707d2247dbb27a6b8db90b11cfe74f855bdf1fb1a63871 languageName: node linkType: hard @@ -4488,17 +4363,16 @@ __metadata: languageName: node linkType: hard -"@walletconnect/relay-auth@npm:1.0.4": - version: 1.0.4 - resolution: "@walletconnect/relay-auth@npm:1.0.4" +"@walletconnect/relay-auth@npm:1.1.0": + version: 1.1.0 + resolution: "@walletconnect/relay-auth@npm:1.1.0" dependencies: - "@stablelib/ed25519": ^1.0.2 - "@stablelib/random": ^1.0.1 + "@noble/curves": 1.8.0 + "@noble/hashes": 1.7.0 "@walletconnect/safe-json": ^1.0.1 "@walletconnect/time": ^1.0.2 - tslib: 1.14.1 uint8arrays: ^3.0.0 - checksum: 35b3229d7b57e74fdb8fe6827d8dd8291dc60bacda880a57b2acb47a34d38f12be46c971c9eff361eb4073e896648b550de7a7a3852ef3752f9619c08dfba891 + checksum: 0081309d341ceab39bd4fc69cd0d92112a2df4ab3e9abab3ba8c03f6bdf3dddd556bdb4e4e091f02f54d02d0a3948be039e6792e213226e85718aab7dde1aea2 languageName: node linkType: hard @@ -4511,20 +4385,20 @@ __metadata: languageName: node linkType: hard -"@walletconnect/sign-client@npm:2.17.1": - version: 2.17.1 - resolution: "@walletconnect/sign-client@npm:2.17.1" +"@walletconnect/sign-client@npm:2.18.1": + version: 2.18.1 + resolution: "@walletconnect/sign-client@npm:2.18.1" dependencies: - "@walletconnect/core": 2.17.1 + "@walletconnect/core": 2.18.1 "@walletconnect/events": 1.0.1 "@walletconnect/heartbeat": 1.2.2 "@walletconnect/jsonrpc-utils": 1.0.8 "@walletconnect/logger": 2.1.2 "@walletconnect/time": 1.0.2 - "@walletconnect/types": 2.17.1 - "@walletconnect/utils": 2.17.1 + "@walletconnect/types": 2.18.1 + "@walletconnect/utils": 2.18.1 events: 3.3.0 - checksum: 055a0aa0d176592dec27d096244635b938c098c2f46ea8616c9e7f3fbfa27ecf68b19593c0576e91a74d49b1ced4da83f94813914e3e34eaad175ab96ba49e15 + checksum: ea5ffb710e191f3952ddfbcc941dec3b38cfcf5095ed67bf70d5b8f3a1142e959a31bc5d60241d4bdf6826e762a1f8656b05290ebf09aaebfc436be9e6e709b9 languageName: node linkType: hard @@ -4537,9 +4411,9 @@ __metadata: languageName: node linkType: hard -"@walletconnect/types@npm:2.17.1": - version: 2.17.1 - resolution: "@walletconnect/types@npm:2.17.1" +"@walletconnect/types@npm:2.18.1": + version: 2.18.1 + resolution: "@walletconnect/types@npm:2.18.1" dependencies: "@walletconnect/events": 1.0.1 "@walletconnect/heartbeat": 1.2.2 @@ -4547,35 +4421,32 @@ __metadata: "@walletconnect/keyvaluestorage": 1.1.1 "@walletconnect/logger": 2.1.2 events: 3.3.0 - checksum: 1cf6be908e825ba5b2a292a228f3223c32041fb5c76de6bac1aa3a898f702f917bf500bd6edca8b3e7bcc9303643a114680b7ce29cdefd82c0702e52ba0b3cf1 + checksum: a15f21c3da358ea8eaf785d44e2cc2f92759239f04294bd569e874b55be4404953123e74ec14aae111d65cf7b83569b549758dc85296e09037bb5a05dc9edfa2 languageName: node linkType: hard -"@walletconnect/utils@npm:2.17.1": - version: 2.17.1 - resolution: "@walletconnect/utils@npm:2.17.1" +"@walletconnect/utils@npm:2.18.1": + version: 2.18.1 + resolution: "@walletconnect/utils@npm:2.18.1" dependencies: - "@ethersproject/hash": 5.7.0 "@ethersproject/transactions": 5.7.0 - "@stablelib/chacha20poly1305": 1.0.1 - "@stablelib/hkdf": 1.0.1 - "@stablelib/random": 1.0.2 - "@stablelib/sha256": 1.0.1 - "@stablelib/x25519": 1.0.3 + "@noble/ciphers": 1.2.1 + "@noble/curves": 1.8.1 + "@noble/hashes": 1.7.1 "@walletconnect/jsonrpc-utils": 1.0.8 "@walletconnect/keyvaluestorage": 1.1.1 "@walletconnect/relay-api": 1.0.11 - "@walletconnect/relay-auth": 1.0.4 + "@walletconnect/relay-auth": 1.1.0 "@walletconnect/safe-json": 1.0.2 "@walletconnect/time": 1.0.2 - "@walletconnect/types": 2.17.1 + "@walletconnect/types": 2.18.1 "@walletconnect/window-getters": 1.0.1 "@walletconnect/window-metadata": 1.0.1 detect-browser: 5.3.0 - elliptic: 6.5.7 + elliptic: 6.6.1 query-string: 7.1.3 uint8arrays: 3.1.0 - checksum: 0e2c4c911308e198b0757914536f85464782c3abeab8caaa4e3516354c4f56b40bc83f44f427e0fa1a1b58730d4e30e9f59d310fc4fcead65b7ed92602d59f54 + checksum: 164e0d4cf5033bb43df235b7cdcd796e05f15c06260b6c01d8934883989754af80928ccbb7a5d77d902666e10cff2561107c411e29c833bf8807529b0a98bbb4 languageName: node linkType: hard @@ -5179,7 +5050,7 @@ __metadata: languageName: node linkType: hard -"base64-js@npm:^1.2.3, base64-js@npm:^1.3.1, base64-js@npm:^1.5.1": +"base64-js@npm:^1.1.2, base64-js@npm:^1.2.3, base64-js@npm:^1.3.1, base64-js@npm:^1.5.1": version: 1.5.1 resolution: "base64-js@npm:1.5.1" checksum: 669632eb3745404c2f822a18fc3a0122d2f9a7a13f7fb8b5823ee19d1d2ff9ee5b52c53367176ea4ad093c332fd5ab4bd0ebae5a8e27917a4105a4cfc86b1005 @@ -5292,6 +5163,15 @@ __metadata: languageName: node linkType: hard +"brotli@npm:^1.3.3": + version: 1.3.3 + resolution: "brotli@npm:1.3.3" + dependencies: + base64-js: ^1.1.2 + checksum: 2c97329f4ccb8e4332cedd2f63b85c2e15ffb305b1cbf046df86201434caf93cb7992ca73c0f7053b6a1417f595069ec7783c26e01510cefc10035a0f466e594 + languageName: node + linkType: hard + "browserslist@npm:^4.23.0, browserslist@npm:^4.23.1": version: 4.23.2 resolution: "browserslist@npm:4.23.2" @@ -11059,6 +10939,16 @@ __metadata: languageName: node linkType: hard +"react-native-linear-gradient@npm:^2.8.3": + version: 2.8.3 + resolution: "react-native-linear-gradient@npm:2.8.3" + peerDependencies: + react: "*" + react-native: "*" + checksum: f980d324e551bbc475c6406bdc5250a08242020cbe653412fa169bbdf51e28a502e225de105b4d696d6a1a1b733d44782469020f4936d8b3ce0e2c78e51cf58f + languageName: node + linkType: hard + "react-native-modal@npm:13.0.1": version: 13.0.1 resolution: "react-native-modal@npm:13.0.1" @@ -13126,7 +13016,7 @@ __metadata: "@json-rpc-tools/utils": 1.7.6 "@kangfenmao/react-native-minimizer": 1.0.4 "@react-native-async-storage/async-storage": 1.24.0 - "@react-native-clipboard/clipboard": 1.14.1 + "@react-native-clipboard/clipboard": 1.15.0 "@react-native-community/netinfo": 11.3.2 "@react-native/babel-preset": 0.74.85 "@react-native/eslint-config": 0.74.85 @@ -13138,12 +13028,12 @@ __metadata: "@react-navigation/native-stack": 6.10.1 "@react-navigation/stack": 6.4.1 "@reown/appkit-ui-react-native": 1.0.1 - "@reown/walletkit": 1.1.1 + "@reown/walletkit": 1.1.2-canary-ca-6 "@sentry/react-native": 6.4.0 "@types/lodash.clonedeep": ^4.5.9 "@types/react": ^18.2.6 "@types/react-test-renderer": ^18.0.0 - "@walletconnect/react-native-compat": 2.17.2 + "@walletconnect/react-native-compat": 2.18.1-canary-ca-5 babel-jest: ^29.6.3 babel-plugin-module-resolver: ^5.0.0 dayjs: 1.11.11 @@ -13162,6 +13052,7 @@ __metadata: react-native-dialog: 9.3.0 react-native-gesture-handler: 2.17.1 react-native-get-random-values: 1.11.0 + react-native-linear-gradient: ^2.8.3 react-native-modal: 13.0.1 react-native-permissions: 4.1.5 react-native-quick-base64: 2.1.2