Skip to content

Commit

Permalink
fix tx submission and error handling
Browse files Browse the repository at this point in the history
  • Loading branch information
v-almonacid committed Jan 17, 2020
1 parent 6577e53 commit 61cec00
Show file tree
Hide file tree
Showing 10 changed files with 64 additions and 37 deletions.
11 changes: 8 additions & 3 deletions src/actions.js
Expand Up @@ -454,9 +454,13 @@ export const setSystemAuth = (enable: boolean) => async (
}
}

export const handleGeneralError = async (message: string, e: Error) => {
export const handleGeneralError = async (
message: string,
e: Error,
intl: ?intlShape,
) => {
Logger.error(`${message}: ${e.message}`, e)
await showErrorDialog(errorMessages.generalError, null, {message})
await showErrorDialog(errorMessages.generalError, intl, {message})
crashReporting.crash()
}

Expand All @@ -471,5 +475,6 @@ export const submitTransaction = (
}

export const submitShelleyTransferTx = async (encodedTx: Uint8Array) => {
await walletManager.submitTransaction(encodedTx)
const signedTx64 = Buffer.from(encodedTx).toString('base64')
await walletManager.submitTransaction(signedTx64)
}
2 changes: 1 addition & 1 deletion src/api/api.js
Expand Up @@ -127,7 +127,7 @@ export const bulkFetchUTXOsForAddresses = async (
return _.flatten(responses)
}

export const submitTransaction = (signedTx: string | Uint8Array) => {
export const submitTransaction = (signedTx: string) => {
return _fetch('txs/signed', {signedTx})
}

Expand Down
32 changes: 17 additions & 15 deletions src/components/WalletInit/RestoreWallet/WalletCredentialsScreen.js
Expand Up @@ -31,6 +31,7 @@ import {
import {generateTransferTxFromMnemonic} from '../../../crypto/shelley/transactions/yoroiTransfer'
import {CARDANO_CONFIG} from '../../../config'
import {NetworkError, ApiError} from '../../../api/errors'
import {InsufficientFunds} from '../../../crypto/errors'
import {errorMessages} from '../../../i18n/global-messages'

import type {Navigation} from '../../../types/navigation'
Expand Down Expand Up @@ -84,7 +85,7 @@ const handleApiError = async (
} else if (error instanceof ApiError) {
await showErrorDialog(errorMessages.apiError, intl)
} else {
await handleGeneralError(fallbackMsg, error)
await handleGeneralError(fallbackMsg, error, intl)
}
}

Expand Down Expand Up @@ -123,17 +124,14 @@ class WalletCredentialsScreen extends React.Component<Props, State> {
transferTx: null,
}

navigateToWallet = ignoreConcurrentAsync(
async (): Promise<void> => {
const {name, password} = this.state
const {navigation, createWallet} = this.props
const phrase = navigation.getParam('phrase')
const isShelleyWallet = !!navigation.getParam('isShelleyWallet')
await createWallet(name, phrase, password, isShelleyWallet)
navigation.navigate(ROOT_ROUTES.WALLET)
},
1000,
)
navigateToWallet = ignoreConcurrentAsync(async (): Promise<void> => {
const {name, password} = this.state
const {navigation, createWallet} = this.props
const phrase = navigation.getParam('phrase')
const isShelleyWallet = !!navigation.getParam('isShelleyWallet')
await createWallet(name, phrase, password, isShelleyWallet)
navigation.navigate(ROOT_ROUTES.WALLET)
}, 1000)

onSubmitWalletCredentials = ({name, password}) => {
// TODO: make sure this call is executed only once
Expand Down Expand Up @@ -248,7 +246,11 @@ class WalletCredentialsScreen extends React.Component<Props, State> {
})
} catch (e) {
this.setState({currentDialogStep: RESTORATION_DIALOG_STEPS.CLOSED})
handleApiError(e, intl, messages.walletCheckError)
if (e instanceof InsufficientFunds) {
await showErrorDialog(errorMessages.insufficientBalance, intl)
} else {
handleApiError(e, intl, 'Could not check wallet')
}
} finally {
this.setState({isProcessing: false})
}
Expand All @@ -268,9 +270,9 @@ class WalletCredentialsScreen extends React.Component<Props, State> {
}
await submitShelleyTransferTx(tx.encodedTx)
this.setState({isProcessing: false})
this.navigateToWallet()
navigation.navigate(ROOT_ROUTES.WALLET)
} catch (e) {
handleApiError(e, intl, 'could not upgrade wallet')
handleApiError(e, intl, 'Could not upgrade wallet')
} finally {
this.setState({isProcessing: false})
}
Expand Down
3 changes: 2 additions & 1 deletion src/crypto/chain.js
Expand Up @@ -45,6 +45,7 @@ export class AddressGenerator {
}
}

