useMultisig.ts 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102
  1. import { Wallet } from '@coral-xyz/anchor'
  2. import { PythCluster } from '@pythnetwork/client/lib/cluster'
  3. import { Cluster, Connection, PublicKey } from '@solana/web3.js'
  4. import SquadsMesh from '@sqds/mesh'
  5. import { TransactionAccount } from '@sqds/mesh/lib/types'
  6. import { useContext, useEffect, useRef, useState } from 'react'
  7. import { getProposals } from 'xc-admin-common'
  8. import { ClusterContext } from '../contexts/ClusterContext'
  9. import { pythClusterApiUrls } from '../utils/pythClusterApiUrl'
  10. export function getMultisigCluster(cluster: PythCluster): Cluster | 'localnet' {
  11. switch (cluster) {
  12. case 'pythnet':
  13. return 'mainnet-beta'
  14. case 'pythtest':
  15. return 'devnet'
  16. default:
  17. return cluster
  18. }
  19. }
  20. export const UPGRADE_MUTLTISIG: Record<Cluster | 'localnet', PublicKey> = {
  21. 'mainnet-beta': new PublicKey('FVQyHcooAtThJ83XFrNnv74BcinbRH3bRmfFamAHBfuj'),
  22. testnet: new PublicKey('FVQyHcooAtThJ83XFrNnv74BcinbRH3bRmfFamAHBfuj'),
  23. devnet: new PublicKey('6baWtW1zTUVMSJHJQVxDUXWzqrQeYBr6mu31j3bTKwY3'),
  24. localnet: new PublicKey('FVQyHcooAtThJ83XFrNnv74BcinbRH3bRmfFamAHBfuj'),
  25. }
  26. interface MultisigHookData {
  27. isLoading: boolean
  28. error: any // TODO: fix any
  29. squads: SquadsMesh | undefined
  30. proposals: TransactionAccount[]
  31. }
  32. export const useMultisig = (wallet: Wallet): MultisigHookData => {
  33. const connectionRef = useRef<Connection>()
  34. const { cluster } = useContext(ClusterContext)
  35. const [isLoading, setIsLoading] = useState(true)
  36. const [error, setError] = useState(null)
  37. const [proposals, setProposals] = useState<TransactionAccount[]>([])
  38. const [squads, setSquads] = useState<SquadsMesh>()
  39. const [urlsIndex, setUrlsIndex] = useState(0)
  40. useEffect(() => {
  41. setIsLoading(true)
  42. setError(null)
  43. }, [urlsIndex, cluster])
  44. useEffect(() => {
  45. let cancelled = false
  46. const urls = pythClusterApiUrls(getMultisigCluster(cluster))
  47. const connection = new Connection(urls[urlsIndex].rpcUrl, {
  48. commitment: 'confirmed',
  49. wsEndpoint: urls[urlsIndex].wsUrl,
  50. })
  51. connectionRef.current = connection
  52. ;(async () => {
  53. if (wallet) {
  54. try {
  55. const squads = new SquadsMesh({
  56. connection,
  57. wallet,
  58. })
  59. setProposals(
  60. await getProposals(
  61. squads,
  62. UPGRADE_MUTLTISIG[getMultisigCluster(cluster)]
  63. )
  64. )
  65. setSquads(squads)
  66. setIsLoading(false)
  67. } catch (e) {
  68. if (cancelled) return
  69. if (urlsIndex === urls.length - 1) {
  70. // @ts-ignore
  71. setError(e)
  72. setIsLoading(false)
  73. console.warn(`Failed to fetch accounts`)
  74. } else if (urlsIndex < urls.length - 1) {
  75. setUrlsIndex((urlsIndex) => urlsIndex + 1)
  76. console.warn(
  77. `Failed with ${urls[urlsIndex]}, trying with ${
  78. urls[urlsIndex + 1]
  79. }`
  80. )
  81. }
  82. }
  83. }
  84. })()
  85. return () => {}
  86. }, [urlsIndex, cluster, wallet])
  87. return {
  88. isLoading,
  89. error,
  90. squads,
  91. proposals,
  92. }
  93. }