Skip to content

Conversation

@Gaubee
Copy link
Contributor

@Gaubee Gaubee commented Jan 23, 2026

Closes #272

Goal (Service)

Start development...

Schema Definition

  • Define Service Meta (Schema-first)
  • Define Input/Output Zod Schemas

Implementation

  • Web Implementation
  • DWeb/Native Implementation (if needed)
  • Mock Implementation
  • Unit Tests

Gaubee added 30 commits January 22, 2026 13:38
- Add throttleError plugin with errorMatchers for 429 rate limit suppression
- Add apiKey plugin for generic API key header injection
- Add onError hook to FetchPlugin interface for error interception
- Add getApiKey helper to encapsulate __API_KEYS__ global access
- Apply throttling and API key to all Tron RPC endpoints
- Prioritize tron-rpc-pro in default-chains.json config
- Etherscan: add API key via query param + 429 error throttling
- EVM RPC: add 429 error throttling for public nodes
- Create etherscan-v2-provider.ts with chainid parameter for V2 API
- Rename etherscan-provider.ts to etherscan-v1-provider.ts
- Add JsonRpcResponseSchema for proxy module responses
- Add hex balance conversion for V2 API
- Reorder Ethereum APIs to prioritize etherscan-v2
- Update V1 factory to not match etherscan-v2 type
- Update tests for blockscout-v1 matching
…handling

- Create ServiceLimitedError class in key-fetch/errors.ts
- Export from @biochain/key-fetch
- V1/V2 providers throw ServiceLimitedError on API failures
- Replaces silent empty array returns with explicit error
- Create useServiceStatus hook to distinguish NoSupportError/ServiceLimitedError
- Create ServiceStatusAlert component with i18n support
- Add service.* i18n keys for zh-CN, en, zh-TW, ar
- Update WalletTab to pass error status to WalletAddressPortfolioView
- Update history page to show ServiceStatusAlert on errors
- Replace ProviderFallbackWarning with ServiceStatusAlert in portfolio view
- Modified core.ts to let Schema errors pass through plugin onError hooks
- Enables throttleError to reduce console noise from repeated Schema errors
- Preserves full error info for debugging when not handled by plugins
- Added Schema error matching to etherscan-v2-provider throttleError
- Add MORALIS_API_KEY to set-secret.ts, vite.config.ts, .env.example
- Add TokenMetadata interface for extended token info (spam, security score)
- Add fromEntity/toEntity/summary fields to TransactionSchema
- Create moralis-provider.ts with nativeBalance, tokenBalances, transactionHistory
- Register Moralis as primary provider for ETH/BSC in default-chains.json
- Moralis provides token list + rich metadata that Etherscan doesn't support
…tion

- Fix chain ID mapping (ethereum/binance instead of eth-mainnet/bsc-mainnet)
- Add pathParams() plugin to replace :address in URLs
- Add searchParams() for walletHistoryApi dynamic parameters
- Fix Request headers construction in API key plugin

Token balances now loading successfully from Moralis API.
…act key conflict

- Filter tokens with possible_spam=true from tokenBalances
- Add TrustWallet Assets as icon fallback (by contract address)
- Add contractAddress to TokenInfo interface for unique React keys
- Fix token list key collision by using contractAddress instead of symbol

Icon fallback chain: Moralis logo > thumbnail > TrustWallet Assets > letter
deps plugin was subscribing to dependencies with empty params {},
causing pathParams() to fail replacing :address placeholder.
Now passes ctx.params so URL parameters are correctly substituted.
- Add DepConfig interface with source and params function
- Support three calling patterns:
  - deps(a, b, c) - original, empty params
  - deps([a, b, c]) - array form
  - deps([{ source: a, params: ctx => ctx.params }]) - per-dep config
- Each dependency can have independent params transformation
- Update moralis-provider to use new deps syntax for nativeBalanceApi

This fixes the :address placeholder not being replaced in Moralis API URLs.
- Add tokenIconContract schema field for contract-address-based icon lookup
- Add getTokenIconByContract() method with checksum address conversion
- Update default-chains.json: ETH/BSC use TrustWallet Assets URLs
- Remove incorrect tokenIconBase from EVM chains (was pointing to BioChain CDN)
- Refactor TokenIcon component: letter-first + image-overlay mode
  - Letter always renders as base layer
  - Image overlays and shows on successful load
  - Eliminates loading flicker

Icon priority: Moralis logo > thumbnail > tokenIconContract config > letter
…t savings

Non-BioChain providers now use at least 30s polling interval:
- moralis: 15s -> 30s (nativeBalance, walletHistory)
- tron-rpc: 3s -> 30s
- tronwallet: 3s -> 30s
- bscwallet: 3s -> 30s
- ethwallet: 12s -> 30s
- evm-rpc: 12s -> 30s
- etherscan-v1: 12s -> 30s
- etherscan-v2: 12s -> 30s

