Skip to content

feat: [E2E] Indexer tests — MINT/BURN/TRANSFER events + balance tracking#220

Merged
dhyaniarun1993 merged 12 commits intomainfrom
sadiq/feat/indexer-e2e
Apr 27, 2026
Merged

feat: [E2E] Indexer tests — MINT/BURN/TRANSFER events + balance tracking#220
dhyaniarun1993 merged 12 commits intomainfrom
sadiq/feat/indexer-e2e

Conversation

@sadiq1971
Copy link
Copy Markdown
Member

@sadiq1971 sadiq1971 commented Apr 16, 2026

Closes #184

Summary

  • tests/e2e/tests/indexer/ — new test package with init_test.go, helpers_test.go, mint_burn_test.go, transfer_test.go

    • TestIndexer_MintEvent — allocates a fresh Canton party, mints 5 DEMO directly via IssuerMint, waits for the indexer to record a MINT event with correct fields. Uses NewIndexerStack (Canton + Indexer only; no bridge needed).
    • TestIndexer_BurnEvent_AfterWithdrawal — deposits 2 PROMPT via the bridge, withdraws 1, verifies the indexer records a BURN event with correct from_party_id, external_address, and that TotalSupply decreases. Uses NewFullStack.
    • TestIndexer_TransferEvent_AfterAPITransfer — registers two external users, mints 50 DEMO to User1, transfers 10 to User2 via the api-server, verifies TRANSFER event fields and both parties' indexer balances. Uses NewAPIStack.
    • TestIndexer_HolderCount_Updates — verifies Token.HolderCount increments on first receipt and decrements when a party's balance returns to zero. Uses NewAPIStack.
  • tests/e2e/devstack/dsl/helpers.go — three new DSL methods:

    • WaitForPartyEvent — polls for first event of given type for a party
    • WaitForPartyEventMatching — same but with a caller-supplied predicate; fetches the last page (by Total) each tick so new events are always reachable regardless of prior event count
    • WaitForHolderCount — polls until GetToken reports the expected HolderCount
    • MaxPartyEventOffset — returns the highest ledger_offset currently indexed for a (partyID, eventType) pair; used to establish a "since" baseline before triggering an operation, preventing stale events from prior runs matching the predicate
    • amountGTE — switched from big.Float to big.Rat (exact arithmetic)
  • tests/e2e/devstack/system/system.goIndexerSystem gains a DSL field; APISystem gains an Indexer field so indexer assertions are available without the full stack

  • Makefiletest-e2e-indexer target now runs the tests (was a stub)

Test plan

  • make test-e2e-indexer passes against a running devstack
  • TestIndexer_MintEvent — MINT event recorded with correct event_type, amount, contract_id, ledger_offset, to_party_id
  • TestIndexer_BurnEvent_AfterWithdrawal — BURN event recorded with correct fields; total_supply decreases; sinceOffset predicate prevents stale-event false positives on re-runs against AnvilAccount1
  • TestIndexer_TransferEvent_AfterAPITransfer — TRANSFER event recorded; both parties' balances correct
  • TestIndexer_HolderCount_UpdatesHolderCount increments and decrements atomically with balance changes

Copy link
Copy Markdown
Contributor

@gemini-code-assist gemini-code-assist Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces end-to-end tests for the indexer, adding new Makefile targets, DSL helper functions for event polling, and test suites for mint, burn, and transfer operations. The review feedback identifies potential logic issues in the paginated event polling that could lead to missed events, suggests stricter error handling in test helpers to prevent silent failures, and recommends consolidating duplicate decimal comparison logic across the test packages.

Comment thread tests/e2e/devstack/dsl/helpers.go Outdated
Comment thread tests/e2e/devstack/dsl/helpers.go Outdated
Comment thread tests/e2e/tests/indexer/helpers_test.go Outdated
@codecov-commenter
Copy link
Copy Markdown

codecov-commenter commented Apr 16, 2026

Codecov Report

❌ Patch coverage is 0% with 74 lines in your changes missing coverage. Please review.
⚠️ Please upload report for BASE (main@5fff0fa). Learn more about missing BASE report.

Files with missing lines Patch % Lines
pkg/cantonsdk/bridge/client.go 0.00% 50 Missing ⚠️
pkg/cantonsdk/values/decode.go 0.00% 7 Missing ⚠️
pkg/cantonsdk/values/encode.go 0.00% 7 Missing ⚠️
pkg/cantonsdk/bridge/encode.go 0.00% 5 Missing ⚠️
pkg/cantonsdk/bridge/config.go 0.00% 2 Missing ⚠️
pkg/cantonsdk/identity/client.go 0.00% 2 Missing ⚠️
pkg/cantonsdk/bridge/decode.go 0.00% 1 Missing ⚠️

❌ Your patch status has failed because the patch coverage (0.00%) is below the target coverage (50.00%). You can increase the patch coverage or adjust the target coverage.

Additional details and impacted files

Impacted file tree graph

@@           Coverage Diff           @@
##             main     #220   +/-   ##
=======================================
  Coverage        ?   32.67%           
=======================================
  Files           ?      123           
  Lines           ?     8627           
  Branches        ?        0           
=======================================
  Hits            ?     2819           
  Misses          ?     5558           
  Partials        ?      250           
Flag Coverage Δ
unittests 32.67% <0.00%> (?)

Flags with carried forward coverage won't be shown. Click here to find out more.

