mirror of
https://github.com/RoboSats/robosats.git
synced 2025-02-20 12:19:00 +00:00
Run linter and add linter GH action
This commit is contained in:
parent
9d73f1ec34
commit
14487a9c2d
2
.github/workflows/codeql-analysis.yml
vendored
2
.github/workflows/codeql-analysis.yml
vendored
@ -16,7 +16,7 @@ on:
|
||||
branches: [ "main" ]
|
||||
pull_request:
|
||||
# The branches below must be a subset of the branches above
|
||||
branches: [ "main" ]
|
||||
# branches: [ "main" ]
|
||||
schedule:
|
||||
- cron: '39 10 * * 2'
|
||||
|
||||
|
39
.github/workflows/linter.yml
vendored
Normal file
39
.github/workflows/linter.yml
vendored
Normal file
@ -0,0 +1,39 @@
|
||||
name: Lint
|
||||
|
||||
on:
|
||||
# Trigger the workflow on push or pull request,
|
||||
# but only for the main branch
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
pull_request:
|
||||
branches:
|
||||
- main
|
||||
|
||||
jobs:
|
||||
run-linters:
|
||||
name: Run linters
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Check out Git repository
|
||||
uses: actions/checkout@v2
|
||||
|
||||
- name: 'Setup node'
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: 16.17.0
|
||||
cache: npm
|
||||
cache-dependency-path: frontend/package-lock.json
|
||||
|
||||
# ESLint and Prettier must be in `package.json`
|
||||
- name: 'Install NPM Dependencies'
|
||||
run: |
|
||||
cd frontend
|
||||
npm install -f
|
||||
|
||||
- name: Run linters
|
||||
uses: wearerequired/lint-action@v2
|
||||
with:
|
||||
prettier: true
|
||||
prettier_dir: frontend
|
@ -1,13 +1,13 @@
|
||||
import React, { Component , Suspense } from "react";
|
||||
import React, { Component, Suspense } from 'react';
|
||||
import ReactDOM from 'react-dom/client';
|
||||
import HomePage from "./HomePage";
|
||||
import { CssBaseline, IconButton , Link} from "@mui/material";
|
||||
import HomePage from './HomePage';
|
||||
import { CssBaseline, IconButton, Link } from '@mui/material';
|
||||
import { ThemeProvider, createTheme } from '@mui/material/styles';
|
||||
import UnsafeAlert from "./UnsafeAlert";
|
||||
import { LearnDialog } from "./Dialogs";
|
||||
import UnsafeAlert from './UnsafeAlert';
|
||||
import { LearnDialog } from './Dialogs';
|
||||
|
||||
import { I18nextProvider } from "react-i18next";
|
||||
import i18n from "./i18n";
|
||||
import { I18nextProvider } from 'react-i18next';
|
||||
import i18n from './i18n';
|
||||
|
||||
//Icons
|
||||
import DarkModeIcon from '@mui/icons-material/DarkMode';
|
||||
@ -24,63 +24,77 @@ export default class App extends Component {
|
||||
dark: window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches,
|
||||
expandedSettings: false,
|
||||
openLearn: false,
|
||||
theme: {typography: { fontSize: 14 }},
|
||||
}
|
||||
theme: { typography: { fontSize: 14 } },
|
||||
};
|
||||
}
|
||||
|
||||
lightTheme = createTheme ({});
|
||||
lightTheme = createTheme({});
|
||||
|
||||
darkTheme = createTheme({
|
||||
palette: {
|
||||
mode: 'dark',
|
||||
background: {
|
||||
default: "#070707"
|
||||
default: '#070707',
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
onSettingsClick = () => {
|
||||
this.setState({
|
||||
expandedSettings: ! this.state.expandedSettings
|
||||
})
|
||||
}
|
||||
expandedSettings: !this.state.expandedSettings,
|
||||
});
|
||||
};
|
||||
|
||||
onZoomClick = (direction) => {
|
||||
let zoomChange;
|
||||
direction === "out" ? zoomChange = -1 : zoomChange = 1;
|
||||
this.setState(({theme}) => ({
|
||||
theme: {
|
||||
direction === 'out' ? (zoomChange = -1) : (zoomChange = 1);
|
||||
this.setState(({ theme }) => ({
|
||||
theme: {
|
||||
...theme,
|
||||
typography: {
|
||||
fontSize: this.state.theme.typography.fontSize + zoomChange,
|
||||
},
|
||||
}
|
||||
},
|
||||
}));
|
||||
}
|
||||
};
|
||||
|
||||
render() {
|
||||
return (
|
||||
<Suspense fallback="loading language">
|
||||
<I18nextProvider i18n={i18n}>
|
||||
<ThemeProvider theme={this.state.dark ? this.darkTheme : createTheme(this.state.theme)}>
|
||||
<CssBaseline/>
|
||||
<LearnDialog open={this.state.openLearn} onClose={()=> this.setState({openLearn:false})}/>
|
||||
<IconButton sx={{position:'fixed',right:'34px'}} onClick={()=> this.setState({openLearn:true})}><SchoolIcon/></IconButton>
|
||||
<IconButton sx={{position:'fixed',right:'0px'}} onClick={()=>this.setState({dark:!this.state.dark})}>
|
||||
{this.state.dark ? <LightModeIcon/>:<DarkModeIcon/>}
|
||||
</IconButton>
|
||||
<IconButton sx={{position:'fixed',right:'34px'}} onClick={()=> this.setState({openLearn:true})}><SchoolIcon/></IconButton>
|
||||
<UnsafeAlert className="unsafeAlert"/>
|
||||
<HomePage {...this.state}/>
|
||||
</ThemeProvider>
|
||||
</I18nextProvider>
|
||||
<Suspense fallback='loading language'>
|
||||
<I18nextProvider i18n={i18n}>
|
||||
<ThemeProvider theme={this.state.dark ? this.darkTheme : createTheme(this.state.theme)}>
|
||||
<CssBaseline />
|
||||
<LearnDialog
|
||||
open={this.state.openLearn}
|
||||
onClose={() => this.setState({ openLearn: false })}
|
||||
/>
|
||||
<IconButton
|
||||
sx={{ position: 'fixed', right: '34px' }}
|
||||
onClick={() => this.setState({ openLearn: true })}
|
||||
>
|
||||
<SchoolIcon />
|
||||
</IconButton>
|
||||
<IconButton
|
||||
sx={{ position: 'fixed', right: '0px' }}
|
||||
onClick={() => this.setState({ dark: !this.state.dark })}
|
||||
>
|
||||
{this.state.dark ? <LightModeIcon /> : <DarkModeIcon />}
|
||||
</IconButton>
|
||||
<IconButton
|
||||
sx={{ position: 'fixed', right: '34px' }}
|
||||
onClick={() => this.setState({ openLearn: true })}
|
||||
>
|
||||
<SchoolIcon />
|
||||
</IconButton>
|
||||
<UnsafeAlert className='unsafeAlert' />
|
||||
<HomePage {...this.state} />
|
||||
</ThemeProvider>
|
||||
</I18nextProvider>
|
||||
</Suspense>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
const root = ReactDOM.createRoot(
|
||||
document.getElementById("app")
|
||||
);
|
||||
const root = ReactDOM.createRoot(document.getElementById('app'));
|
||||
|
||||
root.render(<App />);
|
||||
|
@ -1,30 +1,30 @@
|
||||
import React, { useState } from "react";
|
||||
import React, { useState } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { useAutocomplete } from '@mui/base/AutocompleteUnstyled';
|
||||
import { styled } from '@mui/material/styles';
|
||||
import { Button, Tooltip } from "@mui/material";
|
||||
import { paymentMethods, swapDestinations } from "./payment-methods/Methods";
|
||||
import { Button, Tooltip } from '@mui/material';
|
||||
import { paymentMethods, swapDestinations } from './payment-methods/Methods';
|
||||
|
||||
// Icons
|
||||
import DashboardCustomizeIcon from '@mui/icons-material/DashboardCustomize';
|
||||
import AddIcon from '@mui/icons-material/Add';
|
||||
import PaymentIcon from './payment-methods/Icons'
|
||||
import PaymentIcon from './payment-methods/Icons';
|
||||
import CheckIcon from '@mui/icons-material/Check';
|
||||
import CloseIcon from '@mui/icons-material/Close';
|
||||
|
||||
const Root = styled('div')(
|
||||
({ theme }) => `
|
||||
color: ${
|
||||
theme.palette.mode === 'dark' ? 'rgba(255,255,255,0.65)' : 'rgba(0,0,0,.85)'
|
||||
};
|
||||
color: ${theme.palette.mode === 'dark' ? 'rgba(255,255,255,0.65)' : 'rgba(0,0,0,.85)'};
|
||||
font-size: 14px;
|
||||
`,
|
||||
);
|
||||
|
||||
const Label = styled('label')(
|
||||
({ theme , error}) => `
|
||||
color: ${theme.palette.mode === 'dark' ? (error? '#f44336': '#cfcfcf') : (error? '#dd0000':'#717171')};
|
||||
({ theme, error }) => `
|
||||
color: ${
|
||||
theme.palette.mode === 'dark' ? (error ? '#f44336' : '#cfcfcf') : error ? '#dd0000' : '#717171'
|
||||
};
|
||||
align: center;
|
||||
padding: 0 0 4px;
|
||||
line-height: 1.5; f44336
|
||||
@ -34,11 +34,13 @@ const Label = styled('label')(
|
||||
);
|
||||
|
||||
const InputWrapper = styled('div')(
|
||||
({ theme , error}) => `
|
||||
({ theme, error }) => `
|
||||
width: 244px;
|
||||
min-height: 44px;
|
||||
max-height: 124px;
|
||||
border: 1px solid ${theme.palette.mode === 'dark' ? (error? '#f44336': '#434343') : (error? '#dd0000':'#c4c4c4')};
|
||||
border: 1px solid ${
|
||||
theme.palette.mode === 'dark' ? (error ? '#f44336' : '#434343') : error ? '#dd0000' : '#c4c4c4'
|
||||
};
|
||||
background-color: ${theme.palette.mode === 'dark' ? '#141414' : '#fff'};
|
||||
border-radius: 4px;
|
||||
padding: 1px;
|
||||
@ -47,18 +49,32 @@ const InputWrapper = styled('div')(
|
||||
overflow-y:auto;
|
||||
|
||||
&:hover {
|
||||
border-color: ${theme.palette.mode === 'dark' ? (error? '#f44336':'#ffffff') : (error? '#dd0000' :'#2f2f2f')};
|
||||
border-color: ${
|
||||
theme.palette.mode === 'dark'
|
||||
? error
|
||||
? '#f44336'
|
||||
: '#ffffff'
|
||||
: error
|
||||
? '#dd0000'
|
||||
: '#2f2f2f'
|
||||
};
|
||||
}
|
||||
|
||||
&.focused {
|
||||
border: 2px solid ${theme.palette.mode === 'dark' ? (error? '#f44336':'#90caf9') : (error? '#dd0000' :'#1976d2')};
|
||||
border: 2px solid ${
|
||||
theme.palette.mode === 'dark'
|
||||
? error
|
||||
? '#f44336'
|
||||
: '#90caf9'
|
||||
: error
|
||||
? '#dd0000'
|
||||
: '#1976d2'
|
||||
};
|
||||
}
|
||||
|
||||
& input {
|
||||
background-color: ${theme.palette.mode === 'dark' ? '#141414' : '#fff'};
|
||||
color: ${
|
||||
theme.palette.mode === 'dark' ? 'rgba(255,255,255,0.65)' : 'rgba(0,0,0,.85)'
|
||||
};
|
||||
color: ${theme.palette.mode === 'dark' ? 'rgba(255,255,255,0.65)' : 'rgba(0,0,0,.85)'};
|
||||
height: 30px;
|
||||
box-sizing: border-box;
|
||||
padding: 4px 6px;
|
||||
@ -78,10 +94,10 @@ function Tag(props) {
|
||||
const { label, icon, onDelete, ...other } = props;
|
||||
return (
|
||||
<div {...other}>
|
||||
<div style={{position:'relative',left:'-5px',top:'4px'}}>
|
||||
<PaymentIcon width={22} height={22} icon={icon}/>
|
||||
</div>
|
||||
<span style={{position:'relative',left:'2px'}}>{label}</span>
|
||||
<div style={{ position: 'relative', left: '-5px', top: '4px' }}>
|
||||
<PaymentIcon width={22} height={22} icon={icon} />
|
||||
</div>
|
||||
<span style={{ position: 'relative', left: '2px' }}>{label}</span>
|
||||
<CloseIcon onClick={onDelete} />
|
||||
</div>
|
||||
);
|
||||
@ -100,9 +116,7 @@ const StyledTag = styled(Tag)(
|
||||
height: 34px;
|
||||
margin: 2px;
|
||||
line-height: 22px;
|
||||
background-color: ${
|
||||
theme.palette.mode === 'dark' ? 'rgba(255,255,255,0.08)' : '#fafafa'
|
||||
};
|
||||
background-color: ${theme.palette.mode === 'dark' ? 'rgba(255,255,255,0.08)' : '#fafafa'};
|
||||
border: 1px solid ${theme.palette.mode === 'dark' ? '#303030' : '#e8e8e8'};
|
||||
border-radius: 2px;
|
||||
box-sizing: content-box;
|
||||
@ -131,7 +145,7 @@ const StyledTag = styled(Tag)(
|
||||
);
|
||||
|
||||
const ListHeader = styled('span')(
|
||||
({ theme }) => `
|
||||
({ theme }) => `
|
||||
color: ${theme.palette.mode === 'dark' ? '#90caf9' : '#1976d2'};
|
||||
align: left;
|
||||
line-height:10px;
|
||||
@ -202,83 +216,119 @@ export default function AutocompletePayments(props) {
|
||||
getOptionProps,
|
||||
groupedOptions,
|
||||
value,
|
||||
focused="true",
|
||||
focused = 'true',
|
||||
setAnchorEl,
|
||||
} = useAutocomplete({
|
||||
sx: {width:'200px', align:'left'},
|
||||
sx: { width: '200px', align: 'left' },
|
||||
id: 'payment-methods',
|
||||
multiple: true,
|
||||
options: props.optionsType=="fiat" ? paymentMethods : swapDestinations,
|
||||
options: props.optionsType == 'fiat' ? paymentMethods : swapDestinations,
|
||||
getOptionLabel: (option) => option.name,
|
||||
onInputChange: (e) => setVal(e ? (e.target.value ? e.target.value : "") : ""),
|
||||
onInputChange: (e) => setVal(e ? (e.target.value ? e.target.value : '') : ''),
|
||||
onChange: (event, value) => props.onAutocompleteChange(optionsToString(value)),
|
||||
onClose: () => (setVal(() => "")),
|
||||
onClose: () => setVal(() => ''),
|
||||
});
|
||||
|
||||
const [val, setVal] = useState();
|
||||
|
||||
function optionsToString(newValue){
|
||||
function optionsToString(newValue) {
|
||||
var str = '';
|
||||
var arrayLength = newValue.length;
|
||||
for (var i = 0; i < arrayLength; i++) {
|
||||
str += newValue[i].name + ' ';
|
||||
}
|
||||
for (var i = 0; i < arrayLength; i++) {
|
||||
str += newValue[i].name + ' ';
|
||||
}
|
||||
return str.slice(0, -1);
|
||||
}
|
||||
|
||||
function handleAddNew(inputProps){
|
||||
paymentMethods.push({name: inputProps.value, icon:'custom'})
|
||||
var a = value.push({name: inputProps.value, icon:'custom'});
|
||||
setVal(() => "");
|
||||
function handleAddNew(inputProps) {
|
||||
paymentMethods.push({ name: inputProps.value, icon: 'custom' });
|
||||
var a = value.push({ name: inputProps.value, icon: 'custom' });
|
||||
setVal(() => '');
|
||||
|
||||
if(a || a == null){props.onAutocompleteChange(optionsToString(value))}
|
||||
return false
|
||||
};
|
||||
if (a || a == null) {
|
||||
props.onAutocompleteChange(optionsToString(value));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
return (
|
||||
<Root>
|
||||
<div style={{height:'5px'}}></div>
|
||||
<Tooltip placement="top" enterTouchDelay={300} enterDelay={700} enterNextDelay={2000} title={props.tooltipTitle}>
|
||||
<div {...getRootProps()} >
|
||||
<Label {...getInputLabelProps()} error={props.error ? "error" : null}> {props.label}</Label>
|
||||
<InputWrapper ref={setAnchorEl} error={props.error ? "error" : null} className={focused ? 'focused' : ''}>
|
||||
<div style={{ height: '5px' }}></div>
|
||||
<Tooltip
|
||||
placement='top'
|
||||
enterTouchDelay={300}
|
||||
enterDelay={700}
|
||||
enterNextDelay={2000}
|
||||
title={props.tooltipTitle}
|
||||
>
|
||||
<div {...getRootProps()}>
|
||||
<Label {...getInputLabelProps()} error={props.error ? 'error' : null}>
|
||||
{' '}
|
||||
{props.label}
|
||||
</Label>
|
||||
<InputWrapper
|
||||
ref={setAnchorEl}
|
||||
error={props.error ? 'error' : null}
|
||||
className={focused ? 'focused' : ''}
|
||||
>
|
||||
{value.map((option, index) => (
|
||||
<StyledTag label={t(option.name)} icon={option.icon} {...getTagProps({ index })} />
|
||||
))}
|
||||
<input {...getInputProps()} value={val ? val :""}/>
|
||||
<input {...getInputProps()} value={val ? val : ''} />
|
||||
</InputWrapper>
|
||||
</div>
|
||||
</Tooltip>
|
||||
{groupedOptions.length > 0 ? (
|
||||
<Listbox {...getListboxProps()}>
|
||||
<div style={{position:'fixed', minHeight:'20px', marginLeft: 120-props.listHeaderText.length*3, marginTop: '-13px'}}>
|
||||
<ListHeader ><i>{props.listHeaderText+" "} </i> </ListHeader>
|
||||
</div>
|
||||
<div
|
||||
style={{
|
||||
position: 'fixed',
|
||||
minHeight: '20px',
|
||||
marginLeft: 120 - props.listHeaderText.length * 3,
|
||||
marginTop: '-13px',
|
||||
}}
|
||||
>
|
||||
<ListHeader>
|
||||
<i>{props.listHeaderText + ' '} </i>{' '}
|
||||
</ListHeader>
|
||||
</div>
|
||||
{groupedOptions.map((option, index) => (
|
||||
<li key={option.name} {...getOptionProps({ option, index })}>
|
||||
<Button fullWidth={true} color='inherit' size="small" sx={{textTransform: "none"}} style={{justifyContent: "flex-start"}}>
|
||||
<div style={{position:'relative', right: '4px', top:'4px'}}>
|
||||
<AddIcon style={{color : '#1976d2'}} sx={{width:18,height:18}} />
|
||||
</div>
|
||||
{t(option.name)}
|
||||
<Button
|
||||
fullWidth={true}
|
||||
color='inherit'
|
||||
size='small'
|
||||
sx={{ textTransform: 'none' }}
|
||||
style={{ justifyContent: 'flex-start' }}
|
||||
>
|
||||
<div style={{ position: 'relative', right: '4px', top: '4px' }}>
|
||||
<AddIcon style={{ color: '#1976d2' }} sx={{ width: 18, height: 18 }} />
|
||||
</div>
|
||||
{t(option.name)}
|
||||
</Button>
|
||||
<div style={{position:'relative', top: '5px'}}><CheckIcon/></div>
|
||||
<div style={{ position: 'relative', top: '5px' }}>
|
||||
<CheckIcon />
|
||||
</div>
|
||||
</li>
|
||||
))}
|
||||
{val != null?
|
||||
(val.length > 2 ?
|
||||
<Button size="small" fullWidth={true} onClick={() => handleAddNew(getInputProps())}><DashboardCustomizeIcon sx={{width:18,height:18}}/>{props.addNewButtonText}</Button>
|
||||
:null)
|
||||
:null}
|
||||
{val != null ? (
|
||||
val.length > 2 ? (
|
||||
<Button size='small' fullWidth={true} onClick={() => handleAddNew(getInputProps())}>
|
||||
<DashboardCustomizeIcon sx={{ width: 18, height: 18 }} />
|
||||
{props.addNewButtonText}
|
||||
</Button>
|
||||
) : null
|
||||
) : null}
|
||||
</Listbox>
|
||||
) :
|
||||
//Here goes what happens if there is no groupedOptions
|
||||
(getInputProps().value.length > 0 ?
|
||||
) : //Here goes what happens if there is no groupedOptions
|
||||
getInputProps().value.length > 0 ? (
|
||||
<Listbox {...getListboxProps()}>
|
||||
<Button fullWidth={true} onClick={() => handleAddNew(getInputProps())}><DashboardCustomizeIcon sx={{width:20,height:20}}/>{props.addNewButtonText}</Button>
|
||||
<Button fullWidth={true} onClick={() => handleAddNew(getInputProps())}>
|
||||
<DashboardCustomizeIcon sx={{ width: 20, height: 20 }} />
|
||||
{props.addNewButtonText}
|
||||
</Button>
|
||||
</Listbox>
|
||||
:null)
|
||||
}
|
||||
) : null}
|
||||
</Root>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -1,55 +1,77 @@
|
||||
import React, { useEffect, useState } from "react"
|
||||
import { ResponsiveLine, Serie, Datum, PointTooltipProps, PointMouseHandler, Point, CustomLayer } from '@nivo/line'
|
||||
import { Box, CircularProgress, Grid, IconButton, MenuItem, Paper, Select, useTheme } from "@mui/material"
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import {
|
||||
ResponsiveLine,
|
||||
Serie,
|
||||
Datum,
|
||||
PointTooltipProps,
|
||||
PointMouseHandler,
|
||||
Point,
|
||||
CustomLayer,
|
||||
} from '@nivo/line';
|
||||
import {
|
||||
Box,
|
||||
CircularProgress,
|
||||
Grid,
|
||||
IconButton,
|
||||
MenuItem,
|
||||
Paper,
|
||||
Select,
|
||||
useTheme,
|
||||
} from '@mui/material';
|
||||
import { AddCircleOutline, RemoveCircleOutline } from '@mui/icons-material';
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { useHistory } from "react-router-dom"
|
||||
import { Order } from "../../../models/Order.model";
|
||||
import { LimitList } from "../../../models/Limit.model";
|
||||
import RobotAvatar from '../../Robots/RobotAvatar'
|
||||
import { amountToString } from "../../../utils/prettyNumbers";
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { useHistory } from 'react-router-dom';
|
||||
import { Order } from '../../../models/Order.model';
|
||||
import { LimitList } from '../../../models/Limit.model';
|
||||
import RobotAvatar from '../../Robots/RobotAvatar';
|
||||
import { amountToString } from '../../../utils/prettyNumbers';
|
||||
import currencyDict from '../../../../static/assets/currencies.json';
|
||||
import PaymentText from "../../PaymentText";
|
||||
import getNivoScheme from "../NivoScheme"
|
||||
import median from "../../../utils/match";
|
||||
import PaymentText from '../../PaymentText';
|
||||
import getNivoScheme from '../NivoScheme';
|
||||
import median from '../../../utils/match';
|
||||
|
||||
interface DepthChartProps {
|
||||
bookLoading: boolean
|
||||
orders: Order[]
|
||||
lastDayPremium: number | undefined
|
||||
currency: number
|
||||
setAppState: (state: object) => void
|
||||
limits: LimitList
|
||||
compact?: boolean
|
||||
bookLoading: boolean;
|
||||
orders: Order[];
|
||||
lastDayPremium: number | undefined;
|
||||
currency: number;
|
||||
setAppState: (state: object) => void;
|
||||
limits: LimitList;
|
||||
compact?: boolean;
|
||||
}
|
||||
|
||||
const DepthChart: React.FC<DepthChartProps> = ({
|
||||
bookLoading, orders, lastDayPremium, currency, setAppState, limits, compact
|
||||
const DepthChart: React.FC<DepthChartProps> = ({
|
||||
bookLoading,
|
||||
orders,
|
||||
lastDayPremium,
|
||||
currency,
|
||||
setAppState,
|
||||
limits,
|
||||
compact,
|
||||
}) => {
|
||||
const { t } = useTranslation()
|
||||
const history = useHistory()
|
||||
const theme = useTheme()
|
||||
const [enrichedOrders, setEnrichedOrders] = useState<Order[]>([])
|
||||
const [series, setSeries] = useState<Serie[]>([])
|
||||
const [xRange, setXRange] = useState<number>(8)
|
||||
const [xType, setXType] = useState<string>("premium")
|
||||
const [currencyCode, setCurrencyCode] = useState<number>(1)
|
||||
const [center, setCenter] = useState<number>(0)
|
||||
const { t } = useTranslation();
|
||||
const history = useHistory();
|
||||
const theme = useTheme();
|
||||
const [enrichedOrders, setEnrichedOrders] = useState<Order[]>([]);
|
||||
const [series, setSeries] = useState<Serie[]>([]);
|
||||
const [xRange, setXRange] = useState<number>(8);
|
||||
const [xType, setXType] = useState<string>('premium');
|
||||
const [currencyCode, setCurrencyCode] = useState<number>(1);
|
||||
const [center, setCenter] = useState<number>(0);
|
||||
|
||||
useEffect(() => {
|
||||
if (Object.keys(limits).length === 0) {
|
||||
fetch('/api/limits/')
|
||||
.then((response) => response.json())
|
||||
.then((data) => {
|
||||
setAppState({ limits: data })
|
||||
})
|
||||
setAppState({ limits: data });
|
||||
});
|
||||
}
|
||||
}, [])
|
||||
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
setCurrencyCode(currency === 0 ? 1 : currency)
|
||||
}, [currency])
|
||||
setCurrencyCode(currency === 0 ? 1 : currency);
|
||||
}, [currency]);
|
||||
|
||||
useEffect(() => {
|
||||
if (Object.keys(limits).length > 0) {
|
||||
@ -57,172 +79,176 @@ const DepthChart: React.FC<DepthChartProps> = ({
|
||||
// We need to transform all currencies to the same base (ex. USD), we don't have the exchange rate
|
||||
// for EUR -> USD, but we know the rate of both to BTC, so we get advantage of it and apply a
|
||||
// simple rule of three
|
||||
order.base_amount = (order.price * limits[currencyCode].price) / limits[order.currency].price
|
||||
return order
|
||||
})
|
||||
setEnrichedOrders(enriched)
|
||||
order.base_amount =
|
||||
(order.price * limits[currencyCode].price) / limits[order.currency].price;
|
||||
return order;
|
||||
});
|
||||
setEnrichedOrders(enriched);
|
||||
}
|
||||
}, [limits, orders, currencyCode])
|
||||
}, [limits, orders, currencyCode]);
|
||||
|
||||
useEffect(() => {
|
||||
if (enrichedOrders.length > 0) {
|
||||
generateSeries()
|
||||
if (enrichedOrders.length > 0) {
|
||||
generateSeries();
|
||||
}
|
||||
}, [enrichedOrders, xRange])
|
||||
}, [enrichedOrders, xRange]);
|
||||
|
||||
useEffect(() => {
|
||||
if (xType === 'base_amount') {
|
||||
const prices: number[] = enrichedOrders.map((order) => order?.base_amount || 0)
|
||||
setCenter(~~median(prices))
|
||||
setXRange(1500)
|
||||
if (xType === 'base_amount') {
|
||||
const prices: number[] = enrichedOrders.map((order) => order?.base_amount || 0);
|
||||
setCenter(~~median(prices));
|
||||
setXRange(1500);
|
||||
} else if (lastDayPremium) {
|
||||
setCenter(lastDayPremium)
|
||||
setXRange(8)
|
||||
setCenter(lastDayPremium);
|
||||
setXRange(8);
|
||||
}
|
||||
}, [enrichedOrders, xType, lastDayPremium, currencyCode])
|
||||
}, [enrichedOrders, xType, lastDayPremium, currencyCode]);
|
||||
|
||||
const calculateBtc = (order: Order): number => {
|
||||
const amount = parseInt(order.amount) || order.max_amount
|
||||
return amount / order.price
|
||||
}
|
||||
const amount = parseInt(order.amount) || order.max_amount;
|
||||
return amount / order.price;
|
||||
};
|
||||
|
||||
const generateSeries:() => void = () => {
|
||||
let sortedOrders: Order[] = xType === 'base_amount' ?
|
||||
enrichedOrders.sort((order1, order2) => (order1?.base_amount || 0) - (order2?.base_amount || 0) )
|
||||
: enrichedOrders.sort((order1, order2) => order1.premium - order2.premium )
|
||||
const generateSeries: () => void = () => {
|
||||
let sortedOrders: Order[] =
|
||||
xType === 'base_amount'
|
||||
? enrichedOrders.sort(
|
||||
(order1, order2) => (order1?.base_amount || 0) - (order2?.base_amount || 0),
|
||||
)
|
||||
: enrichedOrders.sort((order1, order2) => order1.premium - order2.premium);
|
||||
|
||||
const sortedBuyOrders: Order[] = sortedOrders.filter((order) => order.type == 0).reverse()
|
||||
const sortedSellOrders: Order[] = sortedOrders.filter((order) => order.type == 1)
|
||||
const sortedBuyOrders: Order[] = sortedOrders.filter((order) => order.type == 0).reverse();
|
||||
const sortedSellOrders: Order[] = sortedOrders.filter((order) => order.type == 1);
|
||||
|
||||
const buySerie: Datum[] = generateSerie(sortedBuyOrders)
|
||||
const sellSerie: Datum[] = generateSerie(sortedSellOrders)
|
||||
const buySerie: Datum[] = generateSerie(sortedBuyOrders);
|
||||
const sellSerie: Datum[] = generateSerie(sortedSellOrders);
|
||||
|
||||
const maxX: number = center + xRange
|
||||
const minX: number = center - xRange
|
||||
const maxX: number = center + xRange;
|
||||
const minX: number = center - xRange;
|
||||
|
||||
setSeries([
|
||||
{
|
||||
id: "buy",
|
||||
data: closeSerie(buySerie, maxX, minX)
|
||||
},
|
||||
id: 'buy',
|
||||
data: closeSerie(buySerie, maxX, minX),
|
||||
},
|
||||
{
|
||||
id: "sell",
|
||||
data: closeSerie(sellSerie, minX, maxX)
|
||||
}
|
||||
])
|
||||
}
|
||||
id: 'sell',
|
||||
data: closeSerie(sellSerie, minX, maxX),
|
||||
},
|
||||
]);
|
||||
};
|
||||
|
||||
const generateSerie = (orders: Order[]): Datum[] => {
|
||||
if (!center) { return [] }
|
||||
if (!center) {
|
||||
return [];
|
||||
}
|
||||
|
||||
let sumOrders: number = 0
|
||||
let serie: Datum[] = []
|
||||
let sumOrders: number = 0;
|
||||
let serie: Datum[] = [];
|
||||
orders.forEach((order) => {
|
||||
const lastSumOrders = sumOrders
|
||||
sumOrders += calculateBtc(order)
|
||||
const lastSumOrders = sumOrders;
|
||||
sumOrders += calculateBtc(order);
|
||||
const datum: Datum[] = [
|
||||
{ // Vertical Line
|
||||
x: xType === 'base_amount' ? order.base_amount : order.premium,
|
||||
y: lastSumOrders
|
||||
{
|
||||
// Vertical Line
|
||||
x: xType === 'base_amount' ? order.base_amount : order.premium,
|
||||
y: lastSumOrders,
|
||||
},
|
||||
{ // Order Point
|
||||
x: xType === 'base_amount' ? order.base_amount : order.premium,
|
||||
{
|
||||
// Order Point
|
||||
x: xType === 'base_amount' ? order.base_amount : order.premium,
|
||||
y: sumOrders,
|
||||
order: order
|
||||
}
|
||||
]
|
||||
order: order,
|
||||
},
|
||||
];
|
||||
|
||||
serie = [...serie, ...datum]
|
||||
})
|
||||
const inlineSerie = serie.filter((datum: Datum) => {
|
||||
return (Number(datum.x) > center - xRange) &&
|
||||
(Number(datum.x) < center + xRange)
|
||||
})
|
||||
serie = [...serie, ...datum];
|
||||
});
|
||||
const inlineSerie = serie.filter((datum: Datum) => {
|
||||
return Number(datum.x) > center - xRange && Number(datum.x) < center + xRange;
|
||||
});
|
||||
|
||||
return inlineSerie
|
||||
}
|
||||
return inlineSerie;
|
||||
};
|
||||
|
||||
const closeSerie = (serie: Datum[], limitBottom: number, limitTop: number): Datum[] =>{
|
||||
if (serie.length == 0) { return [] }
|
||||
const closeSerie = (serie: Datum[], limitBottom: number, limitTop: number): Datum[] => {
|
||||
if (serie.length == 0) {
|
||||
return [];
|
||||
}
|
||||
|
||||
// If the bottom is not 0, exdens the horizontal bottom line
|
||||
if (serie[0].y !== 0) {
|
||||
const startingPoint: Datum = {
|
||||
x: limitBottom,
|
||||
y: serie[0].y
|
||||
}
|
||||
serie.unshift(startingPoint)
|
||||
y: serie[0].y,
|
||||
};
|
||||
serie.unshift(startingPoint);
|
||||
}
|
||||
|
||||
// exdens the horizontal top line
|
||||
const endingPoint: Datum = {
|
||||
x: limitTop,
|
||||
y: serie[serie.length - 1].y
|
||||
}
|
||||
y: serie[serie.length - 1].y,
|
||||
};
|
||||
|
||||
return [...serie, endingPoint]
|
||||
}
|
||||
return [...serie, endingPoint];
|
||||
};
|
||||
|
||||
const centerLine: CustomLayer = (props) => (
|
||||
<path
|
||||
key="center-line"
|
||||
key='center-line'
|
||||
d={props.lineGenerator([
|
||||
{
|
||||
y: 0,
|
||||
x: props.xScale(center)
|
||||
x: props.xScale(center),
|
||||
},
|
||||
{
|
||||
y: props.innerHeight,
|
||||
x: props.xScale(center)
|
||||
x: props.xScale(center),
|
||||
},
|
||||
])}
|
||||
fill="none"
|
||||
fill='none'
|
||||
stroke={getNivoScheme(theme).markers?.lineColor}
|
||||
strokeWidth={getNivoScheme(theme).markers?.lineStrokeWidth}
|
||||
/>
|
||||
)
|
||||
);
|
||||
|
||||
const generateTooltip: React.FunctionComponent<PointTooltipProps> = (pointTooltip: PointTooltipProps) => {
|
||||
const order: Order = pointTooltip.point.data.order
|
||||
const generateTooltip: React.FunctionComponent<PointTooltipProps> = (
|
||||
pointTooltip: PointTooltipProps,
|
||||
) => {
|
||||
const order: Order = pointTooltip.point.data.order;
|
||||
return order ? (
|
||||
<Paper elevation={12} style={{ padding: 10, width: 250 }}>
|
||||
<Grid container justifyContent="space-between">
|
||||
<Grid container justifyContent='space-between'>
|
||||
<Grid item xs={3}>
|
||||
<Grid
|
||||
container
|
||||
justifyContent="center"
|
||||
alignItems="center"
|
||||
>
|
||||
<Grid container justifyContent='center' alignItems='center'>
|
||||
<RobotAvatar order={order} />
|
||||
</Grid>
|
||||
</Grid>
|
||||
<Grid item xs={8}>
|
||||
<Grid
|
||||
container
|
||||
direction="column"
|
||||
justifyContent="center"
|
||||
alignItems="flex-start"
|
||||
>
|
||||
<Box>
|
||||
{order.maker_nick}
|
||||
</Box>
|
||||
<Grid container direction='column' justifyContent='center' alignItems='flex-start'>
|
||||
<Box>{order.maker_nick}</Box>
|
||||
<Box>
|
||||
<Grid
|
||||
container
|
||||
direction="column"
|
||||
justifyContent="flex-start"
|
||||
alignItems="flex-start"
|
||||
direction='column'
|
||||
justifyContent='flex-start'
|
||||
alignItems='flex-start'
|
||||
>
|
||||
<Grid item xs={12}>
|
||||
{amountToString(order.amount, order.has_range, order.min_amount, order.max_amount)}
|
||||
{' '}
|
||||
{amountToString(
|
||||
order.amount,
|
||||
order.has_range,
|
||||
order.min_amount,
|
||||
order.max_amount,
|
||||
)}{' '}
|
||||
{currencyDict[order.currency]}
|
||||
</Grid>
|
||||
<Grid item xs={12}>
|
||||
<PaymentText
|
||||
othersText={t("Others")}
|
||||
verbose={true}
|
||||
size={20}
|
||||
<PaymentText
|
||||
othersText={t('Others')}
|
||||
verbose={true}
|
||||
size={20}
|
||||
text={order.payment_method}
|
||||
/>
|
||||
</Grid>
|
||||
@ -232,69 +258,67 @@ const DepthChart: React.FC<DepthChartProps> = ({
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Paper>
|
||||
) : <></>
|
||||
}
|
||||
) : (
|
||||
<></>
|
||||
);
|
||||
};
|
||||
|
||||
const formatAxisX = (value: number): string => {
|
||||
if (xType === 'base_amount') {
|
||||
return value.toString()
|
||||
return value.toString();
|
||||
}
|
||||
return `${value}%`
|
||||
}
|
||||
const formatAxisY = (value: number): string => `${value}BTC`
|
||||
return `${value}%`;
|
||||
};
|
||||
const formatAxisY = (value: number): string => `${value}BTC`;
|
||||
|
||||
const rangeSteps = xType === 'base_amount' ? 200 : 0.5
|
||||
const rangeSteps = xType === 'base_amount' ? 200 : 0.5;
|
||||
|
||||
const handleOnClick: PointMouseHandler = (point: Point) => {
|
||||
history.push('/order/' + point.data?.order?.id);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
return bookLoading || !center || enrichedOrders.length < 1 ? (
|
||||
<div style={{display: "flex", justifyContent: "center", paddingTop: 200, height: 420 }}>
|
||||
<div style={{ display: 'flex', justifyContent: 'center', paddingTop: 200, height: 420 }}>
|
||||
<CircularProgress />
|
||||
</div>
|
||||
) : (
|
||||
<Grid container style={{ paddingTop: 15 }}>
|
||||
<Grid
|
||||
container
|
||||
direction="row"
|
||||
justifyContent="space-around"
|
||||
alignItems="flex-start"
|
||||
style={{ position: "absolute" }}
|
||||
<Grid
|
||||
container
|
||||
direction='row'
|
||||
justifyContent='space-around'
|
||||
alignItems='flex-start'
|
||||
style={{ position: 'absolute' }}
|
||||
>
|
||||
<Grid container justifyContent="flex-start" alignItems="flex-start" style={{ paddingLeft: 20 }}>
|
||||
<Select
|
||||
variant="standard"
|
||||
value={xType}
|
||||
onChange={(e) => setXType(e.target.value)}
|
||||
>
|
||||
<MenuItem value={"premium"}>
|
||||
<div style={{display:'flex',alignItems:'center', flexWrap:'wrap'}}>
|
||||
{t("Premium")}
|
||||
<Grid
|
||||
container
|
||||
justifyContent='flex-start'
|
||||
alignItems='flex-start'
|
||||
style={{ paddingLeft: 20 }}
|
||||
>
|
||||
<Select variant='standard' value={xType} onChange={(e) => setXType(e.target.value)}>
|
||||
<MenuItem value={'premium'}>
|
||||
<div style={{ display: 'flex', alignItems: 'center', flexWrap: 'wrap' }}>
|
||||
{t('Premium')}
|
||||
</div>
|
||||
</MenuItem>
|
||||
<MenuItem value={"base_amount"}>
|
||||
<div style={{display:'flex',alignItems:'center', flexWrap:'wrap'}}>
|
||||
{t("Price")}
|
||||
<MenuItem value={'base_amount'}>
|
||||
<div style={{ display: 'flex', alignItems: 'center', flexWrap: 'wrap' }}>
|
||||
{t('Price')}
|
||||
</div>
|
||||
</MenuItem>
|
||||
</Select>
|
||||
</Grid>
|
||||
</Grid>
|
||||
<Grid
|
||||
container
|
||||
direction="row"
|
||||
justifyContent="center"
|
||||
alignItems="center"
|
||||
>
|
||||
<Grid container justifyContent="center" alignItems="center">
|
||||
<Grid container direction='row' justifyContent='center' alignItems='center'>
|
||||
<Grid container justifyContent='center' alignItems='center'>
|
||||
<Grid item>
|
||||
<IconButton onClick={() => setXRange(xRange + rangeSteps)}>
|
||||
<RemoveCircleOutline />
|
||||
</IconButton>
|
||||
</Grid>
|
||||
<Grid item>
|
||||
<Box justifyContent="center">
|
||||
<Box justifyContent='center'>
|
||||
{xType === 'base_amount' ? `${center} ${currencyDict[currencyCode]}` : `${center}%`}
|
||||
</Box>
|
||||
</Grid>
|
||||
@ -306,42 +330,42 @@ const DepthChart: React.FC<DepthChartProps> = ({
|
||||
</Grid>
|
||||
</Grid>
|
||||
<Grid container style={{ height: 357, padding: 15 }}>
|
||||
<ResponsiveLine
|
||||
data={series}
|
||||
<ResponsiveLine
|
||||
data={series}
|
||||
enableArea={true}
|
||||
useMesh={true}
|
||||
animate={false}
|
||||
crosshairType="cross"
|
||||
crosshairType='cross'
|
||||
tooltip={generateTooltip}
|
||||
onClick={handleOnClick}
|
||||
axisRight={{
|
||||
tickSize: 5,
|
||||
format: formatAxisY
|
||||
format: formatAxisY,
|
||||
}}
|
||||
axisLeft={{
|
||||
tickSize: 5,
|
||||
format: formatAxisY
|
||||
format: formatAxisY,
|
||||
}}
|
||||
axisBottom={{
|
||||
tickSize: 5,
|
||||
tickRotation: xType === 'base_amount' && compact ? 45 : 0,
|
||||
format: formatAxisX
|
||||
format: formatAxisX,
|
||||
}}
|
||||
margin={{ left: 65, right: 60, bottom: compact ? 36 : 25, top: 10 }}
|
||||
xFormat={(value) => Number(value).toFixed(0)}
|
||||
lineWidth={3}
|
||||
theme={getNivoScheme(theme)}
|
||||
colors={[theme.palette.secondary.main,theme.palette.primary.main]}
|
||||
colors={[theme.palette.secondary.main, theme.palette.primary.main]}
|
||||
xScale={{
|
||||
type: 'linear',
|
||||
min: center - xRange,
|
||||
max: center + xRange
|
||||
max: center + xRange,
|
||||
}}
|
||||
layers={['axes', 'areas', 'crosshair', 'lines', centerLine, 'slices', 'mesh']}
|
||||
/>
|
||||
</Grid>
|
||||
</Grid>
|
||||
)
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
export default DepthChart
|
||||
export default DepthChart;
|
||||
|
@ -1,61 +1,61 @@
|
||||
import { light } from "@mui/material/styles/createPalette"
|
||||
import { palette } from "@mui/system"
|
||||
import { Theme as NivoTheme } from "@nivo/core"
|
||||
import { Theme as MuiTheme } from './createTheme'
|
||||
import { light } from '@mui/material/styles/createPalette';
|
||||
import { palette } from '@mui/system';
|
||||
import { Theme as NivoTheme } from '@nivo/core';
|
||||
import { Theme as MuiTheme } from './createTheme';
|
||||
|
||||
export const getNivoScheme: (theme: MuiTheme) => NivoTheme = (theme) => {
|
||||
const lightMode = {
|
||||
markers: {
|
||||
lineColor: "rgb(0, 0, 0)",
|
||||
lineStrokeWidth: 1
|
||||
lineColor: 'rgb(0, 0, 0)',
|
||||
lineStrokeWidth: 1,
|
||||
},
|
||||
axis: {
|
||||
ticks: {
|
||||
line: {
|
||||
strokeWidth: "1",
|
||||
stroke: "rgb(0, 0, 0)"
|
||||
}
|
||||
strokeWidth: '1',
|
||||
stroke: 'rgb(0, 0, 0)',
|
||||
},
|
||||
},
|
||||
domain: {
|
||||
line: {
|
||||
strokeWidth: "1",
|
||||
stroke: "rgb(0, 0, 0)"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
strokeWidth: '1',
|
||||
stroke: 'rgb(0, 0, 0)',
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
const darkMode = {
|
||||
markers: {
|
||||
lineColor: "rgb(255, 255, 255)",
|
||||
lineStrokeWidth: 1
|
||||
lineColor: 'rgb(255, 255, 255)',
|
||||
lineStrokeWidth: 1,
|
||||
},
|
||||
axis: {
|
||||
ticks: {
|
||||
text: {
|
||||
fill: "rgb(255, 255, 255)"
|
||||
fill: 'rgb(255, 255, 255)',
|
||||
},
|
||||
line: {
|
||||
strokeWidth: "1",
|
||||
stroke: "rgb(255, 255, 255)"
|
||||
}
|
||||
strokeWidth: '1',
|
||||
stroke: 'rgb(255, 255, 255)',
|
||||
},
|
||||
},
|
||||
domain: {
|
||||
line: {
|
||||
strokeWidth: "1",
|
||||
stroke: "rgb(255, 255, 255)"
|
||||
}
|
||||
}
|
||||
strokeWidth: '1',
|
||||
stroke: 'rgb(255, 255, 255)',
|
||||
},
|
||||
},
|
||||
},
|
||||
crosshair: {
|
||||
line: {
|
||||
strokeWidth: 1,
|
||||
stroke: "rgb(255, 255, 255)"
|
||||
}
|
||||
}
|
||||
}
|
||||
stroke: 'rgb(255, 255, 255)',
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
return theme.palette.mode === 'dark' ? darkMode : lightMode
|
||||
}
|
||||
return theme.palette.mode === 'dark' ? darkMode : lightMode;
|
||||
};
|
||||
|
||||
export default getNivoScheme
|
||||
export default getNivoScheme;
|
||||
|
@ -1,51 +1,52 @@
|
||||
import React from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import React from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import {
|
||||
Dialog,
|
||||
DialogTitle,
|
||||
Tooltip,
|
||||
Tooltip,
|
||||
IconButton,
|
||||
TextField,
|
||||
DialogActions,
|
||||
DialogActions,
|
||||
DialogContent,
|
||||
DialogContentText,
|
||||
Button,
|
||||
Button,
|
||||
Grid,
|
||||
Link,
|
||||
} from "@mui/material"
|
||||
} from '@mui/material';
|
||||
|
||||
import { saveAsJson } from "../../utils/saveFile";
|
||||
import { copyToClipboard } from "../../utils/clipboard";
|
||||
import { saveAsJson } from '../../utils/saveFile';
|
||||
import { copyToClipboard } from '../../utils/clipboard';
|
||||
|
||||
// Icons
|
||||
import KeyIcon from '@mui/icons-material/Key';
|
||||
import ContentCopy from "@mui/icons-material/ContentCopy";
|
||||
import ContentCopy from '@mui/icons-material/ContentCopy';
|
||||
import ForumIcon from '@mui/icons-material/Forum';
|
||||
import { ExportIcon, NewTabIcon } from '../Icons';
|
||||
|
||||
function CredentialTextfield(props){
|
||||
return(
|
||||
<Grid item align="center" xs={12}>
|
||||
<Tooltip placement="top" enterTouchDelay={200} enterDelay={200} title={props.tooltipTitle}>
|
||||
function CredentialTextfield(props) {
|
||||
return (
|
||||
<Grid item align='center' xs={12}>
|
||||
<Tooltip placement='top' enterTouchDelay={200} enterDelay={200} title={props.tooltipTitle}>
|
||||
<TextField
|
||||
sx={{width:"100%", maxWidth:"550px"}}
|
||||
sx={{ width: '100%', maxWidth: '550px' }}
|
||||
disabled
|
||||
label={<b>{props.label}</b>}
|
||||
value={props.value}
|
||||
variant='filled'
|
||||
size='small'
|
||||
InputProps={{
|
||||
endAdornment:
|
||||
endAdornment: (
|
||||
<Tooltip disableHoverListener enterTouchDelay={0} title={props.copiedTitle}>
|
||||
<IconButton onClick={()=> copyToClipboard(props.value)}>
|
||||
<ContentCopy/>
|
||||
<IconButton onClick={() => copyToClipboard(props.value)}>
|
||||
<ContentCopy />
|
||||
</IconButton>
|
||||
</Tooltip>,
|
||||
}}
|
||||
/>
|
||||
</Tooltip>
|
||||
),
|
||||
}}
|
||||
/>
|
||||
</Tooltip>
|
||||
</Grid>
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
type Props = {
|
||||
@ -53,15 +54,15 @@ type Props = {
|
||||
onClose: () => void;
|
||||
orderId: number;
|
||||
messages: array;
|
||||
own_pub_key: string;
|
||||
own_pub_key: string;
|
||||
own_enc_priv_key: string;
|
||||
peer_pub_key: string;
|
||||
passphrase: string;
|
||||
onClickBack: () => void;
|
||||
}
|
||||
};
|
||||
|
||||
const AuditPGPDialog = ({
|
||||
open,
|
||||
open,
|
||||
onClose,
|
||||
orderId,
|
||||
messages,
|
||||
@ -74,103 +75,129 @@ const AuditPGPDialog = ({
|
||||
const { t } = useTranslation();
|
||||
|
||||
return (
|
||||
<Dialog
|
||||
open={open}
|
||||
onClose={onClose}
|
||||
>
|
||||
<DialogTitle >
|
||||
{t("Don't trust, verify")}
|
||||
</DialogTitle>
|
||||
<Dialog open={open} onClose={onClose}>
|
||||
<DialogTitle>{t("Don't trust, verify")}</DialogTitle>
|
||||
|
||||
<DialogContent>
|
||||
<DialogContentText>
|
||||
{t("Your communication is end-to-end encrypted with OpenPGP. You can verify the privacy of this chat using any tool based on the OpenPGP standard.")}
|
||||
{t(
|
||||
'Your communication is end-to-end encrypted with OpenPGP. You can verify the privacy of this chat using any tool based on the OpenPGP standard.',
|
||||
)}
|
||||
</DialogContentText>
|
||||
<Grid container spacing={1} align="center">
|
||||
|
||||
<Grid item align="center" xs={12}>
|
||||
<Button component={Link} target="_blank" href="https://learn.robosats.com/docs/pgp-encryption">{t("Learn how to verify")} <NewTabIcon sx={{width:16,height:16}}/></Button>
|
||||
<Grid container spacing={1} align='center'>
|
||||
<Grid item align='center' xs={12}>
|
||||
<Button
|
||||
component={Link}
|
||||
target='_blank'
|
||||
href='https://learn.robosats.com/docs/pgp-encryption'
|
||||
>
|
||||
{t('Learn how to verify')} <NewTabIcon sx={{ width: 16, height: 16 }} />
|
||||
</Button>
|
||||
</Grid>
|
||||
|
||||
<CredentialTextfield
|
||||
tooltipTitle={t("Your PGP public key. Your peer uses it to encrypt messages only you can read.")}
|
||||
label={t("Your public key")}
|
||||
<CredentialTextfield
|
||||
tooltipTitle={t(
|
||||
'Your PGP public key. Your peer uses it to encrypt messages only you can read.',
|
||||
)}
|
||||
label={t('Your public key')}
|
||||
value={own_pub_key}
|
||||
copiedTitle={t("Copied!")}/>
|
||||
copiedTitle={t('Copied!')}
|
||||
/>
|
||||
|
||||
<CredentialTextfield
|
||||
tooltipTitle={t("Your peer PGP public key. You use it to encrypt messages only he can read and to verify your peer signed the incoming messages.")}
|
||||
label={t("Peer public key")}
|
||||
<CredentialTextfield
|
||||
tooltipTitle={t(
|
||||
'Your peer PGP public key. You use it to encrypt messages only he can read and to verify your peer signed the incoming messages.',
|
||||
)}
|
||||
label={t('Peer public key')}
|
||||
value={peer_pub_key}
|
||||
copiedTitle={t("Copied!")}/>
|
||||
copiedTitle={t('Copied!')}
|
||||
/>
|
||||
|
||||
<CredentialTextfield
|
||||
tooltipTitle={t("Your encrypted private key. You use it to decrypt the messages that your peer encrypted for you. You also use it to sign the messages you send.")}
|
||||
label={t("Your encrypted private key")}
|
||||
<CredentialTextfield
|
||||
tooltipTitle={t(
|
||||
'Your encrypted private key. You use it to decrypt the messages that your peer encrypted for you. You also use it to sign the messages you send.',
|
||||
)}
|
||||
label={t('Your encrypted private key')}
|
||||
value={own_enc_priv_key}
|
||||
copiedTitle={t("Copied!")}/>
|
||||
copiedTitle={t('Copied!')}
|
||||
/>
|
||||
|
||||
<CredentialTextfield
|
||||
tooltipTitle={t("The passphrase to decrypt your private key. Only you know it! Do not share. It is also your robot token.")}
|
||||
label={t("Your private key passphrase (keep secure!)")}
|
||||
<CredentialTextfield
|
||||
tooltipTitle={t(
|
||||
'The passphrase to decrypt your private key. Only you know it! Do not share. It is also your robot token.',
|
||||
)}
|
||||
label={t('Your private key passphrase (keep secure!)')}
|
||||
value={passphrase}
|
||||
copiedTitle={t("Copied!")}/>
|
||||
|
||||
<br/>
|
||||
<Grid item xs={6}>
|
||||
<Tooltip placement="top" enterTouchDelay={0} enterDelay={1000} enterNextDelay={2000} title={t("Save credentials as a JSON file")}>
|
||||
<Button
|
||||
size="small"
|
||||
color="primary"
|
||||
variant="contained"
|
||||
onClick={()=>saveAsJson(
|
||||
'keys_'+orderId+'.json',
|
||||
{"own_public_key": own_pub_key,
|
||||
"peer_public_key":peer_pub_key,
|
||||
"encrypted_private_key":own_enc_priv_key,
|
||||
"passphrase":passphrase
|
||||
})}>
|
||||
<div style={{width:26,height:18}}>
|
||||
<ExportIcon sx={{width:18,height:18}}/>
|
||||
</div>
|
||||
{t("Keys")}
|
||||
<div style={{width:26,height:20}}>
|
||||
<KeyIcon sx={{width:20,height:20}}/>
|
||||
</div>
|
||||
</Button>
|
||||
</Tooltip>
|
||||
</Grid>
|
||||
|
||||
<Grid item xs={6}>
|
||||
<Tooltip placement="top" enterTouchDelay={0} enterDelay={1000} enterNextDelay={2000} title={t("Save messages as a JSON file")}>
|
||||
<Button
|
||||
size="small"
|
||||
color="primary"
|
||||
variant="contained"
|
||||
onClick={()=>saveAsJson(
|
||||
'messages_'+orderId+'.json',
|
||||
messages)}>
|
||||
<div style={{width:28,height:20}}>
|
||||
<ExportIcon sx={{width:18,height:18}}/>
|
||||
</div>
|
||||
{t("Messages")}
|
||||
<div style={{width:26,height:20}}>
|
||||
<ForumIcon sx={{width:20,height:20}}/>
|
||||
</div>
|
||||
</Button>
|
||||
</Tooltip>
|
||||
copiedTitle={t('Copied!')}
|
||||
/>
|
||||
|
||||
<br />
|
||||
<Grid item xs={6}>
|
||||
<Tooltip
|
||||
placement='top'
|
||||
enterTouchDelay={0}
|
||||
enterDelay={1000}
|
||||
enterNextDelay={2000}
|
||||
title={t('Save credentials as a JSON file')}
|
||||
>
|
||||
<Button
|
||||
size='small'
|
||||
color='primary'
|
||||
variant='contained'
|
||||
onClick={() =>
|
||||
saveAsJson('keys_' + orderId + '.json', {
|
||||
own_public_key: own_pub_key,
|
||||
peer_public_key: peer_pub_key,
|
||||
encrypted_private_key: own_enc_priv_key,
|
||||
passphrase: passphrase,
|
||||
})
|
||||
}
|
||||
>
|
||||
<div style={{ width: 26, height: 18 }}>
|
||||
<ExportIcon sx={{ width: 18, height: 18 }} />
|
||||
</div>
|
||||
{t('Keys')}
|
||||
<div style={{ width: 26, height: 20 }}>
|
||||
<KeyIcon sx={{ width: 20, height: 20 }} />
|
||||
</div>
|
||||
</Button>
|
||||
</Tooltip>
|
||||
</Grid>
|
||||
|
||||
<Grid item xs={6}>
|
||||
<Tooltip
|
||||
placement='top'
|
||||
enterTouchDelay={0}
|
||||
enterDelay={1000}
|
||||
enterNextDelay={2000}
|
||||
title={t('Save messages as a JSON file')}
|
||||
>
|
||||
<Button
|
||||
size='small'
|
||||
color='primary'
|
||||
variant='contained'
|
||||
onClick={() => saveAsJson('messages_' + orderId + '.json', messages)}
|
||||
>
|
||||
<div style={{ width: 28, height: 20 }}>
|
||||
<ExportIcon sx={{ width: 18, height: 18 }} />
|
||||
</div>
|
||||
{t('Messages')}
|
||||
<div style={{ width: 26, height: 20 }}>
|
||||
<ForumIcon sx={{ width: 20, height: 20 }} />
|
||||
</div>
|
||||
</Button>
|
||||
</Tooltip>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</DialogContent>
|
||||
|
||||
<DialogActions>
|
||||
<Button onClick={onClickBack} autoFocus>{t("Go back")}</Button>
|
||||
<Button onClick={onClickBack} autoFocus>
|
||||
{t('Go back')}
|
||||
</Button>
|
||||
</DialogActions>
|
||||
|
||||
</Dialog>
|
||||
)
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
export default AuditPGPDialog;
|
||||
|
@ -1,5 +1,5 @@
|
||||
import React from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import React from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import {
|
||||
Dialog,
|
||||
DialogContent,
|
||||
@ -12,22 +12,19 @@ import {
|
||||
ListItemButton,
|
||||
Tooltip,
|
||||
Typography,
|
||||
} from "@mui/material";
|
||||
} from '@mui/material';
|
||||
import SendIcon from '@mui/icons-material/Send';
|
||||
import GitHubIcon from '@mui/icons-material/GitHub';
|
||||
import TwitterIcon from '@mui/icons-material/Twitter';
|
||||
import RedditIcon from '@mui/icons-material/Reddit';
|
||||
import Flags from 'country-flag-icons/react/3x2'
|
||||
import Flags from 'country-flag-icons/react/3x2';
|
||||
|
||||
type Props = {
|
||||
isOpen: boolean;
|
||||
handleClickCloseCommunity: () => void;
|
||||
}
|
||||
};
|
||||
|
||||
const CommunityDialog = ({
|
||||
isOpen,
|
||||
handleClickCloseCommunity,
|
||||
}: Props): JSX.Element => {
|
||||
const CommunityDialog = ({ isOpen, handleClickCloseCommunity }: Props): JSX.Element => {
|
||||
const { t } = useTranslation();
|
||||
|
||||
const flagProps = {
|
||||
@ -35,7 +32,7 @@ const CommunityDialog = ({
|
||||
height: 30,
|
||||
opacity: 0.85,
|
||||
style: {
|
||||
filter: "drop-shadow(2px 2px 2px #444444)",
|
||||
filter: 'drop-shadow(2px 2px 2px #444444)',
|
||||
},
|
||||
};
|
||||
|
||||
@ -43,136 +40,139 @@ const CommunityDialog = ({
|
||||
<Dialog
|
||||
open={isOpen}
|
||||
onClose={handleClickCloseCommunity}
|
||||
aria-labelledby="community-dialog-title"
|
||||
aria-describedby="community-description"
|
||||
aria-labelledby='community-dialog-title'
|
||||
aria-describedby='community-description'
|
||||
>
|
||||
<DialogContent>
|
||||
<Typography component="h5" variant="h5">
|
||||
{t("Community")}
|
||||
<Typography component='h5' variant='h5'>
|
||||
{t('Community')}
|
||||
</Typography>
|
||||
|
||||
<Typography component="div" variant="body2">
|
||||
<p>{t("Support is only offered via public channels. Join our Telegram community if you have questions or want to hang out with other cool robots. Please, use our Github Issues if you find a bug or want to see new features!")}</p>
|
||||
<Typography component='div' variant='body2'>
|
||||
<p>
|
||||
{t(
|
||||
'Support is only offered via public channels. Join our Telegram community if you have questions or want to hang out with other cool robots. Please, use our Github Issues if you find a bug or want to see new features!',
|
||||
)}
|
||||
</p>
|
||||
</Typography>
|
||||
|
||||
<List dense>
|
||||
<Divider/>
|
||||
<Divider />
|
||||
|
||||
<ListItemButton
|
||||
component="a"
|
||||
target="_blank"
|
||||
href="https://twitter.com/robosats"
|
||||
rel="noreferrer"
|
||||
component='a'
|
||||
target='_blank'
|
||||
href='https://twitter.com/robosats'
|
||||
rel='noreferrer'
|
||||
>
|
||||
<ListItemIcon>
|
||||
<TwitterIcon color="primary" sx={{height:32,width:32}}/>
|
||||
<TwitterIcon color='primary' sx={{ height: 32, width: 32 }} />
|
||||
</ListItemIcon>
|
||||
|
||||
<ListItemText
|
||||
primary={t("Follow RoboSats in Twitter")}
|
||||
secondary={t("Twitter Official Account")}
|
||||
primary={t('Follow RoboSats in Twitter')}
|
||||
secondary={t('Twitter Official Account')}
|
||||
/>
|
||||
</ListItemButton>
|
||||
|
||||
<Divider/>
|
||||
<Divider />
|
||||
|
||||
<ListItemButton
|
||||
component="a"
|
||||
target="_blank"
|
||||
href="https://reddit.com/r/robosats"
|
||||
rel="noreferrer"
|
||||
component='a'
|
||||
target='_blank'
|
||||
href='https://reddit.com/r/robosats'
|
||||
rel='noreferrer'
|
||||
>
|
||||
<ListItemIcon>
|
||||
<RedditIcon color="primary" sx={{height:35,width:35}}/>
|
||||
<RedditIcon color='primary' sx={{ height: 35, width: 35 }} />
|
||||
</ListItemIcon>
|
||||
|
||||
<ListItemText
|
||||
primary={t("Join RoboSats' Subreddit")}
|
||||
secondary={t("RoboSats in Reddit")}
|
||||
secondary={t('RoboSats in Reddit')}
|
||||
/>
|
||||
</ListItemButton>
|
||||
|
||||
<Divider/>
|
||||
<Divider />
|
||||
|
||||
<ListItem>
|
||||
<ListItemIcon>
|
||||
<SendIcon color="primary" sx={{height:32,width:32}}/>
|
||||
<SendIcon color='primary' sx={{ height: 32, width: 32 }} />
|
||||
</ListItemIcon>
|
||||
|
||||
<ListItemText secondary={t("RoboSats Telegram Communities")}>
|
||||
<Tooltip title={t("Join RoboSats Spanish speaking community!") || ""}>
|
||||
<ListItemText secondary={t('RoboSats Telegram Communities')}>
|
||||
<Tooltip title={t('Join RoboSats Spanish speaking community!') || ''}>
|
||||
<IconButton
|
||||
component="a"
|
||||
target="_blank"
|
||||
href="https://t.me/robosats_es"
|
||||
rel="noreferrer"
|
||||
component='a'
|
||||
target='_blank'
|
||||
href='https://t.me/robosats_es'
|
||||
rel='noreferrer'
|
||||
>
|
||||
<Flags.ES {...flagProps} />
|
||||
</IconButton>
|
||||
</Tooltip>
|
||||
|
||||
<Tooltip title={t("Join RoboSats Russian speaking community!") || ""}>
|
||||
<Tooltip title={t('Join RoboSats Russian speaking community!') || ''}>
|
||||
<IconButton
|
||||
component="a"
|
||||
target="_blank"
|
||||
href="https://t.me/robosats_ru"
|
||||
rel="noreferrer"
|
||||
component='a'
|
||||
target='_blank'
|
||||
href='https://t.me/robosats_ru'
|
||||
rel='noreferrer'
|
||||
>
|
||||
<Flags.RU {...flagProps} />
|
||||
</IconButton>
|
||||
</Tooltip>
|
||||
|
||||
<Tooltip title={t("Join RoboSats Chinese speaking community!") || ""}>
|
||||
<Tooltip title={t('Join RoboSats Chinese speaking community!') || ''}>
|
||||
<IconButton
|
||||
component="a"
|
||||
target="_blank"
|
||||
href="https://t.me/robosats_cn"
|
||||
rel="noreferrer"
|
||||
component='a'
|
||||
target='_blank'
|
||||
href='https://t.me/robosats_cn'
|
||||
rel='noreferrer'
|
||||
>
|
||||
<Flags.CN {...flagProps} />
|
||||
</IconButton>
|
||||
</Tooltip>
|
||||
|
||||
<Tooltip title={t("Join RoboSats English speaking community!") || ""}>
|
||||
<Tooltip title={t('Join RoboSats English speaking community!') || ''}>
|
||||
<IconButton
|
||||
component="a"
|
||||
target="_blank"
|
||||
href="https://t.me/robosats"
|
||||
rel="noreferrer"
|
||||
component='a'
|
||||
target='_blank'
|
||||
href='https://t.me/robosats'
|
||||
rel='noreferrer'
|
||||
>
|
||||
<Flags.US {...flagProps} />
|
||||
</IconButton>
|
||||
</Tooltip>
|
||||
|
||||
<Tooltip title={t("Join RoboSats Portuguese speaking community!") || ""}>
|
||||
<Tooltip title={t('Join RoboSats Portuguese speaking community!') || ''}>
|
||||
<IconButton
|
||||
component="a"
|
||||
target="_blank"
|
||||
href="https://t.me/robosats_pt"
|
||||
rel="noreferrer"
|
||||
component='a'
|
||||
target='_blank'
|
||||
href='https://t.me/robosats_pt'
|
||||
rel='noreferrer'
|
||||
>
|
||||
<Flags.BR {...flagProps} />
|
||||
</IconButton>
|
||||
</Tooltip>
|
||||
|
||||
</ListItemText>
|
||||
</ListItem>
|
||||
|
||||
<Divider/>
|
||||
<Divider />
|
||||
|
||||
<ListItemButton
|
||||
component="a"
|
||||
target="_blank"
|
||||
href="https://github.com/Reckless-Satoshi/robosats/issues"
|
||||
rel="noreferrer"
|
||||
>
|
||||
component='a'
|
||||
target='_blank'
|
||||
href='https://github.com/Reckless-Satoshi/robosats/issues'
|
||||
rel='noreferrer'
|
||||
>
|
||||
<ListItemIcon>
|
||||
<GitHubIcon color="primary" sx={{height:32,width:32}}/>
|
||||
<GitHubIcon color='primary' sx={{ height: 32, width: 32 }} />
|
||||
</ListItemIcon>
|
||||
|
||||
<ListItemText
|
||||
primary={t("Tell us about a new feature or a bug")}
|
||||
secondary={t("Github Issues - The Robotic Satoshis Open Source Project")}
|
||||
primary={t('Tell us about a new feature or a bug')}
|
||||
secondary={t('Github Issues - The Robotic Satoshis Open Source Project')}
|
||||
/>
|
||||
</ListItemButton>
|
||||
</List>
|
||||
|
@ -1,5 +1,5 @@
|
||||
import React from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import React from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
import {
|
||||
Dialog,
|
||||
@ -11,7 +11,7 @@ import {
|
||||
ListItem,
|
||||
ListItemIcon,
|
||||
Typography,
|
||||
} from "@mui/material";
|
||||
} from '@mui/material';
|
||||
|
||||
import InventoryIcon from '@mui/icons-material/Inventory';
|
||||
import SellIcon from '@mui/icons-material/Sell';
|
||||
@ -21,7 +21,7 @@ import PriceChangeIcon from '@mui/icons-material/PriceChange';
|
||||
import BookIcon from '@mui/icons-material/Book';
|
||||
import LinkIcon from '@mui/icons-material/Link';
|
||||
|
||||
import { pn } from "../../utils/prettyNumbers";
|
||||
import { pn } from '../../utils/prettyNumbers';
|
||||
|
||||
type Props = {
|
||||
isOpen: boolean;
|
||||
@ -34,7 +34,7 @@ type Props = {
|
||||
makerFee: number;
|
||||
takerFee: number;
|
||||
swapFeeRate: number;
|
||||
}
|
||||
};
|
||||
|
||||
const ExchangeSummaryDialog = ({
|
||||
isOpen,
|
||||
@ -50,106 +50,108 @@ const ExchangeSummaryDialog = ({
|
||||
}: Props): JSX.Element => {
|
||||
const { t } = useTranslation();
|
||||
if (swapFeeRate === null || swapFeeRate === undefined) {
|
||||
swapFeeRate = 0
|
||||
swapFeeRate = 0;
|
||||
}
|
||||
|
||||
return (
|
||||
<Dialog
|
||||
open={isOpen}
|
||||
onClose={handleClickCloseExchangeSummary}
|
||||
aria-labelledby="exchange-summary-title"
|
||||
aria-describedby="exchange-summary-description"
|
||||
aria-labelledby='exchange-summary-title'
|
||||
aria-describedby='exchange-summary-description'
|
||||
>
|
||||
<DialogContent>
|
||||
<Typography component="h5" variant="h5">{t("Exchange Summary")}</Typography>
|
||||
<Typography component='h5' variant='h5'>
|
||||
{t('Exchange Summary')}
|
||||
</Typography>
|
||||
|
||||
<List dense>
|
||||
<ListItem >
|
||||
<ListItem>
|
||||
<ListItemIcon>
|
||||
<InventoryIcon />
|
||||
</ListItemIcon>
|
||||
|
||||
<ListItemText
|
||||
primaryTypographyProps={{fontSize: '14px'}}
|
||||
secondaryTypographyProps={{fontSize: '12px'}}
|
||||
primaryTypographyProps={{ fontSize: '14px' }}
|
||||
secondaryTypographyProps={{ fontSize: '12px' }}
|
||||
primary={numPublicBuyOrders}
|
||||
secondary={t("Public buy orders")}
|
||||
secondary={t('Public buy orders')}
|
||||
/>
|
||||
</ListItem>
|
||||
|
||||
<Divider />
|
||||
|
||||
<ListItem >
|
||||
<ListItem>
|
||||
<ListItemIcon>
|
||||
<SellIcon />
|
||||
</ListItemIcon>
|
||||
|
||||
<ListItemText
|
||||
primaryTypographyProps={{fontSize: '14px'}}
|
||||
secondaryTypographyProps={{fontSize: '12px'}}
|
||||
primaryTypographyProps={{ fontSize: '14px' }}
|
||||
secondaryTypographyProps={{ fontSize: '12px' }}
|
||||
primary={numPublicSellOrders}
|
||||
secondary={t("Public sell orders")}
|
||||
secondary={t('Public sell orders')}
|
||||
/>
|
||||
</ListItem>
|
||||
|
||||
<Divider/>
|
||||
<Divider />
|
||||
|
||||
<ListItem >
|
||||
<ListItem>
|
||||
<ListItemIcon>
|
||||
<BookIcon />
|
||||
</ListItemIcon>
|
||||
|
||||
<ListItemText
|
||||
primaryTypographyProps={{fontSize: '14px'}}
|
||||
secondaryTypographyProps={{fontSize: '12px'}}
|
||||
primaryTypographyProps={{ fontSize: '14px' }}
|
||||
secondaryTypographyProps={{ fontSize: '12px' }}
|
||||
primary={`${pn(bookLiquidity)} Sats`}
|
||||
secondary={t("Book liquidity")}
|
||||
secondary={t('Book liquidity')}
|
||||
/>
|
||||
</ListItem>
|
||||
|
||||
<Divider/>
|
||||
<Divider />
|
||||
|
||||
<ListItem >
|
||||
<ListItem>
|
||||
<ListItemIcon>
|
||||
<SmartToyIcon />
|
||||
</ListItemIcon>
|
||||
|
||||
<ListItemText
|
||||
primaryTypographyProps={{fontSize: '14px'}}
|
||||
secondaryTypographyProps={{fontSize: '12px'}}
|
||||
primaryTypographyProps={{ fontSize: '14px' }}
|
||||
secondaryTypographyProps={{ fontSize: '12px' }}
|
||||
primary={activeRobotsToday}
|
||||
secondary={t("Today active robots")}
|
||||
secondary={t('Today active robots')}
|
||||
/>
|
||||
</ListItem>
|
||||
|
||||
<Divider/>
|
||||
<Divider />
|
||||
|
||||
<ListItem >
|
||||
<ListItem>
|
||||
<ListItemIcon>
|
||||
<PriceChangeIcon />
|
||||
</ListItemIcon>
|
||||
|
||||
<ListItemText
|
||||
primaryTypographyProps={{fontSize: '14px'}}
|
||||
secondaryTypographyProps={{fontSize: '12px'}}
|
||||
primaryTypographyProps={{ fontSize: '14px' }}
|
||||
secondaryTypographyProps={{ fontSize: '12px' }}
|
||||
primary={`${lastDayNonkycBtcPremium}%`}
|
||||
secondary={t("24h non-KYC bitcoin premium")}
|
||||
secondary={t('24h non-KYC bitcoin premium')}
|
||||
/>
|
||||
</ListItem>
|
||||
|
||||
<Divider/>
|
||||
<Divider />
|
||||
|
||||
<ListItem >
|
||||
<ListItem>
|
||||
<ListItemIcon>
|
||||
<PercentIcon />
|
||||
</ListItemIcon>
|
||||
|
||||
<Grid container >
|
||||
<Grid container>
|
||||
<Grid item xs={6}>
|
||||
<ListItemText
|
||||
primaryTypographyProps={{fontSize: '14px'}}
|
||||
secondaryTypographyProps={{fontSize: '12px'}}
|
||||
secondary={t("Maker fee")}
|
||||
primaryTypographyProps={{ fontSize: '14px' }}
|
||||
secondaryTypographyProps={{ fontSize: '12px' }}
|
||||
secondary={t('Maker fee')}
|
||||
>
|
||||
{(makerFee * 100).toFixed(3)}%
|
||||
</ListItemText>
|
||||
@ -157,9 +159,9 @@ const ExchangeSummaryDialog = ({
|
||||
|
||||
<Grid item xs={6}>
|
||||
<ListItemText
|
||||
primaryTypographyProps={{fontSize: '14px'}}
|
||||
secondaryTypographyProps={{fontSize: '12px'}}
|
||||
secondary={t("Taker fee")}
|
||||
primaryTypographyProps={{ fontSize: '14px' }}
|
||||
secondaryTypographyProps={{ fontSize: '12px' }}
|
||||
secondary={t('Taker fee')}
|
||||
>
|
||||
{(takerFee * 100).toFixed(3)}%
|
||||
</ListItemText>
|
||||
@ -169,19 +171,18 @@ const ExchangeSummaryDialog = ({
|
||||
|
||||
<Divider />
|
||||
|
||||
<ListItem >
|
||||
<ListItem>
|
||||
<ListItemIcon>
|
||||
<LinkIcon />
|
||||
</ListItemIcon>
|
||||
|
||||
<ListItemText
|
||||
primaryTypographyProps={{fontSize: '14px'}}
|
||||
secondaryTypographyProps={{fontSize: '12px'}}
|
||||
primaryTypographyProps={{ fontSize: '14px' }}
|
||||
secondaryTypographyProps={{ fontSize: '12px' }}
|
||||
primary={`${swapFeeRate.toPrecision(3)}%`}
|
||||
secondary={t("Current onchain payout fee")}
|
||||
secondary={t('Current onchain payout fee')}
|
||||
/>
|
||||
</ListItem>
|
||||
|
||||
</List>
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
|
@ -1,19 +1,19 @@
|
||||
import React from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import React from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import {
|
||||
Dialog,
|
||||
Typography,
|
||||
Link,
|
||||
DialogActions,
|
||||
DialogContent,
|
||||
Button,
|
||||
Typography,
|
||||
Link,
|
||||
DialogActions,
|
||||
DialogContent,
|
||||
Button,
|
||||
Grid,
|
||||
Accordion,
|
||||
AccordionDetails,
|
||||
AccordionSummary,
|
||||
} from "@mui/material"
|
||||
import SmoothImage from 'react-smooth-image'
|
||||
import MediaQuery from 'react-responsive'
|
||||
} from '@mui/material';
|
||||
import SmoothImage from 'react-smooth-image';
|
||||
import MediaQuery from 'react-responsive';
|
||||
|
||||
// Icons
|
||||
import ExpandMoreIcon from '@mui/icons-material/ExpandMore';
|
||||
@ -22,213 +22,292 @@ type Props = {
|
||||
maxAmount: string;
|
||||
open: boolean;
|
||||
onClose: () => void;
|
||||
}
|
||||
};
|
||||
|
||||
const InfoDialog = ({
|
||||
maxAmount,
|
||||
open,
|
||||
onClose,
|
||||
}: Props): JSX.Element => {
|
||||
const InfoDialog = ({ maxAmount, open, onClose }: Props): JSX.Element => {
|
||||
const { t } = useTranslation();
|
||||
|
||||
return (
|
||||
<Dialog
|
||||
open={open}
|
||||
onClose={onClose}
|
||||
aria-labelledby="info-dialog-title"
|
||||
aria-describedby="info-dialog-description"
|
||||
scroll="paper">
|
||||
aria-labelledby='info-dialog-title'
|
||||
aria-describedby='info-dialog-description'
|
||||
scroll='paper'
|
||||
>
|
||||
<DialogContent>
|
||||
|
||||
<MediaQuery minWidth={475}>
|
||||
<Grid container>
|
||||
<Grid item xs={8}>
|
||||
<Typography component="h4" variant="h4">{t("What is RoboSats?")}</Typography>
|
||||
<Typography component="div" variant="body2">
|
||||
<p>{t("It is a BTC/FIAT peer-to-peer exchange over lightning.")} <br/>
|
||||
{t("It simplifies matchmaking and minimizes the need of trust. RoboSats focuses in privacy and speed.")}</p>
|
||||
<Grid container>
|
||||
<Grid item xs={8}>
|
||||
<Typography component='h4' variant='h4'>
|
||||
{t('What is RoboSats?')}
|
||||
</Typography>
|
||||
<Typography component='div' variant='body2'>
|
||||
<p>
|
||||
{t('It is a BTC/FIAT peer-to-peer exchange over lightning.')} <br />
|
||||
{t(
|
||||
'It simplifies matchmaking and minimizes the need of trust. RoboSats focuses in privacy and speed.',
|
||||
)}
|
||||
</p>
|
||||
|
||||
<p>{t("RoboSats is an open source project ")} <Link
|
||||
href='https://github.com/reckless-satoshi/robosats'>{t("(GitHub).")}</Link>
|
||||
</p>
|
||||
</Typography>
|
||||
<p>
|
||||
{t('RoboSats is an open source project ')}{' '}
|
||||
<Link href='https://github.com/reckless-satoshi/robosats'>{t('(GitHub).')}</Link>
|
||||
</p>
|
||||
</Typography>
|
||||
</Grid>
|
||||
<Grid item xs={4}>
|
||||
<SmoothImage
|
||||
src={window.location.origin + '/static/assets/images/v0.1.2-04.png'}
|
||||
imageStyles={{
|
||||
borderRadius: '50%',
|
||||
border: '2px solid #555',
|
||||
filter: 'drop-shadow(1px 1px 1px #000000)',
|
||||
height: '170px',
|
||||
width: '170px',
|
||||
}}
|
||||
/>
|
||||
</Grid>
|
||||
</Grid>
|
||||
<Grid item xs={4}>
|
||||
<SmoothImage
|
||||
src={window.location.origin +'/static/assets/images/v0.1.2-04.png'}
|
||||
imageStyles={{borderRadius: "50%",
|
||||
border: "2px solid #555",
|
||||
filter: "drop-shadow(1px 1px 1px #000000)",
|
||||
height: "170px",
|
||||
width: "170px"}}
|
||||
/>
|
||||
</Grid>
|
||||
</Grid>
|
||||
<div style={{height:15}}/>
|
||||
<div style={{ height: 15 }} />
|
||||
</MediaQuery>
|
||||
|
||||
<MediaQuery maxWidth={474}>
|
||||
<Typography component="h4" variant="h4">{t("What is RoboSats?")}</Typography>
|
||||
<Typography component="div" variant="body2">
|
||||
<p>{t("It is a BTC/FIAT peer-to-peer exchange over lightning.")+" "} {t("It simplifies matchmaking and minimizes the need of trust. RoboSats focuses in privacy and speed.")}</p>
|
||||
<Typography component='h4' variant='h4'>
|
||||
{t('What is RoboSats?')}
|
||||
</Typography>
|
||||
<Typography component='div' variant='body2'>
|
||||
<p>
|
||||
{t('It is a BTC/FIAT peer-to-peer exchange over lightning.') + ' '}{' '}
|
||||
{t(
|
||||
'It simplifies matchmaking and minimizes the need of trust. RoboSats focuses in privacy and speed.',
|
||||
)}
|
||||
</p>
|
||||
<img
|
||||
width='100%'
|
||||
src={window.location.origin +'/static/assets/images/v0.1.2-03.png'}
|
||||
src={window.location.origin + '/static/assets/images/v0.1.2-03.png'}
|
||||
/>
|
||||
<p>{t("RoboSats is an open source project ")} <Link
|
||||
href='https://github.com/reckless-satoshi/robosats'>{t("(GitHub).")}</Link>
|
||||
</p>
|
||||
</Typography>
|
||||
<p>
|
||||
{t('RoboSats is an open source project ')}{' '}
|
||||
<Link href='https://github.com/reckless-satoshi/robosats'>{t('(GitHub).')}</Link>
|
||||
</p>
|
||||
</Typography>
|
||||
</MediaQuery>
|
||||
|
||||
<Accordion disableGutters={true}>
|
||||
<AccordionSummary expandIcon={<ExpandMoreIcon/>}>
|
||||
<Typography>
|
||||
{t("How does it work?")}
|
||||
</Typography>
|
||||
<AccordionSummary expandIcon={<ExpandMoreIcon />}>
|
||||
<Typography>{t('How does it work?')}</Typography>
|
||||
</AccordionSummary>
|
||||
<AccordionDetails>
|
||||
<Typography component="div" variant="body2">
|
||||
<p> {t("AnonymousAlice01 wants to sell bitcoin. She posts a sell order. BafflingBob02 wants to buy bitcoin and he takes Alice's order. Both have to post a small bond using lightning to prove they are real robots. Then, Alice posts the trade collateral also using a lightning hold invoice. RoboSats locks the invoice until Alice confirms she received the fiat, then the satoshis are released to Bob. Enjoy your satoshis, Bob!")}</p>
|
||||
<p>{t("At no point, AnonymousAlice01 and BafflingBob02 have to entrust the bitcoin funds to each other. In case they have a conflict, RoboSats staff will help resolving the dispute.")}
|
||||
{t("You can find a step-by-step description of the trade pipeline in ")}
|
||||
<Link target="_blank" href='https://learn.robosats.com/docs/trade-pipeline/'>{t("How it works")}</Link>.
|
||||
{" "+t("You can also check the full guide in ")}
|
||||
<Link target="_blank" href='https://learn.robosats.com/read/en'>{t("How to use")}</Link>.</p>
|
||||
<Typography component='div' variant='body2'>
|
||||
<p>
|
||||
{' '}
|
||||
{t(
|
||||
"AnonymousAlice01 wants to sell bitcoin. She posts a sell order. BafflingBob02 wants to buy bitcoin and he takes Alice's order. Both have to post a small bond using lightning to prove they are real robots. Then, Alice posts the trade collateral also using a lightning hold invoice. RoboSats locks the invoice until Alice confirms she received the fiat, then the satoshis are released to Bob. Enjoy your satoshis, Bob!",
|
||||
)}
|
||||
</p>
|
||||
<p>
|
||||
{t(
|
||||
'At no point, AnonymousAlice01 and BafflingBob02 have to entrust the bitcoin funds to each other. In case they have a conflict, RoboSats staff will help resolving the dispute.',
|
||||
)}
|
||||
{t('You can find a step-by-step description of the trade pipeline in ')}
|
||||
<Link target='_blank' href='https://learn.robosats.com/docs/trade-pipeline/'>
|
||||
{t('How it works')}
|
||||
</Link>
|
||||
.{' ' + t('You can also check the full guide in ')}
|
||||
<Link target='_blank' href='https://learn.robosats.com/read/en'>
|
||||
{t('How to use')}
|
||||
</Link>
|
||||
.
|
||||
</p>
|
||||
</Typography>
|
||||
</AccordionDetails>
|
||||
</Accordion>
|
||||
|
||||
<Accordion disableGutters={true}>
|
||||
<AccordionSummary expandIcon={<ExpandMoreIcon/>}>
|
||||
<Typography>
|
||||
{t("What payment methods are accepted?")
|
||||
}</Typography>
|
||||
<AccordionSummary expandIcon={<ExpandMoreIcon />}>
|
||||
<Typography>{t('What payment methods are accepted?')}</Typography>
|
||||
</AccordionSummary>
|
||||
<AccordionDetails>
|
||||
<Typography component="div" variant="body2">
|
||||
<p>{t("All of them as long as they are fast. You can write down your preferred payment method(s). You will have to match with a peer who also accepts that method. The step to exchange fiat has a expiry time of 24 hours before a dispute is automatically open. We highly recommend using instant fiat payment rails.")} </p>
|
||||
<Typography component='div' variant='body2'>
|
||||
<p>
|
||||
{t(
|
||||
'All of them as long as they are fast. You can write down your preferred payment method(s). You will have to match with a peer who also accepts that method. The step to exchange fiat has a expiry time of 24 hours before a dispute is automatically open. We highly recommend using instant fiat payment rails.',
|
||||
)}{' '}
|
||||
</p>
|
||||
</Typography>
|
||||
</AccordionDetails>
|
||||
</Accordion>
|
||||
|
||||
<Accordion disableGutters={true}>
|
||||
<AccordionSummary expandIcon={<ExpandMoreIcon/>}>
|
||||
<Typography>
|
||||
{t("Are there trade limits?")}
|
||||
</Typography>
|
||||
<AccordionSummary expandIcon={<ExpandMoreIcon />}>
|
||||
<Typography>{t('Are there trade limits?')}</Typography>
|
||||
</AccordionSummary>
|
||||
<AccordionDetails>
|
||||
<Typography component="div" variant="body2">
|
||||
<p>{t("Maximum single trade size is {{maxAmount}} Satoshis to minimize lightning routing failure. There is no limits to the number of trades per day. A robot can only have one order at a time. However, you can use multiple robots simultaneously in different browsers (remember to back up your robot tokens!).", {maxAmount: maxAmount})} </p>
|
||||
<Typography component='div' variant='body2'>
|
||||
<p>
|
||||
{t(
|
||||
'Maximum single trade size is {{maxAmount}} Satoshis to minimize lightning routing failure. There is no limits to the number of trades per day. A robot can only have one order at a time. However, you can use multiple robots simultaneously in different browsers (remember to back up your robot tokens!).',
|
||||
{ maxAmount: maxAmount },
|
||||
)}{' '}
|
||||
</p>
|
||||
</Typography>
|
||||
</AccordionDetails>
|
||||
</Accordion>
|
||||
|
||||
<Accordion disableGutters={true}>
|
||||
<AccordionSummary expandIcon={<ExpandMoreIcon/>}>
|
||||
<Typography>
|
||||
{t("What are the fees?")}
|
||||
</Typography>
|
||||
<AccordionSummary expandIcon={<ExpandMoreIcon />}>
|
||||
<Typography>{t('What are the fees?')}</Typography>
|
||||
</AccordionSummary>
|
||||
<AccordionDetails>
|
||||
<Typography component="div" variant="body2">
|
||||
<p>{t("RoboSats total fee for an order is {{tradeFee}}%. This fee is split to be covered by both: the order maker ({{makerFee}}%) and the order taker ({{takerFee}}%). In case an onchain address is used to received the Sats a variable swap fee applies. Check the exchange details by tapping on the bottom bar icon to see the current swap fee.",{tradeFee:"0.2", makerFee:"0.025", takerFee: "0.175"})} </p>
|
||||
<p>{t("Be aware your fiat payment provider might charge extra fees. In any case, the buyer bears the costs of sending fiat. That includes banking charges, transfer fees and foreign exchange spreads. The seller must receive exactly the amount stated in the order details.")} </p>
|
||||
<Typography component='div' variant='body2'>
|
||||
<p>
|
||||
{t(
|
||||
'RoboSats total fee for an order is {{tradeFee}}%. This fee is split to be covered by both: the order maker ({{makerFee}}%) and the order taker ({{takerFee}}%). In case an onchain address is used to received the Sats a variable swap fee applies. Check the exchange details by tapping on the bottom bar icon to see the current swap fee.',
|
||||
{ tradeFee: '0.2', makerFee: '0.025', takerFee: '0.175' },
|
||||
)}{' '}
|
||||
</p>
|
||||
<p>
|
||||
{t(
|
||||
'Be aware your fiat payment provider might charge extra fees. In any case, the buyer bears the costs of sending fiat. That includes banking charges, transfer fees and foreign exchange spreads. The seller must receive exactly the amount stated in the order details.',
|
||||
)}{' '}
|
||||
</p>
|
||||
</Typography>
|
||||
</AccordionDetails>
|
||||
</Accordion>
|
||||
|
||||
<Accordion disableGutters={true}>
|
||||
<AccordionSummary expandIcon={<ExpandMoreIcon/>}>
|
||||
<Typography>
|
||||
{t("Is RoboSats private?")}
|
||||
</Typography>
|
||||
<AccordionSummary expandIcon={<ExpandMoreIcon />}>
|
||||
<Typography>{t('Is RoboSats private?')}</Typography>
|
||||
</AccordionSummary>
|
||||
<AccordionDetails>
|
||||
<Typography component="div" variant="body2">
|
||||
<p> {t("RoboSats will never ask you for your name, country or ID. RoboSats does not custody your funds and does not care who you are. RoboSats does not collect or custody any personal data. For best anonymity use Tor Browser and access the .onion hidden service.")} </p>
|
||||
<p>{t("Your trading peer is the only one who can potentially guess anything about you. Keep your chat short and concise. Avoid providing non-essential information other than strictly necessary for the fiat payment.")} </p>
|
||||
<Typography component='div' variant='body2'>
|
||||
<p>
|
||||
{' '}
|
||||
{t(
|
||||
'RoboSats will never ask you for your name, country or ID. RoboSats does not custody your funds and does not care who you are. RoboSats does not collect or custody any personal data. For best anonymity use Tor Browser and access the .onion hidden service.',
|
||||
)}{' '}
|
||||
</p>
|
||||
<p>
|
||||
{t(
|
||||
'Your trading peer is the only one who can potentially guess anything about you. Keep your chat short and concise. Avoid providing non-essential information other than strictly necessary for the fiat payment.',
|
||||
)}{' '}
|
||||
</p>
|
||||
</Typography>
|
||||
</AccordionDetails>
|
||||
</Accordion>
|
||||
|
||||
<Accordion disableGutters={true}>
|
||||
<AccordionSummary expandIcon={<ExpandMoreIcon/>}>
|
||||
<Typography>
|
||||
{t("What are the risks?")}
|
||||
</Typography>
|
||||
<AccordionSummary expandIcon={<ExpandMoreIcon />}>
|
||||
<Typography>{t('What are the risks?')}</Typography>
|
||||
</AccordionSummary>
|
||||
<AccordionDetails>
|
||||
<Typography component="div" variant="body2">
|
||||
<p> {t("This is an experimental application, things could go wrong. Trade small amounts!")}</p>
|
||||
<p> {t("The seller faces the same charge-back risk as with any other peer-to-peer service. Paypal or credit cards are not recommended.")}</p>
|
||||
<Typography component='div' variant='body2'>
|
||||
<p>
|
||||
{' '}
|
||||
{t(
|
||||
'This is an experimental application, things could go wrong. Trade small amounts!',
|
||||
)}
|
||||
</p>
|
||||
<p>
|
||||
{' '}
|
||||
{t(
|
||||
'The seller faces the same charge-back risk as with any other peer-to-peer service. Paypal or credit cards are not recommended.',
|
||||
)}
|
||||
</p>
|
||||
</Typography>
|
||||
</AccordionDetails>
|
||||
</Accordion>
|
||||
|
||||
<Accordion disableGutters={true}>
|
||||
<AccordionSummary expandIcon={<ExpandMoreIcon/>}>
|
||||
<Typography>
|
||||
{t("What is the trust model?")}
|
||||
</Typography>
|
||||
<AccordionSummary expandIcon={<ExpandMoreIcon />}>
|
||||
<Typography>{t('What is the trust model?')}</Typography>
|
||||
</AccordionSummary>
|
||||
<AccordionDetails>
|
||||
<Typography component="div" variant="body2">
|
||||
<p> {t("The buyer and the seller never have to trust each other. Some trust on RoboSats is needed since linking the seller's hold invoice and buyer payment is not atomic (yet). In addition, disputes are solved by the RoboSats staff.")}</p>
|
||||
<p> {t("To be totally clear. Trust requirements are minimized. However, there is still one way RoboSats could run away with your satoshis: by not releasing the satoshis to the buyer. It could be argued that such move is not in RoboSats' interest as it would damage the reputation for a small payout. However, you should hesitate and only trade small quantities at a time. For large amounts use an onchain escrow service such as Bisq")}</p>
|
||||
<p> {t("You can build more trust on RoboSats by inspecting the source code.")} <Link href='https://github.com/reckless-satoshi/robosats'> {t("Project source code")}</Link>. </p>
|
||||
<Typography component='div' variant='body2'>
|
||||
<p>
|
||||
{' '}
|
||||
{t(
|
||||
"The buyer and the seller never have to trust each other. Some trust on RoboSats is needed since linking the seller's hold invoice and buyer payment is not atomic (yet). In addition, disputes are solved by the RoboSats staff.",
|
||||
)}
|
||||
</p>
|
||||
<p>
|
||||
{' '}
|
||||
{t(
|
||||
"To be totally clear. Trust requirements are minimized. However, there is still one way RoboSats could run away with your satoshis: by not releasing the satoshis to the buyer. It could be argued that such move is not in RoboSats' interest as it would damage the reputation for a small payout. However, you should hesitate and only trade small quantities at a time. For large amounts use an onchain escrow service such as Bisq",
|
||||
)}
|
||||
</p>
|
||||
<p>
|
||||
{' '}
|
||||
{t('You can build more trust on RoboSats by inspecting the source code.')}{' '}
|
||||
<Link href='https://github.com/reckless-satoshi/robosats'>
|
||||
{' '}
|
||||
{t('Project source code')}
|
||||
</Link>
|
||||
.{' '}
|
||||
</p>
|
||||
</Typography>
|
||||
</AccordionDetails>
|
||||
</Accordion>
|
||||
|
||||
<Accordion disableGutters={true}>
|
||||
<AccordionSummary expandIcon={<ExpandMoreIcon/>}>
|
||||
<Typography>
|
||||
{t("What happens if RoboSats suddenly disappears?")}
|
||||
</Typography>
|
||||
<AccordionSummary expandIcon={<ExpandMoreIcon />}>
|
||||
<Typography>{t('What happens if RoboSats suddenly disappears?')}</Typography>
|
||||
</AccordionSummary>
|
||||
<AccordionDetails>
|
||||
<Typography component="div" variant="body2">
|
||||
<p> {t("Your sats will return to you. Any hold invoice that is not settled would be automatically returned even if RoboSats goes down forever. This is true for both, locked bonds and trading escrows. However, there is a small window between the seller confirms FIAT RECEIVED and the moment the buyer receives the satoshis when the funds could be permanently lost if RoboSats disappears. This window is about 1 second long. Make sure to have enough inbound liquidity to avoid routing failures. If you have any problem, reach out trough the RoboSats public channels.")}</p>
|
||||
<Typography component='div' variant='body2'>
|
||||
<p>
|
||||
{' '}
|
||||
{t(
|
||||
'Your sats will return to you. Any hold invoice that is not settled would be automatically returned even if RoboSats goes down forever. This is true for both, locked bonds and trading escrows. However, there is a small window between the seller confirms FIAT RECEIVED and the moment the buyer receives the satoshis when the funds could be permanently lost if RoboSats disappears. This window is about 1 second long. Make sure to have enough inbound liquidity to avoid routing failures. If you have any problem, reach out trough the RoboSats public channels.',
|
||||
)}
|
||||
</p>
|
||||
</Typography>
|
||||
</AccordionDetails>
|
||||
</Accordion>
|
||||
|
||||
<Accordion disableGutters={true}>
|
||||
<AccordionSummary expandIcon={<ExpandMoreIcon/>}>
|
||||
<Typography>
|
||||
{t("Is RoboSats legal in my country?")}
|
||||
</Typography>
|
||||
<AccordionSummary expandIcon={<ExpandMoreIcon />}>
|
||||
<Typography>{t('Is RoboSats legal in my country?')}</Typography>
|
||||
</AccordionSummary>
|
||||
<AccordionDetails>
|
||||
<Typography component="div" variant="body2">
|
||||
<p> {t("In many countries using RoboSats is no different than using Ebay or Craiglist. Your regulation may vary. It is your responsibility to comply.")}</p>
|
||||
<Typography component='div' variant='body2'>
|
||||
<p>
|
||||
{' '}
|
||||
{t(
|
||||
'In many countries using RoboSats is no different than using Ebay or Craiglist. Your regulation may vary. It is your responsibility to comply.',
|
||||
)}
|
||||
</p>
|
||||
</Typography>
|
||||
</AccordionDetails>
|
||||
</Accordion>
|
||||
|
||||
<Accordion disableGutters={true}>
|
||||
<AccordionSummary expandIcon={<ExpandMoreIcon/>}>
|
||||
<Typography>
|
||||
{t("Disclaimer")}
|
||||
</Typography>
|
||||
<AccordionSummary expandIcon={<ExpandMoreIcon />}>
|
||||
<Typography>{t('Disclaimer')}</Typography>
|
||||
</AccordionSummary>
|
||||
<AccordionDetails>
|
||||
<Typography component="div" variant="body2">
|
||||
<p> {t("This lightning application is provided as is. It is in active development: trade with the utmost caution. There is no private support. Support is only offered via public channels ")}<Link href='https://t.me/robosats'>{t("(Telegram)")}</Link>{t(". RoboSats will never contact you. RoboSats will definitely never ask for your robot token.")}</p>
|
||||
<Typography component='div' variant='body2'>
|
||||
<p>
|
||||
{' '}
|
||||
{t(
|
||||
'This lightning application is provided as is. It is in active development: trade with the utmost caution. There is no private support. Support is only offered via public channels ',
|
||||
)}
|
||||
<Link href='https://t.me/robosats'>{t('(Telegram)')}</Link>
|
||||
{t(
|
||||
'. RoboSats will never contact you. RoboSats will definitely never ask for your robot token.',
|
||||
)}
|
||||
</p>
|
||||
</Typography>
|
||||
</AccordionDetails>
|
||||
</Accordion>
|
||||
|
||||
<DialogActions>
|
||||
<Button onClick={onClose}>{t("Close")}</Button>
|
||||
<Button onClick={onClose}>{t('Close')}</Button>
|
||||
</DialogActions>
|
||||
|
||||
</DialogContent>
|
||||
|
||||
</Dialog>
|
||||
)
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
export default InfoDialog;
|
||||
|
@ -1,50 +1,49 @@
|
||||
import React from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import React from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import {
|
||||
Dialog,
|
||||
DialogTitle,
|
||||
DialogActions,
|
||||
DialogActions,
|
||||
DialogContent,
|
||||
DialogContentText,
|
||||
Button,
|
||||
Link,
|
||||
} from "@mui/material"
|
||||
Link,
|
||||
} from '@mui/material';
|
||||
|
||||
type Props = {
|
||||
open: boolean;
|
||||
onClose: () => void;
|
||||
}
|
||||
};
|
||||
|
||||
const LearnDialog = ({
|
||||
open,
|
||||
onClose,
|
||||
}: Props): JSX.Element => {
|
||||
const LearnDialog = ({ open, onClose }: Props): JSX.Element => {
|
||||
const { t } = useTranslation();
|
||||
|
||||
return (
|
||||
<Dialog
|
||||
open={open}
|
||||
onClose={onClose}
|
||||
>
|
||||
<DialogTitle>
|
||||
{t("Learn RoboSats")}
|
||||
</DialogTitle>
|
||||
<Dialog open={open} onClose={onClose}>
|
||||
<DialogTitle>{t('Learn RoboSats')}</DialogTitle>
|
||||
|
||||
<DialogContent>
|
||||
<DialogContentText>
|
||||
{t("You are about to visit Learn RoboSats. It hosts tutorials and documentation to help you learn how to use RoboSats and understand how it works.")}
|
||||
{t(
|
||||
'You are about to visit Learn RoboSats. It hosts tutorials and documentation to help you learn how to use RoboSats and understand how it works.',
|
||||
)}
|
||||
</DialogContentText>
|
||||
</DialogContent>
|
||||
|
||||
<DialogActions>
|
||||
<Button onClick={onClose}>{t("Back")}</Button>
|
||||
<Button onClick={onClose} autoFocus component={Link} href="https://learn.robosats.com" target="_blank">
|
||||
<Button onClick={onClose}>{t('Back')}</Button>
|
||||
<Button
|
||||
onClick={onClose}
|
||||
autoFocus
|
||||
component={Link}
|
||||
href='https://learn.robosats.com'
|
||||
target='_blank'
|
||||
>
|
||||
{t("Let's go!")}
|
||||
</Button>
|
||||
</DialogActions>
|
||||
|
||||
</Dialog>
|
||||
)
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
export default LearnDialog;
|
||||
|
@ -1,48 +1,43 @@
|
||||
import React from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import React from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import {
|
||||
Dialog,
|
||||
DialogTitle,
|
||||
DialogActions,
|
||||
DialogActions,
|
||||
DialogContent,
|
||||
DialogContentText,
|
||||
Button,
|
||||
} from "@mui/material"
|
||||
import { Link } from 'react-router-dom'
|
||||
Button,
|
||||
} from '@mui/material';
|
||||
import { Link } from 'react-router-dom';
|
||||
|
||||
type Props = {
|
||||
open: boolean;
|
||||
onClose: () => void;
|
||||
}
|
||||
};
|
||||
|
||||
const NoRobotDialog = ({
|
||||
open,
|
||||
onClose,
|
||||
}: Props): JSX.Element => {
|
||||
const NoRobotDialog = ({ open, onClose }: Props): JSX.Element => {
|
||||
const { t } = useTranslation();
|
||||
|
||||
return (
|
||||
<Dialog
|
||||
open={open}
|
||||
onClose={onClose}
|
||||
>
|
||||
<DialogTitle>
|
||||
{t("You do not have a robot avatar")}
|
||||
</DialogTitle>
|
||||
<Dialog open={open} onClose={onClose}>
|
||||
<DialogTitle>{t('You do not have a robot avatar')}</DialogTitle>
|
||||
|
||||
<DialogContent>
|
||||
<DialogContentText>
|
||||
{t("You need to generate a robot avatar in order to become an order maker")}
|
||||
{t('You need to generate a robot avatar in order to become an order maker')}
|
||||
</DialogContentText>
|
||||
</DialogContent>
|
||||
|
||||
<DialogActions>
|
||||
<Button onClick={onClose} autoFocus>{t("Go back")}</Button>
|
||||
<Button onClick={onClose} to="/" component={Link}>{t("Generate Robot")}</Button>
|
||||
<Button onClick={onClose} autoFocus>
|
||||
{t('Go back')}
|
||||
</Button>
|
||||
<Button onClick={onClose} to='/' component={Link}>
|
||||
{t('Generate Robot')}
|
||||
</Button>
|
||||
</DialogActions>
|
||||
|
||||
</Dialog>
|
||||
)
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
export default NoRobotDialog;
|
||||
|
@ -1,6 +1,6 @@
|
||||
import React, { useEffect, useState } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { Link as LinkRouter } from "react-router-dom";
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { Link as LinkRouter } from 'react-router-dom';
|
||||
|
||||
import {
|
||||
Avatar,
|
||||
@ -23,19 +23,19 @@ import {
|
||||
TextField,
|
||||
Tooltip,
|
||||
Typography,
|
||||
} from "@mui/material";
|
||||
} from '@mui/material';
|
||||
|
||||
import BoltIcon from "@mui/icons-material/Bolt";
|
||||
import NumbersIcon from "@mui/icons-material/Numbers";
|
||||
import PasswordIcon from "@mui/icons-material/Password";
|
||||
import ContentCopy from "@mui/icons-material/ContentCopy";
|
||||
import PersonAddAltIcon from "@mui/icons-material/PersonAddAlt";
|
||||
import EmojiEventsIcon from "@mui/icons-material/EmojiEvents";
|
||||
import { UserNinjaIcon, BitcoinIcon } from "../Icons";
|
||||
import BoltIcon from '@mui/icons-material/Bolt';
|
||||
import NumbersIcon from '@mui/icons-material/Numbers';
|
||||
import PasswordIcon from '@mui/icons-material/Password';
|
||||
import ContentCopy from '@mui/icons-material/ContentCopy';
|
||||
import PersonAddAltIcon from '@mui/icons-material/PersonAddAlt';
|
||||
import EmojiEventsIcon from '@mui/icons-material/EmojiEvents';
|
||||
import { UserNinjaIcon, BitcoinIcon } from '../Icons';
|
||||
|
||||
import { getCookie } from "../../utils/cookies";
|
||||
import { copyToClipboard } from "../../utils/clipboard";
|
||||
import { getWebln } from "../../utils/webln";
|
||||
import { getCookie } from '../../utils/cookies';
|
||||
import { copyToClipboard } from '../../utils/clipboard';
|
||||
import { getWebln } from '../../utils/webln';
|
||||
|
||||
type Props = {
|
||||
isOpen: boolean;
|
||||
@ -44,7 +44,7 @@ type Props = {
|
||||
activeOrderId: string | number;
|
||||
lastOrderId: string | number;
|
||||
referralCode: string;
|
||||
handleSubmitInvoiceClicked: (e:any, invoice: string) => void;
|
||||
handleSubmitInvoiceClicked: (e: any, invoice: string) => void;
|
||||
host: string;
|
||||
showRewardsSpinner: boolean;
|
||||
withdrawn: boolean;
|
||||
@ -53,7 +53,7 @@ type Props = {
|
||||
stealthInvoices: boolean;
|
||||
handleSetStealthInvoice: (stealth: boolean) => void;
|
||||
setAppState: (state: any) => void; // TODO: move to a ContextProvider
|
||||
}
|
||||
};
|
||||
|
||||
const ProfileDialog = ({
|
||||
isOpen,
|
||||
@ -74,24 +74,23 @@ const ProfileDialog = ({
|
||||
}: Props): JSX.Element => {
|
||||
const { t } = useTranslation();
|
||||
|
||||
const [rewardInvoice, setRewardInvoice] = useState<string>("");
|
||||
const [rewardInvoice, setRewardInvoice] = useState<string>('');
|
||||
const [showRewards, setShowRewards] = useState<boolean>(false);
|
||||
const [openClaimRewards, setOpenClaimRewards] = useState<boolean>(false);
|
||||
const [weblnEnabled, setWeblnEnabled] = useState<boolean>(false)
|
||||
const [weblnEnabled, setWeblnEnabled] = useState<boolean>(false);
|
||||
|
||||
useEffect(() => {
|
||||
getWebln()
|
||||
.then((webln) => {
|
||||
setWeblnEnabled(webln !== undefined)
|
||||
})
|
||||
}, [showRewards])
|
||||
getWebln().then((webln) => {
|
||||
setWeblnEnabled(webln !== undefined);
|
||||
});
|
||||
}, [showRewards]);
|
||||
|
||||
const copyTokenHandler = () => {
|
||||
const robotToken = getCookie("robot_token");
|
||||
const robotToken = getCookie('robot_token');
|
||||
|
||||
if (robotToken) {
|
||||
copyToClipboard(robotToken);
|
||||
setAppState({copiedToken:true});
|
||||
setAppState({ copiedToken: true });
|
||||
}
|
||||
};
|
||||
|
||||
@ -99,59 +98,71 @@ const ProfileDialog = ({
|
||||
copyToClipboard(`http://${host}/ref/${referralCode}`);
|
||||
};
|
||||
|
||||
const handleWeblnInvoiceClicked = async (e: any) =>{
|
||||
const handleWeblnInvoiceClicked = async (e: any) => {
|
||||
e.preventDefault();
|
||||
if (earnedRewards) {
|
||||
const webln = await getWebln();
|
||||
const invoice = webln.makeInvoice(earnedRewards).then(() => {
|
||||
if (invoice) {
|
||||
handleSubmitInvoiceClicked(e, invoice.paymentRequest)
|
||||
handleSubmitInvoiceClicked(e, invoice.paymentRequest);
|
||||
}
|
||||
})
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<Dialog
|
||||
open={isOpen}
|
||||
onClose={handleClickCloseProfile}
|
||||
aria-labelledby="profile-title"
|
||||
aria-describedby="profile-description"
|
||||
aria-labelledby='profile-title'
|
||||
aria-describedby='profile-description'
|
||||
>
|
||||
<DialogContent>
|
||||
<Typography component="h5" variant="h5">{t("Your Profile")}</Typography>
|
||||
<Typography component='h5' variant='h5'>
|
||||
{t('Your Profile')}
|
||||
</Typography>
|
||||
|
||||
<List>
|
||||
<Divider/>
|
||||
<Divider />
|
||||
|
||||
<ListItem className="profileNickname">
|
||||
<ListItemText secondary={t("Your robot")}>
|
||||
<Typography component="h6" variant="h6">
|
||||
<ListItem className='profileNickname'>
|
||||
<ListItemText secondary={t('Your robot')}>
|
||||
<Typography component='h6' variant='h6'>
|
||||
{nickname ? (
|
||||
<div style={{position:"relative", left:"-7px"}}>
|
||||
<div style={{display:"flex", alignItems:"center", justifyContent:"left", flexWrap:"wrap", width:300}}>
|
||||
<BoltIcon sx={{ color: "#fcba03", height: "28px", width: "24px"}} />
|
||||
<div style={{ position: 'relative', left: '-7px' }}>
|
||||
<div
|
||||
style={{
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'left',
|
||||
flexWrap: 'wrap',
|
||||
width: 300,
|
||||
}}
|
||||
>
|
||||
<BoltIcon sx={{ color: '#fcba03', height: '28px', width: '24px' }} />
|
||||
|
||||
<a>{nickname}</a>
|
||||
|
||||
<BoltIcon sx={{ color: "#fcba03", height: "28px", width: "24px"}} />
|
||||
<BoltIcon sx={{ color: '#fcba03', height: '28px', width: '24px' }} />
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
: null}
|
||||
) : null}
|
||||
</Typography>
|
||||
</ListItemText>
|
||||
|
||||
<ListItemAvatar>
|
||||
<Avatar className="profileAvatar"
|
||||
sx={{ width: 65, height:65 }}
|
||||
<Avatar
|
||||
className='profileAvatar'
|
||||
sx={{ width: 65, height: 65 }}
|
||||
alt={nickname}
|
||||
src={nickname ? `${window.location.origin}/static/assets/avatars/${nickname}.png` : ""}
|
||||
src={
|
||||
nickname ? `${window.location.origin}/static/assets/avatars/${nickname}.png` : ''
|
||||
}
|
||||
/>
|
||||
</ListItemAvatar>
|
||||
</ListItem>
|
||||
|
||||
<Divider/>
|
||||
<Divider />
|
||||
|
||||
{activeOrderId ? (
|
||||
<ListItemButton
|
||||
@ -160,94 +171,94 @@ const ProfileDialog = ({
|
||||
component={LinkRouter}
|
||||
>
|
||||
<ListItemIcon>
|
||||
<Badge badgeContent="" color="primary">
|
||||
<NumbersIcon color="primary" />
|
||||
<Badge badgeContent='' color='primary'>
|
||||
<NumbersIcon color='primary' />
|
||||
</Badge>
|
||||
</ListItemIcon>
|
||||
<ListItemText
|
||||
primary={t("One active order #{{orderID}}", { orderID: activeOrderId })}
|
||||
secondary={t("Your current order")}
|
||||
primary={t('One active order #{{orderID}}', { orderID: activeOrderId })}
|
||||
secondary={t('Your current order')}
|
||||
/>
|
||||
</ListItemButton>
|
||||
) :
|
||||
lastOrderId ? (
|
||||
<ListItemButton
|
||||
onClick={handleClickCloseProfile}
|
||||
to={`/order/${lastOrderId}`}
|
||||
component={LinkRouter}
|
||||
>
|
||||
<ListItemIcon>
|
||||
<NumbersIcon color="primary" />
|
||||
</ListItemIcon>
|
||||
<ListItemText
|
||||
primary={t("Your last order #{{orderID}}", { orderID: lastOrderId })}
|
||||
secondary={t("Inactive order")}
|
||||
/>
|
||||
</ListItemButton>
|
||||
) : (
|
||||
<ListItem>
|
||||
<ListItemIcon>
|
||||
<NumbersIcon />
|
||||
</ListItemIcon>
|
||||
<ListItemText
|
||||
primary={t("No active orders")}
|
||||
secondary={t("You do not have previous orders")}
|
||||
/>
|
||||
</ListItem>
|
||||
)
|
||||
}
|
||||
) : lastOrderId ? (
|
||||
<ListItemButton
|
||||
onClick={handleClickCloseProfile}
|
||||
to={`/order/${lastOrderId}`}
|
||||
component={LinkRouter}
|
||||
>
|
||||
<ListItemIcon>
|
||||
<NumbersIcon color='primary' />
|
||||
</ListItemIcon>
|
||||
<ListItemText
|
||||
primary={t('Your last order #{{orderID}}', { orderID: lastOrderId })}
|
||||
secondary={t('Inactive order')}
|
||||
/>
|
||||
</ListItemButton>
|
||||
) : (
|
||||
<ListItem>
|
||||
<ListItemIcon>
|
||||
<NumbersIcon />
|
||||
</ListItemIcon>
|
||||
<ListItemText
|
||||
primary={t('No active orders')}
|
||||
secondary={t('You do not have previous orders')}
|
||||
/>
|
||||
</ListItem>
|
||||
)}
|
||||
|
||||
<ListItem>
|
||||
<ListItemIcon>
|
||||
<PasswordIcon />
|
||||
</ListItemIcon>
|
||||
|
||||
<ListItemText secondary={t("Your token (will not remain here)")}>
|
||||
{getCookie("robot_token") ? (
|
||||
<ListItemText secondary={t('Your token (will not remain here)')}>
|
||||
{getCookie('robot_token') ? (
|
||||
<TextField
|
||||
disabled
|
||||
sx={{width:"100%", maxWidth:"450px"}}
|
||||
label={t("Back it up!")}
|
||||
value={getCookie("robot_token") }
|
||||
variant="filled"
|
||||
size="small"
|
||||
sx={{ width: '100%', maxWidth: '450px' }}
|
||||
label={t('Back it up!')}
|
||||
value={getCookie('robot_token')}
|
||||
variant='filled'
|
||||
size='small'
|
||||
InputProps={{
|
||||
endAdornment:
|
||||
<Tooltip
|
||||
disableHoverListener
|
||||
enterTouchDelay={0}
|
||||
title={t("Copied!") || ""}
|
||||
>
|
||||
<IconButton onClick={copyTokenHandler}>
|
||||
<ContentCopy color="inherit" />
|
||||
</IconButton>
|
||||
</Tooltip>,
|
||||
}}
|
||||
endAdornment: (
|
||||
<Tooltip disableHoverListener enterTouchDelay={0} title={t('Copied!') || ''}>
|
||||
<IconButton onClick={copyTokenHandler}>
|
||||
<ContentCopy color='inherit' />
|
||||
</IconButton>
|
||||
</Tooltip>
|
||||
),
|
||||
}}
|
||||
/>
|
||||
) :
|
||||
t("Cannot remember")
|
||||
}
|
||||
) : (
|
||||
t('Cannot remember')
|
||||
)}
|
||||
</ListItemText>
|
||||
</ListItem>
|
||||
|
||||
<Divider/>
|
||||
<Divider />
|
||||
|
||||
<ListItem>
|
||||
<ListItemIcon>
|
||||
<UserNinjaIcon/>
|
||||
<UserNinjaIcon />
|
||||
</ListItemIcon>
|
||||
|
||||
<ListItemText>
|
||||
<Tooltip placement="top" enterTouchDelay={0} title={t("Stealth lightning invoices do not contain details about the trade except an order reference. Enable this setting if you don't want to disclose details to a custodial lightning wallet.")}>
|
||||
<Tooltip
|
||||
placement='top'
|
||||
enterTouchDelay={0}
|
||||
title={t(
|
||||
"Stealth lightning invoices do not contain details about the trade except an order reference. Enable this setting if you don't want to disclose details to a custodial lightning wallet.",
|
||||
)}
|
||||
>
|
||||
<Grid item>
|
||||
<FormControlLabel
|
||||
labelPlacement="end"
|
||||
label={t("Use stealth invoices")}
|
||||
labelPlacement='end'
|
||||
label={t('Use stealth invoices')}
|
||||
control={
|
||||
<Switch
|
||||
checked={stealthInvoices}
|
||||
onChange={() => handleSetStealthInvoice(!stealthInvoices)
|
||||
}
|
||||
onChange={() => handleSetStealthInvoice(!stealthInvoices)}
|
||||
/>
|
||||
}
|
||||
/>
|
||||
@ -258,21 +269,19 @@ const ProfileDialog = ({
|
||||
|
||||
<ListItem>
|
||||
<ListItemIcon>
|
||||
<BitcoinIcon/>
|
||||
<BitcoinIcon />
|
||||
</ListItemIcon>
|
||||
|
||||
<ListItemText>
|
||||
<FormControlLabel
|
||||
labelPlacement="end"
|
||||
labelPlacement='end'
|
||||
label={
|
||||
<div style={{display:'flex', alignItems:'center'}}>
|
||||
{t("Rewards and compensations")}
|
||||
</div>}
|
||||
<div style={{ display: 'flex', alignItems: 'center' }}>
|
||||
{t('Rewards and compensations')}
|
||||
</div>
|
||||
}
|
||||
control={
|
||||
<Switch
|
||||
checked={showRewards}
|
||||
onChange={()=> setShowRewards(!showRewards)}
|
||||
/>
|
||||
<Switch checked={showRewards} onChange={() => setShowRewards(!showRewards)} />
|
||||
}
|
||||
/>
|
||||
</ListItemText>
|
||||
@ -285,24 +294,25 @@ const ProfileDialog = ({
|
||||
<PersonAddAltIcon />
|
||||
</ListItemIcon>
|
||||
|
||||
<ListItemText secondary={t("Share to earn 100 Sats per trade")}>
|
||||
<ListItemText secondary={t('Share to earn 100 Sats per trade')}>
|
||||
<TextField
|
||||
label={t("Your referral link")}
|
||||
value={host+'/ref/'+referralCode}
|
||||
size="small"
|
||||
label={t('Your referral link')}
|
||||
value={host + '/ref/' + referralCode}
|
||||
size='small'
|
||||
InputProps={{
|
||||
endAdornment:
|
||||
<Tooltip
|
||||
disableHoverListener
|
||||
enterTouchDelay={0}
|
||||
title={t("Copied!") || ""}
|
||||
>
|
||||
<IconButton onClick={copyReferralCodeHandler}>
|
||||
<ContentCopy />
|
||||
</IconButton>
|
||||
</Tooltip>,
|
||||
}}
|
||||
/>
|
||||
endAdornment: (
|
||||
<Tooltip
|
||||
disableHoverListener
|
||||
enterTouchDelay={0}
|
||||
title={t('Copied!') || ''}
|
||||
>
|
||||
<IconButton onClick={copyReferralCodeHandler}>
|
||||
<ContentCopy />
|
||||
</IconButton>
|
||||
</Tooltip>
|
||||
),
|
||||
}}
|
||||
/>
|
||||
</ListItemText>
|
||||
</ListItem>
|
||||
|
||||
@ -312,7 +322,7 @@ const ProfileDialog = ({
|
||||
</ListItemIcon>
|
||||
|
||||
{!openClaimRewards ? (
|
||||
<ListItemText secondary={t("Your earned rewards")}>
|
||||
<ListItemText secondary={t('Your earned rewards')}>
|
||||
<Grid container>
|
||||
<Grid item xs={9}>
|
||||
<Typography>{`${earnedRewards} Sats`}</Typography>
|
||||
@ -322,54 +332,56 @@ const ProfileDialog = ({
|
||||
<Button
|
||||
disabled={earnedRewards === 0 ? true : false}
|
||||
onClick={() => setOpenClaimRewards(true)}
|
||||
variant="contained"
|
||||
size="small"
|
||||
variant='contained'
|
||||
size='small'
|
||||
>
|
||||
{t("Claim")}
|
||||
{t('Claim')}
|
||||
</Button>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</ListItemText>
|
||||
) : (
|
||||
<form noValidate style={{maxWidth: 270}}>
|
||||
<Grid container style={{ display: "flex", alignItems: "stretch"}}>
|
||||
<Grid item style={{ display: "flex", maxWidth:160}} >
|
||||
<form noValidate style={{ maxWidth: 270 }}>
|
||||
<Grid container style={{ display: 'flex', alignItems: 'stretch' }}>
|
||||
<Grid item style={{ display: 'flex', maxWidth: 160 }}>
|
||||
<TextField
|
||||
error={badInvoice ? true : false}
|
||||
helperText={badInvoice ? badInvoice : "" }
|
||||
label={t("Invoice for {{amountSats}} Sats", { amountSats: earnedRewards })}
|
||||
size="small"
|
||||
helperText={badInvoice ? badInvoice : ''}
|
||||
label={t('Invoice for {{amountSats}} Sats', {
|
||||
amountSats: earnedRewards,
|
||||
})}
|
||||
size='small'
|
||||
value={rewardInvoice}
|
||||
onChange={e => {
|
||||
onChange={(e) => {
|
||||
setRewardInvoice(e.target.value);
|
||||
}}
|
||||
/>
|
||||
</Grid>
|
||||
<Grid item alignItems="stretch" style={{ display: "flex", maxWidth:80}}>
|
||||
<Grid item alignItems='stretch' style={{ display: 'flex', maxWidth: 80 }}>
|
||||
<Button
|
||||
sx={{maxHeight:38}}
|
||||
sx={{ maxHeight: 38 }}
|
||||
onClick={(e) => handleSubmitInvoiceClicked(e, rewardInvoice)}
|
||||
variant="contained"
|
||||
color="primary"
|
||||
size="small"
|
||||
type="submit"
|
||||
variant='contained'
|
||||
color='primary'
|
||||
size='small'
|
||||
type='submit'
|
||||
>
|
||||
{t("Submit")}
|
||||
{t('Submit')}
|
||||
</Button>
|
||||
</Grid>
|
||||
</Grid>
|
||||
{weblnEnabled && (
|
||||
<Grid container style={{ display: "flex", alignItems: "stretch"}}>
|
||||
<Grid item alignItems="stretch" style={{ display: "flex", maxWidth:240}}>
|
||||
<Grid container style={{ display: 'flex', alignItems: 'stretch' }}>
|
||||
<Grid item alignItems='stretch' style={{ display: 'flex', maxWidth: 240 }}>
|
||||
<Button
|
||||
sx={{maxHeight:38, minWidth: 230}}
|
||||
sx={{ maxHeight: 38, minWidth: 230 }}
|
||||
onClick={(e) => handleWeblnInvoiceClicked(e)}
|
||||
variant="contained"
|
||||
color="primary"
|
||||
size="small"
|
||||
type="submit"
|
||||
variant='contained'
|
||||
color='primary'
|
||||
size='small'
|
||||
type='submit'
|
||||
>
|
||||
{t("Generate with Webln")}
|
||||
{t('Generate with Webln')}
|
||||
</Button>
|
||||
</Grid>
|
||||
</Grid>
|
||||
@ -379,15 +391,15 @@ const ProfileDialog = ({
|
||||
</ListItem>
|
||||
|
||||
{showRewardsSpinner && (
|
||||
<div style={{display: "flex", justifyContent: "center"}}>
|
||||
<div style={{ display: 'flex', justifyContent: 'center' }}>
|
||||
<CircularProgress />
|
||||
</div>
|
||||
)}
|
||||
|
||||
{withdrawn && (
|
||||
<div style={{display: "flex", justifyContent: "center"}}>
|
||||
<Typography color="primary" variant="body2">
|
||||
<b>{t("There it goes, thank you!🥇")}</b>
|
||||
<div style={{ display: 'flex', justifyContent: 'center' }}>
|
||||
<Typography color='primary' variant='body2'>
|
||||
<b>{t('There it goes, thank you!🥇')}</b>
|
||||
</Typography>
|
||||
</div>
|
||||
)}
|
||||
|
@ -1,5 +1,5 @@
|
||||
import React from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import React from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
import {
|
||||
Dialog,
|
||||
@ -11,19 +11,19 @@ import {
|
||||
ListItem,
|
||||
ListItemIcon,
|
||||
Typography,
|
||||
} from "@mui/material";
|
||||
} from '@mui/material';
|
||||
|
||||
import BoltIcon from "@mui/icons-material/Bolt";
|
||||
import PublicIcon from "@mui/icons-material/Public";
|
||||
import DnsIcon from "@mui/icons-material/Dns";
|
||||
import WebIcon from "@mui/icons-material/Web";
|
||||
import FavoriteIcon from "@mui/icons-material/Favorite";
|
||||
import GitHubIcon from "@mui/icons-material/GitHub";
|
||||
import EqualizerIcon from "@mui/icons-material/Equalizer";
|
||||
import BoltIcon from '@mui/icons-material/Bolt';
|
||||
import PublicIcon from '@mui/icons-material/Public';
|
||||
import DnsIcon from '@mui/icons-material/Dns';
|
||||
import WebIcon from '@mui/icons-material/Web';
|
||||
import FavoriteIcon from '@mui/icons-material/Favorite';
|
||||
import GitHubIcon from '@mui/icons-material/GitHub';
|
||||
import EqualizerIcon from '@mui/icons-material/Equalizer';
|
||||
|
||||
import { AmbossIcon, BitcoinSignIcon } from "../Icons";
|
||||
import { AmbossIcon, BitcoinSignIcon } from '../Icons';
|
||||
|
||||
import { pn } from "../../utils/prettyNumbers";
|
||||
import { pn } from '../../utils/prettyNumbers';
|
||||
|
||||
type Props = {
|
||||
isOpen: boolean;
|
||||
@ -37,7 +37,7 @@ type Props = {
|
||||
robosatsRunningCommitHash: string;
|
||||
lastDayVolume: number;
|
||||
lifetimeVolume: number;
|
||||
}
|
||||
};
|
||||
|
||||
const StatsDialog = ({
|
||||
isOpen,
|
||||
@ -58,11 +58,13 @@ const StatsDialog = ({
|
||||
<Dialog
|
||||
open={isOpen}
|
||||
onClose={handleClickCloseStatsForNerds}
|
||||
aria-labelledby="stats-for-nerds-dialog-title"
|
||||
aria-describedby="stats-for-nerds-description"
|
||||
aria-labelledby='stats-for-nerds-dialog-title'
|
||||
aria-describedby='stats-for-nerds-description'
|
||||
>
|
||||
<DialogContent>
|
||||
<Typography component="h5" variant="h5">{t("Stats For Nerds")}</Typography>
|
||||
<Typography component='h5' variant='h5'>
|
||||
{t('Stats For Nerds')}
|
||||
</Typography>
|
||||
|
||||
<List dense>
|
||||
<Divider />
|
||||
@ -71,21 +73,21 @@ const StatsDialog = ({
|
||||
<ListItemIcon>
|
||||
<BoltIcon />
|
||||
</ListItemIcon>
|
||||
<ListItemText primary={lndVersion} secondary={t("LND version")} />
|
||||
<ListItemText primary={lndVersion} secondary={t('LND version')} />
|
||||
</ListItem>
|
||||
|
||||
<Divider />
|
||||
|
||||
{network === "testnet" ? (
|
||||
{network === 'testnet' ? (
|
||||
<ListItem>
|
||||
<ListItemIcon>
|
||||
<DnsIcon />
|
||||
</ListItemIcon>
|
||||
<ListItemText secondary={nodeAlias}>
|
||||
<Link
|
||||
target="_blank"
|
||||
target='_blank'
|
||||
href={`https://1ml.com/testnet/node/${nodeId}`}
|
||||
rel="noreferrer"
|
||||
rel='noreferrer'
|
||||
>
|
||||
{`${nodeId.slice(0, 12)}... (1ML)`}
|
||||
</Link>
|
||||
@ -97,11 +99,7 @@ const StatsDialog = ({
|
||||
<AmbossIcon />
|
||||
</ListItemIcon>
|
||||
<ListItemText secondary={nodeAlias}>
|
||||
<Link
|
||||
target="_blank"
|
||||
href={`https://amboss.space/node/${nodeId}`}
|
||||
rel="noreferrer"
|
||||
>
|
||||
<Link target='_blank' href={`https://amboss.space/node/${nodeId}`} rel='noreferrer'>
|
||||
{`${nodeId.slice(0, 12)}... (AMBOSS)`}
|
||||
</Link>
|
||||
</ListItemText>
|
||||
@ -115,11 +113,7 @@ const StatsDialog = ({
|
||||
<WebIcon />
|
||||
</ListItemIcon>
|
||||
<ListItemText secondary={alternativeName}>
|
||||
<Link
|
||||
target="_blank"
|
||||
href={`http://${alternativeSite}`}
|
||||
rel="noreferrer"
|
||||
>
|
||||
<Link target='_blank' href={`http://${alternativeSite}`} rel='noreferrer'>
|
||||
{`${alternativeSite.slice(0, 12)}...onion`}
|
||||
</Link>
|
||||
</ListItemText>
|
||||
@ -131,11 +125,11 @@ const StatsDialog = ({
|
||||
<ListItemIcon>
|
||||
<GitHubIcon />
|
||||
</ListItemIcon>
|
||||
<ListItemText secondary={t("Currently running commit hash")}>
|
||||
<ListItemText secondary={t('Currently running commit hash')}>
|
||||
<Link
|
||||
target="_blank"
|
||||
target='_blank'
|
||||
href={`https://github.com/Reckless-Satoshi/robosats/tree/${robosatsRunningCommitHash}`}
|
||||
rel="noreferrer"
|
||||
rel='noreferrer'
|
||||
>
|
||||
{`${robosatsRunningCommitHash.slice(0, 12)}...`}
|
||||
</Link>
|
||||
@ -148,10 +142,17 @@ const StatsDialog = ({
|
||||
<ListItemIcon>
|
||||
<EqualizerIcon />
|
||||
</ListItemIcon>
|
||||
<ListItemText secondary={t("24h contracted volume")}>
|
||||
<div style={{ cursor: "pointer", display: "flex", alignItems: "center", flexWrap: "wrap" }}>
|
||||
<ListItemText secondary={t('24h contracted volume')}>
|
||||
<div
|
||||
style={{
|
||||
cursor: 'pointer',
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
flexWrap: 'wrap',
|
||||
}}
|
||||
>
|
||||
{pn(lastDayVolume)}
|
||||
<BitcoinSignIcon sx={{ width: 14,height: 14 }} color={"text.secondary"} />
|
||||
<BitcoinSignIcon sx={{ width: 14, height: 14 }} color={'text.secondary'} />
|
||||
</div>
|
||||
</ListItemText>
|
||||
</ListItem>
|
||||
@ -162,10 +163,17 @@ const StatsDialog = ({
|
||||
<ListItemIcon>
|
||||
<EqualizerIcon />
|
||||
</ListItemIcon>
|
||||
<ListItemText secondary={t("Lifetime contracted volume")}>
|
||||
<div style={{ cursor: "pointer", display: "flex",alignItems: "center", flexWrap: "wrap" }}>
|
||||
<ListItemText secondary={t('Lifetime contracted volume')}>
|
||||
<div
|
||||
style={{
|
||||
cursor: 'pointer',
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
flexWrap: 'wrap',
|
||||
}}
|
||||
>
|
||||
{pn(lifetimeVolume)}
|
||||
<BitcoinSignIcon sx={{ width: 14, height: 14 }} color={"text.secondary"} />
|
||||
<BitcoinSignIcon sx={{ width: 14, height: 14 }} color={'text.secondary'} />
|
||||
</div>
|
||||
</ListItemText>
|
||||
</ListItem>
|
||||
@ -177,14 +185,21 @@ const StatsDialog = ({
|
||||
</ListItemIcon>
|
||||
<ListItemText
|
||||
primary={
|
||||
<div style={{ display: "flex", alignItems: "center", justifyContent: "left", flexWrap: "wrap" }}>
|
||||
<span>{`${t("Made with")} `}</span>
|
||||
<FavoriteIcon sx={{ color: "#ff0000", height: "22px", width: "22px" }} />
|
||||
<span>{` ${t("and")} `}</span>
|
||||
<BoltIcon sx={{ color: "#fcba03", height: "23px",width: "23px" }} />
|
||||
<div
|
||||
style={{
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'left',
|
||||
flexWrap: 'wrap',
|
||||
}}
|
||||
>
|
||||
<span>{`${t('Made with')} `}</span>
|
||||
<FavoriteIcon sx={{ color: '#ff0000', height: '22px', width: '22px' }} />
|
||||
<span>{` ${t('and')} `}</span>
|
||||
<BoltIcon sx={{ color: '#fcba03', height: '23px', width: '23px' }} />
|
||||
</div>
|
||||
}
|
||||
secondary={t("... somewhere on Earth!")}
|
||||
secondary={t('... somewhere on Earth!')}
|
||||
/>
|
||||
</ListItem>
|
||||
</List>
|
||||
|
@ -1,19 +1,19 @@
|
||||
import React from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import React from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import {
|
||||
Dialog,
|
||||
DialogTitle,
|
||||
Tooltip,
|
||||
Tooltip,
|
||||
IconButton,
|
||||
TextField,
|
||||
DialogActions,
|
||||
DialogActions,
|
||||
DialogContent,
|
||||
DialogContentText,
|
||||
Button,
|
||||
Button,
|
||||
Grid,
|
||||
} from "@mui/material"
|
||||
import { getCookie } from "../../utils/cookies";
|
||||
import ContentCopy from "@mui/icons-material/ContentCopy";
|
||||
} from '@mui/material';
|
||||
import { getCookie } from '../../utils/cookies';
|
||||
import ContentCopy from '@mui/icons-material/ContentCopy';
|
||||
|
||||
type Props = {
|
||||
open: boolean;
|
||||
@ -22,10 +22,10 @@ type Props = {
|
||||
onClickCopy: () => void;
|
||||
onClickBack: () => void;
|
||||
onClickDone: () => void;
|
||||
}
|
||||
};
|
||||
|
||||
const StoreTokenDialog = ({
|
||||
open,
|
||||
open,
|
||||
onClose,
|
||||
copyIconColor,
|
||||
onClickCopy,
|
||||
@ -35,46 +35,45 @@ const StoreTokenDialog = ({
|
||||
const { t } = useTranslation();
|
||||
|
||||
return (
|
||||
<Dialog
|
||||
open={open}
|
||||
onClose={onClose}
|
||||
>
|
||||
<DialogTitle >
|
||||
{t("Store your robot token")}
|
||||
</DialogTitle>
|
||||
<Dialog open={open} onClose={onClose}>
|
||||
<DialogTitle>{t('Store your robot token')}</DialogTitle>
|
||||
|
||||
<DialogContent>
|
||||
<DialogContentText>
|
||||
{t("You might need to recover your robot avatar in the future: store it safely. You can simply copy it into another application.")}
|
||||
{t(
|
||||
'You might need to recover your robot avatar in the future: store it safely. You can simply copy it into another application.',
|
||||
)}
|
||||
</DialogContentText>
|
||||
<br/>
|
||||
<Grid align="center">
|
||||
<br />
|
||||
<Grid align='center'>
|
||||
<TextField
|
||||
sx={{width:"100%", maxWidth:"550px"}}
|
||||
sx={{ width: '100%', maxWidth: '550px' }}
|
||||
disabled
|
||||
label={t("Back it up!")}
|
||||
value={getCookie("robot_token")}
|
||||
label={t('Back it up!')}
|
||||
value={getCookie('robot_token')}
|
||||
variant='filled'
|
||||
size='small'
|
||||
InputProps={{
|
||||
endAdornment:
|
||||
<Tooltip disableHoverListener enterTouchDelay={0} title={t("Copied!")}>
|
||||
<IconButton onClick={onClickCopy}>
|
||||
<ContentCopy color={copyIconColor}/>
|
||||
</IconButton>
|
||||
</Tooltip>,
|
||||
}}
|
||||
/>
|
||||
endAdornment: (
|
||||
<Tooltip disableHoverListener enterTouchDelay={0} title={t('Copied!')}>
|
||||
<IconButton onClick={onClickCopy}>
|
||||
<ContentCopy color={copyIconColor} />
|
||||
</IconButton>
|
||||
</Tooltip>
|
||||
),
|
||||
}}
|
||||
/>
|
||||
</Grid>
|
||||
</DialogContent>
|
||||
|
||||
<DialogActions>
|
||||
<Button onClick={onClickBack} autoFocus>{t("Go back")}</Button>
|
||||
<Button onClick={onClickDone}>{t("Done")}</Button>
|
||||
<Button onClick={onClickBack} autoFocus>
|
||||
{t('Go back')}
|
||||
</Button>
|
||||
<Button onClick={onClickDone}>{t('Done')}</Button>
|
||||
</DialogActions>
|
||||
|
||||
</Dialog>
|
||||
)
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
export default StoreTokenDialog;
|
||||
|
@ -1,10 +1,9 @@
|
||||
export { default as AuditPGPDialog } from "./AuditPGP";
|
||||
export { default as CommunityDialog } from "./Community";
|
||||
export { default as InfoDialog } from "./Info";
|
||||
export { default as LearnDialog } from "./Learn";
|
||||
export { default as NoRobotDialog } from "./NoRobot";
|
||||
export { default as StoreTokenDialog } from "./StoreToken";
|
||||
export { default as ExchangeSummaryDialog } from "./ExchangeSummary";
|
||||
export { default as ProfileDialog } from "./Profile";
|
||||
export { default as StatsDialog } from "./Stats";
|
||||
|
||||
export { default as AuditPGPDialog } from './AuditPGP';
|
||||
export { default as CommunityDialog } from './Community';
|
||||
export { default as InfoDialog } from './Info';
|
||||
export { default as LearnDialog } from './Learn';
|
||||
export { default as NoRobotDialog } from './NoRobot';
|
||||
export { default as StoreTokenDialog } from './StoreToken';
|
||||
export { default as ExchangeSummaryDialog } from './ExchangeSummary';
|
||||
export { default as ProfileDialog } from './Profile';
|
||||
export { default as StatsDialog } from './Stats';
|
||||
|
@ -1,17 +1,30 @@
|
||||
import React, { Component } from 'react';
|
||||
import { withTranslation } from "react-i18next";
|
||||
import {Button, IconButton, Badge, Tooltip, TextField, Grid, Container, Card, CardHeader, Paper, Avatar, Typography} from "@mui/material";
|
||||
import { withTranslation } from 'react-i18next';
|
||||
import {
|
||||
Button,
|
||||
IconButton,
|
||||
Badge,
|
||||
Tooltip,
|
||||
TextField,
|
||||
Grid,
|
||||
Container,
|
||||
Card,
|
||||
CardHeader,
|
||||
Paper,
|
||||
Avatar,
|
||||
Typography,
|
||||
} from '@mui/material';
|
||||
import ReconnectingWebSocket from 'reconnecting-websocket';
|
||||
import { encryptMessage , decryptMessage} from "../utils/pgp";
|
||||
import { getCookie } from "../utils/cookies";
|
||||
import { saveAsJson } from "../utils/saveFile";
|
||||
import { copyToClipboard } from "../utils/clipboard";
|
||||
import { AuditPGPDialog } from "./Dialogs"
|
||||
import { encryptMessage, decryptMessage } from '../utils/pgp';
|
||||
import { getCookie } from '../utils/cookies';
|
||||
import { saveAsJson } from '../utils/saveFile';
|
||||
import { copyToClipboard } from '../utils/clipboard';
|
||||
import { AuditPGPDialog } from './Dialogs';
|
||||
|
||||
// Icons
|
||||
import CheckIcon from '@mui/icons-material/Check';
|
||||
import CloseIcon from '@mui/icons-material/Close';
|
||||
import ContentCopy from "@mui/icons-material/ContentCopy";
|
||||
import ContentCopy from '@mui/icons-material/ContentCopy';
|
||||
import VisibilityIcon from '@mui/icons-material/Visibility';
|
||||
import CircularProgress from '@mui/material/CircularProgress';
|
||||
import KeyIcon from '@mui/icons-material/Key';
|
||||
@ -23,120 +36,157 @@ class Chat extends Component {
|
||||
}
|
||||
|
||||
state = {
|
||||
own_pub_key: getCookie('pub_key').split('\\').join('\n'),
|
||||
own_pub_key: getCookie('pub_key').split('\\').join('\n'),
|
||||
own_enc_priv_key: getCookie('enc_priv_key').split('\\').join('\n'),
|
||||
peer_pub_key: null,
|
||||
token: getCookie('robot_token'),
|
||||
messages: [],
|
||||
value:'',
|
||||
value: '',
|
||||
connected: false,
|
||||
peer_connected: false,
|
||||
audit: false,
|
||||
showPGP: new Array,
|
||||
showPGP: new Array(),
|
||||
waitingEcho: false,
|
||||
lastSent: '---BLANK---',
|
||||
latestIndex: 0,
|
||||
scrollNow:false,
|
||||
scrollNow: false,
|
||||
};
|
||||
|
||||
rws = new ReconnectingWebSocket('ws://' + window.location.host + '/ws/chat/' + this.props.orderId + '/', [], {connectionTimeout: 15000});
|
||||
|
||||
rws = new ReconnectingWebSocket(
|
||||
'ws://' + window.location.host + '/ws/chat/' + this.props.orderId + '/',
|
||||
[],
|
||||
{ connectionTimeout: 15000 },
|
||||
);
|
||||
|
||||
componentDidMount() {
|
||||
this.rws.addEventListener('open', () => {
|
||||
console.log('Connected!');
|
||||
this.setState({connected: true});
|
||||
this.rws.send(JSON.stringify({
|
||||
type: "message",
|
||||
message: this.state.own_pub_key,
|
||||
nick: this.props.ur_nick,
|
||||
}));
|
||||
this.setState({ connected: true });
|
||||
this.rws.send(
|
||||
JSON.stringify({
|
||||
type: 'message',
|
||||
message: this.state.own_pub_key,
|
||||
nick: this.props.ur_nick,
|
||||
}),
|
||||
);
|
||||
});
|
||||
|
||||
this.rws.addEventListener('message', (message) => {
|
||||
|
||||
const dataFromServer = JSON.parse(message.data);
|
||||
console.log('Got reply!', dataFromServer.type);
|
||||
console.log('PGP message index', dataFromServer.index, ' latestIndex ',this.state.latestIndex);
|
||||
if (dataFromServer){
|
||||
console.log(dataFromServer)
|
||||
this.setState({peer_connected: dataFromServer.peer_connected})
|
||||
console.log(
|
||||
'PGP message index',
|
||||
dataFromServer.index,
|
||||
' latestIndex ',
|
||||
this.state.latestIndex,
|
||||
);
|
||||
if (dataFromServer) {
|
||||
console.log(dataFromServer);
|
||||
this.setState({ peer_connected: dataFromServer.peer_connected });
|
||||
|
||||
// If we receive our own key on a message
|
||||
if (dataFromServer.message == this.state.own_pub_key){console.log("OWN PUB KEY RECEIVED!!")}
|
||||
if (dataFromServer.message == this.state.own_pub_key) {
|
||||
console.log('OWN PUB KEY RECEIVED!!');
|
||||
}
|
||||
|
||||
// If we receive a public key other than ours (our peer key!)
|
||||
if (dataFromServer.message.substring(0,36) == `-----BEGIN PGP PUBLIC KEY BLOCK-----` && dataFromServer.message != this.state.own_pub_key) {
|
||||
if (dataFromServer.message == this.state.peer_pub_key){
|
||||
console.log("PEER HAS RECONNECTED USING HIS PREVIOUSLY KNOWN PUBKEY")
|
||||
} else if (dataFromServer.message != this.state.peer_pub_key & this.state.peer_pub_key != null){
|
||||
console.log("PEER PUBKEY HAS CHANGED")
|
||||
if (
|
||||
dataFromServer.message.substring(0, 36) == `-----BEGIN PGP PUBLIC KEY BLOCK-----` &&
|
||||
dataFromServer.message != this.state.own_pub_key
|
||||
) {
|
||||
if (dataFromServer.message == this.state.peer_pub_key) {
|
||||
console.log('PEER HAS RECONNECTED USING HIS PREVIOUSLY KNOWN PUBKEY');
|
||||
} else if (
|
||||
(dataFromServer.message != this.state.peer_pub_key) &
|
||||
(this.state.peer_pub_key != null)
|
||||
) {
|
||||
console.log('PEER PUBKEY HAS CHANGED');
|
||||
}
|
||||
console.log("PEER PUBKEY RECEIVED!!")
|
||||
this.setState({peer_pub_key:dataFromServer.message})
|
||||
console.log('PEER PUBKEY RECEIVED!!');
|
||||
this.setState({ peer_pub_key: dataFromServer.message });
|
||||
|
||||
// After receiving the peer pubkey we ask the server for the historic messages if any
|
||||
this.rws.send(JSON.stringify({
|
||||
type: "message",
|
||||
this.rws.send(
|
||||
JSON.stringify({
|
||||
type: 'message',
|
||||
message: `-----SERVE HISTORY-----`,
|
||||
nick: this.props.ur_nick,
|
||||
}))
|
||||
} else
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
// If we receive an encrypted message
|
||||
if (dataFromServer.message.substring(0,27) == `-----BEGIN PGP MESSAGE-----` && dataFromServer.index > this.state.latestIndex){
|
||||
|
||||
else if (
|
||||
dataFromServer.message.substring(0, 27) == `-----BEGIN PGP MESSAGE-----` &&
|
||||
dataFromServer.index > this.state.latestIndex
|
||||
) {
|
||||
decryptMessage(
|
||||
dataFromServer.message.split('\\').join('\n'),
|
||||
dataFromServer.user_nick == this.props.ur_nick ? this.state.own_pub_key : this.state.peer_pub_key,
|
||||
this.state.own_enc_priv_key,
|
||||
this.state.token)
|
||||
.then((decryptedData) =>
|
||||
this.setState((state) =>
|
||||
({
|
||||
dataFromServer.message.split('\\').join('\n'),
|
||||
dataFromServer.user_nick == this.props.ur_nick
|
||||
? this.state.own_pub_key
|
||||
: this.state.peer_pub_key,
|
||||
this.state.own_enc_priv_key,
|
||||
this.state.token,
|
||||
).then((decryptedData) =>
|
||||
this.setState((state) => ({
|
||||
scrollNow: true,
|
||||
waitingEcho: this.state.waitingEcho == true ? (decryptedData.decryptedMessage == this.state.lastSent ? false: true ) : false,
|
||||
lastSent: decryptedData.decryptedMessage == this.state.lastSent ? '----BLANK----': this.state.lastSent,
|
||||
latestIndex: dataFromServer.index > this.state.latestIndex ? dataFromServer.index : this.state.latestIndex,
|
||||
messages: [...state.messages,
|
||||
{
|
||||
index: dataFromServer.index,
|
||||
encryptedMessage: dataFromServer.message.split('\\').join('\n'),
|
||||
plainTextMessage: decryptedData.decryptedMessage,
|
||||
validSignature: decryptedData.validSignature,
|
||||
userNick: dataFromServer.user_nick,
|
||||
time: dataFromServer.time
|
||||
}].sort(function(a,b) {
|
||||
waitingEcho:
|
||||
this.state.waitingEcho == true
|
||||
? decryptedData.decryptedMessage == this.state.lastSent
|
||||
? false
|
||||
: true
|
||||
: false,
|
||||
lastSent:
|
||||
decryptedData.decryptedMessage == this.state.lastSent
|
||||
? '----BLANK----'
|
||||
: this.state.lastSent,
|
||||
latestIndex:
|
||||
dataFromServer.index > this.state.latestIndex
|
||||
? dataFromServer.index
|
||||
: this.state.latestIndex,
|
||||
messages: [
|
||||
...state.messages,
|
||||
{
|
||||
index: dataFromServer.index,
|
||||
encryptedMessage: dataFromServer.message.split('\\').join('\n'),
|
||||
plainTextMessage: decryptedData.decryptedMessage,
|
||||
validSignature: decryptedData.validSignature,
|
||||
userNick: dataFromServer.user_nick,
|
||||
time: dataFromServer.time,
|
||||
},
|
||||
].sort(function (a, b) {
|
||||
// order the message array by their index (increasing)
|
||||
return a.index - b.index
|
||||
return a.index - b.index;
|
||||
}),
|
||||
})
|
||||
));
|
||||
|
||||
} else
|
||||
})),
|
||||
);
|
||||
}
|
||||
|
||||
// We allow plaintext communication. The user must write # to start
|
||||
// If we receive an plaintext message
|
||||
if (dataFromServer.message.substring(0,1) == "#"){
|
||||
console.log("Got plaintext message", dataFromServer.message)
|
||||
this.setState((state) =>
|
||||
({
|
||||
scrollNow: true,
|
||||
messages: [...state.messages,
|
||||
{
|
||||
else if (dataFromServer.message.substring(0, 1) == '#') {
|
||||
console.log('Got plaintext message', dataFromServer.message);
|
||||
this.setState((state) => ({
|
||||
scrollNow: true,
|
||||
messages: [
|
||||
...state.messages,
|
||||
{
|
||||
index: this.state.latestIndex + 0.001,
|
||||
encryptedMessage: dataFromServer.message,
|
||||
plainTextMessage: dataFromServer.message,
|
||||
validSignature: false,
|
||||
validSignature: false,
|
||||
userNick: dataFromServer.user_nick,
|
||||
time: (new Date).toString(),
|
||||
}]}));
|
||||
}
|
||||
time: new Date().toString(),
|
||||
},
|
||||
],
|
||||
}));
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
this.rws.addEventListener('close', () => {
|
||||
console.log('Socket is closed. Reconnect will be attempted');
|
||||
this.setState({connected: false});
|
||||
this.setState({ connected: false });
|
||||
});
|
||||
|
||||
this.rws.addEventListener('error', () => {
|
||||
@ -145,216 +195,401 @@ class Chat extends Component {
|
||||
}
|
||||
|
||||
componentDidUpdate() {
|
||||
|
||||
// Only fire the scroll and audio when the reason for Update is a new message
|
||||
if (this.state.scrollNow){
|
||||
const audio = new Audio(`/static/assets/sounds/chat-open.mp3`)
|
||||
if (this.state.scrollNow) {
|
||||
const audio = new Audio(`/static/assets/sounds/chat-open.mp3`);
|
||||
audio.play();
|
||||
this.scrollToBottom();
|
||||
this.setState({scrollNow:false});
|
||||
this.setState({ scrollNow: false });
|
||||
}
|
||||
}
|
||||
|
||||
scrollToBottom = () => {
|
||||
this.messagesEnd.scrollIntoView({ behavior: "smooth" });
|
||||
}
|
||||
this.messagesEnd.scrollIntoView({ behavior: 'smooth' });
|
||||
};
|
||||
|
||||
onButtonClicked = (e) => {
|
||||
// If input string contains token. Do not set message
|
||||
if(this.state.value.indexOf(this.state.token) !== -1){
|
||||
alert(`Aye! You just sent your own robot token to your peer in chat, that's a catastrophic idea! So bad your message was blocked.`)
|
||||
this.setState({value: ""});
|
||||
if (this.state.value.indexOf(this.state.token) !== -1) {
|
||||
alert(
|
||||
`Aye! You just sent your own robot token to your peer in chat, that's a catastrophic idea! So bad your message was blocked.`,
|
||||
);
|
||||
this.setState({ value: '' });
|
||||
}
|
||||
|
||||
// If input string contains '#' send unencrypted and unlogged message
|
||||
else if(this.state.value.substring(0,1)=='#'){
|
||||
this.rws.send(JSON.stringify({
|
||||
type: "message",
|
||||
else if (this.state.value.substring(0, 1) == '#') {
|
||||
this.rws.send(
|
||||
JSON.stringify({
|
||||
type: 'message',
|
||||
message: this.state.value,
|
||||
nick: this.props.ur_nick,
|
||||
}));
|
||||
this.setState({value: ""});
|
||||
}),
|
||||
);
|
||||
this.setState({ value: '' });
|
||||
}
|
||||
|
||||
// Else if message is not empty send message
|
||||
else if(this.state.value!=''){
|
||||
this.setState({value: "", waitingEcho: true, lastSent:this.state.value})
|
||||
encryptMessage(this.state.value, this.state.own_pub_key, this.state.peer_pub_key, this.state.own_enc_priv_key, this.state.token)
|
||||
.then((encryptedMessage) =>
|
||||
console.log("Sending Encrypted MESSAGE", encryptedMessage) &
|
||||
this.rws.send(JSON.stringify({
|
||||
type: "message",
|
||||
message: encryptedMessage.split('\n').join('\\'),
|
||||
nick: this.props.ur_nick,
|
||||
})
|
||||
)
|
||||
|
||||
// Else if message is not empty send message
|
||||
else if (this.state.value != '') {
|
||||
this.setState({ value: '', waitingEcho: true, lastSent: this.state.value });
|
||||
encryptMessage(
|
||||
this.state.value,
|
||||
this.state.own_pub_key,
|
||||
this.state.peer_pub_key,
|
||||
this.state.own_enc_priv_key,
|
||||
this.state.token,
|
||||
).then(
|
||||
(encryptedMessage) =>
|
||||
console.log('Sending Encrypted MESSAGE', encryptedMessage) &
|
||||
this.rws.send(
|
||||
JSON.stringify({
|
||||
type: 'message',
|
||||
message: encryptedMessage.split('\n').join('\\'),
|
||||
nick: this.props.ur_nick,
|
||||
}),
|
||||
),
|
||||
);
|
||||
}
|
||||
e.preventDefault();
|
||||
}
|
||||
};
|
||||
|
||||
createJsonFile = () => {
|
||||
return ({
|
||||
"credentials": {
|
||||
"own_public_key": this.state.own_pub_key,
|
||||
"peer_public_key":this.state.peer_pub_key,
|
||||
"encrypted_private_key":this.state.own_enc_priv_key,
|
||||
"passphrase":this.state.token},
|
||||
"messages": this.state.messages,
|
||||
})
|
||||
}
|
||||
return {
|
||||
credentials: {
|
||||
own_public_key: this.state.own_pub_key,
|
||||
peer_public_key: this.state.peer_pub_key,
|
||||
encrypted_private_key: this.state.own_enc_priv_key,
|
||||
passphrase: this.state.token,
|
||||
},
|
||||
messages: this.state.messages,
|
||||
};
|
||||
};
|
||||
|
||||
messageCard = (props) => {
|
||||
const { t } = this.props;
|
||||
return(
|
||||
<Card elevation={5} align="left" >
|
||||
<CardHeader sx={{color: '#333333'}}
|
||||
return (
|
||||
<Card elevation={5} align='left'>
|
||||
<CardHeader
|
||||
sx={{ color: '#333333' }}
|
||||
avatar={
|
||||
<Badge variant="dot" overlap="circular" badgeContent="" color={props.userConnected ? "success" : "error"}>
|
||||
<Avatar className="flippedSmallAvatar"
|
||||
<Badge
|
||||
variant='dot'
|
||||
overlap='circular'
|
||||
badgeContent=''
|
||||
color={props.userConnected ? 'success' : 'error'}
|
||||
>
|
||||
<Avatar
|
||||
className='flippedSmallAvatar'
|
||||
alt={props.message.userNick}
|
||||
src={window.location.origin +'/static/assets/avatars/' + props.message.userNick + '.png'}
|
||||
/>
|
||||
src={
|
||||
window.location.origin +
|
||||
'/static/assets/avatars/' +
|
||||
props.message.userNick +
|
||||
'.png'
|
||||
}
|
||||
/>
|
||||
</Badge>
|
||||
}
|
||||
style={{backgroundColor: props.cardColor}}
|
||||
style={{ backgroundColor: props.cardColor }}
|
||||
title={
|
||||
<Tooltip placement="top" enterTouchDelay={0} enterDelay={500} enterNextDelay={2000} title={t(props.message.validSignature ? "Verified signature by {{nickname}}": "Cannot verify signature of {{nickname}}",{"nickname": props.message.userNick})}>
|
||||
<div style={{display:'flex',alignItems:'center', flexWrap:'wrap', position:'relative',left:-5, width:240}}>
|
||||
<div style={{width:168,display:'flex',alignItems:'center', flexWrap:'wrap'}}>
|
||||
<Tooltip
|
||||
placement='top'
|
||||
enterTouchDelay={0}
|
||||
enterDelay={500}
|
||||
enterNextDelay={2000}
|
||||
title={t(
|
||||
props.message.validSignature
|
||||
? 'Verified signature by {{nickname}}'
|
||||
: 'Cannot verify signature of {{nickname}}',
|
||||
{ nickname: props.message.userNick },
|
||||
)}
|
||||
>
|
||||
<div
|
||||
style={{
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
flexWrap: 'wrap',
|
||||
position: 'relative',
|
||||
left: -5,
|
||||
width: 240,
|
||||
}}
|
||||
>
|
||||
<div
|
||||
style={{ width: 168, display: 'flex', alignItems: 'center', flexWrap: 'wrap' }}
|
||||
>
|
||||
{props.message.userNick}
|
||||
{props.message.validSignature ?
|
||||
<CheckIcon sx={{height:16}} color="success"/>
|
||||
:
|
||||
<CloseIcon sx={{height:16}} color="error"/>
|
||||
}
|
||||
{props.message.validSignature ? (
|
||||
<CheckIcon sx={{ height: 16 }} color='success' />
|
||||
) : (
|
||||
<CloseIcon sx={{ height: 16 }} color='error' />
|
||||
)}
|
||||
</div>
|
||||
<div style={{width:20}}>
|
||||
<IconButton sx={{height:18,width:18}}
|
||||
onClick={()=>
|
||||
this.setState(prevState => {
|
||||
const newShowPGP = [...prevState.showPGP];
|
||||
newShowPGP[props.index] = !newShowPGP[props.index];
|
||||
return {showPGP: newShowPGP};
|
||||
})}>
|
||||
<VisibilityIcon color={this.state.showPGP[props.index]? "primary":"inherit"} sx={{height:16,width:16,color:this.state.showPGP[props.index]? "primary":"#333333"}}/>
|
||||
<div style={{ width: 20 }}>
|
||||
<IconButton
|
||||
sx={{ height: 18, width: 18 }}
|
||||
onClick={() =>
|
||||
this.setState((prevState) => {
|
||||
const newShowPGP = [...prevState.showPGP];
|
||||
newShowPGP[props.index] = !newShowPGP[props.index];
|
||||
return { showPGP: newShowPGP };
|
||||
})
|
||||
}
|
||||
>
|
||||
<VisibilityIcon
|
||||
color={this.state.showPGP[props.index] ? 'primary' : 'inherit'}
|
||||
sx={{
|
||||
height: 16,
|
||||
width: 16,
|
||||
color: this.state.showPGP[props.index] ? 'primary' : '#333333',
|
||||
}}
|
||||
/>
|
||||
</IconButton>
|
||||
</div>
|
||||
<div style={{width:20}}>
|
||||
<Tooltip disableHoverListener enterTouchDelay={0} title={t("Copied!")}>
|
||||
<IconButton sx={{height:18,width:18}}
|
||||
onClick={()=> copyToClipboard(this.state.showPGP[props.index] ? props.message.encryptedMessage : props.message.plainTextMessage)}>
|
||||
<ContentCopy sx={{height:16,width:16,color:'#333333'}}/>
|
||||
<div style={{ width: 20 }}>
|
||||
<Tooltip disableHoverListener enterTouchDelay={0} title={t('Copied!')}>
|
||||
<IconButton
|
||||
sx={{ height: 18, width: 18 }}
|
||||
onClick={() =>
|
||||
copyToClipboard(
|
||||
this.state.showPGP[props.index]
|
||||
? props.message.encryptedMessage
|
||||
: props.message.plainTextMessage,
|
||||
)
|
||||
}
|
||||
>
|
||||
<ContentCopy sx={{ height: 16, width: 16, color: '#333333' }} />
|
||||
</IconButton>
|
||||
</Tooltip>
|
||||
</div>
|
||||
</div>
|
||||
</Tooltip>
|
||||
}
|
||||
subheader={this.state.showPGP[props.index] ? <a> {props.message.time} <br/> {"Valid signature: " + props.message.validSignature} <br/> {props.message.encryptedMessage} </a> : props.message.plainTextMessage}
|
||||
subheaderTypographyProps={{sx: {wordWrap: "break-word", width: '200px', color: '#444444', fontSize: this.state.showPGP[props.index]? 11 : null }}}
|
||||
subheader={
|
||||
this.state.showPGP[props.index] ? (
|
||||
<a>
|
||||
{' '}
|
||||
{props.message.time} <br /> {'Valid signature: ' + props.message.validSignature}{' '}
|
||||
<br /> {props.message.encryptedMessage}{' '}
|
||||
</a>
|
||||
) : (
|
||||
props.message.plainTextMessage
|
||||
)
|
||||
}
|
||||
subheaderTypographyProps={{
|
||||
sx: {
|
||||
wordWrap: 'break-word',
|
||||
width: '200px',
|
||||
color: '#444444',
|
||||
fontSize: this.state.showPGP[props.index] ? 11 : null,
|
||||
},
|
||||
}}
|
||||
/>
|
||||
</Card>
|
||||
)
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
render() {
|
||||
const { t } = this.props;
|
||||
return (
|
||||
<Container component="main">
|
||||
<Container component='main'>
|
||||
<Grid container spacing={0.5}>
|
||||
<Grid item xs={0.3}/>
|
||||
<Grid item xs={0.3} />
|
||||
<Grid item xs={5.5}>
|
||||
<Paper elevation={1} style={this.state.connected ? {backgroundColor: '#e8ffe6'}: {backgroundColor: '#FFF1C5'}}>
|
||||
<Typography variant='caption' sx={{color: '#333333'}}>
|
||||
{t("You")+": "}{this.state.connected ? t("connected"): t("disconnected")}
|
||||
</Typography>
|
||||
</Paper>
|
||||
</Grid>
|
||||
<Grid item xs={0.4}/>
|
||||
<Grid item xs={5.5}>
|
||||
<Paper elevation={1} style={this.state.peer_connected ? {backgroundColor: '#e8ffe6'}: {backgroundColor: '#FFF1C5'}}>
|
||||
<Typography variant='caption' sx={{color: '#333333'}}>
|
||||
{t("Peer")+": "}{this.state.peer_connected ? t("connected"): t("disconnected")}
|
||||
</Typography>
|
||||
</Paper>
|
||||
</Grid>
|
||||
<Grid item xs={0.3}/>
|
||||
</Grid>
|
||||
<div style={{position:'relative', left:'-2px', margin:'0 auto', width: '285px'}}>
|
||||
<Paper elevation={1} style={{height: '300px', maxHeight: '300px' , width: '285px' ,overflow: 'auto', backgroundColor: '#F7F7F7' }}>
|
||||
{this.state.messages.map((message, index) =>
|
||||
<li style={{listStyleType:"none"}} key={index}>
|
||||
{message.userNick == this.props.ur_nick ?
|
||||
<this.messageCard message={message} index={index} cardColor={'#eeeeee'} userConnected={this.state.connected}/>
|
||||
:
|
||||
<this.messageCard message={message} index={index} cardColor={'#fafafa'} userConnected={this.state.peer_connected}/>
|
||||
<Paper
|
||||
elevation={1}
|
||||
style={
|
||||
this.state.connected
|
||||
? { backgroundColor: '#e8ffe6' }
|
||||
: { backgroundColor: '#FFF1C5' }
|
||||
}
|
||||
</li>)}
|
||||
<div style={{ float:"left", clear: "both" }} ref={(el) => { this.messagesEnd = el; }}></div>
|
||||
>
|
||||
<Typography variant='caption' sx={{ color: '#333333' }}>
|
||||
{t('You') + ': '}
|
||||
{this.state.connected ? t('connected') : t('disconnected')}
|
||||
</Typography>
|
||||
</Paper>
|
||||
</Grid>
|
||||
<Grid item xs={0.4} />
|
||||
<Grid item xs={5.5}>
|
||||
<Paper
|
||||
elevation={1}
|
||||
style={
|
||||
this.state.peer_connected
|
||||
? { backgroundColor: '#e8ffe6' }
|
||||
: { backgroundColor: '#FFF1C5' }
|
||||
}
|
||||
>
|
||||
<Typography variant='caption' sx={{ color: '#333333' }}>
|
||||
{t('Peer') + ': '}
|
||||
{this.state.peer_connected ? t('connected') : t('disconnected')}
|
||||
</Typography>
|
||||
</Paper>
|
||||
</Grid>
|
||||
<Grid item xs={0.3} />
|
||||
</Grid>
|
||||
<div style={{ position: 'relative', left: '-2px', margin: '0 auto', width: '285px' }}>
|
||||
<Paper
|
||||
elevation={1}
|
||||
style={{
|
||||
height: '300px',
|
||||
maxHeight: '300px',
|
||||
width: '285px',
|
||||
overflow: 'auto',
|
||||
backgroundColor: '#F7F7F7',
|
||||
}}
|
||||
>
|
||||
{this.state.messages.map((message, index) => (
|
||||
<li style={{ listStyleType: 'none' }} key={index}>
|
||||
{message.userNick == this.props.ur_nick ? (
|
||||
<this.messageCard
|
||||
message={message}
|
||||
index={index}
|
||||
cardColor={'#eeeeee'}
|
||||
userConnected={this.state.connected}
|
||||
/>
|
||||
) : (
|
||||
<this.messageCard
|
||||
message={message}
|
||||
index={index}
|
||||
cardColor={'#fafafa'}
|
||||
userConnected={this.state.peer_connected}
|
||||
/>
|
||||
)}
|
||||
</li>
|
||||
))}
|
||||
<div
|
||||
style={{ float: 'left', clear: 'both' }}
|
||||
ref={(el) => {
|
||||
this.messagesEnd = el;
|
||||
}}
|
||||
></div>
|
||||
</Paper>
|
||||
<form noValidate onSubmit={this.onButtonClicked}>
|
||||
<Grid alignItems="stretch" style={{ display: "flex" }}>
|
||||
<Grid item alignItems="stretch" style={{ display: "flex"}}>
|
||||
<Grid alignItems='stretch' style={{ display: 'flex' }}>
|
||||
<Grid item alignItems='stretch' style={{ display: 'flex' }}>
|
||||
<TextField
|
||||
label={t("Type a message")}
|
||||
variant="standard"
|
||||
size="small"
|
||||
helperText={this.state.connected ? (this.state.peer_pub_key ? null : t("Waiting for peer public key...")) : t("Connecting...")}
|
||||
label={t('Type a message')}
|
||||
variant='standard'
|
||||
size='small'
|
||||
helperText={
|
||||
this.state.connected
|
||||
? this.state.peer_pub_key
|
||||
? null
|
||||
: t('Waiting for peer public key...')
|
||||
: t('Connecting...')
|
||||
}
|
||||
value={this.state.value}
|
||||
onChange={e => {
|
||||
onChange={(e) => {
|
||||
this.setState({ value: e.target.value });
|
||||
this.value = this.state.value;
|
||||
}}
|
||||
sx={{width: 219}}
|
||||
sx={{ width: 219 }}
|
||||
/>
|
||||
</Grid>
|
||||
<Grid item alignItems="stretch" style={{ display: "flex" }}>
|
||||
<Button sx={{'width':68}} disabled={!this.state.connected || this.state.waitingEcho || this.state.peer_pub_key == null} type="submit" variant="contained" color="primary">
|
||||
{this.state.waitingEcho ?
|
||||
<div style={{display:'flex',alignItems:'center', flexWrap:'wrap', minWidth:68, width:68, position:"relative",left:15}}>
|
||||
<div style={{width:20}}><KeyIcon sx={{width:18}}/></div>
|
||||
<div style={{width:18}}><CircularProgress size={16} thickness={5}/></div>
|
||||
<Grid item alignItems='stretch' style={{ display: 'flex' }}>
|
||||
<Button
|
||||
sx={{ width: 68 }}
|
||||
disabled={
|
||||
!this.state.connected ||
|
||||
this.state.waitingEcho ||
|
||||
this.state.peer_pub_key == null
|
||||
}
|
||||
type='submit'
|
||||
variant='contained'
|
||||
color='primary'
|
||||
>
|
||||
{this.state.waitingEcho ? (
|
||||
<div
|
||||
style={{
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
flexWrap: 'wrap',
|
||||
minWidth: 68,
|
||||
width: 68,
|
||||
position: 'relative',
|
||||
left: 15,
|
||||
}}
|
||||
>
|
||||
<div style={{ width: 20 }}>
|
||||
<KeyIcon sx={{ width: 18 }} />
|
||||
</div>
|
||||
<div style={{ width: 18 }}>
|
||||
<CircularProgress size={16} thickness={5} />
|
||||
</div>
|
||||
</div>
|
||||
:
|
||||
t("Send")
|
||||
}
|
||||
) : (
|
||||
t('Send')
|
||||
)}
|
||||
</Button>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<div style={{height:4}}/>
|
||||
<div style={{ height: 4 }} />
|
||||
|
||||
<Grid container spacing={0}>
|
||||
<AuditPGPDialog
|
||||
open={this.state.audit}
|
||||
onClose={() => this.setState({audit:false})}
|
||||
onClose={() => this.setState({ audit: false })}
|
||||
orderId={Number(this.props.orderId)}
|
||||
messages={this.state.messages}
|
||||
own_pub_key={this.state.own_pub_key}
|
||||
own_enc_priv_key={this.state.own_enc_priv_key}
|
||||
peer_pub_key={this.state.peer_pub_key ? this.state.peer_pub_key : "Not received yet"}
|
||||
peer_pub_key={this.state.peer_pub_key ? this.state.peer_pub_key : 'Not received yet'}
|
||||
passphrase={this.state.token}
|
||||
onClickBack={() => this.setState({audit:false})}
|
||||
onClickBack={() => this.setState({ audit: false })}
|
||||
/>
|
||||
|
||||
|
||||
<Grid item xs={6}>
|
||||
<Tooltip placement="bottom" enterTouchDelay={0} enterDelay={500} enterNextDelay={2000} title={t("Verify your privacy")}>
|
||||
<Button size="small" color="primary" variant="outlined" onClick={()=>this.setState({audit:!this.state.audit})}><KeyIcon/>{t("Audit PGP")} </Button>
|
||||
<Tooltip
|
||||
placement='bottom'
|
||||
enterTouchDelay={0}
|
||||
enterDelay={500}
|
||||
enterNextDelay={2000}
|
||||
title={t('Verify your privacy')}
|
||||
>
|
||||
<Button
|
||||
size='small'
|
||||
color='primary'
|
||||
variant='outlined'
|
||||
onClick={() => this.setState({ audit: !this.state.audit })}
|
||||
>
|
||||
<KeyIcon />
|
||||
{t('Audit PGP')}{' '}
|
||||
</Button>
|
||||
</Tooltip>
|
||||
</Grid>
|
||||
|
||||
|
||||
<Grid item xs={6}>
|
||||
<Tooltip placement="bottom" enterTouchDelay={0} enterDelay={500} enterNextDelay={2000} title={t("Save full log as a JSON file (messages and credentials)")}>
|
||||
<Button size="small" color="primary" variant="outlined" onClick={()=>saveAsJson('complete_log_chat_'+this.props.orderId+'.json', this.createJsonFile())}><div style={{width:28,height:20}}><ExportIcon sx={{width:20,height:20}}/></div> {t("Export")} </Button>
|
||||
<Tooltip
|
||||
placement='bottom'
|
||||
enterTouchDelay={0}
|
||||
enterDelay={500}
|
||||
enterNextDelay={2000}
|
||||
title={t('Save full log as a JSON file (messages and credentials)')}
|
||||
>
|
||||
<Button
|
||||
size='small'
|
||||
color='primary'
|
||||
variant='outlined'
|
||||
onClick={() =>
|
||||
saveAsJson(
|
||||
'complete_log_chat_' + this.props.orderId + '.json',
|
||||
this.createJsonFile(),
|
||||
)
|
||||
}
|
||||
>
|
||||
<div style={{ width: 28, height: 20 }}>
|
||||
<ExportIcon sx={{ width: 20, height: 20 }} />
|
||||
</div>{' '}
|
||||
{t('Export')}{' '}
|
||||
</Button>
|
||||
</Tooltip>
|
||||
</Grid>
|
||||
</Grid>
|
||||
|
||||
</Container>
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,11 +1,11 @@
|
||||
import React from "react";
|
||||
import Flags from 'country-flag-icons/react/3x2'
|
||||
import React from 'react';
|
||||
import Flags from 'country-flag-icons/react/3x2';
|
||||
import SwapCallsIcon from '@mui/icons-material/SwapCalls';
|
||||
import { GoldIcon, EarthIcon } from "../Icons";
|
||||
import { GoldIcon, EarthIcon } from '../Icons';
|
||||
|
||||
type Props = {
|
||||
code: string;
|
||||
}
|
||||
};
|
||||
|
||||
const FlagWithProps = ({ code }: Props): JSX.Element => {
|
||||
const defaultProps = {
|
||||
@ -15,82 +15,80 @@ const FlagWithProps = ({ code }: Props): JSX.Element => {
|
||||
|
||||
let flag: JSX.Element | null = null;
|
||||
|
||||
if(code === 'AED') flag = <Flags.AE {...defaultProps}/>;
|
||||
if(code === 'AUD') flag = <Flags.AU {...defaultProps}/>;
|
||||
if(code === 'ARS') flag = <Flags.AR {...defaultProps}/>;
|
||||
if(code === 'BRL') flag = <Flags.BR {...defaultProps}/>;
|
||||
if(code === 'BYN') flag = <Flags.BY {...defaultProps}/>;
|
||||
if(code === 'CAD') flag = <Flags.CA {...defaultProps}/>;
|
||||
if(code === 'CHF') flag = <Flags.CH {...defaultProps}/>;
|
||||
if(code === 'CLP') flag = <Flags.CL {...defaultProps}/>;
|
||||
if(code === 'CNY') flag = <Flags.CN {...defaultProps}/>;
|
||||
if(code === 'EGP') flag = <Flags.EG {...defaultProps}/>;
|
||||
if(code === 'EUR') flag = <Flags.EU {...defaultProps}/>;
|
||||
if(code === 'HRK') flag = <Flags.HR {...defaultProps}/>;
|
||||
if(code === 'CZK') flag = <Flags.CZ {...defaultProps}/>;
|
||||
if(code === 'DKK') flag = <Flags.DK {...defaultProps}/>;
|
||||
if(code === 'GBP') flag = <Flags.GB {...defaultProps}/>;
|
||||
if(code === 'HKD') flag = <Flags.HK {...defaultProps}/>;
|
||||
if(code === 'HUF') flag = <Flags.HU {...defaultProps}/>;
|
||||
if(code === 'INR') flag = <Flags.IN {...defaultProps}/>;
|
||||
if(code === 'ISK') flag = <Flags.IS {...defaultProps}/>;
|
||||
if(code === 'JPY') flag = <Flags.JP {...defaultProps}/>;
|
||||
if(code === 'KRW') flag = <Flags.KR {...defaultProps}/>;
|
||||
if(code === 'LKR') flag = <Flags.LK {...defaultProps}/>;
|
||||
if(code === 'MAD') flag = <Flags.MA {...defaultProps}/>;
|
||||
if(code === 'MXN') flag = <Flags.MX {...defaultProps}/>;
|
||||
if(code === 'NOK') flag = <Flags.NO {...defaultProps}/>;
|
||||
if(code === 'NZD') flag = <Flags.NZ {...defaultProps}/>;
|
||||
if(code === 'PLN') flag = <Flags.PL {...defaultProps}/>;
|
||||
if(code === 'RON') flag = <Flags.RO {...defaultProps}/>;
|
||||
if(code === 'RUB') flag = <Flags.RU {...defaultProps}/>;
|
||||
if(code === 'SEK') flag = <Flags.SE {...defaultProps}/>;
|
||||
if(code === 'SGD') flag = <Flags.SG {...defaultProps}/>;
|
||||
if(code === 'VES') flag = <Flags.VE {...defaultProps}/>;
|
||||
if(code === 'TRY') flag = <Flags.TR {...defaultProps}/>;
|
||||
if(code === 'USD') flag = <Flags.US {...defaultProps}/>;
|
||||
if(code === 'ZAR') flag = <Flags.ZA {...defaultProps}/>;
|
||||
if(code === 'COP') flag = <Flags.CO {...defaultProps}/>;
|
||||
if(code === 'PEN') flag = <Flags.PE {...defaultProps}/>;
|
||||
if(code === 'UYU') flag = <Flags.UY {...defaultProps}/>;
|
||||
if(code === 'PYG') flag = <Flags.PY {...defaultProps}/>;
|
||||
if(code === 'BOB') flag = <Flags.BO {...defaultProps}/>;
|
||||
if(code === 'IDR') flag = <Flags.ID {...defaultProps}/>;
|
||||
if(code === 'ANG') flag = <Flags.CW {...defaultProps}/>;
|
||||
if(code === 'CRC') flag = <Flags.CR {...defaultProps}/>;
|
||||
if(code === 'CUP') flag = <Flags.CU {...defaultProps}/>;
|
||||
if(code === 'DOP') flag = <Flags.DO {...defaultProps}/>;
|
||||
if(code === 'GHS') flag = <Flags.GH {...defaultProps}/>;
|
||||
if(code === 'GTQ') flag = <Flags.GT {...defaultProps}/>;
|
||||
if(code === 'ILS') flag = <Flags.IL {...defaultProps}/>;
|
||||
if(code === 'JMD') flag = <Flags.JM {...defaultProps}/>;
|
||||
if(code === 'KES') flag = <Flags.KE {...defaultProps}/>;
|
||||
if(code === 'KZT') flag = <Flags.KZ {...defaultProps}/>;
|
||||
if(code === 'MYR') flag = <Flags.MY {...defaultProps}/>;
|
||||
if(code === 'NAD') flag = <Flags.NA {...defaultProps}/>;
|
||||
if(code === 'NGN') flag = <Flags.NG {...defaultProps}/>;
|
||||
if(code === 'AZN') flag = <Flags.AZ {...defaultProps}/>;
|
||||
if(code === 'PAB') flag = <Flags.PA {...defaultProps}/>;
|
||||
if(code === 'PHP') flag = <Flags.PH {...defaultProps}/>;
|
||||
if(code === 'PKR') flag = <Flags.PK {...defaultProps}/>;
|
||||
if(code === 'QAR') flag = <Flags.QA {...defaultProps}/>;
|
||||
if(code === 'SAR') flag = <Flags.SA {...defaultProps}/>;
|
||||
if(code === 'THB') flag = <Flags.TH {...defaultProps}/>;
|
||||
if(code === 'TTD') flag = <Flags.TT {...defaultProps}/>;
|
||||
if(code === 'VND') flag = <Flags.VN {...defaultProps}/>;
|
||||
if(code === 'XOF') flag = <Flags.BJ {...defaultProps}/>;
|
||||
if(code === 'TWD') flag = <Flags.TW {...defaultProps}/>;
|
||||
if(code === 'TZS') flag = <Flags.TZ {...defaultProps}/>;
|
||||
if(code === 'XAF') flag = <Flags.CM {...defaultProps}/>;
|
||||
if(code === 'UAH') flag = <Flags.UA {...defaultProps}/>;
|
||||
if(code === 'TND') flag = <Flags.TN {...defaultProps}/>;
|
||||
if(code === 'ANY') flag = <EarthIcon {...defaultProps}/>;
|
||||
if(code === 'XAU') flag = <GoldIcon {...defaultProps}/>;
|
||||
if(code === 'BTC') flag = <SwapCallsIcon color="primary"/>;
|
||||
if (code === 'AED') flag = <Flags.AE {...defaultProps} />;
|
||||
if (code === 'AUD') flag = <Flags.AU {...defaultProps} />;
|
||||
if (code === 'ARS') flag = <Flags.AR {...defaultProps} />;
|
||||
if (code === 'BRL') flag = <Flags.BR {...defaultProps} />;
|
||||
if (code === 'BYN') flag = <Flags.BY {...defaultProps} />;
|
||||
if (code === 'CAD') flag = <Flags.CA {...defaultProps} />;
|
||||
if (code === 'CHF') flag = <Flags.CH {...defaultProps} />;
|
||||
if (code === 'CLP') flag = <Flags.CL {...defaultProps} />;
|
||||
if (code === 'CNY') flag = <Flags.CN {...defaultProps} />;
|
||||
if (code === 'EGP') flag = <Flags.EG {...defaultProps} />;
|
||||
if (code === 'EUR') flag = <Flags.EU {...defaultProps} />;
|
||||
if (code === 'HRK') flag = <Flags.HR {...defaultProps} />;
|
||||
if (code === 'CZK') flag = <Flags.CZ {...defaultProps} />;
|
||||
if (code === 'DKK') flag = <Flags.DK {...defaultProps} />;
|
||||
if (code === 'GBP') flag = <Flags.GB {...defaultProps} />;
|
||||
if (code === 'HKD') flag = <Flags.HK {...defaultProps} />;
|
||||
if (code === 'HUF') flag = <Flags.HU {...defaultProps} />;
|
||||
if (code === 'INR') flag = <Flags.IN {...defaultProps} />;
|
||||
if (code === 'ISK') flag = <Flags.IS {...defaultProps} />;
|
||||
if (code === 'JPY') flag = <Flags.JP {...defaultProps} />;
|
||||
if (code === 'KRW') flag = <Flags.KR {...defaultProps} />;
|
||||
if (code === 'LKR') flag = <Flags.LK {...defaultProps} />;
|
||||
if (code === 'MAD') flag = <Flags.MA {...defaultProps} />;
|
||||
if (code === 'MXN') flag = <Flags.MX {...defaultProps} />;
|
||||
if (code === 'NOK') flag = <Flags.NO {...defaultProps} />;
|
||||
if (code === 'NZD') flag = <Flags.NZ {...defaultProps} />;
|
||||
if (code === 'PLN') flag = <Flags.PL {...defaultProps} />;
|
||||
if (code === 'RON') flag = <Flags.RO {...defaultProps} />;
|
||||
if (code === 'RUB') flag = <Flags.RU {...defaultProps} />;
|
||||
if (code === 'SEK') flag = <Flags.SE {...defaultProps} />;
|
||||
if (code === 'SGD') flag = <Flags.SG {...defaultProps} />;
|
||||
if (code === 'VES') flag = <Flags.VE {...defaultProps} />;
|
||||
if (code === 'TRY') flag = <Flags.TR {...defaultProps} />;
|
||||
if (code === 'USD') flag = <Flags.US {...defaultProps} />;
|
||||
if (code === 'ZAR') flag = <Flags.ZA {...defaultProps} />;
|
||||
if (code === 'COP') flag = <Flags.CO {...defaultProps} />;
|
||||
if (code === 'PEN') flag = <Flags.PE {...defaultProps} />;
|
||||
if (code === 'UYU') flag = <Flags.UY {...defaultProps} />;
|
||||
if (code === 'PYG') flag = <Flags.PY {...defaultProps} />;
|
||||
if (code === 'BOB') flag = <Flags.BO {...defaultProps} />;
|
||||
if (code === 'IDR') flag = <Flags.ID {...defaultProps} />;
|
||||
if (code === 'ANG') flag = <Flags.CW {...defaultProps} />;
|
||||
if (code === 'CRC') flag = <Flags.CR {...defaultProps} />;
|
||||
if (code === 'CUP') flag = <Flags.CU {...defaultProps} />;
|
||||
if (code === 'DOP') flag = <Flags.DO {...defaultProps} />;
|
||||
if (code === 'GHS') flag = <Flags.GH {...defaultProps} />;
|
||||
if (code === 'GTQ') flag = <Flags.GT {...defaultProps} />;
|
||||
if (code === 'ILS') flag = <Flags.IL {...defaultProps} />;
|
||||
if (code === 'JMD') flag = <Flags.JM {...defaultProps} />;
|
||||
if (code === 'KES') flag = <Flags.KE {...defaultProps} />;
|
||||
if (code === 'KZT') flag = <Flags.KZ {...defaultProps} />;
|
||||
if (code === 'MYR') flag = <Flags.MY {...defaultProps} />;
|
||||
if (code === 'NAD') flag = <Flags.NA {...defaultProps} />;
|
||||
if (code === 'NGN') flag = <Flags.NG {...defaultProps} />;
|
||||
if (code === 'AZN') flag = <Flags.AZ {...defaultProps} />;
|
||||
if (code === 'PAB') flag = <Flags.PA {...defaultProps} />;
|
||||
if (code === 'PHP') flag = <Flags.PH {...defaultProps} />;
|
||||
if (code === 'PKR') flag = <Flags.PK {...defaultProps} />;
|
||||
if (code === 'QAR') flag = <Flags.QA {...defaultProps} />;
|
||||
if (code === 'SAR') flag = <Flags.SA {...defaultProps} />;
|
||||
if (code === 'THB') flag = <Flags.TH {...defaultProps} />;
|
||||
if (code === 'TTD') flag = <Flags.TT {...defaultProps} />;
|
||||
if (code === 'VND') flag = <Flags.VN {...defaultProps} />;
|
||||
if (code === 'XOF') flag = <Flags.BJ {...defaultProps} />;
|
||||
if (code === 'TWD') flag = <Flags.TW {...defaultProps} />;
|
||||
if (code === 'TZS') flag = <Flags.TZ {...defaultProps} />;
|
||||
if (code === 'XAF') flag = <Flags.CM {...defaultProps} />;
|
||||
if (code === 'UAH') flag = <Flags.UA {...defaultProps} />;
|
||||
if (code === 'TND') flag = <Flags.TN {...defaultProps} />;
|
||||
if (code === 'ANY') flag = <EarthIcon {...defaultProps} />;
|
||||
if (code === 'XAU') flag = <GoldIcon {...defaultProps} />;
|
||||
if (code === 'BTC') flag = <SwapCallsIcon color='primary' />;
|
||||
|
||||
return (
|
||||
<div style={{width:28, height: 20}}>{flag}</div>
|
||||
);
|
||||
return <div style={{ width: 28, height: 20 }}>{flag}</div>;
|
||||
};
|
||||
|
||||
export default FlagWithProps;
|
||||
|
@ -1 +1 @@
|
||||
export { default } from "./FlagWithProps";
|
||||
export { default } from './FlagWithProps';
|
||||
|
@ -1,62 +1,128 @@
|
||||
import React, { Component } from "react";
|
||||
import { BrowserRouter as Router, Switch, Route, Link, Redirect,useHistory } from "react-router-dom";
|
||||
import React, { Component } from 'react';
|
||||
import {
|
||||
BrowserRouter as Router,
|
||||
Switch,
|
||||
Route,
|
||||
Link,
|
||||
Redirect,
|
||||
useHistory,
|
||||
} from 'react-router-dom';
|
||||
|
||||
import UserGenPage from "./UserGenPage";
|
||||
import MakerPage from "./MakerPage";
|
||||
import BookPage from "./BookPage";
|
||||
import OrderPage from "./OrderPage";
|
||||
import BottomBar from "./BottomBar";
|
||||
import UserGenPage from './UserGenPage';
|
||||
import MakerPage from './MakerPage';
|
||||
import BookPage from './BookPage';
|
||||
import OrderPage from './OrderPage';
|
||||
import BottomBar from './BottomBar';
|
||||
|
||||
export default class HomePage extends Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
nickname: null,
|
||||
token: null,
|
||||
copiedToken: false,
|
||||
avatarLoaded: false,
|
||||
buyChecked: false,
|
||||
sellChecked: false,
|
||||
type:2,
|
||||
currency:0,
|
||||
bookCurrencyCode:'ANY',
|
||||
bookOrders:new Array(),
|
||||
bookLoading: true,
|
||||
activeOrderId: null,
|
||||
lastOrderId: null,
|
||||
earnedRewards: 0,
|
||||
referralCode:'',
|
||||
lastDayPremium: 0,
|
||||
limits: {}
|
||||
}
|
||||
}
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
nickname: null,
|
||||
token: null,
|
||||
copiedToken: false,
|
||||
avatarLoaded: false,
|
||||
buyChecked: false,
|
||||
sellChecked: false,
|
||||
type: 2,
|
||||
currency: 0,
|
||||
bookCurrencyCode: 'ANY',
|
||||
bookOrders: new Array(),
|
||||
bookLoading: true,
|
||||
activeOrderId: null,
|
||||
lastOrderId: null,
|
||||
earnedRewards: 0,
|
||||
referralCode: '',
|
||||
lastDayPremium: 0,
|
||||
limits: {},
|
||||
};
|
||||
}
|
||||
|
||||
setAppState=(newState)=>{
|
||||
this.setState(newState)
|
||||
}
|
||||
setAppState = (newState) => {
|
||||
this.setState(newState);
|
||||
};
|
||||
|
||||
redirectTo(location) {
|
||||
redirectTo(location) {
|
||||
this.props.history.push(location);
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
const fontSize = this.props.theme.typography.fontSize;
|
||||
const fontSizeFactor = fontSize / 14; // default fontSize is 14
|
||||
return (
|
||||
<Router >
|
||||
<div className='appCenter'>
|
||||
<Switch>
|
||||
<Route exact path='/' render={(props) => <UserGenPage {...props} {...this.state} {...this.props} setAppState={this.setAppState}/>}/>
|
||||
<Route path='/ref/:refCode' render={(props) => <UserGenPage {...props} {...this.state} {...this.props} setAppState={this.setAppState}/>}/>
|
||||
<Route path='/make' render={(props) => <MakerPage {...props} {...this.state} {...this.props} setAppState={this.setAppState}/>}/>
|
||||
<Route path='/book' render={(props) => <BookPage {...props} {...this.state} {...this.props} setAppState={this.setAppState} />}/>
|
||||
<Route path="/order/:orderId" render={(props) => <OrderPage {...props} {...this.state} {...this.props} setAppState={this.setAppState}/>}/>
|
||||
</Switch>
|
||||
</div>
|
||||
<div className='bottomBar' style={{height: `${40*fontSizeFactor}px`, width: window.innerWidth}}>
|
||||
<BottomBar redirectTo={this.redirectTo} {...this.state} {...this.props} setAppState={this.setAppState} />
|
||||
</div>
|
||||
</Router>
|
||||
);
|
||||
}
|
||||
render() {
|
||||
const fontSize = this.props.theme.typography.fontSize;
|
||||
const fontSizeFactor = fontSize / 14; // default fontSize is 14
|
||||
return (
|
||||
<Router>
|
||||
<div className='appCenter'>
|
||||
<Switch>
|
||||
<Route
|
||||
exact
|
||||
path='/'
|
||||
render={(props) => (
|
||||
<UserGenPage
|
||||
{...props}
|
||||
{...this.state}
|
||||
{...this.props}
|
||||
setAppState={this.setAppState}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
<Route
|
||||
path='/ref/:refCode'
|
||||
render={(props) => (
|
||||
<UserGenPage
|
||||
{...props}
|
||||
{...this.state}
|
||||
{...this.props}
|
||||
setAppState={this.setAppState}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
<Route
|
||||
path='/make'
|
||||
render={(props) => (
|
||||
<MakerPage
|
||||
{...props}
|
||||
{...this.state}
|
||||
{...this.props}
|
||||
setAppState={this.setAppState}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
<Route
|
||||
path='/book'
|
||||
render={(props) => (
|
||||
<BookPage
|
||||
{...props}
|
||||
{...this.state}
|
||||
{...this.props}
|
||||
setAppState={this.setAppState}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
<Route
|
||||
path='/order/:orderId'
|
||||
render={(props) => (
|
||||
<OrderPage
|
||||
{...props}
|
||||
{...this.state}
|
||||
{...this.props}
|
||||
setAppState={this.setAppState}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
</Switch>
|
||||
</div>
|
||||
<div
|
||||
className='bottomBar'
|
||||
style={{ height: `${40 * fontSizeFactor}px`, width: window.innerWidth }}
|
||||
>
|
||||
<BottomBar
|
||||
redirectTo={this.redirectTo}
|
||||
{...this.state}
|
||||
{...this.props}
|
||||
setAppState={this.setAppState}
|
||||
/>
|
||||
</div>
|
||||
</Router>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -1,18 +1,28 @@
|
||||
import React, { Component } from "react";
|
||||
import { SvgIcon } from "@mui/material"
|
||||
import React, { Component } from 'react';
|
||||
import { SvgIcon } from '@mui/material';
|
||||
|
||||
export default function AmbossIcon(props) {
|
||||
return (
|
||||
<SvgIcon {...props} x="0px" y="0px" viewBox="0 0 95.7 84.9">
|
||||
<g id="Layer_2_00000052094167160547307180000012226084410257483709_">
|
||||
<g id="Layer_1-2">
|
||||
<linearGradient id="SVGID_1_" gradientUnits="userSpaceOnUse" x1="0" y1="42.45" x2="95.7" y2="42.45">
|
||||
<stop offset="0" style={{stopColor:'#925bc9'}}/>
|
||||
<stop offset="1" style={{stopColor:'#ff59ac'}}/>
|
||||
</linearGradient>
|
||||
<path className={"amboss"} d="M55.3,84.9V61.3h-15v23.6H0V0h95.7v84.9H55.3z M55.3,28.1h-15v17.1h15V28.1z"/>
|
||||
</g>
|
||||
return (
|
||||
<SvgIcon {...props} x='0px' y='0px' viewBox='0 0 95.7 84.9'>
|
||||
<g id='Layer_2_00000052094167160547307180000012226084410257483709_'>
|
||||
<g id='Layer_1-2'>
|
||||
<linearGradient
|
||||
id='SVGID_1_'
|
||||
gradientUnits='userSpaceOnUse'
|
||||
x1='0'
|
||||
y1='42.45'
|
||||
x2='95.7'
|
||||
y2='42.45'
|
||||
>
|
||||
<stop offset='0' style={{ stopColor: '#925bc9' }} />
|
||||
<stop offset='1' style={{ stopColor: '#ff59ac' }} />
|
||||
</linearGradient>
|
||||
<path
|
||||
className={'amboss'}
|
||||
d='M55.3,84.9V61.3h-15v23.6H0V0h95.7v84.9H55.3z M55.3,28.1h-15v17.1h15V28.1z'
|
||||
/>
|
||||
</g>
|
||||
</SvgIcon>
|
||||
);
|
||||
}
|
||||
</g>
|
||||
</SvgIcon>
|
||||
);
|
||||
}
|
||||
|
@ -1,12 +1,12 @@
|
||||
import React, { Component } from "react";
|
||||
import { SvgIcon } from "@mui/material"
|
||||
import React, { Component } from 'react';
|
||||
import { SvgIcon } from '@mui/material';
|
||||
|
||||
export default function BasqueCountryFlag(props) {
|
||||
return (
|
||||
<SvgIcon {...props} x="0px" y="0px" viewBox="0 0 50 28">
|
||||
<path d="M0,0 v28 h50 v-28 z" fill="#D52B1E"/>
|
||||
<path d="M0,0 L50,28 M50,0 L0,28" stroke="#009B48" strokeWidth="4.3"/>
|
||||
<path d="M25,0 v28 M0,14 h50" stroke="#fff" strokeWidth="4.3"/>
|
||||
</SvgIcon>
|
||||
);
|
||||
}
|
||||
return (
|
||||
<SvgIcon {...props} x='0px' y='0px' viewBox='0 0 50 28'>
|
||||
<path d='M0,0 v28 h50 v-28 z' fill='#D52B1E' />
|
||||
<path d='M0,0 L50,28 M50,0 L0,28' stroke='#009B48' strokeWidth='4.3' />
|
||||
<path d='M25,0 v28 M0,14 h50' stroke='#fff' strokeWidth='4.3' />
|
||||
</SvgIcon>
|
||||
);
|
||||
}
|
||||
|
@ -1,10 +1,10 @@
|
||||
import React, { Component } from "react";
|
||||
import { SvgIcon } from "@mui/material"
|
||||
import React, { Component } from 'react';
|
||||
import { SvgIcon } from '@mui/material';
|
||||
|
||||
export default function BitcoinIcon(props) {
|
||||
return (
|
||||
<SvgIcon sx={props.sx} color={props.color} viewBox="0 0 512 512">
|
||||
<path d="M504 256c0 136.967-111.033 248-248 248S8 392.967 8 256 119.033 8 256 8s248 111.033 248 248zm-141.651-35.33c4.937-32.999-20.191-50.739-54.55-62.573l11.146-44.702-27.213-6.781-10.851 43.524c-7.154-1.783-14.502-3.464-21.803-5.13l10.929-43.81-27.198-6.781-11.153 44.686c-5.922-1.349-11.735-2.682-17.377-4.084l.031-.14-37.53-9.37-7.239 29.062s20.191 4.627 19.765 4.913c11.022 2.751 13.014 10.044 12.68 15.825l-12.696 50.925c.76.194 1.744.473 2.829.907-.907-.225-1.876-.473-2.876-.713l-17.796 71.338c-1.349 3.348-4.767 8.37-12.471 6.464.271.395-19.78-4.937-19.78-4.937l-13.51 31.147 35.414 8.827c6.588 1.651 13.045 3.379 19.4 5.006l-11.262 45.213 27.182 6.781 11.153-44.733a1038.209 1038.209 0 0 0 21.687 5.627l-11.115 44.523 27.213 6.781 11.262-45.128c46.404 8.781 81.299 5.239 95.986-36.727 11.836-33.79-.589-53.281-25.004-65.991 17.78-4.098 31.174-15.792 34.747-39.949zm-62.177 87.179c-8.41 33.79-65.308 15.523-83.755 10.943l14.944-59.899c18.446 4.603 77.6 13.717 68.811 48.956zm8.417-87.667c-7.673 30.736-55.031 15.12-70.393 11.292l13.548-54.327c15.363 3.828 64.836 10.973 56.845 43.035z"/>
|
||||
<SvgIcon sx={props.sx} color={props.color} viewBox='0 0 512 512'>
|
||||
<path d='M504 256c0 136.967-111.033 248-248 248S8 392.967 8 256 119.033 8 256 8s248 111.033 248 248zm-141.651-35.33c4.937-32.999-20.191-50.739-54.55-62.573l11.146-44.702-27.213-6.781-10.851 43.524c-7.154-1.783-14.502-3.464-21.803-5.13l10.929-43.81-27.198-6.781-11.153 44.686c-5.922-1.349-11.735-2.682-17.377-4.084l.031-.14-37.53-9.37-7.239 29.062s20.191 4.627 19.765 4.913c11.022 2.751 13.014 10.044 12.68 15.825l-12.696 50.925c.76.194 1.744.473 2.829.907-.907-.225-1.876-.473-2.876-.713l-17.796 71.338c-1.349 3.348-4.767 8.37-12.471 6.464.271.395-19.78-4.937-19.78-4.937l-13.51 31.147 35.414 8.827c6.588 1.651 13.045 3.379 19.4 5.006l-11.262 45.213 27.182 6.781 11.153-44.733a1038.209 1038.209 0 0 0 21.687 5.627l-11.115 44.523 27.213 6.781 11.262-45.128c46.404 8.781 81.299 5.239 95.986-36.727 11.836-33.79-.589-53.281-25.004-65.991 17.78-4.098 31.174-15.792 34.747-39.949zm-62.177 87.179c-8.41 33.79-65.308 15.523-83.755 10.943l14.944-59.899c18.446 4.603 77.6 13.717 68.811 48.956zm8.417-87.667c-7.673 30.736-55.031 15.12-70.393 11.292l13.548-54.327c15.363 3.828 64.836 10.973 56.845 43.035z' />
|
||||
</SvgIcon>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -1,10 +1,10 @@
|
||||
import React, { Component } from "react";
|
||||
import { SvgIcon } from "@mui/material"
|
||||
import React, { Component } from 'react';
|
||||
import { SvgIcon } from '@mui/material';
|
||||
|
||||
export default function BitcoinSignIcon(props) {
|
||||
return (
|
||||
<SvgIcon sx={props.sx} color={props.color} viewBox="0 0 320 512">
|
||||
<path d="M48 32C48 14.33 62.33 0 80 0C97.67 0 112 14.33 112 32V64H144V32C144 14.33 158.3 0 176 0C193.7 0 208 14.33 208 32V64C208 65.54 207.9 67.06 207.7 68.54C254.1 82.21 288 125.1 288 176C288 200.2 280.3 222.6 267.3 240.9C298.9 260.7 320 295.9 320 336C320 397.9 269.9 448 208 448V480C208 497.7 193.7 512 176 512C158.3 512 144 497.7 144 480V448H112V480C112 497.7 97.67 512 80 512C62.33 512 48 497.7 48 480V448H41.74C18.69 448 0 429.3 0 406.3V101.6C0 80.82 16.82 64 37.57 64H48V32zM176 224C202.5 224 224 202.5 224 176C224 149.5 202.5 128 176 128H64V224H176zM64 288V384H208C234.5 384 256 362.5 256 336C256 309.5 234.5 288 208 288H64z"/>
|
||||
<SvgIcon sx={props.sx} color={props.color} viewBox='0 0 320 512'>
|
||||
<path d='M48 32C48 14.33 62.33 0 80 0C97.67 0 112 14.33 112 32V64H144V32C144 14.33 158.3 0 176 0C193.7 0 208 14.33 208 32V64C208 65.54 207.9 67.06 207.7 68.54C254.1 82.21 288 125.1 288 176C288 200.2 280.3 222.6 267.3 240.9C298.9 260.7 320 295.9 320 336C320 397.9 269.9 448 208 448V480C208 497.7 193.7 512 176 512C158.3 512 144 497.7 144 480V448H112V480C112 497.7 97.67 512 80 512C62.33 512 48 497.7 48 480V448H41.74C18.69 448 0 429.3 0 406.3V101.6C0 80.82 16.82 64 37.57 64H48V32zM176 224C202.5 224 224 202.5 224 176C224 149.5 202.5 128 176 128H64V224H176zM64 288V384H208C234.5 384 256 362.5 256 336C256 309.5 234.5 288 208 288H64z' />
|
||||
</SvgIcon>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -1,49 +1,111 @@
|
||||
import React, { Component } from "react";
|
||||
import { SvgIcon } from "@mui/material"
|
||||
import React, { Component } from 'react';
|
||||
import { SvgIcon } from '@mui/material';
|
||||
|
||||
export default function BuySatsIcon(props) {
|
||||
return (
|
||||
<SvgIcon sx={props.sx} color={props.color} x="0px" y="0px" viewBox="0 0 300 300">
|
||||
<g>
|
||||
<polygon fill={props.color} points="178.391,189.96 174.934,186.875 169.489,182.018 166.596,179.436 161.154,174.579 158.645,172.34
|
||||
return (
|
||||
<SvgIcon sx={props.sx} color={props.color} x='0px' y='0px' viewBox='0 0 300 300'>
|
||||
<g>
|
||||
<polygon
|
||||
fill={props.color}
|
||||
points='178.391,189.96 174.934,186.875 169.489,182.018 166.596,179.436 161.154,174.579 158.645,172.34
|
||||
157.717,171.51 152.893,176.918 155.712,179.436 161.154,184.291 164.049,186.875 169.491,191.73 172.947,194.816
|
||||
177.943,199.271 180.826,197.5 184.389,195.311 183.834,194.816 "/>
|
||||
<polygon fill={props.color} points="166.034,194.816 160.588,189.96 157.695,187.377 152.256,182.521 150.52,180.975 149.592,180.145
|
||||
177.943,199.271 180.826,197.5 184.389,195.311 183.834,194.816 '
|
||||
/>
|
||||
<polygon
|
||||
fill={props.color}
|
||||
points='166.034,194.816 160.588,189.96 157.695,187.377 152.256,182.521 150.52,180.975 149.592,180.145
|
||||
144.766,185.551 146.813,187.377 152.256,192.232 155.146,194.814 160.59,199.672 164.049,202.756 167.4,205.748 173.85,201.787
|
||||
169.491,197.9 "/>
|
||||
<polygon fill={props.color} points="157.695,202.255 152.253,197.398 149.358,194.816 143.916,189.96 142.014,188.26 137.189,193.668
|
||||
169.491,197.9 '
|
||||
/>
|
||||
<polygon
|
||||
fill={props.color}
|
||||
points='157.695,202.255 152.253,197.398 149.358,194.816 143.916,189.96 142.014,188.26 137.189,193.668
|
||||
138.476,194.816 143.92,199.672 146.813,202.254 152.256,207.109 155.712,210.195 157.527,211.816 163.973,207.854
|
||||
161.154,205.34 "/>
|
||||
|
||||
<rect x="173.431" y="172.686" transform="matrix(0.7405 0.672 -0.672 0.7405 165.1439 -72.7109)" fill={props.color} width="6.611" height="9.654"/>
|
||||
<polygon fill={props.color} points="141.129,211.877 147.035,215.203 150.877,210.975 145.981,206.533 "/>
|
||||
<polygon fill={props.color} points="186.961,57.038 189.855,59.621 195.298,64.477 198.756,67.562 204.199,72.418 205.449,73.534
|
||||
161.154,205.34 '
|
||||
/>
|
||||
|
||||
<rect
|
||||
x='173.431'
|
||||
y='172.686'
|
||||
transform='matrix(0.7405 0.672 -0.672 0.7405 165.1439 -72.7109)'
|
||||
fill={props.color}
|
||||
width='6.611'
|
||||
height='9.654'
|
||||
/>
|
||||
<polygon
|
||||
fill={props.color}
|
||||
points='141.129,211.877 147.035,215.203 150.877,210.975 145.981,206.533 '
|
||||
/>
|
||||
<polygon
|
||||
fill={props.color}
|
||||
points='186.961,57.038 189.855,59.621 195.298,64.477 198.756,67.562 204.199,72.418 205.449,73.534
|
||||
210.271,68.126 209.643,67.562 204.199,62.705 200.742,59.621 195.298,54.764 192.402,52.182 186.963,47.326 184.453,45.086
|
||||
183.525,44.256 178.695,49.665 181.52,52.182 "/>
|
||||
<polygon fill={props.color} points="178.062,64.979 180.954,67.562 186.398,72.418 189.855,75.503 195.298,80.359 196.396,81.34
|
||||
183.525,44.256 178.695,49.665 181.52,52.182 '
|
||||
/>
|
||||
<polygon
|
||||
fill={props.color}
|
||||
points='178.062,64.979 180.954,67.562 186.398,72.418 189.855,75.503 195.298,80.359 196.396,81.34
|
||||
197.325,82.166 202.146,76.76 200.742,75.503 195.298,70.648 191.841,67.562 186.398,62.705 183.505,60.124 178.062,55.268
|
||||
176.328,53.72 175.396,52.89 170.572,58.299 172.618,60.124 "/>
|
||||
<polygon fill={props.color} points="169.723,72.418 172.618,75 178.062,79.856 181.52,82.941 186.962,87.798 188.818,89.456
|
||||
176.328,53.72 175.396,52.89 170.572,58.299 172.618,60.124 '
|
||||
/>
|
||||
<polygon
|
||||
fill={props.color}
|
||||
points='169.723,72.418 172.618,75 178.062,79.856 181.52,82.941 186.962,87.798 188.818,89.456
|
||||
189.747,90.282 194.57,84.875 192.402,82.942 186.962,78.085 183.505,75 178.062,70.144 175.167,67.562 169.723,62.705
|
||||
167.82,61.006 162.998,66.415 164.282,67.562 "/>
|
||||
|
||||
<rect x="199.243" y="45.425" transform="matrix(0.7403 0.6723 -0.6723 0.7403 86.3919 -123.1221)" fill={props.color} width="6.609" height="9.656"/>
|
||||
<polygon fill={props.color} points="165.298,86.425 170.193,90.867 176.684,83.72 171.789,79.28 "/>
|
||||
<polygon fill={props.color} points="88.684,102.6 87.755,101.77 82.927,107.177 105.743,127.533 109.679,131.046 114.503,125.64
|
||||
112.599,123.938 "/>
|
||||
<polygon fill={props.color} points="80.557,111.232 79.631,110.403 74.803,115.811 94.669,133.537 100.627,138.853 101.553,139.68
|
||||
106.378,134.272 101.42,129.848 "/>
|
||||
<polygon fill={props.color} points="72.049,118.52 67.228,123.928 84.469,139.311 92.184,146.195 93.051,146.968 93.978,147.795
|
||||
98.659,142.548 98.802,142.389 91.107,135.525 "/>
|
||||
|
||||
<rect x="103.471" y="102.94" transform="matrix(0.7405 0.6721 -0.6721 0.7405 100.1373 -43.7934)" fill={props.color} width="6.609" height="9.654"/>
|
||||
<polygon fill={props.color} points="69.529,143.938 72.38,146.525 74.422,148.381 80.622,141.554 80.914,141.234 76.019,136.792 "/>
|
||||
<path fill={props.color} d="M187.466,112.718c7.511,0,14.995-1.878,21.647-5.43c10.848-5.793,18.796-15.48,22.379-27.277
|
||||
167.82,61.006 162.998,66.415 164.282,67.562 '
|
||||
/>
|
||||
|
||||
<rect
|
||||
x='199.243'
|
||||
y='45.425'
|
||||
transform='matrix(0.7403 0.6723 -0.6723 0.7403 86.3919 -123.1221)'
|
||||
fill={props.color}
|
||||
width='6.609'
|
||||
height='9.656'
|
||||
/>
|
||||
<polygon
|
||||
fill={props.color}
|
||||
points='165.298,86.425 170.193,90.867 176.684,83.72 171.789,79.28 '
|
||||
/>
|
||||
<polygon
|
||||
fill={props.color}
|
||||
points='88.684,102.6 87.755,101.77 82.927,107.177 105.743,127.533 109.679,131.046 114.503,125.64
|
||||
112.599,123.938 '
|
||||
/>
|
||||
<polygon
|
||||
fill={props.color}
|
||||
points='80.557,111.232 79.631,110.403 74.803,115.811 94.669,133.537 100.627,138.853 101.553,139.68
|
||||
106.378,134.272 101.42,129.848 '
|
||||
/>
|
||||
<polygon
|
||||
fill={props.color}
|
||||
points='72.049,118.52 67.228,123.928 84.469,139.311 92.184,146.195 93.051,146.968 93.978,147.795
|
||||
98.659,142.548 98.802,142.389 91.107,135.525 '
|
||||
/>
|
||||
|
||||
<rect
|
||||
x='103.471'
|
||||
y='102.94'
|
||||
transform='matrix(0.7405 0.6721 -0.6721 0.7405 100.1373 -43.7934)'
|
||||
fill={props.color}
|
||||
width='6.609'
|
||||
height='9.654'
|
||||
/>
|
||||
<polygon
|
||||
fill={props.color}
|
||||
points='69.529,143.938 72.38,146.525 74.422,148.381 80.622,141.554 80.914,141.234 76.019,136.792 '
|
||||
/>
|
||||
<path
|
||||
fill={props.color}
|
||||
d='M187.466,112.718c7.511,0,14.995-1.878,21.647-5.43c10.848-5.793,18.796-15.48,22.379-27.277
|
||||
c3.583-11.796,2.365-24.266-3.426-35.113c-8.033-15.037-23.645-24.379-40.742-24.379c-7.51,0-14.996,1.878-21.648,5.431
|
||||
c-10.847,5.793-18.794,15.479-22.377,27.275s-2.366,24.266,3.426,35.113C154.755,103.376,170.365,112.718,187.466,112.718z
|
||||
M171.232,36.355c16.688-8.912,37.514-2.587,46.43,14.099c8.908,16.688,2.584,37.516-14.104,46.428
|
||||
c-16.688,8.913-37.518,2.586-46.431-14.1C148.219,66.092,154.544,45.268,171.232,36.355z"/>
|
||||
<path fill={props.color} d="M247.809,155.361c-6.326-5.757-17.865-13.456-34.295-22.881c-18.544-10.639-43.998-23.456-59.836-27.527
|
||||
c-16.688,8.913-37.518,2.586-46.431-14.1C148.219,66.092,154.544,45.268,171.232,36.355z'
|
||||
/>
|
||||
<path
|
||||
fill={props.color}
|
||||
d='M247.809,155.361c-6.326-5.757-17.865-13.456-34.295-22.881c-18.544-10.639-43.998-23.456-59.836-27.527
|
||||
c-0.785-0.199-1.621-0.3-2.484-0.3c-1.917,0-5.62,0.546-15.812,4.946c-0.823-2.478-1.856-4.885-3.086-7.188
|
||||
c-8.032-15.037-23.644-24.379-40.743-24.379c-7.509,0-14.995,1.878-21.646,5.43c-10.847,5.792-18.795,15.478-22.378,27.275
|
||||
c-3.583,11.797-2.365,24.267,3.428,35.113c1.488,2.787,3.262,5.414,5.295,7.841c-3.117,2.348-5.28,4.3-6.706,6.043
|
||||
@ -60,12 +122,16 @@ export default function BuySatsIcon(props) {
|
||||
c-8.912-16.687-2.588-37.511,14.1-46.422c16.689-8.914,37.516-2.588,46.43,14.101c1.647,3.086,2.772,6.316,3.407,9.585
|
||||
C125.997,121.143,126.1,124.779,125.656,128.328z M59.715,174.898l34.511,20.586l-34.511,60.934V174.898z M102.657,200.516
|
||||
l47.237,28.182l46.69-28.232l37.43,66.088c-0.445,0.067-0.896,0.114-1.358,0.114H68.718c-1.125,0-2.196-0.216-3.19-0.595
|
||||
L102.657,200.516z"/>
|
||||
<path fill={props.color} d="M269.921,0H30.08C13.493,0,0,13.494,0,30.08v239.84C0,286.506,13.493,300,30.08,300h239.841
|
||||
L102.657,200.516z'
|
||||
/>
|
||||
<path
|
||||
fill={props.color}
|
||||
d='M269.921,0H30.08C13.493,0,0,13.494,0,30.08v239.84C0,286.506,13.493,300,30.08,300h239.841
|
||||
C286.506,300,300,286.506,300,269.92V30.08C300,13.494,286.506,0,269.921,0z M284.413,269.92c0,7.992-6.501,14.494-14.492,14.494
|
||||
H30.08c-7.992,0-14.494-6.502-14.494-14.494V30.08c0-7.992,6.502-14.494,14.494-14.494h239.841
|
||||
c7.991,0,14.492,6.502,14.492,14.494V269.92z"/>
|
||||
</g>
|
||||
</SvgIcon>
|
||||
);
|
||||
}
|
||||
c7.991,0,14.492,6.502,14.492,14.494V269.92z'
|
||||
/>
|
||||
</g>
|
||||
</SvgIcon>
|
||||
);
|
||||
}
|
||||
|
@ -1,11 +1,13 @@
|
||||
import React, { Component } from "react";
|
||||
import { SvgIcon } from "@mui/material"
|
||||
import React, { Component } from 'react';
|
||||
import { SvgIcon } from '@mui/material';
|
||||
|
||||
export default function BuySatsCheckedIcon(props) {
|
||||
return (
|
||||
<SvgIcon sx={props.sx} color={props.color} x="0px" y="0px" viewBox="0 0 300 300">
|
||||
<g>
|
||||
<path fill={props.color} d="M269.921,0H30.08C13.493,0,0,13.494,0,30.08v239.84C0,286.506,13.493,300,30.08,300h239.841
|
||||
return (
|
||||
<SvgIcon sx={props.sx} color={props.color} x='0px' y='0px' viewBox='0 0 300 300'>
|
||||
<g>
|
||||
<path
|
||||
fill={props.color}
|
||||
d='M269.921,0H30.08C13.493,0,0,13.494,0,30.08v239.84C0,286.506,13.493,300,30.08,300h239.841
|
||||
C286.506,300,300,286.506,300,269.92V30.08C300,13.494,286.506,0,269.921,0z M143.299,53.225
|
||||
c3.583-11.796,11.53-21.482,22.377-27.275c6.652-3.553,14.139-5.431,21.648-5.431c15.026,0,28.906,7.216,37.501,19.173
|
||||
c0.573,0.797,1.123,1.615,1.647,2.454c0.56,0.895,1.092,1.812,1.594,2.752c5.791,10.847,7.009,23.317,3.426,35.113
|
||||
@ -16,8 +18,11 @@ export default function BuySatsCheckedIcon(props) {
|
||||
c0.334-2.09,0.804-4.173,1.43-6.234C51.112,98.94,59.06,89.254,69.907,83.462c6.651-3.552,14.137-5.43,21.646-5.43
|
||||
c17.099,0,32.711,9.342,40.743,24.379c1.23,2.303,2.263,4.71,3.086,7.188c10.192-4.4,13.895-4.946,15.812-4.946
|
||||
c0.863,0,1.699,0.101,2.484,0.3c15.838,4.071,41.292,16.888,59.836,27.527c16.43,9.425,27.969,17.124,34.295,22.881
|
||||
C253.963,160.965,254.477,164.032,254.473,166.466L254.473,166.466z"/>
|
||||
<path fill={props.color} d="M111.93,162.154c-14.119,7.541-30.589,6.39-43.265-1.563c-2.595,1.757-4.684,3.269-6.238,4.499
|
||||
C253.963,160.965,254.477,164.032,254.473,166.466L254.473,166.466z'
|
||||
/>
|
||||
<path
|
||||
fill={props.color}
|
||||
d='M111.93,162.154c-14.119,7.541-30.589,6.39-43.265-1.563c-2.595,1.757-4.684,3.269-6.238,4.499
|
||||
l56.336,33.61v-0.001c-0.178-1.596-0.265-3.194-0.264-4.787c0.006-8.962,2.806-17.76,8.005-25.075
|
||||
c0.347-0.488,0.704-0.969,1.072-1.443c0.654-0.843,1.341-1.664,2.061-2.461c0.72-0.796,1.473-1.568,2.257-2.314
|
||||
c2.746-2.611,5.884-4.899,9.387-6.769c20.966-11.197,47.131-3.25,58.332,17.717c1.73,3.242,3.001,6.613,3.84,10.029l-7.986,4.907
|
||||
@ -31,8 +36,11 @@ export default function BuySatsCheckedIcon(props) {
|
||||
z M167.4,205.748l-3.352-2.992l-3.459-3.084l-5.443-4.857l-2.891-2.582l-5.443-4.855l-2.047-1.826l0.58-0.649l4.246-4.757
|
||||
l0.928,0.83l1.736,1.547l5.439,4.855l2.893,2.583l5.446,4.856l3.457,3.084l4.358,3.887L167.4,205.748z M180.826,197.5l-2.883,1.771
|
||||
l-4.996-4.455l-3.456-3.086l-5.442-4.855l-2.895-2.584l-5.442-4.855l-2.819-2.518l4.824-5.408l0.928,0.83l2.51,2.239l5.441,4.856
|
||||
l2.894,2.582l5.444,4.857l3.457,3.085l5.443,4.856l0.554,0.493l0.001,0.001L180.826,197.5z"/>
|
||||
<path fill={props.color} d="M187.19,100.922c4.427,0.034,8.908-0.79,13.194-2.546c1.071-0.439,2.131-0.937,3.174-1.494
|
||||
l2.894,2.582l5.444,4.857l3.457,3.085l5.443,4.856l0.554,0.493l0.001,0.001L180.826,197.5z'
|
||||
/>
|
||||
<path
|
||||
fill={props.color}
|
||||
d='M187.19,100.922c4.427,0.034,8.908-0.79,13.194-2.546c1.071-0.439,2.131-0.937,3.174-1.494
|
||||
c16.688-8.912,23.012-29.74,14.104-46.428c-6.13-11.472-17.889-18.046-30.062-18.139c-5.533-0.042-11.152,1.255-16.367,4.04
|
||||
c-16.688,8.913-23.014,29.737-14.105,46.427C163.255,94.253,175.016,100.829,187.19,100.922z M165.298,86.425l6.491-7.145v0
|
||||
l4.895,4.44l-6.49,7.147L165.298,86.425z M189.747,90.282l-0.929-0.826l-1.856-1.658l-5.442-4.857l-3.457-3.085L172.618,75
|
||||
@ -41,12 +49,21 @@ export default function BuySatsCheckedIcon(props) {
|
||||
M183.525,44.256l0.928,0.83l2.51,2.24l5.439,4.856l2.896,2.582l5.444,4.857l3.457,3.084l5.443,4.857l0.629,0.564l-4.822,5.408
|
||||
l-1.25-1.116l-5.443-4.856l-3.458-3.085l-5.442-4.856l-2.895-2.583l-5.441-4.856l-2.824-2.517L183.525,44.256z M176.328,53.72
|
||||
l1.734,1.548l5.442,4.856l2.894,2.581l5.442,4.857l3.457,3.086l5.444,4.855l1.404,1.257l-4.821,5.406l-0.001,0l-0.928-0.826
|
||||
l-1.099-0.981l-5.442-4.856l-3.457-3.085l-5.444-4.856l-2.892-2.583l-5.444-4.855l-2.046-1.825l4.824-5.409L176.328,53.72z"/>
|
||||
<polygon fill={props.color} points="59.715,174.898 59.715,256.418 94.226,195.484 "/>
|
||||
<path fill={props.color} d="M241.417,259.706c0.151-0.657,0.24-1.34,0.24-2.042v-84.453l-36.673,22.176L241.417,259.706z"/>
|
||||
<path fill={props.color} d="M196.584,200.466l-46.69,28.232l-47.237-28.183l-37.129,65.557l0,0.001c0.994,0.379,2.065,0.595,3.19,0.595
|
||||
h163.938c0.462,0,0.912-0.047,1.357-0.113l-0.001-0.002L196.584,200.466z"/>
|
||||
<path fill={props.color} d="M68.179,149.165c2.65,2.481,5.651,4.502,8.876,6.015c9.464,4.428,20.827,4.506,30.732-0.785
|
||||
l-1.099-0.981l-5.442-4.856l-3.457-3.085l-5.444-4.856l-2.892-2.583l-5.444-4.855l-2.046-1.825l4.824-5.409L176.328,53.72z'
|
||||
/>
|
||||
<polygon fill={props.color} points='59.715,174.898 59.715,256.418 94.226,195.484 ' />
|
||||
<path
|
||||
fill={props.color}
|
||||
d='M241.417,259.706c0.151-0.657,0.24-1.34,0.24-2.042v-84.453l-36.673,22.176L241.417,259.706z'
|
||||
/>
|
||||
<path
|
||||
fill={props.color}
|
||||
d='M196.584,200.466l-46.69,28.232l-47.237-28.183l-37.129,65.557l0,0.001c0.994,0.379,2.065,0.595,3.19,0.595
|
||||
h163.938c0.462,0,0.912-0.047,1.357-0.113l-0.001-0.002L196.584,200.466z'
|
||||
/>
|
||||
<path
|
||||
fill={props.color}
|
||||
d='M68.179,149.165c2.65,2.481,5.651,4.502,8.876,6.015c9.464,4.428,20.827,4.506,30.732-0.785
|
||||
c1.276-0.682,2.492-1.434,3.646-2.247c8.07-5.697,13.056-14.459,14.224-23.819c0.222-1.774,0.307-3.57,0.25-5.371
|
||||
c-0.058-1.802-0.258-3.608-0.607-5.403c-0.635-3.269-1.76-6.499-3.407-9.585c-8.914-16.688-29.741-23.015-46.43-14.101
|
||||
c-11.474,6.126-18.048,17.884-18.14,30.057c-0.042,5.533,1.255,11.151,4.04,16.365C63.182,143.697,65.503,146.663,68.179,149.165z
|
||||
@ -54,8 +71,9 @@ export default function BuySatsCheckedIcon(props) {
|
||||
l-0.927-0.827l-0.867-0.773l-7.715-6.884l-17.241-15.383l0,0l4.82-5.408l19.058,17.005l7.695,6.864L98.659,142.548z
|
||||
M101.553,139.68l-0.926-0.827l-5.958-5.316l-19.866-17.726l4.828-5.408l0.926,0.829l20.863,18.616l4.958,4.424L101.553,139.68z
|
||||
M109.679,131.046l-3.936-3.513l-22.816-20.356l4.828-5.407l0.929,0.83l23.915,21.338l1.904,1.702L109.679,131.046z
|
||||
M101.086,109.122l6.486-7.146l4.892,4.44l0.002,0.002l-6.489,7.149l-4.894-4.442L101.086,109.122z"/>
|
||||
</g>
|
||||
</SvgIcon>
|
||||
);
|
||||
}
|
||||
M101.086,109.122l6.486-7.146l4.892,4.44l0.002,0.002l-6.489,7.149l-4.894-4.442L101.086,109.122z'
|
||||
/>
|
||||
</g>
|
||||
</SvgIcon>
|
||||
);
|
||||
}
|
||||
|
@ -1,11 +1,11 @@
|
||||
import React, { Component } from "react";
|
||||
import { SvgIcon } from "@mui/material"
|
||||
import React, { Component } from 'react';
|
||||
import { SvgIcon } from '@mui/material';
|
||||
|
||||
export default function CataloniaFlag(props) {
|
||||
return (
|
||||
<SvgIcon {...props} x="0px" y="0px" viewBox="0 0 810 540">
|
||||
<rect width="810" height="540" fill="#FCDD09"/>
|
||||
<path stroke="#DA121A" strokeWidth="60" d="M0,90H810m0,120H0m0,120H810m0,120H0"/>
|
||||
</SvgIcon>
|
||||
);
|
||||
}
|
||||
return (
|
||||
<SvgIcon {...props} x='0px' y='0px' viewBox='0 0 810 540'>
|
||||
<rect width='810' height='540' fill='#FCDD09' />
|
||||
<path stroke='#DA121A' strokeWidth='60' d='M0,90H810m0,120H0m0,120H810m0,120H0' />
|
||||
</SvgIcon>
|
||||
);
|
||||
}
|
||||
|
@ -1,16 +1,21 @@
|
||||
import React, { Component } from "react";
|
||||
import { SvgIcon } from "@mui/material"
|
||||
import React, { Component } from 'react';
|
||||
import { SvgIcon } from '@mui/material';
|
||||
|
||||
export default function EarthIcon(props) {
|
||||
return (
|
||||
<SvgIcon {...props} x="0px" y="0px" viewBox="0 0 440.45 440.45" >
|
||||
<g id="XMLID_34_">
|
||||
<g>
|
||||
<path style={{fill:"#1EA6C6"}} d="M102.62,211.975c0.02,0.08,0.04,0.15,0.06,0.23c1.91,7.94,3.42,19.8,1.63,35.19
|
||||
return (
|
||||
<SvgIcon {...props} x='0px' y='0px' viewBox='0 0 440.45 440.45'>
|
||||
<g id='XMLID_34_'>
|
||||
<g>
|
||||
<path
|
||||
style={{ fill: '#1EA6C6' }}
|
||||
d='M102.62,211.975c0.02,0.08,0.04,0.15,0.06,0.23c1.91,7.94,3.42,19.8,1.63,35.19
|
||||
c-1.91,16.48,5.5,32.66,19.11,42.15l18.56,12.95c0,0-6.37,48.72,11.31,74.36v0.01C65.91,359.665,0,282.645,0,190.225
|
||||
c0-53.81,22.35-102.41,58.27-137c-14.15,28.48-28.54,72.45-8.29,109.27c9.27,16.85,23.9,27.78,40.15,34.8
|
||||
C96.36,199.975,101.02,205.395,102.62,211.975z"/>
|
||||
<path style={{fill:"#1EA6C6"}} d="M190.23,0.005c41.46,0,79.82,13.26,111.07,35.79c0,0-16.37,25.11-15.71,50.17
|
||||
C96.36,199.975,101.02,205.395,102.62,211.975z'
|
||||
/>
|
||||
<path
|
||||
style={{ fill: '#1EA6C6' }}
|
||||
d='M190.23,0.005c41.46,0,79.82,13.26,111.07,35.79c0,0-16.37,25.11-15.71,50.17
|
||||
c0.15,5.99,4.84,10.89,10.81,11.52c0.42,0.04,0.85,0.07,1.27,0.07c4.55,0,8.75-2.58,10.81-6.73c4.38-8.78,15.91-19.42,45.02,1.77
|
||||
l0.01-0.01c2.17,3.61,4.22,7.3,6.14,11.07c0,0-10.16,2.28-23.77,0.6c-3.78-0.47-7.6,0.45-10.69,2.67
|
||||
c-2.15,1.55-4.62,3.78-7.36,6.53c-13.89,13.96-16.19,43-16.19,43c-0.27,6.06,0,12.76,0.97,20.16
|
||||
@ -20,28 +25,47 @@ export default function EarthIcon(props) {
|
||||
c-16.59-10.07-36.14-23.07-48.73-35.16c-6.33-6.07-15.04-8.98-23.76-8.04c-11.2,1.21-27.07,3.65-42.8,8.55
|
||||
c2.7-26.79-43.7-50.71-31.7-71.71c6.5-11.39,17.42-11.6,26.05-9.41c6.87,1.74,14.08-0.76,18.54-6.27
|
||||
c10.56-13.03,33.63-25.24,50.49-32.96c11.05-5.05,14.62-18.98,7.36-28.71c-22.27-29.9-53.82-49.59-53.82-49.59
|
||||
C141.44,4.815,165.27,0.005,190.23,0.005z M197.98,61.495l23-30c0,0-10-9-46-12C167.79,18.895,194.98,38.495,197.98,61.495z"/>
|
||||
<path style={{fill:"#F7CF52"}} d="M353.51,92.585l-0.01,0.01c-29.11-21.19-40.64-10.55-45.02-1.77c-2.06,4.15-6.26,6.73-10.81,6.73
|
||||
C141.44,4.815,165.27,0.005,190.23,0.005z M197.98,61.495l23-30c0,0-10-9-46-12C167.79,18.895,194.98,38.495,197.98,61.495z'
|
||||
/>
|
||||
<path
|
||||
style={{ fill: '#F7CF52' }}
|
||||
d='M353.51,92.585l-0.01,0.01c-29.11-21.19-40.64-10.55-45.02-1.77c-2.06,4.15-6.26,6.73-10.81,6.73
|
||||
c-0.42,0-0.85-0.03-1.27-0.07c-5.97-0.63-10.66-5.53-10.81-11.52c-0.66-25.06,15.71-50.17,15.71-50.17
|
||||
C322.33,50.935,340.14,70.275,353.51,92.585z"/>
|
||||
<path style={{fill:"#F7CF52"}} d="M380.45,190.225c0,22.57-3.93,44.23-11.15,64.32h-0.01c-6.07-10.32-8.37-22.55-8.98-33.34
|
||||
C322.33,50.935,340.14,70.275,353.51,92.585z'
|
||||
/>
|
||||
<path
|
||||
style={{ fill: '#F7CF52' }}
|
||||
d='M380.45,190.225c0,22.57-3.93,44.23-11.15,64.32h-0.01c-6.07-10.32-8.37-22.55-8.98-33.34
|
||||
c-0.68-11.96-11.49-20.89-23.33-19.05c-0.24,0.03-0.48,0.07-0.72,0.1c-16.41,2.4-31.48-9.2-33.65-25.64
|
||||
c-0.97-7.4-1.24-14.1-0.97-20.16c0,0,2.3-29.04,16.19-43c2.74-2.75,5.21-4.98,7.36-6.53c3.09-2.22,6.91-3.14,10.69-2.67
|
||||
c13.61,1.68,23.77-0.6,23.77-0.6C372.95,129.625,380.45,159.045,380.45,190.225z"/>
|
||||
<path style={{fill:"#F7CF52"}} d="M220.98,31.495l-23,30c-3-23-30.19-42.6-23-42C210.98,22.495,220.98,31.495,220.98,31.495z"/>
|
||||
<path style={{fill:"#F7CF52"}} d="M173.42,63.145c7.26,9.73,3.69,23.66-7.36,28.71c-16.86,7.72-39.93,19.93-50.49,32.96
|
||||
c13.61,1.68,23.77-0.6,23.77-0.6C372.95,129.625,380.45,159.045,380.45,190.225z'
|
||||
/>
|
||||
<path
|
||||
style={{ fill: '#F7CF52' }}
|
||||
d='M220.98,31.495l-23,30c-3-23-30.19-42.6-23-42C210.98,22.495,220.98,31.495,220.98,31.495z'
|
||||
/>
|
||||
<path
|
||||
style={{ fill: '#F7CF52' }}
|
||||
d='M173.42,63.145c7.26,9.73,3.69,23.66-7.36,28.71c-16.86,7.72-39.93,19.93-50.49,32.96
|
||||
c-4.46,5.51-11.67,8.01-18.54,6.27c-8.63-2.19-19.55-1.98-26.05,9.41c-12,21,34.4,44.92,31.7,71.71
|
||||
c-0.02-0.08-0.04-0.15-0.06-0.23c-1.6-6.58-6.26-12-12.49-14.68c-16.25-7.02-30.88-17.95-40.15-34.8
|
||||
c-20.25-36.82-5.86-80.79,8.29-109.27c17.54-16.91,38.33-30.47,61.33-39.67C119.6,13.555,151.15,33.245,173.42,63.145z"/>
|
||||
<path style={{fill:"#F7CF52"}} d="M217.97,246.855c17.77,10.79,21.93,34.83,8.76,50.92c-7.41,9.05-15.93,18.74-24.47,28.12
|
||||
c-20.25-36.82-5.86-80.79,8.29-109.27c17.54-16.91,38.33-30.47,61.33-39.67C119.6,13.555,151.15,33.245,173.42,63.145z'
|
||||
/>
|
||||
<path
|
||||
style={{ fill: '#F7CF52' }}
|
||||
d='M217.97,246.855c17.77,10.79,21.93,34.83,8.76,50.92c-7.41,9.05-15.93,18.74-24.47,28.12
|
||||
l-29.58,31.37c-14.04,14.58-19.39,19.59-19.39,19.59c-17.68-25.64-11.31-74.36-11.31-74.36l-18.56-12.95
|
||||
c-13.61-9.49-21.02-25.67-19.11-42.15c1.79-15.39,0.28-27.25-1.63-35.19c15.73-4.9,31.6-7.34,42.8-8.55
|
||||
c8.72-0.94,17.43,1.97,23.76,8.04C181.83,223.785,201.38,236.785,217.97,246.855z"/>
|
||||
</g>
|
||||
c8.72-0.94,17.43,1.97,23.76,8.04C181.83,223.785,201.38,236.785,217.97,246.855z'
|
||||
/>
|
||||
</g>
|
||||
<path style={{opacity:"0.3",fill:"#808080",enableBackground:"new"}} d="M190.23,0.005c5.8,0,11.54,0.26,17.2,0.77
|
||||
</g>
|
||||
<path
|
||||
style={{ opacity: '0.3', fill: '#808080', enableBackground: 'new' }}
|
||||
d='M190.23,0.005c5.8,0,11.54,0.26,17.2,0.77
|
||||
C110.48,9.515,34.5,90.995,34.5,190.225c0,99.25,76.01,180.74,172.99,189.45c-5.68,0.51-11.44,0.77-17.26,0.77
|
||||
C85.17,380.445,0,295.285,0,190.225S85.17,0.005,190.23,0.005z"/>
|
||||
</SvgIcon>
|
||||
);
|
||||
}
|
||||
C85.17,380.445,0,295.285,0,190.225S85.17,0.005,190.23,0.005z'
|
||||
/>
|
||||
</SvgIcon>
|
||||
);
|
||||
}
|
||||
|
@ -1,10 +1,10 @@
|
||||
import React, { Component } from "react";
|
||||
import { SvgIcon } from "@mui/material"
|
||||
import React, { Component } from 'react';
|
||||
import { SvgIcon } from '@mui/material';
|
||||
|
||||
export default function ExportIcon(props) {
|
||||
return (
|
||||
<SvgIcon sx={props.sx} color={props.color} viewBox="0 0 576 512">
|
||||
<path d="M192 312C192 298.8 202.8 288 216 288H384V160H256c-17.67 0-32-14.33-32-32L224 0H48C21.49 0 0 21.49 0 48v416C0 490.5 21.49 512 48 512h288c26.51 0 48-21.49 48-48v-128H216C202.8 336 192 325.3 192 312zM256 0v128h128L256 0zM568.1 295l-80-80c-9.375-9.375-24.56-9.375-33.94 0s-9.375 24.56 0 33.94L494.1 288H384v48h110.1l-39.03 39.03C450.3 379.7 448 385.8 448 392s2.344 12.28 7.031 16.97c9.375 9.375 24.56 9.375 33.94 0l80-80C578.3 319.6 578.3 304.4 568.1 295z"/>
|
||||
<SvgIcon sx={props.sx} color={props.color} viewBox='0 0 576 512'>
|
||||
<path d='M192 312C192 298.8 202.8 288 216 288H384V160H256c-17.67 0-32-14.33-32-32L224 0H48C21.49 0 0 21.49 0 48v416C0 490.5 21.49 512 48 512h288c26.51 0 48-21.49 48-48v-128H216C202.8 336 192 325.3 192 312zM256 0v128h128L256 0zM568.1 295l-80-80c-9.375-9.375-24.56-9.375-33.94 0s-9.375 24.56 0 33.94L494.1 288H384v48h110.1l-39.03 39.03C450.3 379.7 448 385.8 448 392s2.344 12.28 7.031 16.97c9.375 9.375 24.56 9.375 33.94 0l80-80C578.3 319.6 578.3 304.4 568.1 295z' />
|
||||
</SvgIcon>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -1,21 +1,48 @@
|
||||
import React, { Component } from "react";
|
||||
import { SvgIcon } from "@mui/material"
|
||||
import React, { Component } from 'react';
|
||||
import { SvgIcon } from '@mui/material';
|
||||
|
||||
export default function GoldIcon(props) {
|
||||
return (
|
||||
<SvgIcon {...props} x="0px" y="0px" viewBox="0 0 511.882 511.882">
|
||||
<polygon style={{fill:"#F6BB42"}} points="350.216,176.572 278.374,158.615 37.038,264.123 0,338.207 125.753,374.324 386.13,258.531
|
||||
"/>
|
||||
<polygon style={{fill:"#FFCE54"}} points="350.216,176.572 107.756,284.345 125.753,374.324 386.13,258.531 "/>
|
||||
<polygon style={{fill:"#E8AA3D"}} points="107.756,284.345 37.038,264.123 0.015,338.207 125.753,374.324 "/>
|
||||
<polygon style={{fill:"#F6BB42"}} points="475.969,212.682 404.127,194.717 162.791,300.232 125.753,374.324 251.504,410.41
|
||||
511.882,294.625 "/>
|
||||
<polygon style={{fill:"#FFCE54"}} points="475.969,212.682 233.508,320.431 251.504,410.41 511.882,294.625 "/>
|
||||
<polygon style={{fill:"#E8AA3D"}} points="233.508,320.431 162.791,300.232 125.753,374.324 251.504,410.41 "/>
|
||||
<polygon style={{fill:"#F6BB42"}} points="396.316,119.429 324.488,101.473 103.867,198.435 66.843,272.519 192.596,308.621
|
||||
432.245,201.379 "/>
|
||||
<polygon style={{fill:"#FFCE54"}} points="396.316,119.429 174.6,218.641 192.596,308.621 432.245,201.379 "/>
|
||||
<polygon style={{fill:"#E8AA3D"}} points="174.6,218.641 103.867,198.435 66.843,272.519 192.596,308.621 "/>
|
||||
</SvgIcon>
|
||||
);
|
||||
}
|
||||
return (
|
||||
<SvgIcon {...props} x='0px' y='0px' viewBox='0 0 511.882 511.882'>
|
||||
<polygon
|
||||
style={{ fill: '#F6BB42' }}
|
||||
points='350.216,176.572 278.374,158.615 37.038,264.123 0,338.207 125.753,374.324 386.13,258.531
|
||||
'
|
||||
/>
|
||||
<polygon
|
||||
style={{ fill: '#FFCE54' }}
|
||||
points='350.216,176.572 107.756,284.345 125.753,374.324 386.13,258.531 '
|
||||
/>
|
||||
<polygon
|
||||
style={{ fill: '#E8AA3D' }}
|
||||
points='107.756,284.345 37.038,264.123 0.015,338.207 125.753,374.324 '
|
||||
/>
|
||||
<polygon
|
||||
style={{ fill: '#F6BB42' }}
|
||||
points='475.969,212.682 404.127,194.717 162.791,300.232 125.753,374.324 251.504,410.41
|
||||
511.882,294.625 '
|
||||
/>
|
||||
<polygon
|
||||
style={{ fill: '#FFCE54' }}
|
||||
points='475.969,212.682 233.508,320.431 251.504,410.41 511.882,294.625 '
|
||||
/>
|
||||
<polygon
|
||||
style={{ fill: '#E8AA3D' }}
|
||||
points='233.508,320.431 162.791,300.232 125.753,374.324 251.504,410.41 '
|
||||
/>
|
||||
<polygon
|
||||
style={{ fill: '#F6BB42' }}
|
||||
points='396.316,119.429 324.488,101.473 103.867,198.435 66.843,272.519 192.596,308.621
|
||||
432.245,201.379 '
|
||||
/>
|
||||
<polygon
|
||||
style={{ fill: '#FFCE54' }}
|
||||
points='396.316,119.429 174.6,218.641 192.596,308.621 432.245,201.379 '
|
||||
/>
|
||||
<polygon
|
||||
style={{ fill: '#E8AA3D' }}
|
||||
points='174.6,218.641 103.867,198.435 66.843,272.519 192.596,308.621 '
|
||||
/>
|
||||
</SvgIcon>
|
||||
);
|
||||
}
|
||||
|
@ -1,10 +1,10 @@
|
||||
import React, { Component } from "react";
|
||||
import { SvgIcon } from "@mui/material"
|
||||
import React, { Component } from 'react';
|
||||
import { SvgIcon } from '@mui/material';
|
||||
|
||||
export default function NewTabIcon(props) {
|
||||
return (
|
||||
<SvgIcon sx={props.sx} color={props.color} viewBox="0 0 448 512">
|
||||
<path d="M256 64C256 46.33 270.3 32 288 32H415.1C415.1 32 415.1 32 415.1 32C420.3 32 424.5 32.86 428.2 34.43C431.1 35.98 435.5 38.27 438.6 41.3C438.6 41.35 438.6 41.4 438.7 41.44C444.9 47.66 447.1 55.78 448 63.9C448 63.94 448 63.97 448 64V192C448 209.7 433.7 224 416 224C398.3 224 384 209.7 384 192V141.3L214.6 310.6C202.1 323.1 181.9 323.1 169.4 310.6C156.9 298.1 156.9 277.9 169.4 265.4L338.7 96H288C270.3 96 256 81.67 256 64V64zM0 128C0 92.65 28.65 64 64 64H160C177.7 64 192 78.33 192 96C192 113.7 177.7 128 160 128H64V416H352V320C352 302.3 366.3 288 384 288C401.7 288 416 302.3 416 320V416C416 451.3 387.3 480 352 480H64C28.65 480 0 451.3 0 416V128z"/>
|
||||
<SvgIcon sx={props.sx} color={props.color} viewBox='0 0 448 512'>
|
||||
<path d='M256 64C256 46.33 270.3 32 288 32H415.1C415.1 32 415.1 32 415.1 32C420.3 32 424.5 32.86 428.2 34.43C431.1 35.98 435.5 38.27 438.6 41.3C438.6 41.35 438.6 41.4 438.7 41.44C444.9 47.66 447.1 55.78 448 63.9C448 63.94 448 63.97 448 64V192C448 209.7 433.7 224 416 224C398.3 224 384 209.7 384 192V141.3L214.6 310.6C202.1 323.1 181.9 323.1 169.4 310.6C156.9 298.1 156.9 277.9 169.4 265.4L338.7 96H288C270.3 96 256 81.67 256 64V64zM0 128C0 92.65 28.65 64 64 64H160C177.7 64 192 78.33 192 96C192 113.7 177.7 128 160 128H64V416H352V320C352 302.3 366.3 288 384 288C401.7 288 416 302.3 416 320V416C416 451.3 387.3 480 352 480H64C28.65 480 0 451.3 0 416V128z' />
|
||||
</SvgIcon>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -1,11 +1,12 @@
|
||||
import React, { Component } from "react";
|
||||
import { SvgIcon } from "@mui/material"
|
||||
import React, { Component } from 'react';
|
||||
import { SvgIcon } from '@mui/material';
|
||||
|
||||
export default function RoboSatsIcon(props) {
|
||||
return (
|
||||
<SvgIcon {...props} x="0px" y="0px" width="1000px" height="1000px" viewBox="0 0 1000 900">
|
||||
<g>
|
||||
<path d="M602.336,731.51c16.747-16.94,29.249-35.524,37.504-56.694c18.792-48.193,16.967-94.996-10.46-139.81
|
||||
return (
|
||||
<SvgIcon {...props} x='0px' y='0px' width='1000px' height='1000px' viewBox='0 0 1000 900'>
|
||||
<g>
|
||||
<path
|
||||
d='M602.336,731.51c16.747-16.94,29.249-35.524,37.504-56.694c18.792-48.193,16.967-94.996-10.46-139.81
|
||||
c-10.255-16.756-24.983-29.293-39.461-42.103c-67.731-59.932-135.412-119.919-203.104-179.895
|
||||
c-0.368-0.326-0.644-0.755-1.331-1.579c18.529-12.477,36.983-24.903,55.872-37.62c-9.61-6.799-18.917-13.385-28.648-20.27
|
||||
c11.763-14.483,23.273-28.656,34.738-42.773c13.313,7.081,24.784,5.523,32.075-4.132c6.395-8.467,5.794-20.59-1.412-28.52
|
||||
@ -15,46 +16,64 @@ export default function RoboSatsIcon(props) {
|
||||
c37.661,0.119,75.351,1.898,112.093,11.01c52.81,13.096,95.741,40.904,125.379,87.462c13.802,21.681,20.643,45.764,23.136,71.039
|
||||
c3.595,36.436,1.313,72.517-8.858,107.873c-11.943,41.515-37.09,74.011-69.641,101.357c-16.133,13.552-33.803,24.811-52.581,34.343
|
||||
c-1.3,0.659-2.533,1.445-4.148,2.375c80.735,102.152,161.255,204.034,242.318,306.6C761.843,731.51,682.637,731.51,602.336,731.51z
|
||||
"/>
|
||||
<path d="M282.877,389.186c25.706-0.109,46.42,20.376,46.55,46.038c0.131,25.994-20.404,46.852-46.238,46.96
|
||||
c-25.588,0.108-46.928-21.172-46.758-46.627C236.602,409.95,257.291,389.295,282.877,389.186z"/>
|
||||
<path d="M445.93,607.736c0.705-26.031,21.515-46.381,46.915-45.881c26.295,0.52,46.657,21.756,45.918,47.887
|
||||
c-0.721,25.455-21.862,45.67-47.178,45.104C465.779,654.273,445.244,633.082,445.93,607.736z"/>
|
||||
<path d="M175.223,550.758c23.365,20.689,46.15,40.865,69.337,61.396c-4.974,5.619-9.792,11.063-14.91,16.846
|
||||
'
|
||||
/>
|
||||
<path
|
||||
d='M282.877,389.186c25.706-0.109,46.42,20.376,46.55,46.038c0.131,25.994-20.404,46.852-46.238,46.96
|
||||
c-25.588,0.108-46.928-21.172-46.758-46.627C236.602,409.95,257.291,389.295,282.877,389.186z'
|
||||
/>
|
||||
<path
|
||||
d='M445.93,607.736c0.705-26.031,21.515-46.381,46.915-45.881c26.295,0.52,46.657,21.756,45.918,47.887
|
||||
c-0.721,25.455-21.862,45.67-47.178,45.104C465.779,654.273,445.244,633.082,445.93,607.736z'
|
||||
/>
|
||||
<path
|
||||
d='M175.223,550.758c23.365,20.689,46.15,40.865,69.337,61.396c-4.974,5.619-9.792,11.063-14.91,16.846
|
||||
c-5.634-4.988-11.167-9.738-16.519-14.684c-3.131-2.896-5.343-2.492-8.415,0.467c-9.944,9.58-20.234,18.801-29.493,27.332
|
||||
C175.223,613.414,175.223,582.512,175.223,550.758z"/>
|
||||
<path d="M379.124,731.533c-30.045,0-59.057,0-89.151,0c8.955-9.23,17.236-17.769,25.724-26.519
|
||||
C175.223,613.414,175.223,582.512,175.223,550.758z'
|
||||
/>
|
||||
<path
|
||||
d='M379.124,731.533c-30.045,0-59.057,0-89.151,0c8.955-9.23,17.236-17.769,25.724-26.519
|
||||
c-6.368-5.709-12.409-11.127-18.739-16.803c4.904-5.559,9.594-10.877,14.65-16.608C334.013,691.492,356.2,711.186,379.124,731.533z
|
||||
"/>
|
||||
</g>
|
||||
<g>
|
||||
<path d="M208.875,819.362h-15.495v34.557h-19.45v-94.397h35.075c11.151,0,19.752,2.485,25.804,7.455
|
||||
'
|
||||
/>
|
||||
</g>
|
||||
<g>
|
||||
<path
|
||||
d='M208.875,819.362h-15.495v34.557h-19.45v-94.397h35.075c11.151,0,19.752,2.485,25.804,7.455
|
||||
c6.051,4.972,9.077,11.995,9.077,21.071c0,6.44-1.394,11.811-4.182,16.111s-7.013,7.727-12.675,10.276l20.422,38.576v0.907h-20.876
|
||||
L208.875,819.362z M193.379,803.608h15.69c4.884,0,8.666-1.242,11.346-3.729c2.68-2.484,4.02-5.91,4.02-10.276
|
||||
c0-4.451-1.264-7.952-3.792-10.503c-2.529-2.55-6.409-3.825-11.638-3.825h-15.625V803.608z"/>
|
||||
<path d="M336.208,808.859c0,9.294-1.643,17.44-4.927,24.442c-3.285,7.002-7.985,12.405-14.101,16.209
|
||||
c0-4.451-1.264-7.952-3.792-10.503c-2.529-2.55-6.409-3.825-11.638-3.825h-15.625V803.608z'
|
||||
/>
|
||||
<path
|
||||
d='M336.208,808.859c0,9.294-1.643,17.44-4.927,24.442c-3.285,7.002-7.985,12.405-14.101,16.209
|
||||
c-6.117,3.804-13.129,5.705-21.039,5.705c-7.824,0-14.805-1.881-20.941-5.641c-6.138-3.761-10.892-9.131-14.263-16.111
|
||||
c-3.372-6.979-5.08-15.009-5.122-24.086v-4.668c0-9.292,1.674-17.473,5.024-24.539c3.349-7.067,8.082-12.491,14.199-16.273
|
||||
c6.116-3.781,13.106-5.673,20.974-5.673c7.866,0,14.857,1.892,20.974,5.673c6.116,3.782,10.849,9.206,14.199,16.273
|
||||
c3.349,7.066,5.024,15.226,5.024,24.475V808.859z M316.499,804.58c0-9.896-1.773-17.418-5.316-22.562
|
||||
c-3.545-5.144-8.602-7.716-15.171-7.716c-6.527,0-11.563,2.54-15.106,7.618c-3.545,5.079-5.339,12.524-5.381,22.335v4.604
|
||||
c0,9.639,1.772,17.116,5.316,22.433c3.543,5.316,8.644,7.975,15.301,7.975c6.526,0,11.541-2.561,15.042-7.683
|
||||
s5.272-12.588,5.316-22.4V804.58z"/>
|
||||
<path d="M350.342,853.919v-94.397h33.065c11.453,0,20.141,2.193,26.063,6.58c5.921,4.388,8.882,10.817,8.882,19.288
|
||||
s5.272-12.588,5.316-22.4V804.58z'
|
||||
/>
|
||||
<path
|
||||
d='M350.342,853.919v-94.397h33.065c11.453,0,20.141,2.193,26.063,6.58c5.921,4.388,8.882,10.817,8.882,19.288
|
||||
c0,4.626-1.189,8.699-3.566,12.222c-2.377,3.522-5.684,6.105-9.919,7.747c4.84,1.211,8.655,3.653,11.443,7.326
|
||||
c2.788,3.675,4.182,8.169,4.182,13.485c0,9.077-2.896,15.949-8.688,20.617c-5.792,4.668-14.047,7.046-24.767,7.132H350.342z
|
||||
M369.792,799.069h14.393c9.811-0.172,14.717-4.084,14.717-11.734c0-4.279-1.243-7.358-3.728-9.239
|
||||
c-2.486-1.88-6.408-2.82-11.767-2.82h-13.615V799.069z M369.792,812.814v25.479h16.662c4.581,0,8.158-1.091,10.73-3.274
|
||||
c2.571-2.182,3.858-5.196,3.858-9.044c0-8.645-4.474-13.031-13.421-13.161H369.792z"/>
|
||||
<path d="M512.621,808.859c0,9.294-1.645,17.44-4.928,24.442c-3.285,7.002-7.986,12.405-14.102,16.209
|
||||
c2.571-2.182,3.858-5.196,3.858-9.044c0-8.645-4.474-13.031-13.421-13.161H369.792z'
|
||||
/>
|
||||
<path
|
||||
d='M512.621,808.859c0,9.294-1.645,17.44-4.928,24.442c-3.285,7.002-7.986,12.405-14.102,16.209
|
||||
c-6.117,3.804-13.129,5.705-21.039,5.705c-7.824,0-14.805-1.881-20.941-5.641c-6.138-3.761-10.892-9.131-14.263-16.111
|
||||
c-3.372-6.979-5.08-15.009-5.122-24.086v-4.668c0-9.292,1.674-17.473,5.024-24.539c3.349-7.067,8.082-12.491,14.199-16.273
|
||||
c6.116-3.781,13.106-5.673,20.974-5.673c7.866,0,14.857,1.892,20.974,5.673c6.116,3.782,10.849,9.206,14.199,16.273
|
||||
c3.35,7.066,5.025,15.226,5.025,24.475V808.859z M492.911,804.58c0-9.896-1.773-17.418-5.316-22.562
|
||||
c-3.545-5.144-8.602-7.716-15.171-7.716c-6.527,0-11.563,2.54-15.106,7.618c-3.545,5.079-5.339,12.524-5.381,22.335v4.604
|
||||
c0,9.639,1.772,17.116,5.316,22.433c3.543,5.316,8.644,7.975,15.301,7.975c6.526,0,11.541-2.561,15.042-7.683
|
||||
s5.272-12.588,5.316-22.4V804.58z"/>
|
||||
<path d="M575.704,829.152c0-3.673-1.297-6.493-3.891-8.461c-2.593-1.966-7.261-4.041-14.004-6.224
|
||||
s5.272-12.588,5.316-22.4V804.58z'
|
||||
/>
|
||||
<path
|
||||
d='M575.704,829.152c0-3.673-1.297-6.493-3.891-8.461c-2.593-1.966-7.261-4.041-14.004-6.224
|
||||
c-6.742-2.183-12.081-4.333-16.014-6.451c-10.72-5.791-16.079-13.593-16.079-23.405c0-5.1,1.437-9.648,4.312-13.647
|
||||
c2.874-3.997,7.002-7.12,12.384-9.368c5.381-2.247,11.421-3.371,18.121-3.371c6.742,0,12.75,1.222,18.023,3.663
|
||||
c5.272,2.442,9.368,5.89,12.286,10.341c2.917,4.452,4.376,9.509,4.376,15.171h-19.45c0-4.321-1.361-7.683-4.084-10.081
|
||||
@ -62,11 +81,15 @@ export default function RoboSatsIcon(props) {
|
||||
c0,3.069,1.545,5.641,4.636,7.715c3.09,2.075,7.64,4.02,13.647,5.835c11.064,3.329,19.126,7.456,24.184,12.384
|
||||
c5.057,4.927,7.585,11.065,7.585,18.412c0,8.169-3.091,14.578-9.271,19.224c-6.181,4.646-14.501,6.97-24.961,6.97
|
||||
c-7.261,0-13.874-1.329-19.839-3.987s-10.514-6.299-13.647-10.925c-3.134-4.624-4.7-9.984-4.7-16.078h19.515
|
||||
c0,10.416,6.225,15.624,18.672,15.624c4.625,0,8.234-0.939,10.827-2.82C574.407,835.149,575.704,832.523,575.704,829.152z"/>
|
||||
<path d="M661.673,834.469H627.57l-6.483,19.45h-20.682l35.14-94.397h18.023l35.335,94.397h-20.683L661.673,834.469z
|
||||
M632.822,818.714h23.599l-11.864-35.334L632.822,818.714z"/>
|
||||
<path d="M760.999,775.275h-28.916v78.644h-19.45v-78.644h-28.526v-15.754h76.893V775.275z"/>
|
||||
<path d="M819.997,829.152c0-3.673-1.297-6.493-3.891-8.461c-2.593-1.966-7.261-4.041-14.004-6.224
|
||||
c0,10.416,6.225,15.624,18.672,15.624c4.625,0,8.234-0.939,10.827-2.82C574.407,835.149,575.704,832.523,575.704,829.152z'
|
||||
/>
|
||||
<path
|
||||
d='M661.673,834.469H627.57l-6.483,19.45h-20.682l35.14-94.397h18.023l35.335,94.397h-20.683L661.673,834.469z
|
||||
M632.822,818.714h23.599l-11.864-35.334L632.822,818.714z'
|
||||
/>
|
||||
<path d='M760.999,775.275h-28.916v78.644h-19.45v-78.644h-28.526v-15.754h76.893V775.275z' />
|
||||
<path
|
||||
d='M819.997,829.152c0-3.673-1.297-6.493-3.891-8.461c-2.593-1.966-7.261-4.041-14.004-6.224
|
||||
c-6.742-2.183-12.081-4.333-16.014-6.451c-10.72-5.791-16.079-13.593-16.079-23.405c0-5.1,1.437-9.648,4.312-13.647
|
||||
c2.874-3.997,7.002-7.12,12.384-9.368c5.381-2.247,11.421-3.371,18.121-3.371c6.742,0,12.75,1.222,18.023,3.663
|
||||
c5.272,2.442,9.368,5.89,12.286,10.341c2.917,4.452,4.376,9.509,4.376,15.171h-19.45c0-4.321-1.361-7.683-4.084-10.081
|
||||
@ -74,8 +97,9 @@ export default function RoboSatsIcon(props) {
|
||||
c0,3.069,1.545,5.641,4.636,7.715c3.09,2.075,7.64,4.02,13.647,5.835c11.064,3.329,19.126,7.456,24.184,12.384
|
||||
c5.057,4.927,7.585,11.065,7.585,18.412c0,8.169-3.091,14.578-9.271,19.224c-6.181,4.646-14.501,6.97-24.961,6.97
|
||||
c-7.261,0-13.874-1.329-19.839-3.987s-10.514-6.299-13.647-10.925c-3.134-4.624-4.7-9.984-4.7-16.078h19.515
|
||||
c0,10.416,6.225,15.624,18.672,15.624c4.625,0,8.234-0.939,10.827-2.82C818.7,835.149,819.997,832.523,819.997,829.152z"/>
|
||||
</g>
|
||||
</SvgIcon>
|
||||
);
|
||||
}
|
||||
c0,10.416,6.225,15.624,18.672,15.624c4.625,0,8.234-0.939,10.827-2.82C818.7,835.149,819.997,832.523,819.997,829.152z'
|
||||
/>
|
||||
</g>
|
||||
</SvgIcon>
|
||||
);
|
||||
}
|
||||
|
@ -1,11 +1,12 @@
|
||||
import React, { Component } from "react";
|
||||
import { SvgIcon } from "@mui/material"
|
||||
import React, { Component } from 'react';
|
||||
import { SvgIcon } from '@mui/material';
|
||||
|
||||
export default function RoboSatsNoTextIcon(props) {
|
||||
return (
|
||||
<SvgIcon {...props} x="0px" y="0px" width="1000px" height="1000px" viewBox="0 0 1000 800">
|
||||
<g>
|
||||
<path d="M602.336,731.51c16.747-16.94,29.249-35.524,37.504-56.694c18.792-48.193,16.967-94.996-10.46-139.81
|
||||
return (
|
||||
<SvgIcon {...props} x='0px' y='0px' width='1000px' height='1000px' viewBox='0 0 1000 800'>
|
||||
<g>
|
||||
<path
|
||||
d='M602.336,731.51c16.747-16.94,29.249-35.524,37.504-56.694c18.792-48.193,16.967-94.996-10.46-139.81
|
||||
c-10.255-16.756-24.983-29.293-39.461-42.103c-67.731-59.932-135.412-119.919-203.104-179.895
|
||||
c-0.368-0.326-0.644-0.755-1.331-1.579c18.529-12.477,36.983-24.903,55.872-37.62c-9.61-6.799-18.917-13.385-28.648-20.27
|
||||
c11.763-14.483,23.273-28.656,34.738-42.773c13.313,7.081,24.784,5.523,32.075-4.132c6.395-8.467,5.794-20.59-1.412-28.52
|
||||
@ -15,18 +16,27 @@ export default function RoboSatsNoTextIcon(props) {
|
||||
c37.661,0.119,75.351,1.898,112.093,11.01c52.81,13.096,95.741,40.904,125.379,87.462c13.802,21.681,20.643,45.764,23.136,71.039
|
||||
c3.595,36.436,1.313,72.517-8.858,107.873c-11.943,41.515-37.09,74.011-69.641,101.357c-16.133,13.552-33.803,24.811-52.581,34.343
|
||||
c-1.3,0.659-2.533,1.445-4.148,2.375c80.735,102.152,161.255,204.034,242.318,306.6C761.843,731.51,682.637,731.51,602.336,731.51z
|
||||
"/>
|
||||
<path d="M282.877,389.186c25.706-0.109,46.42,20.376,46.55,46.038c0.131,25.994-20.404,46.852-46.238,46.96
|
||||
c-25.588,0.108-46.928-21.172-46.758-46.627C236.602,409.95,257.291,389.295,282.877,389.186z"/>
|
||||
<path d="M445.93,607.736c0.705-26.031,21.515-46.381,46.915-45.881c26.295,0.52,46.657,21.756,45.918,47.887
|
||||
c-0.721,25.455-21.862,45.67-47.178,45.104C465.779,654.273,445.244,633.082,445.93,607.736z"/>
|
||||
<path d="M175.223,550.758c23.365,20.689,46.15,40.865,69.337,61.396c-4.974,5.619-9.792,11.063-14.91,16.846
|
||||
'
|
||||
/>
|
||||
<path
|
||||
d='M282.877,389.186c25.706-0.109,46.42,20.376,46.55,46.038c0.131,25.994-20.404,46.852-46.238,46.96
|
||||
c-25.588,0.108-46.928-21.172-46.758-46.627C236.602,409.95,257.291,389.295,282.877,389.186z'
|
||||
/>
|
||||
<path
|
||||
d='M445.93,607.736c0.705-26.031,21.515-46.381,46.915-45.881c26.295,0.52,46.657,21.756,45.918,47.887
|
||||
c-0.721,25.455-21.862,45.67-47.178,45.104C465.779,654.273,445.244,633.082,445.93,607.736z'
|
||||
/>
|
||||
<path
|
||||
d='M175.223,550.758c23.365,20.689,46.15,40.865,69.337,61.396c-4.974,5.619-9.792,11.063-14.91,16.846
|
||||
c-5.634-4.988-11.167-9.738-16.519-14.684c-3.131-2.896-5.343-2.492-8.415,0.467c-9.944,9.58-20.234,18.801-29.493,27.332
|
||||
C175.223,613.414,175.223,582.512,175.223,550.758z"/>
|
||||
<path d="M379.124,731.533c-30.045,0-59.057,0-89.151,0c8.955-9.23,17.236-17.769,25.724-26.519
|
||||
C175.223,613.414,175.223,582.512,175.223,550.758z'
|
||||
/>
|
||||
<path
|
||||
d='M379.124,731.533c-30.045,0-59.057,0-89.151,0c8.955-9.23,17.236-17.769,25.724-26.519
|
||||
c-6.368-5.709-12.409-11.127-18.739-16.803c4.904-5.559,9.594-10.877,14.65-16.608C334.013,691.492,356.2,711.186,379.124,731.533z
|
||||
"/>
|
||||
</g>
|
||||
</SvgIcon>
|
||||
);
|
||||
}
|
||||
'
|
||||
/>
|
||||
</g>
|
||||
</SvgIcon>
|
||||
);
|
||||
}
|
||||
|
@ -1,11 +1,12 @@
|
||||
import React, { Component } from "react";
|
||||
import { SvgIcon } from "@mui/material"
|
||||
import React, { Component } from 'react';
|
||||
import { SvgIcon } from '@mui/material';
|
||||
|
||||
export default function RoboSatsTextIcon(props) {
|
||||
return (
|
||||
<SvgIcon {...props} x="0px" y="0px" width="2000px" height="1000px" viewBox="0 300 2000 150">
|
||||
<g>
|
||||
<path d="M455.556,849.519c10.487-10.606,18.315-22.243,23.484-35.499c11.767-30.177,10.624-59.483-6.55-87.546
|
||||
return (
|
||||
<SvgIcon {...props} x='0px' y='0px' width='2000px' height='1000px' viewBox='0 300 2000 150'>
|
||||
<g>
|
||||
<path
|
||||
d='M455.556,849.519c10.487-10.606,18.315-22.243,23.484-35.499c11.767-30.177,10.624-59.483-6.55-87.546
|
||||
c-6.421-10.492-15.644-18.342-24.709-26.363c-42.412-37.528-84.791-75.089-127.178-112.646c-0.23-0.204-0.403-0.473-0.833-0.988
|
||||
c11.603-7.813,23.158-15.593,34.985-23.557c-6.017-4.258-11.845-8.382-17.938-12.692c7.366-9.069,14.573-17.943,21.752-26.783
|
||||
c8.336,4.434,15.519,3.458,20.084-2.588c4.005-5.302,3.629-12.893-0.884-17.858c-4.39-4.829-12.207-5.82-17.747-2.248
|
||||
@ -14,42 +15,58 @@ export default function RoboSatsTextIcon(props) {
|
||||
c1.134-0.051,2.23-0.144,3.327-0.144c61.359-0.006,122.719-0.134,184.077,0.059c23.582,0.074,47.182,1.188,70.189,6.894
|
||||
c33.068,8.2,59.95,25.613,78.508,54.766c8.642,13.576,12.927,28.656,14.487,44.482c2.252,22.815,0.823,45.408-5.545,67.547
|
||||
c-7.479,25.995-23.225,46.343-43.608,63.466c-10.102,8.486-21.167,15.536-32.924,21.505c-0.814,0.413-1.585,0.905-2.597,1.487
|
||||
c50.553,63.965,100.971,127.76,151.731,191.983C555.434,849.519,505.838,849.519,455.556,849.519z"/>
|
||||
<path d="M255.521,635.166c16.096-0.067,29.067,12.759,29.148,28.827c0.083,16.276-12.776,29.339-28.953,29.405
|
||||
c-16.022,0.067-29.385-13.258-29.278-29.196C226.544,648.168,239.5,635.234,255.521,635.166z"/>
|
||||
<path d="M357.619,772.016c0.441-16.3,13.472-29.043,29.376-28.729c16.465,0.325,29.215,13.623,28.752,29.985
|
||||
c-0.451,15.939-13.688,28.597-29.541,28.242C370.048,801.155,357.19,787.886,357.619,772.016z"/>
|
||||
<path d="M188.111,736.337c14.63,12.955,28.898,25.589,43.417,38.445c-3.115,3.519-6.132,6.927-9.336,10.548
|
||||
c50.553,63.965,100.971,127.76,151.731,191.983C555.434,849.519,505.838,849.519,455.556,849.519z'
|
||||
/>
|
||||
<path
|
||||
d='M255.521,635.166c16.096-0.067,29.067,12.759,29.148,28.827c0.083,16.276-12.776,29.339-28.953,29.405
|
||||
c-16.022,0.067-29.385-13.258-29.278-29.196C226.544,648.168,239.5,635.234,255.521,635.166z'
|
||||
/>
|
||||
<path
|
||||
d='M357.619,772.016c0.441-16.3,13.472-29.043,29.376-28.729c16.465,0.325,29.215,13.623,28.752,29.985
|
||||
c-0.451,15.939-13.688,28.597-29.541,28.242C370.048,801.155,357.19,787.886,357.619,772.016z'
|
||||
/>
|
||||
<path
|
||||
d='M188.111,736.337c14.63,12.955,28.898,25.589,43.417,38.445c-3.115,3.519-6.132,6.927-9.336,10.548
|
||||
c-3.528-3.123-6.993-6.098-10.344-9.194c-1.96-1.813-3.346-1.561-5.269,0.292c-6.227,5.999-12.67,11.772-18.468,17.114
|
||||
C188.111,775.57,188.111,756.221,188.111,736.337z"/>
|
||||
<path d="M315.788,849.533c-18.813,0-36.98,0-55.824,0c5.607-5.78,10.793-11.127,16.108-16.606
|
||||
c-3.987-3.574-7.77-6.967-11.734-10.521c3.071-3.48,6.007-6.811,9.173-10.398C287.54,824.461,301.433,836.792,315.788,849.533z"/>
|
||||
C188.111,775.57,188.111,756.221,188.111,736.337z'
|
||||
/>
|
||||
<path
|
||||
d='M315.788,849.533c-18.813,0-36.98,0-55.824,0c5.607-5.78,10.793-11.127,16.108-16.606
|
||||
c-3.987-3.574-7.77-6.967-11.734-10.521c3.071-3.48,6.007-6.811,9.173-10.398C287.54,824.461,301.433,836.792,315.788,849.533z'
|
||||
/>
|
||||
</g>
|
||||
<g>
|
||||
<path d="M766.812,758.155c0,18.361-3.246,34.457-9.734,48.289c-6.49,13.834-15.776,24.51-27.859,32.022
|
||||
<path
|
||||
d='M766.812,758.155c0,18.361-3.246,34.457-9.734,48.289c-6.49,13.834-15.776,24.51-27.859,32.022
|
||||
c-12.085,7.516-25.938,11.273-41.564,11.273c-15.458,0-29.249-3.715-41.374-11.145c-12.127-7.429-21.519-18.039-28.181-31.831
|
||||
c-6.66-13.789-10.035-29.653-10.118-47.584v-9.223c0-18.358,3.308-34.521,9.927-48.481c6.617-13.962,15.968-24.678,28.052-32.15
|
||||
c12.083-7.471,25.894-11.207,41.437-11.207c15.541,0,29.352,3.735,41.437,11.207c12.083,7.473,21.433,18.188,28.052,32.15
|
||||
c6.616,13.961,9.926,30.081,9.926,48.354V758.155L766.812,758.155z M727.873,749.701c0-19.553-3.503-34.411-10.504-44.574
|
||||
c-7.003-10.163-16.993-15.243-29.972-15.243c-12.895,0-22.845,5.017-29.846,15.05c-7.003,10.036-10.546,24.744-10.631,44.127v9.093
|
||||
c0,19.043,3.5,33.817,10.503,44.319c7,10.504,17.079,15.755,30.229,15.755c12.893,0,22.799-5.059,29.715-15.178
|
||||
c6.917-10.119,10.418-24.868,10.504-44.255L727.873,749.701L727.873,749.701z"/>
|
||||
<path d="M794.736,847.177V660.678h65.326c22.627,0,39.791,4.336,51.491,13.001c11.699,8.668,17.549,21.372,17.549,38.107
|
||||
c6.917-10.119,10.418-24.868,10.504-44.255L727.873,749.701L727.873,749.701z'
|
||||
/>
|
||||
<path
|
||||
d='M794.736,847.177V660.678h65.326c22.627,0,39.791,4.336,51.491,13.001c11.699,8.668,17.549,21.372,17.549,38.107
|
||||
c0,9.138-2.35,17.187-7.045,24.146c-4.697,6.961-11.23,12.062-19.597,15.307c9.562,2.39,17.1,7.216,22.607,14.474
|
||||
c5.508,7.259,8.263,16.138,8.263,26.642c0,17.934-5.723,31.51-17.165,40.733c-11.446,9.223-27.754,13.919-48.93,14.089
|
||||
L794.736,847.177L794.736,847.177z M833.162,738.813h28.437c19.383-0.341,29.076-8.069,29.076-23.186
|
||||
c0-8.453-2.455-14.538-7.364-18.252c-4.913-3.714-12.662-5.572-23.248-5.572h-26.9V738.813L833.162,738.813z M833.162,765.968
|
||||
v50.341h32.919c9.051,0,16.118-2.155,21.198-6.469c5.08-4.313,7.621-10.269,7.621-17.868c0-17.078-8.838-25.746-26.514-26.003
|
||||
L833.162,765.968L833.162,765.968z"/>
|
||||
<path d="M1115.343,758.155c0,18.361-3.245,34.457-9.734,48.289c-6.492,13.834-15.776,24.51-27.858,32.022
|
||||
L833.162,765.968L833.162,765.968z'
|
||||
/>
|
||||
<path
|
||||
d='M1115.343,758.155c0,18.361-3.245,34.457-9.734,48.289c-6.492,13.834-15.776,24.51-27.858,32.022
|
||||
c-12.085,7.516-25.94,11.273-41.567,11.273c-15.457,0-29.246-3.715-41.37-11.145c-12.127-7.429-21.521-18.039-28.182-31.831
|
||||
c-6.66-13.789-10.035-29.653-10.119-47.584v-9.223c0-18.358,3.309-34.521,9.928-48.481c6.616-13.962,15.966-24.678,28.051-32.15
|
||||
c12.081-7.471,25.894-11.207,41.436-11.207s29.354,3.735,41.439,11.207c12.079,7.473,21.432,18.188,28.05,32.15
|
||||
c6.616,13.961,9.926,30.081,9.926,48.354v8.325H1115.343z M1076.405,749.701c0-19.553-3.504-34.411-10.505-44.574
|
||||
s-16.992-15.243-29.973-15.243c-12.895,0-22.844,5.017-29.845,15.05c-7.004,10.036-10.548,24.744-10.632,44.127v9.093
|
||||
c0,19.043,3.501,33.817,10.503,44.319c7.002,10.504,17.079,15.755,30.229,15.755c12.896,0,22.802-5.059,29.717-15.178
|
||||
c6.918-10.119,10.419-24.868,10.505-44.255L1076.405,749.701L1076.405,749.701z"/>
|
||||
<path d="M1239.975,798.248c0-7.258-2.563-12.829-7.686-16.717c-5.123-3.884-14.346-7.982-27.666-12.296
|
||||
c6.918-10.119,10.419-24.868,10.505-44.255L1076.405,749.701L1076.405,749.701z'
|
||||
/>
|
||||
<path
|
||||
d='M1239.975,798.248c0-7.258-2.563-12.829-7.686-16.717c-5.123-3.884-14.346-7.982-27.666-12.296
|
||||
c-13.323-4.312-23.869-8.561-31.64-12.744c-21.178-11.443-31.766-26.855-31.766-46.241c0-10.075,2.838-19.064,8.517-26.963
|
||||
c5.679-7.897,13.835-14.067,24.466-18.508c10.631-4.439,22.563-6.66,35.801-6.66c13.323,0,25.191,2.412,35.609,7.236
|
||||
c10.417,4.826,18.509,11.636,24.272,20.43c5.765,8.796,8.647,18.787,8.647,29.973h-38.426c0-8.536-2.692-15.177-8.071-19.917
|
||||
@ -57,11 +74,15 @@ export default function RoboSatsTextIcon(props) {
|
||||
c0,6.063,3.053,11.143,9.16,15.241c6.104,4.099,15.091,7.941,26.962,11.528c21.859,6.577,37.786,14.73,47.776,24.465
|
||||
c9.991,9.735,14.987,21.861,14.987,36.377c0,16.139-6.106,28.8-18.317,37.979c-12.212,9.181-28.649,13.771-49.313,13.771
|
||||
c-14.347,0-27.411-2.626-39.195-7.878s-20.773-12.444-26.964-21.583c-6.192-9.136-9.286-19.725-9.286-31.767h38.556
|
||||
c0,20.581,12.296,30.87,36.891,30.87c9.136,0,16.269-1.858,21.391-5.573C1237.414,810.097,1239.975,804.907,1239.975,798.248z"/>
|
||||
<path d="M1409.822,808.75h-67.376l-12.809,38.427h-40.861l69.424-186.498h35.611l69.809,186.498h-40.861L1409.822,808.75z
|
||||
M1352.822,777.625h46.624l-23.44-69.809L1352.822,777.625z"/>
|
||||
<path d="M1606.055,691.805h-57.127v155.372h-38.429V691.805h-56.358v-31.126h151.914V691.805L1606.055,691.805z"/>
|
||||
<path d="M1722.617,798.248c0-7.258-2.563-12.829-7.687-16.717c-5.123-3.884-14.346-7.982-27.666-12.296
|
||||
c0,20.581,12.296,30.87,36.891,30.87c9.136,0,16.269-1.858,21.391-5.573C1237.414,810.097,1239.975,804.907,1239.975,798.248z'
|
||||
/>
|
||||
<path
|
||||
d='M1409.822,808.75h-67.376l-12.809,38.427h-40.861l69.424-186.498h35.611l69.809,186.498h-40.861L1409.822,808.75z
|
||||
M1352.822,777.625h46.624l-23.44-69.809L1352.822,777.625z'
|
||||
/>
|
||||
<path d='M1606.055,691.805h-57.127v155.372h-38.429V691.805h-56.358v-31.126h151.914V691.805L1606.055,691.805z' />
|
||||
<path
|
||||
d='M1722.617,798.248c0-7.258-2.563-12.829-7.687-16.717c-5.123-3.884-14.346-7.982-27.666-12.296
|
||||
c-13.323-4.312-23.87-8.561-31.639-12.744c-21.179-11.443-31.767-26.855-31.767-46.241c0-10.075,2.837-19.064,8.517-26.963
|
||||
c5.679-7.897,13.835-14.067,24.466-18.508c10.632-4.439,22.563-6.66,35.801-6.66c13.323,0,25.19,2.412,35.609,7.236
|
||||
c10.417,4.826,18.509,11.636,24.273,20.43c5.764,8.796,8.646,18.787,8.646,29.973h-38.426c0-8.536-2.692-15.177-8.072-19.917
|
||||
@ -69,8 +90,9 @@ export default function RoboSatsTextIcon(props) {
|
||||
c0,6.063,3.053,11.143,9.16,15.241c6.104,4.099,15.091,7.941,26.962,11.528c21.858,6.577,37.786,14.73,47.776,24.465
|
||||
c9.991,9.735,14.987,21.861,14.987,36.377c0,16.139-6.106,28.8-18.317,37.979c-12.212,9.181-28.648,13.771-49.313,13.771
|
||||
c-14.346,0-27.411-2.626-39.195-7.878s-20.774-12.444-26.964-21.583c-6.192-9.136-9.286-19.725-9.286-31.767h38.556
|
||||
c0,20.581,12.296,30.87,36.891,30.87c9.136,0,16.268-1.858,21.391-5.573C1720.055,810.097,1722.617,804.907,1722.617,798.248z"/>
|
||||
c0,20.581,12.296,30.87,36.891,30.87c9.136,0,16.268-1.858,21.391-5.573C1720.055,810.097,1722.617,804.907,1722.617,798.248z'
|
||||
/>
|
||||
</g>
|
||||
</SvgIcon>
|
||||
);
|
||||
}
|
||||
</SvgIcon>
|
||||
);
|
||||
}
|
||||
|
@ -1,50 +1,112 @@
|
||||
import React, { Component } from "react";
|
||||
import { SvgIcon } from "@mui/material"
|
||||
import React, { Component } from 'react';
|
||||
import { SvgIcon } from '@mui/material';
|
||||
|
||||
export default function SellSatsIcon(props) {
|
||||
return (
|
||||
<SvgIcon sx={props.sx} color={props.color} x="0px" y="0px" viewBox="0 0 300 300">
|
||||
<g>
|
||||
<polygon fill={props.color} points="121.609,110.04 125.066,113.125 130.511,117.982 133.404,120.564 138.846,125.421 141.355,127.66
|
||||
return (
|
||||
<SvgIcon sx={props.sx} color={props.color} x='0px' y='0px' viewBox='0 0 300 300'>
|
||||
<g>
|
||||
<polygon
|
||||
fill={props.color}
|
||||
points='121.609,110.04 125.066,113.125 130.511,117.982 133.404,120.564 138.846,125.421 141.355,127.66
|
||||
142.283,128.49 147.107,123.082 144.288,120.564 138.846,115.709 135.951,113.125 130.509,108.27 127.053,105.184
|
||||
122.057,100.729 119.174,102.5 115.611,104.689 116.166,105.184 "/>
|
||||
<polygon fill={props.color} points="133.966,105.184 139.412,110.04 142.305,112.623 147.744,117.479 149.48,119.025 150.408,119.855
|
||||
122.057,100.729 119.174,102.5 115.611,104.689 116.166,105.184 '
|
||||
/>
|
||||
<polygon
|
||||
fill={props.color}
|
||||
points='133.966,105.184 139.412,110.04 142.305,112.623 147.744,117.479 149.48,119.025 150.408,119.855
|
||||
155.234,114.449 153.188,112.623 147.744,107.768 144.854,105.186 139.41,100.328 135.951,97.244 132.6,94.252 126.15,98.213
|
||||
130.509,102.1 "/>
|
||||
<polygon fill={props.color} points="142.305,97.745 147.747,102.602 150.643,105.184 156.084,110.04 157.986,111.74 162.811,106.332
|
||||
161.523,105.184 156.08,100.328 153.188,97.746 147.744,92.891 144.288,89.805 142.473,88.184 136.027,92.146 138.846,94.66 "/>
|
||||
|
||||
<rect x="119.966" y="117.668" transform="matrix(0.7405 0.672 -0.672 0.7405 114.3002 -51.0573)" fill={props.color} width="6.611" height="9.654"/>
|
||||
<polygon fill={props.color} points="158.871,88.123 152.965,84.797 149.123,89.025 154.02,93.467 "/>
|
||||
<polygon fill={props.color} points="113.039,242.962 110.145,240.379 104.702,235.523 101.244,232.438 95.801,227.582 94.551,226.466
|
||||
130.509,102.1 '
|
||||
/>
|
||||
<polygon
|
||||
fill={props.color}
|
||||
points='142.305,97.745 147.747,102.602 150.643,105.184 156.084,110.04 157.986,111.74 162.811,106.332
|
||||
161.523,105.184 156.08,100.328 153.188,97.746 147.744,92.891 144.288,89.805 142.473,88.184 136.027,92.146 138.846,94.66 '
|
||||
/>
|
||||
|
||||
<rect
|
||||
x='119.966'
|
||||
y='117.668'
|
||||
transform='matrix(0.7405 0.672 -0.672 0.7405 114.3002 -51.0573)'
|
||||
fill={props.color}
|
||||
width='6.611'
|
||||
height='9.654'
|
||||
/>
|
||||
<polygon
|
||||
fill={props.color}
|
||||
points='158.871,88.123 152.965,84.797 149.123,89.025 154.02,93.467 '
|
||||
/>
|
||||
<polygon
|
||||
fill={props.color}
|
||||
points='113.039,242.962 110.145,240.379 104.702,235.523 101.244,232.438 95.801,227.582 94.551,226.466
|
||||
89.729,231.874 90.357,232.438 95.801,237.295 99.258,240.379 104.702,245.236 107.598,247.818 113.037,252.674 115.547,254.914
|
||||
116.475,255.744 121.305,250.335 118.48,247.818 "/>
|
||||
<polygon fill={props.color} points="121.938,235.021 119.046,232.438 113.602,227.582 110.145,224.497 104.702,219.641
|
||||
116.475,255.744 121.305,250.335 118.48,247.818 '
|
||||
/>
|
||||
<polygon
|
||||
fill={props.color}
|
||||
points='121.938,235.021 119.046,232.438 113.602,227.582 110.145,224.497 104.702,219.641
|
||||
103.604,218.66 102.675,217.834 97.854,223.24 99.258,224.497 104.702,229.352 108.159,232.438 113.602,237.295 116.495,239.876
|
||||
121.938,244.732 123.672,246.279 124.604,247.109 129.428,241.701 127.382,239.876 "/>
|
||||
<polygon fill={props.color} points="130.277,227.582 127.382,225 121.938,220.145 118.48,217.059 113.038,212.202 111.182,210.544
|
||||
121.938,244.732 123.672,246.279 124.604,247.109 129.428,241.701 127.382,239.876 '
|
||||
/>
|
||||
<polygon
|
||||
fill={props.color}
|
||||
points='130.277,227.582 127.382,225 121.938,220.145 118.48,217.059 113.038,212.202 111.182,210.544
|
||||
110.253,209.718 105.43,215.125 107.598,217.059 113.038,221.915 116.495,225 121.938,229.855 124.833,232.438 130.277,237.295
|
||||
132.18,238.994 137.002,233.585 135.718,232.438 "/>
|
||||
|
||||
<rect x="94.143" y="244.919" transform="matrix(0.7403 0.6723 -0.6723 0.7403 193.2158 -0.6485)" fill={props.color} width="6.609" height="9.657"/>
|
||||
<polygon fill={props.color} points="134.702,213.575 129.807,209.133 123.316,216.279 128.211,220.721 "/>
|
||||
<polygon fill={props.color} points="211.316,197.4 212.245,198.23 217.073,192.823 194.257,172.467 190.32,168.954 185.497,174.359
|
||||
187.4,176.062 "/>
|
||||
<polygon fill={props.color} points="219.443,188.768 220.369,189.598 225.197,184.189 205.331,166.463 199.373,161.146
|
||||
198.447,160.32 193.622,165.729 198.58,170.152 "/>
|
||||
<polygon fill={props.color} points="227.951,181.48 232.771,176.072 215.531,160.689 207.816,153.805 206.949,153.032
|
||||
206.021,152.205 201.341,157.452 201.198,157.611 208.893,164.475 "/>
|
||||
|
||||
<rect x="189.921" y="187.4" transform="matrix(0.7405 0.6721 -0.6721 0.7405 179.3349 -79.9756)" fill={props.color} width="6.609" height="9.655"/>
|
||||
<polygon fill={props.color} points="230.471,156.062 227.62,153.475 225.578,151.619 219.378,158.445 219.086,158.766 223.98,163.208
|
||||
"/>
|
||||
<path fill={props.color} d="M112.534,187.282c-7.511,0-14.995,1.878-21.647,5.43c-10.848,5.793-18.796,15.479-22.379,27.277
|
||||
132.18,238.994 137.002,233.585 135.718,232.438 '
|
||||
/>
|
||||
|
||||
<rect
|
||||
x='94.143'
|
||||
y='244.919'
|
||||
transform='matrix(0.7403 0.6723 -0.6723 0.7403 193.2158 -0.6485)'
|
||||
fill={props.color}
|
||||
width='6.609'
|
||||
height='9.657'
|
||||
/>
|
||||
<polygon
|
||||
fill={props.color}
|
||||
points='134.702,213.575 129.807,209.133 123.316,216.279 128.211,220.721 '
|
||||
/>
|
||||
<polygon
|
||||
fill={props.color}
|
||||
points='211.316,197.4 212.245,198.23 217.073,192.823 194.257,172.467 190.32,168.954 185.497,174.359
|
||||
187.4,176.062 '
|
||||
/>
|
||||
<polygon
|
||||
fill={props.color}
|
||||
points='219.443,188.768 220.369,189.598 225.197,184.189 205.331,166.463 199.373,161.146
|
||||
198.447,160.32 193.622,165.729 198.58,170.152 '
|
||||
/>
|
||||
<polygon
|
||||
fill={props.color}
|
||||
points='227.951,181.48 232.771,176.072 215.531,160.689 207.816,153.805 206.949,153.032
|
||||
206.021,152.205 201.341,157.452 201.198,157.611 208.893,164.475 '
|
||||
/>
|
||||
|
||||
<rect
|
||||
x='189.921'
|
||||
y='187.4'
|
||||
transform='matrix(0.7405 0.6721 -0.6721 0.7405 179.3349 -79.9756)'
|
||||
fill={props.color}
|
||||
width='6.609'
|
||||
height='9.655'
|
||||
/>
|
||||
<polygon
|
||||
fill={props.color}
|
||||
points='230.471,156.062 227.62,153.475 225.578,151.619 219.378,158.445 219.086,158.766 223.98,163.208
|
||||
'
|
||||
/>
|
||||
<path
|
||||
fill={props.color}
|
||||
d='M112.534,187.282c-7.511,0-14.995,1.878-21.647,5.43c-10.848,5.793-18.796,15.479-22.379,27.277
|
||||
c-3.583,11.796-2.365,24.266,3.426,35.112c8.033,15.037,23.646,24.379,40.742,24.379c7.51,0,14.996-1.877,21.648-5.431
|
||||
c10.847-5.793,18.794-15.479,22.377-27.274c3.583-11.797,2.365-24.267-3.426-35.113
|
||||
C145.245,196.624,129.635,187.282,112.534,187.282z M128.768,263.645c-16.688,8.912-37.514,2.588-46.43-14.099
|
||||
c-8.908-16.688-2.584-37.517,14.104-46.428c16.688-8.913,37.519-2.586,46.432,14.1
|
||||
C151.781,233.908,145.456,254.732,128.768,263.645z"/>
|
||||
<path fill={props.color} d="M52.191,144.639c6.326,5.757,17.865,13.457,34.295,22.881c18.544,10.64,43.998,23.457,59.836,27.527
|
||||
C151.781,233.908,145.456,254.732,128.768,263.645z'
|
||||
/>
|
||||
<path
|
||||
fill={props.color}
|
||||
d='M52.191,144.639c6.326,5.757,17.865,13.457,34.295,22.881c18.544,10.64,43.998,23.457,59.836,27.527
|
||||
c0.785,0.199,1.621,0.301,2.484,0.301c1.916,0,5.619-0.547,15.812-4.947c0.823,2.479,1.856,4.886,3.086,7.188
|
||||
c8.032,15.037,23.644,24.379,40.743,24.379c7.509,0,14.994-1.878,21.646-5.43c10.847-5.792,18.796-15.478,22.378-27.274
|
||||
c3.583-11.798,2.365-24.268-3.428-35.113c-1.488-2.787-3.262-5.414-5.295-7.842c3.117-2.348,5.279-4.3,6.706-6.043
|
||||
@ -61,12 +123,16 @@ export default function SellSatsIcon(props) {
|
||||
c8.911,16.687,2.588,37.511-14.101,46.422c-16.688,8.914-37.517,2.588-46.431-14.101c-1.646-3.086-2.771-6.316-3.406-9.586
|
||||
C174.003,178.857,173.9,175.221,174.344,171.672z M240.285,125.102l-34.512-20.586l34.512-60.934V125.102z M197.343,99.484
|
||||
l-47.237-28.183l-46.689,28.232l-37.43-66.089c0.445-0.066,0.896-0.113,1.357-0.113h163.938c1.125,0,2.196,0.216,3.19,0.595
|
||||
L197.343,99.484z"/>
|
||||
<path fill={props.color} d="M30.079,300H269.92c16.587,0,30.08-13.494,30.08-30.08V30.08C300,13.494,286.507,0,269.92,0H30.079
|
||||
L197.343,99.484z'
|
||||
/>
|
||||
<path
|
||||
fill={props.color}
|
||||
d='M30.079,300H269.92c16.587,0,30.08-13.494,30.08-30.08V30.08C300,13.494,286.507,0,269.92,0H30.079
|
||||
C13.494,0,0,13.494,0,30.08v239.84C0,286.506,13.494,300,30.079,300z M15.587,30.08c0-7.992,6.501-14.494,14.492-14.494H269.92
|
||||
c7.992,0,14.494,6.502,14.494,14.494v239.84c0,7.992-6.502,14.494-14.494,14.494H30.079c-7.991,0-14.492-6.502-14.492-14.494
|
||||
V30.08z"/>
|
||||
</g>
|
||||
</SvgIcon>
|
||||
);
|
||||
}
|
||||
V30.08z'
|
||||
/>
|
||||
</g>
|
||||
</SvgIcon>
|
||||
);
|
||||
}
|
||||
|
@ -1,13 +1,18 @@
|
||||
import React, { Component } from "react";
|
||||
import { SvgIcon } from "@mui/material"
|
||||
import React, { Component } from 'react';
|
||||
import { SvgIcon } from '@mui/material';
|
||||
|
||||
export default function SellSatsCheckedIcon(props) {
|
||||
return (
|
||||
<SvgIcon sx={props.sx} color={props.color} x="0px" y="0px" viewBox="0 0 300 300">
|
||||
<SvgIcon sx={props.sx} color={props.color} x='0px' y='0px' viewBox='0 0 300 300'>
|
||||
<g>
|
||||
<polygon fill={props.color} points="240.285,125.102 240.285,43.582 205.773,104.516 "/>
|
||||
<path fill={props.color} d="M58.583,40.294c-0.151,0.657-0.24,1.34-0.24,2.042v84.453l36.673-22.176L58.583,40.294z"/>
|
||||
<path fill={props.color} d="M112.81,199.078c-5.534-0.042-11.153,1.255-16.368,4.04c-16.688,8.911-23.012,29.739-14.104,46.428
|
||||
<polygon fill={props.color} points='240.285,125.102 240.285,43.582 205.773,104.516 ' />
|
||||
<path
|
||||
fill={props.color}
|
||||
d='M58.583,40.294c-0.151,0.657-0.24,1.34-0.24,2.042v84.453l36.673-22.176L58.583,40.294z'
|
||||
/>
|
||||
<path
|
||||
fill={props.color}
|
||||
d='M112.81,199.078c-5.534-0.042-11.153,1.255-16.368,4.04c-16.688,8.911-23.012,29.739-14.104,46.428
|
||||
c6.13,11.472,17.889,18.046,30.062,18.139c5.533,0.042,11.152-1.255,16.368-4.04c0.521-0.278,1.033-0.568,1.534-0.87
|
||||
c1.002-0.603,1.963-1.249,2.882-1.938c1.46-1.093,2.813-2.289,4.056-3.571c5.381-5.558,8.668-12.749,9.475-20.292
|
||||
c0.706-6.601-0.487-13.471-3.841-19.756C136.746,205.746,124.985,199.171,112.81,199.078z M129.807,209.133l4.895,4.442
|
||||
@ -18,10 +23,16 @@ export default function SellSatsCheckedIcon(props) {
|
||||
l-1.404-1.257l4.821-5.406l0.001,0.001l0.928,0.825l1.098,0.98l5.443,4.856l3.457,3.085l5.444,4.855l2.892,2.584l5.444,4.854
|
||||
l2.046,1.825L124.604,247.109z M132.18,238.994l-1.903-1.699l-5.444-4.857l-2.895-2.582L116.495,225l-3.457-3.085l-5.44-4.856
|
||||
l-2.168-1.934l4.823-5.407l0.929,0.826l1.856,1.658l5.442,4.856l3.458,3.086l4.854,4.33l0.589,0.525l2.895,2.582l5.441,4.855
|
||||
l1.283,1.146l0.001,0.001L132.18,238.994z"/>
|
||||
<path fill={props.color} d="M103.417,99.533l46.689-28.232l47.237,28.183l10.278-18.148l26.851-47.409l0.001-0.001
|
||||
c-0.994-0.379-2.065-0.595-3.19-0.595H67.344c-0.461,0-0.912,0.047-1.357,0.113l0.002,0.003L103.417,99.533z"/>
|
||||
<path fill={props.color} d="M188.072,137.845c2.039-1.089,4.131-1.976,6.249-2.708c12.551-4.337,26.17-2.534,37.015,4.271l0.001,0
|
||||
l1.283,1.146l0.001,0.001L132.18,238.994z'
|
||||
/>
|
||||
<path
|
||||
fill={props.color}
|
||||
d='M103.417,99.533l46.689-28.232l47.237,28.183l10.278-18.148l26.851-47.409l0.001-0.001
|
||||
c-0.994-0.379-2.065-0.595-3.19-0.595H67.344c-0.461,0-0.912,0.047-1.357,0.113l0.002,0.003L103.417,99.533z'
|
||||
/>
|
||||
<path
|
||||
fill={props.color}
|
||||
d='M188.072,137.845c2.039-1.089,4.131-1.976,6.249-2.708c12.551-4.337,26.17-2.534,37.015,4.271l0.001,0
|
||||
c2.595-1.757,4.685-3.269,6.238-4.499l-56.337-33.61c0,0.001,0,0.003,0,0.004c1.895,17.026-6.509,34.3-22.518,42.847
|
||||
c-6.553,3.5-13.612,5.129-20.564,5.076c-15.294-0.117-30.068-8.378-37.768-22.792c-1.731-3.242-3.001-6.613-3.84-10.029
|
||||
l7.985-4.906l0.001,0c0.578,3.681,1.761,7.325,3.615,10.793c4.733,8.866,12.831,14.807,21.884,17.093
|
||||
@ -35,8 +46,11 @@ export default function SellSatsCheckedIcon(props) {
|
||||
M132.6,94.252l3.351,2.992l3.459,3.084l5.444,4.858l2.89,2.582l5.443,4.855l2.046,1.825l0.001,0.001l-4.826,5.406l-0.928-0.83
|
||||
l-1.736-1.546l-5.439-4.856l-2.893-2.583l-5.446-4.856l-3.457-3.084l-4.359-3.887L132.6,94.252z M119.174,102.5l2.883-1.771
|
||||
l4.996,4.455l3.456,3.086l5.442,4.855l2.895,2.584l5.442,4.855l2.819,2.518l-4.824,5.408l-0.928-0.83l-2.509-2.239l-5.442-4.857
|
||||
l-2.893-2.582l-5.445-4.857l-3.457-3.085l-5.443-4.856l-0.553-0.493l-0.002-0.002L119.174,102.5z"/>
|
||||
<path fill={props.color} d="M231.82,150.836c-2.649-2.482-5.65-4.502-8.875-6.015c-9.465-4.428-20.827-4.506-30.732,0.785
|
||||
l-2.893-2.582l-5.445-4.857l-3.457-3.085l-5.443-4.856l-0.553-0.493l-0.002-0.002L119.174,102.5z'
|
||||
/>
|
||||
<path
|
||||
fill={props.color}
|
||||
d='M231.82,150.836c-2.649-2.482-5.65-4.502-8.875-6.015c-9.465-4.428-20.827-4.506-30.732,0.785
|
||||
c-10.213,5.453-16.535,15.369-17.869,26.066c-0.119,0.951-0.191,1.909-0.23,2.87c-0.108,2.625,0.076,5.276,0.587,7.903
|
||||
c0.635,3.271,1.76,6.5,3.405,9.587c8.914,16.688,29.744,23.015,46.432,14.101c10.432-5.569,16.812-15.792,17.956-26.751
|
||||
c0.686-6.574-0.514-13.413-3.854-19.671C236.818,156.305,234.497,153.338,231.82,150.836z M219.378,158.445l6.2-6.826l2.042,1.855
|
||||
@ -44,8 +58,11 @@ export default function SellSatsCheckedIcon(props) {
|
||||
l1.473-1.623l4.895,4.442L197.446,192.499z M212.245,198.23l-0.929-0.83L187.4,176.062l-1.903-1.703l4.823-5.405l3.937,3.513
|
||||
l22.816,20.356L212.245,198.23z M220.369,189.598l-0.926-0.83l-20.863-18.615l-4.958-4.424l4.825-5.408l0.926,0.826l5.958,5.316
|
||||
l19.866,17.727L220.369,189.598z M227.951,181.48l-19.059-17.006l-7.694-6.863l0.143-0.159l4.681-5.247l0.928,0.827l0.867,0.772
|
||||
l7.715,6.885l17.24,15.383L227.951,181.48z"/>
|
||||
<path fill={props.color} d="M269.92,0H30.079C13.494,0,0,13.494,0,30.08v239.84C0,286.506,13.494,300,30.079,300H269.92
|
||||
l7.715,6.885l17.24,15.383L227.951,181.48z'
|
||||
/>
|
||||
<path
|
||||
fill={props.color}
|
||||
d='M269.92,0H30.079C13.494,0,0,13.494,0,30.08v239.84C0,286.506,13.494,300,30.079,300H269.92
|
||||
c16.587,0,30.08-13.494,30.08-30.08V30.08C300,13.494,286.507,0,269.92,0z M157.316,244.557c-0.187,0.741-0.392,1.481-0.615,2.219
|
||||
c-3.583,11.795-11.53,21.48-22.377,27.273c-6.652,3.555-14.138,5.432-21.648,5.432c-17.096,0-32.709-9.342-40.742-24.379
|
||||
c-3.62-6.779-5.453-14.192-5.444-21.679c0.004-2.995,0.302-6.001,0.898-8.983c0.298-1.491,0.671-2.977,1.119-4.451
|
||||
@ -57,8 +74,9 @@ export default function SellSatsCheckedIcon(props) {
|
||||
c-16.43-9.424-27.969-17.124-34.295-22.88c-1.155-1.052-2.111-2.014-2.902-2.899c-3.426-3.833-3.765-6.229-3.761-8.206V42.337
|
||||
c0-12.027,9.789-21.814,21.817-21.814l163.939-0.005c5.638,0,10.784,2.151,14.66,5.675c4.393,3.994,7.155,9.752,7.155,16.143
|
||||
v91.201c0,2.378-0.841,4.516-2.646,6.729c-1.427,1.743-3.589,3.695-6.706,6.043c2.033,2.428,3.807,5.055,5.295,7.841
|
||||
C254.836,164.996,256.054,177.466,252.471,189.264z"/>
|
||||
C254.836,164.996,256.054,177.466,252.471,189.264z'
|
||||
/>
|
||||
</g>
|
||||
</SvgIcon>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -1,11 +1,13 @@
|
||||
import React, { Component } from "react";
|
||||
import { SvgIcon } from "@mui/material"
|
||||
import React, { Component } from 'react';
|
||||
import { SvgIcon } from '@mui/material';
|
||||
|
||||
export default function SendReceiveIcon(props) {
|
||||
return (
|
||||
<SvgIcon sx={props.sx} color={props.color} x="0px" y="0px" viewBox="0 0 300 300">
|
||||
<g>
|
||||
<path fill={props.color} d="M150.021,2.579C68.341,2.579,2.127,68.793,2.127,150.472c0,81.682,66.214,147.895,147.895,147.895
|
||||
return (
|
||||
<SvgIcon sx={props.sx} color={props.color} x='0px' y='0px' viewBox='0 0 300 300'>
|
||||
<g>
|
||||
<path
|
||||
fill={props.color}
|
||||
d='M150.021,2.579C68.341,2.579,2.127,68.793,2.127,150.472c0,81.682,66.214,147.895,147.895,147.895
|
||||
c81.676,0,147.89-66.213,147.89-147.895C297.911,68.793,231.697,2.579,150.021,2.579z M99.195,73.557
|
||||
c0,0,60.301,60.307,60.306,60.309c4.899,4.895,11.188,13.849,8.663,21.061c-1.835,5.236-6.053,9.546-9.893,13.383
|
||||
c-0.091,0.093-59.076,59.078-59.076,59.078c-6.26,6.26-16.406,6.26-22.665,0c-6.261-6.256-6.261-16.406,0-22.665l54.247-54.25
|
||||
@ -13,8 +15,9 @@ export default function SendReceiveIcon(props) {
|
||||
z M146.365,73.557c3.125-3.128,7.23-4.693,11.33-4.693c4.101,0,8.204,1.565,11.335,4.693c0,0,60.303,60.307,60.308,60.309
|
||||
c4.895,4.894,11.188,13.849,8.659,21.061c-1.832,5.236-6.05,9.546-9.889,13.383c-0.092,0.094-59.078,59.078-59.078,59.078
|
||||
c-6.256,6.26-16.405,6.26-22.665,0c-6.258-6.256-6.258-16.406,0-22.665l54.246-54.25l-54.246-54.25
|
||||
C140.107,89.966,140.107,79.818,146.365,73.557z"/>
|
||||
</g>
|
||||
</SvgIcon>
|
||||
);
|
||||
}
|
||||
C140.107,89.966,140.107,79.818,146.365,73.557z'
|
||||
/>
|
||||
</g>
|
||||
</SvgIcon>
|
||||
);
|
||||
}
|
||||
|
@ -1,11 +1,10 @@
|
||||
import React, { Component } from "react";
|
||||
import { SvgIcon } from "@mui/material"
|
||||
import React, { Component } from 'react';
|
||||
import { SvgIcon } from '@mui/material';
|
||||
|
||||
export default function UserNinjaIcon(props) {
|
||||
return (
|
||||
<SvgIcon {...props} x="0px" y="0px" viewBox="0 0 512 512">
|
||||
<path d="M64 192c27.25 0 51.75-11.5 69.25-29.75c15 54 64 93.75 122.8 93.75c70.75 0 127.1-57.25 127.1-128s-57.25-128-127.1-128c-50.38 0-93.63 29.38-114.5 71.75C124.1 47.75 96 32 64 32c0 33.37 17.12 62.75 43.13 80C81.13 129.3 64 158.6 64 192zM208 96h95.1C321.7 96 336 110.3 336 128h-160C176 110.3 190.3 96 208 96zM337.8 306.9L256 416L174.2 306.9C93.36 321.6 32 392.2 32 477.3c0 19.14 15.52 34.67 34.66 34.67H445.3c19.14 0 34.66-15.52 34.66-34.67C480 392.2 418.6 321.6 337.8 306.9z"/>
|
||||
</SvgIcon>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<SvgIcon {...props} x='0px' y='0px' viewBox='0 0 512 512'>
|
||||
<path d='M64 192c27.25 0 51.75-11.5 69.25-29.75c15 54 64 93.75 122.8 93.75c70.75 0 127.1-57.25 127.1-128s-57.25-128-127.1-128c-50.38 0-93.63 29.38-114.5 71.75C124.1 47.75 96 32 64 32c0 33.37 17.12 62.75 43.13 80C81.13 129.3 64 158.6 64 192zM208 96h95.1C321.7 96 336 110.3 336 128h-160C176 110.3 190.3 96 208 96zM337.8 306.9L256 416L174.2 306.9C93.36 321.6 32 392.2 32 477.3c0 19.14 15.52 34.67 34.66 34.67H445.3c19.14 0 34.66-15.52 34.66-34.67C480 392.2 418.6 321.6 337.8 306.9z' />
|
||||
</SvgIcon>
|
||||
);
|
||||
}
|
||||
|
@ -1,20 +1,20 @@
|
||||
export { default as AmbossIcon } from "./Amboss";
|
||||
export { default as BitcoinIcon } from "./Bitcoin";
|
||||
export { default as BitcoinSignIcon } from "./BitcoinSign";
|
||||
export { default as BuySatsIcon } from "./BuySats";
|
||||
export { default as BuySatsCheckedIcon } from "./BuySatsChecked";
|
||||
export { default as EarthIcon } from "./Earth";
|
||||
export { default as GoldIcon } from "./Gold";
|
||||
export { default as NewTabIcon } from "./NewTab";
|
||||
export { default as RoboSatsIcon } from "./RoboSats";
|
||||
export { default as RoboSatsNoTextIcon } from "./RoboSatsNoText";
|
||||
export { default as RoboSatsTextIcon } from "./RoboSatsText";
|
||||
export { default as SellSatsCheckedIcon } from "./SellSatsChecked";
|
||||
export { default as SellSatsIcon } from "./SellSats";
|
||||
export { default as SendReceiveIcon } from "./SendReceive";
|
||||
export { default as ExportIcon } from "./Export";
|
||||
export { default as UserNinjaIcon } from "./UserNinja";
|
||||
export { default as AmbossIcon } from './Amboss';
|
||||
export { default as BitcoinIcon } from './Bitcoin';
|
||||
export { default as BitcoinSignIcon } from './BitcoinSign';
|
||||
export { default as BuySatsIcon } from './BuySats';
|
||||
export { default as BuySatsCheckedIcon } from './BuySatsChecked';
|
||||
export { default as EarthIcon } from './Earth';
|
||||
export { default as GoldIcon } from './Gold';
|
||||
export { default as NewTabIcon } from './NewTab';
|
||||
export { default as RoboSatsIcon } from './RoboSats';
|
||||
export { default as RoboSatsNoTextIcon } from './RoboSatsNoText';
|
||||
export { default as RoboSatsTextIcon } from './RoboSatsText';
|
||||
export { default as SellSatsCheckedIcon } from './SellSatsChecked';
|
||||
export { default as SellSatsIcon } from './SellSats';
|
||||
export { default as SendReceiveIcon } from './SendReceive';
|
||||
export { default as ExportIcon } from './Export';
|
||||
export { default as UserNinjaIcon } from './UserNinja';
|
||||
|
||||
// Some Flags missing on react-flags
|
||||
export { default as BasqueCountryFlag } from "./BasqueCountryFlag";
|
||||
export { default as CataloniaFlag } from "./CataloniaFlag";
|
||||
export { default as BasqueCountryFlag } from './BasqueCountryFlag';
|
||||
export { default as CataloniaFlag } from './CataloniaFlag';
|
||||
|
@ -1,5 +1,5 @@
|
||||
import React, { useState, useEffect } from "react";
|
||||
import { Box, LinearProgress } from "@mui/material"
|
||||
import React, { useState, useEffect } from 'react';
|
||||
import { Box, LinearProgress } from '@mui/material';
|
||||
import { calcTimeDelta } from 'react-countdown';
|
||||
|
||||
type Props = {
|
||||
@ -7,10 +7,7 @@ type Props = {
|
||||
totalSecsExp: number;
|
||||
};
|
||||
|
||||
const LinearDeterminate = ({
|
||||
expiresAt,
|
||||
totalSecsExp,
|
||||
}: Props): JSX.Element => {
|
||||
const LinearDeterminate = ({ expiresAt, totalSecsExp }: Props): JSX.Element => {
|
||||
const [progress, setProgress] = useState<number>(0);
|
||||
|
||||
useEffect(() => {
|
||||
@ -28,7 +25,7 @@ const LinearDeterminate = ({
|
||||
|
||||
return (
|
||||
<Box sx={{ width: '100%' }}>
|
||||
<LinearProgress variant="determinate" value={progress} />
|
||||
<LinearProgress variant='determinate' value={progress} />
|
||||
</Box>
|
||||
);
|
||||
};
|
||||
|
@ -1 +1 @@
|
||||
export { default } from "./LinearDeterminate";
|
||||
export { default } from './LinearDeterminate';
|
||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -1,60 +1,107 @@
|
||||
import React, { Component } from 'react'
|
||||
import { withTranslation } from "react-i18next";
|
||||
import PaymentIcon from './payment-methods/Icons'
|
||||
import {Tooltip} from "@mui/material"
|
||||
import { paymentMethods, swapDestinations } from "./payment-methods/Methods";
|
||||
import React, { Component } from 'react';
|
||||
import { withTranslation } from 'react-i18next';
|
||||
import PaymentIcon from './payment-methods/Icons';
|
||||
import { Tooltip } from '@mui/material';
|
||||
import { paymentMethods, swapDestinations } from './payment-methods/Methods';
|
||||
|
||||
const ns = [{name: "not specified",icon:'notspecified'}];
|
||||
const ns = [{ name: 'not specified', icon: 'notspecified' }];
|
||||
const methods = ns.concat(swapDestinations).concat(paymentMethods);
|
||||
|
||||
class PaymentText extends Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
constructor(props) {
|
||||
super(props);
|
||||
}
|
||||
|
||||
parseText() {
|
||||
const { t } = this.props;
|
||||
var rows = [];
|
||||
var custom_methods = this.props.text;
|
||||
// Adds icons for each PaymentMethod that matches
|
||||
methods.forEach((method, i) => {
|
||||
if (this.props.text.includes(method.name)) {
|
||||
custom_methods = custom_methods.replace(method.name, '');
|
||||
rows.push(
|
||||
<Tooltip
|
||||
key={`${method.name}-${i}`}
|
||||
placement='top'
|
||||
enterTouchDelay={0}
|
||||
title={t(method.name)}
|
||||
>
|
||||
<div
|
||||
style={{
|
||||
display: 'inline-block',
|
||||
width: this.props.size + 2,
|
||||
height: this.props.size,
|
||||
}}
|
||||
>
|
||||
<PaymentIcon width={this.props.size} height={this.props.size} icon={method.icon} />
|
||||
</div>
|
||||
</Tooltip>,
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
// Adds a Custom icon if there are words that do not match
|
||||
var chars_left = custom_methods
|
||||
.replace(' ', '')
|
||||
.replace(' ', '')
|
||||
.replace(' ', '')
|
||||
.replace(' ', '')
|
||||
.replace(' ', '');
|
||||
|
||||
if (chars_left.length > 0) {
|
||||
rows.push(
|
||||
<Tooltip
|
||||
key={'pushed'}
|
||||
placement='top'
|
||||
enterTouchDelay={0}
|
||||
title={
|
||||
this.props.verbose
|
||||
? this.props.othersText
|
||||
: this.props.othersText + ': ' + custom_methods
|
||||
}
|
||||
>
|
||||
<div
|
||||
style={{
|
||||
position: 'relative',
|
||||
display: 'inline-block',
|
||||
width: this.props.size + 2,
|
||||
maxHeight: this.props.size,
|
||||
top: '-1px',
|
||||
}}
|
||||
>
|
||||
<PaymentIcon
|
||||
width={this.props.size * 1.1}
|
||||
height={this.props.size * 1.1}
|
||||
icon={'custom'}
|
||||
/>
|
||||
</div>
|
||||
</Tooltip>,
|
||||
);
|
||||
}
|
||||
|
||||
parseText(){
|
||||
const { t } = this.props;
|
||||
var rows = [];
|
||||
var custom_methods = this.props.text;
|
||||
// Adds icons for each PaymentMethod that matches
|
||||
methods.forEach((method, i) =>{
|
||||
if(this.props.text.includes(method.name)){
|
||||
custom_methods = custom_methods.replace(method.name,'')
|
||||
rows.push(
|
||||
<Tooltip key={`${method.name}-${i}`} placement="top" enterTouchDelay={0} title={t(method.name)}>
|
||||
<div style={{display: 'inline-block', width: this.props.size+2, height: this.props.size}}>
|
||||
<PaymentIcon width={this.props.size} height={this.props.size} icon={method.icon}/>
|
||||
</div>
|
||||
</Tooltip>
|
||||
);
|
||||
}
|
||||
})
|
||||
|
||||
// Adds a Custom icon if there are words that do not match
|
||||
var chars_left = custom_methods.replace(' ','').replace(' ','').replace(' ','').replace(' ','').replace(' ','')
|
||||
|
||||
if(chars_left.length > 0){rows.push(
|
||||
<Tooltip key={"pushed"} placement="top" enterTouchDelay={0} title={this.props.verbose ? this.props.othersText: this.props.othersText+": "+ custom_methods} >
|
||||
<div style={{position:'relative', display: 'inline-block',width: this.props.size+2, maxHeight: this.props.size, top:'-1px'}}>
|
||||
<PaymentIcon width={this.props.size*1.1} height={this.props.size*1.1} icon={"custom"}/>
|
||||
</div>
|
||||
</Tooltip>
|
||||
)}
|
||||
|
||||
if(this.props.verbose){
|
||||
return (<>{rows} <div style={{display: 'inline-block'}}> <span>{custom_methods}</span></div></>)
|
||||
}else{
|
||||
return rows
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
if (this.props.verbose) {
|
||||
return (
|
||||
<div style={{display:'flex',alignItems:'center', flexWrap:'wrap'}}>
|
||||
{this.parseText()}
|
||||
</div>
|
||||
)
|
||||
<>
|
||||
{rows}{' '}
|
||||
<div style={{ display: 'inline-block' }}>
|
||||
{' '}
|
||||
<span>{custom_methods}</span>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
} else {
|
||||
return rows;
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<div style={{ display: 'flex', alignItems: 'center', flexWrap: 'wrap' }}>
|
||||
{this.parseText()}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default withTranslation()(PaymentText);
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { Slider } from "@mui/material"
|
||||
import { Slider } from '@mui/material';
|
||||
import { styled } from '@mui/material/styles';
|
||||
|
||||
const RangeSlider = styled(Slider)(({ theme }) => ({
|
||||
@ -6,15 +6,15 @@ const RangeSlider = styled(Slider)(({ theme }) => ({
|
||||
height: 3,
|
||||
padding: '13px 0',
|
||||
'& .MuiSlider-thumb': {
|
||||
height: `${27/16}em`,
|
||||
width: `${27/16}em`,
|
||||
height: `${27 / 16}em`,
|
||||
width: `${27 / 16}em`,
|
||||
backgroundColor: '#fff',
|
||||
border: '1px solid currentColor',
|
||||
'&:hover': {
|
||||
boxShadow: '0 0 0 8px rgba(58, 133, 137, 0.16)',
|
||||
},
|
||||
'& .range-bar': {
|
||||
height: `${9/16}em`,
|
||||
height: `${9 / 16}em`,
|
||||
width: 1,
|
||||
backgroundColor: 'currentColor',
|
||||
marginLeft: 1,
|
||||
@ -22,13 +22,13 @@ const RangeSlider = styled(Slider)(({ theme }) => ({
|
||||
},
|
||||
},
|
||||
'& .MuiSlider-track': {
|
||||
height: `${3/16}em`,
|
||||
height: `${3 / 16}em`,
|
||||
},
|
||||
'& .MuiSlider-rail': {
|
||||
color: theme.palette.mode === 'dark' ? '#bfbfbf' : '#d8d8d8',
|
||||
opacity: theme.palette.mode === 'dark' ? undefined : 1,
|
||||
height: `${3/16}em`,
|
||||
height: `${3 / 16}em`,
|
||||
},
|
||||
}));
|
||||
|
||||
export default RangeSlider;
|
||||
export default RangeSlider;
|
||||
|
@ -1,61 +1,74 @@
|
||||
import React from "react"
|
||||
import { Badge, Tooltip } from "@mui/material";
|
||||
import SmoothImage from 'react-smooth-image'
|
||||
import React from 'react';
|
||||
import { Badge, Tooltip } from '@mui/material';
|
||||
import SmoothImage from 'react-smooth-image';
|
||||
|
||||
import Order from "../../../models/Order.model"
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { SendReceiveIcon } from "../../Icons";
|
||||
import Order from '../../../models/Order.model';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { SendReceiveIcon } from '../../Icons';
|
||||
|
||||
interface DepthChartProps {
|
||||
order: Order
|
||||
order: Order;
|
||||
}
|
||||
|
||||
const RobotAvatar: React.FC<DepthChartProps> = ({ order }) => {
|
||||
const { t } = useTranslation()
|
||||
const { t } = useTranslation();
|
||||
|
||||
const avatarSrc: string = window.location.origin +'/static/assets/avatars/' + order?.maker_nick + '.png'
|
||||
const avatarSrc: string =
|
||||
window.location.origin + '/static/assets/avatars/' + order?.maker_nick + '.png';
|
||||
|
||||
const statusBadge = (
|
||||
<div style={{position:"relative", left:"6px", top:"1px"}}>
|
||||
{order?.type === 0 ?
|
||||
<SendReceiveIcon sx={{transform: "scaleX(-1)",height:"18px",width:"18px"}} color="secondary"/> :
|
||||
<SendReceiveIcon sx={{height:"20px",width:"20px"}} color="primary"/>}
|
||||
<div style={{ position: 'relative', left: '6px', top: '1px' }}>
|
||||
{order?.type === 0 ? (
|
||||
<SendReceiveIcon
|
||||
sx={{ transform: 'scaleX(-1)', height: '18px', width: '18px' }}
|
||||
color='secondary'
|
||||
/>
|
||||
) : (
|
||||
<SendReceiveIcon sx={{ height: '20px', width: '20px' }} color='primary' />
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
);
|
||||
|
||||
const statusBadgeColor = () => {
|
||||
if(!order){ return }
|
||||
if(order.maker_status ==='Active'){ return("success") }
|
||||
if(order.maker_status ==='Seen recently'){ return("warning") }
|
||||
if(order.maker_status ==='Inactive'){ return('error') }
|
||||
}
|
||||
if (!order) {
|
||||
return;
|
||||
}
|
||||
if (order.maker_status === 'Active') {
|
||||
return 'success';
|
||||
}
|
||||
if (order.maker_status === 'Seen recently') {
|
||||
return 'warning';
|
||||
}
|
||||
if (order.maker_status === 'Inactive') {
|
||||
return 'error';
|
||||
}
|
||||
};
|
||||
|
||||
return order ? (
|
||||
<Tooltip placement="right" enterTouchDelay={0} title={t(order.maker_status) || ""}>
|
||||
<Badge
|
||||
variant="dot"
|
||||
overlap="circular"
|
||||
badgeContent=""
|
||||
color={statusBadgeColor()}
|
||||
>
|
||||
<Badge
|
||||
overlap="circular"
|
||||
anchorOrigin={{horizontal: 'right', vertical: 'bottom'}}
|
||||
<Tooltip placement='right' enterTouchDelay={0} title={t(order.maker_status) || ''}>
|
||||
<Badge variant='dot' overlap='circular' badgeContent='' color={statusBadgeColor()}>
|
||||
<Badge
|
||||
overlap='circular'
|
||||
anchorOrigin={{ horizontal: 'right', vertical: 'bottom' }}
|
||||
badgeContent={statusBadge}
|
||||
>
|
||||
<div style={{ width: 45, height: 45 }}>
|
||||
<SmoothImage
|
||||
src={avatarSrc}
|
||||
imageStyles={{borderRadius: "50%",
|
||||
transform: "scaleX(-1)",
|
||||
border: "0.3px solid #555",
|
||||
filter: "dropShadow(0.5px 0.5px 0.5px #000000)"}}
|
||||
imageStyles={{
|
||||
borderRadius: '50%',
|
||||
transform: 'scaleX(-1)',
|
||||
border: '0.3px solid #555',
|
||||
filter: 'dropShadow(0.5px 0.5px 0.5px #000000)',
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
</Badge>
|
||||
</Badge>
|
||||
</Tooltip>
|
||||
) : <></>
|
||||
}
|
||||
) : (
|
||||
<></>
|
||||
);
|
||||
};
|
||||
|
||||
export default RobotAvatar
|
||||
export default RobotAvatar;
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,28 +1,28 @@
|
||||
import React, { useState } from "react";
|
||||
import { format } from "date-fns";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import React, { useState } from 'react';
|
||||
import { format } from 'date-fns';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import {
|
||||
Avatar,
|
||||
Badge,
|
||||
ToggleButton,
|
||||
ToggleButtonGroup,
|
||||
List,
|
||||
ListItem,
|
||||
ListItemText,
|
||||
ListItemIcon,
|
||||
Grid,
|
||||
Tooltip,
|
||||
IconButton,
|
||||
Accordion,
|
||||
AccordionSummary,
|
||||
AccordionDetails,
|
||||
Typography,
|
||||
} from "@mui/material"
|
||||
import { pn } from "../utils/prettyNumbers";
|
||||
import { saveAsJson } from "../utils/saveFile";
|
||||
Avatar,
|
||||
Badge,
|
||||
ToggleButton,
|
||||
ToggleButtonGroup,
|
||||
List,
|
||||
ListItem,
|
||||
ListItemText,
|
||||
ListItemIcon,
|
||||
Grid,
|
||||
Tooltip,
|
||||
IconButton,
|
||||
Accordion,
|
||||
AccordionSummary,
|
||||
AccordionDetails,
|
||||
Typography,
|
||||
} from '@mui/material';
|
||||
import { pn } from '../utils/prettyNumbers';
|
||||
import { saveAsJson } from '../utils/saveFile';
|
||||
|
||||
// Icons
|
||||
import FlagWithProps from "./FlagWithProps";
|
||||
import FlagWithProps from './FlagWithProps';
|
||||
import ScheduleIcon from '@mui/icons-material/Schedule';
|
||||
import PriceChangeIcon from '@mui/icons-material/PriceChange';
|
||||
import ExpandMoreIcon from '@mui/icons-material/ExpandMore';
|
||||
@ -32,7 +32,7 @@ import RouteIcon from '@mui/icons-material/Route';
|
||||
import AccountBoxIcon from '@mui/icons-material/AccountBox';
|
||||
import LockOpenIcon from '@mui/icons-material/LockOpen';
|
||||
import LinkIcon from '@mui/icons-material/Link';
|
||||
import { RoboSatsNoTextIcon , SendReceiveIcon , BitcoinIcon} from "./Icons";
|
||||
import { RoboSatsNoTextIcon, SendReceiveIcon, BitcoinIcon } from './Icons';
|
||||
|
||||
interface Item {
|
||||
id: string;
|
||||
@ -48,7 +48,7 @@ type Props = {
|
||||
takerSummary: Record<string, Item>;
|
||||
platformSummary: Record<string, Item>;
|
||||
orderId: number;
|
||||
}
|
||||
};
|
||||
|
||||
const TradeSummary = ({
|
||||
isMaker,
|
||||
@ -60,186 +60,261 @@ const TradeSummary = ({
|
||||
platformSummary,
|
||||
orderId,
|
||||
}: Props): JSX.Element => {
|
||||
const { t , i18n } = useTranslation();
|
||||
const { t, i18n } = useTranslation();
|
||||
const [buttonValue, setButtonValue] = useState<number>(isMaker ? 0 : 2);
|
||||
var userSummary = buttonValue == 0 ? makerSummary : takerSummary;
|
||||
const contractTimestamp = new Date(platformSummary.contract_timestamp)
|
||||
const total_time = platformSummary.contract_total_time
|
||||
const hours = parseInt(total_time / 3600)
|
||||
const mins = parseInt((total_time - hours * 3600) / 60)
|
||||
const secs = parseInt(total_time - hours * 3600 - mins * 60)
|
||||
const contractTimestamp = new Date(platformSummary.contract_timestamp);
|
||||
const total_time = platformSummary.contract_total_time;
|
||||
const hours = parseInt(total_time / 3600);
|
||||
const mins = parseInt((total_time - hours * 3600) / 60);
|
||||
const secs = parseInt(total_time - hours * 3600 - mins * 60);
|
||||
|
||||
return (
|
||||
<Grid item xs={12} align="center">
|
||||
<Accordion defaultExpanded={true} elevation={0} sx={{width:322, position:'relative', right:8}}>
|
||||
<AccordionSummary expandIcon={<ExpandMoreIcon sx={{width:28}} color="primary"/>}>
|
||||
<Typography sx={{flexGrow:1}} color="text.secondary">{t("Trade Summary")}</Typography>
|
||||
<Grid item xs={12} align='center'>
|
||||
<Accordion
|
||||
defaultExpanded={true}
|
||||
elevation={0}
|
||||
sx={{ width: 322, position: 'relative', right: 8 }}
|
||||
>
|
||||
<AccordionSummary expandIcon={<ExpandMoreIcon sx={{ width: 28 }} color='primary' />}>
|
||||
<Typography sx={{ flexGrow: 1 }} color='text.secondary'>
|
||||
{t('Trade Summary')}
|
||||
</Typography>
|
||||
</AccordionSummary>
|
||||
<AccordionDetails>
|
||||
<div style={{position:'relative',left:14, display:'flex',alignItems:'center', justifyContent:'center', flexWrap:'wrap'}}>
|
||||
<ToggleButtonGroup
|
||||
size="small"
|
||||
value={buttonValue}
|
||||
exclusive>
|
||||
<ToggleButton value={0} disableRipple={true} onClick={() => setButtonValue(0)}>
|
||||
<Avatar
|
||||
className="flippedSmallAvatar"
|
||||
sx={{height:24,width:24}}
|
||||
alt={makerNick}
|
||||
src={window.location.origin +'/static/assets/avatars/' + makerNick + '.png'}
|
||||
/>
|
||||
|
||||
{t("Maker")}
|
||||
</ToggleButton>
|
||||
<ToggleButton value={1} disableRipple={true} onClick={() => setButtonValue(1)}>
|
||||
<RoboSatsNoTextIcon/>
|
||||
</ToggleButton>
|
||||
<ToggleButton value={2} disableRipple={true} onClick={() => setButtonValue(2)}>
|
||||
{t("Taker")}
|
||||
|
||||
<Avatar
|
||||
className="smallAvatar"
|
||||
sx={{height:28,width:28}}
|
||||
alt={takerNick}
|
||||
src={window.location.origin +'/static/assets/avatars/' + takerNick + '.png'}
|
||||
/>
|
||||
</ToggleButton>
|
||||
<div
|
||||
style={{
|
||||
position: 'relative',
|
||||
left: 14,
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
flexWrap: 'wrap',
|
||||
}}
|
||||
>
|
||||
<ToggleButtonGroup size='small' value={buttonValue} exclusive>
|
||||
<ToggleButton value={0} disableRipple={true} onClick={() => setButtonValue(0)}>
|
||||
<Avatar
|
||||
className='flippedSmallAvatar'
|
||||
sx={{ height: 24, width: 24 }}
|
||||
alt={makerNick}
|
||||
src={window.location.origin + '/static/assets/avatars/' + makerNick + '.png'}
|
||||
/>
|
||||
|
||||
{t('Maker')}
|
||||
</ToggleButton>
|
||||
<ToggleButton value={1} disableRipple={true} onClick={() => setButtonValue(1)}>
|
||||
<RoboSatsNoTextIcon />
|
||||
</ToggleButton>
|
||||
<ToggleButton value={2} disableRipple={true} onClick={() => setButtonValue(2)}>
|
||||
{t('Taker')}
|
||||
|
||||
<Avatar
|
||||
className='smallAvatar'
|
||||
sx={{ height: 28, width: 28 }}
|
||||
alt={takerNick}
|
||||
src={window.location.origin + '/static/assets/avatars/' + takerNick + '.png'}
|
||||
/>
|
||||
</ToggleButton>
|
||||
</ToggleButtonGroup>
|
||||
<Tooltip enterTouchDelay={250} title={t("Save trade summary as file")}>
|
||||
<span>
|
||||
<IconButton
|
||||
color="primary"
|
||||
onClick={()=> saveAsJson(`order${orderId}-summary.json`, {'order_id':orderId,'currency':currencyCode,'maker':makerSummary,'taker':takerSummary,'platform':platformSummary})}
|
||||
>
|
||||
<DownloadIcon sx={{width:26, height:26}}/>
|
||||
</IconButton>
|
||||
</span>
|
||||
</Tooltip>
|
||||
</div>
|
||||
{/* Maker/Taker Summary */}
|
||||
<div style={{display: [0,2].includes(buttonValue) ? '':'none'}}>
|
||||
<List dense={true}>
|
||||
<ListItem>
|
||||
<ListItemIcon>
|
||||
<Badge
|
||||
overlap="circular"
|
||||
anchorOrigin={{horizontal: 'right', vertical: 'bottom'}}
|
||||
badgeContent={<div
|
||||
style={{position:"relative", left:"3px", top:"2px"}}>
|
||||
{userSummary.is_buyer ?
|
||||
<SendReceiveIcon
|
||||
sx={{transform: "scaleX(-1)",height:"18px",width:"18px"}}
|
||||
color="secondary"/>
|
||||
: <SendReceiveIcon
|
||||
sx={{height:"18px",width:"18px"}}
|
||||
color="primary"/>
|
||||
}
|
||||
</div>}>
|
||||
<AccountBoxIcon sx={{position:'relative',left:-2,width:28,height:28}}/>
|
||||
</Badge>
|
||||
</ListItemIcon>
|
||||
<ListItemText
|
||||
primary={userSummary.is_buyer ? t("Buyer") : t("Seller")}
|
||||
secondary={t("User role")}/>
|
||||
<Tooltip enterTouchDelay={250} title={t('Save trade summary as file')}>
|
||||
<span>
|
||||
<IconButton
|
||||
color='primary'
|
||||
onClick={() =>
|
||||
saveAsJson(`order${orderId}-summary.json`, {
|
||||
order_id: orderId,
|
||||
currency: currencyCode,
|
||||
maker: makerSummary,
|
||||
taker: takerSummary,
|
||||
platform: platformSummary,
|
||||
})
|
||||
}
|
||||
>
|
||||
<DownloadIcon sx={{ width: 26, height: 26 }} />
|
||||
</IconButton>
|
||||
</span>
|
||||
</Tooltip>
|
||||
</div>
|
||||
{/* Maker/Taker Summary */}
|
||||
<div style={{ display: [0, 2].includes(buttonValue) ? '' : 'none' }}>
|
||||
<List dense={true}>
|
||||
<ListItem>
|
||||
<ListItemIcon>
|
||||
<Badge
|
||||
overlap='circular'
|
||||
anchorOrigin={{ horizontal: 'right', vertical: 'bottom' }}
|
||||
badgeContent={
|
||||
<div style={{ position: 'relative', left: '3px', top: '2px' }}>
|
||||
{userSummary.is_buyer ? (
|
||||
<SendReceiveIcon
|
||||
sx={{ transform: 'scaleX(-1)', height: '18px', width: '18px' }}
|
||||
color='secondary'
|
||||
/>
|
||||
) : (
|
||||
<SendReceiveIcon sx={{ height: '18px', width: '18px' }} color='primary' />
|
||||
)}
|
||||
</div>
|
||||
}
|
||||
>
|
||||
<AccountBoxIcon
|
||||
sx={{ position: 'relative', left: -2, width: 28, height: 28 }}
|
||||
/>
|
||||
</Badge>
|
||||
</ListItemIcon>
|
||||
<ListItemText
|
||||
primary={userSummary.is_buyer ? t('Buyer') : t('Seller')}
|
||||
secondary={t('User role')}
|
||||
/>
|
||||
|
||||
<ListItemIcon>
|
||||
<div style={{position:'relative',left:15,zoom:1.25,opacity: 0.7,msZoom:1.25,WebkitZoom:1.25,MozTransform:'scale(1.25,1.25)',MozTransformOrigin:'left center'}}>
|
||||
<FlagWithProps code={currencyCode}/>
|
||||
</div>
|
||||
</ListItemIcon>
|
||||
<ListItemText
|
||||
primary={(userSummary.is_buyer ? pn(userSummary.sent_fiat) : pn(userSummary.received_fiat))+" "+currencyCode}
|
||||
secondary={userSummary.is_buyer ? t("Sent") : t("Received")}/>
|
||||
</ListItem>
|
||||
|
||||
<ListItem>
|
||||
<ListItemIcon>
|
||||
<BitcoinIcon/>
|
||||
</ListItemIcon>
|
||||
<ListItemText
|
||||
primary={pn(userSummary.is_buyer ? userSummary.received_sats : userSummary.sent_sats)+" Sats"}
|
||||
secondary={userSummary.is_buyer ? "BTC received" : "BTC sent"}/>
|
||||
<ListItemIcon>
|
||||
<div
|
||||
style={{
|
||||
position: 'relative',
|
||||
left: 15,
|
||||
zoom: 1.25,
|
||||
opacity: 0.7,
|
||||
msZoom: 1.25,
|
||||
WebkitZoom: 1.25,
|
||||
MozTransform: 'scale(1.25,1.25)',
|
||||
MozTransformOrigin: 'left center',
|
||||
}}
|
||||
>
|
||||
<FlagWithProps code={currencyCode} />
|
||||
</div>
|
||||
</ListItemIcon>
|
||||
<ListItemText
|
||||
primary={
|
||||
(userSummary.is_buyer
|
||||
? pn(userSummary.sent_fiat)
|
||||
: pn(userSummary.received_fiat)) +
|
||||
' ' +
|
||||
currencyCode
|
||||
}
|
||||
secondary={userSummary.is_buyer ? t('Sent') : t('Received')}
|
||||
/>
|
||||
</ListItem>
|
||||
|
||||
<ListItemText
|
||||
primary={t("{{tradeFeeSats}} Sats ({{tradeFeePercent}}%)",{tradeFeeSats:pn(userSummary.trade_fee_sats),tradeFeePercent:parseFloat((userSummary.trade_fee_percent*100).toPrecision(3))})}
|
||||
secondary={"Trade fee"}/>
|
||||
</ListItem>
|
||||
|
||||
{userSummary.is_swap ?
|
||||
<ListItem>
|
||||
<ListItemIcon>
|
||||
<LinkIcon/>
|
||||
</ListItemIcon>
|
||||
<ListItemText
|
||||
primary={t("{{swapFeeSats}} Sats ({{swapFeePercent}}%)" , {swapFeeSats:pn(userSummary.swap_fee_sats), swapFeePercent:userSummary.swap_fee_percent})}
|
||||
secondary={t("Onchain swap fee")}/>
|
||||
<ListItemText
|
||||
primary={t("{{miningFeeSats}} Sats",{miningFeeSats:pn(userSummary.mining_fee_sats)})}
|
||||
secondary={t("Mining fee")}/>
|
||||
</ListItem>
|
||||
: null}
|
||||
<ListItem>
|
||||
<ListItemIcon>
|
||||
<BitcoinIcon />
|
||||
</ListItemIcon>
|
||||
<ListItemText
|
||||
primary={
|
||||
pn(userSummary.is_buyer ? userSummary.received_sats : userSummary.sent_sats) +
|
||||
' Sats'
|
||||
}
|
||||
secondary={userSummary.is_buyer ? 'BTC received' : 'BTC sent'}
|
||||
/>
|
||||
|
||||
<ListItem>
|
||||
<ListItemIcon>
|
||||
<LockOpenIcon color="success"/>
|
||||
</ListItemIcon>
|
||||
<ListItemText
|
||||
primary={t("{{bondSats}} Sats ({{bondPercent}}%)" , {bondSats:pn(userSummary.bond_size_sats), bondPercent:userSummary.bond_size_percent})}
|
||||
secondary={buttonValue === 0 ? t("Maker bond") : t("Taker bond") }/>
|
||||
<ListItemText
|
||||
sx={{color:'#2e7d32'}}
|
||||
primary={<b>{t("Unlocked")}</b>}/>
|
||||
</ListItem>
|
||||
</List>
|
||||
</div>
|
||||
{/* Platform Summary */}
|
||||
<div style={{display: buttonValue == 1 ? '':'none'}}>
|
||||
<List dense={true}>
|
||||
<ListItemText
|
||||
primary={t('{{tradeFeeSats}} Sats ({{tradeFeePercent}}%)', {
|
||||
tradeFeeSats: pn(userSummary.trade_fee_sats),
|
||||
tradeFeePercent: parseFloat(
|
||||
(userSummary.trade_fee_percent * 100).toPrecision(3),
|
||||
),
|
||||
})}
|
||||
secondary={'Trade fee'}
|
||||
/>
|
||||
</ListItem>
|
||||
|
||||
{userSummary.is_swap ? (
|
||||
<ListItem>
|
||||
<ListItemIcon>
|
||||
<AccountBalanceIcon/>
|
||||
<LinkIcon />
|
||||
</ListItemIcon>
|
||||
<ListItemText
|
||||
primary={t("{{revenueSats}} Sats",{revenueSats:pn(platformSummary.trade_revenue_sats)})}
|
||||
secondary={t("Platform trade revenue")}/>
|
||||
</ListItem>
|
||||
|
||||
<ListItem>
|
||||
<ListItemIcon>
|
||||
<RouteIcon/>
|
||||
</ListItemIcon>
|
||||
<ListItemText
|
||||
primary={t("{{routingFeeSats}} MiliSats",{routingFeeSats:pn(platformSummary.routing_fee_sats)})}
|
||||
secondary={t("Platform covered routing fee")}/>
|
||||
<ListItemText
|
||||
primary={t('{{swapFeeSats}} Sats ({{swapFeePercent}}%)', {
|
||||
swapFeeSats: pn(userSummary.swap_fee_sats),
|
||||
swapFeePercent: userSummary.swap_fee_percent,
|
||||
})}
|
||||
secondary={t('Onchain swap fee')}
|
||||
/>
|
||||
<ListItemText
|
||||
primary={t('{{miningFeeSats}} Sats', {
|
||||
miningFeeSats: pn(userSummary.mining_fee_sats),
|
||||
})}
|
||||
secondary={t('Mining fee')}
|
||||
/>
|
||||
</ListItem>
|
||||
) : null}
|
||||
|
||||
<ListItem>
|
||||
<ListItemIcon>
|
||||
<PriceChangeIcon/>
|
||||
</ListItemIcon>
|
||||
<ListItemText
|
||||
primary={`${pn(platformSummary.contract_exchange_rate.toPrecision(7))} ${currencyCode}/BTC`}
|
||||
secondary={t("Contract exchange rate")}/>
|
||||
</ListItem>
|
||||
|
||||
<ListItem>
|
||||
<ListItemText
|
||||
primary={format(contractTimestamp, "do LLL HH:mm:ss")}
|
||||
secondary={t("Timestamp")}/>
|
||||
<ListItemIcon>
|
||||
<ScheduleIcon/>
|
||||
</ListItemIcon>
|
||||
<ListItemText
|
||||
primary={`${String(hours).padStart(2, '0')}:${String(mins).padStart(2, '0')}:${String(secs).padStart(2, '0')}`}
|
||||
secondary={t("Completed in")}/>
|
||||
</ListItem>
|
||||
</List>
|
||||
</div>
|
||||
<ListItem>
|
||||
<ListItemIcon>
|
||||
<LockOpenIcon color='success' />
|
||||
</ListItemIcon>
|
||||
<ListItemText
|
||||
primary={t('{{bondSats}} Sats ({{bondPercent}}%)', {
|
||||
bondSats: pn(userSummary.bond_size_sats),
|
||||
bondPercent: userSummary.bond_size_percent,
|
||||
})}
|
||||
secondary={buttonValue === 0 ? t('Maker bond') : t('Taker bond')}
|
||||
/>
|
||||
<ListItemText sx={{ color: '#2e7d32' }} primary={<b>{t('Unlocked')}</b>} />
|
||||
</ListItem>
|
||||
</List>
|
||||
</div>
|
||||
{/* Platform Summary */}
|
||||
<div style={{ display: buttonValue == 1 ? '' : 'none' }}>
|
||||
<List dense={true}>
|
||||
<ListItem>
|
||||
<ListItemIcon>
|
||||
<AccountBalanceIcon />
|
||||
</ListItemIcon>
|
||||
<ListItemText
|
||||
primary={t('{{revenueSats}} Sats', {
|
||||
revenueSats: pn(platformSummary.trade_revenue_sats),
|
||||
})}
|
||||
secondary={t('Platform trade revenue')}
|
||||
/>
|
||||
</ListItem>
|
||||
|
||||
<ListItem>
|
||||
<ListItemIcon>
|
||||
<RouteIcon />
|
||||
</ListItemIcon>
|
||||
<ListItemText
|
||||
primary={t('{{routingFeeSats}} MiliSats', {
|
||||
routingFeeSats: pn(platformSummary.routing_fee_sats),
|
||||
})}
|
||||
secondary={t('Platform covered routing fee')}
|
||||
/>
|
||||
</ListItem>
|
||||
|
||||
<ListItem>
|
||||
<ListItemIcon>
|
||||
<PriceChangeIcon />
|
||||
</ListItemIcon>
|
||||
<ListItemText
|
||||
primary={`${pn(
|
||||
platformSummary.contract_exchange_rate.toPrecision(7),
|
||||
)} ${currencyCode}/BTC`}
|
||||
secondary={t('Contract exchange rate')}
|
||||
/>
|
||||
</ListItem>
|
||||
|
||||
<ListItem>
|
||||
<ListItemText
|
||||
primary={format(contractTimestamp, 'do LLL HH:mm:ss')}
|
||||
secondary={t('Timestamp')}
|
||||
/>
|
||||
<ListItemIcon>
|
||||
<ScheduleIcon />
|
||||
</ListItemIcon>
|
||||
<ListItemText
|
||||
primary={`${String(hours).padStart(2, '0')}:${String(mins).padStart(
|
||||
2,
|
||||
'0',
|
||||
)}:${String(secs).padStart(2, '0')}`}
|
||||
secondary={t('Completed in')}
|
||||
/>
|
||||
</ListItem>
|
||||
</List>
|
||||
</div>
|
||||
</AccordionDetails>
|
||||
</Accordion>
|
||||
</Grid>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
export default TradeSummary;
|
||||
|
@ -1,7 +1,7 @@
|
||||
import React, { Component } from 'react'
|
||||
import { withTranslation, Trans} from "react-i18next";
|
||||
import {Paper, Alert, AlertTitle, Button, Link} from "@mui/material"
|
||||
import MediaQuery from 'react-responsive'
|
||||
import React, { Component } from 'react';
|
||||
import { withTranslation, Trans } from 'react-i18next';
|
||||
import { Paper, Alert, AlertTitle, Button, Link } from '@mui/material';
|
||||
import MediaQuery from 'react-responsive';
|
||||
|
||||
class UnsafeAlert extends Component {
|
||||
constructor(props) {
|
||||
@ -11,86 +11,126 @@ class UnsafeAlert extends Component {
|
||||
isSelfhosted: this.isSelfhosted(),
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
getHost(){
|
||||
var url = (window.location != window.parent.location) ? this.getHost(document.referrer) : document.location.href;
|
||||
return url.split('/')[2]
|
||||
getHost() {
|
||||
var url =
|
||||
window.location != window.parent.location
|
||||
? this.getHost(document.referrer)
|
||||
: document.location.href;
|
||||
return url.split('/')[2];
|
||||
}
|
||||
|
||||
isSelfhosted(){
|
||||
isSelfhosted() {
|
||||
var http = new XMLHttpRequest();
|
||||
http.open('HEAD', `${location.protocol}//${this.getHost()}/selfhosted`, false);
|
||||
http.send();
|
||||
return http.status!=404;
|
||||
return http.status != 404;
|
||||
}
|
||||
|
||||
|
||||
safe_urls = [
|
||||
'robosats6tkf3eva7x2voqso3a5wcorsnw34jveyxfqi2fu7oyheasid.onion',
|
||||
'robotestagw3dcxmd66r4rgksb4nmmr43fh77bzn2ia2eucduyeafnyd.onion',
|
||||
'robodevs7ixniseezbv7uryxhamtz3hvcelzfwpx3rvoipttjomrmpqd.onion',
|
||||
'robosats.i2p',
|
||||
'r7r4sckft6ptmk4r2jajiuqbowqyxiwsle4iyg4fijtoordc6z7a.b32.i2p',
|
||||
]
|
||||
];
|
||||
|
||||
render() {
|
||||
const { t, i18n} = this.props;
|
||||
const { t, i18n } = this.props;
|
||||
|
||||
// If alert is hidden return null
|
||||
if (!this.state.show){return null}
|
||||
if (!this.state.show) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Show selfhosted notice
|
||||
if (this.state.isSelfhosted){
|
||||
return(
|
||||
if (this.state.isSelfhosted) {
|
||||
return (
|
||||
<div>
|
||||
<Paper elevation={6} className="alertUnsafe">
|
||||
<Alert severity="success" sx={{maxHeight:"120px"}}
|
||||
action={<Button color="success" onClick={() => this.setState({show:false})}>{t("Hide")}</Button>}
|
||||
>
|
||||
<AlertTitle>{t("You are self-hosting RoboSats")}</AlertTitle>
|
||||
{t("RoboSats client is served from your own node granting you the strongest security and privacy.")}
|
||||
<Paper elevation={6} className='alertUnsafe'>
|
||||
<Alert
|
||||
severity='success'
|
||||
sx={{ maxHeight: '120px' }}
|
||||
action={
|
||||
<Button color='success' onClick={() => this.setState({ show: false })}>
|
||||
{t('Hide')}
|
||||
</Button>
|
||||
}
|
||||
>
|
||||
<AlertTitle>{t('You are self-hosting RoboSats')}</AlertTitle>
|
||||
{t(
|
||||
'RoboSats client is served from your own node granting you the strongest security and privacy.',
|
||||
)}
|
||||
</Alert>
|
||||
</Paper>
|
||||
</div>
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
// Show unsafe alert
|
||||
if (!this.safe_urls.includes(this.getHost())){
|
||||
return(
|
||||
if (!this.safe_urls.includes(this.getHost())) {
|
||||
return (
|
||||
<div>
|
||||
<MediaQuery minWidth={800}>
|
||||
<Paper elevation={6} className="alertUnsafe">
|
||||
<Alert severity="warning" sx={{maxHeight:"100px"}}
|
||||
action={<Button onClick={() => this.setState({show:false})}>{t("Hide")}</Button>}
|
||||
<Paper elevation={6} className='alertUnsafe'>
|
||||
<Alert
|
||||
severity='warning'
|
||||
sx={{ maxHeight: '100px' }}
|
||||
action={<Button onClick={() => this.setState({ show: false })}>{t('Hide')}</Button>}
|
||||
>
|
||||
<AlertTitle>{t("You are not using RoboSats privately")}</AlertTitle>
|
||||
<Trans i18nKey="desktop_unsafe_alert">
|
||||
Some features are disabled for your protection (e.g. chat) and you will not be able to complete a
|
||||
trade without them. To protect your privacy and fully enable RoboSats, use <Link href='https://www.torproject.org/download/' target="_blank">Tor Browser</Link> and visit the <Link href='http://robosats6tkf3eva7x2voqso3a5wcorsnw34jveyxfqi2fu7oyheasid.onion' target="_blank">Onion</Link> site.
|
||||
<AlertTitle>{t('You are not using RoboSats privately')}</AlertTitle>
|
||||
<Trans i18nKey='desktop_unsafe_alert'>
|
||||
Some features are disabled for your protection (e.g. chat) and you will not be
|
||||
able to complete a trade without them. To protect your privacy and fully enable
|
||||
RoboSats, use{' '}
|
||||
<Link href='https://www.torproject.org/download/' target='_blank'>
|
||||
Tor Browser
|
||||
</Link>{' '}
|
||||
and visit the{' '}
|
||||
<Link
|
||||
href='http://robosats6tkf3eva7x2voqso3a5wcorsnw34jveyxfqi2fu7oyheasid.onion'
|
||||
target='_blank'
|
||||
>
|
||||
Onion
|
||||
</Link>{' '}
|
||||
site.
|
||||
</Trans>
|
||||
</Alert>
|
||||
</Paper>
|
||||
</MediaQuery>
|
||||
|
||||
<MediaQuery maxWidth={799}>
|
||||
<Paper elevation={6} className="alertUnsafe">
|
||||
<Alert severity="warning" sx={{maxHeight:"120px"}}>
|
||||
<AlertTitle>{t("You are not using RoboSats privately")}</AlertTitle>
|
||||
<Trans i18nKey="phone_unsafe_alert">
|
||||
You will not be able to complete a
|
||||
trade. Use <Link href='https://www.torproject.org/download/' target="_blank">Tor Browser</Link> and visit the <Link href='http://robosats6tkf3eva7x2voqso3a5wcorsnw34jveyxfqi2fu7oyheasid.onion' target="_blank">Onion</Link> site.
|
||||
</Trans>
|
||||
<div style={{width: '100%'}}>
|
||||
</div>
|
||||
<div align="center">
|
||||
<Button className="hideAlertButton" onClick={() => this.setState({show:false})}>{t("Hide")}</Button>
|
||||
</div>
|
||||
</Alert>
|
||||
<Paper elevation={6} className='alertUnsafe'>
|
||||
<Alert severity='warning' sx={{ maxHeight: '120px' }}>
|
||||
<AlertTitle>{t('You are not using RoboSats privately')}</AlertTitle>
|
||||
<Trans i18nKey='phone_unsafe_alert'>
|
||||
You will not be able to complete a trade. Use{' '}
|
||||
<Link href='https://www.torproject.org/download/' target='_blank'>
|
||||
Tor Browser
|
||||
</Link>{' '}
|
||||
and visit the{' '}
|
||||
<Link
|
||||
href='http://robosats6tkf3eva7x2voqso3a5wcorsnw34jveyxfqi2fu7oyheasid.onion'
|
||||
target='_blank'
|
||||
>
|
||||
Onion
|
||||
</Link>{' '}
|
||||
site.
|
||||
</Trans>
|
||||
<div style={{ width: '100%' }}></div>
|
||||
<div align='center'>
|
||||
<Button
|
||||
className='hideAlertButton'
|
||||
onClick={() => this.setState({ show: false })}
|
||||
>
|
||||
{t('Hide')}
|
||||
</Button>
|
||||
</div>
|
||||
</Alert>
|
||||
</Paper>
|
||||
</MediaQuery>
|
||||
</div>
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,23 +1,32 @@
|
||||
import React, { Component } from "react";
|
||||
import { withTranslation } from "react-i18next";
|
||||
import { Button , Tooltip, Grid, Typography, TextField, ButtonGroup, CircularProgress, IconButton} from "@mui/material"
|
||||
import { Link } from 'react-router-dom'
|
||||
import SmoothImage from 'react-smooth-image'
|
||||
import { InfoDialog } from './Dialogs'
|
||||
import React, { Component } from 'react';
|
||||
import { withTranslation } from 'react-i18next';
|
||||
import {
|
||||
Button,
|
||||
Tooltip,
|
||||
Grid,
|
||||
Typography,
|
||||
TextField,
|
||||
ButtonGroup,
|
||||
CircularProgress,
|
||||
IconButton,
|
||||
} from '@mui/material';
|
||||
import { Link } from 'react-router-dom';
|
||||
import SmoothImage from 'react-smooth-image';
|
||||
import { InfoDialog } from './Dialogs';
|
||||
|
||||
import SmartToyIcon from '@mui/icons-material/SmartToy';
|
||||
import CasinoIcon from '@mui/icons-material/Casino';
|
||||
import ContentCopy from "@mui/icons-material/ContentCopy";
|
||||
import ContentCopy from '@mui/icons-material/ContentCopy';
|
||||
import BoltIcon from '@mui/icons-material/Bolt';
|
||||
import DownloadIcon from '@mui/icons-material/Download';
|
||||
import { RoboSatsNoTextIcon } from "./Icons";
|
||||
import { RoboSatsNoTextIcon } from './Icons';
|
||||
|
||||
import { sha256 } from 'js-sha256';
|
||||
import { genBase62Token, tokenStrength } from "../utils/token";
|
||||
import { genKey } from "../utils/pgp";
|
||||
import { getCookie, writeCookie, deleteCookie } from "../utils/cookies";
|
||||
import { saveAsJson } from "../utils/saveFile";
|
||||
import { copyToClipboard } from "../utils/clipboard";
|
||||
import { genBase62Token, tokenStrength } from '../utils/token';
|
||||
import { genKey } from '../utils/pgp';
|
||||
import { getCookie, writeCookie, deleteCookie } from '../utils/cookies';
|
||||
import { saveAsJson } from '../utils/saveFile';
|
||||
import { copyToClipboard } from '../utils/clipboard';
|
||||
|
||||
class UserGenPage extends Component {
|
||||
constructor(props) {
|
||||
@ -25,7 +34,7 @@ class UserGenPage extends Component {
|
||||
this.state = {
|
||||
openInfo: false,
|
||||
tokenHasChanged: false,
|
||||
token: ""
|
||||
token: '',
|
||||
};
|
||||
|
||||
this.refCode = this.props.match.params.refCode;
|
||||
@ -34,304 +43,398 @@ class UserGenPage extends Component {
|
||||
componentDidMount() {
|
||||
// Checks in parent HomePage if there is already a nick and token
|
||||
// Displays the existing one
|
||||
if (this.props.nickname != null){
|
||||
if (this.props.nickname != null) {
|
||||
this.setState({
|
||||
nickname: this.props.nickname,
|
||||
token: this.props.token? this.props.token : "",
|
||||
token: this.props.token ? this.props.token : '',
|
||||
avatarUrl: '/static/assets/avatars/' + this.props.nickname + '.png',
|
||||
loadingRobot: false
|
||||
loadingRobot: false,
|
||||
});
|
||||
}
|
||||
else{
|
||||
var newToken = genBase62Token(36)
|
||||
} else {
|
||||
var newToken = genBase62Token(36);
|
||||
this.setState({
|
||||
token: newToken
|
||||
token: newToken,
|
||||
});
|
||||
this.getGeneratedUser(newToken);
|
||||
}
|
||||
}
|
||||
|
||||
getGeneratedUser=(token)=>{
|
||||
|
||||
getGeneratedUser = (token) => {
|
||||
const strength = tokenStrength(token);
|
||||
const refCode = this.refCode
|
||||
const refCode = this.refCode;
|
||||
|
||||
const requestOptions = genKey(token).then(function(key) {
|
||||
const requestOptions = genKey(token).then(function (key) {
|
||||
return {
|
||||
method: 'POST',
|
||||
headers: {'Content-Type':'application/json', 'X-CSRFToken': getCookie('csrftoken')},
|
||||
headers: { 'Content-Type': 'application/json', 'X-CSRFToken': getCookie('csrftoken') },
|
||||
body: JSON.stringify({
|
||||
token_sha256: sha256(token),
|
||||
public_key: key.publicKeyArmored,
|
||||
encrypted_private_key: key.encryptedPrivateKeyArmored,
|
||||
unique_values: strength.uniqueValues,
|
||||
counts: strength.counts,
|
||||
length: token.length,
|
||||
ref_code: refCode,
|
||||
})
|
||||
}}
|
||||
);
|
||||
token_sha256: sha256(token),
|
||||
public_key: key.publicKeyArmored,
|
||||
encrypted_private_key: key.encryptedPrivateKeyArmored,
|
||||
unique_values: strength.uniqueValues,
|
||||
counts: strength.counts,
|
||||
length: token.length,
|
||||
ref_code: refCode,
|
||||
}),
|
||||
};
|
||||
});
|
||||
|
||||
console.log(requestOptions);
|
||||
|
||||
console.log(requestOptions)
|
||||
|
||||
requestOptions.then((options) =>
|
||||
fetch("/api/user/",options)
|
||||
fetch('/api/user/', options)
|
||||
.then((response) => response.json())
|
||||
.then((data) => { console.log(data) &
|
||||
this.setState({
|
||||
.then((data) => {
|
||||
console.log(data) &
|
||||
this.setState({
|
||||
nickname: data.nickname,
|
||||
bit_entropy: data.token_bits_entropy,
|
||||
avatarUrl: '/static/assets/avatars/' + data.nickname + '.png',
|
||||
shannon_entropy: data.token_shannon_entropy,
|
||||
bad_request: data.bad_request,
|
||||
found: data.found,
|
||||
loadingRobot:false,
|
||||
loadingRobot: false,
|
||||
stealthInvoices: data.wants_stealth,
|
||||
})
|
||||
&
|
||||
// Add nick and token to App state (token only if not a bad request)
|
||||
(data.bad_request ? this.props.setAppState({
|
||||
nickname: data.nickname,
|
||||
avatarLoaded: false,
|
||||
activeOrderId: data.active_order_id ? data.active_order_id : null,
|
||||
referralCode: data.referral_code,
|
||||
earnedRewards: data.earned_rewards,
|
||||
lastOrderId: data.last_order_id ? data.last_order_id : null,
|
||||
stealthInvoices: data.wants_stealth,
|
||||
})
|
||||
:
|
||||
(this.props.setAppState({
|
||||
nickname: data.nickname,
|
||||
token: token,
|
||||
avatarLoaded: false,
|
||||
activeOrderId: data.active_order_id ? data.active_order_id : null,
|
||||
lastOrderId: data.last_order_id ? data.last_order_id : null,
|
||||
referralCode: data.referral_code,
|
||||
earnedRewards: data.earned_rewards,
|
||||
stealthInvoices: data.wants_stealth,
|
||||
})) & writeCookie("robot_token",token)
|
||||
& writeCookie("pub_key",data.public_key.split('\n').join('\\'))
|
||||
& writeCookie("enc_priv_key",data.encrypted_private_key.split('\n').join('\\')))
|
||||
&
|
||||
// If the robot has been found (recovered) we assume the token is backed up
|
||||
(data.found ? this.props.setAppState({copiedToken:true}) : null)
|
||||
})
|
||||
}) &
|
||||
// Add nick and token to App state (token only if not a bad request)
|
||||
(data.bad_request
|
||||
? this.props.setAppState({
|
||||
nickname: data.nickname,
|
||||
avatarLoaded: false,
|
||||
activeOrderId: data.active_order_id ? data.active_order_id : null,
|
||||
referralCode: data.referral_code,
|
||||
earnedRewards: data.earned_rewards,
|
||||
lastOrderId: data.last_order_id ? data.last_order_id : null,
|
||||
stealthInvoices: data.wants_stealth,
|
||||
})
|
||||
: this.props.setAppState({
|
||||
nickname: data.nickname,
|
||||
token: token,
|
||||
avatarLoaded: false,
|
||||
activeOrderId: data.active_order_id ? data.active_order_id : null,
|
||||
lastOrderId: data.last_order_id ? data.last_order_id : null,
|
||||
referralCode: data.referral_code,
|
||||
earnedRewards: data.earned_rewards,
|
||||
stealthInvoices: data.wants_stealth,
|
||||
}) &
|
||||
writeCookie('robot_token', token) &
|
||||
writeCookie('pub_key', data.public_key.split('\n').join('\\')) &
|
||||
writeCookie('enc_priv_key', data.encrypted_private_key.split('\n').join('\\'))) &
|
||||
// If the robot has been found (recovered) we assume the token is backed up
|
||||
(data.found ? this.props.setAppState({ copiedToken: true }) : null);
|
||||
}),
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
delGeneratedUser() {
|
||||
const requestOptions = {
|
||||
method: 'DELETE',
|
||||
headers: {'Content-Type':'application/json', 'X-CSRFToken': getCookie('csrftoken')},
|
||||
headers: { 'Content-Type': 'application/json', 'X-CSRFToken': getCookie('csrftoken') },
|
||||
};
|
||||
fetch("/api/user", requestOptions)
|
||||
.then((response) => response.json());
|
||||
fetch('/api/user', requestOptions).then((response) => response.json());
|
||||
|
||||
deleteCookie("sessionid");
|
||||
deleteCookie("robot_token");
|
||||
deleteCookie("pub_key");
|
||||
deleteCookie("enc_priv_key");
|
||||
deleteCookie('sessionid');
|
||||
deleteCookie('robot_token');
|
||||
deleteCookie('pub_key');
|
||||
deleteCookie('enc_priv_key');
|
||||
}
|
||||
|
||||
handleClickNewRandomToken=()=>{
|
||||
handleClickNewRandomToken = () => {
|
||||
var token = genBase62Token(36);
|
||||
this.setState({
|
||||
token: token,
|
||||
tokenHasChanged: true,
|
||||
});
|
||||
this.props.setAppState({copiedToken: true})
|
||||
}
|
||||
this.props.setAppState({ copiedToken: true });
|
||||
};
|
||||
|
||||
handleChangeToken=(e)=>{
|
||||
handleChangeToken = (e) => {
|
||||
this.setState({
|
||||
token: e.target.value.split(' ').join(''),
|
||||
tokenHasChanged: true,
|
||||
})
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
handleClickSubmitToken=()=>{
|
||||
handleClickSubmitToken = () => {
|
||||
this.delGeneratedUser();
|
||||
this.getGeneratedUser(this.state.token);
|
||||
this.setState({loadingRobot: true, tokenHasChanged: false});
|
||||
this.props.setAppState({avatarLoaded: false,
|
||||
nickname: null,
|
||||
token: null,
|
||||
copiedToken: false,
|
||||
this.setState({ loadingRobot: true, tokenHasChanged: false });
|
||||
this.props.setAppState({
|
||||
avatarLoaded: false,
|
||||
nickname: null,
|
||||
token: null,
|
||||
copiedToken: false,
|
||||
lastOrderId: null,
|
||||
activeOrderId: null});
|
||||
}
|
||||
activeOrderId: null,
|
||||
});
|
||||
};
|
||||
|
||||
handleClickOpenInfo = () => {
|
||||
this.setState({openInfo: true});
|
||||
this.setState({ openInfo: true });
|
||||
};
|
||||
|
||||
handleCloseInfo = () => {
|
||||
this.setState({openInfo: false});
|
||||
this.setState({ openInfo: false });
|
||||
};
|
||||
|
||||
createJsonFile = () => {
|
||||
return ({
|
||||
"token":getCookie('robot_token'),
|
||||
"token_shannon_entropy": this.state.shannon_entropy,
|
||||
"token_bit_entropy": this.state.bit_entropy,
|
||||
"public_key": getCookie('pub_key').split('\\').join('\n'),
|
||||
"encrypted_private_key": getCookie('enc_priv_key').split('\\').join('\n'),
|
||||
})
|
||||
}
|
||||
return {
|
||||
token: getCookie('robot_token'),
|
||||
token_shannon_entropy: this.state.shannon_entropy,
|
||||
token_bit_entropy: this.state.bit_entropy,
|
||||
public_key: getCookie('pub_key').split('\\').join('\n'),
|
||||
encrypted_private_key: getCookie('enc_priv_key').split('\\').join('\n'),
|
||||
};
|
||||
};
|
||||
|
||||
render() {
|
||||
const { t, i18n} = this.props;
|
||||
const { t, i18n } = this.props;
|
||||
const fontSize = this.props.theme.typography.fontSize;
|
||||
const fontSizeFactor = fontSize / 14; // to scale sizes, default fontSize is 14
|
||||
return (
|
||||
<Grid container spacing={1}>
|
||||
<Grid item>
|
||||
<div className='clickTrough'/>
|
||||
<div className='clickTrough' />
|
||||
</Grid>
|
||||
<Grid item xs={12} align="center" sx={{width:370 * fontSizeFactor, height: 260 * fontSizeFactor}}>
|
||||
{!this.state.loadingRobot && this.state.avatarUrl ?
|
||||
<Grid
|
||||
item
|
||||
xs={12}
|
||||
align='center'
|
||||
sx={{ width: 370 * fontSizeFactor, height: 260 * fontSizeFactor }}
|
||||
>
|
||||
{!this.state.loadingRobot && this.state.avatarUrl ? (
|
||||
<div>
|
||||
<Grid item xs={12} align="center">
|
||||
<Typography component="h5" variant="h5">
|
||||
<b>{this.state.nickname && getCookie("sessionid") ?
|
||||
<div style={{display:'flex', alignItems:'center', justifyContent:'center', flexWrap:'wrap', height: 45 * fontSizeFactor}}>
|
||||
<BoltIcon sx={{ color: "#fcba03", height: 33 * fontSizeFactor, width: 33 * fontSizeFactor}}/>
|
||||
<a>{this.state.nickname}</a>
|
||||
<BoltIcon sx={{ color: "#fcba03", height: 33 * fontSizeFactor, width: 33 * fontSizeFactor}}/>
|
||||
</div>
|
||||
: ""}</b>
|
||||
<Grid item xs={12} align='center'>
|
||||
<Typography component='h5' variant='h5'>
|
||||
<b>
|
||||
{this.state.nickname && getCookie('sessionid') ? (
|
||||
<div
|
||||
style={{
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
flexWrap: 'wrap',
|
||||
height: 45 * fontSizeFactor,
|
||||
}}
|
||||
>
|
||||
<BoltIcon
|
||||
sx={{
|
||||
color: '#fcba03',
|
||||
height: 33 * fontSizeFactor,
|
||||
width: 33 * fontSizeFactor,
|
||||
}}
|
||||
/>
|
||||
<a>{this.state.nickname}</a>
|
||||
<BoltIcon
|
||||
sx={{
|
||||
color: '#fcba03',
|
||||
height: 33 * fontSizeFactor,
|
||||
width: 33 * fontSizeFactor,
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
) : (
|
||||
''
|
||||
)}
|
||||
</b>
|
||||
</Typography>
|
||||
</Grid>
|
||||
<Grid item xs={12} align="center">
|
||||
<Tooltip enterTouchDelay={0} title={t("This is your trading avatar")}>
|
||||
<div style={{ maxWidth: 200 * fontSizeFactor, maxHeight: 200 * fontSizeFactor}}>
|
||||
<SmoothImage
|
||||
src={this.state.avatarUrl}
|
||||
imageStyles={{borderRadius: "50%",
|
||||
border: "2px solid #555",
|
||||
filter: "drop-shadow(1px 1px 1px #000000)",
|
||||
height: `${195*fontSizeFactor}px`,
|
||||
width: `${200*fontSizeFactor}px`}}
|
||||
/>
|
||||
</div>
|
||||
<Grid item xs={12} align='center'>
|
||||
<Tooltip enterTouchDelay={0} title={t('This is your trading avatar')}>
|
||||
<div style={{ maxWidth: 200 * fontSizeFactor, maxHeight: 200 * fontSizeFactor }}>
|
||||
<SmoothImage
|
||||
src={this.state.avatarUrl}
|
||||
imageStyles={{
|
||||
borderRadius: '50%',
|
||||
border: '2px solid #555',
|
||||
filter: 'drop-shadow(1px 1px 1px #000000)',
|
||||
height: `${195 * fontSizeFactor}px`,
|
||||
width: `${200 * fontSizeFactor}px`,
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
</Tooltip>
|
||||
<br/>
|
||||
<br />
|
||||
</Grid>
|
||||
</div>
|
||||
: <CircularProgress sx={{position: 'relative', top: 100, }}/>}
|
||||
) : (
|
||||
<CircularProgress sx={{ position: 'relative', top: 100 }} />
|
||||
)}
|
||||
</Grid>
|
||||
{this.state.found ? (
|
||||
<Grid item xs={12} align='center'>
|
||||
<Typography variant='subtitle2' color='primary'>
|
||||
{this.state.found ? t('A robot avatar was found, welcome back!') : null}
|
||||
<br />
|
||||
</Typography>
|
||||
</Grid>
|
||||
{
|
||||
this.state.found ?
|
||||
<Grid item xs={12} align="center">
|
||||
<Typography variant="subtitle2" color='primary'>
|
||||
{this.state.found ? t("A robot avatar was found, welcome back!"):null}<br/>
|
||||
</Typography>
|
||||
</Grid>
|
||||
:
|
||||
""
|
||||
}
|
||||
<Grid container align="center">
|
||||
<Grid item xs={12} align="center">
|
||||
<TextField sx={{maxWidth: 280 * fontSizeFactor}}
|
||||
error={this.state.bad_request ? true : false}
|
||||
label={t("Store your token safely")}
|
||||
required={true}
|
||||
value={this.state.token}
|
||||
variant='standard'
|
||||
helperText={this.state.bad_request}
|
||||
size='small'
|
||||
onChange={this.handleChangeToken}
|
||||
onKeyPress={(e) => {
|
||||
if (e.key === 'Enter') {
|
||||
this.handleClickSubmitToken();
|
||||
}
|
||||
}}
|
||||
InputProps={{
|
||||
startAdornment:
|
||||
<div style={{width: 50*fontSizeFactor, minWidth: 50*fontSizeFactor, position:'relative',left:-6}}>
|
||||
) : (
|
||||
''
|
||||
)}
|
||||
<Grid container align='center'>
|
||||
<Grid item xs={12} align='center'>
|
||||
<TextField
|
||||
sx={{ maxWidth: 280 * fontSizeFactor }}
|
||||
error={this.state.bad_request ? true : false}
|
||||
label={t('Store your token safely')}
|
||||
required={true}
|
||||
value={this.state.token}
|
||||
variant='standard'
|
||||
helperText={this.state.bad_request}
|
||||
size='small'
|
||||
onChange={this.handleChangeToken}
|
||||
onKeyPress={(e) => {
|
||||
if (e.key === 'Enter') {
|
||||
this.handleClickSubmitToken();
|
||||
}
|
||||
}}
|
||||
InputProps={{
|
||||
startAdornment: (
|
||||
<div
|
||||
style={{
|
||||
width: 50 * fontSizeFactor,
|
||||
minWidth: 50 * fontSizeFactor,
|
||||
position: 'relative',
|
||||
left: -6,
|
||||
}}
|
||||
>
|
||||
<Grid container>
|
||||
<Grid item xs={6}>
|
||||
<Tooltip enterTouchDelay={250} title={t("Save token and PGP credentials to file")}>
|
||||
<Grid item xs={6}>
|
||||
<Tooltip
|
||||
enterTouchDelay={250}
|
||||
title={t('Save token and PGP credentials to file')}
|
||||
>
|
||||
<span>
|
||||
<IconButton
|
||||
color="primary"
|
||||
disabled={!(getCookie('robot_token')==this.state.token) || !this.props.avatarLoaded}
|
||||
onClick={()=> saveAsJson(this.state.nickname+'.json', this.createJsonFile())}
|
||||
<IconButton
|
||||
color='primary'
|
||||
disabled={
|
||||
!(getCookie('robot_token') == this.state.token) ||
|
||||
!this.props.avatarLoaded
|
||||
}
|
||||
onClick={() =>
|
||||
saveAsJson(this.state.nickname + '.json', this.createJsonFile())
|
||||
}
|
||||
>
|
||||
<DownloadIcon sx={{width: 22*fontSizeFactor, height: 22*fontSizeFactor}}/>
|
||||
</IconButton>
|
||||
<DownloadIcon
|
||||
sx={{ width: 22 * fontSizeFactor, height: 22 * fontSizeFactor }}
|
||||
/>
|
||||
</IconButton>
|
||||
</span>
|
||||
</Tooltip>
|
||||
</Grid>
|
||||
<Grid item xs={6}>
|
||||
<Tooltip disableHoverListener enterTouchDelay={0} title={t("Copied!")}>
|
||||
<IconButton
|
||||
color={this.props.copiedToken ? "inherit":"primary"}
|
||||
disabled={!(getCookie('robot_token')==this.state.token) || !this.props.avatarLoaded}
|
||||
onClick={()=> (copyToClipboard(getCookie('robot_token')) & this.props.setAppState({copiedToken:true}))}
|
||||
>
|
||||
<ContentCopy sx={{width: 18*fontSizeFactor, height: 18*fontSizeFactor}}/>
|
||||
<Tooltip disableHoverListener enterTouchDelay={0} title={t('Copied!')}>
|
||||
<IconButton
|
||||
color={this.props.copiedToken ? 'inherit' : 'primary'}
|
||||
disabled={
|
||||
!(getCookie('robot_token') == this.state.token) ||
|
||||
!this.props.avatarLoaded
|
||||
}
|
||||
onClick={() =>
|
||||
copyToClipboard(getCookie('robot_token')) &
|
||||
this.props.setAppState({ copiedToken: true })
|
||||
}
|
||||
>
|
||||
<ContentCopy
|
||||
sx={{ width: 18 * fontSizeFactor, height: 18 * fontSizeFactor }}
|
||||
/>
|
||||
</IconButton>
|
||||
</Tooltip>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</div>,
|
||||
endAdornment:
|
||||
<Tooltip enterTouchDelay={250} title={t("Generate a new token")}>
|
||||
</div>
|
||||
),
|
||||
endAdornment: (
|
||||
<Tooltip enterTouchDelay={250} title={t('Generate a new token')}>
|
||||
<IconButton onClick={this.handleClickNewRandomToken}>
|
||||
<CasinoIcon sx={{width: 18*fontSizeFactor, height: 18*fontSizeFactor}}/>
|
||||
<CasinoIcon
|
||||
sx={{ width: 18 * fontSizeFactor, height: 18 * fontSizeFactor }}
|
||||
/>
|
||||
</IconButton>
|
||||
</Tooltip>,
|
||||
}}
|
||||
/>
|
||||
</Grid>
|
||||
</Tooltip>
|
||||
),
|
||||
}}
|
||||
/>
|
||||
</Grid>
|
||||
<Grid item xs={12} align="center">
|
||||
{this.state.tokenHasChanged ?
|
||||
<Button type="submit" size='small' onClick= {this.handleClickSubmitToken}>
|
||||
<SmartToyIcon sx={{width: 18*fontSizeFactor, height: 18*fontSizeFactor}} />
|
||||
<span> {t("Generate Robot")}</span>
|
||||
</Grid>
|
||||
<Grid item xs={12} align='center'>
|
||||
{this.state.tokenHasChanged ? (
|
||||
<Button type='submit' size='small' onClick={this.handleClickSubmitToken}>
|
||||
<SmartToyIcon sx={{ width: 18 * fontSizeFactor, height: 18 * fontSizeFactor }} />
|
||||
<span> {t('Generate Robot')}</span>
|
||||
</Button>
|
||||
:
|
||||
<Tooltip enterTouchDelay={0} enterDelay={500} enterNextDelay={2000} title={t("You must enter a new token first")}>
|
||||
) : (
|
||||
<Tooltip
|
||||
enterTouchDelay={0}
|
||||
enterDelay={500}
|
||||
enterNextDelay={2000}
|
||||
title={t('You must enter a new token first')}
|
||||
>
|
||||
<div>
|
||||
<Button disabled={true} type="submit" size='small' >
|
||||
<SmartToyIcon sx={{width: 18*fontSizeFactor, height: 18*fontSizeFactor}} />
|
||||
<span>{t("Generate Robot")}</span>
|
||||
</Button>
|
||||
<Button disabled={true} type='submit' size='small'>
|
||||
<SmartToyIcon sx={{ width: 18 * fontSizeFactor, height: 18 * fontSizeFactor }} />
|
||||
<span>{t('Generate Robot')}</span>
|
||||
</Button>
|
||||
</div>
|
||||
</Tooltip>
|
||||
}
|
||||
</Grid>
|
||||
<Grid item xs={12} align="center">
|
||||
<ButtonGroup variant="contained" aria-label="outlined primary button group">
|
||||
<Button disabled={this.state.loadingRobot || !(this.props.token ? getCookie('robot_token')==this.props.token : true )} color='primary' to='/make/' component={Link}>{t("Make Order")}</Button>
|
||||
<Button color='inherit' style={{color: '#111111'}} onClick={this.handleClickOpenInfo}>{t("Info")}</Button>
|
||||
<InfoDialog open={Boolean(this.state.openInfo)} maxAmount='4,000,000' onClose = {this.handleCloseInfo}/>
|
||||
<Button disabled={this.state.loadingRobot || !(this.props.token ? getCookie('robot_token')==this.props.token : true )} color='secondary' to='/book/' component={Link}>{t("View Book")}</Button>
|
||||
</ButtonGroup>
|
||||
</Grid>
|
||||
)}
|
||||
</Grid>
|
||||
<Grid item xs={12} align='center'>
|
||||
<ButtonGroup variant='contained' aria-label='outlined primary button group'>
|
||||
<Button
|
||||
disabled={
|
||||
this.state.loadingRobot ||
|
||||
!(this.props.token ? getCookie('robot_token') == this.props.token : true)
|
||||
}
|
||||
color='primary'
|
||||
to='/make/'
|
||||
component={Link}
|
||||
>
|
||||
{t('Make Order')}
|
||||
</Button>
|
||||
<Button color='inherit' style={{ color: '#111111' }} onClick={this.handleClickOpenInfo}>
|
||||
{t('Info')}
|
||||
</Button>
|
||||
<InfoDialog
|
||||
open={Boolean(this.state.openInfo)}
|
||||
maxAmount='4,000,000'
|
||||
onClose={this.handleCloseInfo}
|
||||
/>
|
||||
<Button
|
||||
disabled={
|
||||
this.state.loadingRobot ||
|
||||
!(this.props.token ? getCookie('robot_token') == this.props.token : true)
|
||||
}
|
||||
color='secondary'
|
||||
to='/book/'
|
||||
component={Link}
|
||||
>
|
||||
{t('View Book')}
|
||||
</Button>
|
||||
</ButtonGroup>
|
||||
</Grid>
|
||||
|
||||
<Grid item xs={12} align="center" sx={{width: 370*fontSizeFactor}}>
|
||||
<Grid item>
|
||||
<div style={{height: 30*fontSizeFactor}}/>
|
||||
</Grid>
|
||||
<div style={{width: 370*fontSizeFactor, left: 30*fontSizeFactor}}>
|
||||
<Grid container align="center">
|
||||
<Grid item xs={0.8}/>
|
||||
<Grid item xs={7.5} align="right">
|
||||
<Typography component="h5" variant="h5">
|
||||
{t("Simple and Private LN P2P Exchange")}
|
||||
</Typography>
|
||||
</Grid>
|
||||
<Grid item xs={2.5} align="left">
|
||||
<RoboSatsNoTextIcon color="primary"
|
||||
sx={{height: 72 * fontSizeFactor, width: 72 * fontSizeFactor}}
|
||||
/>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</div>
|
||||
<Grid item xs={12} align='center' sx={{ width: 370 * fontSizeFactor }}>
|
||||
<Grid item>
|
||||
<div style={{ height: 30 * fontSizeFactor }} />
|
||||
</Grid>
|
||||
<div style={{ width: 370 * fontSizeFactor, left: 30 * fontSizeFactor }}>
|
||||
<Grid container align='center'>
|
||||
<Grid item xs={0.8} />
|
||||
<Grid item xs={7.5} align='right'>
|
||||
<Typography component='h5' variant='h5'>
|
||||
{t('Simple and Private LN P2P Exchange')}
|
||||
</Typography>
|
||||
</Grid>
|
||||
<Grid item xs={2.5} align='left'>
|
||||
<RoboSatsNoTextIcon
|
||||
color='primary'
|
||||
sx={{ height: 72 * fontSizeFactor, width: 72 * fontSizeFactor }}
|
||||
/>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</div>
|
||||
</Grid>
|
||||
</Grid>
|
||||
);
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
import i18n from "i18next";
|
||||
import LanguageDetector from "i18next-browser-languagedetector";
|
||||
import { initReactI18next } from "react-i18next";
|
||||
import i18n from 'i18next';
|
||||
import LanguageDetector from 'i18next-browser-languagedetector';
|
||||
import { initReactI18next } from 'react-i18next';
|
||||
import HttpApi from 'i18next-http-backend';
|
||||
|
||||
// import translationEN from "../../static/locales/en.json";
|
||||
@ -20,49 +20,49 @@ i18n
|
||||
.use(LanguageDetector)
|
||||
.use(initReactI18next)
|
||||
.init({
|
||||
// resources: {
|
||||
// en: {translations: translationEN},
|
||||
// es: {translations: translationES},
|
||||
// ru: {translations: translationRU},
|
||||
// de: {translations: translationDE},
|
||||
// // zh: {translations: translationZH},
|
||||
// pl: {translations: translationPL},
|
||||
// fr: {translations: translationFR},
|
||||
// ca: {translations: translationCA},
|
||||
// it: {translations: translationIT},
|
||||
// pt: {translations: translationPT},
|
||||
// eu: {translations: translationEU},
|
||||
// sv: {translations: translationSV},
|
||||
// cs: {translations: translationCS},
|
||||
// th: {translations: translationCS},
|
||||
// },
|
||||
|
||||
backend:{
|
||||
loadPath: '/static/locales/{{lng}}.json',
|
||||
allowMultiLoading: false, // set loadPath: '/locales/resources.json?lng={{lng}}&ns={{ns}}' to adapt to multiLoading
|
||||
crossDomain: false,
|
||||
withCredentials: false,
|
||||
overrideMimeType: false,
|
||||
reloadInterval: false // can be used to reload resources in a specific interval (useful in server environments)
|
||||
},
|
||||
// resources: {
|
||||
// en: {translations: translationEN},
|
||||
// es: {translations: translationES},
|
||||
// ru: {translations: translationRU},
|
||||
// de: {translations: translationDE},
|
||||
// // zh: {translations: translationZH},
|
||||
// pl: {translations: translationPL},
|
||||
// fr: {translations: translationFR},
|
||||
// ca: {translations: translationCA},
|
||||
// it: {translations: translationIT},
|
||||
// pt: {translations: translationPT},
|
||||
// eu: {translations: translationEU},
|
||||
// sv: {translations: translationSV},
|
||||
// cs: {translations: translationCS},
|
||||
// th: {translations: translationCS},
|
||||
// },
|
||||
|
||||
fallbackLng: "en",
|
||||
debug: false,
|
||||
backend: {
|
||||
loadPath: '/static/locales/{{lng}}.json',
|
||||
allowMultiLoading: false, // set loadPath: '/locales/resources.json?lng={{lng}}&ns={{ns}}' to adapt to multiLoading
|
||||
crossDomain: false,
|
||||
withCredentials: false,
|
||||
overrideMimeType: false,
|
||||
reloadInterval: false, // can be used to reload resources in a specific interval (useful in server environments)
|
||||
},
|
||||
|
||||
// have a common namespace used around the full app
|
||||
ns: ["translations"],
|
||||
defaultNS: "translations",
|
||||
fallbackLng: 'en',
|
||||
debug: false,
|
||||
|
||||
keySeparator: false, // we use content as keys
|
||||
// have a common namespace used around the full app
|
||||
ns: ['translations'],
|
||||
defaultNS: 'translations',
|
||||
|
||||
interpolation: {
|
||||
escapeValue: false,
|
||||
formatSeparator: ","
|
||||
},
|
||||
|
||||
react: {
|
||||
useSuspense: false,
|
||||
}
|
||||
});
|
||||
keySeparator: false, // we use content as keys
|
||||
|
||||
export default i18n;
|
||||
interpolation: {
|
||||
escapeValue: false,
|
||||
formatSeparator: ',',
|
||||
},
|
||||
|
||||
react: {
|
||||
useSuspense: false,
|
||||
},
|
||||
});
|
||||
|
||||
export default i18n;
|
||||
|
File diff suppressed because one or more lines are too long
@ -1,86 +1,86 @@
|
||||
export const paymentMethods = [
|
||||
{name: "Revolut",icon:'revolut'},
|
||||
{name: "CashApp",icon:'cashapp'},
|
||||
{name: "Zelle",icon:'zelle'},
|
||||
{name: "Strike",icon:'strike'},
|
||||
{name: "WeChat Pay", icon: 'wechatpay'},
|
||||
{name: "Rebellion",icon:'rebellion'},
|
||||
{name: "Instant SEPA", icon:'sepa'},
|
||||
{name: "Interac e-Transfer",icon:'interac'},
|
||||
{name: "Wise",icon:'wise'},
|
||||
{name: "Venmo",icon:'venmo'},
|
||||
{name: "Faster Payments",icon:'faster'},
|
||||
{name: "Paypal Friends & Family",icon:'paypal'},
|
||||
{name: "LINE Pay",icon:'linepay'},
|
||||
{name: "PromptPay",icon:'promptpay'},
|
||||
{name: "Bizum",icon:'bizum'},
|
||||
{name: "N26",icon:'n26'},
|
||||
{name: "Tinkoff",icon:'tinkoff'},
|
||||
{name: "TWINT",icon:'twint'},
|
||||
{name: "BLIK",icon:'blik'},
|
||||
{name: "MBWay",icon:'mbway'},
|
||||
{name: "W1TTY",icon:'w1tty'},
|
||||
{name: "Verse",icon:'verse'},
|
||||
{name: "Paysera",icon:'paysera'},
|
||||
{name: "Amazon GiftCard",icon:'amazon'},
|
||||
{name: "Ozon GiftCard",icon:'ozon'},
|
||||
{name: "AliPay", icon: 'alipay'},
|
||||
{name: "GPay", icon: 'gpay'},
|
||||
{name: "Bancolombia",icon:'bancolombia'},
|
||||
{name: "Pago Movil BDV",icon:'pagomovilbdv'},
|
||||
{name: "SPEI",icon:'spei'},
|
||||
{name: "PIX",icon:'pix'},
|
||||
{name: "PayID",icon:'payid'},
|
||||
{name: "Paysafe",icon:'paysafe'},
|
||||
{name: "Sberbank",icon:'sberbank'},
|
||||
{name: "PhonePe",icon:'phonepe'},
|
||||
{name: "OVO",icon:'ovo'},
|
||||
{name: "HalCash",icon:'halcash'},
|
||||
{name: "Vivid",icon:'vivid'},
|
||||
{name: "Google Play Gift Code",icon:'googleplay'},
|
||||
{name: "Apple Pay",icon:'applepay'},
|
||||
{name: "Steam",icon:'steam'},
|
||||
{name: "Nequi",icon:'nequi'},
|
||||
{name: "ShakePay",icon:'shakepay'},
|
||||
{name: "DaviPlata",icon:'daviplata'},
|
||||
{name: "CoDi",icon:'codi'},
|
||||
{name: "TaiwanPay",icon:'taiwanpay'},
|
||||
{name: "MaiCoin",icon:'maicoin'},
|
||||
{name: "GoPay", icon: 'gopay'},
|
||||
{name: "MercadoPago",icon:'mercadopago'},
|
||||
{name: "Monero",icon:'monero'},
|
||||
{name: "USDT",icon:'usdt'},
|
||||
{name: "Airtel Money",icon:'airtel'},
|
||||
{name: "MTN Money",icon:'mtn'},
|
||||
{name: "M-Pesa",icon:'mpesa'},
|
||||
{name: "UPI",icon:'upi'},
|
||||
{name: "MoMo",icon:'momo'},
|
||||
{name: "Tigo Pesa",icon:'tigopesa'},
|
||||
{name: "Cash F2F",icon:'cash'},
|
||||
{name: "Amazon USA GiftCard",icon:'amazonus'},
|
||||
{name: "Amazon DE GiftCard",icon:'amazonde'},
|
||||
{name: "Amazon AU GiftCard",icon:'amazonau'},
|
||||
{name: "Amazon SA GiftCard",icon:'amazonsa'},
|
||||
{name: "Amazon ES GiftCard",icon:'amazones'},
|
||||
{name: "Amazon CA GiftCard",icon:'amazonca'},
|
||||
{name: "Amazon CN GiftCard",icon:'amazoncn'},
|
||||
{name: "Amazon AE GiftCard",icon:'amazonae'},
|
||||
{name: "Amazon FR GiftCard",icon:'amazonfr'},
|
||||
{name: "Amazon NL GiftCard",icon:'amazonnl'},
|
||||
{name: "Amazon IN GiftCard",icon:'amazonin'},
|
||||
{name: "Amazon IT GiftCard",icon:'amazonit'},
|
||||
{name: "Amazon JP GiftCard",icon:'amazonjp'},
|
||||
{name: "Amazon MX GiftCard",icon:'amazonmx'},
|
||||
{name: "Amazon PL GiftCard",icon:'amazonpl'},
|
||||
{name: "Amazon UK GiftCard",icon:'amazonuk'},
|
||||
{name: "Amazon SE GiftCard",icon:'amazonse'},
|
||||
{name: "Amazon SG GiftCard",icon:'amazonsg'},
|
||||
{name: "Amazon TR GiftCard",icon:'amazontr'},
|
||||
];
|
||||
|
||||
{ name: 'Revolut', icon: 'revolut' },
|
||||
{ name: 'CashApp', icon: 'cashapp' },
|
||||
{ name: 'Zelle', icon: 'zelle' },
|
||||
{ name: 'Strike', icon: 'strike' },
|
||||
{ name: 'WeChat Pay', icon: 'wechatpay' },
|
||||
{ name: 'Rebellion', icon: 'rebellion' },
|
||||
{ name: 'Instant SEPA', icon: 'sepa' },
|
||||
{ name: 'Interac e-Transfer', icon: 'interac' },
|
||||
{ name: 'Wise', icon: 'wise' },
|
||||
{ name: 'Venmo', icon: 'venmo' },
|
||||
{ name: 'Faster Payments', icon: 'faster' },
|
||||
{ name: 'Paypal Friends & Family', icon: 'paypal' },
|
||||
{ name: 'LINE Pay', icon: 'linepay' },
|
||||
{ name: 'PromptPay', icon: 'promptpay' },
|
||||
{ name: 'Bizum', icon: 'bizum' },
|
||||
{ name: 'N26', icon: 'n26' },
|
||||
{ name: 'Tinkoff', icon: 'tinkoff' },
|
||||
{ name: 'TWINT', icon: 'twint' },
|
||||
{ name: 'BLIK', icon: 'blik' },
|
||||
{ name: 'MBWay', icon: 'mbway' },
|
||||
{ name: 'W1TTY', icon: 'w1tty' },
|
||||
{ name: 'Verse', icon: 'verse' },
|
||||
{ name: 'Paysera', icon: 'paysera' },
|
||||
{ name: 'Amazon GiftCard', icon: 'amazon' },
|
||||
{ name: 'Ozon GiftCard', icon: 'ozon' },
|
||||
{ name: 'AliPay', icon: 'alipay' },
|
||||
{ name: 'GPay', icon: 'gpay' },
|
||||
{ name: 'Bancolombia', icon: 'bancolombia' },
|
||||
{ name: 'Pago Movil BDV', icon: 'pagomovilbdv' },
|
||||
{ name: 'SPEI', icon: 'spei' },
|
||||
{ name: 'PIX', icon: 'pix' },
|
||||
{ name: 'PayID', icon: 'payid' },
|
||||
{ name: 'Paysafe', icon: 'paysafe' },
|
||||
{ name: 'Sberbank', icon: 'sberbank' },
|
||||
{ name: 'PhonePe', icon: 'phonepe' },
|
||||
{ name: 'OVO', icon: 'ovo' },
|
||||
{ name: 'HalCash', icon: 'halcash' },
|
||||
{ name: 'Vivid', icon: 'vivid' },
|
||||
{ name: 'Google Play Gift Code', icon: 'googleplay' },
|
||||
{ name: 'Apple Pay', icon: 'applepay' },
|
||||
{ name: 'Steam', icon: 'steam' },
|
||||
{ name: 'Nequi', icon: 'nequi' },
|
||||
{ name: 'ShakePay', icon: 'shakepay' },
|
||||
{ name: 'DaviPlata', icon: 'daviplata' },
|
||||
{ name: 'CoDi', icon: 'codi' },
|
||||
{ name: 'TaiwanPay', icon: 'taiwanpay' },
|
||||
{ name: 'MaiCoin', icon: 'maicoin' },
|
||||
{ name: 'GoPay', icon: 'gopay' },
|
||||
{ name: 'MercadoPago', icon: 'mercadopago' },
|
||||
{ name: 'Monero', icon: 'monero' },
|
||||
{ name: 'USDT', icon: 'usdt' },
|
||||
{ name: 'Airtel Money', icon: 'airtel' },
|
||||
{ name: 'MTN Money', icon: 'mtn' },
|
||||
{ name: 'M-Pesa', icon: 'mpesa' },
|
||||
{ name: 'UPI', icon: 'upi' },
|
||||
{ name: 'MoMo', icon: 'momo' },
|
||||
{ name: 'Tigo Pesa', icon: 'tigopesa' },
|
||||
{ name: 'Cash F2F', icon: 'cash' },
|
||||
{ name: 'Amazon USA GiftCard', icon: 'amazonus' },
|
||||
{ name: 'Amazon DE GiftCard', icon: 'amazonde' },
|
||||
{ name: 'Amazon AU GiftCard', icon: 'amazonau' },
|
||||
{ name: 'Amazon SA GiftCard', icon: 'amazonsa' },
|
||||
{ name: 'Amazon ES GiftCard', icon: 'amazones' },
|
||||
{ name: 'Amazon CA GiftCard', icon: 'amazonca' },
|
||||
{ name: 'Amazon CN GiftCard', icon: 'amazoncn' },
|
||||
{ name: 'Amazon AE GiftCard', icon: 'amazonae' },
|
||||
{ name: 'Amazon FR GiftCard', icon: 'amazonfr' },
|
||||
{ name: 'Amazon NL GiftCard', icon: 'amazonnl' },
|
||||
{ name: 'Amazon IN GiftCard', icon: 'amazonin' },
|
||||
{ name: 'Amazon IT GiftCard', icon: 'amazonit' },
|
||||
{ name: 'Amazon JP GiftCard', icon: 'amazonjp' },
|
||||
{ name: 'Amazon MX GiftCard', icon: 'amazonmx' },
|
||||
{ name: 'Amazon PL GiftCard', icon: 'amazonpl' },
|
||||
{ name: 'Amazon UK GiftCard', icon: 'amazonuk' },
|
||||
{ name: 'Amazon SE GiftCard', icon: 'amazonse' },
|
||||
{ name: 'Amazon SG GiftCard', icon: 'amazonsg' },
|
||||
{ name: 'Amazon TR GiftCard', icon: 'amazontr' },
|
||||
];
|
||||
|
||||
export const swapDestinations = [
|
||||
{name: "On-Chain BTC",icon:'onchain'},
|
||||
{name: "RBTC",icon:'rbtc'},
|
||||
{name: "LBTC",icon:'lbtc'},
|
||||
{name: "WBTC",icon:'wbtc'},
|
||||
];
|
||||
{ name: 'On-Chain BTC', icon: 'onchain' },
|
||||
{ name: 'RBTC', icon: 'rbtc' },
|
||||
{ name: 'LBTC', icon: 'lbtc' },
|
||||
{ name: 'WBTC', icon: 'wbtc' },
|
||||
];
|
||||
|
@ -1 +1 @@
|
||||
import App from "./components/App";
|
||||
import App from './components/App';
|
||||
|
@ -1,13 +1,13 @@
|
||||
export interface Limit {
|
||||
code: string,
|
||||
price: number,
|
||||
min_amount: number,
|
||||
max_amount: number,
|
||||
max_bondless_amount: number
|
||||
code: string;
|
||||
price: number;
|
||||
min_amount: number;
|
||||
max_amount: number;
|
||||
max_bondless_amount: number;
|
||||
}
|
||||
|
||||
export interface LimitList {
|
||||
[currencyCode: string]: Limit
|
||||
[currencyCode: string]: Limit;
|
||||
}
|
||||
|
||||
export default Limit
|
||||
export default Limit;
|
||||
|
@ -1,24 +1,24 @@
|
||||
export interface Order {
|
||||
id: number,
|
||||
created_at: Date,
|
||||
expires_at: Date,
|
||||
type: number,
|
||||
currency: number,
|
||||
amount: string,
|
||||
base_amount?: number,
|
||||
has_range: boolean,
|
||||
min_amount: number,
|
||||
max_amount: number,
|
||||
payment_method: string,
|
||||
is_explicit: false,
|
||||
premium: number,
|
||||
satoshis: number,
|
||||
bondless_taker: boolean,
|
||||
maker: number,
|
||||
escrow_duration: number,
|
||||
maker_nick: string,
|
||||
price: number,
|
||||
maker_status: "Active" | "Seen recently" | "Inactive"
|
||||
id: number;
|
||||
created_at: Date;
|
||||
expires_at: Date;
|
||||
type: number;
|
||||
currency: number;
|
||||
amount: string;
|
||||
base_amount?: number;
|
||||
has_range: boolean;
|
||||
min_amount: number;
|
||||
max_amount: number;
|
||||
payment_method: string;
|
||||
is_explicit: false;
|
||||
premium: number;
|
||||
satoshis: number;
|
||||
bondless_taker: boolean;
|
||||
maker: number;
|
||||
escrow_duration: number;
|
||||
maker_nick: string;
|
||||
price: number;
|
||||
maker_status: 'Active' | 'Seen recently' | 'Inactive';
|
||||
}
|
||||
|
||||
export default Order
|
||||
export default Order;
|
||||
|
@ -1,24 +1,25 @@
|
||||
export function copyToClipboard(textToCopy) {
|
||||
// navigator clipboard api needs a secure context (https)
|
||||
// this function attempts to copy also on http contexts
|
||||
// useful on the http i2p site and on torified browsers
|
||||
if (navigator.clipboard && window.isSecureContext) {
|
||||
// navigator clipboard api needs a secure context (https)
|
||||
// this function attempts to copy also on http contexts
|
||||
// useful on the http i2p site and on torified browsers
|
||||
if (navigator.clipboard && window.isSecureContext) {
|
||||
// navigator clipboard api method'
|
||||
return navigator.clipboard.writeText(textToCopy);
|
||||
} else {
|
||||
} else {
|
||||
// text area method
|
||||
let textArea = document.createElement("textarea");
|
||||
let textArea = document.createElement('textarea');
|
||||
textArea.value = textToCopy;
|
||||
// make the textarea out of viewport
|
||||
textArea.style.position = "fixed";
|
||||
textArea.style.left = "-999999px";
|
||||
textArea.style.top = "-999999px";
|
||||
textArea.style.position = 'fixed';
|
||||
textArea.style.left = '-999999px';
|
||||
textArea.style.top = '-999999px';
|
||||
document.body.appendChild(textArea);
|
||||
textArea.focus();
|
||||
textArea.select();
|
||||
return new Promise((res, rej) => {
|
||||
// here the magic happens
|
||||
document.execCommand('copy') ? res() : rej();
|
||||
textArea.remove();
|
||||
// here the magic happens
|
||||
document.execCommand('copy') ? res() : rej();
|
||||
textArea.remove();
|
||||
});
|
||||
}}
|
||||
}
|
||||
}
|
||||
|
@ -5,7 +5,7 @@ export const getCookie = (name) => {
|
||||
for (let i = 0; i < cookies.length; i++) {
|
||||
const cookie = cookies[i].trim();
|
||||
// Does this cookie string begin with the name we want?
|
||||
if (cookie.substring(0, name.length + 1) === (name + '=')) {
|
||||
if (cookie.substring(0, name.length + 1) === name + '=') {
|
||||
cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
|
||||
break;
|
||||
}
|
||||
@ -14,10 +14,10 @@ export const getCookie = (name) => {
|
||||
return cookieValue;
|
||||
};
|
||||
|
||||
export const writeCookie = (key,value) => {
|
||||
document.cookie=`${key}=${value};path=/;SameSite=Strict`;
|
||||
}
|
||||
export const writeCookie = (key, value) => {
|
||||
document.cookie = `${key}=${value};path=/;SameSite=Strict`;
|
||||
};
|
||||
|
||||
export const deleteCookie = (name) => {
|
||||
document.cookie = `${name}= ; expires = Thu, 01 Jan 1970 00:00:00 GMT`
|
||||
}
|
||||
document.cookie = `${name}= ; expires = Thu, 01 Jan 1970 00:00:00 GMT`;
|
||||
};
|
||||
|
@ -4,4 +4,4 @@ export const median = (arr: number[]) => {
|
||||
return arr.length % 2 !== 0 ? nums[mid] : (nums[mid - 1] + nums[mid]) / 2;
|
||||
};
|
||||
|
||||
export default median
|
||||
export default median;
|
||||
|
@ -1,12 +1,12 @@
|
||||
import {
|
||||
generateKey,
|
||||
readKey,
|
||||
readPrivateKey,
|
||||
decryptKey,
|
||||
encrypt,
|
||||
decrypt,
|
||||
createMessage,
|
||||
readMessage
|
||||
import {
|
||||
generateKey,
|
||||
readKey,
|
||||
readPrivateKey,
|
||||
decryptKey,
|
||||
encrypt,
|
||||
decrypt,
|
||||
createMessage,
|
||||
readMessage,
|
||||
} from 'openpgp/lightweight';
|
||||
import { sha256 } from 'js-sha256';
|
||||
|
||||
@ -16,60 +16,69 @@ export async function genKey(highEntropyToken) {
|
||||
const keyPair = await generateKey({
|
||||
type: 'ecc', // Type of the key, defaults to ECC
|
||||
curve: 'curve25519', // ECC curve name, defaults to curve25519
|
||||
userIDs: [{name: 'RoboSats ID '+ sha256(sha256(highEntropyToken))}], //Ideally it would be the avatar nickname, but the nickname is generated only after submission. The second SHA256 can be converted into the Nickname using nick_generator package.
|
||||
userIDs: [{ name: 'RoboSats ID ' + sha256(sha256(highEntropyToken)) }], //Ideally it would be the avatar nickname, but the nickname is generated only after submission. The second SHA256 can be converted into the Nickname using nick_generator package.
|
||||
passphrase: highEntropyToken,
|
||||
format: 'armored',
|
||||
date: d.setDate(d.getDate()-1) // One day of offset. Helps reducing errors due to client's system time being in the future.
|
||||
})
|
||||
date: d.setDate(d.getDate() - 1), // One day of offset. Helps reducing errors due to client's system time being in the future.
|
||||
});
|
||||
|
||||
return {publicKeyArmored: keyPair.publicKey, encryptedPrivateKeyArmored: keyPair.privateKey}
|
||||
};
|
||||
return { publicKeyArmored: keyPair.publicKey, encryptedPrivateKeyArmored: keyPair.privateKey };
|
||||
}
|
||||
|
||||
// Encrypt and sign a message
|
||||
export async function encryptMessage(plaintextMessage, ownPublicKeyArmored, peerPublicKeyArmored, privateKeyArmored, passphrase) {
|
||||
|
||||
export async function encryptMessage(
|
||||
plaintextMessage,
|
||||
ownPublicKeyArmored,
|
||||
peerPublicKeyArmored,
|
||||
privateKeyArmored,
|
||||
passphrase,
|
||||
) {
|
||||
const ownPublicKey = await readKey({ armoredKey: ownPublicKeyArmored });
|
||||
const peerPublicKey = await readKey({ armoredKey: peerPublicKeyArmored });
|
||||
const privateKey = await decryptKey({
|
||||
privateKey: await readPrivateKey({ armoredKey: privateKeyArmored }),
|
||||
passphrase
|
||||
privateKey: await readPrivateKey({ armoredKey: privateKeyArmored }),
|
||||
passphrase,
|
||||
});
|
||||
|
||||
const d = new Date();
|
||||
const encryptedMessage = await encrypt({
|
||||
message: await createMessage({ text: plaintextMessage }), // input as Message object, message must be string
|
||||
encryptionKeys: [ ownPublicKey, peerPublicKey ],
|
||||
signingKeys: privateKey, // optional
|
||||
date: d.setDate(d.getDate()-1) // One day of offset, avoids verification issue due to clock mismatch
|
||||
message: await createMessage({ text: plaintextMessage }), // input as Message object, message must be string
|
||||
encryptionKeys: [ownPublicKey, peerPublicKey],
|
||||
signingKeys: privateKey, // optional
|
||||
date: d.setDate(d.getDate() - 1), // One day of offset, avoids verification issue due to clock mismatch
|
||||
});
|
||||
|
||||
return encryptedMessage; // '-----BEGIN PGP MESSAGE ... END PGP MESSAGE-----'
|
||||
};
|
||||
}
|
||||
|
||||
// Decrypt and check signature of a message
|
||||
export async function decryptMessage(encryptedMessage, publicKeyArmored, privateKeyArmored, passphrase) {
|
||||
|
||||
export async function decryptMessage(
|
||||
encryptedMessage,
|
||||
publicKeyArmored,
|
||||
privateKeyArmored,
|
||||
passphrase,
|
||||
) {
|
||||
const publicKey = await readKey({ armoredKey: publicKeyArmored });
|
||||
const privateKey = await decryptKey({
|
||||
privateKey: await readPrivateKey({ armoredKey: privateKeyArmored }),
|
||||
passphrase
|
||||
privateKey: await readPrivateKey({ armoredKey: privateKeyArmored }),
|
||||
passphrase,
|
||||
});
|
||||
|
||||
const message = await readMessage({
|
||||
armoredMessage: encryptedMessage // parse armored message
|
||||
armoredMessage: encryptedMessage, // parse armored message
|
||||
});
|
||||
const { data: decrypted, signatures } = await decrypt({
|
||||
message,
|
||||
verificationKeys: publicKey, // optional
|
||||
decryptionKeys: privateKey
|
||||
message,
|
||||
verificationKeys: publicKey, // optional
|
||||
decryptionKeys: privateKey,
|
||||
});
|
||||
|
||||
// check signature validity (signed messages only)
|
||||
try {
|
||||
await signatures[0].verified; // throws on invalid signature
|
||||
console.log('Signature is valid');
|
||||
return {decryptedMessage: decrypted, validSignature: true}
|
||||
return { decryptedMessage: decrypted, validSignature: true };
|
||||
} catch (e) {
|
||||
return {decryptedMessage: decrypted, validSignature: false};
|
||||
return { decryptedMessage: decrypted, validSignature: false };
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@ -1,45 +1,45 @@
|
||||
import { pn, amountToString } from "./prettyNumbers";
|
||||
import { pn, amountToString } from './prettyNumbers';
|
||||
|
||||
describe("prettyNumbers", () => {
|
||||
test("pn()", () => {
|
||||
describe('prettyNumbers', () => {
|
||||
test('pn()', () => {
|
||||
[
|
||||
{input: null, output: undefined},
|
||||
{input: undefined, output: undefined},
|
||||
{input: 0, output: "0"},
|
||||
{input: 1, output: "1"},
|
||||
{input: 2, output: "2"},
|
||||
{input: 10, output: "10"},
|
||||
{input: 11, output: "11"},
|
||||
{input: 11.0, output: "11"},
|
||||
{input: 12.0, output: "12"},
|
||||
{input: 100.50, output: "100.5"},
|
||||
{input: 224.56, output: "224.56"},
|
||||
{input: 1567, output: "1,567"},
|
||||
{input: 15678, output: "15,678"},
|
||||
{input: 2984.99, output: "2,984.99"},
|
||||
{input: 100000.00, output: "100,000"},
|
||||
{ input: null, output: undefined },
|
||||
{ input: undefined, output: undefined },
|
||||
{ input: 0, output: '0' },
|
||||
{ input: 1, output: '1' },
|
||||
{ input: 2, output: '2' },
|
||||
{ input: 10, output: '10' },
|
||||
{ input: 11, output: '11' },
|
||||
{ input: 11.0, output: '11' },
|
||||
{ input: 12.0, output: '12' },
|
||||
{ input: 100.5, output: '100.5' },
|
||||
{ input: 224.56, output: '224.56' },
|
||||
{ input: 1567, output: '1,567' },
|
||||
{ input: 15678, output: '15,678' },
|
||||
{ input: 2984.99, output: '2,984.99' },
|
||||
{ input: 100000.0, output: '100,000' },
|
||||
].forEach((it) => {
|
||||
const response = pn(it.input);
|
||||
expect(response).toBe(it.output);
|
||||
});
|
||||
});
|
||||
})
|
||||
});
|
||||
|
||||
describe("amountToString", () => {
|
||||
test("pn()", () => {
|
||||
describe('amountToString', () => {
|
||||
test('pn()', () => {
|
||||
[
|
||||
{input: null, output: "NaN"},
|
||||
{input: undefined, output: "NaN"},
|
||||
{input: ["", false, 50, 150] , output: "0"},
|
||||
{input: ["100.00", false, 50, 150] , output: "100"},
|
||||
{input: ["100.00", true, undefined, undefined] , output: "NaN-NaN"},
|
||||
{input: ["100.00", true, undefined, 150] , output: "NaN-150"},
|
||||
{input: ["100.00", true, 50, undefined] , output: "50-NaN"},
|
||||
{input: ["100.00", true, 50, 150] , output: "50-150"},
|
||||
{ input: null, output: 'NaN' },
|
||||
{ input: undefined, output: 'NaN' },
|
||||
{ input: ['', false, 50, 150], output: '0' },
|
||||
{ input: ['100.00', false, 50, 150], output: '100' },
|
||||
{ input: ['100.00', true, undefined, undefined], output: 'NaN-NaN' },
|
||||
{ input: ['100.00', true, undefined, 150], output: 'NaN-150' },
|
||||
{ input: ['100.00', true, 50, undefined], output: '50-NaN' },
|
||||
{ input: ['100.00', true, 50, 150], output: '50-150' },
|
||||
].forEach((it) => {
|
||||
const params: any[] = it.input || []
|
||||
const response = amountToString(params[0],params[1],params[2],params[3]);
|
||||
const params: any[] = it.input || [];
|
||||
const response = amountToString(params[0], params[1], params[2], params[3]);
|
||||
expect(response).toBe(it.output);
|
||||
});
|
||||
});
|
||||
})
|
||||
});
|
||||
|
@ -3,21 +3,27 @@ export const pn = (value?: number | null): string | undefined => {
|
||||
return;
|
||||
}
|
||||
|
||||
const parts = value.toString().split(".");
|
||||
const parts = value.toString().split('.');
|
||||
|
||||
parts[0] = parts[0].replace(/\B(?=(\d{3})+(?!\d))/g, ",");
|
||||
parts[0] = parts[0].replace(/\B(?=(\d{3})+(?!\d))/g, ',');
|
||||
|
||||
return parts.join(".");
|
||||
return parts.join('.');
|
||||
};
|
||||
|
||||
export const amountToString: (amount: string, has_range: boolean , min_amount: number, max_amount: number) => string =
|
||||
(amount, has_range, min_amount, max_amount) => {
|
||||
if (has_range){
|
||||
return pn(parseFloat(Number(min_amount).toPrecision(4))) +
|
||||
'-' +
|
||||
pn(parseFloat(Number(max_amount).toPrecision(4)))
|
||||
export const amountToString: (
|
||||
amount: string,
|
||||
has_range: boolean,
|
||||
min_amount: number,
|
||||
max_amount: number,
|
||||
) => string = (amount, has_range, min_amount, max_amount) => {
|
||||
if (has_range) {
|
||||
return (
|
||||
pn(parseFloat(Number(min_amount).toPrecision(4))) +
|
||||
'-' +
|
||||
pn(parseFloat(Number(max_amount).toPrecision(4)))
|
||||
);
|
||||
}
|
||||
return pn(parseFloat(Number(amount).toPrecision(4))) || ""
|
||||
}
|
||||
return pn(parseFloat(Number(amount).toPrecision(4))) || '';
|
||||
};
|
||||
|
||||
export default pn
|
||||
export default pn;
|
||||
|
@ -1,22 +1,22 @@
|
||||
/* function to save DATA as text from browser
|
||||
* @param {String} file -- file name to save to
|
||||
* @param {filename} data -- object to save
|
||||
*/
|
||||
* @param {String} file -- file name to save to
|
||||
* @param {filename} data -- object to save
|
||||
*/
|
||||
|
||||
export const saveAsJson = (filename, dataObjToWrite) => {
|
||||
const blob = new Blob([JSON.stringify(dataObjToWrite, null, 2)], { type: "text/json" });
|
||||
const link = document.createElement("a");
|
||||
const blob = new Blob([JSON.stringify(dataObjToWrite, null, 2)], { type: 'text/json' });
|
||||
const link = document.createElement('a');
|
||||
|
||||
link.download = filename;
|
||||
link.href = window.URL.createObjectURL(blob);
|
||||
link.dataset.downloadurl = ["text/json", link.download, link.href].join(":");
|
||||
link.download = filename;
|
||||
link.href = window.URL.createObjectURL(blob);
|
||||
link.dataset.downloadurl = ['text/json', link.download, link.href].join(':');
|
||||
|
||||
const evt = new MouseEvent("click", {
|
||||
view: window,
|
||||
bubbles: true,
|
||||
cancelable: true,
|
||||
});
|
||||
const evt = new MouseEvent('click', {
|
||||
view: window,
|
||||
bubbles: true,
|
||||
cancelable: true,
|
||||
});
|
||||
|
||||
link.dispatchEvent(evt);
|
||||
link.remove()
|
||||
};
|
||||
link.dispatchEvent(evt);
|
||||
link.remove();
|
||||
};
|
||||
|
@ -1,17 +1,19 @@
|
||||
// sort of cryptographically strong function to generate Base62 token client-side
|
||||
export function genBase62Token(length){
|
||||
return window.btoa(Array.from(
|
||||
window.crypto.getRandomValues(
|
||||
new Uint8Array(length * 2)))
|
||||
.map((b) => String.fromCharCode(b))
|
||||
.join("")).replace(/[+/]/g, "")
|
||||
.substring(0, length);
|
||||
export function genBase62Token(length) {
|
||||
return window
|
||||
.btoa(
|
||||
Array.from(window.crypto.getRandomValues(new Uint8Array(length * 2)))
|
||||
.map((b) => String.fromCharCode(b))
|
||||
.join(''),
|
||||
)
|
||||
.replace(/[+/]/g, '')
|
||||
.substring(0, length);
|
||||
}
|
||||
|
||||
export function tokenStrength(token) {
|
||||
const characters = token.split("").reduce(function(obj, s){
|
||||
const characters = token.split('').reduce(function (obj, s) {
|
||||
obj[s] = (obj[s] || 0) + 1;
|
||||
return obj;
|
||||
}, {});
|
||||
return {uniqueValues:Object.keys(characters).length,counts:Object.values(characters)}
|
||||
}
|
||||
return { uniqueValues: Object.keys(characters).length, counts: Object.values(characters) };
|
||||
}
|
||||
|
@ -1,18 +1,18 @@
|
||||
import { requestProvider, WeblnProvider } from "webln";
|
||||
import { requestProvider, WeblnProvider } from 'webln';
|
||||
|
||||
export const getWebln = async (): Promise<WeblnProvider> => {
|
||||
const resultPromise = new Promise<WeblnProvider>(async (resolve, reject) => {
|
||||
try {
|
||||
const webln = await requestProvider()
|
||||
const webln = await requestProvider();
|
||||
if (webln) {
|
||||
webln.enable()
|
||||
resolve(webln)
|
||||
webln.enable();
|
||||
resolve(webln);
|
||||
}
|
||||
} catch (err) {
|
||||
console.log("Coulnd't connect to Webln")
|
||||
reject()
|
||||
console.log("Coulnd't connect to Webln");
|
||||
reject();
|
||||
}
|
||||
})
|
||||
});
|
||||
|
||||
return resultPromise
|
||||
}
|
||||
return resultPromise;
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user