Skip to content

Commit

Permalink
feat: show pending inbound and outbound stx balances (#2208)
Browse files Browse the repository at this point in the history
* feat: add estimated inbound and outbound stx balance

* fix: add select

* fix: query

* test: pending balance

* fix: address tests
  • Loading branch information
rafaelcr authored Jan 29, 2025
1 parent 396e2ea commit 5330c07
Show file tree
Hide file tree
Showing 6 changed files with 67 additions and 12 deletions.
20 changes: 16 additions & 4 deletions src/api/routes/address.ts
Original file line number Diff line number Diff line change
Expand Up @@ -121,13 +121,19 @@ export const AddressRoutes: FastifyPluginAsync<
blockHeight
);
let mempoolBalance: bigint | undefined = undefined;
let mempoolInbound: bigint | undefined = undefined;
let mempoolOutbound: bigint | undefined = undefined;
if (req.query.until_block === undefined) {
const delta = await fastify.db.getPrincipalMempoolStxBalanceDelta(sql, stxAddress);
mempoolBalance = stxBalanceResult.balance + delta;
const pending = await fastify.db.getPrincipalMempoolStxBalanceDelta(sql, stxAddress);
mempoolInbound = pending.inbound;
mempoolOutbound = pending.outbound;
mempoolBalance = stxBalanceResult.balance + pending.delta;
}
const result: AddressStxBalance = {
balance: stxBalanceResult.balance.toString(),
estimated_balance: mempoolBalance?.toString(),
pending_balance_inbound: mempoolInbound?.toString(),
pending_balance_outbound: mempoolOutbound?.toString(),
total_sent: stxBalanceResult.totalSent.toString(),
total_received: stxBalanceResult.totalReceived.toString(),
total_fees_sent: stxBalanceResult.totalFeesSent.toString(),
Expand Down Expand Up @@ -211,15 +217,21 @@ export const AddressRoutes: FastifyPluginAsync<
});

let mempoolBalance: bigint | undefined = undefined;
let mempoolInbound: bigint | undefined = undefined;
let mempoolOutbound: bigint | undefined = undefined;
if (req.query.until_block === undefined) {
const delta = await fastify.db.getPrincipalMempoolStxBalanceDelta(sql, stxAddress);
mempoolBalance = stxBalanceResult.balance + delta;
const pending = await fastify.db.getPrincipalMempoolStxBalanceDelta(sql, stxAddress);
mempoolInbound = pending.inbound;
mempoolOutbound = pending.outbound;
mempoolBalance = stxBalanceResult.balance + pending.delta;
}

