├── .env ├── .gitattributes ├── .gitignore ├── LICENSE ├── README.md ├── brownie-config.yaml ├── build └── interfaces │ ├── IERC20.json │ ├── IQuoter.json │ ├── ISwapRouter.json │ ├── IUniswapV2Router01.json │ └── IUniswapV2Router02.json ├── front-end ├── README.md ├── package-lock.json ├── package.json ├── public │ ├── favicon.ico │ ├── index.html │ ├── logo192.png │ ├── logo512.png │ ├── manifest.json │ └── robots.txt ├── src │ ├── App.css │ ├── App.js │ ├── App.test.js │ ├── artifacts │ │ └── interfaces │ │ │ ├── IERC20.json │ │ │ ├── IQuoter.json │ │ │ ├── ISwapRouter.json │ │ │ ├── IUniswapV2Router01.json │ │ │ └── IUniswapV2Router02.json │ ├── assets │ │ ├── css │ │ │ └── styles.css │ │ └── images │ │ │ ├── aave.png │ │ │ ├── bnb.png │ │ │ ├── crv.png │ │ │ ├── dai.png │ │ │ ├── etherLogo.png │ │ │ ├── link.png │ │ │ ├── matic.png │ │ │ ├── uni.jpg │ │ │ ├── usdc.png │ │ │ └── usdt.png │ ├── components │ │ ├── Account.js │ │ ├── Exchanges.js │ │ ├── Main.js │ │ ├── NavBar.js │ │ ├── NavbarElements.js │ │ └── Swap.js │ ├── dapp-logo.png │ ├── features │ │ └── blockchain.js │ ├── index.css │ ├── index.js │ ├── reportWebVitals.js │ ├── setupTests.js │ └── utils │ │ ├── helpers.js │ │ └── networksMap.json └── yarn.lock ├── interfaces ├── IERC20.sol ├── IQouter.sol ├── ISwapRouter.sol └── IUniswapV2Router02.sol └── scripts ├── get_prices.py ├── get_weth.py ├── helper_scripts.py └── update_front_end.py /.env: -------------------------------------------------------------------------------- 1 | PRIVATE_KEY=<< YOUR PRIVATE KEY >> 2 | WEB3_INFURA_PROJECT_ID=<< YOUR INFURA PROJECT ID >> 3 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | *.sol linguist-language=Solidity 2 | *.vy linguist-language=Python 3 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | __pycache__ 2 | .env 3 | .history 4 | .hypothesis/ 5 | build/ 6 | reports/ 7 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 Aymen 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |
2 | 3 | 4 | ## Dex-aggregator 5 | 6 | With the ever growing DEFI world and the appearance of multiple decentralized exchanges on the different blockchains, the WEB3 ecosystem needs a way to compare the pros & cons of swapping on each DEX. 7 | 8 | This excatly what Paraswap & 1inch protocol are trying to do, they aggregate the prices of tokens from multiple exchanges in each Blockchain (for example: uniswap, sushiswap, shibaswap in the Ethereum Mainnet), then they compare those prices and the swapping fee and offer to their user the best exchange rate possible. 9 | 10 | In this Dapp, i built a simplified version of Paraswap it works on 4 blockchains: Ethereum, Polygon, Binance Smart Chain and the kovan testnet.For the moment it supports some well known tokens (ETH, Matic, Dai, USDC,...). 11 | 12 |

13 | Dark 14 |

15 | 16 | ### Built With 17 | 18 | * [Solidity](https://docs.soliditylang.org/) 19 | * [Brownie](https://eth-brownie.readthedocs.io) 20 | * [React.js](https://reactjs.org/) 21 | * [ethers.js](https://docs.ethers.io/v5/) 22 | * [web3modal](https://github.com/Web3Modal/web3modal) 23 | * [material ui](https://mui.com/getting-started/installation/) 24 | 25 | 26 | 27 | ## Getting Started 28 | 29 | ### Prerequisites 30 | 31 | Please install or have installed the following: 32 | * [nodejs and npm](https://nodejs.org/en/download/) 33 | * [python](https://www.python.org/downloads/) 34 | * [MetaMask](https://chrome.google.com/webstore/detail/metamask/nkbihfbeogaeaoehlefnkodbefgpgknn) Chrome extension installed in your browser 35 | 36 | ### Installation 37 | 38 | 1. Installing Brownie: Brownie is a python framework for smart contracts development,testing and deployments. It's quit like [HardHat](https://hardhat.org) but it uses python for writing test and deployements scripts instead of javascript. 39 | Here is a simple way to install brownie. 40 | ``` 41 | pip install --user pipx 42 | pipx ensurepath 43 | # restart your terminal 44 | pipx install eth-brownie 45 | ``` 46 | Or if you can't get pipx to work, via pip (it's recommended to use pipx) 47 | ```sh 48 | pip install eth-brownie 49 | ``` 50 | Install [ganache-cli](https://www.npmjs.com/package/ganache-cli): 51 | ```sh 52 | npm install -g ganache-cli 53 | ``` 54 | 2. Clone the repo: 55 | ```sh 56 | git clone https://github.com/kaymen99/Dex-aggregator.git 57 | cd Dex-aggregator 58 | ``` 59 | 60 | 3. Set your environment variables 61 | To be able to deploy to real testnets you need to add your PRIVATE_KEY (You can find your PRIVATE_KEY from your ethereum wallet like metamask) and the infura project Id (just create an infura account it's free) to the .env file: 62 | ``` 63 | PRIVATE_KEY= 64 | WEB3_INFURA_PROJECT_ID=<< YOUR INFURA PROJECT ID >> 65 | ``` 66 | You can choose to use ethereum testnets like rinkeby, Kovan or any other evm compatible testnet. 67 | You'll also need some eth in the testnet. You can get it into your wallet by using a public faucet. 68 | 69 | 70 |

(back to top)

71 | 72 | 73 | 74 | ## How to Use 75 | After going throught the installation part you can start the app by running: 76 | ```sh 77 | cd front-end 78 | yarn 79 | yarn start 80 | ``` 81 | The front-end is built using the following libraries: 82 | 88 | There are 2 main components: 89 | 93 | 94 |

(back to top)

95 | 96 | 97 | 98 | ## Contact 99 | 100 | If you have any question or problem running this project just contact me: aymenMir1001@gmail.com 101 | 102 |

(back to top)

103 | 104 | 105 | 106 | ## License 107 | 108 | Distributed under the MIT License. See `LICENSE.txt` for more information. 109 | 110 |

(back to top)

