-
Notifications
You must be signed in to change notification settings - Fork 8
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #93 from aesirxio/modal
Modal
- Loading branch information
Showing
18 changed files
with
858 additions
and
56 deletions.
There are no files selected for viewing
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
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,68 @@ | ||
import { toast } from 'react-toastify'; | ||
import axios from 'axios'; | ||
import { getClientApp } from '../utils'; | ||
|
||
const useWallet = (wallet: any, publicAddress: string) => { | ||
const { endpoint } = getClientApp(); | ||
|
||
const getWalletNonce = async () => { | ||
try { | ||
const reqAuthFormData = { | ||
publicAddress: publicAddress, | ||
wallet: wallet, | ||
}; | ||
|
||
const config = { | ||
method: 'post', | ||
url: `${endpoint}/index.php?webserviceClient=site&webserviceVersion=1.0.0&option=member&task=getWalletNonce&api=hal`, | ||
headers: { | ||
'Content-Type': 'application/json', | ||
}, | ||
data: reqAuthFormData, | ||
}; | ||
const { data } = await axios(config); | ||
|
||
if (data.result) { | ||
return data.result; | ||
} | ||
throw false; | ||
} catch (error) { | ||
toast('Wrong authentication', { closeOnClick: false }); | ||
return false; | ||
} | ||
}; | ||
|
||
const verifySignature = async (wallet: any, publicAddress: string, signature: any) => { | ||
try { | ||
const reqAuthFormData = { | ||
wallet: wallet, | ||
publicAddress: publicAddress, | ||
signature: signature, | ||
}; | ||
|
||
const config = { | ||
method: 'post', | ||
url: `${endpoint}/index.php?webserviceClient=site&webserviceVersion=1.0.0&option=member&task=walletLogin&api=hal`, | ||
headers: { | ||
'Content-Type': 'application/json', | ||
}, | ||
data: reqAuthFormData, | ||
}; | ||
|
||
const { data } = await axios(config); | ||
if (data?.result) { | ||
return data?.result; | ||
} else { | ||
throw false; | ||
} | ||
} catch (error) { | ||
console.log(error); | ||
toast('Wrong authentication', { closeOnClick: false }); | ||
return false; | ||
} | ||
}; | ||
|
||
return { getWalletNonce, verifySignature }; | ||
}; | ||
|
||
export default useWallet; |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
import { | ||
BrowserWalletConnector, | ||
CONCORDIUM_WALLET_CONNECT_PROJECT_ID, | ||
WalletConnectConnector, | ||
ephemeralConnectorType, | ||
} from '@concordium/react-components'; | ||
|
||
import { SignClientTypes } from '@walletconnect/types'; | ||
|
||
const WALLET_CONNECT_OPTS: SignClientTypes.Options = { | ||
projectId: CONCORDIUM_WALLET_CONNECT_PROJECT_ID, | ||
metadata: { | ||
name: 'AesirX SSO', | ||
description: 'AesirX SSO is our Open Source Single Sign On service.', | ||
url: '#', | ||
icons: ['https://walletconnect.com/walletconnect-logo.png'], | ||
}, | ||
}; | ||
|
||
export const BROWSER_WALLET = ephemeralConnectorType(BrowserWalletConnector.create); | ||
export const WALLET_CONNECT = ephemeralConnectorType( | ||
WalletConnectConnector.create.bind(this, WALLET_CONNECT_OPTS) | ||
); |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
import { BROWSER_WALLET, WALLET_CONNECT } from './config'; | ||
import React from 'react'; | ||
|
||
const ConnectConcordium = ({ | ||
isConnecting, | ||
handleOnConnect, | ||
activeConnectorError, | ||
activeConnectorType, | ||
activeConnector, | ||
}: any) => { | ||
return ( | ||
<> | ||
<button | ||
className="btn btn-secondary" | ||
onClick={() => handleOnConnect(BROWSER_WALLET, 'browser')} | ||
> | ||
{isConnecting ? ( | ||
<> | ||
<span | ||
className="spinner-border spinner-border-sm me-1" | ||
role="status" | ||
aria-hidden="true" | ||
></span> | ||
Connecting | ||
</> | ||
) : ( | ||
<>Browser Wallet</> | ||
)} | ||
</button> | ||
<button | ||
className="btn btn-secondary ms-1" | ||
onClick={() => handleOnConnect(WALLET_CONNECT, 'walletconnect')} | ||
> | ||
{!activeConnectorError && activeConnectorType && !activeConnector ? ( | ||
<span | ||
className="spinner-border spinner-border-sm me-1" | ||
role="status" | ||
aria-hidden="true" | ||
></span> | ||
) : ( | ||
'QR Code' | ||
)} | ||
</button> | ||
</> | ||
); | ||
}; | ||
|
||
export default ConnectConcordium; |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,125 @@ | ||
import React, { useEffect, useState } from 'react'; | ||
|
||
import { toast } from 'react-toastify'; | ||
import { | ||
TESTNET, | ||
MAINNET, | ||
WithWalletConnector, | ||
useConnection, | ||
useConnect, | ||
WalletConnectionProps, | ||
withJsonRpcClient, | ||
ConnectorType, | ||
} from '@concordium/react-components'; | ||
import ConnectConcordium from './connect'; | ||
import SignMessageConcordium from './sign'; | ||
import secureLocalStorage from 'react-secure-storage'; | ||
|
||
const SSOConcordiumProvider = () => { | ||
return ( | ||
<WithWalletConnector network={process.env.NODE_ENV === 'development' ? TESTNET : MAINNET}> | ||
{(props) => <ConcordiumApp {...props} />} | ||
</WithWalletConnector> | ||
); | ||
}; | ||
|
||
const ConcordiumApp = (props: WalletConnectionProps) => { | ||
const { | ||
activeConnectorType, | ||
activeConnector, | ||
activeConnectorError, | ||
network, | ||
connectedAccounts, | ||
genesisHashes, | ||
setActiveConnectorType, | ||
} = props; | ||
|
||
const { connection, setConnection, account, genesisHash } = useConnection( | ||
connectedAccounts, | ||
genesisHashes | ||
); | ||
|
||
const { connect, connectError, isConnecting } = useConnect(activeConnector, setConnection); | ||
|
||
const [rpcGenesisHash, setRpcGenesisHash] = useState(); | ||
const [rpcError, setRpcError] = useState(''); | ||
|
||
useEffect(() => { | ||
if (connection) { | ||
setRpcGenesisHash(undefined); | ||
withJsonRpcClient(connection, async (rpc) => { | ||
const status = await rpc.getConsensusStatus(); | ||
return status.genesisBlock; | ||
}) | ||
.then((hash: any) => { | ||
console.log('NODE_ENV', process.env.NODE_ENV); | ||
|
||
if (process.env.NODE_ENV === 'development' && hash !== TESTNET.genesisHash) { | ||
throw new Error(`Please change the network to Testnet in Wallet`); | ||
} | ||
|
||
if (process.env.NODE_ENV === 'production' && hash !== MAINNET.genesisHash) { | ||
throw new Error(`Please change the network to Mainnet in Wallet`); | ||
} | ||
setRpcGenesisHash(hash); | ||
setRpcError(''); | ||
}) | ||
.catch((err) => { | ||
setRpcGenesisHash(undefined); | ||
toast(err.message); | ||
setRpcError(err.message); | ||
}); | ||
} | ||
}, [connection, genesisHash, network]); | ||
|
||
useEffect(() => { | ||
if (activeConnector) { | ||
connect(); | ||
} | ||
}, [activeConnector]); | ||
|
||
useEffect(() => { | ||
if (connectError) { | ||
toast(connectError); | ||
} | ||
}, [connectError]); | ||
|
||
const handleOnConnect = async (connectorType: ConnectorType, name: string) => { | ||
secureLocalStorage.setItem('concordium', name); | ||
await setActiveConnectorType(connectorType); | ||
}; | ||
return ( | ||
<> | ||
<div className="pb-2">Concordium wallets</div> | ||
{activeConnectorError && <div>Connector error: {activeConnectorError}.</div>} | ||
|
||
{!account || rpcError ? ( | ||
<ConnectConcordium | ||
isConnecting={isConnecting} | ||
handleOnConnect={handleOnConnect} | ||
activeConnectorError={activeConnectorError} | ||
activeConnectorType={activeConnectorType} | ||
activeConnector={activeConnector} | ||
/> | ||
) : ( | ||
<> | ||
{rpcGenesisHash ? ( | ||
<SignMessageConcordium account={account} connection={connection} /> | ||
) : ( | ||
<button className="btn btn-secondary"> | ||
<span | ||
className="spinner-border spinner-border-sm me-1" | ||
role="status" | ||
aria-hidden="true" | ||
></span> | ||
</button> | ||
)} | ||
</> | ||
)} | ||
|
||
{rpcError && <div className="mt-1">RPC error: {rpcError}</div>} | ||
</> | ||
); | ||
}; | ||
|
||
export default SSOConcordiumProvider; |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,65 @@ | ||
import React, { useContext, useState } from 'react'; | ||
import useWallet from '../../../Hooks/useWallet'; | ||
|
||
import { toast } from 'react-toastify'; | ||
import { shortenString } from '../../../utils'; | ||
import { stringMessage } from '@concordium/react-components'; | ||
import { SSOModalContext } from '../../modal'; | ||
|
||
const SignMessageConcordium = ({ account, connection }: any) => { | ||
const [status, setStatus] = useState(''); | ||
const wallet = 'concordium'; | ||
const { handleOnData } = useContext(SSOModalContext); | ||
|
||
const { getWalletNonce, verifySignature } = useWallet(wallet, account); | ||
|
||
const handleConnect = async () => { | ||
setStatus('connect'); | ||
const nonce = await getWalletNonce(); | ||
|
||
if (nonce) { | ||
try { | ||
setStatus('sign'); | ||
const signature = await connection.signMessage(account, stringMessage(`${nonce}`)); | ||
const convertedSignature = | ||
typeof signature === 'object' && signature !== null ? signature : JSON.parse(signature); | ||
|
||
if (signature) { | ||
const data = await verifySignature(wallet, account, convertedSignature); | ||
handleOnData(data); | ||
} | ||
} catch (error) { | ||
toast(error.message); | ||
} | ||
} | ||
setStatus(''); | ||
}; | ||
return ( | ||
<> | ||
<p className="text-break"> | ||
<span className="fw-semibold">Wallet:</span> | ||
<span className="ms-1">{account && shortenString(account)}</span> | ||
</p> | ||
<button className="btn btn-secondary" onClick={handleConnect}> | ||
{status ? ( | ||
<div className="d-flex align-items-center"> | ||
<span | ||
className="spinner-border spinner-border-sm me-1" | ||
role="status" | ||
aria-hidden="true" | ||
></span> | ||
<span className="ms-1"> | ||
{status === 'sign' | ||
? 'Please sign message on the wallet' | ||
: `Please wait to connect...`} | ||
</span> | ||
</div> | ||
) : ( | ||
<>Sign in via Concordium</> | ||
)} | ||
</button> | ||
</> | ||
); | ||
}; | ||
|
||
export default SignMessageConcordium; |
Oops, something went wrong.