-
-
Save tai-bcw/d9c8707f16865bb6331e90a8882469ff to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { atom } from "../atoms/atoms"; | |
import { | |
SENTRY_CATEGORY, | |
useSentry, | |
} from "../hooks/useSentry"; | |
import HashconnectAccount from "../types/hashconnect"; | |
import { | |
HashConnect, | |
HashConnectTypes, | |
MessageTypes, | |
} from "hashconnect"; | |
import React, | |
{ | |
createContext, | |
useEffect, | |
useState, | |
} from "react"; | |
import { | |
useRecoilState, | |
useResetRecoilState, | |
} from "recoil"; | |
type Networks = "testnet" | "mainnet" | "previewnet"; | |
interface Props { | |
children: React.ReactNode; | |
hashConnect: HashConnect; | |
network?: Networks; | |
debug?: boolean; | |
} | |
export interface HashConnectProviderAPI { | |
connect: () => void; | |
installedExtensions: HashConnectTypes.WalletMetadata | null; | |
isHashpackConnected: boolean; | |
setIsHashpackConnected: React.Dispatch<React.SetStateAction<boolean>>; | |
network: Networks; | |
resetPairing: () => void; | |
walletData: HashconnectAccount; | |
hashConnect: HashConnect; | |
} | |
const APP_CONFIG: HashConnectTypes.AppMetadata = { | |
name: 'hashport', | |
description: 'A public utility that facilitates the movement of digital assets between networks in a quick, secure, and cost-effective way', | |
icon: 'https://www.hashport.network/wp-content/uploads/2021/06/hashport-glyph-light.svg', | |
}; | |
export const HashConnectAPIContext = createContext<HashConnectProviderAPI>({} as HashConnectProviderAPI); | |
export default function HashConnectProvider ({ | |
children, | |
hashConnect, | |
network = 'testnet', | |
debug = false, | |
}: Props) { | |
const { logException } = useSentry(); | |
const [ hashconnectAccount, setHashconnectAccount ] = useRecoilState(atom.hashconnectAccount); | |
const resetHashconnectAccount = useResetRecoilState(atom.hashconnectAccount); | |
const [ isHashpackConnected, setIsHashpackConnected ] = useState(false); | |
const [ installedExtensions, setInstalledExtensions ] = useState<HashConnectTypes.WalletMetadata | null>(null); | |
const isNewConnection = () => { | |
const { | |
topic, | |
pairingString, | |
privateKey, | |
pairedAccounts, | |
pairedWalletData, | |
} = hashconnectAccount; | |
return (topic === '' || | |
pairingString === '' || | |
privateKey === '' || | |
pairedAccounts.length === 0 || | |
pairedWalletData === null | |
); | |
}; | |
const initializeHashConnect = async () => { | |
try { | |
if (isNewConnection()) { | |
const initData = await hashConnect.init(APP_CONFIG); | |
const privateKey = initData.privKey; | |
const state = await hashConnect.connect(); | |
const { topic } = state; | |
const pairingString = hashConnect.generatePairingString( | |
state, | |
network, | |
debug ?? false, | |
); | |
setHashconnectAccount((prevState) => ({ | |
...prevState, | |
...{ | |
privateKey, | |
topic, | |
pairingString, | |
network, | |
pairedWalletData: APP_CONFIG, | |
}, | |
})); | |
} else { | |
await hashConnect.init(APP_CONFIG, hashconnectAccount.privateKey); | |
await hashConnect.connect( | |
hashconnectAccount.topic, | |
hashconnectAccount.pairedWalletData ?? APP_CONFIG, | |
); | |
setIsHashpackConnected(true); | |
} | |
//Fires foundExtensionEvent: | |
hashConnect.findLocalWallets(); | |
} catch (e) { | |
logException(e, SENTRY_CATEGORY.WALLET_CONNECTION); | |
} | |
}; | |
const additionalAccountRequestEventHandler = (data: MessageTypes.AdditionalAccountRequest) => { | |
if (debug) console.log('=====additionalAccountRequestEvent======', data); | |
// TODO: Handle requesting additional accounts | |
}; | |
const acknowledgeMessageEventHandler = (data: MessageTypes.Acknowledge) => { | |
if (debug) console.log('====acknowledge::Wallet ack====', data); | |
}; | |
const foundExtensionEventHandler = (data: HashConnectTypes.WalletMetadata) => { | |
if (debug) console.log('====foundExtensionEvent====', data); | |
setInstalledExtensions(data); | |
}; | |
const pairingEventHandler = (data: MessageTypes.ApprovePairing) => { | |
const accountIds: string[] = []; | |
data.accountIds.forEach(id => { | |
if (hashconnectAccount.pairedAccounts.indexOf(id) === -1) { | |
accountIds.push(id); | |
} | |
}); | |
setHashconnectAccount((prevState) => ({ | |
...prevState, | |
topic: data.topic, | |
pairedWalletData: data.metadata, | |
pairedAccounts: accountIds, | |
})); | |
setIsHashpackConnected(true); | |
}; | |
useEffect(() => { | |
initializeHashConnect(); | |
hashConnect.additionalAccountRequestEvent.on(additionalAccountRequestEventHandler); | |
hashConnect.acknowledgeMessageEvent.on(acknowledgeMessageEventHandler); | |
hashConnect.additionalAccountRequestEvent.on(additionalAccountRequestEventHandler); | |
hashConnect.foundExtensionEvent.on(foundExtensionEventHandler); | |
hashConnect.pairingEvent.on(pairingEventHandler); | |
return () => { | |
hashConnect.additionalAccountRequestEvent.off(additionalAccountRequestEventHandler); | |
hashConnect.foundExtensionEvent.off(foundExtensionEventHandler); | |
hashConnect.pairingEvent.off(pairingEventHandler); | |
}; | |
}, []); | |
const resetPairing = () => { | |
if (debug) console.log('====Clearing pairings===='); | |
resetHashconnectAccount(); | |
setIsHashpackConnected(false); | |
}; | |
const connect = () => { | |
if (installedExtensions && !isHashpackConnected) { | |
if (debug) console.log('Pairing String::', hashconnectAccount.pairingString); | |
hashConnect.connectToLocalWallet(hashconnectAccount.pairingString); | |
} else { | |
if (debug && !installedExtensions) console.log('====No extension in browser===='); | |
} | |
}; | |
return ( | |
<HashConnectAPIContext.Provider | |
value={{ | |
connect, | |
walletData: hashconnectAccount, | |
network, | |
installedExtensions, | |
isHashpackConnected, | |
setIsHashpackConnected, | |
resetPairing, | |
hashConnect, | |
}}> | |
{children} | |
</HashConnectAPIContext.Provider> | |
); | |
} | |
export function useHashConnect () { | |
const value = React.useContext(HashConnectAPIContext); | |
return value; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment