This project is a portal for creating, monitoring, and managing a heavily (some would say, "absurdly") diversified investment portfolio, encompassing an arbitrary combination of four asset classes. It accommodates both novice users (through easy on-ramps like the Portis wallet, with a familiar email/password interface), and crypto-savvy investors (who know crypto, have Metamask, and own ENS domains with avatars). The asset classes are: 1) Gold - through PAXOS PAXG tokens 2) Traditional stocks and ETFs - wrapped in an UMA Synthetic, with an off-chain price and analytics data feed from Confluence Analytics for analysis and decision support (including Environmental/Social/Governance efficiency forecasts, return calculation, and backtesting that simulates daily rebalancing). That never happens in the traditional finance world, but is how this product's underlying Balancer technology works. I meant to implement a perpetual Synthetic, by creating a Balancer with two synthetics with the same constituents, expiring a month apart, and having the weights automatically adjust per block. I don't think the Balancer quite supports that yet, and anyway I ran out of time, but that's what I would do. Create a separate balancer, and have the main Balancer hold perpetual pool tokens. 3) Crypto - up to 3, chosen in settings by sector, including non-Ethereum blockchain coins, through pTokens 4) Cash - up to 3 stable coins, chosen in settings. (These limits arise from the fact that a Balancer can only accommodate 8 slices: hence 3 crypto, 3 cash, 1 gold, and 1 synthetic.) Novice users can start with one of the provided model portfolios (eventually including those of other users), and customize it from there; or they can start with the global default (equal shares of everything). One key innovation and advantage is the matching engine. The idea behind this is you can come up with an optimized portfolio of many coins, but you probably don't already have them all - and you don't need to. You can just have one pile of DAI, or USDT, or USDC, and a little bit of ETH - and it will find a way to convert what you have into what you need - if it possibly can. And if it can't it will tell you why: e.g., you need to do a bitcoin transaction to get pBTC tokens (and it goes out to pTokens for a deposit address). Or it will say you're short $250 of USDC. You can also tell it *not* to use some coins that you do have, in case you have other plans for them. In that case, it will find another way. It displays your "Pie design" graphically, in terms of coins and percentages, when the system retrieves your balances and runs the matching engine, it also displays the "plan" graphically, with a drilldown pie graph that shows exactly what it plans to do. Once the plan is satisfactory, it leads you through all the implementation steps, keeping track of its progress, and skipping steps that are already done or that you don't need. It creates a synthetic, then shows you the detailed swapping plan (through both AAVE and Uniswap, as needed). When the swaps are complete, you see the final token balances that will go into the Balancer. When the Balancer is created and funded, you can monitor/adjust both it and the synthetic. You can deposit/withdraw collateral (using the 2-step request process), and redeem synthetic tokens; it graphically displays your current collateralization, based on off-chain prices - both to you when you're logged in, and publicly in a list of all that have been created. You can adjust weights on the balancer (it is kept "controlled" by default, though you can finalize it through the interface). It will calculate the effect of the weight changes (based on current prices; effectively rebalancing it manually), and if you approve it, actually rebind the Balancer and change the weights, which can will cause tokens to flow in and out of the Balancer.
How It's Made
I built this with Buidler (with the Truffle plugin), and Ganache, on a fork of Mainnet. I wrote scripts in Buidler to do necessary setup: transferring significant token balances, and deploying many contracts needed to enable UMA functionality. The app itself is Rails; it uses web3 and ethers primarily to interact with the blockchain, on pure JS/jQuery. (This was challenging, as most tools use EC6 syntax or node/React.) I made a couple false starts. The very first attempt was with Truffle along on a private chain. I got UMA mostly working, but it was just untenable to deploy all the dozens of contracts I would need from all the different frameworks (especially all the coins, addresses, abis, etc.) Then I learned about Ganache's fork option, and unlocking addresses - and that was the way to go. It was interesting - and a testament to composability - how problems I encountered with one integration could be solved by another integration. For instance, I wanted the "large cap" portfolio to contain native Ethereum - but Balancers can only hold ERC-20 tokens. So if one of the cryptos is ETH, it adds a swap task to get aETH, and uses that in the Balancer. (There were several special cases with native Eth; I used AAVE's special address to represent ETH and track it through the process in those cases.) I also initially started with a massive controller contract - still left in the code, partially implemented (just UMA). But it turned out that since I only needed to deploy a few new contracts (and only once), and didn't need to fork and alter anything, it was really unnecessary overhead, and I could just make the calls from the client (also keeping the solution non-custodial, and relying more on the secure, audited client contracts). I also deployed a static version on IPFS (endymionjkb.eth.link), as part of the ENS integration. The demo on heroku is a "safe" version (with most blockchain calls commented out, so it doesn't steal your money :) 90% functional; server skips the heavy on-chain calls and just assumes they worked).