├── joinmarket ├── src │ ├── components │ │ ├── button.css │ │ ├── wallet.css │ │ ├── Homepage.css │ │ ├── Button.jsx │ │ ├── displayMixdepth.css │ │ ├── Wallets.jsx │ │ ├── utils.jsx │ │ ├── DisplayUTXOs.jsx │ │ ├── Wallet.jsx │ │ ├── homepage.jsx │ │ ├── createWallet.css │ │ ├── receive.css │ │ ├── maker.css │ │ ├── payment.css │ │ ├── Maker.jsx │ │ ├── CreateWallet.jsx │ │ ├── DisplayWallet.jsx │ │ ├── Receive.jsx │ │ ├── Payment.jsx │ │ └── DisplayMixdepth.jsx │ ├── setupTests.js │ ├── App.test.js │ ├── index.css │ ├── reportWebVitals.js │ ├── App.css │ ├── index.js │ ├── twitter.svg │ ├── github.svg │ ├── logo.svg │ └── App.js ├── public │ ├── robots.txt │ ├── favicon.ico │ ├── logo192.png │ ├── logo512.png │ ├── manifest.json │ └── index.html ├── .gitignore ├── package.json └── README.md └── README.md /joinmarket/src/components/button.css: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /joinmarket/src/components/wallet.css: -------------------------------------------------------------------------------- 1 | .wallet_cards{ 2 | margin: 0 auto; 3 | } -------------------------------------------------------------------------------- /joinmarket/public/robots.txt: -------------------------------------------------------------------------------- 1 | # https://www.robotstxt.org/robotstxt.html 2 | User-agent: * 3 | Disallow: 4 | -------------------------------------------------------------------------------- /joinmarket/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JoinMarket-Org/jm-web-client/HEAD/joinmarket/public/favicon.ico -------------------------------------------------------------------------------- /joinmarket/public/logo192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JoinMarket-Org/jm-web-client/HEAD/joinmarket/public/logo192.png -------------------------------------------------------------------------------- /joinmarket/public/logo512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JoinMarket-Org/jm-web-client/HEAD/joinmarket/public/logo512.png -------------------------------------------------------------------------------- /joinmarket/src/components/Homepage.css: -------------------------------------------------------------------------------- 1 | .container1{ 2 | height: 100vh; 3 | padding-top: 100px; 4 | } 5 | 6 | 7 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Web client for joinmarket 2 | 3 | This project was an earlier proof-of-concept, please go to: https://github.com/joinmarket-webui/joinmarket-webui 4 | -------------------------------------------------------------------------------- /joinmarket/src/setupTests.js: -------------------------------------------------------------------------------- 1 | // jest-dom adds custom jest matchers for asserting on DOM nodes. 2 | // allows you to do things like: 3 | // expect(element).toHaveTextContent(/react/i) 4 | // learn more: https://github.com/testing-library/jest-dom 5 | import '@testing-library/jest-dom'; 6 | -------------------------------------------------------------------------------- /joinmarket/src/App.test.js: -------------------------------------------------------------------------------- 1 | import { render, screen } from '@testing-library/react'; 2 | import App from './App'; 3 | 4 | test('renders learn react link', () => { 5 | render(); 6 | const linkElement = screen.getByText(/learn react/i); 7 | expect(linkElement).toBeInTheDocument(); 8 | }); 9 | -------------------------------------------------------------------------------- /joinmarket/src/components/Button.jsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import "./button.css"; 3 | 4 | export const Button = ({name,children, type, onClick, buttonStyle, buttonSize}) => { 5 | return ( 6 | 9 | ) 10 | } 11 | 12 | -------------------------------------------------------------------------------- /joinmarket/src/components/displayMixdepth.css: -------------------------------------------------------------------------------- 1 | .head{ 2 | font-size: small; 3 | } 4 | 5 | .address_label{ 6 | text-align: right; 7 | padding-right: 7%; 8 | color: rgb(10, 192, 10); 9 | } 10 | 11 | .xpub{ 12 | text-align: left; 13 | padding-left: 20px; 14 | } 15 | 16 | .branch_body{ 17 | text-align: left; 18 | } -------------------------------------------------------------------------------- /joinmarket/.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.js 7 | 8 | # testing 9 | /coverage 10 | 11 | # production 12 | /build 13 | 14 | # misc 15 | .DS_Store 16 | .env.local 17 | .env.development.local 18 | .env.test.local 19 | .env.production.local 20 | 21 | npm-debug.log* 22 | yarn-debug.log* 23 | yarn-error.log* 24 | -------------------------------------------------------------------------------- /joinmarket/src/index.css: -------------------------------------------------------------------------------- 1 | body { 2 | margin: 0; 3 | font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 4 | 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', 5 | sans-serif; 6 | -webkit-font-smoothing: antialiased; 7 | -moz-osx-font-smoothing: grayscale; 8 | } 9 | 10 | code { 11 | font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New', 12 | monospace; 13 | } 14 | -------------------------------------------------------------------------------- /joinmarket/src/reportWebVitals.js: -------------------------------------------------------------------------------- 1 | const reportWebVitals = onPerfEntry => { 2 | if (onPerfEntry && onPerfEntry instanceof Function) { 3 | import('web-vitals').then(({ getCLS, getFID, getFCP, getLCP, getTTFB }) => { 4 | getCLS(onPerfEntry); 5 | getFID(onPerfEntry); 6 | getFCP(onPerfEntry); 7 | getLCP(onPerfEntry); 8 | getTTFB(onPerfEntry); 9 | }); 10 | } 11 | }; 12 | 13 | export default reportWebVitals; 14 | -------------------------------------------------------------------------------- /joinmarket/src/components/Wallets.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import Wallet from './Wallet' 3 | const Wallets = ({walletList,onUnlock,onLock,onDisplay}) => { 4 | 5 | return ( 6 | <> 7 |

