Skip to content

Conversation

@Gaubee
Copy link
Contributor

@Gaubee Gaubee commented Jan 5, 2026

Summary

Extract WalletTab's portfolio section (assets + transactions) into reusable components with real chainProvider data support.

Changes

New Components

  • WalletAddressPortfolioView - Pure view component with TokenList + TransactionList tabs
  • WalletAddressPortfolioFromProvider - Container component using chainProvider for data fetching

Provider Enhancements

  • All providers now use Zod z.looseObject().safeParse() for type-safe API responses
  • BiowalletProvider: Added getTokenBalances() method
  • TronRpcProvider: Added getTransactionHistory() using TronGrid API
  • BscWalletProvider: New provider using walletapi.bfmeta.info/wallet/bsc API

Storybook Stories (8 tests)

Real data stories for: bfmeta, ethereum, bitcoin, tron, binance

Best Practices

Added Zod safeParse guidelines to best-practices.md

Testing

  • All 8 storybook tests pass
  • Typecheck passes

Gaubee added 19 commits January 5, 2026 16:54
Phase 1: Chain Config Strict Types (A1 decision)
- Remove `custom` from ChainKindSchema (only bioforest/evm/bitcoin/tron)
- Remove `normalizeUnknownKind` fallback logic - unknown kinds now fail validation
- Update testnet-chains.json to use chainKind and proper types
- Delete bip39 imports from providers/index.ts

Phase 2: Unified Identity Derivation (B2 + C2 decisions)
- EVM: Implement deriveAddress using deriveKey from @/lib/crypto
- Tron: Use unified deriveKey instead of separate HDKey implementation
- Bitcoin: Use deriveBitcoinKey with BIP84 (Native SegWit bc1q...)
- All identity services now expect UTF-8 mnemonic bytes as seed input

Tests updated to match new seed input semantics (TextEncoder vs mnemonicToSeedSync)
…vider support

- Add TokenBalance type and getTokenBalances to ChainProvider API
- Implement getTokenBalances in BiowalletProvider for full asset list
- Create WalletAddressPortfolioView (pure view component)
- Create WalletAddressPortfolioFromProvider (provider-backed container)
- Add Storybook stories with real chain data (bfmeta/ethmeta)
- Replace 'as' type assertions with z.looseObject().safeParse() in all providers
- Fix BiowalletProvider transaction parsing (result.trs instead of result.transactions)
- Fix balance display using toFormatted() instead of toString()
- Update stories with new test addresses and simplified play assertions
- Use useMemo with chainConfigState.snapshot dependency to create provider
- Add Bitcoin and Tron stories with real test addresses
- Fix provider initialization timing issue that caused empty capabilities
…e sync

- Split into ChainConfigInitializer (triggers init) and ChainConfigGate (checks snapshot)
- Use useChainConfigState() hook to ensure provider created after store update
- Simplify play assertions to accept either token list or empty state
- Implement getTransactionHistory using TronGrid /v1/accounts/{address}/transactions API
- Fix loading state: show loading when provider not ready OR query is loading
- Simplify ChainConfigProvider in stories to use single component with store hook
- Update play assertions to verify real data loads correctly
- Add provider existence to queryKey for proper cache invalidation
- Create provider inside queryFn instead of using closure reference
- Add DebugProviderInfo component for troubleshooting
- z.record(z.record(...)) fails in Zod 4
- Use z.record(z.string(), z.record(z.string(), schema)) instead
- Extract BiowalletAssetItemSchema for clarity
- Remove DebugProviderInfo component from stories
- Add Real Data: binance story with BSC hot wallet address
- All 8 chain stories now pass (bfmeta, ethereum, bitcoin, tron, binance)
- Create BscWalletProvider with balance and transaction history support
- Use bscwallet-v1 API key in default-chains.json
- Register provider factory in providers/index.ts
- TransactionItem: pass decimals to AmountDisplay
- AssetItem: use AmountDisplay instead of toFormatted()
- WalletList: use AddressDisplay instead of truncateAddress()
- WalletSelector: use AddressDisplay instead of truncateAddress()
- TransactionDetails: use AddressDisplay instead of formatAddress()
- SendResult: use AddressDisplay for address and txHash display
- Add AssetType x Action x Direction classification for transactions
- Create transaction-schema.ts with Zod schemas for Transaction types
- Update EtherscanProvider to fetch both txlist and tokentx
- Update BiowalletProvider with BioForest action type detection
- Update all providers (Tron, Mempool, BSC) with new Transaction format
- Add convertToTransactionInfo helper for UI mapping
- Add script to download and filter real tx samples
- Add fixtures for ETH/BFMeta/BTC/TRON
- Fix EtherscanProvider methodId parsing and contract metadata
- Add unit tests validating action/direction/assets conversion
## EVM Transaction Aggregation (Option B1)
- Aggregate txlist + tokentx by hash, with txlist as source of truth
- Prioritize token assets in display (avoid 'send 0 ETH' for ERC-20)
- Handle orphan token txs (no corresponding native tx in window)
- Increase fetch window (limit * 5) to mitigate pagination trap

