Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Updated BTCTransactionInfo layout #446

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
12 changes: 10 additions & 2 deletions client/src/PublicRequest.ts
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,12 @@ export type SignTransactionRequest

export type SignBtcTransactionRequestStandard = SimpleRequest & BitcoinTransactionInfo & {
layout?: 'standard',

// data needed for display
fiatCurrency?: string,
fiatRate?: number,
delay?: number,
feePerByte?: number,
};

export type SignBtcTransactionRequestCheckout = SimpleRequest & BitcoinTransactionInfo & {
Expand All @@ -183,9 +189,11 @@ export type SignBtcTransactionRequestCheckout = SimpleRequest & BitcoinTransacti
shopLogoUrl?: string,
time?: number,
expires?: number,
fiatCurrency?: string,
fiatAmount?: number,
vendorMarkup?: number,

// data needed for display
fiatCurrency: string,
fiatRate: number,
};

export type SignBtcTransactionRequest
Expand Down
63 changes: 61 additions & 2 deletions src/request/sign-btc-transaction/SignBtcTransaction.css
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,66 @@
font-weight: bold;
}

#confirm-transaction .fee-section {
#confirm-transaction .fee-section,
#confirm-transaction .fiat-section,
#confirm-transaction .estimation-section .speed-gauge,
#confirm-transaction .estimation-section .values,
#confirm-transaction .estimation-section .info-icon {
opacity: 0.5;
margin-bottom: 0.25rem;
margin-top: 0;
}

#confirm-transaction .estimation-section {
display: flex;
justify-content: center;
align-items: center;
gap: 1.5rem;
}

#confirm-transaction .needle,
#confirm-transaction .needle-cover {
transform-origin: 50% 54.1666667%;
transition: transform 0.3s var(--nimiq-ease);
}

#confirm-transaction .needle-cover {
fill: white;
}

#confirm-transaction .estimation-section .info-icon {
margin-top: 6px;
}

#confirm-transaction .tooltip {
margin-top: -.25rem;
align-self: flex-start;
}

#confirm-transaction .tooltip-box {
--tooltip-width: 250px;
width: var(--tooltip-width);
right: calc(var(--tooltip-width) * -1 / 4);
}

#confirm-transaction .tx-info:hover .tooltip::after,
#confirm-transaction .tx-info:hover .tooltip .tooltip-box {
visibility: visible;
opacity: 1;
}

#confirm-transaction .tooltip-box > p,
#confirm-transaction .network-fee .network-fee__btc {
opacity: 0.6;
}

#confirm-transaction .tooltip-box p:first-child {
margin-top: 0.75rem;
}


#confirm-transaction .network-fee {
display: flex;
flex-direction: column;
}


107 changes: 98 additions & 9 deletions src/request/sign-btc-transaction/SignBtcTransaction.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
/* global SignBtcTransactionApi */
/* global PasswordBox */
/* global Errors */
/* global TemplateTags */
/* global Utf8Tools */
/* global TopLevelApi */
/* global PaymentInfoLine */
Expand All @@ -23,7 +24,7 @@

