From 5ba7a6106e290e5345dd7173b8206111094c3eaf Mon Sep 17 00:00:00 2001 From: alet89 Date: Mon, 24 Aug 2020 17:10:18 +0200 Subject: [PATCH 01/76] ff --- assets/css/style.css | 2 ++ 1 file changed, 2 insertions(+) diff --git a/assets/css/style.css b/assets/css/style.css index 0388303..85159ca 100644 --- a/assets/css/style.css +++ b/assets/css/style.css @@ -69,6 +69,8 @@ footer p a, footer h5 a {color: #c7ac97; font-weight: bold;} .unifiDapp .MenuAll .connectOpener span {font-size: 18px; vertical-align: middle;} .unifiDapp .MenuOpen {text-align: left; position: absolute; left: 90px; top: 50px; z-index: 99999999999999;} .unifiDapp .MenuOpen .coverMenu {margin: 0;z-index: 99999999999999;} +.ethereumWalletProvider {text-align: left; position: absolute; right: 90px; top: 50px; z-index: 99999999999999;} + .UniBox, .UniSideBox {position: relative;max-width: 250px;width: 100%; opacity: 1;padding: 30px 1rem; margin: 50px 10px 50px 10px;vertical-align: top;} .UniStableManage {width: 25px; height: 25px;vertical-align: middle; margin: 7px;} .UniActiveQuantityTier, .UniDisactiveQuantityTier {display: inline-block; margin: 5px auto;} From b98a6b7e73915ee48190315225ec534bd9ea936a Mon Sep 17 00:00:00 2001 From: alet89 Date: Mon, 24 Aug 2020 17:20:37 +0200 Subject: [PATCH 02/76] Connetc --- assets/css/style.css | 4 +++- spa/stableCoin/view.jsx | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/assets/css/style.css b/assets/css/style.css index 85159ca..2159ebf 100644 --- a/assets/css/style.css +++ b/assets/css/style.css @@ -69,7 +69,7 @@ footer p a, footer h5 a {color: #c7ac97; font-weight: bold;} .unifiDapp .MenuAll .connectOpener span {font-size: 18px; vertical-align: middle;} .unifiDapp .MenuOpen {text-align: left; position: absolute; left: 90px; top: 50px; z-index: 99999999999999;} .unifiDapp .MenuOpen .coverMenu {margin: 0;z-index: 99999999999999;} -.ethereumWalletProvider {text-align: left; position: absolute; right: 90px; top: 50px; z-index: 99999999999999;} +.ethereumWalletProvider {text-align: left; position: absolute; right: 20px; top: 0px; z-index: 99999999999999;} .UniBox, .UniSideBox {position: relative;max-width: 250px;width: 100%; opacity: 1;padding: 30px 1rem; margin: 50px 10px 50px 10px;vertical-align: top;} .UniStableManage {width: 25px; height: 25px;vertical-align: middle; margin: 7px;} @@ -143,6 +143,8 @@ footer p a, footer h5 a {color: #c7ac97; font-weight: bold;} .RPG .UniActiveQuantityTier h6, .RPG .UniDisactiveQuantityTier h6 {color: #adadad;} .RPG .UniActiveQuantityTier h6 a, .RPG .UniDisactiveQuantityTier h6 a {background-color: #000000; color: #ffffff; border-radius: 5px; margin-right: 5px;} .RPG .coverConnectMenu .ethereumWalletProvider {background-color: #2b2622; border-color: #2b2622;box-shadow: rgba(0, 0, 0, 0.01) 0px 0px 1px, rgba(0, 0, 0, 0.04) 0px 4px 8px, rgba(0, 0, 0, 0.04) 0px 16px 24px, rgba(0, 0, 0, 0.01) 0px 24px 32px;} +.RPG .ethereumWalletProvider a {color: #bab9b9;} + @media only screen and (min-width: 640px) { .cover {max-height: 740px; width: 100%;} diff --git a/spa/stableCoin/view.jsx b/spa/stableCoin/view.jsx index f486ae9..fe78242 100644 --- a/spa/stableCoin/view.jsx +++ b/spa/stableCoin/view.jsx @@ -191,7 +191,7 @@ var StableCoin = React.createClass({ )} } } - {window.walletAddress && this.state && this.state.totalCoins &&
+ {this.state && this.state.totalCoins &&

Health:

From 4fbe204cfac521508f61ac65a13446865cf49695 Mon Sep 17 00:00:00 2001 From: alet89 Date: Mon, 24 Aug 2020 19:18:36 +0200 Subject: [PATCH 03/76] roba --- assets/css/style.css | 9 ++++++--- spa/grimoire/view.jsx | 14 +++++++++++--- 2 files changed, 17 insertions(+), 6 deletions(-) diff --git a/assets/css/style.css b/assets/css/style.css index 2159ebf..a67d25f 100644 --- a/assets/css/style.css +++ b/assets/css/style.css @@ -68,7 +68,7 @@ footer p a, footer h5 a {color: #c7ac97; font-weight: bold;} .unifiDapp .MenuAll .connectOpener img {width: 25px; height: 25px; vertical-align: middle;} .unifiDapp .MenuAll .connectOpener span {font-size: 18px; vertical-align: middle;} .unifiDapp .MenuOpen {text-align: left; position: absolute; left: 90px; top: 50px; z-index: 99999999999999;} -.unifiDapp .MenuOpen .coverMenu {margin: 0;z-index: 99999999999999;} +.unifiDapp .MenuOpen .coverMenu {margin: 0;z-index: 99999999999999;outline: -webkit-focus-ring-color auto 0px;} .ethereumWalletProvider {text-align: left; position: absolute; right: 20px; top: 0px; z-index: 99999999999999;} .UniBox, .UniSideBox {position: relative;max-width: 250px;width: 100%; opacity: 1;padding: 30px 1rem; margin: 50px 10px 50px 10px;vertical-align: top;} @@ -76,6 +76,9 @@ footer p a, footer h5 a {color: #c7ac97; font-weight: bold;} .UniActiveQuantityTier, .UniDisactiveQuantityTier {display: inline-block; margin: 5px auto;} .UniTierQuantity h6 {font-size: 15px; margin: 6px auto;} .StableCoinTitle, .grimoireWelcome {width: 100%; margin-top: 100px; text-align: center;} +.grimoireBoxAll {width: 100%; margin-top: 25px; text-align: center;} +.grimoireBox {width: 95%; margin-bottom: 18px;} + .StableCoinTitle .StableCoinTitleIntern, .grimoireWelcome .grimoireWelcomeIntern {display: none;} .StableCoinTitle h2, .grimoireWelcome h2 {font-size: 25px; margin: 10px 0; vertical-align: middle;text-align: left;} .StableCoinTitle h6, .grimoireWelcome h6 {font-size: 15px; text-align: left; line-height: 1.4; font-weight: normal;} @@ -168,7 +171,7 @@ footer p a, footer h5 a {color: #c7ac97; font-weight: bold;} .coverMenu .menuArrow img {width: 20px; height: 20px;} .unifiWelcome .MenuOpen {display: inline-block !important;} .MenuOpen {width: 100%; display: inline-block; text-align: center;} - .StableCoinTitle .StableCoinTitleIntern, .grimoireWelcome .grimoireWelcomeIntern {width: 590px; padding: 20px; border-radius: 8px; display: inline-block;} + .StableCoinTitle .StableCoinTitleIntern, .grimoireWelcome .grimoireWelcomeIntern, .grimoireBox {width: 590px; padding: 20px; border-radius: 8px; display: inline-block;} .StableCoinTitleIntern article, .grimoireWelcomeIntern article {width: 480px; display: inline-block; vertical-align: middle;} .StableCoinTitle img, .grimoireWelcome img {width: 80px; height: 80px; margin-right: 10px; vertical-align: middle;} footer .welcomeLinks, footer p {width: 500px; padding: 20px;} @@ -185,7 +188,7 @@ footer p a, footer h5 a {color: #c7ac97; font-weight: bold;} .featureActions a {padding: 4px 7px; font-size: 18px; border: 4px solid #5d5e60;} .unifiWelcome header {width: 500px;} .unifiWelcome header h2 {font-size: 20px;} - .StableCoinTitle .StableCoinTitleIntern, .grimoireWelcome .grimoireWelcomeIntern {width: 740px;} + .StableCoinTitle .StableCoinTitleIntern, .grimoireWelcome .grimoireWelcomeIntern, .grimoireBox {width: 740px;} .StableCoinTitleIntern article, .grimoireWelcomeIntern article {width: 590px;} .StableCoinTitle img, .grimoireWelcome img {width: 100px; height: 100px;} footer .welcomeLinks, footer p {width: 500px;} diff --git a/spa/grimoire/view.jsx b/spa/grimoire/view.jsx index 90b8a58..a211174 100644 --- a/spa/grimoire/view.jsx +++ b/spa/grimoire/view.jsx @@ -11,12 +11,20 @@ var Grimoire = React.createClass({
-

Uniswap State Dollar

-
uSD is a Stable Coin based on Uniswap Liquidity Pools More

Here, you can mint uSD by adding liquidity to whitelisted Uniswap Stable Coin Pools or redeem anytime whitelisted Stable Coins by burning uSD.
+

The Grimoire

+
The comprehensive giude to use the Uniswap Magic

Here, you can find every info needed to understand UniFi and to integrate your dapp with this protocol.
-
+
+
+ +
From 0511ffac4291edf3a308edec4c5aef457961c470 Mon Sep 17 00:00:00 2001 From: alet89 Date: Mon, 24 Aug 2020 22:56:59 +0200 Subject: [PATCH 04/76] Grimoire Index --- assets/css/style.css | 12 ++++++++++-- spa/grimoire/view.jsx | 9 +++++---- 2 files changed, 15 insertions(+), 6 deletions(-) diff --git a/assets/css/style.css b/assets/css/style.css index a67d25f..2380c00 100644 --- a/assets/css/style.css +++ b/assets/css/style.css @@ -77,7 +77,11 @@ footer p a, footer h5 a {color: #c7ac97; font-weight: bold;} .UniTierQuantity h6 {font-size: 15px; margin: 6px auto;} .StableCoinTitle, .grimoireWelcome {width: 100%; margin-top: 100px; text-align: center;} .grimoireBoxAll {width: 100%; margin-top: 25px; text-align: center;} -.grimoireBox {width: 95%; margin-bottom: 18px;} +.grimoireBox {width: 95%; margin-bottom: 18px; text-align: center;} +.grimoireIndex {width: 95%; margin-left: 4%; text-align: left;} +.grimoireIndex a {width: 100%; padding: 20px 0; display: inline-block; font-size: 18px; vertical-align: middle;} +.grimoireIndex h2 {font-size: 30px; margin-bottom: 20px;} +.grimoireIndex a img {width: 30px;height: 30px; margin-right: 6px; vertical-align: middle;} .StableCoinTitle .StableCoinTitleIntern, .grimoireWelcome .grimoireWelcomeIntern {display: none;} .StableCoinTitle h2, .grimoireWelcome h2 {font-size: 25px; margin: 10px 0; vertical-align: middle;text-align: left;} @@ -127,7 +131,7 @@ footer p a, footer h5 a {color: #c7ac97; font-weight: bold;} .Boomer .UniBox {background: rgb(33, 36, 41); box-shadow: rgba(0, 0, 0, 0.01) 0px 0px 1px, rgba(0, 0, 0, 0.04) 0px 4px 8px, rgba(0, 0, 0, 0.04) 0px 16px 24px, rgba(0, 0, 0, 0.01) 0px 24px 32px; border-radius: 30px; color: #f1f1f1;} -.RPG .UniBox {position: initial;background: rgb(33, 36, 41); border-radius: 20px; color: rgb(195, 197, 203);box-shadow: rgba(0, 0, 0, 0.01) 0px 0px 1px, rgba(0, 0, 0, 0.04) 0px 4px 8px, rgba(0, 0, 0, 0.04) 0px 16px 24px, rgba(0, 0, 0, 0.01) 0px 24px 32px;width: 100%;} +.RPG .UniBox, .grimoireBox {position: initial;background: rgb(33, 36, 41); border-radius: 20px; color: rgb(195, 197, 203);box-shadow: rgba(0, 0, 0, 0.01) 0px 0px 1px, rgba(0, 0, 0, 0.04) 0px 4px 8px, rgba(0, 0, 0, 0.04) 0px 16px 24px, rgba(0, 0, 0, 0.01) 0px 24px 32px;width: 100%;} .RPG .UniSideBox {border-radius: 20px; color: #bab9b9; width: 100%; background-color: #2b2622;box-shadow: rgba(0, 0, 0, 0.01) 0px 0px 1px, rgba(0, 0, 0, 0.04) 0px 4px 8px, rgba(0, 0, 0, 0.04) 0px 16px 24px, rgba(0, 0, 0, 0.01) 0px 24px 32px;} .RPG body {background: linear-gradient(29deg, rgba(80,80,80,1) 0%, rgba(46,46,46,1) 66%);} .RPG .UniTitle select, .RPG .UniActiveQuantityTier input, .RPG .UniDisactiveQuantityTier input, .RebalanceEmergency label input {background-color: #000000; color: #f1f1f1; border: 5px solid #000000; border-radius: 5px;} @@ -147,6 +151,8 @@ footer p a, footer h5 a {color: #c7ac97; font-weight: bold;} .RPG .UniActiveQuantityTier h6 a, .RPG .UniDisactiveQuantityTier h6 a {background-color: #000000; color: #ffffff; border-radius: 5px; margin-right: 5px;} .RPG .coverConnectMenu .ethereumWalletProvider {background-color: #2b2622; border-color: #2b2622;box-shadow: rgba(0, 0, 0, 0.01) 0px 0px 1px, rgba(0, 0, 0, 0.04) 0px 4px 8px, rgba(0, 0, 0, 0.04) 0px 16px 24px, rgba(0, 0, 0, 0.01) 0px 24px 32px;} .RPG .ethereumWalletProvider a {color: #bab9b9;} +.RPG .grimoireIndex h2 {text-shadow:2px 2px 2px #5d5e60; color: #bab9b9;} +.RPG .grimoireIndex a {text-shadow:2px 2px 2px #5d5e60; color: #bab9b9;} @media only screen and (min-width: 640px) { @@ -175,6 +181,7 @@ footer p a, footer h5 a {color: #c7ac97; font-weight: bold;} .StableCoinTitleIntern article, .grimoireWelcomeIntern article {width: 480px; display: inline-block; vertical-align: middle;} .StableCoinTitle img, .grimoireWelcome img {width: 80px; height: 80px; margin-right: 10px; vertical-align: middle;} footer .welcomeLinks, footer p {width: 500px; padding: 20px;} + .grimoireIndex {width: 350px;} } @media only screen and (min-width: 890px) { @@ -192,5 +199,6 @@ footer p a, footer h5 a {color: #c7ac97; font-weight: bold;} .StableCoinTitleIntern article, .grimoireWelcomeIntern article {width: 590px;} .StableCoinTitle img, .grimoireWelcome img {width: 100px; height: 100px;} footer .welcomeLinks, footer p {width: 500px;} + .grimoireIndex {width: 450px;} } \ No newline at end of file diff --git a/spa/grimoire/view.jsx b/spa/grimoire/view.jsx index a211174..a5bf263 100644 --- a/spa/grimoire/view.jsx +++ b/spa/grimoire/view.jsx @@ -19,10 +19,11 @@ var Grimoire = React.createClass({
From 934c5afd686768bd17ee3122afee24c3aac8e341 Mon Sep 17 00:00:00 2001 From: alet89 Date: Mon, 24 Aug 2020 23:29:37 +0200 Subject: [PATCH 05/76] grimu --- spa/grimoire/grimuSD.jsx | 33 +++++++++++++++++++++++++++++++++ spa/grimoire/view.jsx | 5 ++++- 2 files changed, 37 insertions(+), 1 deletion(-) create mode 100644 spa/grimoire/grimuSD.jsx diff --git a/spa/grimoire/grimuSD.jsx b/spa/grimoire/grimuSD.jsx new file mode 100644 index 0000000..b1301bb --- /dev/null +++ b/spa/grimoire/grimuSD.jsx @@ -0,0 +1,33 @@ +var GrimuSD = React.createClass({ + requiredScripts: [ + 'spa/loader.jsx' + ], + + render() { + return ( +
+ +
+
+ +
+

The Grimoire - Uniswap State Dollar

+
uSD is a Stable Coin based on Uniswap Liquidity Pools Launch Dapp Minted by the magic rainbow of Uniswap stablecoin pools. Backed by the power of the Unicorn, uSD is the most secure stablecoin ever. The only way it could be destabilized is if the entire stablecoin industry crashed.
+
+
+
+
+
+ +
+
+
+ ); + } +}); \ No newline at end of file diff --git a/spa/grimoire/view.jsx b/spa/grimoire/view.jsx index a5bf263..33c117c 100644 --- a/spa/grimoire/view.jsx +++ b/spa/grimoire/view.jsx @@ -1,6 +1,7 @@ var Grimoire = React.createClass({ requiredScripts: [ - 'spa/loader.jsx' + 'spa/loader.jsx', + 'spa/grimoire/grimuSD.jsx' ], render() { @@ -24,10 +25,12 @@ var Grimoire = React.createClass({ Crafting: Programmable Liquidity ILO: Initial Liquidity Offering Bazaar: Uniswap Advanced Listing + UniFi Strategy: Token and WP
+
); } From f4a5eefa8de1985f75c039ebd57497f532962a65 Mon Sep 17 00:00:00 2001 From: Marco Vasapollo Date: Mon, 24 Aug 2020 23:59:24 +0200 Subject: [PATCH 06/76] Bazar first implementation --- assets/img/eth-logo.png | Bin 0 -> 193431 bytes assets/scripts/script.js | 90 ++++++++++++++--- data/context.json | 8 ++ spa/loader.jsx | 2 +- spa/stableCoin/controller.jsx | 4 +- spa/stableCoin/view.jsx | 4 +- spa/swapBazar/controller.jsx | 145 ++++++++++++++++++++++++++- spa/swapBazar/style.min.css | 2 +- spa/swapBazar/style.scss | 25 ----- spa/swapBazar/uniswapTokenPicker.jsx | 73 ++++++++++++++ spa/swapBazar/view.jsx | 69 ++++++++----- 11 files changed, 348 insertions(+), 74 deletions(-) create mode 100644 assets/img/eth-logo.png create mode 100644 spa/swapBazar/uniswapTokenPicker.jsx diff --git a/assets/img/eth-logo.png b/assets/img/eth-logo.png new file mode 100644 index 0000000000000000000000000000000000000000..b2a42b899008ab346bea914bf2ec965fb4e06b12 GIT binary patch literal 193431 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 literal 0 HcmV?d00001 diff --git a/assets/scripts/script.js b/assets/scripts/script.js index fa05237..99d08d2 100644 --- a/assets/scripts/script.js +++ b/assets/scripts/script.js @@ -29,16 +29,33 @@ window.loadDFO = async function loadDFO(address, allAddresses) { var votingToken = window.voidEthereumAddress; try { - votingToken = (await window.blockchainCall(dfo.methods.getDelegates))[0]; - } catch (e) {} + var delegates = await window.web3.eth.call({ + to: element.dFO.options.address, + data: element.dFO.methods.getDelegates().encodeABI() + }); + try { + delegates = window.web3.eth.abi.decodeParameter("address[]", delegates); + } catch (e) { + delegates = window.web3.eth.abi.decodeParameters(["address", "address", "address", "address", "address", "address"], delegates); + } + votingToken = delegates[0]; + } catch (e) { + votingToken = undefined; + } - if (votingToken === window.voidEthereumAddress) { + if (!votingToken || votingToken === window.voidEthereumAddress) { try { votingToken = await window.blockchainCall(dfo.methods.getToken); } catch (e) {} } - if (votingToken === window.voidEthereumAddress) { + try { + await window.blockchainCall(window.newContract(window.context.votingTokenAbi, votingToken).methods.name); + } catch (e) { + votingToken = undefined; + } + + if (!votingToken || votingToken === window.voidEthereumAddress) { var logs = await window.getLogs({ address, topics: [ @@ -98,8 +115,8 @@ window.onEthereumUpdate = function onEthereumUpdate(millis) { window.uniswapV2Router = window.newContract(window.context.UniswapV2RouterAbi, window.context.uniswapV2RouterAddress); window.wethToken = window.newContract(window.context.votingTokenAbi, window.wethAddress = window.web3.utils.toChecksumAddress(await window.blockchainCall(window.uniswapV2Router.methods.WETH))); window.uniswapV2Factory = window.newContract(window.context.UniswapV2FactoryAbi, window.context.uniswapV2FactoryAddress); - window.stableCoin = await window.loadTokenInfos(stableCoin.options.address, window.wethToken.options.address, window.context.StableCoinAbi); - window.votingToken = await window.loadTokenInfos((await (window.dfo = await window.dfo).votingToken).options.address, window.wethToken.options.address); + window.stableCoin = await window.loadTokenInfos(stableCoin.options.address, window.context.StableCoinAbi); + window.votingToken = await window.loadTokenInfos((await (window.dfo = await window.dfo).votingToken).options.address); update = true; } delete window.walletAddress; @@ -1200,22 +1217,21 @@ window.eliminateFloatingFinalZeroes = function eliminateFloatingFinalZeroes(valu return split[1].length === 0 ? split[0] : split.join(decSeparator); }; -window.loadTokenInfos = async function loadTokenInfos(addresses, wethAddress, abi) { - wethAddress = wethAddress || await window.blockchainCall(window.newContract(window.context.uniSwapV2RouterAbi, window.context.uniSwapV2RouterAddress).methods.WETH); - wethAddress = window.web3.utils.toChecksumAddress(wethAddress); +window.loadTokenInfos = async function loadTokenInfos(addresses, abi, noLogo) { var single = (typeof addresses).toLowerCase() === 'string'; addresses = single ? [addresses] : addresses; var tokens = []; + window.tokenInfosCache = window.tokenInfosCache || {}; for (var address of addresses) { address = window.web3.utils.toChecksumAddress(address); var token = window.newContract(abi || window.context.votingTokenAbi, address); - tokens.push({ + tokens.push(window.tokenInfosCache[address] = window.tokenInfosCache[address] || { address, token, - name: address === wethAddress ? 'Ethereum' : await window.blockchainCall(token.methods.name), - symbol: address === wethAddress ? 'ETH' : await window.blockchainCall(token.methods.symbol), - decimals: address === wethAddress ? '18' : await window.blockchainCall(token.methods.decimals), - logo: await window.loadLogo(address === wethAddress ? window.voidEthereumAddress : address) + name: address === window.wethAddress ? 'Ethereum' : await window.blockchainCall(token.methods.name), + symbol: address === window.wethAddress ? 'ETH' : await window.blockchainCall(token.methods.symbol), + decimals: address === window.wethAddress ? '18' : await window.blockchainCall(token.methods.decimals), + logo: noLogo ? undefined : await window.loadLogo(address === window.wethAddress ? window.voidEthereumAddress : address) }); } return single ? tokens[0] : tokens; @@ -1272,4 +1288,50 @@ window.getEthereumPrice = async function getEthereumPrice() { price, requestExpires: new Date().getTime() + window.context.coingeckoEthereumPriceRequestInterval }).price; +}; + +window.loadUniswapPairs = async function loadUniswapPairs(token, indexes) { + window.pairCreatedTopic = window.pairCreatedTopic || window.web3.utils.sha3('PairCreated(address,address,address,uint256)'); + var address = window.web3.utils.toChecksumAddress(token.address); + if (address === window.voidEthereumAddress) { + address = window.wethAddress; + } + var myToken = window.web3.eth.abi.encodeParameter('address', address); + var logs = await window.getLogs({ + address: window.context.uniSwapV2FactoryAddress, + fromBlock: '0', + topics: [ + window.pairCreatedTopic, [myToken] + ] + }); + logs.push(...(await window.getLogs({ + address: window.context.uniSwapV2FactoryAddress, + fromBlock: '0', + topics: [ + window.pairCreatedTopic, [], + [myToken] + ] + }))); + var uniswapPairs = []; + var alreadyAdded = {}; + for (var log of logs) { + for (var topic of log.topics) { + if (topic === window.pairCreatedTopic || topic.toLowerCase() === myToken.toLowerCase()) { + continue; + } + var pairTokenAddress = window.web3.utils.toChecksumAddress(window.web3.eth.abi.decodeParameters(['address', 'uint256'], log.data)[0]); + if (alreadyAdded[pairTokenAddress]) { + continue; + } + alreadyAdded[pairTokenAddress] = true; + var pairToken = await window.loadTokenInfos(pairTokenAddress, window.context.UniswapV2PairAbi, true); + var token0 = window.web3.utils.toChecksumAddress(await window.blockchainCall(pairToken.token.methods.token0)); + var token1 = window.web3.utils.toChecksumAddress(await window.blockchainCall(pairToken.token.methods.token1)); + pairToken.token0 = token0 === address ? token : await window.loadTokenInfos(token0, undefined, true); + pairToken.token1 = token1 === address ? token : await window.loadTokenInfos(token1, undefined, true); + pairToken.key = `${token0}_${token1}-${token1}_${token0}`; + uniswapPairs.push(indexes[pairToken.key] = pairToken); + } + } + return uniswapPairs; }; \ No newline at end of file diff --git a/data/context.json b/data/context.json index f5021bc..0306690 100644 --- a/data/context.json +++ b/data/context.json @@ -10,17 +10,25 @@ "coingeckoEthereumPriceURL": "https://api.coingecko.com/api/v3/coins/markets?vs_currency=usd&ids=ethereum", "coingeckoEthereumPriceRequestInterval": 600000, "trustwalletImgURLTemplate": "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/{0}/logo.png", + "uniswapDappLinkTemplate" : "https://app.uniswap.org/#/{0}?inputCurrency={1}&outputCurrency={2}", + "uniswapInfoLinkTemplate" : "https://uniswap.info/token/{0}", "stableCoinAddressRopsten" : "0x9f4c43A51C9a67F432E5C8BcBFa55312110BCD3A", "stableCoinAddress" : "0x04C2d7C0712089a61C52A315FCe8F28a55F34DFa", "infuraNode" : "https://ropsten.infura.io/v3/5e302428cc5e41a188dc717dc6f34a5b", + "uniwsapOfficialTokensList" : "https://unpkg.com/@uniswap/default-token-list@latest", "uniswapV2RouterAddress" : "0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D", "uniSwapV2FactoryAddress" : "0x5C69bEe701ef814a2B6a3EDD4B1652CB9cc5aA6f", + "dfoAddress": "0xc3BE549499f1e504c793a6c89371Bd7A98229500", + "dfoAddressRopsten": "0x761E02FEC5A21C6d3F284bd536dB2D2d33d5540B", "blockSearchSection" : 9000000, + "deploySearchStart": 9779603, + "deploySearchStartRopsten": 7465062, "typeTimeout" : 600, "defaultCharsAmount" : 90, "transactionConfirmations": 0, "transactionConfirmationsTimeoutMillis": 7000, "slippageAmount" : 0.005, + "proxyAbi": [{"inputs":[{"internalType":"address","name":"location","type":"address"},{"internalType":"bytes","name":"payload","type":"bytes"}],"name":"callFromManager","outputs":[{"internalType":"bool","name":"","type":"bool"},{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newAddress","type":"address"},{"internalType":"bytes","name":"initPayload","type":"bytes"}],"name":"changeProxy","outputs":[],"stateMutability":"nonpayable","type":"function"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"position","type":"uint256"},{"indexed":true,"internalType":"address","name":"oldAddress","type":"address"},{"indexed":true,"internalType":"address","name":"newAddress","type":"address"}],"name":"DelegateChanged","type":"event"},{"inputs":[{"internalType":"address","name":"proposalAddress","type":"address"}],"name":"disableProposal","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"eventSignature","type":"string"},{"internalType":"bytes","name":"firstIndex","type":"bytes"},{"internalType":"bytes","name":"secondIndex","type":"bytes"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"emitEvent","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"codeName","type":"string"},{"internalType":"address","name":"proposal","type":"address"},{"internalType":"string","name":"replaced","type":"string"},{"internalType":"address","name":"replacedSourceLocation","type":"address"},{"internalType":"uint256","name":"replacedSourceLocationId","type":"uint256"},{"internalType":"address","name":"location","type":"address"},{"internalType":"bool","name":"submitable","type":"bool"},{"internalType":"string","name":"methodSignature","type":"string"},{"internalType":"bool","name":"isInternal","type":"bool"},{"internalType":"bool","name":"needsSender","type":"bool"},{"internalType":"address","name":"proposalAddress","type":"address"}],"name":"emitFromManager","outputs":[],"stateMutability":"nonpayable","type":"function"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"string","name":"key","type":"string"},{"indexed":true,"internalType":"bytes32","name":"firstIndex","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"secondIndex","type":"bytes32"},{"indexed":false,"internalType":"bytes","name":"data","type":"bytes"}],"name":"Event","type":"event"},{"inputs":[{"internalType":"address","name":"tokenAddress","type":"address"},{"internalType":"bool","name":"is721","type":"bool"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"flushToWallet","outputs":[],"stateMutability":"nonpayable","type":"function"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"string","name":"codeName","type":"string"},{"indexed":true,"internalType":"address","name":"proposal","type":"address"},{"indexed":false,"internalType":"string","name":"replaced","type":"string"},{"indexed":false,"internalType":"address","name":"replacedSourceLocation","type":"address"},{"indexed":false,"internalType":"uint256","name":"replacedSourceLocationId","type":"uint256"},{"indexed":true,"internalType":"address","name":"replacedLocation","type":"address"},{"indexed":false,"internalType":"bool","name":"replacedWasSubmitable","type":"bool"},{"indexed":false,"internalType":"string","name":"replacedMethodSignature","type":"string"},{"indexed":false,"internalType":"bool","name":"replacedWasInternal","type":"bool"},{"indexed":false,"internalType":"bool","name":"replacedNeededSender","type":"bool"},{"indexed":true,"internalType":"address","name":"replacedProposal","type":"address"}],"name":"FunctionalitySet","type":"event"},{"inputs":[{"internalType":"address","name":"votingTokenAddress","type":"address"},{"internalType":"address","name":"functionalityProposalManagerAddress","type":"address"},{"internalType":"address","name":"stateHolderAddress","type":"address"},{"internalType":"address","name":"functionalityModelsManagerAddress","type":"address"},{"internalType":"address","name":"functionalitiesManagerAddress","type":"address"},{"internalType":"address","name":"walletAddress","type":"address"},{"internalType":"address","name":"doubleProxyAddress","type":"address"}],"name":"init","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"codeName","type":"string"},{"internalType":"bool","name":"emergency","type":"bool"},{"internalType":"address","name":"sourceLocation","type":"address"},{"internalType":"uint256","name":"sourceLocationId","type":"uint256"},{"internalType":"address","name":"location","type":"address"},{"internalType":"bool","name":"submitable","type":"bool"},{"internalType":"string","name":"methodSignature","type":"string"},{"internalType":"string","name":"returnParametersJSONArray","type":"string"},{"internalType":"bool","name":"isInternal","type":"bool"},{"internalType":"bool","name":"needsSender","type":"bool"},{"internalType":"string","name":"replaces","type":"string"}],"name":"newProposal","outputs":[{"internalType":"address","name":"proposalAddress","type":"address"}],"stateMutability":"nonpayable","type":"function"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"proposal","type":"address"}],"name":"Proposal","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"proposal","type":"address"}],"name":"ProposalCheck","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"proposal","type":"address"},{"indexed":false,"internalType":"bool","name":"success","type":"bool"}],"name":"ProposalSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"newAddress","type":"address"}],"name":"ProxyChanged","type":"event"},{"inputs":[{"internalType":"uint256","name":"position","type":"uint256"},{"internalType":"address","name":"newAddress","type":"address"}],"name":"setDelegate","outputs":[{"internalType":"address","name":"oldAddress","type":"address"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"setProposal","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"proposalAddress","type":"address"}],"name":"startProposal","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"codeName","type":"string"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"submit","outputs":[{"internalType":"bytes","name":"returnData","type":"bytes"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"receiver","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"},{"internalType":"address","name":"token","type":"address"}],"name":"transfer","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"receiver","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"},{"internalType":"bool","name":"safe","type":"bool"},{"internalType":"address","name":"token","type":"address"}],"name":"transfer721","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"getDelegates","outputs":[{"internalType":"address[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getDoubleProxyAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getMVDFunctionalitiesManagerAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getMVDFunctionalityModelsManagerAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getMVDFunctionalityProposalManagerAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getMVDWalletAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getStateHolderAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getToken","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"functionality","type":"address"}],"name":"isAuthorizedFunctionality","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"proposal","type":"address"}],"name":"isValidProposal","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"string","name":"codeName","type":"string"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"read","outputs":[{"internalType":"bytes","name":"returnData","type":"bytes"}],"stateMutability":"view","type":"function"}], "StableCoinAbi" : [{"inputs":[{"internalType":"string","name":"name","type":"string"},{"internalType":"string","name":"symbol","type":"string"},{"internalType":"address","name":"doubleProxy","type":"address"},{"internalType":"address[]","name":"allowedPairs","type":"address[]"},{"internalType":"uint256[]","name":"rebalanceRewardMultiplier","type":"uint256[]"},{"internalType":"uint256[]","name":"timeWindows","type":"uint256[]"},{"internalType":"uint256[]","name":"mintables","type":"uint256[]"}],"stateMutability":"nonpayable","type":"constructor"},{"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"},{"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"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"allowedPairs","outputs":[{"internalType":"address[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"availableToMint","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"pairIndex","type":"uint256"},{"internalType":"uint256","name":"pairAmount","type":"uint256"},{"internalType":"uint256","name":"amount0","type":"uint256"},{"internalType":"uint256","name":"amount1","type":"uint256"}],"name":"burn","outputs":[{"internalType":"uint256","name":"removed0","type":"uint256"},{"internalType":"uint256","name":"removed1","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"burnt","type":"uint256"}],"name":"calculateRebalanceByDebtReward","outputs":[{"internalType":"uint256","name":"reward","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"subtractedValue","type":"uint256"}],"name":"decreaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"differences","outputs":[{"internalType":"uint256","name":"credit","type":"uint256"},{"internalType":"uint256","name":"debt","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"doubleProxy","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"tokenAddress","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"fromTokenToStable","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"addedValue","type":"uint256"}],"name":"increaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"name","type":"string"},{"internalType":"string","name":"symbol","type":"string"},{"internalType":"address","name":"doubleProxy","type":"address"},{"internalType":"address[]","name":"allowedPairs","type":"address[]"},{"internalType":"uint256[]","name":"rebalanceRewardMultiplier","type":"uint256[]"},{"internalType":"uint256[]","name":"timeWindows","type":"uint256[]"},{"internalType":"uint256[]","name":"mintables","type":"uint256[]"}],"name":"init","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"pairIndex","type":"uint256"},{"internalType":"uint256","name":"amount0","type":"uint256"},{"internalType":"uint256","name":"amount1","type":"uint256"},{"internalType":"uint256","name":"amount0Min","type":"uint256"},{"internalType":"uint256","name":"amount1Min","type":"uint256"}],"name":"mint","outputs":[{"internalType":"uint256","name":"minted","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"pairIndex","type":"uint256"},{"internalType":"uint256","name":"pairAmount","type":"uint256"},{"internalType":"uint256","name":"amount0","type":"uint256"},{"internalType":"uint256","name":"amount1","type":"uint256"}],"name":"rebalanceByCredit","outputs":[{"internalType":"uint256","name":"redeemed","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"rebalanceByDebt","outputs":[{"internalType":"uint256","name":"reward","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"rebalanceRewardMultiplier","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"newAllowedPairs","type":"address[]"}],"name":"setAllowedPairs","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newDoubleProxy","type":"address"}],"name":"setDoubleProxy","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"tierData","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"},{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transfer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"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"}],"stateMutability":"nonpayable","type":"function"}], "UniswapV2RouterAbi" : [{"inputs":[],"name":"WETH","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"tokenA","type":"address"},{"internalType":"address","name":"tokenB","type":"address"},{"internalType":"uint256","name":"amountADesired","type":"uint256"},{"internalType":"uint256","name":"amountBDesired","type":"uint256"},{"internalType":"uint256","name":"amountAMin","type":"uint256"},{"internalType":"uint256","name":"amountBMin","type":"uint256"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"addLiquidity","outputs":[{"internalType":"uint256","name":"amountA","type":"uint256"},{"internalType":"uint256","name":"amountB","type":"uint256"},{"internalType":"uint256","name":"liquidity","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"amountTokenDesired","type":"uint256"},{"internalType":"uint256","name":"amountTokenMin","type":"uint256"},{"internalType":"uint256","name":"amountETHMin","type":"uint256"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"addLiquidityETH","outputs":[{"internalType":"uint256","name":"amountToken","type":"uint256"},{"internalType":"uint256","name":"amountETH","type":"uint256"},{"internalType":"uint256","name":"liquidity","type":"uint256"}],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"factory","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"uint256","name":"amountOut","type":"uint256"},{"internalType":"uint256","name":"reserveIn","type":"uint256"},{"internalType":"uint256","name":"reserveOut","type":"uint256"}],"name":"getAmountIn","outputs":[{"internalType":"uint256","name":"amountIn","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"uint256","name":"amountIn","type":"uint256"},{"internalType":"uint256","name":"reserveIn","type":"uint256"},{"internalType":"uint256","name":"reserveOut","type":"uint256"}],"name":"getAmountOut","outputs":[{"internalType":"uint256","name":"amountOut","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"uint256","name":"amountOut","type":"uint256"},{"internalType":"address[]","name":"path","type":"address[]"}],"name":"getAmountsIn","outputs":[{"internalType":"uint256[]","name":"amounts","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amountIn","type":"uint256"},{"internalType":"address[]","name":"path","type":"address[]"}],"name":"getAmountsOut","outputs":[{"internalType":"uint256[]","name":"amounts","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amountA","type":"uint256"},{"internalType":"uint256","name":"reserveA","type":"uint256"},{"internalType":"uint256","name":"reserveB","type":"uint256"}],"name":"quote","outputs":[{"internalType":"uint256","name":"amountB","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"tokenA","type":"address"},{"internalType":"address","name":"tokenB","type":"address"},{"internalType":"uint256","name":"liquidity","type":"uint256"},{"internalType":"uint256","name":"amountAMin","type":"uint256"},{"internalType":"uint256","name":"amountBMin","type":"uint256"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"removeLiquidity","outputs":[{"internalType":"uint256","name":"amountA","type":"uint256"},{"internalType":"uint256","name":"amountB","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"liquidity","type":"uint256"},{"internalType":"uint256","name":"amountTokenMin","type":"uint256"},{"internalType":"uint256","name":"amountETHMin","type":"uint256"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"removeLiquidityETH","outputs":[{"internalType":"uint256","name":"amountToken","type":"uint256"},{"internalType":"uint256","name":"amountETH","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"liquidity","type":"uint256"},{"internalType":"uint256","name":"amountTokenMin","type":"uint256"},{"internalType":"uint256","name":"amountETHMin","type":"uint256"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"removeLiquidityETHSupportingFeeOnTransferTokens","outputs":[{"internalType":"uint256","name":"amountETH","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"liquidity","type":"uint256"},{"internalType":"uint256","name":"amountTokenMin","type":"uint256"},{"internalType":"uint256","name":"amountETHMin","type":"uint256"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"bool","name":"approveMax","type":"bool"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"removeLiquidityETHWithPermit","outputs":[{"internalType":"uint256","name":"amountToken","type":"uint256"},{"internalType":"uint256","name":"amountETH","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"liquidity","type":"uint256"},{"internalType":"uint256","name":"amountTokenMin","type":"uint256"},{"internalType":"uint256","name":"amountETHMin","type":"uint256"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"bool","name":"approveMax","type":"bool"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"removeLiquidityETHWithPermitSupportingFeeOnTransferTokens","outputs":[{"internalType":"uint256","name":"amountETH","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"tokenA","type":"address"},{"internalType":"address","name":"tokenB","type":"address"},{"internalType":"uint256","name":"liquidity","type":"uint256"},{"internalType":"uint256","name":"amountAMin","type":"uint256"},{"internalType":"uint256","name":"amountBMin","type":"uint256"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"bool","name":"approveMax","type":"bool"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"removeLiquidityWithPermit","outputs":[{"internalType":"uint256","name":"amountA","type":"uint256"},{"internalType":"uint256","name":"amountB","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amountOut","type":"uint256"},{"internalType":"address[]","name":"path","type":"address[]"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"swapETHForExactTokens","outputs":[{"internalType":"uint256[]","name":"amounts","type":"uint256[]"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amountOutMin","type":"uint256"},{"internalType":"address[]","name":"path","type":"address[]"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"swapExactETHForTokens","outputs":[{"internalType":"uint256[]","name":"amounts","type":"uint256[]"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amountOutMin","type":"uint256"},{"internalType":"address[]","name":"path","type":"address[]"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"swapExactETHForTokensSupportingFeeOnTransferTokens","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amountIn","type":"uint256"},{"internalType":"uint256","name":"amountOutMin","type":"uint256"},{"internalType":"address[]","name":"path","type":"address[]"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"swapExactTokensForETH","outputs":[{"internalType":"uint256[]","name":"amounts","type":"uint256[]"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amountIn","type":"uint256"},{"internalType":"uint256","name":"amountOutMin","type":"uint256"},{"internalType":"address[]","name":"path","type":"address[]"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"swapExactTokensForETHSupportingFeeOnTransferTokens","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amountIn","type":"uint256"},{"internalType":"uint256","name":"amountOutMin","type":"uint256"},{"internalType":"address[]","name":"path","type":"address[]"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"swapExactTokensForTokens","outputs":[{"internalType":"uint256[]","name":"amounts","type":"uint256[]"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amountIn","type":"uint256"},{"internalType":"uint256","name":"amountOutMin","type":"uint256"},{"internalType":"address[]","name":"path","type":"address[]"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"swapExactTokensForTokensSupportingFeeOnTransferTokens","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amountOut","type":"uint256"},{"internalType":"uint256","name":"amountInMax","type":"uint256"},{"internalType":"address[]","name":"path","type":"address[]"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"swapTokensForExactETH","outputs":[{"internalType":"uint256[]","name":"amounts","type":"uint256[]"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amountOut","type":"uint256"},{"internalType":"uint256","name":"amountInMax","type":"uint256"},{"internalType":"address[]","name":"path","type":"address[]"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"swapTokensForExactTokens","outputs":[{"internalType":"uint256[]","name":"amounts","type":"uint256[]"}],"stateMutability":"nonpayable","type":"function"}], "UniswapV2FactoryAbi" : [{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"token0","type":"address"},{"indexed":true,"internalType":"address","name":"token1","type":"address"},{"indexed":false,"internalType":"address","name":"pair","type":"address"},{"indexed":false,"internalType":"uint256","name":"","type":"uint256"}],"name":"PairCreated","type":"event"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"allPairs","outputs":[{"internalType":"address","name":"pair","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"allPairsLength","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"tokenA","type":"address"},{"internalType":"address","name":"tokenB","type":"address"}],"name":"createPair","outputs":[{"internalType":"address","name":"pair","type":"address"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"feeTo","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"feeToSetter","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"tokenA","type":"address"},{"internalType":"address","name":"tokenB","type":"address"}],"name":"getPair","outputs":[{"internalType":"address","name":"pair","type":"address"}],"stateMutability":"view","type":"function"}], diff --git a/spa/loader.jsx b/spa/loader.jsx index 31f5952..42d2741 100644 --- a/spa/loader.jsx +++ b/spa/loader.jsx @@ -25,7 +25,7 @@ var Loader = React.createClass({ },*/ render() { return ( - + ); } }); \ No newline at end of file diff --git a/spa/stableCoin/controller.jsx b/spa/stableCoin/controller.jsx index e87772d..df44990 100644 --- a/spa/stableCoin/controller.jsx +++ b/spa/stableCoin/controller.jsx @@ -35,8 +35,8 @@ var StableCoinController = function (view) { index: pairs.length, address: pairAddress, pair: pair, - token0: await window.loadTokenInfos(await window.blockchainCall(pair.methods.token0), window.wethToken.options.address), - token1: await window.loadTokenInfos(await window.blockchainCall(pair.methods.token1), window.wethToken.options.address) + token0: await window.loadTokenInfos(await window.blockchainCall(pair.methods.token0)), + token1: await window.loadTokenInfos(await window.blockchainCall(pair.methods.token1)) }; pairData.name = pairData.token0.symbol + ' / ' + pairData.token1.symbol; pairs.push(pairData); diff --git a/spa/stableCoin/view.jsx b/spa/stableCoin/view.jsx index fe78242..7b8d2e8 100644 --- a/spa/stableCoin/view.jsx +++ b/spa/stableCoin/view.jsx @@ -130,14 +130,14 @@ var StableCoin = React.createClass({ {!this.state || !this.state.selectedPair && } {this.state && this.state.selectedPair &&

- + +
@@ -230,6 +234,15 @@ var StableCoin = React.createClass({
}

This protocol is built using a Responsable DeFi approach. But it's new, so use it at your own risk and remember, in Ethereum transactions are irreversible.

} +
+
+ + {this.state && this.state.grimoire && X} + {(!this.state || !this.state.grimoire) && Grimoire} + +
+ {this.state && this.state.grimoire && Grimoire Tag goes Here} +
); } diff --git a/spa/swapBazar/view.jsx b/spa/swapBazar/view.jsx index 5f3ced9..0ebbb75 100644 --- a/spa/swapBazar/view.jsx +++ b/spa/swapBazar/view.jsx @@ -61,6 +61,10 @@ var SwapBazar = React.createClass({ } }); }, + toggleGrimoire(e) { + e && e.preventDefault && e.preventDefault(true) && e.stopPropagation && e.stopPropagation(true); + this.setState({ grimoire: !(this.state && this.state.grimoire) }); + }, render() { return (
{this.state && this.state.uniswap && this.state.inputToken && this.state.outputToken &&
@@ -84,6 +88,15 @@ var SwapBazar = React.createClass({ Swap Pool
} +
+
+ + {this.state && this.state.grimoire && X} + {(!this.state || !this.state.grimoire) && Grimoire} + +
+ {this.state && this.state.grimoire && Grimoire Tag goes Here} +
); } }); \ No newline at end of file From 4d210addaf0fe8ab054ebeabbc45e1cbcb3e957a Mon Sep 17 00:00:00 2001 From: alet89 Date: Tue, 25 Aug 2020 23:29:26 +0200 Subject: [PATCH 14/76] gelato --- assets/css/style.css | 5 +++-- spa/grimoire/grimBazar.jsx | 33 +++++++++++++++++++++++++++++++++ spa/grimoire/grimCrafting.jsx | 33 +++++++++++++++++++++++++++++++++ spa/grimoire/grimUnifi.jsx | 33 +++++++++++++++++++++++++++++++++ spa/grimoire/grimuSD.jsx | 6 ++++-- spa/grimoire/view.jsx | 13 +++++++++---- 6 files changed, 115 insertions(+), 8 deletions(-) create mode 100644 spa/grimoire/grimBazar.jsx create mode 100644 spa/grimoire/grimCrafting.jsx create mode 100644 spa/grimoire/grimUnifi.jsx diff --git a/assets/css/style.css b/assets/css/style.css index 2380c00..401aa45 100644 --- a/assets/css/style.css +++ b/assets/css/style.css @@ -83,7 +83,7 @@ footer p a, footer h5 a {color: #c7ac97; font-weight: bold;} .grimoireIndex h2 {font-size: 30px; margin-bottom: 20px;} .grimoireIndex a img {width: 30px;height: 30px; margin-right: 6px; vertical-align: middle;} -.StableCoinTitle .StableCoinTitleIntern, .grimoireWelcome .grimoireWelcomeIntern {display: none;} +.StableCoinTitle .StableCoinTitleIntern, .grimoireWelcome .grimoireWelcomeIntern {display: none; position: relative;} .StableCoinTitle h2, .grimoireWelcome h2 {font-size: 25px; margin: 10px 0; vertical-align: middle;text-align: left;} .StableCoinTitle h6, .grimoireWelcome h6 {font-size: 15px; text-align: left; line-height: 1.4; font-weight: normal;} .UniActiveQuantityTier h6, .UniDisactiveQuantityTier h6 {font-size: 12px; margin: 0 0 0 10px;} @@ -179,7 +179,8 @@ footer p a, footer h5 a {color: #c7ac97; font-weight: bold;} .MenuOpen {width: 100%; display: inline-block; text-align: center;} .StableCoinTitle .StableCoinTitleIntern, .grimoireWelcome .grimoireWelcomeIntern, .grimoireBox {width: 590px; padding: 20px; border-radius: 8px; display: inline-block;} .StableCoinTitleIntern article, .grimoireWelcomeIntern article {width: 480px; display: inline-block; vertical-align: middle;} - .StableCoinTitle img, .grimoireWelcome img {width: 80px; height: 80px; margin-right: 10px; vertical-align: middle;} + .StableCoinTitle img, .grimoireWelcome img {width: 80px; height: 80px; margin-right: 10px; vertical-align: middle; z-index: 1; position: relative;} + .grimoireWelcome .GrimImg2 {width: 70px; height: 70px; position: absolute; bottom: 10px; left: 5px; z-index: 2;} footer .welcomeLinks, footer p {width: 500px; padding: 20px;} .grimoireIndex {width: 350px;} diff --git a/spa/grimoire/grimBazar.jsx b/spa/grimoire/grimBazar.jsx new file mode 100644 index 0000000..58f7f12 --- /dev/null +++ b/spa/grimoire/grimBazar.jsx @@ -0,0 +1,33 @@ +var GrimBazar = React.createClass({ + requiredScripts: [ + 'spa/loader.jsx' + ], + + render() { + return ( +
+ +
+
+ +
+

The Grimoire - Bazar

+
Ancient black magic is unleashing the true power of the Unicorn. Programmable Equities, Token Indexes and NFTs (including ERC 1155 NFTs, thanks to ethArt V2) can now be swapped, on the new Bazaar DEX.
+
+
+
+
+
+ +
+
+
+ ); + } +}); \ No newline at end of file diff --git a/spa/grimoire/grimCrafting.jsx b/spa/grimoire/grimCrafting.jsx new file mode 100644 index 0000000..8941cd4 --- /dev/null +++ b/spa/grimoire/grimCrafting.jsx @@ -0,0 +1,33 @@ +var GrimCrafting = React.createClass({ + requiredScripts: [ + 'spa/loader.jsx' + ], + + render() { + return ( +
+
+
+ + +
+

The Grimoire - Crafting and Initial Liquidity Offering

+
Craft makes it possible to provide liquidity that is programmable with advanced rules. Using Unicorn magic, pools can balance tokens diversely with unprecedented security.
+
+
+
+
+
+ +
+
+
+ ); + } +}); \ No newline at end of file diff --git a/spa/grimoire/grimUnifi.jsx b/spa/grimoire/grimUnifi.jsx new file mode 100644 index 0000000..91c0c9e --- /dev/null +++ b/spa/grimoire/grimUnifi.jsx @@ -0,0 +1,33 @@ +var GrimUnifi = React.createClass({ + requiredScripts: [ + 'spa/loader.jsx' + ], + + render() { + return ( +
+ +
+
+ +
+

The Grimoire - UniFi DFO and UniFi Token

+
uSD is a Stable Coin based on Uniswap Liquidity Pools Launch Dapp Minted by the magic rainbow of Uniswap stablecoin pools. Backed by the power of the Unicorn, uSD is the most secure stablecoin ever. The only way it could be destabilized is if the entire stablecoin industry crashed.
+
+
+
+
+
+ +
+
+
+ ); + } +}); \ No newline at end of file diff --git a/spa/grimoire/grimuSD.jsx b/spa/grimoire/grimuSD.jsx index b1301bb..3736434 100644 --- a/spa/grimoire/grimuSD.jsx +++ b/spa/grimoire/grimuSD.jsx @@ -21,9 +21,11 @@ var GrimuSD = React.createClass({ diff --git a/spa/grimoire/view.jsx b/spa/grimoire/view.jsx index 33c117c..17886ae 100644 --- a/spa/grimoire/view.jsx +++ b/spa/grimoire/view.jsx @@ -1,7 +1,10 @@ var Grimoire = React.createClass({ requiredScripts: [ 'spa/loader.jsx', - 'spa/grimoire/grimuSD.jsx' + 'spa/grimoire/grimuSD.jsx', + 'spa/grimoire/grimCrafting.jsx', + 'spa/grimoire/grimBazar.jsx', + 'spa/grimoire/grimUnifi.jsx' ], render() { @@ -21,9 +24,8 @@ var Grimoire = React.createClass({
@@ -31,6 +33,9 @@ var Grimoire = React.createClass({
+ + + ); } From 028e61ba8e1cb36e27e47fa1e8ecddb30e4c2641 Mon Sep 17 00:00:00 2001 From: Marco Vasapollo Date: Tue, 25 Aug 2020 23:34:24 +0200 Subject: [PATCH 15/76] Grimoire --- spa/stableCoin/view.jsx | 5 +++-- spa/swapBazar/view.jsx | 5 +++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/spa/stableCoin/view.jsx b/spa/stableCoin/view.jsx index 9d0725d..fbf2dbc 100644 --- a/spa/stableCoin/view.jsx +++ b/spa/stableCoin/view.jsx @@ -1,7 +1,8 @@ var StableCoin = React.createClass({ requiredScripts: [ 'spa/banner.jsx', - 'spa/loader.jsx' + 'spa/loader.jsx', + 'spa/grimoire/grimuSD.jsx' ], requiredModules: [ 'spa/dappMenu' @@ -241,7 +242,7 @@ var StableCoin = React.createClass({ {(!this.state || !this.state.grimoire) && Grimoire} - {this.state && this.state.grimoire && Grimoire Tag goes Here} + {this.state && this.state.grimoire && } ); diff --git a/spa/swapBazar/view.jsx b/spa/swapBazar/view.jsx index 0ebbb75..299334d 100644 --- a/spa/swapBazar/view.jsx +++ b/spa/swapBazar/view.jsx @@ -1,7 +1,8 @@ var SwapBazar = React.createClass({ requiredScripts: [ 'spa/loader.jsx', - 'spa/swapBazar/uniswapTokenPicker.jsx' + 'spa/swapBazar/uniswapTokenPicker.jsx', + 'spa/grimoire/grimBazar.jsx' ], getDefaultSubscriptions() { return { @@ -95,7 +96,7 @@ var SwapBazar = React.createClass({ {(!this.state || !this.state.grimoire) && Grimoire} - {this.state && this.state.grimoire && Grimoire Tag goes Here} + {this.state && this.state.grimoire && } ); } From 95f98d681df3b641764b008105175519dc570f4c Mon Sep 17 00:00:00 2001 From: alet89 Date: Wed, 26 Aug 2020 11:55:52 +0200 Subject: [PATCH 16/76] uSD explained --- assets/css/style.css | 7 ++++ spa/grimoire/grimBazar.jsx | 2 +- spa/grimoire/grimCrafting.jsx | 2 +- spa/grimoire/grimUnifi.jsx | 2 +- spa/grimoire/grimuSD.jsx | 61 +++++++++++++++++++++++++++++++---- spa/grimoire/view.jsx | 6 ++-- 6 files changed, 67 insertions(+), 13 deletions(-) diff --git a/assets/css/style.css b/assets/css/style.css index 401aa45..6f29f35 100644 --- a/assets/css/style.css +++ b/assets/css/style.css @@ -82,6 +82,13 @@ footer p a, footer h5 a {color: #c7ac97; font-weight: bold;} .grimoireIndex a {width: 100%; padding: 20px 0; display: inline-block; font-size: 18px; vertical-align: middle;} .grimoireIndex h2 {font-size: 30px; margin-bottom: 20px;} .grimoireIndex a img {width: 30px;height: 30px; margin-right: 6px; vertical-align: middle;} +.grimoireArticle {width: 90%; padding: 4%; text-align: left;} +.grimoireArticle h2 {font-size: 30px; margin-bottom: 25px;} +.grimoireArticle p {font-size: 15px; line-height: 1.4; width: 100%; display: inline-block; margin-bottom: 15px;} +.grimoireArticle h6 {font-size: 19px; width: 100%; display: inline-block; margin-bottom: 20px; font-weight: normal;margin-top: 10px;} +.grimoireArticle h4 {font-size: 21px; width: 100%; display: inline-block; margin-bottom: 15px; font-weight: bold;} +.grimoireArticle ol {width: 100%; display: inline-block; text-align: right;} +.grimoireArticle li {width: 95%; text-align: left; display: inline-block; font-size: 15px;line-height: 1.3; margin: 10px auto;} .StableCoinTitle .StableCoinTitleIntern, .grimoireWelcome .grimoireWelcomeIntern {display: none; position: relative;} .StableCoinTitle h2, .grimoireWelcome h2 {font-size: 25px; margin: 10px 0; vertical-align: middle;text-align: left;} diff --git a/spa/grimoire/grimBazar.jsx b/spa/grimoire/grimBazar.jsx index 58f7f12..5b4affc 100644 --- a/spa/grimoire/grimBazar.jsx +++ b/spa/grimoire/grimBazar.jsx @@ -10,7 +10,7 @@ var GrimBazar = React.createClass({
-
+

The Grimoire - Bazar

Ancient black magic is unleashing the true power of the Unicorn. Programmable Equities, Token Indexes and NFTs (including ERC 1155 NFTs, thanks to ethArt V2) can now be swapped, on the new Bazaar DEX.
diff --git a/spa/grimoire/grimCrafting.jsx b/spa/grimoire/grimCrafting.jsx index 8941cd4..df1217c 100644 --- a/spa/grimoire/grimCrafting.jsx +++ b/spa/grimoire/grimCrafting.jsx @@ -10,7 +10,7 @@ var GrimCrafting = React.createClass({
-
+

The Grimoire - Crafting and Initial Liquidity Offering

Craft makes it possible to provide liquidity that is programmable with advanced rules. Using Unicorn magic, pools can balance tokens diversely with unprecedented security.
diff --git a/spa/grimoire/grimUnifi.jsx b/spa/grimoire/grimUnifi.jsx index 91c0c9e..5df05f7 100644 --- a/spa/grimoire/grimUnifi.jsx +++ b/spa/grimoire/grimUnifi.jsx @@ -10,7 +10,7 @@ var GrimUnifi = React.createClass({
-
+

The Grimoire - UniFi DFO and UniFi Token

uSD is a Stable Coin based on Uniswap Liquidity Pools Launch Dapp Minted by the magic rainbow of Uniswap stablecoin pools. Backed by the power of the Unicorn, uSD is the most secure stablecoin ever. The only way it could be destabilized is if the entire stablecoin industry crashed.
diff --git a/spa/grimoire/grimuSD.jsx b/spa/grimoire/grimuSD.jsx index 3736434..61a8c52 100644 --- a/spa/grimoire/grimuSD.jsx +++ b/spa/grimoire/grimuSD.jsx @@ -10,7 +10,7 @@ var GrimuSD = React.createClass({
-
+

The Grimoire - Uniswap State Dollar

uSD is a Stable Coin based on Uniswap Liquidity Pools Launch Dapp Minted by the magic rainbow of Uniswap stablecoin pools. Backed by the power of the Unicorn, uSD is the most secure stablecoin ever. The only way it could be destabilized is if the entire stablecoin industry crashed.
@@ -20,13 +20,60 @@ var GrimuSD = React.createClass({
+
+

Basics

+

The aim of the Uniswap State Dollar (uSD) protocol is to build the most secure and resilient stablecoin on Ethereum—ever. Independent from any off-chain issuer, it is fortified against the risks inherent to all other stablecoins, and free of the anxiety that pervades the industry.

+

uSD achieves stability by collateralizing stablecoins, and, when necessary, rebalancing itself in relation to them, so that if any lose value or fail, it is still secured by the others. The only way uSD can be destabilized is if the entire stablecoin industry collapses.

+
uSD is backed by Uniswap’s (whitelisted) stablecoin liquidity pools.
+
Anyone can mint it by adding these stablecoins to those pools.
+

Example:

+

Mint 2x uSD by adding 1x Stablecoin A and 1x Stablecoin B.

+
And by burning uSD, anyone can receive these stablecoins from those pools.
+

Example:

+

Burn 2x uSD and receive 1x Stablecoin A and 1x Stablecoin C.

+
+
+

Rebalancing

+
Sometimes, collateralization is not enough, and uSD must rebalance in one of two ways.
+

DFO Debit

+

When a stablecoin loses value, the Uniswap Tier pools rebalance to an uneven disparity (≠ 50/50). If the stablecoin totally fails, the other stablecoins effectively pump in correlation.

+

DFO Debit resolves this issue on-chain by rebalancing uSD, creating debt which the UniFi DFO then pays off by minting UniFi. Let’s look at how this plays out, step by step:

+
    +
  1. Holders of the $UniFi programmable equity vote to remove the tiers that contain the failed stablecoin from the whitelist. In doing so, the uSD supply becomes greater than the supply of the collateralized pooled stablecoins.
  2. +
  3. To restore the 1:1 equilibrium, anyone holding uSD can burn it to receive new UniFi, minted at a 50% discount of the uSD/UniFi Uniswap pool mid-price ratio.
  4. +
+
The goal of UniFi holders, which aligns with their self-interest, is to ensure uSD’s security. Thus there is an economic disincentive to whitelist stablecoins that don’t provide security.
+

DFO Credit

+

As has already been established, uSD is backed by Uniswap pool liquidity. There is an issue here, given that Uniswap pools earn 0.3% of trading fees, which can destabilize uSD by creating an excess of collateralized stablecoins in the pools.

+

DFO Credit, the second rebalancing function of the UniFi DFO, resolves this by removing the excess from the pools and sending it in the DFO wallet managed by UniFi holders.This is a long term economic incentive for the UniFi DFO to grow and invest credit in R&D.

+
+
+

Security and Emergency Strategies

+

The UniFi has a number of measures in place to ensure its security.

+

1 - The DFO can’t vote to manage the locked pool collateral of uSD, which is stored in an external smart contract. This precludes voter fraud by bad actors.

+

2 - In the case of any bug or update, UniFi holders can vote to pause the uSD smart contract. This will prevent it from minting new uSD or rebalancing uSD, but holders will still be able to redeem uSD for the pooled stable coins, and thereby revoke the collateral.

+

3 - Even if the protocol fails, or even if the UniFi DFO votes to update uSD to an undesirable new version, uSD holders will still be able to interact with the old smart contract (until all collateral is revoked) as well as the new one.

+
+
+

Resilience, Decentralization and independency

+

uSD is the most resilient stablecoin in the industry. It frees holders from dependence on any centralized manipulation by states and stablecoin issuers, by taking advantage of Uniswap, an important security layer with a decentralized core.

+

uSD is backed by a DFO. There is no centralized entity behind it, only UniFi holders on the Ethereum network. They have 100% control of the code and Credit/Debit of the protocol. Nobody can stop or censor the UniFi-uSD protocol; for the first time, the Ethereum network doesn’t have to choose between stability and independence in a stablecoin; it can have both.

+

uSD resolves all of the risks associated with trusting the big stablecoin companies, such as MakerDAO, Coinbase, Tether etc.

+
+
+

APIs and Documentation

+

To build on top of uSD and to interact with the dapp, you can find all of the documentation and APIs here:

+
+
+

Responsible DeFi Architecture

+
diff --git a/spa/grimoire/view.jsx b/spa/grimoire/view.jsx index 17886ae..fe0e8e8 100644 --- a/spa/grimoire/view.jsx +++ b/spa/grimoire/view.jsx @@ -25,9 +25,9 @@ var Grimoire = React.createClass({
From 4cf70f977078c73e0b62c20aa6e603dfcfda818c Mon Sep 17 00:00:00 2001 From: alet89 Date: Wed, 26 Aug 2020 13:07:36 +0200 Subject: [PATCH 17/76] Boomer --- assets/css/style.css | 40 +++++++++++++++++++++++++++++++++------- index.html | 2 +- 2 files changed, 34 insertions(+), 8 deletions(-) diff --git a/assets/css/style.css b/assets/css/style.css index 6f29f35..4a8c1ec 100644 --- a/assets/css/style.css +++ b/assets/css/style.css @@ -1,6 +1,6 @@ html {margin: 0; background-color: #2b2622;} h1,h4,h3, h5,h6,h2 {margin-block-end: 0;margin-block-start: 0;} -body {width: 100%; position: relative; margin: 0; font-family: "Myriad Pro";} +body {width: 100%; position: relative; margin: 0;} ol,ul, li {margin-block-start: 0; margin-block-end: 0; list-style-type: none; padding-inline-start:0;} p {display: inline-block;margin-block-start: 0px;margin-block-end: 0px;margin-inline-start: 0px;margin-inline-end: 0px;} h1 {font-size: 30px;} @@ -137,12 +137,36 @@ footer p a, footer h5 a {color: #c7ac97; font-weight: bold;} .UniTierQuantity label input, .RebalanceEmergency label input {width: 130px; display: inline-block; height: 30px;} -.Boomer .UniBox {background: rgb(33, 36, 41); box-shadow: rgba(0, 0, 0, 0.01) 0px 0px 1px, rgba(0, 0, 0, 0.04) 0px 4px 8px, rgba(0, 0, 0, 0.04) 0px 16px 24px, rgba(0, 0, 0, 0.01) 0px 24px 32px; border-radius: 30px; color: #f1f1f1;} -.RPG .UniBox, .grimoireBox {position: initial;background: rgb(33, 36, 41); border-radius: 20px; color: rgb(195, 197, 203);box-shadow: rgba(0, 0, 0, 0.01) 0px 0px 1px, rgba(0, 0, 0, 0.04) 0px 4px 8px, rgba(0, 0, 0, 0.04) 0px 16px 24px, rgba(0, 0, 0, 0.01) 0px 24px 32px;width: 100%;} +.Boomer .UniBox, .Boomer .grimoireBox {background: rgb(255, 255, 255); box-shadow: rgba(0, 0, 0, 0.01) 0px 0px 1px, rgba(0, 0, 0, 0.04) 0px 4px 8px, rgba(0, 0, 0, 0.04) 0px 16px 24px, rgba(0, 0, 0, 0.01) 0px 24px 32px; border-radius: 30px; color: #000000;} +.Boomer .UniSideBox {border-radius: 20px; color: #000000; width: 100%; background-color: #bab9b9;box-shadow: rgba(0, 0, 0, 0.01) 0px 0px 1px, rgba(0, 0, 0, 0.04) 0px 4px 8px, rgba(0, 0, 0, 0.04) 0px 16px 24px, rgba(0, 0, 0, 0.01) 0px 24px 32px;} +.Boomer body {background: linear-gradient(29deg, rgba(255,255,255,1) 0%, rgba(228,228,228,1) 66%);font-family: "Inter var", sans-serif;} +.Boomer .UniTitle select, .Boomer .UniActiveQuantityTier input, .Boomer .UniDisactiveQuantityTier input, .Boomer .RebalanceEmergency label input {background-color: #e7e7e7; color: #000000; border: 5px solid #e7e7e7; border-radius: 5px;} +.Boomer .UniTitle {color: #000000;} +.Boomer .menuOpener, .Boomer .connectOpener {background-color: #bab9b9; color: #000000;box-shadow: rgba(0, 0, 0, 0.01) 0px 0px 1px, rgba(0, 0, 0, 0.04) 0px 4px 8px, rgba(0, 0, 0, 0.04) 0px 16px 24px, rgba(0, 0, 0, 0.01) 0px 24px 32px;} +.Boomer .unifiDapp .MenuOpen .coverMenu {background-color: #bab9b9; border-color: #bab9b9;box-shadow: rgba(0, 0, 0, 0.01) 0px 0px 1px, rgba(0, 0, 0, 0.04) 0px 4px 8px, rgba(0, 0, 0, 0.04) 0px 16px 24px, rgba(0, 0, 0, 0.01) 0px 24px 32px;} +.Boomer .StableCoinTitleIntern, .Boomer .grimoireWelcomeIntern {background-color: #bab9b9;box-shadow: rgba(0, 0, 0, 0.01) 0px 0px 1px, rgba(0, 0, 0, 0.04) 0px 4px 8px, rgba(0, 0, 0, 0.04) 0px 16px 24px, rgba(0, 0, 0, 0.01) 0px 24px 32px;} +.Boomer .StableCoinTitle h2, .Boomer .grimoireWelcome h2 {color: #000000;} +.Boomer .StableCoinTitle h6, .Boomer .grimoireWelcome h6 {color: #000000;} +.Boomer .StableCoinTitle h6 a, .Boomer .grimoireWelcome h6 a {color: #000000;} +.Boomer .UniSideBox .SideStandard h6 a {color: #000000;} +.Boomer .UniSideBox .SideStableList li span {color: #000000;} +.Boomer .UniSideBox .SideHealth aside {background-color: #128b03; border:none;} +.Boomer .loaderRegular {background-color: #e3d2c2;box-shadow: rgba(0, 0, 0, 0.01) 0px 0px 1px, rgba(0, 0, 0, 0.04) 0px 4px 8px, rgba(0, 0, 0, 0.04) 0px 16px 24px, rgba(0, 0, 0, 0.01) 0px 24px 32px;} +.Boomer .Disclamerone a {color: #000000; text-decoration: underline;} +.Boomer .UniActiveQuantityTier h6, .Boomer .UniDisactiveQuantityTier h6 {color: #000000;} +.Boomer .UniActiveQuantityTier h6 a, .Boomer .UniDisactiveQuantityTier h6 a {background-color: #000000; color: #ffffff; border-radius: 5px; margin-right: 5px;} +.Boomer .coverConnectMenu .ethereumWalletProvider {background-color: #bab9b9; border-color: #bab9b9;box-shadow: rgba(0, 0, 0, 0.01) 0px 0px 1px, rgba(0, 0, 0, 0.04) 0px 4px 8px, rgba(0, 0, 0, 0.04) 0px 16px 24px, rgba(0, 0, 0, 0.01) 0px 24px 32px; color: #000000;} +.Boomer .ethereumWalletProvider a {color: #000000;} +.Boomer .grimoireIndex h2 {color: #000000;} +.Boomer .grimoireIndex a {color: #000000;} +.Boomer .coverMenu li a span {color: #000000;} + + +.RPG .UniBox, .RPG .grimoireBox {position: initial;background: rgb(33, 36, 41); border-radius: 20px; color: rgb(195, 197, 203);box-shadow: rgba(0, 0, 0, 0.01) 0px 0px 1px, rgba(0, 0, 0, 0.04) 0px 4px 8px, rgba(0, 0, 0, 0.04) 0px 16px 24px, rgba(0, 0, 0, 0.01) 0px 24px 32px;width: 100%;} .RPG .UniSideBox {border-radius: 20px; color: #bab9b9; width: 100%; background-color: #2b2622;box-shadow: rgba(0, 0, 0, 0.01) 0px 0px 1px, rgba(0, 0, 0, 0.04) 0px 4px 8px, rgba(0, 0, 0, 0.04) 0px 16px 24px, rgba(0, 0, 0, 0.01) 0px 24px 32px;} -.RPG body {background: linear-gradient(29deg, rgba(80,80,80,1) 0%, rgba(46,46,46,1) 66%);} -.RPG .UniTitle select, .RPG .UniActiveQuantityTier input, .RPG .UniDisactiveQuantityTier input, .RebalanceEmergency label input {background-color: #000000; color: #f1f1f1; border: 5px solid #000000; border-radius: 5px;} -.RPG .UniTitle {color: rgb(195, 197, 203);} +.RPG body {background: linear-gradient(29deg, rgba(80,80,80,1) 0%, rgba(46,46,46,1) 66%);font-family: "Myriad Pro";} +.RPG .UniTitle select, .RPG .UniActiveQuantityTier input, .RPG .UniDisactiveQuantityTier input, .RPG .RebalanceEmergency label input {background-color: #000000; color: #f1f1f1; border: 5px solid #000000; border-radius: 5px;} +.RPG .UniTitle {color: #000000;} .RPG .menuOpener, .RPG .connectOpener {background-color: #c7ac97; color: #444444;box-shadow: rgba(0, 0, 0, 0.01) 0px 0px 1px, rgba(0, 0, 0, 0.04) 0px 4px 8px, rgba(0, 0, 0, 0.04) 0px 16px 24px, rgba(0, 0, 0, 0.01) 0px 24px 32px;} .RPG .unifiDapp .MenuOpen .coverMenu {background-color: #2b2622; border-color: #2b2622;box-shadow: rgba(0, 0, 0, 0.01) 0px 0px 1px, rgba(0, 0, 0, 0.04) 0px 4px 8px, rgba(0, 0, 0, 0.04) 0px 16px 24px, rgba(0, 0, 0, 0.01) 0px 24px 32px;} .RPG .StableCoinTitleIntern, .RPG .grimoireWelcomeIntern {background-color: #2b2622;box-shadow: rgba(0, 0, 0, 0.01) 0px 0px 1px, rgba(0, 0, 0, 0.04) 0px 4px 8px, rgba(0, 0, 0, 0.04) 0px 16px 24px, rgba(0, 0, 0, 0.01) 0px 24px 32px;} @@ -160,6 +184,8 @@ footer p a, footer h5 a {color: #c7ac97; font-weight: bold;} .RPG .ethereumWalletProvider a {color: #bab9b9;} .RPG .grimoireIndex h2 {text-shadow:2px 2px 2px #5d5e60; color: #bab9b9;} .RPG .grimoireIndex a {text-shadow:2px 2px 2px #5d5e60; color: #bab9b9;} +.RPG .coverMenu li a span {text-shadow: 2px 2px 2px #5d5e60;color: #bab9b9;} + @media only screen and (min-width: 640px) { @@ -178,7 +204,7 @@ footer p a, footer h5 a {color: #c7ac97; font-weight: bold;} .coverMenu li {width: 200; display: inline-block; position: relative; margin-left: 25px;} .coverMenu li a {width: 100%; display: inline-block; padding: 5px 5px; text-decoration: none;} .coverMenu li a img {width: 35px; height: 35px; margin: 0 7px; vertical-align: middle;} - .coverMenu li a span {font-size: 16px; font-weight: bolder; text-shadow:2px 2px 2px #5d5e60; color: #bab9b9; vertical-align: middle;} + .coverMenu li a span {font-size: 16px; font-weight: bolder; vertical-align: middle;} .coverMenu li .menuArrow {display: none;} .coverMenu li:hover .menuArrow {width: 20px; height: 20px; position: absolute; left: -15px; top: 15px; display: block;} .coverMenu .menuArrow img {width: 20px; height: 20px;} diff --git a/index.html b/index.html index 55bf773..0bb3f9d 100644 --- a/index.html +++ b/index.html @@ -1,4 +1,4 @@ - + From 74d286ec04e99546a31af3257e660363d70570d2 Mon Sep 17 00:00:00 2001 From: alet89 Date: Wed, 26 Aug 2020 13:32:22 +0200 Subject: [PATCH 18/76] Grim Menu --- assets/css/style.css | 12 ++++++++++-- index.html | 2 +- spa/grimoire/grimBazar.jsx | 3 +-- spa/grimoire/grimUnifi.jsx | 3 +-- spa/grimoire/grimuSD.jsx | 3 +-- spa/stableCoin/view.jsx | 18 +++++++++--------- 6 files changed, 23 insertions(+), 18 deletions(-) diff --git a/assets/css/style.css b/assets/css/style.css index 4a8c1ec..8f28525 100644 --- a/assets/css/style.css +++ b/assets/css/style.css @@ -136,10 +136,15 @@ footer p a, footer h5 a {color: #c7ac97; font-weight: bold;} .UniTierQuantity label img {width: 20px; height: 20px; margin: 0 5px; vertical-align: middle; display: inline-block;} .UniTierQuantity label input, .RebalanceEmergency label input {width: 130px; display: inline-block; height: 30px;} +.CallToGrim {position: fixed; top: 10px; left: 190px; width: 35px; height: 35px;} +.CallToGrim a {width: 35px; height: 35px; display: inline-block; text-align: center; border-radius: 10px;} +.CallToGrim a img {width: 30px; height: 30px; display: inline-block; vertical-align: center;} -.Boomer .UniBox, .Boomer .grimoireBox {background: rgb(255, 255, 255); box-shadow: rgba(0, 0, 0, 0.01) 0px 0px 1px, rgba(0, 0, 0, 0.04) 0px 4px 8px, rgba(0, 0, 0, 0.04) 0px 16px 24px, rgba(0, 0, 0, 0.01) 0px 24px 32px; border-radius: 30px; color: #000000;} + +.Boomer .UniBox, .Boomer .grimoireBox {position: initial;background: rgb(255, 255, 255); box-shadow: rgba(0, 0, 0, 0.01) 0px 0px 1px, rgba(0, 0, 0, 0.04) 0px 4px 8px, rgba(0, 0, 0, 0.04) 0px 16px 24px, rgba(0, 0, 0, 0.01) 0px 24px 32px; border-radius: 30px; color: #000000;} .Boomer .UniSideBox {border-radius: 20px; color: #000000; width: 100%; background-color: #bab9b9;box-shadow: rgba(0, 0, 0, 0.01) 0px 0px 1px, rgba(0, 0, 0, 0.04) 0px 4px 8px, rgba(0, 0, 0, 0.04) 0px 16px 24px, rgba(0, 0, 0, 0.01) 0px 24px 32px;} .Boomer body {background: linear-gradient(29deg, rgba(255,255,255,1) 0%, rgba(228,228,228,1) 66%);font-family: "Inter var", sans-serif;} +.Boomer body > .unifiAll > .explainer {background: linear-gradient(29deg, rgba(80,80,80,1) 0%, rgba(46,46,46,1) 66%);font-family: "Myriad Pro";} .Boomer .UniTitle select, .Boomer .UniActiveQuantityTier input, .Boomer .UniDisactiveQuantityTier input, .Boomer .RebalanceEmergency label input {background-color: #e7e7e7; color: #000000; border: 5px solid #e7e7e7; border-radius: 5px;} .Boomer .UniTitle {color: #000000;} .Boomer .menuOpener, .Boomer .connectOpener {background-color: #bab9b9; color: #000000;box-shadow: rgba(0, 0, 0, 0.01) 0px 0px 1px, rgba(0, 0, 0, 0.04) 0px 4px 8px, rgba(0, 0, 0, 0.04) 0px 16px 24px, rgba(0, 0, 0, 0.01) 0px 24px 32px;} @@ -160,9 +165,11 @@ footer p a, footer h5 a {color: #c7ac97; font-weight: bold;} .Boomer .grimoireIndex h2 {color: #000000;} .Boomer .grimoireIndex a {color: #000000;} .Boomer .coverMenu li a span {color: #000000;} +.Boomer body > .unifiAll > .explainer .coverMenu li a span {text-shadow: 2px 2px 2px #5d5e60;color: #bab9b9;} +.Boomer .CallToGrim a {background-color: #bab9b9;box-shadow: rgba(0, 0, 0, 0.01) 0px 0px 1px, rgba(0, 0, 0, 0.04) 0px 4px 8px, rgba(0, 0, 0, 0.04) 0px 16px 24px, rgba(0, 0, 0, 0.01) 0px 24px 32px;} -.RPG .UniBox, .RPG .grimoireBox {position: initial;background: rgb(33, 36, 41); border-radius: 20px; color: rgb(195, 197, 203);box-shadow: rgba(0, 0, 0, 0.01) 0px 0px 1px, rgba(0, 0, 0, 0.04) 0px 4px 8px, rgba(0, 0, 0, 0.04) 0px 16px 24px, rgba(0, 0, 0, 0.01) 0px 24px 32px;width: 100%;} +.RPG .UniBox, .RPG .grimoireBox {position: initial;background: rgb(33, 36, 41); border-radius: 20px; color: rgb(195, 197, 203);box-shadow: rgba(0, 0, 0, 0.01) 0px 0px 1px, rgba(0, 0, 0, 0.04) 0px 4px 8px, rgba(0, 0, 0, 0.04) 0px 16px 24px, rgba(0, 0, 0, 0.01) 0px 24px 32px;} .RPG .UniSideBox {border-radius: 20px; color: #bab9b9; width: 100%; background-color: #2b2622;box-shadow: rgba(0, 0, 0, 0.01) 0px 0px 1px, rgba(0, 0, 0, 0.04) 0px 4px 8px, rgba(0, 0, 0, 0.04) 0px 16px 24px, rgba(0, 0, 0, 0.01) 0px 24px 32px;} .RPG body {background: linear-gradient(29deg, rgba(80,80,80,1) 0%, rgba(46,46,46,1) 66%);font-family: "Myriad Pro";} .RPG .UniTitle select, .RPG .UniActiveQuantityTier input, .RPG .UniDisactiveQuantityTier input, .RPG .RebalanceEmergency label input {background-color: #000000; color: #f1f1f1; border: 5px solid #000000; border-radius: 5px;} @@ -185,6 +192,7 @@ footer p a, footer h5 a {color: #c7ac97; font-weight: bold;} .RPG .grimoireIndex h2 {text-shadow:2px 2px 2px #5d5e60; color: #bab9b9;} .RPG .grimoireIndex a {text-shadow:2px 2px 2px #5d5e60; color: #bab9b9;} .RPG .coverMenu li a span {text-shadow: 2px 2px 2px #5d5e60;color: #bab9b9;} +.RPG .CallToGrim a {background-color: #c7ac97;box-shadow: rgba(0, 0, 0, 0.01) 0px 0px 1px, rgba(0, 0, 0, 0.04) 0px 4px 8px, rgba(0, 0, 0, 0.04) 0px 16px 24px, rgba(0, 0, 0, 0.01) 0px 24px 32px;} diff --git a/index.html b/index.html index 0bb3f9d..f136d8d 100644 --- a/index.html +++ b/index.html @@ -1,4 +1,4 @@ - + diff --git a/spa/grimoire/grimBazar.jsx b/spa/grimoire/grimBazar.jsx index 5b4affc..f443129 100644 --- a/spa/grimoire/grimBazar.jsx +++ b/spa/grimoire/grimBazar.jsx @@ -5,8 +5,7 @@ var GrimBazar = React.createClass({ render() { return ( -
- +
diff --git a/spa/grimoire/grimUnifi.jsx b/spa/grimoire/grimUnifi.jsx index 5df05f7..43e7381 100644 --- a/spa/grimoire/grimUnifi.jsx +++ b/spa/grimoire/grimUnifi.jsx @@ -5,8 +5,7 @@ var GrimUnifi = React.createClass({ render() { return ( -
- +
diff --git a/spa/grimoire/grimuSD.jsx b/spa/grimoire/grimuSD.jsx index 61a8c52..0f3485e 100644 --- a/spa/grimoire/grimuSD.jsx +++ b/spa/grimoire/grimuSD.jsx @@ -5,8 +5,7 @@ var GrimuSD = React.createClass({ render() { return ( -
- +
diff --git a/spa/stableCoin/view.jsx b/spa/stableCoin/view.jsx index fbf2dbc..08242d7 100644 --- a/spa/stableCoin/view.jsx +++ b/spa/stableCoin/view.jsx @@ -123,6 +123,14 @@ var StableCoin = React.createClass({ return (
+
+
+ + {this.state && this.state.grimoire && } + {(!this.state || !this.state.grimoire) && } + +
+
@@ -235,15 +243,7 @@ var StableCoin = React.createClass({
}

This protocol is built using a Responsable DeFi approach. But it's new, so use it at your own risk and remember, in Ethereum transactions are irreversible.

} -
-
- - {this.state && this.state.grimoire && X} - {(!this.state || !this.state.grimoire) && Grimoire} - -
- {this.state && this.state.grimoire && } -
+ {this.state && this.state.grimoire && }
); } From 19408996578e8f4dcc9530df073e28eaf4151440 Mon Sep 17 00:00:00 2001 From: Marco Vasapollo Date: Wed, 26 Aug 2020 13:27:47 +0200 Subject: [PATCH 19/76] Little glitches correction --- assets/scripts/script.js | 2 +- spa/dappMenu/view.jsx | 2 +- spa/stableCoin/view.jsx | 4 ++-- spa/swapBazar/uniswapTokenPicker.jsx | 13 +++++++++++-- spa/swapBazar/view.jsx | 20 ++------------------ 5 files changed, 17 insertions(+), 24 deletions(-) diff --git a/assets/scripts/script.js b/assets/scripts/script.js index 5be0144..8aa4796 100644 --- a/assets/scripts/script.js +++ b/assets/scripts/script.js @@ -133,7 +133,7 @@ window.loadEthereumStuff = async function loadEthereumStuff() { window.uniswapV2Router = window.newContract(window.context.UniswapV2RouterAbi, window.context.uniswapV2RouterAddress); window.wethToken = window.newContract(window.context.votingTokenAbi, window.wethAddress = window.web3.utils.toChecksumAddress(await window.blockchainCall(window.uniswapV2Router.methods.WETH))); window.uniswapV2Factory = window.newContract(window.context.UniswapV2FactoryAbi, window.context.uniswapV2FactoryAddress); - window.stableCoin = await window.loadTokenInfos(stableCoin.options.address, window.context.StableCoinAbi); + window.stableCoin = await window.loadTokenInfos(window.stableCoin.options.address, window.context.StableCoinAbi); window.votingToken = await window.loadTokenInfos((await (window.dfo = await window.dfo).votingToken).options.address); }; diff --git a/spa/dappMenu/view.jsx b/spa/dappMenu/view.jsx index c1475a3..e5e9cc7 100644 --- a/spa/dappMenu/view.jsx +++ b/spa/dappMenu/view.jsx @@ -60,7 +60,7 @@ var DappMenu = React.createClass({ state[type] = !(_this.state && _this.state[type]); _this[type] && delete _this[type].onblur; _this.setState(state, function() { - _this.state[type] && _this[type] && !_this[type].onblur && (_this[type].onblur = function(e) { + _this.state[type] && _this[type] && (_this[type].onblur = _this[type].onblur || function(e) { e && e.preventDefault && e.preventDefault(true) && e.stopPropagation && e.stopPropagation(true); e.relatedTarget && e.relatedTarget !== oldTarget && e.relatedTarget.click(); toggleWork(type); diff --git a/spa/stableCoin/view.jsx b/spa/stableCoin/view.jsx index 08242d7..68fe00c 100644 --- a/spa/stableCoin/view.jsx +++ b/spa/stableCoin/view.jsx @@ -210,7 +210,7 @@ var StableCoin = React.createClass({
} - {window.walletAddress && this.state && this.state.pairs && this.state.totalCoins && this.state.differences && (this.state.differences[0] !== '0' || this.state.differences[1] !== '0') &&
+ {window.walletAddress && this.state && this.state.pairs && this.state.totalCoins && this.state.differences && (parseInt(this.state.totalCoins.regularPercentage) > 103 || parseInt(this.state.totalCoins.regularPercentage) < 97) &&

Rebalance

{parseInt(this.state.totalCoins.regularPercentage) > 103 &&
}
}
} -

This protocol is built using a Responsable DeFi approach. But it's new, so use it at your own risk and remember, in Ethereum transactions are irreversible.

+

This protocol is built using a Responsible DeFi approach. But it's new, so use it at your own risk and remember, in Ethereum transactions are irreversible.

} {this.state && this.state.grimoire && }
diff --git a/spa/swapBazar/uniswapTokenPicker.jsx b/spa/swapBazar/uniswapTokenPicker.jsx index 89ec5d3..23af2ef 100644 --- a/spa/swapBazar/uniswapTokenPicker.jsx +++ b/spa/swapBazar/uniswapTokenPicker.jsx @@ -13,7 +13,16 @@ var UniswapTokenPicker = React.createClass({ }, open(e) { e && e.preventDefault && e.preventDefault(true) && e.stopPropagation && e.stopPropagation(true); - this.setState({ opened: true }); + var _this = this; + var oldTarget = e.currentTarget; + this.setState({ opened: true }, function() { + _this.opened && (_this.opened.onblur = _this.opened.onblur || function onblur(e) { + e && e.preventDefault && e.preventDefault(true) && e.stopPropagation && e.stopPropagation(true); + e.relatedTarget && e.relatedTarget !== oldTarget && e.relatedTarget.click(); + e.relatedTarget && e.relatedTarget !== oldTarget && _this.opened && _this.opened.focus(); + (!e.relatedTarget || (e.relatedTarget !== oldTarget && !e.relatedTarget.dataset.key)) && _this.setState({opened: null}); + }) && _this.opened.focus(); + }); }, onClick(e) { e && e.preventDefault && e.preventDefault(true) && e.stopPropagation && e.stopPropagation(true); @@ -33,7 +42,7 @@ var UniswapTokenPicker = React.createClass({ renderOpened() { var _this = this; var thisKey = this.getKey(); - return (
+ return (
this.opened = ref}>
X
diff --git a/spa/swapBazar/view.jsx b/spa/swapBazar/view.jsx index 299334d..2af1278 100644 --- a/spa/swapBazar/view.jsx +++ b/spa/swapBazar/view.jsx @@ -25,26 +25,10 @@ var SwapBazar = React.createClass({ _this.setState({ uniswap }); }); }, - close(e) { + closeUniswap(e) { e && e.preventDefault && e.preventDefault(true) && e.stopPropagation && e.stopPropagation(true); this.setState({ uniswap: null }); }, - onInputToken(inputToken) { - var state = { inputToken }; - if (inputToken && this.state.outputToken && this.state.outputToken.address === inputToken.address) { - state.outputToken = null; - this.outputToken.setState({ key: null, selected: null }); - } - this.setState(state); - }, - onOutputToken(outputToken) { - var state = { outputToken }; - if (outputToken && this.state.inputToken && this.state.inputToken.address === outputToken.address) { - state.inputToken = null; - this.inputToken.setState({ key: null, selected: null }); - } - this.setState(state); - }, onToken(token, tokenName) { var otherTokenName = (tokenName === 'input' ? 'output' : 'input') + 'Token'; var otherToken = this.state && this.state[otherTokenName]; @@ -69,7 +53,7 @@ var SwapBazar = React.createClass({ render() { return (
{this.state && this.state.uniswap && this.state.inputToken && this.state.outputToken &&
- X + X
} {(!this.state || !this.state.tokensList) && } From 8bd45a06cc76d9fa97b161559a94d806a3b266b0 Mon Sep 17 00:00:00 2001 From: alet89 Date: Wed, 26 Aug 2020 13:56:51 +0200 Subject: [PATCH 20/76] Bug Fixing --- assets/css/style.css | 17 ++++++++++------- index.html | 2 +- spa/grimoire/grimCrafting.jsx | 6 ++++-- spa/index/view.jsx | 2 +- 4 files changed, 16 insertions(+), 11 deletions(-) diff --git a/assets/css/style.css b/assets/css/style.css index 8f28525..c3fe660 100644 --- a/assets/css/style.css +++ b/assets/css/style.css @@ -23,6 +23,7 @@ section, article, label {display: inline-block;} .expMoreandMore {width: 100%; text-align: center; padding: 50px 0;} .expMoreandMore h5 {font-size: 25px; color: #c7ac97;} .expMoreandMore h5 img {width: 40px; height: 40px; vertical-align: middle;} +.unifiAll {min-height: 100%;} .loaderRegular {margin: 30px auto; width: 100px; height: 100px; padding: 30px; border-radius: 8px;} .loaderMini {width: 30px; height: 30px; vertical-align: middle; margin: 0 10px; display: inline-block;} @@ -75,7 +76,7 @@ footer p a, footer h5 a {color: #c7ac97; font-weight: bold;} .UniStableManage {width: 25px; height: 25px;vertical-align: middle; margin: 7px;} .UniActiveQuantityTier, .UniDisactiveQuantityTier {display: inline-block; margin: 5px auto;} .UniTierQuantity h6 {font-size: 15px; margin: 6px auto;} -.StableCoinTitle, .grimoireWelcome {width: 100%; margin-top: 100px; text-align: center;} +.StableCoinTitle, .grimoireWelcome {width: 100%; margin-top: 100px; text-align: center;position: initial;z-index: 1;} .grimoireBoxAll {width: 100%; margin-top: 25px; text-align: center;} .grimoireBox {width: 95%; margin-bottom: 18px; text-align: center;} .grimoireIndex {width: 95%; margin-left: 4%; text-align: left;} @@ -90,7 +91,7 @@ footer p a, footer h5 a {color: #c7ac97; font-weight: bold;} .grimoireArticle ol {width: 100%; display: inline-block; text-align: right;} .grimoireArticle li {width: 95%; text-align: left; display: inline-block; font-size: 15px;line-height: 1.3; margin: 10px auto;} -.StableCoinTitle .StableCoinTitleIntern, .grimoireWelcome .grimoireWelcomeIntern {display: none; position: relative;} +.StableCoinTitle .StableCoinTitleIntern, .grimoireWelcome .grimoireWelcomeIntern {display: none;} .StableCoinTitle h2, .grimoireWelcome h2 {font-size: 25px; margin: 10px 0; vertical-align: middle;text-align: left;} .StableCoinTitle h6, .grimoireWelcome h6 {font-size: 15px; text-align: left; line-height: 1.4; font-weight: normal;} .UniActiveQuantityTier h6, .UniDisactiveQuantityTier h6 {font-size: 12px; margin: 0 0 0 10px;} @@ -143,8 +144,8 @@ footer p a, footer h5 a {color: #c7ac97; font-weight: bold;} .Boomer .UniBox, .Boomer .grimoireBox {position: initial;background: rgb(255, 255, 255); box-shadow: rgba(0, 0, 0, 0.01) 0px 0px 1px, rgba(0, 0, 0, 0.04) 0px 4px 8px, rgba(0, 0, 0, 0.04) 0px 16px 24px, rgba(0, 0, 0, 0.01) 0px 24px 32px; border-radius: 30px; color: #000000;} .Boomer .UniSideBox {border-radius: 20px; color: #000000; width: 100%; background-color: #bab9b9;box-shadow: rgba(0, 0, 0, 0.01) 0px 0px 1px, rgba(0, 0, 0, 0.04) 0px 4px 8px, rgba(0, 0, 0, 0.04) 0px 16px 24px, rgba(0, 0, 0, 0.01) 0px 24px 32px;} -.Boomer body {background: linear-gradient(29deg, rgba(255,255,255,1) 0%, rgba(228,228,228,1) 66%);font-family: "Inter var", sans-serif;} -.Boomer body > .unifiAll > .explainer {background: linear-gradient(29deg, rgba(80,80,80,1) 0%, rgba(46,46,46,1) 66%);font-family: "Myriad Pro";} +.Boomer {background: linear-gradient(29deg, rgba(255,255,255,1) 0%, rgba(228,228,228,1) 66%);font-family: "Inter var", sans-serif;} +.Boomer > .explainer {background: linear-gradient(29deg, rgba(80,80,80,1) 0%, rgba(46,46,46,1) 66%);font-family: "Myriad Pro";} .Boomer .UniTitle select, .Boomer .UniActiveQuantityTier input, .Boomer .UniDisactiveQuantityTier input, .Boomer .RebalanceEmergency label input {background-color: #e7e7e7; color: #000000; border: 5px solid #e7e7e7; border-radius: 5px;} .Boomer .UniTitle {color: #000000;} .Boomer .menuOpener, .Boomer .connectOpener {background-color: #bab9b9; color: #000000;box-shadow: rgba(0, 0, 0, 0.01) 0px 0px 1px, rgba(0, 0, 0, 0.04) 0px 4px 8px, rgba(0, 0, 0, 0.04) 0px 16px 24px, rgba(0, 0, 0, 0.01) 0px 24px 32px;} @@ -165,15 +166,16 @@ footer p a, footer h5 a {color: #c7ac97; font-weight: bold;} .Boomer .grimoireIndex h2 {color: #000000;} .Boomer .grimoireIndex a {color: #000000;} .Boomer .coverMenu li a span {color: #000000;} -.Boomer body > .unifiAll > .explainer .coverMenu li a span {text-shadow: 2px 2px 2px #5d5e60;color: #bab9b9;} +.Boomer > .explainer .coverMenu li a span {text-shadow: 2px 2px 2px #5d5e60;color: #bab9b9;} .Boomer .CallToGrim a {background-color: #bab9b9;box-shadow: rgba(0, 0, 0, 0.01) 0px 0px 1px, rgba(0, 0, 0, 0.04) 0px 4px 8px, rgba(0, 0, 0, 0.04) 0px 16px 24px, rgba(0, 0, 0, 0.01) 0px 24px 32px;} +.Boomer .maghetto {-webkit-filter: grayscale(100%); filter: grayscale(100%);} .RPG .UniBox, .RPG .grimoireBox {position: initial;background: rgb(33, 36, 41); border-radius: 20px; color: rgb(195, 197, 203);box-shadow: rgba(0, 0, 0, 0.01) 0px 0px 1px, rgba(0, 0, 0, 0.04) 0px 4px 8px, rgba(0, 0, 0, 0.04) 0px 16px 24px, rgba(0, 0, 0, 0.01) 0px 24px 32px;} .RPG .UniSideBox {border-radius: 20px; color: #bab9b9; width: 100%; background-color: #2b2622;box-shadow: rgba(0, 0, 0, 0.01) 0px 0px 1px, rgba(0, 0, 0, 0.04) 0px 4px 8px, rgba(0, 0, 0, 0.04) 0px 16px 24px, rgba(0, 0, 0, 0.01) 0px 24px 32px;} -.RPG body {background: linear-gradient(29deg, rgba(80,80,80,1) 0%, rgba(46,46,46,1) 66%);font-family: "Myriad Pro";} +.RPG {background: linear-gradient(29deg, rgba(80,80,80,1) 0%, rgba(46,46,46,1) 66%);font-family: "Myriad Pro";} .RPG .UniTitle select, .RPG .UniActiveQuantityTier input, .RPG .UniDisactiveQuantityTier input, .RPG .RebalanceEmergency label input {background-color: #000000; color: #f1f1f1; border: 5px solid #000000; border-radius: 5px;} -.RPG .UniTitle {color: #000000;} +.RPG .UniTitle {color: #bab9b9;} .RPG .menuOpener, .RPG .connectOpener {background-color: #c7ac97; color: #444444;box-shadow: rgba(0, 0, 0, 0.01) 0px 0px 1px, rgba(0, 0, 0, 0.04) 0px 4px 8px, rgba(0, 0, 0, 0.04) 0px 16px 24px, rgba(0, 0, 0, 0.01) 0px 24px 32px;} .RPG .unifiDapp .MenuOpen .coverMenu {background-color: #2b2622; border-color: #2b2622;box-shadow: rgba(0, 0, 0, 0.01) 0px 0px 1px, rgba(0, 0, 0, 0.04) 0px 4px 8px, rgba(0, 0, 0, 0.04) 0px 16px 24px, rgba(0, 0, 0, 0.01) 0px 24px 32px;} .RPG .StableCoinTitleIntern, .RPG .grimoireWelcomeIntern {background-color: #2b2622;box-shadow: rgba(0, 0, 0, 0.01) 0px 0px 1px, rgba(0, 0, 0, 0.04) 0px 4px 8px, rgba(0, 0, 0, 0.04) 0px 16px 24px, rgba(0, 0, 0, 0.01) 0px 24px 32px;} @@ -224,6 +226,7 @@ footer p a, footer h5 a {color: #c7ac97; font-weight: bold;} .grimoireWelcome .GrimImg2 {width: 70px; height: 70px; position: absolute; bottom: 10px; left: 5px; z-index: 2;} footer .welcomeLinks, footer p {width: 500px; padding: 20px;} .grimoireIndex {width: 350px;} + .DuGustis {position: relative;} } @media only screen and (min-width: 890px) { diff --git a/index.html b/index.html index f136d8d..52449bb 100644 --- a/index.html +++ b/index.html @@ -1,4 +1,4 @@ - + diff --git a/spa/grimoire/grimCrafting.jsx b/spa/grimoire/grimCrafting.jsx index df1217c..fdab478 100644 --- a/spa/grimoire/grimCrafting.jsx +++ b/spa/grimoire/grimCrafting.jsx @@ -8,8 +8,10 @@ var GrimCrafting = React.createClass({
- - +
+ + +

The Grimoire - Crafting and Initial Liquidity Offering

Craft makes it possible to provide liquidity that is programmable with advanced rules. Using Unicorn magic, pools can balance tokens diversely with unprecedented security.
diff --git a/spa/index/view.jsx b/spa/index/view.jsx index 6ace569..3c78d4f 100644 --- a/spa/index/view.jsx +++ b/spa/index/view.jsx @@ -29,7 +29,7 @@ var Index = React.createClass({ props.props && Object.entries(props.props).forEach(entry => props[entry[0]] = entry[1]); delete props.props; return ( -
+
{React.createElement(window[props.section || 'Explainer'], props)}
); From 5f996827df34cb8d47b0a321c380419a01a6b085 Mon Sep 17 00:00:00 2001 From: Marco Vasapollo Date: Wed, 26 Aug 2020 14:15:53 +0200 Subject: [PATCH 21/76] Loading glitches --- assets/plugins/react/react.module.manager.js | 2 +- index.html | 8 +++---- spa/explainer/view.jsx | 6 ----- spa/index/view.jsx | 24 ++++++++++++++++---- 4 files changed, 24 insertions(+), 16 deletions(-) diff --git a/assets/plugins/react/react.module.manager.js b/assets/plugins/react/react.module.manager.js index 2348f8c..cccb546 100644 --- a/assets/plugins/react/react.module.manager.js +++ b/assets/plugins/react/react.module.manager.js @@ -105,7 +105,7 @@ var ReactModuleManager = function() { if (rendered.props === undefined || rendered.props === null) { rendered.props = {}; } - rendered.props.className = loader ? rendered.props.defaultClassName : rendered.props.className; + rendered.props.className = loader && rendered.props.defaultClassName ? rendered.props.defaultClassName : rendered.props.className; if (rendered.props.className === undefined || rendered.props.className === null) { rendered.props.className = ''; } diff --git a/index.html b/index.html index 52449bb..14c91ff 100644 --- a/index.html +++ b/index.html @@ -39,10 +39,10 @@ -
- -

Welcome to the UniFi World

-
+
+ +

Welcome to the UniFi World

+
\ No newline at end of file diff --git a/spa/explainer/view.jsx b/spa/explainer/view.jsx index 9786c33..3b02904 100644 --- a/spa/explainer/view.jsx +++ b/spa/explainer/view.jsx @@ -1,10 +1,4 @@ var Explainer = React.createClass({ - requiredScripts: [ - 'spa/loader.jsx' - ], - requiredModules: [ - 'spa/dappMenu' - ], renderExStableCoin() { return this.renderInput("ExStableCoin", "assets/img/exp1.png", "a", "InfoButton", "a", "dappButton", "More", "Launch Dapp", "A Stable Coin to Pool Them All", "Uniswap State Dollar (uSD) is a new stablecoin minted by the magic rainbow of Uniswap stablecoin pools. Backed by the power of the Unicorn, uSD is the most secure stablecoin ever. The only way it could be destabilized is if the entire stablecoin industry crashed.", undefined, () => this.emit('section/change', 'stableCoin')); }, diff --git a/spa/index/view.jsx b/spa/index/view.jsx index 3c78d4f..185fa8f 100644 --- a/spa/index/view.jsx +++ b/spa/index/view.jsx @@ -3,18 +3,26 @@ var Index = React.createClass({ 'spa/loader.jsx' ], requiredModules: [ - 'spa/explainer' + 'spa/explainer', + 'spa/dappMenu' ], + getCustomLoader() { + return (
+ +

Welcome to the UniFi World

+
); + }, getDefaultSubscriptions() { return { - 'section/change': this.sectionChange + 'section/change': this.sectionChange, + 'visual/mode/toggle': this.toggleBoomerMode }; }, sectionChange(section, props) { var _this = this; ReactModuleLoader.load({ - modules : ['spa/' + section.firstLetterToLowerCase()], - callback: () => _this.setState({section: section.firstLetterToUpperCase(), props}) + modules: ['spa/' + section.firstLetterToLowerCase()], + callback: () => _this.setState({ section: section.firstLetterToUpperCase(), props }) }); }, componentDidMount() { @@ -22,6 +30,12 @@ var Index = React.createClass({ delete window.addressBarParams.section; section && this.sectionChange(section); }, + toggleBoomerMode(e) { + e && e.preventDefault(true) && e.stopPropagation(true); + e && $(e.target).html('&#' + (this.domRoot.toggleClass('Boomer').hasClass('Boomer') ? '128161' : '127769') + ';'); + window.localStorage.setItem('boomerMode', !this.domRoot.hasClass('Boomer')); + !e && this.forceUpdate(); + }, render() { var props = {}; this.props && Object.entries(this.props).forEach(entry => props[entry[0]] = entry[1]); @@ -29,7 +43,7 @@ var Index = React.createClass({ props.props && Object.entries(props.props).forEach(entry => props[entry[0]] = entry[1]); delete props.props; return ( -
+
{React.createElement(window[props.section || 'Explainer'], props)}
); From 94c956cb5c2bbab565700a555df0374f1374feb0 Mon Sep 17 00:00:00 2001 From: Marco Vasapollo Date: Wed, 26 Aug 2020 14:33:01 +0200 Subject: [PATCH 22/76] Boomer Mode Keys --- spa/dappMenu/view.jsx | 5 +++++ spa/index/view.jsx | 6 ++---- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/spa/dappMenu/view.jsx b/spa/dappMenu/view.jsx index e5e9cc7..411a5e3 100644 --- a/spa/dappMenu/view.jsx +++ b/spa/dappMenu/view.jsx @@ -69,9 +69,14 @@ var DappMenu = React.createClass({ }; toggleWork(e.currentTarget.dataset.type); }, + toggleBoomerMode(e) { + e && e.preventDefault && e.preventDefault(true) && e.stopPropagation && e.stopPropagation(true); + this.emit('visual/mode/toggle'); + }, render() { return (
+ ref && (ref.innerHTML = ('&#' + (window.localStorage.boomerMode === 'true' ? '127769' : '128161') + ';'))}> Menu {!window.walletAddress && Connect} diff --git a/spa/index/view.jsx b/spa/index/view.jsx index 185fa8f..e0e7f6c 100644 --- a/spa/index/view.jsx +++ b/spa/index/view.jsx @@ -30,11 +30,9 @@ var Index = React.createClass({ delete window.addressBarParams.section; section && this.sectionChange(section); }, - toggleBoomerMode(e) { - e && e.preventDefault(true) && e.stopPropagation(true); - e && $(e.target).html('&#' + (this.domRoot.toggleClass('Boomer').hasClass('Boomer') ? '128161' : '127769') + ';'); + toggleBoomerMode() { window.localStorage.setItem('boomerMode', !this.domRoot.hasClass('Boomer')); - !e && this.forceUpdate(); + this.forceUpdate(); }, render() { var props = {}; From a4100db904b0bf323250b99e2496b12975422176 Mon Sep 17 00:00:00 2001 From: alet89 Date: Wed, 26 Aug 2020 14:54:15 +0200 Subject: [PATCH 23/76] Boomer --- assets/css/style.css | 5 +++-- spa/dappMenu/view.jsx | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/assets/css/style.css b/assets/css/style.css index c3fe660..548d079 100644 --- a/assets/css/style.css +++ b/assets/css/style.css @@ -140,6 +140,7 @@ footer p a, footer h5 a {color: #c7ac97; font-weight: bold;} .CallToGrim {position: fixed; top: 10px; left: 190px; width: 35px; height: 35px;} .CallToGrim a {width: 35px; height: 35px; display: inline-block; text-align: center; border-radius: 10px;} .CallToGrim a img {width: 30px; height: 30px; display: inline-block; vertical-align: center;} +.BoomerModeToggler {width: 35px; height: 35px; display: inline-block; text-align: center; border-radius: 10px; position: fixed; top: 10px; right: 230px; text-decoration: none;} .Boomer .UniBox, .Boomer .grimoireBox {position: initial;background: rgb(255, 255, 255); box-shadow: rgba(0, 0, 0, 0.01) 0px 0px 1px, rgba(0, 0, 0, 0.04) 0px 4px 8px, rgba(0, 0, 0, 0.04) 0px 16px 24px, rgba(0, 0, 0, 0.01) 0px 24px 32px; border-radius: 30px; color: #000000;} @@ -169,7 +170,7 @@ footer p a, footer h5 a {color: #c7ac97; font-weight: bold;} .Boomer > .explainer .coverMenu li a span {text-shadow: 2px 2px 2px #5d5e60;color: #bab9b9;} .Boomer .CallToGrim a {background-color: #bab9b9;box-shadow: rgba(0, 0, 0, 0.01) 0px 0px 1px, rgba(0, 0, 0, 0.04) 0px 4px 8px, rgba(0, 0, 0, 0.04) 0px 16px 24px, rgba(0, 0, 0, 0.01) 0px 24px 32px;} .Boomer .maghetto {-webkit-filter: grayscale(100%); filter: grayscale(100%);} - +.Boomer .BoomerModeToggler {background-color: #bab9b9;box-shadow: rgba(0, 0, 0, 0.01) 0px 0px 1px, rgba(0, 0, 0, 0.04) 0px 4px 8px, rgba(0, 0, 0, 0.04) 0px 16px 24px, rgba(0, 0, 0, 0.01) 0px 24px 32px;} .RPG .UniBox, .RPG .grimoireBox {position: initial;background: rgb(33, 36, 41); border-radius: 20px; color: rgb(195, 197, 203);box-shadow: rgba(0, 0, 0, 0.01) 0px 0px 1px, rgba(0, 0, 0, 0.04) 0px 4px 8px, rgba(0, 0, 0, 0.04) 0px 16px 24px, rgba(0, 0, 0, 0.01) 0px 24px 32px;} .RPG .UniSideBox {border-radius: 20px; color: #bab9b9; width: 100%; background-color: #2b2622;box-shadow: rgba(0, 0, 0, 0.01) 0px 0px 1px, rgba(0, 0, 0, 0.04) 0px 4px 8px, rgba(0, 0, 0, 0.04) 0px 16px 24px, rgba(0, 0, 0, 0.01) 0px 24px 32px;} @@ -195,7 +196,7 @@ footer p a, footer h5 a {color: #c7ac97; font-weight: bold;} .RPG .grimoireIndex a {text-shadow:2px 2px 2px #5d5e60; color: #bab9b9;} .RPG .coverMenu li a span {text-shadow: 2px 2px 2px #5d5e60;color: #bab9b9;} .RPG .CallToGrim a {background-color: #c7ac97;box-shadow: rgba(0, 0, 0, 0.01) 0px 0px 1px, rgba(0, 0, 0, 0.04) 0px 4px 8px, rgba(0, 0, 0, 0.04) 0px 16px 24px, rgba(0, 0, 0, 0.01) 0px 24px 32px;} - +.RPG .BoomerModeToggler {background-color: #c7ac97;box-shadow: rgba(0, 0, 0, 0.01) 0px 0px 1px, rgba(0, 0, 0, 0.04) 0px 4px 8px, rgba(0, 0, 0, 0.04) 0px 16px 24px, rgba(0, 0, 0, 0.01) 0px 24px 32px;} @media only screen and (min-width: 640px) { diff --git a/spa/dappMenu/view.jsx b/spa/dappMenu/view.jsx index 411a5e3..9c4dc8e 100644 --- a/spa/dappMenu/view.jsx +++ b/spa/dappMenu/view.jsx @@ -76,7 +76,7 @@ var DappMenu = React.createClass({ render() { return (
- ref && (ref.innerHTML = ('&#' + (window.localStorage.boomerMode === 'true' ? '127769' : '128161') + ';'))}> + ref && (ref.innerHTML = ('&#' + (window.localStorage.boomerMode === 'true' ? '128188' : '10024') + ';'))}> Menu {!window.walletAddress && Connect} From c0503fbb74879d9190742c4c2f2a946e4711b467 Mon Sep 17 00:00:00 2001 From: Marco Vasapollo Date: Wed, 26 Aug 2020 14:59:03 +0200 Subject: [PATCH 24/76] Toggle Menu Glitch Correction --- spa/dappMenu/view.jsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spa/dappMenu/view.jsx b/spa/dappMenu/view.jsx index 9c4dc8e..2847c70 100644 --- a/spa/dappMenu/view.jsx +++ b/spa/dappMenu/view.jsx @@ -63,7 +63,7 @@ var DappMenu = React.createClass({ _this.state[type] && _this[type] && (_this[type].onblur = _this[type].onblur || function(e) { e && e.preventDefault && e.preventDefault(true) && e.stopPropagation && e.stopPropagation(true); e.relatedTarget && e.relatedTarget !== oldTarget && e.relatedTarget.click(); - toggleWork(type); + e.relatedTarget !== oldTarget && toggleWork(type); }) && _this[type].focus(); }); }; From 7427f9e3d6eea44c1b418dc7582adc91c70f7ced Mon Sep 17 00:00:00 2001 From: Marco Vasapollo Date: Wed, 26 Aug 2020 15:01:16 +0200 Subject: [PATCH 25/76] Amount Bugfix --- spa/stableCoin/view.jsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spa/stableCoin/view.jsx b/spa/stableCoin/view.jsx index 68fe00c..d2010b1 100644 --- a/spa/stableCoin/view.jsx +++ b/spa/stableCoin/view.jsx @@ -197,7 +197,7 @@ var StableCoin = React.createClass({ {this.state.toggleTotalCoins &&
    {Object.values(this.state.totalCoins.list).map(it =>
  • - {window.fromDecimals(it.amount, window.stableCoin.decimals)} + {window.fromDecimals(it.balanceOf, window.stableCoin.decimals)} {'\u00a0'} {it.symbol}
    From efb5601824989374d1ef1dbe123e78611ccea692 Mon Sep 17 00:00:00 2001 From: Marco Vasapollo Date: Wed, 26 Aug 2020 16:40:07 +0200 Subject: [PATCH 26/76] My balance when burn --- data/context.json | 2 +- spa/stableCoin/controller.jsx | 12 ++++++++++++ spa/stableCoin/view.jsx | 13 ++++++++++++- 3 files changed, 25 insertions(+), 2 deletions(-) diff --git a/data/context.json b/data/context.json index 8172330..5679f5f 100644 --- a/data/context.json +++ b/data/context.json @@ -12,7 +12,7 @@ "trustwalletImgURLTemplate": "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/{0}/logo.png", "uniswapDappLinkTemplate" : "https://app.uniswap.org/#/{0}?inputCurrency={1}&outputCurrency={2}", "uniswapInfoLinkTemplate" : "https://uniswap.info/token/{0}", - "stableCoinAddressRopsten" : "0x9f4c43A51C9a67F432E5C8BcBFa55312110BCD3A", + "stableCoinAddressRopsten" : "0x0407fb98ae1972a61f544fe41335eb1213f8f372", "stableCoinAddress" : "0x04C2d7C0712089a61C52A315FCe8F28a55F34DFa", "infuraNode" : "https://ropsten.infura.io/v3/5e302428cc5e41a188dc717dc6f34a5b", "uniwsapOfficialTokensList" : "https://unpkg.com/@uniswap/default-token-list@latest", diff --git a/spa/stableCoin/controller.jsx b/spa/stableCoin/controller.jsx index ff9a53e..803c248 100644 --- a/spa/stableCoin/controller.jsx +++ b/spa/stableCoin/controller.jsx @@ -280,6 +280,13 @@ var StableCoinController = function (view) { } }; + context.getMyBalance = async function getMyBalance() { + if(!window.walletAddress) { + return null; + } + return await window.blockchainCall(window.stableCoin.token.methods.balanceOf, window.walletAddress); + }; + context.calculateRebalanceByDebtReward = async function calculateRebalanceByDebtReward(amount) { amount = window.toDecimals(amount.split(',').join(''), window.stableCoin.decimals); return await window.blockchainCall(window.stableCoin.token.methods.calculateRebalanceByDebtReward, amount); @@ -330,11 +337,16 @@ var StableCoinController = function (view) { var first = totalSupply < balanceOf ? totalSupply : balanceOf; var second = totalSupply > balanceOf ? totalSupply : balanceOf; var percentage = (first / second) * 100; + percentage = parseInt(window.formatMoney(percentage, 0)); balanceOf > totalSupply && (percentage = percentage === 200 ? 200 : percentage > 200 ? 201 : 200 - percentage); totalCoins.regularPercentage = window.numberToString(percentage).split(',').join('').split('.')[0]; totalCoins.healthPercentage = window.numberToString(percentage / 2).split(',').join('').split('.')[0]; parseInt(totalCoins.regularPercentage) > 200 && (totalCoins.regularPercentage = '200+'); parseInt(totalCoins.healthPercentage) > 100 && (totalCoins.healthPercentage = '100'); + if(isNaN(parseInt(totalCoins.regularPercentage))) { + totalCoins.regularPercentage = '100'; + totalCoins.healthPercentage = '50'; + } context.view.setState({totalCoins}); }; diff --git a/spa/stableCoin/view.jsx b/spa/stableCoin/view.jsx index d2010b1..9f03643 100644 --- a/spa/stableCoin/view.jsx +++ b/spa/stableCoin/view.jsx @@ -16,6 +16,16 @@ var StableCoin = React.createClass({ componentDidMount() { this.controller.loadData(); }, + onActionChange(e) { + e && e.preventDefault && e.preventDefault(true) && e.stopPropagation && e.stopPropagation(true); + var value = e.currentTarget.value; + var _this = this; + _this.setState({myBalance : null}, function() { + value === 'Burn' && _this.controller.getMyBalance().then(function(myBalance) { + _this.setState({myBalance}); + }); + }); + }, onPairChange(e) { e && e.preventDefault && e.preventDefault(true) && e.stopPropagation && e.stopPropagation(true); var _this = this; @@ -144,7 +154,7 @@ var StableCoin = React.createClass({ {this.state && this.state.selectedPair &&

    for this.stableCoinOutput = ref}>0{'\u00a0'}{window.stableCoin.symbol}

    + {window.walletAddress && this.state && this.state.myBalance &&
    Balance: {window.fromDecimals(this.state.myBalance, window.stableCoin.decimals)}{'\u00a0'}{window.stableCoin.symbol}
    } {window.walletAddress && (!this.state.token0Approved || this.state.token1Approved) && (this.state.approving === undefined || this.state.approving === null) && Approve {this.state.selectedPair.token0.symbol}} {window.walletAddress && this.state.token0Approved && !this.state.token1Approved && (this.state.approving === undefined || this.state.approving === null) && Approve {this.state.selectedPair.token1.symbol}} {this.state.approving !== undefined && this.state.approving !== null && } From 7e5654347c2e7b5e280e314c47b663ab0327a32e Mon Sep 17 00:00:00 2001 From: alet89 Date: Wed, 26 Aug 2020 16:43:31 +0200 Subject: [PATCH 27/76] Push Push Push --- assets/css/style.css | 2 +- spa/grimoire/grimBazar.jsx | 10 ++++++- spa/grimoire/grimCrafting.jsx | 56 ++++++++++++++++++++++++++++++++--- spa/grimoire/view.jsx | 2 +- spa/swapBazar/view.jsx | 28 ++++++++++++------ 5 files changed, 82 insertions(+), 16 deletions(-) diff --git a/assets/css/style.css b/assets/css/style.css index 548d079..4c617ea 100644 --- a/assets/css/style.css +++ b/assets/css/style.css @@ -140,7 +140,7 @@ footer p a, footer h5 a {color: #c7ac97; font-weight: bold;} .CallToGrim {position: fixed; top: 10px; left: 190px; width: 35px; height: 35px;} .CallToGrim a {width: 35px; height: 35px; display: inline-block; text-align: center; border-radius: 10px;} .CallToGrim a img {width: 30px; height: 30px; display: inline-block; vertical-align: center;} -.BoomerModeToggler {width: 35px; height: 35px; display: inline-block; text-align: center; border-radius: 10px; position: fixed; top: 10px; right: 230px; text-decoration: none;} +.BoomerModeToggler {width: 35px; height: 35px; display: inline-block; text-align: center; border-radius: 10px; position: fixed; top: 10px; right: 230px; text-decoration: none;line-height: 2;} .Boomer .UniBox, .Boomer .grimoireBox {position: initial;background: rgb(255, 255, 255); box-shadow: rgba(0, 0, 0, 0.01) 0px 0px 1px, rgba(0, 0, 0, 0.04) 0px 4px 8px, rgba(0, 0, 0, 0.04) 0px 16px 24px, rgba(0, 0, 0, 0.01) 0px 24px 32px; border-radius: 30px; color: #000000;} diff --git a/spa/grimoire/grimBazar.jsx b/spa/grimoire/grimBazar.jsx index f443129..c87a253 100644 --- a/spa/grimoire/grimBazar.jsx +++ b/spa/grimoire/grimBazar.jsx @@ -19,11 +19,19 @@ var GrimBazar = React.createClass({
    +
    +

    Basics

    +

    Programmable Liquidity is an exciting feature in AMMs, but if it impacts the AMM itself, this can introduce bugs due to math complexities (like what happened with Balancer). UniFi crafting aims to achieve Programmable Liquidity, but using Uniswap as a base layer. This helps liquidity providers customize their investment, and empower new applications on top of Uniswap.

    +

    Uniswap accepts liquidity pools composed of 50:50 asset ratios. This is the most secure setup for an AMM, except for some cases. However, this setup disincentivizes liquidity provision due to the problem of impermanent losses.

    +

    To solve this problem and create new opportunities for the financial use of Uniswap pools, UniFi introduces “Crafting.” This is a new fancy way to build liquidity together, without needing to trust and know each other.

    +

    Anyone can create a Craft Order, customize the liquidity setup and deploy it by adding his or her own portion of liquidity. Anyone can then fill the remaining liquidity required to pool the liquidity in the Uniswap pool. After a pre-selected block, the first one who transacts the removal will remove and send the liquidity to all of the Order participants, based on the rules created initially.

    + +
    diff --git a/spa/grimoire/grimCrafting.jsx b/spa/grimoire/grimCrafting.jsx index fdab478..bfe9e51 100644 --- a/spa/grimoire/grimCrafting.jsx +++ b/spa/grimoire/grimCrafting.jsx @@ -22,11 +22,59 @@ var GrimCrafting = React.createClass({
    +
    +

    Basics

    +

    Programmable Liquidity is an exciting feature in AMMs, but if it impacts the AMM itself, this can introduce bugs due to math complexities (like what happened with Balancer). UniFi crafting aims to achieve Programmable Liquidity, but using Uniswap as a base layer. This helps liquidity providers customize their investment, and empower new applications on top of Uniswap.

    +

    Uniswap accepts liquidity pools composed of 50:50 asset ratios. This is the most secure setup for an AMM, except for some cases. However, this setup disincentivizes liquidity provision due to the problem of impermanent losses.

    +

    To solve this problem and create new opportunities for the financial use of Uniswap pools, UniFi introduces “Crafting.” This is a new fancy way to build liquidity together, without needing to trust and know each other.

    +

    Anyone can create a Craft Order, customize the liquidity setup and deploy it by adding his or her own portion of liquidity. Anyone can then fill the remaining liquidity required to pool the liquidity in the Uniswap pool. After a pre-selected block, the first one who transacts the removal will remove and send the liquidity to all of the Order participants, based on the rules created initially.

    +
    +
    +

    Programmable Liquidity Rules

    +
      +
    1. - Selected Tier: The Tier to add liquidity.
    2. +
    3. - Waiting Length: the max time (in Blocks) the order can remain available while the required liquidity is waiting to be filled.
    4. +
    5. - Min Block Length: The time (in Blocks) in which the liquidity will be locked. If 0, any of the participants can trigger the removal of liquidity anytime.
    6. +
    7. - Liquidity Ratio: The creator of the order can set the ratio of liquidity (e.g. 10% DAI - 90% ETH or 0% DAI - 100 ETH). After the order is deployed, participants will be able to fill the liquidity required, so in the first example, if the creator sets 10% DAI - 90% ETH, the participant can add 90% DAI and 10% ETH.
    8. +
    9. - Liquidity Exit/Discount: An advanced feature for orders that allows for the creation of a different ratio or even a discount for the exit.
    10. +
    +

    Example:

    +

    Let’s expand on the given example. A creates an order for USDC - DAI, with a min block length of 543055 Blocks and a ratio of 10% DAI - 90% USDC. He adds 100 DAI and 900 USDC. He also sets the exit liquidity at 30% DAI and 70% USDC, B fills part of the required liquidity (the ratio in his case is 90% DAI and 10% USDC) with 500 DAI and 50 USDC.

    +

    C fills part of the required liquidity (the ratio in his case is also 90% DAI and 10% USDC) with 100 DAI and 10 USDC.

    +

    D fills part of the required liquidity (the ratio in his case is also 90% DAI and 10% USDC) with 300 DAI and 30 USDC. D’s liquidity is enough to fill the 50:50 Uniswap pool, so D automatically triggers Uniswap’s Add Liquidity order by its last filling.

    +

    The total Uniswap liquidity pooled by A,B,C andD is 1,000 DAI and 1,000 USDC.

    +

    After 543055 Blocks, the liquidity pool has earned by the Uniswap Fees 1,000 USDC and 1,000 DAI for a total of 2,000 DAI and 2,000 USDC. B triggers the removal action, and based on the fixed rules, each of our providers receives the following:

    +

    A receives 600 DAI and 1,400 USDC (based on the Exit Ratio of 30% DAI and 70% USDC).

    +

    B, C and D receive 1,400 DAI and 600 USDC each, slipped by the liquidity added (based on the Exit Ratio of 70% DAI and 30% USDC).

    +
    +
    +

    Initial Liquidity Offering (ILO)

    +

    Initial Liquidity Offerings are a procedure for Ethereum based startups to use a set of “Crafting”—aka, Programmable Liquidity—rules to reach long term funds in the form of Uniswap liquidity.

    +

    ILOs are helpful for three important reasons:

    +
    Initial Liquidity into AMMs for Fixed Inflation/Liquidity Staking
    +

    Reach the liquidity required to set fixed inflation without dumping on new holders, and helping new investors reduce slippage and become holders with a large amount of capital.

    +
    Avoid Sniper Bots
    +

    Sniper Bots are Ethereum-based bots who track new Uniswap low liquidity pools to sniff out significant amounts of capital before the liquidity even comes in, making it impossible for startups to start their offering with low collateral.

    +
    Reach Long Term Locked Investors
    +

    Investors lock their funds for the long run.

    +

    How ILOs work:

    +

    Before a new token is distributed, a new startup can set a crafting order with fixed pre-values, adding the token and requesting the collateral required for investors to fill the order.Investors fill the collateral needed, and if the startup has set, investors can have an exit Discount to mitigate the high risk.

    +
    Example
    +

    The token creator sets a Crafting order with low liquidity, like 1,000,000 of the token and 1 ETH, with a 90% - 10% ratio, or even 1,000,000 of token and 0 ETH, with a 100% - 0% ratio (adding a pre-value of the token, if the liquidity pool is not open yet) for one year. Setting the Liquidity Exit/Discount (10%/20%) means that investors will receive at the end of the order (90%/80%).

    +

    In this case, investors invest their own Ethereum for a new token not already tradable, so with a high level of risk, they’ll receive a more significant portion of the liquidity at the end of the year (from 50% added to 170% received).

    +

    ILOs can open new Ethereum fundraising rules that solve liquidity in early stages while also helping legitimate projects set Fixed Inflation. This empowers projects and investors in the long run.

    +
    UniFi DFO Tax:
    +

    The earning of the UniFi DFO using the Crafting function id the 0.1% of the total Uniswap Pool Tokens into a Craft order, this tax is paid directly when a participant calls the remove function.

    +
    +
    +

    Release

    +

    The Release Of Crafting and ILOs is expected for early October 2020

    +
diff --git a/spa/grimoire/view.jsx b/spa/grimoire/view.jsx index fe0e8e8..fd3516a 100644 --- a/spa/grimoire/view.jsx +++ b/spa/grimoire/view.jsx @@ -16,7 +16,7 @@ var Grimoire = React.createClass({

The Grimoire

-
The comprehensive giude to use the Uniswap Magic

Here, you can find every info needed to understand UniFi and to integrate your dapp with this protocol.
+
Ancient black magic is unleashing the true power of the Unicorn. Programmable Equities, Token Indexes and NFTs (including ERC 1155 NFTs, thanks to ethArt V2) can now be swapped, on the new Bazaar DEX.
diff --git a/spa/swapBazar/view.jsx b/spa/swapBazar/view.jsx index 2af1278..1dbb0f7 100644 --- a/spa/swapBazar/view.jsx +++ b/spa/swapBazar/view.jsx @@ -51,7 +51,25 @@ var SwapBazar = React.createClass({ this.setState({ grimoire: !(this.state && this.state.grimoire) }); }, render() { - return (
+ return (
+ +
+
+ + {this.state && this.state.grimoire && } + {(!this.state || !this.state.grimoire) && } + +
+
+
+
+ +
+

The Bazar

+
uSD is a Stable Coin based on Uniswap Liquidity Pools More

Here, you can mint uSD by adding liquidity to whitelisted Uniswap Stable Coin Pools or redeem anytime whitelisted Stable Coins by burning uSD.
+
+
+
{this.state && this.state.uniswap && this.state.inputToken && this.state.outputToken &&
X @@ -73,15 +91,7 @@ var SwapBazar = React.createClass({ Swap Pool
} -
-
- - {this.state && this.state.grimoire && X} - {(!this.state || !this.state.grimoire) && Grimoire} - -
{this.state && this.state.grimoire && } -
); } }); \ No newline at end of file From 67b7402c39044704740ff5a2dc2be627e9780ead Mon Sep 17 00:00:00 2001 From: Marco Vasapollo Date: Wed, 26 Aug 2020 17:14:38 +0200 Subject: [PATCH 28/76] Bazar Prices --- assets/scripts/script.js | 13 ++++++++----- spa/swapBazar/controller.jsx | 18 ++++++++++++++---- spa/swapBazar/uniswapTokenPicker.jsx | 23 ++++++++++++++--------- spa/swapBazar/view.jsx | 14 ++++++++++++++ 4 files changed, 50 insertions(+), 18 deletions(-) diff --git a/assets/scripts/script.js b/assets/scripts/script.js index 8aa4796..d642d19 100644 --- a/assets/scripts/script.js +++ b/assets/scripts/script.js @@ -127,14 +127,17 @@ window.onEthereumUpdate = function onEthereumUpdate(millis) { }; window.loadEthereumStuff = async function loadEthereumStuff() { - window.stableCoin = window.newContract(window.context.StableCoinAbi, window.getNetworkElement("stableCoinAddress")); - window.doubleProxy = window.newContract(window.context.DoubleProxyAbi, await window.blockchainCall(window.stableCoin.methods.doubleProxy)) - window.dfo = window.web3.eth.dfoHub.load(await window.blockchainCall(window.doubleProxy.methods.proxy)); window.uniswapV2Router = window.newContract(window.context.UniswapV2RouterAbi, window.context.uniswapV2RouterAddress); window.wethToken = window.newContract(window.context.votingTokenAbi, window.wethAddress = window.web3.utils.toChecksumAddress(await window.blockchainCall(window.uniswapV2Router.methods.WETH))); window.uniswapV2Factory = window.newContract(window.context.UniswapV2FactoryAbi, window.context.uniswapV2FactoryAddress); - window.stableCoin = await window.loadTokenInfos(window.stableCoin.options.address, window.context.StableCoinAbi); - window.votingToken = await window.loadTokenInfos((await (window.dfo = await window.dfo).votingToken).options.address); + try { + window.stableCoin = window.newContract(window.context.StableCoinAbi, window.getNetworkElement("stableCoinAddress")); + window.doubleProxy = window.newContract(window.context.DoubleProxyAbi, await window.blockchainCall(window.stableCoin.methods.doubleProxy)) + window.dfo = window.web3.eth.dfoHub.load(await window.blockchainCall(window.doubleProxy.methods.proxy)); + window.stableCoin = await window.loadTokenInfos(window.stableCoin.options.address, window.context.StableCoinAbi); + window.votingToken = await window.loadTokenInfos((await (window.dfo = await window.dfo).votingToken).options.address); + } catch(e) { + } }; window.getNetworkElement = function getNetworkElement(element) { diff --git a/spa/swapBazar/controller.jsx b/spa/swapBazar/controller.jsx index 187b7ed..4183a35 100644 --- a/spa/swapBazar/controller.jsx +++ b/spa/swapBazar/controller.jsx @@ -11,12 +11,13 @@ var SwapBazarController = function (view) { context.newDfoDeployedEvent = "DFODeployed(address_indexed,address_indexed,address,address)"; context.loadData = async function loadData() { + await window.loadEthereumStuff(); try { context.view.setState({ tokensList: { - "Programmable Equities": (await window.AJAXRequest(window.context.programmableEquitiesURL)).tokens, - "Tokens": (await window.AJAXRequest(window.context.uniswapTokensURL)).tokens, - Indexes: (await window.AJAXRequest(window.context.indexesURL)).tokens + "Programmable Equities": (await window.AJAXRequest(window.context.programmableEquitiesURL)).tokens.map(it => it.chainId === window.networkId && it), + "Tokens": (await window.AJAXRequest(window.context.uniswapTokensURL)).tokens.map(it => it.chainId === window.networkId && it), + Indexes: (await window.AJAXRequest(window.context.indexesURL)).tokens.map(it => it.chainId === window.networkId && it) } }); } catch (e) { @@ -25,7 +26,6 @@ var SwapBazarController = function (view) { }; context.loadDataOnChain = async function loadDataOnChain() { - await window.loadEthereumStuff(); var dfoHub = await window.loadDFO(window.getNetworkElement("dfoAddress")); context.dfoHubAddresses = dfoHub.options.allAddresses; context.list = { @@ -152,4 +152,14 @@ var SwapBazarController = function (view) { context.getLatestSearchBlock = function getLatestSearchBlock() { return (context.list && Object.keys(context.list).length > 0 && Math.max(...Object.keys(context.list).map(it => parseInt(it.split('_')[0])))) || window.getNetworkElement('deploySearchStart'); }; + + context.calculatePriceInDollars = async function calculatePriceInDollars(token) { + var ethereumPrice = await window.getEthereumPrice(); + try { + var priceInDollars = window.fromDecimals((await window.blockchainCall(window.uniswapV2Router.methods.getAmountsOut, window.toDecimals('1', token.decimals), [token.address, window.wethAddress]))[1], 18, true); + priceInDollars = parseFloat(priceInDollars) * ethereumPrice; + return priceInDollars; + } catch (e) { + } + }; }; \ No newline at end of file diff --git a/spa/swapBazar/uniswapTokenPicker.jsx b/spa/swapBazar/uniswapTokenPicker.jsx index 23af2ef..7b0e8a3 100644 --- a/spa/swapBazar/uniswapTokenPicker.jsx +++ b/spa/swapBazar/uniswapTokenPicker.jsx @@ -3,7 +3,7 @@ var UniswapTokenPicker = React.createClass({ e && e.preventDefault && e.preventDefault(true) && e.stopPropagation && e.stopPropagation(true); var key = e.currentTarget.dataset.key; var _this = this; - this.setState({ key, selected: null }, function() { + this.setState({ key, selected: null }, function () { _this.props.onChange && setTimeout(() => _this.props.onChange(null)); }); }, @@ -15,19 +15,19 @@ var UniswapTokenPicker = React.createClass({ e && e.preventDefault && e.preventDefault(true) && e.stopPropagation && e.stopPropagation(true); var _this = this; var oldTarget = e.currentTarget; - this.setState({ opened: true }, function() { + this.setState({ opened: true }, function () { _this.opened && (_this.opened.onblur = _this.opened.onblur || function onblur(e) { e && e.preventDefault && e.preventDefault(true) && e.stopPropagation && e.stopPropagation(true); e.relatedTarget && e.relatedTarget !== oldTarget && e.relatedTarget.click(); e.relatedTarget && e.relatedTarget !== oldTarget && _this.opened && _this.opened.focus(); - (!e.relatedTarget || (e.relatedTarget !== oldTarget && !e.relatedTarget.dataset.key)) && _this.setState({opened: null}); + (!e.relatedTarget || (e.relatedTarget !== oldTarget && !e.relatedTarget.dataset.key)) && _this.setState({ opened: null }); }) && _this.opened.focus(); }); }, onClick(e) { e && e.preventDefault && e.preventDefault(true) && e.stopPropagation && e.stopPropagation(true); var _this = this; - this.setState({ opened: null, key : this.getKey(), selected: parseInt(e.currentTarget.dataset.index) }, function () { + this.setState({ opened: null, key: this.getKey(), selected: parseInt(e.currentTarget.dataset.index) }, function () { _this.props.onChange && setTimeout(() => _this.props.onChange(_this.props.tokensList[_this.state.key][_this.state.selected])); }); }, @@ -35,7 +35,7 @@ var UniswapTokenPicker = React.createClass({ var key = null; try { key = (this.state && this.state.key) || Object.keys(this.props.tokensList)[0]; - } catch(e) { + } catch (e) { } return key; }, @@ -52,15 +52,20 @@ var UniswapTokenPicker = React.createClass({ )}
{thisKey &&
- {this.props.tokensList[thisKey].map((it, i) =>
  • - {this.renderInput(it, this.onClick, i)} -
  • )} + {this.props.tokensList[thisKey].map((it, i) => { + if (!it) { + return; + } + return (
  • + {this.renderInput(it, this.onClick, i)} +
  • ); + })}
    }
    ); }, renderInput(it, onClick, i) { return ( - + {it.symbol} ); }, diff --git a/spa/swapBazar/view.jsx b/spa/swapBazar/view.jsx index 1dbb0f7..7f5d919 100644 --- a/spa/swapBazar/view.jsx +++ b/spa/swapBazar/view.jsx @@ -30,13 +30,17 @@ var SwapBazar = React.createClass({ this.setState({ uniswap: null }); }, onToken(token, tokenName) { + var otherTokenPrice = (tokenName === 'input' ? 'output' : 'input') + 'Price'; var otherTokenName = (tokenName === 'input' ? 'output' : 'input') + 'Token'; var otherToken = this.state && this.state[otherTokenName]; + var tokenPrice = tokenName + 'Price'; tokenName += "Token"; var state = {}; state[tokenName] = token; + state[tokenPrice] = null; if (token && otherToken && otherToken.address === token.address) { state[otherTokenName] = null; + state[otherTokenPrice] = null; this[otherTokenName].setState({ key: null, selected: null }); } var _this = this; @@ -44,6 +48,14 @@ var SwapBazar = React.createClass({ if ((!_this.state.inputToken || !_this.state.outputToken) && _this.state.uniswap) { _this.setState({ uniswap: null }); } + if(!token) { + return; + } + _this.controller.calculatePriceInDollars(token).then(function(priceInDollars) { + var state = {}; + state[tokenPrice] = priceInDollars; + _this.setState(state); + }); }); }, toggleGrimoire(e) { @@ -82,10 +94,12 @@ var SwapBazar = React.createClass({
    Input
    Output
    Swap From 2bee5812df8e78cd734ee8d546cb213194d1cd6a Mon Sep 17 00:00:00 2001 From: alet89 Date: Wed, 26 Aug 2020 18:08:03 +0200 Subject: [PATCH 29/76] Doc 0.8 --- assets/css/style.css | 6 +++-- spa/grimoire/grimBazar.jsx | 24 +++++++++++------ spa/grimoire/grimUnifi.jsx | 53 ++++++++++++++++++++++++++++++++++---- spa/grimoire/view.jsx | 2 +- 4 files changed, 69 insertions(+), 16 deletions(-) diff --git a/assets/css/style.css b/assets/css/style.css index 4c617ea..7d6abff 100644 --- a/assets/css/style.css +++ b/assets/css/style.css @@ -171,6 +171,8 @@ footer p a, footer h5 a {color: #c7ac97; font-weight: bold;} .Boomer .CallToGrim a {background-color: #bab9b9;box-shadow: rgba(0, 0, 0, 0.01) 0px 0px 1px, rgba(0, 0, 0, 0.04) 0px 4px 8px, rgba(0, 0, 0, 0.04) 0px 16px 24px, rgba(0, 0, 0, 0.01) 0px 24px 32px;} .Boomer .maghetto {-webkit-filter: grayscale(100%); filter: grayscale(100%);} .Boomer .BoomerModeToggler {background-color: #bab9b9;box-shadow: rgba(0, 0, 0, 0.01) 0px 0px 1px, rgba(0, 0, 0, 0.04) 0px 4px 8px, rgba(0, 0, 0, 0.04) 0px 16px 24px, rgba(0, 0, 0, 0.01) 0px 24px 32px;} +.Boomer .grimoireArticle a {color: #000000; font-weight: bold;} + .RPG .UniBox, .RPG .grimoireBox {position: initial;background: rgb(33, 36, 41); border-radius: 20px; color: rgb(195, 197, 203);box-shadow: rgba(0, 0, 0, 0.01) 0px 0px 1px, rgba(0, 0, 0, 0.04) 0px 4px 8px, rgba(0, 0, 0, 0.04) 0px 16px 24px, rgba(0, 0, 0, 0.01) 0px 24px 32px;} .RPG .UniSideBox {border-radius: 20px; color: #bab9b9; width: 100%; background-color: #2b2622;box-shadow: rgba(0, 0, 0, 0.01) 0px 0px 1px, rgba(0, 0, 0, 0.04) 0px 4px 8px, rgba(0, 0, 0, 0.04) 0px 16px 24px, rgba(0, 0, 0, 0.01) 0px 24px 32px;} @@ -197,7 +199,7 @@ footer p a, footer h5 a {color: #c7ac97; font-weight: bold;} .RPG .coverMenu li a span {text-shadow: 2px 2px 2px #5d5e60;color: #bab9b9;} .RPG .CallToGrim a {background-color: #c7ac97;box-shadow: rgba(0, 0, 0, 0.01) 0px 0px 1px, rgba(0, 0, 0, 0.04) 0px 4px 8px, rgba(0, 0, 0, 0.04) 0px 16px 24px, rgba(0, 0, 0, 0.01) 0px 24px 32px;} .RPG .BoomerModeToggler {background-color: #c7ac97;box-shadow: rgba(0, 0, 0, 0.01) 0px 0px 1px, rgba(0, 0, 0, 0.04) 0px 4px 8px, rgba(0, 0, 0, 0.04) 0px 16px 24px, rgba(0, 0, 0, 0.01) 0px 24px 32px;} - +.RPG .grimoireArticle a {color: #c7ac97; font-weight: bold;} @media only screen and (min-width: 640px) { .cover {max-height: 740px; width: 100%;} @@ -224,7 +226,7 @@ footer p a, footer h5 a {color: #c7ac97; font-weight: bold;} .StableCoinTitle .StableCoinTitleIntern, .grimoireWelcome .grimoireWelcomeIntern, .grimoireBox {width: 590px; padding: 20px; border-radius: 8px; display: inline-block;} .StableCoinTitleIntern article, .grimoireWelcomeIntern article {width: 480px; display: inline-block; vertical-align: middle;} .StableCoinTitle img, .grimoireWelcome img {width: 80px; height: 80px; margin-right: 10px; vertical-align: middle; z-index: 1; position: relative;} - .grimoireWelcome .GrimImg2 {width: 70px; height: 70px; position: absolute; bottom: 10px; left: 5px; z-index: 2;} + .grimoireWelcome .GrimImg2 {width: 70px; height: 70px; position: absolute;bottom: -10px;left: -15px; z-index: 2;} footer .welcomeLinks, footer p {width: 500px; padding: 20px;} .grimoireIndex {width: 350px;} .DuGustis {position: relative;} diff --git a/spa/grimoire/grimBazar.jsx b/spa/grimoire/grimBazar.jsx index c87a253..04f88ec 100644 --- a/spa/grimoire/grimBazar.jsx +++ b/spa/grimoire/grimBazar.jsx @@ -20,17 +20,25 @@ var GrimBazar = React.createClass({

    Basics

    -

    Programmable Liquidity is an exciting feature in AMMs, but if it impacts the AMM itself, this can introduce bugs due to math complexities (like what happened with Balancer). UniFi crafting aims to achieve Programmable Liquidity, but using Uniswap as a base layer. This helps liquidity providers customize their investment, and empower new applications on top of Uniswap.

    -

    Uniswap accepts liquidity pools composed of 50:50 asset ratios. This is the most secure setup for an AMM, except for some cases. However, this setup disincentivizes liquidity provision due to the problem of impermanent losses.

    -

    To solve this problem and create new opportunities for the financial use of Uniswap pools, UniFi introduces “Crafting.” This is a new fancy way to build liquidity together, without needing to trust and know each other.

    -

    Anyone can create a Craft Order, customize the liquidity setup and deploy it by adding his or her own portion of liquidity. Anyone can then fill the remaining liquidity required to pool the liquidity in the Uniswap pool. After a pre-selected block, the first one who transacts the removal will remove and send the liquidity to all of the Order participants, based on the rules created initially.

    - +

    The UniFi Bazar unleashes the true potential of Uniswap, by enabling Ethereans to trade Index Funds, Programmable Equities and NFTs more easily than ever before.

    +
    +
    +

    Listing

    +

    Index Funds

    +

    Previously, any ERC20 Uniswap V2 pool token could be traded on Uniswap. But Index Funds—backed by multiple ERC20 tokens—could not. Until now.

    +
    On the Bazar, Ethereans can freely swap and track crypto Index Funds.
    +

    Programmable Equities

    +

    Programmable equities are a new asset class in crypto. They are the ERC20 voting tokens of Decentralized Flexible Organizations (DFOs). Holders have 100% ownership of the protocol; there is no opportunity for external manipulation.

    +
    On the Bazar, all programmable equities can be listed and traded on Uniswap.
    +

    Non-Fungible Tokens (NFTs)

    +

    ERC1155 NFTs are tokens with metadata, but at the same time have a supply. The reason they haven’t been tradable in AMMs before is due to their ‘transfer’ function. They use the ‘SafeTransferFrom’ method, instead of the ERC20 methods, ‘Transfer’ and ‘TransferFrom.’ Also, they don’t have decimals; they’re transferred using ID and Amount.

    +

    ethArt V2 will be released in November, and the Bazar will be able to synthesize ERC1155 tokens with an ERC20 (à la WETH with ETH) in the background, fundamentally reshaping the NFT market by allowing Ethereans to trade ERC1155 tokens for the first time.

    +

    Swappable ERC 1155 release

    +

    The release of ethArt V2 and swappable NFTs is schedulate for late November

    diff --git a/spa/grimoire/grimUnifi.jsx b/spa/grimoire/grimUnifi.jsx index 43e7381..fb5d28b 100644 --- a/spa/grimoire/grimUnifi.jsx +++ b/spa/grimoire/grimUnifi.jsx @@ -11,7 +11,7 @@ var GrimUnifi = React.createClass({

    The Grimoire - UniFi DFO and UniFi Token

    -
    uSD is a Stable Coin based on Uniswap Liquidity Pools Launch Dapp Minted by the magic rainbow of Uniswap stablecoin pools. Backed by the power of the Unicorn, uSD is the most secure stablecoin ever. The only way it could be destabilized is if the entire stablecoin industry crashed.
    +
    UniFi is a new Decentralized Flexible Organization (DFO) that researches and develops a responsible Decentralized Finance layer on top of Uniswap.
    @@ -19,11 +19,54 @@ var GrimUnifi = React.createClass({
    +
    +

    Basics

    +

    Thanks to the DFOhub standard, UniFi dApps are entirely independent from any off-chain entity. The $UniFi voting token is a programmable equity of the UniFi DFO; $UniFi holders hold real equity of the protocol, and rule every part of its code and assets. More at dfohub.com

    +
    +
    +

    UniFi Distribution

    +

    The total supply of $UniFi is 88,888,888, which is initially distributed as follows:

    +
      +
    1. - 36% (32,042,000) are locked in the NERV Wallet [0x25756f9C2cCeaCd787260b001F224159aB9fB97A] This is the DFOhub Operations wallet, funded by Fair Inflation.
    2. +
    3. - 40% (35,900,000) are locked in the UniFI DFO wallet [0x2578aA454b29C15c8eEF62C972Ee1ff57CD99DEf]. This pays out the liquidity staking rewards. The active reward staking contract is [0xb266252Fd70D253b4330151A96694d35e94b846c]
    4. +
    5. - 16% (14,333,333) are locked in the DFOhub wallet (owned by $buidl holders) [0x5D40c724ba3e7Ffa6a91db223368977C522BdACD]
    6. +
    +
    +
    +

    UniFi Fair Inflation

    +
    A sustainable economic model for DFO-based startups to maintain value and fund operations | UniFi version
    +

    The original whitepaper of the first fair inflation mechanism was for buidl (https://github.com/b-u-i-d-l/fair-inflation-v2)

    +

    UniFi’s fair inflation will inflate the supply by 2% (1,788,500 $UniFi) over the first year via NERV (The DFOhub Team Operations' DFO)

    +
    Inflation events will occur once a day (every 6,300 ETH Blocks) across three Uniswap pairs, for a total of 4,900 $UniFi each event:
    +
      +
    1. - Uniswap V2 $ETH/$UniFi (2695 $UniFi every day) - 55%
    2. +
    3. - Uniswap V2 $USDC/$UniFi (1470 $UniFi every day) - 30%
    4. +
    5. - Uniswap V2 $BUIDL/$UniFi (735 $UniFi every day) - 15%
    6. +
    +

    All functionalities related to this R&D will become available for every DFO as Optional Basic Functionalities, to accelerate the exploration of Programmable Equity R&D.

    +
    +
    +

    UniFi Liquidity Staking

    +

    UniFi Liquidity Stakinf is available here: https://dapp.dfohub.com/?staking=0xb266252Fd70D253b4330151A96694d35e94b846c

    +

    The UniFi Liquidity Staking Mechanism is designed to reward those who lock up Uniswap V2 liquidity for the long term.

    +

    Liquidity Staking will inflate the supply over the first year (if every tier is completely filled) by 918,000 UniFi (1% of the supply).

    +

    The Five Year tier was filled by the team in an early test, and we won’t touch the rewards for three years. When they are unlocked and redeemed, 50% of the UniFi will be sent to the UniFi wallet and 50% to the NERV operations wallet.

    +
    +
    +

    DFO Earnings

    +

    The UniFi DFO earn from:

    +
      +
    1. - The uSD positive rebalance (the trading fees of Uniswap collateralized stablecoins)
    2. +
    3. - The 0.1% in Uniswap Pool Tokens taxed by crafting Programmable Liquidity
    4. +
    +

    As an on-chain company, UniFi’s value will be backed by these earnings, and by the core of Flexible Organizations, totally ruled in code and assets by tokens, without any chance of external manipulation.

    +
    diff --git a/spa/grimoire/view.jsx b/spa/grimoire/view.jsx index fd3516a..5a6635e 100644 --- a/spa/grimoire/view.jsx +++ b/spa/grimoire/view.jsx @@ -27,7 +27,7 @@ var Grimoire = React.createClass({ Stable Coin: Uniswap State Dollar Crafting and ILO: Programmable Liquidity Bazaar: Uniswap Advanced Listing - UniFi Strategy: Token and WP + UniFi Strategy: Token and DFO
    From 07d1960cc5e0e7f90bed6e121c41517d96d0016f Mon Sep 17 00:00:00 2001 From: alet89 Date: Wed, 26 Aug 2020 20:03:50 +0200 Subject: [PATCH 30/76] pusg --- assets/css/style.css | 1 + spa/grimoire/grimUnifi.jsx | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/assets/css/style.css b/assets/css/style.css index 7d6abff..d9eb991 100644 --- a/assets/css/style.css +++ b/assets/css/style.css @@ -141,6 +141,7 @@ footer p a, footer h5 a {color: #c7ac97; font-weight: bold;} .CallToGrim a {width: 35px; height: 35px; display: inline-block; text-align: center; border-radius: 10px;} .CallToGrim a img {width: 30px; height: 30px; display: inline-block; vertical-align: center;} .BoomerModeToggler {width: 35px; height: 35px; display: inline-block; text-align: center; border-radius: 10px; position: fixed; top: 10px; right: 230px; text-decoration: none;line-height: 2;} +.explainer .BoomerModeToggler {display: none;} .Boomer .UniBox, .Boomer .grimoireBox {position: initial;background: rgb(255, 255, 255); box-shadow: rgba(0, 0, 0, 0.01) 0px 0px 1px, rgba(0, 0, 0, 0.04) 0px 4px 8px, rgba(0, 0, 0, 0.04) 0px 16px 24px, rgba(0, 0, 0, 0.01) 0px 24px 32px; border-radius: 30px; color: #000000;} diff --git a/spa/grimoire/grimUnifi.jsx b/spa/grimoire/grimUnifi.jsx index fb5d28b..aefb81f 100644 --- a/spa/grimoire/grimUnifi.jsx +++ b/spa/grimoire/grimUnifi.jsx @@ -53,7 +53,7 @@ var GrimUnifi = React.createClass({

    UniFi Liquidity Staking

    -

    UniFi Liquidity Stakinf is available here: https://dapp.dfohub.com/?staking=0xb266252Fd70D253b4330151A96694d35e94b846c

    +

    UniFi Liquidity Staking is available here: https://dapp.dfohub.com/?staking=0xb266252Fd70D253b4330151A96694d35e94b846c

    The UniFi Liquidity Staking Mechanism is designed to reward those who lock up Uniswap V2 liquidity for the long term.

    Liquidity Staking will inflate the supply over the first year (if every tier is completely filled) by 918,000 UniFi (1% of the supply).

    The Five Year tier was filled by the team in an early test, and we won’t touch the rewards for three years. When they are unlocked and redeemed, 50% of the UniFi will be sent to the UniFi wallet and 50% to the NERV operations wallet.

    From c9c25e93d1466349e16171f94a69fb4f894b485f Mon Sep 17 00:00:00 2001 From: Marco Vasapollo Date: Wed, 26 Aug 2020 17:34:40 +0200 Subject: [PATCH 31/76] Ethereum network swap --- spa/swapBazar/controller.jsx | 1 + spa/swapBazar/uniswapTokenPicker.jsx | 5 +++++ 2 files changed, 6 insertions(+) diff --git a/spa/swapBazar/controller.jsx b/spa/swapBazar/controller.jsx index 4183a35..428e24c 100644 --- a/spa/swapBazar/controller.jsx +++ b/spa/swapBazar/controller.jsx @@ -12,6 +12,7 @@ var SwapBazarController = function (view) { context.loadData = async function loadData() { await window.loadEthereumStuff(); + context.view.setState({inputToken : null, outputToken : null, inputPrice : null, outputPrice: null, uniswap: null}); try { context.view.setState({ tokensList: { diff --git a/spa/swapBazar/uniswapTokenPicker.jsx b/spa/swapBazar/uniswapTokenPicker.jsx index 7b0e8a3..f1e449d 100644 --- a/spa/swapBazar/uniswapTokenPicker.jsx +++ b/spa/swapBazar/uniswapTokenPicker.jsx @@ -1,4 +1,9 @@ var UniswapTokenPicker = React.createClass({ + getDefaultSubscriptions() { + return { + 'ethereum/update' : () => this.setState({key: null, selected : null}) + }; + }, onSectionChange(e) { e && e.preventDefault && e.preventDefault(true) && e.stopPropagation && e.stopPropagation(true); var key = e.currentTarget.dataset.key; From 3089299d878236dd81682d48bac7bdac9f40ced2 Mon Sep 17 00:00:00 2001 From: Marco Vasapollo Date: Wed, 26 Aug 2020 17:38:14 +0200 Subject: [PATCH 32/76] Wallet address link --- spa/dappMenu/view.jsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spa/dappMenu/view.jsx b/spa/dappMenu/view.jsx index 2847c70..a0102b7 100644 --- a/spa/dappMenu/view.jsx +++ b/spa/dappMenu/view.jsx @@ -80,7 +80,7 @@ var DappMenu = React.createClass({ Menu {!window.walletAddress && Connect} - {window.walletAddress && {window.shortenWord(window.walletAddress, 12)}} + {window.walletAddress && {window.shortenWord(window.walletAddress, 12)}}
    this.menu = ref} className="coverMenu" tabIndex="-1"> {this.state.menuItems.map(this.renderMenuItem)} From 20b0908f7b05c7b124bc36b1467af8c743907d34 Mon Sep 17 00:00:00 2001 From: alet89 Date: Wed, 26 Aug 2020 21:18:46 +0200 Subject: [PATCH 33/76] bazar --- assets/css/style.css | 21 ++++++++++++++++++++- spa/swapBazar/uniswapTokenPicker.jsx | 21 ++++++++++++--------- spa/swapBazar/view.jsx | 6 +++--- 3 files changed, 35 insertions(+), 13 deletions(-) diff --git a/assets/css/style.css b/assets/css/style.css index d9eb991..d550e47 100644 --- a/assets/css/style.css +++ b/assets/css/style.css @@ -142,7 +142,15 @@ footer p a, footer h5 a {color: #c7ac97; font-weight: bold;} .CallToGrim a img {width: 30px; height: 30px; display: inline-block; vertical-align: center;} .BoomerModeToggler {width: 35px; height: 35px; display: inline-block; text-align: center; border-radius: 10px; position: fixed; top: 10px; right: 230px; text-decoration: none;line-height: 2;} .explainer .BoomerModeToggler {display: none;} - +.BazTokenSelector {width: 100%; display: inline-block; margin: 10px auto; text-align: center;} +.BazTokenSelector a {padding: 10px 20px; text-decoration: none; font-weight: bold; display: inline-block; margin: 5px;} +.BazSelectorContainer {position: fixed; top: 100; left: 5%; width: 90%; overflow-y: scroll;overflow-x: hidden;} +.BazSelectorContainerClose {position: fixed; border-radius: 50%; width: 40px; height: 40px; top: 70px; left: 5px;} +.BazSelectorContainerClose a {font-size: 25px; padding: 0;} +.BazSelectorContainerMenu {display: inline-block; width: 100%;} +.BazSelectorContainerMenuintern {width: 100%;} +.BazSelectorContainerMenu li {width: 33.3%; display: inline-block; height: 32px;} +.BazSelectorContainerMenu li a {padding: 8px 0; width: 100%; margin: 0; font-size: 14px;} .Boomer .UniBox, .Boomer .grimoireBox {position: initial;background: rgb(255, 255, 255); box-shadow: rgba(0, 0, 0, 0.01) 0px 0px 1px, rgba(0, 0, 0, 0.04) 0px 4px 8px, rgba(0, 0, 0, 0.04) 0px 16px 24px, rgba(0, 0, 0, 0.01) 0px 24px 32px; border-radius: 30px; color: #000000;} .Boomer .UniSideBox {border-radius: 20px; color: #000000; width: 100%; background-color: #bab9b9;box-shadow: rgba(0, 0, 0, 0.01) 0px 0px 1px, rgba(0, 0, 0, 0.04) 0px 4px 8px, rgba(0, 0, 0, 0.04) 0px 16px 24px, rgba(0, 0, 0, 0.01) 0px 24px 32px;} @@ -173,7 +181,14 @@ footer p a, footer h5 a {color: #c7ac97; font-weight: bold;} .Boomer .maghetto {-webkit-filter: grayscale(100%); filter: grayscale(100%);} .Boomer .BoomerModeToggler {background-color: #bab9b9;box-shadow: rgba(0, 0, 0, 0.01) 0px 0px 1px, rgba(0, 0, 0, 0.04) 0px 4px 8px, rgba(0, 0, 0, 0.04) 0px 16px 24px, rgba(0, 0, 0, 0.01) 0px 24px 32px;} .Boomer .grimoireArticle a {color: #000000; font-weight: bold;} +.Boomer .BazTokenSelector a {background-color: #bab9b9; color: #000000;} +.Boomer .BazSelectorContainer {background-color: #2b2622; color: #444444;} +.Boomer .BazSelectorContainerMenu {background-color: #bab9b9;} +.Boomer .BazSelectorContainerClose {background-color: #bab9b9;} +.Boomer .BazSelectorContainerMenu .selected {background-color: #5549c9;} +.Boomer .BazSelectorContainerMenu .selected a {color: #ffffff;} +.Boomer .BazSelectorContainerMenu a {background-color: transparent;} .RPG .UniBox, .RPG .grimoireBox {position: initial;background: rgb(33, 36, 41); border-radius: 20px; color: rgb(195, 197, 203);box-shadow: rgba(0, 0, 0, 0.01) 0px 0px 1px, rgba(0, 0, 0, 0.04) 0px 4px 8px, rgba(0, 0, 0, 0.04) 0px 16px 24px, rgba(0, 0, 0, 0.01) 0px 24px 32px;} .RPG .UniSideBox {border-radius: 20px; color: #bab9b9; width: 100%; background-color: #2b2622;box-shadow: rgba(0, 0, 0, 0.01) 0px 0px 1px, rgba(0, 0, 0, 0.04) 0px 4px 8px, rgba(0, 0, 0, 0.04) 0px 16px 24px, rgba(0, 0, 0, 0.01) 0px 24px 32px;} @@ -201,6 +216,8 @@ footer p a, footer h5 a {color: #c7ac97; font-weight: bold;} .RPG .CallToGrim a {background-color: #c7ac97;box-shadow: rgba(0, 0, 0, 0.01) 0px 0px 1px, rgba(0, 0, 0, 0.04) 0px 4px 8px, rgba(0, 0, 0, 0.04) 0px 16px 24px, rgba(0, 0, 0, 0.01) 0px 24px 32px;} .RPG .BoomerModeToggler {background-color: #c7ac97;box-shadow: rgba(0, 0, 0, 0.01) 0px 0px 1px, rgba(0, 0, 0, 0.04) 0px 4px 8px, rgba(0, 0, 0, 0.04) 0px 16px 24px, rgba(0, 0, 0, 0.01) 0px 24px 32px;} .RPG .grimoireArticle a {color: #c7ac97; font-weight: bold;} +.RPG .BazTokenSelector a {background-color: #000000; color: #ffffff;} +.RPG .BazSelectorContainer {background-color: #2b2622; color: #444444;} @media only screen and (min-width: 640px) { .cover {max-height: 740px; width: 100%;} @@ -231,6 +248,7 @@ footer p a, footer h5 a {color: #c7ac97; font-weight: bold;} footer .welcomeLinks, footer p {width: 500px; padding: 20px;} .grimoireIndex {width: 350px;} .DuGustis {position: relative;} + .BazSelectorContainerMenuintern {width: 400px;} } @media only screen and (min-width: 890px) { @@ -249,5 +267,6 @@ footer p a, footer h5 a {color: #c7ac97; font-weight: bold;} .StableCoinTitle img, .grimoireWelcome img {width: 100px; height: 100px;} footer .welcomeLinks, footer p {width: 500px;} .grimoireIndex {width: 450px;} + .BazSelectorContainerMenuintern {width: 600px;} } \ No newline at end of file diff --git a/spa/swapBazar/uniswapTokenPicker.jsx b/spa/swapBazar/uniswapTokenPicker.jsx index 7b0e8a3..b008c58 100644 --- a/spa/swapBazar/uniswapTokenPicker.jsx +++ b/spa/swapBazar/uniswapTokenPicker.jsx @@ -20,7 +20,7 @@ var UniswapTokenPicker = React.createClass({ e && e.preventDefault && e.preventDefault(true) && e.stopPropagation && e.stopPropagation(true); e.relatedTarget && e.relatedTarget !== oldTarget && e.relatedTarget.click(); e.relatedTarget && e.relatedTarget !== oldTarget && _this.opened && _this.opened.focus(); - (!e.relatedTarget || (e.relatedTarget !== oldTarget && !e.relatedTarget.dataset.key)) && _this.setState({ opened: null }); + // (!e.relatedTarget || (e.relatedTarget !== oldTarget && !e.relatedTarget.dataset.key)) && _this.setState({ opened: null }); }) && _this.opened.focus(); }); }, @@ -42,14 +42,16 @@ var UniswapTokenPicker = React.createClass({ renderOpened() { var _this = this; var thisKey = this.getKey(); - return (
    this.opened = ref}> -
    + return (
    this.opened = ref}> +
    X
    -
    - {this.props.tokensList && Object.keys(this.props.tokensList).map(key =>
  • - {key} -
  • )} +
    +
    + {this.props.tokensList && Object.keys(this.props.tokensList).map(key =>
  • + {key} +
  • )} +
    {thisKey &&
    {this.props.tokensList[thisKey].map((it, i) => { @@ -77,11 +79,12 @@ var UniswapTokenPicker = React.createClass({ } return (
    {selected && this.renderInput(selected, this.open)} - {!selected && Select token...} + {!selected && Select}
    ); }, render() { - return (
    + return ( +
    {this.state && this.state.opened && this.renderOpened()} {(!this.state || !this.state.opened) && this.renderClosed()}
    ); diff --git a/spa/swapBazar/view.jsx b/spa/swapBazar/view.jsx index 7f5d919..cf243d7 100644 --- a/spa/swapBazar/view.jsx +++ b/spa/swapBazar/view.jsx @@ -78,7 +78,7 @@ var SwapBazar = React.createClass({

    The Bazar

    -
    uSD is a Stable Coin based on Uniswap Liquidity Pools More

    Here, you can mint uSD by adding liquidity to whitelisted Uniswap Stable Coin Pools or redeem anytime whitelisted Stable Coins by burning uSD.
    +
    Ancient black magic is unleashing the true power of the Unicorn. Programmable Equities, Token Indexes and NFTs (including ERC 1155 NFTs, thanks to ethArt V2) can now be swapped, on the new Bazaar DEX.
    @@ -91,12 +91,12 @@ var SwapBazar = React.createClass({
    -
    Input
    +
    From
    -
    Output
    +
    To
    } {this.state && this.state.grimoire && }
    ); From 28317d46daac7048be004dcc07d5df06e9613c2a Mon Sep 17 00:00:00 2001 From: Marco Vasapollo Date: Wed, 26 Aug 2020 21:18:28 +0200 Subject: [PATCH 35/76] Swap Bazar Query Params --- spa/swapBazar/controller.jsx | 58 +++++++++++++++++++++++++++++++++++- 1 file changed, 57 insertions(+), 1 deletion(-) diff --git a/spa/swapBazar/controller.jsx b/spa/swapBazar/controller.jsx index 428e24c..6b7026a 100644 --- a/spa/swapBazar/controller.jsx +++ b/spa/swapBazar/controller.jsx @@ -22,8 +22,64 @@ var SwapBazarController = function (view) { } }); } catch (e) { - context.loadDataOnChain(); + await context.loadDataOnChain(); } + context.readAddressBarParams(); + }; + + context.readAddressBarParams = async function readAddressBarParams() { + var token0 = window.addressBarParams.inputCurrency; + var token1 = window.addressBarParams.outputCurrency; + var uniswap = window.addressBarParams.action; + delete window.addressBarParams.token0; + delete window.addressBarParams.token1; + delete window.addressBarParams.action; + if(!token0 && !token1) { + return; + } + token0 && (token0 = window.web3.utils.toChecksumAddress(token0)); + token1 && (token1 = window.web3.utils.toChecksumAddress(token1)); + token1 === token0 && (token1 = undefined); + uniswap = token1 ? uniswap : undefined; + var selection = function selection(tokenAddress) { + if(!tokenAddress) { + return; + } + var keys = Object.keys(context.view.state.tokensList); + for(var key of keys) { + var tokens = context.view.state.tokensList[key]; + for(var selected = 0; selected < tokens.length; selected++) { + if(window.web3.utils.toChecksumAddress(tokens[selected].address) === tokenAddress) { + return { + key, + selected, + token: tokens[selected] + } + } + } + } + }; + var setState = async function setState(tokenName, tokenAddress) { + if(!tokenAddress) { + return; + } + var find = selection(tokenAddress); + if(!find) { + return; + } + var tokenPrice = tokenName + "Price"; + tokenName += "Token"; + var state = {}; + state[tokenName] = find.token; + state[tokenPrice] = await context.calculatePriceInDollars(state[tokenName]); + delete find.token; + context.view.setState(state, function() { + context.view[tokenName] && context.view[tokenName].setState(find); + }); + }; + await setState("input", token0); + await setState("output", token1); + uniswap && context.view.setState({uniswap}); }; context.loadDataOnChain = async function loadDataOnChain() { From 427066e130895fa4287ac9c7cfd696215ea83134 Mon Sep 17 00:00:00 2001 From: alet89 Date: Wed, 26 Aug 2020 21:37:21 +0200 Subject: [PATCH 36/76] container --- assets/css/style.css | 8 ++++++-- spa/swapBazar/uniswapTokenPicker.jsx | 2 +- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/assets/css/style.css b/assets/css/style.css index d550e47..5d893a3 100644 --- a/assets/css/style.css +++ b/assets/css/style.css @@ -143,14 +143,16 @@ footer p a, footer h5 a {color: #c7ac97; font-weight: bold;} .BoomerModeToggler {width: 35px; height: 35px; display: inline-block; text-align: center; border-radius: 10px; position: fixed; top: 10px; right: 230px; text-decoration: none;line-height: 2;} .explainer .BoomerModeToggler {display: none;} .BazTokenSelector {width: 100%; display: inline-block; margin: 10px auto; text-align: center;} -.BazTokenSelector a {padding: 10px 20px; text-decoration: none; font-weight: bold; display: inline-block; margin: 5px;} -.BazSelectorContainer {position: fixed; top: 100; left: 5%; width: 90%; overflow-y: scroll;overflow-x: hidden;} +.BazTokenSelector a {padding: 10px 20px; text-decoration: none; font-weight: bold; display: inline-block; margin: 5px; border-radius: 6px;} +.BazSelectorContainer {position: fixed; top: 100; left: 5%; width: 90%; overflow-y: scroll;overflow-x: hidden; min-height: 50%;} .BazSelectorContainerClose {position: fixed; border-radius: 50%; width: 40px; height: 40px; top: 70px; left: 5px;} .BazSelectorContainerClose a {font-size: 25px; padding: 0;} .BazSelectorContainerMenu {display: inline-block; width: 100%;} .BazSelectorContainerMenuintern {width: 100%;} .BazSelectorContainerMenu li {width: 33.3%; display: inline-block; height: 32px;} .BazSelectorContainerMenu li a {padding: 8px 0; width: 100%; margin: 0; font-size: 14px;} +.BazSelectorContainerObjects {width: 90%; display: inline-block; margin-top: 20px;} +.BazSelectorContainerObjects li {display: inline-block;} .Boomer .UniBox, .Boomer .grimoireBox {position: initial;background: rgb(255, 255, 255); box-shadow: rgba(0, 0, 0, 0.01) 0px 0px 1px, rgba(0, 0, 0, 0.04) 0px 4px 8px, rgba(0, 0, 0, 0.04) 0px 16px 24px, rgba(0, 0, 0, 0.01) 0px 24px 32px; border-radius: 30px; color: #000000;} .Boomer .UniSideBox {border-radius: 20px; color: #000000; width: 100%; background-color: #bab9b9;box-shadow: rgba(0, 0, 0, 0.01) 0px 0px 1px, rgba(0, 0, 0, 0.04) 0px 4px 8px, rgba(0, 0, 0, 0.04) 0px 16px 24px, rgba(0, 0, 0, 0.01) 0px 24px 32px;} @@ -248,6 +250,7 @@ footer p a, footer h5 a {color: #c7ac97; font-weight: bold;} footer .welcomeLinks, footer p {width: 500px; padding: 20px;} .grimoireIndex {width: 350px;} .DuGustis {position: relative;} + .BazSelectorContainer {width: 400px;} .BazSelectorContainerMenuintern {width: 400px;} } @@ -267,6 +270,7 @@ footer p a, footer h5 a {color: #c7ac97; font-weight: bold;} .StableCoinTitle img, .grimoireWelcome img {width: 100px; height: 100px;} footer .welcomeLinks, footer p {width: 500px;} .grimoireIndex {width: 450px;} + .BazSelectorContainer {width: 600px;} .BazSelectorContainerMenuintern {width: 600px;} } \ No newline at end of file diff --git a/spa/swapBazar/uniswapTokenPicker.jsx b/spa/swapBazar/uniswapTokenPicker.jsx index de7d3f7..f828b0c 100644 --- a/spa/swapBazar/uniswapTokenPicker.jsx +++ b/spa/swapBazar/uniswapTokenPicker.jsx @@ -58,7 +58,7 @@ var UniswapTokenPicker = React.createClass({ )}
    - {thisKey &&
    + {thisKey &&
    {this.props.tokensList[thisKey].map((it, i) => { if (!it) { return; From e60045fe096151a04ab555c773f0e2a509f8be2f Mon Sep 17 00:00:00 2001 From: alet89 Date: Wed, 26 Aug 2020 23:07:38 +0200 Subject: [PATCH 37/76] Bazar Improvements --- assets/css/style.css | 49 ++++++++++++++++++++-------- spa/swapBazar/controller.jsx | 4 +-- spa/swapBazar/uniswapTokenPicker.jsx | 6 ++-- spa/swapBazar/view.jsx | 13 +++++--- 4 files changed, 49 insertions(+), 23 deletions(-) diff --git a/assets/css/style.css b/assets/css/style.css index 5d893a3..eec155c 100644 --- a/assets/css/style.css +++ b/assets/css/style.css @@ -124,7 +124,7 @@ footer p a, footer h5 a {color: #c7ac97; font-weight: bold;} .RebalanceEmergency label span {display: inline-block; margin: 0 5px; font-size: 15px;} .RebalanceEmergencyRew {width: 100%; display: inline-block;} .coverConnectMenu:focus {border: none; outline: -webkit-focus-ring-color auto 0px;} - +.Boh {position: fixed; top: 0; left: 0; width: 100%; height: 100%; overflow: hidden; z-index: 5;} .UniTitle select, .UniTierQuantity label input {padding: 2px 5px; font-size: 15px; font-weight: bold; margin: 7px; vertical-align: middle;} .UniTitle p {font-size: 17px;margin: 7px; font-weight: normal;} @@ -144,15 +144,21 @@ footer p a, footer h5 a {color: #c7ac97; font-weight: bold;} .explainer .BoomerModeToggler {display: none;} .BazTokenSelector {width: 100%; display: inline-block; margin: 10px auto; text-align: center;} .BazTokenSelector a {padding: 10px 20px; text-decoration: none; font-weight: bold; display: inline-block; margin: 5px; border-radius: 6px;} -.BazSelectorContainer {position: fixed; top: 100; left: 5%; width: 90%; overflow-y: scroll;overflow-x: hidden; min-height: 50%;} -.BazSelectorContainerClose {position: fixed; border-radius: 50%; width: 40px; height: 40px; top: 70px; left: 5px;} +.BazSelectorContainer {position: fixed; top: 20%; left: 50%; width: 90%; overflow-y: scroll;overflow-x: hidden; height: 60%; margin: auto; z-index: 10; border-radius: 10px;} +.BazSelectorContainerClose {position: fixed; border-radius: 50%; width: 40px; height: 40px; top: 70px; left: 5px;top: 14%;left: 48%;} .BazSelectorContainerClose a {font-size: 25px; padding: 0;} .BazSelectorContainerMenu {display: inline-block; width: 100%;} .BazSelectorContainerMenuintern {width: 100%;} .BazSelectorContainerMenu li {width: 33.3%; display: inline-block; height: 32px;} -.BazSelectorContainerMenu li a {padding: 8px 0; width: 100%; margin: 0; font-size: 14px;} -.BazSelectorContainerObjects {width: 90%; display: inline-block; margin-top: 20px;} -.BazSelectorContainerObjects li {display: inline-block;} +.BazSelectorContainerMenu li a {padding: 8px 0; width: 100%; margin: 0; font-size: 13px; font-weight: bold;} +.BazSelectorContainerObjects {width: 95%; display: inline-block; margin-top: 20px; text-align: left;} +.BazSelectorContainerObjects li {display: inline-block; width: 120px; margin: 10px;word-wrap: break-word;} +.BazSelectorContainerObjects li a {font-size: 13px; font-weight: normal; padding: 3px 6px; margin: 0; border-radius: 0; display: inline-block;} +.BazSelectorContainerObjects li a img {width: 20px; height: 20px; vertical-align: middle;} +.BazSelectorContainerObjects li a p {display: inline;} +.BazzPreDescfalse {display: none;} +.BazPrice {width: 100%; text-align: center;display: inline-block; font-weight: bold;} + .Boomer .UniBox, .Boomer .grimoireBox {position: initial;background: rgb(255, 255, 255); box-shadow: rgba(0, 0, 0, 0.01) 0px 0px 1px, rgba(0, 0, 0, 0.04) 0px 4px 8px, rgba(0, 0, 0, 0.04) 0px 16px 24px, rgba(0, 0, 0, 0.01) 0px 24px 32px; border-radius: 30px; color: #000000;} .Boomer .UniSideBox {border-radius: 20px; color: #000000; width: 100%; background-color: #bab9b9;box-shadow: rgba(0, 0, 0, 0.01) 0px 0px 1px, rgba(0, 0, 0, 0.04) 0px 4px 8px, rgba(0, 0, 0, 0.04) 0px 16px 24px, rgba(0, 0, 0, 0.01) 0px 24px 32px;} @@ -184,13 +190,17 @@ footer p a, footer h5 a {color: #c7ac97; font-weight: bold;} .Boomer .BoomerModeToggler {background-color: #bab9b9;box-shadow: rgba(0, 0, 0, 0.01) 0px 0px 1px, rgba(0, 0, 0, 0.04) 0px 4px 8px, rgba(0, 0, 0, 0.04) 0px 16px 24px, rgba(0, 0, 0, 0.01) 0px 24px 32px;} .Boomer .grimoireArticle a {color: #000000; font-weight: bold;} .Boomer .BazTokenSelector a {background-color: #bab9b9; color: #000000;} -.Boomer .BazSelectorContainer {background-color: #2b2622; color: #444444;} +.Boomer .BazSelectorContainer {background-color: #ffffff; color: #444444;} +.Boomer .BazSelectorContainer:focus {border: none;} .Boomer .BazSelectorContainerMenu {background-color: #bab9b9;} .Boomer .BazSelectorContainerClose {background-color: #bab9b9;} -.Boomer .BazSelectorContainerMenu .selected {background-color: #5549c9;} -.Boomer .BazSelectorContainerMenu .selected a {color: #ffffff;} +.Boomer .BazSelectorContainerMenu .selected {background-color: #ffffff;} +.Boomer .BazSelectorContainerMenu .selected a {color: #000000;} .Boomer .BazSelectorContainerMenu a {background-color: transparent;} +.Boomer .Boh {background-color: #000000eb;} +.Boomer .BazSelectorContainerObjects li a {background-color: transparent; color: #000000; font-weight: bold;} +.Boomer .ActiveDesc {color:#000000;display: inline-block;} .RPG .UniBox, .RPG .grimoireBox {position: initial;background: rgb(33, 36, 41); border-radius: 20px; color: rgb(195, 197, 203);box-shadow: rgba(0, 0, 0, 0.01) 0px 0px 1px, rgba(0, 0, 0, 0.04) 0px 4px 8px, rgba(0, 0, 0, 0.04) 0px 16px 24px, rgba(0, 0, 0, 0.01) 0px 24px 32px;} .RPG .UniSideBox {border-radius: 20px; color: #bab9b9; width: 100%; background-color: #2b2622;box-shadow: rgba(0, 0, 0, 0.01) 0px 0px 1px, rgba(0, 0, 0, 0.04) 0px 4px 8px, rgba(0, 0, 0, 0.04) 0px 16px 24px, rgba(0, 0, 0, 0.01) 0px 24px 32px;} @@ -219,7 +229,18 @@ footer p a, footer h5 a {color: #c7ac97; font-weight: bold;} .RPG .BoomerModeToggler {background-color: #c7ac97;box-shadow: rgba(0, 0, 0, 0.01) 0px 0px 1px, rgba(0, 0, 0, 0.04) 0px 4px 8px, rgba(0, 0, 0, 0.04) 0px 16px 24px, rgba(0, 0, 0, 0.01) 0px 24px 32px;} .RPG .grimoireArticle a {color: #c7ac97; font-weight: bold;} .RPG .BazTokenSelector a {background-color: #000000; color: #ffffff;} -.RPG .BazSelectorContainer {background-color: #2b2622; color: #444444;} +.RPG .BazSelectorContainer {background-color: rgb(33, 36, 41); color: #444444;} + +.RPG .BazSelectorContainerMenu {background-color: #000000;} +.RPG .BazSelectorContainerClose {background-color: #c7ac97;} +.RPG .BazSelectorContainerMenu .selected {background-color: #c7ac97;} +.RPG .BazSelectorContainerMenu .selected a {color: #000000;} +.RPG .BazSelectorContainerMenu a {background-color: transparent;} +.RPG .Boh {background-color: #5d00aaeb;} +.RPG .BazSelectorContainerObjects li a {background-color: transparent; color: #ffffff; font-weight: bold;} +.RPG .BazSelectorContainerMenu li a {font-size: 14px;} +.RPG .BazSelectorContainerClose a {background-color: transparent; color: #000000;} +.RPG .ActiveDesc {color:#5d5e60; display: inline-block;} @media only screen and (min-width: 640px) { .cover {max-height: 740px; width: 100%;} @@ -250,8 +271,8 @@ footer p a, footer h5 a {color: #c7ac97; font-weight: bold;} footer .welcomeLinks, footer p {width: 500px; padding: 20px;} .grimoireIndex {width: 350px;} .DuGustis {position: relative;} - .BazSelectorContainer {width: 400px;} - .BazSelectorContainerMenuintern {width: 400px;} + .BazSelectorContainer {width: 70%; left: 15%;} + .BazSelectorContainerMenuintern {width: 100%;} } @media only screen and (min-width: 890px) { @@ -270,7 +291,7 @@ footer p a, footer h5 a {color: #c7ac97; font-weight: bold;} .StableCoinTitle img, .grimoireWelcome img {width: 100px; height: 100px;} footer .welcomeLinks, footer p {width: 500px;} .grimoireIndex {width: 450px;} - .BazSelectorContainer {width: 600px;} - .BazSelectorContainerMenuintern {width: 600px;} + .BazSelectorContainer {width: 50%; left: 25%;} + .BazSelectorContainerMenuintern {width: 100%;} } \ No newline at end of file diff --git a/spa/swapBazar/controller.jsx b/spa/swapBazar/controller.jsx index 6b7026a..dfdcfeb 100644 --- a/spa/swapBazar/controller.jsx +++ b/spa/swapBazar/controller.jsx @@ -16,7 +16,7 @@ var SwapBazarController = function (view) { try { context.view.setState({ tokensList: { - "Programmable Equities": (await window.AJAXRequest(window.context.programmableEquitiesURL)).tokens.map(it => it.chainId === window.networkId && it), + "Prog. Equities": (await window.AJAXRequest(window.context.programmableEquitiesURL)).tokens.map(it => it.chainId === window.networkId && it), "Tokens": (await window.AJAXRequest(window.context.uniswapTokensURL)).tokens.map(it => it.chainId === window.networkId && it), Indexes: (await window.AJAXRequest(window.context.indexesURL)).tokens.map(it => it.chainId === window.networkId && it) } @@ -111,7 +111,7 @@ var SwapBazarController = function (view) { await context.recursiveLoadPair(indexes); var tokensList = { - "Programmable Equities": programmableEquities, + "Prog. Equities": programmableEquities, "Tokens": uniswapTokens, Indexes: Object.values(indexes) }; diff --git a/spa/swapBazar/uniswapTokenPicker.jsx b/spa/swapBazar/uniswapTokenPicker.jsx index 67168ae..aa92cc6 100644 --- a/spa/swapBazar/uniswapTokenPicker.jsx +++ b/spa/swapBazar/uniswapTokenPicker.jsx @@ -71,9 +71,10 @@ var UniswapTokenPicker = React.createClass({
    ); }, renderInput(it, onClick, i) { + var key = this.getKey(); return ( - - {it.symbol} + {key !== "Indexes" && } +

    {it.symbol}

    ); }, renderClosed() { @@ -91,6 +92,7 @@ var UniswapTokenPicker = React.createClass({ return (
    {this.state && this.state.opened && this.renderOpened()} + {this.state && this.state.opened &&
    } {(!this.state || !this.state.opened) && this.renderClosed()}
    ); } diff --git a/spa/swapBazar/view.jsx b/spa/swapBazar/view.jsx index 01b12af..8b0b1f8 100644 --- a/spa/swapBazar/view.jsx +++ b/spa/swapBazar/view.jsx @@ -97,17 +97,20 @@ var SwapBazar = React.createClass({
    From
    To
    - Swap - Add to Pool - Remove from Pool +
    + Swap + Add Liquidity + Remove Liquidity +

    Select Tiers to Swap or Manage Liquidity

    +
    } {this.state && this.state.grimoire && }
    ); From 1d37b54eb093923949028994271c3db3c3246bbc Mon Sep 17 00:00:00 2001 From: alet89 Date: Wed, 26 Aug 2020 23:25:44 +0200 Subject: [PATCH 38/76] f --- assets/css/style.css | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets/css/style.css b/assets/css/style.css index eec155c..7f3a098 100644 --- a/assets/css/style.css +++ b/assets/css/style.css @@ -236,7 +236,7 @@ footer p a, footer h5 a {color: #c7ac97; font-weight: bold;} .RPG .BazSelectorContainerMenu .selected {background-color: #c7ac97;} .RPG .BazSelectorContainerMenu .selected a {color: #000000;} .RPG .BazSelectorContainerMenu a {background-color: transparent;} -.RPG .Boh {background-color: #5d00aaeb;} +.RPG .Boh {background-color: #c7ac97d6;} .RPG .BazSelectorContainerObjects li a {background-color: transparent; color: #ffffff; font-weight: bold;} .RPG .BazSelectorContainerMenu li a {font-size: 14px;} .RPG .BazSelectorContainerClose a {background-color: transparent; color: #000000;} From 71a57f6cf4707a89aa5be43317eb703d78be73b3 Mon Sep 17 00:00:00 2001 From: Marco Vasapollo Date: Wed, 26 Aug 2020 22:20:13 +0200 Subject: [PATCH 39/76] Link Fixes --- spa/dappMenu/view.jsx | 22 +++++++++++++++++++--- spa/explainer/view.jsx | 14 +++++++------- spa/grimoire/view.jsx | 16 +++++++++++++++- 3 files changed, 41 insertions(+), 11 deletions(-) diff --git a/spa/dappMenu/view.jsx b/spa/dappMenu/view.jsx index a0102b7..a126523 100644 --- a/spa/dappMenu/view.jsx +++ b/spa/dappMenu/view.jsx @@ -18,10 +18,22 @@ var DappMenu = React.createClass({ icon: "m4" }, { title: "Liquidity Crafting", - icon: "m2" + icon: "m2", + props : { + onClick: () => this.emit("section/change", "grimoire", { + href : "#grimCraft" + }), + href: "#grimCraft" + } }, { title: "Liquidity Offering", - icon: "m5" + icon: "m5", + props : { + onClick: () => this.emit("section/change", "grimoire", { + href : "#grimCraft" + }), + href: "#grimCraft" + } }, { title: "Swap Bazar", icon: "m1" @@ -30,7 +42,11 @@ var DappMenu = React.createClass({ icon: "m0" }, { title: "Github", - icon: "m3" + icon: "m3", + props : { + href: "https://github.com/b-u-i-d-l/unifi", + target: "_blank" + } }] }; }, diff --git a/spa/explainer/view.jsx b/spa/explainer/view.jsx index 3b02904..c6a36d1 100644 --- a/spa/explainer/view.jsx +++ b/spa/explainer/view.jsx @@ -1,18 +1,18 @@ var Explainer = React.createClass({ renderExStableCoin() { - return this.renderInput("ExStableCoin", "assets/img/exp1.png", "a", "InfoButton", "a", "dappButton", "More", "Launch Dapp", "A Stable Coin to Pool Them All", "Uniswap State Dollar (uSD) is a new stablecoin minted by the magic rainbow of Uniswap stablecoin pools. Backed by the power of the Unicorn, uSD is the most secure stablecoin ever. The only way it could be destabilized is if the entire stablecoin industry crashed.", undefined, () => this.emit('section/change', 'stableCoin')); + return this.renderInput("ExStableCoin", "assets/img/exp1.png", "a", "InfoButton", "a", "dappButton", "More", "Launch Dapp", "A Stable Coin to Pool Them All", "Uniswap State Dollar (uSD) is a new stablecoin minted by the magic rainbow of Uniswap stablecoin pools. Backed by the power of the Unicorn, uSD is the most secure stablecoin ever. The only way it could be destabilized is if the entire stablecoin industry crashed.", () => this.emit('section/change', 'grimoire', {href: "#grimuSD"}), () => this.emit('section/change', 'stableCoin')); }, renderExCrafting() { - return this.renderInput("ExCrafting", "assets/img/exp0.png", "a", "InfoButton", "a", "soonButton", "More", "Coming Soon", "Crafting Programmable Liquidity", "Craft makes it possible to provide liquidity that is programmable with advanced rules. Using Unicorn magic, pools can balance tokens diversely with unprecedented security."); + return this.renderInput("ExCrafting", "assets/img/exp0.png", "a", "InfoButton", "a", "soonButton", "More", "Coming Soon", "Crafting Programmable Liquidity", "Craft makes it possible to provide liquidity that is programmable with advanced rules. Using Unicorn magic, pools can balance tokens diversely with unprecedented security.", () => this.emit('section/change', 'grimoire', {href: "#grimCraft"})); }, renderExIlo() { - return this.renderInput("ExIlo", "assets/img/exp4.png", "a", "InfoButton", "a", "soonButton", "More", "Coming Soon", "ILOs Offering Tokens for Liquidity", "The Initial Liquidity Offering (ILO) is a new way for startups to provide that liquidity. By using Craft, ILOs offer total security against Sniper Bots, a new villain in the Unicorn Story."); + return this.renderInput("ExIlo", "assets/img/exp4.png", "a", "InfoButton", "a", "soonButton", "More", "Coming Soon", "ILOs Offering Tokens for Liquidity", "The Initial Liquidity Offering (ILO) is a new way for startups to provide that liquidity. By using Craft, ILOs offer total security against Sniper Bots, a new villain in the Unicorn Story.", () => this.emit('section/change', 'grimoire', {href: "#grimCraft"})); }, renderExDex() { - return this.renderInput("ExDex", "assets/img/exp3.png", "a", "InfoButton", "a", "dappButton", "More", "Launch Dapp", "Swap More Than Just Tokens", "Ancient black magic is unleashing the true power of the Unicorn. Programmable Equities, Token Indexes and NFTs (including ERC 1155 NFTs, thanks to ethArt V2) can now be swapped, on the new Bazaar DEX.", undefined, () => this.emit('section/change', 'swapBazar')); + return this.renderInput("ExDex", "assets/img/exp3.png", "a", "InfoButton", "a", "dappButton", "More", "Launch Dapp", "Swap More Than Just Tokens", "Ancient black magic is unleashing the true power of the Unicorn. Programmable Equities, Token Indexes and NFTs (including ERC 1155 NFTs, thanks to ethArt V2) can now be swapped, on the new Bazaar DEX.", () => this.emit('section/change', 'grimoire', {href: "#grimBaz"}), () => this.emit('section/change', 'swapBazar')); }, renderExGrimoire() { - return this.renderInput("ExGrimoire", "assets/img/exp2.png", "a", "readButton", "a", "gitButton", "Read", "Github", "Unicorn Magic For Dummies", "The Official guide for using Uniswap Unicorn magic. Grimoire, the best selling book of 2020, is prescribed by all the top wizard Universities, and won this years' Booker Prize."); + return this.renderInput("ExGrimoire", "assets/img/exp2.png", "a", "readButton", "a", "gitButton", "Read", "Github", "Unicorn Magic For Dummies", "The Official guide for using Uniswap Unicorn magic. Grimoire, the best selling book of 2020, is prescribed by all the top wizard Universities, and won this years' Booker Prize.", () => this.emit('section/change', 'Grimoire'), "https://github.com/b-u-i-d-l/unifi"); }, renderInput(expFeature, featureIllustration, featureActionA, featureActionAStyle, featureActionB, featureActionBStyle, featureBtnA, featureBtnB, featureTitle, featureDesc, actionA, actionB) { return ( @@ -25,8 +25,8 @@ var Explainer = React.createClass({

    {featureTitle}

    {featureDesc}

    diff --git a/spa/grimoire/view.jsx b/spa/grimoire/view.jsx index 5a6635e..998c3b0 100644 --- a/spa/grimoire/view.jsx +++ b/spa/grimoire/view.jsx @@ -6,7 +6,21 @@ var Grimoire = React.createClass({ 'spa/grimoire/grimBazar.jsx', 'spa/grimoire/grimUnifi.jsx' ], - + componentDidMount() { + if(!this.props.href) { + return; + } + var href = this.props.href; + setTimeout(function() { + var host = window.location.protocol; + host += "//"; + host += window.location.hostname; + window.location.port && (host += (":" + window.location.port)); + host +="/"; + host += href; + window.location.href = host; + }, 200); + }, render() { return (
    From dc8e65976205b6d0cdd3faea6117c12a77065f67 Mon Sep 17 00:00:00 2001 From: Marco Vasapollo Date: Wed, 26 Aug 2020 23:23:04 +0200 Subject: [PATCH 40/76] Price Fixup --- spa/swapBazar/controller.jsx | 5 ++++- spa/swapBazar/view.jsx | 10 +++++----- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/spa/swapBazar/controller.jsx b/spa/swapBazar/controller.jsx index dfdcfeb..e7d2fd4 100644 --- a/spa/swapBazar/controller.jsx +++ b/spa/swapBazar/controller.jsx @@ -215,8 +215,11 @@ var SwapBazarController = function (view) { try { var priceInDollars = window.fromDecimals((await window.blockchainCall(window.uniswapV2Router.methods.getAmountsOut, window.toDecimals('1', token.decimals), [token.address, window.wethAddress]))[1], 18, true); priceInDollars = parseFloat(priceInDollars) * ethereumPrice; - return priceInDollars; + priceInDollars = window.numberToString(priceInDollars); + var priceString = window.formatMoney(priceInDollars, 4); + return priceString === '0' ? priceInDollars : priceString; } catch (e) { + return "notFound"; } }; }; \ No newline at end of file diff --git a/spa/swapBazar/view.jsx b/spa/swapBazar/view.jsx index 8b0b1f8..a902749 100644 --- a/spa/swapBazar/view.jsx +++ b/spa/swapBazar/view.jsx @@ -97,18 +97,18 @@ var SwapBazar = React.createClass({
    From
    To
    - Swap - Add Liquidity - Remove Liquidity + Swap + Add Liquidity + Remove Liquidity

    Select Tiers to Swap or Manage Liquidity

    } From 2af019fec69f220f18dad906453c0bd01628db4b Mon Sep 17 00:00:00 2001 From: alet89 Date: Thu, 27 Aug 2020 00:00:32 +0200 Subject: [PATCH 41/76] bazar --- assets/css/style.css | 17 ++++++++++++++--- spa/swapBazar/view.jsx | 14 +++++++++----- 2 files changed, 23 insertions(+), 8 deletions(-) diff --git a/assets/css/style.css b/assets/css/style.css index 7f3a098..be3c47b 100644 --- a/assets/css/style.css +++ b/assets/css/style.css @@ -156,8 +156,14 @@ footer p a, footer h5 a {color: #c7ac97; font-weight: bold;} .BazSelectorContainerObjects li a {font-size: 13px; font-weight: normal; padding: 3px 6px; margin: 0; border-radius: 0; display: inline-block;} .BazSelectorContainerObjects li a img {width: 20px; height: 20px; vertical-align: middle;} .BazSelectorContainerObjects li a p {display: inline;} -.BazzPreDescfalse {display: none;} +.BazzPreDescDisabled {display: none;} .BazPrice {width: 100%; text-align: center;display: inline-block; font-weight: bold;} +.StableITBTNDisabled, .StableITBTNFDisabled {display: none;} +.StableITBTNActive, .StableITBTNFActive {display: inline-block;} +.StableITBTNFActive {font-size: 13px; padding: 5px 9px; margin-top: 5px;} +.ArrivaUniswap {position: fixed; width: 100%; height: 100%; overflow: hidden; z-index: 10;left: 0;top: 0;} +.ArrivaUniswap img {width: 40%; position: absolute; left: 30%; top: 150px;} +.ArrivaUniswapQuelloVero iframe {position: fixed; width: 100%; height: 100%; overflow: hidden; z-index: 10;left: 0;top: 0;z-index: 9;} .Boomer .UniBox, .Boomer .grimoireBox {position: initial;background: rgb(255, 255, 255); box-shadow: rgba(0, 0, 0, 0.01) 0px 0px 1px, rgba(0, 0, 0, 0.04) 0px 4px 8px, rgba(0, 0, 0, 0.04) 0px 16px 24px, rgba(0, 0, 0, 0.01) 0px 24px 32px; border-radius: 30px; color: #000000;} @@ -192,7 +198,6 @@ footer p a, footer h5 a {color: #c7ac97; font-weight: bold;} .Boomer .BazTokenSelector a {background-color: #bab9b9; color: #000000;} .Boomer .BazSelectorContainer {background-color: #ffffff; color: #444444;} .Boomer .BazSelectorContainer:focus {border: none;} - .Boomer .BazSelectorContainerMenu {background-color: #bab9b9;} .Boomer .BazSelectorContainerClose {background-color: #bab9b9;} .Boomer .BazSelectorContainerMenu .selected {background-color: #ffffff;} @@ -201,6 +206,10 @@ footer p a, footer h5 a {color: #c7ac97; font-weight: bold;} .Boomer .Boh {background-color: #000000eb;} .Boomer .BazSelectorContainerObjects li a {background-color: transparent; color: #000000; font-weight: bold;} .Boomer .ActiveDesc {color:#000000;display: inline-block;} +.Boomer .StableITBTNActive {background-color: #b030df;} +.Boomer .StableITBTNFActive {background-color: #5549c9;} +.RPG .ArrivaUniswap {background-color: #ffffff;} + .RPG .UniBox, .RPG .grimoireBox {position: initial;background: rgb(33, 36, 41); border-radius: 20px; color: rgb(195, 197, 203);box-shadow: rgba(0, 0, 0, 0.01) 0px 0px 1px, rgba(0, 0, 0, 0.04) 0px 4px 8px, rgba(0, 0, 0, 0.04) 0px 16px 24px, rgba(0, 0, 0, 0.01) 0px 24px 32px;} .RPG .UniSideBox {border-radius: 20px; color: #bab9b9; width: 100%; background-color: #2b2622;box-shadow: rgba(0, 0, 0, 0.01) 0px 0px 1px, rgba(0, 0, 0, 0.04) 0px 4px 8px, rgba(0, 0, 0, 0.04) 0px 16px 24px, rgba(0, 0, 0, 0.01) 0px 24px 32px;} @@ -230,7 +239,6 @@ footer p a, footer h5 a {color: #c7ac97; font-weight: bold;} .RPG .grimoireArticle a {color: #c7ac97; font-weight: bold;} .RPG .BazTokenSelector a {background-color: #000000; color: #ffffff;} .RPG .BazSelectorContainer {background-color: rgb(33, 36, 41); color: #444444;} - .RPG .BazSelectorContainerMenu {background-color: #000000;} .RPG .BazSelectorContainerClose {background-color: #c7ac97;} .RPG .BazSelectorContainerMenu .selected {background-color: #c7ac97;} @@ -241,6 +249,9 @@ footer p a, footer h5 a {color: #c7ac97; font-weight: bold;} .RPG .BazSelectorContainerMenu li a {font-size: 14px;} .RPG .BazSelectorContainerClose a {background-color: transparent; color: #000000;} .RPG .ActiveDesc {color:#5d5e60; display: inline-block;} +.RPG .StableITBTNActive {background-color: #5549c9;} +.RPG .StableITBTNFActive {background-color: #c7ac97; color: #1a1a1a;} +.RPG .ArrivaUniswap {background-color: #e3d2c2;} @media only screen and (min-width: 640px) { .cover {max-height: 740px; width: 100%;} diff --git a/spa/swapBazar/view.jsx b/spa/swapBazar/view.jsx index a902749..888033b 100644 --- a/spa/swapBazar/view.jsx +++ b/spa/swapBazar/view.jsx @@ -85,9 +85,13 @@ var SwapBazar = React.createClass({
    - {this.state && this.state.uniswap && this.state.inputToken && this.state.outputToken &&
    + {this.state && this.state.uniswap && this.state.inputToken && this.state.outputToken && +
    X +
    + +
    } {(!this.state || !this.state.tokensList) && } {this.state && this.state.tokensList &&
    @@ -106,10 +110,10 @@ var SwapBazar = React.createClass({
    - Swap - Add Liquidity - Remove Liquidity -

    Select Tiers to Swap or Manage Liquidity

    + Swap

    + Add Liquidity + Remove Liquidity +

    Select Tiers to Swap or Manage Liquidity

    } {this.state && this.state.grimoire && } From 289c4106dea8f0cbe773217c76842e3fbc09376c Mon Sep 17 00:00:00 2001 From: Marco Vasapollo Date: Thu, 27 Aug 2020 00:22:06 +0200 Subject: [PATCH 42/76] Loader Timeout --- spa/swapBazar/view.jsx | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/spa/swapBazar/view.jsx b/spa/swapBazar/view.jsx index 888033b..3bbace5 100644 --- a/spa/swapBazar/view.jsx +++ b/spa/swapBazar/view.jsx @@ -65,6 +65,12 @@ var SwapBazar = React.createClass({ renderUniswapLink() { return window.context[this.state.uniswap === 'swap' ? "uniswapDappLinkTemplate" : "uniswapDappLinkTemplatePool"].format(this.state.uniswap, this.state.inputToken.address, this.state.outputToken.address); }, + componentDidUpdate() { + var _this = this; + _this.state && _this.state.uniswap && _this.uniswapLoader && setTimeout(function() { + $(_this.uniswapLoader).css('display', 'none'); + }, 2000); + }, render() { return (
    @@ -89,7 +95,7 @@ var SwapBazar = React.createClass({
    X -
    +
    this.uniswapLoader = ref} className="ArrivaUniswap">
    } From 9ed801362e0284387864a1852f78b0bdf9146fee Mon Sep 17 00:00:00 2001 From: alet89 Date: Thu, 27 Aug 2020 00:23:18 +0200 Subject: [PATCH 43/76] e --- assets/css/style.css | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets/css/style.css b/assets/css/style.css index be3c47b..5969413 100644 --- a/assets/css/style.css +++ b/assets/css/style.css @@ -162,7 +162,7 @@ footer p a, footer h5 a {color: #c7ac97; font-weight: bold;} .StableITBTNActive, .StableITBTNFActive {display: inline-block;} .StableITBTNFActive {font-size: 13px; padding: 5px 9px; margin-top: 5px;} .ArrivaUniswap {position: fixed; width: 100%; height: 100%; overflow: hidden; z-index: 10;left: 0;top: 0;} -.ArrivaUniswap img {width: 40%; position: absolute; left: 30%; top: 150px;} +.ArrivaUniswap img {width: 30%; position: absolute; left: 35%; top: 150px;} .ArrivaUniswapQuelloVero iframe {position: fixed; width: 100%; height: 100%; overflow: hidden; z-index: 10;left: 0;top: 0;z-index: 9;} From 15ac8138f99d6431df45762c5c8c94670a14d4b6 Mon Sep 17 00:00:00 2001 From: Marco Vasapollo Date: Thu, 27 Aug 2020 00:34:30 +0200 Subject: [PATCH 44/76] Uniswap Dark Mode --- data/context.json | 4 ++-- spa/swapBazar/view.jsx | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/data/context.json b/data/context.json index 4b87e19..3f59ec4 100644 --- a/data/context.json +++ b/data/context.json @@ -10,8 +10,8 @@ "coingeckoEthereumPriceURL": "https://api.coingecko.com/api/v3/coins/markets?vs_currency=usd&ids=ethereum", "coingeckoEthereumPriceRequestInterval": 600000, "trustwalletImgURLTemplate": "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/{0}/logo.png", - "uniswapDappLinkTemplate" : "https://app.uniswap.org/#/{0}?inputCurrency={1}&outputCurrency={2}", - "uniswapDappLinkTemplatePool" : "https://app.uniswap.org/#/{0}/{1}-{2}", + "uniswapDappLinkTemplate" : "https://app.uniswap.org/#/{0}?inputCurrency={1}&outputCurrency={2}&theme={3}", + "uniswapDappLinkTemplatePool" : "https://app.uniswap.org/#/{0}/{1}-{2}?theme={3}", "uniswapInfoLinkTemplate" : "https://uniswap.info/token/{0}", "stableCoinAddressRopsten" : "0x0407fb98ae1972a61f544fe41335eb1213f8f372", "stableCoinAddress" : "0x04C2d7C0712089a61C52A315FCe8F28a55F34DFa", diff --git a/spa/swapBazar/view.jsx b/spa/swapBazar/view.jsx index 3bbace5..5cb829c 100644 --- a/spa/swapBazar/view.jsx +++ b/spa/swapBazar/view.jsx @@ -63,7 +63,7 @@ var SwapBazar = React.createClass({ this.setState({ grimoire: !(this.state && this.state.grimoire) }); }, renderUniswapLink() { - return window.context[this.state.uniswap === 'swap' ? "uniswapDappLinkTemplate" : "uniswapDappLinkTemplatePool"].format(this.state.uniswap, this.state.inputToken.address, this.state.outputToken.address); + return window.context[this.state.uniswap === 'swap' ? "uniswapDappLinkTemplate" : "uniswapDappLinkTemplatePool"].format(this.state.uniswap, this.state.inputToken.address, this.state.outputToken.address, window.localStorage.boomerMode === 'true' ? 'light' : 'dark'); }, componentDidUpdate() { var _this = this; From 409648b8ec7fd8aea2337fdb35f696f1f34d535e Mon Sep 17 00:00:00 2001 From: alet89 Date: Thu, 27 Aug 2020 00:39:24 +0200 Subject: [PATCH 45/76] Uniswap --- assets/css/style.css | 9 ++++++--- spa/swapBazar/view.jsx | 2 +- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/assets/css/style.css b/assets/css/style.css index 5969413..0bd9545 100644 --- a/assets/css/style.css +++ b/assets/css/style.css @@ -161,9 +161,10 @@ footer p a, footer h5 a {color: #c7ac97; font-weight: bold;} .StableITBTNDisabled, .StableITBTNFDisabled {display: none;} .StableITBTNActive, .StableITBTNFActive {display: inline-block;} .StableITBTNFActive {font-size: 13px; padding: 5px 9px; margin-top: 5px;} -.ArrivaUniswap {position: fixed; width: 100%; height: 100%; overflow: hidden; z-index: 10;left: 0;top: 0;} +.ArrivaUniswap {position: fixed; width: 80%; height: 80%; overflow: hidden; z-index: 10;left: 10%;top: 10%;border: none;border-radius: 35px;} .ArrivaUniswap img {width: 30%; position: absolute; left: 35%; top: 150px;} -.ArrivaUniswapQuelloVero iframe {position: fixed; width: 100%; height: 100%; overflow: hidden; z-index: 10;left: 0;top: 0;z-index: 9;} +.ArrivaUniswapQuelloVero iframe {position: fixed;width: 80%;height: 80%;overflow: hidden;left: 10%;top: 10%;z-index: 9;border: none;border-radius: 35px;} +.SeneVaUniswap {position: fixed; top: 10px; left: 50%; border-radius: 50%; width: 40px; height: 40px; line-height: 2.5; font: 12px; font-weight: bold; text-decoration: none;} .Boomer .UniBox, .Boomer .grimoireBox {position: initial;background: rgb(255, 255, 255); box-shadow: rgba(0, 0, 0, 0.01) 0px 0px 1px, rgba(0, 0, 0, 0.04) 0px 4px 8px, rgba(0, 0, 0, 0.04) 0px 16px 24px, rgba(0, 0, 0, 0.01) 0px 24px 32px; border-radius: 30px; color: #000000;} @@ -208,7 +209,8 @@ footer p a, footer h5 a {color: #c7ac97; font-weight: bold;} .Boomer .ActiveDesc {color:#000000;display: inline-block;} .Boomer .StableITBTNActive {background-color: #b030df;} .Boomer .StableITBTNFActive {background-color: #5549c9;} -.RPG .ArrivaUniswap {background-color: #ffffff;} +.Boomer .ArrivaUniswap {background-color: #ffffff;} +.Boomer .SeneVaUniswap {background-color: #ffffff; color: #000000;} .RPG .UniBox, .RPG .grimoireBox {position: initial;background: rgb(33, 36, 41); border-radius: 20px; color: rgb(195, 197, 203);box-shadow: rgba(0, 0, 0, 0.01) 0px 0px 1px, rgba(0, 0, 0, 0.04) 0px 4px 8px, rgba(0, 0, 0, 0.04) 0px 16px 24px, rgba(0, 0, 0, 0.01) 0px 24px 32px;} @@ -252,6 +254,7 @@ footer p a, footer h5 a {color: #c7ac97; font-weight: bold;} .RPG .StableITBTNActive {background-color: #5549c9;} .RPG .StableITBTNFActive {background-color: #c7ac97; color: #1a1a1a;} .RPG .ArrivaUniswap {background-color: #e3d2c2;} +.RPG .SeneVaUniswap {background-color: #e3d2c2; color: #000000;} @media only screen and (min-width: 640px) { .cover {max-height: 740px; width: 100%;} diff --git a/spa/swapBazar/view.jsx b/spa/swapBazar/view.jsx index 3bbace5..a0bbe80 100644 --- a/spa/swapBazar/view.jsx +++ b/spa/swapBazar/view.jsx @@ -93,7 +93,7 @@ var SwapBazar = React.createClass({
    {this.state && this.state.uniswap && this.state.inputToken && this.state.outputToken &&
    - X + X
    this.uniswapLoader = ref} className="ArrivaUniswap"> From fe549d17c130fc93c6e266f76d9e8f3153c1cee0 Mon Sep 17 00:00:00 2001 From: Marco Vasapollo Date: Thu, 27 Aug 2020 00:46:58 +0200 Subject: [PATCH 46/76] Delete More Link --- spa/stableCoin/view.jsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spa/stableCoin/view.jsx b/spa/stableCoin/view.jsx index 9f03643..7ceed99 100644 --- a/spa/stableCoin/view.jsx +++ b/spa/stableCoin/view.jsx @@ -146,7 +146,7 @@ var StableCoin = React.createClass({

    Uniswap State Dollar

    -
    uSD is a Stable Coin based on Uniswap Liquidity Pools More

    Here, you can mint uSD by adding liquidity to whitelisted Uniswap Stable Coin Pools or redeem anytime whitelisted Stable Coins by burning uSD.
    +
    uSD is a Stable Coin based on Uniswap Liquidity Pools
    Here, you can mint uSD by adding liquidity to whitelisted Uniswap Stable Coin Pools or redeem anytime whitelisted Stable Coins by burning uSD.
    From 15790544b0ef9c1c23dfa41dd46a7c27f480c84f Mon Sep 17 00:00:00 2001 From: alet89 Date: Thu, 27 Aug 2020 11:09:24 +0200 Subject: [PATCH 47/76] Grimoire Finished --- spa/grimoire/grimBazar.jsx | 6 ++-- spa/grimoire/grimCrafting.jsx | 61 +++++++++++++++++++---------------- spa/grimoire/grimUnifi.jsx | 22 ++++++------- spa/grimoire/grimuSD.jsx | 39 +++++++++++++--------- 4 files changed, 70 insertions(+), 58 deletions(-) diff --git a/spa/grimoire/grimBazar.jsx b/spa/grimoire/grimBazar.jsx index 04f88ec..d948daa 100644 --- a/spa/grimoire/grimBazar.jsx +++ b/spa/grimoire/grimBazar.jsx @@ -10,7 +10,7 @@ var GrimBazar = React.createClass({
    -

    The Grimoire - Bazar

    +

    The Grimoire - The Bazar

    Ancient black magic is unleashing the true power of the Unicorn. Programmable Equities, Token Indexes and NFTs (including ERC 1155 NFTs, thanks to ethArt V2) can now be swapped, on the new Bazaar DEX.
    @@ -36,9 +36,9 @@ var GrimBazar = React.createClass({
    On the Bazar, all programmable equities can be listed and traded on Uniswap.

    Non-Fungible Tokens (NFTs)

    ERC1155 NFTs are tokens with metadata, but at the same time have a supply. The reason they haven’t been tradable in AMMs before is due to their ‘transfer’ function. They use the ‘SafeTransferFrom’ method, instead of the ERC20 methods, ‘Transfer’ and ‘TransferFrom.’ Also, they don’t have decimals; they’re transferred using ID and Amount.

    -

    ethArt V2 will be released in November, and the Bazar will be able to synthesize ERC1155 tokens with an ERC20 (à la WETH with ETH) in the background, fundamentally reshaping the NFT market by allowing Ethereans to trade ERC1155 tokens for the first time.

    +

    ethArt V2 will be released in November, and the Bazar will be able to synthesize ERC1155 tokens with an ERC20 (à la WETH with ETH) in the background, fundamentally reshaping the NFT market by allowing Ethereans to trade ERC1155 tokens for the first time.

    Swappable ERC 1155 release

    -

    The release of ethArt V2 and swappable NFTs is schedulate for late November

    +

    The release of ethArt V2 and swappable NFTs is scheduled for late November using ethArt V2

    diff --git a/spa/grimoire/grimCrafting.jsx b/spa/grimoire/grimCrafting.jsx index bfe9e51..6b531f1 100644 --- a/spa/grimoire/grimCrafting.jsx +++ b/spa/grimoire/grimCrafting.jsx @@ -29,47 +29,52 @@ var GrimCrafting = React.createClass({

    Basics

    -

    Programmable Liquidity is an exciting feature in AMMs, but if it impacts the AMM itself, this can introduce bugs due to math complexities (like what happened with Balancer). UniFi crafting aims to achieve Programmable Liquidity, but using Uniswap as a base layer. This helps liquidity providers customize their investment, and empower new applications on top of Uniswap.

    -

    Uniswap accepts liquidity pools composed of 50:50 asset ratios. This is the most secure setup for an AMM, except for some cases. However, this setup disincentivizes liquidity provision due to the problem of impermanent losses.

    -

    To solve this problem and create new opportunities for the financial use of Uniswap pools, UniFi introduces “Crafting.” This is a new fancy way to build liquidity together, without needing to trust and know each other.

    -

    Anyone can create a Craft Order, customize the liquidity setup and deploy it by adding his or her own portion of liquidity. Anyone can then fill the remaining liquidity required to pool the liquidity in the Uniswap pool. After a pre-selected block, the first one who transacts the removal will remove and send the liquidity to all of the Order participants, based on the rules created initially.

    +

    Programmable liquidity is an exciting new feature in AMMs (Automated Market Makers). However, if not applied correctly, it can actually be a security hole for bugs, due to math complexities (as we saw with Balancer recently).

    +

    UniFi Crafting resolves this by offering programmable liquidity, but with Uniswap as a base layer, taking advantage of its secure and decentralized core. This also helps liquidity providers customize their investments, and empowers new applications on top of Uniswap.

    +

    How Does It Work?

    +

    Uniswap allows for liquidity pools composed of 50:50 asset ratios. This is usually the most secure setup for an AMM, but disincentivizes liquidity provision by incurring impermanent losses. Crafting resolves this, and opens up novel financial use cases for Uniswap pools. It is a fancy new way to build liquidity together, without needing to trust and know each other.

    +

    Anyone can create a Craft order, customize the liquidity setup and deploy it by contributing some of the liquidity. Others can then contribute the rest required to pool the order on Uniswap. Later, after the predetermined block, any of the participants can trigger removal of the liquidity. It is then distributed to all order participants based on the predetermined rules.

    Programmable Liquidity Rules

    +
    With Crafting, Uniswap liquidity providers can program a liquidity order by customizing the following:
      -
    1. - Selected Tier: The Tier to add liquidity.
    2. -
    3. - Waiting Length: the max time (in Blocks) the order can remain available while the required liquidity is waiting to be filled.
    4. -
    5. - Min Block Length: The time (in Blocks) in which the liquidity will be locked. If 0, any of the participants can trigger the removal of liquidity anytime.
    6. -
    7. - Liquidity Ratio: The creator of the order can set the ratio of liquidity (e.g. 10% DAI - 90% ETH or 0% DAI - 100 ETH). After the order is deployed, participants will be able to fill the liquidity required, so in the first example, if the creator sets 10% DAI - 90% ETH, the participant can add 90% DAI and 10% ETH.
    8. +
    9. - Tier: The Uniswap tier to which the liquidity will added.
    10. +
    11. - Waiting Length: The max time (in blocks) the order can remain available while the required liquidity is waiting to be filled.
    12. +
    13. - Min Block Length: The time (in blocks) for which the liquidity will be locked. If 0, any participant can trigger the removal of liquidity anytime.
    14. +
    15. - Liquidity Ratio: The ratio of liquidity, e.g. 10% DAI - 90% ETH or 0% DAI - 100 ETH. Once deployed by the creator, others can add the required liquidity. If the creator sets the ratio at 10% DAI - 90% ETH, the others can add the rest at 90% DAI - 10% ETH.
    16. - Liquidity Exit/Discount: An advanced feature for orders that allows for the creation of a different ratio or even a discount for the exit.
    -

    Example:

    -

    Let’s expand on the given example. A creates an order for USDC - DAI, with a min block length of 543055 Blocks and a ratio of 10% DAI - 90% USDC. He adds 100 DAI and 900 USDC. He also sets the exit liquidity at 30% DAI and 70% USDC, B fills part of the required liquidity (the ratio in his case is 90% DAI and 10% USDC) with 500 DAI and 50 USDC.

    -

    C fills part of the required liquidity (the ratio in his case is also 90% DAI and 10% USDC) with 100 DAI and 10 USDC.

    -

    D fills part of the required liquidity (the ratio in his case is also 90% DAI and 10% USDC) with 300 DAI and 30 USDC. D’s liquidity is enough to fill the 50:50 Uniswap pool, so D automatically triggers Uniswap’s Add Liquidity order by its last filling.

    -

    The total Uniswap liquidity pooled by A,B,C andD is 1,000 DAI and 1,000 USDC.

    -

    After 543055 Blocks, the liquidity pool has earned by the Uniswap Fees 1,000 USDC and 1,000 DAI for a total of 2,000 DAI and 2,000 USDC. B triggers the removal action, and based on the fixed rules, each of our providers receives the following:

    -

    A receives 600 DAI and 1,400 USDC (based on the Exit Ratio of 30% DAI and 70% USDC).

    -

    B, C and D receive 1,400 DAI and 600 USDC each, slipped by the liquidity added (based on the Exit Ratio of 70% DAI and 30% USDC).

    +

    Let’s play out that aforementioned example.

    +

    Person A creates an order for USDC - DAI, with a min block length of 543055 Blocks and a ratio of 10% DAI - 90% USDC. He adds 100 DAI and 900 USDC, and also decides to set the exit liquidity at 30% DAI and 70% USDC (read on to see exactly how exit liquidity works).

    +

    B fills part of the remaining required liquidity (at a ratio of 90% DAI and 10% USDC) with 500 DAI and 50 USDC.

    +

    C fills part of the remaining required liquidity (at a ratio of 90% DAI and 10% USDC) with 100 DAI and 10 USDC.

    +

    D fills the rest of the required liquidity (at a ratio of 90% DAI and 10% USDC) with 300 DAI and 30 USDC.

    +
    By adding the remaining required liquidity, D has triggered Uniswap’s Add Liquidity order ...
    +

    The total Uniswap liquidity pooled by A,B,C and D is 1,000 DAI and 1,000 USDC.

    +

    After 543055 Blocks, the liquidity pool has earned 1,000 USDC and 1,000 DAI in Uniswap trading fees, bringing the total to 2,000 DAI and 2,000 USDC.

    +
    ... B then triggers the removal action, and based on the fixed predetermined rules, the providers receive the following:
    +

    A receives 600 DAI and 1,400 USDC (at the Exit Ratio of 30% DAI and 70% USDC).

    +

    Based on how much they individually contributed, B, C and D receive their respective proportion of 1,400 DAI and 600 USDC (at the Exit Ratio of 70% DAI and 30% USDC).

    Initial Liquidity Offering (ILO)

    -

    Initial Liquidity Offerings are a procedure for Ethereum based startups to use a set of “Crafting”—aka, Programmable Liquidity—rules to reach long term funds in the form of Uniswap liquidity.

    -

    ILOs are helpful for three important reasons:

    -
    Initial Liquidity into AMMs for Fixed Inflation/Liquidity Staking
    -

    Reach the liquidity required to set fixed inflation without dumping on new holders, and helping new investors reduce slippage and become holders with a large amount of capital.

    -
    Avoid Sniper Bots
    -

    Sniper Bots are Ethereum-based bots who track new Uniswap low liquidity pools to sniff out significant amounts of capital before the liquidity even comes in, making it impossible for startups to start their offering with low collateral.

    -
    Reach Long Term Locked Investors
    +

    Initial Liquidity Offerings are a way for Ethereum-based startups to configure “Crafting”—i.e, Programmable Liquidity—rules to secure long term funding by providing Uniswap liquidity.

    +
    ILOs are helpful for three specific reasons:
    +

    Securing Initial Liquidity for AMMs with fixed inflation/liquidity staking

    +

    Providers can offer liquidity with fixed inflation without dumping on new holders. They also help new investors reduce slippage and become holders with a large amount of capital.

    +

    Disarming Sniper Bots

    +

    Sniper Bots track new low liquidity Uniswap pools for sizable capital before liquidity even comes in, making it (until now) impossible for startups to offer liquidity with low collateral.

    +

    Securing Long Term Locked Investors

    Investors lock their funds for the long run.

    How ILOs work:

    -

    Before a new token is distributed, a new startup can set a crafting order with fixed pre-values, adding the token and requesting the collateral required for investors to fill the order.Investors fill the collateral needed, and if the startup has set, investors can have an exit Discount to mitigate the high risk.

    +

    Before distributing their tokens, startups can set crafting orders with fixed pre-values, adding the token and requesting the collateral required to fill the order. Investors provide that collateral, and if the startup chooses, investors get an Exit/Discount to mitigate the high risk.

    Example
    -

    The token creator sets a Crafting order with low liquidity, like 1,000,000 of the token and 1 ETH, with a 90% - 10% ratio, or even 1,000,000 of token and 0 ETH, with a 100% - 0% ratio (adding a pre-value of the token, if the liquidity pool is not open yet) for one year. Setting the Liquidity Exit/Discount (10%/20%) means that investors will receive at the end of the order (90%/80%).

    -

    In this case, investors invest their own Ethereum for a new token not already tradable, so with a high level of risk, they’ll receive a more significant portion of the liquidity at the end of the year (from 50% added to 170% received).

    -

    ILOs can open new Ethereum fundraising rules that solve liquidity in early stages while also helping legitimate projects set Fixed Inflation. This empowers projects and investors in the long run.

    +

    The token creator sets a Crafting order with low liquidity, e.g. 1,000,000 of the token and 1 ETH, with a 90% - 10% ratio, or even 1,000,000 of token and 0 ETH, with a 100% - 0% ratio (adding a pre-value of the token, if the liquidity pool is not open yet) for one year. Setting the Liquidity Exit/Discount 10%/20%, investors will receive at the end of the order 90%/80%.

    +

    In this case, investors invest their own Ethereum for a new token that is not already tradable. This entails a high level or risk, and so they are compensated by receiving a more significant portion of the liquidity at the end of the year; in this case, from 50% added to 170% received.

    +
    ILOs enable new Ethereum fundraising rules that solve liquidity issues in early stages, while also helping legitimate projects set Fixed Inflation. This empowers projects and investors in the long run.
    UniFi DFO Tax:
    -

    The earning of the UniFi DFO using the Crafting function id the 0.1% of the total Uniswap Pool Tokens into a Craft order, this tax is paid directly when a participant calls the remove function.

    +

    The UniFi DFO earns via the Crafting function; 0.1% of the total Uniswap Pool Tokens in a Craft order is taxed and paid directly when a participant calls the remove function.

    Release

    diff --git a/spa/grimoire/grimUnifi.jsx b/spa/grimoire/grimUnifi.jsx index aefb81f..95e30d9 100644 --- a/spa/grimoire/grimUnifi.jsx +++ b/spa/grimoire/grimUnifi.jsx @@ -10,7 +10,7 @@ var GrimUnifi = React.createClass({
    -

    The Grimoire - UniFi DFO and UniFi Token

    +

    The Grimoire - Uniswap Finance and the UniFi token

    UniFi is a new Decentralized Flexible Organization (DFO) that researches and develops a responsible Decentralized Finance layer on top of Uniswap.
    @@ -19,22 +19,22 @@ var GrimUnifi = React.createClass({

    Basics

    -

    Thanks to the DFOhub standard, UniFi dApps are entirely independent from any off-chain entity. The $UniFi voting token is a programmable equity of the UniFi DFO; $UniFi holders hold real equity of the protocol, and rule every part of its code and assets. More at dfohub.com

    +

    UniFi is a new Decentralized Flexible Organization (DFO) that researches and develops a responsible Decentralized Finance layer on top of Uniswap. Thanks to the DFOhub standard, UniFi dApps are entirely independent from any off-chain entity. The $UniFi voting token is a programmable equity of the UniFi DFO; $UniFi holders hold real equity of the protocol, and rule every part of its code and assets. More info here: dfohub.com

    -

    UniFi Distribution

    +

    UniFi Token Distribution

    The total supply of $UniFi is 88,888,888, which is initially distributed as follows:

      -
    1. - 36% (32,042,000) are locked in the NERV Wallet [0x25756f9C2cCeaCd787260b001F224159aB9fB97A] This is the DFOhub Operations wallet, funded by Fair Inflation.
    2. -
    3. - 40% (35,900,000) are locked in the UniFI DFO wallet [0x2578aA454b29C15c8eEF62C972Ee1ff57CD99DEf]. This pays out the liquidity staking rewards. The active reward staking contract is [0xb266252Fd70D253b4330151A96694d35e94b846c]
    4. +
    5. - 36% (32,042,000) are locked in the NERV Wallet [0x25756f9C2cCeaCd787260b001F224159aB9fB97A] This is the DFOhub Operation' DFO wallet, funded by Fair Inflation.
    6. +
    7. - 40% (35,900,000) are locked in the UniFI's DFO wallet [0x2578aA454b29C15c8eEF62C972Ee1ff57CD99DEf]. This pays out the liquidity staking rewards. The active reward staking contract is [0xb266252Fd70D253b4330151A96694d35e94b846c]
    8. - 16% (14,333,333) are locked in the DFOhub wallet (owned by $buidl holders) [0x5D40c724ba3e7Ffa6a91db223368977C522BdACD]
    @@ -53,13 +53,13 @@ var GrimUnifi = React.createClass({

    UniFi Liquidity Staking

    -

    UniFi Liquidity Staking is available here: https://dapp.dfohub.com/?staking=0xb266252Fd70D253b4330151A96694d35e94b846c

    +

    $UniFi liquidity staking is available here: https://dapp.dfohub.com/?staking=0xb266252Fd70D253b4330151A96694d35e94b846c

    The UniFi Liquidity Staking Mechanism is designed to reward those who lock up Uniswap V2 liquidity for the long term.

    -

    Liquidity Staking will inflate the supply over the first year (if every tier is completely filled) by 918,000 UniFi (1% of the supply).

    +

    Staking will inflate the supply over the first year (if every tier is completely filled) by 918,000 $UniFi (1% of the supply).

    The Five Year tier was filled by the team in an early test, and we won’t touch the rewards for three years. When they are unlocked and redeemed, 50% of the UniFi will be sent to the UniFi wallet and 50% to the NERV operations wallet.

    -

    DFO Earnings

    +

    UniFi Earning System

    The UniFi DFO earn from:

    1. - The uSD positive rebalance (the trading fees of Uniswap collateralized stablecoins)
    2. diff --git a/spa/grimoire/grimuSD.jsx b/spa/grimoire/grimuSD.jsx index 0f3485e..022e0f5 100644 --- a/spa/grimoire/grimuSD.jsx +++ b/spa/grimoire/grimuSD.jsx @@ -29,14 +29,15 @@ var GrimuSD = React.createClass({

      Basics

      The aim of the Uniswap State Dollar (uSD) protocol is to build the most secure and resilient stablecoin on Ethereum—ever. Independent from any off-chain issuer, it is fortified against the risks inherent to all other stablecoins, and free of the anxiety that pervades the industry.

      -

      uSD achieves stability by collateralizing stablecoins, and, when necessary, rebalancing itself in relation to them, so that if any lose value or fail, it is still secured by the others. The only way uSD can be destabilized is if the entire stablecoin industry collapses.

      +

      uSD achieves this unprecedented level of stability by collateralizing other stablecoins. If any of them lose value or fail, it can simply rebalance itself to leverage the security of the others. And to account for excess due to fees in their pools, it can rebalance itself in another way.

      +

      The only way uSD can be destabilized is if the entire stablecoin industry collapses.

      uSD is backed by Uniswap’s (whitelisted) stablecoin liquidity pools.
      Anyone can mint it by adding these stablecoins to those pools.

      Example:

      -

      Mint 2x uSD by adding 1x Stablecoin A and 1x Stablecoin B.

      +

      Mint 2x uSD by adding 1x Stablecoin A and 1x Stablecoin B

      And by burning uSD, anyone can receive these stablecoins from those pools.

      Example:

      -

      Burn 2x uSD and receive 1x Stablecoin A and 1x Stablecoin C.

      +

      Burn 2x uSD and receive 1x Stablecoin A and 1x Stablecoin C

      Rebalancing

      @@ -45,33 +46,39 @@ var GrimuSD = React.createClass({

      When a stablecoin loses value, the Uniswap Tier pools rebalance to an uneven disparity (≠ 50/50). If the stablecoin totally fails, the other stablecoins effectively pump in correlation.

      DFO Debit resolves this issue on-chain by rebalancing uSD, creating debt which the UniFi DFO then pays off by minting UniFi. Let’s look at how this plays out, step by step:

        -
      1. Holders of the $UniFi programmable equity vote to remove the tiers that contain the failed stablecoin from the whitelist. In doing so, the uSD supply becomes greater than the supply of the collateralized pooled stablecoins.
      2. -
      3. To restore the 1:1 equilibrium, anyone holding uSD can burn it to receive new UniFi, minted at a 50% discount of the uSD/UniFi Uniswap pool mid-price ratio.
      4. +
      5. 1 - A stablecoin collateralized by uSD loses value or fails altogether.
      6. +
      7. 2 - $UniFi holders vote to remove the tiers containing the failed stablecoin from the whitelist.
      8. +
      9. The uSD supply becomes grater than the supply of the collateralized pooled stablecoins.
      10. +
      11. To restore 1:1 equilibrium, anyone holding uSD can burn it to receive new UniFi, minted at a 50% discount of the uSD/UniFi Uniswap pool mid-price ratio.
      -
      The goal of UniFi holders, which aligns with their self-interest, is to ensure uSD’s security. Thus there is an economic disincentive to whitelist stablecoins that don’t provide security.
      +
      The goal of $UniFi holders, which aligns with their self-interest, is to ensure uSD’s security. Thus there is an economic disincentive to whitelist insecure stablecoins.

      DFO Credit

      -

      As has already been established, uSD is backed by Uniswap pool liquidity. There is an issue here, given that Uniswap pools earn 0.3% of trading fees, which can destabilize uSD by creating an excess of collateralized stablecoins in the pools.

      -

      DFO Credit, the second rebalancing function of the UniFi DFO, resolves this by removing the excess from the pools and sending it in the DFO wallet managed by UniFi holders.This is a long term economic incentive for the UniFi DFO to grow and invest credit in R&D.

      +

      As established, uSD is backed by Uniswap pool liquidity. This raises an issue; Uniswap pools earn 0.3% of trading fees. This could destabilize uSD by creating an excess of collateralized stablecoins in the pools.

      +

      DFO Credit, the second rebalancing function of the UniFi DFO, resolves this by removing that excess from the pools and sending it in the DFO wallet managed by $UniFi holders.

      +

      This is a long term economic incentive for the UniFi DFO to grow and invest credit in R&D.

      Security and Emergency Strategies

      The UniFi has a number of measures in place to ensure its security.

      -

      1 - The DFO can’t vote to manage the locked pool collateral of uSD, which is stored in an external smart contract. This precludes voter fraud by bad actors.

      -

      2 - In the case of any bug or update, UniFi holders can vote to pause the uSD smart contract. This will prevent it from minting new uSD or rebalancing uSD, but holders will still be able to redeem uSD for the pooled stable coins, and thereby revoke the collateral.

      -

      3 - Even if the protocol fails, or even if the UniFi DFO votes to update uSD to an undesirable new version, uSD holders will still be able to interact with the old smart contract (until all collateral is revoked) as well as the new one.

      +

      1 - uSD pool collateral is locked. Stored in an external smart contract, it can’t be touched even by the UniFi DFO, precluding voter fraud by bad actors.

      +

      2 - In the case of any bug or update, $UniFi holders can vote to pause the uSD smart contract. This prevents minting of new uSD or rebalancing of uSD, but holders will still be able to redeem it for the pooled stable coins, and thus revoke the collateral.

      +

      3 - Even if the uSD protocol fails, and even if the UniFi DFO votes to update uSD to an undesirable new version, uSD holders will still be able to interact with the old smart contract—until all collateral is revoked—as well as the new one.

      Resilience, Decentralization and independency

      -

      uSD is the most resilient stablecoin in the industry. It frees holders from dependence on any centralized manipulation by states and stablecoin issuers, by taking advantage of Uniswap, an important security layer with a decentralized core.

      -

      uSD is backed by a DFO. There is no centralized entity behind it, only UniFi holders on the Ethereum network. They have 100% control of the code and Credit/Debit of the protocol. Nobody can stop or censor the UniFi-uSD protocol; for the first time, the Ethereum network doesn’t have to choose between stability and independence in a stablecoin; it can have both.

      -

      uSD resolves all of the risks associated with trusting the big stablecoin companies, such as MakerDAO, Coinbase, Tether etc.

      +

      uSD is the most resilient, secure and stable stablecoin in the industry. By taking advantage of Uniswap, a security layer with a decentralized core, it frees holders from dependence on censorship or centralized manipulation by states and stablecoin issuers. It resolves all risks that come with trusting the big stablecoin companies, like MakerDAO, Coinbase, Tether etc.

      +

      uSD is backed by a Decentralized Flexible Organization. $UniFi holders on the Ethereum network have 100% control of the code and Credit/Debit of the protocol. Nobody can stop or censor the UniFi-uSD protocol; for the first time, the Ethereum network doesn’t have to choose between stability and independence in a stablecoin; it can have both.

      APIs and Documentation

      -

      To build on top of uSD and to interact with the dapp, you can find all of the documentation and APIs here:

      +

      To build on top of uSD and to interact with the dApp, you can find all of the documentation and APIs here: Documentation

      -

      Responsible DeFi Architecture

      +

      Responsible DeFi Limits

      +

      Due to a Responible DeFi Approach, UniFi uSD is limited in its early stage to mint by:

      +
        +
      1. +
      From c4112bf4e938cfc4252db1d7bb991ec231673914 Mon Sep 17 00:00:00 2001 From: alet89 Date: Thu, 27 Aug 2020 11:21:35 +0200 Subject: [PATCH 48/76] t --- assets/css/style.css | 2 ++ spa/grimoire/grimUnifi.jsx | 2 +- spa/grimoire/grimuSD.jsx | 4 ++-- spa/grimoire/style.min.css | 2 +- spa/grimoire/style.scss | 25 ------------------------- spa/stableCoin/view.jsx | 2 +- 6 files changed, 7 insertions(+), 30 deletions(-) diff --git a/assets/css/style.css b/assets/css/style.css index 0bd9545..47d7e5f 100644 --- a/assets/css/style.css +++ b/assets/css/style.css @@ -165,6 +165,8 @@ footer p a, footer h5 a {color: #c7ac97; font-weight: bold;} .ArrivaUniswap img {width: 30%; position: absolute; left: 35%; top: 150px;} .ArrivaUniswapQuelloVero iframe {position: fixed;width: 80%;height: 80%;overflow: hidden;left: 10%;top: 10%;z-index: 9;border: none;border-radius: 35px;} .SeneVaUniswap {position: fixed; top: 10px; left: 50%; border-radius: 50%; width: 40px; height: 40px; line-height: 2.5; font: 12px; font-weight: bold; text-decoration: none;} +.grimoire .connectOpener, .swapBazar .connectOpener{display: none;} +.grimoire .BoomerModeToggler, .swapBazar .BoomerModeToggler {right: 15px;} .Boomer .UniBox, .Boomer .grimoireBox {position: initial;background: rgb(255, 255, 255); box-shadow: rgba(0, 0, 0, 0.01) 0px 0px 1px, rgba(0, 0, 0, 0.04) 0px 4px 8px, rgba(0, 0, 0, 0.04) 0px 16px 24px, rgba(0, 0, 0, 0.01) 0px 24px 32px; border-radius: 30px; color: #000000;} diff --git a/spa/grimoire/grimUnifi.jsx b/spa/grimoire/grimUnifi.jsx index 95e30d9..d7a452f 100644 --- a/spa/grimoire/grimUnifi.jsx +++ b/spa/grimoire/grimUnifi.jsx @@ -31,7 +31,7 @@ var GrimUnifi = React.createClass({

    UniFi Token Distribution

    -

    The total supply of $UniFi is 88,888,888, which is initially distributed as follows:

    +

    The total supply of $UniFi is 88,888,888, which is initially distributed and Locked as follows:

    1. - 36% (32,042,000) are locked in the NERV Wallet [0x25756f9C2cCeaCd787260b001F224159aB9fB97A] This is the DFOhub Operation' DFO wallet, funded by Fair Inflation.
    2. - 40% (35,900,000) are locked in the UniFI's DFO wallet [0x2578aA454b29C15c8eEF62C972Ee1ff57CD99DEf]. This pays out the liquidity staking rewards. The active reward staking contract is [0xb266252Fd70D253b4330151A96694d35e94b846c]
    3. diff --git a/spa/grimoire/grimuSD.jsx b/spa/grimoire/grimuSD.jsx index 022e0f5..a7cad21 100644 --- a/spa/grimoire/grimuSD.jsx +++ b/spa/grimoire/grimuSD.jsx @@ -11,7 +11,7 @@ var GrimuSD = React.createClass({

      The Grimoire - Uniswap State Dollar

      -
      uSD is a Stable Coin based on Uniswap Liquidity Pools Launch Dapp Minted by the magic rainbow of Uniswap stablecoin pools. Backed by the power of the Unicorn, uSD is the most secure stablecoin ever. The only way it could be destabilized is if the entire stablecoin industry crashed.
      +
      uSD is a Stable Coin based on Uniswap Liquidity Pools Minted by the magic rainbow of Uniswap stablecoin pools. Backed by the power of the Unicorn, uSD is the most secure stablecoin ever. The only way it could be destabilized is if the entire stablecoin industry crashed. | Etherscan Uniswap
      @@ -49,7 +49,7 @@ var GrimuSD = React.createClass({
    4. 1 - A stablecoin collateralized by uSD loses value or fails altogether.
    5. 2 - $UniFi holders vote to remove the tiers containing the failed stablecoin from the whitelist.
    6. The uSD supply becomes grater than the supply of the collateralized pooled stablecoins.
    7. -
    8. To restore 1:1 equilibrium, anyone holding uSD can burn it to receive new UniFi, minted at a 50% discount of the uSD/UniFi Uniswap pool mid-price ratio.
    9. +
    10. 3 - To restore 1:1 equilibrium, anyone holding uSD can burn it to receive new UniFi, minted at a 50% discount of the uSD/UniFi Uniswap pool mid-price ratio.
    The goal of $UniFi holders, which aligns with their self-interest, is to ensure uSD’s security. Thus there is an economic disincentive to whitelist insecure stablecoins.

    DFO Credit

    diff --git a/spa/grimoire/style.min.css b/spa/grimoire/style.min.css index 8721c7d..ec747fa 100644 --- a/spa/grimoire/style.min.css +++ b/spa/grimoire/style.min.css @@ -1 +1 @@ -.swapBazar{width:100%;height:100%;position:relative;color:white}.swapBazar iframe{width:100%;height:100%;border:none}.swapBazar .floatingMenu{position:absolute;top:10%;left:10%}.swapBazar .floatingMenu .loader{margin:2%}.swapBazar .floatingMenu .tokensList{overflow-y:hidden;overflow-x:auto;width:100%;max-height:350px} +null \ No newline at end of file diff --git a/spa/grimoire/style.scss b/spa/grimoire/style.scss index 1c1ff73..e69de29 100644 --- a/spa/grimoire/style.scss +++ b/spa/grimoire/style.scss @@ -1,25 +0,0 @@ -.swapBazar { - width: 100%; - height: 100%; - position: relative; - color: white; - iframe { - width: 100%; - height: 100%; - border: none; - } - .floatingMenu { - position: absolute; - top: 10%; - left: 10%; - .loader { - margin: 2%; - } - .tokensList { - overflow-y: hidden; - overflow-x: auto; - width: 100%; - max-height: 350px; - } - } -} \ No newline at end of file diff --git a/spa/stableCoin/view.jsx b/spa/stableCoin/view.jsx index 7ceed99..c7dd304 100644 --- a/spa/stableCoin/view.jsx +++ b/spa/stableCoin/view.jsx @@ -146,7 +146,7 @@ var StableCoin = React.createClass({

    Uniswap State Dollar

    -
    uSD is a Stable Coin based on Uniswap Liquidity Pools
    Here, you can mint uSD by adding liquidity to whitelisted Uniswap Stable Coin Pools or redeem anytime whitelisted Stable Coins by burning uSD.
    +
    uSD is a Stable Coin based on Uniswap Liquidity Pools
    Here, you can mint uSD by adding liquidity to whitelisted Uniswap Stable Coin Pools or redeem anytime whitelisted Stable Coins by burning uSD. | Etherscan Uniswap
    From 18b1f661901240b976637db1b95187408b00e7b8 Mon Sep 17 00:00:00 2001 From: alet89 Date: Thu, 27 Aug 2020 12:54:20 +0200 Subject: [PATCH 49/76] Grimoire Updates uSD --- assets/css/style.css | 2 +- spa/grimoire/grimCrafting.jsx | 3 --- spa/grimoire/grimuSD.jsx | 22 ++++++++++++++++++++-- spa/grimoire/style.min.css | 1 - 4 files changed, 21 insertions(+), 7 deletions(-) diff --git a/assets/css/style.css b/assets/css/style.css index 47d7e5f..e2f18ce 100644 --- a/assets/css/style.css +++ b/assets/css/style.css @@ -282,7 +282,7 @@ footer p a, footer h5 a {color: #c7ac97; font-weight: bold;} .MenuOpen {width: 100%; display: inline-block; text-align: center;} .StableCoinTitle .StableCoinTitleIntern, .grimoireWelcome .grimoireWelcomeIntern, .grimoireBox {width: 590px; padding: 20px; border-radius: 8px; display: inline-block;} .StableCoinTitleIntern article, .grimoireWelcomeIntern article {width: 480px; display: inline-block; vertical-align: middle;} - .StableCoinTitle img, .grimoireWelcome img {width: 80px; height: 80px; margin-right: 10px; vertical-align: middle; z-index: 1; position: relative;} + .StableCoinTitle img, .grimoireWelcome img {width: 80px; height: 80px; margin-right: 10px; vertical-align: middle; z-index: 1;} .grimoireWelcome .GrimImg2 {width: 70px; height: 70px; position: absolute;bottom: -10px;left: -15px; z-index: 2;} footer .welcomeLinks, footer p {width: 500px; padding: 20px;} .grimoireIndex {width: 350px;} diff --git a/spa/grimoire/grimCrafting.jsx b/spa/grimoire/grimCrafting.jsx index 6b531f1..f5065d5 100644 --- a/spa/grimoire/grimCrafting.jsx +++ b/spa/grimoire/grimCrafting.jsx @@ -8,10 +8,7 @@ var GrimCrafting = React.createClass({
    -
    - -

    The Grimoire - Crafting and Initial Liquidity Offering

    Craft makes it possible to provide liquidity that is programmable with advanced rules. Using Unicorn magic, pools can balance tokens diversely with unprecedented security.
    diff --git a/spa/grimoire/grimuSD.jsx b/spa/grimoire/grimuSD.jsx index a7cad21..11e2727 100644 --- a/spa/grimoire/grimuSD.jsx +++ b/spa/grimoire/grimuSD.jsx @@ -23,6 +23,7 @@ var GrimuSD = React.createClass({ Rebalancing Security and Emergency Strategies Resilience, Decentralization and independency + Allowed Stable Coins APIs and Documentation Responsible DeFi Architecture @@ -69,15 +70,32 @@ var GrimuSD = React.createClass({

    uSD is the most resilient, secure and stable stablecoin in the industry. By taking advantage of Uniswap, a security layer with a decentralized core, it frees holders from dependence on censorship or centralized manipulation by states and stablecoin issuers. It resolves all risks that come with trusting the big stablecoin companies, like MakerDAO, Coinbase, Tether etc.

    uSD is backed by a Decentralized Flexible Organization. $UniFi holders on the Ethereum network have 100% control of the code and Credit/Debit of the protocol. Nobody can stop or censor the UniFi-uSD protocol; for the first time, the Ethereum network doesn’t have to choose between stability and independence in a stablecoin; it can have both.

    +

    APIs and Documentation

    To build on top of uSD and to interact with the dApp, you can find all of the documentation and APIs here: Documentation

    Responsible DeFi Limits

    -

    Due to a Responible DeFi Approach, UniFi uSD is limited in its early stage to mint by:

    +

    Due to a Responible DeFi Approach, UniFi uSD is limited in its early stage to mint by:

      -
    1. +
    2. - 500,000 uSD Mintable for the first month (untill block n 10941929)
    3. +
    4. - 2,000,000 uSD Mintable for the first two months (untill block n 11141929)
    5. +
    6. - 5,000,000 uSD Mintable for the first three months (untill block n 11341929)
    7. +
    8. - 10,000,000 uSD Mintable for the first four months (untill block n 11541929)
    9. +
    10. - 20,000,000 uSD Mintable for the first five months (untill block n 11741929)
    diff --git a/spa/grimoire/style.min.css b/spa/grimoire/style.min.css index ec747fa..e69de29 100644 --- a/spa/grimoire/style.min.css +++ b/spa/grimoire/style.min.css @@ -1 +0,0 @@ -null \ No newline at end of file From c8bec35ac201235b82c3cfd2d32ecc78d692e431 Mon Sep 17 00:00:00 2001 From: alet89 Date: Thu, 27 Aug 2020 13:03:41 +0200 Subject: [PATCH 50/76] uSD update --- spa/grimoire/grimuSD.jsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spa/grimoire/grimuSD.jsx b/spa/grimoire/grimuSD.jsx index 11e2727..4dfc389 100644 --- a/spa/grimoire/grimuSD.jsx +++ b/spa/grimoire/grimuSD.jsx @@ -50,7 +50,7 @@ var GrimuSD = React.createClass({
  • 1 - A stablecoin collateralized by uSD loses value or fails altogether.
  • 2 - $UniFi holders vote to remove the tiers containing the failed stablecoin from the whitelist.
  • The uSD supply becomes grater than the supply of the collateralized pooled stablecoins.
  • -
  • 3 - To restore 1:1 equilibrium, anyone holding uSD can burn it to receive new UniFi, minted at a 50% discount of the uSD/UniFi Uniswap pool mid-price ratio.
  • +
  • 3 - To restore 1:1 equilibrium, anyone holding uSD can burn it to receive new UniFi, minted at a 20% discount of the uSD/UniFi Uniswap pool mid-price ratio.
  • The goal of $UniFi holders, which aligns with their self-interest, is to ensure uSD’s security. Thus there is an economic disincentive to whitelist insecure stablecoins.

    DFO Credit

    From fab942aa72b2c4511354fb157c40b5bf4dd55881 Mon Sep 17 00:00:00 2001 From: alet89 Date: Thu, 27 Aug 2020 14:05:22 +0200 Subject: [PATCH 51/76] Front-End Updates --- assets/css/style.css | 89 ++++++++++++++++++++++++++++++++-------- spa/grimoire/grimuSD.jsx | 2 +- spa/stableCoin/view.jsx | 2 +- 3 files changed, 74 insertions(+), 19 deletions(-) diff --git a/assets/css/style.css b/assets/css/style.css index e2f18ce..b89c965 100644 --- a/assets/css/style.css +++ b/assets/css/style.css @@ -61,14 +61,14 @@ footer p a, footer h5 a {color: #c7ac97; font-weight: bold;} .unifiDapp {position: relative;} .unifiDapp .MenuAll {width: 100%; position: fixed; top: 0; left: 0;} .unifiDapp .MenuAll .connectOpener, .unifiDapp .MenuAll .menuOpener {padding: 6px 10px; border-radius: 8px; margin-top: 10px;text-decoration: none;} -.unifiDapp .MenuAll .maghetto {width: 40px; height: 40px; float: left;margin: 5px 10px 0 20px;} +.unifiDapp .MenuAll .maghetto {width: 30px; height: 30px; float: left;margin: 5px 10px 0 20px;} .unifiDapp .MenuAll .maghetto img {width: 100%; height: 100%;} .unifiDapp .MenuAll .menuOpener {float: left; margin-left: 20px;} -.unifiDapp .MenuAll .menuOpener, .unifiDapp .MenuAll .connectOpener span {font-size: 18px; font-weight: bold;} +.unifiDapp .MenuAll .menuOpener, .unifiDapp .MenuAll .connectOpener span {font-size: 12px; font-weight: bold;} .unifiDapp .MenuAll .connectOpener {float: right; margin-right: 20px; text-decoration: none;} -.unifiDapp .MenuAll .connectOpener img {width: 25px; height: 25px; vertical-align: middle;} -.unifiDapp .MenuAll .connectOpener span {font-size: 18px; vertical-align: middle;} -.unifiDapp .MenuOpen {text-align: left; position: absolute; left: 90px; top: 50px; z-index: 99999999999999;} +.unifiDapp .MenuAll .connectOpener img {width: 10px; height: 10px; vertical-align: middle;} +.unifiDapp .MenuAll .connectOpener span {font-size: 12px; vertical-align: middle;} +.unifiDapp .MenuOpen {text-align: left; position: absolute; left: 10px; top: 50px; z-index: 99999999999999;} .unifiDapp .MenuOpen .coverMenu {margin: 0;z-index: 99999999999999;outline: -webkit-focus-ring-color auto 0px;} .ethereumWalletProvider {text-align: left; position: absolute; right: 20px; top: 0px; z-index: 99999999999999;} @@ -76,13 +76,13 @@ footer p a, footer h5 a {color: #c7ac97; font-weight: bold;} .UniStableManage {width: 25px; height: 25px;vertical-align: middle; margin: 7px;} .UniActiveQuantityTier, .UniDisactiveQuantityTier {display: inline-block; margin: 5px auto;} .UniTierQuantity h6 {font-size: 15px; margin: 6px auto;} -.StableCoinTitle, .grimoireWelcome {width: 100%; margin-top: 100px; text-align: center;position: initial;z-index: 1;} +.StableCoinTitle, .grimoireWelcome {width: 100%; margin-top: 30px; text-align: center;position: initial;z-index: 1;} .grimoireBoxAll {width: 100%; margin-top: 25px; text-align: center;} .grimoireBox {width: 95%; margin-bottom: 18px; text-align: center;} .grimoireIndex {width: 95%; margin-left: 4%; text-align: left;} -.grimoireIndex a {width: 100%; padding: 20px 0; display: inline-block; font-size: 18px; vertical-align: middle;} -.grimoireIndex h2 {font-size: 30px; margin-bottom: 20px;} -.grimoireIndex a img {width: 30px;height: 30px; margin-right: 6px; vertical-align: middle;} +.grimoireIndex h2 {font-size: 20px; margin-bottom: 20px; margin-top: 20px;} +.grimoireIndex a {width: 100%; padding: 10px 0; display: inline-block; font-size: 14px; vertical-align: middle;} +.grimoireIndex a img {width: 20px;height: 20px; margin-right: 6px; vertical-align: middle;} .grimoireArticle {width: 90%; padding: 4%; text-align: left;} .grimoireArticle h2 {font-size: 30px; margin-bottom: 25px;} .grimoireArticle p {font-size: 15px; line-height: 1.4; width: 100%; display: inline-block; margin-bottom: 15px;} @@ -91,6 +91,7 @@ footer p a, footer h5 a {color: #c7ac97; font-weight: bold;} .grimoireArticle ol {width: 100%; display: inline-block; text-align: right;} .grimoireArticle li {width: 95%; text-align: left; display: inline-block; font-size: 15px;line-height: 1.3; margin: 10px auto;} + .StableCoinTitle .StableCoinTitleIntern, .grimoireWelcome .grimoireWelcomeIntern {display: none;} .StableCoinTitle h2, .grimoireWelcome h2 {font-size: 25px; margin: 10px 0; vertical-align: middle;text-align: left;} .StableCoinTitle h6, .grimoireWelcome h6 {font-size: 15px; text-align: left; line-height: 1.4; font-weight: normal;} @@ -138,21 +139,22 @@ footer p a, footer h5 a {color: #c7ac97; font-weight: bold;} .UniTierQuantity label input, .RebalanceEmergency label input {width: 130px; display: inline-block; height: 30px;} .CallToGrim {position: fixed; top: 10px; left: 190px; width: 35px; height: 35px;} +.CallToGrim {display: none;} .CallToGrim a {width: 35px; height: 35px; display: inline-block; text-align: center; border-radius: 10px;} .CallToGrim a img {width: 30px; height: 30px; display: inline-block; vertical-align: center;} -.BoomerModeToggler {width: 35px; height: 35px; display: inline-block; text-align: center; border-radius: 10px; position: fixed; top: 10px; right: 230px; text-decoration: none;line-height: 2;} +.BoomerModeToggler {width: 20px; height: 20px; display: inline-block; text-align: center; border-radius: 10px; position: fixed; bottom: 10px; right: 0px; text-decoration: none;line-height: 2; font-size: 12px;} .explainer .BoomerModeToggler {display: none;} .BazTokenSelector {width: 100%; display: inline-block; margin: 10px auto; text-align: center;} .BazTokenSelector a {padding: 10px 20px; text-decoration: none; font-weight: bold; display: inline-block; margin: 5px; border-radius: 6px;} -.BazSelectorContainer {position: fixed; top: 20%; left: 50%; width: 90%; overflow-y: scroll;overflow-x: hidden; height: 60%; margin: auto; z-index: 10; border-radius: 10px;} -.BazSelectorContainerClose {position: fixed; border-radius: 50%; width: 40px; height: 40px; top: 70px; left: 5px;top: 14%;left: 48%;} -.BazSelectorContainerClose a {font-size: 25px; padding: 0;} +.BazSelectorContainer {position: fixed; top: 20%; left: 5%; width: 90%; overflow-y: scroll;overflow-x: hidden; height: 60%; margin: auto; z-index: 10; border-radius: 10px;} +.BazSelectorContainerClose {position: fixed; border-radius: 50%; width: 30px; height: 30px; top: 20px; left: 5px;top: 10%;left: 48%;} +.BazSelectorContainerClose a {font-size: 18px; padding: 0;} .BazSelectorContainerMenu {display: inline-block; width: 100%;} .BazSelectorContainerMenuintern {width: 100%;} .BazSelectorContainerMenu li {width: 33.3%; display: inline-block; height: 32px;} .BazSelectorContainerMenu li a {padding: 8px 0; width: 100%; margin: 0; font-size: 13px; font-weight: bold;} .BazSelectorContainerObjects {width: 95%; display: inline-block; margin-top: 20px; text-align: left;} -.BazSelectorContainerObjects li {display: inline-block; width: 120px; margin: 10px;word-wrap: break-word;} +.BazSelectorContainerObjects li {display: inline-block; width: 110px; margin: 10px;word-wrap: break-word;} .BazSelectorContainerObjects li a {font-size: 13px; font-weight: normal; padding: 3px 6px; margin: 0; border-radius: 0; display: inline-block;} .BazSelectorContainerObjects li a img {width: 20px; height: 20px; vertical-align: middle;} .BazSelectorContainerObjects li a p {display: inline;} @@ -163,11 +165,26 @@ footer p a, footer h5 a {color: #c7ac97; font-weight: bold;} .StableITBTNFActive {font-size: 13px; padding: 5px 9px; margin-top: 5px;} .ArrivaUniswap {position: fixed; width: 80%; height: 80%; overflow: hidden; z-index: 10;left: 10%;top: 10%;border: none;border-radius: 35px;} .ArrivaUniswap img {width: 30%; position: absolute; left: 35%; top: 150px;} -.ArrivaUniswapQuelloVero iframe {position: fixed;width: 80%;height: 80%;overflow: hidden;left: 10%;top: 10%;z-index: 9;border: none;border-radius: 35px;} -.SeneVaUniswap {position: fixed; top: 10px; left: 50%; border-radius: 50%; width: 40px; height: 40px; line-height: 2.5; font: 12px; font-weight: bold; text-decoration: none;} +.ArrivaUniswapQuelloVero iframe {position: fixed;width: 90%;height: 80%;overflow: hidden;left: 5%;top: 10%;z-index: 9;border: none;border-radius: 35px;} +.SeneVaUniswap {position: fixed; top: 10px; left: 70%; border-radius: 50%; width: 30px; height: 30px; line-height: 2; font: 12px; font-weight: bold; text-decoration: none;} .grimoire .connectOpener, .swapBazar .connectOpener{display: none;} .grimoire .BoomerModeToggler, .swapBazar .BoomerModeToggler {right: 15px;} - +.grimoire .grimoireWelcome {display: inline-block; margin-top: 60px; width: 90%;} +.grimoire .grimoireWelcomeintern {display: inline-block;border-radius: 30px; padding: 15px 0;} +.grimoire .grimoireWelcomeintern img {display: none;} +.grimoire .grimoireWelcomeintern article {width: 80%;display: inline-block;} +.grimoire .grimoireWelcomeintern h2 {font-size: 20px;} +.grimoire .grimoireWelcomeintern h6 {font-size: 13px;} +.grimoire .grimoireArticle {word-wrap: break-word;} +.grimUnifi, .grimBazar, .grimCrafting, .grimuSD {max-width: 100%;} +.coverMenu {margin: 50px auto 50px auto; width: 90%; border-radius: 8px; text-align: left; padding: 8px 5px;} +.coverMenu li {width: 200; display: inline-block; position: relative; margin-left: 25px;} +.coverMenu li a {width: 100%; display: inline-block; padding: 5px 5px; text-decoration: none;} +.coverMenu li a img {width: 35px; height: 35px; margin: 0 7px; vertical-align: middle;} +.coverMenu li a span {font-size: 16px; font-weight: bolder; vertical-align: middle;} +.coverMenu li .menuArrow {display: none;} +.coverMenu li:hover .menuArrow {width: 20px; height: 20px; position: absolute; left: -15px; top: 15px; display: block;} +.coverMenu .menuArrow img {width: 20px; height: 20px;} .Boomer .UniBox, .Boomer .grimoireBox {position: initial;background: rgb(255, 255, 255); box-shadow: rgba(0, 0, 0, 0.01) 0px 0px 1px, rgba(0, 0, 0, 0.04) 0px 4px 8px, rgba(0, 0, 0, 0.04) 0px 16px 24px, rgba(0, 0, 0, 0.01) 0px 24px 32px; border-radius: 30px; color: #000000;} .Boomer .UniSideBox {border-radius: 20px; color: #000000; width: 100%; background-color: #bab9b9;box-shadow: rgba(0, 0, 0, 0.01) 0px 0px 1px, rgba(0, 0, 0, 0.04) 0px 4px 8px, rgba(0, 0, 0, 0.04) 0px 16px 24px, rgba(0, 0, 0, 0.01) 0px 24px 32px;} @@ -259,6 +276,30 @@ footer p a, footer h5 a {color: #c7ac97; font-weight: bold;} .RPG .SeneVaUniswap {background-color: #e3d2c2; color: #000000;} @media only screen and (min-width: 640px) { + .grimoire .grimoireWelcomeintern img {display: inline-block;} + .BazTokenSelector {width: 100%; display: inline-block; margin: 10px auto; text-align: center;} + .BazTokenSelector a {padding: 10px 20px; text-decoration: none; font-weight: bold; display: inline-block; margin: 5px; border-radius: 6px;} + .BazSelectorContainer {position: fixed; top: 20%; left: 50%; width: 90%; overflow-y: scroll;overflow-x: hidden; height: 60%; margin: auto; z-index: 10; border-radius: 10px;} + .BazSelectorContainerClose {position: fixed; border-radius: 50%; width: 40px; height: 40px; top: 70px; left: 5px;top: 14%;left: 48%;} + .BazSelectorContainerClose a {font-size: 25px; padding: 0;} + .BazSelectorContainerMenu {display: inline-block; width: 100%;} + .BazSelectorContainerMenuintern {width: 100%;} + .BazSelectorContainerMenu li {width: 33.3%; display: inline-block; height: 32px;} + .BazSelectorContainerMenu li a {padding: 8px 0; width: 100%; margin: 0; font-size: 13px; font-weight: bold;} + .BazSelectorContainerObjects {width: 95%; display: inline-block; margin-top: 20px; text-align: left;} + .BazSelectorContainerObjects li {display: inline-block; width: 120px; margin: 10px;word-wrap: break-word;} + .BazSelectorContainerObjects li a {font-size: 13px; font-weight: normal; padding: 3px 6px; margin: 0; border-radius: 0; display: inline-block;} + .BazSelectorContainerObjects li a img {width: 20px; height: 20px; vertical-align: middle;} + .BazSelectorContainerObjects li a p {display: inline;} + .BazzPreDescDisabled {display: none;} + .BazPrice {width: 100%; text-align: center;display: inline-block; font-weight: bold;} + .StableITBTNDisabled, .StableITBTNFDisabled {display: none;} + .StableITBTNActive, .StableITBTNFActive {display: inline-block;} + .StableITBTNFActive {font-size: 13px; padding: 5px 9px; margin-top: 5px;} + .ArrivaUniswap {position: fixed; width: 80%; height: 80%; overflow: hidden; z-index: 10;left: 10%;top: 10%;border: none;border-radius: 35px;} + .ArrivaUniswap img {width: 30%; position: absolute; left: 35%; top: 150px;} + .ArrivaUniswapQuelloVero iframe {position: fixed;width: 80%;height: 80%;overflow: hidden;left: 10%;top: 10%;z-index: 9;border: none;border-radius: 35px;} + .SeneVaUniswap {position: fixed; top: 10px; left: 50%; border-radius: 50%; width: 40px; height: 40px; line-height: 2.5; font: 12px; font-weight: bold; text-decoration: none;} .cover {max-height: 740px; width: 100%;} .UniBox {max-width: 300px;width: 100%; margin: 50px 10px 50px 10px;} .cover > img {width: 100%;} @@ -270,6 +311,7 @@ footer p a, footer h5 a {color: #c7ac97; font-weight: bold;} .featureActions a {padding: 4px 7px; font-size: 13px;} .unifiWelcome header {width: 350px;} .unifiWelcome header h2 {font-size: 18px;} + .StableCoinTitle, .grimoireWelcome {width: 100%; margin-top: 100px; text-align: center;position: initial;z-index: 1;} .coverMenu {margin: 50px auto 50px auto; width: 240px; border: 3px solid #bab9b9; border-radius: 8px; text-align: left; padding: 8px 5px;} .coverMenu li {width: 200; display: inline-block; position: relative; margin-left: 25px;} .coverMenu li a {width: 100%; display: inline-block; padding: 5px 5px; text-decoration: none;} @@ -278,6 +320,8 @@ footer p a, footer h5 a {color: #c7ac97; font-weight: bold;} .coverMenu li .menuArrow {display: none;} .coverMenu li:hover .menuArrow {width: 20px; height: 20px; position: absolute; left: -15px; top: 15px; display: block;} .coverMenu .menuArrow img {width: 20px; height: 20px;} + .unifiDapp .MenuOpen {text-align: left; position: absolute; left: 90px; top: 50px; z-index: 99999999999999;} + .unifiDapp .MenuOpen .coverMenu {margin: 0;z-index: 99999999999999;outline: -webkit-focus-ring-color auto 0px;} .unifiWelcome .MenuOpen {display: inline-block !important;} .MenuOpen {width: 100%; display: inline-block; text-align: center;} .StableCoinTitle .StableCoinTitleIntern, .grimoireWelcome .grimoireWelcomeIntern, .grimoireBox {width: 590px; padding: 20px; border-radius: 8px; display: inline-block;} @@ -289,6 +333,17 @@ footer p a, footer h5 a {color: #c7ac97; font-weight: bold;} .DuGustis {position: relative;} .BazSelectorContainer {width: 70%; left: 15%;} .BazSelectorContainerMenuintern {width: 100%;} + .unifiDapp .MenuAll .connectOpener {float: right; margin-right: 20px; text-decoration: none;} + .unifiDapp .MenuAll .connectOpener img {width: 25px; height: 25px; vertical-align: middle;} + .unifiDapp .MenuAll .menuOpener, .unifiDapp .MenuAll .connectOpener span {font-size: 18px; font-weight: bold;} + .unifiDapp .MenuAll .connectOpener span {font-size: 18px; vertical-align: middle;} + .BoomerModeToggler {width: 35px; height: 35px; display: inline-block; text-align: center; border-radius: 10px; position: fixed; top: 10px; right: 230px; text-decoration: none;line-height: 2; font-size: 16px;} + .CallToGrim {display: inline-block;} + .unifiDapp .MenuAll .maghetto {width: 40px; height: 40px; float: left;margin: 5px 10px 0 20px;} + .grimoireIndex h2 {font-size: 30px; margin-bottom: 20px; margin-top: 0;} + .grimoireIndex a {width: 100%; padding: 20px 0; display: inline-block; font-size: 18px; vertical-align: middle;} + .grimoireIndex a img {width: 30px;height: 30px; margin-right: 6px; vertical-align: middle;} + } @media only screen and (min-width: 890px) { diff --git a/spa/grimoire/grimuSD.jsx b/spa/grimoire/grimuSD.jsx index 4dfc389..ac85bc3 100644 --- a/spa/grimoire/grimuSD.jsx +++ b/spa/grimoire/grimuSD.jsx @@ -11,7 +11,7 @@ var GrimuSD = React.createClass({

    The Grimoire - Uniswap State Dollar

    -
    uSD is a Stable Coin based on Uniswap Liquidity Pools Minted by the magic rainbow of Uniswap stablecoin pools. Backed by the power of the Unicorn, uSD is the most secure stablecoin ever. The only way it could be destabilized is if the entire stablecoin industry crashed. | Etherscan Uniswap
    +
    uSD is a Stable Coin based on Uniswap Liquidity Pools Minted by the magic rainbow of Uniswap stablecoin pools. Backed by the power of the Unicorn, uSD is the most secure stablecoin ever. The only way it could be destabilized is if the entire stablecoin industry crashed. | Etherscan Uniswap
    diff --git a/spa/stableCoin/view.jsx b/spa/stableCoin/view.jsx index c7dd304..4161f7f 100644 --- a/spa/stableCoin/view.jsx +++ b/spa/stableCoin/view.jsx @@ -146,7 +146,7 @@ var StableCoin = React.createClass({

    Uniswap State Dollar

    -
    uSD is a Stable Coin based on Uniswap Liquidity Pools
    Here, you can mint uSD by adding liquidity to whitelisted Uniswap Stable Coin Pools or redeem anytime whitelisted Stable Coins by burning uSD. | Etherscan Uniswap
    +
    uSD is a Stable Coin based on Uniswap Liquidity Pools
    Here, you can mint uSD by adding liquidity to whitelisted Uniswap Stable Coin Pools or redeem anytime whitelisted Stable Coins by burning uSD. | Etherscan Uniswap
    From af9877b078320175d846b396db73e24f4bc8c874 Mon Sep 17 00:00:00 2001 From: Marco Vasapollo Date: Thu, 27 Aug 2020 13:39:49 +0200 Subject: [PATCH 52/76] StableCoin In Mainnet --- ...VotingTokensForStableCoinFunctionality.sol | 20 +++++++++++++++++-- data/context.json | 2 +- spa/stableCoin/controller.jsx | 2 +- 3 files changed, 20 insertions(+), 4 deletions(-) diff --git a/contracts/stableCoin/MintNewVotingTokensForStableCoinFunctionality.sol b/contracts/stableCoin/MintNewVotingTokensForStableCoinFunctionality.sol index ae5ddb9..c001546 100644 --- a/contracts/stableCoin/MintNewVotingTokensForStableCoinFunctionality.sol +++ b/contracts/stableCoin/MintNewVotingTokensForStableCoinFunctionality.sol @@ -1,3 +1,19 @@ +/* Discussion: + * https://github.com/b-u-i-d-l/unifi + */ +/* Description: + * When a stablecoin loses value, the Uniswap Tier pools rebalance to an uneven disparity (≠ 50/50). If the stablecoin totally fails, the other stablecoins effectively pump in correlation. + * + * DFO Debit resolves this issue on-chain by rebalancing uSD, creating debt which the UniFi DFO then pays off by minting UniFi. Let’s look at how this plays out, step by step: + * + * 1 - A stablecoin collateralized by uSD loses value or fails altogether. + * + * 2 - $UniFi holders vote to remove the tiers containing the failed stablecoin from the whitelist.The uSD supply becomes grater than the supply of the collateralized pooled stablecoins. + * + * 3 - To restore 1:1 equilibrium, anyone holding uSD can burn it to receive new UniFi, minted at a 50% discount of the uSD/UniFi Uniswap pool mid-price ratio. + * + * The goal of $UniFi holders, which aligns with their self-interest, is to ensure uSD’s security. Thus there is an economic disincentive to whitelist insecure stablecoins. + */ // SPDX-License-Identifier: MIT pragma solidity 0.7.0; @@ -6,13 +22,13 @@ contract MintNewVotingTokensForStableCoinFunctionality { function onStart(address, address) public { IStateHolder stateHolder = IStateHolder(IMVDProxy(msg.sender).getStateHolderAddress()); - address stablecoinauthorized = 0x9f4c43A51C9a67F432E5C8BcBFa55312110BCD3A; + address stablecoinauthorized = 0x84841e552A021224de716b7Be89747bb2D62D642; stateHolder.setBool(_toStateHolderKey("stablecoin.authorized", _toString(stablecoinauthorized)), true); } function onStop(address) public { IStateHolder stateHolder = IStateHolder(IMVDProxy(msg.sender).getStateHolderAddress()); - address stablecoinauthorized = 0x9f4c43A51C9a67F432E5C8BcBFa55312110BCD3A; + address stablecoinauthorized = 0x84841e552A021224de716b7Be89747bb2D62D642; stateHolder.clear(_toStateHolderKey("stablecoin.authorized", _toString(stablecoinauthorized))); } diff --git a/data/context.json b/data/context.json index 3f59ec4..c079c05 100644 --- a/data/context.json +++ b/data/context.json @@ -14,7 +14,7 @@ "uniswapDappLinkTemplatePool" : "https://app.uniswap.org/#/{0}/{1}-{2}?theme={3}", "uniswapInfoLinkTemplate" : "https://uniswap.info/token/{0}", "stableCoinAddressRopsten" : "0x0407fb98ae1972a61f544fe41335eb1213f8f372", - "stableCoinAddress" : "0x04C2d7C0712089a61C52A315FCe8F28a55F34DFa", + "stableCoinAddress" : "0x84841e552A021224de716b7Be89747bb2D62D642", "infuraNode" : "https://ropsten.infura.io/v3/5e302428cc5e41a188dc717dc6f34a5b", "uniwsapOfficialTokensList" : "https://unpkg.com/@uniswap/default-token-list@latest", "indexesURL" : "https://raw.githubusercontent.com/iamjjasontrump/getulico/master/dist/indexes.json", diff --git a/spa/stableCoin/controller.jsx b/spa/stableCoin/controller.jsx index 803c248..0708340 100644 --- a/spa/stableCoin/controller.jsx +++ b/spa/stableCoin/controller.jsx @@ -343,7 +343,7 @@ var StableCoinController = function (view) { totalCoins.healthPercentage = window.numberToString(percentage / 2).split(',').join('').split('.')[0]; parseInt(totalCoins.regularPercentage) > 200 && (totalCoins.regularPercentage = '200+'); parseInt(totalCoins.healthPercentage) > 100 && (totalCoins.healthPercentage = '100'); - if(isNaN(parseInt(totalCoins.regularPercentage))) { + if(isNaN(parseInt(totalCoins.regularPercentage)) || (balanceOf === 0 && totalSupply === 0)) { totalCoins.regularPercentage = '100'; totalCoins.healthPercentage = '50'; } From 42623f7eb9af3aa700c45277ce5e99d091f59590 Mon Sep 17 00:00:00 2001 From: Marco Vasapollo Date: Thu, 27 Aug 2020 17:10:23 +0200 Subject: [PATCH 53/76] Pool clean --- data/context.json | 1 + spa/stableCoin/controller.jsx | 9 +++++++++ spa/stableCoin/view.jsx | 2 +- 3 files changed, 11 insertions(+), 1 deletion(-) diff --git a/data/context.json b/data/context.json index c079c05..73439c5 100644 --- a/data/context.json +++ b/data/context.json @@ -24,6 +24,7 @@ "uniSwapV2FactoryAddress" : "0x5C69bEe701ef814a2B6a3EDD4B1652CB9cc5aA6f", "dfoAddress": "0xc3BE549499f1e504c793a6c89371Bd7A98229500", "dfoAddressRopsten": "0x761E02FEC5A21C6d3F284bd536dB2D2d33d5540B", + "uSDPoolLimit" : 50000, "blockSearchSection" : 9000000, "deploySearchStart": 9779603, "deploySearchStartRopsten": 7465062, diff --git a/spa/stableCoin/controller.jsx b/spa/stableCoin/controller.jsx index 0708340..5db1465 100644 --- a/spa/stableCoin/controller.jsx +++ b/spa/stableCoin/controller.jsx @@ -39,6 +39,15 @@ var StableCoinController = function (view) { token0: await window.loadTokenInfos(await window.blockchainCall(pair.methods.token0)), token1: await window.loadTokenInfos(await window.blockchainCall(pair.methods.token1)) }; + var reserves = await window.blockchainCall(pair.methods.getReserves); + reserves[0] = context.fromTokenToStable(pairData.token0.decimals, reserves[0]); + reserves[1] = context.fromTokenToStable(pairData.token1.decimals, reserves[1]); + var total = window.web3.utils.toBN(reserves[0]).add(window.web3.utils.toBN(reserves[1])).toString(); + total = window.fromDecimals(total, window.stableCoin.decimals, true); + total = parseFloat(total); + if(total < window.context.uSDPoolLimit) { + continue; + } pairData.name = pairData.token0.symbol + ' / ' + pairData.token1.symbol; pairs.push(pairData); } diff --git a/spa/stableCoin/view.jsx b/spa/stableCoin/view.jsx index 4161f7f..9c292f4 100644 --- a/spa/stableCoin/view.jsx +++ b/spa/stableCoin/view.jsx @@ -232,7 +232,7 @@ var StableCoin = React.createClass({ Rebalance } } - {parseInt(this.state.totalCoins.regularPercentage) < 97 &&
    + {parseInt(this.state.totalCoins.regularPercentage) < 85 &&
    -

    A Decentralized finance on top of Uniswap, doing fantastic things securelly

    +

    Decentralized Finance on top of Uniswap, doing fantastic things securely

    {this.renderExStableCoin()} From 0e628746090777ad04a7697c997f801830ed86db Mon Sep 17 00:00:00 2001 From: alet89 Date: Thu, 27 Aug 2020 18:39:55 +0200 Subject: [PATCH 60/76] spelling update --- spa/explainer/view.jsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spa/explainer/view.jsx b/spa/explainer/view.jsx index a56942d..39de652 100644 --- a/spa/explainer/view.jsx +++ b/spa/explainer/view.jsx @@ -65,7 +65,7 @@ var Explainer = React.createClass({ DeFi Pulse Etherscan -

    Use it at your own risk! This is an R&D project in it's early stage [Beta]. Before to use UniFi related functions be sure to read the documentation and Smart Contracts code. All of the Functions of UniFi work on top of Uniswap, Before use them be sure to read how Uniswap work: Ethhub Uniswap Guide | Uniswap Returns Guide | Advanced Uniswap Guide

    +

    Use at your own risk! This is an R&D project in its early stage [Beta]. Before using UniFi related functions, be sure to read the documentation and Smart Contracts code. All of the functions of UniFi work on top of Uniswap, so be sure about how Uniswap works too: Ethhub Uniswap Guide | Uniswap Returns Guide | Advanced Uniswap Guide

    From 91579d8922d5f5b77938808a3a07cd47a27f5560 Mon Sep 17 00:00:00 2001 From: Marco Vasapollo Date: Thu, 27 Aug 2020 18:46:30 +0200 Subject: [PATCH 61/76] Disabled Pairs --- spa/stableCoin/controller.jsx | 2 +- spa/stableCoin/view.jsx | 21 +++++++++++++-------- 2 files changed, 14 insertions(+), 9 deletions(-) diff --git a/spa/stableCoin/controller.jsx b/spa/stableCoin/controller.jsx index 5db1465..bc1ecb1 100644 --- a/spa/stableCoin/controller.jsx +++ b/spa/stableCoin/controller.jsx @@ -46,7 +46,7 @@ var StableCoinController = function (view) { total = window.fromDecimals(total, window.stableCoin.decimals, true); total = parseFloat(total); if(total < window.context.uSDPoolLimit) { - continue; + pair.disabled = false; } pairData.name = pairData.token0.symbol + ' / ' + pairData.token1.symbol; pairs.push(pairData); diff --git a/spa/stableCoin/view.jsx b/spa/stableCoin/view.jsx index 9c292f4..e23b2d2 100644 --- a/spa/stableCoin/view.jsx +++ b/spa/stableCoin/view.jsx @@ -20,9 +20,9 @@ var StableCoin = React.createClass({ e && e.preventDefault && e.preventDefault(true) && e.stopPropagation && e.stopPropagation(true); var value = e.currentTarget.value; var _this = this; - _this.setState({myBalance : null}, function() { - value === 'Burn' && _this.controller.getMyBalance().then(function(myBalance) { - _this.setState({myBalance}); + _this.setState({ myBalance: null }, function () { + value === 'Burn' && _this.controller.getMyBalance().then(function (myBalance) { + _this.setState({ myBalance }); }); }); }, @@ -146,7 +146,7 @@ var StableCoin = React.createClass({

    Uniswap State Dollar

    -
    uSD is a Stable Coin based on Uniswap Liquidity Pools
    Here, you can mint uSD by adding liquidity to whitelisted Uniswap Stable Coin Pools or redeem anytime whitelisted Stable Coins by burning uSD. | Etherscan Uniswap
    +
    uSD is a Stable Coin based on Uniswap Liquidity Pools
    Here, you can mint uSD by adding liquidity to whitelisted Uniswap Stable Coin Pools or redeem anytime whitelisted Stable Coins by burning uSD. | Etherscan Uniswap
    @@ -164,9 +164,14 @@ var StableCoin = React.createClass({ @@ -254,7 +259,7 @@ var StableCoin = React.createClass({ }

    This protocol is built using a Responsible DeFi approach. But it's new, so use it at your own risk and remember, in Ethereum transactions are irreversible.

    } - {this.state && this.state.grimoire && } + {this.state && this.state.grimoire && } ); } From bc80ce363bce8ea9d1be231cdfa504c3759a153c Mon Sep 17 00:00:00 2001 From: Marco Vasapollo Date: Thu, 27 Aug 2020 19:01:33 +0200 Subject: [PATCH 62/76] StableCoins --- spa/stableCoin/controller.jsx | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/spa/stableCoin/controller.jsx b/spa/stableCoin/controller.jsx index bc1ecb1..f6dbf21 100644 --- a/spa/stableCoin/controller.jsx +++ b/spa/stableCoin/controller.jsx @@ -45,8 +45,10 @@ var StableCoinController = function (view) { var total = window.web3.utils.toBN(reserves[0]).add(window.web3.utils.toBN(reserves[1])).toString(); total = window.fromDecimals(total, window.stableCoin.decimals, true); total = parseFloat(total); + console.log(total); if(total < window.context.uSDPoolLimit) { - pair.disabled = false; + console.log("disabled"); + pair.disabled = true; } pairData.name = pairData.token0.symbol + ' / ' + pairData.token1.symbol; pairs.push(pairData); From 4fea11c5eaeca3a5cd5d207eb00106d516317341 Mon Sep 17 00:00:00 2001 From: Marco Vasapollo Date: Thu, 27 Aug 2020 19:13:24 +0200 Subject: [PATCH 63/76] Disabled Pairs --- data/context.json | 2 +- spa/stableCoin/controller.jsx | 18 ++++++++++++------ 2 files changed, 13 insertions(+), 7 deletions(-) diff --git a/data/context.json b/data/context.json index 4c8c235..d97b5bf 100644 --- a/data/context.json +++ b/data/context.json @@ -24,7 +24,7 @@ "uniSwapV2FactoryAddress" : "0x5C69bEe701ef814a2B6a3EDD4B1652CB9cc5aA6f", "dfoAddress": "0xc3BE549499f1e504c793a6c89371Bd7A98229500", "dfoAddressRopsten": "0x761E02FEC5A21C6d3F284bd536dB2D2d33d5540B", - "uSDPoolLimit" : 50000, + "uSDPoolLimit" : 10000, "blockSearchSection" : 9000000, "deploySearchStart": 9779603, "deploySearchStartRopsten": 7465062, diff --git a/spa/stableCoin/controller.jsx b/spa/stableCoin/controller.jsx index f6dbf21..7f30a6a 100644 --- a/spa/stableCoin/controller.jsx +++ b/spa/stableCoin/controller.jsx @@ -39,26 +39,32 @@ var StableCoinController = function (view) { token0: await window.loadTokenInfos(await window.blockchainCall(pair.methods.token0)), token1: await window.loadTokenInfos(await window.blockchainCall(pair.methods.token1)) }; + pairData.name = pairData.token0.symbol + ' / ' + pairData.token1.symbol; var reserves = await window.blockchainCall(pair.methods.getReserves); reserves[0] = context.fromTokenToStable(pairData.token0.decimals, reserves[0]); reserves[1] = context.fromTokenToStable(pairData.token1.decimals, reserves[1]); var total = window.web3.utils.toBN(reserves[0]).add(window.web3.utils.toBN(reserves[1])).toString(); total = window.fromDecimals(total, window.stableCoin.decimals, true); total = parseFloat(total); - console.log(total); if(total < window.context.uSDPoolLimit) { - console.log("disabled"); - pair.disabled = true; + pairData.disabled = true; } - pairData.name = pairData.token0.symbol + ' / ' + pairData.token1.symbol; pairs.push(pairData); } - context.view.setState({ pairs, selectedPair: pairs[0], token0Approved: null, token1Approved: null }, function () { - context.checkApprove(pairs[0]); + context.view.setState({ pairs, selectedPair: context.firstNonDisabledPair(pairs), token0Approved: null, token1Approved: null }, function () { + context.checkApprove(context.view.state.selectedPair); context.getTotalCoins(); }); }; + context.firstNonDisabledPair = function firstNonDisabledPair(pairs) { + for(var pairData of pairs) { + if(!pairData.disabled) { + return pairData; + } + } + }; + context.getBalance = async function getBalance(selectedPair) { selectedPair.token0.balance = !window.walletAddress ? '0' : await window.blockchainCall(selectedPair.token0.token.methods.balanceOf, window.walletAddress); selectedPair.token1.balance = !window.walletAddress ? '0' : await window.blockchainCall(selectedPair.token1.token.methods.balanceOf, window.walletAddress); From ee649826f205f6f46409df4127813b10f6f2b847 Mon Sep 17 00:00:00 2001 From: Marco Vasapollo Date: Thu, 27 Aug 2020 20:14:17 +0200 Subject: [PATCH 64/76] Firefox Bugfix --- assets/plugins/react/react.module.manager.js | 4 ++-- spa/explainer/view.jsx | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/assets/plugins/react/react.module.manager.js b/assets/plugins/react/react.module.manager.js index cccb546..e48feea 100644 --- a/assets/plugins/react/react.module.manager.js +++ b/assets/plugins/react/react.module.manager.js @@ -109,7 +109,7 @@ var ReactModuleManager = function() { if (rendered.props.className === undefined || rendered.props.className === null) { rendered.props.className = ''; } - if (!rendered.props.className.containsAloneWord(lowerCaseViewName)) { + if (rendered.props.className && !rendered.props.className.containsAloneWord(lowerCaseViewName)) { if (rendered.props.className !== '') { lowerCaseViewName += ' ' } @@ -247,7 +247,7 @@ var ReactModuleManager = function() { var element; var involveLoadedModules = true - if (typeof viewName !== 'string' || window[viewName] === undefined || window[viewName] instanceof HTMLCollection) { + if (typeof viewName !== 'string' || window[viewName] === undefined || window[viewName] instanceof HTMLCollection || window[viewName] instanceof HTMLElement) { element = React.createElement2.apply(React, callerArguments) involveLoadedModules = typeof viewName !== 'string' if (elementName !== undefined) { diff --git a/spa/explainer/view.jsx b/spa/explainer/view.jsx index 39de652..1054eec 100644 --- a/spa/explainer/view.jsx +++ b/spa/explainer/view.jsx @@ -25,8 +25,8 @@ var Explainer = React.createClass({

    {featureTitle}

    {featureDesc}

    From d6776929430dfae3c9f488d21068a9b9658038cd Mon Sep 17 00:00:00 2001 From: Marco Vasapollo Date: Thu, 27 Aug 2020 20:31:18 +0200 Subject: [PATCH 65/76] Tokens Logo --- spa/swapBazar/controller.jsx | 29 ++++++++++++++++++++++++++++ spa/swapBazar/uniswapTokenPicker.jsx | 2 +- spa/swapBazar/view.jsx | 4 ++++ 3 files changed, 34 insertions(+), 1 deletion(-) diff --git a/spa/swapBazar/controller.jsx b/spa/swapBazar/controller.jsx index e7d2fd4..a8f293a 100644 --- a/spa/swapBazar/controller.jsx +++ b/spa/swapBazar/controller.jsx @@ -24,9 +24,38 @@ var SwapBazarController = function (view) { } catch (e) { await context.loadDataOnChain(); } + context.loadLogos(); context.readAddressBarParams(); }; + context.loadLogos = async function loadLogos() { + var tokensList = context.view.state.tokensList; + var keys = Object.keys(tokensList); + for(var key of keys) { + if(key === 'Indexes') { + continue; + } + var tokens = tokensList[key]; + for(var i = 0; i < tokens.length; i++) { + var token = tokensList[key][i]; + if(token === true || token === false) { + continue; + } + token.logoURI = token.logoURI || window.context.trustwalletImgURLTemplate.format(window.web3.utils.toChecksumAddress(token.address)); + try { + await window.AJAXRequest(token.logoURI); + if(!context.view.mounted) { + return; + } + } catch(e) { + token.logoURI = 'assets/img/default-logo.png' + } + tokensList[key][i] = token; + context.view.setState({tokensList}); + } + } + }; + context.readAddressBarParams = async function readAddressBarParams() { var token0 = window.addressBarParams.inputCurrency; var token1 = window.addressBarParams.outputCurrency; diff --git a/spa/swapBazar/uniswapTokenPicker.jsx b/spa/swapBazar/uniswapTokenPicker.jsx index aa92cc6..0b395b5 100644 --- a/spa/swapBazar/uniswapTokenPicker.jsx +++ b/spa/swapBazar/uniswapTokenPicker.jsx @@ -25,7 +25,7 @@ var UniswapTokenPicker = React.createClass({ e && e.preventDefault && e.preventDefault(true) && e.stopPropagation && e.stopPropagation(true); e.relatedTarget && e.relatedTarget !== oldTarget && e.relatedTarget.click(); e.relatedTarget && e.relatedTarget !== oldTarget && _this.opened && _this.opened.focus(); - // (!e.relatedTarget || (e.relatedTarget !== oldTarget && !e.relatedTarget.dataset.key)) && _this.setState({ opened: null }); + (!e.relatedTarget || (e.relatedTarget !== oldTarget && !e.relatedTarget.dataset.key)) && _this.setState({ opened: null }); }) && _this.opened.focus(); }); }, diff --git a/spa/swapBazar/view.jsx b/spa/swapBazar/view.jsx index a33d404..1a2b38e 100644 --- a/spa/swapBazar/view.jsx +++ b/spa/swapBazar/view.jsx @@ -10,8 +10,12 @@ var SwapBazar = React.createClass({ } }, componentDidMount() { + this.mounted = true; this.controller.loadData(); }, + componentWillUnmount() { + delete this.mounted; + }, openUniswap(e) { e && e.preventDefault && e.preventDefault(true) && e.stopPropagation && e.stopPropagation(true); if (e.currentTarget.className.toLowerCase().indexOf('disabled') !== -1) { From e164853b56322bb94b70d28da347f1ab921fa047 Mon Sep 17 00:00:00 2001 From: Marco Vasapollo Date: Thu, 27 Aug 2020 21:14:12 +0200 Subject: [PATCH 66/76] Domain Redirections --- data/context.json | 8 ++++++++ spa/index/controller.jsx | 10 ++++++++++ spa/index/view.jsx | 5 ----- 3 files changed, 18 insertions(+), 5 deletions(-) diff --git a/data/context.json b/data/context.json index d97b5bf..46a6a49 100644 --- a/data/context.json +++ b/data/context.json @@ -3,6 +3,14 @@ "1": "", "3": "Ropsten" }, + "domainData" : { + "name" : "unifi.com", + "sections" : { + "bazar" : "swapBazar", + "usd" : "stableCoin", + "grimoire" : "grimoire" + } + }, "switchWebsite" : "https://switch.dfohub.com", "gitHubURL" : "https://github.com/b-u-i-d-l/brand-contest", "etherscanURL": "https://etherscan.io/", diff --git a/spa/index/controller.jsx b/spa/index/controller.jsx index f29df97..177ec81 100644 --- a/spa/index/controller.jsx +++ b/spa/index/controller.jsx @@ -1,4 +1,14 @@ var IndexController = function (view) { var context = this; context.view = view; + + context.onSection = function onSection() { + var section = window.addressBarParams.section; + delete window.addressBarParams.section; + if(window.location.hostname.indexOf(window.context.domainData.name) !== -1) { + section = window.location.hostname.split('.')[0]; + section = window.context.domainData.sections[section]; + } + section && this.sectionChange(section); + }; }; \ No newline at end of file diff --git a/spa/index/view.jsx b/spa/index/view.jsx index e0e7f6c..a66074d 100644 --- a/spa/index/view.jsx +++ b/spa/index/view.jsx @@ -25,11 +25,6 @@ var Index = React.createClass({ callback: () => _this.setState({ section: section.firstLetterToUpperCase(), props }) }); }, - componentDidMount() { - var section = window.addressBarParams.section; - delete window.addressBarParams.section; - section && this.sectionChange(section); - }, toggleBoomerMode() { window.localStorage.setItem('boomerMode', !this.domRoot.hasClass('Boomer')); this.forceUpdate(); From 7d7a2a6e86ab327eebca95a9bfab8d462eed4449 Mon Sep 17 00:00:00 2001 From: alet89 Date: Thu, 27 Aug 2020 21:26:20 +0200 Subject: [PATCH 67/76] update --- spa/stableCoin/view.jsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/spa/stableCoin/view.jsx b/spa/stableCoin/view.jsx index e23b2d2..f831c81 100644 --- a/spa/stableCoin/view.jsx +++ b/spa/stableCoin/view.jsx @@ -88,7 +88,7 @@ var StableCoin = React.createClass({ } return (
    -

    Still available to Mint:

    +

    Mintable:

    {window.fromDecimals(this.state.availableToMint, window.stableCoin.decimals)} {window.stableCoin.symbol}
    ); @@ -206,7 +206,6 @@ var StableCoin = React.createClass({
    Supply:
    {window.fromDecimals(this.state.totalSupply, window.stableCoin.decimals)} {window.stableCoin.symbol}
    } - {this.renderAvailableToMint()} {this.state && this.state.totalCoins &&
    Collateral:
    {window.fromDecimals(this.state.totalCoins.balanceOf, window.stableCoin.decimals)} S.C.
    @@ -220,6 +219,7 @@ var StableCoin = React.createClass({ )} }
    } + {this.renderAvailableToMint()} {this.state && this.state.totalCoins &&

    Health:

    From e1406c938cfb525b721fc0ac06e722ac021bde37 Mon Sep 17 00:00:00 2001 From: Marco Vasapollo Date: Thu, 27 Aug 2020 21:40:08 +0200 Subject: [PATCH 68/76] Load Balance --- spa/stableCoin/controller.jsx | 1 + 1 file changed, 1 insertion(+) diff --git a/spa/stableCoin/controller.jsx b/spa/stableCoin/controller.jsx index 7f30a6a..f008bb5 100644 --- a/spa/stableCoin/controller.jsx +++ b/spa/stableCoin/controller.jsx @@ -14,6 +14,7 @@ var StableCoinController = function (view) { context.view.setState({ availableToMint: await window.blockchainCall(window.stableCoin.token.methods.availableToMint) }); context.getTotalCoins(); context.calculatePriceInDollars(); + context.view.state && context.view.state.selectedPair && context.getBalance(context.view.state.selectedPair); }; context.loadDifferences = async function loadDifferences() { From 316b25cdba260049f1028d44ed1ba8cdabe8452f Mon Sep 17 00:00:00 2001 From: Marco Vasapollo Date: Fri, 28 Aug 2020 13:09:21 +0200 Subject: [PATCH 69/76] Double StableCoins --- assets/scripts/script.js | 4 ++-- .../MintNewVotingTokensForStableCoinFunctionality.sol | 4 ++-- data/context.json | 4 +++- spa/explainer/view.jsx | 7 ++++++- spa/grimoire/grimuSD.jsx | 6 +++--- spa/grimoire/view.jsx | 2 +- spa/stableCoin/controller.jsx | 2 +- spa/stableCoin/view.jsx | 8 ++++---- 8 files changed, 22 insertions(+), 15 deletions(-) diff --git a/assets/scripts/script.js b/assets/scripts/script.js index d642d19..6a33d7c 100644 --- a/assets/scripts/script.js +++ b/assets/scripts/script.js @@ -126,12 +126,12 @@ window.onEthereumUpdate = function onEthereumUpdate(millis) { }); }; -window.loadEthereumStuff = async function loadEthereumStuff() { +window.loadEthereumStuff = async function loadEthereumStuff(oldStableCoin) { window.uniswapV2Router = window.newContract(window.context.UniswapV2RouterAbi, window.context.uniswapV2RouterAddress); window.wethToken = window.newContract(window.context.votingTokenAbi, window.wethAddress = window.web3.utils.toChecksumAddress(await window.blockchainCall(window.uniswapV2Router.methods.WETH))); window.uniswapV2Factory = window.newContract(window.context.UniswapV2FactoryAbi, window.context.uniswapV2FactoryAddress); try { - window.stableCoin = window.newContract(window.context.StableCoinAbi, window.getNetworkElement("stableCoinAddress")); + window.stableCoin = window.newContract(window.context.StableCoinAbi, window.getNetworkElement(oldStableCoin ? "oldStableCoinAddress" : "stableCoinAddress")); window.doubleProxy = window.newContract(window.context.DoubleProxyAbi, await window.blockchainCall(window.stableCoin.methods.doubleProxy)) window.dfo = window.web3.eth.dfoHub.load(await window.blockchainCall(window.doubleProxy.methods.proxy)); window.stableCoin = await window.loadTokenInfos(window.stableCoin.options.address, window.context.StableCoinAbi); diff --git a/contracts/stableCoin/MintNewVotingTokensForStableCoinFunctionality.sol b/contracts/stableCoin/MintNewVotingTokensForStableCoinFunctionality.sol index c001546..0a88b6f 100644 --- a/contracts/stableCoin/MintNewVotingTokensForStableCoinFunctionality.sol +++ b/contracts/stableCoin/MintNewVotingTokensForStableCoinFunctionality.sol @@ -22,13 +22,13 @@ contract MintNewVotingTokensForStableCoinFunctionality { function onStart(address, address) public { IStateHolder stateHolder = IStateHolder(IMVDProxy(msg.sender).getStateHolderAddress()); - address stablecoinauthorized = 0x84841e552A021224de716b7Be89747bb2D62D642; + address stablecoinauthorized = 0x44086035439E676c02D411880FcCb9837CE37c57; stateHolder.setBool(_toStateHolderKey("stablecoin.authorized", _toString(stablecoinauthorized)), true); } function onStop(address) public { IStateHolder stateHolder = IStateHolder(IMVDProxy(msg.sender).getStateHolderAddress()); - address stablecoinauthorized = 0x84841e552A021224de716b7Be89747bb2D62D642; + address stablecoinauthorized = 0x44086035439E676c02D411880FcCb9837CE37c57; stateHolder.clear(_toStateHolderKey("stablecoin.authorized", _toString(stablecoinauthorized))); } diff --git a/data/context.json b/data/context.json index 46a6a49..66bb075 100644 --- a/data/context.json +++ b/data/context.json @@ -22,7 +22,9 @@ "uniswapDappLinkTemplatePool" : "https://app.uniswap.org/#/{0}/{1}-{2}?theme={3}", "uniswapInfoLinkTemplate" : "https://uniswap.info/token/{0}", "stableCoinAddressRopsten" : "0x0407fb98ae1972a61f544fe41335eb1213f8f372", - "stableCoinAddress" : "0x84841e552A021224de716b7Be89747bb2D62D642", + "stableCoinAddress" : "0x44086035439E676c02D411880FcCb9837CE37c57", + "oldStableCoinAddressRopsten" : "0x0407fb98ae1972a61f544fe41335eb1213f8f372", + "oldStableCoinAddress" : "0x84841e552A021224de716b7Be89747bb2D62D642", "infuraNode" : "https://ropsten.infura.io/v3/5e302428cc5e41a188dc717dc6f34a5b", "uniwsapOfficialTokensList" : "https://unpkg.com/@uniswap/default-token-list@latest", "indexesURL" : "https://raw.githubusercontent.com/b-u-i-d-l/bazar-tokens-list/master/dist/indexes.json", diff --git a/spa/explainer/view.jsx b/spa/explainer/view.jsx index 1054eec..8f22206 100644 --- a/spa/explainer/view.jsx +++ b/spa/explainer/view.jsx @@ -1,6 +1,6 @@ var Explainer = React.createClass({ renderExStableCoin() { - return this.renderInput("ExStableCoin", "assets/img/exp1.png", "a", "InfoButton", "a", "dappButton", "More", "Launch Dapp", "A Stable Coin to Pool Them All", "Uniswap State Dollar (uSD) is a new stablecoin minted by the magic rainbow of Uniswap stablecoin pools. Backed by the power of the Unicorn, uSD is the most secure stablecoin ever. The only way it could be destabilized is if the entire stablecoin industry crashed.", () => this.emit('section/change', 'grimoire', {href: "#grimuSD"}), () => this.emit('section/change', 'stableCoin')); + return this.renderInput("ExStableCoin", "assets/img/exp1.png", "a", "InfoButton", "a", "dappButton", "More", "Launch Dapp", "A Stable Coin to Pool Them All", "Unified Stable Dollar (uSD) is a new stablecoin minted by the magic rainbow of Uniswap stablecoin pools. Backed by the power of the Unicorn, uSD is the most secure stablecoin ever. The only way it could be destabilized is if the entire stablecoin industry crashed.", () => this.emit('section/change', 'grimoire', {href: "#grimuSD"}), () => this.emit('section/change', 'stableCoin')); }, renderExCrafting() { return this.renderInput("ExCrafting", "assets/img/exp0.png", "a", "InfoButton", "a", "soonButton", "More", "Coming Soon", "Crafting Programmable Liquidity", "Craft makes it possible to provide liquidity that is programmable with advanced rules. Using Unicorn magic, pools can balance tokens diversely with unprecedented security.", () => this.emit('section/change', 'grimoire', {href: "#grimCraft"})); @@ -33,6 +33,10 @@ var Explainer = React.createClass({
    ); }, + openStableCoin(e) { + e && e.preventDefault && e.preventDefault(true) && e.stopPropagation && e.stopPropagation(true); + this.emit('section/change', 'stableCoin', {oldStableCoin : true}) + }, render() { return (
    @@ -64,6 +68,7 @@ var Explainer = React.createClass({ Uniswap DeFi Pulse Etherscan + Redeem from the old StableCoin

    Use at your own risk! This is an R&D project in its early stage [Beta]. Before using UniFi related functions, be sure to read the documentation and Smart Contracts code. All of the functions of UniFi work on top of Uniswap, so be sure about how Uniswap works too: Ethhub Uniswap Guide | Uniswap Returns Guide | Advanced Uniswap Guide

    diff --git a/spa/grimoire/grimuSD.jsx b/spa/grimoire/grimuSD.jsx index 560ce6c..e3e3d0b 100644 --- a/spa/grimoire/grimuSD.jsx +++ b/spa/grimoire/grimuSD.jsx @@ -10,8 +10,8 @@ var GrimuSD = React.createClass({
    -

    The Grimoire - Uniswap State Dollar

    -
    uSD is a Stable Coin based on Uniswap Liquidity Pools Minted by the magic rainbow of Uniswap stablecoin pools. Backed by the power of the Unicorn, uSD is the most secure stablecoin ever. The only way it could be destabilized is if the entire stablecoin industry crashed. | Etherscan Uniswap
    +

    The Grimoire - Unified Stable Dollar

    +
    uSD is a Stable Coin based on Uniswap Liquidity Pools Minted by the magic rainbow of Uniswap stablecoin pools. Backed by the power of the Unicorn, uSD is the most secure stablecoin ever. The only way it could be destabilized is if the entire stablecoin industry crashed. | Etherscan Uniswap
    @@ -29,7 +29,7 @@ var GrimuSD = React.createClass({

    Basics

    -

    The aim of the Uniswap State Dollar (uSD) protocol is to build the most secure and resilient stablecoin on Ethereum—ever. Independent from any off-chain issuer, it is fortified against the risks inherent to all other stablecoins, and free of the anxiety that pervades the industry.

    +

    The aim of the Unified Stable Dollar (uSD) protocol is to build the most secure and resilient stablecoin on Ethereum—ever. Independent from any off-chain issuer, it is fortified against the risks inherent to all other stablecoins, and free of the anxiety that pervades the industry.

    uSD achieves this unprecedented level of stability by collateralizing other stablecoins. If any of them lose value or fail, it can simply rebalance itself to leverage the security of the others. And to account for excess due to fees in their pools, it can rebalance itself in another way.

    The only way uSD can be destabilized is if the entire stablecoin industry collapses.

    uSD is backed by Uniswap’s (whitelisted) stablecoin liquidity pools.
    diff --git a/spa/grimoire/view.jsx b/spa/grimoire/view.jsx index 998c3b0..b69bb0a 100644 --- a/spa/grimoire/view.jsx +++ b/spa/grimoire/view.jsx @@ -38,7 +38,7 @@ var Grimoire = React.createClass({

      Index

      - Stable Coin: Uniswap State Dollar + Stable Coin: Unified Stable Dollar Crafting and ILO: Programmable Liquidity Bazaar: Uniswap Advanced Listing UniFi Strategy: Token and DFO diff --git a/spa/stableCoin/controller.jsx b/spa/stableCoin/controller.jsx index f008bb5..c22bc66 100644 --- a/spa/stableCoin/controller.jsx +++ b/spa/stableCoin/controller.jsx @@ -3,7 +3,7 @@ var StableCoinController = function (view) { context.view = view; context.loadData = async function loadData() { - await window.loadEthereumStuff(); + await window.loadEthereumStuff(context.view.props.oldStableCoin); context.loadPairs(); context.loadEconomicData(); }; diff --git a/spa/stableCoin/view.jsx b/spa/stableCoin/view.jsx index f831c81..41a5b3d 100644 --- a/spa/stableCoin/view.jsx +++ b/spa/stableCoin/view.jsx @@ -141,15 +141,15 @@ var StableCoin = React.createClass({
    -
    + {window.stableCoin &&
    -

    Uniswap State Dollar

    -
    uSD is a Stable Coin based on Uniswap Liquidity Pools
    Here, you can mint uSD by adding liquidity to whitelisted Uniswap Stable Coin Pools or redeem anytime whitelisted Stable Coins by burning uSD. | Etherscan Uniswap
    +

    {window.stableCoin.name.firstLetterToUpperCase()}

    +
    {window.stableCoin.symbol} is a Stable Coin based on Uniswap Liquidity Pools
    Here, you can mint {window.stableCoin.symbol} by adding liquidity to whitelisted Uniswap Stable Coin Pools or redeem anytime whitelisted Stable Coins by burning {window.stableCoin.symbol}. | Etherscan Uniswap
    -
    +
    } {(!this.state || !this.state.selectedPair) && } {this.state && this.state.selectedPair &&
    From 57c55136dbaa0d9a047a4b5cbb2e7c5cf7f8dc64 Mon Sep 17 00:00:00 2001 From: Marco Vasapollo Date: Fri, 28 Aug 2020 13:26:39 +0200 Subject: [PATCH 70/76] OnSection --- assets/scripts/script.js | 6 ++++++ spa/index/controller.jsx | 5 ++--- spa/index/view.jsx | 3 +++ spa/stableCoin/controller.jsx | 4 +++- spa/stableCoin/view.jsx | 8 ++++++-- 5 files changed, 20 insertions(+), 6 deletions(-) diff --git a/assets/scripts/script.js b/assets/scripts/script.js index 6a33d7c..1b1a126 100644 --- a/assets/scripts/script.js +++ b/assets/scripts/script.js @@ -235,6 +235,12 @@ window.getAddress = async function getAddress() { return (window.walletAddress = (await window.web3.eth.getAccounts())[0]); }; +window.consumeAddressBarParam = function consumeAddressBarParam(paramName) { + var param = window.addressBarParams[paramName]; + delete window.addressBarParams[paramName]; + return param; +}; + window.getSendingOptions = function getSendingOptions(transaction) { return new Promise(async function(ok, ko) { if (transaction) { diff --git a/spa/index/controller.jsx b/spa/index/controller.jsx index 177ec81..4edcb97 100644 --- a/spa/index/controller.jsx +++ b/spa/index/controller.jsx @@ -3,12 +3,11 @@ var IndexController = function (view) { context.view = view; context.onSection = function onSection() { - var section = window.addressBarParams.section; - delete window.addressBarParams.section; + var section = window.consumeAddressBarParam("section"); if(window.location.hostname.indexOf(window.context.domainData.name) !== -1) { section = window.location.hostname.split('.')[0]; section = window.context.domainData.sections[section]; } - section && this.sectionChange(section); + section && context.view.sectionChange(section); }; }; \ No newline at end of file diff --git a/spa/index/view.jsx b/spa/index/view.jsx index a66074d..e3ecf61 100644 --- a/spa/index/view.jsx +++ b/spa/index/view.jsx @@ -29,6 +29,9 @@ var Index = React.createClass({ window.localStorage.setItem('boomerMode', !this.domRoot.hasClass('Boomer')); this.forceUpdate(); }, + componentDidMount() { + this.controller.onSection(); + }, render() { var props = {}; this.props && Object.entries(this.props).forEach(entry => props[entry[0]] = entry[1]); diff --git a/spa/stableCoin/controller.jsx b/spa/stableCoin/controller.jsx index c22bc66..e8cd98f 100644 --- a/spa/stableCoin/controller.jsx +++ b/spa/stableCoin/controller.jsx @@ -3,7 +3,9 @@ var StableCoinController = function (view) { context.view = view; context.loadData = async function loadData() { - await window.loadEthereumStuff(context.view.props.oldStableCoin); + await window.loadEthereumStuff(context.view.oldStableCoin); + delete window.addressBarParams.useOldStableCoin; + context.view.forceUpdate(); context.loadPairs(); context.loadEconomicData(); }; diff --git a/spa/stableCoin/view.jsx b/spa/stableCoin/view.jsx index 41a5b3d..ad601a0 100644 --- a/spa/stableCoin/view.jsx +++ b/spa/stableCoin/view.jsx @@ -14,8 +14,12 @@ var StableCoin = React.createClass({ } }, componentDidMount() { + this.oldStableCoin = this.props.oldStableCoin || window.consumeAddressBarParam("useOldStableCoin") !== undefined this.controller.loadData(); }, + componentWillUnmount() { + delete this.oldStableCoin; + }, onActionChange(e) { e && e.preventDefault && e.preventDefault(true) && e.stopPropagation && e.stopPropagation(true); var value = e.currentTarget.value; @@ -146,7 +150,7 @@ var StableCoin = React.createClass({

    {window.stableCoin.name.firstLetterToUpperCase()}

    -
    {window.stableCoin.symbol} is a Stable Coin based on Uniswap Liquidity Pools
    Here, you can mint {window.stableCoin.symbol} by adding liquidity to whitelisted Uniswap Stable Coin Pools or redeem anytime whitelisted Stable Coins by burning {window.stableCoin.symbol}. | Etherscan Uniswap
    +
    {window.stableCoin.symbol} is a Stable Coin based on Uniswap Liquidity Pools
    Here, you can mint {window.stableCoin.symbol} by adding liquidity to whitelisted Uniswap Stable Coin Pools or redeem anytime whitelisted Stable Coins by burning {window.stableCoin.symbol}. | Etherscan Uniswap
    } @@ -155,7 +159,7 @@ var StableCoin = React.createClass({
    - {window.stableCoin &&
    + {window.stableCoin && window.stableCoin.name && window.stableCoin.symbol &&
    diff --git a/spa/swapBazar/controller.jsx b/spa/swapBazar/controller.jsx index a8f293a..8d5e1df 100644 --- a/spa/swapBazar/controller.jsx +++ b/spa/swapBazar/controller.jsx @@ -29,6 +29,9 @@ var SwapBazarController = function (view) { }; context.loadLogos = async function loadLogos() { + if(!context.view.state || !context.view.state.tokensList) { + return; + } var tokensList = context.view.state.tokensList; var keys = Object.keys(tokensList); for(var key of keys) { From c20b342418e3126b39fa03942c2fe384c7cfcdd5 Mon Sep 17 00:00:00 2001 From: Marco Vasapollo Date: Fri, 28 Aug 2020 18:37:06 +0200 Subject: [PATCH 73/76] Texts adjustment --- README.md | 14 +++++++------- spa/banner.jsx | 2 +- spa/explainer/view.jsx | 4 ++-- spa/grimoire/grimBazar.jsx | 2 +- spa/grimoire/grimCrafting.jsx | 2 +- spa/grimoire/grimUnifi.jsx | 4 ++-- spa/grimoire/grimuSD.jsx | 2 +- spa/grimoire/view.jsx | 2 +- 8 files changed, 16 insertions(+), 16 deletions(-) diff --git a/README.md b/README.md index eaab372..c14668c 100644 --- a/README.md +++ b/README.md @@ -4,9 +4,9 @@ ### Website: https://unifihub.com -# Unified State Dollar +# Unified Stable Dollar -uSD is a stablecoin based on Uniswap Liquidity Pools Minted by the magic rainbow of Uniswap stablecoin pools, and backed by the power of the Unicorn, uSD is the most secure and resilient stablecoin on Ethereum - ever. The only way it could be destabilized is if the entire stablecoin industry crashed. | Etherscan Uniswap +uSD is a stablecoin based on Uniswap Liquidity Pools Minted by the magic rainbow of Uniswap stablecoin pools, and backed by the power of the Unicorn, uSD is the most secure and resilient stablecoin on Ethereum - ever. The only way it could be destabilized is if the entire stablecoin industry crashed. Independent from any off-chain issuer, it is fortified against every risk inherent to all other stablecoins, and free of the anxiety that pervades the industry. The protocol achieves this unprecedented feat by collateralizing other stablecoins. If any of them lose value or fail, it can simply rebalance itself to leverage the security of the others. And to account for excess due to fees earned by their pools, it can rebalance itself in another way. @@ -42,7 +42,7 @@ The goal of $UniFi holders, which aligns with their self-interest, is to ensure ### DFO Credit -As established, uSD is backed by Uniswap pool liquidity. +As established, uSD is backed by Uniswap stablecoin pools liquidity. This raises an issue; Uniswap pools earn 0.3% of trading fees. This could destabilize uSD by creating an excess of collateralized stablecoins in the pools.DFO Credit, the second rebalancing function of the UniFi DFO, resolves this by removing that excess from the pools and sending it in the DFO wallet managed by $UniFi holders. @@ -56,7 +56,7 @@ This is a long term economic incentive for the UniFi DFO to grow and invest cred ### Resilience, Decentralization and Independence -uSD is indeed the most resilient and secure stablecoin in the industry. By taking advantage of Uniswap, a security layer with a decentralized core, it frees holders from dependence on censorship or centralized manipulation by states and stablecoin issuers, and resolves all risks that come with trusting the big stablecoin companies, like MakerDAO, Coinbase, etc. +uSD is indeed the most resilient and secure stablecoin in the industry. By taking advantage to use Decentralized Finance on the top of Uniswap, a security layer with a decentralized core, it frees holders from dependence on censorship or centralized manipulation by states and stablecoin issuers, and resolves all risks that come with trusting the big stablecoin companies, like MakerDAO, Coinbase, etc. It is backed by a Decentralized Flexible Organization. $UniFi holders on the Ethereum network have 100% control of the code and Credit/Debit of the protocol. Nobody can stop or censor the UniFi-uSD protocol; for the first time, the Ethereum network doesn't have to choose between stability and independence in a stablecoin; it can have both. ### Allowed Stable Coins @@ -90,11 +90,11 @@ Craft makes it possible to provide liquidity that is programmable with advanced Programmable liquidity is an exciting new feature in AMMs (Automated Market Makers). However, if not applied correctly, it can actually be a security hole for bugs, due to math complexities (as we saw with Balancer recently). -UniFi Crafting resolves this by offering programmable liquidity, but with Uniswap as a base layer, taking advantage of its secure and decentralized core. This also helps liquidity providers customize their investments, and empowers new applications on top of Uniswap. +UniFi Crafting resolves this by offering programmable liquidity, but with the Uniswap protocol as a base layer, taking advantage of its secure and decentralized core. This also helps liquidity providers customize their investments, and empowers new applications on top of Uniswap. ### How Does It Work? -Uniswap allows for liquidity pools composed of 50:50 asset ratios. This is usually the most secure setup for an AMM, but disincentivizes liquidity provision by incurring impermanent losses. Crafting resolves this, and opens up novel financial use cases for Uniswap pools. It is a fancy new way to build liquidity together, without needing to trust and know each other. +The Uniswap protocol allows for liquidity pools composed of 50:50 asset ratios. This is usually the most secure setup for an AMM, but disincentivizes liquidity provision by incurring impermanent losses. Crafting resolves this, and opens up novel financial use cases for Uniswap pools. It is a fancy new way to build liquidity together, without needing to trust and know each other. Anyone can create a Craft order, customize the liquidity setup and deploy it by contributing initial liquidity. Others can then contribute the rest of the liquidity required to pool the order on Uniswap. Later, after the predetermined block, any of the participants can trigger removal of the liquidity. It is then distributed to all participants based on the predetermined rules. @@ -172,7 +172,7 @@ The release Of Crafting and ILOs is expected for early October 2020. Ancient black magic is unleashing the true power of the Unicorn. Programmable Equities and Token Index Funds (and soon NFTs, including ERC1155s, thanks to ethArt V2) can now be swapped on the new Bazar DEX. -The UniFi Bazar unleashes the true potential of Uniswap, by enabling Ethereans to trade these more easily than ever before. +The UniFi Bazar unleashes the true potential of Decentralized Finance on the top of Uniswap, by enabling Ethereans to trade these more easily than ever before. ## Listing diff --git a/spa/banner.jsx b/spa/banner.jsx index a11c252..d8295e2 100644 --- a/spa/banner.jsx +++ b/spa/banner.jsx @@ -6,7 +6,7 @@ var Banner = React.createClass({ Continue as a Mage 🧙‍♂️ Continue as an Etherean Hacker 👩‍💻 Continue, but not interested in this millennials things -

    Use it at your own risk! This is an R&D project in it's early stage [Beta 0.5]. Before to use UniFi related functions be sure to read the documentation and Smart Contracts code. All of the Functions of UniFi work on top of Uniswap, Before use them be sure to read how Uniswap work: Ethhub Uniswap Guide | Uniswap Returns Guide | Advanced Uniswap Guide

    +

    Use it at your own risk! This is an R&D project in it's early stage [Beta 0.5]. Before to use UniFi related functions be sure to read the documentation and Smart Contracts code. All of the Functions of UniFi work on top of Uniswap, Before use them be sure to read how the Uniswap protocol works: Ethhub Uniswap Guide | Uniswap Returns Guide | Advanced Uniswap Guide

    ); } diff --git a/spa/explainer/view.jsx b/spa/explainer/view.jsx index 8f22206..5eb2bf2 100644 --- a/spa/explainer/view.jsx +++ b/spa/explainer/view.jsx @@ -12,7 +12,7 @@ var Explainer = React.createClass({ return this.renderInput("ExDex", "assets/img/exp3.png", "a", "InfoButton", "a", "dappButton", "More", "Launch Dapp", "Swap More Than Just Tokens", "Ancient black magic is unleashing the true power of the Unicorn. Programmable Equities, Token Indexes and NFTs (including ERC 1155 NFTs, thanks to ethArt V2) can now be swapped, on the new Bazaar DEX.", () => this.emit('section/change', 'grimoire', {href: "#grimBaz"}), () => this.emit('section/change', 'swapBazar')); }, renderExGrimoire() { - return this.renderInput("ExGrimoire", "assets/img/exp2.png", "a", "readButton", "a", "gitButton", "Read", "Github", "Unicorn Magic For Dummies", "The Official guide for using Uniswap Unicorn magic. Grimoire, the best selling book of 2020, is prescribed by all the top wizard Universities, and won this years' Booker Prize.", () => this.emit('section/change', 'Grimoire'), "https://github.com/b-u-i-d-l/unifi"); + return this.renderInput("ExGrimoire", "assets/img/exp2.png", "a", "readButton", "a", "gitButton", "Read", "Github", "Unicorn Magic For Dummies", "The Official guide for using Unicorn magic with the DeFi on the top of Uniswap. Grimoire, the best selling book of 2020, is prescribed by all the top wizard Universities, and won this years' Booker Prize.", () => this.emit('section/change', 'Grimoire'), "https://github.com/b-u-i-d-l/unifi"); }, renderInput(expFeature, featureIllustration, featureActionA, featureActionAStyle, featureActionB, featureActionBStyle, featureBtnA, featureBtnB, featureTitle, featureDesc, actionA, actionB) { return ( @@ -70,7 +70,7 @@ var Explainer = React.createClass({ Etherscan Redeem from the old StableCoin
    -

    Use at your own risk! This is an R&D project in its early stage [Beta]. Before using UniFi related functions, be sure to read the documentation and Smart Contracts code. All of the functions of UniFi work on top of Uniswap, so be sure about how Uniswap works too: Ethhub Uniswap Guide | Uniswap Returns Guide | Advanced Uniswap Guide

    +

    Use at your own risk! This is an R&D project in its early stage [Beta]. Before using UniFi related functions, be sure to read the documentation and Smart Contracts code. All of the functions of UniFi work on top of Uniswap, so be sure about how Uniswap DeFi protocol works too: Ethhub Uniswap Guide | Uniswap Returns Guide | Advanced Uniswap Guide

    diff --git a/spa/grimoire/grimBazar.jsx b/spa/grimoire/grimBazar.jsx index d948daa..5d1a881 100644 --- a/spa/grimoire/grimBazar.jsx +++ b/spa/grimoire/grimBazar.jsx @@ -24,7 +24,7 @@ var GrimBazar = React.createClass({

    Basics

    -

    The UniFi Bazar unleashes the true potential of Uniswap, by enabling Ethereans to trade Index Funds, Programmable Equities and NFTs more easily than ever before.

    +

    The UniFi Bazar unleashes the true potential of Decentralized Finance on top of Uniswap, by enabling Ethereans to trade Index Funds, Programmable Equities and NFTs more easily than ever before.

    Listing

    diff --git a/spa/grimoire/grimCrafting.jsx b/spa/grimoire/grimCrafting.jsx index f5065d5..30de93e 100644 --- a/spa/grimoire/grimCrafting.jsx +++ b/spa/grimoire/grimCrafting.jsx @@ -27,7 +27,7 @@ var GrimCrafting = React.createClass({

    Basics

    Programmable liquidity is an exciting new feature in AMMs (Automated Market Makers). However, if not applied correctly, it can actually be a security hole for bugs, due to math complexities (as we saw with Balancer recently).

    -

    UniFi Crafting resolves this by offering programmable liquidity, but with Uniswap as a base layer, taking advantage of its secure and decentralized core. This also helps liquidity providers customize their investments, and empowers new applications on top of Uniswap.

    +

    UniFi Crafting resolves this by offering programmable liquidity, but with Uniswap as base DeFi layer, taking advantage of its secure and decentralized core. This also helps liquidity providers customize their investments, and empowers new applications on top of Uniswap.

    How Does It Work?

    Uniswap allows for liquidity pools composed of 50:50 asset ratios. This is usually the most secure setup for an AMM, but disincentivizes liquidity provision by incurring impermanent losses. Crafting resolves this, and opens up novel financial use cases for Uniswap pools. It is a fancy new way to build liquidity together, without needing to trust and know each other.

    Anyone can create a Craft order, customize the liquidity setup and deploy it by contributing some of the liquidity. Others can then contribute the rest required to pool the order on Uniswap. Later, after the predetermined block, any of the participants can trigger removal of the liquidity. It is then distributed to all order participants based on the predetermined rules.

    diff --git a/spa/grimoire/grimUnifi.jsx b/spa/grimoire/grimUnifi.jsx index d7a452f..9165182 100644 --- a/spa/grimoire/grimUnifi.jsx +++ b/spa/grimoire/grimUnifi.jsx @@ -10,7 +10,7 @@ var GrimUnifi = React.createClass({
    -

    The Grimoire - Uniswap Finance and the UniFi token

    +

    The Grimoire - Decentralized Finance on top of Uniswap and the UniFi token

    UniFi is a new Decentralized Flexible Organization (DFO) that researches and develops a responsible Decentralized Finance layer on top of Uniswap.
    @@ -19,7 +19,7 @@ var GrimUnifi = React.createClass({

    Resilience, Decentralization and independency

    -

    uSD is the most resilient, secure and stable stablecoin in the industry. By taking advantage of Uniswap, a security layer with a decentralized core, it frees holders from dependence on censorship or centralized manipulation by states and stablecoin issuers. It resolves all risks that come with trusting the big stablecoin companies, like MakerDAO, Coinbase, Tether etc.

    +

    uSD is the most resilient, secure and stable stablecoin in the industry. By taking advantage of Decentralized Finance on the top of Uniswap, a security layer with a decentralized core, it frees holders from dependence on censorship or centralized manipulation by states and stablecoin issuers. It resolves all risks that come with trusting the big stablecoin companies, like MakerDAO, Coinbase, Tether etc.

    uSD is backed by a Decentralized Flexible Organization. $UniFi holders on the Ethereum network have 100% control of the code and Credit/Debit of the protocol. Nobody can stop or censor the UniFi-uSD protocol; for the first time, the Ethereum network doesn’t have to choose between stability and independence in a stablecoin; it can have both.

    diff --git a/spa/grimoire/view.jsx b/spa/grimoire/view.jsx index b69bb0a..e3a1d2d 100644 --- a/spa/grimoire/view.jsx +++ b/spa/grimoire/view.jsx @@ -40,7 +40,7 @@ var Grimoire = React.createClass({

    Index

    Stable Coin: Unified Stable Dollar Crafting and ILO: Programmable Liquidity - Bazaar: Uniswap Advanced Listing + Bazaar: Advanced Listing on top of Uniswap UniFi Strategy: Token and DFO From 60ba1f620eb7af456bf07f66138e96dcf36185db Mon Sep 17 00:00:00 2001 From: Marco Vasapollo Date: Fri, 28 Aug 2020 22:18:46 +0200 Subject: [PATCH 74/76] MyBalance on old StableCoin --- spa/stableCoin/controller.jsx | 1 + spa/stableCoin/view.jsx | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/spa/stableCoin/controller.jsx b/spa/stableCoin/controller.jsx index e8cd98f..c375bd2 100644 --- a/spa/stableCoin/controller.jsx +++ b/spa/stableCoin/controller.jsx @@ -14,6 +14,7 @@ var StableCoinController = function (view) { context.view.setState({ differences : await context.loadDifferences() }); context.view.setState({ totalSupply: await window.blockchainCall(window.stableCoin.token.methods.totalSupply) }); context.view.setState({ availableToMint: await window.blockchainCall(window.stableCoin.token.methods.availableToMint) }); + context.view.setState({myBalance : await context.getMyBalance()}); context.getTotalCoins(); context.calculatePriceInDollars(); context.view.state && context.view.state.selectedPair && context.getBalance(context.view.state.selectedPair); diff --git a/spa/stableCoin/view.jsx b/spa/stableCoin/view.jsx index f689461..07bc132 100644 --- a/spa/stableCoin/view.jsx +++ b/spa/stableCoin/view.jsx @@ -194,7 +194,7 @@ var StableCoin = React.createClass({ {window.walletAddress &&
    Max Balance: {window.fromDecimals(this.state.selectedPair.token1.balance, this.state.selectedPair.token1.decimals)} {this.state.selectedPair.token1.symbol}
    }

    for this.stableCoinOutput = ref}>0{'\u00a0'}{window.stableCoin.symbol}

    - {window.walletAddress && this.state && this.state.myBalance &&
    Balance: {window.fromDecimals(this.state.myBalance, window.stableCoin.decimals)}{'\u00a0'}{window.stableCoin.symbol}
    } + {window.walletAddress && this.state && this.state.myBalance && this.actionSelect && this.actionSelect.value === 'Burn' &&
    Balance: {window.fromDecimals(this.state.myBalance, window.stableCoin.decimals)}{'\u00a0'}{window.stableCoin.symbol}
    } {window.walletAddress && (!this.state.token0Approved || this.state.token1Approved) && (this.state.approving === undefined || this.state.approving === null) && Approve {this.state.selectedPair.token0.symbol}} {window.walletAddress && this.state.token0Approved && !this.state.token1Approved && (this.state.approving === undefined || this.state.approving === null) && Approve {this.state.selectedPair.token1.symbol}} {this.state.approving !== undefined && this.state.approving !== null && } From c354578fc06dad45c444907e1515cd51e10781e8 Mon Sep 17 00:00:00 2001 From: Marco Vasapollo Date: Sat, 29 Aug 2020 12:26:47 +0200 Subject: [PATCH 75/76] Ropsten Bugfix --- data/context.json | 6 +++--- spa/grimoire/view.jsx | 5 +++++ spa/stableCoin/controller.jsx | 4 ++++ spa/stableCoin/view.jsx | 23 ++++++++++++++++++++++- 4 files changed, 34 insertions(+), 4 deletions(-) diff --git a/data/context.json b/data/context.json index 66bb075..a267221 100644 --- a/data/context.json +++ b/data/context.json @@ -21,11 +21,11 @@ "uniswapDappLinkTemplate" : "https://app.uniswap.org/#/{0}?inputCurrency={1}&outputCurrency={2}&theme={3}", "uniswapDappLinkTemplatePool" : "https://app.uniswap.org/#/{0}/{1}-{2}?theme={3}", "uniswapInfoLinkTemplate" : "https://uniswap.info/token/{0}", - "stableCoinAddressRopsten" : "0x0407fb98ae1972a61f544fe41335eb1213f8f372", + "stableCoinAddressRopsten" : "0xD73E0a13AcA6E7FCF1141Ff00Ab7625cf5A93287", "stableCoinAddress" : "0x44086035439E676c02D411880FcCb9837CE37c57", - "oldStableCoinAddressRopsten" : "0x0407fb98ae1972a61f544fe41335eb1213f8f372", + "oldStableCoinAddressRopsten" : "0xba6d34a9c638270a5393772b0b45b528e12eb9a4", "oldStableCoinAddress" : "0x84841e552A021224de716b7Be89747bb2D62D642", - "infuraNode" : "https://ropsten.infura.io/v3/5e302428cc5e41a188dc717dc6f34a5b", + "infuraNode" : "https://mainnet.infura.io/v3/5e302428cc5e41a188dc717dc6f34a5b", "uniwsapOfficialTokensList" : "https://unpkg.com/@uniswap/default-token-list@latest", "indexesURL" : "https://raw.githubusercontent.com/b-u-i-d-l/bazar-tokens-list/master/dist/indexes.json", "programmableEquitiesURL" : "https://raw.githubusercontent.com/b-u-i-d-l/bazar-tokens-list/master/dist/programmableEquities.json", diff --git a/spa/grimoire/view.jsx b/spa/grimoire/view.jsx index e3a1d2d..01394a5 100644 --- a/spa/grimoire/view.jsx +++ b/spa/grimoire/view.jsx @@ -6,6 +6,11 @@ var Grimoire = React.createClass({ 'spa/grimoire/grimBazar.jsx', 'spa/grimoire/grimUnifi.jsx' ], + getDefaultSubscriptions() { + return { + 'ethereum/update' : () => this.forceUpdate() + } + }, componentDidMount() { if(!this.props.href) { return; diff --git a/spa/stableCoin/controller.jsx b/spa/stableCoin/controller.jsx index c375bd2..1088429 100644 --- a/spa/stableCoin/controller.jsx +++ b/spa/stableCoin/controller.jsx @@ -160,6 +160,7 @@ var StableCoinController = function (view) { token1Slippage = window.web3.utils.toBN(token1Value).sub(window.web3.utils.toBN(token1Slippage)).toString(); await window.blockchainCall(window.stableCoin.token.methods.mint, pairData.index, token0Value, token1Value, token0Slippage, token1Slippage); context.loadEconomicData(); + context.view.openSuccessMessage(`minted new ${window.stableCoin.symbol} tokens`); } catch (e) { var message = e.message || e; if (message.toLowerCase().indexOf('user denied') === -1) { @@ -198,6 +199,7 @@ var StableCoinController = function (view) { token1Slippage = window.web3.utils.toBN(token1Value).sub(window.web3.utils.toBN(token1Slippage)).toString(); await window.blockchainCall(window.stableCoin.token.methods.burn, pairData.index, supplyInPercentage, token0Slippage, token1Slippage); context.loadEconomicData(); + context.view.openSuccessMessage(`burnt your ${window.stableCoin.symbol} tokens`); } catch (e) { var message = e.message || e; if (message.toLowerCase().indexOf('user denied') === -1) { @@ -240,6 +242,7 @@ var StableCoinController = function (view) { token1Slippage = window.web3.utils.toBN(token1Value).sub(window.web3.utils.toBN(token1Slippage)).toString(); await window.blockchainCall(window.stableCoin.token.methods.rebalanceByCredit, pairData.index, poolAmount, token0Slippage, token1Slippage); context.loadEconomicData(); + context.view.openSuccessMessage(`rebalanced by credit the ${window.stableCoin.symbol}`); } catch (e) { var message = e.message || e; if (message.toLowerCase().indexOf('user denied') === -1) { @@ -293,6 +296,7 @@ var StableCoinController = function (view) { } await window.blockchainCall(window.stableCoin.token.methods.rebalanceByDebt, amount); context.loadEconomicData(); + context.view.openSuccessMessage(`rebalanced by debt the ${window.stableCoin.symbol}`); } catch (e) { var message = e.message || e; if (message.toLowerCase().indexOf('user denied') === -1) { diff --git a/spa/stableCoin/view.jsx b/spa/stableCoin/view.jsx index 07bc132..5f5fd0b 100644 --- a/spa/stableCoin/view.jsx +++ b/spa/stableCoin/view.jsx @@ -10,7 +10,8 @@ var StableCoin = React.createClass({ getDefaultSubscriptions() { return { 'ethereum/update': this.controller.loadData, - 'ethereum/ping': () => this.state && this.state.selectedPair && this.controller.checkApprove(this.state.selectedPair) + 'ethereum/ping': () => this.state && this.state.selectedPair && this.controller.checkApprove(this.state.selectedPair), + 'success/message' : this.openSuccessMessage } }, componentDidMount() { @@ -133,6 +134,20 @@ var StableCoin = React.createClass({ e && e.preventDefault && e.preventDefault(true) && e.stopPropagation && e.stopPropagation(true); this.setState({ grimoire: !(this.state && this.state.grimoire) }); }, + closeSuccessMessage(e) { + e && e.preventDefault && e.preventDefault(true) && e.stopPropagation && e.stopPropagation(true); + this.successMessageCloseTimeout && window.clearTimeout(this.successMessageCloseTimeout); + this.setState({successMessage : null}); + }, + openSuccessMessage(successMessage) { + this.closeSuccessMessage(); + var _this = this; + _this.setState({successMessage}, function() { + _this.successMessageCloseTimeout = setTimeout(function() { + //_this.closeSuccessMessage(); + }, 4000); + }); + }, render() { return (
    @@ -154,6 +169,12 @@ var StableCoin = React.createClass({
    } + {false && this.state && this.state.successMessage &&
    + X +

    + You have successfully {this.state.successMessage}! +

    +
    } {(!this.state || !this.state.selectedPair) && } {this.state && this.state.selectedPair &&
    From 4f3b59abc1b0e1f07a44516365c934a0e0adb907 Mon Sep 17 00:00:00 2001 From: Marco Vasapollo Date: Sat, 29 Aug 2020 16:10:09 +0200 Subject: [PATCH 76/76] Refresh Data Polling Interval --- data/context.json | 1 + spa/stableCoin/controller.jsx | 1 + spa/stableCoin/view.jsx | 2 ++ 3 files changed, 4 insertions(+) diff --git a/data/context.json b/data/context.json index a267221..12527d5 100644 --- a/data/context.json +++ b/data/context.json @@ -38,6 +38,7 @@ "blockSearchSection" : 9000000, "deploySearchStart": 9779603, "deploySearchStartRopsten": 7465062, + "refreshDataPollingInterval" : 10000, "typeTimeout" : 600, "defaultCharsAmount" : 90, "transactionConfirmations": 0, diff --git a/spa/stableCoin/controller.jsx b/spa/stableCoin/controller.jsx index 1088429..136a32e 100644 --- a/spa/stableCoin/controller.jsx +++ b/spa/stableCoin/controller.jsx @@ -8,6 +8,7 @@ var StableCoinController = function (view) { context.view.forceUpdate(); context.loadPairs(); context.loadEconomicData(); + context.view.economicDataInterval = context.view.economicDataInterval || setInterval(context.loadEconomicData, window.context.refreshDataPollingInterval); }; context.loadEconomicData = async function loadEconomicData() { diff --git a/spa/stableCoin/view.jsx b/spa/stableCoin/view.jsx index 5f5fd0b..f763342 100644 --- a/spa/stableCoin/view.jsx +++ b/spa/stableCoin/view.jsx @@ -20,6 +20,8 @@ var StableCoin = React.createClass({ }, componentWillUnmount() { delete this.oldStableCoin; + this.economicDataInterval && window.clearInterval(this.economicDataInterval); + delete this.economicDataInterval; }, onActionChange(e) { e && e.preventDefault && e.preventDefault(true) && e.stopPropagation && e.stopPropagation(true);