-
-
Notifications
You must be signed in to change notification settings - Fork 1.1k
/
getBalance.ts
149 lines (140 loc) · 4.08 KB
/
getBalance.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
import { type Address, type Hex, formatUnits, hexToString, trim } from 'viem'
import {
type GetBalanceErrorType as viem_GetBalanceErrorType,
type GetBalanceParameters as viem_GetBalanceParameters,
getBalance as viem_getBalance,
} from 'viem/actions'
import type { Config } from '../createConfig.js'
import type { ChainIdParameter } from '../types/properties.js'
import type { Unit } from '../types/unit.js'
import type { Compute } from '../types/utils.js'
import { getAction } from '../utils/getAction.js'
import { getUnit } from '../utils/getUnit.js'
import { type ReadContractsErrorType, readContracts } from './readContracts.js'
export type GetBalanceParameters<config extends Config = Config> = Compute<
ChainIdParameter<config> &
viem_GetBalanceParameters & {
/** @deprecated */
token?: Address | undefined
/** @deprecated */
unit?: Unit | undefined
}
>
export type GetBalanceReturnType = {
decimals: number
/** @deprecated */
formatted: string
symbol: string
value: bigint
}
export type GetBalanceErrorType = viem_GetBalanceErrorType
/** https://wagmi.sh/core/api/actions/getBalance */
export async function getBalance<config extends Config>(
config: config,
parameters: GetBalanceParameters<config>,
): Promise<GetBalanceReturnType> {
const {
address,
blockNumber,
blockTag,
chainId,
token: tokenAddress,
unit = 'ether',
} = parameters
if (tokenAddress) {
try {
return await getTokenBalance(config, {
balanceAddress: address,
chainId,
symbolType: 'string',
tokenAddress,
})
} catch (error) {
// In the chance that there is an error upon decoding the contract result,
// it could be likely that the contract data is represented as bytes32 instead
// of a string.
if (
(error as ReadContractsErrorType).name ===
'ContractFunctionExecutionError'
) {
const balance = await getTokenBalance(config, {
balanceAddress: address,
chainId,
symbolType: 'bytes32',
tokenAddress,
})
const symbol = hexToString(
trim(balance.symbol as Hex, { dir: 'right' }),
)
return { ...balance, symbol }
}
throw error
}
}
const client = config.getClient({ chainId })
const action = getAction(client, viem_getBalance, 'getBalance')
const value = await action(
blockNumber ? { address, blockNumber } : { address, blockTag },
)
const chain = config.chains.find((x) => x.id === chainId) ?? client.chain!
return {
decimals: chain.nativeCurrency.decimals,
formatted: formatUnits(value, getUnit(unit)),
symbol: chain.nativeCurrency.symbol,
value,
}
}
type GetTokenBalanceParameters = {
balanceAddress: Address
chainId?: number | undefined
symbolType: 'bytes32' | 'string'
tokenAddress: Address
unit?: Unit | undefined
}
async function getTokenBalance(
config: Config,
parameters: GetTokenBalanceParameters,
) {
const { balanceAddress, chainId, symbolType, tokenAddress, unit } = parameters
const contract = {
abi: [
{
type: 'function',
name: 'balanceOf',
stateMutability: 'view',
inputs: [{ type: 'address' }],
outputs: [{ type: 'uint256' }],
},
{
type: 'function',
name: 'decimals',
stateMutability: 'view',
inputs: [],
outputs: [{ type: 'uint8' }],
},
{
type: 'function',
name: 'symbol',
stateMutability: 'view',
inputs: [],
outputs: [{ type: symbolType }],
},
],
address: tokenAddress,
} as const
const [value, decimals, symbol] = await readContracts(config, {
allowFailure: false,
contracts: [
{
...contract,
functionName: 'balanceOf',
args: [balanceAddress],
chainId,
},
{ ...contract, functionName: 'decimals', chainId },
{ ...contract, functionName: 'symbol', chainId },
] as const,
})
const formatted = formatUnits(value ?? '0', getUnit(unit ?? decimals))
return { decimals, formatted, symbol, value }
}