diff --git a/.browserslistrc b/.browserslistrc new file mode 100644 index 0000000..214388f --- /dev/null +++ b/.browserslistrc @@ -0,0 +1,3 @@ +> 1% +last 2 versions +not dead diff --git a/.env b/.env new file mode 100644 index 0000000..7c35c84 --- /dev/null +++ b/.env @@ -0,0 +1,4 @@ +VUE_APP_WS_URL=wss://rinkeby.infura.io/ws/v3/6c266c0719d144369f24093fbed4c6d8 +VUE_APP_HUB_URL=https://makiswap-dev.thinkincoin.com +VUE_APP_IPFS_NODE=gateway.pinata.cloud +VUE_DEFAULT_NETWORK=4 diff --git a/.env.dev b/.env.dev new file mode 100644 index 0000000..95ceed5 --- /dev/null +++ b/.env.dev @@ -0,0 +1,4 @@ +HOST=makiswap-dev.thinkincoin.com +VUE_APP_HTTP_URL=https://polygon-mainnet.infura.io/v3/6c266c0719d144369f24093fbed4c6d8 +VUE_APP_HUB_URL=https://makiswap-dev.thinkincoin.com +VUE_APP_IPFS_NODE=gateway.pinata.cloud diff --git a/.eslintrc.js b/.eslintrc.js new file mode 100644 index 0000000..ea2969f --- /dev/null +++ b/.eslintrc.js @@ -0,0 +1,24 @@ +module.exports = { + root: true, + env: { + node: true + }, + extends: [ + 'plugin:vue/essential', + 'eslint:recommended', + '@vue/typescript/recommended', + '@vue/prettier', + '@vue/prettier/@typescript-eslint' + ], + parserOptions: { + ecmaVersion: 2020 + }, + rules: { + 'no-console': 'off', + 'no-debugger': process.env.NODE_ENV === 'production' ? 'warn' : 'off', + '@typescript-eslint/no-explicit-any': 'off', + '@typescript-eslint/ban-ts-ignore': 'off', + '@typescript-eslint/camelcase': 'off', + '@typescript-eslint/no-undef': 'off' + } +}; diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..11f5d71 --- /dev/null +++ b/.gitignore @@ -0,0 +1,22 @@ +.DS_Store +node_modules +/dist + +# local env files +.env.local +.env.*.local + +# Log files +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* + +# Editor directories and files +.idea +.vscode +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? diff --git a/.prettierrc.js b/.prettierrc.js new file mode 100644 index 0000000..7d93e18 --- /dev/null +++ b/.prettierrc.js @@ -0,0 +1,3 @@ +module.exports = { + singleQuote: true +}; diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..7c9b370 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) Balancer Labs + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..5de5f69 --- /dev/null +++ b/README.md @@ -0,0 +1,25 @@ +# Snapshot + +## Project setup +``` +npm install +``` + +### Compiles and hot-reloads for development +``` +npm run serve +``` + +### Compiles and minifies for production +``` +npm run build +``` + +### Lints and fixes files +``` +npm run lint +``` + +## License + +[MIT](LICENSE). diff --git a/babel.config.js b/babel.config.js new file mode 100644 index 0000000..916db64 --- /dev/null +++ b/babel.config.js @@ -0,0 +1,3 @@ +module.exports = { + presets: ['@vue/cli-plugin-babel/preset'] +}; diff --git a/package.json b/package.json new file mode 100644 index 0000000..b7cc453 --- /dev/null +++ b/package.json @@ -0,0 +1,72 @@ +{ + "name": "snapshot", + "version": "0.1.1", + "repository": "balancer-labs/snapshot", + "license": "MIT", + "scripts": { + "serve": "vue-cli-service serve", + "build": "vue-cli-service build", + "lint": "vue-cli-service lint" + }, + "dependencies": { + "@bonustrack/lock": "github:bonustrack/lock#e66d69d728e4003c4fcf5b124387bb16c37cbfe1", + "@ethersproject/abi": "^5.0.1", + "@ethersproject/address": "^5.0.1", + "@ethersproject/constants": "^5.0.1", + "@ethersproject/contracts": "^5.0.1", + "@ethersproject/providers": "^5.0.4", + "@ethersproject/units": "^5.0.1", + "@ethersproject/wallet": "^5.0.1", + "@pinata/sdk": "^1.1.10", + "@portis/web3": "2.0.0-beta.49", + "@primer/css": "^14.4.0", + "@vue/cli-plugin-babel": "^4.4.0", + "@vue/cli-plugin-eslint": "^4.4.0", + "@vue/cli-plugin-typescript": "^4.4.0", + "@vue/cli-service": "^4.4.0", + "@walletconnect/web3-provider": "^1.0.13", + "bluebird": "^3.7.2", + "body-parser": "^1.19.0", + "core-js": "^3.6.5", + "cors": "^2.8.5", + "eslint": "^6.7.2", + "fortmatic": "^2.0.6", + "frameguard": "^3.1.0", + "json-to-graphql-query": "^2.0.0", + "jsonexport": "^3.0.1", + "lodash": "^4.17.15", + "numeral": "^2.0.4", + "primer-support": "^5.0.0", + "redis": "^3.0.2", + "remarkable": "^2.0.1", + "sanitize-html": "^1.27.1", + "serve-static": "^1.14.1", + "stylus": "^0.54.8", + "stylus-loader": "^3.0.2", + "typescript": "~3.9.3", + "vue": "^2.6.11", + "vue-autofocus-directive": "^1.0.4", + "vue-cli-plugin-webpack-bundle-analyzer": "^2.0.0", + "vue-i18n": "^8.18.1", + "vue-infinite-scroll": "^2.0.2", + "vue-jazzicon": "^0.1.3", + "vue-router": "^3.2.0", + "vue-textarea-autosize": "^1.1.1", + "vuex": "^3.4.0" + }, + "devDependencies": { + "@types/node": "^14.0.13", + "@typescript-eslint/eslint-plugin": "^2.33.0", + "@typescript-eslint/parser": "^2.33.0", + "@vue/cli-plugin-router": "^4.4.0", + "@vue/cli-plugin-vuex": "^4.4.0", + "@vue/eslint-config-prettier": "^6.0.0", + "@vue/eslint-config-typescript": "^5.0.2", + "eslint-plugin-prettier": "^3.1.3", + "eslint-plugin-vue": "^6.2.2", + "node-sass": "^4.12.0", + "prettier": "^1.19.1", + "sass-loader": "^8.0.2", + "vue-template-compiler": "^2.6.11" + } +} diff --git a/public/favicon.ico b/public/favicon.ico new file mode 100644 index 0000000..f103ead Binary files /dev/null and b/public/favicon.ico differ diff --git a/public/index.html b/public/index.html new file mode 100644 index 0000000..9e5a626 --- /dev/null +++ b/public/index.html @@ -0,0 +1,16 @@ + + + + + + + Snapshot + + + +
+ + + diff --git a/src/App.vue b/src/App.vue new file mode 100644 index 0000000..1e36f62 --- /dev/null +++ b/src/App.vue @@ -0,0 +1,25 @@ + + + diff --git a/src/assets/fonts/Calibre-Medium.eot b/src/assets/fonts/Calibre-Medium.eot new file mode 100644 index 0000000..bf85d1d Binary files /dev/null and b/src/assets/fonts/Calibre-Medium.eot differ diff --git a/src/assets/fonts/Calibre-Medium.ttf b/src/assets/fonts/Calibre-Medium.ttf new file mode 100644 index 0000000..9932cbf Binary files /dev/null and b/src/assets/fonts/Calibre-Medium.ttf differ diff --git a/src/assets/fonts/Calibre-Medium.woff b/src/assets/fonts/Calibre-Medium.woff new file mode 100644 index 0000000..bb702dc Binary files /dev/null and b/src/assets/fonts/Calibre-Medium.woff differ diff --git a/src/assets/fonts/Calibre-Semibold.eot b/src/assets/fonts/Calibre-Semibold.eot new file mode 100644 index 0000000..8303c21 Binary files /dev/null and b/src/assets/fonts/Calibre-Semibold.eot differ diff --git a/src/assets/fonts/Calibre-Semibold.ttf b/src/assets/fonts/Calibre-Semibold.ttf new file mode 100644 index 0000000..457cf3d Binary files /dev/null and b/src/assets/fonts/Calibre-Semibold.ttf differ diff --git a/src/assets/fonts/Calibre-Semibold.woff b/src/assets/fonts/Calibre-Semibold.woff new file mode 100644 index 0000000..5bea21c Binary files /dev/null and b/src/assets/fonts/Calibre-Semibold.woff differ diff --git a/src/assets/fonts/iconfont.css b/src/assets/fonts/iconfont.css new file mode 100644 index 0000000..f53652c --- /dev/null +++ b/src/assets/fonts/iconfont.css @@ -0,0 +1,77 @@ +@font-face {font-family: "iconfont"; + src: url('iconfont.eot?t=1595018697091'); /* IE9 */ + src: url('iconfont.eot?t=1595018697091#iefix') format('embedded-opentype'), /* IE6-IE8 */ + url('data:application/x-font-woff2;charset=utf-8;base64,d09GMgABAAAAAAhoAAsAAAAAEKQAAAgZAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHEIGVgCFFAqRJI1LATYCJANACyIABCAFhG0HgUEb3g2jopRwBpP9RYJtLP2hg6GpjdjQNCwMlxaY9USehGvQ1PapDEvsQJDx8M9+/X6fKzqGmCQRiSSxap5IUEmEpCl5Mmme5rHWa8Cvf/62V8ncvke6Rpbs3GraHuE//oZ/D0jS83W6xm4hW+H6A572L8k6tM6gj8lImm47yFNy5+Z/tz5waE9u+6WDgm92+3Kbf7igj4GptVZFNOri7VOitRP932Nu8X1MJX1EKtMZquuLJ4jECwXx0KmRUt5APOslmx+VaJ5AY65NqX3ntw+kKMOqA/0u+S4jRUueLCA8VDmFx43ZIJ6Sq5K7yRvcUz4+xq0JfxJ5ir3w8JkzhxwO/R5P74xopyQ3THYYj8NIsRqRPaQPnvIr0MRPZEYzNPMAszXJX+sMDevhahvscNZVt9z3Zvhn7PTHRyMC3F97nZodu16YzbnPaShxpJBplCpdqVqrI9fTl9z/eQWq6cD7ZWufISGLYFhnUTBcjWRfuAFIA7gDSAl4FkgFeBVIF/AWkBTwPtSyha+BtIBvgHQA/yCLnLFTSE+Bp4H1TUwGIyRggBvmIxYgyWPS44QNuqQpZJIfim5WCSGRBm8eNFc7h/lqzckzMta7e9G+6tL0brcKU4PjgxzXdJUq4XysXdBe5ghKFAjCYAmuNp4IpcY9YTrLuXw2VfyM2s+Xvyh7XWy9ITaanaGIybGeNkgbvQkJxixrWSNQVu+Oe/eQAeXxCfChg0mjX0MoZWY13xNDkJxxzEjqMaVSENQlV6ZIVIO6Eg5GIMxzBdKxyyE9Dn1Sl+FinPSi+yGw7A/qmqCTu40HwuGAR9aeuBTcPcmm9pqvJMrY55GwHwrtdTIrtL0k1d0oBwieJ0WREoQZY88xz7Me2j1gceufi0Dsv3qFr2cEPUfzrNhHu/UpWk6qF1g/RvRjeQOBJsjJ2aBB1qgQJapA5IP6lE2OFNIkb7TS7hVxTOpmp+vQYRsmVJ5PM8h9TvDvkCfMSHBChOl0gsmWeMIT/CKfaD8TKghaRkw1CbkMT95gm0URznFBk/zD9dTPeOphgrYmiu9RwpebpVCGClQQDkkH++AxUctEnHLMESGxOxMVrJNxSDuvcFE+R/h61etiLMY4+mULDPQkG7oYJOxEIrC40U8YjYN0UJCBP4wwHB+zhVLyMQcTu0prso8P36BgoxGCB+hgRQzuza4nxu0hWoU527tC5JTZNnY8iAgyGCBoeftfruW4pUq9KRSx5jGxUfEqHw1TxaHV8rHrEbZjkZSTTSatR8IsV5crTlwLtx4OIyYGQ9G2o5F2V/un0FVfXeQ51hpZDeiCBcqRNkxtXGJ7tudO/JbTxq3VK5vHdMuDt+26vL79Dn/o5W+d76yNiGloQH+Z0dIiJyX3yar5MYn9h2Z98wLIqxXRkFIZcCPAIeBU/5tK5U3/0VFRNyCFHDoarFVvxi9r3F2d2lkzVNveQeJkWztpyGS7nAsE9Fb4k93tLvwKvrnstqvuhqZMc2NBnQuvgCN5N7cCbD13xev+HPoXXId+Ha+9myo2eW90QHQIQz53exdXLJ5yBWXnXBC+wBXt55rSR3XL4Vy0fsPU1CKIwqo8Pv/8k4mC505iklHz0eHcAg7HxUppoPTj/mC4Tw0Onub1mc4Ky81BDh8mihfXbc3V6fK27WYIOX5r3p5teZ1yt9UuLiYCDtLA6BMa6NHoIc2RrBOQPd0LhfIKSNekQ0X5j1tACtGkI+XlDped3q+AJL9nBPMx+h2fqCifd9CTz6O2/Oj/29mzlI3ZuraPpH+IL3y8a0UDBcObNBM6CbsYeyIlsm5ri39jHFbr35R+d+fdpoxaPyzOr7F/X0RdAPbkY4t0kvcqMGDb6ZiDhS4JMu7zTlQUPDpa9cILfBXkdzuHvBGQzWpQPJED8c1xW3DoOtQkAYkIuzQT8T0uqG1lN2P3xrnkslp8S9xe3IELdsXtgfy5eyVBgYExufOePvXb+wcfq5n/A9TPr4cf1N88dvD9307NfUpTu8IPgxt7whz4/RNDtfO902QUOe2FduiJ7xGO1A51LklCelet6hXDkVWrSnpWrTYuWP3e0g7F/x1C1tFxTn8OciTxe2EXLnxZ0pW/Y7z75/PvLKlbgm3+3D2+Ix9aV3ocWjkKwIjXYqlKwqkHWK/8AidW4fh3d6PfApDS6AtMhA79sDb5GKW9mCsWiaXdNLIH9UZjaI+UepY7qbNfY7d7buz+V7UXvvqvm/ZOTh39PzLn0juodj51FECd0+ScBKwg/+VYcfCnRill3gU6s6QBT7EpQcPpcDarmOivSGlKZOZEKk0xQKI0B6Qqi90z79Ug11oHCpWdoLHKxe2tSVBGZDVWemVAGHgDiZ4nIDXwQ4CA9y/ITfUPCoPAQONIdPRsLY2l5RMEZsCh4xfqcyUFX2jKav87cG3E0Mwp8U+A2q+nw97A3n4BEjCLS/TEHRkjqEAV03PGMogiRRNUAXDT84xJtvt94XVpj6uYlO2FAGOk9A5q7EXVxymSWNsoO97/DnBZEQYDpv1RfQKQ5m+dGuoZRHC/0MhI01ZlqDbhGjEEC1QYi5QYdU4wiLgWhUq8jwsAzujxEjQltvXJciKqple8FI/5DdBgH3YQaKSRRR5FlFFFHU200Ylu9KIfg9Ao3fRdyYxFaPIK4uAnZktZE/kSnBz3gIeFKUPpSzevgSH3sjFIm+OR0pB3fePZcTmJrN7SMYuiGswMoGTRVmyzw7SrsmPGw6zVgEWGqKZbNimrgiNoJSEAAA==') format('woff2'), + url('iconfont.woff?t=1595018697091') format('woff'), + url('iconfont.ttf?t=1595018697091') format('truetype'), /* chrome, firefox, opera, Safari, Android, iOS 4.2+ */ + url('iconfont.svg?t=1595018697091#iconfont') format('svg'); /* iOS 4.1- */ +} + +.iconfont { + font-family: "iconfont" !important; + font-size: 16px; + font-style: normal; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} + +.iconsignature:before { + content: "\e600"; +} + +.iconreceipt-outlined:before { + content: "\e8eb"; +} + +.iconcheck:before { + content: "\e679"; +} + +.iconwarning:before { + content: "\e62c"; +} + +.iconsearch:before { + content: "\e6f2"; +} + +.iconmenu:before { + content: "\e609"; +} + +.iconclose:before { + content: "\e63e"; +} + +.icongithub:before { + content: "\e667"; +} + +.iconplus-small:before { + content: "\e69d"; +} + +.iconexternal-link:before { + content: "\e636"; +} + +.icongo:before { + content: "\e6cb"; +} + +.iconback:before { + content: "\e6cc"; +} + +.iconuser:before { + content: "\e66f"; +} + +.iconarrow-up:before { + content: "\e75c"; +} + +.iconarrow-down:before { + content: "\e75d"; +} + diff --git a/src/assets/fonts/iconfont.eot b/src/assets/fonts/iconfont.eot new file mode 100644 index 0000000..13e7224 Binary files /dev/null and b/src/assets/fonts/iconfont.eot differ diff --git a/src/assets/fonts/iconfont.json b/src/assets/fonts/iconfont.json new file mode 100644 index 0000000..efe2c28 --- /dev/null +++ b/src/assets/fonts/iconfont.json @@ -0,0 +1,114 @@ +{ + "id": "1946815", + "name": "gang", + "font_family": "iconfont", + "css_prefix_text": "icon", + "description": "", + "glyphs": [ + { + "icon_id": "11399282", + "name": "signature", + "font_class": "signature", + "unicode": "e600", + "unicode_decimal": 58880 + }, + { + "icon_id": "15617545", + "name": "receipt-outlined", + "font_class": "receipt-outlined", + "unicode": "e8eb", + "unicode_decimal": 59627 + }, + { + "icon_id": "10561798", + "name": "Check, label", + "font_class": "check", + "unicode": "e679", + "unicode_decimal": 59001 + }, + { + "icon_id": "59347", + "name": "warning", + "font_class": "warning", + "unicode": "e62c", + "unicode_decimal": 58924 + }, + { + "icon_id": "1262104", + "name": "search", + "font_class": "search", + "unicode": "e6f2", + "unicode_decimal": 59122 + }, + { + "icon_id": "1336076", + "name": "Menu", + "font_class": "menu", + "unicode": "e609", + "unicode_decimal": 58889 + }, + { + "icon_id": "2518398", + "name": "close", + "font_class": "close", + "unicode": "e63e", + "unicode_decimal": 58942 + }, + { + "icon_id": "5679219", + "name": "mark-github", + "font_class": "github", + "unicode": "e667", + "unicode_decimal": 58983 + }, + { + "icon_id": "5679273", + "name": "plus-small", + "font_class": "plus-small", + "unicode": "e69d", + "unicode_decimal": 59037 + }, + { + "icon_id": "7141712", + "name": "external-link", + "font_class": "external-link", + "unicode": "e636", + "unicode_decimal": 58934 + }, + { + "icon_id": "11262646", + "name": "go", + "font_class": "go", + "unicode": "e6cb", + "unicode_decimal": 59083 + }, + { + "icon_id": "11262647", + "name": "back", + "font_class": "back", + "unicode": "e6cc", + "unicode_decimal": 59084 + }, + { + "icon_id": "13519508", + "name": "user-solid", + "font_class": "user", + "unicode": "e66f", + "unicode_decimal": 58991 + }, + { + "icon_id": "13895880", + "name": "arrow-up", + "font_class": "arrow-up", + "unicode": "e75c", + "unicode_decimal": 59228 + }, + { + "icon_id": "14232782", + "name": "arrow-up", + "font_class": "arrow-down", + "unicode": "e75d", + "unicode_decimal": 59229 + } + ] +} diff --git a/src/assets/fonts/iconfont.svg b/src/assets/fonts/iconfont.svg new file mode 100644 index 0000000..1e5ae12 --- /dev/null +++ b/src/assets/fonts/iconfont.svg @@ -0,0 +1,71 @@ + + + + + +Created by iconfont + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/assets/fonts/iconfont.ttf b/src/assets/fonts/iconfont.ttf new file mode 100644 index 0000000..28ba4cb Binary files /dev/null and b/src/assets/fonts/iconfont.ttf differ diff --git a/src/assets/fonts/iconfont.woff b/src/assets/fonts/iconfont.woff new file mode 100644 index 0000000..7873a6e Binary files /dev/null and b/src/assets/fonts/iconfont.woff differ diff --git a/src/assets/fonts/iconfont.woff2 b/src/assets/fonts/iconfont.woff2 new file mode 100644 index 0000000..2fa4c90 Binary files /dev/null and b/src/assets/fonts/iconfont.woff2 differ diff --git a/src/assets/logo.svg b/src/assets/logo.svg new file mode 100644 index 0000000..ee8d35e --- /dev/null +++ b/src/assets/logo.svg @@ -0,0 +1,19 @@ + + + + pebbles-pad + Created with Sketch. + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/components/Avatar.vue b/src/components/Avatar.vue new file mode 100644 index 0000000..5b414b2 --- /dev/null +++ b/src/components/Avatar.vue @@ -0,0 +1,13 @@ + + + diff --git a/src/components/Block.vue b/src/components/Block.vue new file mode 100644 index 0000000..3de78c9 --- /dev/null +++ b/src/components/Block.vue @@ -0,0 +1,19 @@ + + + diff --git a/src/components/Block/Results.vue b/src/components/Block/Results.vue new file mode 100644 index 0000000..4335806 --- /dev/null +++ b/src/components/Block/Results.vue @@ -0,0 +1,81 @@ + + + diff --git a/src/components/Block/Votes.vue b/src/components/Block/Votes.vue new file mode 100644 index 0000000..8adc19e --- /dev/null +++ b/src/components/Block/Votes.vue @@ -0,0 +1,79 @@ + + + diff --git a/src/components/Container.vue b/src/components/Container.vue new file mode 100644 index 0000000..ecf77f6 --- /dev/null +++ b/src/components/Container.vue @@ -0,0 +1,13 @@ + + + diff --git a/src/components/Icon.vue b/src/components/Icon.vue new file mode 100644 index 0000000..6bf4016 --- /dev/null +++ b/src/components/Icon.vue @@ -0,0 +1,21 @@ + + + + + diff --git a/src/components/Modal/About.vue b/src/components/Modal/About.vue new file mode 100644 index 0000000..51dc03b --- /dev/null +++ b/src/components/Modal/About.vue @@ -0,0 +1,77 @@ + + + diff --git a/src/components/Modal/Account.vue b/src/components/Modal/Account.vue new file mode 100644 index 0000000..33eb244 --- /dev/null +++ b/src/components/Modal/Account.vue @@ -0,0 +1,82 @@ + + + diff --git a/src/components/Modal/Confirm.vue b/src/components/Modal/Confirm.vue new file mode 100644 index 0000000..f0e2c91 --- /dev/null +++ b/src/components/Modal/Confirm.vue @@ -0,0 +1,95 @@ + + + diff --git a/src/components/Modal/Receipt.vue b/src/components/Modal/Receipt.vue new file mode 100644 index 0000000..3ed54b6 --- /dev/null +++ b/src/components/Modal/Receipt.vue @@ -0,0 +1,39 @@ + + + diff --git a/src/components/Modal/SelectDate.vue b/src/components/Modal/SelectDate.vue new file mode 100644 index 0000000..0450b02 --- /dev/null +++ b/src/components/Modal/SelectDate.vue @@ -0,0 +1,68 @@ + + + diff --git a/src/components/Modal/User.vue b/src/components/Modal/User.vue new file mode 100644 index 0000000..867812c --- /dev/null +++ b/src/components/Modal/User.vue @@ -0,0 +1,22 @@ + + + diff --git a/src/components/Notifications.vue b/src/components/Notifications.vue new file mode 100644 index 0000000..03e8a47 --- /dev/null +++ b/src/components/Notifications.vue @@ -0,0 +1,40 @@ + + + diff --git a/src/components/RowLoading.vue b/src/components/RowLoading.vue new file mode 100644 index 0000000..5ac2647 --- /dev/null +++ b/src/components/RowLoading.vue @@ -0,0 +1,22 @@ + + + diff --git a/src/components/RowProposal.vue b/src/components/RowProposal.vue new file mode 100644 index 0000000..9fb6672 --- /dev/null +++ b/src/components/RowProposal.vue @@ -0,0 +1,42 @@ + + + diff --git a/src/components/State.vue b/src/components/State.vue new file mode 100644 index 0000000..4bc0f2d --- /dev/null +++ b/src/components/State.vue @@ -0,0 +1,25 @@ + + + diff --git a/src/components/Sticky.vue b/src/components/Sticky.vue new file mode 100644 index 0000000..658c60f --- /dev/null +++ b/src/components/Sticky.vue @@ -0,0 +1,43 @@ + + + diff --git a/src/components/Token.vue b/src/components/Token.vue new file mode 100644 index 0000000..5b18b5d --- /dev/null +++ b/src/components/Token.vue @@ -0,0 +1,18 @@ + + + diff --git a/src/components/Topnav.vue b/src/components/Topnav.vue new file mode 100644 index 0000000..2ea852b --- /dev/null +++ b/src/components/Topnav.vue @@ -0,0 +1,106 @@ + + + diff --git a/src/components/Ui/Button.vue b/src/components/Ui/Button.vue new file mode 100644 index 0000000..c3fe6a9 --- /dev/null +++ b/src/components/Ui/Button.vue @@ -0,0 +1,67 @@ + + + + + diff --git a/src/components/Ui/Calendar.vue b/src/components/Ui/Calendar.vue new file mode 100644 index 0000000..7421abd --- /dev/null +++ b/src/components/Ui/Calendar.vue @@ -0,0 +1,143 @@ + + + + + diff --git a/src/components/Ui/Counter.vue b/src/components/Ui/Counter.vue new file mode 100644 index 0000000..f0f3ad9 --- /dev/null +++ b/src/components/Ui/Counter.vue @@ -0,0 +1,28 @@ + + + + + diff --git a/src/components/Ui/Label.vue b/src/components/Ui/Label.vue new file mode 100644 index 0000000..2d4517f --- /dev/null +++ b/src/components/Ui/Label.vue @@ -0,0 +1,17 @@ + + + diff --git a/src/components/Ui/Loading.vue b/src/components/Ui/Loading.vue new file mode 100644 index 0000000..91a3a39 --- /dev/null +++ b/src/components/Ui/Loading.vue @@ -0,0 +1,66 @@ + + + diff --git a/src/components/Ui/Markdown.vue b/src/components/Ui/Markdown.vue new file mode 100644 index 0000000..100f6ef --- /dev/null +++ b/src/components/Ui/Markdown.vue @@ -0,0 +1,42 @@ + + + + diff --git a/src/components/Ui/Modal.vue b/src/components/Ui/Modal.vue new file mode 100644 index 0000000..a4f89e6 --- /dev/null +++ b/src/components/Ui/Modal.vue @@ -0,0 +1,79 @@ + + + + + diff --git a/src/components/Ui/Progress.vue b/src/components/Ui/Progress.vue new file mode 100644 index 0000000..eb49c5b --- /dev/null +++ b/src/components/Ui/Progress.vue @@ -0,0 +1,40 @@ + + + + + diff --git a/src/components/User.vue b/src/components/User.vue new file mode 100644 index 0000000..ec7ce9a --- /dev/null +++ b/src/components/User.vue @@ -0,0 +1,43 @@ + + + diff --git a/src/config.json b/src/config.json new file mode 100644 index 0000000..7df8b50 --- /dev/null +++ b/src/config.json @@ -0,0 +1,88 @@ +{ + "master": { + "network": "homestead", + "chainId": 4, + "subgraphUrl": "https://api.thegraph.com/subgraphs/", + "hubUrl": "https://makiswap-dev.thinkincoin.com", + "multicall": "0xb5ec65821e27de5ec9d52d5826057a99bd78c875", + "connectors": { + "injected": { + "id": "injected", + "name": "MetaMask" + }, + "portis": { + "id": "portis", + "name": "Portis", + "options": { + "dappId": "3f1c3cfc-7dd5-4e8a-aa03-71ff7396d9fe", + "network": "mainnet" + } + }, + "fortmatic": { + "id": "fortmatic", + "name": "Fortmatic", + "options": { + "apiKey": "pk_live_9CE8FD92E54684ED" + } + } + } + }, + "develop": { + "network": "heco", + "chainId": 4, + "subgraphUrl": "https://api.thegraph.com/subgraphs/", + "hubUrl": "https://makiswap-dev.thinkincoin.com", + "multicall": "0xb5ec65821e27de5ec9d52d5826057a99bd78c875", + "disableHostCheck": true, + "connectors": { + "injected": { + "id": "injected", + "name": "MetaMask" + }, + "portis": { + "id": "portis", + "name": "Portis", + "options": { + "dappId": "3f1c3cfc-7dd5-4e8a-aa03-71ff7396d9fe", + "network": "mainnet" + } + }, + "fortmatic": { + "id": "fortmatic", + "name": "Fortmatic", + "options": { + "apiKey": "pk_live_9CE8FD92E54684ED" + } + } + } + }, + "local": { + "network": "homestead", + "chainId": 4, + "subgraphUrl": "https://api.thegraph.com/subgraphs/", + "hubUrl": "http://localhost:3001", + "multicall": "0xeefBa1e63905eF1D7ACbA5a8513c70307C1cE441", + "disableHostCheck": true, + "connectors": { + "injected": { + "id": "injected", + "name": "MetaMask" + }, + "portis": { + "id": "portis", + "name": "Portis", + "options": { + "dappId": "3f1c3cfc-7dd5-4e8a-aa03-71ff7396d9fe", + "network": "mainnet" + } + }, + "magic": { + "id": "magic", + "name": "Magic", + "options": { + "apiKey": "pk_live_9CE8FD92E54684ED" + } + } + } + } +} diff --git a/src/fonts.scss b/src/fonts.scss new file mode 100644 index 0000000..c6aee22 --- /dev/null +++ b/src/fonts.scss @@ -0,0 +1,21 @@ +@import './assets/fonts/iconfont.css'; + +@font-face { + font-family: 'Calibre-Medium'; + src: url('./assets/fonts/Calibre-Medium.eot'); + src: url('./assets/fonts/Calibre-Medium.eot?#iefix') format('embedded-opentype'), + url('./assets/fonts/Calibre-Medium.woff') format('woff'), + url('./assets/fonts/Calibre-Medium.ttf') format('truetype'); + font-weight: normal; + font-style: normal; +} + +@font-face { + font-family: 'Calibre-Semibold'; + src: url('./assets/fonts/Calibre-Semibold.eot'); + src: url('./assets/fonts/Calibre-Semibold.eot?#iefix') format('embedded-opentype'), + url('./assets/fonts/Calibre-Semibold.woff') format('woff'), + url('./assets/fonts/Calibre-Semibold.ttf') format('truetype'); + font-weight: normal; + font-style: normal; +} diff --git a/src/helpers/abi/Multicall.json b/src/helpers/abi/Multicall.json new file mode 100644 index 0000000..801f1df --- /dev/null +++ b/src/helpers/abi/Multicall.json @@ -0,0 +1,146 @@ +{ + "contractName": "Multicall", + "abi": [ + { + "constant": true, + "inputs": [], + "name": "getCurrentBlockTimestamp", + "outputs": [ + { + "name": "timestamp", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "components": [ + { + "name": "target", + "type": "address" + }, + { + "name": "callData", + "type": "bytes" + } + ], + "name": "calls", + "type": "tuple[]" + } + ], + "name": "aggregate", + "outputs": [ + { + "name": "blockNumber", + "type": "uint256" + }, + { + "name": "returnData", + "type": "bytes[]" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "getLastBlockHash", + "outputs": [ + { + "name": "blockHash", + "type": "bytes32" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "name": "addr", + "type": "address" + } + ], + "name": "getEthBalance", + "outputs": [ + { + "name": "balance", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "getCurrentBlockDifficulty", + "outputs": [ + { + "name": "difficulty", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "getCurrentBlockGasLimit", + "outputs": [ + { + "name": "gaslimit", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "getCurrentBlockCoinbase", + "outputs": [ + { + "name": "coinbase", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "name": "blockNumber", + "type": "uint256" + } + ], + "name": "getBlockHash", + "outputs": [ + { + "name": "blockHash", + "type": "bytes32" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + } + ] +} diff --git a/src/helpers/abi/TestToken.json b/src/helpers/abi/TestToken.json new file mode 100644 index 0000000..21d7a21 --- /dev/null +++ b/src/helpers/abi/TestToken.json @@ -0,0 +1,1177 @@ +{ + "contractName": "TestToken", + "abi": [ + { + "constant": true, + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "mint", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "decimals", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "addedValue", + "type": "uint256" + } + ], + "name": "increaseAllowance", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "symbol", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "subtractedValue", + "type": "uint256" + } + ], + "name": "decreaseAllowance", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "spender", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "name", + "type": "string" + }, + { + "internalType": "string", + "name": "symbol", + "type": "string" + }, + { + "internalType": "uint8", + "name": "decimals", + "type": "uint8" + }, + { + "internalType": "uint256", + "name": "initialSupply", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event" + } + ], + "metadata": "{\"compiler\":{\"version\":\"0.5.11+commit.c082d0b4\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"constant\":true,\"inputs\":[],\"name\":\"name\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"approve\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"totalSupply\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"transferFrom\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"decimals\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"\",\"type\":\"uint8\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"addedValue\",\"type\":\"uint256\"}],\"name\":\"increaseAllowance\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"balanceOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"symbol\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"subtractedValue\",\"type\":\"uint256\"}],\"name\":\"decreaseAllowance\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"transfer\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"}],\"name\":\"allowance\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"symbol\",\"type\":\"string\"},{\"internalType\":\"uint8\",\"name\":\"decimals\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"initialSupply\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"Transfer\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"Approval\",\"type\":\"event\"}],\"devdoc\":{\"methods\":{\"allowance(address,address)\":{\"details\":\"See `IERC20.allowance`.\"},\"approve(address,uint256)\":{\"details\":\"See `IERC20.approve`. * Requirements: * - `spender` cannot be the zero address.\"},\"balanceOf(address)\":{\"details\":\"See `IERC20.balanceOf`.\"},\"decimals()\":{\"details\":\"Returns the number of decimals used to get its user representation. For example, if `decimals` equals `2`, a balance of `505` tokens should be displayed to a user as `5,05` (`505 / 10 ** 2`). * Tokens usually opt for a value of 18, imitating the relationship between Ether and Wei. * > Note that this information is only used for _display_ purposes: it in no way affects any of the arithmetic of the contract, including `IERC20.balanceOf` and `IERC20.transfer`.\"},\"decreaseAllowance(address,uint256)\":{\"details\":\"Atomically decreases the allowance granted to `spender` by the caller. * This is an alternative to `approve` that can be used as a mitigation for problems described in `IERC20.approve`. * Emits an `Approval` event indicating the updated allowance. * Requirements: * - `spender` cannot be the zero address. - `spender` must have allowance for the caller of at least `subtractedValue`.\"},\"increaseAllowance(address,uint256)\":{\"details\":\"Atomically increases the allowance granted to `spender` by the caller. * This is an alternative to `approve` that can be used as a mitigation for problems described in `IERC20.approve`. * Emits an `Approval` event indicating the updated allowance. * Requirements: * - `spender` cannot be the zero address.\"},\"name()\":{\"details\":\"Returns the name of the token.\"},\"symbol()\":{\"details\":\"Returns the symbol of the token, usually a shorter version of the name.\"},\"totalSupply()\":{\"details\":\"See `IERC20.totalSupply`.\"},\"transfer(address,uint256)\":{\"details\":\"See `IERC20.transfer`. * Requirements: * - `recipient` cannot be the zero address. - the caller must have a balance of at least `amount`.\"},\"transferFrom(address,address,uint256)\":{\"details\":\"See `IERC20.transferFrom`. * Emits an `Approval` event indicating the updated allowance. This is not required by the EIP. See the note at the beginning of `ERC20`; * Requirements: - `sender` and `recipient` cannot be the zero address. - `sender` must have a balance of at least `value`. - the caller must have allowance for `sender`'s tokens of at least `amount`.\"}}},\"userdoc\":{\"methods\":{}}},\"settings\":{\"compilationTarget\":{\"/Users/thomas/Code/client/balancer/external-contracts/contracts/TestToken.sol\":\"TestToken\"},\"evmVersion\":\"petersburg\",\"libraries\":{},\"optimizer\":{\"enabled\":false,\"runs\":200},\"remappings\":[]},\"sources\":{\"/Users/thomas/Code/client/balancer/external-contracts/contracts/TestToken.sol\":{\"keccak256\":\"0x12fdb31a50e502eac30b764735cdb7d4acff7a51a564933dc79a63b9fd5d3f81\",\"urls\":[\"bzz-raw://512ea3a0db85076dedd0e75dd639e8777215f36742e7eac40fcffb30e4b5e40b\",\"dweb:/ipfs/QmZmEcpKAMkekctF5GJQgsAL4VqS62HepSDbmGbEr7evuW\"]},\"@openzeppelin/contracts/math/SafeMath.sol\":{\"keccak256\":\"0xd1804d04fb39689453f673601429a99a0c68c422a981fc338773df9a59180fe9\",\"urls\":[\"bzz-raw://1b9307920e0378d58c6677f8952ad090a9ecb30e878835e301a0d18386a870c1\",\"dweb:/ipfs/QmYYixTDVF4FXqFpYzEcufAwEY9BFBJ33Ew9ncsGvD7btC\"]},\"@openzeppelin/contracts/token/ERC20/ERC20.sol\":{\"keccak256\":\"0x852793a3c2f86d336a683b30d688ec3dcfc57451af5a2bf5975cda3b7191a901\",\"urls\":[\"bzz-raw://4f5b57664069671648fb81f55b0082faecdf1b2f159eec6b1fa6cef9b7d73bc5\",\"dweb:/ipfs/QmcyytaLs7zFdb4Uu7C5PmQRhQdB3wA3fUdkV6mkYfdDFH\"]},\"@openzeppelin/contracts/token/ERC20/ERC20Detailed.sol\":{\"keccak256\":\"0xc61b3603089b09a730d8ca72e9133a496cc4405da40e9b87c12f073245d774bf\",\"urls\":[\"bzz-raw://de8bb0003d53de236913f0e0102e7a9d015e02098f2495edd000f207fe2be2f4\",\"dweb:/ipfs/QmbtwNwAJEehWWL7yGGyyMoenQvcqtz91pqLgQPpLRoLYC\"]},\"@openzeppelin/contracts/token/ERC20/IERC20.sol\":{\"keccak256\":\"0x90e8c2521653bbb1768b05889c5760031e688d9cd361f167489b89215e201b95\",\"urls\":[\"bzz-raw://d0abb99bb8bfc2bc0a89902b8ed1dc0442ad08cc78cee64c291b3df6a27bcccc\",\"dweb:/ipfs/QmP5NaEwZthQeM2ESz4WTT3osrP7jhbvu7ocbttBi2JAw6\"]}},\"version\":1}", + "bytecode": "0x60806040523480156200001157600080fd5b50604051620014f5380380620014f5833981810160405260808110156200003757600080fd5b81019080805160405193929190846401000000008211156200005857600080fd5b838201915060208201858111156200006f57600080fd5b82518660018202830111640100000000821117156200008d57600080fd5b8083526020830192505050908051906020019080838360005b83811015620000c3578082015181840152602081019050620000a6565b50505050905090810190601f168015620000f15780820380516001836020036101000a031916815260200191505b50604052602001805160405193929190846401000000008211156200011557600080fd5b838201915060208201858111156200012c57600080fd5b82518660018202830111640100000000821117156200014a57600080fd5b8083526020830192505050908051906020019080838360005b838110156200018057808201518184015260208101905062000163565b50505050905090810190601f168015620001ae5780820380516001836020036101000a031916815260200191505b5060405260200180519060200190929190805190602001909291905050508383838260039080519060200190620001e79291906200048e565b508160049080519060200190620002009291906200048e565b5080600560006101000a81548160ff021916908360ff1602179055505050506200023133826200023b60201b60201c565b505050506200053d565b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415620002df576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601f8152602001807f45524332303a206d696e7420746f20746865207a65726f20616464726573730081525060200191505060405180910390fd5b620002fb816002546200040560201b62000e5d1790919060201c565b60028190555062000359816000808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020546200040560201b62000e5d1790919060201c565b6000808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508173ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef836040518082815260200191505060405180910390a35050565b60008082840190508381101562000484576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601b8152602001807f536166654d6174683a206164646974696f6e206f766572666c6f77000000000081525060200191505060405180910390fd5b8091505092915050565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10620004d157805160ff191683800117855562000502565b8280016001018555821562000502579182015b8281111562000501578251825591602001919060010190620004e4565b5b50905062000511919062000515565b5090565b6200053a91905b80821115620005365760008160009055506001016200051c565b5090565b90565b610fa8806200054d6000396000f3fe608060405234801561001057600080fd5b50600436106100a95760003560e01c80633950935111610071578063395093511461025f57806370a08231146102c557806395d89b411461031d578063a457c2d7146103a0578063a9059cbb14610406578063dd62ed3e1461046c576100a9565b806306fdde03146100ae578063095ea7b31461013157806318160ddd1461019757806323b872dd146101b5578063313ce5671461023b575b600080fd5b6100b66104e4565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156100f65780820151818401526020810190506100db565b50505050905090810190601f1680156101235780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b61017d6004803603604081101561014757600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050610586565b604051808215151515815260200191505060405180910390f35b61019f61059d565b6040518082815260200191505060405180910390f35b610221600480360360608110156101cb57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803590602001909291905050506105a7565b604051808215151515815260200191505060405180910390f35b610243610658565b604051808260ff1660ff16815260200191505060405180910390f35b6102ab6004803603604081101561027557600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291908035906020019092919050505061066f565b604051808215151515815260200191505060405180910390f35b610307600480360360208110156102db57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610714565b6040518082815260200191505060405180910390f35b61032561075c565b6040518080602001828103825283818151815260200191508051906020019080838360005b8381101561036557808201518184015260208101905061034a565b50505050905090810190601f1680156103925780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b6103ec600480360360408110156103b657600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803590602001909291905050506107fe565b604051808215151515815260200191505060405180910390f35b6104526004803603604081101561041c57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803590602001909291905050506108a3565b604051808215151515815260200191505060405180910390f35b6104ce6004803603604081101561048257600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506108ba565b6040518082815260200191505060405180910390f35b606060038054600181600116156101000203166002900480601f01602080910402602001604051908101604052809291908181526020018280546001816001161561010002031660029004801561057c5780601f106105515761010080835404028352916020019161057c565b820191906000526020600020905b81548152906001019060200180831161055f57829003601f168201915b5050505050905090565b6000610593338484610941565b6001905092915050565b6000600254905090565b60006105b4848484610b38565b61064d843361064885600160008a73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054610dd490919063ffffffff16565b610941565b600190509392505050565b6000600560009054906101000a900460ff16905090565b600061070a338461070585600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054610e5d90919063ffffffff16565b610941565b6001905092915050565b60008060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050919050565b606060048054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156107f45780601f106107c9576101008083540402835291602001916107f4565b820191906000526020600020905b8154815290600101906020018083116107d757829003601f168201915b5050505050905090565b6000610899338461089485600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054610dd490919063ffffffff16565b610941565b6001905092915050565b60006108b0338484610b38565b6001905092915050565b6000600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054905092915050565b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1614156109c7576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526024815260200180610f506024913960400191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415610a4d576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526022815260200180610f096022913960400191505060405180910390fd5b80600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925836040518082815260200191505060405180910390a3505050565b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff161415610bbe576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526025815260200180610f2b6025913960400191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415610c44576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526023815260200180610ee66023913960400191505060405180910390fd5b610c95816000808673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054610dd490919063ffffffff16565b6000808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550610d28816000808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054610e5d90919063ffffffff16565b6000808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef836040518082815260200191505060405180910390a3505050565b600082821115610e4c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601e8152602001807f536166654d6174683a207375627472616374696f6e206f766572666c6f77000081525060200191505060405180910390fd5b600082840390508091505092915050565b600080828401905083811015610edb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601b8152602001807f536166654d6174683a206164646974696f6e206f766572666c6f77000000000081525060200191505060405180910390fd5b809150509291505056fe45524332303a207472616e7366657220746f20746865207a65726f206164647265737345524332303a20617070726f766520746f20746865207a65726f206164647265737345524332303a207472616e736665722066726f6d20746865207a65726f206164647265737345524332303a20617070726f76652066726f6d20746865207a65726f2061646472657373a265627a7a723158201a68b621826f87edc888b7fee157c6fb5686e303e10dcb96b5e4698620f1204364736f6c634300050b0032", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100a95760003560e01c80633950935111610071578063395093511461025f57806370a08231146102c557806395d89b411461031d578063a457c2d7146103a0578063a9059cbb14610406578063dd62ed3e1461046c576100a9565b806306fdde03146100ae578063095ea7b31461013157806318160ddd1461019757806323b872dd146101b5578063313ce5671461023b575b600080fd5b6100b66104e4565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156100f65780820151818401526020810190506100db565b50505050905090810190601f1680156101235780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b61017d6004803603604081101561014757600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050610586565b604051808215151515815260200191505060405180910390f35b61019f61059d565b6040518082815260200191505060405180910390f35b610221600480360360608110156101cb57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803590602001909291905050506105a7565b604051808215151515815260200191505060405180910390f35b610243610658565b604051808260ff1660ff16815260200191505060405180910390f35b6102ab6004803603604081101561027557600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291908035906020019092919050505061066f565b604051808215151515815260200191505060405180910390f35b610307600480360360208110156102db57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610714565b6040518082815260200191505060405180910390f35b61032561075c565b6040518080602001828103825283818151815260200191508051906020019080838360005b8381101561036557808201518184015260208101905061034a565b50505050905090810190601f1680156103925780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b6103ec600480360360408110156103b657600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803590602001909291905050506107fe565b604051808215151515815260200191505060405180910390f35b6104526004803603604081101561041c57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803590602001909291905050506108a3565b604051808215151515815260200191505060405180910390f35b6104ce6004803603604081101561048257600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506108ba565b6040518082815260200191505060405180910390f35b606060038054600181600116156101000203166002900480601f01602080910402602001604051908101604052809291908181526020018280546001816001161561010002031660029004801561057c5780601f106105515761010080835404028352916020019161057c565b820191906000526020600020905b81548152906001019060200180831161055f57829003601f168201915b5050505050905090565b6000610593338484610941565b6001905092915050565b6000600254905090565b60006105b4848484610b38565b61064d843361064885600160008a73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054610dd490919063ffffffff16565b610941565b600190509392505050565b6000600560009054906101000a900460ff16905090565b600061070a338461070585600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054610e5d90919063ffffffff16565b610941565b6001905092915050565b60008060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050919050565b606060048054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156107f45780601f106107c9576101008083540402835291602001916107f4565b820191906000526020600020905b8154815290600101906020018083116107d757829003601f168201915b5050505050905090565b6000610899338461089485600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054610dd490919063ffffffff16565b610941565b6001905092915050565b60006108b0338484610b38565b6001905092915050565b6000600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054905092915050565b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1614156109c7576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526024815260200180610f506024913960400191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415610a4d576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526022815260200180610f096022913960400191505060405180910390fd5b80600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925836040518082815260200191505060405180910390a3505050565b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff161415610bbe576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526025815260200180610f2b6025913960400191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415610c44576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526023815260200180610ee66023913960400191505060405180910390fd5b610c95816000808673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054610dd490919063ffffffff16565b6000808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550610d28816000808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054610e5d90919063ffffffff16565b6000808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef836040518082815260200191505060405180910390a3505050565b600082821115610e4c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601e8152602001807f536166654d6174683a207375627472616374696f6e206f766572666c6f77000081525060200191505060405180910390fd5b600082840390508091505092915050565b600080828401905083811015610edb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601b8152602001807f536166654d6174683a206164646974696f6e206f766572666c6f77000000000081525060200191505060405180910390fd5b809150509291505056fe45524332303a207472616e7366657220746f20746865207a65726f206164647265737345524332303a20617070726f766520746f20746865207a65726f206164647265737345524332303a207472616e736665722066726f6d20746865207a65726f206164647265737345524332303a20617070726f76652066726f6d20746865207a65726f2061646472657373a265627a7a723158201a68b621826f87edc888b7fee157c6fb5686e303e10dcb96b5e4698620f1204364736f6c634300050b0032", + "sourceMap": "146:238:1:-;;;195:187;8:9:-1;5:2;;;30:1;27;20:12;5:2;195:187:1;;;;;;;;;;;;;;;13:3:-1;8;5:12;2:2;;;30:1;27;20:12;2:2;195:187:1;;;;;;;;;;;;;19:11:-1;14:3;11:20;8:2;;;44:1;41;34:12;8:2;71:11;66:3;62:21;55:28;;123:4;118:3;114:14;159:9;141:16;138:31;135:2;;;182:1;179;172:12;135:2;219:3;213:10;330:9;325:1;311:12;307:20;289:16;285:43;282:58;261:11;247:12;244:29;233:115;230:2;;;361:1;358;351:12;230:2;384:12;379:3;372:25;420:4;415:3;411:14;404:21;;0:432;;195:187:1;;;;;;;;;;23:1:-1;8:100;33:3;30:1;27:10;8:100;;;99:1;94:3;90:11;84:18;80:1;75:3;71:11;64:39;52:2;49:1;45:10;40:15;;8:100;;;12:14;195:187:1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;19:11:-1;14:3;11:20;8:2;;;44:1;41;34:12;8:2;71:11;66:3;62:21;55:28;;123:4;118:3;114:14;159:9;141:16;138:31;135:2;;;182:1;179;172:12;135:2;219:3;213:10;330:9;325:1;311:12;307:20;289:16;285:43;282:58;261:11;247:12;244:29;233:115;230:2;;;361:1;358;351:12;230:2;384:12;379:3;372:25;420:4;415:3;411:14;404:21;;0:432;;195:187:1;;;;;;;;;;23:1:-1;8:100;33:3;30:1;27:10;8:100;;;99:1;94:3;90:11;84:18;80:1;75:3;71:11;64:39;52:2;49:1;45:10;40:15;;8:100;;;12:14;195:187:1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;302:4;308:6;316:8;512:4:4;504:5;:12;;;;;;;;;;;;:::i;:::-;;536:6;526:7;:16;;;;;;;;;;;;:::i;:::-;;564:8;552:9;;:20;;;;;;;;;;;;;;;;;;416:163;;;343:32:1;349:10;361:13;343:5;;;:32;;:::i;:::-;195:187;;;;146:238;;5771:302:3;5865:1;5846:21;;:7;:21;;;;5838:65;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;5929:24;5946:6;5929:12;;:16;;;;;;:24;;;;:::i;:::-;5914:12;:39;;;;5984:30;6007:6;5984:9;:18;5994:7;5984:18;;;;;;;;;;;;;;;;:22;;;;;;:30;;;;:::i;:::-;5963:9;:18;5973:7;5963:18;;;;;;;;;;;;;;;:51;;;;6050:7;6029:37;;6046:1;6029:37;;;6059:6;6029:37;;;;;;;;;;;;;;;;;;5771:302;;:::o;834:176:2:-;892:7;911:9;927:1;923;:5;911:17;;951:1;946;:6;;938:46;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;1002:1;995:8;;;834:176;;;;:::o;146:238:1:-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;", + "deployedSourceMap": "146:238:1:-;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;146:238:1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;644:81:4;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;23:1:-1;8:100;33:3;30:1;27:10;8:100;;;99:1;94:3;90:11;84:18;80:1;75:3;71:11;64:39;52:2;49:1;45:10;40:15;;8:100;;;12:14;644:81:4;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;2453:145:3;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;2453:145:3;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;1514:89;;;:::i;:::-;;;;;;;;;;;;;;;;;;;3055:252;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;3055:252:3;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;1478:81:4;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;3702:203:3;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;3702:203:3;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;1661:108;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;1661:108:3;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;838:85:4;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;23:1:-1;8:100;33:3;30:1;27:10;8:100;;;99:1;94:3;90:11;84:18;80:1;75:3;71:11;64:39;52:2;49:1;45:10;40:15;;8:100;;;12:14;838:85:4;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;4392:213:3;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;4392:213:3;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;1972:153;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;1972:153:3;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;2183:132;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;2183:132:3;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;644:81:4;681:13;713:5;706:12;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;644:81;:::o;2453:145:3:-;2518:4;2534:36;2543:10;2555:7;2564:5;2534:8;:36::i;:::-;2587:4;2580:11;;2453:145;;;;:::o;1514:89::-;1558:7;1584:12;;1577:19;;1514:89;:::o;3055:252::-;3144:4;3160:36;3170:6;3178:9;3189:6;3160:9;:36::i;:::-;3206:73;3215:6;3223:10;3235:43;3271:6;3235:11;:19;3247:6;3235:19;;;;;;;;;;;;;;;:31;3255:10;3235:31;;;;;;;;;;;;;;;;:35;;:43;;;;:::i;:::-;3206:8;:73::i;:::-;3296:4;3289:11;;3055:252;;;;;:::o;1478:81:4:-;1519:5;1543:9;;;;;;;;;;;1536:16;;1478:81;:::o;3702:203:3:-;3782:4;3798:79;3807:10;3819:7;3828:48;3865:10;3828:11;:23;3840:10;3828:23;;;;;;;;;;;;;;;:32;3852:7;3828:32;;;;;;;;;;;;;;;;:36;;:48;;;;:::i;:::-;3798:8;:79::i;:::-;3894:4;3887:11;;3702:203;;;;:::o;1661:108::-;1718:7;1744:9;:18;1754:7;1744:18;;;;;;;;;;;;;;;;1737:25;;1661:108;;;:::o;838:85:4:-;877:13;909:7;902:14;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;838:85;:::o;4392:213:3:-;4477:4;4493:84;4502:10;4514:7;4523:53;4560:15;4523:11;:23;4535:10;4523:23;;;;;;;;;;;;;;;:32;4547:7;4523:32;;;;;;;;;;;;;;;;:36;;:53;;;;:::i;:::-;4493:8;:84::i;:::-;4594:4;4587:11;;4392:213;;;;:::o;1972:153::-;2041:4;2057:40;2067:10;2079:9;2090:6;2057:9;:40::i;:::-;2114:4;2107:11;;1972:153;;;;:::o;2183:132::-;2255:7;2281:11;:18;2293:5;2281:18;;;;;;;;;;;;;;;:27;2300:7;2281:27;;;;;;;;;;;;;;;;2274:34;;2183:132;;;;:::o;7117:329::-;7226:1;7209:19;;:5;:19;;;;7201:68;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;7306:1;7287:21;;:7;:21;;;;7279:68;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;7388:5;7358:11;:18;7370:5;7358:18;;;;;;;;;;;;;;;:27;7377:7;7358:27;;;;;;;;;;;;;;;:35;;;;7424:7;7408:31;;7417:5;7408:31;;;7433:5;7408:31;;;;;;;;;;;;;;;;;;7117:329;;;:::o;5079:422::-;5194:1;5176:20;;:6;:20;;;;5168:70;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;5277:1;5256:23;;:9;:23;;;;5248:71;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;5350:29;5372:6;5350:9;:17;5360:6;5350:17;;;;;;;;;;;;;;;;:21;;:29;;;;:::i;:::-;5330:9;:17;5340:6;5330:17;;;;;;;;;;;;;;;:49;;;;5412:32;5437:6;5412:9;:20;5422:9;5412:20;;;;;;;;;;;;;;;;:24;;:32;;;;:::i;:::-;5389:9;:20;5399:9;5389:20;;;;;;;;;;;;;;;:55;;;;5476:9;5459:35;;5468:6;5459:35;;;5487:6;5459:35;;;;;;;;;;;;;;;;;;5079:422;;;:::o;1274:179:2:-;1332:7;1364:1;1359;:6;;1351:49;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;1410:9;1426:1;1422;:5;1410:17;;1445:1;1438:8;;;1274:179;;;;:::o;834:176::-;892:7;911:9;927:1;923;:5;911:17;;951:1;946;:6;;938:46;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;1002:1;995:8;;;834:176;;;;:::o", + "source": "pragma solidity ^0.5.0;\n\nimport \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/ERC20Detailed.sol\";\n\ncontract TestToken is ERC20, ERC20Detailed {\n constructor(string memory name, string memory symbol, uint8 decimals, uint256 initialSupply) ERC20Detailed(name, symbol, decimals) public {\n _mint(msg.sender, initialSupply);\n }\n}", + "sourcePath": "/Users/thomas/Code/client/balancer/external-contracts/contracts/TestToken.sol", + "ast": { + "absolutePath": "/Users/thomas/Code/client/balancer/external-contracts/contracts/TestToken.sol", + "exportedSymbols": { + "TestToken": [ + 88 + ] + }, + "id": 89, + "nodeType": "SourceUnit", + "nodes": [ + { + "id": 58, + "literals": [ + "solidity", + "^", + "0.5", + ".0" + ], + "nodeType": "PragmaDirective", + "src": "0:23:1" + }, + { + "absolutePath": "@openzeppelin/contracts/token/ERC20/ERC20.sol", + "file": "@openzeppelin/contracts/token/ERC20/ERC20.sol", + "id": 59, + "nodeType": "ImportDirective", + "scope": 89, + "sourceUnit": 619, + "src": "25:55:1", + "symbolAliases": [], + "unitAlias": "" + }, + { + "absolutePath": "@openzeppelin/contracts/token/ERC20/ERC20Detailed.sol", + "file": "@openzeppelin/contracts/token/ERC20/ERC20Detailed.sol", + "id": 60, + "nodeType": "ImportDirective", + "scope": 89, + "sourceUnit": 677, + "src": "81:63:1", + "symbolAliases": [], + "unitAlias": "" + }, + { + "baseContracts": [ + { + "arguments": null, + "baseName": { + "contractScope": null, + "id": 61, + "name": "ERC20", + "nodeType": "UserDefinedTypeName", + "referencedDeclaration": 618, + "src": "168:5:1", + "typeDescriptions": { + "typeIdentifier": "t_contract$_ERC20_$618", + "typeString": "contract ERC20" + } + }, + "id": 62, + "nodeType": "InheritanceSpecifier", + "src": "168:5:1" + }, + { + "arguments": null, + "baseName": { + "contractScope": null, + "id": 63, + "name": "ERC20Detailed", + "nodeType": "UserDefinedTypeName", + "referencedDeclaration": 676, + "src": "175:13:1", + "typeDescriptions": { + "typeIdentifier": "t_contract$_ERC20Detailed_$676", + "typeString": "contract ERC20Detailed" + } + }, + "id": 64, + "nodeType": "InheritanceSpecifier", + "src": "175:13:1" + } + ], + "contractDependencies": [ + 618, + 676, + 745 + ], + "contractKind": "contract", + "documentation": null, + "fullyImplemented": true, + "id": 88, + "linearizedBaseContracts": [ + 88, + 676, + 618, + 745 + ], + "name": "TestToken", + "nodeType": "ContractDefinition", + "nodes": [ + { + "body": { + "id": 86, + "nodeType": "Block", + "src": "333:49:1", + "statements": [ + { + "expression": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "expression": { + "argumentTypes": null, + "id": 81, + "name": "msg", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 760, + "src": "349:3:1", + "typeDescriptions": { + "typeIdentifier": "t_magic_message", + "typeString": "msg" + } + }, + "id": 82, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "memberName": "sender", + "nodeType": "MemberAccess", + "referencedDeclaration": null, + "src": "349:10:1", + "typeDescriptions": { + "typeIdentifier": "t_address_payable", + "typeString": "address payable" + } + }, + { + "argumentTypes": null, + "id": 83, + "name": "initialSupply", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 72, + "src": "361:13:1", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_address_payable", + "typeString": "address payable" + }, + { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + ], + "id": 80, + "name": "_mint", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 504, + "src": "343:5:1", + "typeDescriptions": { + "typeIdentifier": "t_function_internal_nonpayable$_t_address_$_t_uint256_$returns$__$", + "typeString": "function (address,uint256)" + } + }, + "id": 84, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "343:32:1", + "typeDescriptions": { + "typeIdentifier": "t_tuple$__$", + "typeString": "tuple()" + } + }, + "id": 85, + "nodeType": "ExpressionStatement", + "src": "343:32:1" + } + ] + }, + "documentation": null, + "id": 87, + "implemented": true, + "kind": "constructor", + "modifiers": [ + { + "arguments": [ + { + "argumentTypes": null, + "id": 75, + "name": "name", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 66, + "src": "302:4:1", + "typeDescriptions": { + "typeIdentifier": "t_string_memory_ptr", + "typeString": "string memory" + } + }, + { + "argumentTypes": null, + "id": 76, + "name": "symbol", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 68, + "src": "308:6:1", + "typeDescriptions": { + "typeIdentifier": "t_string_memory_ptr", + "typeString": "string memory" + } + }, + { + "argumentTypes": null, + "id": 77, + "name": "decimals", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 70, + "src": "316:8:1", + "typeDescriptions": { + "typeIdentifier": "t_uint8", + "typeString": "uint8" + } + } + ], + "id": 78, + "modifierName": { + "argumentTypes": null, + "id": 74, + "name": "ERC20Detailed", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 676, + "src": "288:13:1", + "typeDescriptions": { + "typeIdentifier": "t_type$_t_contract$_ERC20Detailed_$676_$", + "typeString": "type(contract ERC20Detailed)" + } + }, + "nodeType": "ModifierInvocation", + "src": "288:37:1" + } + ], + "name": "", + "nodeType": "FunctionDefinition", + "parameters": { + "id": 73, + "nodeType": "ParameterList", + "parameters": [ + { + "constant": false, + "id": 66, + "name": "name", + "nodeType": "VariableDeclaration", + "scope": 87, + "src": "207:18:1", + "stateVariable": false, + "storageLocation": "memory", + "typeDescriptions": { + "typeIdentifier": "t_string_memory_ptr", + "typeString": "string" + }, + "typeName": { + "id": 65, + "name": "string", + "nodeType": "ElementaryTypeName", + "src": "207:6:1", + "typeDescriptions": { + "typeIdentifier": "t_string_storage_ptr", + "typeString": "string" + } + }, + "value": null, + "visibility": "internal" + }, + { + "constant": false, + "id": 68, + "name": "symbol", + "nodeType": "VariableDeclaration", + "scope": 87, + "src": "227:20:1", + "stateVariable": false, + "storageLocation": "memory", + "typeDescriptions": { + "typeIdentifier": "t_string_memory_ptr", + "typeString": "string" + }, + "typeName": { + "id": 67, + "name": "string", + "nodeType": "ElementaryTypeName", + "src": "227:6:1", + "typeDescriptions": { + "typeIdentifier": "t_string_storage_ptr", + "typeString": "string" + } + }, + "value": null, + "visibility": "internal" + }, + { + "constant": false, + "id": 70, + "name": "decimals", + "nodeType": "VariableDeclaration", + "scope": 87, + "src": "249:14:1", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_uint8", + "typeString": "uint8" + }, + "typeName": { + "id": 69, + "name": "uint8", + "nodeType": "ElementaryTypeName", + "src": "249:5:1", + "typeDescriptions": { + "typeIdentifier": "t_uint8", + "typeString": "uint8" + } + }, + "value": null, + "visibility": "internal" + }, + { + "constant": false, + "id": 72, + "name": "initialSupply", + "nodeType": "VariableDeclaration", + "scope": 87, + "src": "265:21:1", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "typeName": { + "id": 71, + "name": "uint256", + "nodeType": "ElementaryTypeName", + "src": "265:7:1", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "value": null, + "visibility": "internal" + } + ], + "src": "206:81:1" + }, + "returnParameters": { + "id": 79, + "nodeType": "ParameterList", + "parameters": [], + "src": "333:0:1" + }, + "scope": 88, + "src": "195:187:1", + "stateMutability": "nonpayable", + "superFunction": null, + "visibility": "public" + } + ], + "scope": 89, + "src": "146:238:1" + } + ], + "src": "0:384:1" + }, + "legacyAST": { + "absolutePath": "/Users/thomas/Code/client/balancer/external-contracts/contracts/TestToken.sol", + "exportedSymbols": { + "TestToken": [ + 88 + ] + }, + "id": 89, + "nodeType": "SourceUnit", + "nodes": [ + { + "id": 58, + "literals": [ + "solidity", + "^", + "0.5", + ".0" + ], + "nodeType": "PragmaDirective", + "src": "0:23:1" + }, + { + "absolutePath": "@openzeppelin/contracts/token/ERC20/ERC20.sol", + "file": "@openzeppelin/contracts/token/ERC20/ERC20.sol", + "id": 59, + "nodeType": "ImportDirective", + "scope": 89, + "sourceUnit": 619, + "src": "25:55:1", + "symbolAliases": [], + "unitAlias": "" + }, + { + "absolutePath": "@openzeppelin/contracts/token/ERC20/ERC20Detailed.sol", + "file": "@openzeppelin/contracts/token/ERC20/ERC20Detailed.sol", + "id": 60, + "nodeType": "ImportDirective", + "scope": 89, + "sourceUnit": 677, + "src": "81:63:1", + "symbolAliases": [], + "unitAlias": "" + }, + { + "baseContracts": [ + { + "arguments": null, + "baseName": { + "contractScope": null, + "id": 61, + "name": "ERC20", + "nodeType": "UserDefinedTypeName", + "referencedDeclaration": 618, + "src": "168:5:1", + "typeDescriptions": { + "typeIdentifier": "t_contract$_ERC20_$618", + "typeString": "contract ERC20" + } + }, + "id": 62, + "nodeType": "InheritanceSpecifier", + "src": "168:5:1" + }, + { + "arguments": null, + "baseName": { + "contractScope": null, + "id": 63, + "name": "ERC20Detailed", + "nodeType": "UserDefinedTypeName", + "referencedDeclaration": 676, + "src": "175:13:1", + "typeDescriptions": { + "typeIdentifier": "t_contract$_ERC20Detailed_$676", + "typeString": "contract ERC20Detailed" + } + }, + "id": 64, + "nodeType": "InheritanceSpecifier", + "src": "175:13:1" + } + ], + "contractDependencies": [ + 618, + 676, + 745 + ], + "contractKind": "contract", + "documentation": null, + "fullyImplemented": true, + "id": 88, + "linearizedBaseContracts": [ + 88, + 676, + 618, + 745 + ], + "name": "TestToken", + "nodeType": "ContractDefinition", + "nodes": [ + { + "body": { + "id": 86, + "nodeType": "Block", + "src": "333:49:1", + "statements": [ + { + "expression": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "expression": { + "argumentTypes": null, + "id": 81, + "name": "msg", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 760, + "src": "349:3:1", + "typeDescriptions": { + "typeIdentifier": "t_magic_message", + "typeString": "msg" + } + }, + "id": 82, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "memberName": "sender", + "nodeType": "MemberAccess", + "referencedDeclaration": null, + "src": "349:10:1", + "typeDescriptions": { + "typeIdentifier": "t_address_payable", + "typeString": "address payable" + } + }, + { + "argumentTypes": null, + "id": 83, + "name": "initialSupply", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 72, + "src": "361:13:1", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_address_payable", + "typeString": "address payable" + }, + { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + ], + "id": 80, + "name": "_mint", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 504, + "src": "343:5:1", + "typeDescriptions": { + "typeIdentifier": "t_function_internal_nonpayable$_t_address_$_t_uint256_$returns$__$", + "typeString": "function (address,uint256)" + } + }, + "id": 84, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "343:32:1", + "typeDescriptions": { + "typeIdentifier": "t_tuple$__$", + "typeString": "tuple()" + } + }, + "id": 85, + "nodeType": "ExpressionStatement", + "src": "343:32:1" + } + ] + }, + "documentation": null, + "id": 87, + "implemented": true, + "kind": "constructor", + "modifiers": [ + { + "arguments": [ + { + "argumentTypes": null, + "id": 75, + "name": "name", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 66, + "src": "302:4:1", + "typeDescriptions": { + "typeIdentifier": "t_string_memory_ptr", + "typeString": "string memory" + } + }, + { + "argumentTypes": null, + "id": 76, + "name": "symbol", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 68, + "src": "308:6:1", + "typeDescriptions": { + "typeIdentifier": "t_string_memory_ptr", + "typeString": "string memory" + } + }, + { + "argumentTypes": null, + "id": 77, + "name": "decimals", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 70, + "src": "316:8:1", + "typeDescriptions": { + "typeIdentifier": "t_uint8", + "typeString": "uint8" + } + } + ], + "id": 78, + "modifierName": { + "argumentTypes": null, + "id": 74, + "name": "ERC20Detailed", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 676, + "src": "288:13:1", + "typeDescriptions": { + "typeIdentifier": "t_type$_t_contract$_ERC20Detailed_$676_$", + "typeString": "type(contract ERC20Detailed)" + } + }, + "nodeType": "ModifierInvocation", + "src": "288:37:1" + } + ], + "name": "", + "nodeType": "FunctionDefinition", + "parameters": { + "id": 73, + "nodeType": "ParameterList", + "parameters": [ + { + "constant": false, + "id": 66, + "name": "name", + "nodeType": "VariableDeclaration", + "scope": 87, + "src": "207:18:1", + "stateVariable": false, + "storageLocation": "memory", + "typeDescriptions": { + "typeIdentifier": "t_string_memory_ptr", + "typeString": "string" + }, + "typeName": { + "id": 65, + "name": "string", + "nodeType": "ElementaryTypeName", + "src": "207:6:1", + "typeDescriptions": { + "typeIdentifier": "t_string_storage_ptr", + "typeString": "string" + } + }, + "value": null, + "visibility": "internal" + }, + { + "constant": false, + "id": 68, + "name": "symbol", + "nodeType": "VariableDeclaration", + "scope": 87, + "src": "227:20:1", + "stateVariable": false, + "storageLocation": "memory", + "typeDescriptions": { + "typeIdentifier": "t_string_memory_ptr", + "typeString": "string" + }, + "typeName": { + "id": 67, + "name": "string", + "nodeType": "ElementaryTypeName", + "src": "227:6:1", + "typeDescriptions": { + "typeIdentifier": "t_string_storage_ptr", + "typeString": "string" + } + }, + "value": null, + "visibility": "internal" + }, + { + "constant": false, + "id": 70, + "name": "decimals", + "nodeType": "VariableDeclaration", + "scope": 87, + "src": "249:14:1", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_uint8", + "typeString": "uint8" + }, + "typeName": { + "id": 69, + "name": "uint8", + "nodeType": "ElementaryTypeName", + "src": "249:5:1", + "typeDescriptions": { + "typeIdentifier": "t_uint8", + "typeString": "uint8" + } + }, + "value": null, + "visibility": "internal" + }, + { + "constant": false, + "id": 72, + "name": "initialSupply", + "nodeType": "VariableDeclaration", + "scope": 87, + "src": "265:21:1", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "typeName": { + "id": 71, + "name": "uint256", + "nodeType": "ElementaryTypeName", + "src": "265:7:1", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "value": null, + "visibility": "internal" + } + ], + "src": "206:81:1" + }, + "returnParameters": { + "id": 79, + "nodeType": "ParameterList", + "parameters": [], + "src": "333:0:1" + }, + "scope": 88, + "src": "195:187:1", + "stateMutability": "nonpayable", + "superFunction": null, + "visibility": "public" + } + ], + "scope": 89, + "src": "146:238:1" + } + ], + "src": "0:384:1" + }, + "compiler": { + "name": "solc", + "version": "0.5.11+commit.c082d0b4.Emscripten.clang" + }, + "networks": {}, + "schemaVersion": "3.0.11", + "updatedAt": "2019-09-21T08:47:25.358Z", + "devdoc": { + "methods": { + "allowance(address,address)": { + "details": "See `IERC20.allowance`." + }, + "approve(address,uint256)": { + "details": "See `IERC20.approve`. * Requirements: * - `spender` cannot be the zero address." + }, + "balanceOf(address)": { + "details": "See `IERC20.balanceOf`." + }, + "decimals()": { + "details": "Returns the number of decimals used to get its user representation. For example, if `decimals` equals `2`, a balance of `505` tokens should be displayed to a user as `5,05` (`505 / 10 ** 2`). * Tokens usually opt for a value of 18, imitating the relationship between Ether and Wei. * > Note that this information is only used for _display_ purposes: it in no way affects any of the arithmetic of the contract, including `IERC20.balanceOf` and `IERC20.transfer`." + }, + "decreaseAllowance(address,uint256)": { + "details": "Atomically decreases the allowance granted to `spender` by the caller. * This is an alternative to `approve` that can be used as a mitigation for problems described in `IERC20.approve`. * Emits an `Approval` event indicating the updated allowance. * Requirements: * - `spender` cannot be the zero address. - `spender` must have allowance for the caller of at least `subtractedValue`." + }, + "increaseAllowance(address,uint256)": { + "details": "Atomically increases the allowance granted to `spender` by the caller. * This is an alternative to `approve` that can be used as a mitigation for problems described in `IERC20.approve`. * Emits an `Approval` event indicating the updated allowance. * Requirements: * - `spender` cannot be the zero address." + }, + "name()": { + "details": "Returns the name of the token." + }, + "symbol()": { + "details": "Returns the symbol of the token, usually a shorter version of the name." + }, + "totalSupply()": { + "details": "See `IERC20.totalSupply`." + }, + "transfer(address,uint256)": { + "details": "See `IERC20.transfer`. * Requirements: * - `recipient` cannot be the zero address. - the caller must have a balance of at least `amount`." + }, + "transferFrom(address,address,uint256)": { + "details": "See `IERC20.transferFrom`. * Emits an `Approval` event indicating the updated allowance. This is not required by the EIP. See the note at the beginning of `ERC20`; * Requirements: - `sender` and `recipient` cannot be the zero address. - `sender` must have a balance of at least `value`. - the caller must have allowance for `sender`'s tokens of at least `amount`." + } + } + }, + "userdoc": { + "methods": {} + } +} diff --git a/src/helpers/abi/index.ts b/src/helpers/abi/index.ts new file mode 100644 index 0000000..28abc70 --- /dev/null +++ b/src/helpers/abi/index.ts @@ -0,0 +1,10 @@ +const requireFile = require.context('./', true, /[\w-]+\.json$/); + +export default Object.fromEntries( + requireFile + .keys() + .map(fileName => [ + fileName.replace('./', '').replace('.json', ''), + requireFile(fileName).abi + ]) +); diff --git a/src/helpers/client.ts b/src/helpers/client.ts new file mode 100644 index 0000000..6d07b2d --- /dev/null +++ b/src/helpers/client.ts @@ -0,0 +1,28 @@ +class Client { + request(command, body?) { + const url = `${process.env.VUE_APP_HUB_URL}/api/${command}`; + let init; + if (body) { + init = { + method: 'POST', + headers: { + Accept: 'application/json', + 'Content-Type': 'application/json' + }, + body: JSON.stringify(body) + }; + } + return new Promise((resolve, reject) => { + fetch(url, init) + .then(res => { + if (res.ok) return resolve(res.json()); + throw res; + }) + .catch(e => e.json().then(json => reject(json))); + }); + } +} + +const client = new Client(); + +export default client; diff --git a/src/helpers/config.ts b/src/helpers/config.ts new file mode 100644 index 0000000..ff5edf2 --- /dev/null +++ b/src/helpers/config.ts @@ -0,0 +1,8 @@ +import config from '@/config.json'; + +let id = 'master'; +const domainName = window.location.hostname; +if (domainName.includes('localhost:')) id = 'local'; +if (domainName === 'makiswap-dev.thinkincoin.com') id = 'develop'; + +export default config[id]; diff --git a/src/helpers/ipfs.ts b/src/helpers/ipfs.ts new file mode 100644 index 0000000..78bb98e --- /dev/null +++ b/src/helpers/ipfs.ts @@ -0,0 +1,10 @@ +class Client { + get(ipfsHash) { + const url = `https://${process.env.VUE_APP_IPFS_NODE}/ipfs/${ipfsHash}`; + return fetch(url).then(res => res.json()); + } +} + +const client = new Client(); + +export default client; diff --git a/src/helpers/lock.ts b/src/helpers/lock.ts new file mode 100644 index 0000000..c699928 --- /dev/null +++ b/src/helpers/lock.ts @@ -0,0 +1,17 @@ +import { Lock } from '@bonustrack/lock/dist/lock.cjs'; +import config from '@/helpers/config'; +import injected from '@bonustrack/lock/connectors/injected'; +import portis from '@bonustrack/lock/connectors/portis'; +import magic from '@bonustrack/lock/connectors/fortmatic'; + +const connectors = { injected, portis, magic }; +const lock = new Lock(); +Object.entries(config.connectors).forEach((connector: any) => { + lock.addConnector({ + key: connector[0], + connector: connectors[connector[0]], + options: connector[1].options + }); +}); + +export default lock; diff --git a/src/helpers/queries.json b/src/helpers/queries.json new file mode 100644 index 0000000..6a01d51 --- /dev/null +++ b/src/helpers/queries.json @@ -0,0 +1,25 @@ +{ + "getVotingPowers": { + "poolShares": { + "__args": { + "first": 1000, + "orderBy": "balance", + "orderDirection": "desc", + "where": { + "balance_gt": 0 + } + }, + "userAddress": { + "id": true + }, + "balance": true, + "poolId": { + "totalShares": true, + "tokens": { + "id": true, + "balance": true + } + } + } + } +} diff --git a/src/helpers/subgraph.ts b/src/helpers/subgraph.ts new file mode 100644 index 0000000..26d340b --- /dev/null +++ b/src/helpers/subgraph.ts @@ -0,0 +1,24 @@ +import merge from 'lodash/merge'; +import { clone } from '@/helpers/utils'; +import { jsonToGraphQLQuery } from 'json-to-graphql-query'; +import config from '@/helpers/config'; +import queries from '@/helpers/queries.json'; + +// @ts-ignore +queries.custom = {}; + +export async function request(key: string | null, params: any = {}) { + // @ts-ignore + let query = merge(clone(queries[key]), clone(params)); + query = jsonToGraphQLQuery({ query }); + const res = await fetch(config.subgraphUrl, { + method: 'POST', + headers: { + Accept: 'application/json', + 'Content-Type': 'application/json' + }, + body: JSON.stringify({ query }) + }); + const { data } = await res.json(); + return data || {}; +} diff --git a/src/helpers/utils.ts b/src/helpers/utils.ts new file mode 100644 index 0000000..f67dedd --- /dev/null +++ b/src/helpers/utils.ts @@ -0,0 +1,62 @@ +import config from '@/helpers/config'; +import pkg from '@/../package.json'; + +export function shorten(str = '') { + return `${str.slice(0, 6)}...${str.slice(str.length - 4)}`; +} + +export function jsonParse(input, fallback?) { + if (typeof input !== 'string') { + return fallback || {}; + } + try { + return JSON.parse(input); + } catch (err) { + return fallback || {}; + } +} + +export function clone(item) { + return JSON.parse(JSON.stringify(item)); +} + +export function etherscanLink(str: string, type = 'address'): string { + const network = config.network === 'homestead' ? '' : `${config.network}.`; + return `https://${network}etherscan.io/${type}/${str}`; +} + +export function lsSet(key: string, value: any) { + return localStorage.setItem(`${pkg.name}.${key}`, JSON.stringify(value)); +} + +export function lsGet(key: string) { + const item = localStorage.getItem(`${pkg.name}.${key}`); + return jsonParse(item, ''); +} + +export function lsRemove(key: string) { + return localStorage.removeItem(`${pkg.name}.${key}`); +} + +export function formatProposal(proposal) { + proposal.msg = jsonParse(proposal.msg, proposal.msg); + + // v0.1.0 + if (proposal.msg.version === '0.1.0') { + proposal.msg.payload.start = 1595088000; + proposal.msg.payload.end = 1595174400; + proposal.msg.payload.snapshot = 10484400; + proposal.bpt_voting_disabled = '1'; + } + + return proposal; +} + +export function formatProposals(proposals) { + return Object.fromEntries( + Object.entries(proposals).map(proposal => [ + proposal[0], + formatProposal(proposal[1]) + ]) + ); +} diff --git a/src/helpers/ws.ts b/src/helpers/ws.ts new file mode 100644 index 0000000..044a705 --- /dev/null +++ b/src/helpers/ws.ts @@ -0,0 +1,6 @@ +import { WebSocketProvider } from '@ethersproject/providers'; + +const wsUrl: any = process.env.VUE_APP_WS_URL; +const wsProvider = new WebSocketProvider(wsUrl); + +export default wsProvider; diff --git a/src/i18n.ts b/src/i18n.ts new file mode 100644 index 0000000..9e9b2b1 --- /dev/null +++ b/src/i18n.ts @@ -0,0 +1,55 @@ +import Vue from 'vue'; +import VueI18n from 'vue-i18n'; + +Vue.use(VueI18n); + +const locale = 'en-US'; + +export default new VueI18n({ + locale, + messages: { + en: { + messages: { + EMPTY_STATE: 'No results found' + } + } + }, + numberFormats: { + en: { + currency: { + style: 'currency', + currency: 'USD', + minimumFractionDigits: 0, + maximumFractionDigits: 0 + }, + price: { + style: 'currency', + currency: 'USD', + minimumFractionDigits: 2, + maximumFractionDigits: 6 + }, + percent: { + style: 'percent', + minimumFractionDigits: 0, + maximumFractionDigits: 2 + } + } + }, + dateTimeFormats: { + 'en-US': { + short: { + year: 'numeric', + month: 'short', + day: 'numeric', + hour: 'numeric' + }, + long: { + year: 'numeric', + month: 'long', + day: 'numeric', + hour: 'numeric', + minute: 'numeric' + } + } + } +}); diff --git a/src/main.ts b/src/main.ts new file mode 100644 index 0000000..816ec8e --- /dev/null +++ b/src/main.ts @@ -0,0 +1,38 @@ +import Vue from 'vue'; +import autofocus from 'vue-autofocus-directive'; +import infiniteScroll from 'vue-infinite-scroll'; +import TextareaAutosize from 'vue-textarea-autosize'; +import Jazzicon from 'vue-jazzicon'; +import upperFirst from 'lodash/upperFirst'; +import camelCase from 'lodash/camelCase'; +import App from '@/App.vue'; +import router from '@/router'; +import store from '@/store'; +import mixins from '@/mixins'; +import i18n from '@/i18n'; +import '@/style.scss'; + +Vue.use(infiniteScroll); +Vue.use(TextareaAutosize); + +const requireComponent = require.context('@/components', true, /[\w-]+\.vue$/); +requireComponent.keys().forEach(fileName => { + const componentConfig = requireComponent(fileName); + const componentName = upperFirst( + camelCase(fileName.replace(/^\.\//, '').replace(/\.\w+$/, '')) + ); + Vue.component(componentName, componentConfig.default || componentConfig); +}); + +Vue.component('jazzicon', Jazzicon); +Vue.mixin(mixins); +Vue.directive('autofocus', autofocus); + +Vue.config.productionTip = false; + +new Vue({ + i18n, + router, + store, + render: h => h(App) +}).$mount('#app'); diff --git a/src/mixins.ts b/src/mixins.ts new file mode 100644 index 0000000..7ab8758 --- /dev/null +++ b/src/mixins.ts @@ -0,0 +1,33 @@ +import { mapState } from 'vuex'; +import numeral from 'numeral'; +import store from '@/store'; +import config from '@/helpers/config'; +import { shorten, etherscanLink } from '@/helpers/utils'; + +// @ts-ignore +const modules = Object.entries(store.state).map(module => module[0]); + +export default { + data() { + return { + config + }; + }, + computed: { + ...mapState(modules) + }, + methods: { + _numeral(number, format = '(0.[00]a)') { + return numeral(number).format(format); + }, + _shorten(str: string): string { + return shorten(str); + }, + _ipfsUrl(ipfsHash: string): string { + return `https://${process.env.VUE_APP_IPFS_NODE}/ipfs/${ipfsHash}`; + }, + _etherscanLink(str: string, type: string): string { + return etherscanLink(str, type); + } + } +}; diff --git a/src/namespaces.json b/src/namespaces.json new file mode 100644 index 0000000..d8e0959 --- /dev/null +++ b/src/namespaces.json @@ -0,0 +1,27 @@ +{ + "SOY": { + "key": "soy", + "symbol": "SOY", + "name": "SoyBar Token", + "address": "0x993163cad35162fb579d7b64e6695cb076ef5064", + "token": "0x993163cad35162fb579d7b64e6695cb076ef5064", + "image": "0x993163cad35162fb579d7b64e6695cb076ef5064", + "coreDevs": [ + "0x07Dee7d1828554a59C8B5E1466Cba8C0B87daF10" + ], + "min": 100, + "max": 1000 + }, + "maki": { + "key": "maki", + "symbol": "MAKI", + "name": "MakiSwap Token", + "address": "0x89d45ccdae300e9a2a725eec8ec76dda571d6e2b", + "token": "0x89d45ccdae300e9a2a725eec8ec76dda571d6e2b", + "image": "0x89d45ccdae300e9a2a725eec8ec76dda571d6e2b", + "coreDevs": [ + ], + "min": 10, + "max": 100 + } +} diff --git a/src/router.ts b/src/router.ts new file mode 100644 index 0000000..eb0b5bd --- /dev/null +++ b/src/router.ts @@ -0,0 +1,23 @@ +import Vue from 'vue'; +import VueRouter, { RouteConfig } from 'vue-router'; +import Home from '@/views/Home.vue'; +import Proposals from '@/views/Proposals.vue'; +import Proposal from '@/views/Proposal.vue'; +import Create from '@/views/Create.vue'; + +Vue.use(VueRouter); + +const routes: Array = [ + { path: '/:key/proposal/:id', name: 'proposal', component: Proposal }, + { path: '/:key/create', name: 'create', component: Create }, + { path: '/:key', name: 'proposals', component: Proposals }, + { path: '/', name: 'home', component: Home }, + { path: '/*', name: 'error-404', beforeEnter: (to, from, next) => next('/') } +]; + +const router = new VueRouter({ + mode: 'hash', + routes +}); + +export default router; diff --git a/src/shims-tsx.d.ts b/src/shims-tsx.d.ts new file mode 100644 index 0000000..3b88b58 --- /dev/null +++ b/src/shims-tsx.d.ts @@ -0,0 +1,13 @@ +import Vue, { VNode } from 'vue'; + +declare global { + namespace JSX { + // tslint:disable no-empty-interface + interface Element extends VNode {} + // tslint:disable no-empty-interface + interface ElementClass extends Vue {} + interface IntrinsicElements { + [elem: string]: any; + } + } +} diff --git a/src/shims-vue.d.ts b/src/shims-vue.d.ts new file mode 100644 index 0000000..8f6f410 --- /dev/null +++ b/src/shims-vue.d.ts @@ -0,0 +1,4 @@ +declare module '*.vue' { + import Vue from 'vue'; + export default Vue; +} diff --git a/src/store/index.ts b/src/store/index.ts new file mode 100644 index 0000000..28d75aa --- /dev/null +++ b/src/store/index.ts @@ -0,0 +1,12 @@ +import Vue from 'vue'; +import Vuex from 'vuex'; +import modules from '@/store/modules'; + +Vue.use(Vuex); + +const store = new Vuex.Store({ + modules, + strict: process.env.NODE_ENV !== 'production' +}); + +export default store; diff --git a/src/store/modules/gov.ts b/src/store/modules/gov.ts new file mode 100644 index 0000000..2ac712a --- /dev/null +++ b/src/store/modules/gov.ts @@ -0,0 +1,252 @@ +import { Contract } from '@ethersproject/contracts'; +import { Interface } from '@ethersproject/abi'; +import { formatUnits } from '@ethersproject/units'; +import client from '@/helpers/client'; +import ipfs from '@/helpers/ipfs'; +import config from '@/helpers/config'; +import abi from '@/helpers/abi'; +import wsProvider from '@/helpers/ws'; +import { formatProposal, formatProposals } from '@/helpers/utils'; +import { version } from '@/../package.json'; + +const mutations = { + SEND_REQUEST() { + console.debug('SEND_REQUEST'); + }, + SEND_SUCCESS() { + console.debug('SEND_SUCCESS'); + }, + SEND_FAILURE(_state, payload) { + console.debug('SEND_FAILURE', payload); + }, + GET_PROPOSALS_REQUEST() { + console.debug('GET_PROPOSALS_REQUEST'); + }, + GET_PROPOSALS_SUCCESS() { + console.debug('GET_PROPOSALS_SUCCESS'); + }, + GET_PROPOSALS_FAILURE(_state, payload) { + console.debug('GET_PROPOSALS_FAILURE', payload); + }, + GET_PROPOSAL_REQUEST() { + console.debug('GET_PROPOSAL_REQUEST'); + }, + GET_PROPOSAL_SUCCESS() { + console.debug('GET_PROPOSAL_SUCCESS'); + }, + GET_PROPOSAL_FAILURE(_state, payload) { + console.debug('GET_PROPOSAL_FAILURE', payload); + }, + GET_VOTERS_BALANCES_REQUEST() { + console.debug('GET_VOTERS_BALANCES_REQUEST'); + }, + GET_VOTERS_BALANCES_SUCCESS() { + console.debug('GET_VOTERS_BALANCES_SUCCESS'); + }, + GET_VOTERS_BALANCES_FAILURE(_state, payload) { + console.debug('GET_VOTERS_BALANCES_FAILURE', payload); + }, + GET_POWER_REQUEST() { + console.debug('GET_POWER_REQUEST'); + }, + GET_POWER_SUCCESS() { + console.debug('GET_POWER_SUCCESS'); + }, + GET_POWER_FAILURE(_state, payload) { + console.debug('GET_POWER_FAILURE', payload); + } +}; + +const actions = { + send: async ({ commit, dispatch, rootState }, { token, type, payload }) => { + commit('SEND_REQUEST'); + try { + const msg: any = { + address: rootState.web3.account, + msg: JSON.stringify({ + version, + timestamp: (Date.now() / 1e3).toFixed(), + token, + type, + payload + }) + }; + msg.sig = await dispatch('signMessage', msg.msg); + const result = await client.request('message', msg); + commit('SEND_SUCCESS'); + dispatch('notify', ['green', `Your ${type} is in!`]); + return result; + } catch (e) { + commit('SEND_FAILURE', e); + const errorMessage = + e && e.error_description + ? `Oops, ${e.error_description}` + : 'Oops, something went wrong!'; + dispatch('notify', ['red', errorMessage]); + return; + } + }, + getProposals: async ({ commit, dispatch, rootState }, payload) => { + const { decimals } = rootState.web3.namespaces[payload]; + commit('GET_PROPOSALS_REQUEST'); + try { + let proposals: any = await client.request(`${payload}/proposals`); + if (proposals) { + let balances = await dispatch('multicall', { + name: 'TestToken', + calls: Object.values(proposals).map((proposal: any) => { + return [proposal.msg.token, 'balanceOf', [proposal.address]]; + }) + }); + balances = balances.map(balance => + parseFloat(formatUnits(balance.toString(), decimals)) + ); + proposals = Object.fromEntries( + Object.entries(proposals).map((proposal: any, i) => { + proposal[1].balance = balances[i]; + return [proposal[0], proposal[1]]; + }) + ); + } + commit('GET_PROPOSALS_SUCCESS'); + return formatProposals(proposals); + } catch (e) { + commit('GET_PROPOSALS_FAILURE', e); + } + }, + getProposal: async ({ commit, dispatch, rootState }, payload) => { + commit('GET_PROPOSAL_REQUEST'); + try { + const result: any = {}; + const [proposal, votes] = await Promise.all([ + ipfs.get(payload.id), + client.request(`${payload.token}/proposal/${payload.id}`) + ]); + result.proposal = formatProposal(proposal); + result.proposal.ipfsHash = payload.id; + result.votes = votes; + const bptDisabled = !!result.proposal.bpt_voting_disabled; + const { snapshot } = result.proposal.msg.payload; + const blockTag = + snapshot > rootState.web3.blockNumber ? 'latest' : parseInt(snapshot); + const votersBalances = await dispatch('getVotersBalances', { + token: payload.token, + addresses: Object.values(result.votes).map((vote: any) => vote.address), + blockTag + }); + // @ts-ignore + const addresses = Object.keys(votes); + let votingPowers = {}; + if (!bptDisabled) { + votingPowers = await dispatch('getVotingPowers', { + token: result.proposal.msg.token, + blockTag, + addresses + }); + } + result.votes = Object.fromEntries( + Object.entries(result.votes) + .map((vote: any) => { + const bptBalance = bptDisabled ? 0 : votingPowers[vote[1].address]; + vote[1].balance = votersBalances[vote[1].address] + bptBalance; + vote[1].bptBalance = bptBalance; + vote[1].walletBalance = votersBalances[vote[1].address]; + return vote; + }) + .sort((a, b) => b[1].balance - a[1].balance) + .filter(vote => vote[1].balance > 0) + ); + result.results = { + totalVotes: result.proposal.msg.payload.choices.map( + (choice, i) => + Object.values(result.votes).filter( + (vote: any) => vote.msg.payload.choice === i + 1 + ).length + ), + totalBalances: result.proposal.msg.payload.choices.map((choice, i) => + Object.values(result.votes) + .filter((vote: any) => vote.msg.payload.choice === i + 1) + .reduce((a, b: any) => a + b.balance, 0) + ), + totalBptBalances: bptDisabled + ? 0 + : result.proposal.msg.payload.choices.map((choice, i) => + Object.values(result.votes) + .filter((vote: any) => vote.msg.payload.choice === i + 1) + .reduce((a, b: any) => a + b.bptBalance, 0) + ), + totalWalletBalances: result.proposal.msg.payload.choices.map( + (choice, i) => + Object.values(result.votes) + .filter((vote: any) => vote.msg.payload.choice === i + 1) + .reduce((a, b: any) => a + b.walletBalance, 0) + ), + totalVotesBalances: Object.values(result.votes).reduce( + (a, b: any) => a + b.balance, + 0 + ) + }; + commit('GET_PROPOSAL_SUCCESS'); + return result; + } catch (e) { + commit('GET_PROPOSAL_FAILURE', e); + } + }, + getVotersBalances: async ( + { commit, rootState }, + { token, addresses, blockTag } + ) => { + commit('GET_VOTERS_BALANCES_REQUEST'); + const multi = new Contract(config.multicall, abi['Multicall'], wsProvider); + const calls = []; + const testToken = new Interface(abi.TestToken); + addresses.forEach(address => { + // @ts-ignore + calls.push([token, testToken.encodeFunctionData('balanceOf', [address])]); + }); + const balances: any = {}; + try { + const { decimals } = rootState.web3.namespaces[token]; + const [, response] = await multi.aggregate(calls, { blockTag }); + response.forEach((value, i) => { + balances[addresses[i]] = parseFloat( + formatUnits(value.toString(), decimals) + ); + }); + commit('GET_VOTERS_BALANCES_SUCCESS'); + return balances; + } catch (e) { + commit('GET_VOTERS_BALANCES_FAILURE', e); + return Promise.reject(); + } + }, + getPower: async ( + { commit, dispatch, rootState }, + { token, address, snapshot } + ) => { + commit('GET_POWER_REQUEST'); + const blockTag = + snapshot > rootState.web3.blockNumber ? 'latest' : parseInt(snapshot); + try { + const bpts = await dispatch('getVotingPowersByPools', { + blockTag, + token, + addresses: [address] + }); + const bpt = Object.values(bpts[address]).reduce( + (a: any, b: any) => a + b, + 0 + ); + const base = await dispatch('getBalance', { blockTag, token }); + commit('GET_POWER_SUCCESS'); + return { base, bpt, total: base + bpt }; + } catch (e) { + commit('GET_POWER_FAILURE', e); + } + } +}; + +export default { + mutations, + actions +}; diff --git a/src/store/modules/index.ts b/src/store/modules/index.ts new file mode 100644 index 0000000..0c2194c --- /dev/null +++ b/src/store/modules/index.ts @@ -0,0 +1,12 @@ +import camelCase from 'lodash/camelCase'; + +const requireModule = require.context('.', false, /\.ts$/); +const modules = {}; + +requireModule.keys().forEach(fileName => { + if (fileName === './index.ts') return; + const moduleName = camelCase(fileName.replace(/(\.\/|\.ts)/g, '')); + modules[moduleName] = requireModule(fileName).default; +}); + +export default modules; diff --git a/src/store/modules/notifications.ts b/src/store/modules/notifications.ts new file mode 100644 index 0000000..39efa71 --- /dev/null +++ b/src/store/modules/notifications.ts @@ -0,0 +1,23 @@ +const state = { + items: [] +}; + +const mutations = { + notify(_state, payload) { + _state.items.push({ ...payload, timestamp: Date.now() }); + } +}; + +const actions = { + notify({ commit }, payload) { + Array.isArray(payload) + ? commit('notify', { message: payload[1], type: payload[0] }) + : commit('notify', { message: payload, type: 'green' }); + } +}; + +export default { + state, + mutations, + actions +}; diff --git a/src/store/modules/subgraph.ts b/src/store/modules/subgraph.ts new file mode 100644 index 0000000..bccb5a6 --- /dev/null +++ b/src/store/modules/subgraph.ts @@ -0,0 +1,108 @@ +import { getAddress } from '@ethersproject/address'; +import { request } from '@/helpers/subgraph'; + +const mutations = { + GET_VOTING_POWER_REQUEST() { + console.debug('GET_VOTING_POWER_REQUEST'); + }, + GET_VOTING_POWER_SUCCESS() { + console.debug('GET_VOTING_POWER_SUCCESS'); + }, + GET_VOTING_POWER_FAILURE(_state, payload) { + console.debug('GET_VOTING_POWER_FAILURE', payload); + }, + GET_VOTING_POWERS_REQUEST() { + console.debug('GET_VOTING_POWERS_REQUEST'); + }, + GET_VOTING_POWERS_SUCCESS() { + console.debug('GET_VOTING_POWERS_SUCCESS'); + }, + GET_VOTING_POWERS_FAILURE(_state, payload) { + console.debug('GET_VOTING_POWERS_FAILURE', payload); + } +}; + +const actions = { + getVotingPowers: async ({ commit }, { blockTag, token, addresses }) => { + commit('GET_VOTING_POWERS_REQUEST'); + try { + const block = blockTag === 'latest' ? undefined : { number: blockTag }; + const result = await request('getVotingPowers', { + poolShares: { + __args: { + block, + where: { + userAddress_in: addresses.map(address => address.toLowerCase()) + } + } + } + }); + const votingPowers: any = Object.fromEntries( + addresses.map(address => [address, 0]) + ); + if (result && result.poolShares) { + result.poolShares.forEach(poolShare => + poolShare.poolId.tokens.map(poolToken => { + const [, tokenAddress] = poolToken.id.split('-'); + if (tokenAddress === token.toLowerCase()) { + const userAddress = getAddress(poolShare.userAddress.id); + const shares = + (poolToken.balance / poolShare.poolId.totalShares) * + poolShare.balance; + votingPowers[userAddress] = votingPowers[userAddress] + shares; + } + }) + ); + } + commit('GET_VOTING_POWERS_SUCCESS'); + return votingPowers; + } catch (e) { + commit('GET_VOTING_POWERS_FAILURE', e); + } + }, + getVotingPowersByPools: async ( + { commit }, + { blockTag, token, addresses } + ) => { + commit('GET_VOTING_POWERS_REQUEST'); + try { + const block = blockTag === 'latest' ? undefined : { number: blockTag }; + const result = await request('getVotingPowers', { + poolShares: { + __args: { + block, + where: { + userAddress_in: addresses.map(address => address.toLowerCase()) + } + } + } + }); + const votingPowers: any = Object.fromEntries( + addresses.map(address => [address, {}]) + ); + if (result && result.poolShares) { + result.poolShares.forEach(poolShare => + poolShare.poolId.tokens.map(poolToken => { + const [poolId, tokenAddress] = poolToken.id.split('-'); + if (tokenAddress === token.toLowerCase()) { + const userAddress = getAddress(poolShare.userAddress.id); + const poolAddress = getAddress(poolId); + votingPowers[userAddress][poolAddress] = + (poolToken.balance / poolShare.poolId.totalShares) * + poolShare.balance; + } + }) + ); + } + commit('GET_VOTING_POWERS_SUCCESS'); + return votingPowers || {}; + } catch (e) { + commit('GET_VOTING_POWERS_FAILURE', e); + } + } +}; + +export default { + mutations, + actions +}; diff --git a/src/store/modules/ui.ts b/src/store/modules/ui.ts new file mode 100644 index 0000000..a4d22bf --- /dev/null +++ b/src/store/modules/ui.ts @@ -0,0 +1,39 @@ +import Vue from 'vue'; +import lock from '@/helpers/lock'; +import { lsGet } from '@/helpers/utils'; +import config from '@/helpers/config'; + +const state = { + init: false, + loading: false +}; + +const mutations = { + SET(_state, payload) { + Object.keys(payload).forEach(key => { + Vue.set(_state, key, payload[key]); + }); + } +}; + +const actions = { + init: async ({ commit, dispatch }) => { + commit('SET', { loading: true }); + await Promise.all([dispatch('getBlockNumber'), dispatch('metadata')]); + const connector = lsGet('connector'); + if (Object.keys(config.connectors).includes(connector)) { + const lockConnector = lock.getConnector(connector); + if (await lockConnector.isLoggedIn()) await dispatch('login', connector); + } + commit('SET', { loading: false, init: true }); + }, + loading: ({ commit }, payload) => { + commit('SET', { loading: payload }); + } +}; + +export default { + state, + mutations, + actions +}; diff --git a/src/store/modules/web3.ts b/src/store/modules/web3.ts new file mode 100644 index 0000000..f2f0702 --- /dev/null +++ b/src/store/modules/web3.ts @@ -0,0 +1,396 @@ +import Vue from 'vue'; +import { Web3Provider } from '@ethersproject/providers'; +import { Contract } from '@ethersproject/contracts'; +import { getAddress } from '@ethersproject/address'; +import { formatUnits } from '@ethersproject/units'; +import { Interface } from '@ethersproject/abi'; +import store from '@/store'; +import abi from '@/helpers/abi'; +import config from '@/helpers/config'; +import lock from '@/helpers/lock'; +import wsProvider from '@/helpers/ws'; +import { lsSet, lsGet, lsRemove } from '@/helpers/utils'; +import namespaces from '@/namespaces.json'; + +let provider; +let web3; + +wsProvider.on('block', blockNumber => { + store.commit('GET_BLOCK_SUCCESS', blockNumber); +}); + +const state = { + injectedLoaded: false, + injectedChainId: null, + account: null, + name: null, + active: false, + balances: {}, + blockNumber: 0, + namespaces: {} +}; + +const mutations = { + LOGOUT(_state) { + Vue.set(_state, 'injectedLoaded', false); + Vue.set(_state, 'injectedChainId', null); + Vue.set(_state, 'account', null); + Vue.set(_state, 'name', null); + Vue.set(_state, 'active', false); + Vue.set(_state, 'balances', {}); + console.debug('LOGOUT'); + }, + LOAD_WEB3_REQUEST() { + console.debug('LOAD_WEB3_REQUEST'); + }, + LOAD_WEB3_SUCCESS() { + console.debug('LOAD_WEB3_SUCCESS'); + }, + LOAD_WEB3_FAILURE(_state, payload) { + console.debug('LOAD_WEB3_FAILURE', payload); + }, + LOAD_PROVIDER_REQUEST() { + console.debug('LOAD_PROVIDER_REQUEST'); + }, + LOAD_PROVIDER_SUCCESS(_state, payload) { + Vue.set(_state, 'injectedLoaded', payload.injectedLoaded); + Vue.set(_state, 'injectedChainId', payload.injectedChainId); + Vue.set(_state, 'account', payload.account); + Vue.set(_state, 'name', payload.name); + console.debug('LOAD_PROVIDER_SUCCESS'); + }, + LOAD_PROVIDER_FAILURE(_state, payload) { + Vue.set(_state, 'injectedLoaded', false); + Vue.set(_state, 'injectedChainId', null); + Vue.set(_state, 'account', null); + Vue.set(_state, 'active', false); + console.debug('LOAD_PROVIDER_FAILURE', payload); + }, + LOAD_BACKUP_PROVIDER_REQUEST() { + console.debug('LOAD_BACKUP_PROVIDER_REQUEST'); + }, + LOAD_BACKUP_PROVIDER_SUCCESS(_state, payload) { + console.debug('LOAD_BACKUP_PROVIDER_SUCCESS', payload); + }, + LOAD_BACKUP_PROVIDER_FAILURE(_state, payload) { + Vue.set(_state, 'injectedLoaded', false); + Vue.set(_state, 'backUpLoaded', false); + Vue.set(_state, 'account', null); + Vue.set(_state, 'activeChainId', null); + Vue.set(_state, 'active', false); + console.debug('LOAD_BACKUP_PROVIDER_FAILURE', payload); + }, + HANDLE_CHAIN_CHANGED() { + console.debug('HANDLE_CHAIN_CHANGED'); + }, + HANDLE_ACCOUNTS_CHANGED(_state, payload) { + Vue.set(_state, 'account', payload); + console.debug('HANDLE_ACCOUNTS_CHANGED', payload); + }, + HANDLE_CLOSE_CHANGED() { + console.debug('HANDLE_CLOSE_CHANGED'); + }, + HANDLE_NETWORK_CHANGED() { + console.debug('HANDLE_NETWORK_CHANGED'); + }, + LOOKUP_ADDRESS_REQUEST() { + console.debug('LOOKUP_ADDRESS_REQUEST'); + }, + LOOKUP_ADDRESS_SUCCESS(_state, payload) { + Vue.set(_state, 'name', payload); + console.debug('LOOKUP_ADDRESS_SUCCESS'); + }, + LOOKUP_ADDRESS_FAILURE(_state, payload) { + console.debug('LOOKUP_ADDRESS_FAILURE', payload); + }, + RESOLVE_NAME_REQUEST() { + console.debug('RESOLVE_NAME_REQUEST'); + }, + RESOLVE_NAME_SUCCESS() { + console.debug('RESOLVE_NAME_SUCCESS'); + }, + RESOLVE_NAME_FAILURE(_state, payload) { + console.debug('RESOLVE_NAME_FAILURE', payload); + }, + SEND_TRANSACTION_REQUEST() { + console.debug('SEND_TRANSACTION_REQUEST'); + }, + SEND_TRANSACTION_SUCCESS() { + console.debug('SEND_TRANSACTION_SUCCESS'); + }, + SEND_TRANSACTION_FAILURE(_state, payload) { + console.debug('SEND_TRANSACTION_FAILURE', payload); + }, + SIGN_MESSAGE_REQUEST() { + console.debug('SIGN_MESSAGE_REQUEST'); + }, + SIGN_MESSAGE_SUCCESS() { + console.debug('SIGN_MESSAGE_SUCCESS'); + }, + SIGN_MESSAGE_FAILURE(_state, payload) { + console.debug('SIGN_MESSAGE_FAILURE', payload); + }, + GET_BLOCK_REQUEST() { + console.debug('GET_BLOCK_REQUEST'); + }, + GET_BLOCK_SUCCESS(_state, payload) { + Vue.set(_state, 'blockNumber', payload); + console.debug('GET_BLOCK_SUCCESS', payload); + }, + GET_BLOCK_FAILURE(_state, payload) { + console.debug('GET_BLOCK_FAILURE', payload); + }, + GET_BALANCE_REQUEST() { + console.debug('GET_BALANCE_REQUEST'); + }, + GET_BALANCE_SUCCESS() { + console.debug('GET_BALANCE_SUCCESS'); + }, + GET_BALANCE_FAILURE(_state, payload) { + console.debug('GET_BALANCE_FAILURE', payload); + }, + MULTICALL_SUCCESS() { + console.debug('MULTICALL_SUCCESS'); + }, + METADATA_SUCCESS(_state, payload) { + Vue.set(_state, 'namespaces', payload); + console.debug('METADATA_SUCCESS'); + } +}; + +const actions = { + login: async ({ dispatch }, connector = 'injected') => { + const lockConnector = lock.getConnector(connector); + provider = await lockConnector.connect(); + if (provider) { + web3 = new Web3Provider(provider); + await dispatch('loadWeb3'); + if (state.account) lsSet('connector', connector); + } + }, + logout: async ({ commit }) => { + const connector = lsGet('connector'); + if (connector) { + const lockConnector = lock.getConnector(connector); + await lockConnector.logout(); + lsRemove('connector'); + } + commit('LOGOUT'); + }, + loadWeb3: async ({ commit, dispatch }) => { + commit('LOAD_WEB3_REQUEST'); + try { + await dispatch('loadProvider'); + await dispatch('loadAccount'); + commit('LOAD_WEB3_SUCCESS'); + if (!state.injectedLoaded || state.injectedChainId !== config.chainId) { + await dispatch('loadBackupProvider'); + } else { + /** + this.providerStatus.activeChainId = this.providerStatus.injectedChainId; + this.providerStatus.injectedActive = true; + if (this.providerStatus.account) + this.fetchUserBlockchainData(this.providerStatus.account); + */ + } + } catch (e) { + commit('LOAD_WEB3_FAILURE', e); + return Promise.reject(); + } + }, + loadProvider: async ({ commit, dispatch }) => { + commit('LOAD_PROVIDER_REQUEST'); + try { + provider.removeAllListeners(); + if (provider.on) { + provider.on('chainChanged', async () => { + commit('HANDLE_CHAIN_CHANGED'); + if (state.active) { + await dispatch('loadWeb3'); + } + }); + provider.on('accountsChanged', async accounts => { + if (accounts.length === 0) { + if (state.active) await dispatch('loadWeb3'); + } else { + commit('HANDLE_ACCOUNTS_CHANGED', accounts[0]); + await dispatch('loadWeb3'); + } + }); + provider.on('close', async () => { + commit('HANDLE_CLOSE'); + if (state.active) await dispatch('loadWeb3'); + }); + provider.on('networkChanged', async () => { + commit('HANDLE_NETWORK_CHANGED'); + if (state.active) { + await dispatch('loadWeb3'); + } + }); + } + const network = await web3.getNetwork(); + const accounts = await web3.listAccounts(); + const account = accounts.length > 0 ? accounts[0] : null; + commit('LOAD_PROVIDER_SUCCESS', { + injectedLoaded: true, + injectedChainId: network.chainId, + account, + name + }); + } catch (e) { + commit('LOAD_PROVIDER_FAILURE', e); + return Promise.reject(); + } + }, + loadBackupProvider: async ({ commit }) => { + try { + web3 = wsProvider; + const network = await wsProvider.getNetwork(); + commit('LOAD_BACKUP_PROVIDER_SUCCESS', { + injectedActive: false, + backUpLoaded: true, + account: null, + activeChainId: network.chainId + // backUpWeb3: web3, + }); + } catch (e) { + commit('LOAD_BACKUP_PROVIDER_FAILURE', e); + return Promise.reject(); + } + }, + lookupAddress: async ({ commit }) => { + commit('LOOKUP_ADDRESS_REQUEST'); + try { + const name = await web3.lookupAddress(state.account); + commit('LOOKUP_ADDRESS_SUCCESS', name); + return name; + } catch (e) { + commit('LOOKUP_ADDRESS_FAILURE', e); + } + }, + resolveName: async ({ commit }, payload) => { + commit('RESOLVE_NAME_REQUEST'); + try { + const address = await web3.resolveName(payload); + commit('RESOLVE_NAME_SUCCESS'); + return address; + } catch (e) { + commit('RESOLVE_NAME_FAILURE', e); + return Promise.reject(); + } + }, + sendTransaction: async ( + { commit }, + [contractType, contractAddress, action, params] + ) => { + commit('SEND_TRANSACTION_REQUEST'); + try { + const signer = web3.getSigner(); + const contract = new Contract( + getAddress(contractAddress), + abi[contractType], + web3 + ); + const contractWithSigner = contract.connect(signer); + const tx = await contractWithSigner[action](...params); + await tx.wait(); + commit('SEND_TRANSACTION_SUCCESS'); + return tx; + } catch (e) { + commit('SEND_TRANSACTION_FAILURE', e); + return Promise.reject(); + } + }, + signMessage: async ({ commit }, message) => { + commit('SIGN_MESSAGE_REQUEST'); + try { + const signer = web3.getSigner(); + const sig = await signer.signMessage(message); + commit('SIGN_MESSAGE_SUCCESS'); + return sig; + } catch (e) { + commit('SIGN_MESSAGE_FAILURE', e); + return Promise.reject(e); + } + }, + loadAccount: async ({ dispatch }) => { + await dispatch('lookupAddress'); + }, + getBlockNumber: async ({ commit }) => { + commit('GET_BLOCK_REQUEST'); + try { + const blockNumber: any = await wsProvider.getBlockNumber(); + commit('GET_BLOCK_SUCCESS', parseInt(blockNumber)); + return blockNumber; + } catch (e) { + commit('GET_BLOCK_FAILURE', e); + return Promise.reject(); + } + }, + getBalance: async ({ commit, dispatch }, { blockTag, token }) => { + const { decimals } = state.namespaces[token]; + commit('GET_BALANCE_REQUEST'); + try { + const response = await dispatch('multicall', { + name: 'TestToken', + calls: [[token, 'balanceOf', [state.account]]], + options: { blockTag } + }); + const balance = parseFloat(formatUnits(response[0].toString(), decimals)); + commit('GET_BALANCE_SUCCESS'); + return balance; + } catch (e) { + commit('GET_BALANCE_FAILURE', e); + return Promise.reject(); + } + }, + multicall: async ({ commit }, { name, calls, options }) => { + const multi = new Contract(config.multicall, abi['Multicall'], wsProvider); + const itf = new Interface(abi[name]); + try { + let [, response] = await multi.aggregate( + calls.map(call => [ + call[0].toLowerCase(), + itf.encodeFunctionData(call[1], call[2]) + ]), + options || {} + ); + response = response.map((call, i) => + itf.decodeFunctionResult(calls[i][1], call) + ); + commit('MULTICALL_SUCCESS'); + return response; + } catch (e) { + return Promise.reject(); + } + }, + metadata: async ({ commit, dispatch }) => { + try { + const response = await dispatch('multicall', { + name: 'TestToken', + calls: Object.values(namespaces).map((namespace: any) => [ + namespace.address, + 'decimals', + [] + ]) + }); + const payload = Object.fromEntries( + response.map((item, i) => [ + // @ts-ignore + Object.values(namespaces)[i].address, + { decimals: response[i][0] } + ]) + ); + commit('METADATA_SUCCESS', payload); + return payload; + } catch (e) { + return Promise.reject(); + } + } +}; + +export default { + state, + mutations, + actions +}; diff --git a/src/style.scss b/src/style.scss new file mode 100644 index 0000000..33278e5 --- /dev/null +++ b/src/style.scss @@ -0,0 +1,99 @@ +@import './fonts'; +@import './vars'; +@import "~@primer/css/index.scss"; + +html, body, #app { + background-color: $black; + color: $gray; + font-family: $font-weight-normal; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} + +* { + outline: none !important; +} + +h1, h2, h3, h4 { + color: $white; + font-family: $font-weight-bold; +} + +b { + font-family: $font-weight-bold; +} + +p { + font-size: 22px; +} + +#app { + min-height: 100vh; +} + +a { + color: $white; + + &:hover { + color: $white !important; + cursor: pointer; + text-decoration: none !important; + } +} + +::placeholder { + color: $gray; +} + +.input { + outline: none; + color: $white; + background-color: transparent; + border: none; +} + +textarea { + font-size: 20px; +} + +::-webkit-scrollbar-thumb { + background-color: $border-color; + background-clip: padding-box; + border: 0; + border-radius: 0; + + &:hover { + background-color: $border-color; + } +} + +.eyebrow { + text-transform: uppercase; + letter-spacing: 1px; + font-size: 16px; +} + +.column { + width: 160px; +} + +.anim-fade-in { + animation-duration: 0.6s !important; +} + +.line-height-0 { + line-height: 0; +} + +.bg-black { + background-color: $black; +} + +.State { + font-size: 16px; + line-height: 30px; + height: 28px; + vertical-align: middle; + padding: 0 12px; + border-radius: 14px; +} diff --git a/src/vars.scss b/src/vars.scss new file mode 100644 index 0000000..6ba276e --- /dev/null +++ b/src/vars.scss @@ -0,0 +1,30 @@ +@import '~primer-support'; + +// Default skin +$black: #0f1011; +$border-color: #353d45; +$blue: #384AFF; +$green: #21b66f; +$red: #ff3856; +$bg-blue: $blue; +$bg-green: $green; +$bg-red: $red; +$text-blue: $blue; +$text-green: $green; +$text-red: $red; +$bg-gray-dark: lighten($black, 2); + +@import './yam'; + +$border: 1px solid $border-color; +$border-radius: 4px; +$body-font-size: 18px; +$body-line-height: 1.4; +$h1-size: 36px; +$h2-size: 28px; +$h3-size: 24px; +$h4-size: 20px; +$font-weight-normal: 'Calibre-Medium', -apple-system, BlinkMacSystemFont, Segoe UI, Helvetica, Arial, sans-serif, Apple Color Emoji, Segoe UI Emoji; +$font-weight-bold: 'Calibre-Semibold', -apple-system, BlinkMacSystemFont, Segoe UI, Helvetica, Arial, sans-serif, Apple Color Emoji, Segoe UI Emoji; +$body-font: $font-weight-normal; +$font-mktg: $font-weight-bold; diff --git a/src/views/Create.vue b/src/views/Create.vue new file mode 100644 index 0000000..c146b94 --- /dev/null +++ b/src/views/Create.vue @@ -0,0 +1,185 @@ + + + diff --git a/src/views/Home.vue b/src/views/Home.vue new file mode 100644 index 0000000..c7fb4bc --- /dev/null +++ b/src/views/Home.vue @@ -0,0 +1,45 @@ + + + diff --git a/src/views/Proposal.vue b/src/views/Proposal.vue new file mode 100644 index 0000000..2ca6dc3 --- /dev/null +++ b/src/views/Proposal.vue @@ -0,0 +1,193 @@ + + + diff --git a/src/views/Proposals.vue b/src/views/Proposals.vue new file mode 100644 index 0000000..68488d6 --- /dev/null +++ b/src/views/Proposals.vue @@ -0,0 +1,142 @@ + + + diff --git a/src/yam.scss b/src/yam.scss new file mode 100644 index 0000000..0f901ac --- /dev/null +++ b/src/yam.scss @@ -0,0 +1,23 @@ +$white: #5b2739; +$text-white: $white; +$black: #efe7ea; +$border-color: #e2cfd5; +$bg-gray-dark: lighten($black, 2); +$gray: #a98592; +$text-gray: $gray; +$blue: #d2004a; +$gray-900: $gray; +$bg-blue: $blue; + +.State, .Counter, .button--submit { + color: $black !important; + + &:disabled { + border: 1px solid $border-color !important; + background-color: $border-color !important; + } +} + +.bg-gray-9 { + background-color: $border-color !important; +} diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..00c6365 --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,41 @@ +{ + "compilerOptions": { + "target": "esnext", + "module": "esnext", + "strict": true, + "jsx": "preserve", + "importHelpers": true, + "moduleResolution": "node", + "esModuleInterop": true, + "allowSyntheticDefaultImports": true, + "sourceMap": true, + "baseUrl": ".", + "types": [ + "webpack-env" + ], + "paths": { + "@/*": [ + "src/*" + ] + }, + "lib": [ + "esnext", + "dom", + "dom.iterable", + "scripthost" + ], + "noImplicitAny": false, + "resolveJsonModule": true, + "skipLibCheck": true + }, + "include": [ + "src/**/*.ts", + "src/**/*.tsx", + "src/**/*.vue", + "tests/**/*.ts", + "tests/**/*.tsx" + ], + "exclude": [ + "node_modules" + ] +} diff --git a/vue.config.js b/vue.config.js new file mode 100644 index 0000000..d272bf2 --- /dev/null +++ b/vue.config.js @@ -0,0 +1,7 @@ +module.exports = { + pluginOptions: { + webpackBundleAnalyzer: { + openAnalyzer: false + } + } +};