Files with missing lines Coverage Δ
pkg/cantonsdk/bridge/decode.go 0.00% <0.00%> (ø)
pkg/cantonsdk/bridge/config.go 0.00% <0.00%> (ø)
pkg/cantonsdk/identity/client.go 0.00% <0.00%> (ø)
pkg/cantonsdk/bridge/encode.go 0.00% <0.00%> (ø)
pkg/cantonsdk/values/decode.go 0.00% <0.00%> (ø)
pkg/cantonsdk/values/encode.go 0.00% <0.00%> (ø)
pkg/cantonsdk/bridge/client.go 0.00% <0.00%> (ø)
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Switch TestIndexer_BurnEvent_AfterWithdrawal from AnvilAccount1 to
AnvilAccount0: the PROMPT token supply is minted entirely to the deployer
(Account0) at construction, so Account1 has zero balance and its deposit
transaction reverts. MaxPartyEventOffset already guards against stale burn
events from other tests via the sinceOffset predicate, so Account0 is safe.

Also fatal on last-page fetch failure in MaxPartyEventOffset instead of
silently falling back to page1 items, which would return a stale lower
ledger_offset and defeat the sinceOffset baseline.
…rawal

Common.Types.EvmAddress is defined as:
  newtype EvmAddress = EvmAddress with value : Text

The DAML Ledger API v2 requires newtypes to be submitted as a Record
wrapping the inner value; sending a plain ValueText causes
COMMAND_PREPROCESSING_FAILED. Adds values.NewtypeValue to the values
package and uses it in bridge/encode.go for the evmDestination field.
…IsDepositProcessed package ID

- values/decode.go: add NewtypeText to extract inner Text from DAML newtype records
  (EvmAddress is encoded as a single-field Record, not a plain Text value)
- bridge/decode.go: use NewtypeText for evmDestination field decoding; previously
  values.Text() returned "" causing relayer to send withdrawals to the zero address
- bridge/encode.go: remove spurious timestamp field from encodeInitiateWithdrawalArgs;
  the DAML InitiateWithdrawal choice has no timestamp parameter, causing
  COMMAND_PREPROCESSING_FAILED
- identity/client.go: expose PackageID() on the Identity interface and *Client so
  callers can retrieve the identity package ID
- bridge/client.go: fix IsDepositProcessed to use identity package ID for
  Common.FingerprintAuth templates (PendingDeposit, DepositReceipt); these templates
  live in identityPackageID, not bridgePackageID, so the prior code always hit
  TEMPLATES_OR_INTERFACES_NOT_FOUND and lost idempotency
@sadiq1971 sadiq1971 self-assigned this Apr 17, 2026
@sadiq1971
Copy link
Copy Markdown
Member Author

/gemini review

Copy link
Copy Markdown
Contributor

@gemini-code-assist gemini-code-assist Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces end-to-end tests for the indexer and refactors the bridge client to support a two-step withdrawal process (initiate and process). Key changes include adding the ProcessWithdrawal method to the bridge SDK, making user registration idempotent in the test DSL, and implementing several E2E helper methods for polling ledger events. A logic bug was identified in the WaitForPartyEventMatching helper where pagination logic could cause events on page boundaries to be missed.

Comment thread tests/e2e/devstack/dsl/helpers.go Outdated
@sadiq1971
Copy link
Copy Markdown
Member Author

/gemini review

Copy link
Copy Markdown
Contributor

@gemini-code-assist gemini-code-assist Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request enhances the E2E testing infrastructure and the Canton bridge client, notably adding support for processing withdrawals and comprehensive indexer testing. Key improvements include DAML Ledger API v2 newtype support, idempotent user registration in the DSL, and utility methods for seeding test accounts with ETH and tokens. Feedback focuses on optimizing the E2E polling logic to iterate backward through events for accuracy and reducing API overhead, as well as ensuring consistent nil-safety for the identity client within the bridge SDK.

Comment thread tests/e2e/devstack/dsl/helpers.go
Comment thread pkg/cantonsdk/bridge/client.go Outdated
Comment thread tests/e2e/devstack/dsl/helpers.go
Copy link
Copy Markdown
Member

@dhyaniarun1993 dhyaniarun1993 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@sadiq1971 Could you summarise the change done in pkg

@sadiq1971
Copy link
Copy Markdown
Member Author

@sadiq1971 Could you summarise the change done in pkg

Each changes in the pkg was required to pass the e2e tests. Here is the summery -


pkg/cantonsdk/bridge/

  • New ProcessWithdrawal method — exercises the DAML choice, burns tokens, returns WithdrawalEvent CID
  • Split package IDsBridge.Contracts templates now use a new CorePackageID; IsDepositProcessed bug fixed to use identity package ID instead
  • Newtype encodingEvmAddress (a DAML newtype) now correctly encoded/decoded as a single-field Record in encode.go and decode.go

pkg/cantonsdk/identity/

  • Added PackageID() to the interface so the bridge client can reference identity templates without a config dependency

pkg/cantonsdk/values/

  • Added NewtypeText (decode) and NewtypeValue (encode) helpers for DAML newtypes

pkg/config/

  • New core_package_id field added to bridge: config across all six default YAMLs

pkg/relayer/engine/mocks/

  • Mock regenerated for the new ProcessWithdrawal method

@dhyaniarun1993 dhyaniarun1993 merged commit 77c9673 into main Apr 27, 2026
3 checks passed
@dhyaniarun1993 dhyaniarun1993 deleted the sadiq/feat/indexer-e2e branch April 27, 2026 10:51
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[E2E] Tests: Indexer (MINT/BURN/TRANSFER events + balance tracking)

4 participants