Skip to content

Commit

Permalink
feat: implement Nano Contract integration with Wallet Connect
Browse files Browse the repository at this point in the history
  • Loading branch information
alexruzenhack committed Jul 3, 2024
1 parent 42ae166 commit d79397b
Show file tree
Hide file tree
Showing 24 changed files with 1,963 additions and 264 deletions.
244 changes: 181 additions & 63 deletions locale/da/texts.po

Large diffs are not rendered by default.

249 changes: 184 additions & 65 deletions locale/pt-br/texts.po

Large diffs are not rendered by default.

244 changes: 181 additions & 63 deletions locale/ru-ru/texts.po

Large diffs are not rendered by default.

243 changes: 180 additions & 63 deletions locale/texts.pot

Large diffs are not rendered by default.

4 changes: 4 additions & 0 deletions src/App.js
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,8 @@ import { NetworkStatusBar } from './components/NetworkSettings/NetworkStatusBar'
import { NanoContractDetailsScreen } from './screens/NanoContract/NanoContractDetailsScreen';
import { NanoContractTransactionScreen } from './screens/NanoContract/NanoContractTransactionScreen';
import { NanoContractRegisterScreen } from './screens/NanoContract/NanoContractRegisterScreen';
import { NewNanoContractTransactionScreen } from './screens/WalletConnect/NewNanoContractTransactionScreen';
import { NewNanoContractTransactionModal } from './components/WalletConnect/NanoContract/NewNanoContractTransactionModal';

/**
* This Stack Navigator is exhibited when there is no wallet initialized on the local storage.
Expand Down Expand Up @@ -387,6 +389,7 @@ const AppStack = () => {
<Stack.Screen name='WalletConnectList' component={WalletConnectList} />
<Stack.Screen name='WalletConnectManual' component={WalletConnectManual} />
<Stack.Screen name='WalletConnectScan' component={WalletConnectScan} />
<Stack.Screen name='NewNanoContractTransactionScreen' component={NewNanoContractTransactionScreen} />
<Stack.Screen name='PushNotification' component={PushNotification} />
<Stack.Screen name='ChangePin' component={ChangePin} />
<Stack.Screen
Expand Down Expand Up @@ -733,6 +736,7 @@ const App = () => (
>
<NetworkStatusBar />
<RootStack />
<NewNanoContractTransactionModal />
</NavigationContainer>
<WalletConnectModal />
<GlobalErrorHandler />
Expand Down
74 changes: 73 additions & 1 deletion src/actions.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import {
metadataApi,
} from '@hathor/wallet-lib';
import {
METADATA_CONCURRENT_DOWNLOAD,
METADATA_CONCURRENT_DOWNLOAD, WALLETCONNECT_NEW_NANOCONTRACT_TX_STATUS,
} from './constants';
import { mapToTxHistory } from './utils';

Expand Down Expand Up @@ -57,6 +57,8 @@ export const types = {
TOKEN_METADATA_LOADED: 'TOKEN_METADATA_LOADED',
SET_UNIQUE_DEVICE_ID: 'SET_UNIQUE_DEVICE_ID',
SET_IS_SHOWING_PIN_SCREEN: 'SET_IS_SHOWING_PIN_SCREEN',
/* It initiates download of tokens metadata. */
TOKENS_FETCH_METADATA_REQUESTED: 'TOKENS_FETCH_METADATA_REQUESTED',
TOKEN_FETCH_METADATA_REQUESTED: 'TOKEN_FETCH_METADATA_REQUESTED',
TOKEN_FETCH_METADATA_SUCCESS: 'TOKEN_FETCH_METADATA_SUCCESS',
TOKEN_FETCH_METADATA_FAILED: 'TOKEN_FETCH_METADATA_FAILED',
Expand Down Expand Up @@ -113,6 +115,9 @@ export const types = {
SET_WALLET_CONNECT: 'SET_WALLET_CONNECT',
SET_WALLET_CONNECT_MODAL: 'SET_WALLET_CONNECT_MODAL',
SET_WALLET_CONNECT_SESSIONS: 'SET_WALLET_CONNECT_SESSIONS',
WALLET_CONNECT_ACCEPT: 'WALLET_CONNECT_ACCEPT',
WALLET_CONNECT_REJECT: 'WALLET_CONNECT_REJECT',
SET_NEW_NANO_CONTRACT_TRANSACTION: 'SET_NEW_NANO_CONTRACT_TRANSACTION',
SET_UNLEASH_CLIENT: 'SET_UNLEASH_CLIENT',
WC_URI_INPUTTED: 'WC_URI_INPUTTED',
WC_CANCEL_SESSION: 'WC_CANCEL_SESSION',
Expand Down Expand Up @@ -175,6 +180,8 @@ export const types = {
FIRSTADDRESS_SUCCESS: 'FIRSTADDRESS_SUCCESS',
/* It signals a fetch failure due to an error. */
FIRSTADDRESS_FAILURE: 'FIRSTADDRESS_FAILURE',
/* It updates the redux state of new nano contract transaction status on wallet connect register. */
WALLETCONNECT_NEW_NANOCONTRACT_STATUS: 'WALLETCONNECT_NEW_NANOCONTRACT_STATUS',
};

export const featureToggleInitialized = () => ({
Expand Down Expand Up @@ -235,6 +242,30 @@ export const walletConnectCancelSession = (sessionKey) => ({
payload: sessionKey,
});

/**
* @param {Object} data Data that the user has accepted.
*/
export const walletConnectAccept = (data) => ({
type: types.WALLET_CONNECT_ACCEPT,
payload: data,
});

export const walletWalletReject = () => ({
type: types.WALLET_CONNECT_REJECT,
});

/**
* @param {Object} ncRequest
* @param {boolean} ncRequest.show
* @param {Object} ncRequest.data
* @param {Object} ncRequest.data.nc
* @param {Object} ncRequest.data.dapp
*/
export const setNewNanoContractTransaction = (ncRequest) => ({
type: types.SET_NEW_NANO_CONTRACT_TRANSACTION,
payload: ncRequest
});

/**
* isShowingPinScreen {bool}
* */
Expand Down Expand Up @@ -1205,3 +1236,44 @@ export const firstAddressFailure = (failurePayload) => ({
type: types.FIRSTADDRESS_FAILURE,
payload: failurePayload,
});

/**
* Request the downalod of token metadata for a list of tokens.
* @param {string[]} tokens A list of token uid
*/
export const tokensFetchMetadataRequest = (tokens) => ({
type: types.TOKENS_FETCH_METADATA_REQUESTED,
tokens
});

/**
* Signals update on new nano contract status to ready.
*/
export const setNewNanoContractStatusReady = () => ({
type: types.WALLETCONNECT_NEW_NANOCONTRACT_STATUS,
payload: WALLETCONNECT_NEW_NANOCONTRACT_TX_STATUS.READY,
});

/**
* Signals update on new nano contract status to loading.
*/
export const setNewNanoContractStatusLoading = () => ({
type: types.WALLETCONNECT_NEW_NANOCONTRACT_STATUS,
payload: WALLETCONNECT_NEW_NANOCONTRACT_TX_STATUS.LOADING,
});

/**
* Signals update on new nano contract status to failed.
*/
export const setNewNanoContractStatusFailure = () => ({
type: types.WALLETCONNECT_NEW_NANOCONTRACT_STATUS,
payload: WALLETCONNECT_NEW_NANOCONTRACT_TX_STATUS.FAILED,
});

/**
* Signals update on new nano contract status to successful.
*/
export const setNewNanoContractStatusSuccess = () => ({
type: types.WALLETCONNECT_NEW_NANOCONTRACT_STATUS,
payload: WALLETCONNECT_NEW_NANOCONTRACT_TX_STATUS.SUCCESSFUL,
});
28 changes: 25 additions & 3 deletions src/components/FeedbackContent.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import { COLORS } from '../styles/themes';
* @param {Object?} props.action A react component or react element containing a call to action,
* if provided, it renders underneath the content
* @param {boolean} props.offcard Renders a feedback without card style
* @param {boolean} props.offmargin Renders a feedback without margins
*
* @example
* <FeedbackContent
Expand All @@ -34,8 +35,22 @@ import { COLORS } from '../styles/themes';
* action={<TryAgain ncId={ncId} />}
* />
*/
export const FeedbackContent = ({ title, message, icon, action, offcard }) => (
<View style={[styles.container, !offcard && styles.card]}>
export const FeedbackContent = ({
title,
message,
icon,
action,
offcard,
offmargin,
offbackground
}) => (
<View style={[
styles.container,
!offcard && styles.card,
offmargin && styles.offMargin,
offbackground && styles.offBackground
]}
>
<View style={styles.wrapper}>
<View style={styles.content}>
{icon
Expand All @@ -55,8 +70,8 @@ const styles = StyleSheet.create({
alignSelf: 'stretch',
marginTop: 16,
marginBottom: 45,
backgroundColor: COLORS.backgroundColor,
marginHorizontal: 16,
backgroundColor: COLORS.backgroundColor,
},
card: {
borderRadius: 16,
Expand All @@ -65,6 +80,13 @@ const styles = StyleSheet.create({
shadowColor: COLORS.textColor,
shadowOpacity: 0.08,
},
offMargin: {
marginHorizontal: 0,
marginVertical: 0,
},
offBackground: {
backgroundColor: COLORS.lowContrastDetail,
},
wrapper: {
overflow: 'scroll',
},
Expand Down
13 changes: 13 additions & 0 deletions src/components/FeedbackModal.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,19 @@ import { Text, View } from 'react-native';
import PropTypes from 'prop-types';
import HathorModal from './HathorModal';

/**
* It renders a modal with some feedback to user.
*
* @param {Object} props
*
* @example
* <FeedbackModal
* icon={(<Image source={errorIcon} resizeMode='contain' />)}
* text={t`Error while sending transaction.`}
* onDismiss={handleFeedbackModalDismiss}
* action={(<NewHathorButton discrete title={t`Ok, close`} onPress={handleErrorModalAction} />)}
* />
*/
const FeedbackModal = (props) => (
<HathorModal
onDismiss={props.onDismiss}
Expand Down
2 changes: 1 addition & 1 deletion src/components/HathorFlatList.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import { COLORS } from '../styles/themes';
* param {FlatListProps} props
*/
export const HathorFlatList = (props) => (
<View style={styles.wrapper}>
<View style={[styles.wrapper, props.wrapperStyle]}>
<FlatList
ItemSeparatorComponent={ItemSeparator}
// Introduced last to allow overwrite
Expand Down
2 changes: 1 addition & 1 deletion src/components/Icons/CircleInfo.icon.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ export const CircleInfoIcon = ({ size = 20, color = COLORS.white }) => (
>
<G clipPath='url(#a)'>
<Path
fill='#004F7E'
fill={color}
d='M9.167 5.833h1.666V7.5H9.167V5.833Zm0 3.334h1.666v5H9.167v-5Zm.833-7.5A8.336 8.336 0 0 0 1.667 10c0 4.6 3.733 8.333 8.333 8.333S18.333 14.6 18.333 10 14.6 1.667 10 1.667Zm0 15A6.675 6.675 0 0 1 3.333 10 6.676 6.676 0 0 1 10 3.333 6.676 6.676 0 0 1 16.667 10 6.675 6.675 0 0 1 10 16.667Z'
/>
</G>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import { COLORS } from '../../styles/themes';
import { combineURLs, getShortContent, getShortHash, getTimestampFormat } from '../../utils';
import SimpleButton from '../SimpleButton';
import { ArrowDownIcon } from '../Icons/ArrowDown.icon';
import { ArrowUpIcon } from '../Icons/ArrowUp.icon';

Check warning on line 23 in src/components/NanoContract/NanoContractTransactionHeader.js

View workflow job for this annotation

GitHub Actions / test (14.x)

'ArrowUpIcon' is defined but never used

Check warning on line 23 in src/components/NanoContract/NanoContractTransactionHeader.js

View workflow job for this annotation

GitHub Actions / test (16.x)

'ArrowUpIcon' is defined but never used
import { TextValue } from '../TextValue';
import { TextLabel } from '../TextLabel';
import { TransactionStatusLabel } from '../TransactionStatusLabel';
Expand Down
84 changes: 84 additions & 0 deletions src/components/WalletConnect/NanoContract/DappContainer.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
/**
* Copyright (c) Hathor Labs and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/

import React from 'react';
import {
StyleSheet,
View,
Text,
Image
} from 'react-native';
import { t } from 'ttag';
import { commonStyles } from '../theme';

/**
* Renders DApp information.
*
* @param {Object} props
* @param {Object} props.dapp
*/
export const DappContainer = ({ dapp }) => (
<View style={styles.container}>
<View style={styles.header}>
<View style={styles.avatar}>
<Image
source={{ uri: dapp.icon }}
width={48}
height={48}
style={styles.avatarIcon}
/>
</View>
<View>
<Text style={styles.proposer}>{dapp.proposer}</Text>
<Text style={styles.network}>{'• '}{'mainnet'}</Text>
</View>
</View>
<View>
<Text style={styles.emphasis}>{t`Review your transaction from this dApp`}</Text>
</View>
<View>
<Text style={commonStyles.text}>{t`Stay vigilant and protect your data from potential phishing attempts.`}</Text>
</View>
</View>
);

const styles = StyleSheet.create({
container: {
gap: 16,
paddingVertical: 16,
paddingHorizontal: 16,
},
header: {
flexDirection: 'row',
gap: 16,
},
avatar: {
flexShrink: 1,
alignSelf: 'flex-start',
maxWidth: 48,
maxHeight: 48,
},
avatarIcon: {
width: 48,
height: 48,
backgroundColor: 'hsla(0, 0%, 85%, 1)',
borderRadius: 24,
},
proposer: [
commonStyles.text,
commonStyles.bold,
commonStyles.mb4,
],
network: [
commonStyles.text,
{ color: 'hsla(263, 100%, 64%, 1)', }
],
emphasis: [
commonStyles.text,
commonStyles.bold
]
});
54 changes: 54 additions & 0 deletions src/components/WalletConnect/NanoContract/DeclineModal.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
/**
* Copyright (c) Hathor Labs and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/

import React from 'react';
import {
StyleSheet,
Text,
} from 'react-native';
import { t } from 'ttag';
import { ModalBase } from '../../ModalBase';

/**
* It renders a confirmation modal to decline the tranaction creation.
*
* @param {Object} props
* @param {boolean} props.show Flag that determines the if the modal should appear or not.
* @param {() => void} props.onDecline Callback fn for decline action.
* @param {() => void} props.onDismiss Callback fn for dismiss action.
*/
export const DeclineModal = ({ show, onDecline, onDismiss }) => (
<ModalBase show={show} onDismiss={onDismiss}>
<ModalBase.Title>{t`Decline transaction`}</ModalBase.Title>
<ModalBase.Body style={styles.declineModalBody}>
<Text style={styles.text}>
{t`Are you sure you want to decline this transaction?`}
</Text>
</ModalBase.Body>
<ModalBase.Button
title={t`Yes, decline transaction`}
secondary
danger
onPress={onDecline}
/>
<ModalBase.DiscreteButton
title={t`No, go back`}
onPress={onDismiss}
/>
</ModalBase>
);

const styles = StyleSheet.create({
declineModalBody: {
paddingBottom: 24,
},
text: {
fontSize: 16,
lineHeight: 20,
textAlign: 'center',
},
});
Loading

0 comments on commit d79397b

Please sign in to comment.