Skip to content

Extend IssuerWallet with balance and redemption queries#1624

Open
Soumya8898 wants to merge 26 commits into
hyperledger-labs:mainfrom
Soumya8898:Soumya8898/extend-issuer-wallet
Open

Extend IssuerWallet with balance and redemption queries#1624
Soumya8898 wants to merge 26 commits into
hyperledger-labs:mainfrom
Soumya8898:Soumya8898/extend-issuer-wallet

Conversation

@Soumya8898
Copy link
Copy Markdown
Contributor

@Soumya8898 Soumya8898 commented May 2, 2026

Summary

Added changes to close #872

This PR extends the IssuerWallet interface with five new methods that give issuers full visibility into their token lifecycle — from issuance through redemption — with flexible query filtering and sorting.

Motivation

The existing IssuerWallet only exposed HistoryTokens, which lists issued tokens. There was no way for an issuer to:

  • Query the total value of tokens they have issued
  • List or sum tokens that have been redeemed
  • Compute the net outstanding supply still in circulation
  • Filter any of the above by token type, issuer identity, or time range
  • Control the sort order of returned results

Issuers operating multi-wallet nodes or managing multiple token types had no first-class API for these common reporting needs.

New API Surface

Five methods added to IssuerWallet (driver and public interfaces):

Method Returns Description
IssuedBalance(ctx, opts) uint64 Sum of all non-deleted tokens issued by this wallet
RedeemedTokens(ctx, opts) *IssuedTokens List of redeemed tokens originally issued by this wallet
RedeemedBalance(ctx, opts) uint64 Sum of amounts of redeemed tokens
OutstandingBalance(ctx, opts) uint64 Net in circulation: IssuedBalance − RedeemedBalance

All methods accept *ListTokensOptions which now supports:

Option Type Effect
TokenType token.Type Filter by token type (e.g. "USD")
SortBy SortField SortByDefault or SortByQuantity
SortDirection SortDirection SortAscending or SortDescending
From / To *time.Time Restrict to tokens stored within a time range

The issuer identity filter is applied automatically — each wallet scopes queries to its own identity.

Data Model Changes

Added two fields to IssuedToken:

  • IsSpent bool — whether the token has been deleted/spent
  • SpentBy string — the transaction ID that spent the token

These fields enable the SQL layer to JOIN tokens with transactions and identify redemptions (action_type = Redeem).

SQL Implementation

  • IssuedBalance: SELECT SUM(amount) over non-deleted tokens with issuer = true, filtered by token type, issuer identity, and time range
  • ListRedeemedTokens: SELECT ... FROM tokens JOIN transactions where is_deleted = true AND action_type = Redeem, with optional ORDER BY amount ASC|DESC
  • RedeemedBalance: Same join as above but returns SUM(amount)
  • OutstandingBalance: Computed at the wallet layer as IssuedBalance − RedeemedBalance (no extra SQL query)

All SQL conditions are built dynamically — empty/nil filters are skipped, so callers only supply what they need.

Testing

  • Unit tests added for IssuedBalance, RedeemedTokens, RedeemedBalance, and OutstandingBalance
  • Covers: happy path, error propagation from vault, identity filtering, and edge cases (redeemed > issued guard)
  • Uses existing counterfeiter mock pattern (mock.IssuerTokenVault)

@Soumya8898 Soumya8898 force-pushed the Soumya8898/extend-issuer-wallet branch 3 times, most recently from 2a8c960 to 6083c16 Compare May 2, 2026 15:12
@adecaro adecaro self-requested a review May 4, 2026 05:10
@adecaro adecaro self-assigned this May 4, 2026
@adecaro adecaro added the wallet label May 4, 2026
@adecaro adecaro added this to the Q2/26 milestone May 4, 2026
@adecaro adecaro force-pushed the Soumya8898/extend-issuer-wallet branch from 6083c16 to 76d9847 Compare May 4, 2026 05:10
@adecaro
Copy link
Copy Markdown
Contributor

adecaro commented May 4, 2026

Hi @Soumya8898 , thanks for this effort. I'll review ASAP.

A quick note already: Please, extend the fungible integration test integration/token/fungible (TestAll function), to include calls to the new APIs and test against expected values.

Thanks a lot 🙏

@adecaro adecaro force-pushed the Soumya8898/extend-issuer-wallet branch from 76d9847 to 74c672a Compare May 4, 2026 09:33
Comment thread token/driver/vault.go
@Soumya8898 Soumya8898 force-pushed the Soumya8898/extend-issuer-wallet branch from 74c672a to 2e42941 Compare May 4, 2026 21:27
Comment thread token/wallet.go
Comment thread token/wallet.go
Comment thread token/vault.go
Comment thread token/wallet.go Outdated
@adecaro adecaro force-pushed the Soumya8898/extend-issuer-wallet branch from 1ee94bf to ba79a30 Compare May 5, 2026 05:46
@Soumya8898 Soumya8898 force-pushed the Soumya8898/extend-issuer-wallet branch 2 times, most recently from d3c4f5b to 1667520 Compare May 5, 2026 19:15
@Soumya8898
Copy link
Copy Markdown
Contributor Author

