react-bootstrap#Image JavaScript Examples

The following examples show how to use react-bootstrap#Image. You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: ChartPart.js    From real-time-web-samples with MIT License 7 votes vote down vote up
render() {
        const options = {
            legend: {
                position: "bottom"
            },
            scales: {
                yAxes: [{
                    ticks: {
                        beginAtZero: true
                    }}]
            },
            plugins: {
                datalabels: {
                    display: function(context) {
                        return context
                    },
                    font: {
                        weight: 'bold'
                    }
                }
            },
            tooltips: {
                enabled: false
            }
        };

        return (
            <div>
                <Image src={azureImage} style={{width: "98%"}} />
                <h3 className="text-left my-3">实时统计</h3>
                <Bar data={this.state.chartData} options={options} plugins={DataLabels}/>
                <NoticeAlert />
            </div>
        )
    }
Example #2
Source File: NoticeForm.js    From real-time-web-samples with MIT License 6 votes vote down vote up
render() {
        return (
            <Container fluid>
                <Row>
                    <Col xs={{ span: 2, offset: 10 }}  md={{ span: 1, offset: 11 }}>
                        <Image src={staffImage} roundedCircle fluid className="border border-primary my-3" />
                    </Col>
                </Row>
                <Row>
                    <Col md="6" className="mb-3">
                        <Form onSubmit={this.submitNotice}>
                            <Form.Group controlId="ControlTextarea">
                                <Form.Control className="" style={{backgroundColor: 'rgba(255, 255, 255, 6%)'}} value={this.state.formText} onChange={this.changeNotice} name="formText" as="textarea" rows="10" placeholder="输入通知消息..."/>
                            </Form.Group>
                            <Button variant="primary" type="submit" className="float-right">通知</Button>
                        </Form>
                    </Col>
                    <Col md="6">
                        <Image src={azureImage} fluid />
                    </Col>
                </Row>
            </Container>
        );
    }
Example #3
Source File: index.js    From wedding-planner with MIT License 6 votes vote down vote up
/**
 *  Navbar Component using {Link}
 */
function NavigationBar() {
  const { isAuthenticated } = useAuth0();

  return (
    <Navbar bg="light" shadow="lg" expand="lg">
      <Navbar.Brand href="/">
        <Image src={logo} className="custom-img" />
      </Navbar.Brand>
      <Navbar.Toggle aria-controls="navbar-nav" />
      <Navbar.Collapse>
        {isAuthenticated ? (
          <Nav className="ml-auto color-link">
            <NavDropdown title="Events" id="basic-nav-dropdown">
              <NavDropdown.Item href="/events">
                Your Events
              </NavDropdown.Item>
              <NavDropdown.Divider />
              <NavDropdown.Item href="/events/new">
                Create New
              </NavDropdown.Item>
            </NavDropdown>
            <ProfileLink />
            <LogoutLink />
          </Nav>
        ) : (
          <Nav className="ml-auto color-link">
            <LoginLink />
            <SignupLink />
          </Nav>
        )}
      </Navbar.Collapse>
    </Navbar>
  );
}
Example #4
Source File: ErrorPage.js    From CS-Hut with MIT License 6 votes vote down vote up
export default function ErrorPage() {
  return (
    <div>
      <div className="Container">
        <p className="NotFoundMessage">
          The page you are looking for doesn’ t exist!
        </p>
        <Col className="ImgColumn">
          <Image
            className="NotFoundImage"
            src={NotFound}
            alt="Page Not Found"
          />
        </Col>
      </div>
    </div>
  );
}
Example #5
Source File: intro_screen.js    From twmwallet with MIT License 6 votes vote down vote up
render() {
        return (
            <div className="width100 height100 d-flex flex-column text-center intro-background-image">
                <Container fluid className="height100 flex-column d-flex justify-content-center">
                    <Image onClick={() => app.quit()} className="entry-off-button pointer" src={require("./../../img/off_black.svg")}/>

                    <Row className="row justify-content-md justify-content-center p-3 intro-safex-logo">
                        <Image className="w-50 intro-safex-logo " src={require("./../../img/safex-home-multi.png")}/>
                    </Row>

                    <button onClick={this.open_select} className="w-50 custom-button-entry my-5 intro-safex-logo">
                        Get Started
                    </button>
                </Container>  
            </div>
        );
    }
Example #6
Source File: MainHeader.js    From twmwallet with MIT License 6 votes vote down vote up
export default function MainHeader(props) {
    const renderMenuItem = (activeOnView, label, onClick) => {
        const isActive = props.view === activeOnView;
        return (<Col className={isActive ? "menu-link-active" : ""}>
        <p className="pointer" onClick={() => onClick()}>
            {label}
        </p>
    </Col>)
    }

    return (
        <Row id="header" className="main-header">
                <Col sm={2} className="main-header-logo">
                    <Image src={require("./../../img/white-logo.svg")}/>
                </Col>
            

                <Col sm={6} className="d-flex">
                    {renderMenuItem('home', 'Home', props.goHome)}
                    {renderMenuItem('market', 'Market', props.goToMarket)}
                    {renderMenuItem('merchant', 'Merchant', props.goToMerchant)}
                    {renderMenuItem('tokens', 'Tokens', props.goToTokens)}                
                </Col>

                <Col sm={2} className="">
                    <BiCog tabIndex={4} size={40} className="m-3 pointer" onClick={props.goToSettings}/>

                    <BiPowerOff tabIndex={5} size={40} className="m-3 pointer" onClick={props.logout}/>
                </Col>
        </Row>
    )
}
Example #7
Source File: index.js    From Devhipster with MIT License 6 votes vote down vote up
function CardCourse({ title, description, icon, url, color }) {

  const history = useHistory();

  function handleClick() {
    history.push(url);
  }

  return (
    <Col md='4' style={{ padding: '15px' }} >
      <Card className={['dark', color, 'shadow'].join(' ')} bg="dark" text="white">
        <Card.Body className="text-white">
          <Card.Title className={color}>
            <h3>{title}</h3>
          </Card.Title>
          <Image fluid={true} src={icon} />
          <h5>{description}</h5>
          <Button
            onClick={handleClick}
            variant='dark'
          >
            <h5 style={{ margin: 0 }} >EM BREVE</h5>
          </Button>
        </Card.Body>
      </Card>
    </Col>
  );
}
Example #8
Source File: Member.js    From dscmec-website with MIT License 6 votes vote down vote up
MemberResponsive = (props) => {
    return (
        <>
            <div className="member-responsive">
                <Image className="rect-icon" src={props.img} alt="member" />
            </div>

            <div className="details-responsive">
                <h4><strong>{props.name}</strong></h4>
                <h5>{props.designation}</h5>
                <a href={props.link} target="_blank" rel="noreferrer">
                    <Image className="ln-icon-resp" src={linkedinIcon} alt="member" />
                </a>
            </div>
        </>
    )
}
Example #9
Source File: Member.js    From dscmec-website with MIT License 6 votes vote down vote up
Member = (props) => {
    return (
        <>
            <div className="member">
                <Image className="circle-icon" src={props.img} alt="member" />

                <a href={props.link} target="_blank" rel="noreferrer">
                    <Image className="ln-icon" src={linkedinIcon} alt="member" />
                </a>
            </div>
            <div className="details">
                <h4><strong>{props.name}</strong></h4>
                <h5>{props.designation}</h5>
            </div>
        </>
    )
}
Example #10
Source File: maintenancePage.js    From community-forum-frontend with GNU General Public License v3.0 6 votes vote down vote up
function MaintenancePage() {
  return (
    <Container className="common-page-maintenance-container">
      <Row className="center-row">
        <Col>
          <h2 className="main-heading">
            <PowerIcon />
            Under Maintenance
          </h2>
          <Image
            src={maintenanceImage}
            className="common-page-maintenance-image"
          />
          <h6 className="common-page-maintenance-message">
            We are currently under maintenance. Apologies for the
            inconvenience caused. Please check back sometime later.
          </h6>
        </Col>
      </Row>
    </Container>
  );
}
Example #11
Source File: TokenAvatar.js    From plenty-interface with GNU General Public License v3.0 6 votes vote down vote up
TokenAvatar = (props) => {
  if (!props.imgPath1) {
    return <Image src={null} height={32} width={32} alt={''} />;
  }

  if (props.imgPath2) {
    return (
      <div className={styles.root}>
        <Image src={props.imgPath1.url} height={32} width={32} alt={''} className={styles.token1} />
        <Image src={props.imgPath2.url} height={32} width={32} alt={''} className={styles.token2} />
      </div>
    );
  }

  return <Image src={props.imgPath1.url} height={32} width={32} alt={''} />;
}
Example #12
Source File: VideoPart.js    From real-time-web-samples with MIT License 6 votes vote down vote up
render() {
        return (
            <div>
                <div className="position-relative overflow-hidden">
                    <video controls className="w-100" src={this.state.videoSource}></video>
                    {this.state.comments.map((comment, index) =>
                        <p key={index} className="h4 comment text-dark" style={{top: comment.position + "px"}}>{comment.text}</p>
                    )}
                </div>
                <form style={{backgroundColor: '#262930'}} className="form-inline py-1 px-3" onSubmit={this.submitComment}>
                    <div className="form-group m-0">
                        <input name="commentText" value={this.state.commentText} onChange={this.changeComment} type="text" className="form-control" placeholder="聊天..." id="comment" />
                    </div>
                    <Button variant="primary" type="submit" className="mx-2">发送</Button>
                    <Image src={staffImage} roundedCircle fluid className="border border-primary position-absolute" style={{ width: "5%", right: "40px" }} />
                </form>
            </div>
        )
    }
Example #13
Source File: FirstTimeDisclaimer.js    From plenty-interface with GNU General Public License v3.0 5 votes vote down vote up
FirstTimeDisclaimer = () => {
  const [checked, setChecked] = useState([false, false]);

  const onAccept = () => {
    localStorage.setItem(FIRST_TIME_DISCLAIMER, 'true');
    window.location.reload(); // ? Try moving this to redux later
  };

  return (
    <div className="d-flex justify-content-center align-center vh-100 vw-100">
      <div className={clsx(styles.card, 'p-4')}>
        <div className="d-flex justify-content-center p-2">
          <Image src={PlentyLogo} alt={'Plenty'} className={styles.logo} />
        </div>

        <hr />

        <div>
          <div className={clsx('d-flex', styles.checkbox)}>
            <input
              value={checked[0]}
              type="checkbox"
              onChange={(ev) => setChecked([ev.target.checked, checked[1]])}
              id="d-01"
            />

            <label className={clsx(styles.disclaimerItem, 'ml-3 mb-2 p-3')} htmlFor="d-01">
              I understand that I am using this product in beta at my own risk. Any losses incurred
              due to my actions are my own responsibility.
            </label>
          </div>

          <div className={clsx('d-flex', styles.checkbox)}>
            <input
              value={checked[1]}
              type="checkbox"
              onChange={(ev) => setChecked([checked[0], ev.target.checked])}
              id="d-02"
            />

            <label className={clsx(styles.disclaimerItem, 'ml-3 mb-2 p-3')} htmlFor="d-02">
              I understand that this product is still in beta. I am participating at my own risk.
            </label>
          </div>
        </div>

        <Button
          onClick={onAccept}
          color={'primary'}
          disabled={!checked.every((x) => x)}
          className="w-100"
        >
          Confirm
        </Button>
      </div>
    </div>
  );
}
Example #14
Source File: 500.js    From stacker.news with MIT License 5 votes vote down vote up
export default function fourZeroFour () {
  return (
    <LayoutError>
      <Image width='500' height='375' src='/falling.gif' fluid />
      <h1 className={styles.fourZeroFour}><span>500</span><span className={styles.notFound}>server error</span></h1>
    </LayoutError>
  )
}
Example #15
Source File: 404.js    From stacker.news with MIT License 5 votes vote down vote up
export default function fourZeroFour () {
  return (
    <LayoutError>
      <Image width='500' height='376' src='/maze.gif' fluid />
      <h1 className={styles.fourZeroFour}><span>404</span><span className={styles.notFound}>page not found</span></h1>
    </LayoutError>
  )
}
Example #16
Source File: select_entry.js    From twmwallet with MIT License 5 votes vote down vote up
render() {
        return (
            <div className="width100 height100 d-flex flex-column text-center">
                
                <Container fluid className="height100 flex-column d-flex justify-content-center start-background-image">

                    
                    <Image onClick={this.back} className="entry-off-button pointer" src={require("./../../img/off_black.svg")}/>
                    

                    <Row className="rowjustify-content-md-center justify-content-center p-3">
                        <Image className="w-25" src={require("./../../img/safex-home-multi.png")}/>
                    </Row>

                    <Col className="my-5">
                        <Col className="my-2 p-3">
                            <button onClick={this.open_existing} className="custom-button-entry">Open Existing Wallet</button>
                        </Col>

                        <Col className="my-2 p-3">
                            <button onClick={this.create_new} className="custom-button-entry">Create New Wallet</button>
                        </Col>

                        <Col className="my-2 p-3">
                            <button onClick={this.restore_keys} className="custom-button-entry">Recover Wallet From Keys</button>
                        </Col>

                        <Col className="my-2 p-3">
                            <button onClick={this.seed_phrase} className="custom-button-entry">Recover Wallet From Seed Phrase</button>
                        </Col>

                        {this.state.legacy_detected ? 
                        (
                            <Col className="my-5 p-3">
                                <button className="custom-button-entry orange-border" onClick={() => this.setState({showLegacyAlert: !this.state.showLegacyAlert})}>Open Legacy Wallet</button>
                                <Collapse in={this.state.showLegacyAlert}>
                                <Alert 
                                    variant="info" 
                                    transition={false}
                                    className="mt-3 w-50 mx-auto entry-back-text"    
                                >
                                    <Alert.Heading>We are working on this feature. Thank you for your patience!</Alert.Heading>
                                   
                                </Alert>
                                </Collapse>
                            </Col>
                        ) 
                        : 
                            (<div></div>)
                        }
                        
                    </Col>
                </Container>  
            </div>);
    }
