Skip to content

Commit

Permalink
SSO modal
Browse files Browse the repository at this point in the history
  • Loading branch information
Lu Nguyen committed Jul 24, 2023
1 parent a24923d commit 9043fed
Show file tree
Hide file tree
Showing 18 changed files with 886 additions and 53 deletions.
22 changes: 19 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,18 +5,29 @@
"author": "AesirX",
"repository": "https://github.com/aesirxio/sso",
"main": "build/lib/index.js",
"types": "build/lib/types/index.d.ts",
"module": "build/lib/index.js",
"exports": {
"require": "./build/lib/index.js",
"import": "./build/lib/index.js"
},
"types": "build/lib/types/index.d.ts",
"source": "src/index.js",
"dependencies": {
"@concordium/react-components": "^0.3.0",
"@wagmi/core": "^1.3.8",
"@web3modal/ethereum": "^2.7.0",
"@web3modal/react": "^2.7.0",
"axios": "^1.4.0",
"bootstrap": "^5.3.0",
"cross-env": "^7.0.3",
"dotenv": "^16.0.3",
"ethers": "^6.6.5",
"react": "^18.2.0",
"react-spinners": "^0.13.6"
"react-secure-storage": "^1.2.2",
"react-spinners": "^0.13.6",
"react-toastify": "^9.1.3",
"viem": "^1.0.0",
"wagmi": "^1.3.2"
},
"tsup": {
"entry": [
Expand All @@ -27,6 +38,7 @@
"clean": true
},
"scripts": {
"dev": "NODE_ENV=development tsup --watch --onSuccess 'yalc push --no-scripts'",
"build": "tsup",
"lint": "eslint --fix \"src/**/\"",
"lint:check": "eslint \"src/**/\"",
Expand Down Expand Up @@ -60,11 +72,15 @@
"@babel/plugin-transform-runtime": "^7.21.4",
"@babel/preset-env": "^7.21.5",
"@babel/preset-react": "^7.18.6",
"@types/bootstrap": "^5.2.6",
"@types/node": "^20.1.4",
"@types/react": "^18.2.6",
"@typescript-eslint/eslint-plugin": "^5.59.7",
"@typescript-eslint/parser": "^5.59.7",
"@walletconnect/types": "^2.9.1",
"babel-plugin-module-resolver": "^5.0.0",
"esbuild-plugin-inline-image": "^0.0.9",
"esbuild-sass-plugin": "^2.10.0",
"eslint": "^8.35",
"eslint-plugin-react": "^7.31.10",
"prettier": "^2.8.7",
Expand All @@ -75,4 +91,4 @@
"build",
"src"
]
}
}
68 changes: 68 additions & 0 deletions src/Hooks/useWallet.ts
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;
Binary file added src/SSOButton/Providers/Concordium/concordium.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
23 changes: 23 additions & 0 deletions src/SSOButton/Providers/Concordium/config.tsx
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)
);
57 changes: 57 additions & 0 deletions src/SSOButton/Providers/Concordium/connect.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import { BROWSER_WALLET, WALLET_CONNECT } from './config';
import React from 'react';
import logo from './concordium.png';

const ConnectConcordium = ({
isConnecting,
handleOnConnect,
activeConnectorError,
activeConnectorType,
activeConnector,
}: any) => {
return (
<>
<div className="p-2 bg-white border fw-semibold text-center rounded-2">
<div className="pb-2">Connect to Concordium</div>
<div className="d-flex">
<button
className="btn btn-secondary bg-secondary text-white me-1"
onClick={() => handleOnConnect(BROWSER_WALLET, 'browser')}
>
{isConnecting ? (
<>
<span
className="spinner-border spinner-border-sm me-1"
role="status"
aria-hidden="true"
></span>{' '}
Connecting
</>
) : (
<>
<img className="me-2" width={20} height={21} src={logo} alt="logo-concordium" />
Browser Wallet
</>
)}
</button>
<button
className="btn btn-secondary bg-secondary text-white 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>
</div>
</div>
</>
);
};

export default ConnectConcordium;
129 changes: 129 additions & 0 deletions src/SSOButton/Providers/Concordium/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
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 (
<>
{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} />
) : (
<div className="p-2 bg-white border fw-semibold text-center rounded-2">
<div className="pb-2">Connect to Concordium</div>
<div className="d-flex">
<button className="btn btn-secondary bg-secondary fw-semibold text-white w-50 py-3">
<span
className="spinner-border spinner-border-sm me-1"
role="status"
aria-hidden="true"
></span>
</button>
</div>
</div>
)}
</>
)}

{rpcError && <div className="mt-1">RPC error: {rpcError}</div>}
</>
);
};

export default SSOConcordiumProvider;
Loading

0 comments on commit 9043fed

Please sign in to comment.