Skip to content

Commit

Permalink
checkpoint
Browse files Browse the repository at this point in the history
  • Loading branch information
SebastienGllmt committed Jan 14, 2021
1 parent 7aaf0a3 commit 12e3071
Show file tree
Hide file tree
Showing 12 changed files with 453 additions and 4 deletions.
52 changes: 50 additions & 2 deletions app/components/wallet/send/WalletSendForm.js
Expand Up @@ -25,20 +25,24 @@ import { MAX_MEMO_SIZE } from '../../../config/externalStorageConfig';
import type { TokenRow, NetworkRow } from '../../../api/ada/lib/storage/database/primitives/tables';
import {
formattedAmountToBigNumber,
formattedAmountToNaturalUnits
formattedAmountToNaturalUnits,
truncateAddressShort,
} from '../../../utils/formatters';
import config from '../../../config';
import { InputOwnSkin } from '../../../themes/skins/InputOwnSkin';
import LocalizableError from '../../../i18n/LocalizableError';
import WarningBox from '../../widgets/WarningBox';
import type { $npm$ReactIntl$IntlFormat, } from 'react-intl';
import { getTokenName, genFormatTokenAmount, } from '../../../stores/stateless/tokenHelpers';
import { getTokenName, genFormatTokenAmount, getTokenStrictName, getTokenIdentifierIfExists, } from '../../../stores/stateless/tokenHelpers';
import {
MultiToken,
} from '../../../api/common/lib/MultiToken';
import type {
TokenLookupKey,
} from '../../../api/common/lib/MultiToken';
import { Select } from 'react-polymorph/lib/components/Select';
import { SelectTokenSkin } from '../../../themes/skins/SelectTokenSkin';
import TokenOptionRow from '../../widgets/tokenOption/TokenOptionRow';

