11import {
2+ ETagType ,
3+ handleCache ,
24 handlePrincipalCache ,
35 handlePrincipalMempoolCache ,
46 handleTransactionCache ,
@@ -13,17 +15,15 @@ import { LimitParam, OffsetParam, PrincipalSchema } from '../../schemas/params';
1315import { getPagingQueryLimit , ResourceType } from '../../pagination' ;
1416import { PaginatedResponse } from '../../schemas/util' ;
1517import {
16- AddressBalance ,
17- AddressBalanceSchema ,
18- AddressBalanceV2 ,
19- AddressBalanceV2Schema ,
2018 AddressTransaction ,
2119 AddressTransactionEvent ,
2220 AddressTransactionEventSchema ,
2321 AddressTransactionSchema ,
22+ PrincipalFtBalance ,
23+ PrincipalFtBalanceSchema ,
2424} from '../../schemas/entities/addresses' ;
25- import { formatMapToObject } from '../../../helpers' ;
2625import { validatePrincipal } from '../../query-helpers' ;
26+ import { StxBalance , StxBalanceSchema } from '../../schemas/entities/balances' ;
2727
2828export const AddressRoutesV2 : FastifyPluginAsync <
2929 Record < never , never > ,
@@ -125,21 +125,31 @@ export const AddressRoutesV2: FastifyPluginAsync<
125125 }
126126 ) ;
127127
128- // get balances for STX, FTs, and counts for NFTs
129128 fastify . get (
130- '/:principal/balances' ,
129+ '/:principal/balances/stx ' ,
131130 {
132- preHandler : handlePrincipalMempoolCache ,
131+ preHandler : ( req , reply ) => {
132+ const etagType = req . query . include_mempool ? ETagType . principalMempool : ETagType . principal ;
133+ return handleCache ( etagType , req , reply ) ;
134+ } ,
133135 schema : {
134- operationId : 'get_principal_balances ' ,
135- summary : 'Get principal balances ' ,
136- description : `Retrieves total account balance information for a given Address or Contract Identifier. This includes the balances of STX Tokens and Fungible Tokens for the account .` ,
136+ operationId : 'get_principal_stx_balance ' ,
137+ summary : 'Get principal STX balance ' ,
138+ description : `Retrieves STX account balance information for a given Address or Contract Identifier.` ,
137139 tags : [ 'Accounts' ] ,
138140 params : Type . Object ( {
139141 principal : PrincipalSchema ,
140142 } ) ,
143+ querystring : Type . Object ( {
144+ include_mempool : Type . Optional (
145+ Type . Boolean ( {
146+ description : 'Include pending mempool transactions in the balance calculation' ,
147+ default : false ,
148+ } )
149+ ) ,
150+ } ) ,
141151 response : {
142- 200 : AddressBalanceV2Schema ,
152+ 200 : StxBalanceSchema ,
143153 } ,
144154 } ,
145155 } ,
@@ -150,21 +160,12 @@ export const AddressRoutesV2: FastifyPluginAsync<
150160 const result = await fastify . db . sqlTransaction ( async sql => {
151161 const chainTip = await fastify . db . getChainTip ( sql ) ;
152162
153- // Get balances for fungible tokens
154- const ftBalancesResult = await fastify . db . v2 . getFungibleTokenHolderBalances ( {
163+ // Get stx balance (sum of credits, debits, and fees) for address
164+ const stxBalancesResult = await fastify . db . v2 . getStxHolderBalance ( {
155165 sql,
156166 stxAddress,
157167 } ) ;
158- const ftBalances : Record < string , string > = { } ;
159- for ( const { token, balance } of ftBalancesResult ) {
160- if ( token !== 'stx' ) {
161- ftBalances [ token ] = balance ;
162- }
163- }
164-
165- // Get stx balance (sum of credits, debits, and fees) for address
166- const stxBalanceResult = ftBalancesResult . find ( entry => entry . token === 'stx' ) ;
167- let stxBalance = BigInt ( stxBalanceResult ?. balance ?? '0' ) ;
168+ let stxBalance = stxBalancesResult . found ? stxBalancesResult . result . balance : 0n ;
168169
169170 // Get pox-locked info for STX token
170171 const stxPoxLockedResult = await fastify . db . v2 . getStxPoxLockedAtBlock ( {
@@ -182,23 +183,78 @@ export const AddressRoutesV2: FastifyPluginAsync<
182183 } ) ;
183184 stxBalance += totalMinerRewardsReceived ;
184185
185- const mempoolResult = await fastify . db . getPrincipalMempoolStxBalanceDelta ( sql , stxAddress ) ;
186- const mempoolBalance : bigint = stxBalance + mempoolResult . delta ;
186+ const result : StxBalance = {
187+ balance : stxBalance . toString ( ) ,
188+ total_miner_rewards_received : totalMinerRewardsReceived . toString ( ) ,
189+ lock_tx_id : stxPoxLockedResult . lockTxId ,
190+ locked : stxPoxLockedResult . locked . toString ( ) ,
191+ lock_height : stxPoxLockedResult . lockHeight ,
192+ burnchain_lock_height : stxPoxLockedResult . burnchainLockHeight ,
193+ burnchain_unlock_height : stxPoxLockedResult . burnchainUnlockHeight ,
194+ } ;
195+
196+ if ( req . query . include_mempool ) {
197+ const mempoolResult = await fastify . db . getPrincipalMempoolStxBalanceDelta (
198+ sql ,
199+ stxAddress
200+ ) ;
201+ const mempoolBalance = stxBalance + mempoolResult . delta ;
202+ result . estimated_balance = mempoolBalance . toString ( ) ;
203+ result . pending_balance_inbound = mempoolResult . inbound . toString ( ) ;
204+ result . pending_balance_outbound = mempoolResult . outbound . toString ( ) ;
205+ }
206+
207+ return result ;
208+ } ) ;
209+ await reply . send ( result ) ;
210+ }
211+ ) ;
187212
188- const result : AddressBalanceV2 = {
189- stx : {
190- balance : stxBalance . toString ( ) ,
191- estimated_balance : mempoolBalance . toString ( ) ,
192- pending_balance_inbound : mempoolResult . inbound . toString ( ) ,
193- pending_balance_outbound : mempoolResult . outbound . toString ( ) ,
194- total_miner_rewards_received : totalMinerRewardsReceived . toString ( ) ,
195- lock_tx_id : stxPoxLockedResult . lockTxId ,
196- locked : stxPoxLockedResult . locked . toString ( ) ,
197- lock_height : stxPoxLockedResult . lockHeight ,
198- burnchain_lock_height : stxPoxLockedResult . burnchainLockHeight ,
199- burnchain_unlock_height : stxPoxLockedResult . burnchainUnlockHeight ,
200- } ,
201- fungible_tokens : ftBalances ,
213+ fastify . get (
214+ '/:principal/balances/ft' ,
215+ {
216+ preHandler : handlePrincipalMempoolCache ,
217+ schema : {
218+ operationId : 'get_principal_ft_balances' ,
219+ summary : 'Get principal FT balances' ,
220+ description : `Retrieves Fungible-token account balance information for a given Address or Contract Identifier.` ,
221+ tags : [ 'Accounts' ] ,
222+ params : Type . Object ( {
223+ principal : PrincipalSchema ,
224+ } ) ,
225+ querystring : Type . Object ( {
226+ limit : LimitParam ( ResourceType . FtBalance ) ,
227+ offset : OffsetParam ( ) ,
228+ } ) ,
229+ response : {
230+ 200 : PaginatedResponse ( PrincipalFtBalanceSchema ) ,
231+ } ,
232+ } ,
233+ } ,
234+ async ( req , reply ) => {
235+ const stxAddress = req . params . principal ;
236+ validatePrincipal ( stxAddress ) ;
237+ const limit = getPagingQueryLimit ( ResourceType . FtBalance , req . query . limit ) ;
238+ const offset = req . query . offset ?? 0 ;
239+ const result = await fastify . db . sqlTransaction ( async sql => {
240+ // Get balances for fungible tokens
241+ const ftBalancesResult = await fastify . db . v2 . getFungibleTokenHolderBalances ( {
242+ sql,
243+ stxAddress,
244+ limit,
245+ offset,
246+ } ) ;
247+ const ftBalances : PrincipalFtBalance [ ] = ftBalancesResult . results . map (
248+ ( { token, balance } ) => ( {
249+ token,
250+ balance,
251+ } )
252+ ) ;
253+ const result = {
254+ limit,
255+ offset,
256+ total : ftBalancesResult . total ,
257+ results : ftBalances ,
202258 } ;
203259 return result ;
204260 } ) ;
0 commit comments