111 | 112 | 113 | -------------------------------------------------------------------------------- /brownie-config.yaml: -------------------------------------------------------------------------------- 1 | dotenv: .env 2 | 3 | wallets: 4 | from_key: ${PRIVATE_KEY} 5 | 6 | dependencies: 7 | - OpenZeppelin/openzeppelin-contracts@3.4.0 8 | - Uniswap/v3-core@1.0.0 9 | 10 | compiler: 11 | solc: 12 | remappings: 13 | - "@openzeppelin=OpenZeppelin/openzeppelin-contracts@3.4.0" 14 | - "@uniswap=Uniswap/v3-core@1.0.0" 15 | 16 | networks: 17 | mainnet-fork: 18 | uniswap-router: "0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D" 19 | uniswapV3-router: "0xE592427A0AEce92De3Edee1F18E0157C05861564" 20 | uniswapV3-qouter: "0xb27308f9F90D607463bb33eA1BeBb41C27CE5AB6" 21 | sushiswap-router: "0xd9e1cE17f2641f24aE83637ab66a2cca9C378B9F" 22 | shibaswap-router: "0x03f7724180AA6b939894B5Ca4314783B0b36b329" 23 | weth-token: "0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2" 24 | dai-token: "0x6b175474e89094c44da98b954eedeac495271d0f" 25 | kovan: 26 | uniswap-router: "0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D" 27 | uniswapV3-router: "0xE592427A0AEce92De3Edee1F18E0157C05861564" 28 | uniswapV3-qouter: "0xb27308f9F90D607463bb33eA1BeBb41C27CE5AB6" 29 | sushiswap-router: "0xd9e1cE17f2641f24aE83637ab66a2cca9C378B9F" 30 | weth-token: "0xd0a1e359811322d97991e03f863a0c30c2cf029c" 31 | dai-token: "0xFf795577d9AC8bD7D90Ee22b6C1703490b6512FD" 32 | 33 | polygone-mainnet-dev: 34 | uniswapV3-router: "0xE592427A0AEce92De3Edee1F18E0157C05861564" 35 | uniswapV3-qouter: "0xb27308f9F90D607463bb33eA1BeBb41C27CE5AB6" 36 | quickswap-router: "0xa5E0829CaCEd8fFDD4De3c43696c57F7D7A678ff" 37 | sushiswap-router: "0x1b02dA8Cb0d097eB8D57A175b88c7D8b47997506" 38 | jetswap-router: "0x5C6EC38fb0e2609672BDf628B1fD605A523E5923" 39 | weth-token: "0x7ceB23fD6bC0adD59E62ac25578270cFf1b9f619" 40 | dai-token: "0x8f3Cf7ad23Cd3CaDbD9735AFf958023239c6A063" 41 | -------------------------------------------------------------------------------- /build/interfaces/IERC20.json: -------------------------------------------------------------------------------- 1 | { 2 | "abi": [ 3 | { 4 | "anonymous": false, 5 | "inputs": [ 6 | { 7 | "indexed": true, 8 | "internalType": "address", 9 | "name": "owner", 10 | "type": "address" 11 | }, 12 | { 13 | "indexed": true, 14 | "internalType": "address", 15 | "name": "spender", 16 | "type": "address" 17 | }, 18 | { 19 | "indexed": false, 20 | "internalType": "uint256", 21 | "name": "value", 22 | "type": "uint256" 23 | } 24 | ], 25 | "name": "Approval", 26 | "type": "event" 27 | }, 28 | { 29 | "anonymous": false, 30 | "inputs": [ 31 | { 32 | "indexed": true, 33 | "internalType": "address", 34 | "name": "from", 35 | "type": "address" 36 | }, 37 | { 38 | "indexed": true, 39 | "internalType": "address", 40 | "name": "to", 41 | "type": "address" 42 | }, 43 | { 44 | "indexed": false, 45 | "internalType": "uint256", 46 | "name": "value", 47 | "type": "uint256" 48 | } 49 | ], 50 | "name": "Transfer", 51 | "type": "event" 52 | }, 53 | { 54 | "inputs": [ 55 | { 56 | "internalType": "address", 57 | "name": "owner", 58 | "type": "address" 59 | }, 60 | { 61 | "internalType": "address", 62 | "name": "spender", 63 | "type": "address" 64 | } 65 | ], 66 | "name": "allowance", 67 | "outputs": [ 68 | { 69 | "internalType": "uint256", 70 | "name": "", 71 | "type": "uint256" 72 | } 73 | ], 74 | "stateMutability": "view", 75 | "type": "function" 76 | }, 77 | { 78 | "inputs": [ 79 | { 80 | "internalType": "address", 81 | "name": "spender", 82 | "type": "address" 83 | }, 84 | { 85 | "internalType": "uint256", 86 | "name": "amount", 87 | "type": "uint256" 88 | } 89 | ], 90 | "name": "approve", 91 | "outputs": [ 92 | { 93 | "internalType": "bool", 94 | "name": "", 95 | "type": "bool" 96 | } 97 | ], 98 | "stateMutability": "nonpayable", 99 | "type": "function" 100 | }, 101 | { 102 | "inputs": [ 103 | { 104 | "internalType": "address", 105 | "name": "account", 106 | "type": "address" 107 | } 108 | ], 109 | "name": "balanceOf", 110 | "outputs": [ 111 | { 112 | "internalType": "uint256", 113 | "name": "", 114 | "type": "uint256" 115 | } 116 | ], 117 | "stateMutability": "view", 118 | "type": "function" 119 | }, 120 | { 121 | "inputs": [], 122 | "name": "totalSupply", 123 | "outputs": [ 124 | { 125 | "internalType": "uint256", 126 | "name": "", 127 | "type": "uint256" 128 | } 129 | ], 130 | "stateMutability": "view", 131 | "type": "function" 132 | }, 133 | { 134 | "inputs": [ 135 | { 136 | "internalType": "address", 137 | "name": "recipient", 138 | "type": "address" 139 | }, 140 | { 141 | "internalType": "uint256", 142 | "name": "amount", 143 | "type": "uint256" 144 | } 145 | ], 146 | "name": "transfer", 147 | "outputs": [ 148 | { 149 | "internalType": "bool", 150 | "name": "", 151 | "type": "bool" 152 | } 153 | ], 154 | "stateMutability": "nonpayable", 155 | "type": "function" 156 | }, 157 | { 158 | "inputs": [ 159 | { 160 | "internalType": "address", 161 | "name": "sender", 162 | "type": "address" 163 | }, 164 | { 165 | "internalType": "address", 166 | "name": "recipient", 167 | "type": "address" 168 | }, 169 | { 170 | "internalType": "uint256", 171 | "name": "amount", 172 | "type": "uint256" 173 | } 174 | ], 175 | "name": "transferFrom", 176 | "outputs": [ 177 | { 178 | "internalType": "bool", 179 | "name": "", 180 | "type": "bool" 181 | } 182 | ], 183 | "stateMutability": "nonpayable", 184 | "type": "function" 185 | } 186 | ], 187 | "ast": { 188 | "absolutePath": "interfaces/IERC20.sol", 189 | "exportedSymbols": { 190 | "IERC20": [ 191 | 77 192 | ] 193 | }, 194 | "id": 78, 195 | "license": "MIT", 196 | "nodeType": "SourceUnit", 197 | "nodes": [ 198 | { 199 | "id": 1, 200 | "literals": [ 201 | "solidity", 202 | ">=", 203 | "0.6", 204 | ".0", 205 | "<", 206 | "0.8", 207 | ".0" 208 | ], 209 | "nodeType": "PragmaDirective", 210 | "src": "33:31:1" 211 | }, 212 | { 213 | "abstract": false, 214 | "baseContracts": [], 215 | "contractDependencies": [], 216 | "contractKind": "interface", 217 | "documentation": { 218 | "id": 2, 219 | "nodeType": "StructuredDocumentation", 220 | "src": "66:70:1", 221 | "text": " @dev Interface of the ERC20 standard as defined in the EIP." 222 | }, 223 | "fullyImplemented": false, 224 | "id": 77, 225 | "linearizedBaseContracts": [ 226 | 77 227 | ], 228 | "name": "IERC20", 229 | "nodeType": "ContractDefinition", 230 | "nodes": [ 231 | { 232 | "documentation": { 233 | "id": 3, 234 | "nodeType": "StructuredDocumentation", 235 | "src": "160:66:1", 236 | "text": " @dev Returns the amount of tokens in existence." 237 | }, 238 | "functionSelector": "18160ddd", 239 | "id": 8, 240 | "implemented": false, 241 | "kind": "function", 242 | "modifiers": [], 243 | "name": "totalSupply", 244 | "nodeType": "FunctionDefinition", 245 | "parameters": { 246 | "id": 4, 247 | "nodeType": "ParameterList", 248 | "parameters": [], 249 | "src": "251:2:1" 250 | }, 251 | "returnParameters": { 252 | "id": 7, 253 | "nodeType": "ParameterList", 254 | "parameters": [ 255 | { 256 | "constant": false, 257 | "id": 6, 258 | "mutability": "mutable", 259 | "name": "", 260 | "nodeType": "VariableDeclaration", 261 | "scope": 8, 262 | "src": "277:7:1", 263 | "stateVariable": false, 264 | "storageLocation": "default", 265 | "typeDescriptions": { 266 | "typeIdentifier": "t_uint256", 267 | "typeString": "uint256" 268 | }, 269 | "typeName": { 270 | "id": 5, 271 | "name": "uint256", 272 | "nodeType": "ElementaryTypeName", 273 | "src": "277:7:1", 274 | "typeDescriptions": { 275 | "typeIdentifier": "t_uint256", 276 | "typeString": "uint256" 277 | } 278 | }, 279 | "visibility": "internal" 280 | } 281 | ], 282 | "src": "276:9:1" 283 | }, 284 | "scope": 77, 285 | "src": "231:55:1", 286 | "stateMutability": "view", 287 | "virtual": false, 288 | "visibility": "external" 289 | }, 290 | { 291 | "documentation": { 292 | "id": 9, 293 | "nodeType": "StructuredDocumentation", 294 | "src": "292:72:1", 295 | "text": " @dev Returns the amount of tokens owned by `account`." 296 | }, 297 | "functionSelector": "70a08231", 298 | "id": 16, 299 | "implemented": false, 300 | "kind": "function", 301 | "modifiers": [], 302 | "name": "balanceOf", 303 | "nodeType": "FunctionDefinition", 304 | "parameters": { 305 | "id": 12, 306 | "nodeType": "ParameterList", 307 | "parameters": [ 308 | { 309 | "constant": false, 310 | "id": 11, 311 | "mutability": "mutable", 312 | "name": "account", 313 | "nodeType": "VariableDeclaration", 314 | "scope": 16, 315 | "src": "388:15:1", 316 | "stateVariable": false, 317 | "storageLocation": "default", 318 | "typeDescriptions": { 319 | "typeIdentifier": "t_address", 320 | "typeString": "address" 321 | }, 322 | "typeName": { 323 | "id": 10, 324 | "name": "address", 325 | "nodeType": "ElementaryTypeName", 326 | "src": "388:7:1", 327 | "stateMutability": "nonpayable", 328 | "typeDescriptions": { 329 | "typeIdentifier": "t_address", 330 | "typeString": "address" 331 | } 332 | }, 333 | "visibility": "internal" 334 | } 335 | ], 336 | "src": "387:17:1" 337 | }, 338 | "returnParameters": { 339 | "id": 15, 340 | "nodeType": "ParameterList", 341 | "parameters": [ 342 | { 343 | "constant": false, 344 | "id": 14, 345 | "mutability": "mutable", 346 | "name": "", 347 | "nodeType": "VariableDeclaration", 348 | "scope": 16, 349 | "src": "428:7:1", 350 | "stateVariable": false, 351 | "storageLocation": "default", 352 | "typeDescriptions": { 353 | "typeIdentifier": "t_uint256", 354 | "typeString": "uint256" 355 | }, 356 | "typeName": { 357 | "id": 13, 358 | "name": "uint256", 359 | "nodeType": "ElementaryTypeName", 360 | "src": "428:7:1", 361 | "typeDescriptions": { 362 | "typeIdentifier": "t_uint256", 363 | "typeString": "uint256" 364 | } 365 | }, 366 | "visibility": "internal" 367 | } 368 | ], 369 | "src": "427:9:1" 370 | }, 371 | "scope": 77, 372 | "src": "369:68:1", 373 | "stateMutability": "view", 374 | "virtual": false, 375 | "visibility": "external" 376 | }, 377 | { 378 | "documentation": { 379 | "id": 17, 380 | "nodeType": "StructuredDocumentation", 381 | "src": "443:209:1", 382 | "text": " @dev Moves `amount` tokens from the caller's account to `recipient`.\n Returns a boolean value indicating whether the operation succeeded.\n Emits a {Transfer} event." 383 | }, 384 | "functionSelector": "a9059cbb", 385 | "id": 26, 386 | "implemented": false, 387 | "kind": "function", 388 | "modifiers": [], 389 | "name": "transfer", 390 | "nodeType": "FunctionDefinition", 391 | "parameters": { 392 | "id": 22, 393 | "nodeType": "ParameterList", 394 | "parameters": [ 395 | { 396 | "constant": false, 397 | "id": 19, 398 | "mutability": "mutable", 399 | "name": "recipient", 400 | "nodeType": "VariableDeclaration", 401 | "scope": 26, 402 | "src": "675:17:1", 403 | "stateVariable": false, 404 | "storageLocation": "default", 405 | "typeDescriptions": { 406 | "typeIdentifier": "t_address", 407 | "typeString": "address" 408 | }, 409 | "typeName": { 410 | "id": 18, 411 | "name": "address", 412 | "nodeType": "ElementaryTypeName", 413 | "src": "675:7:1", 414 | "stateMutability": "nonpayable", 415 | "typeDescriptions": { 416 | "typeIdentifier": "t_address", 417 | "typeString": "address" 418 | } 419 | }, 420 | "visibility": "internal" 421 | }, 422 | { 423 | "constant": false, 424 | "id": 21, 425 | "mutability": "mutable", 426 | "name": "amount", 427 | "nodeType": "VariableDeclaration", 428 | "scope": 26, 429 | "src": "694:14:1", 430 | "stateVariable": false, 431 | "storageLocation": "default", 432 | "typeDescriptions": { 433 | "typeIdentifier": "t_uint256", 434 | "typeString": "uint256" 435 | }, 436 | "typeName": { 437 | "id": 20, 438 | "name": "uint256", 439 | "nodeType": "ElementaryTypeName", 440 | "src": "694:7:1", 441 | "typeDescriptions": { 442 | "typeIdentifier": "t_uint256", 443 | "typeString": "uint256" 444 | } 445 | }, 446 | "visibility": "internal" 447 | } 448 | ], 449 | "src": "674:35:1" 450 | }, 451 | "returnParameters": { 452 | "id": 25, 453 | "nodeType": "ParameterList", 454 | "parameters": [ 455 | { 456 | "constant": false, 457 | "id": 24, 458 | "mutability": "mutable", 459 | "name": "", 460 | "nodeType": "VariableDeclaration", 461 | "scope": 26, 462 | "src": "744:4:1", 463 | "stateVariable": false, 464 | "storageLocation": "default", 465 | "typeDescriptions": { 466 | "typeIdentifier": "t_bool", 467 | "typeString": "bool" 468 | }, 469 | "typeName": { 470 | "id": 23, 471 | "name": "bool", 472 | "nodeType": "ElementaryTypeName", 473 | "src": "744:4:1", 474 | "typeDescriptions": { 475 | "typeIdentifier": "t_bool", 476 | "typeString": "bool" 477 | } 478 | }, 479 | "visibility": "internal" 480 | } 481 | ], 482 | "src": "743:6:1" 483 | }, 484 | "scope": 77, 485 | "src": "657:93:1", 486 | "stateMutability": "nonpayable", 487 | "virtual": false, 488 | "visibility": "external" 489 | }, 490 | { 491 | "documentation": { 492 | "id": 27, 493 | "nodeType": "StructuredDocumentation", 494 | "src": "756:264:1", 495 | "text": " @dev Returns the remaining number of tokens that `spender` will be\n allowed to spend on behalf of `owner` through {transferFrom}. This is\n zero by default.\n This value changes when {approve} or {transferFrom} are called." 496 | }, 497 | "functionSelector": "dd62ed3e", 498 | "id": 36, 499 | "implemented": false, 500 | "kind": "function", 501 | "modifiers": [], 502 | "name": "allowance", 503 | "nodeType": "FunctionDefinition", 504 | "parameters": { 505 | "id": 32, 506 | "nodeType": "ParameterList", 507 | "parameters": [ 508 | { 509 | "constant": false, 510 | "id": 29, 511 | "mutability": "mutable", 512 | "name": "owner", 513 | "nodeType": "VariableDeclaration", 514 | "scope": 36, 515 | "src": "1044:13:1", 516 | "stateVariable": false, 517 | "storageLocation": "default", 518 | "typeDescriptions": { 519 | "typeIdentifier": "t_address", 520 | "typeString": "address" 521 | }, 522 | "typeName": { 523 | "id": 28, 524 | "name": "address", 525 | "nodeType": "ElementaryTypeName", 526 | "src": "1044:7:1", 527 | "stateMutability": "nonpayable", 528 | "typeDescriptions": { 529 | "typeIdentifier": "t_address", 530 | "typeString": "address" 531 | } 532 | }, 533 | "visibility": "internal" 534 | }, 535 | { 536 | "constant": false, 537 | "id": 31, 538 | "mutability": "mutable", 539 | "name": "spender", 540 | "nodeType": "VariableDeclaration", 541 | "scope": 36, 542 | "src": "1059:15:1", 543 | "stateVariable": false, 544 | "storageLocation": "default", 545 | "typeDescriptions": { 546 | "typeIdentifier": "t_address", 547 | "typeString": "address" 548 | }, 549 | "typeName": { 550 | "id": 30, 551 | "name": "address", 552 | "nodeType": "ElementaryTypeName", 553 | "src": "1059:7:1", 554 | "stateMutability": "nonpayable", 555 | "typeDescriptions": { 556 | "typeIdentifier": "t_address", 557 | "typeString": "address" 558 | } 559 | }, 560 | "visibility": "internal" 561 | } 562 | ], 563 | "src": "1043:32:1" 564 | }, 565 | "returnParameters": { 566 | "id": 35, 567 | "nodeType": "ParameterList", 568 | "parameters": [ 569 | { 570 | "constant": false, 571 | "id": 34, 572 | "mutability": "mutable", 573 | "name": "", 574 | "nodeType": "VariableDeclaration", 575 | "scope": 36, 576 | "src": "1123:7:1", 577 | "stateVariable": false, 578 | "storageLocation": "default", 579 | "typeDescriptions": { 580 | "typeIdentifier": "t_uint256", 581 | "typeString": "uint256" 582 | }, 583 | "typeName": { 584 | "id": 33, 585 | "name": "uint256", 586 | "nodeType": "ElementaryTypeName", 587 | "src": "1123:7:1", 588 | "typeDescriptions": { 589 | "typeIdentifier": "t_uint256", 590 | "typeString": "uint256" 591 | } 592 | }, 593 | "visibility": "internal" 594 | } 595 | ], 596 | "src": "1122:9:1" 597 | }, 598 | "scope": 77, 599 | "src": "1025:107:1", 600 | "stateMutability": "view", 601 | "virtual": false, 602 | "visibility": "external" 603 | }, 604 | { 605 | "documentation": { 606 | "id": 37, 607 | "nodeType": "StructuredDocumentation", 608 | "src": "1138:642:1", 609 | "text": " @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\n Returns a boolean value indicating whether the operation succeeded.\n IMPORTANT: Beware that changing an allowance with this method brings the risk\n that someone may use both the old and the new allowance by unfortunate\n transaction ordering. One possible solution to mitigate this race\n condition is to first reduce the spender's allowance to 0 and set the\n desired value afterwards:\n https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\n Emits an {Approval} event." 610 | }, 611 | "functionSelector": "095ea7b3", 612 | "id": 46, 613 | "implemented": false, 614 | "kind": "function", 615 | "modifiers": [], 616 | "name": "approve", 617 | "nodeType": "FunctionDefinition", 618 | "parameters": { 619 | "id": 42, 620 | "nodeType": "ParameterList", 621 | "parameters": [ 622 | { 623 | "constant": false, 624 | "id": 39, 625 | "mutability": "mutable", 626 | "name": "spender", 627 | "nodeType": "VariableDeclaration", 628 | "scope": 46, 629 | "src": "1802:15:1", 630 | "stateVariable": false, 631 | "storageLocation": "default", 632 | "typeDescriptions": { 633 | "typeIdentifier": "t_address", 634 | "typeString": "address" 635 | }, 636 | "typeName": { 637 | "id": 38, 638 | "name": "address", 639 | "nodeType": "ElementaryTypeName", 640 | "src": "1802:7:1", 641 | "stateMutability": "nonpayable", 642 | "typeDescriptions": { 643 | "typeIdentifier": "t_address", 644 | "typeString": "address" 645 | } 646 | }, 647 | "visibility": "internal" 648 | }, 649 | { 650 | "constant": false, 651 | "id": 41, 652 | "mutability": "mutable", 653 | "name": "amount", 654 | "nodeType": "VariableDeclaration", 655 | "scope": 46, 656 | "src": "1819:14:1", 657 | "stateVariable": false, 658 | "storageLocation": "default", 659 | "typeDescriptions": { 660 | "typeIdentifier": "t_uint256", 661 | "typeString": "uint256" 662 | }, 663 | "typeName": { 664 | "id": 40, 665 | "name": "uint256", 666 | "nodeType": "ElementaryTypeName", 667 | "src": "1819:7:1", 668 | "typeDescriptions": { 669 | "typeIdentifier": "t_uint256", 670 | "typeString": "uint256" 671 | } 672 | }, 673 | "visibility": "internal" 674 | } 675 | ], 676 | "src": "1801:33:1" 677 | }, 678 | "returnParameters": { 679 | "id": 45, 680 | "nodeType": "ParameterList", 681 | "parameters": [ 682 | { 683 | "constant": false, 684 | "id": 44, 685 | "mutability": "mutable", 686 | "name": "", 687 | "nodeType": "VariableDeclaration", 688 | "scope": 46, 689 | "src": "1853:4:1", 690 | "stateVariable": false, 691 | "storageLocation": "default", 692 | "typeDescriptions": { 693 | "typeIdentifier": "t_bool", 694 | "typeString": "bool" 695 | }, 696 | "typeName": { 697 | "id": 43, 698 | "name": "bool", 699 | "nodeType": "ElementaryTypeName", 700 | "src": "1853:4:1", 701 | "typeDescriptions": { 702 | "typeIdentifier": "t_bool", 703 | "typeString": "bool" 704 | } 705 | }, 706 | "visibility": "internal" 707 | } 708 | ], 709 | "src": "1852:6:1" 710 | }, 711 | "scope": 77, 712 | "src": "1785:74:1", 713 | "stateMutability": "nonpayable", 714 | "virtual": false, 715 | "visibility": "external" 716 | }, 717 | { 718 | "documentation": { 719 | "id": 47, 720 | "nodeType": "StructuredDocumentation", 721 | "src": "1865:296:1", 722 | "text": " @dev Moves `amount` tokens from `sender` to `recipient` using the\n allowance mechanism. `amount` is then deducted from the caller's\n allowance.\n Returns a boolean value indicating whether the operation succeeded.\n Emits a {Transfer} event." 723 | }, 724 | "functionSelector": "23b872dd", 725 | "id": 58, 726 | "implemented": false, 727 | "kind": "function", 728 | "modifiers": [], 729 | "name": "transferFrom", 730 | "nodeType": "FunctionDefinition", 731 | "parameters": { 732 | "id": 54, 733 | "nodeType": "ParameterList", 734 | "parameters": [ 735 | { 736 | "constant": false, 737 | "id": 49, 738 | "mutability": "mutable", 739 | "name": "sender", 740 | "nodeType": "VariableDeclaration", 741 | "scope": 58, 742 | "src": "2197:14:1", 743 | "stateVariable": false, 744 | "storageLocation": "default", 745 | "typeDescriptions": { 746 | "typeIdentifier": "t_address", 747 | "typeString": "address" 748 | }, 749 | "typeName": { 750 | "id": 48, 751 | "name": "address", 752 | "nodeType": "ElementaryTypeName", 753 | "src": "2197:7:1", 754 | "stateMutability": "nonpayable", 755 | "typeDescriptions": { 756 | "typeIdentifier": "t_address", 757 | "typeString": "address" 758 | } 759 | }, 760 | "visibility": "internal" 761 | }, 762 | { 763 | "constant": false, 764 | "id": 51, 765 | "mutability": "mutable", 766 | "name": "recipient", 767 | "nodeType": "VariableDeclaration", 768 | "scope": 58, 769 | "src": "2221:17:1", 770 | "stateVariable": false, 771 | "storageLocation": "default", 772 | "typeDescriptions": { 773 | "typeIdentifier": "t_address", 774 | "typeString": "address" 775 | }, 776 | "typeName": { 777 | "id": 50, 778 | "name": "address", 779 | "nodeType": "ElementaryTypeName", 780 | "src": "2221:7:1", 781 | "stateMutability": "nonpayable", 782 | "typeDescriptions": { 783 | "typeIdentifier": "t_address", 784 | "typeString": "address" 785 | } 786 | }, 787 | "visibility": "internal" 788 | }, 789 | { 790 | "constant": false, 791 | "id": 53, 792 | "mutability": "mutable", 793 | "name": "amount", 794 | "nodeType": "VariableDeclaration", 795 | "scope": 58, 796 | "src": "2248:14:1", 797 | "stateVariable": false, 798 | "storageLocation": "default", 799 | "typeDescriptions": { 800 | "typeIdentifier": "t_uint256", 801 | "typeString": "uint256" 802 | }, 803 | "typeName": { 804 | "id": 52, 805 | "name": "uint256", 806 | "nodeType": "ElementaryTypeName", 807 | "src": "2248:7:1", 808 | "typeDescriptions": { 809 | "typeIdentifier": "t_uint256", 810 | "typeString": "uint256" 811 | } 812 | }, 813 | "visibility": "internal" 814 | } 815 | ], 816 | "src": "2187:81:1" 817 | }, 818 | "returnParameters": { 819 | "id": 57, 820 | "nodeType": "ParameterList", 821 | "parameters": [ 822 | { 823 | "constant": false, 824 | "id": 56, 825 | "mutability": "mutable", 826 | "name": "", 827 | "nodeType": "VariableDeclaration", 828 | "scope": 58, 829 | "src": "2287:4:1", 830 | "stateVariable": false, 831 | "storageLocation": "default", 832 | "typeDescriptions": { 833 | "typeIdentifier": "t_bool", 834 | "typeString": "bool" 835 | }, 836 | "typeName": { 837 | "id": 55, 838 | "name": "bool", 839 | "nodeType": "ElementaryTypeName", 840 | "src": "2287:4:1", 841 | "typeDescriptions": { 842 | "typeIdentifier": "t_bool", 843 | "typeString": "bool" 844 | } 845 | }, 846 | "visibility": "internal" 847 | } 848 | ], 849 | "src": "2286:6:1" 850 | }, 851 | "scope": 77, 852 | "src": "2166:127:1", 853 | "stateMutability": "nonpayable", 854 | "virtual": false, 855 | "visibility": "external" 856 | }, 857 | { 858 | "anonymous": false, 859 | "documentation": { 860 | "id": 59, 861 | "nodeType": "StructuredDocumentation", 862 | "src": "2299:158:1", 863 | "text": " @dev Emitted when `value` tokens are moved from one account (`from`) to\n another (`to`).\n Note that `value` may be zero." 864 | }, 865 | "id": 67, 866 | "name": "Transfer", 867 | "nodeType": "EventDefinition", 868 | "parameters": { 869 | "id": 66, 870 | "nodeType": "ParameterList", 871 | "parameters": [ 872 | { 873 | "constant": false, 874 | "id": 61, 875 | "indexed": true, 876 | "mutability": "mutable", 877 | "name": "from", 878 | "nodeType": "VariableDeclaration", 879 | "scope": 67, 880 | "src": "2477:20:1", 881 | "stateVariable": false, 882 | "storageLocation": "default", 883 | "typeDescriptions": { 884 | "typeIdentifier": "t_address", 885 | "typeString": "address" 886 | }, 887 | "typeName": { 888 | "id": 60, 889 | "name": "address", 890 | "nodeType": "ElementaryTypeName", 891 | "src": "2477:7:1", 892 | "stateMutability": "nonpayable", 893 | "typeDescriptions": { 894 | "typeIdentifier": "t_address", 895 | "typeString": "address" 896 | } 897 | }, 898 | "visibility": "internal" 899 | }, 900 | { 901 | "constant": false, 902 | "id": 63, 903 | "indexed": true, 904 | "mutability": "mutable", 905 | "name": "to", 906 | "nodeType": "VariableDeclaration", 907 | "scope": 67, 908 | "src": "2499:18:1", 909 | "stateVariable": false, 910 | "storageLocation": "default", 911 | "typeDescriptions": { 912 | "typeIdentifier": "t_address", 913 | "typeString": "address" 914 | }, 915 | "typeName": { 916 | "id": 62, 917 | "name": "address", 918 | "nodeType": "ElementaryTypeName", 919 | "src": "2499:7:1", 920 | "stateMutability": "nonpayable", 921 | "typeDescriptions": { 922 | "typeIdentifier": "t_address", 923 | "typeString": "address" 924 | } 925 | }, 926 | "visibility": "internal" 927 | }, 928 | { 929 | "constant": false, 930 | "id": 65, 931 | "indexed": false, 932 | "mutability": "mutable", 933 | "name": "value", 934 | "nodeType": "VariableDeclaration", 935 | "scope": 67, 936 | "src": "2519:13:1", 937 | "stateVariable": false, 938 | "storageLocation": "default", 939 | "typeDescriptions": { 940 | "typeIdentifier": "t_uint256", 941 | "typeString": "uint256" 942 | }, 943 | "typeName": { 944 | "id": 64, 945 | "name": "uint256", 946 | "nodeType": "ElementaryTypeName", 947 | "src": "2519:7:1", 948 | "typeDescriptions": { 949 | "typeIdentifier": "t_uint256", 950 | "typeString": "uint256" 951 | } 952 | }, 953 | "visibility": "internal" 954 | } 955 | ], 956 | "src": "2476:57:1" 957 | }, 958 | "src": "2462:72:1" 959 | }, 960 | { 961 | "anonymous": false, 962 | "documentation": { 963 | "id": 68, 964 | "nodeType": "StructuredDocumentation", 965 | "src": "2540:148:1", 966 | "text": " @dev Emitted when the allowance of a `spender` for an `owner` is set by\n a call to {approve}. `value` is the new allowance." 967 | }, 968 | "id": 76, 969 | "name": "Approval", 970 | "nodeType": "EventDefinition", 971 | "parameters": { 972 | "id": 75, 973 | "nodeType": "ParameterList", 974 | "parameters": [ 975 | { 976 | "constant": false, 977 | "id": 70, 978 | "indexed": true, 979 | "mutability": "mutable", 980 | "name": "owner", 981 | "nodeType": "VariableDeclaration", 982 | "scope": 76, 983 | "src": "2717:21:1", 984 | "stateVariable": false, 985 | "storageLocation": "default", 986 | "typeDescriptions": { 987 | "typeIdentifier": "t_address", 988 | "typeString": "address" 989 | }, 990 | "typeName": { 991 | "id": 69, 992 | "name": "address", 993 | "nodeType": "ElementaryTypeName", 994 | "src": "2717:7:1", 995 | "stateMutability": "nonpayable", 996 | "typeDescriptions": { 997 | "typeIdentifier": "t_address", 998 | "typeString": "address" 999 | } 1000 | }, 1001 | "visibility": "internal" 1002 | }, 1003 | { 1004 | "constant": false, 1005 | "id": 72, 1006 | "indexed": true, 1007 | "mutability": "mutable", 1008 | "name": "spender", 1009 | "nodeType": "VariableDeclaration", 1010 | "scope": 76, 1011 | "src": "2748:23:1", 1012 | "stateVariable": false, 1013 | "storageLocation": "default", 1014 | "typeDescriptions": { 1015 | "typeIdentifier": "t_address", 1016 | "typeString": "address" 1017 | }, 1018 | "typeName": { 1019 | "id": 71, 1020 | "name": "address", 1021 | "nodeType": "ElementaryTypeName", 1022 | "src": "2748:7:1", 1023 | "stateMutability": "nonpayable", 1024 | "typeDescriptions": { 1025 | "typeIdentifier": "t_address", 1026 | "typeString": "address" 1027 | } 1028 | }, 1029 | "visibility": "internal" 1030 | }, 1031 | { 1032 | "constant": false, 1033 | "id": 74, 1034 | "indexed": false, 1035 | "mutability": "mutable", 1036 | "name": "value", 1037 | "nodeType": "VariableDeclaration", 1038 | "scope": 76, 1039 | "src": "2781:13:1", 1040 | "stateVariable": false, 1041 | "storageLocation": "default", 1042 | "typeDescriptions": { 1043 | "typeIdentifier": "t_uint256", 1044 | "typeString": "uint256" 1045 | }, 1046 | "typeName": { 1047 | "id": 73, 1048 | "name": "uint256", 1049 | "nodeType": "ElementaryTypeName", 1050 | "src": "2781:7:1", 1051 | "typeDescriptions": { 1052 | "typeIdentifier": "t_uint256", 1053 | "typeString": "uint256" 1054 | } 1055 | }, 1056 | "visibility": "internal" 1057 | } 1058 | ], 1059 | "src": "2707:93:1" 1060 | }, 1061 | "src": "2693:108:1" 1062 | } 1063 | ], 1064 | "scope": 78, 1065 | "src": "137:2666:1" 1066 | } 1067 | ], 1068 | "src": "33:2771:1" 1069 | }, 1070 | "contractName": "IERC20", 1071 | "dependencies": [], 1072 | "offset": [ 1073 | 137, 1074 | 2803 1075 | ], 1076 | "sha1": "6b2cffe7b0ed20aefdb3bb642379dddeb6506a5f", 1077 | "source": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\n/**\n * @dev Interface of the ERC20 standard as defined in the EIP.\n */\ninterface IERC20 {\n /**\n * @dev Returns the amount of tokens in existence.\n */\n function totalSupply() external view returns (uint256);\n\n /**\n * @dev Returns the amount of tokens owned by `account`.\n */\n function balanceOf(address account) external view returns (uint256);\n\n /**\n * @dev Moves `amount` tokens from the caller's account to `recipient`.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transfer(address recipient, uint256 amount)\n external\n returns (bool);\n\n /**\n * @dev Returns the remaining number of tokens that `spender` will be\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\n * zero by default.\n *\n * This value changes when {approve} or {transferFrom} are called.\n */\n function allowance(address owner, address spender)\n external\n view\n returns (uint256);\n\n /**\n * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\n * that someone may use both the old and the new allowance by unfortunate\n * transaction ordering. One possible solution to mitigate this race\n * condition is to first reduce the spender's allowance to 0 and set the\n * desired value afterwards:\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\n *\n * Emits an {Approval} event.\n */\n function approve(address spender, uint256 amount) external returns (bool);\n\n /**\n * @dev Moves `amount` tokens from `sender` to `recipient` using the\n * allowance mechanism. `amount` is then deducted from the caller's\n * allowance.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transferFrom(\n address sender,\n address recipient,\n uint256 amount\n ) external returns (bool);\n\n /**\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\n * another (`to`).\n *\n * Note that `value` may be zero.\n */\n event Transfer(address indexed from, address indexed to, uint256 value);\n\n /**\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\n * a call to {approve}. `value` is the new allowance.\n */\n event Approval(\n address indexed owner,\n address indexed spender,\n uint256 value\n );\n}\n", 1078 | "type": "interface" 1079 | } -------------------------------------------------------------------------------- /build/interfaces/IQuoter.json: -------------------------------------------------------------------------------- 1 | { 2 | "abi": [ 3 | { 4 | "inputs": [ 5 | { 6 | "internalType": "bytes", 7 | "name": "path", 8 | "type": "bytes" 9 | }, 10 | { 11 | "internalType": "uint256", 12 | "name": "amountIn", 13 | "type": "uint256" 14 | } 15 | ], 16 | "name": "quoteExactInput", 17 | "outputs": [ 18 | { 19 | "internalType": "uint256", 20 | "name": "amountOut", 21 | "type": "uint256" 22 | } 23 | ], 24 | "stateMutability": "nonpayable", 25 | "type": "function" 26 | }, 27 | { 28 | "inputs": [ 29 | { 30 | "internalType": "address", 31 | "name": "tokenIn", 32 | "type": "address" 33 | }, 34 | { 35 | "internalType": "address", 36 | "name": "tokenOut", 37 | "type": "address" 38 | }, 39 | { 40 | "internalType": "uint24", 41 | "name": "fee", 42 | "type": "uint24" 43 | }, 44 | { 45 | "internalType": "uint256", 46 | "name": "amountIn", 47 | "type": "uint256" 48 | }, 49 | { 50 | "internalType": "uint160", 51 | "name": "sqrtPriceLimitX96", 52 | "type": "uint160" 53 | } 54 | ], 55 | "name": "quoteExactInputSingle", 56 | "outputs": [ 57 | { 58 | "internalType": "uint256", 59 | "name": "amountOut", 60 | "type": "uint256" 61 | } 62 | ], 63 | "stateMutability": "nonpayable", 64 | "type": "function" 65 | }, 66 | { 67 | "inputs": [ 68 | { 69 | "internalType": "bytes", 70 | "name": "path", 71 | "type": "bytes" 72 | }, 73 | { 74 | "internalType": "uint256", 75 | "name": "amountOut", 76 | "type": "uint256" 77 | } 78 | ], 79 | "name": "quoteExactOutput", 80 | "outputs": [ 81 | { 82 | "internalType": "uint256", 83 | "name": "amountIn", 84 | "type": "uint256" 85 | } 86 | ], 87 | "stateMutability": "nonpayable", 88 | "type": "function" 89 | }, 90 | { 91 | "inputs": [ 92 | { 93 | "internalType": "address", 94 | "name": "tokenIn", 95 | "type": "address" 96 | }, 97 | { 98 | "internalType": "address", 99 | "name": "tokenOut", 100 | "type": "address" 101 | }, 102 | { 103 | "internalType": "uint24", 104 | "name": "fee", 105 | "type": "uint24" 106 | }, 107 | { 108 | "internalType": "uint256", 109 | "name": "amountOut", 110 | "type": "uint256" 111 | }, 112 | { 113 | "internalType": "uint160", 114 | "name": "sqrtPriceLimitX96", 115 | "type": "uint160" 116 | } 117 | ], 118 | "name": "quoteExactOutputSingle", 119 | "outputs": [ 120 | { 121 | "internalType": "uint256", 122 | "name": "amountIn", 123 | "type": "uint256" 124 | } 125 | ], 126 | "stateMutability": "nonpayable", 127 | "type": "function" 128 | } 129 | ], 130 | "ast": { 131 | "absolutePath": "interfaces/IQouter.sol", 132 | "exportedSymbols": { 133 | "IQuoter": [ 134 | 56 135 | ] 136 | }, 137 | "id": 57, 138 | "license": "GPL-2.0-or-later", 139 | "nodeType": "SourceUnit", 140 | "nodes": [ 141 | { 142 | "id": 1, 143 | "literals": [ 144 | "solidity", 145 | ">=", 146 | "0.7", 147 | ".5" 148 | ], 149 | "nodeType": "PragmaDirective", 150 | "src": "45:24:1" 151 | }, 152 | { 153 | "id": 2, 154 | "literals": [ 155 | "abicoder", 156 | "v2" 157 | ], 158 | "nodeType": "PragmaDirective", 159 | "src": "70:19:1" 160 | }, 161 | { 162 | "abstract": false, 163 | "baseContracts": [], 164 | "canonicalName": "IQuoter", 165 | "contractDependencies": [], 166 | "contractKind": "interface", 167 | "documentation": { 168 | "id": 3, 169 | "nodeType": "StructuredDocumentation", 170 | "src": "91:320:1", 171 | "text": "@title Quoter Interface\n @notice Supports quoting the calculated amounts from exact input or exact output swaps\n @dev These functions are not marked view because they rely on calling non-view functions and reverting\n to compute the result. They are also not gas efficient and should not be called on-chain." 172 | }, 173 | "fullyImplemented": false, 174 | "id": 56, 175 | "linearizedBaseContracts": [ 176 | 56 177 | ], 178 | "name": "IQuoter", 179 | "nameLocation": "421:7:1", 180 | "nodeType": "ContractDefinition", 181 | "nodes": [ 182 | { 183 | "documentation": { 184 | "id": 4, 185 | "nodeType": "StructuredDocumentation", 186 | "src": "435:319:1", 187 | "text": "@notice Returns the amount out received for a given exact input swap without executing the swap\n @param path The path of the swap, i.e. each token pair and the pool fee\n @param amountIn The amount of the first token to swap\n @return amountOut The amount of the last token that would be received" 188 | }, 189 | "functionSelector": "cdca1753", 190 | "id": 13, 191 | "implemented": false, 192 | "kind": "function", 193 | "modifiers": [], 194 | "name": "quoteExactInput", 195 | "nameLocation": "768:15:1", 196 | "nodeType": "FunctionDefinition", 197 | "parameters": { 198 | "id": 9, 199 | "nodeType": "ParameterList", 200 | "parameters": [ 201 | { 202 | "constant": false, 203 | "id": 6, 204 | "mutability": "mutable", 205 | "name": "path", 206 | "nameLocation": "797:4:1", 207 | "nodeType": "VariableDeclaration", 208 | "scope": 13, 209 | "src": "784:17:1", 210 | "stateVariable": false, 211 | "storageLocation": "memory", 212 | "typeDescriptions": { 213 | "typeIdentifier": "t_bytes_memory_ptr", 214 | "typeString": "bytes" 215 | }, 216 | "typeName": { 217 | "id": 5, 218 | "name": "bytes", 219 | "nodeType": "ElementaryTypeName", 220 | "src": "784:5:1", 221 | "typeDescriptions": { 222 | "typeIdentifier": "t_bytes_storage_ptr", 223 | "typeString": "bytes" 224 | } 225 | }, 226 | "visibility": "internal" 227 | }, 228 | { 229 | "constant": false, 230 | "id": 8, 231 | "mutability": "mutable", 232 | "name": "amountIn", 233 | "nameLocation": "811:8:1", 234 | "nodeType": "VariableDeclaration", 235 | "scope": 13, 236 | "src": "803:16:1", 237 | "stateVariable": false, 238 | "storageLocation": "default", 239 | "typeDescriptions": { 240 | "typeIdentifier": "t_uint256", 241 | "typeString": "uint256" 242 | }, 243 | "typeName": { 244 | "id": 7, 245 | "name": "uint256", 246 | "nodeType": "ElementaryTypeName", 247 | "src": "803:7:1", 248 | "typeDescriptions": { 249 | "typeIdentifier": "t_uint256", 250 | "typeString": "uint256" 251 | } 252 | }, 253 | "visibility": "internal" 254 | } 255 | ], 256 | "src": "783:37:1" 257 | }, 258 | "returnParameters": { 259 | "id": 12, 260 | "nodeType": "ParameterList", 261 | "parameters": [ 262 | { 263 | "constant": false, 264 | "id": 11, 265 | "mutability": "mutable", 266 | "name": "amountOut", 267 | "nameLocation": "863:9:1", 268 | "nodeType": "VariableDeclaration", 269 | "scope": 13, 270 | "src": "855:17:1", 271 | "stateVariable": false, 272 | "storageLocation": "default", 273 | "typeDescriptions": { 274 | "typeIdentifier": "t_uint256", 275 | "typeString": "uint256" 276 | }, 277 | "typeName": { 278 | "id": 10, 279 | "name": "uint256", 280 | "nodeType": "ElementaryTypeName", 281 | "src": "855:7:1", 282 | "typeDescriptions": { 283 | "typeIdentifier": "t_uint256", 284 | "typeString": "uint256" 285 | } 286 | }, 287 | "visibility": "internal" 288 | } 289 | ], 290 | "src": "854:19:1" 291 | }, 292 | "scope": 56, 293 | "src": "759:115:1", 294 | "stateMutability": "nonpayable", 295 | "virtual": false, 296 | "visibility": "external" 297 | }, 298 | { 299 | "documentation": { 300 | "id": 14, 301 | "nodeType": "StructuredDocumentation", 302 | "src": "880:491:1", 303 | "text": "@notice Returns the amount out received for a given exact input but for a swap of a single pool\n @param tokenIn The token being swapped in\n @param tokenOut The token being swapped out\n @param fee The fee of the token pool to consider for the pair\n @param amountIn The desired input amount\n @param sqrtPriceLimitX96 The price limit of the pool that cannot be exceeded by the swap\n @return amountOut The amount of `tokenOut` that would be received" 304 | }, 305 | "functionSelector": "f7729d43", 306 | "id": 29, 307 | "implemented": false, 308 | "kind": "function", 309 | "modifiers": [], 310 | "name": "quoteExactInputSingle", 311 | "nameLocation": "1385:21:1", 312 | "nodeType": "FunctionDefinition", 313 | "parameters": { 314 | "id": 25, 315 | "nodeType": "ParameterList", 316 | "parameters": [ 317 | { 318 | "constant": false, 319 | "id": 16, 320 | "mutability": "mutable", 321 | "name": "tokenIn", 322 | "nameLocation": "1424:7:1", 323 | "nodeType": "VariableDeclaration", 324 | "scope": 29, 325 | "src": "1416:15:1", 326 | "stateVariable": false, 327 | "storageLocation": "default", 328 | "typeDescriptions": { 329 | "typeIdentifier": "t_address", 330 | "typeString": "address" 331 | }, 332 | "typeName": { 333 | "id": 15, 334 | "name": "address", 335 | "nodeType": "ElementaryTypeName", 336 | "src": "1416:7:1", 337 | "stateMutability": "nonpayable", 338 | "typeDescriptions": { 339 | "typeIdentifier": "t_address", 340 | "typeString": "address" 341 | } 342 | }, 343 | "visibility": "internal" 344 | }, 345 | { 346 | "constant": false, 347 | "id": 18, 348 | "mutability": "mutable", 349 | "name": "tokenOut", 350 | "nameLocation": "1449:8:1", 351 | "nodeType": "VariableDeclaration", 352 | "scope": 29, 353 | "src": "1441:16:1", 354 | "stateVariable": false, 355 | "storageLocation": "default", 356 | "typeDescriptions": { 357 | "typeIdentifier": "t_address", 358 | "typeString": "address" 359 | }, 360 | "typeName": { 361 | "id": 17, 362 | "name": "address", 363 | "nodeType": "ElementaryTypeName", 364 | "src": "1441:7:1", 365 | "stateMutability": "nonpayable", 366 | "typeDescriptions": { 367 | "typeIdentifier": "t_address", 368 | "typeString": "address" 369 | } 370 | }, 371 | "visibility": "internal" 372 | }, 373 | { 374 | "constant": false, 375 | "id": 20, 376 | "mutability": "mutable", 377 | "name": "fee", 378 | "nameLocation": "1474:3:1", 379 | "nodeType": "VariableDeclaration", 380 | "scope": 29, 381 | "src": "1467:10:1", 382 | "stateVariable": false, 383 | "storageLocation": "default", 384 | "typeDescriptions": { 385 | "typeIdentifier": "t_uint24", 386 | "typeString": "uint24" 387 | }, 388 | "typeName": { 389 | "id": 19, 390 | "name": "uint24", 391 | "nodeType": "ElementaryTypeName", 392 | "src": "1467:6:1", 393 | "typeDescriptions": { 394 | "typeIdentifier": "t_uint24", 395 | "typeString": "uint24" 396 | } 397 | }, 398 | "visibility": "internal" 399 | }, 400 | { 401 | "constant": false, 402 | "id": 22, 403 | "mutability": "mutable", 404 | "name": "amountIn", 405 | "nameLocation": "1495:8:1", 406 | "nodeType": "VariableDeclaration", 407 | "scope": 29, 408 | "src": "1487:16:1", 409 | "stateVariable": false, 410 | "storageLocation": "default", 411 | "typeDescriptions": { 412 | "typeIdentifier": "t_uint256", 413 | "typeString": "uint256" 414 | }, 415 | "typeName": { 416 | "id": 21, 417 | "name": "uint256", 418 | "nodeType": "ElementaryTypeName", 419 | "src": "1487:7:1", 420 | "typeDescriptions": { 421 | "typeIdentifier": "t_uint256", 422 | "typeString": "uint256" 423 | } 424 | }, 425 | "visibility": "internal" 426 | }, 427 | { 428 | "constant": false, 429 | "id": 24, 430 | "mutability": "mutable", 431 | "name": "sqrtPriceLimitX96", 432 | "nameLocation": "1521:17:1", 433 | "nodeType": "VariableDeclaration", 434 | "scope": 29, 435 | "src": "1513:25:1", 436 | "stateVariable": false, 437 | "storageLocation": "default", 438 | "typeDescriptions": { 439 | "typeIdentifier": "t_uint160", 440 | "typeString": "uint160" 441 | }, 442 | "typeName": { 443 | "id": 23, 444 | "name": "uint160", 445 | "nodeType": "ElementaryTypeName", 446 | "src": "1513:7:1", 447 | "typeDescriptions": { 448 | "typeIdentifier": "t_uint160", 449 | "typeString": "uint160" 450 | } 451 | }, 452 | "visibility": "internal" 453 | } 454 | ], 455 | "src": "1406:138:1" 456 | }, 457 | "returnParameters": { 458 | "id": 28, 459 | "nodeType": "ParameterList", 460 | "parameters": [ 461 | { 462 | "constant": false, 463 | "id": 27, 464 | "mutability": "mutable", 465 | "name": "amountOut", 466 | "nameLocation": "1571:9:1", 467 | "nodeType": "VariableDeclaration", 468 | "scope": 29, 469 | "src": "1563:17:1", 470 | "stateVariable": false, 471 | "storageLocation": "default", 472 | "typeDescriptions": { 473 | "typeIdentifier": "t_uint256", 474 | "typeString": "uint256" 475 | }, 476 | "typeName": { 477 | "id": 26, 478 | "name": "uint256", 479 | "nodeType": "ElementaryTypeName", 480 | "src": "1563:7:1", 481 | "typeDescriptions": { 482 | "typeIdentifier": "t_uint256", 483 | "typeString": "uint256" 484 | } 485 | }, 486 | "visibility": "internal" 487 | } 488 | ], 489 | "src": "1562:19:1" 490 | }, 491 | "scope": 56, 492 | "src": "1376:206:1", 493 | "stateMutability": "nonpayable", 494 | "virtual": false, 495 | "visibility": "external" 496 | }, 497 | { 498 | "documentation": { 499 | "id": 30, 500 | "nodeType": "StructuredDocumentation", 501 | "src": "1588:355:1", 502 | "text": "@notice Returns the amount in required for a given exact output swap without executing the swap\n @param path The path of the swap, i.e. each token pair and the pool fee. Path must be provided in reverse order\n @param amountOut The amount of the last token to receive\n @return amountIn The amount of first token required to be paid" 503 | }, 504 | "functionSelector": "2f80bb1d", 505 | "id": 39, 506 | "implemented": false, 507 | "kind": "function", 508 | "modifiers": [], 509 | "name": "quoteExactOutput", 510 | "nameLocation": "1957:16:1", 511 | "nodeType": "FunctionDefinition", 512 | "parameters": { 513 | "id": 35, 514 | "nodeType": "ParameterList", 515 | "parameters": [ 516 | { 517 | "constant": false, 518 | "id": 32, 519 | "mutability": "mutable", 520 | "name": "path", 521 | "nameLocation": "1987:4:1", 522 | "nodeType": "VariableDeclaration", 523 | "scope": 39, 524 | "src": "1974:17:1", 525 | "stateVariable": false, 526 | "storageLocation": "memory", 527 | "typeDescriptions": { 528 | "typeIdentifier": "t_bytes_memory_ptr", 529 | "typeString": "bytes" 530 | }, 531 | "typeName": { 532 | "id": 31, 533 | "name": "bytes", 534 | "nodeType": "ElementaryTypeName", 535 | "src": "1974:5:1", 536 | "typeDescriptions": { 537 | "typeIdentifier": "t_bytes_storage_ptr", 538 | "typeString": "bytes" 539 | } 540 | }, 541 | "visibility": "internal" 542 | }, 543 | { 544 | "constant": false, 545 | "id": 34, 546 | "mutability": "mutable", 547 | "name": "amountOut", 548 | "nameLocation": "2001:9:1", 549 | "nodeType": "VariableDeclaration", 550 | "scope": 39, 551 | "src": "1993:17:1", 552 | "stateVariable": false, 553 | "storageLocation": "default", 554 | "typeDescriptions": { 555 | "typeIdentifier": "t_uint256", 556 | "typeString": "uint256" 557 | }, 558 | "typeName": { 559 | "id": 33, 560 | "name": "uint256", 561 | "nodeType": "ElementaryTypeName", 562 | "src": "1993:7:1", 563 | "typeDescriptions": { 564 | "typeIdentifier": "t_uint256", 565 | "typeString": "uint256" 566 | } 567 | }, 568 | "visibility": "internal" 569 | } 570 | ], 571 | "src": "1973:38:1" 572 | }, 573 | "returnParameters": { 574 | "id": 38, 575 | "nodeType": "ParameterList", 576 | "parameters": [ 577 | { 578 | "constant": false, 579 | "id": 37, 580 | "mutability": "mutable", 581 | "name": "amountIn", 582 | "nameLocation": "2054:8:1", 583 | "nodeType": "VariableDeclaration", 584 | "scope": 39, 585 | "src": "2046:16:1", 586 | "stateVariable": false, 587 | "storageLocation": "default", 588 | "typeDescriptions": { 589 | "typeIdentifier": "t_uint256", 590 | "typeString": "uint256" 591 | }, 592 | "typeName": { 593 | "id": 36, 594 | "name": "uint256", 595 | "nodeType": "ElementaryTypeName", 596 | "src": "2046:7:1", 597 | "typeDescriptions": { 598 | "typeIdentifier": "t_uint256", 599 | "typeString": "uint256" 600 | } 601 | }, 602 | "visibility": "internal" 603 | } 604 | ], 605 | "src": "2045:18:1" 606 | }, 607 | "scope": 56, 608 | "src": "1948:116:1", 609 | "stateMutability": "nonpayable", 610 | "virtual": false, 611 | "visibility": "external" 612 | }, 613 | { 614 | "documentation": { 615 | "id": 40, 616 | "nodeType": "StructuredDocumentation", 617 | "src": "2070:538:1", 618 | "text": "@notice Returns the amount in required to receive the given exact output amount but for a swap of a single pool\n @param tokenIn The token being swapped in\n @param tokenOut The token being swapped out\n @param fee The fee of the token pool to consider for the pair\n @param amountOut The desired output amount\n @param sqrtPriceLimitX96 The price limit of the pool that cannot be exceeded by the swap\n @return amountIn The amount required as the input for the swap in order to receive `amountOut`" 619 | }, 620 | "functionSelector": "30d07f21", 621 | "id": 55, 622 | "implemented": false, 623 | "kind": "function", 624 | "modifiers": [], 625 | "name": "quoteExactOutputSingle", 626 | "nameLocation": "2622:22:1", 627 | "nodeType": "FunctionDefinition", 628 | "parameters": { 629 | "id": 51, 630 | "nodeType": "ParameterList", 631 | "parameters": [ 632 | { 633 | "constant": false, 634 | "id": 42, 635 | "mutability": "mutable", 636 | "name": "tokenIn", 637 | "nameLocation": "2662:7:1", 638 | "nodeType": "VariableDeclaration", 639 | "scope": 55, 640 | "src": "2654:15:1", 641 | "stateVariable": false, 642 | "storageLocation": "default", 643 | "typeDescriptions": { 644 | "typeIdentifier": "t_address", 645 | "typeString": "address" 646 | }, 647 | "typeName": { 648 | "id": 41, 649 | "name": "address", 650 | "nodeType": "ElementaryTypeName", 651 | "src": "2654:7:1", 652 | "stateMutability": "nonpayable", 653 | "typeDescriptions": { 654 | "typeIdentifier": "t_address", 655 | "typeString": "address" 656 | } 657 | }, 658 | "visibility": "internal" 659 | }, 660 | { 661 | "constant": false, 662 | "id": 44, 663 | "mutability": "mutable", 664 | "name": "tokenOut", 665 | "nameLocation": "2687:8:1", 666 | "nodeType": "VariableDeclaration", 667 | "scope": 55, 668 | "src": "2679:16:1", 669 | "stateVariable": false, 670 | "storageLocation": "default", 671 | "typeDescriptions": { 672 | "typeIdentifier": "t_address", 673 | "typeString": "address" 674 | }, 675 | "typeName": { 676 | "id": 43, 677 | "name": "address", 678 | "nodeType": "ElementaryTypeName", 679 | "src": "2679:7:1", 680 | "stateMutability": "nonpayable", 681 | "typeDescriptions": { 682 | "typeIdentifier": "t_address", 683 | "typeString": "address" 684 | } 685 | }, 686 | "visibility": "internal" 687 | }, 688 | { 689 | "constant": false, 690 | "id": 46, 691 | "mutability": "mutable", 692 | "name": "fee", 693 | "nameLocation": "2712:3:1", 694 | "nodeType": "VariableDeclaration", 695 | "scope": 55, 696 | "src": "2705:10:1", 697 | "stateVariable": false, 698 | "storageLocation": "default", 699 | "typeDescriptions": { 700 | "typeIdentifier": "t_uint24", 701 | "typeString": "uint24" 702 | }, 703 | "typeName": { 704 | "id": 45, 705 | "name": "uint24", 706 | "nodeType": "ElementaryTypeName", 707 | "src": "2705:6:1", 708 | "typeDescriptions": { 709 | "typeIdentifier": "t_uint24", 710 | "typeString": "uint24" 711 | } 712 | }, 713 | "visibility": "internal" 714 | }, 715 | { 716 | "constant": false, 717 | "id": 48, 718 | "mutability": "mutable", 719 | "name": "amountOut", 720 | "nameLocation": "2733:9:1", 721 | "nodeType": "VariableDeclaration", 722 | "scope": 55, 723 | "src": "2725:17:1", 724 | "stateVariable": false, 725 | "storageLocation": "default", 726 | "typeDescriptions": { 727 | "typeIdentifier": "t_uint256", 728 | "typeString": "uint256" 729 | }, 730 | "typeName": { 731 | "id": 47, 732 | "name": "uint256", 733 | "nodeType": "ElementaryTypeName", 734 | "src": "2725:7:1", 735 | "typeDescriptions": { 736 | "typeIdentifier": "t_uint256", 737 | "typeString": "uint256" 738 | } 739 | }, 740 | "visibility": "internal" 741 | }, 742 | { 743 | "constant": false, 744 | "id": 50, 745 | "mutability": "mutable", 746 | "name": "sqrtPriceLimitX96", 747 | "nameLocation": "2760:17:1", 748 | "nodeType": "VariableDeclaration", 749 | "scope": 55, 750 | "src": "2752:25:1", 751 | "stateVariable": false, 752 | "storageLocation": "default", 753 | "typeDescriptions": { 754 | "typeIdentifier": "t_uint160", 755 | "typeString": "uint160" 756 | }, 757 | "typeName": { 758 | "id": 49, 759 | "name": "uint160", 760 | "nodeType": "ElementaryTypeName", 761 | "src": "2752:7:1", 762 | "typeDescriptions": { 763 | "typeIdentifier": "t_uint160", 764 | "typeString": "uint160" 765 | } 766 | }, 767 | "visibility": "internal" 768 | } 769 | ], 770 | "src": "2644:139:1" 771 | }, 772 | "returnParameters": { 773 | "id": 54, 774 | "nodeType": "ParameterList", 775 | "parameters": [ 776 | { 777 | "constant": false, 778 | "id": 53, 779 | "mutability": "mutable", 780 | "name": "amountIn", 781 | "nameLocation": "2810:8:1", 782 | "nodeType": "VariableDeclaration", 783 | "scope": 55, 784 | "src": "2802:16:1", 785 | "stateVariable": false, 786 | "storageLocation": "default", 787 | "typeDescriptions": { 788 | "typeIdentifier": "t_uint256", 789 | "typeString": "uint256" 790 | }, 791 | "typeName": { 792 | "id": 52, 793 | "name": "uint256", 794 | "nodeType": "ElementaryTypeName", 795 | "src": "2802:7:1", 796 | "typeDescriptions": { 797 | "typeIdentifier": "t_uint256", 798 | "typeString": "uint256" 799 | } 800 | }, 801 | "visibility": "internal" 802 | } 803 | ], 804 | "src": "2801:18:1" 805 | }, 806 | "scope": 56, 807 | "src": "2613:207:1", 808 | "stateMutability": "nonpayable", 809 | "virtual": false, 810 | "visibility": "external" 811 | } 812 | ], 813 | "scope": 57, 814 | "src": "411:2411:1", 815 | "usedErrors": [] 816 | } 817 | ], 818 | "src": "45:2778:1" 819 | }, 820 | "contractName": "IQuoter", 821 | "dependencies": [], 822 | "offset": [ 823 | 411, 824 | 2822 825 | ], 826 | "sha1": "ceb9e5faaa7a24c3d862871705d3893b833b0f25", 827 | "source": "// SPDX-License-Identifier: GPL-2.0-or-later\npragma solidity >=0.7.5;\npragma abicoder v2;\n\n/// @title Quoter Interface\n/// @notice Supports quoting the calculated amounts from exact input or exact output swaps\n/// @dev These functions are not marked view because they rely on calling non-view functions and reverting\n/// to compute the result. They are also not gas efficient and should not be called on-chain.\ninterface IQuoter {\n /// @notice Returns the amount out received for a given exact input swap without executing the swap\n /// @param path The path of the swap, i.e. each token pair and the pool fee\n /// @param amountIn The amount of the first token to swap\n /// @return amountOut The amount of the last token that would be received\n function quoteExactInput(bytes memory path, uint256 amountIn)\n external\n returns (uint256 amountOut);\n\n /// @notice Returns the amount out received for a given exact input but for a swap of a single pool\n /// @param tokenIn The token being swapped in\n /// @param tokenOut The token being swapped out\n /// @param fee The fee of the token pool to consider for the pair\n /// @param amountIn The desired input amount\n /// @param sqrtPriceLimitX96 The price limit of the pool that cannot be exceeded by the swap\n /// @return amountOut The amount of `tokenOut` that would be received\n function quoteExactInputSingle(\n address tokenIn,\n address tokenOut,\n uint24 fee,\n uint256 amountIn,\n uint160 sqrtPriceLimitX96\n ) external returns (uint256 amountOut);\n\n /// @notice Returns the amount in required for a given exact output swap without executing the swap\n /// @param path The path of the swap, i.e. each token pair and the pool fee. Path must be provided in reverse order\n /// @param amountOut The amount of the last token to receive\n /// @return amountIn The amount of first token required to be paid\n function quoteExactOutput(bytes memory path, uint256 amountOut)\n external\n returns (uint256 amountIn);\n\n /// @notice Returns the amount in required to receive the given exact output amount but for a swap of a single pool\n /// @param tokenIn The token being swapped in\n /// @param tokenOut The token being swapped out\n /// @param fee The fee of the token pool to consider for the pair\n /// @param amountOut The desired output amount\n /// @param sqrtPriceLimitX96 The price limit of the pool that cannot be exceeded by the swap\n /// @return amountIn The amount required as the input for the swap in order to receive `amountOut`\n function quoteExactOutputSingle(\n address tokenIn,\n address tokenOut,\n uint24 fee,\n uint256 amountOut,\n uint160 sqrtPriceLimitX96\n ) external returns (uint256 amountIn);\n}\n", 828 | "type": "interface" 829 | } -------------------------------------------------------------------------------- /front-end/README.md: -------------------------------------------------------------------------------- 1 | # Getting Started with Create React App 2 | 3 | This project was bootstrapped with [Create React App](https://github.com/facebook/create-react-app). 4 | 5 | ## Available Scripts 6 | 7 | In the project directory, you can run: 8 | 9 | ### `npm start` 10 | 11 | Runs the app in the development mode.\ 12 | Open [http://localhost:3000](http://localhost:3000) to view it in your browser. 13 | 14 | The page will reload when you make changes.\ 15 | You may also see any lint errors in the console. 16 | 17 | ### `npm test` 18 | 19 | Launches the test runner in the interactive watch mode.\ 20 | See the section about [running tests](https://facebook.github.io/create-react-app/docs/running-tests) for more information. 21 | 22 | ### `npm run build` 23 | 24 | Builds the app for production to the `build` folder.\ 25 | It correctly bundles React in production mode and optimizes the build for the best performance. 26 | 27 | The build is minified and the filenames include the hashes.\ 28 | Your app is ready to be deployed! 29 | 30 | See the section about [deployment](https://facebook.github.io/create-react-app/docs/deployment) for more information. 31 | 32 | ### `npm run eject` 33 | 34 | **Note: this is a one-way operation. Once you `eject`, you can't go back!** 35 | 36 | If you aren't satisfied with the build tool and configuration choices, you can `eject` at any time. This command will remove the single build dependency from your project. 37 | 38 | Instead, it will copy all the configuration files and the transitive dependencies (webpack, Babel, ESLint, etc) right into your project so you have full control over them. All of the commands except `eject` will still work, but they will point to the copied scripts so you can tweak them. At this point you're on your own. 39 | 40 | You don't have to ever use `eject`. The curated feature set is suitable for small and middle deployments, and you shouldn't feel obligated to use this feature. However we understand that this tool wouldn't be useful if you couldn't customize it when you are ready for it. 41 | 42 | ## Learn More 43 | 44 | You can learn more in the [Create React App documentation](https://facebook.github.io/create-react-app/docs/getting-started). 45 | 46 | To learn React, check out the [React documentation](https://reactjs.org/). 47 | 48 | ### Code Splitting 49 | 50 | This section has moved here: [https://facebook.github.io/create-react-app/docs/code-splitting](https://facebook.github.io/create-react-app/docs/code-splitting) 51 | 52 | ### Analyzing the Bundle Size 53 | 54 | This section has moved here: [https://facebook.github.io/create-react-app/docs/analyzing-the-bundle-size](https://facebook.github.io/create-react-app/docs/analyzing-the-bundle-size) 55 | 56 | ### Making a Progressive Web App 57 | 58 | This section has moved here: [https://facebook.github.io/create-react-app/docs/making-a-progressive-web-app](https://facebook.github.io/create-react-app/docs/making-a-progressive-web-app) 59 | 60 | ### Advanced Configuration 61 | 62 | This section has moved here: [https://facebook.github.io/create-react-app/docs/advanced-configuration](https://facebook.github.io/create-react-app/docs/advanced-configuration) 63 | 64 | ### Deployment 65 | 66 | This section has moved here: [https://facebook.github.io/create-react-app/docs/deployment](https://facebook.github.io/create-react-app/docs/deployment) 67 | 68 | ### `npm run build` fails to minify 69 | 70 | This section has moved here: [https://facebook.github.io/create-react-app/docs/troubleshooting#npm-run-build-fails-to-minify](https://facebook.github.io/create-react-app/docs/troubleshooting#npm-run-build-fails-to-minify) 71 | -------------------------------------------------------------------------------- /front-end/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "front-end", 3 | "version": "0.1.0", 4 | "private": true, 5 | "dependencies": { 6 | "@emotion/react": "^11.9.0", 7 | "@emotion/styled": "^11.8.1", 8 | "@mui/material": "^5.6.0", 9 | "@reduxjs/toolkit": "^1.8.1", 10 | "@testing-library/jest-dom": "^5.16.4", 11 | "@testing-library/react": "^12.1.4", 12 | "@testing-library/user-event": "^13.5.0", 13 | "bootstrap": "^5.1.3", 14 | "ethers": "^5.6.2", 15 | "framer-motion": "^6.2.9", 16 | "moment": "^2.29.3", 17 | "react": "^18.0.0", 18 | "react-bootstrap": "^2.2.3", 19 | "react-dom": "^18.0.0", 20 | "react-redux": "^7.2.8", 21 | "react-scripts": "5.0.0", 22 | "redux": "^4.1.2", 23 | "redux-persist": "^6.0.0", 24 | "styled-components": "^5.3.5", 25 | "web-vitals": "^2.1.4", 26 | "web3modal": "^1.9.6" 27 | }, 28 | "scripts": { 29 | "start": "react-scripts start", 30 | "build": "react-scripts build", 31 | "test": "react-scripts test", 32 | "eject": "react-scripts eject" 33 | }, 34 | "eslintConfig": { 35 | "extends": [ 36 | "react-app", 37 | "react-app/jest" 38 | ] 39 | }, 40 | "browserslist": { 41 | "production": [ 42 | ">0.2%", 43 | "not dead", 44 | "not op_mini all" 45 | ], 46 | "development": [ 47 | "last 1 chrome version", 48 | "last 1 firefox version", 49 | "last 1 safari version" 50 | ] 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /front-end/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kaymen99/Dex-aggregator/f9f1478ec780196f5b4248535bccbf05b513fcc3/front-end/public/favicon.ico -------------------------------------------------------------------------------- /front-end/public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 12 | 13 | 17 | 18 | 27 | React App 28 | 29 | 30 | 31 |
32 | 42 | 43 | 44 | -------------------------------------------------------------------------------- /front-end/public/logo192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kaymen99/Dex-aggregator/f9f1478ec780196f5b4248535bccbf05b513fcc3/front-end/public/logo192.png -------------------------------------------------------------------------------- /front-end/public/logo512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kaymen99/Dex-aggregator/f9f1478ec780196f5b4248535bccbf05b513fcc3/front-end/public/logo512.png -------------------------------------------------------------------------------- /front-end/public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "short_name": "React App", 3 | "name": "Create React App Sample", 4 | "icons": [ 5 | { 6 | "src": "favicon.ico", 7 | "sizes": "64x64 32x32 24x24 16x16", 8 | "type": "image/x-icon" 9 | }, 10 | { 11 | "src": "logo192.png", 12 | "type": "image/png", 13 | "sizes": "192x192" 14 | }, 15 | { 16 | "src": "logo512.png", 17 | "type": "image/png", 18 | "sizes": "512x512" 19 | } 20 | ], 21 | "start_url": ".", 22 | "display": "standalone", 23 | "theme_color": "#000000", 24 | "background_color": "#ffffff" 25 | } 26 | -------------------------------------------------------------------------------- /front-end/public/robots.txt: -------------------------------------------------------------------------------- 1 | # https://www.robotstxt.org/robotstxt.html 2 | User-agent: * 3 | Disallow: 4 | -------------------------------------------------------------------------------- /front-end/src/App.css: -------------------------------------------------------------------------------- 1 | .App { 2 | text-align: center; 3 | } 4 | 5 | .App-logo { 6 | height: 40vmin; 7 | pointer-events: none; 8 | } 9 | 10 | /* 11 | body { 12 | background: rgb(30, 30, 30) !important; 13 | } 14 | */ 15 | 16 | 17 | @media (prefers-reduced-motion: no-preference) { 18 | .App-logo { 19 | animation: App-logo-spin infinite 20s linear; 20 | } 21 | } 22 | 23 | .App-header { 24 | background-color: #282c34; 25 | min-height: 100vh; 26 | display: flex; 27 | flex-direction: column; 28 | align-items: center; 29 | justify-content: center; 30 | font-size: calc(10px + 2vmin); 31 | color: white; 32 | } 33 | 34 | .App-link { 35 | color: #61dafb; 36 | } 37 | 38 | @keyframes App-logo-spin { 39 | from { 40 | transform: rotate(0deg); 41 | } 42 | 43 | to { 44 | transform: rotate(360deg); 45 | } 46 | } -------------------------------------------------------------------------------- /front-end/src/App.js: -------------------------------------------------------------------------------- 1 | import './App.css'; 2 | import Main from "./components/Main"; 3 | import Swap from './components/Swap'; 4 | 5 | function App() { 6 | 7 | return ( 8 |
9 | 10 |
11 |
12 |