Hi @adecaro can you please give it another review. Thanks

@adecaro adecaro force-pushed the Soumya8898/extend-issuer-wallet branch from 9c811de to 5b5bc89 Compare May 8, 2026 07:35
@adecaro
Copy link
Copy Markdown
Contributor

adecaro commented May 8, 2026

Hi @Soumya8898 , there is something failing in the integration tests, please, have a look. Thanks 🙏

@Soumya8898 Soumya8898 force-pushed the Soumya8898/extend-issuer-wallet branch 2 times, most recently from 47a0dc3 to b37a5b2 Compare May 8, 2026 13:34
@adecaro
Copy link
Copy Markdown
Contributor

adecaro commented May 11, 2026

Hi @Soumya8898 , thanks for the effort so far 🙏
There are still issues with the tests. Do you need support?

@Soumya8898
Copy link
Copy Markdown
Contributor Author

Hi @adecaro I am doing a last round of verification of all the changes, if unable to resolve it, will surely ask you for help. Thanks

@Soumya8898 Soumya8898 force-pushed the Soumya8898/extend-issuer-wallet branch from 53e3c2d to 8da2b44 Compare May 11, 2026 07:42
@Soumya8898
Copy link
Copy Markdown
Contributor Author

Hi @Soumya8898 , thanks for the effort so far 🙏 There are still issues with the tests. Do you need support?

Hi @adecaro i think i need support here, can you please share your views like wht is going wrong in the changes for which these panic calls are getting triggered.

@adecaro
Copy link
Copy Markdown
Contributor

adecaro commented May 11, 2026

Hi @Soumya8898 , I think I got the problem. The question is: Which are the tokens that represent a redeem? Those whose owner field is empty. Now, this means that the query performed by RedeemedBalance on the token store needs to be adjusted. Please, double check also that extractTransferOutputs returns two outputs as well. I haven't checked, but it is worth having a look. Why that function? Because it is used to extract the tokens from a token request. When a finality listener (token/services/ttx/finality/listener.go) gets invoked, AppendValid is invoked and there inputs and outputs are extracted from the token request. Hope it helps. This is getting interesting, actually 😄

Thanks for the effort @Soumya8898 🙏

@Soumya8898
Copy link
Copy Markdown
Contributor Author

Hi @adecaro Thanks for these catches, let me give them a look will update here.

Soumya Mohapatra added 10 commits May 15, 2026 10:58
Signed-off-by: Soumya Mohapatra <mohapatras@microsoft.com>
Signed-off-by: Soumya Mohapatra <mohapatras@microsoft.com>
Signed-off-by: Soumya Mohapatra <mohapatras@microsoft.com>
…dBalance SQL queries

Signed-off-by: Soumya Mohapatra <mohapatras@microsoft.com>
…emedBalance

Signed-off-by: Soumya Mohapatra <mohapatras@microsoft.com>
- Issue hyperledger-labs#3: Thread From/To *time.Time params through all 6 layers for
  IssuedBalance, ListRedeemedTokens, and RedeemedBalance. SQL uses
  cond.Gte/cond.Lte on stored_at column.

- Issue hyperledger-labs#4: Thread SortBy/SortDirection to ListRedeemedTokens SQL.
  SortByQuantity maps to ORDER BY amount ASC/DESC.

- Issue hyperledger-labs#5: Add unit tests for IssuedBalance, RedeemedTokens,
  RedeemedBalance, and OutstandingBalance (happy path, error
  propagation, edge cases).

- Issue hyperledger-labs#6: Add OutstandingBalance method to IssuerWallet
  (IssuedBalance minus RedeemedBalance) with overflow guard.

Signed-off-by: Soumya Mohapatra <mohapatras@microsoft.com>
Add IssuedBalanceView, RedeemedBalanceView, and OutstandingBalanceView
with corresponding view factories, support helpers (CheckIssuedBalance,
CheckRedeemedBalance, CheckOutstandingBalance), and two assertion blocks
in TestAll that exercise the new APIs after issue+redeem cycles.

Signed-off-by: Soumya Mohapatra <soumyaranjanmohapatra8@gmail.com>
Signed-off-by: Soumya Mohapatra <mohapatras@microsoft.com>
…e; add GoDocs

Signed-off-by: Soumya Mohapatra <soumyaranjanmohapatra8@gmail.com>
Signed-off-by: Soumya Mohapatra <mohapatras@microsoft.com>
CallView returns JSON-encoded []byte, not the raw Go type.
The Check*Balance functions were doing res.(uint64) which panics
because res is actually []byte. Use JSONUnmarshalUint64 helper
(analogous to existing JSONUnmarshalFloat64) to properly decode
the result.