// TODO: make ShelleyAddressGenerator a subclass of AddressGenerator
export class ShelleyAddressGenerator {
addressChain: Bip32PublicKey
// stakingKey: PublicKey
Expand Down Expand Up @@ -114,7 +115,7 @@ export class AddressChain {
)

constructor(
addressGenerator: AddressGenerator,
addressGenerator: AddressGenerator | ShelleyAddressGenerator,
blockSize: number = CONFIG.WALLET.DISCOVERY_BLOCK_SIZE,
gapLimit: number = CONFIG.WALLET.DISCOVERY_GAP_SIZE,
) {
Expand Down
1 change: 0 additions & 1 deletion src/crypto/shelley/transactions/utxoTransactions.js
Expand Up @@ -352,7 +352,6 @@ export const sendAllUnsignedTxFromUtxo = async (
)).to_str()
fee = new BigNumber(feeValue)
}

// create a new transaction subtracing the fee from your total UTXO
if (totalBalance.isLessThan(fee)) {
throw new InsufficientFunds()
Expand Down
11 changes: 9 additions & 2 deletions src/crypto/shelley/transactions/yoroiTransfer.js
Expand Up @@ -2,6 +2,8 @@
import {BigNumber} from 'bignumber.js'
import {isEmpty} from 'lodash'
import {Address, Bip32PrivateKey} from 'react-native-chain-libs'

import {InsufficientFunds} from '../../errors'
import type {AddressedUtxo, Addressing} from '../../../types/HistoryTransaction'
import {signTransaction, sendAllUnsignedTx} from './utxoTransactions'
import {getShelleyTxFee} from './utils'
Expand Down Expand Up @@ -66,8 +68,13 @@ export const buildYoroiTransferTx = async (payload: {|
)).to_string(CONFIG.BECH32_PREFIX.ADDRESS),
}
} catch (error) {
Logger.error(`transfer::buildYoroiTransferTx: ${error.message}`)
throw new Error(`buildYoroiTransferTx: ${error.message}`)
if (error instanceof InsufficientFunds) {
// handle error at UI-level
throw error
} else {
Logger.error(`transfer::buildYoroiTransferTx: ${error.message}`)
throw new Error(`buildYoroiTransferTx: ${error.message}`)
}
}
}

Expand Down
11 changes: 4 additions & 7 deletions src/crypto/shelley/util.test.js
Expand Up @@ -7,9 +7,7 @@ import {
// getFirstInternalAddr,
getGroupAddressesFromMnemonics,
} from './util'
import {
getMasterKeyFromMnemonic,
} from '../byron/util'
import {getMasterKeyFromMnemonic} from '../byron/util'
import {NUMBERS} from '../../config'

jestSetup.setup()
Expand All @@ -23,11 +21,10 @@ const mnemonic = [

test('Can create master key', async () => {
const masterKeyV2 = await getMasterKeyFromMnemonic(mnemonic)
const masterKeyV3 = await generateWalletRootKey(
mnemonic,
)
const masterKeyV3 = await generateWalletRootKey(mnemonic)
expect(masterKeyV2).toEqual(
Buffer.from(await masterKeyV3.as_bytes()).toString('hex'))
Buffer.from(await masterKeyV3.as_bytes()).toString('hex'),
)
})