Multi-Chain Dex Aggregator

13 |
14 | 15 |
16 | ); 17 | } 18 | 19 | export default App; 20 | 21 | -------------------------------------------------------------------------------- /front-end/src/App.test.js: -------------------------------------------------------------------------------- 1 | import { render, screen } from '@testing-library/react'; 2 | import App from './App'; 3 | 4 | test('renders learn react link', () => { 5 | render(); 6 | const linkElement = screen.getByText(/learn react/i); 7 | expect(linkElement).toBeInTheDocument(); 8 | }); 9 | -------------------------------------------------------------------------------- /front-end/src/artifacts/interfaces/IQuoter.json: -------------------------------------------------------------------------------- 1 | { 2 | "abi": [ 3 | { 4 | "inputs": [ 5 | { 6 | "internalType": "bytes", 7 | "name": "path", 8 | "type": "bytes" 9 | }, 10 | { 11 | "internalType": "uint256", 12 | "name": "amountIn", 13 | "type": "uint256" 14 | } 15 | ], 16 | "name": "quoteExactInput", 17 | "outputs": [ 18 | { 19 | "internalType": "uint256", 20 | "name": "amountOut", 21 | "type": "uint256" 22 | } 23 | ], 24 | "stateMutability": "nonpayable", 25 | "type": "function" 26 | }, 27 | { 28 | "inputs": [ 29 | { 30 | "internalType": "address", 31 | "name": "tokenIn", 32 | "type": "address" 33 | }, 34 | { 35 | "internalType": "address", 36 | "name": "tokenOut", 37 | "type": "address" 38 | }, 39 | { 40 | "internalType": "uint24", 41 | "name": "fee", 42 | "type": "uint24" 43 | }, 44 | { 45 | "internalType": "uint256", 46 | "name": "amountIn", 47 | "type": "uint256" 48 | }, 49 | { 50 | "internalType": "uint160", 51 | "name": "sqrtPriceLimitX96", 52 | "type": "uint160" 53 | } 54 | ], 55 | "name": "quoteExactInputSingle", 56 | "outputs": [ 57 | { 58 | "internalType": "uint256", 59 | "name": "amountOut", 60 | "type": "uint256" 61 | } 62 | ], 63 | "stateMutability": "nonpayable", 64 | "type": "function" 65 | }, 66 | { 67 | "inputs": [ 68 | { 69 | "internalType": "bytes", 70 | "name": "path", 71 | "type": "bytes" 72 | }, 73 | { 74 | "internalType": "uint256", 75 | "name": "amountOut", 76 | "type": "uint256" 77 | } 78 | ], 79 | "name": "quoteExactOutput", 80 | "outputs": [ 81 | { 82 | "internalType": "uint256", 83 | "name": "amountIn", 84 | "type": "uint256" 85 | } 86 | ], 87 | "stateMutability": "nonpayable", 88 | "type": "function" 89 | }, 90 | { 91 | "inputs": [ 92 | { 93 | "internalType": "address", 94 | "name": "tokenIn", 95 | "type": "address" 96 | }, 97 | { 98 | "internalType": "address", 99 | "name": "tokenOut", 100 | "type": "address" 101 | }, 102 | { 103 | "internalType": "uint24", 104 | "name": "fee", 105 | "type": "uint24" 106 | }, 107 | { 108 | "internalType": "uint256", 109 | "name": "amountOut", 110 | "type": "uint256" 111 | }, 112 | { 113 | "internalType": "uint160", 114 | "name": "sqrtPriceLimitX96", 115 | "type": "uint160" 116 | } 117 | ], 118 | "name": "quoteExactOutputSingle", 119 | "outputs": [ 120 | { 121 | "internalType": "uint256", 122 | "name": "amountIn", 123 | "type": "uint256" 124 | } 125 | ], 126 | "stateMutability": "nonpayable", 127 | "type": "function" 128 | } 129 | ], 130 | "ast": { 131 | "absolutePath": "interfaces/IQouter.sol", 132 | "exportedSymbols": { 133 | "IQuoter": [ 134 | 56 135 | ] 136 | }, 137 | "id": 57, 138 | "license": "GPL-2.0-or-later", 139 | "nodeType": "SourceUnit", 140 | "nodes": [ 141 | { 142 | "id": 1, 143 | "literals": [ 144 | "solidity", 145 | ">=", 146 | "0.7", 147 | ".5" 148 | ], 149 | "nodeType": "PragmaDirective", 150 | "src": "45:24:1" 151 | }, 152 | { 153 | "id": 2, 154 | "literals": [ 155 | "abicoder", 156 | "v2" 157 | ], 158 | "nodeType": "PragmaDirective", 159 | "src": "70:19:1" 160 | }, 161 | { 162 | "abstract": false, 163 | "baseContracts": [], 164 | "canonicalName": "IQuoter", 165 | "contractDependencies": [], 166 | "contractKind": "interface", 167 | "documentation": { 168 | "id": 3, 169 | "nodeType": "StructuredDocumentation", 170 | "src": "91:320:1", 171 | "text": "@title Quoter Interface\n @notice Supports quoting the calculated amounts from exact input or exact output swaps\n @dev These functions are not marked view because they rely on calling non-view functions and reverting\n to compute the result. They are also not gas efficient and should not be called on-chain." 172 | }, 173 | "fullyImplemented": false, 174 | "id": 56, 175 | "linearizedBaseContracts": [ 176 | 56 177 | ], 178 | "name": "IQuoter", 179 | "nameLocation": "421:7:1", 180 | "nodeType": "ContractDefinition", 181 | "nodes": [ 182 | { 183 | "documentation": { 184 | "id": 4, 185 | "nodeType": "StructuredDocumentation", 186 | "src": "435:319:1", 187 | "text": "@notice Returns the amount out received for a given exact input swap without executing the swap\n @param path The path of the swap, i.e. each token pair and the pool fee\n @param amountIn The amount of the first token to swap\n @return amountOut The amount of the last token that would be received" 188 | }, 189 | "functionSelector": "cdca1753", 190 | "id": 13, 191 | "implemented": false, 192 | "kind": "function", 193 | "modifiers": [], 194 | "name": "quoteExactInput", 195 | "nameLocation": "768:15:1", 196 | "nodeType": "FunctionDefinition", 197 | "parameters": { 198 | "id": 9, 199 | "nodeType": "ParameterList", 200 | "parameters": [ 201 | { 202 | "constant": false, 203 | "id": 6, 204 | "mutability": "mutable", 205 | "name": "path", 206 | "nameLocation": "797:4:1", 207 | "nodeType": "VariableDeclaration", 208 | "scope": 13, 209 | "src": "784:17:1", 210 | "stateVariable": false, 211 | "storageLocation": "memory", 212 | "typeDescriptions": { 213 | "typeIdentifier": "t_bytes_memory_ptr", 214 | "typeString": "bytes" 215 | }, 216 | "typeName": { 217 | "id": 5, 218 | "name": "bytes", 219 | "nodeType": "ElementaryTypeName", 220 | "src": "784:5:1", 221 | "typeDescriptions": { 222 | "typeIdentifier": "t_bytes_storage_ptr", 223 | "typeString": "bytes" 224 | } 225 | }, 226 | "visibility": "internal" 227 | }, 228 | { 229 | "constant": false, 230 | "id": 8, 231 | "mutability": "mutable", 232 | "name": "amountIn", 233 | "nameLocation": "811:8:1", 234 | "nodeType": "VariableDeclaration", 235 | "scope": 13, 236 | "src": "803:16:1", 237 | "stateVariable": false, 238 | "storageLocation": "default", 239 | "typeDescriptions": { 240 | "typeIdentifier": "t_uint256", 241 | "typeString": "uint256" 242 | }, 243 | "typeName": { 244 | "id": 7, 245 | "name": "uint256", 246 | "nodeType": "ElementaryTypeName", 247 | "src": "803:7:1", 248 | "typeDescriptions": { 249 | "typeIdentifier": "t_uint256", 250 | "typeString": "uint256" 251 | } 252 | }, 253 | "visibility": "internal" 254 | } 255 | ], 256 | "src": "783:37:1" 257 | }, 258 | "returnParameters": { 259 | "id": 12, 260 | "nodeType": "ParameterList", 261 | "parameters": [ 262 | { 263 | "constant": false, 264 | "id": 11, 265 | "mutability": "mutable", 266 | "name": "amountOut", 267 | "nameLocation": "863:9:1", 268 | "nodeType": "VariableDeclaration", 269 | "scope": 13, 270 | "src": "855:17:1", 271 | "stateVariable": false, 272 | "storageLocation": "default", 273 | "typeDescriptions": { 274 | "typeIdentifier": "t_uint256", 275 | "typeString": "uint256" 276 | }, 277 | "typeName": { 278 | "id": 10, 279 | "name": "uint256", 280 | "nodeType": "ElementaryTypeName", 281 | "src": "855:7:1", 282 | "typeDescriptions": { 283 | "typeIdentifier": "t_uint256", 284 | "typeString": "uint256" 285 | } 286 | }, 287 | "visibility": "internal" 288 | } 289 | ], 290 | "src": "854:19:1" 291 | }, 292 | "scope": 56, 293 | "src": "759:115:1", 294 | "stateMutability": "nonpayable", 295 | "virtual": false, 296 | "visibility": "external" 297 | }, 298 | { 299 | "documentation": { 300 | "id": 14, 301 | "nodeType": "StructuredDocumentation", 302 | "src": "880:491:1", 303 | "text": "@notice Returns the amount out received for a given exact input but for a swap of a single pool\n @param tokenIn The token being swapped in\n @param tokenOut The token being swapped out\n @param fee The fee of the token pool to consider for the pair\n @param amountIn The desired input amount\n @param sqrtPriceLimitX96 The price limit of the pool that cannot be exceeded by the swap\n @return amountOut The amount of `tokenOut` that would be received" 304 | }, 305 | "functionSelector": "f7729d43", 306 | "id": 29, 307 | "implemented": false, 308 | "kind": "function", 309 | "modifiers": [], 310 | "name": "quoteExactInputSingle", 311 | "nameLocation": "1385:21:1", 312 | "nodeType": "FunctionDefinition", 313 | "parameters": { 314 | "id": 25, 315 | "nodeType": "ParameterList", 316 | "parameters": [ 317 | { 318 | "constant": false, 319 | "id": 16, 320 | "mutability": "mutable", 321 | "name": "tokenIn", 322 | "nameLocation": "1424:7:1", 323 | "nodeType": "VariableDeclaration", 324 | "scope": 29, 325 | "src": "1416:15:1", 326 | "stateVariable": false, 327 | "storageLocation": "default", 328 | "typeDescriptions": { 329 | "typeIdentifier": "t_address", 330 | "typeString": "address" 331 | }, 332 | "typeName": { 333 | "id": 15, 334 | "name": "address", 335 | "nodeType": "ElementaryTypeName", 336 | "src": "1416:7:1", 337 | "stateMutability": "nonpayable", 338 | "typeDescriptions": { 339 | "typeIdentifier": "t_address", 340 | "typeString": "address" 341 | } 342 | }, 343 | "visibility": "internal" 344 | }, 345 | { 346 | "constant": false, 347 | "id": 18, 348 | "mutability": "mutable", 349 | "name": "tokenOut", 350 | "nameLocation": "1449:8:1", 351 | "nodeType": "VariableDeclaration", 352 | "scope": 29, 353 | "src": "1441:16:1", 354 | "stateVariable": false, 355 | "storageLocation": "default", 356 | "typeDescriptions": { 357 | "typeIdentifier": "t_address", 358 | "typeString": "address" 359 | }, 360 | "typeName": { 361 | "id": 17, 362 | "name": "address", 363 | "nodeType": "ElementaryTypeName", 364 | "src": "1441:7:1", 365 | "stateMutability": "nonpayable", 366 | "typeDescriptions": { 367 | "typeIdentifier": "t_address", 368 | "typeString": "address" 369 | } 370 | }, 371 | "visibility": "internal" 372 | }, 373 | { 374 | "constant": false, 375 | "id": 20, 376 | "mutability": "mutable", 377 | "name": "fee", 378 | "nameLocation": "1474:3:1", 379 | "nodeType": "VariableDeclaration", 380 | "scope": 29, 381 | "src": "1467:10:1", 382 | "stateVariable": false, 383 | "storageLocation": "default", 384 | "typeDescriptions": { 385 | "typeIdentifier": "t_uint24", 386 | "typeString": "uint24" 387 | }, 388 | "typeName": { 389 | "id": 19, 390 | "name": "uint24", 391 | "nodeType": "ElementaryTypeName", 392 | "src": "1467:6:1", 393 | "typeDescriptions": { 394 | "typeIdentifier": "t_uint24", 395 | "typeString": "uint24" 396 | } 397 | }, 398 | "visibility": "internal" 399 | }, 400 | { 401 | "constant": false, 402 | "id": 22, 403 | "mutability": "mutable", 404 | "name": "amountIn", 405 | "nameLocation": "1495:8:1", 406 | "nodeType": "VariableDeclaration", 407 | "scope": 29, 408 | "src": "1487:16:1", 409 | "stateVariable": false, 410 | "storageLocation": "default", 411 | "typeDescriptions": { 412 | "typeIdentifier": "t_uint256", 413 | "typeString": "uint256" 414 | }, 415 | "typeName": { 416 | "id": 21, 417 | "name": "uint256", 418 | "nodeType": "ElementaryTypeName", 419 | "src": "1487:7:1", 420 | "typeDescriptions": { 421 | "typeIdentifier": "t_uint256", 422 | "typeString": "uint256" 423 | } 424 | }, 425 | "visibility": "internal" 426 | }, 427 | { 428 | "constant": false, 429 | "id": 24, 430 | "mutability": "mutable", 431 | "name": "sqrtPriceLimitX96", 432 | "nameLocation": "1521:17:1", 433 | "nodeType": "VariableDeclaration", 434 | "scope": 29, 435 | "src": "1513:25:1", 436 | "stateVariable": false, 437 | "storageLocation": "default", 438 | "typeDescriptions": { 439 | "typeIdentifier": "t_uint160", 440 | "typeString": "uint160" 441 | }, 442 | "typeName": { 443 | "id": 23, 444 | "name": "uint160", 445 | "nodeType": "ElementaryTypeName", 446 | "src": "1513:7:1", 447 | "typeDescriptions": { 448 | "typeIdentifier": "t_uint160", 449 | "typeString": "uint160" 450 | } 451 | }, 452 | "visibility": "internal" 453 | } 454 | ], 455 | "src": "1406:138:1" 456 | }, 457 | "returnParameters": { 458 | "id": 28, 459 | "nodeType": "ParameterList", 460 | "parameters": [ 461 | { 462 | "constant": false, 463 | "id": 27, 464 | "mutability": "mutable", 465 | "name": "amountOut", 466 | "nameLocation": "1571:9:1", 467 | "nodeType": "VariableDeclaration", 468 | "scope": 29, 469 | "src": "1563:17:1", 470 | "stateVariable": false, 471 | "storageLocation": "default", 472 | "typeDescriptions": { 473 | "typeIdentifier": "t_uint256", 474 | "typeString": "uint256" 475 | }, 476 | "typeName": { 477 | "id": 26, 478 | "name": "uint256", 479 | "nodeType": "ElementaryTypeName", 480 | "src": "1563:7:1", 481 | "typeDescriptions": { 482 | "typeIdentifier": "t_uint256", 483 | "typeString": "uint256" 484 | } 485 | }, 486 | "visibility": "internal" 487 | } 488 | ], 489 | "src": "1562:19:1" 490 | }, 491 | "scope": 56, 492 | "src": "1376:206:1", 493 | "stateMutability": "nonpayable", 494 | "virtual": false, 495 | "visibility": "external" 496 | }, 497 | { 498 | "documentation": { 499 | "id": 30, 500 | "nodeType": "StructuredDocumentation", 501 | "src": "1588:355:1", 502 | "text": "@notice Returns the amount in required for a given exact output swap without executing the swap\n @param path The path of the swap, i.e. each token pair and the pool fee. Path must be provided in reverse order\n @param amountOut The amount of the last token to receive\n @return amountIn The amount of first token required to be paid" 503 | }, 504 | "functionSelector": "2f80bb1d", 505 | "id": 39, 506 | "implemented": false, 507 | "kind": "function", 508 | "modifiers": [], 509 | "name": "quoteExactOutput", 510 | "nameLocation": "1957:16:1", 511 | "nodeType": "FunctionDefinition", 512 | "parameters": { 513 | "id": 35, 514 | "nodeType": "ParameterList", 515 | "parameters": [ 516 | { 517 | "constant": false, 518 | "id": 32, 519 | "mutability": "mutable", 520 | "name": "path", 521 | "nameLocation": "1987:4:1", 522 | "nodeType": "VariableDeclaration", 523 | "scope": 39, 524 | "src": "1974:17:1", 525 | "stateVariable": false, 526 | "storageLocation": "memory", 527 | "typeDescriptions": { 528 | "typeIdentifier": "t_bytes_memory_ptr", 529 | "typeString": "bytes" 530 | }, 531 | "typeName": { 532 | "id": 31, 533 | "name": "bytes", 534 | "nodeType": "ElementaryTypeName", 535 | "src": "1974:5:1", 536 | "typeDescriptions": { 537 | "typeIdentifier": "t_bytes_storage_ptr", 538 | "typeString": "bytes" 539 | } 540 | }, 541 | "visibility": "internal" 542 | }, 543 | { 544 | "constant": false, 545 | "id": 34, 546 | "mutability": "mutable", 547 | "name": "amountOut", 548 | "nameLocation": "2001:9:1", 549 | "nodeType": "VariableDeclaration", 550 | "scope": 39, 551 | "src": "1993:17:1", 552 | "stateVariable": false, 553 | "storageLocation": "default", 554 | "typeDescriptions": { 555 | "typeIdentifier": "t_uint256", 556 | "typeString": "uint256" 557 | }, 558 | "typeName": { 559 | "id": 33, 560 | "name": "uint256", 561 | "nodeType": "ElementaryTypeName", 562 | "src": "1993:7:1", 563 | "typeDescriptions": { 564 | "typeIdentifier": "t_uint256", 565 | "typeString": "uint256" 566 | } 567 | }, 568 | "visibility": "internal" 569 | } 570 | ], 571 | "src": "1973:38:1" 572 | }, 573 | "returnParameters": { 574 | "id": 38, 575 | "nodeType": "ParameterList", 576 | "parameters": [ 577 | { 578 | "constant": false, 579 | "id": 37, 580 | "mutability": "mutable", 581 | "name": "amountIn", 582 | "nameLocation": "2054:8:1", 583 | "nodeType": "VariableDeclaration", 584 | "scope": 39, 585 | "src": "2046:16:1", 586 | "stateVariable": false, 587 | "storageLocation": "default", 588 | "typeDescriptions": { 589 | "typeIdentifier": "t_uint256", 590 | "typeString": "uint256" 591 | }, 592 | "typeName": { 593 | "id": 36, 594 | "name": "uint256", 595 | "nodeType": "ElementaryTypeName", 596 | "src": "2046:7:1", 597 | "typeDescriptions": { 598 | "typeIdentifier": "t_uint256", 599 | "typeString": "uint256" 600 | } 601 | }, 602 | "visibility": "internal" 603 | } 604 | ], 605 | "src": "2045:18:1" 606 | }, 607 | "scope": 56, 608 | "src": "1948:116:1", 609 | "stateMutability": "nonpayable", 610 | "virtual": false, 611 | "visibility": "external" 612 | }, 613 | { 614 | "documentation": { 615 | "id": 40, 616 | "nodeType": "StructuredDocumentation", 617 | "src": "2070:538:1", 618 | "text": "@notice Returns the amount in required to receive the given exact output amount but for a swap of a single pool\n @param tokenIn The token being swapped in\n @param tokenOut The token being swapped out\n @param fee The fee of the token pool to consider for the pair\n @param amountOut The desired output amount\n @param sqrtPriceLimitX96 The price limit of the pool that cannot be exceeded by the swap\n @return amountIn The amount required as the input for the swap in order to receive `amountOut`" 619 | }, 620 | "functionSelector": "30d07f21", 621 | "id": 55, 622 | "implemented": false, 623 | "kind": "function", 624 | "modifiers": [], 625 | "name": "quoteExactOutputSingle", 626 | "nameLocation": "2622:22:1", 627 | "nodeType": "FunctionDefinition", 628 | "parameters": { 629 | "id": 51, 630 | "nodeType": "ParameterList", 631 | "parameters": [ 632 | { 633 | "constant": false, 634 | "id": 42, 635 | "mutability": "mutable", 636 | "name": "tokenIn", 637 | "nameLocation": "2662:7:1", 638 | "nodeType": "VariableDeclaration", 639 | "scope": 55, 640 | "src": "2654:15:1", 641 | "stateVariable": false, 642 | "storageLocation": "default", 643 | "typeDescriptions": { 644 | "typeIdentifier": "t_address", 645 | "typeString": "address" 646 | }, 647 | "typeName": { 648 | "id": 41, 649 | "name": "address", 650 | "nodeType": "ElementaryTypeName", 651 | "src": "2654:7:1", 652 | "stateMutability": "nonpayable", 653 | "typeDescriptions": { 654 | "typeIdentifier": "t_address", 655 | "typeString": "address" 656 | } 657 | }, 658 | "visibility": "internal" 659 | }, 660 | { 661 | "constant": false, 662 | "id": 44, 663 | "mutability": "mutable", 664 | "name": "tokenOut", 665 | "nameLocation": "2687:8:1", 666 | "nodeType": "VariableDeclaration", 667 | "scope": 55, 668 | "src": "2679:16:1", 669 | "stateVariable": false, 670 | "storageLocation": "default", 671 | "typeDescriptions": { 672 | "typeIdentifier": "t_address", 673 | "typeString": "address" 674 | }, 675 | "typeName": { 676 | "id": 43, 677 | "name": "address", 678 | "nodeType": "ElementaryTypeName", 679 | "src": "2679:7:1", 680 | "stateMutability": "nonpayable", 681 | "typeDescriptions": { 682 | "typeIdentifier": "t_address", 683 | "typeString": "address" 684 | } 685 | }, 686 | "visibility": "internal" 687 | }, 688 | { 689 | "constant": false, 690 | "id": 46, 691 | "mutability": "mutable", 692 | "name": "fee", 693 | "nameLocation": "2712:3:1", 694 | "nodeType": "VariableDeclaration", 695 | "scope": 55, 696 | "src": "2705:10:1", 697 | "stateVariable": false, 698 | "storageLocation": "default", 699 | "typeDescriptions": { 700 | "typeIdentifier": "t_uint24", 701 | "typeString": "uint24" 702 | }, 703 | "typeName": { 704 | "id": 45, 705 | "name": "uint24", 706 | "nodeType": "ElementaryTypeName", 707 | "src": "2705:6:1", 708 | "typeDescriptions": { 709 | "typeIdentifier": "t_uint24", 710 | "typeString": "uint24" 711 | } 712 | }, 713 | "visibility": "internal" 714 | }, 715 | { 716 | "constant": false, 717 | "id": 48, 718 | "mutability": "mutable", 719 | "name": "amountOut", 720 | "nameLocation": "2733:9:1", 721 | "nodeType": "VariableDeclaration", 722 | "scope": 55, 723 | "src": "2725:17:1", 724 | "stateVariable": false, 725 | "storageLocation": "default", 726 | "typeDescriptions": { 727 | "typeIdentifier": "t_uint256", 728 | "typeString": "uint256" 729 | }, 730 | "typeName": { 731 | "id": 47, 732 | "name": "uint256", 733 | "nodeType": "ElementaryTypeName", 734 | "src": "2725:7:1", 735 | "typeDescriptions": { 736 | "typeIdentifier": "t_uint256", 737 | "typeString": "uint256" 738 | } 739 | }, 740 | "visibility": "internal" 741 | }, 742 | { 743 | "constant": false, 744 | "id": 50, 745 | "mutability": "mutable", 746 | "name": "sqrtPriceLimitX96", 747 | "nameLocation": "2760:17:1", 748 | "nodeType": "VariableDeclaration", 749 | "scope": 55, 750 | "src": "2752:25:1", 751 | "stateVariable": false, 752 | "storageLocation": "default", 753 | "typeDescriptions": { 754 | "typeIdentifier": "t_uint160", 755 | "typeString": "uint160" 756 | }, 757 | "typeName": { 758 | "id": 49, 759 | "name": "uint160", 760 | "nodeType": "ElementaryTypeName", 761 | "src": "2752:7:1", 762 | "typeDescriptions": { 763 | "typeIdentifier": "t_uint160", 764 | "typeString": "uint160" 765 | } 766 | }, 767 | "visibility": "internal" 768 | } 769 | ], 770 | "src": "2644:139:1" 771 | }, 772 | "returnParameters": { 773 | "id": 54, 774 | "nodeType": "ParameterList", 775 | "parameters": [ 776 | { 777 | "constant": false, 778 | "id": 53, 779 | "mutability": "mutable", 780 | "name": "amountIn", 781 | "nameLocation": "2810:8:1", 782 | "nodeType": "VariableDeclaration", 783 | "scope": 55, 784 | "src": "2802:16:1", 785 | "stateVariable": false, 786 | "storageLocation": "default", 787 | "typeDescriptions": { 788 | "typeIdentifier": "t_uint256", 789 | "typeString": "uint256" 790 | }, 791 | "typeName": { 792 | "id": 52, 793 | "name": "uint256", 794 | "nodeType": "ElementaryTypeName", 795 | "src": "2802:7:1", 796 | "typeDescriptions": { 797 | "typeIdentifier": "t_uint256", 798 | "typeString": "uint256" 799 | } 800 | }, 801 | "visibility": "internal" 802 | } 803 | ], 804 | "src": "2801:18:1" 805 | }, 806 | "scope": 56, 807 | "src": "2613:207:1", 808 | "stateMutability": "nonpayable", 809 | "virtual": false, 810 | "visibility": "external" 811 | } 812 | ], 813 | "scope": 57, 814 | "src": "411:2411:1", 815 | "usedErrors": [] 816 | } 817 | ], 818 | "src": "45:2778:1" 819 | }, 820 | "contractName": "IQuoter", 821 | "dependencies": [], 822 | "offset": [ 823 | 411, 824 | 2822 825 | ], 826 | "sha1": "ceb9e5faaa7a24c3d862871705d3893b833b0f25", 827 | "source": "// SPDX-License-Identifier: GPL-2.0-or-later\npragma solidity >=0.7.5;\npragma abicoder v2;\n\n/// @title Quoter Interface\n/// @notice Supports quoting the calculated amounts from exact input or exact output swaps\n/// @dev These functions are not marked view because they rely on calling non-view functions and reverting\n/// to compute the result. They are also not gas efficient and should not be called on-chain.\ninterface IQuoter {\n /// @notice Returns the amount out received for a given exact input swap without executing the swap\n /// @param path The path of the swap, i.e. each token pair and the pool fee\n /// @param amountIn The amount of the first token to swap\n /// @return amountOut The amount of the last token that would be received\n function quoteExactInput(bytes memory path, uint256 amountIn)\n external\n returns (uint256 amountOut);\n\n /// @notice Returns the amount out received for a given exact input but for a swap of a single pool\n /// @param tokenIn The token being swapped in\n /// @param tokenOut The token being swapped out\n /// @param fee The fee of the token pool to consider for the pair\n /// @param amountIn The desired input amount\n /// @param sqrtPriceLimitX96 The price limit of the pool that cannot be exceeded by the swap\n /// @return amountOut The amount of `tokenOut` that would be received\n function quoteExactInputSingle(\n address tokenIn,\n address tokenOut,\n uint24 fee,\n uint256 amountIn,\n uint160 sqrtPriceLimitX96\n ) external returns (uint256 amountOut);\n\n /// @notice Returns the amount in required for a given exact output swap without executing the swap\n /// @param path The path of the swap, i.e. each token pair and the pool fee. Path must be provided in reverse order\n /// @param amountOut The amount of the last token to receive\n /// @return amountIn The amount of first token required to be paid\n function quoteExactOutput(bytes memory path, uint256 amountOut)\n external\n returns (uint256 amountIn);\n\n /// @notice Returns the amount in required to receive the given exact output amount but for a swap of a single pool\n /// @param tokenIn The token being swapped in\n /// @param tokenOut The token being swapped out\n /// @param fee The fee of the token pool to consider for the pair\n /// @param amountOut The desired output amount\n /// @param sqrtPriceLimitX96 The price limit of the pool that cannot be exceeded by the swap\n /// @return amountIn The amount required as the input for the swap in order to receive `amountOut`\n function quoteExactOutputSingle(\n address tokenIn,\n address tokenOut,\n uint24 fee,\n uint256 amountOut,\n uint160 sqrtPriceLimitX96\n ) external returns (uint256 amountIn);\n}\n", 828 | "type": "interface" 829 | } -------------------------------------------------------------------------------- /front-end/src/assets/css/styles.css: -------------------------------------------------------------------------------- 1 | /* header */ 2 | 3 | .header { 4 | width: 100%; 5 | position: relative; 6 | padding-bottom: 2rem; 7 | } 8 | 9 | .header-container { 10 | width: 80%; 11 | min-height: 65vh; 12 | margin: 0 auto; 13 | display: flex; 14 | justify-content: center; 15 | align-items: center; 16 | } 17 | 18 | .header-box { 19 | width: 50%; 20 | height: 100%; 21 | display: flex; 22 | flex-direction: column; 23 | justify-content: center; 24 | align-items: center; 25 | } 26 | 27 | #window { 28 | width: 500px; 29 | margin-top: 50px; 30 | background-color: rgb(81, 76, 76); 31 | color: #fff; 32 | padding: 15px; 33 | border-radius: 20px; 34 | box-shadow: 0 0 5px black; 35 | } 36 | 37 | .swapbox_select { 38 | width: 70%; 39 | float: left; 40 | } 41 | 42 | .swapbox { 43 | overflow: auto; 44 | margin: 20px 0; 45 | padding: 20px; 46 | background-color: #2f2f2f; 47 | border-radius: 20px; 48 | border: 1px solid #565656; 49 | } 50 | 51 | .token_select { 52 | padding: 5px 0; 53 | width: 30%; 54 | } 55 | 56 | .token_select:hover { 57 | background-color: #464646; 58 | cursor: pointer; 59 | } 60 | 61 | .token_row { 62 | padding: 5px 10px; 63 | } 64 | 65 | .token_img { 66 | height: 30px; 67 | } 68 | 69 | .token_text { 70 | padding: 10px; 71 | } 72 | 73 | .token_row:hover { 74 | background-color: #e4e4e4; 75 | cursor: pointer; 76 | } 77 | 78 | .gas_estimate_label { 79 | padding-bottom: 10px; 80 | } 81 | 82 | .modal-body { 83 | overflow: scroll; 84 | } 85 | 86 | @media (max-width: 64em) { 87 | .header-container { 88 | flex-direction: column; 89 | width: 100%; 90 | } 91 | 92 | #window { 93 | width: 400px; 94 | margin-bottom: 35px; 95 | } 96 | } 97 | 98 | @media (max-width: 32em) { 99 | .header-container { 100 | flex-direction: column; 101 | width: 100%; 102 | } 103 | 104 | .header-box { 105 | width: 100%; 106 | } 107 | 108 | #window { 109 | width: 350px; 110 | margin-bottom: 35px; 111 | } 112 | 113 | .token_img { 114 | height: 25px; 115 | } 116 | } 117 | -------------------------------------------------------------------------------- /front-end/src/assets/images/aave.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kaymen99/Dex-aggregator/f9f1478ec780196f5b4248535bccbf05b513fcc3/front-end/src/assets/images/aave.png -------------------------------------------------------------------------------- /front-end/src/assets/images/bnb.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kaymen99/Dex-aggregator/f9f1478ec780196f5b4248535bccbf05b513fcc3/front-end/src/assets/images/bnb.png -------------------------------------------------------------------------------- /front-end/src/assets/images/crv.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kaymen99/Dex-aggregator/f9f1478ec780196f5b4248535bccbf05b513fcc3/front-end/src/assets/images/crv.png -------------------------------------------------------------------------------- /front-end/src/assets/images/dai.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kaymen99/Dex-aggregator/f9f1478ec780196f5b4248535bccbf05b513fcc3/front-end/src/assets/images/dai.png -------------------------------------------------------------------------------- /front-end/src/assets/images/etherLogo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kaymen99/Dex-aggregator/f9f1478ec780196f5b4248535bccbf05b513fcc3/front-end/src/assets/images/etherLogo.png -------------------------------------------------------------------------------- /front-end/src/assets/images/link.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kaymen99/Dex-aggregator/f9f1478ec780196f5b4248535bccbf05b513fcc3/front-end/src/assets/images/link.png -------------------------------------------------------------------------------- /front-end/src/assets/images/matic.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kaymen99/Dex-aggregator/f9f1478ec780196f5b4248535bccbf05b513fcc3/front-end/src/assets/images/matic.png -------------------------------------------------------------------------------- /front-end/src/assets/images/uni.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kaymen99/Dex-aggregator/f9f1478ec780196f5b4248535bccbf05b513fcc3/front-end/src/assets/images/uni.jpg -------------------------------------------------------------------------------- /front-end/src/assets/images/usdc.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kaymen99/Dex-aggregator/f9f1478ec780196f5b4248535bccbf05b513fcc3/front-end/src/assets/images/usdc.png -------------------------------------------------------------------------------- /front-end/src/assets/images/usdt.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kaymen99/Dex-aggregator/f9f1478ec780196f5b4248535bccbf05b513fcc3/front-end/src/assets/images/usdt.png -------------------------------------------------------------------------------- /front-end/src/components/Account.js: -------------------------------------------------------------------------------- 1 | import React, { useState, useEffect } from 'react' 2 | import { useDispatch, useSelector } from "react-redux" 3 | import { updateAccountData, disconnect } from "../features/blockchain" 4 | import { ethers, utils } from "ethers" 5 | import { Modal } from "react-bootstrap" 6 | import { Button } from "@mui/material" 7 | import Web3Modal from "web3modal" 8 | import networks from "../utils/networksMap.json"; 9 | 10 | 11 | const eth = window.ethereum 12 | let web3Modal = new Web3Modal() 13 | 14 | function Account() { 15 | const dispatch = useDispatch() 16 | const data = useSelector((state) => state.blockchain.value) 17 | 18 | const [injectedProvider, setInjectedProvider] = useState(); 19 | const [show, setShow] = useState(false); 20 | 21 | const handleClose = () => setShow(false); 22 | const handleShow = () => setShow(true); 23 | 24 | async function fetchAccountData() { 25 | if (typeof window.ethereum !== 'undefined') { 26 | const connection = await web3Modal.connect() 27 | const provider = new ethers.providers.Web3Provider(connection) 28 | 29 | setInjectedProvider(provider); 30 | 31 | const signer = provider.getSigner() 32 | const chainId = await provider.getNetwork() 33 | const account = await signer.getAddress() 34 | const balance = await signer.getBalance() 35 | 36 | dispatch(updateAccountData( 37 | { 38 | account: account, 39 | balance: utils.formatUnits(balance), 40 | network: networks[String(chainId.chainId)] 41 | } 42 | )) 43 | } 44 | else { 45 | console.log("Please install metamask") 46 | window.alert("Please Install Metamask") 47 | } 48 | } 49 | 50 | async function Disconnect() { 51 | web3Modal.clearCachedProvider(); 52 | if (injectedProvider && injectedProvider.provider && typeof injectedProvider.provider.disconnect == "function") { 53 | await injectedProvider.provider.disconnect(); 54 | setInjectedProvider(null) 55 | } 56 | dispatch(disconnect()) 57 | setShow(false) 58 | } 59 | 60 | useEffect(() => { 61 | if (eth) { 62 | eth.on('chainChanged', (chainId) => { 63 | fetchAccountData() 64 | }) 65 | eth.on('accountsChanged', (accounts) => { 66 | fetchAccountData() 67 | }) 68 | } 69 | }, []) 70 | 71 | const isConnected = data.account !== "" 72 | 73 | return ( 74 | 75 |
76 | {isConnected ? ( 77 | <> 78 | 89 | 90 | 91 | User 92 | 93 | 94 |

Account: {data.account}

95 |

Balance: {data.balance && parseFloat(data.balance).toFixed(4)} ETH

96 |

Network: {data.network}

97 |
98 | 99 | 102 | 103 |
104 | 105 | ) : ( 106 | 114 | )} 115 |
116 | ) 117 | } 118 | 119 | export default Account; 120 | 121 | 122 | 123 | 124 | 125 | -------------------------------------------------------------------------------- /front-end/src/components/Exchanges.js: -------------------------------------------------------------------------------- 1 | import React, { useEffect, useState } from 'react' 2 | import { ethers, utils } from 'ethers'; 3 | import { Table } from "@mui/material" 4 | import { useSelector } from "react-redux"; 5 | import { tokens, exchanges } from "../utils/helpers"; 6 | 7 | function Exchanges(props) { 8 | 9 | const data = useSelector((state) => state.blockchain.value) 10 | const [amounts, setAmounts] = useState([]) 11 | 12 | const currentNet = data.network !== "" ? data.network : "Ethereum Mainnet" 13 | 14 | async function getPrices() { 15 | if (window.ethereum !== undefined) { 16 | const provider = new ethers.providers.Web3Provider(window.ethereum, "any"); 17 | 18 | const _tokenIn = tokens[currentNet][props.token0]["address"] 19 | const _tokenOut = tokens[currentNet][props.token1]["address"] 20 | let path = [_tokenIn, _tokenOut] 21 | 22 | const decimals = tokens[currentNet][props.token1]["decimals"] 23 | 24 | let amountIn = utils.parseEther("1", "ether") 25 | 26 | const items = await Promise.all( 27 | exchanges[currentNet].map(async (e) => { 28 | if (e.name !== "Uniswap V3") { 29 | const router = new ethers.Contract(e.address, e.router.abi, provider) 30 | try { 31 | const amount = await router.getAmountsOut(amountIn, path) 32 | 33 | let item = { 34 | exchange: e.name, 35 | price: amount[1] / 10 ** decimals 36 | } 37 | return item 38 | } catch (err) { 39 | let item = { 40 | exchange: e.name, 41 | price: 0 42 | } 43 | return item 44 | } 45 | } else { 46 | const quoter = new ethers.Contract(e.address, e.quoter.abi, provider) 47 | try { 48 | const amount = await quoter.callStatic.quoteExactInputSingle( 49 | _tokenIn, 50 | _tokenOut, 51 | 3000, 52 | amountIn, 53 | 0 54 | ) 55 | 56 | let item = { 57 | exchange: e.name, 58 | price: amount / 10 ** decimals 59 | } 60 | return item 61 | } catch (err) { 62 | let item = { 63 | exchange: e.name, 64 | price: 0 65 | } 66 | return item 67 | } 68 | } 69 | })) 70 | setAmounts(items) 71 | } 72 | } 73 | 74 | /* 75 | setInterval(() => { 76 | getPrices() 77 | }, 30000); 78 | */ 79 | 80 | useEffect(() => { 81 | if (window.ethereum != undefined && data.network !== "") { 82 | getPrices() 83 | } 84 | 85 | }, [props.token0, props.token1, data.network]) 86 | 87 | return ( 88 | <> 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | {amounts.map((a, index) => { 98 | return ( 99 | 100 | 103 | 106 | 107 | ) 108 | })} 109 | 110 |
ExchangePrice
101 | {a.exchange} 102 | 104 | {a.price !== 0 ? parseFloat(a.price).toFixed(8) : "/"} 105 |
111 | 112 | ) 113 | } 114 | 115 | export default Exchanges; 116 | -------------------------------------------------------------------------------- /front-end/src/components/Main.js: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import { useSelector } from "react-redux" 3 | import NavBar from "./NavBar" 4 | import { NoteNav, Note } from "./NavbarElements" 5 | 6 | function Main() { 7 | const data = useSelector((state) => state.blockchain.value) 8 | 9 | const isConnected = data.account !== "" 10 | 11 | return ( 12 | <> 13 | 14 | 15 | 16 | {isConnected ? ( 17 |

18 | Note: You are currently connected to the {data.network} network 19 |

20 | ) : ( 21 |

Please connect your wallet

22 | )} 23 |
24 |
25 | 26 | 27 | ) 28 | } 29 | 30 | export default Main -------------------------------------------------------------------------------- /front-end/src/components/NavBar.js: -------------------------------------------------------------------------------- 1 | import { Navbar, Container, Nav } from "react-bootstrap" 2 | import 'bootstrap/dist/css/bootstrap.css'; 3 | import Account from "./Account" 4 | import logo from '../dapp-logo.png'; 5 | 6 | function NavBar() { 7 | 8 | return ( 9 | <> 10 | 11 | 12 | 13 | DeXAggregator 14 | 15 | 16 | 17 | 18 | 19 | ); 20 | } 21 | 22 | export default NavBar; 23 | -------------------------------------------------------------------------------- /front-end/src/components/NavbarElements.js: -------------------------------------------------------------------------------- 1 | import styled from 'styled-components'; 2 | 3 | export const NoteNav = styled.nav` 4 | background: black; 5 | height: 30px; 6 | width: 450px; 7 | text-align: center; 8 | display: block; 9 | margin: 0px auto; 10 | margin-bottom: 80px; 11 | 12 | @media (max-width: 32em) { 13 | width: 250px; 14 | height: 50px; 15 | } 16 | } 17 | `; 18 | 19 | export const NavBar = styled.nav` 20 | text-align: center; 21 | display: flex; 22 | margin-left: 10%; 23 | 24 | `; 25 | 26 | export const Note = styled.div` 27 | color: white; 28 | align-text: center; 29 | font-size: 14px; 30 | 31 | `; 32 | 33 | 34 | -------------------------------------------------------------------------------- /front-end/src/components/Swap.js: -------------------------------------------------------------------------------- 1 | import React, { useEffect, useState } from 'react' 2 | import { useSelector } from "react-redux" 3 | import { Modal } from "react-bootstrap" 4 | import { Button, CircularProgress } from "@mui/material"; 5 | import { ethers, utils } from 'ethers'; 6 | import qs from 'qs' 7 | 8 | import "../assets/css/styles.css"; 9 | import { tokens, exchanges, exchangesMap } from "../utils/helpers"; 10 | import IRouter from "../artifacts/interfaces/IUniswapV2Router02.json"; 11 | import ISwapRouter from "../artifacts/interfaces/ISwapRouter.json"; 12 | import ERC20 from "../artifacts/interfaces/IERC20.json"; 13 | import Exchanges from './Exchanges'; 14 | 15 | function Swap() { 16 | const data = useSelector((state) => state.blockchain.value) 17 | const [amountIn, setAmountIn] = useState(0); 18 | const [amountOut, setAmountOut] = useState(0); 19 | const [tokenInBalance, setTokenInBalance] = useState(null); 20 | const [gasPrice, setGasPrice] = useState(null); 21 | const [bestExchange, setBestExchange] = useState(null); 22 | const [isSwapping, setIsSwapping] = useState(false); 23 | 24 | const [tradeSide, setTradeSide] = useState(""); 25 | const [trade, setTrade] = useState({ 26 | fromToken: "0", 27 | toToken: "1" 28 | }); 29 | 30 | const [show, setShow] = useState(false); 31 | 32 | const handleClose = () => setShow(false); 33 | const handleShow = (side) => { 34 | setTradeSide(side) 35 | setShow(true); 36 | } 37 | 38 | 39 | async function getPriceOut(_amountIn) { 40 | if (window.ethereum !== undefined) { 41 | const provider = new ethers.providers.Web3Provider(window.ethereum, "any"); 42 | setAmountIn(Number(_amountIn)) 43 | if (Number(_amountIn) !== 0) { 44 | const decimals = tokens[currentNet][trade.toToken]["decimals"] 45 | const _tokenIn = tokens[currentNet][trade.fromToken]["address"] 46 | const _tokenOut = tokens[currentNet][trade.toToken]["address"] 47 | let path = [_tokenIn, _tokenOut] 48 | 49 | let amount_in = utils.parseEther(_amountIn.toString(), "ether") 50 | const prices = await Promise.all( 51 | exchanges[currentNet].map(async (e) => { 52 | if (e.name !== "Uniswap V3") { 53 | const router = new ethers.Contract(e.address, e.router.abi, provider) 54 | try { 55 | const amount = await router.getAmountsOut(amount_in, path) 56 | return Number(amount[1]) 57 | } catch (err) { 58 | return 0 59 | } 60 | } else { 61 | const quoter = new ethers.Contract(e.address, e.quoter.abi, provider) 62 | try { 63 | const amount = await quoter.callStatic.quoteExactInputSingle( 64 | _tokenIn, 65 | _tokenOut, 66 | 3000, 67 | amount_in, 68 | 0 69 | ) 70 | return Number(amount) 71 | } catch (err) { 72 | return 0 73 | } 74 | } 75 | })) 76 | 77 | const maxPrice = Math.max.apply(null, prices) 78 | const maxPriceIndex = prices.indexOf(maxPrice) 79 | 80 | setAmountOut(Number(maxPrice) / 10 ** decimals) 81 | getGasPrice(_tokenIn, _tokenOut, Number(_amountIn) * 10 ** decimals) 82 | setBestExchange(exchangesMap[currentNet][maxPriceIndex]) 83 | } else { 84 | setAmountOut("0") 85 | } 86 | } 87 | } 88 | 89 | async function getPriceIn(_amountOut) { 90 | if (window.ethereum !== undefined) { 91 | const provider = new ethers.providers.Web3Provider(window.ethereum, "any"); 92 | setAmountOut(Number(_amountOut)) 93 | if (Number(_amountOut) !== 0) { 94 | const decimals = tokens[currentNet][trade.toToken]["decimals"] 95 | const _tokenIn = tokens[currentNet][trade.fromToken]["address"] 96 | const _tokenOut = tokens[currentNet][trade.toToken]["address"] 97 | let path = [_tokenIn, _tokenOut] 98 | 99 | let amount_out = utils.parseEther(_amountOut.toString(), "ether") 100 | const prices = await Promise.all( 101 | exchanges[currentNet].map(async (e) => { 102 | const router = new ethers.Contract(e.address, e.router.abi, provider) 103 | try { 104 | const amount = await router.getAmountsIn(amount_out, path) 105 | return Number(amount[0]) 106 | } catch (err) { 107 | return 10 ** 60 108 | } 109 | })) 110 | 111 | const minPrice = Math.min.apply(null, prices) 112 | const minPriceIndex = prices.indexOf(minPrice) 113 | 114 | setAmountIn(Number(minPrice) / 10 ** decimals) 115 | getGasPrice(_tokenOut, _tokenIn, Number(_amountOut) * 10 ** decimals) 116 | setBestExchange(exchangesMap[currentNet][minPriceIndex]) 117 | } else { 118 | setAmountIn("0") 119 | } 120 | } 121 | } 122 | 123 | async function swap() { 124 | if (window.ethereum !== undefined) { 125 | const provider = new ethers.providers.Web3Provider(window.ethereum, "any"); 126 | try { 127 | setIsSwapping(true) 128 | const _tokenIn = tokens[currentNet][trade.fromToken]["address"] 129 | const _tokenOut = tokens[currentNet][trade.toToken]["address"] 130 | let path = [_tokenIn, _tokenOut] 131 | 132 | const _amountOutMin = Number(amountOut) * 0.95 133 | 134 | const amountOutMin = utils.parseEther(_amountOutMin.toString(), "ether") 135 | 136 | const signer = provider.getSigner() 137 | 138 | const erc20Contract = new ethers.Contract(_tokenIn, ERC20.abi, signer); 139 | 140 | const amount_in = utils.parseEther(amountIn.toString(), "ether") 141 | 142 | const approve_tx = await erc20Contract.approve(bestExchange["address"], amount_in) 143 | 144 | await approve_tx.wait() 145 | 146 | let timestamp = Math.floor(new Date().getTime() / 1000.0) + 15 147 | 148 | let router; 149 | if (bestExchange["name"] !== "Uniswap V3") { 150 | router = new ethers.Contract(bestExchange["address"], IRouter.abi, signer) 151 | try { 152 | const swap_tx = await router.swapExactTokensForTokens( 153 | amount_in, 154 | amountOutMin, 155 | path, 156 | data.account, 157 | timestamp 158 | ); 159 | await swap_tx.wait() 160 | 161 | setIsSwapping(false) 162 | setAmountIn(null) 163 | setAmountIn(null) 164 | } catch (err) { 165 | setIsSwapping(false) 166 | window.alert("An error has occured") 167 | } 168 | } else { 169 | router = new ethers.Contract(bestExchange["address"], ISwapRouter.abi, signer) 170 | try { 171 | const params = { 172 | tokenIn: path[0], 173 | tokenOut: path[1], 174 | fee: 3000, 175 | recipient: data.account, 176 | deadline: timestamp, 177 | amountIn: amount_in, 178 | amountOutMinimum: amountOutMin, 179 | sqrtPriceLimitX96: 0 180 | } 181 | const swap_tx = await router.exactInputSingle(params); 182 | await swap_tx.wait() 183 | 184 | setIsSwapping(false) 185 | setAmountIn(null) 186 | setAmountIn(null) 187 | } catch (err) { 188 | setIsSwapping(false) 189 | window.alert("An error has occured") 190 | } 191 | } 192 | } catch (err) { 193 | setIsSwapping(false) 194 | window.alert("An error has occured") 195 | } 196 | } 197 | } 198 | 199 | async function getGasPrice(tokenIn, tokenOut, amount) { 200 | if (window.ethereum !== undefined) { 201 | const provider = new ethers.providers.Web3Provider(window.ethereum, "any"); 202 | const params = { 203 | sellToken: tokenIn, 204 | buyToken: tokenOut, 205 | sellAmount: amount, 206 | } 207 | // Fetch the swap price. 208 | const response = await fetch( 209 | `https://api.0x.org/swap/v1/price?${qs.stringify(params)}` 210 | ); 211 | const swapPriceJSON = await response.json(); 212 | const _gasPrice = await provider.getGasPrice() 213 | setGasPrice(swapPriceJSON.estimatedGas) 214 | } 215 | } 216 | 217 | async function getErc20Balance() { 218 | if (window.ethereum !== undefined) { 219 | const provider = new ethers.providers.Web3Provider(window.ethereum, "any"); 220 | const signer = provider.getSigner() 221 | 222 | const decimals = tokens[currentNet][trade.fromToken]["decimals"] 223 | const _tokenIn = tokens[currentNet][trade.fromToken]["address"] 224 | 225 | const erc20Contract = new ethers.Contract(_tokenIn, ERC20.abi, signer); 226 | const balance = (await erc20Contract.balanceOf(data.account)).toString(); 227 | 228 | setTokenInBalance(Number(balance) / 10 ** decimals) 229 | } 230 | } 231 | 232 | async function selectToken(tokenIndex) { 233 | handleClose() 234 | if (tradeSide == "from") { 235 | setTrade({ ...trade, fromToken: tokenIndex }) 236 | } else { 237 | setTrade({ ...trade, toToken: tokenIndex }) 238 | } 239 | } 240 | const currentNet = data.network !== "" ? data.network : "Ethereum Mainnet" 241 | 242 | useEffect(() => { 243 | if (window.ethereum != undefined && data.network !== "") { 244 | getErc20Balance() 245 | } 246 | }, [trade.fromToken, data.network]) 247 | 248 | return ( 249 | data.network !== "" ? ( 250 |
251 |
252 |
253 |
254 |

Swap

255 |
256 |
257 |
{ handleShow("from") }}> 259 | {trade.fromToken !== "" ? ( 260 | <> 261 | 264 | 265 | {tokens["Ethereum Mainnet"][trade.fromToken].name} 266 | 267 | 268 | ) : "Select A Token"} 269 |
270 |
271 | { getPriceOut(e.target.value) }} /> 276 |
277 |
278 |
279 |
{ handleShow("to") }}> 281 | {trade.toToken !== "" ? ( 282 | <> 283 | 286 | 287 | {tokens["Ethereum Mainnet"][trade.toToken].name} 288 | 289 | 290 | ) : "Select A Token"} 291 |
292 |
293 | { getPriceIn(e.target.value) }} /> 298 |
299 |
300 |
301 | Estimated Gas: {gasPrice} 302 |
303 |
304 | Your {tokens["Ethereum Mainnet"][trade.fromToken].name} Balance: {tokenInBalance} 305 |
306 | 309 |
310 |
311 |
312 | 313 | 314 | SELECT A TOKEN 315 | 316 | 317 | {tokens["Ethereum Mainnet"].map((token, index) => { 318 | return ( 319 |
{ selectToken(index) }} > 320 | 321 | {token.name} 322 |
323 | ) 324 | })} 325 |
326 | 327 | 330 | 331 |
332 |
333 |

