diff --git a/wallets/rn_cli_wallet/ios/Podfile.lock b/wallets/rn_cli_wallet/ios/Podfile.lock
index 69380559..d5fb96f6 100644
--- a/wallets/rn_cli_wallet/ios/Podfile.lock
+++ b/wallets/rn_cli_wallet/ios/Podfile.lock
@@ -1811,7 +1811,7 @@ PODS:
- React-RCTFBReactNativeSpec
- ReactCommon/turbomodule/core
- SocketRocket
- - react-native-compat (2.23.5):
+ - react-native-compat (2.23.5-canary.0):
- boost
- DoubleConversion
- fast_float
@@ -1839,7 +1839,7 @@ PODS:
- ReactCommon/turbomodule/core
- SocketRocket
- Yoga
- - YttriumWrapper (= 0.10.37)
+ - YttriumWrapper (= 0.10.40)
- react-native-config (1.5.5):
- react-native-config/App (= 1.5.5)
- react-native-config/App (1.5.5):
@@ -3069,7 +3069,7 @@ PODS:
- VisionCamera/React (4.7.2):
- React-Core
- Yoga (0.0.0)
- - YttriumWrapper (0.10.37)
+ - YttriumWrapper (0.10.40)
DEPENDENCIES:
- boost (from `../node_modules/react-native/third-party-podspecs/boost.podspec`)
@@ -3413,7 +3413,7 @@ SPEC CHECKSUMS:
React-logger: 30adf849117e87cf86e88dca1824bb0f18f87e10
React-Mapbuffer: 499069c3dcd4b438a70fcc2a65e8a4185ea9170b
React-microtasksnativemodule: f0238469cb9894fd18c419137d312665b8fc05b3
- react-native-compat: 33720a178be8c565138dfdaa5d9d931f59786d2f
+ react-native-compat: 15386cd0e3059d55d58985cff53e3edaab14e4b0
react-native-config: 644074ab88db883fcfaa584f03520ec29589d7df
react-native-get-random-values: d16467cf726c618e9c7a8c3c39c31faa2244bbba
react-native-keyboard-controller: f2ed31d12d9d8cb8ad2f9110c18fa5df499b66a3
@@ -3469,8 +3469,8 @@ SPEC CHECKSUMS:
SocketRocket: d4aabe649be1e368d1318fdf28a022d714d65748
VisionCamera: 30b358b807324c692064f78385e9a732ce1bebfe
Yoga: edeb9900b9e5bb5b27b9a6a2d5914e4fe4033c1b
- YttriumWrapper: 2ae3722e8f07fde214725edd499679d03e7e86c9
+ YttriumWrapper: e99db26ea3ca6b4580933320e11e046f9607525a
PODFILE CHECKSUM: c628b2429557a37c740a92f2f7ffe4c0bbb44669
-COCOAPODS: 1.14.3
+COCOAPODS: 1.16.2
diff --git a/wallets/rn_cli_wallet/package.json b/wallets/rn_cli_wallet/package.json
index c92b87d3..43f76bb8 100644
--- a/wallets/rn_cli_wallet/package.json
+++ b/wallets/rn_cli_wallet/package.json
@@ -40,7 +40,7 @@
"@ton/core": "0.62.0",
"@ton/crypto": "3.3.0",
"@ton/ton": "15.4.0",
- "@walletconnect/react-native-compat": "2.23.5",
+ "@walletconnect/react-native-compat": "2.23.5-canary.0",
"@zoontek/react-native-navigation-bar": "^1.0.2",
"bip39": "3.1.0",
"crc-32": "^1.2.2",
@@ -121,7 +121,8 @@
"valibot": "1.2.0",
"tar": "7.5.7",
"js-yaml": "4.1.1",
- "lodash": "4.17.23"
+ "lodash": "4.17.23",
+ "@walletconnect/pay": "1.0.4-canary.0"
},
"packageManager": "yarn@3.8.7"
}
diff --git a/wallets/rn_cli_wallet/src/modals/PaymentOptionsModal/CollectDataWebView.tsx b/wallets/rn_cli_wallet/src/modals/PaymentOptionsModal/CollectDataWebView.tsx
index d333d5c0..81ed58ce 100644
--- a/wallets/rn_cli_wallet/src/modals/PaymentOptionsModal/CollectDataWebView.tsx
+++ b/wallets/rn_cli_wallet/src/modals/PaymentOptionsModal/CollectDataWebView.tsx
@@ -12,6 +12,21 @@ import { Spacing } from '@/utils/ThemeUtil';
import LogStore from '@/store/LogStore';
import SettingsStore from '@/store/SettingsStore';
+// Forces the page to fit within the WebView viewport without scrolling
+const FIT_CONTENT_JS = `
+ (function() {
+ var meta = document.querySelector('meta[name="viewport"]');
+ if (!meta) {
+ meta = document.createElement('meta');
+ meta.name = 'viewport';
+ document.head.appendChild(meta);
+ }
+ meta.content = 'width=device-width, initial-scale=1, maximum-scale=1, shrink-to-fit=yes';
+ document.body.style.overflow = 'hidden';
+ })();
+ true;
+`;
+
function getBaseUrl(urlString: string): string {
try {
const urlObj = new URL(urlString);
@@ -209,8 +224,9 @@ export function CollectDataWebView({
javaScriptEnabled
domStorageEnabled
startInLoadingState
- scalesPageToFit
+ scalesPageToFit={true}
showsVerticalScrollIndicator={false}
+ injectedJavaScript={FIT_CONTENT_JS}
/>
);
diff --git a/wallets/rn_cli_wallet/src/modals/PaymentOptionsModal/ConfirmPaymentView.tsx b/wallets/rn_cli_wallet/src/modals/PaymentOptionsModal/ConfirmPaymentView.tsx
index a6270978..61121135 100644
--- a/wallets/rn_cli_wallet/src/modals/PaymentOptionsModal/ConfirmPaymentView.tsx
+++ b/wallets/rn_cli_wallet/src/modals/PaymentOptionsModal/ConfirmPaymentView.tsx
@@ -2,41 +2,30 @@ import { View, Image, StyleSheet, ScrollView } from 'react-native';
import type { PaymentInfo, PaymentOption } from '@walletconnect/pay';
import { useTheme } from '@/hooks/useTheme';
-import LogStore from '@/store/LogStore';
import { ActionButton } from '@/components/ActionButton';
import { formatAmount, getCurrencySymbol } from './utils';
import { MerchantInfo } from './MerchantInfo';
-import SvgCaretUpDown from '@/assets/CaretUpDown';
import { PresetsUtil } from '@/utils/PresetsUtil';
-import { useCallback, useEffect, useState } from 'react';
-import Animated, {
- Easing,
- useAnimatedStyle,
- useSharedValue,
- withTiming,
-} from 'react-native-reanimated';
+import { useCallback } from 'react';
import { Spacing, BorderRadius } from '@/utils/ThemeUtil';
import { Text } from '@/components/Text';
import { Button } from '@/components/Button';
+import type { PaymentOptionWithCollectData } from '@/utils/TypesUtil';
-const OPTION_HEIGHT = 64;
const OPTION_GAP = 8;
-const COLLAPSED_HEIGHT = 0;
-const ANIMATION_DURATION = 250;
+const MAX_VISIBLE_OPTIONS = 4;
+const OPTION_HEIGHT = 64;
// ----- Option Item Component -----
interface OptionItemProps {
option: PaymentOption;
isSelected: boolean;
+ hasCollectData: boolean;
onSelect: (option: PaymentOption) => void;
}
-/**
- * Individual payment option item component.
- * Displays the amount, asset symbol, network name, and selection state.
- */
-function OptionItem({ option, isSelected, onSelect }: OptionItemProps) {
+function OptionItem({ option, isSelected, hasCollectData, onSelect }: OptionItemProps) {
const Theme = useTheme();
const amount = formatAmount(
@@ -85,22 +74,19 @@ function OptionItem({ option, isSelected, onSelect }: OptionItemProps) {
{amount} {option.amount.display.assetSymbol}
-
- {isSelected && (
-
+ {hasCollectData && (
-
- )}
+ >
+
+ Info required
+
+
+ )}
+
);
}
@@ -116,6 +102,8 @@ interface ConfirmPaymentViewProps {
onSelectOption: (option: PaymentOption) => void;
onApprove: () => void;
info?: PaymentInfo;
+ showNextButton: boolean;
+ collectDataCompletedIds: string[];
}
export function ConfirmPaymentView({
@@ -126,63 +114,32 @@ export function ConfirmPaymentView({
onApprove,
info,
isLoadingActions,
+ showNextButton,
+ collectDataCompletedIds,
}: ConfirmPaymentViewProps) {
const Theme = useTheme();
- const [isExpanded, setIsExpanded] = useState(false);
- const amount = formatAmount(
+ const payAmount = formatAmount(
info?.amount?.value || '0',
info?.amount?.display?.decimals || 0,
2,
);
const currencySymbol = getCurrencySymbol(info?.amount?.display?.assetSymbol);
- const chainIcon = PresetsUtil.getIconLogoByName(
- selectedOption?.amount?.display?.networkName,
- );
-
- // Calculate max height based on number of options (max 4 visible, then scroll)
- const maxVisibleOptions = 4;
- const optionsCount = options.length;
- const visibleCount = Math.min(optionsCount, maxVisibleOptions);
- const calculatedHeight =
- visibleCount * OPTION_HEIGHT + (visibleCount - 1) * OPTION_GAP;
-
- const expandedHeight = useSharedValue(COLLAPSED_HEIGHT);
-
- useEffect(() => {
- expandedHeight.value = withTiming(
- isExpanded ? calculatedHeight : COLLAPSED_HEIGHT,
- {
- duration: ANIMATION_DURATION,
- easing: Easing.bezier(0.25, 0.1, 0.25, 1),
- },
- );
- }, [isExpanded, calculatedHeight, expandedHeight]);
-
- const animatedContainerStyle = useAnimatedStyle(() => ({
- height: expandedHeight.value,
- opacity: expandedHeight.value > 0 ? 1 : 0,
- }));
+ const selectedCompleted =
+ selectedOption && collectDataCompletedIds.includes(selectedOption.id);
+ const visibleOptions = selectedCompleted
+ ? options.filter(o => o.id === selectedOption.id)
+ : options;
- const toggleExpanded = useCallback(() => {
- LogStore.log(
- 'Toggle payment options',
- 'ConfirmPaymentView',
- 'toggleExpanded',
- {
- optionsLength: options.length,
- },
- );
- if (options.length > 1) {
- setIsExpanded(prev => !prev);
- }
- }, [options.length]);
+ const visibleCount = visibleOptions.length;
+ const scrollable = visibleCount > MAX_VISIBLE_OPTIONS;
+ const listMaxHeight =
+ MAX_VISIBLE_OPTIONS * OPTION_HEIGHT + (MAX_VISIBLE_OPTIONS - 1) * OPTION_GAP;
const handleSelectOption = useCallback(
(option: PaymentOption) => {
onSelectOption(option);
- setIsExpanded(false);
},
[onSelectOption],
);
@@ -191,94 +148,25 @@ export function ConfirmPaymentView({
<>
-
-
- Amount
-
-
- {currencySymbol}
- {amount}
-
-
-
-
-
-
- {/* Expandable Options List */}
-
- maxVisibleOptions}
- nestedScrollEnabled
- >
- {options.map(option => (
-
- ))}
-
-
-
+ {visibleOptions.map(option => (
+
+ ))}
+
{/* Action Buttons */}
@@ -287,8 +175,7 @@ export function ConfirmPaymentView({
disabled={isSigningPayment || isLoadingActions || !selectedOption}
fullWidth
>
- Pay {currencySymbol}
- {amount}
+ {showNextButton ? 'Next' : `Pay ${currencySymbol}${payAmount}`}
>
@@ -296,36 +183,12 @@ export function ConfirmPaymentView({
}
const styles = StyleSheet.create({
- amountRow: {
- flexDirection: 'row',
- justifyContent: 'space-between',
- alignItems: 'center',
- paddingHorizontal: Spacing[5],
- height: Spacing[13],
- borderRadius: BorderRadius[5],
- marginBottom: Spacing[2],
- marginTop: Spacing[5],
- },
- payWithContainer: {
- borderRadius: BorderRadius[5],
- },
- payWithContainerExpanded: {
- paddingBottom: Spacing[3],
- },
- payWithRow: {
- flexDirection: 'row',
- justifyContent: 'space-between',
- alignItems: 'center',
- height: Spacing[13],
- paddingHorizontal: Spacing[5],
- },
- optionsContainer: {
- maxHeight: 300,
+ optionsList: {
+ marginTop: Spacing[4],
+ flexGrow: 0,
},
- optionCard: {
- flexDirection: 'row',
- alignItems: 'center',
- gap: Spacing[2],
+ optionsListContent: {
+ gap: OPTION_GAP,
},
optionItem: {
flexDirection: 'row',
@@ -338,25 +201,18 @@ const styles = StyleSheet.create({
flexDirection: 'row',
alignItems: 'center',
gap: Spacing[2],
+ flex: 1,
+ },
+ collectDataPill: {
+ paddingHorizontal: Spacing[2],
+ paddingVertical: 2,
+ borderRadius: BorderRadius.full,
+ marginLeft: 'auto',
},
optionIconContainer: {
width: Spacing[8],
height: Spacing[8],
},
- selectedOptionIcon: {
- width: Spacing[6],
- height: Spacing[6],
- borderRadius: BorderRadius.full,
- },
- selectedOptionChainIcon: {
- height: 14,
- width: 14,
- position: 'absolute',
- borderRadius: BorderRadius.full,
- borderWidth: 2,
- right: -1,
- bottom: -2,
- },
optionIcon: {
width: Spacing[8],
height: Spacing[8],
@@ -371,28 +227,9 @@ const styles = StyleSheet.create({
right: -2,
bottom: -2,
},
- radioOuter: {
- height: 22,
- width: 22,
- borderWidth: 1,
- borderRadius: BorderRadius.full,
- alignItems: 'center',
- justifyContent: 'center',
- },
- radioInner: {
- height: Spacing[3],
- width: Spacing[3],
- borderRadius: BorderRadius.full,
- },
- optionsScrollView: {
- flex: 1,
- },
- optionsScrollContent: {
- gap: OPTION_GAP,
- paddingHorizontal: Spacing[5],
- },
buttonContainer: {
marginTop: Spacing[5],
+ marginBottom: Spacing[2],
gap: Spacing[2],
},
});
diff --git a/wallets/rn_cli_wallet/src/modals/PaymentOptionsModal/InfoExplainerView.tsx b/wallets/rn_cli_wallet/src/modals/PaymentOptionsModal/InfoExplainerView.tsx
new file mode 100644
index 00000000..23a574ea
--- /dev/null
+++ b/wallets/rn_cli_wallet/src/modals/PaymentOptionsModal/InfoExplainerView.tsx
@@ -0,0 +1,53 @@
+import { View, StyleSheet } from 'react-native';
+
+import { Text } from '@/components/Text';
+import { ActionButton } from '@/components/ActionButton';
+import { Spacing } from '@/utils/ThemeUtil';
+
+interface InfoExplainerViewProps {
+ onDismiss: () => void;
+}
+
+export function InfoExplainerView({ onDismiss }: InfoExplainerViewProps) {
+ return (
+
+
+ Why we need your information?
+
+
+
+ For regulatory compliance, we collect basic information on your first
+ payment: full name, date of birth, and place of birth.
+
+
+
+ This information is tied to your wallet address and this specific
+ network. If you use the same wallet on this network again, you won't
+ need to provide it again.
+
+
+
+
+ Got it!
+
+
+
+ );
+}
+
+const styles = StyleSheet.create({
+ container: {
+ paddingTop: Spacing[2],
+ },
+ title: {
+ marginBottom: Spacing[4],
+ textAlign: 'center',
+ },
+ body: {
+ marginBottom: Spacing[3],
+ },
+ buttonContainer: {
+ marginTop: Spacing[5],
+ marginBottom: Spacing[2],
+ },
+});
diff --git a/wallets/rn_cli_wallet/src/modals/PaymentOptionsModal/ResultView.tsx b/wallets/rn_cli_wallet/src/modals/PaymentOptionsModal/ResultView.tsx
index 491d0dcf..305c9b20 100644
--- a/wallets/rn_cli_wallet/src/modals/PaymentOptionsModal/ResultView.tsx
+++ b/wallets/rn_cli_wallet/src/modals/PaymentOptionsModal/ResultView.tsx
@@ -132,6 +132,7 @@ const styles = StyleSheet.create({
},
footerContainer: {
paddingTop: Spacing[11],
+ marginBottom: Spacing[2],
alignItems: 'center',
},
});
diff --git a/wallets/rn_cli_wallet/src/modals/PaymentOptionsModal/ViewWrapper.tsx b/wallets/rn_cli_wallet/src/modals/PaymentOptionsModal/ViewWrapper.tsx
index 56292eb1..e9e71166 100644
--- a/wallets/rn_cli_wallet/src/modals/PaymentOptionsModal/ViewWrapper.tsx
+++ b/wallets/rn_cli_wallet/src/modals/PaymentOptionsModal/ViewWrapper.tsx
@@ -22,6 +22,7 @@ interface ViewWrapperProps {
showBackButton: boolean;
onBack: () => void;
onClose: () => void;
+ headerLeftContent?: React.ReactNode;
}
const ANIMATION_DURATION = 250;
@@ -33,6 +34,7 @@ export function ViewWrapper({
showBackButton,
onBack,
onClose,
+ headerLeftContent,
}: ViewWrapperProps) {
const Theme = useTheme();
const insets = useSafeAreaInsets();
@@ -41,8 +43,8 @@ export function ViewWrapper({
<>
{/* Header */}
-
- {showBackButton && !isWebView && (
+
+ {showBackButton ? (
- )}
+ ) : headerLeftContent ? (
+ headerLeftContent
+ ) : null}
{/* Spacer */}
@@ -82,7 +86,7 @@ export function ViewWrapper({
{content}
@@ -127,6 +131,11 @@ const styles = StyleSheet.create({
alignItems: 'flex-start',
justifyContent: 'center',
},
+ headerLeftFlex: {
+ height: 38,
+ alignItems: 'flex-start',
+ justifyContent: 'center',
+ },
headerCenter: {
flex: 1,
},
diff --git a/wallets/rn_cli_wallet/src/modals/PaymentOptionsModal/index.tsx b/wallets/rn_cli_wallet/src/modals/PaymentOptionsModal/index.tsx
index ddfe8752..fc774ce9 100644
--- a/wallets/rn_cli_wallet/src/modals/PaymentOptionsModal/index.tsx
+++ b/wallets/rn_cli_wallet/src/modals/PaymentOptionsModal/index.tsx
@@ -1,24 +1,34 @@
-import { useCallback, useEffect } from 'react';
+import { useCallback, useEffect, useState } from 'react';
+import { StyleSheet } from 'react-native';
import { useSnapshot } from 'valtio';
import LogStore from '@/store/LogStore';
import ModalStore from '@/store/ModalStore';
import PaymentStore from '@/store/PaymentStore';
import type { PaymentOption } from '@walletconnect/pay';
+import type { PaymentOptionWithCollectData } from '@/utils/TypesUtil';
+import { useTheme } from '@/hooks/useTheme';
+import { Text } from '@/components/Text';
+import { Button } from '@/components/Button';
+import { BorderRadius, Spacing } from '@/utils/ThemeUtil';
import { LoadingView } from './LoadingView';
import { CollectDataWebView } from './CollectDataWebView';
import { ConfirmPaymentView } from './ConfirmPaymentView';
+import { InfoExplainerView } from './InfoExplainerView';
import { ResultView } from './ResultView';
import { ViewWrapper } from './ViewWrapper';
import { detectErrorType, getErrorMessage } from './utils';
export default function PaymentOptionsModal() {
const snap = useSnapshot(PaymentStore.state);
+ const Theme = useTheme();
+ const [showInfoExplainer, setShowInfoExplainer] = useState(false);
- const collectDataUrl = snap.paymentOptions?.collectData?.url;
+ const selectedOptionCollectDataUrl = (
+ snap.selectedOption as PaymentOptionWithCollectData | null
+ )?.collectData?.url;
- // Transition from loading to the next step when data is available
useEffect(() => {
if (snap.step === 'loading') {
if (snap.errorMessage) {
@@ -35,7 +45,6 @@ export default function PaymentOptionsModal() {
errorType,
});
} else if (snap.paymentOptions) {
- // Check for empty options
if (!snap.paymentOptions.options || snap.paymentOptions.options.length === 0) {
LogStore.warn(
'No payment options available',
@@ -49,19 +58,17 @@ export default function PaymentOptionsModal() {
message: getErrorMessage('insufficient_funds'),
});
} else {
- if (collectDataUrl) {
- // Collect data via WebView (intro is handled inside the WebView)
- PaymentStore.setStep('collectData');
- } else {
- // No collect data needed, go directly to confirm
- PaymentStore.setStep('confirm');
- }
+ PaymentStore.setStep('confirm');
}
}
}
- }, [snap.step, snap.paymentOptions, snap.errorMessage, collectDataUrl]);
+ }, [snap.step, snap.paymentOptions, snap.errorMessage]);
const handleWebViewComplete = useCallback(() => {
+ const { selectedOption } = PaymentStore.state;
+ if (selectedOption) {
+ PaymentStore.markCollectDataCompleted(selectedOption.id);
+ }
PaymentStore.setStep('confirm');
}, []);
@@ -82,30 +89,41 @@ export default function PaymentOptionsModal() {
const goBack = useCallback(() => {
const { step } = PaymentStore.state;
switch (step) {
+ case 'collectData':
+ PaymentStore.setStep('confirm');
+ break;
case 'confirm':
- PaymentStore.clearSelectedOption();
- if (collectDataUrl) {
- PaymentStore.setStep('collectData');
- } else {
- onClose();
- }
+ onClose();
break;
default:
onClose();
}
- }, [onClose, collectDataUrl]);
+ }, [onClose]);
const onSelectOption = useCallback((option: PaymentOption) => {
PaymentStore.selectOption(option);
PaymentStore.fetchPaymentActions(option);
}, []);
- // Auto-select first payment option when entering confirm step
+ const handleConfirmOrNext = useCallback(() => {
+ const { selectedOption, collectDataCompletedIds } = PaymentStore.state;
+ if (!selectedOption) return;
+
+ const option = selectedOption as PaymentOptionWithCollectData;
+ const needsCollectData = !!option.collectData?.url;
+ const alreadyCompleted = collectDataCompletedIds.includes(option.id);
+
+ if (needsCollectData && !alreadyCompleted) {
+ PaymentStore.setStep('collectData');
+ } else {
+ PaymentStore.approvePayment();
+ }
+ }, []);
+
useEffect(() => {
if (snap.step === 'confirm') {
const options = snap.paymentOptions?.options || [];
- // Fallback check (main check is in useEffect)
if (options.length === 0) {
PaymentStore.setResult({
status: 'error',
@@ -121,7 +139,17 @@ export default function PaymentOptionsModal() {
}
}, [snap.step, snap.paymentOptions?.options, snap.selectedOption, onSelectOption]);
+ const selectedNeedsCollectData = !!(
+ snap.selectedOption &&
+ (snap.selectedOption as PaymentOptionWithCollectData).collectData?.url &&
+ !snap.collectDataCompletedIds.includes(snap.selectedOption.id)
+ );
+
const renderContent = useCallback(() => {
+ if (showInfoExplainer) {
+ return setShowInfoExplainer(false)} />;
+ }
+
switch (snap.step) {
case 'loading':
return (
@@ -133,7 +161,7 @@ export default function PaymentOptionsModal() {
case 'collectData':
return (
@@ -149,7 +177,9 @@ export default function PaymentOptionsModal() {
isSigningPayment={false}
error={snap.actionsError}
onSelectOption={onSelectOption}
- onApprove={PaymentStore.approvePayment}
+ onApprove={handleConfirmOrNext}
+ showNextButton={selectedNeedsCollectData}
+ collectDataCompletedIds={snap.collectDataCompletedIds as string[]}
/>
);
@@ -179,26 +209,56 @@ export default function PaymentOptionsModal() {
snap.resultMessage,
snap.loadingMessage,
snap.paymentOptions,
- collectDataUrl,
+ snap.collectDataCompletedIds,
+ selectedOptionCollectDataUrl,
+ selectedNeedsCollectData,
+ showInfoExplainer,
handleWebViewComplete,
handleWebViewError,
+ handleConfirmOrNext,
onSelectOption,
onClose,
]);
- // Show back button when there's a previous step to go back to
- const showBackButton = snap.step === 'confirm' && !!collectDataUrl;
- const isWebView = snap.step === 'collectData' && !!collectDataUrl;
+ const showBackButton = snap.step === 'collectData';
+ const isWebView = snap.step === 'collectData' && !!selectedOptionCollectDataUrl;
+
+ const headerLeftContent =
+ snap.step === 'confirm' && selectedNeedsCollectData && !showInfoExplainer ? (
+
+ ) : undefined;
return (
setShowInfoExplainer(false) : onClose}
+ headerLeftContent={headerLeftContent}
>
{renderContent()}
);
}
+
+const styles = StyleSheet.create({
+ infoButton: {
+ borderRadius: BorderRadius[3],
+ borderWidth: 1,
+ alignItems: 'center',
+ justifyContent: 'center',
+ paddingHorizontal: Spacing[3],
+ paddingVertical: Spacing[2] + 2,
+ },
+});
diff --git a/wallets/rn_cli_wallet/src/store/PaymentStore.ts b/wallets/rn_cli_wallet/src/store/PaymentStore.ts
index 90122dcd..56387da4 100644
--- a/wallets/rn_cli_wallet/src/store/PaymentStore.ts
+++ b/wallets/rn_cli_wallet/src/store/PaymentStore.ts
@@ -37,6 +37,9 @@ interface PaymentState {
paymentActions: any[] | null;
isLoadingActions: boolean;
actionsError: string | null;
+
+ // Tracks option IDs that have completed collectData
+ collectDataCompletedIds: string[];
}
/**
@@ -55,6 +58,7 @@ const initialState: PaymentState = {
paymentActions: null,
isLoadingActions: false,
actionsError: null,
+ collectDataCompletedIds: [],
};
/**
@@ -138,6 +142,16 @@ const PaymentStore = {
state.actionsError = null;
},
+ markCollectDataCompleted(optionId: string) {
+ if (!state.collectDataCompletedIds.includes(optionId)) {
+ state.collectDataCompletedIds.push(optionId);
+ }
+ },
+
+ isCollectDataCompleted(optionId: string): boolean {
+ return state.collectDataCompletedIds.includes(optionId);
+ },
+
setPaymentActions(actions: any[]) {
state.paymentActions = ref(actions);
},
diff --git a/wallets/rn_cli_wallet/src/utils/TypesUtil.ts b/wallets/rn_cli_wallet/src/utils/TypesUtil.ts
index c9dcfd30..3ac787fe 100644
--- a/wallets/rn_cli_wallet/src/utils/TypesUtil.ts
+++ b/wallets/rn_cli_wallet/src/utils/TypesUtil.ts
@@ -96,4 +96,10 @@ export type Step =
| 'collectData'
| 'confirm'
| 'confirming'
- | 'result';
\ No newline at end of file
+ | 'result';
+
+// Extended PaymentOption with per-option collectData (SDK types not yet updated)
+import type { PaymentOption, CollectDataAction } from '@walletconnect/pay';
+export interface PaymentOptionWithCollectData extends PaymentOption {
+ collectData?: CollectDataAction;
+}
\ No newline at end of file
diff --git a/wallets/rn_cli_wallet/yarn.lock b/wallets/rn_cli_wallet/yarn.lock
index 16997bc6..7a1975d7 100644
--- a/wallets/rn_cli_wallet/yarn.lock
+++ b/wallets/rn_cli_wallet/yarn.lock
@@ -4260,9 +4260,9 @@ __metadata:
languageName: node
linkType: hard
-"@walletconnect/pay@npm:1.0.4":
- version: 1.0.4
- resolution: "@walletconnect/pay@npm:1.0.4"
+"@walletconnect/pay@npm:1.0.4-canary.0":
+ version: 1.0.4-canary.0
+ resolution: "@walletconnect/pay@npm:1.0.4-canary.0"
dependencies:
"@walletconnect/logger": 3.0.2
"@walletconnect/types": 2.23.5
@@ -4273,13 +4273,13 @@ __metadata:
peerDependenciesMeta:
react-native:
optional: true
- checksum: 6ac56d803536bcc8afd3b6ae6c623101214ec8d67e1037f7126d1885c52b35d31424e4b8d3c99b4841fca966e6c827ef10351d0ddd5bf1f215793c44bd140ff8
+ checksum: 99c3943fece7e04dabb5cbf5147ef5d7c8a599c1ef42a4f0c3833706025a21dac3c9e4c1a39f7f2db2132e579ff52c5c8870dc74dc4dc7af6acaad647ef88e14
languageName: node
linkType: hard
-"@walletconnect/react-native-compat@npm:2.23.5":
- version: 2.23.5
- resolution: "@walletconnect/react-native-compat@npm:2.23.5"
+"@walletconnect/react-native-compat@npm:2.23.5-canary.0":
+ version: 2.23.5-canary.0
+ resolution: "@walletconnect/react-native-compat@npm:2.23.5-canary.0"
dependencies:
events: 3.3.0
fast-text-encoding: 1.0.6
@@ -4293,7 +4293,7 @@ __metadata:
peerDependenciesMeta:
expo-application:
optional: true
- checksum: 09d07be80517bf1d4678a1f9974276b636ce285a09e69d8a628af6681e04b66101c1217082bb8a209a9a9ed2862e8697af75fc8c51d24f55c768d0ba962d7226
+ checksum: e741b7ee67d6a5cd7a91dc957c7c8c54e7644a3657744486bce56db03add12420f5c2b1e8682721a95265f7fa3603ba731178ba5249c8945d911c76202fed2fb
languageName: node
linkType: hard
@@ -4467,7 +4467,7 @@ __metadata:
"@types/lodash.clonedeep": ^4.5.9
"@types/react": ^19.1.1
"@types/react-test-renderer": ^19.1.0
- "@walletconnect/react-native-compat": 2.23.5
+ "@walletconnect/react-native-compat": 2.23.5-canary.0
"@zoontek/react-native-navigation-bar": ^1.0.2
babel-plugin-module-resolver: ^5.0.0
bip39: 3.1.0