describe('group addresses', () => {
Expand Down
18 changes: 11 additions & 7 deletions src/crypto/wallet.js
Expand Up @@ -203,8 +203,12 @@ export class Wallet {
)).derive(0 + NUMBERS.HARD_DERIVATION_START)

const accountPublic = await accountKey.to_public()
const privateChainKey = await accountPublic.derive(NUMBERS.CHAIN_DERIVATIONS.INTERNAL)
const publicChainKey = await accountPublic.derive(NUMBERS.CHAIN_DERIVATIONS.EXTERNAL)
const privateChainKey = await accountPublic.derive(
NUMBERS.CHAIN_DERIVATIONS.INTERNAL,
)
const publicChainKey = await accountPublic.derive(
NUMBERS.CHAIN_DERIVATIONS.EXTERNAL,
)

this._transactionCache = new TransactionCache()

Expand Down Expand Up @@ -441,7 +445,7 @@ export class Wallet {
return Buffer.from(signedTxData.cbor_encoded_tx, 'hex').toString('base64')
}

async submitTransaction(signedTx: string | Uint8Array) {
async submitTransaction(signedTx: string) {
const response = await api.submitTransaction(signedTx)
Logger.info(response)
return response
Expand Down Expand Up @@ -671,7 +675,7 @@ class WalletManager {
)
}

async submitTransaction(signedTx: string | Uint8Array) {
async submitTransaction(signedTx: string) {
if (!this._wallet) throw new WalletClosed()
return await this.abortWhenWalletCloses(
this._wallet.submitTransaction(signedTx),
Expand All @@ -686,9 +690,9 @@ class WalletManager {
): Promise<Wallet> {
// Ignore id & name for now
const wallet = new Wallet()
const id = isShelleyWallet ?
await wallet._createShelleyWallet(mnemonic, password) :
await wallet._create(mnemonic, password)
const id = isShelleyWallet
? await wallet._createShelleyWallet(mnemonic, password)
: await wallet._create(mnemonic, password)

this._id = id
this._wallets = {
Expand Down
10 changes: 10 additions & 0 deletions src/i18n/global-messages.js
Expand Up @@ -127,6 +127,16 @@ export const errorMessages = {
'Please try again later or check our Twitter account (https://twitter.com/YoroiWallet)',
},
}),
insufficientBalance: defineMessages({
title: {
id: 'global.actions.dialogs.insufficientBalance.title',
defaultMessage: '!!!Transaction error',
},
message: {
id: 'global.actions.dialogs.insufficientBalance.message',
defaultMessage: '!!Not enough money to make this transaction',
},
}),
disableEasyConfirmationFirst: defineMessages({
title: {
id: 'global.actions.dialogs.disableEasyConfirmationFirst.title',
Expand Down
2 changes: 2 additions & 0 deletions src/i18n/locales/en-US.json
Expand Up @@ -252,6 +252,8 @@
"global.actions.dialogs.logout.yesButton": "Yes",
"global.actions.dialogs.apiError.title": "API error",
"global.actions.dialogs.apiError.message": "Error received from api method call while sending transaction. Please try again later or check our Twitter account (https://twitter.com/YoroiWallet)",
"global.actions.dialogs.insufficientBalance.title": "Transaction error",
"global.actions.dialogs.insufficientBalance.message": "Not enough money to make this transaction",
"global.actions.dialogs.networkError.message": "Error connecting to the server. Please check your internet connection",
"global.actions.dialogs.networkError.title": "Network error",
"global.actions.dialogs.pinMismatch.message": "PINs do not match.",
Expand Down

0 comments on commit 61cec00

Please sign in to comment.