-
Notifications
You must be signed in to change notification settings - Fork 24
/
Copy pathuseAwaitNextBlock.ts
48 lines (39 loc) · 1.43 KB
/
useAwaitNextBlock.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
import { useCallback } from 'react'
import { useRecoilValueLoadable, useSetRecoilState } from 'recoil'
import {
cosmWasmClientForChainSelector,
refreshBlockHeightAtom,
} from '@dao-dao/state'
import { useChain } from '@dao-dao/stateless'
// Returns a function that polls the chain's block height and resolves once it
// increments.
export const useAwaitNextBlock = () => {
const { chainId } = useChain()
const clientLoadable = useRecoilValueLoadable(
cosmWasmClientForChainSelector(chainId)
)
const client =
clientLoadable.state === 'hasValue' ? clientLoadable.contents : undefined
const setRefreshBlockHeight = useSetRecoilState(refreshBlockHeightAtom)
const doAfterNextBlock = useCallback(async () => {
if (!client) {
return
}
// Store what block height we want to wait for.
const nextBlockHeight = (await client.getHeight()) + 1
// Refresh block height every 1 second until height changes.
await new Promise<void>((resolve) => {
const interval = setInterval(async () => {
const currentBlockHeight = await client.getHeight()
// Once we reach the next block height, stop polling and resolve.
if (currentBlockHeight >= nextBlockHeight) {
clearInterval(interval)
resolve()
}
}, 1000)
})
// Refresh global block height.
setRefreshBlockHeight((id) => id + 1)
}, [client, setRefreshBlockHeight])
return doAfterNextBlock
}