diff --git a/web/cashtab/src/assets/tabcash.png b/web/cashtab/src/assets/tabcash.png new file mode 100644 index 000000000..b00b35798 Binary files /dev/null and b/web/cashtab/src/assets/tabcash.png differ diff --git a/web/cashtab/src/components/App.js b/web/cashtab/src/components/App.js index 8b3a0cecf..73f131d4f 100644 --- a/web/cashtab/src/components/App.js +++ b/web/cashtab/src/components/App.js @@ -1,254 +1,280 @@ import React from 'react'; import 'antd/dist/antd.less'; import '../index.css'; import styled from 'styled-components'; import { Tabs } from 'antd'; import { FolderOpenFilled, CaretRightOutlined, SettingFilled, } from '@ant-design/icons'; import Wallet from '@components/Wallet/Wallet'; import Send from '@components/Send/Send'; import SendToken from '@components/Send/SendToken'; import Configure from '@components/Configure/Configure'; import NotFound from '@components/NotFound'; import CashTab from '@assets/cashtab.png'; +import TabCash from '@assets/tabcash.png'; import ABC from '@assets/bitcoinabclogo.png'; import './App.css'; import { WalletContext } from '@utils/context'; +import { checkForTokenById } from '@utils/tokenMethods.js'; import WalletLabel from '@components/Common/WalletLabel.js'; import { Route, Redirect, Switch, useLocation, useHistory, } from 'react-router-dom'; import fbt from 'fbt'; const { TabPane } = Tabs; const Footer = styled.div` background-color: #fff; border-radius: 20px; position: fixed; bottom: 0; width: 500px; @media (max-width: 768px) { width: 100%; } border-top: 1px solid #e2e2e2; .ant-tabs-nav-list { } .ant-tabs-top > .ant-tabs-nav::before, .ant-tabs-bottom > .ant-tabs-nav::before, .ant-tabs-top > div > .ant-tabs-nav::before, .ant-tabs-bottom > div > .ant-tabs-nav::before { border-bottom: none; } .ant-tabs-tab { padding: 24px 12px 12px 12px; margin: 0 24px; @media (max-width: 360px) { margin: 0 12px; } span { font-size: 12px; font-weight: bold; } .anticon { display: block; color: rgb(148, 148, 148); font-size: 24px; margin-left: 8px; margin-bottom: 3px; } } .ant-tabs-tab:hover { color: #ff8d00; .anticon { color: #ff8d00; } } .ant-tabs-tab-active > div > span { color: #ff8d00; } .ant-tabs-tab-active.ant-tabs-tab { color: #ff8d00; .anticon { color: #ff8d00; } } .ant-tabs-ink-bar { display: none !important; } .ant-tabs-nav { margin: -3.5px 0 0 0; } `; export const WalletBody = styled.div` display: flex; align-items: center; justify-content: center; width: 100%; min-height: 100vh; background: linear-gradient(270deg, #040c3c, #212c6e); `; export const WalletCtn = styled.div` position: relative; width: 500px; background-color: #fff; min-height: 100vh; padding: 10px 30px 120px 30px; background: #fff; -webkit-box-shadow: 0px 0px 24px 1px rgba(0, 0, 0, 1); -moz-box-shadow: 0px 0px 24px 1px rgba(0, 0, 0, 1); box-shadow: 0px 0px 24px 1px rgba(0, 0, 0, 1); @media (max-width: 768px) { width: 100%; -webkit-box-shadow: none; -moz-box-shadow: none; box-shadow: none; } `; export const HeaderCtn = styled.div` display: flex; align-items: center; justify-content: center; width: 100%; padding: 20px 0 30px; margin-bottom: 20px; justify-content: space-between; border-bottom: 1px solid #e2e2e2; a { color: #848484; :hover { color: #ff8d00; } } @media (max-width: 768px) { a { font-size: 12px; } padding: 10px 0 20px; } `; +export const EasterEgg = styled.img` + position: fixed; + bottom: -195px; + margin: 0; + right: 10%; + transition-property: bottom; + transition-duration: 1.5s; + transition-timing-function: ease-out; + + :hover { + bottom: 0; + } + + @media screen and (max-width: 1250px) { + display: none; + } +`; + export const CashTabLogo = styled.img` width: 120px; @media (max-width: 768px) { width: 110px; } `; export const AbcLogo = styled.img` width: 150px; @media (max-width: 768px) { width: 120px; } `; const App = () => { const ContextValue = React.useContext(WalletContext); - const { wallet } = ContextValue; + const { wallet, tokens } = ContextValue; + + const hasTab = checkForTokenById( + tokens, + '50d8292c6255cda7afc6c8566fed3cf42a2794e9619740fe8f4c95431271410e', + ); const location = useLocation(); const history = useHistory(); const selectedKey = location && location.pathname ? location.pathname.substr(1) : ''; return (
); }; export default App; diff --git a/web/cashtab/src/utils/__mocks__/mockTokenList.js b/web/cashtab/src/utils/__mocks__/mockTokenList.js new file mode 100644 index 000000000..a6f9b149f --- /dev/null +++ b/web/cashtab/src/utils/__mocks__/mockTokenList.js @@ -0,0 +1,382 @@ +export const mockTokens = [ + { + info: { + height: 661014, + tx_hash: + 'cca1d12cb240d1529d370b2cec40b2c0230586d0b53f1c48f6dac8dff2702672', + tx_pos: 2, + value: 546, + txid: + 'cca1d12cb240d1529d370b2cec40b2c0230586d0b53f1c48f6dac8dff2702672', + vout: 2, + utxoType: 'token', + transactionType: 'send', + tokenId: + '7443f7c831cdf2b2b04d5f0465ed0bcf348582675b0e4f17906438c232c22f3d', + tokenTicker: 'WDT', + tokenName: + 'Test Token With Exceptionally Long Name For CSS And Style Revisions', + tokenDocumentUrl: + 'https://www.ImpossiblyLongWebsiteDidYouThinkWebDevWouldBeFun.org', + tokenDocumentHash: + '����\\�IS\u001e9�����k+���\u0018���\u001b]�߷2��', + decimals: 7, + tokenType: 1, + tokenQty: '476587641.203853', + isValid: true, + address: 'bitcoincash:qpv9fx6mjdpgltygudnpw3tvmxdyzx7savhphtzswu', + }, + tokenId: + '7443f7c831cdf2b2b04d5f0465ed0bcf348582675b0e4f17906438c232c22f3d', + balance: '476587644.2038557', + hasBaton: false, + }, + { + info: { + height: 661700, + tx_hash: + '854d49d29819cdb5c4d9248146ffc82771cd3a7727f25a22993456f68050503e', + tx_pos: 1, + value: 546, + txid: + '854d49d29819cdb5c4d9248146ffc82771cd3a7727f25a22993456f68050503e', + vout: 1, + utxoType: 'token', + transactionType: 'send', + tokenId: + 'd4ffc597cb08b8c929e464f84069b9009649c7514860f673da48b1b3eba5b56e', + tokenTicker: 'JoeyTest2', + tokenName: 'Jt2', + tokenDocumentUrl: 'thecryptoguy.com', + tokenDocumentHash: '', + decimals: 0, + tokenType: 1, + tokenQty: '1', + isValid: true, + address: 'bitcoincash:qpv9fx6mjdpgltygudnpw3tvmxdyzx7savhphtzswu', + }, + tokenId: + 'd4ffc597cb08b8c929e464f84069b9009649c7514860f673da48b1b3eba5b56e', + balance: '1', + hasBaton: false, + }, + { + info: { + height: 661711, + tx_hash: + '28a83416798159c3c36fe1633a1c89639228f53b7b8e6552a573958efdef74b9', + tx_pos: 1, + value: 546, + txid: + '28a83416798159c3c36fe1633a1c89639228f53b7b8e6552a573958efdef74b9', + vout: 1, + utxoType: 'token', + transactionType: 'send', + tokenId: + 'dd84ca78db4d617221b58eabc6667af8fe2f7eadbfcc213d35be9f1b419beb8d', + tokenTicker: 'TAP', + tokenName: 'Thoughts and Prayers', + tokenDocumentUrl: '', + tokenDocumentHash: '', + decimals: 0, + tokenType: 1, + tokenQty: '1', + isValid: true, + address: 'bitcoincash:qpv9fx6mjdpgltygudnpw3tvmxdyzx7savhphtzswu', + }, + tokenId: + 'dd84ca78db4d617221b58eabc6667af8fe2f7eadbfcc213d35be9f1b419beb8d', + balance: '1', + hasBaton: false, + }, + { + info: { + height: 661711, + tx_hash: + 'd662e05b76bed604caf1ceb8fb9fd7ed39a5b831c35c7f2fb567c50ee95cff72', + tx_pos: 1, + value: 546, + txid: + 'd662e05b76bed604caf1ceb8fb9fd7ed39a5b831c35c7f2fb567c50ee95cff72', + vout: 1, + utxoType: 'token', + transactionType: 'send', + tokenId: + '645d9161e03ae27e5a3bb9cd256ee90341d320d13ac403229a9800b638cf4a83', + tokenTicker: 'ARCHON', + tokenName: 'Icon Worthiness', + tokenDocumentUrl: 'mint.bitcoin.com', + tokenDocumentHash: '', + decimals: 0, + tokenType: 1, + tokenQty: '1', + isValid: true, + address: 'bitcoincash:qpv9fx6mjdpgltygudnpw3tvmxdyzx7savhphtzswu', + }, + tokenId: + '645d9161e03ae27e5a3bb9cd256ee90341d320d13ac403229a9800b638cf4a83', + balance: '1', + hasBaton: false, + }, + { + info: { + height: 661789, + tx_hash: + '7e782389d203e5f213b6a02041929870c1c47c967a869bf8fae2aab1f8b72a84', + tx_pos: 1, + value: 546, + txid: + '7e782389d203e5f213b6a02041929870c1c47c967a869bf8fae2aab1f8b72a84', + vout: 1, + utxoType: 'token', + transactionType: 'send', + tokenId: + '8ead21ce4b3b9e7b57607b97b65b5013496dc6e3dfdea162c08ce7265a66ebc8', + tokenTicker: 'IFP', + tokenName: 'Infrastructure Funding Proposal Token', + tokenDocumentUrl: 'ifp.cash', + tokenDocumentHash: '�gA������3�$\n��1\u0005�A-lg\b�:�O�H��S', + decimals: 8, + tokenType: 1, + tokenQty: '1', + isValid: true, + address: 'bitcoincash:qpv9fx6mjdpgltygudnpw3tvmxdyzx7savhphtzswu', + }, + tokenId: + '8ead21ce4b3b9e7b57607b97b65b5013496dc6e3dfdea162c08ce7265a66ebc8', + balance: '1', + hasBaton: false, + }, + { + info: { + height: 666951, + tx_hash: + 'e5a3f4357f703e0874779fb66e7555f7ac7f8e86fa3fa005e4bfcfc1115a5afe', + tx_pos: 1, + value: 546, + txid: + 'e5a3f4357f703e0874779fb66e7555f7ac7f8e86fa3fa005e4bfcfc1115a5afe', + vout: 1, + utxoType: 'token', + transactionType: 'send', + tokenId: + 'eed8c50e278d02087c820f8fdc16bc0db034912b5c61d9bb315d1eaeec5d3c7b', + tokenTicker: 'CAMS', + tokenName: 'CAMS Token', + tokenDocumentUrl: 'https://onlycams.cc', + tokenDocumentHash: '', + decimals: 2, + tokenType: 1, + tokenQty: '0.12', + isValid: true, + address: 'bitcoincash:qpv9fx6mjdpgltygudnpw3tvmxdyzx7savhphtzswu', + }, + tokenId: + 'eed8c50e278d02087c820f8fdc16bc0db034912b5c61d9bb315d1eaeec5d3c7b', + balance: '0.12', + hasBaton: false, + }, + { + info: { + height: 666952, + tx_hash: + 'bd465ee1c47e697c2d952f58e03d9cade28492e7bc33490cb962a3c3fe31e77b', + tx_pos: 1, + value: 546, + txid: + 'bd465ee1c47e697c2d952f58e03d9cade28492e7bc33490cb962a3c3fe31e77b', + vout: 1, + utxoType: 'token', + transactionType: 'send', + tokenId: + '7f8889682d57369ed0e32336f8b7e0ffec625a35cca183f4e81fde4e71a538a1', + tokenTicker: 'HONK', + tokenName: 'HONK HONK', + tokenDocumentUrl: 'THE REAL HONK SLP TOKEN', + tokenDocumentHash: '', + decimals: 0, + tokenType: 1, + tokenQty: '7', + isValid: true, + address: 'bitcoincash:qpv9fx6mjdpgltygudnpw3tvmxdyzx7savhphtzswu', + }, + tokenId: + '7f8889682d57369ed0e32336f8b7e0ffec625a35cca183f4e81fde4e71a538a1', + balance: '11', + hasBaton: false, + }, + { + info: { + height: 667909, + tx_hash: + '5bb8f9831d616b3a859ffec4507f66bd5f2f3c057d7f5d5fa5c026216d6c2646', + tx_pos: 2, + value: 546, + txid: + '5bb8f9831d616b3a859ffec4507f66bd5f2f3c057d7f5d5fa5c026216d6c2646', + vout: 2, + utxoType: 'token', + transactionType: 'send', + tokenId: + 'bef614aac85c0c866f4d39e4d12a96851267d38d1bca5bdd6488bbd42e28b6b1', + tokenTicker: 'CTP', + tokenName: 'Cash Tab Points', + tokenDocumentUrl: 'https://cashtabapp.com/', + tokenDocumentHash: '', + decimals: 9, + tokenType: 1, + tokenQty: '1', + isValid: true, + address: 'bitcoincash:qpmytrdsakt0axrrlswvaj069nat3p9s7ct4lsf8k9', + }, + tokenId: + 'bef614aac85c0c866f4d39e4d12a96851267d38d1bca5bdd6488bbd42e28b6b1', + balance: '1', + hasBaton: false, + }, + { + info: { + height: 667909, + tx_hash: + 'd3183b663a8d67b2b558654896b95102bbe68d164de219da96273ae52de93813', + tx_pos: 2, + value: 546, + txid: + 'd3183b663a8d67b2b558654896b95102bbe68d164de219da96273ae52de93813', + vout: 2, + utxoType: 'token', + transactionType: 'send', + tokenId: + 'bd1acc4c986de57af8d6d2a64aecad8c30ee80f37ae9d066d758923732ddc9ba', + tokenTicker: 'TBS', + tokenName: 'TestBits', + tokenDocumentUrl: 'https://thecryptoguy.com/', + tokenDocumentHash: '', + decimals: 9, + tokenType: 1, + tokenQty: '4.004000001', + isValid: true, + address: 'bitcoincash:qpmytrdsakt0axrrlswvaj069nat3p9s7ct4lsf8k9', + }, + tokenId: + 'bd1acc4c986de57af8d6d2a64aecad8c30ee80f37ae9d066d758923732ddc9ba', + balance: '1000109.789698951', + hasBaton: false, + }, + { + info: { + height: 669057, + tx_hash: + 'dd560d87bd632e40c6548021006653a150197ede13fadb5eadfa29abe4400d0e', + tx_pos: 2, + value: 546, + txid: + 'dd560d87bd632e40c6548021006653a150197ede13fadb5eadfa29abe4400d0e', + vout: 2, + utxoType: 'token', + transactionType: 'send', + tokenId: + 'df808a41672a0a0ae6475b44f272a107bc9961b90f29dc918d71301f24fe92fb', + tokenTicker: 'NAKAMOTO', + tokenName: 'NAKAMOTO', + tokenDocumentUrl: '', + tokenDocumentHash: '', + decimals: 8, + tokenType: 1, + tokenQty: '4', + isValid: true, + address: 'bitcoincash:qpmytrdsakt0axrrlswvaj069nat3p9s7ct4lsf8k9', + }, + tokenId: + 'df808a41672a0a0ae6475b44f272a107bc9961b90f29dc918d71301f24fe92fb', + balance: '4', + hasBaton: false, + }, + { + info: { + height: 669673, + tx_hash: + 'bd8b527df1d5d3bd611a8f0ee8f14af83cb7d107fb2e140dbd2d9f4b3a86786a', + tx_pos: 1, + value: 546, + txid: + 'bd8b527df1d5d3bd611a8f0ee8f14af83cb7d107fb2e140dbd2d9f4b3a86786a', + vout: 1, + utxoType: 'token', + transactionType: 'send', + tokenId: + 'bfddfcfc9fb9a8d61ed74fa94b5e32ccc03305797eea461658303df5805578ef', + tokenTicker: 'Sending Token', + tokenName: 'Sending Token', + tokenDocumentUrl: 'developer.bitcoin.com', + tokenDocumentHash: '', + decimals: 9, + tokenType: 1, + tokenQty: '1e-9', + isValid: true, + address: 'bitcoincash:qpmytrdsakt0axrrlswvaj069nat3p9s7ct4lsf8k9', + }, + tokenId: + 'bfddfcfc9fb9a8d61ed74fa94b5e32ccc03305797eea461658303df5805578ef', + balance: '4e-9', + hasBaton: false, + }, + { + info: { + height: 671724, + tx_hash: + '37f63a9b1bcdc4733425dcfc3a7f3564d5095467ad7f64707fe52dbe5c1e1897', + tx_pos: 2, + value: 546, + txid: + '37f63a9b1bcdc4733425dcfc3a7f3564d5095467ad7f64707fe52dbe5c1e1897', + vout: 2, + utxoType: 'token', + transactionType: 'send', + tokenId: + 'acba1d7f354c6d4d001eb99d31de174e5cea8a31d692afd6e7eb8474ad541f55', + tokenTicker: 'CTB', + tokenName: 'CashTabBits', + tokenDocumentUrl: 'https://cashtabapp.com/', + tokenDocumentHash: '', + decimals: 9, + tokenType: 1, + tokenQty: '90.000000001', + isValid: true, + address: 'bitcoincash:qpmytrdsakt0axrrlswvaj069nat3p9s7ct4lsf8k9', + }, + tokenId: + 'acba1d7f354c6d4d001eb99d31de174e5cea8a31d692afd6e7eb8474ad541f55', + balance: '90.000000001', + hasBaton: false, + }, + { + info: { + height: 0, + tx_hash: + '618d0dd8c0c5fa5a34c6515c865dd72bb76f8311cd6ee9aef153bab20dabc0e6', + tx_pos: 1, + value: 546, + txid: + '618d0dd8c0c5fa5a34c6515c865dd72bb76f8311cd6ee9aef153bab20dabc0e6', + vout: 1, + utxoType: 'token', + transactionType: 'send', + tokenId: + '50d8292c6255cda7afc6c8566fed3cf42a2794e9619740fe8f4c95431271410e', + tokenTicker: 'TBC', + tokenName: 'tabcash', + tokenDocumentUrl: 'https://cashtabapp.com/', + tokenDocumentHash: '', + decimals: 0, + tokenType: 1, + tokenQty: '100', + isValid: true, + address: 'bitcoincash:qpmytrdsakt0axrrlswvaj069nat3p9s7ct4lsf8k9', + }, + tokenId: + '50d8292c6255cda7afc6c8566fed3cf42a2794e9619740fe8f4c95431271410e', + balance: '100', + hasBaton: false, + }, +]; diff --git a/web/cashtab/src/utils/__tests__/tokenMethods.test.js b/web/cashtab/src/utils/__tests__/tokenMethods.test.js new file mode 100644 index 000000000..bf0435fdc --- /dev/null +++ b/web/cashtab/src/utils/__tests__/tokenMethods.test.js @@ -0,0 +1,16 @@ +import { checkForTokenById } from '../tokenMethods'; +import { mockTokens } from '../__mocks__/mockTokenList'; + +describe('Correctly executes token parsing methods', () => { + it(`checkForTokenById returns 'false' if token ID is not found in wallet token list`, () => { + expect(checkForTokenById(mockTokens, 'not there')).toBe(false); + }); + it(`checkForTokenById returns 'true' if token ID is found in wallet token list`, () => { + expect( + checkForTokenById( + mockTokens, + '50d8292c6255cda7afc6c8566fed3cf42a2794e9619740fe8f4c95431271410e', + ), + ).toBe(true); + }); +}); diff --git a/web/cashtab/src/utils/tokenMethods.js b/web/cashtab/src/utils/tokenMethods.js new file mode 100644 index 000000000..279eac459 --- /dev/null +++ b/web/cashtab/src/utils/tokenMethods.js @@ -0,0 +1,8 @@ +export const checkForTokenById = (tokenList, specifiedTokenId) => { + for (const t of tokenList) { + if (t.tokenId === specifiedTokenId) { + return true; + } + } + return false; +};