import { describe, expect, it } from 'vitest'
import {
  encodeErc20BalanceOfCall,
  filterTokensWithNonZeroBalance,
  formatNativeEthFromWei,
  parseHexBigInt,
} from './walletTokenBalances'

describe('walletTokenBalances', () => {
  it('encodes balanceOf calldata', () => {
    expect(
      encodeErc20BalanceOfCall('0x4A666F96fC8764181194447A7dFdb7d471b301C8'),
    ).toBe(
      '0x70a08231' +
        '0000000000000000000000004a666f96fc8764181194447a7dfdb7d471b301c8',
    )
  })

  it('parses hex bigint values', () => {
    expect(parseHexBigInt('0x0')).toBe(0n)
    expect(parseHexBigInt('0x1')).toBe(1n)
    expect(parseHexBigInt('0x')).toBe(0n)
  })

  it('filters tokens with non-zero balance and skips undeployed contracts', async () => {
    const tokens = [
      { address: '0x0000000000000000000000000000000000000001', symbol: 'A' },
      { address: '0x0000000000000000000000000000000000000002', symbol: 'B' },
      { address: '0x0000000000000000000000000000000000000003', symbol: 'C' },
    ]

    const provider = {
      request: async ({ method, params }: { method: string; params?: unknown }) => {
        if (method === 'eth_getCode') {
          const [addr] = params as [string]
          if (addr.endsWith('0003')) return '0x'
          return '0x6000'
        }
        if (method === 'eth_call') {
          const [call] = params as [{ to: string }]
          if (call.to.endsWith('0001')) return '0x0'
          if (call.to.endsWith('0002')) return '0x2a'
          return '0x0'
        }
        throw new Error(`unexpected ${method}`)
      },
    }

    const funded = await filterTokensWithNonZeroBalance(
      provider,
      '0x4A666F96fC8764181194447A7dFdb7d471b301C8',
      tokens,
    )

    expect(funded.map((token) => token.symbol)).toEqual(['B'])
  })

  it('formats native ETH from wei', () => {
    expect(formatNativeEthFromWei(10n ** 18n)).toBe('1 ETH')
    expect(formatNativeEthFromWei(1500000000000000000n)).toBe('1.5 ETH')
  })
})
