Skip to content
GitLab
Projects
Groups
Snippets
Help
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in / Register
Toggle navigation
Open sidebar
Whirlpool
whirlpool-gui
Commits
aac5f20c
Commit
aac5f20c
authored
Nov 13, 2020
by
zeroleak
Browse files
hide non-mixable utxos + remove mixs-target + use react-table
parent
0aa65759
Changes
12
Hide whitespace changes
Inline
Side-by-side
Showing
12 changed files
with
331 additions
and
314 deletions
+331
-314
app/components/Modals/Tx0Modal.js
app/components/Modals/Tx0Modal.js
+2
-21
app/components/TableGeneric/TableGeneric.js
app/components/TableGeneric/TableGeneric.js
+63
-0
app/components/Utxo/UtxoMixsTargetSelector.js
app/components/Utxo/UtxoMixsTargetSelector.js
+0
-30
app/components/Utxo/UtxosTable.js
app/components/Utxo/UtxosTable.js
+130
-165
app/containers/ConfigPage.js
app/containers/ConfigPage.js
+1
-21
app/containers/LastActivityPage.js
app/containers/LastActivityPage.js
+1
-1
app/css/samourai.css
app/css/samourai.css
+1
-2
app/services/backendService.js
app/services/backendService.js
+4
-6
app/services/mixService.js
app/services/mixService.js
+6
-11
app/services/utils.js
app/services/utils.js
+26
-19
package.json
package.json
+4
-2
yarn.lock
yarn.lock
+93
-36
No files found.
app/components/Modals/Tx0Modal.js
View file @
aac5f20c
...
...
@@ -2,7 +2,7 @@
import
React
from
'
react
'
;
import
{
Button
}
from
'
react-bootstrap
'
;
import
*
as
Icon
from
'
react-feather
'
;
import
utils
,
{
MIXSTARGET_VALUES
}
from
'
../../services/utils
'
;
import
utils
from
'
../../services/utils
'
;
import
mixService
from
'
../../services/mixService
'
;
import
AbstractModal
from
'
./AbstractModal
'
;
import
poolsService
from
'
../../services/poolsService
'
;
...
...
@@ -15,7 +15,6 @@ export default class Tx0Modal extends AbstractModal {
pools
:
undefined
,
feeTarget
:
TX0_FEE_TARGET
.
BLOCKS_2
.
value
,
poolId
:
props
.
utxo
.
poolId
,
mixsTarget
:
props
.
utxo
.
mixsTargetOrDefault
}
super
(
props
,
'
modal-tx0
'
,
initialState
)
...
...
@@ -23,7 +22,6 @@ export default class Tx0Modal extends AbstractModal {
this
.
handleChangeFeeTarget
=
this
.
handleChangeFeeTarget
.
bind
(
this
);
this
.
handleChangePoolTx0
=
this
.
handleChangePoolTx0
.
bind
(
this
);
this
.
handleChangeMixsTargetTx0
=
this
.
handleChangeMixsTargetTx0
.
bind
(
this
);
this
.
handleSubmitTx0
=
this
.
handleSubmitTx0
.
bind
(
this
)
this
.
fetchPoolsForTx0FeeTarget
=
this
.
fetchPoolsForTx0FeeTarget
.
bind
(
this
)
this
.
setStateWithTx0Preview
=
this
.
setStateWithTx0Preview
.
bind
(
this
)
...
...
@@ -85,16 +83,8 @@ export default class Tx0Modal extends AbstractModal {
})
}
handleChangeMixsTargetTx0
(
e
)
{
const
mixsTarget
=
parseInt
(
e
.
target
.
value
)
this
.
setState
({
mixsTarget
:
mixsTarget
})
}
handleSubmitTx0
()
{
mixService
.
tx0
(
this
.
props
.
utxo
,
this
.
state
.
feeTarget
,
this
.
state
.
poolId
,
this
.
state
.
mixsTarget
)
mixService
.
tx0
(
this
.
props
.
utxo
,
this
.
state
.
feeTarget
,
this
.
state
.
poolId
)
this
.
props
.
onClose
();
}
...
...
@@ -132,15 +122,6 @@ export default class Tx0Modal extends AbstractModal {
<
/select><br/
>
{
!
this
.
isError
()
&&
<
div
>
Mixs
target
:
(
editable
later
)
<
select
className
=
"
form-control col-sm-2
"
onChange
=
{
this
.
handleChangeMixsTargetTx0
}
defaultValue
=
{
this
.
state
.
mixsTarget
}
>
{
MIXSTARGET_VALUES
.
map
(
value
=>
{
value
=
parseInt
(
value
)
const
label
=
utils
.
mixsTargetLabel
(
value
)
return
<
option
value
=
{
value
}
>
{
label
}
<
/option
>
})}
<
/select><br/
>
{
this
.
state
.
tx0Preview
&&
<
div
>
This
will
generate
<
strong
>
{
this
.
state
.
tx0Preview
.
nbPremix
}
premixs
<
/strong> of <strong>{utils.toBtc
(
this.state.tx0Preview.premixValue
)
} btc</
strong
>
+
<
strong
>
{
utils
.
toBtc
(
this
.
state
.
tx0Preview
.
changeValue
)}
btc
<
/strong> chang
e
<
/div>
}
...
...
app/components/TableGeneric/TableGeneric.js
0 → 100644
View file @
aac5f20c
import
React
from
'
react
'
;
import
BTable
from
'
react-bootstrap/Table
'
;
import
{
usePagination
,
useSortBy
,
useTable
}
from
'
react-table
'
;
export
default
function
TableGeneric
({
columns
,
data
,
size
=
'
sm
'
,
/*onFetchData, pageIndex, pageSize, filters, */
sortBy
,
getRowStyle
=
()
=>
{},
getRowClassName
=
()
=>
{}
})
{
if
(
!
data
)
{
return
}
const
initialState
=
{};
if
(
sortBy
)
{
initialState
.
sortBy
=
sortBy
;
}
// Use the state and functions returned from useTable to build your UI
const
{
getTableProps
,
headerGroups
,
rows
,
prepareRow
}
=
useTable
(
{
columns
,
data
,
initialState
,
},
useSortBy
,
);
// When these table states change, fetch new data!
/*React.useEffect(() => {
onFetchData({ pageIndex, pageSize, sortBy, filters })
}, [onFetchData, pageIndex, pageSize, sortBy, filters])*/
// Render the UI for your table
return
(
<
BTable
hover
size
=
{
size
}
{...
getTableProps
()}
>
<
thead
>
{
headerGroups
.
map
(
headerGroup
=>
(
<
tr
{...
headerGroup
.
getHeaderGroupProps
()}
>
{
headerGroup
.
headers
.
map
(
column
=>
(
<
th
{...
column
.
getHeaderProps
(
column
.
getSortByToggleProps
())}
>
{
column
.
render
(
'
Header
'
)}
<
span
>
{
column
.
isSorted
?
(
column
.
isSortedDesc
?
'
▼
'
:
'
▲
'
)
:
''
}
<
/span
>
<
/th
>
))}
<
/tr
>
))}
<
/thead
>
<
tbody
>
{
rows
.
map
((
row
,
i
)
=>
{
prepareRow
(
row
);
return
(
<
tr
{...
row
.
getRowProps
({
style
:
getRowStyle
(
row
),
className
:
getRowClassName
(
row
)
})}
>
{
row
.
cells
.
map
(
cell
=>
(
<
td
{...
cell
.
getCellProps
()}
>
{
cell
.
render
(
'
Cell
'
)}
<
/td
>
))}
<
/tr
>
);
})}
<
/tbody
>
<
/BTable
>
);
}
app/components/Utxo/UtxoMixsTargetSelector.js
deleted
100644 → 0
View file @
0aa65759
/**
*
* Status
*
*/
import
React
from
'
react
'
;
import
{
Dropdown
,
DropdownButton
}
from
'
react-bootstrap
'
;
import
mixService
from
'
../../services/mixService
'
;
import
utils
,
{
MIXSTARGET_VALUES
}
from
'
../../services/utils
'
;
/* eslint-disable react/prefer-stateless-function */
class
UtxoMixsTargetSelector
extends
React
.
PureComponent
{
render
()
{
const
utxo
=
this
.
props
.
utxo
return
(
<
DropdownButton
size
=
'
sm
'
variant
=
"
default
"
title
=
{
utxo
.
mixsDone
+
'
/
'
+
utils
.
mixsTargetLabel
(
utxo
.
mixsTargetOrDefault
)}
className
=
'
utxoMixsTargetSelector
'
>
{
MIXSTARGET_VALUES
.
map
(
value
=>
{
value
=
parseInt
(
value
)
const
label
=
utils
.
mixsTargetLabel
(
value
)
return
<
Dropdown
.
Item
key
=
{
value
}
active
=
{
value
===
utxo
.
mixsTarget
}
onClick
=
{()
=>
mixService
.
setMixsTarget
(
utxo
,
value
)}
>
{
label
}
<
/Dropdown.Item
>
})}
<
/DropdownButton
>
)
}
}
export
default
UtxoMixsTargetSelector
app/components/Utxo/UtxosTable.js
View file @
aac5f20c
...
...
@@ -4,17 +4,17 @@
*
*/
import
React
,
{
useCallback
,
useMemo
,
useState
}
from
'
react
'
;
import
_
from
'
lodash
'
;
import
React
,
{
useState
}
from
'
react
'
;
import
mixService
from
'
../../services/mixService
'
;
import
*
as
Icon
from
'
react-feather
'
;
import
utils
,
{
MIXABLE_STATUS
,
UTXO_STATUS
,
WHIRLPOOL_ACCOUNTS
}
from
'
../../services/utils
'
;
import
LinkExternal
from
'
../Utils/LinkExternal
'
;
import
UtxoMixsTargetSelector
from
'
./UtxoMixsTargetSelector
'
;
import
UtxoPoolSelector
from
'
./UtxoPoolSelector
'
;
import
modalService
from
'
../../services/modalService
'
;
import
*
as
Icons
from
'
@fortawesome/free-solid-svg-icons
'
;
import
{
FormCheck
}
from
'
react-bootstrap
'
;
import
{
FontAwesomeIcon
}
from
'
@fortawesome/react-fontawesome
'
;
import
TableGeneric
from
'
../TableGeneric/TableGeneric
'
;
const
UtxoControls
=
React
.
memo
(({
utxo
})
=>
{
return
(
...
...
@@ -30,172 +30,137 @@ const UtxoControls = React.memo(({ utxo }) => {
/* eslint-disable react/prefer-stateless-function */
const
UtxosTable
=
({
controls
,
account
,
utxos
})
=>
{
const
copyToClipboard
=
useCallback
((
text
)
=>
{
const
el
=
document
.
createElement
(
'
textarea
'
);
el
.
value
=
text
;
el
.
setAttribute
(
'
readonly
'
,
''
);
el
.
style
.
position
=
'
absolute
'
;
el
.
style
.
left
=
'
-9999px
'
;
document
.
body
.
appendChild
(
el
);
el
.
select
();
document
.
execCommand
(
'
copy
'
);
document
.
body
.
removeChild
(
el
);
},
[]);
const
[
sortBy
,
setSortBy
]
=
useState
(
'
lastActivityElapsed
'
);
const
[
ascending
,
setAscending
]
=
useState
(
true
);
const
handleSetSort
=
useCallback
((
key
)
=>
{
if
(
sortBy
===
key
)
{
setAscending
(
!
ascending
);
}
else
{
setAscending
(
true
);
}
setSortBy
(
key
);
},
[
sortBy
,
ascending
]);
const
sortedUtxos
=
useMemo
(()
=>
{
const
sortedUtxos
=
_
.
sortBy
(
utxos
,
sortBy
);
if
(
!
ascending
)
{
return
_
.
reverse
(
sortedUtxos
);
const
[
showReadOnly
,
setShowReadOnly
]
=
useState
(
false
)
const
isReadOnly
=
utxo
=>
utils
.
isUtxoReadOnly
(
utxo
)
||
mixService
.
getPoolsForUtxo
(
utxo
).
length
==
0
;
const
columns
=
[]
if
(
account
)
{
columns
.
push
({
Header
:
'
Account
'
,
accessor
:
o
=>
o
.
account
,
Cell
:
o
=>
<
small
>
{
o
.
cell
.
value
}
<
/small
>
})
}
columns
.
push
(
{
Header
:
'
UTXO
'
,
accessor
:
o
=>
o
.
hash
+
'
:
'
+
o
.
index
,
Cell
:
o
=>
{
const
utxo
=
o
.
row
.
original
return
<
small
>
<
span
title
=
{
utxo
.
hash
+
'
:
'
+
utxo
.
index
}
>
<
LinkExternal
href
=
{
utils
.
linkExplorer
(
utxo
)}
>
{
utils
.
shorten
(
utxo
.
hash
)}:{
utxo
.
index
}
<
/LinkExternal
>
<
/span>{' '
}
<
span
title
=
'
Copy TXID
'
>
<
Icon
.
Clipboard
className
=
'
clipboard-icon
'
size
=
{
18
}
onClick
=
{()
=>
utils
.
copyToClipboard
(
utxo
.
hash
)}
/
>
<
/span
>
<
/small
>
}
},
{
Header
:
'
Address
'
,
accessor
:
o
=>
o
.
address
,
Cell
:
o
=>
{
const
utxo
=
o
.
row
.
original
return
<
small
>
<
span
title
=
{
utxo
.
address
+
'
\n
(
'
+
utxo
.
path
+
'
)
'
}
>
<
LinkExternal
href
=
{
utils
.
linkExplorerAddress
(
utxo
)}
>
{
utils
.
shorten
(
utxo
.
address
)}
<
/LinkExternal
>
<
/span>{' '
}
<
span
title
=
'
Copy address
'
>
<
Icon
.
Clipboard
className
=
'
clipboard-icon
'
size
=
{
18
}
onClick
=
{()
=>
copyToClipboard
(
utxo
.
address
)}
/
>
<
/span
>
<
/small
>
}
},
{
Header
:
'
Confs
'
,
accessor
:
o
=>
o
.
confirmations
,
className
:
'
text-muted
'
,
Cell
:
o
=>
o
.
cell
.
value
>
0
?
(
<
small
title
=
"
confirmations
"
>
{
o
.
cell
.
value
}
<
/small
>
)
:
(
<
FontAwesomeIcon
icon
=
{
Icons
.
faClock
}
size
=
'
xs
'
title
=
'
Unconfirmed
'
/>
)
},
{
Header
:
'
Amount
'
,
accessor
:
o
=>
o
.
value
,
Cell
:
o
=>
utils
.
toBtc
(
o
.
cell
.
value
)
},
{
Header
:
'
Pool
'
,
accessor
:
o
=>
o
.
poolId
,
Cell
:
o
=>
{
const
utxo
=
o
.
row
.
original
const
allowNoPool
=
utxo
.
account
===
WHIRLPOOL_ACCOUNTS
.
DEPOSIT
;
return
!
isReadOnly
(
utxo
)
&&
<
UtxoPoolSelector
utxo
=
{
utxo
}
noPool
=
{
allowNoPool
}
/
>
}
},
{
Header
:
'
Mixs
'
,
accessor
:
o
=>
o
.
mixsDone
,
Cell
:
o
=>
!
isReadOnly
(
o
.
row
.
original
)
&&
<
span
>
{
o
.
cell
.
value
}
<
/span
>
},
{
Header
:
'
Status
'
,
accessor
:
o
=>
o
.
status
,
Cell
:
o
=>
!
isReadOnly
(
o
.
row
.
original
)
&&
<
span
className
=
'
text-primary
'
>
{
utils
.
statusLabel
(
o
.
row
.
original
)}
<
/span
>
},
{
Header
:
'
Last activity
'
,
accessor
:
o
=>
o
.
lastActivityElapsed
,
Cell
:
o
=>
{
const
lastActivity
=
mixService
.
computeLastActivity
(
o
.
row
.
original
);
return
lastActivity
?
lastActivity
:
'
-
'
}
},
{
Header
:
'
Info
'
,
accessor
:
o
=>
o
.
error
,
className
:
'
utxoMessage
'
,
Cell
:
o
=>
!
isReadOnly
(
o
.
row
.
original
)
&&
<
small
>
{
utils
.
utxoMessage
(
o
.
row
.
original
)}
<
/small
>
}
return
sortedUtxos
;
},
[
utxos
,
sortBy
,
ascending
]);
const
renderSort
=
sort
=>
sortBy
===
sort
&&
(
ascending
?
"
▲
"
:
"
▼
"
)
);
if
(
controls
)
{
columns
.
push
({
id
:
'
utxoControls
'
,
Header
:
''
,
Cell
:
o
=>
!
isReadOnly
(
o
.
row
.
original
)
&&
<
UtxoControls
utxo
=
{
o
.
row
.
original
}
/
>
})
}
const
visibleUtxos
=
showReadOnly
?
utxos
:
utxos
.
filter
(
utxo
=>
!
isReadOnly
(
utxo
))
const
utxosReadOnly
=
utxos
.
filter
(
utxo
=>
isReadOnly
(
utxo
))
const
amountUtxosReadOnly
=
utxosReadOnly
.
map
(
utxo
=>
utxo
.
value
).
reduce
((
total
,
current
)
=>
total
+
current
,
0
)
return
(
<
div
className
=
'
table-utxos
'
>
<
table
className
=
"
table table-sm table-hover
"
>
<
thead
>
<
tr
>
{
account
&&
<
th
scope
=
"
col
"
className
=
'
account
'
>
<
a
onClick
=
{()
=>
handleSetSort
(
'
account
'
)}
>
Account
{
renderSort
(
'
account
'
)}
<
/a
>
<
/th>
}
<
th
scope
=
"
col
"
className
=
'
hash
'
>
<
a
onClick
=
{()
=>
handleSetSort
(
'
hash
'
)}
>
UTXO
{
renderSort
(
'
hash
'
)}
<
/a
>
<
/th
>
<
th
scope
=
"
col
"
className
=
'
address
'
>
<
a
onClick
=
{()
=>
handleSetSort
(
'
address
'
)}
>
Address
{
renderSort
(
'
address
'
)}
<
/a
>
<
/th
>
<
th
scope
=
"
col
"
className
=
'
confirmations
'
>
<
a
onClick
=
{()
=>
handleSetSort
(
'
confirmations
'
)}
>
Confs
{
renderSort
(
'
confirmations
'
)}
<
/a
>
<
/th
>
<
th
scope
=
"
col
"
className
=
'
value
'
>
<
a
onClick
=
{()
=>
handleSetSort
(
'
value
'
)}
>
Amount
{
renderSort
(
'
value
'
)}
<
/a
>
<
/th
>
<
th
scope
=
"
col
"
className
=
'
poolId
'
>
<
a
onClick
=
{()
=>
handleSetSort
(
'
poolId
'
)}
>
Pool
{
renderSort
(
'
poolId
'
)}
<
/a
>
<
/th
>
<
th
scope
=
"
col
"
className
=
'
mixsDone
'
>
<
a
onClick
=
{()
=>
handleSetSort
(
'
mixsDone
'
)}
>
Mixs
{
renderSort
(
'
mixsDone
'
)}
<
/a
>
<
/th
>
<
th
scope
=
"
col
"
className
=
'
utxoStatus
'
>
<
a
onClick
=
{()
=>
handleSetSort
(
'
status
'
)}
>
Status
{
renderSort
(
'
status
'
)}
<
/a
>
<
/th
>
<
th
scope
=
"
col
"
colSpan
=
{
2
}
>
<
a
onClick
=
{()
=>
handleSetSort
(
'
lastActivityElapsed
'
)}
>
Last
activity
{
renderSort
(
'
lastActivityElapsed
'
)}
<
/a
>
<
/th
>
{
controls
&&
<
th
scope
=
"
col
"
className
=
'
utxoControls
'
/>
}
<
/tr
>
<
/thead
>
<
tbody
>
{
sortedUtxos
.
map
((
utxo
,
i
)
=>
{
const
lastActivity
=
mixService
.
computeLastActivity
(
utxo
);
const
utxoReadOnly
=
utils
.
isUtxoReadOnly
(
utxo
)
||
mixService
.
getPoolsForUtxo
(
utxo
).
length
==
0
;
const
allowNoPool
=
utxo
.
account
===
WHIRLPOOL_ACCOUNTS
.
DEPOSIT
;
return
(
<
tr
key
=
{
i
}
className
=
{
utxoReadOnly
?
'
utxo-disabled
'
:
''
}
>
{
account
&&
<
td
><
small
>
{
utxo
.
account
}
<
/small></
td
>
}
<
td
>
<
small
>
<
span
title
=
{
utxo
.
hash
+
'
:
'
+
utxo
.
index
}
>
<
LinkExternal
href
=
{
utils
.
linkExplorer
(
utxo
)}
>
{
utils
.
shorten
(
utxo
.
hash
)}:{
utxo
.
index
}
<
/LinkExternal
>
<
/span>{' '
}
<
span
title
=
'
Copy TXID
'
>
<
Icon
.
Clipboard
className
=
'
clipboard-icon
'
size
=
{
18
}
onClick
=
{()
=>
copyToClipboard
(
utxo
.
hash
)}
/
>
<
/span
>
<
/small
>
<
/td
>
<
td
>
<
small
>
<
span
title
=
{
utxo
.
address
+
'
\n
(
'
+
utxo
.
path
+
'
)
'
}
>
<
LinkExternal
href
=
{
utils
.
linkExplorerAddress
(
utxo
)}
>
{
utils
.
shorten
(
utxo
.
address
)}
<
/LinkExternal
>
<
/span>{' '
}
<
span
title
=
'
Copy address
'
>
<
Icon
.
Clipboard
className
=
'
clipboard-icon
'
size
=
{
18
}
onClick
=
{()
=>
copyToClipboard
(
utxo
.
address
)}
/
>
<
/span
>
<
/small
>
<
/td
>
<
td
className
=
'
text-muted
'
>
{
utxo
.
confirmations
>
0
?
(
<
small
title
=
"
confirmations
"
>
{
utxo
.
confirmations
}
<
/small
>
)
:
(
<
FontAwesomeIcon
icon
=
{
Icons
.
faClock
}
size
=
'
xs
'
title
=
'
Unconfirmed
'
/>
)}
<
/td
>
<
td
>
{
utils
.
toBtc
(
utxo
.
value
)}
<
/td
>
<
td
>
{
!
utxoReadOnly
&&
<
UtxoPoolSelector
utxo
=
{
utxo
}
noPool
=
{
allowNoPool
}
/>
}
<
/td
>
<
td
>
{
!
utxoReadOnly
&&
<
UtxoMixsTargetSelector
utxo
=
{
utxo
}
/>
}
<
/td
>
<
td
>
{
!
utxoReadOnly
&&
<
span
className
=
'
text-primary
'
>
{
utils
.
statusLabel
(
utxo
)}
<
/span>
}
<
/td
>
<
td
className
=
'
utxoMessage
'
>
{
!
utxoReadOnly
&&
<
small
>
{
utils
.
utxoMessage
(
utxo
)}
<
/small>
}
<
/td
>
<
td
>
{
!
utxoReadOnly
&&
<
small
>
{
lastActivity
?
lastActivity
:
'
-
'
}
<
/small>
}
<
/td
>
<
td
>
{
!
utxoReadOnly
&&
controls
&&
<
UtxoControls
utxo
=
{
utxo
}
/>
}
<
/td
>
<
/tr
>
);
})}
<
/tbody
>
<
/table
>
<
div
>
{
utxosReadOnly
.
length
>
0
&&
<
div
className
=
'
text-center text-muted
'
>
<
FormCheck
id
=
"
showReadOnly
"
type
=
"
checkbox
"
label
=
{
<
span
>
{
utxosReadOnly
.
length
}
non
-
mixable
utxos
({
utils
.
toBtc
(
amountUtxosReadOnly
)}
btc
)
<
/span>} onClick={
()
=> setShowReadOnly
(
!showReadOnly
)
} checked={showReadOnly}/
>
<
/div>
}
<
div
className
=
'
table-utxos
'
>
<
TableGeneric
columns
=
{
columns
}
data
=
{
visibleUtxos
}
sortBy
=
{[{
id
:
'
lastActivityElapsed
'
,
desc
:
true
}]}
getRowClassName
=
{
row
=>
isReadOnly
(
row
.
original
)
?
'
utxo-disabled
'
:
''
}
/
>
{
visibleUtxos
.
length
==
0
&&
<
div
className
=
'
text-center text-muted
'
><
small
>
No
utxo
yet
<
/small></
div
>
}
<
/div
>
<
/div
>
);
};
...
...
app/containers/ConfigPage.js
View file @
aac5f20c
...
...
@@ -3,7 +3,6 @@ import React, { Component } from 'react';
import
{
Alert
,
Card
}
from
'
react-bootstrap
'
;
import
{
FontAwesomeIcon
}
from
'
@fortawesome/react-fontawesome
'
;
import
*
as
Icons
from
'
@fortawesome/free-solid-svg-icons
'
;
import
{
WHIRLPOOL_SERVER
}
from
'
../const
'
;
import
{
logger
}
from
'
../utils/logger
'
;
import
{
CliConfigService
}
from
'
../services/cliConfigService
'
;
import
cliService
from
'
../services/cliService
'
;
...
...
@@ -98,15 +97,6 @@ export default class ConfigPage extends Component<Props> {
<
Card
>
<
Card
.
Header
>
CLI
General
configuration
<
/Card.Header
>
<
Card
.
Body
>
<
div
className
=
"
form-group row
"
>
<
label
htmlFor
=
"
mixsTarget
"
className
=
"
col-sm-2 col-form-label
"
>
Mixs
target
min
<
/label
>
<
input
type
=
"
number
"
className
=
'
form-control col-sm-3
'
onChange
=
{
e
=>
{
const
myValue
=
parseInt
(
e
.
target
.
value
)
myThis
.
onChangeCliConfig
(
cliConfig
=>
cliConfig
.
mix
.
mixsTarget
=
myValue
)
}}
defaultValue
=
{
cliConfig
.
mix
.
mixsTarget
}
id
=
"
mixsTarget
"
/>
<
label
className
=
'
col-form-label col-sm-5 text-muted
'
>
Minimum
number
of
mixs
to
achieve
per
UTXO
<
/label
>
<
/div
>
<
div
className
=
"
form-group row
"
>
<
label
htmlFor
=
"
autoMix
"
className
=
"
col-sm-2 col-form-label
"
>
Auto
-
MIX
<
/label
>
<
div
className
=
"
col-sm-10 custom-control custom-switch
"
>
...
...
@@ -172,7 +162,7 @@ export default class ConfigPage extends Component<Props> {
const
myValue
=
parseInt
(
e
.
target
.
value
)
myThis
.
onChangeCliConfig
(
cliConfig
=>
cliConfig
.
mix
.
tx0MaxOutputs
=
myValue
)
}}
defaultValue
=
{
cliConfig
.
mix
.
tx0MaxOutputs
}
id
=
"
tx0MaxOutputs
"
/>
<
label
className
=
'
col-form-label col-sm-5 text-muted
'
>
Max
premixes
per
TX0
(
0
=
no
limit
)
<
/label
>
<
label
className
=
'
col-form-label col-sm-5 text-muted
'
>
Max
premixes
per
TX0
(
0
=
max
limit
)
<
/label
>
<
/div
>
{
clientsPerPoolEditable
&&
<
div
className
=
"
form-group row
"
>
...
...
@@ -196,16 +186,6 @@ export default class ConfigPage extends Component<Props> {
<
/label
>
<
/div
>
<
div
className
=
"
form-group row
"
>
<
label
htmlFor
=
"
server
"
className
=
"
col-sm-2 col-form-label
"
>
Server
<
/label
>
<
select
className
=
"
col-sm-3 form-control
"
id
=
"
server
"
onChange
=
{
e
=>
{
const
myValue
=
e
.
target
.
value
myThis
.
onChangeCliConfig
(
cliConfig
=>
cliConfig
.
server
=
myValue
)
}}
defaultValue
=
{
cliConfig
.
server
}
>
{
Object
.
keys
(
WHIRLPOOL_SERVER
).
map
((
value
)
=>
<
option
value
=
{
value
}
key
=
{
value
}
>
{
WHIRLPOOL_SERVER
[
value
]}
<
/option>
)
}
<
/select
>
<
/div
>
<
/Card.Body
>
<
/Card>
}
<
br
/>
...
...
app/containers/LastActivityPage.js
View file @
aac5f20c
...
...
@@ -39,7 +39,7 @@ class LastActivityPage extends Component {
<
div
className
=
'
lastActivityPage
'
>
<
div
className
=
'
row
'
>
<
div
className
=
'
col-sm-12
'
>
<
h2
>
Last
activity
<
FontAwesomeIcon
icon
=
{
Icons
.
faCircleNotch
}
spin
size
=
'
xs
'
/>
<
/h2
>
<
h2
>
Last
activity
<
/h2
>
<
/div
>
<
/div
>
<
div
className
=
'
row h-100 d-flex flex-column
'
>
...
...
app/css/samourai.css
View file @
aac5f20c
...
...
@@ -153,8 +153,7 @@ code {
width
:
100%
;
}
.utxoPoolSelector
.dropdown-item
,
.utxoMixsTargetSelector
.dropdown-item
{
.utxoPoolSelector
.dropdown-item
{
padding
:
0
0.4em
;
}
...
...
app/services/backendService.js
View file @
aac5f20c
...
...
@@ -160,20 +160,18 @@ class BackendService {
})
)
},
tx0
:
(
hash
,
index
,
feeTarget
,
poolId
,
mixsTarget
)
=>
{
tx0
:
(
hash
,
index
,
feeTarget
,
poolId
)
=>
{
return
this
.
withStatus
(
'
Utxo
'
,
'
New tx0
'
,
()
=>
this
.
fetchBackendAsJson
(
'
/rest/utxos/
'
+
hash
+
'
:
'
+
index
+
'
/tx0
'
,
'
POST
'
,
{
feeTarget
:
feeTarget
,
poolId
:
poolId
,
mixsTarget
:
mixsTarget
poolId
:
poolId
})
)
},
configure
:
(
hash
,
index
,
poolId
,
mixsTarget
)
=>
{
configure
:
(
hash
,
index
,
poolId
)
=>
{
return
this
.
withStatus
(
'
Utxo
'
,
'
Configure utxo
'
,
()
=>
this
.
fetchBackendAsJson
(
'
/rest/utxos/
'
+
hash
+
'
:
'
+
index
,
'
POST
'
,
{
poolId
:
poolId
,
mixsTarget
:
mixsTarget
poolId
:
poolId
})
)
},
...
...
app/services/mixService.js
View file @
aac5f20c
import
ifNot
from
'
if-not-running
'
;
import
backendService
from
'
./backendService
'
;
import
utils
,
{
TX0_MIN_CONFIRMATIONS
,
WHIRLPOOL_ACCOUNTS
}
from
'
./utils
'
;
import
utils
,
{
TX0_MIN_CONFIRMATIONS
,
UTXO_STATUS
,
WHIRLPOOL_ACCOUNTS
}
from
'
./utils
'
;
import
poolsService
from
'
./poolsService
'
;
import
walletService
from
'
./walletService
'
;
...
...
@@ -75,17 +75,12 @@ class MixService {
return
this
.
configure
(
utxo
)
}