-
Notifications
You must be signed in to change notification settings - Fork 149
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
refactor: api clients and add stx-20 balances #5315
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
import axios from 'axios'; | ||
|
||
import { type DefaultNetworkConfigurations, defaultNetworksKeyedById } from '@shared/constants'; | ||
|
||
export const leatherHeaders = { | ||
'x-leather-version': VERSION, | ||
'x-hiro-product': 'leather', | ||
}; | ||
|
||
export function hiroApiClient(network: DefaultNetworkConfigurations) { | ||
return axios.create({ | ||
baseURL: defaultNetworksKeyedById[network].chain.stacks.url, | ||
headers: { ...leatherHeaders }, | ||
}); | ||
Comment on lines
+10
to
+14
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. Mmm, actually (contrary to my earlier recommendation), this wouldn't work with custom networks, should just pass the URL 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. I see this now, thx. |
||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
import axios from 'axios'; | ||
|
||
export function stx20ApiClient() { | ||
return axios.create({ | ||
baseURL: 'https://api.stx20.com/api/v1', | ||
}); | ||
} | ||
Comment on lines
+3
to
+7
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. I think we want to call this once, and export, vs every time. E.g, if we want to modify all requests for stx20.com, we'd use 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. mm, but yeah we can't do this for custom networks 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. so now I'm questioning if it is a good idea to use all the separate axios clients / vs a single client where we don't set baseURL. Thoughts? 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. Thinking on the refactor here, I might close this and separate out the STX-20 balance work just to get that merged first. I'm not sure we absolutely need to refactor the api clients rn, but I'd like to think on how to set this all up a bit better. 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. You are right, this should only be called once with the config nec to handle that service. |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
import type { AddressBalanceResponse } from '@stacks/stacks-blockchain-api-types'; | ||
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. Can you check this lib is up to date? |
||
|
||
import type { DefaultNetworkConfigurations } from '@shared/constants'; | ||
|
||
// import type { AddressBalanceResponse } from '@shared/models/account.model'; | ||
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. I removed this and am using the one imported from the api-types bc the need for this might be outdated? I'm not seeing why we would need to keep this? |
||
import { hiroApiClient } from '../clients/hiro-api-client'; | ||
|
||
export function fetchAccountBalances(network: DefaultNetworkConfigurations, signal?: AbortSignal) { | ||
return async (principal: string): Promise<AddressBalanceResponse> => { | ||
const response = await hiroApiClient(network).get<AddressBalanceResponse>( | ||
`/extended/v1/address/${principal}/balances`, | ||
{ signal } | ||
); | ||
return response.data; | ||
}; | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
import { stx20ApiClient } from '../clients/stx20-api-client'; | ||
import type { Stx20Balance, Stx20BalanceResponse } from '../types/stx20-types'; | ||
|
||
export async function fetchStx20Balances(address: string): Promise<Stx20Balance[]> { | ||
const response = await stx20ApiClient().get<Stx20BalanceResponse>(`/balance/${address}`); | ||
return response.data.balances; | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
import type { Money } from '@shared/models/money.model'; | ||
|
||
/* API RESPONSE TYPES */ | ||
export interface Stx20Balance { | ||
ticker: string; | ||
balance: string; | ||
updateDate: string; | ||
} | ||
|
||
export interface Stx20BalanceResponse { | ||
address: string; | ||
balances: Stx20Balance[]; | ||
} | ||
|
||
/* LEATHER TYPES */ | ||
export interface Stx20Token extends Omit<Stx20Balance, 'balance'> { | ||
balance: Money; | ||
marketData: null; | ||
} | ||
Comment on lines
+16
to
+19
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. Per comment in other PR, do wonder if these should be paired ahead of time at model-level? |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
import { styled } from 'leather-styles/jsx'; | ||
|
||
import type { Stx20Token } from '@app/api/stacks/types/stx20-types'; | ||
import { formatBalance } from '@app/common/format-balance'; | ||
import { Avatar } from '@app/ui/components/avatar/avatar'; | ||
import { ItemLayout } from '@app/ui/components/item-layout/item-layout'; | ||
import { BasicTooltip } from '@app/ui/components/tooltip/basic-tooltip'; | ||
import { Pressable } from '@app/ui/pressable/pressable'; | ||
|
||
interface Stx20TokenAssetItemLayoutProps { | ||
token: Stx20Token; | ||
} | ||
export function Stx20TokenAssetItemLayout({ token }: Stx20TokenAssetItemLayoutProps) { | ||
const balanceAsString = token.balance.amount.toString(); | ||
const formattedBalance = formatBalance(balanceAsString); | ||
|
||
return ( | ||
<Pressable my="space.02"> | ||
<ItemLayout | ||
flagImg={ | ||
// TODO: Replace, need avatar for STX-20 | ||
<Avatar.Root> | ||
<Avatar.Image alt="STX20" src="" /> | ||
<Avatar.Fallback>STX20</Avatar.Fallback> | ||
</Avatar.Root> | ||
} | ||
titleLeft={token.ticker} | ||
captionLeft="STX-20" | ||
titleRight={ | ||
<BasicTooltip | ||
asChild | ||
label={formattedBalance.isAbbreviated ? balanceAsString : undefined} | ||
side="left" | ||
> | ||
<styled.span data-testid={token.ticker} fontWeight={500} textStyle="label.02"> | ||
{formattedBalance.value} | ||
</styled.span> | ||
</BasicTooltip> | ||
} | ||
/> | ||
</Pressable> | ||
); | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
import type { Stx20Token } from '@app/api/stacks/types/stx20-types'; | ||
|
||
import { Stx20TokenAssetItemLayout } from './stx20-token-asset-item.layout'; | ||
|
||
interface Stx20TokenAssetListProps { | ||
stx20Tokens: Stx20Token[]; | ||
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, for me it's clear enough from component name this is for stx20, so just "tokens" is good as a prop name? |
||
} | ||
export function Stx20TokenAssetList({ stx20Tokens }: Stx20TokenAssetListProps) { | ||
return stx20Tokens.map((token, i) => ( | ||
<Stx20TokenAssetItemLayout key={`${token.ticker}${i}`} token={token} /> | ||
)); | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
import type { Stx20Token } from '@app/api/stacks/types/stx20-types'; | ||
import { useStx20Tokens } from '@app/query/stacks/stx20/stx20-tokens.hooks'; | ||
|
||
interface Stx20TokensLoaderProps { | ||
address: string; | ||
children(runes: Stx20Token[]): React.ReactNode; | ||
} | ||
export function Stx20TokensLoader({ address, children }: Stx20TokensLoaderProps) { | ||
const { data: stx20Tokens = [] } = useStx20Tokens(address); | ||
return children(stx20Tokens); | ||
} |
This file was deleted.
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.
This will be removed if we refactor them all.