Skip to content

Commit

Permalink
Merge branch 'upgrade310' of github.com:relativisticelectron/specter-…
Browse files Browse the repository at this point in the history
…desktop into upgrade310
  • Loading branch information
Kim Neunert committed Sep 9, 2022
2 parents b5a7ce2 + d6335f9 commit a09e5f6
Show file tree
Hide file tree
Showing 8 changed files with 181 additions and 8 deletions.
1 change: 1 addition & 0 deletions cypress.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
"spec_configures_nodes.js",
"spec_devices.js",
"spec_ghost_machine.js",
"spec_fees.js",
"spec_rescan.js",
"spec_qr_signing.js",
"spec_wallet_send.js",
Expand Down
1 change: 1 addition & 0 deletions cypress/fixtures/fees/asymmetric_fees.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"result": {"fastestFee": 13, "halfHourFee": 4, "hourFee": 2, "minimumFee": 1}, "error_messages": []}
1 change: 1 addition & 0 deletions cypress/fixtures/fees/high_fees.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"result": {"fastestFee": 14, "halfHourFee": 10, "hourFee": 7, "minimumFee": 1}, "error_messages": []}
1 change: 1 addition & 0 deletions cypress/fixtures/fees/low_fees.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"result": {"fastestFee": 1, "halfHourFee": 1, "hourFee": 1, "minimumFee": 1}, "error_messages": []}
1 change: 1 addition & 0 deletions cypress/fixtures/fees/low_non-integer_fees.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"result": {"fastestFee": 1.1, "halfHourFee": 1, "hourFee": 1, "minimumFee": 1}, "error_messages": []}
1 change: 1 addition & 0 deletions cypress/fixtures/fees/normal_fees.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"result": {"fastestFee": 9, "halfHourFee": 5, "hourFee": 3, "minimumFee": 1}, "error_messages": []}
157 changes: 157 additions & 0 deletions cypress/integration/spec_fees.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,157 @@
// This spec file assumes that the Ghost wallet is available,
// Fetch API values for fees are mocked

