Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
lightning-bits
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
bitsoko services
lightning-bits
Commits
f95256ae
Unverified
Commit
f95256ae
authored
Sep 16, 2019
by
Tankred Hase
Committed by
GitHub
Sep 16, 2019
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #1304 from lightninglabs/dev/send-coin-fee-selection
Dev/send coin fee selection
parents
6f89cac9
26de7af6
Changes
15
Hide whitespace changes
Inline
Side-by-side
Showing
15 changed files
with
209 additions
and
19 deletions
+209
-19
lnd.conf
mobile/android/app/src/main/assets/lnd.conf
+1
-1
lnd.conf
mobile/ios/lightning/lnd.conf
+1
-1
package-lock.json
mobile/package-lock.json
+13
-0
package.json
mobile/package.json
+1
-0
rn-cli.config.js
mobile/rn-cli.config.js
+4
-0
lnd-child-process.js
public/lnd-child-process.js
+1
-1
payment.js
src/action/payment.js
+33
-4
field-mobile.js
src/component/field-mobile.js
+71
-0
payment.js
src/computed/payment.js
+9
-0
config.js
src/config.js
+3
-1
store.js
src/store.js
+8
-1
pay-bitcoin-confirm-mobile.js
src/view/pay-bitcoin-confirm-mobile.js
+7
-3
screen-story.js
stories/screen-story.js
+0
-4
payment.spec.js
test/unit/action/payment.spec.js
+38
-3
payment.spec.js
test/unit/computed/payment.spec.js
+19
-0
No files found.
mobile/android/app/src/main/assets/lnd.conf
View file @
f95256ae
...
...
@@ -20,7 +20,7 @@ neutrino.feeurl=https://nodes.lightning.computer/fees/v1/btc-fee-estimates.json
autopilot
.
active
=
0
autopilot
.
private
=
1
autopilot
.
minconfs
=
1
autopilot
.
conftarget
=
6
autopilot
.
conftarget
=
1
6
autopilot
.
allocation
=
1
.
0
autopilot
.
heuristic
=
externalscore
:
0
.
95
autopilot
.
heuristic
=
preferential
:
0
.
05
mobile/ios/lightning/lnd.conf
View file @
f95256ae
...
...
@@ -20,7 +20,7 @@ neutrino.feeurl=https://nodes.lightning.computer/fees/v1/btc-fee-estimates.json
autopilot
.
active
=
0
autopilot
.
private
=
1
autopilot
.
minconfs
=
1
autopilot
.
conftarget
=
6
autopilot
.
conftarget
=
1
6
autopilot
.
allocation
=
1
.
0
autopilot
.
heuristic
=
externalscore
:
0
.
95
autopilot
.
heuristic
=
preferential
:
0
.
05
mobile/package-lock.json
View file @
f95256ae
...
...
@@ -3896,6 +3896,11 @@
"integrity"
:
"sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk="
,
"dev"
:
true
},
"lodash.isequal"
:
{
"version"
:
"4.5.0"
,
"resolved"
:
"https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz"
,
"integrity"
:
"sha1-QVxEePK8wwEgwizhDtMib30+GOA="
},
"lodash.pad"
:
{
"version"
:
"4.5.1"
,
"resolved"
:
"https://registry.npmjs.org/lodash.pad/-/lodash.pad-4.5.1.tgz"
,
...
...
@@ -5523,6 +5528,14 @@
"resolved"
:
"https://registry.npmjs.org/react-native-keychain/-/react-native-keychain-3.1.3.tgz"
,
"integrity"
:
"sha512-eWUbjYJge4icX8FhWJk/OPlyGxPnW9bZDysBX3WwOG37iurdH692HKnM2Ih+S+0te65RytImvUrcVnHVBbumYg=="
},
"react-native-picker-select"
:
{
"version"
:
"6.3.2"
,
"resolved"
:
"https://registry.npmjs.org/react-native-picker-select/-/react-native-picker-select-6.3.2.tgz"
,
"integrity"
:
"sha512-f7DNP9M4UHOtsXizpbd1jWgzV38Yn9WEPu+rY2o8to4rr+CHXl/V6W2G1qXkDPMIzUa9oClYsK8PylVRSoH8iQ=="
,
"requires"
:
{
"lodash.isequal"
:
"^4.5.0"
}
},
"react-native-randombytes"
:
{
"version"
:
"3.5.3"
,
"resolved"
:
"https://registry.npmjs.org/react-native-randombytes/-/react-native-randombytes-3.5.3.tgz"
,
...
...
mobile/package.json
View file @
f95256ae
...
...
@@ -25,6 +25,7 @@
"react-native-gesture-handler"
:
"^1.3.0"
,
"react-native-icloudstore"
:
"^0.9.0"
,
"react-native-keychain"
:
"^3.1.3"
,
"react-native-picker-select"
:
"^6.3.2"
,
"react-native-share"
:
"^1.2.1"
,
"react-native-svg"
:
"^9.6.2"
,
"react-native-unimodules"
:
"^0.5.4"
,
...
...
mobile/rn-cli.config.js
View file @
f95256ae
...
...
@@ -52,6 +52,10 @@ module.exports = {
__dirname
,
'node_modules/react-native-device-info'
),
'react-native-picker-select'
:
path
.
resolve
(
__dirname
,
'node_modules/react-native-picker-select'
),
mobx
:
path
.
resolve
(
__dirname
,
'node_modules/mobx'
),
'mobx-react'
:
path
.
resolve
(
__dirname
,
'node_modules/mobx-react'
),
'locale-currency'
:
path
.
resolve
(
...
...
public/lnd-child-process.js
View file @
f95256ae
...
...
@@ -66,7 +66,7 @@ module.exports.startLndProcess = async function({
'--historicalsyncinterval=20m'
,
'--autopilot.private'
,
'--autopilot.minconfs=1'
,
'--autopilot.conftarget=6'
,
'--autopilot.conftarget=
1
6'
,
'--autopilot.allocation=1.0'
,
'--autopilot.heuristic=externalscore:0.95'
,
'--autopilot.heuristic=preferential:0.05'
,
...
...
src/action/payment.js
View file @
f95256ae
...
...
@@ -7,7 +7,9 @@ import {
PREFIX_REGEX
,
PAYMENT_TIMEOUT
,
POLL_STORE_TIMEOUT
,
SEND_TARGET_CONF
,
LOW_TARGET_CONF
,
MED_TARGET_CONF
,
HIGH_TARGET_CONF
,
}
from
'../config'
;
import
{
toSatoshis
,
toAmount
,
isLnUri
,
isAddress
,
nap
}
from
'../helper'
;
import
*
as
log
from
'./log'
;
...
...
@@ -105,6 +107,7 @@ class PaymentAction {
init
()
{
this
.
_store
.
payment
.
address
=
''
;
this
.
_store
.
payment
.
amount
=
''
;
this
.
_store
.
payment
.
targetConf
=
MED_TARGET_CONF
;
this
.
_store
.
payment
.
fee
=
''
;
this
.
_store
.
payment
.
note
=
''
;
this
.
_store
.
payment
.
useScanner
=
false
;
...
...
@@ -223,14 +226,40 @@ class PaymentAction {
* @return {Promise<undefined>}
*/
async
estimateFee
()
{
const
{
payment
}
=
this
.
_store
;
payment
.
feeEstimates
=
[];
await
this
.
_fetchEstimate
(
LOW_TARGET_CONF
,
'Low'
);
await
this
.
_fetchEstimate
(
MED_TARGET_CONF
,
'Med'
);
await
this
.
_fetchEstimate
(
HIGH_TARGET_CONF
,
'High'
);
payment
.
fee
=
payment
.
feeEstimates
[
1
].
fee
;
}
async
_fetchEstimate
(
targetConf
,
prio
)
{
const
{
payment
,
settings
}
=
this
.
_store
;
const
AddrToAmount
=
{};
AddrToAmount
[
payment
.
address
]
=
toSatoshis
(
payment
.
amount
,
settings
);
const
{
feeSat
}
=
await
this
.
_grpc
.
sendCommand
(
'estimateFee'
,
{
AddrToAmount
,
targetConf
:
SEND_TARGET_CONF
,
targetConf
,
});
payment
.
fee
=
toAmount
(
feeSat
,
settings
);
payment
.
feeEstimates
.
push
({
fee
:
toAmount
(
feeSat
,
settings
),
targetConf
,
prio
,
});
}
/**
* Set the target_conf for the on-chain send operation and set a fee.
* @param {number} options.targetConf The number blocks to target
*/
setTargetConf
({
targetConf
})
{
const
{
payment
}
=
this
.
_store
;
payment
.
targetConf
=
targetConf
;
if
(
!
payment
.
feeEstimates
.
length
)
return
;
payment
.
fee
=
payment
.
feeEstimates
.
find
(
e
=>
e
.
targetConf
===
targetConf
).
fee
;
}
/**
...
...
@@ -286,7 +315,7 @@ class PaymentAction {
await
this
.
_grpc
.
sendCommand
(
'sendCoins'
,
{
addr
:
payment
.
address
,
amount
,
targetConf
:
SEND_TARGET_CONF
,
targetConf
:
payment
.
targetConf
,
sendAll
:
payment
.
sendAll
,
});
}
...
...
src/component/field-mobile.js
0 → 100644
View file @
f95256ae
import
React
from
'react'
;
import
{
StyleSheet
,
View
,
ViewPropTypes
}
from
'react-native'
;
import
RNPickerSelect
from
'react-native-picker-select'
;
import
PropTypes
from
'prop-types'
;
import
Text
from
'./text'
;
import
ArrowDownIcon
from
'../asset/icon/arrow-down'
;
import
{
color
,
font
}
from
'./style'
;
//
// Named Field Select
//
const
namedSelectStyles
=
StyleSheet
.
create
({
content
:
{
alignSelf
:
'stretch'
,
flexDirection
:
'row'
,
justifyContent
:
'space-between'
,
borderBottomColor
:
color
.
blackText
,
borderBottomWidth
:
1
,
},
name
:
{
color
:
color
.
blackText
,
fontSize
:
font
.
sizeM
,
lineHeight
:
font
.
lineHeightM
+
2
*
12
,
marginRight
:
15
,
},
wrapper
:
{
flexDirection
:
'row'
,
alignItems
:
'center'
,
},
});
const
baseInputStyles
=
{
fontFamily
:
'OpenSans Regular'
,
fontSize
:
font
.
sizeM
,
lineHeight
:
font
.
lineHeightM
+
3
,
height
:
font
.
lineHeightM
+
2
*
12
,
color
:
color
.
blackText
,
padding
:
0
,
};
const
pickerStyles
=
StyleSheet
.
create
({
inputIOS
:
{
...
baseInputStyles
,
opacity
:
0.75
,
},
inputAndroid
:
{
...
baseInputStyles
,
opacity
:
0.5
,
},
});
export
const
NamedFieldSelect
=
({
name
,
style
,
...
props
})
=>
(
<
View
style
=
{[
namedSelectStyles
.
content
,
style
]}
>
<
Text
style
=
{
namedSelectStyles
.
name
}
>
{
name
}
<
/Text
>
<
View
style
=
{
namedSelectStyles
.
wrapper
}
>
<
RNPickerSelect
placeholder
=
{{}}
style
=
{
pickerStyles
}
useNativeAndroidPickerStyle
=
{
false
}
{...
props
}
/
>
<
ArrowDownIcon
height
=
{
22
}
width
=
{
22
}
stroke
=
"#969596"
/>
<
/View
>
<
/View
>
);
NamedFieldSelect
.
propTypes
=
{
name
:
PropTypes
.
string
,
style
:
ViewPropTypes
.
style
,
};
src/computed/payment.js
View file @
f95256ae
...
...
@@ -10,6 +10,15 @@ const ComputedPayment = store => {
get
paymentAmountLabel
()
{
return
toLabel
(
store
.
payment
.
amount
,
store
.
settings
);
},
get
paymentFeeEstimateItems
()
{
return
store
.
payment
.
feeEstimates
.
map
(
e
=>
{
const
feeLabel
=
toLabel
(
e
.
fee
,
store
.
settings
);
return
{
label
:
`
${
e
.
prio
}
${
feeLabel
}
${
store
.
unitLabel
||
''
}
`
.
trim
(),
value
:
e
.
targetConf
,
};
});
},
get
paymentFeeLabel
()
{
return
toLabel
(
store
.
payment
.
fee
,
store
.
settings
);
},
...
...
src/config.js
View file @
f95256ae
...
...
@@ -24,7 +24,9 @@ module.exports.PREFIX_URI = `${prefixName}:`;
module
.
exports
.
PREFIX_REGEX
=
/^
[
a-zA-Z
]
*:/
;
module
.
exports
.
DEFAULT_ROUTE
=
'Welcome'
;
module
.
exports
.
SEND_TARGET_CONF
=
6
;
module
.
exports
.
LOW_TARGET_CONF
=
26
;
module
.
exports
.
MED_TARGET_CONF
=
16
;
module
.
exports
.
HIGH_TARGET_CONF
=
4
;
module
.
exports
.
PIN_LENGTH
=
6
;
module
.
exports
.
MIN_PASSWORD_LENGTH
=
8
;
module
.
exports
.
STRONG_PASSWORD_LENGTH
=
12
;
...
...
src/store.js
View file @
f95256ae
...
...
@@ -14,7 +14,12 @@ import ComputedPayment from './computed/payment';
import
ComputedNotification
from
'./computed/notification'
;
import
ComputedSetting
from
'./computed/setting'
;
import
ComputedSeed
from
'./computed/seed'
;
import
{
DEFAULT_ROUTE
,
DEFAULT_UNIT
,
DEFAULT_FIAT
}
from
'./config'
;
import
{
DEFAULT_ROUTE
,
DEFAULT_UNIT
,
DEFAULT_FIAT
,
MED_TARGET_CONF
,
}
from
'./config'
;
export
class
Store
{
constructor
()
{
...
...
@@ -69,6 +74,8 @@ export class Store {
payment
:
{
address
:
''
,
amount
:
''
,
targetConf
:
MED_TARGET_CONF
,
feeEstimates
:
[],
fee
:
''
,
note
:
''
,
sendAll
:
false
,
...
...
src/view/pay-bitcoin-confirm-mobile.js
View file @
f95256ae
...
...
@@ -5,6 +5,7 @@ import PropTypes from 'prop-types';
import
Background
from
'../component/background'
;
import
MainContent
from
'../component/main-content'
;
import
{
NamedField
}
from
'../component/field'
;
import
{
NamedFieldSelect
}
from
'../component/field-mobile'
;
import
{
Header
,
Title
}
from
'../component/header'
;
import
{
CancelButton
,
BackButton
,
SmallGlasButton
}
from
'../component/button'
;
import
Card
from
'../component/card'
;
...
...
@@ -66,9 +67,12 @@ const PayBitcoinConfirmView = ({ store, nav, payment }) => (
{
store
.
unitLabel
}
<
/BalanceLabelUnit
>
<
/BalanceLabel
>
<
NamedField
name
=
"Fee"
>
{
store
.
paymentFeeLabel
}
{
store
.
unitLabel
}
<
/NamedField
>
<
NamedFieldSelect
name
=
"Fee"
items
=
{
store
.
paymentFeeEstimateItems
}
value
=
{
store
.
payment
.
targetConf
}
onValueChange
=
{
targetConf
=>
payment
.
setTargetConf
({
targetConf
})}
/
>
<
NamedField
name
=
"Total"
style
=
{
styles
.
totalLbl
}
>
{
store
.
paymentTotalLabel
}
{
store
.
unitLabel
}
<
/NamedField
>
...
...
stories/screen-story.js
View file @
f95256ae
...
...
@@ -53,7 +53,6 @@ import PayLightningDoneMobile from '../src/view/pay-lightning-done-mobile';
import
PayBitcoin
from
'../src/view/pay-bitcoin'
;
import
PayBitcoinMobile
from
'../src/view/pay-bitcoin-mobile'
;
import
PayBitcoinConfirm
from
'../src/view/pay-bitcoin-confirm'
;
import
PayBitcoinConfirmMobile
from
'../src/view/pay-bitcoin-confirm-mobile'
;
import
PayBitcoinDone
from
'../src/view/pay-bitcoin-done'
;
import
PayBitcoinDoneMobile
from
'../src/view/pay-bitcoin-done-mobile'
;
import
PaymentFailed
from
'../src/view/payment-failed'
;
...
...
@@ -304,9 +303,6 @@ storiesOf('Screens', module)
.
add
(
'Pay Bitcoin Confirm'
,
()
=>
(
<
PayBitcoinConfirm
store
=
{
store
}
payment
=
{
payment
}
nav
=
{
nav
}
/
>
))
.
add
(
'Pay Bitcoin Confirm (Mobile)'
,
()
=>
(
<
PayBitcoinConfirmMobile
store
=
{
store
}
payment
=
{
payment
}
nav
=
{
navMobile
}
/
>
))
.
add
(
'Pay Bitcoin Done'
,
()
=>
<
PayBitcoinDone
payment
=
{
payment
}
nav
=
{
nav
}
/>
)
.
add
(
'Pay Bitcoin Done (Mobile)'
,
()
=>
(
<
PayBitcoinDoneMobile
payment
=
{
payment
}
nav
=
{
navMobile
}
/
>
...
...
test/unit/action/payment.spec.js
View file @
f95256ae
...
...
@@ -161,6 +161,7 @@ describe('Action Payments Unit Tests', () => {
store
.
payment
.
amount
=
'bar'
;
store
.
payment
.
note
=
'baz'
;
store
.
payment
.
fee
=
'blub'
;
store
.
payment
.
targetConf
=
1
;
store
.
payment
.
useScanner
=
true
;
store
.
payment
.
sendAll
=
true
;
payment
.
init
();
...
...
@@ -169,11 +170,45 @@ describe('Action Payments Unit Tests', () => {
expect
(
store
.
payment
.
note
,
'to equal'
,
''
);
expect
(
store
.
payment
.
fee
,
'to equal'
,
''
);
expect
(
store
.
payment
.
useScanner
,
'to equal'
,
false
);
expect
(
store
.
payment
.
targetConf
,
'to equal'
,
16
);
expect
(
store
.
payment
.
sendAll
,
'to equal'
,
false
);
expect
(
nav
.
goPay
,
'was called once'
);
});
});
describe
(
'estimateFee()'
,
()
=>
{
beforeEach
(()
=>
{
store
.
payment
.
address
=
'foo'
;
store
.
payment
.
amount
=
'2000'
;
grpc
.
sendCommand
.
withArgs
(
'estimateFee'
).
resolves
({
feeSat
:
10000
,
});
});
it
(
'should get three fee estimates'
,
async
()
=>
{
await
payment
.
estimateFee
();
expect
(
grpc
.
sendCommand
,
'was called thrice'
);
expect
(
store
.
payment
.
feeEstimates
[
0
].
prio
,
'to equal'
,
'Low'
);
expect
(
store
.
payment
.
feeEstimates
[
1
].
prio
,
'to equal'
,
'Med'
);
expect
(
store
.
payment
.
feeEstimates
[
2
].
prio
,
'to equal'
,
'High'
);
});
});
describe
(
'setTargetConf()'
,
()
=>
{
it
(
'should set target conf and fee'
,
async
()
=>
{
store
.
payment
.
feeEstimates
=
[{
targetConf
:
6
,
fee
:
'42'
}];
await
payment
.
setTargetConf
({
targetConf
:
6
});
expect
(
store
.
payment
.
targetConf
,
'to equal'
,
6
);
expect
(
store
.
payment
.
fee
,
'to equal'
,
'42'
);
});
it
(
'should set target conf but not fee if not estimates'
,
async
()
=>
{
await
payment
.
setTargetConf
({
targetConf
:
6
});
expect
(
store
.
payment
.
targetConf
,
'to equal'
,
6
);
expect
(
store
.
payment
.
fee
,
'to equal'
,
''
);
});
});
describe
(
'initPayBitcoinConfirm()'
,
()
=>
{
beforeEach
(()
=>
{
store
.
payment
.
address
=
'foo'
;
...
...
@@ -185,7 +220,7 @@ describe('Action Payments Unit Tests', () => {
it
(
'should get estimate and navigate to confirm view'
,
async
()
=>
{
await
payment
.
initPayBitcoinConfirm
();
expect
(
grpc
.
sendCommand
,
'was called
on
ce'
);
expect
(
grpc
.
sendCommand
,
'was called
thri
ce'
);
expect
(
nav
.
goPayBitcoinConfirm
,
'was called once'
);
expect
(
notification
.
display
,
'was not called'
);
expect
(
store
.
payment
.
fee
,
'to be'
,
'0.0001'
);
...
...
@@ -204,7 +239,7 @@ describe('Action Payments Unit Tests', () => {
it
(
'should get estimate and navigate if fee is set'
,
async
()
=>
{
store
.
payment
.
fee
=
'0.0002'
;
await
payment
.
initPayBitcoinConfirm
();
expect
(
grpc
.
sendCommand
,
'was called
on
ce'
);
expect
(
grpc
.
sendCommand
,
'was called
thri
ce'
);
expect
(
nav
.
goPayBitcoinConfirm
,
'was called once'
);
expect
(
notification
.
display
,
'was not called'
);
expect
(
store
.
payment
.
fee
,
'to be'
,
'0.0001'
);
...
...
@@ -213,7 +248,7 @@ describe('Action Payments Unit Tests', () => {
it
(
'should get estimate and navigate if sendAll is set'
,
async
()
=>
{
store
.
payment
.
sendAll
=
true
;
await
payment
.
initPayBitcoinConfirm
();
expect
(
grpc
.
sendCommand
,
'was called
on
ce'
);
expect
(
grpc
.
sendCommand
,
'was called
thri
ce'
);
expect
(
nav
.
goPayBitcoinConfirm
,
'was called once'
);
expect
(
notification
.
display
,
'was not called'
);
expect
(
store
.
payment
.
fee
,
'to be'
,
'0.0001'
);
...
...
test/unit/computed/payment.spec.js
View file @
f95256ae
...
...
@@ -14,10 +14,29 @@ describe('Computed Payment Unit Tests', () => {
it
(
'should work with initial store'
,
()
=>
{
ComputedPayment
(
store
);
expect
(
store
.
paymentAmountLabel
,
'to equal'
,
'0'
);
expect
(
store
.
paymentFeeEstimateItems
,
'to equal'
,
[]);
expect
(
store
.
paymentFeeLabel
,
'to equal'
,
'0'
);
expect
(
store
.
paymentTotalLabel
,
'to equal'
,
'0'
);
});
it
(
'should calculate fee estimate label'
,
()
=>
{
store
.
unitLabel
=
'sats'
;
store
.
payment
.
feeEstimates
=
[
{
fee
:
'10'
,
targetConf
:
6
,
prio
:
'Med'
,
},
];
ComputedPayment
(
store
);
expect
(
store
.
paymentFeeEstimateItems
[
0
].
label
,
'to match'
,
/^Med 10 sats$/
);
expect
(
store
.
paymentFeeEstimateItems
[
0
].
value
,
'to equal'
,
6
);
});
it
(
'should calculate btc total'
,
()
=>
{
store
.
payment
.
fee
=
'0.0001'
;
store
.
payment
.
amount
=
'0.1'
;
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment