mirror of
https://github.com/joinmarket-webui/jam.git
synced 2026-08-20 13:28:21 +02:00
Format files
This commit is contained in:
parent
ca009e01b3
commit
fadf91ef7a
23 changed files with 1083 additions and 1287 deletions
|
|
@ -1,476 +1,399 @@
|
|||
import './App.css';
|
||||
import '@ibunker/bitcoin-react/dist/index.css';
|
||||
import './App.css'
|
||||
import '@ibunker/bitcoin-react/dist/index.css'
|
||||
import {useState,useEffect} from 'react'
|
||||
import Wallets from './components/Wallets';
|
||||
import Payment from './components/Payment';
|
||||
import CreateWallet from './components/CreateWallet';
|
||||
import Homepage from './components/homepage';
|
||||
import Maker from './components/Maker';
|
||||
import Receive from './components/Receive';
|
||||
import Wallets from './components/Wallets'
|
||||
import Payment from './components/Payment'
|
||||
import CreateWallet from './components/CreateWallet'
|
||||
import Homepage from './components/homepage'
|
||||
import Maker from './components/Maker'
|
||||
import Receive from './components/Receive'
|
||||
import DisplayWallet from './components/DisplayWallet'
|
||||
import * as rb from 'react-bootstrap';
|
||||
import * as rb from 'react-bootstrap'
|
||||
import github_logo from './github.svg'
|
||||
import twitter_logo from './twitter.svg'
|
||||
import useInterval from './components/utils'
|
||||
import { BrowserRouter as Router, Route ,Switch} from 'react-router-dom';
|
||||
import { useGlobal } from 'reactn';
|
||||
import { BrowserRouter as Router, Route ,Switch} from 'react-router-dom'
|
||||
import { useGlobal } from 'reactn'
|
||||
|
||||
function App() {
|
||||
const [walletList,setWalletList] = useState([])
|
||||
const [makerStarted, setmakerStarted] = useGlobal("makerStarted");
|
||||
const [walletName, setWalletName] = useGlobal("walletName");
|
||||
const [coinjoinInProcess, setCoinjoinInProcess] = useGlobal("coinjoinInProcess");
|
||||
const [, setCurrentStatusMessage] = useGlobal("currentStatusMessage");
|
||||
const [walletList, setWalletList] = useState([])
|
||||
const [makerStarted, setmakerStarted] = useGlobal('makerStarted')
|
||||
const [walletName, setWalletName] = useGlobal('walletName')
|
||||
const [coinjoinInProcess, setCoinjoinInProcess] = useGlobal('coinjoinInProcess')
|
||||
const [, setCurrentStatusMessage] = useGlobal('currentStatusMessage')
|
||||
|
||||
const listWallets = async () =>{
|
||||
const res = await fetch('/api/v1/wallet/all');
|
||||
const data = await res.json();
|
||||
const walletList = data.wallets;
|
||||
return walletList;
|
||||
const res = await fetch('/api/v1/wallet/all')
|
||||
const data = await res.json()
|
||||
return data.wallets
|
||||
}
|
||||
|
||||
const resetWalletSessionStorage = async () =>{
|
||||
sessionStorage.clear();
|
||||
setWalletName("No wallet loaded");
|
||||
setmakerStarted(false);
|
||||
setCoinjoinInProcess(false);
|
||||
sessionStorage.clear()
|
||||
setWalletName('No wallet loaded')
|
||||
setmakerStarted(false)
|
||||
setCoinjoinInProcess(false)
|
||||
}
|
||||
|
||||
const getCurrentStatusMessage = () =>
|
||||
`Wallet: ${walletName}, YG ${makerStarted ? 'started' : 'not running'}, Coinjoin in process: ${coinjoinInProcess}`;
|
||||
`Wallet: ${walletName}, YG ${makerStarted ? 'started' : 'not running'}, Coinjoin in process: ${coinjoinInProcess}`
|
||||
|
||||
useInterval(() => {
|
||||
const sessionClear = async () =>{
|
||||
const sessionClear = async () => {
|
||||
try {
|
||||
const res = await fetch('/api/v1/session');
|
||||
const { session, maker_running, wallet_name, coinjoin_in_process } = await res.json();
|
||||
const res = await fetch('/api/v1/session')
|
||||
const { session, maker_running, wallet_name, coinjoin_in_process } = await res.json()
|
||||
|
||||
if (session === false) {
|
||||
console.log("no wallet in backend");
|
||||
console.log('no wallet in backend')
|
||||
// This status requires us to clear, especially
|
||||
// the auth state, so we just reset everything:
|
||||
return resetWalletSessionStorage();
|
||||
return resetWalletSessionStorage()
|
||||
}
|
||||
|
||||
setmakerStarted(maker_running);
|
||||
setWalletName(wallet_name);
|
||||
setCoinjoinInProcess(coinjoin_in_process);
|
||||
setCurrentStatusMessage(getCurrentStatusMessage());
|
||||
setmakerStarted(maker_running)
|
||||
setWalletName(wallet_name)
|
||||
setCoinjoinInProcess(coinjoin_in_process)
|
||||
setCurrentStatusMessage(getCurrentStatusMessage())
|
||||
} catch(e) {
|
||||
console.error(e);
|
||||
alert("Lost connection to backend! Please restart the backend server.");
|
||||
sessionStorage.clear();
|
||||
console.error(e)
|
||||
alert('Lost connection to backend! Please restart the backend server.')
|
||||
sessionStorage.clear()
|
||||
}
|
||||
}
|
||||
sessionClear();
|
||||
sessionClear()
|
||||
}, 8*1000)
|
||||
|
||||
}, 8*1000);
|
||||
|
||||
useEffect(()=>{
|
||||
|
||||
const getWallets = async()=>{
|
||||
const wallets = await listWallets();
|
||||
setWalletList(wallets);
|
||||
useEffect(() => {
|
||||
const getWallets = async () => {
|
||||
const wallets = await listWallets()
|
||||
setWalletList(wallets)
|
||||
}
|
||||
|
||||
getWallets();
|
||||
|
||||
},[])
|
||||
|
||||
getWallets()
|
||||
}, [])
|
||||
|
||||
const unlockWallet = async (name) => {
|
||||
const authData = JSON.parse(sessionStorage.getItem('auth'));
|
||||
const authData = JSON.parse(sessionStorage.getItem('auth'))
|
||||
|
||||
if (authData && authData.login) {
|
||||
return alert(authData.name === name
|
||||
// unlocking same wallet
|
||||
? `${name} is already unlocked`
|
||||
// unlocking another wallet while one is already unlocked
|
||||
: `${authData.name} is currently in use, please lock it first`);
|
||||
: `${authData.name} is currently in use, please lock it first`)
|
||||
} else {
|
||||
try {
|
||||
const password = prompt(`Enter the passphrase for ${name}`);
|
||||
const password = prompt(`Enter the passphrase for ${name}`)
|
||||
const res = await fetch(`/api/v1/wallet/${name}/unlock`,{
|
||||
method: 'POST',
|
||||
headers: { 'Content-type': 'application/json' },
|
||||
body: JSON.stringify({ password }),
|
||||
})
|
||||
const data = await res.json();
|
||||
const data = await res.json()
|
||||
console.log(data)
|
||||
const token = data.token;
|
||||
sessionStorage.setItem('auth', JSON.stringify({ login: true, token, name }));
|
||||
const token = data.token
|
||||
sessionStorage.setItem('auth', JSON.stringify({ login: true, token, name }))
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
alert('Something went wrong, please try again!');
|
||||
console.error(e)
|
||||
alert('Something went wrong, please try again!')
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const lockWallet = async(name)=>{
|
||||
let authData =JSON.parse(sessionStorage.getItem('auth'));
|
||||
if(!authData || authData.login===false || authData.name!==name){
|
||||
alert("Please unlock "+name+" first")
|
||||
return;
|
||||
}
|
||||
const lockWallet = async (name) => {
|
||||
const authData = JSON.parse(sessionStorage.getItem('auth'))
|
||||
if (!authData || !authData.login || authData.name !== name) {
|
||||
return alert(`Please unlock ${name} first`)
|
||||
}
|
||||
|
||||
try{
|
||||
let token = "Bearer "+authData.token
|
||||
const res = await fetch(`/api/v1/wallet/${name}/lock`,{
|
||||
method:"GET",
|
||||
headers:{
|
||||
'Authorization':token
|
||||
try {
|
||||
const res = await fetch(`/api/v1/wallet/${name}/lock`, {
|
||||
headers: {
|
||||
'Authorization': `Bearer ${authData.token}`
|
||||
}
|
||||
});
|
||||
sessionStorage.setItem('auth',JSON.stringify({
|
||||
login:false,
|
||||
token:'',
|
||||
name:''
|
||||
|
||||
})
|
||||
sessionStorage.setItem('auth', JSON.stringify({
|
||||
login: false,
|
||||
token: '',
|
||||
name: ''
|
||||
}))
|
||||
const data = await res.json();
|
||||
console.log(data);
|
||||
alert("locked wallet succesfully")
|
||||
}
|
||||
catch(e){
|
||||
alert("Error while locking.")
|
||||
const data = await res.json()
|
||||
console.log(data)
|
||||
alert('Wallet locked succesfully')
|
||||
} catch (e) {
|
||||
console.error(e)
|
||||
alert('Error while locking.')
|
||||
}
|
||||
}
|
||||
|
||||
const listWalletInfo = async (name) => {
|
||||
const authData = JSON.parse(sessionStorage.getItem('auth'))
|
||||
const res = await fetch(`/api/v1/wallet/${name}/display`, {
|
||||
headers:{
|
||||
'Authorization': `Bearer ${authData.token}`
|
||||
}
|
||||
})
|
||||
const { walletinfo } = await res.json()
|
||||
const balance = walletinfo.total_balance
|
||||
const mix_depths = walletinfo.accounts
|
||||
const wallet_info = { balance }
|
||||
wallet_info[mix_depths[0].account] = mix_depths[0].account_balance
|
||||
wallet_info[mix_depths[1].account] = mix_depths[1].account_balance
|
||||
wallet_info[mix_depths[2].account] = mix_depths[2].account_balance
|
||||
wallet_info[mix_depths[3].account] = mix_depths[3].account_balance
|
||||
wallet_info[mix_depths[4].account] = mix_depths[4].account_balance
|
||||
|
||||
return [walletinfo]
|
||||
}
|
||||
|
||||
const displayWallet = async (name) => {
|
||||
const authData = JSON.parse(sessionStorage.getItem('auth'))
|
||||
if (!authData || !authData.login || authData.name !== name) {
|
||||
return alert(`Please unlock ${name} first`)
|
||||
}
|
||||
|
||||
const listWalletInfo = async(name)=>{
|
||||
let authData =JSON.parse(sessionStorage.getItem('auth'));
|
||||
let token = "Bearer "+authData.token
|
||||
const res = await fetch(`/api/v1/wallet/${name}/display`,{
|
||||
method:"GET",
|
||||
headers:{
|
||||
'Authorization':token
|
||||
}
|
||||
});
|
||||
const { walletinfo } = await res.json();
|
||||
const balance = walletinfo.total_balance;
|
||||
const mix_depths = walletinfo.accounts;
|
||||
const wallet_info = { balance }
|
||||
wallet_info[mix_depths[0].account] = mix_depths[0].account_balance
|
||||
wallet_info[mix_depths[1].account] = mix_depths[1].account_balance
|
||||
wallet_info[mix_depths[2].account] = mix_depths[2].account_balance
|
||||
wallet_info[mix_depths[3].account] = mix_depths[3].account_balance
|
||||
wallet_info[mix_depths[4].account] = mix_depths[4].account_balance
|
||||
const res = await fetch(`/api/v1/wallet/${name}/display`, {
|
||||
headers:{
|
||||
'Authorization': `Bearer ${authData.token}`
|
||||
}
|
||||
})
|
||||
|
||||
return [walletinfo];
|
||||
const { walletinfo } = await res.json()
|
||||
const balance = walletinfo.total_balance
|
||||
const mix_depths = walletinfo.accounts
|
||||
const wallet_info={}
|
||||
wallet_info['balance'] = balance
|
||||
wallet_info[mix_depths[0].account] = mix_depths[0].account_balance
|
||||
wallet_info[mix_depths[1].account] = mix_depths[1].account_balance
|
||||
wallet_info[mix_depths[2].account] = mix_depths[2].account_balance
|
||||
wallet_info[mix_depths[3].account] = mix_depths[3].account_balance
|
||||
wallet_info[mix_depths[4].account] = mix_depths[4].account_balance
|
||||
console.log(wallet_info)
|
||||
return wallet_info
|
||||
}
|
||||
|
||||
const createWallet = async (walletname, password) => {
|
||||
const authData = JSON.parse(sessionStorage.getItem('auth'))
|
||||
if (!authData || !authData.login) {
|
||||
try {
|
||||
const wallettype = 'sw'
|
||||
const res = await fetch(`/api/v1/wallet/create`, {
|
||||
method: 'POST',
|
||||
headers: { 'Content-type': 'application/json', },
|
||||
body: JSON.stringify({
|
||||
password,
|
||||
walletname,
|
||||
wallettype
|
||||
}),
|
||||
})
|
||||
|
||||
const { seedphrase, token } = await res.json()
|
||||
alert('Wallet created succesfully')
|
||||
// TODO: figure out a safer way to show the seedphrase
|
||||
alert(seedphrase)
|
||||
sessionStorage.setItem('auth', JSON.stringify({ login: true, token, name: walletname }))
|
||||
} catch (e) {
|
||||
console.error(e)
|
||||
//some other error occurs where wallet is not created
|
||||
alert('Unexpected error! Please try again')
|
||||
}
|
||||
} else {
|
||||
alert(`${authData.name} is in use! Please lock it first.`)
|
||||
}
|
||||
}
|
||||
|
||||
const displayWallet = async(name)=>{
|
||||
|
||||
let authData =JSON.parse(sessionStorage.getItem('auth'));
|
||||
if(authData.login===false || authData.name!==name){
|
||||
alert("Please unlock "+name+" first")
|
||||
return;
|
||||
const makePayment = async (name, mixdepth, amount_sats,destination) => {
|
||||
const authData = JSON.parse(sessionStorage.getItem('auth'))
|
||||
if (authData && authData.login === true){
|
||||
try {
|
||||
const res = await fetch(`/api/v1/wallet/${name}/taker/direct-send`, {
|
||||
method:'POST',
|
||||
headers: {
|
||||
'Content-type': 'application/json',
|
||||
'Authorization': `Bearer ${authData.token}`
|
||||
},
|
||||
body: JSON.stringify({
|
||||
mixdepth,
|
||||
amount_sats,
|
||||
destination
|
||||
}),
|
||||
})
|
||||
const data = await res.json()
|
||||
console.log(data)
|
||||
alert('Payment Succesful!')
|
||||
} catch(e) {
|
||||
alert('Error while processing payment!')
|
||||
}
|
||||
let token = "Bearer "+authData.token
|
||||
const res = await fetch(`/api/v1/wallet/${name}/display`,{
|
||||
method:"GET",
|
||||
headers:{
|
||||
'Authorization':token
|
||||
}
|
||||
});
|
||||
const { walletinfo } = await res.json();
|
||||
const balance = walletinfo.total_balance;
|
||||
const mix_depths = walletinfo.accounts;
|
||||
const wallet_info={}
|
||||
wallet_info['balance'] = balance;
|
||||
wallet_info[mix_depths[0].account] = mix_depths[0].account_balance
|
||||
wallet_info[mix_depths[1].account] = mix_depths[1].account_balance
|
||||
wallet_info[mix_depths[2].account] = mix_depths[2].account_balance
|
||||
wallet_info[mix_depths[3].account] = mix_depths[3].account_balance
|
||||
wallet_info[mix_depths[4].account] = mix_depths[4].account_balance
|
||||
console.log(wallet_info)
|
||||
return wallet_info;
|
||||
} else {
|
||||
alert('please unlock wallet first')
|
||||
}
|
||||
}
|
||||
|
||||
const createWallet = async(name,password)=>{
|
||||
const authData = JSON.parse(sessionStorage.getItem('auth'));
|
||||
if (!authData || !authData.login) {
|
||||
try {
|
||||
const res = await fetch(`/api/v1/wallet/create`,{
|
||||
method:'POST',
|
||||
headers: { 'Content-type': 'application/json', },
|
||||
body: JSON.stringify({ password, "walletname": name, "wallettype":"sw" }),
|
||||
})
|
||||
|
||||
const { seedphrase, token } = await res.json();
|
||||
alert("Wallet created succesfully")
|
||||
|
||||
//figure out a safer way to show the seedphrase
|
||||
alert(seedphrase)
|
||||
sessionStorage.setItem('auth', JSON.stringify({ login: true, token, name }))
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
//some other error occurs where wallet is not created
|
||||
alert('Unexpected error! Please try again')
|
||||
}
|
||||
} else{
|
||||
alert(`${authData.name} is in use! Please lock it first.`)
|
||||
//route for frontend
|
||||
const doCoinjoin = async (mixdepth, amount, counterparties, destination) => {
|
||||
try {
|
||||
const authData = JSON.parse(sessionStorage.getItem('auth'))
|
||||
if (!authData || !authData.login || authData.name === '') {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
const makePayment = async(name,mixdepth,amountSats,destination)=>{
|
||||
let authData =JSON.parse(sessionStorage.getItem('auth'));
|
||||
if(authData!=null && authData.login===true){
|
||||
try{
|
||||
let token = "Bearer "+authData.token
|
||||
const res = await fetch(`/api/v1/wallet/${name}/taker/direct-send`,{
|
||||
method:'POST',
|
||||
headers: {
|
||||
'Content-type': 'application/json',
|
||||
'Authorization':token
|
||||
},
|
||||
body: JSON.stringify({
|
||||
"mixdepth": mixdepth,
|
||||
"amount_sats": amountSats,
|
||||
"destination": destination
|
||||
}
|
||||
|
||||
),
|
||||
})
|
||||
const data = await res.json();
|
||||
console.log(data);
|
||||
alert("Payment Succesful!")
|
||||
}
|
||||
catch(e){
|
||||
alert("Error while processing payment!")
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
else{
|
||||
alert("please unlock wallet first")
|
||||
}
|
||||
}
|
||||
|
||||
//route for frontend
|
||||
|
||||
const doCoinjoin = async(mixdepth,amount,counterparties,destination)=>{
|
||||
try{
|
||||
console.log("hellooo")
|
||||
let authData = JSON.parse(sessionStorage.getItem('auth'));
|
||||
|
||||
if(!authData|| authData.login===false || authData.name===''){
|
||||
return;
|
||||
}
|
||||
|
||||
let token = "Bearer "+authData.token;
|
||||
let name = authData.name;
|
||||
const res = await fetch(`/api/v1/wallet/${name}/taker/coinjoin`,{
|
||||
method:'POST',
|
||||
headers: {
|
||||
'Content-type': 'application/json',
|
||||
'Authorization':token
|
||||
},
|
||||
body: JSON.stringify({
|
||||
|
||||
"mixdepth": mixdepth,
|
||||
"amount": amount,
|
||||
"counterparties": counterparties,
|
||||
"destination":destination
|
||||
}
|
||||
|
||||
),
|
||||
})
|
||||
const data = await res.json();
|
||||
console.log(data);
|
||||
alert("Coinjoin in Progress!")
|
||||
|
||||
}
|
||||
catch(e){
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
const startMakerService = async(txfee,cjfee_a,cjfee_r,ordertype,minsize)=>{
|
||||
let authData =JSON.parse(sessionStorage.getItem('auth'));
|
||||
|
||||
if(!authData|| authData.login===false || authData.name===''){
|
||||
alert("Please unlock a wallet first")
|
||||
return;
|
||||
}
|
||||
let name = authData.name
|
||||
try{
|
||||
let token = "Bearer "+authData.token
|
||||
const res = await fetch(`/api/v1/wallet/${name}/maker/start`,{
|
||||
method:"POST",
|
||||
headers:{
|
||||
'Authorization':token
|
||||
const res = await fetch(`/api/v1/wallet/${authData.name}/taker/coinjoin`, {
|
||||
method:'POST',
|
||||
headers: {
|
||||
'Content-type': 'application/json',
|
||||
'Authorization': `Bearer ${authData.token}`
|
||||
},
|
||||
body: JSON.stringify({
|
||||
"txfee":txfee,
|
||||
"cjfee_a":cjfee_a,
|
||||
"cjfee_r":cjfee_r,
|
||||
"ordertype":ordertype,
|
||||
"minsize":minsize
|
||||
}
|
||||
|
||||
),
|
||||
});
|
||||
|
||||
const data = await res.json();
|
||||
console.log(data);
|
||||
}
|
||||
|
||||
catch(e){
|
||||
alert("Error while starting service!")
|
||||
}
|
||||
mixdepth,
|
||||
amount,
|
||||
counterparties,
|
||||
destination
|
||||
}),
|
||||
})
|
||||
const data = await res.json()
|
||||
console.log(data)
|
||||
alert('Coinjoin in Progress!')
|
||||
} catch (e) {
|
||||
console.error(e)
|
||||
}
|
||||
}
|
||||
|
||||
const startMakerService = async (txfee, cjfee_a, cjfee_r, ordertype, minsize) => {
|
||||
const authData =JSON.parse(sessionStorage.getItem('auth'))
|
||||
if (!authData || !authData.login || authData.name === ''){
|
||||
return alert('Please unlock a wallet first')
|
||||
}
|
||||
|
||||
const stopMakerService= async()=>{
|
||||
let authData =JSON.parse(sessionStorage.getItem('auth'));
|
||||
if(authData===null ||authData.login===false || authData.name===''){
|
||||
alert('Wallet needs to be unlocked')
|
||||
return;
|
||||
}
|
||||
try{
|
||||
let name = authData.name
|
||||
let token = "Bearer "+authData.token
|
||||
const res = await fetch(`/api/v1/wallet/${name}/maker/stop`,{
|
||||
method:"GET",
|
||||
headers:{
|
||||
'Authorization':token
|
||||
},
|
||||
try {
|
||||
const res = await fetch(`/api/v1/wallet/${authData.name}/maker/start`, {
|
||||
method: 'POST',
|
||||
headers:{
|
||||
'Authorization': `Bearer ${authData.token}`
|
||||
},
|
||||
body: JSON.stringify({
|
||||
txfee,
|
||||
cjfee_a,
|
||||
cjfee_r,
|
||||
ordertype,
|
||||
minsize
|
||||
})
|
||||
const data = await res.json();
|
||||
console.log(data);
|
||||
alert("Maker service stopped")
|
||||
}
|
||||
})
|
||||
|
||||
catch(e){
|
||||
alert("Error while stopping service!")
|
||||
}
|
||||
const data = await res.json()
|
||||
console.log(data)
|
||||
} catch (e) {
|
||||
console.error(e)
|
||||
alert('Error while starting service!')
|
||||
}
|
||||
}
|
||||
|
||||
const stopMakerService = async () => {
|
||||
const authData = JSON.parse(sessionStorage.getItem('auth'))
|
||||
if (!authData || !authData.login || authData.name === '') {
|
||||
return alert('Wallet needs to be unlocked')
|
||||
}
|
||||
|
||||
const getUTXOs = async()=>{
|
||||
try{
|
||||
let authData =JSON.parse(sessionStorage.getItem('auth'));
|
||||
let token = "Bearer "+authData.token
|
||||
if(!authData|| authData.login===false || authData.name===''){
|
||||
return;
|
||||
}
|
||||
let name = authData.name;
|
||||
const res = await fetch(`/api/v1/wallet/${name}/utxos`, {
|
||||
headers: { 'Authorization':token }
|
||||
});
|
||||
const { utxos } = await res.json();
|
||||
return utxos;
|
||||
} catch(e){
|
||||
return console.error(e);
|
||||
}
|
||||
try {
|
||||
const res = await fetch(`/api/v1/wallet/${authData.name}/maker/stop`, {
|
||||
headers:{
|
||||
'Authorization': `Bearer ${authData.token}`
|
||||
},
|
||||
})
|
||||
const data = await res.json()
|
||||
console.log(data)
|
||||
alert('Maker service stopped')
|
||||
} catch (e) {
|
||||
console.error(e)
|
||||
alert('Error while stopping service!')
|
||||
}
|
||||
}
|
||||
|
||||
const getUTXOs = async () => {
|
||||
try {
|
||||
const authData = JSON.parse(sessionStorage.getItem('auth'))
|
||||
if (!authData || !authData.login || authData.name === '') {
|
||||
return
|
||||
}
|
||||
const res = await fetch(`/api/v1/wallet/${authData.name}/utxos`, {
|
||||
headers: {
|
||||
'Authorization': `Bearer ${authData.token}`
|
||||
}
|
||||
})
|
||||
const { utxos } = await res.json()
|
||||
return utxos
|
||||
} catch (e) {
|
||||
console.error(e)
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<Router>
|
||||
<div className="App">
|
||||
|
||||
<rb.Navbar sticky="top" collapseOnSelect expand="lg" bg="dark" variant="dark">
|
||||
|
||||
<rb.Container>
|
||||
<rb.Navbar.Brand href='/'>Joinmarket</rb.Navbar.Brand>
|
||||
<rb.Navbar.Toggle aria-controls="responsive-rb.Navbar-rb.Nav" />
|
||||
<rb.Navbar.Collapse id="responsive-rb.Navbar-rb.Nav">
|
||||
<rb.Nav className="me-auto">
|
||||
<rb.Nav.Link href="https://github.com/JoinMarket-Org/joinmarket-clientserver/tree/master/docs">Docs</rb.Nav.Link>
|
||||
<rb.Nav.Link href="https://github.com/JoinMarket-Org/joinmarket-clientserver#wallet-features">Features</rb.Nav.Link>
|
||||
<rb.Nav.Link href="https://github.com/JoinMarket-Org/joinmarket-clientserver#joinmarket-clientserver">About</rb.Nav.Link>
|
||||
</rb.Nav>
|
||||
<rb.Nav>
|
||||
<rb.Navbar.Brand href="https://github.com/JoinMarket-Org/joinmarket-clientserver">
|
||||
<img
|
||||
src={github_logo}
|
||||
width="50"
|
||||
height="50"
|
||||
className="github"
|
||||
alt="github logo"
|
||||
/>
|
||||
</rb.Navbar.Brand>
|
||||
<rb.Navbar.Brand href="https://twitter.com/joinmarket">
|
||||
<img
|
||||
src={twitter_logo}
|
||||
width="50"
|
||||
height="50"
|
||||
className="twitter"
|
||||
alt="twitter logo"
|
||||
/>
|
||||
</rb.Navbar.Brand>
|
||||
</rb.Nav>
|
||||
</rb.Navbar.Collapse>
|
||||
</rb.Container>
|
||||
<rb.Container>
|
||||
<rb.Navbar.Text>{getCurrentStatusMessage()}</rb.Navbar.Text>
|
||||
</rb.Container>
|
||||
</rb.Navbar>
|
||||
|
||||
<div className="App">
|
||||
<rb.Navbar sticky="top" collapseOnSelect expand="lg" bg="dark" variant="dark">
|
||||
<rb.Container>
|
||||
<rb.Navbar.Brand href='/'>Joinmarket</rb.Navbar.Brand>
|
||||
<rb.Navbar.Toggle aria-controls="responsive-rb.Navbar-rb.Nav" />
|
||||
<rb.Navbar.Collapse id="responsive-rb.Navbar-rb.Nav">
|
||||
<rb.Nav className="me-auto">
|
||||
<rb.Nav.Link href="https://github.com/JoinMarket-Org/joinmarket-clientserver/tree/master/docs">Docs</rb.Nav.Link>
|
||||
<rb.Nav.Link href="https://github.com/JoinMarket-Org/joinmarket-clientserver#wallet-features">Features</rb.Nav.Link>
|
||||
<rb.Nav.Link href="https://github.com/JoinMarket-Org/joinmarket-clientserver#joinmarket-clientserver">About</rb.Nav.Link>
|
||||
</rb.Nav>
|
||||
<rb.Nav>
|
||||
<rb.Navbar.Brand href="https://github.com/JoinMarket-Org/joinmarket-clientserver">
|
||||
<img
|
||||
src={github_logo}
|
||||
width="50"
|
||||
height="50"
|
||||
className="github"
|
||||
alt="github logo"
|
||||
/>
|
||||
</rb.Navbar.Brand>
|
||||
<rb.Navbar.Brand href="https://twitter.com/joinmarket">
|
||||
<img
|
||||
src={twitter_logo}
|
||||
width="50"
|
||||
height="50"
|
||||
className="twitter"
|
||||
alt="twitter logo"
|
||||
/>
|
||||
</rb.Navbar.Brand>
|
||||
</rb.Nav>
|
||||
</rb.Navbar.Collapse>
|
||||
</rb.Container>
|
||||
<rb.Container>
|
||||
<rb.Navbar.Text>
|
||||
{getCurrentStatusMessage()}
|
||||
</rb.Navbar.Text>
|
||||
</rb.Container>
|
||||
</rb.Navbar>
|
||||
<p></p>
|
||||
<Switch>
|
||||
|
||||
<Route
|
||||
path='/'
|
||||
exact
|
||||
render={(props) => (
|
||||
<>
|
||||
<Homepage></Homepage>
|
||||
</>
|
||||
)}
|
||||
/>
|
||||
|
||||
<Route
|
||||
path='/showWallets'
|
||||
exact
|
||||
render={(props) => (
|
||||
<>
|
||||
<Wallets walletList = {walletList} onUnlock = {unlockWallet} onLock = {lockWallet} onDisplay = {displayWallet}></Wallets>
|
||||
</>
|
||||
)}
|
||||
/>
|
||||
|
||||
|
||||
<Route path='/payment' exact render={(props) => (
|
||||
<>
|
||||
<Payment onPayment = {makePayment} onCoinjoin = {doCoinjoin}></Payment>
|
||||
</>
|
||||
)}
|
||||
/>
|
||||
|
||||
<Route path='/create' exact render={(props) => (
|
||||
<>
|
||||
<CreateWallet onCreate={createWallet}></CreateWallet>
|
||||
</>
|
||||
)}
|
||||
/>
|
||||
|
||||
<Route path='/maker' exact render={(props) => (
|
||||
<>
|
||||
<Maker onStart = {startMakerService} onStop = {stopMakerService}></Maker>
|
||||
</>
|
||||
)}
|
||||
/>
|
||||
<Route path='/receive' exact render={(props) => (
|
||||
<>
|
||||
<Receive></Receive>
|
||||
</>
|
||||
)}
|
||||
/>
|
||||
<Route path='/display' exact render={(props) => (
|
||||
<>
|
||||
<DisplayWallet listWalletInfo = {listWalletInfo} onSend = {makePayment} listUTXOs={getUTXOs}></DisplayWallet>
|
||||
</>
|
||||
)}
|
||||
/>
|
||||
|
||||
</Switch>{" "}
|
||||
|
||||
</div>
|
||||
<Route path='/' exact render={props => (
|
||||
<Homepage />
|
||||
)} />
|
||||
<Route path='/showWallets' exact render={props => (
|
||||
<Wallets walletList={walletList} currentWallet={walletName} onUnlock={unlockWallet} onLock={lockWallet} onDisplay={displayWallet} />
|
||||
)} />
|
||||
<Route path='/payment' exact render={props => (
|
||||
<Payment onPayment={makePayment} onCoinjoin={doCoinjoin} />
|
||||
)} />
|
||||
<Route path='/create' exact render={props => (
|
||||
<CreateWallet onCreate={createWallet} />
|
||||
)} />
|
||||
<Route path='/maker' exact render={props => (
|
||||
<Maker onStart={startMakerService} onStop={stopMakerService} />
|
||||
)} />
|
||||
<Route path='/receive' exact render={props => (
|
||||
<Receive />
|
||||
)} />
|
||||
<Route path='/display' exact render={props => (
|
||||
<DisplayWallet listWalletInfo={listWalletInfo} onSend={makePayment} listUTXOs={getUTXOs} />
|
||||
)} />
|
||||
</Switch>
|
||||
</div>
|
||||
</Router>
|
||||
|
||||
|
||||
);
|
||||
)
|
||||
}
|
||||
|
||||
export default App;
|
||||
export default App
|
||||
|
|
|
|||
|
|
@ -1,8 +0,0 @@
|
|||
import { render, screen } from '@testing-library/react';
|
||||
import App from './App';
|
||||
|
||||
test('renders learn react link', () => {
|
||||
render(<App />);
|
||||
const linkElement = screen.getByText(/learn react/i);
|
||||
expect(linkElement).toBeInTheDocument();
|
||||
});
|
||||
|
|
@ -1,11 +1,8 @@
|
|||
import React from "react";
|
||||
import "./button.css";
|
||||
|
||||
export const Button = ({name,children, type, onClick, buttonStyle, buttonSize}) => {
|
||||
return (
|
||||
<button onClick = {()=>onClick(name)} type = {type}>
|
||||
{children}
|
||||
</button>
|
||||
)
|
||||
}
|
||||
import React from 'react'
|
||||
import './button.css'
|
||||
|
||||
export const Button = ({ name, children, type, onClick }) => (
|
||||
<button onClick={() => onClick(name)} type={type}>
|
||||
{children}
|
||||
</button>
|
||||
)
|
||||
|
|
|
|||
|
|
@ -3,82 +3,60 @@ import { useState } from 'react'
|
|||
import './createWallet.css'
|
||||
import * as rb from 'react-bootstrap'
|
||||
|
||||
const CreateWallet = ({onCreate}) => {
|
||||
const CreateWallet = ({ onCreate }) => {
|
||||
const [wallet, setWallet] = useState('')
|
||||
const [password, setPassword] = useState('')
|
||||
|
||||
const [wallet,setWallet] = useState('')
|
||||
const [password,setPassword]=useState('')
|
||||
const onSubmit = (e) => {
|
||||
e.preventDefault()
|
||||
|
||||
const onSubmit = (e) => {
|
||||
e.preventDefault()
|
||||
|
||||
if (!wallet || !password) {
|
||||
alert('Please add details')
|
||||
return;
|
||||
}
|
||||
|
||||
onCreate(wallet,password)
|
||||
setWallet('')
|
||||
setPassword('')
|
||||
}
|
||||
return (
|
||||
|
||||
<div>
|
||||
|
||||
<br></br>
|
||||
<div className = "heading">
|
||||
Create Wallet
|
||||
</div>
|
||||
if (!wallet || !password) {
|
||||
alert('Please add details')
|
||||
return;
|
||||
}
|
||||
|
||||
<form method="POST" onSubmit={onSubmit}>
|
||||
<rb.Container className = "center">
|
||||
<rb.Container fluid = "false" className = "form1">
|
||||
<rb.Row>
|
||||
|
||||
<rb.Col className="label">
|
||||
Wallet Name
|
||||
</rb.Col>
|
||||
<rb.Col>
|
||||
<input style = {{width: "220px"}} classname = "field-border" type="text" name="wallet" value = {wallet} onChange={(e) => setWallet(e.target.value)}/>
|
||||
</rb.Col>
|
||||
|
||||
</rb.Row>
|
||||
<rb.Row className = "field">
|
||||
|
||||
<rb.Col className="label">
|
||||
Password
|
||||
</rb.Col>
|
||||
<rb.Col>
|
||||
<input type="password" style = {{width: "220px"}} name="password" value = {password} onChange={(e) => setPassword(e.target.value)} />
|
||||
</rb.Col>
|
||||
|
||||
</rb.Row>
|
||||
<rb.Row className = "btn-field">
|
||||
<button className="btncr" type="submit" value="Submit" ><span>Submit</span></button>
|
||||
</rb.Row>
|
||||
</rb.Container>
|
||||
</rb.Container>
|
||||
</form>
|
||||
|
||||
{/* <form method="POST" onSubmit={onSubmit}>
|
||||
|
||||
|
||||
<label>
|
||||
Wallet Name
|
||||
<input className = "test" type="text" name="wallet" value = {wallet} onChange={(e) => setWallet(e.target.value)}/>
|
||||
</label>
|
||||
<p></p>
|
||||
<label>
|
||||
Password
|
||||
<input type="password" name="password" value = {password} onChange={(e) => setPassword(e.target.value)} />
|
||||
</label>
|
||||
<p></p>
|
||||
|
||||
<input className = "submit" type="submit" value="Submit" />
|
||||
|
||||
onCreate(wallet, password)
|
||||
setWallet('')
|
||||
setPassword('')
|
||||
}
|
||||
|
||||
</form> */}
|
||||
</div>
|
||||
)
|
||||
return (
|
||||
<div>
|
||||
<div className="heading">
|
||||
Create Wallet
|
||||
</div>
|
||||
|
||||
<form method="POST" onSubmit={onSubmit}>
|
||||
<rb.Container className="center">
|
||||
<rb.Container fluid="false" className="form1">
|
||||
<rb.Row>
|
||||
|
||||
<rb.Col className="label">
|
||||
Wallet Name
|
||||
</rb.Col>
|
||||
<rb.Col>
|
||||
<input style={{ width: "220px" }} classname="field-border" type="text" name="wallet" value={wallet} onChange={(e) => setWallet(e.target.value)} />
|
||||
</rb.Col>
|
||||
|
||||
</rb.Row>
|
||||
<rb.Row className="field">
|
||||
|
||||
<rb.Col className="label">
|
||||
Password
|
||||
</rb.Col>
|
||||
<rb.Col>
|
||||
<input type="password" style={{ width: "220px" }} name="password" value={password} onChange={(e) => setPassword(e.target.value)} />
|
||||
</rb.Col>
|
||||
|
||||
</rb.Row>
|
||||
<rb.Row className="btn-field">
|
||||
<button className="btncr" type="submit" value="Submit"><span>Submit</span></button>
|
||||
</rb.Row>
|
||||
</rb.Container>
|
||||
</rb.Container>
|
||||
</form>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default CreateWallet
|
||||
|
|
|
|||
|
|
@ -1,110 +1,99 @@
|
|||
import React from 'react'
|
||||
import './displayMixdepth.css'
|
||||
import { Link } from 'react-router-dom';
|
||||
import { Link } from 'react-router-dom'
|
||||
import * as rb from 'react-bootstrap'
|
||||
|
||||
const DisplayMixdepth = ({walletInfo}) => {
|
||||
const DisplayMixdepth = ({ walletInfo }) => {
|
||||
const accounts = []
|
||||
|
||||
const accounts = []
|
||||
for (const account_info of walletInfo.accounts) {
|
||||
accounts.push(account_info)
|
||||
}
|
||||
|
||||
for (const account_info of walletInfo.accounts){
|
||||
accounts.push(account_info)
|
||||
}
|
||||
|
||||
return (
|
||||
<div>
|
||||
Total Balance: {walletInfo.total_balance} BTC
|
||||
<p></p>
|
||||
<rb.Button href="/maker">Maker Service</rb.Button>
|
||||
<p></p>
|
||||
{accounts.map((account, index) => (
|
||||
|
||||
<div key = {index}>
|
||||
|
||||
<rb.Accordion>
|
||||
<rb.Accordion.Item eventKey={index}>
|
||||
<rb.Accordion.Header className = "head">
|
||||
<div className = "links">
|
||||
|
||||
<rb.Container>
|
||||
<rb.Row>
|
||||
<rb.Col>
|
||||
Account {accounts[index].account}
|
||||
|
||||
</rb.Col>
|
||||
<rb.Col>
|
||||
Balance: {accounts[index].account_balance} BTC
|
||||
|
||||
</rb.Col>
|
||||
<rb.Col>
|
||||
|
||||
<Link to={{pathname:"/payment", state: { account_no: accounts[index].account }}} className="btn btn-primary">Send </Link>{' '}
|
||||
</rb.Col>
|
||||
<rb.Col>
|
||||
<Link to={{pathname:"/receive", state: { account_no: accounts[index].account }}} className="btn btn-primary">Receive </Link>
|
||||
</rb.Col>
|
||||
</rb.Row>
|
||||
</rb.Container>
|
||||
|
||||
|
||||
</div>
|
||||
</rb.Accordion.Header>
|
||||
<rb.Accordion.Body>
|
||||
<rb.Accordion>
|
||||
<rb.Accordion.Item eventKey="0">
|
||||
|
||||
<rb.Accordion.Header>External Addresses Balance: {accounts[index].branches[0].balance} BTC </rb.Accordion.Header>
|
||||
<div className = "xpub">
|
||||
Extended Pubkey : {accounts[index].branches[0].branch.split("\t").pop()}
|
||||
</div>
|
||||
<rb.Accordion.Body>
|
||||
{accounts[index].branches[0].entries.map((user, i) => (
|
||||
<div key={i}>
|
||||
<rb.Accordion>
|
||||
<rb.Accordion.Item eventKey="0">
|
||||
<div className = "address_label">
|
||||
<b>{accounts[index].branches[0].entries[i].labels}</b>
|
||||
</div>
|
||||
|
||||
<rb.Accordion.Header>{accounts[index].branches[0].entries[i].address} {' '} </rb.Accordion.Header>
|
||||
<rb.Accordion.Body>
|
||||
<div className = "branch-body">
|
||||
amount: {accounts[index].branches[0].entries[i].amount}
|
||||
</div>
|
||||
</rb.Accordion.Body>
|
||||
</rb.Accordion.Item>
|
||||
</rb.Accordion>
|
||||
</div>
|
||||
))}
|
||||
</rb.Accordion.Body>
|
||||
</rb.Accordion.Item>
|
||||
<rb.Accordion.Item eventKey="1">
|
||||
<rb.Accordion.Header>Internal Addresses Balance: {accounts[index].branches[1].balance} BTC</rb.Accordion.Header>
|
||||
<rb.Accordion.Body>
|
||||
{accounts[index].branches[1].entries.map((user, j) => (
|
||||
<div key={j}>
|
||||
<rb.Accordion>
|
||||
<rb.Accordion.Item eventKey="0">
|
||||
<rb.Accordion.Header>{accounts[index].branches[0].entries[j].address} {' '} {accounts[index].branches[0].entries[j].labels} </rb.Accordion.Header>
|
||||
<rb.Accordion.Body>
|
||||
<div className = "branch_body">
|
||||
amount: {accounts[index].branches[0].entries[j].amount}
|
||||
</div>
|
||||
</rb.Accordion.Body>
|
||||
</rb.Accordion.Item>
|
||||
</rb.Accordion>
|
||||
</div>
|
||||
))}
|
||||
</rb.Accordion.Body>
|
||||
</rb.Accordion.Item>
|
||||
</rb.Accordion>
|
||||
</rb.Accordion.Body>
|
||||
</rb.Accordion.Item>
|
||||
</rb.Accordion>
|
||||
return (
|
||||
<div>
|
||||
Total Balance: {walletInfo.total_balance} BTC
|
||||
<p></p>
|
||||
<rb.Button href="/maker">Maker Service</rb.Button>
|
||||
<p></p>
|
||||
{accounts.map((account, index) => (
|
||||
<div key={index}>
|
||||
<rb.Accordion>
|
||||
<rb.Accordion.Item eventKey={index}>
|
||||
<rb.Accordion.Header className="head">
|
||||
<div className="links">
|
||||
<rb.Container>
|
||||
<rb.Row>
|
||||
<rb.Col>
|
||||
Account {accounts[index].account}
|
||||
</rb.Col>
|
||||
<rb.Col>
|
||||
Balance: {accounts[index].account_balance} BTC
|
||||
</rb.Col>
|
||||
<rb.Col>
|
||||
<Link to={{ pathname: "/payment", state: { account_no: accounts[index].account } }} className="btn btn-primary">Send </Link>{' '}
|
||||
</rb.Col>
|
||||
<rb.Col>
|
||||
<Link to={{ pathname: "/receive", state: { account_no: accounts[index].account } }} className="btn btn-primary">Receive </Link>
|
||||
</rb.Col>
|
||||
</rb.Row>
|
||||
</rb.Container>
|
||||
</div>
|
||||
))}
|
||||
</rb.Accordion.Header>
|
||||
<rb.Accordion.Body>
|
||||
<rb.Accordion>
|
||||
<rb.Accordion.Item eventKey="0">
|
||||
<rb.Accordion.Header>External Addresses Balance: {accounts[index].branches[0].balance} BTC </rb.Accordion.Header>
|
||||
<div className="xpub">
|
||||
Extended Pubkey : {accounts[index].branches[0].branch.split("\t").pop()}
|
||||
</div>
|
||||
<rb.Accordion.Body>
|
||||
{accounts[index].branches[0].entries.map((user, i) => (
|
||||
<div key={i}>
|
||||
<rb.Accordion>
|
||||
<rb.Accordion.Item eventKey="0">
|
||||
<div className="address_label">
|
||||
<b>{accounts[index].branches[0].entries[i].labels}</b>
|
||||
</div>
|
||||
<rb.Accordion.Header>{accounts[index].branches[0].entries[i].address} {' '} </rb.Accordion.Header>
|
||||
<rb.Accordion.Body>
|
||||
<div className="branch-body">
|
||||
amount: {accounts[index].branches[0].entries[i].amount}
|
||||
</div>
|
||||
</rb.Accordion.Body>
|
||||
</rb.Accordion.Item>
|
||||
</rb.Accordion>
|
||||
</div>
|
||||
))}
|
||||
</rb.Accordion.Body>
|
||||
</rb.Accordion.Item>
|
||||
<rb.Accordion.Item eventKey="1">
|
||||
<rb.Accordion.Header>Internal Addresses Balance: {accounts[index].branches[1].balance} BTC</rb.Accordion.Header>
|
||||
<rb.Accordion.Body>
|
||||
{accounts[index].branches[1].entries.map((user, j) => (
|
||||
<div key={j}>
|
||||
<rb.Accordion>
|
||||
<rb.Accordion.Item eventKey="0">
|
||||
<rb.Accordion.Header>{accounts[index].branches[0].entries[j].address} {' '} {accounts[index].branches[0].entries[j].labels} </rb.Accordion.Header>
|
||||
<rb.Accordion.Body>
|
||||
<div className="branch_body">
|
||||
amount: {accounts[index].branches[0].entries[j].amount}
|
||||
</div>
|
||||
</rb.Accordion.Body>
|
||||
</rb.Accordion.Item>
|
||||
</rb.Accordion>
|
||||
</div>
|
||||
))}
|
||||
</rb.Accordion.Body>
|
||||
</rb.Accordion.Item>
|
||||
</rb.Accordion>
|
||||
</rb.Accordion.Body>
|
||||
</rb.Accordion.Item>
|
||||
</rb.Accordion>
|
||||
</div>
|
||||
)
|
||||
))}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default DisplayMixdepth
|
||||
|
|
|
|||
|
|
@ -1,22 +1,19 @@
|
|||
import React from 'react'
|
||||
|
||||
const DisplayUTXOs = ({utxoID,utxo}) => {
|
||||
return (
|
||||
<div>
|
||||
<p></p>
|
||||
<p></p>
|
||||
<br></br>
|
||||
<span>Address: {utxo.address}</span>
|
||||
<br></br>
|
||||
<span>Value(Sats): {utxo.value}</span>
|
||||
<br></br>
|
||||
<span>Confirmations: {utxo.confirmations}</span>
|
||||
<br></br>
|
||||
<span>Mixdepth: {utxo.mixdepth}</span>
|
||||
<p></p>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default DisplayUTXOs;
|
||||
const DisplayUTXOs = ({ utxoID, utxo }) => (
|
||||
<div>
|
||||
<p></p>
|
||||
<p></p>
|
||||
<br></br>
|
||||
<span>Address: {utxo.address}</span>
|
||||
<br></br>
|
||||
<span>Value(Sats): {utxo.value}</span>
|
||||
<br></br>
|
||||
<span>Confirmations: {utxo.confirmations}</span>
|
||||
<br></br>
|
||||
<span>Mixdepth: {utxo.mixdepth}</span>
|
||||
<p></p>
|
||||
</div>
|
||||
)
|
||||
|
||||
export default DisplayUTXOs
|
||||
|
|
|
|||
|
|
@ -1,75 +1,73 @@
|
|||
import React from 'react'
|
||||
import {useState,useEffect} from 'react'
|
||||
import { useState, useEffect } from 'react'
|
||||
import { Button } from './Button'
|
||||
import DisplayMixdepth from './DisplayMixdepth'
|
||||
import DisplayUTXOs from './DisplayUTXOs'
|
||||
|
||||
const DisplayWallet = ({listWalletInfo,onSend,listUTXOs}) => {
|
||||
const [wallet_info,setWalletInfo] = useState([])
|
||||
const [UTXOHistory,setUTXOHistory] = useState({})
|
||||
const [showUTXO,setShowUTXO] = useState(false);
|
||||
// Websocket object with scope of DisplayWallet - we don't initialize
|
||||
// yet because it auto-opens, and we can only open once
|
||||
// we have authenticated:
|
||||
var ws;
|
||||
useEffect(()=>{
|
||||
const name = JSON.parse(sessionStorage.getItem('auth')).name;
|
||||
const token = JSON.parse(sessionStorage.getItem('auth')).token;
|
||||
ws = new WebSocket(`ws://${window.location.hostname}:${window.location.port}`);
|
||||
ws.onopen = (event) => {
|
||||
console.log("connected to websocket");
|
||||
ws.send(token);
|
||||
}
|
||||
ws.onmessage = (event) => {
|
||||
// For now we only have one message type,
|
||||
// namely the transaction notification:
|
||||
// For now, note that since the `getUtxos` function
|
||||
// is called on every render of the display page,
|
||||
// we don't need to somehow use this data other
|
||||
// than as some kind of popup/status bar notifier.
|
||||
// In future it might be possible to use the detailed
|
||||
// transaction deserialization passed in this notification,
|
||||
// for something.
|
||||
var wsdata = JSON.parse(event.data);
|
||||
alert("Websocket sent: " + wsdata.txid);
|
||||
}
|
||||
const getWalletInfo = async()=>{
|
||||
const wallet_info = await listWalletInfo(name);
|
||||
console.log(wallet_info);
|
||||
setWalletInfo(wallet_info);
|
||||
}
|
||||
const DisplayWallet = ({ listWalletInfo, onSend, listUTXOs }) => {
|
||||
const [wallet_info, setWalletInfo] = useState([])
|
||||
const [UTXOHistory, setUTXOHistory] = useState({})
|
||||
const [showUTXO, setShowUTXO] = useState(false)
|
||||
|
||||
const getUTXOs = async()=>{
|
||||
const utxos = await listUTXOs();
|
||||
setUTXOHistory(utxos)
|
||||
console.log(utxos)
|
||||
}
|
||||
// Websocket object with scope of DisplayWallet - we don't initialize
|
||||
// yet because it auto-opens, and we can only open once
|
||||
// we have authenticated:
|
||||
var ws
|
||||
useEffect(() => {
|
||||
const name = JSON.parse(sessionStorage.getItem('auth')).name;
|
||||
const token = JSON.parse(sessionStorage.getItem('auth')).token;
|
||||
ws = new WebSocket(`ws://${window.location.hostname}:${window.location.port}`);
|
||||
ws.onopen = (event) => {
|
||||
console.log("connected to websocket");
|
||||
ws.send(token);
|
||||
}
|
||||
ws.onmessage = (event) => {
|
||||
// For now we only have one message type,
|
||||
// namely the transaction notification:
|
||||
// For now, note that since the `getUtxos` function
|
||||
// is called on every render of the display page,
|
||||
// we don't need to somehow use this data other
|
||||
// than as some kind of popup/status bar notifier.
|
||||
// In future it might be possible to use the detailed
|
||||
// transaction deserialization passed in this notification,
|
||||
// for something.
|
||||
var wsdata = JSON.parse(event.data);
|
||||
alert("Websocket sent: " + wsdata.txid);
|
||||
}
|
||||
const getWalletInfo = async () => {
|
||||
const wallet_info = await listWalletInfo(name);
|
||||
console.log(wallet_info);
|
||||
setWalletInfo(wallet_info);
|
||||
}
|
||||
|
||||
getWalletInfo();
|
||||
getUTXOs();
|
||||
},[])
|
||||
const getUTXOs = async () => {
|
||||
const utxos = await listUTXOs();
|
||||
setUTXOHistory(utxos)
|
||||
console.log(utxos)
|
||||
}
|
||||
|
||||
return (
|
||||
<div>
|
||||
Wallet Details
|
||||
<p></p>
|
||||
{wallet_info.map((walletInfo,index)=>{
|
||||
return <DisplayMixdepth key={index} walletInfo = {walletInfo}></DisplayMixdepth>
|
||||
})}
|
||||
<p></p>
|
||||
<Button onClick={()=>{setShowUTXO(!showUTXO)}}>{showUTXO?"Hide UTXOs":"Show UTXOs"}</Button>
|
||||
<p></p>
|
||||
getWalletInfo();
|
||||
getUTXOs();
|
||||
}, [])
|
||||
|
||||
{
|
||||
showUTXO?
|
||||
Object.entries(UTXOHistory).map(([key, val])=>
|
||||
<DisplayUTXOs key={key} utxoID={key} utxo={val}> </DisplayUTXOs>
|
||||
)
|
||||
|
||||
: ""
|
||||
}
|
||||
</div>
|
||||
)
|
||||
return (
|
||||
<div>
|
||||
Wallet Details
|
||||
<p></p>
|
||||
{wallet_info.map((walletInfo, index) => {
|
||||
return <DisplayMixdepth key={index} walletInfo={walletInfo}></DisplayMixdepth>
|
||||
})}
|
||||
<p></p>
|
||||
<Button onClick={() => { setShowUTXO(!showUTXO) }}>{showUTXO ? "Hide UTXOs" : "Show UTXOs"}</Button>
|
||||
<p></p>
|
||||
{ showUTXO
|
||||
? Object.entries(UTXOHistory).map(([key, val]) =>
|
||||
<DisplayUTXOs key={key} utxoID={key} utxo={val}> </DisplayUTXOs>
|
||||
)
|
||||
: null
|
||||
}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default DisplayWallet
|
||||
|
|
|
|||
|
|
@ -1,6 +1,4 @@
|
|||
.container1{
|
||||
height: 100vh;
|
||||
padding-top: 100px;
|
||||
.container1 {
|
||||
height: 100vh;
|
||||
padding-top: 100px;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -1,67 +1,51 @@
|
|||
import React from 'react'
|
||||
import { useHistory } from 'react-router-dom';
|
||||
import { useHistory } from 'react-router-dom'
|
||||
import { useState } from 'react'
|
||||
import { useGlobal } from 'reactn';
|
||||
import { useGlobal } from 'reactn'
|
||||
|
||||
const Maker = ({onStart,onStop}) => {
|
||||
const Maker = ({ onStart, onStop }) => {
|
||||
const [cjfeeRel, setCjfeerel] = useState('')
|
||||
const [makerStarted] = useGlobal('makerStarted')
|
||||
const [setSubmitVal] = useState('Start Maker Service')
|
||||
const history = useHistory()
|
||||
|
||||
const [cjfeeRel,setCjfeerel] = useState('')
|
||||
const [makerStarted] = useGlobal("makerStarted");
|
||||
const [setSubmitVal] = useState('Start Maker Service')
|
||||
|
||||
const history = useHistory();
|
||||
|
||||
const onSubmit = (e) => {
|
||||
e.preventDefault()
|
||||
|
||||
|
||||
|
||||
if(makerStarted === false){
|
||||
console.log('b')
|
||||
if (!cjfeeRel) {
|
||||
alert('Please add details')
|
||||
return;
|
||||
}
|
||||
onStart(0,0,cjfeeRel,'sw0reloffer',1000);
|
||||
setCjfeerel('')
|
||||
alert("Attempting to start the yield generator. Check the status bar for updates.");
|
||||
setSubmitVal('Stop Maker Service')
|
||||
|
||||
}
|
||||
else{
|
||||
console.log('c')
|
||||
onStop();
|
||||
setSubmitVal('Start Maker Service')
|
||||
|
||||
}
|
||||
let path = `/display`;
|
||||
history.push(path);
|
||||
const onSubmit = (e) => {
|
||||
e.preventDefault()
|
||||
|
||||
if (makerStarted === false) {
|
||||
if (!cjfeeRel) {
|
||||
return alert('Please add details')
|
||||
}
|
||||
|
||||
onStart(0, 0, cjfeeRel, 'sw0reloffer', 1000)
|
||||
setCjfeerel('')
|
||||
alert("Attempting to start the yield generator. Check the status bar for updates.")
|
||||
setSubmitVal('Stop Maker Service')
|
||||
} else {
|
||||
onStop()
|
||||
setSubmitVal('Start Maker Service')
|
||||
}
|
||||
return (
|
||||
<div>
|
||||
<h3>Maker Service</h3>
|
||||
<form method="POST" onSubmit={onSubmit}>
|
||||
|
||||
let path = `/display`;
|
||||
history.push(path);
|
||||
}
|
||||
|
||||
return (
|
||||
<div>
|
||||
<h3>Maker Service</h3>
|
||||
<form method="POST" onSubmit={onSubmit}>
|
||||
<p></p>
|
||||
{
|
||||
makerStarted === false ?
|
||||
<label>
|
||||
Relative Coinjoin Fee
|
||||
<input type="text" name="cjfee_r" value = {cjfeeRel} onChange={(e) => setCjfeerel(e.target.value)}/>
|
||||
</label>
|
||||
:''
|
||||
{ makerStarted === false
|
||||
? <label>
|
||||
Relative Coinjoin Fee
|
||||
<input type="text" name="cjfee_r" value={cjfeeRel} onChange={(e) => setCjfeerel(e.target.value)} />
|
||||
</label>
|
||||
: null
|
||||
}
|
||||
|
||||
<p></p>
|
||||
|
||||
<input type="submit" value={makerStarted ==='true'?'Stop Maker Service':'Start Maker Service'} />
|
||||
|
||||
</form>
|
||||
</div>
|
||||
)
|
||||
<input type="submit" value={makerStarted === 'true' ? 'Stop Maker Service' : 'Start Maker Service'} />
|
||||
</form>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default Maker
|
||||
|
|
|
|||
|
|
@ -4,132 +4,108 @@ import { useLocation } from "react-router-dom"
|
|||
import './payment.css'
|
||||
import * as rb from 'react-bootstrap'
|
||||
|
||||
const Payment = ({onPayment,onCoinjoin}) => {
|
||||
const location = useLocation()
|
||||
const [destination, setDestination] = useState('')
|
||||
const [amount, setAmount] = useState('')
|
||||
const [mixdepth, setMixdepth] = useState(location.state.account_no)
|
||||
const [counterparties,setcounterparties] = useState('');
|
||||
const [isCoinjoin,setisCoinjoin] = useState(false);
|
||||
const Payment = ({ onPayment, onCoinjoin }) => {
|
||||
const location = useLocation()
|
||||
const [destination, setDestination] = useState('')
|
||||
const [amount, setAmount] = useState('')
|
||||
const [mixdepth, setMixdepth] = useState(location.state.account_no)
|
||||
const [counterparties, setcounterparties] = useState('')
|
||||
const [isCoinjoin, setisCoinjoin] = useState(false)
|
||||
|
||||
const onSubmit = (e) => {
|
||||
e.preventDefault()
|
||||
|
||||
if (!amount || !mixdepth || !destination) {
|
||||
alert('Please add details')
|
||||
return
|
||||
}
|
||||
//maybe add await here
|
||||
//if normal payment
|
||||
if(isCoinjoin===false){
|
||||
let wallet =JSON.parse(sessionStorage.getItem('auth')).name;
|
||||
onPayment(wallet,mixdepth,amount,destination);
|
||||
}
|
||||
//coinjoin
|
||||
else{
|
||||
if(!counterparties){
|
||||
alert("Please set counterparties to a non zero number");
|
||||
|
||||
return;
|
||||
}
|
||||
else{
|
||||
onCoinjoin(mixdepth,amount,counterparties,destination);
|
||||
alert("Coinjoin in progress");
|
||||
}
|
||||
const onSubmit = (e) => {
|
||||
e.preventDefault()
|
||||
|
||||
}
|
||||
|
||||
setcounterparties('');
|
||||
setMixdepth('');
|
||||
setAmount('');
|
||||
setDestination('');
|
||||
setisCoinjoin(false);
|
||||
|
||||
|
||||
|
||||
if (!amount || !mixdepth || !destination) {
|
||||
return alert('Please add details')
|
||||
}
|
||||
|
||||
//maybe add await here
|
||||
if (!isCoinjoin) { //if normal payment
|
||||
let wallet = JSON.parse(sessionStorage.getItem('auth')).name
|
||||
onPayment(wallet, mixdepth, amount, destination)
|
||||
} else { //coinjoin
|
||||
if (!counterparties) {
|
||||
return alert('Please set counterparties to a non zero number')
|
||||
} else {
|
||||
onCoinjoin(mixdepth, amount, counterparties, destination)
|
||||
alert('Coinjoin in progress')
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<div>
|
||||
setcounterparties('')
|
||||
setMixdepth('')
|
||||
setAmount('')
|
||||
setDestination('')
|
||||
setisCoinjoin(false)
|
||||
}
|
||||
|
||||
<br></br>
|
||||
<div className = "heading">
|
||||
Send Payment
|
||||
</div>
|
||||
return (
|
||||
<div>
|
||||
<div className="heading">
|
||||
Send Payment
|
||||
</div>
|
||||
|
||||
<form method="POST" onSubmit={onSubmit}>
|
||||
<rb.Container className = "center">
|
||||
<rb.Container fluid = "false" className = "form1">
|
||||
<rb.Row>
|
||||
|
||||
<rb.Col className="label">
|
||||
Receiver address:
|
||||
</rb.Col>
|
||||
<rb.Col>
|
||||
<input type="text" name="destination" value = {destination }onChange={(e) => setDestination(e.target.value)}/>
|
||||
</rb.Col>
|
||||
|
||||
</rb.Row>
|
||||
<rb.Row className = "field">
|
||||
|
||||
<rb.Col className="label">
|
||||
Account
|
||||
</rb.Col>
|
||||
<rb.Col>
|
||||
<input type="text" name="mixdepth" value = {mixdepth} onChange={(e) => setMixdepth(e.target.value)} readOnly={true}/>
|
||||
</rb.Col>
|
||||
|
||||
</rb.Row>
|
||||
<rb.Row className = "field">
|
||||
|
||||
<rb.Col className="label">
|
||||
Amount(SATS)
|
||||
</rb.Col>
|
||||
<rb.Col>
|
||||
<input type="text" name="amount_sats" value = {amount} onChange={(e) => setAmount(e.target.value)}/>
|
||||
</rb.Col>
|
||||
|
||||
</rb.Row>
|
||||
|
||||
<p></p>
|
||||
<br></br>
|
||||
<div className = "coinjoin">
|
||||
Do you want to do a coinjoin?
|
||||
<p></p>
|
||||
Yes<input type="radio" name="coinjoin" onChange={(e) => setisCoinjoin(true)} />
|
||||
<p></p>
|
||||
No<input type="radio" name="coinjoin" onChange={(e) => setisCoinjoin(false)}/>
|
||||
<p></p>
|
||||
</div>
|
||||
|
||||
|
||||
{
|
||||
isCoinjoin?
|
||||
<div>
|
||||
<rb.Row className = "field">
|
||||
<rb.Col className="label">
|
||||
Counterparties
|
||||
</rb.Col>
|
||||
<rb.Col>
|
||||
<input type="text" name="counterparties" value = {counterparties} onChange={(e)=>setcounterparties(e.target.value)}/>
|
||||
</rb.Col>
|
||||
<form method="POST" onSubmit={onSubmit}>
|
||||
<rb.Container className="center">
|
||||
<rb.Container fluid="false" className="form1">
|
||||
<rb.Row>
|
||||
<rb.Col className="label">
|
||||
Receiver address:
|
||||
</rb.Col>
|
||||
<rb.Col>
|
||||
<input type="text" name="destination" value={destination} onChange={(e) => setDestination(e.target.value)} />
|
||||
</rb.Col>
|
||||
</rb.Row>
|
||||
<rb.Row className="field">
|
||||
<rb.Col className="label">
|
||||
Account
|
||||
</rb.Col>
|
||||
<rb.Col>
|
||||
<input type="text" name="mixdepth" value={mixdepth} onChange={(e) => setMixdepth(e.target.value)} readOnly={true} />
|
||||
</rb.Col>
|
||||
</rb.Row>
|
||||
<rb.Row className="field">
|
||||
<rb.Col className="label">
|
||||
Amount(SATS)
|
||||
</rb.Col>
|
||||
<rb.Col>
|
||||
<input type="text" name="amount_sats" value={amount} onChange={(e) => setAmount(e.target.value)} />
|
||||
</rb.Col>
|
||||
</rb.Row>
|
||||
</div>
|
||||
:
|
||||
|
||||
""
|
||||
|
||||
}
|
||||
|
||||
<rb.Row className = "btn-field">
|
||||
<button className="btncr" type="submit" value="Submit" ><span>Submit</span></button>
|
||||
<p></p>
|
||||
<br></br>
|
||||
<div className="coinjoin">
|
||||
Do you want to do a coinjoin?
|
||||
<p></p>
|
||||
Yes<input type="radio" name="coinjoin" onChange={(e) => setisCoinjoin(true)} />
|
||||
<p></p>
|
||||
No<input type="radio" name="coinjoin" onChange={(e) => setisCoinjoin(false)} />
|
||||
<p></p>
|
||||
</div>
|
||||
|
||||
{isCoinjoin
|
||||
? <div>
|
||||
<rb.Row className="field">
|
||||
<rb.Col className="label">
|
||||
Counterparties
|
||||
</rb.Col>
|
||||
<rb.Col>
|
||||
<input type="text" name="counterparties" value={counterparties} onChange={(e) => setcounterparties(e.target.value)} />
|
||||
</rb.Col>
|
||||
</rb.Row>
|
||||
</rb.Container>
|
||||
</rb.Container>
|
||||
</form>
|
||||
</div>
|
||||
)
|
||||
</div>
|
||||
: null
|
||||
}
|
||||
|
||||
<rb.Row className="btn-field">
|
||||
<button className="btncr" type="submit" value="Submit" ><span>Submit</span></button>
|
||||
</rb.Row>
|
||||
</rb.Container>
|
||||
</rb.Container>
|
||||
</form>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default Payment
|
||||
|
|
|
|||
|
|
@ -6,105 +6,92 @@ import { useLocation } from "react-router-dom";
|
|||
import * as rb from 'react-bootstrap'
|
||||
import './receive.css'
|
||||
|
||||
const Receive = ({onReceive}) => {
|
||||
const location = useLocation()
|
||||
const [new_address, setNewAddress] = useState('')
|
||||
const Receive = ({ onReceive }) => {
|
||||
const location = useLocation()
|
||||
const [new_address, setNewAddress] = useState('')
|
||||
|
||||
const getAddress = async (mixdepth) =>{
|
||||
//update request with token if backend updated
|
||||
let authData = JSON.parse(sessionStorage.getItem('auth'));
|
||||
let token = "Bearer "+authData.token;
|
||||
let name = authData.name;
|
||||
const res = await fetch(`/api/v1/wallet/${name}/address/new/${mixdepth}`,{
|
||||
method:'GET',
|
||||
headers: {
|
||||
'Content-type': 'application/json',
|
||||
'Authorization':token
|
||||
},
|
||||
});
|
||||
const { address } = await res.json();
|
||||
return address;
|
||||
const getAddress = async (mixdepth) => {
|
||||
//update request with token if backend updated
|
||||
let authData = JSON.parse(sessionStorage.getItem('auth'));
|
||||
let token = "Bearer " + authData.token;
|
||||
let name = authData.name;
|
||||
const res = await fetch(`/api/v1/wallet/${name}/address/new/${mixdepth}`, {
|
||||
method: 'GET',
|
||||
headers: {
|
||||
'Content-type': 'application/json',
|
||||
'Authorization': token
|
||||
},
|
||||
});
|
||||
const { address } = await res.json();
|
||||
return address;
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
const getNewAddress = async (account) => {
|
||||
const temp1 = parseInt(account, 10)
|
||||
const temp = await getAddress(temp1)
|
||||
setNewAddress(temp)
|
||||
return
|
||||
}
|
||||
|
||||
useEffect(()=>{
|
||||
getNewAddress(location.state.account_no);
|
||||
}, [location.state.account_no])
|
||||
|
||||
const getNewAddress = async(account) => {
|
||||
const temp1 = parseInt(account,10)
|
||||
const temp = await getAddress(temp1)
|
||||
//window.alert(temp1)
|
||||
setNewAddress(temp)
|
||||
return
|
||||
}
|
||||
const [temp_address, setTempAddress] = useState('')
|
||||
const [amount, setAmount] = useState('')
|
||||
|
||||
getNewAddress(location.state.account_no);
|
||||
}, [location.state.account_no])
|
||||
const onSubmit = (e) => {
|
||||
e.preventDefault()
|
||||
|
||||
const [temp_address, setTempAddress] = useState('')
|
||||
const [amount, setAmount] = useState('')
|
||||
if (!new_address) {
|
||||
return alert('Please add the address')
|
||||
}
|
||||
|
||||
const onSubmit = (e) => {
|
||||
e.preventDefault()
|
||||
setTempAddress(new_address)
|
||||
}
|
||||
|
||||
if (!new_address) {
|
||||
alert('Please add the address')
|
||||
return
|
||||
}
|
||||
|
||||
setTempAddress(new_address)
|
||||
|
||||
}
|
||||
|
||||
return (
|
||||
<div>
|
||||
|
||||
<br></br>
|
||||
<div className = "heading">
|
||||
Receive Funds
|
||||
</div>
|
||||
|
||||
<form method="POST" onSubmit={onSubmit}>
|
||||
<rb.Container className = "center">
|
||||
<rb.Container fluid = "false" className = "form1">
|
||||
<rb.Row>
|
||||
|
||||
<rb.Col className="label">
|
||||
Address
|
||||
</rb.Col>
|
||||
<rb.Col>
|
||||
<input type="text" name="address" value = {new_address } style = {{width: "415px"}} readOnly = {true} onChange={(e) => setNewAddress(e.target.value)}/>
|
||||
</rb.Col>
|
||||
|
||||
</rb.Row>
|
||||
<rb.Row className = "field">
|
||||
|
||||
<rb.Col className="label">
|
||||
Amount(BTC)
|
||||
</rb.Col>
|
||||
<rb.Col>
|
||||
<input type="text" name="amount_sats" value = {amount} style = {{width: "415px"}} onChange={(e) => setAmount(e.target.value)}/>
|
||||
</rb.Col>
|
||||
|
||||
</rb.Row>
|
||||
<rb.Row className = "btn-field">
|
||||
<button className="btncr" type="submit" value="Submit" ><span>Get QR Code</span></button>
|
||||
</rb.Row>
|
||||
|
||||
{temp_address.length > 0? (
|
||||
<BitcoinQR
|
||||
bitcoinAddress={temp_address}
|
||||
message = ""
|
||||
amount ={amount}
|
||||
time = ""
|
||||
exp = ""
|
||||
/>):("")}
|
||||
|
||||
</rb.Container>
|
||||
</rb.Container>
|
||||
|
||||
|
||||
</form>
|
||||
</div>
|
||||
)
|
||||
return (
|
||||
<div>
|
||||
<div className="heading">
|
||||
Receive Funds
|
||||
</div>
|
||||
<form method="POST" onSubmit={onSubmit}>
|
||||
<rb.Container className="center">
|
||||
<rb.Container fluid="false" className="form1">
|
||||
<rb.Row>
|
||||
<rb.Col className="label">
|
||||
Address
|
||||
</rb.Col>
|
||||
<rb.Col>
|
||||
<input type="text" name="address" value={new_address} style={{ width: "415px" }} readOnly={true} onChange={(e) => setNewAddress(e.target.value)} />
|
||||
</rb.Col>
|
||||
</rb.Row>
|
||||
<rb.Row className="field">
|
||||
<rb.Col className="label">
|
||||
Amount(BTC)
|
||||
</rb.Col>
|
||||
<rb.Col>
|
||||
<input type="text" name="amount_sats" value={amount} style={{ width: "415px" }} onChange={(e) => setAmount(e.target.value)} />
|
||||
</rb.Col>
|
||||
</rb.Row>
|
||||
<rb.Row className="btn-field">
|
||||
<button className="btncr" type="submit" value="Submit" ><span>Get QR Code</span></button>
|
||||
</rb.Row>
|
||||
{temp_address.length > 0
|
||||
? <BitcoinQR
|
||||
bitcoinAddress={temp_address}
|
||||
message=""
|
||||
amount={amount}
|
||||
time=""
|
||||
exp=""
|
||||
/>
|
||||
: null
|
||||
}
|
||||
</rb.Container>
|
||||
</rb.Container>
|
||||
</form>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default Receive
|
||||
|
|
|
|||
|
|
@ -1,20 +1,20 @@
|
|||
import React from 'react'
|
||||
import * as rb from 'react-bootstrap'
|
||||
import './wallet.css'
|
||||
const Wallet = ({name,onUnlock,onLock,onDisplay}) => {
|
||||
return (
|
||||
<div>
|
||||
<br></br>
|
||||
<rb.Card style={{ width: '18rem' }} className = "wallet_cards">
|
||||
<rb.Card.Body>
|
||||
<rb.Card.Title>{name}</rb.Card.Title>
|
||||
<rb.Button className="btn btn-primary" onClick={()=>onUnlock(name)}>Unlock</rb.Button>{' '}
|
||||
<rb.Button href="/display">Open</rb.Button>{' '}
|
||||
<rb.Button onClick = {()=>onLock(name)}>Lock</rb.Button>
|
||||
</rb.Card.Body>
|
||||
</rb.Card>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
const Wallet = ({ name, isCurrent, onUnlock, onLock }) => (
|
||||
<rb.Card style={{ width: '18rem' }} className="wallet_cards mb-3">
|
||||
<rb.Card.Body>
|
||||
<rb.Card.Title>{name}</rb.Card.Title>
|
||||
{ isCurrent
|
||||
? <>
|
||||
<rb.Button className="btn btn-primary me-2" href="/display">Open</rb.Button>
|
||||
<rb.Button className="btn btn-secondary" onClick={() => onLock(name)}>Lock</rb.Button>
|
||||
</>
|
||||
: <rb.Button className="btn btn-primary" onClick={() => onUnlock(name)}>Unlock</rb.Button>
|
||||
}
|
||||
</rb.Card.Body>
|
||||
</rb.Card>
|
||||
)
|
||||
|
||||
export default Wallet
|
||||
|
|
|
|||
|
|
@ -1,15 +1,9 @@
|
|||
import React from 'react'
|
||||
import Wallet from './Wallet'
|
||||
const Wallets = ({walletList,onUnlock,onLock,onDisplay}) => {
|
||||
|
||||
return (
|
||||
<>
|
||||
<p></p>
|
||||
{walletList.map((wallet,index)=>{
|
||||
return <Wallet key = {index} name={wallet} onUnlock = {onUnlock} onLock = {onLock} onDisplay = {onDisplay}></Wallet>
|
||||
})}
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
const Wallets = ({ walletList, currentWallet, onUnlock, onLock, onDisplay }) =>
|
||||
walletList.map((wallet, index)=>
|
||||
<Wallet key={index} name={wallet} isCurrent={wallet === currentWallet} onUnlock={onUnlock} onLock={onLock} onDisplay={onDisplay} />
|
||||
)
|
||||
|
||||
export default Wallets
|
||||
|
|
|
|||
|
|
@ -1,10 +1,10 @@
|
|||
.heading{
|
||||
color:rgb(15, 3, 58);
|
||||
.heading {
|
||||
color: rgb(15, 3, 58);
|
||||
font-size: 40px;
|
||||
font-weight: 450;
|
||||
}
|
||||
|
||||
.form1{
|
||||
.form1 {
|
||||
margin: 0 auto;
|
||||
background-color: rgb(244, 247, 253);
|
||||
width: 40%;
|
||||
|
|
@ -16,24 +16,23 @@
|
|||
border-width: 3px;
|
||||
border-style: dashed;
|
||||
border-color: #e0e3f0;
|
||||
|
||||
}
|
||||
|
||||
.center{
|
||||
.center {
|
||||
padding: 40px;
|
||||
}
|
||||
|
||||
.label{
|
||||
.label {
|
||||
text-align: left;
|
||||
font-size: 20px;
|
||||
color:rgb(15, 3, 58)
|
||||
color: rgb(15, 3, 58)
|
||||
}
|
||||
|
||||
.field{
|
||||
.field {
|
||||
padding-top: 20px;
|
||||
}
|
||||
|
||||
.field-border{
|
||||
.field-border {
|
||||
border-radius: 10px;
|
||||
border-width: 2px;
|
||||
border-style: dashed;
|
||||
|
|
@ -62,7 +61,7 @@
|
|||
}
|
||||
|
||||
.btncr span {
|
||||
position: relative;
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
color:rgb(15, 3, 58)
|
||||
}
|
||||
|
|
@ -84,4 +83,4 @@
|
|||
.btncr:hover:after {
|
||||
-webkit-transform: translateX(-9%) translateY(-25%) rotate(45deg);
|
||||
transform: translateX(-9%) translateY(-25%) rotate(45deg);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,18 +1,18 @@
|
|||
.head{
|
||||
font-size: small;
|
||||
.head {
|
||||
font-size: small;
|
||||
}
|
||||
|
||||
.address_label{
|
||||
text-align: right;
|
||||
padding-right: 7%;
|
||||
color: rgb(10, 192, 10);
|
||||
.address_label {
|
||||
text-align: right;
|
||||
padding-right: 7%;
|
||||
color: rgb(10, 192, 10);
|
||||
}
|
||||
|
||||
.xpub{
|
||||
text-align: left;
|
||||
padding-left: 20px;
|
||||
.xpub {
|
||||
text-align: left;
|
||||
padding-left: 20px;
|
||||
}
|
||||
|
||||
.branch_body{
|
||||
text-align: left;
|
||||
}
|
||||
text-align: left;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,33 +1,21 @@
|
|||
import React from 'react'
|
||||
import * as rb from 'react-bootstrap'
|
||||
import './Homepage.css'
|
||||
import { Link } from 'react-router-dom';
|
||||
import { Link } from 'react-router-dom'
|
||||
|
||||
const Homepage = () => {
|
||||
|
||||
return (
|
||||
<>
|
||||
|
||||
<div className="showcase-container">
|
||||
<h1 className="main-title" id="home">Joinmarket</h1>
|
||||
</div>
|
||||
|
||||
<rb.Container className = "container1">
|
||||
<rb.Row>
|
||||
<rb.Col className = "column">
|
||||
<div className="text-center">
|
||||
<Link to="/create" className="btn btn-primary">Create Wallet</Link>
|
||||
</div>
|
||||
</rb.Col>
|
||||
|
||||
<rb.Col className = "column">
|
||||
<Link to="/showWallets" className="btn btn-primary">Show Wallets</Link>
|
||||
</rb.Col>
|
||||
</rb.Row>
|
||||
</rb.Container>
|
||||
|
||||
</>
|
||||
)
|
||||
}
|
||||
const Homepage = () => (
|
||||
<rb.Container className="container1">
|
||||
<rb.Row>
|
||||
<rb.Col className="column">
|
||||
<div className="text-center">
|
||||
<Link to="/create" className="btn btn-primary">Create Wallet</Link>
|
||||
</div>
|
||||
</rb.Col>
|
||||
<rb.Col className="column">
|
||||
<Link to="/showWallets" className="btn btn-primary">Show Wallets</Link>
|
||||
</rb.Col>
|
||||
</rb.Row>
|
||||
</rb.Container>
|
||||
)
|
||||
|
||||
export default Homepage
|
||||
|
|
|
|||
|
|
@ -1,91 +1,91 @@
|
|||
.heading{
|
||||
color:rgb(15, 3, 58);
|
||||
font-size: 40px;
|
||||
font-weight: 450;
|
||||
}
|
||||
|
||||
.form1{
|
||||
margin: 0 auto;
|
||||
background-color: rgb(244, 247, 253);
|
||||
width: 50%;
|
||||
padding-top: 40px;
|
||||
padding-bottom: 40px;
|
||||
padding-left: 40px;
|
||||
padding-right: 40px;
|
||||
border-radius: 10px;
|
||||
border-width: 3px;
|
||||
border-style: dashed;
|
||||
border-color: #e0e3f0;
|
||||
|
||||
}
|
||||
|
||||
.coinjoin{
|
||||
font-size: 20px;
|
||||
.heading {
|
||||
color:rgb(15, 3, 58);
|
||||
font-size: 40px;
|
||||
font-weight: 450;
|
||||
}
|
||||
|
||||
.center{
|
||||
padding: 40px;
|
||||
}
|
||||
|
||||
.label{
|
||||
text-align: left;
|
||||
font-size: 20px;
|
||||
color:rgb(15, 3, 58)
|
||||
}
|
||||
|
||||
.field{
|
||||
padding-top: 20px;
|
||||
}
|
||||
|
||||
.field-border{
|
||||
border-radius: 10px;
|
||||
border-width: 2px;
|
||||
border-style: dashed;
|
||||
border-color: #e0e3f0;
|
||||
}
|
||||
|
||||
.btn-field{
|
||||
padding-top: 50px;
|
||||
}
|
||||
|
||||
.btncr {
|
||||
border: none;
|
||||
border-radius: 2px;
|
||||
display: block;
|
||||
text-align: center;
|
||||
cursor: pointer;
|
||||
outline: none;
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
font-weight: 500;
|
||||
font-size: 20px;
|
||||
background-color: rgb(244, 247, 253);
|
||||
padding: 10px 60px;
|
||||
margin: 0 auto;
|
||||
box-shadow: 0 5px 15px rgba(0,0,0,0.20);
|
||||
}
|
||||
|
||||
.btncr span {
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
color:rgb(15, 3, 58)
|
||||
}
|
||||
|
||||
.btncr:after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
height: 300%;
|
||||
width: 130%;
|
||||
background: #e0e3f0;
|
||||
-webkit-transition: all .5s ease-in-out;
|
||||
transition: all .5s ease-in-out;
|
||||
-webkit-transform: translateX(-98%) translateY(-25%) rotate(45deg);
|
||||
transform: translateX(-98%) translateY(-25%) rotate(45deg);
|
||||
}
|
||||
|
||||
.btncr:hover:after {
|
||||
-webkit-transform: translateX(-9%) translateY(-25%) rotate(45deg);
|
||||
transform: translateX(-9%) translateY(-25%) rotate(45deg);
|
||||
}
|
||||
.form1 {
|
||||
margin: 0 auto;
|
||||
background-color: rgb(244, 247, 253);
|
||||
width: 50%;
|
||||
padding-top: 40px;
|
||||
padding-bottom: 40px;
|
||||
padding-left: 40px;
|
||||
padding-right: 40px;
|
||||
border-radius: 10px;
|
||||
border-width: 3px;
|
||||
border-style: dashed;
|
||||
border-color: #e0e3f0;
|
||||
|
||||
}
|
||||
|
||||
.coinjoin{
|
||||
font-size: 20px;
|
||||
}
|
||||
|
||||
.center{
|
||||
padding: 40px;
|
||||
}
|
||||
|
||||
.label{
|
||||
text-align: left;
|
||||
font-size: 20px;
|
||||
color: rgb(15, 3, 58)
|
||||
}
|
||||
|
||||
.field{
|
||||
padding-top: 20px;
|
||||
}
|
||||
|
||||
.field-border{
|
||||
border-radius: 10px;
|
||||
border-width: 2px;
|
||||
border-style: dashed;
|
||||
border-color: #e0e3f0;
|
||||
}
|
||||
|
||||
.btn-field{
|
||||
padding-top: 50px;
|
||||
}
|
||||
|
||||
.btncr {
|
||||
border: none;
|
||||
border-radius: 2px;
|
||||
display: block;
|
||||
text-align: center;
|
||||
cursor: pointer;
|
||||
outline: none;
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
font-weight: 500;
|
||||
font-size: 20px;
|
||||
background-color: rgb(244, 247, 253);
|
||||
padding: 10px 60px;
|
||||
margin: 0 auto;
|
||||
box-shadow: 0 5px 15px rgba(0,0,0,0.20);
|
||||
}
|
||||
|
||||
.btncr span {
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
color:rgb(15, 3, 58)
|
||||
}
|
||||
|
||||
.btncr:after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
height: 300%;
|
||||
width: 130%;
|
||||
background: #e0e3f0;
|
||||
-webkit-transition: all .5s ease-in-out;
|
||||
transition: all .5s ease-in-out;
|
||||
-webkit-transform: translateX(-98%) translateY(-25%) rotate(45deg);
|
||||
transform: translateX(-98%) translateY(-25%) rotate(45deg);
|
||||
}
|
||||
|
||||
.btncr:hover:after {
|
||||
-webkit-transform: translateX(-9%) translateY(-25%) rotate(45deg);
|
||||
transform: translateX(-9%) translateY(-25%) rotate(45deg);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,91 +1,90 @@
|
|||
.heading{
|
||||
color:rgb(15, 3, 58);
|
||||
font-size: 40px;
|
||||
font-weight: 450;
|
||||
}
|
||||
|
||||
.form1{
|
||||
margin: 0 auto;
|
||||
background-color: rgb(244, 247, 253);
|
||||
width: 50%;
|
||||
padding-top: 40px;
|
||||
padding-bottom: 40px;
|
||||
padding-left: 40px;
|
||||
padding-right: 40px;
|
||||
border-radius: 10px;
|
||||
border-width: 3px;
|
||||
border-style: dashed;
|
||||
border-color: #e0e3f0;
|
||||
|
||||
}
|
||||
|
||||
.coinjoin{
|
||||
font-size: 20px;
|
||||
.heading {
|
||||
color:rgb(15, 3, 58);
|
||||
font-size: 40px;
|
||||
font-weight: 450;
|
||||
}
|
||||
|
||||
.center{
|
||||
padding: 40px;
|
||||
}
|
||||
|
||||
.label{
|
||||
text-align: left;
|
||||
font-size: 20px;
|
||||
color:rgb(15, 3, 58)
|
||||
}
|
||||
|
||||
.field{
|
||||
padding-top: 20px;
|
||||
}
|
||||
|
||||
.field-border{
|
||||
border-radius: 10px;
|
||||
border-width: 2px;
|
||||
border-style: dashed;
|
||||
border-color: #e0e3f0;
|
||||
}
|
||||
|
||||
.btn-field{
|
||||
padding-top: 50px;
|
||||
}
|
||||
|
||||
.btncr {
|
||||
border: none;
|
||||
border-radius: 2px;
|
||||
display: block;
|
||||
text-align: center;
|
||||
cursor: pointer;
|
||||
outline: none;
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
font-weight: 500;
|
||||
font-size: 20px;
|
||||
background-color: rgb(244, 247, 253);
|
||||
padding: 10px 60px;
|
||||
margin: 0 auto;
|
||||
box-shadow: 0 5px 15px rgba(0,0,0,0.20);
|
||||
}
|
||||
|
||||
.btncr span {
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
color:rgb(15, 3, 58)
|
||||
}
|
||||
|
||||
.btncr:after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
height: 300%;
|
||||
width: 130%;
|
||||
background: #e0e3f0;
|
||||
-webkit-transition: all .5s ease-in-out;
|
||||
transition: all .5s ease-in-out;
|
||||
-webkit-transform: translateX(-98%) translateY(-25%) rotate(45deg);
|
||||
transform: translateX(-98%) translateY(-25%) rotate(45deg);
|
||||
}
|
||||
|
||||
.btncr:hover:after {
|
||||
-webkit-transform: translateX(-9%) translateY(-25%) rotate(45deg);
|
||||
transform: translateX(-9%) translateY(-25%) rotate(45deg);
|
||||
}
|
||||
.form1 {
|
||||
margin: 0 auto;
|
||||
background-color: rgb(244, 247, 253);
|
||||
width: 50%;
|
||||
padding-top: 40px;
|
||||
padding-bottom: 40px;
|
||||
padding-left: 40px;
|
||||
padding-right: 40px;
|
||||
border-radius: 10px;
|
||||
border-width: 3px;
|
||||
border-style: dashed;
|
||||
border-color: #e0e3f0;
|
||||
}
|
||||
|
||||
.coinjoin{
|
||||
font-size: 20px;
|
||||
}
|
||||
|
||||
.center {
|
||||
padding: 40px;
|
||||
}
|
||||
|
||||
.label {
|
||||
text-align: left;
|
||||
font-size: 20px;
|
||||
color:rgb(15, 3, 58)
|
||||
}
|
||||
|
||||
.field {
|
||||
padding-top: 20px;
|
||||
}
|
||||
|
||||
.field-border {
|
||||
border-radius: 10px;
|
||||
border-width: 2px;
|
||||
border-style: dashed;
|
||||
border-color: #e0e3f0;
|
||||
}
|
||||
|
||||
.btn-field {
|
||||
padding-top: 50px;
|
||||
}
|
||||
|
||||
.btncr {
|
||||
border: none;
|
||||
border-radius: 2px;
|
||||
display: block;
|
||||
text-align: center;
|
||||
cursor: pointer;
|
||||
outline: none;
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
font-weight: 500;
|
||||
font-size: 20px;
|
||||
background-color: rgb(244, 247, 253);
|
||||
padding: 10px 60px;
|
||||
margin: 0 auto;
|
||||
box-shadow: 0 5px 15px rgba(0,0,0,0.20);
|
||||
}
|
||||
|
||||
.btncr span {
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
color: rgb(15, 3, 58)
|
||||
}
|
||||
|
||||
.btncr:after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
height: 300%;
|
||||
width: 130%;
|
||||
background: #e0e3f0;
|
||||
-webkit-transition: all .5s ease-in-out;
|
||||
transition: all .5s ease-in-out;
|
||||
-webkit-transform: translateX(-98%) translateY(-25%) rotate(45deg);
|
||||
transform: translateX(-98%) translateY(-25%) rotate(45deg);
|
||||
}
|
||||
|
||||
.btncr:hover:after {
|
||||
-webkit-transform: translateX(-9%) translateY(-25%) rotate(45deg);
|
||||
transform: translateX(-9%) translateY(-25%) rotate(45deg);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,87 +1,87 @@
|
|||
.heading{
|
||||
color:rgb(15, 3, 58);
|
||||
font-size: 40px;
|
||||
font-weight: 450;
|
||||
}
|
||||
|
||||
.form1{
|
||||
margin: 0 auto;
|
||||
background-color: rgb(244, 247, 253);
|
||||
width: 60%;
|
||||
padding-top: 40px;
|
||||
padding-bottom: 40px;
|
||||
padding-left: 40px;
|
||||
padding-right: 40px;
|
||||
border-radius: 10px;
|
||||
border-width: 3px;
|
||||
border-style: dashed;
|
||||
border-color: #e0e3f0;
|
||||
|
||||
}
|
||||
|
||||
.center{
|
||||
padding: 40px;
|
||||
}
|
||||
|
||||
.label{
|
||||
text-align: left;
|
||||
font-size: 20px;
|
||||
color:rgb(15, 3, 58)
|
||||
}
|
||||
|
||||
.field{
|
||||
padding-top: 20px;
|
||||
}
|
||||
|
||||
.field-border{
|
||||
border-radius: 10px;
|
||||
border-width: 2px;
|
||||
border-style: dashed;
|
||||
border-color: #e0e3f0;
|
||||
}
|
||||
|
||||
.btn-field{
|
||||
padding-top: 50px;
|
||||
}
|
||||
|
||||
.btncr {
|
||||
border: none;
|
||||
border-radius: 2px;
|
||||
display: block;
|
||||
text-align: center;
|
||||
cursor: pointer;
|
||||
outline: none;
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
font-weight: 500;
|
||||
font-size: 20px;
|
||||
background-color: rgb(244, 247, 253);
|
||||
padding: 10px 60px;
|
||||
margin: 0 auto;
|
||||
box-shadow: 0 5px 15px rgba(0,0,0,0.20);
|
||||
}
|
||||
|
||||
.btncr span {
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
color:rgb(15, 3, 58)
|
||||
}
|
||||
|
||||
.btncr:after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
height: 300%;
|
||||
width: 130%;
|
||||
background: #e0e3f0;
|
||||
-webkit-transition: all .5s ease-in-out;
|
||||
transition: all .5s ease-in-out;
|
||||
-webkit-transform: translateX(-98%) translateY(-25%) rotate(45deg);
|
||||
transform: translateX(-98%) translateY(-25%) rotate(45deg);
|
||||
}
|
||||
|
||||
.btncr:hover:after {
|
||||
-webkit-transform: translateX(-9%) translateY(-25%) rotate(45deg);
|
||||
transform: translateX(-9%) translateY(-25%) rotate(45deg);
|
||||
}
|
||||
.heading {
|
||||
color: rgb(15, 3, 58);
|
||||
font-size: 40px;
|
||||
font-weight: 450;
|
||||
}
|
||||
|
||||
.form1{
|
||||
margin: 0 auto;
|
||||
background-color: rgb(244, 247, 253);
|
||||
width: 60%;
|
||||
padding-top: 40px;
|
||||
padding-bottom: 40px;
|
||||
padding-left: 40px;
|
||||
padding-right: 40px;
|
||||
border-radius: 10px;
|
||||
border-width: 3px;
|
||||
border-style: dashed;
|
||||
border-color: #e0e3f0;
|
||||
|
||||
}
|
||||
|
||||
.center {
|
||||
padding: 40px;
|
||||
}
|
||||
|
||||
.label {
|
||||
text-align: left;
|
||||
font-size: 20px;
|
||||
color:rgb(15, 3, 58)
|
||||
}
|
||||
|
||||
.field {
|
||||
padding-top: 20px;
|
||||
}
|
||||
|
||||
.field-border {
|
||||
border-radius: 10px;
|
||||
border-width: 2px;
|
||||
border-style: dashed;
|
||||
border-color: #e0e3f0;
|
||||
}
|
||||
|
||||
.btn-field {
|
||||
padding-top: 50px;
|
||||
}
|
||||
|
||||
.btncr {
|
||||
border: none;
|
||||
border-radius: 2px;
|
||||
display: block;
|
||||
text-align: center;
|
||||
cursor: pointer;
|
||||
outline: none;
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
font-weight: 500;
|
||||
font-size: 20px;
|
||||
background-color: rgb(244, 247, 253);
|
||||
padding: 10px 60px;
|
||||
margin: 0 auto;
|
||||
box-shadow: 0 5px 15px rgba(0,0,0,0.20);
|
||||
}
|
||||
|
||||
.btncr span {
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
color:rgb(15, 3, 58)
|
||||
}
|
||||
|
||||
.btncr:after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
height: 300%;
|
||||
width: 130%;
|
||||
background: #e0e3f0;
|
||||
-webkit-transition: all .5s ease-in-out;
|
||||
transition: all .5s ease-in-out;
|
||||
-webkit-transform: translateX(-98%) translateY(-25%) rotate(45deg);
|
||||
transform: translateX(-98%) translateY(-25%) rotate(45deg);
|
||||
}
|
||||
|
||||
.btncr:hover:after {
|
||||
-webkit-transform: translateX(-9%) translateY(-25%) rotate(45deg);
|
||||
transform: translateX(-9%) translateY(-25%) rotate(45deg);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,22 +1,21 @@
|
|||
import { useEffect, useRef } from 'react';
|
||||
import { useEffect, useRef } from 'react'
|
||||
|
||||
const useInterval = (callback, delay) => {
|
||||
const savedCallback = useRef();
|
||||
|
||||
useEffect(() => {
|
||||
savedCallback.current = callback;
|
||||
savedCallback.current = callback
|
||||
}, [callback]);
|
||||
|
||||
|
||||
useEffect(() => {
|
||||
function tick() {
|
||||
savedCallback.current();
|
||||
savedCallback.current()
|
||||
}
|
||||
if (delay !== null) {
|
||||
const id = setInterval(tick, delay);
|
||||
return () => clearInterval(id);
|
||||
const id = setInterval(tick, delay)
|
||||
return () => clearInterval(id)
|
||||
}
|
||||
}, [delay]);
|
||||
}, [delay])
|
||||
}
|
||||
|
||||
export default useInterval;
|
||||
export default useInterval
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
.wallet_cards{
|
||||
margin: 0 auto;
|
||||
}
|
||||
.wallet_cards {
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,13 +1,10 @@
|
|||
body {
|
||||
margin: 0;
|
||||
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
|
||||
'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',
|
||||
sans-serif;
|
||||
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
}
|
||||
|
||||
code {
|
||||
font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New',
|
||||
monospace;
|
||||
font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New', monospace;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ import App from './App';
|
|||
import reportWebVitals from './reportWebVitals';
|
||||
import 'bootstrap/dist/css/bootstrap.min.css';
|
||||
import { setGlobal } from 'reactn';
|
||||
|
||||
// Set an initial global state directly:
|
||||
setGlobal({
|
||||
currentStatusMessage: "loading",
|
||||
|
|
@ -14,7 +15,7 @@ setGlobal({
|
|||
});
|
||||
|
||||
ReactDOM.render(
|
||||
|
||||
|
||||
<App />
|
||||
,
|
||||
document.getElementById('root')
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue