diff --git a/packages/core-mobile/.env.example b/packages/core-mobile/.env.example index 9663edbc84..5daa31064d 100644 --- a/packages/core-mobile/.env.example +++ b/packages/core-mobile/.env.example @@ -49,4 +49,7 @@ DD_SITE= # public key and key id for analytics data encryption ANALYTICS_ENCRYPTION_KEY= -ANALYTICS_ENCRYPTION_KEY_ID= \ No newline at end of file +ANALYTICS_ENCRYPTION_KEY_ID= + +# required for gasless +GAS_STATION_URL= diff --git a/packages/core-mobile/__mocks__/react-native-config.js b/packages/core-mobile/__mocks__/react-native-config.js index 46c7f84d1e..3bfc57d85c 100644 --- a/packages/core-mobile/__mocks__/react-native-config.js +++ b/packages/core-mobile/__mocks__/react-native-config.js @@ -17,5 +17,6 @@ export default { ANALYTICS_ENCRYPTION_KEY: 'MOCK_ANALYTICS_ENCRYPTION_KEY', ANALYTICS_ENCRYPTION_KEY_ID: 'MOCK_ANALYTICS_ENCRYPTION_KEY_ID', GOOGLE_OAUTH_CLIENT_WEB_ID: 'MOCK_GOOGLE_OAUTH_CLIENT_WEB_ID', - GOOGLE_OAUTH_CLIENT_IOS_ID: 'MOCK_GOOGLE_OAUTH_CLIENT_IOS_ID' + GOOGLE_OAUTH_CLIENT_IOS_ID: 'MOCK_GOOGLE_OAUTH_CLIENT_IOS_ID', + GAS_STATION_URL: 'MOCK_GAS_STATION_URL' } diff --git a/packages/core-mobile/app/screens/rpc/components/v2/AlertBanner.tsx b/packages/core-mobile/app/screens/rpc/components/v2/AlertBanner.tsx index b3844fd3f0..1a5f610021 100644 --- a/packages/core-mobile/app/screens/rpc/components/v2/AlertBanner.tsx +++ b/packages/core-mobile/app/screens/rpc/components/v2/AlertBanner.tsx @@ -3,34 +3,54 @@ import { Alert, AlertType } from '@avalabs/vm-module-types' import InfoSVG from 'components/svg/InfoSVG' import React, { useMemo } from 'react' -const AlertBanner = ({ alert }: { alert: Alert }): JSX.Element | null => { +interface AlertBannerProps { + alert: Alert + customStyle?: { + borderColor?: string + backgroundColor?: string + iconColor?: string + } +} + +const AlertBanner = ({ + alert, + customStyle +}: AlertBannerProps): JSX.Element | null => { const { theme: { colors } } = useTheme() const textStyle = { color: '$black', fontSize: 13, lineHeight: 16 } const icon = useMemo(() => { + const iconColor = customStyle?.iconColor || colors.$black + if (alert.type === AlertType.DANGER) { - return + return } if (alert.type === AlertType.WARNING) { - return + return } - return - }, [alert, colors]) + return ( + + ) + }, [alert, colors, customStyle?.iconColor]) if (alert.type === AlertType.INFO) { return ( @@ -49,7 +69,8 @@ const AlertBanner = ({ alert }: { alert: Alert }): JSX.Element | null => { padding: 16, borderRadius: 8, backgroundColor: - alert.type === AlertType.DANGER ? '$dangerLight' : '$warningLight', + customStyle?.backgroundColor || + (alert.type === AlertType.DANGER ? '$dangerLight' : '$warningLight'), flexDirection: 'row', alignItems: 'center', gap: 12 diff --git a/packages/core-mobile/app/screens/rpc/components/v2/ApprovalPopup.tsx b/packages/core-mobile/app/screens/rpc/components/v2/ApprovalPopup.tsx index af562a0e14..a3c07dfb3e 100644 --- a/packages/core-mobile/app/screens/rpc/components/v2/ApprovalPopup.tsx +++ b/packages/core-mobile/app/screens/rpc/components/v2/ApprovalPopup.tsx @@ -1,6 +1,11 @@ import React, { useCallback, useEffect, useMemo, useState } from 'react' import { ActivityIndicator, StyleSheet, ScrollView } from 'react-native' -import { TokenType } from '@avalabs/vm-module-types' +import { + Alert, + AlertType, + SigningData_EthSendTx, + TokenType +} from '@avalabs/vm-module-types' import { Space } from 'components/Space' import { Row } from 'components/Row' import NetworkFeeSelector from 'components/NetworkFeeSelector' @@ -10,7 +15,10 @@ import { useNavigation, useRoute } from '@react-navigation/native' import { useSelector } from 'react-redux' import { NetworkLogo } from 'screens/network/NetworkLogo' import { Button, Text, View, useTheme } from '@avalabs/k2-mobile' -import { selectIsSeedlessSigningBlocked } from 'store/posthog' +import { + selectIsGaslessBlocked, + selectIsSeedlessSigningBlocked +} from 'store/posthog' import FeatureBlocked from 'screens/posthog/FeatureBlocked' import { Eip1559Fees } from 'utils/Utils' import WalletConnectService from 'services/walletconnectv2/WalletConnectService' @@ -20,7 +28,6 @@ import { selectAccountByIndex, selectActiveAccount } from 'store/account/slice' -import Logger from 'utils/Logger' import TokenAddress from 'components/TokenAddress' import { isInAppRequest } from 'store/rpc/utils/isInAppRequest' import { isAccountApproved } from 'store/rpc/utils/isAccountApproved/isAccountApproved' @@ -30,12 +37,19 @@ import GlobeSVG from 'components/svg/GlobeSVG' import { useSpendLimits } from 'hooks/useSpendLimits' import { isHex } from 'viem' import { getChainIdFromCaip2 } from 'utils/caip2ChainIds' +import Switch from 'components/Switch' +import GaslessService from 'services/gasless/GaslessService' +import Logger from 'utils/Logger' +import { SendErrorMessage } from 'screens/send/utils/types' +import { useNativeTokenWithBalance } from 'screens/send/hooks/useNativeTokenWithBalance' +import { Tooltip } from 'components/Tooltip' +import InfoSVG from 'components/svg/InfoSVG' +import { validateFee } from 'screens/send/utils/evm/validate' import RpcRequestBottomSheet from '../shared/RpcRequestBottomSheet' import { DetailSectionView } from '../shared/DetailSectionView' import BalanceChange from './BalanceChange' import { SpendLimits } from './SpendLimits' import AlertBanner from './AlertBanner' - type ApprovalPopupScreenProps = WalletScreenProps< typeof AppNavigation.Modal.ApprovalPopup > @@ -50,6 +64,30 @@ const ApprovalPopup = (): JSX.Element => { const caip2ChainId = request.chainId const chainId = getChainIdFromCaip2(caip2ChainId) const network = getNetwork(chainId) + const [isGaslessEligible, setIsGaslessEligible] = useState(false) + const [gaslessEnabled, setGaslessEnabled] = useState(false) + const isGaslessBlocked = useSelector(selectIsGaslessBlocked) + const [amountError, setAmountError] = useState() + const nativeToken = useNativeTokenWithBalance() + const [gaslessError, setGaslessError] = useState(null) + + useEffect(() => { + const checkGaslessEligibility = async (): Promise => { + if (!chainId) { + setIsGaslessEligible(false) + return + } + const isEligible = await GaslessService.isEligibleForChain( + chainId.toString() + ).catch(err => { + Logger.error('Error checking gasless eligibility', err) + return false + }) + Logger.info('ApprovalPopup: Gasless eligibility', isEligible) + setIsGaslessEligible(isEligible) + } + checkGaslessEligibility() + }, [chainId, request.chainId]) const accountSelector = 'account' in signingData @@ -74,7 +112,8 @@ const ApprovalPopup = (): JSX.Element => { !account || (displayData.networkFeeSelector && maxFeePerGas === undefined) || (displayData.networkFeeSelector && maxPriorityFeePerGas === undefined) || - submitting + submitting || + amountError !== undefined const showNetworkFeeSelector = displayData.networkFeeSelector @@ -132,23 +171,73 @@ const ApprovalPopup = (): JSX.Element => { setMaxPriorityFeePerGas(fees.maxPriorityFeePerGas) }, []) + const handleGaslessTx = async ( + addressFrom: string + ): Promise => { + let attempts = 0 + const MAX_ATTEMPTS = 1 + + while (attempts <= MAX_ATTEMPTS) { + const result = await GaslessService.fundTx( + signingData as SigningData_EthSendTx, + addressFrom + ) + + if (result.txHash) { + setGaslessError(null) + return result.txHash + } + + // Show error and stop if we get a DO_NOT_RETRY error or + // if we've hit max attempts with a RETRY_WITH_NEW_CHALLENGE error + if ( + result.error?.category === 'DO_NOT_RETRY' || + (result.error?.category === 'RETRY_WITH_NEW_CHALLENGE' && + attempts === MAX_ATTEMPTS) + ) { + setGaslessError({ + type: AlertType.INFO, + details: { + title: 'Free Gas Error', + description: + 'Core was unable to fund the gas. You will need to pay the gas fee to continue with this transaction. ' + } + }) + setSubmitting(false) + return undefined + } + + attempts++ + } + return undefined + } + const onHandleApprove = async (): Promise => { if (approveDisabled) return - setSubmitting(true) - onApprove({ - network, - account, - maxFeePerGas, - maxPriorityFeePerGas, - overrideData: hashedCustomSpend - }) - .catch(Logger.error) - .finally(() => { + if (gaslessEnabled) { + const txHash = await handleGaslessTx(account.addressC) + if (!txHash) { setSubmitting(false) - goBack() + return + } + } + + try { + await onApprove({ + network, + account, + maxFeePerGas, + maxPriorityFeePerGas, + overrideData: hashedCustomSpend }) + goBack() + } catch (error: unknown) { + Logger.error('Error approving transaction', error) + } finally { + setSubmitting(false) + } } const renderAlert = (): JSX.Element | null => { @@ -161,6 +250,22 @@ const ApprovalPopup = (): JSX.Element => { ) } + const renderGaslessAlert = (): JSX.Element | null => { + if (!gaslessError) return null + return ( + + + + ) + } + const renderDappInfo = (): JSX.Element | null => { if (!displayData.dAppInfo) return null @@ -331,7 +436,37 @@ const ApprovalPopup = (): JSX.Element => { return } + const renderGasless = (): JSX.Element | null => { + if (!isGaslessEligible || isGaslessBlocked || gaslessError) { + return null + } + return ( + + + Get Free Gas + + } + /> + + setGaslessEnabled(prevState => !prevState)} + /> + + ) + } + const renderNetworkFeeSelector = (): JSX.Element | null => { + if (gaslessEnabled && isGaslessEligible) return null if (!showNetworkFeeSelector || !chainId) return null let gasLimit: number | undefined @@ -368,6 +503,46 @@ const ApprovalPopup = (): JSX.Element => { ) } + const validateEthSendTransaction = useCallback(() => { + if ( + !signingData || + !network?.networkToken || + !nativeToken || + signingData.type !== 'eth_sendTransaction' + ) + return + const ethSendTx = signingData.data + + try { + const gasLimit = ethSendTx.gasLimit ? BigInt(ethSendTx.gasLimit) : 0n + const amount = ethSendTx.value ? BigInt(ethSendTx.value) : 0n + + validateFee({ + gasLimit, + maxFee: maxFeePerGas || 0n, + amount, + nativeToken, + token: nativeToken + }) + + setAmountError(undefined) + } catch (err) { + if (err instanceof Error) { + setAmountError(err.message) + } else { + setAmountError(SendErrorMessage.UNKNOWN_ERROR) + } + } + }, [signingData, network, maxFeePerGas, nativeToken]) + + useEffect(() => { + if (gaslessEnabled) { + setAmountError(undefined) + return + } + validateEthSendTransaction() + }, [validateEthSendTransaction, gaslessEnabled]) + return ( <> { {displayData.title} {renderAlert()} + {renderGaslessAlert()} {renderDappInfo()} {renderNetwork()} @@ -387,8 +563,20 @@ const ApprovalPopup = (): JSX.Element => { {renderDetails()} {renderSpendLimits()} {renderBalanceChange()} + {renderGasless()} {renderNetworkFeeSelector()} {renderDisclaimer()} + {amountError && ( + + {amountError} + + )} {renderApproveRejectButtons()} diff --git a/packages/core-mobile/app/screens/send/hooks/useEVMSend.ts b/packages/core-mobile/app/screens/send/hooks/useEVMSend.ts index 15db021d23..39cda4d435 100644 --- a/packages/core-mobile/app/screens/send/hooks/useEVMSend.ts +++ b/packages/core-mobile/app/screens/send/hooks/useEVMSend.ts @@ -6,6 +6,8 @@ import { assertNotUndefined } from 'utils/assertions' import { useEVMProvider } from 'hooks/networks/networkProviderHooks' import { bigIntToString } from '@avalabs/core-utils-sdk' import Logger from 'utils/Logger' +import { selectIsGaslessBlocked } from 'store/posthog' +import { useSelector } from 'react-redux' import { SendAdapterEVM, SendErrorMessage } from '../utils/types' import { send as sendEVM } from '../utils/evm/send' import { getGasLimit } from '../utils/evm/getGasLimit' @@ -14,6 +16,7 @@ import { validateERC1155, validateERC721, validateAmount, + validateFee, validateGasLimit, validateSupportedToken } from '../utils/evm/validate' @@ -36,6 +39,7 @@ const useEVMSend: SendAdapterEVM = ({ canValidate } = useSendContext() const provider = useEVMProvider(network) + const isGaslessBlocked = useSelector(selectIsGaslessBlocked) const send = useCallback(async () => { try { @@ -71,12 +75,19 @@ const useEVMSend: SendAdapterEVM = ({ const handleError = useCallback( (err: unknown) => { if (err instanceof Error) { + if ( + !isGaslessBlocked && + err.message === SendErrorMessage.INSUFFICIENT_BALANCE_FOR_FEE + ) { + setError(undefined) + return + } setError(err.message) } else { setError(SendErrorMessage.UNKNOWN_ERROR) } }, - [setError] + [setError, isGaslessBlocked] ) const validate = useCallback(async () => { @@ -109,11 +120,15 @@ const useEVMSend: SendAdapterEVM = ({ token.type === TokenType.ERC20 ) { validateAmount({ - gasLimit, amount: amount?.bn, - token, + token + }) + validateFee({ + gasLimit, maxFee, - nativeToken + amount: amount?.bn, + nativeToken, + token }) } diff --git a/packages/core-mobile/app/screens/send/utils/evm/validate.test.ts b/packages/core-mobile/app/screens/send/utils/evm/validate.test.ts index 6eeb4200df..b42b4f5804 100644 --- a/packages/core-mobile/app/screens/send/utils/evm/validate.test.ts +++ b/packages/core-mobile/app/screens/send/utils/evm/validate.test.ts @@ -14,7 +14,8 @@ import { validateBasicInputs, validateERC1155, validateERC721, - validateSupportedToken + validateSupportedToken, + validateFee } from './validate' const tokenWithBalance: NativeTokenBalance = { @@ -180,34 +181,35 @@ describe('validate evm send', () => { it('should succeed when all requirements met', async () => { validateAmount({ - gasLimit: 1n, amount: 10n, - token: mockNativeTokenWithBalance, + token: mockNativeTokenWithBalance + }) + validateFee({ + gasLimit: 1n, maxFee: 1n, - nativeToken: mockNativeTokenWithBalance + amount: 10n, + nativeToken: mockNativeTokenWithBalance, + token: mockNativeTokenWithBalance }) }) it('should fail when amount is greater than token balance', async () => { expect(() => validateAmount({ - gasLimit: 1n, amount: 10000n, - token: mockNativeTokenWithBalance, - maxFee: 1n, - nativeToken: mockNativeTokenWithBalance + token: mockNativeTokenWithBalance }) ).toThrow(SendErrorMessage.INSUFFICIENT_BALANCE) }) it('should fail when totalFee is greater than remaining balance', async () => { expect(() => - validateAmount({ + validateFee({ gasLimit: 10n, - amount: 1000n, - token: mockNativeTokenWithBalance, maxFee: 10n, - nativeToken: mockNativeTokenWithBalance + amount: 1000n, + nativeToken: mockNativeTokenWithBalance, + token: mockNativeTokenWithBalance }) ).toThrow(SendErrorMessage.INSUFFICIENT_BALANCE_FOR_FEE) }) @@ -215,11 +217,8 @@ describe('validate evm send', () => { it('should fail when amount is 0', async () => { expect(() => validateAmount({ - gasLimit: 1n, amount: 0n, - token: mockNativeTokenWithBalance, - maxFee: 1n, - nativeToken: mockNativeTokenWithBalance + token: mockNativeTokenWithBalance }) ).toThrow(SendErrorMessage.AMOUNT_REQUIRED) }) @@ -237,22 +236,23 @@ describe('validate evm send', () => { it('should succeed when all requirements met', async () => { validateAmount({ - gasLimit: 1n, amount: 10n, - token: mockERC20TokenWithBalance, + token: mockERC20TokenWithBalance + }) + validateFee({ + gasLimit: 1n, maxFee: 1n, - nativeToken: mockNativeTokenWithBalance + amount: 10n, + nativeToken: mockNativeTokenWithBalance, + token: mockERC20TokenWithBalance }) }) it('should fail when amount is greater than token balance', async () => { expect(() => validateAmount({ - gasLimit: 1n, amount: 10000n, - token: mockERC20TokenWithBalance, - maxFee: 1n, - nativeToken: mockNativeTokenWithBalance + token: mockERC20TokenWithBalance }) ).toThrow(SendErrorMessage.INSUFFICIENT_BALANCE) }) @@ -260,11 +260,8 @@ describe('validate evm send', () => { it('should fail when amount is 0', async () => { expect(() => validateAmount({ - gasLimit: 1n, amount: 0n, - token: mockERC20TokenWithBalance, - maxFee: 1n, - nativeToken: mockNativeTokenWithBalance + token: mockERC20TokenWithBalance }) ).toThrow(SendErrorMessage.AMOUNT_REQUIRED) }) diff --git a/packages/core-mobile/app/screens/send/utils/evm/validate.ts b/packages/core-mobile/app/screens/send/utils/evm/validate.ts index a559de2ef3..1566e4f226 100644 --- a/packages/core-mobile/app/screens/send/utils/evm/validate.ts +++ b/packages/core-mobile/app/screens/send/utils/evm/validate.ts @@ -40,32 +40,40 @@ export const validateERC1155 = ( } export const validateAmount = ({ - gasLimit, amount, - token, - maxFee, - nativeToken + token }: { - gasLimit: bigint amount: bigint | undefined token: TokenWithBalanceERC20 | NetworkTokenWithBalance - maxFee: bigint - nativeToken: NetworkTokenWithBalance }): void => { if (amount && token.balance < amount) { throw new Error(SendErrorMessage.INSUFFICIENT_BALANCE) } + if (!amount || (amount && amount <= 0n)) { + throw new Error(SendErrorMessage.AMOUNT_REQUIRED) + } +} + +export const validateFee = ({ + gasLimit, + maxFee, + amount, + nativeToken, + token +}: { + gasLimit: bigint + maxFee: bigint + amount: bigint | undefined + nativeToken: NetworkTokenWithBalance + token: TokenWithBalanceEVM +}): void => { const totalFee = gasLimit * maxFee const remainingBalance = nativeToken.balance - (amount ?? 0n) if (token.type === TokenType.NATIVE && remainingBalance < totalFee) { throw new Error(SendErrorMessage.INSUFFICIENT_BALANCE_FOR_FEE) } - - if (!amount || (amount && amount <= 0n)) { - throw new Error(SendErrorMessage.AMOUNT_REQUIRED) - } } export const validateGasLimit = (gasLimit: bigint): void => { diff --git a/packages/core-mobile/app/services/gasless/GaslessService.ts b/packages/core-mobile/app/services/gasless/GaslessService.ts new file mode 100644 index 0000000000..2cb486627f --- /dev/null +++ b/packages/core-mobile/app/services/gasless/GaslessService.ts @@ -0,0 +1,67 @@ +import { FundResult, GaslessSdk } from '@avalabs/core-gasless-sdk' +import { SigningData_EthSendTx } from '@avalabs/vm-module-types' +import Config from 'react-native-config' +import Logger from 'utils/Logger' +import AppCheckService from 'services/fcm/AppCheckService' +import { Transaction, TransactionLike } from 'ethers' + +if (!Config.GAS_STATION_URL) { + Logger.warn( + 'GAS_STATION_URL is missing. Gasless service may not work properly.' + ) +} + +class GaslessService { + private sdk: GaslessSdk | null = null + + constructor() { + if (Config.GAS_STATION_URL) { + this.sdk = new GaslessSdk(Config.GAS_STATION_URL) + } + } + + private getSdk = async (): Promise => { + if (!this.sdk) { + return null + } + const appCheckToken = (await AppCheckService.getToken()).token + this.sdk.setAppCheckToken(appCheckToken) + return this.sdk + } + + isEligibleForChain = async (chainId: string): Promise => { + const sdk = await this.getSdk() + if (!sdk) return false + return await sdk.isEligibleForChain({ chainId }) + } + + fundTx = async ( + signingData: SigningData_EthSendTx, + addressFrom: string + ): Promise => { + const sdk = await this.getSdk() + if (!sdk) { + return { + error: { + category: 'DO_NOT_RETRY', + message: 'INTERNAL_ERROR' + } + } + } + + const { difficulty, challengeHex } = await sdk.fetchChallenge() + const { solutionHex } = await sdk.solveChallenge(challengeHex, difficulty) + const txHex = Transaction.from({ + ...signingData.data, + from: null + } as TransactionLike).unsignedSerialized + return await sdk.fundTx({ + challengeHex, + solutionHex, + txHex, + from: addressFrom + }) + } +} + +export default new GaslessService() diff --git a/packages/core-mobile/app/services/posthog/types.ts b/packages/core-mobile/app/services/posthog/types.ts index a53b0331db..28bb4a7a9c 100644 --- a/packages/core-mobile/app/services/posthog/types.ts +++ b/packages/core-mobile/app/services/posthog/types.ts @@ -33,7 +33,8 @@ export enum FeatureGates { BLOCKAID_DAPP_SCAN = 'blockaid-dapp-scan', ALL_NOTIFICATIONS = 'all-notifications', ENABLE_NOTIFICATION_PROMPT = 'enable-notification-prompt', - HALLIDAY_BRIDGE_BANNER = 'halliday-bridge-banner' + HALLIDAY_BRIDGE_BANNER = 'halliday-bridge-banner', + GASLESS = 'gasless-feature' } export enum FeatureVars { diff --git a/packages/core-mobile/app/store/posthog/slice.ts b/packages/core-mobile/app/store/posthog/slice.ts index bdda349fce..a5440c0bd8 100644 --- a/packages/core-mobile/app/store/posthog/slice.ts +++ b/packages/core-mobile/app/store/posthog/slice.ts @@ -334,6 +334,14 @@ export const selectIsHallidayBridgeBannerBlocked = ( ) } +export const selectIsGaslessBlocked = (state: RootState): boolean => { + const { featureFlags } = state.posthog + return ( + !featureFlags[FeatureGates.GASLESS] || + !featureFlags[FeatureGates.EVERYTHING] + ) +} + // actions export const { regenerateUserId, toggleAnalytics, setFeatureFlags } = posthogSlice.actions diff --git a/packages/core-mobile/app/store/posthog/types.ts b/packages/core-mobile/app/store/posthog/types.ts index 9a839db8fd..f99131d231 100644 --- a/packages/core-mobile/app/store/posthog/types.ts +++ b/packages/core-mobile/app/store/posthog/types.ts @@ -37,7 +37,8 @@ export const DefaultFeatureFlagConfig = { [FeatureGates.UNIFIED_BRIDGE_AB_EVM]: true, [FeatureGates.UNIFIED_BRIDGE_AB_AVA_TO_BTC]: true, [FeatureGates.UNIFIED_BRIDGE_AB_BTC_TO_AVA]: true, - [FeatureGates.HALLIDAY_BRIDGE_BANNER]: true + [FeatureGates.HALLIDAY_BRIDGE_BANNER]: true, + [FeatureGates.GASLESS]: true } export const initialState = { diff --git a/packages/core-mobile/docs/features.md b/packages/core-mobile/docs/features.md index 7b27a2ee59..4370557e3a 100644 --- a/packages/core-mobile/docs/features.md +++ b/packages/core-mobile/docs/features.md @@ -21,7 +21,7 @@ - Transaction Validation + Simulation (Blockaid) - PROXY_URL - In app browser (Token purchase, Suggested dApp list) - - PROXY_URL + - PROXY_URL - COINBASE_APP_ID - DeFi Asset Balances - PROXY_URL @@ -43,4 +43,5 @@ - C-Chain Balance notifications - APPCHECK_DEBUG_TOKEN - NOTIFICATION_SENDER_API_URL - +- Gasless + - GAS_STATION_URL diff --git a/packages/core-mobile/package.json b/packages/core-mobile/package.json index c6039f36a7..1211006fe7 100644 --- a/packages/core-mobile/package.json +++ b/packages/core-mobile/package.json @@ -1,325 +1,326 @@ { - "name": "@avalabs/core-mobile", - "private": true, - "license": "Limited Ecosystem License", - "scripts": { - "setup": "yarn allow-scripts", - "envs": "./scripts/getEnvs.sh && ./scripts/getGoogleServices.sh", - "android": "ENVFILE=.env.development react-native run-android --mode=internalDebug", - "podInstall": "bundle _2.1.4_ install && cd ios && bundle exec pod install", - "ios": "ENVFILE=.env.development react-native run-ios", - "start": "react-native start", - "test": "jest", - "tsc": "tsc -p tsconfig.test.json", - "lint": "eslint .", - "clean": "./scripts/clean", - "postinstall": "node ${PROJECT_CWD}/scripts/generate-metro-monorepo-config.js; node_modules/.bin/patch-package; node_modules/.bin/rn-nodeify --install events,stream,vm,assert,https,http,os,zlib,path,fs --hack; yarn run gen:contracts", - "storybook-generate": "sb-rn-get-stories --v6-store", - "storybook-watch": "sb-rn-watcher", - "gen:contracts": "typechain --target=ethers-v6 --out-dir app/contracts/openzeppelin ./node_modules/@openzeppelin/contracts/build/contracts/ERC20.json ./node_modules/@openzeppelin/contracts/build/contracts/ERC721.json ./node_modules/@openzeppelin/contracts/build/contracts/ERC1155.json", - "gen:glacierApi": "npx openapi-zod-client 'https://glacier-api-dev.avax.network/api-json' -o './app/utils/network/glacierApi.client.ts'" - }, - "dependencies": { - "@avalabs/avalanche-module": "1.4.3", - "@avalabs/avalanchejs": "4.2.0-alpha.1", - "@avalabs/bitcoin-module": "1.4.3", - "@avalabs/bridge-unified": "4.0.1", - "@avalabs/core-bridge-sdk": "3.1.0-alpha.34", - "@avalabs/core-chains-sdk": "3.1.0-alpha.34", - "@avalabs/core-coingecko-sdk": "3.1.0-alpha.34", - "@avalabs/core-utils-sdk": "3.1.0-alpha.34", - "@avalabs/core-wallets-sdk": "3.1.0-alpha.34", - "@avalabs/evm-module": "1.4.3", - "@avalabs/glacier-sdk": "3.1.0-alpha.34", - "@avalabs/k2-alpine": "workspace:*", - "@avalabs/k2-mobile": "workspace:*", - "@avalabs/types": "3.1.0-alpha.34", - "@avalabs/vm-module-types": "1.4.3", - "@blockaid/client": "0.27.4", - "@coinbase/cbpay-js": "2.2.1", - "@cubist-labs/cubesigner-sdk": "0.4.117-0", - "@cubist-labs/cubesigner-sdk-ethers-v6": "0.4.117-0", - "@datadog/mobile-react-native": "2.4.3", - "@datadog/mobile-react-navigation": "2.4.3", - "@date-fns/utc": "2.1.0", - "@ethereumjs/common": "4.4.0", - "@ethereumjs/tx": "5.4.0", - "@gorhom/bottom-sheet": "4.6.4", - "@hookform/resolvers": "3.9.0", - "@invertase/react-native-apple-authentication": "2.4.0", - "@lavamoat/preinstall-always-fail": "2.1.0", - "@metamask/eth-sig-util": "7.0.3", - "@metamask/rpc-errors": "6.3.0", - "@noble/secp256k1": "2.1.0", - "@notifee/react-native": "9.1.1", - "@openzeppelin/contracts": "5.0.2", - "@paraswap/sdk": "7.2.1", - "@react-native-async-storage/async-storage": "2.0.0", - "@react-native-clipboard/clipboard": "1.14.2", - "@react-native-community/blur": "4.4.1", - "@react-native-community/datetimepicker": "8.2.0", - "@react-native-community/netinfo": "11.4.1", - "@react-native-community/slider": "4.5.3", - "@react-native-firebase/app": "21.0.0", - "@react-native-firebase/app-check": "21.0.0", - "@react-native-firebase/messaging": "21.0.0", - "@react-native-google-signin/google-signin": "13.1.0", - "@react-native-masked-view/masked-view": "0.3.0", - "@react-native-menu/menu": "1.1.3", - "@react-navigation/bottom-tabs": "6.5.20", - "@react-navigation/drawer": "6.7.2", - "@react-navigation/elements": "1.3.31", - "@react-navigation/native": "6.1.18", - "@react-navigation/native-stack": "6.11.0", - "@react-navigation/stack": "6.4.1", - "@reduxjs/toolkit": "1.8.1", - "@reown/walletkit": "^1.0.0", - "@sentry/react-native": "5.33.2", - "@shopify/flash-list": "1.7.1", - "@shopify/react-native-performance": "4.1.2", - "@shopify/react-native-skia": "0.1.233", - "@tanstack/query-sync-storage-persister": "5.59.6", - "@tanstack/react-query": "5.59.8", - "@tanstack/react-query-persist-client": "5.59.6", - "@tradle/react-native-http": "2.0.1", - "@walletconnect/react-native-compat": "2.11.0", - "@walletconnect/types": "2.17.2", - "@walletconnect/utils": "2.17.2", - "@zodios/core": "10.9.6", - "assert": "2.1.0", - "asyncstorage-down": "4.2.0", - "axios": "1.7.7", - "base-64": "1.0.0", - "big.js": "6.2.2", - "bip174": "2.1.0", - "bip39": "3.0.4", - "bitcoinjs-lib": "5.2.0", - "bn.js": "5.2.1", - "browserify-zlib": "0.2.0", - "camelcase-keys": "9.1.3", - "coinselect": "3.1.13", - "crypto-browserify": "3.12.0", - "date-fns": "4.1.0", - "deprecated-react-native-prop-types": "5.0.0", - "es6-promise": "4.2.8", - "ethers": "6.8.1", - "events": "3.3.0", - "expo": "50.0.21", - "expo-blur": "12.9.2", - "expo-constants": "15.4.6", - "expo-image": "1.10.6", - "expo-linear-gradient": "12.7.2", - "expo-linking": "6.2.2", - "expo-router": "3.4.10", - "expo-status-bar": "1.11.1", - "https-browserify": "1.0.0", - "jail-monkey": "2.8.0", - "jimp": "1.6.0", - "jsc-android": "294992.0.0", - "lodash.debounce": "4.0.8", - "lodash.isempty": "4.4.0", - "lodash.isstring": "4.0.1", - "lodash.merge": "4.6.2", - "lottie-react-native": "7.0.0", - "moment": "2.30.1", - "node-cache": "5.1.2", - "path-browserify": "1.0.1", - "qrcode-reader": "1.0.4", - "react": "18.3.1", - "react-content-loader": "6.2.0", - "react-hook-form": "7.53.0", - "react-native": "0.73.7", - "react-native-aes-crypto": "1.3.10", - "react-native-argon2": "2.0.1", - "react-native-big-list": "1.6.1", - "react-native-bootsplash": "6.1.4", - "react-native-camera": "4.2.1", - "react-native-chart-kit": "6.12.0", - "react-native-circular-progress": "1.4.0", - "react-native-collapsible": "1.6.2", - "react-native-collapsible-tab-view": "8.0.0", - "react-native-config": "1.5.3", - "react-native-device-info": "13.0.0", - "react-native-fs": "2.20.0", - "react-native-gesture-handler": "2.20.0", - "react-native-graph": "1.1.0", - "react-native-haptic-feedback": "2.0.3", - "react-native-inappbrowser-reborn": "3.7.0", - "react-native-keychain": "8.1.1", - "react-native-level-fs": "3.0.1", - "react-native-localize": "3.2.1", - "react-native-mmkv": "2.12.2", - "react-native-modal-datetime-picker": "18.0.0", - "react-native-os": "1.2.6", - "react-native-pager-view": "6.4.1", - "react-native-passkey": "3.1.0", - "react-native-performance": "5.1.2", - "react-native-permissions": "4.1.5", - "react-native-popable": "0.4.3", - "react-native-popover-view": "6.1.0", - "react-native-qrcode-scanner": "1.5.5", - "react-native-qrcode-svg": "6.3.2", - "react-native-quick-base64": "2.1.2", - "react-native-quick-crypto": "0.6.1", - "react-native-reanimated": "3.6.2", - "react-native-redash": "18.1.3", - "react-native-restart": "0.0.27", - "react-native-root-siblings": "5.0.1", - "react-native-safe-area-context": "4.11.0", - "react-native-screens": "3.34.0", - "react-native-sensors": "7.3.6", - "react-native-sound": "0.11.2", - "react-native-svg": "15.7.1", - "react-native-tab-view": "3.5.1", - "react-native-toast-notifications": "3.4.0", - "react-native-url-polyfill": "2.0.0", - "react-native-view-shot": "3.8.0", - "react-native-webview": "ava-labs/react-native-webview", - "react-native-webview-crypto": "0.0.26", - "react-redux": "9.1.2", - "react-timer-hook": "3.0.7", - "readable-stream": "4.5.2", - "redux-persist": "6.0.0", - "redux-persist-transform-encrypt": "4.0.0", - "rn-dominant-color": "1.7.2", - "rn-nodeify": "10.3.0", - "rxjs": "7.8.1", - "semver": "7.5.4", - "stream-browserify": "3.0.0", - "text-encoding": "0.7.0", - "type-fest": "4.26.1", - "url": "0.11.4", - "viem": "2.21.21", - "vm-browserify": "1.1.2", - "web3": "1.7.5", - "xss": "1.0.15", - "zod": "3.23.8" - }, - "devDependencies": { - "@avalabs/tsconfig-mobile": "workspace:*", - "@babel/core": "7.25.7", - "@babel/plugin-proposal-nullish-coalescing-operator": "7.18.6", - "@babel/plugin-syntax-object-rest-spread": "7.8.3", - "@babel/plugin-transform-class-static-block": "7.25.7", - "@babel/plugin-transform-export-namespace-from": "7.25.7", - "@babel/plugin-transform-private-methods": "7.25.7", - "@babel/preset-env": "7.25.7", - "@babel/preset-typescript": "7.25.7", - "@babel/runtime": "7.25.7", - "@dlenroc/testrail": "1.9.1", - "@lavamoat/allow-scripts": "3.2.1", - "@playwright/test": "1.48.0", - "@react-native/babel-preset": "0.73.21", - "@react-native/metro-config": "0.73.5", - "@rushstack/eslint-patch": "1.10.4", - "@spotlightjs/spotlight": "2.5.0", - "@storybook/addon-ondevice-actions": "7.6.20", - "@storybook/addon-ondevice-backgrounds": "7.6.20", - "@storybook/addon-ondevice-controls": "7.6.20", - "@storybook/react-native": "7.6.20", - "@typechain/ethers-v6": "0.5.1", - "@types/big.js": "6.2.2", - "@types/bn.js": "5.1.6", - "@types/d3": "7.4.3", - "@types/jest": "29.5.13", - "@types/lodash.debounce": "4.0.9", - "@types/lodash.isempty": "4.4.9", - "@types/lodash.isstring": "4.0.9", - "@types/numeral": "2.0.5", - "@types/react": "18.3.11", - "@types/react-dom": "18.3.0", - "@types/react-test-renderer": "18.3.0", - "@types/semver": "7.5.4", - "@welldone-software/why-did-you-render": "8.0.3", - "babel-jest": "29.7.0", - "babel-loader": "9.2.1", - "babel-plugin-inline-dotenv": "1.7.0", - "babel-plugin-module-resolver": "5.0.2", - "babel-plugin-react-require": "4.0.3", - "detox": "20.27.2", - "eslint": "8.50.0", - "eslint-plugin-avalabs-mobile": "workspace:*", - "jest": "29.7.0", - "json-stringify-pretty-compact": "4.0.0", - "msw": "1.3.2", - "node-fetch": "3.3.2", - "patch-package": "8.0.0", - "playwright-extra": "4.3.6", - "postinstall-postinstall": "2.1.0", - "puppeteer-extra-plugin-stealth": "2.11.2", - "react-dom": "18.3.1", - "react-native-svg-transformer": "1.5.0", - "react-test-renderer": "18.3.1", - "reactotron-react-native": "5.1.8", - "reactotron-react-native-mmkv": "0.2.7", - "reactotron-redux": "3.1.10", - "ts-jest": "29.2.5", - "ts-node": "10.9.2", - "typechain": "8.3.2", - "typescript": "5.6.3" - }, - "engines": { - "node": ">=18.14.1", - "yarn": ">=3.6.4" - }, - "lavamoat": { - "allowScripts": { - "$root$": true, - "@avalabs/core-wallets-sdk>hdkey>secp256k1": false, - "@avalabs/evm-module": false, - "@avalabs/k2-mobile": false, - "@avalabs/k2-alpine": false, - "@datadog/mobile-react-native": false, - "@lavamoat/preinstall-always-fail": false, - "@sentry/react-native>@sentry/cli": false, - "@storybook/react-native>@storybook/core-common>esbuild": false, - "bitcoinjs-lib>tiny-secp256k1": false, - "detox": false, - "detox>bunyan>dtrace-provider": false, - "msw": false, - "postinstall-postinstall": false, - "react-native-bootsplash>sharp": false, - "react-native-inappbrowser-reborn": false, - "viem>ws>bufferutil": false, - "viem>ws>utf-8-validate": false, - "web3": false, - "web3>web3-bzz": false, - "web3>web3-core>web3-core-requestmanager>web3-providers-ws>websocket>es5-ext": false, - "web3>web3-shh": false, - "web3>web3-utils>ethereumjs-util>ethereum-cryptography>keccak": false, - "@react-native-firebase/app>firebase>@firebase/firestore>@grpc/proto-loader>protobufjs": false, - "@avalabs/vm-module-types>hypersdk-client>@metamask/sdk>eciesjs>secp256k1": false, - "web3>web3-core>web3-core-requestmanager>web3-providers-ws>websocket>bufferutil": false - } - }, - "react-native": { - "http": "@tradle/react-native-http", - "https": "https-browserify", - "os": "react-native-os", - "_stream_transform": "readable-stream/transform", - "_stream_readable": "readable-stream/readable", - "_stream_writable": "readable-stream/writable", - "_stream_duplex": "readable-stream/duplex", - "_stream_passthrough": "readable-stream/passthrough", - "stream": "stream-browserify", - "vm": "vm-browserify", - "zlib": "browserify-zlib", - "path": "path-browserify", - "fs": "react-native-level-fs" - }, - "browser": { - "_stream_duplex": "readable-stream/duplex", - "_stream_passthrough": "readable-stream/passthrough", - "_stream_readable": "readable-stream/readable", - "_stream_transform": "readable-stream/transform", - "_stream_writable": "readable-stream/writable", - "fs": "react-native-level-fs", - "http": "@tradle/react-native-http", - "https": "https-browserify", - "os": "react-native-os", - "path": "path-browserify", - "stream": "stream-browserify", - "vm": "vm-browserify", - "zlib": "browserify-zlib" + "name": "@avalabs/core-mobile", + "private": true, + "license": "Limited Ecosystem License", + "scripts": { + "setup": "yarn allow-scripts", + "envs": "./scripts/getEnvs.sh && ./scripts/getGoogleServices.sh", + "android": "ENVFILE=.env.development react-native run-android --mode=internalDebug", + "podInstall": "bundle _2.1.4_ install && cd ios && bundle exec pod install", + "ios": "ENVFILE=.env.development react-native run-ios", + "start": "react-native start", + "test": "jest", + "tsc": "tsc -p tsconfig.test.json", + "lint": "eslint .", + "clean": "./scripts/clean", + "postinstall": "node ${PROJECT_CWD}/scripts/generate-metro-monorepo-config.js; node_modules/.bin/patch-package; node_modules/.bin/rn-nodeify --install events,stream,vm,assert,https,http,os,zlib,path,fs --hack; yarn run gen:contracts", + "storybook-generate": "sb-rn-get-stories --v6-store", + "storybook-watch": "sb-rn-watcher", + "gen:contracts": "typechain --target=ethers-v6 --out-dir app/contracts/openzeppelin ./node_modules/@openzeppelin/contracts/build/contracts/ERC20.json ./node_modules/@openzeppelin/contracts/build/contracts/ERC721.json ./node_modules/@openzeppelin/contracts/build/contracts/ERC1155.json", + "gen:glacierApi": "npx openapi-zod-client 'https://glacier-api-dev.avax.network/api-json' -o './app/utils/network/glacierApi.client.ts'" + }, + "dependencies": { + "@avalabs/avalanche-module": "1.4.3", + "@avalabs/avalanchejs": "4.2.0-alpha.1", + "@avalabs/bitcoin-module": "1.4.3", + "@avalabs/bridge-unified": "4.0.1", + "@avalabs/core-bridge-sdk": "3.1.0-alpha.34", + "@avalabs/core-chains-sdk": "3.1.0-alpha.34", + "@avalabs/core-coingecko-sdk": "3.1.0-alpha.34", + "@avalabs/core-gasless-sdk": "3.1.0-alpha.40", + "@avalabs/core-utils-sdk": "3.1.0-alpha.34", + "@avalabs/core-wallets-sdk": "3.1.0-alpha.34", + "@avalabs/evm-module": "1.4.3", + "@avalabs/glacier-sdk": "3.1.0-alpha.34", + "@avalabs/k2-alpine": "workspace:*", + "@avalabs/k2-mobile": "workspace:*", + "@avalabs/types": "3.1.0-alpha.34", + "@avalabs/vm-module-types": "1.4.3", + "@blockaid/client": "0.27.4", + "@coinbase/cbpay-js": "2.2.1", + "@cubist-labs/cubesigner-sdk": "0.4.117-0", + "@cubist-labs/cubesigner-sdk-ethers-v6": "0.4.117-0", + "@datadog/mobile-react-native": "2.4.3", + "@datadog/mobile-react-navigation": "2.4.3", + "@date-fns/utc": "2.1.0", + "@ethereumjs/common": "4.4.0", + "@ethereumjs/tx": "5.4.0", + "@gorhom/bottom-sheet": "4.6.4", + "@hookform/resolvers": "3.9.0", + "@invertase/react-native-apple-authentication": "2.4.0", + "@lavamoat/preinstall-always-fail": "2.1.0", + "@metamask/eth-sig-util": "7.0.3", + "@metamask/rpc-errors": "6.3.0", + "@noble/secp256k1": "2.1.0", + "@notifee/react-native": "9.1.1", + "@openzeppelin/contracts": "5.0.2", + "@paraswap/sdk": "7.2.1", + "@react-native-async-storage/async-storage": "2.0.0", + "@react-native-clipboard/clipboard": "1.14.2", + "@react-native-community/blur": "4.4.1", + "@react-native-community/datetimepicker": "8.2.0", + "@react-native-community/netinfo": "11.4.1", + "@react-native-community/slider": "4.5.3", + "@react-native-firebase/app": "21.0.0", + "@react-native-firebase/app-check": "21.0.0", + "@react-native-firebase/messaging": "21.0.0", + "@react-native-google-signin/google-signin": "13.1.0", + "@react-native-masked-view/masked-view": "0.3.0", + "@react-native-menu/menu": "1.1.3", + "@react-navigation/bottom-tabs": "6.5.20", + "@react-navigation/drawer": "6.7.2", + "@react-navigation/elements": "1.3.31", + "@react-navigation/native": "6.1.18", + "@react-navigation/native-stack": "6.11.0", + "@react-navigation/stack": "6.4.1", + "@reduxjs/toolkit": "1.8.1", + "@reown/walletkit": "^1.0.0", + "@sentry/react-native": "5.33.2", + "@shopify/flash-list": "1.7.1", + "@shopify/react-native-performance": "4.1.2", + "@shopify/react-native-skia": "0.1.233", + "@tanstack/query-sync-storage-persister": "5.59.6", + "@tanstack/react-query": "5.59.8", + "@tanstack/react-query-persist-client": "5.59.6", + "@tradle/react-native-http": "2.0.1", + "@walletconnect/react-native-compat": "2.11.0", + "@walletconnect/types": "2.17.2", + "@walletconnect/utils": "2.17.2", + "@zodios/core": "10.9.6", + "assert": "2.1.0", + "asyncstorage-down": "4.2.0", + "axios": "1.7.7", + "base-64": "1.0.0", + "big.js": "6.2.2", + "bip174": "2.1.0", + "bip39": "3.0.4", + "bitcoinjs-lib": "5.2.0", + "bn.js": "5.2.1", + "browserify-zlib": "0.2.0", + "camelcase-keys": "9.1.3", + "coinselect": "3.1.13", + "crypto-browserify": "3.12.0", + "date-fns": "4.1.0", + "deprecated-react-native-prop-types": "5.0.0", + "es6-promise": "4.2.8", + "ethers": "6.8.1", + "events": "3.3.0", + "expo": "50.0.21", + "expo-blur": "12.9.2", + "expo-constants": "15.4.6", + "expo-image": "1.10.6", + "expo-linear-gradient": "12.7.2", + "expo-linking": "6.2.2", + "expo-router": "3.4.10", + "expo-status-bar": "1.11.1", + "https-browserify": "1.0.0", + "jail-monkey": "2.8.0", + "jimp": "1.6.0", + "jsc-android": "294992.0.0", + "lodash.debounce": "4.0.8", + "lodash.isempty": "4.4.0", + "lodash.isstring": "4.0.1", + "lodash.merge": "4.6.2", + "lottie-react-native": "7.0.0", + "moment": "2.30.1", + "node-cache": "5.1.2", + "path-browserify": "1.0.1", + "qrcode-reader": "1.0.4", + "react": "18.3.1", + "react-content-loader": "6.2.0", + "react-hook-form": "7.53.0", + "react-native": "0.73.7", + "react-native-aes-crypto": "1.3.10", + "react-native-argon2": "2.0.1", + "react-native-big-list": "1.6.1", + "react-native-bootsplash": "6.1.4", + "react-native-camera": "4.2.1", + "react-native-chart-kit": "6.12.0", + "react-native-circular-progress": "1.4.0", + "react-native-collapsible": "1.6.2", + "react-native-collapsible-tab-view": "8.0.0", + "react-native-config": "1.5.3", + "react-native-device-info": "13.0.0", + "react-native-fs": "2.20.0", + "react-native-gesture-handler": "2.20.0", + "react-native-graph": "1.1.0", + "react-native-haptic-feedback": "2.0.3", + "react-native-inappbrowser-reborn": "3.7.0", + "react-native-keychain": "8.1.1", + "react-native-level-fs": "3.0.1", + "react-native-localize": "3.2.1", + "react-native-mmkv": "2.12.2", + "react-native-modal-datetime-picker": "18.0.0", + "react-native-os": "1.2.6", + "react-native-pager-view": "6.4.1", + "react-native-passkey": "3.1.0", + "react-native-performance": "5.1.2", + "react-native-permissions": "4.1.5", + "react-native-popable": "0.4.3", + "react-native-popover-view": "6.1.0", + "react-native-qrcode-scanner": "1.5.5", + "react-native-qrcode-svg": "6.3.2", + "react-native-quick-base64": "2.1.2", + "react-native-quick-crypto": "0.6.1", + "react-native-reanimated": "3.6.2", + "react-native-redash": "18.1.3", + "react-native-restart": "0.0.27", + "react-native-root-siblings": "5.0.1", + "react-native-safe-area-context": "4.11.0", + "react-native-screens": "3.34.0", + "react-native-sensors": "7.3.6", + "react-native-sound": "0.11.2", + "react-native-svg": "15.7.1", + "react-native-tab-view": "3.5.1", + "react-native-toast-notifications": "3.4.0", + "react-native-url-polyfill": "2.0.0", + "react-native-view-shot": "3.8.0", + "react-native-webview": "ava-labs/react-native-webview", + "react-native-webview-crypto": "0.0.26", + "react-redux": "9.1.2", + "react-timer-hook": "3.0.7", + "readable-stream": "4.5.2", + "redux-persist": "6.0.0", + "redux-persist-transform-encrypt": "4.0.0", + "rn-dominant-color": "1.7.2", + "rn-nodeify": "10.3.0", + "rxjs": "7.8.1", + "semver": "7.5.4", + "stream-browserify": "3.0.0", + "text-encoding": "0.7.0", + "type-fest": "4.26.1", + "url": "0.11.4", + "viem": "2.21.21", + "vm-browserify": "1.1.2", + "web3": "1.7.5", + "xss": "1.0.15", + "zod": "3.23.8" + }, + "devDependencies": { + "@avalabs/tsconfig-mobile": "workspace:*", + "@babel/core": "7.25.7", + "@babel/plugin-proposal-nullish-coalescing-operator": "7.18.6", + "@babel/plugin-syntax-object-rest-spread": "7.8.3", + "@babel/plugin-transform-class-static-block": "7.25.7", + "@babel/plugin-transform-export-namespace-from": "7.25.7", + "@babel/plugin-transform-private-methods": "7.25.7", + "@babel/preset-env": "7.25.7", + "@babel/preset-typescript": "7.25.7", + "@babel/runtime": "7.25.7", + "@dlenroc/testrail": "1.9.1", + "@lavamoat/allow-scripts": "3.2.1", + "@playwright/test": "1.48.0", + "@react-native/babel-preset": "0.73.21", + "@react-native/metro-config": "0.73.5", + "@rushstack/eslint-patch": "1.10.4", + "@spotlightjs/spotlight": "2.5.0", + "@storybook/addon-ondevice-actions": "7.6.20", + "@storybook/addon-ondevice-backgrounds": "7.6.20", + "@storybook/addon-ondevice-controls": "7.6.20", + "@storybook/react-native": "7.6.20", + "@typechain/ethers-v6": "0.5.1", + "@types/big.js": "6.2.2", + "@types/bn.js": "5.1.6", + "@types/d3": "7.4.3", + "@types/jest": "29.5.13", + "@types/lodash.debounce": "4.0.9", + "@types/lodash.isempty": "4.4.9", + "@types/lodash.isstring": "4.0.9", + "@types/numeral": "2.0.5", + "@types/react": "18.3.11", + "@types/react-dom": "18.3.0", + "@types/react-test-renderer": "18.3.0", + "@types/semver": "7.5.4", + "@welldone-software/why-did-you-render": "8.0.3", + "babel-jest": "29.7.0", + "babel-loader": "9.2.1", + "babel-plugin-inline-dotenv": "1.7.0", + "babel-plugin-module-resolver": "5.0.2", + "babel-plugin-react-require": "4.0.3", + "detox": "20.27.2", + "eslint": "8.50.0", + "eslint-plugin-avalabs-mobile": "workspace:*", + "jest": "29.7.0", + "json-stringify-pretty-compact": "4.0.0", + "msw": "1.3.2", + "node-fetch": "3.3.2", + "patch-package": "8.0.0", + "playwright-extra": "4.3.6", + "postinstall-postinstall": "2.1.0", + "puppeteer-extra-plugin-stealth": "2.11.2", + "react-dom": "18.3.1", + "react-native-svg-transformer": "1.5.0", + "react-test-renderer": "18.3.1", + "reactotron-react-native": "5.1.8", + "reactotron-react-native-mmkv": "0.2.7", + "reactotron-redux": "3.1.10", + "ts-jest": "29.2.5", + "ts-node": "10.9.2", + "typechain": "8.3.2", + "typescript": "5.6.3" + }, + "engines": { + "node": ">=18.14.1", + "yarn": ">=3.6.4" + }, + "lavamoat": { + "allowScripts": { + "$root$": true, + "@avalabs/core-wallets-sdk>hdkey>secp256k1": false, + "@avalabs/evm-module": false, + "@avalabs/k2-mobile": false, + "@avalabs/k2-alpine": false, + "@datadog/mobile-react-native": false, + "@lavamoat/preinstall-always-fail": false, + "@sentry/react-native>@sentry/cli": false, + "@storybook/react-native>@storybook/core-common>esbuild": false, + "bitcoinjs-lib>tiny-secp256k1": false, + "detox": false, + "detox>bunyan>dtrace-provider": false, + "msw": false, + "postinstall-postinstall": false, + "react-native-bootsplash>sharp": false, + "react-native-inappbrowser-reborn": false, + "viem>ws>bufferutil": false, + "viem>ws>utf-8-validate": false, + "web3": false, + "web3>web3-bzz": false, + "web3>web3-core>web3-core-requestmanager>web3-providers-ws>websocket>es5-ext": false, + "web3>web3-shh": false, + "web3>web3-utils>ethereumjs-util>ethereum-cryptography>keccak": false, + "@react-native-firebase/app>firebase>@firebase/firestore>@grpc/proto-loader>protobufjs": false, + "@avalabs/vm-module-types>hypersdk-client>@metamask/sdk>eciesjs>secp256k1": false, + "web3>web3-core>web3-core-requestmanager>web3-providers-ws>websocket>bufferutil": false } + }, + "react-native": { + "http": "@tradle/react-native-http", + "https": "https-browserify", + "os": "react-native-os", + "_stream_transform": "readable-stream/transform", + "_stream_readable": "readable-stream/readable", + "_stream_writable": "readable-stream/writable", + "_stream_duplex": "readable-stream/duplex", + "_stream_passthrough": "readable-stream/passthrough", + "stream": "stream-browserify", + "vm": "vm-browserify", + "zlib": "browserify-zlib", + "path": "path-browserify", + "fs": "react-native-level-fs" + }, + "browser": { + "_stream_duplex": "readable-stream/duplex", + "_stream_passthrough": "readable-stream/passthrough", + "_stream_readable": "readable-stream/readable", + "_stream_transform": "readable-stream/transform", + "_stream_writable": "readable-stream/writable", + "fs": "react-native-level-fs", + "http": "@tradle/react-native-http", + "https": "https-browserify", + "os": "react-native-os", + "path": "path-browserify", + "stream": "stream-browserify", + "vm": "vm-browserify", + "zlib": "browserify-zlib" + } } diff --git a/yarn.lock b/yarn.lock index edf0f222ac..ec0d932250 100644 --- a/yarn.lock +++ b/yarn.lock @@ -159,6 +159,16 @@ __metadata: languageName: node linkType: hard +"@avalabs/core-gasless-sdk@npm:3.1.0-alpha.40": + version: 3.1.0-alpha.40 + resolution: "@avalabs/core-gasless-sdk@npm:3.1.0-alpha.40" + dependencies: + "@noble/hashes": 1.7.1 + zod: 3.23.8 + checksum: 4e571c8830adaad07076ed82e4a1abfaf7224f335b873879794b171151a2ddc4c5b7e3d95467d188938306b0d07ed8cdea54ba3897a0801710e49fd61a8f3183 + languageName: node + linkType: hard + "@avalabs/core-mobile@workspace:packages/core-mobile": version: 0.0.0-use.local resolution: "@avalabs/core-mobile@workspace:packages/core-mobile" @@ -170,6 +180,7 @@ __metadata: "@avalabs/core-bridge-sdk": 3.1.0-alpha.34 "@avalabs/core-chains-sdk": 3.1.0-alpha.34 "@avalabs/core-coingecko-sdk": 3.1.0-alpha.34 + "@avalabs/core-gasless-sdk": 3.1.0-alpha.40 "@avalabs/core-utils-sdk": 3.1.0-alpha.34 "@avalabs/core-wallets-sdk": 3.1.0-alpha.34 "@avalabs/evm-module": 1.4.3 @@ -27103,7 +27114,7 @@ react-native-webview@ava-labs/react-native-webview: peerDependencies: react: "*" react-native: "*" - checksum: ae658f8c94177d1b419ffb73d26bd70474b6c688af507daaabc11451f983f77a906b2aafcdfdd09c96cab846d9722dcaf26a7c22ee7d19fb4cf70578c8812ac5 + checksum: 856a172d7a0046e6d93bf3900031f7743e67103ad7de882acf86db5a90c595a70cb05df54c44ae532a8b3c6e20f3d744771335803b84930e6110d75e323f974b languageName: node linkType: hard