Signed-off-by: Soumya Mohapatra <mohapatras@microsoft.com>
ListRedeemedTokens and RedeemedBalance previously JOINed with the
transactions table to identify tokens spent by a Redeem action. However,
the issuer node does not have entries in the transactions table for
redeem transactions initiated by other nodes, because StoreTransactionRecords
is only called by view initiators/responders and the issuer is not in the
redeem distribution list.

Instead, identify redeemed tokens by LEFT JOINing the tokens table with
itself: a redeemed token (issuer=true, is_deleted=true) has a spent_by
tx_id that has NO output tokens in the tokens table (Parse() skips redeem
outputs with empty owner), whereas a transferred token's spent_by tx_id
DOES have output tokens.

This fixes all 8 failing CI integration tests that were panicking with
'close of closed channel' due to the view assertion failure when
CheckRedeemedBalance returned 0 instead of the expected value.

Signed-off-by: Soumya Mohapatra <mohapatras@microsoft.com>
@Soumya8898 Soumya8898 force-pushed the Soumya8898/extend-issuer-wallet branch from 8da2b44 to dc53d86 Compare May 15, 2026 06:04
Signed-off-by: Soumya Mohapatra <mohapatras@microsoft.com>
@Soumya8898 Soumya8898 force-pushed the Soumya8898/extend-issuer-wallet branch from dc53d86 to 28ab079 Compare May 15, 2026 06:07
Soumya Mohapatra added 6 commits May 15, 2026 12:12
…tion

- Update role wallets_test.go to use driver.BalanceOpts instead of
  driver.ListTokensOptions for IssuedBalance, RedeemedBalance, and
  OutstandingBalance test calls (go vet failures)
- Fix QueryTokenDetails in sql/common/tokens.go to scan the BIGINT
  amount column into int64 first, then convert to *big.Int, since the
  SQL driver cannot scan int64 directly into *big.Int
- Align OwnerWallet.Balance in token/wallet.go to return *big.Int and
  properly convert BalanceOption to driver ListTokensOptions

Signed-off-by: Soumya Mohapatra <mohapatras@microsoft.com>
- run gofmt-compliant updates in token/wallet.go\n- satisfy golangci-lint nlreturn in QueryTokenDetails callback\n- keep big.Int scan conversion path intact

Signed-off-by: Soumya Mohapatra <mohapatras@microsoft.com>
Integration suites panic in BeforeEach when FAB_BINS lacks configtxgen.\nInstall configtxgen unconditionally in the itest workflow so both fabric and fabricx matrix jobs have the required binary.

Signed-off-by: Soumya Mohapatra <mohapatras@microsoft.com>
Root cause of repeated integration panics is missing binaries in FAB_BINS during BeforeEach bootstrap. Set FAB_BINS explicitly for itest jobs and fail fast by validating required Fabric binaries (configtxgen, configtxlator, cryptogen, discover, orderer, osnadmin, peer) before running suites.

Signed-off-by: Soumya Mohapatra <mohapatras@microsoft.com>
All failing suites panic in BeforeEach during binary lookup.\nExport FAB_BINS in the same shell that runs make integration-tests-* and log the directory contents to eliminate env propagation ambiguity and aid root-cause diagnosis.

Signed-off-by: Soumya Mohapatra <mohapatras@microsoft.com>
When SQL SUM(amount) returns NULL for no matching tokens, Balance was returning (nil, nil).\nRecipients then called balance.Cmp(...) in AcceptCashView and panicked with nil pointer during issue/update integration tests.\n\nChanges:\n- Return big.NewInt(0) when SUM(amount) is NULL in sql/common TokenStore balance\n- Add dbtest regression asserting empty balance is non-nil zero

Signed-off-by: Soumya Mohapatra <mohapatras@microsoft.com>
@Soumya8898 Soumya8898 force-pushed the Soumya8898/extend-issuer-wallet branch 2 times, most recently from cd1e31f to e6c44ad Compare May 17, 2026 13:48
…alance test

Signed-off-by: Soumya Mohapatra <mohapatras@microsoft.com>
@Soumya8898 Soumya8898 force-pushed the Soumya8898/extend-issuer-wallet branch 2 times, most recently from e84dc66 to 1ef3293 Compare May 17, 2026 14:02
…alance test

Signed-off-by: Soumya Mohapatra <mohapatras@microsoft.com>
@Soumya8898 Soumya8898 force-pushed the Soumya8898/extend-issuer-wallet branch 3 times, most recently from d9cf618 to 9324273 Compare May 17, 2026 20:40
…em and transfer lineage

Signed-off-by: Soumya Mohapatra <mohapatras@microsoft.com>
@Soumya8898 Soumya8898 force-pushed the Soumya8898/extend-issuer-wallet branch from 9324273 to 3cf8252 Compare May 17, 2026 21:11
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

issuer wallet: extensions

2 participants