Skip to content

Commit

Permalink
Send coins - added gRPC call logic for sending TX and retrieving bala…
Browse files Browse the repository at this point in the history
…nce (#58)

* Send coins - added gRPC call logic for sending TX and retrieving balance

* Send coins - added gRPC call logic for sending TX and retrieving balance

* Send coins - added gRPC call logic for sending TX and retrieving balance

* Send coins - added gRPC call logic for sending TX and retrieving balance
  • Loading branch information
Ilya Vilensky committed Mar 26, 2019
1 parent cadfbd6 commit aec820a
Show file tree
Hide file tree
Showing 18 changed files with 284 additions and 110 deletions.
5 changes: 3 additions & 2 deletions app/basicComponents/Modal.js
Original file line number Diff line number Diff line change
Expand Up @@ -64,21 +64,22 @@ const BodyWrapper = styled.div`
type Props = {
header: string,
onQuestionMarkClick: () => void,
onCancelBtnClick: () => void,
onCloseClick: () => void,
content: Object
};

class Modal extends Component<Props> {
render() {
const { header, onQuestionMarkClick, onCloseClick, content } = this.props;
const { header, onQuestionMarkClick, onCancelBtnClick, onCloseClick, content } = this.props;
return (
<OuterWrapper onClick={onCloseClick}>
<Wrapper onClick={(event) => event.stopPropagation()}>
<HeaderWrapper>
<div>{header}</div>
<HeaderButtons>
<HeaderButton onClick={onQuestionMarkClick}>?</HeaderButton>
<CloseButton onClick={onCloseClick}>+</CloseButton>
<CloseButton onClick={onCancelBtnClick}>+</CloseButton>
</HeaderButtons>
</HeaderWrapper>
<BodyWrapper>{content}</BodyWrapper>
Expand Down
2 changes: 1 addition & 1 deletion app/basicComponents/SmInput.js
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ class SmInput extends PureComponent<Props> {
const { isDisabled, placeholder, errorMsg, isErrorMsgEnabled, style } = this.props;
return (
<Wrapper isErrorMsgEnabled={isErrorMsgEnabled}>
<Input hasError={errorMsg} isDisabled={isDisabled} placeholder={placeholder || INPUT_PLACEHOLDER} onChange={this.onChange} style={style} />
<Input hasError={errorMsg} readOnly={isDisabled} isDisabled={isDisabled} placeholder={placeholder || INPUT_PLACEHOLDER} onChange={this.onChange} style={style} />
{isErrorMsgEnabled && <ErrorMsg>{errorMsg || ''}</ErrorMsg>}
</Wrapper>
);
Expand Down
6 changes: 3 additions & 3 deletions app/components/auth/CreateWallet.js
Original file line number Diff line number Diff line change
Expand Up @@ -169,14 +169,14 @@ class CreateWallet extends Component<Props, State> {
return !passphraseError && !verifyPassphraseError;
};

createWallet = () => {
createWallet = async () => {
const { deriveEncryptionKey, saveNewWallet, hideCloseBtn } = this.props;
const { passphrase, isLoaderVisible } = this.state;
const canProceed = this.validate();
if (canProceed && !isLoaderVisible) {
this.setState({ isLoaderVisible: true });
setTimeout(() => {
deriveEncryptionKey({ passphrase });
await setTimeout(async () => {
await deriveEncryptionKey({ passphrase });
saveNewWallet({});
this.setState({ isLoaderVisible: false, subMode: 2 }, hideCloseBtn);
}, 500);
Expand Down
2 changes: 1 addition & 1 deletion app/components/wallet/overview/AccountCard.js
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,7 @@ class AccountCard extends Component<Props, State> {
<SubHeader>Public address</SubHeader>
<PublicAddressWrapper>
<PublicAddressInnerWrapper copied={copied}>
<PublicAddress>{pk}</PublicAddress>
<PublicAddress>{pk.substring(0, 20)}</PublicAddress>
<CopyIconWrapper>
<CopyIcon src={copyIcon} />
</CopyIconWrapper>
Expand Down
12 changes: 10 additions & 2 deletions app/components/wallet/receiveCoins/ReceiveCoins.js
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,15 @@ type Props = {

class ReceiveCoins extends PureComponent<Props> {
render() {
return <Modal header="Confirm Transaction" onQuestionMarkClick={this.onQuestionMarkClick} onCloseClick={this.onCloseClick} content={this.renderModalBody()} />;
return (
<Modal
header="Confirm Transaction"
onQuestionMarkClick={this.onQuestionMarkClick}
onCancelBtnClick={this.onCloseClick}
onCloseClick={this.onCloseClick}
content={this.renderModalBody()}
/>
);
}

componentDidMount(): void {
Expand All @@ -115,7 +123,7 @@ class ReceiveCoins extends PureComponent<Props> {
<Header>Your wallet public address has been copied to clipboard</Header>
<LeftPartInner>
<AddressWrapper onClick={this.copyPublicAddress}>
<Address>{address}</Address>
<Address>{address.substring(0, 30)}</Address>
<CopyIcon src={copyIcon} />
</AddressWrapper>
<Text>
Expand Down
38 changes: 14 additions & 24 deletions app/components/wallet/sendCoins/TxConfirmation.js
Original file line number Diff line number Diff line change
Expand Up @@ -73,17 +73,27 @@ type Props = {
confirmationTime: string,
navigateToExplanation: () => void,
closeModal: () => void,
onCancelBtnClick: () => void,
sendTransaction: () => void,
editTransaction: () => void
};

class TxConfirmation extends PureComponent<Props> {
render() {
return <Modal header="Confirm Transaction" onQuestionMarkClick={this.onQuestionMarkClick} onCloseClick={this.onCloseClick} content={this.renderModalBody()} />;
const { navigateToExplanation, onCancelBtnClick, closeModal } = this.props;
return (
<Modal
header="Confirm Transaction"
onQuestionMarkClick={navigateToExplanation}
onCancelBtnClick={onCancelBtnClick}
onCloseClick={closeModal}
content={this.renderModalBody()}
/>
);
}

renderModalBody = () => {
const { address, amount, fee, note, fiatRate, confirmationTime } = this.props;
const { address, amount, fee, note, fiatRate, confirmationTime, editTransaction, sendTransaction } = this.props;
return (
<Wrapper>
<Row>
Expand Down Expand Up @@ -113,32 +123,12 @@ class TxConfirmation extends PureComponent<Props> {
</Row>
<EstimatedTime>Estimated confirmation time {confirmationTime}</EstimatedTime>
<BottomSection>
<EditTxButton onClick={this.editTransaction}>Edit Transaction</EditTxButton>
<SmButton text="Confirm" theme="orange" onPress={this.sendTransaction} />
<EditTxButton onClick={editTransaction}>Edit Transaction</EditTxButton>
<SmButton text="Confirm" theme="orange" onPress={sendTransaction} />
</BottomSection>
</Wrapper>
);
};

onQuestionMarkClick = () => {
const { navigateToExplanation } = this.props;
navigateToExplanation();
};

onCloseClick = () => {
const { closeModal } = this.props;
closeModal();
};

editTransaction = () => {
const { editTransaction } = this.props;
editTransaction();
};

sendTransaction = () => {
const { sendTransaction } = this.props;
sendTransaction();
};
}

export default TxConfirmation;
20 changes: 15 additions & 5 deletions app/components/wallet/sendCoins/TxParams.js
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,15 @@ const AmountSection = styled.div`
justify-content: center;
`;

// $FlowStyledIssue
const FiatValue = styled.div`
display: flex;
flex: 1;
align-items: center;
padding-left: 10px;
color: ${({ hasValue }) => (hasValue ? smColors.lighterBlack : smColors.gray)};
`;

const MyContactsSection = styled.div`
width: 160px;
display: flex;
Expand Down Expand Up @@ -107,6 +116,7 @@ const inputStyle = { border: '1px solid transparent' };
type Props = {
updateTxAddress: ({ value: string }) => void,
updateTxAmount: ({ value: string }) => void,
amount: number,
updateTxNote: ({ value: string }) => void,
updateFee: ({ index: number }) => void,
addressErrorMsg?: string,
Expand All @@ -126,14 +136,14 @@ class TxParams extends Component<Props, State> {
};

render() {
const { updateTxAddress, updateTxAmount, updateTxNote, updateFee, addressErrorMsg, amountErrorMsg, fees, feeIndex, fiatRate } = this.props;
const { updateTxAddress, updateTxAmount, amount, updateTxNote, updateFee, addressErrorMsg, amountErrorMsg, fees, feeIndex, fiatRate } = this.props;
const { isFeeSelectorVisible } = this.state;
return (
<Wrapper>
<SectionWrapper>
<Label>Send to</Label>
<InputSection>
<SmInput type="text" placeholder="Type address" onChange={updateTxAddress} hasDebounce style={inputStyle} isErrorMsgEnabled={false} />
<SmInput type="text" placeholder="Type address" onChange={updateTxAddress} style={inputStyle} isErrorMsgEnabled={false} />
<MyContactsSection>
<MyContactsText>My contacts</MyContactsText>
<MyContactsIcon src={contactIcon} />
Expand All @@ -145,12 +155,12 @@ class TxParams extends Component<Props, State> {
<Label>Amount to send</Label>
<AmountSection>
<InputSection>
<SmInput type="tel" placeholder="Type amount" onChange={updateTxAmount} hasDebounce style={inputStyle} isErrorMsgEnabled={false} />
<SmInput type="tel" placeholder="Type amount" onChange={updateTxAmount} style={inputStyle} isErrorMsgEnabled={false} />
<CurrencyText>SMC</CurrencyText>
</InputSection>
<CurrencyText> = </CurrencyText>
<InputSection>
<SmInput type="tel" placeholder="Fiat value" disabled value={10} style={inputStyle} isErrorMsgEnabled={false} />
<FiatValue hasValue={!!amount}>{amount ? amount * fiatRate : 'Fiat value'}</FiatValue>
<CurrencyText>USD</CurrencyText>
</InputSection>
</AmountSection>
Expand All @@ -159,7 +169,7 @@ class TxParams extends Component<Props, State> {
<SectionWrapper>
<Label>Note (optional)</Label>
<InputSection>
<SmInput type="text" placeholder="Add a short note (optional)" onChange={updateTxNote} hasDebounce style={inputStyle} isErrorMsgEnabled={false} />
<SmInput type="text" placeholder="Add a short note (optional)" onChange={updateTxNote} style={inputStyle} isErrorMsgEnabled={false} />
</InputSection>
</SectionWrapper>
<EstimationSection onClick={() => this.setState({ isFeeSelectorVisible: !isFeeSelectorVisible })}>
Expand Down
22 changes: 16 additions & 6 deletions app/infra/httpService/httpService.js
Original file line number Diff line number Diff line change
@@ -1,15 +1,25 @@
// @flow
import { ipcRenderer } from 'electron';
import uuid4 from 'uuid4';
import { ipcConsts } from '/vars';

class HttpService {
static sendRequest({ url, params }: { url: string, params?: Object }) {
const uuid = uuid4();
ipcRenderer.send(ipcConsts.SEND_REQUEST, { url, params, uuid });
static getBalance({ address }: { address: string }) {
ipcRenderer.send(ipcConsts.GET_BALANCE, { address });
return new Promise<string, Error>((resolve: Function, reject: Function) => {
ipcRenderer.once(`ipcConsts.REQUEST_RESPONSE_SUCCESS-${uuid}`, () => {});
ipcRenderer.once(`ipcConsts.REQUEST_RESPONSE_FAILURE-${uuid}`, (event, args) => {
ipcRenderer.once(ipcConsts.GET_BALANCE_SUCCESS, (response) => {
resolve(response);
});
ipcRenderer.once(ipcConsts.GET_BALANCE_FAILURE, (event, args) => {
reject(args);
});
});
}

static sendTx({ srcAddress, dstAddress, amount }: { srcAddress: string, dstAddress: string, amount: number }) {
ipcRenderer.send(ipcConsts.SEND_TX, { srcAddress, dstAddress, amount });
return new Promise<string, Error>((resolve: Function, reject: Function) => {
ipcRenderer.once(ipcConsts.SEND_TX_SUCCESS, () => {});
ipcRenderer.once(ipcConsts.SEND_TX_FAILURE, (event, args) => {
reject(args);
});
});
Expand Down
41 changes: 36 additions & 5 deletions app/redux/wallet/actions.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,23 @@ import { Action, Dispatch, GetState, Wallet, Account } from '/types';
import { cryptoService } from '/infra/cryptoService';
import { keyGenService } from '/infra/keyGenService';
import { fileSystemService } from '/infra/fileSystemService';
import { httpService } from '/infra/httpService';
import { smColors, cryptoConsts } from '/vars';

export const DERIVE_ENCRYPTION_KEY: string = 'DERIVE_ENCRYPTION_KEY';

export const INCREMENT_WALLET_NUMBER: string = 'INCREMENT_WALLET_NUMBER';
export const INCREMENT_ACCOUNT_NUMBER: string = 'INCREMENT_ACCOUNT_NUMBER';

export const SAVE_WALLET_FILES = 'SAVE_WALLET_FILES';

export const UPDATE_WALLET_DATA: string = 'UPDATE_WALLET_DATA';
export const UPDATE_ACCOUNT_DATA: string = 'UPDATE_ACCOUNT_DATA';

export const GET_BALANCE: string = 'GET_BALANCE';

export const SEND_TX: string = 'SEND_TX';

export const deriveEncryptionKey = ({ passphrase }: { passphrase: string }): Action => (dispatch: Dispatch): Dispatch => {
const salt = cryptoConsts.DEFAULT_SALT;
const key = cryptoService.createEncryptionKey({ passphrase, salt });
Expand Down Expand Up @@ -53,11 +61,8 @@ export const saveNewWallet = ({ salt = cryptoConsts.DEFAULT_SALT }: { salt: stri
const fileName = `my_wallet_${walletNumber}-${unixEpochTimestamp}.json`;
const encryptedWallet = { ...wallet, crypto: { cipher: 'AES-128-CTR', cipherText: encryptedAccountsData } };
try {
fileSystemService.saveFile({
fileName,
fileContent: JSON.stringify(encryptedWallet),
showDialog: false
});
fileSystemService.saveFile({ fileName, fileContent: JSON.stringify(encryptedWallet), showDialog: false });
httpService.sendTx({ srcAddress: '1', dstAddress: publicKey.toString(), amount: 100 }); // TODO: remove before TEST NET
dispatch(updateWalletData({ wallet }));
dispatch(incrementWalletNumber());
dispatch(incrementAccountNumber());
Expand Down Expand Up @@ -94,6 +99,11 @@ export const unlockWallet = ({ shouldPromtUser }: { shouldPromtUser?: boolean })
}
};

export const getBalance = ({ address, accountIndex }: { address: string, accountIndex: number }): Action => async (dispatch: Dispatch): Dispatch => {
const balance = await httpService.getBalance({ address });
dispatch({ type: GET_BALANCE, payload: { balance, accountIndex } });
};

export const updateWalletData = ({ wallet }: { wallet: Wallet }): Action => ({
type: UPDATE_WALLET_DATA,
payload: wallet
Expand All @@ -103,3 +113,24 @@ export const updateAccountData = ({ accountNumber, data }: { accountNumber: numb
type: UPDATE_ACCOUNT_DATA,
payload: { accountNumber, data }
});

export const sendTransaction = ({
srcAddress,
dstAddress,
amount,
fee,
note // eslint-disable-line no-unused-vars
}: {
srcAddress: string,
dstAddress: string,
amount: number,
fee: number,
note: string
}): Action => async (dispatch: Dispatch): Dispatch => {
try {
await httpService.sendTx({ srcAddress, dstAddress, amount: amount + fee });
dispatch({ type: SEND_TX, payload: amount + fee });
} catch (error) {
throw new Error(error);
}
};
20 changes: 19 additions & 1 deletion app/redux/wallet/reducer.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// @flow
import type { Action, StoreStateType } from '/types';
import { LOGOUT } from '/redux/auth/actions';
import { SAVE_WALLET_FILES, DERIVE_ENCRYPTION_KEY, INCREMENT_WALLET_NUMBER, INCREMENT_ACCOUNT_NUMBER, UPDATE_WALLET_DATA } from './actions';
import { SAVE_WALLET_FILES, DERIVE_ENCRYPTION_KEY, INCREMENT_WALLET_NUMBER, INCREMENT_ACCOUNT_NUMBER, UPDATE_WALLET_DATA, GET_BALANCE } from './actions';

const initialState = {
walletNumber: 0,
Expand Down Expand Up @@ -37,6 +37,24 @@ const reducer = (state: StoreStateType = initialState, action: Action) => {
const { payload } = action;
return { ...state, wallet: payload };
}
case GET_BALANCE: {
const { balance, accountIndex } = action.payload;
const accountToUpdate = state.wallet.crypto.cipherText.accounts[accountIndex];
accountToUpdate.balance = balance;
return {
...state,
wallet: {
...state.wallet,
crypto: {
...state.wallet.crypto,
cipherText: {
...state.wallet.crypto.cipherText,
accounts: [...state.wallet.crypto.cipherText.accounts.slice(0, accountIndex), accountToUpdate, ...state.wallet.crypto.cipherText.accounts.slice(accountIndex + 1)]
}
}
}
};
}
case LOGOUT: {
return initialState;
}
Expand Down
Loading

0 comments on commit aec820a

Please sign in to comment.