diff --git a/package.json b/package.json
index aa590430..89682040 100644
--- a/package.json
+++ b/package.json
@@ -25,7 +25,8 @@
"@polkadot/extension-inject": "latest",
"@polkadot/types": "latest",
"@polkadot/ui-keyring": "latest",
- "@polkadot/util": "latest",
+ "@polkadot/util": "^12.6.2",
+ "@polkadot/util-crypto": "^12.6.2",
"@types/humanize-duration": "^3.27.3",
"@vercel/analytics": "^1.2.2",
"clsx": "^1.1.1",
@@ -67,4 +68,4 @@
"typescript": "^4.7.4",
"webpack": "^5.81.0"
}
-}
\ No newline at end of file
+}
diff --git a/src/components/Elements/ListingCard/index.tsx b/src/components/Elements/ListingCard/index.tsx
index 029f5276..3f23f2ba 100644
--- a/src/components/Elements/ListingCard/index.tsx
+++ b/src/components/Elements/ListingCard/index.tsx
@@ -196,7 +196,10 @@ const ListingCardInner = ({
>
Price/timeslice:
- {`${formatBalance(listing.timeslicePrice.toString(), true)} ${symbol}`}
+ {`${formatBalance(
+ listing.timeslicePrice.toString(),
+ true
+ )} ${symbol}`}
Total:
- {`${formatBalance(listing.currentPrice.toString(), true)} ${symbol}`}
+ {`${formatBalance(
+ listing.currentPrice.toString(),
+ true
+ )} ${symbol}`}
diff --git a/src/components/Elements/RegionCard/index.tsx b/src/components/Elements/RegionCard/index.tsx
index 55381e5f..b34f69bc 100644
--- a/src/components/Elements/RegionCard/index.tsx
+++ b/src/components/Elements/RegionCard/index.tsx
@@ -26,7 +26,7 @@ import { useRelayApi } from '@/contexts/apis';
import { ApiState } from '@/contexts/apis/types';
import { useCommon } from '@/contexts/common';
import { useTasks } from '@/contexts/tasks';
-import { RegionLocation, RegionMetadata } from '@/models';
+import { POOLING_TASK_ID, RegionLocation, RegionMetadata } from '@/models';
import styles from './index.module.scss';
import { Label } from '..';
@@ -168,6 +168,7 @@ const RegionCardInner = ({
};
const getTask = (taskId: number | null): string => {
+ if (taskId === POOLING_TASK_ID) return 'Instantaneous Pool';
const getTaskName = (taskId: number) => {
return tasks.find(({ id }) => id === taskId)?.name || '';
};
diff --git a/src/components/Elements/Selectors/FinalitySelector/index.module.scss b/src/components/Elements/Selectors/FinalitySelector/index.module.scss
new file mode 100644
index 00000000..c994ef44
--- /dev/null
+++ b/src/components/Elements/Selectors/FinalitySelector/index.module.scss
@@ -0,0 +1,26 @@
+.options {
+ display: flex;
+ justify-content: center;
+}
+
+.option,
+.activeOption {
+ min-width: 15rem;
+ margin: 1rem 5rem;
+ border-radius: 0.5rem !important;
+ text-transform: capitalize;
+}
+
+.activeOption {
+ border: 1px solid #e84d68;
+ background: linear-gradient(180deg, #e84d68 0%, #ad2b49 100%);
+ -webkit-background-clip: text;
+ -webkit-text-fill-color: transparent;
+ background-clip: text;
+}
+
+.option {
+ border: 1px solid #cccccc !important;
+ background-color: white;
+ color: black;
+}
diff --git a/src/components/Elements/Selectors/FinalitySelector/index.tsx b/src/components/Elements/Selectors/FinalitySelector/index.tsx
new file mode 100644
index 00000000..2b974e8e
--- /dev/null
+++ b/src/components/Elements/Selectors/FinalitySelector/index.tsx
@@ -0,0 +1,27 @@
+import { MenuItem, Select } from '@mui/material';
+
+import { FinalityType } from '@/models';
+
+interface FinalitySelectorProps {
+ finality: FinalityType;
+ setFinality: (_: FinalityType) => void;
+}
+
+export const FinalitySelector = ({
+ finality,
+ setFinality,
+}: FinalitySelectorProps) => {
+ return (
+
+ );
+};
diff --git a/src/components/Elements/Selectors/index.ts b/src/components/Elements/Selectors/index.ts
index 3246a937..286b62e4 100644
--- a/src/components/Elements/Selectors/index.ts
+++ b/src/components/Elements/Selectors/index.ts
@@ -1,4 +1,5 @@
export * from './AssetSelector';
export * from './ChainSelector';
+export * from './FinalitySelector';
export * from './RecipientSelector';
export * from './RegionSelector';
diff --git a/src/components/Modals/Pooling/index.module.scss b/src/components/Modals/Pooling/index.module.scss
new file mode 100644
index 00000000..779e8db1
--- /dev/null
+++ b/src/components/Modals/Pooling/index.module.scss
@@ -0,0 +1,26 @@
+.container {
+ display: flex;
+ flex-direction: column;
+ gap: 0.75rem;
+ min-width: 35rem;
+}
+
+.content {
+ display: flex;
+ flex-direction: column;
+ gap: 0.75rem;
+ margin: 1rem 0;
+}
+
+.options {
+ display: flex;
+ flex-direction: column;
+ gap: 1rem;
+ padding: 1rem;
+}
+
+.optionItem {
+ display: flex;
+ flex-direction: column;
+ gap: 0.5rem;
+}
diff --git a/src/components/Modals/Pooling/index.tsx b/src/components/Modals/Pooling/index.tsx
new file mode 100644
index 00000000..4a48c077
--- /dev/null
+++ b/src/components/Modals/Pooling/index.tsx
@@ -0,0 +1,173 @@
+import {
+ Box,
+ Button,
+ Dialog,
+ DialogActions,
+ DialogContent,
+ Input,
+ InputAdornment,
+ Paper,
+ Typography,
+ useTheme,
+} from '@mui/material';
+import { useEffect, useState } from 'react';
+
+import { isValidAddress } from '@/utils/functions';
+
+import {
+ FinalitySelector,
+ ProgressButton,
+ SimpleRegionCard,
+} from '@/components/Elements';
+
+import { useAccounts } from '@/contexts/account';
+import { useCoretimeApi } from '@/contexts/apis';
+import { useRegions } from '@/contexts/regions';
+import { useToast } from '@/contexts/toast';
+import { FinalityType, RegionMetadata } from '@/models';
+
+import styles from './index.module.scss';
+
+interface PoolingModalProps {
+ open: boolean;
+ onClose: () => void;
+ regionMetadata: RegionMetadata;
+}
+
+export const PoolingModal = ({
+ open,
+ onClose,
+ regionMetadata,
+}: PoolingModalProps) => {
+ const theme = useTheme();
+ const {
+ state: { activeAccount, activeSigner },
+ } = useAccounts();
+
+ const {
+ state: { api: coretimeApi },
+ } = useCoretimeApi();
+ const { fetchRegions } = useRegions();
+ const { toastError, toastInfo, toastSuccess } = useToast();
+
+ const [finality, setFinality] = useState(FinalityType.FINAL);
+ const [payee, setPayee] = useState('');
+
+ const [working, setWorking] = useState(false);
+
+ const onPool = async () => {
+ if (!coretimeApi || !activeAccount || !activeSigner) return;
+
+ const txPooling = coretimeApi.tx.broker.pool(
+ regionMetadata.region.getOnChainRegionId(), // region id
+ activeAccount.address, // payee
+ finality
+ );
+
+ try {
+ setWorking(true);
+ await txPooling.signAndSend(
+ activeAccount.address,
+ { signer: activeSigner },
+ ({ status, events }) => {
+ if (status.isReady) toastInfo('Transaction was initiated');
+ else if (status.isInBlock) toastInfo(`In Block`);
+ else if (status.isFinalized) {
+ setWorking(false);
+ events.forEach(({ event: { method } }) => {
+ if (method === 'ExtrinsicSuccess') {
+ toastSuccess(
+ 'Successfully contributed to the instantaneous region pool'
+ );
+ onClose();
+ fetchRegions();
+ } else if (method === 'ExtrinsicFailed') {
+ toastError(
+ `Failed to contribute to the instantaneous region pool`
+ );
+ }
+ });
+ }
+ }
+ );
+ } catch (e) {
+ toastError(`Failed to contribute to the instantaneous region pool ${e}`);
+ setWorking(false);
+ }
+ };
+
+ useEffect(() => {
+ if (!open) return;
+ setFinality(FinalityType.FINAL);
+ setPayee('');
+ setWorking(false);
+ }, [open]);
+
+ return (
+
+ );
+};
diff --git a/src/components/Modals/TaskAssign/index.module.scss b/src/components/Modals/TaskAssign/index.module.scss
index cd583cf3..342d1d4f 100644
--- a/src/components/Modals/TaskAssign/index.module.scss
+++ b/src/components/Modals/TaskAssign/index.module.scss
@@ -18,3 +18,9 @@
padding: 1.25rem;
gap: 1rem;
}
+
+.alert {
+ max-width: 32rem;
+ align-items: center;
+ margin: 0 auto;
+}
diff --git a/src/components/Modals/TaskAssign/index.tsx b/src/components/Modals/TaskAssign/index.tsx
index ed9dfc44..47c6129d 100644
--- a/src/components/Modals/TaskAssign/index.tsx
+++ b/src/components/Modals/TaskAssign/index.tsx
@@ -165,14 +165,12 @@ export const TaskAssignModal = ({
+
+ Finally assigned regions can no longer be managed.
+ They will not be displayed on the Region Management page anymore.
+
-
- Finally assigned regions can no longer be managed. They will not be
- displayed on the Region Management page anymore.
-
+