Skip to content

Commit 5330c07

Browse files
authored
feat: show pending inbound and outbound stx balances (#2208)
* feat: add estimated inbound and outbound stx balance * fix: add select * fix: query * test: pending balance * fix: address tests
1 parent 396e2ea commit 5330c07

File tree

6 files changed

+67
-12
lines changed

6 files changed

+67
-12
lines changed

src/api/routes/address.ts

+16-4
Original file line numberDiff line numberDiff line change
@@ -121,13 +121,19 @@ export const AddressRoutes: FastifyPluginAsync<
121121
blockHeight
122122
);
123123
let mempoolBalance: bigint | undefined = undefined;
124+
let mempoolInbound: bigint | undefined = undefined;
125+
let mempoolOutbound: bigint | undefined = undefined;
124126
if (req.query.until_block === undefined) {
125-
const delta = await fastify.db.getPrincipalMempoolStxBalanceDelta(sql, stxAddress);
126-
mempoolBalance = stxBalanceResult.balance + delta;
127+
const pending = await fastify.db.getPrincipalMempoolStxBalanceDelta(sql, stxAddress);
128+
mempoolInbound = pending.inbound;
129+
mempoolOutbound = pending.outbound;
130+
mempoolBalance = stxBalanceResult.balance + pending.delta;
127131
}
128132
const result: AddressStxBalance = {
129133
balance: stxBalanceResult.balance.toString(),
130134
estimated_balance: mempoolBalance?.toString(),
135+
pending_balance_inbound: mempoolInbound?.toString(),
136+
pending_balance_outbound: mempoolOutbound?.toString(),
131137
total_sent: stxBalanceResult.totalSent.toString(),
132138
total_received: stxBalanceResult.totalReceived.toString(),
133139
total_fees_sent: stxBalanceResult.totalFeesSent.toString(),
@@ -211,15 +217,21 @@ export const AddressRoutes: FastifyPluginAsync<
211217
});
212218

213219
let mempoolBalance: bigint | undefined = undefined;
220+
let mempoolInbound: bigint | undefined = undefined;
221+
let mempoolOutbound: bigint | undefined = undefined;
214222
if (req.query.until_block === undefined) {
215-
const delta = await fastify.db.getPrincipalMempoolStxBalanceDelta(sql, stxAddress);
216-
mempoolBalance = stxBalanceResult.balance + delta;
223+
const pending = await fastify.db.getPrincipalMempoolStxBalanceDelta(sql, stxAddress);
224+
mempoolInbound = pending.inbound;
225+
mempoolOutbound = pending.outbound;
226+
mempoolBalance = stxBalanceResult.balance + pending.delta;
217227
}
218228

219229
const result: AddressBalance = {
220230
stx: {
221231
balance: stxBalanceResult.balance.toString(),
222232
estimated_balance: mempoolBalance?.toString(),
233+
pending_balance_inbound: mempoolInbound?.toString(),
234+
pending_balance_outbound: mempoolOutbound?.toString(),
223235
total_sent: stxBalanceResult.totalSent.toString(),
224236
total_received: stxBalanceResult.totalReceived.toString(),
225237
total_fees_sent: stxBalanceResult.totalFeesSent.toString(),

src/api/schemas/entities/balances.ts

+10
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,16 @@ export const StxBalanceSchema = Type.Object(
2626
description: 'Total STX balance considering pending mempool transactions',
2727
})
2828
),
29+
pending_balance_inbound: Type.Optional(
30+
Type.String({
31+
description: 'Inbound STX balance from pending mempool transactions',
32+
})
33+
),
34+
pending_balance_outbound: Type.Optional(
35+
Type.String({
36+
description: 'Outbound STX balance from pending mempool transactions',
37+
})
38+
),
2939
total_sent: Type.String(),
3040
total_received: Type.String(),
3141
total_fees_sent: Type.String(),

src/datastore/pg-store.ts

