diff --git a/packages/wallet-service/src/api/balances.ts b/packages/wallet-service/src/api/balances.ts index e5daac65..8a09b7d7 100644 --- a/packages/wallet-service/src/api/balances.ts +++ b/packages/wallet-service/src/api/balances.ts @@ -13,6 +13,7 @@ import { closeDbAndGetError, warmupMiddleware } from '@src/api/utils'; import { getWalletBalances, walletIdProxyHandler } from '@src/commons'; import { getWallet, + getTokenInformation, } from '@src/db'; import { closeDbConnection, @@ -24,6 +25,7 @@ import cors from '@middy/http-cors'; import Joi from 'joi'; import errorHandler from '@src/api/middlewares/errorHandler'; import { bigIntUtils } from '@hathor/wallet-lib'; +import { WalletTokenBalance, Balance } from '@src/types'; const mysql = getDbConnection(); @@ -74,7 +76,15 @@ export const get: APIGatewayProxyHandler = middy(walletIdProxyHandler(async (wal tokenIds.push(tokenId); } - const balances = await getWalletBalances(mysql, getUnixTimestamp(), walletId, tokenIds); + let balances = await getWalletBalances(mysql, getUnixTimestamp(), walletId, tokenIds); + + // If a specific token was requested but wallet has no balance, return zero balance + if (value.token_id && balances.length === 0) { + const tokenInfo = await getTokenInformation(mysql, value.token_id); + if (tokenInfo) { + balances = [new WalletTokenBalance(tokenInfo, new Balance(), 0)]; + } + } await closeDbConnection(mysql); diff --git a/packages/wallet-service/tests/api.test.ts b/packages/wallet-service/tests/api.test.ts index 2417d74d..cdb2a6bc 100644 --- a/packages/wallet-service/tests/api.test.ts +++ b/packages/wallet-service/tests/api.test.ts @@ -635,6 +635,33 @@ test('GET /balances', async () => { lockExpires: null, tokenAuthorities: { unlocked: { mint: false, melt: false }, locked: { mint: false, melt: false } }, }); + + // request balance for a token the wallet doesn't have - should return zero balance + const tokenNotOwned = { id: 'tokennotowned', name: 'NotOwnedToken', symbol: 'NOT' }; + await addToTokenTable(mysql, [ + { id: tokenNotOwned.id, name: tokenNotOwned.name, symbol: tokenNotOwned.symbol, transactions: 0 }, + ]); + event = makeGatewayEventWithAuthorizer('my-wallet', { token_id: 'tokennotowned' }); + result = await balancesGet(event, null, null) as APIGatewayProxyResult; + returnBody = JSON.parse(result.body as string); + expect(result.statusCode).toBe(200); + expect(returnBody.success).toBe(true); + expect(returnBody.balances).toHaveLength(1); + expect(returnBody.balances).toContainEqual({ + token: tokenNotOwned, + transactions: 0, + balance: { unlocked: 0, locked: 0 }, + lockExpires: null, + tokenAuthorities: { unlocked: { mint: false, melt: false }, locked: { mint: false, melt: false } }, + }); + + // request balance for a token that doesn't exist - should return empty array + event = makeGatewayEventWithAuthorizer('my-wallet', { token_id: 'nonexistenttoken' }); + result = await balancesGet(event, null, null) as APIGatewayProxyResult; + returnBody = JSON.parse(result.body as string); + expect(result.statusCode).toBe(200); + expect(returnBody.success).toBe(true); + expect(returnBody.balances).toHaveLength(0); }); test('GET /txhistory', async () => {