-
Notifications
You must be signed in to change notification settings - Fork 22
/
useDaoWithWalletSecretNetworkPermit.ts
137 lines (121 loc) · 4.01 KB
/
useDaoWithWalletSecretNetworkPermit.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
import { useCallback, useEffect, useMemo, useState } from 'react'
import { useUpdatingRef } from '@dao-dao/stateless'
import { DaoSource, IDaoBase, PermitForPermitData } from '@dao-dao/types'
import { isSecretNetwork } from '@dao-dao/utils'
import { SecretCwDao } from '../clients/dao'
import { useDaoClient } from './useDaoClient'
import { useOnSecretNetworkPermitUpdate } from './useOnSecretNetworkPermitUpdate'
import { UseWalletOptions, UseWalletReturn, useWallet } from './useWallet'
export type UseWalletWithSecretNetworkPermitOptions = Omit<
UseWalletOptions,
'chainId'
> & {
/**
* DAO to fetch the permit for, or the current DAO context.
*/
dao?: DaoSource
}
export type UseWalletWithSecretNetworkPermitReturn = UseWalletReturn & {
/**
* Whether or not the current chain is Secret Network.
*/
isSecretNetwork: boolean
/**
* Whether or not a permit is needed. This is true when the wallet is
* connected, the DAO is on Secret Network, and no permit has been found for
* the current DAO in the browser.
*/
isSecretNetworkPermitNeeded: boolean
/**
* DAO client.
*/
dao: IDaoBase
/**
* Permit saved for the given DAO, if exists.
*/
permit: PermitForPermitData | undefined
/**
* Function to create and return a permit for the given DAO.
*/
getPermit: () => Promise<PermitForPermitData>
}
/**
* Hook to help manage a wallet's Secret Network permits for a DAO.
*/
export const useDaoWithWalletSecretNetworkPermit = ({
dao,
...options
}: UseWalletWithSecretNetworkPermitOptions = {}): UseWalletWithSecretNetworkPermitReturn => {
const { dao: daoClient } = useDaoClient({
dao,
})
const wallet = useWallet({
chainId: daoClient.chainId,
...options,
})
// Stabilize reference so callback doesn't change. This only needs to update
// on wallet connection state change anyway.
const signAminoRef = useUpdatingRef(wallet.signAmino)
// Register for offline signer if Secret DAO.
useEffect(() => {
if (daoClient instanceof SecretCwDao && wallet.isWalletConnected) {
daoClient.registerSignAmino(signAminoRef.current)
}
}, [daoClient, signAminoRef, wallet.isWalletConnected])
// Attempt to initialize with existing permit.
const [permit, setPermit] = useState<PermitForPermitData | undefined>(() =>
daoClient instanceof SecretCwDao &&
wallet.isWalletConnected &&
wallet.address
? daoClient.getExistingPermit(wallet.address)
: undefined
)
// On wallet address change, re-fetch existing permit.
useEffect(() => {
if (
daoClient instanceof SecretCwDao &&
wallet.isWalletConnected &&
wallet.address
) {
setPermit(daoClient.getExistingPermit(wallet.address))
}
}, [daoClient, wallet.address, wallet.isWalletConnected])
// Attempt to fetch existing permit on change if not already set.
useOnSecretNetworkPermitUpdate({
dao,
callback:
daoClient instanceof SecretCwDao && wallet.isWalletConnected
? () => {
if (wallet.address) {
setPermit(daoClient.getExistingPermit(wallet.address))
}
}
: undefined,
// We already set state and re-render in the callback.
reRender: false,
})
const getPermit = useCallback(async (): Promise<PermitForPermitData> => {
if (!(daoClient instanceof SecretCwDao)) {
throw new Error('Not a Secret DAO.')
}
if (!wallet.address || !wallet.isWalletConnected) {
throw new Error('Log in to continue.')
}
const permit = await daoClient.getPermit(wallet.address)
setPermit(permit)
return permit
}, [daoClient, wallet.address, wallet.isWalletConnected])
const response = useMemo((): UseWalletWithSecretNetworkPermitReturn => {
const isSecret = isSecretNetwork(daoClient.chainId)
return {
...wallet,
isSecretNetwork: isSecret,
isSecretNetworkPermitNeeded:
wallet.isWalletConnected && isSecret && !permit,
dao: daoClient,
permit,
getPermit,
}
}, [wallet, daoClient, permit, getPermit])
return response
}