Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add UI for License Mint #38

Merged
merged 4 commits into from
May 22, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 11 additions & 20 deletions rair-front/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,9 @@ import {

//import CSVParser from './components/metadata/csvParser';
import AboutPageNew from './components/AboutPage/AboutPageNew/AboutPageNew';
import ImportAndTransfer from './components/adminViews/ImportAndTransfer';
import ImportExternalContracts from './components/adminViews/ImportExternalContracts';
import TransferTokens from './components/adminViews/transferTokens';
import LicenseExchange from './components/adminViews/LicenseExchange';
import useServerSettings from './components/adminViews/useServerSettings';
import AlertMetamask from './components/AlertMetamask/index';
import ConsumerMode from './components/consumerMode';
Expand All @@ -32,7 +33,6 @@ import ListCollections from './components/creatorStudio/ListCollections';
import WorkflowSteps from './components/creatorStudio/workflowSteps';
import DemoMediaUpload from './components/DemoMediaUpload/DemoMediaUpload';
import Footer from './components/Footer/Footer';
import ImportAndTransfer from './components/adminViews/ImportAndTransfer';
import WelcomeHeader from './components/FrontPage/WelcomeHeader';
import MainHeader from './components/Header/MainHeader';
import IframePage from './components/iframePage/IframePage';
Expand Down Expand Up @@ -81,7 +81,6 @@ import { ColorStoreType } from './ducks/colors/colorStore.types';
import { setChainId } from './ducks/contracts/actions';
import { ContractsInitialType } from './ducks/contracts/contracts.types';
import { getCurrentPageEnd } from './ducks/pages/actions';
import { setAdminRights } from './ducks/users/actions';
import { TUsersInitialState } from './ducks/users/users.types';
import useConnectUser from './hooks/useConnectUser';
import useWeb3Tx from './hooks/useWeb3Tx';
Expand Down Expand Up @@ -198,16 +197,6 @@ function App() {
});
}, []);

useEffect(() => {
// setTitle('Welcome');
if (import.meta.env.NODE_ENV === 'development') {
window.gotoRouteBackdoor = navigate;
window.adminAccessBackdoor = (boolean) => {
dispatch(setAdminRights(boolean));
};
}
}, [dispatch, navigate]);

useEffect(() => {
btnCheck();
}, [btnCheck]);
Expand Down Expand Up @@ -555,16 +544,18 @@ function App() {
content: VideoManager
},