8 | {walletList.map((wallet,index)=>{ 9 | return 10 | })} 11 | 12 | ) 13 | } 14 | 15 | export default Wallets 16 | -------------------------------------------------------------------------------- /joinmarket/src/components/utils.jsx: -------------------------------------------------------------------------------- 1 | import React, { useState, useEffect, useRef } from 'react'; 2 | 3 | const useInterval = (callback, delay) => { 4 | 5 | const savedCallback = useRef(); 6 | 7 | useEffect(() => { 8 | savedCallback.current = callback; 9 | }, [callback]); 10 | 11 | 12 | useEffect(() => { 13 | function tick() { 14 | savedCallback.current(); 15 | } 16 | if (delay !== null) { 17 | const id = setInterval(tick, delay); 18 | return () => clearInterval(id); 19 | } 20 | }, [delay]); 21 | } 22 | 23 | export default useInterval; -------------------------------------------------------------------------------- /joinmarket/public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "short_name": "React App", 3 | "name": "Create React App Sample", 4 | "icons": [ 5 | { 6 | "src": "favicon.ico", 7 | "sizes": "64x64 32x32 24x24 16x16", 8 | "type": "image/x-icon" 9 | }, 10 | { 11 | "src": "logo192.png", 12 | "type": "image/png", 13 | "sizes": "192x192" 14 | }, 15 | { 16 | "src": "logo512.png", 17 | "type": "image/png", 18 | "sizes": "512x512" 19 | } 20 | ], 21 | "start_url": ".", 22 | "display": "standalone", 23 | "theme_color": "#000000", 24 | "background_color": "#ffffff" 25 | } 26 | -------------------------------------------------------------------------------- /joinmarket/src/components/DisplayUTXOs.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | 3 | const DisplayUTXOs = ({utxoID,utxo}) => { 4 | return ( 5 |
6 |

7 |

8 |

9 | Address: {utxo.address} 10 |

11 | Value(Sats): {utxo.value} 12 |

13 | Confirmations: {utxo.confirmations} 14 |

15 | Mixdepth: {utxo.mixdepth} 16 |

17 |
18 | ) 19 | } 20 | 21 | export default DisplayUTXOs; 22 | 23 | -------------------------------------------------------------------------------- /joinmarket/src/App.css: -------------------------------------------------------------------------------- 1 | .App { 2 | text-align: center; 3 | } 4 | 5 | .App-logo { 6 | height: 40vmin; 7 | pointer-events: none; 8 | } 9 | 10 | @media (prefers-reduced-motion: no-preference) { 11 | .App-logo { 12 | animation: App-logo-spin infinite 20s linear; 13 | } 14 | } 15 | 16 | .App-header { 17 | background-color: #282c34; 18 | min-height: 100vh; 19 | display: flex; 20 | flex-direction: column; 21 | align-items: center; 22 | justify-content: center; 23 | font-size: calc(10px + 2vmin); 24 | color: white; 25 | } 26 | 27 | .App-link { 28 | color: #61dafb; 29 | } 30 | 31 | @keyframes App-logo-spin { 32 | from { 33 | transform: rotate(0deg); 34 | } 35 | to { 36 | transform: rotate(360deg); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /joinmarket/src/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | import './index.css'; 4 | import App from './App'; 5 | import reportWebVitals from './reportWebVitals'; 6 | import 'bootstrap/dist/css/bootstrap.min.css'; 7 | import { setGlobal } from 'reactn'; 8 | // Set an initial global state directly: 9 | setGlobal({ 10 | currentStatusMessage: "loading", 11 | makerStarted: false, 12 | walletName: "(waiting..)", 13 | coinjoinInProcess: false 14 | }); 15 | 16 | ReactDOM.render( 17 | 18 | 19 | , 20 | document.getElementById('root') 21 | ); 22 | 23 | // If you want to start measuring performance in your app, pass a function 24 | // to log results (for example: reportWebVitals(console.log)) 25 | // or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals 26 | reportWebVitals(); 27 | -------------------------------------------------------------------------------- /joinmarket/src/components/Wallet.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import { Button } from './Button' 3 | import {Link} from 'react-router-dom' 4 | import * as rb from 'react-bootstrap' 5 | import './wallet.css' 6 | const Wallet = ({name,onUnlock,onLock,onDisplay}) => { 7 | return ( 8 |
9 |

10 | 11 | 12 | {name} 13 | onUnlock(name)}>Unlock{' '} 14 | Open{' '} 15 | onLock(name)}>Lock 16 | 17 | 18 |
19 | ) 20 | } 21 | 22 | export default Wallet 23 | -------------------------------------------------------------------------------- /joinmarket/src/twitter.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /joinmarket/src/components/homepage.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import * as rb from 'react-bootstrap' 3 | import './Homepage.css' 4 | import { BrowserRouter as Router, Link, Route ,Switch} from 'react-router-dom'; 5 | 6 | const Homepage = () => { 7 | 8 | return ( 9 | <> 10 | 11 |
12 |

Joinmarket

13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | Create Wallet 23 |
24 |
25 | 26 | 27 | Show Wallets 28 | 29 |
30 |
31 | 32 | 33 | ) 34 | } 35 | 36 | export default Homepage 37 | -------------------------------------------------------------------------------- /joinmarket/src/github.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /joinmarket/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "joinmarket", 3 | "version": "0.1.0", 4 | "private": true, 5 | "proxy": "https://localhost:28183", 6 | "dependencies": { 7 | "@ibunker/bitcoin-react": "^0.1.13-cd", 8 | "@testing-library/jest-dom": "^5.11.4", 9 | "@testing-library/react": "^11.1.0", 10 | "@testing-library/user-event": "^12.1.10", 11 | "bootstrap": "^5.1.0", 12 | "moving-letters": "^1.0.1", 13 | "react": "^17.0.2", 14 | "react-bootstrap": "^2.0.0-beta.6", 15 | "react-dom": "^17.0.2", 16 | "react-router-dom": "^5.2.0", 17 | "react-scripts": "4.0.3", 18 | "reactn": "^2.2.7", 19 | "web-vitals": "^1.0.1" 20 | }, 21 | "scripts": { 22 | "start": "react-scripts start", 23 | "build": "react-scripts build", 24 | "test": "react-scripts test", 25 | "eject": "react-scripts eject" 26 | }, 27 | "eslintConfig": { 28 | "extends": [ 29 | "react-app", 30 | "react-app/jest" 31 | ] 32 | }, 33 | "browserslist": { 34 | "production": [ 35 | ">0.2%", 36 | "not dead", 37 | "not op_mini all" 38 | ], 39 | "development": [ 40 | "last 1 chrome version", 41 | "last 1 firefox version", 42 | "last 1 safari version" 43 | ] 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /joinmarket/src/components/createWallet.css: -------------------------------------------------------------------------------- 1 | .heading{ 2 | color:rgb(15, 3, 58); 3 | font-size: 40px; 4 | font-weight: 450; 5 | } 6 | 7 | .form1{ 8 | margin: 0 auto; 9 | background-color: rgb(244, 247, 253); 10 | width: 40%; 11 | padding-top: 40px; 12 | padding-bottom: 40px; 13 | padding-left: 40px; 14 | padding-right: 40px; 15 | border-radius: 10px; 16 | border-width: 3px; 17 | border-style: dashed; 18 | border-color: #e0e3f0; 19 | 20 | } 21 | 22 | .center{ 23 | padding: 40px; 24 | } 25 | 26 | .label{ 27 | text-align: left; 28 | font-size: 20px; 29 | color:rgb(15, 3, 58) 30 | } 31 | 32 | .field{ 33 | padding-top: 20px; 34 | } 35 | 36 | .field-border{ 37 | border-radius: 10px; 38 | border-width: 2px; 39 | border-style: dashed; 40 | border-color: #e0e3f0; 41 | } 42 | 43 | .btn-field{ 44 | padding-top: 50px; 45 | } 46 | 47 | .btncr { 48 | border: none; 49 | border-radius: 2px; 50 | display: block; 51 | text-align: center; 52 | cursor: pointer; 53 | outline: none; 54 | overflow: hidden; 55 | position: relative; 56 | font-weight: 500; 57 | font-size: 20px; 58 | background-color: rgb(244, 247, 253); 59 | padding: 10px 60px; 60 | margin: 0 auto; 61 | box-shadow: 0 5px 15px rgba(0,0,0,0.20); 62 | } 63 | 64 | .btncr span { 65 | position: relative; 66 | z-index: 1; 67 | color:rgb(15, 3, 58) 68 | } 69 | 70 | .btncr:after { 71 | content: ""; 72 | position: absolute; 73 | left: 0; 74 | top: 0; 75 | height: 300%; 76 | width: 130%; 77 | background: #e0e3f0; 78 | -webkit-transition: all .5s ease-in-out; 79 | transition: all .5s ease-in-out; 80 | -webkit-transform: translateX(-98%) translateY(-25%) rotate(45deg); 81 | transform: translateX(-98%) translateY(-25%) rotate(45deg); 82 | } 83 | 84 | .btncr:hover:after { 85 | -webkit-transform: translateX(-9%) translateY(-25%) rotate(45deg); 86 | transform: translateX(-9%) translateY(-25%) rotate(45deg); 87 | } -------------------------------------------------------------------------------- /joinmarket/src/components/receive.css: -------------------------------------------------------------------------------- 1 | .heading{ 2 | color:rgb(15, 3, 58); 3 | font-size: 40px; 4 | font-weight: 450; 5 | } 6 | 7 | .form1{ 8 | margin: 0 auto; 9 | background-color: rgb(244, 247, 253); 10 | width: 60%; 11 | padding-top: 40px; 12 | padding-bottom: 40px; 13 | padding-left: 40px; 14 | padding-right: 40px; 15 | border-radius: 10px; 16 | border-width: 3px; 17 | border-style: dashed; 18 | border-color: #e0e3f0; 19 | 20 | } 21 | 22 | .center{ 23 | padding: 40px; 24 | } 25 | 26 | .label{ 27 | text-align: left; 28 | font-size: 20px; 29 | color:rgb(15, 3, 58) 30 | } 31 | 32 | .field{ 33 | padding-top: 20px; 34 | } 35 | 36 | .field-border{ 37 | border-radius: 10px; 38 | border-width: 2px; 39 | border-style: dashed; 40 | border-color: #e0e3f0; 41 | } 42 | 43 | .btn-field{ 44 | padding-top: 50px; 45 | } 46 | 47 | .btncr { 48 | border: none; 49 | border-radius: 2px; 50 | display: block; 51 | text-align: center; 52 | cursor: pointer; 53 | outline: none; 54 | overflow: hidden; 55 | position: relative; 56 | font-weight: 500; 57 | font-size: 20px; 58 | background-color: rgb(244, 247, 253); 59 | padding: 10px 60px; 60 | margin: 0 auto; 61 | box-shadow: 0 5px 15px rgba(0,0,0,0.20); 62 | } 63 | 64 | .btncr span { 65 | position: relative; 66 | z-index: 1; 67 | color:rgb(15, 3, 58) 68 | } 69 | 70 | .btncr:after { 71 | content: ""; 72 | position: absolute; 73 | left: 0; 74 | top: 0; 75 | height: 300%; 76 | width: 130%; 77 | background: #e0e3f0; 78 | -webkit-transition: all .5s ease-in-out; 79 | transition: all .5s ease-in-out; 80 | -webkit-transform: translateX(-98%) translateY(-25%) rotate(45deg); 81 | transform: translateX(-98%) translateY(-25%) rotate(45deg); 82 | } 83 | 84 | .btncr:hover:after { 85 | -webkit-transform: translateX(-9%) translateY(-25%) rotate(45deg); 86 | transform: translateX(-9%) translateY(-25%) rotate(45deg); 87 | } -------------------------------------------------------------------------------- /joinmarket/src/components/maker.css: -------------------------------------------------------------------------------- 1 | .heading{ 2 | color:rgb(15, 3, 58); 3 | font-size: 40px; 4 | font-weight: 450; 5 | } 6 | 7 | .form1{ 8 | margin: 0 auto; 9 | background-color: rgb(244, 247, 253); 10 | width: 50%; 11 | padding-top: 40px; 12 | padding-bottom: 40px; 13 | padding-left: 40px; 14 | padding-right: 40px; 15 | border-radius: 10px; 16 | border-width: 3px; 17 | border-style: dashed; 18 | border-color: #e0e3f0; 19 | 20 | } 21 | 22 | .coinjoin{ 23 | font-size: 20px; 24 | } 25 | 26 | .center{ 27 | padding: 40px; 28 | } 29 | 30 | .label{ 31 | text-align: left; 32 | font-size: 20px; 33 | color:rgb(15, 3, 58) 34 | } 35 | 36 | .field{ 37 | padding-top: 20px; 38 | } 39 | 40 | .field-border{ 41 | border-radius: 10px; 42 | border-width: 2px; 43 | border-style: dashed; 44 | border-color: #e0e3f0; 45 | } 46 | 47 | .btn-field{ 48 | padding-top: 50px; 49 | } 50 | 51 | .btncr { 52 | border: none; 53 | border-radius: 2px; 54 | display: block; 55 | text-align: center; 56 | cursor: pointer; 57 | outline: none; 58 | overflow: hidden; 59 | position: relative; 60 | font-weight: 500; 61 | font-size: 20px; 62 | background-color: rgb(244, 247, 253); 63 | padding: 10px 60px; 64 | margin: 0 auto; 65 | box-shadow: 0 5px 15px rgba(0,0,0,0.20); 66 | } 67 | 68 | .btncr span { 69 | position: relative; 70 | z-index: 1; 71 | color:rgb(15, 3, 58) 72 | } 73 | 74 | .btncr:after { 75 | content: ""; 76 | position: absolute; 77 | left: 0; 78 | top: 0; 79 | height: 300%; 80 | width: 130%; 81 | background: #e0e3f0; 82 | -webkit-transition: all .5s ease-in-out; 83 | transition: all .5s ease-in-out; 84 | -webkit-transform: translateX(-98%) translateY(-25%) rotate(45deg); 85 | transform: translateX(-98%) translateY(-25%) rotate(45deg); 86 | } 87 | 88 | .btncr:hover:after { 89 | -webkit-transform: translateX(-9%) translateY(-25%) rotate(45deg); 90 | transform: translateX(-9%) translateY(-25%) rotate(45deg); 91 | } -------------------------------------------------------------------------------- /joinmarket/src/components/payment.css: -------------------------------------------------------------------------------- 1 | .heading{ 2 | color:rgb(15, 3, 58); 3 | font-size: 40px; 4 | font-weight: 450; 5 | } 6 | 7 | .form1{ 8 | margin: 0 auto; 9 | background-color: rgb(244, 247, 253); 10 | width: 50%; 11 | padding-top: 40px; 12 | padding-bottom: 40px; 13 | padding-left: 40px; 14 | padding-right: 40px; 15 | border-radius: 10px; 16 | border-width: 3px; 17 | border-style: dashed; 18 | border-color: #e0e3f0; 19 | 20 | } 21 | 22 | .coinjoin{ 23 | font-size: 20px; 24 | } 25 | 26 | .center{ 27 | padding: 40px; 28 | } 29 | 30 | .label{ 31 | text-align: left; 32 | font-size: 20px; 33 | color:rgb(15, 3, 58) 34 | } 35 | 36 | .field{ 37 | padding-top: 20px; 38 | } 39 | 40 | .field-border{ 41 | border-radius: 10px; 42 | border-width: 2px; 43 | border-style: dashed; 44 | border-color: #e0e3f0; 45 | } 46 | 47 | .btn-field{ 48 | padding-top: 50px; 49 | } 50 | 51 | .btncr { 52 | border: none; 53 | border-radius: 2px; 54 | display: block; 55 | text-align: center; 56 | cursor: pointer; 57 | outline: none; 58 | overflow: hidden; 59 | position: relative; 60 | font-weight: 500; 61 | font-size: 20px; 62 | background-color: rgb(244, 247, 253); 63 | padding: 10px 60px; 64 | margin: 0 auto; 65 | box-shadow: 0 5px 15px rgba(0,0,0,0.20); 66 | } 67 | 68 | .btncr span { 69 | position: relative; 70 | z-index: 1; 71 | color:rgb(15, 3, 58) 72 | } 73 | 74 | .btncr:after { 75 | content: ""; 76 | position: absolute; 77 | left: 0; 78 | top: 0; 79 | height: 300%; 80 | width: 130%; 81 | background: #e0e3f0; 82 | -webkit-transition: all .5s ease-in-out; 83 | transition: all .5s ease-in-out; 84 | -webkit-transform: translateX(-98%) translateY(-25%) rotate(45deg); 85 | transform: translateX(-98%) translateY(-25%) rotate(45deg); 86 | } 87 | 88 | .btncr:hover:after { 89 | -webkit-transform: translateX(-9%) translateY(-25%) rotate(45deg); 90 | transform: translateX(-9%) translateY(-25%) rotate(45deg); 91 | } -------------------------------------------------------------------------------- /joinmarket/public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 12 | 18 | 19 | 23 | 24 | 33 | React App 34 | 35 | 36 | 37 |
38 | 48 | 49 | 50 | -------------------------------------------------------------------------------- /joinmarket/src/components/Maker.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import { useHistory } from 'react-router-dom'; 3 | import { useState } from 'react' 4 | import { useGlobal } from 'reactn'; 5 | 6 | const Maker = ({onStart,onStop}) => { 7 | 8 | const [txFee,setTxFee] = useState('') 9 | const [cjfeeAbs,setCjfeeabs] = useState('') 10 | const [cjfeeRel,setCjfeerel] = useState('') 11 | const [orderType,setOrdertype] = useState('') 12 | const [minsize,setMinsize] = useState('') 13 | 14 | 15 | const [makerStarted, setmakerStarted] = useGlobal("makerStarted"); 16 | 17 | const [submitVal,setSubmitVal] = useState('Start Maker Service') 18 | 19 | const history = useHistory(); 20 | 21 | const onSubmit = (e) => { 22 | e.preventDefault() 23 | 24 | 25 | 26 | if(makerStarted === false){ 27 | console.log('b') 28 | if (!cjfeeRel) { 29 | alert('Please add details') 30 | return; 31 | } 32 | onStart(0,0,cjfeeRel,'sw0reloffer',1000); 33 | setCjfeerel('') 34 | alert("Attempting to start the yield generator. Check the status bar for updates."); 35 | setSubmitVal('Stop Maker Service') 36 | 37 | } 38 | else{ 39 | console.log('c') 40 | onStop(); 41 | setSubmitVal('Start Maker Service') 42 | 43 | } 44 | let path = `/display`; 45 | history.push(path); 46 | 47 | 48 | } 49 | return ( 50 |
51 |

Maker Service

52 |
53 | 54 | 55 |

56 | { 57 | makerStarted === false ? 58 | 62 | :'' 63 | } 64 | 65 |

66 | 67 | 68 | 69 |
70 |
71 | ) 72 | } 73 | 74 | export default Maker 75 | -------------------------------------------------------------------------------- /joinmarket/src/logo.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /joinmarket/src/components/CreateWallet.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import { useState } from 'react' 3 | import './createWallet.css' 4 | import * as rb from 'react-bootstrap' 5 | 6 | const CreateWallet = ({onCreate}) => { 7 | 8 | const [wallet,setWallet] = useState('') 9 | const [password,setPassword]=useState('') 10 | 11 | const onSubmit = (e) => { 12 | e.preventDefault() 13 | 14 | if (!wallet || !password) { 15 | alert('Please add details') 16 | return; 17 | } 18 | 19 | onCreate(wallet,password) 20 | setWallet('') 21 | setPassword('') 22 | } 23 | return ( 24 | 25 |
26 | 27 |

28 |
29 | Create Wallet 30 |
31 | 32 |
33 | 34 | 35 | 36 | 37 | 38 | Wallet Name 39 | 40 | 41 | setWallet(e.target.value)}/> 42 | 43 | 44 | 45 | 46 | 47 | 48 | Password 49 | 50 | 51 | setPassword(e.target.value)} /> 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 |
61 | 62 | {/*
63 | 64 | 65 | 69 |

70 | 74 |

75 | 76 | 77 | 78 | 79 |
*/} 80 |
81 | ) 82 | } 83 | 84 | export default CreateWallet 85 | -------------------------------------------------------------------------------- /joinmarket/src/components/DisplayWallet.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import {useState,useEffect} from 'react' 3 | import { Button } from './Button' 4 | import DisplayMixdepth from './DisplayMixdepth' 5 | import DisplayUTXOs from './DisplayUTXOs' 6 | 7 | const DisplayWallet = ({listWalletInfo,onSend,listUTXOs}) => { 8 | const [wallet_info,setWalletInfo] = useState([]) 9 | const [UTXOHistory,setUTXOHistory] = useState({}) 10 | const [showUTXO,setShowUTXO] = useState(false); 11 | // Websocket object with scope of DisplayWallet - we don't initialize 12 | // yet because it auto-opens, and we can only open once 13 | // we have authenticated: 14 | var ws; 15 | useEffect(()=>{ 16 | const name = JSON.parse(sessionStorage.getItem('auth')).name; 17 | const token = JSON.parse(sessionStorage.getItem('auth')).token; 18 | ws = new WebSocket("wss://127.0.0.1:28283"); 19 | ws.onopen = (event) => { 20 | console.log("connected to websocket"); 21 | ws.send(token); 22 | } 23 | ws.onmessage = (event) => { 24 | // For now we only have one message type, 25 | // namely the transaction notification: 26 | // For now, note that since the `getUtxos` function 27 | // is called on every render of the display page, 28 | // we don't need to somehow use this data other 29 | // than as some kind of popup/status bar notifier. 30 | // In future it might be possible to use the detailed 31 | // transaction deserialization passed in this notification, 32 | // for something. 33 | var wsdata = JSON.parse(event.data); 34 | alert("Websocket sent: " + wsdata.txid); 35 | } 36 | const getWalletInfo = async()=>{ 37 | const wallet_info = await listWalletInfo(name); 38 | console.log(wallet_info); 39 | setWalletInfo(wallet_info); 40 | } 41 | 42 | const getUTXOs = async()=>{ 43 | const utxos = await listUTXOs(); 44 | setUTXOHistory(utxos) 45 | console.log(utxos) 46 | } 47 | 48 | getWalletInfo(); 49 | getUTXOs(); 50 | },[]) 51 | 52 | return ( 53 |
54 | Wallet Details 55 |

56 | {wallet_info.map((walletInfo,index)=>{ 57 | return 58 | })} 59 |

60 | 61 |

62 | 63 | { 64 | showUTXO? 65 | Object.entries(UTXOHistory).map(([key, val])=> 66 | 67 | ) 68 | 69 | : "" 70 | } 71 |
72 | ) 73 | } 74 | 75 | export default DisplayWallet 76 | -------------------------------------------------------------------------------- /joinmarket/README.md: -------------------------------------------------------------------------------- 1 | # Getting Started with Create React App 2 | 3 | This project was bootstrapped with [Create React App](https://github.com/facebook/create-react-app). 4 | 5 | ## Available Scripts 6 | 7 | In the project directory, you can run: 8 | 9 | ### `yarn start` 10 | 11 | Runs the app in the development mode.\ 12 | Open [http://localhost:3000](http://localhost:3000) to view it in the browser. 13 | 14 | The page will reload if you make edits.\ 15 | You will also see any lint errors in the console. 16 | 17 | ### `yarn test` 18 | 19 | Launches the test runner in the interactive watch mode.\ 20 | See the section about [running tests](https://facebook.github.io/create-react-app/docs/running-tests) for more information. 21 | 22 | ### `yarn build` 23 | 24 | Builds the app for production to the `build` folder.\ 25 | It correctly bundles React in production mode and optimizes the build for the best performance. 26 | 27 | The build is minified and the filenames include the hashes.\ 28 | Your app is ready to be deployed! 29 | 30 | See the section about [deployment](https://facebook.github.io/create-react-app/docs/deployment) for more information. 31 | 32 | ### `yarn eject` 33 | 34 | **Note: this is a one-way operation. Once you `eject`, you can’t go back!** 35 | 36 | If you aren’t satisfied with the build tool and configuration choices, you can `eject` at any time. This command will remove the single build dependency from your project. 37 | 38 | Instead, it will copy all the configuration files and the transitive dependencies (webpack, Babel, ESLint, etc) right into your project so you have full control over them. All of the commands except `eject` will still work, but they will point to the copied scripts so you can tweak them. At this point you’re on your own. 39 | 40 | You don’t have to ever use `eject`. The curated feature set is suitable for small and middle deployments, and you shouldn’t feel obligated to use this feature. However we understand that this tool wouldn’t be useful if you couldn’t customize it when you are ready for it. 41 | 42 | ## Learn More 43 | 44 | You can learn more in the [Create React App documentation](https://facebook.github.io/create-react-app/docs/getting-started). 45 | 46 | To learn React, check out the [React documentation](https://reactjs.org/). 47 | 48 | ### Code Splitting 49 | 50 | This section has moved here: [https://facebook.github.io/create-react-app/docs/code-splitting](https://facebook.github.io/create-react-app/docs/code-splitting) 51 | 52 | ### Analyzing the Bundle Size 53 | 54 | This section has moved here: [https://facebook.github.io/create-react-app/docs/analyzing-the-bundle-size](https://facebook.github.io/create-react-app/docs/analyzing-the-bundle-size) 55 | 56 | ### Making a Progressive Web App 57 | 58 | This section has moved here: [https://facebook.github.io/create-react-app/docs/making-a-progressive-web-app](https://facebook.github.io/create-react-app/docs/making-a-progressive-web-app) 59 | 60 | ### Advanced Configuration 61 | 62 | This section has moved here: [https://facebook.github.io/create-react-app/docs/advanced-configuration](https://facebook.github.io/create-react-app/docs/advanced-configuration) 63 | 64 | ### Deployment 65 | 66 | This section has moved here: [https://facebook.github.io/create-react-app/docs/deployment](https://facebook.github.io/create-react-app/docs/deployment) 67 | 68 | ### `yarn build` fails to minify 69 | 70 | This section has moved here: [https://facebook.github.io/create-react-app/docs/troubleshooting#npm-run-build-fails-to-minify](https://facebook.github.io/create-react-app/docs/troubleshooting#npm-run-build-fails-to-minify) 71 | -------------------------------------------------------------------------------- /joinmarket/src/components/Receive.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import { useState, useEffect } from 'react' 3 | import { BitcoinQR } from '@ibunker/bitcoin-react'; 4 | import '@ibunker/bitcoin-react/dist/index.css'; 5 | import { useLocation } from "react-router-dom"; 6 | import * as rb from 'react-bootstrap' 7 | import './receive.css' 8 | 9 | const Receive = ({onReceive}) => { 10 | const location = useLocation() 11 | const [new_address, setNewAddress] = useState('') 12 | 13 | const getAddress = async(mixdepth)=>{ 14 | //update request with token if backend updated 15 | let authData = JSON.parse(sessionStorage.getItem('auth')); 16 | let token = "Bearer "+authData.token; 17 | let name = authData.name; 18 | const res = await fetch(`/api/v1/wallet/${name}/address/new/${mixdepth}`,{ 19 | method:'GET', 20 | headers: { 21 | 'Content-type': 'application/json', 22 | 'Authorization':token 23 | }, 24 | }); 25 | const data = await res.json(); 26 | console.log(data) 27 | return (data[0].address); 28 | 29 | } 30 | 31 | useEffect(()=>{ 32 | 33 | const getNewAddress = async(account) => { 34 | const temp1 = parseInt(account,10) 35 | const temp = await getAddress(temp1) 36 | //window.alert(temp1) 37 | setNewAddress(temp) 38 | return 39 | } 40 | 41 | getNewAddress(location.state.account_no); 42 | },[]) 43 | 44 | const [temp_address, setTempAddress] = useState('') 45 | const [amount, setAmount] = useState('') 46 | 47 | const onSubmit = (e) => { 48 | e.preventDefault() 49 | 50 | if (!new_address) { 51 | alert('Please add the address') 52 | return 53 | } 54 | 55 | setTempAddress(new_address) 56 | 57 | } 58 | 59 | return ( 60 |
61 | 62 |

