diff --git a/apps/browser-extension-wallet/src/assets/icons/pause-icon.component.svg b/apps/browser-extension-wallet/src/assets/icons/pause-icon.component.svg
new file mode 100644
index 000000000..f458660af
--- /dev/null
+++ b/apps/browser-extension-wallet/src/assets/icons/pause-icon.component.svg
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
+
diff --git a/apps/browser-extension-wallet/src/assets/icons/play-icon.component.svg b/apps/browser-extension-wallet/src/assets/icons/play-icon.component.svg
new file mode 100644
index 000000000..6036aa2de
--- /dev/null
+++ b/apps/browser-extension-wallet/src/assets/icons/play-icon.component.svg
@@ -0,0 +1,14 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/apps/browser-extension-wallet/src/features/dapp/components/DappTransactionFail.tsx b/apps/browser-extension-wallet/src/features/dapp/components/DappTransactionFail.tsx
index 2db3ec9a9..8eada5728 100644
--- a/apps/browser-extension-wallet/src/features/dapp/components/DappTransactionFail.tsx
+++ b/apps/browser-extension-wallet/src/features/dapp/components/DappTransactionFail.tsx
@@ -1,21 +1,25 @@
import React, { useEffect } from 'react';
import { useTranslation } from 'react-i18next';
-import { Button, PostHogAction } from '@lace/common';
+import { Button, PostHogAction, WarningBanner } from '@lace/common';
import Fail from '../../../assets/icons/exclamation-circle.svg';
import styles from './Layout.module.scss';
import { Image } from 'antd';
import { useAnalyticsContext } from '@providers';
import { TX_CREATION_TYPE_KEY, TxCreationType } from '@providers/AnalyticsProvider/analyticsTracker';
+import { useWalletStore } from '@stores';
+import { useCustomSubmitApi } from '@hooks';
export const DappTransactionFail = (): React.ReactElement => {
const { t } = useTranslation();
const analytics = useAnalyticsContext();
+ const { environmentName } = useWalletStore();
const onClose = async () => {
await analytics?.sendEventToPostHog(PostHogAction.SendSomethingWentWrongCancelClick, {
[TX_CREATION_TYPE_KEY]: TxCreationType.External
});
window.close();
};
+ const { getCustomSubmitApiForNetwork } = useCustomSubmitApi();
useEffect(() => {
analytics?.sendEventToPostHog(PostHogAction.SendSomethingWentWrongView, {
@@ -33,6 +37,9 @@ export const DappTransactionFail = (): React.ReactElement => {
{t('dapp.sign.failure.description')}
+ {getCustomSubmitApiForNetwork(environmentName).status && (
+
+ )}
{
const { priceResult } = useFetchCoinPrice();
const { balance } = useBalances(priceResult?.cardano?.price);
const stakingRewards = useStakingRewards();
+ const { getCustomSubmitApiForNetwork } = useCustomSubmitApi();
const {
walletType,
inMemoryWallet,
@@ -48,7 +49,8 @@ export const MultiDelegationStakingPopup = (): JSX.Element => {
networkInfo,
blockchainProvider,
walletInfo,
- currentChain
+ currentChain,
+ environmentName
} = useWalletStore((state) => ({
walletType: state.walletType,
inMemoryWallet: state.inMemoryWallet,
@@ -60,7 +62,8 @@ export const MultiDelegationStakingPopup = (): JSX.Element => {
fetchNetworkInfo: state.fetchNetworkInfo,
blockchainProvider: state.blockchainProvider,
walletInfo: state.walletInfo,
- currentChain: state.currentChain
+ currentChain: state.currentChain,
+ environmentName: state.environmentName
}));
const sendAnalytics = useCallback(() => {
// TODO implement analytics for the new flow
@@ -140,7 +143,8 @@ export const MultiDelegationStakingPopup = (): JSX.Element => {
compactNumber: compactNumberWithUnit,
walletAddress,
currentChain,
- isMultidelegationSupportedByDevice
+ isMultidelegationSupportedByDevice,
+ isCustomSubmitApiEnabled: getCustomSubmitApiForNetwork(environmentName).status
}}
>
{
]
});
expect(clearBackgroundStorage).toBeCalledWith({
- except: ['fiatPrices', 'userId', 'usePersistentUserId', 'experimentsConfiguration']
+ except: ['fiatPrices', 'userId', 'usePersistentUserId', 'experimentsConfiguration', 'customSubmitTxUrl']
});
expect(resetWalletLock).toBeCalledWith();
expect(setCardanoWallet).toBeCalledWith();
diff --git a/apps/browser-extension-wallet/src/hooks/index.ts b/apps/browser-extension-wallet/src/hooks/index.ts
index deb0270bc..e3f254fab 100644
--- a/apps/browser-extension-wallet/src/hooks/index.ts
+++ b/apps/browser-extension-wallet/src/hooks/index.ts
@@ -23,3 +23,5 @@ export * from './useOnAddressSave';
export * from './useAppInit';
export * from './useChainHistoryProvider';
export * from './useWalletAvatar';
+export * from './useActionExecution';
+export * from './useCustomSubmitApi';
diff --git a/apps/browser-extension-wallet/src/hooks/useAppInit.ts b/apps/browser-extension-wallet/src/hooks/useAppInit.ts
index b05896bdd..f7e3bdfab 100644
--- a/apps/browser-extension-wallet/src/hooks/useAppInit.ts
+++ b/apps/browser-extension-wallet/src/hooks/useAppInit.ts
@@ -5,6 +5,8 @@ import { isKeyHashAddress } from '@cardano-sdk/wallet';
import { AddressesDiscoveryStatus } from '@lib/communication/addresses-discoverer';
import { useWalletManager } from './useWalletManager';
import { useWalletState } from './useWalletState';
+import { setBackgroundStorage } from '@lib/scripts/background/storage';
+import { useCustomSubmitApi } from '@hooks/useCustomSubmitApi';
export const useAppInit = (): void => {
const {
@@ -19,6 +21,8 @@ export const useAppInit = (): void => {
} = useWalletStore();
const { loadWallet, walletManager, walletRepository } = useWalletManager();
const walletState = useWalletState();
+ const { environmentName } = useWalletStore();
+ const { getCustomSubmitApiForNetwork } = useCustomSubmitApi();
useEffect(() => {
setWalletState(walletState);
@@ -46,6 +50,13 @@ export const useAppInit = (): void => {
}
}, [walletInfo, initialHdDiscoveryCompleted, setAddressesDiscoveryCompleted]);
+ useEffect(() => {
+ (async () => {
+ environmentName &&
+ (await setBackgroundStorage({ customSubmitTxUrl: getCustomSubmitApiForNetwork(environmentName).url }));
+ })();
+ }, [environmentName, getCustomSubmitApiForNetwork]);
+
const wallets = useObservable(walletRepository.wallets$);
const activeWalletProps = useObservable(walletManager.activeWalletId$);
useEffect(() => {
diff --git a/apps/browser-extension-wallet/src/hooks/useCustomSubmitApi.ts b/apps/browser-extension-wallet/src/hooks/useCustomSubmitApi.ts
new file mode 100644
index 000000000..0046acc9b
--- /dev/null
+++ b/apps/browser-extension-wallet/src/hooks/useCustomSubmitApi.ts
@@ -0,0 +1,26 @@
+import { useLocalStorage } from '@hooks/useLocalStorage';
+import { EnvironmentTypes } from '@stores';
+import { CustomSubmitApiConfig } from '@types';
+
+interface useCustomSubmitApiReturn {
+ getCustomSubmitApiForNetwork: (network: EnvironmentTypes) => CustomSubmitApiConfig;
+ updateCustomSubmitApi: (network: EnvironmentTypes, data: CustomSubmitApiConfig) => void;
+}
+
+export const useCustomSubmitApi = (): useCustomSubmitApiReturn => {
+ const [isCustomSubmitApiEnabled, { updateLocalStorage: updateCustomSubmitApiEnabled }] =
+ useLocalStorage('isCustomSubmitApiEnabled');
+
+ const getCustomSubmitApiForNetwork = (network: EnvironmentTypes) => {
+ const networkConfig = isCustomSubmitApiEnabled?.[network];
+ const status = networkConfig?.status || false;
+ const url = networkConfig?.url || '';
+ return { status, url };
+ };
+
+ const updateCustomSubmitApi = (network: EnvironmentTypes, data: CustomSubmitApiConfig) => {
+ updateCustomSubmitApiEnabled({ ...isCustomSubmitApiEnabled, [network]: data });
+ };
+
+ return { getCustomSubmitApiForNetwork, updateCustomSubmitApi };
+};
diff --git a/apps/browser-extension-wallet/src/hooks/useWalletManager.ts b/apps/browser-extension-wallet/src/hooks/useWalletManager.ts
index 27b3c8d87..2f5e12614 100644
--- a/apps/browser-extension-wallet/src/hooks/useWalletManager.ts
+++ b/apps/browser-extension-wallet/src/hooks/useWalletManager.ts
@@ -2,7 +2,7 @@
/* eslint-disable unicorn/no-null */
import { useCallback } from 'react';
import { Wallet } from '@lace/cardano';
-import { useWalletStore } from '@stores';
+import { EnvironmentTypes, useWalletStore } from '@stores';
import { useAppSettingsContext } from '@providers/AppSettings';
import { useBackgroundServiceAPIContext } from '@providers/BackgroundServiceAPI';
import { AddressBookSchema, addressBookSchema, NftFoldersSchema, nftFoldersSchema, useDbState } from '@src/lib/storage';
@@ -32,6 +32,8 @@ import {
import { deepEquals, HexBlob } from '@cardano-sdk/util';
import { BackgroundService } from '@lib/scripts/types';
import { getChainName } from '@src/utils/get-chain-name';
+import { useCustomSubmitApi } from '@hooks/useCustomSubmitApi';
+import { setBackgroundStorage } from '@lib/scripts/background/storage';
const { AVAILABLE_CHAINS, CHAIN } = config();
const DEFAULT_CHAIN_ID = Wallet.Cardano.ChainIds[CHAIN];
@@ -89,8 +91,15 @@ export interface UseWalletManager {
*/
deleteWallet: (isForgotPasswordFlow?: boolean) => Promise;
switchNetwork: (chainName: Wallet.ChainName) => Promise;
+
+ /**
+ * Force the wallet to recreate all providers and reload. This is useful for changing
+ * provider properties or configurations without switching the wallet.
+ */
+ reloadWallet: () => Promise;
addAccount: (props: WalletManagerAddAccountProps) => Promise;
getMnemonic: (passphrase: Uint8Array) => Promise;
+ enableCustomNode: (network: EnvironmentTypes, value: string) => Promise;
}
const clearBytes = (bytes: Uint8Array) => {
@@ -219,6 +228,7 @@ export const useWalletManager = (): UseWalletManager => {
} = useDbState([], nftFoldersSchema);
const backgroundService = useBackgroundServiceAPIContext();
const userIdService = getUserIdService();
+ const { getCustomSubmitApiForNetwork, updateCustomSubmitApi } = useCustomSubmitApi();
const getCurrentChainId = useCallback(() => {
if (currentChain) return currentChain;
@@ -592,7 +602,7 @@ export const useWalletManager = (): UseWalletManager => {
deleteFromLocalStorage('userInfo');
deleteFromLocalStorage('keyAgentData');
await backgroundService.clearBackgroundStorage({
- except: ['fiatPrices', 'userId', 'usePersistentUserId', 'experimentsConfiguration']
+ except: ['fiatPrices', 'userId', 'usePersistentUserId', 'experimentsConfiguration', 'customSubmitTxUrl']
});
resetWalletLock();
setCardanoWallet();
@@ -639,6 +649,12 @@ export const useWalletManager = (): UseWalletManager => {
]
);
+ const reloadWallet = useCallback(async (): Promise => {
+ const activeWallet = await firstValueFrom(walletManager.activeWalletId$);
+
+ await walletManager.activate(activeWallet, true);
+ }, []);
+
/**
* Deactivates current wallet and activates it again with the new network
*/
@@ -651,11 +667,22 @@ export const useWalletManager = (): UseWalletManager => {
setAddressesDiscoveryCompleted(false);
updateAppSettings({ ...settings, chainName });
+ const customSubmitApi = getCustomSubmitApiForNetwork(chainName);
+ await setBackgroundStorage({ customSubmitTxUrl: customSubmitApi.url });
+ await reloadWallet();
setCurrentChain(chainName);
setCardanoCoin(chainId);
},
- [setAddressesDiscoveryCompleted, updateAppSettings, settings, setCurrentChain, setCardanoCoin]
+ [
+ setAddressesDiscoveryCompleted,
+ updateAppSettings,
+ settings,
+ getCustomSubmitApiForNetwork,
+ reloadWallet,
+ setCurrentChain,
+ setCardanoCoin
+ ]
);
/**
@@ -738,6 +765,19 @@ export const useWalletManager = (): UseWalletManager => {
[getCurrentChainId]
);
+ const enableCustomNode = useCallback(
+ async (network: EnvironmentTypes, value: string) => {
+ const customApiData = {
+ status: !!value,
+ url: value
+ };
+ updateCustomSubmitApi(network, customApiData);
+ await backgroundService.setBackgroundStorage({ customSubmitTxUrl: value });
+ await reloadWallet();
+ },
+ [backgroundService, reloadWallet, updateCustomSubmitApi]
+ );
+
return {
activateWallet,
addAccount,
@@ -751,9 +791,11 @@ export const useWalletManager = (): UseWalletManager => {
connectHardwareWalletRevamped,
saveHardwareWallet,
deleteWallet,
+ reloadWallet,
switchNetwork,
walletManager,
walletRepository,
- getMnemonic
+ getMnemonic,
+ enableCustomNode
};
};
diff --git a/apps/browser-extension-wallet/src/lib/scripts/background/config.ts b/apps/browser-extension-wallet/src/lib/scripts/background/config.ts
index e7d9e27f0..0cc320c0a 100644
--- a/apps/browser-extension-wallet/src/lib/scripts/background/config.ts
+++ b/apps/browser-extension-wallet/src/lib/scripts/background/config.ts
@@ -3,6 +3,7 @@ import { Wallet } from '@lace/cardano';
import { RemoteApiProperties, RemoteApiPropertyType } from '@cardano-sdk/web-extension';
import { getBaseUrlForChain } from '@src/utils/chain';
import { BackgroundService, UserIdService as UserIdServiceInterface } from '../types';
+import { getBackgroundStorage } from '@lib/scripts/background/storage';
export const backgroundServiceProperties: RemoteApiProperties = {
requestMessage$: RemoteApiPropertyType.HotObservable,
@@ -20,16 +21,16 @@ export const backgroundServiceProperties: RemoteApiProperties
backendFailures$: RemoteApiPropertyType.HotObservable
};
-export const getProviders = (chainName: Wallet.ChainName): Wallet.WalletProvidersDependencies => {
+export const getProviders = async (chainName: Wallet.ChainName): Promise => {
const baseCardanoServicesUrl = getBaseUrlForChain(chainName);
+ const { customSubmitTxUrl } = await getBackgroundStorage();
+
return Wallet.createProviders({
axiosAdapter: axiosFetchAdapter,
- baseUrl: baseCardanoServicesUrl
+ baseUrl: baseCardanoServicesUrl,
+ customSubmitTxUrl
});
};
-export const ownOrigin = globalThis.location.origin;
-
-export const BASE_EXTENSION_APP_URL = 'app.html';
export const cip30WalletProperties = {
// eslint-disable-next-line max-len
diff --git a/apps/browser-extension-wallet/src/lib/scripts/background/wallet.ts b/apps/browser-extension-wallet/src/lib/scripts/background/wallet.ts
index 0f58377d9..5c4f68741 100644
--- a/apps/browser-extension-wallet/src/lib/scripts/background/wallet.ts
+++ b/apps/browser-extension-wallet/src/lib/scripts/background/wallet.ts
@@ -56,7 +56,7 @@ const chainIdToChainName = (chainId: Cardano.ChainId): Wallet.ChainName => {
const walletFactory: WalletFactory = {
create: async ({ chainId, accountIndex }, wallet, { stores, witnesser }) => {
const chainName: Wallet.ChainName = chainIdToChainName(chainId);
- const providers = getProviders(chainName);
+ const providers = await getProviders(chainName);
if (wallet.type === WalletType.Script || typeof accountIndex !== 'number') {
throw new NotImplementedError('Script wallet support is not implemented');
}
diff --git a/apps/browser-extension-wallet/src/lib/scripts/types/storage.ts b/apps/browser-extension-wallet/src/lib/scripts/types/storage.ts
index c066d5977..4aef5704f 100644
--- a/apps/browser-extension-wallet/src/lib/scripts/types/storage.ts
+++ b/apps/browser-extension-wallet/src/lib/scripts/types/storage.ts
@@ -28,6 +28,7 @@ export interface BackgroundStorage {
userId?: string;
usePersistentUserId?: boolean;
experimentsConfiguration?: Record;
+ customSubmitTxUrl?: string;
}
export type BackgroundStorageKeys = keyof BackgroundStorage;
diff --git a/apps/browser-extension-wallet/src/lib/translations/en.json b/apps/browser-extension-wallet/src/lib/translations/en.json
index 2b7fd4f39..b224b443d 100644
--- a/apps/browser-extension-wallet/src/lib/translations/en.json
+++ b/apps/browser-extension-wallet/src/lib/translations/en.json
@@ -752,6 +752,7 @@
"browserView.transaction.send.confirmationTitle": "Transaction confirmation",
"browserView.transaction.send.signTransactionWithPassword": "Please sign the transaction with your password.",
"browserView.transaction.send.enterWalletPasswordToConfirmTransaction": "Enter your wallet password to confirm transaction",
+ "browserView.transaction.send.customSubmitApiBannerText": "Custom submit API enabled to send transactions. To disable, go to Settings >> Custom submit API",
"browserView.settings.heading": "Settings",
"browserView.settings.wallet.title": "Wallet",
"browserView.settings.wallet.about.title": "About",
@@ -798,6 +799,20 @@
"browserView.settings.wallet.network.description": "Switch from mainnet to testnet",
"browserView.settings.wallet.network.drawerDescription": "Select the network you would like your wallet to operate on.",
"browserView.settings.wallet.network.networkSwitched": "Switched network",
+ "browserView.settings.wallet.customSubmitApi.title": "Custom submit API",
+ "browserView.settings.wallet.customSubmitApi.description": "Ensure your local node is on the same network as your wallet and fully synced to submit transactions.",
+ "browserView.settings.wallet.customSubmitApi.descriptionLink": "Learn more about Cardano-submit-API",
+ "browserView.settings.wallet.customSubmitApi.defaultAddress": "Default address: {{url}}",
+ "browserView.settings.wallet.customSubmitApi.settingsLinkTitle": "Custom Submit API",
+ "browserView.settings.wallet.customSubmitApi.settingsLinkDescription": "Send transactions through a local Cardano node and cardano-submit-api",
+ "browserView.settings.wallet.customSubmitApi.usingCustomTxSubmitEndpoint": "You custom submit API is enabled to submit transactions",
+ "browserView.settings.wallet.customSubmitApi.usingStandardTxSubmitEndpoint": "You custom submit API is disabled. Lace will send transactions through its infrastructure",
+ "browserView.settings.wallet.customSubmitApi.inputLabel": "Insert the URL here",
+ "browserView.settings.wallet.customSubmitApi.enable": "Enable",
+ "browserView.settings.wallet.customSubmitApi.disable": "Disable",
+ "browserView.settings.wallet.customSubmitApi.enabled": "Enabled",
+ "browserView.settings.wallet.customSubmitApi.disabled": "Disabled",
+ "browserView.settings.wallet.customSubmitApi.validationError": "Invalid URL",
"browserView.settings.wallet.authorizedDApps.title": "Authorized DApps",
"browserView.settings.wallet.authorizedDApps.description": "See and manage authorized DApps",
"browserView.settings.wallet.walletSync.description": "Sync new addresses of your HD wallet. This may be needed if you're using other HD wallets at the same time as Lace",
diff --git a/apps/browser-extension-wallet/src/stores/slices/blockchain-provider-slice.ts b/apps/browser-extension-wallet/src/stores/slices/blockchain-provider-slice.ts
index 93fd2caa6..9e75d6eaa 100644
--- a/apps/browser-extension-wallet/src/stores/slices/blockchain-provider-slice.ts
+++ b/apps/browser-extension-wallet/src/stores/slices/blockchain-provider-slice.ts
@@ -41,6 +41,7 @@ export const IBlockchainProvider = {
export const getProviderByChain: BlockchainProviderFactory = (chain = CHAIN) => {
const baseCardanoServicesUrl = getBaseUrlForChain(chain);
+
const providers = Wallet.createProviders({
axiosAdapter: axiosFetchAdapter,
baseUrl: baseCardanoServicesUrl
diff --git a/apps/browser-extension-wallet/src/types/local-storage.ts b/apps/browser-extension-wallet/src/types/local-storage.ts
index c513d2cd4..b7ccfd532 100644
--- a/apps/browser-extension-wallet/src/types/local-storage.ts
+++ b/apps/browser-extension-wallet/src/types/local-storage.ts
@@ -38,6 +38,11 @@ export interface UnconfirmedTransaction {
date: string;
}
+export interface CustomSubmitApiConfig {
+ status: boolean;
+ url: string;
+}
+
export type UnconfirmedTransactions = UnconfirmedTransaction[];
export interface ILocalStorage {
@@ -59,4 +64,5 @@ export interface ILocalStorage {
showPinExtension?: boolean;
showMultiAddressModal?: boolean;
userAvatar?: Record<`${EnvironmentTypes}${string}`, string>;
+ isCustomSubmitApiEnabled?: Record;
}
diff --git a/apps/browser-extension-wallet/src/views/browser-view/features/send-transaction/components/Form/Form.module.scss b/apps/browser-extension-wallet/src/views/browser-view/features/send-transaction/components/Form/Form.module.scss
index 35b4bd682..0986ccf62 100644
--- a/apps/browser-extension-wallet/src/views/browser-view/features/send-transaction/components/Form/Form.module.scss
+++ b/apps/browser-extension-wallet/src/views/browser-view/features/send-transaction/components/Form/Form.module.scss
@@ -72,4 +72,4 @@
@include text-body-medium;
text-align: center;
}
-}
\ No newline at end of file
+}
diff --git a/apps/browser-extension-wallet/src/views/browser-view/features/send-transaction/components/Form/Form.tsx b/apps/browser-extension-wallet/src/views/browser-view/features/send-transaction/components/Form/Form.tsx
index de813f4c7..a93c88f1c 100644
--- a/apps/browser-extension-wallet/src/views/browser-view/features/send-transaction/components/Form/Form.tsx
+++ b/apps/browser-extension-wallet/src/views/browser-view/features/send-transaction/components/Form/Form.tsx
@@ -1,13 +1,12 @@
import React, { useEffect, useMemo, useState } from 'react';
import { Skeleton } from 'antd';
import { useTranslation } from 'react-i18next';
-
import { Tokens } from '@src/types';
-import { PriceResult } from '@hooks';
+import { PriceResult, useCustomSubmitApi } from '@hooks';
import { useCurrencyStore } from '@providers';
import { Wallet } from '@lace/cardano';
import { SendTransactionCost } from '@lace/core';
-import { Button, useObservable } from '@lace/common';
+import { Button, useObservable, WarningBanner } from '@lace/common';
import { useWalletStore } from '@src/stores';
import { useMaxAda } from '@hooks/useMaxAda';
import BundleIcon from '../../../../../../assets/icons/bundle-icon.component.svg';
@@ -39,7 +38,8 @@ export const Form = ({
const { t } = useTranslation();
const {
inMemoryWallet,
- walletUI: { cardanoCoin }
+ walletUI: { cardanoCoin },
+ environmentName
} = useWalletStore();
const balance = useObservable(inMemoryWallet.balance.utxo.total$);
const { builtTxData: { totalMinimumCoins, uiTx } = {} } = useBuiltTxState();
@@ -50,6 +50,7 @@ export const Form = ({
const [insufficientBalanceInputs, setInsufficientBalanceInputs] = useState([]); // we save all the element input ids with insufficient balance error
const { lastFocusedInput } = useLastFocusedInput();
const { fiatCurrency } = useCurrencyStore();
+ const { getCustomSubmitApiForNetwork } = useCustomSubmitApi();
const { setNewOutput } = useOutputs();
@@ -105,6 +106,9 @@ export const Form = ({
return (
+ {getCustomSubmitApiForNetwork(environmentName).status && (
+
+ )}
,
[Sections.CONFIRMATION]: ,
[Sections.SUCCESS_TX]: ,
- [Sections.FAIL_TX]: ,
+ [Sections.FAIL_TX]: (
+
+ ),
[Sections.UNAUTHORIZED_TX]: ,
[Sections.ADDRESS_LIST]: ,
[Sections.ADDRESS_FORM]: ,
diff --git a/apps/browser-extension-wallet/src/views/browser-view/features/send-transaction/components/TransactionFail.tsx b/apps/browser-extension-wallet/src/views/browser-view/features/send-transaction/components/TransactionFail.tsx
index 4666f15df..0a8e04cad 100644
--- a/apps/browser-extension-wallet/src/views/browser-view/features/send-transaction/components/TransactionFail.tsx
+++ b/apps/browser-extension-wallet/src/views/browser-view/features/send-transaction/components/TransactionFail.tsx
@@ -5,8 +5,13 @@ import { useAnalyticsContext } from '@providers';
import { PostHogAction, TX_CREATION_TYPE_KEY, TxCreationType } from '@providers/AnalyticsProvider/analyticsTracker';
import styles from './TransactionSuccessView.module.scss';
import { useAnalyticsSendFlowTriggerPoint } from '../store';
+import { WarningBanner } from '@lace/common';
-export const TransactionFail = (): React.ReactElement => {
+interface TransactionFailProps {
+ showCustomApiBanner?: boolean;
+}
+
+export const TransactionFail = ({ showCustomApiBanner = false }: TransactionFailProps): React.ReactElement => {
const { t } = useTranslation();
const analytics = useAnalyticsContext();
const { triggerPoint } = useAnalyticsSendFlowTriggerPoint();
@@ -34,7 +39,12 @@ export const TransactionFail = (): React.ReactElement => {
{t('browserView.transaction.fail.problemSubmittingYourTransaction')}
- {t('browserView.transaction.fail.clickBackAndTryAgain')}
+
+ {t('browserView.transaction.fail.clickBackAndTryAgain')}
+
+ {showCustomApiBanner && (
+
+ )}
>
}
/>
diff --git a/apps/browser-extension-wallet/src/views/browser-view/features/send-transaction/components/TransactionSuccessView.module.scss b/apps/browser-extension-wallet/src/views/browser-view/features/send-transaction/components/TransactionSuccessView.module.scss
index 8ba177678..998e8cae2 100644
--- a/apps/browser-extension-wallet/src/views/browser-view/features/send-transaction/components/TransactionSuccessView.module.scss
+++ b/apps/browser-extension-wallet/src/views/browser-view/features/send-transaction/components/TransactionSuccessView.module.scss
@@ -8,3 +8,7 @@
flex: 1;
justify-content: center;
}
+
+.message {
+ margin-bottom: 34px;
+}
diff --git a/apps/browser-extension-wallet/src/views/browser-view/features/settings/components/CustomSubmitApiDrawer.tsx b/apps/browser-extension-wallet/src/views/browser-view/features/settings/components/CustomSubmitApiDrawer.tsx
new file mode 100644
index 000000000..4b7971b5f
--- /dev/null
+++ b/apps/browser-extension-wallet/src/views/browser-view/features/settings/components/CustomSubmitApiDrawer.tsx
@@ -0,0 +1,128 @@
+import React, { ReactElement, useEffect, useState } from 'react';
+import { Drawer, DrawerHeader, DrawerNavigation, PostHogAction, toast } from '@lace/common';
+import { Typography } from 'antd';
+import styles from './SettingsLayout.module.scss';
+import { useTranslation } from 'react-i18next';
+import { Button, TextBox } from '@lace/ui';
+import { getBackgroundStorage } from '@lib/scripts/background/storage';
+import { useCustomSubmitApi, useWalletManager } from '@hooks';
+import { useWalletStore } from '@stores';
+import { isValidURL } from '@utils/is-valid-url';
+import { useAnalyticsContext } from '@providers';
+import SwitchIcon from '@assets/icons/switch.component.svg';
+import ErrorIcon from '@assets/icons/address-error-icon.component.svg';
+import PlayIcon from '@assets/icons/play-icon.component.svg';
+import PauseIcon from '@assets/icons/pause-icon.component.svg';
+
+const { Text } = Typography;
+
+interface CustomSubmitApiDrawerProps {
+ visible: boolean;
+ onClose: () => void;
+ popupView?: boolean;
+}
+
+const LEARN_SUBMIT_API_URL = 'https://github.com/IntersectMBO/cardano-node/tree/master/cardano-submit-api';
+const DEFAULT_SUBMIT_API = 'http://localhost:8090/api/submit/tx';
+
+export const CustomSubmitApiDrawer = ({
+ visible,
+ onClose,
+ popupView = false
+}: CustomSubmitApiDrawerProps): ReactElement => {
+ const { t } = useTranslation();
+ const { enableCustomNode } = useWalletManager();
+ const { environmentName } = useWalletStore();
+ const analytics = useAnalyticsContext();
+
+ const [customSubmitTxUrl, setCustomSubmitTxUrl] = useState(DEFAULT_SUBMIT_API);
+ const [isValidationError, setIsValidationError] = useState(false);
+ const { getCustomSubmitApiForNetwork } = useCustomSubmitApi();
+
+ const isCustomApiEnabledForCurrentNetwork = getCustomSubmitApiForNetwork(environmentName).status;
+
+ useEffect(() => {
+ getBackgroundStorage()
+ .then((storage) => {
+ setCustomSubmitTxUrl(storage.customSubmitTxUrl || DEFAULT_SUBMIT_API);
+ })
+ .catch(console.error);
+ }, []);
+
+ const handleCustomTxSubmitEndpoint = async (enable: boolean) => {
+ if (enable && !isValidURL(customSubmitTxUrl)) {
+ setIsValidationError(true);
+ return;
+ }
+
+ setIsValidationError(false);
+ const value = enable ? customSubmitTxUrl : undefined;
+ try {
+ await enableCustomNode(environmentName, value);
+ toast.notify({
+ text: value
+ ? t('browserView.settings.wallet.customSubmitApi.usingCustomTxSubmitEndpoint')
+ : t('browserView.settings.wallet.customSubmitApi.usingStandardTxSubmitEndpoint'),
+ withProgressBar: true,
+ icon: SwitchIcon
+ });
+ if (enable) {
+ void analytics.sendEventToPostHog(PostHogAction.SettingsCustomSubmitApiEnableClick);
+ }
+ } catch (error) {
+ console.error('Error switching TxSubmit endpoint', error);
+ toast.notify({ text: t('general.errors.somethingWentWrong'), icon: ErrorIcon });
+ }
+ };
+
+ return (
+ }
+ navigation={
+
+ }
+ popupView={popupView}
+ >
+
+
+ {t('browserView.settings.wallet.customSubmitApi.description')}{' '}
+
+ {t('browserView.settings.wallet.customSubmitApi.descriptionLink')}
+
+
+
+ {t('browserView.settings.wallet.customSubmitApi.defaultAddress', { url: DEFAULT_SUBMIT_API })}
+
+
+
setCustomSubmitTxUrl(event.target.value)}
+ disabled={isCustomApiEnabledForCurrentNetwork}
+ />
+ : }
+ onClick={() => handleCustomTxSubmitEndpoint(!isCustomApiEnabledForCurrentNetwork)}
+ />
+
+ {isValidationError && (
+
+ {t('browserView.settings.wallet.customSubmitApi.validationError')}
+
+ )}
+
+
+ );
+};
diff --git a/apps/browser-extension-wallet/src/views/browser-view/features/settings/components/SettingsLayout.module.scss b/apps/browser-extension-wallet/src/views/browser-view/features/settings/components/SettingsLayout.module.scss
index 1be1d117a..69bb6da6f 100644
--- a/apps/browser-extension-wallet/src/views/browser-view/features/settings/components/SettingsLayout.module.scss
+++ b/apps/browser-extension-wallet/src/views/browser-view/features/settings/components/SettingsLayout.module.scss
@@ -321,10 +321,20 @@
@include text-bodyLarge-semi-bold;
color: var(--text-color-secondary) !important;
display: block !important;
+ margin-top: size_unit(1);
@media (max-width: $breakpoint-popup) {
font-size: var(--body) !important;
}
+
+ a {
+ text-decoration: underline;
+ }
+}
+
+.drawerText {
+ @extend .drawerDescription;
+ margin-top: size_unit(3);
}
h5 {
@@ -520,3 +530,21 @@ h5 {
display: grid;
grid-template-columns: size_unit(5) 1fr;
}
+
+.customApiContainer {
+ margin-top: size_unit(4);
+ display: grid;
+ grid-template-columns: 4fr 1fr;
+ grid-gap: size_unit(2);
+ align-items: center;
+
+ svg {
+ font-size: 18px;
+ }
+}
+
+.validationError {
+ @include text-bodyXS-medium;
+ color: var(--data-pink) !important;
+ margin-left: size_unit(1);
+}
diff --git a/apps/browser-extension-wallet/src/views/browser-view/features/settings/components/SettingsWalletBase.tsx b/apps/browser-extension-wallet/src/views/browser-view/features/settings/components/SettingsWalletBase.tsx
index de1db2d0e..3cd368cb8 100644
--- a/apps/browser-extension-wallet/src/views/browser-view/features/settings/components/SettingsWalletBase.tsx
+++ b/apps/browser-extension-wallet/src/views/browser-view/features/settings/components/SettingsWalletBase.tsx
@@ -9,7 +9,7 @@ import { NetworkChoiceDrawer } from './NetworkChoiceDrawer';
import { useWalletStore } from '@src/stores';
import { AboutDrawer } from './AboutDrawer';
import { config } from '@src/config';
-import { COLLATERAL_AMOUNT_LOVELACES, useRedirection } from '@hooks';
+import { COLLATERAL_AMOUNT_LOVELACES, useCustomSubmitApi, useRedirection } from '@hooks';
import { BrowserViewSections, MessageTypes } from '@lib/scripts/types';
import { useAnalyticsContext, useBackgroundServiceAPIContext } from '@providers';
import { useSearchParams, useObservable, Button } from '@lace/common';
@@ -18,6 +18,7 @@ import { PostHogAction } from '@providers/AnalyticsProvider/analyticsTracker';
import uniq from 'lodash/uniq';
import { isKeyHashAddress } from '@cardano-sdk/wallet';
import { AddressesDiscoveryStatus } from '@lib/communication/addresses-discoverer';
+import { CustomSubmitApiDrawer } from './CustomSubmitApiDrawer';
const { Title } = Typography;
@@ -26,7 +27,8 @@ export enum SettingsDrawer {
collateral = 'collateral',
dappList = 'dappList',
general = 'general',
- networkChoice = 'networkChoice'
+ networkChoice = 'networkChoice',
+ customSubmitApi = 'customSubmitApi'
}
export type SettingsSearchParams = {
@@ -67,6 +69,7 @@ export const SettingsWalletBase = ({
const hasCollateral = useMemo(() => unspendable?.coins >= COLLATERAL_AMOUNT_LOVELACES, [unspendable?.coins]);
const backgroundServices = useBackgroundServiceAPIContext();
const analytics = useAnalyticsContext();
+ const { getCustomSubmitApiForNetwork } = useCustomSubmitApi();
const isNetworkChoiceEnabled = AVAILABLE_CHAINS.length > 1;
const authorizedAppsEnabled = process.env.USE_DAPP_CONNECTOR === 'true';
@@ -108,10 +111,15 @@ export const SettingsWalletBase = ({
const handleOpenGeneralSettingsDrawer = () =>
handleOpenDrawer(SettingsDrawer.general, PostHogAction.SettingsYourKeysClick);
+ const handleOpenCustomSubmitApiDrawer = () =>
+ handleOpenDrawer(SettingsDrawer.customSubmitApi, PostHogAction.SettingsCustomSubmitApiClick);
+
const handleCloseNetworkChoiceDrawer = () => handleCloseDrawer(PostHogAction.SettingsNetworkXClick);
const handleCloseGeneralSettingsDrawer = () => handleCloseDrawer(PostHogAction.SettingsYourKeysShowPublicKeyXClick);
+ const handleCloseCustomSubmitApiDrawer = () => handleCloseDrawer(PostHogAction.SettingsCustomSubmitApiXClick);
+
const handleSendAnalyticsEvent = (postHogEvent: PostHogAction) => analytics.sendEventToPostHog(postHogEvent);
const syncButton = (
@@ -153,6 +161,11 @@ export const SettingsWalletBase = ({
popupView={popupView}
sendAnalyticsEvent={handleSendAnalyticsEvent}
/>
+
{t('browserView.settings.wallet.title')}
@@ -186,6 +199,17 @@ export const SettingsWalletBase = ({
>
)}
+
+ {t('browserView.settings.wallet.customSubmitApi.settingsLinkTitle')}
+
{authorizedAppsEnabled && (
<>
{
const { theme } = useTheme();
const { priceResult } = useFetchCoinPrice();
const { blockchainProvider, currentChain, activityDetail, resetActivityState } = useWalletStore((state) => ({
- walletType: state.walletType,
- inMemoryWallet: state.inMemoryWallet,
- walletUI: { cardanoCoin: state.walletUI.cardanoCoin },
- stakePoolSearchResults: state.stakePoolSearchResults,
- stakePoolSearchResultsStatus: state.stakePoolSearchResultsStatus,
- fetchStakePools: state.fetchStakePools,
- resetStakePools: state.resetStakePools,
- networkInfo: state.networkInfo,
- fetchNetworkInfo: state.fetchNetworkInfo,
blockchainProvider: state.blockchainProvider,
- walletInfo: state.walletInfo,
currentChain: state.currentChain,
activityDetail: state.activityDetail,
resetActivityState: state.resetActivityState
diff --git a/apps/browser-extension-wallet/src/views/browser-view/features/staking/components/StakingContainer.tsx b/apps/browser-extension-wallet/src/views/browser-view/features/staking/components/StakingContainer.tsx
index 3df3675da..805454e5e 100644
--- a/apps/browser-extension-wallet/src/views/browser-view/features/staking/components/StakingContainer.tsx
+++ b/apps/browser-extension-wallet/src/views/browser-view/features/staking/components/StakingContainer.tsx
@@ -11,7 +11,7 @@ import { isMultidelegationSupportedByDevice } from '@views/browser/features/stak
import { useWalletStore } from '@stores';
import { useAnalyticsContext, useCurrencyStore, useExternalLinkOpener } from '@providers';
import { DEFAULT_STAKING_BROWSER_PREFERENCES, OutsideHandlesProvider } from '@lace/staking';
-import { useBalances, useFetchCoinPrice, useLocalStorage } from '@hooks';
+import { useBalances, useCustomSubmitApi, useFetchCoinPrice, useLocalStorage } from '@hooks';
import {
MULTIDELEGATION_FIRST_VISIT_LS_KEY,
MULTIDELEGATION_FIRST_VISIT_SINCE_PORTFOLIO_PERSISTENCE_LS_KEY,
@@ -58,6 +58,7 @@ export const StakingContainer = (): React.ReactElement => {
const { walletActivities, walletActivitiesStatus } = useWalletActivities({ sendAnalytics });
const password = usePassword();
const submittingState = useSubmitingState();
+ const { getCustomSubmitApiForNetwork } = useCustomSubmitApi();
const {
walletInfo,
@@ -71,7 +72,8 @@ export const StakingContainer = (): React.ReactElement => {
fetchNetworkInfo,
networkInfo,
blockchainProvider,
- currentChain
+ currentChain,
+ environmentName
} = useWalletStore((state) => ({
walletType: state.walletType,
inMemoryWallet: state.inMemoryWallet,
@@ -85,8 +87,7 @@ export const StakingContainer = (): React.ReactElement => {
blockchainProvider: state.blockchainProvider,
walletInfo: state.walletInfo,
currentChain: state.currentChain,
- activityDetail: state.activityDetail,
- resetActivityState: state.resetActivityState
+ environmentName: state.environmentName
}));
const walletAddress = walletInfo.addresses?.[0].address?.toString();
@@ -131,7 +132,8 @@ export const StakingContainer = (): React.ReactElement => {
},
walletAddress,
currentChain,
- isMultidelegationSupportedByDevice
+ isMultidelegationSupportedByDevice,
+ isCustomSubmitApiEnabled: getCustomSubmitApiForNetwork(environmentName).status
}}
>
diff --git a/apps/browser-extension-wallet/webpack-utils.js b/apps/browser-extension-wallet/webpack-utils.js
index 6c1eb49a3..1892f495b 100644
--- a/apps/browser-extension-wallet/webpack-utils.js
+++ b/apps/browser-extension-wallet/webpack-utils.js
@@ -25,8 +25,8 @@ const transformManifest = (content, mode) => {
.replace(
'$LOCALHOST_CONNECT_SRC',
mode === 'development'
- ? 'http://localhost:3000 http://localhost:3001 http://localhost:8080 ws://localhost:3000 ws://0.0.0.0:3000/ws wss://localhost:3000 ws://localhost:3001 ws://0.0.0.0:3001/ws wss://localhost:3001'
- : ''
+ ? 'http://localhost:* http://127.0.0.1:* ws://localhost:3000 ws://0.0.0.0:3000/ws wss://localhost:3000 ws://localhost:3001 ws://0.0.0.0:3001/ws wss://localhost:3001'
+ : 'http://localhost:* http://127.0.0.1:*'
);
if (process.env.LACE_EXTENSION_KEY) {
diff --git a/packages/cardano/src/wallet/lib/providers.ts b/packages/cardano/src/wallet/lib/providers.ts
index 1d7db5473..21fb1d8a2 100644
--- a/packages/cardano/src/wallet/lib/providers.ts
+++ b/packages/cardano/src/wallet/lib/providers.ts
@@ -1,3 +1,4 @@
+/* eslint-disable no-new */
import { WalletProvidersDependencies } from '@src/wallet';
import { AxiosAdapter } from 'axios';
import {
@@ -18,10 +19,29 @@ import {
networkInfoHttpProvider,
rewardsHttpProvider,
stakePoolHttpProvider,
- txSubmitHttpProvider,
- utxoHttpProvider
+ utxoHttpProvider,
+ TxSubmitApiProvider,
+ txSubmitHttpProvider
} from '@cardano-sdk/cardano-services-client';
+const createTxSubmitProvider = (
+ httpProviderConfig: CreateHttpProviderConfig,
+ customSubmitTxUrl?: string
+): TxSubmitProvider => {
+ if (customSubmitTxUrl) {
+ httpProviderConfig.logger.info(`Using custom TxSubmit api URL ${customSubmitTxUrl}`);
+
+ const url = new URL(customSubmitTxUrl);
+
+ return new TxSubmitApiProvider(
+ { baseUrl: url, path: url.pathname },
+ { logger: httpProviderConfig.logger, adapter: httpProviderConfig.adapter }
+ );
+ }
+
+ return txSubmitHttpProvider(httpProviderConfig);
+};
+
export type AllProviders = {
assetProvider: AssetProvider;
networkInfoProvider: NetworkInfoProvider;
@@ -35,9 +55,14 @@ export type AllProviders = {
export interface ProvidersConfig {
axiosAdapter?: AxiosAdapter;
baseUrl: string;
+ customSubmitTxUrl?: string;
}
-export const createProviders = ({ axiosAdapter, baseUrl }: ProvidersConfig): WalletProvidersDependencies => {
+export const createProviders = ({
+ axiosAdapter,
+ baseUrl,
+ customSubmitTxUrl
+}: ProvidersConfig): WalletProvidersDependencies => {
const httpProviderConfig: CreateHttpProviderConfig = {
baseUrl,
logger: console,
@@ -47,7 +72,7 @@ export const createProviders = ({ axiosAdapter, baseUrl }: ProvidersConfig): Wal
return {
assetProvider: assetInfoHttpProvider(httpProviderConfig),
networkInfoProvider: networkInfoHttpProvider(httpProviderConfig),
- txSubmitProvider: txSubmitHttpProvider(httpProviderConfig),
+ txSubmitProvider: createTxSubmitProvider(httpProviderConfig, customSubmitTxUrl),
stakePoolProvider: stakePoolHttpProvider(httpProviderConfig),
utxoProvider: utxoHttpProvider(httpProviderConfig),
chainHistoryProvider: chainHistoryHttpProvider(httpProviderConfig),
diff --git a/packages/common/src/analytics/types.ts b/packages/common/src/analytics/types.ts
index abf9901aa..02d0a9f2c 100644
--- a/packages/common/src/analytics/types.ts
+++ b/packages/common/src/analytics/types.ts
@@ -207,6 +207,9 @@ export enum PostHogAction {
SettingsFaqsClick = 'settings | faqs | click',
SettingsWalletHdWalletSyncSyncClick = 'settings | wallet | hd wallet sync | sync | click',
SettingsWalletHdWalletSyncSyncNewAddresses = 'settings | wallet | hd wallet sync | sync | new addresses',
+ SettingsCustomSubmitApiClick = 'settings | custom submit api | click',
+ SettingsCustomSubmitApiXClick = 'settings | custom submit api | x | click',
+ SettingsCustomSubmitApiEnableClick = 'settings | custom submit api | enable | click',
// Recieve section
ReceiveClick = 'receive | receive | click',
ReceiveCopyAddressIconClick = 'receive | receive | copy address icon | click',
diff --git a/packages/common/src/ui/assets/icons/red-warning-icon.component.svg b/packages/common/src/ui/assets/icons/red-warning-icon.component.svg
new file mode 100644
index 000000000..0d11ea15c
--- /dev/null
+++ b/packages/common/src/ui/assets/icons/red-warning-icon.component.svg
@@ -0,0 +1,3 @@
+
+
+
diff --git a/packages/common/src/ui/components/Banner/WarningBanner.module.scss b/packages/common/src/ui/components/Banner/WarningBanner.module.scss
new file mode 100644
index 000000000..789763c39
--- /dev/null
+++ b/packages/common/src/ui/components/Banner/WarningBanner.module.scss
@@ -0,0 +1,7 @@
+.icon {
+ height: 72px !important;
+}
+
+.message {
+ text-align: left;
+}
diff --git a/packages/common/src/ui/components/Banner/WarningBanner.tsx b/packages/common/src/ui/components/Banner/WarningBanner.tsx
new file mode 100644
index 000000000..addffc3f7
--- /dev/null
+++ b/packages/common/src/ui/components/Banner/WarningBanner.tsx
@@ -0,0 +1,12 @@
+import React, { ReactElement } from 'react';
+import { ReactComponent as WarningIcon } from '../../assets/icons/red-warning-icon.component.svg';
+import styles from './WarningBanner.module.scss';
+import { Banner } from './Banner';
+
+export const WarningBanner = ({ message }: { message: string }): ReactElement => (
+ {message} }
+ withIcon
+ customIcon={ }
+ />
+);
diff --git a/packages/common/src/ui/components/Banner/index.ts b/packages/common/src/ui/components/Banner/index.ts
index bc95f09d6..ffa9c8785 100644
--- a/packages/common/src/ui/components/Banner/index.ts
+++ b/packages/common/src/ui/components/Banner/index.ts
@@ -1 +1,2 @@
export * from './Banner';
+export * from './WarningBanner';
diff --git a/packages/staking/src/features/Drawer/TransactionFail.tsx b/packages/staking/src/features/Drawer/TransactionFail.tsx
index 26e441cf5..a9ddf59ad 100644
--- a/packages/staking/src/features/Drawer/TransactionFail.tsx
+++ b/packages/staking/src/features/Drawer/TransactionFail.tsx
@@ -1,5 +1,6 @@
/* eslint-disable react/no-multi-comp */
-import { Button } from '@lace/common';
+import { Button, WarningBanner } from '@lace/common';
+import { Box } from '@lace/ui';
import cn from 'classnames';
import React, { useCallback, useState } from 'react';
import { useTranslation } from 'react-i18next';
@@ -14,12 +15,26 @@ type TransactionFailProps = {
export const TransactionFail = ({ popupView }: TransactionFailProps): React.ReactElement => {
const { t } = useTranslation();
+ const { isCustomSubmitApiEnabled } = useOutsideHandles();
return (
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
-
+
+ {t('drawer.failure.subTitle')}
+ {isCustomSubmitApiEnabled && (
+
+
+
+ )}
+ >
+ }
+ />
);
diff --git a/packages/staking/src/features/i18n/translations/en.ts b/packages/staking/src/features/i18n/translations/en.ts
index 8b5a1840a..0778ff1a3 100644
--- a/packages/staking/src/features/i18n/translations/en.ts
+++ b/packages/staking/src/features/i18n/translations/en.ts
@@ -106,6 +106,8 @@ export const en: Translations = {
'drawer.failure.button.close': 'Close',
'drawer.failure.button.removePools': 'Remove pools',
'drawer.failure.button.retry': 'Retry',
+ 'drawer.failure.customSubmitApiWarning':
+ 'Custom submit API enabled to send transactions. To disable, go to Settings >> Custom submit API',
'drawer.failure.deviceUpdate.subTitle':
'Your device needs to be up to date in order to use Multi-delegation. You can still delegate to a single pool with your current version',
'drawer.failure.deviceUpdate.title': 'Device update required',
diff --git a/packages/staking/src/features/i18n/types.ts b/packages/staking/src/features/i18n/types.ts
index ba917d8c1..f1562258d 100644
--- a/packages/staking/src/features/i18n/types.ts
+++ b/packages/staking/src/features/i18n/types.ts
@@ -134,6 +134,7 @@ type KeysStructure = {
title: '';
subTitle: '';
};
+ customSubmitApiWarning: '';
};
details: {
metrics: {
diff --git a/packages/staking/src/features/outside-handles-provider/types.ts b/packages/staking/src/features/outside-handles-provider/types.ts
index 66d1c28ab..6ab94b359 100644
--- a/packages/staking/src/features/outside-handles-provider/types.ts
+++ b/packages/staking/src/features/outside-handles-provider/types.ts
@@ -108,4 +108,5 @@ export type OutsideHandlesContextValue = {
walletAddress: string;
currentChain: Wallet.Cardano.ChainId;
isMultidelegationSupportedByDevice: (walletType: string) => Promise;
+ isCustomSubmitApiEnabled: boolean;
};