Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 0 additions & 11 deletions client/src/lib/peg.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,25 +3,14 @@ const isNonNegativeNumber = value => Number.isFinite(value) && value >= 0
export const getPegAccounting = (chainStats = {}) => {
const pegInAmount = chainStats.peg_in_amount
, pegOutAmount = chainStats.peg_out_amount
, burnedAmount = chainStats.burned_amount
, federationAssets = isNonNegativeNumber(pegInAmount) &&
isNonNegativeNumber(pegOutAmount) && pegInAmount >= pegOutAmount
? pegInAmount - pegOutAmount
: null
, circulatingLiabilities = isNonNegativeNumber(federationAssets) &&
isNonNegativeNumber(burnedAmount) && federationAssets >= burnedAmount
? federationAssets - burnedAmount
: null
, assetsVsLiabilitiesRatio = isNonNegativeNumber(federationAssets) && circulatingLiabilities > 0
? federationAssets / circulatingLiabilities * 100
: null

return {
pegInAmount
, pegOutAmount
, burnedAmount
, federationAssets
, circulatingLiabilities
, assetsVsLiabilitiesRatio
}
}
60 changes: 2 additions & 58 deletions client/src/views/peg-info.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,7 @@ import {
} from "../const";

const staticRoot = process.env.STATIC_ROOT || "";
const ratioMiddleBound = 100;
const minimumRatioHalfRange = 0.1;
const ratioScaleIncrement = 0.1;
const ratioScaleHeadroom = 0.05;
const recentPegTransactionLimit = 4;
const recentPegTransactionLimit = 7;