describe('Test the fee UI', () => {
before(() => {
Cypress.config('includeShadowDom', true)
cy.visit('/')
})

// Keeps the session cookie alive, Cypress by default clears all cookies before each test
beforeEach(() => {
cy.viewport(1200,660)
Cypress.Cookies.preserveOnce('session')
})

it('Using dynamic mode with normal fees', () => {
// Fees: {"fastestFee": 9, "halfHourFee": 5, "hourFee": 3, "minimumFee": 1}
cy.selectWallet('Ghost wallet')
cy.intercept('GET', '/wallets/fees', { fixture: 'fees/normal_fees.json' })
cy.get('#btn_send').click()
cy.get('#toggle_advanced').click()
// Preselected dynamic fee rate
cy.get('#fee_rate_dynamic_text').should('have.text', '5')
// Speed text
cy.get('#fee_rate_speed_text').should('have.text', 'Fast (30 minutes)')
// Slider
cy.get('#fees_slider').should('have.value', '5')
cy.get('#fees_slider').invoke('attr', 'min').should('eq', '1')
cy.get('#fees_slider').invoke('attr', 'max').should('eq', '12')
// Simulate sliding to 1.5
cy.get('#fees_slider').invoke('val', '1.5').trigger('input')
cy.get('#fees_slider').should('have.value', '1.5')
cy.get('#fee_rate_speed_text').should('have.text', 'Very slow')
// Sliding to 2
cy.get('#fees_slider').invoke('val', '2').trigger('input')
cy.get('#fees_slider').should('have.value', '2')
cy.get('#fee_rate_speed_text').should('have.text', 'Slow')
// Sliding to 11
cy.get('#fees_slider').invoke('val', '11').trigger('input')
cy.get('#fees_slider').should('have.value', '11')
cy.get('#fee_rate_speed_text').should('have.text', 'Overpaid! (10 minutes)')
})

it('Using dynamic mode with low fees', () => {
// Fees: {"fastestFee": 1, "halfHourFee": 1, "hourFee": 1, "minimumFee": 1}
cy.selectWallet('Ghost wallet')
cy.intercept('GET', '/wallets/fees', { fixture: 'fees/low_fees.json' })
cy.get('#btn_send').click()
cy.get('#toggle_advanced').click()
// Preselected dynamic fee rate
cy.get('#fee_rate_dynamic_text').should('have.text', '1')
// Speed text
cy.get('#fee_rate_speed_text').should('have.text', 'Very fast (10 minutes)')
// Slider
cy.get('#fees_slider').should('have.value', '1')
cy.get('#fees_slider').invoke('attr', 'min').should('eq', '1')
cy.get('#fees_slider').invoke('attr', 'max').should('eq', '1.5')
// Simulate sliding to 1.5
cy.get('#fees_slider').invoke('val', '1.5').trigger('input')
cy.get('#fees_slider').should('have.value', '1.5')
cy.get('#fee_rate_speed_text').should('have.text', 'Overpaid! (10 minutes)')
})

it('Using dynamic mode with low non-integer fees', () => {
// Fees: {"fastestFee": 1.1, "halfHourFee": 1, "hourFee": 1, "minimumFee": 1}
cy.selectWallet('Ghost wallet')
cy.intercept('GET', '/wallets/fees', { fixture: 'fees/low_non-integer_fees.json' })
cy.get('#btn_send').click()
cy.get('#toggle_advanced').click()
// Preselected dynamic fee rate
cy.get('#fee_rate_dynamic_text').should('have.text', '1')
// Speed text
cy.get('#fee_rate_speed_text').should('have.text', 'Fast (30 minutes)')
// Slider
cy.get('#fees_slider').should('have.value', '1')
cy.get('#fees_slider').invoke('attr', 'min').should('eq', '1')
cy.get('#fees_slider').invoke('attr', 'max').should('eq', '2')
// Simulate sliding to 1.1
cy.get('#fees_slider').invoke('val', '1.1').trigger('input')
cy.get('#fees_slider').should('have.value', '1.1')
cy.get('#fee_rate_speed_text').should('have.text', 'Very fast (10 minutes)')
})

it('Using dynamic mode with high fees', () => {
// Fees: {"fastestFee": 14, "halfHourFee": 10, "hourFee": 7, "minimumFee": 1}
cy.selectWallet('Ghost wallet')
cy.intercept('GET', '/wallets/fees', { fixture: 'fees/high_fees.json' })
cy.get('#btn_send').click()
cy.get('#toggle_advanced').click()
// Preselected dynamic fee rate
cy.get('#fee_rate_dynamic_text').should('have.text', '7')
// Speed text
cy.get('#fee_rate_speed_text').should('have.text', 'Medium (1 hour)')
// Slider
cy.get('#fees_slider').should('have.value', '7')
cy.get('#fees_slider').invoke('attr', 'min').should('eq', '1')
cy.get('#fees_slider').invoke('attr', 'max').should('eq', '19')
// Simulate sliding to 3
cy.get('#fees_slider').invoke('val', '3').trigger('input')
cy.get('#fees_slider').should('have.value', '3')
cy.get('#fee_rate_speed_text').should('have.text', 'Very slow')
// Simulate sliding to 4.5
cy.get('#fees_slider').invoke('val', '4.5').trigger('input')
cy.get('#fees_slider').should('have.value', '4.5')
cy.get('#fee_rate_speed_text').should('have.text', 'Slow')
})

it('Using dynamic mode with asymmetric fees', () => {
// Fees: {"fastestFee": 13, "halfHourFee": 4, "hourFee": 2, "minimumFee": 1}
cy.selectWallet('Ghost wallet')
cy.intercept('GET', '/wallets/fees', { fixture: 'fees/asymmetric_fees.json' })
cy.get('#btn_send').click()
cy.get('#toggle_advanced').click()
// Preselected dynamic fee rate
cy.get('#fee_rate_dynamic_text').should('have.text', '2')
// Speed text
cy.get('#fee_rate_speed_text').should('have.text', 'Medium (1 hour)')
// Slider
cy.get('#fees_slider').should('have.value', '2')
cy.get('#fees_slider').invoke('attr', 'min').should('eq', '1')
cy.get('#fees_slider').invoke('attr', 'max').should('eq', '18')
// Simulate sliding to 12.5
cy.get('#fees_slider').invoke('val', '12.5').trigger('input')
cy.get('#fees_slider').should('have.value', '12.5')
cy.get('#fee_rate_speed_text').should('have.text', 'Fast (30 minutes)')
// Simulate sliding to 4
cy.get('#fees_slider').invoke('val', '4').trigger('input')
cy.get('#fees_slider').should('have.value', '4')
cy.get('#fee_rate_speed_text').should('have.text', 'Fast (30 minutes)')
// Simulate sliding to 3
cy.get('#fees_slider').invoke('val', '3').trigger('input')
cy.get('#fees_slider').should('have.value', '3')
cy.get('#fee_rate_speed_text').should('have.text', 'Medium (1 hour)')
// Simulate sliding to 1.6
cy.get('#fees_slider').invoke('val', '1.6').trigger('input')
cy.get('#fees_slider').should('have.value', '1.6')
cy.get('#fee_rate_speed_text').should('have.text', 'Slow')
// Simulate sliding to 1.2
cy.get('#fees_slider').invoke('val', '1.2').trigger('input')
cy.get('#fees_slider').should('have.value', '1.2')
cy.get('#fee_rate_speed_text').should('have.text', 'Very slow')
})

it('Using manual mode', () => {
cy.selectWallet('Ghost wallet')
cy.intercept('GET', '/wallets/fees', { fixture: 'fees/normal_fees.json' })
cy.get('#btn_send').click()
cy.get('#toggle_advanced').click()
cy.get('.fee_container').find('#fee_option_manual').click()
cy.get('#fee_manual').find('#fee_rate').should('have.value', '1')
cy.get('#fee_manual').find('#fee_rate').clear( { force: true })
cy.get('#fee_manual').find('#fee_rate').type(5, { force: true })
cy.get('#fee_manual').find('#fee_rate').should('have.value', '5')
cy.get('#fee_manual').find('.note').contains('1 sat/vbyte is the minimal fee rate.')
})

})
26 changes: 18 additions & 8 deletions src/cryptoadvance/specter/templates/includes/fee-selection.html
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ <h4 slot="title">{{ _("Subtract fees from amount") }}</h4>
</div>
<div id ="fee_dynamic" style="display: {% if fee_options_dynamic %}block{% else %}none{% endif %}">
<div id="blocks"></div>
<input type="range" style="width: 12em" min="{{min_fee}}" max="" value="" step="1" id="fees_slider">
<input type="range" style="width: 12em" min="{{min_fee}}" max="" value="" step="0.1" id="fees_slider">
<input type="hidden" id="fee_rate_dynamic" name="fee_rate_dynamic" value="{{min_fee}}">
<div>
{{ _("Estimated speed:") }} <span id="fee_rate_speed_text"></span>
Expand Down Expand Up @@ -238,11 +238,21 @@ <h4 slot="title">{{ _("Subtract fees from amount") }}</h4>
// Gets executed after fee initialisation
initWithFees() {
// this.feesSlider.min is set above via min_fee
this.feesSlider.max = Math.floor(this.fees["fastestFee"] * 1.4)
let sliderMin = this.fees["minimumFee"]
let sliderMax = this.fees["fastestFee"]
let average = Math.floor((sliderMin + sliderMax) / 2)
this.feesSlider.value = average
// For low fee environment, API results are integers
if (this.fees["fastestFee"] == 1) {
this.feesSlider.max = 1.5
}
else {
let feeSliderMax = Math.floor(this.fees["fastestFee"] * 1.4)
this.feesSlider.max = feeSliderMax >= 2 ? feeSliderMax : 2
}
// Avoid calculating the default value with a very high fastestFee
if (this.fees["fastestFee"] > 2 * this.fees["halfHourFee"]) {
this.feesSlider.value = Math.floor((this.fees["minimumFee"] + this.fees["hourFee"] + this.fees["halfHourFee"]) / 3)
}
else {
this.feesSlider.value = Math.floor((this.fees["minimumFee"] + this.fees["fastestFee"]) / 2)
}
this.dynamicFeeUpdated() // otherwise no text next to estimated speed
}

Expand Down Expand Up @@ -274,9 +284,9 @@ <h4 slot="title">{{ _("Subtract fees from amount") }}</h4>
let hourFee = this.fees["hourFee"]
let halfHourFee = this.fees["halfHourFee"]
let fastestFee = this.fees["fastestFee"]
if (this.feesSlider.value <= minFee + ((hourFee - minFee) / 2)) {
if (this.feesSlider.value < minFee + ((hourFee - minFee) / 2)) {
this.fee_rate_speed_text.innerText = '{{ _("Very slow") }}';
} else if (this.feesSlider.value > minFee + ((hourFee - minFee) / 2) && this.feesSlider.value < hourFee) {
} else if (this.feesSlider.value >= minFee + ((hourFee - minFee) / 2) && this.feesSlider.value < hourFee) {
this.fee_rate_speed_text.innerText = '{{ _("Slow") }}';
} else if (this.feesSlider.value >= hourFee && this.feesSlider.value < halfHourFee) {
this.fee_rate_speed_text.innerText = '{{ _("Medium (1 hour)") }}';
Expand Down

0 comments on commit a09e5f6

Please sign in to comment.