const messages = defineMessages({
receiverLabel: {
Expand Down Expand Up @@ -96,6 +100,8 @@ type Props = {|
+onAddMemo: void => void,
+getTokenInfo: Inexact<TokenLookupKey> => $ReadOnly<TokenRow>,
+defaultToken: $ReadOnly<TokenRow>, // need since no guarantee input in non-null
+onAddToken: $ReadOnly<TokenRow> => void,
+spendableBalance: ?MultiToken,
|};

@observer
Expand Down Expand Up @@ -230,6 +236,13 @@ export default class WalletSendForm extends Component<Props> {
return isValidAmount;
}],
},
selectedToken: {
label: this.context.intl.formatMessage(globalMessages.assetSelect),
value: this.props.getTokenInfo({
identifier: this.props.defaultToken.Identifier,
networkId: this.props.defaultToken.NetworkId,
}).TokenId,
},
memo: {
label: this.context.intl.formatMessage(memoMessages.memoLabel),
placeholder: this.context.intl.formatMessage(memoMessages.optionalMemo),
Expand Down Expand Up @@ -314,13 +327,48 @@ export default class WalletSendForm extends Component<Props> {

const formatValue = genFormatTokenAmount(this.props.getTokenInfo);

const tokenOptions = (() => {
if (this.props.spendableBalance == null) return [];
const { spendableBalance } = this.props;
return [
// make sure default token is always first in the list
spendableBalance.getDefaultEntry(),
...spendableBalance.nonDefaultEntries(),
].map(entry => ({
entry,
info: this.props.getTokenInfo(entry),
})).map(token => ({
value: token.info.TokenId,
label: getTokenStrictName(token.info) ?? '-',
id: getTokenIdentifierIfExists(token.info) ?? '-',
amount: genFormatTokenAmount(this.props.getTokenInfo)(token.entry)
}));
})();

return (
<div className={styles.component}>

{hasAnyPending && pendingTxWarningComponent}

<BorderedBox>

{tokenOptions.length > 1 && (
<Select
className={styles.currencySelect}
options={tokenOptions}
{...form.$('selectedToken').bind()}
onChange={this.props.onAddToken}
skin={SelectTokenSkin}
optionRenderer={option => (
<TokenOptionRow
displayName={option.label}
id={truncateAddressShort(option.id)}
amount={option.amount}
/>
)}
/>
)}

<div className={styles.receiverInput}>
<Input
className="receiver"
Expand Down
32 changes: 32 additions & 0 deletions app/components/widgets/tokenOption/TokenOptionHeader.js
@@ -0,0 +1,32 @@
// @flow
import React, { Component } from 'react';
import type { Node } from 'react';
import { observer } from 'mobx-react';
import { intlShape } from 'react-intl';
import type { $npm$ReactIntl$IntlFormat } from 'react-intl';
import globalMessages from '../../../i18n/global-messages';
import classnames from 'classnames';

import styles from './TokenOptionRow.scss';

type Props = {|
|};

@observer
export default class TokenOptionHeader extends Component<Props> {
static contextTypes: {|intl: $npm$ReactIntl$IntlFormat|} = {
intl: intlShape.isRequired,
};

render(): Node {
const { intl } = this.context;

return (
<div className={classnames([styles.container, styles.headerText])}>
<span>{intl.formatMessage(globalMessages.name)}</span>
<span>{intl.formatMessage(globalMessages.id)}</span>
<span>{intl.formatMessage(globalMessages.amount)}</span>
</div>
);
}
}
26 changes: 26 additions & 0 deletions app/components/widgets/tokenOption/TokenOptionRow.js
@@ -0,0 +1,26 @@
// @flow
import React, { Component } from 'react';
import type { Node } from 'react';
import { observer } from 'mobx-react';
import classnames from 'classnames';

import styles from './TokenOptionRow.scss';

type Props = {|
+displayName: string,
+id: string,
+amount: string,
|};

@observer
export default class TokenOptionRow extends Component<Props> {
render(): Node {
return (
<div className={classnames([styles.container, styles.rowText])}>
<span>{this.props.displayName}</span>
<span>{this.props.id}</span>
<span>{this.props.amount}</span>
</div>
);
}
}
22 changes: 22 additions & 0 deletions app/components/widgets/tokenOption/TokenOptionRow.scss
@@ -0,0 +1,22 @@
.container {
display: flex;
width: 100%;
span {
width: 30%
}
}

.headerText {
color: #6B7384;
font-family: var(--font-regular);
font-size: 14px;
letter-spacing: 0;
line-height: 22px;
}
.rowText {
color: #242838;
font-family: var(--font-mono-regular);
font-size: 16px;
letter-spacing: 0;
line-height: 22px;
}
19 changes: 18 additions & 1 deletion app/containers/wallet/WalletSendPage.js
Expand Up @@ -158,6 +158,8 @@ export default class WalletSendPage extends Component<InjectedOrGenerated<Genera
dialog: MemoNoExternalStorageDialog,
continuation: this.toggleShowMemo,
})}
spendableBalance={this.generated.stores.transactions.getBalanceRequest.result}
onAddToken={() => { console.log('TODO'); }}
/>
{this.renderDialog()}
</>
Expand Down Expand Up @@ -442,7 +444,12 @@ export default class WalletSendPage extends Component<InjectedOrGenerated<Genera
|}
|}
|},
transactions: {| hasAnyPending: boolean |},
transactions: {|
hasAnyPending: boolean,
getBalanceRequest: {|
result: ?MultiToken,
|},
|},
uiDialogs: {|
getParam: <T>(number | string) => T,
isOpen: any => boolean
Expand Down Expand Up @@ -490,6 +497,16 @@ export default class WalletSendPage extends Component<InjectedOrGenerated<Genera
},
transactions: {
hasAnyPending: stores.transactions.hasAnyPending,
getBalanceRequest: (() => {
if (stores.wallets.selected == null) return {
result: undefined,
};
const { requests } = stores.transactions.getTxRequests(stores.wallets.selected);

return {
result: requests.getBalanceRequest.result,
};
})(),
},
transactionBuilderStore: {
totalInput: stores.transactionBuilderStore.totalInput,
Expand Down
3 changes: 3 additions & 0 deletions app/containers/wallet/WalletSendPage.stories.js
Expand Up @@ -105,6 +105,9 @@ const genBaseProps: {|
hasAnyPending: request.dialogInfo == null
? boolean('hasAnyPending', false)
: false,
getBalanceRequest: {
result: undefined,
},
},
transactionBuilderStore: request.dialogInfo == null
? {
Expand Down
16 changes: 16 additions & 0 deletions app/i18n/global-messages.js
Expand Up @@ -60,6 +60,18 @@ const globalMessages: * = defineMessages({
id: 'global.labels.current',
defaultMessage: '!!!Current',
},
name: {
id: 'global.labels.name',
defaultMessage: '!!!Name',
},
amount: {
id: 'global.labels.amount',
defaultMessage: '!!!Amount',
},
id: {
id: 'global.labels.id',
defaultMessage: '!!!ID',
},
finish: {
id: 'global.labels.finish',
defaultMessage: '!!!Finish',
Expand Down Expand Up @@ -268,6 +280,10 @@ const globalMessages: * = defineMessages({
id: 'wallet.summary.no.transaction',
defaultMessage: '!!!No transactions found',
},
assetSelect: {
id: 'global.selectAsset.labael',
defaultMessage: '!!!Select asset',
},
step1: {
id: 'transfer.form.instructions.step1.text',
defaultMessage: '!!!It will take about 1 minute to restore your balance. In the next step, you will be presented with a transaction that will move all of your funds. Please review the details of the transaction carefully. You will need to pay a standard transaction fee on the Cardano network to make the transaction.',
Expand Down
30 changes: 30 additions & 0 deletions app/stores/stateless/tokenHelpers.js
Expand Up @@ -9,6 +9,7 @@ import type { TokenRow } from '../../api/ada/lib/storage/database/primitives/tab
export function getTokenName(
tokenRow: $ReadOnly<{
Identifier: string,
IsDefault: boolean,
Metadata: {
ticker: null | string,
longName: null | string,
Expand All @@ -17,12 +18,41 @@ export function getTokenName(
...,
}>
): string {
const strictName = getTokenStrictName(tokenRow);
if (strictName != null) return strictName;
const identifier = getTokenIdentifierIfExists(tokenRow);
if (identifier != null) return identifier;
return '-';
}

export function getTokenStrictName(
tokenRow: $ReadOnly<{
Identifier: string,
Metadata: {
ticker: null | string,
longName: null | string,
...,
},
...,
}>
): void | string {
if (tokenRow.Metadata.ticker != null) {
return tokenRow.Metadata.ticker;
}
if (tokenRow.Metadata.longName != null) {
return tokenRow.Metadata.longName;
}
return undefined;
}

export function getTokenIdentifierIfExists(
tokenRow: $ReadOnly<{
Identifier: string,
IsDefault: boolean,
...,
}>
): void | string {
if (tokenRow.IsDefault) return undefined;
return tokenRow.Identifier;
}

Expand Down
2 changes: 1 addition & 1 deletion app/stores/toplevel/TransactionBuilderStore.js
Expand Up @@ -57,7 +57,7 @@ export default class TransactionBuilderStore extends Store {
// REQUESTS
@observable createUnsignedTx: LocalizedRequest<DeferredCall<ISignRequest<any>>>
= new LocalizedRequest<DeferredCall<ISignRequest<any>>>(async func => await func());
// this.api.ada.createUnsignedTx.bind(this.api.ada)

@observable memo: void | string;

@observable setupSelfTx: LocalizedRequest<SetupSelfTxFunc>
Expand Down

0 comments on commit 12e3071

Please sign in to comment.