## UI Improvements
- Add 'interaction' TransactionType for unknown contract calls
- Map 'contract' action to 'interaction' UI type
- Add i18n for 'Contract Interaction' in en/zh-CN/zh-TW/ar

## BIW Chain Support
- Add BIWMeta fixtures for 5 tx types (BSE-01/AST-02/AST-03/ETY-01/ETY-02)
- Extend BiowalletProvider action mapping for BIW-specific types
- Add real fixture tests for BIW transaction conversion

## Tests
- Add aggregation test: same hash txlist + tokentx produces 1 tx
- Add test: unrecognized contract call with no tokens -> 'contract' action
- Add BIWMeta real fixture tests (5 tx types)
## Changes
- Add TRC-20 transaction fetching via /v1/accounts/{addr}/transactions/trc20
- Aggregate native txs + TRC-20 events by txID (same pattern as EVM)
- Token assets prioritized over 0-value TRX
- Handle orphan TRC-20 txs (no native tx in window)

## Action Detection
- TransferContract/TransferAssetContract -> transfer
- TriggerSmartContract + TRC-20 -> transfer
- TriggerSmartContract without TRC-20 -> contract
- FreezeBalanceV2/VoteWitness -> stake
- UnfreezeBalanceV2 -> unstake
- WithdrawExpireUnfreeze -> claim

## Tests
- Aggregation test: same txID native + TRC-20 produces 1 tx
- Orphan TRC-20 test: token tx without native tx
- Stake/unstake action detection test
- Contract action for unrecognized TriggerSmartContract
## Option A: Smart Filter Implementation

Filter TriggerSmartContract transactions that have:
- 0 TRX amount
- No associated TRC-20 token events

## Whitelist (never filtered)
- TransferContract / TransferAssetContract (native transfers)
- FreezeBalance / UnfreezeBalance (staking)
- VoteWitnessContract (voting for super representatives)
- AccountCreateContract (account activation)
- WithdrawBalanceContract (claim rewards)

## Keep conditions
- Has TRC-20 events associated (token transfer)
- Has non-zero TRX amount (value transfer)
- Is a whitelisted contract type

## Tests
- Filter spam TriggerSmartContract (0 TRX, no TRC-20)
- Keep TriggerSmartContract with TRC-20 events
- Keep TriggerSmartContract with non-zero TRX
## Smart Filter Rules (Option A + Safety Whitelist)

### Keep Rules (match any = keep)
1. Core system actions: Freeze/Unfreeze/Vote/Withdraw/AccountCreate/Transfer
2. Asset changes: has TRC-20 events OR TRX amount > 0
3. Critical feedback: FAILED transactions (user needs to see failure)
4. Key actions: approve (0x095ea7b3) - required before Swap

### Drop Rule
- TriggerSmartContract + SUCCESS + 0 TRX + no TRC-20 + not approve → noise

## Changes
- Add Rule 3: Keep failed transactions regardless of amount
- Add Rule 4: Keep approve transactions, detect via MethodID 0x095ea7b3
- Set action='approve' for approve transactions
- Add isApproveTransaction() helper method

## Tests (4 new)
- Keep FAILED 0-TRX transactions (Rule 3)
- Keep approve transactions with correct action (Rule 4)
- Filter successful 0-TRX spam without TRC-20 and not approve
- Verify 12 total Tron provider tests pass
## Problem
Tron approve transactions were incorrectly mapped to 'signature'
(设置安全密码), causing confusion in the transaction list.

## Solution
- Add 'approve' to TransactionType enum
- Add 'interaction' to TransactionType enum (was missing)
- Map action 'approve' -> UI type 'approve' (not 'signature')
- Add IconShieldCheck for approve type
- Add i18n: 'Approve' / '授权' / '授權' in all 4 locales

## Files changed
- transaction-item.tsx: Add 'approve' type + icon
- wallet-address-portfolio-from-provider.tsx: Fix mapping
- transaction/types.ts: Add 'approve' and 'interaction' types
- i18n locales: Add 'approve' translations
@Gaubee Gaubee merged commit c274ae3 into main Jan 5, 2026
5 checks passed
@Gaubee Gaubee deleted the feat/wallet-portfolio branch January 5, 2026 12:36
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.

2 participants