-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathhelpers.ts
More file actions
144 lines (116 loc) · 4.36 KB
/
Copy pathhelpers.ts
File metadata and controls
144 lines (116 loc) · 4.36 KB
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
import 'isomorphic-fetch'
import TokenAmount from 'token-amount'
import { Contract, Provider } from 'ethers-multicall'
import { ethers } from 'ethers'
export function initEthersProvider() {
const provider = new ethers.providers.InfuraProvider('mainnet', process.env.INFURA_KEY)
return new Provider(provider, parseInt(process.env.CHAIN_ID))
}
export async function fetchTokenList() {
const tokenSource = 'https://defiprime.com/defiprime.tokenlist.json'
return fetch(tokenSource).then(data => data.json())
}
export async function fetchTokenBalances(provider, daoList, tokenList) {
const daos = await generateContractFunctionList(provider, daoList, tokenList)
const daoBalances = []
return Promise.all(
daos.map(async ({ daoName, daoAddress, balanceMultiCall }) => {
if (Array.isArray(balanceMultiCall)) {
const tokenHoldings = {}
const resp = await provider.all(balanceMultiCall)
resp.map((resp, index) => {
const { _hex } = resp
if (index == 0) {
tokenHoldings['ETH'] = convertToNumber(resp, 18)
} else if (_hex != '0x00') {
const { name, decimals, symbol } = tokenList[index]
tokenHoldings[symbol] = convertToNumber(resp, decimals)
}
})
daoBalances.push({
daoName,
daoAddress,
tokenHoldings
})
} else {
const tokenHoldings = {}
const [ethBalances, tokenBalances] = await Promise.all([
await provider.all(balanceMultiCall['ethBalanceByAddress']),
await Promise.all(
balanceMultiCall['balanceCallsByAddress'].map(async tokenCall => await provider.all(tokenCall))
)
])
ethBalances.map(ethBalance => {
tokenHoldings['ETH'] = tokenHoldings['ETH']
? tokenHoldings['ETH'] + convertToNumber(ethBalance, 18)
: convertToNumber(ethBalance, 18)
})
tokenBalances.map(addressBalances => {
Object.keys(addressBalances).map(key => {
const resp = addressBalances[key]
const { _hex } = resp
if (_hex != '0x00') {
const { name, decimals, symbol } = tokenList[key]
tokenHoldings[symbol] = tokenHoldings[symbol]
? tokenHoldings[symbol] + convertToNumber(resp, decimals) + convertToNumber(resp, decimals)
: convertToNumber(resp, decimals)
}
})
})
daoBalances.push({
daoName,
daoAddress,
tokenHoldings
})
}
})
).then(() => daoBalances)
}
const convertToNumber = (bigNum, decimals) => {
return new TokenAmount(bigNum, decimals).format({ commify: true })
}
const getETHBalanceCall = (provider, address) => provider.getEthBalance(address)
const getERC20BalanceCall = (provider, address, tokenAddress) => {
const abi = ['function balanceOf(address _owner) public view returns (uint256 balance)']
const tokenContract = new Contract(tokenAddress, abi)
return tokenContract.balanceOf(address)
}
const generateContractFunctionList = async (provider, daoList, tokenList) => {
const daoFunctionCallMap = []
daoList.map(({ daoName, daoAddress }) => {
const multicallRequests = []
// Ugly hack for a DAO with multiple addresses to track.
if (Array.isArray(daoAddress)) {
const ethBalanceByAddress = []
const balanceCallsByAddress = []
daoAddress.map(address => {
const tokenBalanceCalls = []
tokenList.map(async ({ address: tokenAddress }) =>
tokenBalanceCalls.push(getERC20BalanceCall(provider, address, tokenAddress))
)
ethBalanceByAddress.push(getETHBalanceCall(provider, address))
balanceCallsByAddress.push(tokenBalanceCalls)
})
daoFunctionCallMap.push({
daoName,
daoAddress,
balanceMultiCall: {
ethBalanceByAddress: ethBalanceByAddress,
balanceCallsByAddress: balanceCallsByAddress
}
})
} else {
// Handle ETH
const ethBalanceCall = getETHBalanceCall(provider, daoAddress)
tokenList.map(async ({ address: tokenAddress }) =>
multicallRequests.push(getERC20BalanceCall(provider, daoAddress, tokenAddress))
)
daoFunctionCallMap.push({
daoName,
daoAddress,
balanceMultiCall: multicallRequests
})
}
})
return daoFunctionCallMap
}