const Wrapper = styled.div` padding-bottom: 48px; `; const Main = styled.div` display: grid; gap: 40px; grid-template-columns: 352px minmax(0, 1fr); align-items: start; @media (max-width: 1200px) { grid-template-columns: minmax(0, 1fr); } `; const BackgroundImage = styled.div` height: 240px; border-radius: 20px 20px 0 0; overflow: hidden; margin: 0 -12px; background: #eceef0; img { object-fit: cover; width: 100%; height: 100%; } @media (max-width: 1200px) { margin: calc(var(--body-top-padding) * -1) -12px 0; border-radius: 0; } @media (max-width: 900px) { height: 100px; } `; const SidebarWrapper = styled.div` position: relative; z-index: 5; margin-top: -55px; @media (max-width: 900px) { margin-top: -40px; } `; const Content = styled.div` .post { padding-left: 0; padding-right: 0; } `; const Title = styled.h1` font-weight: 600; font-size: ${(p) => p.size || "25px"}; line-height: 1.2em; color: #11181c; margin: ${(p) => (p.margin ? "0 0 24px" : "0")}; overflow-wrap: anywhere; `; const Tabs = styled.div` display: flex; height: 48px; border-bottom: 1px solid #eceef0; margin-bottom: 72px; overflow: auto; scroll-behavior: smooth; @media (max-width: 1200px) { background: #f8f9fa; border-top: 1px solid #eceef0; margin: 0 -12px 48px; > * { flex: 1; } } `; const TabsButton = styled.a` display: inline-flex; align-items: center; justify-content: center; height: 100%; font-weight: 600; font-size: 12px; padding: 0 12px; position: relative; color: ${(p) => (p.selected ? "#11181C" : "#687076")}; background: none; border: none; outline: none; text-align: center; text-decoration: none !important; &:hover { color: #11181c; } &::after { content: ""; display: ${(p) => (p.selected ? "block" : "none")}; position: absolute; bottom: 0; left: 0; right: 0; height: 3px; background: #59e692; } `; const Bio = styled.div` color: #11181c; font-size: 14px; line-height: 20px; margin-bottom: 48px; > *:last-child { margin-bottom: 0 !important; } @media (max-width: 900px) { margin-bottom: 48px; } `; if ( state.chainId === undefined && ethers !== undefined && Ethers.send("eth_requestAccounts", [])[0] ) { Ethers.provider() .getNetwork() .then((chainIdData) => { if (chainIdData?.chainId) { State.update({ chainId: chainIdData.chainId }); } }); } if (state.chainId !== undefined && state.chainId !== 1) { return <p>Switch to Ethereum Mainnet</p>; } // FETCH LIDO ABI const lidoContract = "0xae7ab96520de3a18e5e111b5eaab095312d7fe84"; const tokenDecimals = 18; const lidoAbi = fetch( "https://raw.githubusercontent.com/lidofinance/lido-subgraph/master/abis/Lido.json" ); if (!lidoAbi.ok) { return "Loading"; } const iface = new ethers.utils.Interface(lidoAbi.body); // FETCH LIDO STAKING APR if (state.lidoArp === undefined) { const apr = fetch( "https://api.allorigins.win/get?url=https://stake.lido.fi/api/sma-steth-apr" ); if (!apr) return; State.update({ lidoArp: JSON.parse(apr?.body?.contents) ?? "..." }); } // HELPER FUNCTIONS const getStakedBalance = (receiver) => { const encodedData = iface.encodeFunctionData("balanceOf", [receiver]); return Ethers.provider() .call({ to: lidoContract, data: encodedData, }) .then((rawBalance) => { const receiverBalanceHex = iface.decodeFunctionResult( "balanceOf", rawBalance ); return Big(receiverBalanceHex.toString()) .div(Big(10).pow(tokenDecimals)) .toFixed(2) .replace(/\d(?=(\d{3})+\.)/g, "$&,"); }); }; const submitEthers = (strEther, _referral) => { if (!strEther) { return console.log("Amount is missing"); } const erc20 = new ethers.Contract( lidoContract, lidoAbi.body, Ethers.provider().getSigner() ); let amount = ethers.utils.parseUnits(strEther, tokenDecimals).toHexString(); erc20.submit(lidoContract, { value: amount }).then((transactionHash) => { console.log("transactionHash is " + transactionHash); }); }; // DETECT SENDER if (state.sender === undefined) { const accounts = Ethers.send("eth_requestAccounts", []); if (accounts.length) { State.update({ sender: accounts[0] }); console.log("set sender", accounts[0]); } } //if (!state.sender) return "Please login first"; // FETCH SENDER BALANCE if (state.balance === undefined && state.sender) { Ethers.provider() .getBalance(state.sender) .then((balance) => { State.update({ balance: Big(balance).div(Big(10).pow(18)).toFixed(2) }); }); } // FETCH SENDER STETH BALANCE if (state.stakedBalance === undefined && state.sender) { getStakedBalance(state.sender).then((stakedBalance) => { State.update({ stakedBalance }); }); } // FETCH TX COST if (state.txCost === undefined) { const gasEstimate = ethers.BigNumber.from(1875000); const gasPrice = ethers.BigNumber.from(1500000000); const gasCostInWei = gasEstimate.mul(gasPrice); const gasCostInEth = ethers.utils.formatEther(gasCostInWei); let responseGql = fetch( "https://api.thegraph.com/subgraphs/name/uniswap/uniswap-v2", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ query: `{ bundle(id: "1" ) { ethPrice } }`, }), } ); if (!responseGql) return ""; const ethPriceInUsd = responseGql.body.data.bundle.ethPrice; const txCost = Number(gasCostInEth) * Number(ethPriceInUsd); State.update({ txCost: `$${txCost.toFixed(2)}` }); } // FETCH CSS const cssFont = fetch( "https://fonts.googleapis.com/css2?family=Manrope:wght@200;300;400;500;600;700;800" ).body; const css = fetch( "https://pluminite.mypinata.cloud/ipfs/Qmboz8aoSvVXLeP5pZbRtNKtDD3kX5D9DEnfMn2ZGSJWtP" ).body; if (!cssFont || !css) return ""; if (!state.theme) { State.update({ theme: styled.div` font-family: Manrope, -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Oxygen, Ubuntu, Cantarell, Fira Sans, Droid Sans, Helvetica Neue, sans-serif; ${cssFont} ${css} `, }); } const Theme = state.theme; // OUTPUT UI const getSender = () => { return !state.sender ? "" : state.sender.substring(0, 6) + "..." + state.sender.substring(state.sender.length - 4, state.sender.length); }; return ( <Theme> <Content> <Tabs> <TabsButton href={`${accountUrl}&tab=overview`} selected={state.selectedTab === "overview"} > Overview </TabsButton> <TabsButton href={`${accountUrl}&tab=apps`} selected={state.selectedTab === "apps"} > Components </TabsButton> <TabsButton href={`${accountUrl}&tab=nfts`} selected={state.selectedTab === "nfts"} > NFTs </TabsButton> <TabsButton href={`${accountUrl}&tab=following`} selected={state.selectedTab === "following"} > Following </TabsButton> <TabsButton href={`${accountUrl}&tab=followers`} selected={state.selectedTab === "followers"} > Followers </TabsButton> <TabsButton href={`${accountUrl}&tab=explorer`} selected={state.selectedTab === "explorer"} > Explorer </TabsButton> </Tabs> {state.selectedTab === "overview" && ( <> {profile.description && ( <> <Title as="h2" size="19px" margin> About </Title> <Bio> <Widget src="near/widget/SocialMarkdown" props={{ text: profile.description }} /> </Bio> </> )} <Widget src="near/widget/Posts.Feed" props={{ accounts: [accountId] }} /> </> )} {state.selectedTab === "nfts" && ( <Widget src="near/widget/NFTCollection" props={{ accountId }} /> )} {state.selectedTab === "apps" && ( <Widget src="near/widget/ComponentCollection" props={{ accountId }} /> )} {state.selectedTab === "followers" && ( <Widget src="near/widget/FollowersList" props={{ accountId }} /> )} {state.selectedTab === "following" && ( <Widget src="near/widget/FollowingList" props={{ accountId }} /> )} {state.selectedTab === "explorer" && ( <Widget src="ethpraguedemo.near/widget/Progress-Pool-Voters" props={{ accountId, network: context.networkId, language: "en", baseUrl: props.baseUrl, }} /> )} </Content> <div style={{ display: "flex", marginBottom: "50px", marginTop: "20px" }}> <div style={ { /* Add any additional styling for the first LidoContainer */ } } > <Widget src="ethpraguedemo.near/widget/Progress-Pool-Voters" props={{}} /> </div> <div style={{ marginLeft: "10px" /* Add any additional styling for the second LidoContainer */, }} > <Widget src="ethpraguedemo.near/widget/Progress-Pool-Grantees" props={{}} /> </div> </div> <Widget src="ethpraguedemo.near/widget/Progress-Pool-Proposals" props={{}} /> </Theme> );