110 lines
47 KiB
HTML
110 lines
47 KiB
HTML
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width,initial-scale=1"> <title>Bob's Fund on Blockchain</title> <link rel="stylesheet" href="css/main.min.css"> <link rel="preconnect" href="https://fonts.googleapis.com"> <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin> <link href="https://fonts.googleapis.com/css2?family=Overpass:ital,wght@0,400;0,500;1,400;1,500;1,700&family=Roboto:ital,wght@0,400;0,500;0,700;1,400;1,500;1,700&display=swap" rel="stylesheet"> <script id="floGlobals">const floGlobals={blockchain:"FLO",adminID:"FFXy5pJnfzu2fCDLhpUremyXQjGtFpgCDN",application:"BobsFund"}</script> <script src="scripts/lib.js"></script> <script src="scripts/floCrypto.js"></script> <script src="scripts/floBlockchainAPI.min.js"></script> <script src="scripts/floExchangeAPI.js"></script> <script src="scripts/compactIDB.js"></script> <script src="scripts/btcOperator.js"></script> <script src="scripts/bobs-fund.js"></script> <script src="scripts/components.min.js"></script> <script src="https://unpkg.com/uhtml@3.0.1/es.js"></script> <script>function onLoadStartUp(){floExchangeAPI.init().then((o=>{compactIDB.initDB(floGlobals.application,{funds:{},appendix:{}}).then((o=>refresh())).catch((o=>console.error(o)))})).catch((o=>{console.error(o),notify("Unable to connect to FLO blockchain","error")}))}</script> </head> <body onload="onLoadStartUp()" data-theme="light"> <article id="loading_page" class="page"> <h3 class="h3 overpass">Bob's Fund</h3> <svg id="loader" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64"> <polygon points="17.76 23.78 17.76 40.22 32 48.44 46.24 40.22 46.24 23.78 32 15.56 17.76 23.78"/> <polyline points="17.76 23.78 32 32 46.24 23.78"/> <line x1="32" y1="48.44" x2="32" y2="32"/> <polyline points="32 2 6.02 17 6.02 47"/> <polyline points="57.98 47 57.98 17 32 2"/> <polyline points="6.02 47 32 62 57.98 47"/> </svg> <h4>Loading data from blockchain</h4> <footer class="page__footer flex align-items-center"> <svg id="rm_logo" class="icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"> <path d="M20.46,21.32C20,19.78,18.6,18.59,15.3,17a12.67,12.67,0,0,1-2.64-1.56,4.27,4.27,0,0,1-.79-1,2.6,2.6,0,0,1,0-1.41c.24-.68.49-1,2.43-2.85a7.18,7.18,0,0,0,2.09-2.92,4.25,4.25,0,0,0,0-1.77,6.52,6.52,0,0,0-2.85-3.11c-.56-.36-.81-.4-.81-.15a2.33,2.33,0,0,1-.18.45L12.4,3l-.53-.36c-.28-.21-.64-.41-.77-.49s-.46-.11-.46,0a6.21,6.21,0,0,1-.37.83s-.08,0-.17-.08c-1.15-.83-1.64-1-1.64-.73A7.33,7.33,0,0,1,7.7,3.65C6.48,5.68,5.24,6.7,4,6.7c-.56,0-.54,0-.37.64s.2.58.68.43a3.37,3.37,0,0,0,1.09-.54.86.86,0,0,1,.3-.17,1.34,1.34,0,0,1,.13.39.79.79,0,0,0,.17.4A3.5,3.5,0,0,0,7.37,7.3L7.8,7l.09.34c.12.45.19.51.62.39a4.25,4.25,0,0,0,2.17-1.54l.38-.45,0,.39A5.92,5.92,0,0,1,8.89,9.54L7.67,10.71c-2,1.93-1.89,3.51.37,5a27.41,27.41,0,0,0,2.89,1.51c.17.07.62.32,1,.54C14,19,15,20.23,15,21.48a2,2,0,0,0,0,.49h0c0,.05,0,.05.56-.1a1.89,1.89,0,0,0,.53-.21,2.41,2.41,0,0,0-.34-1.15,7.05,7.05,0,0,0-1.68-1.77,21.91,21.91,0,0,0-3.2-1.83A9.53,9.53,0,0,1,8.16,15.2a2.18,2.18,0,0,1-.74-1.55C7.42,12.79,7.86,12,9,11c1.77-1.64,2.45-2.45,2.92-3.55a2.28,2.28,0,0,0,.26-1.26A2,2,0,0,0,12,5.06l-.2-.45L12,4.3l.28-.49.09-.18L12.6,4a3.69,3.69,0,0,1,.61,1.76A3.47,3.47,0,0,1,12.94,7l-.09.25s-.21.37-.41.69A17.78,17.78,0,0,1,9.91,10.6c-1.07,1-1.43,1.62-1.47,2.47a2.05,2.05,0,0,0,.7,1.73,10.47,10.47,0,0,0,3.28,2.08c2.28,1.13,3.26,1.81,4,2.73a2.94,2.94,0,0,1,.74,1.75,1.26,1.26,0,0,0,.09.57.48.48,0,0,0,.26,0l.51-.13.29-.08,0-.28c-.13-1-1-2-2.47-3a25.52,25.52,0,0,0-3.26-1.77,8.59,8.59,0,0,1-2.23-1.43,2.09,2.09,0,0,1-.5-2.62c.26-.53.5-.83,2.35-2.6,1.51-1.45,2.15-2.58,2.15-3.79A3.67,3.67,0,0,0,13,3.48a3,3,0,0,1-.4-.42A1.85,1.85,0,0,1,13,2.33a6.74,6.74,0,0,1,1.83,1.73,2.62,2.62,0,0,1,.47,1.68,3,3,0,0,1-.55,1.84c-.45.78-.79,1.14-2.67,2.93a5.56,5.56,0,0,0-1.3,1.64,1.77,1.77,0,0,0-.21,1,1.76,1.76,0,0,0,.19.92,6.28,6.28,0,0,0,2.9,2.34,21.6,21.6,0,0,1,3.66,2c1.35,1,2,2,2,3a1.06,1.06,0,0,0,.05.47,2.83,2.83,0,0,0,1-.24C20.56,21.68,20.56,21.66,20.46,21.32ZM7.29,6.4h0a2.23,2.23,0,0,1-.9.28L6,6.72l.43-.53a15.22,15.22,0,0,0,1.89-3,3.52,3.52,0,0,1,.38-.67c.07-.08.49.2,1,.64l.39.35L9.66,4A6.7,6.7,0,0,1,7.29,6.4Zm3.58-1.11A5.8,5.8,0,0,1,9.25,6.51h0a3.3,3.3,0,0,1-.74.17l-.35,0,.39-.49a15.64,15.64,0,0,0,1.32-2,4.63,4.63,0,0,1,.28-.49c.06-.08.33.26.57.77l.28.57Zm1-1.4a1.63,1.63,0,0,1-.28.4A6.63,6.63,0,0,1,11,3.72l-.53-.56.12-.29c.2-.49.24-.51.64-.19a5.57,5.57,0,0,1,.85.78A2.78,2.78,0,0,1,11.87,3.89Z"/> </svg> <h4 class="weight-500">RanchiMall</h4> </footer> </article> <article id="error_page" class="page hidden"> <h3 class="h3 overpass">Bob's Fund</h3> <svg class="sad-face" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 500 500"> <g class="face"> <g class="eyes"> <circle cx="187.52" cy="249.17" r="13.42"/> <circle cx="312.48" cy="249.17" r="13.42"/> </g> <path d="M288,349.35a6.07,6.07,0,0,1-3.81-1.34c-.09-.07-12.31-9.4-34.14-9.4S216,347.94,215.83,348a6.1,6.1,0,0,1-7.59-9.55c.61-.5,15.4-12.08,41.76-12.08s41.15,11.58,41.76,12.08A6.1,6.1,0,0,1,288,349.35Z"/> <path d="M344.21,237.41a52,52,0,0,1-23.45-6c-15.91-8.09-21.28-19.61-21.5-20.1a4.07,4.07,0,0,1,7.41-3.36c0,.08,4.56,9.49,17.77,16.21S347.93,229,348,229a4.07,4.07,0,0,1,1.63,8A29.26,29.26,0,0,1,344.21,237.41Z"/> <path d="M155.79,237.41a29.26,29.26,0,0,1-5.45-.43,4.07,4.07,0,0,1,1.63-8c.2,0,10.43,1.87,23.59-4.81s17.73-16.13,17.78-16.23a4.07,4.07,0,0,1,7.4,3.38c-.22.49-5.59,12-21.5,20.1A52,52,0,0,1,155.79,237.41Z"/> </g> <path d="M450.16,220.16A200.16,200.16,0,0,0,108.46,78.63,200.69,200.69,0,0,0,57.61,275.68V407.4a10.17,10.17,0,1,0,20.33,0V322.6a201.91,201.91,0,0,0,99.41,84.19v52.27l-11.45.62a10.17,10.17,0,0,0,.54,20.32H167l30.69-1.66V413.45a202.3,202.3,0,0,0,104.62,0v64.88L333,480h.56a10.17,10.17,0,0,0,.54-20.32l-11.45-.62V406.79a201.91,201.91,0,0,0,99.41-84.19v84.8a10.17,10.17,0,1,0,20.33,0V275.68A200.81,200.81,0,0,0,450.16,220.16ZM250,400c-99.16,0-179.83-80.67-179.83-179.83S150.84,40.34,250,40.34,429.83,121,429.83,220.16,349.16,400,250,400Z"/> </svg> <h4 class="margin-bottom-0-5r">Oops, Couldn't get data from blockchain</h4> <footer class="page__footer flex align-items-center"> <svg id="rm_logo" class="icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"> <path d="M20.46,21.32C20,19.78,18.6,18.59,15.3,17a12.67,12.67,0,0,1-2.64-1.56,4.27,4.27,0,0,1-.79-1,2.6,2.6,0,0,1,0-1.41c.24-.68.49-1,2.43-2.85a7.18,7.18,0,0,0,2.09-2.92,4.25,4.25,0,0,0,0-1.77,6.52,6.52,0,0,0-2.85-3.11c-.56-.36-.81-.4-.81-.15a2.33,2.33,0,0,1-.18.45L12.4,3l-.53-.36c-.28-.21-.64-.41-.77-.49s-.46-.11-.46,0a6.21,6.21,0,0,1-.37.83s-.08,0-.17-.08c-1.15-.83-1.64-1-1.64-.73A7.33,7.33,0,0,1,7.7,3.65C6.48,5.68,5.24,6.7,4,6.7c-.56,0-.54,0-.37.64s.2.58.68.43a3.37,3.37,0,0,0,1.09-.54.86.86,0,0,1,.3-.17,1.34,1.34,0,0,1,.13.39.79.79,0,0,0,.17.4A3.5,3.5,0,0,0,7.37,7.3L7.8,7l.09.34c.12.45.19.51.62.39a4.25,4.25,0,0,0,2.17-1.54l.38-.45,0,.39A5.92,5.92,0,0,1,8.89,9.54L7.67,10.71c-2,1.93-1.89,3.51.37,5a27.41,27.41,0,0,0,2.89,1.51c.17.07.62.32,1,.54C14,19,15,20.23,15,21.48a2,2,0,0,0,0,.49h0c0,.05,0,.05.56-.1a1.89,1.89,0,0,0,.53-.21,2.41,2.41,0,0,0-.34-1.15,7.05,7.05,0,0,0-1.68-1.77,21.91,21.91,0,0,0-3.2-1.83A9.53,9.53,0,0,1,8.16,15.2a2.18,2.18,0,0,1-.74-1.55C7.42,12.79,7.86,12,9,11c1.77-1.64,2.45-2.45,2.92-3.55a2.28,2.28,0,0,0,.26-1.26A2,2,0,0,0,12,5.06l-.2-.45L12,4.3l.28-.49.09-.18L12.6,4a3.69,3.69,0,0,1,.61,1.76A3.47,3.47,0,0,1,12.94,7l-.09.25s-.21.37-.41.69A17.78,17.78,0,0,1,9.91,10.6c-1.07,1-1.43,1.62-1.47,2.47a2.05,2.05,0,0,0,.7,1.73,10.47,10.47,0,0,0,3.28,2.08c2.28,1.13,3.26,1.81,4,2.73a2.94,2.94,0,0,1,.74,1.75,1.26,1.26,0,0,0,.09.57.48.48,0,0,0,.26,0l.51-.13.29-.08,0-.28c-.13-1-1-2-2.47-3a25.52,25.52,0,0,0-3.26-1.77,8.59,8.59,0,0,1-2.23-1.43,2.09,2.09,0,0,1-.5-2.62c.26-.53.5-.83,2.35-2.6,1.51-1.45,2.15-2.58,2.15-3.79A3.67,3.67,0,0,0,13,3.48a3,3,0,0,1-.4-.42A1.85,1.85,0,0,1,13,2.33a6.74,6.74,0,0,1,1.83,1.73,2.62,2.62,0,0,1,.47,1.68,3,3,0,0,1-.55,1.84c-.45.78-.79,1.14-2.67,2.93a5.56,5.56,0,0,0-1.3,1.64,1.77,1.77,0,0,0-.21,1,1.76,1.76,0,0,0,.19.92,6.28,6.28,0,0,0,2.9,2.34,21.6,21.6,0,0,1,3.66,2c1.35,1,2,2,2,3a1.06,1.06,0,0,0,.05.47,2.83,2.83,0,0,0,1-.24C20.56,21.68,20.56,21.66,20.46,21.32ZM7.29,6.4h0a2.23,2.23,0,0,1-.9.28L6,6.72l.43-.53a15.22,15.22,0,0,0,1.89-3,3.52,3.52,0,0,1,.38-.67c.07-.08.49.2,1,.64l.39.35L9.66,4A6.7,6.7,0,0,1,7.29,6.4Zm3.58-1.11A5.8,5.8,0,0,1,9.25,6.51h0a3.3,3.3,0,0,1-.74.17l-.35,0,.39-.49a15.64,15.64,0,0,0,1.32-2,4.63,4.63,0,0,1,.28-.49c.06-.08.33.26.57.77l.28.57Zm1-1.4a1.63,1.63,0,0,1-.28.4A6.63,6.63,0,0,1,11,3.72l-.53-.56.12-.29c.2-.49.24-.51.64-.19a5.57,5.57,0,0,1,.85.78A2.78,2.78,0,0,1,11.87,3.89Z"/> </svg> <h4 class="h4 color-0-8 weight-500">RanchiMall</h4> </footer> </article> <header id="main_header" class="hidden"> <div class="flex align-items-center"> <svg id="main_header__logo" class="icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"> <path d="M20.46,21.32C20,19.78,18.6,18.59,15.3,17a12.67,12.67,0,0,1-2.64-1.56,4.27,4.27,0,0,1-.79-1,2.6,2.6,0,0,1,0-1.41c.24-.68.49-1,2.43-2.85a7.18,7.18,0,0,0,2.09-2.92,4.25,4.25,0,0,0,0-1.77,6.52,6.52,0,0,0-2.85-3.11c-.56-.36-.81-.4-.81-.15a2.33,2.33,0,0,1-.18.45L12.4,3l-.53-.36c-.28-.21-.64-.41-.77-.49s-.46-.11-.46,0a6.21,6.21,0,0,1-.37.83s-.08,0-.17-.08c-1.15-.83-1.64-1-1.64-.73A7.33,7.33,0,0,1,7.7,3.65C6.48,5.68,5.24,6.7,4,6.7c-.56,0-.54,0-.37.64s.2.58.68.43a3.37,3.37,0,0,0,1.09-.54.86.86,0,0,1,.3-.17,1.34,1.34,0,0,1,.13.39.79.79,0,0,0,.17.4A3.5,3.5,0,0,0,7.37,7.3L7.8,7l.09.34c.12.45.19.51.62.39a4.25,4.25,0,0,0,2.17-1.54l.38-.45,0,.39A5.92,5.92,0,0,1,8.89,9.54L7.67,10.71c-2,1.93-1.89,3.51.37,5a27.41,27.41,0,0,0,2.89,1.51c.17.07.62.32,1,.54C14,19,15,20.23,15,21.48a2,2,0,0,0,0,.49h0c0,.05,0,.05.56-.1a1.89,1.89,0,0,0,.53-.21,2.41,2.41,0,0,0-.34-1.15,7.05,7.05,0,0,0-1.68-1.77,21.91,21.91,0,0,0-3.2-1.83A9.53,9.53,0,0,1,8.16,15.2a2.18,2.18,0,0,1-.74-1.55C7.42,12.79,7.86,12,9,11c1.77-1.64,2.45-2.45,2.92-3.55a2.28,2.28,0,0,0,.26-1.26A2,2,0,0,0,12,5.06l-.2-.45L12,4.3l.28-.49.09-.18L12.6,4a3.69,3.69,0,0,1,.61,1.76A3.47,3.47,0,0,1,12.94,7l-.09.25s-.21.37-.41.69A17.78,17.78,0,0,1,9.91,10.6c-1.07,1-1.43,1.62-1.47,2.47a2.05,2.05,0,0,0,.7,1.73,10.47,10.47,0,0,0,3.28,2.08c2.28,1.13,3.26,1.81,4,2.73a2.94,2.94,0,0,1,.74,1.75,1.26,1.26,0,0,0,.09.57.48.48,0,0,0,.26,0l.51-.13.29-.08,0-.28c-.13-1-1-2-2.47-3a25.52,25.52,0,0,0-3.26-1.77,8.59,8.59,0,0,1-2.23-1.43,2.09,2.09,0,0,1-.5-2.62c.26-.53.5-.83,2.35-2.6,1.51-1.45,2.15-2.58,2.15-3.79A3.67,3.67,0,0,0,13,3.48a3,3,0,0,1-.4-.42A1.85,1.85,0,0,1,13,2.33a6.74,6.74,0,0,1,1.83,1.73,2.62,2.62,0,0,1,.47,1.68,3,3,0,0,1-.55,1.84c-.45.78-.79,1.14-2.67,2.93a5.56,5.56,0,0,0-1.3,1.64,1.77,1.77,0,0,0-.21,1,1.76,1.76,0,0,0,.19.92,6.28,6.28,0,0,0,2.9,2.34,21.6,21.6,0,0,1,3.66,2c1.35,1,2,2,2,3a1.06,1.06,0,0,0,.05.47,2.83,2.83,0,0,0,1-.24C20.56,21.68,20.56,21.66,20.46,21.32ZM7.29,6.4h0a2.23,2.23,0,0,1-.9.28L6,6.72l.43-.53a15.22,15.22,0,0,0,1.89-3,3.52,3.52,0,0,1,.38-.67c.07-.08.49.2,1,.64l.39.35L9.66,4A6.7,6.7,0,0,1,7.29,6.4Zm3.58-1.11A5.8,5.8,0,0,1,9.25,6.51h0a3.3,3.3,0,0,1-.74.17l-.35,0,.39-.49a15.64,15.64,0,0,0,1.32-2,4.63,4.63,0,0,1,.28-.49c.06-.08.33.26.57.77l.28.57Zm1-1.4a1.63,1.63,0,0,1-.28.4A6.63,6.63,0,0,1,11,3.72l-.53-.56.12-.29c.2-.49.24-.51.64-.19a5.57,5.57,0,0,1,.85.78A2.78,2.78,0,0,1,11.87,3.89Z"/> </svg> <div class="grid"> <h5 class="header__company-name">RanchiMall</h5> </div> </div> <div id="current_price" class="grid gap-1 flow-column align-items-center"> </div> <div class="dropdown"> <button id="profile_button" onclick='changeDropdownState("profile_dropdown","toggle",this)'> <svg class="icon" xmlns="http://www.w3.org/2000/svg" enable-background="new 0 0 24 24" height="24px" viewBox="0 0 24 24" width="24px" fill="#000000"> <g> <path d="M0,0h24v24H0V0z" fill="none"/> <path d="M19.14,12.94c0.04-0.3,0.06-0.61,0.06-0.94c0-0.32-0.02-0.64-0.07-0.94l2.03-1.58c0.18-0.14,0.23-0.41,0.12-0.61 l-1.92-3.32c-0.12-0.22-0.37-0.29-0.59-0.22l-2.39,0.96c-0.5-0.38-1.03-0.7-1.62-0.94L14.4,2.81c-0.04-0.24-0.24-0.41-0.48-0.41 h-3.84c-0.24,0-0.43,0.17-0.47,0.41L9.25,5.35C8.66,5.59,8.12,5.92,7.63,6.29L5.24,5.33c-0.22-0.08-0.47,0-0.59,0.22L2.74,8.87 C2.62,9.08,2.66,9.34,2.86,9.48l2.03,1.58C4.84,11.36,4.8,11.69,4.8,12s0.02,0.64,0.07,0.94l-2.03,1.58 c-0.18,0.14-0.23,0.41-0.12,0.61l1.92,3.32c0.12,0.22,0.37,0.29,0.59,0.22l2.39-0.96c0.5,0.38,1.03,0.7,1.62,0.94l0.36,2.54 c0.05,0.24,0.24,0.41,0.48,0.41h3.84c0.24,0,0.44-0.17,0.47-0.41l0.36-2.54c0.59-0.24,1.13-0.56,1.62-0.94l2.39,0.96 c0.22,0.08,0.47,0,0.59-0.22l1.92-3.32c0.12-0.22,0.07-0.47-0.12-0.61L19.14,12.94z M12,15.6c-1.98,0-3.6-1.62-3.6-3.6 s1.62-3.6,3.6-3.6s3.6,1.62,3.6,3.6S13.98,15.6,12,15.6z"/> </g> </svg> </button> <ul id="profile_dropdown" class="dropdown__panel hidden"> <li class="grid gap-0-5"> <h4 class="weight-700 margin-bottom-0-5r">Preferred currency</h4> <p>This will convert all amounts to preferred currency.</p> <sm-select id="currency_selector" class="justify-self-start"> <sm-option value="inr" selected>INR</sm-option> <sm-option value="usd">USD</sm-option> </sm-select> </li> <li class="flex align-items-center space-between"> <div class="flex weight-700">Dark theme</div> </li> <li class="interact weight-700" onclick='showPage("admin_page")'> Admin panel </li> </ul> </div> </header> <main id="home_page" class="page hidden"> <section id="homepage__hero-section"> <h3 class="h3 overpass margin-bottom-1r">Bob's Fund<br>on FLO Blockchain</h3> <p> Bob's Fund is a 20 year long term Bitcoin price linked product. Investors are entitled to 100% of Bitcoin price gains, but they must hold for 20 years. Over a very long time period, investor returns on an asset like Bitcoin should outstrip returns on conventional assets like real estate and stocks. The management fees on this product is zero. RanchiMall earns by having invested an equal amount as every investor, thus the interests of fund manager, and fund investors are totally aligned. </p> </section> <sm-input id="search_investor" type="search" placeholder="Search investor with FLO/BTC address"> <svg class="icon" slot="icon" xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 0 24 24" width="24px" fill="#000000"> <path d="M0 0h24v24H0V0z" fill="none"/> <path d="M15.5 14h-.79l-.28-.27C15.41 12.59 16 11.11 16 9.5 16 5.91 13.09 3 9.5 3S3 5.91 3 9.5 5.91 16 9.5 16c1.61 0 3.09-.59 4.23-1.57l.27.28v.79l5 4.99L20.49 19l-4.99-5zm-6 0C7.01 14 5 11.99 5 9.5S7.01 5 9.5 5 14 7.01 14 9.5 11.99 14 9.5 14z"/> </svg> </sm-input> <header class="fund-list__header"> <h4 class="h4">Funds</h4> <button id="refresh_button" class="button justify-right">Refresh</button> </header> <section> <div id="fund_list__empty-state" class="grid hidden"> <svg class="icon icon--big" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24"> <path fill="none" d="M0 0h24v24H0z"/> <path d="M12 22C6.477 22 2 17.523 2 12S6.477 2 12 2s10 4.477 10 10-4.477 10-10 10zm0-2a8 8 0 1 0 0-16 8 8 0 0 0 0 16zm-4-6h8v2H8v-2zm0-3a1.5 1.5 0 1 1 0-3 1.5 1.5 0 0 1 0 3zm8 0a1.5 1.5 0 1 1 0-3 1.5 1.5 0 0 1 0 3z"/> </svg> <h4>No Funds found</h4> </div> </section></main> <article id="admin_page" class="page page-layout hidden"> <header class="flex margin-top-1-5 align-items-center margin-bottom-1-5r"> <button onclick='showPage("home_page")'> <svg class="icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24"> <path fill="none" d="M0 0h24v24H0z"/> <path d="M7.828 11H20v2H7.828l5.364 5.364-1.414 1.414L4 12l7.778-7.778 1.414 1.414z"/> </svg> </button> <h3>Admin Panel</h3> </header> <form id="create_fund_form" class="grid gap-1-5"> <sm-switch id="fund_creation_toggle"> <div class="flex" slot="left"> Add investors to existing fund </div> </sm-switch> <section id="fund_details_form" class="grid gap-1-5 margin-bottom-0-5r"> <label class="grid gap-0-5"> Fund start date <input type="date" name="start_date" required> </label> <label class="grid gap-0-5"> Base BTC value ($) <input type="number" name="btc_base" step="0.01" pattern="[\d,]+(.\d+)?" required> </label> <label class="grid gap-0-5"> Base USD rate (₹) <input type="number" name="usd_rate" min="0" step="0.01" required> </label> <div class="grid gap-0-5"> Maximum Duration <div class="flex"> <input type="number" name="max_pv" inputmode="numeric" required> <sm-select id="max_pt" align-select="right"> <sm-option value="year(s)" selected>year(s)</sm-option> <sm-option value="month(s)">month(s)</sm-option> <sm-option value="week(s)">week(s)</sm-option> <sm-option value="day(s)">day(s)</sm-option> </sm-select> </div> </div> <sm-switch id="tapout_toggle"> <div class="flex" slot="left"> Tapout </div> </sm-switch> <section id="tapout_container" class="grid gap-1-5 hidden"> <div class="grid gap-0-5"> Tapout window <div class="flex"> <input type="number" name="tap_wv" inputmode="numeric" disabled required> <sm-select id="tap_wt" align-select="right"> <sm-option value="year(s)">year(s)</sm-option> <sm-option value="month(s)" selected>month(s)</sm-option> <sm-option value="week(s)">week(s)</sm-option> <sm-option value="day(s)">day(s)</sm-option> </sm-select> </div> </div> <div class="grid gap-0-5"> Tapout interval(Use comma separated values. e.g. 10, 15...) <div class="flex"> <input name="tap_iv" disabled required> <sm-select id="tap_it" align-select="right"> <sm-option value="year(s)" selected>year(s)</sm-option> <sm-option value="month(s)">month(s)</sm-option> </sm-select> </div> </div> </section> <label class="grid gap-0-5"> Fee <input type="number" name="fee" min="0" max="100" step="0.01" value="0" inputmode="numeric" required> </label> </section> <div id="fund_selector_container" class="grid margin-bottom-0-5r hidden"> <span class="margin-bottom-0-5r">Select Fund</span> </div> <h4>Add Investors</h4> <ul id="investors_input_list" class="grid gap-1"> <li class="investor-input grid"> <button class="remove-investor" title="Remove this investor"> <svg class="icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24"> <path fill="none" d="M0 0h24v24H0z"/> <path d="M12 10.586l4.95-4.95 1.414 1.414-4.95 4.95 4.95 4.95-1.414 1.414-4.95-4.95-4.95 4.95-1.414-1.414 4.95-4.95-4.95-4.95L7.05 5.636z"/> </svg> </button> </li> </ul> <button type="button" class="margin-bottom-1r justify-self-start" style="margin-top:-1rem" onclick="renderInvestor()"> <svg class="icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24"> <path fill="none" d="M0 0h24v24H0z"/> <path d="M11 11V5h2v6h6v2h-6v6h-2v-6H5v-2z"/> </svg> Add new </button> <button id="add_investors_button" type="submit" class="button--primary justify-self-start hidden">Add Investors</button> <button id="create_fund_button" type="submit" class="button--primary justify-self-start">Create Fund</button> </form> </article> <article id="confirm_term_page" class="page page-layout hidden"> <header class="flex margin-top-1-5 align-items-center margin-bottom-1-5r"> <button class="back-button" onclick='showPage("admin_page")'> <svg class="icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24"> <path fill="none" d="M0 0h24v24H0z"/> <path d="M7.828 11H20v2H7.828l5.364 5.364-1.414 1.414L4 12l7.778-7.778 1.414 1.414z"/> </svg> </button> <h3>Confirm Details</h3> </header> <form class="grid gap-1-5" onsubmit="return!1"> <div class="grid"> </div> <button id="create_term_button" type="submit" class="button--primary justify-self-start">Create term</button> </form> </article> <article id="confirm_fund_page" class="page page-layout hidden"> <header class="flex margin-top-1-5 align-items-center margin-bottom-1-5r"> <button class="back-button" onclick='showPage("admin_page")'> <svg class="icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24"> <path fill="none" d="M0 0h24v24H0z"/> <path d="M7.828 11H20v2H7.828l5.364 5.364-1.414 1.414L4 12l7.778-7.778 1.414 1.414z"/> </svg> </button> <h3>Confirm Details</h3> </header> <form class="grid gap-1-5" onsubmit="return!1"> <div class="grid"> </div> <button id="confirm_fund_button" type="submit" class="button--primary justify-self-start">Create Fund</button> </form> </article> <sm-popup id="withdraw_popup"> <header slot="header" class="popup__header"> <button class="popup__header__close" onclick="closePopup()"> <svg class="icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24"> <path fill="none" d="M0 0h24v24H0z"/> <path d="M12 10.586l4.95-4.95 1.414 1.414-4.95 4.95 4.95 4.95-1.414 1.414-4.95-4.95-4.95 4.95-1.414-1.414 4.95-4.95-4.95-4.95L7.05 5.636z"/> </svg> </button> <h3>Withdraw fund</h3> </header> <div id="withdraw_process"> <div id="withdraw_precess__get_priv_key"> <sm-form class="grid gap-1-5"> <sm-input id="withdraw_private_key" class="password-field" type="password" placeholder="FLO private key" error-text="Private key is invalid" autofocus data-private-key required> <label slot="right" class="interact"> <input type="checkbox" class="hidden" autocomplete="off" readonly onchange="togglePrivateKeyVisibility(this)"> <svg class="icon invisible" xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 0 24 24" width="24px" fill="#000000"> <title>Hide password</title> <path d="M0 0h24v24H0zm0 0h24v24H0zm0 0h24v24H0zm0 0h24v24H0z" fill="none"/> <path d="M12 7c2.76 0 5 2.24 5 5 0 .65-.13 1.26-.36 1.83l2.92 2.92c1.51-1.26 2.7-2.89 3.43-4.75-1.73-4.39-6-7.5-11-7.5-1.4 0-2.74.25-3.98.7l2.16 2.16C10.74 7.13 11.35 7 12 7zM2 4.27l2.28 2.28.46.46C3.08 8.3 1.78 10.02 1 12c1.73 4.39 6 7.5 11 7.5 1.55 0 3.03-.3 4.38-.84l.42.42L19.73 22 21 20.73 3.27 3 2 4.27zM7.53 9.8l1.55 1.55c-.05.21-.08.43-.08.65 0 1.66 1.34 3 3 3 .22 0 .44-.03.65-.08l1.55 1.55c-.67.33-1.41.53-2.2.53-2.76 0-5-2.24-5-5 0-.79.2-1.53.53-2.2zm4.31-.78l3.15 3.15.02-.16c0-1.66-1.34-3-3-3l-.17.01z"/> </svg> <svg class="icon visible" xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 0 24 24" width="24px" fill="#000000"> <title>Show password</title> <path d="M0 0h24v24H0z" fill="none"/> <path d="M12 4.5C7 4.5 2.73 7.61 1 12c1.73 4.39 6 7.5 11 7.5s9.27-3.11 11-7.5c-1.73-4.39-6-7.5-11-7.5zM12 17c-2.76 0-5-2.24-5-5s2.24-5 5-5 5 2.24 5 5-2.24 5-5 5zm0-8c-1.66 0-3 1.34-3 3s1.34 3 3 3 3-1.34 3-3-1.34-3-3-3z"/> </svg> </label> </sm-input> <div class="multi-state-button"> <button id="withdraw_private_key_button" type="submit" class="button button--primary cta">Confirm withdrawal</button> </div> </sm-form> </div> <div class="grid gap-0-5 hidden justify-center text-center"> <svg class="icon user-action-result__icon success" xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 0 24 24" width="24px" fill="#000000"> <path d="M0 0h24v24H0V0z" fill="none"/> <path d="M9 16.2L4.8 12l-1.4 1.4L9 19 21 7l-1.4-1.4L9 16.2z"/> </svg> <h4>Withdraw request sent</h4> <p>Balance may take upto 30mins to reflect in your FLO address</p> </div> <div class="grid gap-0-5 hidden justify-center text-center"> <svg class="icon user-action-result__icon failed" xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 0 24 24" width="24px" fill="#000000"> <path d="M0 0h24v24H0z" fill="none"/> <path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm1 15h-2v-2h2v2zm0-4h-2V7h2v6z"/> </svg> <h3>Failed</h3> </div> </div> </sm-popup> <script id="ui">const{html:html,render:renderElem}=uhtml,domRefs={};function getRef(e){return domRefs.hasOwnProperty(e)?domRefs[e].count<3?(domRefs[e].count=domRefs[e].count+1,document.getElementById(e)):(domRefs[e].ref||(domRefs[e].ref=document.getElementById(e)),domRefs[e].ref):(domRefs[e]={count:1,ref:null},document.getElementById(e))}function notify(e,t,n={}){let a;switch(t){case"success":a='<svg class="icon icon--success" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24"><path fill="none" d="M0 0h24v24H0z"/><path d="M10 15.172l9.192-9.193 1.415 1.414L10 18l-6.364-6.364 1.414-1.414z"/></svg>';break;case"error":a='<svg class="icon icon--error" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24"><path fill="none" d="M0 0h24v24H0z"/><path d="M12 22C6.477 22 2 17.523 2 12S6.477 2 12 2s10 4.477 10 10-4.477 10-10 10zm-1-7v2h2v-2h-2zm0-8v6h2V7h-2z"/></svg>',n.pinned=!0}return"error"===t&&console.error(e),getRef("notification_drawer").push(e,{icon:a,...n})}function createRipple(e,t){const n=document.createElement("span"),a=Math.max(t.clientWidth,t.clientHeight),s=a/2,r=t.getBoundingClientRect();n.style.width=n.style.height=`${a}px`,n.style.left=e.clientX-(r.left+s)+"px",n.style.top=e.clientY-(r.top+s)+"px",n.classList.add("ripple");const o=n.animate([{transform:"scale(4)",opacity:0}],{duration:floGlobals.prefersReducedMotion?0:600,fill:"forwards",easing:"ease-out"});t.append(n),o.onfinish=()=>{n.remove()}}navigator.onLine||notify("There seems to be a problem connecting to the internet, Please check you internet connection.","error","",!0),window.addEventListener("offline",(()=>{notify("There seems to be a problem connecting to the internet, Please check you internet connection.","error",!0,!0)})),window.addEventListener("online",(()=>{getRef("notification_drawer").clearAll(),notify("We are back online.","success")})),window.addEventListener("load",(()=>{document.querySelectorAll("sm-input[data-flo-id]").forEach((e=>e.customValidation=floCrypto.validateAddr)),document.querySelectorAll("sm-input[data-private-key]").forEach((e=>e.customValidation=floCrypto.getPubKeyHex)),document.addEventListener("keyup",(e=>{"Escape"===e.code&&closePopup()})),document.addEventListener("keydown",(e=>{"/"===e.key&&(e.preventDefault(),getRef("search_investor").focusIn())})),document.addEventListener("copy",(()=>{notify("copied","success")})),document.addEventListener("pointerdown",(e=>{e.target.closest("button:not([disabled]), .interact")?createRipple(e,e.target.closest("button, .interact")):isDropdownOpen&&!e.target.closest(".dropdown")&&changeDropdownState("profile_dropdown","hide")})),localStorage.getItem("preferred-currency")?(preferredCurrency=localStorage.getItem("preferred-currency"),setTimeout((()=>{getRef("currency_selector").value=preferredCurrency}),1e3)):(preferredCurrency="inr",localStorage.setItem("preferred-currency","inr"))}));const debounce=(e,t)=>{let n=null;return(...a)=>{window.clearTimeout(n),n=window.setTimeout((()=>{e.apply(null,a)}),t)}};let zIndex=50;function openPopup(e,t){return zIndex++,getRef(e).setAttribute("style",`z-index: ${zIndex}`),getRef(e).show({pinned:t}),getRef(e)}function closePopup(){void 0!==popupStack.peek()&&popupStack.peek().popup.hide()}function buttonLoader(e,t){const n="string"==typeof e?getRef(e):e;n.disabled=t;const a={duration:floGlobals.prefersReducedMotion?0:200,fill:"forwards",easing:"ease"};if(t)n.animate([{clipPath:"circle(100%)"},{clipPath:"circle(0)"}],a),n.parentNode.append(document.createElement("sm-spinner"));else{n.getAnimations().forEach((e=>e.cancel()));const e=n.parentNode.querySelector("sm-spinner");e&&e.remove()}}document.addEventListener("popupopened",(e=>{getRef("home_page").setAttribute("inert","")})),document.addEventListener("popupclosed",(e=>{if("withdraw_popup"===e.detail.popup.id)showChildElement(getRef("withdraw_process"),0),buttonLoader("withdraw_private_key_button",!1),getRef("withdraw_private_key_button").disabled=!0;0===popupStack.items.length&&getRef("home_page").removeAttribute("inert")}));const slideInLeft=[{opacity:0,transform:"translateX(1rem)"},{opacity:1,transform:"translateX(0)"}],slideOutLeft=[{opacity:1,transform:"translateX(0)"},{opacity:0,transform:"translateX(-1rem)"}],slideInRight=[{opacity:0,transform:"translateX(-1rem)"},{opacity:1,transform:"translateX(0)"}],slideOutRight=[{opacity:1,transform:"translateX(0)"},{opacity:0,transform:"translateX(1rem)"}],slideInDown=[{opacity:0,transform:"translateY(-1rem)"},{opacity:1,transform:"translateY(0)"}],slideOutDown=[{opacity:1,transform:"translateY(0)"},{opacity:0,transform:"translateY(1rem)"}],slideInUp=[{opacity:0,transform:"translateY(1rem)"},{opacity:1,transform:"translateY(0)"}],slideOutUp=[{opacity:1,transform:"translateY(0)"},{opacity:0,transform:"translateY(-1rem)"}];function showChildElement(e,t,n={}){return new Promise((a=>{const{mobileView:s=!1,entry:r,exit:o}=n,d={duration:floGlobals.prefersReducedMotion?0:150,easing:"ease",fill:"forwards"},l="string"==typeof e?document.getElementById(e):e,i=[...l.children].find((e=>!e.classList.contains(s?"hide-on-mobile":"hidden")));i!==l.children[t]&&(i.getAnimations().forEach((e=>e.cancel())),l.children[t].getAnimations().forEach((e=>e.cancel())),i?o?(l.style.overflow="hidden",i.animate(o,d).onfinish=()=>{i.classList.add(s?"hide-on-mobile":"hidden"),l.style.overflow=""},l.children[t].classList.remove(s?"hide-on-mobile":"hidden"),r&&(l.children[t].animate(r,d).onfinish=()=>a())):(i.classList.add(s?"hide-on-mobile":"hidden"),l.children[t].classList.remove(s?"hide-on-mobile":"hidden"),a()):(l.children[t].classList.remove(s?"hide-on-mobile":"hidden"),l.children[t].animate(r,d).onfinish=()=>a()))}))}function togglePrivateKeyVisibility(e){const t=e.closest("sm-input");t.type="password"===t.type?"text":"password",t.focusIn()}function formatAmount(e=0,t="inr"){return(e=parseFloat(e))?e.toLocaleString("inr"===t?"en-IN":"en-US",{style:"currency",currency:t}):"₹0"}const render={investorInput(){const e=document.createElement("li");return e.classList.add("investor-input","grid"),e.innerHTML='\n <sm-input placeholder="FLO address" class="outlined" animate></sm-input>\n <sm-input placeholder="Amount(₹)" type="number" min=0 class="outlined" animate></sm-input>\n <button class="remove-investor" title="Remove this investor">\n <svg class="icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24"><path fill="none" d="M0 0h24v24H0z"/><path d="M12 10.586l4.95-4.95 1.414 1.414-4.95 4.95 4.95 4.95-1.414 1.414-4.95-4.95-4.95 4.95-1.414-1.414 4.95-4.95-4.95-4.95L7.05 5.636z"/></svg>\n </button>\n ',e},fundPlaceholder(){const e=document.createElement("li");return e.classList.add("fund-placeholder","grid"),e.innerHTML='\n <div class="flex-grid justify-start">\n <div class="placeholder__block"></div>\n <div class="placeholder__block"></div>\n <div class="placeholder__block"></div>\n <div class="placeholder__block"></div>\n </div>\n <div class="grid flow-column gap-1">\n <div class="placeholder__block"></div>\n <div class="placeholder__block"></div>\n </div>\n <div class="placeholder__block justify-self-end"></div>\n ',e},investmentCard(e){const{floId:t,amountInvested:n,netValue:a,fundId:s,hasMatured:r=!1,allowsEarlyWithdrawal:o=!1}=e,d=r||o,l=btcOperator.convert.legacy2bech(t);return html`
|
|
<li class="fund-investor" id=${`${s}_${t}`} .dataset=${{btcId:l}}>
|
|
<div class="grid gap-1">
|
|
<div class="grid">
|
|
<span class="label">FLO address</span>
|
|
<span class="value flo-id">${t}</span>
|
|
</div>
|
|
<div class="grid">
|
|
<span class="label">BTC address</span>
|
|
<span class="value btc-id">${l}</span>
|
|
</div>
|
|
</div>
|
|
<div class="flex gap-1-5">
|
|
<div class="transaction-column">
|
|
<span class="label">Invested</span>
|
|
<span class="value amount-invested">${formatAmount(n[preferredCurrency],preferredCurrency)}</span>
|
|
</div>
|
|
<div class="transaction-column">
|
|
<span class="label">Present value</span>
|
|
<span class="value net-value" style="color: var(--green)">${formatAmount(a[preferredCurrency],preferredCurrency)}</span>
|
|
</div>
|
|
</div>
|
|
<button class="button fund-investor__withdraw" ?disabled=${!d}>Withdraw</button>
|
|
</li>
|
|
`},closedInvestmentCard(e){const{floId:t,amountInvested:n,fundId:a,BTC_net:s,endDate:r,finalAmount:o,USD_net:d,payment_refRef:l}=e,i=btcOperator.convert.legacy2bech(t);return html`
|
|
<li class="fund-investor" id=${`${a}_${t}`} .dataset=${{btcId:i}}>
|
|
<div class="flex align-items-center space-between w-100">
|
|
<span class="tag">Closed: ${bobsFund.dateFormat(r)}</span>
|
|
</div>
|
|
<div class="grid gap-1">
|
|
<div class="grid">
|
|
<span class="label">FLO address</span>
|
|
<span class="value flo-id">${t}</span>
|
|
</div>
|
|
<div class="grid">
|
|
<span class="label">BTC address</span>
|
|
<span class="value btc-id">${i}</span>
|
|
</div>
|
|
</div>
|
|
<div class="flex gap-1-5">
|
|
<div class="transaction-column">
|
|
<span class="label">Invested</span>
|
|
<span class="value amount-invested">${formatAmount(n[preferredCurrency],preferredCurrency)}</span>
|
|
</div>
|
|
<div class="transaction-column">
|
|
<span class="label">Withdrawn amount</span>
|
|
<span class="value net-value" style="color: var(--green)">${formatAmount(o[preferredCurrency],preferredCurrency)}</span>
|
|
</div>
|
|
</div>
|
|
<div class="flex gap-1-5 align-center space-between w-100">
|
|
<div class="transaction-column">
|
|
<a href=${`${floBlockchainAPI.current_server}tx/${l}`} target="_blank">See withdrawal transaction</a>
|
|
</div>
|
|
</div>
|
|
</li>
|
|
`},fundBlock(e){let{fundTxs:t,startDate:n,endDate:a,baseUsd:s,baseBtc:r,tapouts:o,totalInvestment:d,totalNet:l,investorsFrag:i}=e;const c=o.map(((e,t)=>{const n=`${bobsFund.dateFormat(e.start)} to ${bobsFund.dateFormat(e.end)}`;return html`
|
|
<li class="tapout-point grid">
|
|
<span class="label">Tapout ${t+1}</span>
|
|
<span class="value">${n}</span>
|
|
</li>`})),u=t.map(((e,t)=>html`<a href=${`${floBlockchainAPI.current_server}tx/${e.txid}`} target="_blank">Transaction ${t+1}</a>`));return html.node`
|
|
<li class="fund-block">
|
|
<h4 class="start-date">${n} Fund</h4>
|
|
<div class="fund-block__details margin-bottom-3r">
|
|
<div class="grid">
|
|
<span class="label">End date</span>
|
|
<span class="value end-date">${bobsFund.dateFormat(a)}</span>
|
|
</div>
|
|
<div class="flex flex-wrap gap-1">
|
|
<div class="grid">
|
|
<span class="label">Initial BTC value</span>
|
|
<span class="value base-btc">${formatAmount(r[preferredCurrency],preferredCurrency)}</span>
|
|
</div>
|
|
<div class="grid">
|
|
<span class="label">Base USD rate</span>
|
|
<span class="value base-usd">${s.toLocaleString("en-US",{style:"currency",currency:"INR"})}</span>
|
|
</div>
|
|
</div>
|
|
<div class="flex flex-wrap gap-1">
|
|
<div class="grid">
|
|
<span class="label">Total investment</span>
|
|
<span class="value total-investment">${formatAmount(d[preferredCurrency],preferredCurrency)}</span>
|
|
</div>
|
|
<div class="grid">
|
|
<span class="label">Total present value</span>
|
|
<span class="value net-value" style="color: var(--green)">${formatAmount(l[preferredCurrency],preferredCurrency)}</span>
|
|
</div>
|
|
</div>
|
|
${c.length?html`
|
|
<div class="grid">
|
|
<span class="value margin-bottom-0-5r">Tapouts</span>
|
|
<ul class="tapout-list">${c}</ul>
|
|
</div>`:""}
|
|
<div class="grid">
|
|
<span class="label">Fund transactions</span>
|
|
<div class="flex gap-0-5 flex-wrap">${u}</div>
|
|
</div>
|
|
</div>
|
|
<div class="grid">
|
|
<h4 class="margin-bottom-0-5r">Investors</h4>
|
|
<ul class="investors-list grid">${i}</ul>
|
|
</div>
|
|
</li>
|
|
`}};let preferredCurrency;getRef("currency_selector").addEventListener("change",(e=>{preferredCurrency=e.target.value,localStorage.setItem("preferred-currency",preferredCurrency),document.querySelectorAll(".fund-block").forEach((e=>{const{baseBtc:t,totalInvestment:n,totalNet:a}=floGlobals.investments[e.id];e.querySelector(".base-btc").textContent=formatAmount(t[preferredCurrency],preferredCurrency),e.querySelector(".total-investment").textContent=formatAmount(n[preferredCurrency],preferredCurrency),e.querySelector(".net-value").textContent=formatAmount(a[preferredCurrency],preferredCurrency)})),document.querySelectorAll(".fund-investor").forEach((e=>{const{amountInvested:t,netValue:n}=floGlobals.investments[e.id];e.querySelector(".amount-invested").textContent=formatAmount(t[preferredCurrency],preferredCurrency),e.querySelector(".net-value").textContent=formatAmount(n[preferredCurrency],preferredCurrency)}))}));let isDropdownOpen=!1;function changeDropdownState(e,t,n){const a={duration:300,easing:"ease",fill:"both"};"show"===t?showDropdown(e,a,n):"toggle"===t?isDropdownOpen?hideDropdown(e,a):showDropdown(e,a,n):"hide"===t&&hideDropdown(e,a)}function showDropdown(e,t,n){if(!isDropdownOpen){if(n){const t=n.getBoundingClientRect();getRef(e).setAttribute("style",`top: ${t.top+t.height+document.documentElement.scrollTop}px; right: calc(${window.innerWidth-t.right}px - 1.5rem)`)}getRef(e).classList.remove("hidden"),getRef(e).animate([{transform:"translateY(-1rem)",opacity:0},{transform:"translateY(0)",opacity:1}],t).onfinish=()=>{isDropdownOpen=!0}}}function hideDropdown(e,t){isDropdownOpen&&(getRef(e).animate([{transform:"translateY(0)",opacity:1},{transform:"translateY(-1rem)",opacity:0}],t).onfinish=()=>{isDropdownOpen=!1,getRef(e).classList.add("hidden")})}function showPage(e){document.querySelector(".page:not(.hidden)")?.classList.add("hidden"),getRef(e).classList.remove("hidden"),"home_page"===e&&(clearAddedInvestors(),getRef("create_fund_form").reset(),""!==window.location.hash&&getRef(`${window.location.hash.split("#").pop()}`).scrollIntoView({behavior:"smooth",block:"start"})),"confirm_term_page"!==e&&(getRef("get_term_private_key").value="",getRef("get_fund_private_key").value=""),"loading_page"===e||"error_page"===e?getRef("main_header").classList.add("hidden"):getRef("main_header").classList.remove("hidden")}function renderInvestor(){getRef("investors_input_list").append(render.investorInput()),getRef("investors_input_list").lastElementChild.scrollIntoView(),getRef("investors_input_list").lastElementChild.children[0].focusIn()}function clearAddedInvestors(){getRef("investors_input_list").innerHTML="",getRef("investors_input_list").append(render.investorInput())}function getAddedInvestors(){const e=getRef("investors_input_list").querySelectorAll(".investor-input"),t=[];return e.forEach((e=>{const n=e.children[0].value.trim(),a=e.children[1].value.trim();t.push([n,a])})),t}var USD_current,BTC_current;function refresh(e=!0){e&&showPage("loading_page"),getCurrentRates().then((async e=>{USD_current=e.USD_INR,BTC_current=e.BTC_USD,console.log(`USD rate: ${USD_current} INR\nBTC rate: ${BTC_current} USD`),getRef("usd-rate").textContent=`USD: ₹${e.USD_INR.toFixed(2)}`,getRef("btc-usd-rate").textContent=`BTC: ${parseFloat(e.BTC_USD.toFixed(2)).toLocaleString("en-US",{style:"currency",currency:"USD"})}`,getRef("fund_list").innerHTML="",getRef("fund_selector").innerHTML="",refreshBlockchainData().then((e=>{renderFunds(e),showPage("home_page")})).catch((e=>{console.error(e),showPage("error_page")}))})).catch((e=>console.error(e)))}function renderFunds(e){if(!Object.keys(e).length)return;const t=e=>{let t=document.getElementById(e);t&&t.remove()},n=[];let a=[];for(let s in e){let r=bobsFund.parse(e[s].map((e=>e.data))),o=new Date(r.start_date).getTime(),d=[];r.tapoutInterval&&(d=r.tapoutInterval.map(((e,t)=>{const n=bobsFund.dateAdder(o,e);return{start:n,end:bobsFund.dateAdder(n,r.topoutWindow)}})));const l={fundTxs:e[s],startDate:bobsFund.dateFormat(r.start_date),endDate:bobsFund.dateAdder(o,r.duration),baseUsd:r.USD_base,baseBtc:{usd:r.BTC_base,inr:r.BTC_base*r.USD_base},tapouts:d},i=new Date(l.endDate)<new Date,c=d.some((e=>new Date(e.start)<new Date&&new Date(e.end)>new Date));n.push(html`
|
|
<sm-option value="${e[s][0].txid}">
|
|
<div class="grid gap-0-5">
|
|
<span>Start date: ${l.startDate}</span>
|
|
<span>Base BTC: ${parseFloat(l.baseBtc.usd).toLocaleString("en-US",{style:"currency",currency:"USD"})} | Base USD: ₹${l.baseUsd}</span>
|
|
</div>
|
|
</sm-option>
|
|
`);const u=[];let f=total_net=0;for(let e in r.investments){const{amount:t,closed:n}=r.investments[e];let a=bobsFund.calcNetValue(r.BTC_base,BTC_current,r.USD_base,USD_current,t,r.fee);const o={fundId:s,floId:e,amountInvested:{inr:t.toFixed(2),usd:(t/r.USD_base).toFixed(2)},netValue:{inr:a.toFixed(2),usd:(a/USD_current).toFixed(2)},hasMatured:i,allowsEarlyWithdrawal:c};f+=t,n?(console.log(n),total_net+=n.amountFinal,o.finalAmount={inr:n.amountFinal.toFixed(2),usd:(n.amountFinal/n.USD_net).toFixed(2)},u.push(render.closedInvestmentCard({...o,...n})),floGlobals.investments[`${s}_${e}`]={amountInvested:o.amountInvested,netValue:o.finalAmount}):(total_net+=a,u.push(render.investmentCard(o)),floGlobals.investments[`${s}_${e}`]={amountInvested:o.amountInvested,netValue:o.netValue})}l.totalInvestment={inr:f.toFixed(2),usd:(f/r.USD_base).toFixed(2)},l.totalNet={inr:total_net.toFixed(2),usd:(total_net/USD_current).toFixed(2)},floGlobals.investments[s]={totalInvestment:l.totalInvestment,totalNet:l.totalNet,baseBtc:l.baseBtc},l.investorsFrag=u;const p=render.fundBlock(l);t(s),p.id=s;let m=a.length-1;for(;m>=0&&a[m]<o;)a[m+1]=a[m],m--;a[m+1]=o,getRef("fund_list").insertBefore(p,getRef("fund_list").childNodes[m+1])}renderElem(getRef("fund_selector"),html`${n}`)}getRef("search_investor").addEventListener("input",debounce((e=>{const t=e.target.value.trim().toLowerCase();document.querySelectorAll(".fund-block").forEach((e=>{e.querySelectorAll(".fund-investor").forEach((e=>{e.id.toLowerCase().includes(t)||e.dataset.btcId.toLowerCase().includes(t)?e.classList.remove("hidden"):e.classList.add("hidden")})),Array.from(e.querySelectorAll(".fund-investor")).every((e=>e.classList.contains("hidden")))?e.classList.add("hidden"):e.classList.remove("hidden"),Array.from(getRef("fund_list").children).every((e=>e.classList.contains("hidden")))?document.getElementById("fund_list__empty-state")?.classList.remove("hidden"):document.getElementById("fund_list__empty-state")?.classList.add("hidden")}))}),100)),getRef("investors_input_list").addEventListener("click",(e=>{e.target.closest(".remove-investor")&&e.target.closest(".investor-input").remove()})),getRef("fund_creation_toggle").addEventListener("change",(e=>{e.target.checked?(getRef("fund_details_form").classList.add("hidden"),getRef("fund_details_form").querySelectorAll("input").forEach((e=>e.disabled=!0)),getRef("create_fund_button").classList.add("hidden"),getRef("add_investors_button").classList.remove("hidden"),getRef("fund_selector_container").classList.remove("hidden")):(getRef("fund_details_form").classList.remove("hidden"),getRef("create_fund_button").classList.remove("hidden"),getRef("fund_details_form").querySelectorAll("input").forEach((e=>e.disabled=!1)),getRef("add_investors_button").classList.add("hidden"),getRef("fund_selector_container").classList.add("hidden"))})),getRef("tapout_toggle").addEventListener("change",(e=>{e.target.checked?(getRef("tapout_container").classList.remove("hidden"),getRef("tapout_container").querySelectorAll("input").forEach((e=>e.disabled=!1))):(getRef("tapout_container").classList.add("hidden"),getRef("tapout_container").querySelectorAll("input").forEach((e=>e.disabled=!0)))})),getRef("refresh_button").addEventListener("click",refresh),floGlobals.investments={},getRef("create_fund_form").addEventListener("submit",(e=>{let t,n,a,s,r,o;if(e.preventDefault(),t=e.target,a=t.max_pv.value+" "+getRef("max_pt").value,getRef("tapout_toggle").checked){let e=getRef("tap_it").value;r=t.tap_iv.value.split(",").map((t=>t.trim()+" "+e)),s=t.tap_wv.value+" "+getRef("tap_wt").value}else s=r=null;o=getAddedInvestors();let d=!getRef("fund_creation_toggle").checked;if(console.info(o),n=d?bobsFund.stringify.main(t.btc_base.value,t.usd_rate.value,t.start_date.value,a,o,t.fee.value,s,r):bobsFund.stringify.continue(getRef("fund_selector").value,o),console.log(n),n.length>=1040)return console.error("flo data length is too long, Please reduce it and try again"),void notify("floData is too large! Please reduce it and try again.","error");getRef("fund_details").innerHTML=n.replace(/\|/g,"<br>"),getRef("fund_admin_id").innerHTML=`Enter Private key of admin ID <h5 class="weight-400">${floGlobals.adminID}</h5>`,showPage("confirm_fund_page"),getRef("confirm_fund_button").onclick=()=>{const e=getRef("get_fund_private_key").value;console.log(e),floCrypto.verifyPrivKey(e,floGlobals.adminID)?floBlockchainAPI.writeData(floGlobals.adminID,n,e,floGlobals.adminID).then((e=>{console.log(e),showPage("admin_page"),notify(d?"New Fund created":"Invesments added to fund","success"),getRef("create_fund_form").reset(),clearAddedInvestors(),refresh(!1)})).catch((e=>console.error(e))):notify("Access Denied! incorrect private key","error")}})),getRef("fund_list").addEventListener("click",(e=>{if(e.target.closest(".fund-investor__withdraw")){floGlobals.withdrawId=e.target.closest(".fund-investor").id.split("_");const[t,n]=floGlobals.withdrawId;renderElem(getRef("withdraw__id"),html`<div class='label'>Investor address</div> <strong class="value">${n}</strong>`),openPopup("withdraw_popup")}})),getRef("withdraw_private_key_button").addEventListener("click",(e=>{buttonLoader("withdraw_private_key_button",!0);const t=getRef("withdraw_private_key").value,[n,a]=floGlobals.withdrawId;floExchangeAPI.closeBobsFundInvestment(n,a,t).then((e=>{console.log(e),showChildElement(getRef("withdraw_process"),1,{entry:slideInLeft,exit:slideOutLeft});const t=document.getElementById(floGlobals.withdrawId.join("_"))?.querySelector(".fund-investor__withdraw");t&&(t.textContent="Withdrawn",t.disabled=!0)})).catch((e=>{getRef("withdraw_failed_message").textContent=e.message,showChildElement(getRef("withdraw_process"),2,{entry:slideInLeft,exit:slideOutLeft}),console.error(e)})).finally((()=>{buttonLoader("withdraw_private_key_button",!1)}))}))</script> |