Example #17
Source File: MerchantTabs.js    From twmwallet with MIT License 5 votes vote down vote up
export default function MerchantTabs(props) {

    return (
            <div className="merchant-tabs-box">
                <div onClick={props.handleNewAccountForm} className="merchant-tab pointer">
                    <Image
                    onClick={props.handleNewAccountForm} 
                        width={75}
                        height={75}
                        src={props.newAccountImage}
                        roundedCircle
                    />

                    <h1 onClick={props.handleNewAccountForm} >Make a New Account</h1>
                    
                </div>
                
                <div onClick={props.showAccounts} className="merchant-tab pointer">
                    <Image
                        width={75}
                        height={75}
                        src={props.accountsImage}
                        roundedCircle
                    />

                    <h1>See Your Accounts</h1>
                    
                </div>
                
                <div onClick={props.handleNewOfferForm} className="merchant-tab pointer">
                    <Image
                        width={75}
                        height={75}
                        src={props.newOfferImage}
                        roundedCircle
                    />

                    <h1>Make a New Offer</h1>
                    
                </div>
                
                <div onClick={props.showOffers} className="merchant-tab pointer">
                    <Image
                        width={75}
                        height={75}
                        src={props.offersImage}
                        roundedCircle
                    />

                    <h1>See Your Offers</h1>
                    
                </div>
                
            </div>

    )
}
Example #18
Source File: index.js    From pooled-loan with MIT License 5 votes vote down vote up
export default function SwapTokens() {
    const [showMetamaskError, setShowMetamaskError] =
        useState(false);

    useEffect(() => {
        if (typeof window.ethereum === 'undefined' ||
            !window.ethereum.selectedAddress
        ) {
            setShowMetamaskError(true);
        }
    }, []);

    return (
        <div>
            {showMetamaskError ?
                <AlertModal
                    open={showMetamaskError}
                    toggle={() => {
                        setShowMetamaskError(false);
                        history.push('/');
                    }}
                >
                    <div>
                        {typeof window.ethereum === 'undefined' ?
                            <div>
                                You can't use these features without Metamask.
                                <br />
                                Please install
                                <Image width="50px" src={metamask}></Image>
                                first !!
                            </div>
                            :
                            <div>
                                Please connect to
                                <Image width="50px" src={metamask}></Image>
                                to use this feature !!
                            </div>
                        }
                    </div>
                </AlertModal>
                :
                <CardDeck style={{ marginTop: "12%" }}>
                    <Card className="hidden-card"></Card>
                    <SwapToken fixedBuyToken={false} buyToken="DAI" />
                    <Card className="hidden-card"></Card>
                </CardDeck>
            }
        </div>
    );
}
Example #19
Source File: index.js    From pooled-loan with MIT License 5 votes vote down vote up
export default function Header() {
    const [errorModal, setErrorModal] = useState(false);

    const handleConnectMetamask = () => {
        if (isMetamaskInstalled()) {
            initContract();
        } else {
            setErrorModal(true);
        }
    };

    const isMetamaskInstalled = () => {
        return (typeof window.ethereum !== 'undefined');
    }

    return (
        <div>
            <Navbar collapseOnSelect bg="light" variant="light">
                <Navbar.Brand href="#">
                    <Image width="120px" src={logo} />
                </Navbar.Brand>
                <Navbar.Toggle aria-controls="responsive-navbar-nav" />
                <Nav className="mr-auto">
                    <Nav.Link href="#create-pool">Create Pool</Nav.Link>
                    <Nav.Link href="#swap-token">Swap Token</Nav.Link>
                </Nav>
                <Nav>
                    <Image
                        style={{ cursor: "pointer" }}
                        width="60px"
                        src={metamask}
                        onClick={handleConnectMetamask}
                    />
                </Nav>
            </Navbar>

            <AlertModal
                open={errorModal}
                toggle={() => setErrorModal(false)}
            >
                You can't use these features without Metamask.
                <br />
                Please install
                <Image width="50px" src={metamask}></Image>
                first !!
            </AlertModal>
        </div>
    )
}
Example #20
Source File: MultiMedia.js    From tclone with MIT License 5 votes vote down vote up
function MM(props) {
    let { post, expanded = false, className } = props
    let style = {
        card: {
            maxHeight: !expanded ? '350' : 'fit-content',
            overflow: 'hidden',
        },
    }
    let { entities = {}, text } = post
    let {
        media: [photo] = [],
        urls: [url],
    } = entities
    if (photo) {
        photo = <Image fluid rounded={true} src={photo.media_url_https} alt="media preview" />
    }
    if (!url) {
        // TODO see if this even necessary
        let unparsed_urls = Array.from(getUrls(text))
        if (unparsed_urls.length) {
            url = {
                expanded_url: unparsed_urls[0], // just the first one
            }
        }
    }
    if (url) {
        url = (
            <ReactTinyLink
                width="100%"
                cardSize={expanded ? 'large' : 'small'}
                autoPlay={expanded}
                showGraphic={true}
                maxLine={2}
                minLine={1}
                url={url.expanded_url}
            />
        )
    }
    if (photo || url)
        return (
            <Card className={`${className} w-100 bg-transparent`} style={style.card}>
                {photo}
                <div className="mt-1">{url}</div>
            </Card>
        )
    else return <></>
}
Example #21
Source File: Jumbotron.js    From talk4free with MIT License 5 votes vote down vote up
Jumbotron = props => {
  const signInHandler = () => {
    document.getElementById("signInBtn").click();
  };
  return (
    <section className="jumbotron">
      <Container>
        <Row className="mt-5">
          <Col md="6">
            <h1>Practice lenguages at anytime.</h1>
            <p className="lead mt-5 mb-5">
              Talk4Free is created to talk to people around the world in many
              languages such as English, Mandarin, Spanish, French, German,
              Italian, Portuguese, Arabic, Russian, Japanese among others.
              <br />
              <br />
              People can exchange languages and culture, make friends and meet
              up people around the world.
            </p>
            <div className="callToActions">
              <a
                href="#test"
                className="btn btn-primary my-2"
                onClick={props.isLoggedIn ? console.log("") : signInHandler}
              >
                Join & Talk Now! <FaSignInAlt />
              </a>
              <a
                type="btn"
                href="#test"
                className="btn btn-secondary my-2 ml-4"
              >
                Rules & Penalies <FaSkull />
              </a>
            </div>
          </Col>
          <Col md="6" className="introImage">
            <Image src={require("./logo10x10.png")} />
          </Col>
        </Row>
      </Container>
    </section>
  );
}
Example #22
Source File: App.js    From masakhane-web with MIT License 5 votes vote down vote up
function App() {
  return (
    <Router>
      <div>
        <Navbar style={{ backgroundColor: '#F2F0E9', width: '100%' }} >
          <Navbar.Brand href="#home" variant="dark" style={{ fontFamily: 'lato', color: 'grey'}}>Masakhane</Navbar.Brand>
          <Navbar.Toggle aria-controls="basic-navbar-nav" />
          <Navbar.Collapse id="basic-navbar-nav" className="justify-content-start">
            <Nav className="ml-auto">
            <Nav.Link href="/">Home</Nav.Link>
                <Nav.Link href="/about">About</Nav.Link>
                <Nav.Link href="/faq">FAQ</Nav.Link>
            </Nav>
          </Navbar.Collapse>
        </Navbar>
        <Jumbotron xs={12} style={{ backgroundColor: '#F2F0E9', paddingTop: '50px', paddingBottom: '50px',backgroundSize: 'cover', backgroundSize: 'cover'}} fluid>
          <Container style={{display:'flex', flexDirection:'row', alignItems:'center', justifyContent:'center'}}>
            <Image src={image}  className="d-none d-sm-block" width='240' height='250' roundedCircle style={{position:"absolute", left:0, right:0}}/>
            <Row xs={12} md={8} style={{display:'flex', flexDirection:'column' ,justifyContent:'center', alignItems:'center'}}>
              <h1 style={{ fontFamily: 'lato, sans-serif', fontWeight: 'lighter', fontSize: 80 }}>Masakhane</h1>
              <p>Machine translation service for African languages</p>
            </Row>
          </Container>
        </Jumbotron>

        <Switch>
            <Route exact path="/">
              <Home />
            </Route>
            <Route path="/about">
              <About />
            </Route>
            <Route path="/faq">
              <FAQPage />
            </Route>
          </Switch>
        {/* <Container className="my-4">
          <br />
          <br />
          <TranslateCard />
          <br />
          <p style={{fontSize: 12, color: 'gray'}}>This is a community research project. Read more about it <span style={{color: 'blue'}}>here</span></p>
        </Container> */}
      </div>
    </Router>
  );
}
Example #23
Source File: Stats.js    From plenty-interface with GNU General Public License v3.0 5 votes vote down vote up
Stats = (props) => {
  const loading = useMemo(() => {
    return (
      props.valueLocked == null || props.plentyInWallet == null || props.plentyToHarvest == null
    );
  }, [props.plentyInWallet, props.plentyToHarvest, props.valueLocked]);

  return (
    <div className={clsx('p-3', 'bg-themed', styles.container)}>
      <Row className="p-1">
        <Col xs={12}>
          <span className="d-flex font-weight-bold m-0 py-3">
            Your Stats
            <Image className="ml-2" src={greenBullet} />
          </span>
          <hr />
        </Col>
      </Row>

      <Row className="p-1">
        <Col xs={6}>
          <Label
            text={
              loading ? null : (
                <NumericLabel params={currencyOptionsWithSymbol}>
                  {props.valueLocked.toFixed(0)}
                </NumericLabel>
              )
            }
            subText={'Total value locked'}
            icon={dollar}
            iconClass={'mt-1'}
            className={'pt-1'}
          />
        </Col>
        <Col xs={6}>
          <Label
            text={loading ? null : `${props.plentyToHarvest?.toFixed(5)}`}
            subText={'PLENTY to harvest'}
            icon={plentyToHarvest}
            iconClass={'mt-1'}
          />
        </Col>
      </Row>

      <hr className="mt-0" />
      <Row className="p-1">
        <Col xs={6}>
          <Label
            text={loading ? null : `${props.plentyInWallet?.toFixed(5)}`}
            subText={'PLENTY in wallet'}
            icon={plentyInWallet}
            iconClass={'mt-1'}
          />
        </Col>
        <Col xs={6}>
          <Label
            text={loading ? null : `${props.xplentyBalance?.toFixed(5)}`}
            subText={'xPLENTY in wallet'}
            icon={xplentyIcon}
            iconClass={'mt-1'}
          />
        </Col>
      </Row>
      <Row className="p-1 mt-1">
        <Col>
          <Button
            onClick={props.harvestAll}
            color={'primary'}
            className={'w-100'}
            disabled={false}
            loading={props.harvestAllOperations.loading}
          >
            Harvest all
          </Button>
        </Col>
      </Row>
    </div>
  );
}
Example #24
Source File: SwapDetailsConfirmSwap.js    From plenty-interface with GNU General Public License v3.0 4 votes vote down vote up
SwapDetailsConfirmSwap = (props) => {
  const [isOpen, setOpen] = useState(false);

  const swapRoute = useMemo(() => {
    if (props.routePath?.length > 2) {
      return props.routePath.map((tokenName) => tokens.find((token) => token.name === tokenName));
    }

    return null;
  }, [props.routePath]);

  if (!props.firstTokenAmount && !swapRoute) {
    return null;
  }

  return (
    <div className={clsx('swap-detail-wrapper-cs', isOpen ? 'bg-themed-light' : 'closedbg')}>
      <div
        className="space-between-confirmswap"
        onClick={() => setOpen(!isOpen)}
        style={{ cursor: 'pointer' }}
      >
        <div className="flex">
          <p className="price-formula-cs whitespace-prewrap  flex flex-row">
            1 {props.tokenIn.name} ={' '}
            <OverlayTrigger
              placement="auto"
              overlay={
                <Tooltip id="swap-token-out-tooltip" {...props}>
                  {props.isStableSwap
                    ? Number(props.computedOutDetails.data.exchangeRate).toFixed(6)
                    : fromExponential(props.routeData.bestRouteUntilNoInput.tokenOutPerTokenIn)}
                </Tooltip>
              }
            >
              <div>
                {props.isStableSwap
                  ? Number(props.computedOutDetails.data.exchangeRate).toFixed(3)
                  : props.routeData.bestRouteUntilNoInput.tokenOutPerTokenIn
                  ? Number(props.routeData.bestRouteUntilNoInput.tokenOutPerTokenIn).toFixed(3)
                  : 0}{' '}
                {props.tokenOut.name === 'tez'
                  ? 'TEZ'
                  : props.tokenOut.name === 'ctez'
                  ? 'CTEZ'
                  : props.tokenOut.name}
              </div>
            </OverlayTrigger>
          </p>
        </div>
        <span
          className={`material-icons-round buttonanim button--trigger open-confirmswap-details ${
            isOpen ? 'dropdown-open' : 'dropdown-close'
          }`}
        >
          expand_more
        </span>
        {/* {isOpen ? (
          <span className="material-icons-round flex buttonanim button--trigger-todisappear  open-confirmswap-details">
            keyboard_arrow_up
          </span>
        ) : (
          <span className="material-icons-round buttonanim button--trigger flex open-confirmswap-details">
            keyboard_arrow_down
          </span>
        )} */}
      </div>
      <div className="buttonanim button--disapear-cs">
        {props.firstTokenAmount &&
          (isOpen ? (
            <div className="scale-in-animation-confirm-swap">
              <div className="flex flex-row mt-3 align-items-center">
                <p className="swap-detail-amt-details-cs">Minimum received </p>
                <OverlayTrigger
                  key="top"
                  placement="top"
                  overlay={
                    <Tooltip
                      id="button-tooltip-swap-details-minimum-received"
                      arrowProps={{ styles: { display: 'none' } }}
                    >
                      Your transaction will revert if there is a large, unfavorable price movement
                      before it is confirmed.
                    </Tooltip>
                  }
                >
                  <span
                    style={{ cursor: 'pointer' }}
                    className="material-icons-round ml-1 swap-detail-amt-details-cs"
                  >
                    help_outline
                  </span>
                </OverlayTrigger>
                <p className="swap-detail-amt-details-cs ml-auto">
                  {props.computedOutDetails.data.finalMinimumOut
                    ? props.computedOutDetails.data.finalMinimumOut
                    : '0.00'}{' '}
                  {props.tokenOut.name === 'tez'
                    ? 'TEZ'
                    : props.tokenOut.name === 'ctez'
                    ? 'CTEZ'
                    : props.tokenOut.name}
                </p>
              </div>
              <div className="flex flex-row align-items-center">
                <p className="swap-detail-amt-details-cs">Price Impact </p>
                <OverlayTrigger
                  key="top"
                  placement="top"
                  overlay={
                    <Tooltip
                      id="button-tooltip-swap-details"
                      arrowProps={{ styles: { display: 'none' } }}
                    >
                      The difference between the market price and estimated price due to trade size.
                    </Tooltip>
                  }
                >
                  <span
                    style={{ cursor: 'pointer' }}
                    className="material-icons-round ml-1 swap-detail-amt-details-cs"
                  >
                    help_outline
                  </span>
                </OverlayTrigger>
                <p className="swap-detail-amt-details-cs ml-auto">
                  {props.computedOutDetails.data.priceImpact
                    ? props.computedOutDetails.data.priceImpact
                    : '0.00'}{' '}
                  %
                </p>
              </div>
              <div className="flex flex-row align-items-center">
                <p className="swap-detail-amt-details-cs">Fee </p>
                <OverlayTrigger
                  key="top"
                  placement="top"
                  overlay={
                    <Tooltip
                      id="button-tooltip-swap-details"
                      arrowProps={{ styles: { display: 'none' } }}
                    >
                      Fees are 0.35% for each volatile swap and 0.10% for each stable swap.
                    </Tooltip>
                  }
                >
                  <span
                    style={{ cursor: 'pointer' }}
                    className="material-icons-round ml-1 swap-detail-amt-details-cs"
                  >
                    help_outline
                  </span>
                </OverlayTrigger>
                <p className="swap-detail-amt-details-cs ml-auto">
                  {props.isStableSwap ? '0.10' : props.computedOutDetails.data.maxfee} %
                </p>
              </div>
              {/* {props.isConfirmSwap && !props.isStableSwap && (
                <div className="flex flex-row align-items-center">
                  <p className="swap-detail-amt-details-cs">xPlenty Fee </p>
                  <OverlayTrigger
                    key="top"
                    placement="top"
                    overlay={
                      <Tooltip
                        id="button-tooltip-swap-details"
                        arrowProps={{ styles: { display: 'none' } }}
                      >
                        A portion of each trade (0.09%) goes to xPLENTY holders as a protocol
                        incentive.
                      </Tooltip>
                    }
                  >
                    <span
                      style={{ cursor: 'pointer' }}
                      className="material-icons-round ml-1 swap-detail-amt-details-cs"
                    >
                      help_outline
                    </span>
                  </OverlayTrigger>
                  <p className="swap-detail-amt-details-cs ml-auto">
                    {props.firstTokenAmount / 1000} {props.tokenIn.name}
                  </p>
                </div>
              )} */}
              {props.isConfirmSwap ? (
                <div className="flex flex-row align-items-center">
                  <p className="swap-detail-amt-details-cs">Slippage tolerance </p>
                  <OverlayTrigger
                    key="top"
                    placement="top"
                    overlay={
                      <Tooltip
                        id="button-tooltip-swap-details"
                        arrowProps={{ styles: { display: 'none' } }}
                      >
                        Change the slippage tolerance in the transaction settings.
                      </Tooltip>
                    }
                  >
                    <span
                      style={{ cursor: 'pointer' }}
                      className="material-icons-round ml-1 swap-detail-amt-details-cs"
                    >
                      help_outline
                    </span>
                  </OverlayTrigger>
                  <p className="swap-detail-amt-details-cs ml-auto">{props.slippage} %</p>
                </div>
              ) : null}
            </div>
          ) : null)}
        {props.firstTokenAmount && swapRoute && <hr />}
        {swapRoute && (
          <>
            <div className="flex flex-row">
              <p className="swap-detail-amt-details-cs">Route </p>
              <OverlayTrigger
                key="top"
                placement="top"
                overlay={
                  <Tooltip
                    id="button-tooltip-swap-details"
                    arrowProps={{ styles: { display: 'none' } }}
                  >
                    Routing through these tokens results in the best price for your trade
                  </Tooltip>
                }
              >
                <span
                  style={{ cursor: 'pointer' }}
                  className="material-icons-round ml-1 swap-detail-amt-details-cs"
                >
                  help_outline
                </span>
              </OverlayTrigger>
            </div>

            <div className="swap-detail-route-container mt-3">
              {swapRoute.map((token, idx) => (
                <div key={token.name} className="d-flex my-2">
                  <Image src={token.image} height={20} width={20} alt={''} />
                  <span className="ml-1 my-auto">{token.name}</span>
                  {swapRoute[idx + 1] && <MdChevronRight className="" fontSize={20} />}
                </div>
              ))}
            </div>
          </>
        )}
      </div>
    </div>
  );
}
Example #25
Source File: Frontpage.js    From plenty-interface with GNU General Public License v3.0 4 votes vote down vote up
Frontpage = ({
  homeStats,
  tvl,
  getTVL,
  getHomeStats,
  wallet,
  plentyToHarvest,
  plentyBalance,
  getPlentyToHarvest,
  getPlentyBalanceOfUser,
  getTVLOfUser,
  userTVL,
  harvestAll,
  openCloseModal,
  modalData,
  harvestAllOperations,
  rpcNode,
  xplentyBalance,
  theme,
  setLoader,
}) => {
  const [showConfirmTransaction, setShowConfirmTransaction] = useState(false);
  const [loaderMessage, setLoaderMessage] = useState({});
  useEffect(() => {
    const getAllData = () => {
      getHomeStats();
      getTVL();
      if (wallet) {
        getPlentyToHarvest(wallet);
        getPlentyBalanceOfUser(wallet);
        getTVLOfUser(wallet);
      }
    };
    getAllData();
    const intervalId = setInterval(getAllData(), 60 * 1000);
    return () => clearInterval(intervalId);
  }, [wallet, rpcNode]);
  const handleClose = () => {
    setShowConfirmTransaction(false);
  };

  const walletConnected = !!wallet;

  const onHarvestAll = () => {
    setShowConfirmTransaction(true);
    setLoader(true);
    !!wallet && harvestAll(wallet, setShowConfirmTransaction, setLoader);
  };
  useEffect(() => {
    if (harvestAllOperations.completed || harvestAllOperations.failed) {
      setLoader(false);
      setLoaderMessage({
        message: harvestAllOperations.completed ? 'Transaction confirmed' : 'Transaction failed',
        type: harvestAllOperations.completed ? 'success' : 'error',
      });
      setTimeout(() => {
        setLoaderMessage({});
      }, 5000);
    } else {
      setLoaderMessage({});
    }
  }, [harvestAllOperations]);

  return (
    <>
      <Container fluid>
        <div className={`d-flex flex-column ${styles.fullScreen}`}>
          <FrontPageGradientDiv className={`row flex-grow-1 ${styles.homePageBanner}`}>
            <div
              className={clsx(
                `${styles.centerAlign}`,
                'py-5',
                walletConnected ? ['col-lg-6', 'col-sm-12', 'col-md-12'] : 'col-sm-12 col-md-12',
              )}
            >
              <div
                className={clsx(
                  walletConnected
                    ? [
                        'd-flex',
                        'flex-column',
                        'col-10',
                        'col-xl-9',
                        'm-auto',
                        'py-lg-5',
                        'text-center',
                        'align-items-center',
                        'ml-lg-auto',
                        'mr-lg-0',
                        'align-items-lg-start',
                        'text-lg-left',
                      ]
                    : [
                        'col-10',
                        'col-lg-7',
                        'm-auto',
                        'd-flex',
                        'align-items-center',
                        'text-center',
                        'flex-column',
                        'py-lg-5',
                      ],
                )}
              >
                <h5 className={`mb-3  text-white font-weight-light ${styles.textMulish}`}>
                  Total Value Locked
                </h5>
                <h1 className="mb-3 text-white font-weight-bold">
                  <NumericLabel params={currencyOptionsWithSymbol}>{tvl ? tvl : '0'}</NumericLabel>
                </h1>
                <h5
                  className={`mb-4 text-white text-mulish font-weight-light ${styles.textMulish}`}
                >
                  Bridge, trade, and earn. There is plenty of DeFi to explore on Tezos.
                </h5>
                <Link to={'swap'} className="text-decoration-none">
                  <Button
                    className={`px-lg-3 btn-frontPage ${styles.button}`}
                    color={'tertiary'}
                    onClick={null}
                  >
                    Enter App
                  </Button>
                </Link>
              </div>
            </div>
            {walletConnected && (
              <div className={`py-3 pb-lg-5 col-lg-6 col-sm-12 ${styles.centerAlign}`}>
                <div
                  className="col-lg-9 col-xl-7 m-auto py-lg-5 px-0 text-center
                                    align-items-center align-items-lg-start text-lg-left"
                >
                  <Stats
                    wallet={wallet}
                    harvestAll={onHarvestAll}
                    valueLocked={userTVL}
                    plentyEarned={251_532}
                    plentyInWallet={plentyBalance}
                    plentyToHarvest={plentyToHarvest}
                    harvestAllOperations={harvestAllOperations}
                    xplentyBalance={xplentyBalance}
                  />
                </div>
              </div>
            )}
          </FrontPageGradientDiv>
          <Row className="row bg-themed border-bottom-themed-dark-none">
            <Col sm={6} md={4} xl={2} className="px-5 pb-2 pt-3 m-sm-auto">
              <Label
                text={
                  homeStats.price ? (
                    <NumericLabel params={currencyOptions}>{homeStats.price}</NumericLabel>
                  ) : (
                    '0'
                  )
                }
                icon={theme === 'light' ? dollar : dollarDark}
                subText={'Price'}
              />
            </Col>
            <Col sm={6} md={4} xl={2} className="px-5 pb-2 pt-3 m-sm-auto">
              <Label
                text={
                  homeStats.marketcap ? (
                    <NumericLabel params={currencyOptions}>
                      {homeStats.marketcap.toFixed(0)}
                    </NumericLabel>
                  ) : (
                    '0'
                  )
                }
                icon={theme === 'light' ? marketCap : marketCapDark}
                subText={'Market Cap'}
              />
            </Col>
            <Col sm={6} md={4} xl={2} className="px-5 pb-2 pt-3 m-sm-auto">
              <Label
                text={
                  homeStats.total_minted ? (
                    <NumericLabel params={currencyOptions}>
                      {homeStats.total_minted.toFixed(0)}
                    </NumericLabel>
                  ) : (
                    '0'
                  )
                }
                icon={theme === 'light' ? farms : farmsDark}
                subText={'Total minted'}
              />
            </Col>
            <Col sm={6} md={4} xl={2} className="px-5 pb-2 pt-3 m-sm-auto">
              <Label
                text={
                  homeStats.total_burned ? (
                    <NumericLabel params={currencyOptions}>
                      {homeStats.total_burned.toFixed(0)}
                    </NumericLabel>
                  ) : (
                    '0'
                  )
                }
                icon={theme === 'light' ? totalBurned : totalBurnedDark}
                subText={'Total burned'}
              />
            </Col>
            <Col sm={6} md={4} xl={2} className="px-5 pb-2 pt-3 m-sm-auto">
              <Label
                text={
                  homeStats.circulating_supply ? (
                    <NumericLabel params={currencyOptions}>
                      {homeStats.circulating_supply.toFixed(0)}
                    </NumericLabel>
                  ) : (
                    '0'
                  )
                }
                icon={theme === 'light' ? circulatingSupply : circulatingSupplyDark}
                subText={'Circulating Supply'}
              />
            </Col>
            <Col sm={6} md={4} xl={2} className="px-5 pb-2 pt-3 m-sm-auto">
              <Label
                text={
                  homeStats.plenty_per_block ? (
                    <NumericLabel params={currencyOptions}>
                      {homeStats.plenty_per_block}
                    </NumericLabel>
                  ) : (
                    '0'
                  )
                }
                subText={'New PLENTY/Block'}
                icon={theme === 'light' ? plentyBlock : plentyBlockDark}
              />
            </Col>
          </Row>
        </div>
        <Row>
          <Col xs={12} className="text-center my-5">
            <h2 className="font-weight-bold">
              <p>Plenty of DeFi on Tezos</p>
            </h2>
          </Col>
        </Row>
        <Row className="mb-4 mx-lg-5">
          <div
            className="col-xl-11 row m-auto"
            style={{
              display: 'flex',
              justifyContent: 'center',
            }}
          >
            <Col xs={12} md={6} xl={3} className="mb-3 d-flex">
              <LinkTile
                text={'Transfer your tokens from Ethereum to Tezos within five minutes.'}
                linkTo={'/bridge'}
                linkText={'Enter Bridge'}
                headerIcon={theme === 'light' ? bridge : bridgeDark}
                headerText={'Bridge'}
              />
            </Col>
            <Col xs={12} md={6} xl={3} className="mb-3 d-flex">
              <LinkTile
                text={'Swap tokens instantly with high liquidity and audited smart contracts.'}
                linkTo={'/swap'}
                linkText={'Enter Exchange'}
                headerIcon={theme === 'light' ? amm : ammDark}
                headerText={'Swap'}
              />
            </Col>
            <Col xs={12} md={6} xl={3} className="mb-3 d-flex">
              <LinkTile
                text={'Add liquidity for any trading pair and start earning trading fees.'}
                linkTo={'/liquidity'}
                linkText={'Add Liquidity'}
                headerIcon={theme === 'light' ? liquidity : liquidityDark}
                headerText={'Pool'}
              />
            </Col>
            <Col xs={12} md={6} xl={3} className="mb-3 d-flex">
              <LinkTile
                text={
                  'Earn PLENTY and other tokens by staking Plenty Liquidity Provider tokens in a farm.'
                }
                linkTo={'/farms'}
                linkText={'Enter Farms'}
                headerIcon={theme === 'light' ? farms2 : farms2Dark}
                headerText={'Farm'}
              />
            </Col>
          </div>
        </Row>
        <Row className="py-5 bg-themed-alt">
          <Col lg={6} xs={12}>
            <div
              className="col-10 col-lg-9 col-xl-7 m-auto py-lg-5 px-0 text-center
                                    align-items-center align-items-lg-start text-lg-left"
            >
              <h2 className={`mb-1 font-weight-bold ${styles.about}`}>
                <p>About Plenty</p>
              </h2>
              <div className={`mb-3 ${styles.aboutSubtext}`}>
                <span>
                  <p>
                    Plenty is expanding DeFi use cases on Tezos towards a full scale decentralized
                    financial ecosystem. Empowering traders, liquidity providers & developers to
                    participate in an open financial marketplace.
                  </p>
                </span>
              </div>
              <a href={'https://plentydefi.medium.com/'} target="_blank" rel="noreferrer">
                <Medium className="mr-2 icon-themed" />
              </a>
              <a href={'https://discord.gg/9wZ4CuvkuJ'} target="_blank" rel="noreferrer">
                <Discord className="mr-2 icon-themed" />
              </a>

              <a href={'https://twitter.com/PlentyDeFi'} target="_blank" rel="noreferrer">
                <Twitter className="mr-2 icon-themed" />
              </a>
            </div>
          </Col>
          <Col lg={6} className="d-none d-lg-block">
            <div className="p-lg-5">
              <Image src={plentyBig} />
            </div>
          </Col>
        </Row>
        <FrontPageBottomGradientDiv className="row">
          <Col className="pt-5">
            <Row>
              <Col xs={12} md={6}>
                <div
                  className="col-10 col-xl-8 m-auto pb-5 py-lg-3 px-0
                                    align-items-start text-left"
                >
                  <h2 className="text-white font-weight-bold">Frequently asked questions</h2>
                </div>
              </Col>
            </Row>
            <Row className="border-bottom-themed">
              <Col xs={12} md={6}>
                <div
                  className="col-10 col-xl-8 m-auto py-lg-5 px-0
                                    align-items-start text-left"
                >
                  <Accordion isOpen={true} text={'What is Plenty?'} className={styles.divider}>
                    <div>
                      <p className="text-white">
                        The Plenty protocol enables swapping of fungible tokens on Tezos.
                      </p>
                      <p className="text-white">
                        You can only swap tokens on Plenty if there is enough liquidity for those
                        tokens. Providing liquidity will get you Plenty Liquidity Provider (PLP)
                        tokens, which will generate rewards in the form of trading fees for making
                        sure there&apos;s always liquidity for the exchange to use.
                      </p>
                      <p className="text-white">
                        Yield farming lets users that are providing liquidity earn PLENTY rewards by
                        locking their PLP tokens into a farm.
                      </p>
                    </div>
                  </Accordion>
                  <Accordion text={'How does Plenty work?'} className={styles.divider}>
                    <div>
                      <p className="text-white">
                        Plenty is a collection of smart contracts to make liquidity pools and
                        corresponding markets that are compatible with each other. The architecture
                        is based on&nbsp;
                        <a
                          href={
                            'https://docs.uniswap.org/protocol/V2/concepts/protocol-overview/how-uniswap-works'
                          }
                          target="_blank"
                          rel="noreferrer"
                        >
                          Uniswap V2
                        </a>
                        .
                      </p>
                      <p className="text-white">
                        Each pool is defined by a smart contract that includes a few functions to
                        enable swapping tokens, adding liquidity and more. At its core each pool
                        uses the function x*y=k to maintain a curve along which trades can happen.
                        The pools keep track of reserves (liquidity) and update those reserves every
                        single time someone trades. Because the reserves are automatically
                        rebalanced, a liquidity pool can always be used to buy or sell a token
                        without requiring a counterparty on the other side of a trade.
                      </p>
                    </div>
                  </Accordion>
                  <Accordion text={'Why can’t I trade native tez?'} className={styles.divider}>
                    <div>
                      <p className="text-white">
                        Plenty is the first token-to-token Automated Market Maker (AMM) on Tezos.
                        This means that native tez trading is not supported. However, trading with a
                        collateralized version of tez, called&nbsp;
                        <a href={'https://ctez.app/'} target="_blank" rel="noreferrer">
                          ctez
                        </a>
                        &nbsp;is supported.
                      </p>

                      <p className="text-white">
                        Ctez solves the issue of using tez inside DeFi contracts without worrying
                        about the governance matter of &quot;who should be the baker&quot; and
                        without the opportunity cost of not delegating.
                      </p>
                    </div>
                  </Accordion>
                </div>
              </Col>
              <Col xs={12} md={6}>
                <div
                  className="col-10 col-xl-8 m-auto py-lg-5 px-0
                                    align-items-start text-left"
                >
                  <Accordion text={'How do I use Plenty?'} className={styles.divider}>
                    <div>
                      <p className="text-white">
                        First you’ll need a Tezos wallet and some tez. Tez is available at all big
                        crypto exchanges like&nbsp;
                        <a href={'https://www.coinbase.com/'} target="_blank" rel="noreferrer">
                          Coinbase
                        </a>
                        ,&nbsp;
                        <a href={'https://www.kraken.com/'} target="_blank" rel="noreferrer">
                          Kraken
                        </a>
                        &nbsp; and&nbsp;
                        <a href={'https://www.binance.com/'} target="_blank" rel="noreferrer">
                          Binance
                        </a>
                        . Do you have some tez? Go to&nbsp;
                        <a href={'https://ctez.app/'} target="_blank" rel="noreferrer">
                          ctez.app
                        </a>
                        &nbsp;to swap it for ctez!
                      </p>
                      <p className="text-white">
                        Each transaction on Tezos comes with a small gas fee, paid in tez, which is
                        a fee for the bakers to keep the Proof of Stake network running. So make
                        sure you to keep some tez for these fees.
                      </p>
                      <p className="text-white">
                        If you are a DeFi user from another blockchain, you can wrap your assets
                        using the&nbsp;
                        <a href={'https://www.benderlabs.io/wrap'} target="_blank" rel="noreferrer">
                          Wrap Protocol
                        </a>
                        .&nbsp;Wrap tokens like USDC, BUSD, LINK, MATIC, or WBTC on the Ethereum
                        blockchain, and use them on Plenty to trade and earn.
                      </p>
                    </div>
                  </Accordion>
                  <Accordion text={'How are prices determined?'} className={styles.divider} s>
                    <div>
                      <p className="text-white">
                        Prices are determined by the amount of each token in a pool. The smart
                        contract maintains a constant using the following function: x*y=k. For
                        example, x = tokenABC, y = tokenXYZ, and k = constant. During each trade, a
                        certain amount of one token is removed from the pool for an amount of the
                        other token. To maintain k, the balances held by the smart contract are
                        adjusted during the execution of the trade, thereby changing the price.
                      </p>
                    </div>
                  </Accordion>
                  <Accordion text={'Are there risks?'} className={styles.divider}>
                    <div>
                      <p className="text-white">
                        Using smart contracts always brings risk. To reduce this risk, the Plenty
                        smart contracts are audited. Both the AMM and staking smart contracts&nbsp;
                        <a
                          href={
                            'https://plenty-defi.notion.site/Audits-70fdccf107ec42feb0bcf720cb6c5ba5'
                          }
                          target="_blank"
                          rel="noreferrer"
                        >
                          were audited
                        </a>
                        &nbsp;successfully.
                      </p>
                      <p className="text-white">
                        For liquidity providers there is the risk of Impermanent loss. This is a
                        price difference that can occur when holding tokens in an AMM liquidity pool
                        instead of holding them in your wallet. It occurs when the price of tokens
                        inside an AMM diverge in any direction. The more divergence, the greater the
                        impermanent loss.
                      </p>
                    </div>
                  </Accordion>
                  <Image className={'mt-4'} src={plentyMedium} />
                </div>
              </Col>
            </Row>
            <Row className="justify-content-center mb-5 mt-4">
              <Footer />
            </Row>
          </Col>
        </FrontPageBottomGradientDiv>
      </Container>
      <InfoModal
        open={modalData.open === HOME_PAGE_MODAL.TRANSACTION_SUCCESS}
        theme={theme}
        InfoMessage={'Harvest tokens'}
        onClose={() => openCloseModal({ open: HOME_PAGE_MODAL.NULL, transactionId: '' })}
        message={'Transaction submitted'}
        buttonText={'View on Block Explorer'}
        onBtnClick={
          !modalData.transactionId
            ? undefined
            : () => window.open(`https://tzkt.io/${modalData.transactionId}`, '_blank')
        }
      />
      {modalData.snackbar && (
        <Loader
          loading={harvestAllOperations.processing}
          loaderMessage={loaderMessage}
          setLoaderMessage={setLoaderMessage}
          content={'Harvest tokens'}
          theme={theme}
          onBtnClick={
            !modalData.transactionId
              ? undefined
              : () => window.open(`https://tzkt.io/${modalData.transactionId}`, '_blank')
          }
        />
      )}
      <ConfirmTransaction
        show={showConfirmTransaction}
        theme={theme}
        content={'Harvest tokens'}
        onHide={handleClose}
      />
    </>
  );
}
Example #26
Source File: Tokens.js    From plenty-interface with GNU General Public License v3.0 4 votes vote down vote up
Tokens = () => {
  const {
    data = [],
    isLoading,
    error,
  } = useGetTokensQuery(undefined, {
    pollingInterval: 30_000,
  });

  const { data: priceChangeData = {}, isLoading: priceChangeLoading } = useGet7DaysChangeQuery(
    undefined,
    {
      pollingInterval: 30_000,
    },
  );

  const { imgPaths } = useLazyImages({ data });

  const { isOnlyFavTokens, setIsOnlyFavTokens, favoriteTokens, editFavoriteTokenList } =
    useFavoriteToken('token');

  const { positiveOrNegative, valueFormat, stringSort, numberSort } = useTableNumberUtils();

  // ? Move to React Table filter later
  const finalData = useMemo(() => {
    if (isOnlyFavTokens) {
      return data?.filter((datum) => favoriteTokens.includes(datum.symbol_token)) ?? [];
    }

    return data;
  }, [favoriteTokens, isOnlyFavTokens, data]);

  const columns = useMemo(
    () => [
      {
        Header: (
          <TokensSymbolHeader
            className={styles.favoriteIcon}
            isOnlyFavTokens={isOnlyFavTokens}
            setIsOnlyFavTokens={setIsOnlyFavTokens}
          />
        ),
        id: 'favorite',
        accessor: 'symbol_token',
        disableSortBy: true,
        Cell: (row) => (
          <TokensSymbol
            tokenSymbol={row.value}
            className={styles.favoriteIcon}
            favoriteTokens={favoriteTokens}
            editFavoriteTokenList={editFavoriteTokenList}
          />
        ),
      },
      {
        Header: <span className="ml-2">Name</span>,
        id: 'token',
        accessor: 'symbol_token',
        sortType: stringSort,
        Cell: (row) => (
          <div className="d-flex pl-2 align-items-center">
            <Image src={imgPaths[row.value]?.url} height={32} width={32} alt={''} />
            <span className="ml-2 mr-4">
              {row.value === 'tez' ? 'TEZ' : row.value === 'ctez' ? 'CTEZ' : row.value}
            </span>
          </div>
        ),
        width: 120,
      },
      {
        Header: 'Price',
        accessor: 'token_price',
        sortType: numberSort,
        Cell: (row) => <span title={row.value}>{valueFormat(row.value)}</span>,
      },
      {
        Header: '24h Change',
        accessor: 'price_change_percentage',
        sortType: numberSort,
        Cell: (row) => (
          <span>{positiveOrNegative(valueFormat(row.value, { percentChange: true }))}</span>
        ),
      },
      {
        Header: '24h Volume',
        accessor: 'volume_token',
        sortType: numberSort,
        Cell: (row) => <span>{valueFormat(row.value)}</span>,
      },
      {
        Header: 'Liquidity',
        accessor: 'liquidity',
        sortType: numberSort,
        Cell: (row) => <span>{valueFormat(row.value)}</span>,
      },
      {
        id: 'price7d',
        Header: 'Last 7 Days',
        accessor: 'symbol_token',
        Cell: (row) => {
          let value = [...(priceChangeData[row.value] ?? [])].reverse();

          if (priceChangeLoading) return <div />;

          if (value.length === 0) return <div>N/A</div>;

          const changePositive = value[value.length - 1].value >= value[0].value;

          if (value.length <= 38) {
            const timeData = priceChangeData.PLENTY.map((x) => ({
              ...x,
              value: undefined,
            })).reverse();
            value = [...timeData.filter((x) => x.time < value[0].time), ...value];
          }

          return (
            <SimpleLineChart
              data={value}
              color={changePositive ? '#4FBF67' : '#FF7A68'}
              className="mx-2"
            />
          );
        },
        minWidth: 170,
        disableSortBy: true,
      },
      {
        disableSortBy: true,
        Header: '',
        id: 'trade',
        accessor: (x) => (
          <Link style={{ textDecoration: 'none' }} to={`/swap?from=${x.symbol_token}`}>
            <Button color="primary" className={styles.tradeBtn}>
              Trade
            </Button>
          </Link>
        ),
        width: 120,
      },
    ],
    [
      isOnlyFavTokens,
      setIsOnlyFavTokens,
      stringSort,
      numberSort,
      favoriteTokens,
      editFavoriteTokenList,
      imgPaths,
      priceChangeData,
      priceChangeLoading,
    ],
  );

  const [searchQuery, setSearchQuery] = useState('');

  return (
    <>
      <Container fluid className={clsx(styles.tokens, styles.tokensTable)}>
        <div className="w-100 d-flex justify-content-between px-5 align-items-center">
          <h5 className="font-weight-bolder">Tokens</h5>
          <InputGroup className={styles.searchBar}>
            <InputGroup.Prepend>
              <InputGroup.Text className={`${styles.searchIcon} border-right-0`}>
                <BsSearch />
              </InputGroup.Text>
            </InputGroup.Prepend>
            <FormControl
              placeholder="Search"
              className={`shadow-none border-left-0 ${styles.searchBox}`}
              value={searchQuery}
              onChange={(ev) => setSearchQuery(ev.target.value)}
            />
          </InputGroup>
        </div>

        {data.length > 0 && (
          <div>
            <Table searchQuery={searchQuery} data={finalData} columns={columns} />
          </div>
        )}

        {data.length === 0 && (isLoading || error) && (
          <div className="d-flex justify-content-between w-100" style={{ height: 800 }}>
            <div className="m-auto">
              {error ? <div>Something went wrong</div> : <PuffLoader color={'#813CE1'} size={56} />}
            </div>
          </div>
        )}
      </Container>

      <FavoriteIconGradient />
    </>
  );
}
Example #27
Source File: NFTprofile.js    From RC4Community with Apache License 2.0 4 votes vote down vote up
GalleryModal = ({
  handleClose,
  show,
  assets,
  handleImage,
  uid,
  select,
  load,
  setLoad,
  errMess,
  setErrMess,
}) => {
  const [upsertNFT, { data, loading, error, reset }] = useMutation(UPSERT_NFT);
  useEffect(() => {
    if (data) {
      setLoad(false);
    }
  }, [data]);
  if (loading) {
    setLoad(true);
  }
  const handleSubmit = (e) => {
    e.preventDefault();
    const assetSelected = assets[select.split("_")[1]];
    const address = assetSelected.asset_contract.address;
    const token = assetSelected.token_id;
    upsertNFT({ variables: { id: uid, address: address, token: token } });
  };

  if (error) {
    if (error.graphQLErrors[0].extensions.code == "instance not found") {
      setErrMess("User not found");
    }
    if (error.graphQLErrors[0].extensions.code == "instance not unique") {
      setErrMess("NFT is owned by someone else");
    } else {
      setErrMess(error.message);
    }
    setTimeout(() => {
      reset();
      setLoad(false);
    }, 5000);
  }

  return (
    <>
      <Modal show={show} onHide={handleClose}>
        <Modal.Header closeButton>
          <Modal.Title>Select a NFT</Modal.Title>
        </Modal.Header>
        {error && (
          <Alert variant={"danger"}>{errMess} - Please try again!</Alert>
        )}
        <Modal.Body className={styles.selectNFT}>
          {assets
            ? assets.map(
                (a, i) =>
                  a.image_url && (
                    <div key={i} className={styles.asset}>
                      <Image
                        key={i}
                        onClick={handleImage}
                        className={`${styles.assetImage} nim_${i}`}
                        src={a.image_url}
                      />
                    </div>
                  )
              )
            : "No assets available"}
        </Modal.Body>
        <Modal.Footer>
          <Button variant="secondary" onClick={handleClose}>
            Close
          </Button>
          <Button variant="primary" disabled={load} onClick={handleSubmit}>
            {!load ? (
              "Save Changes"
            ) : (
              <Spinner
                as="span"
                animation="grow"
                size="sm"
                role="status"
                aria-hidden="true"
              />
            )}
          </Button>
        </Modal.Footer>
      </Modal>
    </>
  );
}
Example #28
Source File: user-header.js    From stacker.news with MIT License 4 votes vote down vote up
export default function UserHeader ({ user }) {
  const [editting, setEditting] = useState(false)
  const me = useMe()
  const router = useRouter()
  const client = useApolloClient()
  const [setName] = useMutation(NAME_MUTATION)

  const isMe = me?.name === user.name
  const Satistics = () => <div className={`mb-2 ml-0 ml-sm-1 ${styles.username} text-success`}>{isMe ? `${user.sats} sats \\ ` : ''}{user.stacked} stacked</div>

  const UserSchema = Yup.object({
    name: Yup.string()
      .required('required')
      .matches(/^[\w_]+$/, 'only letters, numbers, and _')
      .max(32, 'too long')
      .test({
        name: 'name',
        test: async name => {
          if (!name || !name.length) return false
          const { data } = await client.query({ query: NAME_QUERY, variables: { name }, fetchPolicy: 'network-only' })
          return data.nameAvailable
        },
        message: 'taken'
      })
  })

  const lnurlp = encodeLNUrl(new URL(`https://stacker.news/.well-known/lnurlp/${user.name}`))

  return (
    <>
      <div className='d-flex mt-2 flex-wrap flex-column flex-sm-row'>
        <div className='position-relative' style={{ width: 'fit-content' }}>
          <Image
            src={user.photoId ? `https://${process.env.NEXT_PUBLIC_AWS_UPLOAD_BUCKET}.s3.amazonaws.com/${user.photoId}` : '/dorian400.jpg'} width='135' height='135'
            className={styles.userimg}
          />
          {isMe && <PhotoEditor userId={me.id} />}
        </div>
        <div className='ml-0 ml-sm-1 mt-3 mt-sm-0 justify-content-center align-self-sm-center'>
          {editting
            ? (
              <Form
                schema={UserSchema}
                initial={{
                  name: user.name
                }}
                validateImmediately
                onSubmit={async ({ name }) => {
                  if (name === user.name) {
                    setEditting(false)
                    return
                  }
                  const { error } = await setName({ variables: { name } })
                  if (error) {
                    throw new Error({ message: error.toString() })
                  }
                  router.replace({
                    pathname: router.pathname,
                    query: { ...router.query, name }
                  })

                  client.writeFragment({
                    id: `User:${user.id}`,
                    fragment: gql`
                  fragment CurUser on User {
                    name
                  }
                `,
                    data: {
                      name
                    }
                  })

                  setEditting(false)
                }}
              >
                <div className='d-flex align-items-center mb-2'>
                  <Input
                    prepend=<InputGroup.Text>@</InputGroup.Text>
                    name='name'
                    autoFocus
                    groupClassName={styles.usernameForm}
                    showValid
                  />
                  <SubmitButton variant='link' onClick={() => setEditting(true)}>save</SubmitButton>
                </div>
              </Form>
              )
            : (
              <div className='d-flex align-items-center mb-2'>
                <div className={styles.username}>@{user.name}</div>
                {isMe &&
                  <Button className='py-0' style={{ lineHeight: '1.25' }} variant='link' onClick={() => setEditting(true)}>edit nym</Button>}
              </div>
              )}
          <Satistics user={user} />
          <ModalButton
            clicker={
              <Button className='font-weight-bold ml-0 ml-sm-2'>
                <LightningIcon
                  width={20}
                  height={20}
                  className='mr-1'
                />{user.name}@stacker.news
              </Button>
            }
          >
            <a className='d-flex m-auto p-3' style={{ background: 'white', width: 'fit-content' }} href={`lightning:${lnurlp}`}>
              <QRCode className='d-flex m-auto' value={lnurlp} renderAs='svg' size={300} />
            </a>
            <div className='text-center font-weight-bold text-muted mt-3'>click or scan</div>
          </ModalButton>
        </div>
      </div>
      <Nav
        className={styles.nav}
        activeKey={router.asPath.split('?')[0]}
      >
        <Nav.Item>
          <Link href={'/' + user.name} passHref>
            <Nav.Link>bio</Nav.Link>
          </Link>
        </Nav.Item>
        <Nav.Item>
          <Link href={'/' + user.name + '/posts'} passHref>
            <Nav.Link>{user.nitems} posts</Nav.Link>
          </Link>
        </Nav.Item>
        <Nav.Item>
          <Link href={'/' + user.name + '/comments'} passHref>
            <Nav.Link>{user.ncomments} comments</Nav.Link>
          </Link>
        </Nav.Item>
        {isMe &&
          <Nav.Item>
            <Link href='/satistics?inc=invoice,withdrawal' passHref>
              <Nav.Link eventKey='/satistics'>satistics</Nav.Link>
            </Link>
          </Nav.Item>}
      </Nav>
    </>
  )
}
Example #29
Source File: index.jsx    From nightfall_3 with Creative Commons Zero v1.0 Universal 4 votes vote down vote up
Transactions = () => {
  const [txs, setTxs] = React.useState([]);
  const [isActive, setActive] = React.useState('all');
  const [showModal, setShowModal] = React.useState({ show: false });
  const [delay, setDelay] = React.useState(50);
  const [etherscan] = React.useState(
    ChainIdMapping[process.env.REACT_APP_MODE].chainName === 'Ethereum Mainnet'
      ? 'etherscan.io'
      : 'goerli.etherscan.io',
  );

  const initialPrices = {};
  supportedTokens.forEach(t => {
    initialPrices[t.id] = 0;
  }, {});

  const [currencyValues, setCurrencyValues] = React.useState({ now: 0, ...initialPrices });

  React.useEffect(async () => {
    if (!getPricing()) await setPricing(supportedTokens.map(t => t.id));
    else if (Date.now() - getPricing().time > 86400)
      await setPricing(supportedTokens.map(t => t.id));
    setCurrencyValues(getPricing());
  }, []);

  useInterval(async () => {
    console.log('currencyVals', currencyValues);
    const transactionsDB = await getAllTransactions();
    const commitmentsDB = await getAllCommitments();
    const commits = commitmentsDB.map(c => c._id);
    const nullifiers = commitmentsDB.map(c => c.nullifier);

    const transactions = Array.from(new Set(transactionsDB)).filter(
      t =>
        t.commitments.some(c => commits.includes(c)) ||
        t.nullifiers.some(n => nullifiers.includes(n)),
    );
    const shieldContractAddress = shieldAddressGet();
    const shieldContractInstance = await getContractInstance(
      SHIELD_CONTRACT_NAME,
      shieldContractAddress,
    );
    setDelay(20000);

    const blocks = await findBlocksFromBlockNumberL2(-1);
    const promisedTxs = transactions.map(async tx => {
      const safeTransactionType = BigInt(tx.transactionType).toString();
      let value = BigInt(tx.value);
      // The value of transfers need to be derived from the components making up the transfer
      // Add sum nullifiers in transactions
      // Subtract sum of commitments we have.
      if (safeTransactionType === '1' || safeTransactionType === '2')
        commitmentsDB.forEach(c => {
          if (tx.nullifiers.includes(c.nullifier)) value -= BigInt(c.preimage.value);
          else if (tx.commitments.includes(c._id)) value += BigInt(c.preimage.value);
        });

      const safeValue = value.toString();
      const { ercAddress } = commitmentsDB.find(c => {
        return tx.commitments.includes(c._id) || tx.nullifiers.includes(c.nullifier);
      })?.preimage ?? {
        ercAddress: '0x00',
      };

      // eslint-disable-next-line no-param-reassign
      if (tx?.blockNumberL2) tx.isOnChain = tx.blockNumberL2; // Temp for handling transfers
      blocks.forEach(b => {
        if (tx.isOnChain >= 0) return;
        if (b.transactionHashes.includes(tx._id)) {
          // eslint-disable-next-line no-param-reassign
          tx.isOnChain = b.blockNumberL2;
        }
        // eslint-disable-next-line no-param-reassign
        else tx.isOnChain = -1;
      });

      let withdrawReady = false;
      if (
        safeTransactionType === '3' &&
        tx.isOnChain > 0 &&
        tx.withdrawState !== 'finalised' &&
        Math.floor(Date.now() / 1000) - tx.createdTime > 3600 * 24 * 7
      ) {
        withdrawReady = await isValidWithdrawal(tx._id, shieldContractAddress);
      }
      if (tx.withdrawState === 'instant') {
        const newOwner = await shieldContractInstance.methods.advancedWithdrawals(tx._id).call();
        const myAddress = await Web3.getAccount();
        if (newOwner.toLowerCase() !== ZERO && newOwner.toLowerCase() !== myAddress.toLowerCase())
          // eslint-disable-next-line no-param-reassign
          tx.withdrawState = 'fulfilled';
      }

      const { logoURI, decimals, id, symbol } = supportedTokens.find(
        t => t.address.toLowerCase() === `0x${ercAddress.slice(-40).toLowerCase()}`,
      ) ?? {
        logoURI: null,
        decimals: 0,
        id: '',
      };
      const currencyValue = id !== '' ? currencyValues[id] : 0;
      return {
        ...tx,
        transactionHash: tx._id,
        txType: safeTransactionType,
        value: safeValue,
        now: Math.floor(Date.now() / 1000),
        logoURI,
        decimals,
        currencyValue,
        symbol,
        withdrawReady,
      };
    });
    const mappedTxs = (await Promise.all(promisedTxs)).sort(
      (a, b) => b.createdTime - a.createdTime,
    );
    console.log('Transactions', transactions);
    setTxs(mappedTxs);
  }, delay);

  function downloadFile(content) {
    const a = document.createElement('a');
    const file = new Blob([content], { type: 'text/plain' });
    a.href = URL.createObjectURL(file);
    a.download = 'pnf_bkp.json';
    a.click();
  }

  const handleExportIndedexDB = async () => {
    const exportedDB = await exportIndexdDB('nightfall_commitments');
    const filteredTables = exportedDB.filter(
      arr => arr.table === 'commitments' || arr.table === 'transactions',
    );
    downloadFile(JSON.stringify(filteredTables));
  };

  return (
    <div className="pagePartition" style={{ width: '100%' }}>
      <TxInfoModal onHide={() => setShowModal(false)} {...showModal} />
      <div className="infoWrapper">
        <div className="wrapperTabList">
          <div className="tab-list">
            <div
              className={`tab-list-item ${isActive === 'all' ? 'active' : ''}`}
              onClick={() => setActive('all')}
            >
              All Transactions
            </div>
            <div
              className={`tab-list-item ${isActive === 'pending' ? 'active' : ''}`}
              onClick={() => setActive('pending')}
            >
              Pending
            </div>
            <div
              className={`tab-list-item ${isActive === 'deposit' ? 'active' : ''}`}
              onClick={() => setActive('deposit')}
            >
              Deposits
            </div>
            <div
              className={`tab-list-item ${isActive === 'transfer' ? 'active' : ''}`}
              onClick={() => setActive('transfer')}
            >
              Transfers
            </div>
            <div
              className={`tab-list-item ${isActive === 'withdraw' ? 'active' : ''}`}
              onClick={() => setActive('withdraw')}
            >
              Withdraws
            </div>
          </div>
          <div>
            <button onClick={() => handleExportIndedexDB()} className="exportTransactionsButton">
              Export transactions
            </button>
          </div>
        </div>
        <div className="separator" />
        <div className="innerWrapper">
          {txs
            .filter(f => {
              switch (isActive) {
                case 'deposit':
                  return f.txType === '0';
                case 'transfer':
                  return f.txType === '1' || f.txType === '2';
                case 'withdraw':
                  return f.txType === '3';
                case 'pending':
                  return f.isOnChain === -1;
                default:
                  return f;
              }
            })
            .map(tx => (
              <Row
                key={tx.transactionHash}
                className="transactionRow"
                onClick={() =>
                  setShowModal({
                    show: true,
                    transactionhash: tx.transactionHash,
                    symbol: tx.symbol,
                    value: new BigFloat(BigInt(tx.value), tx.decimals).toFixed(4),
                    _id: tx._id,
                    recipientaddress: tx.recipientAddress,
                    withdrawready: tx.withdrawReady ? 1 : 0,
                    txtype: tx.txType,
                  })
                }
              >
                <Row>
                  <div className="transactionDetails">
                    <div>
                      {tx.isOnChain >= 0 ? (
                        <Image src={tickBox} />
                      ) : (
                        <Spinner animation="border" variant="warning" />
                      )}
                    </div>
                    <div style={{ marginLeft: '14px' }}>
                      {/* Details */}
                      <div style={{ display: 'flex', fontWeight: '600', fontSize: '14px' }}>
                        {/* tx-type-time */}
                        <div style={{ textTransform: 'capitalize' }}>
                          {txTypeOptions[tx.txType]}
                        </div>
                        {/* tx-type-time-type */}
                        <div style={{ color: '#b0b4bb', paddingLeft: '5px' }}>
                          {/* tx-type-time-time */}
                          {displayTime(tx.createdTime, tx.now)}
                        </div>
                      </div>
                      <div
                        style={{
                          display: 'flex',
                          color: '#52555d',
                          fontWeight: '400',
                          fontSize: '12px',
                          lineHeight: '16px',
                        }}
                      >
                        {/* tx-status-hash */}
                        {/* <div> 1/3 • Action Required • From Mumbai to Goerli</div> */}
                        <div style={{ textTransform: 'capitalize' }}>
                          {tx.isOnChain >= 0 ? 'Success' : 'Pending'} • {txTypeDest[tx.txType]}{' '}
                          {!tx.withdrawState ? '' : `• ${tx.withdrawState}`}
                        </div>
                      </div>
                    </div>
                  </div>
                  <div
                    style={{
                      padding: '20px',
                      width: '42%',
                      alignItems: 'center',
                      display: 'flex',
                    }}
                  >
                    {/* details-section */}
                    <div style={{ display: 'block' }}>
                      {/* token-image */}
                      <img src={tx.logoURI} alt="" height="32" width="32" />
                    </div>
                    <div
                      style={{
                        width: 'calc(50% - 50px)',
                        marginLeft: '8px',
                        flexShrink: '0',
                      }}
                    >
                      {/* amount-details */}
                      <div style={{ fontWeight: '600', fontSize: '14px', lineHeight: '20px' }}>
                        {new BigFloat(BigInt(tx.value), tx.decimals).toFixed(4)} {tx.symbol}
                      </div>
                      <div
                        style={{
                          color: '#52555d',
                          marginTop: '4px',
                          wordBreak: 'break-all',
                          fontWeight: '400',
                          fontSize: '12px',
                          lineHeight: '16px',
                        }}
                      >
                        $
                        {new BigFloat(BigInt(tx.value), tx.decimals)
                          .mul(tx.currencyValue)
                          .toFixed(4)}
                      </div>
                    </div>
                    <div
                      style={{
                        marginLeft: '8px',
                        width: 'calc(50% - 50px)',
                        flexShrink: '0',
                      }}
                    >
                      {/* Transaction Details */}
                      <div style={{ fontWeight: '600', fontSize: '14px', lineHeight: '20px' }}>
                        {/* Transaction Hash label */}
                        Transaction Hash
                      </div>
                      <div
                        style={{
                          color: '#52555d',
                          marginTop: '4px',
                          display: 'flex',
                          alignItems: 'center',
                          cursor: 'pointer',
                          fontWeight: '400',
                          fontSize: '12px',
                          lineHeight: '16px',
                        }}
                      >
                        {/* Tooltip */}
                        <img src={polygonChainImage} alt="Polygon Chain" height="16" width="16" />
                        <div style={{ marginLeft: '4px' }}>{`${tx.transactionHash.slice(
                          0,
                          5,
                        )}...${tx.transactionHash.slice(-5)}`}</div>
                      </div>
                    </div>
                    <a
                      href={`https://${etherscan}/tx/${tx.l1Hash}`}
                      className="etherscanLink"
                      rel="noopener noreferrer"
                      target="_blank"
                      style={{ marginLeft: '20px' }}
                      onClick={e => e.stopPropagation()}
                    >
                      <Image src={etherscanArrow} />
                    </a>
                  </div>
                </Row>
                {tx.txType === '3' && tx.isOnChain > 0 && !tx.withdrawState ? (
                  <WithdrawTransaction
                    withdrawready={tx.withdrawReady}
                    transactionhash={tx.transactionHash}
                  />
                ) : (
                  <></>
                )}
              </Row>
            ))}
        </div>
        <Row>
          <div className="bottomSection">
            <img src={bridgeInfoImage} alt="" height="219" width="326" />
          </div>
        </Row>
      </div>
    </div>
  );
}