BioChain (biowallet) keeps dynamic forgeInterval from genesis block.
Bitcoin providers already use 60s (unchanged).
Cost optimization:
- transactionHistory: 30s -> 2min polling (75% reduction)
- tokenBalances: remove independent interval, now deps-driven
  - Triggered only when transactionHistory or nativeBalance changes
  - Expected 90%+ reduction in erc20 API calls

New capabilities:
- Add transactionStatus API for waiting transaction confirmation
- Uses eth_getTransactionReceipt via RPC (3s polling)
- Triggers nativeBalance and transactionHistory refresh on confirmation

Dependency chain:
  nativeBalance (30s) -> transactionHistory (2min)
                      -> tokenBalances (on-demand)
- Upgrade dedupe plugin: global deduplication + configurable minInterval
- Add DedupeThrottledError for throttled requests
- Add 401 quota exceeded to moralis throttleError matcher
- Read polling intervals from chain config (txStatusInterval, balanceInterval, erc20Interval)
- Configure ETH: 12s/36s/150s, BSC: 15s/30s/120s
… cooldown

- core.ts: Add automatic time-based deduplication calculated from interval/deps plugins
- interval.ts: Expose _intervalMs property for introspection
- deps.ts: Expose _sources property for introspection
- fallback.ts: Add 60s cooldown for failed sources to prevent request storms
…urce API

- Create @biochain/chain-effect package with:
  - source.ts: createPollingSource, createDependentSource, createHybridSource
  - event-bus.ts: WalletEvent type, EventBusService with per-wallet filtering
  - instance.ts: createStreamInstanceFromSource for React bridge
  - http.ts: httpFetch with Effect error handling

- Deep refactor 11 providers using Effect native patterns:
  - biowallet, moralis, tron-rpc, ethwallet, bscwallet, tronwallet
  - evm-rpc, etherscan-v1, etherscan-v2, mempool, btcwallet

- Core pattern: txHistory (polling+events) -> balance (dependent)
- EventBus supports chainId + address for per-wallet event isolation
- No TTL guessing - cache invalidates on dependency change
- Add superjson to chain-effect for BigInt/Amount serialization
- Add NoSupportError and ServiceLimitedError classes
- Update pages to use chain-effect superjson instead of key-fetch
- Fix unused imports in chain-effect source files
- Delete old provider test files
- Replace require('react') with ESM import in instance.ts
- Use useSyncExternalStore for React 18+ concurrent mode support
- Remove dynamic import('effect') in favor of direct Fiber.interrupt
- Add reference links to Effect docs (context7.com/effect-ts/effect/llms.txt)
- Refactor bioforest/fetch.ts to Effect-TS native DataSource
- Refactor pending-tx.ts to Effect-TS with createDependentSource
- Refactor ecosystem/registry.ts with native fetch + IndexedDB cache
- Remove @biochain/key-fetch imports from main.tsx
- Update use-pending-transactions.ts to use Effect-based API
- Backward compatible: existing .useState() API unchanged
- Delete packages/key-fetch/ directory
- Remove @biochain/key-fetch from root package.json dependencies
- Update pnpm-lock.yaml
…value

- createPollingSource: execute immediate fetch synchronously before returning
- createDependentSource: check dependency current value on creation
- changes stream: prepend current value with Stream.concat
- Fixes issue where SubscriptionRef.changes only emits future changes
…caching

- http-cache.ts: Cache API wrapper with smart update strategy
- poll-meta.ts: IndexedDB persistence for poll timing
- source-registry.ts: Global singleton + ref counting for sources
- biowallet-provider: Refactored to use shared txHistory source

This ensures that subscribing to balance/tokenBalances shares the same
txHistory source instead of creating duplicate polling instances.
…tion

- Add httpFetchCached() with TTL-based caching using Cache API
- Simplify source-registry.ts (remove cacheUrl/cacheBody, cache handled by fetch)
- Update biowallet provider to use httpFetchCached with forgeInterval as TTL
…efactor

- Add cacheStrategy option: 'ttl' | 'cache-first' | 'network-first'
- Add Promise lock to prevent concurrent duplicate requests
- Biowallet: blockHeight -> txHistory -> balance/tokenBalances dependency chain
- blockHeight uses TTL = forgeInterval/2
- txHistory/balance use cache-first (triggered by dependency change)
- source-registry.ts: Log poll and immediate fetch errors
- source.ts: Log dependent source initial fetch errors
- http.ts: Log fetch errors in all cache strategies
- biowallet: Fix fetch signature for createDependentSource
@Gaubee Gaubee added type/service Service / logic work area/core Core / service area labels Jan 23, 2026
@Gaubee Gaubee marked this pull request as ready for review January 23, 2026 19:28
@Gaubee Gaubee merged commit 9eaabae into main Jan 23, 2026
5 checks passed
@Gaubee Gaubee deleted the feat/issue-272 branch January 23, 2026 19:28
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/core Core / service area type/service Service / logic work

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Fix transfer broken: fee/error/broadcast

2 participants