63 |
64 | Recieve Funds 65 |
66 | 67 |
68 | 69 | 70 | 71 | 72 | 73 | Address 74 | 75 | 76 | setNewAddress(e.target.value)}/> 77 | 78 | 79 | 80 | 81 | 82 | 83 | Amount(BTC) 84 | 85 | 86 | setAmount(e.target.value)}/> 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | {temp_address.length > 0? ( 95 | ):("")} 102 | 103 | 104 | 105 | 106 | 107 |
108 |
109 | ) 110 | } 111 | 112 | export default Receive 113 | -------------------------------------------------------------------------------- /joinmarket/src/components/Payment.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import { useState } from 'react' 3 | import { useLocation } from "react-router-dom" 4 | import './payment.css' 5 | import * as rb from 'react-bootstrap' 6 | 7 | const Payment = ({onPayment,onCoinjoin}) => { 8 | const location = useLocation() 9 | const [destination, setDestination] = useState('') 10 | const [amount, setAmount] = useState('') 11 | const [mixdepth, setMixdepth] = useState(location.state.account_no) 12 | const [counterparties,setcounterparties] = useState(''); 13 | const [isCoinjoin,setisCoinjoin] = useState(false); 14 | 15 | const onSubmit = (e) => { 16 | e.preventDefault() 17 | 18 | if (!amount || !mixdepth || !destination) { 19 | alert('Please add details') 20 | return 21 | } 22 | //maybe add await here 23 | //if normal payment 24 | if(isCoinjoin===false){ 25 | let wallet =JSON.parse(sessionStorage.getItem('auth')).name; 26 | onPayment(wallet,mixdepth,amount,destination); 27 | } 28 | //coinjoin 29 | else{ 30 | if(!counterparties){ 31 | alert("Please set counterparties to a non zero number"); 32 | 33 | return; 34 | } 35 | else{ 36 | onCoinjoin(mixdepth,amount,counterparties,destination); 37 | alert("Coinjoin in progress"); 38 | } 39 | 40 | } 41 | 42 | setcounterparties(''); 43 | setMixdepth(''); 44 | setAmount(''); 45 | setDestination(''); 46 | setisCoinjoin(false); 47 | 48 | 49 | 50 | 51 | } 52 | 53 | return ( 54 |
55 | 56 |

57 |
58 | Send Payment 59 |
60 | 61 |
62 | 63 | 64 | 65 | 66 | 67 | Receiver address: 68 | 69 | 70 | setDestination(e.target.value)}/> 71 | 72 | 73 | 74 | 75 | 76 | 77 | Account 78 | 79 | 80 | setMixdepth(e.target.value)} readOnly={true}/> 81 | 82 | 83 | 84 | 85 | 86 | 87 | Amount(SATS) 88 | 89 | 90 | setAmount(e.target.value)}/> 91 | 92 | 93 | 94 | 95 |

