Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions packages/mobile/.env
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
ENVIRONMENT=local
DEFAULT_TESTNET=integration
# If ZERO_SYNC_ENABLED_INITIALLY, local geth will not run initially.
# If FORNO_ENABLED_INITIALLY, local geth will not run initially.
# If toggled on, it will use DEFAULT_SYNC_MODE. See src/geth/consts.ts for more info
ZERO_SYNC_ENABLED_INITIALLY=false
FORNO_ENABLED_INITIALLY=false
DEFAULT_SYNC_MODE=5
FIREBASE_ENABLED=true
SECRETS_KEY=debug
Expand Down
4 changes: 2 additions & 2 deletions packages/mobile/.env.alfajores
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
ENVIRONMENT=alfajores
DEFAULT_TESTNET=alfajores
# If ZERO_SYNC_ENABLED_INITIALLY, local geth will not run initially.
# If FORNO_ENABLED_INITIALLY, local geth will not run initially.
# If toggled on, it will use DEFAULT_SYNC_MODE. See src/geth/consts.ts for more info
ZERO_SYNC_ENABLED_INITIALLY=false
FORNO_ENABLED_INITIALLY=false
DEFAULT_SYNC_MODE=5
DEV_SETTINGS_ACTIVE_INITIALLY=false
FIREBASE_ENABLED=true
Expand Down
4 changes: 2 additions & 2 deletions packages/mobile/.env.integration
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
ENVIRONMENT=integration
DEFAULT_TESTNET=integration
# If ZERO_SYNC_ENABLED_INITIALLY, local geth will not run initially.
# If FORNO_ENABLED_INITIALLY, local geth will not run initially.
# If toggled on, it will use DEFAULT_SYNC_MODE. See src/geth/consts.ts for more info
ZERO_SYNC_ENABLED_INITIALLY=true
FORNO_ENABLED_INITIALLY=true
DEFAULT_SYNC_MODE=5
DEV_SETTINGS_ACTIVE_INITIALLY=true
FIREBASE_ENABLED=true
Expand Down
4 changes: 2 additions & 2 deletions packages/mobile/.env.pilot
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
ENVIRONMENT=pilot
DEFAULT_TESTNET=pilot
# If ZERO_SYNC_ENABLED_INITIALLY, local geth will not run initially.
# If FORNO_ENABLED_INITIALLY, local geth will not run initially.
# If toggled on, it will use DEFAULT_SYNC_MODE. See src/geth/consts.ts for more info
ZERO_SYNC_ENABLED_INITIALLY=true
FORNO_ENABLED_INITIALLY=true
DEFAULT_SYNC_MODE=5
DEV_SETTINGS_ACTIVE_INITIALLY=false
FIREBASE_ENABLED=true
Expand Down
4 changes: 2 additions & 2 deletions packages/mobile/.env.pilotstaging
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
ENVIRONMENT=pilotstaging
DEFAULT_TESTNET=pilotstaging
# If ZERO_SYNC_ENABLED_INITIALLY, local geth will not run initially.
# If FORNO_ENABLED_INITIALLY, local geth will not run initially.
# If toggled on, it will use DEFAULT_SYNC_MODE. See src/geth/consts.ts for more info
ZERO_SYNC_ENABLED_INITIALLY=true
FORNO_ENABLED_INITIALLY=true
DEFAULT_SYNC_MODE=5
DEV_SETTINGS_ACTIVE_INITIALLY=true
FIREBASE_ENABLED=true
Expand Down
4 changes: 2 additions & 2 deletions packages/mobile/.env.production
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
ENVIRONMENT=production
DEFAULT_TESTNET=argentinaproduction
# If ZERO_SYNC_ENABLED_INITIALLY, local geth will not run initially.
# If FORNO_ENABLED_INITIALLY, local geth will not run initially.
# If toggled on, it will use DEFAULT_SYNC_MODE. See src/geth/consts.ts for more info
ZERO_SYNC_ENABLED_INITIALLY=true
FORNO_ENABLED_INITIALLY=true
DEFAULT_SYNC_MODE=5
DEV_SETTINGS_ACTIVE_INITIALLY=false
FIREBASE_ENABLED=true
Expand Down
4 changes: 2 additions & 2 deletions packages/mobile/.env.staging
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
ENVIRONMENT=staging
DEFAULT_TESTNET=alfajoresstaging
# If ZERO_SYNC_ENABLED_INITIALLY, local geth will not run initially.
# If FORNO_ENABLED_INITIALLY, local geth will not run initially.
# If toggled on, it will use DEFAULT_SYNC_MODE. See src/geth/consts.ts for more info
ZERO_SYNC_ENABLED_INITIALLY=false
FORNO_ENABLED_INITIALLY=false
DEFAULT_SYNC_MODE=5
DEV_SETTINGS_ACTIVE_INITIALLY=true
FIREBASE_ENABLED=true
Expand Down
4 changes: 2 additions & 2 deletions packages/mobile/.env.test
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
ENVIRONMENT=local
DEFAULT_TESTNET=integration
# If ZERO_SYNC_ENABLED_INITIALLY, local geth will not run initially.
# If FORNO_ENABLED_INITIALLY, local geth will not run initially.
# If toggled on, it will use DEFAULT_SYNC_MODE. See src/geth/consts.ts for more info
ZERO_SYNC_ENABLED_INITIALLY=true
FORNO_ENABLED_INITIALLY=true
DEFAULT_SYNC_MODE=5
DEV_SETTINGS_ACTIVE_INITIALLY=true
# Disable firebase b.c. google-services.json files are missing in CI
Expand Down
10 changes: 5 additions & 5 deletions packages/mobile/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -88,13 +88,13 @@ renders when no state has changed. Reducing renders can be done via pure
components in react or overloading the should component update method
[example here][rn optimize example].