Exchanges

334 | 335 |
336 |
337 |
338 | ) : null 339 | ) 340 | } 341 | 342 | export default Swap; 343 | -------------------------------------------------------------------------------- /front-end/src/dapp-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kaymen99/Dex-aggregator/f9f1478ec780196f5b4248535bccbf05b513fcc3/front-end/src/dapp-logo.png -------------------------------------------------------------------------------- /front-end/src/features/blockchain.js: -------------------------------------------------------------------------------- 1 | import { createSlice } from '@reduxjs/toolkit'; 2 | 3 | const initialData = { account: "", balance: 0, network: "" } 4 | export const blockchainSlice = createSlice({ 5 | name: "blockchain", 6 | initialState: { value: initialData }, 7 | reducers: { 8 | updateAccountData: (state, action) => { 9 | state.value = action.payload 10 | }, 11 | disconnect: (state) => { 12 | state.value = initialData 13 | } 14 | }, 15 | } 16 | ) 17 | 18 | export default blockchainSlice.reducer; 19 | 20 | export const { updateAccountData, disconnect } = blockchainSlice.actions; 21 | -------------------------------------------------------------------------------- /front-end/src/index.css: -------------------------------------------------------------------------------- 1 | body { 2 | margin: 0; 3 | font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 4 | 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', 5 | sans-serif; 6 | -webkit-font-smoothing: antialiased; 7 | -moz-osx-font-smoothing: grayscale; 8 | } 9 | 10 | code { 11 | font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New', 12 | monospace; 13 | } -------------------------------------------------------------------------------- /front-end/src/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | import './index.css'; 4 | import { combineReducers } from 'redux' 5 | import reportWebVitals from './reportWebVitals'; 6 | import { configureStore } from "@reduxjs/toolkit"; 7 | import { Provider } from "react-redux"; 8 | import blockchainReducer from "./features/blockchain" 9 | import { 10 | persistStore, 11 | persistReducer, 12 | FLUSH, 13 | REHYDRATE, 14 | PAUSE, 15 | PERSIST, 16 | PURGE, 17 | REGISTER, 18 | } from 'redux-persist' 19 | import storage from 'redux-persist/lib/storage' 20 | import { PersistGate } from 'redux-persist/integration/react'; 21 | import App from './App'; 22 | 23 | 24 | const persistConfig = { 25 | key: 'root', 26 | version: 1, 27 | storage, 28 | } 29 | 30 | const rootReducer = combineReducers({ 31 | blockchain: blockchainReducer 32 | }) 33 | 34 | 35 | const persistedReducer = persistReducer(persistConfig, rootReducer) 36 | 37 | const store = configureStore({ 38 | reducer: persistedReducer, 39 | middleware: (getDefaultMiddleware) => 40 | getDefaultMiddleware({ 41 | serializableCheck: { 42 | ignoredActions: [FLUSH, REHYDRATE, PAUSE, PERSIST, PURGE, REGISTER], 43 | }, 44 | }), 45 | }) 46 | 47 | let persistor = persistStore(store) 48 | 49 | ReactDOM.render( 50 | 51 | 52 | 53 | 54 | 55 | 56 | , 57 | document.getElementById('root') 58 | ); 59 | 60 | // If you want to start measuring performance in your app, pass a function 61 | // to log results (for example: reportWebVitals(console.log)) 62 | // or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals 63 | reportWebVitals(); 64 | 65 | -------------------------------------------------------------------------------- /front-end/src/reportWebVitals.js: -------------------------------------------------------------------------------- 1 | const reportWebVitals = onPerfEntry => { 2 | if (onPerfEntry && onPerfEntry instanceof Function) { 3 | import('web-vitals').then(({ getCLS, getFID, getFCP, getLCP, getTTFB }) => { 4 | getCLS(onPerfEntry); 5 | getFID(onPerfEntry); 6 | getFCP(onPerfEntry); 7 | getLCP(onPerfEntry); 8 | getTTFB(onPerfEntry); 9 | }); 10 | } 11 | }; 12 | 13 | export default reportWebVitals; 14 | -------------------------------------------------------------------------------- /front-end/src/setupTests.js: -------------------------------------------------------------------------------- 1 | // jest-dom adds custom jest matchers for asserting on DOM nodes. 2 | // allows you to do things like: 3 | // expect(element).toHaveTextContent(/react/i) 4 | // learn more: https://github.com/testing-library/jest-dom 5 | import '@testing-library/jest-dom'; 6 | -------------------------------------------------------------------------------- /front-end/src/utils/helpers.js: -------------------------------------------------------------------------------- 1 | import IRouter from "./../artifacts/interfaces/IUniswapV2Router02.json"; 2 | import ISwapRouter from "./../artifacts/interfaces/ISwapRouter.json"; 3 | import IQouter from "./../artifacts/interfaces/IQuoter.json"; 4 | 5 | import eth from "./../assets/images/etherLogo.png"; 6 | import bnb from "./../assets/images/bnb.png"; 7 | import matic from "./../assets/images/matic.png"; 8 | import dai from "./../assets/images/dai.png"; 9 | import crv from "./../assets/images/crv.png"; 10 | import usdc from "./../assets/images/usdc.png"; 11 | import aave from "./../assets/images/aave.png" 12 | import link from "./../assets/images/link.png" 13 | import usdt from "./../assets/images/usdt.png"; 14 | import uni from "./../assets/images/uni.jpg" 15 | 16 | export const tokens = { 17 | "Ethereum Mainnet": [ 18 | { 19 | "image": eth, 20 | "name": "ETH", 21 | "address": "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2", 22 | "decimals": 18 23 | }, 24 | { 25 | "image": dai, 26 | "name": "DAI", 27 | "address": "0x6b175474e89094c44da98b954eedeac495271d0f", 28 | "decimals": 18 29 | }, 30 | { 31 | "image": usdc, 32 | "name": "USDC", 33 | "address": "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48", 34 | "decimals": 6 35 | }, 36 | { 37 | "image": usdt, 38 | "name": "USDT", 39 | "address": "0xdAC17F958D2ee523a2206206994597C13D831ec7", 40 | "decimals": 6 41 | }, 42 | { 43 | "image": matic, 44 | "name": "MATIC", 45 | "address": "0x7D1AfA7B718fb893dB30A3aBc0Cfc608AaCfeBB0", 46 | "decimals": 18 47 | }, 48 | { 49 | "image": crv, 50 | "name": "CRV", 51 | "address": "0xD533a949740bb3306d119CC777fa900bA034cd52", 52 | "decimals": 18 53 | }, 54 | { 55 | "image": link, 56 | "name": "LINK", 57 | "address": "0x514910771AF9Ca656af840dff83E8264EcF986CA", 58 | "decimals": 18 59 | }, 60 | { 61 | "image": uni, 62 | "name": "UNI", 63 | "address": "0x1f9840a85d5aF5bf1D1762F925BDADdC4201F984", 64 | "decimals": 18 65 | } 66 | ], 67 | "Goerli": [ 68 | { 69 | "image": eth, 70 | "name": "ETH", 71 | "address": "0xd0A1E359811322d97991E03f863a0C30C2cF029C", 72 | "decimals": 18 73 | }, 74 | { 75 | "image": dai, 76 | "name": "DAI", 77 | "address": "0x4F96Fe3b7A6Cf9725f59d353F723c1bDb64CA6Aa", 78 | "decimals": 18 79 | }, 80 | { 81 | "image": usdc, 82 | "name": "USDC", 83 | "address": "0xdCFaB8057d08634279f8201b55d311c2a67897D2", 84 | "decimals": 2 85 | }, 86 | { 87 | "image": usdt, 88 | "name": "USDT", 89 | "address": "0xf3e0d7bF58c5d455D31ef1c2d5375904dF525105", 90 | "decimals": 6 91 | }, 92 | { 93 | "image": crv, 94 | "name": "CRV", 95 | "address": "0xB8EEb94cFf33EfACf0c6def6967FD8852DcECDdB", 96 | "decimals": 18 97 | }, 98 | { 99 | "image": matic, 100 | "name": "MATIC", 101 | "address": "0x7D1AfA7B718fb893dB30A3aBc0Cfc608AaCfeBB0", 102 | "decimals": 18 103 | }, 104 | { 105 | "image": link, 106 | "name": "LINK", 107 | "address": "0xa36085F69e2889c224210F603D836748e7dC0088", 108 | "decimals": 18 109 | }, 110 | { 111 | "image": uni, 112 | "name": "UNI", 113 | "address": "0x9b6Ff80Ff8348852d5281de45E66B7ED36E7B8a9", 114 | "decimals": 18 115 | }, 116 | ], 117 | "Polygon Mainnet": [ 118 | { 119 | "image": matic, 120 | "name": "MATIC", 121 | "address": "0x0d500B1d8E8eF31E21C99d1Db9A6444d3ADf1270", 122 | "decimals": 18 123 | }, 124 | { 125 | "image": eth, 126 | "name": "ETH", 127 | "address": "0x7ceB23fD6bC0adD59E62ac25578270cFf1b9f619", 128 | "decimals": 18 129 | }, 130 | { 131 | "image": dai, 132 | "name": "DAI", 133 | "address": "0x8f3Cf7ad23Cd3CaDbD9735AFf958023239c6A063", 134 | "decimals": 18 135 | }, 136 | { 137 | "image": usdc, 138 | "name": "USDC", 139 | "address": "0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174", 140 | "decimals": 6 141 | }, 142 | { 143 | "image": usdt, 144 | "name": "USDT", 145 | "address": "0xdAC17F958D2ee523a2206206994597C13D831ec7", 146 | "decimals": 6 147 | }, 148 | { 149 | "image": aave, 150 | "name": "AAVE", 151 | "address": "0xD6DF932A45C0f255f85145f286eA0b292B21C90B", 152 | "decimals": 18 153 | }, 154 | { 155 | "image": link, 156 | "name": "LINK", 157 | "address": "0x53E0bca35eC356BD5ddDFebbD1Fc0fD03FaBad39", 158 | "decimals": 18 159 | } 160 | ], 161 | "BSC": [ 162 | { 163 | "image": eth, 164 | "name": "ETH", 165 | "address": "0x2170Ed0880ac9A755fd29B2688956BD959F933F8", 166 | "decimals": 18 167 | }, 168 | { 169 | "image": bnb, 170 | "name": "BNB", 171 | "address": "0xbb4CdB9CBd36B01bD1cBaEBF2De08d9173bc095c", 172 | "decimals": 18 173 | }, 174 | { 175 | "image": dai, 176 | "name": "DAI", 177 | "address": "0x1AF3F329e8BE154074D8769D1FFa4eE058B1DBc3", 178 | "decimals": 18 179 | }, 180 | { 181 | "image": usdc, 182 | "name": "USDC", 183 | "address": "0x8AC76a51cc950d9822D68b83fE1Ad97B32Cd580d", 184 | "decimals": 6 185 | }, 186 | { 187 | "image": usdt, 188 | "name": "USDT", 189 | "address": "0xdAC17F958D2ee523a2206206994597C13D831ec7", 190 | "decimals": 6 191 | }, 192 | { 193 | "image": link, 194 | "name": "LINK", 195 | "address": "0xF8A0BF9cF54Bb92F17374d9e9A321E6a111a51bD", 196 | "decimals": 18 197 | } 198 | ], 199 | } 200 | 201 | export const exchanges = { 202 | "Ethereum Mainnet": [ 203 | { 204 | "name": "Uniswap", 205 | "address": "0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D", 206 | "router": IRouter 207 | }, 208 | { 209 | "name": "Uniswap V3", 210 | "address": "0xb27308f9F90D607463bb33eA1BeBb41C27CE5AB6", 211 | "router": ISwapRouter, 212 | "quoter": IQouter 213 | }, 214 | { 215 | "name": "Sushiswap", 216 | "address": "0xd9e1cE17f2641f24aE83637ab66a2cca9C378B9F", 217 | "router": IRouter 218 | }, 219 | { 220 | "name": "Shibaswap", 221 | "address": "0x03f7724180AA6b939894B5Ca4314783B0b36b329", 222 | "router": IRouter 223 | } 224 | ], 225 | "Goerli": [ 226 | { 227 | "name": "Uniswap", 228 | "address": "0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D", 229 | "router": IRouter 230 | }, 231 | { 232 | "name": "Uniswap V3", 233 | "address": "0xb27308f9F90D607463bb33eA1BeBb41C27CE5AB6", 234 | "router": ISwapRouter, 235 | "quoter": IQouter 236 | }, 237 | { 238 | "name": "Sushiswap", 239 | "address": "0xd9e1cE17f2641f24aE83637ab66a2cca9C378B9F", 240 | "router": IRouter 241 | }, 242 | { 243 | "name": "Shibaswap", 244 | "address": "0x03f7724180AA6b939894B5Ca4314783B0b36b329", 245 | "router": IRouter 246 | } 247 | ], 248 | "Polygon Mainnet": [ 249 | { 250 | "name": "Sushiswap", 251 | "address": "0x1b02dA8Cb0d097eB8D57A175b88c7D8b47997506", 252 | "router": IRouter 253 | }, 254 | { 255 | "name": "Uniswap V3", 256 | "address": "0xb27308f9F90D607463bb33eA1BeBb41C27CE5AB6", 257 | "router": ISwapRouter, 258 | "quoter": IQouter 259 | }, 260 | { 261 | "name": "Quickswap", 262 | "address": "0xa5E0829CaCEd8fFDD4De3c43696c57F7D7A678ff", 263 | "router": IRouter 264 | }, 265 | { 266 | "name": "Jetswap", 267 | "address": "0x5C6EC38fb0e2609672BDf628B1fD605A523E5923", 268 | "router": IRouter 269 | }, 270 | { 271 | "name": "Apeswap", 272 | "address": "0xC0788A3aD43d79aa53B09c2EaCc313A787d1d607", 273 | "router": IRouter 274 | } 275 | 276 | ], 277 | "BSC": [ 278 | { 279 | "name": "Sushiswap", 280 | "address": "0x947950BcC74888a40Ffa2593C5798F11Fc9124C4", 281 | "router": IRouter 282 | }, 283 | { 284 | "name": "Apeswap", 285 | "address": "0xcF0feBd3f17CEf5b47b0cD257aCf6025c5BFf3b7", 286 | "router": IRouter 287 | }, 288 | { 289 | "name": "Jetswap", 290 | "address": "0x5C6EC38fb0e2609672BDf628B1fD605A523E5923", 291 | "router": IRouter 292 | }, 293 | { 294 | "name": "Pancakeswap", 295 | "address": "0x10ED43C718714eb63d5aA57B78B54704E256024E", 296 | "router": IRouter 297 | } 298 | ] 299 | } 300 | 301 | export const exchangesMap = { 302 | "Ethereum Mainnet": { 303 | 0: { 304 | "name": "UNISWAP", 305 | "address": "0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D" 306 | }, 307 | 1: { 308 | "name": "Uniswap V3", 309 | "address": "0xE592427A0AEce92De3Edee1F18E0157C05861564", 310 | }, 311 | 2: { 312 | "name": "SUSHISWAP", 313 | "address": "0xd9e1cE17f2641f24aE83637ab66a2cca9C378B9F" 314 | }, 315 | 3: { 316 | "name": "SHIBASWAP", 317 | "address": "0x03f7724180AA6b939894B5Ca4314783B0b36b329" 318 | } 319 | }, 320 | "Goerli": { 321 | 0: { 322 | "name": "UNISWAP", 323 | "address": "0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D" 324 | }, 325 | 1: { 326 | "name": "Uniswap V3", 327 | "address": "0xE592427A0AEce92De3Edee1F18E0157C05861564", 328 | }, 329 | 2: { 330 | "name": "SUSHISWAP", 331 | "address": "0xd9e1cE17f2641f24aE83637ab66a2cca9C378B9F" 332 | }, 333 | 3: { 334 | "name": "SHIBASWAP", 335 | "address": "0x03f7724180AA6b939894B5Ca4314783B0b36b329" 336 | } 337 | }, 338 | "Polygon Mainnet": { 339 | 0: { 340 | "name": "SUSHISWAP", 341 | "address": "0x1b02dA8Cb0d097eB8D57A175b88c7D8b47997506" 342 | }, 343 | 1: { 344 | "name": "Uniswap V3", 345 | "address": "0xE592427A0AEce92De3Edee1F18E0157C05861564", 346 | }, 347 | 2: { 348 | "name": "QUICKSWAP", 349 | "address": "0xa5E0829CaCEd8fFDD4De3c43696c57F7D7A678ff" 350 | }, 351 | 3: { 352 | "name": "JETSWAP", 353 | "address": "0x5C6EC38fb0e2609672BDf628B1fD605A523E5923" 354 | }, 355 | 4: { 356 | "name": "APESWAP", 357 | "address": "0xC0788A3aD43d79aa53B09c2EaCc313A787d1d607" 358 | } 359 | }, 360 | "BSC": { 361 | 0: { 362 | "name": "SUSHISWAP", 363 | "address": "0x947950BcC74888a40Ffa2593C5798F11Fc9124C4" 364 | }, 365 | 1: { 366 | "name": "PANCAKESWAP", 367 | "address": "0x10ED43C718714eb63d5aA57B78B54704E256024E" 368 | }, 369 | 2: { 370 | "name": "JETSWAP", 371 | "address": "0x5C6EC38fb0e2609672BDf628B1fD605A523E5923" 372 | }, 373 | 3: { 374 | "name": "APESWAP", 375 | "address": "0xcF0feBd3f17CEf5b47b0cD257aCf6025c5BFf3b7" 376 | } 377 | }, 378 | } 379 | -------------------------------------------------------------------------------- /front-end/src/utils/networksMap.json: -------------------------------------------------------------------------------- 1 | { 2 | "1": "Ethereum Mainnet", 3 | "5": "Goerli", 4 | "1337": "ganache", 5 | "80001": "Polygon Testnet", 6 | "137": "Polygon Mainnet", 7 | "56": "BSC" 8 | } 9 | -------------------------------------------------------------------------------- /interfaces/IERC20.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity >=0.6.0 <0.8.0; 4 | 5 | /** 6 | * @dev Interface of the ERC20 standard as defined in the EIP. 7 | */ 8 | interface IERC20 { 9 | /** 10 | * @dev Returns the amount of tokens in existence. 11 | */ 12 | function totalSupply() external view returns (uint256); 13 | 14 | /** 15 | * @dev Returns the amount of tokens owned by `account`. 16 | */ 17 | function balanceOf(address account) external view returns (uint256); 18 | 19 | /** 20 | * @dev Moves `amount` tokens from the caller's account to `recipient`. 21 | * 22 | * Returns a boolean value indicating whether the operation succeeded. 23 | * 24 | * Emits a {Transfer} event. 25 | */ 26 | function transfer(address recipient, uint256 amount) 27 | external 28 | returns (bool); 29 | 30 | /** 31 | * @dev Returns the remaining number of tokens that `spender` will be 32 | * allowed to spend on behalf of `owner` through {transferFrom}. This is 33 | * zero by default. 34 | * 35 | * This value changes when {approve} or {transferFrom} are called. 36 | */ 37 | function allowance(address owner, address spender) 38 | external 39 | view 40 | returns (uint256); 41 | 42 | /** 43 | * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. 44 | * 45 | * Returns a boolean value indicating whether the operation succeeded. 46 | * 47 | * IMPORTANT: Beware that changing an allowance with this method brings the risk 48 | * that someone may use both the old and the new allowance by unfortunate 49 | * transaction ordering. One possible solution to mitigate this race 50 | * condition is to first reduce the spender's allowance to 0 and set the 51 | * desired value afterwards: 52 | * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 53 | * 54 | * Emits an {Approval} event. 55 | */ 56 | function approve(address spender, uint256 amount) external returns (bool); 57 | 58 | /** 59 | * @dev Moves `amount` tokens from `sender` to `recipient` using the 60 | * allowance mechanism. `amount` is then deducted from the caller's 61 | * allowance. 62 | * 63 | * Returns a boolean value indicating whether the operation succeeded. 64 | * 65 | * Emits a {Transfer} event. 66 | */ 67 | function transferFrom( 68 | address sender, 69 | address recipient, 70 | uint256 amount 71 | ) external returns (bool); 72 | 73 | /** 74 | * @dev Emitted when `value` tokens are moved from one account (`from`) to 75 | * another (`to`). 76 | * 77 | * Note that `value` may be zero. 78 | */ 79 | event Transfer(address indexed from, address indexed to, uint256 value); 80 | 81 | /** 82 | * @dev Emitted when the allowance of a `spender` for an `owner` is set by 83 | * a call to {approve}. `value` is the new allowance. 84 | */ 85 | event Approval( 86 | address indexed owner, 87 | address indexed spender, 88 | uint256 value 89 | ); 90 | } 91 | -------------------------------------------------------------------------------- /interfaces/IQouter.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-2.0-or-later 2 | pragma solidity >=0.7.5; 3 | pragma abicoder v2; 4 | 5 | /// @title Quoter Interface 6 | /// @notice Supports quoting the calculated amounts from exact input or exact output swaps 7 | /// @dev These functions are not marked view because they rely on calling non-view functions and reverting 8 | /// to compute the result. They are also not gas efficient and should not be called on-chain. 9 | interface IQuoter { 10 | /// @notice Returns the amount out received for a given exact input swap without executing the swap 11 | /// @param path The path of the swap, i.e. each token pair and the pool fee 12 | /// @param amountIn The amount of the first token to swap 13 | /// @return amountOut The amount of the last token that would be received 14 | function quoteExactInput(bytes memory path, uint256 amountIn) 15 | external 16 | returns (uint256 amountOut); 17 | 18 | /// @notice Returns the amount out received for a given exact input but for a swap of a single pool 19 | /// @param tokenIn The token being swapped in 20 | /// @param tokenOut The token being swapped out 21 | /// @param fee The fee of the token pool to consider for the pair 22 | /// @param amountIn The desired input amount 23 | /// @param sqrtPriceLimitX96 The price limit of the pool that cannot be exceeded by the swap 24 | /// @return amountOut The amount of `tokenOut` that would be received 25 | function quoteExactInputSingle( 26 | address tokenIn, 27 | address tokenOut, 28 | uint24 fee, 29 | uint256 amountIn, 30 | uint160 sqrtPriceLimitX96 31 | ) external returns (uint256 amountOut); 32 | 33 | /// @notice Returns the amount in required for a given exact output swap without executing the swap 34 | /// @param path The path of the swap, i.e. each token pair and the pool fee. Path must be provided in reverse order 35 | /// @param amountOut The amount of the last token to receive 36 | /// @return amountIn The amount of first token required to be paid 37 | function quoteExactOutput(bytes memory path, uint256 amountOut) 38 | external 39 | returns (uint256 amountIn); 40 | 41 | /// @notice Returns the amount in required to receive the given exact output amount but for a swap of a single pool 42 | /// @param tokenIn The token being swapped in 43 | /// @param tokenOut The token being swapped out 44 | /// @param fee The fee of the token pool to consider for the pair 45 | /// @param amountOut The desired output amount 46 | /// @param sqrtPriceLimitX96 The price limit of the pool that cannot be exceeded by the swap 47 | /// @return amountIn The amount required as the input for the swap in order to receive `amountOut` 48 | function quoteExactOutputSingle( 49 | address tokenIn, 50 | address tokenOut, 51 | uint24 fee, 52 | uint256 amountOut, 53 | uint160 sqrtPriceLimitX96 54 | ) external returns (uint256 amountIn); 55 | } 56 | -------------------------------------------------------------------------------- /interfaces/ISwapRouter.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-2.0-or-later 2 | pragma solidity >=0.7.5; 3 | pragma abicoder v2; 4 | 5 | import "@uniswap/contracts/interfaces/callback/IUniswapV3SwapCallback.sol"; 6 | 7 | /// @title Router token swapping functionality 8 | /// @notice Functions for swapping tokens via Uniswap V3 9 | interface ISwapRouter is IUniswapV3SwapCallback { 10 | struct ExactInputSingleParams { 11 | address tokenIn; 12 | address tokenOut; 13 | uint24 fee; 14 | address recipient; 15 | uint256 deadline; 16 | uint256 amountIn; 17 | uint256 amountOutMinimum; 18 | uint160 sqrtPriceLimitX96; 19 | } 20 | 21 | /// @notice Swaps `amountIn` of one token for as much as possible of another token 22 | /// @param params The parameters necessary for the swap, encoded as `ExactInputSingleParams` in calldata 23 | /// @return amountOut The amount of the received token 24 | function exactInputSingle(ExactInputSingleParams calldata params) 25 | external 26 | payable 27 | returns (uint256 amountOut); 28 | 29 | struct ExactInputParams { 30 | bytes path; 31 | address recipient; 32 | uint256 deadline; 33 | uint256 amountIn; 34 | uint256 amountOutMinimum; 35 | } 36 | 37 | /// @notice Swaps `amountIn` of one token for as much as possible of another along the specified path 38 | /// @param params The parameters necessary for the multi-hop swap, encoded as `ExactInputParams` in calldata 39 | /// @return amountOut The amount of the received token 40 | function exactInput(ExactInputParams calldata params) 41 | external 42 | payable 43 | returns (uint256 amountOut); 44 | 45 | struct ExactOutputSingleParams { 46 | address tokenIn; 47 | address tokenOut; 48 | uint24 fee; 49 | address recipient; 50 | uint256 deadline; 51 | uint256 amountOut; 52 | uint256 amountInMaximum; 53 | uint160 sqrtPriceLimitX96; 54 | } 55 | 56 | /// @notice Swaps as little as possible of one token for `amountOut` of another token 57 | /// @param params The parameters necessary for the swap, encoded as `ExactOutputSingleParams` in calldata 58 | /// @return amountIn The amount of the input token 59 | function exactOutputSingle(ExactOutputSingleParams calldata params) 60 | external 61 | payable 62 | returns (uint256 amountIn); 63 | 64 | struct ExactOutputParams { 65 | bytes path; 66 | address recipient; 67 | uint256 deadline; 68 | uint256 amountOut; 69 | uint256 amountInMaximum; 70 | } 71 | 72 | /// @notice Swaps as little as possible of one token for `amountOut` of another along the specified path (reversed) 73 | /// @param params The parameters necessary for the multi-hop swap, encoded as `ExactOutputParams` in calldata 74 | /// @return amountIn The amount of the input token 75 | function exactOutput(ExactOutputParams calldata params) 76 | external 77 | payable 78 | returns (uint256 amountIn); 79 | } 80 | -------------------------------------------------------------------------------- /interfaces/IUniswapV2Router02.sol: -------------------------------------------------------------------------------- 1 | pragma solidity >=0.6.2; 2 | 3 | interface IUniswapV2Router01 { 4 | function factory() external pure returns (address); 5 | 6 | function WETH() external pure returns (address); 7 | 8 | function addLiquidity( 9 | address tokenA, 10 | address tokenB, 11 | uint256 amountADesired, 12 | uint256 amountBDesired, 13 | uint256 amountAMin, 14 | uint256 amountBMin, 15 | address to, 16 | uint256 deadline 17 | ) 18 | external 19 | returns ( 20 | uint256 amountA, 21 | uint256 amountB, 22 | uint256 liquidity 23 | ); 24 | 25 | function addLiquidityETH( 26 | address token, 27 | uint256 amountTokenDesired, 28 | uint256 amountTokenMin, 29 | uint256 amountETHMin, 30 | address to, 31 | uint256 deadline 32 | ) 33 | external 34 | payable 35 | returns ( 36 | uint256 amountToken, 37 | uint256 amountETH, 38 | uint256 liquidity 39 | ); 40 | 41 | function removeLiquidity( 42 | address tokenA, 43 | address tokenB, 44 | uint256 liquidity, 45 | uint256 amountAMin, 46 | uint256 amountBMin, 47 | address to, 48 | uint256 deadline 49 | ) external returns (uint256 amountA, uint256 amountB); 50 | 51 | function removeLiquidityETH( 52 | address token, 53 | uint256 liquidity, 54 | uint256 amountTokenMin, 55 | uint256 amountETHMin, 56 | address to, 57 | uint256 deadline 58 | ) external returns (uint256 amountToken, uint256 amountETH); 59 | 60 | function removeLiquidityWithPermit( 61 | address tokenA, 62 | address tokenB, 63 | uint256 liquidity, 64 | uint256 amountAMin, 65 | uint256 amountBMin, 66 | address to, 67 | uint256 deadline, 68 | bool approveMax, 69 | uint8 v, 70 | bytes32 r, 71 | bytes32 s 72 | ) external returns (uint256 amountA, uint256 amountB); 73 | 74 | function removeLiquidityETHWithPermit( 75 | address token, 76 | uint256 liquidity, 77 | uint256 amountTokenMin, 78 | uint256 amountETHMin, 79 | address to, 80 | uint256 deadline, 81 | bool approveMax, 82 | uint8 v, 83 | bytes32 r, 84 | bytes32 s 85 | ) external returns (uint256 amountToken, uint256 amountETH); 86 | 87 | function swapExactTokensForTokens( 88 | uint256 amountIn, 89 | uint256 amountOutMin, 90 | address[] calldata path, 91 | address to, 92 | uint256 deadline 93 | ) external returns (uint256[] memory amounts); 94 | 95 | function swapTokensForExactTokens( 96 | uint256 amountOut, 97 | uint256 amountInMax, 98 | address[] calldata path, 99 | address to, 100 | uint256 deadline 101 | ) external returns (uint256[] memory amounts); 102 | 103 | function swapExactETHForTokens( 104 | uint256 amountOutMin, 105 | address[] calldata path, 106 | address to, 107 | uint256 deadline 108 | ) external payable returns (uint256[] memory amounts); 109 | 110 | function swapTokensForExactETH( 111 | uint256 amountOut, 112 | uint256 amountInMax, 113 | address[] calldata path, 114 | address to, 115 | uint256 deadline 116 | ) external returns (uint256[] memory amounts); 117 | 118 | function swapExactTokensForETH( 119 | uint256 amountIn, 120 | uint256 amountOutMin, 121 | address[] calldata path, 122 | address to, 123 | uint256 deadline 124 | ) external returns (uint256[] memory amounts); 125 | 126 | function swapETHForExactTokens( 127 | uint256 amountOut, 128 | address[] calldata path, 129 | address to, 130 | uint256 deadline 131 | ) external payable returns (uint256[] memory amounts); 132 | 133 | function quote( 134 | uint256 amountA, 135 | uint256 reserveA, 136 | uint256 reserveB 137 | ) external pure returns (uint256 amountB); 138 | 139 | function getAmountOut( 140 | uint256 amountIn, 141 | uint256 reserveIn, 142 | uint256 reserveOut 143 | ) external pure returns (uint256 amountOut); 144 | 145 | function getAmountIn( 146 | uint256 amountOut, 147 | uint256 reserveIn, 148 | uint256 reserveOut 149 | ) external pure returns (uint256 amountIn); 150 | 151 | function getAmountsOut(uint256 amountIn, address[] calldata path) 152 | external 153 | view 154 | returns (uint256[] memory amounts); 155 | 156 | function getAmountsIn(uint256 amountOut, address[] calldata path) 157 | external 158 | view 159 | returns (uint256[] memory amounts); 160 | } 161 | 162 | interface IUniswapV2Router02 is IUniswapV2Router01 { 163 | function removeLiquidityETHSupportingFeeOnTransferTokens( 164 | address token, 165 | uint256 liquidity, 166 | uint256 amountTokenMin, 167 | uint256 amountETHMin, 168 | address to, 169 | uint256 deadline 170 | ) external returns (uint256 amountETH); 171 | 172 | function removeLiquidityETHWithPermitSupportingFeeOnTransferTokens( 173 | address token, 174 | uint256 liquidity, 175 | uint256 amountTokenMin, 176 | uint256 amountETHMin, 177 | address to, 178 | uint256 deadline, 179 | bool approveMax, 180 | uint8 v, 181 | bytes32 r, 182 | bytes32 s 183 | ) external returns (uint256 amountETH); 184 | 185 | function swapExactTokensForTokensSupportingFeeOnTransferTokens( 186 | uint256 amountIn, 187 | uint256 amountOutMin, 188 | address[] calldata path, 189 | address to, 190 | uint256 deadline 191 | ) external; 192 | 193 | function swapExactETHForTokensSupportingFeeOnTransferTokens( 194 | uint256 amountOutMin, 195 | address[] calldata path, 196 | address to, 197 | uint256 deadline 198 | ) external payable; 199 | 200 | function swapExactTokensForETHSupportingFeeOnTransferTokens( 201 | uint256 amountIn, 202 | uint256 amountOutMin, 203 | address[] calldata path, 204 | address to, 205 | uint256 deadline 206 | ) external; 207 | } 208 | -------------------------------------------------------------------------------- /scripts/get_prices.py: -------------------------------------------------------------------------------- 1 | from brownie import config, network, interface 2 | from scripts.helper_scripts import get_account, toWei, fromWei, approve_erc20, FORKED_BLOCHCHAINS 3 | from scripts.get_weth import get_weth 4 | import brownie, requests 5 | 6 | 7 | 8 | weth_token = config["networks"][network.show_active()]["weth-token"] 9 | dai_token = config["networks"][network.show_active()]["dai-token"] 10 | 11 | 12 | uni_router_address = config["networks"][network.show_active()]["uniswap-router"] 13 | shiba_router_address = config["networks"][network.show_active()]["shibaswap-router"] 14 | sushi_router_address = config["networks"][network.show_active()]["sushiswap-rou 15 | 16 | 17 | def main(): 18 | amount = toWei(1) 19 | 20 | uniswap_router = interface.IUniswapV2Router02(uni_router_address) 21 | sushiswap_router = interface.IUniswapV2Router02(sushi_router_address) 22 | shibaswap_router = interface.IUniswapV2Router02(shiba_router_address) 23 | 24 | path = [weth_token, usdt_token] 25 | 26 | amount_uniswap= uniswap_router.getAmountsOut(amount, path)[1] 27 | amount_sushiswap = sushiswap_router.getAmountsOut(amount, path)[1] 28 | amount_shibaswap = shibaswap_router.getAmountsOut(amount, path)[1] 29 | 30 | print("amount in uniswap: " , float(amount_uniswap) / 10**18) 31 | print("amount in sushiswap: " , float(amount_sushiswap)/ 10**18) 32 | print("amount in shibaswap: " , float(amount_shibaswap)/ 10**18) 33 | 34 | 35 | -------------------------------------------------------------------------------- /scripts/get_weth.py: -------------------------------------------------------------------------------- 1 | from brownie import network, interface, config 2 | from scripts.helper_scripts import fromWei, get_account, toWei 3 | 4 | 5 | 6 | def get_weth(account, amount): 7 | weth_address = config["networks"][network.show_active()]["weth-token"] 8 | 9 | weth = interface.IWeth(weth_address) 10 | 11 | deposit_tx = weth.deposit({"from": account, "value": toWei(amount)}) 12 | deposit_tx.wait(1) 13 | 14 | print(f"You recieved {amount} weth") 15 | 16 | def main(): 17 | account = get_account() 18 | amount = toWei(10) 19 | get_weth(account, amount) -------------------------------------------------------------------------------- /scripts/helper_scripts.py: -------------------------------------------------------------------------------- 1 | from brownie import config, network, accounts, Contract, interface 2 | from web3 import Web3 3 | 4 | 5 | LOCAL_BLOCKCHAINS = ["ganache-local", "development"] 6 | 7 | FORKED_BLOCHCHAINS = ["mainnet-fork", "mainnet-fork-dev"] 8 | 9 | ZERO_ADDRESS = "0x0000000000000000000000000000000000000000" 10 | 11 | def get_account(index=None): 12 | if network.show_active() in LOCAL_BLOCKCHAINS or network.show_active() in FORKED_BLOCHCHAINS: 13 | if index is not None: 14 | return accounts[index] 15 | else: 16 | return accounts[0] 17 | else: 18 | return accounts.add(config["wallets"]["from_key"]) 19 | 20 | def toWei(amount): 21 | return Web3.toWei(amount, "ether") 22 | 23 | def fromWei(amount): 24 | return Web3.fromWei(amount, "ether") 25 | 26 | 27 | def get_contract(_contract, contract_address): 28 | contract = Contract.from_abi(_contract._name, contract_address, _contract.abi) 29 | 30 | def approve_erc20(erc20_address, spender, amount, account): 31 | erc20 = interface.IERC20(erc20_address) 32 | approve_tx = erc20.approve(spender, amount, {"from": account}) 33 | approve_tx.wait(1) 34 | 35 | print("----- Erc20 approved -----") -------------------------------------------------------------------------------- /scripts/update_front_end.py: -------------------------------------------------------------------------------- 1 | import json, yaml, os, shutil 2 | 3 | # functions to copy smart contract data to the front end 4 | 5 | def copy_build_folder(): 6 | copy2frontend("./build", "./front-end/src/artifacts") 7 | with open("brownie-config.yaml", "r") as brownie_config: 8 | config_dict = yaml.load(brownie_config, Loader=yaml.FullLoader) 9 | with open("./front-end/src/utils/brownie-config.json", 'w') as brownie_config_json: 10 | json.dump(config_dict, brownie_config_json) 11 | 12 | print("front end updated !!!") 13 | 14 | def copy2frontend(src, des): 15 | if os.path.exists(des): 16 | shutil.rmtree(des) 17 | shutil.copytree(src, des) 18 | 19 | 20 | def main(): 21 | copy_build_folder() --------------------------------------------------------------------------------