const getPegTypes = (tx) => {
const pegTypes = [];
Expand Down Expand Up @@ -68,30 +64,6 @@ const getPegAmount = (tx, pegType) => {
: sumValues(outputs.filter((output) => output.pegout));
};

const getRatioScale = (ratio) => {
const ratioDistance = Number.isFinite(ratio)
? Math.abs(ratio - ratioMiddleBound)
: 0;
const halfRange = Math.max(
minimumRatioHalfRange,
Math.ceil(
(ratioDistance + ratioScaleHeadroom) / ratioScaleIncrement,
) * ratioScaleIncrement,
);
const lowerBound = ratioMiddleBound - halfRange;
const upperBound = ratioMiddleBound + halfRange;
const fill = Number.isFinite(ratio)
? Math.min(
100,
Math.max(0, ((ratio - lowerBound) / (upperBound - lowerBound)) * 100),
)
: 0;

return { lowerBound, upperBound, fill };
};

const formatRatioBound = (ratio) => `${ratio.toFixed(1)}%`;

const getLastConfirmationTime = (txs) =>
txs.reduce(
(latest, tx) =>
Expand Down Expand Up @@ -155,9 +127,7 @@ export const pegInfo = (asset, txs, { t, feeEst, error }) => {
pegInAmount,
pegOutAmount,
federationAssets,
assetsVsLiabilitiesRatio,
} = getPegAccounting(chainStats);
const ratioScale = getRatioScale(assetsVsLiabilitiesRatio);
const allPegTransactions = txs
.reduce(
(entries, tx) => entries.concat(
Expand All @@ -179,7 +149,7 @@ export const pegInfo = (asset, txs, { t, feeEst, error }) => {
);

return (
<div>
<div className="proof-of-reserves-container">
<p className="section-title">{t`Proof of Reserves`}</p>
<div className="peg-info">
{error ? (
Expand All @@ -199,32 +169,6 @@ export const pegInfo = (asset, txs, { t, feeEst, error }) => {
}
/>

<InfoCard
title={t`Assets vs Liabilities`}
className="assets-vs-liabilities"
tooltip={t`Confirmed federation BTC holdings divided by circulating L-BTC supply.`}
body={
<div className="assets-vs-liabilities-body">
<div className="assets-vs-liabilities-scale">
<p>{formatRatioBound(ratioScale.lowerBound)}</p>
<p>{formatRatioBound(ratioMiddleBound)}</p>
<p>{formatRatioBound(ratioScale.upperBound)}</p>
</div>
<div className="assets-vs-liabilities-bar">
<div
className="assets-vs-liabilities-fill"
style={{ width: `${ratioScale.fill}%` }}
></div>
</div>
<p className="assets-vs-liabilities-ratio">
{Number.isFinite(assetsVsLiabilitiesRatio)
? `${assetsVsLiabilitiesRatio.toFixed(3)}%`
: t`N/A`}
</p>
</div>
}
/>

<div className="table peg-transaction-table">
<div className="table-header">
<div className="table-header-icon-container">
Expand Down
2 changes: 0 additions & 2 deletions lang/pt-pt.json
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,6 @@
"AVERAGE BLOCK TIME": "TEMPO MÉDIO DO BLOCO",
"AVG FEE": "TAXA MÉDIA",
"All selected transactions are shown individually.": "Todas as transações selecionadas são apresentadas individualmente.",
"Assets vs Liabilities": "Ativos vs Passivos",
"Average": "Média",
"Average fee rate and transaction fee in the high-fee portion of this template.": "Taxa de comissão média e taxa de transação na parte de taxas altas deste modelo.",
"Average fee rate and transaction fee in the low-fee portion of this template.": "Taxa de comissão média e taxa de transação na parte de taxas baixas deste modelo.",
Expand All @@ -81,7 +80,6 @@
"Block is %s% full": "O bloco está %0% preenchido",
"Block utilization unavailable": "Utilização do bloco indisponível",
"Blocks History": "Histórico de Blocos",
"Confirmed federation BTC holdings divided by circulating L-BTC supply.": "Reservas confirmadas de BTC da federação divididas pela oferta de L-BTC em circulação.",
"Confirmed peg-ins minus confirmed peg-outs.": "Peg-ins confirmados menos peg-outs confirmados.",
"Copy block number %s": "Copiar número do bloco %0",
"Copy transaction id %s": "Copiar ID da transação %0",
Expand Down
6 changes: 0 additions & 6 deletions lang/pt-pt.po
Original file line number Diff line number Diff line change
Expand Up @@ -554,9 +554,6 @@ msgstr "TAXA MÉDIA"
msgid "All selected transactions are shown individually."
msgstr "Todas as transações selecionadas são apresentadas individualmente."

msgid "Assets vs Liabilities"
msgstr "Ativos vs Passivos"

msgid "Average"
msgstr "Média"

Expand Down Expand Up @@ -599,9 +596,6 @@ msgstr "Utilização do bloco indisponível"
msgid "Blocks History"
msgstr "Histórico de Blocos"

msgid "Confirmed federation BTC holdings divided by circulating L-BTC supply."
msgstr "Reservas confirmadas de BTC da federação divididas pela oferta de L-BTC em circulação."

msgid "Confirmed peg-ins minus confirmed peg-outs."
msgstr "Peg-ins confirmados menos peg-outs confirmados."

Expand Down
2 changes: 0 additions & 2 deletions lang/strings.txt
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ Asset commitment
Asset ID
Asset name
Asset: %s
Assets vs Liabilities
Average
Bits
BLOCK
Expand Down Expand Up @@ -42,7 +41,6 @@ EXPECTED INTERVAL REACHED
compared to bitcoind's suggested fee of %s sat/vB for confirmation within 2 blocks
Confidential
Confirmed
Confirmed federation BTC holdings divided by circulating L-BTC supply.
Confirmed non-confidential tx count
Confirmed peg-ins minus confirmed peg-outs.
Confirmed received
Expand Down
67 changes: 8 additions & 59 deletions test/peg.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,53 +7,26 @@ const { pegInfo } = require("../client/src/views/peg-info");
const l10n = require("../client/src/l10n").default;
const { nativeAssetId } = require("../client/src/const");

test("derives federation assets and circulating liabilities from distinct peg fields", () => {
test("derives federation assets from peg amounts", () => {
const accounting = getPegAccounting({
peg_in_amount: 100_000_000_000,
peg_out_amount: 10_000_000_000,
burned_amount: 1_000_000_000,
});

assert.equal(accounting.federationAssets, 90_000_000_000);
assert.equal(accounting.circulatingLiabilities, 89_000_000_000);
assert.equal(
accounting.assetsVsLiabilitiesRatio,
90_000_000_000 / 89_000_000_000 * 100,
);
});

test("keeps burns separate from peg-outs and handles invalid ratios", () => {
const withoutBurns = getPegAccounting({
peg_in_amount: 1000,
peg_out_amount: 100,
burned_amount: 0,
});
const withoutLiabilities = getPegAccounting({
peg_in_amount: 1000,
peg_out_amount: 100,
burned_amount: 900,
});
test("handles invalid or incomplete peg amounts", () => {
const invalidAssets = getPegAccounting({
peg_in_amount: 100,
peg_out_amount: 101,
burned_amount: 0,
});
const incompleteStats = getPegAccounting({
peg_in_amount: 100,
peg_out_amount: 10,
});

assert.equal(withoutBurns.pegOutAmount, 100);
assert.equal(withoutBurns.federationAssets, 900);
assert.equal(withoutBurns.circulatingLiabilities, 900);
assert.equal(withoutBurns.assetsVsLiabilitiesRatio, 100);
assert.equal(withoutLiabilities.assetsVsLiabilitiesRatio, null);
assert.equal(invalidAssets.federationAssets, null);
assert.equal(invalidAssets.circulatingLiabilities, null);
assert.equal(invalidAssets.assetsVsLiabilitiesRatio, null);
assert.equal(incompleteStats.federationAssets, 90);
assert.equal(incompleteStats.circulatingLiabilities, null);
assert.equal(incompleteStats.assetsVsLiabilitiesRatio, null);
assert.equal(incompleteStats.federationAssets, null);
});

test("renders holdings in BTC and aggregate volumes with two decimal places", () => {
Expand All @@ -63,12 +36,10 @@ test("renders holdings in BTC and aggregate volumes with two decimal places", ()
peg_in_amount: 100_000_000_000,
peg_out_count: 4,
peg_out_amount: 10_000_000_000,
burned_amount: 1_000_000_000,
},
}, [], { t: l10n.en, feeEst: null }));

assert.match(html, />900\.00000000 BTC</);
assert.match(html, />101\.124%<\/p>/);
assert.match(html, /VOLUME IN<\/div><div class="info-stat-value">~1,000\.00</);
assert.match(html, /VOLUME OUT<\/div><div class="info-stat-value">~100\.00</);
});
Expand Down Expand Up @@ -101,7 +72,6 @@ test("passes peg information copy through localization", () => {
peg_in_amount: 600,
peg_out_count: 1,
peg_out_amount: 400,
burned_amount: 0,
},
}, txs, { t, feeEst: null }));

Expand All @@ -110,8 +80,6 @@ test("passes peg information copy through localization", () => {
"Federation BTC Holdings",
"Confirmed peg-ins minus confirmed peg-outs.",
"Last change on %s",
"Assets vs Liabilities",
"Confirmed federation BTC holdings divided by circulating L-BTC supply.",
"Recent Peg-Ins/Outs",
"PEG-IN",
"PEG-OUT",
Expand Down Expand Up @@ -141,7 +109,6 @@ test("expands a transaction containing both peg directions into two event rows",
peg_in_amount: 1010,
peg_out_count: 1,
peg_out_amount: 400,
burned_amount: 0,
},
}, [{
txid,
Expand All @@ -168,7 +135,6 @@ test("subtracts regular native inputs when deriving a peg-in amount", () => {
peg_in_amount: 610,
peg_out_count: 0,
peg_out_amount: 0,
burned_amount: 0,
},
}, [{
txid: "b".repeat(64),
Expand All @@ -189,8 +155,8 @@ test("subtracts regular native inputs when deriving a peg-in amount", () => {
assert.match(html, /0\.00000610 BTC/);
});

test("shows at most four recent peg transactions", () => {
const txs = Array.from({ length: 5 }, (_, index) => ({
test("shows at most seven recent peg transactions", () => {
const txs = Array.from({ length: 8 }, (_, index) => ({
txid: String(index + 1).repeat(64),
vin: [{ is_pegin: true }],
vout: [{ asset: nativeAssetId, value: 100 + index }],
Expand All @@ -202,33 +168,17 @@ test("shows at most four recent peg transactions", () => {
}));
const html = render(pegInfo({
chain_stats: {
peg_in_count: 5,
peg_in_amount: 510,
peg_in_count: 8,
peg_in_amount: 828,
peg_out_count: 0,
peg_out_amount: 0,
burned_amount: 0,
},
}, txs, { t: l10n.en, feeEst: null }));

assert.equal((html.match(/href="tx\//g) || []).length, 4);
assert.equal((html.match(/href="tx\//g) || []).length, 7);
assert.doesNotMatch(html, new RegExp(`href="tx/${txs[0].txid}"`));
});

test("keeps the ratio within a parity-centered gauge with headroom", () => {
const html = render(pegInfo({
chain_stats: {
peg_in_count: 1,
peg_in_amount: 100_000_000_000,
peg_out_count: 1,
peg_out_amount: 50_000_000_000,
burned_amount: 100_000_000,
},
}, [], { t: l10n.en, feeEst: null }));

assert.match(html, /99\.7%<\/p><p>100\.0%<\/p><p>100\.3%/);
assert.doesNotMatch(html, /assets-vs-liabilities-fill" style="width: 100%/);
});

test("renders an unavailable state when peg requests fail", () => {
const html = render(pegInfo(null, null, {
t: l10n.en,
Expand All @@ -247,7 +197,6 @@ test("keeps previous peg data visible when a refresh fails", () => {
peg_in_amount: 100_000_000_000,
peg_out_count: 4,
peg_out_amount: 10_000_000_000,
burned_amount: 1_000_000_000,
},
}, [], {
t: l10n.en,
Expand Down
47 changes: 6 additions & 41 deletions www/style.css
Original file line number Diff line number Diff line change
Expand Up @@ -4100,7 +4100,13 @@ a.back-link img{
min-width: 0;
}

.proof-of-reserves-container {
display: flex;
flex-direction: column;
}

.peg-info {
flex: 1;
display: flex;
flex-direction: column;
gap: var(--page-gap);
Expand Down Expand Up @@ -4128,47 +4134,6 @@ a.back-link img{
width: 100%;
}

.assets-vs-liabilities {
width: 100%;
height: auto;
}

.assets-vs-liabilities-body {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
margin-top: 13px;
gap: 6px;
}

.assets-vs-liabilities-scale {
display: flex;
justify-content: space-between;
font-size: 14px;
font-weight: 600;
width: 100%;
}

.assets-vs-liabilities-bar {
width: 100%;
height: 6px;
border-radius: 9999px;
background-color: var(--surface-secondary-color);
}

.assets-vs-liabilities-fill {
height: 100%;
background-color: var(--accent-color);
border-radius: 9999px;
}

.assets-vs-liabilities-ratio {
font-size: 20px;
font-weight: 700;
font-family: "Rigid Square";
}

.peg-transaction-table {
display: flex;
flex-direction: column;
Expand Down
Loading