96 |

97 |
98 | Do you want to do a coinjoin? 99 |

100 | Yes setisCoinjoin(true)} /> 101 |

102 | No setisCoinjoin(false)}/> 103 |

104 |
105 | 106 | 107 | { 108 | isCoinjoin? 109 |
110 | 111 | 112 | Counterparties 113 | 114 | 115 | setcounterparties(e.target.value)}/> 116 | 117 | 118 |
119 | : 120 | 121 | "" 122 | 123 | } 124 | 125 | 126 | 127 | 128 |
129 |
130 |
131 |
132 | ) 133 | } 134 | 135 | export default Payment 136 | -------------------------------------------------------------------------------- /joinmarket/src/components/DisplayMixdepth.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import { Button } from './Button' 3 | import './displayMixdepth.css' 4 | import { BrowserRouter as Router, Link, Route ,Switch} from 'react-router-dom'; 5 | import * as rb from 'react-bootstrap' 6 | 7 | const DisplayMixdepth = ({walletInfo}) => { 8 | 9 | const accounts = [] 10 | 11 | for (const account_info of walletInfo.accounts){ 12 | accounts.push(account_info) 13 | } 14 | 15 | return ( 16 |
17 | Total Balance: {walletInfo.total_balance} BTC 18 |

19 | Maker Service 20 |

21 | {accounts.map((account, index) => ( 22 | 23 |
24 | 25 | 26 | 27 | 28 |
29 | 30 | 31 | 32 | 33 | Account {accounts[index].account} 34 | 35 | 36 | 37 | Balance: {accounts[index].account_balance} BTC 38 | 39 | 40 | 41 | 42 | Send {' '} 43 | 44 | 45 | Receive 46 | 47 | 48 | 49 | 50 | 51 |
52 |
53 | 54 | 55 | 56 | 57 | External Addresses Balance: {accounts[index].branches[0].balance} BTC 58 |
59 | Extended Pubkey : {accounts[index].branches[0].branch.split("\t").pop()} 60 |
61 | 62 | {accounts[index].branches[0].entries.map((user, i) => ( 63 |
64 | 65 | 66 |
67 | {accounts[index].branches[0].entries[i].labels} 68 |
69 | 70 | {accounts[index].branches[0].entries[i].address} {' '} 71 | 72 |
73 | amount: {accounts[index].branches[0].entries[i].amount} 74 |
75 |
76 |
77 |
78 |
79 | ))} 80 |
81 |
82 | 83 | Internal Addresses Balance: {accounts[index].branches[1].balance} BTC 84 | 85 | {accounts[index].branches[1].entries.map((user, j) => ( 86 |
87 | 88 | 89 | {accounts[index].branches[0].entries[j].address} {' '} {accounts[index].branches[0].entries[j].labels} 90 | 91 |
92 | amount: {accounts[index].branches[0].entries[j].amount} 93 |
94 |
95 |
96 |
97 |
98 | ))} 99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 | ))} 107 |
108 | ) 109 | } 110 | 111 | export default DisplayMixdepth 112 | -------------------------------------------------------------------------------- /joinmarket/src/App.js: -------------------------------------------------------------------------------- 1 | import './App.css'; 2 | import '@ibunker/bitcoin-react/dist/index.css'; 3 | import {useState,useEffect} from 'react' 4 | import Wallets from './components/Wallets'; 5 | import Payment from './components/Payment'; 6 | import CreateWallet from './components/CreateWallet'; 7 | import Homepage from './components/homepage'; 8 | import Maker from './components/Maker'; 9 | import Receive from './components/Receive'; 10 | import DisplayWallet from './components/DisplayWallet' 11 | import * as rb from 'react-bootstrap'; 12 | import github_logo from './github.svg' 13 | import twitter_logo from './twitter.svg' 14 | import useInterval from './components/utils' 15 | import { BrowserRouter as Router, Route ,Switch} from 'react-router-dom'; 16 | import { useGlobal } from 'reactn'; 17 | 18 | function App() { 19 | 20 | const [walletList,setWalletList] = useState([]) 21 | 22 | const [makerStarted, setmakerStarted] = useGlobal("makerStarted"); 23 | const [walletName, setWalletName] = useGlobal("walletName"); 24 | const [coinjoinInProcess, setCoinjoinInProcess] = useGlobal("coinjoinInProcess"); 25 | const [currentStatusMessage, setCurrentStatusMessage] = useGlobal("currentStatusMessage"); 26 | 27 | const listWallets = async()=>{ 28 | const res = await fetch('/api/v1/wallet/all'); 29 | const data = await res.json(); 30 | const walletList = data[0].wallets; 31 | return walletList; 32 | } 33 | const resetWalletSessionStorage = async()=>{ 34 | sessionStorage.clear(); 35 | setWalletName("No wallet loaded"); 36 | setmakerStarted(false); 37 | setCoinjoinInProcess(false); 38 | } 39 | 40 | function getCurrentStatusMessage(){ 41 | return "Wallet: " + walletName + ", Yg started: " + makerStarted + ", Coinjoin in process: " + coinjoinInProcess; 42 | } 43 | 44 | useInterval(() => { 45 | const sessionClear = async()=>{ 46 | 47 | try{ 48 | const res = await fetch('/api/v1/session',{ 49 | method:"GET", 50 | }); 51 | 52 | const data = await res.json(); 53 | if(data[0].session===false){ 54 | console.log("no wallet in backend"); 55 | // This status requires us to clear, especially 56 | // the auth state, so we just reset everything: 57 | resetWalletSessionStorage(); 58 | return; 59 | } 60 | console.log("backend alive and wallet loaded"); 61 | console.log("maker status: " + data[0].maker_running); 62 | if (data[0].maker_running === true) { 63 | setmakerStarted(true); 64 | } 65 | else { 66 | setmakerStarted(false); 67 | } 68 | setWalletName(data[0].wallet_name); 69 | 70 | if (data[0].coinjoin_in_process === true){ 71 | setCoinjoinInProcess(true); 72 | } 73 | else { 74 | setCoinjoinInProcess(false); 75 | } 76 | setCurrentStatusMessage(getCurrentStatusMessage()); 77 | } 78 | 79 | catch(e){ 80 | console.log("test") 81 | alert("Lost connection to backend! Please restart the backend server."); 82 | sessionStorage.clear(); 83 | } 84 | } 85 | sessionClear(); 86 | 87 | }, 8*1000); 88 | 89 | useEffect(()=>{ 90 | 91 | const getWallets = async()=>{ 92 | const wallets = await listWallets(); 93 | console.log(wallets); 94 | setWalletList(wallets); 95 | } 96 | 97 | getWallets(); 98 | 99 | },[]) 100 | 101 | 102 | const unlockWallet = async (name)=>{ 103 | 104 | let authData =JSON.parse(sessionStorage.getItem('auth')); 105 | console.log(authData) 106 | //if unlocking same wallet 107 | if(authData && authData.login===true && authData.name===name){ 108 | alert(name+" is already unlocked") 109 | return; 110 | } 111 | //if unlocking another wallet while one is already unlocked 112 | else if(authData && authData.login===true && authData.name!==name){ 113 | alert(authData.name+" is currently in use, please lock it first"); 114 | return; 115 | } 116 | 117 | else{ 118 | try{ 119 | var passphrase = prompt("Enter the passphrase for " + name); 120 | const res = await fetch(`/api/v1/wallet/${name}/unlock`,{ 121 | method:'POST', 122 | headers: { 123 | 'Content-type': 'application/json', 124 | }, 125 | body: JSON.stringify({"password": passphrase}), 126 | }) 127 | const data = await res.json(); 128 | const token = data[0].token; 129 | sessionStorage.setItem('auth',JSON.stringify({ 130 | login:true, 131 | token:token, 132 | name:name 133 | })) 134 | 135 | } 136 | 137 | catch(e){ 138 | alert("Something went wrong,please try again!") 139 | } 140 | 141 | } 142 | } 143 | 144 | const lockWallet = async(name)=>{ 145 | let authData =JSON.parse(sessionStorage.getItem('auth')); 146 | if(!authData || authData.login===false || authData.name!==name){ 147 | alert("Please unlock "+name+" first") 148 | return; 149 | } 150 | 151 | try{ 152 | let token = "Bearer "+authData.token 153 | const res = await fetch(`/api/v1/wallet/${name}/lock`,{ 154 | method:"GET", 155 | headers:{ 156 | 'Authorization':token 157 | } 158 | }); 159 | sessionStorage.setItem('auth',JSON.stringify({ 160 | login:false, 161 | token:'', 162 | name:'' 163 | 164 | })) 165 | const data = await res.json(); 166 | console.log(data); 167 | alert("locked wallet succesfully") 168 | } 169 | catch(e){ 170 | alert("Error while locking.") 171 | } 172 | 173 | } 174 | 175 | const listWalletInfo = async(name)=>{ 176 | let authData =JSON.parse(sessionStorage.getItem('auth')); 177 | let token = "Bearer "+authData.token 178 | const res = await fetch(`/api/v1/wallet/${name}/display`,{ 179 | method:"GET", 180 | headers:{ 181 | 'Authorization':token 182 | } 183 | }); 184 | const data = await res.json(); 185 | const balance = data[0].walletinfo.total_balance; 186 | const mix_depths = data[0].walletinfo.accounts; 187 | const wallet_info={} 188 | wallet_info['balance'] = balance; 189 | wallet_info[mix_depths[0].account] = mix_depths[0].account_balance 190 | wallet_info[mix_depths[1].account] = mix_depths[1].account_balance 191 | wallet_info[mix_depths[2].account] = mix_depths[2].account_balance 192 | wallet_info[mix_depths[3].account] = mix_depths[3].account_balance 193 | wallet_info[mix_depths[4].account] = mix_depths[4].account_balance 194 | 195 | return [data[0].walletinfo]; 196 | } 197 | 198 | const displayWallet = async(name)=>{ 199 | 200 | let authData =JSON.parse(sessionStorage.getItem('auth')); 201 | if(authData.login===false || authData.name!==name){ 202 | alert("Please unlock "+name+" first") 203 | return; 204 | } 205 | let token = "Bearer "+authData.token 206 | const res = await fetch(`/api/v1/wallet/${name}/display`,{ 207 | method:"GET", 208 | headers:{ 209 | 'Authorization':token 210 | } 211 | }); 212 | const data = await res.json(); 213 | console.log(data[0].walletinfo); 214 | const wallet_name = name 215 | const balance = data[0].walletinfo.total_balance; 216 | const mix_depths = data[0].walletinfo.accounts; 217 | const wallet_info={} 218 | wallet_info['balance'] = balance; 219 | wallet_info[mix_depths[0].account] = mix_depths[0].account_balance 220 | wallet_info[mix_depths[1].account] = mix_depths[1].account_balance 221 | wallet_info[mix_depths[2].account] = mix_depths[2].account_balance 222 | wallet_info[mix_depths[3].account] = mix_depths[3].account_balance 223 | wallet_info[mix_depths[4].account] = mix_depths[4].account_balance 224 | console.log(wallet_info) 225 | return wallet_info; 226 | } 227 | 228 | const createWallet = async(name,password)=>{ 229 | let authData =JSON.parse(sessionStorage.getItem('auth')); 230 | if(authData===null || authData.login===false){ 231 | try{ 232 | const res = await fetch(`/api/v1/wallet/create`,{ 233 | method:'POST', 234 | headers: { 235 | 'Content-type': 'application/json', 236 | }, 237 | body: JSON.stringify({"password":password,"walletname":name,"wallettype":"sw"}), 238 | }) 239 | 240 | const data = await res.json(); 241 | 242 | alert("Wallet created succesfully") 243 | //figure out a safer way to show the seedphrase 244 | alert(data[0].seedphrase) 245 | const token = data[0].token; 246 | sessionStorage.setItem('auth',JSON.stringify({ 247 | login:true, 248 | token:token, 249 | name:name 250 | })) 251 | } 252 | catch(e){ 253 | //some other error occurs where wallet is not created 254 | alert("Unexpected error! PLease try again") 255 | } 256 | } 257 | else{ 258 | alert(authData.name +" is in use! Please lock it first.") 259 | } 260 | 261 | } 262 | 263 | 264 | const makePayment = async(name,mixdepth,amountSats,destination)=>{ 265 | let authData =JSON.parse(sessionStorage.getItem('auth')); 266 | if(authData!=null && authData.login===true){ 267 | try{ 268 | let token = "Bearer "+authData.token 269 | const res = await fetch(`/api/v1/wallet/${name}/taker/direct-send`,{ 270 | method:'POST', 271 | headers: { 272 | 'Content-type': 'application/json', 273 | 'Authorization':token 274 | }, 275 | body: JSON.stringify({ 276 | "mixdepth": mixdepth, 277 | "amount_sats": amountSats, 278 | "destination": destination 279 | } 280 | 281 | ), 282 | }) 283 | const data = await res.json(); 284 | console.log(data); 285 | alert("Payment Succesful!") 286 | } 287 | catch(e){ 288 | alert("Error while processing payment!") 289 | } 290 | 291 | 292 | } 293 | else{ 294 | alert("please unlock wallet first") 295 | } 296 | } 297 | 298 | //route for frontend 299 | 300 | const doCoinjoin = async(mixdepth,amount,counterparties,destination)=>{ 301 | try{ 302 | console.log("hellooo") 303 | let authData = JSON.parse(sessionStorage.getItem('auth')); 304 | 305 | if(!authData|| authData.login===false || authData.name===''){ 306 | return; 307 | } 308 | 309 | let token = "Bearer "+authData.token; 310 | let name = authData.name; 311 | const res = await fetch(`/api/v1/wallet/${name}/taker/coinjoin`,{ 312 | method:'POST', 313 | headers: { 314 | 'Content-type': 'application/json', 315 | 'Authorization':token 316 | }, 317 | body: JSON.stringify({ 318 | 319 | "mixdepth": mixdepth, 320 | "amount": amount, 321 | "counterparties": counterparties, 322 | "destination":destination 323 | } 324 | 325 | ), 326 | }) 327 | const data = await res.json(); 328 | console.log(data); 329 | alert("Coinjoin in Progress!") 330 | 331 | } 332 | catch(e){ 333 | return; 334 | } 335 | } 336 | 337 | const startMakerService = async(txfee,cjfee_a,cjfee_r,ordertype,minsize)=>{ 338 | let authData =JSON.parse(sessionStorage.getItem('auth')); 339 | 340 | if(!authData|| authData.login===false || authData.name===''){ 341 | alert("Please unlock a wallet first") 342 | return; 343 | } 344 | let name = authData.name 345 | try{ 346 | let token = "Bearer "+authData.token 347 | const res = await fetch(`/api/v1/wallet/${name}/maker/start`,{ 348 | method:"POST", 349 | headers:{ 350 | 'Authorization':token 351 | }, 352 | body: JSON.stringify({ 353 | "txfee":txfee, 354 | "cjfee_a":cjfee_a, 355 | "cjfee_r":cjfee_r, 356 | "ordertype":ordertype, 357 | "minsize":minsize 358 | } 359 | 360 | ), 361 | }); 362 | 363 | const data = await res.json(); 364 | console.log(data); 365 | } 366 | 367 | catch(e){ 368 | alert("Error while starting service!") 369 | } 370 | 371 | } 372 | 373 | const stopMakerService= async()=>{ 374 | let authData =JSON.parse(sessionStorage.getItem('auth')); 375 | if(authData===null ||authData.login===false || authData.name===''){ 376 | alert('Wallet needs to be unlocked') 377 | return; 378 | } 379 | try{ 380 | let name = authData.name 381 | let token = "Bearer "+authData.token 382 | const res = await fetch(`/api/v1/wallet/${name}/maker/stop`,{ 383 | method:"GET", 384 | headers:{ 385 | 'Authorization':token 386 | }, 387 | }) 388 | const data = await res.json(); 389 | console.log(data); 390 | alert("Maker service stopped") 391 | } 392 | 393 | catch(e){ 394 | alert("Error while stopping service!") 395 | } 396 | } 397 | 398 | const getUTXOs = async()=>{ 399 | try{ 400 | let authData =JSON.parse(sessionStorage.getItem('auth')); 401 | let token = "Bearer "+authData.token 402 | if(!authData|| authData.login===false || authData.name===''){ 403 | return; 404 | } 405 | let name = authData.name; 406 | const res = await fetch(`/api/v1/wallet/${name}/utxos`,{ 407 | method:"GET", 408 | headers:{ 409 | 'Authorization':token 410 | }, 411 | }); 412 | const data = await res.json(); 413 | return data[0].utxos; 414 | } 415 | catch(e){ 416 | return; 417 | } 418 | } 419 | 420 | 421 | return ( 422 | 423 |
424 | 425 | 426 | 427 | 428 | Joinmarket 429 | 430 | 431 | 432 | Docs 433 | Features 434 | About 435 | 436 | 437 | 438 | github logo 445 | 446 | 447 | twitter logo 454 | 455 | 456 | 457 | 458 | 459 | {getCurrentStatusMessage()} 460 | 461 | 462 | 463 |

464 | 465 | 466 | ( 470 | <> 471 | 472 | 473 | )} 474 | /> 475 | 476 | ( 480 | <> 481 | 482 | 483 | )} 484 | /> 485 | 486 | 487 | ( 488 | <> 489 | 490 | 491 | )} 492 | /> 493 | 494 | ( 495 | <> 496 | 497 | 498 | )} 499 | /> 500 | 501 | ( 502 | <> 503 | 504 | 505 | )} 506 | /> 507 | ( 508 | <> 509 | 510 | 511 | )} 512 | /> 513 | ( 514 | <> 515 | 516 | 517 | )} 518 | /> 519 | 520 | {" "} 521 | 522 |
523 |
524 | 525 | 526 | ); 527 | } 528 | 529 | export default App; --------------------------------------------------------------------------------