diff --git a/web/cashtab/src/components/Common/StyledCollapse.js b/web/cashtab/src/components/Common/StyledCollapse.js --- a/web/cashtab/src/components/Common/StyledCollapse.js +++ b/web/cashtab/src/components/Common/StyledCollapse.js @@ -51,3 +51,36 @@ } `} `; + +export const AdvancedCollapse = styled(Collapse)` + ${({ disabled = false, ...props }) => + disabled === true + ? ` + background: ${props.theme.buttons.secondary.background} !important; + .ant-collapse-header { + font-size: 18px; + font-weight: normal; + color: ${props.theme.buttons.secondary.color} !important; + svg { + color: ${props.theme.buttons.secondary.color} !important; + } + } + .ant-collapse-arrow { + font-size: 18px; + } + ` + : ` + background: ${props.theme.primary} !important; + .ant-collapse-header { + font-size: 18px; + font-weight: bold; + color: ${props.theme.contrast} !important; + svg { + color: ${props.theme.contrast} !important; + } + } + .ant-collapse-arrow { + font-size: 18px; + } + `} +`; diff --git a/web/cashtab/src/components/Configure/__tests__/__snapshots__/Configure.test.js.snap b/web/cashtab/src/components/Configure/__tests__/__snapshots__/Configure.test.js.snap --- a/web/cashtab/src/components/Configure/__tests__/__snapshots__/Configure.test.js.snap +++ b/web/cashtab/src/components/Configure/__tests__/__snapshots__/Configure.test.js.snap @@ -2,7 +2,7 @@ exports[`Configure with a wallet 1`] = ` <div - className="sc-kkGfuU liSflp" + className="sc-iAyFgw hatKtw" > <h2> <span @@ -110,7 +110,7 @@ </div> </div> <div - className="sc-iAyFgw AbOBK" + className="sc-hSdWYo iEyugW" /> <h2> <span @@ -135,7 +135,7 @@ Manage Wallets </h2> <button - className="sc-VigVT RpRhe" + className="sc-jTzLTM iVNQiK" onClick={[Function]} > <span @@ -163,7 +163,7 @@ New Wallet </button> <button - className="sc-jTzLTM bLkbAy" + className="sc-fjdhpX eXuEIC" onClick={[Function]} > <span @@ -188,7 +188,7 @@ Import Wallet </button> <div - className="sc-iAyFgw AbOBK" + className="sc-hSdWYo iEyugW" /> <h2> <span @@ -213,7 +213,7 @@ Fiat Currency </h2> <div - className="sc-iwsKbI dmHKdG" + className="sc-gZMcBi bZwSTm" > <div className="ant-select select-after ant-select-single ant-select-show-arrow" @@ -305,11 +305,11 @@ </div> </div> <div - className="sc-iAyFgw AbOBK" + className="sc-hSdWYo iEyugW" /> [ <a - className="sc-dxgOiQ jbuVAx" + className="sc-ckVGcZ bhwAJY" href="https://docs.cashtabapp.com/docs/" rel="noreferrer" target="_blank" @@ -323,7 +323,7 @@ exports[`Configure without a wallet 1`] = ` <div - className="sc-kkGfuU liSflp" + className="sc-iAyFgw hatKtw" > <h2> <span @@ -393,7 +393,7 @@ </div> </div> <div - className="sc-iAyFgw AbOBK" + className="sc-hSdWYo iEyugW" /> <h2> <span @@ -418,7 +418,7 @@ Manage Wallets </h2> <button - className="sc-VigVT RpRhe" + className="sc-jTzLTM iVNQiK" onClick={[Function]} > <span @@ -446,7 +446,7 @@ New Wallet </button> <button - className="sc-jTzLTM bLkbAy" + className="sc-fjdhpX eXuEIC" onClick={[Function]} > <span @@ -471,7 +471,7 @@ Import Wallet </button> <div - className="sc-iAyFgw AbOBK" + className="sc-hSdWYo iEyugW" /> <h2> <span @@ -496,7 +496,7 @@ Fiat Currency </h2> <div - className="sc-iwsKbI dmHKdG" + className="sc-gZMcBi bZwSTm" > <div className="ant-select select-after ant-select-single ant-select-show-arrow" @@ -588,11 +588,11 @@ </div> </div> <div - className="sc-iAyFgw AbOBK" + className="sc-hSdWYo iEyugW" /> [ <a - className="sc-dxgOiQ jbuVAx" + className="sc-ckVGcZ bhwAJY" href="https://docs.cashtabapp.com/docs/" rel="noreferrer" target="_blank" diff --git a/web/cashtab/src/components/Send/Send.js b/web/cashtab/src/components/Send/Send.js --- a/web/cashtab/src/components/Send/Send.js +++ b/web/cashtab/src/components/Send/Send.js @@ -1,8 +1,11 @@ import React, { useState, useEffect } from 'react'; import PropTypes from 'prop-types'; import { WalletContext } from '@utils/context'; +import { AntdFormWrapper } from '@components/Common/EnhancedInputs'; +import { AdvancedCollapse } from '@components/Common/StyledCollapse'; import { Form, notification, message, Modal, Alert } from 'antd'; import { Row, Col } from 'antd'; +import { Collapse, Input } from 'antd'; import Paragraph from 'antd/lib/typography/Paragraph'; import PrimaryButton, { SecondaryButton, @@ -32,6 +35,7 @@ import { getWalletState } from '@utils/cashMethods'; import { CashReceivedNotificationIcon } from '@components/Common/CustomIcons'; import ApiError from '@components/Common/ApiError'; +const { Panel } = Collapse; // Note jestBCH is only used for unit tests; BCHJS must be mocked for jest const SendBCH = ({ jestBCH, passLoadingStatus }) => { @@ -141,6 +145,8 @@ return; } + let optionalOpReturnMsg = formData.opReturnMsg; + // Event("Category", "Action", "Label") // Track number of BCHA send transactions and whether users // are sending BCHA or USD @@ -191,6 +197,7 @@ cleanAddress, bchValue, currency.defaultFee, + optionalOpReturnMsg, ); notification.success({ @@ -327,6 +334,15 @@ })); }; + const handleOpReturnMsgChange = e => { + const { value, name } = e.target; + + setFormData(p => ({ + ...p, + [name]: value, + })); + }; + const onMax = async () => { // Clear amt error setSendBchAmountError(false); @@ -479,6 +495,42 @@ <ConvertAmount> {fiatPriceString !== '' && '='} {fiatPriceString} </ConvertAmount> + <div + style={{ + paddingTop: '32px', + }} + > + <AdvancedCollapse + style={{ + marginBottom: '24px', + }} + > + <Panel header="Advanced" key="1"> + <AntdFormWrapper> + <Form + size="small" + style={{ + width: 'auto', + }} + > + <Form.Item> + <Input + addonBefore="Message" + placeholder="Optional OP_RETURN Msg (max 150 chars)" + name="opReturnMsg" + onChange={e => + handleOpReturnMsgChange( + e, + ) + } + maxLength="150" + /> + </Form.Item> + </Form> + </AntdFormWrapper> + </Panel> + </AdvancedCollapse> + </div> <div style={{ paddingTop: '12px', diff --git a/web/cashtab/src/components/Send/__tests__/__snapshots__/Send.test.js.snap b/web/cashtab/src/components/Send/__tests__/__snapshots__/Send.test.js.snap --- a/web/cashtab/src/components/Send/__tests__/__snapshots__/Send.test.js.snap +++ b/web/cashtab/src/components/Send/__tests__/__snapshots__/Send.test.js.snap @@ -3,7 +3,7 @@ exports[`Wallet with BCH balances 1`] = ` Array [ <div - className="sc-cSHVUG evOoHm" + className="sc-kgoBCf fswuXg" > You currently have 0 XEC @@ -30,7 +30,7 @@ } > <div - className="sc-gZMcBi bZwSTm" + className="sc-htoDjs cDnNqw" > <div className="ant-row ant-form-item" @@ -99,7 +99,7 @@ className="ant-input-group-addon" > <span - className="sc-htoDjs clindv" + className="sc-EHOje jPIGGt" onClick={[Function]} > <span @@ -140,7 +140,7 @@ </div> </div> <div - className="sc-gZMcBi bZwSTm" + className="sc-htoDjs cDnNqw" > <div className="ant-row ant-form-item" @@ -285,7 +285,7 @@ </span> </div> <span - className="sc-VigVT hzxqG" + className="sc-iwsKbI bMOJU" disabled={false} onClick={[Function]} style={ @@ -314,12 +314,63 @@ </div> </div> <div - className="sc-kgoBCf kMQqjE" + className="sc-dxgOiQ kbCOBL" > = $ NaN USD </div> + <div + style={ + Object { + "paddingTop": "32px", + } + } + > + <div + className="ant-collapse ant-collapse-icon-position-left sc-VigVT idAASz" + role={null} + style={ + Object { + "marginBottom": "24px", + } + } + > + <div + className="ant-collapse-item" + > + <div + aria-expanded={false} + className="ant-collapse-header" + onClick={[Function]} + onKeyPress={[Function]} + role="button" + tabIndex={0} + > + <span + aria-label="right" + className="anticon anticon-right ant-collapse-arrow" + role="img" + > + <svg + aria-hidden="true" + data-icon="right" + fill="currentColor" + focusable="false" + height="1em" + viewBox="64 64 896 896" + width="1em" + > + <path + d="M765.7 486.8L314.9 134.7A7.97 7.97 0 00302 141v77.3c0 4.9 2.3 9.6 6.1 12.6l360 281.1-360 281.1c-3.9 3-6.1 7.7-6.1 12.6V883c0 6.7 7.7 10.4 12.9 6.3l450.8-352.1a31.96 31.96 0 000-50.4z" + /> + </svg> + </span> + Advanced + </div> + </div> + </div> + </div> <div style={ Object { @@ -328,7 +379,7 @@ } > <button - className="sc-bZQynM hlOQYo" + className="sc-fjdhpX eXuEIC" > Send </button> @@ -342,7 +393,7 @@ exports[`Wallet with BCH balances and tokens 1`] = ` Array [ <div - className="sc-cSHVUG evOoHm" + className="sc-kgoBCf fswuXg" > You currently have 0 XEC @@ -369,7 +420,7 @@ } > <div - className="sc-gZMcBi bZwSTm" + className="sc-htoDjs cDnNqw" > <div className="ant-row ant-form-item" @@ -438,7 +489,7 @@ className="ant-input-group-addon" > <span - className="sc-htoDjs clindv" + className="sc-EHOje jPIGGt" onClick={[Function]} > <span @@ -479,7 +530,7 @@ </div> </div> <div - className="sc-gZMcBi bZwSTm" + className="sc-htoDjs cDnNqw" > <div className="ant-row ant-form-item" @@ -624,7 +675,7 @@ </span> </div> <span - className="sc-VigVT hzxqG" + className="sc-iwsKbI bMOJU" disabled={false} onClick={[Function]} style={ @@ -653,12 +704,63 @@ </div> </div> <div - className="sc-kgoBCf kMQqjE" + className="sc-dxgOiQ kbCOBL" > = $ NaN USD </div> + <div + style={ + Object { + "paddingTop": "32px", + } + } + > + <div + className="ant-collapse ant-collapse-icon-position-left sc-VigVT idAASz" + role={null} + style={ + Object { + "marginBottom": "24px", + } + } + > + <div + className="ant-collapse-item" + > + <div + aria-expanded={false} + className="ant-collapse-header" + onClick={[Function]} + onKeyPress={[Function]} + role="button" + tabIndex={0} + > + <span + aria-label="right" + className="anticon anticon-right ant-collapse-arrow" + role="img" + > + <svg + aria-hidden="true" + data-icon="right" + fill="currentColor" + focusable="false" + height="1em" + viewBox="64 64 896 896" + width="1em" + > + <path + d="M765.7 486.8L314.9 134.7A7.97 7.97 0 00302 141v77.3c0 4.9 2.3 9.6 6.1 12.6l360 281.1-360 281.1c-3.9 3-6.1 7.7-6.1 12.6V883c0 6.7 7.7 10.4 12.9 6.3l450.8-352.1a31.96 31.96 0 000-50.4z" + /> + </svg> + </span> + Advanced + </div> + </div> + </div> + </div> <div style={ Object { @@ -667,7 +769,7 @@ } > <button - className="sc-bZQynM hlOQYo" + className="sc-fjdhpX eXuEIC" > Send </button> @@ -681,14 +783,14 @@ exports[`Wallet with BCH balances and tokens and state field 1`] = ` Array [ <div - className="sc-fjdhpX llHaIR" + className="sc-kAzzGY kdOdTZ" > 0.06047469 XEC </div>, <div - className="sc-jzJRlG fVAWpo" + className="sc-chPdSV elAazB" > $ NaN @@ -715,7 +817,7 @@ } > <div - className="sc-gZMcBi bZwSTm" + className="sc-htoDjs cDnNqw" > <div className="ant-row ant-form-item" @@ -784,7 +886,7 @@ className="ant-input-group-addon" > <span - className="sc-htoDjs clindv" + className="sc-EHOje jPIGGt" onClick={[Function]} > <span @@ -825,7 +927,7 @@ </div> </div> <div - className="sc-gZMcBi bZwSTm" + className="sc-htoDjs cDnNqw" > <div className="ant-row ant-form-item" @@ -970,7 +1072,7 @@ </span> </div> <span - className="sc-VigVT hzxqG" + className="sc-iwsKbI bMOJU" disabled={false} onClick={[Function]} style={ @@ -999,12 +1101,63 @@ </div> </div> <div - className="sc-kgoBCf kMQqjE" + className="sc-dxgOiQ kbCOBL" > = $ NaN USD </div> + <div + style={ + Object { + "paddingTop": "32px", + } + } + > + <div + className="ant-collapse ant-collapse-icon-position-left sc-VigVT idAASz" + role={null} + style={ + Object { + "marginBottom": "24px", + } + } + > + <div + className="ant-collapse-item" + > + <div + aria-expanded={false} + className="ant-collapse-header" + onClick={[Function]} + onKeyPress={[Function]} + role="button" + tabIndex={0} + > + <span + aria-label="right" + className="anticon anticon-right ant-collapse-arrow" + role="img" + > + <svg + aria-hidden="true" + data-icon="right" + fill="currentColor" + focusable="false" + height="1em" + viewBox="64 64 896 896" + width="1em" + > + <path + d="M765.7 486.8L314.9 134.7A7.97 7.97 0 00302 141v77.3c0 4.9 2.3 9.6 6.1 12.6l360 281.1-360 281.1c-3.9 3-6.1 7.7-6.1 12.6V883c0 6.7 7.7 10.4 12.9 6.3l450.8-352.1a31.96 31.96 0 000-50.4z" + /> + </svg> + </span> + Advanced + </div> + </div> + </div> + </div> <div style={ Object { @@ -1013,7 +1166,7 @@ } > <button - className="sc-EHOje bfWfmf" + className="sc-jTzLTM iVNQiK" onClick={[Function]} > Send @@ -1028,7 +1181,7 @@ exports[`Wallet without BCH balance 1`] = ` Array [ <div - className="sc-cSHVUG evOoHm" + className="sc-kgoBCf fswuXg" > You currently have 0 XEC @@ -1055,7 +1208,7 @@ } > <div - className="sc-gZMcBi bZwSTm" + className="sc-htoDjs cDnNqw" > <div className="ant-row ant-form-item" @@ -1124,7 +1277,7 @@ className="ant-input-group-addon" > <span - className="sc-htoDjs clindv" + className="sc-EHOje jPIGGt" onClick={[Function]} > <span @@ -1165,7 +1318,7 @@ </div> </div> <div - className="sc-gZMcBi bZwSTm" + className="sc-htoDjs cDnNqw" > <div className="ant-row ant-form-item" @@ -1310,7 +1463,7 @@ </span> </div> <span - className="sc-VigVT hzxqG" + className="sc-iwsKbI bMOJU" disabled={false} onClick={[Function]} style={ @@ -1339,12 +1492,63 @@ </div> </div> <div - className="sc-kgoBCf kMQqjE" + className="sc-dxgOiQ kbCOBL" > = $ NaN USD </div> + <div + style={ + Object { + "paddingTop": "32px", + } + } + > + <div + className="ant-collapse ant-collapse-icon-position-left sc-VigVT idAASz" + role={null} + style={ + Object { + "marginBottom": "24px", + } + } + > + <div + className="ant-collapse-item" + > + <div + aria-expanded={false} + className="ant-collapse-header" + onClick={[Function]} + onKeyPress={[Function]} + role="button" + tabIndex={0} + > + <span + aria-label="right" + className="anticon anticon-right ant-collapse-arrow" + role="img" + > + <svg + aria-hidden="true" + data-icon="right" + fill="currentColor" + focusable="false" + height="1em" + viewBox="64 64 896 896" + width="1em" + > + <path + d="M765.7 486.8L314.9 134.7A7.97 7.97 0 00302 141v77.3c0 4.9 2.3 9.6 6.1 12.6l360 281.1-360 281.1c-3.9 3-6.1 7.7-6.1 12.6V883c0 6.7 7.7 10.4 12.9 6.3l450.8-352.1a31.96 31.96 0 000-50.4z" + /> + </svg> + </span> + Advanced + </div> + </div> + </div> + </div> <div style={ Object { @@ -1353,7 +1557,7 @@ } > <button - className="sc-bZQynM hlOQYo" + className="sc-fjdhpX eXuEIC" > Send </button> @@ -1367,7 +1571,7 @@ exports[`Without wallet defined 1`] = ` Array [ <div - className="sc-cSHVUG evOoHm" + className="sc-kgoBCf fswuXg" > You currently have 0 XEC @@ -1394,7 +1598,7 @@ } > <div - className="sc-gZMcBi bZwSTm" + className="sc-htoDjs cDnNqw" > <div className="ant-row ant-form-item" @@ -1463,7 +1667,7 @@ className="ant-input-group-addon" > <span - className="sc-htoDjs clindv" + className="sc-EHOje jPIGGt" onClick={[Function]} > <span @@ -1504,7 +1708,7 @@ </div> </div> <div - className="sc-gZMcBi bZwSTm" + className="sc-htoDjs cDnNqw" > <div className="ant-row ant-form-item" @@ -1649,7 +1853,7 @@ </span> </div> <span - className="sc-VigVT hzxqG" + className="sc-iwsKbI bMOJU" disabled={false} onClick={[Function]} style={ @@ -1678,12 +1882,63 @@ </div> </div> <div - className="sc-kgoBCf kMQqjE" + className="sc-dxgOiQ kbCOBL" > = $ NaN USD </div> + <div + style={ + Object { + "paddingTop": "32px", + } + } + > + <div + className="ant-collapse ant-collapse-icon-position-left sc-VigVT idAASz" + role={null} + style={ + Object { + "marginBottom": "24px", + } + } + > + <div + className="ant-collapse-item" + > + <div + aria-expanded={false} + className="ant-collapse-header" + onClick={[Function]} + onKeyPress={[Function]} + role="button" + tabIndex={0} + > + <span + aria-label="right" + className="anticon anticon-right ant-collapse-arrow" + role="img" + > + <svg + aria-hidden="true" + data-icon="right" + fill="currentColor" + focusable="false" + height="1em" + viewBox="64 64 896 896" + width="1em" + > + <path + d="M765.7 486.8L314.9 134.7A7.97 7.97 0 00302 141v77.3c0 4.9 2.3 9.6 6.1 12.6l360 281.1-360 281.1c-3.9 3-6.1 7.7-6.1 12.6V883c0 6.7 7.7 10.4 12.9 6.3l450.8-352.1a31.96 31.96 0 000-50.4z" + /> + </svg> + </span> + Advanced + </div> + </div> + </div> + </div> <div style={ Object { @@ -1692,7 +1947,7 @@ } > <button - className="sc-bZQynM hlOQYo" + className="sc-fjdhpX eXuEIC" > Send </button> diff --git a/web/cashtab/src/components/Tokens/__tests__/__snapshots__/Tokens.test.js.snap b/web/cashtab/src/components/Tokens/__tests__/__snapshots__/Tokens.test.js.snap --- a/web/cashtab/src/components/Tokens/__tests__/__snapshots__/Tokens.test.js.snap +++ b/web/cashtab/src/components/Tokens/__tests__/__snapshots__/Tokens.test.js.snap @@ -3,14 +3,14 @@ exports[`Wallet with BCH balances 1`] = ` Array [ <div - className="sc-chPdSV kmzXKJ" + className="sc-kgoBCf fswuXg" > You need some XEC in your wallet to create tokens. </div>, <div - className="sc-cSHVUG lalYdv" + className="sc-kAzzGY kdOdTZ" > 0 @@ -60,7 +60,7 @@ </div> </div>, <p - className="sc-kGXeez gsczLr" + className="sc-kpOJdX bjUfnF" > You need at least @@ -83,14 +83,14 @@ exports[`Wallet with BCH balances and tokens 1`] = ` Array [ <div - className="sc-chPdSV kmzXKJ" + className="sc-kgoBCf fswuXg" > You need some XEC in your wallet to create tokens. </div>, <div - className="sc-cSHVUG lalYdv" + className="sc-kAzzGY kdOdTZ" > 0 @@ -140,7 +140,7 @@ </div> </div>, <p - className="sc-kGXeez gsczLr" + className="sc-kpOJdX bjUfnF" > You need at least @@ -163,14 +163,14 @@ exports[`Wallet with BCH balances and tokens and state field 1`] = ` Array [ <div - className="sc-cSHVUG lalYdv" + className="sc-kAzzGY kdOdTZ" > 0.06047469 XEC </div>, <div - className="sc-kAzzGY hVJvbw" + className="sc-chPdSV elAazB" > $ NaN @@ -226,10 +226,10 @@ onClick={[Function]} > <div - className="sc-jKJlTe gnEvYb" + className="sc-eNQAEJ cKMjcK" > <div - className="sc-dxgOiQ ehOwnn" + className="sc-ckVGcZ ealBRQ" > <img alt="identicon of tokenId bd1acc4c986de57af8d6d2a64aecad8c30ee80f37ae9d066d758923732ddc9ba " @@ -244,7 +244,7 @@ /> </div> <div - className="sc-ckVGcZ dWSPyd" + className="sc-jKJlTe bUCZgB" > 6.001 @@ -261,14 +261,14 @@ exports[`Wallet without BCH balance 1`] = ` Array [ <div - className="sc-chPdSV kmzXKJ" + className="sc-kgoBCf fswuXg" > You need some XEC in your wallet to create tokens. </div>, <div - className="sc-cSHVUG lalYdv" + className="sc-kAzzGY kdOdTZ" > 0 @@ -318,7 +318,7 @@ </div> </div>, <p - className="sc-kGXeez gsczLr" + className="sc-kpOJdX bjUfnF" > You need at least @@ -341,14 +341,14 @@ exports[`Without wallet defined 1`] = ` Array [ <div - className="sc-chPdSV kmzXKJ" + className="sc-kgoBCf fswuXg" > You need some XEC in your wallet to create tokens. </div>, <div - className="sc-cSHVUG lalYdv" + className="sc-kAzzGY kdOdTZ" > 0 @@ -398,7 +398,7 @@ </div> </div>, <p - className="sc-kGXeez gsczLr" + className="sc-kpOJdX bjUfnF" > You need at least diff --git a/web/cashtab/src/hooks/useBCH.js b/web/cashtab/src/hooks/useBCH.js --- a/web/cashtab/src/hooks/useBCH.js +++ b/web/cashtab/src/hooks/useBCH.js @@ -869,6 +869,7 @@ destinationAddress, sendAmount, feeInSatsPerByte, + optionalOpReturnMsg, ) => { try { if (!sendAmount) { @@ -941,6 +942,21 @@ REMAINDER_ADDR = wallet.Path1899.cashAddress; } + // Start of building the OP_RETURN output. + // only build the OP_RETURN output if the user supplied it + if ( + typeof optionalOpReturnMsg !== 'undefined' && + optionalOpReturnMsg !== '' + ) { + const script = [ + BCH.Script.opcodes.OP_RETURN, + Buffer.from(`${optionalOpReturnMsg}`), + ]; + const data = BCH.Script.encode(script); + transactionBuilder.addOutput(data, 0); + } + // End of building the OP_RETURN output. + // amount to send back to the remainder address. const remainder = originalAmount.minus(satoshisToSend).minus(txFee);