Skip to content
This repository has been archived by the owner on Apr 28, 2023. It is now read-only.

Commit

Permalink
feat: add reverse swap (#49)
Browse files Browse the repository at this point in the history
  • Loading branch information
michael1011 authored Jan 14, 2019
1 parent 1fa26e9 commit d7b2449
Show file tree
Hide file tree
Showing 24 changed files with 3,764 additions and 967 deletions.
4,030 changes: 3,124 additions & 906 deletions package-lock.json

Large diffs are not rendered by default.

11 changes: 6 additions & 5 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,16 +27,17 @@
"axios": "^0.18.0",
"bignumber.js": "^8.0.1",
"bitcoinjs-lib": "^4.0.2",
"boltz-core": "0.0.3",
"boltz-core": "^0.0.5",
"eventsource": "^1.0.7",
"prop-types": "^15.6.2",
"qrious": "^4.0.2",
"react": "^16.7.0",
"react-dom": "^16.7.0",
"react-icons": "^3.2.2",
"react-icons": "^3.3.0",
"react-jss": "^8.6.1",
"react-loader-spinner": "^2.3.0",
"react-redux": "^5.1.1",
"react-scripts": "2.1.1",
"react-scripts": "^2.1.3",
"redux": "^4.0.1",
"redux-logger": "^3.0.6",
"redux-thunk": "^2.3.0"
Expand All @@ -47,8 +48,8 @@
"eslint-config-google": "^0.11.0",
"eslint-config-prettier": "^3.3.0",
"eslint-plugin-html": "^5.0.0",
"eslint-plugin-prettier": "^3.0.0",
"eslint-plugin-react": "^7.11.1",
"eslint-plugin-prettier": "^3.0.1",
"eslint-plugin-react": "^7.12.3",
"prettier": "^1.15.3"
}
}
1 change: 1 addition & 0 deletions src/action/navigation/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ class Navigation {

goHome = () => navAction(routes.home);
goSwap = () => navAction(routes.swap);
goReverseSwap = () => navAction(routes.reverseSwap);
goSwapConfirm = () => navAction(routes.swapConfirm);
goSwapDownloadRefund = () => navAction(routes.swapDownloadRefund);
goSwapDone = () => navAction(routes.swapDone);
Expand Down
26 changes: 13 additions & 13 deletions src/components/controls/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import injectSheet from 'react-jss';
import PropTypes from 'prop-types';
import View from '../view';
import { MdArrowForward } from 'react-icons/md';
import Loader from 'react-loader-spinner';

const styles = theme => ({
wrapper: {
Expand All @@ -20,27 +21,27 @@ const styles = theme => ({
width: '30px',
color: theme.colors.white,
},
spinner: {
marginRight: '20px',
},
});

const Controls = ({
classes,
text,
onPress,
loading,
loadingText,
loadingStyle,
}) => {
const Controls = ({ classes, text, onPress, loading, loadingText }) => {
return (
<View
className={classes.wrapper}
onClick={loading ? null : () => onPress()}
>
<View className={classes.controls}>
<h1 className={loading ? loadingStyle : classes.text}>
{loading ? loadingText : text}
</h1>
<h1 className={classes.text}>{loading ? loadingText : text}</h1>
</View>
<MdArrowForward className={classes.nextIcon} />
{loading ? (
<View className={classes.spinner}>
<Loader type="TailSpin" color="#fff" height={50} width={50} />
</View>
) : (
<MdArrowForward className={classes.nextIcon} />
)}
</View>
);
};
Expand All @@ -51,7 +52,6 @@ Controls.propTypes = {
onPress: PropTypes.func,
loading: PropTypes.bool,
loadingText: PropTypes.string,
loadingStyle: PropTypes.string,
};

export default injectSheet(styles)(Controls);
2 changes: 1 addition & 1 deletion src/components/dropzone/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ class DropZone extends React.Component {
}
}

DropZone.protoTypes = {
DropZone.propTypes = {
className: PropTypes.string,
children: PropTypes.children,
style: PropTypes.object,
Expand Down
67 changes: 59 additions & 8 deletions src/components/swaptab/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -79,22 +79,59 @@ const styles = theme => ({
});

class SwapTab extends React.Component {
baseAsset = {};
quoteAsset = {};

constructor(props) {
super(props);

this.state = {
error: false,
base: 'LTC',
quote: 'BTC',
quote: 'BTC',
baseAmount: MIN,
quoteAmount: 0,
};
}

updateAssets = (isBase, symbol, isLightning) => {
if (isBase) {
this.baseAsset = {
symbol,
isLightning,
};
} else {
this.quoteAsset = {
symbol,
isLightning,
};
}
};

parseBoltSuffix = (entry, isBase) => {
const index = entry.lastIndexOf('⚡');
const isLightning = index !== -1;

const symbol = isLightning ? entry.substr(0, index - 1) : entry;

this.updateAssets(isBase, symbol, isLightning);

return symbol;
};

getRate = () => {
return this.props.rates[
`${this.parseBoltSuffix(this.state.base, true)}/${this.parseBoltSuffix(
this.state.quote,
false
)}`
];
};

componentDidMount = () => {
this.setState(
{
rate: this.props.rates[`${this.state.base}/${this.state.quote}`],
rate: this.getRate(),
},
() => this.updateQuoteAmount(this.state.baseAmount)
);
Expand All @@ -106,9 +143,20 @@ class SwapTab extends React.Component {
prevState.base !== this.state.base ||
prevState.quote !== this.state.quote
) {
this.setState({
rate: this.props.rates[`${this.state.base}/${this.state.quote}`],
});
const rate = this.getRate();

// Swapping from chain to chain or from Lightning to Lightning is not supported right now
if (this.baseAsset.isLightning !== this.quoteAsset.isLightning) {
this.setState({
rate,
error: false,
});
} else {
this.setState({
rate: undefined,
error: true,
});
}
}
};

Expand All @@ -118,7 +166,7 @@ class SwapTab extends React.Component {

updateBaseAmount = quoteAmount => {
const rate = new BigNumber(this.state.rate.rate);
const newBaseAmount = new BigNumber(quoteAmount).dividedBy(rate).toNumber();
const newBaseAmount = new BigNumber(quoteAmount).dividedBy(rate).toFixed(8);
const error = !this.checkBaseAmount(newBaseAmount);
this.setState({
quoteAmount: Number.parseFloat(quoteAmount),
Expand All @@ -144,14 +192,17 @@ class SwapTab extends React.Component {
if (error === false && this.rate !== 'Not found') {
const state = {
...this.state,
base: this.baseAsset.symbol,
quote: this.quoteAsset.symbol,
isReverseSwap: this.baseAsset.isLightning,
pair: rate.pair,
};

this.props.onPress(state);
}
};

getRate = () => {
parseRate = () => {
const rate = this.state.rate;

if (rate) {
Expand All @@ -171,7 +222,7 @@ class SwapTab extends React.Component {
<InfoText title="Min amount:" text={`${MIN}`} />
<InfoText title="Max amount:" text={`${MAX}`} />
<InfoText title="Fee:" text={'0'} />
<InfoText title="Rate:" text={`${this.getRate(rates)}`} />
<InfoText title="Rate:" text={`${this.parseRate(rates)}`} />
</View>
<View className={classes.options}>
<View className={classes.select}>
Expand Down
1 change: 1 addition & 0 deletions src/components/view/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ View.propTypes = {
style: PropTypes.object,
className: PropTypes.string,
otherProps: PropTypes.array,
inputRef: PropTypes.string,
};

export default View;
12 changes: 11 additions & 1 deletion src/constants/actions/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,19 @@ export const COMPLETE_SWAP = 'COMPLETE_SWAP';
export const INIT_SWAP = 'INIT_SWAP';
export const SET_SWAP_INVOICE = 'SET_SWAP_INVOICE';
export const SET_SWAP_STATUS = 'SET_SWAP_STATUS';
export const SWAP_REQUEST = 'REQUEST_SWAP';
export const SWAP_REQUEST = 'SWAP_REQUEST';
export const SWAP_RESPONSE = 'SWAP_RESPONSE';

/**
* Reverse Swap actions
*/
export const COMPLETE_REVERSE_SWAP = 'COMPLETE_REVERSE_SWAP';
export const INIT_REVERSE_SWAP = 'INIT_REVERSE_SWAP';
export const SET_REVERSE_SWAP_ADDRESS = 'SET_REVERSE_SWAP_ADDRESS';
export const SET_REVERSE_SWAP_STATUS = 'SET_REVERSE_SWAP_STATUS';
export const REVERSE_SWAP_REQUEST = 'REVERSE_SWAP_REQUEST';
export const REVERSE_SWAP_RESPONSE = 'REVERSE_SWAP_RESPONSE';

/**
* Refund actions
*/
Expand Down
5 changes: 5 additions & 0 deletions src/constants/routes/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,11 @@ export const swapConfirm = 'SwapConfirm';
export const swapDownloadRefund = 'SwapDownloadRefund';
export const swapDone = 'SwapDone';

/**
* Reverse Swap routes
*/
export const reverseSwap = 'ReverseSwap';

/**
* Refund routes
*/
Expand Down
32 changes: 31 additions & 1 deletion src/scripts/utils.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
import { bitcoinNetwork, litecoinNetwork } from '../constants';

// Number satohis and litoshis in a whole coin
const decimals = 100000000;

/**
* Get a hex encoded string from a Buffer
*
Expand Down Expand Up @@ -50,7 +55,14 @@ export const splitPairId = pairId => {
* Convert satoshis and litoshis to whole coins
*/
export const toWholeCoins = satoshis => {
return (satoshis / 100000000).toFixed(8);
return (satoshis / decimals).toFixed(8);
};

/**
* Convert whole coins into satoshis or litoshis
*/
export const toSatoshi = coins => {
return Math.floor(coins * decimals);
};

/**
Expand All @@ -59,3 +71,21 @@ export const toWholeCoins = satoshis => {
export const getCurrencyName = symbol => {
return symbol === 'BTC' ? 'Bitcoin' : 'Litecoin';
};

// TODO: refactor how we copy
/**
* Copy the content of the element "copy" into the clipboard
*/
export const copyToClipBoard = () => {
const range = document.getSelection().getRangeAt(0);
range.selectNode(document.getElementById('copy'));
window.getSelection().addRange(range);
document.execCommand('copy');
};

/**
* Get the network for a symbol
*/
export const getNetwork = symbol => {
return symbol === 'BTC' ? bitcoinNetwork : litecoinNetwork;
};
2 changes: 2 additions & 0 deletions src/state/rootReducer.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { combineReducers } from 'redux';
import swapReducer from '../views/swap/swapReducer';
import reverseSwapReducer from '../views/reverse/reverseReducer';
import landingpageReducer from '../views/landingpage/landingpageReducer';
import routerReducer from '../views/router/routerReducer';
import refundReducer from '../views/refund/refundReducer';
Expand All @@ -9,6 +10,7 @@ const createRootReducer = () =>
route: routerReducer,
landingpageReducer,
swapReducer,
reverseSwapReducer,
refundReducer,
});

Expand Down
3 changes: 3 additions & 0 deletions src/views/landingpage/index.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { connect } from 'react-redux';
import LandingPage from './landingpage';
import { initSwap } from '../swap/swapActions';
import { initReverseSwap } from '../reverse/reverseActions';
import { nav } from '../../action';
import * as actions from './landingpageActions';

Expand All @@ -11,9 +12,11 @@ const mapStateToProps = state => ({

const mapDispatchToProps = dispatch => ({
goSwap: () => dispatch(nav.goSwap()),
goReverseSwap: () => dispatch(nav.goReverseSwap()),
goRefund: () => dispatch(nav.goRefund()),
goHome: () => dispatch(nav.goHome()),
initSwap: state => dispatch(initSwap(state)),
initReverseSwap: state => dispatch(initReverseSwap(state)),
getPairs: cb => dispatch(actions.getPairs(cb)),
});

Expand Down
Loading

0 comments on commit d7b2449

Please sign in to comment.