Skip to content

Commit

Permalink
add staking center and update podfile (#974)
Browse files Browse the repository at this point in the history
  • Loading branch information
v-almonacid committed Sep 21, 2020
1 parent 4306ba2 commit ab6c3eb
Show file tree
Hide file tree
Showing 7 changed files with 128 additions and 61 deletions.
18 changes: 9 additions & 9 deletions ios/Podfile.lock
Expand Up @@ -13,7 +13,7 @@ PODS:
- DoubleConversion
- glog
- glog (0.3.5)
- MultiplatformBleAdapter (0.1.5)
- MultiplatformBleAdapter (0.1.6)
- Permission-Camera (2.1.5):
- RNPermissions
- React (0.60.0):
Expand Down Expand Up @@ -64,8 +64,8 @@ PODS:
- React-jsinspector (0.60.0)
- react-native-background-timer (2.2.0):
- React
- react-native-ble-plx (2.0.0):
- MultiplatformBleAdapter (= 0.1.5)
- react-native-ble-plx (2.0.1):
- MultiplatformBleAdapter (= 0.1.6)
- React
- react-native-camera (3.30.0):
- React
Expand All @@ -77,7 +77,7 @@ PODS:
- React
- react-native-config (0.12.0):
- React
- react-native-haskell-shelley (0.0.5):
- react-native-haskell-shelley (0.0.8):
- React
- react-native-netinfo (5.6.2):
- React
Expand Down Expand Up @@ -115,7 +115,7 @@ PODS:
- React
- RNCAsyncStorage (1.5.1):
- React
- RNDeviceInfo (5.5.7):
- RNDeviceInfo (6.0.1):
- React
- RNFS (2.13.3):
- React
Expand Down Expand Up @@ -272,7 +272,7 @@ SPEC CHECKSUMS:
DoubleConversion: 5805e889d232975c086db112ece9ed034df7a0b2
Folly: 30e7936e1c45c08d884aa59369ed951a8e68cf51
glog: 1f3da668190260b06b429bb211bfbee5cd790c28
MultiplatformBleAdapter: 3c4391d428382738a47662ae1f665a29ce78ff39
MultiplatformBleAdapter: 652f47ecd7f5036756517cf66833210709a72eab
Permission-Camera: afad27bf90337684d4a86f3825112d648c8c4d3b
React: 4b3c068e793e96672dcd186a2b572fac43e4b031
React-Core: 3dc86b22920597f813c62a96db3165950b64826b
Expand All @@ -283,10 +283,10 @@ SPEC CHECKSUMS:
React-jsiexecutor: 7a3554f703a58963ec80b860144ea0f0e9b910e1
React-jsinspector: d4ed52225912efe0019bb7f1a225aec20f23049a
react-native-background-timer: 1f7d560647b40e6a60b01c452ba29c54bf581fc4
react-native-ble-plx: 21acd4201f9de46ab690b24898e8d3ad02f518fd
react-native-ble-plx: d8dcca81ecc617eda824a4ace85f7ffd55d90c6c
react-native-camera: eeb5b5f4ba4c1365fed3563af8a72007cbad7aab
react-native-config: f2c2ae45625a068c35681a16b9bfb1ca58b0adc7
react-native-haskell-shelley: 963db135ddf00646fb4170b9b5f6f8c4da449036
react-native-haskell-shelley: 241bdb4e191404ed8ee4e877388482fb0d73f03d
react-native-netinfo: 73303369946c2487c600418961bfdc87748b832f
react-native-randombytes: 3638d24759d67c68f6ccba60c52a7a8a8faa6a23
react-native-splash-screen: 200d11d188e2e78cea3ad319964f6142b6384865
Expand All @@ -303,7 +303,7 @@ SPEC CHECKSUMS:
React-RCTWebSocket: fca087d583724aa0e5fef7d911f0f2a28d0f2736
RNCardano: ffdd908e7dde81508914dbff2fbd739183b2bf34
RNCAsyncStorage: b63d6e83fc629b01df6b624688f17944cea5637f
RNDeviceInfo: e2102056bde3ad5d137fd029d8d431510a00486a
RNDeviceInfo: 6dd5c07a482f2a5e4a29fe8a9d99eadd4277175a
RNFS: c9bbde46b0d59619f8e7b735991c60e0f73d22c1
RNKeychain: 3aa3cf891a09a0d18d306862ab2bb9e106079b24
RNPermissions: ad71dd4f767ec254f2cd57592fbee02afee75467
Expand Down
7 changes: 7 additions & 0 deletions src/components/Delegation/DelegationConfirmation.stories.js
@@ -1,11 +1,16 @@
// @flow
/* eslint-disable max-len */
import React from 'react'
import {BigNumber} from 'bignumber.js'

import {storiesOf} from '@storybook/react-native'

import DelegationConfirmation from './DelegationConfirmation'

const transactionData = {
totalAmountToDelegate: new BigNumber('100000000'), // 100 ADA
}

storiesOf('DelegationConfirmation', module).add('Default', ({navigation}) => {
navigation.getParam = (param) => {
switch (param) {
Expand All @@ -19,6 +24,8 @@ storiesOf('DelegationConfirmation', module).add('Default', ({navigation}) => {
return new BigNumber('100000000') // 100 ADA
case 'transactionFee':
return new BigNumber('2000000') // 2 ADA
case 'transactionData':
return transactionData
default:
return ''
}
Expand Down
148 changes: 105 additions & 43 deletions src/components/Delegation/StakingCenter.js
Expand Up @@ -2,22 +2,30 @@
import React from 'react'
import {View} from 'react-native'
import {WebView} from 'react-native-webview'
import {connect} from 'react-redux'
import {compose} from 'redux'
import {withHandlers, withStateHandlers} from 'recompose'
import {injectIntl, defineMessages} from 'react-intl'

// import {STAKING_CENTER_ROUTES} from '../../RoutesList'
import {STAKING_CENTER_ROUTES} from '../../RoutesList'
import {withNavigationTitle} from '../../utils/renderUtils'
import {CONFIG} from '../../config/config'
import {Logger} from '../../utils/logging'
// import walletManager from '../../crypto/walletManager'
// import {getShelleyTxFee} from '../../crypto/jormungandr/transactions/utils'
// import {InsufficientFunds} from '../../crypto/errors'
import globalMessages from '../../i18n/global-messages'
import walletManager from '../../crypto/walletManager'
import globalMessages, {errorMessages} from '../../i18n/global-messages'
import {showErrorDialog} from '../../actions'
// import {NetworkError, ApiError} from '../../api/errors'
import {PleaseWaitModal} from '../UiKit'
import PoolWarningModal from './PoolWarningModal'
import {ObjectValues} from '../../utils/flow'
import {
isOnlineSelector,
utxosSelector,
accountBalanceSelector,
} from '../../selectors'
import UtxoAutoRefresher from '../Send/UtxoAutoRefresher'
import AccountAutoRefresher from './AccountAutoRefresher'
import {NetworkError, ApiError} from '../../api/errors'
import {InsufficientFunds} from '../../crypto/errors'

import styles from './styles/DelegationCenter.style'

Expand Down Expand Up @@ -50,25 +58,19 @@ const noPoolDataDialog = defineMessages({

/**
* Prepares WebView's target staking URI
* @param {*} userAda : needs to be in ADA (not Lovelaces) as per Seiza API
* @param {*} poolList : Array of delegated pool hash
*/
const prepareStakingURL = (
userAda: string,
poolList: Array<string>,
): null | string => {
// eslint-disable-next-line max-len
// Refer: https://github.com/Emurgo/yoroi-frontend/blob/2f06f7afa5283365f1070b6a042bcfedba51646f/app/containers/wallet/staking/StakingPage.js#L60
const prepareStakingURL = (poolList: ?Array<string>): null | string => {
// source=mobile is constant and already included
// TODO: add locale parameter
let finalURL = CONFIG.NETWORKS.JORMUNGANDR.SEIZA_STAKING_SIMPLE(userAda)
let finalURL = CONFIG.NETWORKS.HASKELL_SHELLEY.POOL_EXPLORER
if (poolList != null) {
finalURL += `&delegated=${encodeURIComponent(JSON.stringify(poolList))}`
}
return finalURL
}

const DelegationCenter = ({
const StakingCenter = ({
navigation,
intl,
handleOnMessage,
Expand All @@ -79,13 +81,15 @@ const DelegationCenter = ({
selectedPools,
reputationInfo,
}) => {
const approxAdaToDelegate = navigation.getParam('approxAdaToDelegate')
const poolList = navigation.getParam('pools')
// pools user is currently delegating to
const poolList: ?Array<string> = navigation.getParam('poolList')
return (
<>
<View style={styles.container}>
<UtxoAutoRefresher />
<AccountAutoRefresher />
<WebView
source={{uri: prepareStakingURL(approxAdaToDelegate, poolList)}}
source={{uri: prepareStakingURL(poolList)}}
onMessage={(event) => handleOnMessage(event)}
/>
</View>
Expand All @@ -111,7 +115,7 @@ const DelegationCenter = ({
}

type SelectedPool = {|
+name: null | string,
+poolName: null | string,
+poolHash: string,
|}

Expand All @@ -123,6 +127,11 @@ type ExternalProps = {|
export default injectIntl(
(compose(
withNavigationTitle(({intl}) => intl.formatMessage(messages.title)),
connect((state) => ({
utxos: utxosSelector(state),
accountBalance: accountBalanceSelector(state),
isOnline: isOnlineSelector(state),
})),
withStateHandlers(
{
busy: false,
Expand Down Expand Up @@ -150,7 +159,37 @@ export default injectIntl(
},
}),
withHandlers({
navigateToDelegationConfirm: () => () => ({}),
navigateToDelegationConfirm: ({
navigation,
accountBalance,
utxos,
intl,
}) => async (selectedPools: Array<SelectedPool>) => {
try {
const selectedPool = selectedPools[0]
const transactionData = await walletManager.createDelegationTx(
selectedPool.poolHash,
accountBalance,
utxos,
)
const transactionFee = await transactionData.signTxRequest.fee(false)
navigation.navigate(STAKING_CENTER_ROUTES.DELEGATION_CONFIRM, {
poolName: selectedPool.poolName,
poolHash: selectedPool.poolHash,
transactionData,
transactionFee,
})
} catch (e) {
if (e instanceof InsufficientFunds) {
await showErrorDialog(errorMessages.insufficientBalance, intl)
} else {
Logger.error(e)
await showErrorDialog(errorMessages.generalError, intl, {
message: e.message,
})
}
}
},
}),
withHandlers({
handleOnMessage: ({
Expand All @@ -161,34 +200,57 @@ export default injectIntl(
setShowPoolWarning,
intl,
}) => async (event) => {
const selectedPools: Array<SelectedPool> = JSON.parse(
decodeURI(event.nativeEvent.data),
)
const poolsReputation = navigation.getParam('poolsReputation')
Logger.debug(`From Seiza: ${JSON.stringify(selectedPools)}`)
if (
selectedPools &&
selectedPools.length >= 1 &&
selectedPools[0].poolHash != null
) {
setSelectedPools(selectedPools)
// check if pool in blacklist
const poolsInBlackList = []
for (const pool of selectedPools) {
if (pool.poolHash in poolsReputation) {
poolsInBlackList.push(pool.poolHash)
try {
const selectedPoolHashes: Array<string> = JSON.parse(
decodeURI(event.nativeEvent.data),
)
Logger.debug('selected pools from explorer:', selectedPoolHashes)

const poolInfoResponse = await walletManager.fetchPoolInfo({
poolIds: selectedPoolHashes,
})
const poolInfo = ObjectValues(poolInfoResponse)[0]
Logger.debug('poolInfo', poolInfo)

// TODO: fetch reputation info once an endpoint is implemented
const poolsReputation: {[key: string]: mixed} = {}
if (poolInfo?.info != null) {
const selectedPools: Array<SelectedPool> = [
{
poolName: poolInfo.info.name,
poolHash: selectedPoolHashes[0],
},
]
setSelectedPools(selectedPools)
// check if pool in blacklist
const poolsInBlackList = []
for (const pool of selectedPoolHashes) {
if (pool in poolsReputation) {
poolsInBlackList.push(pool)
}
}
if (poolsInBlackList.length > 0) {
setReputationInfo(poolsReputation[poolsInBlackList[0]])
setShowPoolWarning(true)
} else {
navigateToDelegationConfirm(selectedPools)
}
} else {
await showErrorDialog(noPoolDataDialog, intl)
}
if (poolsInBlackList.length > 0) {
setReputationInfo(poolsReputation[poolsInBlackList[0]])
setShowPoolWarning(true)
} catch (e) {
if (e instanceof NetworkError) {
await showErrorDialog(errorMessages.networkError, intl)
} else if (e instanceof ApiError) {
await showErrorDialog(noPoolDataDialog, intl)
} else {
navigateToDelegationConfirm()
Logger.error(e)
await showErrorDialog(errorMessages.generalError, intl, {
message: e.message,
})
}
} else {
await showErrorDialog(noPoolDataDialog, intl)
}
},
}),
)(DelegationCenter): ComponentType<ExternalProps>),
)(StakingCenter): ComponentType<ExternalProps>),
)
4 changes: 1 addition & 3 deletions src/components/Delegation/StakingCenter.stories.js
Expand Up @@ -14,9 +14,7 @@ storiesOf('StakingCenter', module).add(
case 'approxAdaToDelegate':
return '100'
case 'pools':
return [
'bd885c7fa6bcceaa6e530fe4f285daa4c631fab6ff31544dfc37b88eade9763e',
]
return ['af22f95915a19cd57adb14c558dcc4a175f60c6193dc23b8bd2d8beb']
default:
return ''
}
Expand Down
5 changes: 2 additions & 3 deletions src/components/Delegation/StakingCenterNavigator.js
Expand Up @@ -3,7 +3,7 @@ import React from 'react'
import {createStackNavigator} from 'react-navigation'

import {Button} from '../UiKit'
import StakeByIdScreen from './StakeByIdScreen'
import StakingCenter from './StakingCenter'
import BiometricAuthScreen from '../Send/BiometricAuthScreen'
import DelegationConfirmation from './DelegationConfirmation'
import {
Expand All @@ -24,8 +24,7 @@ import styles from '../TxHistory/styles/SettingsButton.style'
const StakingNavigatorCenter = createStackNavigator(
{
[STAKING_CENTER_ROUTES.MAIN]: {
// this should be temporal. Implement StakingCenter in next iteration
screen: StakeByIdScreen,
screen: StakingCenter,
navigationOptions: ({navigation}) => ({
title: navigation.getParam('title'),
headerRight: (
Expand Down
6 changes: 3 additions & 3 deletions src/components/Delegation/StakingDashboard.stories.js
Expand Up @@ -9,10 +9,10 @@ import StakingDashboard from './StakingDashboard'

const poolInfo = {
info: {
ticker: '3EMUR',
name: 'EMURGO’ STAKEPOOL',
ticker: 'EMUR1',
name: 'Emurgo #1',
description:
'EMURGO’s official Stake Pool. EMURGO is one of three organizations that contribute to the development of Cardano. Let’s make this Testnet successful by delegation to multiple stakepools.',
'EMURGO is a multinational blockchain technology company providing solutions for developers, startups, enterprises, and governments.',
homepage: 'https://emurgo.io',
},
history: [
Expand Down
1 change: 1 addition & 0 deletions src/config/networks.js
Expand Up @@ -32,6 +32,7 @@ export const NETWORKS = {
IS_MAINNET: true,
EXPLORER_URL_FOR_ADDRESS: (address: string) =>
`https://explorer.cardano.org/en/address?address=${address}`,
POOL_EXPLORER: 'https://adapools.yoroiwallet.com/?source=mobile',
BACKEND: {
API_ROOT: 'https://iohk-mainnet.yoroiwallet.com/api',
..._DEFAULT_BACKEND_RULES,
Expand Down

0 comments on commit ab6c3eb

Please sign in to comment.