Changeset View
Changeset View
Standalone View
Standalone View
web/cashtab/src/components/Send/Send.js
Show First 20 Lines • Show All 50 Lines • ▼ Show 20 Lines | |||||
import WalletLabel from 'components/Common/WalletLabel.js'; | import WalletLabel from 'components/Common/WalletLabel.js'; | ||||
const { TextArea } = Input; | const { TextArea } = Input; | ||||
const TextAreaLabel = styled.div` | const TextAreaLabel = styled.div` | ||||
text-align: left; | text-align: left; | ||||
color: ${props => props.theme.forms.text}; | color: ${props => props.theme.forms.text}; | ||||
padding-left: 1px; | padding-left: 1px; | ||||
white-space: nowrap; | |||||
`; | `; | ||||
const AmountPreviewCtn = styled.div` | const AmountPreviewCtn = styled.div` | ||||
margin-top: -30px; | margin-top: -30px; | ||||
`; | `; | ||||
const SendInputCtn = styled.div` | const SendInputCtn = styled.div` | ||||
.ant-form-item-with-help { | .ant-form-item-with-help { | ||||
margin-bottom: 32px; | margin-bottom: 32px; | ||||
} | } | ||||
`; | `; | ||||
const LocaleFormattedValue = styled.h3` | const LocaleFormattedValue = styled.h3` | ||||
color: ${props => props.theme.contrast}; | color: ${props => props.theme.contrast}; | ||||
font-weight: bold; | font-weight: bold; | ||||
margin-bottom: 0; | margin-bottom: 0; | ||||
`; | `; | ||||
const SendAddressHeader = styled.div` | |||||
display: flex; | |||||
align-items: center; | |||||
`; | |||||
const DestinationAddressSingleCtn = styled.div``; | |||||
const DestinationAddressMultiCtn = styled.div``; | |||||
const ExpandingAddressInputCtn = styled.div` | |||||
min-height: 14rem; | |||||
${DestinationAddressSingleCtn} { | |||||
overflow: hidden; | |||||
max-height: ${props => (props.open ? '0rem' : '17rem')}; | |||||
} | |||||
${DestinationAddressMultiCtn} { | |||||
overflow: hidden; | |||||
max-height: ${props => (props.open ? '17rem' : '0rem')}; | |||||
} | |||||
`; | |||||
// Note jestBCH is only used for unit tests; BCHJS must be mocked for jest | // Note jestBCH is only used for unit tests; BCHJS must be mocked for jest | ||||
const SendBCH = ({ jestBCH, passLoadingStatus }) => { | const SendBCH = ({ jestBCH, passLoadingStatus }) => { | ||||
// use balance parameters from wallet.state object and not legacy balances parameter from walletState, if user has migrated wallet | // use balance parameters from wallet.state object and not legacy balances parameter from walletState, if user has migrated wallet | ||||
// this handles edge case of user with old wallet who has not opened latest Cashtab version yet | // this handles edge case of user with old wallet who has not opened latest Cashtab version yet | ||||
// If the wallet object from ContextValue has a `state key`, then check which keys are in the wallet object | // If the wallet object from ContextValue has a `state key`, then check which keys are in the wallet object | ||||
// Else set it as blank | // Else set it as blank | ||||
const ContextValue = React.useContext(WalletContext); | const ContextValue = React.useContext(WalletContext); | ||||
▲ Show 20 Lines • Show All 584 Lines • ▼ Show 20 Lines | return ( | ||||
<Row type="flex"> | <Row type="flex"> | ||||
<Col span={24}> | <Col span={24}> | ||||
<Form | <Form | ||||
style={{ | style={{ | ||||
width: 'auto', | width: 'auto', | ||||
marginTop: '40px', | marginTop: '40px', | ||||
}} | }} | ||||
> | > | ||||
{!isOneToManyXECSend ? ( | <SendAddressHeader> | ||||
<SendInputCtn> | {' '} | ||||
<FormLabel>Send to</FormLabel> | <FormLabel>Send to</FormLabel> | ||||
<TextAreaLabel> | |||||
Multiple Recipients: | |||||
<Switch | |||||
defaultunchecked="true" | |||||
checked={isOneToManyXECSend} | |||||
onChange={() => { | |||||
setIsOneToManyXECSend( | |||||
!isOneToManyXECSend, | |||||
); | |||||
setIsEncryptedOptionalOpReturnMsg( | |||||
false, | |||||
); | |||||
}} | |||||
style={{ | |||||
marginBottom: '7px', | |||||
}} | |||||
/> | |||||
</TextAreaLabel> | |||||
</SendAddressHeader> | |||||
<ExpandingAddressInputCtn open={isOneToManyXECSend}> | |||||
<SendInputCtn> | |||||
<DestinationAddressSingleCtn> | |||||
<DestinationAddressSingle | <DestinationAddressSingle | ||||
style={{ marginBottom: '0px' }} | style={{ marginBottom: '0px' }} | ||||
loadWithCameraOpen={ | loadWithCameraOpen={ | ||||
location && | location && | ||||
location.state && | location.state && | ||||
location.state.replyAddress | location.state.replyAddress | ||||
? false | ? false | ||||
: scannerSupported | : scannerSupported | ||||
} | } | ||||
validateStatus={ | validateStatus={ | ||||
sendBchAddressError ? 'error' : '' | sendBchAddressError | ||||
? 'error' | |||||
: '' | |||||
} | } | ||||
help={ | help={ | ||||
sendBchAddressError | sendBchAddressError | ||||
? sendBchAddressError | ? sendBchAddressError | ||||
: '' | : '' | ||||
} | } | ||||
onScan={result => | onScan={result => | ||||
handleAddressChange({ | handleAddressChange({ | ||||
target: { | target: { | ||||
name: 'address', | name: 'address', | ||||
value: result, | value: result, | ||||
}, | }, | ||||
}) | }) | ||||
} | } | ||||
inputProps={{ | inputProps={{ | ||||
placeholder: `${currency.ticker} Address`, | placeholder: `${currency.ticker} Address`, | ||||
name: 'address', | name: 'address', | ||||
onChange: e => | onChange: e => | ||||
handleAddressChange(e), | handleAddressChange(e), | ||||
required: true, | required: true, | ||||
value: formData.address, | value: formData.address, | ||||
}} | }} | ||||
></DestinationAddressSingle> | ></DestinationAddressSingle> | ||||
<FormLabel>Amount</FormLabel> | <FormLabel>Amount</FormLabel> | ||||
<SendBchInput | <SendBchInput | ||||
activeFiatCode={ | activeFiatCode={ | ||||
cashtabSettings && | cashtabSettings && | ||||
cashtabSettings.fiatCurrency | cashtabSettings.fiatCurrency | ||||
? cashtabSettings.fiatCurrency.toUpperCase() | ? cashtabSettings.fiatCurrency.toUpperCase() | ||||
: 'USD' | : 'USD' | ||||
} | } | ||||
validateStatus={ | validateStatus={ | ||||
sendBchAmountError ? 'error' : '' | sendBchAmountError | ||||
? 'error' | |||||
: '' | |||||
} | } | ||||
help={ | help={ | ||||
sendBchAmountError | sendBchAmountError | ||||
? sendBchAmountError | ? sendBchAmountError | ||||
: '' | : '' | ||||
} | } | ||||
onMax={onMax} | onMax={onMax} | ||||
inputProps={{ | inputProps={{ | ||||
name: 'value', | name: 'value', | ||||
dollar: | dollar: | ||||
selectedCurrency === 'USD' | selectedCurrency === 'USD' | ||||
? 1 | ? 1 | ||||
: 0, | : 0, | ||||
placeholder: 'Amount', | placeholder: 'Amount', | ||||
onChange: e => | onChange: e => | ||||
handleBchAmountChange(e), | handleBchAmountChange(e), | ||||
required: true, | required: true, | ||||
value: formData.value, | value: formData.value, | ||||
disabled: priceApiError, | disabled: priceApiError, | ||||
}} | }} | ||||
selectProps={{ | selectProps={{ | ||||
value: selectedCurrency, | value: selectedCurrency, | ||||
disabled: queryStringText !== null, | disabled: | ||||
queryStringText !== null, | |||||
onChange: e => | onChange: e => | ||||
handleSelectedCurrencyChange(e), | handleSelectedCurrencyChange( | ||||
e, | |||||
), | |||||
}} | }} | ||||
></SendBchInput> | ></SendBchInput> | ||||
</DestinationAddressSingleCtn> | |||||
{priceApiError && ( | {priceApiError && ( | ||||
<AlertMsg> | <AlertMsg> | ||||
Error fetching fiat price. Setting | Error fetching fiat price. Setting | ||||
send by{' '} | send by{' '} | ||||
{currency.fiatCurrencies[ | {currency.fiatCurrencies[ | ||||
cashtabSettings.fiatCurrency | cashtabSettings.fiatCurrency | ||||
].slug.toUpperCase()}{' '} | ].slug.toUpperCase()}{' '} | ||||
disabled | disabled | ||||
</AlertMsg> | </AlertMsg> | ||||
)} | )} | ||||
</SendInputCtn> | </SendInputCtn> | ||||
) : ( | |||||
<> | <> | ||||
<FormLabel>Send to</FormLabel> | <DestinationAddressMultiCtn> | ||||
<DestinationAddressMulti | <DestinationAddressMulti | ||||
validateStatus={ | validateStatus={ | ||||
sendBchAddressError ? 'error' : '' | sendBchAddressError | ||||
? 'error' | |||||
: '' | |||||
} | } | ||||
help={ | help={ | ||||
sendBchAddressError | sendBchAddressError | ||||
? sendBchAddressError | ? sendBchAddressError | ||||
: '' | : '' | ||||
} | } | ||||
inputProps={{ | inputProps={{ | ||||
placeholder: `One XEC address & value per line, separated by comma \ne.g. \necash:qpatql05s9jfavnu0tv6lkjjk25n6tmj9gkpyrlwu8,500 \necash:qzvydd4n3lm3xv62cx078nu9rg0e3srmqq0knykfed,700`, | placeholder: `One XEC address & value per line, separated by comma \ne.g. \necash:qpatql05s9jfavnu0tv6lkjjk25n6tmj9gkpyrlwu8,500 \necash:qzvydd4n3lm3xv62cx078nu9rg0e3srmqq0knykfed,700`, | ||||
name: 'address', | name: 'address', | ||||
onChange: e => | onChange: e => | ||||
handleMultiAddressChange(e), | handleMultiAddressChange(e), | ||||
required: true, | required: true, | ||||
value: formData.address, | value: formData.address, | ||||
}} | }} | ||||
></DestinationAddressMulti> | ></DestinationAddressMulti> | ||||
</DestinationAddressMultiCtn> | |||||
</> | </> | ||||
)} | |||||
{!priceApiError && !isOneToManyXECSend && ( | |||||
<AmountPreviewCtn> | <AmountPreviewCtn> | ||||
{!priceApiError && !isOneToManyXECSend && ( | |||||
<> | |||||
<LocaleFormattedValue> | <LocaleFormattedValue> | ||||
{formatBalance( | {formatBalance( | ||||
formData.value, | formData.value, | ||||
userLocale, | userLocale, | ||||
)}{' '} | )}{' '} | ||||
{selectedCurrency} | {selectedCurrency} | ||||
</LocaleFormattedValue> | </LocaleFormattedValue> | ||||
<ConvertAmount> | <ConvertAmount> | ||||
{fiatPriceString !== '' && '='}{' '} | {fiatPriceString !== '' && '='}{' '} | ||||
{fiatPriceString} | {fiatPriceString} | ||||
</ConvertAmount> | </ConvertAmount> | ||||
</AmountPreviewCtn> | </> | ||||
)} | )} | ||||
</AmountPreviewCtn> | |||||
</ExpandingAddressInputCtn> | |||||
{queryStringText && ( | {queryStringText && ( | ||||
<Alert | <Alert | ||||
message={`You are sending a transaction to an address including query parameters "${queryStringText}." Only the "amount" parameter, in units of ${currency.ticker} satoshis, is currently supported.`} | message={`You are sending a transaction to an address including query parameters "${queryStringText}." Only the "amount" parameter, in units of ${currency.ticker} satoshis, is currently supported.`} | ||||
type="warning" | type="warning" | ||||
/> | /> | ||||
)} | )} | ||||
<div | <div | ||||
▲ Show 20 Lines • Show All 42 Lines • ▼ Show 20 Lines | return ( | ||||
optionalKey="1" | optionalKey="1" | ||||
> | > | ||||
<AntdFormWrapper | <AntdFormWrapper | ||||
style={{ | style={{ | ||||
marginBottom: '20px', | marginBottom: '20px', | ||||
}} | }} | ||||
> | > | ||||
<TextAreaLabel> | <TextAreaLabel> | ||||
Multiple Recipients: | |||||
<Switch | |||||
defaultunchecked="true" | |||||
checked={isOneToManyXECSend} | |||||
onChange={() => { | |||||
setIsOneToManyXECSend( | |||||
!isOneToManyXECSend, | |||||
); | |||||
setIsEncryptedOptionalOpReturnMsg( | |||||
false, | |||||
); | |||||
}} | |||||
style={{ | |||||
marginBottom: '7px', | |||||
}} | |||||
/> | |||||
</TextAreaLabel> | |||||
<TextAreaLabel> | |||||
Message: | Message: | ||||
<Switch | <Switch | ||||
disabled={isOneToManyXECSend} | disabled={isOneToManyXECSend} | ||||
style={{ | style={{ | ||||
marginBottom: '7px', | marginBottom: '7px', | ||||
}} | }} | ||||
checkedChildren="Private" | checkedChildren="Private" | ||||
unCheckedChildren="Public" | unCheckedChildren="Public" | ||||
▲ Show 20 Lines • Show All 106 Lines • Show Last 20 Lines |