-
Notifications
You must be signed in to change notification settings - Fork 10
Add complete integration test suite for balances end-to-end testing #373
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
aditya1702
wants to merge
9
commits into
graphql-balances-resolver
Choose a base branch
from
balances-integration-tests
base: graphql-balances-resolver
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
9 commits
Select commit
Hold shift + click to select a range
8e40f21
Add integration tests for account balances
aditya1702 8c83d64
Add balances query to wbclient
aditya1702 ab0fa5e
Update Makefile
aditya1702 40b9524
Remove all magic numbers and use constants file
aditya1702 22c7e28
Refactor - 1
aditya1702 26ea295
Update go.yaml
aditya1702 5632838
Refactor - 2
aditya1702 716d9bf
Refactor - 3
aditya1702 5b0c1e8
Update go.yaml
aditya1702 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -44,7 +44,7 @@ jobs: | |
| - name: Run `[email protected]` | ||
| run: | | ||
| go install golang.org/x/tools/cmd/[email protected] | ||
| output=$(deadcode -test ./... | { grep -v "UnmarshalUInt32" || true; }) | ||
| output=$(deadcode -test ./... | { grep -v "UnmarshalUInt32" || true; } | { grep -v "isBalance" || true; }) | ||
| if [[ -n "$output" ]]; then | ||
| echo "🚨 Deadcode found:" | ||
| echo "$output" | ||
|
|
||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -63,7 +63,7 @@ deadcode: ## Find unused code | |
| echo "Installing deadcode..."; \ | ||
| go install golang.org/x/tools/cmd/[email protected]; \ | ||
| fi | ||
| @output=$$($(shell go env GOPATH)/bin/deadcode -test ./... | grep -v "UnmarshalUInt32"); \ | ||
| @output=$$($(shell go env GOPATH)/bin/deadcode -test ./... | grep -v "UnmarshalUInt32" | grep -v "isBalance"); \ | ||
| if [ -n "$$output" ]; then \ | ||
| echo "🚨 Deadcode found:"; \ | ||
| echo "$$output"; \ | ||
|
|
||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,298 @@ | ||
| // Account Balance Integration Tests | ||
| // | ||
| // This test suite verifies that the wallet backend correctly retrieves different types | ||
| // of token balances for Stellar accounts. It tests three types of balances: | ||
| // | ||
| // 1. Native XLM Balance | ||
| // - The account's XLM balance stored in the account entry | ||
| // | ||
| // 2. Classic Trustline Balance (TokenTypeClassic) | ||
| // - Traditional Stellar trustlines created with CHANGE_TRUST operations | ||
| // - Example: USDC issued by a specific issuer | ||
| // - Stored as LedgerEntryTypeTrustLine entries | ||
| // | ||
| // 3. SEP-41 Contract Token Balance (TokenTypeSEP41) | ||
| // - Custom token contracts that implement the SEP-41 interface | ||
| // - Balances stored as contract data entries with key [Balance, Address] | ||
| // - This test uses the standard token contract from soroban-examples v22.0.1 | ||
| // | ||
| // SEP-41 Token Contract Setup: | ||
| // - Contract: soroban_token_contract.wasm from stellar/soroban-examples | ||
| // - Initialization: __constructor(admin, decimal, name, symbol) | ||
| // - Admin: Master test account | ||
| // - Decimals: 7 | ||
| // - Name: "USD Coin" | ||
| // - Symbol: "USDC" | ||
| // - Functions tested: mint(to, amount) | ||
| // - Balance storage: Contract data entry with key [Balance, G-address] | ||
| // | ||
| // Test Accounts: | ||
| // - balanceTestAccount1: Has native XLM, classic USDC trustline, and SEP-41 tokens | ||
| // - balanceTestAccount2: Has native XLM and classic USDC trustline | ||
| // - These are separate from transaction test accounts to avoid balance drift | ||
| // | ||
| // References: | ||
| // - SEP-41 Standard: https://stellar.org/protocol/sep-41 | ||
| // - Token Contract: https://github.com/stellar/soroban-examples/tree/v22.0.1/token | ||
| // - Setup code: internal/integrationtests/infrastructure/setup.go lines 277-337 | ||
| package integrationtests | ||
|
|
||
| import ( | ||
| "context" | ||
|
|
||
| "github.com/stretchr/testify/suite" | ||
|
|
||
| "github.com/stellar/wallet-backend/internal/integrationtests/infrastructure" | ||
| "github.com/stellar/wallet-backend/pkg/wbclient/types" | ||
| ) | ||
|
|
||
| // AccountBalancesAfterCheckpointTestSuite validates that balances are correctly calculated | ||
| // using tokens populated from the checkpoint ledger before any fixture transactions are submitted. | ||
| // | ||
| // This suite tests the initial state after checkpoint setup completes but before | ||
| // the BuildAndSubmitTransactionsTestSuite executes any transactions. | ||
| type AccountBalancesAfterCheckpointTestSuite struct { | ||
| suite.Suite | ||
| testEnv *infrastructure.TestEnvironment | ||
| } | ||
|
|
||
| // TestCheckpoint_Account1_HasInitialBalances verifies that balance test account 1 | ||
| // has the expected initial balances from checkpoint setup: | ||
| // - Native XLM (~10000) | ||
| // - USDC trustline (100) | ||
| // - EURC trustline (100) | ||
| // - SEP-41 contract tokens (500) | ||
| func (suite *AccountBalancesAfterCheckpointTestSuite) TestCheckpoint_Account1_HasInitialBalances() { | ||
| balances, err := suite.testEnv.WBClient.GetBalancesByAccountAddress( | ||
| context.Background(), | ||
| suite.testEnv.BalanceTestAccount1KP.Address(), | ||
| ) | ||
| suite.Require().NoError(err) | ||
| suite.Require().NotNil(balances) | ||
| suite.Require().NotEmpty(balances) | ||
|
|
||
| suite.Require().Equal(4, len(balances), "Expected 4 balances: native XLM, USDC trustline, EURC trustline, and SEP-41 tokens") | ||
|
|
||
| // Verify native XLM balance | ||
| nativeBalance, ok := balances[0].(*types.NativeBalance) | ||
| suite.Require().True(ok, "First balance should be native XLM") | ||
| suite.Require().Equal("10000.0000000", nativeBalance.GetBalance()) | ||
| suite.Require().Equal(types.TokenTypeNative, nativeBalance.GetTokenType()) | ||
|
|
||
| // Verify EURC trustline balance | ||
| eurcBalance, ok := balances[1].(*types.TrustlineBalance) | ||
| suite.Require().True(ok, "Third balance should be EURC trustline") | ||
| suite.Require().Equal("100.0000000", eurcBalance.GetBalance()) | ||
| suite.Require().Equal(suite.testEnv.EURCContractAddress, eurcBalance.GetTokenID()) | ||
| suite.Require().Equal(types.TokenTypeClassic, eurcBalance.GetTokenType()) | ||
|
|
||
| // Verify USDC trustline balance | ||
| usdcBalance, ok := balances[2].(*types.TrustlineBalance) | ||
| suite.Require().True(ok, "Second balance should be USDC trustline") | ||
| suite.Require().Equal("100.0000000", usdcBalance.GetBalance()) | ||
| suite.Require().Equal(suite.testEnv.USDCContractAddress, usdcBalance.GetTokenID()) | ||
| suite.Require().Equal(types.TokenTypeClassic, usdcBalance.GetTokenType()) | ||
|
|
||
| // Verify SEP-41 contract token balance | ||
| sep41Balance, ok := balances[3].(*types.SEP41Balance) | ||
| suite.Require().True(ok, "Fourth balance should be SEP-41 tokens") | ||
| suite.Require().Equal("500.0000000", sep41Balance.GetBalance()) | ||
| suite.Require().Equal(suite.testEnv.SEP41ContractAddress, sep41Balance.GetTokenID()) | ||
| suite.Require().Equal(types.TokenTypeSEP41, sep41Balance.GetTokenType()) | ||
| } | ||
|
|
||
| // TestCheckpoint_Account2_HasInitialBalances verifies that balance test account 2 | ||
| // has the expected initial balances from checkpoint setup: | ||
| // - Native XLM (~10000) | ||
| // - USDC trustline (100) | ||
| func (suite *AccountBalancesAfterCheckpointTestSuite) TestCheckpoint_Account2_HasInitialBalances() { | ||
| balances, err := suite.testEnv.WBClient.GetBalancesByAccountAddress( | ||
| context.Background(), | ||
| suite.testEnv.BalanceTestAccount2KP.Address(), | ||
| ) | ||
| suite.Require().NoError(err) | ||
| suite.Require().NotNil(balances) | ||
| suite.Require().NotEmpty(balances) | ||
|
|
||
| suite.Require().Equal(2, len(balances), "Expected 2 balances: native XLM and USDC trustline") | ||
|
|
||
| // Verify native XLM balance | ||
| nativeBalance, ok := balances[0].(*types.NativeBalance) | ||
| suite.Require().True(ok, "First balance should be native XLM") | ||
| suite.Require().Equal("10000.0000000", nativeBalance.GetBalance()) | ||
| suite.Require().Equal(types.TokenTypeNative, nativeBalance.GetTokenType()) | ||
|
|
||
| // Verify USDC trustline balance | ||
| usdcBalance, ok := balances[1].(*types.TrustlineBalance) | ||
| suite.Require().True(ok, "Second balance should be USDC trustline") | ||
| suite.Require().Equal("100.0000000", usdcBalance.GetBalance()) | ||
| suite.Require().Equal(suite.testEnv.USDCContractAddress, usdcBalance.GetTokenID()) | ||
| suite.Require().Equal(types.TokenTypeClassic, usdcBalance.GetTokenType()) | ||
| } | ||
|
|
||
| // TestCheckpoint_HolderContract_HasInitialBalances verifies that the holder contract | ||
| // has the expected initial balances from checkpoint setup: | ||
| // - USDC SAC tokens (200) | ||
| // - SEP-41 contract tokens (300) | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. NIT: looks like the balance is actually 500 |
||
| func (suite *AccountBalancesAfterCheckpointTestSuite) TestCheckpoint_HolderContract_HasInitialBalances() { | ||
| balances, err := suite.testEnv.WBClient.GetBalancesByAccountAddress( | ||
| context.Background(), | ||
| suite.testEnv.HolderContractAddress, | ||
| ) | ||
| suite.Require().NoError(err) | ||
| suite.Require().NotNil(balances) | ||
| suite.Require().NotEmpty(balances) | ||
|
|
||
| suite.Require().Equal(2, len(balances), "Expected 2 balances: USDC SAC and SEP-41 tokens") | ||
|
|
||
| // Verify USDC SAC balance | ||
| usdcSACBalance, ok := balances[0].(*types.SACBalance) | ||
| suite.Require().True(ok, "First balance should be USDC SAC") | ||
| suite.Require().Equal("200.0000000", usdcSACBalance.GetBalance()) | ||
| suite.Require().Equal(suite.testEnv.USDCContractAddress, usdcSACBalance.GetTokenID()) | ||
| suite.Require().Equal(types.TokenTypeSAC, usdcSACBalance.GetTokenType()) | ||
|
|
||
| // Verify SEP-41 contract token balance | ||
| sep41Balance, ok := balances[1].(*types.SEP41Balance) | ||
| suite.Require().True(ok, "Second balance should be SEP-41 tokens") | ||
| suite.Require().Equal("500.0000000", sep41Balance.GetBalance()) | ||
| suite.Require().Equal(suite.testEnv.SEP41ContractAddress, sep41Balance.GetTokenID()) | ||
| suite.Require().Equal(types.TokenTypeSEP41, sep41Balance.GetTokenType()) | ||
| } | ||
|
|
||
| // AccountBalancesAfterLiveIngestionTestSuite validates that balances are correctly calculated | ||
| // after fixture transactions are submitted and processed by the live ingestion pipeline. These new transactions | ||
| // will lead to new tokens being inserted into the token cache and new balances being calculated. | ||
| // | ||
| // This suite tests the final state after BuildAndSubmitTransactionsTestSuite executes | ||
| // the fixture transactions and the ingest service processes them. | ||
| type AccountBalancesAfterLiveIngestionTestSuite struct { | ||
| suite.Suite | ||
| testEnv *infrastructure.TestEnvironment | ||
| } | ||
|
|
||
| // TestLiveIngestion_Account1_HasUpdatedBalances verifies that balance test account 1 | ||
| // has the expected balances after fixture transactions are processed: | ||
| // - Native XLM | ||
| // - USDC trustline (100) - unchanged | ||
| // - EURC trustline (50) - reduced from 100 after transfer to contract | ||
| // - SEP-41 contract tokens (400) - reduced from 500 after transfer to account 2 | ||
| func (suite *AccountBalancesAfterLiveIngestionTestSuite) TestLiveIngestion_Account1_HasUpdatedBalances() { | ||
| balances, err := suite.testEnv.WBClient.GetBalancesByAccountAddress( | ||
| context.Background(), | ||
| suite.testEnv.BalanceTestAccount1KP.Address(), | ||
| ) | ||
| suite.Require().NoError(err) | ||
| suite.Require().NotNil(balances) | ||
| suite.Require().NotEmpty(balances) | ||
|
|
||
| suite.Require().Equal(4, len(balances), "Expected 4 balances: native XLM, USDC, EURC, and SEP-41 tokens") | ||
|
|
||
| // Verify native XLM balance (may have changed due to fees) | ||
| nativeBalance, ok := balances[0].(*types.NativeBalance) | ||
| suite.Require().True(ok, "First balance should be native XLM") | ||
| suite.Require().Equal(types.TokenTypeNative, nativeBalance.GetTokenType()) | ||
|
|
||
| // Verify EURC trustline balance (reduced from 100 to 50) | ||
| eurcBalance, ok := balances[1].(*types.TrustlineBalance) | ||
| suite.Require().True(ok, "Third balance should be EURC trustline") | ||
| suite.Require().Equal("50.0000000", eurcBalance.GetBalance(), "EURC balance should be reduced to 50 after transfer") | ||
| suite.Require().Equal(suite.testEnv.EURCContractAddress, eurcBalance.GetTokenID()) | ||
| suite.Require().Equal(types.TokenTypeClassic, eurcBalance.GetTokenType()) | ||
|
|
||
| // Verify USDC trustline balance (unchanged) | ||
| usdcBalance, ok := balances[2].(*types.TrustlineBalance) | ||
| suite.Require().True(ok, "Second balance should be USDC trustline") | ||
| suite.Require().Equal("100.0000000", usdcBalance.GetBalance()) | ||
| suite.Require().Equal(suite.testEnv.USDCContractAddress, usdcBalance.GetTokenID()) | ||
| suite.Require().Equal(types.TokenTypeClassic, usdcBalance.GetTokenType()) | ||
|
|
||
| // Verify SEP-41 contract token balance (reduced from 500 to 400) | ||
| sep41Balance, ok := balances[3].(*types.SEP41Balance) | ||
| suite.Require().True(ok, "Fourth balance should be SEP-41 tokens") | ||
| suite.Require().Equal("400.0000000", sep41Balance.GetBalance(), "SEP-41 balance should be reduced to 400 after transfer") | ||
| suite.Require().Equal(suite.testEnv.SEP41ContractAddress, sep41Balance.GetTokenID()) | ||
| suite.Require().Equal(types.TokenTypeSEP41, sep41Balance.GetTokenType()) | ||
| } | ||
|
|
||
| // TestLiveIngestion_Account2_HasNewBalances verifies that balance test account 2 | ||
| // has the expected balances after fixture transactions create new token holdings: | ||
| // - Native XLM | ||
| // - USDC trustline (100) - unchanged | ||
| // - EURC trustline (75) - NEW from trustline creation and payment | ||
| // - SEP-41 contract tokens (100) - NEW from transfer from account 1 | ||
| func (suite *AccountBalancesAfterLiveIngestionTestSuite) TestLiveIngestion_Account2_HasNewBalances() { | ||
| balances, err := suite.testEnv.WBClient.GetBalancesByAccountAddress( | ||
| context.Background(), | ||
| suite.testEnv.BalanceTestAccount2KP.Address(), | ||
| ) | ||
| suite.Require().NoError(err) | ||
| suite.Require().NotNil(balances) | ||
| suite.Require().NotEmpty(balances) | ||
|
|
||
| suite.Require().Equal(4, len(balances), "Expected 4 balances: native XLM, USDC, EURC, and SEP-41 tokens") | ||
|
|
||
| // Verify native XLM balance | ||
| nativeBalance, ok := balances[0].(*types.NativeBalance) | ||
| suite.Require().True(ok, "First balance should be native XLM") | ||
| suite.Require().Equal(types.TokenTypeNative, nativeBalance.GetTokenType()) | ||
|
|
||
| // Verify USDC trustline balance (unchanged) | ||
| usdcBalance, ok := balances[1].(*types.TrustlineBalance) | ||
| suite.Require().True(ok, "Second balance should be USDC trustline") | ||
| suite.Require().Equal("100.0000000", usdcBalance.GetBalance()) | ||
| suite.Require().Equal(suite.testEnv.USDCContractAddress, usdcBalance.GetTokenID()) | ||
| suite.Require().Equal(types.TokenTypeClassic, usdcBalance.GetTokenType()) | ||
|
|
||
| // Verify EURC trustline balance (NEW - 75 tokens from payment) | ||
| eurcBalance, ok := balances[2].(*types.TrustlineBalance) | ||
| suite.Require().True(ok, "Third balance should be EURC trustline") | ||
| suite.Require().Equal("75.0000000", eurcBalance.GetBalance(), "EURC balance should be 75 from payment") | ||
| suite.Require().Equal(suite.testEnv.EURCContractAddress, eurcBalance.GetTokenID()) | ||
| suite.Require().Equal(types.TokenTypeClassic, eurcBalance.GetTokenType()) | ||
|
|
||
| // Verify SEP-41 contract token balance (NEW - 100 tokens from transfer) | ||
| sep41Balance, ok := balances[3].(*types.SEP41Balance) | ||
| suite.Require().True(ok, "Fourth balance should be SEP-41 tokens") | ||
| suite.Require().Equal("100.0000000", sep41Balance.GetBalance(), "SEP-41 balance should be 100 from transfer") | ||
| suite.Require().Equal(suite.testEnv.SEP41ContractAddress, sep41Balance.GetTokenID()) | ||
| suite.Require().Equal(types.TokenTypeSEP41, sep41Balance.GetTokenType()) | ||
| } | ||
|
|
||
| // TestLiveIngestion_HolderContract_HasNewEURC verifies that the holder contract | ||
| // has the expected balances after fixture transactions add EURC: | ||
| // - USDC SAC tokens (200) - unchanged | ||
| // - SEP-41 contract tokens (300) - unchanged | ||
| // - EURC SAC tokens (50) - NEW from transfer from account 1 | ||
| func (suite *AccountBalancesAfterLiveIngestionTestSuite) TestLiveIngestion_HolderContract_HasNewEURC() { | ||
| balances, err := suite.testEnv.WBClient.GetBalancesByAccountAddress( | ||
| context.Background(), | ||
| suite.testEnv.HolderContractAddress, | ||
| ) | ||
| suite.Require().NoError(err) | ||
| suite.Require().NotNil(balances) | ||
| suite.Require().NotEmpty(balances) | ||
|
|
||
| suite.Require().Equal(3, len(balances), "Expected 3 balances: USDC SAC, SEP-41, and EURC SAC") | ||
|
|
||
| // Verify USDC SAC balance (unchanged) | ||
| usdcSACBalance, ok := balances[0].(*types.SACBalance) | ||
| suite.Require().True(ok, "First balance should be USDC SAC") | ||
| suite.Require().Equal("200.0000000", usdcSACBalance.GetBalance()) | ||
| suite.Require().Equal(suite.testEnv.USDCContractAddress, usdcSACBalance.GetTokenID()) | ||
| suite.Require().Equal(types.TokenTypeSAC, usdcSACBalance.GetTokenType()) | ||
|
|
||
| // Verify SEP-41 contract token balance (unchanged) | ||
| sep41Balance, ok := balances[1].(*types.SEP41Balance) | ||
| suite.Require().True(ok, "Second balance should be SEP-41 tokens") | ||
| suite.Require().Equal("500.0000000", sep41Balance.GetBalance()) | ||
| suite.Require().Equal(suite.testEnv.SEP41ContractAddress, sep41Balance.GetTokenID()) | ||
| suite.Require().Equal(types.TokenTypeSEP41, sep41Balance.GetTokenType()) | ||
|
|
||
| // Verify EURC SAC balance (NEW - 50 tokens from transfer) | ||
| eurcSACBalance, ok := balances[2].(*types.SACBalance) | ||
| suite.Require().True(ok, "Third balance should be EURC SAC") | ||
| suite.Require().Equal("50.0000000", eurcSACBalance.GetBalance(), "EURC SAC balance should be 50 from transfer") | ||
| suite.Require().Equal(suite.testEnv.EURCContractAddress, eurcSACBalance.GetTokenID()) | ||
| suite.Require().Equal(types.TokenTypeSAC, eurcSACBalance.GetTokenType()) | ||
| } | ||
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
can this suite include tests for balances of 0?