+13-8
Original file line numberDiff line numberDiff line change
@@ -2480,8 +2480,8 @@ export class PgStore extends BasePgStore {
24802480
* Returns the total STX balance delta affecting a principal from transactions currently in the
24812481
* mempool.
24822482
*/
2483-
async getPrincipalMempoolStxBalanceDelta(sql: PgSqlClient, principal: string): Promise<bigint> {
2484-
const results = await sql<{ delta: string }[]>`
2483+
async getPrincipalMempoolStxBalanceDelta(sql: PgSqlClient, principal: string) {
2484+
const results = await sql<{ inbound: string; outbound: string; delta: string }[]>`
24852485
WITH sent AS (
24862486
SELECT SUM(COALESCE(token_transfer_amount, 0) + fee_rate) AS total
24872487
FROM mempool_txs
@@ -2496,14 +2496,19 @@ export class PgStore extends BasePgStore {
24962496
SELECT SUM(COALESCE(token_transfer_amount, 0)) AS total
24972497
FROM mempool_txs
24982498
WHERE pruned = false AND token_transfer_recipient_address = ${principal}
2499+
),
2500+
values AS (
2501+
SELECT
2502+
COALESCE((SELECT total FROM received), 0) AS inbound,
2503+
COALESCE((SELECT total FROM sent), 0) + COALESCE((SELECT total FROM sponsored), 0) AS outbound
24992504
)
2500-
SELECT
2501-
COALESCE((SELECT total FROM received), 0)
2502-
- COALESCE((SELECT total FROM sent), 0)
2503-
- COALESCE((SELECT total FROM sponsored), 0)
2504-
AS delta
2505+
SELECT inbound, outbound, (inbound - outbound) AS delta FROM values
25052506
`;
2506-
return BigInt(results[0]?.delta ?? '0');
2507+
return {
2508+
inbound: BigInt(results[0]?.inbound ?? '0'),
2509+
outbound: BigInt(results[0]?.outbound ?? '0'),
2510+
delta: BigInt(results[0]?.delta ?? '0'),
2511+
};
25072512
}
25082513

25092514
async getUnlockedStxSupply(

tests/api/address.test.ts

+8
Original file line numberDiff line numberDiff line change
@@ -1551,6 +1551,8 @@ describe('address tests', () => {
15511551
stx: {
15521552
balance: '88679',
15531553
estimated_balance: '88679',
1554+
pending_balance_inbound: '0',
1555+
pending_balance_outbound: '0',
15541556
total_sent: '6385',
15551557
total_received: '100000',
15561558
total_fees_sent: '4936',
@@ -1601,6 +1603,8 @@ describe('address tests', () => {
16011603
stx: {
16021604
balance: '91',
16031605
estimated_balance: '91',
1606+
pending_balance_inbound: '0',
1607+
pending_balance_outbound: '0',
16041608
total_sent: '15',
16051609
total_received: '1350',
16061610
total_fees_sent: '1244',
@@ -1637,6 +1641,8 @@ describe('address tests', () => {
16371641
const expectedStxResp1 = {
16381642
balance: '91',
16391643
estimated_balance: '91',
1644+
pending_balance_inbound: '0',
1645+
pending_balance_outbound: '0',
16401646
total_sent: '15',
16411647
total_received: '1350',
16421648
total_fees_sent: '1244',
@@ -1668,6 +1674,8 @@ describe('address tests', () => {
16681674
const expectedStxResp1Sponsored = {
16691675
balance: '3766',
16701676
estimated_balance: '3766',
1677+
pending_balance_inbound: '0',
1678+
pending_balance_outbound: '0',
16711679
total_sent: '0',
16721680
total_received: '5000',
16731681
total_fees_sent: '1234',

tests/api/mempool.test.ts

+12
Original file line numberDiff line numberDiff line change
@@ -2208,6 +2208,8 @@ describe('mempool tests', () => {
22082208
const balance0 = await supertest(api.server).get(url);
22092209
expect(balance0.body.balance).toEqual('2000');
22102210
expect(balance0.body.estimated_balance).toEqual('2000');
2211+
expect(balance0.body.pending_balance_inbound).toEqual('0');
2212+
expect(balance0.body.pending_balance_outbound).toEqual('0');
22112213

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

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

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

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

22772287
// Confirm all txs
22782288
await db.update(
@@ -2317,5 +2327,7 @@ describe('mempool tests', () => {
23172327
const balance4 = await supertest(api.server).get(url);
23182328
expect(balance4.body.balance).toEqual('1850');
23192329
expect(balance4.body.estimated_balance).toEqual('1850');
2330+
expect(balance4.body.pending_balance_inbound).toEqual('0');
2331+
expect(balance4.body.pending_balance_outbound).toEqual('0');
23202332
});
23212333
});

tests/api/tx.test.ts

+8
Original file line numberDiff line numberDiff line change
@@ -1031,6 +1031,8 @@ describe('tx tests', () => {
10311031
const expectedSponsoredRespBefore = {
10321032
balance: '0',
10331033
estimated_balance: '0',
1034+
pending_balance_inbound: '0',
1035+
pending_balance_outbound: '0',
10341036
total_sent: '0',
10351037
total_received: '0',
10361038
total_fees_sent: '0',
@@ -1139,6 +1141,8 @@ describe('tx tests', () => {
11391141
const expectedResp = {
11401142
balance: '0',
11411143
estimated_balance: '0',
1144+
pending_balance_inbound: '0',
1145+
pending_balance_outbound: '0',
11421146
total_sent: '0',
11431147
total_received: '0',
11441148
total_fees_sent: '0',
@@ -1158,6 +1162,8 @@ describe('tx tests', () => {
11581162
stx: {
11591163
balance: '0',
11601164
estimated_balance: '0',
1165+
pending_balance_inbound: '0',
1166+
pending_balance_outbound: '0',
11611167
total_sent: '0',
11621168
total_received: '0',
11631169
total_fees_sent: '0',
@@ -1181,6 +1187,8 @@ describe('tx tests', () => {
11811187
const expectedSponsoredRespAfter = {
11821188
balance: '-300',
11831189
estimated_balance: '-300',
1190+
pending_balance_inbound: '0',
1191+
pending_balance_outbound: '0',
11841192
total_sent: '0',
11851193
total_received: '0',
11861194
total_fees_sent: '300',

0 commit comments

Comments
 (0)