Commit e6a85799 authored by zeroleak's avatar zeroleak
Browse files

add tx0 mix fee selection

parent 838c8e89
...@@ -25,7 +25,8 @@ export default function Tx0Modal(props) { ...@@ -25,7 +25,8 @@ export default function Tx0Modal(props) {
} }
const [spendValue, setSpendValue] = useState(utils.sumUtxos(utxos)) const [spendValue, setSpendValue] = useState(utils.sumUtxos(utxos))
const [poolId, setPoolId] = useState(computeInitialPoolId(utxos)) const [poolId, setPoolId] = useState(computeInitialPoolId(utxos))
const [feeTarget, setFeeTarget] = useState(TX0_FEE_TARGET.BLOCKS_2.value) const [tx0FeeTarget, setTx0FeeTarget] = useState(TX0_FEE_TARGET.BLOCKS_2.value)
const [mixFeeTarget, setMixFeeTarget] = useState(TX0_FEE_TARGET.BLOCKS_12.value)
const [pools, setPools] = useState([]) const [pools, setPools] = useState([])
const [tx0Preview, setTx0Preview] = useState(undefined) const [tx0Preview, setTx0Preview] = useState(undefined)
...@@ -40,14 +41,13 @@ export default function Tx0Modal(props) { ...@@ -40,14 +41,13 @@ export default function Tx0Modal(props) {
// compute available pools // compute available pools
useEffect(() => { useEffect(() => {
// fetch pools for tx0 feeTarget // fetch pools for tx0 feeTarget
modalUtils.load("Fetching pools for tx0...", poolsService.fetchPoolsForTx0(spendValue, feeTarget).then(newPools => { modalUtils.load("Fetching pools for tx0...", poolsService.fetchPoolsForTx0(spendValue, tx0FeeTarget, mixFeeTarget).then(newPools => {
console.log('????newPools',newPools,spendValue)
if (newPools.length == 0) { if (newPools.length == 0) {
modalUtils.setError("No pool for this utxo and miner fee.") modalUtils.setError("No pool for this utxo and miner fee.")
} }
setPools(newPools) setPools(newPools)
})) }))
}, [feeTarget, spendValue]) }, [tx0FeeTarget, mixFeeTarget, spendValue])
// compute selected poolId // compute selected poolId
useEffect(() => { useEffect(() => {
...@@ -57,30 +57,30 @@ export default function Tx0Modal(props) { ...@@ -57,30 +57,30 @@ export default function Tx0Modal(props) {
setPoolId(newPoolId) setPoolId(newPoolId)
}, [pools]) }, [pools])
const isTx0Possible = (feeTarget, poolId, utxos) => feeTarget && poolId && utxos && utxos.length > 0 const isTx0Possible = (tx0FeeTarget, mixFeeTarget, poolId, utxos) => tx0FeeTarget && mixFeeTarget && poolId && utxos && utxos.length > 0
// tx0 preview // tx0 preview
useEffect(() => { useEffect(() => {
if (!isTx0Possible(feeTarget, poolId, utxos)) { if (!isTx0Possible(tx0FeeTarget, mixFeeTarget, poolId, utxos)) {
// cannot preview yet // cannot preview yet
setTx0Preview(undefined) setTx0Preview(undefined)
} else { } else {
// preview // preview
modalUtils.load("Fetching tx0 data...", backendService.tx0.tx0Preview(utxos, feeTarget, poolId).then(newTx0Preview => { modalUtils.load("Fetching tx0 data...", backendService.tx0.tx0Preview(utxos, tx0FeeTarget, mixFeeTarget, poolId).then(newTx0Preview => {
setTx0Preview(newTx0Preview) setTx0Preview(newTx0Preview)
})) }))
} }
}, [feeTarget, poolId, utxos]) }, [tx0FeeTarget, mixFeeTarget, poolId, utxos])
const submitTx0 = () => { const submitTx0 = () => {
mixService.tx0(utxos, feeTarget, poolId) mixService.tx0(utxos, tx0FeeTarget, mixFeeTarget, poolId)
onClose(); onClose();
} }
return <GenericModal dialogClassName='modal-tx0' return <GenericModal dialogClassName='modal-tx0'
modalUtils={modalUtils} modalUtils={modalUtils}
title='Send to Premix' title='Send to Premix'
buttons={isTx0Possible(feeTarget, poolId, utxos) && <Button onClick={submitTx0}>Premix <Icon.ChevronsRight size={12}/></Button>} buttons={isTx0Possible(tx0FeeTarget, mixFeeTarget, poolId, utxos) && <Button onClick={submitTx0}>Premix <Icon.ChevronsRight size={12}/></Button>}
onClose={onClose}> onClose={onClose}>
This will send <strong>{utils.toBtc(spendValue)}btc</strong> to Premix and prepare for mixing.<br/> This will send <strong>{utils.toBtc(spendValue)}btc</strong> to Premix and prepare for mixing.<br/>
...@@ -99,13 +99,30 @@ export default function Tx0Modal(props) { ...@@ -99,13 +99,30 @@ export default function Tx0Modal(props) {
</div>} </div>}
<br/> <br/>
Miner fee: {tx0Preview && <strong>{utils.toBtc(tx0Preview.minerFee)} btc</strong>} <div className='row'>
<select className="form-control" onChange={e => setFeeTarget(e.target.value)} defaultValue={feeTarget}> <div className='col-sm-6'>
{Object.keys(TX0_FEE_TARGET).map(feeTargetKey => { Tx0 miner fee: {tx0Preview && <strong>{utils.toBtc(tx0Preview.tx0MinerFee)} btc</strong>}
const feeTargetItem = TX0_FEE_TARGET[feeTargetKey] <select className="form-control" onChange={e => setTx0FeeTarget(e.target.value)} defaultValue={tx0FeeTarget}>
return <option key={feeTargetItem.value} value={feeTargetItem.value}>{feeTargetItem.label}</option> {Object.keys(TX0_FEE_TARGET).map(feeTargetKey => {
})} const feeTargetItem = TX0_FEE_TARGET[feeTargetKey]
</select><br/> return <option key={feeTargetItem.value} value={feeTargetItem.value}>{feeTargetItem.label}</option>
})}
</select>
<small className='text-muted'>Tx0 confirmation time (delay before start mixing)</small>
</div>
<div className='col-sm-6'>
Mix miner fee contribution: {tx0Preview && <strong>{tx0Preview.nbPremix} x {utils.toBtc(tx0Preview.premixMinerFee)} btc = {utils.toBtc(tx0Preview.mixMinerFee)} btc</strong>}
<select className="form-control" onChange={e => setMixFeeTarget(e.target.value)} defaultValue={mixFeeTarget}>
{Object.keys(TX0_FEE_TARGET).map(feeTargetKey => {
const feeTargetItem = TX0_FEE_TARGET[feeTargetKey]
return <option key={feeTargetItem.value} value={feeTargetItem.value}>{feeTargetItem.label}</option>
})}
</select>
<small className='text-muted'>Mix speed and confirmation time (delay for completing mixing)</small>
</div>
</div>
<br/>
{!modalUtils.isError() && <div> {!modalUtils.isError() && <div>
{tx0Preview && <div> {tx0Preview && <div>
......
...@@ -29,7 +29,7 @@ const UtxoControls = React.memo(({ utxo }) => { ...@@ -29,7 +29,7 @@ const UtxoControls = React.memo(({ utxo }) => {
}); });
/* eslint-disable react/prefer-stateless-function */ /* eslint-disable react/prefer-stateless-function */
const UtxosTable = ({ controls, account, utxos, tableKey }) => { const UtxosTable = ({ controls, pool, mixs, account, utxos, tableKey }) => {
const [showReadOnly, setShowReadOnly] = useState(false) const [showReadOnly, setShowReadOnly] = useState(false)
...@@ -100,21 +100,28 @@ const UtxosTable = ({ controls, account, utxos, tableKey }) => { ...@@ -100,21 +100,28 @@ const UtxosTable = ({ controls, account, utxos, tableKey }) => {
Header: 'Amount', Header: 'Amount',
accessor: o => o.value, accessor: o => o.value,
Cell: o => utils.toBtc(o.cell.value) Cell: o => utils.toBtc(o.cell.value)
}, }
{ );
Header: 'Pool', if (pool) {
accessor: o => o.poolId, columns.push(
Cell: o => { {
const utxo = o.row.original Header: 'Pool',
const allowNoPool = utxo.account === WHIRLPOOL_ACCOUNTS.DEPOSIT; accessor: o => o.poolId,
return !isReadOnly(utxo) && <UtxoPoolSelector utxo={utxo} noPool={allowNoPool}/> Cell: o => {
const utxo = o.row.original
return utxo.poolId?utxo.poolId:'-'
}
} }
}, );
{ }
Header: 'Mixs', if (mixs) {
accessor: o => o.mixsDone, columns.push({
Cell: o => !isReadOnly(o.row.original) && <span>{o.cell.value}</span> Header: 'Mixs',
}, accessor: o => o.mixsDone,
Cell: o => !isReadOnly(o.row.original) && <span>{o.cell.value}</span>
});
}
columns.push(
{ {
Header: 'Status', Header: 'Status',
accessor: o => o.status, accessor: o => o.status,
......
...@@ -50,9 +50,13 @@ export const TX0_FEE_TARGET = { ...@@ -50,9 +50,13 @@ export const TX0_FEE_TARGET = {
value: 'BLOCKS_6', value: 'BLOCKS_6',
label: 'Medium priority · in 6 blocks' label: 'Medium priority · in 6 blocks'
}, },
BLOCKS_12: {
value: 'BLOCKS_12',
label: 'Low priority · in 12 blocks'
},
BLOCKS_24: { BLOCKS_24: {
value: 'BLOCKS_24', value: 'BLOCKS_24',
label: 'Low priority · in 24 blocks' label: 'Lowest priority · in 24 blocks'
} }
} }
......
...@@ -44,7 +44,7 @@ class DepositPage extends Component { ...@@ -44,7 +44,7 @@ class DepositPage extends Component {
</div> </div>
<div className='row h-100 d-flex flex-column'> <div className='row h-100 d-flex flex-column'>
<div className='col-sm-12 flex-grow-1 tablescroll'> <div className='col-sm-12 flex-grow-1 tablescroll'>
<UtxosTable tableKey='DepositPage' utxos={utxos} controls={true} account={false}/> <UtxosTable tableKey='DepositPage' utxos={utxos} pool={false} mixs={false} controls={true} account={false}/>
</div> </div>
</div> </div>
</div> </div>
......
...@@ -473,7 +473,7 @@ class InitPage extends Component<Props> { ...@@ -473,7 +473,7 @@ class InitPage extends Component<Props> {
step3() { step3() {
return <div> return <div>
Success. Restarting... Restarting...
</div> </div>
} }
} }
......
...@@ -44,7 +44,7 @@ class LastActivityPage extends Component { ...@@ -44,7 +44,7 @@ class LastActivityPage extends Component {
</div> </div>
<div className='row h-100 d-flex flex-column'> <div className='row h-100 d-flex flex-column'>
<div className='col-sm-12 flex-grow-1 tablescroll'> <div className='col-sm-12 flex-grow-1 tablescroll'>
<UtxosTable tableKey='LastActivityPage' utxos={utxos} controls={false} account={true}/> <UtxosTable tableKey='LastActivityPage' utxos={utxos} pool={true} mixs={true} controls={false} account={true}/>
</div> </div>
</div> </div>
</div> </div>
......
...@@ -39,7 +39,7 @@ export default class PostmixPage extends Component<Props> { ...@@ -39,7 +39,7 @@ export default class PostmixPage extends Component<Props> {
</div> </div>
<div className='row h-100 d-flex flex-column'> <div className='row h-100 d-flex flex-column'>
<div className='col-sm-12 flex-grow-1 tablescroll'> <div className='col-sm-12 flex-grow-1 tablescroll'>
<UtxosTable tableKey='PostmixPage' utxos={utxos} controls={true} account={false}/> <UtxosTable tableKey='PostmixPage' utxos={utxos} pool={true} mixs={true} controls={true} account={false}/>
</div> </div>
</div> </div>
</div> </div>
......
...@@ -39,7 +39,7 @@ export default class PremixPage extends Component<Props> { ...@@ -39,7 +39,7 @@ export default class PremixPage extends Component<Props> {
</div> </div>
<div className='row h-100 d-flex flex-column'> <div className='row h-100 d-flex flex-column'>
<div className='col-sm-12 flex-grow-1 tablescroll'> <div className='col-sm-12 flex-grow-1 tablescroll'>
<UtxosTable tableKey='PremixPage' utxos={utxos}tableKey controls={true} account={false}/> <UtxosTable tableKey='PremixPage' utxos={utxos} pool={true} mixs={false} controls={true} account={false}/>
</div> </div>
</div> </div>
</div> </div>
......
...@@ -112,9 +112,12 @@ class BackendService { ...@@ -112,9 +112,12 @@ class BackendService {
}; };
pools = { pools = {
fetchPools: (tx0FeeTarget=undefined) => { fetchPools: (tx0FeeTarget=undefined, mixFeeTarget=undefined) => {
return this.withStatus('Pools', 'Fetch pools', () => return this.withStatus('Pools', 'Fetch pools', () =>
this.fetchBackendAsJson('/rest/pools'+(tx0FeeTarget!=undefined?'?tx0FeeTarget='+tx0FeeTarget:''), 'GET') this.fetchBackendAsJson('/rest/pools?true=true'
+(tx0FeeTarget!=undefined?'&tx0FeeTarget='+tx0FeeTarget:'')
+(mixFeeTarget!=undefined?'&mixFeeTarget='+mixFeeTarget:'')
, 'GET')
, 'pools.fetchPools', true) , 'pools.fetchPools', true)
} }
}; };
...@@ -152,21 +155,23 @@ class BackendService { ...@@ -152,21 +155,23 @@ class BackendService {
}; };
tx0 = { tx0 = {
tx0Preview: (utxos, feeTarget, poolId) => { tx0Preview: (utxos, tx0FeeTarget, mixFeeTarget, poolId) => {
const inputsRef = utils.utxoRefs(utxos) const inputsRef = utils.utxoRefs(utxos)
return this.withStatus('Utxo', 'Preview tx0', () => return this.withStatus('Utxo', 'Preview tx0', () =>
this.fetchBackendAsJson('/rest/tx0/preview', 'POST', { this.fetchBackendAsJson('/rest/tx0/preview', 'POST', {
feeTarget: feeTarget, tx0FeeTarget: tx0FeeTarget,
mixFeeTarget: mixFeeTarget,
poolId: poolId, poolId: poolId,
inputs: inputsRef inputs: inputsRef
}) })
) )
}, },
tx0: (utxos, feeTarget, poolId) => { tx0: (utxos, tx0FeeTarget, mixFeeTarget, poolId) => {
const inputsRef = utils.utxoRefs(utxos) const inputsRef = utils.utxoRefs(utxos)
return this.withStatus('Utxo', 'New tx0', () => return this.withStatus('Utxo', 'New tx0', () =>
this.fetchBackendAsJson('/rest/tx0', 'POST', { this.fetchBackendAsJson('/rest/tx0', 'POST', {
feeTarget: feeTarget, tx0FeeTarget: tx0FeeTarget,
mixFeeTarget: mixFeeTarget,
poolId: poolId, poolId: poolId,
inputs: inputsRef inputs: inputsRef
}) })
......
...@@ -79,8 +79,8 @@ class MixService { ...@@ -79,8 +79,8 @@ class MixService {
return backendService.utxo.configure(utxo.hash, utxo.index, utxo.poolId).then(() => walletService.fetchState()) return backendService.utxo.configure(utxo.hash, utxo.index, utxo.poolId).then(() => walletService.fetchState())
} }
tx0(utxos, feeTarget, poolId) { tx0(utxos, tx0FeeTarget, mixFeeTarget, poolId) {
return backendService.tx0.tx0(utxos, feeTarget, poolId).then(() => walletService.fetchState()) return backendService.tx0.tx0(utxos, tx0FeeTarget, mixFeeTarget, poolId).then(() => walletService.fetchState())
} }
startMixUtxo(utxo) { startMixUtxo(utxo) {
......
...@@ -53,8 +53,8 @@ class PoolsService { ...@@ -53,8 +53,8 @@ class PoolsService {
return this.state.pools.pools; return this.state.pools.pools;
} }
fetchPoolsForTx0(utxoBalance, tx0FeeTarget) { fetchPoolsForTx0(utxoBalance, tx0FeeTarget, mixFeeTarget) {
return backendService.pools.fetchPools(tx0FeeTarget).then(poolsResponse => poolsResponse.pools.filter(pool => utxoBalance >= pool.tx0BalanceMin)) return backendService.pools.fetchPools(tx0FeeTarget, mixFeeTarget).then(poolsResponse => poolsResponse.pools.filter(pool => utxoBalance >= pool.tx0BalanceMin))
} }
getPoolsForTx0(utxoBalance) { getPoolsForTx0(utxoBalance) {
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment