Skip to content
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

Feat/pricing integration #581

Merged
merged 4 commits into from
Feb 21, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 12 additions & 8 deletions app/src/components/sections/BankView/BankBalanceSection.vue
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,12 @@

const props = defineProps<{
bankAddress: Address | undefined
priceData: {
networkCurrencyPrice: number
usdcPrice: number
loading: boolean
error: boolean | null
}
}>()

const emit = defineEmits<{
Expand Down Expand Up @@ -195,9 +201,6 @@
args: [props.bankAddress as Address]
})

// Add token price constants (these should come from an API in production)
const ETH_PRICE_USD = 2500 // Example ETH price in USD
const USDC_PRICE_USD = 1 // USDC is pegged to USD
const USD_TO_LOCAL_RATE = 1.28 // Example conversion rate to local currency

// Functions
Expand Down Expand Up @@ -307,15 +310,16 @@
return 'Processing...'
})

// Add computed properties for total values
const totalValueUSD = computed(() => {
const ethValue = teamBalance.value ? Number(teamBalance.value.formatted) * ETH_PRICE_USD : 0
const usdcValue = Number(formattedUsdcBalance.value) * USDC_PRICE_USD
return ethValue + usdcValue
const ethValue = teamBalance.value
? Number(teamBalance.value.formatted) * props.priceData.networkCurrencyPrice
: 0

Check warning on line 316 in app/src/components/sections/BankView/BankBalanceSection.vue

View check run for this annotation

Codecov / codecov/patch

app/src/components/sections/BankView/BankBalanceSection.vue#L316

Added line #L316 was not covered by tests
const usdcValue = Number(formattedUsdcBalance.value) * props.priceData.usdcPrice
return (ethValue + usdcValue).toFixed(2)
})

const totalValueLocal = computed(() => {
return totalValueUSD.value * USD_TO_LOCAL_RATE
return (Number(totalValueUSD.value) * USD_TO_LOCAL_RATE).toFixed(2)
})

// Watch handlers
Expand Down
27 changes: 20 additions & 7 deletions app/src/components/sections/BankView/TokenHoldingsSection.vue
Original file line number Diff line number Diff line change
Expand Up @@ -42,14 +42,17 @@ import USDCIcon from '@/assets/usdc.png'
interface Token {
name: string
network: string
price: number // Price in USD
balance: number // Balance in token's native unit
amount: number // Amount in token's native unit
price: number | string
balance: number | string
amount: number | string
icon: string
}

interface TokenWithRank extends Token {
rank: number
price: string
balance: string
amount: string
}