### Running Wallet app in zero sync (Data Saver) mode
### Running Wallet app in forno (Data Saver) mode

By default, the mobile wallet app runs geth in ultralight sync mode where all the epoch headers are fetched. The default sync mode is defined in [packages/mobile/.env](https://github.com/celo-org/celo-monorepo/blob/master/packages/mobile/.env#L4) file.

To run the wallet in zero sync (Data Saver) mode, using a trusted node rather than the local geth node as a provider, turn it on from the Data Saver page in settings or update the `ZERO_SYNC_ENABLED_INITIALLY` parameter in the .env file linked above. When zero sync mode is turned back off, the wallet will switch to the default sync mode as specified in the .env file. By default, the trusted node is `https://{TESTNET}-forno.celo-testnet.org`, however any trusted node can be used by updating `DEFAULT_FORNO_URL`. In zero sync mode, the wallet signs transactions locally in web3 then sends them to the trusted node.
To run the wallet in forno (Data Saver) mode, using a trusted node rather than the local geth node as a provider, turn it on from the Data Saver page in settings or update the `FORNO_ENABLED_INITIALLY` parameter in the .env file linked above. When forno mode is turned back off, the wallet will switch to the default sync mode as specified in the .env file. By default, the trusted node is `https://{TESTNET}-forno.celo-testnet.org`, however any trusted node can be used by updating `DEFAULT_FORNO_URL`. In forno mode, the wallet signs transactions locally in web3 then sends them to the trusted node.

To debug network requests in zero sync mode, we use Charles, a proxy for monitoring network traffic to see Celo JSON RPC calls and responses. Follow instructions [here](https://community.tealiumiq.com/t5/Tealium-for-Android/Setting-up-Charles-to-Proxy-your-Android-Device/ta-p/5121) to configure Charles to proxy a test device.
To debug network requests in forno mode, we use Charles, a proxy for monitoring network traffic to see Celo JSON RPC calls and responses. Follow instructions [here](https://community.tealiumiq.com/t5/Tealium-for-Android/Setting-up-Charles-to-Proxy-your-Android-Device/ta-p/5121) to configure Charles to proxy a test device.

## Testing

Expand Down Expand Up @@ -199,9 +199,9 @@ Relevant code references:
2. [Initialization](https://github.com/celo-org/celo-monorepo/blob/8689634a1d10d74ba6d4f3b36b2484db60a95bdb/packages/mobile/android/app/src/main/java/org/celo/mobile/MainApplication.java#L156) of the NDKCrashService
3. [Sentry code](https://github.com/celo-org/celo-monorepo/blob/799d74675dc09327543c210e88cbf5cc796721a0/packages/mobile/src/sentry/Sentry.ts#L53) to read NDK crash logs on restart

There are two major differencs in ZeroSync mode:
There are two major differences in Forno mode:

1. Geth won't run at all. The web3 would instead connect to <testnet>-forno.celo-testnet.org using an https provider, for example, [https://integration-forno.celo-testnet.org](https://integration-forno.celo-testnet.org).
1. Geth won't run at all. Instead, web3 connects to <testnet>-forno.celo-testnet.org using an https provider, for example, [https://integration-forno.celo-testnet.org](https://integration-forno.celo-testnet.org).
2. Changes to [sendTransactionAsyncWithWeb3Signing](https://github.com/celo-org/celo-monorepo/blob/8689634a1d10d74ba6d4f3b36b2484db60a95bdb/packages/walletkit/src/contract-utils.ts#L362) in walletkit to poll after sending a transaction for the transaction to succeed. This is needed because http provider, unliked web sockets and IPC provider, does not support subscriptions.

#### Why http(s) provider?
Expand Down
2 changes: 1 addition & 1 deletion packages/mobile/locales/en-US/accountScreen10.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
"body": "In case of incorrect PIN, you will need to restart the app.",
"understand": "I understand"
},
"promptZeroSyncModal": {
"promptFornoModal": {
"header": "Switch Connection Mode?",
"body": "We’ve noticed you’re having some trouble connecting. We recommend enabling Data Saver mode to allow you to keep using the Celo Wallet with intermittent connection.",
"switchToDataSaver": "Switch To Data Saver"
Expand Down
2 changes: 1 addition & 1 deletion packages/mobile/locales/es-419/accountScreen10.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
"body": "En caso de ingresar un PIN incorrecto, la aplicación se reiniciará.",
"understand": "Entendido"
},
"promptZeroSyncModal": {
"promptFornoModal": {
"header": "Cambiar modo de conexión?",
"body": "Hemos notado que tienes problemas para conectarte. Recomendamos habilitar el modo de ahorro de datos para que pueda seguir usando Celo Wallet con una conexión intermitente.",
"switchToDataSaver": "Habilitar Ahorro de Datos"
Expand Down
48 changes: 26 additions & 22 deletions packages/mobile/src/account/DataSaver.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,27 +12,27 @@ import i18n, { Namespaces, withTranslation } from 'src/i18n'
import { headerWithBackButton } from 'src/navigator/Headers'
import { navigateBack } from 'src/navigator/NavigationService'
import { RootState } from 'src/redux/reducers'
import { toggleZeroSyncMode } from 'src/web3/actions'
import { toggleFornoMode } from 'src/web3/actions'

interface StateProps {
zeroSyncEnabled: boolean
fornoEnabled: boolean
gethStartedThisSession: boolean
}

interface DispatchProps {
toggleZeroSyncMode: typeof toggleZeroSyncMode
toggleFornoMode: typeof toggleFornoMode
}

type Props = StateProps & DispatchProps & WithTranslation & NavigationInjectedProps

const mapDispatchToProps = {
toggleZeroSyncMode,
toggleFornoMode,
}

const mapStateToProps = (state: RootState): StateProps => {
return {
zeroSyncEnabled: state.web3.zeroSyncMode,
gethStartedThisSession: state.web3.gethStartedThisSession,
fornoEnabled: state.web3.fornoMode,
gethStartedThisSession: state.geth.gethStartedThisSession,
}
}

Expand Down Expand Up @@ -109,7 +109,7 @@ export class DataSaver extends React.Component<Props, State> {
}

onPressToggleWithSwitchOffModal = () => {
this.props.toggleZeroSyncMode(false)
this.props.toggleFornoMode(false)
this.hideSwitchOffModal()
}

Expand All @@ -122,48 +122,52 @@ export class DataSaver extends React.Component<Props, State> {
}

onPressToggleWithSwitchOnModal = () => {
this.props.toggleZeroSyncMode(true)
this.props.toggleFornoMode(true)
this.hideSwitchOnModal()
}

onPressPromptModal = () => {
this.props.toggleZeroSyncMode(true)
this.props.toggleFornoMode(true)
navigateBack()
}

hidePromptModal = () => {
this.props.toggleZeroSyncMode(false)
this.props.toggleFornoMode(false)
navigateBack()
}

handleZeroSyncToggle = (zeroSyncMode: boolean) => {
if (!zeroSyncMode && this.props.gethStartedThisSession) {
// Starting geth a second time this app session which will
// require an app restart, so show restart modal
this.showSwitchOffModal()
handleFornoToggle = (fornoMode: boolean) => {
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixes if else- if switching off forno mode, show the modal if need be, else just turn it off. If switching on forno mode, show switch on modal.

Previously, if switching off forno mode and modal not necessary, this would switch forno on (opposite of intended behavior)

if (!fornoMode) {
if (this.props.gethStartedThisSession) {
// Starting geth a second time this app session which will
// require an app restart, so show restart modal
this.showSwitchOffModal()
} else {
this.props.toggleFornoMode(false)
}
} else {
// If move to zeroSync was not successful we will need
// If move to forno was not successful we will need
// to rollback starting geth a second time
this.showSwitchOnModal()
}
}

render() {
const { zeroSyncEnabled, t } = this.props
const { fornoEnabled, t } = this.props
return (
<ScrollView style={styles.scrollView} keyboardShouldPersistTaps="handled">
<SettingsSwitchItem
switchValue={zeroSyncEnabled}
onSwitchChange={this.handleZeroSyncToggle}
switchValue={fornoEnabled}
onSwitchChange={this.handleFornoToggle}
details={t('dataSaverDetail')}
>
<Text style={fontStyles.body}>{t('enableDataSaver')}</Text>
</SettingsSwitchItem>
<WarningModal
isVisible={this.state.promptModalVisible}
header={t('promptZeroSyncModal.header')}
body={t('promptZeroSyncModal.body')}
continueTitle={t('promptZeroSyncModal.switchToDataSaver')}
header={t('promptFornoModal.header')}
body={t('promptFornoModal.body')}
continueTitle={t('promptFornoModal.switchToDataSaver')}
cancelTitle={t('global:goBack')}
onCancel={this.hidePromptModal}
onContinue={this.onPressPromptModal}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -185,7 +185,7 @@ exports[`DataSaver renders correctly 1`] = `
}
}
>
promptZeroSyncModal.header
promptFornoModal.header
</Text>
<Text
style={
Expand All @@ -197,7 +197,7 @@ exports[`DataSaver renders correctly 1`] = `
}
}
>
promptZeroSyncModal.body
promptFornoModal.body
</Text>
<View
style={
Expand Down Expand Up @@ -286,7 +286,7 @@ exports[`DataSaver renders correctly 1`] = `
]
}
>
promptZeroSyncModal.switchToDataSaver
promptFornoModal.switchToDataSaver
</Text>
</View>
</View>
Expand Down
12 changes: 12 additions & 0 deletions packages/mobile/src/account/actions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ export enum Actions {
DISMISS_INVITE_FRIENDS = 'ACCOUNT/DISMISS_INVITE_FRIENDS',
DISMISS_GET_VERIFIED = 'ACCOUNT/DISMISS_GET_VERIFIED',
SET_USER_CONTACT_DETAILS = 'ACCOUNT/SET_USER_CONTACT_DETAILS',
SET_PROMPT_FORNO = 'GETH/SET_PROMPT_FORNO',
}

export interface SetNameAction {
Expand Down Expand Up @@ -107,6 +108,11 @@ export interface SetContactDetailsAction {
thumbnailPath: string | null
}

interface SetPromptFornoAction {
type: Actions.SET_PROMPT_FORNO
promptIfNeeded: boolean
}

export type ActionTypes =
| SetNameAction
| SetPhoneNumberAction
Expand All @@ -126,6 +132,7 @@ export type ActionTypes =
| UpdateIncomingPaymentRequestsAction
| UpdateOutgoingPaymentRequestsAction
| SetContactDetailsAction
| SetPromptFornoAction

export function setName(name: string): SetNameAction {
return {
Expand Down Expand Up @@ -212,6 +219,11 @@ export const dismissGetVerified = (): DismissGetVerifiedAction => ({
type: Actions.DISMISS_GET_VERIFIED,
})

export const setPromptForno = (promptIfNeeded: boolean): SetPromptFornoAction => ({
type: Actions.SET_PROMPT_FORNO,
promptIfNeeded,
})

export const setUserContactDetails = (
contactId: string,
thumbnailPath: string | null
Expand Down
8 changes: 8 additions & 0 deletions packages/mobile/src/account/reducer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ export interface State {
dismissedEarnRewards: boolean
dismissedInviteFriends: boolean
dismissedGetVerified: boolean
promptFornoIfNeeded: boolean
}

export enum PincodeType {
Expand Down Expand Up @@ -60,6 +61,7 @@ export const initialState = {
dismissedEarnRewards: false,
dismissedInviteFriends: false,
dismissedGetVerified: false,
promptFornoIfNeeded: false,
}

export const reducer = (
Expand Down Expand Up @@ -178,6 +180,11 @@ export const reducer = (
thumbnailPath: action.thumbnailPath,
},
}
case Actions.SET_PROMPT_FORNO:
return {
...state,
promptFornoIfNeeded: action.promptIfNeeded,
}
default:
return state
}
Expand All @@ -189,3 +196,4 @@ export const e164NumberSelector = (state: RootState) => state.account.e164PhoneN
export const defaultCountryCodeSelector = (state: RootState) => state.account.defaultCountryCode
export const userContactDetailsSelector = (state: RootState) => state.account.contactDetails
export const pincodeTypeSelector = (state: RootState) => state.account.pincodeType
export const promptFornoIfNeededSelector = (state: RootState) => state.account.promptFornoIfNeeded
6 changes: 3 additions & 3 deletions packages/mobile/src/app/saga.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ import { NavActions, navigate } from 'src/navigator/NavigationService'
import { Screens, Stacks } from 'src/navigator/Screens'
import { web3 } from 'src/web3/contracts'
import { getAccount } from 'src/web3/saga'
import { zeroSyncSelector } from 'src/web3/selectors'
import { fornoSelector } from 'src/web3/selectors'

jest.mock('src/utils/time', () => ({
clockInSync: () => true,
Expand Down Expand Up @@ -83,7 +83,7 @@ describe('App saga', () => {
it('Navigates after verifying PIN - Forno', async () => {
const testRoute = { routeName: 'test', params: { a: '1' } }
await expectSaga(navigatePinProtected, testRoute)
.provide([[select(zeroSyncSelector), true]])
.provide([[select(fornoSelector), true]])
.run()
expect(navigate).toHaveBeenCalledWith(testRoute.routeName, testRoute.params)
})
Expand All @@ -92,7 +92,7 @@ describe('App saga', () => {
const testRoute = { routeName: 'test', params: { a: '1' } }
await expectSaga(navigatePinProtected, testRoute)
.provide([
[select(zeroSyncSelector), false],
[select(fornoSelector), false],
[call(getPincode, false), '123456'],
[call(getAccount), 'account'],
[call(web3.eth.personal.unlockAccount, 'account', '123456', UNLOCK_DURATION), undefined],
Expand Down
Loading