class SignBtcTransaction {
/**
* @param {Parsed<KeyguardRequest.SignBtcTransactionRequest>} request
* @param {Required<Parsed<KeyguardRequest.SignBtcTransactionRequest>>} request
* @param {SignBtcTransaction.resolve} resolve
* @param {reject} reject
*/
Expand Down Expand Up @@ -94,16 +95,104 @@ class SignBtcTransaction {

/** @type {HTMLDivElement} */
const $value = (this.$el.querySelector('#value'));
/** @type {HTMLDivElement} */
const $fee = (this.$el.querySelector('#fee'));
const amountBTC = BitcoinUtils.satoshisToCoins(recipientOutput.value);
$value.textContent = NumberFormatting.formatNumber(amountBTC, 8);

// Set value and fee.
$value.textContent = NumberFormatting.formatNumber(BitcoinUtils.satoshisToCoins(recipientOutput.value), 8);
if ($fee && fee > 0) {
$fee.textContent = NumberFormatting.formatNumber(BitcoinUtils.satoshisToCoins(fee), 8);
const feeBTC = NumberFormatting.formatNumber(BitcoinUtils.satoshisToCoins(fee), 8);

// Right now, we have two types of layouts. See #445
if (request.layout === SignBtcTransactionApi.Layouts.CHECKOUT) {
/** @type {HTMLDivElement} */
const $feeSection = (this.$el.querySelector('.fee-section'));
$feeSection.classList.remove('display-none');
const $fee = (this.$el.querySelector('#fee'));

if ($fee && fee > 0) {
$fee.textContent = feeBTC;
/** @type {HTMLDivElement} */
const $feeSection = (this.$el.querySelector('.fee-section'));
$feeSection.classList.remove('display-none');
}
} else if (request.layout === SignBtcTransactionApi.Layouts.STANDARD) {
/** @type {HTMLSpanElement|null} */
const $fiat = (this.$el.querySelector('#fiat'));
if (!$fiat) return;

const {
fiatCurrency: currency, fiatRate, delay, feePerByte,
} = request;

const amountFiat = fiatRate * amountBTC;
$fiat.textContent = `~${NumberFormatting.formatCurrency(amountFiat, currency)}`;


/** @type {HTMLDivElement|null} */
const $fiatSection = (this.$el.querySelector('.fiat-section'));
if (!$fiatSection) return;
$fiatSection.classList.remove('display-none');

/** @type {HTMLDivElement|null} */
const $estimationSection = (this.$el.querySelector('.estimation-section'));
if (!$estimationSection) return;
$estimationSection.classList.remove('display-none');

let estimatedDuration = '';
let speed = 50;
if (delay === 1) { estimatedDuration = I18n.translatePhrase('sign-btc-tx-15m'); speed = 100; }
if (delay === 12) { estimatedDuration = I18n.translatePhrase('sign-btc-tx-2-4h'); speed = 50; }
if (delay === 36) { estimatedDuration = I18n.translatePhrase('sign-btc-tx-6h-plus'); speed = 0; }

const rotation = (Math.min(100, Math.max(0, speed)) / 100 - 1) * 180;
this.$el.querySelectorAll('#speed-gauge-icon g > path').forEach($path => {
// @ts-ignore
$path.style.transform = `rotate(${rotation}deg)`;
});

if (!request.changeOutput || !request.changeOutput.value) return;
const fiatAmount = NumberFormatting.formatCurrency(BitcoinUtils.satoshisToCoins(fee) * fiatRate, currency);

/** @type {HTMLDivElement|null} */
const $values = ($estimationSection.querySelector('#values'));
if (!$values) return;
$values.innerText = `${estimatedDuration} / ${fiatAmount}`;

/** @type {HTMLDivElement|null} */
const $tooltip = document.querySelector('#txInfo');
if (!$tooltip) return;
$tooltip.classList.add('tooltip', 'top');
$tooltip.tabIndex = 0; // make the tooltip focusable

/* eslint-disable indent */
$tooltip.innerHTML = TemplateTags.hasVars(2)`
<svg class="info-icon nq-icon">
<use xlink:href="../../../node_modules/@nimiq/style/nimiq-style.icons.svg#nq-info-circle-small"/>
</svg>
<div class="tooltip-box">
<div class="network-fee">
<span>
<label data-i18n="sign-btc-tx-network-fee">
Network fee
</label>
: ${feePerByte}
<label data-i18n="sign-btc-tx-sat-byte">
sat/byte
</label>
</span>
<span class="network-fee__btc">
${feeBTC}
<span class="btc-symbol"></span>
</span>
</div>
<p data-i18n="sign-btc-tx-fee-description">
Increase the speed of your transaction by paying a higher network fee.
The fees go directly to the miners.
<p>
<p data-i18n="sign-btc-tx-fee-values-estimations">
Duration and fees are estimates.
</p>
</div>
`;
/* eslint-enable indent */

I18n.translateDom($tooltip);
}

// Set up password box.
Expand Down
27 changes: 21 additions & 6 deletions src/request/sign-btc-transaction/SignBtcTransactionApi.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,16 @@ class SignBtcTransactionApi extends BitcoinRequestParserMixin(TopLevelApi) {
+ 'sequence number < 0xffffffff');
}
parsedRequest.layout = this.parseLayout(request.layout);

parsedRequest.fiatRate = this.parseNonNegativeFiniteNumber(request.fiatRate) || 0;
if (!parsedRequest.fiatRate) {
throw new Errors.InvalidRequestError('fiatRate must be defined and different to 0');
}
parsedRequest.fiatCurrency = this.parseFiatCurrency(request.fiatCurrency) || '';
if (!parsedRequest.fiatCurrency) {
throw new Errors.InvalidRequestError('fiatCurrency must be defined and different to empty string');
}

if (request.layout === SignBtcTransactionApi.Layouts.CHECKOUT
&& parsedRequest.layout === SignBtcTransactionApi.Layouts.CHECKOUT) {
parsedRequest.shopOrigin = this.parseShopOrigin(request.shopOrigin);
Expand All @@ -43,12 +53,6 @@ class SignBtcTransactionApi extends BitcoinRequestParserMixin(TopLevelApi) {
throw new Errors.InvalidRequestError('origin of shopLogoUrl must be same as shopOrigin');
}

parsedRequest.fiatAmount = this.parseNonNegativeFiniteNumber(request.fiatAmount);
parsedRequest.fiatCurrency = this.parseFiatCurrency(request.fiatCurrency);
if ((parsedRequest.fiatAmount === undefined) !== (parsedRequest.fiatCurrency === undefined)) {
throw new Errors.InvalidRequestError('fiatAmount and fiatCurrency must be both defined or undefined.');
}

parsedRequest.vendorMarkup = this.parseVendorMarkup(request.vendorMarkup);

parsedRequest.time = this.parseNonNegativeFiniteNumber(request.time);
Expand All @@ -60,6 +64,17 @@ class SignBtcTransactionApi extends BitcoinRequestParserMixin(TopLevelApi) {
throw new Errors.InvalidRequestError('`expires` must be greater than `time`');
}
}
} else if (request.layout === SignBtcTransactionApi.Layouts.STANDARD
&& parsedRequest.layout === SignBtcTransactionApi.Layouts.STANDARD) {
parsedRequest.delay = this.parseNonNegativeFiniteNumber(request.delay) || 0;
if (!parsedRequest.delay) {
throw new Errors.InvalidRequestError('delay must be defined.');
}

parsedRequest.feePerByte = this.parseNonNegativeFiniteNumber(request.feePerByte) || 0;
if (!parsedRequest.feePerByte) {
throw new Errors.InvalidRequestError('feePerByte must be defined.');
}
}

return parsedRequest;
Expand Down
27 changes: 27 additions & 0 deletions src/request/sign-btc-transaction/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,33 @@ <h1 data-i18n="sign-tx-heading-tx" class="nq-h1 hide-checkout hide-cashlink">Con
<div class="fee-section nq-text-s display-none">
+ <span id="fee"></span> <span class="btc-symbol"></span> <span data-i18n="sign-tx-fee">fee</span>
</div>

<div class="fiat-section nq-text-s display-none">
<span id="fiat"></span>
</div>
</div>

<div class="estimation-section nq-text-s display-none">
<svg id="speed-gauge-icon" width="24" height="24" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"
fill="currentColor" class="speed-gauge">
<path d="M12 0a12 12 0 110 24 12 12 0 010-24zM4.67 18.8a15.84 15.84 0 0114.66 0 10 10 0 10-14.66 0z" />
<!-- housing -->
<path d="M5.5 11.25H4a.75.75 0 100 1.5h1.5a.75.75 0 100-1.5z" /> <!-- 1/5 -->
<path d="M6.97 5.91a.75.75 0 10-1.06 1.06l1.06 1.06a.75.75 0 101.06-1.06L6.97 5.91z" /> <!-- 2/5 -->
<path d="M12 6.25a.75.75 0 01-.75-.75V4a.75.75 0 111.5 0v1.5a.75.75 0 01-.75.75z" /> <!-- 3/5 -->
<path d="M17.03 5.91a.75.75 0 111.06 1.06l-1.06 1.06a.75.75 0 11-1.06-1.06l1.06-1.06z" /> <!-- 4/5 -->
<path d="M18.5 11.25H20a.75.75 0 110 1.5h-1.5a.75.75 0 110-1.5z" /> <!-- 5/5 -->
<g transform="translate(0 -1)">
<path
d="M21.02 13.07a.5.5 0 00-.38-.49c-.78-.2-7.64-1.93-8.7-1.94a2.39 2.39 0 00-2.4 2.38 2.42 2.42 0 002.37 2.4c1.07 0 7.95-1.67 8.73-1.86a.5.5 0 00.38-.49z"
class="needle-cover" />
<path
d="M21.02 13.07a.5.5 0 00-.38-.49c-.78-.2-7.64-1.93-8.7-1.94a2.39 2.39 0 00-2.4 2.38 2.42 2.42 0 002.37 2.4c1.07 0 7.95-1.67 8.73-1.86a.5.5 0 00.38-.49z"
class="needle" />
</g>
</svg>
<div id="values" class="values"></div>
<div id="txInfo" class="tx-info"></div>
</div>
</div>

Expand Down
11 changes: 10 additions & 1 deletion src/translations/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -236,5 +236,14 @@
"sign-swap-exchange-fee": "Swap fee",
"sign-swap-of-exchange-value": "of swap value.",
"sign-swap-total-fees": "Total fees",
"sign-swap-your-bank": "Your bank"
"sign-swap-your-bank": "Your bank",

"sign-btc-tx-15m": "15m",
"sign-btc-tx-2-4h": "2-4h",
"sign-btc-tx-6h-plus": "6h+",
"sign-btc-tx-network-fee": "Network fee",
"sign-btc-tx-sat-byte": "sat/byte",
"sign-btc-tx-fee-description": "Increase the speed of your transaction by paying a higher network fee. The fees go directly to the miners.",
"sign-btc-tx-fee-values-estimations": "Duration and fees are estimates.",
"sign-btc-tx-fee": "fee"
}