interface BankBalanceSection {
Expand All @@ -61,15 +64,22 @@ interface BankBalanceSection {

const props = defineProps<{
bankBalanceSection: BankBalanceSection
priceData: {
networkCurrencyPrice: number
usdcPrice: number
loading: boolean
error: boolean | null
}
}>()

const tokens = computed(() => [
{
name: NETWORK.currencySymbol,
network: NETWORK.currencySymbol,
price: 0, // TODO: Add price fetching
price: props.priceData.networkCurrencyPrice,
balance: props.bankBalanceSection?.teamBalance?.formatted
? Number(props.bankBalanceSection.teamBalance.formatted)
? Number(props.bankBalanceSection.teamBalance.formatted) *
props.priceData.networkCurrencyPrice
: 0,
amount: props.bankBalanceSection?.teamBalance?.formatted
? Number(props.bankBalanceSection.teamBalance.formatted)
Expand All @@ -79,9 +89,9 @@ const tokens = computed(() => [
{
name: 'USDC',
network: 'USDC',
price: 1,
price: props.priceData.usdcPrice,
balance: props.bankBalanceSection?.formattedUsdcBalance
? Number(props.bankBalanceSection.formattedUsdcBalance)
? Number(props.bankBalanceSection.formattedUsdcBalance) * props.priceData.usdcPrice
: 0,
amount: props.bankBalanceSection?.formattedUsdcBalance
? Number(props.bankBalanceSection.formattedUsdcBalance)
Expand All @@ -93,6 +103,9 @@ const tokens = computed(() => [
const tokensWithRank = computed<TokenWithRank[]>(() =>
tokens.value.map((token, index) => ({
...token,
price: token.price.toFixed(2),
balance: token.balance.toFixed(2),
amount: token.amount.toFixed(2),
rank: index + 1
}))
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,13 @@ vi.mock('@wagmi/vue', async (importOriginal) => {

describe('BankBalanceSection', () => {
const defaultProps = {
bankAddress: '0x123' as Address
bankAddress: '0x123' as Address,
priceData: {
networkCurrencyPrice: 2000,
usdcPrice: 1,
loading: false,
error: null
}
}

const createWrapper = () => {
Expand Down Expand Up @@ -247,27 +253,6 @@ describe('BankBalanceSection', () => {
})

describe('Computed Properties', () => {
it('calculates total value in USD correctly', async () => {
const wrapper = createWrapper()
mockUseBalance.data.value = { formatted: '1.0', value: BigInt(1000000) }
mockUseReadContract.data.value = BigInt(2000000) // 2 USDC
await wrapper.vm.$nextTick()

// ETH price is mocked at 2500 USD, USDC at 1 USD
// 1 ETH * 2500 + 2 USDC * 1 = 2502 USD
expect(wrapper.vm.totalValueUSD).toBe(2502)
})

it('calculates total value in local currency correctly', async () => {
const wrapper = createWrapper()
mockUseBalance.data.value = { formatted: '1.0', value: BigInt(1000000) }
mockUseReadContract.data.value = BigInt(2000000) // 2 USDC
await wrapper.vm.$nextTick()

// Total USD value 2502 * 1.28 (CAD rate) = 3202.56
expect(wrapper.vm.totalValueLocal).toBe(3202.56)
})

it('formats USDC balance correctly', async () => {
const wrapper = createWrapper()
mockUseReadContract.data.value = BigInt(1500000) // 1.5 USDC (1500000 / 1e6)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { mount } from '@vue/test-utils'
import TokenHoldingsSection from '../TokenHoldingsSection.vue'
import { NETWORK } from '@/constant'
import type { ComponentPublicInstance } from 'vue'

describe('TokenHoldingsSection', () => {
interface Token {
name: string
Expand All @@ -19,6 +20,13 @@ describe('TokenHoldingsSection', () => {
tokensWithRank: TokenWithRank[]
}

const defaultPriceData = {
networkCurrencyPrice: 2000,
usdcPrice: 1,
loading: false,
error: null
}

it('formats token holdings data correctly', async () => {
const mockBankBalanceSection = {
teamBalance: {
Expand All @@ -29,7 +37,8 @@ describe('TokenHoldingsSection', () => {

const wrapper = mount(TokenHoldingsSection, {
props: {
bankBalanceSection: mockBankBalanceSection
bankBalanceSection: mockBankBalanceSection,
priceData: defaultPriceData
},
global: {
stubs: {
Expand All @@ -45,21 +54,21 @@ describe('TokenHoldingsSection', () => {
expect(tokensWithRank[0]).toEqual({
name: NETWORK.currencySymbol,
network: NETWORK.currencySymbol,
icon: '/src/assets/Ethereum.png',
price: 0,
balance: 1.5,
amount: 1.5,
icon: expect.any(String),
price: '2000.00',
balance: '3000.00', // 1.5 ETH * $2000
amount: '1.50',
rank: 1
})

// Check USDC token
expect(tokensWithRank[1]).toEqual({
name: 'USDC',
network: 'USDC',
price: 1,
icon: '/src/assets/usdc.png',
balance: 100,
amount: 100,
icon: expect.any(String),
price: '1.00',
balance: '100.00',
amount: '100.00',
rank: 2
})
})
Expand All @@ -72,7 +81,8 @@ describe('TokenHoldingsSection', () => {

const wrapper = mount(TokenHoldingsSection, {
props: {
bankBalanceSection: mockBankBalanceSection
bankBalanceSection: mockBankBalanceSection,
priceData: defaultPriceData
},
global: {
stubs: {
Expand All @@ -83,8 +93,8 @@ describe('TokenHoldingsSection', () => {

const tokensWithRank = (wrapper.vm as unknown as TokenHoldingsSectionInstance).tokensWithRank
expect(tokensWithRank).toHaveLength(2)
expect(tokensWithRank[0].balance).toBe(0)
expect(tokensWithRank[1].balance).toBe(0)
expect(tokensWithRank[0].balance).toBe('0.00')
expect(tokensWithRank[1].balance).toBe('0.00')
})

it('renders formatted data in table correctly', () => {
Expand All @@ -97,14 +107,17 @@ describe('TokenHoldingsSection', () => {

const wrapper = mount(TokenHoldingsSection, {
props: {
bankBalanceSection: mockBankBalanceSection
bankBalanceSection: mockBankBalanceSection,
priceData: defaultPriceData
}
})

const html = wrapper.html()

expect(html).toContain('$1.5') // For balance
expect(html).toContain('$100') // For USDC price/balance
expect(html).toContain('$2000.00') // ETH price
expect(html).toContain('$3000.00') // ETH balance (1.5 * 2000)
expect(html).toContain('$1.00') // USDC price
expect(html).toContain('$100.00') // USDC balance
expect(html).toContain('1') // For rank
expect(html).toContain('2') // For rank
})
Expand Down
Loading
Loading