├── .gitignore ├── README.md ├── babel.config.js ├── package.json ├── public ├── css │ ├── Gilroy-Bold.woff │ ├── Gilroy-Heavy.woff │ ├── Gilroy-Light.woff │ ├── Gilroy-Medium.woff │ ├── Gilroy-Regular.woff │ ├── mdb.min.css │ ├── style.css │ └── style.css.map ├── favicon.ico ├── img │ ├── Approve.svg │ ├── Delete.svg │ ├── Edit.svg │ ├── Spender.svg │ ├── Withdraw.svg │ ├── bg-bnb.jpg │ ├── bg-cricle.jpg │ ├── bnb.svg │ ├── close.svg │ ├── coin.svg │ ├── delete-warning.svg │ ├── dots.svg │ ├── error.svg │ ├── eth.svg │ ├── exclude.png │ ├── finish.svg │ ├── formatic.svg │ ├── info-card.svg │ ├── info-circle.svg │ ├── info.svg │ ├── install-meta.svg │ ├── logo.svg │ ├── observe.svg │ ├── plus.svg │ ├── portis.svg │ ├── question.svg │ ├── search.svg │ ├── spinner.svg │ ├── success.svg │ ├── unobserve.svg │ ├── unwatch.svg │ ├── view.svg │ ├── wallet-connect.svg │ ├── warning.svg │ └── watch.svg ├── index.html └── js │ └── mdb.min.js ├── src ├── App.vue ├── components │ ├── AccountList.vue │ ├── AlertModal.vue │ ├── ConfirmModal.vue │ ├── DepositModal.vue │ ├── InformationList.vue │ ├── InputModal.vue │ ├── Loader.vue │ ├── Modal.vue │ ├── NotificationList.vue │ ├── TpSlModal.vue │ └── TransactionConfig.vue ├── config.js ├── constants │ ├── CopyTradingSamples.js │ ├── abi.js │ └── events.js ├── helpers │ ├── ABI.js │ ├── API.js │ ├── CopyTrade.js │ ├── Crypto.js │ ├── Listener.js │ ├── Observer.js │ ├── Parse.js │ ├── Transaction.js │ ├── Utils.js │ └── Web3.js ├── main.js ├── router │ └── index.js ├── store │ ├── index.js │ └── modules │ │ ├── accounts.js │ │ ├── contracts.js │ │ ├── histories.js │ │ ├── information.js │ │ ├── positions.js │ │ ├── targets.js │ │ ├── transactions.js │ │ └── watches.js └── views │ ├── Contract │ ├── components │ │ ├── Details.vue │ │ ├── HistoryList.vue │ │ ├── PositionList.vue │ │ └── WarnModal.vue │ └── index.vue │ ├── CopyTrading │ ├── components │ │ ├── EditTriggerModal.vue │ │ ├── ExcludeModal.vue │ │ └── TargetList.vue │ └── index.vue │ ├── Home │ ├── components │ │ ├── ActiveList.vue │ │ └── WatchList.vue │ └── index.vue │ ├── Navbar │ └── index.vue │ └── Template.vue └── vue.config.js /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .env 3 | package-lock.json -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | **WARNING**: links that are related to community are closed and scammers are dealing with it. 2 | 3 | To run the sniper locally, see this [Wiki](https://github.com/anysniper/Frontend/wiki/Project-Setup) 4 | 5 | # AnySniper DApp 6 | 7 | This repository contains all the code to run AnySniper DApp which had 500 active users. All logic code is in this repository and you can add your custom DEX to src/config.js 8 | 9 | There are currently Uniswap, Pancakeswap, Sushiswap, Degenswap and some DEXs on Crono chains. 10 | 11 | The backend is intended to store user configurations such as contract scanner information, favorite contract addresses, and copy trading targets. 12 | 13 | The backend is using [Parse Server](https://parseplatform.org/) 14 | 15 | You can use a free backend service like Back4App, details about this can be found in [here](https://github.com/anysniper/Frontend/wiki/Project-Setup). 16 | 17 | There is a minor issue with copy trading and will be fixed soon. It basically calculates amountOut / amountIn. 18 | 19 | One or two files have multiple lines of code with almost all the logic for sniping, but you can optimize it and any PRs are welcome. 20 | 21 | I hope this will help the space for developing new projects at Defi and I'm sure this code will be nice to use as a template or boilerplate for new projects. 22 | 23 | ## Project setup 24 | ``` 25 | npm install 26 | ``` 27 | 28 | Open `src/config.js` and change the Parse urls into your backend's urls. 29 | 30 | You can create a free server on https://back4app.com. 31 | 32 | Create New App and then get the `applicationId` and `javascriptKey` in `App Settings / Security & Keys` 33 | 34 | The final configration would be looking like this 35 | 36 | ``` 37 | PARSE_APP_ID: 'R0qwhAQIbNmHctk030RjGGlYD9hSTuytv...', 38 | PARSE_URL: 'https://parseapi.back4app.com', 39 | PARSE_MASTER_KEY: '', 40 | PARSE_JS_KEY: '1MT3Ew8i1yQUX4SIvqbDiaggfszvtZ....', 41 | ``` 42 | 43 | You also need to change `MAINNET_RPC` which is used to fetch the token balance. Create a new project at [Infura](https://infura.io/) and get RPC url. 44 | 45 | ### Compiles and hot-reloads for development 46 | ``` 47 | npm run serve 48 | ``` 49 | 50 | ### Compiles and minifies for production 51 | ``` 52 | npm run build 53 | ``` 54 | 55 | ### Lints and fixes files 56 | ``` 57 | npm run lint 58 | ``` 59 | -------------------------------------------------------------------------------- /babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | presets: [ 3 | '@vue/cli-plugin-babel/preset' 4 | ] 5 | } 6 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "AnySniper", 3 | "version": "0.1.0", 4 | "private": true, 5 | "scripts": { 6 | "serve": "vue-cli-service serve", 7 | "build": "vue-cli-service build", 8 | "lint": "vue-cli-service lint" 9 | }, 10 | "dependencies": { 11 | "@fortawesome/fontawesome-svg-core": "^1.3.0", 12 | "@fortawesome/free-brands-svg-icons": "^5.15.4", 13 | "@fortawesome/free-regular-svg-icons": "^5.15.4", 14 | "@fortawesome/free-solid-svg-icons": "^5.15.4", 15 | "@fortawesome/vue-fontawesome": "^2.0.6", 16 | "@walletconnect/web3-provider": "^1.7.1", 17 | "axios": "^0.24.0", 18 | "core-js": "^3.6.5", 19 | "crypto-js": "^4.1.1", 20 | "epic-spinners": "^1.1.0", 21 | "ethers": "^5.5.1", 22 | "merkletreejs": "^0.2.24", 23 | "parse": "^3.4.0", 24 | "socket.io-client": "^4.4.0", 25 | "v-calendar": "^2.3.4", 26 | "v-click-outside": "^3.1.2", 27 | "v-emoji-picker": "^2.3.3", 28 | "vue": "^2.6.11", 29 | "vue-json-pretty": "^1.8.2", 30 | "vue-router": "^3.2.0", 31 | "vue-toastification": "^1.7.14", 32 | "vue-tour": "^2.0.0", 33 | "vuesax": "^4.0.1-alpha.25", 34 | "vuex": "^3.6.2", 35 | "web3": "^1.6.0", 36 | "web3modal": "^1.9.4" 37 | }, 38 | "devDependencies": { 39 | "@vue/cli-plugin-babel": "~4.5.0", 40 | "@vue/cli-plugin-eslint": "~4.5.0", 41 | "@vue/cli-plugin-router": "^4.5.15", 42 | "@vue/cli-service": "~4.5.0", 43 | "babel-eslint": "^10.1.0", 44 | "eslint": "^6.7.2", 45 | "eslint-plugin-vue": "^6.2.2", 46 | "vue-template-compiler": "^2.6.11" 47 | }, 48 | "eslintConfig": { 49 | "root": true, 50 | "env": { 51 | "node": true 52 | }, 53 | "extends": [ 54 | "plugin:vue/essential", 55 | "eslint:recommended" 56 | ], 57 | "parserOptions": { 58 | "parser": "babel-eslint" 59 | }, 60 | "rules": {} 61 | }, 62 | "browserslist": [ 63 | "> 1%", 64 | "last 2 versions", 65 | "not dead" 66 | ] 67 | } 68 | -------------------------------------------------------------------------------- /public/css/Gilroy-Bold.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/anysniper/Frontend/31453e68bb459e0bce381b02f0cd629ff7cb47c0/public/css/Gilroy-Bold.woff -------------------------------------------------------------------------------- /public/css/Gilroy-Heavy.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/anysniper/Frontend/31453e68bb459e0bce381b02f0cd629ff7cb47c0/public/css/Gilroy-Heavy.woff -------------------------------------------------------------------------------- /public/css/Gilroy-Light.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/anysniper/Frontend/31453e68bb459e0bce381b02f0cd629ff7cb47c0/public/css/Gilroy-Light.woff -------------------------------------------------------------------------------- /public/css/Gilroy-Medium.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/anysniper/Frontend/31453e68bb459e0bce381b02f0cd629ff7cb47c0/public/css/Gilroy-Medium.woff -------------------------------------------------------------------------------- /public/css/Gilroy-Regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/anysniper/Frontend/31453e68bb459e0bce381b02f0cd629ff7cb47c0/public/css/Gilroy-Regular.woff -------------------------------------------------------------------------------- /public/css/style.css.map: -------------------------------------------------------------------------------- 1 | { 2 | "version": 3, 3 | "mappings": "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", 4 | "sources": ["style.scss"], 5 | "names": [], 6 | "file": "style.css" 7 | } 8 | -------------------------------------------------------------------------------- /public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/anysniper/Frontend/31453e68bb459e0bce381b02f0cd629ff7cb47c0/public/favicon.ico -------------------------------------------------------------------------------- /public/img/Approve.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 6 | 7 | 11 | 13 | 15 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /public/img/Delete.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /public/img/Edit.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /public/img/Spender.svg: -------------------------------------------------------------------------------- 1 | n -------------------------------------------------------------------------------- /public/img/Withdraw.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /public/img/bg-bnb.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/anysniper/Frontend/31453e68bb459e0bce381b02f0cd629ff7cb47c0/public/img/bg-bnb.jpg -------------------------------------------------------------------------------- /public/img/bg-cricle.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/anysniper/Frontend/31453e68bb459e0bce381b02f0cd629ff7cb47c0/public/img/bg-cricle.jpg -------------------------------------------------------------------------------- /public/img/bnb.svg: -------------------------------------------------------------------------------- 1 | binance-coin-bnb -------------------------------------------------------------------------------- /public/img/close.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /public/img/delete-warning.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /public/img/dots.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /public/img/error.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /public/img/exclude.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/anysniper/Frontend/31453e68bb459e0bce381b02f0cd629ff7cb47c0/public/img/exclude.png -------------------------------------------------------------------------------- /public/img/finish.svg: -------------------------------------------------------------------------------- 1 | finish -------------------------------------------------------------------------------- /public/img/formatic.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /public/img/info-card.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /public/img/info-circle.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /public/img/info.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /public/img/install-meta.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /public/img/observe.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /public/img/plus.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /public/img/question.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 10 | 11 | 12 | 15 | 16 | -------------------------------------------------------------------------------- /public/img/search.svg: -------------------------------------------------------------------------------- 1 | b -------------------------------------------------------------------------------- /public/img/spinner.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | -------------------------------------------------------------------------------- /public/img/success.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /public/img/unobserve.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /public/img/unwatch.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 7 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | -------------------------------------------------------------------------------- /public/img/view.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 27 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /public/img/warning.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /public/img/watch.svg: -------------------------------------------------------------------------------- 1 | v -------------------------------------------------------------------------------- /public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 14 | 15 | 16 | Sniper 17 | 18 | 19 | 22 |
23 | 24 | 25 | 26 | 27 | 28 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /src/App.vue: -------------------------------------------------------------------------------- 1 | 96 | 97 | 220 | 221 | 222 | 295 | -------------------------------------------------------------------------------- /src/components/AlertModal.vue: -------------------------------------------------------------------------------- 1 | 31 | 32 | 86 | 87 | -------------------------------------------------------------------------------- /src/components/ConfirmModal.vue: -------------------------------------------------------------------------------- 1 | 34 | 35 | 96 | 97 | -------------------------------------------------------------------------------- /src/components/DepositModal.vue: -------------------------------------------------------------------------------- 1 | 55 | 56 | 101 | 102 | -------------------------------------------------------------------------------- /src/components/InformationList.vue: -------------------------------------------------------------------------------- 1 | 76 | 77 | 212 | 213 | -------------------------------------------------------------------------------- /src/components/InputModal.vue: -------------------------------------------------------------------------------- 1 | 35 | 36 | 93 | 94 | -------------------------------------------------------------------------------- /src/components/Loader.vue: -------------------------------------------------------------------------------- 1 | 54 | 55 | 65 | 66 | -------------------------------------------------------------------------------- /src/components/Modal.vue: -------------------------------------------------------------------------------- 1 | 21 | 22 | 35 | 36 | -------------------------------------------------------------------------------- /src/components/NotificationList.vue: -------------------------------------------------------------------------------- 1 | 38 | 39 | 125 | 126 | -------------------------------------------------------------------------------- /src/components/TpSlModal.vue: -------------------------------------------------------------------------------- 1 | 79 | 80 | 155 | 156 | -------------------------------------------------------------------------------- /src/config.js: -------------------------------------------------------------------------------- 1 | import ABI from '@/constants/abi'; 2 | 3 | const config = { 4 | API_BASE_URL: 'http://localhost:8001', // API not used 5 | 6 | // TODO: change backend's endpoints 7 | PARSE_APP_ID: 'standalone', 8 | PARSE_URL: 'http://localhost:9000/standalone', 9 | PARSE_LIVE_QUERY_URL: 'ws://localhost:1338', 10 | PARSE_MASTER_KEY: 'master', 11 | PARSE_JS_KEY: '', 12 | // User's default password 13 | PARSE_DEFAULT_PASSWORD: 'password', 14 | 15 | ADMIN: '0x0000', 16 | 17 | CHAIN_ID: 1, // 1: eth mainnet, 4: rinkeby, 1337: localhost, 5777: ganache, 56: BSC 18 | // CHAIN_NAME: 'Ethereum Mainnet', 19 | // RPC_URL: '', 20 | 21 | // Socket configrations 22 | NETWORK: 'main', // bsc-main, rinkeby, main 23 | 24 | SOCKET_DAPP_ID: 'e72e44c7-d688-4e0e-82a1-6ceb410b2992', 25 | 26 | // Threshold 27 | MIN_SNIPER_VALUE: 0, 28 | MIN_SNIPER_VALUE_FOR_COPY_TRADING: 0, 29 | MIN_DETAILS_SNIPER_AMOUNT: 0, 30 | 31 | SNIPER_ADDRESS: '0xb8fb35e3406e597e5f86d4f3c0e3063a6fab71a5', 32 | 33 | MAINNET_RPC: 'https://mainnet.infura.io/v3/', 34 | MAINNET_UNI_ROUTER_ADDRESS: '0x7a250d5630b4cf539739df2c5dacb4c659f2488d', 35 | MAINNET_WETH_ADDRESS: '0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2', 36 | 37 | // For V1 Escros contracts (not used) 38 | ETH_ESCROW_ADDRESS: '0x89d7c52b999DE0f2D862eD944203BFA0526AE973', // Main 39 | RINKEBY_ESCROW_ADDRESS: '0x3e4dEaB798b75FB19E3305cf2DDc83032940A24c', // Test 40 | BSC_ESCROW_ADDRESS: '0xf965f1995A6CC011524F8762d811F64f1045777E', // BSC 41 | 42 | // For V1 Router contracts (not used) 43 | ETH_ROUTER_ADDRESS: '0xf05dab17B820063Ca143303641adD237C3cA9d32', 44 | RINKEBY_ROUTER_ADDRESS: '0xAAa83841d5a6Ea44E90Cd534d2e470005e4633c3', 45 | BSC_ROUTER_ADDRESS: '0x9d1a0E3492F16Ad58E744071e41483495537e488', 46 | 47 | // For Aggregator 48 | ETH_AGGREGATOR_ADDRESS: '0x0Ff5F706A99BE785B35dF6788ED698290ab56ac0', // Main 49 | RINKEBY_AGGREGATOR_ADDRESS: '0xf2Ca019454C5e0dcdcBD8e3539CcfCF00850e148', // Test 50 | BSC_AGGREGATOR_ADDRESS: '0x328c0Ac24544fbF031080E470A7037d66F57013b', // BSC 51 | CRO_AGGREGATOR_ADDRESS: '', // CRO 52 | 53 | // V2 Router 54 | ETH_ROUTER_V2_ADDRESS: '0xd82E803289b22DAa6EAE106764AF92C88de7bc78', 55 | RINKEBY_ROUTER_V2_ADDRESS: '0x39a70EDaC9413F4A71ea9c682b2c62095b165A7b', 56 | BSC_ROUTER_V2_ADDRESS: '0xa7c94265eeC99B43C17BAC5Cd04d24641F73c934', 57 | CRO_ROUTER_V2_ADDRESS: '', 58 | 59 | ETH_WETH_ADDRESS: '0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2', 60 | RINKEBY_WETH_ADDRESS: '0xc778417e063141139fce010982780140aa0cd5ab', 61 | BSC_WETH_ADDRESS: '0xbb4CdB9CBd36B01bD1cBaEBF2De08d9173bc095c', 62 | CRO_WETH_ADDRESS: '0x5C7F8A570d578ED84E63fdFA7b1eE72dEae1AE23', 63 | 64 | ETH_DEX_LIST: [ 65 | { 66 | title: 'UniSwapV2', 67 | address: '0x5C69bEe701ef814a2B6a3EDD4B1652CB9cc5aA6f', // factory 68 | router: '0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D', 69 | abi: ABI.UniswapRouterABI 70 | }, 71 | { 72 | title: 'UniSwapV3', 73 | address: '0x5C69bEe701ef814a2B6a3EDD4B1652CB9cc5aA6f', 74 | router: '0x68b3465833fb72A70ecDF485E0e4C7bD8665Fc45', 75 | isCopyTrading: true, 76 | }, 77 | { 78 | title: 'SushiSwap', 79 | address: '0xC0AEe478e3658e2610c5F7A4A2E1777cE9e4f2Ac', 80 | router: '0xd9e1ce17f2641f24ae83637ab66a2cca9c378b9f', 81 | abi: ABI.UniswapRouterABI 82 | }, 83 | { 84 | title: 'DegenSwap', 85 | address: '0x5c515455efb90308689579993c11a84fc41229c0', 86 | router: '0x4bf3E2287D4CeD7796bFaB364C0401DFcE4a4f7F', 87 | isDirect: true, // indicates if can't buy through our router 88 | abi: ABI.UniswapRouterABI 89 | } 90 | ], 91 | CRO_DEX_LIST: [ 92 | { 93 | title: 'MMF Swap', 94 | address: '0xd590cc180601aecd6eeadd9b7f2b7611519544f4', 95 | router: '0x145677fc4d9b8f19b5d56d1820c48e0443049a30', 96 | isDirect: true // indicates if can't buy through our router 97 | } 98 | ], 99 | RINKEBY_DEX_LIST: [ 100 | { 101 | title: 'Uniswap', 102 | address: '0x5C69bEe701ef814a2B6a3EDD4B1652CB9cc5aA6f', 103 | router: '0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D', 104 | abi: ABI.UniswapRouterABI 105 | }, 106 | { 107 | title: 'UniSwapV3', 108 | address: '0x5C69bEe701ef814a2B6a3EDD4B1652CB9cc5aA6f', 109 | router: '0x68b3465833fb72A70ecDF485E0e4C7bD8665Fc45', 110 | isCopyTrading: true, 111 | }, 112 | ], 113 | BSC_DEX_LIST: [ 114 | { 115 | title: 'PancakeSwap', 116 | address: '0xcA143Ce32Fe78f1f7019d7d551a6402fC5350c73', 117 | router: '0x10ED43C718714eb63d5aA57B78B54704E256024E' 118 | } 119 | ], 120 | 121 | IS_TEST: false, 122 | 123 | load() { 124 | try { 125 | const localConfig = JSON.parse(localStorage.getItem(`backend_configs`)); 126 | this.PARSE_APP_ID = localConfig.APP_ID; 127 | this.PARSE_URL = localConfig.URL; 128 | this.PARSE_MASTER_KEY = localConfig.MASTER_KEY; 129 | this.PARSE_JS_KEY = localConfig.JS_KEY; 130 | // eslint-disable-next-line no-empty 131 | } catch (e) {} 132 | }, 133 | 134 | save() { 135 | try { 136 | const config = { 137 | APP_ID: this.PARSE_APP_ID, 138 | URL: this.PARSE_URL, 139 | MASTER_KEY: this.PARSE_MASTER_KEY, 140 | JS_KEY: this.PARSE_JS_KEY 141 | } 142 | localStorage.setItem('backend_configs', JSON.stringify(config)); 143 | // eslint-disable-next-line no-empty 144 | } catch (e) {} 145 | } 146 | } 147 | 148 | config.load(); 149 | 150 | export default config; -------------------------------------------------------------------------------- /src/constants/events.js: -------------------------------------------------------------------------------- 1 | export const E_ACCOUNT_CHANGED = 'e_account_changed'; 2 | export const E_CHAIN_CHANGED = 'e_chain_changed'; 3 | 4 | export const E_LOGIN = 'e_login'; 5 | 6 | export const C_NEW_TX = 'c_new_tx'; 7 | 8 | export const C_TEST_FAILED = 'c_test_failed'; 9 | export const C_TEST_FINISHED = 'c_test_finished'; 10 | export const C_TEST_SUCCESS = 'c_test_success'; 11 | 12 | export const E_REJECT_SIGN = 'e_reject_sign'; 13 | 14 | export const E_NEW_BLOCK = 'e_new_block'; 15 | 16 | export const E_NEW_ORDER = 'e_new_order'; -------------------------------------------------------------------------------- /src/helpers/ABI.js: -------------------------------------------------------------------------------- 1 | import Web3 from './Web3'; 2 | 3 | class ABI { 4 | constructor() { 5 | } 6 | 7 | getAbi(address) { 8 | for (let dex of Web3.getDexList()) { 9 | if (dex.address.toLowerCase() == address.toLowerCase()) { 10 | if (dex.abi) { 11 | return dex.abi; 12 | } 13 | } 14 | } 15 | return null; 16 | } 17 | } 18 | 19 | const helper = new ABI(); 20 | export default helper; -------------------------------------------------------------------------------- /src/helpers/API.js: -------------------------------------------------------------------------------- 1 | import axios from 'axios'; 2 | import config from '../config'; 3 | 4 | class APIHelper { 5 | 6 | constructor() { 7 | } 8 | 9 | config() { 10 | return this.call('GET', 'config'); 11 | } 12 | 13 | cancel(accounts) { 14 | return this.call('POST', 'cancel', { 15 | accounts 16 | }); 17 | } 18 | 19 | // accounts: array of publick key to be used 20 | // if history is null, then use normal gas 21 | // if gasGwei is 0, then use normal gas 22 | // max supply is max wallet percent of total supply 23 | buy(accounts, history, contract, gasGwei, gasMultiplier, amount, maxSupply) { 24 | return this.call('POST', 'buy', { 25 | accounts, 26 | history, 27 | contract, 28 | gasGwei, 29 | gasMultiplier, 30 | amount, 31 | maxSupply 32 | }); 33 | } 34 | 35 | // accounts: array of publick key to be used 36 | // if history is null, then use normal gas 37 | // if gasGwei is 0, then use normal gas 38 | // max supply is max wallet percent of total supply 39 | sell(accounts, history, contract, gasGwei, gasMultiplier, percent) { 40 | return this.call('POST', 'sell', { 41 | accounts, 42 | history, 43 | contract, 44 | gasGwei, 45 | gasMultiplier, 46 | percent 47 | }); 48 | } 49 | 50 | call(method, endpoint, params) { 51 | let url = config.API_BASE_URL + '/' + endpoint; 52 | 53 | let args = {}; 54 | 55 | if (method == 'POST') { 56 | args = { 57 | method: 'post', 58 | url, 59 | data: params, 60 | headers: { 'Content-Type': 'application/json' } 61 | } 62 | } else { 63 | url += '?' + (new URLSearchParams(params)).toString() 64 | args = { 65 | method: 'get', 66 | url, 67 | headers: { 'Content-Type': 'application/json' } 68 | } 69 | } 70 | return axios(args).then(response => { 71 | return response.data; 72 | }); 73 | } 74 | } 75 | 76 | const helper = new APIHelper(); 77 | export default helper; -------------------------------------------------------------------------------- /src/helpers/CopyTrade.js: -------------------------------------------------------------------------------- 1 | import Web3 from 'web3'; 2 | class CopyTrade { 3 | constructor() { 4 | this.boughtTokens = []; 5 | this.buyProcessed = []; 6 | this.soldTokens = []; 7 | this.sellProcessed = []; 8 | this.processed = []; 9 | } 10 | 11 | setProcessed(tx, status) { 12 | this.processed.push(tx.toLowerCase() + '-' + status.toLowerCase()); 13 | } 14 | 15 | hasProcessed(tx, status) { 16 | return this.processed.includes(tx.toLowerCase() + '-' + status.toLowerCase()); 17 | } 18 | 19 | setBought(token) { 20 | this.boughtTokens.push(token.toLowerCase()); 21 | } 22 | 23 | hasBought(token) { 24 | return this.boughtTokens.includes(token.toLowerCase()); 25 | } 26 | 27 | setSold(token) { 28 | this.soldTokens.push(token.toLowerCase()); 29 | } 30 | 31 | hasSold(token) { 32 | return this.soldTokens.includes(token.toLowerCase()); 33 | } 34 | 35 | setBuyProcessed(token) { 36 | this.buyProcessed.push(token.toLowerCase()); 37 | } 38 | 39 | hasBuyProcessed(token) { 40 | return this.buyProcessed.includes(token.toLowerCase()); 41 | } 42 | 43 | setSellProcessed(token) { 44 | this.sellProcessed.push(token.toLowerCase()); 45 | } 46 | 47 | hasSellProcessed(token) { 48 | return this.sellProcessed.includes(token.toLowerCase()); 49 | } 50 | 51 | pad(num, size) { 52 | // eslint-disable-next-line no-undef 53 | num = BigInt(num).toString(16); 54 | while (num.length < size) num = "0" + num; 55 | return num; 56 | } 57 | 58 | fill(str, size) { 59 | while (str.length < size) str = str + "0"; 60 | return str; 61 | } 62 | 63 | getInput({input, selector, args, abi, index}) { 64 | const web3 = new Web3(); 65 | const params = []; 66 | let value = 0; 67 | 68 | for (let i = 0; i <= 5; i++) { 69 | for (let key in index) { 70 | if (index[key] === i && key != 'isExact') { 71 | if (i == 0) { 72 | value = args[key]; 73 | } else { 74 | params.push(args[key]); 75 | } 76 | break; 77 | } 78 | } 79 | } 80 | const inputParams = web3.eth.abi.encodeParameters(abi, params); 81 | let finalInput = selector + inputParams.substr(2); 82 | 83 | if (index.deadline == -1) { 84 | let newInput = input.substr(0, 10) + this.pad(args['deadline'], 64) + input.substring(74, input.indexOf(selector.substr(2))); 85 | newInput += finalInput.substr(2, input.length - newInput.length); 86 | 87 | finalInput = newInput; 88 | finalInput = this.fill(finalInput, input.length); 89 | } 90 | return { 91 | value, 92 | input: finalInput 93 | }; 94 | } 95 | } 96 | 97 | const helper = new CopyTrade(); 98 | export default helper; -------------------------------------------------------------------------------- /src/helpers/Crypto.js: -------------------------------------------------------------------------------- 1 | const CryptoJS = require('crypto-js'); 2 | 3 | class Crypto { 4 | encrypt(text, password) { 5 | return CryptoJS.AES.encrypt(text, password).toString(); 6 | } 7 | 8 | decrypt(encrypted, password) { 9 | const bytes = CryptoJS.AES.decrypt(encrypted, password); 10 | const originalText = bytes.toString(CryptoJS.enc.Utf8); 11 | return originalText; 12 | } 13 | } 14 | 15 | export default new Crypto(); -------------------------------------------------------------------------------- /src/helpers/Listener.js: -------------------------------------------------------------------------------- 1 | import Config from '../config'; 2 | import Observer from "./Observer"; 3 | import Parse from './Parse'; 4 | import Web3 from './Web3'; 5 | 6 | import {C_NEW_TX} from "../constants/events"; 7 | 8 | function uuidv4() { 9 | return 'Cn-xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xyn]/g, function(c) { 10 | if (c=='n') { 11 | return Math.random() * 9 | 0; 12 | } 13 | var r = Math.random() * 16 | 1, v = c == 'x' ? r : (r & 0x3 | 0x8); 14 | return v.toString(16); 15 | }); 16 | } 17 | 18 | class Socket { 19 | constructor() { 20 | this.webSocket = null; 21 | this.socketClosed = true; 22 | this.firstMessageArrived = false; 23 | this.callback = null; 24 | } 25 | 26 | setCallback(callback) { 27 | this.callback = callback; 28 | } 29 | 30 | init(config, abi) { 31 | if (this.close()) { 32 | // if not closed, then callback handler will call this func again 33 | // return; 34 | } 35 | this.firstMessageArrived = false; 36 | this.webSocket = new WebSocket("wss://api.blocknative.com/v0"); 37 | this.socketClosed = false; 38 | 39 | this.webSocket.onmessage = (event) => { 40 | if (!this.firstMessageArrived) { 41 | // Communicating for protocol init 42 | this.firstMessageArrived = true; 43 | let condition = { 44 | "appName": 'Onboard', 45 | "appVersion": '1.34.1', 46 | "blockchain": { 47 | "system": "ethereum", 48 | "network": Web3.getNetwork().network 49 | }, 50 | "categoryCode": "configs", 51 | "config": { 52 | // "scope": router, 53 | // "filters": filters, 54 | "watchAddress": true, 55 | ...config 56 | }, 57 | "dappId": Config.SOCKET_DAPP_ID, 58 | "eventCode": "put", 59 | "timeStamp": new Date().toISOString(), 60 | "version": '3.5.0', 61 | } 62 | if (abi) { 63 | condition['config']['abi'] = abi; 64 | } 65 | setTimeout(() => { 66 | this.webSocket.send(JSON.stringify(condition)); 67 | }, 1000); 68 | return; 69 | } 70 | 71 | let data = JSON.parse(event.data); 72 | 73 | if (!data.event || !data.event.transaction) { 74 | return; 75 | } 76 | 77 | data = data.event; 78 | 79 | // if ( data.transaction.status != 'txStuck' || data.transaction.status != 'stuck') { 80 | // data.transaction.status = 'pending'; 81 | // } 82 | 83 | if ( 84 | data.transaction.status != 'pending' 85 | && data.transaction.status != 'confirmed' 86 | && data.transaction.status != 'failed' 87 | ) { 88 | return; 89 | } 90 | 91 | this.callback(data); 92 | } 93 | 94 | this.webSocket.onclose = () => { 95 | console.log('The connection has been closed and reconnecting'); 96 | this.socketClosed = true; 97 | this.init(); 98 | }; 99 | 100 | this.webSocket.onerror = () => { 101 | console.log('The connection faced an error and reconnecting'); 102 | this.init(); 103 | } 104 | 105 | this.webSocket.onopen = () => { 106 | this.webSocket.send(JSON.stringify({ 107 | "appName": 'Onboard', 108 | "appVersion": '3.5.0', 109 | "blockchain": { 110 | "system": "ethereum", 111 | "network": Web3.getNetwork().network 112 | }, 113 | "categoryCode": "initialize", 114 | "connectionId": uuidv4(), 115 | "dappId": Config.SOCKET_DAPP_ID, 116 | "eventCode": "checkDappId", 117 | "timeStamp": new Date().toISOString(), 118 | "version": '3.5.0', 119 | })); 120 | }; 121 | } 122 | 123 | close() { 124 | if (this.webSocket) { 125 | this.webSocket.onclose = () => {}; 126 | this.webSocket.close(); 127 | this.webSocket = null; 128 | return true; 129 | } 130 | return false; 131 | } 132 | } 133 | 134 | class Listener { 135 | constructor() { 136 | this.contract = null; 137 | this.owner = null; 138 | this.abi = null; 139 | this.isListening = false; 140 | this.sockets = []; 141 | } 142 | 143 | stop() { 144 | if (this.sockets.length > 0) { 145 | for (let socket of this.sockets) { 146 | socket.close(); 147 | } 148 | this.sockets = []; 149 | } 150 | this.isListening = false; 151 | } 152 | 153 | async listenTargets(addresses, contracts) { 154 | this.stop(); 155 | this.isListening = true; 156 | this.sockets = addresses.map((address) => { 157 | const socket = new Socket(); 158 | const config = { 159 | "scope": address, 160 | "filters": [ 161 | // { 162 | // "_join": "OR", 163 | // "terms": addresses.map((address) => { 164 | // return { 165 | // 'from': address 166 | // } 167 | // }) 168 | // }, 169 | { 170 | "_join": "OR", 171 | "terms": contracts.map((contract) => { 172 | return { 173 | 'to': contract 174 | } 175 | }) 176 | } 177 | ], 178 | // "watchAddress": true 179 | } 180 | socket.setCallback(async (data) => { 181 | const History = Parse.getClass('History'); 182 | const history = new History(); 183 | history.set('data', data); 184 | history.set('owner', data.transaction.from); 185 | history.set('status', data.transaction.status); 186 | history.set('hash', data.transaction.hash); 187 | history.set('contract', this.contract); 188 | // await history.save(); 189 | Observer.$emit(C_NEW_TX, history) 190 | }); 191 | socket.init(config); 192 | return socket; 193 | }) 194 | } 195 | 196 | async listen(address, owner) { 197 | this.stop(); 198 | this.sockets = [ 199 | new Socket() 200 | ]; 201 | this.isListening = true; 202 | 203 | // abi can be null 204 | this.contract = address; 205 | this.owner = owner; 206 | 207 | const config = { 208 | "scope": this.owner, 209 | "filters": [ 210 | { 211 | "_join": "OR", 212 | "terms": [ 213 | { 214 | "from": this.owner 215 | }, 216 | { 217 | "to": this.contract 218 | } 219 | ] 220 | } 221 | ], 222 | "watchAddress": true 223 | } 224 | this.sockets[0].setCallback(async (data) => { 225 | const History = Parse.getClass('History'); 226 | const history = new History(); 227 | history.set('data', data); 228 | history.set('owner', this.owner); 229 | history.set('status', data.transaction.status); 230 | history.set('hash', data.transaction.hash); 231 | history.set('contract', this.contract); 232 | // await history.save(); 233 | Observer.$emit(C_NEW_TX, history) 234 | }); 235 | this.sockets[0].init(config); 236 | } 237 | 238 | } 239 | 240 | export default new Listener(); -------------------------------------------------------------------------------- /src/helpers/Observer.js: -------------------------------------------------------------------------------- 1 | import Vue from "vue"; 2 | 3 | const observer = new Vue(); 4 | 5 | export default observer; -------------------------------------------------------------------------------- /src/helpers/Parse.js: -------------------------------------------------------------------------------- 1 | const parse = require('parse'); 2 | import config from '../config'; 3 | export class ParseHelper { 4 | constructor() { 5 | this._initilized = false; 6 | } 7 | 8 | get client() { 9 | return parse; 10 | } 11 | 12 | instance() { 13 | return parse; 14 | } 15 | 16 | getClass(className) { 17 | return parse.Object.extend(className); 18 | } 19 | 20 | getUserClass() { 21 | return parse.User; 22 | } 23 | 24 | getAccountQuery() { 25 | return this.getQuery('Account'); 26 | } 27 | 28 | getTargetQuery() { 29 | return this.getQuery('Target'); 30 | } 31 | 32 | getContractQuery() { 33 | return this.getQuery('Contract'); 34 | } 35 | 36 | getHistoryQuery() { 37 | return this.getQuery('History'); 38 | } 39 | 40 | getQuery(className) { 41 | return new parse.Query(className); 42 | } 43 | 44 | destroy() { 45 | return Promise.all([ 46 | ]); 47 | } 48 | 49 | init(isRefresh) { 50 | if (!this._initilized || isRefresh) { 51 | parse.initialize(config.PARSE_APP_ID, config.PARSE_JS_KEY); 52 | parse.masterKey = config.PARSE_MASTER_KEY; 53 | parse.serverURL = config.PARSE_URL; 54 | } 55 | 56 | this.destroy().then(() => { 57 | this._initilized = true; 58 | }) 59 | } 60 | 61 | getLiveQueryClient() { 62 | return new parse.LiveQueryClient({ 63 | applicationId: config.PARSE_APP_ID, 64 | serverURL: config.PARSE_LIVE_QUERY_URL, 65 | javascriptKey: config.PARSE_JS_KEY 66 | }); 67 | } 68 | 69 | callCloud(func, params) { 70 | return parse.Cloud.run(func, params) 71 | } 72 | 73 | getHistories(contract, skip = 0, limit = 100) { 74 | const query = this.getHistoryQuery(); 75 | query.equalTo('contract', contract); 76 | query.descending("createdAt"); 77 | query.skip(skip); 78 | query.limit(limit); 79 | return query.find(); 80 | } 81 | } 82 | 83 | const instance = new ParseHelper(); 84 | // instance.init(); 85 | export default instance; 86 | -------------------------------------------------------------------------------- /src/helpers/Transaction.js: -------------------------------------------------------------------------------- 1 | import Web3 from 'web3'; 2 | import Web3Helper from './Web3'; 3 | import axios from 'axios'; 4 | import ABIHelper from './ABI'; 5 | import ABI from '../constants/abi'; 6 | 7 | class Transaction { 8 | constructor() { 9 | this.abis = {}; 10 | this.isLoading = {}; 11 | this.details = {}; 12 | } 13 | 14 | async getAbiFromSelector(selector) { 15 | if (this.isLoading[selector]) { 16 | return null; 17 | } 18 | this.isLoading[selector] = true; 19 | return axios.get( 20 | `https://www.4byte.directory/api/v1/signatures/?hex_signature=${selector}`, 21 | { 22 | headers: { 23 | 'Content-Type': 'application/json' 24 | } 25 | } 26 | ) 27 | .then(async response => { 28 | const results = response.data.results; 29 | if (results.length > 0) { 30 | const result = results[0]; 31 | const text = result.text_signature; 32 | const name = text.split('(')[0]; 33 | const args = text.split('(')[1].split(')')[0].split(','); 34 | const abi = { 35 | "inputs": [], 36 | "name": name, 37 | "type": "function" 38 | } 39 | args.map((arg) => { 40 | if (arg != '') { 41 | abi.inputs.push({ 42 | "name": arg, 43 | "type": arg 44 | }); 45 | } 46 | }); 47 | this.abis[selector] = abi; 48 | return abi; 49 | } 50 | return null; 51 | }); 52 | } 53 | 54 | getFunctionSelector(abiItem) { 55 | const args = abiItem.inputs.map(input => { 56 | return input.type 57 | }).join(','); 58 | const func = `${abiItem.name}(${args})`; 59 | const web3 = new Web3(); 60 | return web3.eth.abi.encodeFunctionSignature(func); 61 | } 62 | 63 | parseFunctionArgs(abiItem, input) { 64 | const web3 = new Web3(); 65 | const argInput = input.substring(10); 66 | const argTypes = abiItem.inputs.map(item => item.type); 67 | const argNames = abiItem.inputs.map(item => item.name); 68 | const parameters = web3.eth.abi.decodeParameters( 69 | argTypes, 70 | argInput 71 | ); 72 | const result = {}; 73 | for (let i = 0; i < argTypes.length; i++) { 74 | result[argNames[i]] = parameters[i]; 75 | } 76 | return result; 77 | } 78 | 79 | isWarn(history, accounts, details, warns) { 80 | if (details && details.method && details.method.indexOf('removeLiquidity') != -1) { 81 | return true; 82 | } 83 | 84 | if (details && details.selector && warns && warns.includes(details.selector)) { 85 | return true; 86 | } 87 | 88 | const transaction = history.get('data').transaction; 89 | const input = transaction.input.toLowerCase(); 90 | for (let account of accounts) { 91 | if ( 92 | input.indexOf(account.get('address').substring(2).toLowerCase()) != -1 93 | && transaction.from.toLowerCase() != account.get('address').toLowerCase() 94 | ) { 95 | return true; 96 | } 97 | } 98 | return false; 99 | } 100 | 101 | getDetails(contract, history, isRaw) { 102 | const data = history.get('data'); 103 | const transaction = data.transaction; 104 | const hash = transaction.hash; 105 | 106 | const id = `${hash}`; 107 | 108 | let abi; 109 | if (contract) { 110 | abi = Web3Helper.getAbi(contract.get('address')); 111 | } else { 112 | abi = ABIHelper.getAbi(transaction.to); 113 | } 114 | 115 | let details = { 116 | hash, 117 | status: transaction.status, 118 | value: (parseInt(transaction.value) / (10 ** 18)).toFixed(3) 119 | }; 120 | 121 | const txSelector = transaction.input.substring(0, 10); 122 | 123 | if (data.contractCall) { 124 | this.details[id] = { 125 | ...details, 126 | method: data.contractCall.methodName, 127 | selector: txSelector, 128 | params: data.contractCall.params 129 | }; 130 | } else { 131 | let method, params; 132 | 133 | if (!isRaw) { 134 | let isFound = false; 135 | if (abi && Array.isArray(abi)) { 136 | for (let item of abi) { 137 | if (item.type == 'function') { 138 | const selector = this.getFunctionSelector(item); 139 | if (txSelector == selector) { 140 | method = item.name; 141 | params = this.parseFunctionArgs(item, transaction.input); 142 | isFound = true; 143 | break; 144 | } 145 | } 146 | } 147 | } 148 | if (!isFound) { 149 | 150 | if (this.abis[txSelector]) { 151 | method = this.abis[txSelector].name; 152 | params = this.parseFunctionArgs(this.abis[txSelector], transaction.input); 153 | } else { 154 | this.getAbiFromSelector(txSelector); 155 | } 156 | } 157 | } 158 | this.details[id] = { 159 | ...details, 160 | input: transaction.input, 161 | method, 162 | selector: txSelector, 163 | params 164 | } 165 | } 166 | return this.details[id]; 167 | } 168 | 169 | parseTransaction(transaction) { 170 | let input = transaction.input; 171 | if (input.substring(0, 10) == '0x5ae401dc') { 172 | // this is multicall proxy 173 | input = '0x' + input.substr(330) + '00000000'; 174 | } 175 | console.log(input) 176 | const web3 = new Web3(); 177 | for (let abi of ABI.TradingABI) { 178 | // console.log(input.substring(0, 10)); 179 | if (input.substring(0, 10) == abi.selector) { 180 | const params = web3.eth.abi.decodeParameters(abi.inputs, '0x' + input.substr(10)); 181 | return { 182 | params, 183 | abi 184 | }; 185 | } 186 | } 187 | return null; 188 | } 189 | } 190 | export default new Transaction(); -------------------------------------------------------------------------------- /src/helpers/Utils.js: -------------------------------------------------------------------------------- 1 | class Utils { 2 | formatAddress(string, size) { 3 | if (!string) { 4 | return string; 5 | } 6 | size = size || 4; 7 | if (string.length < size * 2 + 3) { 8 | return string; 9 | } 10 | return string.substring(0, size) + '...' + string.substr(-size); 11 | } 12 | sleep(seconds) { 13 | return new Promise((resolve) => { 14 | setTimeout(() => { 15 | resolve() 16 | }, seconds * 1000); 17 | }); 18 | } 19 | formatBigInt(int) { 20 | // eslint-disable-next-line no-undef 21 | return '0x' + BigInt(int).toString(16); 22 | } 23 | loadScript(script) { 24 | const jQuery = window.jQuery; 25 | return new Promise((resolve) => { 26 | jQuery.getScript(script).done(() => { 27 | resolve(); 28 | }); 29 | }) 30 | } 31 | formatBalance(balance, decimals) { 32 | if (!decimals) { 33 | decimals = 18; 34 | } 35 | // eslint-disable-next-line no-undef 36 | return parseInt(BigInt(balance * 10000) / BigInt(10 ** decimals)) / 10000; 37 | } 38 | copyToClipboard(text) { 39 | /* Copy the text inside the text field */ 40 | navigator.clipboard.writeText(text); 41 | } 42 | convertToCSV(objArray) { 43 | var array = typeof objArray != 'object' ? JSON.parse(objArray) : objArray; 44 | var str = ''; 45 | 46 | for (var i = 0; i < array.length; i++) { 47 | var line = ''; 48 | for (var index in array[i]) { 49 | if (line != '') line += ',' 50 | 51 | line += array[i][index]; 52 | } 53 | 54 | str += line + '\r\n'; 55 | } 56 | 57 | return str; 58 | } 59 | exportCSVFile(headers, items, fileTitle) { 60 | if (headers) { 61 | items.unshift(headers); 62 | } 63 | 64 | // Convert Object to JSON 65 | var jsonObject = JSON.stringify(items); 66 | 67 | var csv = this.convertToCSV(jsonObject); 68 | 69 | var exportedFilenmae = fileTitle + '.csv' || 'export.csv'; 70 | 71 | var blob = new Blob([csv], { type: 'text/csv;charset=utf-8;' }); 72 | if (navigator.msSaveBlob) { // IE 10+ 73 | navigator.msSaveBlob(blob, exportedFilenmae); 74 | } else { 75 | var link = document.createElement("a"); 76 | if (link.download !== undefined) { // feature detection 77 | // Browsers that support HTML5 download attribute 78 | var url = URL.createObjectURL(blob); 79 | link.setAttribute("href", url); 80 | link.setAttribute("download", exportedFilenmae); 81 | link.style.visibility = 'hidden'; 82 | document.body.appendChild(link); 83 | link.click(); 84 | document.body.removeChild(link); 85 | } 86 | } 87 | } 88 | exportJSONFile(data, file) { 89 | var exportedFilenmae = file + '.json' || 'export.json'; 90 | var blob = new Blob([data], { type: 'text/json;charset=utf-8;' }); 91 | if (navigator.msSaveBlob) { // IE 10+ 92 | navigator.msSaveBlob(blob, exportedFilenmae); 93 | } else { 94 | var link = document.createElement("a"); 95 | if (link.download !== undefined) { // feature detection 96 | // Browsers that support HTML5 download attribute 97 | var url = URL.createObjectURL(blob); 98 | link.setAttribute("href", url); 99 | link.setAttribute("download", exportedFilenmae); 100 | link.style.visibility = 'hidden'; 101 | document.body.appendChild(link); 102 | link.click(); 103 | document.body.removeChild(link); 104 | } 105 | } 106 | } 107 | } 108 | export default new Utils(); -------------------------------------------------------------------------------- /src/main.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import App from './App.vue' 3 | import router from './router' 4 | import Parse from './helpers/Parse'; 5 | 6 | import { library } from '@fortawesome/fontawesome-svg-core' 7 | import { faUserSecret, faTimes, faInfo, faForward, faPause, faPlay, faUser, faSmileBeam, faComments, faCheck, faExclamationTriangle, faCheckCircle, faTimesCircle, faArrowLeft, faArrowRight, faArrowUp, faArrowDown, faChevronLeft, faChevronRight, faChevronDown } from '@fortawesome/free-solid-svg-icons' 8 | import { FontAwesomeIcon } from '@fortawesome/vue-fontawesome' 9 | 10 | import vClickOutside from 'v-click-outside' 11 | 12 | import VueTour from 'vue-tour' 13 | 14 | require('vue-tour/dist/vue-tour.css') 15 | 16 | Vue.use(VueTour) 17 | 18 | import Vuesax from 'vuesax' 19 | 20 | import 'vuesax/dist/vuesax.css' //Vuesax styles 21 | Vue.use(Vuesax, { 22 | // options here 23 | }) 24 | 25 | 26 | import Toast from "vue-toastification"; 27 | // Import the CSS or use your own! 28 | import "vue-toastification/dist/index.css"; 29 | Vue.use(Toast); 30 | 31 | 32 | 33 | Vue.use(vClickOutside) 34 | library.add(faUserSecret, faTimes, faInfo, faForward, faPause, faPlay, faUser, faSmileBeam, faComments, faCheck, faExclamationTriangle, faCheckCircle, faTimesCircle, faArrowLeft, faArrowRight, faArrowUp, faArrowDown, faChevronLeft, faChevronRight, faChevronDown); 35 | 36 | Vue.component('font-awesome-icon', FontAwesomeIcon) 37 | 38 | // import Loader from '@/components/Loader'; 39 | 40 | // Vue.component('loader', Loader); 41 | 42 | Parse.init(); 43 | import store from './store/index'; 44 | import 'vue-json-pretty/lib/styles.css'; 45 | Vue.config.productionTip = false 46 | 47 | new Vue({ 48 | router, 49 | store, 50 | render: h => h(App) 51 | }).$mount('#app') 52 | 53 | document.addEventListener('visibilitychange', () => { 54 | if (document.visibilityState === 'hidden') { 55 | window.localStorage.removeItem('WALLETCONNECT_DEEPLINK_CHOICE'); 56 | } 57 | }); -------------------------------------------------------------------------------- /src/router/index.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import VueRouter from 'vue-router' 3 | import Home from '@/views/Home/index.vue' 4 | import CopyTrading from '@/views/CopyTrading/index.vue' 5 | import Contract from '@/views/Contract/index.vue'; 6 | // import store from '../store'; 7 | 8 | Vue.use(VueRouter) 9 | 10 | const routes = [ 11 | { 12 | path: '/', 13 | name: 'Home', 14 | component: Home 15 | }, 16 | { 17 | path: '/contract/:address?', 18 | name: 'Contract', 19 | component: Contract, 20 | }, 21 | 22 | // Copy Trading 23 | { 24 | path: '/copytrading', 25 | name: 'CopyTrading', 26 | component: CopyTrading 27 | }, 28 | ] 29 | 30 | const router = new VueRouter({ 31 | // mode: 'history', 32 | // base: process.env.BASE_URL, 33 | routes 34 | }) 35 | 36 | router.beforeEach((to, from, next) => { 37 | // console.log('ROUTER MIDDLEWARE', store.state.account); 38 | // if (to.name !== 'Home' && !isAuthenticated) next({ name: 'Login' }) 39 | // else next() 40 | next(); 41 | }) 42 | 43 | export default router 44 | -------------------------------------------------------------------------------- /src/store/index.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import Vuex from 'vuex' 3 | 4 | import accounts from './modules/accounts'; 5 | import contracts from './modules/contracts'; 6 | import positions from './modules/positions'; 7 | import histories from './modules/histories'; 8 | import watches from './modules/watches'; 9 | import information from './modules/information'; 10 | import transactions from './modules/transactions'; 11 | import targets from './modules/targets'; 12 | 13 | import { E_LOGIN } from "@/constants/events"; 14 | import Observer from '@/helpers/Observer'; 15 | 16 | Vue.use(Vuex) 17 | 18 | const Store = new Vuex.Store({ 19 | modules: { 20 | accounts, 21 | contracts, 22 | positions, 23 | histories, 24 | watches, 25 | information, 26 | transactions, 27 | targets 28 | }, 29 | state: { 30 | account: null, 31 | balance: 0 32 | }, 33 | getters: { 34 | account: (state) => state.account, 35 | balance: (state) => state.balance 36 | }, 37 | actions: { 38 | }, 39 | mutations: { 40 | SET (state, [key, value]) { 41 | state[key] = value; 42 | } 43 | } 44 | }) 45 | 46 | Observer.$on(E_LOGIN, () => { 47 | Store.dispatch('accounts/fetch'); 48 | 49 | Store.dispatch('watches/fetch', 'watch'); 50 | Store.dispatch('watches/fetch', 'live'); 51 | Store.dispatch('watches/fetch', 'past'); 52 | }) 53 | 54 | export default Store; -------------------------------------------------------------------------------- /src/store/modules/contracts.js: -------------------------------------------------------------------------------- 1 | import Parse from "@/helpers/Parse"; 2 | import Web3 from '@/helpers/Web3'; 3 | // import Config from '@/config'; 4 | 5 | const state = { 6 | list: [], 7 | active: null 8 | }; 9 | const getters = { 10 | list: (state) => state.list, 11 | active: (state) => state.active 12 | }; 13 | const actions = { 14 | async fetch({commit}) { 15 | console.log('Getting contracts'); 16 | const query = Parse.getContractQuery(); 17 | query.equalTo('user', Web3.address); 18 | query.equalTo('network', Web3.getNetwork().network); 19 | query.limit(30); 20 | query.descending("createdAt"); 21 | const contracts = await query.find(); 22 | commit('SET', ['list', contracts]); 23 | }, 24 | async setActive({commit}, contract) { 25 | commit('SET', ['active', contract]); 26 | }, 27 | // Get Contract from db or Create if not exists 28 | async get({dispatch}, address) { 29 | const contractQuery = Parse.getContractQuery(); 30 | // contractQuery.equalTo('network', Web3.getNetwork().network); 31 | // contractQuery.equalTo('address', address); 32 | contractQuery.matches('address', address, 'i'); 33 | contractQuery.ascending("createdAt"); 34 | contractQuery.limit(1); 35 | const contracts = await contractQuery.find(); 36 | 37 | if (contracts.length > 0) { 38 | if (contracts[0].get('totalSupply')) { 39 | return contracts[0]; 40 | } 41 | await contracts[0].destroy(); 42 | } 43 | return await dispatch('create', address); 44 | }, 45 | // eslint-disable-next-line no-empty-pattern 46 | async create({}, address) { 47 | const details = await Web3.getTokenDetails(address); 48 | const Contract = Parse.getClass('Contract'); 49 | const contract = new Contract(); 50 | contract.set('owner', details.owner); 51 | contract.set('network', Web3.getNetwork().network); 52 | contract.set('address', address); 53 | contract.set('abi', []); 54 | contract.set('totalSupply', details.totalSupply); 55 | contract.set('decimals', details.decimals); 56 | contract.set('name', details.name); 57 | contract.set('symbol', details.symbol); 58 | await contract.save(); 59 | return contract; 60 | }, 61 | }; 62 | const mutations = { 63 | SET (state, [key, value]) { 64 | state[key] = value; 65 | } 66 | }; 67 | 68 | export default { 69 | namespaced: true, 70 | state, 71 | getters, 72 | actions, 73 | mutations 74 | } 75 | -------------------------------------------------------------------------------- /src/store/modules/histories.js: -------------------------------------------------------------------------------- 1 | import Parse from "@/helpers/Parse"; 2 | // import Config from '@/config'; 3 | import Web3 from '@/helpers/Web3'; 4 | 5 | const state = { 6 | }; 7 | const getters = { 8 | }; 9 | const actions = { 10 | // eslint-disable-next-line no-empty-pattern 11 | async fetch({}, address) { 12 | const query = Parse.getQuery('History'); 13 | query.equalTo('contract', address); 14 | query.equalTo('network', Web3.getNetwork().network); 15 | query.limit(30); 16 | query.descending("createdAt"); 17 | const histories = await query.find(); 18 | return histories; 19 | } 20 | }; 21 | const mutations = { 22 | SET (state, [key, value]) { 23 | state[key] = value; 24 | } 25 | }; 26 | 27 | export default { 28 | namespaced: true, 29 | state, 30 | getters, 31 | actions, 32 | mutations 33 | } 34 | -------------------------------------------------------------------------------- /src/store/modules/information.js: -------------------------------------------------------------------------------- 1 | import Parse from "@/helpers/Parse"; 2 | import Web3 from '@/helpers/Web3'; 3 | 4 | const state = { 5 | status: [], 6 | orders: { 7 | pageSize: 5, 8 | page: 1, 9 | data: [] 10 | }, 11 | }; 12 | const getters = { 13 | status: (state) => state.status, 14 | orders: (state) => state.orders, 15 | }; 16 | const actions = { 17 | async fetchStatus({commit}) { 18 | const statusQuery = Parse.getQuery('Status'); 19 | const source = Web3.getLevel().canUseAccount() ? 'account' : 'wallet'; 20 | statusQuery.equalTo('network', Web3.getNetwork().network); 21 | statusQuery.equalTo('source', source); 22 | statusQuery.matches('owner', Web3.address, 'i'); 23 | const status = await statusQuery.find(); 24 | commit('SET', ['status', status]); 25 | }, 26 | async fetchOrders({state, commit}) { 27 | const orderQuery = Parse.getQuery('Order'); 28 | const source = Web3.getLevel().canUseAccount() ? 'account' : 'wallet'; 29 | orderQuery.equalTo('network', Web3.getNetwork().network); 30 | orderQuery.equalTo('source', source); 31 | orderQuery.matches('owner', Web3.address, 'i'); 32 | orderQuery.skip(state.orders.pageSize * (state.orders.page - 1)) 33 | orderQuery.limit(state.orders.pageSize); 34 | orderQuery.descending("createdAt"); 35 | 36 | const orders = await orderQuery.find(); 37 | commit('SET', ['orders', { 38 | pageSize: state.orders.pageSize, 39 | page: state.orders.page, 40 | data: orders 41 | }]); 42 | }, 43 | }; 44 | const mutations = { 45 | SET (state, [key, value]) { 46 | state[key] = value; 47 | } 48 | }; 49 | 50 | export default { 51 | namespaced: true, 52 | state, 53 | getters, 54 | actions, 55 | mutations 56 | } 57 | -------------------------------------------------------------------------------- /src/store/modules/positions.js: -------------------------------------------------------------------------------- 1 | import Parse from "@/helpers/Parse"; 2 | import Web3 from '@/helpers/Web3'; 3 | // import Config from '@/config'; 4 | 5 | const state = { 6 | }; 7 | const getters = { 8 | }; 9 | const actions = { 10 | // eslint-disable-next-line no-empty-pattern 11 | async fetch({}, contract) { 12 | const query = Parse.getContractQuery(); 13 | query.equalTo('user', Web3.address); 14 | query.equalTo('network', Web3.getNetwork().network); 15 | query.equalTo('contract', contract); 16 | query.limit(30); 17 | query.descending("createdAt"); 18 | return await query.find(); 19 | } 20 | }; 21 | const mutations = { 22 | SET (state, [key, value]) { 23 | state[key] = value; 24 | } 25 | }; 26 | 27 | export default { 28 | namespaced: true, 29 | state, 30 | getters, 31 | actions, 32 | mutations 33 | } 34 | -------------------------------------------------------------------------------- /src/store/modules/targets.js: -------------------------------------------------------------------------------- 1 | import Parse from "@/helpers/Parse"; 2 | // import Config from '@/config'; 3 | import Web3 from '@/helpers/Web3'; 4 | // import Observer from '@/helpers/Observer'; 5 | // import {E_NEW_ORDER} from "@/constants/events"; 6 | 7 | const state = { 8 | list: [], 9 | templates: [] 10 | }; 11 | 12 | const getters = { 13 | list: (state) => { 14 | return state.list 15 | }, 16 | templates: state => state.templates 17 | }; 18 | const actions = { 19 | async fetchTemplate({commit}) { 20 | const query = Parse.getQuery('TargetTemplate'); 21 | query.ascending("createdAt"); 22 | const templates = await query.find(); 23 | 24 | commit('SET', ['templates', templates]); 25 | }, 26 | async fetch({commit}) { 27 | const query = Parse.getTargetQuery(); 28 | query.matches('user', Web3.address, 'i'); 29 | query.equalTo('network', Web3.getNetwork().network); 30 | query.limit(30); 31 | query.ascending("createdAt"); 32 | const list = await query.find(); 33 | 34 | commit('SET', ['list', list]); 35 | }, 36 | 37 | async create({commit}, {name, address}) { 38 | const Target = Parse.getClass('Target'); 39 | const target = new Target(); 40 | target.set('user', Web3.address); 41 | target.set('name', name); 42 | target.set('network', Web3.getNetwork().network); 43 | target.set('address', address); 44 | await target.save(); 45 | commit('PUSH', ['list', target]); 46 | }, 47 | 48 | // eslint-disable-next-line no-empty-pattern 49 | async edit({}, {target, fields}) { 50 | Object.keys(fields).map(key => { 51 | target.set(key, fields[key]); 52 | }) 53 | await target.save(); 54 | }, 55 | 56 | async delete({commit, state}, target) { 57 | await target.destroy(); 58 | commit('SET', ['list', state.list.filter(tar => { 59 | return tar.id != target.id; 60 | })]); 61 | }, 62 | }; 63 | const mutations = { 64 | SET (state, [key, value]) { 65 | state[key] = value; 66 | }, 67 | PUSH (state, [key, value]) { 68 | state[key].push(value); 69 | } 70 | }; 71 | 72 | export default { 73 | namespaced: true, 74 | state, 75 | getters, 76 | actions, 77 | mutations 78 | } 79 | -------------------------------------------------------------------------------- /src/store/modules/transactions.js: -------------------------------------------------------------------------------- 1 | import Utils from "@/helpers/Utils"; 2 | import Web3 from '@/helpers/Web3'; 3 | 4 | const state = { 5 | config: { 6 | gasGWei: 0, 7 | blocks: 1, 8 | buyGasMultiplier: 1, 9 | buyFastGasMultiplier: 1.5, 10 | buyAmount: 0.1, 11 | maxSupply: 0, 12 | sellPercent: 100, 13 | sellGasMultiplier: 1, 14 | sellFastGasMultiplier: 1.5, 15 | cancelGasMultiplier: 1.5, 16 | 17 | // Buy Params 18 | buyOn: '', 19 | isBuyInstant: true, 20 | isSellOnWarn: true, 21 | factory: 0, 22 | copyRouters: [], 23 | 24 | isOriginalRouter: false, 25 | slippage: 0, 26 | warns: [], 27 | 28 | // Copy Trading Params 29 | isBuySameAmount: false, 30 | isSellSameAmount: true, 31 | isBuyOnce: false, 32 | sellThreshold: 0, 33 | 34 | // Gas Limit 35 | gasLimitETH: 0 36 | } 37 | }; 38 | const getters = { 39 | config: (state) => state.config 40 | }; 41 | const actions = { 42 | // eslint-disable-next-line no-empty-pattern 43 | async getConfig({state}, {action, type, history}) { 44 | if (!type) { 45 | type = 'normal'; 46 | } 47 | // gas: gasLimit, value, gasPrice / (maxFeePerGas, maxPriorityFeePerGas) 48 | let gasPrice, maxFeePerGas, maxPriorityFeePerGas, gasLimit = 1000000; 49 | 50 | if (!history) { 51 | gasPrice = await Web3.getGasPrice(); 52 | maxFeePerGas = 0; 53 | maxPriorityFeePerGas = 0; 54 | } else { 55 | const data = history.get('data'); 56 | gasPrice = data.transaction.gasPrice; 57 | maxFeePerGas = data.transaction.maxFeePerGas; 58 | maxPriorityFeePerGas = data.transaction.maxPriorityFeePerGas; 59 | if (maxFeePerGas && maxPriorityFeePerGas) { 60 | gasPrice = 0; 61 | } else { 62 | maxFeePerGas = 0; 63 | maxPriorityFeePerGas = 0; 64 | } 65 | } 66 | 67 | if (!maxFeePerGas && !maxPriorityFeePerGas && !gasPrice) { 68 | gasPrice = await Web3.getGasPrice(); 69 | } 70 | 71 | let gasGWei = parseFloat(state.config.gasGWei), gasMultiplier; 72 | if (type == 'frontrun') { 73 | gasMultiplier = parseFloat(state.config[action + 'FastGasMultiplier']); 74 | } else if (type == 'backrun' && history) { 75 | gasGWei = 0; 76 | gasMultiplier = 1; 77 | } else { 78 | gasMultiplier = parseFloat(state.config[action + 'GasMultiplier']); 79 | } 80 | 81 | if (gasGWei) { 82 | // eslint-disable-next-line no-undef 83 | gasPrice = BigInt(gasGWei) * BigInt(10 ** 9); 84 | maxFeePerGas = 0; 85 | maxPriorityFeePerGas = 0; 86 | } else if (gasMultiplier != 1) { 87 | if (gasPrice) { 88 | // eslint-disable-next-line no-undef 89 | gasPrice = BigInt(gasPrice) * BigInt(parseInt(gasMultiplier * 100)) / BigInt(100) 90 | } else { 91 | // eslint-disable-next-line no-undef 92 | maxFeePerGas = BigInt(maxFeePerGas) * BigInt(parseInt(gasMultiplier * 100)) / BigInt(100); 93 | // eslint-disable-next-line no-undef 94 | maxPriorityFeePerGas = BigInt(maxPriorityFeePerGas) * BigInt(parseInt(gasMultiplier * 100)) / BigInt(100); 95 | } 96 | } 97 | 98 | const config = { 99 | gas: gasLimit 100 | }; 101 | 102 | if (gasPrice) { 103 | config.gasPrice = Utils.formatBigInt(gasPrice); 104 | } else { 105 | config.maxFeePerGas = Utils.formatBigInt(maxFeePerGas); 106 | config.maxPriorityFeePerGas = Utils.formatBigInt(maxPriorityFeePerGas); 107 | } 108 | return config; 109 | }, 110 | }; 111 | const mutations = { 112 | SET (state, [key, value]) { 113 | state[key] = value; 114 | } 115 | }; 116 | 117 | export default { 118 | namespaced: true, 119 | state, 120 | getters, 121 | actions, 122 | mutations 123 | } 124 | -------------------------------------------------------------------------------- /src/store/modules/watches.js: -------------------------------------------------------------------------------- 1 | import Parse from "@/helpers/Parse"; 2 | import Web3 from '@/helpers/Web3'; 3 | // import Config from '@/config'; 4 | 5 | const state = { 6 | liveList: [], 7 | pastList: [], 8 | watchList: [] 9 | }; 10 | 11 | const getters = { 12 | liveList: (state) => state.liveList, 13 | pastList: (state) => state.pastList, 14 | watchList: (state) => state.watchList 15 | }; 16 | const actions = { 17 | async fetch({commit}, type) { 18 | let key = ''; 19 | const query = Parse.getQuery('Watch'); 20 | query.equalTo('user', Web3.address); 21 | query.equalTo('network', Web3.getNetwork().network); 22 | 23 | if (type == 'live') { 24 | query.equalTo('isActive', true); 25 | query.equalTo('isFinished', false); 26 | key = 'liveList'; 27 | } else if (type == 'past') { 28 | query.equalTo('isActive', true); 29 | query.equalTo('isFinished', true); 30 | key = 'pastList'; 31 | } else { 32 | query.equalTo('isActive', false); 33 | key = 'watchList'; 34 | } 35 | 36 | query.limit(30); 37 | query.descending("createdAt"); 38 | const watches = await query.find(); 39 | commit('SET', [key, watches]); 40 | }, 41 | 42 | // eslint-disable-next-line no-empty-pattern 43 | async get({}, address) { 44 | const query = Parse.getQuery('Watch'); 45 | query.equalTo('network', Web3.getNetwork().network); 46 | query.equalTo('address', address); 47 | query.limit(1); 48 | const watches = await query.find(); 49 | 50 | if (watches.length > 0) { 51 | return watches[0]; 52 | } 53 | return null; 54 | }, 55 | 56 | // eslint-disable-next-line no-empty-pattern 57 | async delete({commit, state}, {address, type}) { 58 | const query = Parse.getQuery('Watch'); 59 | query.equalTo('address', address); 60 | query.equalTo('network', Web3.getNetwork().network); 61 | query.equalTo('user', Web3.address); 62 | query.limit(1); 63 | const watches = await query.find(); 64 | 65 | if (watches.length > 0) { 66 | await watches[0].destroy(); 67 | const key = type + 'List'; 68 | commit('SET', [key, state[key].filter(item => { 69 | return item.get('address') != address; 70 | })]) 71 | } 72 | return true; 73 | }, 74 | 75 | async createUpdate({commit, state}, {address, owner, symbol, name, isActive, isFinished}) { 76 | const query = Parse.getQuery('Watch'); 77 | query.equalTo('network', Web3.getNetwork().network); 78 | query.equalTo('address', address); 79 | query.limit(1); 80 | const watches = await query.find(); 81 | 82 | let watch = null; 83 | let wasActive = null; 84 | let wasFinished = null; 85 | 86 | if (watches.length > 0) { 87 | watch = watches[0]; 88 | wasActive = !!watch.get('isActive'); 89 | wasFinished = !!watch.get('isFinished'); 90 | } else { 91 | const Watch = Parse.getClass('Watch'); 92 | watch = new Watch(); 93 | watch.set('network', Web3.getNetwork().network); 94 | } 95 | 96 | if (address) { 97 | watch.set('address', address); 98 | } 99 | if (name) { 100 | watch.set('name', name); 101 | } 102 | if (symbol) { 103 | watch.set('symbol', symbol); 104 | } 105 | if (owner) { 106 | watch.set('owner', owner); 107 | } 108 | watch.set('user', Web3.address); 109 | if (isActive != undefined) { 110 | watch.set('isActive', isActive); 111 | } 112 | if (isFinished != undefined) { 113 | watch.set('isFinished', isFinished); 114 | } 115 | await watch.save(); 116 | 117 | if (wasActive === false) { 118 | commit('SET', ['watchList', state.watchList.filter(item => { 119 | return item.id != watch.id; 120 | })]) 121 | } else if (wasFinished === false) { 122 | commit('SET', ['liveList', state.liveList.filter(item => { 123 | return item.id != watch.id; 124 | })]) 125 | } else { 126 | commit('SET', ['pastList', state.pastList.filter(item => { 127 | return item.id != watch.id; 128 | })]) 129 | } 130 | 131 | if (!watch.get('isActive')) { 132 | commit('PUSH', ['watchList', watch]); 133 | } else if (!watch.get('isFinished')) { 134 | commit('PUSH', ['liveList', watch]); 135 | } else { 136 | commit('PUSH', ['pastList', watch]); 137 | } 138 | return watch; 139 | } 140 | }; 141 | const mutations = { 142 | SET (state, [key, value]) { 143 | state[key] = value; 144 | }, 145 | PUSH (state, [key, value]) { 146 | state[key].push(value); 147 | } 148 | }; 149 | 150 | export default { 151 | namespaced: true, 152 | state, 153 | getters, 154 | actions, 155 | mutations 156 | } 157 | -------------------------------------------------------------------------------- /src/views/Contract/components/HistoryList.vue: -------------------------------------------------------------------------------- 1 | 45 | 46 | 162 | -------------------------------------------------------------------------------- /src/views/Contract/components/PositionList.vue: -------------------------------------------------------------------------------- 1 | 54 | 55 | 227 | -------------------------------------------------------------------------------- /src/views/Contract/components/WarnModal.vue: -------------------------------------------------------------------------------- 1 | 59 | 60 | 141 | 142 | -------------------------------------------------------------------------------- /src/views/Contract/index.vue: -------------------------------------------------------------------------------- 1 | 21 | 22 | 107 | -------------------------------------------------------------------------------- /src/views/CopyTrading/components/EditTriggerModal.vue: -------------------------------------------------------------------------------- 1 | 51 | 52 | 101 | 102 | -------------------------------------------------------------------------------- /src/views/CopyTrading/components/ExcludeModal.vue: -------------------------------------------------------------------------------- 1 | 65 | 66 | 205 | 206 | -------------------------------------------------------------------------------- /src/views/CopyTrading/index.vue: -------------------------------------------------------------------------------- 1 | 7 | 8 | 30 | -------------------------------------------------------------------------------- /src/views/Home/components/ActiveList.vue: -------------------------------------------------------------------------------- 1 | 85 | 86 | 141 | 142 | -------------------------------------------------------------------------------- /src/views/Home/components/WatchList.vue: -------------------------------------------------------------------------------- 1 | 62 | 63 | 150 | 151 | -------------------------------------------------------------------------------- /src/views/Home/index.vue: -------------------------------------------------------------------------------- 1 | 18 | 19 | 74 | 75 | -------------------------------------------------------------------------------- /src/views/Navbar/index.vue: -------------------------------------------------------------------------------- 1 | 67 | 68 | 187 | 188 | -------------------------------------------------------------------------------- /src/views/Template.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 18 | -------------------------------------------------------------------------------- /vue.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | publicPath: './' 3 | } --------------------------------------------------------------------------------