const result: AddressBalance = {
stx: {
balance: stxBalanceResult.balance.toString(),
estimated_balance: mempoolBalance?.toString(),
pending_balance_inbound: mempoolInbound?.toString(),
pending_balance_outbound: mempoolOutbound?.toString(),
total_sent: stxBalanceResult.totalSent.toString(),
total_received: stxBalanceResult.totalReceived.toString(),
total_fees_sent: stxBalanceResult.totalFeesSent.toString(),
Expand Down
10 changes: 10 additions & 0 deletions src/api/schemas/entities/balances.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,16 @@ export const StxBalanceSchema = Type.Object(
description: 'Total STX balance considering pending mempool transactions',
})
),
pending_balance_inbound: Type.Optional(
Type.String({
description: 'Inbound STX balance from pending mempool transactions',
})
),
pending_balance_outbound: Type.Optional(
Type.String({
description: 'Outbound STX balance from pending mempool transactions',
})
),
total_sent: Type.String(),
total_received: Type.String(),
total_fees_sent: Type.String(),
Expand Down
21 changes: 13 additions & 8 deletions src/datastore/pg-store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2480,8 +2480,8 @@ export class PgStore extends BasePgStore {
* Returns the total STX balance delta affecting a principal from transactions currently in the
* mempool.
*/
async getPrincipalMempoolStxBalanceDelta(sql: PgSqlClient, principal: string): Promise<bigint> {
const results = await sql<{ delta: string }[]>`
async getPrincipalMempoolStxBalanceDelta(sql: PgSqlClient, principal: string) {
const results = await sql<{ inbound: string; outbound: string; delta: string }[]>`
WITH sent AS (
SELECT SUM(COALESCE(token_transfer_amount, 0) + fee_rate) AS total
FROM mempool_txs
Expand All @@ -2496,14 +2496,19 @@ export class PgStore extends BasePgStore {
SELECT SUM(COALESCE(token_transfer_amount, 0)) AS total
FROM mempool_txs
WHERE pruned = false AND token_transfer_recipient_address = ${principal}
),
values AS (
SELECT
COALESCE((SELECT total FROM received), 0) AS inbound,
COALESCE((SELECT total FROM sent), 0) + COALESCE((SELECT total FROM sponsored), 0) AS outbound
)
SELECT
COALESCE((SELECT total FROM received), 0)
- COALESCE((SELECT total FROM sent), 0)
- COALESCE((SELECT total FROM sponsored), 0)
AS delta
SELECT inbound, outbound, (inbound - outbound) AS delta FROM values
`;
return BigInt(results[0]?.delta ?? '0');
return {
inbound: BigInt(results[0]?.inbound ?? '0'),
outbound: BigInt(results[0]?.outbound ?? '0'),
delta: BigInt(results[0]?.delta ?? '0'),
};
}

async getUnlockedStxSupply(
Expand Down
8 changes: 8 additions & 0 deletions tests/api/address.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1551,6 +1551,8 @@ describe('address tests', () => {
stx: {
balance: '88679',
estimated_balance: '88679',
pending_balance_inbound: '0',
pending_balance_outbound: '0',
total_sent: '6385',
total_received: '100000',
total_fees_sent: '4936',
Expand Down Expand Up @@ -1601,6 +1603,8 @@ describe('address tests', () => {
stx: {
balance: '91',
estimated_balance: '91',
pending_balance_inbound: '0',
pending_balance_outbound: '0',
total_sent: '15',
total_received: '1350',
total_fees_sent: '1244',
Expand Down Expand Up @@ -1637,6 +1641,8 @@ describe('address tests', () => {
const expectedStxResp1 = {
balance: '91',
estimated_balance: '91',
pending_balance_inbound: '0',
pending_balance_outbound: '0',
total_sent: '15',
total_received: '1350',
total_fees_sent: '1244',
Expand Down Expand Up @@ -1668,6 +1674,8 @@ describe('address tests', () => {
const expectedStxResp1Sponsored = {
balance: '3766',
estimated_balance: '3766',
pending_balance_inbound: '0',
pending_balance_outbound: '0',
total_sent: '0',
total_received: '5000',
total_fees_sent: '1234',
Expand Down
12 changes: 12 additions & 0 deletions tests/api/mempool.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2208,6 +2208,8 @@ describe('mempool tests', () => {
const balance0 = await supertest(api.server).get(url);
expect(balance0.body.balance).toEqual('2000');
expect(balance0.body.estimated_balance).toEqual('2000');
expect(balance0.body.pending_balance_inbound).toEqual('0');
expect(balance0.body.pending_balance_outbound).toEqual('0');

// STX transfer in mempool
await db.updateMempoolTxs({
Expand All @@ -2223,6 +2225,8 @@ describe('mempool tests', () => {
const balance1 = await supertest(api.server).get(url);
expect(balance1.body.balance).toEqual('2000');
expect(balance1.body.estimated_balance).toEqual('1850'); // Minus amount and fee
expect(balance1.body.pending_balance_inbound).toEqual('0');
expect(balance1.body.pending_balance_outbound).toEqual('150');

// Contract call in mempool
await db.updateMempoolTxs({
Expand All @@ -2242,6 +2246,8 @@ describe('mempool tests', () => {
const balance1b = await supertest(api.server).get(url);
expect(balance1b.body.balance).toEqual('2000');
expect(balance1b.body.estimated_balance).toEqual('1800'); // Minus fee
expect(balance1b.body.pending_balance_inbound).toEqual('0');
expect(balance1b.body.pending_balance_outbound).toEqual('200');

// Sponsored tx in mempool
await db.updateMempoolTxs({
Expand All @@ -2258,6 +2264,8 @@ describe('mempool tests', () => {
const balance2 = await supertest(api.server).get(url);
expect(balance2.body.balance).toEqual('2000');
expect(balance2.body.estimated_balance).toEqual('1750'); // Minus fee
expect(balance2.body.pending_balance_inbound).toEqual('0');
expect(balance2.body.pending_balance_outbound).toEqual('250');

// STX received in mempool
await db.updateMempoolTxs({
Expand All @@ -2273,6 +2281,8 @@ describe('mempool tests', () => {
const balance3 = await supertest(api.server).get(url);
expect(balance3.body.balance).toEqual('2000');
expect(balance3.body.estimated_balance).toEqual('1850'); // Plus amount
expect(balance3.body.pending_balance_inbound).toEqual('100');
expect(balance3.body.pending_balance_outbound).toEqual('250');

// Confirm all txs
await db.update(
Expand Down Expand Up @@ -2317,5 +2327,7 @@ describe('mempool tests', () => {
const balance4 = await supertest(api.server).get(url);
expect(balance4.body.balance).toEqual('1850');
expect(balance4.body.estimated_balance).toEqual('1850');
expect(balance4.body.pending_balance_inbound).toEqual('0');
expect(balance4.body.pending_balance_outbound).toEqual('0');
});
});
8 changes: 8 additions & 0 deletions tests/api/tx.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1031,6 +1031,8 @@ describe('tx tests', () => {
const expectedSponsoredRespBefore = {
balance: '0',
estimated_balance: '0',
pending_balance_inbound: '0',
pending_balance_outbound: '0',
total_sent: '0',
total_received: '0',
total_fees_sent: '0',
Expand Down Expand Up @@ -1139,6 +1141,8 @@ describe('tx tests', () => {
const expectedResp = {
balance: '0',
estimated_balance: '0',
pending_balance_inbound: '0',
pending_balance_outbound: '0',
total_sent: '0',
total_received: '0',
total_fees_sent: '0',
Expand All @@ -1158,6 +1162,8 @@ describe('tx tests', () => {
stx: {
balance: '0',
estimated_balance: '0',
pending_balance_inbound: '0',
pending_balance_outbound: '0',
total_sent: '0',
total_received: '0',
total_fees_sent: '0',
Expand All @@ -1181,6 +1187,8 @@ describe('tx tests', () => {
const expectedSponsoredRespAfter = {
balance: '-300',
estimated_balance: '-300',
pending_balance_inbound: '0',
pending_balance_outbound: '0',
total_sent: '0',
total_received: '0',
total_fees_sent: '300',
Expand Down

0 comments on commit 5330c07

Please sign in to comment.