// Old Video Upload view
// Server Settings view
{
path: '/admin/fileUpload',
path: '/admin/settings',
content: FileUpload,
requirement:
loggedIn && !creatorViewsDisabled && adminRights,
props: {
primaryColor: primaryColor,
textColor: textColor
}
loggedIn && !creatorViewsDisabled && adminRights
},
// License UI
{
path: '/license',
content: LicenseExchange,
requirement: loggedIn && !creatorViewsDisabled
},
// Token transfers
{
Expand Down
76 changes: 54 additions & 22 deletions rair-front/src/components/Header/AdminPanel/AdminPanel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -33,48 +33,80 @@ const AdminPanel = ({ creatorViewsDisabled, adminPanel, setAdminPanel }) => {
backgroundColor: primaryColor
}}
className="container-admin-panel">
{
adminPanel &&
{adminPanel &&
adminRights === true &&
!creatorViewsDisabled &&
[
{
name: <TooltipBox position={'top'} title="Server Settings"> <div>
<i className="fa fa-cog" aria-hidden="true" /></div></TooltipBox>,
route: '/admin/fileUpload',
name: (
<TooltipBox position={'top'} title="Server Settings">
{' '}
<div>
<i className="fa fa-cog" aria-hidden="true" />
</div>
</TooltipBox>
),
route: '/admin/settings',
disabled: !loggedIn
},
// {
// name: <TooltipBox position={'top'} title="Imprort / Export"><div><i className="fas fa-exchange"></i></div></TooltipBox>,
// route: '/importExternalContracts',
// disabled: !loggedIn
// },
{
name: <TooltipBox position={'top'} title="Import / Export / Transfer"><div><i className="fas fa-city" /></div></TooltipBox>,
name: (
<TooltipBox position={'top'} title="License">
{' '}
<div>
<i className="fa fa-id-card" aria-hidden="true" />
</div>
</TooltipBox>
),
route: '/license',
disabled: !loggedIn
},
{
name: (
<TooltipBox
position={'top'}
title="Import / Export / Transfer">
<div>
<i className="fas fa-city" />
</div>
</TooltipBox>
),
route: '/admin/transferNFTs',
disabled: !loggedIn
},
{
name: <TooltipBox position={'top'} title="Streaming">
<div style={{width: "70px"}}><i className="fas fa-film" /></div>
</TooltipBox>,
name: (
<TooltipBox position={'top'} title="Streaming">
<div style={{ width: '70px' }}>
<i className="fas fa-film" />
</div>
</TooltipBox>
),
route: '/user/videos',
disabled: !loggedIn
},
{
name: <TooltipBox position={'top'} title="Old Market (diamond)">
<div style={{width: "70px"}}><i className="fas fa-gem" /></div>
</TooltipBox>,
name: (
<TooltipBox position={'top'} title="Old Market (diamond)">
<div style={{ width: '70px' }}>
<i className="fas fa-gem" />
</div>
</TooltipBox>
),
route: '/diamondMinter',
disabled: diamondMarketplaceInstance === undefined
},
{
name: <TooltipBox position={'top'} title="Old Market (classic)">
<div style={{width: "70px"}}><i className="fa fa-shopping-cart" aria-hidden="true" /></div>
</TooltipBox>,
name: (
<TooltipBox position={'top'} title="Old Market (classic)">
<div style={{ width: '70px' }}>
<i className="fa fa-shopping-cart" aria-hidden="true" />
</div>
</TooltipBox>
),
route: '/on-sale',
disabled: !loggedIn
},
}
].map((item, index) => {
if (!item.disabled) {
return (
Expand Down Expand Up @@ -106,4 +138,4 @@ const AdminPanel = ({ creatorViewsDisabled, adminPanel, setAdminPanel }) => {
);
};

export default AdminPanel;
export default AdminPanel;
199 changes: 199 additions & 0 deletions rair-front/src/components/adminViews/LicenseExchange.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,199 @@
import { useCallback, useState } from 'react';
import { useSelector } from 'react-redux';
import { formatEther, parseUnits } from 'ethers/lib/utils';

import { RootState } from '../../ducks';
import { ColorStoreType } from '../../ducks/colors/colorStore.types';
import { ContractsInitialType } from '../../ducks/contracts/contracts.types';
import { TUsersInitialState } from '../../ducks/users/users.types';
import useSwal from '../../hooks/useSwal';
import useWeb3Tx from '../../hooks/useWeb3Tx';
import InputField from '../common/InputField';

const LicenseExchange = () => {
const [tokenIndex, setTokenIndex] = useState(0);
const [tokenPrice, setTokenPrice] = useState(0);
const [userAddress, setUserAddress] = useState('');
const [signedHash, setSignedhash] = useState('');

const { licenseExchangeInstance, erc777Instance, currentUserAddress } =
useSelector<RootState, ContractsInitialType>(
(store) => store.contractStore
);

const { adminRights } = useSelector<RootState, TUsersInitialState>(
(store) => store.userStore
);

const { primaryButtonColor, secondaryButtonColor, textColor } = useSelector<
RootState,
ColorStoreType
>((store) => store.colorStore);

const { web3TxHandler, web3TxSignMessage } = useWeb3Tx();
const rSwal = useSwal();

const generateLicenseHash = useCallback(async () => {
if (!licenseExchangeInstance) {
return;
}
const result = await web3TxHandler(
licenseExchangeInstance,
'generateLicenseHash',
[tokenIndex, userAddress, parseUnits(tokenPrice.toString(), 18)]
);
const result2 = await web3TxSignMessage(result);
if (result2) {
setSignedhash(result2);
navigator.clipboard.writeText(result2);
rSwal.fire(
'Hash ready',
`'${result2}' has been copied to the clipboard`,
'success'
);
}
}, [
licenseExchangeInstance,
web3TxHandler,
tokenIndex,
userAddress,
tokenPrice,
web3TxSignMessage,
rSwal
]);

const purchaseLicense = useCallback(async () => {
if (!licenseExchangeInstance || !erc777Instance) {
return;
}
const tokenPriceBigNumber = parseUnits(tokenPrice.toString(), 18);
rSwal.fire({
title: 'Checking allowance',
html: `Please wait`,
showConfirmButton: false
});
const allowance = await web3TxHandler(erc777Instance, 'allowance', [
currentUserAddress,
licenseExchangeInstance.address
]);
if (allowance.lt(tokenPriceBigNumber)) {
rSwal.fire({
title: 'Awaiting approval',
html: `Approve the exchange contract to take ${formatEther(
tokenPriceBigNumber
)}`,
showConfirmButton: false
});
await web3TxHandler(erc777Instance, 'approve', [
licenseExchangeInstance.address,
tokenPriceBigNumber
]);
}
rSwal.fire({
title: 'Minting License NFT',
html: `Minting License #${tokenIndex} for ${formatEther(
tokenPriceBigNumber
)} tokens`,
showConfirmButton: false
});
if (
await web3TxHandler(licenseExchangeInstance, 'mint', [
tokenIndex,
tokenPriceBigNumber,
signedHash
])
) {
rSwal.fire('Success', `You now own License #${tokenIndex}`, 'success');
}
}, [
licenseExchangeInstance,
web3TxHandler,
tokenIndex,
tokenPrice,
signedHash,
rSwal,
erc777Instance,
currentUserAddress
]);

const connectERC20 = useCallback(async () => {
if (!licenseExchangeInstance || !erc777Instance) {
return;
}
await web3TxHandler(licenseExchangeInstance, 'setPurchasePeriod', [180]);
await web3TxHandler(licenseExchangeInstance, 'updateERC20Address', [
erc777Instance.address
]);
}, [licenseExchangeInstance, web3TxHandler, erc777Instance]);

if (!licenseExchangeInstance) {
return <>No exchange available</>;
}

return (
<div className="row w-100 px-5">
<h3>Licenses</h3>
<div className="col-12 col-md-6">
<InputField
customClass="rounded-rair form-control"
label={'License Number'}
getter={tokenIndex}
setter={setTokenIndex}
/>
</div>
<div className="col-12 col-md-6">
<InputField
customClass="rounded-rair form-control"
label={'Token Price'}
getter={tokenPrice}
setter={setTokenPrice}
/>
</div>
{adminRights && (
<div className="col-12 col-md-6">
<InputField
customClass="rounded-rair form-control"
label={'User address'}
getter={userAddress}
setter={setUserAddress}
/>
</div>
)}
<div className="col-12">
<InputField
customClass="rounded-rair form-control"
label={'Signed Hash'}
getter={signedHash}
setter={setSignedhash}
/>
</div>
<hr className="my-2" />
{adminRights && (
<button
className="btn col-12 col-md-3 rair-button"
disabled={userAddress === ''}
style={{ background: secondaryButtonColor, color: textColor }}
onClick={generateLicenseHash}>
Sign Hash (as admin)
</button>
)}
{adminRights && (
<button
className="btn col-12 col-md-3 rair-button"
style={{ background: secondaryButtonColor, color: textColor }}
onClick={connectERC20}>
Connect ERC20 to Exchange (as admin)
</button>
)}
<div className="col-12 col-md" />
<button
className="btn col-12 h1 col-md-3 rair-button"
style={{ background: primaryButtonColor, color: textColor }}
onClick={purchaseLicense}>
Purchase License (as user)
</button>
</div>
);
};

export default LicenseExchange;
Loading